日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

LR模型常见问题小议

發布時間:2025/3/21 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 LR模型常见问题小议 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
 LR模型常見問題小議 標簽: LR機器學習 671人閱讀 評論(0) 收藏 舉報 本文章已收錄于: 分類: 機器學習(10) 作者同類文章X

    目錄(?)[+]

  • 數據歸一化
  • 特征離散化組合
  • 離散化
  • 特征組合
  • 小結
  • 高緯度01特征
  • 正負樣本不均衡問題
  • // 畢竟不是什么大牛,只是總結一下自己的一些認識和想法,如果有不正確的,還請大牛們斧正。

    經常說的2/8原則,LR肯定就是能解決80%問題中那20%的工具。所以LR還是值得好好研究的。發現以前對LR重視不夠,總想著趕緊把其他算法也學了,才能拉小跟同事之間機器學習的gap。其實LR用得還是挺多的,而且效果還是不錯的。一些高大上的算法,在公司這種大數據面前不一定跑得動,即使跑得動,效果也不一定好,而且還有可解釋性和工程維護方面復雜度的問題。這倒是挺殘酷的現實。

    發現學完coursera的機器學習課程后,離具體實踐還是有不少距離,也沒找到什么好的資料可以學習(如果誰發現有的話,麻煩告訴我一聲吧),耳濡目染了一些奇技淫巧,總結一下,有一些其實之前的筆記也零散提到了。

    數據歸一化

    仔細區分的話,有兩種:

  • 歸一化: (x-最小值)/(最大值-最小值)
  • 標準化: (x-平均數)/標準差
  • 反正就是把數據縮放到大小差不多,在1左右。這樣起到的作用是加速迭代。根本原因其實是因為你偷懶,沒有為每一個特征單獨設置一個a。既然用了同一個a,那你也要保證數據scale也差不多。

    特征離散化&組合

    剛開始覺得,機器學習公司里有現成的包可以調用,然后把數據灌進去就好了,機器學習到底有啥搞頭呢? 后來才搞明白,現實中,機器學習里面重要的一環其實就是搞“特征工程”,如果你對數據有足夠的敏銳,能抽取出一些有效的特征,往往比算法本身的優化來得有效得多。怎么抽取特征這里就不多說,這里所說常見的特征處理方法:離散化和特征組合。

    離散化

    離散化就是把數值型特征離散化到幾個固定的區間段。比如說成績0-100,離散化成A、B、C、D四檔,然后用4個01特征來one-hot編碼,比如
    A為1,0,0,0
    B為0,1,0,0
    C為0,0,1,0
    D為0,0,0,1
    那第一位就表示是否為A,第二位表示是否為B……
    這里起到的作用就是減少過擬合,畢竟95和96分的兩個學生能力不見得就一定有差別,但是A的學生跟D的比起來還是有明顯差別的。其實就是把線性函數轉換成分段階躍函數了。

    另外一種,比如把汽車時速按10公里/小時之類的分一些檔,就像這樣:
    0-10
    10-20
    20-30
    ……

    如果現在我們想學習的目標是油耗

    這里以某款國內比較熱銷的車型做了下面的幾項測試:
    120km/h勻速行駛時,油耗為7.81升/100km
    90km/h勻速行駛時, 油耗為5.86升/100km
    60km/h勻速行駛時, 油耗為4.12升/100km
    30km/h勻速行駛時 ,油耗為4.10升/100km

    顯然油耗不是線性的,不離散化肯定不行。仔細想想,這樣離散化之后,其實可以近似擬合任意函數了。

    特征組合

    特征組合就比較簡單,比如現在有兩個特征A和B,再新增一個A and B的特征。

    小結

    LR的劣勢就是線性模型的線性假設過強,但我們發現通過上面這些trick,其實也可以學習”非線性“的特征,大大增強了LR的能力,所以LR才能這么流行。

    高緯度01特征

    就是one-hot編碼,上面就用了。
    還有一個優點沒提到,就是沒有數據歸一化(標準化)的問題。
    高緯度的特征我們一般不會存一個<特征名,下標值>這樣一個hashmap,而是直接用
    哈希(特征名)%特征數
    以前還以為這樣做是因為在算法預測能力上會有神奇的提升,結果不是,只是出于工程方便的考慮。
    好處只是少維護了一個索引,方便多了。當然,哈希沖突是有的,而且這個對算法是有害的,只不過沖突一般比較少,還hold得住。這里有個資料(http://scikit-learn.org/stable/modules/generated/sklearn.feature_extraction.text.HashingVectorizer.html#sklearn.feature_extraction.text.HashingVectorizer)不錯,說的是處理文本,其實對LR也一樣。

    正負樣本不均衡問題

    (注意這里只討論LR,不要亂推廣到其他算法)感覺怎么這問題有點像”玄學”了,坊間通用的說法是樣本太不均衡是會有問題的,正負樣本比例多大合適? 一些經驗主義的說法是頂多負樣本是正樣本的幾(5以內吧)倍。
    這問題的分析,顯然要從loss function入手。
    假設現在負樣本復制多一份,從loss function的角度看來,就是負樣本的cost前面乘以2,這個2其實可以當做負樣本的權重。所以,誰樣本多,誰占的權重其實就大一些。要看看loss function的優化目標是不是跟你的目標一致,如果正負樣本對你來說一樣重要,那可以不用管,但通常都不是,所以是個問題。通常情況都是比較少的樣本反而比較重要的,這真是一個大問題。假設正負樣本是1:1w,你關心的是正樣本,直接學出來的模型可能就直接把樣本全判別為負樣本。但這顯然不是你想要的結果。

    像我這樣的懶人,直覺是覺得保持1:1最好,或者說至少沒壞處。那通常采用的方法就是up-sampling或者down-sampling,具體操作方法很簡單,少的樣本復制多份,或者多的樣本只抽樣一些。但我感覺前者容易過擬合,后者數據利用得又不夠充分。難道咸魚與熊掌就不可得兼?后來某大牛指點了一下,告訴我一個簡單的trick:

    用down-sampling,然后采樣多次,訓練多個模型,跟隨機森林一樣,求個平均即可

    這里還有另外一個問題,我們知道LR學出來是一個概率值,樣本不均衡,我們調一下閾值不就行了么?比如從原來的0.5調整到0.3,這樣就會多判斷一些正樣本,唯一的問題就是樣本不均衡時候的分類邊界跟均衡時的邊界平行么?
    好吧,作為一個懶惰的“工程學派”,懶得去推到公式從理論上去證明,還是來做個直觀的實驗吧。

    用R語言來做。我知道用R比較簡單,但是R本身我不熟,還要google一番+?<函數名> 命令,勉強還是把代碼擼出來了。代碼邏輯很簡單,自己定好一個斜率K=5,然后在邊界上下生成一些隨機數,高斯分布,均勻分布都可以。

    <code class="language-r hljs has-numbering"> LABEL_1_NUM <- <span class="hljs-number">100</span> LABEL_0_NUM <- <span class="hljs-number">100</span>K <- <span class="hljs-number">5</span>x1 <-runif(LABEL_1_NUM, <span class="hljs-number">0</span>, <span class="hljs-number">10</span>) x2 <-runif(LABEL_0_NUM , <span class="hljs-number">0</span>, <span class="hljs-number">10</span>)D <-<span class="hljs-number">1</span> x2 <- rep(x2,D) Y <- c( x1* K + rnorm(LABEL_1_NUM, mean=<span class="hljs-number">15</span>, sd=<span class="hljs-number">19</span>), x2 * K + rnorm(LABEL_0_NUM, mean=-<span class="hljs-number">15</span>, sd=<span class="hljs-number">19</span>) ) <span class="hljs-comment">#Y <- c( x1* K + runif(LABEL_1_NUM, min=-15, max=50), x2 * K + runif(LABEL_0_NUM, min=-50, max=15) )</span>X <- c( x1, x2 ) label <- as.factor( c(rep(<span class="hljs-number">1</span>,LABEL_1_NUM), rep(<span class="hljs-number">0</span>,LABEL_0_NUM*D) ) )data <- data.frame(X,Y, label)model <- glm(label~Y+X, data=data, family=<span class="hljs-string">'binomial'</span>, control = list(maxit = <span class="hljs-number">600</span>))plot( data$X , data$Y , type=<span class="hljs-string">"p"</span>, pch=<span class="hljs-number">19</span>, col=<span class="hljs-string">"red"</span>) points( data$X[ data$label==<span class="hljs-number">1</span>], data$Y[ data$label==<span class="hljs-number">1</span>], type=<span class="hljs-string">"p"</span>, pch=<span class="hljs-number">19</span>, col=<span class="hljs-string">"blue"</span>) points( data$X[ data$label==<span class="hljs-number">0</span>], data$Y[ data$label==<span class="hljs-number">0</span>], type=<span class="hljs-string">"p"</span>, pch=<span class="hljs-number">19</span>, col=<span class="hljs-string">"red"</span>) co = coef(model) lines(c(<span class="hljs-number">0</span>,<span class="hljs-number">100</span>),c(-co[<span class="hljs-number">1</span>]/co[<span class="hljs-number">2</span>], -(co[<span class="hljs-number">1</span>]+co[<span class="hljs-number">3</span>]*<span class="hljs-number">100</span>)/co[<span class="hljs-number">2</span>]), type=<span class="hljs-string">"l"</span>, col=<span class="hljs-string">'green'</span>, lwd=<span class="hljs-number">3</span>)print(co) <span class="hljs-comment">#截距</span> print(-co[<span class="hljs-number">1</span>]/co[<span class="hljs-number">2</span>]) <span class="hljs-comment">#斜率</span> print(-co[<span class="hljs-number">3</span>]/co[<span class="hljs-number">2</span>]) </code><ul class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li><li>27</li><li>28</li><li>29</li><li>30</li><li>31</li><li>32</li><li>33</li><li>34</li></ul><div class="save_code tracking-ad" style="display: none;" data-mod="popu_249"><a target=_blank href="javascript:;" target="_blank"><img src="http://static.blog.csdn.net/images/save_snippets.png" alt="" /></a></div><ul class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li><li>27</li><li>28</li><li>29</li><li>30</li><li>31</li><li>32</li><li>33</li><li>34</li></ul>


    正負 100:100


    正負 100:1000

    有點遺憾,采樣多次取平均,斜率居然都是5左右。后來想想,負樣本多的時候,其實正樣本都不用怎么看了,而負樣本形成的帶狀物,邊緣斜率肯定也是接近5。
    改變方法,負樣本生成的時候斜率改成-K,然后標準差調大一些。這樣分類邊界應該是Y=0。


    注意,一定要多抽樣幾次。能發現,負樣本多的話,邊界還是會向下偏一些的(至少比1:1的時候。 斜率 (-∞, -1] vs [-1,1] )。這個問題能舉一個反例證明就夠了。注意這里為了方便展示,取的只有2維,高維的就更不好說了。不過這里還發現,邊界向下其實偏離得不會特別大,LR還是有一些容錯能力的,但比賽的話,能提升0.5%都已經很不錯了。

    總結

    以上是生活随笔為你收集整理的LR模型常见问题小议的全部內容,希望文章能夠幫你解決所遇到的問題。

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