LR模型常见问题小议

标签: LR机器学习
2016-01-10 23:33 671人阅读 评论(0) 收藏 举报
本文章已收录于:
分类:
机器学习(10)

作者同类文章X

版权声明:本文为博主原创文章,转载请注明出处。

目录(?)[+]

  1. 数据归一化
  2. 特征离散化组合
    1. 离散化
    2. 特征组合
    3. 小结
  3. 高纬度01特征
  4. 正负样本不均衡问题

// 毕竟不是什么大牛,只是总结一下自己的一些认识和想法,如果有不正确的,还请大牛们斧正。

经常说的2/8原则,LR肯定就是能解决80%问题中那20%的工具。所以LR还是值得好好研究的。发现以前对LR重视不够,总想着赶紧把其他算法也学了,才能拉小跟同事之间机器学习的gap。其实LR用得还是挺多的,而且效果还是不错的。一些高大上的算法,在公司这种大数据面前不一定跑得动,即使跑得动,效果也不一定好,而且还有可解释性和工程维护方面复杂度的问题。这倒是挺残酷的现实。

发现学完coursera的机器学习课程后,离具体实践还是有不少距离,也没找到什么好的资料可以学习(如果谁发现有的话,麻烦告诉我一声吧),耳濡目染了一些奇技淫巧,总结一下,有一些其实之前的笔记也零散提到了。

数据归一化

仔细区分的话,有两种:

  1. 归一化: (x-最小值)/(最大值-最小值)
  2. 标准化: (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模型常见问题小议相关推荐

  1. 逻辑回归LR模型简介

    1. 定义 LR是线性二分类模型,也是广义的线性回归模型,可以计算某个样本特征下事件发生的概率. 假设数据服从伯努力分布,通过极大化似然函数的方法,运用梯度下降求解参数,来达到将数据二分类的目的. 1 ...

  2. Sklearn参数详解—LR模型

    总第105篇 最近会开始一个新的系列,sklearn库中各模型的参数解释,本篇主要讲述最基础的LR模型. 模型参数详解 逻辑回归: sklearn.linear_model.LogisticRegre ...

  3. Facebook的GBDT+LR模型python代码实现

    承接上篇讲解,本文代码,讲解看上篇 目标:GBDT+LR模型 步骤:GBDT+OneHot+LR 测试数据:iris 代码: 结果比较:与直接GBDT模型的比较 目标:GBDT+LR模型 实现GBDT ...

  4. 神经网络思想建立LR模型(DL公开课第二周答案)

    上海站 | 高性能计算之GPU CUDA培训 4月13-15日 三天密集式学习  快速带你晋级 阅读全文 > 正文共6603个字,3张图,预计阅读时间17分钟. LR回顾 LR计算图求导 算法结 ...

  5. c++ vector排序_个性化推荐系统源代码之基于LR模型的推荐系统离线排序方案

    排序流程包括离线排序和在线排序: 离线排序 读取前天(第 T - 2 天)之前的用户行为数据作为训练集,对离线模型进行训练:训练完成后,读取昨天(第 T - 1 天)的用户行为数据作为验证集进行预测, ...

  6. 推荐系统 | 基础推荐模型 | GBDT+LR模型 | Python实现

    基础推荐模型--传送门: 推荐系统 | 基础推荐模型 | 协同过滤 | UserCF与ItemCF的Python实现及优化 推荐系统 | 基础推荐模型 | 矩阵分解模型 | 隐语义模型 | PyTor ...

  7. 模型常见问题及规范--模型制作PBR流程规范规范

    链接: 美术 2.5 模型常见问题及规范笔记. 链接: 美术 2.7 Metallic与Speculer流程. 模型制作规范 模型制作流程 模型制作规范 示例 图例 软件初始设置 统一单位 所有制作软 ...

  8. 传统推荐算法Facebook的GBDT+LR模型深入理解

    目标: 深入理解Facebook 2014年提出的的GBDT+LR模型. CSDN上泛泛而谈的文章很多,真正讲解透彻的没几篇.争取我这篇能讲解透彻. 今晚又想了许久,想通了一些原理.也分享出来. 算法 ...

  9. XGBOOST + LR 模型融合 python 代码

    XGBOOST + LR (XGBOOST grid search) 先留个广告,最近做一个数据挖掘的比赛,主要用的就是 xgboost,等比赛完后年前好好整理代码开源,到时候代码会比下面整份完整. ...

最新文章

  1. tinybert华为
  2. Ubuntu任务栏Tint2安装与使用
  3. 动态添加 ajax,ajax动态的添加内容【原创】
  4. FFmpeg源代码:avcodec_receive_frame
  5. 1224 哥德巴赫猜想(2)
  6. ef mysql 的坑_C# EF 与 MySql 的那些坑
  7. 微机原理换行代码_微机原理课程设计——汇编输出杨辉三角
  8. Java Redis 连接池 Jedis 工具类,java基础面试笔试题
  9. 3-1-Servlet技术
  10. axis 开发webservice
  11. 读 zepto 源码之工具函数
  12. activex java 控件_swt java 内嵌ActiveX控件
  13. 费马定理中值定理_长盛不衰的法国数学|费马
  14. scratch编程作品展示
  15. 什么时候都要记得:生活愈是往下,嘴角愈要上扬
  16. Python 调用JSON接口实例
  17. 钉钉本地开发环境配置(H5微应用)
  18. 新版悟能口罩预约小程序源码V1.1.1
  19. 又一个程序猿的奋斗史——第五章 苦逼的宿舍条件
  20. 【计科快速入门】一、计算机早期历史

热门文章

  1. hashlist java_java中集合类HashSet、ArrayList、LinkedList总结
  2. lisp 焊接符号标注_焊接符号标注大全
  3. excel分类_Excel数据处理学习(七)使用分类汇总
  4. 计划完成提醒系统C语言,通信录管理计划系统C语言知识程序设计.doc
  5. 数学知识复习:二阶导复合函数的链式法则
  6. pytorch 学习笔记:nn.Sequential构造神经网络
  7. 产品经理经验谈50篇(三):在设定产品的功能优先级时,有哪些指导性原则与依据?
  8. tableau必知必会之用蝴蝶图(旋风图)实现数据之间对比
  9. hc05与单片机连接图_单片机科普:单片机的IO口不够用了怎么办?如何扩展单片机的IO口...
  10. Python入门100题 | 第013题