分治法—可能会错过更好的取值。如果数据集或者维度大,代价也大。
我们要找一个更好的算法—梯度下降算法。
梯度:gradient,本文将用g代替。
所以:
梯度下降总是朝着下降速度最快的方向。
如果不都在随便一个辅助线之上或者之下则就是非凸函数。如果损失函数是上图的曲线,很容易卡在局部最优点。那么为什么深度学习里最普遍的就是梯度下降算法呢,是因为非凸函数在真正的深度学习里是很少见的。你我们要解决的最大问题就是鞍点。
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]
w=1.0
a=0.01
def forward(x):
return x*w
def cost(xs,ys):
cost=0
for x,y in zip(xs,ys):
y_pred=forward(x)
cost+=(y_pred-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))
cost_list=[]
epoch_list=[]
for epoch in range(100):
cost_val=cost(x_data,y_data)
grad_val=gradient(x_data,y_data)
w-=a*grad_val
cost_list.append(cost_val)
epoch_list.append(epoch)
print("Epoch=",epoch,"w=",w,"cost=",cost_val)
print("Predict(after training):",4,forward(4)
运行结果:
plt.plot(epoch_list,cost_list)
plt.ylabel("cost")
plt.xlabel("epoch")
plt.show()
训练结果一定是收敛的,如果发散则训练失败了,一般原因就是学习率a太大,调参重新训练。
此时鞍点问题还是没有解决
我们引入***随机梯度下降***(Stochastic Gradient Descent)SGD
cost所有样本的损失函数,loss是一个样本的损失函数,随机梯度下降是用样本里随即一个样本来计算。
引入随机噪声可能会将鞍点跨过去,让样本继续前进,事实证明这是一种非常有效的办法。
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]
w=1.0
a=0.01
def forward(x):
return x*w
def loss_i(x,y):
y_pred=forward(x)
lossi=(y_pred-y)**2
return lossi
def Sgradient(x,y):
grad=2*x*(x*w-y)
return grad
print("Predict (before training):",4,forward(4))
for epoch in range(100):
for x,y in zip(x_data,y_data):
loss_val=loss_i(x,y)
grad_val=Sgradient(x,y)
w-=a*grad_val
print("\tgrad: ",x,y,grad_val)
print("progress:",epoch,"w=",w,"loss=",loss_val)
print("Predict(after training):",4,forward(4))
处理结果:
。
。
。
梯度下降的效率高。可能无法找到最优点。
随机梯度下降运算性能太高,无法并行,时间空间复杂度高。
实际应用的时候,我们会采用折中的方式—批量随机梯度下降(batch),性能越高越好,时间复杂度越低越好。
将一个个样本分组,用随机梯度下降法来学习。
MiNi-Batch是主流。