Hyper@2016-10-21

Class=MachineLearning 机器学习实战笔记_KNN

机器学习实战笔记-KNN

第2章

程序2-1

diffMat=tile(inX, (dataSetSize,1))-dataSet

temp_1.png

tile就是平铺,瓦片,操作系统桌面的背景图片里有这词

argsort返回的是位置⇔Ordering

orders = Ordering[list = {1, 3, 5, 2, 8, 4}]

temp_2.png

Extract[list, List /@ orders]

temp_3.png

矩阵里按距离计算,对距离排序后然后从Labels里提取做循环,其实就是intX跟矩阵里的每个Vector进行一次距离的度量,然后再选择距离最小的点。

classify0[vec_, dataSet_, labels_, k_] :=

 Block[{},

  dataSetSize = dataSet // Dimensions;

  

  diffMat = ConstantArray[vec, dataSetSize[[1]]] - dataSet;

  (*注意这里dataSetSize索引取值和vec是一维还是二维的变化情况*)

  sqDiffMat = diffMat^2;

  sqDistances = sqDiffMat // Total[#, {2}] &;

  (*这里Total类比numpy里的一些axis的操作,也可以用Total/@#&*)

  distances = Sqrt[sqDistances];

  sortedDistIndices = distances // Ordering;

  classCount = Association[];

  For[i = 1, i <= k, i++,

   voteIlabel = labels[[sortedDistIndices[[i]]]];

   If[KeyExistsQ[classCount, voteIlabel], classCount[voteIlabel] += 1,

     classCount[voteIlabel] = 1];

   ];

  

  Sort[classCount] // Reverse

  

  

  ]
vec = RandomReal[10, {2}];

dataSet = RandomReal[10, {20, 2}];

(*使用聚类算法标注一下。。。*)

asso = Association[

   Flatten[Thread /@ 

     Thread[FindClusters[dataSet, 4] -> CharacterRange["A", "D"]]]];

labels = asso /@ dataSet

dataSet // MatrixForm

ListPlot[{dataSet, {vec}}, PlotStyle -> PointSize[.05], 

 Epilog -> Thread[Text[labels, dataSet]]]

temp_4.png

temp_5.png

temp_6.png

classify0[vec, dataSet, labels, 10]

temp_7.png

temp_8.png

优化版

如果要在大量的数据上进行一些实战,加些简单的策略,比如聚类后,对每分组索引等,然后再对小类[区域]进行更细的比对,或使用KD-Tree等等,这些属于算法和数据结构的优化

Mathematica版代码优化

在类比numpy数组的操作中,还是自己从矩阵结构计算了一下欧氏距离,那么如果调用一个计算+map一下呢?

classify1[vec_, dataSet_, labels_, k_] :=

 Block[{},

  distances1 = EuclideanDistance[vec, #] & /@ dataSet;

  sortedDistIndices = distances1 // Ordering;

  classCount = Association[];

  For[i = 1, i <= k, i++,

   voteIlabel = labels[[sortedDistIndices[[i]]]];

   If[KeyExistsQ[classCount, voteIlabel], classCount[voteIlabel] += 1,

     classCount[voteIlabel] = 1];

   ];

  

  Sort[classCount] // Reverse

  

  

  ]
classify1[vec, dataSet, labels, 10]

temp_9.png

如果使用pandas的话,也可以对整个数据集进行一次apply一个函数,python⇒numpy⇒pandas,然后代码越来越短。。。

classify2[vec_, dataSet_, labels_, k_] :=

 Block[{},

  asso = AssociationThread[dataSet -> labels];

  assoSorted = KeySortBy[asso, EuclideanDistance[vec, #] &];

  res = Counts[Values@assoSorted[[1 ;; k]]] // Sort // Reverse

  ]
classify2[vec, dataSet, labels, 10]

temp_10.png

当然也可以写成一句话⇒真尼玛短
这就是学习使用一些高级函数和数据结构,在做实验,学习一些东西时,可以先把一些不是重点的东西pass掉,关注如何调一些关键参数,做出效果等,当然前提是数据是理想的。

Counts[KeySortBy[AssociationThread[dataSet -> labels], 

      EuclideanDistance[vec, #] &][[1 ;; 10]] // Values] // 

  Sort // Reverse

temp_11.png