python sklearn 梯度下降法_梯度下降法及其Python实现

基本介绍

梯度下降法(gradient descent),又名最速下降法(steepest descent)是求解无约束最优化问题最常用的方法,它是一种迭代方法,每一步主要的操作是求解目标函数的梯度向量,将当前位置的负梯度方向作为搜索方向。

梯度下降法特点:越接近目标值,步长越小,下降速度越慢。

下面将通过公式来说明梯度下降法。

建立模型为拟合函数

equation?tex=h%28%CE%B8%29

equation?tex=+h%28%CE%B8%29%3D+%5Ctheta_%7B0%7D%2B+%5Ctheta_%7B1%7D+x_%7B1%7D%2B....%2B+%5Ctheta_%7Bn%7D+x_%7Bn%7D%3D%5Csum_%7Bj%3D0%7D%5E%7Bn%7D%5Ctheta_%7Bj%7D+x_%7Bj%7D

接下来的目标是将该函数通过样本的拟合出来,得到最佳的函数模型。因此构建损失函数

equation?tex=J%28%CE%B8%29 (目的是通过求解

equation?tex=min+J%28%CE%B8%29 ,得到在最优解下的

equation?tex=%CE%B8 向量),其中的每一项

equation?tex=h_%7B%CE%B8%7D%28x%5E%7Bi%7D%29-y%5E%7Bi%7D 都表示在已有的训练集上我们的拟合函数与 之间的残差,计算其平方损失函数作为我们构建的风险函数(这里采用最小二乘法构造损失函数,在逻辑回归中也可采用最大似然估计构造损失函数从而估计参数)。

equation?tex=min+J%28%CE%B8%29%3D%5Cfrac%7B1%7D%7B2%7D%5Csum_%7Bi%3D0%7D%5E%7Bm%7D%28h_%7B%CE%B8%7D%28x%5E%7Bi%7D%29-y%5E%7Bi%7D%29%5E2

要使得

equation?tex=J%28%CE%B8%29 最小,则对其

equation?tex=J%28%CE%B8%29 求导等于零。

equation?tex=%CE%B8_%7Bj%7D%3A%3D%CE%B8_%7Bj%7D-%5Cfrac%7B%5Cpartial+J%28%5Ctheta%29%7D%7B%5Cpartial+%CE%B8_%7Bj%7D+%7D

在处理以下步骤时,可以用批量梯度下降算法(BGD)与随机梯度下降算法(SGD)。

批量梯度下降算法(BGD)

单个特征

equation?tex=x%5E%7Bi%7D 的迭代如下:

equation?tex=%CE%B8_%7Bj%7D%3A%3D%CE%B8_%7Bj%7D%2Ba%28y%5Ei-h_%CE%B8%28x%5Ei%29%29x%5Ei_j

equation?tex=a 为步长,如果太小,则找到函数最小值的速度就很慢,如果太大,则可能会错过最小值,而使得函数值发散。初始点不同,获得的最小值也不同,因此梯度下降求得的只是局部最小值。

多个特征的迭代如下:

repeat until convergence{

equation?tex=%CE%B8_%7Bj%7D%3A%3D%CE%B8_%7Bj%7D%2Ba%5Csum%5Em_%7Bi%3D1%7D%28y%5Ei-h_%CE%B8%28x%5Ei%29%29x%5Ei_j+ (for every )

}

当上式收敛时则退出迭代,一开始设置一个具体参数,当前后两次迭代差值小于该参数时候结束迭代。

使用梯度下降法,越接近最小值时,下降速度越慢。计算批量梯度下降法时,计算每一个θ值都需要遍历计算所有样本,当数据量比较大时这是比较费时的计算。

随机梯度下降算法(SGD)

为解决数据量大的时批量梯度下降算法费时的困境。随机梯度下降算法,每次迭代只是考虑让该样本点的

equation?tex=J%28%CE%B8%29 趋向最小,而不管其他的样本点,这样算法会很快,但是收敛的过程会比较曲折,整体效果上,大多数时候它只能接近局部最优解,而无法真正达到局部最优解。该算法适合用于较大训练集的例子。

Loop{

for i=1 to m,{

equation?tex=%CE%B8_%7Bj%7D%3A%3D%CE%B8_%7Bj%7D%2Ba%28y%5Ei-h_%CE%B8%28x%5Ei%29%29x%5Ei_j (for every )

}

}

改进的随机梯度下降算法

为了避免迭代时系数出现周期性波动,同时让系数很快收敛,这里改进随机梯度下降算法。

1)在每次迭代时,调整更新步长

equation?tex=a 的值。随着迭代的进行,

equation?tex=a 越来越小,这会缓解系数的高频波动。同时为了避免

equation?tex=a 随着迭代不断减小到接近于0,约束

equation?tex=a 一定大于一个稍微大点的常数项。

2)每次迭代,改变样本的优化顺序。也就是随机选择样本来更新回归系数。这样做可以减少周期性的波动,因为样本顺序的改变,使得每次迭代不再形成周期性。

算法应用和python实现

梯度下降法可以用于在前面提到的logistic回归分类器中,主要是求解模型中的cost函数,这里用泰坦尼克数据集进行演示,并且使用python中的sklearn库进行实现,代码如下:

import pandas

from sklearn.linear_model import LinearRegression, LogisticRegression

from sklearn.model_selection import KFold, cross_val_score

import numpy as np

titanic = pandas.read_csv('E:\TitanicData\Titanic\\train.csv')

# print(titanic.describe())

titanic['Age'] = titanic['Age'].fillna(titanic['Age'].mean())

# print(titanic.describe())

# print(titanic['Sex'].unique())

titanic.loc[titanic['Sex'] == 'male', 'Sex'] = 0

titanic.loc[titanic['Sex'] == 'female', 'Sex'] = 1

# print(titanic['Embarked'].unique())

titanic['Embarked'] = titanic['Embarked'].fillna('S')

titanic.loc[titanic['Embarked'] == 'S', 'Embarked'] = 0

titanic.loc[titanic['Embarked'] == 'C', 'Embarked'] = 1

titanic.loc[titanic['Embarked'] == 'Q', 'Embarked'] = 2

# print(titanic.columns)

predictors = ['Pclass', 'Sex', 'Age', 'SibSp', 'Parch', 'Fare', 'Embarked']

#开始线性回归预测

alg = LinearRegression()

X = titanic[predictors]

kf = KFold(n_splits=3)

prediction = []

for train, test in kf.split(X):

x_train = titanic[predictors].iloc[train, :]

y_train = titanic['Survived'].iloc[train]

x_test = titanic[predictors].iloc[test, :]

y_test = titanic['Survived'].iloc[test]

alg.fit(x_train, y_train)

test_prediction = alg.predict(x_test)

prediction.append(test_prediction)

prediction = np.concatenate(prediction)

prediction[prediction > 0.5] = 1

prediction[prediction < 0.5] = 0

accuracy_linear = sum(prediction[prediction == titanic['Survived']])/len(prediction) #查准率

#score1 = cross_val_score(alg, X, titanic['Survived'], cv=3).mean()

# cross_val_score是直接将算法得到的值与y_test进行对比算scoring

# 这个步骤错误,因为线性回归得到的是概率值,需要后期判别到{0,1}上,才能和原y_test的数据进行比较算accuracy,所以LinearRegression不适合做cross_val_score的estimator。

print(accuracy_linear, score1)

#开始逻辑回归预测

alh = LogisticRegression()

score = cross_val_score(alh, X, titanic['Survived'], cv=3).mean()

#logisticregression的算法结果直接是{0,1}两值,所以可以直接进行score比较算accuracy,所以这个alh适合这个estimator。

print(score)

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值