蜗牛慢爬的李成广 2019-11-30
【定义】如果一个样本在特征空间中的k个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类别。
两个样本的距离可以通过如下公式计算,又叫【欧式距离】
设有特征,a(a1,a2,a3),b(b1,b2,b3),那么:
\[\sqrt{(a1-b1)^{2}+(a2-b2)^{2}+(a3-b3)^{2}}\]
sklearn.neighbors.KNeighborsClassifier(n_neighbors=5,algorithm='auto')
数据位置: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)]
数据集示例(trian.csv):
此处分为两步:
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 '''
接上例代码,在第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 '''
排查发现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 '''
1、k值取多大?有什么影响?
2、性能影响:k近邻每个都要进行数值运算,当数据非常多时,非常耗时
#【6】执行Knn算法 knn=KNeighborsClassifier(n_neighbors=6) '''结果:经多次调试发现 k值调整成6预测准确率最高变为: 48% '''
import pandas as pd from sklearn.model_selection import train_test_split #数据集分割成:测试集、训练集模块 from sklearn.preprocessing import StandardScaler #特征工程 标准化 模块 from sklearn.neighbors import KNeighborsClassifier #knn近邻算法模块 详情见上一节代码……
优点:
缺点: