https://blog.csdn.net/hzw19920329/article/details/77200475
線性迴歸作爲一種迴歸分析技術,其分析的因變量屬於連續型變量,如果因變量轉變爲離散型變量,將轉換爲分類問題。迴歸分析屬於有監督學習問題,本博客將重點回顧標準線性迴歸知識點,並就線性迴歸中可能出現的問題進行簡單探討,引出線性迴歸的兩個變種嶺迴歸以及Lasso迴歸,最後通過sklearn庫模擬整個迴歸過程。
目錄結構
- 線性迴歸的一般形式
- 線性迴歸中可能遇到的問題
- 過擬合問題及其解決方法
- 線性迴歸代碼實現
- 嶺迴歸與Lasso迴歸
- 嶺迴歸以及Lasso迴歸代碼實現
- 線性迴歸的一般形式
線性迴歸中可能遇到的問題
求解損失函數的最小值有兩種方法:梯度下降法以及正規方程,兩者的對比在附加筆記中有列出。
特徵縮放:即對特徵數據進行歸一化操作,進行特徵縮放的好處有兩點,一是能夠提升模型的收斂速度,因爲如果特徵間的數據相差級別較大的話,以兩個特徵爲例,以這兩個特徵爲橫縱座標繪製等高線圖,繪製出來是扁平狀的橢圓,這時候通過梯度下降法尋找梯度方向最終將走垂直於等高線的之字形路線,迭代速度變慢。但是如果對特徵進行歸一化操作之後,整個等高線圖將呈現圓形,梯度的方向是指向圓心的,迭代速度遠遠大於前者。二是能夠提升模型精度。
學習率α的選取:如果學習率α選取過小,會導致迭代次數變多,收斂速度變慢;學習率α選取過大,有可能會跳過最優解,最終導致根本無法收斂。
過擬合問題及其解決方法
問題:以下面一張圖片展示過擬合問題
解決方法:(1):丟棄一些對我們最終預測結果影響不大的特徵,具體哪些特徵需要丟棄可以通過PCA算法來實現;(2):使用正則化技術,保留所有特徵,但是減少特徵前面的參數θ的大小,具體就是修改線性迴歸中的損失函數形式即可,嶺迴歸以及Lasso迴歸就是這麼做的。
線性迴歸代碼示例
import matplotlib.pyplot as plt
import numpy as np
from sklearn import datasets, linear_model, discriminant_analysis, cross_validation
def load_data():
diabetes = datasets.load_diabetes()
return cross_validation.train_test_split(diabetes.data, diabetes.target, test_size=0.25, random_state=0)
def test_LinearRegression(*data):
X_train, X_test, y_train, y_test = data
#通過sklearn的linear_model創建線性迴歸對象
linearRegression = linear_model.LinearRegression()
#進行訓練
linearRegression.fit(X_train, y_train)
#通過LinearRegression的coef_屬性獲得權重向量,intercept_獲得b的值
print("權重向量:%s, b的值爲:%.2f" % (linearRegression.coef_, linearRegression.intercept_))
#計算出損失函數的值
print("損失函數的值: %.2f" % np.mean((linearRegression.predict(X_test) - y_test) ** 2))
#計算預測性能得分
print("預測性能得分: %.2f" % linearRegression.score(X_test, y_test))
if __name__ == '__main__':
#獲得數據集
X_train, X_test, y_train, y_test = load_data()
#進行訓練並且輸出預測結果
test_LinearRegression(X_train, X_test, y_train, y_test)
線性迴歸示例輸出
權重向量:[ -43.26774487 -208.67053951 593.39797213 302.89814903 -560.27689824
261.47657106 -8.83343952 135.93715156 703.22658427 28.34844354], b的值爲:153.07
損失函數的值: 3180.20
預測性能得分: 0.36
嶺迴歸與Lasso迴歸
嶺迴歸與Lasso迴歸的出現是爲了解決線性迴歸出現的過擬合以及在通過正規方程方法求解θ的過程中出現的x轉置乘以x不可逆這兩類問題的,這兩種迴歸均通過在損失函數中引入正則化項來達到目的,具體三者的損失函數對比見下圖:
其中λ稱爲正則化參數,如果λ選取過大,會把所有參數θ均最小化,造成欠擬合,如果λ選取過小,會導致對過擬合問題解決不當,因此λ的選取是一個技術活。
嶺迴歸與Lasso迴歸最大的區別在於嶺迴歸引入的是L2範數懲罰項,Lasso迴歸引入的是L1範數懲罰項,Lasso迴歸能夠使得損失函數中的許多θ均變成0,這點要優於嶺迴歸,因爲嶺迴歸是要所有的θ均存在的,這樣計算量Lasso迴歸將遠遠小於嶺迴歸。
可以看到,Lasso迴歸最終會趨於一條直線,原因就在於好多θ值已經均爲0,而嶺迴歸卻有一定平滑度,因爲所有的θ值均存在。
嶺迴歸以及Lasso迴歸代碼實現
嶺迴歸代碼示例
import matplotlib.pyplot as plt
import numpy as np
from sklearn import datasets, linear_model, discriminant_analysis, cross_validation
def load_data():
diabetes = datasets.load_diabetes()
return cross_validation.train_test_split(diabetes.data, diabetes.target, test_size=0.25, random_state=0)
def test_ridge(*data):
X_train, X_test, y_train, y_test = data
ridgeRegression = linear_model.Ridge()
ridgeRegression.fit(X_train, y_train)
print("權重向量:%s, b的值爲:%.2f" % (ridgeRegression.coef_, ridgeRegression.intercept_))
print("損失函數的值:%.2f" % np.mean((ridgeRegression.predict(X_test) - y_test) ** 2))
print("預測性能得分: %.2f" % ridgeRegression.score(X_test, y_test))
#測試不同的α值對預測性能的影響
def test_ridge_alpha(*data):
X_train, X_test, y_train, y_test = data
alphas = [0.01, 0.02, 0.05, 0.1, 0.2, 0.5, 1, 2, 5, 10, 20, 50, 100, 200, 500, 1000]
scores = []
for i, alpha in enumerate(alphas):
ridgeRegression = linear_model.Ridge(alpha=alpha)
ridgeRegression.fit(X_train, y_train)
scores.append(ridgeRegression.score(X_test, y_test))
return alphas, scores
def show_plot(alphas, scores):
figure = plt.figure()
ax = figure.add_subplot(1, 1, 1)
ax.plot(alphas, scores)
ax.set_xlabel(r"$\alpha$")
ax.set_ylabel(r"score")
ax.set_xscale("log")
ax.set_title("Ridge")
plt.show()
if __name__ == '__main__':
#使用默認的alpha
#獲得數據集
#X_train, X_test, y_train, y_test = load_data()
#進行訓練並且預測結果
#test_ridge(X_train, X_test, y_train, y_test)
#使用自己設置的alpha
X_train, X_test, y_train, y_test = load_data()
alphas, scores = test_ridge_alpha(X_train, X_test, y_train, y_test)
show_plot(alphas, scores)
Lasso迴歸代碼示例
import matplotlib.pyplot as plt
import numpy as np
from sklearn import datasets, linear_model, discriminant_analysis, cross_validation
def load_data():
diabetes = datasets.load_diabetes()
return cross_validation.train_test_split(diabetes.data, diabetes.target, test_size=0.25, random_state=0)
def test_lasso(*data):
X_train, X_test, y_train, y_test = data
lassoRegression = linear_model.Lasso()
lassoRegression.fit(X_train, y_train)
print("權重向量:%s, b的值爲:%.2f" % (lassoRegression.coef_, lassoRegression.intercept_))
print("損失函數的值:%.2f" % np.mean((lassoRegression.predict(X_test) - y_test) ** 2))
print("預測性能得分: %.2f" % lassoRegression.score(X_test, y_test))
#測試不同的α值對預測性能的影響
def test_lasso_alpha(*data):
X_train, X_test, y_train, y_test = data
alphas = [0.01, 0.02, 0.05, 0.1, 0.2, 0.5, 1, 2, 5, 10, 20, 50, 100, 200, 500, 1000]
scores = []
for i, alpha in enumerate(alphas):
lassoRegression = linear_model.Lasso(alpha=alpha)
lassoRegression.fit(X_train, y_train)
scores.append(lassoRegression.score(X_test, y_test))
return alphas, scores
def show_plot(alphas, scores):
figure = plt.figure()
ax = figure.add_subplot(1, 1, 1)
ax.plot(alphas, scores)
ax.set_xlabel(r"$\alpha$")
ax.set_ylabel(r"score")
ax.set_xscale("log")
ax.set_title("Ridge")
plt.show()
if __name__=='__main__':
X_train, X_test, y_train, y_test = load_data()
# 使用默認的alpha
#test_lasso(X_train, X_test, y_train, y_test)
# 使用自己設置的alpha
alphas, scores = test_lasso_alpha(X_train, X_test, y_train, y_test)
show_plot(alphas, scores)
參考文獻
python大戰機器學習
Andrew Ng機器學習公開課
http://www.jianshu.com/p/35e67c9e4cbf
http://freemind.pluskid.org/machine-learning/sparsity-and-some-basics-of-l1-regularization/#ed61992b37932e208ae114be75e42a3e6dc34cb3