一、基本概念
随机梯度下降法(Stochastic Gradient Descent,SGD)相对于传统的梯度下降法,是一种更为高效的机器学习优化算法。梯度下降法每次迭代都要遍历整个训练集,计算所有样本的梯度才能更新权重,因此在大规模数据的情况下会十分耗时。而SGD每次只选取一个或一小批量样本来计算梯度,从而使得每次迭代的计算量大大降低,具有更高的计算效率。
SGD的具体实现过程如下:对于目标函数 $J(w)$,权重 $w$,学习率 $\eta$,SGD每次从训练集中随机选取一个样本 $x_i$,计算该样本的梯度 $g_i$,然后使用梯度下降法的公式更新权重:$w = w - \eta g_i$。这样不断迭代更新,直到达到一定的迭代次数或者达到收敛要求即可。
下面给出SGD的伪代码实现:
for i in range(0, max_iter): shuffle(X) # 打乱训练集 for j in range(num_samples): # 随机选取一个训练样本进行梯度计算 xi = X[j] yi = y[j] gi = compute_gradient(J, xi, yi, w) # 更新权重 w = w - eta * gi
二、SGD的优点
1、高效:SGD每次只需要计算一个样本的梯度,计算量较小,适合大规模数据集的优化问题。
2、易于并行:SGD每次更新只操作一个样本,易于实现并行化操作,从而大大缩短了计算时间。
3、可收敛到局部最优解:SGD的收敛路径具有一定的随机性,能在一定程度上跳出局部最优解,收敛到全局最优解的概率也相对较大。
三、SGD的缺点与改进
1、收敛速度慢:SGD每次只更新一个样本,可能会出现跳出最优解的情况,同时也容易受到样本噪声的干扰,导致收敛速度慢。
2、有一定的不稳定性:由于每次只考虑一个样本,SGD可能会受到单个样本的影响,进而影响到整个模型的参数更新。
为了克服SGD的缺点,研究者们提出了一系列改进方法。其中最常见的是Batch SGD和Mini-batch SGD。Batch SGD每次更新所有的样本梯度,Mini-batch SGD选取一个小批量样本进行梯度计算,大小通常设置在2~256之间。这样权衡了运算速度和参数更新的精度。
下面给出Mini-batch SGD的实现代码:
for i in range(0, max_iter): shuffle(X) # 打乱训练集 for j in range(0, num_samples, batch_size): # 随机选取一个小批量训练样本进行梯度计算 batch_indices = range(j, min(j + batch_size, num_samples)) X_batch = X[batch_indices] y_batch = y[batch_indices] gi = compute_gradient(J, X_batch, y_batch, w) # 更新权重 w = w - eta * gi
四、实战代码示例
下面以sklearn库中的breast_cancer数据集为例,展示如何使用SGDClassifier类进行二分类问题训练。在示例代码中,我们使用SGDClassifier类进行100次迭代的训练,打印出了训练集和测试集上的分类准确率。
from sklearn.datasets import load_breast_cancer from sklearn.linear_model import SGDClassifier from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler # 加载数据集 data = load_breast_cancer() X = data.data y = data.target # 数据归一化 scaler = StandardScaler() X = scaler.fit_transform(X) # 划分训练集和测试集 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) # 使用SGDClassifier进行训练 clf = SGDClassifier(max_iter=100, tol=1e-3) clf.fit(X_train, y_train) # 打印结果 print("Train set score:", clf.score(X_train, y_train)) print("Test set score:", clf.score(X_test, y_test))