机器学习训练营——机器学习爱好者的自由交流空间(qq 群号:696721295)
随机梯度下降(Stochastic Gradient Descent, SGD)是一种简单高效的线性分类器判别学习方法。该方法针对的是凸损失函数,例如,(线性)支持向量机、Logistic回归。虽然SGD在机器学习领域已经提出了很久,但随着近年来的大规模学习它才受到重视。
SGD已经成功地应用到文本分类、自然语言处理这样的大规模和稀疏的机器学习问题里。假设数据是稀疏的,分类器很容易遭遇超过 个训练样本、 个特征这类问题。随机梯度下降的优势主要体现在:
高效率
易执行
它的不足包括:
SGD需要很多超参数,例如正则参数、迭代次数。
SGD对于特征变换是敏感的。
分类
类SGDClassifier
执行一个普通的随机梯度下降程序,它支持不同的损失函数和分类惩罚。SGD必须拟合两个数组:[n_samples, n_features]数组X, 装载训练样本; [n_samples]数组Y, 装载训练样本的目标值(即,类标签)。
from sklearn.linear_model import SGDClassifier
X = [[0., 0.], [1., 1.]]
y = [0, 1]
clf = SGDClassifier(loss="hinge", penalty="l2")
clf.fit(X, y)
拟合后的模型可以用来预测新值。
clf.predict([[2., 2.]])
SGD拟合一个线性模型到训练数据上,成员coef_装载模型参数,成员intercept_装载常数项。
clf.coef_
clf.intercept_
至于模型是否应该有常数项,即,一个有偏超平面,由参数fit_intercept控制。
使用SGDClassifier.decision_function
得到带符号的超平面距离。
clf.decision_function([[2., 2.]])
损失函数由参数loss设置,SGDClassifier支持下面的几种损失函数:
loss=”hinge”: 灵活边界的线性支持向量机
loss=”modified_huber”: 平滑的hinge损失
loss=”log”: logistic回归
下面所列的所有回归损失
其中,前两个损失函数是lazy的,只有当一个例子样本违反了边界约束,它才升级模型参数。这使得训练非常有效,即使使用L2惩罚也可能导致更稀疏的模型。
使用loss=”log” or loss=”modified_huber”时, 能够使用predict_proba方法,它给每一个样本 一个概率估计 的向量。
clf = SGDClassifier(loss="log").fit(X, y)
clf.predict_proba([[1., 1.]])
参数penalty设置惩罚项。SGD支持以下惩罚形式:
penalty=”l2”: 惩罚在coef_上的L2范数
penalty=”l1”: 惩罚在coef_上的L1范数
penalty=”elasticnet”: L1, L2的凸组合,(1 - l1_ratio) L2 + l1_ratio L1
默认设置是penalty=”l2”. L1惩罚导致稀疏解,这使得很多系数被迫为0. 弹性网格解决了L1惩罚在属性高度相关情况下的不足,参数l1_ratio控制L1, L2惩罚的凸组合形式。
SGDClassifier支持多类别分类,这是通过组合多个二值分类器在一个“one versus all” (OVA)方案里实现的。对于K个类的每一个类,学习一个二值分类器,判别属于该类还是其余K-1个类。在检验时,我们计算每一个类的置信分数,即,该类边界与超平面的带符号距离,选择具有最高分数的类。下图解释了iris数据集的OVA方法,其中的虚线代表三个OVA分类器,背景颜色代表了决策面。
在多类的分类里,coef_是一个[n_classes, n_features]二维数组,intercept_是一个[n_classes]一维数组。coef_的第i行装载第i类的权向量,类标号按升序排列。请注意,原则上,由于允许产生一个概率模型,所以loss=”log” and loss=”modified_huber”更适合one-vs-all分类。
回归
类SGDRegressor
执行一个普通的随机梯度下降学习程序,支持不同的损失函数和惩罚拟合线性回归模型。SGDRegressor也很适合大训练样本(>10,000)的回归问题。对于其它问题,我们推荐使用类Ridge, Lasso, ElasticNet.
损失函数由参数loss设置,SGDRegressor支持以下几种损失函数:
loss=”squared_loss”: 普通最小二乘
loss=”huber”: 稳健回归的huber损失
loss=”epsilon_insensitive”: 线性支持向量回归
huber and epsilon_insensitive损失用于稳健回归。非敏感区域的宽度由参数epsilon指定。
实际应用提示
- 随机梯度下降对于特征scaling是敏感的,因此强烈建议scale数据。例如,scale输入向量X的每个属性到[0, 1]或[-1, 1], 或者标准化为0均值、1标准差。请注意,相同的scaling必须被应用到检验向量,这样才能获得有意义的结果。使用
StandardScaler
很容易完成。
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
scaler.fit(X_train) # Don't cheat - fit only on training data
X_train = scaler.transform(X_train)
X_test = scaler.transform(X_test) # apply same transformation to test data
mits_{i=1}^n L(y_i, f(x_i))+\alpha R(w)$$
这里,
是测量模型拟合的损失函数,
是正则项,或称惩罚项,惩罚模型的复杂度。
是一个非负超参数。选择不同的损失函数对应不同的分类器:
Hinge: 灵活边界的支持向量机
Log: Logistic回归
Least-Squares: 岭回归
Epsilon-Insensitive: 灵活边界的支持向量回归
以上所有损失函数都被当作错分如果你的属性有固有的scale, 比如说词频数、指示特征,则不必作scaling.
使用GridSearchCV找到一个合理的正则项 , 范围通常在10.0**-np.arange(1,7).
经验地,我们发现SGD收敛于观测大概 个训练样本之后。那么,一个合理的迭代数猜想是n_iter = np.ceil(10**6 / n), 这里的n是训练集样本数。
如果你应用SGD到使用主成分提取的特征上,你会发现按下面的办法scale特征是明智的:通过某常数c, 使得训练数据的平均的L2范数等于1.
数学原理
给定一个训练样本集
,
, 我们的目标是学习一个线性打分函数
, 其中模型参数
, 截距项
. 为了作预测,我们只考虑
的符号。估计模型参数的一个普遍的方法是最小化正则的训练误差
$$E(w, b)=\frac{1}{n}\sum\li误差的上界,如下图所示
对于正则项 的主流选择包括:
L2范数:
L1范数: , 导致稀疏解
弹性网格: , L1, L2的凸组合, 由1 - l1_ratio指定。
SGD
随机梯度下降(SGD)是一个优化方法,主要用于无约束的优化问题。与传统的梯度下降比较,SGD近似
的真实梯度,一次考虑一个训练样本。类SGDClassifier
执行一个一阶的SGD学习程序,该算法在训练样本上迭代。对于每一个样本,根据以下公式升级参数
这里,
是学习率,用来控制参数空间的搜索步长,或者为常数,或者逐渐减小。对于分类问题,默认的学习率learning_rate=’optimal’, 由下式给出
这里, 是时间步长,总共有n_samples * n_iter 次步, 由一个heuristic方法确定,它的精确定义可以在BaseSGD的_init_t里找到。
对于回归,默认的学习率learning_rate=’invscaling’, 由下式给出
这里, , 是超参数,由用户在
eta0
,
power_t
里选择。
对于一个常数学习率,使用learning_rate=’constant’, 由eta0指定学习率。
模型参数可以由成员coef_, intercept_访问。
成员coef_装载权向量
成员intercept_装载
阅读更多精彩内容,请关注微信公众号:统计学习与大数据