思想简单
用于分类
利用样本与数据的距离,进行预测,距离最小的最多的数据的类别,就是预测结果
k的值为取最近的样本的个数
距离计算:欧拉距离
代码实现:
# -*- coding: utf-8 -*-
import numpy as np
from math import sqrt
from collections import Counter
from sklearn.model_selection import train_test_split
data=[[1,1],
[1,3],
[2,3],
[3,2],
[5,7],
[5,3],
[6,2],
[6,6]
]
##特征训练数据集
typelist=[0,0,0,0,1,1,1,1]
##类别向量
#x=[9,8]
##样例
#x=np.array(x)
class Knn:
def __init__(self,k):
self._X_train=[]
self._y_train=[]
self._k=k
def fit(self,X_train,y_train):
self._X_train=X_train
self._y_train=y_train
return self
def predict(self,x_predict):
distances=[]
distances=[sqrt(np.sum((x-x_predict)**2)) for x in self._X_train]
nearest=np.argsort(distances)
#排序,并返回相应索引序列
topK_y=[self._y_train[i] for i in nearest[:self._k]]
#得到相应数量的的索引类别向量序列
votes=Counter(topK_y)
#获取数量聚集
return votes.most_common(1)[0][0]
#返回最多的数量
#返回一个TopN列表。如果n没有被指定,则返回所有元素。当多个元素计数值相同时,排列是无确定顺序的。
def score(self,y_predict,y_test):
return sum(y_predict==y_test)/len(y_test)
if '__main__'==__name__:
X_train,X_test,y_train,y_test=train_test_split(data,typelist,test_size=0.2,random_state=11)
knn=Knn(6)
knn.fit(X_train,y_train)
y_predict=[]
X_train=np.array(X_train)
X_test=np.array(X_test)
y_test=np.array(y_test)
for x in X_test:
y_predict.append(knn.predict(x))
print(knn.score(y_predict,y_test))
与机器学习流程对比:
对kNN来说,训练集就是模型
在sklearn中的应用
from sklearn.neighbors import KNeighborsClassifier
kNN_classifier = KNeighborsClassifier(n_neighbors=6)
kNN_classifier.fit(X_train,y_train)
kNN_classifier.predict(x) # x是个矩阵
算法的性能
利用训练数据集产生模型,再利用测试数据进行算法性能的判断。
train test split
测试数据集、训练数据集通过原数据集进行拆分得到,即train test split.
def train_test_split(X, y, test_ratio=0.2, seed=None):
"""将数据 X 和 y 按照test_ratio分割成X_train, X_test, y_train, y_test"""
if seed:
np.random.seed(seed)
shuffled_indexes = np.random.permutation(len(X))
test_size = int(len(X) * test_ratio)
test_indexes = shuffled_indexes[:test_size]
train_indexes = shuffled_indexes[test_size:]
X_train = X[train_indexes]
y_train = y[train_indexes]
X_test = X[test_indexes]
y_test = y[test_indexes]
return X_train, X_test, y_train, y_test
算法准确度
def accuracy_score(y_true, y_predict):
"""计算y_true和y_predict之间的准确率"""
return np.sum(y_true == y_predict) / len(y_true)
超参数
运行算法之前需要指定的数。
kNN的k就是典型的超参数
寻找最好的k:
考虑距离,即考虑距离权重:
距离
欧拉距离
曼哈顿距离:
明可夫斯基距离:
即有了新的超参数p
搜索明可夫斯基参数:
这种搜索模式,叫做网格搜索
其他距离详见sklearn中的metric
网格搜索
参数列表
默认明可夫斯基距离
使用sklearn中的自带算法
获得最好参数算法
最好的准确度
最好的参数
多核并行运算以及显示网格搜索过程
数据归一化
样本距离相差过大,导致准确度不高,为解决这一问题,提出了数据归一化处理。
即将所有数据映射到同一尺度。
最值归一化
把所有数据映射到0、1之间
适用于分布有明显边界的情况;
均值方差归一化
把所有数据归一到均值为0方差为1的分布中
适用于分布没有明显边界的情况;
在sklearn中的使用
kNN算法的缺点:
1、效率低下
2、高度数据相关
3、预测结果不具有可解释性
4、维数灾难:随着维度的增加,看似相近的样本之间距离越来越大
解决方法:降维