1. 程式人生 > >基於sciket-learn實現邏輯迴歸

基於sciket-learn實現邏輯迴歸

邏輯迴歸雖然名稱裡有迴歸兩個字,但是邏輯迴歸主要用來解決分類問題,並且只能解決二分類問題。(當然邏輯迴歸也可以解決迴歸問題;同時邏輯迴歸可以通過OvO、OvR等方法實現多分類,但本質還是二分類。)

邏輯迴歸與線性迴歸不同的是,線性迴歸得出的是一個具體的預測值,預測房價的模型得出的就是房價,預測成績的模型得出的就是成績,而邏輯迴歸得出的是概率,通過概率大於小於來進行分類。下面是邏輯迴歸的公式:

接下來通過程式碼,來具體看看邏輯迴歸是怎麼一回事。

先匯入基本類庫,生成模擬資料集,並且增加噪聲

import numpy as np
import matplotlib.pyplot as plt

np.random.seed(666)
X = np.random.normal(0, 1, size=(200, 2))
y = np.array((X[:,0]**2+X[:,1])<1.5, dtype='int')
for _ in range(20):
    y[np.random.randint(200)] = 1

視覺化資料

plt.scatter(X[y==0,0], X[y==0,1])
plt.scatter(X[y==1,0], X[y==1,1])
plt.show()

劃分測試集和預測集

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=666)

生成sciket-learn為我們封裝好的邏輯迴歸構造器進行fit操作

from sklearn.linear_model import LogisticRegression

log_reg = LogisticRegression()
log_reg.fit(X_train, y_train)

檢視分類結果

log_reg.score(X_train, y_train)
log_reg.score(X_test, y_test)

視覺化(這個視覺化函式不是重點,知道意思即可)

def plot_decision_boundary(model, axis):
    
    x0, x1 = np.meshgrid(
        np.linspace(axis[0], axis[1], int((axis[1]-axis[0])*100)).reshape(-1, 1),
        np.linspace(axis[2], axis[3], int((axis[3]-axis[2])*100)).reshape(-1, 1),
    )
    X_new = np.c_[x0.ravel(), x1.ravel()]

    y_predict = model.predict(X_new)
    zz = y_predict.reshape(x0.shape)

    from matplotlib.colors import ListedColormap
    custom_cmap = ListedColormap(['#EF9A9A','#FFF59D','#90CAF9'])
    
    plt.contourf(x0, x1, zz, linewidth=5, cmap=custom_cmap)
plot_decision_boundary(log_reg, axis=[-4, 4, -4, 4])
plt.scatter(X[y==0,0], X[y==0,1])
plt.scatter(X[y==1,0], X[y==1,1])
plt.show()

可以看出擬合結果非常不好,因為用直線去擬合一個二次曲線,結果必然是欠擬合的,所以增加一個特徵值,還是先使用管道的方式

from sklearn.preprocessing import PolynomialFeatures
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler

def PolynomialLogisticRegression(degree):
    return Pipeline([
        ('poly', PolynomialFeatures(degree=degree)),
        ('std_scaler', StandardScaler()),
        ('log_reg', LogisticRegression())
    ])

在這裡給degree傳入2進行訓練

poly_log_reg = PolynomialLogisticRegression(degree=2)
poly_log_reg.fit(X_train, y_train)

檢視結果並可視化

poly_log_reg.score(X_train, y_train)
poly_log_reg.score(X_test, y_test)

plot_decision_boundary(poly_log_reg, axis=[-4, 4, -4, 4])
plt.scatter(X[y==0,0], X[y==0,1])
plt.scatter(X[y==1,0], X[y==1,1])
plt.show()

可以看出現在擬合的已經很不錯了

在使用sciket-learn封裝好的類庫,degree傳入較大的值,檢視分類結果。

poly_log_reg2 = PolynomialLogisticRegression(degree=50)
poly_log_reg2.fit(X_train, y_train)

poly_log_reg2.score(X_train, y_train)
poly_log_reg2.score(X_test, y_test)

因為在生成預測資料集的時候,便已經知道了是條二次曲線,所以degree=2時的擬合結果及泛化能力都是最好的,但是實際業務中,往往需要綜合很多因素才能得出最佳的degree去值。