机器学习-分类算法-kNN
kNN(k-Nearest Neighbor)算法:一种基于向量间相似度的分类算法。
kNN原理
k最近邻(k-Nearest Neighbor)算法是比较简单的机器学习算法。它采用测量不同特征之间的距离方法进行分类。
如果一个样本在特征空间中的k个最近邻(最相似)的样本中的大多数都属于一个类别,则该样本也属于这个类别。k表示外部定义的近邻数量。
实现步骤
第一阶段:确定k值(就是指最近邻居的个数)。一般是奇数个
第二阶段:确定距离度量公式。文本分类一般使用夹角余弦,得出待分类数据点和所有已知类别的样本点,从中选择距离最近的k个样本。
夹角余弦:cos = AB/|A||B|
第三阶段:统计这k个样本点中各个类别的数量。根据k个样本中数量最多的样本是什么类别,我们就把这个数据点定为什么类别。
实现代码1(训练集为一组事件发生概率,测试集为事件发生概率,求类型)
from numpy import *
import operator
# 夹角余弦距离公式
def consdist(vector1, vector2):
print("vecotr1:",vector1)
print("vector2:",vector2)
result = dot(vector1, vector2) / (linalg.norm(vector1) * linalg.norm(vector2))
print("result:", result)
return result
# KNN分类器
# testData:测试集 trainSet:训练集 listClasses:类别标签 k:k个邻居
def classify(testData, trainSet, listClasses, k):
dataSetSize = trainSet.shape[0] # 返回样本的行数
distances = array(zeros(dataSetSize))
print("dataSetSize:", dataSetSize)
for indx in range(dataSetSize): # 计算测试集和训练集之间的距离:余弦夹角
distances[indx] = consdist(testData, trainSet[indx])
# 根据生成的余弦夹角按从大到小排序,结果为索引号
sortedDistIndics = argsort(-distances)
classCount = {}
for i in range(k): # 获得角度最小的前K项作为参考项
# 按排序顺序返回样本集对应的类别标签
voteIlabel = listClasses[sortedDistIndics[i]]
# 为字典classCount赋值,相同key,其中value加1
classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1 # 获得voteIlabel的value值,没有则默认为0
# 对分类字典classCount按value重新排序
# sorted(data.items(), key = operator.itemgetter(1), reverse = True)
# 该句是按字典排序的固定用法
# classCount.items() # 字典迭代器函数
# key:排序参数 operator.itemgetter(1):多级排序
sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
return sortedClassCount[0][0] # 返回序最高的一项
dataArr = np.array([[0.238, 0, 0.1905, 0.1905, 0.1905, 0.1905], [0, 0.177, 0, 0.294, 0.235, 0.294], [0.2, 0.16, 0.12, 0.12, 0.2, 0.2]])
dataMat = mat(dataArr)
print("dataMat:", dataMat.shape)
print("dataMat type:", type(dataMat))
testSet = [0.2174, 0.2174, 0.1304, 0, 0.2174, 0.2174]
testMat = mat(testSet)
classLabel = [0, 1, 2]
k = 3
print("result:",classify(testSet, dataArr, classLabel, k))
实现代码2(文本测试)
# K近邻分类
from numpy import *
import numpy as np
import operator
from com.machineLearning.Bayes.NBayes import NBayes
def loadDataSet():
# 训练集文本
postingList = [
['my', 'dog', 'has', 'flea', 'problems', 'help', 'please'],
['maybe', 'not', 'take', 'him', 'to', 'dog', 'park', 'stupid'],
['my', 'dalmation', 'is', 'so', 'cute', 'I', 'love', 'him', 'my'],
['stop', 'posting', 'stupid', 'worthless', 'garbage'],
['mr', 'licks', 'ate', 'my', 'steak', 'how', 'to', 'stop', 'him'],
['quit', 'buying', 'worthless', 'dog', 'food', 'stopid']
]
# 每个文本对应的分类
classVec = [0, 1, 0, 1, 0, 1]
return postingList, classVec
# 夹角余弦距离公式
def consdist(vector1, vector2):
return dot(vector1, vector2) / (linalg.norm(vector1) * linalg.norm(vector2))
# KNN分类器
# testData:测试集 trainSet:训练集 listClasses:类别标签 k:k个邻居
def classify(testData, trainSet, listClasses, k):
dataSetSize = trainSet.shape[0] # 返回样本的行数
distances = array(zeros(dataSetSize))
for indx in range(dataSetSize): # 计算测试集和训练集之间的距离:余弦夹角
distances[indx] = consdist(testData, trainSet[indx])
# 根据生成的余弦夹角按从大到小排序,结果为索引号
sortedDistIndics = argsort(-distances)
classCount = {}
for i in range(k): # 获得角度最小的前K项作为参考项
# 按排序顺序返回样本集对应的类别标签
voteIlabel = listClasses[sortedDistIndics[i]]
# 为字典classCount赋值,相同key,其中value加1
classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1 # 获得voteIlabel的value值,没有则默认为0
# 对分类字典classCount按value重新排序
# sorted(data.items(), key = operator.itemgetter(1), reverse = True)
# 该句是按字典排序的固定用法
# classCount.items() # 字典迭代器函数
# key:排序参数 operator.itemgetter(1):多级排序
sortedClassCount = sorted(classCount.items(), key = operator.itemgetter(1), reverse=True)
return sortedClassCount[0][0] # 返回序最高的一项
# 使用KNN算法实现文本分类
k = 3
dataSet, lisClasses = loadDataSet()
nb = NBayes()
nb.train_set(dataSet, lisClasses)
# 使用之前的贝叶斯分类阶段的数据集及生成的TF向量进行分类
print(classify(nb.tf[3], nb.tf, lisClasses, k))
NBayes看上一篇。