一、引言
之前的几篇博文我们学习了线性回归、梯度下降的基础思想与操作方法,但也只限于纸上谈兵。机器学习是一门更看重应用与问题解决的学科,因此动手实操尤为重要。 本篇博文我们会详细叙述线性回归与梯度下降初步用python语言实现的过程,为日后研究学习大型项目打下基础。本次实验的目的是复习掌握线性回归与梯度下降的思想,并且熟悉使用python语言实现机器学习。
二、简单模拟线性回归
首先生成x列向量,设定好真实线性函数方程ytrue。由于我们没有相关的离散训练数据集,因此我们使用一定方法去制作一个训练集。我们通过ytrue+noise来产生所有的训练数据集,并用此数据集来训练线性模型。 我们使用sklearn中内置的线性回归相关函数,生成一个线性回归对象,再由该对象训练数据集得到训练后的模型。我们最后通过在图中画出训练集中所有散点与训练得到的线性函数来评估拟合程度。 具体python代码如下:
import numpy as np
from sklearn import linear_model
import matplotlib. pyplot as plt
reg = linear_model. LinearRegression( )
x = np. arange( - 3 , 5 , step= 1 )
x = x. reshape( - 1 , 1 )
ytrue = 2 * x - 1
noise = np. random. normal( 0 , 0.2 , len ( x) ) . reshape( - 1 , 1 )
y = ytrue + noise
lmodel = reg. fit( x, y)
coef = lmodel. coef_
intercept = lmodel. intercept_
R2 = lmodel. score( x, y)
ytrain = coef * x + intercept
plt. plot( x, y, 'b+' )
plt. plot( x, ytrain)
plt. xlabel( 'x' )
plt. ylabel( 'y' )
plt. show( )
最后得出的图像为: 不需要分析,得出的图像一定十分拟合。因为我们这次实验只是一次模拟而已,训练数据集是我们根据真实函数加入一定偏差得到的并不具有分散的代表性。
三、简单梯度下降实现
import numpy as np
from sklearn import linear_model
import matplotlib. pyplot as plt
reg = linear_model. LinearRegression( )
x = np. array( [ 1 , 3 , 5 ] ) . reshape( - 1 , 1 )
ytrue = 3 * x - 1
noise = np. array( [ 1 , - 2 , 2 ] ) . reshape( - 1 , 1 )
y = ytrue + noise
plt. plot( x, y, 'b+' )
lmodel = reg. fit( x, y)
coef = lmodel. coef_
intercept = lmodel. intercept_
R2 = lmodel. score( x, y)
ytrain1 = coef * x + intercept
plt. plot( x, ytrain1)
plt. plot( x, y, 'b+' )
def cal_minus_gradient ( a, b) :
gradient_a = 70 * a + 18 * b - 202
gradient_b = 18 * a + 6 * b - 50
return ( [ - gradient_a, - gradient_b] )
大家可能会对以上函数中梯度计算的公式感到疑惑,其实本次实验也只是简单模拟梯度下降。仅仅设计了三个散点作为训练数据集,根据损失函数LOSS我们可以直接表示出梯度的计算公式,推导过程如下:
alpha = 0.01
a = 100
b = - 11
epslon = 0.00001
diff = 1
model = np. array( [ [ a, b] ] )
while diff > epslon:
G = cal_minus_gradient( a, b)
a = a + alpha * G[ 0 ]
b = b + alpha * G[ 1 ]
model = np. concatenate( ( model, np. array( [ [ a, b] ] ) ) , axis= 0 )
diffvec = np. array( [ alpha * G[ 0 ] , alpha * G[ 1 ] ] )
diff = np. linalg. norm( diffvec)
ypred = x * a + b
fig, axs = plt. subplots( 2 )
axs[ 0 ] . plot( model)
axs[ 1 ] . plot( x, ypred, 'red' )
axs[ 1 ] . plot( x, y, 'bo' )
error = ypred - y
SST = sum ( ( y - y. mean( ) ) ** 2 )
SSR = sum ( error ** 2 )
R2 = 1 - SSR / SST
print ( R2)