美文网首页KNN
机器学习路程——k近邻(KNN)算法(python实现)

机器学习路程——k近邻(KNN)算法(python实现)

作者: 一只黍离 | 来源:发表于2018-12-25 19:45 被阅读178次

    使用python库sklearn,pandas
    数据来源:kaggle Facebook V: Predicting Check Ins
    数据网址:https://www.kaggle.com/c/facebook-v-predicting-check-ins/data
    如存在问题或不足之处请指正,靴靴!!!

    1 k-近邻算法描述

    1.1 简介

    对于传统k近邻算法,对于给定的数据集,有n个数据样本是已标记的,另一部分数据样本是未标记的,对于未标记的数据样本,通过如下方式进行分类:

    • 度量每个未标记数据样本与所有已标记数据样本的距离;
    • 对所有求出的距离选择与未标记数据样本距离最近的k(k≤n)个已标记数据样本;
    • 统计这k个已标记的数据样本,那一类的数据样本个数最多,则未标记的拘束样本标记为该类样本

    k近邻算法没有一个数据样本训练过程,本身是一种惰性监督算法,该算法对k值的选择以及距离的度量方式都会影响最终的分类精度。

    1.2 算法特性及优缺点

    优点:精度高,对异常值不敏感

    缺点:k值敏感,空间复杂度高(需要保存全部数据),时间复杂度高(平均O(logM),M是训练集样本数)

    适用于: 带lable的数值类

    2 距离计算

    2.1 欧氏距离:

    二维空间:

    公式: 二维空间欧氏距离公式

    为点(x1,y1)与(x2,y2)间的距离。

    多维空间

    公式: 多维空间欧氏距离公式

    为点(x1,x2,···,xn)与(y1,y2,···,yn)间的距离。

    3 简单案例

    在已知6部电影中的打斗镜头与接吻镜头数目,和每部电影所属类别的情况下,已知出未知电影中的打斗镜头与接吻镜头数目,求出其所属类别。如下图所示:

    案例图 图中所给电影数据具有两个特征值(打斗镜头数目,接吻镜头数目),可以用一个二维空间进行表示,如下图所示: 坐标系

    1、根据欧氏距离可以求出未知影片与各影片间的距离

    • 未知影片->影片1 = 20.5
      未知影片->影片2 = 18.9
      未知影片->影片3 = 19.2
      未知影片->影片4 = 115.3
      未知影片->影片5 = 117.4
      未知影片->影片6 = 118.9

    2、按照远近顺序排序:
    影片2<影片3<影片1<影片4<影片5<影片6

    3、选取样本
    k取值(上文提到为选取样本数量):1,3,6

    • k=1:
      -- 选取样本为影片2
      -- 未知影片为爱情片
    • k=3:
      -- 选取样本为影片2,影片3,影片1
      -- 未知影片为爱情片
    • k=6:
      -- 选取样本为影片2,影片3,影片1,影片4,影片5,影片6
      -- 未知影片不确定

    由此可见k值取值至关重要,其取值影响此算法的分类结果

    4 代码展示

    导入所需模块

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

    文件在当前目录文件夹data\FBlocation中


    文件

    k近邻算法:

    def knncls():
        """
        K-近邻预测用户位置
        :return: None
        """
        # 窗口内输出不带省略号
        pd.set_option('display.width', 1000)  # 设置字符显示宽度
        pd.set_option('display.max_rows', 1000)  # 设置显示最大行
        pd.set_option('display.max_columns', None)  # 设置显示最大列
    
        # 读取数据
        data = pd.read_csv('data\\FBlocation\\train.csv')
    
        # print(data.head(10))
    
        # 处理数据
        # 1、缩小数据,查询数据筛选
        data = data.query("x > 1.0 & x < 1.25 & y > 2.5 & y < 2.75")
    
        # 2、处理时间数据
        # pd.to_datatime把时间戳转换成时间年月日的形式
        # pd.DatetimeIndex 把日期数据转换为字典格式
        time_value = pd.to_datetime(data['time'], unit='s')
    
        # print(time_value)
        # 把日期格式转换为字典格式
        time_value = pd.DatetimeIndex(time_value)
    
        # 构造一些特征
        data['day'] = time_value.day
        data['hour'] = time_value.hour
        data['weekday'] = time_value.weekday
    
        # 把时间戳特征删除
        data.drop(['time'], axis=1)  # 这里1表示列,sklearn里面0表示列
        # print(data)
    
        # 把签到数量少于n个的目标位置删除
        place_count = data.groupby('place_id').count()
        # print(place_count)
        tf = place_count[place_count.row_id > 3].reset_index()  # 索引从0开始
    
        data = data[data['place_id'].isin(tf.place_id)]
    
        # 取出数据当中的特征值与目标值
        y = data['place_id']  # 目标值
    
        x = data.drop(['place_id','row_id'], axis=1)  # 特征值
    
    
        # 进行数据的分割训练集合测试集
        x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.25)
    
        # print(data)
        # 特征化工程(标准化)
        std = StandardScaler()
    
        # 对测试集和训练集的特征值进行标准化
        x_train = std.fit_transform(x_train)
        x_test = std.transform(x_test)
    
    
        # 进行算法流程    # 超参数(n_neighbors)默认为5
        knn = KNeighborsClassifier(n_neighbors=8)
    
        # fit, predict,score
        knn.fit(x_train,y_train)
    
        # 得出预测结果
        y_predict = knn.predict(x_test)
    
        print("预测目标签到位置为:",y_predict)
    
        print("得出准确率:",knn.score(x_test,y_test))
    
        return None
    
    if __name__ == '__main__':
        knncls()
    

    输出结果:


    结果

    参考文献
    [1]章宦记.改良的kmeans与K近邻算法特性分析[J].电子产品世界,2016,23(01):79-80.

    相关文章

      网友评论

        本文标题:机器学习路程——k近邻(KNN)算法(python实现)

        本文链接:https://www.haomeiwen.com/subject/suaakqtx.html