🎬个人简介:一个全栈工程师的升级之路!
📋个人专栏:pytorch深度学习
🎀CSDN主页 发狂的小花
🌄人生秘诀:学习的本质就是极致重复!
视频来自【b站刘二大人】
目录
1 梯度下降(Gradient Descent)
2 随机梯度下降(SGD Stochastic Gradient Descent)
3 批量梯度下降(BGD Batch Gradient Descent)
4 小批量梯度下降(mini-Batch GD,mini-batch Gradient Descent)
5 代码
1 梯度下降(Gradient Descent)
- 梯度:
方向导数在该点的最大值,建立cost与w的关系,优化使得w能够快速收敛
- 引入:
可以发现上一章节我们寻找权重ω的时候,使用的是遍历 ω 的方法,显然在工程上这是不可行的,于是引入了梯度下降(Gradient Descent)算法。
- 方案:
我们的目标是找出 ω∗ 最小化 cost(ω)函数 。梯度下降使用公式ω=ω−α∗∂cost∂ω,其中α是人为设定的学习率,显然 ω 总是往cost局部最小化的方向趋近(可以注意并不总是往全局最优的方向)
- 局部最优:
我们经常担心模型在训练的过程中陷入局部最优的困境中,但实际上由于Mini-batch的存在在实际工程中模型陷入鞍点(局部最优)的概率是很小的
- epoch:
轮次,一个epoch指的是所有的训练样本在模型中都进行了一次正向传播和一次反向传播
2 随机梯度下降(SGD Stochastic Gradient Descent)
随机梯度下降算法在梯度下降算法的基础上进行了一定的优化,其对于每一个实例都进行更新,也就是不是用MSE,而是
对 ω进行更新
优势:SGD更不容易陷入鞍点之中,同时其拥有更好的性能
优点:
由于不是在全部训练数据上的损失函数,而是在每轮迭代中,随机优化某一条训练数据上的损失函数,这样每一轮参数的更新速度大大加快。
缺点:
准确度下降。由于即使在目标函数为强凸函数的情况下,SGD仍旧无法做到线性收敛。
可能会收敛到局部最优,由于单个样本并不能代表全体样本的趋势.
不易于并行实现。
for i in range(number of epochs):
np.random.shuffle(data)
for each in data:
weights_grad = evaluate_gradient(loss_function, each, weights)
weights = weights - learning_rate * weights_grad
3 批量梯度下降(BGD Batch Gradient Descent)
BGD通常是取所有训练样本损失函数的平均作为损失函数,每次计算所有样本的梯度,进行求均值,计算量比较大,会陷入鞍点
优点:
一次迭代是对所有样本进行计算,此时利用矩阵进行操作,实现了并行。
由全数据集确定的方向能够更好地代表样本总体,从而更准确地朝向极值所在的方向。当目标函数为凸函数时,BGD一定能够得到全局最优。
缺点:
当样本数目 m 很大时,每迭代一步都需要对所有样本计算,训练过程会很慢。(有些样本被重复计算,浪费资源)
for i in range(number of epochs):
np.random.shuffle(data)
for each in data:
weights_grad = evaluate_gradient(loss_function, each, weights)
weights = weights - learning_rate * weights_grad
4 小批量梯度下降(mini-Batch GD,mini-batch Gradient Descent)
mini-batch GD采取了一个折中的方法,每次选取一定数目(mini-batch)的样本组成一个小批量样本,然后用这个小批量来更新梯度,这样不仅可以减少计算成本,还可以提高算法稳定性。
for i in range(number of epochs):
np.random.shuffle(data)
for batch in get_batches(data, batch_size = batch_size):
weights_grad = evaluate_gradient(loss_function, batch, weights)
weights = weights - learning_rate * weights_grad
优点:融合了BGD和SGD优点
- 通过矩阵运算,每次在一个batch上优化神经网络参数并不会比单个数据慢太多。
- 每次使用一个batch可以大大减小收敛所需要的迭代次数,同时可以使收敛到的结果更加接近梯度下降的效果。
- 可实现并行化。
梯度下降:BGD、SGD、mini-batch GD介绍及其优缺点
blog.csdn.net/qq_41375609/article/details/112913848编辑
5 代码
- BGD
import matplotlib.pyplot as plt
import numpy as np
# BGD 批量梯度下降
x_data = np.arange(1.0,200.0,1.0)
y_data = np.arange(2.0,400.0,2.0)
def forward(x,w):
return x*w
def cost(x,y,w):
cost = 0
for x_val,y_true in zip(x,y):
y_pred = forward(x_val,w)
loss_val = (y_true - y_pred)**2
cost = cost + loss_val
return cost/len(x)
def gradient(x,y,w):
gradient = 0
for x_val,y_true in zip(x,y):
gradient_temp = 2 * x_val *(x_val * w - y_true)
gradient = gradient + gradient_temp
return gradient/len(x)
w = 1.0
lr = 0.00001
epoch_list = []
cost_list = []
print("Before train 4: ",forward(400,w))
for epoch in range(100):
cost_val = cost(x_data,y_data,w)
gradient_val = gradient(x_data,y_data,w)
w = w - lr * gradient_val
print("epoch: ",epoch," loss: ",cost_val," w: ",w)
epoch_list.append(epoch)
cost_list.append(cost_val)
if (cost_val < 1e-5):
break
print("After train 4: ",forward(400,w))
plt.plot(epoch_list,cost_list)
plt.xlabel("epoch")
plt.ylabel("loss")
plt.savefig("./data/pytorch2.png")
- SGD
import matplotlib.pyplot as plt
import numpy as np
# SGD随机梯度下降
x_data = np.arange(1.0,200.0,1.0)
y_data = np.arange(2.0,400.0,2.0)
def forward(x,w):
return x * w
def loss(x,y_true,w):
y_pred = forward(x,w)
return (y_pred-y_true)**2
def gradient(x,y,w):
return 2 *x *(x *w-y)
w = 1.0
lr = 0.00001
epoch_list = []
loss_list = []
print("Before train 4: ",forward(400,w))
for epoch in range(1000):
seed = np.random.choice(range(len(x_data)))
loss_val = loss(x_data[seed],y_data[seed],w)
gradient_val = gradient(x_data[seed],y_data[seed],w)
w -= lr*gradient_val
print("epoch: ",epoch," loss: ",loss_val," w: ",w)
epoch_list.append(epoch)
loss_list.append(loss_val)
if (loss_val < 1e-7):
break
print("After train 4: ",forward(400,w))
plt.plot(epoch_list,loss_list)
plt.xlabel("epoch")
plt.ylabel("loss")
plt.savefig("./data/pytorch2_1.png")
- mini-Batch GD
import matplotlib.pyplot as plt
import numpy as np
import random
# mini-batch GD 小批量随机梯度下降
x_data = np.arange(1.0,200.0,1.0)
y_data = np.arange(2.0,400.0,2.0)
def forward(x,w):
return x*w
def cost(x,y,w):
cost = 0
for x_val,y_true in zip(x,y):
y_pred = forward(x_val,w)
loss_val = (y_true - y_pred)**2
cost = cost + loss_val
return cost/len(x)
def gradient(x,y,w):
gradient = 0
for x_val,y_true in zip(x,y):
gradient_temp = 2 * x_val *(x_val * w - y_true)
gradient = gradient + gradient_temp
return gradient/len(x)
def get_seed_two(nums):
# 从数组中随机取两个索引
index1 = random.randrange(len(nums))
index2 = random.randrange(len(nums))
while index2 == index1:
index2 = random.randrange(len(nums))
return index1, index2
w = 1.0
lr = 0.00001
batch_size = 2
epoch_list = []
loss_list = []
# 存储随机取出的数的索引
seed = []
# 存储一个batch的数据
x_data_mini = []
y_data_mini = []
print("Before train 4: ",forward(400,w))
for epoch in range(1000):
# 设定Batchsize 大小为2,每次随机取所有数据中的两个,作为一个batch,进行训练
idx1,idx2= get_seed_two(x_data)
seed.append(idx1)
seed.append(idx2)
for i in range(batch_size):
x_data_mini.append(x_data[seed[i]])
y_data_mini.append(y_data[seed[i]])
loss_val = cost(x_data_mini,y_data_mini,w)
gradient_val = gradient(x_data_mini,y_data_mini,w)
w -= lr*gradient_val
print("epoch: ",epoch," loss: ",loss_val," w: ",w)
epoch_list.append(epoch)
loss_list.append(loss_val)
if (loss_val < 1e-7):
break
print("After train 4: ",forward(400,w))
plt.plot(epoch_list,loss_list)
plt.xlabel("epoch")
plt.ylabel("loss")
plt.savefig("./data/pytorch2_2.png")
🌈我的分享也就到此结束啦🌈
如果我的分享也能对你有帮助,那就太好了!
若有不足,还请大家多多指正,我们一起学习交流!
📢未来的富豪们:点赞👍→收藏⭐→关注🔍,如果能评论下就太惊喜了!
感谢大家的观看和支持!最后,☺祝愿大家每天有钱赚!!!欢迎关注、关注!