KNN算法的两个常用实际例子
一、使用K-邻近算法来对电影的类型进行判断
1.实验思路:
通过电影场景里面的打斗镜头次数与接吻镜头次数的比较然后根据KNN算法来进行判断该电影的类型是动作片还是爱情片
2.代码实现:
(一)首先创建一个数据集,里面有两个数组,其中一个存放打斗/接吻次数,另一个存放与之相对应的电影类型标签
def createDataSet():
# 四组二维特征
group = np.array([[104, 3], [100, 2], [81, 1], [10, 101], [5, 99], [2, 98]])
# 四组特征的标签
labels = ['爱情片', '爱情片', '爱情片', '动作片', '动作片', '动作片']
return group, labels
(二)KNN算法的核心,用来判断测试集属于训练集中的哪一种。这里有四个参数,分别表示输入的测试集,数据集,数据集中的标签,选择距离最小的k个点以用来投票。出现次数最多的为影片的最终类型
def classify(inx, dataset, labels, k):
# 计算距离 其实就是计算点一定之间的距离
dist = np.sum((inx - dataset) ** 2, axis=1) ** 0.5
# dist.argsort 将x中的元素从小到大排列,提取其对应的index(索引)
k_labels = [labels[index] for index in dist.argsort()[0: k]]
label = collections.Counter(k_labels).most_common(1)[0][0]
return label
(三)输入一个自定义测试集进行测试
if __name__ == '__main__':
# 创建数据集
group, labels = createDataSet()
# 测试集
test = [100, 23]
test_class = classify(test, group, labels, 3)
# 打印分类结果
print('最终判定的影片类型:',test_class)
3.运行截图:
给定的测试集[100,23],接吻镜头次数为100/打斗镜头次数为23
4.完整代码展示:
import collections
import numpy as np
def createDataSet():
# 四组二维特征
group = np.array([[104, 3], [100, 2], [81, 1], [10, 101], [5, 99], [2, 98]])
# 四组特征的标签
labels = ['爱情片', '爱情片', '爱情片', '动作片', '动作片', '动作片']
return group, labels
def classify(inx, dataset, labels, k):
# 计算距离 其实就是计算点一定之间的距离
dist = np.sum((inx - dataset) ** 2, axis=1) ** 0.5
# k个最近的标签
# dist.argsort 将x中的元素从小到大排列,提取其对应的index(索引)
k_labels = [labels[index] for index in dist.argsort()[0: k]]
label = collections.Counter(k_labels).most_common(1)[0][0]
return label
if __name__ == '__main__':
# 创建数据集
group, labels = createDataSet()
# 测试集
test = [100, 23]
test_class = classify(test, group, labels, 5)
# 打印分类结果
print('最终判定的影片类型:',test_class)
二、在约会网站上使用KNN算法
(一)准备数据:从文本文件中解析数据
通过海伦收集的一些数据存放在文本文件datingTestSet.txt中,每个样本数据占一行,总共有1000行。(数据前三列分别表示:每年获得的飞行常客里程数,玩视频游戏所消耗时间百分比和每周消耗的冰淇淋公升数目。最后一列则表示喜欢和讨厌程度),然后通过自定义的函数file2matrix将本本文件的数据处理为分类器可以接受的格式,以此来处理输入格式的问题。
datingTestSet.txt中的个别数据:
40920 8.326976 0.953952 3
14488 7.153469 1.673904 2
26052 1.441871 0.805124 1
75136 13.147394 0.428964 1
38344 1.669788 0.134296 1
72993 10.141740 1.032955 1
35948 6.830792 1.213192 3
42666 13.276369 0.543880 3
67497 8.631577 0.749278 1
file2matrix函数
def file2matrix(filename):
fr = open(filename)
arrayOLines = fr.readlines() #注意需要加s
numberOfLines = len(arrayOLines)
returnMat = zeros((numberOfLines,3))
classLabelVector = []
index = 0
for line in arrayOLines:
line = line.strip()
listFormLine = line.split('\t')
for x in range(0,3):
returnMat[index,x] = float(listFormLine[x])
classLabelVector.append(int(listFormLine[-1])) # -1 为最后一个元素
index += 1
return returnMat,classLabelVector
(二)分析数据:使用Matplotlib创建散点图
使用Matplotlib制作原始数据的散点图
datingDataMat,datingLabels = file2matrix('datingTestSet.txt')
fig = plt.figure()
ax = fig.add_subplot(111)
ax.scatter(datingDataMat[:,1],datingDataMat[:,2],15.0*array(datingLabels),marker=(4,1),alpha=0.5)
plt.show()
横坐标表示“玩视频游戏所消耗时间百分比”
纵坐标表示“每周消耗冰淇凌公升数”
(三)准备数据:归一化数值
由于特征值的大小不同,所以就会对结果的影响程度不同。这就需要我们归一化特征值,把每个特征值的大小固定在[0,1]
def autoNorm(dataSet):
minVals = dataSet.min(0)
maxVals = dataSet.max(0)
ranges = maxVals - minVals
normDataSet = zeros(shape(dataSet))
m = dataSet.shape[0]
normDataSet = dataSet - tile(minVals, (m,1))
normDataSet = normDataSet/tile(ranges, (m,1)) #element wise divide
return normDataSet, ranges, minVals
(四)测试算法:作为完整程序验证分类器
用10%的数据作为输入来测试,另外90%作为已知集合
def datingClassTest():
filename = "datingTestSet.txt"
datingDataMat, datingLabels = file2matrix(filename)
hoRatio = 0.10
normMat, ranges, minVals = autoNorm(datingDataMat)
m = normMat.shape[0]
numTestVecs = int(m * hoRatio)
errorCount = 0.0
for i in range(numTestVecs):
# 前numTestVecs个数据作为测试集,后m-numTestVecs个数据作为训练集
classifierResult = classify0(normMat[i, :], normMat[numTestVecs:m, :], datingLabels[numTestVecs:m], 4)
print("分类结果:%d\t真实类别:%d" % (classifierResult, datingLabels[i]))
if classifierResult != datingLabels[i]:
errorCount += 1.0
print("错误率:%f%%" % (errorCount / float(numTestVecs) * 100))
(五)使用算法:构建完整可用系统
根据问题提示输出相应的信息,判断出海伦是否喜欢这个人
#约会网站测试函数
def classifyperson():
resultList=['讨厌', '喜欢', '非常喜欢']
percentTats=float(input("玩视频游戏所占时间百分比?"))
ffMiles=float(input("每年获得的飞行常客里程数?"))
iceCream=float(input("每周消费的冰淇淋公升数?"))
datingDatMat,datingLabels=file2matrix('datingTestSet.txt')
normMat,ranges,minVals=autoNorm(datingDatMat)
inArr=np.array([ffMiles,percentTats,iceCream])
classifierResult=classify0((inArr-minVals)/ranges,normMat,datingLabels,3)
print("你喜欢这个人的程度可能是:",resultList[classifierResult-1])
以上一些代码数据来源于Peter Harrington所著的《机器学习实战》