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()
|