KNN的全称是k- Nearest Neighbors. 在数据中找到最接近的数据,然后根据剩下的k个数据做选择。 怎么测量A数据和B数据是否接近方面,我们用到了测量数据距离的公式,Euclidian:
例如计算点(0,0) 和点(1,2)的距离就是:
假设,你就是在相亲网站注册了你,你平时在选择是否觉得与女嘉宾出来约会是,总有些考量,比如,身高,年龄,长相,体重等。等你选择了多个你觉得会出去约会的女嘉宾,代码就对新来的女嘉宾,做个预测,找的你之前选择这些特征最为接近的K个女嘉宾。做出决策
def classify0(inX, dataSet, labels, k):
# getting the rows of the dataset.
dataSetSize = dataSet.shape[0]
# tile the second parameter means tile shape
diffMat = tile(inX, (dataSetSize, 1)) - dataSet
sqDiffMat = diffMat ** 2
# This axis = 1 mean sum the row of data
sqDistances = sqDiffMat.sum(axis=1)
distances = sqDistances ** 0.5
# example: x=np.array([1,4,3,-1,6,9])
# y=array([3,0,2,1,4,5])
sortedDistIndicies = distances.argsort()
classCount = {}
for i in range(k):
voteIlabel = labels[sortedDistIndicies[i]]
# P
# dict = {'Name': 'Zara', 'Age': 27}
# print "Value : %s" % dict.get('Age')
# print "Value : %s" % dict.get('Sex', "Never")
# Value : 27 Value : Never
classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1
sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True)
return sortedClassCount[0][0]
这片段代码摘自Machin Learning In Action.
我们这里就以这片段做分析。已相亲节目为例子,它是怎么完成对于新来相亲嘉宾,根据她(他)的基本信息如,身高,体重,长相…来判断他(她)是否喜欢的类型。
def classify0(inX, dataSet, labels, k):
有四个参数:
第一个inX,一组样本用例。例如相亲节目中对【身高,体重,收入】比较重视,也就是这组数据是【170cm, 60kg, 1000~2000收入】
第二个dataSet, 采集到所以对于相亲对象的身高,体重,收入等数据。
第三个Labels,这标记样本数据,如,在一组数据中【身高,体重,收入】他满意这类相亲对象那标记为1, 不满意为0
第四个参数K, 就是比对K个人的相关信息,比如,这些相似的相亲数据中,他选择的偏好是哪些。
dataSetSize = dataSet.shape[0]
这个是获得样本的条数,比如收集到的100个相亲对象信息,对应的dataSetSize就是100.
diffMat = tile(inX, (dataSetSize, 1)) - dataSet
这行就是计算其中一条样例与其他对象的差值。其中需要强调的是tile. 在英语中
tile指的是瓷砖,做动词就是铺瓷砖。《老友记》第8季,第七集中,女佣很喜欢Manica的清洁剂就说到:Mrs Bing, this tile cleaner is in credible. 这就是其中的tile. 回到代码,tile就相当我们把inX,平铺出去,怎么铺呢?按照(dataSetSize,1)的大小平铺。在相亲为例子的中,我们得到一个女孩的中比较重要的信息,如【身高,体重,年龄,长相】等等,给她tile出去,就是把这个女孩的信息复制出去,复制出来的条数跟dataSet的条数一样的。然后在减掉dataSet的数据。得到diffMat这种差值数据集合。
sqDiffMat = diffMat ** 2
这行就是对这差值求平方。为什么这么做,运用的是数学中的卡达尔公式,求两点之间的距离。
sqDistances = sqDiffMat.sum(axis=1)
这个是对矩阵中的行进行相加,axis 是最关键的参数,表示维度。如其中一个人的信息,与别人比对完之后,汇总起来。前几天刚看了《非诚勿扰》的节目,其中两个女孩的陈东源,和陈子涵的身高,年龄都很象,她们两个女孩都对那男孩子感兴趣。那男孩子改选谁呢?
distances = sqDistances ** 0.5
这个在对值求平方根,是公式的一部分,不做重点强调,强调的是**的意思就是求数值的指数幂。
sortedDistIndicies = distances.argsort()
这行运行代码时的重点,也是难点,就是它的还回值到底是什么呢?它还回从小到大数值对应的Index. 比较拗口,举个例子:distances =[5,3,9,4] , 它对于从小到大应该是[3,4,5,9], 那3是在位置1,5在位置0,所以输出结果应该是[1,3,0,2],建议自己去实验下。
classCount = {}
for i in range(k):
voteIlabel = labels[sortedDistIndicies[i]]
# P
# dict = {'Name': 'Zara', 'Age': 27}
# print "Value : %s" % dict.get('Age')
# print "Value : %s" % dict.get('Sex', "Never")
# Value : 27 Value : Never
classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1
这片段中的get对我来说非常重要。总结下get用法:
在《老友记》第八季第七集中,女佣看见Manica清洁剂很好用,后面补充到:“How did you get it?” 这里get就是,得到,买到意思。
在《泰坦尼克号》电影中,Rose在甲板上问Jone:“You do get around for poor guy?” 这里的get就是“动身”,身体发出的动作。
在《穿普拉达的女王》电影中,女主角气氛的对男朋友说:“But I can’t let Miranda get to me” 我不想让Miranda影响到我,这里的get,是收到影响。
我们这代码中get是什么意思呢?当然就是第一种情况,在字典{}中得到它的值,如果没值的话,默认为0.
sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True)
return sortedClassCount[0]
[0]