梯度下降算法
梯度下降是一种优化算法,用于最小化各种机器学习算法中的成本函数。它主要用于更新学习模型的参数。
在求解损失函数的最小值时,可以通过梯度下降法来一步步的迭代求解,得到最小化的损失函数和模型参数值。
反过来,如果我们需要求解损失函数的最大值,这时就需要用梯度上升法来迭代了。在机器学习中,基于基本的梯度下降法发展了两种梯度下降方法,分别为随机梯度下降法和批量梯度下降法。
数学基础
梯度
一元函数里梯度就是表示某一函数在该点处的方向导数沿 着该方向取得较大值,即函数在当前位置的导数。如果函数为一元函数,梯度就是该函数的导数。
而多元函数中梯度为求偏导(其实一元函数同理)
例如 f(x,y) = x^2 + y^2 在点(1,2)处的梯度
grad(f) = (∂f/∂x , ∂f/∂y) = (2x , 2y) = (2,4)
cost
它可以帮助我们计算出一个算法的准确性
cost定义了一个算法的当前表现与期望之间的差距,以便帮助我们确定算法的有效性。也可以帮我们评价模型A和模型B哪个更好,若模型A的cost小于B的cost,那么我们说模型A优于模型B。
普通算法
附上全部代码,看一遍就懂了
# 普通算法
# 梯度下降是一种优化算法,用于最小化各种机器学习算法中的成本函数。它主要用于更新学习模型的参数。
# step 1 数据集
x_data = [1.0, 2.0, 3.0] # 输入
y_data = [2.0, 4.0, 6.0] # 输出
# 要被训练的参数
w = 1.0
# 训练的线性公式 y = wx
def forward(x):
return x * w
# step 2 cost函数
# 它可以帮助我们计算出一个算法的准确性
# 它定义了一个算法的当前表现与期望之间的差距,以便帮助我们确定算法的有效性。
# 参数:xs 和 ys 是一堆x和y的值,我们在算法中要成对使用。
#
# 也可以帮我们评价模型A和模型B哪个更好
# 若模型A的cost小于B的cost,那么我们说模型A优于模型B
def cost(xs, ys):
cost = 0
for x,y in zip(xs,ys):
y_pred = forward(x) # 使用我们训练的 w 参数来计算一个 y 的预测值
cost += (y_pred - y) ** 2 # Cost先对所有 delta y 的平方 进行求和
return cost / len(xs) # 随后根据有多少点求出平均 cost
# 梯度下降 Gradient Descent
# step 3 gradient函数
# 参数与cost函数同理
def gradient(xs,ys):
grad = 0
for x,y in zip(xs,ys):
grad += 2 * x * (x * w - y) # 计算的公式 2x(wx-y) 是 cost函数 对 w 的偏导数
return grad / len(xs) # 这里也是求出平均grad
print('Predict (before training)', 4 , forward(4)) # 首先输出训练前模型的表现
for epoch in range(100): # 训练100轮
cost_val = cost(x_data, y_data) # 利用cost函数先计算本次循环的cost,用于评估训练效果
grad_val = gradient(x_data, y_data) # 算出梯度
w -= 0.01 * grad_val # 根据梯度对要训练的 w 进行相应调整
print("Epoch:", epoch, 'w=', w, 'loss=', cost_val) # 输出本轮训练信息
print('Predict (after training)', 4, forward(4)) # 输出经过训练后模型的表现
随机梯度下降
# 随机梯度下降
# 噪声能够帮助 cost 离开鞍点
# 批量随机梯度下降 (Mini-Batch)
# 折中的方法,性能中,时间复杂度中
# 相同的数据集
x_data = [1.0, 2.0, 3.0]
y_data = [2.0, 4.0, 6.0]
# 要被训练的参数
w = 1.0
# 线性模型 y = wx
def forward(x):
return x * w
# Loss函数
# 仅计算一个 x 的预测y值与真实y之间的loss
# 与cost相比,loss是一个x的loss,cost是很多个x的loss的平均值
def loss(x, y):
y_pred = forward(x)
return (y_pred - y) ** 2
# 计算梯度,即求loss的偏导数
# loss = (wx - y)^2
# grad(loss) = 2x(wx-y)
def gradient(x,y):
return 2 * x * (x * w - y)
print('Predict (before training)', 4 , forward(4))
for epoch in range(100):
# 这次我们每个循环将每个点单独计算loss
for x,y in zip(x_data, y_data):
grad = gradient(x, y) # 求出一个点的梯度
w -= 0.01 * grad # 对w进行调整
print("\tgrad: ", x,y,grad) # 输出这个点计算的梯度信息 此处y是真实值
l = loss(x,y) # 算出当前loss
print("progress:", epoch, "w=", w, "loss=", l) # 将数据集中点用过一遍后 输出本次循环训练效果
print('Predict (after training)', 4, forward(4))