机器学习实战笔记——KNN约会网站
1 ''' 2 机器学习实战——KNN约会网站优化 3 ''' 4 5 import operator 6 import numpy as np 7 from numpy import * 8 from matplotlib.font_manager import FontProperties 9 import matplotlib.lines as mlines 10 import matplotlib.pyplot as plt 11 12 # largeDoses :极具魅力 ;smallDoses :魅力一般 ;didntLike:不喜欢 13 def str_3(str_i): 14 if str_i=='largeDoses': 15 return 3 16 elif str_i=='smallDoses': 17 return 2 18 elif str_i=='didntLike': 19 return 1 20 else: 21 return np.nan 22 23 # 获取特征矩阵、label向量 24 def file2matrix(filename): 25 fr = open(filename,'r') #打开文件 26 numberOfLines = len(fr.readlines()) # 获得文件的行数 27 returnMat = zeros((numberOfLines,3)) # 创建一个空的特征矩阵 28 classLabelVector = [] # 分类label向量 29 fr = open(filename,'r') 30 index = 0 #行索引 31 for line in fr.readlines(): 32 line = line.strip() # 为空是默认删除('\n','\r','\t',' ') 33 listFromLine = line.split('\t') #读取的每行数据根据'\t'进行切片 34 returnMat[index,:] = listFromLine[0:3] #提取对应行的前三行(特征列)存放入retunMat特征矩阵 35 classLabelVector.append(str_3(listFromLine[-1])) #将每行的label转为数值后存入classLabelVector 36 index += 1 37 # 返回特征矩阵和分类label向量 38 return returnMat,classLabelVector 39 40 # 归一化 41 def autoNorm(dataSet): 42 #获得数据的最小值 按列寻找最大|最小值 43 minVals = dataSet.min(0) 44 maxVals = dataSet.max(0) 45 # print('minVals:\n',minVals) 46 # print('maxVals:\n',maxVals) 47 #最大值和最小值的范围 48 ranges = maxVals - minVals 49 #shape(dataSet)返回dataSet的矩阵行列数 50 normDataSet = np.zeros(np.shape(dataSet)) 51 #返回dataSet的行数 52 m = dataSet.shape[0] 53 #原始值减去最小值 54 normDataSet = dataSet - np.tile(minVals, (m, 1)) 55 #除以最大和最小值的差,得到归一化数据 56 normDataSet = normDataSet / np.tile(ranges, (m, 1)) 57 #返回归一化数据结果,数据范围,最小值 58 return normDataSet, ranges, minVals 59 60 # 画图 61 def showdatas(datingDataMat, datingLabels): 62 #设置汉字格式 63 font = FontProperties(fname=r"c:\windows\fonts\simsun.ttc", size=14) 64 #将fig画布分隔成1行1列,不共享x轴和y轴,fig画布的大小为(13,8) 65 #当nrow=2,nclos=2时,代表fig画布被分为四个区域,axs[0][0]表示第一行第一个区域 66 fig, axs = plt.subplots(nrows=2, ncols=2, figsize=(13,8)) 67 68 numberOfLabels = len(datingLabels) 69 LabelsColors = [] 70 for i in datingLabels: 71 if i == 1: 72 LabelsColors.append('black') 73 if i == 2: 74 LabelsColors.append('orange') 75 if i == 3: 76 LabelsColors.append('red') 77 #画出散点图,以datingDataMat矩阵的第一(飞行常客例程)、第二列(玩游戏)数据画散点数据,散点大小为15,透明度为0.5 78 axs[0][0].scatter(x=datingDataMat[:,0], y=datingDataMat[:,1], color=LabelsColors,s=15, alpha=.5) 79 #设置标题,x轴label,y轴label 80 axs0_title_text = axs[0][0].set_title(u'每年获得的飞行常客里程数与玩视频游戏所消耗时间占比',FontProperties=font) 81 axs0_xlabel_text = axs[0][0].set_xlabel(u'每年获得的飞行常客里程数',FontProperties=font) 82 axs0_ylabel_text = axs[0][0].set_ylabel(u'玩视频游戏所消耗时间占',FontProperties=font) 83 plt.setp(axs0_title_text, size=9, weight='bold', color='red') 84 plt.setp(axs0_xlabel_text, size=7, weight='bold', color='black') 85 plt.setp(axs0_ylabel_text, size=7, weight='bold', color='black') 86 87 #画出散点图,以datingDataMat矩阵的第一(飞行常客例程)、第三列(冰激凌)数据画散点数据,散点大小为15,透明度为0.5 88 axs[0][1].scatter(x=datingDataMat[:,0], y=datingDataMat[:,2], color=LabelsColors,s=15, alpha=.5) 89 #设置标题,x轴label,y轴label 90 axs1_title_text = axs[0][1].set_title(u'每年获得的飞行常客里程数与每周消费的冰激淋公升数',FontProperties=font) 91 axs1_xlabel_text = axs[0][1].set_xlabel(u'每年获得的飞行常客里程数',FontProperties=font) 92 axs1_ylabel_text = axs[0][1].set_ylabel(u'每周消费的冰激淋公升数',FontProperties=font) 93 plt.setp(axs1_title_text, size=9, weight='bold', color='red') 94 plt.setp(axs1_xlabel_text, size=7, weight='bold', color='black') 95 plt.setp(axs1_ylabel_text, size=7, weight='bold', color='black') 96 97 #画出散点图,以datingDataMat矩阵的第二(玩游戏)、第三列(冰激凌)数据画散点数据,散点大小为15,透明度为0.5 98 axs[1][0].scatter(x=datingDataMat[:,1], y=datingDataMat[:,2], color=LabelsColors,s=15, alpha=.5) 99 #设置标题,x轴label,y轴label 100 axs2_title_text = axs[1][0].set_title(u'玩视频游戏所消耗时间占比与每周消费的冰激淋公升数',FontProperties=font) 101 axs2_xlabel_text = axs[1][0].set_xlabel(u'玩视频游戏所消耗时间占比',FontProperties=font) 102 axs2_ylabel_text = axs[1][0].set_ylabel(u'每周消费的冰激淋公升数',FontProperties=font) 103 plt.setp(axs2_title_text, size=9, weight='bold', color='red') 104 plt.setp(axs2_xlabel_text, size=7, weight='bold', color='black') 105 plt.setp(axs2_ylabel_text, size=7, weight='bold', color='black') 106 #设置图例 107 didntLike = mlines.Line2D([], [], color='black', marker='.', 108 markersize=6, label='didntLike') 109 smallDoses = mlines.Line2D([], [], color='orange', marker='.', 110 markersize=6, label='smallDoses') 111 largeDoses = mlines.Line2D([], [], color='red', marker='.', 112 markersize=6, label='largeDoses') 113 #添加图例 114 axs[0][0].legend(handles=[didntLike,smallDoses,largeDoses]) 115 axs[0][1].legend(handles=[didntLike,smallDoses,largeDoses]) 116 axs[1][0].legend(handles=[didntLike,smallDoses,largeDoses]) 117 #显示图片 118 plt.show() 119 120 # classify0(测试集特征,训练集特征,训练集label,4) 121 def classify0(inX, dataSet, labels, k): 122 # numpy函数shape[0]返回dataSet的行数 1000 123 dataSetSize = dataSet.shape[0] 124 # 在列向量方向上重复inX共1次(横向),行向量方向上重复inX共dataSetSize次(纵向) 将单个样本的维度扩展为和dataSet相同 125 diffMat = np.tile(inX, (dataSetSize, 1)) - dataSet 126 # print(diffMat.shape) # (900,3) 127 # 二维特征相减后平方 128 sqDiffMat = diffMat ** 2 129 # print(sqDiffMat.shape) # (900,3) 130 # sum()所有元素相加,sum(0)列相加,sum(1)行相加 # 样本 131 sqDistances = sqDiffMat.sum(axis=1) 132 # print(sqDistances.shape) # (900,) 133 # print(sqDistances) 134 # 开方,计算出距离 135 distances = sqDistances**0.5 136 # 以上四步为欧氏距离计算公式 137 138 # 返回distances中元素从小到大排序后的索引值 argsort()返回数字值从小到大的索引值列表 139 sortedDistIndices = distances.argsort() 140 # 定一个记录类别次数的字典 141 classCount = {} 142 for i in range(k): 143 # 取出前k个元素的类别 144 voteIlabel = labels[sortedDistIndices[i]] 145 # dict.get(key,default=None),字典的get()方法,返回指定键的值,如果值不在字典中返回默认值。 146 # 计算类别次数 # get(返回此键的值,default) 返回指定键的值,如果此键不存在返回0 147 classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1 148 # python3中用items()替换python2中的iteritems() 149 # key=operator.itemgetter(1)根据字典的值进行排序 150 # key=operator.itemgetter(0)根据字典的键进行排序 151 # reverse降序排序字典 152 sortedClassCount = sorted(classCount.items(),key=operator.itemgetter(1),reverse=True) 153 # 返回次数最多的类别,即所要分类的类别 154 return sortedClassCount[0][0] 155 156 157 def datingClassTest(filename): 158 # 打开的文件名 159 filename = filename 160 # 将返回的特征矩阵和分类向量分别存储到datingDataMat和datingLabels中 161 datingDataMat, datingLabels = file2matrix(filename) 162 # 取所有数据的百分之十 163 hoRatio = 0.10 164 # 数据归一化,返回归一化后的矩阵,数据范围,数据最小值 165 normMat, ranges, minVals = autoNorm(datingDataMat) 166 # 获得normMat的行数 (特征矩阵) 167 m = normMat.shape[0] 168 # 百分之十的测试数据的个数 169 numTestVecs = int(m * hoRatio) 170 # 分类错误计数 171 errorCount = 0.0 172 173 for i in range(numTestVecs): 174 # 前numTestVecs个数据作为测试集,后m-numTestVecs个数据作为训练集 175 classifierResult = classify0(normMat[i,:], normMat[numTestVecs:m,:], 176 datingLabels[numTestVecs:m], 4) 177 print("分类结果:%d\t真实类别:%d" % (classifierResult, datingLabels[i])) 178 if classifierResult != datingLabels[i]: 179 errorCount += 1.0 180 print("错误率:%f%%" %(errorCount/float(numTestVecs)*100)) 181 182 183 if __name__ == '__main__': 184 filename = '../data/datingTestSet.txt' 185 # 接收返回的特征矩阵和分类label向量 186 datingDataMat, datingLabels = file2matrix(filename) 187 # print(datingDataMat,datingLabels) 188 # showdatas(datingDataMat,datingLabels) # 调用此函数以画图 189 datingClassTest(filename)
下次继续~~~
https://www.cnblogs.com/zhangzhixing/