机器学习(五)k-近邻算法

机器学习(五)k-近邻算法

一. k-近邻算法简介

该算法可以算得上是最简单的分类算法了。他的原理也很简单。举一个比较通俗的例子,在生活当中,我们经常说:物以类聚,人以群分。假设,我们认识了一个人,你想调查这个人到底是什么样子的性格,有什么样子的性格爱好。那么你就可以看看他的密友,或者亲戚。那么大概率会是这个结果:朋友是什么样子的人,他也是那个样子的人。

这便是k近邻算法的一个通俗的解释。在实际运用当中,k近邻算法也是用来判断一个未知的样本属于什么类型的。判断方式,就是看这个未知样本和哪个已知样本比较相近。比如下面这个例子:

我们有若干个已知样本和他们的类型,现在,统计出来了一个新的电影,我们不知道他是什么类型,但是知道这个电影当中有18个打斗镜头,有90个接吻镜头,我们该怎么判断这个电影的类型?

在这里插入图片描述

其实,根据人的直观观察,大体就能猜出这是一个爱情电影。因为他接吻镜头很多,与前三行那几个爱情电影比较相近。但是,放到机器学习里面,你该如何判断这个“相近程度”呢?这便是k-近邻算法所涉及的问题。

1.1 k-近邻算法定义:

k-近邻算法,也简称为:KNN算法。其定义如下:

如果一个样本在特征空间中的k个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类别。

1.2 k-近邻算法的距离:

也就是我们开头所说的“相近程度”。实际上,关于这个距离的度量,有很多算法,其中最简单的莫过于欧氏距离:
在这里插入图片描述

除了欧氏距离,常见的还有:

在这里插入图片描述

二.k-近邻算法的使用

2.1 API介绍

在skleanr当中,为我们直接提供了K-近邻算法的接口:

sklearn.neighbors.KNeighborsClassifier(n_neighbors=5,algorithm='auto')

它的参数含义如下:

  • n_neighbors:int,可选(默认= 5),k_neighbors查询默认使用的邻居数

  • algorithm:{‘auto’,‘ball_tree’,‘kd_tree’,‘brute’},可选用于计算最近邻居的算法:‘ball_tree’将会使用 BallTree,‘kd_tree’将使用 KDTree。‘auto’将尝试根据传递给fit方法的值来决定最合适的算法。 (不同实现方式影响效率)。

    这当中,brute代表暴力求解。至于什么是kd-tree, 什么事ball-tree。暂时先不作要求

2.2 案例

假设我们有一个虚拟城市,这个城市的市民每到一个地方都要签到。现在我们有一个.csv文件,里面记录了这个城市市民签到的信息。让你去预测一下,如果这个城市来了一个新人,那这个人最有可能在哪个地方签到。

这个.csv文件的字段如下:

row_id,    x,    y,    accuracy,    time,    place_id

其中row-id 代表行号

(x,y)代表一个坐标

accuracy代表精确值

time为入住时间(这个是一个时间戳,而不是我们常用的时间格式)

place_id 代表入住地点的id号

重点:

无论是做什么样子的案例,大体都应该遵循以下步骤:

  • 1、数据集的处理

  • 2、分割数据集

  • 3、对数据集进行标准化

  • 4、estimator流程进行分类预测

from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
from sklearn.preprocessing import StandardScaler
import pandas as pd

def knn():
    """
    K-近邻预测用户签到位置
    :return:None
    """
    # 读取数据
    data = pd.read_csv("./Data/train.csv")


    # 处理数据(对应上述的步骤1)
    # 1、缩小数据,查询数据范围
    data = data.query("x > 1.0 &  x < 1.25 & y > 2.5 & y < 2.75")

    # 处理时间的数据,把原数据里面的时间戳给改成以秒为单位的时间
    time_value = pd.to_datetime(data['time'], unit='s')

    # 把日期格式转换成 字典格式
    time_value = pd.DatetimeIndex(time_value)

    # 构造一些特征
    data['day'] = time_value.day
    data['hour'] = time_value.hour
    data['weekday'] = time_value.weekday
	
    """
    很多时候,我们都需要把不需要的属性,对结果形成干扰的部分给删除掉,一方面不需要,另一方面,可以提高运行效率
    """
    # 把时间戳特征删除
    data = data.drop(['time'], axis=1)

    # 把签到数量少于或者等于3个目标位置删除(太少了,对结果形成不了太多的影响)
    place_count = data.groupby('place_id').count()
    tf = place_count[place_count.row_id > 3].reset_index()
    data = data[data['place_id'].isin(tf.place_id)]

    # 取出数据当中的特征值和目标值,即签到地点的相关数据
    y = data['place_id']

    # 注意:sklearn,axis=0代表列,但是在pandas当中,axis=1代表列
    x = data.drop(['place_id'], axis=1)

    # 进行数据的分割训练集合测试集(对应上面的步骤2)
    #x_train: 训练数据集,x_test:测试数据集,y_train:训练集tag,y_test:测试集tag
    x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.25)

    # 特征工程(标准化)(对应上面的步骤3)
    std = StandardScaler()

    # 对测试集和训练集的特征值进行标准化
    x_train = std.fit_transform(x_train)
    x_test = std.transform(x_test)

    # 进行算法流程
    knn = KNeighborsClassifier()

    # fit, predict,score (对应上面的step4)
    knn.fit(x_train, y_train)

    # 得出预测结果
    y_predict = knn.predict(x_test)

    print("预测的目标签到位置为:", y_predict)

    # 得出准确率
    print("预测的准确率:", knn.score(x_test, y_test))

if __name__ == "__main__":
    knn()

三、总结

k-近邻算法算是最简单的分类算法,他有如下特点:

  • 优点:简单,易于理解,易于实现,无需估计参数,无需训练

  • 缺点:k-近邻算法是一种懒惰算法,对测试样本分类时的计算量大,内存开销大;必须指定K值,K值选择不当则分类精度不能保证

    • k取值过小,则无法有效应对异常点影响
    • k值取过大,则导致计算量过大,且容易受最近数据太多影响,回到开头的人以群分的例子,就好比说,你想调查一个人,但是你既找了他的密友,也找了很多和他并没有太多接触的人,那么,你就很难了解这个人到底是什么人了。
  • k-近邻算法适用于小数据场景

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值