选择 scikit-learn

训练模型:

步骤:

先计算正向词 负向词  PMI 算共现频率  选择更多的 正向词, 负向词

标注正常词 和 负向词 在训练集里面出现的 one-hot 词向量

SKlearn  LogisticRegression 逻辑回归分类

 

 

构建一个基于scikit-learn 的 perceptron
读取数据 – iris
分配训练集和测试集
标准化特征值
训练感知器模型
用训练好的模型进行预测
计算性能指标
描绘分类界面

import os
import pickle
import matplotlib as mpl 
mpl.use('Agg')
import matplotlib.pyplot as plt 
import numpy as np
import pandas as pd
import seaborn as sns 
from sklearn.ensemble import AdaBoostClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.linear_model import Perceptron
from sklearn.linear_model import SGDClassifier
from sklearn.model_selection import KFold, cross_val_score, train_test_split
from sklearn.model_selection import learning_curve
from sklearn.naive_bayes import GaussianNB
from sklearn.neighbors import KNeighborsClassifier
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC, LinearSVC
from sklearn.tree import DecisionTreeClassifier
from sklearn.utils import column_or_1d
from sklearn.utils import shuffle
import Preprocessor

代码分析:

matplotlib:

Python 的 2D绘图库

numpy

高性能科学 和数据分析的基础包

pandas

pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的

sklearn

Adaboost

AdaBoostClassifier : 分类

AdaBoostRegressor: 回归

参数:

1)base_estimator:AdaBoostClassifier和AdaBoostRegressor都有,即我们的弱分类学习器或者弱回归学习器。理论上可以选择任何一个分类或者回归学习器,不过需要支持样本权重。我们常用的一般是CART决策树或者神经网络MLP。默认是决策树,即AdaBoostClassifier默认使用CART分类树DecisionTreeClassifier,而AdaBoostRegressor默认使用CART回归树DecisionTreeRegressor。另外有一个要注意的点是,如果我们选择的AdaBoostClassifier算法是SAMME.R,则我们的弱分类学习器还需要支持概率预测,也就是在scikit-learn中弱分类学习器对应的预测方法除了predict还需要有predict_proba。

 

2)algorithm:这个参数只有AdaBoostClassifier有。主要原因是scikit-learn实现了两种Adaboost分类算法,SAMME和SAMME.R。两者的主要区别是弱学习器权重的度量,SAMME使用了和我们的原理篇里二元分类Adaboost算法的扩展,即用对样本集分类效果作为弱学习器权重,而SAMME.R使用了对样本集分类的预测概率大小来作为弱学习器权重。由于SAMME.R使用了概率度量的连续值,迭代一般比SAMME快,因此AdaBoostClassifier的默认算法algorithm的值也是SAMME.R。我们一般使用默认的SAMME.R就够了,但是要注意的是使用了SAMME.R, 则弱分类学习器参数base_estimator必须限制使用支持概率预测的分类器。SAMME算法则没有这个限制。

 

3)loss:这个参数只有AdaBoostRegressor有,Adaboost.R2算法需要用到。有线性‘linear’, 平方‘square’和指数 ‘exponential’三种选择, 默认是线性,一般使用线性就足够了,除非你怀疑这个参数导致拟合程度不好。这个值的意义在原理篇我们也讲到了,它对应了我们对第k个弱分类器的中第i个样本的误差的处理,即:如果是线性误差,则eki=|yiGk(xi)|Ekeki=|yi−Gk(xi)|Ek;如果是平方误差,则eki=(yiGk(xi))2E2keki=(yi−Gk(xi))2Ek2,如果是指数误差,则eki=1expyi+Gk(xi))Ekeki=1−exp(−yi+Gk(xi))Ek)EkEk为训练集上的最大误差Ek=max|yiGk(xi)|i=1,2…mEk=max|yi−Gk(xi)|i=1,2…m

 

4) n_estimators: AdaBoostClassifier和AdaBoostRegressor都有,就是我们的弱学习器的最大迭代次数,或者说最大的弱学习器的个数。一般来说n_estimators太小,容易欠拟合,n_estimators太大,又容易过拟合,一般选择一个适中的数值。默认是50。在实际调参的过程中,我们常常将n_estimators和下面介绍的参数learning_rate一起考虑。

 

5) learning_rate:  AdaBoostClassifier和AdaBoostRegressor都有,即每个弱学习器的权重缩减系数νν,在原理篇的正则化章节我们也讲到了,加上了正则化项,我们的强学习器的迭代公式为fk(x)=fk1(x)+ναkGk(x)fk(x)=fk−1(x)+ναkGk(x)νν的取值范围为0<ν10<ν≤1。对于同样的训练集拟合效果,较小的νν意味着我们需要更多的弱学习器的迭代次数。通常我们用步长和迭代最大次数一起来决定算法的拟合效果。所以这两个参数n_estimators和learning_rate要一起调参。一般来说,可以从一个小一点的νν开始调参,默认是1。

 

RandomForest

的分类类是RandomForestClassifier

回归类是RandomForestRegressor

需要调参的参数包括两部分

第一部分是Bagging框架的参数

第二部分是CART决策树的参数

n_estimators=10:决策树的个数,越多越好,但是性能就会越差,至少100左右(具体数字忘记从哪里来的了)可以达到可接受的性能和误差率。

bootstrap=True:是否有放回的采样。

oob_score=False:oob(out of band,带外)数据,即:在某次决策树训练中没有被bootstrap选中的数据。多单个模型的参数训练,我们知道可以用cross validation(cv)来进行,但是特别消耗时间,而且对于随机森林这种情况也没有大的必要,所以就用这个数据对决策树模型进行验证,算是一个简单的交叉验证。性能消耗小,但是效果不错。

n_jobs=1:并行job个数。这个在ensemble算法中非常重要,尤其是bagging(而非boosting,因为boosting的每次迭代之间有影响,所以很难进行并行化),因为可以并行从而提高性能。1=不并行;n:n个并行;-1:CPU有多少core,就启动多少job warm_start=False:热启动,决定是否使用上次调用该类的结果然后增加新的。

class_weight=None:各个label的权重。

 

 

LogisticRegression

在scikit-learn中,与逻辑回归有关的主要是这3个类。LogisticRegression, LogisticRegressionCV 和logistic_regression_path。其中LogisticRegression和LogisticRegressionCV的主要区别是LogisticRegressionCV使用了交叉验证来选择正则化系数C。而LogisticRegression需要自己每次指定一个正则化系数。除了交叉验证,以及选择正则化系数C以外, LogisticRegression和LogisticRegressionCV的使用方法基本相同。

logistic_regression_path类则比较特殊,它拟合数据后,不能直接来做预测,只能为拟合数据选择合适逻辑回归的系数和正则化系数。主要是用在模型选择的时候。一般情况用不到这个类,所以后面不再讲述logistic_regression_path类。

此外,scikit-learn里面有个容易让人误解的类RandomizedLogisticRegression,虽然名字里有逻辑回归的词,但是主要是用L1正则化的逻辑回归来做特征选择的,属于维度规约的算法类,不属于我们常说的分类算法的范畴。

后面的讲解主要围绕LogisticRegression和LogisticRegressionCV中的重要参数的选择来来展开,这些参数的意义在这两个类中都是一样的。

2. 正则化选择参数:penalty

LogisticRegression和LogisticRegressionCV默认就带了正则化项。penalty参数可选择的值为”l1″和”l2″.分别对应L1的正则化和L2的正则化,默认是L2的正则化。

在调参时如果我们主要的目的只是为了解决过拟合,一般penalty选择L2正则化就够了。但是如果选择L2正则化发现还是过拟合,即预测效果差的时候,就可以考虑L1正则化。另外,如果模型的特征非常多,我们希望一些不重要的特征系数归零,从而让模型系数稀疏化的话,也可以使用L1正则化。

penalty参数的选择会影响我们损失函数优化算法的选择。即参数solver的选择,如果是L2正则化,那么4种可选的算法{‘newton-cg’, ‘lbfgs’, ‘liblinear’, ‘sag’}都可以选择。但是如果penalty是L1正则化的话,就只能选择‘liblinear’了。这是因为L1正则化的损失函数不是连续可导的,而{‘newton-cg’, ‘lbfgs’,‘sag’}这三种优化算法时都需要损失函数的一阶或者二阶连续导数。而‘liblinear’并没有这个依赖。

具体使用了这4个算法有什么不同以及有什么影响我们下一节讲。

3. 优化算法选择参数:solver

solver参数决定了我们对逻辑回归损失函数的优化方法,有4种算法可以选择,分别是:

a) liblinear:使用了开源的liblinear库实现,内部使用了坐标轴下降法来迭代优化损失函数。

b) lbfgs:拟牛顿法的一种,利用损失函数二阶导数矩阵即海森矩阵来迭代优化损失函数。

c) newton-cg:也是牛顿法家族的一种,利用损失函数二阶导数矩阵即海森矩阵来迭代优化损失函数。

d) sag:即随机平均梯度下降,是梯度下降法的变种,和普通梯度下降法的区别是每次迭代仅仅用一部分的样本来计算梯度,适合于样本数据多的时候,SAG是一种线性收敛算法,这个速度远比SGD快。关于SAG的理解,参考博文线性收敛的随机优化算法之 SAG、SVRG(随机梯度下降)

 

从上面的描述可以看出,newton-cg, lbfgs和sag这三种优化算法时都需要损失函数的一阶或者二阶连续导数,因此不能用于没有连续导数的L1正则化,只能用于L2正则化。而liblinear通吃L1正则化和L2正则化。

同时,sag每次仅仅使用了部分样本进行梯度迭代,所以当样本量少的时候不要选择它,而如果样本量非常大,比如大于10万,sag是第一选择。但是sag不能用于L1正则化,所以当你有大量的样本,又需要L1正则化的话就要自己做取舍了。要么通过对样本采样来降低样本量,要么回到L2正则化。

在sklearn的官方文档中,对于solver的使用说明如下:

In a nutshell, one may choose the solver with the following rules:

Case Solver
Small dataset or L1 penalty “liblinear”
Multinomial loss or large dataset “lbfgs”, “sag” or “newton-cg”
Very Large dataset “sag”

 

从上面的描述,大家可能觉得,既然newton-cg, lbfgs和sag这么多限制,如果不是大样本,我们选择liblinear不就行了嘛!错,因为liblinear也有自己的弱点!我们知道,逻辑回归有二元逻辑回归和多元逻辑回归。对于多元逻辑回归常见的有one-vs-rest(OvR)和many-vs-many(MvM)两种。而MvM一般比OvR分类相对准确一些。郁闷的是liblinear只支持OvR,不支持MvM,这样如果我们需要相对精确的多元逻辑回归时,就不能选择liblinear了。也意味着如果我们需要相对精确的多元逻辑回归不能使用L1正则化了。

总结而言,liblinear支持L1和L2,只支持OvR做多分类,“lbfgs”, “sag” “newton-cg”只支持L2,支持OvR和MvM做多分类。

具体OvR和MvM有什么不同我们下一节讲。

4. 分类方式选择参数:multi_class

multi_class参数决定了我们分类方式的选择,有 ovr和multinomial两个值可以选择,默认是 ovr。

ovr即前面提到的one-vs-rest(OvR),而multinomial即前面提到的many-vs-many(MvM)。如果是二元逻辑回归,ovr和multinomial并没有任何区别,区别主要在多元逻辑回归上。

OvR的思想很简单,无论你是多少元逻辑回归,我们都可以看做二元逻辑回归。具体做法是,对于第K类的分类决策,我们把所有第K类的样本作为正例,除了第K类样本以外的所有样本都作为负例,然后在上面做二元逻辑回归,得到第K类的分类模型。其他类的分类模型获得以此类推。

而MvM则相对复杂,这里举MvM的特例one-vs-one(OvO)作讲解。如果模型有T类,我们每次在所有的T类样本里面选择两类样本出来,不妨记为T1类和T2类,把所有的输出为T1和T2的样本放在一起,把T1作为正例,T2作为负例,进行二元逻辑回归,得到模型参数。我们一共需要T(T-1)/2次分类。

从上面的描述可以看出OvR相对简单,但分类效果相对略差(这里指大多数样本分布情况,某些样本分布下OvR可能更好)。而MvM分类相对精确,但是分类速度没有OvR快。

如果选择了ovr,则4种损失函数的优化方法liblinear,newton-cg, lbfgs和sag都可以选择。但是如果选择了multinomial,则只能选择newton-cg, lbfgs和sag了。

5. 类型权重参数: class_weight

class_weight参数用于标示分类模型中各种类型的权重,可以不输入,即不考虑权重,或者说所有类型的权重一样。如果选择输入的话,可以选择balanced让类库自己计算类型权重,或者我们自己输入各个类型的权重,比如对于0,1的二元模型,我们可以定义class_weight={0:0.9, 1:0.1},这样类型0的权重为90%,而类型1的权重为10%。

如果class_weight选择balanced,那么类库会根据训练样本量来计算权重。某种类型样本量越多,则权重越低,样本量越少,则权重越高。

sklearn的官方文档中,当class_weight为balanced时,类权重计算方法如下:

n_samples / (n_classes * np.bincount(y)),n_samples为样本数,n_classes为类别数量,np.bincount(y)会输出每个类的样本数,例如y=[1,0,0,1,1],则np.bincount(y)=[2,3]

那么class_weight有什么作用呢?在分类模型中,我们经常会遇到两类问题:

第一种是误分类的代价很高。比如对合法用户和非法用户进行分类,将非法用户分类为合法用户的代价很高,我们宁愿将合法用户分类为非法用户,这时可以人工再甄别,但是却不愿将非法用户分类为合法用户。这时,我们可以适当提高非法用户的权重。

第二种是样本是高度失衡的,比如我们有合法用户和非法用户的二元样本数据10000条,里面合法用户有9995条,非法用户只有5条,如果我们不考虑权重,则我们可以将所有的测试集都预测为合法用户,这样预测准确率理论上有99.95%,但是却没有任何意义。这时,我们可以选择balanced,让类库自动提高非法用户样本的权重。

提高了某种分类的权重,相比不考虑权重,会有更多的样本分类划分到高权重的类别,从而可以解决上面两类问题。

当然,对于第二种样本失衡的情况,我们还可以考虑用下一节讲到的样本权重参数: sample_weight,而不使用class_weight。sample_weight在下一节讲。

6. 样本权重参数: sample_weight

上一节我们提到了样本不失衡的问题,由于样本不平衡,导致样本不是总体样本的无偏估计,从而可能导致我们的模型预测能力下降。遇到这种情况,我们可以通过调节样本权重来尝试解决这个问题。调节样本权重的方法有两种,第一种是在class_weight使用balanced。第二种是在调用fit函数时,通过sample_weight来自己调节每个样本权重。

在scikit-learn做逻辑回归时,如果上面两种方法都用到了,那么样本的真正权重是class_weight*sample_weight.

以上就是scikit-learn中逻辑回归类库调参的一个小结,还有些参数比如正则化参数C(交叉验证就是 Cs),迭代次数max_iter等,由于和其它的算法类库并没有特别不同,这里不多累述了。

 

 

 

Perceptron

SGDClassifier

KFold

cross_val_score

train_test_split

learning_curve

GaussianNB

KNeighborsClassifier

Pipeline

 

StandardScaler

LinearSVC

DecisionTreeClassifier

column_or_1d

 

column_or_1d

shuffle

关于PMI

PMI, 是互信息(NMI)中的一种特例, 而互信息,是源于信息论中的一个概念,主要用于衡量2个信号的关联程度.至于PMI,是在文本处理中,用于计算两个词语之间的关联程度.比起传统的相似度计算, pmi的好处在于,从统计的角度发现词语共现的情况来分析出词语间是否存在语义相关 , 或者主题相关的情况.

场景实例

说起接触PMI的原因,是我在一个主题词挖掘研究的时候, 想到能否融入pmi,以增强主题词的特征.于是乎, 我寻找了一些文献材料,其中不少印证了pmi具有这样的功能,我可以分享当中的一篇:
基于互信息的文本自动摘要_刘星含
当时,我们需要做的工作是聚集微博中的热点事件, 然后抽取主题词.以”六小龄童上春晚”主题为例, 我收集了9条热门微博,分别如下:

1.郭富城方发声明否认炒作,真的是这样吗?我发布了头条文章:《罗生门:六小龄童上春晚究竟谁炒作?从这开8并怀念当年那美好的西游》 
2.除夕还剩几天时间,这几天“猴哥”#六小龄童#突然成为网络热搜词,朋友圈全是“帮猴哥上春晚”的帖子。在充当“自来水”的同时,有人开始反思,“大圣”热闹上春晚话题是不是一种“情怀绑架”?有网友说“这年头,似乎打上情怀的标签,都能把一个看似毫无逻辑的事,套上隆重的仪式感,煽动起某种情绪。 
​3.呼吁六小龄童老师上春晚是好事,是人人盼望之事,但是不要被人牵着鼻子走,像央视张立,借着六小龄童老师炒作自己,中伤他人,这对章老师本人也不是益事,更不会促进什么期望实现。 
4.发布了头条文章:《六小龄童,你真的不配上春晚!》 这两天大家都在为六小龄童鸣不平,咱说句公道话,六小龄童,你不配上春晚!别急着拍砖,听我细细道来!〔希望能静下来看完内容再评论〕[微笑] 
5.凡事物极必反,现在给央视的舆论压力足够大了,甚至有点过了,而且我觉得现在最大的受害者还是六小龄童老师,不管最后上不上春晚,六小龄童老师现在估计都十分尴尬。大家可以稍微缓一缓,毕竟春晚的不可预测性是有太多先例的,04年那次六小龄童老师还是腊月28才接到通知临时进组的呢。[doge] 
6.#热点#【六小龄童:如果上不了我就在家看春晚】“其实我完全没有料到,观众会对我上春晚的事这么轰动。我很感动,很感谢。除夕如果上(春晚),那就去给大家拜年,让大家高兴。如果没有上,我会和我的家人一起看春晚,继续支持央视春节联欢晚会。”昨日,@六小龄童 接受采访时说。 
7.​#支付宝集福#怎么了?全国人都在找敬业福,支付宝红包口令?还是希望看到#六小龄童上春晚# 
8.如何看待有的人因为六小龄童老师没上春晚就骂tfboys 
9.#帮六小龄童上春晚#故事大概是这样的,央视内部@央视张立 都实在看不下去了, 站出来为大家和@六小龄童 爷爷开口,然后就有人给他发了消息要删微博。还是那句话,六小龄童在台下嗑瓜子我们也愿意看。@央视张立 必须挺你。好棒哒![赞]挺他的请转发支持! #玩在成都#

PMI原理

根据pmi(x, y) = p(x, y) / [ p (x) * p(y) ] , 即两个单词共现的概率除以两个单词的频率乘积, 这个的概率是document frequency , 实现起来并不是很难, 不是关键是对 文档 – 单词 的存储, 建议使用倒排索引的结构, 这样可以方便存储和计算. 而我在实验中, 由于单词与文档并不多, 所以采用的是文档词语关联矩阵的思想.

代码实现

我使用的分词工具包是结巴分词, 对原来的文本进行以下三个操作:
Continue reading

NLP 在情感分析上的研究:

博文1:本文重点对电影推文进行情感分析(https://www.analyticsvidhya.com/blog/2016/02/step-step-guide-building-sentiment-analysis-model-graphlab/)

博文2:本文重点对印度金奈洪水期间的推文进行情感分析。(https://www.analyticsvidhya.com/blog/2017/01/sentiment-analysis-of-twitter-posts-on-chennai-floods-using-python/)

论文1:本文采用朴素贝叶斯的监督学习方法对IMDB评论进行分类。(https://arxiv.org/pdf/1305.6143.pdf)

论文2:本文利用LDA的无监督学习方法来识别用户生成评论的观点和情感。本文在解决注释评论短缺的问题上表现突出。(http://www.cs.cmu.edu/~yohanj/research/papers/WSDM11.pdf)

资料库:这是一个很好的包含相关研究论文和各种语言情感分析程序实现的资料库。(https://github.com/xiamx/awesome-sentiment-analysis)

数据集1:多域情感数据集版本2.0(http://www.cs.jhu.edu/~mdredze/datasets/sentiment/)

数据集2:Twitter情感分析数据集(http://www.sananalytics.com/lab/twitter-sentiment/)

竞赛:一个非常好的比赛,你可以检查你的模型在烂番茄电影评论的情感分析任务中的表现。(https://www.kaggle.com/c/sentiment-analysis-on-movie-reviews)