SGD 代表随机梯度下降。它是一种优化算法,用于最小化机器学习模型的成本函数。SGD 和批量梯度下降 (BGD) 之间的主要区别在于,SGD 不是使用整个数据集来计算每一步的梯度,而是随机选择单个数据点或一小部分数据点(也称为小批量)来计算梯度。
在 SGD 中,成本函数是在单个数据点上计算的,模型的参数也会相应地更新。对数据集中的所有数据点或随机选择的小批量重复该过程。这使得 SGD 比 BGD 快得多,尤其是对于大型数据集,因为它计算数据点子集而不是整个数据集的梯度。
SGD 的主要优势之一是它可以帮助模型避免陷入局部最小值,这在 BGD 中可能会发生。使用 SGD,模型参数更新更频繁,梯度计算涉及随机数据点,这会在优化过程中引入更多随机性,优化器可以摆脱次优局部最小值。
但是,由于 SGD 仅使用单个数据点或一小部分数据点来更新参数,因此与 BGD 相比,它可能会导致更多噪声更新。这会使收敛变慢并导致优化过程中的振荡或不稳定。为了缓解这个问题,SGD 中的学习率通常会随着时间的推移而降低,以平滑更新。
总的来说,SGD 是一种强大的优化算法,由于其计算效率和处理噪声数据的能力,广泛应用于深度学习,特别是对于大规模数据集。但是,它需要仔细调整学习率和小批量大小以确保收敛性和稳定性。
SGD 和 BGD 的时间比较
如果我们比较具有相同时期数的 SGD 和 BGD,并假设我们使用相同的硬件和相同的学习率,那么对于每个阶段,SGD(小批量大小为 1)确实会比 BGD 执行更多的计算时代。这是因为在 SGD 中,我们需要计算每个单独数据点的梯度,而在 BGD 中,我们计算整个数据集的梯度。
例如,如果我们有 10,000 个数据点并训练 10 个 epoch,那么使用 SGD,我们将执行 100,000 (10,000 x 10) 次计算来更新模型参数。相比之下,对于 BGD,我们将仅执行 10 次计算(每个时期 1 次计算)来更新模型参数。
基于前面的解释,如果我们将 SGD 和 BGD 与相同的 epoch 数进行比较,并假设相同的硬件和学习率,那么 SGD 可能比 BGD 花费更多的时间来完成训练过程。这是因为 SGD 每个时期比 BGD 执行更多的计算,因为它使用更小批量的数据更频繁地更新模型参数。
然而,值得注意的是,算法的实际运行时间取决于许多因素,例如数据集的大小、模型的复杂性、实现细节以及超参数的选择。因此,在某些情况下,即使 epoch 数相同,SGD 也有可能比 BGD 更快。
总体而言,SGD 和 BGD 之间的选择取决于具体问题以及收敛速度和计算效率之间的权衡。SGD 通常是大型数据集或复杂模型的首选,因为它能够更频繁地更新模型参数,并且可以扩展到并行和分布式计算环境。另一方面,BGD 可能更适用于计算效率更重要的较小数据集或更简单的模型。
from sklearn.datasets import load_diabetes
import numpy as np
from sklearn.linear_model import LinearRegression
from sklearn.metrics import r2_score
from sklearn.model_selection import train_test_split
import time
X,y = load_diabetes(return_X_y=True)
print(X.shape)
print(y.shape)
>>> (442, 10)
>>> (442,)
X_train,X_test,y_train,y_test = train_test_split(X,y,test_size=0.2,random_state=2)
reg = LinearRegression()
reg.fit(X_train,y_train)
LinearRegression()
print(reg.coef_)
print(reg.intercept_)
>>> [ -9.16088483 -205.46225988 516.68462383 340.62734108 -895.54360867
561.21453306 153.88478595 126.73431596 861.12139955 52.41982836]
>>> 151.88334520854633
y_pred = reg.predict(X_test)
r2_score(y_test,y_pred)
>>> 0.4399387660024645
class SGDRegressor:
def __init__(self,learning_rate=0.01,epochs=100):
self.coef_ = None
self.intercept_ = None
self.lr = learning_rate
self.epochs = epochs
def fit(self,X_train,y_train):
# init your coefs
self.intercept_ = 0
self.coef_ = np.ones(X_train.shape[1])
for i in range(self.epochs):
for j in range(X_train.shape[0]):
idx = np.random.randint(0,X_train.shape[0])
y_hat = np.dot(X_train[idx],self.coef_) + self.intercept_
intercept_der = -2 * (y_train[idx] - y_hat)
self.intercept_ = self.intercept_ - (self.lr * intercept_der)
coef_der = -2 * np.dot((y_train[idx] - y_hat),X_train[idx])
self.coef_ = self.coef_ - (self.lr * coef_der)
print(self.intercept_,self.coef_)
def predict(self,X_test):
return np.dot(X_test,self.coef_) + self.intercept_
sgd = SGDRegressor(learning_rate=0.01,epochs=40)
start = time.time()
sgd.fit(X_train,y_train)
print("The time taken is",time.time() - start)
>>> 157.2641767094034 [ 58.34618831 -41.65635944 314.02875897 219.47021721 30.2641263
-8.98591625 -165.98040412 132.42543708 294.42536821 122.71528461]
>>> The time taken is 0.17459607124328613
y_pred = sgd.predict(X_test)
r2_score(y_test,y_pred)
>>> 0.4205755931585481
from sklearn.linear_model import SGDRegressor
reg = SGDRegressor(max_iter=100,learning_rate='constant',eta0=0.01)
reg.fit(X_train,y_train)
C:\Users\91842\anaconda3\lib\site-packages\sklearn\linear_model_stochastic_gradient.py:1220: ConvergenceWarning: Maximum number of iteration reached before convergence. Consider increasing max_iter to improve the fit.
warnings.warn("Maximum number of iteration reached before "
SGDRegressor(learning_rate='constant', max_iter=100)
y_pred = reg.predict(X_test)
r2_score(y_test,y_pred)
>>> 0.43059547063734904
显示收敛
随机梯度下降VS ****批量梯度下降
在 (SGD) 中,您可以看到某种随机行为。
随机梯度下降
批量梯度下降
随机梯度下降
在 SGD 的情况下,成本函数在迭代过程中更随机地波动,因为算法一次基于单个示例更新模型参数。这可以可视化为线向模型参数的最佳值更不稳定的收敛。然而,波动最终会在多次迭代中平均化,导致收敛到成本函数的最小值。
随机梯度下降
在 BGD 的情况下,成本函数在迭代过程中逐渐平滑地减小,因为算法在成本函数的最陡梯度方向上采取步骤。这可以看作是直线向模型参数的最佳值平滑和逐渐收敛。
批量梯度下降
随机梯度下降 (SGD) 是一种流行的优化算法,用于训练模型的机器学习。SGD 在处理大型数据集或复杂模型时特别有用,在这种情况下计算整个数据集的梯度可能不切实际或效率低下。
以下是 SGD 可能是不错选择的一些情况:
- 大型数据集:在处理大型数据集时,计算整个数据集的梯度在计算上可能非常昂贵。在这种情况下,SGD 可用于使用小批量数据点更新模型参数,这可以显着减少计算时间。
- 非凸优化问题: 在非凸优化问题中,可能存在很多局部极小值,这使得优化算法很难找到全局最小值。使用 SGD 可以帮助优化器摆脱局部最优并更快地收敛到全局最小值。
凸函数和非凸函数 (3d)
- 在线学习:在在线学习中,数据是流式的,模型需要实时更新。在这种情况下,SGD 可用于一次使用一个数据点更新模型参数,使其成为在线学习场景的理想选择。
- Regularization:SGD也可以用来实现L1和L2正则化等正则化技术,有助于防止过拟合,提高模型的泛化性能。
学习率调度器
学习率计划:使用固定的学习率可能不是最佳的,因为最佳学习率在训练期间可能会发生变化。解决方案:使用随时间逐渐降低学习率的学习率计划,例如在固定数量的 epoch 后将学习率降低 2 倍。