数据挖掘系列笔记(3)——估计器

内容提要:估计器是scikit库里面已经封装好的识别算法模板,通过直接调用估计器的函数能完成自动的分类算法,并进行输出准确率估计。实用性来看未必很准确,但是如果能找到合适的方法和参数,要比自己构造模型训练算法方便很多。

主要包括以下概念:

 估计器(Estimator):用于分类、聚类和回归分析。
 转换器(Transformer):用于数据预处理和数据转换。
 流水线(Pipeline):组合数据挖掘流程,便于再次使用。

scikit-learn提供了大量估计器,其中有支持向量机(SVM)、随机森林、神经网络等。后边的例子采用近邻算法。

近邻算法原理就是找一个个体最接近的样本所属于的类别作为他自己的类别。这里面涉及两个问题:样本的特征值要怎么取,这里是对样本的建模问题;另一个问题就是如何定义邻近,换句话就是:个体距离的定义。

特征值的选择不是这里的讨论范围,我们假设已经选好了特征值;距离的定义问题则是数据挖掘中的一个核心问题:距离的定义会直接影响到分类结果。下面介绍几个距离计算方法:

我们最常见的分类方法是欧氏距离,也就是真实距离。比如我们在坐标系上画两个点,那么连一条线段,长度就是距离。计算的话就是特征向量平方和的平方根(a^2 + b^2 = c^2)。欧氏距离的局限性在于,如果特征向量中很多特征值都为0,也就是构成稀疏矩阵,计算结果并不理想;如果存在显著大的特征值,那么他对结果的影响也会特别显著。

曼哈顿距离:两个特征在标准坐标系中绝对轴距之和(没有使用平方距离)。可以把坐标系抽象出很多正南北正东西的路,不能走斜线的距离就是曼哈顿距离(也许是曼哈顿街区都是这种直角路,所以才叫曼哈顿距离?)

余弦距离:余弦距离更适合解决异常值和数据稀疏问题。这个距离不计算向量的长度,只关注特征向量夹角的余弦。

数据挖掘系列笔记(3)——估计器_第1张图片

接下来的实验只使用了欧氏距离,作为原理验证。

数据来源:Ionosphere数据集可以从UCI机器学习数据库下载,该数据库包含大量数据集,可用于多种数据挖掘任务。打开http://archive.ics.uci.edu/ml/datasets/Ionosphere,点击Data Folder。在随后打开的页面中,下载ionosphere.data和ionosphere.names文件。

代码会直接贴后面。实验需要安装matplotlib显示算法的训练结果。下载下来的数据是351*35的数组,最后一列是判断结果,有g和f两类,前34列则够成特征向量,用来描述对象个体。算法的任务就是,通过识别34维的特征向量给出一个分类为g或者不是。第一步是构造特征向量矩阵和结果向量:

数据挖掘系列笔记(3)——估计器_第2张图片

继续使用上一个笔记中提到的拆分训练数据和测试数据的算法:

接下来就是见证奇迹的时刻:使用近邻算法直接载入训练数据:

数据挖掘系列笔记(3)——估计器_第3张图片

这时模型已经训练完毕了。

可以导入训练数据进行准确度计算:

可以看到近邻算法在这里表现还是比较不错的。可是,我们有没有办法提升这个库函数的性能呢,因为函数对外只提供接口,如果效果达不到要求,我们有没有办法改进也是关键问题。KNeighborClassifier提供了一个距离参数,修改参数就能修改近邻的范围定义,可以把邻居圈画大一点或者小一点。这里结合作图展示,效果更直观:

from sklearn.model_selection import cross_val_score
avg_scores = []
all_scores = []
parametier_values = list(range(1, 21))
for n_neighbors in parametier_values:
    estimator = KNeighborsClassifier(n_neighbors=n_neighbors)
    scores = cross_val_score(estimator, X, y, scoring = 'accuracy')
    avg_scores.append(np.mean(scores))
    all_scores.append(scores)

from matplotlib import pyplot as plt
plt.figure(figsize=(32,20))
plt.plot(parametier_values, avg_scores, '-o', linewidth=5, markersize=24)

数据挖掘系列笔记(3)——估计器_第4张图片

可见近邻值选择2的时候效果最好。以上就是估计器的傻瓜式使用方法。

接下来是转换器。转换器的作用简单来说就是特征值修复,比如我们有一个显著怪的特征值,它会很大程度上破坏整体的特征,那么怎么识别并处理这个数据呢,针对这个情况我们提出一个预处理的概念。为了减少极端大特征值影响特征向量,数据科学家提出使用0-1的值来规范特征值,这样数据直接仅剩相对大小,这是影响就小很多了。处理方法为:引入MinMaxScaler,直接调用转换函数。转换就是1行代码:

X_transformed = MinMaxScaler().fit_transform(X)

 还有很多其他类似的规范化方法,对于其他类型的应用和特征类型会很有用。
 为使每条数据各特征值的和为1,使用sklearn.preprocessing.Normalizer。
 为使各特征的均值为0,方差为1,使用sklearn.preprocessing.StandardScaler,常用作规范化的基准。
 为将数值型特征的二值化,使用sklearn.preprocessing.Binarizer,大于阈值的为1,反之为0。

最后来说流水线:必要性来自于随着实验的增加,操作的复杂程度也在提高。我们可能需要切分数据集,对特征进行二值化
处理,以特征或数据集中的个体为基础规范化数据,除此之外还可能需要其他各种操作。要跟踪记录所有这些操作可不容易,如果中间出点问题,先前实验的结果将很难再现。常见问题有落下步骤,数据转换错误,或进行了不必要的转换操作等。另一个问题就是代码的先后顺序。上一节,我们创建了X_transformed数据集,然后创建了一个新的估计器用于交叉检验。如果有多个步骤,就需要跟踪代码中对数据集进行的每一步操作。

简单来说:需要确定化的流程来让整个过程规范化工业化,方便定位问题,也便于减少差错。

可以借助Pipeline库来构造流水线:如果我们希望首先用MinMaxScaler规范化,然后用KNeighborClassifier预测,那么直接:

from sklearn.pipeline import Pipeline
scaling_pipeline = Pipeline([('scale', MinMaxScaler()),('predict', KNeighborsClassifier())])

然后运行流水线:

scores = cross_val_score(scaling_pipeline, X_broken, y,scoring='accuracy')
print("The pipeline scored an average accuracy for is {0:.1f}%".format(np.mean(transformed_scores) * 100))

这样就直接得到结论了。

import numpy as np

import csv

%matplotlib inline

import os

print(os.path.expanduser("~"))

data_filename = os.path.join(data_folder, "Ionosphere","ionosphere.data")

print(data_filename)


data_folder = "C:\\Users\\Tao\\Data"

data_filename = os.path.join(data_folder, "Ionosphere","ionosphere.data")

print(data_filename)

C:\Users\Tao\Data\Ionosphere\ionosphere.data

X = np.zeros((351, 34), dtype='float')

y = np.zeros((351, ), dtype = 'bool')

with open(data_filename, 'r') as input_file:

    reader = csv.reader(input_file)

    for i, row in enumerate(reader):

        data = [float(datum) for datum in row [:-1]]

        X[i] = data

        y[i] = row[-1] == 'g'

from sklearn.model_selection import  train_test_split

X_train, X_test, y_train, y_test = train_test_split(X, y, random_state = 14)

from sklearn.neighbors import KNeighborsClassifier

estimator = KNeighborsClassifier()

estimator.fit(X_train, y_train)

KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',
           metric_params=None, n_jobs=None, n_neighbors=5, p=2,
           weights='uniform')

y_predicted = estimator.predict(X_test)

accuracy = np.mean(y_test == y_predicted) * 100

print("The accuracy is {0:.1f}%".format(accuracy))

The accuracy is 86.4%

from sklearn.model_selection import cross_val_score

avg_scores = []

all_scores = []

parametier_values = list(range(1, 21))

for n_neighbors in parametier_values:

    estimator = KNeighborsClassifier(n_neighbors=n_neighbors)

    scores = cross_val_score(estimator, X, y, scoring = 'accuracy')

    avg_scores.append(np.mean(scores))

    all_scores.append(scores)

print(scores)

[0.81196581 0.67521368 0.88888889]

from matplotlib import pyplot as plt

plt.figure(figsize=(32,20))

plt.plot(parametier_values, avg_scores, '-o', linewidth=5, markersize=24)

[]

X_broken = np.array(X)

X_broken[:,::2] /= 10

avg_scores = []

all_scores = []

parametier_values = list(range(1, 21))

for n_neighbors in parametier_values:

    estimator = KNeighborsClassifier(n_neighbors=n_neighbors)

    scores = cross_val_score(estimator, X_broken, y, scoring = 'accuracy')

    avg_scores.append(np.mean(scores))

    all_scores.append(scores)

    y_predicted = estimator.predict(X_test)

    accuracy = np.mean(y_test == y_predicted) * 100

    print("The accuracy is {0:.1f}% at {1}".format(accuracy, n_neighbors))


NotFittedError: This KNeighborsClassifier instance is not fitted yet. Call 'fit' with appropriate arguments before using this method.

plt.figure(figsize=(32,20))

plt.plot(parametier_values, avg_scores, '-o', linewidth=5, markersize=24)

[]

from sklearn.preprocessing import MinMaxScaler

X_transformed = MinMaxScaler().fit_transform(X)

X_transformed = MinMaxScaler().fit_transform(X_broken)

estimator = KNeighborsClassifier()

transformed_scores = cross_val_score(estimator, X_transformed, y,

scoring='accuracy')

print("The average accuracy for is{0:.1f}%".format(np.mean(transformed_scores) * 100))

The average accuracy for is82.3%


​

 

你可能感兴趣的:(数据挖掘)