机器学习之K-邻近算法
最后发布时间:2022-11-08 22:10:53
浏览量:
特征
- 优点:精确度高、对异常值不敏感、无数据输入假定
- 缺点:计算复杂度高、空间复杂度高
- 适用数据范围:数值型和标称型
一般流程
- 收集数据:可以使用任何方法
- 准备数据:距离计算所需要的数值,最好是结构化的数据格式
- 分析数据:可以使用任何方法
- 训练算法:这个不适用于K-邻近算法
- 测试算法:计算错误率
- 使用算法:得到预测结果
算法理论概述
- 使用欧式距离计算两个向量点A和B之间的距离
- 例如:计算点(0,0)与点(1,2)之间的距离为:
以一个简单例子介绍KNN算法
这里给出一个简单的分类问题,根据KNN算法求出C所在的类别是A还是B。如果只看图,我们很容易发现C属于类别B,因为C距B的距离短。
使用K邻近算法的分析流程:
- 计算已知类别数据集中的点(A B)与当前点(C)之间的距离
- 按照距离的递增次序排序
- 选取与当前点(C)距离最小的K个点(BBA)
- 确定前K个点在类别中出现的频率
- 返回前K个点出现频率最高的类别当做当前点的预测分类
完整的代码如下:
from numpy import *
def createDataSet():
group=array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]])
labels=["A","A","B","B"]
return group,labels
group,labels=createDataSet()
# 使用K邻近算需要4个参数:
# inX 需要预测分类向量
# dataSet 训练样本数据集
# labels 训练样本对应的标签
# k 选择最邻近的数目
def classify0(inX,dataSet,labels,k):
# 获得训练样本的个数,本例中有4个
dataSetSize=dataSet.shape[0] # 4
# 复制inX,为4行1列
diffMat=tile(inX,(dataSetSize,1))
'''
[[0.2 0.4]
[0.2 0.4]
[0.2 0.4]
[0.2 0.4]]
'''
# 计算两点之差
diffMat=diffMat-dataSet
'''
[[-0.8 -0.7]
[-0.8 -0.6]
[ 0.2 0.4]
[ 0.2 0.3]]
'''
# 计算平方和
sqDiffMat=diffMat**2
'''
[[0.64 0.49]
[0.64 0.36]
[0.04 0.16]
[0.04 0.09]]
'''
# 相加
sqDistances=sqDiffMat.sum(axis=1)
'''
[1.13 1. 0.2 0.13]
'''
# 开放
distance=sqDistances**0.5
'''
[1.06301458 1. 0.4472136 0.36055513]
'''
# 升序排序,返回的是数组下标
sortedDistIndicies=distance.argsort()
'''
[3 2 1 0] 数组下标为0的元素最大
'''
classCount={} # {'B': 2, 'A': 1}
for i in range(k):
# 循环k次,获取升序排列的第i个标签
voteIlabel=labels[sortedDistIndicies[i]] # B B A
# 计算在循环的k次中,某一个标签出现的次数
classCount[voteIlabel]=classCount.get(voteIlabel,0)+1
''' k = 3
{'B': 1} 第一次循环
{'B': 2} 第二次循环
{'B': 2, 'A': 1} 第三次循环,A出现1次,B出现2次
'''
# 降序排列得到的字典的值
sortedClassCount = sorted(classCount.items(),key=lambda item: item[1],reverse=True)
'''
[('B', 2), ('A', 1)]
'''
return sortedClassCount[0][0]
# 预测向量[0.2,0.4] 所在的分类
result=classify0([0.2,0.4],group,labels,3)
print(result)
现在我们使用classify0预测sklearn中鸢尾花数据集
鸢尾花的数据集有四个变量 ['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)']
from sklearn import datasets
from KnnMethod import classify0
iris = datasets.load_iris()
iris_X = iris.data
iris_y = iris.target
# 预测向量[5.8, 2.7, 5.1 ,1.9] 所在的分类
result=classify0([5.8, 2.7, 5.1 ,1.9],iris_X,iris_y,3)
print(result) # 2
使用sklearn的通用机器学习模式
import numpy as np
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
iris = datasets.load_iris()
iris_X = iris.data
iris_y = iris.target
X_train,X_test,y_train,y_test = train_test_split(iris_X,iris_y,test_size=0.3)
knn = KNeighborsClassifier()
knn.fit(X_train, y_train)
# 预测[5.8, 2.7, 5.1 ,1.9]
print(knn.predict([[5.8, 2.7, 5.1 ,1.9]]))
print(knn.predict(X_test))
print(y_test)
结果:可以看到机器学习并不是100%正确
[2]
[0 2 2 1 1 1 0 1 0 1 2 0 0 0 2 2 0 2 0 2 0 0 1 0 1 0 0 0 0 0 2 2 2 2 2 1 2
2 1 0 2 0 0 1 1]
[0 2 2 1 1 1 0 1 0 1 2 0 0 0 1 2 0 2 0 2 0 0 1 0 1 0 0 0 0 0 2 2 2 2 2 1 2
2 1 0 2 0 0 1 1]
注:本内容参考《机器学习实战》这本书