6.3 常用文本分类工具

6.3.1 使用 scikit-learn 进行文本分类

scikit-learn 库提供了丰富的分类算法,本部分选取几个常用分类方法进行说明。

6.3.1.1 朴素贝叶斯分类器(Naive Bayes)

scikit-learn 库的 naive_bayes 模块提供了朴素贝叶斯分类器的训练算法。朴素贝叶斯方法是基于贝叶斯定理的有监督学习算法,由于特征值之间相互独立的朴素假设,称之为“朴素贝叶斯”。给定类别变量 y 以及相互独立的特征向量(x1,……,xn),根据贝叶斯公式可以得到以下计算关系:

@todo 补充公式

根据独立性假设以上公式可以简化为

@todo 补充公式

由于分母项恒定,可以使用以下分类规则:

@todo 补充公式

不同朴素贝叶斯分类器的差别主要在于 P(xi|y) 的假设分布不同,scikit-learn 提供了 Gaussian Naive Bayes、Multinomial Naive Bayes、 Bernoulli Naive Bayes 三种假设,后续会一一进行介绍。

尽管假设过于简化,朴素贝叶斯分类器在很多实际分类问题中取得了较好的分析效果,尤其是在文档分类和垃圾邮件过滤方面,且相对于其他复杂算法,朴素贝叶斯分类器训练速度更快,但是该算法分类结果的预测概率比较不准确。

常见有两种模型,分别是多项式模型(multinomial model)和伯努利模型(Bernoulli model)。

(1)高斯朴素贝叶斯分类器(Gaussian Naive Bayes)

高斯模型即假设 P(xi|y) 服从高斯分布,并使用极大似然进行参数估计,模型训练主要利用 naive_bayes 模块下的 GaussianNB 类。

GaussianNB 类实例化方式为:实例=GaussianNB(priors=None),参数 priors 为类别先验概率,如果在实例化过程中人为设定,则先验概率值不会根据实际数据进行调整。

(1.1)fit 方法

fit 方法根据给定的数据训练高斯朴素贝叶斯模型,调用方式为:实例.fit(X, y, sample_weight=None)

参数说明:

X:数组型数据,形如 (n_samples, m_features)的训练集,表示 n 个样本及其对应的 m 个特征项

y:数组型数据,长度为 n,表示 n 个样本的分类情况

sample_weight:可选参数,用于设置每个样本在训练过程中的权重,默认取值为“None”,即不做任何加权处理

(1.2)predict 方法

predict 方法利用训练好的模型对测试集进行分类,调用方式为:实例.predict(X),其中参数 X 即为测试集数据,数据类型为数组,该方法直接返回测试集的分类结果

(1.3)predict_proba 方法

predict_proba 方法以数组形式返回测试集样本属于各个类别的概率,数组的列表示类别,调用方式为:实例.predict_proba(X),其中参数 X 即为待预测测试集数组

(1.4)score 方法

score 方法可以用于计算分类结果的平均准确率,调用方式为:实例.score(X, y, sample_weight=None)

参数说明:

X:数组型数据,形如 (n_samples, m_features)的测试集,表示 n 个样本及其对应的 m 个特征项

y:数组型数据,长度为 n,表示测试集 n 个样本的真实分类情况

sample_weight:样本权重

例 1


In [1]:import sklearn
       from sklearn.naive_bayes import GaussianNB
       import numpy as np
       X = np.array([[-1, -1], [-2, -1], [-3, -2], [1, 1], [2, 1], [3, 2]])
       Y = np.array([1, 1, 1, 2, 2, 2])
       clf = GaussianNB()
       clf.fit(X, Y) # 以 X、Y 为训练集训练分类模型
Out[1]:GaussianNB()
In [2]:clf.predict(np.array([[-5,-0.1],[5,0.1]])) # 预测测试集分类
Out[2]:array([1, 2])
In [3]:clf.predict_proba( np.array([[-5,-0.1],[5,0.1]])) # 预测测试集样本被分到各个类别的概率
Out[3]:array([[  1.00000000e+00,   2.81846254e-14],
              [  2.81846254e-14,   1.00000000e+00]])
In [4]:X_test= np.array([[-5,-0.1],[5,0.1]]) # 测试集特征值
       y_test=np.array([1, 2]) # 测试集真实分类
       clf.score(X_test,y_test) # 计算平均准确率
Out[4]:1.0

(1.5)partial_fit 方法

当训练集的规模非常大不适合放在内存中时,可以利用 partial_fit 方法进行训练,该方法可以以动态增加的形式使用训练数据,或者说是一个在线学习过程。调用方式为:实例.partial_fit(X, y, classes=None, sample_weight=None)

参数说明:

X:数组型数据,形如 (n_samples, m_features)的训练集,表示 n 个样本及其对应的 m 个特征项

y:数组型数据,长度为 n,表示训练集 n 个样本的分类情况

classes:可选参数,类别列表,包括 y 中可能出现的所有类别,第一次调用时一定要提供该参数

sample_weight:样本权重

(1.6)属性

classprior 属性返回各个类别的概率

classcount 属性返回各个类别包含的样本数

theta_ 属性返回各个类别样本属性均值

sigma_ 属性返回各个类别样本属性方差

例 2


In [5]:clf.class_prior_
Out[5]:array([ 0.5,  0.5])

In [6]:clf.class_count_
Out[6]:array([ 3.,  3.])

In [7]:clf.theta_
Out[7]:array([[-2.        , -1.33333333],
              [ 2.        ,  1.33333333]])

In [8]:clf.sigma_
Out[8]:array([[ 0.66666667,  0.22222223],
              [ 0.66666667,  0.22222223]])

(2)多项式朴素贝叶斯分类器(Multinomial Naive Bayes)

多项式分类器基于多项式分布执行朴素贝叶斯算法,适用于特征值为离散值的训练集,是贝叶斯分类器中适用于文本分类的分类器之一,因为文本分类过程中常常提取词频作为分类特征,虽然多项式分布一般要求特征值为整数,但是在实际分析过程中,如 tf-idf 这样的非整数值也可以取得较好的训练效果。

多项式分类器将每一个类参数化为向量

@todo 补充公式

其中,n 为特征数,对应到文本分类中即为词汇总数,

@todo 补充公式

可以使用以下方式进行参数估计:

@todo 补充公式

在 sklearn 库中,多项式模型训练主要利用 naive_bayes 模块下的 MultinomialNB 类,该类实例化方式为:实例=MultinomialNB(alpha=1.0, fit_prior=True, class_prior=None)

参数说明:

alpha:设置平滑参数,默认缺失值为 1 ,即 Laplace 平滑

fit_prior:是否学习类别先验概率,默认取值为“True”,若取值为“False”,将使用均匀先验概率

class_prior:类别概率,默认值为“None”

与 GaussianNB 类类似,MultinomialNB 类也通过 fit 方法进行训练集的训练、通过 predict 方法进行测试集类别预测、通过 predict_proba 方法返回测试集属于各个类别的概率、通过 score 方法计算分类器的平均准确率、利用 partial_fit 方法进行大型训练集的训练,具体调用方式及参数说明可以参考 GaussianNB 类。

例 3


In [9]:from sklearn.naive_bayes import MultinomialNB
       X = np.random.randint(5, size=(6, 100))
       y = np.array([1, 2, 3, 4, 5, 6])
       clf = MultinomialNB()
       clf.fit(X, Y) # 以 X、Y 为训练集训练分类模型
Out[9]:MultinomialNB(alpha=1.0, class_prior=None, fit_prior=True)
In [10]:X_test=np.random.randint(5, size=(2, 100))
        clf.predict(X_test) # 预测测试集分类
Out[10]:array([1, 2])

(3)伯努利朴素贝叶斯分类器(Bernoulli Naive Bayes)

伯努利分类器假设数据服从多元伯努利分布,也就是说,可能训练集包含多个特征项,但是每个特征项都是布尔型变量,即只有两种取值情况,因此要使用该种分类器需要先将样本特征项转换为布尔型,也可以通过参数设置将原始数据直接转换为布尔型。在文本分类中,如果文档词——词项矩阵元素不是词频而是词汇是否出现这样的二值变量,就可以利用伯努利分类器进行文本分类,特别的,当文档长度比较短时,伯努利朴素贝叶斯分类器可以达到较好的分类效果。

naive_bayes 模块下的 BernoulliNB 类可以实现伯努利朴素贝叶斯分类器的训练,实例化方式为:BernoulliNB(alpha=1.0, binarize=0.0, fit_prior=True, class_prior=None),其中参数 binarize 用于设置二值变量的阈值,如果取值为“None”则默认输入训练集已经为二值型。相关类方法可以参考 GaussianNB 、MultinomialNB 类。

例 4


In [11]:from sklearn.naive_bayes import BernoulliNB
        X = np.random.randint(2, size=(5, 20)) # 随机生成二值型训练集
        Y = np.array([1, 2, 3, 4, 4])
        clf = BernoulliNB()
        clf.fit(X, Y)
Out[11]:BernoulliNB(alpha=1.0, binarize=0.0, class_prior=None, fit_prior=True)
In [12]:X_test=np.random.randint(2, size=(2, 20))
        clf.predict(X_test) # 预测测试集分类
Out[12]:array([1, 1])

6.3.1.2 K-最邻近分类器(KNN)

最邻近分类器的基本思想可以概括为:对于一个新的待分类的数据点,找到离其较近的已知分类的数据点,这些数据点中大多数属于哪一类,新的数据点就被归为哪一类。可见 最邻近分类器是一种基于距离计算的分类器,并不涉及模型的拟合。sklearn 库提供了两种不同的最邻近分类器,分别是 K-最邻近分类器:KNeighborsClassifier 和 半径最邻近分类器:RadiusNeighborsClassifier 。两个分类器的差别在于临近点的选取规则不同,KNeighborsClassifier 选取离待分类点最近的 K 个点进行距离计算,RadiusNeighborsClassifier 选取以待分类点为中心、以 r 为半径的圆所覆盖的所有点进行距离计算,其中 K 和 r 都是使用者自行定义的值。两种方法中 K 最邻近分类器最为常用,K 的选择很大程度上取决于实际数据情况,一般来讲,K 值越大,分类器受噪音的影响越小,分类界限也越模糊。当样本点分布比较不均匀时,可以考虑使用半径最邻近分类器,

sklearn 库 neighbors 包的 classification 模块下定义了 KNeighborsClassifier 类进行 K 最邻近分类器的训练,KNeighborsClassifier 类实例化方式为:实例=KNeighborsClassifier(n_neighbors=5, weights='uniform', algorithm='auto', leaf_size=30, p=2, metric='minkowski', metric_params=None, n_jobs=1, **kwargs)

参数说明:

n_neighbors:用于设置临近点个数 K 取值的参数,默认取值为 5

weights:用于设置临近点的权重,有三种取值形式:
(1)“uniform”:所有临近点都有相同的权重
(2)“distance”:有时需要给距离待分类点距离近的点较大的权重,可以选取该参数值实现这一需求,即临近点的权重是与待分类点距离的倒数
(3)自定义函数:使用者可以根据需求自行定义权重设置函数,函数输入值为点与点之间的距离数组,返回包含权重的同形数组

algorithm:对于临近点的计算,neighbors 包提供了 BallTree、KDTree、brute-force 三种算法,“algorithm” 参数就是用于算法的选择,有以下四种取值:
(1)“ball_tree”:使用 BallTree 算法
(2)“kd_tree”:使用 KDTree 算法
(3)“brute”:使用 brute-force 算法
(4)“auto”:将根据实际数据情况选择最优算法

leaf_size:传给 BallTree 或 KDTree 算法的叶子节点个数,默认取值为 30

p:用于设置距离计算方法,不同取值及对应的计算方法如下:
(1) p = 1:使用曼哈顿距离(manhattan distance,l1)
(2) p = 2:使用欧式距离(euclidean distance,l2),默认取值为 2
(3)其他任意 p 值:使用闵可夫斯基聚力(minkowski distance,l_p)
metric:算法树的距离测度,默认取值为“minkowski”,即闵可夫斯基测度,当参数“p=2”时,即为欧式测度,其他可用测度可以查看 DistanceMetric 类说明文档(http://scikit-learn.org/stable/modules/generated/sklearn.neighbors.DistanceMetric.html)

n_jobs:搜索临近点的并行任务的数量,默认取值为“1”,当取值为“-1”时,并行任务数取决于 CPU 内核数

(1)fit 方法

fit 方法根据实例化时 algorithm 的取值,使用训练集数据进行训练生成一个 kd_tree 或者 ball_tree,如果 algorithm='brute',则什么都不做。调用方式为:实例.fit(X, y),其中 X 为训练集样本特征值矩阵,y 为对应的分类。

(2)kneighbors 方法

kneighbors 方法可以找到待分类点的 K 个最邻近点,直接返回临近点的标签和距待分类点的距离,调用方式为:实例.kneighbors(X=None, n_neighbors=None, return_distance=True)

参数说明:

X:待分类样本特征矩阵,若不指定该参数,则默认输入训练样本数据

n_neighbors:返回的临近点个数,默认为实例化时设置的 K 值

return_distance:是否返回距离值,默认取值为“True”,即返回

(3)其他方法

predict :对测试集进行分类,调用方式为:实例.predict(X),参数 X 即为测试集数据

predict_proba :用于估计测试集被划分到各个类别的概率,调用方式为:实例.predict_proba(X),参数 X 为测试集数据

score :计算分类器的平均准确率,调用方式为:实例.score(X, y, sample_weight=None),参数 X、y 为测试集数据,sample_weight 为样本权重

例 5


In [13]:from sklearn.neighbors import  KNeighborsClassifier
        X = np.array([[0,0], [1,0.5], [2,4], [3,3.7]])
        y = np.array([0, 0, 1, 1])
        clf_knn = KNeighborsClassifier(n_neighbors=2)
        clf_knn.fit(X,y) # 使用训练数据进行训练
Out[13]:KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',metric_params=None, n_jobs=1, n_neighbors=2, p=2,weights='uniform')
In [14]:clf_knn.predict([[0.5,0.5],[5,5]]) # 预测测试集类别
Out[14]:array([0, 1])
In [15]:clf_knn.predict_proba([[0,3],[1,5]])
Out[15]:array([[ 0.5,  0.5],
               [ 0. ,  1. ]])

6.3.1.3 支持向量机(SVM)

另外一个常用的分类器是支持向量机,支持向量机在数据维度较高或者特征项维度高于样本数的情况下也能得到较好的分类效果,并且在计算决策函数过程中只使用支持向量,简化了计算量,此外使用不同的核函数可以得到不同的决策函数。

sklearn 库 svm 包下定义了支持向量机的算法,其中类 SVC、NuSVC 和 LinearSVC 都可以进行多类别分类,SVC 和 NuSVC 方法相似,但是在参数设置和计算原理上有所不同,而 LinearSVC 是使用线性核函数的分类器,故在参数设置时不用考虑核函数的设置。此外,在进行多类别分类时,SVC 和 NuSVC 默认使用“一对一”(“one-against-one” )的方式对任意两个类构建分类器,若一共有 n 个类别,则需要构建 n * (n - 1) / 2 个分类器,但是也提供了“一对多”的参数选项,为每一类和其余的类集合构建分类器,若一共有 n 个类别,则需要构建 n 个分类器。而 LinearSVC 默认使用“一对多”的方式。关于三种分类器原理上的差异可以阅读 sklearn 官方说明文档(http://scikit-learn.org/stable/modules/svm.html#svm-mathematical-formulation)。

(1)SVC

SVC 基于 libsvm 算法库,数据拟合的时间复杂度大于样本数量的二次方,使得该方法很难扩展到包含 10000 个样本的数据集。

该类实例化方式为:实例=SVC(C=1.0, kernel='rbf', degree=3, gamma='auto', coef0=0.0, shrinking=True, probability=False, tol=0.001, cache_size=200, class_weight=None, verbose=False, max_iter=-1, decision_function_shape=None, random_state=None)

参数说明:

C:误差项的惩罚系数,用以平衡分类间隔和误判样本,惩罚系数越大,被误判的样本点越少,但可能存在噪音样本过拟合的情况,默认取值为 1

kernel:用于设置核函数类型,必须在以下核函数中进行选择:‘linear’、‘poly’、‘rbf’、‘sigmoid’、‘precomputed’,默认取值为‘rbf’

degree:当核函数为多项式核函数‘poly’时,该参数用于设定多项式的最高次幂

gamma:当核函数为‘poly’、‘rbf’、‘sigmoid’时,该参数用于设定核函数系数,默认取值为“auto”,表示使用 1/n_features 作为系数

coef0:当核函数为‘poly’和‘sigmoid’时,该参数用于设定核函数中的独立项

probability:是否进行概率估计

tol;停止计算的最小差值

cache_size:设置训练过程所需的内存

class_weight:用于设置各个类的权重,各个类别的惩罚系数 C 随权重改变

max_iter:用于设置最大迭代次数,默认取值为 -1,即无限制

decision_function_shape:解决多分类问题,需要组合多个二分类器来实现多类别分类器的构造,使用该参数选择组合方式,有以下三种取值:
(1)‘ovo’: “一对一”
(2)‘ovr’ :“一对多”
(3)None:默认取值,为了后续兼容一般执行‘ovo’

random_state:概率估计时数据重新排序依照的伪随机数的生成器种子

关于核函数的形式和部分参数关系,可以阅读官方文档(http://scikit-learn.org/stable/modules/svm.html#svm-kernels)。

(1.1)decision_function 方法

decision_function 方法返回样本点到各个分割超平面之间的距离,即决策函数值,调用方式为:实例.decision_function(X),其中参数 X 即为样本特征矩阵。

(1.2)fit 方法

和其他分类器一样,fit 方法用训练集数据训练支持向量机,调用方式为:实例.fit(X, y, sample_weight=None),其中 X、y 为训练集数据,sample_weight 是调节惩罚系数 C 的权重

(1.3)其他方法

predict 方法:对给定的数据进行分类,调用方式为:实例.predict(X),其中参数 X 即为样本特征矩阵,直接返回各个待分类样本的类别标签。

predict_proba 方法:计算样本被划分到各个类别的概率,调用方式为:实例.predict_proba(X)

score 方法:计算分类器平均精度,调用方式为:实例.score(X, y, sample_weight=None),其中 sample_weight 为样本权重

(1.4)部分属性

support_ : 返回支持向量的标签

supportvectors : 返回支持向量

nsupport : 返回每一类支持向量的个数

dualcoef : 返回支持向量在决策函数中的系数

intercept_ : 返回决策函数中的常数项

例 6


In [16]:from sklearn.svm import SVC
        X = np.array([[-1, -1, -1], [-2, -1, -2], [1, 1, 1], [2, 1, 2]])
        y = np.array([1, 1, 2, 2])
        clf_svc = SVC()
        clf_svc.fit(X, y) 
Out[16]:SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0,decision_function_shape=None, degree=3, gamma='auto', kernel='rbf',max_iter=-1, probability=False, random_state=None, shrinking=True,tol=0.001, verbose=False)
In [17]:clf_svc.support_vectors_
Out[17]:array([[-1., -1., -1.],
               [-2., -1., -2.],
               [ 1.,  1.,  1.],
               [ 2.,  1.,  2.]])
In [18]:clf_svc.decision_function(X)
Out[18]:array([-0.99974151, -0.99977318,  0.99975735,  0.99975734])
In [19]:X_test = np.array([[-3, 0, -1], [5, 4, 3]])
        clf_svc.predict(X_test)
Out[19]:array([1, 2])

(2)NuSVC

NuSVC 与 SVC 相似,同样也是基于 libsvm 算法库,但是在分类器训练过程中 NuSVC 通过参数设置控制支持向量数量。该类实例化方式为:实例=NuSVC(nu=0.5, kernel='rbf', degree=3, gamma='auto', coef0=0.0, shrinking=True, probability=False, tol=0.001, cache_size=200, class_weight=None, verbose=False, max_iter=-1, decision_function_shape=None, random_state=None),其中参数“nu”为误判样本占比上界、支持向量占比下界,其他参数含义均与 SVC 相同,相关属性及方法也可参照 SVC。

(3)LinearSVC

LinearSVC 与参数 kernel=’linear’ 的 SVC 相似,但是 LinearSVC 基于 liblinear 算法库,而不是 libsvm,所以惩罚函数、损失函数的选择都更加灵活,并且对于大样本数据具有更好的伸缩性。该类实例化方式为:实例=LinearSVC(penalty='l2', loss='squared_hinge', dual=True, tol=0.0001, C=1.0, multi_class='ovr', fit_intercept=True, intercept_scaling=1, class_weight=None, verbose=0, random_state=None, max_iter=1000)

部分参数说明:

loss:用于设置损失函数,有以下两种取值:
(1)‘hinge’:标准 SVM 损失函数
(2)‘squared_hinge’:标准 SVM 损失函数的平方,为默认值

penalty:用于设置惩罚项中的范数类型,有‘l1’ 和 ‘l2’ 两种取值,默认取值为 l2 范数

6.3.1.4 决策树(Decision tree)

决策树是一个非参数的有监督学习过程。决策树在学习之前不需要过多的数据预处理,并且可以处理数值型变量和分类型变量,可视化的特性使其便于理解和解释说明,但是比较容易出现过拟合的情况,易受样本数据变动的影响。

sklearn 库中 tree 包中定义的 DecisionTreeClassifier 类可以实现多类别的决策树分类,默认使用的是 CART 算法。该类的实例化方式为:实例.DecisionTreeClassifier(criterion='gini', splitter='best', max_depth=None, min_samples_split=2, min_samples_leaf=1, min_weight_fraction_leaf=0.0, max_features=None, random_state=None, max_leaf_nodes=None, min_impurity_split=1e-07, class_weight=None, presort=False)

参数说明:

criterion:设置节点特征信息量度量方法,“gini”表示基尼指数,“entropy”表示信息增益,默认取值为“gini”

splitter: 设置节点特征选择规则,“best” 表示选择最优的特征,“random”表示随机的在部分特征中找局部最优的特征。

max_features:寻找节点特征时考量的特征个数,有以下几种取值情况:
(1)整数:在每一个节点都考量 max_features 个特征
(2)浮点数:max_features 值为考量特征在全部特征数 n_features 中的占比,在每一个节点考量(max_features * n_features)个特征
(3)“auto”:max_features=sqrt(n_features)
(4)“sqrt”:max_features=sqrt(n_features)
(5)“log2”:max_features=log2(n_features)
(6)None : max_features=n_features

max_depth:树的最大深度,默认取值为 "None" ,树将扩展到直至所有的叶节点为单一类别或者包含的样本数小于参数 “min_samples_split” 界定的样本数为止。

min_samples_split:样本数阈值,停止划分一个中间节点的最小样本数,有以下两种取值方式:
(1)整数:最小样本数为 min_samples_split
(2)浮点数:min_samples_split 为考量的样本数在全部样本数 n_samples 中的占比,故每个节点最小样本数为 (min_samples_split * n_samples)

min_samples_leaf:确认一个叶子节点的最小样本数,若小于该值,则被剪枝,同样有整数和浮点数两种取值方式:
(1)整数:最小样本数为 min_samples_leaf
(2)浮点数:min_samples_leaf 为考量的样本数在全部样本数 n_samples 中的占比,故每个节点最小样本数为 (min_samples_leaf * n_samples)

min_weight_fraction_leaf:确认一个叶子节点的所有样本权重之和的最小值,若小于该值,则被剪枝,默认取值为“0”,即不考虑权重问题

max_leaf_nodes:允许拟合的最大叶子节点个数,避免过拟合问题,默认取值为“None”,即不限制叶子节点个数

class_weight:类别权重,若不指定该参数,所有的类别权重均为 1,有三种取值方式:
(1)利用形如 {class_label: weight} 的字典设置类别权重
(2)“balanced”:根据各个类别样本数自动进行权重调整
(3)“None”

min_impurity_split:控制决策树增长的阈值,如果一个节点的信息量(基尼系数、信息增益)大于该值,则继续划分,否则为叶子节点。

presort:是否对样本数据进行排序以加快节点特征筛选速度,对于数据量较大的样本进行排序可能会降低训练速度,但是当数据量较小或者预设深度较小时,排序可以加快训练速度。

(1)apply 方法

apply 方法返回每个样本预测叶子节点的标签,调用方式为:实例.apply(X, check_input=True),参数 X 即为样本特征矩阵,参数 check_input 用于设置可以忽略的输入检查,一般不清楚具体需求时,不对该参数进行设置。

(2)fit 方法

fit 方法用于训练决策树分类器,调用方式为:fit(X, y, sample_weight=None, check_input=True, X_idx_sorted=None),在对同一个样本集合进行多次训练时,需要设置参数 X_idx_sorted 对多个决策树进行标记,一般情况不需要进行设置。

(3)其他方法

predict:预测测试集类别,调用方式为:实例.predict(X, check_input=True)

predict_proba:预测测试集样本被划分到各个类别的概率,调用方式为:实例.predict_proba(X, check_input=True)

score:利用测试集计算决策树分类器的平均准确率,调用方式为:实例.score(X, y, sample_weight=None)

例 7


In [20]:from sklearn import tree
        X = [[0, 0, -1], [1, 0, 1]]
        Y = [0, 1]
        clf_DecisionTre = tree.DecisionTreeClassifier()
        clf_DecisionTre.fit(X, Y)
Out[20]:DecisionTreeClassifier(class_weight=None, criterion='gini', max_depth=None,max_features=None, max_leaf_nodes=None, min_samples_leaf=1,min_samples_split=2, min_weight_fraction_leaf=0.0,presort=False, random_state=None, splitter='best')
In [21]:clf_DecisionTre.predict([[2, 2, 0]])
Out[21]:array([1])

6.3.1.5 神经网络(Neural network)

0.18 版本的 scikit-learn 库 neural_network 包提供了两种神经网络分类器,分别是 BernoulliRBM 和 MLPClassifier,而 0.17 版本只支持 BernoulliRBM 算法,本部分主要介绍多层感知器 MLP(multi-layer perceptron)。

scikit-learn 库定义了 MLPClassifier 类利用 BP 算法训练多层神经网络,仅支持交叉熵(Cross-Entropy)损失函数和分类概率估计,类实例化方式为:实例=MLPClassifier(hidden_layer_sizes=(100, ), activation='relu', solver='adam', alpha=0.0001, batch_size='auto', learning_rate='constant', learning_rate_init=0.001, power_t=0.5, max_iter=200, shuffle=True, random_state=None, tol=0.0001, verbose=False, warm_start=False, momentum=0.9, nesterovs_momentum=True, early_stopping=False, validation_fraction=0.1, beta_1=0.9, beta_2=0.999, epsilon=1e-08)

参数说明:

hidden_layer_sizes:设置各个隐层的单元数,取值类型为元组,元组长度为神经网络总层数减 2,元组中第 i 个元素就代表第 i 个隐层的单元数,默认取值为“(100,)”

activation:设置隐层的激活函数 f(x),提供了以下四种取值:
(1)‘identity’:无激活函数,只进行线性转换,即 f(x) = x
(2)‘logistic’:logistic sigmoid 函数,即f(x) = 1 / (1 + exp(-x))
(3)‘tanh’:双曲函数,即 f(x) = tanh(x)
(4)‘relu’:修正线性函数,即 f(x) = max(0, x)
默认取值为 ‘relu’

solver:设置寻找最优权重的算法,支持以下三种算法:
(1)‘lbfgs’:属于拟牛顿算法的一种最优化算法,对于较小数据集训练效果较好
(2)‘sgd’:随机梯度下降法
(3)‘adam’:Kingma 等人提出的基于梯度搜索的最优化算法,对于较大的数据集该算法不论是训练时间还是交叉验证结果都有较好的表现,
默认取值为 ‘adam’

alpha:设置正则化项的惩罚系数。默认取值为 0.0001

learning_rate_init:初始学习率,默认取值为 0.001

power_t:当参数 learning_rate 取值为 ‘invscaling’ 时,用于设置缩放指数

tol:寻找最优权重过程中的最优化阈值,如果迭代过程中损失函数或者交叉验证得分变动未满足该参数,则对学习率进行调整

learning_rate:设置学习率变化趋势,有以下三种取值:
(1)‘constant’:始终保持初始学习率 learning_rate_init
(2)‘invscaling’:随着迭代次数 t 的增加在初始学习率的基础上逐渐减小学习率,减小规则为 learning_rate_init / pow(t, power_t),其中 power_t 参数需另外设置
(3)‘adaptive’:只要损失函数取值随着迭代次数的增加而减小就保持初始学习率不变,如果连续两个迭代的损失函数减小没有超过参数 tol ,或者交叉验证得分的增加没有超过参数 tol ,学习率就缩小为原来的1/5
默认取值为 ‘constant’

max_iter:最大迭代次数,默认取值为 200

warm_start:取值为“True”时,表示使用之前调用的参数进行初始化,否则覆盖掉之前的结果

nesterovs_momentum:是否使用 Nesterov momentum 优化算法

momentum:用于设置优化梯度下降算法的 momentum 值,取值范围在 0-1 之间,默认取值为 0.9

early_stopping:当交叉验证得分没有提升时是否提前终止迭代,如果取值为“True”时,会自动预留 10% 的训练集作为验证样本,当连续两次迭代交叉验证得分增加不超过参数 tol 时,终止训练

validation_fraction:在需要提前终止训练时,该参数用于设置用来验证的训练样本的比重,

(1)相关方法

@todo 补充方法列表

(2)相关属性

@@todo 补充属性列表

6.3.2 使用 TextGrocery 进行文本分类

TextGrocery 是基于 LibLinear 和 jieba 分词的 Python 短文本分类工具,同时支持中文和英文语料,安装和使用都较为简单,可访问官方文档进行详细了解 http://textgrocery.readthedocs.io/zh/latest/index.html#。

6.3.2.1 安装 TextGrocery


In [22]:!pip install tgrocery
        Collecting tgrocery
          Downloading tgrocery-0.1.4.tar.gz
        Requirement already satisfied: ……
        Building wheels for collected packages: ……
        Successfully built tgrocery
        Installing collected packages: tgrocery
        Successfully installed tgrocery-0.1.4

6.3.2.2 Grocery 类

tgrocery 模块下的 Grocery 类定义了短文本分类器的训练方法, Grocery 类实例化方式为:实例=Grocery(name, custom_tokenize=None)

参数说明:

name:自定义分类器名称 custom_tokenize:指定分词器,默认为 jieba 分词,使用者可以自行指定分词函数

(1)train 方法

train 方法使用训练集训练样本,调用方式为:实例.train(train_src, delimiter='\t')

参数说明:

train_src:用于训练分类器的训练集,有两种取值方式:
(1)语料列表:列表元素为 (类别,文本) 元组
(2)文件路径:一行为一个训练样本,类别标签在前、语料文本在后,默认分隔符是\t

delimiter:解析训练集文件的分隔符,默认为'\t',仅在 train_src 为文件路径时有用

(2)predict 方法

predict 方法用于预测单一文本类别,调用方式为:实例.predict(single_text),参数 single_text 为待预测文本

(3)test 方法

test 方法使用测试集测试分类器的准确性,调用方式为:实例.test(test_src, delimiter='\t')

参数说明:

test_src:用于测试分类器的测试集,有两种取值方式:
(1)语料列表:列表元素为 (类别,文本) 元组
(2)文件路径:一行为一个测试样本,类别标签在前、语料文本在后,默认分隔符是\t

delimiter:解析测试集文件的分隔符,默认为'\t',仅在 test_src 为文件路径时有用

例 8


In [23]:from tgrocery import Grocery
        grocery = Grocery('sample')
        train_src = [('财经', '格力电器继续排名深股通十大成交活跃股榜首'),
                     ('财经', '全国玉米市场化电子交易平台正式启动'),
                     ('体育', '英超-桑切斯进球阿森纳1-2遭逆转 14轮不败终结'),
                     ('体育', '当年湖人因对抗不足弃波神 斯科特调侃成笑柄')]
        grocery.train(train_src)
Out[23]:<tgrocery.Grocery at 0x7fd101daba90>
In [24]:print grocery.predict('吉林东北虎一战重返前八 卡姆拉尼弑杀旧主')
Out[24]:体育
In [25]:test_src = [('财经', '发改委今日调油价 成品油价或迎四年内最大涨幅'),
                    ('体育', '裁判界C罗!英超名哨动作引网友群嘲:他要罚球吗'),]
        print grocery.test(test_src)
Out[25]:0.5

6.3.3 使用 NLTK 进行文本分类

NLTK 库中 classify 包给出了文本分类的相关接口和模块,包括决策树、朴素贝叶斯、支持向量机等。在 NLTK 文本分类过程中,有以下几个常用的概念:

feature set:字面意思是特征集合,实际上是一个样本所包含的特征名称( feature names)和特征值(feature values)一一对应构成的字典,形如 {feature name:feature value},feature sets 即为所有样本的 feature set 的集合

labeled feature sets:带有类别标记的 feature sets,形如 [({feature name:feature value},label)],是通用的训练集表示方式,也可以用于分类器分类效果的评价

比如,现有 8 个文档,包含“x,y,z”三种字符串,分为“1,2”两类,以字符串为特征项,字符串出现次数为特征值,构建可用于训练 NLTK 分类器的训练集和测试集如下:


train = [(dict(x=5,y=8,z=1), '1'),
         (dict(x=3,y=5,z=0), '1'),
         (dict(x=6,y=4,z=0), '1'),
         (dict(x=1,y=9,z=2), '1'),
         (dict(x=0,y=1,z=7), '2'),
         (dict(x=1,y=1,z=7), '2'),
         (dict(x=1,y=1,z=8), '2'),
         (dict(x=2,y=0,z=7), '2')]

test = [(dict(x=3,y=8,z=1), '1'),
        (dict(x=7,y=1,z=2), '1'),
        (dict(x=2,y=1,z=9), '2'),
        (dict(x=0,y=3,z=6), '2')]

6.3.3.1 词袋特征提取

在基于文本数据构建分类器之前,有必要先进行相应的结构化处理,而 NLTK 分类器指定传入上述字典类型的 feature set,词袋模型是进行这一转换的最简单的方法,即对每一个文本样本中的词汇构建一个是否存在的特征集合,featx.py(https://github.com/japerk/nltk3-cookbook/blob/master/featx.py) 中的 bag_of_words 函数可以快速实现这一转换,使用方式也颇为简单:


In [26]:from featx import bag_of_words
        bag_of_words(['bag', 'of', 'words'])
Out[26]:{'bag': True, 'of': True, 'words': True}

除函数 bag_of_words 外,featx.py 中还定义了其他稍微复杂的文本结构化处理函数,如指定词汇筛选(bag_of_words_not_in_set)、去除停用词(bag_of_non_stopwords)、输出 bigram 词组(bag_of_bigrams_words)等等。

6.3.3.2 朴素贝叶斯分类器

得到 feature sets 形式的文本数据后,就可以训练分类器了,首先对构建朴素贝叶斯分类器的类和方法进行说明。NLTK 库 naivebayes 模块下定义了 NaiveBayesClassifier 类及相应的方法训练朴素贝叶斯分类器,NaiveBayesClassifier 类初始化方式为:NaiveBayesClassifier(label_probdist, feature_probdist),利用 train 方法计算相关参数值并传入进而得到训练模型。

参数说明:

label_probdist:基于训练集计算的各个类别的先验概率

feature_probdist:基于训练集计算的给定类别时各个特征的条件概率

相关类方法及调用方式见下表:

@todo 补充方法列表

另外,利用 classify 包 util 模块的 accuracy 函数可以计算分类器的准确性,调用方式为:accuracy(classifier, gold),其中参数 classifier 即为需要评价的分类器,gold 为用来评价的测试集数据。

例 9


In [26]:from nltk import NaiveBayesClassifier
        from nltk.classify.util import accuracy
        nb_classifier = NaiveBayesClassifier.train(train)
        nb_classifier.classify_many([dict(x=3,y=8,z=1),dict(x=7,y=1,z=2)])
Out[26]:['1', '2']
In [27]:probs = nb_classifier.prob_classify(test[0][0])
        probs.samples()
Out[27]:['1', '2']
In [28]:probs.prob('1')
Out[28]:0.9642857142857137
In [29]:probs.prob('2')
Out[29]:0.03571428571428566
In [30]:nb_classifier.most_informative_features(5)
Out[30]:[('x', 1), ('z', 0), ('y', 9), ('z', 1), ('y', 1)]
In [31]:accuracy(nb_classifier, test)
Out[31]:0.75

6.3.3.3 决策树分类器

classify 包中的 decisiontree 模块中定义了决策树类 DecisionTreeClassifier 和相关方法来训练决策树分类器,该类同样通过调用 train 方法进行模型训练,调用方式为:train(labeled_featuresets, entropy_cutoff=0.05, depth_cutoff=100, support_cutoff=10, binary=False, feature_values=None, verbose=False)

参数说明:

labeled_featuresets:训练集,形如[({feature name:feature value},label)]

entropy_cutoff:该参数用于决策树优化过程,即决策树是否需要扩展新的决策枝,如果新增决策枝的类别概率分布熵值大于该参数值,说明在当前节点或者特征项下,类别分布差异较小,应该继续优化,否则停止优化,也就是说当某一类别出现的次数显著高于其他类别时,决策树不需要进一步扩展

depth_cutoff:最大决策树深度,默认取值为 100,降低该参数值可以加快训练速度,但是也很有可能降低分类器的准确性

support_cutoff:该参数用于控制优化决策树所需的样本数目,在决策树优化过程中,一旦样本对训练过程不提供新的信息则不考虑该样本,当样本数小于或等于该参数值时,则停止优化

binary:当所有的特征项取值均为二元类型时,该参数取值为“True”,注意不是训练二元分类器

其他相关类方法及调用方式见下表:

@todo 补充方法列表

例 10


In [32]:from nltk import DecisionTreeClassifier
        dt_classifier = DecisionTreeClassifier.train(train,entropy_cutoff=0.8, depth_cutoff=5, support_cutoff=2)
        dt_classifier.classify(test[0][0])
Out[32]:'1'
In [33]:dt_classifier.error(test)
Out[33]:0.25
In [34]:accuracy(dt_classifier, test)
Out[34]:0.75

6.3.3.4 最大熵分类器(maximum entropy classifier)

classify 包中的 maxent 模块中定义了类 MaxentClassifier 和相关方法来训练最大熵分类器,该类同样通过调用 train 方法进行模型训练,调用方式为:train(cls, train_toks, algorithm=None, trace=3, encoding=None, labels=None, gaussian_prior_sigma=0, **cutoffs)

参数说明:

train_toks:训练集,形如[({feature name:feature value},label)]

algorithm:用于设置训练算法,可选算法包括:'GIS'( Generalized Iterative Scaling)、'IIS'(Improved Iterative Scaling)、'megam'(LM-BFGS algorithm with training performed by Megam),默认取值是'IIS'

trace:用于设置分类器训练结束后输出的信息详细水平,值越高输出越详细,默认取值为 3

labels:所有可能的类别标签集合,若不指定,则默认使用训练集中出现的所有类别

gaussian_prior_sigma:在算法为'megam'时,该参数用于设置高斯先验模型权数

cutoffs:其他用于终止训练过程的参数,包括:
(1)max_iter:最大迭代次数
(2)min_lldelta:如果两次迭代之间对数似然函数的变动值小于该参数,则停止迭代
(3)min_ll:如果负平均似然函数值小于该参数,停止迭代

其他相关类方法及调用方式见下表:

@todo 补充方法列表

例 11


In [35]:from nltk.classify import MaxentClassifier
        me_classifier = MaxentClassifier.train(train)
Out[35]: ==> Training (100 iterations)

             Iteration    Log Likelihood    Accuracy
             ---------------------------------------
                    1          -0.69315        0.500
                    2          -0.42087        1.000
                    3          -0.30768        1.000
                    …… 
                   97          -0.01176        1.000
                   98          -0.01164        1.000
                   99          -0.01152        1.000
                Final          -0.01141        1.000
In [36]:me_classifier.weights()
Out[36]:array([ 2.21461873,  2.21461873,  2.21461873,  2.21461873,  2.21461873,
                2.21461873,  2.21461873,  2.21461873,  3.75522551, -1.21475776,
                3.75522551,  2.30467634,  2.18639661,  2.25638061,  0.5696256 ,
                2.35114273,  2.20626101,  2.20626101])
In [37]:me_classifier.classify(test[0][0])
Out[37]:'1'
In [38]:accuracy(me_classifier, test)
Out[38]:1.0

6.3.4 使用 TextBlob 进行文本分类

TextBlob 库也封装了 NLTK 中定义的分类工具,但是 TextBlob 对训练集或测试集的形式要求较 NLTK 更为宽松,在利用 TextBlob 进行文本分类之前,毋需将文本数据转换为形如 [({feature name:feature value},label)] 的 labeled feature sets ,直接传入 [(text,label)] 即可,其中 text 即为原始的待分类文本字符串,当然也可以直接读入文本文件。下面以一个简单的例子快速说明 TextBlob 库的文本分类工具的使用方法。

例 12

首先安装最新版本的 TextBlob


In [39]:!pip install -U textblob
        Collecting textblob
          Downloading textblob-0.11.1-py2.py3-none-any.whl (634kB)
            100% |████████████████████████████████| 634kB 33kB/s 
        Requirement already up-to-date: ……
        Installing collected packages: textblob
        Successfully installed textblob-0.11.1
In [40]:import textblob
        from textblob.classifiers import NaiveBayesClassifier

以情感分类文本数据为例


In [41]:train = [('I love this film.', 'pos'),
                 ('he is an amazing actor!', 'pos'),
                 ("what an awesome story", 'pos'),
                 ('I do not like this cinema', 'neg'),
                 ('a horrible story line.', 'neg')]
         test = [('the film was good.', 'pos'),
                 ("I feel amazing!", 'pos'),
                 ("It sucks.", 'neg')]
In [42]:cl = NaiveBayesClassifier(train) # 训练分类器 
In [43]:cl.classify(test[0][0]) # 预测文本情感分类
Out[43]:'pos'
In [44]:cl.accuracy(test) # 检验分类器准确率
Out[44]:0.6666666666666666

6.3.5 使用 Pattern 进行文本分类

Pattern 库 vector 包下定义了 IGTree、KNN、NB、SLP、SVM 类实现分类算法,相关类方法的调用方式一致,下面以 KNN 为例进行说明。KNN 类实例化方式为:实例=KNN(train=[], baseline='majority', k=10, distance='cosine')

参数说明:

train:训练集数据列表,列表元素取值类型为 Document,或者(document, type)元组,其中 document 可以是 Document、向量、字典、字符串。这里面提到的 Document 是 vector 模块中定义的类,在进行分类之前需要调用相关方法将文本数据转换为 Document,转换方式为:document = Document(string, punctuation = '.,;:!?()[]{}\'`"@#$*+-|=~_', top = None,threshold = 0,exclude = [],stemmer = None, stopwords = False,type = None,language = None)

相关参数说明:

string:待处理文本,可以是字符串,也可以是包含字符串数值元组的列表、字典等 punctuation:需要过滤掉的标点符号 top:过滤掉出现次数不在此最频繁范围之内的词汇 threshold:删除出现次数小于该值的词汇 exclude:直接过滤掉该列表中的词汇 stemmer:词干化处理算法,有以下四种取值:STEMMER、LEMMA、自定义函数、None stopwords:是否包含停用词 type:类别标注 language:语言种类,有以下几种取值:en(英语)、es(西班牙语)、de(德语)、fr(法语)、it(意大利语)、nl(荷兰语)

Document 类支持词频统计等方法,具体可以参考官方文档(http://www.clips.ua.ac.be/pages/pattern-vector#document)。

例 13


In [45]:import pattern
        from pattern.vector import Document
        s="text mining with python"
        d = Document(s, threshold=0,stopwords = True)
        d.words
Out[45]:{u'mining': 1, u'python': 1, u'text': 1, u'with': 1}

baseline:默认的类别预测规则,多数投票法或者自行定义

k:分类数

distance:距离衡量方式,默认取值为 COSINE ,即夹角余弦,此外还支持 EUCLIDEAN、MANHATTAN 和 HAMMING

相关类方法及调用方式见下表:

@todo 补充方法列表

例 14 以例 12 中的情感分类文本为例


In [46]:import pattern
        from pattern.vector import KNN,Document
        train = [Document('I love this film.', type='pos'),
                 Document('he is an amazing actor!', type='pos'),
                 Document("what an awesome story", type='pos'),
                 Document('I do not like this cinema',type='neg'),
                 Document('a horrible story line.', type='neg')]
        test = [Document('the film was good.', type='pos'),
                Document("I feel amazing!", type='pos'),
                Document("It sucks.", type='neg')]
        cl=KNN(train=train,k=2)
        cl.classify(test[0], discrete=True)
Out[46]:'pos'
In [47]:cl.classify(test[0], discrete=False)
Out[47]:defaultdict(float, {'pos': 1.0})
In [48]:cl.test(test)
Out[48]:(0.6666666666666666, 0.3333333333333333, 0.5, 0.4)

results matching ""

    No results matching ""