三种你可能不知道的表示百分比的图表
原文:
towardsdatascience.com/three-charts-to-represent-a-percentage-you-may-not-know-84cc7d5c62a3
数据可视化,Python
一个即用的 Python Altair 教程,用于构建表示百分比的图表
·发表于 Towards Data Science ·5 分钟阅读·2023 年 8 月 23 日
–
Markus Winkler 拍摄的照片,来自 Unsplash
以视觉方式表示百分比可能会更吸引观众,并帮助他们更好地理解数据。有多种方式可以以视觉方式表示百分比。最直接的策略是大数字(BAN),如下图所示。
图片由作者提供
除了 BAN,还有其他方式可以以视觉方式表示百分比。在本文中,我们将重点介绍三种策略:
-
饼图
-
100% 堆叠图
-
华夫图。
我们将使用 Python Altair 展示如何构建每种策略。Vega-Altair 库(简称 Altair)是一个基于 Vega 和 Vega-Lite 可视化语法的声明式 Python 统计可视化库。有关如何开始使用 Altair 的更多细节,你可以阅读官方的 Python Altair 文档。
设置场景
为了展示每种图表的工作原理,我们将表示以下百分比:70%。为了表示这个值,你需要使用以下 Pandas DataFrame:
data = {
'percentage': [0.7,0.3],
'label' : ['70%','30%'],
'color' : ['#81c01e','lightgray']
}
df = pd.DataFrame(data)
DataFrame 必须包含两个值:百分比(70%)及其互补值(30%)。此外,我们设置了与每个切片相关的颜色:#81c01e(绿色的一种)用于我们的值,浅灰色用于其他。
让我们开始通过饼图来表示这个 DataFrame。
饼图
饼图是一种圆形图表,以环形显示数据。它类似于饼图,但中心有一个空洞,从而创建了不同类别百分比的可视化表示。
写下以下代码以在 Altair 中构建一个基本的甜甜圈图:
import pandas as pd
import altair as alt
data = {
'percentage': [0.7,0.3],
'label' : ['70%','30%'],
'color' : ['#81c01e','lightgray']
}
df = pd.DataFrame(data)
chart = alt.Chart(df).mark_arc(
innerRadius=100,
outerRadius=150
).encode(
theta='percentage',
color=alt.Color('color', scale=None),
tooltip='label'
).properties(
width=300,
height=300
)
chart.save('chart.html')
使用 innerRadius
和 outerRadius
设置甜甜圈图的内半径和外半径。
接下来,在甜甜圈图中添加文本,如下面的代码所示:
text = alt.Chart(df.head(1)).mark_text(
align='center',
baseline='middle',
fontSize=60,
fontWeight='bold',
color='black'
).encode(
text='label',
color=alt.Color('color', scale=None)
).properties(
width=300,
height=300
)
仅将 DataFrame 的第一行传递给图表,并使用 mark_text()
在 Altair 中绘制文本。同时,设置字体大小、粗细和颜色。
最后,结合这两个图表,如以下代码片段所示:
chart = (chart + text
).configure_view(
strokeWidth=0
)
chart.save('donut-chart.html')
以下图示显示了结果图表:
作者提供的图片
100% 堆叠条形图
100% 堆叠条形图是一种将每个条形图堆叠到 100% 高度的堆叠条形图,用于显示每个类别的比例组成。
写下以下代码以在 Altair 中构建一个基本的 100% 堆叠条形图:
import pandas as pd
import altair as alt
data = {
'percentage': [0.7,0.3],
'label' : ['70%','30%'],
'color' : ['#81c01e','lightgray']
}
df = pd.DataFrame(data)
chart = alt.Chart(df).mark_bar(
size=40
).encode(
x=alt.X('sum(percentage)', axis=None),
color=alt.Color("color", scale=None)
).properties(
width=300
)
接下来,在条形图中添加文本,如下面的代码所示:
text = alt.Chart(df.head(1)).mark_text(
align='center',
baseline='middle',
fontSize=20,
fontWeight='bold',
color='lightgrey',
dx=-30
).encode(
text='label',
x='percentage'
).properties(
width=300
)
最后,结合这两个图表:
chart = (chart + text
).configure_view(
strokeOpacity=0
)
chart.save('stacked-bar-chart.html')
以下图示显示了结果图表:
作者提供的图片
华夫图
华夫图使用方格来显示数据,类似于一堆华夫饼。
在构建华夫图之前,你必须设置 10x10 网格,如下面的代码所示:
import numpy as np
import pandas as pd
import altair as alt
# Compute x² + y² across a 2D grid
x, y = np.meshgrid(range(0, 10), range(0, 10))
ndex = 0
value = 70 # percentage
## calculate colors for each cell of the waffle chart
colors = []
for i in range(100,0,-1):
if i <= np.round(value):
colors.append(1)
else:
colors.append(0)
# Convert this grid to columnar data expected by Altair
df = pd.DataFrame({'x': x.ravel(),
'y': y.ravel(),
'z': colors})
接下来,使用 Altair 的 mark_rect()
标记方法构建你的华夫图:
chart = alt.Chart(df).mark_rect(
size=5,
stroke='black'
).encode(
x=alt.X('x:O', axis=None),
y=alt.Y('y:O', axis=None),
color=alt.condition(alt.datum.z == 0,
alt.value('lightgrey'),
alt.value('#81c01e')
)
).properties(
width=200,
height=200
)
可选地,在华夫图下方添加文本:
text = alt.Chart(pd.DataFrame({'label' : [value/100]})).mark_text(
align='center',
baseline='middle',
fontSize=30,
fontWeight='bold',
color='#81c01e'
).encode(
text=alt.Text('label', format='.0%'),
).properties(
width=200
)
最后,结合这两个图表并保存最终图表:
chart = chart & text
chart.save('waffle-chart.html')
以下图示显示了结果图表:
作者提供的图片
总结
恭喜你!你刚刚学会了在 Python Altair 中表示百分比的三种不同方法:
-
通过
mar_arc()
标记方法绘制甜甜圈图 -
通过
mark_bar()
标记方法绘制 100% 堆叠条形图 -
通过
mark_rect()
标记方法绘制华夫图。
感谢阅读这篇博客文章!如果你有任何问题或意见,请留言或直接在 LinkedIn 上联系我。我很乐意与你联系!
你可以在我的书的 GitHub 仓库 中找到这个示例的完整代码,Data Storytelling with Generative AI using Python and Altair 的第六章。
相关文章
## 3 种在 Python Altair 中构建地理地图的方法
一项关于如何在 Python Altair 中构建三种不同地图的数据可视化教程:区划图、点密度图……
[towardsdatascience.com ## 3 种你可能不知道的时间序列可视化方法
一个关于如何在 Python 和 Altair 中可视化时间序列的即用教程
towardsdatascience.com
参考资料
-
A. Lo Duca 《使用 Python 和 Altair 的生成性 AI 进行数据讲述》 曼宁 2024
-
A. Lo Duca 《使用 Python Altair 和生成性 AI 进行数据讲述》 — GitHub 仓库
在你离开之前…
要查看 Altair 的实际应用,请观看视频教程。
常见强化学习算法的三个根本性缺陷(及其修复方法)
对抗在日常强化学习算法中遇到的这些缺陷
·发布于 数据科学前沿 ·阅读时间 8 分钟·2023 年 1 月 30 日
–
图片由 Varvara Grabova 提供,来源于 Unsplash
像 Q 学习和 REINFORCE 这样的强化学习算法已经存在了几十年,其教科书中的实现仍然被广泛使用。不幸的是,它们存在一些根本性的缺陷,这大大增加了学习良好策略的难度。
本文讨论了经典强化学习算法的三个主要缺陷,并提出了克服这些缺陷的解决方案。
I. 选择被高估的动作
问题
大多数强化学习算法使用某种形式的价值函数来捕捉后续奖励,其中许多基于广为人知的 Q 学习算法。Q 学习的机制是选择带来最高期望值的动作。根据初始化情况,这一机制可能会在尝试的第一个动作上陷入困境,因此我们还以概率ϵ选择随机动作,通常设定为 0.05 左右。
在极限情况下,我们将无限次地探索每个动作,Q 值将收敛于真实值。然而,在实践中,我们处理的是有限样本和有偏的 Q 值。因此,Q 学习一贯选择具有高估值的动作!
想象这样一个场景,我们玩两个完全相同的老虎机。机器 A 在早期迭代中给出的奖励高于平均水平,因此其 Q 值更高,我们持续玩 A。由于机器 B 仅偶尔被选择,我们需要很长时间才能发现 Q 值实际上是相同的。
更一般地说,价值函数总是会存在不完美之处,而强化学习往往会执行过高估值的动作。从某种意义上说,强化学习“奖励”了糟糕的估计,这显然不是一个理想的特性。
多臂老虎机问题清楚地展示了选择过高估值动作的影响[照片由Bangyu Wang提供,见Unsplash]
解决方案
Q 学习的问题可以追溯到使用相同观察进行采样和更新的实践。我们可以通过使用一个策略进行采样,另一个策略进行更新来解耦这些步骤。这正是双 Q 学习(Van Hasselt, 2010)所做的。
双 Q 学习使用一个网络来采样动作,但用另一个网络的输出更新 Q 值。这一过程将采样和学习解耦,并且克服了过度估计。[来源:Van Hasselt (2010)]
更一般地说,使用目标网络是一个良好的实践。目标网络是策略的周期性副本,用于生成我们训练的目标值(而不是使用完全相同的策略来生成观察和目标)。这种方法减少了目标与观察之间的相关性。
另一种解决角度是考虑我们 Q 值估计的不确定性。与其仅仅记录动作的期望值,我们还可以跟踪观察的方差,以指示我们可能偏离真实值的程度。使用不确定性边界和知识梯度是实现这一目标的两种方法。我们不仅考虑选择具有最高期望 Q 值的动作,还考虑从新观察中能学到多少。这种方法偏向于探索具有高不确定性的动作,同时仍然进行智能采样。
你应该知道的七种强化学习探索策略
纯探索和-利用,ϵ-贪婪,玻尔兹曼探索,乐观初始化,置信区间……
towardsdatascience.com
II. 糟糕的策略梯度更新
问题
策略梯度算法已经存在了几十年,并且是所有现代演员-评论员模型的根基。普通的策略梯度算法——例如 REINFORCE——依赖梯度来确定权重更新的方向。高奖励和高梯度的组合会产生强烈的更新信号。
传统的策略梯度更新函数,通过目标函数梯度 ∇_θJ(θ) 和步长 α 来更新策略权重 θ。
这个想法似乎很自然。如果奖励函数的斜率很陡,你就朝那个方向迈出大步。如果斜率很小,那就没有必要进行大幅更新。虽然这个逻辑可能很有说服力,但它也是根本有缺陷的。
左:超调行为的示例,进行了一次大幅策略更新但错过了奖励峰值。右:停滞行为的示例,被困在局部最优点,梯度接近 0。 [图像由作者提供]
梯度仅提供局部信息。它告诉我们斜率的陡峭程度,但不告诉我们在该方向上应走多远;我们可能会超调。此外,策略梯度并未考虑缺乏梯度信号可能会使我们陷入次优平稳点。
更糟的是,我们无法通过强制权重更新在某个参数区域内来控制这种行为。例如,在下面的图中,相同幅度的权重更新对策略产生了非常不同的效果。
两个高斯策略更新的示例。尽管这两个更新在参数空间中的大小相同,但左侧的策略显然受到的影响要大得多,而右侧的影响则较小 [图像由作者提供]
解决方案
一个简单的开始是尝试各种学习算法。传统的随机梯度下降(SGD)算法只考虑一阶矩。现代学习算法(例如 ADAM)考虑了二阶矩,通常会显著提升性能。虽然不能完全解决问题,但性能提升可能会非常显著。
熵正则化是一种常见的方法来防止普通策略梯度算法的过早收敛。大致来说,强化学习中的熵是衡量动作选择不可预测性的指标。熵正则化为探索未知动作添加了奖励,当我们对系统了解较少时,这种奖励会更高:
强化学习中的熵度量
更复杂的策略梯度算法扩展还考虑了二阶导数,这提供了函数的局部灵敏度信息。在平稳区域,我们可以安全地大步前进而不会产生后果。在陡峭但弯曲的坡度上,我们则会更倾向于谨慎地前进。诸如 自然策略梯度、 TRPO 和 PPO 之类的算法考虑了更新的敏感性,无论是显式还是隐式地考虑了二阶导数。目前,PPO 是首选的策略梯度算法,在实现的便利性、速度和性能之间取得了良好的平衡。
自然策略梯度的权重更新方案。F(θ) 的 Fischer 矩阵包含关于局部灵敏度的信息,生成动态权重更新。
传统的策略梯度方法固有地存在缺陷。自然梯度收敛更快、更好,形成了…
towardsdatascience.com ## 信赖区域策略优化(TRPO)解释
强化学习算法 TRPO 基于自然策略梯度算法,确保更新保持…
towardsdatascience.com ## 近端策略优化(PPO)解释
从 REINFORCE 到在连续控制中的首选算法的旅程
[towardsdatascience.com
III. 性能不足的离策略学习
问题
某些算法(例如,基于 Q 学习的算法)依赖于 离策略学习,这意味着 更新可能会使用与实际观察到的不同的动作。而在策略学习中需要一个元组 (s,a,r,s’,a’) — 实际上,就像其算法名称 SARSA 一样— 离策略学习使用已知的最佳动作 a 而不是 a’。因此,我们只存储 (s,a,r,s’) 用于权重更新,并且学习策略独立于代理的动作。
由于其设置,离策略学习可以通过从经验回放缓冲区中提取先前观察进行重用,这在生成观察(计算上)昂贵时尤其方便。我们只需将状态s’输入到我们的策略中以获得动作a,使用得到的值来更新 Q 值。状态从s到*s’*的转移动态不需要重新计算。
不幸的是,即使在大型数据集上广泛训练离策略强化学习算法,当部署时,它通常表现得远不如预期。这是为什么呢?
问题归结为一个常见的统计学警告。假设是训练集代表真实数据集。当这种情况不成立时——通常是不成立的,因为更新的策略生成了不同的状态-动作对——策略就会拟合一个不反映代理最终操作环境的数据集。
解决方案
真实的离策略学习——例如,仅从静态数据集中学习良好的策略——在强化学习中可能从根本上是不可行的,因为更新策略不可避免地会改变观察到状态-动作对的概率。由于我们无法彻底探索搜索空间,我们不可避免地将值外推到未见的状态-动作对。
最常见的解决方案是不要在完全静态的数据集上训练,而是不断丰富数据集,添加在新策略下生成的观察。也可以考虑移除旧的样本,这些样本不再代表最近策略生成的数据。
另一个解决方案是重要性采样,本质上是根据观察在当前策略下生成的可能性重新加权观察。对于每个观察,我们可以计算它在原始和当前策略下生成的概率的比率,使得来自相似策略的观察更可能被抽取。
重要性采样考虑原始策略和目标策略之间的相似性,以更高的概率选择在与当前策略相似的策略下生成的观察。
如果你继续在样本外使离策略算法表现不佳,可以考虑切换到在策略算法。特别是当生成新观察很便宜时,样本效率的损失可能会被增强的策略质量所弥补。
关于使用 TensorFlow 2.0 进行稳定和成功的深度 Q 学习的三种基本技巧的快速教程
[towardsdatascience.com
摘要
这篇文章解决了传统强化学习算法中遇到的三个常见缺陷,以及应对这些缺陷的策略。
I. 高估的动作
问题:
- 基于价值函数逼近的算法系统性地选择具有高估值的动作。
解决方案:
-
使用目标网络减少目标和观察之间的相关性(例如,如在双重 Q 学习中)。
-
在动作选择中纳入价值估计的不确定性(例如,不确定性边界、知识梯度)。
II. 策略梯度更新不良
问题:
- 策略梯度算法常常执行不佳的更新步骤,例如,当陷入局部最优时采取小步,或当过度步骤时错过奖励峰值。
解决方案:
-
使用包括例如 ADAM 的学习算法——它除了跟踪一阶梯度外,还跟踪动量——而不是标准的随机梯度下降。
-
向奖励信号中添加熵奖励,鼓励对未知区域进行更多探索。
-
部署包含二阶导数的算法(无论是显式还是隐式),如自然策略梯度、TRPO 或 PPO。
III. 离策略学习的表现不足
问题:
- 回放缓冲区中的经验可能无法代表样本外的经验,从而导致值被错误地外推并且性能下降。
解决方案:
-
更新回放缓冲区,添加新的经验并删除旧的经验。
-
执行重要性采样以增加选择来自更接近目标策略的策略的经验的概率。
-
切换到在线学习(如果采样观察很便宜)。
参考文献
问题 I: 高估的动作
Hasselt, H. (2010). 双重 Q 学习。神经信息处理系统进展,23。
Matiisen, Tambet (2015). 解密深度强化学习。计算神经科学实验室。取自 neuro.cs.ut.ee/demystifying-deep-reinforcement-learning/
问题 II: 策略梯度更新不良
Mahmood, A. R., Van Hasselt, H. P., & Sutton, R. S. (2014). 具有线性函数逼近的离策略学习的加权重要性采样。神经信息处理系统进展,27。
康奈尔大学计算优化开放教材。 (2021). ADAM。网址:optimization.cbe.cornell.edu/index.php?title=Adam
问题 III: 离策略学习的表现不足
Fujimoto, S., Meger, D., & Precup, D. (2019 年 5 月). 无探索的离策略深度强化学习。在 国际机器学习大会(第 2052–2062 页)。PMLR。
阈值化 — 使图像更清晰的方式 (CV-04)
原文:
towardsdatascience.com/thresholding-a-way-to-make-images-more-visible-b3e314b5215c
通过阈值化从图像中提取更多信息
·发表于 Towards Data Science ·阅读时间 7 分钟·2023 年 4 月 26 日
–
图片由 Jonas Svidras 提供,来源于 Pixabay
动机
在现实世界中,我们并不总是处理百分之百清晰的图像。有时,图像会变得模糊、扭曲等等。从这些类型的图像中提取信息成为一个关键问题。这就是为什么透明、清晰和更具视觉吸引力的图像在获取全面信息方面扮演着重要角色。
左侧图像取自pxfuel,并且在创意共享许可下使用。右侧图像是应用阈值化后的生成结果。
阈值化后的图像更具视觉清晰度。除了图像,这种阈值化技术在数千种应用场景中可能会很有帮助。如果你读到文章的最后,你将掌握 如何使用、在哪里使用以及何时使用 图像阈值化的技能。
具体来说,图像阈值化将图像转换为二值图像,以提取更多信息。
目录
-
什么是图像阈值化?
-
全局阈值化与局部阈值化的区别
-
流行的阈值化技术和 Python 实现
什么是图像阈值化?
图像阈值化作用于灰度图像。这是一种将灰度图像分割成二值图像的方法 [1]。对于阈值化,某个特定的像素强度值被视为阈值值。所有大于或小于阈值的像素都被分配为最大或最小值。这将整个图像转换为二值图像。因为现在只有两种像素值。
假设我们想对像素强度值 123、50、180、200 应用图像阈值化。我们将阈值设置为 128。因此,所有大于 128 的值将变为最高的像素强度值 255,而小于 128 的值将变为 0。
左侧的图像是阈值化后的结果,右侧的图像是阈值化之前的图像(来自 Wikimedia Commons,公共领域许可)
看一下上面的两张图像。应用阈值化后,得到的图像完全是白色或黑色。相对高强度值的像素被转换成完全白色(强度值 255),而低强度值则变成纯黑色(强度值 0)。
全局阈值化和局部阈值化的区别
有许多阈值化技术可用。
相同的过程或阈值通常应用于整个图像。这种类型的阈值化被称为 全局阈值化。
另一方面,局部/自适应阈值化在局部区域内工作。相同的阈值值不会应用于整个图像。我们可以对图像的不同部分应用不同的阈值值。
全局图像阈值化并不适用于所有情况。有时自适应阈值化更为合适。看看下面的图像。
图像来自于 OpenCV 文档
在原始图像中,光照在不同图像位置上有所变化。对整个图像应用相同的阈值将产生类似于全局阈值化图像的结果。自适应阈值化提供了更好的结果。
流行的阈值化技术和 Python 实现
我们将讨论 全局阈值化 技术——*简单阈值化和 Otsu 阈值化*
。以及局部/自适应阈值化技术。
- 简单阈值化
简单阈值化是一种全局阈值技术。在这种方法中,我们需要设置一个边界(阈值)强度值。阈值值用于转换新的像素强度值。看看下面的表格。
不同的简单阈值化技术(图像由作者提供)
看看上面的表格。在操作部分,
pixel(x,y)
表示阈值化图像的更新后的特定强度值,而src(x,y)
表示应用阈值化之前图像的原始强度值。
⭐ Python 实现️
为了演示目的,我使用了以下图像。
一些通用代码用于导入库和加载图像 —
阈值化始终作用于灰度图像。因此,我将图像从 BGR(OpenCV 通常以 BGR 格式读取图像)转换为灰度图像,代码为cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
。
二值阈值化
**OpenCV**
库通过提供各种函数来实现计算机视觉技术,使我们的工作变得更加轻松。以下代码片段帮助我们实现二值阈值化。其中120
是阈值,255
是最大强度值。因此,所有低于120
的强度值将被设为0
,其余为255
。
输出会因不同的阈值而有所变化。
二值反向阈值化
这正好是二值化阈值的反向操作。我们将阈值设为120
,最大值设为255
。因此,所有低于120
的强度值将为255
(白色),其余为0
(黑色)。请查看以下代码。
因此,在二值反向阈值的情况下,输出正好是二值阈值的相反结果。
截断阈值化
在我们的编码示例中,我们将阈值设为145
,最大值设为255
。因此,对于截断阈值化,所有低于145
的值将被设为阈值145
。否则,它将保持不变。
输出文本比之前的技术更为清晰可见。
阈值为零
在阈值为零的情况下,低于阈值的像素值将被设为零,否则保持不变。为了演示目的,我将阈值设置为 145,最大值设置为 255。代码如下所示。
阈值反转
这正好是阈值为零的相反操作。
大津法阈值化
大津法的阈值化与简单阈值化有所不同。它通过计算类间方差来设置阈值。有两个类别,即背景和前景像素。类间方差可以通过以下公式计算。
在这里,背景和前景类的平均权重分别用Wb和Wf表示。类的均值权重用µb和µf表示。我们需要计算所有像素强度值的类间方差。最终,选择类间方差最高的阈值。
为了演示目的,下面给出了一个示例。
3 x 3 图像(图像由作者提供)
在上图中,圆圈内的值是每个像素的强度值。像素强度为***0,1,2, 和 3***
。强度值的频率如下所示。
在这里,我们将阈值设置为 2。所有小于 2 的值被视为背景,大于或等于 2 的值是前景。在上述图表中,红色条是背景频率,绿色条代表前景频率。
阈值计算如下所示。
阈值 2 的类间方差计算(图片作者提供)
其他阈值 0、1 和 3 的类间方差见下表。
图片由作者提供
最大的类间方差为 0.89,与阈值 2 相关。因此,根据 Otsu 方法,阈值为 2。
以下是对之前图像的 Python 实现。
这个结果非常棒,与之前的技术相比效果很好。让我们看看 Otsu 阈值处理的阈值。
自适应/局部阈值处理
在自适应/局部阈值处理的情况下,整个图像被分成一些分段,并对每个分段应用全局阈值。当光照均匀分布时,这种阈值处理更为可取。
演示灰度图像具有 6 个不同的分段(图片作者提供)
跟随灰度图像。方框是图像的分段。在自适应阈值处理的情况下,每个分段会被分开以应用全局阈值。因此,我们可以调整每个区域/分段的阈值。
文本图像上的自适应阈值处理实现如下所示。
结果也令人满意。
我们还可以将两个阈值输出进行融合以提取更多信息,如下所示。
结论
图像阈值处理是从模糊或不清晰的图像中提取信息的最佳方法之一。阈值处理技术不限于上述技术,但这些技术被广泛使用。选择何时使用哪种阈值处理技术完全依赖于你;我相信如果你对上述方法有清晰的概念,你将能够做出正确的决定。
参考文献
通过以下链接支持我的写作。
[
mzh706.medium.com/membership](https://mzh706.medium.com/membership)
我计算机视觉系列的先前文章 —
[## NumPy 和 OpenCV 计算机视觉入门 (CV-01)]
使用 Python 开始你的计算机视觉编码
towardsdatascience.com ## 关于计算机视觉中色彩表示的全面指南 (CV-02)
颜色空间和颜色模型的详细解释
[towardsdatascience.com ## 最简单的图像融合指南 (CV-03)
最简单的图像融合和粘贴指南
[towardsdatascience.com
透过镜子,谷歌在眼睛中发现了什么
原文:
towardsdatascience.com/through-the-looking-glass-and-what-google-find-there-in-the-eye-e7a836eb9571
| 计算机视觉 | 医疗 AI | CNN
或者,谷歌如何利用深度学习来诊断眼部照片中的疾病
·发表于Towards Data Science ·阅读时间 12 分钟·2023 年 3 月 30 日
–
图片由作者使用 OpenAI DALL-E 生成
谷歌最近发布了一篇科学论文,展示了人工智能模型如何通过一张简单的眼睛照片预测多个系统性生物标志物。
这如何运作?这些结果是如何得出的?这为何重要?我们将在本文中讨论这些问题。
眼睛中的隐藏宝藏
图片由v2osk提供,来自 Unsplash
疾病诊断通常需要昂贵仪器的检查,然后由受过训练的医疗专业人员进行解读。这并不总是可行。并非所有医院都有相同的仪器,有时还缺乏专家。
例如,糖尿病视网膜病变(DR)的诊断需要使用检查眼睛后部的眼底相机。这需要由资质高的人员进行分析。此检查还可以揭示其他状况,如心血管风险、贫血、慢性肾病及其他系统性参数。
曾经认为,眼底图像可以使用机器学习算法进行分析。然而,谷歌发布的一篇论文在 2017 年展示了外部眼睛照片能够诊断糖尿病视网膜病变并检测血糖控制不佳。
“糖尿病相关并发症可以通过使用专用相机拍摄眼底照片来诊断,这些照片可视化眼睛的后部区域。相反,使用标准消费级相机进行前眼成像可以揭示影响眼睑、结膜、角膜和晶状体的情况。” 图片来源:这里
在这项工作中,作者使用了来自加利福尼亚和其他队列的 145,832 名糖尿病患者的照片。作者然后使用了Inception V3(它之前已经在ImageNet上进行过训练)进行这项研究,结果显示:
我们的结果显示,眼睛的外部图像包含糖尿病相关视网膜病变、血糖控制不良和脂质升高的信号。(来源)
简而言之,Inception V3 当时在 ImageNet 上展示了最先进的性能(准确率 > 78.1%)。此外,Inception 比以前的模型计算效率更高。该模型通过使用并行结构(在同一个块中使用不同类型的卷积层)和积极的正则化来达到这些结果。在同一篇文章中,作者定义了一些原则,这些原则在接下来的几年里塑造了卷积神经网络(CNN)领域:
-
避免表示瓶颈。表示大小应从输入到输出逐渐减少。
-
高维表示在网络内部本地处理起来更容易。这显示出可以更快地训练网络。
-
空间聚合可以更好地减少维度而不会丢失信息
-
平衡网络的宽度和深度
“模型的高层次图示” 图片来源:这里
作者使用了经典的监督学习,实际上,他们使用了患者眼睛的图像作为是否存在疾病(糖尿病视网膜病、升高的血糖或升高的脂质)的基础真值。因此,训练出的模型在糖尿病视网膜病诊断方面显示出超过 80%的曲线下面积(AUC),而对于血糖和脂质则显示出突出的(但较低的)结果。
结果令人惊讶,因为通常这些系统参数可以从前眼得出,而这项初步研究表明,从外眼的照片中,通过深度学习也可以得出相同的结论。
此外,通过使用消融研究和显著性图,作者也能更好地理解模型为何做出这些预测:
首先,消融分析表明,对于所有预测,图像的中心(瞳孔/晶状体、虹膜/角膜和结膜/巩膜)比图像的周边(例如眼睑)更为重要。其次,显著性分析同样表明,DLS 最受图像中心附近区域的影响。(来源)
重要性图。图片来源:这里
消融研究:图像不同区域的重要性。图片来源:这里
这些结果表明,对于日益增长的糖尿病患者群体,一些参数可以在不需要专业医疗人员的情况下进行测量。此外,外眼的照片也可以使用简单相机拍摄获取。
虽然需要进一步工作来确定是否有额外的要求,例如光线、拍摄距离或角度、图像稳定性、镜头质量或传感器保真度,但我们希望通过外眼图像进行疾病检测的技术最终可以广泛提供给患者,无论是在诊所、药店还是在家中。(来源)
无论如何,目前这些模型并不打算取代广泛筛查,而是用于标识哪些患者需要进一步筛查(这种方法比问卷调查更可靠)。
作者们继续评估模型,并引起了对潜在偏见和包含问题的关注。确实,生物医学领域人工智能模型最大的问题之一是,如果数据集不能代表总体人群,这可能会导致误导性结果。
我们的开发数据集覆盖了美国范围内多个不同地点,包括在 301 个糖尿病视网膜病筛查点拍摄的超过 300,000 张去标识化照片。我们的评估数据集包括来自 18 个美国州的 198 个地点的超过 95,000 张图像,其中包括主要为西班牙裔或拉丁裔患者的数据集、主要为黑人患者的数据集以及包括非糖尿病患者的数据集。我们对不同人口统计学和身体特征(如年龄、性别、种族和民族、白内障存在、瞳孔大小,甚至相机类型)的患者群体进行了广泛的亚组分析,并将这些变量作为协变量进行控制。(来源)
眼睛,灵魂的镜子
图片由Caroline Veronez在 Unpslash 提供
Google 和其他研究人员也认为这种方法很有前途。因此,他们后来尝试将其扩展到其他标记和其他疾病。
到目前为止,作者已展示他们的模型能够有效诊断眼科疾病(糖尿病视网膜病)。另一方面,疾病种类繁多,诊断复杂(例如,找到合适的测试,昂贵的仪器并不总是存在等等)。因此,问题仍然是模型是否也能捕捉到眼睛图像中的其他疾病迹象。
我们可以将这种方法扩展到其他疾病吗?
毕竟,深度学习模型能够识别那些微妙的模式,而这些模式可能对非专家来说难以识别。考虑到这些假设,Google 研究人员决定测试是否可以在眼底图像中检测心血管风险因素。
心血管疾病是全球主要死亡原因,能够早期诊断可能拯救无数生命。此外,风险分层对于识别和管理高风险患者群体至关重要。通常,通过病史和不同测试(血糖和胆固醇水平的血液样本、年龄、性别、吸烟状态、血压和体重指数)获得的多个变量用于诊断和分层患者。有时所有必要的数据可能并不齐全(如一项综述研究所示)。
这项研究的作者展示了不仅可以预测一些患者特征(在某些数据未记录或缺失的情况下非常有用),例如BMI、年龄、性别和吸烟状态,还可以预测与心血管疾病相关的参数,例如收缩压(SBP)和舒张压(DBP)。
“左上角的图像是来自英国生物库数据集的彩色视网膜图像样本。其余图像显示的是相同的视网膜图像,但为黑白色。每个预测的软注意力热图以绿色覆盖,指示神经网络模型在进行图像预测时所使用的热图区域。” 图片来源:这里
作者们也使用了相同的 Inception V3 模型。此外,为了处理连续变量,作者们使用了分箱技术,基本上是将变量划分为不同的区间,使用不同的分割点(例如,<120,120–140,140–160 和 ≥160 作为 SBP)。
此外,作者使用了一种称为soft attention的技术来识别与特定特征相关的区域。简而言之,soft attention是一种考虑图像不同子区域并使用梯度下降和反向传播的方法(无需在模型中实现注意力机制)。
soft-attention 可以帮助发现模型的预测错误。图像来源:这里
在另一项工作中,作者测试了贫血。一种影响超过 16 亿人的病症,需要监测血红蛋白浓度以进行诊断(这是一种侵入性测试,可能引起疼痛和感染风险)。
使用深度学习对贫血分类进行预测。图像来源:这里
在这种情况下,他们使用了Inception V4。这是一个比之前描述的模型更晚的版本(在这篇后续文章中,作者描述了通过添加残差连接可以改进 Inception V3 的架构)。Inception V4 展示了如何测试和使用不同类型的 Inception 块(其中有不同的卷积层,既有并行也有顺序)。
残差连接。图像来源:这里
在这项后续工作中,Google 展示了这种方法不限于分类(患者是否有贫血),还包括是否可以测量血红蛋白浓度(回归任务)。作者训练了一个用于分类的模型和一个用于回归任务的模型(Inception V4,预训练于 ImageNet)。
对于回归问题,作者仅使用了均方误差作为损失函数(而非交叉熵)。最终的预测是通过创建一个包含 10 个模型的集成(以相同方式训练)来实现的,并将这些模型的输出进行平均,以得到最终的预测结果。
“预测血红蛋白浓度。每个蓝点代表每位患者的测量血红蛋白浓度和预测值”。图片来源:这里
广阔景观的一瞥
图片由Bailey Zindel提供,来源于 Unsplash
到目前为止,研究人员观察到的通常是少量参数。通常,血液检测可以在一次检查中监测更多的参数。一个眼睛的照片模型能否估计一组系统性生物标志物?
这是谷歌今年测试并刚刚发布的内容:
[## 一种用于外眼照片中新型系统性生物标志物的深度学习模型:…
系统性疾病引起的眼部后遗症已被充分记录,并作为全球公认的基础…
www.thelancet.com](https://www.thelancet.com/journals/landig/article/PIIS2589-7500%2823%2900022-5/fulltext?source=post_page-----e7a836eb9571--------------------------------)
显然,这不是一项容易的任务,部分原因是当你想进行这样的分析时,存在发现虚假和错误结果的风险(也称为多重比较问题)。换句话说,同时进行的统计推断越多,发现错误推断的风险就越大。
虚假相关的示例。图片来源:这里
因此,作者首先将数据集分成两部分。他们在“开发数据集”上训练模型并进行分析,选择了九个最有前景的预测任务,并在测试数据集上评估了模型(他们仍然纠正了多重比较)。
他们首先收集了包含眼睛图像和相应实验室测试结果的数据集。然后,作者训练了一个卷积神经网络,该网络以外眼图像为输入,并预测临床和实验室测量结果。在这种情况下,这是一个多任务分类,每个任务都有一个预测头(以便可以使用交叉熵作为损失)。作者决定为每个任务选择阈值(与临床医生协商后选择)。
在这种情况下,作者使用了 2020 年发布的 Big Transfer(BiT)模型,该模型在训练时能够在各种其他数据集上很好地推广。简而言之,该模型与 ResNet 非常相似,不过在训练过程中使用了一些技巧,例如组归一化(GN)和权重标准化(WS)。你可以在这个GitHub 仓库中找到该模型。
预训练模型的转移性能超越了现有技术。图像来源:这里
超过了基线模型(对患者数据进行的逻辑回归)。虽然这些结果仍然不足以用于诊断应用,但与初步筛查工具一致(糖尿病预筛查)。
基线模型与深度学习模型的 AUC 比较。图像来源: 这里
在本研究及之前的研究中,作者使用了桌面相机(患者还使用了头托)获取图像,并在良好的照明条件下生成了高质量的图像。因此,作者尝试通过降低分辨率来查看模型是否有效。
作者注意到,即使将图像缩小到 150x150 像素,模式仍然对图像质量具有鲁棒性。
这个像素计数低于 0.1 百万像素,比典型的智能手机相机要小得多。(来源)
“输入图像分辨率的影响。 上图: 为本实验缩放到不同尺寸的样本图像。 下图: DLS 在图像尺寸下的性能比较”。图像来源:这里
此外,作者研究了图像的哪个部分对模型的预测目的重要。为此,作者在训练和评估期间遮蔽了几个区域(瞳孔或虹膜,将图像转换为黑白)。
结果表明,信息通常不仅仅局限于瞳孔或虹膜,并且颜色信息对大多数预测目标至少有一定的重要性(来源)
实验遮蔽不同的图像区域或移除颜色**。** 图像来源:这里
尽管这篇文章令人印象深刻,但仍然存在一些局限性。实际上,认为它可以在现实世界中使用仍然为时尚早。首先,照片是在最佳条件下获取的,我们需要验证在其他条件下获取的照片的准确性。
此外,这项工作中使用的数据集主要包括糖尿病患者,并没有充分代表一些重要的亚组——在考虑临床使用之前,需要对 DLS 的改进和评估进行更加针对性的数据收集,包括对更广泛人群和亚组的评估。(来源)
分析思考
来自 Saif71.com 在 Unsplash 的图片
如本文所示,深度学习模型能够捕捉眼睛中的模式和信息,这些信息有时难以诊断。此外,诊断通常使用昂贵的工具和侵入性测试,并且需要经验丰富的人员。Google 多年来已经表明,可以通过眼睛的图像获取类似的信息。
未来,许多疾病可以通过简单的眼睛外部照片来诊断(或至少进行初步筛查)。这些照片可以通过手机摄像头简单地拍摄。此外,由于可以获得定量结果(如血红蛋白浓度),这些结果可以用于非侵入性的患者监测。
在技术方面,有趣的是像 Inception V3 这样的模型如何在第一次尝试时就取得了结果。这表明迁移学习和卷积网络的能力。此外,作者对模型进行了分类、回归和多任务分类的适配。
然而,还有几个情境是开放的。显然,Google 计划扩展数据集(正如他们在文章中所写的)。另一方面,作者使用了 CNN,也可以测试其他几种模型,如视觉变换器。此外,未来他们也可能会尝试使用语言模型作为输入,这些输入包括患者或医生的笔记(毕竟,未来是多模态的)。
另一方面,尽管这些应用可以用于没有装备医院的患者,但它也引发了伦理问题。如所见,模型还能够预测诸如年龄、性别、生活方式(吸烟/不吸烟)以及其他参数等敏感数据。这项技术也可能用于其他更具争议的应用。
无论如何,这些研究开启了非常有趣的应用领域。这不仅仅是 Google 在研究这样的模型。例如,其他团队已经显示,其他疾病如肝胆疾病可以通过眼睛识别,其他疾病也可能在不久的将来被识别。
如果你觉得这很有趣:
你可以查看我的其他文章,也可以订阅以便在我发布文章时获得通知,还可以通过LinkedIn联系我。
这是我 GitHub 仓库的链接,我计划在这里收集与机器学习、人工智能等相关的代码和许多资源。
[## GitHub - SalvatoreRa/tutorial: 关于机器学习、人工智能、数据科学的教程…
提供关于机器学习、人工智能、数据科学的教程,包括数学解释和可重用的代码(用 Python…
或许你对我最近的一篇文章感兴趣:
语言模型和人脑在自然语言处理方面仍存在差距,激励人工智能填补这一差距
towardsdatascience.com ## 谷歌 Med-PaLM:人工智能临床医生
谷歌的新模型经过训练可以回答医学问题。怎么做的?
towardsdatascience.com ## 多模态思维链:解决多模态世界中的问题
世界不仅仅是文字:如何将思维链扩展到图像和文字?
towardsdatascience.com [## 稳定扩散填补医疗图像数据中的空白
一项新研究表明,稳定扩散可能有助于医学图像分析和稀有疾病。怎么做的?
抛出一只猫到鸽子中间?用大型语言模型增强人类计算能力
生成性人工智能的时代提供了改善群体工作机会的可能性,而不一定是取代它
·
关注 发表在Towards Data Science ·12 分钟阅读·2023 年 7 月 21 日
–
照片由Steve Johnson拍摄,来源于Unsplash
我一直对词源学充满兴趣。通常,单词和短语如何获得我们熟悉的意义背后有一个引人入胜的故事。随着时代的变迁,词汇也在不断演变。机械土耳其人是 18 世纪匈牙利作家和发明家沃尔夫冈·冯·肯佩伦制造的一个下棋类人形机器。传说机械土耳其人在欧洲巡演,并在传说中的棋局中击败了拿破仑·波拿巴和本杰明·富兰克林等显赫人物。直到后来,真正的秘密才被揭示出来,原来是一个隐藏在地板下的真实人类棋手,在那里操控着机械人形的走棋。
这个故事启发了 2005 年推出的亚马逊机械土耳其人众包平台的命名。该平台旨在解决当时的替代方案无法解决的任务,并需要人工输入或智能。在这种背景下,“人工人工智能”的概念形成了,人类在机器能力之外提供智能。我们已经从那里走了很长一段路,达到了全新的“人工人工人工智能”概念的边缘。没错,你没看错,三个人工。在你试图用额头破解这个难题之前,让我们快速回顾一些记忆。
众包的早期日子
在他 2004 年出版的《群体的智慧》一书中,詹姆斯·苏罗维基探讨并综合了形成明智群体所需的特征——这种群体通常能比单一个体做出更好的决策。他指出,意见的多样性、判断的独立性和知识的分散性是实现这一目标的重要属性。2006 年,杰夫·豪在为《连线》杂志撰写的关于《众包的兴起》的文章中创造了众包这个词,它是“crowds”和“outsourcing”的合成词。他讨论了企业如何通过公开征集的方式,开始利用分布式在线社区的集体能力来完成某些任务。
亚马逊机械土耳其人在首次推出后蓬勃发展,几年内,全球数十万人通过在平台上完成任务找到了谋生的机会。这激发了全球范围内众包平台的增长,铸造并巩固了在线微任务众包工作的全新经济。研究人员和从业者开始依赖众包平台来完成各种任务,并证明了即使是高度复杂的任务也可以分解并众包。提出了系统和工具,以支持众包工作者有效完成任务。一些当代众包平台的显著例子包括 Toloka AI(“一个支持快速和可扩展 AI 发展的数据中心环境”)。
借助人类洞察力”) 和 Prolific(一个“进行研究或训练下一代人工智能”的平台)。
2009 年,ImageNet 的发布推动了整个机器学习领域。该数据集包含超过 320 万张图像,分为 12 个子树,并具有超过五千个同义词集,这是通过亚马逊机械土耳其工人众包进行的巨大数据收集努力[1]。这为多个计算机视觉任务提供了前所未有的进步机会,包括对象识别和图像分类。
我们不要忘记,这一进展伴随着一系列的试炼和磨难。许多人感受到了依赖易受认知和系统性偏见影响的人类生成数据所带来的危险的震颤。在 2013 年,一群在众包社区中著名的研究者写了一篇名为《众包工作的未来》的论文,反思了这一范式的现状以及需要立即解决的一系列挑战[2]。尽管取得了显著进展,但许多这些挑战在 10 年后的今天仍未得到解决。关于数据质量(例如,偏见传播)、平台上的权力不对称、低劣的小时工资、不公平的工作拒绝、隐形劳动、不健康的工作环境等问题已有充分记录。尽管有些人认为这是一个破碎的工作范式的脆弱之处,历史上却点缀着显著的成果,众包的力量无疑推动了技术进步的速度,只有少数人会预见到。
生成性人工智能的迷人时代
目前全球主流媒体陷入了关于生成性人工智能和大型语言模型民主化的广泛叙事中。许多生活将继续以预期和意想不到的方式受到人工智能的影响。而正是幕后辛勤工作的人工推动了这场人工智能革命。如果我们“审视人工智能的阴影,我们将发现推动它的人类”,正如玛丽·格雷和西德·苏里在《幽灵工作》中难以忘怀地指出的那样[3]。
夸大的预测和引人注目的标题将这一时代中人类的角色比作焦虑的鸽子,并将大型语言模型比作大胆的猫——隐喻中的猫打乱了队伍,使它们四散离去。但这个生成性人工智能新时代的开始对人类输入究竟意味着什么?在塑造未来技术方面,人类输入的需求是否已经在很大程度上被消除了?在本文的其余部分,我将论证答案是否定的,我们应预期的主要变化是在继续需要的人类输入的性质上。
我最近共同撰写了一篇研讨会论文,探讨了人类计算工作流程如何适应生成式 AI 模型的出现[4]。这项工作在今年早些时候于汉堡举办的顶级 HCI 会议 ACM CHI 2023 上的生成式 AI 研讨会上进行了展示。我们强调了大型语言模型(LLMs)在增强现有众包工作流程中可能发挥的作用,并讨论了如何对这些工作流程进行实证评估。
众包工作流程入门
众包工作流程是管理大规模任务如何被分解成较小任务以供众包工人完成的不同模式。众包驱动的文字处理器 Soylent 运用了Find-Fix-Verify工作流程,通过将任务分成生成和审查文本的阶段来生产高质量的文本。这使得“作家可以调用 Mechanical Turk 工人根据需要缩短、校对和编辑他们文档的部分[5]。” Iterate-and-Vote工作流程已被用于创建图像描述,在这个过程中,工人首先被要求写出图像的描述(例如,最终目的是帮助盲人)。随后,通过投票任务来确定最佳描述[6]。Map-Reduce工作流程则被提议用于“将工作分成可以并行完成的任务,映射任务到工人,并管理它们之间的依赖关系[7]。” 具有相同本质的工具,如CrowdWeaver,被提议用于管理复杂的工作流程,支持任务之间的数据共享,并提供监控工具和实时任务调整能力[8]。
利用 LLMs 提升众包工作流程
语言模型的出现不太可能使这些工作流程、框架和工具变得完全平凡。相反,众包社区独特地能够通过利用几十年的有效工作流程、人机交互方法和构建混合人类-人工智能系统的知识,来迎接 LLMs 带来的好处。
以人为本的技术开发视角专注于增强人们日常生活中的体验和提高人的能力。如果大语言模型(LLMs)确实可以帮助众包工人完成任务,它们应该以一种能够让工人更准确、更迅速地完成任务的方式被接纳和整合,或以某种方式改善他们的整体体验。
信息检索领域的研究者(这是我在过去十年中参与的一个社区)最近考虑了 LLMs 的普及对人类注释员在相关性判断中的角色意味着什么[9]。他们提出了一个人类与 LLMs 之间合作的谱系,以生成相关性判断(从人类判断到完全自动评估,类似于流行的自动化水平)。作者探讨了在辅助注释任务中引入 LLMs 的潜在好处,并将其与这样做的风险进行了权衡。显然,LLMs 可以降低创建评估集合的注释成本。然而,尚不清楚这些集合是否会系统性地与由人类创建的集合不同,以及这些文献会如何影响信息检索系统的评估,从而影响未来这些系统的设计。
除了在工作流程中支持个体写作或分类任务外,研究者们还在探索 LLMs 在辅助众包工作者中的应用。刘等人将 GPT-3 的生成能力与人类的评估能力结合,创建了一个新的自然语言推理数据集,该数据集在用作训练集时能产生更有效的模型[10]。类似地,其他人引入了一个‘生成注释助手’,以帮助生成动态对抗数据集合,显著提高了收集速率[11]。然而,关于 LLMs 如何提高众包工作流程的有效性以及如何全面评估这些工作流程,还有一些尚未完全理解的开放性问题。
前方有许多障碍吗?
与人类类似,LLMs 也可能受到偏见和不公平的影响。一方面,先前的研究表明,人类注释员在完成注释任务时容易受自身意见的影响,从而导致系统性偏见渗入结果数据集合[12]。其他研究者提出了用于对抗或报告注释过程中可能出现的认知偏见的检查清单[13]。另一方面,最近的研究揭示了 LLMs 中存在的歧视性立场和刻板印象偏见[14, 15]。
人类计算与众包研究社区(HCOMP)设计了多种有效的方法、接口、衡量标准和工具,以确保从众包工作者那里收集到高质量的数据。我们集体弄清楚如何在决策管道中集成 LLMs 的同时,提供这些质量相关的保证只是时间问题。
表面上,将大型语言模型(LLMs)整合进众包工作流程似乎相当简单。正如许多复杂系统解决方案的提议一样,说起来容易做起来难。众包涉及许多不同的利益相关者:希望收集大规模注释的任务请求者,愿意提供帮助以获得报酬的众包工人,提供基础设施并充当这些交易市场的平台,以及在下游开发或建设中间接使用产品或技术的最终用户。将 LLMs 纳入工作流程的影响可能以不同方式影响每个利益相关者。
如果众包工人能够通过在智能工作流程中利用 LLMs 变得更加高效,那么有可能在不增加成本的情况下完成更多工作。然而,还需要进一步的工作来更好地理解将 LLMs 纳入众包工作流程所带来的风险和奖励。考虑到可能需要的责任追究,谁将负责设计、开发和将 LLMs 整合到这些工作流程中呢?
历史上,众包工人通常被留给自己来提高生产力以及改善他们工作的环境和条件。难道现在不应该由众包平台和任务请求者共同负责,更好地理解如何配备基于 LLMs 的解决方案,以帮助工人成功完成任务,并提升和增强他们的工作体验吗?
人工人工人工智能与可期的未来
一项近期案例研究探讨了“人类”在文本总结任务中生成的众包数据在多大程度上确实是由人类生成的。作者发现证据表明,在他们对 Amazon Mechanical Turk 的研究中,超过 30%的众包工人已经开始依赖 LLMs [16]。尽管该研究仅报告了 44 名工人的这些见解,数字需谨慎对待,但这确实反映了越来越多的众包工人可能转向 LLM-based 解决方案的不可否认的前景,这些解决方案可以帮助他们提高生产力、最大化收入,并改善他们在众包市场中的时间。这就是“人工人工人工智能”概念的来源——众包工人可能利用 AI(LLMs 的帮助)提供所谓的“人类”输入。
图:一张插图描绘了“人工人工人工智能”这一术语的出现,该术语源于[29]的 AI(1)到 AAI(2),最终到 AAAI(3)。来源:作者提供的图像。
需要进一步考虑 LLMs 的透明度和可解释性,与从人类那里获得的相比。当众包工人完成注释或其他需要决策的任务时,任务请求者可以通过后续问题提取有意义的理由。众包工人具备在需要时提供这些见解的能力。目前 LLMs 尚无法实现这一点。是的,存在模型可解释性的方法,但没有一种显示出与人类在沟通两端所能实现的效果相当的有效性。这种对 LLMs 的“黑箱”感知可能会对任务请求者和众包平台的采纳形成障碍,同时也阻碍了众包工人对这些工具的适当依赖。
人类与 LLMs?无限的可能性和一片引人入胜的问题海洋,只有少数闪烁的答案。利用这一技术进步来改善众包工作,更像是捕捉到风帆上的一阵风,而不是搅动一个黄蜂窝。让我们忙起来,因为当我们能够让人类居于中心舞台时,一个美好的未来在等待着我们。
参考文献
-
Deng, J., Dong, W., Socher, R., Li, L. J., Li, K., & Fei-Fei, L. (2009 年 6 月)。Imagenet:大规模层次图像数据库。发表于 2009 年 IEEE 计算机视觉与模式识别会议论文集(第 248–255 页)。IEEE。
-
Kittur, A., Nickerson, J.V., Bernstein, M., Gerber, E., Shaw, A., Zimmerman, J., Lease, M. 和 Horton, J., 2013 年 2 月。众包工作的未来。发表于 2013 年计算机支持协作工作会议论文集(第 1301–1318 页)。
-
Gray, M. L., & Suri, S. (2019)。幽灵工作:如何阻止硅谷建立一个新的全球底层阶级。Eamon Dolan Books。
-
Allen, G., He, G., Gadiraju, U. 提升!生成模型能为人类计算工作流程做些什么?发表于 ACM 国际计算系统人因会议(CHI 2023)的生成 AI 研讨会论文集。
-
Bernstein, Michael S., Greg Little, Robert C. Miller, Björn Hartmann, Mark S. Ackerman, David R. Karger, David Crowell, 和 Katrina Panovich. “Soylent:一个内部含有众包的文字处理器。” 发表于第 23 届年度 ACM 用户界面软件与技术研讨会论文集,第 313–322 页。2010 年。
-
Little, G., Chilton, L. B., Goldman, M., & Miller, R. C. (2009 年 6 月)。Turkit:机械土耳其上迭代任务的工具。发表于 ACM SIGKDD 人类计算研讨会论文集(第 29–30 页)。
-
Kittur, A., Smus, B., Khamkar, S., & Kraut, R. E. (2011 年 10 月)。Crowdforge:众包复杂工作。发表于第 24 届年度 ACM 用户界面软件与技术研讨会论文集(第 43–52 页)。
-
Kittur, A., Khamkar, S., André, P. 和 Kraut, R., 2012 年 2 月。CrowdWeaver:可视化管理复杂的众包工作。发表于 ACM 2012 年计算机支持协作工作会议论文集(第 1033–1036 页)。
-
Faggioli, G., Dietz, L., Clarke, C., Demartini, G., Hagen, M., Hauff, C., Kando, N., Kanoulas, E., Potthast, M., Stein, B. 和 Wachsmuth, H., 2023. 《对大型语言模型在相关性判断中的视角》。arXiv 预印本 arXiv:2304.09161。
-
Liu, Z., Roberts, R.A., Lal-Nag, M., Chen, X., Huang, R. 和 Tong, W., 2021. 《基于 AI 的语言模型在药物发现与开发中的应用》。Drug Discovery Today, 26(11), 第 2593–2607 页。
-
Bartolo, M., Thrush, T., Riedel, S., Stenetorp, P., Jia, R. 和 Kiela, D., 2021. 《模型在循环中:利用生成式注释助手辅助众包工作者》。arXiv 预印本 arXiv:2112.09062。
-
Hube, C., Fetahu, B. 和 Gadiraju, U., 2019 年 5 月。《理解和减轻众包收集主观判断中的工作者偏见》。见于 2019 年 CHI 计算机系统人因会议论文集(第 1–12 页)。
-
Draws, T., Rieger, A., Inel, O., Gadiraju, U., 和 Tintarev, N. (2021 年 10 月)。 《应对众包中的认知偏见检查表》。见于 AAAI 人类计算与众包会议论文集(第 9 卷,第 48–59 页)。
-
Abid, A., Farooqi, M. 和 Zou, J., 2021 年 7 月。《大型语言模型中的持久反穆斯林偏见》。见于 2021 年 AAAI/ACM 人工智能、伦理与社会会议论文集(第 298–306 页)。
-
Nadeem, M., Bethke, A. 和 Reddy, S., 2020. 《StereoSet:测量预训练语言模型中的刻板偏见》。arXiv 预印本 arXiv:2004.09456。
-
Veselovsky, V., Ribeiro, M. H., 和 West, R. (2023)。 《人工人工人工智能:众包工作者广泛使用大型语言模型进行文本生成任务》。arXiv 预印本 arXiv:2306.07899。
TiDE:那个‘令人尴尬’的简单 MLP,击败了 Transformers
原文:
towardsdatascience.com/tide-the-embarrassingly-simple-mlp-that-beats-transformers-7db77d588079
深入探讨 TiDE,使用 Darts 的实现,以及与 DeepAR 和 TFT(一个 Transformer 架构)的实际案例比较
·发布在 Towards Data Science ·9 分钟阅读·2023 年 12 月 8 日
–
随着各行业的不断发展,准确预测的重要性成为了一项不可妥协的资产,无论你是在电子商务、医疗保健、零售业,甚至是农业领域工作。能够预见未来并相应地制定计划,以克服未来的挑战,是使你在竞争中领先并在利润紧张、客户要求比以往任何时候都高的经济环境中蓬勃发展的关键。
Transformer 架构在过去几年里一直是 AI 的热门话题,特别是由于它们在自然语言处理(NLP)中的成功,chatGPT 就是最成功的用例之一,引起了所有人的关注,无论你是否是 AI 爱好者。然而,NLP 并不是唯一一个展示 Transformers 超越最先进解决方案的领域,在计算机视觉中,Stable Diffusion 及其变体也同样如此。
但 Transformers 能否超越最先进的时间序列模型?虽然已经付出了很多努力来开发用于时间序列预测的 Transformers,但似乎对于长期预测,简单的线性模型能够超越几种基于 Transformer 的方法。
在这篇文章中,我探讨了 TiDE,一个能够在长期预测中击败 Transformer 架构的简单深度学习模型。我还提供了使用 Python 的预测库 Darts 对 Walmart 数据集进行周销量预测的逐步实现。最后,我将 TiDE、DeepAR 和 TFT 在我公司实际案例中的表现进行了比较。
图 1:TiDE 是一种全新的预测模型,它是“简单到尴尬”的 MLP,旨在超越 Transformers (source)
一如既往,代码可以在 Github 上找到。
时间序列稠密编码器模型 (TiDE)
TiDE 是一种新颖的时间序列编码器-解码器模型,已显示出在长期预测中优于最先进的 Transformer 模型 [1]。它是一种多变量时间序列模型,能够使用静态协变量(例如产品品牌)和动态协变量(例如产品价格),这些协变量可以在预测范围内已知或未知。
与 Transformers 复杂的架构不同,TiDE 基于简单的编码器-解码器架构,仅使用多层感知机(MLP),没有任何注意力层。
编码器负责通过两个关键步骤将时间序列的过去和协变量映射到特征的稠密表示:
-
特征投影,它减少了整个回溯和预测范围内动态协变量的维度。并且;
-
稠密编码器,它接收特征投影的输出,与静态协变量和时间序列的过去连接,并将它们映射到嵌入中。
解码器接收来自编码器的嵌入,并通过两项操作将其转换为未来预测:
-
稠密解码器,它将嵌入映射到预测范围内每个时间步的向量;以及
-
时间解码器,它将稠密解码器的输出与该时间步的投影特征结合,以生成预测。
残差连接将回溯线性映射到与预测范围大小相同的向量,并将其添加到时间解码器的输出中,以生成最终预测。
图 2:TiDE 架构 (source)
如何在实践中使用 TiDE
本节介绍了使用 Walmart 的每周销售数据集(可在 kaggle(许可证 CC0:公共领域)上获取)逐步实现 TiDE 的过程,并借助名为 Darts 的包。
Darts 是一个用于预测和异常检测的 Python 库 [2],包含多个模型,如用于基线的简单模型、传统模型(如 ARIMA 或 Holt-Winters)、深度学习模型(如 TiDE 或 TFT)或基于树的模型(如 LightGBM 或随机森林)。它还支持单变量和多变量模型,其中一些模型提供概率预测解决方案。
训练数据集包含 2 年 8 个月的每周销售数据和 5 列:
-
Store — 存储编号和一个静态协变量
-
Dept — 部门编号和其他静态协变量
-
Date — 时间序列的时间索引,按周分布,将用于提取动态协变量,如周数和月份
-
Weekly_Sales — 目标变量
-
IsHoliday — 另一个动态协变量,用于识别某一周是否有假期
测试数据集具有相同的列,除了目标 (Weekly_Sales*)*。
我们首先导入所需的库,并定义一些全局变量,如日期列、目标列、静态协变量、序列的频率以及要使用的缩放器:
# Libraries
import pandas as pd
import numpy as np
from darts import TimeSeries
from darts.models import TiDEModel
from darts.dataprocessing.transformers import Scaler
from darts.utils.timeseries_generation import datetime_attribute_timeseries
from darts.utils.likelihood_models import QuantileRegression
from darts.dataprocessing.transformers import StaticCovariatesTransformer
# Global Variables
TIME_COL = "Date"
TARGET = "Weekly_Sales"
STATIC_COV = ["Store", "Dept"]
FREQ = "W-FRI"
SCALER = Scaler()
TRANSFORMER = StaticCovariatesTransformer()
默认的缩放器是 MinMax Scaler,但我们可以使用来自 scikit-learn 的任何缩放器,只要它具备 fit()
、transform()
和 inverse_transform()
方法。转换器也是如此,默认情况下是来自 scikit-learn 的 Label Encoder。
之后,我们加载训练数据集,并将 pandas 数据框转换为 TimeSeries,这是 Darts 所期望的格式。
我没有进行探索性数据分析,因为我的目标只是向你展示如何实现它,但我注意到了一些负值,这可能表示退货。然而,我将这些负值视为错误,并将其替换为 0。
我还使用了 fill_missing_dates
参数来添加缺失的周,并将这些日期也填充为 0。
# read train and test datasets and transform train dataset
train = pd.read_csv('data/train.csv')
train["Date"] = pd.to_datetime(train["Date"])
train[TARGET] = np.where(train[TARGET] < 0, 0, train[TARGET])
train_darts = TimeSeries.from_group_dataframe(
df=train,
group_cols=STATIC_COV,
time_col=TIME_COL,
value_cols=TARGET,
static_cols=STATIC_COV,
freq=FREQ,
fill_missing_dates=True,
fillna_value=0)
我们还加载了测试数据集,以便定义我们的预测范围以及预测范围中的假期。
# read test dataset and determine Forecast Horizon
test = pd.read_csv('data/test.csv')
test["Date"] = pd.to_datetime(test["Date"])
FORECAST_HORIZON = len(test['Date'].unique())
之后,对于训练集中的每个序列,我们创建动态协变量(周、月和一个识别特定周假期的二进制列):
# we get the holiday data that we have in both train and test dataset
holidays_df = pd.concat([train[["Date", "IsHoliday"]], test[["Date", "IsHoliday"]]]).drop_duplicates()
# convert bool to numeric
holidays_df["IsHoliday"] = holidays_df["IsHoliday"]*1
# create dynamic covariates for each series in the training darts
dynamic_covariates = []
for serie in train_darts:
# add the month and week as a covariate
covariate = datetime_attribute_timeseries(
serie,
attribute="month",
one_hot=True,
cyclic=False,
add_length=FORECAST_HORIZON,
)
covariate = covariate.stack(
datetime_attribute_timeseries(
serie,
attribute="week",
one_hot=True,
cyclic=False,
add_length=FORECAST_HORIZON,
)
)
# create holidays with dates for training and test
holidays_serie = pd.merge(pd.DataFrame(covariate.time_index).rename(columns={'time':'Date'}), holidays_df, on='Date', how='left')
covariate = covariate.stack(
TimeSeries.from_dataframe(holidays_serie, time_col="Date", value_cols="IsHoliday", freq=FREQ)
)
dynamic_covariates.append(covariate)
现在,我们已经准备好所有数据,只需对数据进行缩放:
# scale covariates
dynamic_covariates_transformed = SCALER.fit_transform(dynamic_covariates)
# scale data
data_transformed = SCALER.fit_transform(train_darts)
# transform static covariates
data_transformed = TRANSFORMER.fit_transform(data_transformed)
最后,我们准备好进行预测了!
在我们的案例中,我们将预测接下来的 38 周的同一系列的每周销售额,不过你也可以预测不在训练集中的时间序列,只要它们具有相同的静态协变量。为此,你必须重复相同的数据准备过程。
TiDE_params = {
"input_chunk_length": 4, # number of weeks to lookback
"output_chunk_length": FORECAST_HORIZON,
"num_encoder_layers": 1,
"num_decoder_layers": 1,
"decoder_output_dim": 1,
"hidden_size": 15,
"temporal_width_past": 4,
"temporal_width_future": 4,
"temporal_decoder_hidden": 26,
"dropout": 0.1,
"batch_size": 16,
"n_epochs": 5,
"likelihood": QuantileRegression(quantiles=[0.25, 0.5, 0.75]),
"random_state": 42,
"use_static_covariates": True,
"optimizer_kwargs": {"lr": 1e-3},
"use_reversible_instance_norm": False,
}
model = TiDEModel(**TiDE_params)
model.fit(data_transformed, future_covariates=dynamic_covariates_transformed, verbose=False)
pred = SCALER.inverse_transform(model.predict(n=FORECAST_HORIZON, series=data_transformed, future_covariates=dynamic_covariates_transformed, num_samples=50))
这里有一个商店 1 和部门 1 的预测示例,我们可以看到模型能够预测 2012 年黑色星期五和感恩节那周的激增,这是由于我们拥有的三个动态协变量(周、月以及识别某一周是否有假期的二进制列)。我们还可以看到,一年中有几个激增,可能来自折扣或营销活动,这可以通过动态协变量来处理,以改进我们的预测,这些数据也可以在 kaggle 上找到。
图 3:商店 1 和部门 1 的预测结果(图片由作者制作)
TiDE 与 DeepAR 的比较以及 TiDE 与 TFT 在实际应用中的比较
在我的公司,我们在 2022 年底部署了一个新的预测模型,旨在预测接下来 16 周内 264 个时间序列的订单量。
当时击败生产中模型的模型是 DeepAR,一种可在 Python 库 GluonTS [3] 中找到的深度学习架构。像 TiDE 一样,DeepAR 允许使用静态和动态协变量。
尽管 DeepAR 为我们提供了良好的结果,但它在较长时间范围(+8 周)内出现了我们称之为*‘预测爆炸’*的问题。从一周到另一周,仅增加一周的数据,模型就会给出与前一周完全不同的预测,预测的量高于正常水平。
尽管如此,我们制定了控制机制,并更改了一个特定的超参数(上下文长度,DeepAR 对此非常敏感),以避免此类情况,但最近发现这还不够,我们不得不每周密切监控结果,并调整其他超参数以获得合理的预测。
因此,我们决定开始新一轮研究,寻找一个更稳定可靠的模型,这时我们发现了 TiDE。我们对 TiDE 进行了超参数优化,包括使用哪些动态和静态协变量,哪些系列用于训练,哪些不用于训练等。然后我们在 2022 年 7 月到 2023 年 7 月的整整一年数据中,比较了优化后的 DeepAR 和 TiDE 模型在 26 个不同的截止日期上的表现。
结果显示,TiDE 不仅在短期和长期内优于 DeepAR(如图 4 所示),而且也解决了我们希望解决的*‘预测爆炸’*初始问题。
图 4:DeepAR 与 TiDE 在实际用例中的比较。用于比较的指标是 MSE,但由于保密原因在 y 轴上未显示(图像由作者制作)。
在我们的模型研究中,我们还将 TiDE 与 TFT [4](一种 Transformer 架构)进行了比较,以验证[1]中作者关于 TiDE 在长期预测中超越 Transformer 架构的说法。正如图 5 所示,TiDE 能够击败 TFT,特别是在长期预测(6 周以上)中。
图 5:TFT 与 TiDE 在实际用例中的比较(图像由作者制作)。
结论
Transformer 架构将是人类历史上下一次重大革命的基础。尽管它们在 NLP 和计算机视觉领域表现出色,但正如[1]中的作者所述,它们在长期预测方面无法超越更简单的模型。
在这篇文章中,我们将 TFT(一种 Transformer 架构)和 DeepAR 与 TiDE 进行了比较,验证了对于我们的用例,TiDE 能够超越这两个模型。
尽管 Transformer 架构足够强大以进行长期预测,但为什么谷歌还会开发一种新的非 Transformer 时间序列模型?TSMixer [5] 是谷歌开发的最新时间序列模型,它在 M5 竞赛中击败了包括 TFT 在内的 Transformers。
目前,更简单的模型似乎在预测方面更具优势,但让我们拭目以待未来的发展,看看 Transformers 是否能得到改进,以提供更好的长期结果!
参考文献
[1] Abhimanyu Das, Weihao Kong, Andrew Leach, Shaan Mathur, Rajat Sen, Rose Yu. 使用 TiDE 进行长期预测:时间序列密集编码器。arXiv:2304.08424, 2023
[2] Julien Herzen, Francesco Lässig, Samuele Giuliano Piazzetta, Thomas Neuer, Léo Tafti, Guillaume Raille, Tomas Van Pottelbergh, Marek Pasieka, Andrzej Skrodzki, Nicolas Huguenin, Maxime Dumonal, Jan Kościsz, Dennis Bader, Frédérick Gusset, Mounir Benheddi, Camila Williamson, Michal Kosinski, Matej Petrik, Gaël Grosch. Darts: 用户友好的现代机器学习时间序列,2022
[3] Alexander Alexandrov, Konstantinos Benidis, Michael Bohlke-Schneider, Valentin Flunkert, Jan Gasthaus, Tim Januschowski, Danielle C. Maddix, Syama Rangapuram, David Salinas, Jasper Schulz, Lorenzo Stella, Ali Caner Türkmen, Yuyang Wang. GluonTS: Python 中的概率时间序列模型。arXiv:1906.05264, 2019
[4] Bryan Lim, Sercan O. Arik, Nicolas Loeff, Tomas Pfister. 时间融合变压器用于可解释的多时间跨度时间序列预测。arXiv:1912.09363, 2019
[5] Si-An Chen, Chun-Liang Li, Nate Yoder, Sercan O. Arik, Tomas Pfister. TSMixer: 用于时间序列预测的全 MLP 架构。arXiv:2303.06053, 2023
整理数据集变化框架
回顾模型降级的原因
·
关注 发表在 Towards Data Science · 11 分钟阅读 · 2023 年 7 月 18 日
–
与 Marco Dalla Vecchia 合作,担任图像创作者
我们训练模型,并使用它们根据一组输入预测特定的结果。我们都知道这就是机器学习的游戏。我们对训练它们知道很多,以至于它们现在已经进化成了人工智能,这是有史以来最先进的智能水平。但在使用它们时,我们还没有那么远,我们继续探索和理解模型部署后每一个重要的方面。
所以今天,我们将讨论模型性能漂移(或简称模型漂移)的问题,也常被称为模型失败或模型退化。我们指的是我们的机器学习模型所提供的预测质量问题。不论是分类还是数值,我们关注的是该预测与真实类别或值之间的差距。当预测质量相对于我们部署模型时下降时,我们称之为模型性能漂移。你可能在文献中找到过其他术语,但在我们当前的讨论中,请关注 模型性能漂移 或简洁地说 模型漂移。
我们所知道的
几个博客、书籍和许多论文已经探索并解释了模型漂移的核心概念,因此我们将首先进入当前的图景。我们主要将这些概念组织为 协变量偏移、先验偏移 和 条件偏移。后者也常被称为 概念漂移。这些偏移被认为是模型漂移的主要原因(记住,这是预测质量的下降)。总结定义如下:
-
协变量偏移:P(X) 的分布发生变化,但 P(Y|X) 不一定发生变化。这意味着输入特征的分布发生了变化,这些偏移可能导致模型漂移。
-
先验偏移:P(Y) 分布的变化。在这里,标签或数值输出变量的分布发生了变化。如果输出变量的概率分布发生偏移,当前模型对给定预测的确定性会大大降低,因此模型可能会出现漂移。
-
条件偏移(即 概念漂移):条件分布 P(Y|X) 发生变化。这意味着,对于给定的输入,输出变量的概率发生了变化。根据我们目前的了解,这种偏移通常使我们很难保持预测质量。真的如此吗?
有许多来源列举了这些数据集偏移的发生实例。研究的一个核心机会是检测这些类型的偏移,而无需新的标签[1, 2, 3]。最近发布了有趣的指标,以无监督的方式监控模型的预测性能[2, 3]。这些指标确实受到数据集偏移不同概念的驱动,并且相当准确地反映了数据真实概率分布的变化。因此,我们将深入探讨这些偏移的理论。为什么?因为也许我们可以对这些定义进行一定的整理。通过整理,我们可能能够更轻松地前进,或者更清楚地理解整个框架。
为此,让我们回到一开始,慢慢推导这个故事。拿一杯咖啡,慢慢阅读,跟随我。或者,千万不要漂移!
真实模型与估计模型
我们训练的机器学习模型尝试让我们接近一个真实但未知的关系或函数,这个函数将特定输入 X 映射到输出 Y。我们自然区分真实的未知关系和估计的关系。然而,估计模型受限于真实未知模型的行为。也就是说,如果真实模型发生变化,而估计模型对这些变化不够稳健,那么估计模型的预测将会不够准确。
我们可以监控的性能涉及到估计函数,但模型漂移的原因在于真实模型的变化。
-
真正的模型是什么? 真正的模型建立在所谓的条件分布 P(Y|X)上。这是给定输入的输出的概率分布。
-
估计模型是什么? 这是一个函数ê(x),它专门估计 P(Y|X=x)的期望值。这个函数是与我们的机器学习模型相关的。
这是这些元素的视觉表示:
(图片由作者提供)
好的,现在我们澄清了这两个元素,我们准备好组织所谓的数据集偏移的想法,以及这些概念之间的联系。
新的安排
模型漂移的全球原因
我们的主要目标是理解我们估计模型的模型漂移的原因。因为我们已经理解了估计模型和条件概率分布之间的联系,我们可以在这里陈述我们之前已经知道的:我们估计模型漂移的全球原因是 P(Y|X)的变化。
基本而显然容易,但比我们想象的更为根本。我们假设我们的估计模型是对真实模型的良好反映。真实模型由 P(Y|X)支配。因此,如果 P(Y|X)发生变化,我们的估计模型很可能会漂移。我们需要注意我们在上述图中展示的推理路径。
我们之前已经知道这一点,那有什么新鲜的?新鲜的是我们现在将 P(Y|X)的变化称为全球原因,而不仅仅是一种原因。这将对其他原因施加一种层次结构。这种层次结构将帮助我们很好地定位关于其他原因的概念。
特定原因:全球原因的元素
知道全球原因在于 P(Y|X)的变化,自然而然地需要深入挖掘构成这一概率的元素。一旦我们识别了这些元素,我们将继续讨论模型漂移的原因。那么这些元素是什么呢?
我们一直都知道这一点。条件概率在理论上定义为 P(Y|X) = P(Y, X) / P(X),即联合概率除以 X 的边际概率。但我们可以再次展开联合概率,我们获得了几个世纪以来我们所熟知的神奇公式:
(图片由作者提供)
你已经看到我们要去哪里了吗?条件概率完全由三个元素定义:
-
P(X|Y):逆条件概率
-
P(Y):先验概率
-
P(X):协变量的边际概率
因为这三个元素定义了条件概率 P(Y|X),所以我们可以给出第二个陈述:如果 P(Y|X) 发生变化,这些变化来自于定义它的至少一个元素。换句话说,P(Y|X) 的变化由 P(X|Y)、P(Y) 或 P(X) 的任何变化定义。
也就是说,我们已经将当前知识中的其他元素定位为模型漂移的具体原因,而不仅仅是 P(Y|X) 的平行原因。
回到这篇文章的开头,我们列出了协变量漂移和先验漂移。我们注意到,还有另一个具体原因:逆条件分布 P(X|Y) 的变化。我们通常在谈论 P(Y) 的变化时会提到这个分布,好像我们一般在考虑从 Y 到 X 的逆关系 [1,4]。
新的概念层次结构
(图片来源于作者)
现在我们可以清楚地比较当前关于这些概念的思考和提出的层次结构。到目前为止,我们一直在通过识别不同的概率分布来讨论模型漂移的原因。已知这三种主要分布,P(X)、P(Y) 和 P(Y|X) 是我们 ML 模型预测质量漂移的主要原因。
我在这里提出的转折为这些概念施加了一个层次结构。在这个结构中,估计 X -> Y 关系的模型的漂移的全局原因是条件概率 P(Y|X) 的变化。这些 P(Y|X) 的变化可以来自于 P(X)、P(Y) 或 P(X|Y) 的变化。
列举一下这个层次结构的一些影响:
-
我们可能会遇到 P(X) 发生变化的情况,但如果 P(Y) 和 P(X|Y) 也相应地发生变化,那么 P(Y|X) 保持不变。
-
我们也可能遇到 P(X) 变化的情况,但如果 P(Y) 或 P(X|Y) 没有相应地变化,P(Y|X) 将会变化。如果你之前对此主题进行过一些思考,你可能已经看到在某些情况下,我们看到 X 的变化,并且这些变化似乎并不完全独立于 Y|X,所以最终 Y|X 也会发生变化。在这里,P(X) 是 P(Y|X) 变化的具体原因,而 P(Y|X) 反过来是我们模型漂移的全局原因。
-
前两个陈述对于 P(Y) 也是正确的。
因为这三个具体原因可能会或可能不会独立变化,总体而言,P(Y|X) 的变化可以通过这些具体元素的变化来解释。可能是 P(X) 在这里稍微变化了一下,P(Y) 在那里稍微变化了一下,这两个变化也会导致 P(X|Y) 变化,最终导致 P(Y|X) 变化。
P(X) 和 P(Y|X) 不能被独立看待,P(X) 是 P(Y|X) 的一个原因
在这一切中,估计的 ML 模型在哪里?
好,现在我们知道所谓的协变量和先验转移是条件转移的原因,而不是与之并行。条件转移包括导致估计模型预测性能下降的具体原因。但估计模型实际上是决策边界或函数,而不是对实际概率的直接估计。那么这些原因对真实和估计的决策边界意味着什么呢?
让我们收集所有的部分,绘制连接所有元素的完整路径:
(图片由作者提供)
注意,我们的机器学习模型可以是解析的或数值的。此外,它可以是参数化或非参数化的表示。因此,最终,我们的机器学习模型是决策边界或回归函数的估计,这些是从预期的条件值中推导出来的。
这一事实对我们讨论的原因有重要的影响。虽然 P(X)、P(Y)和 P(X|Y)中发生的大多数变化将意味着 P(Y|X)和 E(Y|X)的变化,但并非所有这些变化都必然意味着真实决策边界或函数的变化。在这种情况下,如果估计的决策边界或函数最初是准确的,那么它将保持有效。看看下面这个例子:
(图片由作者提供)
-
看到 P(Y)和 P(X)发生了变化。点的密度和位置导致了不同的概率分布。
-
这些变化使得 P(Y|X)发生变化。
-
然而,决策边界保持有效。
这里有一个重要的点。假设我们只关注 P(X)的变化,而没有真实标签的信息。我们想知道预测的准确性。如果 P(X)转向估计决策边界有很大不确定性的区域,预测可能是不准确的。因此,在协变量转移到决策边界的不确定区域的情况下,很可能也发生了条件转移。但我们无法知道决策边界是否发生了变化。在这种情况下,我们可以量化 P(X)的变化,这可能表明 P(Y|X)的变化,但我们无法知道决策边界或回归函数发生了什么。这是这个问题的表示:
既然我们说了这些,现在是时候再做一个声明了。当我们提到 P(Y|X)的变化时,我们讨论的是条件转移。我们所说的概念漂移可能特别指的是真实决策边界或回归函数的变化。下面是一个典型的条件转移示例,显示了决策边界的变化,但没有协变量或先验转移。实际上,这种变化来自于逆条件概率 P(X|Y)的变化。
(图片由作者提供)
对我们当前监控方法的影响
我们关心理解这些原因,以便开发方法来尽可能准确地监测我们的机器学习模型的性能。所提出的任何想法都不是对现有实际解决方案的坏消息。恰恰相反,借助这一新的概念层次,我们可能能够进一步推动检测模型性能下降原因的尝试。我们已有的方法和指标主要是在我们列出的不同概念的基础上提出的。然而,我们可能在度量指标的假设中混淆了概念。例如,我们可能将“无条件漂移”作为一种假设,而实际上它可能是“决策边界无变化”或“回归函数无变化”。我们需要继续思考这一点。
更多关于预测性能下降的信息
放大和缩小。我们已经深入探讨了框架,以思考预测性能下降的原因。但我们还有另一个维度来讨论这个话题,那就是预测性能漂移的类型。我们的模型因列出的原因而遭受痛苦,这些原因以不同的预测错位形式体现出来。我们主要发现了四种类型:偏差、斜率、方差和非线性漂移。查看这篇文章以了解这一硬币的另一面。
总结
我们在这篇文章中研究了模型性能下降的原因,并提出了基于我们之前已知概念的理论联系的框架。以下是要点:
-
概率 P(Y|X)支配真实的决策边界或函数。
-
估计的决策边界或函数被假定为对真实边界或函数的最佳近似。
-
估计的决策边界或函数即是机器学习模型。
-
机器学习模型可能会经历预测性能下降。
-
这种退化是由 P(Y|X)的变化引起的。
-
P(Y|X)的变化是因为这些元素中的至少一个发生了变化:P(X)、P(Y)或 P(X|Y)。
-
P(X)和 P(Y)可以发生变化,而决策边界或回归函数不变。
一般的说法是:如果机器学习模型在漂移,那么 P(Y|X)也在变化。反之则不一定成立。
这一概念框架希望能成为机器学习预测性能下降这一关键主题的种子。尽管理论讨论本身非常令人愉快,但我相信这个联系将帮助我们进一步推进在实践中测量这些变化的目标,同时优化所需资源(样本和标签)。如果你有其他贡献,请加入讨论。
是什么导致你的模型在预测性能上出现漂移?
祝你思考愉快!
参考文献
[1] huyenchip.com/2022/02/07/data-distribution-shifts-and-monitoring.html
[2] www.sciencedirect.com/science/article/pii/S016974392300134X
[4] medium.com/towards-data-science/understanding-dataset-shift-f2a5a262a766
数据集转移框架的整理:示例
条件概率如何随三个概率元素的函数变化
·
关注 发表在 Towards Data Science ·7 min 阅读·2023 年 9 月 1 日
–
作者提供的图片
最近我讨论了模型性能下降的原因,即它们在我们训练和部署模型时预测质量下降的情况。在另一篇文章中,我提出了一种新的思考模型退化原因的方式。在这个框架中,所谓的条件概率成为全局原因。
条件概率本质上由三个我称之为具体原因的概率组成。这种概念重构最重要的学习是协变量偏移和条件偏移不是两个独立或平行的概念。条件偏移可以作为协变量偏移的一个函数发生。
通过这种重构,我相信我们更容易思考原因,并且解释我们在应用中观察到的变化变得更加合乎逻辑。
这是机器学习模型的原因与模型性能的框架:
作者提供的图片。改编自 towardsdatascience.com/tidying-up-the-framework-of-dataset-shifts-cd9f922637b7
在这个框架中,我们可以清晰地看到将原因与我们估计模型的预测性能连接起来的路径。我们在统计学习中需要做的一个基本假设是,我们的模型是对真实模型(真实决策边界、真实回归函数等)的“良好”估计。“良好”可以有不同的含义,例如无偏估计、精确估计、完整估计、充分估计等。但为了简化和接下来的讨论,我们可以说它们在预测误差较小的意义上是好的。换句话说,我们假设它们能够代表真实模型。
在这个假设下,我们可以在概率P(X)、P(Y)、P(X|Y)中寻找估计模型退化的原因,并因此P(Y|X)。
所以,我们今天要做的就是举例并演示不同的场景,看看P(Y|X)如何作为 3 个概率P(X|Y)、***P(X)和P(Y)的函数变化。我们将使用二维空间中的少量点,并按拉普拉斯的方法计算这些样本点的概率。目的是消化模型退化的原因层次结构,将P(Y|X)***作为全局原因,而其他三个作为具体原因。通过这种方式,我们可以理解,例如,潜在的协变量偏移有时可能是条件偏移的论据,而不是一个独立的偏移。
示例
我们今天课程中要绘制的案例是一个非常简单的。我们有两个协变量X1和X2,输出Y是一个二元变量。这就是我们的模型空间的样子:
作者提供的图片
你可以看到,空间被划分为 4 个象限,而这个空间中的决策边界是交叉的。这意味着模型将样本分类为类别 1 如果它们位于第 1 象限和第 3 象限,否则分类为类别 0。为了这个练习的目的,我们将通过比较P(Y=1|X1>a)来逐步解析不同情况。这将是我们展示的条件概率。如果你在想为什么不考虑X2,这是为了简化练习。这不会影响我们想要理解的见解。
如果你仍然有些复杂的感觉,计算P(Y=1|X1>a) 相当于 P(Y=1|X1>a, -inf <X2 < inf),所以理论上,我们仍然考虑了X2。
图片由作者提供
参考模型
所以,首先,我们计算我们的展示概率,得到的是1/2。在这里,我们的样本组在整个空间中相当均匀,先验概率也很均匀:
图片由作者提供
变化正在出现
- 一个额外的样本出现在右下角象限。所以我们首先要问的是:我们是否在讨论协变量变化?
是的,因为在X1>a的区域内的抽样比以前更多。所以,这只是一个协变量变化而不是条件变化吗?让我们看看。这里是用更新后的点集计算的所有相同概率(变化的概率用橙色标记):
图片由作者提供
我们在这里看到了什么?实际上,我们不仅仅获得了协变量变化,而且所有的概率都发生了变化。先验概率也发生了变化,因为协变量变化带来了一个新的类别 1 的点,使得这一类别的发生率大于类别 2。因此,逆概率 P(X1>a|Y=1) 正是因为先验变化而发生了变化。所有这些最终导致了一个条件变化,所以我们现在得到了P(Y=1|X1>a)=2/3,而不是1/2。
这是一个思考泡泡。实际上是一个非常重要的思考泡泡。
随着抽样分布的变化,我们获得了所有在我们模型整体方案中起作用的概率的变化。然而,基于初始抽样存在的决策边界对这一变化仍然有效。
这是什么意思?
尽管我们获得了条件变化,但决策边界并没有必然退化。因为决策边界来自期望值,如果我们基于当前的变化计算这个值,边界可能保持不变,但条件概率不同。
2. 第一个象限中的样本不再存在。
因此,对于X1>a,情况保持不变。让我们看看展示的条件概率及其元素发生了什么变化。
图片由作者提供
直观上,因为在X1>a的情况下,条件概率保持不变。然而,当我们查看P(X1>a)时,我们得到2/3而不是与训练采样相比的1/2。所以在这里我们有一个协变量漂移,没有 条件漂移。
从数学角度来看,协变量概率如何在条件概率不变的情况下发生变化?这是因为***P(Y=1)和P(X1>a|Y=1)***按照协变量概率的变化而变化。因此,补偿使条件概率保持不变。
有了这些变化,就像之前一样,决策边界保持有效。
3. 在不同象限中投放一些样本,同时决策边界保持有效。
这里有两个额外的组合。在一种情况下,先验保持不变,而其他两个概率发生了变化,但条件概率仍未变化。在第二种情况下,仅 逆概率与条件漂移相关。请查看下面的漂移。后者是一个相当重要的点,所以不要错过!
图片来源于作者
有了这些,我们现在对条件概率如何作为其他三种概率的函数发生变化有了相当扎实的理解。但最重要的是,我们也知道,并非所有的条件漂移都会使现有的决策边界失效。那么问题是什么呢?
概念漂移
在上一篇文章中,我还提出了一种更具体的定义概念漂移(或概念变化)的方法。提议是:
当决策边界或回归函数在相关概率发生变化时变得无效,我们称之为概念漂移。
所以,关键在于,如果决策边界变得无效,肯定存在条件漂移。相反的情况,如我们在上一篇文章中讨论过,并且如上述示例所示,并不一定成立。
从实际角度来看,这可能并不是那么令人惊叹,因为这意味着为了真正了解是否存在概念漂移,我们可能被迫重新估计边界或函数。但至少从理论理解的角度来看,这同样引人入胜。
这是一个示例,我们有一个概念漂移,自然地伴随着一个条件漂移,但实际上没有协变量或先验漂移。
图片来源于作者
这个组件分离有多酷?这里唯一改变的元素是逆概率,但与我们上面研究的先前偏移不同,这种逆概率的变化与决策边界的变化相关。现在,合法的决策边界仅仅是根据X1>a的分隔,抛弃了由X2所决定的边界。
我们学到了什么?
我们非常缓慢地走过了模型退化原因的分解过程。我们研究了概率元素的不同偏移及其与机器学习模型预测性能退化的关系。最重要的见解是:
-
条件偏移是机器学习模型预测退化的全球原因。
-
具体原因包括协变量偏移、先验偏移和逆概率偏移。
-
在决策边界保持有效的情况下,我们可能会遇到许多不同的概率偏移情况。
-
决策边界的变化会引起条件偏移,但反过来不一定成立!
-
概念漂移可能更具体地与决策边界相关,而不是与整体条件概率分布相关。
这会带来什么?在这个定义层次结构的指导下重新组织我们的实际解决方案是我提出的最大建议。我们可能会找到许多当前问题的理想答案,关于如何监控我们的模型。
如果你目前正在使用这些定义进行模型性能监控,不要犹豫,分享你对这个框架的想法。
祝大家思维愉快!
Tidyverse 与 Base-R:如何为你选择最佳框架
原文:
towardsdatascience.com/tidyverse-vs-base-r-how-to-choose-the-best-framework-for-you-29b702bdb384
R 编程最流行方法的优缺点
·发表于 Towards Data Science ·阅读时间 7 分钟·2023 年 2 月 27 日
–
程序员是充满热情的人。他们会就自己喜欢的语言和框架展开热烈的辩论(也就是激烈的争吵),捍卫自己偏爱的做法免受批评。在 R 编程社区中,其中一个最大的争论点就是选择两个框架之一:Base-R 和 tidyverse。
Base-R 指的是 R 编程语言中自带的所有功能。tidyverse 是一个扩展 R 的包集合,拥有自己在数据分析方面的理念和立场。两者都非常受欢迎,人们对哪个更好争论不休。
Base-R 爱好者指责 tidyverse 用户不是“真正的程序员”的推文似乎成了年度惯例。这场争论有点激烈。
有些人对 R 编程非常认真。截图来自 Twitter(作者编辑)
从我的角度来看,这种对立被过分夸大了。我认为这两种方法只是不同的工具集,应该根据你的需求来选择使用。
在这篇文章中,我将考虑五个问题,以帮助你在 tidyverse 和 Base-R 之间做出选择。根据你的情况,我还会给出我对哪个框架更适合你的判断。
1. 哪个更容易使用?
就像木匠不会用黄油刀来修剪地板一样,当使用 R 时,你应该选择合适的工具。尽管 Base-R 和 tidyverse 提供了大致相同的功能,但在某些方面,一个方法要比另一个更容易使用。
例如,tidyverse 通常是快速且简单的数据操作的最佳选择。通过许多变量对数据集进行分组以创建汇总统计,使用像 dplyr 这样的包比使用 Base-R 函数要容易得多。
从初学者到高级用户,使用这些分组工作流
[towardsdatascience.com
然而,Base-R 更适合用于运行快速模拟等其他应用。根据你日常工作中 R 的使用情况,你的首选框架可能会有所变化。
在考虑可用性时,还值得考虑你的技能水平和编程背景。
初学者往往更喜欢 tidyverse,因为它比 Base-R 更易读。语法在函数之间一致,使得学习更容易,而且关键函数有描述性的名称,这使得阅读代码像是一组简单的指令。
话虽如此,一些经验丰富的程序员对此感到困惑,更喜欢 Base-R 的感觉。与 tidyverse 不同,Base-R 更加注重程序功能,这对来自其他语言的开发者来说更为熟悉。
2. 哪个更快?
在进行计算开销较大的操作时,执行时间非常重要。在许多情况下,Base-R 和 tidyverse 之间的速度差异非常大。
举个例子,当 Base-R 速度明显更快时,我们可以使用内置于 R 的 mtcars 数据集。执行一个简单的操作,比如筛选数据集以仅显示六缸的汽车,Base-R 的速度比 tidyverse 快超过 40 倍!
library(microbenchmark)
library(tidyverse)
results <- microbenchmark(mtcars %>% filter(cyl == 6),
mtcars[mtcars$cyl == 6,])
summary(results) %>%
as_tibble() %>%
select(expression = expr, mean_execution_time = mean)
当然,tidyverse 版本对初学者来说更具可读性,并且有其他优点。但是,如果你运行的脚本中需要重复执行该筛选操作数百次,那么 40 倍的性能提升将非常实用。
尽管在很多情况下 Base-R 的速度比 tidyverse 更快,但有时情况也可能正好相反。虽然 Base-R 通常在速度上占优,但根据具体情况进行检查是值得的。
3. 我的合作者使用哪种工具?
尽管能够独立编写出色的代码很重要,但每个 R 用户的生活中都会遇到必须分享代码的时候。无论你是科学家、开发者还是数据分析师,让别人能够理解并使用你的代码至关重要。
在这里,你应该听取同事对 R 包的偏好。如果你合作的每个人都使用 tidyverse,那么考虑在某些情况下默认使用它以便于合作。同样地,如果他们都使用 Base-R。
与同事有共同的方法也有助于遇到问题或顽固的错误时。以个人经验为例,我在学习了 tidyverse 之后,与我以 tidyverse 为主的同事合作时要容易得多,尽管我在 R 学习的第二年才学会它。
这并不是说你必须根据合作伙伴的心情来限制自己使用 tidyverse 或 Base-R。即使我和我合作的大多数人默认使用 tidyverse,我偶尔也会为他们编写 Base-R 代码。不过,使用他们喜欢的方法作为基础是有帮助的。
4. 哪个社区更易于接触?
除了合作学习外,学习 R 最好的事情之一是它附带的在线社区。很多人和组织分享 R 的技巧和更新,这可以帮助你改进代码。
对于 tidyverse 和 Base-R 爱好者来说,社区精神总是充足的。#RStats 是获取社交媒体技巧的好地方。还有很多博客,包括 Medium 上的,提供 Base-R 和 tidyverse 的技巧。
快速而免费地深入理解 R。
对于 tidyverse 爱好者来说,每周的 Tidy Tuesday 活动强调使用 tidyverse 包创建惊艳的可视化。R for Data Science 社区也源于 Hadley Wickham 合著的同名开创性书籍,他是 tidyverse 的共同创建者。
许多忠实的 Base-R 爱好者历史上曾在论坛上聚集。尽管许多人也在社交媒体上,但在 Twitter 和 Mastodon 等平台上,tidyverse 似乎有更多的社区存在。根据你在线上花费的时间,你可以对这两种方法有很多了解。
5. 哪个更适合软件开发?
虽然 tidyverse 很棒,但它在软件开发方面可能会有所不足。目前 tidyverse 中有超过 25 个包,每个包都需要自己的更新以保持最新。
如果你依赖这些技巧来编写自己的 R 包或其他软件,你的代码中可能会引入许多额外的依赖。虽然依赖额外的包不一定不好,但也不是理想的。
你的代码功能现在受其依赖的包的更新影响;这些更新是你无法控制的。依赖越多,重现你的环境以便他人运行你的代码就变得越困难。
如果你认真对待 R 开发并想向 CRAN 提交一个包,你会面临严格的依赖限制,这些限制是由于这些(和其他)原因。此情况下,tidyverse 包通常可能不适合。
相比之下,Base-R 不引入额外的依赖。问题解决。
你应该选择哪个:Base-R 还是 tidyverse?
综上所述,你应该选择哪一个——Base-R 还是 tidyverse?
两者都可以。
是的,这有点避重就轻。但说真的。了解这两种方法是扩展你的工具集并确保你能够处理 R 中所有类型任务的最佳方式。
话虽如此,许多程序员在日常工作中仍然专注于一种方法,并在需要时添加另一种方法的部分。以下是选择每种方法作为默认方法的一些理由。
如果你有以下情况,请将 tidyverse 设为你的默认方法:
-
大多数你的工作涉及数据清理、可视化和常见统计
-
你刚开始接触 R,觉得 Base-R 比 tidyverse 更容易阅读和理解
-
大多数你的合作者和在线网络也在使用它
如果你有以下情况,请将 Base-R 设为你的默认方法:
-
大多数你的工作涉及软件或包开发、先进的统计程序,或计算密集型操作
-
你习惯使用与 Base-R 更相似的其他语言
-
大多数你的合作者和在线网络也在使用它
这不是使用每个包的原因的详尽列表,但它们可以帮助你根据你的情况做出正确的选择。
作为心理学研究人员,我在进行大多数数据清理和简单分析时默认使用 tidyverse。然而,在进行更复杂的统计建模和模拟,或者当依赖性是个问题时,我会使用 Base-R。
最重要的是,我认为没有一种正确的方法。使用 tidyverse 并不会阻止你成为一个“真正的 R 程序员”,使用 Base-R 也不会阻止你编写整洁的代码。它们只是工具集,你可以用它们来做出很酷的 R 作品。
学习两者,混合搭配,使用适合工作的工具。
想要阅读我关于 R 编程、数据科学等的所有文章?请在 这个链接 注册 Medium 会员,获取我所有文章的完整访问权限以及 Medium 上的其他故事。这也直接帮助我,因为我可以从你的会员费中获得一小部分贡献,而你无需额外支付费用。
你还可以通过 订阅这里 直接将我所有的新文章送到你的收件箱。感谢阅读!
时间序列增强
一种简单但有效的增加时间序列数据量的方法
·
关注 发布于 Towards Data Science ·8 min read·2023 年 10 月 19 日
–
这篇博客文章可以在 GitHub 上的 jupyter notebook找到。
增强已成为计算机视觉管道中不可或缺的组成部分。然而,它们在其他领域如时间序列中的受欢迎程度却没有达到相同的高度。在本教程中,我将深入探讨时间序列增强的世界,阐明其重要性,并提供使用强大的生成时间序列建模库 TSGM [5]的实际应用示例。
我们的起点是一个标记为(𝐗,𝐲)的数据集。在这里,𝐱ᵢ ∈ 𝐗 是多变量的(意味着每个时间点是一个多维特征向量)时间序列,而 y 是标签。预测标签 y 被称为下游任务。我们的目标是使用(𝐗,𝐲)生成额外的样本(𝐗*,𝐲*),这可以帮助我们更有效地解决下游任务(在预测性能或鲁棒性方面)。为了简化起见,我们在本教程中不会处理标签,但我们在这里描述的方法可以很容易地推广到有标签的情况,并且我们使用的软件实现可以通过向.generate
方法添加额外参数来轻松扩展到监督情况(见下例)。
事不宜迟,让我们逐一考虑时间序列增强。
在 TSGM 中,所有的增强方法都整齐地组织在tsgm.models.augmentations
中,你可以查看 TSGM documentation 提供的全面文档。
现在,让我们通过安装 tsgm 来启动编码示例:
pip install tsgm
接下来,我们导入 tsgm,并加载一个示例数据集。一个张量X
现在包含 100 个长度为 64 的正弦时间序列,每个序列有 2 个特征。具有随机的偏移、频率和振幅(最大振幅为 20)。
# import the libraries
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
import random
from tensorflow import keras
import tsgm
# and now generate the dataset
X = tsgm.utils.gen_sine_dataset(100, 64, 2, max_value=20)
抖动 / Gaussian 噪声
作为第一个增强方法,我们考虑抖动。
时间序列数据通过随机 Gaussian 噪声进行增强 (Wikipedia))
在 tsgm 中,Gaussian 噪声增强可以如下应用:
aug_model = tsgm.models.augmentations.GaussianNoise()
samples = aug_model.generate(X=X, n_samples=10, variance=0.2)
Gaussian 噪声增强的理念是,向时间序列中添加少量的抖动可能不会显著改变它,但会增加数据集中这种噪声样本的数量。这通常使下游模型对噪声样本更具鲁棒性或提高预测性能。
Gaussian 噪声的超参数及其添加方式(例如,Gaussian 噪声可能会在时间序列的末尾增加)是一个困难的问题,并且取决于特定的数据集和下游问题。通常值得进行实验,看看这些参数如何影响目标模型的性能。
在这里,我们提供了原始正弦数据集样本和增强样本的可视化。
原始时间序列和通过抖动生成的合成数据。
打乱特征
另一种时间序列增强的方法是简单地打乱特征。这种方法仅适用于特定的多变量时间序列,其中这些序列对所有或特定特征的排列是不变的。例如,它可以应用于每个特征表示来自各种传感器的相同独立测量的时间序列。
为了解释这种方法,假设有五个相同的传感器,标记为 S_1, S_2, S_3, S_4 和 S_5。为了说明,假设传感器 1 到 4 在旋转方面是可以互换的。那么,尝试在 S_1,…,S_5 传感器的旋转角度上进行特征旋转的数据增强是有意义的。
在这个例子中,有五个传感器,来自这些传感器的测量生成了五维时间序列数据。传感器 1 到 4 可以被任意旋转以生成新的合成样本(例如,1->2,2->3,3->4,4->1)。因此,通过对原始数据应用这些变换,可以生成新的合成样本。
与之前的例子类似,增强可以如下进行:
aug_model = tsgm.models.augmentations.Shuffle()
samples = aug_model.generate(X=X, n_samples=3)
这里,我们展示了一个具有 5 个特征的时间序列样本,以及一个增强样本,类似于上面的图像。
原始时间序列和通过特征洗牌生成的合成数据。
切片和洗牌
切片和洗牌增强 [3] 将时间序列切成片段并洗牌这些片段。对于在时间上表现出某种形式的不变性的时间序列,可以执行这种增强。例如,假设从可穿戴设备上测量的时间序列持续了几天。在这种情况下,一个好的策略是按天切割时间序列,并通过洗牌这些天来获得额外的样本。切片和洗牌增强在以下图像中可视化:
切片和洗牌示意图。
aug_model = tsgm.models.augmentations.SliceAndShuffle()
samples = aug_model.generate(X=X, n_samples=10, n_segments=3)
让我们查看增强样本和原始样本:
原始时间序列和通过切片和洗牌生成的合成数据。
幅度扭曲
幅度扭曲 [3] 通过将原始时间序列与立方样条曲线相乘来改变时间序列数据集中每个样本的幅度。这个过程会缩放时间序列的幅度,这在许多情况下是有益的,例如我们用正弦波 n_knots
数量的结点在随机幅度下分布的合成例子,其中 σ 由函数 .generate
中的参数 sigma
设置。
aug_model = tsgm.models.augmentations.MagnitudeWarping()
samples = aug_model.generate(X=X, n_samples=10, sigma=1)
这里是一个原始数据和通过 MagnitudeWarping
生成的增强样本的例子。
原始时间序列和通过幅度扭曲生成的合成数据。
窗口扭曲
在这种技术 [4] 中,时间序列数据中的选定窗口要么加速,要么减速。然后,将整个结果时间序列缩放回原始大小,以保持时间步长在原始长度。请参见下面的这种增强的例子:
这种增强可能是有益的,例如,在设备建模中。在这种应用中,传感器测量可以根据设备的使用方式改变变化速度。
在 tsgm 中,与往常一样,可以通过以下方式进行生成:
aug_model = tsgm.models.augmentations.WindowWarping()
samples = aug_model.generate(X=X, n_samples=10, scales=(0.5,), window_ratio=0.5)
下面可以找到一个生成的时间序列示例。
原始时间序列和通过窗口规整生成的合成数据。
动态时间规整重心平均(DTWBA)
动态时间规整重心平均(DTWBA)[2]是一种基于动态时间规整(DTW)的扩增方法。DTW 是一种测量时间序列相似性的方法。其思想是“同步”这些时间序列,如下图所示。
DTW 用于测量两个时间序列信号 sin(x)和 sin(2x)的相似性。DTW 测量通过白色线条显示。此外,还可视化了交叉相似性矩阵。
关于 DTW 计算的更多细节可以在rtavenar.github.io/blog/dtw.html
中找到。
DTWBA 的过程如下:
1. 算法选择一个时间序列来初始化 DTWBA 结果。这个时间序列可以明确给出,也可以从数据集中随机选择。
2. 对于每一个N
个时间序列,算法计算 DTW 距离和路径(路径是最小化距离的映射)。
3. 在计算所有N
个 DTW 距离后,算法通过对所有找到的路径进行平均来更新 DTWBA 结果。
4. 算法重复步骤(2)和(3),直到 DTWBA 结果收敛。
参考实现可以在tslearn中找到,描述可以在[2]中找到。
在 tsgm 中,可以通过以下方式生成样本:
aug_model = tsgm.models.augmentations.DTWBarycentricAveraging()
initial_timeseries = random.sample(range(X.shape[0]), 10)
initial_timeseries = X[initial_timeseries]
samples = aug_model.generate(X=X, n_samples=10, initial_timeseries=initial_timeseries )
原始时间序列和通过 DTWBA 生成的合成数据。
使用生成机器学习模型进行扩增
另一种扩增方法是训练一个机器学习模型在历史数据上,并训练它生成新颖的合成样本。这是一种黑箱方法,因为很难解释新样本是如何生成的。在时间序列的情况下,可以应用几种方法;特别是,tsgm 拥有 VAE、GANs 和高斯过程。以下是使用 VAE 生成合成时间序列的示例:
n, n_ts, n_features = 1000, 24, 5
data = tsgm.utils.gen_sine_dataset(n, n_ts, n_features)
scaler = tsgm.utils.TSFeatureWiseScaler()
scaled_data = scaler.fit_transform(data)
architecture = tsgm.models.zoo“vae_conv5”
encoder, decoder = architecture.encoder, architecture.decodervae = tsgm.models.cvae.BetaVAE(encoder, decoder)
vae.compile(optimizer=keras.optimizers.Adam())
vae.fit(scaled_data, epochs=1, batch_size=64)
samples = vae.generate(10)
结论
我们探索了几种合成时间序列生成方法。许多方法将归纳偏差引入模型,并在实际应用中非常有用。
如何选择?首先,分析你的问题是否包含不变性。它对随机噪声不变吗?对特征洗牌不变吗?
接下来,选择一组广泛的方法,并验证这些方法中的任何一种是否提高了下游问题的性能(tsgm 有下游性能指标)。然后,选择那些提供最大性能提升的扩增方法。
最后但同样重要的是,我感谢 Letizia Iannucci 和 Georgy Gritsenko 对于这篇文章写作的帮助和有益讨论。除非另有说明,所有图片均由作者提供。
这篇博客文章是 TSGM 项目的一部分,我们正在创建一个工具,通过增强和合成数据生成来提升时间序列管道。如果你觉得它有帮助,可以查看 我们的仓库 并考虑引用 关于 TSGM 的论文:
@article{
nikitin2023tsgm,
title={TSGM: A Flexible Framework for Generative Modeling of Synthetic Time Series},
author={Nikitin, Alexander and Iannucci, Letizia and Kaski, Samuel},
journal={arXiv preprint arXiv:2305.11567},
year={2023}
}
参考文献
[1] H. Sakoe 和 S. Chiba, “用于口语词汇识别的动态规划算法优化”。IEEE 声学、语音与信号处理学报, 26(1), 43–49 (1978)。
[2] F. Petitjean, A. Ketterlin & P. Gancarski. 动态时间规整的全局平均方法及其在聚类中的应用。模式识别,Elsevier,2011,第 44 卷,第 3 期,第 678–693 页。
[3] Um TT, Pfister FM, Pichler D, Endo S, Lang M, Hirche S,
Fietzek U, Kulic´ D (2017) 使用卷积神经网络对可穿戴传感器数据进行数据增强以监测帕金森病。发表于第 19 届 ACM 国际多模态交互会议论文集,第 216–220 页。
[4] Rashid, K.M. 和 Louis, J., 2019. Window-warping: 一种用于施工设备活动识别的 IMU 数据时间序列数据增强方法。发表于 ISARC. 国际自动化与施工机器人学会国际研讨会论文集(第 36 卷,第 651–657 页)。IAARC 出版社。
[5] Nikitin, A., Iannucci, L. 和 Kaski, S., 2023. TSGM: 一种用于合成时间序列生成建模的灵活框架。arXiv 预印本 arXiv:2305.11567。 Arxiv 链接。
对跑步者疲劳检测的时间序列分类 — 一个教程
对跑步者可穿戴传感器数据进行的参与者间和参与者内分类的逐步演示
·
关注 发表在 Towards Data Science · 6 分钟阅读 · 2023 年 12 月 7 日
–
图片由作者提供
使用可穿戴传感器收集的运行数据可以提供有关跑步者表现和整体技术的洞见。这些传感器提供的数据通常具有时间序列的特性。本教程讲解了一个疲劳检测任务,其中时间序列分类方法用于跑步数据集。在本教程中,时间序列数据以原始格式使用,而不是从时间序列中提取特征。这导致数据中增加了一个维度,因此使用传统向量格式的数据的传统机器学习算法效果不佳。因此,需要使用特定的时间序列算法。
数据包含跑步者在正常和疲劳状态下的运动捕捉数据。数据使用位于爱尔兰都柏林大学的惯性测量单元(IMU)收集。本教程中使用的数据可以在zenodo.org/records/7997851
找到。数据呈现一个二分类任务,我们试图预测‘疲劳’和‘非疲劳’之间的区别。在本教程中,我们使用专门的 Python 包,Scikit-learn;这是一个用于 Python 的机器学习工具包,以及sktime;这是一个专门为时间序列机器学习创建的库。
数据集包含多个数据通道。在这里,为了简化问题,我们将问题建模为单变量问题,因此仅使用一个数据通道。我们选择了幅度加速度信号,因为它是性能最佳的信号[1, 2]。幅度信号是每个方向分量平方和的平方根。
关于数据收集和处理的更多详细信息可以在以下文献中找到,[1, 2]。
总结一下,在本教程中:
-
使用最先进的时间序列分类技术在可穿戴传感器收集的数据上执行时间序列分类任务。
-
对跑步者疲劳检测中使用的参与者间模型(全球化)和参与者内模型(个性化)进行了比较。
分类任务的设置
首先,我们需要加载分析所需的数据。对于此评估,我们使用“Accel_mag_all.csv”中的数据。我们使用 pandas 加载数据。确保你已经从https://10.5281/zenodo.7997850 下载了此文件。
import pandas as pd
filename = "Accel_mag_all.csv"
data = pd.read_csv(filename, header = None)
需要从 sktime 和 sklearn 包中调用一些函数,因此我们在开始分析之前加载它们:
from sktime.transformations.panel.rocket import Rocket
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import RidgeClassifierCV, LogisticRegression, LogisticRegressionCV
from sklearn.model_selection import LeaveOneGroupOut
接下来,我们将标签和参与者编号分开。从这里开始,数据将通过数组来表示。
import numpy as np
X = data.iloc[:,2:].values
y = data[1].values
participant_no = data[0].values
对于这个任务,我们将使用 Rocket 变换结合岭回归分类器。Rocket 是一种用于时间序列分类的最先进技术[3]。Rocket 通过生成随机卷积核,然后沿时间序列进行卷积来生成特征图。然后,在此特征图上使用简单的线性分类器,例如岭回归分类器。可以创建一个管道,首先使用 Rocket 对数据进行变换,标准化特征,最后使用岭回归分类器进行分类。
rocket_pipeline_ridge = make_pipeline(
Rocket(random_state=0),
StandardScaler(),
RidgeClassifierCV(alphas=np.logspace(-3, 3, 10))
)
全球化分类
在我们有来自多个参与者的数据的应用中,使用所有数据一起意味着一个参与者的数据可能同时出现在训练集和测试集中。为避免这种情况,通常进行留一法(LOSO)分析,即模型在所有参与者的基础上进行训练,但测试时只测试一个被排除的参与者。这对于每个参与者都重复此过程。这种方法可以测试模型在参与者之间泛化的能力。
logo = LeaveOneGroupOut()
logo.get_n_splits(X, y, participant_no)
Rocket_score_glob = []
for i, (train_index, test_index) in enumerate(logo.split(X, y, participant_no)):
rocket_pipeline_ridge.fit(X[train_index], y[train_index])
Rocket_score = rocket_pipeline_ridge.score(X[test_index],y[test_index])
Rocket_score_glob = np.append(Rocket_score_glob, Rocket_score)
打印出上述结果的摘要:
print("Global Model Results")
print(f"mean accuracy: {np.mean(Rocket_score_glob)}")
print(f"standard deviation: {np.std(Rocket_score_glob)}")
print(f"minimum accuracy: {np.min(Rocket_score_glob)}")
print(f"maximum accuracy: {np.max(Rocket_score_glob)}")
上述代码的输出:
Global Model Results
mean accuracy: 0.5919805636306338
standard deviation: 0.10360659996594646
minimum accuracy: 0.4709480122324159
maximum accuracy: 0.8283582089552238
从这次 LOSO 分析中得到的准确率明显较低,有些数据集的结果甚至和随机猜测一样差。这表明,一个参与者的数据可能无法很好地泛化到另一个参与者。这是处理个人传感数据时常见的问题,因为运动技术和整体生理状况因人而异。此外,在此应用中,一个人如何应对疲劳可能与另一个人不同。让我们看看通过个性化模型是否可以提高性能。
个性化分类
在构建个性化模型时,预测是基于个人的数据进行的。在将时间序列数据分为训练集和测试集时,应以数据未被打乱的方式进行。为此,我们将每个类别分为单独的训练集和测试集,以保持训练集和测试集中每个类别的比例,同时保持数据的时间序列特性。使用跑步的前三分之一的数据来训练模型,以预测最后三分之一的数据。
Rocket_score_pers = []
for i, (train_index, test_index) in enumerate(logo.split(X, y, participant_no)):
#print(f"Participant: {participant_no[test_index][0]}")
label = y[test_index]
X_S = X[test_index]
# Identify the indices for each class
class_0_indices = np.where(label == 'NF')[0]
class_1_indices = np.where(label == 'F')[0]
# Split each class into train and test using indexing
class_0_split_index = int(0.66 * len(class_0_indices))
class_1_split_index = int(0.66 * len(class_1_indices))
X_train = np.concatenate((X_S[class_0_indices[:class_0_split_index]], X_S[class_1_indices[:class_1_split_index]]), axis=0)
y_train = np.concatenate((label[class_0_indices[:class_0_split_index]], label[class_1_indices[:class_1_split_index]]), axis=0)
X_test = np.concatenate((X_S[class_0_indices[class_0_split_index:]],X_S[class_1_indices[class_1_split_index:]]), axis=0)
y_test = np.concatenate((label[class_0_indices[class_0_split_index:]], label[class_1_indices[class_1_split_index:]]), axis=0)
rocket_pipeline_ridge.fit(X_train, y_train)
Rocket_score_pers = np.append(Rocket_score_pers, rocket_pipeline_ridge.score(X_test,y_test))
打印出上述结果的摘要:
print("Personalised Model Results")
print(f"mean accuracy: {np.mean(Rocket_score_pers)}")
print(f"standard deviation: {np.std(Rocket_score_pers)}")
print(f"minimum accuracy: {np.min(Rocket_score_pers)}")
print(f"maximum accuracy: {np.max(Rocket_score_pers)}")
上述代码的输出:
Personalised Model Results
mean accuracy: 0.9517626092184379
standard deviation: 0.07750979452994386
minimum accuracy: 0.7037037037037037
maximum accuracy: 1.0
通过个性化模型,性能得到了显著提升。因此,在此应用中,显然从一个人到另一个人的泛化存在困难。
结论
为了对来自可穿戴传感器的时间序列数据进行分类,使用了最先进的技术 Rocket。这项分析表明,在这一领域中,个性化模型能带来更好的分类模型。
全球分类与每个参与者的个性化分类所获得的准确率
上图显示了使用个性化模型在性能上的显著提升,对于许多参与者,性能几乎翻倍。这种现象可能与个体间生理和跑步技巧的差异有关。从用户的角度来看,全球模型和个性化模型在不同的应用场景下都有其优点。例如,在需要监测个体用户运动技巧的临床环境中,个性化模型可能会很有用。然而,从单个个体收集足够的数据以进行准确预测可能是困难的,因此对于许多应用来说,全球模型将是理想的选择。
本教程中介绍的代码也可以在 github 上找到: github.com/bahavathyk/TSC_for_Fatigue_Detection
参考文献:
[1] B. Kathirgamanathan, T. Nguyen, G. Ifrim, B. Caulfield, P. Cunningham. 通过对可穿戴传感器数据进行时间序列分析来解释跑步者的疲劳,XKDD 2023: 第五届国际解释性知识发现数据挖掘研讨会,ECML PKDD,2023,xkdd2023.isti.cnr.it/papers/223.pdf
[2] B. Kathirgamanathan, B. Caulfield 和 P. Cunningham,“基于惯性测量单元的全球化运动分类模型,”2023 IEEE 第 19 届国际体感网络会议(BSN),波士顿,马萨诸塞州,美国,2023 年,页码 1–4,doi: 10.1109/BSN58485.2023.10331612。
[3] A. Dempster, F. Petitjean 和 G. I. Webb. ROCKET:使用随机卷积核进行极其快速和准确的时间序列分类。《数据挖掘与知识发现》,34(5):1454–1495,2020。
时间序列复杂性分析使用熵
这里有一种方法,可以用几行代码了解你的时间序列有多复杂
·
关注 发表在 Towards Data Science ·8 分钟阅读·2023 年 9 月 4 日
–
图片由作者提供,使用 Midjourney 生成
每个数据科学家都知道:解决机器学习问题的第一步是探索数据。
而且,这不仅仅是理解哪些特征可以帮助你解决问题。这实际上需要领域知识、大量的努力、很多询问和尝试去了解。这是一个必要的步骤,但在我看来,这是第二步。
第一步在某种程度上、形态上或形式上,基于对你数据的复杂性分析。他们是让你在总是一样的东西中寻找细节和模式,还是输出完全不同?他们想让你找到 0.0001 和 0.0002 之间的距离,还是找到 0 和 10 之间的距离?
让我更好地解释一下。
比如说,我是一个信号处理专家。我学习了傅里叶变换、chirplet 变换、小波变换、希尔伯特变换、时间序列预测、时间序列聚类、1D CNN、RNN,以及许多其他吓人的名字。
在时间序列领域,一个非常常见的问题是从一个输入(可能是另一个时间序列)到一个时间序列输出。例如:
-
你有一个实验设置的属性,你想使用机器学习来模拟你的实验: 这实际上是我的博士论文,称为代理建模。
-
你有了股票市场到第 300 天的数据,你想预测第 301 天的情况:这非常著名,被称为时间序列预测。
-
你有一个非常脏或嘈杂的信号,你想清理它:这被称为编码器-解码器信号去噪,也非常著名。
在这些问题中,我惊讶地发现,首先看的通常是输出(而不是输入)时间序列。
假设我在我的数据集中取一个随机时间序列。这个时间序列是一个温和且平滑的正弦和余弦组合吗?它是一个多项式函数吗?它是一个对数函数吗?还是一个我连名字都无法称呼的函数?
如果我再拿一个随机时间序列,它会如何变化?任务是基于从明显的基线中观察到的小变化,还是识别整个数据集中完全不同的行为?
用一句话来说,我们试图理解我们的任务有多复杂:我们在估计时间序列的复杂性。现在,“复杂”这个词对我们每个人的意义可能不同。
当我妻子向我展示她的解剖学课程时,我发现它们极其复杂,但对她来说,这只是另一个星期二 😃
好消息是,有一种更科学和独特的方式来描述复杂性:熵的概念。
1. 1/0 时间序列的熵(理论)
让我们从一个非常简单的例子开始定义熵:一个只能有值 1 和 0 的时间序列。我知道这并不是我们习惯处理的时间序列类型,但你可以想象成每分钟你进入房间时翻一个硬币:如果是正面,你测得 1;如果是反面,你测得 0(或者相反,坦白说我并没有特别偏好 1 是正面……)。
作者制作的图像
现在,如果你考虑一下,当它在我们的大脑中没有真正的印象时,或者当它没有给你大量信息时,某些东西会更“复杂”。
我不再逗你了,我将给你这个该死的熵的方程:
方程 1
让我们分解一下:
-
X是我们的时间序列的领域,在我们的例子中,X = {0,1}
-
**p(x)**是验证 X 中值 x 的概率
为什么里面有对数?这是什么意思?为什么有那个负号?
让我们通过示例来学习。
想象一下 X 为 0(尾部)的概率是 0,X 为 1(头部)的概率是 1. 这甚至不是真正的时间序列,因为它总是 1. 熵的值是多少?
现在,p(x=0)=0,因此第一个贡献是 0. p(x=1)=1,但 1 的对数是 0. 这意味着第二个贡献也是 0,因此熵确实是 0。
熵是 0 是什么意思?意味着时间序列完全不复杂,这很有意义,因为它看起来像这样:
图片来源于作者
这个时间序列没有“复杂性”,对吧?这就是为什么它的熵是 0。
如果我们知道 p(x=0)=p(x=1)=0.5,那么意味着 1 和 0(正面或反面)的概率完全相同。
图片来源于作者
这确实更复杂了,不是吗?
熵现在变成:
这个值高于 0. 这个值本身没有意义,但它是你可以得到的最高值。这意味着如果你将 p(x=0)更改为不同于 0.5 的值,熵会降低*。
图片来源于作者
*** 注意,当你改变 p(x=0)时,你也会改变 p(x=1),因为 p(x=1)=1-p(x=0)**
现在让我们思考一下我们的发现。
-
当概率是 0 时,这意味着没有复杂性,因为我们已经知道了一切:你只有一个值。
-
当概率是 0.0001 时,这意味着复杂性非常小,因为可能 x=0,但大多数时候 x 将等于 1
-
当概率是 0.5 时,现在复杂性是最大的,因为你真的不知道接下来会发生什么:它可能是 1 或 0,概率相同
这就是我们认为的“复杂”的概念。在简单的 1/0 方式中,你可以通过回顾出现次数来找到概率,并获取熵。
2. 1/0 时间序列的熵(练习)
在我们的代码中,我们将使用Python,并且我们还将使用非常基础的库:
让我们写代码以找到相同的解决方案,但使用概率的“回顾性”,或者说,使用它们的频率定义:
其中:
-
x 是定义域中的一个值:在我们的例子中,x 只有 0 和 1 两种可能,因此 x 的值为 0 或 1。
-
n(x) 是时间序列中x出现的次数。
-
N 是我们时间序列的长度。
我们将找到 p(x=0)和 p(x=1),然后使用上面的方程 1……
好的,我再为你粘贴一次:
方程 1
在Python中,你可以通过这段非常简单的代码来实现:
它有效吗?让我们测试一下!
让我们生成一个长度为 100 的时间序列,0 出现的概率为 0.5:
太棒了。所以我们得到了平衡的时间序列。虽然我们设置了 0.5 作为概率,但这并不意味着完全50 和 50,如你所见,这会给我们在估计概率时带来一些误差。这就是我们生活在的不完美世界 😃
计算理论熵的方程如下:
让我们看看理论熵和实际熵是否匹配:
太棒了!它们确实匹配!
现在让我们改变 p_0,看看它们是否继续匹配:
它们匹配的误差非常小,对吧?
有趣的是,如果我们这样做三次,增加时间序列的大小,误差将会越来越小。
在大小为 10k 后,我们基本上没有实际熵和预测熵之间的差异❤
3. 任意时间序列的熵
现在,如果我们仍然假设我们的时间序列具有离散值(0、1、2……),我们可以扩展熵的定义,适用于超过 2 个值的时间序列。
例如,让我们选择一个三值情况。所以我们的时间序列可以是 0、1 或 2。
让我们创建一个新的概率向量 p_0、p_1 和 p_2。为此,我们将生成 3 个 0 到 100 之间的随机数,并将它们存储在一个向量中,然后除以总和:
我们可以使用之前相同的方程(和相同的代码)来计算实际熵和预测熵。
让我们扩展熵的定义到实际熵的定义中:
这同样适用于仅有 0/1 的情况:
正如我们所看到的,即使在三值情况下,理论熵和预测熵也相匹配:
为了向你展示我没有作弊,我们可以看到它适用于各种情况。如果我们迭代地改变 p_vector(和时间序列),我们仍然会看到实际熵和预测熵匹配:
4. 结果
在这篇博客中,我们:
-
反思在应用任何机器学习之前分析时间序列的复杂性。
-
反思了时间序列的熵和无序的概念。
-
定义了熵的数学方程,并通过示例进行解释。
-
在实践中应用了 0/1 时间序列和 0、1、2 时间序列,展示了理论定义如何与我们的计算近似相匹配。
现在,这种方法的问题(限制)是有时时间序列可能过于连续,以至于该方法无法工作。但不要惊慌!有一种连续熵的定义可以修正时间序列的熵。
我将在下一篇博客中讨论!
5. 结论
如果你喜欢这篇文章并且想了解更多关于机器学习的内容,或者你只是想问我一些问题,你可以:
A. 在Linkedin上关注我,我会在上面发布所有的故事。
订阅我的新闻通讯。它会让你了解新故事,并给你机会向我提问,获取所有可能的修正或解答。
成为推荐会员,这样你就不会有“每月最大故事数量”的限制,可以阅读我(以及其他数千名机器学习和数据科学顶级作者)关于最新技术的文章。
使用 sARIMA 和 Dash 进行时间序列数据分析
介绍一个 Dash 网页应用程序,指导时间序列数据集的分析,使用 sARIMA 模型 | 在线应用 | Git Hub
·
关注 发表在 Towards Data Science · 10 分钟阅读 · 2023 年 5 月 6 日
–
介绍
在处理时间序列数据集时,统计模型如 SARIMA 可以是理解数据组成部分(趋势、季节性和时间依赖性)的强大工具。
本文将简要介绍 sARIMA 模型,然后展示一个网页应用程序,该程序指导用户完成分析数据和拟合最佳模型以进行预测的步骤。该应用程序是使用 Plotly Dash 和 Python 构建的:
目录:
1. Sarima 模型的理论介绍
1.1 模型的基本构件
1.2 如何选择模型超参数:ACF 和 PACF
1.3 平稳性
2. 实用模板用于处理 Sarima 模型
2.1 绘制你的数据
2.2 将数据转换为平稳
2.3 使用 ACF 和 PACF 确定合适的模型超参数
2.4 执行模型网格搜索以识别最佳超参数
2.5 最终模型:拟合和预测
结论
1. Sarima 模型的理论介绍
1.1 模型的基本构件
要理解 sARIMA 模型是什么,我们首先介绍这些模型的基本构件。
sARIMA 是由不同子模型组成的(即我们用来表示时间序列数据的多项式),其缩写为:季节性(s)自回归(AR)积分(I)移动平均(MA):
- AR:自回归组件,由超参数“p”控制,假设在时间“t”上的当前值可以表示为前“p”值的线性组合:
AR | 作者提供的图片
- I:积分组件由超参数“d”表示,这是应用于数据的差分变换的阶数。差分是一种用于去除数据趋势的技术(即使数据相对于均值平稳,正如我们稍后会看到的),这有助于模型拟合数据,因为它隔离了趋势组件(我们使用 d=1 处理线性趋势,d=2 处理二次趋势,等等)。差分数据 d=1 意味着处理连续数据点之间的差异:
I | 作者提供的图片
- MA:移动平均组件,由超参数“q”控制,假设在时间“t”上的当前值可以表示为一个常数项(通常是均值)加上前“q”点误差的线性组合:
MA | 作者提供的图片
- 如果我们考虑到目前的组件,我们得到“ARIMA”,这是一个用于处理没有季节性的时间序列数据的模型家族的名称。sARIMA 模型是一种广泛应用于具有季节性的数据的模型,通过增加一个 S 组件:季节性组件,它由一组新的 AR、I、MA 组件组成,并带有季节滞后。换句话说,一旦确定了季节性并定义了其滞后(由超参数“m”表示——例如 m=12 意味着在每年的月度数据集中,我们会看到相同的行为),我们会创建一组新的 AR(P)、I(D)、MA(Q)组件,相对于季节滞后(m)(例如如果 D=1 且 m=12,这意味着我们对序列应用 1 阶差分,滞后为 12)。
总结一下,sARIMA 模型由 7 个超参数定义:3 个用于模型的非季节性部分,4 个用于季节性部分。它们表示为:
sARIMA (p,d,q) (P,D,Q)m
多亏了模型的灵活性,我们可以“关闭”数据中未体现的组件(即如果数据没有趋势或季节性,相应的参数可以设置为 0),仍然使用相同的模型框架来拟合数据。
另一方面,sARIMA 的局限性之一是这些模型只能捕捉到 1 种季节性。如果一个每日数据集具有年季节性和周季节性,我们需要选择其中较强的一种。
1.2 如何选择模型超参数:ACF 和 PACF
为了确定模型超参数,我们通常查看时间序列的自相关和部分自相关;由于所有上述组件使用过去的数据来建模现在和未来的数据点,我们应该研究过去和现在的数据是如何相关的,并定义需要多少个过去的数据点来建模现在。
因此,自相关和部分自相关是两个广泛使用的函数:
- ACF(自相关):描述时间序列及其滞后的相关性。所有数据点都与它们之前的滞后 1、滞后 2、滞后 3 等进行比较。结果的相关性绘制在直方图上。此图(也称为“自相关图”)用于可视化整个时间序列中保留了多少信息。ACF 帮助我们选择 sARIMA 模型,因为:
ACF 有助于确定 MA(q)超参数。
- PACF(部分自相关):描述时间序列及其滞后的部分相关性。与 ACF 不同,PACF 显示了一个点 X_t 和一个滞后之间的相关性,而这种相关性并未被与其他较低滞后的常见相关性所解释。换句话说,PACF 隔离了两个项之间的直接相关性。PACF 帮助我们选择 sARIMA 模型,因为:
PACF 有助于确定 AR§超参数。
然而,在使用这些工具之前,我们需要提到 ACF 和 PACF 只能用于“平稳”的时间序列。
1.3 平稳性
一个(弱)平稳的时间序列是一个:
-
均值是恒定的(即序列围绕一条水平线波动,没有正或负趋势)
-
方差是恒定的(即没有季节性或均值偏离的变化)
当然,并不是所有的时间序列本身就是平稳的;然而,我们可以通过转换来使它们变得平稳。最常见的转换用于使时间序列平稳包括:
-
自然对数:通过对每个数据点应用对数,我们通常能够使时间序列在方差方面变得平稳。
-
差分:通过对时间序列进行差分,我们通常能够去除趋势,使时间序列在均值方面变得平稳。
在转换时间序列后,我们可以使用两个工具来确认它是否平稳:
-
Box-Cox图:这是一个滚动均值(x 轴)与滚动标准差(y 轴)(或分组点的均值与方差)的图。如果我们在图表中没有观察到任何特定趋势,并且在两个轴上都看到很少的变化,那么我们的数据就是平稳的。
-
增广迪基–福勒检验(ADF):一种统计检验,我们尝试拒绝原假设,即时间序列是非平稳的。
一旦时间序列平稳,我们可以分析 ACF 和 PACF 模式,并找到 SARIMA 模型的超参数。
2. 使用 Sarima 模型的实用模板
确定适合我们数据的 sARIMA 模型包括一系列步骤,我们将在 AirPassenger 数据集上执行这些步骤(数据集可在此处获取)。
每一步大致对应于 Dash 网页应用程序的一个“页面”。
2.1 绘制数据图
创建你的原始数据的折线图:一些上述特征可以通过肉眼看到,特别是平稳性和季节性。
原始折线图 | 图片由作者提供
在上面的图表中,我们看到一个正向线性趋势和一个反复出现的季节性模式;考虑到我们有月度数据,我们可以假设季节性为年度(滞后 12)。数据不是平稳的。
2.2 转换数据以使其平稳
为了找到模型超参数,我们需要使用平稳的时间序列。因此,如果数据不是平稳的,我们需要对其进行转换:
-
从对数变换开始,以使数据相对于方差平稳(对数定义在正值上。因此,如果数据呈现负值或 0 值,请在每个数据点上添加一个常数)。
-
应用差分以使数据相对于均值平稳。通常从差分阶数 1 和滞后 1 开始。如果数据仍然不平稳,尝试相对于季节性滞后进行差分(例如,如果我们有月度数据,则为 12)。 (使用反向顺序不会有差异)。
对于我们的数据集,我们需要执行以下步骤以使其完全平稳:
平稳转换 | 图片由作者提供
在每一步之后,通过查看 ADF 检验的 p 值和 Box-Cox 图,我们看到:
-
Box-Cox 图从任何趋势中逐渐变得干净,所有点越来越接近。
-
p 值逐渐下降。我们最终可以拒绝原假设。
平稳转换(2)| 图片由作者提供
2.3 使用 ACF 和 PACF 识别合适的模型超参数
在将数据转换为平稳的过程中,我们已经确定了 3 个参数:
- 由于我们应用了差分,模型将包括差分组件。我们应用了 1 和 12 的差分:我们可以设置 d=1 和 D=1,并且 m=12(12 的季节性)。
对于其余参数,我们可以查看变换后的 ACF 和 PACF。
一般来说,我们可以应用以下规则:
-
我们有一个AR§过程如果:PACF 在某个滞后“p”处有显著峰值(之后没有显著峰值),并且 ACF 衰减或显示出正弦波行为(交替的正、负峰值)。
-
我们有一个MA(q)过程如果:ACF 在某个滞后“q”处有显著峰值(之后没有显著峰值),并且 PACF 衰减或显示出正弦波行为(交替的正、负峰值)。
-
在季节性 AR§或 MA(Q)过程的情况下,我们会看到显著的峰值在季节性滞后处重复出现。
通过查看我们的示例,我们可以看到以下内容:
变换后的 ACF 和 PACF | 图片由作者提供
- 与上述行为最接近的规则,建议使用“q”介于 1 到 3 之间的某些 MA(q)过程;我们在 12 处仍然有显著的峰值,这也可能暗示着 MA(Q)过程,其中 Q=1(因为 m=12)。
我们使用 ACF 和 PACF 来获取一系列超参数值,这些值将形成模型候选者。我们可以将这些不同的模型候选者与我们的数据进行比较,并选择表现最好的一个。
在示例中,我们的模型候选者似乎是:
-
SARIMA (p,d,q) (P,D,Q)m = (0, 1, 1) (0, 1, 1) 12
-
SARIMA (p,d,q) (P,D,Q)m = (0, 1, 3) (0, 1, 1) 12
2.4 执行模型网格搜索以识别最佳超参数
网格搜索可以用来比较多个模型候选者:我们将每个模型拟合到数据中,并选择表现最好的一个。
要设置网格搜索,我们需要:
-
创建一个包含所有可能模型超参数组合的列表,给定每个超参数的值范围。
-
拟合每个模型,并使用选择的 KPI 测量其性能。
-
根据表现最佳的模型选择超参数。
在我们的案例中,我们将使用AIC(赤池信息量准则)分数来比较模型性能。这个 KPI 公式是拟合误差(准确性)与模型复杂性之间的权衡。一般来说,当复杂性过低时,误差较高,因为我们过度简化了模型拟合任务;相反,当复杂性过高时,由于过拟合,误差仍然较高。这两者之间的权衡将帮助我们识别“表现最佳”的模型。
实用说明:在拟合 sARIMA 模型时,我们需要使用带有对数变换的原始数据集(如果我们已应用),但我们不希望使用经过差分变换的数据。
我们可以选择保留部分时间序列(通常是最新的 20%观察值)作为测试集。
在我们的示例中,基于以下超参数范围,最佳模型是:
模型网格搜索 | 作者图片
SARIMA (p,d,q) (P,D,Q)m = (0, 1, 1) (0, 1, 1) 12
2.5 最终模型:拟合与预测
我们最终可以对训练集、测试集以及任何未来的样本观察进行预测。最终的图表是:
最终模型 | 作者图片
为了确认我们捕捉了所有的相关性,我们可以绘制模型残差的 ACF 和 PACF:
在这种情况下,强季节性成分的一些信号仍然存在,但大多数剩余滞后项的相关性为 0。
结论
上述步骤应适用于任何可以通过 sARIMA 建模的数据集。总结:
1-绘制并探索你的数据
Dash 实时应用 | 作者图片
2-应用变换使数据平稳(关注左侧图表和 ADF 测试)
Dash 实时应用 | 作者图片
3-通过查看 ACF 和 PACF(右侧图表)来确定合适的超参数
Dash 实时应用 | 作者图片
4-执行网格搜索以选择最佳超参数
Dash 实时应用 | 作者图片
5-使用最佳模型进行拟合和预测
Dash 实时应用 | 作者图片
在本地下载应用程序,上传自己的数据集(通过替换数据文件夹中的.csv 文件)并尝试拟合最佳模型。
感谢阅读!