#coding=utf8
#KNN.py
from numpy import *
import operator
def createDataSet():
group=array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]]) #我觉得可以这样理解,每一种方括号都是一个维度(秩),这里就是二维数组,最里面括着每一行的有一个方括号,后面又有一个,就是二维,四行
labels=['A','A','B','B']
return group,labels
def classify0(inX,dataSet,labels,k): #inX是你要输入的要分类的“坐标”,dataSet是上面createDataSet的array,就是已经有的,分类过的坐标,label是相应分类的标签,k是KNN,k近邻里面的k
dataSetSize=dataSet.shape[0] #dataSetSize是sataSet的行数,用上面的举例就是4行
diffMat=tile(inX,(dataSetSize,1))-dataSet #前面用tile,把一行inX变成4行一模一样的(tile有重复的功能,dataSetSize是重复4遍,后面的1保证重复完了是4行,而不是一行里有四个一样的),然后再减去dataSet,是为了求两点的距离,先要坐标相减,这个就是坐标相减 [(x1-x2),(y1-y2)]
sqDiffMat=diffMat**2 #上一行得到了坐标相减,然后这里要(x1-x2)^2,要求乘方 [(x1-x2)^2,(y1-y2)^2]
sqDistances=sqDiffMat.sum(axis=1) #axis=1是列相加,,这样得到了(x1-x2)^2+(y1-y2)^2
distances=sqDistances**0.5 #开根号,这个之后才是距离
sortedDistIndicies=distances.argsort() #argsort是排序,将元素按照由小到大的顺序返回下标,比如([3,1,2]),它返回的就是([1,2,0]),返回的是坐标。也就是说返回的是距离哪个点最近的index。如果距离第三个点最近,那么就是[3,*,*,*]
classCount={}
for i in range(k):
voteIlabel=labels[sortedDistIndicies[i]] #取到距离最近点的lables,如果是3,那么就是'B'
classCount[voteIlabel]=classCount.get(voteIlabel,0)+1 #get是取字典里的元素,如果之前这个voteIlabel是有的,那么就返回字典里这个voteIlabel里的值,如果没有就返回0(后面写的),这行代码的意思就是算离目标点距离最近的k个点的类别,这个点是哪个类别哪个类别就加1
soredClassCount=sorted(classCount.iteritems(),key=operator.itemgetter(1),reverse=True) #key=operator.itemgetter(1)的意思是按照字典里的第1个排序,classCount的第0个是label,第1个是label对应的数量。reverse=True是降序排序
return soredClassCount[0][0] #返回类别最多的类别
def file2matrix(filename):
fr = open(filename)
arrayOfLines = fr.readlines() #文件读取
numberOfLines = len(arrayOfLines) #计算行数
returnMat = zeros((numberOfLines,3)) #将数据拆分成矩阵 m行3列
classLabelVector = []
index = 0
for line in arrayOfLines:
line = line.strip() #出去列头尾的多余字符比如\t
listFromLine = line.split('\t')
returnMat[index,:] = listFromLine[0:3] #取出头三数, returnMat[index,:]等价于returnMat[index], listFromLine[0:3] 等价于取出从0到3列
classLabelVector.append(int(listFromLine[-1])) #取出最后个数
index +=1
return returnMat, classLabelVector
def autoNorm(dataSet):
minVals = dataSet.min(0)#取出每一列的最小值
maxVals = dataSet.max(0)#取出每一列的最大值
ranges = maxVals-minVals#算出每一列中最大值-最小值
normDataSet = zeros(shape(dataSet))#加入dataSet有m行n列,会初始化为m行n列的0矩阵
m = dataSet.shape[0]#取出dataSet有多少行
normDataSet = dataSet - tile(minVals,(m,1))#矩阵进行减法(当前值-最小值)
normDataSet = normDataSet/tile(ranges,(m,1))#矩阵进行除法(除以最大差值)
return normDataSet, ranges, minVals
def datingClassTest():
hoRatio = 0.1#取出10%的数据作为测试数据
datingDataMat,datingLabels = file2matrix('datingTestSet2.txt')#将数据进行分类
normMat,ranges,minVals = autoNorm(datingDataMat)#归一化数据
m = normMat.shape[0]#算出数据的从行数
numTestVecs = int(m*hoRatio)#算出测试数据个数
errorCount = 0.0#错误数量
for i in range(numTestVecs):
classifierResult = classify0(normMat[i,:],normMat[numTestVecs:m],datingLabels[numTestVecs:m],3)#normMat[i],第i个测试数据,normMat[numTestVecs:m]取出剩下的90%作为训练数据,和训练标签,以前三个中最多的作为结果
print("the classifier came back with: %d, the real answer is: %d" %(classifierResult, datingLabels[i]))
if(classifierResult!=datingLabels[i]):#如何和标准的不一致,那么就认为错误。
errorCount+=1.0
print("the total error rate is : %f" %(errorCount/float(numTestVecs)))#计算错误率
def classifyPersion():
resultList = ['not at all', 'in small doses', 'in large doses']
percentTats = float(raw_input('percentage of time spend playing video games?'))
ffMiles = float(raw_input('frequent flier miles earned per year'))
iceCreate = float(raw_input('liters of ice cream consumed per year?'))
datingDataMat, datingLabels = file2matrix('datingTestSet2.txt')
normMat, ranges, minVals = autoNorm(datingDataMat)
inArr = array([ffMiles, percentTats, iceCreate])
classifierResult = classify0(inArr-minVals/ranges, normMat, datingLabels, 3)#对输入数据进行归一化,然后通过classify0分类器进行分类,得出结果
print classifierResult
print('You will probably like this person:',resultList[classifierResult])
有人说初学者,啥也不会就不要进入这行,我倒要看看,能不能进!啥不会我就学啥,有啥不一样的,你有脑袋我就没有啊!
numpy 数学库参数
.shape[0] 取行数 .shape[1]取列数
tile(A,(x,n)) 将A重复x行,n列
**2 平方 **0.5 开方
argsort 有小到大排序返回下标
operator.itemgetter(1) 按照第几个参数排列
调用matplotlib画图的流程是:调用figure()得到fig对象 -> 调用fig.add_subplot(111)得到axis对象 -> 调用plt.plot绘制 -> plt.show()显示出figure
>>> import matplotlib
>>> import matplotlib.pyplot as plt
>>> fig = plt.figure()
>>> ax = fig.add_subplot(111)
>>> ax.scatter(datingDataMat[:,1], datingDataMat[:,2])
fig.add_subplot(111) 是把整个画布拆分成1行1列,将画布分割成1行1列,图像画在从左到右从上到下的第1块
书上让加入颜色:
ax.scatter(datingDataMat[:,1], datingDataMat[:,2], 15.0*numpy.array(datingLabels), 15.0*numpy.array(datingLabels))
书上的方式行不通哇,然后改成了这种方式,但是需要import numpy
经过本人对游戏行业的考虑,针对MMO类型的游戏,我们可以应用此算法,应用到游戏的结婚系统中,但是具体数据的获取,需要针对数据库进行筛选,然后取出相应的数据。如在线时长,上线时间,经常做的任务,等级等一系列字段,进行筛选,归一化,按照kNN算法,进行推荐,这样推荐成功的概率会很大。并且很容易增加玩家上线时长,以及配对的符合度。