1.Knn:
knn是目前为止接触到的最简单之一的算法,算法很简单,就是求取测试样本距离最近的几个点,然后采用多数表决的规则,将测试样本归为那一类。
算法流程:
- 计算已知类别数据集中的点与当前点之间的距离
- 按照距离递增次序排序
- 选取与当前点距离最小的k个点
- 确定前k个点所在类别出现的频率
- 返回前k个点出现频率最高的类别作为当前点的预测分类
def classify0(inX, dataSet, labels, k):
dataSetSize = dataSet.shape[0]
diffMat = tile(inX, (dataSetSize,1)) - dataSet
#inx为我们的输入测试集,tile这个函数将它变成dataSetSize行1列的矩阵,这样就能同时跟所有的训练样本进行加减
sqDiffMat = diffMat**2 #采用欧式距离
sqDistances = sqDiffMat.sum(axis=1)
distances = sqDistances**0.5
sortedDistIndicies = distances.argsort() #返回的是对distances进行从小到大的排序返回对应值的索引
classCount={}
for i in range(k):
voteIlabel = labels[sortedDistIndicies[i]] #对应值的索引在labels当中就是对应的类
classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1 #在字典中获取voteIlabel的大小,没有则赋0
sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
#items返回的是键值的元组所组成的迭代器,key是定义了一个函数跟lambda的功能相似,这里的意思是按照值的大小进行排序
return sortedClassCount[0][0] #返回最多的值所对应的类,也即与测试样本最接近的类
2.kd数:
如果数据量非常大的时候我们并不能采用上面的方法,这样太耗时了,每一个都要做欧式计算,想要提高速率,肯定要减少计算距离的次数,而kd树就能做到
构造kd树算法:
- 构造根节点:确定样本有几个维度,比如说有三个维度1,2,3,在构造的过程中会一直不停的在这三个维度循环,首先选择维度1,以所有实例的第一维的坐标的中位数为切分点,注意寻找中位数的过程是,先对那一维的数据进行排序,然后计算len(trainlist)//2,一般奇数的时候会是中间的数,偶数的时候会是中间两个靠后的那一个,然后选出来的坐标就是我们的切分点,切分点的左边都是小于切分点的数,切分点的右边都是大于切分点的数,然后在左右两区域,再利用同样的方法切分,只不过此时要用第二维度的数据来比较,如此的循环下去,直到所有的数据被划分。
搜索kd树算法:
- 在kd树中找出包含目标点x的叶结点:从根结点出发,递归的向下访问kd树。若目标点当前维的坐标值小于切分点的坐标值,则移动到左子结点,否则移动到右子结点。直到子结点为叶结点为止
- 以此叶结点为“当前最近点”
- 递归的向上回退,在每个结点进行以下操作
-
(1)如果该结点保存的实例点比当前最近点距目标点更近,则以该实例点为“当前最近点”
-
(2)当前最近点一定存在于该结点一个子结点对应的区域。检查该子结点的父结点的另一个子结点对应的区域是否有更近的点。具体的,检查另一个子结点对应的区域是否与以目标点为球心、以目标点与“当前最近点”间的距离为半径的超球体相交。如果相交,可能在另一个子结点对应的区域内存在距离目标更近的点,移动到另一个子结点。接着,递归的进行最近邻搜索。如果不相交,向上回退
- 当回退到根结点时,搜索结束。最后的“当前最近点”即为x的最近邻点