TowardsDataScience 博客中文翻译 2021(三百六十二)
数据科学家擅长创建代表和预测现实世界数据的模型,但实际上将机器学习模型投入使用更多的是一门艺术而不是科学。部署需要软件工程和开发运维中常见的技能。指出,87%的数据科学项目从未投入生产,而redapt指出是 90%。两者都强调了决定成功和失败的一个重要因素是团队的协作和迭代。机器学习模型的目标是解决一个问题,只有通过用户界面才能解决这个问题。因此,开发和部署用户界面是建模的一个重要步骤。缩小构建和
如何以最简单的方式创建机器学习界面
我如何为一个复杂的草图识别模型构建一个很棒的 UI
草图预测应用—作者图片
最终部署的应用程序—作者的视频
介绍
数据科学家擅长创建代表和预测现实世界数据的模型,但实际上将机器学习模型投入使用更多的是一门艺术而不是科学。部署需要软件工程和开发运维中常见的技能。 Venturebeat 指出,87%的数据科学项目从未投入生产,而 redapt 指出是 90%。两者都强调了决定成功和失败的一个重要因素是团队的协作和迭代。
机器学习模型的目标是解决一个问题,只有通过用户界面才能解决这个问题。
因此,开发和部署用户界面是建模的一个重要步骤。缩小构建和部署模型之间的差距是我们如何确保拥有一个健壮的模型。
在这篇文章中,我将演示一些简单的步骤来给你的机器学习模型带来活力。我将为草图识别模型构建一个 UI。它将包括一个供用户绘制的画板输入,以及一个对草图进行实时分类的标签输出,所有这些都被部署到一个任何人都可以使用的实时链接中。那么,我们开始吧。
先决条件
本教程假设您熟悉在 TensorFlow 和 Keras 中构建 ANN 模型。对于本教程,我们将使用来自 AI 实验 Github repo 的训练模型来构建与 Gradio 的接口。
此外,如果你需要复习 gradio,你可以看看我以前的教程,一步一步地指导你如何建立一个 Gradio 帐户。此外,您可以点击查看 gradio 网站上的入门指南。
在本教程中,我们将使用tensorflow version 1.x
如果您想使用最新版本的tensorflow 2.x
,您需要相应地重新培训该模型。但是,步骤应该是相同的。
与本教程相关的笔记本托管在 Github 这里,如果你愿意跟随的话。
安装所需的库
您需要使用pip install gradio
命令安装 gradio。
然后,我们需要导入 gradio 以及 TensorFlow。之后,我们将使用tf.keras
模块中的“load_model”功能将预训练的模型加载到 colab 笔记本中。
!pip install gradio -q%tensorflow_version 1.x
此外,我们需要获取与每个绘图相关联的标签;为此,我们将从 google creative lab 公共存储库中导入它们。
以. txt 格式存储的绘图类别,我们需要将它们解码成utf-8
格式,并通过在\n
字符上拆分来转换成列表。
import gradio as gr
import tensorflow as tf
import urllib.request
cnn_model = tf.keras.models.load_model("/content/cnn.h5")labels = urllib.request.urlopen(
"https://raw.githubusercontent.com/googlecreativelab/quickdraw-dataset/master/categories.txt")labels = labels.read()
labels = labels.decode('utf-8').split("\n")[:-1]
我们对列表中的最后一个元素进行了切片,因为它是拆分过程产生的空字符串。
声明预测函数
Gradio 接口包括三个主要组件:
1.可调用函数—在我们的例子中是` predict_shape()’
2.输入组件—可调用函数的参数
3.输出组件-应用可调用函数后的输入。
因此,在接下来的几行中,我们定义了predict_shape()
方法,并将绘图作为输入图像传递。之后,对上传的模型调用 predict 方法来获得预测。
predict_shape()
在这里返回所有标签及其预测分数,标签的输出组件中的 gradio 有一个默认为 3 的num_top_classes
def predict_shape(img):
img = tf.math.divide(img, 255)
preds = cnn_model.predict(img.reshape(-1, 28, 28, 1))[0]
return {label: float(pred) for label, pred in zip(labels, preds)}
定义输入和输出组件
Gradio 有各种各样的组件可供您选择,以满足您的应用需求——点击此处查看完整的库组件。
https://www.gradio.app/docs#i_image
对于这个应用程序,我们将使用图像组件,并将源设置为“canvas”以获得一个画板界面。此外,我们将画布的大小设置为 28x 28 像素。
我们将选择标签作为输出组件,并将只显示预测中最高的两个类。
output = gr.outputs.Label(num_top_classes=2)
input = gr.inputs.Image(
image_mode='L',
source='canvas',
shape=(28, 28),
invert_colors=True,
tool= 'select')
设置界面
呈现之前准备好的组件的最后一步是通过接口函数。您需要做的就是将可调用的函数、输入和输出传递给Interface()
,然后调用launch()
来呈现应用程序。
Gradio 的一个很好的特性是,您可以向呈现的界面添加 HTML 标记元素,因此它可以作为一个独立的 web 应用程序运行。在接口方法中,我为呈现的应用程序传递了标题和描述。
如果您在 google colab 上,您需要在
launch()
方法内将 debug 设置为 True,以便在 colab 内呈现。
title="Sketch prediction app"description="A Convolution Neural Network model trained on Google's QuickDraw dataset." \
" Start by draw a smily face, or anything you can think of!"
请注意:根据文档,您需要将 capture_session 标志设置为 True,因为模型最初是使用 TensorFlow 1.x 训练的。
gr.Interface(fn = predict_shape, inputs = input,
outputs = output, live = True,
title=title, description = description,
capture_session=True).launch(debug=True)
工作梯度界面—图片由作者提供
厉害!我们现在有一个很好的界面。
部署接口以获得持久链接
在之前的一篇文章中,我向您展示了 Gradio 如何使用 Flask 和 Docker 构建应用程序后端的整个生命周期。
直到这一步,你有一个 24 小时工作的可共享链接,如果你想保持链接,你需要在 Gradio 主机上托管应用程序,在那里你可以上传接口并获得一个永久链接。
https://www.gradio.app/introducing-hosted
步骤很简单,您只需要:
1.Github 项目回购,应该包括 requirements.txt 文件
2.Gradio 帐户(与 GitHub 的电子邮件相同)
就是这样!
部署屏幕—作者提供的图片
该界面可能需要几分钟来构建映像后端要求。
可能需要几分钟https://gradio.app/g/salma71/sketch_predict—图片由作者提供
然后可以在已部署的链接中找到已部署的接口。您可能会收到一封确认接口已成功部署的电子邮件—您可以在这里检查已部署的接口。
https://gradio.app/g/salma71/sketch_predict
在集线器上显示
通过将应用程序托管在 Hub 上,您可以将模型向前推进一步。你所需要做的就是指定标题、描述和一个缩略图,一切都准备好了。
在 Gradio Hub 上显示应用程序—图片由作者提供
https://gradio.app/hub/salma71/sketch_predict—作者图片
谢谢大家!
我希望这篇文章能让你对 Gradio 库有一个全面的了解。如有疑问,请写在下方评论区;我很乐意帮忙。
鼓励我的最好方式是在MediumLinkedIn**或 Github **上跟随我。感谢阅读!
参考
如何使用 Python 创建类似 3Blue1Brown 的数学动画
利用您的 Python 技能创建美丽的数学动画
动机
你是否曾经纠结于机器学习算法的数学概念,并将 3Blue1Brown 作为学习资源?3Blue1Brown 是著名的数学 YouTube 频道,由格兰特·桑德森(Grant Sanderson)创建。很多人喜欢 3Blue1Brown 是因为 Grant 的精彩讲解和下面这样很酷的动画。
如果您可以了解他是如何创建这些动画的,这样您就可以创建类似的动画来向您的队友、经理或追随者解释一些数据科学概念,这不是很酷吗?
幸运的是,Grant 开发了一个名为 manim 的 Python 包,可以让你使用 Python 创建数学动画或图片。在这篇文章中,你将学习如何使用 manim 创建如下数学动画。
作者 GIF
什么是曼尼姆?
Manim 是一个精确动画引擎,设计用于创建解释性数学视频。注意,manim 有两个版本。一个是由 Grant 创建的,另一个是由 Manim 社区派生和维护的。
由于 Manim 社区维护的版本比 Grant 的版本更新更频繁,测试更好,所以我们将使用 Manim 社区维护的版本。
要安装软件包的依赖项,请访问文档。安装完依赖项后,键入:
pip install manim==0.9.0
开始
创建一个从中心开始增长的蓝色方块
我们将创建一个从中心开始增长的蓝色正方形。创建动画的代码在从Scene
派生的类的construct
方法中。
将上面的脚本另存为start.py
。现在运行下面的命令为脚本生成一个视频。
$ manim -p -ql start.py PointMovingOnShapes
并且一个名为PointMovingOnShapes.mp4
的视频会保存在你的本地目录下。您应该会看到类似下面的内容!
作者 GIF
上述选项的解释:
-p
:视频生成完成后播放-ql
:生成低质量视频
要生成高质量的视频,请使用-qh
。
要创建一个 GIF 而不是视频,添加-i
到命令中,如下所示:
$ manim -p -ql -i start.py PointMovingOnShapes
把正方形变成圆形
单独创建一个正方形并不那么有趣。让我们把这个正方形变成一个圆形。
作者 GIF
创建上述动画的代码:
点击查看形状的完整列表。
自定义 Manim
如果不希望背景是黑色的,可以像下面这样变成灰色:
作者 GIF
通过使用config.background_color
在这里找到定制 manim 的其他方法。
我还能拿曼尼姆怎么办?
用一个移动的框架写出数学方程
您还可以创建一个动画,用如下所示的移动帧编写数学方程:
作者 GIF
或者一步一步地写下如何解方程:
作者 GIF
移动和变焦照相机
您还可以调整相机,并使用从MovingCameraScene
对象继承的类来选择放大方程的哪一部分。
作者 GIF
图表
您还可以使用 manim 来创建一个注释图,如下所示:
作者 GIF
如果你想得到一个场景最后一帧的图像,添加-s
到命令中:
manim -p -qh -s more.py Graph
您也可以通过设置animate=True
来设置轴的过程
$ manim -p -qh more.py Graph
作者 GIF
一起移动对象
您也可以使用VGroup
将不同的 Manim 对象分组,并像下面这样一起移动它们:
作者 GIF
跟踪路径
你也可以使用TracedPath
创建一个移动物体的轨迹,如下图所示:
作者 GIF
概述
恭喜你!您刚刚学习了如何使用 manim 以及它能做什么。概括地说,manim 提供了 3 种对象:
- 移动对象:可以在屏幕上显示的对象,如
Circle
、Square
、Matrix
、Angle
等 - 场景:用于
Scene
、MovingCameraScene
等动画的画布 - 动画:应用于
Write
、Create
、GrowFromCenter
、Transform
等物体的动画
有这么多的人可以做,我不能在这里涵盖。最好的学习方法是通过实践,所以我鼓励你尝试本文中的例子,并查看 manim 的教程。
本文的源代码可以在这里找到:
我喜欢写一些基本的数据科学概念,并尝试不同的算法和数据科学工具。你可以通过 LinkedIn 和 Twitter 与我联系。
如果你想查看我写的所有文章的代码,请点击这里。在 Medium 上关注我,了解我的最新数据科学文章,例如:
如何创建更高效的深度学习模型
方法和技术概述
托马斯·凯利在 Unsplash 上的照片
在这篇文章中,我将介绍和讨论几种重要的方法和技术,这些方法和技术可以帮助在不同层面上提高深度学习模型的效率。这些类型的优化现在变得更加重要,因为深度学习模型的新改进也带来了参数数量、训练资源要求、延迟、存储要求等的增加。
我将讨论的主要议题如下:
- 按压手法
- 学习技巧
- 高效架构
- 自动化
压缩技术
这些类型的技术以整个模型的表示效率为目标,这是可能的,主要是因为许多最先进的模型是过度参数化的。主模型的多个组件可以受益,而不会影响(在一定范围内)对原始版本计算的评分结果,例如训练时间、推理延迟、内存占用。通过压缩神经网络模型的计算图的一部分,我们还可以提高其泛化能力。
这里探讨了多种想法,其中一些最成功的是:
- 修剪 —指的是使用各种策略从神经网络中删除一组参数或将其设置为零,以挑选受影响的权重,从而获得一个不需要像以前那样多内存的稀疏网络。最流行的剪枝策略基于:**显著性、随机结构化/非结构化、调度、稀疏预算分布、再生长。**通常在修剪后,建议对生成的模型进行微调。
PyTorch 中的模型修剪示例:
**import** torch.nn.utils.prune **as** prune**model** **=** **Model()****layers_to_prune** **=** **(**
**(model.conv1,** 'weight'**),**
**(model.fc1,** 'weight'**)**
**)**// This will prune 20% of the parameters with lowest L1-norm
**prune.global_unstructured(**
**layers_to_prune,**
**pruning_method=prune.L1Unstructured,**
**amount=**0.2**,**
**)**
- 量化 —降低用于模型权重和激活的数据类型的精度(例如:从 32 位浮点值降低到 8 位定点)。大多数时候,当我们应用量化时,我们可以看到内存占用和延迟方面的改进。通常有两种量化方式:后培训和量化感知培训;我认为这些术语大多是不言自明的(至少从高层次的角度来看),唯一需要提到的是,第一个术语可能会影响用于推断的模型的质量。
PyTorch 有多种量化策略,下面是最简单的一种:
**quantized_model=** **torch.quantization.quantize_dynamic(**
**model,**
**qconfig_spec={torch.nn.Linear},**
**dtype=torch.qint8**
**)****//**qconfig_spec specifies the list of submodule names in model to apply quantization to.
- 基于矩阵的压缩技术:低秩逼近、字典学习、层拼接等。
学习技巧
这些类型的技术试图通过改变训练过程的某些方面来提高模型的质量。通过只针对培训阶段,验证/测试得分应该保持对生产的代表性。
学习技巧的类型:
- 蒸馏 —对于这种方法,我们引入了“学生”网络和“教师”网络的概念。基本上,我们有一个或一组较大的网络在“教导”较小的网络来重现整个过程或只是一些中间的表现。我们还可以使用教师网络来创建软标签,我们可以在损失函数中使用这些软标签以及地面真实标签,其想法是软标签可以捕捉类之间的一些关系,这可以帮助训练。
- 数据扩充 —当处理深度模型时,我们通常需要大量的样本来确保我们的模型能够一般化。但是,由于特定数据类型的高成本或稀缺性,这有时会成为一个问题。数据集大小问题的一个可能的改进是数据扩充,它基本上是一套通过应用某种变换或插值来生成合成样本的方法。大多数数据增强技术针对计算机视觉任务,例如:调整大小、旋转、翻转、裁剪等。
在 PyTorch 中,我们可以堆叠多种类型的转换,并在自定义数据集类中直接使用它们:
train_transforms = A.Compose(
[
A.Resize(width=320, height=320),
A.RandomCrop(height=728, width=728),
A.HorizontalFlip(p=0.5),
A.VerticalFlip(p=0.5),
A.RandomRotate90(p=0.5),
ToTensor(),
]
)
- 自我监督学习(Self-Supervised Learning)——代表了对没有足够大的标签数据集的“老”问题的最有趣的解决方案之一。当应用自我监督学习方法时,我们使用未标记的数据创建了一个“借口任务”,允许我们生成良好的表示,这些表示可以在以后用于更具体的任务。一旦我们有足够好的嵌入,我们可以添加一个预测头,并用标记的数据微调模型。例如,在 NLP 中,应用自我监督来预测未标记句子中的屏蔽词是相当常见的。在 CV 中有对比学习的概念,其中模型被训练来区分不同的图像。由于对标记数据的要求较低,这种技术被认为是数据高效的。
高效架构
提高深度学习系统效率的另一种方法是后退一步,尝试在模型的架构层面解决问题,一些神经网络层设计更适合特定的任务或数据类型。
接下来,我将尝试向您展示几个模型架构设计的示例,这些设计为计算机视觉和自然语言处理带来了一些改进:
- 计算机视觉:卷积层 —这种类型的层彻底改变了计算机视觉领域。它利用了图像特征的空间位置,通过堆叠它们,它创建了多级表示,从而允许在后面的层中检测更复杂的特征。此外,因为卷积操作对整个图像重复使用相同的滤波器,这也大大减少了模型的参数数量。
- 自然语言处理:变形金刚——给 NLP 领域带来了巨大的改进(从注意力是你所需要的, Ashish Vaswani 等开始),使用这种类型的神经网络的主要优势是它消除了只有单一特征向量来表示整个输入序列上下文的瓶颈。Transformer 体系结构使用自我关注和交叉关注来编码序列中每个输入元素的上下文。这里的是一个很棒的课程,解释了变压器的基本原理和用法。
自动化
寻找提高机器学习模型效率的新途径的另一种方法是通过使用不同的自动搜索技术来“强力”搜索不同的想法。最大的缺点是基于搜索的方法需要大量的计算资源和时间。
我们可以通过考虑搜索空间的级别来划分自动化的类型:
- 超参数优化(HO) —顾名思义,这种类型的自动化试图通过改变一些超参数的值来搜索更有效的模型,如学习速率、层数、重量衰减、批量等。即使我们使用 k 折叠分裂策略来迭代每个折叠中超参数的不同值,也仍然需要大量的计算来遍历它们。有几种搜索策略我们可以遵循: 网格搜索、随机搜索、贝叶斯搜索、由粗到细搜索。
- 神经架构搜索(NAS) —这可以被认为是超参数优化的扩展,允许搜索空间中的其他元素,如不同的操作块(卷积、线性层、池)以及组合它们的不同方式。此外,对于 NAS,研究人员还使用强化学习来寻找更好的体系结构。
最后,我在这篇文章中列出的列表绝不是全面的,还有许多正在进行的研究努力试图改善深度学习系统的每个瓶颈。
感谢您的阅读,如果您想了解最新的机器学习新闻和一些优质的模因:),您可以在 Twitter 上关注我这里。
资源
- https://py torch . org/blog/introduction-to-quantization-on-py torch/
- https://blog . tensor flow . org/2020/02/matrix-compression-operator-tensor flow . html
- 高拉夫·蒙哈尼:高效深度学习:关于让深度学习模型更小、更快、更好的调查(https://arxiv.org/abs/2106.08962)
如何使用 Python 创建 PDF 报告——基本指南
在 10 分钟或更短时间内创建具有漂亮可视化效果的 PDF 报告
杰西·G-C 在 Unsplash 上的照片
报告无处不在,因此任何技术专业人员都必须知道如何创建它们。这是一项乏味且耗时的任务,这使得它成为 Python 自动化的完美候选。
无论您是数据科学家还是软件开发人员,都可以从自动报告生成中受益。例如,数据科学家可能会使用报告来显示机器学习模型的性能或解释。
本文将教您如何制作基于数据可视化的报告,并将它们保存为 pdf。更准确地说,您将学习如何将多个数据可视化(虚拟销售数据)合并到一个 PDF 文件中。
最棒的是——这比你想象的要简单!
这篇文章的结构如下:
- 数据生成
- 数据可视化
- 创建 PDF 页面结构
- 创建 PDF 报告
- 结论
你可以在这里下载源代码为的笔记本。
数据生成
没有数据就没有报告。这就是为什么您必须首先生成一些——稍后再详细介绍。
让我们从进口开始。你将需要很多东西——但是FPDF
库可能是唯一未知的。简而言之,它用于创建 pdf,稍后您将使用它。请参考下面的导入代码片段:
接下来我们生成一些假数据。其思想是声明一个函数,该函数返回给定月份的虚拟销售数据的数据帧。它通过构建整个月的日期范围,然后将销售额作为给定范围内的随机整数来分配。
您可以使用calendar
库来获取任意年/月组合的最后一天。以下是完整的代码片段:
对generate_sales_data(month=3)
的调用产生了 2020 年 3 月的 31 个数据点。下面是前几行的样子:
图 1 —生成数据的样本(作者提供的图片)
就这样——您现在有了一个生成虚拟销售数据的函数。接下来我们来看看如何可视化。
数据可视化
您的下一个任务是创建一个函数,将之前创建的数据集可视化为一个线图。当您处理时间序列数据时,这是最合适的可视化类型。
下面是数据可视化的函数和一个调用示例:
简而言之——创建数据可视化、设置标题、摆弄字体——没什么特别的。可视化结果不会显示给用户,而是保存在机器上。稍后您会看到这有多么强大。
示例调用将保存 2020 年 12 月的数据可视化。它看起来是这样的:
图片 2—2020 年 12 月的销售图(图片由作者提供)
这就是你的视觉化功能。在创建 PDF 文档之前,只剩下一个步骤,那就是保存所有的可视化并定义报告页面结构。
创建 PDF 页面结构
现在的任务是创建一个执行以下操作的函数:
- 为图表创建文件夹—如果存在,则删除并重新创建
- 保存 2020 年除一月之外的每个月的数据可视化,以便您可以看到如何在每页上使用不同数量的元素(也可以随意包含一月)
- 从可视化效果创建 PDF 矩阵,这是一个二维矩阵,其中一行代表 PDF 报告中的一个页面
下面是该函数的代码片段:
可能有很多东西需要消化,所以一行一行地看一遍。这些评论应该会有所帮助。排序背后的想法是从字符串中获取月份的整数表示—例如,从“3.png”中获取 3,并使用该值对图表进行排序。如果顺序无关紧要,请删除这一行,但月份就不是这样了。
下面是一个调用construct()
函数的例子:
运行上述代码片段后,您应该会在笔记本中看到以下内容:
图片 3 —生成的可视化效果(作者提供的图片)
如果你想知道——这是我的机器上的plots/
文件夹的样子(在调用了construct()
函数之后):
图 4 — PDF 报告内容矩阵(图片由作者提供)
这就是构建 PDF 报告所需的全部内容—接下来您将学习如何完成。
创建 PDF 报告
这是一切汇集的地方。现在您将创建一个从FPDF
继承而来的自定义PDF
类。这样,所有的属性和方法在我们的类中都是可用的,如果你没有忘记在构造函数中调用super().__init__()
的话。构造函数还将保存页面宽度和高度的值(A4 纸)。
您的PDF
类将有几个方法:
header()
–用于定义文件标题。自定义徽标放在左边(确保有一个或删除此代码行),硬编码文本放在右边footer()
–用于定义文档页脚。它只会显示页码page_body()
–用于定义页面的外观。这将取决于每页显示的可视化效果的数量,因此位置和边距会相应地设置(您可以随意调整这些值)print_page()
–用于添加空白页并填充内容
以下是该类的完整代码片段:
现在是实例化它并从二维内容矩阵中追加页面的时候了:
上面的单元需要一些时间来执行,完成后将返回一个空字符串。这是意料之中的,因为您的报告保存在笔记本所在的文件夹中。
报告的首页应该是这样的:
图 PDF 报告的第一页(图片由作者提供)
当然,由于不同的标志和完全随机的销售数据,你的看起来会不同。
这就是如何用 Python 创建数据可视化的 PDF 报告。接下来让我们总结一下。
结论
今天,您已经学习了很多东西——如何为任何场合创建虚拟数据,如何将其可视化,以及如何将可视化嵌入到单个 PDF 报告中。嵌入可视化只需要最少的代码修改——主要是定位和边距。
如果你想看基于机器学习模型解释(SHAP 或莱姆)或其他与数据科学相关的东西的自动化报告创建指南,请告诉我。
感谢阅读。
喜欢这篇文章吗?成为 中等会员 继续无限制学习。如果你使用下面的链接,我会收到你的一部分会员费,不需要你额外付费。
https://medium.com/@radecicdario/membership
加入我的私人邮件列表,获取更多有用的见解。
了解更多信息
- 2021 年学习数据科学的前 5 本书
- SHAP:如何用 Python 解释机器学习模型
- 三大分类机器学习指标—一劳永逸地消除准确性
- ROC 和 AUC——如何评估机器学习模型
- 精确召回曲线:如何轻松评估机器学习模型
原载于 2021 年 1 月 18 日https://betterdatascience.com/create-pdf-reports-with-python/。
如何打造完美的 AI 战略
人工智能笔记
深入了解人工智能战略的三大支柱
工作室 Kealaula 在 Unsplash 拍摄的照片
大多数技术都是从行业内的大肆宣传开始的,并逐步失去人们的关注,因为它们在解决现实世界的问题时不能满足我们的期望。人工智能是仅有的几项达到并超过预期的最新技术之一。然而,如果我们在追求人工智能发展方面没有一个坚实的战略,这项技术可能会像其他技术一样最终走向相同的终点。人工智能战略有三个主要支柱:可行性、性能和可扩展性。如今,每个人都在谈论人工智能模型的潜力,但我想指出为了创造一个完美的人工智能战略必须仔细研究的问题。有了坚实的人工智能战略,你就增加了构建人工智能产品的成功几率。出于同样的目的,我最近写了一篇关于如何创建完美数据策略的文章。你可以在下面找到。
—可行性
要构建和推出一个人工智能产品,你会遇到许多挑战。如果你认为在人工智能世界里一切都是可行的,你可能会很容易失望。许多公司开始开发一种人工智能产品,在中途,发现它对他们不起作用。这造成了失望,更重要的是,阻止了他们正确使用人工智能并为企业创造价值。强烈建议在开始实施人工智能产品之前与人工智能专家进行头脑风暴,并以你的人工智能任务为短期目标。
例如,在一些应用中,必须在设备级别(也称为边缘人工智能)实现人工智能模型,以遵守数据隐私法案。当 AI 模型在最接近数据收集的点实现时,隐私问题被最小化。然而,在这个级别实现人工智能模型会产生许多问题。例如,你在这个层次上没有强大的计算能力。或者,你不能很容易地在那些与 edge AI 兼容的语言(如 C)上实现你用高级编程语言(如 Python)开发的东西,因为所需的库不存在。再比如,你开始为一个应用开发深度学习模型。然后,你发现所需的计算能力或深度学习专家对你来说是不可及的,或者不是以一种经济高效的方式。在那一点上你必须三思。你可以阅读更多关于大公司在分析构建人工智能产品的可行性时所犯的错误。
https://pub.towardsai.net/ai-strategy-a-battlefield-that-even-big-firms-struggle-539a9f3df396
要创建一个完美的 AI 策略,你必须有一个计划来保证技术上的可行性。为实现一个强大的人工智能模型的复杂性做好准备。
—性能
您可能会说“在文献中存在许多标准的度量标准来帮助人们评估模型的质量。因此,人工智能模型的性能很容易衡量。”不幸的是,我必须说这并不完全正确。一个主要问题是,您只能在您收集的数据范围内衡量性能。换句话说,您必须始终处理样本外错误(也称为泛化错误)。**没人能保证你的用户数据是什么样的。**你可以尽最大努力使用与真实世界数据高度相似的数据集来评估 AI 模型;然而,你总是会惊讶于从未预料到的新情况。
更重要的是,大多数时候(如果不是总是)你不能保证一个人工智能模型的最差性能。存在许多方法来减少概括误差;然而,他们不太成功地给它划定界限,特别是在深度学习模型等灰箱模型中。此外,输入数据中的小扰动可能会导致结果不稳定,这在许多使用情况下是不可接受的。你可以在下面的文章中了解更多关于如何管理人工智能模型的性能。
要创建一个完美的 AI 策略,你必须有一个评估 AI 模型的计划。超越标准指标思考!
—可扩展性
为试点项目建立人工智能模型很容易。然而,当你决定建立一个人工智能产品时,它变得更加困难,当你决定扩展它时,它变得更加困难。帕累托原则(也叫 80-20 法则)在这里也是有效的。一般来说,你可以用 20%的努力建立一个符合你 80%预期的 AI 模型。剩下的 20%的期望将会很难实现,这会让你震惊,尤其是当你想要扩展产品的时候。
例如,可伸缩性挑战源于收集大量干净且有标签的数据,并构建一个可以解决大多数用例的通用模型。人工智能模型的质量与其数据的质量一样好。因此,你必须确保用于训练人工智能模型的数据集是全面的,并涵盖大多数用例。实际上,训练数据集并不是普遍完整的。这就是为什么在构建人工智能模型时,你总是会遇到偏差-方差的权衡。例如,这种权衡基本上迫使您降低当前数据集中的精度,同时希望提高尚未收集的数据集中的精度。
最后,但同样重要的是,您经常需要构建各种上下文化的模型来处理不同的上下文。用一个模型来处理各种不同的环境通常是不可能的。这就是为什么 AI 聊天机器人必须为每个行业专门设计才能使用。你可以在下面的文章中阅读更多关于帮助我们管理情境化模型的人工智能模型的信息。
为了创造一个完美的人工智能战略,你必须有一个计划来扩大人工智能模型的规模。请注意,达到您预期的 80%并不意味着您有一个案例!
感谢阅读!
如果你喜欢这个帖子,想支持我…
https://pedram-ataee.medium.com/membership
如何创造依赖机器学习的产品
产品团队用机器学习来平衡特定风险并增加开发成功产品的可能性的框架
创造依赖机器学习等技术的产品,与普通产品相比,有着不同的考虑因素、风险和限制。为了在你的产品工作中取得成功,开发过程应该承认这些固有的挑战并直面它们——即使这可能不适合你的开发团队
由 Austin Distel 在 Unsplash 上拍摄
你真的对工作中的新项目感到兴奋。你正在与贵公司最强的工程师和科学家团队合作开发一个很酷的新产品,其核心是使用定制的机器学习方法来交付成果。具体来说,它可以是一个决定何时为零售商店重新进货并自动规划卡车运输的工具,也可以是一个新的应用程序,帮助你的客户在购买前预览你的家具在他们家中的外观,一个用于你公司生产线的自动故障检测系统或完全不同的东西。
每个人都开始为这个项目工作。大量的技术设计和开发工作。三个月来,数据科学家正在研究一种复杂的新深度学习架构,并在使其工作方面遇到了困难。工程师们已经创建了一个非常乏味的应用程序,但在模型准备好之前,他们真的不知道如何进行。与此同时,管理层在要求地位,团队中的能量,曾经因为兴奋而非常高,现在随着沮丧而下降。
经过长时间的延迟,试点产品终于推出了,然而不知何故,预期用户并没有真正拿起它。管理层不高兴,技术团队也不高兴。一些工程师和科学家感觉自己很失败,有些人甚至感觉他们在公司的地位下降了。
如果你经历过类似上述场景的事情,你并不孤单。**成功打造使用机器学习[1]作为核心技术的产品与其他数字产品计划不同。**指标很多:“人工智能项目”的失败率据说大大超过 50 %(尽管很难获得确切的数字)[2,3],对许多人来说,超越试点或概念验证已被证明是一个挑战[4,5],人工智能人才的整体保留是一个巨大的挑战[6]。虽然该技术本身在过去十年中已经从令人兴奋的发展成为相当主流的技术,许多发展改善了可访问性,但在产品人员和技术人员之间仍然没有就如何进行机器学习产品开发达成共识,尽管似乎有一些理解,即机器学习产品开发的技术要求和风险概况不同于普通的数字产品,并且需要一些调整。
**产品工作失败的一个关键原因是数据科学家和产品人员对风险没有相同的理解,并且在解决这些风险的顺序上存在分歧。**由于主要关注“核心智能”,数据科学家将直观地关注模型开发的应用研发,以探索技术可行性;这是一项耗时的探索性工作,通常以非线性方式进行。另一方面,产品领导者将更关心以对公司有益的方式创造强大和用户友好的价值主张(考虑价值、合意性和可行性以及技术可行性的组合[7]),并将希望快速迭代以探索这一点。这也是一个非线性的发现过程,只是控制旋钮和成功标准不同。通常,没有人考虑如何确保以新产品所需的速度持续获得正确质量的正确数据。
发现对用户和公司都有用的正确产品,同时不断平衡和最小化价值、合意性、可行性和可行性这四个风险总是很困难的,即使是基于熟悉技术的产品。然而,这四种高级风险对于机器学习驱动的产品有一些特殊的表现,这些表现可能不明显。这些并不能取代四大风险,它们只是四大风险中需要特别关注的关键点。这些是
-
早期在模型可行性评估上花费的时间太少:机器学习的技术可行性受到数据和技能的限制。事后改进机器学习模型,基础强的容易,基础不到位的不可能。如果你假设的模型在科学上是不可能开发出来的,那么它会扼杀你的整个产品。因此,你应该遵循#monkeyfirst 原则[8]:首先做困难的事情,如果它们是不可能的,你必须评估另一种方法是否可行,或者放弃这个产品想法。
机器学习的限制因素是 a)你是否有持续和及时地访问正确的数据,b)你是否有开发和部署正确模型的技能,因此在产品开发的早期就必须在这些方面建立正确的信心水平。
-
**早期(在验证产品之前)在机器学习模型上花了太多时间。**改进模型性能非常耗时,但这可能是对时间的极大浪费,除非已经证实我们提供给用户的产品也通过这种努力得到了改进。因此,第一个风险是确保足够深入地评估机器学习是否可行,第二个风险是过早地过度投资,忽视用户的需求(价值和愿望的风险)。
-
不满的数据科学家。数据科学家非常喜欢研究机器学习模型,如果有选择的话,他们更喜欢研究更高级的模型,这样可以增长他们的技能和经验。另一方面,许多数据科学家在构建部署机器学习模型的系统方面不如软件工程同行强大,并且数据科学家也经常觉得他们不应该做这项工作。
如果将上述前两种风险放在心上,数据科学家就有理由担心他们是否能够利用自己的核心竞争力。一旦产品 MVP 证明了对用户的价值,就有时间这么做了。尽管如此,这可能会导致沮丧和高流动,除非及早和适当地解决。
对期望的结果和达到目标的风险达成共识,并同意允许团队解决这些问题的开发方法是关键。技术团队经常忘记的是,预期的结果是解决重要、有价值的问题的出色用户体验——工作机器学习技术本身是不够的。事实上,处理异常以及用户如何对机器学习预测采取行动是成功的关键,但通常完全位于机器学习技术本身之外。很难对风险和挑战保持清醒的认识,尤其是在团队还在学习价值主张和技术挑战的早期。尽早就期望的用户结果和开发方法进行公开的对话,并在此之后定期检查,以在需要时进行重新评估和调整,这仍然是至关重要的。
基于机器学习的产品开发方法
下面的方法融合了第一手经验和其他团队的观察,试图达到良好的平衡。就像任何其他创造性的追求一样,你不应该以拥有一个完美的过程为目标,而是试图创造伟大的(“完美的”)结果,并尊重你将在过程中学习到的东西:因此,预计这有时会变得混乱,并且会犯错误。也就是说,希望下面的方法将强调最关键的风险是如何在开发过程中变化的,并希望为技术团队和产品负责人提供一些视角。
考虑到最大的风险是产品是否会引起用户的共鸣,以及机器学习的预期用途是否可行,在发现过程中使用步骤 1a 和 1b 来解决这些风险,同时迭代出可行的解决方案。一旦达到初始牵引力,步骤 2a 和 2b 着重于改进或扩展产品。在发现阶段会测试许多不同的想法,开发会产生许多不同的结果。当一个 MVP 被开发出来的时候,过程就变得更加狭窄了。作者插图。
这种方法实际上就是识别前面提到的哪些产品风险在哪个阶段最大,以及如何解决这些风险的一些建议。希望这能让你在开发新产品的时候走得更快,增加你的信心和成功的可能性。在探索可能使用机器学习的新产品的过程中,两个重要的风险是所提议产品的技术可行性和用户的合意性,即该产品是否以吸引人的方式解决了一个重要问题(上面强调的前两个风险)。在产品发现过程中,解决这个问题的最好方法是在速度和细节之间找到平衡点,从而确定一个吸引用户的有价值的产品,并且这个产品在技术上也是可行的。前两个步骤(1a 和 1b,见图)是关于执行适当数量的发现/开发周期,以找到我们有信心在技术上能够制造的强有力的候选产品。迭代步骤 1a 和 1b 的结果是一个最小可行产品(MVP ),我们可以从中学习。
大部分技术开发将发生在步骤 2a,这是所有关于产品的成熟。这是很多详细的机器学习优化、数据管道优化等的地方。会发生。最后,步骤 2b 是扩展更多功能的通用产品方面。
步骤 1a:用技术解决问题是否可行?
当产品经理提出一个想法时,技术团队的工作就是评估通过技术解决它是否可行。尽管在早期发现阶段,你不应该过早地专注于某个特定的技术解决方案,但你仍然需要树立信心,相信可以开发出技术上可行的解决方案*。否则你就不知道如何构建产品,你应该把注意力转移到另一种满足用户需求的方式上。*
这并不是说“我们有技术,现在让我们寻找一个问题来解决”,但是即使当把用户问题放在中心位置时,团队的技术能力和问题的背景在交付解决方案的技术可行性中也起着重要作用。
因此,第一步的目标是在足够详细的程度上考虑潜在技术解决方案的细节,同时仍然能够保持适当的速度。具体来说,这意味着评估您的团队和您的产品建立机器学习技术来交付用户问题所需的解决方案(包括对模型性能的一些粗略了解)是否现实,确保在进行预测时机器学习的数据可以始终如一地来源于产品,并建立可行的方法来衡量性能。**
举一个重要的例子,无法一致地获取和清理模型运行所需的数据通常是一个巨大的挑战,因为不存在如何获取数据的途径。一个常见的原因是在静态数据集上训练的模型,当转换为产品时失败,因为没有充分考虑如何控制数据生成过程[9]。在发现阶段就考虑建立一个良好的数据生成过程的可行性是非常重要的:这不仅可以节省大量的时间、金钱和麻烦[10],而且数据获取策略的缺乏将会停止扩展,从而在产品上市之前就扼杀你的产品。
机器学习模型和数据采集的可行性评估通常是通过概念的技术证明来完成的,但如何进行当然可以有所不同。无论你怎么做,都是为了在产品团队中建立信心,相信这些挑战是可以解决的。虽然在某些情况下可能会发生,但如果在这个阶段进行高级数学建模,我会感到惊讶;更确切地说,它是关于确定问题是否可以用数学建模的方式来表达,确定模型性能(准确性、提供结果的时间等)的早期信心。)是否可以通过微调达到所需的水平,以及所需的数据材料是否可以持续获得。
步骤 1b:专注于向用户证明价值主张
第二步是面向用户的,类似于第一步:产品发现,即确定如何塑造产品以使其对用户既有价值又有吸引力的过程。我将这两个步骤命名为 1a 和 1b,以表明它们应该被同时处理[11]。预计 1a 和 1b 将是产品与市场匹配的迭代循环。
目标是为用户探索价值驱动因素,以了解如何设计和构建产品。也就是说,这是确定我们相信哪些想法来开发 MVP 以与用户进行测试的过程,所有这些都是为了确定一个强有力的价值主张。一个关键问题涉及识别用户眼中机器学习的实际价值驱动因素,包括如何以一种允许用户尽可能容易地采取正确行动的方式呈现机器学习的结果。细节当然会非常依赖于上下文,但汽车导航系统提供了一个很好的例子:要想成功,这种系统需要能够通过 GPS(机器学习和优化)提供一个好的计划,及时的口头更新(解释与运动相关的结果)是成功的关键。前者需要良好的规划能力和体面的计算速度,而后者的低延迟,以不断能够评估汽车相对于计划的位置,这是有用和无用产品之间的区别。
在这个阶段成功的关键是能够快速评估想法是否可行,我们寻找的信号是我们是否给了用户他们真正需要的东西。结果是,现在是简单、现成的机器学习模型的时候了(或者可能是一个模仿的模型,即根本没有实际的模型!);一旦确定问题可以用机器学习来解决(步骤 1a 的问题已经解决),就没有更多工作要做了。
然而,作为探索可能的价值主张的一部分,探索如何向用户呈现结果通常是相关的。也就是说,哪些指标最能向用户传达信息?结果应该如何呈现(在图表中?作为推荐动作?)以及用户是否能够交互式地探索结果(例如,在上述示例中,在汽车导航系统的地图中四处移动)。准确性和服务时间的相对重要性是什么?显示结果的正确粒度级别是什么?一个 GPS 只能引导你从一个城市到另一个城市,但没有在城市中引导你的分辨率,对大多数人来说不是特别有价值。所有这些问题都处于产品和数据科学的界面上,找到好的解决方案将决定最终产品的成败。
步骤 2a:使产品成熟:提高机器学习性能和价值交付
当你发现了一种既有价值、又令人满意且可行的产品时,科学和工程开发工作就可以开始提高机器学习能力了。这是详细的改进工作,其中解决方案得到强化,新的机器学习架构和模型类型得到彻底探索,边缘情况得到处理等。要明确的是,技术和用户体验的成熟适用于产品的所有方面,而不仅仅是机器学习;在接下来的内容中,我将只关注对机器学习部分特别重要的一些方面,它们是扩展和长寿的基础。
在这一阶段,监控和再培训策略是根据步骤 1a 中的草图制定的,以便为产品提供支持,这一领域也称为 MLOps[12–14]。大多数机器学习(以及其他类型的应用数学引擎)都会随着时间的推移而恶化,而 MLOps 可以确保我们监控性能并主动调整模型,以便它们继续为产品提供工作。没有 MLOps,机器学习模型将很快停止产生有用的结果,产品将毫无用处。产品经理应与技术团队一起在定义 MLOps 战略中发挥积极作用,以确保用户价值主张是首要关注点,关键机器学习性能指标应成为产品经理每日审查的 KPI 的一部分。
MLOps 的一个部分需要特别提及,因为最佳解决方案通常是通过产品设计:数据恶化。有时候,在产品上线后,一个或几个数据源开始转移。在营销情况下,这可能发生在引入之前不属于改变行为的数据集的新产品时(甚至可能是引入我们自己的产品),这可能是新的法规(例如 GDPR),而在其他情况下,这可能是由于物理传感器的退化、生产线图像的上下文变化(背景中的混乱)等。MLOps 将允许主动解决数据中的变化,但它不能保证机器学习模型的质量得以保持。解决这一问题的最佳方式是设计产品,使您能够控制数据生成,或者产品的定位使价值主张在模型无法运行时不会恶化。确定解决这些问题的策略是一个产品问题,应该是一个主动的选择。
步骤 2b:开发产品,但要警惕模型出错带来的意外事故
在讨论本节的细节之前,需要澄清机器学习模型的一些方面。作为开发过程的一部分,这些模型根据历史的、有代表性的数据进行“训练”(拟合),以使其预测能力适合您正在处理的特定问题和数据。但是,如果在模型训练的数据域之外应用,性能通常会下降,如果数据生成过程(例如,不同的用户行为)和我们测量数据的方式(例如,使用不同的传感器读取一个数据源)发生变化,都会发生这种情况。这些方面对如何扩展机器学习驱动的产品有一些影响。
如果事情进展顺利,产品将在某个时候需要扩展。扩展机器学习模型的服务和操作是一项技术挑战(本身就具有挑战性),只要它发生在相同的用户群中,但扩展到新的用户组或细分市场会带来额外的复杂性,因为数据生成过程可能会发生变化。在这种情况下,密切监控通常是一个好策略:由于机器学习模型通常用于帮助决策,并且由于新用户组的决策和/或行为可能与之前的细分市场不同,这些变化将反映在数据和性能监控中。如果有理由相信新的目标用户组具有不同的行为,或者如果数据生成过程的部分对于这个新的组是不同的,则应该预期添加这个新的组将需要调整机器学习模型本身(基本上经过步骤 1a、1b 和 2a),而不仅仅是在这个新的段上打开现有模型的开关。以我们之前使用的 GPS 为例:将英国作为一个新的国家需要对路由引擎进行重大调整,因为所有的路由决策都会受到左侧驾驶的影响。关键的标注是让团队意识到这项重要的工作,并在正确的时间点将它考虑进去。
与任何产品一样,一旦我们推出了具有良好吸引力和规模的产品,“最后”一步是通过添加更多功能来继续改进产品。这包括发现、原型和用户验证的连续循环,以确定每个新功能的产品市场适应性,这在别处有很好的描述[7]。这些新功能中的一些可能是新的基于机器学习的解决方案,与核心产品没有技术关系,如果是这样,它们的开发将遵循上述步骤。这里需要注意的是,任何改变用户行为的新功能也会影响(潜在地破坏)支持传统功能的现有机器学习模型。例如,一家全球能源公司的人力资源部门对每名新员工在公司未来成功的可能性进行评分,但同时将该分数与绩效和其他变量一起使用,以确定哪些员工将获得发展机会;由于这种(可能是无意的)负面反馈循环,在加入时得分不高的人没有获得同样的机会,导致整体人才库的多样性下降和员工流动率上升。注意这些非直观的依赖关系是很重要的,同样重要的是要意识到这些依赖关系可能只存在于某些细分市场中,甚至可能会因细分市场而异。除了对风险本身的认识之外,努力测量现有模型对用户行为和性能的影响,并在引入新功能时进行受控实验,是避免意外颠覆您之前成功的最佳实践。
确认
Simon Kiilerich Vedel(无关系)的一篇全面的评论,包括对这篇文章有重大改进的观点,得到了欣然认可( LinkedIn 简介)。
参考
[1]我在本帖中描述的内容适用于所有使用高级数学建模作为解决问题前提的情况,并不仅限于机器学习问题(甚至适用于传统的数据科学问题)。也就是说,在数学建模、优化和相关领域也会发现类似的挑战。为了简洁起见,我将自始至终使用术语机器学习,但是读者应该记住,所讨论的主题适用范围更广。
[3] Irving Wladawsky-Berger:为什么一些人工智能努力成功而许多努力失败,《华尔街日报》,2020 年 1 月 24 日,https://www . wsj . com/articles/Why-Some-AI-Efforts-success-While-Many-Fail-01579901883
[5]https://www . BCG . com/publications/2019/travel-time-push-ai-beyond-pilot-phase
[7]马蒂·卡甘:灵感,https://svpg . com/Inspired-how-to-create-products-customers-love/
[8]天文柜员:先擒猴子,2016https://blog . x . company/先擒猴子-90fd6223e04d
[9] Will Douglas Heaven:谷歌的医疗人工智能在实验室中非常准确。现实生活是一个不同的故事。麻省理工科技评论 2020 年 4 月 27 日,https://www . Technology Review . com/2020/04/27/1000658/Google-medical-ai-accurate-lab-real-life-clinic-covid-diabetes-retina-disease/
[10]吴恩达:人工智能对你的企业来说不必太复杂或昂贵,《哈佛商业评论》2021 年 7 月 29 日https://HBR . org/2021/07/AI-不必对你的企业来说太复杂或昂贵
[11]这篇文章关注的是向用户证明价值是挑战的一部分的情况,因为这是从初创公司到企业普遍面临的情况。但是,应该注意的是,有些领域的价值主张很明确,工作流程/产品开发工作旨在迎合对机器学习的依赖,例如助听器和其他嵌入式信号处理、期权定价和银行欺诈检测等。在这些情况下,步骤 1b 试图缓解的问题就不是大问题了。
[12]对于专家:我自由地使用术语 MLOps,因此它也包括 DataOps(相当于 DevOps 的数据)。这两者之间有着重要的差异,但就这篇博文的目的而言,它们是如何大规模运营机器学习和数据产品的同一问题的两个方面。
[13]https://en.wikipedia.org/wiki/MLOps
[14] Terence Tse 等人,你的人工智能项目将失败的愚蠢原因,哈佛商业评论,2020 年 1 月 8 日,https://HBR . org/2020/06/The-Dumb-Reason-Your-AI-Project-Will-Fail
如何使用 LaTeX 创建出版就绪的绘图
实践教程
使用 LaTeX 启动你的绘图之旅,使用 5 种基本的绘图变化
介绍
如果你曾经在科学杂志上写过一篇文章,那么你很有可能使用过乳胶模板来准备你的手稿。毕竟这是排版文档的行业标准。然而,你们中有多少人考虑过将 LaTeX 作为绘图工具?
LaTeX 基于其图形系统 PGF/TikZ 提供了一个强大的可视化库 PGFPlots。这使得直接在您的。tex 文档。它有一个简单的用户界面,即使是业余程序员也能轻松掌握。然而,我们在网上还有各种各样的绘图选项。无论是流行的数据科学编程语言,如 Python 和 R,它们拥有自己令人印象深刻的数据可视化库,还是绘图软件,如 Origin、Veusz、GraphRobot 和 Orange。大多数这样的选项还提供了处理非常大的数据集和执行复杂的数学计算的灵活性,不幸的是,PGFPlots 库没有这种灵活性。但是,如果这些缺点对您来说不构成问题,PGFPlots 库肯定会为您呈现与当今大多数其他可用选项相比质量最高的图。
然而,尽管不像其他语言/工具那样陡峭,使用 LaTeX 绘图也有自己的学习曲线。PGFPlots 确实提供了自己的综合手册,但是你需要知道在那里搜索什么才能找到你的答案!而且,很多时候,我们寻找的是抽象的想法,而不是完整的图片。这就是像 tex.stackexchange.com 这样的网站来拯救我们的地方。即便如此,在我挖到金子之前,我仍然不得不翻遍成吨的 stackexchange 帖子,经历无数次反复试验。因此,我决定写这篇文章。我希望通过研究科学出版物中可能遇到的 5 种基本绘图类型,向您介绍 LaTeX 绘图的基本知识。每个图将关注 PGFPlots 库中可用的不同类型的定制。要理解本文,您只需要对 LaTeX 有基本的了解。当然,这只是开始您的 LaTeX 绘图之旅。我希望在以后的文章中深入探讨更复杂的情节,因此可以将此视为一系列文章的背景。
所以事不宜迟,我们开始吧!
使用 PGFPlots 绘图
让我们从设置 LaTeX 中绘图的文档序言开始。和其他人一样。tex 文件,我们将从使用\documentclass
命令定义我们的文档类型开始。我们还将为我们的文档添加推荐的编码包。因为我们使用 PGFPlots 绘图,所以我们将调用 PGFPlots 包。下一行中的\pgfplotsset
命令用于为整个文档(或者,正如我们稍后将看到的,文档的一部分)定义一组特定的选项。在这种情况下,我们将整个文档的兼容性选项设置为PGFPlots 1.9
,以确保向后兼容性。注意:最好总是在序言中包含这一行,以避免由于版本更新而导致输出发生变化。
\documentclass[12pt, a4paper]{article}
\usepackage[utf8]{inputenc}
\usepackage{pgfplots}
\pgfplotsset{compat=1.9}
接下来,让我们使用\pgfplotsset
命令(名为 myplotstyle )为我们的绘图设置一些常见的样式规范。注意:如果需要,我们可以在特定的安讯士环境中覆盖这些样式。
\pgfplotsset{
myplotstyle/.style={
legend style={draw=none, font=\small},
legend cell align=left,
legend pos=north east,
ylabel style={align=center, font=\bfseries\boldmath},
xlabel style={align=center, font=\bfseries\boldmath},
x tick label style={font=\bfseries\boldmath},
y tick label style={font=\bfseries\boldmath},
scaled ticks=false,
every axis plot/.append style={thick},
},
}
上述样式选项的简要描述:
legend style
、legend cell align
、legend pos
:用于图例造型;在这种情况下,设置一个无边框、\small
字体、左对齐文本的图例,并放置在绘图的东北方向xlabel style
和ylabel style
:用于改变 x 轴和 y 轴标签样式;在这里,它们用于加粗轴标签(\bfseries
用于文本,\boldmath
用于数字轴标签),并将它们对齐轴的中心x tick label style
和y tick label style
:用于设置轴刻度标签样式;这里,文本和数字记号标签的记号字体都设置为粗体every axis plot./append style
:用于设置一个图内每个轴的样式;这里,图中线条和标记的粗细被设置为thick
。注意:这里,我使用了every axis plot
选项来改变图的线宽scaled y ticks=false
:用于防止 PGFPlots 分解轴刻度标签的公共指数
现在,让我们定义一个简单的绘图环境,使用 myplotstyle 来检查它的外观!用于此目的的代码如下所示:
\begin{tikzpicture}
\begin{axis}[
myplotstyle,
]
\end{axis}
\end{tikzpicture}
使用 myplotstyle 看一个简单的情节(图片由作者提供)
由于 PGFPlots 是基于 PGF/TikZ 的,所以每个情节都应该放在\begin{tikzpicture} ... \end{tikzpicture}
给出的画面环境中。在此范围内,我们将定义一个正常的 axis 环境,并为其设置我们的首选样式。在右边,我们可以看到我们的简单坐标轴图看起来是什么样的!注意:我在最后一个样式选项后加了一个逗号, *myplotstyle*
。虽然这不是必需的,但是这是一个很好的实践。这样,您可以减少在以后引入其他样式选项时可能出现的任何潜在错误。
接下来,让我们继续,看看如何使用数据集来创建绘图。对于较大的数据集,谨慎的做法是保存。csv 文件外部。然而,对于较小的数据集,正如我在本文中所使用的,您总是可以在。tex 文件在\begin{document} ... \end{document}
标签之外。这可以使用以下代码来完成:
\begin{filecontents*}{*filename.csv*}
...
\end{filecontents*}
在这两种情况下,我们都可以使用下一节中描述的相同方法来添加绘图数据。
看起来我们现在都准备好继续策划了。让我们开始策划吧!
1.带标记的折线图
我们将创建的第一个图是一个简单的线图(在我们的例子中,有标记)。我将用于此目的的数据集如下所示。注意:为了简洁起见,我只使用前四个月来解释;但是,我也添加了一个图形,显示了包含整个数据集时我们的图看起来会是什么样子。
flights.csv (数据集由 seaborn.pydata.org 提供)
现在,让我们开始绘制数据集。绘制数据集中的列的格式如下所示:
\addplot+[*<options>*] table[x=*colname*,y=*colname*, col sep=*sep*] {*filename.csv*};
要求在每个\addplot
命令后增加一个;
。注意:也可以用 *\addplot[<options>]*
代替 *\addplot+[<options]*
。两者的区别仅仅在于你是希望将你的 *<options>*
追加到默认的 *cycle list*
(选项控制线条样式)还是完全忽略 *cycle list*
。关于 PGFPlots 中可用的不同 *cycle list*
的详细信息,请参考 PGFPlots 手册 第 4 章第 4.7.7 节。
让我们结合到目前为止所学的知识,使用我们的数据集创建一个简单的线图。到目前为止的代码如下所示:
\begin{tikzpicture}
\begin{axis}[
myplotstyle,
]
\addplot+[] table[x=year,y=Jan, col sep=comma] {Fig_lineplot.csv};
\addplot+[] table[x=year,y=Feb, col sep=comma] {Fig_lineplot.csv};
\addplot+[] table[x=year,y=Mar, col sep=comma] {Fig_lineplot.csv};
\addplot+[] table[x=year,y=Apr, col sep=comma] {Fig_lineplot.csv};
\end{axis}
\end{tikzpicture}
基于默认选项的初始绘图(图片由作者提供)
正如我们从左边的图中看到的,要使这个情节吸引人,还需要做大量的工作。
让我们先处理 x 轴和 y 轴标签!添加轴标签非常简单。只需在轴选项中添加xlabel={Year}
和ylabel={No. of passengers}
。另一个明显的样式是添加图例键。这可以通过添加legend entries={Jan, Feb, Mar, Apr}
来实现。此外, myplotstlye 将图例定位在我们绘图的东北方向。从我们的图中可以看出,在这种情况下,这会阻塞图内容。因此,让我们使用legend pos=south east
将该地块的图例移动到东南方。legend pos
的其他选项有south west
、north east
和north west
。您也可以使用选项outer north east
在绘图外添加图例键。
在绘制的图上有一个明显的错误;每个 x 刻度标签代表一年,但显示时带有逗号分隔符。这可以通过将 x 刻度标签的数字格式更改为:
x tick label style={/pgf/number format/.cd,
set thousands separator={}}
我还希望 x-tick 标签旋转 90 度,所以我也将添加rotate=90
到 x-tick 标签样式。最终轴选项如下:
\begin{axis}[
myplotstyle,
legend pos=south east,
legend entries={Jan, Feb, Mar, Apr},
xlabel={Year},
ylabel={No. of passengers},
x tick label style={rotate=90,
/pgf/number format/.cd, set thousands separator={}},
]
}
让我们现在开始设计我们的线条和标记。这些风格选项将包含在\addplot+[*<options>*]
中。让我们为线条/标记添加以下选项:
smooth
:在两点之间插值,使过渡平滑
2.mark=
:您可以指定您喜欢的标记样式(PGFPlots 手册中提供了marks
选项的详细列表)或使用cycle list
中的默认线条样式。在末尾添加一个*
(比如说triangle*
)表示标记需要填充相应的线条颜色
3.mark options={}
:在这里,您可以指定marker size
,是否希望scale
标记大小、fill
用特定颜色等。
带有选项的示例\addplot
命令如下所示:
\addplot+[smooth, mark=diamond*, mark options={scale=2,fill=white}] table[x=year,y=Jan, col sep=comma] {Fig_lineplot.csv};
而且就是这么简单!最终的代码将如下所示:
\begin{tikzpicture}
\begin{axis}[
myplotstyle,
legend pos=south east,
legend entries={Jan, Feb, Mar, Apr},
xlabel={Year},
ylabel={No. of passengers},
x tick label style={rotate=90, /pgf/number format/.cd, set thousands separator={}},
]
\addplot+[smooth, mark=diamond*, mark options={scale=2,fill=white}] table[x=year,y=Jan, col sep=comma] {Fig_lineplot.csv};
\addplot+[smooth, mark=*, mark options={scale=1.5,fill=white}] table[x=year,y=Feb, col sep=comma] {Fig_lineplot.csv};
\addplot+[smooth,, mark=triangle*, mark options={scale=2,fill=white}] table[x=year,y=Mar, col sep=comma] {Fig_lineplot.csv};
\addplot+[smooth, mark=square*, mark options={scale=1.5,fill=white}] table[x=year,y=Apr, col sep=comma] {Fig_lineplot.csv};
\end{axis}
\end{tikzpicture}
这是最后的剧情结局:
定制后的最终剧情(图片由作者提供)
使用整个数据集的示例图如下所示:
定制后所有月份的最终绘图(图片由作者提供)
2.对数轴图
我们要生成的下一个图是一个简单的对数图。我们将使用这个图来探索两个定制:
- 如何使用 PGFPlots 绘制双对数或半对数图?
- 如何使用中的列数据?csv 文件作为轴刻度标签?
用于该图的数据集如下所示。正如我们从数据集中看到的,它有两列:月份和 2020 年印度马哈拉施特拉邦相应的新冠肺炎确诊病例数。只需要绘制这些列中的一列;另一列将用作 x 轴刻度标签。那么我们如何使用 PGFPlots 来绘制呢?
马哈拉施特拉邦 2020 年每月新冠肺炎病例(数据集由 Kaggle 提供);作者修改)
让我们首先根据目前所学的知识创建一个简单的情节:
\begin{tikzpicture}
\begin{axis}[
myplotstyle,
xlabel={Month $(2020)$},
ylabel={No. of confirmed cases},
]
\addplot+[mark=o,mark options={scale=1.5}] table[x expr=\coordindex, y=confirmed, col sep=comma] {Fig_semilogplot.csv};
\end{axis}
\end{tikzpicture}
法线轴和半对数 y 轴上的初始图(图片由作者提供)
在这里,因为我们没有任何要在 x 轴上绘制的列,所以我们使用x expr=\coordindex
来绘制相对于坐标索引的 y 轴数据。我们得到的图显示在左手边。很难从这个情节中正确地推断出疫情的行为。在这种情况下,更谨慎的做法是在双对数轴(在我们的例子中,是半对数轴)上重新排列这些信息。为了将我们的图从正态改为半对数,我们需要将轴环境从begin{axis} ... \end{axis}
修改为\begin{semilogyaxis} ... \end{semilogyaxis}
(因为我们只想将 y 轴修改为对数刻度)。对数轴环境的其他选项包括semilogxaxis
和loglogaxis
。从图中可以看出,在我们的图中使用半对数特征,我们可以更清晰地推断趋势。
但是,剧情还是有很多问题。看一下 x 轴刻度标签,我们可以看到从x expr=\coordindex
提供的默认刻度中无法获得任何信息。控件中的月列值。csv 文件作为 x 轴刻度标签,我们将添加以下轴选项:
table/col sep=comma,
xticklabels from table={*filename.csv*}{*colname*}
首先,我们需要为我们的。csv 文件使用table/col sep
选项。然后,我们可以使用命令xticklabels from table
指示 PGFPlots 从表中的特定列检索 x-tick 标签。
另一个样式偏好是如何显示对数轴刻度标签。一些人喜欢用科学符号来显示它,而另一些人则喜欢数字原样显示。如果您希望将对数轴刻度标签显示为固定数字,那么您可以使用命令log ticks with fixed point
显示所有带有固定数字符号的对数轴。因为半对数图只有一个对数轴,所以使用起来很简单。然而,如果你正在绘制一个双对数图形,并且希望只将一个对数轴修改成固定的数字符号,那么这篇关于 stackexchange 的文章可以帮到你!
我们几乎完成了我们的造型!让我们使用之前学习的命令将 x 标记旋转 90 度。此外,我们将使用xtick
选项为我们的绘图指定刻度位置。xtick
选项的可能值是\empty
、data
或{<list of coordinates>}
。\empty
不会产生刻度线,而{<list of coordinates>}
会在提供的坐标上产生刻度线。因为我们是从。csv 文件,我们将使用xtick=data
在我们的地块的每个坐标产生刻度线。在我们完成之前还有最后一个修改。由于我们使用离散数据点来绘图,我们将删除连接标记的线。为此,PGFPlots 为我们提供了可以添加到\addplot
命令的only marks
选项。注意:相反,如果你想只显示没有标记的线条,你可以使用 *no marks*
选项。
就是这样!我们的半对数图的最终代码将如下所示:
\begin{tikzpicture}
\begin{semilogyaxis}[
myplotstyle,
table/col sep=comma,
xticklabels from table={Fig_loglog_lineplot.csv}{month},
xtick=data,
x tick label style={rotate=90},
xlabel={Month $(2020)$},
ylabel={No. of confirmed cases},
log ticks with fixed point,
]
\addplot+[only marks, mark=o, mark options={scale=1.5}] table[x expr=\coordindex, y=confirmed, col sep=comma] {Fig_loglog_lineplot.csv};
\end{semilogyaxis}
\end{tikzpicture}
在这里,我们可以看到我们对应的情节是什么样子的:
定制后的最终剧情(图片由作者提供)
3.多轴图
现在开始我们的下一个情节!让我们看看如何绘制第二个 y 轴。为了便于绘图,我将 seaborn (Python 绘图库)提供的 tips 数据集修改为两个独立的数据集。csv 文件(午餐时间的小费金额和晚餐时间的小费金额)。注意:您也可以在单个。csv 文件来绘制相同的图形。
tips.csv (数据集由 seaborn.pydata.org 提供;作者修改)
我们将首先写下我们感兴趣的双轴环境的规格。
\begin{tikzpicture}%% axis 1 %%
\begin{axis}[
myplotstyle,
scale only axis,
axis y line*=left,
xlabel={Total bill $(\$)$},
ylabel={Tips $(\$)$},
]
\addplot+[only marks, mark=*, mark options={scale=1.5, fill=white}] table[x=total_bill,y=tip, col sep=comma] {Fig_multiaxisplot_1.csv};
\end{axis}%% axis 2 %%
\begin{axis}[
myplotstyle,
scale only axis,
axis y line*=right,
axis x line=none,
ylabel={Tips $(\$)$},
]
\addplot+[only marks, mark=triangle*, mark options={scale=1.5, fill=white}] table[x=total_bill,y=tip, col sep=comma] {Fig_multiaxisplot_2.csv};
\end{axis}
\end{tikzpicture}
现在,我们将两个环境相互叠加。为此,我们将在\begin{tikzpicture}
之后立即使用\pgfplotsset{set layers}
选项。还需要指定一些附加的样式选项:
axis y line*=left/right
:指定哪个数据集显示在哪个 y 轴上。注:***
表示轴没有箭头axis x line=none
:隐藏第二个图的 x 轴线scale only axis
:强制两个 y 轴尺寸相同
合并后的代码现在看起来像这样:
\begin{tikzpicture}
\pgfplotsset{set layers}
%% axis 1 %%
\begin{axis}[
myplotstyle,
scale only axis,
axis y line*=left,
xlabel={Total bill $(\$)$},
ylabel={Tips $(\$)$},
]
\addplot+[only marks, mark=*, mark options={scale=1.5, fill=white}] table[x=total_bill,y=tip, col sep=comma] {Fig_multiaxisplot_1.csv};
\end{axis}
%% axis 2 %%
\begin{axis}[
myplotstyle,
scale only axis,
axis y line*=right,
axis x line=none,
ylabel={Tips $(\$)$},
]
\addplot+[only marks, mark=triangle*, mark options={scale=1.5, fill=white}] table[x=total_bill,y=tip, col sep=comma] {Fig_multiaxisplot_2.csv};
\end{axis}
\end{tikzpicture}
基于这些规格的初始图如下所示:
将两个轴分层后的初始图(图片由作者提供)
我们可以添加什么样式选项来使这个情节更有吸引力?让我们从使两个 y 轴限值相同开始。这可以通过为两个轴添加ymin
和ymax
来完成。让我们也改变左纵坐标的颜色为蓝色,右纵坐标为红色。我们通过为两个轴设置选项y axis line style
、y tick label style
和ylabel style
来实现这一点。我们还将标记颜色与其对应的轴颜色进行匹配。
目前的代码是:
\begin{tikzpicture}
\pgfplotsset{set layers}
%% axis 1 %%
\begin{axis}[
myplotstyle,
scale only axis,
axis y line*=left,
ymin=0, ymax=7,
y axis line style={blue},
y tick label style={blue},
ylabel style={blue},
xlabel={Total bill $(\$)$},
ylabel={Tips $(\$)$},
]
\addplot+[only marks, mark=*, mark options={scale=1.5, fill=white}] table[x=total_bill,y=tip, col sep=comma] {Fig_multiaxisplot_1.csv};
\end{axis}
%% axis 2%%
\begin{axis}[
myplotstyle,
scale only axis,
axis y line*=right,
ymin=0, ymax=7,
axis x line=none,
y axis line style={red},
tick label style={red},
ylabel style={red},
ylabel={Tips $(\$)$},
]
\addplot+[only marks, mark=triangle*, color=red, mark options={scale=1.5, fill=white}] table[x=total_bill,y=tip, col sep=comma] {Fig_multiaxisplot_2.csv};
\end{axis}
\end{tikzpicture}
这就是我们的地块现在的样子:
自定义 y 轴样式后的绘图(图片由作者提供)
由于我们的 y 轴标签是相同的,谨慎的做法是添加一个图例,使该图信息更加丰富。我们需要一些调整来为两个轴环境渲染一个单独的图例。为此,我使用了在 stackexchange 上提出的解决方法。我们将向第一个图添加一个标签,并使用该标签为第二个轴环境中的第一个图创建一个图例条目。最终的代码将如下所示:
\begin{tikzpicture}
\pgfplotsset{set layers}
\begin{axis}[
myplotstyle,
scale only axis,
axis y line*=left,
ymin=0, ymax=7,
y axis line style={blue},
y tick label style={blue},
ylabel style={blue},
xlabel={Total bill $(\$)$},
ylabel={Tips $(\$)$},
]
\addplot+[only marks, mark=*, mark options={scale=1.5, fill=white}] table[x=total_bill,y=tip, col sep=comma] {Fig_multiaxisplot_1.csv};
\label{multiplot:plot1}
\end{axis}
\begin{axis}[
myplotstyle,
scale only axis,
axis y line*=right,
ymin=0, ymax=7,
axis x line=none,
y axis line style={red},
y tick label style={red},
ylabel style={red},
ylabel={Tips $(\$)$},
legend pos=south east,
]
\addlegendimage{/pgfplots/refstyle=multiplot:plot1}\addlegendentry{Tips during lunch hour}
\addplot+[only marks, mark=triangle*, color=red, mark options={scale=1.5, fill=white}] table[x=total_bill,y=tip, col sep=comma] {Fig_multiaxisplot_2.csv};
\addlegendentry{Tips during dinner hour}
\end{axis}
\end{tikzpicture}
从上面的代码中我们可以看到,添加图例条目的另一种方式是在\addplot
命令后使用\addlegendentry[*<options>*]{*text*}
。我使用了\addlegendimage{}
命令来引用第一个图的线条样式。然后,我们将在相应的\addplot
命令后,添加该轴环境中绘图的图例。注意:为了保持顺序,我在第二个图的 *\addplot*
命令前添加了第一个图的图例。
我们做到了!这是我们最后的情节:
定制后的最终剧情(图片由作者提供)
4.均值图
我们要处理的下一个场景是如何在情节中添加文本。为此,让我们再次使用小费数据集(午餐和晚餐时间数据集的组合)来创建一个均值图。
像往常一样,让我们从利用我们目前所学的知识创建一个基本情节开始:
\begin{tikzpicture}
\begin{axis}[
myplotstyle,
xlabel={Total bill ($\$$)},
ylabel={Tips ($\$$)},
]\addplot+[only marks, mark=square, color=red, mark options={scale=2}] table[x=total_bill,y=tip, col sep=comma] {Fig_multiaxisplot_1.csv};
\addplot+[only marks, mark=square, color=red, mark options={scale=2}] table[x=total_bill,y=tip, col sep=comma] {Fig_multiaxisplot_2.csv};
\end{axis}
\end{tikzpicture}
这就是我们的出发点:
带有基本定制的初始情节(图片由作者提供)
现在,我们需要添加一条均值线和两条标准差线(mean + 2σ
和mean-2σ
;我已经预先计算了必要的值)。为了绘制常量值,我们可以使用格式\addplot+[]{*constant*}
(在这种情况下,我们必须指定需要绘制直线的区域)或\addplot+[] coordinates{*(x,y)*}
。注意:这两个选项我都参考过了。我还指定了常量值图的区域。由于添加一个域会引起轴界限的变化,所以我又添加了*xmin*
*xmax*
*xtick*
*ytick*
。这是我们目前为止的代码:**
**\begin{tikzpicture}
\begin{axis}[
myplotstyle,
xlabel={Total bill ($\$$)},
ylabel={Tips ($\$$)},
xmin=0, xmax=40,
xtick={5,10,15,20,25,30,35},
ytick={1,2,3,4,5,6},
domain=5:35,
]
\addplot+[smooth, only marks, mark=square, mark options={scale=2,fill=white}, color=red] table[x=total_bill,y=tip, col sep=comma] {Fig_multiaxisplot_1.csv};
\addplot+[smooth, only marks, mark=square, mark options={scale=2,fill=white}, color=red] table[x=total_bill,y=tip, col sep=comma] {Fig_multiaxisplot_2.csv};
\addplot+[smooth, no marks, color=black, dashdotted] {2.97};
\addplot+[smooth, no marks, color=black, solid] {0.62};
\addplot+[smooth, no marks, color=black, solid] coordinates {(5, 5.32) (35, 5.32)};
\end{axis}
\end{tikzpicture}**
相应的绘图输出为:
添加均值和标准差线后的绘图(图片由作者提供)
在我们为每条常量线添加描述之前,这个图是不完整的。我在这里使用的方法是在期望的位置添加一个node
。我将基于rel axis cs
(或者,相对轴坐标系;详见下图)。
基于相对轴 cs** 定位节点(图片由作者提供)**
添加节点遵循的格式是:
**\node[*<options>*] at (rel axis cs: *x,y*) {*text*};**
添加文本描述后的最终代码如下所示:
**\begin{tikzpicture}
\begin{axis}[
myplotstyle,
xlabel={Total bill ($\$$)},
ylabel={Tips ($\$$)},
xmin=0, xmax=40,
xtick={5,10,15,20,25,30,35},
ytick={1,2,3,4,5,6},
domain=5:35,
]\addplot+[smooth, only marks, mark=square, mark options={scale=2,fill=white}, color=red] table[x=total_bill,y=tip, col sep=comma] {Fig_multiaxisplot_1.csv};
\addplot+[smooth, only marks, mark=square, mark options={scale=2,fill=white}, color=red] table[x=total_bill,y=tip, col sep=comma] {Fig_multiaxisplot_2.csv};\addplot+[smooth, no marks, color=black, dashdotted] {2.97};
\node [] at (rel axis cs: 0.2,0.51) {Mean};\addplot+[smooth, no marks, color=black, solid] coordinates {(5, 5.32) (35, 5.32)};
\node [] at (rel axis cs: 0.24,0.87) {Mean + $2\sigma$};\addplot+[smooth, no marks, color=black, solid] {0.62};
\node [] at (rel axis cs: 0.23,0.13) {Mean - $2\sigma$};\end{axis}
\end{tikzpicture}**
我们的最终图如下所示:
定制后的最终剧情(图片由作者提供)
5.覆盖在图形上的绘图
现在,我将在本文中处理的最后一个图是覆盖在图像上的图。为此,我将使用下图。注意:我将删除下表中提供的轴和刻度标签,代之以添加我自己的轴和刻度标签。
用于覆盖权重数据集的图像(生长图由疾病控制和预防中心提供——临床生长图)
我将在此图中使用一个虚拟的权重数据集(见下文)。
weights.csv (作者创作)
让我们首先基于数据集创建一个简单的绘图。下面给出了到目前为止带有相应图形的代码:
**\begin{tikzpicture}
\begin{axis}[
myplotstyle,
legend pos=south east,
legend entries={{\large Child 1}, {\large Child 2}},
xlabel={Age (in years)},
ylabel={Weight (in $kg$)},
]\addplot+[only marks, mark options={scale=1.5}, mark=triangle,color=blue] table[x=age,y=weight1, col sep=comma] {Fig_overlaidplot.csv};
\addplot+[only marks, mark options={scale=1.5}, mark=square,color=red] table[x=age,y=weight2, col sep=comma] {Fig_overlaidplot.csv};
\end{axis}
\end{tikzpicture}**
带有默认选项的初始绘图(图片由作者提供)
我们将修改一些东西,使我们的绘图和图像具有匹配的尺寸和轴刻度标签:
- 我们将添加
width
和height
选项来改变我们绘图的维度 - 我们将使用
xmin
、xmax
、ymin
和ymax
选项将我们的轴限制与图像对齐 - 最后,我们将添加
xtick
和ytick
选项,以使我们的绘图轴刻度标签与图像的刻度标签相匹配(我已经用公制单位指定了 y 轴的权重)
我们的代码组合在一起将如下所示:
**\begin{tikzpicture}
\begin{axis}[
myplotstyle,
legend pos=south east,
legend entries={{\large Child 1}, {\large Child 2}},
xlabel={Age (in years)},
ylabel={Weight (in $kg$)},
ymin=5, ymax=105,
ytick={10,15,20,25,30,35,40,45,50,55,60,65,70,75,80,85,90,95,100},
xmin=2, xmax=21,
xtick={2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20},
width=13cm, height=15cm,
]\addplot+[only marks, mark options={scale=1.5}, mark=triangle,color=blue] table[x=age,y=weight1, col sep=comma] {Fig_overlaidplot.csv};
\addplot+[only marks, mark options={scale=1.5}, mark=square,color=red] table[x=age,y=weight2, col sep=comma] {Fig_overlaidplot.csv};
\end{axis}
\end{tikzpicture}**
相应的曲线将会是:
覆盖在生长图上的初始图(图片由作者提供)
现在,将图形添加到绘图中的命令是:
**\addplot graphics[*<options>*] {*figure.png*};**
该图背后的中心思想是在我们的绘图轴坐标内拟合图形。因此,我们必须添加带有选项xmin
、xmax
、ymin
和ymax
的\addplot graphics
命令,以匹配主绘图的选项。我还添加了axis on top
选项,将轴线和刻度定位在图像上。
而且就是这么简单!最终代码将是:
**\begin{tikzpicture}
\begin{axis}[
myplotstyle,
legend pos=south east,
legend entries={{\large Child 1}, {\large Child 2}},
xlabel={Age (in years)},
ylabel={Weight (in $kg$)},
ymin=5, ymax=105,
ytick={10,15,20,25,30,35,40,45,50,55,60,65,70,75,80,85,90,95,100},
xmin=2, xmax=21,
xtick={2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20},
axis on top,
width=13cm, height=15cm,
]\addplot+[only marks, mark options={scale=1.5}, mark=triangle,color=blue] table[x=age,y=weight1, col sep=comma] {Fig_overlaidplot.csv};
\addplot+[only marks, mark options={scale=1.5}, mark=square,color=red] table[x=age,y=weight2, col sep=comma] {Fig_overlaidplot.csv};
\addplot graphics[ymin=5, ymax=105, xmin=2, xmax=21] {Fig_comparisons.png};
\end{axis}
\end{tikzpicture}**
我们的叠加图看起来会像这样:
定制后的最终剧情(图片由作者提供)
感谢阅读!😃
这篇文章就到此为止了!
图片来源:http://pgfplots.sourceforge.net/
当然,这只是 LaTeX 呈现给我们的整个范围的一小部分!对于初学者来说,用 LaTeX 绘图可能会令人望而生畏。我希望这篇文章能帮助新手不要被大量的信息淹没,并鼓励他们使用这个神奇的工具。如果这篇文章说服了你至少尝试一下用 LaTeX 绘图,我甚至会认为它是成功的!
快乐学习!
如何用 Qiskit 创建量子多内核分布
实践中的量子机器学习
量子机器学习要不要入门?看看 动手量子机器学习用 Python 。
概率分布在机器学习中无处不在。我们的目标是回答最简单的问题还是解决最大的问题并不重要。从技术上讲,目标总是从数据中学习一个未知的概率分布。
无论我们进行简单的回归分析还是训练深度神经网络,都无关紧要。目标总是找到某个概率分布。
而且,就算用量子机器学习算法也没关系。最终,你要寻找的答案将是概率性的。
但并不是所有的概率分布都是一样的。他们可能是非常异质的。每种类型的分布都有其特殊性,你最好知道。如果你不知道哪种分布适合你手头的问题,你就有麻烦了。
此外,如果您知道哪种分布适合您的问题,但不知道如何生成合适的分布,您的情况也不会更好。而且,你猜怎么着,用量子位生成分布本身就是一个挑战。
经典计算机有数十亿比特的内存。节省一些来存储概率分布没什么大不了的。但是量子计算机只有不到一百个量子位。我们应该考虑如何有效地表示一个概率分布。幸运的是,一个量子位不仅仅是 0 或 1。即使如果我们测量它,它只有 0 或 1,但它处于量子叠加态。这个状态包含了更多的信息。
在之前的中,我们研究了如何创建一个量子系统来重现伯努利分布。伯努利分布是所有分布中最简单的。只有两个可能的值,每个值都以一定的概率出现。这差不多就是单个量子比特叠加的含义。
假设我们的单个量子比特在|𝜓⟩=√0.7|0⟩+√0.3|1⟩.态如果你在这种状态下测量许多量子位,就会产生以下伯努利分布。
作者图片
伯努利分布回答简单的问题,你可以用“是”或“否”来回答。例如,一名乘客在泰坦尼克号沉船中幸存了吗?这是一只猫吗?这个学生通过考试了吗?
但是如果我们有多种可能的答案呢?假设我们想从著名的 MNIST 数据集中标注手写数字?显然,我们需要区分两个以上的输出值。
我们需要多个量子位来代表所有类别,因为我们测量单个量子位为 0 或 1。假设我们想要标记从 0 到 7 的数字。然后,我们有八个不同的类别。我们可以用三个量子位来编码这些可能的结果。量子位测量的每个组合代表一个数字。000 代表数字 0。001 代表 1。010 代表 2。011 代表 3,以此类推。最后,111 代表 7。
因此,我们会得到一个多内核分布,也称为分类分布。它涵盖了一个事件有多种可能结果的情况。因此,它概括了伯努利分布,该分布涵盖了两种可能结果中的一种。
作者图片
那么,假设我们有这样一个多元分布的数据。
实际问题是:“怎样才能让一个量子电路代表这样的分布?”
最简单的方法就是把这些概率转换成振幅,传递给量子电路的initialize
函数。
真正的神奇发生在第 6 行。我们计算三量子位系统的初始状态。整个技巧是取每个概率的平方根,因为概率是量子态振幅的平方。
Qiskit QuantumCircuit
的initialize
功能将所有振幅列表作为输入参数(参见官方 Qiskit 文档)。
当我们用'statevector_simulator'
执行这个电路时,它会再现我们指定的精确分布。
还有别的办法吗?我们能通过使用量子门来创造多量子分布吗?
当然了。但是,这并不简单。
我们可以使用量子门来转换量子位的状态。例如,我们可以使用qc.ry(theta, 0)
函数将位置 0 的量子位的状态向量旋转角度theta
。此外,我们可以使用prob_to_angle
函数根据概率计算角度θ。更多细节请看这篇文章。
问题是,在我们的分布中,我们将单个量子位的值用于不同的值。例如,对于所有状态['100', '101', '110', '111']
,左边的数字是 1。
所以,当我们指定量子位 3(左手边的量子位)的状态时,我们需要取所有这些状态的概率之和。
首先,我们定义我们的便利函数prob_to_angle
并定义一个QuantumRegister
。QuantumRegister
是我们量子位的容器,允许我们在 Python 代码中轻松地处理单个量子位。
动作从第 9 行开始。在那里,我们将分布的值从 4 到 7 分开,计算这些状态的总和,并将我们的总概率分成两半。下图描述了迄今为止的状态。
作者图片
因此,我们只区分两类国家。高位量子位为 0 的和高位量子位为 1 的。(注意:上量子位在图中字符串的左下方。)
下一步,我们进一步将后半部分减半。我们应用相同的逻辑。我们把上量子位为 1 的状态分成四分之二。
与第一次分裂的唯一区别是我们使用的量子门。这一次,我们使用受控 RY 门而不是普通 RY 门。不同之处在于,如果控制量子位为 1,受控 RY 门仅应用概率分割。在我们的例子中,这意味着我们只拆分“100”块,而不改动“000”块。
作者图片
最后,我们还需要一个上季度的分裂。我们必须分别管理每个季度。首先,我们把上面的四分之一分成两半。现在,我们必须只触及两个上量子位为 1 的状态。因此,我们使用多控 RY 门(qc.mcry
)。
在这一点上,QuantumRegister
派上了用场,因为我们可以以数组的形式访问量子位。术语qr[1:]
选择除第一个以外的所有量子位。这些是多重控制 RY 门的控制量子位。最后一个参数qr[0]
表示目标量子位。
作者图片
我们还需要使用另一个多重控制的 RY 门来分割下面的四分之一。我们把它封装成非门,应用在中间的量子位上。这让我们可以选择中间量子位是 0 而不是 1 的状态。
到目前为止的结果表明,我们准备了一半的状态。
作者图片
我们还需要在下半部分执行相应的步骤,以生成整体分布。这是完整的源代码。
当我们看结果时,我们看到它类似于我们的多诺尔分布。
作者图片
方法很简单。我们重复地将状态分成两半,并应用相应的量子位变换。然而,这比简单地用概率初始化三个量子位要多得多。
但是在某些情况下,你不能在初始化的时候指定所有的概率。例如,如果创建一个量子贝叶斯网络,分布值可能来自其他变量。然后,您不可避免地希望能够以编程方式创建一个多内核发行版。
量子机器学习要不要入门?看看 动手量子机器学习用 Python 。
在这里免费获得前三章。
如何在 Python 类中创建只读和删除证明属性
对类中的属性施加控制
图片由 Charles Deluvio 通过 Unsplash 提供
控制你的属性
本教程将演示如何在 Python 类中创建只读和防删除属性。通过这种方式,可以对您的属性应用额外的控制层,确保您的类按预期使用。虽然在 Python 中有多种方法可以创建只读和防删除属性,但使用 setattr 和 delattr dunder 方法是快速控制对象中属性的一种便捷方法。
示例:雇员类
设置属性一次
举例来说,假设我们正在创建一个简单的 Employee 类,它需要在对象中设置三个值。这些值将是雇员的姓名、年龄和唯一的 id 号。这些属性值将在属性中设置;并且用下划线表示,表示它们是私有属性,不打算在类外使用。
一旦设置了__init__
方法,就有必要定义神奇的方法__setattr__
。在这种方法中,我们可以应用一些简单的逻辑来施加强大的属性控制。在给出的例子中,当属性在对象初始化期间首先被设置时,方法将调用方法。我们可以通过应用以下逻辑来防止_name
属性被重置。
为了实现这一点,我们可以编写一个条件,当设置一个新属性时,如果该属性等于_name
并且已经有一个值,那么程序将退出并引发一个内置的AttributeError
异常,并在标准错误(stderr)输出中显示一条定制消息。_name
属性是在对象初始化期间设置的,因此对该属性的任何重置都会引发异常并终止程序。
我们还可以进一步控制,确保_age
和_id_number
属性都是整数类型。我们可以创建一个列表,并在将它们设置为整数之前检查_age
和_id_number
属性是否在最后。下面的 setattr 方法显示了实现这一点的代码。
**注意:**在所示的例子中,当设置一个属性时,它不是使用 setattr 魔术方法中的 object.attribute 语法来设置的,而是使用object.__dict__[key] = value
。如果我们使用前一种方法,将会启动一个无休止的递归循环,因为 object.attribute 语法将调用 setattr 方法!
现在,让我们创建一个 Employee 对象,并检查是否已经设置了属性。如图所示,属性已经设置,并且是正确的类型。
现在,假设我们想要重新设置_name
属性,尽管它已经被设置了。在这种情况下,会引发AttributeError
异常,并向控制台输出一条消息,通知用户 name 属性已经被设置,并且不能被重新设置。
删除证明属性
为了证明我们的名称属性删除,我们可以简单地向 dunderlattr 方法添加一些逻辑。这里,我们说如果用户试图从对象中删除属性名,将会出现一个AttributeError
异常,通知用户名称属性不能被删除。但是,我们仍然允许用户删除 Employee 对象中任何其他属性的行为。
当我们试图从 Employee,emp_1 对象中删除受保护的 name 属性时,会引发一个AttributeError
异常。
奖励:自定义信息类
虽然AttributeError
类很好地向用户解释了当用户试图删除_name
属性时程序为什么会退出,但是通过构建一个定制的异常类,这个原因可以变得甚至更加明确。
我们可以编写一个自定义的DeletionException
类,如果用户试图删除_name
属性,这个类将被引发。当DeletionException
类被引发时,我们还可以有效地告诉用户 name 属性当前是什么。该消息可以打印到标准错误输出中。
为此,我们创建了一个DeletionException
类,它从基本异常类继承并接受一个参数,这里是属性的初始值。当类被实例化时,例如当它被引发时,这个值在DeletionException
对象中被设置。当它被引发时,我们将原始的 name 属性作为唯一的参数传递给该类。这发生在__delattr__
方法内部。
当引发时,将调用__str__
方法并打印出一条消息,通知用户不能删除 Employees 对象中的原始 name 属性。
摘要
可以通过定制逻辑修改 dunder 方法 setattr 和 delattr,以保护属性并控制它们的访问。此外,可以添加定制的异常类来有效地通知用户为什么属性受到保护。
如何创建实时人脸检测器
使用 Python、TensorFlow/Keras 和 OpenCV
在本文中,我将向您展示如何使用 Python、TensorFlow/Keras 和 OpenCV 编写实时人脸检测器。
我马上会注意到,所有代码文件都可以在这个 repo 中获得。
https://gitlab.com/Winston-90/me_not_me_detector/
首先,在理论部分我会告诉你一些对我们有用的概念(迁移学习和数据扩充),然后我会在实践部分部分进行代码分析。
注意,您必须安装 TensorFlow 和 OpenCV 库来运行这段代码。你可以手动完成,或者在你下载了 repo 之后简单地运行pip install -r requirements.txt
命令。你也可以用 conda 命令conda install -c conda-forge numpy, opencv, tensorflow
来完成。
问题陈述
在这里,我想建立一个面部检测器,也可以区分我和其他人。你可以在本文末尾看到我的工作成果。
初始任务可以分为两个子任务:
- 为人脸分类训练一个模型。
- 调整模型,使其与作为检测器的网络摄像头一起工作。
更详细地说,该任务可以分为以下几个阶段:
- 数据集集合。
- 寻找迁移学习的基础模型。
- 训练一个模特。
- 将分类器转换为检测器。
在我开始分析这些阶段之前,我想非常简要地概述一下对我们有用的概念。
理论部分
在这一点上,我必须说,这个教程是不详细的,因为它可以。例如,我不会解释什么是卷积或者为什么在 CNN 架构中需要池层。当然,你需要知道这些才能理解 CNN 是如何工作的,但我认为如果我解释所有的概念,这个教程会太繁琐。另一方面,其他人已经解释了很多东西,而且做得比我好。例如,在这里你可以读到 CNN 的概况,而在这里——关于流行的 CNN 架构。
卷积神经网络
由于我们正在讨论图像识别,我们将使用 CNN —卷积神经网络,这种架构在这项任务中取得了最大的成功。
典型的卷积神经网络架构。 公共领域
与经典神经网络(这里我指的是FDN——前馈神经网络)不同,在 CNN 中,神经元是:
- 首先:以矩阵(张量)的形式排列,而不是数组,
- 其次:它们只与前一层的一小部分神经元相连,因此层之间并不完全相连。
这种方法允许您显著减少网络参数的数量,并使图像的模板搜索更有效。
前馈神经网络 vs 卷积神经网络。作者图片
在这张图的底部,我想说明一下,CNN 中的层是一个张量(经常被画成平行六面体)。我将把张量作为矩阵序列来讲。所以这些张量中的每一个都是一系列的矩阵,像披萨盒一样一个接一个的叠在一起。反过来,矩阵只是以矩阵形式排列的神经元序列,而不是像在经典网络中那样的阵列。
迁移学习
迁移学习是这项任务中最重要的概念,因为从头开始构建人脸分类器非常困难(几乎不可能)。迁移学习是在自己的任务中使用预先训练好的模型的过程。
转移学习。作者图片
这种情况发生如下。你找到一个为类似任务训练过的模型(例如,识别 1000 类图像,就像在 ImageNet 中一样,而你只需要识别少数几类)。然后使用它的权重(冻结它们,这意味着它们不会改变),并在您的小数据集上完成模型的训练。之后还可以解冻所有权重,继续用极小的学习率训练模型。
由于 CNN 架构和图像识别任务的特征,该过程变得可能(但是也可以用于不同的架构)。网络学会从一层到另一层(从输入到输出)看到模式,它们变得越来越复杂。事实证明,所有问题的一般模式大致相同,这允许我们使用预先训练的权重。
数据扩充
图像分类问题中的另一个重要概念是数据扩充。数据扩充是通过对原始图像应用一些变换来人为增加数据集大小的过程。例如,我们可以使用水平和垂直反射、小旋转或放大、颜色反转等等。这将显著增加数据集的大小,从而提高网络的概化能力。
在上面的例子中(文章中的第一个图像),当偏移值很高时,有时会出现只有部分图像可见的情况。一方面,这是好的(在头部不可见的图像情况下,网络可以通过爪子和尾巴而不是通过口鼻来学习识别猫),但如果你过度进行这样的转换,也会使网络混淆。
TensorFlow 中有多种数据扩充方法。我们可以生成图像并保存到磁盘,或者我们可以将生成器直接传送到网络。我选择了第一个选项,这样做更明确。但是这里也有两种方法:生成随机数量的图像或者生成特定图像的几个版本。您可以在data_augmentation.ipynb
笔记本中看到这两个选项的实现。我使用了第二个选项,并专门为每张图像生成了五个转换。
实用部分
项目结构
该项目的结构如下:
me_not_me_detector
├───article
├───datasets
│ ├───face_dataset_test_images
│ │ ├───me # contains TEST images for ME class
│ │ └───not_me # contains TEST images for NOT_ME class
│ ├───face_dataset_train_aug_images (optional)
│ │ ├───me # contains aug TRAIN images for ME class
│ │ └───not_me # contains aug TRAIN images for NOT_ME class
│ └───face_dataset_train_images
│ ├───me # contains TRAIN images for ME class
│ └───not_me # contains TRAIN images for NOT_ME class
├───models
│ .gitignore
│ data_augmentation.ipynb
│ me_not_me_classifier.ipynb
│ me_not_me_classifier_model_comparison.ipynb
│ me_not_me_detector.ipynb
│ README.md
└── requirements.txt
先说文件夹。
article
文件夹包含本教程的数据。models
文件夹包含了用于测试和进一步使用的训练模型。datasets
文件夹包含三个文件夹——用于训练集、测试集和扩充训练集(可选)。其中每一个都包含两个子文件夹,用于两个类- me 和 not_me 。在一般情况下,它包含 N 类分类问题的 N 个子文件夹。
现在我们来谈谈代码文件——jupyter 笔记本。
data_augmentation.ipynb
文件从初始数据集创建一个扩充数据集,并提供关于数据集的一些信息。- 文件包含训练和测试五个不同模型的代码。
me_not_me_classifier.ipynb
file 做同样的事情,但是针对一个特定的模型。您可以将它作为构建自己的分类器的示例。me_not_me_detector.ipynb
文件使用 OpenCV 库,将分类器变成实时检测器。
其他文件用作附加文件:
.gitignore
包含 git 中不会推送的文件,requirements.txt
包含了运行这些代码需要安装的库列表,等等。
1.数据集集合
首先,我们需要收集一个数据集。我用我的照片和我家人的照片来训练模型,但是你也可以在其他一些人脸数据集上训练模型。我只使用了个人照片来检查这样一个小数据集是否足以让模型显示出可接受的质量。
我从每张照片中裁剪出面部,并将它们的大小调整为 250x250(您不必这样做,因为 TensorFlow 可以为您完成)。以下是初始数据集中的一些照片示例:
初始数据集照片。作者图片
我一共收集了 215 张照片,其中 82 张是我,133 张是非 _ 我。
对于测试集,我立即搁置了 20 张照片。这可以自动完成,但我是手动完成的,因为数据集太小。对于列车组,我应用了来自data_augmentation.ipynb
笔记本的数据增强代码。因此,数据集增加了五倍!(每张照片生成五张照片)。以下是生成的照片示例:
增强照片。作者图片
当数据集准备好时,我们可以开始训练模型。
2.寻找迁移学习的基本模式
这里没有什么复杂的——我只是使用了在 ImageNet 数据集上训练的不同模型。如果他们没有很好的准确性,那么我想我会使用类似 VGGFace 模型的东西比如这里的。但是我得到的质量足够好。我们可以用以下代码加载预训练模型:
3.训练模特
现在,我们必须冻结这些权重,在模型上添加一些层,并在我们的小数据集上训练模型。
正如我前面说过的,me_not_me_classifier_model_comparison.ipynb
文件包含了不同型号的代码。你可以用它来做你自己的实验。下面的代码示例摘自me_not_me_classifier.ipynb
。这里我们将使用 ResNet50 作为初始模型。
在导入库和数据集加载之后,我们完全按照上面的代码加载预训练模型。之后,我们需要恢复模型的顶部——密集的部分。请注意,这部分因型号不同而不同。要知道你需要哪些层,你可以加载带顶层和不带顶层的模型,调用 model.summary() 方法,看看它们有什么不同:
为了添加层,我使用了 TensorFlow 函数 API 。当然,你需要一些关于 TensorFlow 和 CNN 的知识,但你也可以尝试添加不同的层,获得非原创的架构。在我的例子中,我们需要一个全局平均池层和密集层。不要忘记预先冻结其他重量。
之后,我们继续配置模型。我添加了一个 ModelCheckpoint 对象,以便在出错时将模型保存在磁盘上,同时作为一种正则化技术,我还添加了提前停止。作为一种优化方法,我使用了具有标准学习率值的 Adam。我也尝试使用各种调度技术,但是它们没有带来多少结果。
所以现在我们可以开始训练了。结束后,你将有一个现成的模型。您可以通过me_not_me_classifier.ipynb
文件中的测试部分代码来检查其功能。
4.将分类器转换为检测器
现在我们必须使用 OpenCV 库进行网络摄像头访问和人脸检测。
坦率地说,由于分类器和检测器的定义,短语“将分类器转换为检测器”是不正确的。分类器(理解为图像分类器)是一种模型,它接收图像作为输入,并在输出端给出一个可能类别的标签(在我们的例子中,是 me 或 not_me )。检测器(理解为面部检测器)是一种模型,其接收图像作为输入,并且如果该图片中存在面部,则输出面部周围的边界框的坐标。
我用这个短语来说明最终的程序(它仍然是一个分类器)现在也给出了人脸在图片中的确切位置。此外,现在它可以在照片中同时有几个人脸的情况下正确工作。
训练一个人脸检测器是一件非常困难的事情(主要是因为数据很难标注),所以我会使用 OpenCV 提供的人脸检测器。使用起来非常简单。在下面的代码中,faces 变量是图像中所有面孔的数组。对于每个面,边界框有四个值:
- 左上角的 x-x 坐标,
- 左上角的 y-y 坐标,
- w —边界框的宽度,
- h-边界框的高度。
以下代码在网络摄像机图像中实时突出显示您的面部,如下图所示。
用 OpenCV 进行人脸检测。照片由西蒙·罗本从派克斯拍摄
现在剩下的就是加载预先训练好的模型,将人脸所在的图像片段传递给它,并在屏幕上显示文本!事实上,在这个阶段我面临一个小困难——模型只是有时认出我。发生这种情况是因为我训练她在图像上“留有空白”,不仅仅是脸部的位置。
我可以向数据集添加不同比例的图像,但我决定诚实地这样做。为此,我编写了函数 get_extended_image() ,用某个系数 k 来增大裁剪后的图像的大小,k 越大,人脸周围的面积越大。为了解释这个函数的操作(或者更让你迷惑),我给出下图(为简单起见,这里 k = 0.3。没有观察到刻度。注意,左上坐标是(0,0))。你也可以看到不同 k 参数的我的脸的剪报(根据 OpenCV,它使用 BGR 而不是 RGB,但不是调整颜色,让我们想象我是一个头像)。对于结果模型,我使用 k = 0.5。
get_extended_image()函数说明。作者图片
具有不同 k 参数的 get_extended_image()的图像。作者图片
我想指出的是,我使用了 MobileNet 作为基础模型。最初,我使用的是 ResNet50 ,因为它显示的质量最好,但图像滞后了一点,而更轻的 MobileNet 则没有这些问题。我在一台配有 i7–10750h 和 32G 内存的电脑上测试了所有这些。
就是这样!您可以在me_not_me_detector.ipynb
笔记本中找到完成的代码,但是注意,要使用它,您需要在models
文件夹中有一个模型,否则您将在加载模型单元格中得到一个错误。这是结果。
实时人脸检测器的视频演示
我必须说,虽然模型相当简单,但它已经很好地识别了我,例如,如果脸部的一部分被覆盖。另外,我的数据集中没有威利姆·达福的照片,所以模特以前没有见过他。
面具识别中的人脸呢——你可以看到,如果我的鼻子被完全遮住,程序就会停止识别我的脸(或者当它旋转太多的时候)。但是这在检测器侧是一个问题,因为它停止将图像传输到模型。这是因为 OpenCV 人脸检测器通常看不到戴面具的人。但我认为,如果你能收集一个大型数据集,你也可以教你的模型区分戴面具的人。
让我感到惊讶的是——当脸的下半部分被遮住时,模特比上半部分更容易认出我。你可以看到,当我戴上帽子或者用手遮住额头时,模特开始怀疑。我想这是因为在我所有的照片中,我的头都是敞开的,而且我只有一种发型。
好模式!作者图片
结论
下面,我展示了使用或不使用数据扩充(本例中为 x5 数据扩充)的不同模型的训练结果。最佳质量(99%的验证准确性)由 ResNet50 显示。但正如我上面所说,我使用了基于 MobileNet 的模型,因为它在实时操作中表现得很好。
不同车型的训练结果。作者图片
这些结果表明,数据扩充可以显著提高模型的质量。在这种情况下,验证损失下降了 10 倍,但这是关于非常少的数据集。我试图生成更多的图像,并获得更多的准确性。该参数(数据集的系数增加,因此为每幅图像生成的增强图像的数量)可以通过交叉验证来选择。我在 MobileNet 中得到的最好的模型是验证损失= 0.09886,验证准确度= 0.9589,数据集增加系数= 15。
数据集大小对 MobileNet 示例中模型质量的依赖性。作者图片
与此同时,学习过程变得非常缓慢。有道理,数据集规模增加,学习时间也增加。您可以在下面看到训练时间对数据集大小的依赖关系图,它几乎是线性的。
MobileNet 示例中数据集大小对学习时间的依赖性。作者图片
下表是上一个表的扩展版。在这里,您可以看到参数的数量、模型的深度和测试精度。请注意,图层被计为 model.layers 对象的数量,这并不完全正确,但给出了模型深度的概念。测试准确性没有太多的统计能力,因为我只有 20 张测试图像。
扩展结果。作者图片
关于 VGG 的一件事。我用两个 1024 密集层替换了两个 4096 密集层,模型显示了大致相同的结果,尽管参数数量分三次下降(从 1.34 亿下降到 4100 万,可训练值从 1.19 亿下降到 2700 万)。该型号的磁盘大小为 368 MB。
从所做的工作中,我可以得出以下结论。有些比较明显,有些不太明显:
- 你需要收集的数据集应该尽可能的多样化,同时尽可能的接近真实数据。
- 更简单的模型训练速度更快,预测速度更快,占用硬盘空间更少。更简单的模型有更少的参数,但是,同时,可以更深入。
- 迁移学习是一种非常强大的技术,即使只有很小的数据集,它也能让你解决你的任务。
- 数据扩充技术允许你显著地提高模型的质量,但是它也增加了训练时间。您可以通过交叉验证选择数据扩充系数。
- 结果很大程度上取决于随机初始化。因此,即使是相同参数的训练过程也要运行几次。例如,在 22 分钟和 150 个历元中,我在没有数据增强的情况下使用 ResNet50 得到的验证损失结果为 0.1334,比常规 ResNet50 好 39%。
现在我要再说一句让你更加困惑的话。
网络的卷积部分(上至稠密层)将原始图像转化为某个高维空间中的点(这类似于嵌入的概念),稠密层再在这个空间中构建分离超平面。
因此,最好建立一个模型来更好地定位这些点,然后您可以使用更简单的分类器。当然,构建这些表示的规则非常复杂,这就是为什么我们需要具有大量参数的深度模型。
一个能够很好地创建嵌入的网络能够解决最初没有被训练过的任务。所以,一个好的模型会把我所有的照片彼此靠近(在某个高维空间)定位,把威利姆·达福所有的照片彼此靠近定位。但同时,这两个点云的位置应该相距很远。现在,当你向网络展示另一个人的照片时,它将能够说这是而不是 _me ,但是除此之外,它将能够给出他最像的人或者注意到这个人不在数据集中。这是度量学习的变体,这里使用三重损失。
感谢您的阅读!
- 我希望这些材料对你有用。在媒体上关注我以获得更多类似的文章。
- 如果您有任何问题或意见,我将很高兴得到任何反馈。在评论中问我,或者通过 LinkedIn 或 Twitter 联系我。
- 为了支持我作为一名作家,并获得数以千计的其他媒体文章,使用我的推荐链接获得媒体会员资格(不收取额外费用)。
如何用谷歌图表和熊猫数据框创建简单的可视化
数据可视化
谷歌图表能让你创造出令人愉悦的互动情节,但不能直接阅读熊猫数据。这里我们创建了一个简单的 Python Web 应用程序来结合这两种技术。
作者图片
Google Charts 已经存在很多年了,我都不记得了,所以我想我们可以有把握地认为它是一项成熟稳定的技术。
它还可以用来创建吸引人的图表和图形。
月最高和最低温度-2018 年。图片作者。
在这里,我们可以看到一个简单的交互式折线图,当您将鼠标悬停在图上的某个点上时,它会向您显示该数据点的详细信息。
我们将看看如何使用 HTML 和 Javascript 中的一些基本样板代码、Pandas dataframes 和一个简单的 Flask web 应用程序来创建这样的图表。下面,我们将开发完整的代码。(在本文的最后,我将包含一个应用程序的链接,您可以在这里看到运行中的代码,并下载代码和示例数据。)
以下是以下内容的概要:
- 编写一个基本的 Flask 应用程序(可选)
- 使用样本 HTML 和 Javascript 显示图表
- 创建熊猫数据框架并将其转换成与谷歌图表兼容的形式
- 将烧瓶代码和网页放在一起作为一个应用
创建并运行 Flask 应用程序
这是创建和运行 Flask 应用程序的一个非常简单的介绍。如果您已经知道如何做到这一点,那么您可以安全地跳过这一部分。
Flask 是一个 web 应用程序微框架,这意味着它是一个用于开发 web 应用程序的非常轻量级的库。创建您的第一个 Flask 应用程序很容易,但首先您需要用 pip 或 conda 安装它,例如:
pip3 install flask
接下来,打开一个新目录,用下面的代码创建一个文件 app.py :
from flask import Flask
app = Flask(__name__)
@app.route('/')
def root():
return 'Hello'
代码非常简单。第一行导入烧瓶库;第二个创建一个 Flask 对象(将被运行);剩下的部分定义了一条路线。一个路由是一个网页,或者端点,而 @app.route 装饰器定义了 url,在这种情况下它是根 url(即/)。下面是一个函数定义,它告诉 Flask 服务器当这个特定的端点被请求时该做什么——在这个例子中,只需返回字符串“Hello”。
现在打开终端窗口,导航到正确的目录,并键入:
python3 -m flask run
(注意:我在一个标准的 Linux 环境中使用 Python3,这里,如果你使用一个不同的环境,Python3 是默认的——例如,portable Python 或 Conda——那么你的命令可能是 python 而不是 python3。)
这将启动 Flask 服务器,结果应该是这样的:
运行 Flask 应用程序-作者图片
Flask 现在正在运行您的应用程序,它可以从 url 获得, http://127.0.0.1:5000 ,所以在浏览器的地址栏中键入它,您应该会看到类似这样的内容:
跑步烧瓶应用程序——作者图片
我们稍后将使用模板将 Flask 应用程序连接到网页,但现在,这就是我们需要了解的关于 Flask 的全部内容。
一个简单的谷歌图表
现在我们来看一个可以在许多不同的应用程序中重用的模板 HTML 页面。基本文件布局如下所示:
<!DOCTYPE html>
<html>
<head>
<script>
// Script 1 — where the data gets loaded
</script> <! — Script 2 — Load the AJAX API →
<script src=”https://www.gstatic.com/charts/loader.js">
</script> <script>
// Script 3 — Where we create and display a chart
</script>
</head>
<body> <! — the div where a chart will be displayed →
<div style=”width:600px; height:300px” id=”chart1"></div> </body>
</html>
这是一个简单的 HTML 文件,文件体只有一个
,文件头有 3 个脚本。是显示图表的地方,并被赋予了一个 id——我还赋予了它一个高度和宽度。id 是强制性的,尺寸不是——您可以随意改变高度和宽度,或者完全不考虑它们。
主要逻辑来自三个脚本。第一个脚本 1 是我们加载数据的地方。对于第一个示例,我将在本地创建数据,但稍后我们将从 Pandas 数据框架中加载它。第二个脚本,脚本 2,加载一个 Google Charts API,脚本 3 将使用它。和脚本 3。它本身负责创建和显示图表的主要工作。
我们马上会看到这些是如何工作的,但值得指出的是,如果你想创建自己的应用程序,你只需要修改脚本 1 和 HTML。所以只需要很少的 Javascript 编程。
脚本 2 已经定义,我们不需要修改它。
脚本 3 相当长,但是,同样,一旦我们定义了它,我们不需要改变它。这是:
<script>
// Load the Visualization API and the corechart package
google.charts.load(‘current’, {‘packages’:[‘corechart’]}); // Set a callback for when the API is loaded
google.charts.setOnLoadCallback(drawChart);
// This is the callback function which actually draws the chart
function drawChart(){
google.visualization.drawChart({
"containerId": **containerId**,
"dataTable": **data**,
"chartType": **chartType**,
"options": **options** });
}
</script>
这里发生的事情是,我们从 Google 加载可视化 API,然后设置一个回调函数,该函数将在 API 完成加载时运行。回调函数是 drawChart 并完全按照它所说的去做。
drawChart 简单地从 Google API 调用另一个同名函数,并传递一些参数,我们将在稍后的脚本 1 中定义这些参数。让我们检查一下这些参数。
containerId 是将显示图表的< div >的 Id。
数据是要绘制的实际数据。
chartType 是我们想要的绘图类型,例如,折线图、饼图、柱形图。
选项可以包括图表的多个不同选项,例如标题。
我们将在脚本 1 中定义这些选项。
定义数据
为了获得一个有效的 web 页面,首先我们将在本地定义数据——稍后我们将从 python 应用程序导入数据。
您可以用几种不同的方式定义 Google Charts 的数据,但是对于我们的目的来说,最简单的方式是一个简单的表格。这是停在我家街道上的汽车数量和品牌表:
但是我们需要将其格式化为 Javascript 二维数组中的行列表。这与 Python 中的列表列表非常相似。看起来像是:
[
["Car","Number"],
["Audi", 3],
["BMW", 2],
["Mercedes", 1],
["Opel", 3],
["Volkswagen", 4]
]
列表中的第一项是列名列表,其余的是数据行。
这是脚本 1,它包含了我们之前看到的数据和选项…
<script>
data = [
["Car","Number"],
["Audi", 3],
["BMW", 2],
["Mercedes", 1],
["Opel", 3],
["Volkswagen", 4]
]; chartType = "ColumnChart";
containerId = "chart1";
options = {"title":"Cars parked in my road"};
</script>
我们首先看到的是包含 car 表的变量数据。接下来是我们将要绘制的图表的类型,然后是图表将要绘制到的< div >的 id。最后,我们为图表设置选项——这里只是标题,但是根据我们想要绘制的图表类型,可能还有其他选项。稍后您将看到如何使用这些选项。
如果你把这些脚本和上面的 HTML 模板放在一起,你就有了一个工作网页。您可以在浏览器中打开它并查看结果图。
停在我的道路上的汽车柱形图-图片由作者提供
这里有一个巧妙的技巧:改变线路
chartType = “ColumnChart”;
到
chartType = “PieChart”;
保存并重新加载网页,然后…
那很容易!
好的,但这只是一个简单的独立演示,实际上我们想从其他地方获取数据。这就是我们接下来要去的地方。
熊猫数据框到谷歌数据表
我们可以看到示例中提供的数据格式是一个列表列表。列表的第一个元素是包含列标题的列表,其余元素包含构成表格行的数据。
虽然这在概念上与熊猫数据帧没有太大的不同,但我们确实需要做一些工作来将两者转换。
让我们首先编写一些 Python 代码来加载我们的数据,并创建一个 dataframe 来表示我们想要绘制的数据。
如果你下载程序文件,你会在根目录中找到一个名为 london2018.csv 的文件,我们将把它加载到一个熊猫数据帧中,如下所示:
url = ‘london2018.csv’
weather = pd.read_csv(url)
数据帧看起来像这样:
weather.csv —图片由作者提供
这是 2018 年伦敦天气统计的记录(来自英国气象局数据)。 Tmax 和 Tmin 是 2018 年各月的最高和最低气温, Rain 是以毫米为单位的总降雨量, Sun 是总日照时数。
我们将生成一个温度图表,我们只需要 Tmax 和 Tmin 以及 Month 列,因此我们创建了一个我们需要的数据的新数据框架,如下所示:
title = “Monthly Max and Min Temperature”temps = weather[[‘Month’,’Tmax’,’Tmin’]]temps[‘Month’] = temps[‘Month’].astype(str)
请注意,我还将月列转换为字符串,因为将其视为数字没有多大意义,并且我还为图表创建了一个标题。
所以现在我们有了想要的数据;我们只需要将它转换成谷歌图表将处理的形状。我们通过从图表中提取值并将它们转换成列表来实现这一点。这将为我们提供列表中的值,这正是我们在图表中需要的。一个问题是:没有包含列名。这很容易解决,我们提取列名,然后将结果列表附加到值列表的顶部。
d = temps.values.tolist()c = temps.columns.tolist()d.insert(0,c)
现在,我们将数据和标题捆绑到一个 JSON 字符串中,可以传递给 web 页面。
tempdata = json.dumps({'title':title,'data':d})
我们使用内置于 Flask 中的模板机制将数据传递给网页。像这样:
return render_template('weather.html', tempdata=tempdata)
函数 render_template 找到模板【weather.html并通过将传递给它的数据插入模板来创建一个网页。
整合应用程序
所以现在我们需要修改我们的 html 文件,使之成为一个模板。这意味着将 Script 1 改为将 JSON 数据加载到 Javascript 变量中的脚本,方法是在要传递的数据所在的位置放置命名的占位符。(一个宫托是一对双花括号,里面有名字。)
在我们的例子中,只有一个数据项叫做 tempdata 。因此,我们将脚本 1 中的代码替换为:
<script> tdata = JSON.parse({{tempdata|tojson|safe}});
tempdata = tdata.data;
temptitle = tdata.title;
chartType = "LineChart";
containerId = "chart1";
options = {"title":temptitle};</script>
名称用双花括号{{name}}括起来,这里我们也是说数据要转换成 json,并且包含‘安全’的 HTML,也就是说,我们不希望任何特殊字符转换成转义序列。
将数据放入模板后,我们将它分配给变量 tdata 并从中为数据和标题设置变量。
所以我们最终得到了两个文件,如清单 1 和清单 2 所示。
清单 1。烧瓶计划——作者图片
清单 2。网页——作者图片
现在这一点是重要的:首先,我们将 Flask app app.py ,其次,Flask app 希望 HTML 文件被称为weather.html(正如我们在清单中看到的那样),所以确保您给它起了那个名字。最后,Flask 希望它的模板是一个名为 templates 的目录,该目录与 Flask 应用程序在同一个目录中。
当你运行 flask 应用程序时,你会看到下面的页面。
除此之外,Google Charts 还有很多其他功能,但我希望这是一个有用的介绍,可以让你用 Python 应用程序生成这些功能。感谢阅读。
源代码
当你下载完文件后,将它们解压到一个空文件夹中,用 python -m flask run 运行 Flask app(如上)。
时事通讯
我可能会进一步研究这些代码和/或就这个主题写更多的文章。如果你想了解最新的文章,请考虑在这里订阅我偶尔发布的免费时事通讯。
如何为您的数据科学项目创建出色的 Web 应用程序
数据科学家不必学习 HTML、CSS 和 JavaScript 来构建网页。
在 Unsplash 上由Meagan carscience拍摄的照片
Web 开发不是数据科学家的核心能力。大多数数据科学家都懒得学习不同的技术来做这件事。这不是他们喜欢的咖啡。
然而,大多数数据科学项目也有软件开发部分。开发人员有时对问题有不同的理解,他们使用离散的技术。它经常会导致问题,并且毫无成效地消耗两个团队的宝贵时间。
此外,Tableau 和 Power BI 等可视化工具更侧重于数据探索。然而,这只是一个完整的数据科学项目的一部分。如果你需要集成一个机器学习模型,它们还远远不够完美。
Streamlit 允许你为你的数据科学项目开发网络应用。这个开源库的 API 完全是 python 的。因此,你不必学习任何其他网络技术来使用它。此外,它简单易学,修改灵活。
本文是对 Streamlit 的介绍。我们将构建一个交互式 web 应用程序,它接受用户输入,运行 K-means 算法,并在 web 界面中即时绘制结果。
到这篇短文的结尾,我们已经涵盖了
- 安装 Streamlit 并试水;
- 构建交互式网络应用程序;
- 使用用户输入运行 K-means 算法;
- 使用缓存提高性能,以及;
- 在云上部署它;
这里是链接到部署版本。如果你想先睹为快,就去看看吧。
为开发建立 Streamlit。
这个非凡的工具有一个令人尴尬的简单设置,几乎所有 Python 用户都熟悉它。使用 PyPI。
pip install streamlit
也可以使用 conda 等流行的 python 包管理器。
完成后,您可以使用安装时附带的 hello world 应用程序对其进行测试。在终端窗口中执行下面的命令来启动开发服务器。
streamlit hello
hello world 应用程序是一套出色的可视化工具,您可以使用 Streamlit 来完成。上述命令将启动一个本地开发服务器,并在默认浏览器中打开链接。您还可以在同一页面上找到源代码。此外,这个示例应用程序还提供了许多高级教程的链接,可以帮助您自学。
现在设置已经完成,让我们创建一个应用程序来与我们的机器学习模型进行交互。
通过 Streamlit web 应用程序使用机器学习模型。
下面的应用程序使用 Pandas、Scikit-Learn、Matplotlib、Seaborn 和 Streamlit。开始之前,请确保您已经安装了所有必需的软件包。如果没有,下面的命令将为您完成。
pip install pandas scikit-learn matplotlib seaborn streamlit
创建您的第一个 web 应用程序
使用以下内容创建一个名为“quickstart.py”的文件。
来自作者的代码片段。
上面的文件很简单。为了便于说明,我在文件中添加了一些部分。
在主应用程序部分,我们有三行代码。我们向页面添加了标题和描述。然后我们在页面上显示数据框。“st.write”功能是一个一体化的解决方案。您几乎可以将任何内容传递给这个函数,Streamlit 足够智能,可以在 UI 中显示正确的小部件。为了了解不同的 Streamlit 函数,这里有一个备忘单。
让我们用下面的命令运行我们的初始应用程序。
streamlilt run quickstart.py
像 hello 应用程序一样,这个命令将启动一个新的开发服务器。在您的浏览器上,您会看到以下内容。
截图来自作者。
恭喜你,你刚刚创建了你的第一个 web 应用程序;没有 HTML,CSS,绝对没有 JavaScript。
但这只是初步的。一个网络应用可以做很多很酷的事情。它可以与用户实时互动,并更新其内容。让我们看看我们如何能做它。
添加交互
在 Streamlit web 应用程序中实现互动毫不费力。Streamlit API 包含几个小部件。您可以使用它们来获取用户输入并将它的值存储在一个变量中。其余的就像任何其他 python 程序一样。
让我们添加一个复选框来切换数据集显示。毕竟,没有人开发一个 web 应用程序来查看原始数据。用以下内容替换数据框显示(第 30 行)。
来自作者的代码片段。
如果刷新浏览器,现在可以看到一个复选框来切换数据框显示。
截图来自作者。
但是应用程序中间的切换按钮并不令人满意。让我们把它移到边栏。
向应用程序添加边栏
又是一个轻松的动作。Streamlit API 具有侧栏属性。您在主应用程序中创建的所有小部件也可以在这个侧栏属性中使用。
使用“st.sidebar”属性创建侧栏变量。然后将我们在主应用程序部分添加的复选框分配移动到侧边栏部分。请注意,我们现在使用“st.sidebar.checkbox”而不是“st.checkbox”
来自作者的代码片段。
在上面的代码中,我们还向侧边栏添加了一个滑块。这个小部件将捕获用户选择的集群数量。下面是输出的样子。
截图来自作者。
下一步,我们将使用用户选择的聚类数运行 K 均值算法。
使用实时输入运行 K-Means。
用下面的代码扩展导入、助手函数和主应用程序部分。
代码片段来自作者。
在上面的代码中,我们创建了一个函数来运行 K-Means 算法。它将数据框和聚类数作为参数,并返回一个 Matplotlib 图。
K-Means 聚类的示例超出了本项目的范围。这是一个机器学习算法,这才是我们关心的。不过你可以参考我之前的帖子描述一下。
我们使用 n_clusters 变量作为 run_forecast 函数的第二个参数,该变量捕获上一节中的滑块值。
如果你刷新页面,你会看到一个仪表板,接受用户输入,运行机器学习算法,并即时更新用户界面。
截图来自作者。
即使你是一个经验丰富的开发人员,这种级别的交互和与后端 ML 的集成也是一项艰巨的任务。尤其是如果你是一个不知道如何开发 web 应用的数据科学家,这可能会花费你数周的时间。
通过缓存提高性能。
数据科学管道中的一些任务非常耗时。然而,这种任务很少对相同的输入产生不同的结果。您可以使用 Streamlit 内置的缓存功能来存储它们的值以供将来使用。
虽然这听起来可能很复杂,但用 streamlit 做起来很简单。你的耗时任务应该是一个函数,你用 @ts 包装它。缓存装饰器。只要输入参数是相同的,并且函数体没有被改动,Streamline 就会从缓存中获取它。
在我们构建的应用程序中,我们调用外部 URL 来下载数据。如果它是一个活动的 API,您可能不想缓存它。但在我们的情况下,它不是。因此,让我们通过用下面的代码替换该行来缓存它。
来自作者的代码片段。
第一次重新加载时,您可能会在浏览器上看到消息“正在处理加载数据”。但随后的再装不会有那个音符。这是因为请求是从缓存中提取的,而不是从外部 URL 下载的。
在互联网上部署
如果您注意到了 Streamlit 控制台,您还会看到一个网络 URL。这意味着,如果您的防火墙允许,您的应用程序可以通过内部网访问。
但是如果你想在你的网络之外分享,我们有很多选择。正如文档所说,Streamlit 应用程序可以在 Python 应用程序工作的任何地方工作。
- Streamlit 推荐“Streamlit 共享”选项。你可以将你的代码放在 GitHub 存储库中,并配置 Streamlit 共享来为你的应用服务。
Streamlit 共享是免费的,但目前只接受邀请。您可以为自己申请邀请。 - 你可以把它部署在云平台上。这里有一篇文章展示了如何用 AWS EC2 free 实例做到这一点。
- 您可以配置一个反向代理。Nginx 和 Apache 之类的代理服务器可以配置为服务于应用程序,并限制特定用户的访问。
请务必阅读关于部署的 Streamlit 社区指南,探索您可用的众多选项。
以下是我如何在 Streamlit Share 上部署这个教程应用程序的。再一次,Streamlit 的便利让我大吃一惊。
第一步:将你的代码放入 GitHub 公共库。 我已经将我的代码添加到这个 GitHub repo 中。我们需要确保它包含一个 requirement.txt 文件以及所有的依赖项。
第二步:使用你的 GitHub 账号登录Streamlit。
第三步:在 Streamlit 控制台上创建一个新应用。 从下拉列表中选择您的 git hub repo,或者在 URL 中选择 past。选择要用于部署的分支。最后,选择主文件名并单击 deploy。
作者截图。
大约一分钟后,我的应用程序将在 Streamlit Share 上直播。但是部署时间可能因项目需求而异。
请注意,streamlit 共享目前只接受邀请。但我没等太久就拿到了。Streamlit 的部署文档包含了更多关于这方面的有用信息。
结论
不用说,Streamlit 解决了数据科学项目中的一个关键问题。它让数据科学家能够构建 web 应用程序,与他们的机器学习模型进行交互。
在这篇介绍性文章中,我们探讨了如何将 Streamlit 与 K-Means 聚类结合使用。虽然这是一个微不足道的应用程序,但它阐明了这项技术的核心概念。除了开发之外,我们还看到了如何在 Streamlit 中轻松管理缓存以提高性能。最后,我们讨论了部署选项。
细流远不止这些。请查看他们的官方文档,里面充满了优秀的教程。还有,他们的 API 备忘单有助于快速开发。
网络应用是一个很好的解决方案。但是在某些情况下,您可能不得不考虑与您的 ML 模型交互的其他方式。或许,为您的模型构建一个命令行界面会有所帮助。
谢谢你的阅读,朋友。看来你和我有许多共同的兴趣。一定要看看我的个人博客。
还不是中等会员?请使用此链接 成为 的会员。你可以享受成千上万的有见地的文章,并支持我,因为我赚了一点佣金介绍你。
如何创建 Tableau(业务)仪表板并利用容器
在本文中,我将给出如何创建业务仪表板的技巧,特别是如何利用容器。
Guillaume Bolduc 在 Unsplash 上拍摄的照片
(你也可以在 我的网站 上找到这篇文章以及其他文章和更多有趣的东西)
本文将部分基于我这个周末从超级商店数据集创建的工作簿,它是专门为本文制作的。
仪表板也可以在 Tableau 公共配置文件中找到, 此处,如果您想下载它并查看容器在仪表板中的使用情况。
仪表板的最终外观如下,稍后我将剖析仪表板的每个部分。
如何利用 Tableau 中的容器创建业务仪表板的 10 个技巧
这篇文章将基于我在创建业务仪表板时经常使用的 10 个技巧。其中许多将针对如何使用容器。
这些不是“神圣的真理”,但它们是我在尝试了许多不同的东西后,发现对我最有效的东西,我觉得分享这些东西很好。
提示如下:
- 画一个你想要的仪表盘的草图
- 从一个固定尺寸的较小仪表板开始
- 从一个垂直/水平浮动容器开始
- 给容器着色,从“后端”容器开始,以便更容易地构建仪表板
- 使用转换键移动集装箱
- 合并容器时,将容器放在的“正确位置”
- 利用并学习如何阅读项目层级****
- 使用“均匀分布内容”和“固定宽度”****
- 使用“空白对象”作为各部分之间的分隔物
- 从固定尺寸更改为“范围-最小尺寸”****
1.如果仪表板应该是水平/垂直的,请快速勾画出您希望仪表板的外观和设计
上面仪表板的快速草图
如果你在开始操作仪表板之前已经决定了你想要什么和你想要它在哪里,这将是一个比以后改变它更容易的过程。
尝试决定你想在哪里有仪表板的主要领域,你想有过滤器,你想有多少可视化和类似的方面。
这里你还应该看看你的设计是更“垂直”还是“水平”。我将构建的这个仪表板有非常具体的“行”,最好构建在垂直主题上。
2.从固定尺寸的较小仪表板开始
固定尺寸较小的仪表板(1000 x 800)
使用较小的固定尺寸仪表板比使用较大范围或自动仪表板更容易设置设计。
我通常会启动一个尺寸为 1000 px * 800 px 的新仪表板,并在我的笔记本电脑上进行最初的设计。
后来,当我以一种好的方式得到容器设计时,我换了一个更大的、范围大小的仪表板,准备用于生产环境。
3.从一个垂直/水平浮动容器开始,稍后您将“修复”它
****
启动浮动容器
我总是发现使用后端浮动容器更容易,当你完成设计后,你可以在后台“修复”它。
当您在第一层使用浮动容器而不是固定容器时,在内部插入新容器并让它们在正确的位置对齐似乎更容易。
(提示:按下容器时按住 shift ,如上图,不需要在下面的菜单中切换到浮动)
4.对容器进行着色/重命名,并从“后端容器”开始,以便更容易地构建仪表板
着色/重命名的容器具有更好的结构
下面是一个例子,我已经开始建立上面的仪表板。顶部容器被重命名为“过滤器容器”,颜色为灰色。
画布的主垂直容器名为“画布容器”,三个画布容器以不同的方式命名和着色。
通过使用这种结构,很容易找到您想要使用的容器**,并在正确的容器中插入新的容器和新的纸张。**
5.使用 shift 键在容器和移除的平铺容器之间移动
******
移除平铺的容器,如果你设法“把它贴在背景中”**
大多数人可能都知道,可以按住 shift 键来移动容器,并将它们合并到其他容器中。
但是如果你也想把一个容器从后面移出(不把它转换成 UI 中的浮动容器),你可以这样做,如果你在项目层次结构中移除平铺的容器。
6.合并容器时,将容器放在“正确的位置”
放下集装箱的正确方法,以便与之前的集装箱对齐
如果你有一个包含多个容器的层次结构,有时很难将新的容器放到正确的位置。有一些有用的技巧可以正确做到这一点。
a)如果您看到顶部图片中的虚线**,这意味着新容器被放入仪表板中最外面的容器中**
b)如果您事先在容器中有两个项目,您可以将新项目放在中间**,它将始终放在仪表板上最外面的容器中**
**c)如果你有一个垂直的容器,**容器的底部是最困难的部分,把它放在别的地方,然后在物品周围移动。
**d)如果你有一个卧式容器,**容器最右边的部分是最难的部分,把它放在别的地方,然后在物品周围移动。
7。利用并学习如何阅读项目层次结构(目录)
项目层次结构
项目层次结构类似于一篇较长文章中的目录,它更容易看到不同部分之间的相互关系,并获得整个仪表板设计的概述。****
您可以重命名项目层次中的所有部分,也可以直接移除项目,使其成为浮动/固定或平均分配项目。****
从本文中仪表板的特定层次结构中,我们可以看到:
**仅第 1 级
-
后端容器**
第二级
->-标题+过滤器容器-
->-顶部画布过滤器容器下面再往下****
**第三级
-
滤镜容器在“标题+滤镜”容器
-
三个不同的容器在“滤镜下的画布”容器内**
我认为项目层次结构是以正确的方式构建仪表板的最佳帮助之一。
8.使用“均匀分布内容”和“固定宽度”****
如果你想控制项目在不同显示之间切换时如何自动调整大小,那么如果你学会恰当地使用“平均分配内容”、“固定宽度”和“固定高度”,会有很大帮助。
我的一些规则是,我总是将过滤器和文本框放在它们自己的容器中,其中固定高度**(如果在顶部)固定宽度(如果在右侧/左侧)。**
这些不是在移动到更大显示时必须调整大小的仪表板项目,而是仪表板中的重要图表在不同大小之间移动时会适当调整大小。
如果您正确使用“平均分配内容”,当您在不同大小的显示屏之间移动时,您将不会在仪表板中有任何不必要的空白区域。
9.使用“空白对象”作为各部分之间的分隔物
****
如果你想要在不同的部分之间有一些特定的线条,你可以包括“空白对象”。
设置分隔线的背景,然后编辑分隔线的高度,我通常设置 2 为分隔线的高度。
10。包括填充,使仪表板更加直观
结论
有许多方法可以增强一个 Tableau 仪表板,容器在其中的许多方面发挥了很大的作用。
在本文中,我讨论了创建更好的 Tableau(业务)仪表板的 10 种不同方法。
其中最重要的是利用项目层次**,知道如何使用浮动与固定容器,并知道如何**“平均分配内容”与“固定宽度/固定高度”容器/仪表板项目。
我希望这些提示能在你阅读这篇文章的过程中对你使用 Tableau 仪表盘有所帮助。
感谢您的阅读
非常感谢你阅读我的博客!
请在下面留下您对内容的看法,或者希望就您如何利用容器或构建仪表板进行讨论。
我很想听听其他人是如何看待这些事情的。
**如果你喜欢阅读我的故事,并愿意支持我成为一名作家,可以考虑使用[这个链接](http://That’s it from my end for this blog. Thank you for reading! Let me know in the comments if you too learned something the hard way and wish your degree taught you. I would love to know more about your journey and thoughts. If you enjoy reading stories like these and want to support me as a writer, consider signing up to become a Medium member using this link (and I can earn a small commission with no extra cost to you!)) **,注册成为一名媒介会员,我和你可以赚取一小笔佣金,不需要额外的费用。
问题或询问
如果您有任何问题或建议,请联系我
****领英:www.linkedin.com/in/elias-nordlinder
邮箱:Elias.Nordlinder@gmail.com
网页:eliasnordlinder.com
祝大家这周过得愉快
更多推荐
所有评论(0)