机器学习笔记(十一):优化梯度公式 | 凌云时刻

凌云时刻 · 技术

导读:这篇笔记主要介绍梯度下降法,梯度下降不是机器学习专属的算法,它是一种基于搜索的最优化方法,也就是通过不断的搜索然后找到损失函数的最小值。像上篇笔记中使用正规方程解实现多元线性回归,基于   这个模型我们可以推导出   的数学解,但是很多模型是推导不出数学解的,所以就需要梯度下降法来搜索出最优解。

作者 | 计缘

来源 | 凌云时刻(微信号:linuxpk)

优化梯度公式

我们先将之前推导出来的梯度公式写出来:

   

将展开来看:

   

将第一行的元素形式统一,每项都乘以   ,并且   恒等于1:

   

 

下面我们来两个矩阵,A为一个1行m列的矩阵,B为一个m行n列的矩阵:

   

   

在第二篇笔记中我们复习过矩阵的运算,让A矩阵点乘B矩阵会得到一个1行n列的新矩阵:

   

   

   

注意上面   A⋅B的矩阵是1行n列的矩阵,将其转置后就称为了n行1列的矩阵,正是之前展开的梯度   ∇L,所以我们的梯度公式可写为:

   

如此一来我们就可以修改一下之前封装的梯度的方法了:

 

# 定义梯度
		def dL(theta, X_b, y):
			# # 开辟空间,大小为theta向量的大小
			# gradient = np.empty(len(theta))
			# # 第0元素个特殊处理
			# gradient[0] = np.sum(X_b.dot(theta) - y)
			#
			# for i in range(1, len(theta)):
			#     # 矩阵求和可以转换为点乘
			#     gradient[i] = (X_b.dot(theta) - y).dot(X_b[:, i])

			return X_b.T.dot(X_b.dot(theta) - y) * 2 / len(X_b)

此时就可以用一行代码取代之前的for循环来实现梯度了。

用真实数据测试梯度下降法

我们用Scikit Learn提供的波士顿房价来测试一下梯度下降法:

 

import numpy as np
from sklearn import datasets
boston = datasets.load_boston()
X = boston.data
y = boston.target

X = X[y < 50.0]
y = y[y < 50.0]

# 取前10行数据观察一下
X[10:]
# 结果

Out[17]:
array([[  2.24890000e-01,   1.25000000e+01,   7.87000000e+00, ...,
		  1.52000000e+01,   3.92520000e+02,   2.04500000e+01],
	   [  1.17470000e-01,   1.25000000e+01,   7.87000000e+00, ...,
		  1.52000000e+01,   3.96900000e+02,   1.32700000e+01],
	   [  9.37800000e-02,   1.25000000e+01,   7.87000000e+00, ...,
		  1.52000000e+01,   3.90500000e+02,   1.57100000e+01],
	   ...,
	   [  6.07600000e-02,   0.00000000e+00,   1.19300000e+01, ...,
		  2.10000000e+01,   3.96900000e+02,   5.64000000e+00],
	   [  1.09590000e-01,   0.00000000e+00,   1.19300000e+01, ...,
		  2.10000000e+01,   3.93450000e+02,   6.48000000e+00],
	   [  4.74100000e-02,   0.00000000e+00,   1.19300000e+01, ...,
		  2.10000000e+01,   3.96900000e+02,   7.88000000e+00]])

从前10行的数据中可以看出来,数据之间的差距非常大,不同于正规方程法的   有数学解,在梯度下降中会非常影响梯度的值,既影响   的搜索,从而影响收敛速度和是否能收敛,所以一般在使用梯度下降法前,都需要对数据进行归一化处理,将数据转换到同一尺度下。在第三篇笔记中介绍过数据归一化的方法,Scikit Learn中也提供了数据归一化的方法,我们就使用Scikit Learn中提供的方法对波士顿数据进行归一化:

 

# 先将样本数据拆分为训练样本数据和测试样本数据
from myML.modelSelection import train_test_split
X_train, y_train, X_test, y_test = train_test_split(X, y, seed=123)

# 使用Scikit Learn提供的数据归一化方法处理训练数据
from sklearn.preprocessing import StandardScaler
standard_scalar = StandardScaler()
standard_scalar.fit(X_train)
X_train_standard = standard_scalar.transform(X_train)

# 再来看看归一化后的数据前10行,和未归一化之前的做一下比较
X_train_standard[10:]
# 结果
array([[-0.3854578 , -0.49494584, -0.70629402, ..., -0.5235474 ,
		 0.22529916, -1.09634897],
	   [ 8.34092707, -0.49494584,  1.03476103, ...,  0.80665081,
		 0.32122168,  1.38375621],
	   [-0.44033902,  1.83594326, -0.83504431, ..., -0.90360404,
		 0.45082029, -0.83197228],
	   ...,
	   [-0.39976896, -0.49494584,  1.58926511, ...,  1.28172161,
		 0.42018591,  0.2101475 ],
	   [-0.422702  , -0.49494584, -0.74140773, ...,  0.33158002,
		 0.4131248 , -0.41372555],
	   [-0.44280463,  3.05688517, -1.35589775, ..., -0.14349077,
		-0.1499176 , -0.02205637]])

 

可以看到数据都在同一个尺度内了,然后我们用优化后的梯度下降法来训练归一化后的样本数据:

 

from myML.LinearRegression import LinearRegression
lr = LinearRegression()
lr.fit_gd(X_train_standard, y_train)
lr.intercept_
# 结果
21.629336734693847

lr.coef_
# 结果
array([-0.9525182 ,  0.55252408, -0.30736822, -0.03926274, -1.37014814,
		2.61387294, -0.82461734, -2.36441751,  2.02340617, -2.17890468,
	   -1.76883751,  0.7438223 , -2.25694241])

# 在计算score前,需要对X_test数据也进行归一化处理
X_test_standard = standard_scalar.transform(X_test)
lr1.score(X_test_standard, y_test)
# 结果
0.80028998868733348

 

看到结果与我们之前使用正规方程法得到的结果是一致的。

  

 

END

往期精彩文章回顾

机器学习笔记(十):梯度下降

机器学习笔记(九):多元线性回归

机器学习笔记(八):线性回归算法的评测标准

机器学习笔记(七):线性回归

机器学习笔记(六):数据归一化

机器学习笔记(五):超参数

机器学习笔记(四):kNN算法

机器学习笔记(三):NumPy、Matplotlib、kNN算法

机器学习笔记(二):矩阵、环境搭建、NumPy

机器学习笔记(一):机器的学习定义、导数和最小二乘

长按扫描二维码关注凌云时刻

每日收获前沿技术与科技洞见

你可能感兴趣的:(机器学习笔记(十一):优化梯度公式 | 凌云时刻)