Python机器学习之数据探索可视化库yellowbrick-tutorial

背景介绍

从学sklearn时,除了算法的坎要过,还得学习matplotlib可视化,对我的实践应用而言,可视化更重要一些,然而matplotlib的易用性和美观性确实不敢恭维。陆续使用过plotly、seaborn,最终定格在了Bokeh,因为它可以与Flask完美的结合,数据看板的开发难度降低了很多。

前阵子看到这个库可以较为便捷的实现数据探索,今天得空打算学习一下。原本访问的是英文文档,结果发现已经有人在做汉化,虽然看起来也像是谷歌翻译的,本着拿来主义,少费点精力的精神,就半抄半学,还是发现了一些与文档不太一致的地方。

# http://www.scikit-yb.org/zh/latest/tutorial.html

模型选择教程

在本教程中,我们将查看各种 Scikit-Learn 模型的分数,并使用 Yellowbrick 的可视化诊断工具对其进行比较,以便为我们的数据选择最佳模型。

模型选择三元组

关于机器学习的讨论常常集中在模型选择上。无论是逻辑回归、随机森林、贝叶斯方法,还是人工神经网络,机器学习实践者通常都能很快地展示他们的偏好。这主要是因为历史原因。尽管现代的第三方机器学习库使得各类模型的部署显得微不足道,但传统上,即使是其中一种算法的应用和调优也需要多年的研究。因此,与其他模型相比,机器学习实践者往往对特定的(并且更可能是熟悉的)模型有强烈的偏好。

然而,模型选择比简单地选择“正确”或“错误”算法更加微妙。实践中的工作流程包括:

选择和/或设计最小和最具预测性的特性集
从模型家族中选择一组算法,并且
优化算法超参数以优化性能。

模型选择三元组 是由Kumar 等人,在 2015 年的 SIGMOD 论文中首次提出。在他们的论文中,谈论到下一代为预测建模而构建的数据库系统的开发。作者很中肯地表示,由于机器学习在实践中具有高度实验性,因此迫切需要这样的系统。“模型选择,”他们解释道,“是迭代的和探索性的,因为(模型选择三元组)的空间通常是无限的,而且通常不可能让分析师事先知道哪个(组合)将产生令人满意的准确性和/或洞察力。”

最近,许多工作流程已经通过网格搜索方法、标准化 API 和基于 GUI 的应用程序实现了自动化。然而,在实践中,人类的直觉和指导可以比穷举搜索更有效地专注于模型质量。通过可视化模型选择过程,数据科学家可以转向最终的、可解释的模型,并避免陷阱。

Yellowbrick 库是一个针对机器学习的可视化诊断平台,它允许数据科学家控制模型选择过程。Yellowbrick 用一个新的核心对象扩展了Scikit-Learn 的 API: Visualizer。Visualizers 允许可视化模型作为Scikit-Learn管道过程的一部分进行匹配和转换,从而在高维数据的转换过程中提供可视化诊断。

关于数据

本教程使用来自 UCI Machine Learning Repository 的修改过的蘑菇数据集版本。我们的目标是基于蘑菇的特定,去预测蘑菇是有毒的还是可食用的。

这些数据包括与伞菌目(Agaricus)和环柄菇属(Lepiota)科中23种烤蘑菇对应的假设样本描述。 每一种都被确定为绝对可食用,绝对有毒,或未知的可食用性和不推荐(后一类与有毒物种相结合)。

我们的文件“agaricus-lepiota.txt”,包含3个名义上有价值的属性信息和8124个蘑菇实例的目标值(4208个可食用,3916个有毒)。

让我们用Pandas加载数据。

import os
import pandas as pd
mushrooms = ‘data/shrooms.csv‘  # 数据集
dataset   = pd.read_csv(mushrooms)
# dataset.columns = names
dataset.head()

<div>
<style scoped>
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}

.dataframe tbody tr th {
    vertical-align: top;
}

.dataframe thead th {
    text-align: right;
}

</style>
<table border="1" class="dataframe">
<thead>
<tr style="text-align: right;">
<th></th>
<th>id</th>
<th>class</th>
<th>cap-shape</th>
<th>cap-surface</th>
<th>cap-color</th>
<th>bruises</th>
<th>odor</th>
<th>gill-attachment</th>
<th>gill-spacing</th>
<th>gill-size</th>
<th>...</th>
<th>stalk-color-above-ring</th>
<th>stalk-color-below-ring</th>
<th>veil-type</th>
<th>veil-color</th>
<th>ring-number</th>
<th>ring-type</th>
<th>spore-print-color</th>
<th>population</th>
<th>habitat</th>
<th>Unnamed: 24</th>
</tr>
</thead>
<tbody>
<tr>
<th>0</th>
<td>1</td>
<td>p</td>
<td>x</td>
<td>s</td>
<td>n</td>
<td>t</td>
<td>p</td>
<td>f</td>
<td>c</td>
<td>n</td>
<td>...</td>
<td>w</td>
<td>w</td>
<td>p</td>
<td>w</td>
<td>o</td>
<td>p</td>
<td>k</td>
<td>s</td>
<td>u</td>
<td>NaN</td>
</tr>
<tr>
<th>1</th>
<td>2</td>
<td>e</td>
<td>x</td>
<td>s</td>
<td>y</td>
<td>t</td>
<td>a</td>
<td>f</td>
<td>c</td>
<td>b</td>
<td>...</td>
<td>w</td>
<td>w</td>
<td>p</td>
<td>w</td>
<td>o</td>
<td>p</td>
<td>n</td>
<td>n</td>
<td>g</td>
<td>NaN</td>
</tr>
<tr>
<th>2</th>
<td>3</td>
<td>e</td>
<td>b</td>
<td>s</td>
<td>w</td>
<td>t</td>
<td>l</td>
<td>f</td>
<td>c</td>
<td>b</td>
<td>...</td>
<td>w</td>
<td>w</td>
<td>p</td>
<td>w</td>
<td>o</td>
<td>p</td>
<td>n</td>
<td>n</td>
<td>m</td>
<td>NaN</td>
</tr>
<tr>
<th>3</th>
<td>4</td>
<td>p</td>
<td>x</td>
<td>y</td>
<td>w</td>
<td>t</td>
<td>p</td>
<td>f</td>
<td>c</td>
<td>n</td>
<td>...</td>
<td>w</td>
<td>w</td>
<td>p</td>
<td>w</td>
<td>o</td>
<td>p</td>
<td>k</td>
<td>s</td>
<td>u</td>
<td>NaN</td>
</tr>
<tr>
<th>4</th>
<td>5</td>
<td>e</td>
<td>x</td>
<td>s</td>
<td>g</td>
<td>f</td>
<td>n</td>
<td>f</td>
<td>w</td>
<td>b</td>
<td>...</td>
<td>w</td>
<td>w</td>
<td>p</td>
<td>w</td>
<td>o</td>
<td>e</td>
<td>n</td>
<td>a</td>
<td>g</td>
<td>NaN</td>
</tr>
</tbody>
</table>
<p>5 rows × 25 columns</p>
</div>

features = [‘cap-shape‘, ‘cap-surface‘, ‘cap-color‘]
target   = [‘class‘]
X = dataset[features]
y = dataset[target]
dataset.shape # 较官方文档少了俩蘑菇
(8122, 25)
dataset.groupby(‘class‘).count() # 各少了1个蘑菇

<div>
<style scoped>
.dataframe tbody tr th:only-of-type {
vertical-align: middle;
}

.dataframe tbody tr th {
    vertical-align: top;
}

.dataframe thead th {
    text-align: right;
}

</style>
<table border="1" class="dataframe">
<thead>
<tr style="text-align: right;">
<th></th>
<th>id</th>
<th>cap-shape</th>
<th>cap-surface</th>
<th>cap-color</th>
<th>bruises</th>
<th>odor</th>
<th>gill-attachment</th>
<th>gill-spacing</th>
<th>gill-size</th>
<th>gill-color</th>
<th>...</th>
<th>stalk-color-above-ring</th>
<th>stalk-color-below-ring</th>
<th>veil-type</th>
<th>veil-color</th>
<th>ring-number</th>
<th>ring-type</th>
<th>spore-print-color</th>
<th>population</th>
<th>habitat</th>
<th>Unnamed: 24</th>
</tr>
<tr>
<th>class</th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<th>e</th>
<td>4207</td>
<td>4207</td>
<td>4207</td>
<td>4207</td>
<td>4207</td>
<td>4207</td>
<td>4207</td>
<td>4207</td>
<td>4207</td>
<td>4207</td>
<td>...</td>
<td>4207</td>
<td>4207</td>
<td>4207</td>
<td>4207</td>
<td>4207</td>
<td>4207</td>
<td>4207</td>
<td>4207</td>
<td>4207</td>
<td>0</td>
</tr>
<tr>
<th>p</th>
<td>3915</td>
<td>3915</td>
<td>3915</td>
<td>3915</td>
<td>3915</td>
<td>3915</td>
<td>3915</td>
<td>3915</td>
<td>3915</td>
<td>3915</td>
<td>...</td>
<td>3915</td>
<td>3915</td>
<td>3915</td>
<td>3915</td>
<td>3915</td>
<td>3915</td>
<td>3915</td>
<td>3915</td>
<td>3915</td>
<td>0</td>
</tr>
</tbody>
</table>
<p>2 rows × 24 columns</p>
</div>

特征提取

我们的数据,包括目标参数,都是分类型数据。为了使用机器学习,我们需要将这些值转化为数值型数据。为了从数据集中提取这一点,我们必须使用Scikit-Learn的转换器(transformers)将输入数据集转换为适合模型的数据集。幸运的是,Sckit-Learn提供了一个转换器,用于将分类标签转换为整数: sklearn.preprocessing.LabelEncoder。不幸的是,它一次只能转换一个向量,所以我们必须对它进行调整,以便将它应用于多个列。
有疑问,这个蘑菇分类就是一个向量?

from sklearn.base import BaseEstimator, TransformerMixin
from sklearn.preprocessing import LabelEncoder, OneHotEncoder
class EncodeCategorical(BaseEstimator, TransformerMixin):
    """
    Encodes a specified list of columns or all columns if None.
    """

    def __init__(self, columns=None):
        self.columns  = [col for col in columns]
        self.encoders = None

    def fit(self, data, target=None):
        """
        Expects a data frame with named columns to encode.
        """
        # Encode all columns if columns is None
        if self.columns is None:
            self.columns = data.columns

        # Fit a label encoder for each column in the data frame
        self.encoders = {
            column: LabelEncoder().fit(data[column])
            for column in self.columns
        }
        return self

    def transform(self, data):
        """
        Uses the encoders to transform a data frame.
        """
        output = data.copy()
        for column, encoder in self.encoders.items():
            output[column] = encoder.transform(data[column])

        return output

建模与评估

评估分类器的常用指标

精确度(Precision) 是正确的阳性结果的数量除以所有阳性结果的数量(例如,我们预测的可食用蘑菇实际上有多少?)

召回率(Recall) 是正确的阳性结果的数量除以应该返回的阳性结果的数量(例如,我们准确预测了多少有毒蘑菇是有毒的?)

F1分数(F1 score) 是测试准确度的一种衡量标准。它同时考虑测试的精确度和召回率来计算分数。F1得分可以解释为精度和召回率的加权平均值,其中F1得分在1处达到最佳值,在0处达到最差值。
precision = true positives / (true positives + false positives)

recall = true positives / (false negatives + true positives)

F1 score = 2 ((precision recall) / (precision + recall))
现在我们准备好作出一些预测了!

让我们构建一种评估多个估算器(multiple estimators)的方法 —— 首先使用传统的数值分数(我们稍后将与Yellowbrick库中的一些可视化诊断进行比较)。

from sklearn.metrics import f1_score
from sklearn.pipeline import Pipeline
def model_selection(X, y, estimator):
    """
    Test various estimators.
    """
    y = LabelEncoder().fit_transform(y.values.ravel())
    model = Pipeline([
         (‘label_encoding‘, EncodeCategorical(X.keys())),
         (‘one_hot_encoder‘, OneHotEncoder(categories=‘auto‘)),  # 此处增加自动分类,否则有warning
         (‘estimator‘, estimator)
    ])

    # Instantiate the classification model and visualizer
    model.fit(X, y)

    expected  = y
    predicted = model.predict(X)

    # Compute and return the F1 score (the harmonic mean of precision and recall)
    return (f1_score(expected, predicted))
from sklearn.svm import LinearSVC, NuSVC, SVC
from sklearn.neighbors import KNeighborsClassifier
from sklearn.linear_model import LogisticRegressionCV, LogisticRegression, SGDClassifier
from sklearn.ensemble import BaggingClassifier, ExtraTreesClassifier, RandomForestClassifier
model_selection(X, y, LinearSVC())
0.6582119537920643
import warnings
warnings.filterwarnings("ignore", category=FutureWarning, module="sklearn")  # 忽略警告
model_selection(X, y, NuSVC())
0.6878837238441299
model_selection(X, y, SVC())
0.6625145971195017
model_selection(X, y, SGDClassifier())
0.5738408700629649
model_selection(X, y, KNeighborsClassifier())
0.6856846473029046
model_selection(X, y, LogisticRegressionCV())
0.6582119537920643
model_selection(X, y, LogisticRegression())
0.6578749058025622
model_selection(X, y, BaggingClassifier())
0.6873901878632248
model_selection(X, y, ExtraTreesClassifier())
0.6872294372294372
model_selection(X, y, RandomForestClassifier())
0.6992081007399714

初步模型评估

根据上面F1分数的结果,哪个模型表现最好?

可视化模型评估

现在,让我们重构模型评估函数,使用Yellowbrick的ClassificationReport类,这是一个模型可视化工具,可以显示精确度、召回率和F1分数。这个可视化的模型分析工具集成了数值分数以及彩色编码的热力图,以支持简单的解释和检测,特别是对于我们用例而言非常相关(性命攸关!)的第一类错误(Type I error)和第二类错误(Type II error)的细微差别。

第一类错误 (或 "假阳性(false positive)" ) 是检测一种不存在的效应(例如,当蘑菇实际上是可以食用的时候,它是有毒的)。

第二类错误 (或 “假阴性”"false negative" ) 是未能检测到存在的效应(例如,当蘑菇实际上有毒时,却认为它是可以食用的)。

from sklearn.pipeline import Pipeline
from yellowbrick.classifier import ClassificationReport

def visual_model_selection(X, y, estimator):
    """
    Test various estimators.
    """
    y = LabelEncoder().fit_transform(y.values.ravel())
    model = Pipeline([
         (‘label_encoding‘, EncodeCategorical(X.keys())),
         (‘one_hot_encoder‘, OneHotEncoder()),
         (‘estimator‘, estimator)
    ])

    # Instantiate the classification model and visualizer
    visualizer = ClassificationReport(model, classes=[‘edible‘, ‘poisonous‘])
    visualizer.fit(X, y)
    visualizer.score(X, y)
    visualizer.poof()
visual_model_selection(X, y, LinearSVC())

# 其他分类器可视化略
visual_model_selection(X, y, RandomForestClassifier())

检验

现在,哪种模型看起来最好?为什么?
哪一个模型最有可能救你的命?
可视化模型评估与数值模型评价,体验起来有何不同?

准确率Precision召回率Recall以及综合评价指标F1-Measure
http://www.makaidong.com/%E5%8D%9A%E5%AE%A2%E5%9B%AD%E7%83%AD%E6%96%87/437.shtml
f1-score综合考虑的准确率和召回率。
可视化就是直观嘛,逃~

作者简介

知乎yeayee,Py龄5年,善Flask+MongoDB+SKlearn+Bokeh

原文地址:https://blog.51cto.com/14509091/2431116

时间: 2024-11-06 22:22:51

Python机器学习之数据探索可视化库yellowbrick-tutorial的相关文章

Python机器学习之数据探索可视化库yellowbrick

背景介绍 从学sklearn时,除了算法的坎要过,还得学习matplotlib可视化,对我的实践应用而言,可视化更重要一些,然而matplotlib的易用性和美观性确实不敢恭维.陆续使用过plotly.seaborn,最终定格在了Bokeh,因为它可以与Flask完美的结合,数据看板的开发难度降低了很多. 前阵子看到这个库可以较为便捷的实现数据探索,今天得空打算学习一下.原本访问的是英文文档,结果发现已经有人在做汉化,虽然看起来也像是谷歌翻译的,本着拿来主义,少费点精力的精神,就半抄半学,还是发

机器学习之数据探索——数据质量分析

数据探索是对样本数据进行解释性的分析工作,它是数据挖掘和机器学习较为前期的部分,更偏重于研究数据的本质.描述数据的形态特征并解释数据的相关性. 换句话说,透过数据探索,我们应该可以回答如下问题: 样本数据的分布怎样?有什么特点?数据之间有何种关系?数据是否满足建模要求? 问题驱动发展,对以上问题进行解答,涉及到数据探索的两个方面工作: 数据质量分析 数据特征分析 需要提及的是,数据探索与数据预处理紧密相连的,二者在数据挖掘的中没有绝对的先后次序.比如,在数据质量分析中,就牵涉到数据预处理中的数据

机器学习之数据探索——数据特征分析(分布分析)

数据特征分析与数据质量分析一道构成数据探索的两方面工作,在前文中介绍过关于数据质量分析的概况,本文将对数据特征分析作简介,并着重于分布分析的角度,相比于数据质量分析,数据特征分析更注重于找寻数据间的关系. 数据特征分析包括以下几个分析角度: 1.分布分析 2.对比分析 3.统计量分析 4.帕累托分析 5.正态性检验 6.相关性分析 其上每一个分析角度都有丰富的内容. 分布分析 顾名思义,分布分析研究数据的分布特征和分布类型.对于定量数据,需要了解分布形式,发现某些特大特小的异常值,通常用到散点图

python 机器学习之数据预处理

#数据预处理方法,主要是处理数据的量纲和同趋势化问题. import numpy as np from sklearn import preprocessing #零均值规范 data=np.random.rand(3,4)#随机生成3行4列的数据 data_standardized=preprocessing.scale(data)#对数据进行归一化处理,即每个数值减去均值除以方差 主要用于svm #线性数据变换最大最小化处理 data_scaler=preprocessing.MinMaxS

Python数据可视化库-Matplotlib(一)

今天我们来学习一下python的数据可视化库,Matplotlib,是一个Python的2D绘图库 通过这个库,开发者可以仅需要几行代码,便可以生成绘图,直方图,功率图,条形图,错误图,散点图等等 废话不多说,我们直接通过例子来进行讲解. 首先我们有一组数据如下: 我们可以看到,这组数据有日期,还有日期对应的值,因为这组数据中的日期格式不是标准的日期格式 那么我们对数据做一下转换,取1948年的整年的数据,来进行一个绘图操作 import pandas as pd unrate = pd.rea

Python机器学习库资料汇总

声明:以下内容转载自平行宇宙. Python在科学计算领域,有两个重要的扩展模块:Numpy和Scipy.其中Numpy是一个用python实现的科学计算包.包括: 一个强大的N维数组对象Array: 比较成熟的(广播)函数库: 用于整合C/C++和Fortran代码的工具包: 实用的线性代数.傅里叶变换和随机数生成函数. SciPy是一个开源的Python算法库和数学工具包,SciPy包含的模块有最优化.线性代数.积分.插值.特殊函数.快速傅里叶变换.信号处理和图像处理.常微分方程求解和其他科

常用python机器学习库总结

开始学习Python,之后渐渐成为我学习工作中的第一辅助脚本语言,虽然开发语言是Java,但平时的很多文本数据处理任务都交给了Python.这些年来,接触和使用了很多Python工具包,特别是在文本处理,科学计算,机器学习和数据挖掘领域,有很多很多优秀的Python工具包可供使用,所以作为Pythoner,也是相当幸福的.如果仔细留意微博和论坛,你会发现很多这方面的分享,自己也Google了一下,发现也有同学总结了"Python机器学习库",不过总感觉缺少点什么.最近流行一个词,全栈工

[resource]Python机器学习库

reference: http://qxde01.blog.163.com/blog/static/67335744201368101922991/ Python在科学计算领域,有两个重要的扩展模块:Numpy和Scipy.其中Numpy是一个用python实现的科学计算包.包括: 一个强大的N维数组对象Array: 比较成熟的(广播)函数库: 用于整合C/C++和Fortran代码的工具包: 实用的线性代数.傅里叶变换和随机数生成函数. SciPy是一个开源的Python算法库和数学工具包,S

Pycon 2017: Python可视化库大全

本文首发于微信公众号“Python数据之道” 前言 本文主要摘录自 pycon 2017大会的一个演讲,同时结合自己的一些理解. pycon 2017的相关演讲主题是“The Python Visualization Landscape”. 先来一张全景图镇楼~~ 看完这张图是不是有点懵? 别着急,我们一起来看看后面的阐述. python可视化库可以大致分为几类: 基于matplotlib的可视化库 基于JS的可视化库 基于上述两者或其他组合功能的库 基于matplotlib的可视化库 matp