从零构建机器学习模型(二)sklearn特征提取源码分析

<开场白>(*´゚∀゚`)ノ 不存在的


1.1.6 实践操作特征选择

上一篇可能抽象的东西比较多,我们现在从代码的角度分析一下整个特征选择的部分。

Python的Sklearn库中有一个包feature_selection主要就是做特征提取的,我们从这个包具体地看一下这个问题。

Sklearn中主要提供五种特征选取的方法,分别代表了不同的特征选择方式:

a.移除低方差的特征(Removing features with low variance)(filter方式):

v2-340b2ecdd7e8f8ecc3e0e06121b83ab5_hd.jpg
v2-05b136b76a96edb298e7b277ddfbc915_hd.jpg

这里VarianceThreshold类直接继承base包下的BaseEstimator,间接继承本包下的SelectorMixin

BaseEstimator主要是一些参数方法(get,set)以及打印版本等功能块:

v2-43b17d8392878453fb4163fc289c2d7b_hd.jpg

例如上图这个静态私有的_get_param_names方法为公有函数提供参数检查。

  1. init先通过反射加载cls实例的deprecated信息,也就是检查函数是否版本过期并在不存在时为init赋值构造函数;
  2. signature为init构造体提供函数信息及函数绑定检查;
  3. parameters遍历init实例Init_signature的parameters字段值并取出除self(也就是实例自身,类函数第一参数)及变量key字段(因为signature返回tuple);
  4. 最后返回param的排序名称;

而该方法内的signature结构如下:

v2-653a1893d6d880283b47e61d8d8964c8_hd.jpg

这部分和python inspect里的signature不太一样,先检查obj是否有callable方法,也就是是否有函数名直接调用的call方法,而后检查传入的obj是否是绑定好的实例方法,sig=signature(obj.func)则为obj内部每个方法提供递归的检查。后续的步骤应该是为实例添加参数绑定,将未绑定的参数的第一项作为self绑定实例,若存在则将都需的转化为tuple也就是*param的类型。总的来说这部分提供了参数的标准化。

后面的部分也都类似,依次检查obj是否属于FunctionType函数,functools.partial偏函数,type类或元类等等。

而SelectorMixin则有比较详细的说明文档doc

v2-c2db05d2c1dc44fa0cf70e086be827a0_hd.jpg

用来返回一个提取特征的mask。内部的基本原理是一个调用自身抽象函数_get_support_mask的get_support函数作为正变换transform和反变换inverse_transform的基础,而这个抽象函数会在继承类中依据不同的类方法重写。正变换transform和反变换inverse_transform的功能主要有检查sparse的性质并做参数检查,而后返回safe_mask。

而后的VarianceThreshold类则是一个标准的fit流程:

v2-3018a070032c320696bfb8ecf7f5bf87_hd.jpg

分别是:

  1. 构建初始化的threshold;
  2. 检查数据类型并依据类型求出方差variance,这里主要是因为稀疏矩阵有自己的variance库,而dense则可以直接求(这里的check_array在init里导入validation下的check_array,可能是出于这个函数用的比较多吧);
  3. 错误检查;
  4. 重写抽象方法_get_support_mask;
v2-428c5acd1eb15c8981f8f3f4cf4412bd_hd.jpg

其中check_is_fitted主要就是检查一下实例和属性的正常:

v2-e6278838c4b5dab8039284a8254baec0_hd.jpg

最后用self.variance>self.threshold做返回。整体涉及算法的部分很少,主要还是在框架下作了很多的数据转换以及检验的部分。其实就是在体现以用户为中心的思路,保证对不同数据源的Robust性质。

b.单变量特征选择(Univariate feature selection)(filter方法)

Univariate feature selection的类和函数都写在了init下面,不过原始的定义还是在univariate_selection里面,我们可以简单看一下比较常用的卡方检验,documentation的实例如下:

v2-f251de52531f8ec74d45d75f7bbeeb28_hd.jpg

chi2就是卡方检验函数

v2-9f69189376826883217817e16255e15f_hd.jpg

v2-441f82fca7cc47f70ce4e0b786a1cb74_hd.jpg

里面包括数据格式化,二值变换以及卡方值计算,对照卡方公式看就好。

SelectKbest用传入的score函数初始化,并重写了继承_BaseFilter类下的_check_params和以及_BaseFilter继承SelectorMixin的_get_support_mask接口,而后添加工厂模式的topk特征选择,当然这里做了个小优化:

v2-9430647950261a45a8597ab4a0e4157c_hd.jpg

也就是说当k取0或all的时候不进行处理,算个小trick吧。

继承自_BaseFilter类下的fit函数将score规范化成输出,而继承自SelectorMixin的transform则进行正变换成标准mask输出。最后的结果就如同示例所示。

最后注意selectKbest实可以自定义score函数的,只要将输入的score函数替换为想要的函数表达式或者函数就可以。

例如下面用lambda表达式计算pearson相关系数作为score的函数

SelectKBest(lambda X, Y: array(map(lambda x:pearsonr(x, Y), X.T)).T, k=2).fit_transform(iris.data, iris.target)

再比如下面利用互信息计算score分数

SelectKBest(lambda X, Y: array(map(lambda x:mic(x, Y), X.T)).T, k=2).fit_transform(iris.data, iris.target)

因为SelectKBest的写法中score函数与SelectKBest框架是分离的,所以可以作为自由发挥的拓展。

c.递归特征消除(Recursive feature elimination)(wrapper)

递归消除特征法的原理其实就是使用一个基模型来进行多轮训练,每轮训练后,消除若干权值系数的特征,再基于新的特征集进行下一轮训练。类似于boosting的思路,例如用线性回归作为基分类器,对特征进行回归并抹除小系数特征做类似降维的行为,再用新的特征集重复回归。这也就是为什么官方说“递归特征消除 ([RFE](https://link.zhihu.com/?target=http%3A//sklearn.lzjqsdd.com/modules/generated/sklearn.feature_selection.RFE.html%23sklearn.feature_selection.RFE))通过递归减少考察的特征集规模来选择特征”。不过可能计算复杂度比较大,基分类器选取也有问题,没有见到很多用的。等以后用到的时候再补充了。

d.使用SelectFromModel选择特征(Feature selection using SelectFromModel)(Embedding)

这个就是带regularize的特征选择了,不同于其他的是这里的threshold相当于全局threshold而不是单个特征的。具体代码等下一部分说完regularize再讨论好了,这一章内容到知乎上限了…………(╯‵□′)╯︵┻━┻

两种基础模型

d1.基于L1的特征选择(L1-based feature selection)

d2.基于树的特征选择(Tree-based feature selection)

以及其拓展结合L2惩罚项来优化可以参考这位老哥的知乎:

特征工程到底是什么?

e.特征选择融入pipeline(Feature selection as part of a pipeline)

pipeline,没什么好说的,Linux和Python最常用的东西。


今天就不讲具体的结构了,内容好像有点多知乎上传不了,等下次吧。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345

推荐阅读更多精彩内容