一、K近邻算法的基本概念
K近邻算法,即是给定一个训练数据集,对新的输入实例,在训练数据集中找到与该实例最邻近的K个实例,这K个实例的多数属于某个类,就把该输入实例分类到这个类中。(这就类似于现实生活中少数服从多数的思想)根据这个说法,咱们来看下引自维基百科上的一幅图:
如上图所示,有两类不同的样本数据,分别用蓝色的小正方形和红色的小三角形表示,而图正中间的那个绿色的圆所标示的数据则是待分类的数据。这也就是我们的目的,来了一个新的数据点,我要得到它的类别是什么?好的,下面我们根据k近邻的思想来给绿色圆点进行分类。
- 如果K=3,绿色圆点的最邻近的3个点是2个红色小三角形和1个蓝色小正方形,少数从属于多数,基于统计的方法,判定绿色的这个待分类点属于红色的三角形一类。
- 如果K=5,绿色圆点的最邻近的5个邻居是2个红色三角形和3个蓝色的正方形,还是少数从属于多数,基于统计的方法,判定绿色的这个待分类点属于蓝色的正方形一类。
二、使用scikit-learn实现k-NN
import numpy as np
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import accuracy_score
### 加载数据
digits = datasets.load_digits()
X = digits.data
y = digits.target
### 拆分训练集、测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=666)
### KNN模型训练
knn_clf = KNeighborsClassifier(n_neighbors=3)
knn_clf.fit(X_train, y_train)
### 测试集结果评估
y_predict = knn_clf.predict(X_test)
accuracy_score(y_test, y_predict)
三、超参数
k-NN算法有三个常用的超参数
- 寻找最好的k
- 是否考虑距离
- 搜索明可夫斯基距离响应的P
使用网格搜索确定超参数
import numpy as np
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.model_selection import GridSearchCV
digits = datasets.load_digits()
X = digits.data
y = digits.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=666)
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()
grid_search = GridSearchCV(knn_clf, param_grid)
grid_search.fit(X_train, y_train)
grid_search.best_estimator_
###Output: KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',metric_params=None, n_jobs=1, n_neighbors=3, p=3,weights='distance')
grid_search.best_score_
四、归一化
均值方差归一化
### 08 Scikit-learn中的Scaler
import numpy as np
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.neighbors import KNeighborsClassifier
iris = datasets.load_iris()
X = iris.data
y = iris.target
X_train, X_test, y_train, y_test = train_test_split(iris.data, iris.target, test_size=0.2, random_state=666)
### scikit-learn中的StandardScaler
standardScalar = StandardScaler()
X_train = standardScalar.transform(X_train)
X_test_standard = standardScalar.transform(X_test)
### 使用归一化后的数据进行knn分类
knn_clf = KNeighborsClassifier(n_neighbors=3)
knn_clf.fit(X_train, y_train)
knn_clf.score(X_test_standard, y_test)
五、k-NN优缺点
KNN的主要优点有:
1.理论成熟,思想简单,既可以用来做分类又可以做回归
2.可以用于非线性分类
3.训练时间复杂度比支持向量机之类的算法低
3.和朴素贝叶斯之类的算法比,对数据没有假设,准确度高,对异常点不敏感
4.由于KNN方法主要靠周围有限的邻近的样本,而不是靠判别类域的方法来确定所属的类别,因此对于类域的交叉或重叠较多的待分类样本集来说,KNN方法较其他方法更为适合
5.该算法比较适用于样本容量比较大的类域的自动分类,而那些样本容量比较小的类域采用这种算法比较容易产生误分类情况
KNN的主要缺点:
1.计算量大,尤其是特征数非常多的时候
2.样本不平衡的时候,对稀有类别的预测准确率低
3.KD树,球树之类的模型建立需要大量的内存
4.是慵懒散学习方法,基本上不学习,导致预测时速度比起逻辑回归之类的算法慢
5.相比决策树模型,KNN模型的可解释性不强