日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

基于sklearn的LogisticRegression二分类实践

發布時間:2024/7/5 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 基于sklearn的LogisticRegression二分类实践 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

    • 1. 預備知識
    • 2. 實踐代碼
    • 3. 結果對比
      • 3.1 正態分布
      • 3.2 均勻分布
      • 3.3 修改Pipeline
        • 3.3.1 刪除多項式轉換
        • 3.3.2 刪除歸一化項
        • 3.3.3 刪除多項式轉換&歸一化
      • 3.4 總結
    • 4. 附
      • 4.1 matplotlib.pyplot.contourf
      • 4.2 numpy 之 np.r_[a,b], np.c_[a,b]

本文使用 sklearn的邏輯斯諦回歸模型,進行二分類預測,并通過調整各種參數,對預測結果進行對比。

1. 預備知識

邏輯斯諦回歸模型( Logistic Regression,LR)

范數(norm) 幾種范數的簡單介紹

  • L0 范數:∣∣X∣∣0=#(i∣xi≠0)||X||_0 = \#(i|x_i\neq 0)X0?=#(ixi??=0) 向量中非零元素個數,由于它沒有一個好的數學表示,難以應用。
  • L1 范數:∣∣X∣∣1=∑i=1n∣xi∣||X||_1 = \sum\limits_{i=1}^n |x_i|X1?=i=1n?xi? 表示非零元素的絕對值之和
  • L2 范數:∣∣X∣∣2=∑i=1nxi2||X||_2 = \sqrt{\sum\limits_{i=1}^n {x_i}^2}X2?=i=1n?xi?2? 表示元素的平方和再開方

機器學習——正則化 (L1與L2范數)

  • 一般來說,監督學習可以看做最小化下面的目標函數:
    ω?=arg?min?ω∑iL(yi,f(xi;ω))+λΩ(ω)\omega^* = \argmin\limits_\omega \sum\limits_i L(y_i, f(x_i;\omega))+\lambda \Omega(\omega)ω?=ωargmin?i?L(yi?,f(xi?;ω))+λΩ(ω) LLL 是損失項(訓練誤差),Ω\OmegaΩ 項是對參數 ω\omegaω 的規則化函數,去約束模型,使之盡量簡單,λ\lambdaλ 為系數,在sklearn的參數中 C=1/λC = 1/\lambdaC=1/λ
  • L1 范數是指向量中各個元素絕對值之和,也叫“稀疏規則算子”(Lasso regularization)
  • L1 范數和 L0 范數可以實現稀疏(趨于產生少量特征,其他為0),L1 因具有比 L0 更好的優化求解特性而被廣泛應用。
  • L2 范數是指向量各元素的平方和然后求平方根
  • L2 范數可以防止過擬合,提升模型的泛化能力(選擇更多的特征,特征都會接近0)。

sklearn中的LogisticRegression模型一文對模型的參數進行了說明

sklearn 中文文檔 https://sklearn.apachecn.org/docs/0.21.3/

2. 實踐代碼

  • 生成以y=-x^2+1.5為分類線的數據集
  • 為增加模型學習難度,將隨機抽取的10%的數據強行賦值為正類
  • 嘗試通過特征的多項式升維、歸一化,然后交給LR模型,訓練一個分類曲線。
  • 為了學習到合適的分類曲線,我們嘗試了不同的參數組合
'''遇到不熟悉的庫、模塊、類、函數,可以依次:1)百度(google確實靠譜一些),如"matplotlib.pyplot",會有不錯的博客供學習參考2)"終端-->python-->import xx-->help(xx.yy)",一開始的時候這么做沒啥用,但作為資深工程師是必備技能3)試著修改一些參數,觀察其輸出的變化,在后面的程序中,會不斷的演示這種辦法 ''' # written by hitskyer # modified by Michael Ming on 2020.2.12 import sys import numpy as np import matplotlib.pyplot as plt # sklearn 中文文檔 https://sklearn.apachecn.org/docs/0.21.3/ from sklearn.model_selection import train_test_split from sklearn.pipeline import Pipeline from sklearn.preprocessing import PolynomialFeatures from sklearn.preprocessing import StandardScaler from sklearn.linear_model import LogisticRegression from sklearn import metricsdef get_parabolic_curve_data_set(n):# 設置隨機數的種子,以保證每回運行程序的隨機結果一致np.random.seed(520) # 520 可以隨便寫 Seed must be between 0 and 2**32 - 1# 隨機生成200個樣本,每個樣本兩維特征# X = np.random.normal(0, 1, size=(n, 2)) # 正態分布,中心0,標準差1# 更改X的分布(正態,均勻),看看結果有什么變化X = np.random.uniform(-4, 4, size=(n, 2)) # 均勻分布,區間[-4,4)# 分類面(線)是y=-x^2+1.5,開口向下的拋物線,口內為1類,口外為0類y = np.array(X[:, 0] ** 2 + X[:, 1] < 1.5, dtype=int) # 滿足關系的為1,否則為0# 加入10%的噪聲數據for _ in range(n // 10): # //為整除y[np.random.randint(n)] = 1return X, ydef show_data_set(X, y):plt.scatter(X[y == 0, 0], X[y == 0, 1], c='r')# 散點圖,分量1,為y==0的行的0列,分量2,y==0的行的1列,c表示顏色plt.scatter(X[y == 1, 0], X[y == 1, 1], c='b')plt.show()def PolynomialLogisticRegression(degree=2, C=1.0, penalty='l2'):# 對輸入特征依次做 多項式轉換、歸一化轉換、類別預測,可以嘗試注釋掉前2個操作,看看結果有什么不同return Pipeline([# Pipeline 可以把多個評估器鏈接成一個。例如特征選擇、標準化和分類# 以多項式的方式對原始特征做轉換,degree次多項式('poly', PolynomialFeatures(degree=degree)),# 對多項式轉換后的特征向量做歸一化處理,例如(數據-均值)/標準差('std_scaler', StandardScaler()),# 用轉換后的特征向量做預測,penalty是正則化約束,C正則化強度,值越小,強度大# solver 不同的求解器擅長的規模類型差異# 正則化 https://blog.csdn.net/zouxy09/article/details/24971995/('log_reg', LogisticRegression(C=C, penalty=penalty, solver="liblinear", max_iter=10000))])def plot_decision_boundary(x_min, x_max, y_min, y_max, pred_func):h = 0.01# 產生網格xx, yy = np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h))# ravel將矩陣展平,np_c[a,b]將a,b按列拼在一起Z = pred_func(np.c_[xx.ravel(), yy.ravel()])Z = Z.reshape(xx.shape)plt.contourf(xx, yy, Z, cmap=plt.cm.Spectral) # 填充等高線# 等高線參考 https://blog.csdn.net/lens___/article/details/83960810def test(X_train, X_test, y_train, y_test, degree=2, C=1.0, penalty='l2'):poly_log_reg = PolynomialLogisticRegression(degree=degree, C=C, penalty=penalty)# 訓練模型poly_log_reg.fit(X_train, y_train)# 在訓練數據上做測試predict_train = poly_log_reg.predict(X_train)sys.stdout.write("LR(degree = %d, C=%.2f, penalty=%s) Train Accuracy : %.4g\n" % (degree, C, penalty, metrics.accuracy_score(y_train, predict_train)))# 在測試數據上做測試predict_test = poly_log_reg.predict(X_test)score = metrics.accuracy_score(y_test, predict_test)sys.stdout.write("LR(degree = %d, C=%.2f, penalty=%s) Test Accuracy : %.4g\n" % (degree, C, penalty, score))print("--------------------------------------")# 展示分類邊界plot_decision_boundary(-4, 4, -4, 4, lambda x: poly_log_reg.predict(x))plt.scatter(X_train[y_train == 0, 0], X_train[y_train == 0, 1], color='r')plt.scatter(X_train[y_train == 1, 0], X_train[y_train == 1, 1], color='b')plt.xlabel("x1")plt.ylabel("x2")plt.rcParams['font.sans-serif'] = 'SimHei' # 消除中文亂碼plt.rcParams['axes.unicode_minus'] = False # 用來正常顯示負號plt.title("參數:degree:%d, C:%.2f, penalty:%s -- 準確率: %.4f" % (degree, C, penalty, score))plt.show()if __name__ == '__main__':# 隨機生成200個擁有2維實數特征 且 分類面(線)為y=-x^2+1.5(換言之,x2=-x1^2+1.5)的語料X, y = get_parabolic_curve_data_set(200) # 可以加大數據量查看對結果的影響# 預留30%作為測試語料X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=0)# 展示所生成的數據show_data_set(X, y)# 測試不同的超參數組合print("準確率高,比較恰當的模型")test(X_train, X_test, y_train, y_test, degree=2, C=1.0, penalty='l2')print("準確率高,且恰當的模型")test(X_train, X_test, y_train, y_test, degree=2, C=0.1, penalty='l2')print("準確率高,但是過擬合的模型")test(X_train, X_test, y_train, y_test, degree=20, C=1.0, penalty='l2')print("準確率低,且過擬合的模型")test(X_train, X_test, y_train, y_test, degree=20, C=0.1, penalty='l2')print("準確率高,且恰當的模型")test(X_train, X_test, y_train, y_test, degree=20, C=0.1, penalty='l1')

3. 結果對比

3.1 正態分布

當樣本為正態分布時:X = np.random.normal(0, 1, size=(n, 2)) # 正態分布,中心0,標準差1

參數組合數據(正態分布)deg = 2, C=1.00, l2deg = 2, C=0.10, l2deg = 20, C=1.00, l2deg = 20, C=0.10, l2deg = 20, C=0.10, l1
200組數據、seed(520)
準確率0.95000.95000.91670.93330.9333
200組數據、seed(777)
準確率0.93330.93330.93330.88330.9167
2000組數據 seed(520)
準確率0.93330.92170.93170.92330.9317
2000組數據 seed(777)
準確率0.91170.89830.92330.90670.9150

對比可以發現:

  • 對比 1,2 列,數據越密集的區域,越容易學到準確的分類邊界,且容易克服噪聲的影響;
  • 隨機種子seed不一樣,產生的樣本集合不同,在假設的分類模型比較接近真實分類界線(y=-x^2+1.5),隨著數據增加,學習到的模型越靠譜;在假設的分類模型比真實分類界限復雜時,在數據密集區域,隨著數據增多,配合上正則化,依然可以學習到更準確的模型。在數據稀釋區域,模型的復雜度很高,且受噪聲數據影響比較大。
  • degree的增加,可以產生高階的曲線分界
  • 對比 3,4 列,C越大,正則化項作用越小,曲線會越復雜,過擬合會越嚴重
  • 對比 4,5 列,可見,l1 正則化下的預測分界曲線可能階數更低(非0參數更少)
  • 分類線實質上是拋物線(2階),我們用20階去學習,首先2000組數據不一定充分,其次,由于正態分布數據集中在中心,邊緣區域數據覆蓋很少,所以周圍區域的分類線有時候會奇形怪狀,但中心區域的分類還是比較準確的

3.2 均勻分布

當樣本為均勻分布時:X = np.random.uniform(-4, 4, size=(n, 2)) # 均勻分布,區間[-4,4)

參數組合數據(均勻分布)deg = 2, C=1.00, l2deg = 2, C=0.10, l2deg = 20, C=1.00, l2deg = 20, C=0.10, l2deg = 20, C=0.10, l1
200組數據、seed(520)
準確率0.85000.83330.83330.80000.8333
200組數據、seed(777)
準確率0.78330.73330.76670.70000.6667
2000組數據 seed(520)
準確率0.87670.87500.90500.89000.8767
2000組數據 seed(777)
準確率0.88830.88830.90500.90170.8950
  • 由上面2大組實驗(X的分布形式改變),可看出均勻分布下,2000組數據下,各組參數下分類結果均比較好
  • 當數據量比較小時,結果易受到seed隨機出來的樣本影響(第1,2行),同時,分類效果也不好

3.3 修改Pipeline

sklearn 的 Pipeline簡介:

  • 管道機制實現了對機器學習全部步驟的流式化封裝和管理
  • 前幾步是轉換器(Transformer)(如多項式轉換、歸一化等等),最后一步必須是估計器(Estimator)或叫分類器,輸入數據經過轉換器處理,輸出的結果作為下一步的輸入
  • pipeline.fit生成預測模型
  • pipeline.predict對數據進行預測

上面實踐代碼里Pipeline定義了模型將要做的事情:

  • a. 對數據進行 多項式轉換PolynomialFeatures(維度變化)
  • b. 歸一化處理StandardScaler(讓異常數據不要對正常數據造成很大影響)
  • c. 邏輯斯諦回歸LogisticRegression(預測)
def PolynomialLogisticRegression(degree=2, C=1.0, penalty='l2'):# 對輸入特征依次做多項式轉換、歸一化轉換、類別預測return Pipeline([# Pipeline 可以把多個評估器鏈接成一個。例如特征選擇、標準化和分類# 以多項式的方式對原始特征做轉換,degree次多項式('poly', PolynomialFeatures(degree=degree)),# 對多項式轉換后的特征向量做歸一化處理,例如(數據-均值)/標準差('std_scaler', StandardScaler()),# 用轉換后的特征向量做預測,penalty是正則化約束,C正則化強度,值越小,強度大# solver 不同的求解器擅長的規模類型差異# 正則化 https://blog.csdn.net/zouxy09/article/details/24971995/('log_reg', LogisticRegression(C=C, penalty=penalty, solver="liblinear"))])

在均勻分布的情況下,刪除a、刪除b、刪除a,b,查看對預測的影響

3.3.1 刪除多項式轉換

參數組合, no ploy數據(均勻分布)deg = 2, C=1.00, l2deg = 2, C=0.10, l2deg = 20, C=1.00, l2deg = 20, C=0.10, l2deg = 20, C=0.10, l1
200組數據、seed(520)
準確率0.73330.73330.73330.73330.7333
200組數據、seed(777)
準確率0.63330.61670.63330.61670.5667
2000組數據 seed(520)
準確率0.69330.69330.69330.69330.6917
2000組數據 seed(777)
準確率0.68670.68670.68670.68670.6867
  • 可以看出在刪除ploy多項式轉換項后,模型維度沒有增加,保持線性
  • 預測分類線為一條直線
  • 預測準確率也下降很多,不管怎么調參數,效果甚微

3.3.2 刪除歸一化項

參數組合, no std_scaler數據(均勻分布)deg = 2, C=1.00, l2deg = 2, C=0.10, l2deg = 20, C=1.00, l2deg = 20, C=0.10, l2deg = 20, C=0.10, l1
200組數據、seed(520)
準確率0.86670.86670.85000.85000.8500(Warning)
200組數據、seed(777)
準確率0.80000.80000.75000.75000.7176(Warning)
2000組數據 seed(520)沒跑出來
準確率0.87670.87830.77670.7767-
2000組數據 seed(777)沒跑出來
準確率0.88830.89170.81000.8133-
  • 可以看出在2階情況下,沒有歸一化,影響不是很大
  • 高階下,沒有歸一化,對結果影響很大(因為噪聲數據下,高階波動相當大,相當于系統不穩定,conditiona number很大)
//報的Warning ConvergenceWarning: Liblinear failed to converge, increase the number of iterations."the number of iterations.", ConvergenceWarning)

3.3.3 刪除多項式轉換&歸一化

參數組合, no ploy & no scaler數據(均勻分布)deg = 2, C=1.00, l2deg = 2, C=0.10, l2deg = 20, C=1.00, l2deg = 20, C=0.10, l2deg = 20, C=0.10, l1
200組數據、seed(520)
準確率0.73330.76670.73330.76670.7500
200組數據、seed(777)
準確率0.61670.66670.61670.66670.6333
2000組數據 seed(520)
準確率0.69330.69330.69330.69330.6917
2000組數據 seed(777)
準確率0.68500.69000.68500.69000.6883
  • 沒有多項式與歸一化后,分類線表現為一條直線(沒有多項式轉換)
  • 分類效果也都很差,調參效果很差

3.4 總結

  • 訓練數據分布對預測結果有直接影響,數據密集的地方預測較準,數據稀疏的地方,預測不準確(噪聲,模型本身都有影響)
  • 特征轉換,有助于預測出更高階的模型
  • 歸一化能夠降低噪聲的影響
  • 加大數據規模一定程度上能夠抗噪,提高模型準確率,重復區域高密度的數據一定程度以后,對模型預測也就失去了價值

4. 附

4.1 matplotlib.pyplot.contourf

import numpy as np import matplotlib.pyplot as plt# 計算x,y坐標對應的高度值 def f(x, y):return x**2+y<1.5# 生成x,y的數據 n = 256 x = np.linspace(-4, 4, n) y = np.linspace(-4, 4, n) # 把x,y數據生成mesh網格狀的數據,在網格的基礎上添加上高度值 X, Y = np.meshgrid(x, y) # 填充等高線 plt.contourf(X, Y, f(X, Y)) # 顯示圖表 plt.show()

畫出 x**2+y = 1.5 的等高線如下

4.2 numpy 之 np.r_[a,b], np.c_[a,b]

np.r_ np.c_ 用法參考下面:>>> a array([[1, 2, 3],[7, 8, 9]]) >>> b array([[4, 5, 6],[1, 2, 3]]) >>> c=np.c_[a,b] >>> c array([[1, 2, 3, 4, 5, 6],[7, 8, 9, 1, 2, 3]]) >>> c=np.r_[a,b] >>> c array([[1, 2, 3],[7, 8, 9],[4, 5, 6],[1, 2, 3]]) >>> c=np.c_[a.ravel(),b.ravel()] # ravel()展平 >>> c array([[1, 4],[2, 5],[3, 6],[7, 1],[8, 2],[9, 3]])

總結

以上是生活随笔為你收集整理的基于sklearn的LogisticRegression二分类实践的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。