KNN优化之调参

上篇博客 我们留下了三个问题:数据集,参数,准确率。这些问题我们将在这篇博客解决!


数据集

这里介绍一个很有意思的开源数据集——scikit-learn ,熟悉了这个数据集我们就可以拿来检验我们自己的写分类器的合理性,当然包括我们今天的主题——KNN,我将使用其中的两个经典的数据集——iris(鸢尾花)和digits(手写数字),来验证上篇博客所写的knn是否符合期望!话不多说,直接上代码,以鸢尾花为例:

from sklearn import datasets
iris = datasets.load_iris()  #鸢尾花
X = iris.data  # 数据
y = iris.target  # 标签

scikit-learn将这些数据集封装了起来,我们来看下它们的格式

print(iris.keys())

截图

这样就拿到了训练数据集和对应的标签,接下来开始验证我们自己写的KNN的准确率!

说明: 1.这里我们只需要知道data和target属性分别是训练数据集和对应的标签,其他属性就不多赘述,感兴趣的话读者可以自行了解
2.我们以iris数据集为例,digits同理,所以对于digits我们只给出结果!


准确率

我们开始操作上一步拿到的iris数据集,首先将数据集分割成train set 和test set,并在test set上求knn的准确率,如果准确率很高,那说明我们的KNN表现的很好!对于准确率如何求?我想,稍微有点数学基础的朋友已经想到了:拿预测的出来的标签和test set的标签一对比,正确的标签数 / 总标签数 = 准确率

至于如何将数据集分割成train set 和test set,有很多方式,我们先用最简单的方式——按比例分,一般来说train set分的多些,比如我用前20%做test set,用后80%做train set,知道了怎么分之后,我们还要知道这样分是否合理,拿iris数据集来说,我们print一下target,结果是这样的:
截图
我们可以看到,它的标签是有按特殊规律排列的,如果按比例分割,显然会导致test set和train set特殊化,无法做到一般性,所以我要用numpy的一个方法,将target的下标随机排列,这样再分割,便符合我们的要求,代码如下:

shuffled_indexes = np.random.permutation(len(X))   # 随机打乱数据集的下标顺序

test_ratio = 0.2
test_size = int(len(X) * test_ratio)             #分割点
# 将数据集2-8分,前20%是test集,后80%是训练集
test_indexes = shuffled_indexes[:test_size]      #取前20%的下标
train_indexes = shuffled_indexes[test_size:]     #取后80%的下标

X_train = X[train_indexes]      #train set
y_train = y[train_indexes]      #对应的标签

X_test = X[test_indexes]        #test set
y_test = y[test_indexes]        #对应的标签

分割之后便可以送到我们事先封装好的的方法里,计算准确率了:

X_train, y_train, X_test, y_test = data_split(X, y)
y_predict = knn_predict(X_test, X_train, y_train, 6)
print("y_predict : ", y_predict)
print("y_test :    ", y_test)
print(sum(y_predict == y_test) / len(y_test))

来看下结果,准确率为:
截图
我试着多运行了几次发现准确率基本是在96%以上,当然也出现了正确率为1的情况(由于np.random.permutation,所以每次运行可能得到不同的train set和test set),这也就证实了我们写的KNN分类是符合期望的,如果再得到新iris数据,我们便可以用我们的KNN高效地预测出对应的标签:
截图
再附一张digits的试验结果:
这里写图片描述


调参

调参事件很有趣的事情!好的参数会让你的模型最大化得发挥其功效,回到KNN,首先对于参数k来说,在毫无经验的情况下,该如何设置这个k呢?我们这样做:

best_score = 0.0
best_k = 0
for k in range(1, 10):
    y_predict = knn_predict(X_test, X_train, y_train, k)
    score = sum(y_predict == y_test) / len(y_test)
    if score > best_score:
        best_score = score
        best_k = k
print("best score is: ", best_score)
print("best k is: ", best_k)

截图
打印结果我们发现,当k=5的时候,模型性能(准确率)达到最优,这个时候我们就可以将我们k设为5(而之前,按经验我们设置k=6,这其中的差别其实并不大,这也就告诉我们,一个具有良好经验的机器学习学者,在调参的时候“经验”会让你达到事半功倍的奇效,使你的工作效率大大提高
回顾下上篇博客 总结中我们提到的,当k=3时距离权重的问题,这便是KNN的另一个比较重要超参数,详情请见KNeighborsClassifier 具体如何将其写到代码里,我将会在下篇博客介绍scikit-learn为用户封装的KNN分类器时候提及,请参见scikit-learn中的KNeighborsClassifier
这里写图片描述


总结

为了更深入地理解KNN原理,我们从底层逐步完成了其代码编写,并使用scikit-learn公开数据集测试了模型的性能,我们的模型表现优良。事实上在实际应用中,为了提高工作效率,有很多方便的框架已经将我们想要使用的模型封装好供我们使用,大部分情况我们只需要import就可以,即所谓的“调包”,并不需要我们自己从开始逐步写模型的代码。但是为了更加深入地理解各类模型的含义及原理,我将以Python语言为基础,尝试从底层逐步完成常用机器学习算法模型的构建,尝试熟练使用常用的库,如numpy,matplotlib,scikit-learn,TensorFlow等来构建算法模型,底层编码与“调包”相结合,对比着学习,我想这样会有趣很多,并将在博客中记录自己的学习过程,这是我接下来几个月要做的工作。由于本人初入机器学习领域,刚开始整理自己的学习笔记,博客中可能会有表述不清,或表述有误的地方,还请各位读者批评指正,欢迎可以在博客下方指出!最后附上我的GitHub地址 ,博客中涉及的所有代码都在这里,会随学习进度持续更新,愿与各位朋友交流,有任何相关问题欢迎在下方留言!

  • 5
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值