机器学习实战(用Scikit-learn和TensorFlow进行机器学习)(四)
上一节三节讲述了真实数据(csv表格数据)的一个实战操作的总流程,然而这个处理是一个回归模型,即目标是一些连续的值(median_house_value)。当目标是一些有限的离散值得时候(比如数字0-9),就变成了分类问题,下面开始讲述分类问题。
四、分类问题
下面将使用新的具有代表性的数据集MNIST(手写体数字数据集),数据集总共有70000个小图片,每个小图片为一个手写的数字,(数据中0代表白,1代表黑),数据中把28*28个像素拉成一个向量作为特征,写的数字作为label。
1、关于MNIST数据集
Scikit-learn提供了MNIST数据的下载,如果下载不了也可以自行网站上下载。
from sklearn.datasets import fetch_mldata
mnist = fetch_mldata('MNIST original')
- 1
- 2
下载完成后可以输入mnist自行查看一下数据的结构,还可以使用matplotlib输出一张图片看看。
下面需要划分训练集和测试集,MNIST数据集已经帮我们划分好(前60000个为训练集,后10000个位测试集)
X, y = mnist["data"], mnist["target"]
X_train, X_test, y_train, y_test = X[:60000], X[60000:], y[:60000], y[60000:]
- 1
- 2
虽然MNIST数据集中已经把训练测试集分好,但是还未打乱(shuffle),所以需要对训练集进行打乱。
import numpy as np
shuffle_index = np.random.permutation(60000)
X_train, y_train = X_train[shuffle_index], y_train[shuffle_index]
- 1
- 2
- 3
2、二分类
假设现在分类是否为数字5,则分类两类(是5或不是5),训练一个SGD分类器(该分类器对大规模的数据处理较快)。
#划分数据
y_train_5 = (y_train == 5)
y_test_5 = (y_test == 5)
#训练模型
from sklearn.linear_model import SGDClassifier
sgd_clf = SGDClassifier(random_state=42)
sgd_clf.fit(X_train, y_train_5)
#交叉验证
from sklearn.model_selection import cross_val_predict
y_train_pred = cross_val_predict(sgd_clf, X_train, y_train_5, cv=3)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
查准率和查全率(Precision and Recall)以及F1指标
与回归问题计算损失函数不同,二分类特有的一种评价指标为查准率和查全率(Precision and Recall)以及F1指标。
Precision就是预测为正类的样本有多少比例的样本是真的正类,TP/(TP+FP);Recall就是所有真正的正类样本有多少比例被预测为正类,TP/(TP+FN)。其中TP为真正类被预测为正类,FP为负类被预测为正类,FN为真正类被预测为负类。Scikit-learn也有对应的函数
from sklearn.metrics import precision_score, recall_score
precision_score(y_train_5, y_train_pred)
recall_score(y_train_5, y_train_pred)
- 1
- 2
- 3
由于Precision和Recall有两个数,如果一大一下的话不好比较两个模型的好坏,F1指标就是结合两者,求调和平均
from sklearn.metrics import f1_score
f1_score(y_train_5, y_train_pred)
- 1
- 2
对于F1值,暗含了Precision和Recall是同等重要的,然而对于现实问题并不一定同等重要,比如推荐电影,给观众推荐一部很好的电影比很多电影更重要,因此Precision更加重要;而对于检查安全问题,宁可多次去核查也不能出现一点错误,因此Recall更重要。所以对于实际问题,应该适当权衡Precision和Recall。
Precision/Recall 的权衡
虽然我们没有办法改变Scikit-learn里面的predict()函数来改变分类输出,但我们能够通过decision_function()方法来得到输出的得分情况,得分越高意味着越有把握分为这一类。因此可以通过对得分设一个界(threshold),得分大于threshod的分为正类,否则为负类,以此来调整Precision和Recall。
然而这个threhold应该怎么确定,scikit-learn中提供相关的函数precision_recall_curve()来帮助我们确定。
需要注意:cross_val_predict计算交叉验证后验证集部分的得分(而不是类别)。
#计算得分
from sklearn.model_selection import cross_val_predict
y_scores = cross_val_predict(sgd_clf, X_train, y_train_5, cv=3,
method="decision_function")
#调用precision_recall_curve
from sklearn.metrics import precision_recall_curve
precisions, recalls, thresholds = precision_recall_curve(y_train_5, y_scores)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
需要注意:得出的结果precisions和recalls的元素个数比threholds多一个,因此画图时需要回退一个。
将结果通过图展示出来
import matplotlib.pyplot as plt
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
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
观察图,按需要选择合适的Threshold。
3、多分类
对于随机森林分类器(Random Forest classifiers)和朴素贝叶斯分类器(naive Bayes classifiers),本来就能够处理多分类的问题。但是有一些算法如支撑向量机(Support Vector Machine classifier)和线性分类器(Linear classifiers)就是二分类器。将二分类器扩展到多分类器一般有两种做法。
1、OVA(one-versus-all):比如分类数字(0-9),则训练10个分类器(是否为0的分类器,是否为1的分类器.,…,是否为9的分类器),每一个分类器最后会算出一个得分,判定为最高分的那一类
2、OVO(one-versus-one):每个类之间训练一个分类器(比如0和1训练一个分类器,1-3训练一个分类器),这样总共有N*(N-1)/2个分类器,哪个类得分最高判定为那一类。
一般情况下,OVO训练速度比较快(因为训练多个小分类器比训练一个大分类器时间要快),而OVA的表现会更好,因此Scikit-learn中二分类器进行多分类默认为OVA,除了支撑向量机使用OVO以外(由于支撑向量机对大规模的数据表现不好)
下面是一个二分类器SGD分类器扩展为多分类器用作数字分类的例子
from sklearn.linear_model import SGDClassifier
sgd_clf = SGDClassifier(random_state=42)
sgd_clf.fit(X_train, y_train)
- 1
- 2
- 3
可以随便取一个数据看看得分情况
some_digit = X[36000]
sgd_clf.predict([some_digit])
some_digit_scores = sgd_clf.decision_function([some_digit])
- 1
- 2
- 3
可以看到第6个分数(代表数字5)最高,即分类为数字5。
这是OVA的情况,也可以强制变为OVO(OVA)的情况OneVsOneClassifier(OneVsRestClassifier)
4、评价分类器的好坏
对于回归任务,上一节评价模型的好坏用的是交叉验证法,对于分类任务,同样也可以采取交叉验证法,不同的是,误差不是均方误差,而是准确率(或者交叉熵)。和之前交叉验证的函数相同为cross_val_score,不过scoring为accuracy。
from sklearn.model_selection import cross_val_score
cross_val_score(sgd_clf, X_train, y_train, cv=3, scoring="accuracy")
- 1
- 2
结果为:
可以看到准确率大概在86%,当然也可以采用预处理(标准化)来增加准确率。
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train.astype(np.float64))
cross_val_score(sgd_clf, X_train_scaled, y_train, cv=3, scoring="accuracy")
- 1
- 2
- 3
- 4
结果为:
可以看到经过标准化后准确率上升到了90%
5、错误分析
当然,如果这是一个真正的项目,还需要尝试多个模型,选择最佳模型并微调超参数,现在假设已经找到了这个模型,并想进一步提升,其中一种方法是分析错误的类型是哪些。
混淆矩阵法
首先要使用cross_val_predict计算交叉验证后验证集部分的预测分类结果(而不是正确率),然后根据真正的标签和预测结果对比,画出混淆矩阵(如下图),第 i 行第 j 列的数字代表数字 i 被预测为数字 j 的个数总和,比如第5行第一个数表示数字4被误判为0的次数为75;对角线上即为正确分类的次数。
from sklearn.model_selection import cross_val_predict
from sklearn.metrics import 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
- 1
- 2
- 3
- 4
- 5
然而矩阵中数据太多很复杂,所以可以通过图更加直观地表示出来
plt.matshow(conf_mx, cmap=plt.cm.gray)
plt.show()
- 1
- 2
从图中可以看到分类结果表现的还好,数字5比较暗,说明数字5被错分的比较多。
还可以去除正确的对角线的分布情况,只看错误的分布
row_sums = conf_mx.sum(axis=1, keepdims=True)
norm_conf_mx = conf_mx / row_sums.astype(np.float64)
np.fill_diagonal(norm_conf_mx, 0)
plt.matshow(norm_conf_mx, cmap=plt.cm.gray)
plt.show()
- 1
- 2
- 3
- 4
- 5
可以看到第6行第4列与第4行第6列种比较白,说明5错分为3,3错分为5的次数比较多。因此还可以把错误分为3和5的样本提取出来观察分析,从而改进算法。
6、多标签分类(Multilabel Classification)
直到现在的例子都是将数据分为某一类,但有些时候想分为多个类(比如人脸识别分类器,如果一张图片上有多个人脸,那就不能只识别一个人,而是要识别出多个人),输出比如为[1,0,1],则分为1和3类。对于这种输出多个二值分类标签的就是多标签分类。下面是一个简单的例子:
from sklearn.neighbors import KNeighborsClassifier
y_train_large = (y_train >= 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])
- 1
- 2
- 3
- 4
- 5
- 6
- 7
例子中的任务是:分类数据 是否大于等于7 以及 是否为奇数 这2个标签,使用k-近邻分类器(KNN)进行多标签分类(不是所有的分类器都能进行多标签分类)。
评价多标签分类模型的方法可以对每种标签求F1值,再求平均值。
7、多输出分类(Multioutput Classification)
多输出分类是多标签分类更一般的一种形式,比如现在图像有噪声,需要将每个像素分类为0或1已达到去噪的目的(也可以多个标签)。下面就是一个例子,如下图,左图为的像素为特征,右图为标签。
#生成左边的噪声图
import numpy.random as rnd
noise1 = rnd.randint(0, 100, (len(X_train), 784))
noise2 = rnd.randint(0, 100, (len(X_test), 784))
X_train_mod = X_train + noise1
X_test_mod = X_test + noise2
y_train_mod = X_train
y_test_mod = X_test
import matplotlib.pyplot as plt
plt.subplot(1,2,1)
plt.imshow(X_train_mod[36000].reshape(28,28),cmap=plt.cm.gray)
plt.subplot(1,2,2)
plt.imshow(X_train[36000].reshape(28,28),cmap=plt.cm.gray)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
接下来训练一个KNN模型实现多输出分类(去噪)
from sklearn.neighbors import KNeighborsClassifier
knn_clf = KNeighborsClassifier()
knn_clf.fit(X_train_mod, y_train_mod)
clean_digit = knn_clf.predict([X_train_mod[36000]])
plt.imshow(clean_digit.reshape(28,28),cmap=plt.cm.gray)
- 1
- 2
- 3
- 4
- 5
可以看到训练的模型能够对每个像素进行分类,从而实现去噪。
机器学习实战(用Scikit-learn和TensorFlow进行机器学习)(四)相关推荐
- [转载]Scikit Learn: 在python中机器学习
原址:http://my.oschina.net/u/175377/blog/84420 目录[-] Scikit Learn: 在python中机器学习 载入示例数据 一个改变数据集大小的示例:数码 ...
- 机器学习实战:基于Scikit-Learn.Keras和TensorFlow(原书第2版) 奥雷利安·杰龙——环境搭建anaconda
这个学期开了一门课,机器学习 然后实验部分用的是这本教材:机器学习实战:基于Scikit-Learn.Keras和TensorFlow 奥雷利安·杰龙,第几版的就不知道了. 用最新的机器学习库,一定会 ...
- Scikit Learn: 在python中机器学习
Warning 警告:有些没能理解的句子,我以自己的理解意译. 翻译自:Scikit Learn:Machine Learning in Python 作者: Fabian Pedregosa, Ga ...
- 机器学习实战 基于_机器学习实战:基于Scikit-Learn和TensorFlow—第四章笔记
机器学习实战:基于Scikit-Learn和TensorFlow---第四章笔记 一.学习目标 之前用了那么多的机器学习的模型,但是它们各自的训练算法在很大程度上还是一个黑匣子,我们对对系统内部的实现 ...
- 机器学习实战指南:如何入手第一个机器学习项目?
点击上方"AI有道",选择"星标公众号" 重磅干货,第一时间送达! 本系列为<Scikit-Learn 和 TensorFlow 机器学习指南>的第 ...
- tensorflow机器学习实战指南 源代码_小小白TensorFlow机器学习实战基础
一.TensorFlow基本概念 TensorFlow以数据流为核心,还具备两大特点:将图的定义和图的运行完全分开:图的计算在会话中执行.具体操作如下: import tensorflow as tf ...
- scikit learn、tensorflow、keras区别
参考:简书-刘敬:https://www.jianshu.com/p/0837b7c6ce10,感谢 一. 功能不同 Scikit-learn(sklearn)的定位是通用机器学习库 TensorFl ...
- python scikit learn 关闭开源_Python机器学习工具:Scikit-Learn介绍与实践
Scikit-learn 简介 官方的解释很简单: Machine Learning in Python, 用python来玩机器学习. 什么是机器学习 机器学习关注的是: 计算机程序如何随着经验积累 ...
- Hands On Machine Learning with Scikit Learn and TensorFlow(第三章)
MNIST 从sklearn自带函数中导入NMIST 第一次导入可能会出错,从这里下载https://github.com/amplab/datascience-sp14/blob/master/la ...
- 机器学习实战:基于Scikit-Learn和TensorFlow(一)
1.1机器学习 答:计算机程序利用经验 E 学习任务 T,性能是 P,如果针对任务 T 的性能 P 随着经验 E 不断增 长,则称为机器学习. -- 汤姆·米切尔,1997 1.2.机器学习系统的类型 ...
最新文章
- document.getElementById vs jQuery $()
- linux下配置 ITK
- 来聊一聊Cookie(小甜饼),及其涉及到的web安全吧
- LeetCode题库第888题 公平的糖果棒交换
- git tag 功能笔记
- 计算机网络基础:ISO/OSI网络体系结构知识笔记​
- leetcode 338. 比特位计数
- css绘制正方体_设计师仅使用CSS绘制了8个标志性X战警
- Haproxy+Percona-XtraDB-Cluster 集群
- 深入浅出的排序算法-冒泡排序
- MyBatis 级联
- AS3 XML全部用法
- linux系统盘打快照,使用Btrfs对Linux系统进行快照回滚
- python day 1 homework 1
- 详述差分进化算法(DE)代码复现
- CCNA系列十一之Frame-Relay
- PENCIL 决策建模器
- linux如何卸载lightdm,在Linux Deepin上安装Pantheon Lightdm主题
- hive项目之微博ETL项目总结分析
- 用netty实现zcool_Netty 系列一(核心组件和实例).
热门文章
- Azkaban报错:Missing required property ‘azkaban.native.lib’
- restful java demo_java通过servlet实现restful接口示例
- qgraphicsview 添加矩形框并拖动改变大小_如何用手机巧影软件为视频添加字幕
- php对字符串进行编码,PHP如何使用convert_uuencode()函数对字符串进行编码?
- python调用shell用什么类_python脚本中调用shell命令
- 计算机二级语义网络的研究现状与展望,计算机二级access选择题题库研究.doc
- linux 服务器 重新启动 慢,Linux系统启动缓慢解决方法[阮胜昌]
- mysql io_MySQL服务器 IO 100%的分析与优化方案
- winpcap基本原理及常见应用_数字图像处理原理及应用教学大纲
- 计算机应用基础计算配置教案,[定稿]计算机应用基础教案_Windows_XP版V8.1(全文完整版)...