易懂:k-近邻算法

前言

  • 尽量表述易懂。
  • 重在算法本身,案例的的特征处理和数据清洗没有做多少。
相关信息
  • 定义:如果一个样本在特征空间中的k个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类别。
    通俗理解:距离最近的k个值中,占大多数的目标值就是被预测数据的目标值(k值就是“邻居值”的个数)。
  • 来源:KNN算法最早是由Cover和Hart提出的一种分类算法。
  • 公式(欧氏距离):可参考勾股定理理解 -。-
    公式详解:a1,a2为测试集的特征值数据;x1,x2为训练集的特征值数据;L为所计算出的距离,距离越小离“邻居”越近。
    L = ( a 1 x 1 ) 2 + ( a 2 x 2 ) 2 L=\sqrt{(a1-x1)^2+(a2-x2)^2}
  • k-近邻算法预测数据的原理:相似的样本,特征之间的值应该是相近的,那么经过测试集样本和训练集样本的距离计算后,推测出距离最近的几个样本中所对应的目标值相同和最大的目标值就是测试集样本的目标值了(这句话读起来有点绕,不要放弃哦-。-)。
    举个例子来说:如果特征差异过大,那么(a1-x1)^2值过大,总的结果就会过大,所以值越相近,越代表其特征相似,进而预测准确的数据。
  • 优点:简单、好理解、好实现、无需估计参数、无需训练
  • 缺点: 懒惰算法,对测试样本分类时的计算量大,内存开销大;必须指定k值,k值选择不当则分类精度不能保证。
  • 使用场景:小数据场景,几千到几万个样本。(考虑到其缺点,一般不会使用该方法,当然,偶尔也可以进行测试。
  • 补充:也正因为其算法特点,如果数据是要使用k近邻算法的话,是要进行标准化处理的,关于标准化参考:归一化与标准化
python实现KNN算法API介绍:
  • API:sklearn.neighbors.KNeighborsClassifier(n_neighbors=5,algorithm=‘auto’)
  • 重要参数介绍(第二个参数了解即可):
    • n_neighbors:int,可选(默认= 5),是查询默认使用的邻居数(邻居数的大小是影响算法准确性的:小了容易受到异常点的影响,k值取很大的时候比例会受到影响)。
    • algorithm:{‘auto’,‘ball_tree’,‘kd_tree’,‘brute’},可选用于计算最近邻居的算法:‘ball_tree’将会使用 BallTree, ‘kd_tree’将使用 KDTree。‘auto’将尝试根据传递给fit方法的值来决定最合适的算法。 (不同实现方式(不同数据结构),计算效率不同)。
测试案例
  • 数据集链接:Facebook用户签到数据集(具体要求请阅读数据集相关说明)
  • 数据集分类简单介绍:
    • 特征值:row_id:签到事件的ID x y:坐标 accuracy:位置精度 time:时间戳 place_id(目标值):商家的ID(睡觉的地方)
    • 目标值:入住位置的id
#!/usr/local/bin/python3
# -*- coding: utf-8 -*-
# Author  : rusi_
import pandas as pd
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler


def where_sleep():
    """
    k-近邻预测用户的(入住)签到位置
    :return:
    """
    # 读取数据
    data = pd.read_csv(r"E:\mac_obj_file\facebook\train.csv")
    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.loc[:, "day"] = time_value.day  # 推荐写法
    data["hour"] = time_value.hour
    data["weekday"] = time_value.weekday
    data = data.drop(["time"], axis=1)

    place_count = data.groupby("place_id").count()
    # tf = place_count[place_count.row_id > 3].reset_index()
    tf = place_count[place_count["row_id"] > 3].reset_index()  # 两种写法都可以
    data = data[data["place_id"].isin(tf["place_id"])]

    y = data["place_id"]
    x = data.drop(["place_id"], axis=1)
    x = x.drop(["row_id"], axis=1)
    x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.25)

    # 特征工程(标准化)ps:如果没有这个特征工程准确率为0.07
    std = StandardScaler()
    x_train = std.fit_transform(x_train)
    x_test = std.transform(x_test)

    # 进行算法流程
    knn = KNeighborsClassifier(n_neighbors=5)  # n_neighbors 参数可调
    knn.fit(x_train, y_train)
    y_predict = knn.predict(x_test)
    # print("预测的目标签到位置:\n", y_predict)
    # 查看准确率
    print("预测的准确率:\n", knn.score(x_test, y_test))
    return None


if __name__ == '__main__':
    where_sleep()
算法实现
发布了55 篇原创文章 · 获赞 3 · 访问量 2725

猜你喜欢

转载自blog.csdn.net/rusi__/article/details/103749442