一、基礎理解
- 使用邏輯回歸算法訓練模型時,為模型引入多項式項,使模型生成不規則的決策邊界,對非線性的數據進行分類;
- 問題:引入多項式項后,模型變的復雜,可能產生過擬合現象;
- 方案:對模型正則化處理,損失函數添加正則項(αL2),生成新的損失函數,並對新的損失函數進行優化;
- 優化新的損失函數:
- 滿足了讓原來的損失函數盡量的小;
- 另一方面,對於 L2 正則項(包含參數 θ 值),限制 θ 的大小;
- 引入了參數 α ,調節新的損失函數中兩部分(原損失函數和 L2 正則項)的重要程度;當然也可以引入 αL1 正則項;
二、正則化的其它方式
- 新的表達正則化的方式:只是方式不同,正則化的原來一樣;
- 改變了超參數的位置:α、C;
- 如果超參數 C 越大,原損失函數 J(θ) 的地位相對較重要,優化損失函數時主要集中優化 J(θ) ,使其減少到最小;
- 如果超參數 C 非常小,正則項 L2 的地位相對較重要,優化損失函數時主要集中優化 L2 ,使參數 θ 中的元素盡量的小;
- 如果想讓使正則項不重要,需要增大參數 C;
- 其實在 J(θ) 前加參數 C,相當於將原來的 αL2 變為 1/αL2 ,兩中方式等效;
- α、C:平衡新的損失函數中兩部分的關系;
- 在邏輯回歸、SVM算法中,更偏好使用 C.J(θ) + L2 的方式;scikit-learn 的邏輯回歸算法中,也是使用此方式;
- 原因:使用 C.J(θ) + L2 方式時,正則項的系數為 1,也就是說優化算法模型時不得不使用正則化;
三、思考
- 多項式回歸:假設在特征空間中,樣本的分布規律呈多項式曲線狀態,可能類似 2 次多項式曲線,也可能是 3 次多項式的曲線,也可能是 n 次多項式的曲線;
- n 次多項式曲線:y = xn + ...,最高 n 次方,還有其他很多項,x 與 y 的關系曲線;
- 疑問1:是不是二維空間的所有不規則曲線都存在一個多項式與其對應?
- 疑問2:如果樣本分布規律不是多項式曲線的規律,再使用多項式回歸算法,或者邏輯回歸的多項式形式進行分類,是不是就不准確?
- 思考:解決具體的問題,通過可視化查看樣本相根據特征大致的分布,再判斷可以使用哪些算法,組個嘗試,找個最合適的一個;
- 最合適:准確度高、效率高;
四、實例scikit-learn中的邏輯回歸算法
- scikit-learn中的邏輯回歸算法自動封裝了模型的正則化的功能,只需要調整 C 和 penalty;
- 主要參數:degree、C、penalty;(還有其它參數)
1)直接使用邏輯回歸算法
-
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') # 隨機抽取 20 個樣本,讓其分類為 1,相當於認為更改數據,添加噪音 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()
- 為虛擬的測試數據設置種子 666:則每次執行 np.random.normal(0, 1, size=(200, 2)) 時,隨機生成的 X 不變;
- 隨機生成數據是系統內定的,隨機種子是系統隨機生成數據時的依據,只要設定的隨機種子相同,所有人生成的數據一樣;(待考察)
-
from sklearn.model_selection import train_test_split X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=666) from sklearn.linear_model import LogisticRegression log_reg = LogisticRegression() log_reg.fit(X_train, y_train) # LogisticRegression(C=1.0, class_weight=None, dual=False, fit_intercept=True, intercept_scaling=1, max_iter=100, multi_class='ovr', n_jobs=1, penalty='l2', random_state=None, solver='liblinear', tol=0.0001, verbose=0, warm_start=False)
-
C=1.0:默認超參數 C 的值為1.0;
- penalty='l2':默認使用 L2 正則項;
-
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()
2)為邏輯回歸算法的模型添加多項式項
-
degree = 2、C 默認1.0
from sklearn.pipeline import Pipeline from sklearn.preprocessing import PolynomialFeatures from sklearn.preprocessing import StandardScaler def PolynomialLogisticRegression(degree): return Pipeline([ ('poly', PolynomialFeatures(degree=degree)), ('std_scaler', StandardScaler()), ('log_reg', LogisticRegression()) ]) # 使用管道時,先生成實例的管道對象,在進行 fit; poly_log_reg = PolynomialLogisticRegression(degree=2) poly_log_reg.fit(X_train, y_train) 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()
-
degree = 20、C 默認1.0
poly_log_reg2 = PolynomialLogisticRegression(degree=20) poly_log_reg2.fit(X_train, y_train) plot_decision_boundary(poly_log_reg2, 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()
-
degree = 20、C = 0.1
def PolynomialLogisticRegression(degree, C): return Pipeline([ ('poly', PolynomialFeatures(degree=degree)), ('std_scaler', StandardScaler()), ('log_reg', LogisticRegression(C=C)) ]) poly_log_reg3 = PolynomialLogisticRegression(degree=20, C=0.1) poly_log_reg3.fit(X_train, y_train) plot_decision_boundary(poly_log_reg3, 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()
-
degree = 20、C = 0.1、penalty = 'L1'(penalty:正則項類型, 默認為 L2)
def PolynomialLogisticRegression(degree, C, penalty='l2'): return Pipeline([ ('poly', PolynomialFeatures(degree=degree)), ('std_scaler', StandardScaler()), ('log_reg', LogisticRegression(C=C, penalty=penalty)) ]) poly_log_reg4 = PolynomialLogisticRegression(degree=20, C=0.1, penalty='l1') poly_log_reg4.fit(X_train, y_train) plot_decision_boundary(poly_log_reg4, 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()
- 分析:degree = 20,模型的決策邊界太復雜,模型可能過擬合,使用 L1 正則項進行模型的正則化;
- 分析2:模型過擬合后,有很多多項式項,使用 L1 正則項,使得這些多項式項的系數為 0,進而使模型決策邊界更加規則,不會彎彎曲曲,便於可視化;