zoukankan      html  css  js  c++  java
  • 《机学五》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值选择不当则分类精度不能保证
    • 使用场景:小数据场景,几千~几万样本,具体场景具体业务去测试
  • 相关阅读:
    Codeforces 834D The Bakery
    hdu 1394 Minimum Inversion Number
    Codeforces 837E Vasya's Function
    Codeforces 837D Round Subset
    Codeforces 825E Minimal Labels
    Codeforces 437D The Child and Zoo
    Codeforces 822D My pretty girl Noora
    Codeforces 799D Field expansion
    Codeforces 438D The Child and Sequence
    Codeforces Round #427 (Div. 2) Problem D Palindromic characteristics (Codeforces 835D)
  • 原文地址:https://www.cnblogs.com/chenxi188/p/11961962.html
Copyright © 2011-2022 走看看