代碼實現三種迴歸算法---嶺迴歸,lasso迴歸,彈性網絡

import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
import pandas as pd
import warnings
import sklearn
from sklearn.linear_model import LinearRegression,LassoCV,RidgeCV,ElasticNetCV
from sklearn.preprocessing import PolynomialFeatures
from sklearn.pipeline import Pipeline  #Pipeline可以將許多算法模型串聯起來,比如將特徵提取、歸一化、分類組織在一起形成一個典型的機器學習問題工作流
from sklearn.linear_model.coordinate_descent import ConvergenceWarning
#設置字符集,防止中文亂碼
mpl.rcParams['font.sans-serif']=[u'simHei']
mpl.rcParams['axes.unicode_minus']=False
## 攔截異常
warnings.filterwarnings(action = 'ignore', category=ConvergenceWarning)
#常見模擬數據
np.random.seed(100)
np.set_printoptions(linewidth=1000, suppress=True)#顯示方式設置,每行的字符數用於插入換行符,是否使用科學計數法
N=10
x = np.linspace(0, 6, N) + np.random.randn(N)
y = 1.8*x**3 + x**2 - 14*x - 7 + np.random.randn(N)
## 將其設置爲矩陣
x.shape = -1, 1
y.shape = -1, 1
## RidgeCV和Ridge的區別是:前者可以進行交叉驗證
models = [
    Pipeline([
            ('Poly', PolynomialFeatures(include_bias=False)),
            ('Linear', LinearRegression(fit_intercept=False))
        ]),
    Pipeline([
            ('Poly', PolynomialFeatures(include_bias=False)),
            # alpha給定的是Ridge算法中,L2正則項的權重值,也就是ppt中的蘭姆達
            # alphas是給定CV交叉驗證過程中,Ridge算法的alpha參數值的取值的範圍
            ('Linear', RidgeCV(alphas=np.logspace(-3,2,50), fit_intercept=False))
        ]),
    Pipeline([
            ('Poly', PolynomialFeatures(include_bias=False)),
            ('Linear', LassoCV(alphas=np.logspace(0,1,10), fit_intercept=False))
        ]),
    Pipeline([
            ('Poly', PolynomialFeatures(include_bias=False)),
            # la_ratio:給定EN算法中L1正則項在整個懲罰項中的比例,這裏給定的是一個列表;
            # 表示的是在CV交叉驗證的過程中,EN算法L1正則項的權重比例的可選值的範圍
            ('Linear', ElasticNetCV(alphas=np.logspace(0,1,10), l1_ratio=[.1, .5, .7, .9, .95, 1], fit_intercept=False))
        ])
]
## 線性模型過擬合圖形識別
plt.figure(facecolor='w')
degree = np.arange(1,N,4) # 階
dm = degree.size
colors = [] # 顏色
for c in np.linspace(16711680, 255, dm):
    colors.append('#%06x' % int(c))

model = models[0]
for i,d in enumerate(degree):
    plt.subplot(int(np.ceil(dm/2.0)),2,i+1)
    plt.plot(x, y, 'ro', ms=10, zorder=N)

    # 設置階數
    model.set_params(Poly__degree=d)
    # 模型訓練
    model.fit(x, y.ravel())
    
    lin = model.get_params('Linear')['Linear']
    output = u'%d階,係數爲:' % (d)
    # 判斷lin對象中是否有對應的屬性
    if hasattr(lin, 'alpha_'):
        idx = output.find(u'係數')
        output = output[:idx] + (u'alpha=%.6f, ' % lin.alpha_) + output[idx:]
    if hasattr(lin, 'l1_ratio_'):
        idx = output.find(u'係數')
        output = output[:idx] + (u'l1_ratio=%.6f, ' % lin.l1_ratio_) + output[idx:]
    print (output, lin.coef_.ravel())
    
    x_hat = np.linspace(x.min(), x.max(), num=100) ## 產生模擬數據
    x_hat.shape = -1,1
    y_hat = model.predict(x_hat)
    s = model.score(x, y)
    
    z = N - 1 if (d == 2) else 0
    label = u'%d階, 正確率=%.3f' % (d,s)
    plt.plot(x_hat, y_hat, color=colors[i], lw=2, alpha=0.75, label=label, zorder=z)
    
    plt.legend(loc = 'upper left')
    plt.grid(True)
    plt.xlabel('X', fontsize=16)
    plt.ylabel('Y', fontsize=16)

plt.tight_layout(1, rect=(0,0,1,0.95))
plt.suptitle(u'線性迴歸過擬合顯示', fontsize=22)
plt.show()

在這裏插入圖片描述

線性迴歸、Lasso迴歸、Ridge迴歸、ElasticNet比較

plt.figure(facecolor='w')
degree = np.arange(1,N, 2) # 階, 多項式擴展允許給定的階數
dm = degree.size
colors = [] # 顏色
for c in np.linspace(16711680, 255, dm):
    colors.append('#%06x' % int(c))
titles = [u'線性迴歸', u'Ridge迴歸', u'Lasso迴歸', u'ElasticNet']

for t in range(4):
    model = models[t]#選擇了模型--具體的pipeline(線性、Lasso、Ridge、EN)
    plt.subplot(2,2,t+1) # 選擇具體的子圖
    plt.plot(x, y, 'ro', ms=10, zorder=N) # 在子圖中畫原始數據點; zorder:圖像顯示在第幾層

    # 遍歷不同的多項式的階,看不同階的情況下,模型的效果
    for i,d in enumerate(degree):
        # 設置階數(多項式)
        model.set_params(Poly__degree=d)
        # 模型訓練
        model.fit(x, y.ravel())

        # 獲取得到具體的算法模型
        # model.get_params()方法返回的其實是一個dict對象,後面的Linear其實是dict對應的key
        # 也是我們在定義Pipeline的時候給定的一個名稱值
        lin = model.get_params()['Linear']
        # 打印數據
        output = u'%s:%d階,係數爲:' % (titles[t],d)
        # 判斷lin對象中是否有對應的屬性
        if hasattr(lin, 'alpha_'): # 判斷lin這個模型中是否有alpha_這個屬性
            idx = output.find(u'係數')
            output = output[:idx] + (u'alpha=%.6f, ' % lin.alpha_) + output[idx:]
        if hasattr(lin, 'l1_ratio_'): # 判斷lin這個模型中是否有l1_ratio_這個屬性
            idx = output.find(u'係數')
            output = output[:idx] + (u'l1_ratio=%.6f, ' % lin.l1_ratio_) + output[idx:]
        # line.coef_:獲取線性模型的參數列表,也就是我們ppt中的theta值,ravel()將結果轉換爲1維數據
        print (output, lin.coef_.ravel())

        # 產生模擬數據
        x_hat = np.linspace(x.min(), x.max(), num=100) ## 產生模擬數據
        x_hat.shape = -1,1
        # 數據預測
        y_hat = model.predict(x_hat)
        # 計算準確率
        s = model.score(x, y)

        # 當d等於5的時候,設置爲N-1層,其它設置0層;將d=5的這條線凸顯出來
        z = N + 1 if (d == 5) else 0
        label = u'%d階, 正確率=%.3f' % (d,s)
        plt.plot(x_hat, y_hat, color=colors[i], lw=2, alpha=0.75, label=label, zorder=z)
    
    plt.legend(loc = 'upper left')
    plt.grid(True)
    plt.title(titles[t])
    plt.xlabel('X', fontsize=16)
    plt.ylabel('Y', fontsize=16)
plt.tight_layout(1, rect=(0,0,1,0.95))
plt.suptitle(u'各種不同線性迴歸過擬合顯示', fontsize=22)
plt.show()

在這裏插入圖片描述
可以看出在不進行正則化的情況下, 9階比較:

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
加上正則後參數明顯降下來了

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章