线性回归算法实验(梯度下降法)
一、前期准备
数据的数量级如果相差太大是不适合梯度下降算法的。(需要进行处理,要把它们变成相同的数量级)
二、梯度下降法简介。
顾名思义,梯度下降法的计算过程就是沿梯度下降的方向求解极小值(也可以沿梯度上升方向求解极大值)。 其迭代公式为
a
k
+
1
=
a
k
+
ρ
k
−
(
k
)
a_{k+1}=a_{k}+ \rho_{k^{-(k)}}
a k + 1 = a k + ρ k − ( k ) ,其中 代表梯度负方向, 表示梯度方向上的搜索步长。梯度方向我们可以通过对函数求导得到,步长的确定比较麻烦,太大了的话可能会发散,太小收敛速度又太慢。一般确定步长的方法是由线性搜索算法来确定,即把下一个点的坐标看做是ak+1的函数,然后求满足f(ak+1)的最小值的ak+1即可。 因为一般情况下,梯度向量为0的话说明是到了一个极值点,此时梯度的幅值也为0.而采用梯度下降算法进行最优化求解时,算法迭代的终止条件是梯度向量的幅值接近0即可,可以设置个非常小的常数阈值。
三、完整代码
import numpy as np
import pandas as pd
from sklearn. datasets import load_boston
pd. set_option( 'display.max_rows' , 1000 )
pd. set_option( 'display.max_columns' , 1000 )
pd. set_option( 'display.width' , 1000 )
if __name__ == '__main__' :
boston = load_boston( )
data = pd. DataFrame( boston. data, columns= boston. feature_names)
data[ 'MEDV' ] = boston[ 'target' ]
data. to_csv( './boston.csv' , index= None )
class LinearRegression :
"""使用Python语言实现线性回归算法。(梯度下降)"""
def __init__ ( self, alpha, times) :
"""初始化方法。
:parameter
alpha:float
学习率。用来控制步长。(权重调整的幅度)
times :int
循环迭代的次数。
"""
self. alpha = alpha
self. times = times
def fit ( self, X, y) :
"""根据提供的训练数据X,对模型进行训练。
:parameter
X:类数组类型。形状:[样本数量,特征数量]
带训练的样本特征属性。(特征矩阵)
y:类数组类型,形状:[样本数量]
目标值(标签信息)。
"""
X = np. asarray( X)
y = np. asarray( y)
self. w_ = np. zeros( 1 + X. shape[ 1 ] )
self. loss_ = [ ]
for i in range ( self. times) :
y_hat = np. dot( X, self. w_[ 1 : ] ) + self. w_[ 0 ]
error = y- y_hat
self. loss_. append( np. sum ( error ** 2 ) / 2 )
self. w_[ 0 ] += self. alpha * np. sum ( error)
self. w_[ 1 : ] += self. alpha * np. dot( X. T, error)
def predict ( self, X) :
"""根据参数传递的样本,对样本数据进行预测。
:parameter
X:类数组类型,形状:[样本数量,特征数量]
待测试的样本。
:returns
result:数组类型。
预测的结果。
"""
X = np. asarray( X)
result = np. dot( X, self. w_[ 1 : ] ) + self. w_[ 0 ]
return result
lr = LinearRegression( alpha= 0.001 , times= 20 )
t = data. sample( len ( data) , random_state= 0 )
train_X = t. iloc[ : 400 , : - 1 ]
train_y = t. iloc[ : 400 , - 1 ]
test_X = t. iloc[ 400 : , : - 1 ]
test_y = t. iloc[ 400 : , - 1 ]
lr. fit( train_X, train_y)
result = lr. predict( test_X)
class StandardScaler :
"""该类对数据进行标准化处理。"""
def fit ( self, X) :
"""根据传递的样本,计算每个特征列的均值与标准差。
:parameter
X:类数组类型
训练数据,用来计算均值与标准差。
"""
X = np. asarray( X)
self. std_ = np. std( X, axis= 0 )
self. mean_ = np. mean( X, axis= 0 )
def transform ( self, X) :
"""对给定的数据X进行标准化处理。(将X的每一列都变成标准正态分布的数据)
:parameter
X: 类数组类型
待转换的数据。
:returns
result:类数组类型。
参数X转换成标准正态分布后的结果。
"""
return ( X- self. mean_) / self. std_
def fit_transform ( self, X) :
"""对数据进行训练,并转换,返回转换之后的结果。
:parameter
X:类数组类型
待转换的数据
:returns
result:类数组类型
参数X转换成标准正态分布后的结果。
"""
self. fit( X)
return self. transform( X)
lr = LinearRegression( alpha= 0.0005 , times= 20 )
t = data. sample( len ( data) , random_state= 0 )
train_X = t. iloc[ : 400 , : - 1 ]
train_y = t. iloc[ : 400 , - 1 ]
test_X = t. iloc[ 400 : , : - 1 ]
test_y = t. iloc[ 400 : , - 1 ]
s = StandardScaler( )
train_X = s. fit_transform( train_X)
test_X = s. fit_transform( test_X)
s2 = StandardScaler( )
train_y = s. fit_transform( train_y)
test_y = s. fit_transform( test_y)
lr. fit( train_X, train_y)
result = lr. predict( test_X)
print ( np. mean( ( result - test_y) ** 2 ) )