写在前面:
学习pytorch也有一段时间了,一直都是在网上看别人的代码然后自己再敲一遍,把不理解的地方查找一下资料,但是总感觉缺点是什么,仔细思考一下整个过程,有点类似背代码的意思,这是非常要命的一点,所以今天就索性把这个在从头一点一点的利用晚上的时间再复习一边,
我们先来创建一个简单的线性回归方程,y=wx+b,这是一个一元一次方程,有点基础就知道,,神经网络是一个求参数的过程,通过不断的寻找最优解,不断的寻找参数。
我们要知道这个网络创建的一个过程,首先应该是干什么,我们的任务是什么,
y=wx+b中参数是谁?w和b,那么我的任务就是求解参数,
1、首先我们要确定模型
2、我们要确定损失函数
3,我们要把求解的w和b的梯度更新一下
以上就是我们要做的任务,但是在我们做这个任务之前,我们要了解pytorch和Pythonde 一些函数,而且我们要知道我们必须使用的是tensor的数据类型,我们要知道怎么创建自己的数据,所以下面先简单的写几个函数
torch.rand(size)
这个是干啥用的呢?这个函数是从【0-1】的均匀分布之间随机产生一组数据,数据的形状(shape)由size决定,比如下边这个例子
tensor_arr=torch.rand(10,1)
print(tensor_arr)
-----》
[8.5231],
[5.8976],
[1.9832],
[1.7113],
......
这就是它创建的一个数据,形状可以自己定
它还有一个双胞胎兄弟,
torch.randn(sizes)
a=torch.rangn((1),requires_grad=True)
print(a)
----->打印结果如下
tensor([-1.2733], requires_grad=True)
他会返回一个张量,这个张量包含了从标准正态分布中(标准差0方差1,即高斯白噪声)随机抽取一组数据,形状(shape)由sizes定,具体例子如上所示,其中这个 requires_grad=True是啥意思呢,这个是求导的意思,意识是这个参数要求导,因为这里我让它做了y=wx+b中的w,所以设定了要求导的表示,不求导可以设置相反,
损失函数
然后什么是损失函数呢?损失函数会有一个损失值,这是损失值的作用是干啥的呢?
这个值的作用是衡量实际输出值与目标值之间的差距,差距越小越好,这个值也就是为我们更新参数提供依据(反向传播loss.backward()),这里简单写一下损失函数,在摸索的过程中可以自己瞎搞
loss=0.58(L1-L2)^2.mean()
L1是L2就是我们说的目标值和预测值,loss就是损失值,我们根据这个值
来更新参数w和b
参数更新
在得到损失值之后,我们可以根据这个值来求解最近的参数,然后再次计算损失值,只有参数更新后我们才能知道下一次的损失值与目标值之间的差距
梯度清零
w.grad.zero_()
b.grad.zero_()
为啥要梯度清零呢?
因为在每次的反向传播之前要把梯度清零,这样梯度值才不会累加,不清零的话上一次反向传播结果会对下一次的反向传播造成影响
最后是一个简单的线性回归模型
#首先我们要有训练样本,这里我们用x和y表示,随机生成的
import torch
x=torch.rand(20,1)*10
y=2*x+(5+torch.rand(20,1)*10)
#构建线性回归参数w,b
w=torch.randn((1),requires_grad=True)#随机生成矩阵,元素服从均值为0方差为1的正态分布
print(w)
b=torch.randn((1),requires_grad=True)#两个参数都需要求导
#print(b)
for item in range(10):
#前向传播
wx=torch.mul(w,x)#mul什么意思,相乘的意思,wx+b中的w和b相乘
y_pred=torch.add(wx,b)#y=wx+b待预测模型,这个和wx是一个道理,把wx和b加起来
#计算loss
loss=(0.5*(y-y_pred)**2).mean()#损失函数
#反向传播
loss.backward()
#更新参数
lr=0.01#学习率
w.data.sub_(lr*w.grad.data)
b.data.sub_(lr * b.grad.data)
#梯度清零
w.grad.data.zero_()
b.grad.data.zero_()
#print(w.data,b.data)
利用随机梯度下降法来更新参数,是损失函数最小化,
由两中计算梯度的方法,一种是手动的,一种是利用autograd实现自动微分,一定要注意在反向传播之前,先把梯度清零