KNN原理:
K最近邻算法(K-Nearest Neighbor),它判断未知类别数据的方法,是根据未知数据最近的K条记录,统计他们的分类,来确定未知类别数据的分类。
如下图所示,正方形和三角形代表两种不同的分类,圆点代表的是未知分类的点。
KNN算法首先会确定一个K值,假设K = 3 ,那么根据其他点与圆点的距离,找出最接近圆点的三个点,三点中,两个属于三角形,一个属于正方形,根据这一结果,KNN算法认为,圆点数以三角形点的分类。
在KNN算法中,参数K的设置会影响模型的效果,K值设置不同,分类结果也会不同,现在通过一个问题来呈现KNN。
问题:
某公司收集华南地区各个商户的ID,注册时长,营业收入,成本,是否续约共五个字段的数据集,现商铺希望根据这份数据,搭建一个可以预测商户是否续约的模型,用于预测其他地区商户是否续约,从而为后续招商工作提供判断依据。
导入数据:
import pandas as pd
data1 = pd.read_csv(
'D:\example_csv\华南地区.csv',encoding = 'ANSI')
data2 = pd.read_csv(
'D:\example_csv\华北地区.csv',encoding = 'ANSI')
部分数据如下所示:
训练集和测试集的划分:
from sklearn.model_selection import train_test_split
x = data1[['注册时长','营收收入','成本']] #特征变量
y = data1[['是否续约']] #目标变量
x_train,x_test,y_train,y_test = train_test_split(x,y,test_size = 0.3)
#把数据集划分为测试集和训练集,测试集样本数量设置为总样本的30%
使用KNN模型:
from sklearn.neighbors import KNeighborsClassifier
knnModel = KNeighborsClassifier(n_neighbors = 3)
#新建一个KNN模型,设置邻居个数为3
knnModel.fit(x_train,y_train)
#使用训练集训练KNN模型
knnModel.score(x_test,y_test)
#使用测试集测试KNN模型
模型得分0.67,还可以接受,这里使用的评估指标是准确率。
计算正确的预测的测试目标列:
y_test_predict = knnModel.predict(x_test)
评估模型除了可以使用准确率,还可以使用精确率,召回率,F1分数等指标,下面将会一一实现。
参数选择:
KNN模型有一个参数n_neighbors,在上面我们设置它为3,在实际场景中,我们需要遍历所有的候选参数,将得分最优秀的参数作为最优参数。
from sklearn.metrics import make_scorer
ks = [] #用来保存KNN模型的邻居个数
accuracy_means = [] #用来保存准确率
precision_means = [] #用来保存精确率
recall_means = [] #用来保存召回率
f1_means = [] #用来保存f1值
使用准确率评估模型:
from sklearn.metrics import accuracy_score
from sklearn.model_selection import cross_val_score
for k in range(2,20):
#n_neighbors 参数,从2到19,一个一个尝试(也可以设置不同的值)
ks.append(k)
#把n_neighbors参数保存起来
knnModel = KNeighborsClassifier(n_neighbors = k)
#改变KNN模型的参数n_neighbors为k
accuracy_cvs = cross_val_score(
knnModel,x,y,cv = 10,
scoring = make_scorer(accuracy_score))
#计算10折交叉验证的准确率
accuracy_means.append(accuracy_cvs.mean())
#将10折交叉验证的准确率保存起来
计算结果如下:
使用精确率评估模型:
from sklearn.metrics import precision_score
precision_csv = cross_val_score(
knnModel,x,y,cv = 10,
scoring = make_scorer(precision_score,pos_label = '续约'))
#计算10折交叉验证的精确率
precision_means.append(precision_csv.mean())
#将10折交叉验证的精确率保存起来
计算结果如下:
使用召回率评估模型:
from sklearn.metrics import recall_score
recall_csv = cross_val_score(
knnModel,x,y,
scoring = make_scorer(recall_score,pos_label = '续约'))
#计算10折交叉验证的召回率
recall_means.append(recall_csv.mean())
#将10折交叉验证的召回率保存起来
计算结果如下:
使用F1分数来评估模型:
from sklearn.metrics import f1_score
f1_csv = cross_val_score(
knnModel,x,y,
scoring = make_scorer(f1_score,pos_label = '续约'))
#计算10折交叉验证的f1分数
f1_means.append(f1_csv.mean())
#将10折交叉验证的f1分数保存起来
计算结果如下:
将计算出的数据列出比较:
scores = pd.DataFrame({
'k':ks,
'accuracy':accuracy_means,
'precision':precision_means,
'recall':recall_means,
'f1':f1_means
})
运行代码:
使用折线图更直观的观察数据变化情况:
scores.plot(x = 'k',
y = ['accuracy','precision','recall','f1'])
运行代码:
从折线图可知,当K值取17时,各项指标都趋于平缓,如果K值继续增加,模型的各项评估指标也不会有太大变化,而在此时,F1分数达到最大值,因此,K值选择17即可。
预测未知数据:
#使用最佳参数n_neighbors = 17 建模
knnModel = KNeighborsClassifier(n_neighbors = 17)
#使用所有训练样本训练模型
knnModel.fit(x,y)
#对未知的目标数据进行预测
data2['预约测试'] = knnModel.predict(
data2[['注册时长','营收收入','成本']])
执行代码,部分数据如下: