java学习30

87 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第30天,点击查看活动详情

 KNN (K-NearestNeighbor) K指K个邻居

(1)正如物以类聚,人以群居。越是相似的东西就越有可能是一类东西。从这张图片来看,判断Xu属于那种类别,可以取Xu最近的K个邻居(距离),在这个K个点中,那一类东西的概率最高,就把他定位为那个类别。

image.png

image.png 其中距离的求解:

曼哈顿距离: {\sum_{i=1}^{n}}\left |x _{Ak}-x _{Bk} \right|

欧氏距离:\sqrt{​{\sum_{i=1}^{n}}(x _{Ak}-x _{Bk})^2(多维空间)

KNN算法最简单粗暴的就是将预测点与所有点距离进行计算,然后保存并排序,选出前面K个值看看哪些类别比较多。

(2)应用

比如在电商中,可以根据消费者选择的东西去推荐他们可能感兴趣的的商品,还可以在一些网站可以看到相似用户这些。

代码:

1.aff内容解读

 在aff文件中有3种类型的花(山鸢尾(Iris-setosa),变色鸢尾(Iris-versicolor),维吉尼亚鸢尾(Iris-virginica)),每一个花类有50个数据,每条记录有 4 项特征(花萼长度、花萼宽度、花瓣长度、花瓣宽度) 2.步骤

(1)解析文本内容,获取数据集

(2)根据获取的数据集划分训练集和测试集,在分割数据集时打乱数据索引位置,以保证在取数时更有说服性

(3)对测试集数据进行预测:对每个测试数据,取他的k个邻居,这k个邻居时距离这个测试数据最近得k个点(计算距离用的欧式距离)

(4)取出的K个邻居,判断每个邻居属于哪一类型的

(5)测试其准确度

kNN 分类器 (续)

 重新实现 computeNearests, 仅需要扫描一遍训练集, 即可获得 k 个邻居

分析:

扫描一次训练集,当时我第一想法是先扫描训练集,计算测试点到训练集的距离并用距离数组进行存储,在对距离数组进行插入排序获取前k个数据,但是这样并不满足时间复杂度的要求,后面对其进行改进,在计算距离的同时对数据进行排序,这样就满足要求了(因为这个方法返回的邻居,这里借助了一个数组来存储训练集的索引并与距离数组一一对应)。经过测试,符合要求。

当时想着不用两个数组来做,用 List<Map<Integer,Double>> distance = new ArrayList<>(),键值对的形式,但是发现这个在进行交换数据比较麻烦,故放弃了。

public int[] computeNearestsNew(int paraCurrent) {
        int[] resultNearests = new int[numNeighbors];
 
        int[] trainingIndex = new int[trainingSet.length];
        double[] trainingDistance = new double[trainingSet.length];
       
        int j;
        double tempData;
 
        //在计算距离的同时进行插入排序
        for (int i = 0; i < trainingSet.length; i++) {
            trainingDistance[i]  = distance(paraCurrent, trainingSet[i]);
            tempData = trainingDistance[i];
            for (j = i-1; j >= 0 && trainingDistance[j] > tempData; j--) {
                trainingDistance[j+1] = trainingDistance[j];
                trainingIndex[j+1] = trainingIndex[j];
            }
            trainingDistance[j+1] = tempData;
            trainingIndex[j+1] = i;
        }
 
        //获取前面k个邻居
        for (int i = 0; i < numNeighbors; i++) {
            resultNearests[i] = trainingSet[trainingIndex[i]];
        }
        System.out.println("The nearest of " + paraCurrent + " are: " + Arrays.toString(resultNearests));
        return resultNearests;
    }