机器学习 sklearn K-近邻

备注:刷视屏记录一下知识点,以防以后忘记。

分类算法之k-近邻

核心思想:通过计算不同特征值之间的距离来对数据进行分类。

优点:不需要估计和训练参数(对比神经网络)。

缺点:K值对预测的结果影响大,进行分类时计算量大。

使用场景:小数据场景,数据量大约几千~几万,具体情况需要测试。

举个栗子:已知6部电影的数据,预测最后一部电影的类别。

我们需要计算未知电影与其他电影之间的距离,用到计算公式如下:

计算结果如下:

找出距离最近的K个数据,其中占大多数的类别为预测的类别。例如:K=3时,{20.5,18.7,19.2}与这三个数据最近,这三个数据都属于爱情片,那么其中爱情片占大多数,预测结果属于爱情片,K= 4,5同理。

k-近邻算法案例分析

实验案例选用的kaggle题目:Facebook V: Predicting Check Ins,网站内提供数据,网址如下:

https://www.kaggle.com/c/facebook-v-predicting-check-ins/data

问题:根据已知的数据(x轴,y轴,精确度,时间戳,地点),来预测签到的地点(place_id)。

这里只用了训练集中小部分的数据实验。

代码整体思路:

数据预处理,主要处理时间戳,然后按照地点对数据分组,row_id由指点的序号,变成了地点出现的次数,将出现次数小于3的过滤掉,将数据分割成训练集+测试集,然后标准化(注意只对特征值进行标准化),调用K近邻算法+网格搜索,打印预测准确率和预测结果。

from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.neighbors import KNeighborsClassifier
from sklearn.preprocessing import StandardScaler
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.naive_bayes import MultinomialNB
from sklearn.metrics import classification_report
from sklearn.feature_extraction import DictVectorizer
from sklearn.tree import DecisionTreeClassifier, export_graphviz
from sklearn.ensemble import RandomForestClassifier
import pandas as pd


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

    # print(data.head(10))

    # 处理数据
    # 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')

    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 = data.drop(['time'], axis=1)

    print(data)

    # 把签到数量少于n个目标位置删除
    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']

    x = data.drop(['place_id'], axis=1)

    # 进行数据的分割训练集合测试集
    x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.25)

    # 特征工程(标准化)
    std = StandardScaler()

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

    x_test = std.transform(x_test)

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

    # # 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))

    # 构造一些参数的值进行搜索
    param = {"n_neighbors": [3, 5, 10]}

    # 进行网格搜索
    gc = GridSearchCV(knn, param_grid=param, cv=2)

    gc.fit(x_train, y_train)

    # 预测准确率
    print("在测试集上准确率:", gc.score(x_test, y_test))

    print("在交叉验证当中最好的结果:", gc.best_score_)

    print("选择最好的模型是:", gc.best_estimator_)

    print("每个超参数每次交叉验证的结果:", gc.cv_results_)

    return None

细节说明:

1)使用DataFrame.query(),按照x轴y轴来缩小数据。

2)处理日期数据:这一步将时间戳转换后加入原始数据中,后删除时间戳。pd.todatetime() ,pd.DatatimeIndex()转化为字典格式,处理后的数据如下:

3)按照place_id进行分组,分组后重置索引。

第一次分组后的索引为地点ID,需要重置让地点为一列,两次处理过后的结果如下:

End

猜你喜欢

转载自blog.csdn.net/Rand_C/article/details/85778896