本文將用一個例子來說述怎麼用scikit-learn和pandas來學習Ridge迴歸。html
在個人另一遍講線性迴歸的文章中,對Ridge迴歸作了一些介紹,以及何時適合用 Ridge迴歸。若是對什麼是Ridge迴歸還徹底不清楚的建議閱讀我這篇文章。python
線性迴歸原理小結git
Ridge迴歸的損失函數表達形式是: github
\(J(\mathbf\theta) = \frac{1}{2}(\mathbf{X\theta} - \mathbf{Y})^T(\mathbf{X\theta} - \mathbf{Y}) + \frac{1}{2}\alpha||\theta||_2^2\)算法
其中\(\alpha\)爲常數係數,須要進行調優。\(||\theta||_2\)爲L2範數。shell
算法須要解決的就是在找到一個合適的超參數\(\alpha\)狀況下,求出使\(J(\mathbf\theta)\)最小的\(\theta\)。通常能夠用梯度降低法和最小二乘法來解決這個問題。scikit-learn用的是最小二乘法。app
這裏咱們仍然用UCI大學公開的機器學習數據來跑Ridge迴歸。dom
數據的介紹在這: http://archive.ics.uci.edu/ml/datasets/Combined+Cycle+Power+Plant機器學習
數據的下載地址在這: http://archive.ics.uci.edu/ml/machine-learning-databases/00294/函數
完整的代碼見個人github: https://github.com/ljpzzz/machinelearning/blob/master/classic-machine-learning/ridge_regression_1.ipynb
裏面是一個循環發電場的數據,共有9568個樣本數據,每一個數據有5列,分別是:AT(溫度), V(壓力), AP(溼度), RH(壓強), PE(輸出電力)。咱們不用糾結於每項具體的意思。
咱們的問題是獲得一個線性的關係,對應PE是樣本輸出,而AT/V/AP/RH這4個是樣本特徵, 機器學習的目的就是經過調節超參數\(\alpha\)獲得一個線性迴歸模型,即:
\(PE = \theta_0 + \theta_1*AT + \theta_2*V + \theta_3*AP + \theta_4*RH\)
使損失函數\(J(\mathbf\theta)\)最小。而須要學習的,就是\(\theta_0, \theta_1, \theta_2, \theta_3, \theta_4\)這5個參數。
下載後的數據能夠發現是一個壓縮文件,解壓後能夠看到裏面有一個xlsx文件,咱們先用excel把它打開,接着「另存爲「」csv格式,保存下來,後面咱們就用這個csv來運行Ridge迴歸。
這組數據並不必定適合用Ridge迴歸模型,實際上這組數據是高度線性的,使用正則化的Ridge迴歸僅僅只是爲了講解方便。
咱們先打開ipython notebook,新建一個notebook。固然也能夠直接在python的交互式命令行裏面輸入,不過仍是推薦用notebook。下面的例子和輸出我都是在notebook裏面跑的。
先把要導入的庫聲明瞭:
import matplotlib.pyplot as plt %matplotlib inline import numpy as np import pandas as pd from sklearn import datasets, linear_model
接着用pandas讀取數據:
# read_csv裏面的參數是csv在你電腦上的路徑,此處csv文件放在notebook運行目錄下面的CCPP目錄裏 data = pd.read_csv('.\CCPP\ccpp.csv')
咱們用AT, V,AP和RH這4個列做爲樣本特徵。用PE做爲樣本輸出:
X = data[['AT', 'V', 'AP', 'RH']] y = data[['PE']]
接着把數據集劃分爲訓練集和測試集:
from sklearn.cross_validation import train_test_split X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=1)
要運行Ridge迴歸,咱們必需要指定超參數\(\alpha\)。你也許會問:「我也不知道超參數是多少啊?」 我也不知道,那麼咱們隨機指定一個(好比1),後面咱們會講到用交叉驗證從多個輸入超參數\(\alpha\)中快速選擇最優超參數的辦法。
from sklearn.linear_model import Ridge ridge = Ridge(alpha=1) ridge.fit(X_train, y_train)
訓練完了,能夠看看模型參數是多少:
print ridge.coef_ print ridge.intercept_
輸出結果以下:
也就是說咱們獲得的模型是:
\(PE = 447.05552892 - 1.97373209*AT - 0.2323016*V + 0.06935852*AP - 0.15806479*RH\)
可是這樣尚未完?爲何呢,由於咱們假設了超參數\(\alpha\)爲1, 實際上咱們並不知道超參數\(\alpha\)取多少最好,實際研究是須要在多組自選的\(\alpha\)中選擇一個最優的。
那麼咱們是否是要把上面這段程序在N種\(\alpha\)的值狀況下,跑N遍,而後再比較結果的優劣程度呢? 能夠這麼作,可是scikit-learn提供了另一個交叉驗證選擇最優\(\alpha\)的API,下面咱們就用這個API來選擇\(\alpha\)。
這裏咱們假設咱們想在這10個\(\alpha\)值中選擇一個最優的值。代碼以下:
from sklearn.linear_model import RidgeCV ridgecv = RidgeCV(alphas=[0.01, 0.1, 0.5, 1, 3, 5, 7, 10, 20, 100]) ridgecv.fit(X_train, y_train) ridgecv.alpha_
輸出結果爲:7.0,說明在咱們給定的這組超參數中, 7是最優的\(\alpha\)值。
經過Ridge迴歸的損失函數表達式能夠看到,\(\alpha\)越大,那麼正則項懲罰的就越厲害,獲得迴歸係數\(\theta\)就越小,最終趨近與0。而若是\(\alpha\)越小,即正則化項越小,那麼迴歸係數\(\theta\)就愈來愈接近於普通的線性迴歸係數。
這裏咱們用scikit-learn來研究這種Ridge迴歸的變化,例子參考了scikit-learn的官網例子。咱們單獨啓動一個notebook或者python shell來運行這個例子。
完整的代碼見個人github: https://github.com/ljpzzz/machinelearning/blob/master/classic-machine-learning/ridge_regression.ipynb
首先仍是加載類庫:
import numpy as np import matplotlib.pyplot as plt from sklearn import linear_model %matplotlib inline
接着咱們本身生成一個10x10的矩陣X,表示一組有10個樣本,每一個樣本有10個特徵的數據。生成一個10x1的向量y表明樣本輸出。
# X is a 10x10 matrix X = 1. / (np.arange(1, 11) + np.arange(0, 10)[:, np.newaxis]) # y is a 10 x 1 vector y = np.ones(10)
這樣咱們的數據有了,接着就是準備超參數\(\alpha\)了。咱們準備了200個超參數,來分別跑 Ridge迴歸。準備這麼多的目的是爲了後面畫圖看\(\alpha\)和\(\theta\)的關係
n_alphas = 200 # alphas count is 200, 都在10的-10次方和10的-2次方之間 alphas = np.logspace(-10, -2, n_alphas)
有了這200個超參數\(\alpha\),咱們作200次循環,分別求出各個超參數對應的\(\theta\)(10個維度),存起來後面畫圖用。
clf = linear_model.Ridge(fit_intercept=False) coefs = [] # 循環200次 for a in alphas: #設置本次循環的超參數 clf.set_params(alpha=a) #針對每一個alpha作ridge迴歸 clf.fit(X, y) # 把每個超參數alpha對應的theta存下來 coefs.append(clf.coef_)
好了,有了200個超參數\(\alpha\),以及對應的\(\theta\),咱們能夠畫圖了。咱們的圖是以\(\alpha\)爲x軸,\(\theta\)的10個維度爲y軸畫的。代碼以下:
ax = plt.gca() ax.plot(alphas, coefs) #將alpha的值取對數便於畫圖 ax.set_xscale('log') #翻轉x軸的大小方向,讓alpha從大到小顯示 ax.set_xlim(ax.get_xlim()[::-1]) plt.xlabel('alpha') plt.ylabel('weights') plt.title('Ridge coefficients as a function of the regularization') plt.axis('tight') plt.show()
最後獲得的圖以下:
從圖上也能夠看出,當\(\alpha\)比較大,接近於\(10^{-2}\)的時候,\(\theta\)的10個維度都趨於0。而當\(\alpha\)比較小,接近於\(10^{-10}\)的時候,\(\theta\)的10個維度都趨於線性迴歸的迴歸係數。
(歡迎轉載,轉載請註明出處。歡迎溝通交流: liujianping-ok@163.com)