
一、線性回歸的概念
1.1、定義
線性回歸通過一個或者多個自變量與因變量之間之間進行建模的回歸分析。其中特點為一個或多個稱為回歸系數的模型參數的線性組合。
優點:
結果易於理解,計算不復雜。
缺點:
對非線性的數據擬合不好。
適用數據類型:
數值型和標稱型。
1.2、分類
一元線性回歸:
涉及到的變量只有一個。
多元線性回歸:
涉及到的變量兩個或兩個以上。
1.3、公式

其中𝑤,𝑥為矩陣:

二、線性回歸的實例
2.1、單變量實例
房子價格與房子面積

2.2、多變量實例
期末成績:0.7×考試成績+0.3×平時成績
西瓜好壞:0.2×色澤+0.5×根蒂+0.3×敲聲

三、損失函數
損失函數是一個貫穿整個機器學習重要的一個概念,大部分機器學習算法都會有誤差,我們得通過顯性的公式來描述這個誤差,並且將這個誤差優化到最小值。
3.1、損失原因
預測結果與真實值是有一定的誤差。

3.2、損失函數定義
損失函數代表了誤差的大小,用公式表示如下:

又稱最小二乘法。
對於線性回歸模型,將模型與數據點之間的距離差之和做為衡量匹配好壞的標准,誤差越小,匹配程度越大。我們要找的模型就是需要將f(x)和我們的真實值之間最相似的狀態。
損失函數由W決定,那么如何去求模型當中的W,使得損失最小?(目的是找到最小損失對應的W值)

3.3、減小損失函數的2種方式
方式一:最小二乘法之正規方程
求解:

𝑋為特征值矩陣,𝑦為目標值矩陣。

缺點:當特征過於復雜,求解速度太慢。
對於復雜的算法,不能使用正規方程求解(邏輯回歸等)
方式二:最小二乘法之梯度下降

𝛼為學習速率,需要手動指定,其中

表示方向
理解:沿着這個函數下降的方向找,最后就能找到山谷的最低點,然后
更新W值


3.4、兩種方式對比:

四、線性回歸API
4.1、普通最小二乘法線性回歸
sklearn.linear_model.LinearRegression()
coef_:回歸系數
from sklearn.linear_model import LinearRegression reg = LinearRegression() # 方法 reg.fit(X,y,sample_weight = None) #使用X作為訓練數據擬合模型,y作為X的類別值。X,y為數組或者矩陣 reg.predict([[X,y]]) # 預測提供的數據對應的結果 #屬性 reg.coef_ #表示回歸系數w=(w1,w2....)
4.2、通過使用SGD最小線性模型
sklearn.linear_model.SGDRegressor( )
coef_:回歸系數
4.3、帶有正則化的線性回歸
sklearn.linear_model.Ridge
具有l2正則化的線性最小二乘法
alpha:正則化力度
coef_:回歸系數
五、實現案例
波士頓房價數據分析流程:
5.1、數據獲取
from sklearn.datasets import load_boston from sklearn.linear_model import LinearRegression, SGDRegressor, Ridge, LogisticRegression from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler from sklearn.metrics import mean_squared_error, classification_report from sklearn.externals import joblib import pandas as pd import numpy as np # 獲取數據 lb = load_boston()
5.2、數據分割
# 分割數據集到訓練集和測試集
x_train, x_test, y_train, y_test = train_test_split(lb.data, lb.target, test_size=0.25)
5.3、訓練與測試數據標准化處理
# 特征值和目標值是都必須進行標准化處理, 實例化兩個標准化API
std_x = StandardScaler()
x_train = std_x.fit_transform(x_train)
x_test = std_x.transform(x_test)
# 目標值
std_y = StandardScaler()
y_train = std_y.fit_transform(y_train)
y_test = std_y.transform(y_test)
5.4、線性回歸模型和梯度下降估計對房價進行預測
# 正規方程求解方式預測結果
lr = LinearRegression()
lr.fit(x_train, y_train)
print(lr.coef_)
保存訓練好的模型
joblib.dump(lr, "test.pkl")
# 預測測試集的房子價格
y_lr_predict = std_y.inverse_transform(lr.predict(x_test))
print("正規方程測試集里面每個房子的預測價格:", y_lr_predict)
print("正規方程的均方誤差:", mean_squared_error(std_y.inverse_transform(y_test), y_lr_predict))
# 梯度下降進行房價預測
sgd = SGDRegressor()
sgd.fit(x_train, y_train)
print(sgd.coef_)
# 預測測試集的房子價格
y_sgd_predict = std_y.inverse_transform(sgd.predict(x_test))
print("梯度下降測試集里面每個房子的預測價格:", y_sgd_predict)
print("梯度下降的均方誤差:", mean_squared_error(std_y.inverse_transform(y_test), y_sgd_predict))
# 嶺回歸進行房價預測
rd = Ridge(alpha=1.0)
rd.fit(x_train, y_train)
print(rd.coef_)
# 預測測試集的房子價格
y_rd_predict = std_y.inverse_transform(rd.predict(x_test))
print("梯度下降測試集里面每個房子的預測價格:", y_rd_predict)
print("梯度下降的均方誤差:", mean_squared_error(std_y.inverse_transform(y_test), y_rd_predict))
六、回歸的性能評估
6.1、均方差誤差評估機制 (MSE):

注:𝑦^𝑖為預測值,¯𝑦為真實值。
6.2、回歸評估API:
sklearn.metrics.mean_squared_error
mean_squared_error(y_true, y_pred) 均方誤差回歸損失 y_true:真實值 y_pred:預測值 return:浮點數結果
注:真實值,預測值為標准化之前的值。
七、線性回歸的可能問題
訓練數據訓練的很好啊,誤差也不大,為什么在測試集上面有問題呢?機器學習可能存在過擬合和欠擬合的問題。如下圖:


7.1、過擬合
一個假設在訓練數據上能夠獲得比其他假設更好的擬合, 但是在訓練數據外的數據集上卻不能很好地擬合數據,此時認為這個假設出現了過擬合的現象。(模型過於復雜),如下圖:

產生原因:
原始特征過多,存在一些嘈雜特征, 模型過於復雜是因為模型嘗試去兼顧各個測試數據點。
解決辦法:
- 進行特征選擇,消除關聯性大的特征(很難做)
- 交叉驗證(建議使用)
- 正則化 (了解即可)
7.2、欠擬合
一個假設在訓練數據上不能獲得更好的擬合, 但是在訓練數據外的數據集上也不能很好地擬合數據,此時認為這個假設出現了欠擬合的現象。(模型過於簡單)。如下圖:

產生原因:
學習到數據的特征過少。
解決辦法:
增加數據的特征數量。
1、問題引入
在統計學中,線性回歸是利用稱為線性回歸方程的最小二乘函數對一個或多個自變量和因變量之間關系進行建模的一種回歸分析。這種函數是一個或多個稱為回歸系數的模型參數的線性組合。一個帶有一個自變量的線性回歸方程代表一條直線。我們需要對線性回歸結果進行統計分析。
例如,假設我們已知一些學生年紀和游戲時間的數據,可以建立一個回歸方程,輸入一個新的年紀時,預測該學生的游戲時間。自變量為學生年紀,因變量為游戲時間。當只有一個因變量時,我們稱該類問題為簡單線性回歸。當游戲時間與學生年紀和學生性別有關,因變量有多個時,我們稱該類問題為多元線性回歸。
2、常見的統計量
在研究該問題之前,首先了解下編程中用到的常見的統計量:
序號 |
概念 |
公式 |
算法 |
說明 |
1 |
均值 |
|
整體的均值 |
|
2 |
中位數 |
|
排序后取中間值 |
|
3 |
眾數 |
|
出現次數最多的數 |
出現頻率 |
4 |
方差 |
|
數據的離散程度 |
|
5 |
標准差 |
|
s |
方差的開方 |
2、簡單線性回歸實例及編程實現
研究一個自變量(X)和一個因變量(y)的關系
簡單線性回歸模型定義:
簡單線性回歸方程:
其中:
為回歸線的截距
為回歸線的斜率
通過訓練數據,求取出估計參數建立的直線方程:
實際編程時,主要是根據已知訓練數據,估計出和
的值
和
以下面實例為例,第一列表示每月投放廣告的次數,第二列表示汽車向量,通過Python編程求取線性回歸方程:
投放廣告數 |
汽車銷量 |
1 |
14 |
3 |
24 |
2 |
18 |
1 |
17 |
3 |
27 |
編程關鍵在於如何求取b0和b1的值,我們引入一個方程(sum of square):
當上述方程的值最小時,我們認為求取到線程回歸方程參數的值,對該方程求最小值可以進一步轉化為求導和求極值的問題,求導過程省略,最后結論如下:
實際代碼:
import numpy as np from matplotlib import pylab as pl # 定義訓練數據 x = np.array([1,3,2,1,3]) y = np.array([14,24,18,17,27]) # 回歸方程求取函數 def fit(x,y): if len(x) != len(y): return numerator = 0.0 denominator = 0.0 x_mean = np.mean(x) y_mean = np.mean(y) for i in range(len(x)): numerator += (x[i]-x_mean)*(y[i]-y_mean) denominator += np.square((x[i]-x_mean)) print('numerator:',numerator,'denominator:',denominator) b0 = numerator/denominator b1 = y_mean - b0*x_mean return b0,b1 # 定義預測函數 def predit(x,b0,b1): return b0*x + b1 # 求取回歸方程 b0,b1 = fit(x,y) print('Line is:y = %2.0fx + %2.0f'%(b0,b1)) # 預測 x_test = np.array([0.5,1.5,2.5,3,4]) y_test = np.zeros((1,len(x_test))) for i in range(len(x_test)): y_test[0][i] = predit(x_test[i],b0,b1) # 繪制圖像 xx = np.linspace(0, 5) yy = b0*xx + b1 pl.plot(xx,yy,'k-') pl.scatter(x,y,cmap=pl.cm.Paired) pl.scatter(x_test,y_test[0],cmap=pl.cm.Paired) pl.show()
執行結果:
C:\Anaconda3\python.exe "C:\Program Files\JetBrains\PyCharm 2019.1.1\helpers\pydev\pydevconsole.py" --mode=client --port=51452 import sys; print('Python %s on %s' % (sys.version, sys.platform)) sys.path.extend(['C:\\app\\PycharmProjects', 'C:/app/PycharmProjects']) Python 3.7.6 (default, Jan 8 2020, 20:23:39) [MSC v.1916 64 bit (AMD64)] Type 'copyright', 'credits' or 'license' for more information IPython 7.12.0 -- An enhanced Interactive Python. Type '?' for help. PyDev console: using IPython 7.12.0 Python 3.7.6 (default, Jan 8 2020, 20:23:39) [MSC v.1916 64 bit (AMD64)] on win32 runfile('C:/app/PycharmProjects/ArtificialIntelligence/test.py', wdir='C:/app/PycharmProjects/ArtificialIntelligence') numerator: 20.0 denominator: 4.0 Line is:y = 5x + 10
藍色表示測試數據,橙色表示預測數據。
3、多元線性回歸實例及編程實現
多元線性回歸方程和簡單線性回歸方程類似,不同的是由於因變量個數的增加,求取參數的個數也相應增加,推導和求取過程也不一樣。
y=β0+β1x1+β2x2+ ... +βpxp+ε
對於b0、b1、…、bn的推導和求取過程,引用一個第三方庫進行計算。以如下數據為例,對運輸里程、運輸次數與運輸總時間的關系,建立多元線性回歸模型:
運輸里程 |
運輸次數 |
運輸總時間 |
100 |
4 |
9.3 |
50 |
3 |
4.8 |
100 |
4 |
8.9 |
100 |
2 |
6.5 |
50 |
2 |
4.2 |
80 |
2 |
6.2 |
75 |
3 |
7.4 |
65 |
4 |
6.0 |
90 |
3 |
7.6 |
90 |
2 |
6.1 |
代碼如下:
import numpy as np from sklearn import datasets,linear_model # 定義訓練數據 x = np.array([[100,4,9.3],[50,3,4.8],[100,4,8.9], [100,2,6.5],[50,2,4.2],[80,2,6.2], [75,3,7.4],[65,4,6],[90,3,7.6],[90,2,6.1]]) print(x) X = x[:,:-1] Y = x[:,-1] print(X,Y) # 訓練數據 regr = linear_model.LinearRegression() regr.fit(X,Y) print('coefficients(b1,b2...):',regr.coef_) print('intercept(b0):',regr.intercept_) # 預測 x_test = np.array([[102,6],[100,4]]) y_test = regr.predict(x_test) print(y_test)
執行結果:
C:\Anaconda3\python.exe "C:\Program Files\JetBrains\PyCharm 2019.1.1\helpers\pydev\pydevconsole.py" --mode=client --port=51529 import sys; print('Python %s on %s' % (sys.version, sys.platform)) sys.path.extend(['C:\\app\\PycharmProjects', 'C:/app/PycharmProjects']) Python 3.7.6 (default, Jan 8 2020, 20:23:39) [MSC v.1916 64 bit (AMD64)] Type 'copyright', 'credits' or 'license' for more information IPython 7.12.0 -- An enhanced Interactive Python. Type '?' for help. PyDev console: using IPython 7.12.0 Python 3.7.6 (default, Jan 8 2020, 20:23:39) [MSC v.1916 64 bit (AMD64)] on win32 runfile('C:/app/PycharmProjects/ArtificialIntelligence/test.py', wdir='C:/app/PycharmProjects/ArtificialIntelligence') [[100. 4. 9.3] [ 50. 3. 4.8] [100. 4. 8.9] [100. 2. 6.5] [ 50. 2. 4.2] [ 80. 2. 6.2] [ 75. 3. 7.4] [ 65. 4. 6. ] [ 90. 3. 7.6] [ 90. 2. 6.1]] [[100. 4.] [ 50. 3.] [100. 4.] [100. 2.] [ 50. 2.] [ 80. 2.] [ 75. 3.] [ 65. 4.] [ 90. 3.] [ 90. 2.]] [9.3 4.8 8.9 6.5 4.2 6.2 7.4 6. 7.6 6.1] coefficients(b1,b2...): [0.0611346 0.92342537] intercept(b0): -0.868701466781709 [10.90757981 8.93845988]
如果特征向量中存在分類型變量,例如車型,我們需要進行特殊處理:
運輸里程 |
輸出次數 |
車型 |
隱式轉換 |
運輸總時間 |
100 |
4 |
1 |
010 |
9.3 |
50 |
3 |
0 |
100 |
4.8 |
100 |
4 |
1 |
010 |
8.9 |
100 |
2 |
2 |
001 |
6.5 |
50 |
2 |
2 |
001 |
4.2 |
80 |
2 |
1 |
010 |
6.2 |
75 |
3 |
1 |
010 |
7.4 |
65 |
4 |
0 |
100 |
6.0 |
90 |
3 |
0 |
100 |
7.6 |
100 |
4 |
1 |
010 |
9.3 |
50 |
3 |
0 |
100 |
4.8 |
100 |
4 |
1 |
010 |
8.9 |
100 |
2 |
2 |
001 |
6.5
|
代碼實現:
import numpy as np from sklearn.feature_extraction import DictVectorizer from sklearn import linear_model # 定義數據集 x = np.array([[100,4,1,9.3],[50,3,0,4.8],[100,4,1,8.9], [100,2,2,6.5],[50,2,2,4.2],[80,2,1,6.2], [75,3,1,7.4],[65,4,0,6],[90,3,0,7.6], [100,4,1,9.3],[50,3,0,4.8],[100,4,1,8.9],[100,2,2,6.5]]) x_trans = [] for i in range(len(x)): x_trans.append({'x1':str(x[i][2])}) vec = DictVectorizer() dummyX = vec.fit_transform(x_trans).toarray() x = np.concatenate((x[:,:-2],dummyX[:,:],x[:,-1].reshape(len(x),1)),axis=1) x = x.astype(float) X = x[:,:-1] Y = x[:,-1] print(x,X,Y) # 訓練數據 regr = linear_model.LinearRegression() regr.fit(X,Y) print('coefficients(b1,b2...):',regr.coef_) print('intercept(b0):',regr.intercept_)
執行結果:
C:\Anaconda3\python.exe "C:\Program Files\JetBrains\PyCharm 2019.1.1\helpers\pydev\pydevconsole.py" --mode=client --port=51576 import sys; print('Python %s on %s' % (sys.version, sys.platform)) sys.path.extend(['C:\\app\\PycharmProjects', 'C:/app/PycharmProjects']) Python 3.7.6 (default, Jan 8 2020, 20:23:39) [MSC v.1916 64 bit (AMD64)] Type 'copyright', 'credits' or 'license' for more information IPython 7.12.0 -- An enhanced Interactive Python. Type '?' for help. PyDev console: using IPython 7.12.0 Python 3.7.6 (default, Jan 8 2020, 20:23:39) [MSC v.1916 64 bit (AMD64)] on win32 runfile('C:/app/PycharmProjects/ArtificialIntelligence/test.py', wdir='C:/app/PycharmProjects/ArtificialIntelligence') [[100. 4. 0. 1. 0. 9.3] [ 50. 3. 1. 0. 0. 4.8] [100. 4. 0. 1. 0. 8.9] [100. 2. 0. 0. 1. 6.5] [ 50. 2. 0. 0. 1. 4.2] [ 80. 2. 0. 1. 0. 6.2] [ 75. 3. 0. 1. 0. 7.4] [ 65. 4. 1. 0. 0. 6. ] [ 90. 3. 1. 0. 0. 7.6] [100. 4. 0. 1. 0. 9.3] [ 50. 3. 1. 0. 0. 4.8] [100. 4. 0. 1. 0. 8.9] [100. 2. 0. 0. 1. 6.5]] [[100. 4. 0. 1. 0.] [ 50. 3. 1. 0. 0.] [100. 4. 0. 1. 0.] [100. 2. 0. 0. 1.] [ 50. 2. 0. 0. 1.] [ 80. 2. 0. 1. 0.] [ 75. 3. 0. 1. 0.] [ 65. 4. 1. 0. 0.] [ 90. 3. 1. 0. 0.] [100. 4. 0. 1. 0.] [ 50. 3. 1. 0. 0.] [100. 4. 0. 1. 0.] [100. 2. 0. 0. 1.]] [9.3 4.8 8.9 6.5 4.2 6.2 7.4 6. 7.6 9.3 4.8 8.9 6.5] coefficients(b1,b2...): [ 0.05452507 0.70930079 -0.18019642 0.60821607 -0.42801964] intercept(b0): 0.1989958956317821