机器学习之k-邻近算法
本文主要根据2013年6月出版的《机器学习实战》中所讲述内容,使用python3.6实现了书中所写代码。
- 主要有数据的文本输入处理
- 算法的具体实现classify()方法
- 对不同数据集进行归一化处理
- 以及对matplotlib绘图的简单使用
github地址:https://github.com/IBITM/Machine-Learning-in-Action
代码实现如下
# 手动实现knn算法
__author__="ZhangXiao"
# group -- array
# labels -- list类型
from numpy import *
import operator
import matplotlib
import matplotlib.pyplot as plt
# 创造数据集
def createDataSet(): # labels
group = array([[1.0, 1.1], [1.0, 1.0], [0, 0], [0, 1.0]])
labels = ['A', 'B', 'C', 'D']
return group, labels
# x是用于分类的输入向量
def classify(x, dataSet, labels, k):
# shape[0] 是返回第一维,也就是行数
dataSetSize = dataSet.shape[0] # shape方法:一个整型数字的元组,元组中的每个元素表示相应的数组每一维的长度
diffMat = tile(x, (dataSetSize, 1)) - dataSet # 见我简书博客的专门讲解
sqDiffMat = diffMat ** 2
sqDistances = sqDiffMat.sum(axis=1) # 每一行,把所有的列的数加起来
distances = sqDistances ** 0.5
sortedDistances = distances.argsort() # argsort函数返回的是数组值从小到大的索引值,并不是对数组进行排序
classCount = {}
# 选择距离最小的k个点
for i in range(k):
voteIabel = labels[sortedDistances[i]]
classCount[voteIabel] = classCount.get(voteIabel, 0) + 1
sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
# 书本中所写的是classCOunt.iteritems() 这是python2.7的写法,我已经更换成python3.6的写法了
return sortedClassCount[0][0]
# 从文本中读取数据
def filematrix(filename):
fr = open(filename)
arrayLines = fr.readlines() # 把文件的每一行读入进来
numberOfLines = len(arrayLines)
returnMat = zeros((numberOfLines, 3)) # 构造一个n行3列的0数组
classLabelVector = []
index = 0
for line in arrayLines:
line = line.strip() # 去掉所有的回车字符
listFromLine = line.split('\t') # 返回是一个list
returnMat[index, :] = listFromLine[0:3]
classLabelVector.append(int(listFromLine[-1])) # 显示指出是int型
index += 1
return returnMat, classLabelVector
# 进行数据归一化
def autoNorm(dataSet):
minValue = dataSet.min(0) # axis=0; 每列的最小值
maxValue = dataSet.max(0)
ranges = maxValue - minValue
normDataSet = zeros(shape(dataSet))
m = dataSet.shape[0]
normDataSet = dataSet - tile(minValue, (m, 1))
normDataSet = normDataSet / tile(ranges, (m, 1))
return normDataSet, ranges, minValue
def datingClassTest():
hoRatio = 0.10
datingDataMat, datingLabels = filematrix("datingTestSet2.txt")
normMat, ranges, minValue = autoNorm(datingDataMat)
m = normMat.shape[0] # 行数
numTestVecs = int(m * hoRatio) # 测试数量
errorCount = 0.0
for i in range(numTestVecs):
classiFierResult = classify(normMat[i, :], normMat[numTestVecs:m, :], \
datingLabels[numTestVecs:m], 3)
print("分类器返回的结果为:%d, 实际的结果为:%d" \
% (classiFierResult, datingLabels[i]))
if (classiFierResult != datingLabels[i]):
errorCount += 1.0
print("错误率为:%f" % (errorCount / float(numTestVecs)))
def calssifyPerson():
resultList = ["没兴趣", "稍微感兴趣", "非常感兴趣"]
percentTats = float(input("玩视频游戏所占的时间比"))
ffMiles = float(input("每年飞行时间历程数"))
iceCream = float(input("每周消费的冰激凌公斤数"))
datingDataMat, datingLabels = filematrix("datingTestSet2.txt")
normMat, ranges, minValue = autoNorm(datingDataMat)
inArr = array([ffMiles, percentTats, iceCream])
classifierResult = classify((inArr - minValue) / ranges, normMat, datingLabels, 3)
print("你对这个人的印象可能是:", resultList[classifierResult - 1])
if __name__ == "__main__":
# 开始数据的读入
datingDataMat, datingLabels = filematrix("datingTestSet2.txt")
# 进行绘图
# fig = plt.figure() # 新建一个绘画窗口
# ax = fig.add_subplot(111) # 设置子图的行数、列数、子图的个数
# ax.scatter(datingDataMat[:,1],datingDataMat[:,2],15.0*array(datingLabels),15.0*array(datingLabels))
# plt.show()
# datingClassTest()
calssifyPerson()
所用到数据和源码的下载地址:
https://www.manning.com/MachineLearninginAction