从零开始通往kaggle竞赛之路---第二章 基础篇(上)

在本章中,我们会使用大量实例和数据,着重介绍两类最为广泛使用的机器学习模型(监督学习经典模型与无监督学习经典模型)的使用方法、性能评价以及优缺点。

对于每一类经典模型,都将从模型简介、数据描述、编程实践、性能评测以及特点分析5个角度分别进行阐述。

2.1 监督学习经典模型

在第一章中我们提到过:机器学习中监督学习模型的任务重点在于,根据已有经验知识对未知样本的目标/标记进行预测。根据目标预测变量的类型不同,我们把监督学习任务大体分为分类学习与回归预测两类。

监督学习任务的基本架构和流程:首先准备训练数据,可以是文本、图像、音频等;然后抽取所需要的特征,形成特征向量(Feature Vectors);接着,把这些特征向量连同对应的标记/目标(Labels)一并送入学习算法中,训练出一个预测模型(Predictive Model),然后采用同样的特征抽取方法作用于新测试数据,得到用于测试的特征向量;最后使用预测模型对这些待测试的特征向量进行预测并得到结果

2.1.1 分类学习

分类学习是最为常见的监督学习问题。其中,最基础的是二分类,即从两个类别中选择一个作为预测结果;除此之外还有多分类的问题,即在多个类别中选择一个;甚至还有多标签分类,与上述二分问题以及多类分类问题不同,多标签分类问题判断一个样本是否同时属于多个不同类别。

2.1.1.1 线性分类器

线性分类器(Linear Classifiers):顾名思义,是一种假设特征与分类结果存在线性关系的模型。这个模型通过累加计算每个维度的特征与各自权重的乘积来帮助类别决策。

如果我们定义 x = &lt; x 1 , x 2 , ⋯ &ThinSpace; , x n &gt; x=&lt;x_{1}, x_{2}, \cdots, x_{n}&gt; x=<x1,x2,,xn>来代表n维特征列向量,同时用n维列向量 w \boldsymbol{w} w = &lt; w 1 , w 2 , ⋯ &ThinSpace; , w n &gt; =&lt;w_{1}, w_{2}, \cdots, w_{n}&gt; =<w1,w2,,wn>来代表对应的权重,或者叫做系数;同时为了避免其过坐标原点这种硬性假设,增加一个截距 b b b。由此这种线性关系便可以表达为
f ( w , x , b ) = w T x + b f(w, x, b)=w^{\mathrm{T}} x+b f(w,x,b)=wTx+b
这里的 f ∈ R f \in \mathrm{R} fR,取值范围分布在整个实数域中。

当然,我们所要处理的最简单的二分类问题希望 f ∈ { 0 , 1 } f \in\{0,1\} f{0,1};因此需要一个函数把原先的 f ∈ R f \in \mathrm{R} fR映射到(0,1).于是我们就想到了Logistic函数:
g ( z ) = 1 1 + e − z g(z)=\frac{1}{1+\mathrm{e}^{-z}} g(z)=1+ez1
这里 z ∈ R z \in \mathrm{R} zR并且 g ∈ ( 0 , 1 ) g \in(0,1) g(0,1),并且其函数图像如下图所示:
在这里插入图片描述
综上,如果将 z \boldsymbol{z} z替换为 f \boldsymbol{f} f,整合上面的两个方程,就得到了一个经典的线性分类器,Logistic Regression:
h w , b ( x ) = g ( f ( w , x , b ) ) = 1 1 + e − f = 1 1 + e − ( w T x + b ) h_{w, b}(x)=g(f(w, x, b))=\frac{1}{1+\mathrm{e}^{-f}}=\frac{1}{1+\mathrm{e}^{-\left(w^{\mathrm{T}} x+b\right)}} hw,b(x)=g(f(w,x,b))=1+ef1=1+e(wTx+b)1

通过观察可以得知,如果 z = 0 z=0 z=0,那么 g = 0.5 g=0.5 g=0.5;若 z &lt; 0 z&lt;0 z<0,则 g &lt; 0.5 g&lt;0.5 g<0.5,这个特征向量被判别为一类;反之,若 z &gt; 0 z&gt;0 z>0,则 g &gt; 0.5 g&gt;0.5 g>0.5,其被归为另外一类。

当使用一组 m m m个用于训练的特征向量 X = &lt; x 1 , x 2 , ⋯ &ThinSpace; , x m &gt; \boldsymbol{X}=&lt;\boldsymbol{x}^{1}, \boldsymbol{x}^{2}, \cdots, \boldsymbol{x}^{m}&gt; X=<x1,x2,,xm>和其所对应的分类目标 y = &lt; y 1 , y 2 , ⋯ &ThinSpace; , y m &gt; y=&lt;y^{1}, y^{2}, \cdots, y^{m}&gt; y=<y1,y2,,ym>,我们希望logisitic模型可以在这组训练集上取得最大似然估计的概率 L ( w , b ) L(w, b) L(w,b)。或者说至少要在训练集上表现如此:

argmax ⁡ w , b L ( w , b ) = \underset{w, b}{\operatorname{argmax}} L(w, b)= w,bargmaxL(w,b)= argmax ⁡ w , b ∏ i = 1 m \underset{w, b}{\operatorname{argmax}} \prod_{i=1}^{m} w,bargmaxi=1m ( h w , b ( i ) ) y ′ ( 1 − h w , b ( i ) ) 1 − y i \left(h_{w, b}(i)\right)^{y^{\prime}}\left(1-h_{w, b}(i)\right)^{1-y^{i}} (hw,b(i))y(1hw,b(i))1yi

为了学习到决定模型的参数,即系数 w w w和截距 b b b,我们普遍使用一种精确计算的解析算法和一种快速估计的随机梯度上升算法。这里不过多介绍,有兴趣可以去查阅吴恩达教授的机器学习课件

接下来我们将使用良/恶性乳腺癌肿瘤预测数据集来讲解逻辑回归分类器。

# 导入pandas与numpy工具包。
import pandas as pd
import numpy as np

# 创建特征列表。
column_names = ['Sample code number', 'Clump Thickness', 'Uniformity of Cell Size', 'Uniformity of Cell Shape', 'Marginal Adhesion', 'Single Epithelial Cell Size', 'Bare Nuclei', 'Bland Chromatin', 'Normal Nucleoli', 'Mitoses', 'Class']

# 使用pandas.read_csv函数从互联网读取指定数据。
data = pd.read_csv('https://archive.ics.uci.edu/ml/machine-learning-databases/breast-cancer-wisconsin/breast-cancer-wisconsin.data', names = column_names )

# 将?替换为标准缺失值表示。
data = data.replace(to_replace='?', value=np.nan)
# 丢弃带有缺失值的数据(只要有一个维度有缺失)。
data = data.dropna(how='any')

# 输出data的数据量和维度。
data.shape
(683, 11)
第一列是检索的ID,9列与肿瘤相关的特征并且已经被量化为1-10之间的数字,最后一列class中2代表良性,4代表恶性。
data.head()

在这里插入图片描述

# 使用sklearn.cross_valiation里的train_test_split模块用于分割数据。
from sklearn.model_selection import train_test_split

# 随机采样25%的数据用于测试,剩下的75%用于构建训练集合。
X_train, X_test, y_train, y_test = train_test_split(data[column_names[1:10]], data[column_names[10]], test_size=0.25, random_state=33)
# 查验训练样本的数量和类别分布。
y_train.value_counts()
2    344
4    168
Name: Class, dtype: int64
# 查验测试样本的数量和类别分布。
y_test.value_counts()
2    100
4     71
Name: Class, dtype: int64
import warnings
warnings.filterwarnings('ignore')
# 从sklearn.preprocessing里导入StandardScaler。
from sklearn.preprocessing import StandardScaler
# 从sklearn.linear_model里导入LogisticRegression与SGDClassifier。
from sklearn.linear_model import LogisticRegression
from sklearn.linear_model import SGDClassifier

# 标准化数据,保证每个维度的特征数据方差为1,均值为0。使得预测结果不会被某些维度过大的特征值而主导。
ss = StandardScaler()
X_train = ss.fit_transform(X_train)
X_test = ss.transform(X_test)
X_train
array([[-1.19196677, -0.68788787, -0.03809494, ..., -0.55666054,
        -0.58626819, -0.34343195],
       [-1.19196677,  0.30608745, -0.03809494, ...,  0.68611648,
         1.09441105, -0.34343195],
       [ 0.24231522, -0.02523765, -0.72246721, ..., -0.97091955,
        -0.58626819, -0.34343195],
       ...,
       [ 0.24231522, -0.68788787, -0.38028108, ..., -0.97091955,
        -0.58626819, -0.34343195],
       [-1.19196677, -0.68788787, -0.72246721, ..., -0.55666054,
        -0.58626819, -0.34343195],
       [ 0.95945621, -0.02523765, -0.38028108, ...,  0.68611648,
         0.42213936,  1.42674078]])
# 初始化LogisticRegression与SGDClassifier。
lr = LogisticRegression()
sgdc = SGDClassifier()

# 调用LogisticRegression中的fit函数/模块用来训练模型参数。
lr.fit(X_train, y_train)
# 使用训练好的模型lr对X_test进行预测,结果储存在变量lr_y_predict中。
lr_y_predict = lr.predict(X_test)

# 调用SGDClassifier中的fit函数/模块用来训练模型参数。
sgdc.fit(X_train, y_train)
# 使用训练好的模型sgdc对X_test进行预测,结果储存在变量sgdc_y_predict中。
sgdc_y_predict = sgdc.predict(X_test)

性能评测
上面的代码,我们通过调用Logisitic Regression和SGDClassifier对测试集进行预测。并且将预测的结果保存在y_test中。通过比较预测的结果和真实值进行对比,计算预测的正确的比例。我们把这个百分比称为准确性(Accuracy),把它当做评估分类模型的一个重要性能指标。

然而在许多情况下,我们往往更关注对某一特定类别的预测能力。比如,我们需要预测出有多少恶性肿瘤被诊断出来,这时候准确性指标就变得很笼统了。

所以我们引入另外两个指标,分别是召回率(Recall)和精确率(Precision)。它们的定义分别是:
A c c u r a c y = # (  True positive  ) + # ( True negative ) # (  True positive  ) + # ( True negative ) # (  False positive  ) # ( False negative ) Accuracy=\frac{\#(\text { True positive })+\#(\text{True negative})}{\#(\text { True positive })+\#(\text{True negative})\#(\text { False positive })\#(\text{False negative})} Accuracy=#( True positive )+#(True negative)#( False positive )#(False negative)#( True positive )+#(True negative)

P r e c i s o n = # (  True positive  ) # (  True positive  ) + # (  False positive  ) Precison=\frac{\#(\text { True positive })}{\#(\text { True positive })+\#(\text { False positive })} Precison=#( True positive )+#( False positive )#( True positive )

R e c a l l = # (  True positive  ) # (  True positive  ) + # (  False negative  ) Recall=\frac{\#(\text { True positive })}{\#(\text { True positive })+\#(\text { False negative })} Recall=#( True positive )+#( False negative )#( True positive )

其中,#(True positive)代表真阳性样本的数量,其余依次类推。此外,为了综合考量召回率与精准率,我们计算这两个指标的调和平均数,得到F1指标(F1 measure):
之所以使用调和平均数,是因为它除了具备平均功能外,还会对那些召回率和精确率更加接近的模型给予更高的分数;而这也是我们所期待的,因为那些召回率和精确率差距过大的学习模型,往往没有足够的实用价值。

F 1 m e s u r e = 2 1 1  Precision  + 1 Recall ⁡ F1 mesure=\frac{2}{\frac{1}{\frac{1}{\text { Precision }}+\frac{1}{\operatorname{Recall}}}} F1mesure= Precision 1+Recall112

# 从sklearn.metrics里导入classification_report模块。
from sklearn.metrics import classification_report

# 使用逻辑斯蒂回归模型自带的评分函数score获得模型在测试集上的准确性结果。
print ('Accuracy of LR Classifier:', lr.score(X_test, y_test))
# 利用classification_report模块获得LogisticRegression其他三个指标的结果。
print (classification_report(y_test, lr_y_predict, target_names=['Benign', 'Malignant']))
Accuracy of LR Classifier: 0.9883040935672515
              precision    recall  f1-score   support

      Benign       0.99      0.99      0.99       100
   Malignant       0.99      0.99      0.99        71

   micro avg       0.99      0.99      0.99       171
   macro avg       0.99      0.99      0.99       171
weighted avg       0.99      0.99      0.99       171
 # 使用随机梯度下降模型自带的评分函数score获得模型在测试集上的准确性结果。
print ('Accuarcy of SGD Classifier:', sgdc.score(X_test, y_test))
# 利用classification_report模块获得SGDClassifier其他三个指标的结果。
print (classification_report(y_test, sgdc_y_predict, target_names=['Benign', 'Malignant']))
Accuarcy of SGD Classifier: 0.935672514619883
              precision    recall  f1-score   support

      Benign       0.90      1.00      0.95       100
   Malignant       1.00      0.85      0.92        71

   micro avg       0.94      0.94      0.94       171
   macro avg       0.95      0.92      0.93       171
weighted avg       0.94      0.94      0.93       171

最后我们发现Logisitic Regression比起SGDClassifier在测试集上有更高的准确性。这是因为Sklearn中采用解析的方式精确计算Logisitic Regression的参数,而使用梯度法估计SGDClassifier的参数。

2.1.1.2 支持向量(分类)

在这里插入图片描述
从图中可以看出H1直线在训练样本上表现不好,本身带有分类错误;H2和H3直线作为这个二分类问题的线性分类模型,在训练集上的表现都是完美的。

支持向量机分类器(Support Vector Classifier),便是根据训练样本的分布,搜索所有可能的线性分类器中最佳的那个。观察上面的图片,我们发现决定其直线位置的样本并不是所有的训练数据,而是其中的两个不同类别的数据点,而我们把这种可以用来真正帮助决策最优线性分类模型的数据点叫做“支持向量”

数据描述
邮政系统每天都会处理大量的邮件,最为紧要的一环是根据信件上的收信人邮编进行识别和分类,以便确定邮件的投送地。然而,因为多数的邮编都是手写的数字,各式各样,没有统一编制的规则可以很好地用于识别和分类。机器学习兴起之后,开始逐渐有研究人员重新考虑这项任务,支持向量机可以在手写数字图片的分类任务上展现良好的性能。因为,接下来我们将使用支持向量机分类器处理Sklearn内部集成的手写体数字图片数据集。

手写体数据读取
import warnings
warnings.filterwarnings('ignore')
# 从sklearn.datasets里导入手写体数字加载器。
from sklearn.datasets import load_digits
# 从通过数据加载器获得手写体数字的数码图像数据并储存在digits变量中。
digits = load_digits()
# 检视数据规模和特征维度。
digits.data.shape
(1797, 64)
digits.data
array([[ 0.,  0.,  5., ...,  0.,  0.,  0.],
       [ 0.,  0.,  0., ..., 10.,  0.,  0.],
       [ 0.,  0.,  0., ..., 16.,  9.,  0.],
       ...,
       [ 0.,  0.,  1., ...,  6.,  0.,  0.],
       [ 0.,  0.,  2., ..., 12.,  0.,  0.],
       [ 0.,  0., 10., ..., 12.,  1.,  0.]])
digits.target
array([0, 1, 2, ..., 8, 9, 8])
手写体数据分割
# 从sklearn.cross_validation中导入train_test_split用于数据分割。
from sklearn.model_selection import train_test_split

# 随机选取75%的数据作为训练样本;其余25%的数据作为测试样本。
X_train, X_test, y_train, y_test = train_test_split(digits.data, digits.target, test_size=0.25, random_state=33)
y_train.shape
(1347,)
y_test.shape
(450,)
使用支持向量机对手写体数字图像进行识别
# 从sklearn.preprocessing里导入数据标准化模块。
from sklearn.preprocessing import StandardScaler

# 从sklearn.svm里导入基于线性假设的支持向量机分类器LinearSVC。
from sklearn.svm import LinearSVC

# 从仍然需要对训练和测试的特征数据进行标准化。
ss = StandardScaler()
X_train = ss.fit_transform(X_train)
X_test = ss.transform(X_test)

# 初始化线性假设的支持向量机分类器LinearSVC。
lsvc = LinearSVC()
#进行模型训练
lsvc.fit(X_train, y_train)
# 利用训练好的模型对测试样本的数字类别进行预测,预测结果储存在变量y_predict中。
y_predict = lsvc.predict(X_test)
支持向量机模型对手写体数码图像识别能力的评估
# 使用模型自带的评估函数进行准确性测评。
print ('The Accuracy of Linear SVC is', lsvc.score(X_test, y_test))
The Accuracy of Linear SVC is 0.9533333333333334
# 依然使用sklearn.metrics里面的classification_report模块对预测结果做更加详细的分析。
from sklearn.metrics import classification_report
print (classification_report(y_test, y_predict, target_names=digits.target_names.astype(str)))
  precision    recall  f1-score   support

           0       0.92      1.00      0.96        35
           1       0.96      0.98      0.97        54
           2       0.98      1.00      0.99        44
           3       0.93      0.93      0.93        46
           4       0.97      1.00      0.99        35
           5       0.94      0.94      0.94        48
           6       0.96      0.98      0.97        51
           7       0.92      1.00      0.96        35
           8       0.98      0.84      0.91        58
           9       0.95      0.91      0.93        44

   micro avg       0.95      0.95      0.95       450
   macro avg       0.95      0.96      0.95       450
weighted avg       0.95      0.95      0.95       450
2.1.1.3 朴素贝叶斯

朴素贝叶斯(Naive Bayes)是一个非常简单,但是实用性很强的分类模型。不过,和上述两个基于线性假设的模型线性分类器和支持向量机分类器)不同,朴素贝叶斯分类器的构造基础是贝叶斯理论。

抽象点说朴素贝叶斯会单独考量每一维度特征被分类的条件概率,进而综合这些概率并对其所在的特征向量做出分类预测。因此,这个模型的基本数学假设是:各个维度上的特征被分类的条件概率之间是相互独立的。

如果采用概率模型来表述,则定义 x = &lt; x 1 , x 2 , ⋯ &ThinSpace; , x n &gt; x=&lt;x_{1}, x_{2}, \cdots, x_{n}&gt; x=<x1,x2,,xn>为某一n维特征向量, y ∈ y \in y { c 1 , c 2 , ⋯ &ThinSpace; , c k } \left\{c_{1}, c_{2}, \cdots, c_{k}\right\} {c1,c2,,ck}为该特征向量 x x x所有 k k k中可能的类别,记 P ( y = c i ∣ x ) P\left(y=c_{i} | x\right) P(y=cix)特征向量 x x x所属于类别 c i c_{i} ci的概率。根据贝叶斯原理:
P ( y ∣ x ) = P ( x ∣ y ) P ( y ) P ( x ) P(y | x)=\frac{P(x | y) P(y)}{P(x)} P(yx)=P(x)P(xy)P(y)
我们的目标是寻找所有 y ∈ { c 1 , c 2 , ⋯ &ThinSpace; , c k } y \in\left\{c_{1}, c_{2}, \cdots, c_{k}\right\} y{c1,c2,,ck} P ( y ∣ x ) P(y | \boldsymbol{x}) P(yx)最大的,即 argmax ⁡ y P ( y ∣ x ) \operatorname{argmax}_{y} P(y | x) argmaxyP(yx);并且考虑到 P ( x ) P(x) P(x)对于同一样本都是相同的,因此可以忽略不计。所以,
argmax ⁡ y P ( y ∣ x ) = argmax ⁡ y P ( x ∣ y ) P ( y ) = argmax ⁡ y P ( x 1 , x 2 , ⋯ &ThinSpace; , x n ∣ y ) P ( y ) \operatorname{argmax}_{y} P(y | x)=\operatorname{argmax}_{y} P(x | y) P(y)=\operatorname{argmax}_{y} P\left(x_{1}, x_{2}, \cdots, x_{n} | y\right) P(y) argmaxyP(yx)=argmaxyP(xy)P(y)=argmaxyP(x1,x2,,xny)P(y)
若每一种特征可能的取值均为0或者1,在没有任何特殊假设的条件下,计算 P ( x 1 , x 2 , ⋯ &ThinSpace; , x n ∣ y ) P\left(x_{1}, x_{2}, \cdots, x_{n} | y\right) P(x1,x2,,xny)需要对 k ∗ 2 n k * 2^{n} k2n可能的参数进行估计:
P ( x 1 , x 2 , ⋯ &ThinSpace; , x n ∣ y ) = P ( x 1 ∣ y ) P ( x 2 ∣ x 1 , y ) P ( x 3 ∣ x 1 , x 2 , y ) ⋯ P ( x n ∣ x 1 , x 2 , ⋯ &ThinSpace; , x n − 1 , y ) P\left(x_{1}, x_{2}, \cdots, x_{n} | y\right)=P\left(x_{1} | y\right) P\left(x_{2} | x_{1}, y\right) P\left(x_{3} | x_{1}, x_{2}, y\right) \cdots P\left(x_{n} | x_{1}, x_{2}, \cdots, x_{n-1}, y\right) P(x1,x2,,xny)=P(x1y)P(x2x1,y)P(x3x1,x2,y)P(xnx1,x2,,xn1,y)

但是由于朴素贝叶斯模型的特征类别条件独立假设, P ( x n ∣ x 1 , x 2 , ⋯ &ThinSpace; , x n − 1 , y ) = P\left(x_{n} | x_{1}, x_{2}, \cdots, x_{n-1}, y\right)= P(xnx1,x2,,xn1,y)= P ( x n ∣ y ) P\left(x_{n} | y\right) P(xny);若依然每一种特征可能的取值只有2种,那么只需要估计2 k n k n kn个参数,即 P ( x 1 P\left(x_{1}\right. P(x1 = 0 ∣ y = c 1 ) , P ( x 1 = 1 ∣ y = c 1 ) , ⋯ &ThinSpace; , P ( x n = 1 ∣ y = c k ) =0 | y=c_{1} ), P\left(x_{1}=1 | y=c_{1}\right), \cdots, P\left(x_{n}=1 | y=c_{k}\right) =0y=c1),P(x1=1y=c1),,P(xn=1y=ck)

为了估计每个参数的概率,采用如下的公式,并且改用频率比近似计算概率:
P ( x n = 1 ∣ y = c k ) = P ( x n = 1 , y = c k ) P ( y = c k ) = # ( x n = 1 , y = c k ) # ( y = c k ) P\left(x_{n}=1 | y=c_{k}\right)=\frac{P\left(x_{n}=1, y=c_{k}\right)}{P\left(y=c_{k}\right)}=\frac{\#\left(x_{n}=1, y=c_{k}\right)}{\#\left(y=c_{k}\right)} P(xn=1y=ck)=P(y=ck)P(xn=1,y=ck)=#(y=ck)#(xn=1,y=ck)

数据描述:朴素贝叶斯模型咋文本分类任务中有着广泛应用。包括互联网的分类、垃圾邮件的筛选等。这里我们使用经典的20类新闻文本作为实验数据。

# 从sklearn.datasets里导入新闻数据抓取器fetch_20newsgroups。
from sklearn.datasets import fetch_20newsgroups
# 与之前预存的数据不同,fetch_20newsgroups需要即时从互联网下载数据。
news = fetch_20newsgroups(subset='all')
# 查验数据规模和细节。
print(len(news.data))
print(news.data[0])
18846
From: Mamatha Devineni Ratnam <mr47+@andrew.cmu.edu>
Subject: Pens fans reactions
Organization: Post Office, Carnegie Mellon, Pittsburgh, PA
Lines: 12
NNTP-Posting-Host: po4.andrew.cmu.edu


I am sure some bashers of Pens fans are pretty confused about the lack
of any kind of posts about the recent Pens massacre of the Devils. Actually,
I am  bit puzzled too and a bit relieved. However, I am going to put an end
to non-PIttsburghers' relief with a bit of praise for the Pens. Man, they
are killing those Devils worse than I thought. Jagr just showed you why
he is much better than his regular season stats. He is also a lot
fo fun to watch in the playoffs. Bowman should let JAgr have a lot of
fun in the next couple of games since the Pens are going to beat the pulp out of Jersey anyway. I was very disappointed not to see the Islanders lose the final
regular season game.          PENS RULE!!!
news.target
array([10,  3, 17, ...,  3,  1,  7])
news.target_names
['alt.atheism',
 'comp.graphics',
 'comp.os.ms-windows.misc',
 'comp.sys.ibm.pc.hardware',
 'comp.sys.mac.hardware',
 'comp.windows.x',
 'misc.forsale',
 'rec.autos',
 'rec.motorcycles',
 'rec.sport.baseball',
 'rec.sport.hockey',
 'sci.crypt',
 'sci.electronics',
 'sci.med',
 'sci.space',
 'soc.religion.christian',
 'talk.politics.guns',
 'talk.politics.mideast',
 'talk.politics.misc',
 'talk.religion.misc']

20类新闻文本数据分割

# 从sklearn.model_selection 导入 train_test_split。
from sklearn.model_selection import train_test_split
# 随机采样25%的数据样本作为测试集。
X_train, X_test, y_train, y_test = train_test_split(news.data, news.target, test_size=0.25, random_state=33)

使用朴素贝叶斯分类器对新闻文本进行类别预测

# 从sklearn.feature_extraction.text里导入用于文本特征向量转化模块。详细介绍请读者参考3.1.1.1 特征抽取一节。
from sklearn.feature_extraction.text import CountVectorizer

vec = CountVectorizer()
X_train = vec.fit_transform(X_train)
X_test = vec.transform(X_test)

# 从sklearn.naive_bayes里导入朴素贝叶斯模型。
from sklearn.naive_bayes import MultinomialNB

# 从使用默认配置初始化朴素贝叶斯模型。
mnb = MultinomialNB()
# 利用训练数据对模型参数进行估计。
mnb.fit(X_train, y_train)
# 对测试样本进行类别预测,结果存储在变量y_predict中。
y_predict = mnb.predict(X_test)

对朴素贝叶斯分类器在新闻文本数据上的表现性能进行评估

# 从sklearn.metrics里导入classification_report用于详细的分类性能报告。
from sklearn.metrics import classification_report
print ('The accuracy of Naive Bayes Classifier is', mnb.score(X_test, y_test))
print (classification_report(y_test, y_predict, target_names = news.target_names))
The accuracy of Naive Bayes Classifier is 0.8397707979626485
                          precision    recall  f1-score   support

             alt.atheism       0.86      0.86      0.86       201
           comp.graphics       0.59      0.86      0.70       250
 comp.os.ms-windows.misc       0.89      0.10      0.17       248
comp.sys.ibm.pc.hardware       0.60      0.88      0.72       240
   comp.sys.mac.hardware       0.93      0.78      0.85       242
          comp.windows.x       0.82      0.84      0.83       263
            misc.forsale       0.91      0.70      0.79       257
               rec.autos       0.89      0.89      0.89       238
         rec.motorcycles       0.98      0.92      0.95       276
      rec.sport.baseball       0.98      0.91      0.95       251
        rec.sport.hockey       0.93      0.99      0.96       233
               sci.crypt       0.86      0.98      0.91       238
         sci.electronics       0.85      0.88      0.86       249
                 sci.med       0.92      0.94      0.93       245
               sci.space       0.89      0.96      0.92       221
  soc.religion.christian       0.78      0.96      0.86       232
      talk.politics.guns       0.88      0.96      0.92       251
   talk.politics.mideast       0.90      0.98      0.94       231
      talk.politics.misc       0.79      0.89      0.84       188
      talk.religion.misc       0.93      0.44      0.60       158

               micro avg       0.84      0.84      0.84      4712
               macro avg       0.86      0.84      0.82      4712
            weighted avg       0.86      0.84      0.82      4712

通过结果,我们可以看到朴素贝叶斯分类器对4712条新闻文本测试样本分类的准确性约为83.977%。

缺点:受强假设的限制,模型训练时无法将各个特征之间的联系考量在内,使得该模型在其他数据特征关联性较强的分类任务上的性能表现不佳

2.1.1.4 K近邻(分类)

思想:简单来说就是样本数据离谁近就归并到哪一类。

数据描述:鸢尾花数据集

# 从sklearn.datasets 导入 iris数据加载器。
from sklearn.datasets import load_iris
# 使用加载器读取数据并且存入变量iris。
iris = load_iris()
# 查验数据规模。
iris.data.shape
(150, 4)
# 查看数据说明。对于一名机器学习的实践者来讲,这是一个好习惯。
print (iris.DESCR)
.. _iris_dataset:

Iris plants dataset
--------------------

**Data Set Characteristics:**

    :Number of Instances: 150 (50 in each of three classes)
    :Number of Attributes: 4 numeric, predictive attributes and the class
    :Attribute Information:
        - sepal length in cm
        - sepal width in cm
        - petal length in cm
        - petal width in cm
        - class:
                - Iris-Setosa
                - Iris-Versicolour
                - Iris-Virginica
                
    :Summary Statistics:

    ============== ==== ==== ======= ===== ====================
                    Min  Max   Mean    SD   Class Correlation
    ============== ==== ==== ======= ===== ====================
    sepal length:   4.3  7.9   5.84   0.83    0.7826
    sepal width:    2.0  4.4   3.05   0.43   -0.4194
    petal length:   1.0  6.9   3.76   1.76    0.9490  (high!)
    petal width:    0.1  2.5   1.20   0.76    0.9565  (high!)
    ============== ==== ==== ======= ===== ====================

    :Missing Attribute Values: None
    :Class Distribution: 33.3% for each of 3 classes.
    :Creator: R.A. Fisher
    :Donor: Michael Marshall (MARSHALL%PLU@io.arc.nasa.gov)
    :Date: July, 1988

The famous Iris database, first used by Sir R.A. Fisher. The dataset is taken
from Fisher's paper. Note that it's the same as in R, but not as in the UCI
Machine Learning Repository, which has two wrong data points.

This is perhaps the best known database to be found in the
pattern recognition literature.  Fisher's paper is a classic in the field and
is referenced frequently to this day.  (See Duda & Hart, for example.)  The
data set contains 3 classes of 50 instances each, where each class refers to a
type of iris plant.  One class is linearly separable from the other 2; the
latter are NOT linearly separable from each other.

.. topic:: References

   - Fisher, R.A. "The use of multiple measurements in taxonomic problems"
     Annual Eugenics, 7, Part II, 179-188 (1936); also in "Contributions to
     Mathematical Statistics" (John Wiley, NY, 1950).
   - Duda, R.O., & Hart, P.E. (1973) Pattern Classification and Scene Analysis.
     (Q327.D83) John Wiley & Sons.  ISBN 0-471-22361-1.  See page 218.
   - Dasarathy, B.V. (1980) "Nosing Around the Neighborhood: A New System
     Structure and Classification Rule for Recognition in Partially Exposed
     Environments".  IEEE Transactions on Pattern Analysis and Machine
     Intelligence, Vol. PAMI-2, No. 1, 67-71.
   - Gates, G.W. (1972) "The Reduced Nearest Neighbor Rule".  IEEE Transactions
     on Information Theory, May 1972, 431-433.
   - See also: 1988 MLC Proceedings, 54-64.  Cheeseman et al"s AUTOCLASS II
     conceptual clustering system finds 3 classes in the data.
   - Many, many more ...

对Iris数据集进行分割

# 从sklearn.model_selection里选择导入train_test_split用于数据分割。
from sklearn.model_selection import train_test_split
# 从使用train_test_split,利用随机种子random_state采样25%的数据作为测试集。
X_train, X_test, y_train, y_test = train_test_split(iris.data, iris.target, test_size=0.25, random_state=33)

使用K近邻分类器对鸢尾花数据进行类别预测

# 从sklearn.preprocessing里选择导入数据标准化模块。
from sklearn.preprocessing import StandardScaler
# 从sklearn.neighbors里选择导入KNeighborsClassifier,即K近邻分类器。
from sklearn.neighbors import KNeighborsClassifier

# 对训练和测试的特征数据进行标准化。
ss = StandardScaler()
X_train = ss.fit_transform(X_train)
X_test = ss.transform(X_test)

# 使用K近邻分类器对测试数据进行类别预测,预测结果储存在变量y_predict中。
knc = KNeighborsClassifier()
knc.fit(X_train, y_train)
y_predict = knc.predict(X_test)
# 使用模型自带的评估函数进行准确性测评。
print ('The accuracy of K-Nearest Neighbor Classifier is', knc.score(X_test, y_test) )
The accuracy of K-Nearest Neighbor Classifier is 0.8947368421052632
# 依然使用sklearn.metrics里面的classification_report模块对预测结果做更加详细的分析。
from sklearn.metrics import classification_report
print (classification_report(y_test, y_predict, target_names=iris.target_names))
    precision    recall  f1-score   support

      setosa       1.00      1.00      1.00         8
  versicolor       0.73      1.00      0.85        11
   virginica       1.00      0.79      0.88        19

   micro avg       0.89      0.89      0.89        38
   macro avg       0.91      0.93      0.91        38
weighted avg       0.92      0.89      0.90        38

特点:K近邻算法与其他模型最大的不同在于:该模型没有参数训练过程。也就是说,我们并没有通过任何学习算法分析训练数据,而是根据测试样本在训练数据的分布直接作出分类决策。所以,K近邻模型属于无参数模型中的一种。正是这样的决策算法,导致了其非常高的计算复杂度和内存消耗。因为该模型每处理一个测试样本都需要对所有预先加载在内存的训练样本进行遍历、逐一计算相似度、排序并且选取K个最近邻训练样本的标记,进而做出分类决策。这是平方级别的算法复杂度,一旦数据规模稍大,使用者便需要权衡更多计算时间的代价。

2.1.1.5 决策树

在前面所使用的逻辑回归和支持向量机模型,都在某种程度上要求数据特征和标签之间遵循线性假设。然而许多情况下并不是这样。

比如,如果根据线性关系来预测一个的年龄来预测患流感的死亡率。那么要么年龄越大死亡率越高,或者年龄越小死亡率越高。然而现实是青年人由于健全的免疫系统不容易死亡。因此这样并不存在线性关系。数学中用分段函数来表示。机器学习模型中,决策树是描述这种非线性关系的不二人选

再比如,信用卡申请的审核涉及申请人的多项特征,也是典型的决策树模型。如图所示,决策树节点代表数据特征,如年龄、身份是否是学生、信用评级等;每个节点下的分支代表对应特征值的分类;而决策树的所有叶子节点则显示模型的决策结果。对于是否通过信用卡申请而言,这是二分类决策任务,因此只有yes和no两种分类结果。
在这里插入图片描述

这类使用多种不同特征组合搭建多层决策树的情况,模型在学习的时候就需要考虑特征节点的选取顺序。常用的度量方式包括信息熵基尼系数

数据描述:泰坦尼克号数据。

# 导入pandas用于数据分析。
import pandas as pd
import warnings
warnings.filterwarnings('ignore')
# 利用pandas的read_csv模块直接从互联网收集泰坦尼克号乘客数据。
titanic = pd.read_csv('http://biostat.mc.vanderbilt.edu/wiki/pub/Main/DataSets/titanic.txt')
# 观察一下前几行数据,可以发现,数据种类各异,数值型、类别型,甚至还有缺失数据。
titanic.head()

在这里插入图片描述

# 使用pandas,数据都转入pandas独有的dataframe格式(二维数据表格),直接使用info(),查看数据的统计特性。
titanic.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1313 entries, 0 to 1312
Data columns (total 11 columns):
row.names    1313 non-null int64
pclass       1313 non-null object
survived     1313 non-null int64
name         1313 non-null object
age          633 non-null float64
embarked     821 non-null object
home.dest    754 non-null object
room         77 non-null object
ticket       69 non-null object
boat         347 non-null object
sex          1313 non-null object
dtypes: float64(1), int64(2), object(8)
memory usage: 112.9+ KB
# 机器学习有一个不太被初学者重视,并且耗时,但是十分重要的一环,特征的选择,这个需要基于一些背景知识。根据我们对这场事故的了解,sex, age, pclass这些都很有可能是决定幸免与否的关键因素。
X = titanic[['pclass', 'age', 'sex']]
y = titanic['survived']

# 对当前选择的特征进行探查。
X.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1313 entries, 0 to 1312
Data columns (total 3 columns):
pclass    1313 non-null object
age       633 non-null float64
sex       1313 non-null object
dtypes: float64(1), object(2)
memory usage: 30.9+ KB
# 借由上面的输出,我们设计如下几个数据处理的任务:
# 1) age这个数据列,只有633个,需要补完。
# 2) sex 与 pclass两个数据列的值都是类别型的,需要转化为数值特征,用0/1代替。

# 首先我们补充age里的数据,使用平均数或者中位数都是对模型偏离造成最小影响的策略。
X['age'].fillna(X['age'].mean(), inplace=True)
# 对补完的数据重新探查。
X.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1313 entries, 0 to 1312
Data columns (total 3 columns):
pclass    1313 non-null object
age       1313 non-null float64
sex       1313 non-null object
dtypes: float64(1), object(2)
memory usage: 30.9+ KB
# 由此得知,age特征得到了补完。

# 数据分割。
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state = 33)
# 我们使用scikit-learn.feature_extraction中的特征转换器,详见3.1.1.1特征抽取。
from sklearn.feature_extraction import DictVectorizer
vec = DictVectorizer(sparse=False)

# 转换特征后,我们发现凡是类别型的特征都单独剥离出来,独成一列特征,数值型的则保持不变。
X_train = vec.fit_transform(X_train.to_dict(orient='record'))
print (vec.feature_names_)
['age', 'pclass=1st', 'pclass=2nd', 'pclass=3rd', 'sex=female', 'sex=male']
X_train
array([[31.19418104,  0.        ,  0.        ,  1.        ,  0.        ,
         1.        ],
       [31.19418104,  1.        ,  0.        ,  0.        ,  1.        ,
         0.        ],
       [31.19418104,  0.        ,  0.        ,  1.        ,  0.        ,
         1.        ],
       ...,
       [12.        ,  0.        ,  1.        ,  0.        ,  1.        ,
         0.        ],
       [18.        ,  0.        ,  1.        ,  0.        ,  0.        ,
         1.        ],
       [31.19418104,  0.        ,  0.        ,  1.        ,  1.        ,
         0.        ]])
# 同样需要对测试数据的特征进行转换。
X_test = vec.transform(X_test.to_dict(orient='record'))
# 从sklearn.tree中导入决策树分类器。
from sklearn.tree import DecisionTreeClassifier
# 使用默认配置初始化决策树分类器。
dtc = DecisionTreeClassifier()
# 使用分割到的训练数据进行模型学习。
dtc.fit(X_train, y_train)
# 用训练好的决策树模型对测试特征数据进行预测。
y_predict = dtc.predict(X_test)
# 从sklearn.metrics导入classification_report。
from sklearn.metrics import classification_report
# 输出预测准确性。
print (dtc.score(X_test, y_test))
# 输出更加详细的分类性能。
print (classification_report(y_predict, y_test, target_names = ['died', 'survived']))
0.7811550151975684
              precision    recall  f1-score   support

        died       0.91      0.78      0.84       236
    survived       0.58      0.80      0.67        93

   micro avg       0.78      0.78      0.78       329
   macro avg       0.74      0.79      0.75       329
weighted avg       0.81      0.78      0.79       329

分析:决策树模型在测试集上的预测准确性约为78.12%。详细的性能指标进一步说明,该模型在预测遇难者方面性能较好;却需要在识别生还者方便下功夫。

决策树的推断逻辑非常直观,具有清晰的可解释性,也方便了模型的可视化。这些特性同时也保证在使用决策树模型时,是无需考虑对数据的量化甚至是标准化的。并且,决策树属于有参模型,需要花费更多的时间在训练集上。

p75

2.1.2 回归预测

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

安替-AnTi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值