机器学习之KNN(k近邻)算法

1、算法介绍
k近邻算法是学习机器学习的入门算法,可实现分类与回归,属于监督学习的一种。算法的工作原理是:输入一个训练数据集,训练数据集包括特征空间的点和点的类别,可以是二分类或是多分类。预测时,输入没有类别的点,找到k个与该点距离最接近的点,使用多数表决的方法,得出最后的预测分类。


2、算法优缺点
优点:没有高深的数学思想,容易理解,精度高,对异常值不敏感,无数据输入假定;
缺点:计算复杂度高,空间复杂度高;
理解:因为knn算法是寻找与目标点接近的点,在计算时,异常值与目标点的“距离”会较远,所以对于异常值不敏感。但是,对于每一个目标点,都要计算一次。若是训练数据集数量很大,且数据集的点维度高,这样计算起来十分费时。因此,也诞生了kd树等优化算法。


3、算法三要素
knn算法三要素分别为:度量距离,k值,决策规则。
3.1、度量距离
特征空间中的两个实例点的距离是两个实例点相似程度的反映。K近邻法的特征空间一般是n维实数向量空间R^n。
对于两个样本点之间
机器学习之KNN(k近邻)算法
距离(闵可夫斯基(Minkowski)距离)定义为
机器学习之KNN(k近邻)算法
当p=1时,该距离称为曼哈顿距离,也称为街区距离;
当p=2时,该距离称为欧式距离,这也是高中数学中求二维空间或是三维空间中两点距离的方法;knn算法也一般取欧式距离。
当p为无穷大时,该距离称为切比雪夫距离。
3.2、k值
k值的选择会对k近邻法的结果产生重大影响。在应用中,k值一般取一个比较小的数值,通常采用交叉验证法来选取最优的k值。
3.3、决策规则
通常采用多数表决的方式,在k个距离较近的点中,哪一个分类较多即作为最后的预测结果。


4、数学例子
训练数据集

x1 x2 分类
1 1.1 A
1 1 A
0 0 B
0 0.2 B

测试数据集(0,0.1)
对于(0,0.1),取欧式距离,k=3:
L=[(1-0)^2+(1.1-0.1)^2]^0.5=√2
L=[(1-0)^2+(1-0.1)^2]^0.5=√1.81
L=[(0-0)^2+(0-0.1)^2]^0.5=√0.01
L=[(0-0)^2+(0.2-0.1)^2]^0.5=√0.01
取k=3,即取L=√1.81,A类;L=√0.01,B类;L=√0.01,B类;
根据多数表决规则,(0,0.1)属于B类


5、数据预处理:归一化数值
为了防止某一特征对结果的影响太大,故常采用数据归一化对数据进行预处理。
归一化是将特征数值转化为0到1之间的值
公式为:newValue = (oldValue - min)/(max - min)


6、knn算法代码实现
6.1、Python代码:

def calDistance(vector1, vector2, q):#定义计算闵可夫斯基距离的函数
    distance = 0.0
    n = len(vector1)
    for i in range(n):
        distance += pow(abs(vector1[i] - vector2[i]), q)
    return round(pow(distance, 1.0 / q), 3)

def findNearestNeighbor(train_x,train_y,item,q=2,k=10):
    neighbors = []#存储训练集与目标点的结果【训练集点,该点分类,距离】
    k_neighbors = {}#存储十个近邻的结果及投票次数
    for x,y in zip(train_x,train_y):#遍历训练集和目标点的距离,并存储在neighbors
        distance = calDistance(x,item,q)
        neighbors.append([x,y,distance])
    neighbors.sort(key=lambda x:x[2])#根据距离进行排序
    for i in range(k):#遍历结果,将k个最近邻的点的结果写成字典形式
        k_neighbors.setdefault(neighbors[i][1],0)
        k_neighbors[neighbors[i][1]] += 1

    # 返回排序后的k个近邻键值对
    nearest_neighbor = sorted(k_neighbors.items(),key=lambda x:x[1],reverse=True)
    #返回最大的投票数那个key
    return nearest_neighbor[0][0]

if __name__ == '__main__':
    data_x = [[1,1],[1,1.1],[0,0],[0,0.2]]
    data_y = ['A','A','B','B']
    item = [0,0]
    q = 2
    k = 3
    result = findNearestNeighbor(train_x=data_x,train_y=data_y,item=item,q=q,k=k)
    print('预测分类为:',result)

6.2、sklearn库的实现

from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import train_test_split
from sklearn import datasets

iris = datasets.load_iris()#鸢尾花数据是一个字典,鸢尾花特征的key是data,类型的key是target
iris_X = iris.data# 拆分属性数据
iris_y = iris.target# 拆分类别数据
# 拆分测试集和训练集,并进行预测,其中训练集80%,测试集20%
iris_X_train , iris_X_test, iris_y_train ,iris_y_test = train_test_split(iris_X, iris_y, test_size=0.2,random_state=0)

knn = KNeighborsClassifier(n_neighbors=10,p=2)#创建knn算法
knn.fit(iris_X_train, iris_y_train)# 提供训练集进行训练
predict_result = knn.predict(iris_X_test)# 预测测试集鸢尾花类型
correct_rate = knn.score(iris_X_test, iris_y_test)#计算正确率

print('预测结果',predict_result)
print('预测准确率',str(correct_rate*100)+'%')

参考书籍:
《统计学习方法》--李航
《机器学习实战》--Peter


本次的学习就到此结束啦!感兴趣的读者或者想和我聊聊的请私信我,或者关注公众号:程序员吃橘子

猜你喜欢

转载自blog.51cto.com/14065757/2341445