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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

机器学习之LR算法理论和实战(实战篇)

發(fā)布時間:2023/12/13 综合教程 28 生活家
生活随笔 收集整理的這篇文章主要介紹了 机器学习之LR算法理论和实战(实战篇) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

1. python 原生實現(xiàn)

這里的原生實現(xiàn)異常粗糙(沒有正則項,隨機梯度上升),就是上一篇 原理篇 的代碼實現(xiàn),數(shù)據(jù)集直接來自sklearn iris(3分類問題),另外,手工提出了0,1兩類,僅做了兩類iris的分類。
對于 (h(X) = w_0 + w_1 x_1 + w_2 x_2 + ... + W_m x_m) = (W^T X)
其中 (W =[w_0,w_1,...w_m] , X = [1,x_1,x_2,...,X_m]) 我習(xí)慣于把截距(w_0) 也合到向量中去了。

import numpy as np
from sklearn.datasets import load_iris

"""
加載數(shù)據(jù)
"""
def load_dataSet():
    X, Y = load_iris(return_X_y=True)
    X_data, Y_data = X[:100,:], Y[:100]   ## 只要 0,1 兩類,做兩分類
    Z = np.concatenate((X_data, Y_data.reshape(X_data.shape[0], 1)), axis=1)
    np.random.shuffle(Z)
    #分割數(shù)據(jù)為訓(xùn)練集和測試集
    X_train, Y_train = Z[:75,0:-1], Z[:75,-1:]
    X_test, Y_test = Z[75:, :-1], Z[75:, -1:]
    return X_train,Y_train,X_test,Y_test

"""
模型訓(xùn)練
"""

def sigmoid(W,X):
    return 1.0 / (np.exp( - np.dot(W.T,X)) + 1)

def LRModel(W,X,Y,epoch,alpha):
    for i in range(0,epoch):
        Yhat = sigmoid(W, X)
        J = np.dot(Y, np.log(Yhat.T + 0.001)) + np.dot((1 - Y), np.log(1 - Yhat.T +0.001)) ## 這里我手工加了一個0.001,防止處理log0的情況
        W = W + (alpha * (np.dot((Y - Yhat),X.T)).T)
    return W

"""
模型預(yù)測,計算各個指標(biāo)
"""
def predict(X_test,Y_test,Wf):
    Ypre = sigmoid(Wf, X_test)
    print(Ypre)
    Ypre = np.where(Ypre > 0.5, 1., 0.)
    print(Ypre)
    print(Y_test)
    acc = Ypre - Y_test
    print(acc)

if __name__ == "__main__":
    # 初始化W
    W0 = np.random.randn(5,1) # 列向量
    print(W0)
    X_train,Y_train,X_test,Y_test = load_dataSet()
    X_train = np.concatenate((np.ones((X_train.shape[0], 1)), X_train),axis=1)
    X_test = np.concatenate((np.ones((X_test.shape[0], 1)), X_test), axis=1)
    Wf = LRModel(W0,X_train.T,Y_train.T,1000,0.05)
    print("最終學(xué)習(xí)的參數(shù)為:")
    print(Wf)
    predict(X_test.T,Y_test.T,Wf)

結(jié)果

[[-0.32794377]
 [-0.16341301]
 [-0.46871745]
 [-0.58777365]
 [ 0.72274566]]
最終學(xué)習(xí)的參數(shù)為:
[[-0.92044644]
 [-0.86818604]
 [-3.75098037]
 [ 5.22856039]
 [ 3.17813294]]
[[9.99919845e-01 9.99939370e-01 9.99912569e-01 9.99983816e-01
  9.97146748e-01 6.61803146e-05 3.19672831e-06 9.99976409e-01
  9.99999553e-01 9.99837974e-01 9.99827795e-01 4.69817201e-04
  1.65549104e-05 9.99878991e-01 9.99982895e-01 1.66078700e-04
  9.88524297e-01 1.12949239e-05 9.99600934e-01 6.22679950e-05
  9.99989180e-01 1.44838053e-04 4.05583288e-05 3.13544364e-04
  9.99987482e-01]]
[[1. 1. 1. 1. 1. 0. 0. 1. 1. 1. 1. 0. 0. 1. 1. 0. 1. 0. 1. 0. 1. 0. 0. 0.
  1.]]
[[1. 1. 1. 1. 1. 0. 0. 1. 1. 1. 1. 0. 0. 1. 1. 0. 1. 0. 1. 0. 1. 0. 0. 0.
  1.]]
[[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.
  0.]]   ## acc,可以看到在測試集上完全預(yù)測正確

2. scikit-learn代碼實現(xiàn)

scikit-learn中LR的損失函數(shù)函數(shù)和我們想象的不一樣,一方面,他加入了正則項,另一方面,scikit-learn中(y_i)取 1 或者 -1,故他構(gòu)造的損失函數(shù)形式與我們常規(guī)的構(gòu)造不同,(其實,不管是機器學(xué)習(xí),還是深度學(xué)習(xí)中,在得出目標(biāo)函數(shù)后,我們都要想辦法把(y_i)加入目標(biāo)函數(shù)中,得到了損失函數(shù),所以可以靈活構(gòu)造哈

[hat{y_i} = P(y_i| x_i;W) = frac{1}{e^{-x_i^T W + c} + 1} (1)
]

其中(hat{y_i})為預(yù)測值,W為列向量,c為標(biāo)量

[(hat{y_i} = 1) = P(y_i = 1| x_i;W) = frac{1}{e^{y_i(-x_i^TW + c)} + 1} = frac{1}{e^{-x_i^T W + c} + 1} (2)
]

[(hat{y_i} = -1) = P(y_i = -1| x_i;W) = 1 - P(y_i = 1| x_i;W) = 1 - frac{1}{e^{-x_i^T W + c} + 1} = frac{1}{e^{x_i^TW + c} + 1} = frac{1}{e^{y_i(-x_i^T W + c)} + 1} (3)
]

綜上(0)(1)(2),sklearn LR的損失函數(shù)可定義為:

[J(W,c) = mathop{argmax}_{W,c} prod_i^m frac{1}{e^{y_i(-x_i^T W + c)} + 1}
]

即為等價于:

[J(W,c) = mathop{argmax}_{W,c}( - sum_{i}^{m} log(e^{y_i(-x_i^T W + c)} + 1) )
]

即為:

[J(W,c) = mathop{argmin}_{W,c} sum_{i}^{m} log(exp(-y_i(x_i^T W + c)) + 1)
]

引入(L_2)正則化:

[J(W,c) = mathop{argmin}_{W,c} sum_{i}^{m} log(exp(-y_i(x_i^T W + c)) + 1) + frac{1}{2} lambda W^T W (4)
]

其中 (lambda)是超參且必須為正浮點數(shù),需要手工調(diào)參
(4)式求出來的參數(shù)W,c的值和下式無異

[J(W,c) = mathop{argmin}_{W,c} lambda sum_{i}^{m} log(exp(-y_i(x_i^T W + c)) + 1) + frac{1}{2} W^T W (5)
]

對于無異的解釋:

另外除了L2正則化外,還有L1,Elastic-Net 正則化

L1正則化:

[min_{W,c} |w|_1 + C sum_{i=1}^n log(exp(- y_i (X_i^T w + c)) + 1)
]

Elastic-Net正則化:

[min_{w, c} frac{1 - ho}{2}w^T w + ho |w|_1 + C sum_{i=1}^n log(exp(- y_i (X_i^T w + c)) + 1)
]

簡單來講,L1正則化偏向于起到特征選擇作用,L2正則化偏向于起到防止過擬合的作用,Elastic-Net綜合了L1,L2兩種正則化的作用
另外說一句,由于水平有限,鄙人僅關(guān)注于sklearn的API的使用,各個參數(shù)的含義,不管追究sklearn中算法的具體實現(xiàn),原因參考如下:https://www.zhihu.com/question/37217348/answer/71147129 [Glenn Qian的回答]

sklearn API

sklearn.linear_model.LogisticRegression 參數(shù)介紹

class sklearn.linear_model.LogisticRegression(penalty='l2', *, dual=False, tol=0.0001, C=1.0, fit_intercept=True, intercept_scaling=1, 
class_weight=None, random_state=None, solver='lbfgs', max_iter=100, multi_class='auto',
verbose=0, warm_start=False, n_jobs=None, l1_ratio=None)

penalty{‘l1’, ‘l2’, ‘elasticnet’, ‘none’}, default=’l2’
penalty表示選擇的正則化,可選L1,L2,elasticnet, none,默認(rèn)是l2

dual: bool, default=False
當(dāng)使用solver='liblinear',l2正則化時,才有dual = true

tol: float, default=1e-4
停止訓(xùn)練的條件,當(dāng)?shù)昂蟮暮瘮?shù)差值小于等于tol時就停止

C: float, default=1.0
正則化強度的倒數(shù),必須為正浮點數(shù)。越小的值表示越強的正則化

fit_intercept: bool, default=True
指定是否應(yīng)將常量(也稱為偏差或截距)添加到?jīng)Q策函數(shù)

intercept_scaling: float, default=1
僅在使用solver = 'liblinear' 且fit_intercept = True時有用。
*intercept_scaling: float, default=1

class_weight: dict or ‘balanced’, default=None
以字典或者'balanced'形式給出模型的參數(shù)。如果沒有給出,所有類的權(quán)重都應(yīng)該是1。“balanced” 模式使用y的值自動調(diào)整權(quán)值與輸入數(shù)據(jù)中的類頻率成反比,如n_samples / (n_classes * np.bincount(y))。
注意,如果指定了sample_weight,那么這些權(quán)重將與sample_weight相乘(通過fit方法傳遞)。
0.17版本新增:class_weight= 'balanced'

random_state: int, RandomState instance, default=None
在solver= 'sag','saga'或 'liblinear' 才需要有random_state設(shè)置。

solver: {‘newton-cg’, ‘lbfgs’, ‘liblinear’, ‘sag’, ‘saga’}, default=’lbfgs’
求解器solver可以使用 'newton-cg','lbfgs','liblinear','sag','sage'算法來更新參數(shù),其中sage 表示 Stochastic Average Gradient descent。選擇solver的一般原則如下:

對于小型數(shù)據(jù)集,選擇'liblinear',大型數(shù)據(jù)集,可選擇‘sag’,'saga';
‘newton-cg’, ‘lbfgs’, ‘sag’ and ‘saga’ 應(yīng)用在L2正則化或沒有正則化的地方;
‘liblinear’ 和‘saga’ 也可以應(yīng)用在L1正則化出現(xiàn)的地方;
‘saga’支持‘elasticnet’正則化;
‘liblinear’不支持penalty='none';
對于多分類問題,只有“newton-cg”, “sag”, “saga”和“l(fā)bfgs”直接處理多分類問題。而"liblinear"多分類問題轉(zhuǎn)化成多個二分類問題(one-versus-rest,又稱ovr)

max_iter: int, default=100
使求解器solver收斂所需的最大迭代次數(shù)
multi_class: {‘a(chǎn)uto’, ‘ovr’, ‘multinomial’}, default=’auto’
multi_class: {‘a(chǎn)uto’, ‘ovr’, ‘multinomial’}, default=’auto’
如果選擇的選項是'ovr',那么將多分類轉(zhuǎn)化成多個二分類問題。對于“multinomial”損失最小化是多項式損失適合整個概率分布,即使當(dāng)數(shù)據(jù)是二進(jìn)制。當(dāng)求解器= ' liblinear '時,'多項'不可用。auto選擇' ovr '如果數(shù)據(jù)是二進(jìn)制的,或者如果solver= ' liblinear ',否則選擇'多項'。
verbose: int, default=0
記錄訓(xùn)練的日志,int類型。默認(rèn)為0。就是不輸出訓(xùn)練過程,1的時候偶爾輸出結(jié)果
warm_start: bool, default=False
熱啟動參數(shù),bool類型。默認(rèn)為False。如果為True,則下一次訓(xùn)練是以重新上一次的調(diào)用作為初始化
n_jobs : int, default: 1
用cpu的幾個核來跑程序,-1表示使用所有處理器。
l1_ratio: float, default=None
當(dāng) 0 <= l1_ratio <= 1 且 penalty = 'Elasticnet'時, 使用的才是'elasticnet'正則化。設(shè)置l1_ratio=0 相當(dāng)于使用penalty='l2',而設(shè)置l1_ratio=1 相當(dāng)于使用penalty='l1'。



參考文獻(xiàn)

[1] https://www.cnblogs.com/wjq-Law/p/9779657.html (參數(shù)的一些解釋)
[2] https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.LogisticRegression.html

總結(jié)

以上是生活随笔為你收集整理的机器学习之LR算法理论和实战(实战篇)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。