备注:刷视屏记录一下知识点,以防以后忘记。
分类算法之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