一、線性回歸(Linear Regression)介紹
線性回歸是利用數理統計中回歸分析,來確定兩種或兩種以上變量間相互依賴的定量關系的一種統計分析方法,運用十分廣泛。其表達形式為y = w'x +e,e為誤差服從均值為0的正態分布。線性回歸是經濟學的主要實證工具。例如,它是用來預測消費支出,固定投資支出,存貨投資,一國出口產品的購買,進口支出,要求持有流動性資產,勞動力需求、勞動力供給。
二、算法步驟
1)預測房價的線性方程,其中theta(i)表示的是第i個特征x(i)的權重,h(x)是根據特征和相應的權重所預測的房價。

2)損失函數是用來評估線性函數好壞,損失函數J是對每個樣本的估計值與真實值的平方進行求和,得到整個樣本預測的值跟真實值之間的差距和損失。

3)使用梯度下降尋找最優的線性方程轉換為求解損失函數的最小值,也就是求解得到J取得最小值的時候的權重向量,權重的更新規則如下所示:

4)不斷迭代,得到J取得較小值的權重向量。
三、數據集介紹
波士頓房價數據集,其實例數量是506個,實例包括了屬性和房價,幫助預測的屬性數量是13個,屬性包含是CRIM 城鎮人均犯罪率,ZN 占地面積超過2.5萬平方英尺的住宅用地比例等等。訓練集選取70%的數據集,測試集選取30%的數據集,訓練集和測試集中都包括數據的特征屬性和真實房價。
四、代碼實現和結果展示
為了標准化數據特征的范圍和加快收斂速度,在線性回歸算法中采用了特征縮放的方法,特征縮放的方法包括調節比例(Rescaling)和標准化方法(Standardization)。Iteration(迭代次數)是1000,learning rate(學習率)是0.0001,權重剛開始初始化為零向量,正則化的懲罰因子是10。
特征所放的思路參考鏈接:https://blog.csdn.net/xlinsist/article/details/51212348;這兩種方法分別對應代碼函數:Rescaling()和Standardization().

#任務:將訓練集和測試和預測的J_theta分別展示在圖上
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
from sklearn import datasets
def loadDataSet():
boston=datasets.load_boston()
data=boston.data
label=boston.target
dataNum=data.shape[0]
print(dataNum)
testRatio=0.3
testNum=int(dataNum*testRatio)#因為乘出來有可能不是整數
trainNum=dataNum-testNum
train_x=data[0:trainNum,:]#train_data
test_x=data[trainNum:,:]#test_data
train_y=label[0:trainNum]#train_label
test_y=label[trainNum:]
return train_x,train_y,test_x,test_y
# def train_model(train_x,train_y,theta,iteration,learning_rate,my_lambda):#my_lambda是正則化參數
def train_model(train_x, train_y, theta, iteration, learning_rate):
m=train_x.shape[0]
n=train_x.shape[1]
print(m)
print(n)
J_theta=np.zeros((iteration,1))#先初始化一個J(theta)列向量,cost function
train_x=np.insert(train_x,0,values=1,axis=1)#train_x是n*n的矩陣,需要增加一個x0特征(x0=1),即增加一個列向量(放在第一列)
for i in range(iteration):
#這里是否要用到temp來暫時存儲theta,用不到
J_theta[i] = sum((train_y[:, np.newaxis] - np.dot(train_x, theta)) ** 2) / 2.0#dot是內積,sum函數是將減掉后的列向量求和成一個數
theta=theta+learning_rate*(np.dot(train_x.T,train_y[:, np.newaxis] - np.dot(train_x, theta)))
#上面代碼的優化(正則化)
# J_theta[i] = (sum((train_y[:, np.newaxis] - np.dot(train_x, theta)) ** 2) +my_lambda*(np.dot(theta.T,theta)-theta[0]**2))/(2.0*m)
#正則化
# theta=theta*(1-learning_rate*my_lambda/m)-learning_rate/m*np.dot(train_x.T,(np.dot(train_x, theta)-train_y[:, np.newaxis] ))
# theta[0]=theta[0]-learning_rate/m*np.dot(train_x[:,0].T,(train_y[:, np.newaxis] - np.dot(train_x, theta)))
# x_iteration=np.linspace(0,iteration,num=iteration)
# plt.plot(x_iteration,J_theta)
# plt.show()
return theta,J_theta
#特征縮放(feature scaling)的問題,標准化方法
def Standardization(x):
m=x.shape[0]
n=x.shape[1]
x_average=np.zeros((1,n))
sigma=np.zeros((1,n))
x_result=np.zeros((m,n))
x_average=x.mean(axis=0)#用np的mean函數來求每一列的平均值
# x_average=sum(x)/m
# sigma=(sum((x-x_average)**2)/m)**0.5
sigma=x.var(axis=0)#用np的var函數來求每一列的方差
x_result=(x-x_average)/sigma
return x_result
#特征縮放中的調節比例方法
def Rescaling(x):
m=x.shape[0]
n=x.shape[1]
x_min=np.zeros((1,n))
x_max=np.zeros((1,n))
x_result=np.zeros((m,n))
x_min=x.min(axis=0)#獲得每個列的最小值
x_max=x.max(axis=0)#獲得每個列的最大值
x_result=(x-x_min)/(x_max-x_min)
return x_result
def predict(test_x,test_y,theta,iteration,my_lambda):#用學習模型學習得來的最好參數,theta是(n+1)*1的矩陣
test_x=np.insert(test_x,0,values=1,axis=1)
m=test_x.shape[0]
h_theta=np.dot(test_x,theta) # np.dot(test_x,theta)是m*1的矩陣
J_theta=np.zeros((iteration,1))#先初始化一個J(theta)列向量,cost function
J_theta = (sum((test_y[:, np.newaxis] - np.dot(test_x, theta)) ** 2) )/ 2.0
#正則化
# J_theta = (sum((test_y[:, np.newaxis] - np.dot(test_x, theta)) ** 2) + my_lambda * (np.dot(theta.T, theta) - theta[0] ** 2)) / (2.0 * m)
rootMeanSquaredError=(sum((h_theta-test_y[:, np.newaxis])**2)/m)**0.5
print("rootMeanSquaredError",rootMeanSquaredError)
return h_theta,J_theta
if __name__=='__main__':
train_x, train_y, test_x, test_y=loadDataSet()
train_x = Standardization(train_x)
test_x=Standardization(test_x)
# train_x =Rescaling(train_x)
# test_x = Rescaling(test_x)
n=test_x.shape[1]+1
theta=np.zeros((n,1))#theta是n+1 * 1的列向量
iteration = 1000
# my_lambda = 0.0001
# my_lambda = 0
my_lambda = 10
learning_rate = 0.0001
# theta,J_train=train_model(train_x, train_y,theta, iteration, learning_rate,my_lambda)#正則化
theta, J_train = train_model(train_x, train_y, theta, iteration, learning_rate) # 正則化
h_theta,J_test=predict(test_x, test_y, theta,iteration,my_lambda)
# x_iteration=np.linspace(0,iteration,num=iteration)
結果展示:
注:RootMeanSquareError是均方根誤差,是一種常用的測量數值之間差異的量度。
表1 線性回歸預測房價結果
| 正則化和特征縮放 |
Standardization |
Rescaling |
||
| 正則化 |
不正則化 |
正則化 |
不正則化 |
|
| RootMeanSquareError |
18.22 |
無窮大 |
13.18 |
10.88 |
表1說明,在特征縮放的標准化方法中,正則化的均方根誤差比不正則化的誤差小得多;在特征縮放的調節比例方法中,不正則化的均方根誤差比正則化后的小;在同時正則化或者不正則化的情況下,調節比例方法的均方根誤差相對來說比標准化方法要小。
