用scikit-learn和pandas學習Ridge迴歸

    本文將用一個例子來說述怎麼用scikit-learn和pandas來學習Ridge迴歸。html

1. Ridge迴歸的損失函數

    在個人另一遍講線性迴歸的文章中,對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

2. 數據獲取與預處理

    這裏咱們仍然用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迴歸僅僅只是爲了講解方便。

3. 數據讀取與訓練集測試集劃分

    咱們先打開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)

    

4. 用scikit-learn運行Ridge迴歸

    要運行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_

    輸出結果以下:

[[-1.97373209 -0.2323016   0.06935852 -0.15806479]]
[ 447.05552892]

    也就是說咱們獲得的模型是:

\(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\)。

5. 用scikit-learn選擇Ridge迴歸超參數\(\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\)值。

6. 用scikit-learn研究超參數\(\alpha\)和迴歸係數\(\theta\)的關係

    經過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) 

相關文章
相關標籤/搜索