0 实验环境
python 3.7.0
- matplotlib
- scikit-learn
1 预备知识
估计器(Estimator):用于分类、聚类和回归分析。
转换器(Transformer):用于数据预处理和数据转换。
流水线(Pipeline):组合数据挖掘流程,便于再次使用。
欧式距离:连接两点的线段的长度(特征向量长度平方和的平方根)
某些特征取值巨大(离群点)时效果会很差。
稀疏矩阵效果也很差。
曼哈顿距离:两个特征在标准坐标系中绝对轴距之和
余弦距离:特征向量夹角的余弦值
更适合解决异常值和数据稀疏问题
采用哪种距离度量方法对最终结果有很大
影响。
此处我们选用欧氏距离做为实验。
2 加载数据集
我们使用Ionosphere数据集。
URL: http://archive.ics.uci.edu/ml/datasets/Ionosphere 下载ionosphere.data
、ionosphere.names
(我是把文件放在主目录下的data文件夹然后新建了一个ionosphere文件夹)
让图片直接出在jupyter里我们需要做一个配置:
%matplotlib inline
获取主目录
import os
home_folder = os.path.expanduser("~")
print(home_folder)
data_folder = os.path.join(home_folder,"data","ionosphere")
data_filename = os.path.join(data_folder,"ionosphere.data")
print(data_filename)
笔者的测试环境是win10
故输出:
C:\Users\skysys\data\ionosphere\ionosphere.data
然后开始加载数据集,该数据集每行35个值,前34个为17座天线采集的数据(每座天线采集两个数据)最后一个值为g或者是b,表示数据的好坏(是否提供了有价值的信息)
我们的任务是建立一个分类器,判断数据的好坏。
import numpy as np
import csv
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'
3 数据处理
scikit-learn内部实现了大量的分类算法,把相关功能封装成一个估计器,用于分类任务。主要包含以下两个函数:
- fit():训练算法,设置内部参数。 参数为训练集和类别
- predict():参数为测试集。返回预测结果。
本文选择近邻算法
划分数据集:
from sklearn.model_selection import train_test_split
x_train,x_test,y_train,y_test = train_test_split(x,y,random_state=14)
print("There are {} samples in the training dataset".format(x_train.shape[0]))
print("There are {} samples in the testing dataset".format(x_test.shape[0]))
print("Each sample has {} features".format(x_train.shape[1]))
There are 263 samples in the training dataset
There are 88 samples in the testing dataset
Each sample has 34 features
近邻算法思想:为了对新个体分类,查找训练集,找到与新个体最相似的那些个体,这些个体大多属于的类别就是新个体的类别。
该算法在特征值取离散值时效果很差。
为了实现这个算法,重点需要衡量两个个体的相似度,在文章开头介绍过的几种距离都是常用的方式。
然后我们借助scikit-learn来实现:
导入k近邻估计器:
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’)
4 算法评估
评估算法:
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%
5 交叉检验
avg_scores = []
all_scores = []
parameter_values = list(range(1,21))
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)
可能会报futureWarning,有强迫症的话参考笔者之前写过的一篇博客消futureWarning:
作图
from matplotlib import pyplot as plt
plt.figure(figsize=(32,20))
plt.plot(parameter_values,avg_scores,'-o',linewidth=5,markersize=24)
for parameter,scores in zip(parameter_values,all_scores):
n_scores = len(scores)
plt.plot([parameter] * n_scores,scores,'-o')
plt.plot(parameter_values,all_scores,'bx')
from collections import defaultdict
all_scores = defaultdict(list)
parameter_values = list(range(1, 21)) # Including 20
for n_neighbors in parameter_values:
for i in range(100):
estimator = KNeighborsClassifier(n_neighbors=n_neighbors)
scores = cross_val_score(estimator, X, y, scoring='accuracy', cv=10)
all_scores[n_neighbors].append(scores)
for parameter in parameter_values:
scores = all_scores[parameter]
n_scores = len(scores)
plt.plot([parameter] * n_scores, scores, '-o')