TowardsDataScience 2023 博客中文翻译(一百三十八)

原文:TowardsDataScience

协议:CC BY-NC-SA 4.0

用 Python 预测间歇时间序列

原文:towardsdatascience.com/forecasting-intermittent-time-series-in-python-9fd028a0c9ee

Python 中间歇时间序列预测的完整指南及其重点项目

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 Marco Peixeiro

·发表于Towards Data Science ·15 分钟阅读·2023 年 8 月 7 日

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

照片由Wexor Tmg拍摄,来源于Unsplash

间歇时间序列或稀疏时间序列是一种特殊情况,其中非零值在时间上偶尔出现,而其余的值都是 0。

一个常见的稀疏时间序列示例是降雨量随时间的变化。可能会有连续很多天没有降雨,而降雨时,降雨量会有所不同。

另一个实际的间歇序列示例是对缓慢移动或高价值物品的需求,例如航空航天或重型机械中的备件。

一些时间序列的间歇性特征在预测中带来了真正的挑战,因为传统模型对间歇性处理不佳。因此,我们必须转向为稀疏时间序列量身定制的替代预测方法。

在这篇文章中,我们将探讨预测间歇时间序列的不同方法。和往常一样,我们首先从理论上探讨每个模型,然后在 Python 中实现它们。

和往常一样,完整的源代码可在GitHub上获得。

通过我的 免费时间序列备忘单 在 Python 中学习最新的时间序列分析技术!获取统计和深度学习技术的实现,全部使用 Python 和 TensorFlow!

让我们开始吧!

Croston 方法

Croston 方法是预测稀疏时间序列最常见的方法之一。它通常作为基准模型来评估更复杂的方法。

使用 Croston 方法,从原始序列中构建两个序列:

  • 包含只有零值的时间序列

  • 包含非零值时间段的时间序列

让我们考虑一个示例来说明这一点。考虑下面的稀疏时间序列:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

一个模拟的稀疏时间序列。图片由作者提供。

然后,根据 Croston 方法,我们创建两个新的序列:一个包含非零值,另一个包含分隔非零值的时间周期。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

构建两个新的序列。第一个序列只有非零值。第二个序列是非零值之间的周期。请注意,我们在两个连续值之间分配了周期为 1。图片由作者提供。

从上表中,我们可以看到我们将非零值表示为 qᵢ,两个连续非零值之间的周期表示为 aᵢ

还要注意 aᵢ 的第一个值是 1,因为我们在 t=1 处有一个非零值。此外,两个连续值之间的周期也被认为是 1。

从那里,我们使用简单指数平滑根据下面的方程预测每个序列:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

预测非零值。图片由作者提供。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

预测连续非零值之间的时间间隔。图片由作者提供。

当然,平滑参数 alpha 在 0 和 1 之间,因为我们使用的是简单指数平滑。请注意,两条方程中使用的是相同的平滑参数。

然后,最终预测是 qa 的比率,如下方的方程所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

使用 Croston 方法的一步预测。图片由作者提供。

现在,由于使用简单指数平滑来预测每个序列,预测将是一个平坦的水平线。这就是为什么我们通常将其作为基线模型的原因。

此外,大多数基本 Croston 方法的实现使用平滑参数值为 0.1。

再次强调,这是预测间歇性时间序列的最基本方法,但有办法轻松改进它,我们将在接下来讨论。

改进 Croston 方法

正如我们之前看到的,经典的 Croston 方法使用相同的平滑参数 0.1 来预测两个构建的序列,这似乎并不理想。

提出了 Croston 方法的优化版本,其中平滑参数在 0.1 和 0.3 之间变化。此外,每个序列都是单独优化的。

一切保持不变,但现在我们为每个序列都有唯一的优化平滑参数,这些参数构成了最终预测。

Croston 方法的应用

让我们在一个模拟数据集上实现 Croston 方法,看看我们可以用这个模型做出什么样的预测。

首先,我将导入所需的库并读取数据。

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

sim_df = pd.read_csv('intermittent_time_series.csv')

然后,我们使用 statsforecast 中的实现。现在,让我们使用经典版本的 Croston 方法,该方法使用平滑因子 0.1。

from statsforecast import StatsForecast
from statsforecast.models import CrostonClassic

models = [CrostonClassic()]

sf = StatsForecast(
    df=sim_df,
    models=models,
    freq='H',
    n_jobs=-1
)

然后,为了将模型的预测与我们模拟数据集中的实际数据进行比较,我们运行交叉验证函数。在这里,我们将预测范围设置为 1,因此我们的预测曲线会在数据集的最后 50 个时间步上每个时间步进行更新。

cv_df = sf.cross_validation(
    df=sim_df,
    h=1,
    step_size=1,
    n_windows=50
)

然后,我们可以绘制实际值和模型预测值。

fig, ax = plt.subplots(figsize=(10,8))

ax.bar(sim_df.index, sim_df['y'], color='lightgray')
ax.plot(cv_df.index, cv_df['CrostonClassic'], ls='--', label='Croston')
ax.set_ylabel('Value')
ax.set_xlabel('Time steps')
ax.legend(loc='best')
plt.xlim(40, 100)

plt.tight_layout()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

使用 Croston 方法预测下一个时间步。图片由作者提供。

从上图中,我们可以直观地看到,Croston 方法实际上是间歇时间序列的加权平均。

仔细观察,如果过去的值较大,那么下一个预测值会增加;如果过去的值较小,那么下一个预测值会减少。

还要注意一段时间内我们有连续的零值,这意味着预测曲线没有更新,保持平坦。

最后,请记住我们的预测曲线变化很大,因为我们只预测下一个时间步。如果我们设定一个更长的预测范围,曲线将更像一个楼梯,因为 Croston 方法输出的是一个恒定值。

优化的 Croston 方法在实际操作中

现在,让我们重复上面的练习,但使用优化版本的 Croston 方法,其中平滑参数分别针对非零值序列和零值序列进行优化。

from statsforecast.models import CrostonOptimized

models = [CrostonOptimized()]

sf = StatsForecast(
    df=sim_df,
    models=models,
    freq='H',
    n_jobs=-1
)

cv_df = sf.cross_validation(
    df=sim_df,
    h=1,
    step_size=1,
    n_windows=50
)

cv_df.index = np.arange(50, 100, 1)

绘制结果生成了下图。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

使用优化后的 Croston 方法进行预测。在这种情况下,它与之前的方法基本相同。图片由作者提供。

从图中可以看到,优化平滑参数导致的预测与经典方法对我们模拟数据的预测几乎相同。

现在我们了解了 Croston 方法,让我们继续学习另一种预测技术。

汇总-拆分间歇性需求方法(ADIDA)

汇总-拆分间歇性需求方法(ADIDA)旨在通过在较低频率下汇总序列来去除间歇性。

例如,如果每小时数据有零值,那么对 24 小时数据求和以获得每日数据可能会去掉零值。同样的逻辑也适用于间歇性的日数据,我们可以将其汇总为周数据,以去除零值期间。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

用五个时间步的滚动总和来汇总我们的模拟数据。注意底部图(汇总值)如何有效去除了系列中的间歇性。图片由作者提供。

在上图中,我们可以看到汇总对模拟数据的影响。这里,我们对五个时间步进行了汇总。结果汇总序列如底部图所示,不再是间歇性的,因为我们去除了所有零值。

一旦数据被汇总,简单的指数平滑再次用于预测汇总后的序列。

然后,我们将预测值拆解回原始频率。例如,如果每小时数据被聚合到每日数据,那么每个预测值将除以 24(因为一天有 24 小时)来得到拆解后的预测值。

如何选择聚合水平

当然,聚合水平对预测和模型性能有很大影响。

如果聚合过大,例如从每小时数据聚合到每周数据,那么可能会丢失很多信息。

如果聚合过小,则结果系列也可能是间歇性的,此时传统的预测方法将无法适用。

尽管没有明确的答案来选择聚合水平,但在statsforecast中实现的一种方法是计算非零值之间所有间隔的长度,并取间隔的平均值作为聚合水平。

例如,如果您的间歇性系列中非零值之间的间隔为[3, 5, 4],则聚合水平将为 4。

在最佳情况下,这种方法可以完全消除间歇性。否则,只有少数零值会残留,这不会对指数平滑产生很大影响。

ADIDA 的实际应用

现在,让我们在模拟数据上实现 ADIDA,并查看我们获得的预测结果。

使用statsforecast,实现仍然简单明了,我们只需更改模型,但管道保持不变。

from statsforecast.models import ADIDA

models = [CrostonOptimized(), ADIDA()]

sf = StatsForecast(
    df=sim_df,
    models=models,
    freq='H',
    n_jobs=-1
)

cv_df = sf.cross_validation(
    df=sim_df,
    h=1,
    step_size=1,
    n_windows=50
)

cv_df.index = np.arange(50, 100, 1)

然后,我们绘制预测图,查看其与 Croston 方法的比较表现如何。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

使用 ADIDA(虚线)和 Croston 方法(虚线)进行预测。我们可以看到,ADIDA 对零值期间的反应更为明显,通过降低预测值来应对。图片由作者提供。

在上图中,我们可以看到 ADIDA 对零值期间的反应明显更强。尽管 Croston 的预测在观察到零值时保持不变,但 ADIDA 将逐渐降低预测曲线,因此更接近实际数据。

虽然 ADIDA 考虑了单一的聚合水平,但模型中提出了一次迭代来考虑多个聚合水平。这是我们在下一节中研究的内容。

间歇性多重聚合预测算法(IMAPA)

如前所述,ADIDA 只考虑一个聚合水平。

然而,信息可能会从不同聚合水平的系列中恢复。

例如,给定每小时数据,如果我们将数据聚合到每日、每周或每月,不同的模式会出现。

这就是间歇性多重聚合预测算法或 IMAPA 的基本思想。

数据再次被聚合,但在多个水平上。然后,就像 ADIDA 一样,使用简单指数平滑来生成每个聚合水平上的预测值。之后,每个预测值被拆解,就像在 ADIDA 中一样。

最终预测是通过在每个聚合级别上取每个预测值的平均值得到的。

因此,我们可以将 IMAPA 看作是在不同聚合级别上多次运行 ADIDA,然后简单地平均预测值以获得最终预测。

记住这些,让我们看看 IMAPA 在我们模拟数据上的表现。

IMAPA 的实际应用

仍然使用statsforecast,我们只需将 IMAPA 算法添加到我们的管道中。

from statsforecast.models import IMAPA

models = [ADIDA(), IMAPA()]

sf = StatsForecast(
    df=sim_df,
    models=models,
    freq='H',
    n_jobs=-1
)

cv_df = sf.cross_validation(
    df=sim_df,
    h=1,
    step_size=1,
    n_windows=50
)

cv_df.index = np.arange(50, 100, 1)

然后,我们可以绘制预测图。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

使用 IMAPA 进行预测。在这种情况下,它给出了与 ADIDA 相同的结果。图片来源于作者。

看上面的图,我们注意到两条曲线重叠,这意味着 IMAPA 和 ADIDA 在这种情况下给出了相同的预测结果。

尽管这有些令人失望,但请记住,我们正在使用模拟数据,很快我们将处理实际数据集。

在此之前,我们还有一种方法需要探索。

Teunter-Syntetos-Babai 模型(TSB)

Teunter-Syntetos-Babais 模型,或 TSB,提出了对 Croston 方法的改进。

正如我们之前所见,Croston 方法的预测在零值期间保持不变。这意味着在多个零值期间,预测可能会过时。

换句话说,Croston 方法忽略了过时的风险,这种风险发生在非零值被越来越长的零需求期隔开时。

这在低需求产品的库存管理中尤其重要,因为公司可能会持有多年未使用的库存,这会带来成本。因此,他们必须评估过时的风险,以确定是否可以处理过时库存。

这就是 TSB 模型的作用。它不会考虑需求间隔(即零值期间),而是考虑需求概率,定义为:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

需求概率的定义。图片来源于 R. Teunter、A. Syntetos、M. Babai,来自间歇性需求:将预测与库存过时性联系起来

尽管这似乎是一个小差异,但实际上可能会产生很大的影响。使用 Croston 方法时,需求间隔只能在观察到非零值后进行更新。

另一方面,需求概率在每个时间步长上都会更新,使模型更具灵活性。

为了进行预测,模型还会从原始序列中创建两个序列:

  • 一个包含仅非零值的序列(也称为需求

  • 另一个是需求概率

每个序列的预测是通过简单的指数平滑完成的。然后,通过将需求量与需求概率相乘,得到最终预测。

记住这些,让我们将 TSB 模型应用于我们的模拟数据。

TSB 的实际应用

与 Croston 方法的优化版本不同,statsforecast 中的 TSB 实现需要我们为每个序列指定平滑参数。

这意味着我们需要手动优化这些参数。现在,我们只使用 0.1 作为两个参数,只是为了看看模型在我们模拟数据上的表现。

from statsforecast.models import TSB

models = [TSB(0.1, 0.1), CrostonClassic()]

sf = StatsForecast(
    df=sim_df,
    models=models,
    freq='H',
    n_jobs=-1
)

cv_df = sf.cross_validation(
    df=sim_df,
    h=1,
    step_size=1,
    n_windows=50
)

cv_df.index = np.arange(50, 100, 1)

然后,我们可以绘制预测图。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

使用 TSB 进行预测。我们可以看到,在零需求期间,使用需求概率更新预测曲线,与 Croston 方法不同。图片由作者提供。

看上面的图,我们可以看到使用需求概率的效果很大,因为预测在无需求期间下降,而不是保持不变。

现在我们已经涵盖了许多间歇性时间序列的预测模型,让我们在一个小的 capstone 项目中应用我们的知识。

Capstone 项目 — 预测风力发电机的功率输出

风力发电机是可再生能源的来源,但由于风的不可预测性,它们不幸地不可靠。

有时,功率输出可能非常大,而其他时候,它可能非常小。

也可能有风速过强的天,因此风力发电机停机,不产生电力。此外,风速不足也会导致没有电力产生。

因此,我们可以看到风力发电机的功率输出是一个间歇性时间序列。

提醒一下,你可以在GitHub上查看这个项目的完整源代码。

数据准备

我们首先读取数据并将其格式化,以便我们可以使用statsforecast。我们删除不必要的列,并将时间格式化为时间戳。最后,我们创建一个unique_id列,并适当地重命名列。

df = pd.read_csv('TexasTurbine.csv')

df = df.drop(['Wind speed | (m/s)', 'Wind direction | (deg)', 'Pressure | (atm)', "Air temperature | ('C)"], axis=1)

start_date = pd.to_datetime('2023-01-01 00:00:00')
end_date = pd.to_datetime('2023-12-31 23:00:00')
date_range = pd.date_range(start=start_date, end=end_date, freq='H')

df['ds'] = date_range

df = df.rename(columns={'System power generated | (kW)': "y"})

df = df.drop(['Time stamp'], axis=1)

df['unique_id'] = 1
df = df[['unique_id', 'ds', 'y']]

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

格式化数据集的前五行。图片由作者提供。

这样,我们的数据就按照statsforecast的期望格式化了。请记住,unique_id列用于识别同一数据集中不同的时间序列。在我们的案例中,我们只有一个序列,所以unique_id对所有行都是恒定的。

然后,我们可以可视化我们的数据。在这里,我们仅关注前 200 个时间步骤,因为我们有一个相当大的数据集。

fig, ax = plt.subplots( figsize=(10,8))

ax.bar(df.index, df['y'], color='grey', width=0.1)
ax.set_ylabel('Wind power (kW)')
ax.set_xlabel('Time steps')

plt.xlim(0, 200)
plt.tight_layout()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

德克萨斯州风力发电机的功率输出。图片由作者提供。

从上图中,我们可以看到数据的间歇性。我们确实注意到零值期间,并且还注意到高功率输出和低功率输出之间的非常大波动。

现在,让我们尝试预测风力发电机的功率输出。我们将考虑三个不同的预测周期:

  • 一小时

  • 一天

  • 一周

对于每个预测周期,我们将使用平均绝对误差(MAE)来评估每个模型的性能,并选择最佳模型。我们的基准模型将是简单指数平滑。

预测下一小时

要测试不同的模型,我们只需将它们列出在 Python 列表中。

在这里,我们立即使用了优化后的 Croston 方法,以获得平滑参数的最佳值。

from statsforecast.models import SimpleExponentialSmoothingOptimized as SESOpt

models = [CrostonOptimized(), ADIDA(), IMAPA(), TSB(0.2, 0.2), SESOpt()]

完成这些操作后,我们可以初始化 Statsforecast 对象以传入我们的数据集,并指定数据的频率。

sf = StatsForecast(
    df=df,
    models=models,
    freq='H',
    n_jobs=-1 # use all computing power available
)

然后,我们进行交叉验证,将预测值与已知值进行比较。由于我们正在预测下一个小时,我们将预测期设置为 1。此外,我们在 50 次预测中评估我们的模型。

h_cv_df = sf.cross_validation(
    df=df,
    h=1, # Horizon is 1, since we forecast the next hour
    step_size=1, # Move the window by 1 time step
    n_windows=50 # Make 50 windows of cross-validation
)

h_cv_df.index = np.arange(8709, 8759, 1)

这会生成一个包含每个模型的预测值和实际值的 DataFrame。这使我们能够将预测值与实际值进行绘图。

fig, ax = plt.subplots( figsize=(10,8))

ax.bar(h_cv_df.index, h_cv_df['y'], color='lightgrey')
ax.plot(h_cv_df.index, h_cv_df['CrostonOptimized'], ls='--', label='Croston')
ax.plot(h_cv_df.index, h_cv_df['ADIDA'], ls=':', label='ADIDA')
ax.plot(h_cv_df.index, h_cv_df['TSB'], ls='-.', label='TSB')
ax.plot(h_cv_df.index, h_cv_df['SESOpt'], ls=':', label='SES')

ax.set_ylabel('Wind power (kW)')
ax.set_xlabel('Time steps')

ax.legend(loc='best')

plt.tight_layout()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

预测风力涡轮机下一小时的功率输出。图片由作者提供。

从上图中,我们注意到两件事。

首先,我没有绘制 IMAPA 的曲线,因为它与 ADIDA 给出的预测完全相同。

其次,简单指数平滑在预测下一个时间步时似乎做得非常好,因为它的曲线比其他模型更接近实际值。

为了验证这一点,让我们计算每个模型的 MAE,并创建一个条形图以识别最佳模型。

from sklearn.metrics import mean_absolute_error

mae_croston_h = mean_absolute_error(h_cv_df['y'], h_cv_df['CrostonOptimized'])
mae_adida_h = mean_absolute_error(h_cv_df['y'], h_cv_df['ADIDA'])
mae_tsb_h = mean_absolute_error(h_cv_df['y'], h_cv_df['TSB'])
mae_ses_h = mean_absolute_error(h_cv_df['y'], h_cv_df['SESOpt'])

y = [mae_croston_h, mae_adida_h, mae_tsb_h, mae_ses_h]
x = ['Croston', 'ADIDA', 'TSB', 'SES']

fig, ax = plt.subplots()

ax.bar(x, y, width=0.4)
ax.set_xlabel('Models')
ax.set_ylabel('MAE (kW)')
ax.set_xlabel('Models')
ax.set_ylim(0, 500)

for index, value in enumerate(y):
    plt.text(x=index, y=value + 5, s=str(round(value,2)), ha='center')

plt.tight_layout()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

每个模型在预测下一个小时时的 MAE。这里,SES 是最佳模型。图片由作者提供。

毫不意外,简单指数平滑是最佳模型,因为它获得了最低的 MAE。在这种情况下,我们的基线似乎在预测下一个时间步时表现最佳。

让我们看看模型在预测下一天时的表现。

预测下一天

为了预测下一天,Statforecast 对象保持不变。

现在,我们只需将预测期设置为 24 小时,并将交叉验证窗口移动 24 个时间步。这里,我们进行了五轮交叉验证。

d_cv_df = sf.cross_validation(
    df=df,
    h=24,
    step_size=24,
    n_windows=5
)

d_cv_df.index = np.arange(8639, 8759, 1)

然后,我们可以绘制预测值和实际值。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

预测接下来的 24 小时的功率输出。图片由作者提供。

在上图中,我们注意到我们的预测在整个预测期内保持平稳,这很正常,因为每个模型输出的是一个常数值。

我们还可以看到,当预测时间跨度较长时,简单指数平滑的表现迅速下降。显然,简单指数平滑对零值周期处理不好。

使用 MAE 评估每个模型会得到以下结果。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

每个模型在预测下一天时的 MAE。这里,Croston 是最佳模型。图片由作者提供。

从上图中,我们可以看到优化后的 Croston 方法是表现最佳的模型,获得了最低的 MAE。我们还发现,简单指数平滑在较长预测期的表现不如 Croston 和 TSB。

另外,请记住,由于我们增加了预测范围,误差也增加,这是可以预期的。我们预测的时间越长,离实际值就越远。

最后,让我们将预测范围设置为一周。

预测下周

为了预测下周,我们将预测范围设置为 168 个时间步长,因为一周有 168 小时,我们的数据是按小时记录的。

w_cv_df = sf.cross_validation(
    df=df,
    h=168,
    step_size=168,
    n_windows=2
)

w_cv_df.index = np.arange(8423, 8759, 1)

再次,我们可以绘制每个模型的预测图。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

预测下周的电力输出。图像由作者提供。

上图稍显平淡,因为我们可以清楚地看到我们的模型与实际值相距甚远。这是可以预期的,因为我们的预测范围相当长。

评估我们的模型得到了以下结果。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

预测下周每个模型的 MAE。再次强调,Croston 是最好的模型。图像由作者提供。

从上图来看,我们再次看到 Croston 的方法是最好的模型,因为它达到了最低的 MAE。

有趣的是,我们还注意到,与预测次日相比,尽管预测期是原来的七倍,MAE 并没有显著增加。

不过,在实践中,我怀疑预测一个常数值一周真的能帮助做决策或计划未来。

结论

我们已经看到,间歇性时间序列提出了有趣的预测挑战,因为传统模型处理零值期间的能力较差。

我们探索了不同的预测模型,如 Croston 方法、ADIDA、IMAPA 和 TSB,每种方法都提供了预测稀疏时间序列的新方法。

恭喜你看到最后,非常感谢你的阅读!希望你喜欢,并且学到了新的东西!

想掌握时间序列预测吗?那就查看Python 中的应用时间序列预测。这是唯一一个使用 Python 在 15 个引导的实际项目中实现统计、深度学习和最先进模型的课程。

干杯 🍻

支持我

喜欢我的工作吗?通过买杯咖啡来支持我,这是一种简单的方式来鼓励我,同时我也能享用一杯咖啡!如果你愿意,只需点击下面的按钮 👇

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

使用 Granger 因果关系进行预测:检查时间序列的虚假相关

原文:towardsdatascience.com/forecasting-with-granger-causality-checking-for-time-series-spurious-correlations-5faed62c3604

使用机器学习方法破解 Granger 因果关系测试

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 Marco Cerliani

·发表于 Towards Data Science ·6 分钟阅读·2023 年 4 月 6 日

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Phoenix Han的照片,来源于 Unsplash

在时间序列预测中,通常通过图形化数据进行检查是非常有帮助的。这有助于我们理解我们所分析现象的动态,并据此做出决策。尽管拥有一个色彩斑斓的时间序列图可能非常迷人,但它可能会导致不正确的结论。时间序列很棘手,因为无关事件往往会在视觉上看起来有关联

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

虚假相关的一个示例 [来源]

作为理性个体,我们可以轻易否定因被床单缠绕而死亡的人数人均奶酪消费量之间的任何关系。我们可以断言存在虚假的(虚假)相关,因为没有任何东西可以将这两个事件联系起来,即使我们在这两个领域都不是专家。

从事数据工作的人知道这些模式可能经常发生,尤其是在我们难以解释上下文和区分真实与虚假相关时。因此,开发能够帮助识别这些情况的方法是至关重要的。

用于检测虚假相关的最著名技术之一是 Granger 因果关系测试

Granger 因果关系建立在这样一种直觉上:如果信号 Y1 “Granger 引起” 另一个信号 Y2,那么 Y1 的滞后(即过去的观察)应包含有助于预测 Y2 的信息,以及 Y2 过去观察中包含的信息。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

可能的 Granger 因果关系示例 [图片由作者提供]

测试 Granger 因果关系并不意味着 Y1 必须是 Y2 的原因。这仅仅意味着 Y1 的过去值足够好,可以改善对 Y2 未来值的预测。由此,我们可能得出一个朴素的因果关系定义。

采用 Granger 因果关系检验意味着对基础数据有严格的假设(即平稳性和线性依赖),这些假设在现实世界应用中可能难以满足。因此,在本文中,我们提出了一种 Granger 因果关系检验的泛化方法,采用了简单的机器学习方法,并涉及预测算法的使用

实验设置

本文的范围内,我们模拟了两个不同的时间序列,这些序列是自回归过程的结果。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

模拟的 AR 过程 [图片由作者提供]

两个序列与其过去的某些时间步长存在相关性(自相关)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

AR 过程的自相关 [图片由作者提供]

时间序列表现出整体皮尔逊相关系数为 0.637,且在时间上保持离散的正相关关系。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

AR 过程的皮尔逊相关性 [图片由作者提供]

初看之下,这似乎表明我们面对的是两个具有正相关的事件。我们用皮尔逊相关系数来表示两个变量之间的相关性。这是测量变量之间线性关系的最常用统计量。如此常见,以至于人们常常错误地将其解释为因果关系。这可能是一个错误!皮尔逊相关仅涉及两个变量的均值和标准差。我们不能据此得出关于它们依赖关系的任何结论

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

皮尔逊相关公式 [图片由作者提供]

在我们模拟的场景中,正相关仅仅是数学结果,因为我们知道这两个序列仅在一个方向上有关联。更确切地说,Y1 的过去值与 Y2 的实际值线性相关(反之则不成立)。我们的目标是对此声明进行实际演示。

Granger 预测

以经典方式进行 Granger 因果关系检验,意味着验证时间序列(Y1)的过去值是否对另一时间序列(Y2)的当前值有统计学上显著的影响。这是通过在滞后序列值上运行线性模型来完成的。

检验的零假设是 Y1 的过去值对应的系数为零。如果 p 值低于特定阈值,我们将拒绝零假设。在这种情况下,Y1 不会 Granger 引起 Y2。

如果我们对预测模型的残差进行相同的检查会怎么样?

换句话说,我们验证了添加 Y1 的过去值是否能改善仅使用目标(Y2)滞后观察值的模型的性能

作为第一步,我们对 Y1 和 Y2 进行两个自回归模型的拟合,不添加额外的外生变量,并存储在测试数据上获得的预测结果。

forecaster = ForecastingCascade(
    RandomForestRegressor(30, random_state=42, n_jobs=-1),
    lags=lags,
    use_exog=False,
)

model_y1 = clone(forecaster).fit(None, df_train['y1'])
model_y2 = clone(forecaster).fit(None, df_train['y2'])

y1_pred = np.concatenate([
    model_y1.predict(
        [[0.]],
        last_y=df['y1'].iloc[:i]
    ) for i in range(len(df_train), len(df_train) + len(df_test))
])
y2_pred = np.concatenate([
    model_y2.predict(
        [[0.]],
        last_y=df['y2'].iloc[:i]
    ) for i in range(len(df_train), len(df_train) + len(df_test))
])

其次,我们重复相同的预测过程,但添加了滞后的外生变量(即在预测 Y1 时使用 Y2 的过去值加上 Y1 的过去值)。

forecaster = ForecastingCascade(
    make_pipeline(
        FunctionTransformer(
            lambda x: x[:,1:]  # remove current values of exog series
        ),
        RandomForestRegressor(30, random_state=42, n_jobs=-1)
    ),
    lags=lags,
    use_exog=True,
    exog_lags=lags,
)

model_y1y2 = clone(forecaster).fit(df_train[['y2']], df_train['y1'])
model_y2y1 = clone(forecaster).fit(df_train[['y1']], df_train['y2'])

y1y2_pred = np.concatenate([
    model_y1y2.predict(
        pd.DataFrame({'y2': [0.]}),
        last_y=df['y1'].iloc[:i],
        last_X=df[['y2']].iloc[:i]
    ) for i in range(len(df_train), len(df_train) + len(df_test))
])
y2y1_pred = np.concatenate([
    model_y2y1.predict(
        pd.DataFrame({'y1': [0.]}),
        last_y=df['y2'].iloc[:i],
        last_X=df[['y1']].iloc[:i]
    ) for i in range(len(df_train), len(df_train) + len(df_test))
])

在预测阶段结束时,我们存储了 4 种不同模型的预测结果(两个用于预测 Y1,另外两个用于预测 Y2)。现在是结果比较的时间。

对所有预测类型的样本级别计算平方残差。对相同预测目标的平方残差分布进行综合分析。我们使用标准的 Kolmogorov-Smirnov 检验来检查分布差异。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

平方残差分布的比较 [图片由作者提供]

对于 Y1 的预测在添加和不添加 Y2 特征的情况下似乎是一样的。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

平方残差分布的比较 [图片由作者提供]

相反,Y2 的预测在添加和不添加 Y1 特征的情况下有显著差异。这意味着 Y1 对预测 Y2 有正面影响,即 Y1 格兰杰导致 Y2(反之则不成立)。

总结

在这篇文章中,我们提出了一种替代标准格兰杰因果检验的方法,以验证时间序列领域中的因果动态。我们没有仅仅依赖于皮尔逊相关系数来得出数据结论。我们以经验的方式分析了可用事件的相互影响的可能性,识别出虚假的关系。所提出的方法易于使用且具有适应性,假设较少,适合用于任何时间序列分析过程。

查看我的 GitHub 仓库

保持联系: Linkedin

忘掉 SQLite,改用 DuckDB——然后感谢我

原文:towardsdatascience.com/forget-about-sqlite-use-duckdb-instead-and-thank-me-later-df76ee9bb777

DuckDB 及其 Python 集成介绍

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 Pol Marin

·发表于 Towards Data Science ·8 分钟阅读·2023 年 3 月 16 日

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片来源 Krzysztof NiewolnyUnsplash

我们程序员往往在需要在本地环境中使用嵌入式数据库时默认选择 SQLite。虽然大多数时候这工作得很好,但就像骑自行车旅行 100 公里:可能不是最佳选择。

介绍 DuckDB。

我第一次了解到 DuckDB 是在 2022 年 9 月,在格拉纳达的 PyCon 西班牙上。现在,经过 6 个月的使用,我已经离不开它了。我希望通过为我的程序员和数据相关专业人士提供对这个出色分析数据库系统的介绍来回馈社区。

在这篇文章中,我将讨论以下主要点:

  • DuckDB 简介:它是什么,为什么你应该使用它以及何时使用。

  • DuckDB 集成到 Python 中。

准备好!

如果你无法看到整个故事,考虑使用我的推荐链接以获得对所有 Medium 故事的无限访问:medium.com/@polmarin/membership

什么是 DuckDB?

如果你查看 DuckDB 的官网[1],你会在首页看到的第一件事是:DuckDB 是一个内嵌 SQL OLAP 数据库管理系统。

让我们尝试解读这句话,因为其中包含相关信息。

  • 内嵌 SQL 意味着 DuckDB 的功能在你的应用程序中运行,而不是在你的应用程序连接的外部进程中。换句话说:没有客户端发送指令,也没有服务器来读取和处理它们。SQLite 的工作方式相同,而 PostgreSQL、MySQL 等则不然。

  • OLAP 代表在线分析处理,微软将其定义为一种组织大型业务数据库并支持复杂分析的技术。它可以用于执行复杂的分析查询而不会对事务系统产生负面影响[2]。另一个 OLAP 数据库管理系统的例子是 Teradata。

所以基本上,如果你在寻找一个无服务器的数据分析数据库管理系统,DuckDB 是一个很好的选择。我强烈建议你查看 Dr. Mark Raasveldt 和 Dr. Hannes Mühleisen [3]— 两位最重要的 DuckDB 开发者 — 的出色同行评审论文,以了解 DuckDB 试图填补的空白。

此外,它是一个支持 SQL 的关系数据库管理系统(DBMS)。这就是为什么我们将它与其他具有相同特征的 DBMS(如 SQLite 或 PostgreSQL)进行比较的原因。

为什么选择 DuckDB?

我们现在知道 DuckDB 在数据库行业中的作用。但为什么我们应该选择它,而不是其他许多可能的选项呢?

在数据库管理系统中,没有一刀切的解决方案,DuckDB 也不例外。我们将讨论它的一些特性,以帮助你决定何时使用它或不使用它。

总而言之,它是一个高性能的工具。如他们的 GitHub 页面[4]所示:“它被设计为快速、可靠且易于使用。” 进一步了解…

  • 它是为了支持分析查询工作负载(OLAP)而创建的。他们的做法是通过向量化查询执行(面向列),而其他之前提到的 DBMS(SQLite、PostgreSQL…)则按顺序处理每一行。这就是为什么其性能会提高。

  • DuckDB 采用了 SQLite 最好的特性:简洁性。简洁的安装和嵌入式进程操作是 DuckDB 开发者在看到 SQLite 的成功后,为这个 DBMS 选择的特点。

    此外,DuckDB 没有外部依赖项,也不需要安装、更新或维护服务器软件。如前所述,它完全嵌入,这具有数据在数据库之间高效传输的额外优势。

  • 技术娴熟的创建者。他们是一个研究小组,创建它是为了开发一个稳定且成熟的数据库系统。这是通过密集而彻底的测试来实现的,测试套件目前包含了数百万个查询,改编自 SQLite、PostgreSQL 和 MonetDB 的测试套件。

  • 它是完整的。它支持 SQL 中的复杂查询,提供事务保证(你肯定听说过的 ACID 特性),支持二级索引以加快查询速度……而且,更重要的是,它与 Python 和 R 深度集成,以便进行高效的交互式数据分析。

    它还提供了 C、C++、Java 等语言的 API。

  • 免费且开源。再好不过了。

这些是官方优势。

但还有更多,我想强调一点:DuckDB 不一定要替代 Pandas。它们可以协同工作,如果你像我一样是 Pandas 的粉丝,你可以在 Pandas 中使用 DuckDB 进行高效的 SQL 操作。

这真是太棒了。

你可以在 DuckDB 的网站[1]上找到更完整的解释。

什么时候使用 DuckDB?

这确实取决于你的个人偏好,但让我们回到其共同创始人发布的论文[3](我强烈推荐你阅读,它只有 4 页,内容非常宝贵)。

他们解释说,嵌入式分析数据管理有着明显的需求。SQLite 是嵌入式的,但如果我们想用它进行全面的数据分析,它太慢了。他们继续说:“这种需求来自两个主要来源:交互式数据分析和‘边缘’计算。”

所以这是 DuckDB 的前两大用例:

  • 交互式数据分析。大多数数据专业人士现在在本地环境中使用 R 或 Python 库,如dplyrPandas来处理他们从数据库中检索的数据。DuckDB 提供了在本地开发中利用 SQL 效率的可能性,而不会影响性能。你可以在不放弃你喜欢的编程语言的情况下享受这些好处(稍后会详细介绍)。

  • 边缘计算。根据维基百科的定义,“边缘计算是一种分布式计算范式,将计算和数据存储更接近数据源。” [5] 使用嵌入式 DBMS,它可以更接近这一点!

DuckDB 可以在不同的环境中安装和使用:Python、R、Java、node.js、Julia、C++……在这里,我们将重点关注 Python,你很快会看到它的使用是多么简单。

使用 DuckDB 与 Python(入门)

打开你的终端并导航到所需的目录,因为我们马上就要开始了。创建一个新的虚拟环境——或者不创建——并安装 DuckDB:

pip install duckdb==0.7.1

如果你需要另一个版本,请删除或更新。

现在进入有趣的部分。为了使事情更有趣,我将使用我在 Kaggle 上找到的关于 Spotify 最流行歌曲的真实数据[6]。我将使用典型的 Jupyter Notebook 进行操作。

许可证: CC0: 公共领域

由于我们获得的数据是两个 CSV 文件——Features.csv 和 Streams.csv——,我们需要创建一个新数据库并将其加载:

import duckdb

# Create DB (embedded DBMS)
conn = duckdb.connect('spotiStats.duckdb')
c = conn.cursor()

# Create tables by importing the content from the CSVs
c.execute(
  "CREATE TABLE features AS SELECT * FROM read_csv_auto('Features.csv');"
)
c.execute(
  "CREATE TABLE streams AS SELECT * FROM read_csv_auto('Streams.csv');"
)

就这样,我们创建了一个全新的数据库,添加了两个新表,并用所有数据填充它们。仅用 4 行简单的代码(如果考虑到导入,则为 5 行)。很酷吧?

让我们展示一下流媒体表中的内容:

c.sql("SELECT * FROM streams")

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

所有时间流媒体前 100 首歌曲的可视化— 作者截图。

让我们开始进行一些分析任务。例如,我想知道前 100 首歌曲中有多少首是在 2000 年之前的。这是其中一种方法:

c.sql('''
SELECT * 
FROM streams 
WHERE regexp_extract("Release Date", '\d{2}$') > '23'
''')

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

所有时间流媒体前 100 首歌曲中的 2000 年之前的歌曲 — 作者截图。

我之前提到过,使用 DuckDB 和 Pandas 同时工作是多么简单。这里有一种使用 Pandas 做到相同的方式:

df = c.sql('SELECT * FROM streams').df()
df[df['Release Date'].apply(lambda x: x[-2:] > '23')]

我所做的只是将初始查询转换成 DataFrame,然后以 Pandas 的方式应用过滤器。结果是一样的,但它们的性能如何呢?

>>> %timeit df[df['Release Date'].apply(lambda x: x[-2:] > '23')]
434 µs ± 25.6 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

>>> %timeit c.sql('SELECT * FROM streams WHERE regexp_extract("Release Date", \'\d{2}$\') > \'23\'')
112 µs ± 25.3 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

你看到了吗?操作相当简单:我们只对一个 100 行的表应用了一个简单的过滤器。但如果我们将其与 DuckDB 实现进行比较,使用 Pandas 的执行时间几乎是其 4 倍。

想象一下,如果我们尝试一个更为详尽的分析操作……改进可能会非常巨大。

我认为再提供更多的示例意义不大,因为这将使 DuckDB 的介绍变成 SQL 入门。这并不是我想要的。

但请随意使用你可能拥有的任何数据集,并开始在 DuckDB 数据库上使用 SQL。你会很快看到它的好处。

为了结束这个简短的介绍,让我们将最后的结果(2000 年前的歌曲)导出为 parquet 文件——因为它们始终是比传统 CSV 更好的替代品。同样,这将是非常简单的:

c.execute('''
COPY (
    SELECT 
        * 
    FROM 
        streams 
    WHERE 
      regexp_extract("Release Date", '\d{2}$') > '23'
) 
TO 'old_songs.parquet' (FORMAT PARQUET);
''')

我所做的只是将之前的查询放在括号内,DuckDB 只会将查询结果复制到 old_songs.parquet 文件中。

瞧瞧。

结论

DuckDB 对我来说是一次生活的改变,我认为它也可以对很多人产生影响。

希望这篇文章既有趣又有信息量。它并不打算成为教程或指南,所以我没有详细讲解代码示例,但我相信已经有足够的信息来理解主要观点。

 **Thanks for reading the post!** 
            I really hope you enjoyed it and found it insightful.

          Follow me for more content like this one, it helps a lot!
                                  **@polmarin**

如果你想进一步支持我,请考虑通过下面的链接订阅 Medium 的会员:这不会花费你额外的钱,但将帮助我完成这个过程。非常感谢!

[## 使用我的推荐链接加入 Medium — Pol Marin

阅读 Pol Marin 的每一篇故事(以及 Medium 上其他成千上万的作者的故事)。你的会员费用直接支持 Pol……

medium.com](https://medium.com/@polmarin/membership?source=post_page-----df76ee9bb777--------------------------------)

资源

[1] DuckDB

[2] 在线分析处理 (OLAP) — Azure 架构中心

[3] Mark Raasveldt 和 Hannes Mühleisen. 2019. DuckDB: an Embeddable Analytical Database. In 2019 International Conference on Management of Data (SIGMOD ’19), June 30-July 5, 2019, Amsterdam, Netherlands. ACM, New York, NY, USA, 4 pages. doi.org/10.1145/3299869.3320212

[4] DuckDB — GitHub

[5] 边缘计算 — 维基百科

[6] 历史上最流行的歌曲 — Kaggle

ETL 测试 — 如何正确测试你的数据管道

原文:towardsdatascience.com/forget-about-the-new-data-trends-in-2023-d2756add3317?source=collection_archive---------0-----------------------#2023-01-06

忘掉 2023 年的新数据趋势吧!这个根本的数据工程挑战仍然没有解决。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 Vino Duraisamy

·

关注 发表在 Towards Data Science · 7 分钟阅读 · 2023 年 1 月 6 日

2023 年!ELT、反向 ETL、EtLT、数据网格、数据合同、FinOps 和现代数据栈等新数据范式(或流行词汇)已经进入主流数据对话。我们的数据团队仍在弄清楚哪些是炒作,哪些不是。

明天可能会有 10 种新范式,但一些数据工程中的根本挑战——如数据质量——仍然相关且尚未完全解决(我认为我们永远无法完全解决这个问题)。提高数据质量的第一步是对我们的数据管道进行严格测试。

在本文中,让我们探讨在有效测试数据管道时面临的挑战以及如何为您的组织建立一个全面的测试策略。

为什么实现数据质量很难?

在软件应用开发领域,提高软件质量意味着进行严格的测试。同样,在数据工程中,我们需要一个全面的测试策略,以确保生产中的数据质量。

大多数数据团队都面临紧迫的截止日期。因此,数据工程的文化使得我们最终构建的管道是在一周结束前提供数据,而不是融入长期有价值的最佳实践。

  • 在 ETL 测试中,我们通常需要比较来自不同源系统的大量数据(例如数百万条记录)。我们在比较经过复杂 SQL 查询或 Spark 作业处理后的转换数据。

  • 不是所有的数据工程师(及数据工程领导者)都有软件工程背景,也不都擅长软件工程开发原则和最佳实践。

  • 自动化测试套件和数据产品的自动化部署/发布仍未成为主流。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

来源:由作者创建

ETL 测试是一个以数据为中心的测试过程。为了有效地测试我们的管道,我们需要类似生产的数据(在体积、多样性和速度方面)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

来源:由作者创建

获得类似生产的数据很困难。以下是不同公司中的数据团队如何解决获取合适数据以测试数据管道的问题。

1. 模拟数据:

优点: 这种方法被我们所有数据工程师广泛使用,因为模拟数据的创建容易,而且有合成数据生成工具(如 Faker)可用。

缺点: 模拟数据在体积、多样性或速度方面无法反映生产数据。

2. 从生产数据中抽样到测试/开发环境:

优点: 复制部分生产数据比复制大量生产数据要容易。

缺点: 应使用正确的抽样策略来确保样本反映真实世界的生产数据。成功在样本生产数据上运行的测试可能在实际生产数据上失败,因为数据的体积和多样性无法保证。

3. 复制所有生产数据到测试环境:

优点: 提供真实世界生产数据用于测试。

缺点: 如果生产数据包含个人身份信息(PII),可能会导致数据隐私违规。如果生产数据不断变化,则测试/开发环境中的生产数据副本将变得陈旧,需要不断更新。体积和多样性有保证,但速度没有保证。

4. 复制匿名化的生产数据到测试环境:

优点: 提供真实世界生产数据用于测试。符合所有数据隐私法规。

缺点:再次强调,生产数据的持续变化意味着测试环境中的数据变得过时,并需要频繁刷新。每次从生产环境中复制数据时都需要进行 PII 匿名化。每次手动执行匿名化步骤并维护长期运行的测试数据环境容易出错且资源消耗大。

5. 使用数据版本控制工具将生产数据镜像到开发/测试环境:

优点:可用的真实生产数据。通过类似 Git 的 API 提供的自动化短期测试环境。

缺点:将一个新工具(如lakeFS)添加到现有的数据堆栈中。

注意:如果你对 ETL 测试中的数据版本控制工具感兴趣,这里有一个快速指南,供你参考。

关于如何使用 lakeFS 创建不同数据环境以进行 ETL 测试的视频教程。来源:作者创建。

好了,假设你拥有正确的数据。接下来呢?

  • 需要运行一系列全面的测试,以确保数据湖或数据仓库中数据的质量和可靠性。

  • 你可以使用数据质量测试工具(如 Great Expectations、soda.io 等)进行这些测试,也可以构建一个内部测试套件。无论如何!

  • 根据项目、数据集和业务的不同,需要执行不同类型的测试。然而,这里有一个由Irene整理的不同数据质量维度的基本测试检查表。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

来源:www.scnsoft.com/blog/guide-to-data-quality-management

1. 一致性:

在上述备忘单的基础上,一致性检查应包括比较源系统和目标系统。在某些行业中,不一致的数据是允许的(是的!),并且误差的变化应低于指定阈值。因为不同的数据系统之间可能存在不一致,如果它们是异步更新的(得益于微服务和消息队列)。

例如,当你比较源和目标中最后一小时的客户订单数量时,结果可能会有所不同。但当你运行汇总测试(即一个月的订单数量)时,数据将会趋于一致。

2. 准确性:

你的检查应包括数据验证和领域值检查。例如,出生日期列不能有超过 200 年的值。

根据你的领域,数据应在特定范围内。一些业务 KPI 不能有特定值。例如,一个名为点击率的列不能有大于 1.0 的值,等等。

3. 完整性:

应包括记录数、列数、每列缺失值的百分比、空值的百分比、范围检查(min_value、max_value)以及基本统计数据,如均值、中位数、方差和数据分布(特定列中值的频率)等检查。

再次,根据业务领域的不同,你可以设定一个错误的阈值。在制药和金融领域,由于合规要求,数据团队力求 100%的数据验证和 0%的错误差异。

4. 数据可审计性:

比较源系统和数据系统的审计日志,确保每个转换或数据移动步骤都被捕捉并匹配。

数据血统工具支持数据审计。

5. 有序性:

这涉及到对数据和列格式检查的测试。列的数据类型、缺失列的百分比、列名不匹配的百分比、数据格式不匹配的百分比(一个来源中的日期可能是MMDDYYYY格式,而另一个来源中的日期可能是DDMMYYYY格式)。

6. 唯一性:

如名称所示,检查哪些列应具有唯一值、重复条目的百分比等。

7. 及时性:

延迟到达的数据是我们面临的一个常见挑战。这种情况发生在源系统生成的数据点在延迟后到达目标区域。例如,昨天的数据可能会进入今天的日期分区,并与今天的数据点一起处理。这会导致意外的数据错误。

因此,验证数据中的created_timestamp列与date_partition的一致性也非常关键。

1. 白盒测试:

上述七种测试类型属于白盒测试。另一种类型是对复杂数据转换进行单元测试。这是为了验证 KPI 定义和其他转换是否符合预期。

2. 黑盒测试:

数据管道包含许多动态部分——从多个数据源、复杂的数据转换到下游的并发数据消费者。因此,仅测试转换是不够的。需要对 ETL 管道进行端到端测试,以确保管道按预期工作。

3. 回归测试:

假设管道的某一部分发生了变化,必须确保其他部分由于这次变化没有出现回归错误。

这就是自动化 ETL 测试重要的地方。也就是说,在每次更改后,需要运行一套测试(有时也称为持续集成测试)。只有当测试套件成功运行时,才能将更改推送到生产环境中。

你可以使用像lakeFS 这样的工具来运行自动化测试,并实现数据湖的 CI/CD

[## 数据湖的 CI/CD

数据管道将处理后的数据从数据湖传送到下游的消费者,如业务仪表盘和机器…

docs.lakefs.io

4. 性能测试:

除了确保数据质量外,对 ETL 管道进行负载测试也是提高数据产品发布可靠性所必需的。

因此,分析 ETL 任务的运行时间和任务的执行顺序,以识别瓶颈。通常,当数据量增加时,会导致管道变慢。通过监控运行时间、优化分布式计算作业和调整硬件需求,可以解决这个问题。

这些是需要运行的全面测试清单。然而,我们中的大多数人在工作中只运行其中的一些。如果你是数据工程师,你们团队的 ETL 测试策略是怎样的?

感谢阅读!

如果你喜欢我的工作并想支持我…

  1. 支持我的最佳方式是关注我在Medium上的账号。

  2. 有关数据工程最佳实践和 Python 初学者的技巧,请在LinkedIn上关注我。

  3. 请随意点赞,以便我知道这篇文章对你有多大帮助。

忘掉 RAG,未来是 RAG-Fusion

原文:towardsdatascience.com/forget-rag-the-future-is-rag-fusion-1147298d8ad1

搜索的下一前沿:检索增强生成遇上互惠排名融合和生成查询

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 Adrian H. Raudaschl

·发表于 Towards Data Science ·阅读时间 10 分钟·2023 年 10 月 6 日

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

RAG 融合的奇妙世界。图示由作者提供。

探索搜索技术近十年后,我可以诚实地说,没有什么比检索增强生成(RAG)的崛起更具颠覆性。这一系统通过使用生成 AI 的向量搜索来基于可信的数据生成直接答案,正在彻底改变搜索和信息检索。

在我的搜索项目中,实验使用 RAG 让我考虑了其潜在的增强功能;我相信 RAG 仍然过于有限,无法满足用户的需求,需要升级。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我的个人搜索系统(Project Ramble),其中我在 2022 年将我的 Obsidian 笔记与 GPT-3 结合的向量搜索连接起来。图像由作者提供。

别误解我的意思,RAG 非常出色,绝对是信息检索技术向正确方向迈进的一步。我自 2021 年 GPT-2 出现以来一直在使用 RAG,它在寻找有价值的信息时显著提高了我的生产力。RAG 有许多优点

  • 向量搜索融合: RAG 通过将向量搜索功能与生成模型结合,介绍了一种新颖的范式。这种融合使得从大型语言模型(LLM)生成更丰富、更具上下文感知的输出成为可能。

  • 减少幻觉: RAG 显著减少了 LLM 的幻觉倾向,使生成的文本更加基于数据。

  • 个人和职业效用: 从个人应用如筛选笔记到更专业的集成,RAG 展示了提升生产力和内容质量的多功能性,同时基于可信的数据源。

然而,我发现 RAG 有越来越多的局限性

  • 当前搜索技术的限制: RAG 受到与我们检索基础的词汇和向量搜索技术相同的限制。

  • 人工搜索的低效: 人们在将他们想要的内容输入搜索系统时表现不佳,如拼写错误、模糊查询或词汇有限,这往往导致错过那些隐藏在明显顶级搜索结果之外的大量信息。虽然 RAG 提供了帮助,但并未完全解决这个问题。

  • 搜索的过度简化: 我们现有的搜索范式将查询线性映射到答案,缺乏理解人类查询多维特性的深度。这种线性模型通常无法捕捉更复杂用户询问的细微差别和背景,导致结果相关性较低。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

2023 年 RAG(检索增强生成)的搜索激增。截图由作者提供,来源于 2023 年 9 月 Google Trends。

那么,我们能做些什么来解决这些问题呢?我们需要一个不仅能检索我们所问内容,还能理解我们查询背后细微差别的系统,而不必依赖越来越高级的 LLM。认识到这些挑战,并受到可能性的启发,我开发了一个更精细的解决方案:RAG-Fusion。

为什么选择 RAG-Fusion?

  • 填补空白: 通过生成多个用户查询并重新排名结果,解决 RAG 固有的局限性。

  • 增强搜索: 利用互惠排序融合和自定义向量分数加权,以获取全面、准确的结果。

RAG-Fusion 致力于弥合用户明确询问的内容与他们实际意图之间的差距,逐步揭示那些通常隐藏的变革性知识。

多年前开始这段旅程时,我遗憾未能分享那些初期实验。但现在是时候弥补了。让我们深入探讨 RAG-Fusion 的技术细节。

深入探讨 RAG-Fusion 的机制

工具和技术栈

供那些只想查看代码并直接玩 RAG-Fusion 的人,请查看这里的 GitHub 仓库

RAG Fusion 的基础三要素与 RAG 相似,涉及相同的三项关键技术:

  • 一种通用编程语言,通常是 Python。

  • 一个专用的向量搜索数据库,如 Elasticsearch 或 Pinecone,指导文档检索。

  • 一个强大的大型语言模型,如 ChatGPT,用于生成文本。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

RAG-Fusion 工作机制的示意图。图像由作者提供。

然而,与 RAG 不同,RAG-Fusion 通过几个额外步骤——查询生成和结果的重新排序,来区分自己。

RAG-Fusion 的工作流程:

  1. 查询复制的新方法: 通过 LLM 将用户的查询转换为类似但又不同的查询。

  2. 向量搜索的释放: 执行对原始查询及其新生成的查询兄弟的向量搜索。

  3. 智能重新排序: 使用互惠排名融合方法汇总和优化所有结果。

  4. 优雅的结局: 将精心挑选的结果与新的查询配对,引导大型语言模型生成考虑所有查询和重新排序结果列表的输出。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

RAG-Fusion 代码 示例。图像来源于作者。

让我们更详细地了解这些步骤。

多查询生成

为什么使用多个查询?

在传统的搜索系统中,用户通常输入一个查询来寻找信息。虽然这种方法简单直接,但它也有其局限性。单一的查询可能无法捕捉用户感兴趣的全部范围,或者可能过于狭窄,导致结果不全面。这时,从不同角度生成多个查询就显得尤为重要。

技术实施(提示工程)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

多查询生成的流程图:利用提示工程和自然语言模型来扩展搜索视野并提升结果质量。图像来源于作者。

使用提示工程来生成多个不仅与原始查询相似而且提供不同角度或视角的查询至关重要。

工作原理如下:

  1. 调用语言模型: 这个方法调用了一个语言模型(在这里是 chatGPT)。这种方法需要一组特定的指令,通常被称为“系统消息”,以指导模型。例如,这里的系统消息指示模型作为“AI 助手”进行操作。

  2. 自然语言查询: 模型根据原始查询生成多个查询。

  3. 多样性和覆盖范围: 这些查询不仅仅是随机变体。它们经过精心生成,以提供原始问题的不同视角。例如,如果原始查询是关于“气候变化的影响”,生成的查询可能包括“气候变化的经济后果”、“气候变化与公共健康”等角度。

这种方法确保了搜索过程考虑了更广泛的信息,从而提高了生成总结的质量和深度。

互惠排名融合(RRF)

为什么使用 RRF?

互惠排名融合(RRF)是一种将多个搜索结果列表的排名结合起来以生成单一统一排名的技术。与滑铁卢大学(加拿大)和 Google 合作开发,RRF 的作者表示,“比任何单独系统产生的结果更好,比标准的重新排序方法更好”。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

RRF 算法,其中 k=60。图像来自 — 互惠排名融合优于 Condorcet 和单独的排名学习方法

通过结合来自不同查询的排名,我们增加了最相关文档出现在最终列表顶部的机会。RRF 特别有效,因为它不依赖于搜索引擎分配的绝对分数,而是依赖于相对排名,使其特别适合结合来自可能具有不同规模或分数分布的查询的结果。

通常,RRF 已被用于混合词汇和向量结果。尽管这种方法可以弥补向量搜索在查找特定术语(如首字母缩略词)时的特异性不足,但我对结果并不满意,因为结果往往更像是多个结果集的拼凑,因为相同的查询很少在词汇和向量搜索中得到相同的结果。

可以把 RRF 想象成那个在做决定前坚持听取每个人意见的人。只不过在这种情况下,它并不令人烦恼,而是有帮助的。更多的意见更好——在这种情况下,更准确。

技术实施

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

互惠排序融合位置重新排序系统。图片来源于作者。

函数 reciprocal_rank_fusion 接受一个搜索结果字典,每个键是一个查询,相应的值是按其与该查询的相关性排序的文档 ID 列表。然后,RRF 算法基于文档在不同列表中的排名计算一个新的分数,并对其进行排序,以创建最终的重新排名列表。

在计算融合分数后,该函数按这些分数的降序对文档进行排序,以获得最终的重新排名列表,然后返回。

生成输出

用户意图保留

使用多个查询的挑战之一是可能会稀释用户的原始意图。为了缓解这一点,我们指示模型在提示工程中给予原始查询更多权重。

技术实施

最后,重新排名的文档和所有查询被输入到一个 LLM 提示中,以典型的 RAG 方式生成输出,例如请求回应或摘要。

通过层叠这些技术和方法,RAG Fusion 提供了一种强大且细致的文本生成方法。它利用搜索技术和生成 AI 的最佳优势,产生高质量、可靠的输出。

RAG-Fusion 的优缺点

优势

1. 优越的源材料质量

使用 RAG Fusion 时,你的搜索深度不仅仅是‘增强’了——它被放大了。重新排名的相关文档列表意味着你不仅仅是在表面获取信息,而是深入到各种观点的海洋中。结构化的输出更易读,感觉直观上更值得信赖,这在一个对 AI 生成内容持怀疑态度的世界中至关重要。

2. 增强的用户意图对齐

从根本上说,RAG Fusion 设计为一种富有同理心的人工智能,它能够揭示用户努力表达但可能无法清晰表达的内容。利用多查询策略捕捉用户信息需求的多方面表现,从而提供全面的输出,与用户意图产生共鸣。

3. 结构化、深刻的输出

通过从多样化的来源汲取信息,模型可以提供组织良好且深刻的回答,预见后续问题并预先解决它们。

4. 自动更正用户查询

系统不仅能够解读,还能优化用户查询。通过生成多个查询变体,RAG Fusion 执行隐式的拼写和语法检查,从而提高搜索结果的准确性。

5. 处理复杂查询

人类语言在表达复杂或专业思想时常常会有所欠缺。系统作为语言催化剂,生成可能包含所需术语或专有名词的变体,以获得更具针对性和相关性的搜索结果。它还可以将更长、更复杂的查询拆解成更小、更易处理的部分,用于向量搜索。

6. 搜索中的意外发现

考虑“未知的未知”——你不知道自己需要的信息,直到你遇到它。RAG Fusion 允许这种意外发现。通过采用更广泛的查询范围,系统增加了发现信息的可能性,虽然这些信息并非明确寻求,但会成为用户的灵光一现。这使得 RAG Fusion 与其他传统搜索模型有所不同。

挑战

1. 过于冗长的风险

RAG-Fusion 的深度有时会导致信息泛滥。输出可能详细到让人不堪重负。可以把 RAG-Fusion 想象成那个喜欢过度解释的朋友——信息丰富,但有时你可能希望他们直接切入重点。

2. 平衡上下文窗口

包括多查询输入和多样化文档集可能会对语言模型的上下文窗口造成压力。想象一个舞台上挤满了演员,使得跟随剧情变得困难。对于上下文约束严格的模型,这可能导致输出不连贯甚至被截断。

道德与用户体验考量

大权在握带来大责任。使用 RAG Fusion 的强大能力来操控用户查询以改进结果,感觉像是跨越了一些道德灰色地带。平衡改善搜索结果与用户意图的完整性至关重要,我有一些你在实施此解决方案时应考虑的想法:

道德问题:

  • 用户自主性: 操控用户查询有时可能偏离原意。必须考虑我们将多少控制权交给 AI,以及付出的代价。

  • 透明度: 这不仅仅是关于更好的结果;用户应当知道他们的查询是否以及如何被调整。这种透明度对维持信任和尊重用户意图至关重要。

用户体验(UX)提升:

  • 保留原始查询: RAG 融合优先考虑最初的用户查询,确保其在生成过程中的重要性。这是防止误解的一种保护措施。

  • 过程可见性: 显示生成的查询和最终结果可以让用户透明地看到搜索的范围和深度。这有助于建立信任和理解。

UX/UI 实施技巧:

  • 用户控制: 提供用户一个选项来切换 RAG 融合,使他们可以在手动控制和增强 AI 辅助之间进行选择。

  • 指导与清晰度: 一个关于 RAG 融合工作原理的工具提示或简要说明可以帮助设定明确的用户期望。

如果要概括 RAG 融合的价值,那就是:它使我们更接近于 AI 本应做到的目标——增强人类潜力。

RAG 融合不仅仅是一个进步;它是对所有创新者的号召。它促使我们超越传统框架,重新构想“搜索”的全景。

对于搜索领域的从业者,我提出一个挑战:让我们不仅仅创建搜索系统,而是设计查询的解读者。

希望 RAG-Fusion 能激励你与我一起接受这个挑战。

深入了解GitHub 仓库,亲自动手实践代码,加入这场革命。

你必须从客户体验开始,然后逆向思考技术。—— 史蒂夫·乔布斯

参考文献

  • 如果你想深入了解这个话题,我强烈推荐阅读 Trey Grainger、Doug Turnbull 和 Max Irwin 合著的《AI-Powered Search》。

计算机视觉中的前向映射和后向映射

原文:towardsdatascience.com/forward-and-backward-mapping-for-computer-vision-833436e2472

前向映射和后向映射在图像变换中的应用

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 哈维尔·马丁内斯·奥赫达

·发表于Towards Data Science ·阅读时间 8 分钟·2023 年 5 月 25 日

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

照片由Vadim Bogulov拍摄,来源于Unsplash

如果你想在没有 Premium Medium 账户的情况下阅读本文,可以通过这个好友链接访问 😃

www.learnml.wiki/forward-and-backward-mapping-for-computer-vision/

本文将介绍和解释两种图像扭曲算法:前向映射后向映射。除了在理论层面介绍这些算法之外,还将它们应用于实际图像,以查看每种算法的结果和能力。

为了充分理解本文解释的内容,需要熟悉 2D 变换矩阵,这些内容在上一篇文章中进行了介绍和解释。

[## 2D 矩阵变换在计算机视觉中的应用

通过变换矩阵进行计算机视觉中的缩放、旋转和平移

medium.com](https://medium.com/@JavierMtz5/2d-matrix-transformations-for-computer-vision-80b4a4f2120f?source=post_page-----833436e2472--------------------------------)

介绍

如前一篇文章所示,对图像应用变换的方法是遍历图像的每个像素,并对每个像素单独应用变换。然而,在某些用例中,变换不能直接应用,例如,某些像素的新位置可能超出了图像范围。另一个可能的问题是新图像可能会有空白像素(白条),因为在变换后很难将原始图像的所有像素映射到新图像的所有像素。

为了避免这些问题,本文将介绍的两个算法,前向映射后向映射,采用了不同的技术来正确转换图像。

前向映射

前向映射过程包括在引言和上一篇文章中讨论的简单图像变换过程:它遍历图像的所有像素,并对每个像素单独应用相应的变换。然而,必须考虑到那些变换后像素的新位置超出图像范围的情况,如下例所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

转换后的图像像素超出了原始图像的范围。图像由作者提供

要执行前向映射过程,首先定义一个函数,该函数以像素的原始坐标作为参数。这个函数会对原始像素坐标应用转换,并返回转换后的新坐标。以下代码示例展示了旋转变换的函数。

def apply_transformation(original_x: int, original_y: int) -> Tuple[int, int]:
    # Define the rotation matrix   
    rotate_transformation = np.array([[np.cos(np.pi/4), -np.sin(np.pi/4), 0],
                                      [np.sin(np.pi/4),  np.cos(np.pi/4), 0],
                                      [0, 0, 1]])
    # Apply transformation after setting homogenous coordinate to 1 for the original vector.
    new_coordinates = rotate_transformation @ np.array([original_x, original_y, 1]).T
    # Round the new coordinates to the nearest pixel   
    return int(np.rint(new_coordinates[0])), int(np.rint(new_coordinates[1]))

一旦你拥有这个函数,你只需遍历图像的每个像素,应用变换,并检查新像素坐标是否在原始图像的范围内。如果新坐标在范围内,新图像的新坐标上的像素将采用原始图像中原始像素的值。如果超出图像范围,该像素将被忽略。

def forward_mapping(original_image: np.ndarray) -> np.ndarray:
    # Create the new image with same shape as the original one
    new_image = np.zeros_like(original_image)
    for original_y in range(original_image.shape[1]):
        for original_x in range(original_image.shape[0]):
            # Apply rotation on the original pixel's coordinates
            new_x, new_y = apply_transformation(original_x, original_y)
            # Check if new coordinates fall inside the image's domain
            if 0 <= new_y < new_image.shape[1] and 0 <= new_x < new_image.shape[0]:
                new_image[new_x, new_y, :] = original_image[original_x, original_y, :]

    return new_image

旋转变换应用前向映射的结果可以在下图中看到,左侧是原始图像,右侧是转换后的图像。需要注意的是,对于这张图像,坐标原点在左上角,因此图像围绕该点逆时针旋转。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

应用前向映射的结果。左图摘自 MNIST 数据集 [1]。完整图像由作者提供

关于变换结果,可以看到变换后的图像不像原始图像那样有完全黑色的背景,而是有许多白色条纹。正如引言中提到的,这种情况发生是因为原始图像的像素并不总是映射到新图像的所有像素上。由于新坐标是通过四舍五入到最近的像素计算的,这导致许多中间像素没有获得值。在这种情况下,由于新图像初始化时所有像素为空,因此在变换过程中没有赋值的像素将保持为空,生成了变换图像中的白色条纹。

此外,还应注意另一个显著问题:重叠。当原始图像的两个像素被变换到新图像的同一像素时,就会出现这个问题。对于本文使用的代码,如果有两个原始图像的像素映射到新图像的同一像素,新像素将取最后一个已变换的原始像素的值,覆盖第一个已设置的值。

反向映射

反向映射算法产生的原因是需要消除由于变换而在图像中生成的白色条纹以及可能的重叠。正如前面所提到的,这些条纹出现的原因是由于在前向映射过程中计算新坐标时四舍五入的缘故,导致不是所有的变换图像像素都有值,而重叠发生在原始图像的两个或多个像素映射到新图像的同一像素时。

这个算法背后的逻辑很简单:不是将原始图像的每个像素转换到新图像中的新坐标(前向),而是将新图像中的所有像素逆向转换到原始图像的像素(反向)。这样,新图像中就不会有没有值的像素,因为它们都会采用原始图像中单个像素的值,从而解决了两个问题。

幸运的是,使用变换矩阵对像素坐标进行的变换可以通过应用逆变换矩阵来撤销。变换矩阵的这个属性以及其证明可以在下图中看到。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

使用逆变换矩阵的变换及证明。作者提供的图像

考虑到这一属性,算法的组成包括对新图像的每个像素进行迭代,并对每个像素的坐标应用逆变换,以知道它们需要从原始图像的哪个像素获取值。

def apply_inverse_transformation(new_x: int, new_y: int) -> Tuple[int, int]:
    # Define the inverse rotation matrix
    rotate_transformation = np.array([[np.cos(np.pi/4), -np.sin(np.pi/4), 0],
                                      [np.sin(np.pi/4),  np.cos(np.pi/4), 0],
                                      [0, 0, 1]])
    inverse_rotate_transformation = np.linalg.inv(rotate_transformation)

    # Apply transformation after setting homogenous coordinate to 1 for the position vector.
    original_coordinates = inverse_rotate_transformation @ np.array([new_x, new_y, 1]).T
    # Round the original coordinates to the nearest pixel
    return int(np.rint(original_coordinates[0])), int(np.rint(original_coordinates[1]))

注意,apply_inverse_transformation() 函数接受新图像中的坐标作为输入,并返回原始图像中的坐标,而不是像正向映射那样接受原始坐标并返回新坐标。

def backward_mapping(original_image: np.ndarray) -> np.ndarray:
    # Create the new image with same shape as the original one
    new_image = np.zeros_like(original_image)
    for new_y in range(new_image.shape[1]):
        for new_x in range(new_image.shape[0]):
            # Apply inverse rotation on the new pixel's coordinates
            original_x, original_y = apply_inverse_transformation(new_x, new_y)
            # Check if original coordinates fall inside the image's domain
            if 0 <= original_y < original_image.shape[1] and 0 <= original_x < original_image.shape[0]:
                new_image[new_x, new_y, :] = original_image[original_x, original_y, :]

    return new_image

应用反向映射的旋转变换结果可以在下图中看到,左侧是原始图像,右侧是变换后的图像。如前所述,图像围绕坐标原点旋转,坐标原点位于左上角。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

反向映射的应用结果。左侧图像摘自 MNIST 数据集 [1]。完整图像由作者提供

在图像中你可以看到,应用正向映射时出现的那些白色条纹,在应用反向映射时都消失了。实际上,你可以看到变换后的图像质量相当好(我们必须考虑到原始图像的质量不是很高),因此我们可以认为,在出现白色条纹的情况下,反向映射算法明显优于正向映射。

结论

正向映射是一个简单易实现且易于理解的算法,因为它直接将原始图像的每个像素转换到新图像。然而,该算法存在重叠问题以及留下一些像素没有值的问题,这些问题会显著降低变换图像的质量。反向映射算法,其实现与正向映射一样简单,结果要好得多,并且解决了这两个问题,因为它为新图像的所有像素提供了一个唯一的值。

关于算法的执行时间,两者具有相同的复杂度,因此一般来说,使用反向映射算法通常是一个更好的选择,因为它的结果更佳。在理想情况下,负责对每个像素应用个体变换的函数(在本文中称为apply_transformation()apply_inverse_transformation())不会构造变换矩阵,而是将其作为参数传入。这将节省正向映射算法构建变换矩阵所需的执行时间,同时也节省反向映射算法构建和反转矩阵的时间。

总之,反向映射算法相比于正向映射算法取得了非常好的结果,两者的执行时间几乎相同。然而,需要注意的是,两种算法都需要较长时间来处理高分辨率图像,尽管如此,它们仍然非常有用,为构建其他更强大的变换算法奠定了基础。

数据

本文中使用的图像摘自 MNIST 数据集 [1]。该数据集在创作共用署名-相同方式共享 3.0 许可协议下提供。

参考资料

[1] yann.lecun.com/exdb/mnist/

神经网络中的前向传播与反向传播

原文:towardsdatascience.com/forward-pass-backpropagation-neural-networks-101-3a75996ada3b

解释神经网络如何通过手动和代码中的 PyTorch 进行“训练”和“学习”数据模式

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 Egor Howell

·发表于 Towards Data Science ·10 分钟阅读·2023 年 11 月 4 日

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

神经网络图标由 juicy_fish 创建 — Flaticon. www.flaticon.com/free-icons/neural-network.

背景

在我过去的两篇文章中,我们探讨了神经网络从单一的 感知机到大型互联的 (多层感知机 (MLP) ) 非线性优化引擎的起源。如果你对感知机、MLP 和激活函数不熟悉,我强烈建议你查看我之前的帖子,因为我们在这篇文章中将讨论很多:

[## 介绍,感知机与架构:神经网络 101

神经网络及其构建块的介绍

levelup.gitconnected.com](https://levelup.gitconnected.com/intro-perceptron-architecture-neural-networks-101-2a487062810c?source=post_page-----3a75996ada3b--------------------------------) ## 激活函数与非线性:神经网络 101

解释为什么神经网络可以学习(几乎)任何事物

towardsdatascience.com

现在是时候理解这些神经网络如何“训练”和“学习”你传递给它的数据中的模式了。有两个关键组件:前向传播反向传播。让我们深入了解吧!

架构

让我们快速回顾一下神经网络的一般结构:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

一个基本的两层隐藏的多层感知器。图示由作者提供。

每个隐藏神经元执行以下过程:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

每个神经元内部执行的过程。图示由作者提供。

  • 输入: 这些是我们数据的特征。

  • 权重: 我们乘以输入的一些系数。算法的目标是找到最优的权重。

  • 线性加权和: 将输入和权重的乘积加起来,并添加一个偏置/偏移项, b*。

  • 隐藏层: 这是存储多个神经元以学习数据模式的地方。上标指的是层,下标指的是该层中的神经元/感知器。

  • 边缘/箭头: 这些是网络的权重,从相应的输入中获取,无论是特征还是隐藏层输出。我已经省略它们以使图表更简洁。

  • ReLU 激活函数: 最流行的 激活函数 因为它计算效率高且直观。

前向传播

概述

训练神经网络的第一部分是让它生成预测。这被称为 前向传播,即数据从第一层经过所有神经元到最后一层(也称为输出层)。

对于本文,我们将手动进行前向传播。实际上,我们会使用像 PyTorchTensorFlow*** 的包。但这将帮助我们更好地理解过程。

示例神经网络

我们将执行前向传播的神经网络如下所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

简单的神经网络。图示由作者提供。

如你所见,使用两个输入、隐藏层中的两个神经元(具有 ReLU 激活函数)和一个预测(输出层)非常简单。

权重和偏置

现在我们为这个简单的网络创建一些任意的权重、偏置和输入:

输入值: [0.9, 1.0]

目标/真实值: [2.0]

输入到隐藏层的权重,W_1:

  • 神经元 1: W_{1,1} = [0.2, 0.3]

  • 神经元 2: W_{1,2} = [0.4, 0.5]

隐藏层偏置,b_1: [0.1, 0.2]

隐藏到输出层的权重, W_2: [0.5, 0.6]

输出层偏置,b_2: [0.4]

需要注意的是,在这种情况下我随机生成了初始权重和偏置。这并不是坏事,你可以通过完全随机的初始化获得不错的结果。然而,还有更复杂的方法:

  • Xavier: 适用于 sigmoid tanh 激活函数。它从均匀分布中生成随机权重,利用该节点的输入数量来设置分布范围。

  • He: 适用于 ReLU 激活函数。它从正态分布中生成随机权重,利用该节点的输入数量来设置标准差。

如果你想了解更多关于这些初始化方法的信息,请查看上面列表中的链接。

关于权重初始化还有一个重要的注意事项是确保它们不同,以便我们‘打破对称性。’ 如果同一层的神经元以相同的权重开始,它们很可能会被完全相同地更新。因此,网络将不会收敛,无法学习任何东西。

第一次前向传播

使用上面列出的数据,我们现在可以进行第一次前向传播!结果如下:

从输入到隐藏层的线性加权和,z¹_{1}z¹_{2},是:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

由作者在 LaTeX 中生成的方程。

记住,上标表示层,下标表示该层中的神经元。第一层被认为是紧接着输入层的那一层,因为输入层不进行任何计算。因此,在我们的情况下,我们有一个 2 层的网络。

在这里,我们利用了 点积 来简化和压缩计算。 现在,我们可以在隐藏层中执行 ReLU 激活函数,a¹_{1,1}a¹_{1,2}

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

由作者在 LaTeX 中生成的方程。

我们需要做的最后一步是生成输出, z²_{1},这没有关联的激活函数:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

由作者在 LaTeX 中生成的方程。

哇,我们刚刚完成了第一次前向传播!

注意:我通过将权重写为向量/矩阵来简化表达。这是文献中常见的做法,以使工作流程更加整洁。

前向传播也如下图所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

简单神经网络及其权重、偏置和输出。图由作者提供。

反向传播算法

概述

完成正向传播后,我们现在可以开始更新权重和偏置,以最小化网络预测的误差。权重和偏置的更新是通过 反向传播 算法实现的。

计算图、链式法则和梯度下降

现在,让我们理解一下这个算法的直观意义。反向传播旨在获得每个权重和偏置对误差(损失)的偏导数。然后使用 梯度下降 更新每个参数,以最小化由每个参数引起的误差(损失)。

对,这在纸面上可能有意义,但我理解它仍然可能显得有些任意。我想通过一个真正的“简单”示例来深入了解 计算图

考虑以下函数:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

由作者在 LaTeX 中生成的方程。

我们可以将其绘制为计算图,这只是另一种可视化计算的方法:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

计算图示例。图示由作者提供。

基本上这是一个计算 f(x,y,z) 的流程图。我也表达了 p=x-y。现在我们来插入一些数字:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

带有数字的计算图示例。图示由作者提供。

这些看起来到目前为止都很好且直观!

我们计算 f(x,y,z) 最小值的方法是使用微积分。特别是,我们需要知道 f(x,y,z) 对其所有三个变量 x, y,z 的偏导数。

我们可以开始计算 p=x-yf=pz 的偏导数:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

由作者在 LaTeX 中生成的方程。

但是,我们该如何进行呢?

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

由作者在 LaTeX 中生成的方程。

好吧,我们使用 链式法则! 这是一个 x 的示例:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

由作者在 LaTeX 中生成的方程。

通过组合不同的偏导数,我们可以得到我们期望的表达式。因此,对于上述示例:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

由作者在 LaTeX 中生成的方程。

输出的梯度 fx 的梯度是 z。这很有意义,因为 z 是我们唯一乘以 x 的值。

yz 进行重复:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

由作者在 LaTeX 中生成的方程。

现在,我们可以在计算图上写出这些梯度及其对应的值:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

带有数字和梯度的计算图示例。图示由作者提供。

梯度下降通过在梯度的相反方向上小幅度更新值(x, y, z)来工作。梯度下降的目标是尽量减少输出函数。例如,对于 x:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者生成的 LaTeX 方程式。

其中 h 称为 学习率,决定了参数更新的幅度。在这个例子中,让我们定义 h=0.1,所以 x=3.7。现在的输出是什么?

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

执行梯度下降后的计算图示例,包含数字和梯度。图示由作者提供。

输出变小了,换句话说,它正在被最小化!

这个例子灵感来源于 Andrej KarpathyYouTube 上的视频。我强烈推荐你查看,以深入了解这一过程。

应用反向传播

以上所有内容如何与神经网络的训练相关?

好了,神经网络其实就是一个计算图!输入类似于上面的 x, yz,而操作门类似于神经元中的激活函数。

现在,让我们将这一过程应用于我们之前的简单示例神经网络。记住,我们的预测是 1.326,假设目标是 2.0。这个预测中的损失函数(误差)可以是 均方误差

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者生成的 LaTeX 方程式。

记住附加在 z 上的 2 是层数,而不是幂次项!

下一步是计算相对于预测/输出的损失梯度:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者生成的 LaTeX 方程式。

现在,我们需要计算相对于输出层偏置和权重的损失梯度:W_2b_2:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者生成的 LaTeX 方程式。

如果上述表达式看起来让你感到害怕,不必担心。我们所做的只是进行了偏导数计算,并多次应用了链式法则。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者生成的 LaTeX 方程式。

最后一步是使用梯度下降更新参数,其中我设置了学习率 h=0.1

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

作者生成的 LaTeX 方程式。

Voilà,我们已经更新了输出层的权重和偏置!

接下来是对隐藏层的权重和偏置重复这一过程。首先,我们需要找到相对于激活函数输出的损失,a¹_{1,1}a¹_{1,2}

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

由作者在 LaTeX 中生成的方程。

现在,我们找到 z¹_{1} 和 z¹_{2} 的导数:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

由作者在 LaTeX 中生成的方程。

一些背景信息:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

由作者在 LaTeX 中生成的方程。

下一步是找到相对于 W_{1,1}W_{1,2} 的损失。在此之前,我想重新定义一些符号,以便清楚我们在处理哪个权重:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

由作者在 LaTeX 中生成的方程。

因此:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

由作者在 LaTeX 中生成的方程。

因此,相对于权重和偏置的损失的偏导数是:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

由作者在 LaTeX 中生成的方程。

最后一步是使用梯度下降来更新这些值:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

由作者在 LaTeX 中生成的方程。

哇,我们刚刚完成了整个反向传播的迭代!

一个前向传播和反向传播(反向传播)的周期被称为 epoch

下一步是使用更新后的权重和偏置进行另一次前向传播。这个前向传播的结果将是 1.618296。这接近目标值 2,因此网络已经“学习”到了更好的权重和偏置。这就是“机器学习”在发挥作用。真的很惊人!

实际上,这个算法会运行 100 或 1000 次 epoch。幸运的是,已经存在处理此过程的包,因为手动完成会非常繁琐!

额外细节

可以看出,为什么这个过程被称为反向传播,因为我们在网络的每一层向后传播误差(导数)。一旦你掌握了它,理解起来就很简单。因此,我强烈建议你慢慢地进行这个过程,最好自己动手,我保证你会很快理解!

PyTorch 示例

手动完成,如上所述,确实很耗费精力,而且这只是一个小网络。然而,我们可以利用 PyTorch(一个深度学习库)来为我们完成所有这些繁重的工作:

GitHub Gist 由作者提供。

因此,我们手动编写的整个前向传播和反向传播过程可以在 ~50 行代码中完成!Python 的威力!

然而,由于随机化、浮点精度和其他计算机因素,权重、偏置和预测可能与手动计算的结果不完全匹配。这不是问题,但重要的是要意识到这一点。

如果你想了解更多关于 PyTorch 的内容,可以查看他们网站上的 教程

总结与进一步思考

在本文中,我们探讨了神经网络如何生成预测并从错误中学习。这个过程围绕使用部分微分更新网络的参数,针对损失误差。算法是反向传播,因为它通过链式法则将误差反向传播通过每一层。一旦你掌握了它,反向传播相当直观,但对于大型神经网络来说非常繁琐。这就是我们使用像 PyTorch 这样的深度学习库,它为我们做了大部分繁重的工作。

本文中使用的完整代码可以在我的 GitHub 上找到:

[## Medium-Articles/Neural Networks/basic_foward_backward_pass.py 在主分支 · egorhowell/Medium-Articles

我在我的中等博客/文章中使用的代码。通过在…上创建帐户来贡献 egorhowell/Medium-Articles 的开发。

github.com](https://github.com/egorhowell/Medium-Articles/blob/main/Neural%20Networks/basic_foward_backward_pass.py?source=post_page-----3a75996ada3b--------------------------------)

参考资料与进一步阅读

另一件事!

我有一个免费的新闻通讯,数据解析,在其中我分享成为更优秀数据科学家的每周技巧。没有“虚华”或“点击诱饵”,只有来自实践数据科学家的纯粹可操作的见解。

[## 数据解析 | Egor Howell | Substack

如何成为更好的数据科学家。点击阅读《数据解析》,由 Egor Howell 撰写,这是一个 Substack 出版物,内容包括…

newsletter.egorhowell.com](https://newsletter.egorhowell.com/?source=post_page-----3a75996ada3b--------------------------------)

与我联系!

四种构建在生成式人工智能基础模型之上的方法

原文:towardsdatascience.com/four-approaches-to-build-on-top-of-generative-ai-foundational-models-43c1a64cffd5?source=collection_archive---------1-----------------------#2023-03-21

每种方法的优缺点、有效性以及示例代码

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 Lak Lakshmanan

·

关注 发表在 Towards Data Science · 11 分钟阅读 · 2023 年 3 月 21 日

如果我在这里使用的术语对你来说不熟悉,我鼓励你先阅读我的 关于大型语言模型的早期文章

确实团队在实际应用中使用 ChatGPT 或其竞争者(如 Anthropic、Google 的 Flan T5 或 PaLM、Meta 的 LLaMA、Cohere、AI21Labs 等),而不是仅仅用于炫酷的演示。不幸的是,关于他们如何做到这一点的信息在市场营销噱头和技术术语中被掩盖。因此,我看到刚开始接触生成式 AI 的人们采取了一些领域专家会告诉你不会奏效的方法。本文尝试组织这个领域并展示哪些方法有效。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片由 Sen 提供,来源于 Unsplash

要跨越的标准

许多关于生成式 AI 的炫酷演示和充满噱头的帖子存在的问题在于它们 击中了训练数据集 ——它们并没有真正告诉你在应用于真实用户和实际新输入的混乱情况下效果如何。典型软件预计要达到 99% 以上的可靠性 ——例如,只有当语音识别技术在短语上跨越了这一准确度标准时,语音 AI 市场才得以起飞。自动字幕、翻译等情况也是如此。

我看到团队在其生产系统中解决这一问题有两种方式:

  • 如果用户体验在他们已经预期需要纠正错误的情况下,人类用户会更宽容(这似乎是 GitHub Copilot 帮助的原因),或者如果它被定位为互动和有帮助但尚未准备好使用(如 ChatGPT、Bing Chat 等)。

  • 目前,生成式 AI 的完全自动化应用大多处于受信测试阶段,是否能够真正达到这一标准仍有待观察。尽管如此,结果令人鼓舞,并且趋势向上发展,最终达到标准只是时间问题。

就个人而言,我一直在尝试 GPT 3.5 Turbo 和 Google Flan-T5,并针对特定的生产使用案例进行实验,并了解了许多有效和无效的方面。我的模型都没有跨越 99% 的标准。到写作时(2023 年 3 月),我也尚未获得 GPT-4 或 Google 的 PaLM API 的访问权限。我基于我的实验、已发布的研究和公开宣布的项目撰写了这篇文章。

在所有生成式 AI 的应用中,牢记预训练模型是基于互联网内容进行训练的,并可能存在多种偏见。这些偏见在你的应用层面上要加以防范。

方法 1:直接使用 API

第一个方法是最简单的,因为许多用户通过 ChatGPT 提供的交互式界面遇到了 GPT。尝试各种提示直到得到你想要的输出似乎非常直观。这就是为什么你会看到许多 LinkedIn 影响者发布了 适用于销售邮件的 ChatGPT 提示 或其他内容。

当涉及到自动化这个工作流时,自然的方法是使用服务的 REST API 端点 并用最终有效的提示直接调用它:

import os
import openai
openai.api_key = os.getenv("OPENAI_API_KEY")
openai.Edit.create(
  model="text-davinci-edit-001",
  input="It was so great to meet you .... ",
  instruction="Summarize the text below in the form of an email that is 5 sentences or less."
)

然而,这种方法不适合操作化。原因有几个:

  1. 脆弱性。底层模型持续改进。部署模型的突然变化 破坏了 许多生产工作负载,人们从这些经验中学到了很多。机器学习工作负载已经很脆弱了;在特定模型的提示中添加额外的失败点是不明智的。

  2. 注入。像上述示例中那样,指令和输入通常不是简单的字符串。它们大多包括来自用户的变量。这些变量必须被纳入提示和输入中。正如任何程序员所知道的那样,通过字符串连接进行注入充满了安全问题。当你这样做时,你将自己置于生成式 AI API 周围的保护措施的摆布之下。像防御 SQL 注入一样,使用一个处理变量注入的 API 更为妥当。

  3. 多个提示。很少能在一次尝试中让一个提示奏效。更常见的做法是向模型发送多个提示,并让模型根据这些提示修改其输出。这些提示本身可能会在工作流中嵌入一些人工输入(例如后续输入)。提示提供一些期望输出的示例(称为少量示例学习)也是很常见的。

解决这三个问题的一种方法是使用 langchain。

方法二:使用 langchain

Langchain 正迅速成为一个首选库,允许你调用来自不同供应商的 LLM,处理变量注入,并进行少量示例训练。 这是一个使用 langchain 的示例

from langchain.prompts.few_shot import FewShotPromptTemplate

examples = [
  {
    "question": "Who lived longer, Muhammad Ali or Alan Turing?",
    "answer": 
"""
Are follow up questions needed here: Yes.
Follow up: How old was Muhammad Ali when he died?
Intermediate answer: Muhammad Ali was 74 years old when he died.
Follow up: How old was Alan Turing when he died?
Intermediate answer: Alan Turing was 41 years old when he died.
So the final answer is: Muhammad Ali
"""
  },
  {
    "question": "When was the founder of craigslist born?",
    "answer": 
"""
Are follow up questions needed here: Yes.
Follow up: Who was the founder of craigslist?
Intermediate answer: Craigslist was founded by Craig Newmark.
Follow up: When was Craig Newmark born?
Intermediate answer: Craig Newmark was born on December 6, 1952.
So the final answer is: December 6, 1952
"""
...
]

example_prompt = PromptTemplate(input_variables=["question", "answer"], 
                                template="Question: {question}\n{answer}")

prompt = FewShotPromptTemplate(
    examples=examples, 
    example_prompt=example_prompt, 
    suffix="Question: {input}", 
    input_variables=["input"]
)

print(prompt.format(input="Who was the father of Mary Ball Washington?"))

我强烈推荐使用 langchain 而不是直接使用供应商的 API。然后,确保你所做的一切与至少两个 API 兼容,或者使用一个不会在你使用期间改变的 LLM 检查点。这两种方法都能避免你的提示/代码对底层 LLM 的变化过于脆弱。(这里,我使用 API 指代一个托管的 LLM 端点)。

Langchain 目前 支持来自 Open AI、Cohere、HuggingFace Hub(因此包括 Google Flan-T5)等的 API,以及 来自 AI21、Anthropic、Open AI、HuggingFace Hub 等的 LLM。

方法 3:微调生成 AI 链

这是前沿的方法,因为这是我看到大多数复杂生成 AI 生产应用程序所使用的方法。仅举一个例子(并非 endorsement),微调就是 一家由斯坦福博士组成的初创公司如何接近像 SQL 生成和记录匹配这样的标准企业用例。

要理解这种方法背后的理由,了解支撑 ChatGPT(或其竞争者)的四个机器学习模型是有帮助的:

  1. 大型语言模型(LLM)被训练以预测给定前一个词后的下一个词。它通过学习在大量文档中的词汇关联和模式来实现这一点。模型足够大,可以在不同的上下文中学习这些模式。

  2. 基于人类反馈的强化学习模型(RL-HF)通过向人类展示生成的文本示例,并要求他们批准令人愉悦的文本来进行训练。之所以需要这样做,是因为 LLM 的输出是概率性的——它不会预测一个单一的下一个词,而是预测一组词,每个词都有一定的概率会出现。RL-HF 使用人类反馈来学习如何选择生成对人类有吸引力的文本的延续。

  3. 指令模型是一个监督模型,通过显示提示(“生成一封向工程领导提议演示的销售邮件”)并在销售邮件的示例上训练模型来进行训练。

  4. 上下文模型被训练以与用户进行对话,使他们能够通过连续的提示来制定输出。

此外,还有保护机制(对输入和输出的过滤器)。模型会拒绝回答某些类型的问题,并撤回某些答案。在实际应用中,这些都是不断更新的机器学习模型。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

步骤 2:RL-HF 如何工作。图片来自 Stiennon et al, 2020

有一些开源生成 AI 模型(Meta 的 LLaMA,Google 的 Flan-T5)允许您从上述任意步骤开始(例如,使用发布的检查点中的步骤 1-2,自行在您的数据上训练第 3 步,不执行第 4 步)。请注意,LLaMA 不允许商业使用,而 Flan-T5 已经有一年时间(因此您需要在质量上做出妥协)。了解每个阶段的成本/收益有助于您决定从哪里开始。

  • 如果您的应用程序使用的术语和词汇非常不同,可能有必要从头开始在您的数据上构建一个 LLM(即,从第 1 步开始)。问题是您可能没有足够的数据,即使有足够的数据,训练成本也会很高(每次训练运行的费用在 300 万到 500 万美元之间)。这似乎是 Salesforce 对 他们为开发人员使用的生成 AI 所做的。

  • RL-HF 模型经过训练,旨在吸引那些可能不是主题专家或代表您自己用户的测试人员。如果您的应用程序需要主题专业知识,您可能更适合从 LLM 开始,然后从第 2 步分支出去。所需的数据集要小得多——Stiennon 等人在 2020 年使用了 125k 文档,并在每次迭代中为每个输入文档呈现一对输出(见图示)。因此,您需要人类标注者随时待命,以对约 100 万个输出进行评分。假设一个标注者需要 10 分钟来评分每对文档,那么每次训练的人工成本大约是 250 人月。我估计费用在 25 万美元到 200 万美元之间,具体取决于地点和技能水平。

  • ChatGPT 被训练来响应成千上万的不同提示。另一方面,您的应用程序可能只需要一两个特定的提示。将 Google Flan-T5 训练到您的特定指令和输入上可能会很方便。这样的模型可以更小(因此部署成本更低)。这种服务成本上的优势解释了为什么第 3 步是最常见的分支点。您可以使用 HuggingFace 和/或 Keras 对 Google Flan-T5 进行针对您特定任务的微调。您可以在常用的 ML 框架如 Databricks、Sagemaker 或 Vertex AI 上进行,并使用相同的服务来部署训练后的模型。由于 Flan-T5 是 Google 的模型,GCP 通过在 Vertex AI 中提供 预构建容器 使训练和部署变得非常简单。费用可能在 50 美元左右。

  • 理论上,有可能通过不同的方法来保持对话上下文。然而,我在实际应用中没有看到这种做法。大多数人做的是使用像 Dialogflow 这样的对话代理框架,它已经内置了 LLM,并为他们的应用设计一个定制的聊天机器人。基础设施成本微不足道,你只需要领域知识,无需任何 AI 专业知识。

可以在这些阶段中的任何一个进行中断。以下例子仅限于公开发布的医学研究:

  1. 这篇Nature 文章从从医学记录中提取的 90 亿字中构建了一个自定义的 89 亿参数 LLM(即,它们从第 1 步开始)。作为比较,下文第 3 种方法中使用的 Flan-PaLM 具有5400 亿参数,而“小型/高效”PaLM 为 620 亿参数。显然,成本是定制语言模型变得更大的一个限制因素。

  2. 这项MIT CSAIL 研究要求模型严格遵循现有文本,并进行指令微调(即,它们从第 2 步开始)。

  3. Deep Mind 的 MedPaLM从一种指令调优的 PaLM 变体 Flan-PaLM 开始(即,它从第 3 步开始)。他们报告称,93%的医疗专业人员认为该 AI 的回答与人类回答相当。

我的建议是,根据你的应用领域与基础模型训练所用的通用互联网文本的差异,选择中断的位置。你应该微调哪个模型?目前,Google Flan T5 是最先进的可微调模型,且开放用于商业用途。对于非商业用途,Meta 的 LLaMA 是最先进的模型。

但需要注意的是:当你使用开源模型进行链式操作时,保护过滤器不会存在,因此你需要设置毒性安全措施。一个选项是使用detoxify库。确保在生产环境中的任何 API 端点周围都实施毒性过滤,否则你会发现自己不得不撤下它。API 网关可以是确保你对所有 ML 模型端点进行此操作的便捷方式。

方法 4:简化问题

有一些聪明的方法可以重新定义你所解决的问题,以便可以使用生成式 AI 模型(如第 3 种方法),但避免出现幻觉等问题。

例如,假设你想做问答系统。你可以从一个强大的 LLM 开始,然后努力“驯服”这个“野兽”,使其不出现幻觉。一个更简单的方法是重新定义问题。将模型从一个预测输出文本的模型改为一个有三个输出的模型:文档的 URL、文档中的起始位置和文本长度。这就是谷歌搜索在这里做的:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

谷歌的问答模型预测一个 URL、起始位置和文本长度。这避免了幻觉问题。

最糟糕的情况下,模型会显示不相关的文本。它不会出现幻觉,因为你不允许它真正预测文本。

一个 遵循此方法的 Keras 示例 将输入和上下文(你要在其中找到答案的文档)进行标记化:

from transformers import AutoTokenizer

model_checkpoint = "google/flan-t5-small"
tokenizer = AutoTokenizer.from_pretrained(model_checkpoint)
...
examples["question"] = [q.lstrip() for q in examples["question"]]
examples["context"] = [c.lstrip() for c in examples["context"]]
tokenized_examples = tokenizer(
        examples["question"],
        examples["context"],
        ...
)
...

然后将这些令牌传递给一个 Keras 回归模型,其第一层是 Transformer 模型,该模型接收这些令牌并输出答案在“上下文”文本中的位置:

from transformers import TFAutoModelForQuestionAnswering
import tensorflow as tf
from tensorflow import keras

model = TFAutoModelForQuestionAnswering.from_pretrained(model_checkpoint)
optimizer = keras.optimizers.Adam(learning_rate=5e-5)
model.compile(optimizer=optimizer)
model.fit(train_set, validation_data=validation_set, epochs=1)

在推理过程中,你会得到预测的位置:

inputs = tokenizer([context], [question], return_tensors="np")
outputs = model(inputs)
start_position = tf.argmax(outputs.start_logits, axis=1)
end_position = tf.argmax(outputs.end_logits, axis=1)

你会注意到,样本并没有预测 URL——上下文假定是典型搜索查询的结果(例如由匹配引擎或向量数据库返回),样本模型只进行提取。然而,你可以通过在 Keras 中添加一个单独的层来将搜索功能也构建到模型中。

总结

我见到的四种在生成 AI 基础模型之上构建生产应用程序的方法:

  1. 使用像 GPT-4 这样的全能模型的 REST API 进行单次提示。

  2. 使用 langchain 来抽象化 LLM、输入注入、多轮对话和少样本学习。

  3. 利用一组模型来对你的自定义数据进行微调,这些模型构成了一个端到端的生成 AI 模型。

  4. 将问题重新定义为一种避免生成 AI(偏见、毒性、幻觉)风险的形式。

方法 #3 是我见过的最常被成熟团队使用的方法。

A/B 测试中的四个常见错误及解决方法

原文:towardsdatascience.com/four-common-mistakes-when-a-b-testing-and-how-to-solve-them-384072b57d75

提升你的 A/B 测试技能:解决四个关键错误以获得更好的结果

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 Terence Shin, MSc, MBA

·发布于 Towards Data Science ·7 分钟阅读·2023 年 6 月 29 日

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图片来源 Oscar Ivan Esquivel ArteagaUnsplash

A/B 测试就像 Jenga,一种由相互关联的部分组成的微妙平衡,形成了成功实验的基础。就像在 Jenga 游戏中,移除错误的块可能会导致整个塔崩溃一样,A/B 测试依赖于多个组件的共同工作。每个部分代表测试的一个关键元素,如果其中任何一个失败了,实验的完整性可能会受到威胁,导致不准确的结果或错失机会。

在我的经验中,我见证了许多出色的实验创意因为许多数据科学家,包括我自己,犯的常见错误而失败!因此,我想和你探讨四个在 A/B 测试中最常见的错误(以及如何解决这些错误!)。

如果你对 A/B 测试不熟悉,并且有意从事数据科学职业,我强烈建议你至少熟悉一下这个概念。

如果你想了解 A/B 测试的入门知识,可以查看我的下文:

## 数据科学 A/B 测试简明指南

这是数据科学家最重要的统计方法之一

towardsdatascience.com

说到这里,让我们深入探讨吧!

问题 #1:统计功效设定得过低。

总结一下,统计功效表示正确检测真实效应的概率,或者更准确地说,它是在零假设为假时拒绝零假设的条件概率。统计功效与犯第二类错误(假阴性)的概率成反比。

通常,在进行研究时,将功效设置为 80% 是一种常见做法。根据其定义,这意味着如果你将功效设置为 80%,那么当零假设为假时,你将有 20% 的概率未能拒绝零假设。简单来说,如果在 100 次实验中存在真实效应,你只会检测到 80 次。

这为什么是个问题?

在商业中,尤其是在科技公司中,一个主要目标是尽可能快速地学习、构建和迭代。大型科技公司,如 Airbnb 和 Uber,能够如此快速地增长并维持市场份额,其中一个原因就是它们能够不断进化。

当你将统计功效设置为 80% 时,这意味着 20% 的真实效应没有被捕捉到,也就是说少了 20% 的迭代。现在将这个问题扩大到,比如说 10 年,你就能理解这可能产生的影响。

解决方案是什么?

对此显而易见的解决办法是提高统计功效。而如何做到这一点并不是那么明显——统计功效直接与其他几个实验参数相关,这意味着有几种方法可以提高统计功效:

  • 增加样本大小。提高统计功效的主要方法是增加样本大小。通过增加样本大小,数据的变异性减少,从而导致更窄的置信区间和更准确的估计。这就是为什么如果你使用像 Evan Miller 的 A/B 测试计算器这样的功效分析工具,设置更高的功效会导致推荐的样本大小更大。

  • 调整 alpha 值。功效和 alpha 值是反相关的,这一点如果你仔细考虑就会明白。如果你将 alpha 值从 0.05 降低到 0.01,拒绝零假设的阈值会变得更严格,从而使得拒绝变得更加困难,这会导致统计功效降低。反之亦然——如果你的 alpha 值过低,通过增加 alpha 值,你更可能拒绝零假设,并获得更高的统计功效。

  • 减少效应大小(最小可检测效应)。通过减少效应大小,测试的统计功效会增强,因为这会增加检测较小效应的能力。不过,这并不是总是推荐的做法,这引出了我的下一个要点!

问题 #2:将最小可检测效应(MDE)设置得过低。

最小可检测效应(MDE)代表实验可以可靠检测到的最小效应大小。如果观察到的效应大小低于 MDE,说明该效应如此微小,以至于可能只是由于数据中的随机变异或噪音,而不是实际的有意义的效应。

如果是这样的话,那为什么希望将 MDE 设定得尽可能低呢?这就是统计显著性与实际显著性的概念发挥作用的地方——统计显著性关注的是效应不是由于随机机会的概率,而实际显著性则考虑了效应在实际中的大小和影响。

举个例子,我在 KOHO 进行了一项定价实验,以确定某一产品的价格弹性。最终结果在统计上显著,因为价格的降低导致了产品采纳的增加。然而,我们降低价格的幅度并不实际显著,因为尽管用户数量增加了,但价格的降低最终导致了总体利润的减少。

解决方案是什么?

你应该根据与上下文相关的实际效应大小来选择最小可检测效应(MDE),并使其与实验的目标保持一致。这确保了检测到的效应既在统计上显著,又在实际中有意义,同时优化资源分配,避免假阴性风险。

问题 #3:进行过多的假设检验。

我经常看到进行几十次 A/B 测试(假设检验)来测试几乎相同的内容,比如测试某一产品的多个价格点、测试各种网站配置和测试多个营销活动。

为什么这是个问题?

问题在于,当你进行更多的假设检验时,你更有可能偶然获得统计显著的结果。从统计学角度看,这是因为 A/B 测试时设定的 alpha 值。alpha 代表了在原假设为真的情况下拒绝原假设的概率,因此如果我们将 alpha 设为 0.05,那么 100 个真实测试的假设中有 5 个将被拒绝。

解决方案是什么?

解决方案是控制虚假发现(假阳性),有几种方法可以实现这一点。最常见的技术是Bonferroni 校正,它通过将显著性水平(alpha)除以测试的数量来进行调整。例如,如果你进行 10 次假设检验并希望保持整体 alpha 为 0.05,你需要将 0.05 除以 10,从而为每个测试得到调整后的 alpha 值 0.005。此校正确保了更严格的统计显著性标准,减少了假阳性的可能性。

问题 #4:没有考虑幸存者偏差。

我看到的另一个问题是,实验设计中往往没有调整幸存者偏差。

这有什么问题?

幸存者偏差用户任期之间有很强的关系。考虑这一点:不活跃或不盈利的用户不太可能与公司保持长期关系——那些没有从产品中获得价值的用户不太可能在公司停留太久。因此,考虑不同任期用户行为的潜在差异非常重要。

在拆分对照组和测试组时,如果未考虑用户任期,可能会因行为差异显著而影响结果。一组可能有更高的平均用户任期,这会影响盈利能力和参与度等因素。换句话说,未考虑用户任期可能引入混杂变量,并阻碍对感兴趣的特定因果关系的分析。

解决方案是什么?

分层抽样可以用来解决用户任期未控制而导致 A/B 测试结果偏差的问题。这包括将总体分成特定段,然后随机抽取每个组。可以通过以下步骤完成:

  1. 定义用户任期组:将用户群体按与公司关系的任期分成不同组。例如,你可以创建“新用户”(短期任期)、“中期用户”(中等任期)和“长期用户”(长期任期)等组。

  2. 确定样本大小:确定每个任期组所需的样本大小。样本大小可以与总体用户群体中每组的大小成比例,或基于特定考虑因素,例如每组的重要性或所需的统计功效。

  3. 在每个组内随机抽样:从每个任期组中随机选择用户,形成对照组和测试组。确保选择代表每组中的用户,保持不同任期级别用户的比例。

  4. 进行 A/B 测试:通过分层抽样,你将减少实验中的偏差,并为更可靠的结果做好准备。现在你可以以一种控制其他变量的方法来正确进行实验。

阅读完这些内容后,你应该知道四种常见的 A/B 测试错误及其解决方法——具体来说,你应该知道如何考虑:

  1. 将统计功效设得太低

  2. 将最小可检测效应(MDE)设得太低

  3. 进行过多的假设检验

  4. 未考虑幸存者偏差

考虑这些错误肯定会提高你 A/B 测试的有效性和可靠性,从而提供有意义的见解和信息化决策。

现在出去看看你能发现什么!

感谢阅读!

如果你喜欢这篇文章, 立即订阅并成为会员,以便不错过有关数据科学指南、技巧和窍门、生活经验等的任何文章!

[## 使用我的推荐链接加入 Medium - Terence Shin

解锁独家见解,保持领先:订阅体验知识的世界。发现一座宝藏…

terenceshin.medium.com](https://terenceshin.medium.com/membership?source=post_page-----384072b57d75--------------------------------)

不确定接下来读什么?我为你挑选了另一篇文章:

[## 你应该了解的所有机器学习算法(2023 年版)

最受欢迎的机器学习模型的直观解释

terenceshin.medium.com](https://terenceshin.medium.com/all-machine-learning-algorithms-you-should-know-for-2023-843dba11419c?source=post_page-----384072b57d75--------------------------------)

或者你可以查看我的 Medium 页面:

[## Terence Shin - Medium

阅读 Terence Shin 在 Medium 上的文章。数据科学 @ KOHO, Saturn Cloud | 硕士, MBA |…

terenceshin.medium.com](https://terenceshin.medium.com/?source=post_page-----384072b57d75--------------------------------)

Terence Shin

自 ChatGPT 以来的四个 LLM 趋势及其对 AI 构建者的影响

原文:towardsdatascience.com/four-llm-trends-since-chatgpt-and-their-implications-for-ai-builders-a140329fc0d2?source=collection_archive---------2-----------------------#2023-05-29

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 Dr. Janna Lipenkova

·

关注 发表在 Towards Data Science ·15 分钟阅读·2023 年 5 月 29 日

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

表 1:截至 2023 年 5 月的热门 LLM(按提及数量排序)。提及数量、趋势和下游任务的适用性是从超过 50 万份与 AI 相关的在线文档中计算得出的,这些文档包括商业媒体、普通新闻、AI 博客和科学出版物。任务适用性通过语义嵌入和模型与 NLP 任务之间的潜在关联强度进行计算。

2022 年 10 月,我发布了一篇关于特定 NLP 用例的 LLM 选择的文章,涉及对话、翻译和摘要等内容。从那时起,AI 已经取得了巨大的进步,在这篇文章中,我们将回顾过去几个月的一些趋势以及它们对 AI 构建者的影响。具体而言,我们将涵盖自回归模型的任务选择、商业和开源 LLMs 之间不断变化的权衡,以及 LLM 的集成和生产中故障的缓解。

1. 生成 AI 推动了自回归模型,而自动编码模型则在等待它们的时机。

对于许多 AI 公司来说,ChatGPT 似乎已成为终极竞争者。在早期推介我的分析初创公司时,我经常面临挑战:“如果谷歌(Facebook、阿里巴巴、Yandex 等)突然出现并做同样的事情,你会怎么做?”现在,当前的问题是:“为什么你不能用 ChatGPT 来做这个?”

简短的回答是:ChatGPT 在很多方面表现出色,但远未覆盖 AI 的全部领域。目前的热潮主要集中在生成AI 上——而不是分析型 AI,或者其相对较新的分支——合成 AI[1]。这对 LLMs 意味着什么?正如我在上一篇文章中描述的,LLMs 可以通过三种目标进行预训练——自回归、自动编码和序列到序列(参见表 1,列“预训练目标”)。通常,一个模型会以这些目标中的一个进行预训练,但也有例外——例如,UniLM[2]在所有三种目标上进行了预训练。近几个月来使 AI 流行的有趣生成任务包括对话、问答和内容生成——这些任务中,模型确实学习“生成”下一个标记、句子等。这些任务最适合由自回归模型执行,包括 GPT 家族以及大多数近期的开源模型,如 MPT-7B、OPT 和 Pythia。自动编码模型更适合信息提取、蒸馏和其他分析任务,虽然它们处于背景中——但不要忘记,初次突破 LLM 的 2018 年是通过 BERT 这款自动编码模型实现的。虽然这对现代 AI 来说可能感觉像是石器时代,但自动编码模型对于许多 B2B 用例特别相关,其中重点是提炼出针对特定业务任务的简明见解。我们确实可能会看到围绕自动编码的另一波浪潮,以及一代新的 LLMs,在提取和综合信息以进行分析方面表现卓越。

对于构建者来说,这意味着流行的自回归模型可以用于所有内容生成的任务——内容越长,效果越好。然而,对于分析任务,你应该仔细评估所使用的自回归大型语言模型(LLM)是否能输出令人满意的结果,并考虑使用自动编码模型或更传统的自然语言处理方法。

2. 开源与商业公司的竞争,推动了 LLM 效率和扩展性的创新。

在过去几个月中,关于开源与商业 AI 之间的复杂关系有很多讨论。短期内,开源社区无法在需要大量数据和/或计算资源的竞赛中跟上。然而,从长远来看,即使是像谷歌和 OpenAI 这样的公司也感受到开源的威胁。[3] 这种紧张关系促使双方继续发展,最终取得的进展逐渐汇聚成富有成果的协同效应。开源社区注重节俭,即通过更少的资源提高 LLM 的效率。这不仅使 LLM 对更广泛的用户群体更具负担能力——即 AI 民主化——而且从环境角度来看也更具可持续性。LLM 变得更高效的主要维度有三个:

  • 更少的计算和内存:例如,FlashAttention [4] 允许减少 GPU 上的读写次数,相比于标准的注意力算法,从而实现更快且内存高效的微调。

  • 更少的参数:在标准微调中,所有模型权重都会被重新训练——然而,在大多数情况下,只有一小部分权重影响模型在微调数据上的表现。参数高效微调(PEFT)识别这一子集并“冻结”其他权重,这可以大幅减少资源使用,同时实现更稳定的模型表现。

  • 更少的训练数据:数据质量比数据规模更具可扩展性[3]——你的训练数据越集中和精心策划,优化性能所需的数据量就越少。其中一种最成功的方法是指令微调。在训练过程中,LLM 会被提供任务特定的指令,这些指令反映了它在推理过程中最终会如何被提示。缩小训练范围可以从更少的数据中更快地学习。指令微调已经被应用了一段时间,例如在 T0、FLAN、InstructGPT 中——最终,它也是 ChatGPT 所基于的方法。

另一方面,目前,“生成性人工智能的控制权掌握在那些能够负担得起训练和大规模部署模型的少数人手中”。[5] 商业产品的规模正在迅速膨胀——无论是模型规模、数据规模还是训练时间——在输出质量方面明显优于开源模型。技术上这里没有太多可以报告的内容——而更多的担忧在于治理和监管。因此,“一个关键风险是像 GPT 这样的强大 LLM 可能只朝着符合这些公司商业目标的方向发展。”[5]

这两端将如何交汇——它们会交汇吗?一方面,任何能够减少资源消耗的技巧最终都可以通过投入更多资源来扩大规模。另一方面,LLM 的训练遵循幂律,这意味着随着模型规模、数据集规模和训练时间的增加,学习曲线会变得平缓。[6] 你可以将其理解为人类教育的类比——在人类历史的长河中,学校教育时间有所增加,但普通人的智力和博学是否也随之增加?

学习曲线平缓的积极之处在于它在对人工智能“变得比人类更强大和聪明”的担忧中带来的缓解。但请做好准备——LLM 领域充满了惊喜,其中最不可预测的之一是涌现。[7] 涌现是指系统中的定量变化导致行为上的定性变化——总结为“量变引起质变”,或者简单地说“更多即不同”。[8] 在训练的某个阶段,LLM 似乎会获得一些新的、意想不到的能力,这些能力不在原始训练范围内。目前,这些能力表现为新的语言技能——例如,模型突然学会了总结或翻译,而不仅仅是生成文本。无法预测何时会发生这种情况,以及这些新能力的性质和范围是什么。因此,虽然涌现现象对研究人员和未来学家来说很吸引人,但在商业背景下仍然远未提供稳健的价值。

随着越来越多的方法被开发出来以提高 LLM 微调和推理的效率,围绕开源 LLM 物理操作的资源瓶颈似乎正在放松。由于商业 LLM 的高使用成本和限制配额,越来越多的公司考虑部署自己的 LLM。然而,开发和维护成本依然存在,大多数描述的优化也需要扩展的技术技能来操作模型及其部署的硬件。选择开源还是商业 LLM 是一个战略性决策,应在仔细探索包括成本(包括开发、运营和使用成本)、可用性、灵活性和性能在内的一系列权衡后做出。一个常见的建议是先使用大型商业 LLM 来快速验证最终产品的商业价值,然后再“切换”到开源 LLM。然而,这种过渡可能会很艰难,甚至不现实,因为 LLM 在擅长的任务上有很大差异。存在着开源模型无法满足你已开发应用需求的风险,或者你需要做大量修改以缓解相关权衡。最后,对于那些在 LLM 上构建各种功能的公司,最先进的设置是多 LLM 架构,这允许利用不同 LLM 的优势。

3. LLM 正在通过插件、代理和框架实现操作。

LLM 训练中的重大挑战已基本解决,另一项工作重点是将 LLM 集成到现实世界的产品中。除了提供提高开发者便利性的现成组件外,这些创新还帮助克服现有 LLM 的限制,并通过推理和使用非语言数据等附加能力来丰富它们。[9] 基本思想是,尽管 LLM 在模拟人类语言能力方面已经很出色,但它们仍需置于更广泛的计算“认知”背景中,以进行更复杂的推理和执行。这种认知包括推理、行动和观察环境等多种不同能力。目前,这通过插件和代理来近似实现,这些插件和代理可以通过 LangChain、LlamaIndex 和 AutoGPT 等模块化 LLM 框架进行组合。

3.1 插件提供对外部数据和功能的访问

预训练的 LLM 在利用数据时存在显著的实际限制:一方面,数据很快就会过时——例如,尽管 GPT-4 于 2023 年发布,其数据却截止于 2021 年。另一方面,大多数现实世界的应用需要对 LLM 中的知识进行一些定制。考虑构建一个允许你创建个性化营销内容的应用——你可以向 LLM 提供关于你的产品和具体用户的信息,结果会更好。插件使这一点成为可能——你的程序可以从外部源(如客户电子邮件和通话记录)获取数据,并将这些数据插入到提示中,以生成个性化的、受控的输出。

3.2 代理人言行一致

语言与可操作性紧密相关。我们的交流意图常常围绕行动展开,例如当我们要求别人做某事或拒绝以某种方式行动时。计算机程序也是如此,它们可以被视为执行特定操作的函数集合,当满足特定条件时会阻止这些操作等。基于 LLM 的代理人将这两个世界结合在一起。这些代理人的指令不是用编程语言硬编码的,而是由 LLM 以推理链的形式自由生成,这些推理链引导实现给定目标。每个代理都有一组插件,并可以根据推理链的需要进行调整——例如,它可以结合一个用于检索特定信息的搜索引擎和一个用于随后对这些信息进行计算的计算器。代理人的概念在强化学习中存在已久——然而,到今天为止,强化学习仍发生在相对封闭和安全的环境中。凭借 LLM 的广泛常识,代理人不仅可以进入“广阔的世界”,还可以发挥无尽的组合潜力:每个代理可以执行多种任务以实现其目标,多个代理可以互相互动和合作。[10] 此外,代理人从与世界的互动中学习,建立的记忆比 LLM 的纯语言记忆更接近人类的多模态记忆。

3.3 框架提供了 LLM 集成的便捷接口

在过去几个月里,我们见证了一系列基于 LLM 的新框架,如 LangChain、AutoGPT 和 LlamaIndex。这些框架允许将插件和代理集成到复杂的生成和操作链中,以实现包括多步骤推理和执行的复杂过程。开发人员现在可以专注于高效的提示工程和快速应用原型设计。[11] 目前,使用这些框架时仍然有很多硬编码的工作——但逐渐地,它们可能会向更全面和灵活的系统发展,比如 Yann LeCun 提出的 JEPA 架构。[12]

这些新组件和框架对构建者有何影响?一方面,它们通过增强外部数据和能力提升了 LLM 的潜力。框架与方便的商业 LLM 结合,将应用原型制作缩短到了几天。但 LLM 框架的兴起也对 LLM 层有影响。它现在隐藏在额外的抽象层之后,任何抽象层都需要更高的意识和纪律,以可持续的方式利用。首先,在生产开发时,仍需要一个结构化的过程来评估和选择适合当前任务的 LLM。目前,许多公司在假设 OpenAI 提供的最新模型最合适的情况下跳过了这个过程。其次,LLM 的选择应该与期望的代理行为协调:期望的行为越复杂和灵活,LLM 应该表现得越好,以确保它能在广泛的选项空间中选择正确的行动。[13] 最后,在操作中,MLOps 管道应该确保模型不会偏离变化的数据分布和用户偏好。

4. LLM 的语言接口为人机交互带来了新的挑战。

随着提示技术的进步,使用 AI 来做炫酷和创造性的事情对于非技术人员变得越来越可行。不再需要成为程序员——只需使用语言,我们的自然沟通媒介,来告诉机器该做什么。然而,在所有围绕快速原型制作和 LLM 实验的热潮和兴奋中,我们仍然会发现“用 LLM 做些炫酷的东西很容易,但要让它们达到生产级的准备却非常困难。”[14] 在生产环境中,LLM 会出现幻觉,对不完美的提示设计很敏感,并且在治理、安全和与期望结果的一致性方面提出了许多问题。我们最喜欢 LLM 的地方——它开放的输入和输出空间——也使得在部署到生产环境之前,更难以测试潜在的故障。

4.1 幻觉和沉默的失败

如果你曾经构建过 AI 产品,你会知道最终用户通常对 AI 故障非常敏感。用户倾向于“负面偏见”:即使你的系统整体准确性很高,那些偶尔但不可避免的错误情况也会被放大镜审视。对于 LLM 来说,情况有所不同。就像任何其他复杂的 AI 系统一样,LLM 也会失败——但它们以沉默的方式失败。即使它们没有一个好的回应,它们仍然会生成某些东西,并以高度自信的方式展示出来,欺骗我们相信和接受它们,并让我们在后续过程中陷入尴尬的境地。想象一下,一个由 LLM 生成指令的多步骤代理——第一步的错误将级联到所有后续任务中,并破坏代理的整个行动序列。

大型语言模型(LLMs)面临的最大质量问题之一是幻觉,指的是生成在语义上或语法上看似合理但事实上却不正确的文本。早在诺姆·乔姆斯基通过他著名的句子“无色的绿色思想愤怒地睡觉”中,就指出了一个句子从语言学角度看可能完美无缺,但对人类而言却完全毫无意义的观点。但对于 LLMs 而言情况不同,它们缺乏人类所拥有的非语言知识,因此无法将语言与基础世界的现实相结合。虽然我们能立即发现乔姆斯基句子中的问题,但一旦进入我们专业领域之外的更专业领域,验证 LLM 输出的准确性会变得相当繁琐。对于长篇内容以及没有真实依据的交互,如预测和开放式的科学或哲学问题,未被发现的幻觉风险尤其高。

对于幻觉有多种处理方法。从统计学的角度来看,我们可以期待随着语言模型的学习越来越多,幻觉现象会减少。但在商业环境中,这种“解决方案”的增量性和不确定的时间线使得它相当不可靠。另一种方法基于神经符号 AI。通过结合统计语言生成和确定性世界知识的力量,我们或许能够减少幻觉和隐性失败,最终使大规模生产中的大型语言模型(LLM)更加稳健。例如,ChatGPT 通过集成 Wolfram Alpha 这一庞大的结构化知识数据库来兑现这一承诺。

4.2 提示的挑战

表面上,提示提供的自然语言界面似乎缩小了 AI 专家和外行之间的差距——毕竟,我们都知道至少一种语言并用它进行沟通,那么为何不在 LLM 中做同样的事?但提示是一门精细的工艺。成功的提示不仅需要强大的语言直觉,还需要对 LLM 的学习和工作原理有深入了解。而且,设计成功的提示过程是高度迭代的,需要系统的实验。如论文 Why Johnny can’t prompt 所示,人类很难保持这种严格性。一方面,我们常常被根植于人际互动经验中的期望所影响。与人交谈不同于与 LLM 交谈——当我们互相交流时,我们的输入是通过丰富的情境背景传递的,这使我们能够中和人类语言中的不精确性和模糊性。LLM 只接收到语言信息,因此宽容度要小得多。另一方面,采用系统化的方法进行提示工程很困难,因此我们很快陷入机会主义的试错中,难以构建一个可扩展且一致的提示系统。

解决这些挑战需要教育提示工程师和用户了解学习过程和 LLM 的失败模式,并保持对界面中可能出现的错误的意识。应该清楚,LLM 的输出总是具有不确定性的。例如,可以通过模型校准得出的置信度分数在用户界面中实现这一点。[15] 对于提示工程,我们目前看到 LLMOps 的兴起,这是 MLOps 的一个子类别,允许通过提示模板、版本控制、优化等管理提示生命周期。最后,在一致性方面,微调胜过少量学习,因为它消除了即兴提示的“人为因素”并丰富了 LLM 的内在知识。只要在你的设置中有可能,你应该考虑在积累了足够的训练数据后从提示切换到微调。

结论

随着新模型、性能优化和集成每天都在出现,LLM 的深度正在不断加深。对公司而言,保持差异化、关注近期发展和新风险以及偏向实际操作实验而非热点是重要的——许多与 LLM 相关的权衡和问题只有在实际使用中才会显现。本文探讨了近期的发展及其对 LLM 构建的影响:

  • 大多数当前的 LLM 是自回归的,在生成任务中表现出色。它们在分析任务中可能不可靠,此时应优先考虑自编码 LLM 或其他 NLP 技术。

  • 开源 LLM 和商业 LLM 之间存在显著差异,切换 LLM 可能比预期的更困难。仔细考虑权衡,评估可能的发展路径(从开源开始,随后切换到商业 LLM),并考虑如果你产品的不同特性依赖于 LLM 时,是否考虑多 LLM 设置。

  • 框架提供了一个便捷的接口来构建 LLM,但不要低估 LLM 层的重要性 — LLM 应经过实验和细致挑选的过程,然后通过完整的 MLOps 周期,以确保稳健、持续优化的操作,并减轻诸如模型漂移等问题。

  • 构建者应主动管理人类因素。LLM 已经征服了语言,这是一个最初仅人类能够接触的认知领域。作为人类,我们很快忘记 LLM 仍然是“机器”,并未能如对待机器一样操作它们。对于用户和员工,考虑如何提高他们的意识,并教育他们正确操作和使用 LLM。

参考文献

[1] 安德森·霍洛维茨。2023 年。 对于 B2B 生成 AI 应用程序,少即是多吗

[2] 李栋等。2019 年。统一语言模型预训练用于自然语言理解和生成。在第 33 届国际神经信息处理系统会议论文集中,第 13063–13075 页。

[3] 信息日报。2023 年。 谷歌研究员:公司在 AI 领域没有“护城河”

[4] 特里·道等。2022 年。 FlashAttention:具有 IO 感知的快速且内存高效的精确注意力

[5] EE Times。2023 年。 开源 LLM 能解决 AI 民主化问题吗

[6] 贾雷德·卡普兰等。2023 年。 神经语言模型的扩展定律

[7] 杰森·魏等。2023 年。 大型语言模型的涌现能力

[8] 菲利普·安德森。1972 年。更多即不同。在《科学》,第 177 卷,第 4047 期,第 393–396 页。

[9] 贾娜·利朋科娃。2023 年。 克服大型语言模型的局限性

[10] 俊尚·朴等。2023 年。 生成代理:人类行为的互动模拟

[11] 哈佛大学。2023 年。GPT-4 — 它是如何工作的,我如何用它构建应用程序? — CS50 技术讲座

[12] 扬·勒昆。2022 年。 走向自主机器智能的路径

[13] 杰瑞·刘。2023 年。 更笨的 LLM 代理需要更多的约束和更好的工具

[14] Chip Huyen. 2023. 构建生产环境中的 LLM 应用

[15] Stephanie Lin 等. 2022. 教模型用语言表达它们的不确定性

减少分析浪费的四个步骤

原文:towardsdatascience.com/four-steps-to-remove-analytics-waste-550f65f9a9e0?source=collection_archive---------13-----------------------#2023-02-03

通过减少分析浪费来加快决策

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 David Sweenor

·

关注 发表在 Towards Data Science ·7 min read·2023 年 2 月 3 日

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

洗车 — 照片由作者 David E Sweenor 提供

思考分析在您的组织决策过程中的作用。您是否认为分析被有效地或高效地使用?或者您是否能够看到宝贵的时间和资源被浪费的方式?在一个经济体中,经理人每年在无效的决策上浪费了超过一百万天的时间,在各个层面上减少浪费的机会是巨大的。

当你怀疑你的组织选择了错误的商业伙伴或者滑向了以前的位置时,你并不孤单。问题可能是你过于依赖共识,你的角色不明确,你的数据过时了,或者——我将在下面描述的——你的文化缺乏授权。在任何情况下,一个组织的决策过程无效的一个重要原因是,他们没有大规模地自动化分析。系统中的浪费导致了缓慢和低效的决策。

决策的组成

接下来,考虑一下你组织做出的不同类型的决策。例如:

  • 战略性(我们应该收购一家公司吗?)

  • 战术性或交叉性(什么是可接受的保险风险水平?)

  • 操作性(我们能向客户提供什么是最好的下一步报价?)

每种决策类型背后都有一系列步骤,大致如下:

业务事件 → 分析准备数据存储 → 分析完成和信息传递 → 做出业务决策 → 采取业务行动

这些步骤之间的联系越紧密,你从竞争格局变化这样的业务事件到市场活动这样的业务行动的过渡速度就越快。但是在你的组织中,这种情况有多常见?难道几乎总会有瓶颈和延迟点以及摩擦,导致从一个步骤到下一个步骤的过渡缓慢吗?

当你在这些步骤的背景下考虑决策时,你会意识到数据的信息价值是易逝的,并且随着时间的推移而衰减。如果你从决策过程中消除分析浪费,你可以变得更加具有竞争力。

四种类型的分析浪费

你组织中的人员不断使用分析工具来生成有关客户流失、商品价格或利率影响的洞察。分析可能是在突出不断变化趋势的先进预测工具中,也可能是在像电子表格这样的传统工具中。

这些洞察会发生什么?在许多情况下,分析完成后,信息被传递了,但之后呢?它可能会被存储在某个地方,几周或几个月后再被重新分析,而那时的行动和业务决策时机已经错过。

这看起来是这样的:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

分析过程中的浪费

鉴于数据的信息价值是易逝的,每一个延迟的红色三角形——无论是在数据、分析、决策还是行动周围——都是你竞争力的障碍。这些延迟点加起来就是你在从业务事件到业务行动过程中所面临的延迟。它们代表了你组织中的分析浪费。那么,你能对此做些什么呢?

消除分析浪费的 4 个步骤

当你将决策障碍视为延迟的函数时,你的下一个目标是检查每种延迟类型,并找出导致分析浪费的原因。

  1. 数据延迟发生在需要访问数据的人无法获得访问权限时。数据访问和共享应该是常态,而不是例外。通过从批处理导向转向更实时的架构来消除分析浪费。例如,那些每天仅监控一次库存水平的零售商在突如其来的暴风雨或假日高峰期可能会面临缺货和损失的风险。

  2. 分析延迟即使在解决数据延迟后也可能出现。是否因为必须依赖专家来分析数据并反馈你而陷入困境?数据科学家和专家因每年处理少数高价值项目而备受珍视,因此,他们可能需要一段时间才能处理你的任务。在这里,答案在于赋予组织中所有人,无论技能水平如何,参与数据和分析过程的能力。当你的数据科学家专注于几个大问题时,业务中的人员则在数据生成的地方工作,并且可以关注许多小问题。但他们需要数据素养、技能提升和易于使用的软件。

  3. 决策延迟可能出现,如果决策者被不直观、难以理解的仪表板和报告所困扰。即使人们被授权做决定,他们能否查看眼前的信息并知道需要做出决定?解决这个问题有三个方面:

    a. 重新评估流程。是否需要人参与其中?你是否可以简单地通过发出采购订单或发送电子邮件授权来自动化决策?

    b. 去中心化决策。授权那些离问题(和数据)最近的人做决定,而无需审批。

    c. 在正确的时间将正确的见解提供给正确的决策者。这是一个效率问题;解决方案的一部分在于组织流程,另一部分在于软件。

  4. 行动延迟指的是一旦做出决策后,组织的敏捷性。你是否能足够迅速地响应以利用有利条件?例如,你可以期望更多地依赖预测分析,但如果你的组织流程陈旧、脆弱且劳动密集,那又有什么意义呢?解决方案是将更多分析自动化引入流程中。这意味着,如果分析显示你的多伦多商店明天将用完米色小部件,那么所有业务流程都应到位以在此之前发货。你能自动化这些流程的程度越高,你就能越早将注意力转向更高价值的任务。

人员的角色

分析自动化是消除分析浪费的核心。矛盾的是,虽然你涉及的人员越多,你越能迅速去除浪费和延迟。原因如下。

如上所述,你的数据科学家的优先任务是高关注度的项目,旨在对你的底线产生可衡量的影响。你孤立的市场预测问题看似紧迫;然而,这并不是全企业范围的问题,所以它将不得不等待数据科学资源。

但如果你的营销分析师或运营专家能在数据上进行分析呢?他们可能不了解数据科学和编程语言,但他们知道业务,他们知道哪些行动是开放的。与其等待数据科学团队的回应,不如直接参与,这样更好。事实证明,你的组织中有很多隐藏在显眼处的公民数据科学家——这是你组织中尚未开发的潜力。

当人们接近业务并被授权做出决策时,他们可以利用易于访问的数据和分析来解决无数的小问题。通过赋能那些:

  • 靠近数据

  • 对分析倾向较强的人,你可以取得更多进展

  • 希望参与去除分析浪费的过程

  • 将会接受使用直观的低代码/无代码工具进行技能提升的机会

结论:更有效的决策制定

当你消除延迟并去除分析浪费时,你将捕捉到上述数据中更多的短暂信息价值。随着时间的推移,你的曲线开始呈现以下形式:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

将业务事件压缩到业务行动中创造价值

你压缩了步骤序列,并将其向上和向左移动,以实现实时决策和高价值。你的组织在提升业务经理、分析师和掌握数据的公民数据科学家时,可以更快地做出更好的决策。

总结

无效的决策会导致业务结果不佳。

决策无处不在;你的公司每天做出成千上万甚至百万的决策。每年浪费超过 50 万天的时间,可能会使公司每年损失高达 2.5 亿美元的工资[i]。除了工资损失外,糟糕和无效的决策还可能使公司损失 3%的利润,2020 年在美国的金额达到 2700 亿美元[ii]

这些决策可以是战略性的、运营性的或战术性的。通过将业务事件压缩到业务行动中,你的组织可以创造和捕捉价值——这种价值会被永久性地捕获。

为了消除分析废料,组织可以应用分析自动化技术来压缩业务事件到业务行动的周期。然而,单靠技术无法解决你的问题。解锁组织潜力的关键是提升知识工作者和一线经理的技能。人生中有一些机会,你可以去除某些东西(分析废料),却最终得到更多(价值)。

了解分析自动化如何帮助创建一个更灵活的组织,从而更好地服务客户和客户,同时提升财务成功。阅读我们的电子书,“自动化分析:以人为本的转型商业成果方法。”

该版本首次发表在 Alteryx #INPUT

https://www.alteryx.com/input/blog/four-steps-to-remove-analytics-waste

[i] De Smet, Aaron, Gregor Jost, and Leigh Weiss. 2019. “Three Keys to Better Decision Making | McKinsey.” Www.mckinsey.com. May 1, 2019. www.mckinsey.com/capabilities/people-and-organizational-performance/our-insights/three-keys-to-faster-better-decisions.

[ii] Southekal, Prashanth. 2022. “Council Post: The DEAR Model: A Method to Make Good Business Decisions.” Forbes. March 14, 2022. www.forbes.com/sites/forbestechcouncil/2022/03/14/the-dear-model-a-method-to-make-good-business-decisions/?sh=ae0983d5b3fd.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值