scikit_learn分类器详解
1 分类
分类是将事物按特性进行分类,例如将手写数字图片分类为对应的数字。
1.1 MINIST数字图片集分类
MINST就是一个70000张规格较小的手写数字图片,如何将他们分类为对应的数字?MINIST这个数据集是由矩阵数组结构,70000个矩阵,每个矩阵28*28=784,每个点代表一个像素值,取值范围在0-256之间。
(1)获取数据集
Scikit-Learn 提供了许多辅助函数,以便于下载流行的数据集。
from sklearn.datasets import fetch_mldata
>>> mnist = fetch_mldata('MNIST original')#获取数字数据集
>>> mnist {'COL_NAMES': ['label', 'data'], 'DESCR': 'mldata.org dataset: mnist-original', 'data': array([[0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0], ..., [0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0], [0, 0, 0, ..., 0, 0, 0]], dtype=uint8), 'target': array([ 0., 0., 0., ..., 9., 9., 9.])}
data是数据集,target是目标数字,也就是每个图片矩阵代表的真实数字。
(2)获取其中一个图片数据转换后画图显示
x, y = mnist["data"], mnist["target"] #获取数据集中的数据
%matplotlib inline#声明使用jupyter的后端渲染图片
import matplotlib import matplotlib.pyplot as plt #引入画图
some_digit = X[36000] #取第36000个数据,是一个784的长形数组
some_digit_image = some_digit.reshape(28, 28) #转换为28*28的矩阵
plt.imshow(some_digit_image, cmap = matplotlib.cm.binary, interpolation="nearest") plt.axis("off") plt.show()#画出矩阵图片显示数字
(3)准备数据训练
分成了一个训练集(前 60000 张图片)和一个测试集(最后 10000 张图片),冒号在前表示取前60000之前的数据,冒号在后表示取60000之后的数据。
X_train, X_test, y_train, y_test = X[:60000], X[60000:], y[:60000],y[60000:]
打乱训练集,洗牌,避免不均匀分布。
import numpy as np
shuffle_index = np.random.permutation(60000) X_train, y_train = X_train[shuffle_index], y_train[shuffle_index]
1.2 二分类器训练
二分类器就是是和否的分类,比较简单。
(1)首先获取训练集和测试集中的为5的数据子集
y_train_5 = (y_train == 5) # True for all 5s, False for all other
digits. y_test_5 = (y_test == 5)
(2)用Scikit-Learn 的 SGDClassifier分类器去训练。这个分类器能够高效地处理非常大的数据 集。可以一次只处理一条数据,适合在线学习。
from sklearn.linear_model import SGDClassifier #引入
sgd_clf = SGDClassifier(random_state=42) #创建分类器对象
sgd_clf.fit(X_train, y_train_5)#训练
sgd_clf.predict([some_digit]) #测试
array([ True], dtype=bool)#测试结果正确
1.3 性能评估
1.3.1 使用交叉验证评估性能
让我们使用 cross_val_score() 函数来评估 SGDClassifier 模型,同时使用K折交叉验证,此 处让 k=3 。即两组训练,一组测试,共测试三轮。
from sklearn.model_selection import cross_val_score
cross_val_score(sgd_clf, X_train, y_train_5, cv=3, scoring="accuracy")
array([ 0.9502 , 0.96565, 0.96495]
1.3.2 混淆矩阵
(1)混淆矩阵的定义
混淆矩阵是指列举出判断错误和判断正确的次数的矩阵。例如上面的二分器,判断为非5的正确的和错误,已经判断为5的正确的和错误的。得到一个2*2的矩阵。为了计算混淆矩阵,首先你需要有一系列的预测值,这样才能将预测值与真实值做比较。
(2)获取预测值
from sklearn.model_selection import cross_val_predict y_train_pred = cross_val_predict(sgd_clf, X_train, y_train_5, cv=3)
cross_val_predict() 也使用 K折交叉验证。返回基于每一个测试折做出的一个预测值。
(3)根据预测值和实际值生成混淆矩阵
在使用 confusion_matrix() 函数,你将会得到一个混淆矩阵。传递目标类(y_train_5)和预 测类( y_train_pred )给它。
>>> from sklearn.metrics import confusion_matrix
>>> confusion_matrix(y_train_5, y_train_pred)
array([[53272, 1307],
[ 1077, 4344]])
53272表示判断为正确的非5(true negative),1307表示判断为错误的非5(false negative)。1077表示判断为错误的5(false positive),4344表示判断为正确的5(true positive)。
(4)准确率和召回率定义
准确率(precision):true positive/( true positive+ false positive)=4344/(1077+4344)
召回率(recall):也叫做敏 感度(sensitivity)或者真正例率(true positive rate, TPR)
recall=ture positive/(true postive+false negative)=4344/(4344+1307)
(1) 准确率和召回率函数计算
Scikit-Learn 提供了一些函数去计算分类器的指标,包括准确率和召回率。
>>> from sklearn.metrics import precision_score, recall_score
>>> precision_score(y_train_5, y_pred) # == 4344 / (4344 + 1307) 0.76871350203503808
>>> recall_score(y_train_5, y_train_pred) # == 4344 / (4344 + 1077) 0.79136690647482011
(2) 调和平均值F1
常结合准确率和召回率来综合的判断算法的准确性。还需要综合实际应用场景,综合考虑采用哪种作为准确性的判断的需要。当准确性和召回率都高的时候,调和平均值才会高。
1.3.3 准确性和召回率的折中
(1)准确性和召回率不能同时提升?
通常情况下提高准确性会降低召回率,反之亦然,即他们是互斥的。为什么准确性和召回率不能同时提升?按照公式将false positive和false negative值都减小不就可以同时提高准确性和召回率,理想情况下,false positive和false negative都为0,准确性和召回率都为100%,为什么不能同时提高呢?
precision=true positive/( true positive+ false positive)=4344/(1077+4344)
recall=ture positive/(true postive+false negative)=4344/(4344+1307)
(2)原因分析
如下图所示, SGDClassifier分类器会对分析的数据进行评分,然后按照分数从小到大排列,设定一个阈值,大于阈值时判定为positive,小于阈值判定为negative。阈值越大准确性越高,但是同时有些是5的数据被判定到negative中,变成false negative,虽然准确性达到100%,但是false negative的数量也增加了,召回率变成50%。
(3)获取单个数据评分值
Scikit-Learn 不让你直接设置阈值,但是它给你提供了获取决策分数的方法decision_function()。这个方法返回每一个样例的分数值,你自己设置阈值去预测。
>>>some_digit = X[36000]#取一个数据
>>> y_score = sgd_clf.decision_function([some_digit])#获取这个数据的评分值
>>> y_scores #显示评分值
array([ 161855.74572176])
>>> threshold = 0 #设置阈值为0
>>> y_some_digit_pred=(y_scores>threshold) #布尔值赋值显示y_score大于0所以为true
array([ True], dtype=bool)
>>> threshold = 200000#重新设置阈值200000
>>> y_some_digit_pred =(y_score >threshold) # y_score小于阈值
>>> y_some_digit_pred array([False], dtype=bool)#得出false
(1) 获取所有数据的评分值
用cross_val_predict()交叉预测方法,设置method="decision_function",得到的不是预测值,而是得到每一个样例的分数值。
y_scores = cross_val_predict(sgd_clf, X_train, y_train_5, cv=3, method="decision_function")
(5)根据评分调用函数precision_recall_curve计算准确率和召回率
现在有了这些分数值。对于任何可能的阈值,使用 precision_recall_curve() ,你都可以计算 准确率和召回率:
from sklearn.metrics import precision_recall_curve
precisions, recalls, thresholds = precision_recall_curve(y_train_5, y_scores)
(6)定义画图函数画出准确率和召回率相对于不同阈值的曲线
def plot_precision_recall_vs_threshold(precisions, recalls, thresholds): plt.plot(thresholds, precisions[:-1], "b--", label="Precision") plt.plot(thresholds, recalls[:-1], "g-", label="Recall") plt.xlabel("Threshold")
plt.legend(loc="upper left")
plt.ylim([0, 1])
plot_precision_recall_vs_threshold(precisions, recalls, thresholds) plt.show()
你可以画出准确率和召回率的曲线图,在曲线图上根据实际项目应用确定准确率和召回率。
1.3.4 ROC曲线
(1)定义
ROC(Receiver Operating Characteristic)曲线是横坐标为假正率,纵坐标为真正率的曲线图。假正率是指判为真的当中假的数量,站总的假的数量的比值。真正率是指判为真的当中真的数量占总的真的数量的比值,和召回率意义一样。还用之前的例子,如下图所示,共有12个数字,其中6个是真5,其他6个是假5。左一位置处,真正率为6/6=100%,假正率为2/6的33.33%。中间位置,真正率为4/6=66.66%,假正率为1/6=16.67%。右侧位置处,真正率为3/6=50%,假正率为0/6=0%。
(2) 曲线下方面积比较分类器性能
roc曲线下面的面积越大,或roc曲线越靠左上角,性能越好,测量ROC曲线下的面积(AUC)评估分类器的好坏。Scikit-Learn 提供了一个函 数来计算 ROC AUC:
>>> from sklearn.metrics import roc_auc_score
>>> roc_auc_score(y_train_5, y_scores)
0.97061072797174941
(3)画出曲线图比较性能
也可以画出两个分类器的ROC曲线,看谁更接近左上角。
1)计算SGDClassifier分类器
为了画出 ROC 曲线,你首先需要计算各种不同阈值下的 TPR、FPR,使用 roc_curve() 函 数:
from sklearn.metrics import roc_curve
fpr, tpr, thresholds = roc_curve(y_train_5, y_scores)
2)计算RandomForestClassifier的TPR和FPR
RandomForestClassifier 不提供 decision_function() 方法。相反,它提供 predict_proba()方法,返回一个数组,每一行代表一个数字记录,每一列代表所属于的类别,数组中数值含义是这一行这个数是这一列这个类的概率。例如数字判断中,每一列是“是5”和“非5”,每一行是一个图片记录,数组中的值是图片“是5”和“非5”的概率,把这个概率值作为评分值。
from sklearn.ensemble import RandomForestClassifier
forest_clf = RandomForestClassifier(random_state=42)
y_probas_forest = cross_val_predict(forest_clf, X_train, y_train_5, cv=3,method="predict_proba")
y_scores_forest = y_probas_forest[:, 1] # 是5的概率值作为评分
fpr_forest, tpr_forest, thresholds_forest = roc_curve(y_train_5,y_scores_forest)
3)画出曲线图
plt.plot(fpr, tpr, "b:", label="SGD") #SGD的ROC曲线图
plot_roc_curve(fpr_forest, tpr_forest, "Random Forest") #随机森林的ROC
plt.legend(loc="bottom right")
plt.show()
如你所见, RandomForestClassifier 的 ROC 曲线比 SGDClassifier 的好得多:它更靠近左上 角。所以,它的 ROC AUC 也会更大。
>>> roc_auc_score(y_train_5, y_scores_forest)
0.99312433660038291
1.4 多分类器
1.4.1 定义
二分类器只能区分两个类,而多类分类器(也被叫做多项式分类器)可以区分多于两个类。如随机森林分类器或者朴素贝叶斯分类器可以直接处理多类分类。(比如 SVM 分类器或者线性分类器)则是严格的二分类器。
一对所有(ONE VS ALL):例如训练0~9共10个分类器,你想对某张 图片进行分类的时候,让每一个分类器对这个图片进行分类,选出决策分数最高的那个分类 器。
一对1=一(ONE VS ONE)0,1之间,0,2之间……,共N(N-1)/2分类器,当你想对一张图片进行分类,你必须将这张图片跑在全部45个二分类器上。然后 看哪个类胜出。
1.4.2 SGDClassifier实现多分类
>>> sgd_clf.fit(X_train, y_train) # 训练
>>> sgd_clf.predict([some_digit])#预测输出是 array([ 5.])
>>> some_digit_scores = sgd_clf.decision_function([some_digit]) >>> some_digit_scores array([[-311402.62954431, -363517.28355739, -446449.5306454 , -183226.61023518, -414337.15339485, 161855.74572176, -452576.39616343, -471957.14962573, -518542.33997148, -536774.63961222]])#获取评分
>>> np.argmax(some_digit_scores) #输出评分最大的结果是5
1.4.3 OneVsOneClassifier 类 或者OneVsRestClassifier类
>>> from sklearn.multiclass import OneVsOneClassifier
>>> ovo_clf = OneVsOneClassifier(SGDClassifier(random_state=42)) >>> ovo_clf.fit(X_train, y_train)
>>> ovo_clf.predict([some_digit])
array([ 5.])
>>> len(ovo_clf.estimators_) 45
1.4.4 RandomForestClassifier多分类
随机森林分类器能够直接将一个样例 分到多个类别。你可以调用 predict_proba() ,得到样例对应的类别的概率值的列表。
>>> forest_clf.fit(X_train, y_train)
>>> forest_clf.predict([some_digit])
array([ 5.])
>>> forest_clf.predict_proba([some_digit]) array([[ 0.1, 0. , 0. , 0.1, 0. , 0.8, 0. , 0. , 0. , 0. ]])
1.5 误差分析
探索方案,尝试多种模型,选择最好的模型,用GridSearchCV调试超参数优化模型。要使用 cross_val_predict() 做出预测,然后调 用 confusion_matrix()函数。
>>> y_train_pred = cross_val_predict(sgd_clf, X_train_scaled, y_train, cv=3)
>>> conf_mx = confusion_matrix(y_train, y_train_pred) >>> conf_mx array([[5725, 3, 24, 9, 10, 49, 50, 10, 39, 4], [ 2, 6493, 43, 25, 7, 40, 5, 10, 109, 8], [ 51, 41, 5321, 104, 89, 26, 87, 60, 166, 13], [ 47, 46, 141, 5342, 1, 231, 40, 50, 141, 92], [ 19, 29, 41, 10, 5366, 9, 56, 37, 86, 189], [ 73, 45, 36, 193, 64, 4582, 111, 30, 193, 94], [ 29, 34, 44, 2, 42, 85, 5627, 10, 45, 0], [ 25, 24, 74, 32, 54, 12, 6, 5787, 15, 236], [ 52, 161, 73, 156, 10, 163, 61, 25, 5027, 123], [ 43, 35, 26, 92, 178, 28, 2, 223, 82, 5240]])
Matplotlib 的 matshow() 函数,将混淆矩阵以图像的方式呈现,将会更 加方便。
plt.matshow(conf_mx, cmap=plt.cm.gray)
plt.show()
主对角线上意味着被分类 正确。数字 5 对应的格子看起来比其他数字要暗淡许多。数据集当中数字 5 的图片 比较少,又或者是分类器对于数字 5的表现不如其他数字那么好。
将混淆矩阵的每一个值除以相应类别的 图片的总数目。这样子,你可以比较错误率,而不是绝对的错误数(这对大的类别不公平)。用 0 来填充对角线正确的分类。最后得到的就是错误率的矩阵和图像。
row_sums = conf_mx.sum(axis=1, keepdims=True)
norm_conf_mx = conf_mx / row_sums
np.fill_diagonal(norm_conf_mx, 0)
plt.matshow(norm_conf_mx, cmap=plt.cm.gray)
plt.show()
第 8、9 列相当亮,这告诉你许多图片被误分成数字 8 或者数字 9,第一行很暗,这意味着大部分的数字 1 被正确分类。分析混淆矩阵通常可以给你提供深刻的见解去改善你的分类器。回顾这幅图,看样子你应该 努力改善分类器在数字 8 和数字 9 上的表现,和纠正 3/5 的混淆
1.6 多标签分类KNeighborsClassifier
(1)分类实现
让你的分类器给 一个样例输出多个类别。例如一个人脸识别分类器,这个分类 器被训练成识别三个人脸,Alice,Bob,Charlie;然后当它被输入一张含有 Alice 和 Bob 的 图片,它应该输出 [1, 0, 1] 。(意思是:Alice 是,Bob 不是,Charlie 是)。这种输出多个二 值标签的分类系统被叫做多标签分类系统。例如要对数字进行分类,两个要求(1)大于等于7;(2)是奇数。
from sklearn.neighbors import KNeighborsClassifier #引入分类器
y_train_large = (y_train >= 7)#大于7的目标值
y_train_odd = (y_train % 2 == 1) #是奇数的目标值
y_multilabel = np.c_[y_train_large, y_train_odd] #组合两种分类值
knn_clf = KNeighborsClassifier()#创建分类器对象
knn_clf.fit(X_train, y_multilabel)#进行分类训练
>>> knn_clf.predict([some_digit]) #输出5的预测值
array([[False, True]], dtype=bool)#结果为小于7,是奇数
(2)F1值评估分类器
y_train_knn_pred = cross_val_predict(knn_clf, X_train, y_train, cv=3)
>>> f1_score(y_train, y_train_knn_pred, average="macro") #平均
0.96845540180280221
,如果你的 Alice 的照片比 Bob 或者 Charlie 更多的时候,也许你想让分类器在 Alice 的照片上具有更大的权重。设置 average="weighted" 。
1.7 多输出分类
是多标签分类的简单泛化,在这里每一个标签可以是多类别的(比如说,它可以有多于两个可能值)。例如去除噪音的系统,输入是含有噪音的图片,输出是一个干净的数字图片,由像素强度数组表示,一个像素是一个标签,每个标签的取值是 0~255。标签的取值多范围就是多输出分类。
我们先给训练数据加上噪音,然后再进行降噪处理。
noise = rnd.randint(0, 100, (len(X_train), 784)) #制造噪音
noise = rnd.randint(0, 100, (len(X_test), 784))
X_train_mod = X_train + noise #加上噪音
X_test_mod = X_test + noise
y_train_mod = X_train
y_test_mod = X_test
knn_clf.fit(X_train_mod, y_train_mod) #训练KNeighborsClassifier分类器
clean_digit = knn_clf.predict([X_test_mod[some_index]]) #输出降噪预测值
plot_digit(clean_digit)
自己开发了一个股票智能分析软件,功能很强大,需要的点击下面的链接获取:
https://www.cnblogs.com/bclshuai/p/11380657.html
scikit_learn分类器详解的更多相关文章
- scikit_learn lasso详解
Lasso 回归 l1 正则化 The Lasso 是估计稀疏系数的线性模型. 它在一些情况下是有用的,因为它倾向于使用具有较少参数值的情况,有效地减少给定解决方案所依赖变量的数量. 因此,Lasso ...
- 机器学习经典算法详解及Python实现--基于SMO的SVM分类器
原文:http://blog.csdn.net/suipingsp/article/details/41645779 支持向量机基本上是最好的有监督学习算法,因其英文名为support vector ...
- 史上最全的maven的pom.xml文件详解
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/20 ...
- Maven-pom.xml详解
(看的比较累,可以直接看最后面有针对整个pom.xml的注解) pom的作用 pom作为项目对象模型.通过xml表示maven项目,使用pom.xml来实现.主要描述了项目:包括配置文件:开发者需要遵 ...
- 史上最全的maven pom.xml文件教程详解
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/20 ...
- 【maven】 pom.xml详解
pom.xml详解 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www ...
- 学习笔记——Maven pom.xml配置详解
POM的全称是“ProjectObjectModel(项目对象模型)”. pom.xml详解 声明规范 <projectxmlns="http://maven.apache.org/P ...
- Maven使用笔记(四)pom.xml配置详解
pom.xml文件配置详解 --声明规范 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi=" ...
- mvn详解
1.前言 Maven,发音是[`meivin],"专家"的意思.它是一个很好的项目管理工具,很早就进入了我的必备工具行列,但是这次为了把project1项目完全迁移并应用maven ...
随机推荐
- 三个值得期待的JavaScript新功能!
让我们来看看JavaScript中一些有用的即将推出的功能.您将看到他们的语法,链接以及时了解他们的进度,我们将编写一个小型测试套件,以展示如何立即开始使用这些提案! JavaScript是如何更新迭 ...
- 前端开发--nginx篇
安装和启动 Mac上搭建nginx教程 通过Homebrew 安装nginx brew install nginx 配置 添加配置文件在 /usr/local/etc/nginx/servers 目录 ...
- 进阶之路 | 奇妙的Thread之旅
前言 本文已经收录到我的Github个人博客,欢迎大佬们光临寒舍: 我的GIthub博客 需要已经具备的知识: Thread的基本概念及使用 AsyncTask的基本概念及使用 学习清单: 线程概述 ...
- MapReduce 简单数据统计
1. 准备数据源 摘录了一片散文,保存格式为utf-8 2. 准备环境 2.1 搭建伪分布式环境 https://www.cnblogs.com/cjq10029/p/12336446.html 上传 ...
- Head First设计模式——生成器和责任链模式
生成器 生成器模式:封装一个产品的构造过程,并允许按步骤构造. 现又一个度假计划指定,需要指定度假每一天的活动.旅馆.用餐.门票等等事情,但是每个客人的度假计划可能不太一样.例如天数.活动类型.用餐等 ...
- utuntu sever1804显示中文putty可以输入中文
默认情况下,putty连接ubuntu server以后,哪怕设置的Utf-8的连接,也是无法显示中文的. 应该是ubuntu服务器端,没有字库的问题. 如果在putty显示和输入中文呢,因为配置信息 ...
- 这些MongoDB的隐藏操作你真的都掌握了吗?反正我是刚知道
背景 最近公司系统还原用户时偶尔会出现部分用户信息未还原成功的问题,最为开发人员,最头疼的不是代码存在bug,而是测试发现了bug,但一旦我去重现,它就不见了.Are you kidding me? ...
- (转)协议森林04 地址耗尽危机 (IPv4与IPv6地址)
协议森林04 地址耗尽危机 (IPv4与IPv6地址) 作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! IP地址是IP协议的重要组 ...
- StormDRPC流程解读
Storm 的编程模型是一个有向无环图,模型角度决定了 Storm 的 Spout 接收到外部系统的请求,将请求数据分发给下游的 bolt 进行处理后,spout 并不能得到 bolt 的处理结果并将 ...
- .net 4.0 以下HttpWebRequest Header 修改hosts方法
.net 4.0 以下HttpWebRequest Header 修改hosts方法 特此记录 public class CusteredHeaderCollection : WebHeaderCol ...