需求背景
Suppose that students would get y points in final exam, if they spent x hours in paper PyTorch Tutorial.
The question is what would be the grade if I study 4 hours?
有一组数据,关系如下表所示。记录了班级同学课程学习时间x和取得分数y的关系,(即:某学生学习了X小时即可取得Y分数),题设是:若某学生学习了4小时,可以取得分数为多少分?
【分析】这道题数据比较简单,我们通过人工推理即可完成。我们可以一眼看出,x和y有如下关系:y=2x。所以,当x=4时,y的值为8。
但是但是但是!实际中,可能数据不会这么显而易见的被观察出y和x的关系,那该如何求解呢?
X | Y | 备注 |
1.0 | 2.0 | 训练集 |
2.0 | 4.0 | 训练集 |
3.0 | 6.0 | 训练集 |
4.0 | ? | 测试集 |
分析思路
【思路1:如何建模?】
1.先假设y和x存在某种关系(可以是线性的,如:y=kx+b,也可以是非线性的,如:y=ax²+bx+c),再把已知的三组数据带入求得预测的y值(y_pred),计算真实值y和预测值(y_pred)误差,误差最小的,说明假设的正确性越高。
2.通常假设y和x存在某种关系时,一定先从简单地线性模型下手,若线性模型解决不了再使用非线性模型。(先易后难)
【概念梳理】
①真实值y:上述例子中,y=2是x=1时的真实值;y=4是x=2时的真实值;y=6是x=3时的真实值。
②预测值y_pred:我们会假设y和x存在某种关系,如y=wx。那把x=1,x=2,x=3带入公式后,会求得相应的y(x=1)的值,y(x=2)的值,y(x=3)的值,此时y的值即预测值,用y_pred表示。
【思路2:如何确定模型是否正确?】
1.根据三组数据得到的真实值曲线如图中红线所示。
2.我们假设y=wx(y和x存在线性关系),且先假设一个w的值,画出相应的图像(如蓝线所示),根据y_pred(x=i)和y(x=i)的差值来判断,我们假设的关系是否是正确的。定义loss=y_pred-y表示两点之间的距离。loss越小,说明预测值跟真实值越接近。(当loss0时,即y_pred-y=0时,预测值曲线和真实值曲线重合,可以理解为“完美预测”)
3.因为图像,y_pred可能在y的上方(y_pred>y),也可能在y的下方(y_pred<y)。所以我们用平方定义loss = (y_pred-y)²(用平方定义的好处是不需要去考虑正负号的问题)
4.我们在3的基础上,对loss进行进一步调整。因为对于每个w,我们把x=1,y=2;x=2,y=4;x=3、y=6这三组数据带入之后,会得到3个loss的值。我们对3个loss求均值作为cost损失。由此,每个w会对应唯一一个值,cost最终的形态为:
【概念梳理】
1.loss,称作损失,即为数学中的“误差”。loss越小,说明预测值和真实值越接近;loss越大,说明预测值偏离了真实值。
2.我们对loss取均值得到cost的方法,称之为MSE(均方误差/均方损失)。常用于衡量线性模型计算预测值和真实值之间的误差。
3.cost和loss区别:loss是单次损失;cost是对loss求均值之后得到的损失。
【思路3:如何预测w】
我们预测y和x之间存在线性关系,假设y=wx。确定了y和x采用的模型之后,需要对w的值进行预测,到底w取何值呢?该如何预测呢?
本实验中采用了最简单的预测方式:穷举。
把w在[1.0,4.0]之间的值依次取出进行预测,画出损失cost和w的图像,判断w取何值时,cost最小。
代码实践
1.准备数据集
根据题意,准备数据集
x_data = [1.0, 2.0, 3.0] y_data = [2.0, 4.0, 6.0]
2.定义模型
使用最最最简单的线性模型y=wx来定义
def forward(x): return x * w
3.定义损失函数
loss=(y_pred-y)²
def loss(x, y): y_pred = forward(x) return (y_pred - y) * (y_pred - y)
4.训练模型(附整套代码)
import numpy as np #numpy用于计算 import matplotlib.pyplot as plt # matplotlib是绘制图像的包 # 定义训练集 x_data = [1.0, 2.0, 3.0] y_data = [2.0, 4.0, 6.0] # 定义模型 def forward(x): return x * w # 定义损失函数,用MSE def loss(x, y): y_pred = forward(x) return (y_pred - y) * (y_pred - y) w_list = [] # 保存权重w mse_list = [] # 保存每个w的损失值loss for w in np.arange(0.0, 4.1, 0.1): # 从0.0~4.1,设置步长为0.1,枚举w的值。即0.0,0.1,0.2,0.3,0.4,0.5……4.0 # print('w=', w) l_sum = 0 # 计算每个w的loss损失总值(假设w=1,l_sum即为w=1时,x=1,x=2,x=3计算得到的损失总值) for x_val, y_val in zip(x_data, y_data): y_pred_val = forward(x_val) # 对每个x_val计算对应y预测值 loss_val = loss(x_val, y_val) l_sum += loss_val # print('\t', x_val, y_val, y_pred_val, loss_val) # print('MSE=', l_sum/3) w_list.append(w) mse_list.append(l_sum/3) # 三组[x,y]数据,需要除以3 # 绘制w和LOSS图像 plt.plot(w_list, mse_list) plt.ylabel('LOSS') plt.xlabel('w') plt.show()
5.展示绘制的图像(w-loss)
6.预测
通过1-5步骤,根据图像我们可知:当w=2.0时,cost损失取最小值。说明当w=2.0时,预测值和真实值最接近,误差最小。
因为我们定义的线性模型为y=wx,所以根据上述训练我们得到w=2,所以y和x的关系为:y=2x。
当x=4时,y=8,完成题目的预测。即:当某同学学习4小时,预测得到的分数为8分。