Pytorch深度学习(一):前馈神经网络(FNN)
参考B站课程:《PyTorch深度学习实践》完结合集 传送门:《PyTorch深度学习实践》完结合集
一、线性模型:
已知数据:
x
=
[
1
,
2
,
3
]
,
y
=
[
2
,
4
,
6
]
x=[1,2,3],\quad y=[2,4,6]
x=[1,2,3],y=[2,4,6] 预测
x
=
4
x=4
x=4时,
y
y
y等于多少 建立线性模型
y
^
=
w
?
x
,
x
,
y
^
∈
R
\hat{y}=w*x,\quad x,\hat{y}\in\mathbb{R}
y^?=w?x,x,y^?∈R 估计权重
w
w
w(weight),再来预测
x
=
4
x=4
x=4时
y
y
y的值。 定义MSE(Mean Square Error):
c
o
s
t
=
1
N
∑
n
=
1
N
(
y
^
n
?
y
n
)
2
cost=\frac{1}{N}\sum_{n=1}^{N} (\hat{y}_n-y_n)^2
cost=N1?n=1∑N?(y^?n??yn?)2
二、普通方法
在可能的区间内
(
0
,
??
4.1
)
(0,\;4.1)
(0,4.1)内遍历来试探最优的权重
w
w
w使得误差MSE最小
import numpy as np
from matplotlib import pyplot as plt
xdata = [1, 2, 3]
ydata = [2, 4, 6]
def forward(x):
return x * w
def loss(x, y):
ypred = forward(x)
return (ypred-y)**2
wlist = []
mse = []
for w in np.arange(0, 4.1, 0.1):
print('w=', w)
lsum = 0
for x_val, y_val in zip(xdata, ydata):
ypred_val = forward(x_val)
lossval = loss(x_val, y_val)
lsum += lossval
print('\t', x_val, y_val, ypred_val, lossval)
print('MSE=', lsum/3)
wlist.append(w)
mse.append(lsum/3)
plt.plot(wlist, mse)
plt.ylabel('Mean squre error')
plt.xlabel('weight')
plt.show()
可见最佳的权重在2.0附近,但这种算法是不够好的,首先区间不好找,其次遍历的步长会影响精度,并且遍历会耗费了大量的计算力。
三、梯度下降法(Gradient Descent)
这是经典的优化算法,在局部确定MSE下降速度最快的方向(梯度的反方向)来求得局部解.
c
o
s
t
=
1
N
∑
n
=
1
N
(
y
^
n
?
y
n
)
2
=
1
N
∑
n
=
1
N
(
x
n
?
w
?
y
n
)
2
cost=\frac{1}{N}\sum_{n=1}^{N} (\hat{y}_n-y_n)^2=\frac{1}{N}\sum_{n=1}^{N} (x_n*w-y_n)^2
cost=N1?n=1∑N?(y^?n??yn?)2=N1?n=1∑N?(xn??w?yn?)2 则梯度方向
?
c
o
s
t
?
w
=
2
N
∑
n
=
1
N
x
n
(
x
n
?
w
?
y
n
)
\frac{\partial cost}{\partial w}=\frac{2}{N}\sum_{n=1}^{N} x_n(x_n *w -y_n)
?w?cost?=N2?n=1∑N?xn?(xn??w?yn?) 更新权重
w
w
w
w
=
w
?
0.01
?
?
c
o
s
t
?
w
w = w-0.01*\frac{\partial cost}{\partial w}
w=w?0.01??w?cost? 其中,0.01是学习率,其不宜取得过大
import numpy as np
from matplotlib import pyplot as plt
xdata = [1, 2, 3]
ydata = [2, 4, 6]
w = 1.0
costlist = []
def forward(x):
return x * w
def cost(xs, ys):
cost = 0
for x, y in zip(xs, ys):
ypred = forward(x)
cost += (ypred - y) **2
return cost / len(xs)
def gradient(xs, ys):
grad = 0
for x, y in zip(xs, ys):
grad += 2 * x * (x * w -y)
return grad / len(xs)
print('Predict(before training', 4, forward(4))
for epoch in range(100):
cost_val = cost(xdata, ydata)
costlist.append(cost_val)
grad_val = gradient(xdata, ydata)
w -= 0.01 * grad_val
print('Epoch:', epoch, 'w=', w, 'loss=', cost_val)
print('Predict(after training)', 4, forward(4))
plt.plot(range(100), costlist)
plt.xlabel('epoch')
plt.ylabel('cost')
plt.title('Gradient Descent')
plt.show()
可见收敛效果较好。最后一步输出的权重以及,预测值如下
Epoch: 99 w= 1.9999444396553017 loss= 1.752432687141379e-08
Predict(after training) 4 7.999777758621207
四、随机梯度下降法(Stochastic Gradient Descent)
正如前所言,DG算法可能陷入局部,一旦碰到拐点等情况就没有办法求到全局最优,于是引入随机梯度下降法 优点:有可能避免陷入局部最优 缺点:计算量比DG更大
import numpy as np
from matplotlib import pyplot as plt
xdata = [1, 2, 3]
ydata = [2, 4, 6]
w = 1.0
costlist = []
def forward(x):
return x * w
def loss(x,y):
ypred = forward(x)
return (ypred - y) ** 2
def gradient(xs, ys):
return 2 * x *(x*w -y)
print('Predict(before training', 4, forward(4))
for epoch in range(100):
for x,y in zip(xdata, ydata):
grad = gradient(x,y)
w = w - 0.01*grad
print('\t grad :', x, y, grad)
l = loss(x,y)
print('progress:', epoch, 'w=', w, 'loss=', l)
costlist.append(l)
print('Predict(after training)', 4, forward(4))
plt.plot(range(100), costlist)
plt.xlabel('epoch')
plt.ylabel('cost')
plt.title('Stochastic Gradient Descent')
plt.show()
progress: 99 w= 1.9999999999999236 loss= 5.250973729513143e-26
Predict(after training) 4 7.9999999999996945
可以看到同样的迭代步数,SDG算法最后产生的误差的数量级比DG算法更小
我们比较两种算法的误差图像: 但SDG算法存在计算量相对大的缺点,所以在实际应用当中可以部分数据用DG,部分数据用SDG。
五、前馈神经网络(FNN)
以上就是一个简单的前馈神经网络的例子,它的第一次“学习”过程如下:
这里由于我们推导出了误差(MSE)关于权重
w
w
w的解析式
?
c
o
s
t
?
w
=
2
N
∑
n
=
1
N
x
n
(
x
n
?
w
?
y
n
)
\frac{\partial cost}{\partial w}=\frac{2}{N}\sum_{n=1}^{N} x_n(x_n *w -y_n)
?w?cost?=N2?n=1∑N?xn?(xn??w?yn?)所以带入相关数据和即可得到梯度值,从而更新
w
w
w。然而实际情况可能更为复杂,不一定能直接求出解析式,仔细观察我们知道:
- 我们不一定非得得到解析式,只需要得到每一次误差
l
o
s
s
loss
loss “反馈” 给权重
w
w
w的值,用于更新
w
w
w
这就是反馈神经网络(BPNN)的基本思想,具体见下一篇文章。
|