网上一个很精彩的PyTorch深度学习实践的课程,几个月前学完了,现在准备再学一遍,加深一下理解与印象,做一些笔记。文章如有错误,望批评指正。本课程只是笔记,如有侵权,请联系我删除。
文章目录
2 线性模型
2.1 机器学习一般步骤
深度学习和机器学习一般有四个步骤:
- 准备数据集
- 模型的选择
- 训练,当然有些算法不需要训练(如K近邻算法)
- 推理预测
2.2 问题引入——线性回归
某个学生的学习时间和学习成绩数据集如下,要预测当学生每天学习4小时后的成绩:
机器学习的作用就是,我们把数据交给算法进行训练,我们再获得新的输入后,能够得到相应的预测结果。输入和输出值都有,所以这是一个监督学习任务。
2.3 数据集的划分
2.3.1 数据集划分的原因
一般而言,当我们拿到数据集后,不是把数据集都当成训练数据,而是将数据集一部分划分成训练集,一部分划分成测试集。训练集训练数据,测试集测试数据。
在训练集中,我们能看到数据和对应标签(x,y);而测试集中,我们只有数据没有标签(x,?)。
如果一个任务,没有给我们测试集,我们不能直接进行测试。那么我们需要对训练集进行数据划分(训练和验证)。因为如果只用训练集来评判我们模型的优劣的话,往往是不全面的。因为训练集不能代表数据的整体分布,只能说是非常接近,而且这样可能会发生过拟合现象。
对于本节课的任务,数据划分非常简明,如下:
2.3.2 过拟合与泛化能力
我们如果要上线一个实际应用,我们必须要保证我们的数据集和真实的数据集的分布之间相差不大。如果我们专注于训练集上的表现,那么我们可能会遇到一个机器学习领域主要的难题——过拟合。
过拟合是指,我们的模型在训练集上,误差很小,但是在测试集上表现不好。因为,我们在训练集进行训练的时候,我们把数据的噪声也学进去了。所以,我们希望训练的模型有很好的泛化能力。泛化能力是指,模型训练好后,它对于没见过的数据集,它也能进行正确的推理和预测。
综上所述,我们把数据划分成训练集、开发集(验证集)和测试集。因为我们在面对一个算法竞赛时,一般没有测试集的标签,这时,我们要将训练集再划分出一部分进行验证,若验证效果好的话,最后再将整个数据进行预测推理。
2.4 模型设计
进行完数据集的划分后,我们要选择一种合适的模型进行训练。我们可以考虑很多模型,比如 y = a x + b y=ax+b y=ax+b , y = a x 2 + b x + c y=ax^2+bx+c y=ax2+bx+c或者 y = a e b x + c y=ae^{bx}+c y=aebx+c 等等。对于很多模型,我们可以先来一个线性模型,做一个baseline,然后再进行模型的优化。
本例子很明显是线性模型,所以我们选择
y
=
w
x
+
b
y=wx+b
y=wx+b 模型。训练要做到的是求解w和b。本节课简化了模型,模型选择
y
=
w
x
y=wx
y=wx 。然后,我们作图看数据分布。
2.5 损失函数
接下来,就是求解w。机器学习中,初始权重一般取一随机数。这个初始权重不一定能很好预测,所以要评估这个权重的效果(偏移,平方误差)。在机器学习中,我们叫损失。
对于这小节的任务,显然用平方偏差函数 ( y ^ − y ) 2 (\hat{y}-y)^2 (y^−y)2,我们的目标就是求解权重,使得损失最低。损失函数在本任务为 c o s t = 1 N ∑ i = 1 n ( y i ^ − y i ) 2 cost=\frac{1}{N} \sum_{i=1}^{n}(\hat{y_i}-y_i)^2 cost=N1∑i=1n(yi^−yi)2 ,平均平方误差MSE。
2.6 代码求解与可视化
本节采用的是穷举法,暂时没用Pytorch。
import numpy as np #常用函数库
import matplotlib.pyplot as plt #画图库
#定义数据集并对应打包
x_data=[1.0,2.0,3.0]
y_data=[2.0,4.0,6.0]
zip(x_data,y_data)
def forword(x_pre,wt): #向前传播预测函数
return x_pre*wt
def loss_function(x_pre,y_gt,wt): #求某一项的均方误差
y_pre=wt*x_pre
return (y_pre-y_gt)**2
loss=[] #损失保存
w_all=[] #权重保存
for i in np.arange(0.0,4.1,0.1):
w=i
loss_sum=0
for x_d,y_d in zip(x_data,y_data):
loss_tmp=loss_function(x_d,y_d,w)
loss_sum+=loss_tmp
loss_mean=loss_sum/3
loss.append(loss_mean)
w_all.append(w) #保持损失和权重,以便画图
plt.plot(w_all,loss) #画出损失曲线图
我们可以从曲线中得到当w=2时,损失最低,所以最终线性拟合函数为
y
=
2
x
y=2x
y=2x 。
不过在深度学习中,我们并不是拿权重作为横坐标,但是用训练次数epoch。我们在训练深度学习时,要重视可视化过程,因为这样可以帮助我们观察训练效果,一个常用的软件是Visdom。
2.7 作业与扩展
课下作业是两个变量w,b的线性拟合,我设计的函数是 y = 3 x − 1 y=3x-1 y=3x−1 ,方法和上面类似,为二维平面搜索法:
def loss_function2(x_pre,y_gt,wt,b):
y_pre=x_pre*wt+b
return (y_gt-y_pre)**2
x2_data=[2.0,3.0,4.0]
y2_data=[5.0,8.0,11.0]
loss2=[]
w2=[]
b2=[]
#双重循环求最佳参数
for w in np.arange(0.0,4.1,0.1):
for b in np.arange(-2.0,2.0,0.1):
#print(b)
loss=0
for x_d,y_d in zip(x2_data,y2_data):
loss_tmp=loss_function2(x_d,y_d,w,b)
loss+=loss_tmp
loss_mean=loss/3
if w==3 and b==-1:
print(loss_mean)
loss2.append(loss_mean)
w2.append(w)
b2.append(b)
min_v=9999999
w_b=0
b_b=0
print(np.min(loss2)) #最小误差
for i in range(0,len(loss2)):
if loss2[i]<min_v:
min_v=loss2[i]
w_b=w2[i]
b_b=b2[i] #求最小误差时的权重值
w_b=round(w_b)
b_b=round(b_b)
print(w_b)
print(b_b)
最后得到 w = 3 , b = − 1 w=3,b=-1 w=3,b=−1,即函数为 y = 3 x − 1 y=3x-1 y=3x−1 这和我设计的函数一样。