• 《机学五》KNN算法及实例


    一、概述

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

    二、距离计算公式

    两个样本的距离可以通过如下公式计算,又叫【欧式距离】

    设有特征,a(a1,a2,a3),b(b1,b2,b3),那么:
    $$sqrt{(a1-b1)^{2}+(a2-b2)^{2}+(a3-b3)^{2}}$$

    三、sklearn k-近邻算法API

    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方法的值来决定最合适的算法 (不同实现方式影响效率)

    四、实战

    数据位置:https://www.kaggle.com/c/facebook-v-predicting-check-ins/data

    五、数据的处理

    1、缩小数据集范围

    DataFrame.query()
    

    2、处理日期数据

    pd.to_datetime
    pd.DatetimeIndex
    

    3、增加分割的日期数据

    4、删除没用的日期数据

    pd.drop
    

    5、将签到位置少于3个用户的删除

    #按place_id列进行分组,并数出每个地方有多少次签到
    place_count =data.groupby('place_id').aggregate(np.count_nonzero)
    #入住次数>3个的拿出来,place_id放到最后做为一个特征,前面加一个新索引列0-n
    tf = place_count[place_count.row_id > 3].reset_index()
    #原表的place_id,存在上一步新建的表里的,单独拿出来做为新数据
    data = data[data['place_id'].isin(tf.place_id)]
    

    六、Knn算法实战

    数据集示例(trian.csv):
    在这里插入图片描述

    6.1.初步knn,暂时不用特征工程(标准化)

    此处分为两步:

    1. 因为数据集太大选择一部分数据进行处理choisecsv()
    2. 进行knn算法knndemo()
    3. 可以看到此时准确率仅为2.7%
    import pandas as pd
    from sklearn.model_selection import train_test_split  #数据集分割成:测试集、训练集模块
    from sklearn.neighbors import KNeighborsClassifier #knn近邻算法模块
    
    def choisecsv():
        """
        选取一部分数据保存为新表格
        :return:
        """
        # 【1】读取数据
        path = "D:\a\data\facebook-v-predicting-check-ins\train.csv"
        data = pd.read_csv(path)
        # print(data.head(10))
    
        # 【2】因为数据集太大,只选取一部分数据,保存一个新表格
        data = data.query("x > 1.0 &  x < 1.25 & y > 2.5 & y < 2.75")
        print(data.head(10))
        data.to_csv('train_s.csv',index=False) #第2参数,不要在新csv里最前列自动加索引
    
    def demoknn():
        """
        根据输入坐标,预测入住地点
        :return:
        """
        data=pd.read_csv("train_s.csv")
    
        #【1】时间戳(785470):转化时间列的时间戳为时间类似:1970-1-1 12:00:00
        time_value=pd.to_datetime(data['time'],unit='s')
        #print(time_value)
        
        #(1.1)把日期转化为字典格式
        time_value=pd.DatetimeIndex(time_value)
    
        # (1.2)根据时间字典构造一些新特征:月,天,时,星期几
        data['mouth']=time_value.month
        data['day'] = time_value.day
        data['hour'] = time_value.hour
        data['weekday'] = time_value.weekday
    
        #(1.3)删除时间戳列。pd里0是行,1是列
        data=data.drop(['time'],axis=1)
        #print(data.head(10))
    
    
        #【2】删除入驻数量少于3次的地方
        place_count=data.groupby('place_id').count() #按place_id列进行分组,并数出每个地方有多少次签到
        tf = place_count[place_count.row_id > 3].reset_index() #入住次数>3个的拿出来,place_id放到最后做为一个特征,前面加一个新索引列0-n
        data = data[data['place_id'].isin(tf.place_id)]  #原表的place_id,存在上一步新建的表里的,单独拿出来做为新数据
        #print(data.sample(10))
    
        #【3】取得特征值x、目标值y
        y=data['place_id']
        x=data.drop('place_id',axis=1)
    
        #【4】分割数据集
        x_train,x_test,y_train,y_test=train_test_split(x,y,test_size=0.25)
    
        #【5】特征工程(标准化)(暂时跳过)
    
        #【6】执行Knn算法
        knn=KNeighborsClassifier(n_neighbors=5)
    
        #【7】fit(处理),执行算法(到此模型已训练完成)
        knn.fit(x_train,y_train)
    
        #【8】预测结果predict(输入测试集进行预测)
        y_predict=knn.predict(x_test)
        print('预测的位置为:',y_predict)
    
        #【9】算出准确率scroe(对模型进行测试集的预测,的准确率计算):
        print('准确率为:',knn.score(x_test,y_test))
    
    
    if __name__=="__main__":
        #choisecsv() #选取部分数据创建一个新表并保存
        demoknn() #knn实例
    
    '''结果(可以看到此次准确率很低):
    预测的位置为: [1097200869 4423196276 4932578245 ... 3312463746 1479000473 1097200869]
    准确率为: 0.027659574468085105
    '''
    

    6.2提升预测准确率1:进行特征工程处理(标准化)

    接上例代码,在第5步加上(特征工程——标准化)处理后再预测,可以看到准确率一下由上例的2.7%,一下提升到41.3%

        #【5】特征工程(标准化)对测试集、训练集的特征值进行,标准化
        std=StandardScaler()
        x_train=std.fit_transform(x_train)
        x_test=std.fit_transform(x_test)
    
    '''结果:
    预测的位置为: [3312463746 7803770431 2327054745 ... 1602053545 5270522918 1267801529]
    准确率为: 0.4134751773049645
    '''
    

    6.3 提升预测准确率2:删除无关特征

    排查发现row_id这列和预测数据结果无关,会对结果造成影响,因此删除
    此时发现准确率由:41%变47%
    关键代码:

        # (2.1)此处打印发现row_id这列特征值与预测没有相关性,会影响模型预测结果;因此把它删除:训练特征集、测试特征集都要删除
        data=data.drop(['row_id'],axis=1)
    

    源码如下:

    import pandas as pd
    from sklearn.model_selection import train_test_split  #数据集分割成:测试集、训练集模块
    from sklearn.neighbors import KNeighborsClassifier #knn近邻算法模块
    from sklearn.preprocessing import StandardScaler #特征工程 标准化 模块
    
    def choisecsv():
        """
        选取一部分数据保存为新表格
        :return:
        """
        # 【1】读取数据
        path = "D:\a\data\facebook-v-predicting-check-ins\train.csv"
        data = pd.read_csv(path)
        # print(data.head(10))
    
        # 【2】因为数据集太大,只选取一部分数据,保存一个新表格
        data = data.query("x > 1.0 &  x < 1.25 & y > 2.5 & y < 2.75")
        print(data.head(10))
        data.to_csv('train_s.csv',index=False) #第2参数,不要在新csv里最前列自动加索引
    
    def demoknn():
        """
        根据输入坐标,预测入住地点
        :return:
        """
        data=pd.read_csv("train_s.csv")
    
        #【1】时间戳处理:转化时间列的时间戳为时间
        time_value=pd.to_datetime(data['time'],unit='s')
        #print(time_value)
        #(1.1)把日期转化为字典格式
        time_value=pd.DatetimeIndex(time_value)
    
        # (1.2)根据时间字典构造一些新特征:月,天,时,星期几
        data['mouth']=time_value.month
        data['day'] = time_value.day
        data['hour'] = time_value.hour
        data['weekday'] = time_value.weekday
    
        #(1.3)删除时间戳列。pd里0是行,1是列
        data=data.drop(['time'],axis=1)
        #print(data.head(10))
    
    
        #【2】删除入驻数量少于3次的地方
        place_count=data.groupby('place_id').count() #数出一共有多少个地方
        tf = place_count[place_count.row_id > 3].reset_index() #入住次数>3个的拿出来,place_id放到最后做为一个特征,前面加一个新索引列0-n
        data = data[data['place_id'].isin(tf.place_id)]  #原表的place_id,存在上一步新建的表里的,单独拿出来做为新数据
        #print(data.sample(10))
    
        # (2.1)此处打印发现row_id这列特征值与预测没有相关性,会影响模型预测结果;因此把它删除:训练特征集、测试特征集都要删除
        data=data.drop(['row_id'],axis=1)
    
    
        #【3】取得特征值x、目标值y
        y=data['place_id']
        x=data.drop('place_id',axis=1)
    
        #【4】分割数据集
        x_train,x_test,y_train,y_test=train_test_split(x,y,test_size=0.25)
        # print(x_train)
    
        #【5】特征工程(标准化)对测试集、训练集的特征值进行,标准化
        std=StandardScaler()
        x_train=std.fit_transform(x_train)
        x_test=std.fit_transform(x_test)
    
        #【6】执行Knn算法
        knn=KNeighborsClassifier(n_neighbors=5)
    
        #【7】fit(处理),执行算法(到此模型已训练完成)
        knn.fit(x_train,y_train)
    
        #【8】预测结果predict(输入测试集进行预测)
        y_predict=knn.predict(x_test)
        print('预测的位置为:',y_predict)
    
        #【9】算出准确率scroe(对模型进行测试集的预测,的准确率计算):
        print('准确率为:',knn.score(x_test,y_test))
    
    
    if __name__=="__main__":
        #choisecsv() #选取部分数据创建一个新表并保存
        demoknn() #knn实例
    '''结果
    预测的位置为: [7803770431 1097200869 3533177779 ... 4932578245 5606572086 1097200869]
    准确率为: 0.4761229314420804
    '''
    

    6.4提升预测准确率3:K值调整等

    1.调整k值关键代码:

    1、k值取多大?有什么影响?

    • k值取很小:容易受异常点影响
    • k值取很大:容易受最近数据太多导致比例变化

    2、性能影响:k近邻每个都要进行数值运算,当数据非常多时,非常耗时

        #【6】执行Knn算法
        knn=KNeighborsClassifier(n_neighbors=6)
    '''结果:经多次调试发现
    k值调整成6预测准确率最高变为:
    48%
    '''
    

    七、K近邻总结

    k-近邻算法步骤

    1. 导入相关模块
    2. 对数据进行初步处理(处理时间戳成新特征、删除无关特征)
    3. 对数据进行划分:分成训练集、测试集
    4. 进行特征工程处理:一般用标准化
    5. 进行knn算法
    import pandas as pd
    from sklearn.model_selection import train_test_split  #数据集分割成:测试集、训练集模块
    from sklearn.preprocessing import StandardScaler #特征工程 标准化 模块
    from sklearn.neighbors import KNeighborsClassifier #knn近邻算法模块
    
    详情见上一节代码……
    

    k-近邻算法优缺点

    优点:

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

    缺点:

    • 懒惰算法,对测试样本分类时的计算量大,内存开销大
    • 必须指定K值,K值选择不当则分类精度不能保证
    • 使用场景:小数据场景,几千~几万样本,具体场景具体业务去测试
  • 相关阅读:
    MongoDB学习笔记(五) MongoDB文件存取操作(转)
    MongoDB学习笔记(四) 用MongoDB的文档结构描述数据关系(转)
    Log4net配置相关
    UML 依赖 关联 聚合 组合
    亲属称谓
    Unity预定义程序集及自定义包编译顺序
    For Windows Phone8 phones make sure that the Windows Phone IP Over USB Transport(IpOverUsbSvc) service is running
    提升Entityframework效率的几种方法
    将RDLC报表工具栏中的英文改为中文
    C#函数式程序设计初探——基础理论篇
  • 原文地址:https://www.cnblogs.com/chenxi188/p/11961962.html
Copyright © 2020-2023  润新知