scikit-learn为了帮助用户实现大量分类算法,scikit-learn把相关功能封装成了所谓的估计器,他用于分类任务。主要包含了两个函数
- fit():训练算法,设置内部参数,该函数接收训练集及其类别两个参数
- predict():参数为测试集。预测测试类别,并返回一个包含测试集各条数据类别的数组。
近邻算法
近邻算法可能诗标准数据挖掘算法中最为直观的一种,为了对新个体进行分类,它查找训练集,找到与新个体最为相似的那些个体。
近邻算法几乎可以对任何数据集进行分类。但是要计算数据集中每两个个体的距离,但是当数据量很大时,计算的距离就太多了,比如我们的数据量有1000时,需要计算大约50万个个体之间的距离,除了计算量大之外,就是在特征取离散值的数据集上表现的很差。
距离是数据挖掘的核心概念之一,我们需要知道两个个体之间的距离是多少,进一步说,我们还能解决一对个体相对另一对个体是否更相似等问题
下面有三种计算距离的方法
- 欧氏距离:既两个点之间连线的距离
- 曼哈顿距离:两个特征值在坐标轴中,横轴距离+纵轴距离之和,也叫街区距离
- 余弦距离:计算坐标轴中余弦值忽略特征向量的长度
这章我们主要说欧氏距离,剩下的会在后续章节中
我们的数据集每行有35个值,前34个为17座天线采集的数据,最后一个值为‘g’或’b’,表示数据是否提供了有价值的信息
首先导入我们需要的numpy和csv,加载数据集
In [32]: import csv
...: import numpy as np
In [33]: X = np.zeros((351, 34), dtype='float')
In [34]: y = np.zeros((351,), dtype='bool')
In [35]: with open('/Users/gn/Downloads/ionosphere.data', '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'
...:
In [36]: X
Out[36]:
array([[ 1. , 0. , 0.99539, ..., -0.54487, 0.18641, -0.453 ],
[ 1. , 0. , 1. , ..., -0.06288, -0.13738, -0.02447],
[ 1. , 0. , 1. , ..., -0.2418 , 0.56045, -0.38238],
...,
[ 1. , 0. , 0.94701, ..., 0.00442, 0.92697, -0.00577],
[ 1. , 0. , 0.90608, ..., -0.03757, 0.87403, -0.16243],
[ 1. , 0. , 0.8471 , ..., -0.06678, 0.85764, -0.06151]])
In [37]: y
Out[37]:
array([ True, False, True, False, True, False, True, False, True,
False, True, False, True, False, True, False, True, False,
True, False, True, False, True, False, True, False, True,
False, True, False, True, False, True, False, True, False,
True, False, True, False, True, False, True, False, True,
False, True, False, True, False, True, False, True, False,
True, False, True, False, True, False, True, False, True,
···
这是我们的数据集True表示这个数据有效
In [38]: from sklearn.model_selection import train_test_split
In [39]: X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=14)
In [40]: print("有 {} 个样本作为训练集".format(X_train.shape[0]))
...: print("有 {} 个样本作为测试集".format(X_test.shape[0]))
...: print("每个样本有 {} 个特征值".format(X_train.shape[1]))
有 263 个样本作为训练集
有 88 个样本作为测试集
每个样本有 34 个特征值
In [41]: from sklearn.neighbors import KNeighborsClassifier #导入K近邻分类器
In [42]: estimator = KNeighborsClassifier() #初始化一个K近邻分类器实例,该算法默认选择5个近邻作为分类依据
In [43]: estimator.fit(X_train, y_train) #训练
Out[43]:
KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',
metric_params=None, n_jobs=None, n_neighbors=5, p=2,
weights='uniform')
In [44]: y_predicted = estimator.predict(X_test)
In [45]: accuracy = np.mean(y_test == y_predicted) * 100
In [46]: print("正确率为{0:.1f}%".format(accuracy))
正确率为86.4%
In [47]: y_predicted
Out[47]:
array([ True, True, True, True, True, False, True, False, True,
True, True, True, True, True, False, False, True, False,
False, True, True, True, True, False, True, True, True,
True, True, True, True, True, True, False, False, True,
True, True, True, True, True, False, True, False, True,
True, True, True, False, True, True, True, True, True,
False, True, True, True, True, True, False, True, True,
True, True, True, True, True, False, False, False, True,
True, False, True, True, True, False, False, True, False,
True, True, False, True, True, False, True])
In [48]: y_test
Out[48]:
array([ True, False, True, True, True, False, True, False, True,
True, True, False, False, True, False, False, True, True,
False, True, True, True, True, False, True, False, True,
True, True, False, True, True, True, False, False, True,
True, True, True, True, True, False, True, False, True,
True, False, True, False, True, False, True, False, True,
False, True, True, True, True, True, True, True, True,
True, True, True, False, True, False, False, False, True,
True, False, False, True, True, False, False, True, False,
True, True, False, True, True, False, True])
这一段就是,我们先将数据分为测试集和训练集
导入K近邻分类器,使用训练集进行训练,再用测试集来判断准确率
最后我们得出86.4%的真确率,当然了针对不同的数据集,根据实验的实际情况,极可能的选择合适的参数,争取到达最佳效果。
在之前的几个试验里,我们把数据集分为训练集和测试机,用训练集训练算法,测试集评估效果,如果我们的结果是碰巧得出了高正确率该怎么办?就需要交叉实验了。
scikit-learn提供了集中交叉检验的方法我们看一下
In [49]: from sklearn.model_selection import cross_val_score
In [50]: scores = cross_val_score(estimator,X,y,scoring='accuracy')
In [51]: average_accuracy = np.mean(scores) *100
In [52]: average_accuracy
Out[52]: 82.33618233618233
经过交叉实验得到的结果为82.3% 较之前虽然差了一点,但是我们还没有调整过参数,这个结果还是非常好的。下面我们通过调节参数到达更理想的效果
近邻算法有多个参数,最为重要的是选取多少个近邻作为预测依据,这就是n_neighbors。我们测试一下n_neighbors的值,比如从1-20,我们重复多次试验
In [53]: avg_scores = []
In [54]: all_scores = []
In [55]: parameter_values = list(range(1,21))
In [56]: for n_neighbors in parameter_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)
...:
In [57]: from matplotlib import pyplot as plt
In [58]: plt.figure(figsize=(32,20))
...: plt.plot(parameter_values, avg_scores, '-o', linewidth=5, markersize=24)
```
这一段就是我们分别给这个算法的参数设置为1-20,计算交叉检验的准确率。得到一个列表avg_scores,之后我们用matplotlib来绘制一个准确率的图

趋势是很明显的,随着n_neighbors的增大准确率是下降的。