数据挖掘:K近邻

数据挖掘:K近邻

@(机器学习)[数据挖掘, K近邻, 算法]

K最近邻(k-Nearest Neighbor,KNN)分类算法,是最简单的机器学习算法之一。该方法的思路是:如果一个样本在特征空间中的k个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类别(近朱者赤近墨者黑)。

  • 数据挖掘K近邻
    • 准备工作
      • 环境与数据集
      • 数据窥探
    • K最近邻算法
      • 算法剖析
      • 距离公式
      • 归一化数值
        • 两种方式
      • 算法实现

准备工作

环境与数据集

  • Anaconda4.2
  • Python3.6
  • numpy
  • pandas
  • windows10
  • Ipython

这里我们使用的是UCI提供的数据集,该数据集描述了从事各行各业的人员的收入情况,是一个二分类的数据集。该数据分别有测试集与训练集,且有多个属性,属性值分别有离散与连续,以后的一些其他算法中也会使用这个数据集。详细信息点击UCI了解,如有需要,请点击这里下载。

PS:其实在应用算法前我们应该进行探索性数据分析(Exploratory Data Analysis,简称EDA),这里只讨论算法的实现,其他一些非必要的步骤我们都非常不专业的省去了。

数据窥探

Ipython中使用pandas模块加载数据集,看看数据集大概长什么样子吧。

可以看到,数据集中包含着离散与连续的属性,这里我们暂时只用到连续的属性值,classes分类标签说明该人员的收入情况,也就是我们需要用算法预测的标签。可以把这些属性的标签存在一个变量中,以便后续的使用。(PS:这里加载的数据已经被预先处理过了,即已经处理过缺失值等情况。)

lables = ['age', 'capital_gain', 'capital_loss', 'hours_per_week', 'education_num', 'fnlwgt']

K最近邻算法

算法剖析

以二维平面举例,

C是待分类的点,通过计算点CAB的距离,从而判断C是属于A还是B。假设图中AB两个位置各有有50个点,通过距离公式计算C到这一百个点中的距离,然后找出K个最小的,在这K个最小的点中,如果A类点比B类点多,就表示C属于A,否则,C属于B。这应该就是K最近邻算法的思想,一般来说K的值最好是取奇数。

距离公式

  • 余弦度
  • Jaccard 距离或相似度
  • Mahalanobis 距离
  • Hamming距离(汉明距离)
  • Manhattan距离(曼哈顿距离)
  • 闵可夫斯基距离(MinkowskiDistance) d=ni=1(Xixi)pp
  • 欧式距离

距离公式的详细介绍请浏览这里是距离公式的详细介绍。这里我们采用相对好理解的也好建模的欧式距离来实现我们的算法。用 Xi 来表示样本空间元素的属性,其中 i{1,2,3...n} ;用 xi 来表示待检测元素的属性,其中 i{1,2,3...n}

d=i=1n(Xixi)2

其中,n是数据集的列长度,即上面lables变量的长度值。

归一化数值

对于距离公式来说,假如我们有一个属性 xi 的值异常的大(相对与其他属性来说),那么对于距离 d 的影响非常的大,为了消除单个属性对于结果的影响,我们首先要将所有的属性值做归一化处理。

两种方式

  1. min-max标准化(Min-Max Normalization)

也称为离差标准化,是对原始数据的线性变换,使结果值映射到[0 - 1]之间。转换函数如下:

X=xminmaxmin

其中max为样本数据的最大值,min为样本数据的最小值。这种方法有个缺陷就是当有新数据加入时,可能导致max和min的变化,需要重新定义。

  1. Z-score标准化方法

这种方法给予原始数据的均值(mean)和标准差(standard deviation)进行数据的标准化。经过处理的数据符合标准正态分布,即均值为0,标准差为1,转化函数为:

X=xuσ

这里采用第二种方法来归一化我们的数值。代码如下:

# 这里的lables是数据集的所有离散属性的标签
mean_std = defaultdict(tuple) # 保存着每个属性的均值与方差
for lable in lables:
    mean = dataset[lable].mean()
    std = dataset[lable].std()
    dataset[lable] = (dataset[lable] - mean) / std
    mean_std = (mean, std)

算法实现

根据欧式距离公式,可以计算出k个最近距离点,代码如下:

def distance(train_data, test_data, k):
    """
    计算最近 k 个点的距离
    :train_data:[Type]->  pandas.core.frame.DataFrame 用于训练的数据集
    :test_data: [Type]-> pandas.core.series.Series 被测试的单行数据
    :k: 距离最近的k个点
    :return: 包含k个最近距离的点的索引
    """
    train_data = np.square((train_data - test_data))
    distace_list = np.sqrt(train_data.sum(axis=1)).argsort()[:k]
    return distace_list

你可能感兴趣的:(python,机器学习,数据分析,机器学习,数据挖掘,算法)