理解近邻分类
你知道蛋白质、蔬菜和水果是怎么分类的吗?生活中我们发现既不脆也不甜的是蛋白质,脆而不甜的是蔬菜,而水果往往是甜的,有可能脆也有可能不脆。基于以上生活经验(人以群分,物以类聚),那么你知道西红柿是水果还是蔬菜呢?首先我们来看下面一组数据。
食物 | 甜度 | 脆度 | 食物类型 |
---|---|---|---|
葡萄 | 8 | 5 | 水果 |
四季豆 | 3 | 7 | 蔬菜 |
坚果 | 3 | 6 | 蛋白质 |
橙子 | 7 | 3 | 水果 |
现在如果我们知道西红柿的甜度为6,脆度为4,如果我们把这些数据放在横轴为甜度,纵轴为脆度的二维平面图上,我们很容易计算出西红柿与其他四种食物之间的直线距离。例如西红柿和四季豆之间的距离为:
$$ d(西红柿, 四季豆) = \sqrt{(6-3)^2 + (4-7)^2} =4.2 $$
根据以上算法,我们分别计算了西红柿和葡萄、四季豆、坚果、橙子之间的距离,分别是2.2、4.2、3.6、1.4。
我们发现西红柿和橙子之间的距离最短,那么我们据此认为西红柿是一种水果。这里其实是只选了一个最近的“邻居”,即k=1,是一个1NN分类。
如果我们使用k=3的KNN算法。那么它会在三个最近邻居即橙子、葡萄和坚果之间进行投票表决。因为这个里面有两票归为水果(2/3的票数),所以西红柿再次归为水果。
那么k究竟选择多少合适呢?
如果我们选择一个很大的k,会减少噪声数据对模型的影响,或者说减少噪声导致的模型的波动,但是它会使分类器忽视不易察觉但是却很重要的模式风险。比如如果k选择所有观测值的数量,那么原数据中如果水果的占比非常高,那么投票结果也很容易导致西红柿被分到水果类。
如果我们选择一个单一的近邻,这会使得噪声数据或者异常值过度影响模型,导致模型不稳定。
显然,最好的k值应该是两个极端值之间的某个值。在实际中,k一般选择样本量的平方根。比如有15个样本,15的平方根为3.87,我们可以设置k=4。另一种方法是居于各种测试数据集来测试多个k值,并选择一个各异提供最好分类性能的k值。除非噪音非常大,否则大的数据集可以使k值的选择不那么重要,因为参与“投票”的邻居足够多。
KNN算法对数据的要求
如果我们在数据集中加入另外一个特征,比如食物的辛辣度,辛辣度的取值在0~超过100万,而甜度和脆度的取值在1~10之间,所以尺度的差异,导致辛辣对距离函数的影响远远超过了甜度和脆度,如果不对数据进行调整,那么我们可以预见,距离度量和辛辣度有很大的关系,而脆度、甜度的影响几乎可以忽略不计。
解决的方法便是对原数据进行标准化处理,使各个特征的值都落在0~1范围内,或者使各个特征在量上具有可比性。常用的方法有两种:
- min-max标准化。特征X的每一个值减去它的最小值再除以特征X的极差。这里直接创建一个函数方便后期调用。
|
|
- z-分数标准化。特征X的每一个值减去特征X的均值后,再除以特征X的标准差。创建函数如下:
|
|
注意:计算非数值型数据的距离,需要将原数据先转化为数值型数据。一种典型的解决方案使利用虚拟变量编码。例如1表示男性,0表示女性。
第一步收集数据
文中数据来源为威斯康星州乳腺癌数据集,本数据包含699个样本,11个变量。可在 UCI机器学习数据库中找到。
|
|
数据集中的变量说明:
- ID:样本ID号码
- clumpThickness:肿块厚度
- sizeUniformity:细胞大小的均匀性
- shapeUniformity:细胞形状的均匀性
- maginalAdhesion:边际附着力
- singleEpithelialCellSize:单个上皮细胞大小
- bareNuclei:裸核
- blandChromatin:乏味染色体
- normalNucleoli:正常核
- mitosis:有丝分裂
- class:类别。benign表示良性,malignant表示恶性。
第二步探索和准备数据
|
|
第一个变量ID不纳入数据分析,最后一个变量class即输出变量。
对于每一个样本来说,另外九个变量是与判别恶性肿瘤相关的细胞特征,任一变量都不能单独作 为判别良性或恶性的标准,建模的目的是找到九个细胞特征的某种组合,从而实现对恶性肿瘤的 准确预测。
数据从UCI数据库中抽取,剔除缺失值,并随机分出训练集和验证集,其中 训练集中包含478个样本单元 (占70%), 其中良性样本单元317个, 恶性样本单元161个; 验证集中包含205个样本单元 (占30%), 其中良性127个, 恶性78个。
第三步基于数据训练模型
|
|
第四步评估模型的性能
|
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
## ## ## Cell Contents ## |-------------------------| ## | N | ## | N / Row Total | ## | N / Col Total | ## | N / Table Total | ## |-------------------------| ## ## ## Total Observations in Table: 205 ## ## ## | Predicted ## Actual | benign | malignant | Row Total | ## -------------|-----------|-----------|-----------| ## benign | 125 | 2 | 127 | ## | 0.984 | 0.016 | 0.620 | ## | 0.940 | 0.028 | | ## | 0.610 | 0.010 | | ## -------------|-----------|-----------|-----------| ## malignant | 8 | 70 | 78 | ## | 0.103 | 0.897 | 0.380 | ## | 0.060 | 0.972 | | ## | 0.039 | 0.341 | | ## -------------|-----------|-----------|-----------| ## Column Total | 133 | 72 | 205 | ## | 0.649 | 0.351 | | ## -------------|-----------|-----------|-----------| ## ## |
左上角代表真阴性,右下角代表真阳性。预测的准确率为(125+70)/205*100%=95.12%。同时我们也发现位于左下角的8个样本,实际为恶性,但是却被KNN错误地归为良性,即假阴性;右上角2个样本,实际为良性,却被KNN错误地归为恶性,即假阳性。但是预测的准确率还是比较高的,模型令人满意。
第五步提高模型的性能
这里我们可以尝试两种简单的改变,一是数据标准化处理时可以考虑采用z-分数标准化,二是尝试几个不同的k值。需要注意的是,过分的追求预测的精度,可能导致过拟合,加大了拟合噪音的可能,从而使泛化能力变弱。
在确定k值方面,caret包又可以大显身手了。
|
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
## k-Nearest Neighbors ## ## 205 samples ## 9 predictor ## 2 classes: 'benign', 'malignant' ## ## No pre-processing ## Resampling: Cross-Validated (10 fold) ## Summary of sample sizes: 185, 184, 185, 184, 185, 184, ... ## Resampling results across tuning parameters: ## ## k Accuracy Kappa ## 2 0.9561905 0.9049269 ## 3 0.9564286 0.9067712 ## 4 0.9466667 0.8857997 ## 5 0.9611905 0.9170926 ## 6 0.9561905 0.9064544 ## 7 0.9511905 0.8953774 ## 8 0.9514286 0.8951847 ## 9 0.9609524 0.9163366 ## 10 0.9609524 0.9163366 ## 11 0.9511905 0.8933637 ## 12 0.9511905 0.8933637 ## 13 0.9511905 0.8933637 ## 14 0.9461905 0.8817695 ## 15 0.9461905 0.8817695 ## 16 0.9511905 0.8933637 ## 17 0.9414286 0.8714247 ## 18 0.9461905 0.8817695 ## 19 0.9464286 0.8830189 ## 20 0.9414286 0.8699629 ## ## Accuracy was used to select the optimal model using the largest value. ## The final value used for the model was k = 5. |
报告显示当k=5时Kappa统计量(用于测量两个分类器对观测值分类的一致性)值最高。
下面我们利用k=5重新训练模型:
|
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
## ## ## Cell Contents ## |-------------------------| ## | N | ## | N / Row Total | ## | N / Col Total | ## | N / Table Total | ## |-------------------------| ## ## ## Total Observations in Table: 205 ## ## ## | Predicted ## Actual | benign | malignant | Row Total | ## -------------|-----------|-----------|-----------| ## benign | 123 | 4 | 127 | ## | 0.969 | 0.031 | 0.620 | ## | 0.969 | 0.051 | | ## | 0.600 | 0.020 | | ## -------------|-----------|-----------|-----------| ## malignant | 4 | 74 | 78 | ## | 0.051 | 0.949 | 0.380 | ## | 0.031 | 0.949 | | ## | 0.020 | 0.361 | | ## -------------|-----------|-----------|-----------| ## Column Total | 127 | 78 | 205 | ## | 0.620 | 0.380 | | ## -------------|-----------|-----------|-----------| ## ## |
我们比较两次结果,我们发现假阴性减少了4个,真阳性增加2个,但是总体上预测的精度还是提高到了(123+74)/205*100%=96.10%,精度提高近1个百分点。
笔者也尝试了利用z-分数标准化对原数据进行处理,根据Kappa统计量确定最优k值为11,结果显示真阴性为123,真阳性为73,假阴性为5,假阳性为4,精度为(123+73)/205*100%=95.61%,精度也是略有提升的。
最后需要指出的是,还有其他方法可以对距离进行加权,kknn包提供了10中不同的加权方式,有兴趣可以尝试。