K近邻算法是机器学习中最简单的分类算法之一,这篇文章主要讲解knn算法的在scikit-learn中的使用,其中不仅仅包括了算法本身,还有测试训练集的分离,交叉验证的使用,数据标准化等。
首先用一个简单的例子引入knn算法
import numpy as np
import matplotlib.pyplot as plt
from sklearn.neighbors import KNeighborsClassifier #从sklearn中导入knn分类器
#建立一个简单的group分组,以及每个不同样本对应的lebel
group = np.array([[1,1],[1,1.1],[0,0.1],[0,0]])
labels = np.array(['a','a','b','b'])
#可视化一下我们的数据
plt.scatter(group[labels=='a',0],group[labels=='a',1],color='r')
plt.scatter(group[labels=='b',0],group[labels=='b',1],color='g')
#实现一个简单的knn分类器
knn_cls = KNeighborsClassifier(n_neighbors=3) #n_neighbor表示我们选择的近邻的数据个数
knn_cls.fit(group,labels)
#预测一下(1,1.3)这个数据应该是a还是b
knn_cls.predict([[1,1.3]])
out:array(['a'], dtype='<U1') 这时候分类器告诉我们这个点是属于a分类的
这样一个简单的knn分类器就实现了是不是很简单,下面我们用一个更复杂的例子实现knn分类器以及文章开头我提到的功能。
这里我们使用鸢尾花数据集
in:from sklearn.datasets import load_iris
iris = load_iris()
iris.data
out:array([[5.1, 3.5, 1.4, 0.2],
[4.9, 3. , 1.4, 0.2],
[4.7, 3.2, 1.3, 0.2],
[4.6, 3.1, 1.5, 0.2],
[5. , 3.6, 1.4, 0.2],
[5.4, 3.9, 1.7, 0.4],...]) #这四个特征分别为花萼长度,花萼宽度,花瓣长度,花瓣宽度
in:iris.target
out:array([0, 0, 0, 0, 0, 0, 0...]) #这里的0代表第一种鸢尾花,1代表第二种鸢尾花,2代表第三种鸢尾花由于数据集比较多所以这里只显示了前6个数据,实际上后面还有很多分类为1和分类为2的数据
数据可视化
plt.scatter(X[y==0,0],X[y==0,1],color='g')
plt.scatter(X[y==1,0],X[y==1,1],color='r')
plt.scatter(X[y==2,0],X[y==2,1],color='b')
这时我们取了鸢尾花的花萼长度和花萼宽度两个特征进行了绘图,当然你也可以选取其他两个特征,可以看出鸢尾花的分布还是比较有规律的。
训练测试的分离
由于我们需要对我们训练的模型进行一个评估,所以我们将数据分为测试集和训练集,我们用测试集拟合我们的模型,之后用测试集来对我们的模型好坏进行评估,这样就有了训练测试集的分离
from sklearn.model_selection import train_test_split
X_train,X_test,y_train,y_test = train_test_split(X,y,test_size=0.2,random_state=42) #这里我们设置了训练集与测试集的比例为2:8
数据的标准化
这里我们使用Z-score标准化,在sklearn的学习中,数据集的标准化是很多机器学习模型算法的常见要求。如果个别特征看起来不是很符合正态分布,那么他们可能为表现不好。
from sklearn.preprocessing import StandardScaler #导入均值方差标准化
scaler = StandardScaler()
scaler.fit(X_train) #让我们的scaler拟合测试数据
X_train_scale = scaler.transform(X_train) #这样就能将数据均值方差标准化了
#再来看一下我们的数据
plt.scatter(X_train_scale[y_train==0,0],X_train_scale[y_train==0,1],color='g')
plt.scatter(X_train_scale[y_train==1,0],X_train_scale[y_train==1,1],color='r')
plt.scatter(X_train_scale[y_train==2,0],X_train_scale[y_train==2,1],color='b')
可以看到数据的均值和方差变为了0和1但是实际形状和之前并没有变化。这样的均值方差归一化方便我们的算法更加准确的拟合数据。
超参数的设定以及交叉验证
knn算法我们可以设定不同的参数,首先最清楚的k参数是选择距离最近的数据的个数,还存在一个参数weights,默认情况下weights = uniform 而当weights = distance时,knn算法则会考虑当前样本到邻近K个样本的距离权重,还有关于距离的参数这里我不详细介绍,主要介绍交叉验证这种思想。
param_grid = [
{
'weights':['uniform'],
'n_neighbors':[i for i in range(1,11)]
},
{
'weights':['distance'],
'n_neighbors':[i for i in range(1,11)],
'p':[i for i in range(1,6)]
}
]
#对以上的超参数进行遍历
knn_clf = KNeighborsClassifier()
from sklearn.model_selection import GridSearchCV
grid_search = GridSearchCV(knn_clf,param_grid,cv=3) #cv表示叫交叉验证的次数
grid_search.fit(X_train,y_train)
这时就能得到我们最好的分数,以及最好的参数选择了
in:grid_search.best_score_
out:0.7583333333333333
in:grid_search.best_params_
out:{'n_neighbors': 4, 'weights': 'uniform'}
accuracy_score
我们一般用accuracy_score来衡量我们的算法的准确度,使用方法如下:
in:from sklearn.metrics import accuracy_score
accuracy_score(y_test,y_predict) #这里我们用我们预测的y_predict和测试集中实际的y_test进行评估
out:0.9