/ MachineLearning  

knn算法预测约会对象是否符合条件

使用knn算法进行分类预测

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
from numpy import *
import operator # 运算符操作模块
import os
from collections import Counter # 快速计数工具

# inx 自定义用于分类的输入向量 - 标准向量 即计算数据集到标准向量的"距离"
# dataset 训练数据集 lables 标签
# 最近邻的特征数量
def classify(inx, dataset, lables, k):
dataSetSize = dataset.shape[0]
# tile(A,(2,3)) 表示第一个维度重复三次,第二个维度重复两次 tile(A,(2,3)) => array([[1, 2, 1, 2, 1, 2],[1, 2, 1, 2, 1, 2]])
diffMat = tile(inx, (dataSetSize, 1)) - dataset
# 计算训练集的数据与标准向量的距离 - 欧氏距离 => [[1,2,3],[1,2,3]]-[[1,2,3],[1,2,0]]
sqDiffMat = diffMat ** 2
# 计算平方和 再开方 => (A1-A2)^2+(B1-B2)^2+(c1-c2)^2
sqDistances = sqDiffMat.sum(axis = 1)
distances = sqDistances ** 0.5
# 按照距离从小到大排序 并获取其对应索引放入数组中 => y=array([3,0,2,1,4,5]) x[3]距离最小 x[5]最大
sorteDistIndicies = distances.argsort()

# 从距离排序中选取最小距离的k个向量
classCount = {}
for i in range(k):
voteIlable = lables[sorteDistIndicies[i]]
# 字典的get方法
# 如:list.get(k,d) 其中 get相当于一条if...else...语句,参数k在字典中,字典将返回list[k];如果参数k不在字典中则返回参数d,如果K在字典中则返回k对应的value值
# l = {5:2,3:4}
# print l.get(3,0)返回的值是4;
# Print l.get(1,0)返回值是0;

classCount[voteIlable] = classCount.get(voteIlable,0) + 1

# 排序选取 出现次数最多的标签
sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
return sortedClassCount[0][0]

# 数据归一化 0,1矩阵
def autoNorm(dataset):
# 计算数据集中的最小最大特征值
minVals = dataset.min(0)
maxVals = dataset.max(0)
rangs = maxVals - minVals
# 转为同维度的零矩阵
normDataset = zeros(shape(dataset))
m = dataset.shape[0]
# 生成与最小值之差的矩阵
normDataset = dataset - tile(minVals,(m,1))
# 将最小值除以极差组成的矩阵
normDataset = normDataset / tile(rangs, (m,1))
return normDataset, rangs, minVals

def file2matrix(filename):
"""
导入训练数据
:param filename: 数据文件路径
:return: 数据矩阵returnMat和对应的类别classLabelVector
"""
fr = open(filename, 'r')
# 获得文件中的数据行的行数
numberOfLines = len(fr.readlines())
# 生成对应的空矩阵
# 例如:zeros(2,3)就是生成一个 2*3 的矩阵,各个位置上全是 0
returnMat = zeros((numberOfLines, 3)) # prepare matrix to return
classLabelVector = [] # prepare labels return
fr = open(filename, 'r')
index = 0
for line in fr.readlines():
# str.strip([chars]) --返回移除字符串头尾指定的字符生成的新字符串
line = line.strip()
# 以 '\t' 切割字符串
listFromLine = line.split('\t')
# 每列的属性数据,即 features
returnMat[index] = listFromLine[0 : 3]
# 每列的类别数据,就是 label 标签数据
classLabelVector.append(int(listFromLine[-1]))
index += 1
# 返回数据矩阵returnMat和对应的类别classLabelVector
return returnMat, classLabelVector


# 约会网站用户数据进行分类 预测 数据在kaggle
def datingClassTest():
# 设置测试数据的的一个比例(训练数据集比例=1-hoRatio)
hoRatio = 0.1 # 测试范围,一部分测试一部分作为样本
# datingDataMat, datingLabels = file2matrix("https://raw.githubusercontent.com/pbharrin/machinelearninginaction/master/Ch02/datingTestSet2.txt") # load data setfrom file
datingDataMat, datingLabels = file2matrix("E:\\python\\MachineLearning\\data\\2.KNN/datingTestSet2.txt") # load data setfrom file
# 归一化数据
normMat, ranges, minVals = autoNorm(datingDataMat)
# m 表示数据的行数,即矩阵的第一维
m = normMat.shape[0]
# 设置测试的样本数量, numTestVecs:m表示训练样本的数量
numTestVecs = int(m * hoRatio)
print('numTestVecs=', numTestVecs)
errorCount = 0
for i in range(numTestVecs):
# 对数据测试
classifierResult = classify(normMat[i], normMat[numTestVecs : m], datingLabels[numTestVecs : m], 3)
print("the classifier came back with: %d, the real answer is: %d" % (classifierResult, datingLabels[i]))
errorCount += classifierResult != datingLabels[i]
print("the total error rate is: %f" % (errorCount / numTestVecs))
print(errorCount)


if __name__ == '__main__':
datingClassTest()