机器学习系统设计笔记4--KNN和逻辑回归
条评论最近看完了 Willi Richert的《机器学习系统设计》。书虽然有点薄但也比较全,内容感觉有点偏文本处理,里面介绍了一些文本处理的方法和工具。综合起来看作为机器学习入门还是挺不错的,这里就简单记一下我做的笔记,方便回顾。书中的代码可以通过它说到的网站下载,这里是第4部分笔记。
第五章 KNN和逻辑回归
这一章给出的想法非常有意思,要做一个问答网站检测答案质量的分类器,它能够持续的判断用户的答案是否有劣质答案的迹象,从而引导用户提高答案的质量。
数据集
然而我并没有下载下来stackoverflow的数据,在书中给出的链接已经失效,书中给出的代码里面并没有提供下载数据的脚本,但我从网上找到了stackoverflow的数据的一个http://blog.stackoverflow.com/tags/cc-wiki-dump/ 这个网站里有关于stackoverflow exchange的一些内容,需要翻墙才能下载。
KNN方法
KNN的方法不是一种基于模型的方法,所以几乎可以学习任何数据。
特征抽取:由于分类器接受的必须是数值形式,所以必须对原始数据进行处理,这里文中的方法是检测一个答案的HTML链接数,数值越高越好。可以手写检测,也可以用工具,如BeautifulSoap解析HTML。除了链接数,代码的行数也是一个较好的选择,他标志着作者花费的时间可能会比较多。统计一下删除代码后的词语的数量也可以作为一个不错的特征。我们还统计了句子的平均词语个数,平均字符个数,大写形式的词语个数以及感叹号的个数。把这7个特征都交给KNN来进行分类,代码的形式类似下面这样:
1 | knn = neighbors.KNeighborsClassifier() |
经过测试发现,KNN的效果并不好,正确率在50%左右,而且KNN的方法带来的明显的问题,一是导致了较低的实时分类性能,二是随着时间的增加,进入系统的帖子会越来越多。KNN方法必须在系统中存储所有的帖子,而我们得到的帖子越多,预测性能会越慢。这跟基于模型的方法是不同的,在那里我们会从数据中得到一个模型。我们怎么提升机器学习的效果呢?
调整性能的方法
提升效果,基本上有如下的选择:
增加更多的数据 也许我们并没有为学习算法提供足够的数据,因此增加更多的训练数据即可
考虑模型复杂度 也许模型还不够复杂,或者夜景太复杂了。在这种情况下,对于KNN,我们可以降低K值,使得较少的近邻被考虑进去,从而更好地预测不平滑的数据。我么也可以提高K值,来得到相反的效果。
修改特征空间 也许我们的特征集合不好。例如,我们可以改变当前特征的范围,或者设计新的特征。又或者,如果有特征和另外一些特征是别名关系,我们还可以删除一些特征。
改变模型 也许KNN并不适合我们的问题。无论我们让模型变得有多复杂,无论特征空间会变得多复杂,它永远也无法得到良好的预测效果。
机器学习中最容易出现的两个问题就是1.高偏差; 2.高方差
高偏差: 测试和训练误差很接近,但都处于难以接受的较大的数值上。 (欠拟合) 此时模型偏离数据太远了;在这种情况下,加入更多的训练数据明显不会有什么帮助,同样,删减特征也没有帮助,模型可能过于简单。往往参数较少的神经网络很容易欠拟合出现高偏差的问题。
解决高偏差的方法:
1.增加更多的特征 2. 让模型更为复杂或者尝试其他模型
高方差: 不同的数据测出来的误差很大,表现为训练误差同测试误差差异大。 (过拟合) 此时模型对于训练数据表现的太好,意味着我们的模型对于训练数据来说太复杂
解决高方差的方法:
在这种情况下,我们只能尝试获得更多数据或者降低模型复杂度。对于KNN来说,增大K使得更多的近邻被考虑进行,或者删掉一些特征。
knn的不足
(1)当不同的类包含的样本数量差异很大时,即有的类包含的样本比其他类样本多很多,有时候输入一个和小容量类同类型的新样本,该样本的k个邻居中大容量类的样本占大多数,从而导致误分类。这种情况可以采用加权的方法,按照样本容量对不同的类分配合适的权值。
(2)分类时需要先计算待分类样本和全体已知样本的距离,计算量大。针对这种情况可以对已知样本点进行剪辑,去除对分类作用不大的样本。
逻辑回归
我们假设一个特征有0.9的概率属于类别1,也就是说,$P(y=1)=0.9$,那么让步比就是$P(y=1)/P(y=0)=0.9/0.1=9$。也就是说,这个特征映射到类别1的机会是9:1.如果$P(y)=0.5$,那么这个样本属于1的机会将是1:1。让步比的范围是(0,+\infty),对他取对数就可以映射到整个实数域。这样的好处就是更高的概率对应于更高的让步比对数。
对于线性等式:
$$y_i=c_0+c_1x_i$$
我们可以用对数的让步比来替换:
$$\log(\dfrac{p_i}{1-p_i})=c_0+c_1x_i$$
我们可以从等式中求解出$p_i$,如下所示:
$$p_i=\dfrac{1}{1+e^{c_0+c_1x_i}}$$
通过找到合适的系数,我们便可以求出对于所有的数据对$(x_i,p_i)$中能给出的最小的误差,这个可以使用scikit-learn来实现。
1 | from sklearn.linear_model import LogisticRegression |
准确率和召回率
准确率表示尽量少的不要分出错误的答案,召回率则表示尽量把所有的正确答案都分出来。
$$准确率=\dfrac{TP}{TP+FP}$$
$$召回率=\dfrac{TP}{TP+FN}$$
sklearn中已经有封装好的准确率和召回率的计算函数:
1 | from sklearn.metrics import precision_recall_curve |
sklearn 中还能以报告的形式输出准确率和召回率的函数
1 | >>> from sklearn.metrics import classification_report |
本文标题:机器学习系统设计笔记4--KNN和逻辑回归
文章作者:throneclay
发布时间:2015-10-17
最后更新:2022-08-03
原始链接:http://blog.throneclay.top/2015/10/17/mldesgin5/
版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC-SA 3.0 CN 许可协议。转载请注明出处!