用穷举法求最佳权值,维度多的话会指数爆炸
分治法,先稀疏搜索,可能陷入局部最优
贪心法
梯度下降(Gradient Descent),求偏导找往loss最小值去的方向
是学习率也就是探索梯度的步长,太大会发散,太小时间太慢
也会陷入局部最优(非凸函数)
特殊点:鞍点(如马鞍),此时梯度=0(梯度消失),不再更新权值
对于的拟合使用梯度下降
对于的梯度下降的代码并画loss值的图
import matplotlib.pyplot as plt
x_data = [1.0,2.0,3.0]
y_data = [2.0,4.0,6.0]
#梯度下降拟合y=wx
w = 1 #初始权值为1
a=0.01 #学习率为0.01
def forward(x): #求当前权值下预测值
return x*w
def cost(xs,ys): ##求mse
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)
epoch_list=[]
cost_list=[]
print('predict(before training)','x=4 y=',forward(4)) ###训练前对x=4.0的y值预测
for epoch in range(100):
cost_val=cost(x_data,y_data) #求出平均损失
grad_val=gradient(x_data,y_data) #根据已推导出的公式求梯度
w=w-a*grad_val #更新权值
print('epoch:',epoch,'w=',w,'loss=',cost_val)
epoch_list.append(epoch)
cost_list.append(cost_val)
print('predict(after training)','x=4 y=',forward(4)) ###训练后对x=4.0的y值预测
plt.plot(epoch_list,cost_list)
plt.ylabel('cost')
plt.xlabel('epoch')
plt.show()
if __name__ == "__main__":
main()
设置学习率为0.5,导致发散
衍生版本:随机梯度下降SGD(Stochastic Gradient Descent)
每迭代一步或更新每一参数时,都要用到训练集中的所有样本数据(在这里权值w更新了3*100=300次)而不是所有样本的平均损失函数来进行梯度更新
引入随机性,这样即使陷入到鞍点也能跨过鞍点,并且在训练大模型的时候也能加快训练速度
对于的随机梯度下降的代码并画loss值的图
import matplotlib.pyplot as plt
x_data = [1.0,2.0,3.0]
y_data = [2.0,4.0,6.0]
#随机梯度下降拟合y=wx
w = 1 #初始权值为1
a=0.01 #学习率为0.01
def forward(x): #求当前权值下预测值
return x*w
def loss(x,y): ##求单个点的loss值
y_pred=forward(x)
return (y_pred-y)**2
def gradient(x,y):
grad=2*x*(x*w-y)
return grad
epoch_list=[]
cost_list=[]
print('predict(before training)','x=4 y=',forward(4)) ###训练前对x=4.0的y值预测
for epoch in range(100):
for x,y in zip(x_data,y_data):
loss_val=loss(x,y) #随机一个点求loss
grad_val=gradient(x,y) #根据已推导出的公式求梯度
w=w-a*grad_val #更新权值
print('epoch:',epoch,'w=',w,'loss=',loss_val)
epoch_list.append(epoch)
cost_list.append(loss_val) #一轮中最后一个样本的loss
print('predict(after training)','x=4 y=',forward(4)) ###训练后对x=4.0的y值预测
plt.plot(epoch_list,cost_list)
plt.ylabel('loss')
plt.xlabel('epoch')
plt.show()
if __name__ == "__main__":
main()
使用所有样本的Loss性能好但是时间复杂度高,使用平均样本loss则反之,于是折中每次使用一组(Mini-Batch)更新梯度