最近在看 实战机器学习 一书,总觉得学了一些机器学习的方法却始终没有好好运用起来。于是开始看此书,今天看完KNN这一章。作一下简单的总结:
K-近邻,看字面意思就可以直接理解为 “由K个邻居决定的",大致的工作流程是:对于一个样本的特征空间中的最近的k个样本中,大多数所属的类别就是当前样本的类别。也就是说,现在存在N个样本点,并且这些样本点的标签(label)是已知的,对于一个新来的未知样本点x,计算x与已知N的样本点之间的距离,这里的"k”是作为用户可以控制的,通过最近的k个样本点的种类,由这k个样本的label值,选出出现次数最大的label即可。
上述流程很简单,有几个值得注意的地方,“距离”是如何定义的,直观地来讲,对于连续的变量,我们会首先想到欧式距离;对于离散的数据(例如文本的分类)来说,那么Hamming距离是可以用来作为标准的。
值得一提的是,距离的度量选择的好坏会很大程度上改善分类器的准确度。(分错的样本数/总的测试样本数)。
数据输入:输入的数据被看做是n维向量,其中的n是选取的特征。(特征可能有点二抽象,其实无非就是用来刻画该样本点的性质,比如一个三维空间的点,那么它的x,y,z轴的取值就是3个特征)。
假设输入的N个样本点。对于给定的一个测试向量y,我们就重复上述流程,得到这个样本的分类即可。
注意:上述分类的动作便是这个算法的开始泛化的结果。因此很多时候,KNN分类器是lazy的,因为将计算距离defer到了需要预测某新样本时。
在整个算法的实现过程中,需要注意的有如下几点:
1 各个特征维度的度量标准不一样,可能会导致某一个特征的对结果影响很大,比如上述的点的左边,三个轴的单位长度所表示的范围不一样,也就是说 一个点的x轴为1可能表示100(可能表示某人的身高),而y轴为1则表示0.01(表示某人在一天之内的工作时间比例,范围是0到1),那么显然,身高的差距会主导着整个度量。因此需要将各个特征进行归一化。归一化很简单: (当前特征值 - 该特征的最大取值)/(该特征的最大值 - 该特征的最小值)。这样就将所有的数据都映射到了[0,1]区间。
2 KNN的结果依赖于该样本周围的样本的集合,因此对于类间交叉重叠较多的情况,KNN工作的很好。
3 关于距离,上述提到了 欧式距离,Hamming距离,譬如还有一些专用的距离度量,比如LMNN。
KNN作为一个简单的机器学习算法,同样存在很多不足:
1 首先,KNN算法是基于实例的,也就是说我们需要掌握接近实际数据的训练样本数据。
2 其次,训练样本的数目决定了存储空间的大小。以及由于必须对数据集中的每一个数据都计算距离,计算量很大。
3 由于只是采用距离来做度量,没有考虑到实际数据本身的结构信息,因此很难知道数据本身背后的含义。
4 kNN采用的是“majority-voting”的方法,在数据严重不对称时,也就是说如果某一类数据本身就出现的概率非常大,那么新来的样本就很有可能落入该类别中。这显然是不合理的。克服这个,可以给每一个邻居加上一个权重。也可以将其中的距离相近的点Merge成一个节点,作为一个整体,就不用管在原先数据集中的密度。再进行分类。
最后, KNN算法不仅可以用于分类,还可以用于回归。同样也是采用该样本的最近的K个样本的属性的均值作为该样本的属性。同样可以按照上述方法给每个邻居一个权值(与距离成反比的权值,一般可以取1/距离)。