TowardsDataScience-博客中文翻译-2022-十-

TowardsDataScience 博客中文翻译 2022(十)

原文:TowardsDataScience

协议:CC BY-NC-SA 4.0

Python 中的自动 MLBox 包概述

原文:https://towardsdatascience.com/auto-ml-in-python-an-overview-of-the-mlbox-package-66668c6b1bfb

了解 MLBox,针对 python 中的分类问题快速高效地训练自动化机器学习管道

郭锦恩Unsplash 上拍照

今天的帖子很特别。它是与 Axel De Romblay 合作编写的,他是 MLBox Auto-ML 软件包的作者,该软件包在过去几年中广受欢迎。

如果你还没有听说过这个库,那就去 Github 上看看吧:它包含了一些有趣的特性,正在变得越来越成熟,现在正在积极开发中。

MLBox

回购

在本帖中,我们将向您展示如何轻松地使用它来训练自动机器学习管道来解决分类问题。它将首先加载和清理数据,消除漂移,启动一个强大的加速优化管道,并生成预测。

我们开始吧!🚀

MLBox 简介

MLBox 已经在许多机器学习会议上展示过。你可以在这里查看其中一张幻灯片。这是一个很好的开始,让我们对更一般的 AutoML 概念的库有一个总体的了解。

MLBox 的幻灯片分享演示

2 —下载训练和测试数据集

在这本笔记本中,我们将解决著名的泰坦尼克号卡格尔挑战,其中包括根据乘客的属性(性别、年龄、姓名等)预测他们的存活率。

如果你不熟悉这个比赛,你可以查看这篇文章。

现在让我们下载数据:

如果你有账户的话

如果您有一个 Kaggle 帐户,您可以在您的个人资料页面上生成一个 API 令牌:

卡格尔

一旦生成了 API 令牌,您的系统上就会下载一个 kaggle.json,其中包含您的用户名和密钥。

  • 如果您使用的是基于 Unix 的操作系统,请将该文件放在~/中。kaggle/然后
chmod 600 ~/.kaggle/kaggle.json
  • 如果您在 Windows 机器上:
export KAGGLE_USERNAME=<your-username>
export KAGGLE_KEY=<your-key>

来自互联网:

确保您安装了 wget:pip install wget

然后将 train.csv 和 test.csv 放在项目根目录下的data文件夹中。

3 —环境设置和从 PyPI 安装 MLBox

建议创建一个 conda 虚拟环境,因为 MLBox 包含几个依赖项,可能会与您当前的库混淆。拥有一个干净的虚拟环境是正确的解决方案,如果出现任何问题,您可以在不影响系统的情况下将其删除。

conda create -n automl python=3.7

这就创建了一个名为 automl 的环境,其中预配置了 python 3.7。

如果你像我一样在 OSX 上,你必须通过 brew 安装 OpenMP (开放式多处理),这是多线程的有效实现:

(base) brew install libomp

现在激活 automl 并直接从 PyPI 安装 MLBox:

(base) source activate automl
(automl) pip install mlbox

原创博文

如你所见,MLBox 有相当多的依赖项,如 scikit-learn、pandas 等。这就是为什么我们创建了一个空的虚拟环境。

[可选]:从 Jupyter 访问 automl 内核。

如果你想在这种环境下使用 jupyter notebook,而不是激活它,而是从基本的 jupyter 下拉列表中选择内核;你必须安装 ipykernel :

(automl) conda install ipykernel

图片由作者修改

现在你可以走了!

4 —测试 MLBox:从数据摄取到模型构建

现在我们将测试并运行 MLBox,快速构建一个模型来解决 Kaggle Titanic 挑战。

有关软件包和 API 文档的更多信息,请访问以下链接:

正在导入 MLBox

Using TensorFlow backend. CPU times: user 2.42 s, sys: 740 ms, total: 3.16 s
Wall time: 4.04 s

MLBox 的输入

如果你有一个 train 和一个测试集,就像在任何 Kaggle 比赛中一样,你可以将这两个路径直接提供给 MLBox 以及目标名称。

否则,如果只输入一个训练集,MLBox 将创建一个测试集。

读取和预处理

MLBox 的 Reader 类负责准备数据。

它提供方法和实用程序来:

  1. 使用正确的分隔符(CSV、XLS、JSON 和 h5)读入数据并加载
  2. 通过以下方式清理数据:
  • 删除未命名的列
  • 推断列类型(float,int,list)
  • 处理日期并从中提取相关信息:年、月、日、星期、小时等。
  • 删除重复项
  • 准备列车和测试分离

更多信息请点击:https://ml box . readthe docs . io/en/latest/features . html # ml box . preprocessing . reader

原创博文

当这个函数完成运行时,它创建一个名为save的文件夹,将目标编码器转储到这个文件夹中以备后用。

df["train"].head()

原创博文

消除漂移

这是我在其他包里没遇到过的创新功能。主要思想是自动检测和移除在训练集和测试集之间具有显著不同分布的变量。

这种情况经常发生,我们通常会谈到有偏差的数据。例如,您可能会遇到这样的情况:列车组中有年轻人,而测试组中只有老年人。这表明年龄特征不是健壮的,并且可能导致模型在测试时的不良性能。所以它必须被丢弃。

更多信息:

图片由作者修改

MLBox 如何计算单个变量的漂移

MLBox 构建了一个分类器,将训练与测试数据分开。然后,它使用与该分类器相关的 ROC 分数作为漂移的度量。

这是有道理的:

  • 如果漂移分数高(即 ROC 分数高),则从测试数据中辨别训练数据的能力很容易,这意味着两种分布非常不同。
  • 否则,如果漂移分数低(即 ROC 分数低),则分类器不能正确地分离两种分布。

MLBox 提供了一个名为 Drift_thresholder 的类,它将训练集和测试集以及目标作为输入,并计算每个变量的漂移分数。

Drift_thresholder 然后删除漂移分数高于阈值(默认为 0.6)的变量。

博文

正如你在这里看到的,NamePassengerIdTicket因为他们各自的漂移分数而被移除。如果你仔细想想,这一点也不奇怪,因为这些变量,鉴于它们的性质,可以有任何随机值,从而导致它们的训练和测试分布之间的似是而非的漂移。

重担:优化

此部分执行管道的优化,并尝试不同的参数配置:

  • NA 编码器(缺失值编码器)
  • CA 编码器(分类特征编码器)
  • 功能选择器(可选)
  • 堆叠估计器—特征工程师(可选)
  • 估计器(分类器或回归器)

更多详情请点击:https://ml box . readthe docs . io/en/latest/features . html # ml box . optimization . optimizer

我们首先实例化优化器类:

opt = Optimiser()

然后,我们可以使用默认的模型配置来运行它,而不需要任何 autoML 或复杂的网格搜索。

这应该是第一个基线

原创博文

对数损失= -0.6325 作为第一基线。

现在让我们定义一个多种配置的空间:

  • ne__numerical_strategy:如何处理数字特征中的缺失数据
  • ce__strategy:如何处理分类变量编码
  • fs:功能选择
  • 堆叠:元功能堆叠器
  • 估计值:最终估计值

现在让我们来评估这个模型:

opt.evaluate(params, df)

原创博文

运行此管道导致了更高的 neg 损失,这是更好的。

如果我们定义一个更好的搜索或堆叠操作空间,也许还有其他的特征选择技术,就有很大的潜力可以进一步改进。

5-运行预测

现在,我们拟合最佳管道并预测我们的测试数据集。

更多详情请点击:https://ml box . readthe docs . io/en/latest/features . html # ml box . prediction . predictor

6 —结论

运行自动化 AutoML 管道从未如此简单。使用 MLBox,您可以快速高效地完成这项工作,以便在解决业务问题时可以专注于重要的事情。

  • 理解问题
  • 获取和整合正确的数据
  • 形式化性能指标以达到和计算

让我们希望这三个第一步不会很快自动化:)

我们希望你喜欢这个图书馆。不要犹豫,在 G ithub 上给它一颗星,或者向它的贡献者报告一个问题

新到中?你可以每月订阅 5 美元,并解锁各种主题的无限文章(技术、设计、创业……)你可以通过点击我的推荐链接来支持我

https://ahmedbesbes.medium.com/membership

Unsplash 上的 Karsten Winegeart 拍摄

基于 ML 技术的时间序列自动模型描述

原文:https://towardsdatascience.com/auto-model-specification-with-ml-techniques-for-time-series-e7b9a90ae9d7

如何使用 Python 库 scalecast 自动选择时间序列的最佳趋势、季节和自回归表示

照片由杰克·希尔斯Unsplash 拍摄

根据所采用的模型,有几种方法可以找到时间序列的最佳模型规格。对于 arIMA 模型,一种流行的方法是在搜索不同的 AR、I 和 MA 订单时监控信息标准。这已经被证明是一种有效的技术,流行的库 RPython 提供了自动 ARIMA 模型供用户试验。类似的方法可以用于其他经典的统计时间序列方法,如霍尔特-温特斯指数平滑和 TBATS。

对于机器学习模型来说,它可以稍微复杂一些,除了复杂的深度学习模型(如 N-BeatsN-HiTS 和其他几个),没有多少自动化的纯 ML 方法持续优于经典模型(Makridakis 等人,2020)。

Python 库 scalecast 提供了一个名为 [auto_Xvar_select()](https://scalecast.readthedocs.io/en/latest/Forecaster/Forecaster.html#src.scalecast.Forecaster.Forecaster.auto_Xvar_select)函数,可以使用来自 scikit-learn 的模型自动选择任何给定系列的最佳趋势、季节性和回望表示(或滞后)。

pip install --upgrade scalecast

该函数的工作方式是首先搜索时间序列给定趋势的理想表示,然后是季节性,然后是回望,所有这些都是分别进行的。“理想”在这种情况下意味着使用选定的模型(默认为多元线性回归,或 MLR)最小化一些样本外误差(或最大化 R2)。在分别找到这些中的每一个之后,搜索所有上述表示的理想组合,并选择考虑不规则周期和用户认为合适的其他回归量。

按作者分类的图片 scalecast 如何使用 auto_Xvar_select()函数为预测模型自动选择回归量

这是一个有趣的功能。当应用于 M4 竞赛的 100,000 系列时,它返回具有不同准确度的结果,这取决于系列的频率。对于每小时频率组,使用 KNN、LightGBM 和 XGBoost 模型均可获得低于 0.6 的 OWA,其中使用默认 MLR 模型搜索这些模型的表示。就背景而言,这意味着这些模型的表现有望超过一个简单的模型,其季节性调整平均超过 40%(1–0.6)。这是一个非常可靠的结果,与 sktime 在同一系列中使用纯 ML 方法发布的结果相当(Loning 等人,2019)。

**# evaluate the hourly series
for** i **in** tqdm(Hourly**.**index):
    y **=** Hourly**.**loc[i]**.**dropna()
    sd **=** info**.**loc[i,'StartingDate']
    fcst_horizon **=** info**.**loc[i,'Horizon']
    cd **=** pd**.**date_range(
        start **=** sd,
        freq **=** 'H',
        periods **=** len(y),
    )
    f **=** Forecaster(
        y **=** y,
        current_dates **=** cd,
        future_dates **=** fcst_horizon,
    )

    f**.**set_test_length(fcst_horizon)
    f**.**integrate(critical_pval**=**.99,max_integration**=**1)
    f**.**set_validation_length(fcst_horizon)
    f**.**set_validation_metric('mae')
    **if** len(f**.**y) **>** 300:
        f**.**auto_Xvar_select(
            monitor**=**'LevelTestSetMAE',
            max_ar **=** 48,
            exclude_seasonalities **=** [
              'quarter',
              'month',
              'week',
              'day',
            ]
        )
        f**.**determine_best_series_length(
            monitor**=**'LevelTestSetMAE',
            step**=**50,
            min_obs **=** 300,
        )
    **else**:
        f**.**auto_Xvar_select(
            monitor**=**'LevelTestSetMAE',
            irr_cycles **=** [168], *# weekly*
            exclude_seasonalities **=** [
              'quarter',
              'month',
              'week',
              'day',
              'dayofweek',
            ],
            max_ar **=** 24,
        )
    f**.**tune_test_forecast(
        models,
        error**=**'ignore',
    )

查看用于在 M4 系列此处运行所有带有 scalecast 的模型的笔记本,以及用于在相同过程中评估每个模型性能的笔记本此处

我的问题是,在auto_Xvar_select()函数中使用不同于缺省值的估计量是否能导致持续更好的结果。以这种方式搜索模型规格可能很耗时,但使用 MLR 来做通常不会使事情变慢太多,这就是为什么它是该功能的默认设置。

不幸的是,这是一个漫长的过程来充分研究。为了简化流程,我将模型限制为:

  • 多元线性回归
  • 弹性网
  • 梯度增强树(GBT)
  • k-最近邻(KNN)
  • 支持向量机
  • 多级感知器(MLP)

这些模型中的每一个都被用来寻找代表和预测,尝试了所有的组合。我也只对每个模型使用默认参数,尽管我相信用网格搜索来调整它们可以显著提高性能。最后,我只使用了从小时组的 414 个系列中随机选择的 50 个样本。即使做了这些修改,这个过程在我的 Windows 电脑上运行了 17 个多小时。由此产生的预测通过各自的平均对称平均绝对百分比误差(SMAPE) 性能进行评估,这是 M4 竞赛中用于评估模型的指标之一。在这里找到完整的笔记本。

for i in tqdm(Hourly.index):
    y = Hourly.loc[i].dropna()
    sd = info.loc[i,'StartingDate']
    fcst_horizon = info.loc[i,'Horizon']
    cd = pd.date_range(
        start = sd,
        freq = 'H',
        periods = len(y),
    )
    f = Forecaster(
        y = y,
        current_dates = cd,
        future_dates = fcst_horizon,
    )
    f.set_test_length(fcst_horizon)
    f.integrate(critical_pval=.99,max_integration=1)
    for xvm in models:
        for fcstm in models:
            f2 = f.deepcopy()
            f2.auto_Xvar_select(
                estimator = xvm,
                monitor='LevelTestSetMAE',
                max_ar = 48,
                exclude_seasonalities = [
                  'quarter',
                  'month',
                  'week',
                  'day'
                ],
            )
            f2.set_estimator(fcstm)
            f2.proba_forecast(dynamic_testing=False) if fcstm in (
                'mlp','gbt','xgboost','lightgbm','rf'
            ) else f2.manual_forecast(dynamic_testing=False)
            point_fcst = f2.export('lvl_fcsts')[fcstm]
            results.loc[xvm,fcstm] += metrics.smape(
                Hourly_test.loc[i].dropna().to_list(),
                point_fcst.to_list(),
            )

这引出了几个值得观察的有趣观点:

  • 在衡量实际预测准确性时,KNN 和 GBT 模型始终优于其他模型,无论哪个模型用于搜索最佳序列表示。这并不奇怪,因为这些是整个 M4 每小时系列中表现最好的车型。
  • 表现最差的模型是 SVR、ElasticNet 和 MLP,最好的模型和最差的模型平均相差 60.8(!!)个百分点。
  • 在寻找理想的系列表现方面最好的模型是 ElasticNet 和 MLP,在这方面最好的和最差的模型之间只有 4 个百分点的差距。
  • 平均而言,表现最好的模型组合是 KNN 模型和 MLP 模型。

作者图片

因此,从该实验中可以看出,用于进行预测的模型比用于寻找理想表示的模型对获得高精度更重要。不过,这两方面的最佳模式似乎也是相互颠倒的。寻找表征的最佳模型在预测方面表现不佳,反之亦然。弱估计量可能更依赖于找到理想的趋势、季节性和回顾性,甚至有机会做出好的预测,因此将弱估计量与强估计量结合起来找到最佳表示以实际做出预测是一个好主意。但是,这只是一个想法,还需要更多的研究来证实。

结论

很难找到一种完全自动化的机器学习技术来预测持续优于经典统计方法的情况。很多时候,最好的结果来自于不同的最大似然估计的组合。在这种情况下,我发现使用较弱的模型来寻找给定序列的理想趋势、季节性和回望表示,并将该表示与较强的模型相结合来进行预测,通常会在我测试的小时序列样本上获得最佳结果。所有这些方法都用样本外数据进行了测试,scalecast 软件包提供了一个非常简单的界面来执行这种分析。

链接

作品引用

马库斯·洛宁、安东尼·巴格纳尔、萨贾苏亚·加内什、维克多·卡萨科夫、杰森·莱恩斯和弗朗兹·基拉里。sktime:时间序列机器学习的统一接口。更正,abs/1909.07872,2019。网址http://arxiv.org/abs/1909.07872.

斯皮罗斯·马克里达基斯、伊万杰洛斯·斯皮里奥蒂斯和瓦西里奥斯·阿西马科普洛斯。M4 竞赛:100,000 个时间序列和 61 种预测方法。国际预测杂志,36(1):54–74,2020。doi:10.1016/j . ijforecast . 2019 . URLhttps://ideas.repec.org/a/eee/int for/v36y 2020 i1p 54–74 . html

时间序列分析的自相关

原文:https://towardsdatascience.com/autocorrelation-for-time-series-analysis-86e68e631f77

描述什么是自相关,为什么它在时间序列分析中有用。

艾萨克·史密斯在 Unsplash 上拍摄的照片

介绍

在时间序列分析中,我们经常对过去进行推断,以预测未来。为了使这一过程成功,我们必须彻底诊断我们的时间序列,找到它所有的“角落和缝隙”

其中一种诊断方法是 自相关 。这有助于我们检测系列中的某些特征,从而为我们的数据选择最佳预测模型。

在这篇短文中,我想回顾一下:什么是自相关,它为什么有用,以及如何在 Python 中将它应用于一个简单的数据集。

什么是自相关?

自相关只是数据与自身的https://en.wikipedia.org/wiki/Correlation。因此,我们不是测量两个随机变量之间的相关性,而是测量一个随机变量自身之间的相关性。于是,为什么叫 自动——关联。

相关性是指两个变量之间的相关程度。如果值为 1,变量完全正相关,-1,它们完全负相关,0,没有相关性。

对于时间序列,自相关是时间序列在两个不同时间点的相关性(也称为滞后)。换句话说,我们是在用时间序列的滞后版本来衡量它。

数学上的,自相关计算为:

作者方程式来自 LaTeX。

其中 N 为时间序列的长度yk为时间序列的指定滞后。所以,在计算 r_1 的时候,我们是在计算 y_ty_{t-1}之间的相关性。

y_ty_t 之间的自相关将是 1 ,因为它们是相同的。

为什么有用?

如上所述,我们使用自相关来衡量时间序列与其自身滞后版本的相关性。这种计算让我们对我们系列的特征有了一些有趣的了解:

  • https://www.investopedia.com/terms/s/seasonality.asp:假设我们发现某些滞后倍数的相关性通常高于其他倍数。这意味着我们的数据中有一些季节性成分。例如,如果我们有每日数据,并且我们发现 7 滞后项的每个倍数都比其他的高,我们可能有一些周季节性。****
  • 趋势 : 如果最近滞后的相关性较高,并且随着滞后的增加而缓慢下降,那么我们的数据中存在某种趋势。因此,我们需要进行一些差分来呈现时间序列https://otexts.com/fpp2/stationarity.html****

要了解更多关于季节性、趋势和平稳性的知识,请查看我以前关于这些主题的文章:

*******

现在让我们通过 Python 中的一个例子来使这个理论更加具体!

Python 示例

在本演练中,我们将使用经典的航空客运量数据集:

数据来自拥有 CC0 许可证的 Kaggle

作者代码要点。

作者用 Python 生成的图。

有明显的上升趋势和年度季节性(数据点按月索引)。

我们可以使用 statsmodels 包中的 plot_acf 函数来绘制我们的时间序列在不同滞后下的自相关,这种类型的图称为相关图:

作者代码要点。

作者用 Python 生成的图。

我们观察到以下情况:

  • 在每倍数个 12 的滞后中有一个清晰的周期模式。由于我们的数据是按月索引的,因此我们的数据中有一个年度季节性
  • 相关性的强度通常随着滞后的增加而缓慢下降。这在我们的数据中指出了一个趋势,在建模时需要对其进行差分以使其稳定。

蓝色区域表示哪些滞后是 统计上显著的 。因此,在为该数据建立预测模型时,下个月的预测可能只考虑前一个值的 ~15 ,因为它们具有统计意义。

值为 0 的滞后具有 1 的完美相关性,因为我们将时间序列与其自身的精确副本相关联。

总结和其他想法

在这篇文章中,我们描述了什么是自相关,以及我们如何用它来检测时间序列中的季节性和趋势。然而,它还有其他用途。例如,我们可以使用预测模型的 残差 的自相关图来确定残差是否确实独立。如果残差的自相关是而不是几乎为零,那么拟合的模型没有考虑所有信息,并且可能可以改进。

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

https://github.com/egorhowell/Medium-Articles/blob/main/Time Series/Time Series Tools/autocorrelation.py

参考资料和进一步阅读

和我联系!

(所有表情符号都是由 OpenMoji 设计的——开源的表情符号和图标项目。许可证: CC BY-SA 4.0*******

自动编码器(AE)——一种使用无监督神经网络处理数据的智能方法

原文:https://towardsdatascience.com/autoencoders-ae-a-smart-way-to-process-your-data-using-unsupervised-neural-networks-9661f93a8509

神经网络

什么是 Autoencoder,如何用 Python 构建一个?

欠完整自动编码器。图片由作者、使用 AlexNail 的 NN-SVG 工具创建。

介绍

自动编码器提供了一种有效的方式来学习数据的表示,它侧重于信号,而不是噪声。您可以将它们用于各种任务,例如:

  • 降维
  • 特征抽出
  • 数据/图像去噪
  • 输入缺失数据

本文将简要介绍自动编码器(AE),并深入探讨一种称为的特定类型,Undercomplete Autoencoder ,适用于降维和特征提取。

同时,我未来的文章将涵盖其他种类,如变分去噪稀疏自动编码器。所以,订阅不要错过我以后的任何帖子。

内容

  • 自动编码器在机器学习算法领域中的地位
  • 自动编码器是如何构造的,它们是如何工作的?
  • 一个完整的 Python 示例,展示了如何使用 Keras/Tensorflow 在 Python 中构建自动编码器。

自动编码器在机器学习领域的地位

下面的图表是我对最常见的机器学习算法进行分类的尝试。

虽然我们经常以监督的方式使用带有标签的训练数据的神经网络,但我们也可以以非监督或自我监督的方式使用它们,例如通过使用自动编码器。因此,我觉得神经网络的普遍性和它们对机器学习的独特方法值得一个单独的类别。

下图是互动,所以请点击不同的类别放大并展示更多👇。

机器学习算法分类。由作者创建的互动图表。

如果你喜欢数据科学和机器学习 ,请 订阅 获取我的新文章的邮件。如果你不是中等会员,可以在这里 加入

自动编码器是如何构造的,它们是如何工作的?

让我们从下图中显示的高级视图开始,查看每个部分。

自动编码器神经网络中各层的高级图示。图片由作者提供。

  • 自动编码器具有类似于其他类型的神经网络的输入、隐藏和输出层。
  • 自动编码器的隐藏层包含两个重要部分:编码器解码器
  • 自动编码器中的输出节点与输入节点相匹配。因此,自动编码器神经网络试图重新创建它在输入层接收到的相同特征值。
  • 因为我们试图重建(预测)特征本身,所以我们不需要带标签的目标数据。因此,我们可以将自动编码器称为无监督模型,尽管一些文献将它们称为自监督模型。

自动编码器的类型

每层中节点数量之间的关系决定了自动编码器的类型,例如:

  • 欠完整自动编码器(本文的重点)——与输入和输出层相比,中间的节点(维度)较少。在这样的设置中,我们倾向于称中间层为“瓶颈”
  • 过完全自动编码器 —与输入和输出层相比,中间有更多的节点(维度)。

有什么意义?

关键问题是,为什么我们要通过神经网络传递数据,以获得与我们作为输入输入到网络中的输出值相同的输出值?

在欠完整自动编码器的情况下,我们将信息压缩到更少的维度中(因此成为瓶颈),同时试图确保我们仍然可以回到原始值。因此,我们正在创建一个压缩数据的自定义函数,这是一种降低维度并提取有意义信息的方法。

在训练欠完整自动编码器之后,我们通常丢弃解码器并且只有使用编码器部分。

现在,让我们使用 Keras functional API 在 Python 中构建一个 Autoencoder 来实现这些例子。

如何用 Python 构建 Autoencoder?

我们将构建一个欠完整的自动编码器,它有 17 个输入和输出节点,我们在“瓶颈”层将它们压缩到 8 个。这是我们将要创建的神经网络的层和连接的图形:

欠完整自动编码器。图片由作者,使用 AlexNail 的 NN-SVG 工具创建。

设置

我们需要获得以下数据和库:

让我们导入库:

上面的代码打印了我在这个例子中使用的包版本:

Tensorflow/Keras: 2.7.0
pandas: 1.3.4
sklearn: 1.0.1
matplotlib: 3.5.1
graphviz: 0.19.1

接下来,下载并摄取澳大利亚的天气数据(来源: Kaggle )。此外,我们执行一些简单的数据操作,并派生出一个名为“RainTodayFlag”的附加变量。

一小段 Kaggle 的澳大利亚天气数据做了一些修改。图片由作者提供。

对于最后的数据准备步骤,我们将把数据添加到一个数组中,应用最小-最大缩放,并把它分成训练和测试样本。

建立并训练一个自动编码器模型

我们将使用功能性的 Keras API,它允许我们在定义模型结构时有更大的灵活性。它还可以在训练模型后轻松丢弃解码器部分,仅保留编码器部分。

下面的代码组装了模型并打印出摘要和图表。我们的 X_train 数据中的特征数量是 17。因此,我们将有 17 个输入节点和 17 个输出节点。隐藏层将由编码器和解码器组成,每个编码器和解码器有 17 个节点,瓶颈有 8 个节点。

上面的代码打印了两项内容。第一个是模型总结:

自动编码器型号摘要。图片由作者提供。

第二部分是看待模型结构的一种略微不同的方式,有些人更喜欢这种方式:

自动编码器模型图。图片由作者提供。

请注意,我们使用了批处理归一化,它应用了一个变换,使平均输出接近 0,输出标准偏差接近 1。虽然这不是强制性的,但它通常有助于模型性能。

组装好模型后,让我们对其进行十个时期的训练,并绘制损失图。

自动编码器按历元的模型丢失。图片作者作者

我们可以看到,我们的自动编码器模型能够以最小的损失重建数据。

最后一部分将编码器和解码器分离,并保存模型。

编码器模型图。图片由作者提供。

如果需要,您也可以通过在新的解码器模型中更改inputs = bottlneckoutputs = output以同样的方式保存解码器部分。

无论何时您想要使用编码器模型,您都可以加载它,并以如下所示的方式应用它,它采用 17 个特征(维度)并将其减少到 8 个:

结束语

您已经学习了如何构建、训练和保存自动编码器模型。您可以通过多种方式使用它,从对数据执行降维到提取用于监督模型训练的要素。

为了您的方便,我在我的 GitHub 库中保存了一个 Jupyter 笔记本,它构建了一个自动编码器模型,并使用编码的功能来训练一个受监督的天气预测模型。

我真诚地希望这篇文章对你有所帮助。如果您有任何问题或建议,请随时联系我们。

干杯!🤓
索尔·多比拉斯

通过以下我的个性化链接加入 Medium,继续您的数据科学学习之旅

*https://bit.ly/3ueQFbR *

自动编码器:从普通到变化

原文:https://towardsdatascience.com/autoencoders-from-vanilla-to-variational-6f5bb5537e4a

因为甘不是你需要的全部

当你听到计算机生成的图像时,你可能会想到深度假货、不存在的猫或马变成的斑马。这很合理地让你想起了甘斯。但是,即使这些模型在生成逼真的图像方面取得了巨大的成功,它们也有缺点,而且决不是全部。自动编码器,GANs 的老兄弟,还没有过时。事实上,现在自动编码器领域正在进行一些热门研究。所以不要把自动编码器一笔勾销!相反,请继续阅读,了解他们!

你需要的不仅仅是甘

当谈到计算机视觉中的生成建模时,GANs 是所有的炒作。这是功不可没的:他们发现了许多令人惊叹的应用,在这些应用中,他们生成了高保真图像。但是看穿了炒作就暴露了一些不足。

gan 很难训练:训练不稳定,他们遭受模式崩溃(最终一次又一次地产生相同的图像),为你的数据找到正确的架构是具有挑战性的。简而言之,他们需要大量的保姆来让他们工作。

此外,gan 很难反转,这意味着从生成的图像到产生它的噪声输入没有简单的方法。如果想稍微增加生成的图像,这将是一个有用的特性。使用可逆生成模型,可以得到产生特定图像的输入,向正确的方向稍微扰动一下,结果得到非常相似的图像。

最后,GANs 不提供密度估计。也就是说,我们可以生成一幅图像,但是没有办法知道特定的特征出现的可能性有多大。例如,如果我们对异常检测感兴趣的话,那就太好了。如果我们有一个生成模型,可以告诉我们一只可能的猫和一只不可能的猫是什么样子,我们就可以将这些密度估计传递给下游的异常检测任务。

gan 产生高质量的图像。不幸的是,它们在训练中需要很多看护,不可逆,并且不提供密度估计。

自动编码器(AEs)是一种替代方案。它们相对快速且易于训练,具有可逆性和概率性。AE 生成的图像的保真度可能还没有 GANs 的好,但这不是将它们一笔勾销的理由!

自动编码器没有死

有人说,GANs 一出现,自动编码器就过时了。这在某种程度上是正确的。但是他们现在正在卷土重来。

人们已经意识到 GANs 的缺点,并承认它们并不总是最合适的模型。目前有一些关于自动编码器的令人兴奋的研究正在进行。

例如,一种被称为矢量量化变分自动编码器(VQ-VAE) 的自回归 AE 声称可以产生与 GAN 的质量相匹配的图像,同时不会遭受 GAN 的已知缺点,如模式崩溃和缺乏多样性。

图 5 的一部分来自“用 VQ-VAE-2 生成多样的高保真图像”(链接: arXiv:1906.00446 )

在本文中,作者通过生成渔民图像,将他们的 AE 模型与 DeepMind 的 BigGAN 进行了比较。请注意在声发射产生的图像中有多少变化。

自动编码器领域另一个令人兴奋的研究例子是的和甘的 T5。这种混合模型使用 GAN 的鉴别器在典型的对抗训练中所学到的知识来提高 AE 的生成能力。

图 4 的一部分来自“使用学习的相似性度量对像素之外的内容进行自动编码”(link: arXiv:1512.09300)

在上图中,作者使用他们的模型从学习的表征中重建了一组图像,这是 GAN 无法做到的,因为它缺乏我们已经讨论过的可逆性。重建看起来很不错,不是吗?

我相信自动编码器还没有以某种方式在图像生成中发挥作用,熟悉它们当然很好。

自动编码器尚未在图像生成中发挥作用。

在本文的剩余部分,我们将看看自动编码器是如何工作的,有哪些不同类型的自动编码器,以及如何使用它们。我们还将使用 TensorFlow 训练一些人。

使用自动编码器的表征学习

自动编码器都是为了有效地表示数据。他们的工作是找到这样一种高维输入的低维表示,它允许重建原始输入而不丢失其内容。

从下图所示的快速绘图数据集中提取 ax 绘图。该图像为 28x28 灰度,这意味着它由 784 个像素组成。自动编码器将找到从这个 784 维空间到 2D 空间的映射,这样压缩后的 ax 图像将仅由两个数字描述:图上的 X 和 Y 坐标。接下来,只知道 X-Y 坐标,自动编码器将尝试从这两个值重建原始的 784 像素。

自动编码器学习其输入的低亮度表示。图片由作者提供。

重建不会是完美的,因为在压缩过程中一些信息不可避免地会丢失,但希望它足以识别原始图像。

我们示例中的地图是有效表示数据的潜在空间。虽然我们使用了 2D 地图进行说明,但实际上潜在空间通常会更大,但仍然比输入图像小得多。

自动编码器的工作是创建这样一个低维表示,让它重建原始输入。这确保该潜在空间压缩最相关的输入特征,并且没有噪声和对于要重建的输入不重要的特征。

Autoencoder 的潜在空间压缩最相关的输入特征,并且没有噪声和冗余特征。

这使得它在许多方面都很有吸引力。您可以使用自动编码器进行降维或特征提取(事实上,您可以构建一个数学上等同于主成分分析(PCA)的自动编码器)。只需用自动编码器在您可能运行的任何数据管道中学习的低维度表示替换您的高维度数据。

自动编码器还有许多其他应用。它们可以用于图像去噪:只需输入一个有噪声的图像,让自动编码器重建原始的无噪声图像。它们还用于自我监督的预训练,在这种训练中,模型从一大组未标记的数据中学习图像特征,然后在一小组标记数据上为一些监督任务进行微调。最后,自动编码器可以用作生成模型,这将是本文的主要焦点。

自动编码器可用于降维、特征提取、图像去噪、自我监督学习,以及作为生成模型。

标准自动编码器

让我们把手弄脏吧!我们将为谷歌游戏“快,画!”的玩家制作的手绘形状的 quickdraw 数据集构建一个简单的自动编码器。我们将只使用三类图像:狗、猫和树。这是一个图像样本。

数据样本。来源:https://github.com/googlecreativelab/quickdraw-dataset

训练自动编码器

那么,我们如何构建一个自动编码器呢?它需要由两部分组成:编码器,它获取输入图像并将其压缩成低亮度的表示;解码器,它做相反的事情:从潜在的表示开始,它产生原始大小的图像。

让我们从编码器开始。因为我们要处理图像,所以我们将在网络中使用卷积层。该模型将输入图像依次通过卷积层和最大池层,以便将它们压缩成低维表示。

这种特殊的架构是基于 Aurélien Géron 在他的书《FashionMNIST 数据集》中使用的架构。如果你好奇为什么我们使用 SELU 激活而不是 ReLU,看看我关于这个话题的帖子

我们的编码器的输出由 64 个特征图组成,每个特征图的大小为 3x3。这是我们对数据的低密度表示。接下来,我们需要一个解码器将这些小的表示处理成原始大小的图像。为此,我们可以使用转置卷积层,这可以看作是常规卷积的反面。他们放大图像,增加其高度和宽度,同时减少其深度或特征地图的数量。

剩下要做的就是将编码器和解码器连接起来,并将它们共同训练成一个自动编码器。请注意我们如何将训练数据作为特征和目标两次传递给 fit 方法。这是因为模型的工作是重构其输入。我们用二进制交叉熵损失为 20 个时期训练该模型。

关于损失函数再多说几句。这通常被选择为原始图像及其重建图像的单个像素之间的二进制交叉熵,如我们在这里所做的,或者均方根误差,或 RMSE。两者之间的主要区别在于,二进制交叉熵对大误差的惩罚更强,这导致将重建图像的像素值推入平均幅度。这反过来使得重建的图像不那么生动。然而,对于我们的灰度图像,损失函数的选择不应该产生任何有意义的差异。

分析自动编码器

让我们来看看测试集中的一些图像,以及它们被我们的自动编码器重建得有多好。

来自测试集的原始图像(顶行)与其重建图像(底行)。图片由作者提供。

看起来这个模型做得很好。一些细节模糊不清,但整体重建精度似乎相当体面。

另一种可视化 autoencoder 所学内容的方法是仅将一些测试图像传递给编码器。这将产生他们的潜在表现,在我们的例子中是大小(3,3,64)。然后,我们可以使用 t-SNE 等降维算法将它们映射到二维空间,并绘制一个散点图,用它们的标签(猫、狗或树)给这些点着色。

t-SNE 映射到 2D 的测试图像的潜在表征。图片由作者提供。

我们可以清楚地看到,树木与其余的图像分离得很好,而猫和狗有点混淆。注意底部的大块蓝色区域。这些是猫的头部图像,典型的特征是胡须,正如你在散点图顶部绘制的示例图像中所看到的。这些没有和狗混为一谈。然而,在图的上部,我们看到了从侧面拍摄的动物,这使得区分猫和狗变得更加困难。令人着迷的是,autoencoder 在没有给定标签的情况下已经了解了多少图像的类别!

自动编码器可以在没有标签的情况下学习很多关于图像类的知识。

总结我们对 vanilla autoencoder 的分析,似乎该模型已经学会了数据的有意义的潜在表示。但是让我们回到这篇文章的主题:它能作为一个生成模型吗?

作为生成模型的标准自动编码器

让我们从断言我们期望从生成模型中得到什么开始。我们希望能够选择潜在空间中的任何随机点,通过解码器,获得逼真的图像。最重要的是,在潜在空间中选择不同的随机点应该会产生不同的生成图像,这些图像应该涵盖模型已经看到的所有类型的数据:猫、狗和树。

从潜在空间取样

当我们在潜在空间中随机选择一个点时,第一个问题就出现了。在这种情况下,“随机”是什么意思?它应该来自正态分布还是均匀分布?分布应该如何参数化?下图显示了对测试数据样本进行编码后,潜在空间值的概率密度。

潜在空间值的概率密度。图片由作者提供。

我也算了一些汇总统计。潜在空间值最小为-1.76,最大为 22.35。对于随机采样点,将潜在空间对称地集中在零周围,或者至少以某种方式有界,会容易得多;这里,大的正值和大的负值都可能出现。

潜在空间值形成一个不规则的、无界的分布,使得很难对随机点进行采样。

图像多样性

另一个问题是潜在空间中代表个体类别的区域,这影响了生成图像的多样性。

我们的潜在空间是 3x3x64 的形状,这使得它是 576 维的,无法可视化。为了便于解释,让我们关注第一维的 3D 切片,它的形状是 3x1x1。当只考虑这个切片时,每个图像在一个潜在空间中由一个 3D 矢量表示,我们可以将它可视化为一个散点图。这是一个测试数据样本的图,用。地面实况课。

测试数据嵌入的 3D 子集。图片由作者提供。

请注意蓝点云是如何分布在比红蓝云小得多的体积上的。这意味着,如果我们从这个空间中随机选取一个点,我们更有可能得到一只猫或一只狗,而不是一棵树。在极端情况下,当考虑潜在空间的所有 576 个维度时,我们可能永远不会对一棵树进行采样,这违背了我们对生成模型能够覆盖它所看到的整个数据空间的要求。

不同图像类别的潜在表示在大小上可能不同,导致模型生成某些类别的频率比其他类别高得多。

再看一下散点图。你可能已经注意到一个从红绿点云中向上突出的尖峰。在这个尖峰信号中隐藏着一些图像。但是,如果我们从那里侧身,在云的正上方,但在尖峰旁边的一个点采样,会怎么样呢?从这个空白空间取样会产生真实的图像吗?让我们再多谈一点。

潜在空间中的有意义区域

在潜在空间的 3D 子空间中,图像嵌入通常被很好地聚类——可能除了点云顶部的红色和绿色尖峰。但是当我们添加更多的维度时,嵌入图像之间会出现更多的空白空间。我们整个 3x3x64 潜空间都是真空的。因此,当从其中随机采样一个点时,我们极有可能得到一个远离(在大多数维度上)任何特定图像的点。如果我们让这些随机选择的点通过解码器,会得到什么呢?答案是无形状的图案。

产生了猫、狗和树——算是吧。图片由作者提供。

为什么会这样?在猫和狗之间的一个点上取样难道不应该产生一个耷拉着耳朵和胡须的生物吗?

不幸的是,普通自动编码器学习的潜在空间不是连续的。这意味着在这个空间中的点之间没有意义的平滑过渡。事实上,即使是解码成格式良好的图像的点的小扰动也可能导致垃圾输出。

普通自动编码器学习的潜在空间是不连续的。

总而言之,我们已经看到了使用普通自动编码器作为生成模型的三个问题:我们不知道如何从不规则的无界空间中采样,一些类可能在潜在空间中比其他类表现得更多,最后,学习的空间是不连续的,这使得很难找到一个点来解码成格式良好的图像。

进入可变自动编码器。

变分自动编码器

变分自动编码器,或 VAE,通过引入随机性和限制潜在空间,从而更容易从中采样,解决了我们刚刚讨论的问题。

变分自动编码器在模型中引入了随机性,并限制了潜在空间。

要将我们的标准自动编码器转换成一个变化的编码器,我们只需要调整编码器部分和损失函数。先说前者。

可变编码器

变分编码器不是将输入图像映射到潜在空间中的一个点,而是将其映射到一个分布中。准确的说是多元正态分布。

多元正态分布是一元正态分布在更多维度上的扩展。正如单变量正态分布由两个参数(均值和方差)描述一样,多变量正态分布由两个参数向量描述,每个向量的长度等于维数。例如,2D 正态分布有两个平均值的向量和两个方差的向量。如果分布的许多维是相关的,则出现附加的协方差参数,但是在 VAEs 中,我们假设所有的维是独立的,这使得所有的协方差为零。

为了将输入图像编码成潜在空间中的低亮度表示,我们将从多元正态分布中对其进行采样,编码器将学习多元正态分布的参数(均值和方差)。

总之,我们的潜在空间将被描述为两个向量:均值向量和方差向量。让我们将这两个向量都设为 576 维,以匹配我们之前构建的普通编码器,它编码成 3x3x64=576 维空间。我们实际上可以重用我们的普通编码器。把它的输出变平,然后把两个向量连接起来。

这里只有两件事需要详细说明。首先,正如您可能从变量名中猜到的,我们使用方差的对数来描述我们的正态分布,而不是原样的方差。这是为了消除包含值:方差必须是正的,而对数方差可以是任何值。

第二,编码器使用自定义的Sampling层,该层根据平均值和对数变量从多元正态中采样一个点。让我们看看它是怎么做到的。

我们简单地取平均值并加上e^(log_var / 2)乘以ε,这是一个从标准正态分布中采样的值(平均值为零,方差为 1)。指数和除以 2 来自对数反转的简单推导——我们有对数方差,但需要方差。如果你对细节感兴趣,请在评论中告诉我。

为什么变分编码器工作

酷,我们有我们的变分编码器!本质上,与普通编码器相比,我们已经用将输入映射到某个空间内的随机点来代替将输入映射到确定性点。为什么这样更好?

想想用一个可变的编码器重复映射同一个图像。每一次,我们都会在潜在空间中找到一个稍微不同的点,尽管它们都在平均值附近。这迫使 VAE 知道在解码时该邻域中的所有点应该产生相似的输出。这确保了潜在空间是连续的!

编码器中的随机化迫使潜在空间是连续的。

变分解码器

现在我们来看解码器。VAE 的这一部分不需要很多改变,我们也可以重用我们的老香草解码器。

唯一的区别是,现在编码器的输出,或潜在空间,是一个 1D 矢量,而不是三维张量。实际上,我们只添加了一个整形层,并将旧的解码器堆叠在上面。

我们现在可以结合变分编码器和解码器,以形成 VAE 模型。

变分损失函数

在普通自动编码器中,我们使用了二进制交叉熵损失,并提到均方根误差也是一种选择。在 VAEs 中,损失函数需要扩展。

交叉熵或 RMSE 损失是一种重建损失,它会因产生与原始输入不同的重建而对模型造成不利影响。

在 VAEs 中,我们在损失函数中增加了一项,它对学习与标准正态分布差异很大的多元正态分布的模型不利。我们通过在损失函数中增加一个 KL 散度来做到这一点。KL-divergence 是对两种分布差异的度量,在这种情况下,我们测量标准正态分布和模型学习到的正态分布之间的差异。也就是说,如果均值不等于零,方差不等于一,就会产生损失。

latent_loss的公式是在这种特殊情况下简化的 KL-divergence 公式,其中目标分布是标准正态分布,并且两者都没有零协方差。在将其添加到常规损失后,我们将其缩放为输入图像的大小,以确保其与重建损失具有相似的比例,而不是占主导地位。但是我们为什么要把这个 KL 部分加到损失里面呢?

首先,它使得在潜在空间中采样随机点变得简单。我们可以只从标准法线采样,并确保这个空间对模型有意义。第二,由于标准法线是圆形的,并且关于它的平均值是对称的,所以潜在空间中存在间隙的风险较小,当解码时,这些间隙会产生不成形的图案。

这样,我们就克服了普通自动编码器在图像生成方面的所有三个缺点。让我们训练我们的变分自动编码器并分析它。

分析变分自动编码器

我们可以再次将测试集中的原始图像与其重建图像进行比较。

来自测试集的原始图像(顶行)与其重建图像(底行)。图片由作者提供。

后者可能看起来比普通自动编码器更模糊,这是意料之中的。毕竟,我们已经调整了损失函数,不仅关注重建精度,还关注产生有意义的潜在空间。

图像之间的变形

我们可以做的一件很酷的事情是,选择两幅图像并在它们之间变形,以验证变分自动编码器学习到的潜在空间确实是连续的、行为良好的和有意义的。让我们以这只猫和这棵树为例。

一只猫和一棵树的样本图像。图片由作者提供。

我们可以对它们进行编码,以获得它们的隐藏表示,在我们的例子中,它们只是长度为 576 的向量,并在它们之间进行线性插值。然后,我们可以将插值线上的每个点传递给解码器,以生成猫和树之间的图像。

用于索引训练数据的数字是我们选择的两个图像的索引。我们将两个潜在的表示堆叠在形状为 2x576 的矩阵中,并对其列应用 scipy 的线性插值函数。因此,我们可以调用linfit([i+1 for i in range(10)])来获得中间插值。

一只猫变成了一棵树。图片由作者提供。

注意猫的嘴是如何变成树干的。以类似的方式,我们可以把另一只猫变成一只狗。注意猫的尖耳朵是如何逐渐变成狗的软耳朵的。

一只猫变成了一只狗。图片由作者提供。

这个有趣的实验表明,变分自动编码器学习的潜在空间是连续的,并确保点之间的平滑过渡。

VAE 的潜在空间是连续的,允许在图像之间生成有意义的插值。

图像算术

如果潜在空间是连续的和有意义的,我们应该能够在图像上做算术。我们试试吧!

考虑这两只猫(图片是重建的,而不是原始图像)。

猫的重建。图片由作者提供。

如果我们把左边有胡须的猫减去右边没有胡须的猫,会得到什么?当然,减法必须发生在潜在空间。

图像算术。

可以说,结果是类似胡须的东西。

包扎

我们已经看到了自动编码器如何学习数据的低维表示,以及这些潜在表示对于新图像的生成如何不完美,至少在普通自动编码器的情况下是这样的:它们学习的空间很难采样并且不连续。

我们还看到了变化的自动编码器如何通过向编码器引入随机性和增加损失函数来缓解这些问题,以加强学习连续和有意义的潜在空间,从而允许在图像之间进行算术和变形。

上面讨论的例子是在具有现成架构的玩具数据集上训练的。想象一下,当认真处理时,变分自动编码器是多么强大!

来源

  • Geron A .,2019,第二版,使用 Scikit-Learn 和 TensorFlow 进行机器学习:构建智能系统的概念、工具和技术,O'Reilly
  • Foster D .,2019,生成式深度学习。教机器绘画、写作、作曲和演奏,奥莱利

感谢阅读!

如果你喜欢这篇文章,为什么不在我的新文章上 订阅电子邮件更新 ?通过 成为媒介会员 ,你可以支持我的写作,并无限制地访问其他作者和我自己的所有故事。

需要咨询?你可以问我任何事情,也可以在这里 预定我 1:1

你也可以试试我的其他文章。不能选择?从这些中选择一个:

</8-tips-for-object-oriented-programming-in-python-3e98b767ae79> </6-useful-probability-distributions-with-applications-to-data-science-problems-2c0bee7cef28>

使用线性规划自动进行预算规划

原文:https://towardsdatascience.com/automate-budget-planning-using-linear-programming-5254aace697c

选择投资回报最大化的项目,遵循管理准则,同时遵守预算限制

线性规划的预算规划问题—(图片由作者提供)

目标

将国际物流公司的年度预算分配决策过程自动化

介绍

在物流行业,公司经常需要投资 IT 能力现代 搬运设备额外的仓库空间来提高他们的运营效率。

区域运营总监从当地团队收到中期项目的预算申请由于预算限制,他们需要决定组织将为哪些项目分配资源

花钱比赚钱难多了。—阿里巴巴集团联合创始人马云

在本文中,我们将使用 Python 设计一个简单的线性规划模型来自动化这个决策过程

  • 三年后每个项目的投资回报 (€)
  • 每年总成本和预算限额(€/年)

我们还将包括公司针对以下方面的最高管理准则…

  • 可持续发展 (二氧化碳减排)
  • 数字化转型 (物联网、自动化和分析)
  • 卓越运营(生产力、质量和持续改进)

💌新文章直接免费放入你的收件箱:时事通讯

**SUMMARY**
**I. Scenario: Budget Planning Process** As a Regional Director you need to allocate your budget on projects
**II. Build your Model
1\. Exploratory Data Analysis** Analyze the budget applications received
**2\. Linear Programming Model**
Decisions variables, objective function and constraints**3\. Initial Solution: Maximum ROI** What would be the results if you focus only on ROI maximization?
**4\. Final Solution: Management Guidelines
III. Conclusion & Next Steps**

如果你喜欢看,看看 Youtube 教程

一.情景

问题陈述

作为一家国际物流公司区域总监,你要负责四个国家的物流运作。

您负责的 56 个项目—(图片由作者提供)

你的团队管理着 48 个客户的运营,这些客户更多的而不是 8 个垂直市场(奢侈品、化妆品……)。

对于 17 个仓库中的每一个、仓库经理(向您汇报)列出了所有需要资本支出(CAPEX)的项目。

在申请表中,他填写了所有有助于证明这项投资(经济上)合理性的信息

  • 该项目将惠及哪个客户
  • 每年的预计成本是多少(€)?
  • 三年后【M€】预计投资回报率是多少?****

他还可以加上与公司长期战略相关的所有非财务结果。

资本支出申请表信息示例—(图片由作者提供)

例如,一个项目可以为可持续发展企业社会责任** (CSR) 或**数字化转型做出贡献。****

目标 找到正确的预算分配使最大化你的利润(ROI)尊重最高管理层的指导方针

(图片由作者提供)

因为您负责 58 个项目,所以让我们构建一个简单的工具来自动化这个决策过程。

二。构建您的模型

我们将使用 python 的纸浆库,这是一个线性(LP)和整数规划(IP)问题的建模框架。

你可以在我的 Github(跟随我:D)资源库中找到带有虚拟数据的完整代码:链接
我的投资组合与其他项目:萨米尔萨奇

1.探索性数据分析

今年,您总共有 58 个项目涵盖 9 个垂直市场

(图片由作者提供)

由于仓库扩建项目,汽车和豪华市场占据了预算分配的很大一部分。****

(图片由作者提供)

大多数项目都与业务发展有关,即给公司带来额外的营业额(和利润)

(图片由作者提供)

2.线性规划问题

让我们使用类比线性规划模型的定义来构建一个模型。

(图片由作者提供)

决策变量

(图片由作者提供)

目标函数

你的目标是使你选择的项目组合的总投资回报率最大化

(图片由作者提供)

预算限制(约束)

你的预算是450 万€** 分三年**(€125 万,€150 万,€175 万)。****

(图片由作者提供)

战略目标(约束条件)

(图片由作者提供)

我们将把三大支柱的最低预算定为 100 万€

3.初始解决方案:最大化投资回报率

为了理解这种模式的附加值,让我们来看看如果我们去除战略目标约束会有什么分配。

**Return of Investment = **1,050,976 Euros**
**36**/58 Projects Accepted with a Budget Allocation of **4.07/4.5 M€****

结果是令人满意的,有良好的投资回报率和超过 80%的预算分配。

按战略目标分配呢?

(图片由作者提供)

当你要求模型关注盈利能力时,你达不到管理目标

4.最终解决方案

如果我们对公司长期战略的关键支柱有最低预算分配的要求:

**Return of Investment = **909,989 Euros**
**34/58** Projects Accepted with a Budget Allocation of **4.15/4.5 M€****

投资回报受轻微影响

管理目标呢?

(图片由作者提供)

管理方针得到了的尊重。

三。结论和下一步措施

关注我的 medium,了解更多与供应链数据科学相关的见解。

结论

这个简单模型提供了自动化决策制定的能力,同时确保符合分配。

它可以很容易地通过添加约束来改进

  • 每个国家、垂直市场或仓库的最大预算分配
  • 预算分配目标(应分配 95%的预算)

后续步骤

这个脚本可以在一个 Flask web 应用中实现,并部署一个上传 excel 文件的功能。

然后,您可以自动化这一复杂的流程,帮助经理获得更多的视觉洞察力,并加快决策过程。

关于我

让我们连接上 LinkedinTwitter ,我是一名供应链工程师,正在使用数据分析来改善物流运营和降低成本。

如果你对数据分析和供应链感兴趣,可以看看我的网站

****https://samirsaci.com ****

参考

[1]运筹学计算基础设施,优化与纸浆(文档),链接

使用 Python 自动组合 Excel 工作表

原文:https://towardsdatascience.com/automate-excel-worksheets-combination-with-python-181052177baf

使用 PYWIN32 实现自动化

用 Python 将多个 Excel 工作簿和多个工作表合并,并保持格式

Artem MilitoníanUnsplash 上拍照

这是我的创造力(懒惰)对重复任务的另一种自动化。所以,我被要求根据文件名中的日期组合几个 Excel 工作簿 。一开始,我非常乐观,因为使用 Python 这个任务很简单。我需要做的就是用pandas读取文件,然后使用神奇的append方法,然后保存到一个新文件。搞定了。

不幸的是,这个计划没有成功,因为所有的 Excel 工作簿内部都有多个工作表,并且根据工作表中的值有一些预设的格式。好了,图片说话比较好,练习册看起来像下图。

工作簿示例。作者 GIF。

所以格式设置得很好,使用pandas合并它们会删除所有格式,这是不可接受的。有一秒钟我想我会遵循 KISS(保持简单愚蠢)方法,即打开每个 Excel 工作簿,一个一个地复制和粘贴。但是,处理速度快死我了🤦‍♂️.

我将再次使用我最喜欢的 Python 库来完成这个自动化任务,它是✨ PyWin32 ✨

25 个练习册将在后面的示例中合并。图片作者。

对于本教程,准备了 25 个 Excel 工作簿,每个工作簿只有一个工作表(由 Python 脚本生成)。这些工作簿包含 2019 年 5 月至 9 月马来西亚选定州的每个分公司的利润信息,如下图所示。

每个工作簿的内部外观。图片作者。

工作簿按照以下格式命名: 。xlsx,而工作表的命名遵循以下格式: _

每个工作表都有如下预设格式:

  1. 自动过滤
  2. 自动调整
  3. 条件格式

在本文中,将演示两种类型的 Excel 工作表的复制粘贴:

  1. 复制整个 Excel 表格并将其作为新工作表粘贴到另一个 Excel 工作簿中
  2. 复制一个 Excel 工作表的数据表并粘贴到另一个 Excel 工作表的现有数据表的下方

最后但同样重要的是,我将在下面的每个示例中频繁地提到类似对象、方法或属性这样的词。我曾经写过一篇文章(使用 Python 实现 Excel 的自动化)来解释对象、方法或属性的概念。我亲爱的读者是鼓励和欢迎阅读文章每当他们有疑问的三个概念。

开始吧!

A.复制整个 Excel 工作表并将其作为新工作表粘贴到另一个 Excel 工作簿中

您可以观看视频或继续阅读本部分。

1 .将一个工作簿中的一个工作表复制/合并到另一个现有工作簿中

此示例将演示如何将一个工作表从一个工作簿复制到另一个现有工作簿。

import win32com.client as win32
from pathlib import Path
win32c =  win32.constants**# create excel object**
excel = win32.gencache.EnsureDispatch('Excel.Application')**# excel can be visible or not**
excel.Visible = True  # False

第一步是导入库并创建 Excel 对象。然后,我们将打开相关的工作簿。

**# open workbooks**
f_path = Path.cwd() # your path
f1_name = 'Penang 20190901.xlsx'
f2_name = 'Sabah 20190901.xlsx'
filename1 = f_path / f1_name
filename2 = f_path / f2_name
wb1 = excel.Workbooks.Open(filename1)
wb2 = excel.Workbooks.Open(filename2)
sheetname = "Penang_9"

在本例中,我们将名为“Penang_9”的工作表从“Penang 20190901.xlsx”复制到名为“Sabah 20190901.xlsx”的现有工作簿中。打开工作簿后,我们可以开始复制工作表的操作。

**# copy worksheet above from wb1 to wb2**
wb1.Worksheets(sheetname).Copy(*Before*=wb2.Sheets(1))

对于此操作,我们使用了工作表对象复制方法

**# remove hashtag to save and quit modified Excel file**
#wb2.Save()
#wb2.SaveAs(Filename = r"new file name.xlsx") # save as new Workbook
#wb2.Close(True)
#excel.Quit()

最后一步是使用 SaveSave as方法保存处理后的工作簿。关闭方法关闭 Excel 工作簿,而退出方法退出使用 Python 创建的 Excel 对象。

2 .将多个工作簿中的工作表复制/合并为一个工作簿

在第一个示例中,我对工作表名称进行了硬编码,对于大量文件而言,这样做并不可取。该脚本将非常长,需要付出更多努力将所有工作表名称保存为单独的变量。

工作表中的 T24 索引 T25 就在这里。通过如下使用 Excel 索引属性 (Excel 对象、方法和属性) ,我们可以创建一个更可持续的函数来组合来自多个工作簿的工作表。

# return Sheet with index = 1 without stating Sheet Name
ws_name = wb1.Sheets(1)

对于本例,我们将根据日期将 25 个 Workbooks 合并为 5 个。每个工作簿最初仅包含一个工作表。如示例 A1 所示,需要 4 个步骤。

i .导入库

import re
import os
import win32com.client as win32
from pathlib import Path
win32c =  win32.constants

需要使用正则表达式(re)库来标识文件名中的日期。

ii .定义复制工作表的功能

该功能用于将工作表从一个工作簿复制到另一个工作簿。IF-ELSE 条件用于确定是否有工作簿打开。如果没有,它将打开第一个工作簿并保存为wb1,否则它将打开第二个工作簿并保存为wb2.,然后wb2中的工作表将被复制到wb1

内部 for 循环将合并同一个f_list中的工作簿,然后外部循环将在该过程完成时移动到下一个f_listcombine list 是一个嵌套列表,里面包含f_list ,而f_list包含

  1. 带有扩展名(f[0])的文件名,
  2. 状态(f[1])和
  3. 文件的日期(f[2])。

每个f_list包含日期相同的文件元组,如下图所示。

combine_list 截图。图片作者。

三。根据标准定义将文件名放入单独列表的函数

该功能是根据文件名中的日期对文件进行分组,并保存到combine_list。所有文件名保存在filename_list 参数中。对于每个文件名,我们将使用正则表达式(re)编译一个模式,如下所示。

pattern = re.compile(r"([\w]+) ([\d]{8}).xlsx")
x = pattern.search(f)

在上面的行中,我们想要标识州名和日期,日期是文件名中的一个 8 位数字。 x 将返回搜索结果,使用group我们可以选择文本中的任何部分来使用。

temp_name = x.group(1)        
temp_date = x.group(2)

索引从 0 开始,索引 0 指的是整个文本,索引 1 指的是第一个括号,在本例中是州名,索引 2 指的是第二个括号,它指的是日期。IF-ELSE 条件是将获得的第一个日期保存为参考日期,然后将其与文件名中的其余日期进行比较。每个匹配将作为一个元组保存到file_list。然后,元组会被追加到主列表中,也就是combined_list

添加到combined_list的每个文件名都将被添加到used_filename,WHILE 循环将继续,直到used_filename的长度等于初始列表filename_listfilename_listfiles的克隆在一开始就被创建,并被用作 FOR-LOOP 的标准。每次一个文件名被添加到used_filename中,它就会从files中被删除,所以不会有重复。

四。设置参数并调用函数

# your path
f_path = r"C:\Users\Desktop\Automate Excel Report Format" # get all files in the directory
filename_list = os.listdir(f_path + "\\" + "Sample File") # create excel object
excel = win32.gencache.EnsureDispatch('Excel.Application')# excel can be visible or not
excel.Visible = True  # False 
group_file_according_criteria(f_path, filename_list, excel)

filename_list 是需要合并的文件列表。由于文件是根据格式命名的,我们可以根据州或日期来组合文件。在此示例中,工作簿根据日期进行合并。原始工作簿保存在名为“Sample File”的文件夹中,而合并的工作簿保存在名为“combined”的文件夹中。这两个文件夹位于同一目录中。

自动化脚本的输出。

自动化脚本的输出。

合并所有月份相同的工作表。

总之,本示例显示如何根据日期将同一文件夹中的工作簿分组到一个列表中,然后将同一列表中所有工作簿的工作表合并到一个工作簿中。

B.复制一张 Excel 表的数据表并粘贴到另一张 Excel 表的现有数据表下方

1。合并两个工作表的数据表

为了确保我们只复制数据表,我们需要知道要复制的列和行的确切数量。因此,pandas.DataFrame.shape 函数将用于获取行数。在这个例子中,列数是硬编码的,因为作者没有想到除了使用 Python 字典之外的更好的方法来返回列的字母表😂

复制数据表的步骤与复制整个工作表(示例 A1)略有不同,因为需要知道行数。主要区别是使用pandas库读取数据表的大小,这里使用的复制方法Range 对象下。

wb1.Sheets(sheetname1).Range(f"A2:E{df_penang.shape[0] + 1}").Copy(*Destination* = wb2.Sheets(sheetname2).Range(f"A{df_sabah.shape[0] + 2}"))

除此之外,请注意,复制数据表时,选定的范围从单元格 A2 开始。

Range(f"**A2**:E{df_penang.shape[0] **+ 1**}")

这是因为第一行是表头行,也因为这样,最后一行是df.shape[0]+1返回的行数。如果数据的行数是 1000 行,不包括标题行(df.shape返回不考虑标题的行数),最后一行将是 1001。

然后,为了定位粘贴复制数据的位置,我们需要在目标工作表的数据表的行数上加 2。

Range(f"A{df_sabah.shape[0] **+ 2**}")

如果在目标工作表中,数据表的行数也是 1000,则在标题行计数后,最后一行也将是 1001。因此,粘贴复制的数据表的位置将在第 1002 行。

2。合并多个工作表的数据表

对于这个例子,我使用了在第 A2 部分中创建的文件。文件名以“Combined _ Dated”开头,每个文件内部都有 5 个工作表,表示 5 个州在同一日期的利润记录,如下图所示。

自动化脚本的输出。

自动化脚本的输出。

由于有多个工作表,最好使用工作表索引来标识工作表,而不是使用工作表名称。在这一部分中,我们将利用下面两个 Excel 对象属性。

# return number of Worksheet in the Workbook
wb1.Sheets.**Count**# return the name of a Worksheet (Sheet with index = 1)
ws_name = wb1.Sheets(1).**Name**

与其他 3 个例子一样,这一部分也需要 4 个步骤。

一、导入库

在示例 A2 中,正则表达式(re)用于比较工作簿的名称。在本例中,它将用于比较工作表的名称。

import win32com.client as win32
from pathlib import Path
import pandas as pd
import re

二。定义打开工作簿的函数

该函数用于打开工作簿,调用copy_data_table函数比较两个工作簿中的工作表,并将数据表粘贴到具有相同州名的工作表中。

IF-ELSE 条件用于确定是否有工作簿打开。如果没有,它将打开第一个工作簿并保存为wb1,否则它将打开第二个工作簿并保存为wb2。然后wb2中的工作表中的所有数据表都会被copy_data_table函数复制到wb1中。这里的计数方法将用于返回wb1中的张数。并且假设wb1wb2有相同数量的工作表,那么计数的结果将被用于获取wb2中工作表的名称。

copy_data_table函数将为外部 for 循环中的每个循环返回wb1save_path。这是因为我们每次将数据表复制粘贴到wb1中,都需要知道更新后的 wb1中数据表的最新大小,才能粘贴下一个数据表。

三。定义复制数据表的功能

此函数用于将所有工作表的数据表从一个工作簿复制到另一个工作簿。

我知道上面的剧本看起来很吓人,但是别担心,我会牵着你的手走完理解的旅程😉。

在上面的脚本中有两个 FOR 循环和两个 IF- ELSE 条件。我来一一解释一下。

1.FOR 循环

for n in range(*number_of_sheet_1*):
    # read the shape of dataframe of both file
    ws_name_1 = *wb1*.Sheets(n+1).Name
    state_name_wb1 = (re.split("_", ws_name_1))[0] # use RE to compile pattern to find a match
    for ws_name_2 in *wb2_ws_namelist*:
        pattern = re.compile(r"*(*[*\w*]+*)*_[*\d*]{1}")
        x = pattern.search(ws_name_2) # assume we are combine according state, which will be in
        first parenthesis
        state_name_wb2 = x.group(1)

当我们将多个工作表从一个工作簿复制到另一个工作簿时,我们将使用索引属性首先选择工作簿 1 (wb1)中的一个工作表,然后使用名称属性来标识工作簿 2 (wb2)中与wb1具有相同州名的工作表。

在外部 FOR 循环中,下面的脚本将获取 wb1 中当前索引为的工作表的名称。正则表达式将用于获取州名。

ws_name_1 = wb1.Sheets(n+1).Name        
state_name_wb1 = (re.split("_", ws_name_1))[0]

一旦我们从 wb1 中得到一个工作表名称,我们将把它与 wb2 中的工作表名称列表进行比较。这是内部 FOR 循环。wb2 中的工作表名称列表已经保存在wb2_ws_namelist中。

在内部 FOR 循环中,工作簿 2 中每个工作表的州名将通过正则表达式获取,如下面的脚本所示。

pattern = re.compile(r"([\w]+)_[\d]{1}")            
x = pattern.search(ws_name_2)            
# assume we are combine according state, which will be in first parenthesis            
state_name_wb2 = x.group(1)

然后,IF-ELSE 条件用于比较工作簿 1 中当前选定工作表的状态名和工作簿 2 中每个工作表的状态名

2.如果-否则

# for the match worksheet, calculate their number of rows and copy the data from one to another**if state_name_wb1 == state_name_wb2:**
    **if *save_path* =="":**
        file_path_1 = *main_file_path* **else:**
        file_path_1 = *save_path*df_main = pd.read_excel(file_path_1, *sheet_name* = ws_name_1)
    df_second = pd.read_excel(*file_path*, *sheet_name* = ws_name_2)**# copy the data table**
    *wb2*.Sheets(ws_name_2).Range(f"A2:E{df_second.shape[0] +            1}").Copy(*Destination* =
*wb1*.Sheets(ws_name_1).Range(f"A{df_main.shape[0] + 2}"))**else:**
    pass

外部 IF-ELSE 条件是比较两个打开的工作簿的工作表名称中的州名。如果状态名相等,那么我们将进入内部 IF-ELSE。

在内部 IF_ELSE 中,如果save_path为空,这意味着这个 IF-ELSE 条件之外的 FOR 循环刚刚开始,还没有数据表被复制。在这个阶段,我们将使用原wb1file_path。否则,我们将使用已处理的wb1中的save_path

然后,我们将使用pandas.shape函数获取当前wb1wb2中数据表的形状,并使用复制方法中的结果,将数据表粘贴到准确的位置。

工作簿 2 中工作表的数据表与工作簿 1 中当前选定的工作表具有相同的状态名,该数据表将被复制到工作簿 1 中当前选定的工作表。

3.在所有循环完成后

*save_path* = f_path + "\\Combined Data Table\\" + "Combined_Dated_State.xlsx"
*wb1*.SaveAs(*Filename* = *save_path*) # use save as to save as a new Workbook
# when overwriting previous saved file, will have pop up window, asking whether save
*wb1*.Close(True)
*wb2*.Close(True)
*wb1* = excel.Workbooks.Open(*save_path*return *wb1*, *save_path*

由于有多个工作簿,工作簿 1 每次都必须与另一个工作簿合并保存,以便 pandas 可以读取最新数据帧的形状,并计算出正确的目的地以粘贴数据表。wb1save_path也需要返回到下一个循环的主函数。

再次保存工作簿时,会有一个弹出窗口,询问是否在现有工作簿上保存,只需单击“是”😁。

四。调用主函数

f_path = r"C:\Users\*D*esktop*\A*utomate Excel Report Format"
# get all files in the directory
filename_list = os.listdir(f_path + "\\Combined\\") # create excel object
excel = win32.gencache.EnsureDispatch('Excel.Application')# excel can be visible or not
excel.Visible = True  # Falseopen_workbook(f_path, filename_list, excel)

该示例使用了示例 B2 的输出。由于工作簿中的工作表是根据一种格式命名的,因此我们可以根据状态来组合文件。最终的合并工作簿保存在名为“合并数据表”的文件夹中。这两个文件夹位于同一目录中。

自动化脚本的输出。

自动化脚本的输出。

总之,此示例显示了如何根据工作表的名称将同一文件夹中不同工作簿的工作表合并到一个工作簿中。最初,每个工作簿只有一个月的数据。合并后,最终的工作簿将包含 5 个月的数据。

这就是从多个工作簿中自动合并工作表的教程。感谢阅读到最后。

保持联系

订阅 YouTube

边注

用 Python 自动化 Excel中,我解释了 Excel VBA 的对象、方法和属性。这是使用pywin32时你必须知道的三个主要概念。

如果您对自动化数据透视表并从数据透视表中提取过滤后的数据到 pandas DataFrame 感兴趣,您可以使用用 Python 自动化数据透视表(创建、过滤和提取)

如果你的工作使用 Google Sheet 而不是 Microsoft Excel,你可以参考这篇文章“自动化 Google Sheet Report ”,了解可能的自动化。

参考

  1. 如何用 Python win32com 模块在 Excel 中创建透视表
  2. Excel VBA 参考
  3. Excel VBA 复制方法
  4. Python 集— GeeksforGeeks

祝贺并感谢你阅读到最后。希望你喜欢这篇文章。😊

照片由亲教会媒体Unsplash 上拍摄

使用 Python 自动创建用于语言学习的闪存卡

原文:https://towardsdatascience.com/automate-flash-cards-creation-for-language-learning-with-python-67871f4d23b3

我使用 Python 来支持我作为一个以法语为母语的人学习普通话的漫长旅程的经历。

(图片由作者提供)

学习一门语言可能是一个漫长的旅程,所以在这个过程中保持动力和明确的目标是至关重要的。

Because Mandarin uses a pictorial system of writing words and sounds called hanzi 汉字, it makes the journey even more challenging for any learner without a background in a similar language.

我想学普通话—(图片由作者提供)

在我追求汉语流利的过程中,抽认卡是我提高阅读和发音的最佳伙伴。

在本文中,我将分享我使用 Python 的数据分析工具来自动化闪存卡创建过程以支持我的学习过程的经验。

💌新文章免费直入你的收件箱:时事通讯

如果你愿意,你可以查看本教程的视频版本

语境

我是一个法国人,为了两年的双学位项目来到中国学习工程学。

最后,我呆了 6 年多,我的主要挑战是学习日常生活和工作所需的普通话。

前车之鉴:lessons drawn from others’ mistakes

当我开始学习普通话时,我犯的主要错误是没有听从那些提倡在 T4 使用闪存卡的聪明人的建议。

你还记得小时候你的父母或导师拿着你的书帮你准备明天的历史考试吗?

她在问你与课程相关的问题:

  • 如果你回答得好:她可以认为你已经准备好考试了。
  • 如果你犯了错误:她会让你再读一遍课文,等你准备好了再回来。

Anki 闪存卡(左:问题,右:答案)——(图片由作者提供)

现在有一款针对这个的开源 app,叫做 Anki

你手机上的私人老师

在上图中,你可以找到一个卡片的例子来学习如何说“你好!”用普通话。

第一步:它首先显示汉字中的单词

第 2 步:它会用以下内容向您显示答案:

  • 使用罗马化系统拼音的发音:nĭho
  • 英语翻译:你好!
  • mp3 声音的口语发音

你的自我评估—(图片由作者提供)

第三步:进行自我评估

  • 如果你猜对了,按下‘好’:卡片会在 10 分钟后重新出现
  • 如果你认为这很简单,Anki 会在 4 天后再问你
  • 如果您没有猜错,请再次按下:卡片将很快重新出现

Anki 的回顾过程—(图片由作者提供)

目标

为了支持你的学习之旅,你想用成千上万的卡片来喂养你的 Anki,并且在你的通勤和空闲时间每天练习 2 个小时。

**http://samirsaci.com **

解决办法

在这一节中,我将解释如何使用 Python 来构建这些卡片…

  • 日常生活或工作中常用的单词或句子
  • 使用 python 库添加音标****
  • 使用谷歌 TTS API 添加一个音频转录****

闪存卡创建流程—(图片由作者提供)

这个框架可以适用于任何语言,不仅仅是汉语普通话。

建立你的词汇列表

作为一名在中国工作的外国人,我的首要任务是掌握基本的词汇,以便在工作中与同事交流。

  1. pywin32 读邮件

因为我的第一个目标是阅读中文邮件,所以我计划提取 outlook 邮箱中最常用的单词。

使用下面这段代码,你可以提取所有电子邮件的正文,并将它们存储在一个列表中。

2.从 pdf 报告中提取关键字

我从供应商那里收到的一些报告和文档可能是技术词汇的很好来源。

因此,我构建了这段简单的代码来从任何 pdf 报告中提取文本。

3.其他来源

另一个主要来源是 Excel 格式的财务月报,可以使用 Pandas 库进行处理。

4。最终结果

经过处理后,我得到一个单词列表,如下所示

从工作中的操作文档中提取的词汇列表—(图片由作者提供)

二。添加音标

为了练习你的发音,正确使用音调,你需要一个音标。

添加语音转录—(图片由作者提供)

对于普通话,我使用 jieba 库,它获取汉字并返回拼音。

你可以为你的语言找到一个库。

例如,法语有 fonem ,意大利语有 epitran

三。添加发音

为了提高你的口语能力,你想在每张卡片上加上发音。

使用gtts 库可以解决这个问题。****

这是一个 Python 库和 CLI 工具,用于与 Google Translate 的文本到语音转换 API 接口。

您可以在官方文档中找到更多详细信息和使用说明。

结论

欢迎关注我的 medium,获取更多与数据分析和供应链管理相关的文章

现在你已经有了一个单词或句子的列表,包括英语翻译、语音记录和一段简短的 mp3 音频。

这些卡片可以用来练习你的…

  • 利用翻译进行阅读理解
  • 用音标发音
  • 用简短的音频进行口语理解

我的学习过程——(图片作者)

应用上图中的过程,我保证在 python 的帮助下,你会看到语言掌握的进步!

关于我

让我们在 LinkedinTwitter 上连线,我是一名供应链工程师,正在使用数据分析来改善物流运营和降低成本。

请随时关注我,我愿意分享和交流与技术、供应链分析、企业家精神和生产力相关的话题。

****http://samirsaci.com ****

使用 Python 自动化图形设计

原文:https://towardsdatascience.com/automate-graphic-design-using-python-e161bce62cfe

使用 Python Pillow 自动创建数百个仓库标签,作为提货地点的标志

(图片由作者提供)

场景 你是一家国际时装零售商物流部的实施经理

对于每个项目,你管理设备的实施,培训团队并设计存储位置的布局。

仓库标签示例—(图片由作者提供)

因此,你要花大量时间设计海报、安全标志标签。

在这篇文章中,我们探索了一种使用 Python 库 Pillow 来自动化图形设计过程的方法。

💌新文章直接免费放入你的收件箱:时事通讯

如果你喜欢看,看看 Youtube 教程

如何用 Python 做平面设计?

方案

你是一家时装零售商物流部门项目团队的一员,该公司在各大洲都有仓库。

该团队负责为新开的配送中心实施流程和设备。

配送中心示例—(图片由作者提供)

例如,您的主要任务是设计存储位置的机架布局。

在一个仓库中,你可以有几百个存放和拣选货物的货盘/货架位置。

(一层:提货地点,其他层:仓库)——(图片由作者提供)

为了帮助操作员找到正确的位置,您需要打印并粘贴带有关键信息的标签。

高架存储位置的标签示例—(图片由作者提供)

目标

您希望设计定制的标签来减少错误、帮助操作人员并遵守您公司的标准操作程序。

因为每个仓库可能有几千个位置,所以您希望自动化这个过程。

解决办法

我将提出一个自动创建这些标签的解决方案。

标签的最终结果—(图片由作者提供)

这是一个简单的 python 脚本,它从 excel 文件导入位置信息,并自动生成如上所示的标签。

有关数据分析、生产力和供应链管理的更多文章,

http://samirsaci.com

标签设计

六个关键参数

此标签将由三种类型的操作员阅读:

  • 联系卡车司机,他们会将托盘或箱子放在这些位置
  • 从这些地点提取物品的提货操作员
  • 将执行库存盘点的库存管理员

标签信息—(图片由作者提供)

因此,您需要包括一些与位置和存储产品相关的关键信息:

  • 一个彩色箭头显示产品的存放位置(上方或下方)
  • 一个带有 SKU 代码的条形码,供使用射频枪的操作人员使用
  • 拣货位置编号,带有小巷、小区和楼层编号
  • 三个图标,提供与存储的位置和物品相关的信息

空间坐标

考虑到每个项目的大小,您希望固定每个项目的空间坐标。

关键坐标—(图片由作者提供)

在这个非常简单的标签中,您有 5 个参数来定位不同的项目。

我们决定把原点放在左上角;是因为枕头用的是同一个原点。

导入 png 图标

存储位置编号和条形码将在 python 脚本中生成。

要添加的图标—(图片由作者提供)

其他项目是图标,将使用本地存储的 png 文件导入到您的枕头对象。

信息源

在您的主数据中,有几千个 SKU,包含尺寸、重量、价格等信息。

您将把这些 SKU 分配到需要特定标签的提货地点。

对于自动化工具,您可以创建一个 excel 文件,每个 SKU 对应一行,包括

  • SKU 码:将用于创建条形码
  • 地理信息:巷子、区域、位置号
  • 物流处理单元:如果你是一件一件的拿货,那么是一件;如果你是一箱一箱的拿货,那么是一箱
  • 箭头类型带有方向和颜色
  • 产品类别(领带、鞋子、连衣裙……)
  • 提货地点特殊信息:危险品、洒水车、RFID、…

自动创建标签

开始循环

您的脚本将遍历数据框的各行,为每一行生成一个标注。

对于每个标签,首先创建一个带有黑色边框和特定尺寸(500,200)像素的空白画布。

空白画布—(作者图片)

添加图标

对于这一步,您将添加图标来指定

  • 坐标(x,y)
  • 使用百分比调整大小后的尺寸
  • 图标文件名取自数据框

附言:

  • 您需要转换您的 png 文件,以保持透明的背景。
  • 图标坐标是使用它们在两个轴上的大小来定义的

图标标签—(作者提供的图片)

添加条形码

使用 SKU 码和 python 的条形码库生成条形码。

页(page 的缩写)学生:

  • create_ean 将生成一个本地存储的 png 文件,该文件将在循环中使用
  • 条形码已调整大小以适合画布

带有条形码的标签—(图片由作者提供)

添加位置代码

这最后一步将完全使用 Python Pillow 来执行。

最终结果—(图片由作者提供)

瞧啊。

您的标签已生成并准备打印。

这不是列奥纳多·达·芬奇的作品,但只需点击一下,它就可以自动生成数千个标签。

30 秒内生成 1000 个标签—(图片由作者提供)

如果你想了解 Pillow 更高级的功能,可以看看他们的官方文档

超出

如果你认为制作 PowerPoint 演示很无聊,看看下面的文章,

https://www.samirsaci.com/automate-powerpoint-slides-creation-with-python/

关于我

让我们在 LinkedinTwitter 上连线,我是一名供应链工程师,正在使用数据分析来改善物流运营和降低成本。

如果你对数据分析和供应链感兴趣,可以看看我的网站

https://samirsaci.com

使用 Python 在 HTML 电子邮件中自动分发运营报告

原文:https://towardsdatascience.com/automate-operational-reports-distribution-in-html-emails-using-python-c65c66fc99a6

利用 Python 在 HTML 电子邮件中内置的可视化功能,自动分发供应链运营报告

(图片由作者提供)

场景 你是一家时装零售公司配送中心的持续改进工程师,负责绩效报告

每周,您连接到系统,提取数据执行分析以构建操作仪表板。

您通过电子邮件向您的管理层发送带有运营指标的每周报告。

这个过程非常耗时,因为您是用 Excel 手动完成的。

目标 在本文中,我们将构建一个全自动解决方案,使用 Python 在 HTML 电子邮件中共享一份单页运营报告

💌新文章直接免费放入你的收件箱:时事通讯

如果你更喜欢视频,你可以看看 Youtube 教程

如何用 Python 通过邮件发送自动报表?

方案

你是一家在世界各地都有商店的国际服装集团的持续改进经理。

该公司在亚洲的工厂生产服装、包包和配饰。

门店本地仓库发货,由工厂直接补货。

物流网络—(图片由作者提供)

性能管理

您必须定期与管理层分享仓库运营指标。

这是一个手动过程,您需要

  1. 仓库管理系统(WMS) 中提取数据
  2. 使用 Excel 处理数据并构建可视化效果
  3. 通过电子邮件发送一份简短的报告,并附上图片和评论

目标

为了提高效率,您希望使用 Python 来自动化这个过程。

你的解决方案将是一个简单的 python 脚本,部署在云上,它将自动执行这四个步骤:

  • 从 WMS SQL 数据库中提取上周准备好的订单行
  • 使用关键洞察处理数据并计算 KPI
  • 自动发送带有视觉效果评论的 HTML 电子邮件

分四步走—(图片由作者提供)

结果

最终报告将如下图所示:

  • 标题将根据本周进行调整
  • 将包括一个条形图视觉
  • 评论区将提供基于视觉的见解

最终结果—(图片由作者提供)

整个过程将是自动化的,因此报告可以在没有您的支持下按时发送。

如果您正在寻找运营管理的应用示例,请观看这个短片

http://samirsaci.com

解决办法

你可以在这里找到带哑数据的源代码: Github

让我们探索生成最终报告的所有步骤。

生成通过电子邮件发送的自动报告的步骤—(图片由作者提供)

数据析取

由于你无法访问我的 WMS 数据库,我共享了一个包含虚拟数据的 CSV 文件。

但是您的解决方案将连接到您的 WMS

  • 创建您的 SQL 查询来提取装运记录
  • 使用 pandas.read_sql_query 进行查询
  • 结果将是一个熊猫数据框

数据处理

一个重要的指标是每个订单的行数,您的处理任务会将该列添加到您的数据框中。

构建图表

您需要一个简单的条形图,显示每天准备的行数和订单数。

视觉—(作者提供的图片)

保存图像

为了嵌入到你的 HTML 页面中,你需要保存它

添加见解

你的报告的一个附加价值是用三个要点来总结一周的行动。

因此,您需要计算正确的指标,为您的最高管理层带来可见性。

这些见解将包含在您的评论区 HTML 文件中。

创建 HTML 报告

在资源库中,您可以找到一个非常简单的 HTML 页面模板,它将用于创建您的电子邮件。

HTML 文件的结构—(图片由作者提供)

结构简单

  • png 文件中带有徽标的标题
  • 更新了当前周的标题
  • 您的视觉使用 png 图像
  • 包含最新见解的评论区
  • 页脚,您可以在其中放置作者的信息

包括图像

为了在 HTML 中包含标题和可视内容,您将创建 MIMEImage 对象,并在 HTML 代码中加入 content-id。

添加见解

在 HTML 代码中,我在要写见解的地方做了一些标记。想法是使用 replace 函数来修改它们,并放入 python 脚本返回的值。

创建并发送电子邮件

要使用 python 发送电子邮件,您可以使用库 smtplib。

使用 python 发送电子邮件—(图片由作者提供)

您需要添加以下信息(示例供参考)

  • SMTP 服务器,端口:例如‘SMTP . Google . com’,465
  • 您的电子邮件地址送货地址
  • 您的邮箱密码

然后,您可以发送带有更新的视觉效果和见解的 HTML 电子邮件。

结论和后续步骤

欢迎关注我的 medium,获取更多与数据分析和供应链管理相关的文章

结论

有了这个非常简单的例子,您就有了一个模板来构建您自己的报告自动化解决方案。

你现在可以了,

  • 添加视觉效果或表格
  • 带来更多见解或用条件丰富文本

后续步骤

只需点击一下鼠标,就可以在您的计算机上本地启动这个 python 脚本。

然而,由于最初的目标是完全自动化这个过程,您可以在 Heroku 上部署这个代码,并安排在每周一上午 9:00 发布。

关于我

让我们在 LinkedinTwitter 上连线,我是一名供应链工程师,正在使用数据分析来改善物流运作和降低成本。

如果你对数据分析和供应链感兴趣,可以看看我的网站

*https://samirsaci.com *

使用 Python 自动创建 PowerPoint 幻灯片

原文:https://towardsdatascience.com/automate-powerpoint-slides-creation-with-python-a639c7d429a6

使用 Python 创建供应链运营 PowerPoint 报告的自动化工具提高您的工作效率

(图片由作者提供)

场景 你是一家时装零售公司物流部的分销计划经理

要执行分析,您需要连接到仓库管理系统,使用 Python 构建的自动化工具提取流程数据

但是,您必须花时间手动将这些视觉效果放入幻灯片,以便进行每周运营回顾。

目标 在本文中,我们将构建一个解决方案来自动创建带有视觉效果和注释的 PowerPoint 幻灯片。

💌新文章直接免费放入你的收件箱:时事通讯

如果你喜欢看,看看 Youtube 教程吧!

如何用 Python 制作 Powerpoint 演示文稿?

你是一家在各大洲都有商店的国际服装零售商的分销计划团队的一员。****

物流网络—(图片由作者提供)

你的分销网络包括几个为商店补充货物的当地仓库。

每月运营回顾

在月底,你与商店经理一起组织一次运营回顾,评估分销网络的 绩效

为了让讨论生动起来,你准备一些幻灯片,

  1. 仓库管理系统中提取数据(WMS)
  2. 用 Python 处理数据和构建视觉效果****
  3. 准备 PowerPoint 演示文稿

目标

为了提高效率,您可能希望自动化 PowerPoint 页面集的创建过程。

您的解决方案将完全自动化

  • WMS SQL 数据库提取上个月的订单行
  • 每周处理数据并使用关键洞察计算 KPI
  • 在 PowerPoint 演示文稿中自动加入视觉效果和见解

分四步走—(图片由作者提供)

结果

最后一组幻灯片将包括如下幻灯片:

  • 5 张幻灯片**显示每日工作量(左)1 张幻灯片用于每月订单分析(右)**
  • 用 Python 生成的可视化
  • 评论区将提供基于视觉的见解

最终结果—(图片由作者提供)

解决方法

你可以在这里找到带哑数据的源代码:Github

让我们探索生成最终报告的所有步骤。

在 PowerPoint 上创建运营报告的步骤—(图片由作者提供)

数据析取

连接到您的 WMS 并提取装运记录

  • 创建您的 SQL 查询来提取装运记录
  • 使用 pandas.read_sql_query 进行查询
  • 结果将是一个熊猫数据框

如果你没有访问WMS 数据库 的权限,可以使用 GitHub repo 中共享的数据集。****

处理数据

添加一个使用 pandas 计算每个订单行数的列。

创造视觉效果

创建一个简单的条形图,显示每天准备的行数和订单数。

条形图—(图片由作者提供)

堆积条形图—(图片由作者提供)

保存图表

为了添加到 PowerPoint 中,您需要将其保存在本地。

添加评论和见解

您可以根据您共享的图表添加评论,该图表将总结每周的表现。

为了更加清晰起见,请将这些评论放在图片下面。

评论示例—(图片由作者提供)

创建 PowerPoint 幻灯片组

我们将使用开源库 python-pptx 来构建我们的 PowerPoint 平台。更多详情,请看文档

介绍幻灯片

我们将在演示开始时以一张特殊的介绍幻灯片开始。

第一张幻灯片—(图片由作者提供)

代码

每周每日分析幻灯片

你的幻灯片的结构总是一样的

  • 顶部的标题(例如:仓库工作量(第 5 周))**
  • 幻灯片中央的一幅画
  • 评论区的文本框

幻灯片结构—(图片由作者提供)

代码

💡提示
你可以通过修改 Inches()函数的参数来改变对象的位置。

订单概况的每周分析

在本幻灯片中,您将使用堆积条形图,注释将基于整个月的范围。

订单简介—(作者图片)

代码

💡提示
您可以通过修改函数 Pt()的参数来改变字体大小。

最后,您有一个包含 7 张幻灯片的 PowerPoint 文件,可用于您的会议。

PowerPoint 决赛—(图片由作者提供)

结论和后续步骤

欢迎关注我的 medium,获取更多与数据分析和供应链管理相关的文章

结论

有了这个非常简单的例子,您就有了构建自己的 PowerPoint 自动化解决方案的模板。

你现在可以了,

  • 添加 PowerPoint 的视觉效果、表格或智能视觉效果(查看文档)
  • 带来更多见解或用条件丰富文本

只需点击一下鼠标,就可以在您的计算机上本地启动这个 python 脚本。

自动化电子邮件报告

您还可以使用 python 的 SMTP 库通过电子邮件自动分发报告。

事实上,一个部署在云上的简单 python 脚本将自动执行这四个步骤:

  • 从 WMS SQL 数据库中提取上周准备好的订单行
  • 使用关键洞察处理数据并计算 KPI
  • 自动发送带有视觉效果评论的 HTML 电子邮件

分四步走—(图片由作者提供)

更多的细节,你可以看看我几周前发表的这篇文章,

****https://www.samirsaci.com/automate-operational-reports-distribution-in-html-emails-using-python/

关于我

让我们在 LinkedinTwitter 上连线,我是一名供应链工程师正在使用数据分析来改善物流运作和降低成本。

如果你对数据分析和供应链感兴趣,可以看看我的网站

https://samirsaci.com ****

使用交互式 AgGrid 和 Google Sheets 自动化 Streamlit Web 应用程序

原文:https://towardsdatascience.com/automate-streamlit-web-app-using-interactive-aggrid-with-google-sheets-81b93fd9e648

可定制的 AgGrid 数据表连接到谷歌工作表数据库

这幅图像旨在展示 Streamlit、Google Sheet 和 AgGrid table 之间微妙的抽象联系,由互联的电话描绘,允许数据在它们之间无缝流动。照片由帕万·特里库塔姆Unsplash 上拍摄

TL;博士

  • 这篇博客文章演示了如何在 Streamlit 应用程序中使用 AgGrid 库来创建交互式数据表。
  • 它展示了如何将表连接到 Google Sheets 数据库,并将数据从表发送到数据库。
  • 此外,还实现了 JavaScript 回调,用于向 AgGrid 表添加行。

1.介绍

treamlit 是一个流行的开源框架,用于构建数据科学和机器学习应用。它允许开发人员使用简单的 Python 代码创建交互式的、基于 web 的应用程序。然而,Streamlit 中内置的数据表组件功能有限,并不总是适合更高级的用例。这就是 AgGrid 库的用武之地。AgGrid 是一个强大的 JavaScript 库,可以用来创建交互式数据网格和表格。

在 Streamlit 应用程序中实现 AgGrid 对于数据科学家和机器学习工程师来说特别有用,他们希望构建用户友好的应用程序,允许用户查看、操作和分析数据。AgGrid 提供了多种功能,如过滤、排序和聚合,可以帮助用户更好地理解和处理大型数据集。它还支持多种数据类型,包括数字、字符串和日期,并且可以根据应用程序的需要进行定制。

在这篇博文中,我们将演示如何在 Streamlit 应用程序中使用 AgGrid,并将其连接到 Google Sheets 数据库。我们将向您展示如何创建一个可定制的数据表,将数据从表发送到数据库,以及使用 JavaScript 函数向表中添加行。

2.先决条件

要阅读这篇博文,您需要安装以下库:

  • streamlit:这是主要的 Streamlit 库,用于在 Python 中构建交互式数据应用。要安装它,您可以使用下面的命令:pip install streamlit
  • pandas:这个库用于 Python 中的数据操作和分析。在我们的用例中,它用于读/写数据和创建数据帧。DataFrame 是一种表格数据结构,可用于存储和操作数据。要安装它,您可以使用下面的命令:pip install pandas
  • streamlit-aggrid:这是一个 Streamlit 扩展或包装器,提供与 AgGrid 库的集成。它用于创建和自定义数据表。要安装它,您可以使用下面的命令:pip install streamlit-aggrid
  • gspread:这是一个用于与 Google Sheets 交互的 Python 库。它用于连接 Google Sheets 数据库。要安装它,您可以使用下面的命令:pip install gspread
  • google-authgoogle-auth-oauthlib:这些库用于谷歌服务的认证。它们是gspread库工作所必需的。要安装它们,您可以使用下面的命令:pip install google-auth google-auth-oauthlib

或者,您可以从终端使用以下命令一起安装这些库,

# Installation of the dependencies 
pip install streamlit pandas streamlit-aggrid gspread

3.设置简单的 AgGrid 表

一旦我们安装了依赖项,我们就可以开始创建一个虚拟数据帧,用于填充 AgGrid 表。我们将首先导入必要的库并创建一个示例数据框架,

# Importing the dependencies

import streamlit as st 
import pandas as pd
from st_aggrid import AgGrid, JsCode
from st_aggrid.grid_options_builder import GridOptionsBuilder
# Creates a Streamlit header and an Expander 
# to provide some context for the app.

st.header("AgGrid Demo `Part 3`")
with st.expander('🤩 What I plan to demonstrate today ? ', expanded=False):
    st.markdown('''

                ◻ 1\. Implementing `button` within AgGrid table

                ◻ 2\. Display any `update` made from the user-end

                ◻ 3\. `Download` the AgGrid table

                ◻ 4\. `Connect` to Database
                ''')

# Create an AgGrid table from a pandas DataFrame
d = {‘Type’:[‘Notebook’, ‘DVDs’] ,’Quantity’: [1, 2],’Price’: [400, 200]}
df = pd.DataFrame(data = d)

现在我们有了一个示例数据帧,我们可以使用AgGrid函数在 Streamlit 中将它显示为一个 AgGrid 表:

# Display the Dataframe in AgGrid
AgGrid(df)

这将为我们提供一个包含虚拟数据的基本 AgGrid 表,但是它的交互性不是很好。为了使我们的 AgGrid 表更具交互性,我们可以使用 JavaScript 添加一些特性,比如单元格渲染器和单元格上的点击事件。

来自演示 Streamlit 应用程序的屏幕截图,展示了(上)AgGrid 表(下)默认 Streamlit-data frame-按作者分类的图像之间的差异

4.实现一个允许向 AgGrid 表中添加新行的按钮

要向 AgGrid 表添加按钮,我们需要使用 JavaScript 创建一个自定义单元格渲染器。单元格渲染器是一个返回要在单元格中显示的 HTML 元素的函数。

我们将首先创建一个 JavaScript 函数,当单击按钮时,该函数向 AgGrid 表添加一个新行。为此,我们将使用 AgGrid API 提供的applyTransaction方法。这个方法允许我们通过应用一个事务对网格进行修改。在这种情况下,我们使用add事务向表中由rowIndex指定的索引处添加一个新的空行。

# JavaScript function to add a new row to the AgGrid table
js_add_row = JsCode ('''
function(e) {
 let api = e.api;
 let rowPos = e.rowIndex + 1; 
 api.applyTransaction({addIndex: rowPos, add: [{}]}) 
};
'''
)

接下来,我们将定义一个单元格呈现器,它将在'🔧' AgGrid 列的每个单元格中呈现一个按钮。单元格渲染器是一个定义如何渲染单元格的类。在本例中,我们使用 HTML button元素来呈现按钮。该按钮将有一个onclick事件,当点击时调用js_add_row函数。我们还在按钮上应用了一些基本的 CSS 样式,使它看起来更有吸引力。

# Cell renderer for the '🔧' column to render a button
cellRenderer_addButton = JsCode('''
    class BtnCellRenderer {
        init(params) {
            this.params = params;
            this.eGui = document.createElement('div');
            this.eGui.innerHTML = `
            <span>
                <style>
                .btn_add {
                    background-color: #71DC87;
                    border: 2px solid black;
                    color: #D05732;
                    text-align: center;
                    display: inline-block;
                    font-size: 12px;
                    font-weight: bold;
                    height: 2em;
                    width: 10em;
                    border-radius: 12px;
                    padding: 0px;
                }
                </style>
                <button id='click-button' 
                    class="btn_add" 
                    >&#x2193; Add</button>
            </span>
        `;
        }
        getGui() {
            return this.eGui;
        }
    };
    ''')

5.用按钮功能可视化 AgGrid

现在我们已经定义了 JavaScript 函数,我们可以创建一个 AgGrid 表并配置它来显示我们的按钮。为此,我们将首先使用from_dataframe方法从我们的熊猫数据帧中创建一个GridOptionsBuilder对象。这将根据 DataFrame 中的数据为我们的 AgGrid 表创建一个默认配置。

接下来,我们将使用configure_column方法指定字段名为'🔧'的列应该使用我们的cellRenderer_addButton单元格渲染器,我们还将指定onCellClicked事件应该触发我们的js_add_row JavaScript 函数。

# Create a GridOptionsBuilder object from our DataFrame
gd = GridOptionsBuilder.from_dataframe(df)

# Configure the default column to be editable
# sets the editable option to True for all columns
gd.configure_default_column(editable=True)

# Configure the '🔧' column to use our the cell renderer 
# and onCellClicked function
gd.configure_column( field = '🔧', 
                     onCellClicked = js_add_row,
                     cellRenderer = cellRenderer_addButton,
                     lockPosition='left')
                    )
gridoptions = gd.build()

最后,我们可以使用AgGrid函数并传入GridOptionsBuilder对象来创建我们的 AgGrid 表。注意,为了从用户界面的角度简化,我们使用st.form()布局在 Streamlit 前端创建一个表单。该表单有一个标题,上面写着“库存清单”🔖和一个标记为“确认项目”的提交按钮🔒".AgGrid函数中使用的参数在代码块中被很好地注释了。

# AgGrid Table with Button Feature
# Streamlit Form helps from rerunning on every widget-click
# Also helps in providing layout

with st.form('Inventory') as f:
    st.header('Inventory List 🔖')

# Inside the form, we are displaying an AgGrid table using the AgGrid function. 
# The allow_unsafe_jscode parameter is set to True, 
# which allows us to use JavaScript code in the AgGrid configuration
# The theme parameter is set to 'balham', 
# which applies the Balham theme to the table
# The height parameter is set to 200, 
# which specifies the height of the table in pixels.
# The fit_columns_on_grid_load parameter is set to True, 
# which ensures that the columns of the table are resized to fit 
# the width of the table when it is first displayed

    response = AgGrid(df,
                    gridOptions = gridoptions, 
                    editable=True,
                    allow_unsafe_jscode = True, 
                    theme = 'balham',
                    height = 200,
                    fit_columns_on_grid_load = True)
    st.write(" *Note: Don't forget to hit enter ↩ on new entry.*")
    st.form_submit_button("Confirm item(s) 🔒", type="primary") 

就是这样!现在您应该有一个工作的 AgGrid 表,在'🔧'列的每个单元格中有一个按钮,单击该按钮时会向表中添加一个新行。

应用程序的屏幕截图,显示 AgGrid 表中呈现的“添加按钮”——图片由作者提供

6.以表格或图的形式获取 AgGrid 数据

表格中的数据很容易获取。每当前端用户确认 AgGrid 表中的任何更改并触发st.form_submit_button()时,st.table函数用于以表格形式显示 AgGrid 表中的更新数据。

# Visualize the AgGrid when submit button triggered           
st.subheader("Updated Inventory")
# Fetch the data from the AgGrid Table
res = response['data']
st.table(res) 

然后我们使用st.bar_chart函数显示来自 AgGrid 表的数据的条形图,使用Type列作为 x 轴,使用Price列作为 y 轴。

# Plotting the data
st.subheader(“Visualize Inventory”)
st.bar_chart(data=res, x = ‘Type’, y = ‘Price’)

7.将 AgGrid 数据保存在本地或云中

为了用户界面的美观,我们使用st.columns函数创建了两列,在第一列中,我们有一个标签,上面写着“保存在本地机器中?”。在第二列中,我们的目标是创建一个按钮,将 AgGrid 数据更新到连接的 Google Sheet。

a)本地下载:csv变量设置为对 AgGrid 表中的数据调用convert_df函数的结果。单击该按钮时,会下载名为“file.csv”的 CSV 文件。

# Function
@st.experimental_memodef 
convert_df(df): 
```Converts the data to a CSV format```
  return df.to_csv(index=False).encode(‘utf-8’)

st.subheader("Store Inventory")
col1,col2 = st.columns(2)
# https://docs.streamlit.io/knowledge-base/using-streamlit/how-download-pandas-dataframe-csv
csv = convert_df(response['data'])
col1.write("Save in Local Machine?")
col1.download_button(
   "Press to Download 🗳️",
   csv,
   "file.csv",
   "text/csv",
   key='download-csv'
)

b)实时更新到云端: Google Sheets 可以作为云存储解决方案,以表格格式存储和访问数据。数据可以由多个用户同时访问和修改,更改会自动保存并实时同步。

注意,在这一步,为了获得服务账户信息,您需要创建一个谷歌云平台(GCP)项目和一个服务账户,然后下载服务账户密钥文件。参考文献[3]对这些步骤进行了详细阐述。

下面的步骤描述了所使用的代码(为了更好地理解,对代码进行了很好的注释),

  • 下面的代码首先导入service_account模块和gspread库。gspread库用于从 Python 访问和修改 Google Sheets 文档。
# Importing the necessary Library
from google.oauth2 import service_account
import gspread 

def send_to_database(res):
    # Create a list of scope values to pass to the credentials object
    scope = ['https://spreadsheets.google.com/feeds',
            'https://www.googleapis.com/auth/drive']

    # Create a credentials object using the service account info and scope values
    credentials = service_account.Credentials.from_service_account_info(
                st.secrets["gcp_service_account"], scopes = scope)

    # Authorize the connection to Google Sheets using the credentials object
    gc = gspread.authorize(credentials)

    # Open the Google Sheets document with the specified name
    sh = gc.open("AgGrid-Database")

    # Access the worksheet within the document with the specified name
    worksheet = sh.worksheet("Sheet1") 

    # Set up a progress bar
    my_bar = st.progress(0)

    # Iterate through the rows of the data frame
    for ind in res.index:
        # Calculate the percentage complete
        percent_complete = (ind+1)/len(res) 
        # Update the progress bar
        my_bar.progress(percent_complete)

        # Get the values in the first column of the worksheet
        values_list = worksheet.col_values(1)
        # Calculate the next empty row in the worksheet
        length_row = len(values_list)

        # Update the cells in the worksheet with the data from the data frame
        worksheet.update_cell(length_row+1, 1, res['Type'][ind])
        worksheet.update_cell(length_row+1, 2, str(res['Quantity'][ind]))
        worksheet.update_cell(length_row+1, 3, str(res['Price'][ind]))

    # Return a success message
    return st.success("Updated to Database ", icon="✅")\

# If the "Send to Database" button is clicked, execute the send_to_database() function
col2.write("Save in Shared Cloud?")
if col2.button("Send to Database"):
    send_to_database(res)
  • 该函数首先定义一个列表scope,指定服务帐户应该拥有的权限。在这种情况下,服务帐户被授权访问 Google Sheets API 和 Google Drive API。
  • 接下来,我们需要检索必要的凭证来访问我们的 Google Sheets 数据库。代码使用Credentials.from_service_account_info()方法创建一个Credentials对象,并传递存储在st.secrets字典中的服务帐户信息。该方法返回一个Credentials对象,该对象可用于验证到 Google Sheets 和 Google Drive 的连接。
  • 然后使用Credentials对象使用gspread.authorize()方法来验证到 Google Sheets 的连接。gc.open()方法用于打开名为“AgGrid-Database”的 Google Sheets 文档,而sh.worksheet()方法用于访问名为“Sheet1”的文档中的工作表。
  • 然后代码使用st.progress()方法建立一个进度条。它遍历 DataFrame res的行,对于每一行,它使用worksheet.col_values()方法检索工作表第一列中的值。然后使用update_cell()方法用数据框res中的数据更新工作表中的单元格。
  • 最后,当所有数据都写入工作表时,代码使用st.success()方法返回一条成功消息。该代码还包含一个if语句,当单击“发送到数据库”按钮时,该语句执行send_to_database()函数。

将数据从 AgGrid 表更新到云(Google Sheets)——作者视频

8.结论

总之,使用上面的代码行创建的 web 应用程序演示了 AgGrid 表中各种功能的实现,包括添加新行、显示用户所做的更新、下载表以及连接到数据库的能力。该应用程序易于使用,界面简洁,功能直观。无论你是想跟踪库存,更新待办事项列表,还是管理任何其他数据,这款网络应用都能满足你。该应用的现场演示可以在这里找到。

9.参考

[1] A.Gadhir,如何在 AG 网格单元格中添加按钮,(2020)

[2] CSS 按钮—基本按钮样式,W3CSS

[3] 将 Streamlit 连接到一个私有的 Google 工作表,Streamlit (2021)

[4] P.Fonseca, streamlit-aggrid Python 包,(2020)

10.代码

这里是完整的代码,快速开始,玩得开心!

请随意写下您的反馈。Tada!

使用您的第一个 Python 警报机器人自动化团队

原文:https://towardsdatascience.com/automate-teams-with-your-first-python-alerting-bot-bcc8f7c6ee5a

图 1——亚历山大·奈特在 Unsplash 上的照片

在 5 分钟内发送您的第一个通知!

在许多公司中,微软团队是公司沟通的核心。您可以与同事交谈,计划和协助会议,创建团队来共享项目中的信息和文件。据称,它是微软协作的中心。

今天,让我们看看如何让团队实现自动化,并使用它来发送个人或专业通知。webhooks 的设置非常简单,不超过 5 分钟。难以置信!

动机

  1. 你在训练一个 ML 模型。这可能需要几个小时,并且您希望在运行结束时得到提醒。在你的电脑和手机上给自己发送一个跑步结束的信号是非常容易的。
  2. 您正在运行 10 分钟的计算操作。太短做不了别的,太长看不了屏幕。你可能会死在你的手机上!在运行结束时收到状态通知可以提高工作效率,避免浪费时间。
  3. 您或您的团队希望在计算过程中得到一些信息的提醒,以防执行异常。(例如:评估较差的数据质量。)
  4. 您希望以报告的形式与您的团队或更广泛的工作受众共享每日或每月的数据。您的同事会很高兴通过特定的(有组织的)渠道接收数据作为专用通知,而不是通过另一封包含数据的电子邮件和另一个加入的 PowerPoint。

技术概述

要发送团队通知,必须执行以下步骤

  • 拥有一个团队帐户和一个团队,并有一个在(先决条件)上发布的渠道
  • 将 webhook 连接器添加到该团队
  • 在通道中配置 webhook 连接器
  • 创建要发布的内容
  • 从任何联网设备请求正确的 URL(最终使用 Python)

创建网页挂钩

webhook 是一个链接,您将获得并使用它来发送一个 HTTP post请求,其中包含所需的通知内容。

首先,你需要决定在哪个香奈儿哪个团队发布通知。为了这篇博文,我创建了一个专门的中型聊天机器人团队,有一个私人教程频道。

  1. 在频道的设置(“ ”)上,点击连接器。

图 2 —在团队通道上打开连接器窗口

2.它将打开所有可用的连接器。在右上角的搜索栏中查找“webhook”。

3.点击“传入网页挂钩”的“添加按钮

图 3 —在团队中选择传入的 Webhook

4.这将打开一个新对话框来验证您的选择。再次点击添加

图 4 —在团队中安装引入的 Webhook

5.不同的窗口将会关闭

6.重新打开通道的连接器:设置“>****连接器。您将看到第一个可用的连接器现在是传入的 webhook。

7.点击配置按钮

图 5 —恢复到团队频道的连接器页面

8.配置框打开。您会立即看到配置是多么简单:

  • 给机器人起个名字。当通知到达时,它将是频道中显示的名称。我习惯在名字里加一个机器人表情符号🤖!让我们把它命名为“你忠诚的机器人”🤖"
  • 添加个人资料图片。也将在发布消息时显示。因为我们想用 Python 实现自动化,所以我会添加 Python 徽标作为个人资料图片。但是你显然可以使用你公司的标志,一个机器人图片,或者你的脸书个人资料图片!

就是这样!不要害怕,如果你不确定你的机器人的名字,你可以在以后更改这些信息而不会有任何后果😉

9.点击“创建”按钮

图 6 —配置传入的 Webhook

10.你的专用机器人的网址将会出现,你可以复制它。

图 7 —获取传入网络挂钩的 URL

它看起来将如下所示:

[https://yourcompanyname.webhook.office.com/webhookb2/3502e881-7606-4faf-99a6-116a08d2ae9b@ebaeb74c-fiff-40f8-b755-10b0e2bf7528/IncomingWebhook/tl23354ab6704kys83466028f40mmss0/49c2927e-6269-4317-9d68-d2d1057b07fb](https://mousquetaires.webhook.office.com/webhookb2/3205e881-7066-4faf-99a6-116a08d2ae9b@ebaeb74c-eeae-40f8-b755-10b0e2bf7528/IncomingWebhook/fa25573da6704dcd83466028d40caaa0/49c2927e-6269-4317-9d68-d2d1057b07fb)

11.把这个 URL 保存在某个地方,我们稍后会看到如何使用它。

12.现在,您可以点击“ Done ”按钮并关闭连接器窗口。

13.现在,回到通道,您将看到一条消息,表明您配置了一个传入的 Webhook。

图 8-正确安装的确认

还有…差不多就是这些了!第一次可能会花你几分钟的时间,但是将来,我相信你可以在 45 秒内完成这个过程⏲

现在,您的通道可以从外部来源接收消息,让我们更深入地了解如何发送通知。

发送通知

通知构成

有很多方法可以通过 webhook 创建内容。你可以在这里找到微软的文档,但是在我做过的许多测试中,没有多少是有效的。然后我将向您展示一个可以被 webhook 解释的基本消息。

该消息必须采用 JSON 格式,并且至少包含 3 个必填字段。

  • 摘要:将显示在电话通知上的文本。
  • activityTitle :将在频道中显示在通知顶部的文本
  • activitySubtitle :是您的通知消息的内容。
  • 在你的通知顶部,你会看到一行出现。该值用十六进制色码定义其颜色。

发送消息

如前所述,要发送通知,您需要发送一个包含数据的 post 请求。Post 请求可能不是从普通浏览器发送的,但是可以很容易地用 Python 来管理。

而要发送 post 请求,没有什么比使用请求包更简单的了,为人类简化 HTTP。

从 Python 脚本发送请求

执行这段代码基本上会将通知发送到您的通道😎

不用说,互联网连接对于这一步是绝对必要的。

图 9 —您的第一个自动通知

您可以看到与所使用的十六进制颜色值“ 00FF00 ”相对应的绿线。

注意:除了使用 python 进行 post 请求,还可以使用软件如 postman 来发送通知。

图 10 —使用邮递员的自动通知—团队中的传入 Webhook

结果会非常相似(不是说完全一样!).

图 11 —您的第二个自动通知

它可能对测试有用,但不用说使用 python 会更容易进行进一步的集成!

格式化内容

您的消息内容必须包装在字符串中。因此,它可以用基本文本编写,如本例所示。但是您也可以使用团队降价解决方案。但是因为它使用了你也可以在你的信息中使用的标记,我推荐使用标准的 HTML 格式,它可以被 webhook 理解。

HTML 格式的通知

如果你想使用 multiline,<br>标签将是你最好的朋友。在 Python 中使用三重引号字符串可以产生一种视觉效果,因此您可以实现“回车”效果。

图 12 — HTML 格式和复杂的自动通知

如果你想在消息中使用变量,我建议使用 f 字符串。然后你完全可以创建动态代码

使用 Python 和 f 字符串动态创建 HTML 内容

⚠️ 删除消息:使用 webhook url,目前无法删除消息。所以要小心你用它发送的数据。

收到警报

您现在知道如何在频道上发布消息。但是因为它没有提到你(对于这个基本的通知解决方案来说是不可能的),你必须订阅频道通知。

  1. 打开频道设置" "
  2. 点击"🔔频道通知
  3. 选择自定义

图 13 —更新通知参数

4.如图图 14 所示设置参数。

图 14 —自定义通知参数

5.点击保存按钮

现在你可以尝试重新发送消息,你会收到一个真正的团队通知。如果你在手机上安装了这款应用,你会收到通知。

图 15 —在电脑(左图)和手机(右图)上接收通知

丢失 bot URL

如果你不记得机器人的网址是什么,不要惊慌。总是可以在配置中找到它。

  1. 点击通道设置“ ”,打开“连接器
  2. 在窗口的左侧,点击“已配置的
  3. 🛑做不做点击配置按钮
  4. 但请点击“ 1 已配置”链接
  5. 点击管理按钮

图 16 —返回到现有的传入 Webhook 的配置

然后,您将能够修改 bot 的配置,并再次复制要使用的 URL。

结论

今天,我们在团队频道中创建和配置了一个 Webhook URL。然后我们看到了如何创建发送到这个 webhook 的内容,最重要的是如何使用 python 进行发送过程。

这允许你包含警报代码 ATAWAD (任何时间,任何地点,任何设备),因为你有互联网连接,并从你的手机接收这些警报或消息,为你或你当前的项目团队。

如果你喜欢这个帖子并想了解更多,你可以在媒体上关注我,成为会员,在 LinkedIn 上与我联系,或者访问我的网站

希望你喜欢&回头见🤠

自动化启动 Django 项目的枯燥工作

原文:https://towardsdatascience.com/automate-the-boring-stuff-of-starting-a-django-project-814c80647c3b

运行一个脚本,按照您需要的方式设置项目

照片由 Diego PHUnsplash 上拍摄

简介

这篇文章的标题显然是对 Al Sweigart 的书 的致敬,这本书用 Python 自动化了枯燥的东西,我总是推荐给那些想以正确的方式开始学习 Python 的人。虽然 Al 的书没有涵盖 Django,但它让读者很好地理解了 Python 是如何成为自动化枯燥、重复的日常任务的伟大工具。

你们中的一些人,在阅读了我的一篇或多篇教程后,可能已经知道我是姜戈的忠实粉丝。但我们必须承认,当开始一个新的 Django 项目时,我们需要在终端上运行大量命令,手动创建一些文件夹和文件,并在其他一些文件夹和文件上进行周期性的更改。大多数初始任务都是重复性的,这为自动化提供了很好的机会。

因此,我写了这个 Python 脚本,它允许我在开始工作之前,按照我需要的方式创建一个新的 Django 项目。与另一种方法相比,我更喜欢这种方法,即复制或克隆一个 starter Django 项目。事实上,我认为这个脚本给了我更多的灵活性,可以按照我需要的方式定制最初的项目结构,例如,如果我愿意,可以一次创建两个、五个、十个或一百个应用程序。

(这里有个小提示:请不要在你的 Django 项目上创建一百个应用。你能,不代表你应该)。

我不会一行一行地讨论我的代码,因为你可以参考README.md文档和关于my_django_starter.py的评论来了解细节。我将对我想通过编写这个自动化脚本来解决的问题做一些评论。

我的完美 DJANGO 启动项目特色

1.它已经包含了我工作中需要的所有新应用程序文件夹,具有以下特征:

  • 一个APP_NAME/templates/APP_NAME文件夹;
  • 一个urls.py文件,因为我喜欢让我的应用程序路径由应用程序文件夹中的一个特定的urls.py文件处理;
  • urls.pyviews.py中的代码足以让路线http://localhost:8000/APP_NAME工作。

2.已经执行了以下终端命令:

django-admin startproject PROJECT_NAME .python manage.py startapp APP_NAME # for each apppython manage.py migratepython manage.py createsuperuser

3.这些额外的文件夹被创建并准备好使用:

/media
/scripts
/templates
/templates/static

4.对PROJECT_NAME/settings.py文件的修改:

  • django_extensions包和我的所有应用名称已经自动包含在INSTALLED_APPS列表中;
  • 设置staticmediatemplates目录的代码;
  • 初始多行注释已经删除(与urls.py中的注释相同)

5.在PROJECT_NAME/urls.py文件中的改变,使得应用程序urls.py文件已经被包括并且它的初始路线可以被导航。

这都是通过遵循我在关于如何将 Python Jupyter 笔记本转换成 RMarkdown 文件的文章 中已经探索过的原则实现的: : .py.html文件是纯文本文件,因此它们可以被我们的 Python 代码作为字符串读取、编辑和保存。

结束语

我们可以为一个初始的 Django 项目制作更进一步的自动化代码,比如:

  • 创建带有{% extends 'base.html' %}{% block content %}标签的模板文件;
  • 从一开始就让其他一些文件和目录可用;
  • 添加代码,从我们在my_django_starter.pyconfig_info部分设置的值自动改变LANGUAGETIMEZONE
  • 如果我们正在用基于类的视图制作 CRUD 应用程序,我们已经可以用由类视图要求的名字(APP_NAME_list.htmlAPP_NAME_form.htmlAPP_NAME_detail.html等等)构成的.html文件填充templates/APP_NAME文件夹,我们也可以给它们一些基本的内容;

现在轮到您了:创建您自己的自动化脚本,以您需要的方式启动您的新 Django 项目。只是不要在不必要的时候一遍又一遍地输入相同的命令。你是一个程序员:写一个程序让它为你工作。

如果你想了解更多关于 Django 的内容,请查看下面链接的文章。

亲爱的读者,我再次感谢你花时间和精力阅读我的文章。

快乐编码

自动化关系数据集的要素工程管道

原文:https://towardsdatascience.com/automate-the-feature-engineering-pipeline-for-your-relational-dataset-1908aba5610c

面向自动化要素工程的开源 Python 框架基本指南

图片由穆罕默德·哈桑拍摄,来自皮克斯拜

特征工程是数据科学模型开发流程中重要且耗时的组成部分。特征工程管道决定了模型的鲁棒性和性能。

有各种自动化要素工程包可为单个数据集处理和创建要素。但是这些包不适用于涉及使用多个关系数据集的用例。合并多个关系数据集并从中计算要素是一项繁琐而耗时的任务。在本文中,我们将讨论一个开源包 Featuretools,它可以通过几行 Python 代码从时态和关系数据集自动创建要素。

功能工具:

Featuretools 是一个开源的 python 框架,用于为时态和关系数据集的预测建模用例自动化特征工程管道。Featuretools 库 的一些 关键特性有:

  • 深度特征合成: Featuretools 包提供了 DFS 来从关系数据集中自动构建有意义的特征。
  • 精确处理时间: Featuretools 提供了 API 来确保只有有效的数据用于计算,使您的特征向量免受常见标签泄漏问题的影响。
  • 可重复使用的特征基元:特征工具提供低级功能,可叠加创建特征。定制原语可以在任何数据集上构建和共享。

Featuretools 软件包与其他流行的软件包兼容,如 Pandas、NumPy 和 scikit-learn,并在很短的时间内创建有意义的功能。

你可以看看我以前的一篇关于自动化特征工程的文章:

实施:

可以使用**pip install featuretools** 从 PyPI 安装 Featuretools 库。

读取数据集:

我们将使用一个模拟样本关系数据集,该数据集具有事务会话客户表。可以使用 featuretools **load_mock_customer()**函数生成模拟数据集。

上述数据集之间的关系是:

(图片由作者提供),关系表之间的关系

指定关系:

  • 首先,我们用数据集中的所有实体指定一个字典(第 1-5 行)。
  • 其次,我们指定实体是如何关联的(第 7-10 行)。当两个实体具有一对多关系时,我们将“一”实体称为“父”实体,其余的实体称为子实体。父子关系定义为:***( parent_table, parent_key, child_table, link_key )*** 为元组列表。

生成要素:

Featuretools 包提供了**dfs()**功能,可以使用深度特征合成生成相关特征。深度特征合成(DFS)是一种对关系数据和时态数据执行特征工程的自动化方法。

通常,如果没有 featuretools,数据科学家将编写代码来为客户汇总数据,并应用不同的统计函数来生成量化客户行为的功能。但是 DFS 算法可以通过指定target_dataframe_name="customers"来生成这些特征,其中‘客户’是集合所有数据的数据集。

在调用**dfs()**函数时,它会在短时间内返回特征工程矩阵和特征描述。通过提供上述 3 个关系数据集并聚合客户数据,我们得到 75 个聚合特征。

结果:

75 个自动生成特征的描述可以从下面的快照中观察到:

(GIF by Author),功能工具生成的功能上的功能描述

结论:

在处理涉及关系数据集的用例时,数据科学家必须手动聚合数据,并使用不同的统计技术创建要素。Featuretools 是一个方便的包,能够从多个表中优雅地提取要素,并将它们聚合到一个最终的数据集中。这为数据科学家节省了大量的时间和精力,他们可以花更多的时间来执行一些高级的功能工程。

参考资料:

[1]功能工具文档:https://www.featuretools.com/

感谢您的阅读

用几行 Python 代码实现时间序列特征工程的自动化

原文:https://towardsdatascience.com/automate-time-series-feature-engineering-in-a-few-lines-of-python-code-f28fe52e4704

为您的时间序列用例提取数百个相关特征

图片来自皮克斯拜扬·瓦塞克

时间序列数据随着时间的推移重复捕获变量的值,从而产生一系列按时间顺序索引的数据点。在时间序列中,数据具有自然的时间顺序,即特定时间的变量值取决于过去的值。

传统的机器学习算法不是为了捕捉时间序列数据的时间顺序而设计的。数据科学家需要执行功能工程,将数据的重要特征捕获到一些指标中。生成大量的时间序列特征并从中提取相关特征是一项耗时且乏味的任务。

在这里 tsfresh 包发挥了作用,它可以为您的时间序列数据生成标准的数百个通用特征。在本文中,我们将深入讨论 tsfresh 包的用法和实现。

tsfresh:

tsfresh 是一个开源包,可以生成数百个相关的时间序列特征,适合训练机器学习模型。从 tsfresh 生成的特征可用于解决分类、预测和异常值检测用例。

开始使用:

tsfresh 包提供了对时间序列数据执行特征工程的各种功能,包括:

  • 特征生成
  • 特征选择
  • 与大数据的兼容性

安装和使用:

tsfresh 是一个开源 Python 包,可以通过以下方式安装:

**pip install -U tsfresh**
# or
**conda install -c conda-forge tsfresh**

1)特征生成:

tsfresh 包提供了一个自动特性生成 API,可以从 1 个时间序列变量生成 750 多个相关特性。生成的特征包括宽范围的光谱,包括:

  • 描述性统计(平均值、最大值、相关性等)
  • 基于物理学的非线性和复杂性指标
  • 数字信号处理相关特性
  • 历史压缩特征

用法:

一个数据科学家不需要在特征工程上浪费时间。**tsfresh.extract_features()** 函数为 1 个时序变量从多个域生成了 789 个特征。

(作者代码)

人们可以浏览 tsfresh 文档来获得提取特征的概述。

2)特征选择:

tsfresh 包还提供了基于假设检验的特征选择实现,可以识别目标变量的相关特征。为了限制不相关特征的数量,tsfresh 部署了 fresh 算法(fresh 代表基于可伸缩假设测试的特征提取)。

**tsfresh.select_features()** 功能用户可以实现特征选择。

3)与大数据的兼容性:

当我们有大量的多时间序列数据时。tsfresh 还提供 API 来扩展大量数据的特征生成/提取和特征选择实施:

  • 多处理:默认情况下,tsfresh 包可以在多个内核上并行执行特征生成/提取和特征选择实现。
  • tsfresh 自己的分布式框架 用于扩展适合单台机器的数据的实施,并将特性计算分布在多台机器上以加快计算速度。
  • Apache spark 或 Dask 对于不适合单机的数据。

这里有一篇 Nils Braun 的精彩文章,解释了使用 Dask 实现 ts fresh(文章第 1 部分文章第 2 部分)。

https://nils-braun.github.io/tsfresh-on-cluster-1/

结论:

tsfresh 是一个方便的包,可以在几行 Python 代码中为时间序列特性生成和选择相关特性。它自动从基于时间的数据样本的多个域中提取和选择 750 多个经过实地测试的要素。它减少了数据科学家浪费在特性工程上的大量工作时间。

通常,时间序列数据是相当大的,tsfresh 包也可以解决同样的问题。tsfresh APIs 可以应用于使用多处理、dask 或 spark 的大型数据样本。

参考资料:

[1]t 新鲜文档:【https://tsfresh.readthedocs.io/en/latest/

[2]尼尔斯·博朗 GitHub 文章:https://nils-braun.github.io/tsfresh-on-cluster-1/

感谢您的阅读

使用 Python 自动编辑视频

原文:https://towardsdatascience.com/automate-video-editing-with-python-4e0c43edef36

自动编辑 explainer 视频,为仓库操作员的培训创建带有文本到语音注释的短片

(图片由作者提供)

场景 你是一家国际时装零售商物流部的运营经理

为了支持新操作员和管理人员的入职培训,您需要准备培训视频。

训练屏幕示例—(图片由作者提供)

你的同事给你分享了一个讲解人视频 (视频作者)介绍了仓库收货的所有流程。

要制作会议动画,您需要将此视频剪成短片,解释每个过程。

在本文中,我们将探索一种使用 python 库 Moviepy 来自动化这些简单视频编辑任务的方法。

💌新文章直接免费放入你的收件箱:时事通讯

如何用 Python 编辑视频?

培训材料

在本视频中,您完整地展示了仓库接收产品的几个过程。

视频中呈现的流程—(视频作者:供应科学)

因此,您可能希望使用这段列出不同流程的视频作为入职培训的培训支持:

  • 总时长:00 分 03 秒 18
  • 包括引言和结尾在内的 18 个部分
  • 背景音乐,但没有背景声音

目标

您想要剪切视频,删除背景音乐,并创建带有音频评论的短片。

三步工作流程—(图片由作者提供)

想法是使用 Python 构建一个自动化的工作流,它将

  1. 加载原始视频
  2. 移除背景音乐
  3. 将视频剪切成几个镜头,分别聚焦于不同的过程
  4. 添加通过文本到语音转换解决方案生成的音频注释

解决办法

有一个使用 Python 库 Moviepy 的解决方案。更多细节,我强烈建议看一下文档

如果你也想自动化图形设计,有另一个教程适合你

履行

步骤 1:加载视频

我们首先加载原始视频的. mp4 文件,你可以在我的 Youtube 频道上找到它。

第二步:剪切视频

由于您希望专注于某些特定流程,因此不会使用整个视频。

通过在特定时间剪切生成短片—(图片由作者提供)

因此,我们需要找到一种方法来剪切特定时间的视频,以生成将用于显示特定过程的短剪辑。

功能:换算成秒

💡见解
我们稍后开始剪辑视频时会用到这个功能。

动作:剪切视频

📹结果

(作者视频)

💡见解
你有一个短视频剪辑,背景音乐是在正确的时间戳从原始视频中剪下的。

第三步:去除声音

你想播放没有声音的视频,所以你想脱下短裤,去掉声音。

📹结果

💡见解
你也可以运用体积的分数运用。低于 1(减少)或高于 1(增加)的 volumex(分数)

第四步:合并两条短裤

你剪了两个视频,你想连续播放?为此有一个 Moviepy 函数,

📹结果

第五步:堆叠视频

你想同时显示几个进程?您可以将视频堆叠在同一个屏幕上。

📹结果

堆叠视频—(图片由作者提供)

第六步:增加一些滞后

如果你想堆叠视频,但每个视频之间有 5 秒钟的延迟,这是可以做到的。我不知道为什么有人会这么做,但为什么不呢!)

📹结果

带滞后的堆叠视频—(图片由作者提供)

最后一步:添加文本到语音的注释

我们已经使用文本到语音的 API 生成了评论。我们能把它们加到视频里吗?

答案是肯定的!

📹结果

💡见解
Google TTS(free tier)很烂!你知道价格合理的更好的吗?

结论

关注我的媒体,获取更多与数据分析和生产力相关的文章。

当然,我们离 Adobe Premiere 或 Final Cut Pro 还很远。但是,如果您需要简单的编辑任务,它也能胜任。

此外,我只和你分享了图书馆能做的一小部分。我强烈建议看一下文档以获得更多的见解。

现在,您可以开始设计培训材料或启动全自动 Tiktok 频道了。

关于我

让我们在 LinkedinTwitter 上连线,我是一名供应链工程师,正在使用数据分析来改善物流运作和降低成本。

如果你对数据分析和供应链感兴趣,可以看看我的网站

https://samirsaci.com

我在一个专门的 Youtube 频道上分享了其他关于自动化手工任务的视频教程,如 PowerPoint、平面设计或商业规划。

https://www.youtube.com/channel/UCiYf8BKpRmuPMLnoic74LyA/videos

如果您想了解更多有关生产力和任务自动化数据分析的信息,

http://samirsaci.com

用 Python 三步实现 WhatsApp 消息自动化

原文:https://towardsdatascience.com/automate-whatsapp-messages-with-python-in-3-steps-d64cf0de4539

使用 Python 向联系人和群组发送 WhatsApp 消息

Eyestetix 工作室Unsplash 拍摄的照片

用 Python 可以做的最酷的事情之一就是自动化日常任务。大概我们每天最常见的任务就是在 WhatsApp 上发消息。

尽管这项任务简单得就像拿起电话、打字、点击“发送”按钮一样,但我们有时会忘记在特殊场合(生日、周年纪念日等)发送信息。

我们可以用 Python 安排 WhatsApp 消息吗?

当然可以!我们只需要安装一个名为 pywhatkit 的库。然后,我们可以安排将消息发送给我们的任何联系人,甚至发送给一个群组。

以下是使用 Python 向联系人和群组发送 WhatsApp 消息需要遵循的 3 个步骤。

免责声明:本指南仅用于教育目的。在学习 Python 时,您可能会使用这个库来安排生日/周年纪念消息,但我不建议您在需要发送需要保持私密的消息时使用它。

使用 pywhatkit 向 WhatsApp 发送消息

Pywhatkit 是一个用于不同目的的 Python 库,其中之一就是发送 WhatsApp 消息。

这是一个易于使用的库,不需要任何额外的设置。也就是说,它有很多依赖项,所以我强烈建议您将它安装在一个新的虚拟环境中(在这里了解如何设置虚拟环境)。

如果你不想看,可以看我的视频!

请务必在此订阅以获取我的自动化备忘单(免费 PDF)

步骤 1:安装 pywhatkit

要安装 pywhatkit 的最新版本,打开终端并运行以下命令。

pip install pywhatkit

安装可能需要几秒钟甚至一分钟,所以请耐心等待。一旦安装了这个库,就可以用命令pip list检查这个库安装的所有依赖项。

第二步:向 WhatsApp 上的联系人发送消息

在我们开始发送消息之前,您必须通过 WhatsApp Web 登录您的 WhatsApp 帐户。如果你没有登录,手机和电脑不在同一个 WiFi 上,或者手机离电脑很远,这个方法就不管用了。

要使用 Python 和 pywhatkit 向 WhatsApp 联系人发送消息,我们使用下面代码所示的.sendwhatmsg方法(改为插入您的联系号码)。

**import** pywhatkit*# syntax: phone number with country code, message, hour and minutes*
pywhatkit.sendwhatmsg('+1xxxxxxxx', 'Message 1', 18, 52)

这个代码的意思是“键入‘消息 1’并在 18:52 将其发送给联系人 X”

运行上面的代码后,您会得到类似这样的消息:

10 秒后,web.WhatsApp.com 将打开,15 秒后,Whatsapp 将发送一条消息。

就是这样!几秒钟后,您的浏览器将会打开,消息将会发送给您的联系人。

重要提示:当您的浏览器打开时,会弹出一条授予访问权限的消息。您必须接受此消息(如果您不授予权限,库将无法控制您的浏览器)。

您也可以手动执行此操作。在 macOS 上,你必须进入“系统偏好设置”,点击“安全与隐私”,选择“可访问”,然后勾选“终端”框。

作者图片

太好了!现在,我们还可以在浏览器中自定义其他操作。

假设我们想在发送消息 2 秒后关闭标签页。我们这样做,运行下面的代码。

**import** pywhatkitpywhatkit.sendwhatmsg(“+1xxxxxxx”, “Message 2”, 18, 55, 15, **True**, **2**)

这里的“真”表示我们希望在消息发送后的“X”秒后关闭标签。最后一个参数“2”表示这个“X”秒。

第三步:向 WhatsApp 上的一个群发送消息

我们还可以向 WhatsApp 上的特定群组发送消息,但首先,我们必须获得群组 id。

要查找 id,请按照下列步骤操作:

  1. 打开任何你想要的群组,点击“群组信息”部分
  2. 向下滚动,找到“通过链接邀请”选项。点击该选项
  3. 你会看到一个链接。复制链接。链接的后缀部分是组的 id。

作者图片

一旦您有了将用于这个测试的组的 id,我们就必须使用.sendwhatmsg_to_group方法。这个方法类似于我们在步骤 2 中使用的方法,但是现在我们插入一个组 id。

**import** pywhatkit*# syntax: group id, message, hour and minutes*
pywhatkit.sendwhatmsg_to_group("write-id-here", "Message 3", 19, 2)

就是这样!注意 pywhatki 还有其他方法。你也可以使用.sendwhatmsg_instantly.sendwhatmsg_to_group_instantly即时发送信息,但它们对我不起作用。

以防万一,下面是我们在本教程中使用的.sendwhatmsg.sendwhatmsg_to_group的参数。

  • phone_no (str):接收方的手机号码
  • group_id (str):组的 id
  • 消息 (str):待发送的消息
  • time_hour (int,0–24), time_min (int):预定时间的小时和分钟
  • wait_time (int = 15):等待消息送达的时间(默认设置为 15 秒)
  • tab_close (bool = False):如果您将此项设置为 True,那么当消息发送后,标签将在 X 秒后关闭
  • close_time (int = 3):表示消息发送后标签页关闭的秒数

https://frankandrade.ck.page/44559e1ae7

如果你喜欢阅读这样的故事,并想支持我成为一名作家,可以考虑报名成为一名媒体成员。每月 5 美元,让您可以无限制地访问数以千计的 Python 指南和数据科学文章。如果你用我的链接注册,我会赚一小笔佣金,不需要你额外付费。

**https://frank-andrade.medium.com/membership **

使用 GitHub 动作和 Cron 自动化您的工作流程

原文:https://towardsdatascience.com/automate-workflow-github-actions-cron-130a8bf68ca6

辅导的

使用 GitHub 动作和 Cron 自动化您的工作流程

了解如何使用 GitHub Actions 免费运行基于时间的任务/脚本

安德烈·德·森蒂斯峰在 Unsplash 上拍摄的照片

在本帖中,我们将介绍一个简单而强大的工具,它可以根据基于时间的计划自动运行你的脚本(或者你可以编程的任务)。

如果您经常手动运行脚本,那么您很有可能从自动化过程中受益,并设置一个自动运行的时间表,而不必担心它。就设置一次,然后就忘了它。

这种自动化的一些例子是:

  • 解析 RSS 源并自动发送电子邮件,
  • 在您正在使用但没有本地集成的两个服务之间进行集成!(本帖中有一个例子),
  • 从数据源提取数据并操纵数据,

在这篇文章中,我交替使用了任务和脚本这个词。此外,GitHub Actions 用来创建自动化任务/脚本的 YAML 文件称为工作流文件。

要求:您希望按基于时间的计划运行的脚本

最重要的部分是有一个我们想要运行的脚本。这取决于你的任务是什么。我将带你看的例子是使用 Zotero2Readwise Python 库(免责声明:我开发了这个库!)。

我将在这篇文章中运行的脚本是这里的。因为我的脚本是用 Python 写的,所以,我会像下面的python run.py <app1_token> <app2_password> <app2_user>那样运行它。在我的个人笔记本电脑上运行这个很好,因为我已经设置好了一切。但是如何在 GitHub Actions 中按照预定义的时间表运行呢?

自动化前的考虑

你的剧本很可能会有所不同。然而,下面的提示可以帮助你开始:

首先,在您的系统上运行脚本。一旦您对结果感到满意,并且想要自动化工作流程,那么请按照下面的说明,使用 GitHub Actions 设置一个预定的工作流程。

当开发一个自动化任务时,考虑如何从一个新的操作系统开始运行它总是好的!这就好像你有一个新的系统,你试着在那里运行你的脚本。问自己几个问题:

  • 我应该从哪里开始?
  • 在运行脚本之前,我需要安装哪些软件/库?
  • 在哪里可以找到我想要运行的脚本?
  • 我是否需要传递一些环境变量或敏感信息,如密码?
  • 我应该如何传递敏感信息,如密码或令牌?

我将为我的工作流程回答上述问题。希望这能给你足够的信息来自动化你的任务!

GitHub 操作设置

首先,我们需要在我们的存储库中创建.github/workflows目录。这是我们的自动化文件(应该是YAML格式)所在的地方。我们将检查文件的每一部分。

你可以在这里学习 GitHub 动作的基础知识。

任何 GitHub Actions 工作流的第一部分都是指定工作流何时触发。这可以通过使用on关键字来实现。因为我们想要一个预定的自动化,我们可以在一个使用cron符号的schedule上运行工作流(在下一节中讨论)。除了按计划运行之外,我还想在任何变更被推送到master分支时运行工作流。

您还可以在一个拉请求上触发您的工作流(使用pull_request关键字)。

克隆(克隆作业)

cron 工具,也称为 cronjob ,基本上是一个作业调度器。用于安排重复性任务。其语法由如下 5 个字段组成:

* * * * *

上面的 cron 作业语法意味着每分钟运行一个任务。可以看出,下表给出了 5 个部分(注意从左到右的顺序)

Cron 工作示例

下面的例子涵盖了 cron 语法的不同方面和所有有效字符(* , - /)。

  • 您可以通过为每个部分选择一个有效的数字来指定您的计划。*表示“每”* ( * * * * *表示在一周的每一天,每月的每一天,每小时的每一分钟🙂).再比如30 13 1 * *表示月 1 日 13:30。*
  • 通过使用值列表分隔符,,给定部分可以有多个参数。例如,* * * * 0,3表示仅在周日和周三的每分钟。**
  • 您可以使用/获得步长值。例如,/10 * * * *表示每 10 分钟一次。**
  • 使用破折号-可以有一个数值范围。例如,4-5 1-10 1 *表示一月第 1 天到第 10 天之间 04:00 - 05:59 AM 之间的每一分钟。**

当然,你也可以有上述选项的组合。例如,*/30 1-5 * 1,6 0,1表示仅在 1 月和 6 月的周日和周一,01:00-05:59 AM 之间每 30 分钟一次。**

检查crontab crontab 专家 为你的日程安排提出 cron 语法。

用例 1

正如我前面提到的,我想使用 Zotero2Readwise Python 库自动化我的 ZoteroReadwise 集成。让我们来回答我们之前提出的问题:

应该从哪里入手?

我们可以从一个全新的 Ubuntu 系统开始。因此,我们在作业下面的部分指定了runs-on: ubuntu-latest,它将作业配置为在包含最新版本 Ubuntu Linux 的全新虚拟机上运行。

下一步是克隆当前的回购。你可以通过使用uses关键字允许我们使用来自GitHub Actions market place的任何动作来实现这一点。我们这里可以使用actions/checkoutmaster分支(也可以像actions/checkout@v2一样指定版本)。

*- name: 🍽️ Checkout the repo
  uses: actions/checkout@master
  with:
    fetch-depth: 1*

我们必须安装哪些软件/库?

只有在必须安装库的情况下,才需要这一步。在我的情况下,我必须首先安装 Python 3.8。这可以通过使用actions/setup-python@v2 GitHub 动作来实现。之后,我们要安装 python 包。我们可以通过运行pip install zotero2readwise来安装 Zotero2Readwise 包。然而,为了在转轮上执行命令,我们必须使用run关键字。

*- name: 🐍 Set up Python 3.8
  uses: actions/setup-python@v2
  with:
    python-version: '3.8'- name: 💿 Install Zotero2Readwise Python package
  run: pip install zotero2readwise*

在哪里可以找到我想要运行的脚本?

如果您尝试运行的脚本位于同一个存储库中,您可以跳过这一步。但是在这里,由于我想要运行的 Python 脚本位于另一个 GitHub 存储库中,所以我必须使用curl Linux 命令下载脚本。

运行脚本

现在我们已经设置了我们的环境,我们可以像前面在需求部分提到的那样运行脚本了。

但是最后一点是,由于我们需要传递一些敏感信息(比如令牌),我们可以通过将秘密传递给设置→秘密→新存储库秘密来实现。

如何将秘密传递到 GitHub 存储库的环境中(图片由作者提供)

这些秘密将可以使用下面的语法:${{ secrets.YOUR_SECRET_NAME }}在你的 YAML 文件中。

有关处理变量和秘密的更多信息,您可以查看 GitHub 文档中关于环境变量加密秘密的以下两页。

现在我们已经添加了我们的秘密,我们可以如下运行脚本:

把所有东西放在一起

包含上述所有步骤的文件如下所示。该文件位于 GitHub 上。

完整的 GitHub 动作工作流文件。

GitHub 操作的截屏显示了工作流是如何按计划运行的,或者是如何通过推送到主分支的。(图片由作者提供)

用例 2

按照上面的过程,我设置了一个 GitHub 页面的定期更新,每周运行两次。到目前为止,它一直工作得很好(到目前为止,写这篇文章已经一年多了)。这种自动化实现了以下功能:

  1. 解析我的个人博客并获取标题和我最新文章的链接。
  2. 将博客文章添加到我的 GitHub README 页面的一个部分。
  3. 在页脚中添加关于自动生成的自述文件页面的日期和时间的注释。

你可以在 GitHub 上找到运行上述任务的文件。这个自动化还运行一个 python 脚本

GitHub 操作成本

**GitHub Actions 对公共存储库免费使用。然而,私有存储库的免费计划有一些限制(在发表这篇文章时,GitHub Actions 免费计划提供 2000 分钟(每月)和 500MB 的存储空间,这对大多数用例来说应该足够了)[1]。

结论

在这篇文章中,我们看到了如何使用 GitHub Actions 根据时间表运行任务。天空是这里的极限。想想你目前经常运行的工作流或任务。如果您可以将任务放在可以在您的计算机上运行的脚本中(不管是 Python、Bash 还是任何其他脚本),那么您实际上可以设置自动化。

感谢阅读🙏

加入我的邮件列表,接收类似的帖子。也可以在LinkedInTwitter 关注我。

👉如果你喜欢阅读这样的故事(以及媒体上的其他故事),也想直接支持我和数千名其他作家,可以考虑注册https://medium.ealizadeh.com/membership来获得所有故事的全部访问权限(免责声明:如果你使用我的链接注册,我会为你赚取一小笔佣金,不需要额外费用。)**

*https://medium.ealizadeh.com/membership

参考

[1] 关于 GitHub 动作的计费*

👉原载于https://ealizadeh.com

有用的链接

*https://www.hostinger.com/tutorials/cron-job https://docs.github.com/en/actions/learn-github-actions/understanding-github-actions

您可能感兴趣的其他帖子:

*

2022 年及以后,使用 Python 自动处理您的电子邮件

原文:https://towardsdatascience.com/automate-your-emails-with-python-for-2022-and-beyond-2284054d1012

如何在最新的 2022 更新和安全变更中使用 Python 实现电子邮件自动化

维塔利·神圣在 Unsplash 上的照片

自从互联网建立以来,电子邮件一直是最受欢迎的交流方式之一。虽然在现代世界中,其他的物理交流方式似乎正在消失,但电子邮件在众多任务中的突出地位仍然适用。

电子邮件具有广泛的应用。我们利用电子邮件与不同类型的人或公司交流。无论你是想给雇主、雇员或职员发信息,提交简历,要求澄清,还是执行各种其他类似的任务,电子邮件都是最直接、最受欢迎的沟通方式。

在这篇文章中,我们将看看谷歌的最新安全更新。然后,我们将通过遵循一些额外的安全步骤,探索获得安全应用程序密码的最有效方法。最后,我们将利用 Python 来构建我们的电子邮件自动化,通过它我们可以轻松地向一个或多个电子邮件地址发送邮件。

在开始这个项目之前,提高您的 Python 基础是一个好主意。我推荐通过下面提供的链接查看我的关于七种最佳 Python 编程实践的文章,以提高您的工作效率。其中一些技巧甚至适用于本文!

</7-python-programming-tips-to-improve-your-productivity-a57802f225b6>

Google 帐户的安全更新:

照片由布雷特·乔丹Unsplash 拍摄

在我们开始自动化电子邮件项目之前,我们需要一些额外的权限,这些权限必须由电子邮件 web 服务授予。在这篇文章中,我们将看看如何访问你的 Gmail 和 Google 账户。一旦我们完成了本节中的步骤,我们就可以继续编写 Python 文件来使用生成的密码访问帐户。

以前,我们可以打开对不太安全的登录的访问。执行以下步骤将允许我们通过 Python 直接访问我们的帐户。(链接)。然而,随着谷歌更新其安全措施,这一步骤现已被取代。因此,它不再允许这种方法。以下是为感兴趣的用户提供的详细信息。

一些应用和设备使用不太安全的登录技术,这使您的帐户容易受到攻击。你可以关闭对这些应用的访问(我们建议你这样做),或者如果你想不顾风险使用它们,也可以将其打开。如果不使用,Google 会自动关闭此设置。

为了帮助保护您的帐户安全,从 2022 年 5 月 30 日起,Google 不再支持使用要求您仅使用用户名和密码登录 Google 帐户的第三方应用程序或设备。

正如上面的截图所强调的那样,前面提到的方法不再适用于谷歌的新安全更新。因此,我们将使用更安全的应用程序生成的密码,该密码将在完成以下步骤后自动提供。让我们分析一下如何获得应用程序密码,以便使用 Python 自动处理您的电子邮件。

  • 登录您的 Gmail 帐户
  • 点击管理您的帐户
  • 选择安全选项并启用双因素身份验证(2-FA)
  • 一旦 2-FA 选项可用,您现在可以选择创建应用程序密码
  • 按照步骤生成并保存您的应用程序密码。以下唯一生成的应用程序密码将用于此 Python 项目。

免责声明: 本节描述的步骤提供了额外的安全性,据我所知,执行这些步骤基本上是安全的。请验证这些步骤并小心操作。要了解更多信息,我建议观众访问官方网站,按照这个链接的步骤进行操作。

开发 Python 项目来自动化您的邮件:

照片由拉诺尔特Unsplash 上拍摄

在文章的这一部分,我们将着重于相应地编写自动化电子邮件所需的程序。我们将构建所有必要的 Python 文件,导入必要的库,并编写自动向一个或多个其他电子邮件地址发送电子邮件的结构。让我们从构建一些先决条件 Python 文件开始。

1.先决条件 Python 文件:

在我们深入主要的 Python 文件之前,让我们创建几个额外的 Python 文件。这些文件主要用于存储您的个人电子邮件地址和其他电子邮件地址列表。我们将创建这两个 Python 文件,用于维护我们个人数据的隐私和安全需求。如果您想要使用不同的登录或更改电子邮件地址列表,您可以修改这些文件。

为了创建第一个 Python 文件,我们将它命名为my_email.py,通过它我们将存储我们的电子邮件地址和特定的应用程序密码,这些密码是我们之前通过身份验证步骤生成的。下面的代码片段显示了如何用相应的参数描述必要的变量。您可以在方便的时候编辑电子邮件和密码。

email_mine  = "Your_Email@gmail.com"
password_mine  = "******"

在第二个 Python 文件中,我们将列出存储发送邮件所需的每个电子邮件地址的各个变量。确保将 Python 文件命名为email_addresses.py以便于访问。下面是关于如何定义电子邮件地址列表的代码片段。

email1 = "email_id_1"
email2 = "email_id_2"

一旦您完成了两个主要 Python 文件的创建,我们就可以继续创建主 Python 文件了。完成后,我们可以导入必要的库。新创建的 Python 文件可以被命名为任何东西,但是如果你想跟随教程,你可以把它命名为automate_email.py.

2.必要的库导入:

这个项目需要的主要库是 smtplib 库,我们可以用它来导入 SMTP 模块。简单邮件传输协议(SMTP)是一种互联网通信协议,允许用户建立连接或媒介,通过互联网将电子邮件从一个帐户传输到另一个帐户。其他必要的导入将是之前创建的 Python 模块以及它们各自的变量。我们将相应地使用这些进口。

# Importing all the necessary requirements
from smtplib import SMTP
from my_email import email_mine , password_mine
from email_addresses import email1, email2

第二个和第三个 Python 模块及其各自的变量可以根据开发人员的偏好进行更改。随意添加和试验不同的定制。

3.连接和登录:

导入所有基本库和模块后,我们可以创建一个安全连接并登录到我们的电子邮件帐户。第一步,我们将端口号设置为 587,并建立到 gmail.com 的连接,我们将在那里解释我们的电子邮件。第二步,我们将调用 ehlo()函数。

此功能是 SMTP 协议的扩展版本,用于增加安全性和识别发送主机的域名。在下一步中,我们建立一个到服务器的传输层安全或安全套接字层连接。starttls()命令将帮助我们将不安全的网络变成安全的网络。

最后,我们可以考虑之前导入的变量,登录到我们的电子邮件地址。在前面步骤中定义的端口变量可用于使用您想要的凭证登录。下面是计算本节中所有步骤的代码块。

# Creating the respective object along with the gmail login and port number
smtp_port = SMTP("smtp.gmail.com", 587)# Establishing a connection to the SMTP server with Transport Layer Security (TLS) mode
smtp_port.ehlo()# Informing the client to establish a secure connection, either to a TLS or SSL
smtp_port.starttls()# Logging into your account
smtp_port.login(email_mine , password_mine)

4.创建主题和正文:

一旦我们建立了安全的连接并安全地登录到我们的帐户,我们就可以开始创建电子邮件的主题和正文。这一步非常简单,因为用户可以利用 f 字符串将主题与内容主体连接起来,以创建最终的消息,如下面的代码片段所示。

# Creating the contents of the email
subject = "Hello"
body = "Email Automation Project!"
final_message = f"Subject: {subject} \n \n {body}"

如果用户希望对消息类型有更多的控制,他们可以利用 input()命令在命令提示符下键入他们各自的消息。通过这样做,用户可以在每次运行程序后想要发送邮件时键入他们自己的定制消息。

5.自动化电子邮件:

建立安全连接并打印出我们的内容后,最后一步是自动发送电子邮件。我们会将我们的电子邮件地址存储在一个列表中,该列表是我们导入到模块中的。最后,我们将使用 SMTP 库中的发送邮件功能来自动化我们的电子邮件。

必需的参数是您的电子邮件地址、自动发送邮件的地址列表和最终消息。一旦该过程完成,最好退出(或退出)连接,直到需要进一步使用。下面是执行以下操作的最终代码片段。

# Creating the list of email addresses
address_list = [email1, email2]
smtp_port.sendmail(email_mine, address_list, final_message)
print("Email Sent")
smtp_port.quit()

6.完整代码:

将所有代码层系统地组装在一起,我们可以将所有这些元素组合成一个完整的代码。创建了前两个 Python 模块文件后,查看者可以使用下面的嵌入式代码块来访问整个代码。

查看者可以自由地对现有代码进行创新,以创建他们自己的变体并获得更突出的结果。通过修改一些代码元素来提高生产率,可以对下面的项目进行一些额外的改进。

结论:

Unsplash 上由 Austin Distel 拍摄的照片

我对我的电子邮件收件箱有条不紊,并且我总是有一个实际的待办事项清单。没有这两样东西,我想我会失去理智。
——泰勒詹金斯里德

在本文中,我们介绍了在 Python 的帮助下实现电子邮件自动化的过程。我们了解了如何使用双因素身份验证方法创建安全的应用程序密码。一旦创建并生成了应用程序密码,我们就可以保存它,以便在我们的 Python 项目中使用它来自动化电子邮件。

在 SMTP 库的帮助下,我们能够与我们的电子邮件地址建立安全连接,并向另一个电子邮件地址列表发送电子邮件。本文中演示的自动化电子邮件的过程非常简单,但是在通过 Python 发送电子邮件时非常有效。然而,观众可以自由地通过进一步的实验来更新和创新这个项目。

如果你想在我的文章发表后第一时间得到通知,请点击下面的链接订阅邮件推荐。如果你希望支持其他作者和我,请订阅下面的链接。

https://bharath-k1297.medium.com/membership

如果你对这篇文章中提到的各点有任何疑问,请在下面的评论中告诉我。我会尽快给你回复。

看看我的一些与本文主题相关的文章,你可能也会喜欢阅读!

</7-best-research-papers-to-read-to-get-started-with-deep-learning-projects-59e11f7b9c32>

谢谢你们坚持到最后。我希望你们都喜欢这篇文章。祝大家有美好的一天!

自动化您的直方图

原文:https://towardsdatascience.com/automate-your-histograms-f9ec5392e593

自动选择箱子数量的方法

照片由алексарцибашевUnsplash

创建直方图的老式方法是手动指定容器的数量。智能的方法是使用一个估计器或算法来为你自动选择箱的数量。

有各种各样的技术来自动化箱柜的数量。在这篇文章中,我将列出最常见的方法。直方图是关于汽车价格的(数据集参考可在故事的结尾获得)。这些技术是基于自动创建的多个库来组织的。因此,创建最少数量的自动箱的技术在列表的开头,而创建最多数量的箱的技术在列表的末尾。

斯特格斯

通常创建最少数量的箱。它仅适用于高斯数据,并且低估了大型非高斯数据集的箱数。

使用 Sturges 估计器的自动垃圾箱(图片由作者提供)

斯科特

这是一种考虑到数据可变性和数据大小的不太稳健的估计方法。

使用 Scott estimator 的自动垃圾箱(图片由作者提供)

估计器不考虑可变性,只考虑数据大小。你可以看到直方图的左边部分有点凹凸不平。它通常会高估所需的箱数。

使用 Rice estimator 的自动垃圾箱(图片由作者提供)

多恩

它是 Sturges 估计器的改进版本,可以更好地处理非正态数据集。汽车的价格不是正态分布而是左偏的。然而,Doane 技术将试图找到一个“正常的钟形曲线”。例如,我们开始看到分布,我们开始在下方直方图的左侧看到一种“正常形状”。

使用 Doane 估计器的自动 bin(图片由作者提供)

弗雷曼·迪康尼斯估算师

这是一个稳健的(对异常值有弹性的)估计量,它考虑了数据的可变性和数据的大小。您可以观察到,与其他箱相比,最初的低值箱显示逐渐增加。

使用 Freedman Diaconis 估计器的自动 bin(图片由作者提供)

结论

一边制作。直方图,最好是自动创建箱,而不是手动选择箱的数量。如果你想保持箱柜数量少,去斯特奇斯或斯科特估计。如果您的数据不是正态分布的,那么 Doane 估计器是一个不错的选择。如果您的数据有异常值,那么 Freedman Diaconis Estimator 将帮助您在有异常值的情况下获得良好的数据表示。

一些直方图也给出了一个“自动”估计器,它将试图找到最佳估计器。在任何情况下,理解在什么情况下使用哪个估计量总是有帮助的。

数据源引用

数据来自https://archive.ics.uci.edu/ml/datasets/automobile

该数据集可用于研究目的,只需提及以下引文

Dua d .和 Graff c .(2019 年)。UCI 机器学习知识库[http://archive . ics . UCI . edu/ml]。加州欧文:加州大学信息与计算机科学学院。

额外资源

网站(全球资讯网的主机站)

你可以访问我的网站,使直方图以及其他零编码分析。https://experiencedatascience.com

订阅,以便在我发布新故事时随时获得通知。

https://pranay-dave9.medium.com/subscribe

你也可以通过我的推荐链接加入 Medium

https://pranay-dave9.medium.com/membership

Youtube 频道

这是我的 YouTube 频道
https://www.youtube.com/c/DataScienceDemonstrated的链接

使用 Python 自动生成普通的 Excel 报表

原文:https://towardsdatascience.com/automate-your-mundane-excel-reporting-with-python-f3a29e6e3a0a

了解如何使用 Excel 自动生成 Excel 报表

活动创作者Unsplash 上拍摄的照片

Excel 功能强大,无处不在。但是也是重复的,手动的。当然,您可以使用像 VBA 这样的工具来自动化报告,但是使用像 Python 这样的通用语言允许您自动化报告过程的更广泛的方面(比如移动和用电子邮件发送文件)。

在这篇文章结束时,你将学会如何:

  1. 如何将多个 Excel 文件合并成一个文件
  2. 用熊猫数据透视表汇总 Excel 数据
  3. 在 Excel 报表中添加标题行
  4. 使用 Python 将动态图表添加到 Excel 文件中
  5. 用 Python 设计 Excel 文件的样式

我们开始吧!

想把这个当视频教程看?查看我下面的完整视频教程:

设置您的环境

为了跟随本教程,我们将使用三个库:ospandasopenpyxl。其中的第一个os与 Python 捆绑在一起,因此您不需要安装它。然而,另外两个需要使用pipconda来安装。

让我们看看如何在 Python 中安装这些库:

在您的终端中使用上述任何一种方法都会安装所需的库。现在,让我们来看看您可以用来跟随本教程的数据。

现在我们已经安装了库,我们可以导入将要使用的库和类:

你可以在这里下载文件。zip 文件包含 3 个不同的 Excel 文件,每个文件包含不同月份的销售信息。虽然像这样存储数据是有意义的,但它会使分析数据变得相当困难。

正因为如此,我们需要先把所有这些文件组合起来。这是您将在下一节学到的内容!

用 Python 组合多个 Excel 文件

Pandas 库将数据存储在 DataFrame 对象中,这可以被认为是一个 Excel 表(尽管这有点简化)。让我们来分解一下我们想要做什么,然后我们来看看如何使用 Python 来做这件事:

  1. 将我们所有的文件收集到一个 Python 列表中
  2. 循环遍历每个文件,并将其附加到熊猫数据帧中

让我们写一些代码,看看如何在 Python 中实现这一点!

让我们来分析一下我们在这里做了什么:

  1. 在第 1 节中,我们首先加载保存文件的路径,并使用os.list()函数获取该文件夹中包含的所有文件的列表
  2. 在第 2 节中,我们首先创建了一个空的数据帧,然后遍历每个文件,将它加载到一个数据帧中,并将其附加到我们的combined数据帧中
  3. 最后,我们将文件保存到它自己的 Excel 文件中

那很容易,不是吗?有许多不同的方法来完成这项任务,这就是 Python 的魅力所在!

现在我们的数据已经加载完毕,让我们学习如何用熊猫来总结我们的数据。

斯科特·格雷厄姆Unsplash 上的照片

用熊猫汇总 Excel 数据

在本节中,您将学习如何使用 Pandas 创建一个汇总表!为此,我们将使用名副其实的熊猫.pivot_table()函数。

该函数旨在熟悉 Excel 中的数据透视表。有了这个,我们就可以知道如何总结我们的数据。假设我们想计算出每个销售人员的总销售额。我们可以这样写:

在上面的代码中,我们使用 Pandas .pivot_table()函数创建了一个数据透视表。其中大部分应该感觉类似于 Excel 数据透视表。然而,默认情况下,Pandas 将使用一个聚合函数'mean',所以我们需要将其设置为'sum'

使用 OpenPyxl 向 Excel 报表添加标题行

在本节中,您将学习如何向 Excel 报表添加描述性标题行,以使它们更易于打印。为此,我们将开始使用 Openpyxl 库。

Openpyxl 的工作原理是将工作簿加载到内存中。从那里,您可以访问其中的不同属性和对象,例如工作表和这些工作表中的单元格。

这里的关键区别在于,您是直接使用工作簿。对于 Pandas,我们只需将工作簿的保存到。(我承认还有更多,但这是一个很好的思考方式。)

在上面的代码中:

  1. 我们加载了一个工作簿对象wb。从那里,我们访问工作表。
  2. 我们能够通过使用.insert_rows()方法插入三行来操作工作表。
  3. 这些行是在索引 0(第一行)处添加的,包括三行。我们给两个单元格分配了有用的值。
  4. 最后,我们使用 Openpyxl .save()方法保存工作簿。

Towfiqu barbhuiyaUnsplash 上拍摄的照片

使用 Python 向 Excel 添加动态图表

在这一节中,我们将了解如何向 Excel 文件添加图表。Openpyxl 库的一大优点是我们可以创建基于 Excel 的图表,这些图表对数据保持动态。

为了使我们的图表动态化,我们需要创建Reference()对象,顾名思义,这些对象保存对工作簿中位置的引用。

我们将创建一个条形图,并将数据和类别粘贴到工作簿中。让我们来看看如何做到这一点:

让我们来分解一下上面的代码是做什么的:

  1. 我们设置了两个Reference对象:一个用于我们的数据,一个用于我们的类别。这些引用对象将把我们的图表与特定的单元格联系起来,使它们保持动态。
  2. 我们添加一个BarChart对象。对于图表,我们使用.add_data().set_categories()方法来传递我们的引用对象。
  3. 最后,我们将图表添加到工作表上的特定锚点。

用 Python 设计 Excel 报表的样式

在这最后一节,我们将看看如何使用 OpenPyxl 来设计工作簿的样式。OpenPyxl 可以基于 Excel 中存在的样式向 Excel 工作簿中的单元格添加样式。

这意味着我们可以添加像Titlecurrency这样的样式。让我们使用.style属性来看看这是如何工作的:

在上面的例子中,我们使用了.style属性为不同的单元格分配不同的样式。我们在单元格 5–6 中使用 for 循环的原因是 OpenPyxl 不允许您为范围分配样式,所以我们一次分配一个样式。

下一步做什么?

太好了!您已经自动完成了枯燥的 Excel 报告!现在,你接下来应该看什么?我建议考虑您可能需要自动化的其他元素。例如:

  • 如何向工作表中添加姓名?
  • 你如何能自动地用电子邮件发送你的结果文件?
  • 如何将值样式化为表格?

结论

感谢您一路阅读教程!我希望你喜欢它,并且你学到了一些东西。使用 Python 来自动化您的工作是一件非常值得学习的事情。如果你想了解更多,请点击这里订阅我的 YouTube 频道。

使用预提交挂钩自动化您的 Python 代码文档

原文:https://towardsdatascience.com/automate-your-python-code-documentation-with-pre-commit-hooks-35c7191949a4

自动化文档字符串检查和使用预提交钩子自动生成文档的实践指南

约书亚·阿拉贡在 Unsplash 上拍摄的照片

当时间紧迫时,代码文档通常是最先受到影响的。然而,高质量的代码文档是在开发团队中有效协作的关键,以便在新开发人员加入时轻松入职,并在团队成员决定离开您的公司时确保连续性。在这篇博客文章中,我们将看看如何使用 docstrings 为团队的 Python 项目自动生成代码文档。

使用文档字符串约定…并执行它

不幸的是,实现文档自动化的第一步包括一个手工步骤:与您的团队就文档字符串约定达成一致,并在您的代码中一致地应用该标准。

但是首先,什么是 docstrings?

文档字符串是字符串,放在代码中函数、类和方法定义的第一位。它们通常出现在一行中,并以三引号符号开始。Docstrings 用于记录函数、类和方法的用途,以及它们接受的参数和返回的内容。在 Python 中,除了少数例外,所有的函数、类和方法都应该有 docstrings。

计算总体均值和总体标准差的函数的文档字符串示例(与 Github Codepilot 共同编写的代码,图片由作者提供)。

存在许多不同的文档字符串标准,但是在 Python 中一些最常用的标准包括 reStructuredTextNumpydocGoogledocEpyText

虽然你仍然需要自己编写好的文档字符串来开发你的代码(除非你正在使用 GitHub Copilot 也许),但是大多数 ide 会在这个过程中帮助你。py charm——我选择的 Python IDE 例如,在你定义了一个函数或类之后,会自动生成一个 docstrings 存根,并预先填充类型注释。您可以设置想要使用的 docstrings 约定,或者使用您自己的模板(请参见下图)。

要在 Pycharm 中设置首选文档字符串格式,请转到 PyCharm >首选项> Python 集成工具>文档字符串格式

一旦您的团队就文档字符串约定达成一致,建议配置预提交挂钩以检查约定是否得到一致应用(并使它们成为您的持续集成管道的一部分,例如, GitHub Actions ,或 AWS CodeBuild )。

预提交钩子是小“脚本”,你在每次提交时运行它来识别,有时甚至自动修复你的代码中的问题。它们有许多不同的风格,可以用来,例如,加强代码风格,修复格式问题,或者分析代码的复杂性

如果你想了解更多关于预提交钩子的知识,以及如何使用它们,请看下面的帖子。👇

https://python.plainenglish.io/how-to-improve-your-python-code-style-with-pre-commit-hooks-e7fe3fd43bfa

当您的团队在自己的机器上本地开发代码时,对 docstrings 使用预提交挂钩可以保持团队一致。当您在一个连续交付的框架中工作时,它们尤其有用,在这个框架中,团队成员需要经常进行较小的变更,并且您需要跟上快速的开发和评审周期。

幸运的是,有很多工具可以帮助您的团队跟踪他们是否正确地使用了 docstrings。

让我们快速浏览几个选项。

审问

首先, interrogate 是一个有用的工具,它会让你知道你是否没有为你的类或函数添加 docstrings。您可以在.pre-commit-config.yaml文件中使用以下语法将询问添加到您的预提交钩子中:

询问的预提交配置示例(作者根据询问文档编写的代码)

--fail-under标志设置了工具报告失败的截止时间,而--verbose标志确保详细的覆盖报告被打印到控制台。在上面显示的配置中,如果少于 80%的代码被覆盖(用 docstrings),询问“test”将失败。您还可以在您的pyproject.toml文件中配置一系列其他选项,以确保 interrogate 符合您的特定需求。而且,如果你和我一样热衷于在你的回复中添加徽章,你会很高兴知道审问有这个选项

一旦你设置了预提交挂钩并进行新的提交(或运行pre-commit run),interrogate 将提供一个覆盖报告:

询问报道的例子(图片由作者提供)

如您所见,我在这里很懒,完全没有为我的任何函数编写 docstrings。并且,审问正确地抱怨我没有达到(配置的)80%的截止值。

Pydocstyle

其次,您可能会发现 Pydocstyle 是一个包含在预提交钩子中的有用工具。您的.pre-commit-config.yaml文件中的配置应该遵循以下格式:

Pydocstyle 的预提交配置示例(作者代码,基于 Pydocstyle 文档)

运行钩子(pre-commit run)时,发现的任何错误都将被打印回控制台,例如:

使用 Pydocstyle 作为提交前挂钩时,由它标识的错误示例(图片由作者提供)

您有足够的灵活性来定制 Pydocstyle 以满足您的需求,有了一个大的错误代码菜单,您可以选择忽略。在上面的例子中,我已经决定禁用错误代码D107D204的警告,这意味着我将允许__init__文件中缺少文档字符串,以及在文档字符串后缺少一个空行。

其他选项

其他值得包括在提交前配置中的选项包括:

从文档字符串自动生成文档

现在我们已经介绍了我们的文档字符串,我们可以使用它们来自动生成文档,并使它在一个地方可用。还是那句话,有很多选择可以考虑。

在下面的例子中,我们将使用 pdoc3 ,它从文档字符串(来自活动对象的 [__doc__](https://pdoc3.github.io/pdoc/doc/pdoc/#gsc.tab=0) 属性)为您的类、模块、函数和变量生成文档。作为一个额外的好处,如果您使用公认的分隔符,它将正确解析 LaTex 语法(非常适合数据科学、机器学习和其他数学密集型项目!).

让我们快速看一下 pdoc3 的预提交配置示例。在下面的例子中,我已经设置了 pdoc3 为一个名为cosine_utils的模块自动生成文档。我已经将其配置为输出 html 文档(pdoc3 也支持纯文本和 PDF 输出)。

pdoc3 的预提交配置示例(由作者编写,基于此)

运行这个预提交钩子将生成一个名为html的文件夹,其中包含自动生成的文档。您将能够在您选择的浏览器中查看文档,其中包含一个格式良好的索引,显示文档对象、源代码和您在文档字符串中包含的信息。

用 pydoc3 生成的 html 文档示例(图片由作者提供)

从 docstrings 自动生成文档的其他选项包括,例如, PydocSphinx ,以及我自己尝试的文档生成器, markdowndocs 。后者可以通过一个预提交挂钩来设置,以将 markdown 风格的文档(基于您的文档字符串和代码)添加到您的项目自述文件中(更多细节请参见本报告,生成的文档示例请参见本文件)。

除了实施特定的 docstring 样式和自动化检查之外,在您的团队中拥有良好的代码文档实践也很重要。我喜欢尝试(虽然我并不总是成功!)来编写 docstrings,我的想法是,当我的同事需要通过阅读我的代码来使用现有的模块或服务时,他们应该能够自行加入。如果团队中的每个人都编写干净的代码,伴随着清晰的、描述性的变量和类名,以及匹配的文档字符串,那么您的开发工作将会变得更加容易。

感谢您的阅读!

https://medium.com/@ndgoet/membership

如果你喜欢这篇文章,这里有一些你可能会喜欢的文章👇

https://python.plainenglish.io/how-to-improve-your-python-code-style-with-pre-commit-hooks-e7fe3fd43bfa

请仔细阅读 本免责声明 在依赖 中的任何内容之前,我关于 Medium.com 的文章 为自己的作品:)

气流松弛的自动警报

原文:https://towardsdatascience.com/automated-alerts-for-airflow-with-slack-5c6ec766a823

利用 Slack API 获得 DAG 任务失败和成功的自动更新和警报

照片由 Artturi JalliUnsplash 拍摄

让我们面对现实吧——有时气流 Dag 需要一段时间才能运行。与其不断地回到 Airflow UI 来检查 dag 更新,为什么不开始跟踪电子邮件、消息和待办事项,然后通过 Slack 获得运行结果的通知呢?

通过 Slack 管理气流通知可以方便地监控和调试气流任务。一个专用的 slack 通道还为其他人(如客户、产品经理和队友)提供了工作流状态的透明度,而无需检查 Airflow UI。

要求

  1. 对您的工作区的宽松管理员访问
  2. 松弛 API 密钥
  3. 气流实例

入门指南

为您的 Airflow 实例安装以下 python 库

# requirements.txt
apache-airflow-providers-http
apache-airflow-providers-slack
apache-airflow-providers-slack[http]

准备松弛

在您的工作区中创建一个通道,供 API 访问。我把我的叫做“气流”。

转到api.slack.com/apps并点击“创建新应用”,供您的 airflow 实例访问。退出模式后,为您的 slack workspace 应用程序启用传入 webhooks。然后,滚动到底部,选择“添加新的 webhook 到工作区”。

Slack API webhooks

您可以从命令行测试您的 webhook/api 密钥,以验证所有设置是否正确(用您自己的密钥替换):

curl -X POST -H 'Content-type: application/json' --data '{"text":"Hello, World!"}' https://hooks.slack.com/services/00000000000/00000000000/000000000000000000000000

完成气流设置

一旦启动并运行了 Airflow,就在 UI 中创建新的 HTTP 连接。将其命名为slack,并将 webhook url 插入到“host”输入中。api 密钥的剩余部分将被输入到“密码”中。

气流松弛 HTTP 连接设置

现在,我们可以使用 Airflow 的BaseHookSlackWebHookOperatorDag Task Instance Context向 slack 发送有关最新 dag 运行信息的警报。

宽限预警代码

该代码将在气流任务失败时发送消息。自动化该过程的最后一步是将slack_fail_alert函数作为参数添加到 dag 默认参数中:

default_args = {
   ...,
   'on_failure_callback': slack_fail_alert
}

该代码也可以很容易地修改,以提醒任务成功或其他状态。

测试

为了进行测试,有意在代码中写入一个错误,以验证 airflow 会在任务失败时发送消息。或者,如果不想破坏代码,可以在on_success_callback参数中使用这些函数。假设一切都设置正确,您将收到一条消息,其中包含最新任务运行的详细信息。

下次您在 dag 工作流中遇到故障时,将通过 slack 通知您任务的名称和日志的直接链接,以便您可以开始调试过程。

气流松弛信息警报

就是这样!只需一点点设置,我们就创建了气流的自动监控和警报。接下来的步骤可能是邀请项目的相关利益相关者到 #airflow slack channel,让他们了解当前工作流的状态。如果您的应用程序或数据仓库的最终用户看到任何错误,他们可以在将问题升级到其他人之前,检查气流通道以查看错误是否立即显现。

感谢阅读!查看这个,获取额外的代码和上下文,以及其他有用的气流技巧。

使用 Python 自动清理数据

原文:https://towardsdatascience.com/automated-data-cleaning-with-python-94d44d854423

如何自动化数据准备并为您的下一个数据科学项目节省时间

图片来自 Unsplash

众所周知,数据清理和预处理是数据科学项目的主要组成部分。而且,你可能会同意我的观点,这不是项目中最令人兴奋的部分。

那么,(让我们扪心自问):我们能自动化这个过程吗?

嗯,自动化数据清理说起来容易做起来难,因为所需的步骤高度依赖于数据的形状和特定领域的用例。尽管如此,还是有办法以一种标准化的方式使自动化至少是相当大的一部分

在本文中,我将向您展示如何在 Python 3.8 中构建自己的自动化数据清理管道

查看Github上的 AutoClean 项目。

1 | 我们想自动化什么?

在深入这个项目之前,我们应该问自己的第一个也是最重要的问题是:数据清理过程的哪些步骤可以实现标准化自动化

最有可能自动化或标准化的步骤是在几乎每个数据科学项目的每个清理过程中反复执行的步骤。而且,由于我们想要建立一个“一刀切”的管道,我们想要确保我们的处理步骤是相当通用的,可以适应各种类型的数据集。

例如,在大多数项目中经常被问到的一些常见问题包括:

  • 我的数据是什么格式的?CSV,JSON,text?还是另一种格式?我该如何处理这种格式?
  • 我们的数据特征有哪些数据类型?我们的数据集包含分类和/或数字数据吗?我们如何处理每一个问题?我们想要对我们的数据进行一次性编码,和/或执行数据类型转换
  • 我们的数据是否包含缺失值?如果是,我们如何处理它们?我们要执行一些插补技术吗?或者我们能安全地删除有缺失值的观测值吗?
  • 我们的数据是否包含异常值?如果是,我们是应用正则化技术,还是让它们保持原样?……等等,我们甚至认为什么是“异常值”?

无论我们的项目将针对什么用例,这些都是很可能需要解决的问题,因此可以成为自动化的一个伟大主题。

这些问题的答案以及它们的实现将在接下来的几章中讨论和展示。

2 |管道的构建模块

首先,让我们从导入我们将使用的库开始。这些将主要是 Python Pandas、SklearnNumpy 库,因为它们在处理数据时非常有用。

我们将定义我们的脚本将接受一个 Pandas dataframe 作为输入,这意味着我们至少需要将数据转换成 Pandas dataframe 格式,然后才能被我们的管道处理。

现在,让我们看看我们的管道的构建模块。以下章节将经历以下处理步骤:

【区块 1】缺失值
【区块 2】异常值
【区块 3】分类编码
【区块 4】提取日期时间特征
【区块 5】打磨步骤

[块 1 ]缺少值

一个项目从一个包含缺失值的数据集开始是相当常见的,并且有各种方法来处理它们。我们可以简单地删除含有缺失值的观测值,或者我们可以使用插补技术。在各种回归或分类模型的帮助下预测数据中的缺失值也是常见的做法。

💡插补技术用某些值(如平均值)或与特征空间中其他样本值类似的值(例如 K-NN)来替换缺失数据。

我们如何处理缺失值的选择主要取决于:

  • 数据类型(数值或分类)和
  • 相对于样本总数,我们有多少缺失值(从 100k 中删除 1 个观察值与从 100 个中删除 1 个观察值的影响不同)

我们的管道将遵循策略插补>删除,并将支持以下技术:线性和逻辑回归预测、K-NN 插补、均值、中值和众数以及删除。

很好,现在我们可以开始为我们的第一个构建块编写函数了。我们将首先创建一个单独的类来处理缺失值。下面的函数 handle 将以不同的方式处理数值型分类型缺失值:一些插补技术可能只适用于数值型数据,而一些则只适用于分类型数据。让我们来看看处理数字特征的第一部分:

点击查看完整源代码

该函数检查为数字和分类特征选择了哪种处理方法。默认设置为“自动”,这意味着:

  • 数值缺失值将首先通过线性回归预测进行插补,剩余值将通过 K-NN 进行插补
  • 分类缺失值将首先使用逻辑回归通过预测进行估算,剩余值将使用 K-NN 进行估算

对于分类特征,与上述相同的原则适用,除了我们将仅支持使用逻辑回归、K-NN 和模式插补的插补。当使用 K-NN 时,我们将首先将我们的分类特征标记编码为整数,使用这些标记来预测我们缺少的值,最后将标记映射回它们的原始值。

根据所选择的处理方法, handle 函数从其类中调用所需的函数,然后在各种 Sklearn 包的帮助下操作数据:_ imput函数将负责 K-NN、均值、中值和众数插补,_ Lin _ regression _ imputlog _ regression _ imput将通过预测执行插补,我假设 _delete 的角色是自我插补

我们最终的 MissingValues 类结构将如下所示:

点击查看完整源代码

我不会更详细地介绍该类其余函数中的代码,但是我邀请您查看 AutoClean 资源库 中的完整源代码。

完成所有需要的步骤后,我们的函数输出处理过的输入数据。

酷,我们通过了管道的第一个模块🎉。现在让我们考虑一下如何处理数据中的异常值。

[区块 2 ]异常值

我们的第二个模块将关注数据中异常值的处理。首先我们需要问自己:什么时候我们认为一个值是异常值?对于我们的管道,我们将使用一个普遍应用的规则,即如果在以下范围之外,则数据点可被视为异常值:

【Q1—1.5 * IQR;Q3 + 1.5 * IQR]

…其中 Q1 和 Q3 是第一和第三四分位数,IQR 是四分位数之间的范围。下面你可以看到一个很好的箱线图:

图片作者。

既然我们已经定义了什么是异常值,我们现在必须决定如何处理这些异常值。同样,有各种策略可以做到这一点,对于我们的用例,我们将重点关注以下两种:winsorization 和 deletion。

💡 Winsorization 在统计学中用于限制数据中的极端值,并通过用数据的特定百分位数替换异常值来减少异常值的影响。

使用 winsorization 时,我们将再次使用上面定义的范围来替换异常值:

  • 值>上限将由上限范围值代替,并且
  • 数值< lower bound will be replaced by the 量程下限值

我们的异常值类的最终结构将如下所示:

点击查看完整源代码

我们到达了第二块的末尾——现在让我们看看如何对分类数据进行编码。

[块 3 ]分类编码

为了能够用分类数据进行计算,在大多数情况下,我们需要我们的数据是数字类型,即数字或整数。因此,常见的技术包括一键编码数据,或标签编码数据。

💡数据的一键编码将特征的每个唯一值表示为二进制向量,而标签编码为每个值分配一个唯一的整数。

图片作者。

每种方法都有不同的利弊,比如独热编码产生了许多额外的特性。此外,如果我们标记 encode,这些标记可能会被某些算法解释为数学相关:1 个苹果+ 1 个橘子= 1 个香蕉,这显然是对这种类型的分类数据的错误解释。

对于我们的管道,我们将设置默认策略‘auto’来根据以下规则执行编码:

  • 如果特征包含< 10 unique values, it will be 单热编码
  • 如果特征包含< 20 unique values, it will be 标签编码的
  • 如果特征包含> 20 个唯一值,它将而不是被编码

这是处理编码过程的一种非常原始和快速的方式,可能会很方便,但也可能导致编码不完全适合我们的数据。即使自动化很棒,我们仍然希望确保我们也可以手动定义哪些特性应该被编码,以及如何编码。这是在 EncodeCateg 类的句柄函数中实现的:

点击查看完整源代码

句柄函数将一个列表作为输入,而我们想要手动编码的特性可以由列名或索引定义,如下所示:

encode_categ = [‘onehot’, [‘column_name’, 2]]

既然我们已经定义了如何处理异常值,我们可以继续我们的第四个块,它将涵盖 datetime 特性的提取。

[块 4 ]提取日期时间特征

如果我们的数据集包含一个具有 datetime 值的特征,比如时间戳或日期,我们很可能希望提取这些值,以便在以后处理或可视化时更容易处理它们。

我们也可以以自动化的方式来做这件事:我们将让我们的管道搜索这些特性,并检查其中的一个是否可以转换成日期时间类型。如果是,那么我们可以有把握地假设这个特性保存了 datetime 值。

点击查看完整源代码

我们可以定义提取日期时间特征的粒度,而默认设置为s’秒。提取后,该函数检查日期和时间的条目是否有效,意思是:如果提取的列、【月】、、【年】、都包含 0,那么这三个都将被删除。对于【小时】【分钟】【秒】也是如此。

现在我们已经完成了日期时间的提取,我们可以进入管道的最后一个构建模块,它将包含一些最终的调整来完善我们的输出数据帧。

[区块 5 ]数据框抛光

现在我们已经处理了我们的数据集,我们仍然需要做一些调整,使我们的数据框架“看起来不错”。我这么说是什么意思?

首先,由于应用了插补技术或其他处理步骤,一些原本属于类型整数的特征可能已经被转换为浮点数。在输出我们最终的数据帧之前,我们将把这些值转换回 整数

其次,我们希望将数据集中的所有 float 要素的舍入到与原始输入数据集中的相同的小数位数。这一方面是为了避免浮点小数中不必要的尾随 0,另一方面是为了确保不要将我们的值四舍五入超过我们的原始值。

同样,我不会更详细地讨论这些想法背后的代码,但我邀请您查看 AutoClean 资源库 中的完整源代码。

3 |将所有内容放在一起

首先,祝贺你坚持到现在!🎉

我们现在已经到了想要将所有构建模块放在一起的阶段,这样我们就可以实际开始使用我们的管道了。你可以在我的 GitHub 库中找到完整的自动清理代码,而不是在这里发布完整的代码:

https://github.com/elisemercury/AutoClean

下面我们来看一个 AutoClean 如何处理样本数据集的可视化示例:

样本数据集。图片作者。

我生成了一个随机数据集,正如您所看到的,当涉及到不同的数据类型时,我使它变化很大,并且我在数据集中添加了一些随机的 NaN 值。

现在,我们可以运行自动清理脚本,如下所示:

产生的清理后的输出数据帧如下所示:

已处理的样本数据集。图片作者。

在上图中,您将看到 AutoClean 对我们的数据所做的可视化更改。估算的缺失值用黄色标记,异常值用绿色标记,提取的日期时间值用蓝色标记,分类编码用橙色标记。

我希望这篇文章对您有所帮助,并且 AutoClean 将帮助您节省一些宝贵的时间。🚀

如果您有任何问题或反馈,请随时发表评论。也欢迎在 GitHub 上投稿!

参考资料:

[1] N. Tamboli,所有你需要知道的关于不同类型的缺失数据值以及如何处理它 (2021)

[2] C .泰勒,什么是四分位间距规则? (2018)

[3] J. Brownlee,(2020)分类数据的顺序和一键编码

针对您的数据的自动化电子邮件和数据质量检查

原文:https://towardsdatascience.com/automated-emails-and-data-quality-checks-for-your-data-1de86ed47cf0

通过预定的电子邮件获得更好、更干净数据的数据仓库指南

作者图片💡迈克·沙克霍米罗夫

用干净的数据构建数据仓库

如果您正在构建一个数据仓库解决方案或/和在数据库中运行一些管理任务,那么本文适合您。它回答了这个问题:

如何测试数据质量,并在出现问题时发送电子邮件通知。

理想情况下,每个数据用户都希望在数据出现任何异常时得到通知,尤其是当我们谈到关键的报告组件和字段时。

每个数据仓库可能有几十个数据管道源,它们来自 API、连接的数据库、像 Kinesis 或 Kafka 这样的数据流以及第三方数据提供商。我以前写过如何用 easy 连接所有这些,你可以在这里阅读我的设置:如何用无服务器摄取管理器和 Node.js 处理 BigQuery 中的数据加载

因此,当数据来了,我想确保所有字段都准备好了,并有正确的格式。例如,您的报告可能使用 **date** 列,并且您希望确保它在数据仓库中的格式正确,或者至少不为空(非空)。

这里有一个简单而有效的框架。

先决条件、库和设置

  • Google BigQuery 。我将使用 BigQuery 作为数据仓库解决方案,因为它是免费的,但是您可以使用任何您喜欢的替代方案,例如雪花、红移、任何 db 引擎。他们中的大多数人无论如何都可以发送电子邮件通知。这就是一切。
  • 标准 SQL 。这不是高级教程。这里提供的 SQL 可以在任何数据库引擎中工作,或者您可以调整它以满足您的需求。很容易。

重要提示 : BigQuery 并不是完全免费的,但是 Google 提供免费的积分,即使你没有剩余的积分,我也会使用免费的数据进行查询。你所需要的就是 Google 账户BigQuery API 启用。

您将学习如何:

  • 使用 SQL 检查数据质量
  • 发送电子邮件通知
  • 用 SQL 创建测试表和模拟数据
  • 检测数据异常

如何安排电子邮件通知

在 BigQuery 中非常简单。

图片作者。💡迈克·沙克霍米罗夫

  • 输入您的 SQL,即测试它的东西:select 1 as test;并点击下面的计划查询:

图片作者。💡迈克·沙克霍米罗夫

  • 为您的查询命名,然后点击下面的“发送电子邮件通知”。所以现在,如果您的 SQL 查询失败,您将开始收到通知:

图片作者。@ MikeShakomirov

如果查询结果中的任何记录满足您指定的行条件,您现在需要做的就是引发一个异常。

如何使用行条件添加数据检查

基本上这就是你如何测试你的数据满足你需要的质量要求。

让我们试着想象一些现实生活中的场景,你的数据必须通过质量保证流程。例如,我的暂存数据仓库中有一个 *user_transaction* 表,可以用您的 SQL 脚本创建:

让我们创建一个表格

如果你像我一样遇到错误: *error: Cannot set write disposition in jobs with DDL statements* 只要刷新你的页面就行了。

当你的网页打开时间过长时,可能会出现一些界面元素失效的问题。

在这里阅读更多关于在 BigQuery 中创建表的信息:https://cloud . Google . com/big query/docs/creating-partitioned-tables # SQL

结果:

作者图片💡迈克·沙克霍米罗夫

现在我想检查数据是否有任何潜在问题

在这里,我将计算带有缺失(NULL)值的记录,并检查您是否从 source pieline 中获得了任何重复项:

因此,您将看到事务总数大于唯一事务计数,并且有一个payment_date的值为NULL:

图片作者。💡迈克·沙克霍米罗夫

如果昨天在我的 数据仓库 中摄取的数据中检测到这种情况,我肯定希望收到电子邮件通知。

那么我们该怎么做呢?

让我们再添加一些 SQL 并引发一个异常

这将触发电子邮件通知:

将引发错误(BigQuery 异常):

图片作者。💡迈克·沙克霍米罗夫

我会收到一封邮件说:

注意:production.user_transaction 昨天有可能丢失数据:1。

很棒。但是,我希望在我的电子邮件中收到一份关于潜在数据问题的完整摘要。

让我们总结一下所有潜在的数据质量问题

我们可以使用类似于:

当我们的任何checks失败时,这将触发一个电子邮件通知,但不会提供太多信息:

注意:production.user_transaction 存在潜在的昨天所有数据质量问题:%t.

相反,我希望得到这样的结果:

注意:production.user_transaction 有 1 个重复的事务和 1 个值为空的 payment_date。

让我们看看使用 SQL 需要做些什么来实现这一点

要总结失败的数据质量检查,您可能需要使用以下内容:

结果:

图片作者。💡迈克·沙克霍米罗夫

图片作者。💡迈克·沙克霍米罗夫

在上面的 SQL 中,我创建了一个 CTE,其中的行条件定义了我需要的警报。

我将使用它来生成数据质量警报的完整摘要,并将其包含在我的电子邮件通知中。

使用 SQL 有很多方法可以实现这一点。它非常灵活,这也是我喜欢它的原因,但我决定使用 BigQuery 数组函数https://cloud . Google . com/big query/docs/reference/standard-SQL/array _ functions

让我们来看看怎么做:

因此,您将看到检测到的潜在数据质量问题的摘要文本消息:

图片作者。💡迈克·沙克霍米罗夫

图片作者。💡迈克·沙克霍米罗夫

最后,让我们用 BigQuery 异常来总结一下,这样它就可以给我们发送一封电子邮件:

图片作者。💡迈克·沙克霍米罗夫

图片作者。💡迈克·沙克霍米罗夫

还有一件事…

让我们创建那个 **dataChecks.check_user_transaction_failed_v** 视图,以便更容易找到没有通过质量检查的准确记录:

图片作者。💡迈克·沙克霍米罗夫

图片作者。💡迈克·沙克霍米罗夫

因此,现在有了这个视图,我们就可以在收到通知时轻松调查数据质量问题。

有用的是,如果你能BigQuery 通知消息中添加一个查看 URL 链接,那么谷歌就能推断出这一点,你就能点击它:

图片作者。💡迈克·沙克霍米罗夫

结论

这是一个简单可靠的数据质量框架,大多数现代数据仓库都支持它。

最终,它允许用视图检查您的数据,并且轻松检测潜在的数据质量问题。不仅仅是缺失数据和空值。在数据集条件中,几乎可以使用任何东西,即使用 regex 函数检查数据是否满足特定模式或任何其他组合条件,其中使用了多列

需要异常检测吗?很简单。只需将 30 天移动平均线和阈值添加到数据集条件中,并在阈值被突破时收到电子邮件通知。

资源

【1】:https://cloud . Google . com/big query/docs/creating-partitioned-tables # SQL

【2】:https://cloud . Google . com/big query/docs/reference/standard-SQL/array _ functions

最初发表于T5【https://mydataschool.com】

用 shell 脚本、R 和 Python 自动绘制海面温度图

原文:https://towardsdatascience.com/automated-mapping-of-sea-surface-temperature-with-shell-scripting-r-and-python-763339432449

新西兰海面温度。资料来源:JPL MUR 措施项目。2015.GHRSST 级 MUR 全球基金会海面温度分析。版本。4.1.阿宝。美国加利福尼亚州 DAAC。数据集于【2022 年 7 月 16 日】在https://doi.org/10.5067/GHGMR-4FJ04通过 NOAA erd DAPhttps://up well . pfeg . NOAA . gov/erd DAP/griddap/NASA _ JPL _ 28d 8 _ bd66 _ 24 B1 . html访问

有许多方法来绘制海洋表面温度,或 SST,它是由一系列卫星传感器产生的,并在多个不同的平台上提供服务。很难决定使用哪种方法,或者从大量选项中选择哪种产品。

20 世纪 80 年代初,当我还是一名海洋学研究生时,如果你想要 SST 数据,你必须向美国国家航空航天局(NASA)提出请求,他们会寄给你一包 CD,里面载有多个文件中的数据。那些日子早已过去。最新的趋势是完全避免下载数据。现在,您可以从基于云的服务器中选择并子集化分析就绪的云优化(ARCO)数据,使用笔记本电脑上的代码在计算机上使用多个处理器远程处理数据,在相同的远程机器上可视化数据,并下载成品(参见https://tinyurl.com/2p8s6y9uhttps://tinyurl.com/yc2jne6d)。这些方法非常强大,但是它们需要更多的专业知识来实现。

在这篇文章中,我将展示一种方法,它仍然可以下载 NetCDF 格式的数据并在本地处理地图。这不是一种分析就绪的云优化方法,但对于许多不涉及处理万亿字节数据的目的来说,这仍然是非常足够和快速的。它确实需要一个快速的互联网连接,一个数据下载不会超过你的配额的数据计划,以及一台具有足够处理能力的计算机。

最初的问题是使用哪个 SST 数据集,以及在哪里方便地获得它。为了便于说明,我选择了一个由几个卫星传感器合并而成的无间隙产品,该产品已经映射到准备投影的坐标上。高分辨率海洋表面温度版本 4 多尺度超高分辨率,或 GHRSST-MUR 产品,是一个近实时(1 天延迟)、4 级(映射)、无间隙产品,由几个辐射计和光谱辐射计以及原位数据合并而成。它提供了 0.01 度分辨率的几乎全球无云 SST 覆盖( Chin et al. 2017 )。

这些数据在 NASA 喷气推进实验室物理海洋学分布式活动档案中心(DAAC )上以 NetCDF-4 文件格式提供,或者在亚马逊网络服务器上以ARCO Zarr 格式提供。要访问 NetCDF 数据,使用国家海洋大气管理局环境研究处数据访问程序 (NOAA-ERDDAP)更方便。在 ERDDAP 上,可以使用 ERDDAP 图形用户界面(GUI )访问 GHRSST-MUR 最终产品并对其进行子集划分,但更好的选择是使用内置于 ERDDAP 中的 OPenDAP 类工具来访问所需格式的数据集子集。ERDDAP GUI 有助于获得正确格式的所需 URL。

ERDDAP 提供了许多使用类似 OPenDAP 的工具从不同的分析程序(如 R、Python 或 Matlab)中获取所需数据的例子。我发现使用 R 通过 ERDDAP 访问和下载数据是最简单的,但是我更喜欢用 Python 绘制 SST 图。我使用一个 bash shell 脚本将所有东西放在一起,并自动完成下载数据和创建地图的过程。

有一些技巧可以让自动化工作。(1)修改外壳环境,以允许从外壳脚本激活 Python 脚本所需的 Conda 环境。(2)使用 shell 脚本运行 R 脚本、thels Python 脚本,并为执行设置计时器。

使用外壳脚本控制代码执行时间和顺序

我在电脑上一个名为“geo_env”的项目环境中运行 Python 代码,在运行脚本之前需要激活这个项目环境。我使用 Conda 包管理器安装了 Python,因此为了从运行在 Linux 上的 shell 脚本中激活环境,有必要修改~/。bashrc 通过 NOAA erd DAPhttps://up well . pfeg . NOAA . gov/erd DAP/griddap/NASA _ JPL _ 28d 8 _ bd66 _ 24 B1 . html在“#<<< conda initialize <<< “, shown below:

# >>> conda initialize >>>
# !! Contents within this block are managed by 'conda init' !!
__conda_setup="$('/home/smcc/anaconda3/bin/conda' 'shell.bash' 'hook' 2> /dev/null)"
if [ $? -eq 0 ]; then
    eval "$__conda_setup"
else
    if [ -f "/home/smcc/anaconda3/etc/profile.d/conda.sh" ]; then
        . "/home/smcc/anaconda3/etc/profile.d/conda.sh"
    else
        export PATH="/home/smcc/anaconda3/bin:$PATH"
    fi
fi
unset __conda_setup
# <<< conda initialize <<<# edit to permit conda activate to work in a shell script
export -f conda
export -f __conda_activate
export -f __conda_reactivate
export -f __conda_hashr
export -f __conda_exe
# end smcc edit

Activation of the project environment from the shell script can then be done using the following command:

conda activate geo_env

To run the shell script every day, or at whatever interval you choose, needs a timed job execution. You can use a cron job, but I prefer to use “at” to run the script once without cron and then call “at” recursively to reset the job each time the shell script runs. This command sets the run time for the shell script to noon each day:

at -f "./shell/download_latest_GHRSST_data_from_ERDdap.sh" 12:00 + 24 hours

You can check the timing of the next run using:

at -l

Here is the full shell script:

#!/bin/bash
############################################ download_latest_GHRSST_data_from_ERDdap.sh
###########################################
# activate the conda environment for python
# NOTE: ~/.bashrc was modified so conda activate will work in a shell script
conda activate geo_env##########################################
# Download the latest GHRSST data for each of the regions
# from ERDDAP.
# NOTE: Edit the R script to add more regions
##########################################
Rscript "../R/download_GHRSST_MUR-JPL-L4-GLOB-v4.1_daily.R"##########################################
# Process the downloaded data and draw maps
###########################################
python "../python/batch_process_sst_and_plots.py"##########################################
# Use "at" to run the script ONE TIME without cron# and then call "at" recursively to reset the job each time
# the shell script runs.
# NOTE: before resetting the at commands, use
# atq | cut -f 1 | xargs atrm# to remove all previous jobs
# (which can be shown with: at -l)
########################################
at -f "../shell/download_latest_GHRSST_data_from_ERDdap.sh" 12:00 + 24 hours

Download the data from ERDDAP with R

Downloading the data is straightforward with a simple R script:

#####################################################
# download GHRSST, MUR-JPL-L4-GLOB-v4.1 daily
#####################################################
*setwd*("/mnt/data/dynamic_data/projects/projects2022/GHRSST_and_anomalies/R")
start_date = *paste*(*Sys.Date*()-2, "T12:00:00Z", sep='') # just one day
end_date = *paste*(*Sys.Date*()-2, "T12:00:00Z", sep='') # today minus 2 days#####################################################
# New Zealand 
url <- paste("https://upwell.pfeg.noaa.gov/erddap/griddap/nasa_jpl_dde5_3be1_897b.nc?analysed_sst%5B(",start_date,"):(",end_date,")%5D%5B(-49.0):(-31.0)%5D%5B(160.5):(179.5)%5D&.draw=surface&.vars=longitude%7Clatitude%7Canalysed_sst&.colorBar=KT_thermal%7CD%7CLinear%7C15%7C18%7C6&.land=over&.bgColor=0xffccccff", sep="")# filename <-"../data/latest_MUR_SST_New_Zealand.nc"
download.file(url, filename)
# end New Zealand#####################################################
# California
url <-*paste*("https://upwell.pfeg.noaa.gov/erddap/griddap/nasa_jpl_dde5_3be1_897b.nc?analysed_sst%5B(",start_date,"):(",end_date,")%5D%5B(30.0):(45.0)%5D%5B(-130.0):(-115.0)%5D&.draw=surface&.vars=longitude%7Clatitude%7Canalysed_sst&.colorBar=KT_thermal%7CD%7CLinear%7C15%7C18%7C6&.land=over&.bgColor=0xffccccff", sep="")filename <-"../data/latest_MUR_SST_SoCal.nc"
download.file(url, filename)
# end California

I’ve just used New Zealand and California for this example. More regions can be added by modifying the coordinates in additional URL commands. I find it convenient to use the ERDDAP GUI to generate the URL used in the R script.

Plotting the maps with Python

I use a simple python script to define the regions of interest and then plot them.

# batch_process_sst_and_plots.py
################################################################
# All regions are processed in a loop
################################################################## define regions to process# region_list =["New_Zealand_Northland","New_Zealand_Taranaki","New_Zealand_East_Cape","Australia_QLD_Brisbane","Australia_QLD_central","Australia_QLD_northern","Australia_NSW_Sydney","Australia_Tasmania","Costa_Rica","Baja_Sur","California","Gulf_of_Maine","US_Central_Bight","Florida"]# to process one or more only ...
region_list = ["New_Zealand", "California"]for region in region_list:
    import plot_SST_map
    plot_SST_map.plot_map(region)

Sea surface Temperature off California. Source: JPL MUR MEaSUREs Project. 2015. GHRSST Level 4 MUR Global Foundation Sea Surface Temperature Analysis. Ver. 4.1. PO.DAAC, CA, USA. Dataset accessed [17 July 2022] at https://doi.org/10.5067/GHGMR-4FJ04之后添加编辑

以下是绘图脚本:

*def* plot_map(region):
#########################################################
# Import packages:
#########################################################
import matplotlib.pyplot as plt
import matplotlib.ticker as mticker
from matplotlib.pyplot import tick_params
# from matplotlib.font_manager import get_fontconfig_fonts
from datetime import datetime
import cartopy.crs as ccrs
import cartopy.feature as cfeature
import cmocean as cmo
import numpy as np
import pandas as pd
import xarray as xr
import os
from pyproj import transform########################################################
# Load data
# Open a netCDF data file using xarray
########################################################
f = "latest_MUR_SST_" + region + ".nc"
datadir = ("/mnt/data/dynamic_data/projects/projects2022/GHRSST_and_anomalies/data")
d = datadir + "/" + f
# open netcdf file as an xarray dataset
ds = xr.open_dataset(d)
# open single variables in the xarray dataset
# sst_3d = ds["analysed_sst"] + 273.15
sst_3d = ds["analysed_sst"]
#reduce dimensions to 2d
sst = sst_3d.squeeze()# Generate figure (set its size (width, height) in inches).
fig = plt.figure(figsize=(5, 8))
ax = plt.subplot(1, 1, 1, projection=ccrs.PlateCarree())
ax.coastlines(linewidths=0.5)
ax.add_feature(cfeature.LAND, facecolor="lightgray")
ax.add_feature(cfeature.BORDERS)
ax.add_feature(cfeature.RIVERS)# get the min, max for SST, convert to a scalar, and round off
varmin = sst.min()
sstmin = *int*(*round*(varmin.item(),0))
varmax = sst.max()
sstmax = *int*(*round*(varmax.item(),0))
sst_int = *int*(sstmax - sstmin)
if sst_int >=6:
    contour_levels = np.array(*range*(sstmin,sstmax,2))
elif sst_int <6:
    contour_levels = np.array(*range*(sstmin,sstmax,1))################################################
# Plot data
###############################################
pt_sst = sst.plot.contourf(ax=ax,
    transform=ccrs.PlateCarree(),
    levels=contour_levels,
    cmap=cmo.cm.ice,
    add_colorbar=*False*,
    zorder=0,
)# color bar ################
from mpl_toolkits.axes_grid1.inset_locator import inset_axescax = inset_axes(ax,
    width="80%",  # width = 80% of parent_bbox width
    height="5%",  # height : 5%
    loc='upper right',
)# axins1.gridlines(draw_labels=False)
    cbar = plt.colorbar(pt_sst,
    cax=cax,
    orientation="horizontal",
    extendrect=*True*,
)cbar.ax.tick_params(labelsize=7, colors='salmon')
gl = ax.gridlines(draw_labels=*True*,
    dms=*True*,
    x_inline=*False*,
    y_inline=*False*,
    linewidth=0.25,
    color="black",
    alpha=0.25,
)# Manipulate latitude and longitude gridline numbers and spacinggl.top_labels = *False* gl.right_labels = *False* if region == "New_Zealand":
    gl.xlocator = mticker.FixedLocator([163, 167, 171, 175, 179])
    gl.ylocator = mticker.FixedLocator([-48, -46, -44, -42, -40, 
    38, -36, -34, -32])
elif region == "California":
    gl.xlocator = mticker.FixedLocator([-130, -128, -126, 
    -124, -122, -120, -118, -116])
    gl.ylocator = mticker.FixedLocator([31, 33, 35, 37, 39, 41, 43])
    gl.xlabel_style = {"rotation": 0, "size": 12}
    gl.ylabel_style = {"rotation": 0, "size": 12}########################################################
# Save the plot
######################################################### tidy by removing any previous file
os.system("rm /mnt/data/dynamic_data/projects/projects2022/GHRSST_and_anomalies/figures/latest_MUR_SST_"+region+".png")plt.savefig("/mnt/data/dynamic_data/projects/projects2022/GHRSST_and_anomalies/figures/latest_MUR_SST_"+region+".png",
    format="png",
    bbox_inches='tight',
    pad_inches=0,
    dpi=300
    )

本文只是展示了一个利用这些 SST 数据可以做什么的例子,即制作感兴趣区域海洋表面温度的每日地图。结合几个互补的工具,比如 shell 脚本、R 和 Python,可以使这个任务变得更容易。使用像 VS Code 这样的 IDE,可以在同一个项目中编辑和调试 R 和 Python,有助于将这两种语言结合起来达到更好的效果。

开源代码库

本文的代码可以在一个 Github 存储库中找到。

参考

陈,T.M .,j .瓦兹奎-库沃,和 E.M .阿姆斯壮。2017.全球海表温度的多尺度高分辨率分析,环境遥感,200。https://doi.org/10.1016/j.rse.2017.07.029

什么是供应链控制塔?

原文:https://towardsdatascience.com/automated-supply-chain-control-tower-with-python-17dbf93a18d0

使用 Python 优化您的供应链网络,通过自动化解决方案跟踪您的货物并评估延迟交付的风险。

(图片由作者提供)

供应链控制塔传统上被定义为一组连接到各种系统的仪表板,使用数据监控整个供应链的重要事件

它使供应链部门能够更好地实时跟踪、了解和解决关键问题。

在本文中,我们将实现自动化工具,用于自动发送事件报告跟踪未结货物并分析交付周期

💌新文章直接免费放入你的收件箱:时事通讯

如果你愿意,你可以观看本教程的视频版本

如何用 Python 监控你的供应链?

场景 你是一家国际服装集团分销计划 经理,该集团在世界各地都有门店。

商店补货配送计划员正在管理商店的库存,以满足需求。

供应链网络—(图片由作者提供)

当库存水平达到最低水平时

发货跟踪 每天,你需要跟踪发货情况,并向商场和物流经理报告事故:

  • 有多少货物延迟交付?
  • 当前运输中的货物在哪里?
  • 有多少转运货物面临风险?

我们的供应链控制塔将基本上是一套自动化的 python 脚本,通过电子邮件分发报告,回答这些问题。

分三步跟踪货物—(图片由作者提供)

  • 步骤 1 :使用 pandas.read_sql 执行 SQL 查询,从系统中提取出货信息
  • 步骤 2 :使用 pandasmatplotlib 处理数据并构建视觉效果
  • 步骤 3 :使用 smtplib 创建 HTML 报告并通过电子邮件发送

http://samirsaci.com

解决办法

截止时间

在系统中创建订单和由不同团队管理的商店交付之间有几个步骤

带截止时间的关键步骤—(图片由作者提供)

对于一些关键步骤,我们有截止时间,如果不遵守这些时间,总交付周期将增加24 小时。

装运记录

执行 SQL 查询后,您就有了一个包含所有所需时间戳的装运信息数据集

  • 最后状态:执行提取时流程的最后一步
  • On-Time Flags :布尔变量,检查是否遵守截止时间

已交付货物的分析

在要求的交货日期之后,已经交付了多少货件?

交付的货物(顶部:准时,底部:迟到)——(图片由作者提供)

  • 准时交货:实际交货时间比要求交货时间早
  • 延迟交货:实际交货时间比要求交货时间晚

💡准时定义
根据国际贸易术语解释通则或您想要评估的团队绩效,您可以使用不同的定义

  • 准时交货衡量的是仓库和运输团队的绩效,因为卡车到达商店时,运输团队停止了工作
  • 准时收货衡量整体物流绩效,因为它包括商店收货:当系统收到商品并准备出售时,准时收货停止
  • 准时发货在从仓库发货时停止:它衡量仓库操作的效率

有关全定义准时的更多信息,

问题 1:有多少货物延迟交付?

延迟交付环形图—(图片由作者提供)[使用 Python 创建环形图:教程

**💡 ANALYSIS**
1,842 shipments delivered with delay
- 696 due to order transmission issues
- 60 due to warehouse operational issues
- 630 impacted by transportation
- 456 due to multiple factors🧮 **PYTHON CALCULATION**
- Filter the shipments to take only the delivered ones
- Groupby Last Status: count the number of shipments
- Pandas pie plot

这种视觉效果可用于为所有团队的绩效评估制作动画

  • 传输问题:询问您的基础设施和网络团队这些问题的根本原因,并跟进他们的行动计划
  • 交付问题:与最后一英里运输团队和商店经理保持一致,以改善协调,避免迟到

按天发货状态

每日订单状态的堆积条形图—(图片由作者提供)【用 Python 创建堆积条形图:教程

例如,如果你需要运送重要的货物。这种视觉效果可以作为日常跟进工具来推动运营团队。

  • 推动仓库运营团队清理状态为 PickPack 的积压订单
  • 与您的货运代理联系,确保订单的清关文件准备就绪,状态开始清关起飞****

在途货物分析

在途货物是已经订购但尚未交付给商店的货物。

问题 2:目前运输中的货物在哪里?

运输中的货物—(图片由作者提供)

**💡 COMMENT** 2,046 shipments in transit
- 782 in the warehouse
- 593 on flight transit
- 535 in customs
- 136 on last mile delivery🧮 **PYTHON CALCULATION**
- Filter the shipments to take only the not delivered one
- Groupby Last Status: count the number of shipments
- Pandas pie plot

问题 3:有多少过境运输面临风险?

定义 如果运输中的货物错过了截止时间或在整个运输链的至少一个步骤中被延误,则被视为有风险。

面临风险的运输示例—(图片由作者提供)

在下面的例子中,您的货物离开仓库的时间落后于计划。因此,延迟交付被认为是有风险的。

运输途中的货物面临风险—(图片由作者提供)

**💡 COMMENT** 1,099 shipments in transit at risk because of delay
- During Warehouse Operations         : 534 shipments
- During the flight                   : 144 shipments
- Due to multiple factors             : 421 shipments🧮 **PYTHON CALCULATION**
- Filter the shipments to take only the not delivered one with at least on OnTime flag False
- Map the shipments with reascon code: if the flag XX OnTime = False the reason code is XX
- If you have multiple reasons the reason code is Multi
- Groupby Reason code: count the number of shipments
- Pandas pie plot

💡系列发布的重要发货
如果你要发布一个新系列,你可以格外关注这些有风险的发货,并推动团队加快进程

  • 在最后一英里使用快递,而不是标准运输
  • 对仓库提货订单进行优先级排序

什么会影响您的端到端交付周期?流程中的可变性

如果您的交付链的不同流程中存在一些可变性,该怎么办?

交付周期可变性的示例—(图片由作者提供)

在理想情况下,如果所有流程的交付周期都符合目标,那么您的交付周期为 72 小时

最佳交付流程示例—(图片由作者提供)

但是,如果您引入一些可变性,您可能会错过供应链中不同的截止时间,并造成交货延迟。

例如,您的仓库劳动力短缺,有些订单需要 5 个小时才能准备好。

这些订单将错过 19:00:00 的截止时间,卡车将不带这些订单离开。你必须再等 24 小时才能从你的 DC 发货。

欲知详情,

后续步骤

报告分发

您是否希望在一封干净的 HTML 电子邮件中自动发送上述带有评论区的图片?

几天前发表的一篇文章中提出了一个解决方案。

通过 Python 使用 HTML 电子邮件分发报告—(图片由作者提供)

您只需将您的工具插入到本文共享的 GitHub 资源库中的脚本中。

这个方法使用了 python 的 SMTP 库和一个简单的 HTML 模板。

欲知详情,

**

高级供应链分析

供应链分析可以表示为一组工具,这些工具将使用信息流来回答问题和支持决策过程。

四种类型的供应链分析—(图片由作者提供)

对于每一种类型,你都需要具体的方法、数学概念和分析工具来回答这个问题。

供应链塔可以包含在描述性和诊断性分析中,因为这有所帮助

  • 监控和可视化延迟交付
  • 使用每个流程的时间戳启动根本原因分析

对于接下来的步骤,您可以使用

欲知详情,

https://www.samirsaci.com/what-is-supply-chain-analytics-2/

关于我

让我们连接上 LinkedinTwitter ,我是一名供应链工程师,正在使用数据分析来改善物流运作和降低成本。

如果你对数据分析和供应链感兴趣,可以看看我的网站

https://samirsaci.com **

合成语音的自动评估

原文:https://towardsdatascience.com/automatic-evaluation-of-synthesized-speech-354f7a2a20d7

理解深度学习和预训练模型如何用于评估自动语音的指南

Vika Strawberrika 在 Unsplash 上拍摄的照片

语音合成,或文本到语音(TTS),是一项有几十年历史的技术,由于深度学习提供的巨大改进,它在最近几年强势回归。

随着时间的推移,合成语音听起来越来越自然,越来越难与人声区分开来。

这是总的趋势,但是不同的系统达到不同的质量水平,并且在科学努力中测量进展是重要的。不幸的是,直到最近,衡量 TTS 质量的唯一方法是请一组人类法官进行听力测试。他们会听合成的声音,并给声音的自然度打个分,通常在 1 到 5 分之间。

这个过程听起来很清楚,但是它有很多缺点。首先,该过程缓慢且昂贵,因此在开发过程中不能经常执行。这与许多其他领域不同,例如机器翻译或语音识别,在这些领域,像 BLEUWER 这样的自动化指标伴随研究人员数十年来快速衡量他们的进步。二是主观性强,不可复制。两套不同的评委会给出不同的分数,所以进入不同科学出版物的结果是无法相互比较的。第三,这个过程很嘈杂,因为我们人类不善于考虑单一因素,而忽略更广泛的背景。举例来说,有语法错误的好听声音可能会得到低分。

因此,希望有一种自动度量来克服这些问题。文献中的一个答案是利用深度学习模型自动计算 MOS。

平均意见得分

Unsplash 上的声阱拍摄的照片

平均意见得分 (MOS)是一种历史悠久的电话通话质量测量方法。它仅仅是 N 个人类裁判给出的分数的平均值。在 TTS 中,通常要求评委在 1 到 5 的范围内评估声音的自然度,其中 1 表示“绝对机器人化”,5 表示“绝对自然”。

如上所述,这是一种昂贵、缓慢且有噪声的测量方法。人类有不同的判断和不同的期望,这些都反映在他们的个人得分上。由于这些原因,测量许多人的综合得分是很重要的。

此外,系统的 MOS 易受时间变化的影响,因为技术的改进改变了对其质量的期望。此外,它还受法官的人口统计数据的影响。年龄、对技术的接触和文化背景都是影响他们将分配的分数的因素。例如,说第二语言的人通常会比母语为 TTS 语言的人给出更高的分数,因为他们会发现更多的发音错误。

自动 MOS

一种使评估过程更加自动化的解决方案是训练机器学习模型来再现人类得分。作为参考,我们将遵循 Erica Cooper 及其同事的“MOS 预测网络的泛化能力”。这不是第一篇关于这个话题的论文,但我发现它真的很有用。

这篇论文是关于 MOS 预测网络的训练技术以及它们如何推广到未知领域的有趣研究。在这篇文章中,我将强调最突出的几点。我将报告我认为最有趣的想法,并尝试为不熟悉该主题的读者解释较难的部分。我推荐感兴趣的读者去看看这篇论文。这篇文章可以看作是对这个主题的介绍和阅读指南。

数据集

与任何机器学习模型一样,自动 MOS 预测需要数据集来训练模型,并在训练训练阶段期间和之后对其进行评估。

该数据集基于自 2008 年以来多年进行的大量听力测试。主数据集被称为 BVCC ,它是由作者创建的,然后他们还使用了三个额外的域外数据集进行测试。

术语

在继续之前,澄清一些将在下文中使用的术语是有用的。

一个听众是人类评价中的法官。他/她提供网络旨在模拟的评级。

扬声器是用于训练 TTS 模型的配音演员。通常,TTS 模型是根据一组预定义的声音进行训练的,并且只能产生这些声音。

一个系统是一个带有推理算法的 TTS 模型。

一个文本仅仅是用来合成声音的文本。这将在下文中考虑,因为对于 TTS 模型来说,在训练期间生成看不见的单词是具有挑战性的。

BVCC

BVCC 之所以被这样称呼,是因为它主要是由 TTS 的Blizzard ChallengeVofficeCon versionChallenge以及用开源工具 ESPnet 生成的公开可用的句子构建而成。由于数据来自多个语境,作者进行了一次新的听力测试,对样本进行统一评分。

它们总计超过 7000 个样本,由 8 位评委、27 位扬声器和 187 个测试系统进行评分。

域外数据

在这种情况下,域外数据是未进行额外听力测试的注释数据(合成语音+人类评级)。它们在域外,因为它们的上下文不同于训练数据的上下文。如前所述,评级会因人而异,并随着时间的推移而变化,因此我们可以预期评级分布与培训数据的分布不同。

此外,还有一个日语数据集和一个汉语语音数据集,这两个数据集在语言领域之外。

培训/开发/测试设备

在划分数据集时,一个目标是每个子集匹配全局数据集的 MOS 分布;此外,它们的目标是匹配每个话语的评分标准偏差的分布。后一点的原因是,一些系统经常收到比其他系统更多样化的评级,这应该反映在所有子集中,以便进行正确的评估。

此外,开发和测试子集应该有看不见的演讲者、系统、听众和文本。如果一个实体不在训练集中,它对开发集是不可见的。如果一个实体既不存在于训练集也不存在于开发集中,那么它对测试集是不可见的。

为此,他们首先将发言者、系统、听众或文本分配给开发或测试集,不进行替换,然后用剩余的材料将其余部分填充到所需的数量,从而生成多个候选拆分。然后使用总数据分布和每个子集之间的推土机距离 (EMD)的总和来评估候选分割。它是针对单个样本的分数以及标准差计算的。

他们用不同的随机种子计算了 1000 个分裂,然后选择了 EMD 总和最低的一个,因为这意味着它是全局分布和每个子集之间距离最低的分裂。

域外数据集被分成大小相等的训练集、开发集和测试集。然后,考虑两种不同的情况:

  • Zero-shot: 在域外测试集上对系统进行评估,之前没有对其训练数据进行任何类型的训练。
  • 微调:系统首先使用域外数据集的训练集和开发集进行训练,然后在其测试集上进行评估。

预训练模型的作用

从到目前为止的讨论中,我们理解为自动 MOS 的任务获取训练数据是困难和昂贵的。这项研究的作者发现,仅仅根据 BVCC 的数据从零开始训练一个 MOSNet [2]并不太好。

更有效的策略在于使用在大量音频数据上预先训练的模型,并在相同的 BVCC 数据上对其进行微调。Wav2vec2 [3]似乎符合目标。它最初是在大型音频数据上以自我监督的学习目标进行训练的,并且已经在其他具有音频输入的任务上成功地进行了微调。说话者、情绪和音素分类都是受益于使用预先训练的 wav2vec2 模型的任务。此外,它在 fairseq 工具包和拥抱脸变形金刚中免费提供代码和预训练模型。

作者还用 XLSR [4]进行了实验,这是另一个大型预训练模型,它是针对多语言音频数据进行训练的。据推测,多语言训练对语音识别是有用的,但从目前的研究结果来看,情况并非如此。XLSR 显然比从零开始训练要好,但只在针对日本人的零射实验中胜过 wav2vec2。但 wav2vec2 在实验条件上更好,对日本小数据进行微调,对中国人同时进行零炮和微调。

挑战

这篇论文的进一步分析清楚地表明,这种自动 MOS 网络很难预测看不见的说话者、听者、系统和文本的正确结果,但方式不同。

看不见的系统绝对是最困难的挑战,所以如果可能的话,在你想要评估的系统上微调你的 MOS 预测器总是一个好主意。看不见的文本监听器只对 6 个测试系统中的 2 个系统特别困难,而看不见的扬声器只对没有微调的预训练模型有问题。

结论

用于 TTS 模型评估的自动 MOS 预测是一项具有挑战性的任务。训练数据的获取必须遵循严格的准则,并考虑许多变量,如各种测试系统、扬声器、听众和文本。

另一方面,很明显,系统的零射击评估特别困难。在快速开发环境中,最好的评估方法是为新系统收集一些训练数据进行评估。然后,根据这些新数据微调 MOS 预测器,最后对系统进行大规模评估。

与语音识别的单词错误率等指标相比,这种方法仍然很慢,但预训练模型的存在使其比从头开始训练好得多。

研究更好的系统零射击评估方法将会改变这一领域的游戏规则。

更多来自我

参考文献(带链接)

[1] Cooper,Erica,等.“MOS 预测网络的泛化能力”ICA ssp 2022–2022 IEEE 声学、语音和信号处理国际会议(ICASSP) 。IEEE,2022。https://arxiv.org/abs/2110.02635v3

[2] Lo,Chen-Chou,等.“MOSNet:基于深度学习的语音转换客观评估” Proc。散客 2019(2019):1541–1545。https://arxiv.org/abs/1904.08352

[3]巴耶夫斯基、阿列克谢等,《wav2vec 2.0:语音表征的自我监督学习框架》神经信息处理系统进展33(2020):12449–12460。https://arxiv.org/abs/2006.11477

[4] Conneau,Alexis 等,“用于语音识别的无监督跨语言表征学习” arXiv 预印本 arXiv:2006.13979 (2020)。https://arxiv.org/abs/2006.13979

感谢您的阅读

这不是一篇简单易懂的文章,所以非常感谢你能坚持到现在。敬请关注我的更多内容!

自动单词相关度评估| WordNet、SpaCy 和 Wikidata API

原文:https://towardsdatascience.com/automatic-word-relatedness-evaluation-wordnet-spacy-wikidata-api-9fd1c72ac73c

⚠️在本文中,我将依靠赫斯特模式和用法的先验知识进行上位词提取。然而,我将使用专利的数据集,所以我建议检查我在这个周期的前一篇文章。

W 我们为什么要关心单词的相关性?那么,让我们从什么是关联性及其在 NLP 中的应用开始。

拓扑结构上下文中的相关度可以通过具有“父”单词和“子”单词来解释。到目前为止,这些术语被称为:

上位词——…一个具有广泛意义的词,构成了一个具有更具体意义的词所属的范畴;

下义——……是反向的意思;比适用于它的一般术语有更具体含义的词。

为了便于理解,这里有一个例子:

在这里,“光盘”和“硬盘”是“存储单元”的的下位词。反过来,“存储单元”是“光盘”和“硬盘”的上位词

简而言之,这样的词汇关系是 NLP 任务的基本构件。与 NER(命名实体识别)一起,这种关系可以应用于各种任务,例如分类预测、信息提取(IE) 和简单的数据集创建(高级模型的示例)。

你会在我之前的文章中找到更多关于上位词以及如何提取它们的信息。在这里,我将集中使用几种工具来评估单词之间的关系类型。它不仅可以用于检查上位词对,还可以用于评估词对关系的任何其他应用。

数据

作为一个例子,我将使用专利的G06KT30【数据识别/数据呈现】小节中的专利文本。最重要的是,我训练了一个定制的 NER 模型来识别技术术语。我在我的 上一篇 中详细描述了这个数据集。

⚠️数据不受版权保护,可安全用于商业目的。 根据USPTO:受 37 CFR 1.71(d) & (e)和 1.84(s)中反映的有限例外限制,专利的文本和图纸通常不受版权限制

用于评估的上位词对

为了实现,我们将重用已经提取的上位词对。你可以从项目的 repo 中下载这个文件。这里有几个例子。

“关系”和“标签”行表示连接的方向。“1”或“hyper”意味着 word1 是 word2 的更广泛的含义(上位词)。

方法 1 | WordNet 相似度

第一种方法基于 WordNet 数据库,以距离的形式比较单词之间的相似性。尽管这个分数不能给出一个精确的答案,如果对是上下位关系,它仍然是有价值的简单和快速评估提取的数据。

实现非常简单;你需要安装 nltk 包并下载 WordNet 到里面。

然后,为每个单词创建一个名为 synset 的对象包装器,并运行它们之间的相似度计算。Synset 是“一组认知同义词,每个同义词表达一个不同的概念”。有时单词可以根据上下文表示不同的意思,因此 synset 提供了一组这些意思以及到其他单词的链接。

下面是一个关于“光盘”和“计算机”与吴-帕尔默相似性的演示。这个分数表示两个词义的相似程度,基于这两个词义在分类法中的深度。正是我们需要的!

然后,为每个单词创建一个名为 synset 的对象包装器,并

由于使用了 WordNet,这种方法可以修改,并在基于单词分类法的任务中有很大的潜力。然而,这种方法的一个很大的缺点是很多单词不能在字典中找到。这尤其与术语和缩写有关。它们不会被 nltk 识别,因此相似度无法计算。

方法 2 |空间

另一种直接的方法是利用深度学习 NLP 模型的单词间嵌入距离。目前最简单的方法是使用空间。有了这个库,你可以利用一个已经预先训练好的模型或者训练定制模型。在前面的步骤中,我们已经为模式数据集中的命名实体识别(NER)调优了一个定制模型。推荐使用微调模型,因为它在相似性评估时会给出更好的准确性

要计算相似度,只需对目标词加载模型运行相似度()函数:

利用空间和定制训练模型计算单词间的相似度

或者,下面是使用默认模型的方法:

与默认空间模型的计算相似性

方法 3 |维基数据 API

最新的、最伟大的、老实说也是最慢的方法——[Wikidata](https://www.wikidata.org/wiki/Wikidata:Main_Page)。

Wikidata “充当其 Wikimedia 姊妹项目(包括 Wikipedia、Wikivoyage、Wiktionary、Wikisource 等)的 结构化数据 的中央存储。”它具有基于图形的结构和开放的 API 来访问数据。与 WordNet 相比,Wikidata 包含大量经常更新的信息。那些我们确实会发现大部分新旧技术术语和缩略语。

你可以在这里玩来搜索图表中的数据,并可视化实例的属性。

作者提供的 word " 计算机 " |图像属性的图形可视化

具体来说,我们对属性p268(的子类)感兴趣,它在图结构中具有“父单词”的 ID。

Web 界面上的必要字段|作者提供的图片

要在 Python 中连接和使用这个 API,安装 qwikidatawptools

在导入 libs 之后,我们需要获得单词对中两个单词的 id。下面是一个“iPad:和母词“电脑”的例子。通过利用 get_parse() ,我们搜索并解析该术语的页面,然后从【wikibase】字段中提取 ID。

用于检查维基数据中单词子类的 Python 脚本

然后,我们通过使用get _ subclass _ of _ item()查找父类的所有可能子类的 ID,简单地检查子类的 ID 是否在这个列表中

最终结果|所有方法一起

综上所述,最好的方法是什么?没有明确的答案,下面是原因。

我们在 144 个提取对的整个列表上运行了所有三种方法,并创建了一个表来比较结果。

最终结果表

总的来说,每个方法的输出被转换成 3 类:相关、不相关和错误。对于距离测量的方法,我们根据经验选择阈值。

评分系统|图片由作者提供

完整的表和 Python 函数来创建这样的结果,您可以在项目报告中找到。

所以,关于得到的结果。已经可以看出,WordNet 大部分时间都是给出错误的。为什么?这就是我们所说的 WordNet 字典的局限性。WordNet 不太可能包含专利中的缩写或高度特定的技术术语。

按最高空间分数排序的最佳结果

让我们来看看空间分数最高的一对。很明显“HSV 颜色空间”是“颜色空间”的子类。这里空间相似性工作得最好。基本上,它只是由类似的话触发,没有什么特别的,但它的工作。

另一方面,这并不是一种持续的行为。看看下面的例子。

按最低空间分数排序的最佳结果

按照预期,“显示设备”和“液晶显示器应该有相当大的相似度得分,但是没有。然而,Wikidata API 有望在这种情况下工作,并提供正确的结果。

你已经注意到了 WordNet 的一个常量⚠️(错误)。但不代表没用。这就是证据:

WordNet 有用性的例子

“手机”明明是“电子设备”;它对维基数据没有影响,仍然给空间相似性一个很小的分数。

它显示了什么?任何问题都没有灵丹妙药。然而,利用几种不同方法的复杂方法可能是一种防弹解决方案。

这个解决方案会更好吗?当然啦!这里有一些想法和可能的改进

  • 🔪利用 WordNet 的 n-grams。像图像处理单元 - >图像处理单元。拆分单词以查找字典中的相似类别
  • 🪞尝试同义词
  • 🛠 改进了维基数据的 Graph-Q 查询。老实说,获取所有子类既慢又不可靠。最好创建一个自定义查询来检查特定的 ID 并将其传递给 API。

完整的代码和解析的数据可以在这里找到:

https://github.com/kinivi/patent_ner_linking

自动单词求解

原文:https://towardsdatascience.com/automatic-wordle-solving-a305954b746e

去掉 Wordle 的乐趣本身就是乐趣…让我们看看怎么做

机器人文字解算器,插图(图片由作者提供)

首先,一个起源的故事。大约一周前,我开始玩单词游戏。对于那些不知道的人,只需点击链接并播放一次:你就会知道它的要点。这有点像游戏的策划者,但是有文字。有一些隐藏的单词,你会得到提示,你猜测的单词是否和那个单词有相同的字母,可能在完全相同的位置。我觉得这特别有趣,因为这又回到了我的博士导师提出的一个观点:语言有特殊的结构,这使它与纯组合学非常不同。因此,如果解决摄魂师是一个棘手的组合问题(实际上是 NP-complete ),那就值得伟大的唐·克努特写一篇文章,Wordle 看起来也应该很有趣。

第一个区别是,在某种意义上,你的目标是在每一步最大化信息(这有一个正式的含义:参见这个漂亮的 数据科学信息论简介 了解更多细节)。所以,重复你已经知道的字母是没有用的。按照这种逻辑,你应该尽量减少你所使用的单词之间的相似性。此外,也许找出隐藏单词中的元音是很好的,因为单词基本上是围绕它们的元音构建的。回到我的起源故事,我按照这个逻辑,用“点”和“激光”的开场序列。然而,在最后一个单词中,不知何故失败了,我在 6 次尝试中没有猜出这个单词。一个未来的 Wordle 反派诞生了。

让我们看看计算机会如何看待 Wordle。

起初,全方位的隐藏单词是可能的。在每一次猜测之后,这个隐藏单词列表会根据收到的反馈进行删减。在我们做出每一个猜测之后,“对手”(一些邪恶的单词恶魔,试图找到最难猜的隐藏单词,给出我们迄今为止所知道的)可以选择最令人困惑的反馈。这在玩家和对手之间建立了一个广泛形式的游戏,理想情况下,我们会运行一个极小极大算法,通过逆向归纳找到玩家在每个阶段要做的最好的事情。然而,这是一个非常大的运行状态空间,以一种合理的方式来完成它是不可行的。此时,我们需要决定以何种方式学习一些不完美的策略(并为此使用来自强化学习的一些方法)。然而,在我们的例子中,有直观的贪婪试探法可以首先尝试,希望它们足够好。让我们提两个:

  • ( Greedy-min-max )选择最小化最大剩余可能单词列表的猜测:

每次猜测后,现有的可能单词列表根据对手给出的反馈进行划分。因为最终,我们只想得到一个可能的单词,一个好的目标是逐渐减少可能单词列表的大小。

  • (平均-最小化)选择最小化平均剩余可能单词列表的猜测:

我不太喜欢这种方法(因为我们的目标是最差情况下的性能,而不是平均性能),但我们也会尝试这种方法,因为无论如何,这些只是启发式算法,而不是最佳算法。请注意,最小化平均单词列表等同于拥有最大数量的不同反馈以供猜测(想想为什么…)

切入正题,这是我的 Github 库,它实现了一个脚本,该脚本遵循以下策略:

https://github.com/yotam-gafni/wordle_solver

(它还有一个实现,您可以每天使用它来玩)

我感谢这两个 Github 项目,在那里我得到了可能的猜测词和隐藏词的列表。查看它们,因为它们具有自动求解器所不具备的有趣特性:

https://github.com/coolbutuseless/wordle https://github.com/octokatherine/word-master

此外,看看 Absurdle :它采用我们讨论过的对抗方式,并试图让你尽可能多地移动!

为了伟大的结果…

贪婪最小最大最坏情况性能是 5 次猜测

平均最小化最坏情况性能是 6 次猜测

两者都能够总是击败沃尔多游戏!难以置信。

但是……有一个小小的警告。这个游戏有一个硬模式,你只能使用在那个阶段仍然有可能的单词作为猜测。这样,Greedy-min-max 最坏情况下的性能是 8 次猜测。我相信这可以通过查看发生这种情况的少量特定树路径来解决:如果有人足够勇敢,这是一个有价值的任务!

最后但同样重要的是,许多人都在问的问题的答案是:在 Wordle 中最佳的第一步是什么?

我见过很多关于它的答案,从 adieu (在 USAtoday,没少)到 raise ,但 greedy-min-max 的答案是毫无疑问的, [aesir](https://en.wikipedia.org/wiki/Æsir#:~:text=The Æsir (Old Norse%3A [,resulting in a unified pantheon.)

由于今天 greedy-min-max 的表现,如果没有一些绿色方块,这篇文章是不完整的:

单词 203 4/6

🟨⬜⬜⬜🟨
🟩🟩⬜⬜⬜
⬜⬜⬜🟨🟩
🟩🟩🟩🟩🟩

这是所有关于曲柄出的数字!

安静,祝你愉快。

(后记:如果想看另一条解决 Wordle 的路径,可以看看 Ido 的帖子:https://medium . com/@ I do-frizler/the-science-behind-Wordle-67c 8112 ed0 d 1。我从 Eyal Walach 那里听说,他们实现了一种类似的方法,能够在最多六次猜测中解决硬模式。也欢迎你在推特上关注我,我在那里分享数学和经济学的内容

使用 isort 自动排序 Python 模块导入

原文:https://towardsdatascience.com/automatically-sort-python-module-imports-using-isort-b750873cde75

在本教程中,我们将探索如何使用 isort 库自动排序 Python 模块导入

Jonah Pettrich 在 Unsplash 上的照片

目录

  • 介绍
  • 什么是 isort
  • 示例代码文件
  • 如何对模块导入进行排序
  • 结论

介绍

随着 Python 项目的增长,您开始拥有越来越多的文件,每个文件都有更多的代码行,执行更多的操作,并且导入更多的依赖项。

在 research step 中,我们通常在需要时一个接一个地导入库,这使得整个导入部分变得杂乱无章,并且通常难以快速编辑。

此外,当在一个工程师团队中工作时,大多数人都有他们自己偏好的构造和排序导入的方式,这导致不同的文件版本在同一个存储库中相互覆盖。

使用 isort 可以很容易地解决这个问题,它提供了一种在 Python 项目中对导入进行排序的系统方法。

为了继续学习本教程,我们需要以下 Python 库:isort。

如果您没有安装它,请打开“命令提示符”(在 Windows 上)并使用以下代码安装它:

pip install isort

什么是 isort

isort 是一个 Python 实用程序和库,它自动按字母顺序对 Python 模块导入进行排序,同时按类型将它分成不同的部分。

除了 CLI 实用程序和 Python 库之外,它还有许多代码编辑器插件,如 VS Code、Sublime 等等。

示例代码文件

为了测试 isort 库的功能,我们需要一个示例 Python 文件。

在这个示例文件中,我们将混合导入的顺序,并添加一些间距来说明未排序文件和排序文件之间的区别。

下面是一个未排序的 Python 代码示例( main.py ):

如何对模块导入进行排序

一旦我们在目录中有了 Python 文件,就很容易用 isort 对模块导入进行排序。

打开命令行或终端,导航到包含 Python 文件的目录。

单个 Python 文件中的排序模块导入

如果只有一个文件需要对模块导入进行排序(在我们的例子中是 main.py ,只需运行:

isort main.py

重新格式化的示例 Python 文件应该如下所示:

看起来好多了,所有的模块导入都是有序的!

多个 Python 文件中的排序模块导入

如果您想对多个 Python 文件或整个 Python 项目中的模块导入进行排序,只需运行:

isort .

isort 将自动查找所有的 Python 文件,并在目录中的所有 Python 文件中对模块导入进行排序。

结论

在本文中,我们探索了如何使用 isort 库对 Python 文件中的模块导入进行自动排序。

如果你有任何问题或对编辑有任何建议,请随时在下面留下评论,并查看我的更多 Python 编程教程。

原载于 2022 年 9 月 23 日 https://pyshark.comhttps://pyshark.com/automatically-sort-python-module-imports-using-isort/

使用外部 API 和云函数自动更新 BigQuery 表

原文:https://towardsdatascience.com/automatically-updating-a-bigquery-table-using-an-external-api-and-a-cloud-function-c05423ca3ed

关于构建完全自动化的过程来定期更新 BigQuery 表的分步指南

沙恩·奥尔登多夫Unsplash

语境

最近,Roquette Data & Advanced Analytics 团队一直在研究 BigQuery 或 Snowflake 等分析数据仓库如何改善我们的最终用户对数据的访问。

这种数据仓库提供了一个全球平台,可以轻松地接收、处理结构化数据,并将其提供给业务用户或解决方案。

在这篇文章中,我将解释我们如何开发一个简单的过程来接收来自外部 API 的天气数据,并将其提供给我们的用户。

此类数据有助于检测本地温度和制造过程输出之间的任何相关性(有时就是这样!)或者我们的销售是否会受到温度变化的影响。

本教程需要的内容:

  • 一个免费的 API 来获取全球各地的各种天气信息(我们的设施几乎遍布每个大洲)。我们的一位数据科学家(亚瑟·特尔德斯)发现 OpenMeteo 很好地满足了我们的需求。
  • 数据仓库平台。在本文中,我们将使用来自 Google 的: BigQuery

在 Google 云平台中建立一个新项目

我会假设你已经有一个 GCP 帐户。如果没有,你可以很容易地打开一个,并获得 300 美元的信用 30 天。如果你已经有了一个,记住这个例子几乎不会花你一分钱(<0.05$).

You should start by creating a new project to isolate your work. Click on the project selector in the top left and then “New Project”:

Project Selector on GCP— Image from Author

New Project Button on GCP — Image from Author

We call this new project “api-weather-test” and click on “create”:

New Project Creation on GCP — Image from Author

Selecting your project and activating APIs

Once your project is created (it should take a few seconds only), we select it by using again the project selector to reach the project homepage:

Project selection on GCP — Image from Author

GCP 的项目主页——图片来自作者

我们的新项目来将已经嵌入的功能(如 BigQuery),但我们需要激活一些额外的 API。我们应该在搜索栏中查找的第一个是“云发布/订阅 API”:

GCP 的云发布/订阅搜索—图片来自作者

到达相应的页面后,我们只需启用 API。

在 GCP 启用云发布/订阅 API 图片来自作者

我们的自动化概念

我们打算定期从外部 API(例如每天),然后将其转移到 BigQuery 表中。

如下所述,实现这一目标的一种可能方式是:

  • 创建能够查询外部 API 和更新 BigQuery 表的 Python 脚本
  • 将这个 Python 脚本封装到一个云函数中,该云函数将“监听”发布/订阅消息并等待其触发,
  • 每天广播一条“Pub/Sub”消息(就说午夜吧!)将被填充到项目中。

因此,每次发送“发布/订阅”消息时,云函数都会执行 Python 脚本并更新大查询表。

自动化概念—图片来自作者

步骤 1:使用云调度程序创建作业

我们通过搜索栏进入“云调度程序”用户界面:

GCP 云调度搜索—图片来自作者

我们创建了一个新职位,并开始定义:

  • 它的名字,
  • 它被执行的区域,
  • 它的描述,
  • 它的频率,在 Unix-cron 格式下指定(如果你不熟悉的话,你应该查一下 CronGuru ),
  • 和它的时区。

云调度程序——在 GCP 创造就业机会——图片来自作者

我们还必须定义将要执行的目标的类型。我们选择“发布/订阅”并创建一个名为“天气”的新主题,因为所有消息都应该属于一个预定义的主题。

云调度程序—GCP 上的作业配置—图片来自作者

云调度程序——GCP 上的主题创建——图片来自作者

我们不会使用消息体的特性,所以您可以随意放置(这里是“更新”):

云调度程序——在 GCP 创造就业机会——图片来自作者

创建完成后,这个新作业应该出现在列表中,其下一次计划的执行时间显示在“下次运行”列中。

云调度器用户界面—图片来自作者

步骤 2:在 BigQuery 中创建我们的表

我们再次使用搜索栏到达 BigQuery 页面,并单击“Create Dataset”(一个包含表或视图的数据集)

BigQuery 主页——图片来自作者

关于这个新数据集的重要信息是:

  • 其 ID(=名称,此处为“天气”)
  • 它的位置

(额外的设置是可用的,但对本例没有用)

BigQuery —在 GCP 上创建数据集—图片来自作者

创建后,它应该出现在我们的项目结构下,如下所示:

BigQuery —数据集—图片来自作者

有几种方法可以创建空表。我们选择执行相应的 SQL 表。

将“api-weather-test- 372410 ”替换为您自己的项目名称后,只需点击“编写一个新的查询,并运行以下指令:

big query—使用 SQL 创建表格—图片来自作者

|CREATE TABLE `api-weather-test-372410.WEATHER.TEMPERATURES` (time TIMESTAMP,
                                                             Portage_la_Prairie FLOAT64 OPTIONS (description = 'External temperatures in C° for Portage plant.'),
                                                             Wuhan FLOAT64 OPTIONS (description = 'External temperatures in C° for Wuhan plant.'),
                                                             Benifaio FLOAT64 OPTIONS (description = 'External temperatures in C° for Benifaio plant.'),
                                                             Beinheim FLOAT64 OPTIONS (description = 'External temperatures in C° for Beinheim plant.'),
                                                             )

我们可以观察到该表包含:

  • 一个带有时间戳类型的“时间”列,
  • 4 个浮动柱对应于我们的四个罗盖特工厂(真实数据集包括 25 个罗盖特工厂)。

BigQuery —带有 SQL 的温度表—图片来自作者

通过在 SQL 指令中使用“OPTIONS (description = '…')”,每个列的描述都包含在表方案中,使用户更容易理解其中包含什么类型的信息。

我们的(空)表已经准备好欢迎数据…让我们跳到下一步!

步骤 3:创建云函数

我们可以通过搜索栏导航到“Cloud Functions”页面,然后点击“Create Function”(注:Google 可能会要求您激活其他 API,如 CloudBuild 和 CloudFunctions )

注意:云函数可以被认为是小容器,在其中执行代码。它们支持不同的语言,例如:。NEt,Go,Java,Node,PHP,Python,或者 Ruby。

我们创建了一个名为“天气更新”的功能,由“天气”主题的“发布/订阅”消息触发。

云功能配置—图片来自作者

一旦配置完成,我们需要选择相应的语言。我们选择 Python 3.9 作为运行时。

现在只需要复制粘贴我的 GitHub 中的代码:

云函数— main.py 配置—图片来自作者

云功能— requirements.txt 配置—图片来自作者

我们点击“部署”并等待云功能激活:

云函数 UI——图片来自作者

因为我们想确保该功能运行良好,而不需要等到午夜,所以我们单击“Test function”立即运行它:

云函数 UI —动作—图片来自作者

日志确实确认了该功能的正确执行。

云函数日志——图片来自作者

我们返回到“BigQuery”页面,执行下面的 SQL 指令(确保使用您自己的项目名称:api-weather-test- XXXXXX )。

该表现在包含从 2022 年 1 月 1 日至今的所有可用记录:

BigQuery — SQL 指令执行—图片来自作者

注:美国石油学会提供的数据为近似值。5 天的延迟,这意味着在 22/12 执行的查询将检索到 17/12 的数据。

严峻的考验!

我们可以去睡觉了😪并且等到第二天早上检查午夜更新是否顺利!

我们从检查“发布/订阅”消息是否运行开始…它确实运行了:

我们跳转到云函数日志,看到“天气更新”函数在午夜被正确执行,几秒钟后:

云函数日志——图片来自作者

正如所料,BigQuery 表现在包含了新记录😁:

BigQuery — SQL 指令执行—图片来自作者

然后,瞧!

不需要任何额外的工作,BigQuery 将在每天午夜更新,没有进一步的行动。

在我们结束这篇文章之前,请注意以下几点:

  • 为了使本文的代码尽可能简单,Python 脚本完全删除了表内容,每次都用所有可用的数据更新它。这不是优化资源的最佳方式。在生产中,我们应该以“增量模式”工作,只从 API 中检索自上次更新以来的新记录,并将它们传输到表中。
  • 假设我们想要将“温度”表中的信息与另一个 BigQuery 表(例如:“流程 _ 输出”)。我们将不需要使用第二个云函数。我们可以直接使用“预定查询”来执行 SQL 指令(例如内部连接)。

像往常一样,我试图确定所有需要的步骤,但如果我的教程中有任何遗漏的说明,请不要犹豫来找我!

请不要犹豫,浏览我在 Medium 上的其他文章:

https://pl-bescond.medium.com/pierre-louis-besconds-articles-on-medium-f6632a6895ad

自动化深度神经网络

原文:https://towardsdatascience.com/automating-deep-neural-networks-d76af8e0c7fa

使用 DeepHyper 自动开发深度神经网络

克里斯里德在 Unsplash 上的照片

创建神经网络模型很困难,因为我们需要估计或找出给定问题的最佳超参数。我们需要决定用于解决问题的层数和神经元数。创建神经网络模型时,需要考虑多个实体。

有不同类型的神经网络,即 ANN、CNN、RNN、LSTM 等。对于所有这些模型,都有不同的超参数来帮助提高模型的准确性和性能。为了创建不同类型的神经网络,我们需要遵循一定的步骤。

DeepHyper 是一个开源的 python 库,它不仅可以自动化创建模型的过程,还可以帮助进行超参数调整和模型评估。这有助于理解黑匣子里发生了什么。

在本文中,我们将使用一个 DeepHyper 来创建神经网络模型并对其执行操作。

让我们开始吧…

安装所需的库

我们将从使用 pip 安装 DeepHyper 开始。下面给出的命令可以做到这一点。

pip install deephyper

导入所需的库

在这一步中,我们将导入所需的库和函数来创建深度学习模型。

from deephyper.problem import HpProblem
from deephyper.evaluator import Evaluator
from deephyper.evaluator.callback import LoggerCallback
from deephyper.search.hps import AMBS
import matplotlib.pyplot as plt

创建模型

在这一步中,我们将创建需要优化的函数,然后创建搜索空间,还创建评估器接口,最后创建搜索算法。

def f(config):
    return - config["x"]**2
problem = HpProblem()
problem.add_hyperparameter((-10.0, 10.0), "x")
problem

功能(来源:作者)

接下来,让我们创建评估器。

evaluator = Evaluator.create(
    f,
    method="ray",
    method_kwargs={
        "num_cpus": 1,
        "num_cpus_per_task": 0.25,
        "callbacks": [LoggerCallback()]
    },
)print(f"Evaluator has {evaluator.num_workers} available worker{'' if evaluator.num_workers == 1 else 's'}")

评估(来源:作者)

创建搜索是最后一步,让我们来完成它。

search = AMBS(problem, evaluator)

创建搜索后,我们需要执行一定数量的搜索。

results = search.search(max_evals=100)
results

结果(来源:作者)

我们也可以使用 matplotlib 可视化评估。

plt.plot(results.objective)plt.xlabel("Iterations")
plt.ylabel("$y = f(x)$")plt.show()

结果(来源:作者)

在这里,我们可以清楚地看到目标以及它是如何向 0 收敛的。继续尝试,如果你发现任何困难,请在回复部分告诉我。

本文是与皮尤什·英加尔合作完成的

在你走之前

感谢 的阅读!如果你想与我取得联系,请随时通过 hmix13@gmail.com 联系我或我的 LinkedIn 个人资料 。可以查看我的Github*简介针对不同的数据科学项目和包教程。还有,随意探索* 我的简介 ,阅读我写过的与数据科学相关的不同文章。

在 Amazon SageMaker 上自动部署预先训练好的模型

原文:https://towardsdatascience.com/automating-deployment-of-pre-trained-models-on-amazon-sagemaker-46d50c246503

在 SageMaker 推理上部署 TensorFlow ResNet50

图片来自 Unsplash附身摄影

过去,我曾写过在亚马逊 SageMaker 上部署预先训练好的模型。虽然我发布的工件是可复制的,但它需要理解AWS SDK和适当的 API 调用,以及理解更高级别的 SageMaker Python SDK

对于新用户来说,这可能需要消化很多东西,为了使体验更简单,我已经帮助构建了一个 API ,它自动化了用户为了正确部署 SageMaker 端点而必须理解的大量底层工作。有了这个 API,重点是使预训练模型的迁移对于数据科学家和一般不熟悉 SageMaker 或 AWS 的用户来说更加简单和直观。

目前支持什么?目前该 API 被称为 SageMaker 迁移工具包,它支持 TensorFlow、PyTorch 和 Sklearn 模型的预训练模型部署。除此之外,还有对实时和无服务器端点的支持,默认情况下,如果您没有指定您想要的推断选项,该包将部署到无服务器端点。最后,目前只有单个模型端点支持实时推理,但对于预先训练的多模型部署的手动示例,请查看这些示例

在今天的文章中,我将带您了解如何利用 TensorFlow 框架将这个 API 与流行的预训练的 ResNet50 模型一起使用。

SageMaker 迁移工具包设置

关于 API 的设置说明可以在 GitHub 自述文件中找到。安装与其他 Python 包非常相似,您将在下面的步骤中看到。

  1. 克隆 GitHub repo
  2. python setup.py bdist_wheel
  3. pip install dist/sage maker _ migration _ toolkit-0 . 0 . 1-py3-none-any . whl
  4. sagemaker _ migration.configure 模块名称 sagemaker_migration.configure

第四步是为 SageMaker 服务添加 IAM 角色。您应该能够在 IAM 控制台中访问它,或者在笔记本单元中运行以下代码来获得您的角色。

import sagemaker
sagemaker.get_execution_role()

在这个例子中,我们将在一台 SageMaker 笔记本上使用 conda_tf2 内核,以便预装 TensorFlow。

ResNet50 型号设置

在开始使用迁移工具包之前,我们需要正确下载和序列化 ResNet50 模型工件。SageMaker 希望模型数据的格式符合框架的服务栈。对于 TensorFlow 服务,序列化模型数据遵循 SavedModel 格式。模型数据的结构应该如下所示:

model_artifact_version/
    variables/
        variables.data
        variables.index
    keras_metadata.pb
    saved_model.pb
inference.py #optional, but recommended

使用 TensorFlow,我们可以加载 ResNet50 模型。

import os
import tensorflow as tf
from tensorflow.keras.applications import resnet50
from tensorflow.keras import backend
import numpy as np
from tensorflow.keras.preprocessing import image

tf.keras.backend.set_learning_phase(0)
model = resnet50.ResNet50() #Load model

既然我们的模型已经加载,我们可以将这些模型工件转储到一个目录中,其结构如上所示。

export_dir = "00002" #directory to store model artifacts
model = tf.keras.applications.ResNet50()

if not os.path.exists(export_dir):
    os.makedirs(export_dir)
    print("Directory ", export_dir, " Created ")
else:
    print("Directory ", export_dir, " already exists")
# Save to SavedModel
model.save(export_dir, save_format="tf", include_optimizer=False)

保存的模型工件(作者截图)

最后,SageMaker 迁移工具包还期望提供一个 inference.py 脚本。对于那些不熟悉的人来说,一个 inference.py 文件允许用户将他们的预处理和后处理逻辑添加到他们的端点。对于这个模型,我们真的不需要任何前/后处理,所以我们可以创建一个没有任何功能的虚拟推理脚本。

%%writefile inference.py
import os
import json

我们现在准备利用迁移工具包进行模型部署。

SageMaker 迁移工具包部署

我们首先导入必要的模块来使用这个包。

from sagemaker_migration import frameworks as fwk
import os

在框架模块中,目前支持 TensorFlow、PyTorch 和 Sklearn。我们创建一个 TensorFlow 模型实体,并传递适当的参数。

# Create a TensorFlow Model Object Entity, you can create a real-time or serverless endpoint
tf_model = fwk.TensorFlowModel(
    version = '2.3.0',
    model_data = '00002',
    inference_option = 'real-time',
    inference = 'inference.py',
    instance_type = 'ml.m5.xlarge')

这里有几个强制参数:

  1. model_data (str):这是序列化模型数据的路径。
  2. 推论(str):这是你的推论. py 脚本,即使是空的也要提供一个。
  3. version (str):这是您的模型的框架版本,在底层,工具包将搜索该版本支持的 SageMaker 容器。

至于推理选项,默认设置为无服务器推理。如果您指定推理选项,您还可以设置参数,例如用于实时推理的实例类型,以及用于无服务器推理的并发/内存。

与使用 Boto3 的主要区别在于,您不再需要与模型、端点配置、图像和其他较低层次的相关 SageMaker 对象进行交互。当您部署这个 TensorFlow 模型实体时,您将看到所有这些都是自动创建的。

tf_model.deploy_to_sagemaker()

端点创建(作者截图)

模型 tarball 是自动为您创建的, SageMaker 模型SageMaker 端点配置,最后是 SageMaker 端点本身。

结论

https://github.com/aws-samples/sagemaker-migration-toolkit/blob/main/examples/resnet-sm-toolkit.ipynb

您可以在上面的链接中找到这个例子的代码。如果您在使用 API 或您想要请求的任何模型时有任何问题,请在 Github 上添加 PR 或问题。一如既往,我希望这篇文章是一个有用的指南,尤其是对那些刚接触 SageMaker 上的模型部署的人。敬请关注更多信息,感谢所有反馈。

额外资源

负载测试 SageMaker 端点

SageMaker 自带容器

如果你喜欢这篇文章,请在 LinkedIn 上与我联系,并订阅我的媒体 简讯 。如果你是新手,使用我的 会员推荐 报名。

自动化 EDA 和机器学习

原文:https://towardsdatascience.com/automating-eda-machine-learning-62724e8967a7

使用 MLJAR-Supervised 自动化 EDA 机器学习模型并创建降价报告

来源:作者

探索性数据分析是理解我们正在处理的数据的重要步骤,它有助于我们识别数据中的任何隐藏模式、数据的不同列之间的相关性以及分析数据的属性。EDA 通常会占用项目总时间的 30%左右,因为我们需要编写大量代码来创建不同类型的可视化并对其进行分析。

Python 提供了 N 个库,这有助于自动化 EDA 过程,从而节省时间和精力,但是如何选择使用哪个库呢?选择一个库取决于我们试图解决什么类型的问题。

如果我们试图从头开始制作一个机器学习模型,我们可以使用 MLJAR-Supervised。它是一个开源的 python 库,具有不同的功能,即:

  1. 自动化 EDA
  2. ML 模型选择和超参数调整。
  3. 创建报告等。

在本文中,我们将探索 MLJAR-Supervised。让我们开始吧…

安装所需的库

我们将从使用 pip 安装一个 MLJAR 监督的库开始。下面给出的命令可以做到这一点。

!pip install mljar-supervised

导入所需的库

在这一步中,我们将导入加载数据集、对数据集执行 EDA 以及创建机器学习模型所需的库。

import pandas as pd 
from sklearn.datasets import load_digits
from sklearn.metrics import accuracy_score
from sklearn.model_selection import train_test_split
from supervised.automl import AutoML
from supervised.preprocessing.eda import EDA

正在加载数据集

在本文中,我们将使用著名的“糖尿病”数据集,可以从网上下载。我们将导入数据,并将其分为训练和测试数据。

df_train = pd.read_csv("/content/train.csv")
df_test = pd.read_csv("/content/test.csv")
X_train,y_train = df_train.drop(['Outcome'],axis=1),df_train['Outcome']
X_test,y_test = df_test.drop(['Outcome'],axis=1),df_test['Outcome']

执行 EDA

现在我们将在一行代码中执行 EDA。

EDA.extensive_eda(X_train,y_train,save_path="/content/mljar-supervised/")

EDA(来源:作者)

在这里,您可以清楚地看到不同类型的图和图形,您可以分析这些图和图形来查看数据模式。

创建机器学习模型

现在我们将使用 AutoML 创建 ML 模型。

a = AutoML(mode='Perform',total_time_limit=10)
a.fit(X_train,y_train)

来源:作者

在这里,您可以看到 AutoML 创建了 6 个不同的模型,并对它们进行了特性重要性分析。

这些模型可以根据我们的要求来使用,我们可以为我们的模型选择最佳的特征,因为我们已经有了特征重要性,所以 MLJAR 是一个完整的包,它可以通过分析数据和创建可视化来帮助您了解数据集是什么,然后它创建不同的模型并找到这些模型的特征重要性,所有这些都是在几行代码中完成的。

继续尝试不同的数据集,执行 EDA 并制作机器学习模型。如果您发现任何困难,请在回复部分告诉我。

在你走之前

感谢 的阅读!如果你想与我取得联系,请随时通过 hmix13@gmail.com 联系我或我的 LinkedIn 个人资料 。可以查看我的Github*简介针对不同的数据科学项目和包教程。还有,随意探索* 我的简介 ,阅读我写过的与数据科学相关的不同文章。

使用 Python 自动生成费用报告

原文:https://towardsdatascience.com/automating-expense-reports-with-python-95c43a63980c

斯科特·格雷厄姆Unsplash 上拍照

使用 Python 和 mindee API 自动化费用报告

过去,员工必须手工提交费用报告,或者至少在电子表格上起草报告。然后,计算机出现了,内置的电子表格使得生成和跟踪报告变得更加容易。但是,如果您能够自动完成整个数据输入过程,以便根据收据图像生成费用报告,那会怎么样呢?

在本文中,我将向您展示使用 Python 自动化费用报告的步骤。

步伐

自动化费用报告的步骤如下:

  1. 开户上 被管理人 平台
  2. 设置一个 API 键
  3. 安装“mindee”包
  4. 导入依赖关系
  5. 编写助手函数
  6. 从费用单据中加载、解析、提取数据
  7. 将结果导出到表中
  8. 保存表格到 ***.csv*** 文件

我们开始吧!

1.在 mindee 平台上创建账户

对于这种自动化,为了避免编写自定义代码来检测收据图像中的文本, 我们将使用一个名为 ***mindee***的 Python 包,它附带了一个 API,只需几行代码就可以完成所有这些工作。

虽然这个包的专业版是付费的, 他们每月免费提供 250 页 ,对于个人来说应该是绰绰有余,可以实现个人费用报告的自动化。

要创建帐户,请执行以下操作:

  1. 前往[mindee](https://platform.mindee.com/) 平台网站
  2. 签约雇用

2.设置 API 密钥

要设置 API 密钥,请执行以下操作:

  1. 点击“创建新的 API”
  2. 选择“费用收据”API
  3. 复制您的 API 密钥并保存它。

3.安装“mindee”软件包

要安装mindee包,请运行:

pip install mindee

4.导入依赖项

对于这个项目,我们将使用以下软件包:

  • mindee
  • pandas
  • random
  • glob
  • matplotlib
  • seaborn

如果您的本地环境中没有它们,请用pip install <package>安装它们。

现在我们可以导入我们的依赖项:

from mindee import Client, documents
import random
import pandas as pd
import glob
# Sanity Check using pandas and matplotlib
import matplotlib.pyplot as plt
import seaborn as sns
sns.set()

5.编写助手函数

为了实现这种自动化,我们需要 3 个助手函数:一个用于在从mindee API 获得响应后提取费用数据,另一个用于将时间转换为膳食类型(在本例中,我的费用报告需要明确说明膳食类型,如午餐或晚餐的食物费用)。最后,第三个函数用于创建包含所有数据的最终表。

代码将是:

作者写的。

# Output of the tests written above['13:51', '11:49', '22:13', '19:57', '10:32', '20:47', '20:40', '14:27', '14:41', '15:06']
13:51 Lunch
11:49 Lunch
22:13 Dinner
19:57 Dinner
10:32 Lunch
20:47 Dinner
20:40 Dinner
14:27 Lunch
14:41 Lunch
15:06 Lunch

最终表格的测试示例。图片由作者提供。

6.从费用收据中加载、解析和提取数据

现在,我们要做的就是:

  1. 使用我们获得的 API 密钥实例化我们的 mindee 客户端
# Instantiate a new client
mindee_client = Client(api_key="Your API KEY")

2。初始化一些包含提取数据的空列表

date_list = []
amount_list = []
category_list = []
time_list = []
meal_type_list = []
filenames_list = []

3。加载费用收据的图像,并将其馈送给 mindee API

image = "./expense_images/1669895159779.jpg"
input_doc = mindee_client.doc_from_path(image)
api_response = input_doc.parse(documents.TypeReceiptV4)
expense_data = api_response.document
expense_data<mindee.documents.receipt.receipt_v4.ReceiptV4 at 0x7f9685b278b0>

输出将是一个为费用收据定制的 mindee 对象(可能有几个选项,所以可以在 mindee 平台的官方文档中随意研究)。

4。从 API 响应中提取费用信息

date, amount, filename, category, time = extract_expenses_data(expense_data)

5。将时间信息转换成相关的餐饮类型信息

这个例子对我来说是非常具体的,所以你可以根据你的费用类型来改变这个函数。但是在这里,我所做的是将一个类似于13:30的字符串转换成午餐,将一个类似于20:30的字符串转换成晚餐。

if not time:
        meal_type = "Unknown"
else:
    meal_type = convert_time_to_meal_type(time)

6。将提取的信息附加到相应的列表中

在这种情况下,我只对单个收据这样做,但是当对多个收据这样做时,列表方法将更有意义。

date_list.append(date)
# I am replacing the . for , here because the final report goes on
# a google sheet which takes `,` instead of `.` for float numbers.
amount_list.append(str(amount).replace(".", ","))
category_list.append(category)
time_list.append(time)
meal_type_list.append(meal_type)
filenames_list.append(filename)

7.将结果导出到表格

现在我们已经组织好了数据,我们可以用结构化数据创建一个表。

# The format of the table will be | data | amount | filename | category |
df = create_table(date_list,amount_list,meal_type_list, time_list,category_list, 
                  filenames_list)

# show the table to check
df

8.将表格保存到.csv文件

最后,我们保存了包含所有费用收据信息的表格。

df.to_csv("expense_table.csv", header=False)

将所有东西整合在一起

现在我们已经详细了解了每个步骤,在多张费用收据上运行该操作的完整源代码如下:

作者写的。

从费用收据中提取数据的最终表。图片由作者提供。

你有它!你自动完成了根据收据图像报告开支的枯燥任务!作为最终检查,最好看一下最终结果,以确保您获得的信息与费用收据中的实际数据一致。

为此, 我们可以将收据与使用 ***matplotlib*** 提取的每张费用收据的文本数据并排可视化。

作者写的。源代码可以在这里找到。

样本检查图像示例。图片由作者提供。

样本检查图像示例。图片由作者提供。

...
...
...
I am showing just a couple of images with restricted 
information for privacy reasons but the overall idea is here.

好的,结果似乎一致!我们有它,一个整洁的自动化来节省你每个月的时间!

关于自动化一切的最终想法

如果您是一名经理、开发人员、会计或几乎任何与某种数据输入相关的人,这种方法可能非常有用。本质上,它清楚地表明,只需几行 Python 代码就可以实现工作场所的自动化。

为什么不使用一个简单的程序来自动处理您的费用报告呢?自动化类似这样的重复性任务可以节省你相当多的时间,并且它打开了简化你的工作流程的大门。

如果你喜欢视频,请点击这里查看我的 Youtube 视频:

如果你喜欢这个帖子, 加入 Medium**订阅我的 youtube 频道 我的快讯 😃。**

这里有几个 提高工作效率必备物品 的链接:

这些是附属链接,如果你使用它们,我会得到一小笔佣金,干杯!😃

参考

用 Python 自动化 Visual Studio 代码中的代码片段

原文:https://towardsdatascience.com/automating-snippets-in-visual-studio-code-with-python-55b8824d05dd

克里斯里德在 Unsplash 上的照片

用 Python 自动化 Visual Studio 代码中的代码片段

使用 Python 和 VSCode 加速片段工作流

每一个好的开发工作流都涉及某种代码片段的管理,在这里,您不断地存储和检索代码片段,以解决编程例程中的各种任务。

在本文中,我将向您展示如何使用 Python 自动创建 VScode 代码片段,只需一个终端命令就可以直接从剪贴板保存它们。

从代码到格式化的片段

在 VScode 中,代码片段文件的格式如下:

{
"Title": {"prefix": "the prefix of the snippet",
"body": ["the body of the snippet", "as a list of strings".
         "where each list element corresponds to a line of code",
"description": "a description of the snippet"}
}

VScode 文本编辑器应该利用这种结构,以便当您调用所需代码片段的前缀时,您会得到一段符合您当前特定需求的格式完美的代码。

这里的问题是,创建这样一个片段的过程可能有点麻烦,所以我们最终谷歌了几乎所有的东西,这有时会有点烦人。

那么,为什么不用 Python 来自动化这个过程呢?这样,当你写一些代码,你想保存它以后,你所要做的就是把它保存到剪贴板,然后在终端上运行一个命令。

从剪贴板保存片段的步骤

做到这一点的步骤将是:

  1. 使用代码片断文件夹的路径指定一个变量。
  2. 编写代码以获取剪贴板的内容。
  3. 编写代码,以正确的格式将内容保存在预先指定的 snippets 文件(在调用脚本时确定)中。
  4. 将最终的 Python 脚本保存在文件夹中。
  5. 编写一个别名,以便在终端的任何地方调用该脚本。

现在,让我们一个接一个地完成每个步骤。

  1. 用 snippets 文件夹的路径指定一个变量
global_snippets_folder = “/home/username/.config/Code/User/snippets/”

VScode 通常有这样一个路径的 snippets 文件夹,根据您的具体情况进行更改。

2。编写代码以获取剪贴板的内容

import clipboardclipboard.paste()clipboard_content = clipboard.paste()

这里,我们使用clipboard包来获取剪贴板的内容。

3。编写代码,以正确的格式将内容保存在预先指定的片段文件(在调用脚本时确定)中

这段代码将剪贴板的内容保存到指定的文件夹中,文件夹的名称由用户在调用脚本时指定,并且具有稍后在 VScode 中调用代码段所需的格式。

4。将最终的 Python 脚本保存在一个文件夹中

在这里你可以把它保存在你电脑里任何你想要的文件夹里。

5。编写一个别名,从终端的任何地方调用该脚本

要做到这一点,你所要做的就是打开你的.bashrc文件并写下:

alias save_snippet_from_clipboard="python /path/to/python_script.py"

然后,保存修改后的文件并运行source .bashrc来更新您的终端。

现在,您可以直接从剪贴板中保存代码片段了!

图片来自 https://giphy.com/

做同样事情的许多方法

值得注意的是,这只是一种方法,有很多方法可以保存和检索代码片段,最后,你应该尽可能多地尝试各种工具,看看哪些对你有用。

由于从剪贴板保存代码的问题,我在这里描述的方法在保证保存的代码片段的格式不变方面有一些缺点,但最终,我觉得每次我需要保存或检索某个代码片段时节省的几秒钟是值得的。

如果你愿意,你可以在这里观看我的 Youtube 视频:

如果你喜欢这个帖子,加入媒体关注订阅我的简讯。还有,订阅我的 youtube 频道Tiktok推特LinkedInInstagram 上和我联系!谢谢,下次再见!😃

使用机器学习自动化视频创建过程

原文:https://towardsdatascience.com/automating-the-process-of-video-creation-f416da4db362

使用机器学习来总结新闻文章并创建短视频提要

照片由马克·克鲁兹Unsplash 上拍摄

随着 短格式视频 和高度 个性化内容 的消费上升,您是否想过根据自己的喜好定制新闻视频源?这种视频源将帮助我们避免我们经常从多个来源消费的冗余新闻和无关内容。

在这篇博客中,让我们尝试自动化视频创作过程。在这个过程中,为了简单起见,我们将使用现成的预训练模型(尽管微调这些模型会提高性能)。

首先,让我们选择一个要制作视频的文本源。

这里有一篇摘自 bbc.com 的文章,谈论新当选的澳大利亚总理及其背景。

https://www.bbc.com/news/world-australia-61267489

工艺流程:

工艺流程

第一步:

既然我们试图将一篇文章制作成一个短视频,那么总结这篇文章并从中获取重要信息是非常必要的。

导入库

我们将使用 hugginface 的管道来总结文章。

第二步

我们的下一个目标是为摘要中的每一句话找到一个关键词,并基于该关键词得到一个相关的图片/视频。我们将使用 KEYBERT 来查找句子中的关键字。KEYBERT 在后台使用 BERT 来提取句子的关键字。

第三步

现在,我们已经为摘要中的每一句话找到了一个关键词,让我们为这些关键词找到一个相关图片

由于我们没有一个大型的图像数据库,我们将使用谷歌的图像搜索来为关键词找到一个合适的图像。

幸运的是,有人已经在这方面做了工作,我们将使用他们的回购来下载图像。

第 4 步

我们可以在这些图像上叠加摘要文本,最后将它们一帧一帧地拼接在一起,形成一个视频。

将文本覆盖在每个框架上

最后,将每一帧拼接在一起

输出视频:

https://youtube.com/shorts/gUG4sneHKwY?feature=share

考虑到我们没有微调我们的模型来寻找关键词和从新闻数据集中提取摘要,视频的输出相当不错。

最终代码:

Github链接:

https://github.com/pawanreddy-u/videocreation

我希望这个博客对你有所帮助。敬请关注机器学习和数据科学领域更多有趣的博客。

Python 自动化:使用 Cx Oracle 连接到 Oracle 数据库

原文:https://towardsdatascience.com/automation-python-scripts-connecting-to-oracle-database-using-cx-oracle-1fe1801821b5

我如何使用 Cx Oracle 和其他一些 Python 库来自动化小型 ETL 任务

来自像素的图像

我一直使用 cx_Oracle Python 扩展模块来访问我的 Oracle 数据库,因此我能够自动化我的大多数小任务。

Oracle 提供的在线文档可以帮助您直接访问 Oracle 数据库,但在本文中,我将演示如何使用 Cx Oracle 和其他一些 python 库来自动执行从本地计算机到 Oracle 数据库的小型 ETL 任务。

目标是编写一个 python 脚本,它读取本地文件夹中的文件,执行数据清理和转换,然后插入到 Oracle 数据库中。然后,可以通过任务调度程序对这个 python 脚本文件进行调度,以便它可以按照设定的时间表自动运行。将添加额外的日志记录代码来跟踪脚本中发生的事情。

先决条件:

在您可以在 python 脚本中编写 Cx Oracle 之前,您需要安装 Oracle 客户端库,当您成功安装这些库后,您就可以开始编写 python 脚本了。为了开始这个脚本,我导入了这些库:

import pandas as pd
import cx_Oracle
import math
import logging

记录器信息块:

logger info 代码块生成一个日志文件,记录您的脚本是否成功运行。如果脚本是自动执行的,这些日志会很有用,这样您就可以得到命令状态的通知。

数据加载和清理:

第一个 python 函数从服务器或本地文件夹读取文件,在必要时清理和转换数据,然后返回所需的数据框输出,该输出将用于插入 Oracle 数据库表。代码非常简单,可以添加任何额外的命令来转换数据集。

Cx Oracle 连接

第二个 python 函数是数据库连接和 Oracle 命令发生的地方。块的第一部分需要连接细节,如用户名、密码、主机名、端口和 SID,以便 python 可以与 Oracle 通信。第二部分是通过简短的 SQL 查询定义命令或任务。我在函数中添加了 3 个查询,Truncate (清除表但保留表模式)、Insert (在表中注入数据)和 Grant Access (授予公共访问权限以便用户可以查询您的表) —如果需要,可以添加更多的查询。

脚本运行程序

调用这两个函数的 python 脚本的最后一部分。如果您已经注意到 logger.info 在整个脚本的大多数行中都被调用,这使得跟踪每个命令的状态变得更加容易。

这个 python 脚本文件现在可以用作批处理文件的一部分,可以通过任务调度器上传或通过命令提示符运行(logger info 也通过 cmd 打印通知)

如果你对导入速度感兴趣,我已经在小型到大型数据集上进行了测试。例如,对于 100 万行代码,python 脚本花了大约 12 分钟才成功导入到我的 Oracle 表上。当然,这取决于您本地机器上的其他几个因素。

总的来说,这个简单的 python 脚本和自动化过程将帮助您节省时间来完成占用您一些时间的小任务。

https://www.kathleenlara.com/】网站:

推特:https://twitter.com/itskathleenlara

利用强化学习实现供热系统调度自动化

原文:https://towardsdatascience.com/automatizing-the-heating-system-scheduling-with-reinforcement-learning-4146480d17b9

一个基于我自己家庭经历的例子

在气候变化和能源危机的背景下,能源效率已经成为焦点话题。建筑物是能源消耗的主要来源,值得考虑采用明智的策略来提高能源的利用率。有人会争辩说全球范围内的事情离我太远了,但即使在今天能源越来越贵的背景下,即使从省钱的角度来说,这个问题也值得更多的讨论。

在这种背景下,我写这篇文章是受到我自己家庭经历的启发:

  1. 我们有三个人,两个成年人和一个婴儿,都有不同的日常事务,即成年人去办公室或留在家里远程工作,婴儿在固定的工作日和工作时间去托儿所。
  2. 成年人和婴儿对舒适度的要求不同,即我可以忍受较低的温度,而婴儿必须保持温暖。此外,我们通常在睡觉时热量较少。
  3. 事实上,包括我们在内的大多数人都不知道我们的理想温度到底是多少。我们能做的,就是每次感觉冷的时候,按下暖气系统界面上的“加号键”。供暖系统会采取行动回应我们的要求,直到我们对环境满意为止。一般来说,按下“加号按钮”告诉系统“我很冷”是我们用户与供暖系统的唯一交互,它将无法访问其他信息。见下图。

作者图片:用户如何与供暖系统互动

我今天要讨论的问题是,供暖系统能否通过与用户的互动,学会执行最佳行动以节约能源并保证所有家庭成员的舒适水平。

为了简化问题,我假设供暖系统只有两种模式:开和关。

在这种背景下,我想建立一个强化学习模型,这样供暖系统将根据与用户的交互来决定何时打开和关闭,以便在保证所有家庭成员舒适的同时降低能耗。

供暖系统环境的模拟

让我们快速了解一下,强化学习的目标是让代理(在我们的例子中是加热系统)通过与环境的交互,通过试错来学习最大化奖励函数的最佳行动。

我想建造一个简化的供暖系统环境(冬季),灵感来自我的家庭经历:

  1. 有三个人两种不同的情况:在家或者不在家。他们每个人都有一个温度下限,即这个人会按下“加号键”来告诉系统“我冷”。当然,当没人在家时,不会有任何互动发生。此外,我们认为我们可以在晚上有较低的温度。没人在家时,温度设定为。
  2. 我们每隔 10 分钟对模型进行离散化,即每隔 10 分钟计算一次室内温度,每隔 10 分钟记录用户是否按下按钮。因此,加热系统必须根据环境状态每 10 分钟执行一次动作。
  3. 每种情况下的室内温度值取决于室内温度值以及最后一次加热是否开启。我们通过离散化由节点描述的简化模型来计算它的值。

回到强化学习语言。在这个模拟中,RL 环境的状态由两部分描述:如果用户感觉冷(加热系统从交互中学习)和时间(星期几、小时、分钟)。并且代理或加热系统学习基于这样的状态来学习是开启(1)还是关闭(0)。

我们将奖励函数定义为:

奖励=-总和(动作+1.5*(手感 _ 冷)),

也就是说,每当暖气开着,家里有人感到冷时,我们就会受到惩罚。请注意,如果有人感到寒冷,我们会加大惩罚力度,以保证家中的舒适度。

作者图片:RL 系统图解

最佳行动的 q 学习

为了学习最佳行动,我们将应用简单而强大的 Q 学习算法。该方法用状态空间和动作空间维度的乘积的维度来构造 Q 表。它在每一步将相应单元的 Q 值更新为旧值和所获得的下一状态的新信息与当前状态和所执行的动作的加权平均值。

下面是 Q-learning 算法的核心部分:

自动化调度

现在环境和学习算法都建立起来了,我们现在要做的就是把每一块拼起来,学习供热系统的最佳调度。在 1e4 训练周期后,奖励从-1173 增加到-533。下面是一周的学习供暖计划(1 表示开,0 表示关,由灰点给出)和模拟室内温度(蓝线)的曲线图。橙色线代表室内温度的下限。你可以看到系统采取尽可能少的“开”动作,让室内温度保持在下限以上。

作者图片:供暖计划和一周内的室内温度

我还会给出另一个类似的情节,但只有一天的持续时间,在此期间没有人在家几个小时。你可以更清楚地看到,供暖会一直持续到家庭成员开始回家前 30 分钟。

供暖计划和一天内的室内温度

结论

在本文中,我举了一个例子,说明强化学习如何帮助供暖系统实现自动化,成功地节省了能源,并在一个受我自己家庭情况启发的模拟环境中保证了一定程度的舒适度。我相信,这一程序可以在其他建筑中实施,包括占用空间大得多的办公楼,供暖系统将从与用户的互动中学习,以达到全局最优的解决方案。

AutoML 与数据科学的未来

原文:https://towardsdatascience.com/automl-and-the-future-of-data-science-82a1b8f65e7e

AutoML 将如何发展应用机器学习的前景

新视野。作者图片

如果你正在阅读这篇文章,你可能已经知道什么是自动机器学习。这是谷歌开发的一个工具,用于自动化整个机器学习管道,微软和亚马逊也有自己的云实现。

自动机器学习旨在对大量模型和超参数进行广泛而深入的搜索,以找到问题的最佳模型和特征工程。除了自动化当前机器学习项目的很大一部分,它也相对容易上手。根据您组织的技术基础设施,对于那些拥有软件或云经验的人来说,大规模运行他们自己的模型可能非常简单。

由于这一点以及过多的低代码/无代码工具席卷了整个行业,我们看到大量文章声称 AutoML 将取代数据科学家。在某种程度上,我不同意,在这个故事中,我将揭示我相信随着 AutoML 的进一步采用会发生什么。

数据科学家是做什么的?

这可能会因公司和领域而有相当大的差异,但总体而言:数据科学家与商业领袖合作,进行实验并建立机器学习模型,以提供统计见解并指导高价值的商业决策。这通常意味着该角色是某种高度技术性的内部和/或外部顾问。

这些项目的整个生命周期始于数据工程师将来自无数系统的数据整理和验证成数据库、数据湖、数据仓库等中合适的格式。然后,当业务需求出现时,数据科学家负责了解手头的问题以及哪些数据可以成为解决方案。这需要与数据工程师和业务领导进行大量的交流,以找到合适的数据源、质量限制等等。

然后,数据科学家通常会构建一个更注重实验而非可扩展性的概念验证模型。这个 PoC 阶段是高度迭代、混乱和探索性的。这一阶段包括与数据分析师更紧密的合作。这个阶段的输出结果是识别初始的强特征、数据依赖性、工作的模型、最佳超参数、模型/项目的限制等等。数据科学家应该掌握大量的统计和算法技术来解决手头的问题。一旦我们对 PoC 有了足够的信心,我们将重构到目前为止编写的代码以优化性能,这样我们就可以将模型投入生产。

部署阶段涉及与机器学习工程师的合作,以帮助生产模型并建立足够的模型监控。项目的后期部署工作通常是数据科学家和机器学习工程师之间的协作。最后,数据科学家将进行演示,简明清晰地解释模型、模型结果以及它与业务的关系。

这是一个令人难以置信的简化观点,每个功能都有自己的深度和挑战,但操作和拥有整个生命周期是应用机器学习。此外,数据项目通常不是线性的,而是迭代的。每个阶段通常会发现一些需要回顾前一个阶段的东西,因此让所有角色从一开始就参与进来会有很大帮助。最后,根据组织的规模和可用资源,您可以轻松地让一个人扮演多个角色。我见过的最常见的角色组合是

  • 数据科学家/机器学习工程师:通常通过创建可扩展的 ML 系统来提高性能,这些系统在远超过 Jupyter 笔记本的领域中工作。从本质上来说,这就是公司招聘“数据科学家”的意思。
  • 数据科学家/数据分析师:通常更擅长速度和实验。通常在首席分析师或产品 ds 职能部门结束。
  • 数据科学家/数据分析师/机器学习工程师:通常出现在高层、领导和校长中。多种行业的大师。

自动机器学习(AutoML)是做什么的?

AutoML 自动化了整个机器学习工作流程。

最好是在云基础设施内部完成,如谷歌云平台或 Azure 机器学习或亚马逊 SageMaker。AutoML 致力于取代当今数据科学家通过搜索找到建模任务的最佳超参数和模型来进行的所有手动调整和模型实验。它还处理迭代部分,因为它的主要功能是优化评估指标,这样它们将保持迭代,直到获得最佳结果(或者达到终止标准)。

作者图片

一旦经过训练,它可以很容易地部署到云上的生产实例中,并在其中设置模型监控检查,以审查精度-召回曲线、特性重要性等。

AutoML 学习的底层算法主要是数据科学家/mle 已经学习的,但这些云产品如何真正执行 AutoML 通常很少透明。也就是说,你可能会看到艺术模型和集合模型在这里被大量使用,并且经常与手工制作的模型性能相当。

数据可视化和特征工程与 AutoML 的结合也非常有用。该系统能够识别关键的特征交叉、适当的转换以及沿途的关键可视化。

最后,这些云平台也有特定的深度学习产品,带有 AutoML,用于诸如 Vision(例如。对象检测)、NLP(例如。OCR)、时间序列(例如预测),等等。

AutoML 真正帮助了谁?

读了上面的内容,你很容易说“那么数据科学家显然是无用的”。我认为恰恰相反。见证低代码/无代码运动真的很棒,尤其是随着云平台被广泛采用。对初学者来说,高度技术性的工作正变得越来越容易上手。事实上,它变得如此简单,以至于人们觉得任何人都可以做这项工作,几乎不用讨论质量和对所做工作的理解程度。低代码/无代码工具的缺点是,在邓宁-克鲁格效应中,它更容易陷入“过度自信,能力不足”的阶段。

公共领域

当我们大量抽象高度技术性和复杂的工作时,我们降低了入门的门槛,但也使人们更容易陷入初级水平。当您可以使用无限制的云计算运行 AutoML 时,为什么要了解哪些模型最适合手头的任务,为什么某些模型会让您的业务用例失败,为什么需要根据您的问题对评估指标进行优先排序,等等。这些问题的答案开始揭示 AutoML 真正的赢家,但让我先做一个类比。

Tableau 是当今最流行的数据分析产品之一。我开始了我的 it 职业生涯,获得了认证,并且是这个工具的超级粉丝。这是一个了不起的产品,因为它把以前非常技术性和耗时的事情变成了简单的拖放。我可以轻松地制作条形图、饼图、复杂的仪表板、伪网页等等。作为一个初学者,这给了我难以置信的力量,对此我很感激。但是老实说,我最初的很多仪表盘都很糟糕。它们没有刺激行动,没有深刻的思想,而且更“有趣”,而不是号召行动的故事。即便如此,对我来说,声称自己是专家还是很容易的,因为我可以利用这个工具相对简单的易用性。随着我职业生涯和硕士项目的进展,我深入了解了色彩理论、视觉极限、有目的的设计以及如何用代码构建数据可视化。这种更深刻的理解帮助我度过了初学者的低谷,但对我来说,继续伪装成专家可能会非常容易。即使是现在,我也看到过多的 Tableau 仪表盘,人们觉得它们很有效,因为他们“有设计眼光”,而实际上它们一点也不有效。

Tableau 让任何人都很容易成为数据分析师,它刚刚证明了大多数人并不擅长它。这并不意味着冒犯,而是意味着认识到好的和高质量的数据分析不是可以简化为拖放工具的东西。学习做正确的事情需要花费时间和精力,这是很深的专业知识,远远超过一次点击就能创建条形图。

AutoML 比任何人都更能帮助数据科学家。每当我听说你可以让工商管理硕士和其他未经培训的 ML 专业人员轻松完成这项工作,我觉得这很滑稽。技术复杂性的抽象使得新手很容易上手,但主要受众总是专家。AutoML 自动化了该工艺最繁琐的部分,但这项工作比仅仅优化一个集合模型的准确性要广泛和深入得多。

展望合作的未来

我所知道的任何一个高度精通的数据科学家根本不关心 AutoML 事实上,他们对此很兴奋。这是因为他们不能等待 PoC 工作中最繁琐、最反复的部分实现自动化,因为他们知道自己真正的价值不在于做这些繁琐的工作。AutoML 无法处理对模型的解释(不,打印评估指标不是解释),无法向业务领导提供采取什么行动的建议、了解数据集中不存在的哪些新功能可能很重要以及如何获得它们、如何将它们集成到跨企业构建的更大的模型或软件系统中,等等。

我确信有这样的例子,未经培训的 ML 专业人员使用 AutoML,将其投入生产,并为企业创造了数百万的价值。这一成功并不归功于 AutoML,而是归功于贵公司的数据文化和基础设施。我读过很多关于谷歌如何用 AutoML“杀死数据科学家”的故事,但很少有人承认他们在谷歌使用它。在大多数公司中,如果您打算加入“公民数据科学家”的行列,您可能需要一个集中的管理机构来监控正在创建的模型、原因以及它们的表现。

也就是说,AutoML 将杀死某一类功能,那就是“伪数据科学家”。这些数据科学家或 MLEs 真正陷入了“过度自信,能力不足”的阶段,并拒绝学习、成长和进化。AutoML 将使他们的价值主张显著降低,并迫使他们从事分析师或 MLE 职能。公民数据科学家是并列的,但只要期望得到管理,这是可以接受的;你不会期望从公民医生或公民律师那里得到高质量的结果,你也不应该在这里。

虽然我认为这些文章有点耸人听闻,但我相信角色和责任的重新定义将会到来,特别是由于这些工具的出现。我并不是说数据科学家或 MLE 角色将完全不受影响,而是说他们的专业知识实际上将比我们今天更需要、更受重视。像 AutoML 这样的工具变得普及是一个迹象,表明这种技能无疑是一致需要的,能够在其技能范围内高水平操作它的人将赢得未来十年的应用机器学习。

作为数据科学家/分析师,不要重复这 5 个编程错误

原文:https://towardsdatascience.com/avoid-these-5-programming-mistakes-as-a-data-scientist-analyst-4b7017d509fe

提高数据科学家工作效率的步骤

图片来源:Unsplash

在我目前作为数据科学经理的角色中,我与多位数据科学家合作,我看到他们中的许多人在处理大数据时犯了一些基本的数据操作错误(我也曾经犯过一些这样的错误!).这些错误会导致代码执行时间的急剧增加,有时还会导致大量的返工和浪费。

在这篇博文中,我将讨论如果你想成为一名更好(更高效)的数据科学家,你应该避免的 5 大编程错误。

处理大数据时应避免的 5 大错误:

1。在不知道数据级别/主键的情况下连接数据集

数据级别被定义为每行具有唯一值的列或列的组合。数据的级别通常由一些 ID 变量定义(比如客户 ID)。让我们用例子来理解这一点:

一、单列为级:在下面的数据集中,Order ID 列没有两行具有相同的值,所以 Order ID 是该数据集的数据(主键)级。

数据集 1(作者提供的图片)

连续列(如 Sales)不能定义为数据级别。

二。作为级别的多列:在下面的数据集中,我们可以看到订单 ID 对于多行是相同的,因此它不是该数据集的级别。如果我们仔细观察,我们会发现没有两行的订单 ID 和产品 ID 组合具有相同的值,因此这两列都是该数据集的数据级别(主键)。

数据集 2(图片由作者提供)

在执行连接时,理解数据的级别变得非常重要,因为连接主要是在数据集的主键上执行的。

在非主键上连接数据集可能会导致错误的结果。

2。不过滤所需的行

有时,数据科学家不会在查询开始时筛选所需的行,而是等到最后一次查询时才筛选这些行。处理大数据是一种犯罪,因为它会大大增加执行时间,尤其是在应用连接等复杂操作时。

不好的做法

Step 1: Transform data 
Step 2: Apply join operation
Step 3: More transformation 
**Step 4: Filter rows**

好的做法

**Step 1: Filter row** Step 2: Transform data 
Step 3: Apply join operation
Step 4: More transformation

3。使用大量连接/自连接

自连接就像一把双刃剑,如果你恰当地使用它们,它们可能是一件好事,但是如果你过于频繁地使用它们,它就是一个祸根,因为在 Hadoop、Hive、Spark 等分布式环境中,连接是最昂贵的任务。

假设我们有一个组织内员工的工资数据。

我们希望添加一个列,其中包含与当前行相对应的工作角色(数据科学家、数据分析师、数据工程师)中所有员工的总工资。我们希望输出如下所示:

你会使用自连接得到上面的输出吗?是不是最优的方式?

不,自连接不是获得该输出的最佳解决方案,相反,我们应该使用窗口函数来获得所需的结果(如下所示)。

不好练

## Using Joins 
select a.EMPID, a.NAME, a.JOB, b.TOTAL_JOB
FROM employee_table a 
INNER JOIN
(select EMPID, NAME, sum(SALARY) as TOTAL_JOB
FROM employee_table
GROUP BY EMPID, NAME) b
on a.EMPID = b.EMPID
and a.NAME = b.NAME

善练

## Using the window function 
select EMPID, NAME, JOB, SALARY, 
**sum(SALARY) over() as TOTAL** FROM
employee_table

4.没有过滤所需的列

在处理具有数百万行的大型数据集时,数据集中的列数超过所需的数量可能会导致运行时间增加。因此,建议在读取数据集时只选择所需的列。

不好的做法

### Selecting all the columns #######
select a.*, b.* 
from 
member_data as a
join 
claims_data as b
on a.member_id = b.member_id

好的做法

### Selecting the required columns 
select a.member_id, a.age,
a.address, b.claim_id
from 
member_data as a
join 
claims_data as b
on a.member_id = b.member_id

5.每次查询后不进行质量检查

质量检查对于及时发现错误并确保我们交付正确的输出非常重要。很多时候,我们跳过这一步,在分析的后期发现最终结果不正确,因此我们必须进行大量的回溯来找到错误的根源,然后重新运行我们的查询。这导致分析的周转时间急剧增加。

为了避免上述问题,我们可以按照以下简单步骤对数据集执行质量检查:

  1. 统计一个查询的输入行/列输出行/列的数量,并确保得到预期的行/列数量。
  2. 检查汇总统计数据(独特值、百分位数等。)在被操纵的柱子上。这将确保您在列中获得预期的值。
  3. 检查数据集的前几行。这就像检查行的样本来推断数据集的正确性。

在注释中分享您在处理数据时执行的质量检查步骤。

摘要

我们研究了一些常见错误,这些错误通过增加分析的周转时间降低了数据科学家的工作效率。

我们可以通过了解我们的数据(数据级别)、只处理所需的行和列的子集、不使用额外的连接以及对我们的查询执行质量检查来克服这些错误。

谢谢你

我希望这个故事对你有用。你可以在收件箱里看到我所有的帖子。 在这里做那个

如果你自己喜欢体验媒介,可以考虑通过 注册会员 来支持我和其他几千名作家。它每个月只需要 5 美元,它极大地支持了我们,作家,你可以在媒体上看到所有精彩的故事。

你可能喜欢的故事!

使用套索和脊回归时避免这个陷阱

原文:https://towardsdatascience.com/avoid-this-pitfall-when-using-lasso-and-ridge-regression-f4f4948bfe70

您的监管处罚可能针对错误的变量

马库斯·斯皮斯克在 Unsplash 上拍摄的照片

在线性回归中,套索和岭正则化通常用于克服过度拟合并生成更健壮的模型。然而,当应用于不正确缩放的变量时,结果可能是灾难性的。

基本线性模型

假设我们有一个非常简单的线性模型,我们根据婚姻状况 x_1 ∈ {0,1} (1 表示已婚)和年薪x_2 ∈ R^+(实数非负数)来预测预期寿命 y。该模型如下所示:

y=β_0+β_1x_1+β_2x_2+ϵ

如果不熟悉术语:y为结果/自变量,β_0为常数,*β_i x_i* 代表加权解释/因变量,ϵ为误差项/随机噪声。

我们如何表达工资x_2?如果我们愿意,我们可以用美元(\(),数千美元(\)k),甚至美分($c)来表示。这里没有固有的对错。

虽然因变量的单位是用户确定的,但它对结果并不重要。如果我们决定将x_2\(改为\)k,我们只需将β_2 乘以 1000 以保持相同的结果y。类似地,如果我们使用美分,我们将β_2除以 100 以保留结果。

目前为止路上没有颠簸,但让我们继续前进。

引入套索和脊

线性回归有许多问题,例如过度拟合。过度拟合意味着模型在训练集上表现良好,但在样本外数据上表现不佳。过度拟合的模型倾向于使变量适应噪声,而不是识别真实的数据模式。

更准确地说,我们处理一个偏差-方差权衡,高偏差意味着我们没有捕捉到相关的模式,高方差意味着我们适合不存在的模式。所谓的规则化技术有助于平衡偏差和方差,套索和脊调节是最常用的技术。

有关套索和脊正规化的更深入讨论,请查看以下文章:

来对抗过度拟合。LASSO 将以下惩罚(用红色标记)添加到基本回归程序中:

套索正则化对绝对β值施加惩罚,导致许多权重被设置为 0。

由于绝对值β被罚,LASSO 倾向于将许多权重设置为 0 。这个过程剔除了不太相关的变量,只保留了最显著的变量。

岭正则化对β应用平方惩罚:

岭正则化对平方的β值进行惩罚,从而产生相对较小(但非零)的权重。

由于平方 a β<1会降低其值(即 0.0⁵ =0.0023),岭回归倾向于在β值中更均匀地分配权重,而不是将它们完全设置为 0。这将导致更可靠的预测。

问题

LASSO 和 ridge 看起来是明智的技术,但它们只考虑了β的值,而忽略了相应的变量x。如果我们有以美分为单位的工资,LASSO 可能会认为相应的贝塔系数很小,无足轻重,而以美元为单位的工资会产生一个大 100,000 倍的β!显然,选择的单位对行为有巨大的影响。在一种情况下,变量似乎高度相关,在另一种情况下,它似乎可以忽略不计,尽管β_i⋅x_i在两种情况下产生相同的结果。

当应用套索或山脊时,我们惩罚大的β值。由于数值变量的单位通常是任意的,因此正则化的影响可能很大。因此,如果没有适当的变换,套索和山脊就不应该被应用。

解决方案

那么,发现问题后,我们能做些什么来解决它呢?通常情况下,没有放之四海而皆准的解决方案,但是有相当标准的解决方案。

机器学习中的一个常见解决方案是将输入重新调整到[0,1]范围。为此,我们可以简单地将所有数据除以数据集中的最大值。如果数据分布合理,这种方法会非常有效。

然而,假设数据集中的一个幸运儿每年赚 2000 万美元。作为最高值,该条目将被设置为等于 1($ 2000 万/$ 2000 万)。对于其他人,我们可能得到非常低的x值,例如,60$k/$20m=0.003。一个孤立点就能完全破坏这种规模。

在处理这种分布时,通常会执行对数转换。在这种情况下,我们将得到 log(20m)=7.30103 和 log(60k)=4.30103。仍然有很大的差别,但远不如以前那么大。变量现在将分别缩放到 1 和 0.59,与β相乘具有更全面的影响。

可以说,最合理的解决方案是转换变量,使所有x_i 的期望值等于 1(或其他常数)。请注意,这也意味着我们将重新调整虚拟变量(其平均值为0 ≤ E(x_i) ≤ 1)。如有必要,可以将围绕相同平均值的中心值与对数变换相结合。

一旦每个变量都有相同的均值,我们就有了直接可比的β值。经过这种转换后,LASSO 和 Ridge 将针对正确的变量,不再受到美分和美元的任意设置的阻碍。

外卖

  • 在回归模型中,变量单位决定了相应β值的大小。为了保持因变量x和自变量y之间的关系不变,β的值随着x单位的增大而减小,反之亦然。
  • 在线性回归中,选择的变量单位通常影响有限,因为β的大小抵消了选择的单位。术语β⋅ x的结果保持不变,对输出y的贡献相等。
  • 线性回归模型往往容易过拟合。正则化技术如 LASSO 和 Ridge 引入了减轻这个问题的惩罚。
  • 由于套索和脊惩罚β值,变量x的选择单位高度相关。大x收益小β收益小,反之亦然,因此单位直接影响惩罚机制。影响可能相当大。
  • 最合适的解决方案是将所有的x变量换算成相同的预期平均值(如果在对数变换后需要的话),这样所有的β都是相同的量级,可以直接比较。在这种情况下,套索和山脊惩罚适当。

对更高级的回归技术感兴趣?你可能也会喜欢这篇关于多项式回归的文章:

避免注释项目中的顶级陷阱

原文:https://towardsdatascience.com/avoiding-top-pitfalls-in-annotation-projects-a3165c5e278f

注释是困难的,并且经常导致整个 ML 项目的失败。

Imagenet 数据集上建模错误的著名例子:拉布拉多还是炸鸡?从左上顺时针依次为:科里·兰克福德Unsplash 上的照片、沙尔达尔·塔里库尔·伊斯拉姆Unsplash 上的照片、阿里翁·雷冯普特拉Unsplash 上的照片、沙尔达尔·塔里库尔·伊斯拉姆Unsplash 上的照片。

大多数机器学习项目都需要在某个时间点进行标注,无论是为了生成更多的训练数据,还是为了监控模型性能恶化的新测试集。在新的 ML 项目中,甚至可能没有标签模式(也称为标签分类法或本体论)。注释是大多数项目成功的关键步骤。如果你做错了,这将影响你所有的下游任务,并最终导致整个项目的失败。

但是为什么它如此重要呢?

  • 获得正确的标签模式会对业务底线产生直接影响。想想那些将产品分成不同类别的电子商务网站。如果这些类别中有一个定义不当或含糊不清,它将对流量和搜索引擎优化产生直接影响,这意味着你可能会在不知不觉中减少你的某个产品领域的流量,因为你没有得到正确的模式。
  • 如果你的公司或产品提供以人工智能为核心的服务,一个糟糕的注释模式最终会影响你预测的质量,增加客户流失。
  • 更糟糕的是,标签不当的数据集最终会导致令人不快、危险甚至不道德的错误。特别是在医疗保健等领域,确保敏感类别在数据中得到充分体现非常重要。

第一个陷阱:你假设你的标签模式不会改变。

如果一个项目是新的,并且您第一次考虑注释模式,一个常见的错误是在早期修复模式,并将其视为新的模式。即使在成熟的 ML 项目中,标签模式随着时间的推移而演变也是很常见的,例如,新产品类别总是出现,或者新药被发布。注释既昂贵又耗时,因此模式中的任何变化都可能导致大量工作的浪费。

如何避免这种情况:

  • 领域专家的多次初始迭代

在新的 ML 项目中,与没有参与模式设计但是是你试图解决的问题的领域专家的人进行第一轮注释。然后再做几轮,直到模式变得稳定。您将看到,每一轮都会发现您的模式的新问题,要么是需要重命名的不明确的类别,要么是可能需要划分为不同子类别的巨大类别。在这一阶段,与能够从经验中思考潜在问题的领域专家密切合作非常重要。

  • 程序化标签

马丁·亚当斯Unsplash 上的照片

使用编程标记也是一种强大的技术,可以帮助您避免浪费工作。您可以使用编程标签,使用单词列表或常见模式来粗略定义您的类别(例如,您的电子商务网站中“”类别的鞋类列表)。这可以帮助您对所有标签类别的示例进行注释,并评估每个类别的大小。它还有一个额外的优点,如果以后您决定将模式分成“夏装鞋和“冬装鞋”,那么很容易回到您定义的模式并对它们进行调整。

第二个陷阱:您可能会通过指令或类名来偏向结果。

如果您正在使用没有参与标签模式设计的外部注释器,您将需要编写一些关于如何标记数据的说明,甚至可能提供模式中每个类别的定义和示例。这通常是注释项目中最难的部分,也是需要最多迭代才能得到正确结果的部分。

使用错误的说明,你可能会无意中给用户一些提示,让他们更喜欢某个类别。如果你为一个在数据中从未出现过的类别提供例子,用户可能不太倾向于选择那个类别,而不是一个在相同领域有例子的类别,因此看起来更熟悉。这是引导用户选择一个答案的一种方式,也是注释项目中偏见的一个主要来源。另一种偏向结果的方法是在界面中显示一些标签提示或建议。

类名也可能引入一些偏见。例如,如果你有一个包含“others”或“accessories”的类名,它可能会让用户认为这个类别比另一个更有针对性的类别更大。类似地,一个“杂七杂八”类型的类别也是一个常见的陷阱,用户可能会在不确定的时候选择它。

这些问题通常只有在几轮注释之后才会变得明显,一些症状可能是:类别比预期的大或小,或者只包含看起来像说明中提供的示例或提示的示例。

如何避免这种情况:

  • 使用注释器的多次早期迭代

现在,您想用最终的注释者运行几个更大的注释测试批次,最终的注释者将执行大部分的注释工作,他们可能不同于您的领域专家。在这些最初的迭代中,强烈建议与这些注释器密切合作,甚至可能在最初与它们一起工作几个例子。

  • 让注释者更容易给出反馈

照片由迈尔斯伯克Unsplash 拍摄

您的接口需要为注释者提供一种提问和反馈的方式。由于您现在正在进行大规模的注释,您将会看到以前与领域专家一起测试时没有看到的新问题。另一个好主意是在注释者不确定答案时为他们添加一个选项。

第三个陷阱:你的问题空间不平衡,有些班级代表性不足。

类别不平衡将影响大多数项目,因为现实世界中的几乎所有过程都遵循幂律分布。对数据进行注释后,您的目标是获得代表问题空间的数据集,但它还需要提供较小少数类别的公平表示,以避免有害的偏见。找到最佳点也是注释数据的最具挑战性的问题之一。

电商产品品类阶层失衡的例子。图片作者。

如何避免这种情况:

  • 标注随机样本和分层样本

鉴于您需要了解数据中的真实分布,建议您创建一个随机样本来进行注释。这将提供对标签分布的估计,并用于导出全局度量,如所有数据的微精度或召回率。

类别不平衡:注释时最大的挑战之一。照片由威尔·迈尔斯Unsplash 上拍摄

但是,如果存在代表性不足的类别,也建议您创建一个不同的数据样本进行注释,该样本将包含比真实世界中看到的数字更多的少数类别的示例。例如,在医疗保健方面,你可能希望确保你对罕见但严重的疾病有良好的覆盖,而不是更常见的良性疾病,因为这些类别中的错误可能更严重。这也是您可以考虑数据的伦理含义,并可能考虑对包含受保护属性的一些示例进行过采样的策略的时候。

  • 程序化标签

如上所述,程序化标记是一种很好的技术,可以确保你在所有类别中进行标注,你可以用它在少数类别中进行粗略的分层抽样。例如,您可以创建最常与敏感类别相关联的单词列表,以确保将它们包含在注释集中。

第四个陷阱:你忽略或者没有量化歧义。

模棱两可无处不在,因为现实世界也大多模棱两可。在注释的情况下,您可能是前面提到的模糊性的来源,因为您提供了错误的指令或者选择了不明确的类名,或者您的数据本质上是不明确的,因为类别有一定程度的重叠。并不是所有不明确的情况都一定是不好的,在许多情况下,对一个标签或另一个标签进行分类并不被认为是一个严重的错误,也不会影响最终产品的性能。因此,记住最终产品是很重要的,并且在做这些决定时,一定要让领域专家参与进来。

如何避免这种情况:

  • 调整模式或指令

有时你需要做的就是把一个类别分成几个类别或者修改你的指令。如果您(模式设计者)是不确定性的来源,这种方法通常会奏效。然而,情况并不总是这样,您可以很容易地改变模式,直到您的改变产生最小的影响。确保你总是理解错误的重要性,例如,在医疗保健中,将严重疾病与其他疾病混淆会导致致命的错误。

两张脸还是一个花瓶?图片由 Brocken Inaglory 通过 Wikimedia Commons 提供。链接

  • 接受这一点可能不会完全消失,但你可以量化它

一些歧义将是数据空间的一部分,并且不能通过改变注释模式来解决。在这种情况下,看到同一个例子的注释者可能不会同意最终的标签,这意味着没有单一的基本事实(在这里它开始变得哲学化)。作为注释负责人,你至少可以确保你完全了解这些模糊之处,这样你就可以通知业务的其他部分,他们可能想利用这一点来改变产品,例如,通过添加免责声明或其他类别的链接,以便最终用户可以形成一个完整的画面。

通过对来自不明确类别的示例使用多个注释器,您甚至可以用一个数字来量化不明确的程度,例如“被某人归类为的 30%的示例也被其他人归类为鞋配件”。机器学习模型也可以帮助您识别这些歧义,但是最终用于量化这些错误的级别和严重性的任何值都必须来自人类注释者。

最后,您还可以指定一名领域专家作为这些硬示例的仲裁者,并作为最终的决策者,以便您的最终标签是一致的。

第五个陷阱:你没有为你的 ML 模型获得足够的数据。

这可能是开始新项目的数据科学家最常被问到的最难的问题:您需要多少数据?如果不先进行一些数据分析,很难(如果不是不可能的话)做出估计。注释可能非常昂贵,因此获得正确的数字可能意味着为您的公司节省数千美元。

  • 保持紧密的反馈回路

理想情况下,注释应该在多个批次中增量完成,直到您认为现在已经获得了足够的数据,但是您如何知道这个时间已经到来呢?尽早知道建模误差的主要来源是很重要的。这里的主要目标是快速识别和意识到 ML 模型最困难的类别。您的第一批注释应该生成一个测试数据集,您将能够在其中为您的业务计算所有重要的指标。每当您做一批新的注释时,您可以运行一个基线预测模型(不一定是您的最终模型)来获得一些基线度量,更重要的是,执行一些错误分析来识别您的 ML 模型的“更难”的例子,并理解错误的严重性。可能更强大的模型可以解决这些更困难的情况,但在这些类别中,数据越多,影响越大。

  • 利用主动学习

主动学习循环。图片作者。

主动学习是一种在注释期间使用 ML 模型来选择用户接下来应该注释什么示例的技术。一种常见的抽样策略是选择模型最不确定的例子。这种类型的技术非常有助于确保您明智地分配您的注释预算,以便您注释最重要的示例,直到您获得一定水平的基线性能。

  • 程序化标签...又来了!

另一个值得探索的领域是使用嘈杂的标签。一些模型能够从大量数据中正确地学习,即使标签并不都是正确的(大多数知名的开源数据集都有一定程度的错误!).这是一个被称为弱监管的活跃研究领域。只要您的测试数据集已经由人工注释者尽可能准确地进行了注释,您就可以比较在较小的人工注释数据集上训练的模型与在带有噪声标签的大得多的数据集上训练的模型的性能。获得嘈杂标签的一种方式是通过程序化标签,在这里你可以定义规则(例如“将标题中有凉鞋的所有产品标记为属于“”类别)。如果这些规则具有很高的精确度,它们可以用于自动注释您的数据并创建大型训练数据集。值得一试!

概括一下

  1. 做一些数据探索,使用编程标记来创建覆盖所有类的数据样本进行注释。
  2. 如果这是一个可能需要新的或修改过的标签模式的项目,请与领域专家进行一些小的注释,直到您对该模式满意为止。
  3. 如果您正在使用外部注释器,请使用它们进行一些中等规模的注释,并迭代这些指令。在这个阶段,为每个示例使用多个注释器来量化标签歧义可能是一个好主意。根据问题的类型和注释设置,您可能需要始终保持多个注释器。
  4. 创建你的第一个测试集并放在一边。理想情况下,一个是随机样本,另一个使用过采样来平衡所有类别,并很好地覆盖敏感和少数类别。
  5. 做大量的注释来创建第一个训练数据集。
  6. 创建基线模型,获取基线测试指标,并确定最常见的建模错误类型。评估错误的严重性。在这个阶段,您可能需要领域专家的参与,并告知业务的其他部分 ML 模型可能会犯的潜在错误。
  7. 选择对学习影响最大的新样本进行注释(例如,使用主动学习或编程标记)。
  8. 重复前面两个步骤,直到你有足够的例子来减少敏感的错误,并涵盖模糊和难以分类的例子。

想通过应用本文中的技术来做智能标签吗?或者您正在开始一个新的注释项目,需要一些建议?请联系我们,我们很想知道:【https://dataqa.ai/】T2。作者是 DataQA 的创始人,这是一个为 NLP 任务高效标注和训练 ML 模型的平台。

更多关于标注为 ML 的内容,请关注我们的TwitterLinkedIn

AWS 雅典娜+ DBT 集成

原文:https://towardsdatascience.com/aws-athena-dbt-integration-4e1dce0d97fc

在 15 分钟或更短时间内

艾蒂安·吉拉尔代在 Unsplash 上拍摄的照片

语境

AWS Athena 是无服务器的,用于对 AWS S3 上的数据进行专门的 SQL 查询。然而,维护数据沿袭和依赖是乏味且容易出错的(尽管在数据仓库中没有区别)。

DBT(数据构建工具)最近变得非常流行,因为它可以自动绘制数据谱系/生成数据管道的文档,更不用说它的其他功能,如快照、Jinja &宏支持。

有很多关于将 DBT 与数据仓库(Snowflake、Redshift、Databrick 等)集成的参考资料,但没有 Athena(是的,它不是数据仓库)。然而,有许多使用案例和团队使用 Athena 来生成 BI 报告等:

  • 该报告有 20 多个从各种 AWS DataCatalog 数据库和表中生成的视图。
  • 数据沿袭对于理解业务逻辑非常重要,并且经常变化。
  • Athena 的计算性能令人满意。
  • 缺乏实施/维护数据仓库的资源/预算。

我们有没有可能将 DBT 与雅典娜集成,以提供一个负担得起的解决方案?

解决方案

感谢 dbt-athena 社区构建了一个 dbt 雅典娜适配器,我用它构建了一个演示来验证集成是如何工作的。所有 AWS 基础设施资源由 Terraform 管理,并在我的 GitHub repo 中提供,因此您可以在 15 分钟(甚至更短)内构建相同的 E2E 演示,用于 POC(概念验证)、内部演示或自学目的。

原始数据

女装电商服装点评点评数据(CC0:公有领域许可)使用,数据统计汇总详情可在 Kaggle 网站查询。

作者图片

简而言之,这些数据包含客户对产品的评论和相应的产品评级。一个典型的用例是在适当的特征工程(数据转换)之后使用这些数据来做情感分析。

数据流

在这个演示中,原始数据存储在 S3,使用 Glue 服务提取其模式,供雅典娜查询,然后由 DBT 转换。

作者图片

  1. 手动触发 Glue crawler 来推断数据架构并更新 DataCatalog 以粘合 DataCatalog。
  2. 粘附数据目录创建对数据(S3 到表)映射的引用,不移动任何数据。
  3. 使用 SQL 在 S3 查询数据,在粘合数据目录中查找架构,没有要加载的数据。
  4. DBT 将软件工程方法应用于数据转换(SQL)。

预计读者将对 TerraformAWSDBT 有一些基本的了解,否则这也是一个很好的迷你项目,让读者了解这些服务。

履行

地形部分

  • 安装地形
  • git 克隆https://github.com/grhaonan/Athena-dbt-demo-tf-local
  • 确保设置了正确的 AWS 用户和权限。为了简单起见,我的 AWS 用户只附带了一个 AdministratorAccess 策略。
  • Terraform main.tf 中的配置文件名应该与用户配置文件相匹配,用户配置文件用于调用 AWS 服务,在“~”中定义。/aws/credentials”。

作者图片

作者图片

注意事项:

  • 该区域默认设置为“ap-southeast-2 ”,可以在 variables.tf 中随意更新
  • 一些 AWS 资源(s3 bucket 等)需要全局唯一,在 Terraform 中使用随机 id 生成器来确保不同用户之间的唯一性。你会在这篇文章中看到几个{16 位 id}约定,指的是一个随机 id。

运行“terraform init”命令启动项目。

作者图片

运行“terraform apply”命令以应用所有 AWS 资源

作者图片

在 AWS web 控制台上手动触发/运行爬虫作业(根据本演示命名为“athena_dbt_demo_crawler ”,在 terraform 中配置)。

作者图片

完成后,您将在 Athena 中的数据库 raw_data_{16 random id}下找到表格“women _ ways _ reviews _ raw _ data”( : 选择 athena-dbt-demo-workgroup,而不是主)。现在,这些原始数据已经可以进行查询了。

作者图片

您还会在 S3 的以下存储桶下看到源原始数据:Athena-dbt-demo-{ 16 random id }/raw _ data/women _ clothing _ ecommerce _ reviews . CSV。此文件会在 Terraform 应用阶段自动上传到 S3。

DBT 部分

作者图片

  • 相反,我会建议通过一个干净的虚拟环境(通过康达等)安装它。注意:requirements . txt 在“Athena-dbt-demo-dbt-demo”文件夹下

作者图片

完成后,检查版本,现在我们可以开始了!

作者图片

如果您的 DBT 个人资料不存在,请创建它(~/)。或者将此项目添加到您现有的 DBT 个人资料中

作者图片

:

您应该只更新上面文件中的以下三个值以匹配您的情况,但保持其他值(根据匹配的地形配置)不变。

  • aws_profile_name:与 terraform main.tf 中配置的 aws 概要文件名和本地 AWS 概要文件名相同。
  • s3_staging_dir:这是为存储 Athena 查询结果而创建的 s3 存储桶,在您的 s3 存储桶中命名为“Athena-dbt-demo-Athena-query-result-bucket-{ 16 random id }”。
  • 架构:这是配置为导出 DBT 模型结果的数据库,它应该与 athena_dbt_models_{16 位 id}匹配

最后,更新 models/VW _ women _ ways _ reviews _ rename _ columns . SQL 中引用的数据库,以匹配创建的 raw_data_{16 位数 id}。

...
FROM "RAW_DATA_9f40f41fee84f437"."WOMEN_CLOTHES_REVIEWS_RAW_DATA"

关于数据转换

在 DBT,我们在原始数据上实现了三个转换(/模型)。

  • (视图)VW _ women _ ways _ reviews _ rename _ columns 进行第一次转换:选择需要的列并重命名它们

作者图片

  • (查看)VW _ women _ ways _ reviews _ perspectives 将根据预定义的 start_rating 列规则创建情感评分。

作者图片

  • (查看)VW _ women _ ways _ reviews _ training _ data 会进行一些最终的过滤,作为转换后的结果。

作者图片

DBT 跑步

最后,运行命令“dbt run”将编译上面定义的所有三个模型,并将结果放在 AwsDataCatalog 数据库“athena_dbt_models_{16 random id}”下,您也可以在 athena 中找到它。

作者图片

DBT 的一个关键特性是提供数据血统和文档。

  • 运行命令“dbt 文档生成”将生成文档
  • 然后通过命令“dbt docs serve-port 8001”(它是 port 前面的两个连字符)设置一个本地 web 服务器来可视化文档。

数据沿袭:

  • women _ clothing _ reviews _ training _ data 依赖于 VW _ women _ clothing _ reviews _ opinions,后者进一步基于 VW _ women _ clothing _ reviews _ rename _ columns。

作者图片

数据文档:

作者图片

摘要

感谢您的关注,希望您喜欢。尽管 Athena 通常用于特定的查询目的,但它仍然可以以较低的成本受益于 DBT 集成。

让我们快速回顾一下这篇文章:

  • 产品评论数据在 S3 加载,并通过 AWS Glue 服务“连接”到 SQL 查询服务 Athena。
  • 本演示中的所有 AWS 资源都由 Terraform (IaC)管理,因此用户可以在几秒钟内部署/销毁它们。
  • dbt-athena 是一个社区维护的 dbt 适配器,用于集成 DBT 和 athena。
  • 基于 Athena 的 BI 报告将从 DBT 的数据传承和文档特性中受益匪浅。

[1] 女装电商服装点评https://www . ka ggle . com/datasets/nica potato/Women-ecommerce-Clothing-Reviews?资源=下载

[2] CC0:公共领域许可https://creativecommons.org/publicdomain/zero/1.0/

AWS 云到边缘人工智能工作流

原文:https://towardsdatascience.com/aws-cloud-to-edge-ai-workflow-1861722cc4f6

AWS 云培训/边缘硬件测试/免费和零本地设置

在亚马逊 AWS Sagemaker 上训练 TensorFlow 模型,在任何英特尔处理器上测试延迟,并免费使用两行 python 代码提升人工智能推理性能

根据 Ojas Sawant 的许可,通过 Storyblocks 提供图像

典型的人工智能工作流程包括定义具体的用例、准备数据集、训练模型、将推理组件集成到应用程序中,以及选择合适的硬件部署到生产中。

虽然有大量的云服务可以简化培训,但在进行任何实际投资之前,在确定合适的生产部署硬件以及神经网络模型以产生符合预算和用例的最佳应用性能方面存在差距

在本文中,我们将带着一些 python 代码和可视化 示例走过云培训到边缘推理应用程序开发阶段,您可以跟随并适应您的用例。

我们将经历以下端到端的工作流程:

  1. 训练一个模型:利用 AWS Sagemaker (自由层)训练一个 TensorFlow 模型——以从 Kaggle 获得的罗马天气图像分类数据集为例。
  2. 导入模型&测试数据:从 S3 桶中导入训练好的模型和测试数据,以预览和使用简单的 python 程序,该程序在英特尔开发人员云上为 Edge 分析图像(免费)。
  3. 基准&优化推理:通过 OpenVINO 与 TensorFlow (python)的集成提升推理性能,并在多个硬件上与股票 TensorFlow 进行性能比较。

…全部在我们的浏览器中完成,无需任何本地设置。在这一过程中,我们将简要讨论指针,以使相同的流适用于其他用例,例如其他张量流实例分割或对象检测模型。

1.用 AWS Sagemaker 训练模型

对于图像分类任务,SageMaker 要求我们的训练数据采用以下结构:

{父目录}/{类名目录}/{图片}

我们将使用一个小的(250 个微小的图像— 2MB)数据集来分类—罗马的多云、 下雨、下雪、晴朗、多雾天气。Kaggle 上的数据浏览器选项是在下载前预览数据集内容的好方法。

数据集格式因任务而异,例如,对象检测需要 JSON 注释文件。使用每个任务的默认数据集作为示例来准备数据集,或者使用 SageMaker Studio 中模型的 train 部分中的了解更多链接。

在本地下载并提取数据集。然后,我们将移动训练目录中的类,并在测试目录中剪切-粘贴-重命名每个类的 1 个图像,以便稍后在我们训练好的模型上快速测试推理。

从每个课程中下载并提取 1 张图片进行测试|图片由作者提供

导航到您的 S3 存储桶并上传罗马天气目录,以确保文件夹结构被保留并可用于图像分类训练。最后,在下一步配置培训时,导航并选择复制 S3 URI 进入培训目录。

如果您没有 SageMaker 帐户,请在此注册一个自由层帐户并创建一个 s3 bucket 来使用。

导航并选择— 培训时复制 S3·URI以供参考|作者图片

启动我们的 SageMaker Studio 实例,并导航到 JumpStart 菜单选择一个可微调 TensorFlow 图像分类模型。

使用 Train 部分从 bucket 和 output 目录指向我们的父训练数据集目录。您还可以进一步配置超参数。对于自由层,选择部署配置中的 ml.m5.xlarge 实例进行训练。

选择型号,配置并开始培训|按作者分类的图像

下一步,确保您的 AWS IAM 用户配置了编程访问和 AmazonS3FullAccess 策略。

我们将为下一步输入 S3 存储桶名称访问密钥 ID秘密访问密钥。更多信息,请参考编程访问&密钥页面。

2.在英特尔 开发者云上导入 S3 数据

导航至概述>JupyterLab入门,启动面向 Edge — JupyterLab 实例的英特尔开发人员云。

如果您还没有面向 Edge 帐户的英特尔开发人员云,请在此免费注册

启动 JupyterLab 实例|作者图片

使用左侧菜单打开云存储连接器选项,输入您的 S3 桶名称访问密钥 ID秘密访问密钥查看您的 S3 桶内容。

登录并导入模型,将测试图像导入面向 Edge 的英特尔开发人员云— JupyterLab |作者提供的图像

多选要导入的文件,例如{ trained-model-output-directory } > { output } > model.tar.gz 和来自您的已训练模型的每个类别的测试图像。

3.基准测试和优化推理:

应用程序集成步骤可能涉及编写代码来加载模型、加载和准备输入层的测试图像,并在以后从输出中提取结果。我们将做到这一点——在支持 TensorFlow 的预装内核中的笔记本电脑单元中进行原型制作,并验证代码是否可以在开发机器上运行。

此外,我们将测量并打印推理时间,不包括任何图像预处理或后处理时间,以重点关注硬件和模型推理性能的关系。

git 克隆https://gist . github . com/945165 defe fa 93360 db 1172472 c 55d 93 . git测试

您可以克隆本文中使用的笔记本来测试任何图像分类 Sagemaker TensorFlow Jumpstart 模型。对于其他任务,相应地为结果输出修改它,例如用于检测的边界框或用于分割的遮罩。

在英特尔开发人员云开发机器上提取并快速测试代码|作者图片

然后,我们将添加一个 shell 脚本,激活预安装的虚拟环境并调用我们的 python 程序,但这次我们将在面向 Edge 的英特尔开发人员云上托管的任何硬件上提交作业。从英特尔酷睿(i3、i5、i7、i9)到至强处理器,跨越多代处理器。使用笔记本中的单元格来标识提交图像分类作业时要使用的平台 id。

编写作业文件和可用边缘硬件的预览列表|按作者排列的图像

我们的 python 推理代码有额外的代码行,使同一个定制训练的 Sagemaker Jumpstart TensorFlow 模型能够以 OpenVINO 集成作为后端运行加速推理。

import openvino_tensorflow as ovtf
ovtf.enable()//Optional: default is CPU or GPU, VPU if the hardware supports it
//one line to run the same model on accelerator hardware.
ovtf.set_backend('<backend_name>')

最后,将我们的作业提交到一个边缘节点,首先使用股票 TensorFlow 运行,然后使用 OpenVINO backend for TensorFlow 运行另一个作业,以比较推理性能和我们的测试程序。

将工作负载提交给边缘硬件进行评估|图片由作者提供

外卖食品

借助上述工作流示例,我们可以继续在 SageMaker Studio 中的其他图像分类 JumpStart 模型(例如 MobileNetV2、EfficientNet…)上试验超参数,以实现理想的准确性指标,快速导入到面向边缘的英特尔开发人员云,并在裸机工作负载(跨各代英特尔酷睿 i3、i5、i7 或至强处理器)上评估其他边缘节点上的吞吐量/延迟。

OpenVINO 与 TensorFlow 集成|图片由作者提供

此外,如预装 OpenVINO 与 TensorFlow Jupyter 内核集成的笔记本所示,我们可以在不改变原始模型的情况下提升推理性能。JupyterLab 文件系统中已提交作业的日志输出表明了模型拓扑中运行 OpenVINO 后端的节点数量,这有助于提高推理性能。

上述流程是剩余应用程序集成步骤的基线。

git 克隆https://gist . github . com/945165 defe fa 93360 db 1172472 c 55d 93 . git测试

有用链接:

AWS 数据科学基础:存储

原文:https://towardsdatascience.com/aws-essentials-for-data-science-storage-5755afc3cb4a

了解和部署 S3、RDS 和 DynamoDB 服务

科技日报在 Unsplash 上拍摄的

你会把你的音乐、视频和个人文件存放在满是硬盘的车库里吗?我敢打赌……不会。除非你在过去的 15 年里避开了 iCloudDropboxGoogle Drive——如果你避开了,那就恭喜你!那么你很可能使用云存储。如果你丢失了手机,你可以找回你的短信;可以用链接分享文件,而不是海量的邮件附件;您可以按照片中的人来整理和搜索照片。

但是这些好处也延伸到了职业领域。如果你开了一家分享数据的公司,比如说,以低廉的月租费分享数以千计的 4K 电影和电视剧(😛)—您会希望将这些数据存储在云服务器上。当你关闭笔记本电脑时,云服务器不会关闭,你也不必担心邪恶的用户获取你的私人数据。

那么如何才能设置云存储呢?哪种存储类型最适合我们的数据?我们如何从代码中直接与云存储交互,而不需要在 UI 中点击?

本帖将回答这些问题。在展示如何在 Amazon Web Services (AWS) 中有效地存储blob、表格数据和 JSONs 之前,我们将设置我们的软件环境。(关于云行业的一般介绍,请查看上一篇文章。)请继续关注关于云计算的另一个主要产品 compute 的后续文章。

背景

为什么选择云存储?

当你独自做一个小项目时,你可能不会过多考虑数据存储。也许你在 Jupyter 笔记本或 R 脚本的同一个文件夹中有几个 CSV。希望所有东西都备份到硬盘上了。

但是,当您想在项目中添加人员时,会发生什么情况呢?轮流使用笔记本电脑没有意义。您可以将数据复制到他们的笔记本电脑上,但是如果数据太多,队友的电脑装不下怎么办?一旦这项工作开始,同步数据集之间的变化将是一个令人头痛的问题。马上交出所有数据也是一种很大的信任——如果这个新人离开了,带走了所有的东西,与竞争对手或恶意行为者分享,怎么办?

作者图片

云存储旨在解决这些问题。和 Dropbox 或 Google Drive 一样,你可以简单地通过一个链接发送数据:“点击这里访问数据库。”通过微调访问规则,这些数据可以变成只读的——如果你的队友是竞争对手的间谍,你可以在他们下次试图获取数据时立即将这些 URL 变成错误消息。[1]

我们可以使用SDK(软件开发工具包)直接从我们的代码中访问数据,这对于将任何应用扩展到极少数用户之外是至关重要的。只要您的互联网连接可靠,您就应该能够随时访问数据,例如,AWS 保证正常运行时间为 99.9%99.99%99.999% ,具体取决于您的应用。[2]

我在储存什么?

因此,我们看到将数据存储在云中是有用的,因此它是安全的,可通过代码访问,并且高度可用。但是“数据”是一个宽泛的术语——是原始视频和文本记录吗?用户档案和活动日志?Python 和 R 脚本?Excel 的颗粒状截图?

我们可以将我们所有的文件放入一个大的 Dropbox 文件夹中,照片与配置文件和 CSV 混合在一起。只要您知道包含所需数据的文件的名称,Dropbox 就会在需要时获取该文件。但是,除非文件严格包含您所请求的数据,否则您需要搜索整个文件以提取相关数据。

这个问题——不知道数据的确切位置——是随着数据量的增长,一个大的 Dropbox 文件夹让我们失望的地方。因为我们经常需要搜索符合某些标准的数据,所以 我们组织数据的方式决定了我们的应用程序是可以支持 100 个用户还是 1 亿个用户。正如我们将会看到的,访问特定类型数据的最佳方式很大程度上取决于它的格式**

这种格式,即结构化半结构化非结构化,是指数据在文件中的组织方式。结构化数据是您可能熟悉的行和列的表格集合:通常,每行是一个样本,每列是该样本的一个特征。关系数据库中的表由结构化数据组成,如果表通过一个很好地划分数据的列进行 索引 ,我们可以快速搜索这些数据。

作者图片

半结构化数据包括 JSONXMLHTML 和大型图表,其中的数据通常不能很好地适应列和行。这种格式非常适合分层数据,其中一个字段可能有子字段,许多子字段包含自己的子字段。层数没有限制,但是需要的结构。例如,一个 HTML 页面可以有许多嵌套在一起的<div>部分,每个部分都有独特的 CSS 格式。**

最后,非结构化数据是原始的、未格式化的,不可能拆分成结构化数据的行和列,甚至是半结构化数据的嵌套字段,没有进一步的处理。不能或者不应该分解的非结构化数据的一个例子是二进制大型对象(BLOBs)。例如,你通常想要一次加载整个图像,所以你不应该在一个文件中存储一半像素,在另一个文件中存储一半像素。类似地,可执行程序(例如,编译后的 C++脚本)是你总是想一次获取的实体。

使用 SDK 时避免被黑客攻击

既然我们对可以存储在云中的数据类型有了概念,我们就可以开始试验针对每种类型优化的 AWS 服务。为了真正展示云的力量,我们将使用 AWS Python SDK 将这些服务集成到我们的代码中。要使用 Python SDK,我们只需安装boto3库。在终端或命令提示符下,我们只需键入以下命令:

*pip install boto3*

但是在我们运行任何脚本之前,我们需要做一件事来避免被黑客删除。在我们的代码中,将我们的 AWS 凭证存储在一个安全的位置是至关重要的。

AWS 服务器每秒接收几十或几百个查询。如果服务器收到从您的 S3 存储桶下载文件的请求,服务器如何知道是阻止还是允许该操作?为了确保这个请求来自你或者代表你的机器我们 用我们的 AWS 访问密钥 ID 和秘密访问密钥签署我们的 API 请求 这些密钥用于加密我们的消息内容并且生成一个哈希来证明 AWS 收到的消息与我们发送的消息相同。

因此本质上,AWS 收到的任何用您的访问密钥签名的请求都将被视为来自您。因此,确保您是唯一执行这些请求的人非常重要!

作者图片

boto3当我们实例化一个客户机对象时,要求我们传递我们的访问密钥 ID 和秘密访问密钥。从技术上讲,我们可以通过将访问键定义为变量,然后像这样传递它们:

但是这是一个巨大的安全漏洞,因为任何阅读这段代码的人都可以冒充你!如果您不小心将这个文件推送到 Git 这样的版本控制系统,删除第 4-5 行并推送到一个新版本是不够的——任何人都可以滚动文件的历史来找到您的密钥。

MacOS 和 Linux 用户可以将这些 秘密 存储在.bash_profile.rc.zshrc文件中,而不是在 Python 中硬编码这些值。(见此处为视窗。)该文件包含文件路径的别名(例如,当您键入python时,终端知道您指的是/opt/homebrew/bin/python),以及数据库密码或其他敏感信息。这个文件位于你的根目录下,是隐藏的——要找到它,你需要键入 + .才能看到它。

在这个文件中,我们可以设置 AWS 访问键。(注意等号两边没有空格。)

一旦我们这样做了,我们就可以通过 Python 的os模块访问我们的变量。通过访问来自os.environ的值,任何阅读代码的人都不会看到它们。[3]

至此,我们已经准备好开始使用 AWS 了。

作者截图

S3:简单的存储服务

S3 或简单存储服务是 Dropbox 或 Google Drive 最接近的类似物。把 S3 想象成你的文件的“包罗万象”。只需创建一个(即不同的目录)并上传 任意任意类型的任意数量的文件——文本、CSV、可执行文件、Python pickle 文件、图像、视频、压缩文件夹等。只需点击几下鼠标,即可定义文件、文件夹、[4]或存储桶级别的访问规则。

这种简单性的缺点是 S3 只包含关于文件的数据,而不是文件里面的内容。所以,如果你忘记了你的脸书密码,并且不能在你的文本文件中搜索短语my Facebook password is,那你就太不幸了。如果我们需要在我们的文件中搜索数据,我们最好将数据存储在数据库中。[5]

但是即使有了数据库,S3 仍然是存储生成这些数据的原始数据的理想选择。S3 可以作为日志、物联网应用的原始传感器数据、用户访谈的文本文件等的备份。一些文件类型,如图像或训练有素的机器学习模型,最好保存在 S3,数据库只需存储对象的路径。

使用 S3

让我们实际创建一个桶。不要担心 AWS 会收取存储数据的费用——我们会保持在自由层的范围内,一旦完成,就会删除所有内容。我们将创建一个 bucket,然后上传和下载文件。我们将使用控制台、AWS CLI 和 Python SDK 来执行这些步骤,但是请注意,我们可以使用任何一种工具来执行所有步骤。

让我们从控制台开始创建一个 bucket。我们首先登录我们的 AWS 账户(最好使用一个 IAM 角色)并导航到 S3。然后,我们只需点击“创建存储桶”按钮:

作者截图

当我们创建一个 bucket 时,我们需要给它一个在所有 AWS buckets 中全局唯一的名称。这里我们创建一个名为matt-sosnas-test-bucket的。

作者截图

我们的 bucket 可以有定制的访问规则,但是现在让我们保持禁用公共访问。一旦我们选择了那个,我们的桶就准备好了。

作者图片

上传文件

现在让我们切换到 AWS CLI。在终端或命令提示符下,我们可以使用以下命令看到我们的新 bucket。(您可能需要按照步骤进行认证,此处为)。

我们现在可以创建一个文件,并将其上传到我们的 bucket。为了简单起见,我们将通过用echo>将一个字符串传送到一个文件中,直接从命令行创建一个文件。然后我们将使用aws s3 cp <source> <destination>上传文件。

我们现在可以用aws s3 ls <bucket_name>查看我们的文件。

如果 S3 文件路径包含一个文件夹,AWS 会自动为我们创建一个文件夹。我们这次创建一个 Python 文件,test.py,并上传到我们 bucket 中的一个python/目录。因为s3://matt-sosnas-test-bucket/python/test.py包含一个python/目录,S3 将为我们创建一个。

现在当我们用aws s3 ls查看内容时,我们看到根目录中test.txt旁边的python/文件夹。如果我们在命令中将/python/添加到我们的 bucket 名称的末尾,我们就可以看到文件夹的内容。

最后,我们可以通过指定--recursive--exclude--include标志来上传多个文件。下面,我们创建两个 CSV,file1.csvfile2.csv,首先创建标题,然后各追加两行。然后,我们使用 AWS CLI 将当前目录(.)中匹配file*模式的所有文件上传到我们的 bucket 中的csv/文件夹。最后,我们列出了csv/文件夹的内容。

下载文件

上传文件很好,但是在某些时候我们会想要下载它们。让我们使用第三个工具 Python SDK boto3来演示下载文件。这一步比一行 AWS CLI 命令更复杂,但是我们将在下面一行一行地进行。

我们先导入boto3io.StringIOospandasboto3包含与 AWS 交互的代码,io是一个用于处理流数据的库,os.environ存储我们的 AWS 凭证,pandas将把我们的 CSV 转换成 dataframe。

在第 7–12 行,我们实例化了一个boto3客户端,它允许我们向 AWS 发出请求。我们执行这样一个请求,从第 15-18 行的matt-sosnas-test-bucket中获取csvs/file1.csv文件。这个对象打包了元数据,所以我们提取第 21 行的字节字符串,在第 22 行将其解码为 CSV 字符串,最后在第 23 行将该字符串解析为 dataframe。

作者截图

RDS:关系数据库服务

把我们所有的数据都扔进一个桶里,即使文件类型是按文件夹排列的,也只能做到这一步。随着数据的增长,我们需要一种更具可扩展性的方法来查找、连接、过滤和计算数据。关系数据库是更好地存储和组织数据的一种方式。(参见这篇文章了解数据库的入门知识。)

我们可以在云中租用一个 EC2 实例(即虚拟服务器),然后自己安装一个 MySQL 或 PostgreSQL 数据库。但这比在我们车库的服务器上托管数据库好不了多少——虽然 AWS 将处理服务器维护,但我们仍将负责扩展、可用性、备份以及软件和操作系统更新。对于稍微增加的成本,我们可以使用类似于 Amazon RDS 的服务,让 AWS 管理除我们实际数据之外的一切。

所以让我们在 RDS 中创建一个数据库。我们将登录 AWS 控制台,导航到 RDS,然后单击Create database。如果您阅读了针对所有人的中间 SQL,那么您可能已经安装了 Postgres 数据库的 GUI。既然我电脑上已经有 pgAdmin 了,那就用 Postgres 吧。🙂

在设置向导中,选择Standard create作为创建方法,选择Postgres作为引擎。

作者截图

确保指定您想要使用空闲层!

作者截图

命名您的数据库标识符并设置一个用户名—postgres对两者都很好——并确保在安全的地方写下您的密码。禁用自动缩放(在“存储”下),并为公共访问选择是。我们的数据库不会真正对世界开放,不要担心——我们仍然需要密码才能访问数据库。(不过,对于专业应用程序,您可能需要配置一个 VPC 。)

作者截图

在“附加配置”下,命名您的初始数据库my_database,然后禁用自动备份、性能洞察和次要版本升级。配置中的其他一切都可以保持不变。

作者截图

当我们点击Create database时,我们被带回 RDS 登录页面,看到我们的数据库正在创建。完成后,您可以单击该实例并转到下一页。在此页面上,单击“安全”下的 VPC 安全组链接。

作者截图

在这里,我们可以向下滚动到Inbound rules选项卡,点击Edit inbound rules,然后点击Add rule。为Type选择“PostgreSQL”,为Source选择“Anywhere-IPv4”。(友情提醒,不要对生产数据库这样做!)您也可以通过指定您的 IP 地址来提高安全性。完成后,点击Save rules

作者截图

现在对出站规则做同样的操作:单击Outbound rules选项卡、Edit outbound rulesAdd ruleType的“PostgreSQL”和Destination的“Anywhere-IPv4”(或您的 IP 地址),然后单击Save rules

我们现在将从 pgAdmin 访问我们的数据库。在 AWS RDS 的 Connectivity & security 选项卡下,复制端点地址。(看起来有点像postgres.abcdef.us-east-1.rds.amazonaws.com。)然后打开 pgAdmin,右键点击 Servers >注册>服务器。将连接命名为类似于aws_rds_postgres的名称,并将端点地址粘贴到主机名/地址字段中。填写您的密码并点击“保存密码”。

如果一切顺利,您应该会看到aws_rds_postgres服务器和my_database数据库。

作者截图

右键点击my_database,然后点击Query Tool,输入以下内容:

由于我们使用免费层,不幸的是我们只能通过 pgAdmin 查询我们的数据库,而不是 AWS 控制台或boto3。(尽管我们可以* 对数据库本身进行修改。)但是为了确保上面的操作有效,请在 pgAdmin 中键入以下内容,以确认我们可以查询我们的数据库。*

作者截图

DynamoDB

让我们讨论最后一种数据库类型:非关系数据库。AWS 为创建和查询 NoSQL 数据库提供了 DynamoDB。

谢天谢地,DynamoDB 比 RDS 更容易设置。我们将从导航到 AWS 控制台内的 DynamoDB 并点击Create table按钮开始。让我们创建一个名为users的表,用id作为数字分区键。然后,点击Customize settings

作者截图

选择DynamoDB Standard作为表类,选择Provisioned作为容量,然后关闭读取和写入的自动扩展,并将配置的容量单元数量减少到各 1 个。

作者截图

让加密归亚马逊 DynamoDB 所有,然后点击Create table

还有…就是这样!现在让我们导航到 Python 来写入我们的表。在 Jupyter 笔记本或 Python 脚本中,运行以下命令:

写入 DynamoDB 的语法相当明确——我们需要指定正在编写的字典的每个元素的数据类型。参见[boto3](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb.html#DynamoDB.Client.put_item) DynamoDB 文档中的一些例子。但总的来说,请注意我们如何能够在favorite_movies下保存电影列表,并为用户 456 编写一组不同的字段。这种灵活性是 NoSQL 数据库的特点。

如果上面的代码运行没有错误,那么我们应该在 DynamoDB 控制台中看到这些记录。点击我们的users表,然后点击Explore table items

作者截图

最后,我们还可以从 Python 中获取对象。

简·kopřiva 在 Unsplash 上拍摄的照片

清理

在这篇文章中,我们建立了一个 S3 桶、关系数据库和 NoSQL 表。尽管我们使用 AWS 的免费层,并且每个数据源仅存储极少量的数据,但我们仍然希望拆除每个数据源,以避免最终被收费。

谢天谢地,删除很简单。在 S3,我们只需点击我们的桶,然后点击Empty按钮。确认我们要删除所有内容。然后再次点击我们的桶,并点击Delete按钮,确认我们希望桶消失。

在 RDS 中,我们只需点击我们的数据库(postgres),然后Actions,然后Delete。确保避免在删除之前拍摄数据库的最终快照。

最后,对于 DynamoDB,我们点击Actions > Delete table,然后确认我们不想要 Cloudwatch 警报。

就是这样!友情提醒,千万不要这样对你公司的生产数据。🤓

照片由亚当·威尔森Unsplash 上拍摄

结论

这篇文章介绍了云存储的好处以及我们可能实际存储的各种数据格式:结构化的数据用于表格数据,半结构化的用于不适合列和行的数据,以及非结构化的用于原始和未格式化的数据。

然后,我们为每一个构建了优化的数据源。我们创建了一个 S3 桶作为日志、CSV、照片和任何我们能想象到的东西的“包罗万象”的来源。然后,我们为结构整齐的表格数据构建了一个 RDS 数据库。最后,我们使用 DynamoDB 编写了具有不同键和数据格式的 Python 字典。

当然,还有很多其他的 AWS 数据存储服务我们没有在这里介绍。 AWS GlueAthena 允许您直接在 S3 桶中的文件上运行 SQL 查询(有一些严重的警告[5])。 AWS Redshift 是一个数据仓库,它让您可以组合来自多个来源(包括 S3、RDS 和 DynamoDB)的数据,从而更容易地运行分析。AWS Cloudwatch 是一个日志监控和警报服务。

凭借您在这篇文章中获得的技能,您应该已经具备了开始构建更大、更复杂的云存储应用程序的基础。在下一篇文章中,我们将通过讨论计算来结束我们的 AWS 系列,其中我们将使用 AWS 服务器来运行数据计算。那里见!

最好,
哑光

脚注

1.为什么选择云存储?

虽然我们可以撤销用户对云数据的访问权限,但当然总是会担心用户制作了本地副本。这个问题没有真正好的答案

一旦那个人离开你的团队,我们不能让下载的数据自毁。对于来自 S3 的文件来说,希望不大,但是至少对于来自数据库的数据来说,下载所有的东西是不切实际或者不可能的。在 Meta 这样的公司,数据访问受到严密监控,从访问包含敏感数据的表格到下载数据的任何时间。

2.为什么选择云存储?

99.999%的正常运行时间是一个很难想象的数字。每年,“五个 9”表示 AWS 保证不超过 5 分 15 秒不可用。

3.使用 SDK 时避免被黑客攻击

我们可以对不太敏感的数据使用类似的过程,比如常量或文件路径。

通过将这些值存储在一个配置文件中,我们可以保持主工作流的整洁:

如果 config.py 存储了我们不想让其他人看到的数据,我们可以将它添加到我们的.gitignore文件中,Git 不会试图对它进行版本控制。下面,Git 不会跟踪名称中带有.ipynb.pycconfig.py的文件。

*.ipynb
.pyc
config.py*

4.S3:简单的存储服务

一个迂腐的注解:S3 的“文件夹”并不真正存在。它们更像是组织数据的人性化方式。

5.S3:简单的存储服务

可以像对待数据库一样对待 S3 存储桶,方法是以标准化格式存储 CSV 或 JSONs,用 AWS Glue 索引存储桶,然后用 AWS Athena 查询索引。但是有一些严重的警告——在以前的工作中,我不小心上传了一个格式错误的 CSV 文件,使得整个桶无法搜索。对于数百个文件,我不知道错误在哪里。在我看来,您最好使用具有严格写入规则的数据库,这些规则会立即标记(并阻止)格式错误的数据。

AWS 数据科学基础:为什么选择云计算?

原文:https://towardsdatascience.com/aws-essentials-for-data-science-why-cloud-computing-141cc6cee284

如何利用这个 5000 亿美元的产业

Unsplash 上的 CHUTTERSNAP 拍摄

假设您是纽约数据科学见面会的协调员。你计划的主要部分包括预定场地来接待你的客人。你总是在城市周围租赁场地,但你想知道是否最好是购买自己的,以避免每次都寻找免费场地的麻烦。

如果这个场所是一台计算机的类比,那么云计算行业会响亮地插一句“不!”云计算的论点是,在数据中心租用计算机比自己购买便宜得多,更安全,也更具可扩展性。他们会说:“让我们给你预定一个场地。”。“事实上,完全忘记场地,只专注于举办一场精彩的派对。”

自 20 世纪 60 年代以来,共享计算机资源的概念就已经存在,自 20 世纪 90 年代以来,“云计算”一词就已经出现。但直到 2000 年代,这个行业才开始加速成为今天这个不可阻挡的庞然大物。例如,全球云计算市场在 2021 年达到令人印象深刻的 4453 亿美元,但预计在短短五年内将翻一番多,达到 9473 亿美元!

为什么云计算如此无处不在?作为数据科学家、机器学习工程师或软件工程师,我如何利用它?这些问题有太多东西要解开,超出了我们一篇文章的篇幅。因此,这篇文章将介绍云计算:它是什么,为什么你应该关注它。接下来的两篇文章将涵盖云计算的两个核心类别存储计算

我们将重点关注亚马逊网络服务(AWS) ,它是市场领导者,也可以说是云革命的推动者。但是我们将要讨论的一切也适用于其他主要参与者:谷歌云平台(GCP)微软 Azure阿里云等等。我们开始吧!

照片由 Szabo ViktorUnsplash 上拍摄

什么是云?

开门见山地说,云只是一堆数据中心里的一堆电脑。一个数据中心是一个别致的、安全的仓库,用来储存大量运行中的计算机,可能位于电费便宜或气候寒冷的地方。

这些电脑没有显示器或键盘——它们只是执行计算、存储和检索数据、响应 HTTP 请求等的硬件。我们称这些机器为服务器,以区别于大多数人熟悉的人性化的笔记本电脑或台式机,因为它们响应用户的请求。

数据中心中的服务器机架。照片由imgixun splash(左)和dlohnerPixabay(右)**

大型科技公司的数据中心——亚马逊、Meta、谷歌等。让数百万台服务器堆叠在一个又一个机架上,将延伸到你所能看到的。任何时候,一个人上传一张猫的照片到 Instagram,或者在 Pinterest 上给一双鞋做书签,或者在 WhatsApp 上回复一条消息,他们都会与其中的一些服务器进行交互。[1]**

云为什么有用?

如果你曾经使用过 iCloudDropboxGoogle Drive ,你可能已经熟悉云存储的便利性。如果你丢失了手机,你可以找回你的短信;可以用链接分享文件,而不是海量的邮件附件;您可以按照片中的人来整理和搜索照片。

但是云的用处不仅仅是让你的个人生活更加顺畅:它还能增加你的职业生活。并非所有亚马逊的服务器都忙于处理鞋子的搜索,或者决定向哪些用户展示埃尔登戒指的广告。事实上,这些服务器中的一些可以供你自己租用。

无需购买和维护服务器就能租赁服务器,这是云计算的主要优势。如果云行业有一个口号,那就是“无论你需要什么资源,无论你何时需要它们。”如果服务器就像物理云中的水滴,那么该行业为用户能够将云塑造成最符合其需求的任何大小和形状而自豪。

作者图片

假设你正在开发一个约会应用。你需要一种存储用户照片的方法,以及一种训练推荐系统匹配用户的方法。只需租用一台针对存储优化的服务器来存放照片;另一个为运行排名模型的计算而优化;也可能是一个小型的,用于托管站点、处理用户认证等。

作者图片

随着你的应用程序的受众在情人节前后增加,将这三台服务器扩展到四台、五台或更多,然后随着用户约会生活的平静下来,再降回三台。当您决定开始随机匹配用户时,完全放弃计算服务器。

在这个疯狂的旅程中,你只需为你使用的东西付费。您还避免了自己购买硬件的前期成本,并且如果用户上传了太多照片,导致您的存储服务器崩溃,您也可以摆脱困境。云提供商提供充足的备份和冗余,这意味着客户基本上可以忘记运行他们服务的确切机器。

最后,我一直在说“服务器”,就好像您租用了整个机器一样。但是为了更容易地利用云,的客户可以保留一台服务器的一部分,它仍然像一台独立的机器这种 虚拟化 对客户和云提供商都有好处——您可以根据需要保留尽可能少的计算或存储,提供商可以通过在多个客户之间分配服务器来保持服务器忙碌(并赚钱)。

作者图片

什么是云(形式上)?

NIST (美国国家标准与技术研究院)通过概述五个基本特征提供了云的更正式定义:

1。按需自助服务
客户可以选择他们需要的计算资源,无需与提供商进行人工交互。例如,用户可以点击一个按钮来预订一个服务器来托管他们的网站,然后点击另一个按钮来释放该服务器。

2。广泛的网络访问这些资源可以通过互联网获得,并且可以通过多种平台访问。例如,用户可以从他们的笔记本电脑上预定一台服务器,然后再从他们的手机上检查它的健康状况。

3。资源池
云资源是动态分配和再分配的,资源的具体位置从用户那里抽象出来。例如,用户可以预订两个服务器,并且不需要知道一个是位于弗吉尼亚州的数据中心 A 中的服务器 123,另一个是位于纽约的数据中心 B 中的服务器 456。

4。快速弹性
可以供应和释放资源,以快速满足需求。例如,当应用流量增加时,用户可以选择自动使用更多服务器。

5。测量服务
资源使用是精确计量、可见和可控的。例如,用户可以实时查看托管其应用的服务器的成本,并根据业务需求的变化重新配置其分配。

让我们回到场地预订的类比。“Venue AWS”服务会宣传你可以通过他们的网站或应用程序(#1、#2)自动预订你需要的任何大小的场地。这些场地是从一大组房间中抽取的,这些房间随着用户活动的开始和结束而消失和重新出现(#3)。如果你的与会者突然比你预期的少了或多了,或者随着与会者来来去去,你可以动态地将每个人传送到最佳大小的场地(#4),次数不限。最后,你清楚地看到了你所支付的费用,如果你在任何时候改变了主意,你都可以放弃。

什么时候云不适合我?

在我们继续之前,有必要提一下反对云计算的观点。尽管他们尽了最大努力,云提供商 偶尔也会失败 ,拖垮他们的客户。例如,2020 年 11 月,Adobe、iRobot 和 Roku 因一批新服务器添加到 AWS 数据中心的方式出错而离线几个小时。同样,云提供商也不能幸免于数据泄露,比如当Twitch 的所有源代码被泄露或者一名不满的员工自愿泄露客户信息**

如果您在一个用户数据极其敏感的领域工作(例如,社会安全号码),或者您的应用程序绝对不能被中断(例如,紧急响应),那么可能有必要投资一个您可以完全控制的系统。

Max LaRochelleUnsplash 上拍摄

什么是 AWS?

AWS,或称亚马逊网络服务,是亚马逊的云服务。AWS 于 2002 年推出,作为亚马逊推动 T2 为其软件工程师提供更加面向服务的架构的一部分。目标是雄心勃勃的:最大化团队的自主性,采用RESTAPI,标准化基础设施,移除守门决策者,并持续部署代码。亚马逊确定需要一个分布式、可扩展的软件架构来实现这个雄心。**

结果如此成功,以至于亚马逊也将 AWS 变成了一个供公众使用的产品。AWS 目前占据云计算市场 32%的份额(微软 Azure 和谷歌云分别占据 20%和 9%的份额),并提供超过 200 种不同抽象层次的服务。深入到操作系统层面,优化运行你的应用的服务器的基础,或者只是通过一个服务来启动你的应用,这个服务为你处理大部分细节

作者截图

安装

让我们创建一个 AWS 帐户。如果你能跟上的话,这些帖子会更有意义,你以后也能自己尝试了。

我们首先访问 AWS 网站,点击“创建 AWS 账户”AWS 提供的大部分服务都是免费的,为期一年,这意味着你可以学习和尝试真实的东西,而不必担心成本。(不过,你确实需要附上信用卡,以防万一你决定放弃温和的教程,开始训练下一个 AlphaGo 。)**

作者截图

假设你不是机器人(🤖),完全按照步骤操作应该很简单。(还没有绝招题!)创建帐户后,您应该会看到控制台主页,上面有一些小部件,如最近访问的应用程序、一些“欢迎使用 AWS”链接、费用和使用情况等。

凯尔·格伦在 Unsplash 上的照片

身份和访问管理

我们成功了!我们应该开始建立一个图像分类器还是聊天机器人?一个视频游戏引擎或者卫星控制器怎么样?其实… 先说身份管理。

以身份管理开始我们的 AWS 冒险听起来可能有点虎头蛇尾,但是遵循安全最佳实践对于成功利用云是至关重要的。如果你的应用被黑了,你的客户不会很同情你(尤其是他们的数据被盗了!),攻击者可以在您取消信用卡之前轻松积累数千美元的费用。从更友好的角度来说,设置身份管理可以让您轻松安全地将新的开发人员引入到您的项目中!

当您创建 AWS 帐户时,您创建了一个根用户。这是该帐户的一个全能用户,可以对任何服务执行任何操作,创建和删除其他用户配置文件,访问和更改支付信息,以及关闭帐户。那就是大量的权力集中在一个地方。事实上,AWS 建议新用户做的第一件事就是设置【MFA】让它变得更难(但不是不可能!)供攻击者侵入 root 帐户。****

如果你导航到 AWS 的身份和访问管理服务 IAM ,你会看到一个红色的警告,提示 root 用户不受保护。(在搜索栏中键入“IAM”即可找到。)

作者截图

因此,让我们修复这个漏洞——只需点击“添加 MFA”,选择方法(如手机上的验证器应用程序),然后按照提供的步骤操作。设置好 MFA 后,任何试图以 root 用户身份登录的人都需要提供额外的证明,证明他们确实是你。这个额外的麻烦是值得的—你通常不会登录到根帐户。****

相反,您通常会登录到一个 用户配置文件 ,并根据您的典型工作流程获得特定权限。例如,您的日常工作可能不涉及更新信用卡详细信息或更改客户密码,因此您可以限制用户(包括您自己,除非您以 root 用户身份登录)的这些操作。

事实上, **IAM 配置文件不能做任何事情,除非你明确表示他们可以做,这是一个安全概念,称为授予最小特权。这大大降低了一个被入侵的帐户可能造成的损害。例如,下面的蓝色用户只能访问 S3 和 DynamoDB,而橙色用户可以访问 S3、Lambda、API Gateway 和 CloudWatch。甚至像 S3 这样的服务中,Blue 对动作或内容的访问可以根据他们的业务需求进行不同于 Orange 的配置。**

作者图片

让我们建立一个 IAM 配置文件。我们将首先创建一个 用户组 ,该用户组具有自动应用于该组中任何用户的某些权限。这使得新用户的加入变得很容易,因为我们只需将他们的配置文件添加到一个预配置的组中,该组具有任何新用户都应该拥有的权限。

要创建组,在 IAM 中,我们只需单击左侧的“用户组”,然后单击右侧的“创建组”。我们可以将这个组命名为admins,然后向下滚动,搜索AdministratorAccess策略,并将其附加到我们的组。

作者截图

最后,我们创建我们的用户。点击左边的“用户”,然后“添加用户”,然后输入你的帐户名称。然后,我们将选择“编程访问”(允许我们通过代码访问 AWS)和“AWS 管理控制台访问”(允许我们作为自己的用户而不是根用户登录)。

作者截图

然后我们点击“下一步:权限”,将我们的用户添加到我们的admins组。“下一步:标签”允许我们为搜索添加标签(例如,如果我们有几十或几百个用户),但我们现在可以跳过这一步。在最后的审查屏幕中,我们可以确认一切正常,然后点击“创建用户”

下一个屏幕很重要!自动生成的密码和秘密访问密钥(用于从代码访问 AWS)只提供一次。在离开页面之前,在安全的地方记下您的访问密钥 ID、秘密访问密钥和自动生成的密码——访问密钥 ID 和秘密访问密钥是互联网上的任何人通过 Python 脚本访问您的 AWS 服务所必需的。

作者截图

干得好!最后一件事:如果我们作为 IAM 用户登录,我们需要提供 AWS 帐户的 12 位帐户 ID。这个数字很难记住,除非你使用密码管理器或者对数字有很好的记忆力。相反,让我们为这个账户创建一个别名(基本上是一个用户名),这样我们就可以用更容易记住的东西登录了。与我们的 IAM 配置文件名不同,这个用户名需要在所有 AWS 中是唯一的,所以您可能需要比matt更具体的名称。**

作者截图

照片由替代代码Unsplash 上拍摄

命令行界面

最后,安装 AWS CLI 以便能够从命令行访问您的 AWS 服务。(Python 用户也可以只输入pip install awscli。)虽然 UI 通常足以满足我们的需求,但有时一个命令行界面是无价的——例如,将 10,000 个 CSV 上传到一个 S3 存储桶可以通过几次击键来完成,而不需要在 UI 中点击并拖动文件。CLI 还设置我们通过脚本自动执行 AWS 操作——比如增加或减少服务器资源。

一旦你安装了命令行界面,你可以输入aws configure来输入你的访问密钥 ID 和秘密访问密钥,以及其他细节。

作者截图

恭喜你。🎉您已经设置了一个 AWS 帐户,遵循了安全最佳实践,现在可以开始试验了。

贾斯汀·克拉克在 Unsplash 上的照片

结论

在这篇文章中,我们介绍了云计算和亚马逊网络服务。我们用预订场地的类比来描述云的主要产品:租用服务器(计算机)而不需要购买和维护它们的能力。然后,我们讲述了云提供商如何通过按需自助服务、广泛的网络访问、资源池化、快速弹性和测量服务实现对服务器的灵活和动态访问。然后,我们简要介绍了 AWS 的历史,并介绍了如何设置帐户、IAM 配置文件和 CLI。**

我们现在已经准备好真正使用 AWS,并更好地理解它的两个主要支柱:计算存储。我们将为每一个产品发布一篇帖子,介绍这些产品的基础知识,并在 Python 和 CLI 中带来许多乐趣。希望在那里见到你!**

最好,
哑光

脚注

1.什么是云?

从技术上讲,你查看贾斯汀比伯最新推文的 HTTP 请求很可能不会一直到达这些大型数据中心之一。相反,你可能只能到达最近的内容交付网络(CDN) 节点(又称为存在点,PoP),分散在世界各地的数千个较小的数据中心之一。

cdn 通过缓存流行内容来减轻数据中心数据库(以及整个互联网)的负荷。从缓存中检索数据比从磁盘中检索要快得多,这意味着服务器可以立即发回比伯的推文,而不需要挖掘数万亿推文来找到它。事实上,网飞能够提供如此无缝的流媒体体验,因为他们利用了大量的 cdn。

但是当然,CND 也有其局限性,否则我们就只能使用它了。用于缓存的硬件非常昂贵——例如,AWS 中的 1 TB 在 S3 上是 23 美元,在 CloudFront 上是 85 美元。还有很多内容我们无法存储在缓存中,比如我们希望在登录后锁定的用户数据。**

Apache Airflow 与 Glue 的 AWS 托管工作流

原文:https://towardsdatascience.com/aws-managed-workflows-for-apache-airflow-vs-glue-184eca9e6996

找出 MWAA 胶水和 AWS 胶水的区别

马丁·亚当斯在 Unsplash 上的照片

2020 年,AWS 为 Apache Airflow (MWAA)推出了亚马逊管理的工作流。Apache Airflow 是一个开源的工作编排平台,由 Airbnb 在 2014 年创建。从那时起,许多公司开始使用它,并将其用于各种用例。它是一个工作流协调工具,允许用户在计划的时间按顺序和逻辑运行作业,或者临时执行作业。由于其架构不依赖于用户无法控制的嵌入式存储,人们可以将队列服务和元数据存储外部化到 Airflow 之外,以便您可以将 Airflow 堆栈设计为可水平扩展的。

然而,与其他开源项目一样,维护气流资源成为了您的责任。这不是一件小事。了解了需求,AWS 让 MWAA 负责后勤方面的工作。最近的 AWS 服务让我想到了 AWS Glue——一种托管 ETL(提取、转换和加载)服务,以及它们之间的区别。

MWAA 和 AWS 胶水对比

Apache Airflow 和 AWS Glue 的目标不同,但它们有一些共同点。两者都允许您创建和管理工作流。由于这种相似性,你可以用气流完成的一些任务也可以用胶水来完成,反之亦然。这种共性让我们在想要选择一个而不是另一个的时候有了歧义。要做出明智的决定,了解它们之间的区别非常重要。

服务器与无服务器

让我们首先从对它们的工作方式有重大影响的架构差异开始。MWAA 是基于服务器的,而 AWS Glue 是无服务器的。我们不会在这里讨论这两个不同的概念,但 MWAA 和胶水继承了建筑差异的缺点和优点,它们出现在三个主要领域。

费用

云平台提供商提供无服务器服务,人们选择它们的原因之一是成本效益。Apache Airflow 被设计为在服务器上运行。这意味着,即使没有作业运行,您的气流资源仍将保持活动状态,这将在空闲时间产生成本。MWAA 仍然是基于服务器的,但它提供了一种通过自动伸缩来节省成本的方法。MWAA 监控资源的使用情况,如果需要更多的资源就增加工作线程的数量,如果需要更少的资源就减少工作线程的数量。但是,由于它是基于服务器的,您无法避免在空闲时间运行服务器。AWS Glue 是无服务器和事件驱动的。当你触发时,它将开始分配服务器资源。在空闲时间,它不使用任何资源,也不会产生任何成本。

在 MWAA,有四个主要因素决定你的账单。

  • 实例大小
  • 附加工作实例
  • 附加调度程序实例
  • 元数据库存储

这些费用将乘以使用小时数。

AWS 胶水里,你是按 DPU 或者数据处理单元乘以使用小时来收费的。根据您运行的工作类型,DPU 的计算方式会有所不同。有三种类型。

  • Python shell:您可以选择 0.0625 或 1 DPU。
  • Apache Spark:您可以最少使用 2 个 dpu,最多使用 100 个 dpu。
  • Spark Streaming:您可以使用最少 2 个 dpu,最多 100 个 dpu。

工作隔离

在服务器环境中,工作流共享相同的资源。当工作流进程消耗大量内存或 CPU 时,它会对其他进程产生负面影响。如果您没有均匀地分配触发时间,并且错误地配置了最大工作人员数,则在 MWAA 可能会出现这种症状。相比之下,AWS Glue 为每个工作流提供了一个隔离的环境,因为每个工作流都使用独立的资源。当您运行繁重的数据密集型工作时,不会影响同时运行的其他工作流。

响应性

在 MWAA,服务器总是在运行,随时可以使用。当触发作业工作流时,它几乎没有延迟就开始了。在 AWS Glue 中,因为它是无服务器的,ETL 工作流从分配必要的资源开始。这意味着在实际作业开始之前会有一些延迟。此外,当您必须使用外部库时,每次作业启动时,它首先安装那些库,然后开始实际的作业。

工作编排与 ETL

值得讨论一下每项服务的设计目的。让我提醒你,气流是一个工作编排工具。如果我们在维基百科中搜索编排的定义,它也会给你一个编排者的定义。

指挥是受过训练的音乐专业人员,他给乐队分配乐器

这里我们要重点说的词是“赋值”。气流的一个理想用例是将工作委派给其他资源。当然,我们仍然可以在 Airflow 内运行非密集型任务,但是如果可能的话,最好分配它们。避免在气流中运行繁重的任务也可以防止它们占用共享资源。MWAA 的一个很好的优势是它在 AWS 之内。这意味着您可以使用 IAM 和安全组更恰当地访问其他 AWS 服务,如 EMR、Athena、S3、Redshift 等。

AWS Glue 专门做 ETL。当您提取、转换和加载数据时,通常需要昂贵的过程。为了处理密集型任务,可以在 Glue 中使用 Apache Spark 集群。由于能够在内部使用 Spark 集群,您可以运行大规模数据处理,而不必担心资源耗尽。

监控和记录

MWAA 和 AWS 胶水都提供了方便的监测方法。这对于气流来说是一个很大的提升。当您在自己的服务器上设置和使用 Airflow 时,您会意识到检查 Airflow 日志并不方便用户。Airflow 为任务、web 服务器、调度程序、工作程序和 Dag 写入不同类型的日志。默认情况下,它将这些日志写在服务器内部。要读取日志,您必须 SSH 到服务器并运行命令。当您希望使用分布式服务器来实现可伸缩性时,这变得更加复杂。这将需要您创建中央日志存储,并进行额外的设置,以使所有服务器都将日志写入该单一位置。

因为 MWAA 是由 AWS 管理的,所以所有的日志都被写入 CloudWatch。这意味着您可以使用 Logs Insights 搜索某些日志,并拥有一个显示 CPU、内存和网络流量等服务器资源使用情况的仪表板。此外,您还可以监控许多其他特定于气流的指标。您还可以通过编程方式设置警报和管理通知收件人。

AWS Glue,由于是原生的 AWS 服务,也有很好的监控能力。不同的是,除了 CloudWatch,你还可以在 GlueStudio 的 Glue 内部监控你的 Glue 资源。

GlueStudio 监控仪表板(图片由作者提供)

我发现在 Glue 中更容易深入和跟踪失败的作业。上图是 GlueStudio 监控菜单的第一个屏幕。它给你高层次的数字。你可以点击每个数字去找相关的工作。当您在那里选择一个作业时,您可以搜索它的 CloudWatch 日志并查看其他指标。当您有许多工作流要监控时,这种设计可以让您更清楚地了解情况,从而更容易地跟踪问题。

云的形成

由于 Airflow 已经成为 AWS 中托管服务的一部分,因此您可以对 Airflow 基础架构进行云计算。然而,不仅是基础设施环境,就连 Airflow 的本地配置变量也可以被云化。当您已经通过 CloudFormation 管理 AWS 资源时,这将为您提供资源管理的一致性,并使跨不同环境的气流管理更加容易。AWS 胶水当然可以通过 CloudFormation 来管理。一个很大的不同是,您甚至可以使用它来创建和定义工作流,这给了您更深层次的可控性。

AWS SDK 和 CLI

除了 CloudFormation,MWAA 还可以像其他 AWS 资源一样与 AWS SDK 和 CLI 交互。使用它们,您可以创建、更新和删除 MWAA 环境,并检索它们的环境信息,包括日志记录策略、工作线程数量、调度程序等等。您也可以运行 Airflow 的内部命令来控制 Dag,但 MWAA CLI 并不支持 Airflow 的所有本机命令,如回填(查看此 AWS 文档)、Dag 列表、Dag 列表运行、Dag 下一次执行等等。这些限制主要是因为 Airflow 不是作为 AWS 的原生服务而创建的。说了这么多,AWS Glue 完全可以用 SDK 和 CLI 来控制。你基本上可以使用库来执行所有的任务和控制整个 Glue 资源。

包扎

MWAA 和 AWS Glue 都是编排作业的好工具——MWAA 用于一般作业,Glue 专门用于 ETL。上面讨论的这些架构和功能上的差异将影响您对工具的选择。当然,知道了这些区别,你可能想考虑同时使用它们,这会给你更多的灵活性。当你使用两者时,你可以控制来自 MWAA 的 Glue 资源,例如,因为 Glue 的 SDK 给了你更多的控制权,而 Airflow 拥有 glue 操作器。这两个服务内部都有很大的生态系统,有很多东西需要学习,所以在开始全面开发之前尝试一下是很好的。

AWS SageMaker X hugging face X AWS quick sight

原文:https://towardsdatascience.com/aws-sagemaker-x-huggingface-x-aws-quicksight-7f4bd53dc484

如何通过机器学习解决医疗成绩单的分类问题,并为以下内容发布模型和数据监控仪表板

来源:丹尼尔·科尔派在 Unsplash 上拍摄的照片

简介

这是一个解决方案,演示了如何在 AWS SageMaker 上训练和部署预训练的 Huggingface 模型,并发布一个 AWS QuickSight 仪表板,该仪表板可视化模型在验证数据集上的性能,并对预处理的训练数据集进行探索性数据分析。以此作为提出的解决方案的架构,我们尝试通过机器学习来解决医疗记录的分类,这基本上是解决一个生物医学 NLP 问题。在本解决方案中,我们还讨论了通过 PyTorch 编写自定义 Huggingface 训练器进行训练时的特征工程和通过类权重处理不平衡数据集。

将 Huggingface 与 SageMaker 一起使用的意义在于简化 SageMaker 上基于 transformer 的模型的训练,并使它们易于部署用于生产。此外,使用 QuickSight Dashboard 将数据和模型分析集中在一个平台上,使监控和配置变得更加容易。当项目需要一个服务器端仪表板来由管理员或开发团队监控模型和数据时,建议的 dashboard 管道非常方便。

体系结构

来源:作者

视频演示

下面是建议的架构的演示视频。

来源:作者

问题陈述

诊断预测旨在自动预测具有特定既往病史的患者所需的诊断。

病历由一个原始文本文件表示,其中包含医生对患者的记录,包括他/她的年龄、在高速公路上描述的主诉、患者的病史等等。它是非结构化的——一个病人病历的不同部分可能在另一个病人的病历中不存在。

目标标签由所需诊断程序的名称表示。

解决方案的价值可以帮助医生找到诊断订单的最佳解决方案。患者可以节省时间和金钱,医生可以通过节省时间进行不必要的诊断来更有效地为患者服务。此外,在困难的情况下,该算法可以帮助医生更快地找到诊断结果,这在某些情况下可能非常有价值,甚至可以挽救生命。

从理论上讲,算法发现的一些规律可能有助于医学研究人员根据某些疾病与某些症状之间的不明显联系,找到治疗某些疾病的思路。

数据集和存储

所有的数据集都存储在 数据集 目录下的 S3 桶( 医学-转录-回购 ) 中。该数据集包含各种医学专业的样本医学转录

预处理和特征工程数据集存储在不同目录下的相同 S3 桶中(S3://medical-transcription-repo/preprocess/)。模型存储也是如此(S3://medical-transcription-repo/models/)。

来源:作者

类似地,在预处理 s3 存储桶目录中,我们存储训练数据和验证数据集以备将来使用。

来源:作者

- dataset - dataset.csv- preprocess - pre-processed - eval - validation.csv -pre-processed.csv - train - dataset-info.json -test - dataset-infor.json- models - huggingface-dd-mm-yyyy:hh-mm-ss - output - model.tar.gz - output.tar.gz

数据集源

从 mtsamples.com 刮来的数据。这个数据集通过提供医学转录样本提供了一个解决方案。

ML 模型训练、部署和推理

AWS SageMaker

为了在 SageMaker 上训练和部署模型,使用了以下服务:

  • 笔记本实例(ml . T2 . medium)
  • 培训岗位(ml . p 3.2x large)
  • 推断终点(ml . T2 . medium)

预处理和特征工程

原始数据集由 40 个要分类的类组成,但是由于缺乏关于这些类的足够的训练样本,一些类集合被移除,最终以 23 个类的分类问题结束。然后,预处理后的数据集被上传到 s3 存储桶,以便在 AWS QuickSight 中进一步创建 EDA 仪表盘。

接下来,数据集被分成训练集和验证集,并对文本数据进行标记。预训练的无壳分词器用于对输入数据进行分词。

from transformers import AutoTokenizer# tokenizer used in preprocessing
tokenizer_name = 'distilbert-base-uncased'
# download tokenizer
tokenizer = AutoTokenizer.from_pretrained(tokenizer_name)# tokenizer helper function
def tokenize(batch):
    return tokenizer(batch['text'],padding=True, truncation=True)# tokenize dataset
train_dataset = dataset['train'].map(tokenize, batched=True)
test_dataset = dataset['test'].map(tokenize, batched=True)# set format for pytorch
train_dataset =  train_dataset.rename_column("target", "labels")
train_dataset.set_format('torch', columns=['input_ids', 'attention_mask', 'labels'])
test_dataset = test_dataset.rename_column("target", "labels")
test_dataset.set_format('torch', columns=['input_ids', 'attention_mask', 'labels'])

令牌化的训练和验证集被上传到 s3 存储桶。

import botocore
from datasets.filesystems import S3FileSystems3 = S3FileSystem()  
prefix = 'preprocess'# save train_dataset to s3
training_input_path = f's3://{bucket}/{prefix}/train'
train_dataset.save_to_disk(training_input_path,fs=s3)# save test_dataset to s3
test_input_path = f's3://{bucket}/{prefix}/test'
test_dataset.save_to_disk(test_input_path,fs=s3)

估计类别权重

对于类别不平衡,要考虑的一个方面是每个批次都有足够的信号来覆盖所有类别,甚至不平衡的类别。否则可能会在训练中退化。

在这种情况下,我们使用类权重来处理不平衡的数据集。

from sklearn.utils import class_weight
class_weights = dict(enumerate(class_weight.compute_class_weight(‘balanced’,
               classes=np.unique(df[‘target’]),
               y=df[‘target’])))

拥抱脸定制训练器

预训练的无壳模型和用于处理不平衡数据集的自定义损失函数用于模型训练。

from transformers import Trainer, TrainingArguments, AutoTokenizer# create Trainer instance
# Subclass Trainer and override the compute_loss method
class MedModelTrainer(Trainer):
    def compute_loss(self, model, inputs, return_outputs=False):
        labels = inputs.get("labels")
        # forward pass
        outputs = model(**inputs)
        logits = outputs.get("logits")
        # compute custom loss
        loss_fct = torch.nn.CrossEntropyLoss(weight=torch.tensor(list(class_weights.values())))
        loss = loss_fct(logits.view(-1, self.model.config.num_labels), labels.view(-1))
        return (loss, outputs) if return_outputs else losstrainer = MedModelTrainer(
    model=model,
    args=training_args,
    compute_metrics=compute_metrics,
    train_dataset=train_dataset,
    eval_dataset=test_dataset,
    tokenizer=tokenizer,
)# train model
trainer.train()

创建评估员并开始培训工作

拥抱脸深度 DLCs(深度学习容器)让在 SageMaker 中训练变形金刚模型变得前所未有的简单。以下是您应该使用拥抱脸 DLCs 来训练和部署您的下一个机器学习模型的一些原因:
*您只需要一个命令。
*加速机器学习从研究到生产的转变。
*内置性能。

在 SageMaker 训练环境中,该估计器执行拥抱面部训练脚本。

使用预构建的拥抱面部 Docker 容器,估计器启动 SageMaker 管理的拥抱面部环境,并执行用户通过**entry_point**参数提供的拥抱面部训练脚本。

from sagemaker.huggingface import HuggingFace, TrainingCompilerConfig
# initialize the Amazon Training Compiler
compiler_config=TrainingCompilerConfig()# hyperparameters, which are passed into the training job
hyperparameters={'epochs': 10,
                 'train_batch_size': 64,
                 'eval_batch_size': 32,
                 'learning_rate': 3e-5, 
                 'model_name':'distilbert-base-uncased'
                 }huggingface_estimator = HuggingFace(entry_point='train.py',
                            source_dir='./scripts',
                            instance_type='ml.p3.2xlarge',
                            instance_count=1,
                            role=role,
                            transformers_version='4.11.0',
                            pytorch_version='1.9.0',
                            py_version='py38', output_path='s3://{}/models'.format(bucket),
                            hyperparameters = hyperparameters,
                            compiler_config = compiler_config
                                   )

以我们上传的数据集作为输入开始训练工作。

huggingface_estimator.fit({'train': training_input_path, 'test': test_input_path})

部署端点

为了部署我们的端点,我们在 HuggingFace estimator 对象上调用 deploy() ,传入我们想要的实例数量和实例类型。

predictor = huggingface_estimator.deploy(1,"ml.t2.medium")

对于推理,您可以使用您训练的拥抱人脸模型或预训练的拥抱人脸模型之一来部署 SageMaker 的推理作业。通过这种协作,您只需要一行代码就可以使用 SageMaker 部署您的已训练模型和预训练模型。

eval_df = pd.read_csv('test.csv')
eval_df['pred'] = 0
eval_df['score'] = 0.0
max_length = 512
for i in range(len(eval_df)):
    sentiment_input= {"inputs": eval_df['text'].iloc[i][:max_length]}
    eval_df['pred'][i] = int(predictor.predict(sentiment_input)[0]['label'].split('_')[1])
    eval_df['score'][i] = float(predictor.predict(sentiment_input)[0]['score'])

带有模型预测的验证集存储在 s3 存储桶中,以开发 AWS QuickSight 上的模型性能仪表板。

eval_df.to_csv("model-performance.csv", index=False)
s3 = boto3.resource('s3')
s3.meta.client.upload_file('model-performance.csv', bucket, 'preprocess/pre-processed/eval/model-performance.csv')

源代码

下面给出了以下建议体系结构的源代码:

托管 QuickSight 仪表盘的架构,用于 SageMaker 上部署的拥抱面部模型监控以及数据 EDA

AWS QuickSight

Quicksight 是 AWS 提供的云原生、无服务器 BI 服务。

EDA 仪表板显示在预处理的医疗记录数据上。分析的重点是医学专业的分布、医学专业的子群、医学专业之间的关系、转录上下文的词云等。

来源:作者

模型性能仪表板是可视化的,用于验证医学转录数据集的模型预测。分析的重点是模型预测的正确性;目标类与预测类分布的差异;模型在验证集上的准确度、精确度、召回率和 f1 分数等。

来源:作者

正确性图的计算字段

ifelse(pred=target, "Correct", "Wrong")

准确度(%)的计算字段

(countIf(Correctness, Correctness="Correct")/ count(Correctness)) * 100

精度的计算字段(%)

((countIf(pred, pred=0 AND target=0)/countIf(pred, pred=0) +countIf(pred, pred=1 AND target=1)/countIf(pred, pred=1) +countIf(pred, pred=2 AND target=2)/countIf(pred, pred=2) +countIf(pred, pred=3 AND target=3)/countIf(pred, pred=3) +countIf(pred, pred=4 AND target=4)/countIf(pred, pred=4) +countIf(pred, pred=5 AND target=5)/countIf(pred, pred=5) +countIf(pred, pred=6 AND target=6)/countIf(pred, pred=6) +countIf(pred, pred=7 AND target=7)/countIf(pred, pred=7) +countIf(pred, pred=8 AND target=8)/countIf(pred, pred=8) +countIf(pred, pred=9 AND target=9)/countIf(pred, pred=9) +countIf(pred, pred=10 AND target=10)/countIf(pred, pred=10) +countIf(pred, pred=11 AND target=11)/countIf(pred, pred=11) +countIf(pred, pred=11 AND target=11)/countIf(pred, pred=11) +countIf(pred, pred=12 AND target=12)/countIf(pred, pred=12) +countIf(pred, pred=13 AND target=13)/countIf(pred, pred=13) +countIf(pred, pred=14 AND target=14)/countIf(pred, pred=14) +countIf(pred, pred=15 AND target=15)/countIf(pred, pred=15) +countIf(pred, pred=16 AND target=16)/countIf(pred, pred=16) +countIf(pred, pred=17 AND target=17)/countIf(pred, pred=17) +countIf(pred, pred=18 AND target=18)/countIf(pred, pred=18) +countIf(pred, pred=19 AND target=19)/countIf(pred, pred=19) +countIf(pred, pred=20 AND target=20)/countIf(pred, pred=20) +countIf(pred, pred=21 AND target=21)/countIf(pred, pred=21) +countIf(pred, pred=22 AND target=22)/countIf(pred, pred=22)) /23) *100

召回的计算字段(%)

((countIf(pred, pred=0 AND target=0)/countIf(target, target=0) +countIf(pred, pred=1 AND target=1)/countIf(target, target=1) +countIf(pred, pred=2 AND target=2)/countIf(target, target=2) +countIf(pred, pred=3 AND target=3)/countIf(target, target=3) +countIf(pred, pred=4 AND target=4)/countIf(target, target=4) +countIf(pred, pred=5 AND target=5)/countIf(target, target=5) +countIf(pred, pred=6 AND target=6)/countIf(target, target=6) +countIf(pred, pred=7 AND target=7)/countIf(target, target=7) +countIf(pred, pred=8 AND target=8)/countIf(target, target=8) +countIf(pred, pred=9 AND target=9)/countIf(target, target=9) +countIf(pred, pred=10 AND target=10)/countIf(target, target=10) +countIf(pred, pred=11 AND target=11)/countIf(target, target=11) +countIf(pred, pred=11 AND target=11)/countIf(target, target=11) +countIf(pred, pred=12 AND target=12)/countIf(target, target=12) +countIf(pred, pred=13 AND target=13)/countIf(target, target=13) +countIf(pred, pred=14 AND target=14)/countIf(target, target=14) +countIf(pred, pred=15 AND target=15)/countIf(target, target=15) +countIf(pred, pred=16 AND target=16)/countIf(target, target=16) +countIf(pred, pred=17 AND target=17)/countIf(target, target=17) +countIf(pred, pred=18 AND target=18)/countIf(target, target=18) +countIf(pred, pred=19 AND target=19)/countIf(target, target=19) +countIf(pred, pred=20 AND target=20)/countIf(target, target=20) +countIf(pred, pred=21 AND target=21)/countIf(target, target=21) +countIf(pred, pred=22 AND target=22)/countIf(target, target=22)) /23) *100

f1 的计算字段-得分(%)

2 * (Precision*Recall ) / (Precision + Recall)

结论

提议的 AWS 云架构提供了一种解决方案,用于训练和部署基于 transformer 的 NLP 预训练模型,这些模型可在 Huggingface 通过 AWS SageMaker 进行生产。AWS QuickSight 用于发布仪表板,以可视化基本数据集的 EDA 和验证集上的 ML 模型性能,这成功地将数据和模型分析集中在一个屋檐下。

改进的范围

  • 可以改进模型性能仪表板,以增加每个类的精确度和召回分数。
  • 向模型性能仪表板添加混淆矩阵。
  • 为更高的时期训练模型以更好地收敛。
  • 尝试不同的预训练模型,如伯特罗伯塔,以获得更好的模型性能。
  • 改进特征工程技术,如减少目标类或使用少数过采样技术以获得更好的性能。

参考

AWS 步骤功能活动

原文:https://towardsdatascience.com/aws-step-functions-activities-f9408a66756a

将分离的工人集成到状态机工作流中

来源:作者提供的图表

AWS Step Functions 于 2016 年推出,提供状态机来协调 AWS 服务之间的请求。Step 函数支持与 Lambda 函数SQS 队列DynamoDB 表更多服务的集成,可以自动化复杂的流程并管理每秒数千个执行启动—适应无服务器架构并利用其扩展能力。

有些情况下,我们希望对工作流中的步骤进行分级限制:手动检查数据质量,或者限制 Lambda 函数并发性以适应外部 API 限制。这给原本同步的流添加了一个异步元素。之前我们探索了步骤函数回调来处理这样的场景:生成任务令牌,将它们推给异步工作器进行处理,并暂停我们的执行,直到工作器返回结果。

通常这就足够了,但是假设我们有一个回调不支持的工作线程,或者网络中的另一个工作线程不可访问 Step 函数,使我们无法推送任务令牌。在这些情况下,我们如何整合员工?

活动Step Functions推出的首批功能之一—是解决这些问题的一个选项。大体上类似于回调,活动依赖于工人和令牌来协调异步任务。基本的区别在于步骤函数和工作器之间的关系:回调是基于推送的,活动工作器轮询任务。

一项活动是如何运作的?

一项活动有两个关键部分。首先我们有工人。这可以是一个 Lambda 函数,一个 EC2 实例,或者任何有效的运行代码的东西。工人使用活动的唯一的 Amazon 资源号 (ARN)来轮询任务的步骤函数。

当检索到一个挂起的任务时,worker 将获得一个惟一的任务令牌以及要处理的输入数据。worker 应用它的魔力,确定请求是成功还是失败,并将结果报告给 Step 函数。如果请求需要一段时间来处理,那么工作者也可以发送一个心跳来确认请求仍在进行中。

在步骤函数工作流中,我们获取活动的 ARN,并将其嵌入到新的活动调用状态中。该状态启动工作者轮询的新活动任务。当步骤函数执行到达调用状态时,工作流暂停,直到活动确认来自工作器的响应,或者活动超时。

来源:作者提供的图表

我们如何建立一个活动?

让我们使用最新版本的AWS Cloud Development Kit(CDK)for TypeScript 来提供一个 Step Functions 活动—在撰写本文时版本为 2.10.0。在本例中,我们将提供一个 Lambda 函数作为我们的活动工作器,并将它集成到一个只有三种状态的 Step Functions 工作流中:开始、活动任务和结束。

首先,我们使用 CDK 的Activity结构提供一个活动。活动的名称是可选的。我们将它合并到一个StepFunctionsInvokeActivity状态中,这将为我们的工人创建活动任务。最后,但同样重要的是,我们定义一个StateMachine来完成我们的步骤函数配置,将调用状态传递到定义中。

现在我们可以把注意力转向工人了。到目前为止,我们已经创建了一个活动,但是还没有工人处理它的任务。为这个例子选择一个节点 Lambda 函数,让我们提供一个NodejsFunction,将活动 ARN 作为环境变量传递,以便在函数代码中引用。

src/activityWorker.ts中定义 Lambda 类型脚本代码,我们使用 AWS SDK getActivityTask方法读取ACTIVITY_ARN环境变量和未决任务的长轮询。请注意,轮询可能会运行一分钟,而 Lambda 函数默认为三秒钟的超时,因此请确保将 Lambda 超时增加到一分钟以上。

如果发现一个挂起的任务,我们就要处理输入数据和任务令牌。使用一个基本的随机生成器来决定这个任务应该成功还是失败,我们可以根据结果将输出和任务令牌一起提供给 SDK 的sendTaskSuccesssendTaskFailure方法。

这就结束了工人逻辑!现在是最后的润色。让我们返回到 CDK,授予我们的 Lambda 函数身份和访问管理 (IAM)权限,以轮询并向 Step Functions 活动报告任务结果,并在 Lambda 函数上安排一个五分钟的调用速率以保持其热度。

从 AWS 控制台手动调用 Step 函数,我们观察到 pending activity 任务,它显示为蓝色,表示它正在进行中,直到我们的 Cron 调度调用 Lambda worker。根据调用和处理时间的不同,这将持续 7 分钟。当工人获取任务并报告成功或失败时,我们的步骤函数在控制台上共享这个结果。在失败的情况下,我们会看到一个异常选项卡,显示来自工作线程的调用状态的错误细节。

来源:作者截图

活动存在哪些限制?

活动工作者在高吞吐量下努力轮询未决任务。如果预计流量很大,请考虑对 SQS 队列使用回调,并将工作线程配置为轮询队列,而不是任务的活动。

结论

活动与回调有很大的相似之处,它提供了一种在 Step 函数中编排异步任务的替代方法。需要一点额外的工作来适应任务令牌的长时间轮询,活动不太可能是大多数异步用例的首选。

然而,当分离的工作者是必要的,或者回调不支持与工作者的集成时,活动仍然是一个有价值的选择。请记住高吞吐量的局限性,使用回调和 SQS 队列的替代方法可能更健壮。

本活动演练的完整代码库可从 GitHub 获得。如果你以前有使用阶跃函数活动的经验,或者更一般的阶跃函数,请告诉我。

博客于 2022 年 2 月 5 日发布,分享了关于活动工作者轮询和高吞吐量的限制,并推荐了使用回调和 SQS 队列的解决方法。感谢艾达·王分享这些。

Azure 数据工厂基本概念

原文:https://towardsdatascience.com/azure-data-factory-basic-concepts-e10448e54023

有很好的资源可以逐步学习 ADF,但是很少有对其基本概念的清晰解释。本文填补了这一空白。

Unsplash 上由 Carlos Muza 拍摄的照片

Azure Data Factory (ADF)是一个数据管道 orchestrator 和 ETL 工具,是微软 Azure 云生态系统的一部分。ADF 可以从外部世界(FTP、亚马逊 S3、甲骨文和更多的)获取数据,转换、过滤、增强数据,并将其移动到另一个目的地。在我为一个健康数据项目所做的工作中,我们使用 ADF 来驱动我们的数据流,从原始摄取到可以显示的完美分析。

有很多学习 ADF 的好资源,包括简介快速入门。然而,当我开始使用 ADF 时,我没有找到对它所基于的基本概念的清晰解释。本文试图填补这一空白。

让 ADF 为您做真正的工作涉及到以下几层技术,从您与之交互的最高层抽象一直到最接近数据的软件。

  • Pipeline,您放置小部件和绘制数据路径的图形用户界面
  • Activity,一个对您的数据做一些事情的图形小部件
  • 源和接收器,活动中指定数据来源和去向的部分
  • 数据集,ADF 可以操作的明确定义的数据集
  • 链接服务,允许 ADF 访问特定外部数据资源的连接信息
  • 集成运行时,一个粘合/网关层,让 ADF 与自身之外的软件对话

理解每一层的用途以及它对整体 ADF 解决方案的贡献是使用好该工具的关键。我发现从靠近数据的底部开始,以相反的顺序考虑各层,最容易理解 ADF。

集成运行时

集成运行时提供了 ADF 和您需要的实际数据或计算资源之间的网关。如果您使用 ADF 来编组本机 Azure 资源,如 Azure 数据湖或数据块,那么 ADF 知道如何与这些资源对话。只需使用内置的集成运行时,不需要考虑它——不需要设置或配置。

但是,假设您希望 ADF 操作存储在您办公桌下的 Oracle 数据库服务器上的数据,或者您公司专用网络中的计算机和数据。在这些情况下,您必须使用自托管集成运行时来设置网关。

这个屏幕截图显示了内置的集成运行时。它开箱即用,并且在您访问本机 Azure 资源时始终存在。

作者图片

链接服务

一个链接的服务告诉 ADF 如何看到你想要操作的特定数据或计算机。要访问特定的 Azure 存储帐户,您需要为其创建一个链接服务并包含访问凭据。要读/写另一个存储帐户,您需要创建另一个链接的服务。为了允许 ADF 在 Azure SQL 数据库上操作,您的链接服务将声明 Azure 订阅、服务器名称、数据库名称和凭据。

该屏幕截图显示了最常见的 Azure 存储(Azure Data Lake Gen 2 容器/blob)的标准链接服务。

作者图片

数据集

数据集使链接的服务更加具体;它描述了你在存储容器中使用的文件夹,或者数据库中的表,等等。

该截图中的数据集指向一个 Azure 存储帐户的一个容器中的一个目录。(容器和目录名称在参数选项卡中设置。)注意数据集如何引用链接的服务。还要注意,这个数据集指定数据是压缩的,这允许 ADF 在您读取数据时自动解压缩数据。

作者图片

源和汇

顾名思义,源和接收器是数据的来源和目的地。源和汇是建立在数据集上的。ADF 主要关心的是将数据从一个地方移动到另一个地方,通常在移动过程中会进行某种转换,因此它需要知道将数据移动到哪里。

理解数据集和源/汇之间模糊的区别是很重要的。数据集定义了特定的数据集合,但是源或接收器可以重新定义该集合。例如,假设 DataSet1 被定义为文件夹/Vehicles/GM/Trucks/。当一个源使用 DataSet1 时,它可以原样使用该集合(默认),或者将集合缩小到/Vehicles/GM/Trucks/Silverado/或者扩展到/Vehicles/。

数据集范围和源/接收器范围之间的权衡涉及到巧妙的设计。我的做法是稍微宽泛地定义数据集(从而减少数据集的数量),然后允许源和接收器缩小各自在特定情况下的需求。

这个源使用上面显示的压缩数据集,缩小它的范围,并确保只选择实际命名为*的文件。zip(否则解压缩会失败)。

作者图片

活动

活动是数据工厂中的 GUI 部件,执行特定类型的数据移动或转换。有一个移动数据的 CopyData 活动,一个遍历文件列表的 ForEach 活动,一个选择文件子集的 Filter 活动,等等。大多数活动都有一个源和一个汇。

管道

ADF 管道是您最直接使用的顶级概念。管道由活动和数据流箭头组成。您可以通过创建管道来编程 ADF。您通过运行管道来完成工作,无论是手动还是通过自动触发器。您通过监控管道执行来查看工作结果。

作者图片

该管道从初始数据湖文件夹中获取入站数据,将其移动到 cold archive 存储,获取文件列表,遍历每个文件,将这些文件复制到解压缩的工作文件夹中,然后根据文件类型应用额外的过滤器。

结论

本文描述了 Azure 数据工厂的基本概念和操作。ADF 还能够进行更复杂的转换,比如在数据块中运行 PySpark 代码、调用自定义虚拟机、进行 webhook 调用等。移动和转换完成后,数据可以被传送到各种目的地,包括 SQL 数据库、普通文件系统和出站 FTP。

有关更多信息,请参见:

Azure DP-100 考试指南:你需要知道的一切

原文:https://towardsdatascience.com/azure-dp-100-exam-guide-everything-you-need-to-know-9f6f84d863d3

通过 Azure 数据科学助理认证考试:在 Azure 上设计和实现数据科学解决方案(DP-100)

文章最后更新时间:2022 年 3 月

我的蓝色数据科学家徽章照片

介绍

所以你想成为认证 Azure 数据科学助理?你来对地方了。这篇文章包含了你需要知道的关于 DP-100 的一切,这是微软 Azure 的云计算和数据科学证书,测试你使用 Azure ML 设计和实现机器学习解决方案的能力。

在列出考试规格后,我们将开始浏览 DP-100 考试的内容以及您将会遇到的 5 种题型。然后,我们将回顾一些准备工作的注意事项,我将介绍哪些资源应该学习,哪些应该避免。一旦你准备好参加考试,我会告诉你如何安排考试以及考试当天会发生什么。

考试规格

DP-100 是一个中等难度的考试(比 AZ-900 更难,更接近 AWS MLS-C01)。

  • 长度:40–60 个问题
  • 时长: 120 分钟时限
  • 考试价格:165 美元
  • 题型:选择题(一到两个正确答案),填空题选择完成代码,情景型题型,顺序重排(无案例分析)。回答错误不会受到惩罚。
  • 及格分数:700/1000 分(70%)
  • 考试最后更新:2021 年 5 月 20 日
  • https://trainingsupport.microsoft.com/en-us/mcp/forum/all/dp-100-retake-policy/08140240-3cfc-4ec8-bf69-74de8917722c****:第一次失败后 24 小时等待期。第二次、第三次和第四次失败后的 14 天等待期。第 5 次故障后的 1 年等待期。
  • ****测试环境:通过培生 VUE 在线或现场。

考试内容

考试内容分为四个部分:

  1. 管理机器学习的 Azure 资源(占考试的 25-30%)
  2. 运行实验和训练模型(20–25%)
  3. 部署和实施机器学习解决方案(35–40%)
  4. 实施负责任的机器学习(5–10%)

我强烈推荐阅读官方认证技能大纲,了解更多关于考试内容的细节。

题型

正如考试规范中提到的,考试有五种不同类型的问题。回答不正确是没有惩罚的,所以一定要回答好每一个问题。您还可以获得问题的部分学分(如果适用)。除了基于场景的问题,通过皮尔逊 VUE 在线考试时,问题可以标记为待复习。

  1. 有 1 个正确答案和 3 个错误选项的多项选择。
  2. 有两个正确答案和三个错误选项的多项选择。
  3. ****用选项填空来完成代码。对于这些问题,您将获得一个潜在解决方案“库”,并被要求选择合适的行来填空。代码块将几乎总是使用用于 python 的 Azure 机器学习软件开发工具包(SDK)。事实上,对于这个考试,你需要知道的唯一代码是用于 python 的 Azure ML SDK,以及对 Azure 命令行界面(CLI) 的一些基本熟悉。下面是这种题型的一个例子。

免责声明:所有这些例题都是我为了说明 DP-100 题的风格而写的。内容基于 Microsoft Learn 提供的 Azure 机器学习实验室代码,而非基于任何实际或练习考试问题。

Fill-in-the-blank example question: You want to write code to connect to your Azure ML workspace. Fill in the blank with the option that completes this code block.**import** azureml.core
**from** azureml.core **import** Workspace

*# Load the workspace from the saved config file*
ws **=** ________**.**from_config()"Bank" of Options: 
- print
- Workspace
- log
- Experiment Correct Answer: Workspace.

4.序列重新排序。在这种问题类型中,你会得到一项任务和一系列后续行动。这个问题会告诉你完成这个任务总共需要多少步。你的任务是从列表中选择正确的动作,并按正确的顺序排列。这里有一个例子。

Sequence Reordering example question:You're working for a large consulting firm, and you want to train a machine learning model for computer vision using Azure ML. Using images from your colleagues, you want to create a neural network that categorizes new images as either cats or dogs. What four steps do you need to do to train your model?"Bank" of Steps: 
1\. Submit your experiment run 
2\. Create a ScriptRunConfig object to connect your training script to your environment
3\. Create a batch inferencing service to make inferences overnight
4\. Create a training script to train your model 
5\. Connect to your workspace
6\. Create an EqualizedOdds object to detect unfairness in your model. Correct Answer: 5 -> 4 -> 2 -> 1\. Note that 3 and 6 were not used.

5.基于场景的问题。这个问题类型从描述 Azure ML 解决方案的一个常见问题开始。然后,它提出了一个潜在的解决方案。你的工作是确定这个解决方案是否真的能解决问题。此部分不可查看,因为这些情景将被重复使用,所以一旦您单击“下一步”,您的答案将被固定下来,您将无法再看到。这些基于场景的问题每套 3 个,出现在 DP-100 考试的最后。这里有一个例子。

Scenario-Based example questions:Question 1: This scenario will be reused for the next three questions. You've written some code to use AutoML to train a binary classification model. Your training dataset is heavily imbalanced with 10 times as many negative classes relative to positive classes. Unfortunately, your code fails to run. After asking a colleague to review your code, she finds that you're missing a line in your AutoMLConfig. She inserts code below (at <<< insert line here >>>):automl_config **=** AutoMLConfig(name**=**'Automated ML Experiment',
                             task**=**'classification',
                             compute_target**=**training_cluster,
                             training_data **=** train_ds,
                             validation_data **=** test_ds,
                             label_column_name**=**'Diabetic',
                             iterations**=**4,
                             <<< insert line here >>>,
                             max_concurrent_iterations**=**2,
                             featurization**=**'auto'
                             )She adds the line "vm_size**=**'STANDARD_DS11_V2'". Does this actually solve the problem? Correct Answer: No. Question 2\. <<<Scenario repeated>>> This time, she adds the line "primary_metric **=** 'AUC_weighted'" Does this actually solve the problem? Correct Answer: Yes.Question 3\. <<<Scenario repeated>>> This time, she adds the line "primary_metric **=** 'normalized_mean_absolute_error'" Does this actually solve the problem?Correct Answer: No.

准备注意事项

这里有一些帮助我第一次通过 DP-100 的学习技巧。

  • 一定要利用微软免费的 DP-100 学习路径。微软提供免费资源帮助您准备 DP-100 考试。使用 Azure Machine Learning 构建和运行机器学习解决方案学习路径提供了 15 个与 DP-100 考试内容一致的高质量内容模块。虽然你可能不需要阅读每个模块的每个单词,但这是开始准备的好地方。每个模块还以知识测验结束,这是一个测试您对材料理解程度的小测验。最起码在考试前要确定自己能通过每一项知识检查。
  • ****一定要花时间学习 python 的 Azure ML SDK。为了通过 DP-100 考试,你需要非常好地理解用于 python 的 Azure 机器学习 SDK。最好的方法是查看微软 Learn 提供的 Azure 机器学习实验室。这些实验由微软编写,并在他们的讲师指导的 DP-100T01 课程中使用,因此它们保证是最新的,并与考试材料相关。
  • ****务必创建一个 Azure 免费试用帐户,获得 Azure ML 的实际操作体验。微软提供 200 美元的 Azure 信用,在创建你的 Azure 帐户的前 30 天内使用(详情在此)。我强烈建议利用这一点来尝试一些 Azure ML 学习实验室。
    专业提示:如果您用完了 200 美元的信用点数或者已经使用了您的主电子邮件地址,只需创建一个新的 Outlook 电子邮件地址,并使用该地址进行免费试用。

以下是我建议你在准备过程中避开的一些事情。

  • 不要使用在线 DP-100 考试转储。如果你在谷歌上搜索任何云认证考试,你一定会找到考试垃圾网站。考试转储网站包含过去考试的真题,由过去参加过考试的人编辑。不幸的是,由于许多原因(除了违反版权法之外),考试垃圾不是好的学习材料。首先,微软测试制造商也有谷歌。考试经常轮换和更新,Microsoft 会保持警惕,以确保考试转储中出现的问题不会出现在实际考试中。其次,DP-100 考试的实际内容也随着时间的推移而演变,所以也不能保证过去 DP-100 考试中的问题会覆盖与现在考试相同的材料。最后,也是最重要的一点,访问考试转储可能会让你终身被禁止参加微软认证,同时你当前的考试成绩也会立即不及格(还记得我提到的版权法吗?).说真的,不要使用考试垃圾。
    注:如果你真的在找练习题,我推荐 WhizLabs (不是赞助,很遗憾)。我使用了 WhizLabs 的练习测试来熟悉问题风格,发现它们相当准确地代表了实际测试。
  • ****学习时不要忽略考试内容分布。每个考试内容板块旁边的百分比都是你的朋友!你应该计划在学习时根据这些百分比来分配你的注意力。尽管了解不同的隐私和 SHAP 价值观很有趣,但请记住,它们只占整个考试的 5-10%(60 道题的测试中有 3-6 道题)。另一方面,当前测试的 25–30%是关于 ML 的 Azure 资源管理,这意味着更好地利用你的时间来熟悉 Azure 的基础知识。
  • ****别忘了花点时间使用自动化 ML 和设计师可视化工具。虽然你应该花很多时间关注用于 python 的 Azure ML SDK,但是要确保你也熟悉 Auto ML 和 Designer 可视化工具。大多数学习计划,包括微软自己的 DP-100 学习计划,在开始时简要介绍这两个工具,然后深入 python SDK。一定要在考试前再次重温 Auto ML 和 Designer,因为你可能会得到一些关于这些功能的问题。

安排考试和考试日提示

一旦你差不多准备好了,前往微软官方考试页面,点击按钮开始安排你的考试。考试时段的可用性各不相同。如果有空的话,你可以把考试安排在第二天,但是未来几个月也有空。我建议你提前一两周安排考试。如果您还没有认证资料,请准备创建一个认证资料,验证您的一些个人信息,并提供 165 美元考试费用的支付方法。

您还可以选择亲自参加考试还是通过皮尔逊 VUE 在线考试。我决定参加在线考试,所以我不能对现场监督发表评论,但我会说我在皮尔逊 VUE 的经历非常积极。这里有一些小贴士,可以让你在皮尔森 VUE 的经历尽可能顺利。

  • 确保你的考试空间是安静的,并且在考试期间你不会被打扰。为了防止作弊,如果你考试时有其他人和你在一起,你的考试成绩可能会作废。皮尔逊 VUE 软件还将使用你的计算机的麦克风记录你考试时发出的任何声音,以防止通过音频信号作弊。这也意味着你需要在整个考试中保持沉默——不要大声朗读问题,因为这可能会导致失格。
  • 确保你的考试空间尽可能的空着。你需要在考试前拍四张你的考试区域的前、后、左、右的照片。在拍摄这些照片之前,请确保移除任何纸张、铅笔、外部键盘或鼠标等。符合测试规则。你不允许在测试过程中书写(尽管你可以使用虚拟记事本)或使用外部设备,所以最好清理你的测试区域。
  • 考试时要注意你的眼睛。您的前置摄像头将记录您的整个测试过程,并且您将在整个过程中受到皮尔森 VUE 监考人的监控。如果你在考试时不看电脑屏幕,会让人怀疑你可能作弊。如果你是那种喜欢在思考的时候盯着远处看的人,那么在考试的 120 分钟里,尽你最大的努力抵制这种冲动。

尽管这些规则看起来很多,但在测试过程中并不明显。如果你没有作弊,你真的没有什么好担心的。想象一下,你回到了高中,遵循你在真实课堂上遵循的规则——保持沉默,眼睛盯着考试,不要从任何人或任何事物获得帮助。

如果你已经做到了这一步,恭喜你!你正在顺利通过 Azure 数据科学助理认证考试。最后一点:永远记住认证只是你学习之旅的开始,而不是结束。一旦你获得认证,你就要好好利用这个认证——无论是工作还是个人项目。

祝你考试顺利,认证愉快!

量子机器学习的一小步

原文:https://towardsdatascience.com/baby-steps-to-quantum-machine-learning-796715c19d32

理解与量子机器学习相关的基本概念并训练虹膜数据集的混合模型

特里·维里斯迪斯在 Unsplash 上的照片

量子机器学习是科技领域的下一步。在本文中,我们将了解机器学习中量子所涉及的基本概念。然后,我们将了解如何使用 Iris 数据集训练具有 Keras 和 Pennylane 的多类混合分类器。 代号

基本概念

量子化学中的表示可以用下图来理解,假设有 3 个能级,每个能级有 2 个电子,一个电子将有向上的自旋,而另一个将有向下的自旋。

量子化学,再现(图片由作者提供)

第二张图中,一个电子在第一能级自旋向下,一个电子在第三能级自旋向上。

在量子机器学习中,我们利用这个概念并定义电路,其中我们有几个功能,例如为一个能级提供 X、Y 和 Z 轴上的旋转,在能级之间打结,分裂等。

Q 节点:

一个 Q 节点由一个电路和一个在其上执行该电路的设备组成。

设备:

这里有一个可以使用的设备列表(https://pennylane.ai/plugins.html)。通常使用“默认量子位”。对于用于训练 Iris 数据的混合模型,我们将使用“strawberryfields.fock”设备。这些设备被用作插件,因此请确保插件已安装。对于 strawberryfields,运行以下命令进行安装:

pip install PennyLane**-**SF

让我们来定义设备:

dev **=** qml**.**device("default.qubit", wires**=**num_modes)

电路:

电路图(左),等效代码(右),图片作者

我们定义了左图中给出的电路。有 2 根线,0 和 1。如果我们把它看作一个时间序列,首先在电线 1 上有一个 X,

qml.PauliX (wires = 1)

那么从导线 0 到 1 有一个交叉点,

qml.CNOT (wires = [1, 0])

然后在 0 号线有一个θ角的旋转。

qml.RY (theta, wires = 0)

输出 Z 也沿着 Z 轴从线 1 出来。

qml.PauliZ (wires = 0)

最后,我们沿着 Z 轴返回期望值。

qml.expval ()

现在,我们知道了器件和电路,我们可以很容易地通过装饰器定义一个 Q 节点。

q 节点(图片作者提供)

现在,让我们从-π到π改变角度,看看电路函数值。

电路(theta) v/s -π,π

因此,当我们试图优化电路时,从机器学习的角度来看,我们试图找到可以实现最小值(即-1)的权重值。给定随机权重作为电路的输入。一般来说,我们不知道这个图看起来像什么,因此我们使用优化器。

An ansatz一个电路的基本架构,即一组作用于特定子系统的门。该架构通过固定可训练参数来定义变分电路可以实现哪些算法。电路 ansatz 类似于神经网络的架构

混合模型

现在,我们已经了解了基础知识,让我们来定义混合模型的架构:

高层混合架构(图片由作者提供)

密集层:

虹膜数据集有 4 个特征,作为输入。之后,我们有 2 个 14 通道的密集层,它们将被馈送到数据编码层或电路。通过直接不将特征馈送到量子电路并使用密集层,我们允许输入更加灵活,并且能够知道应该将什么输入提供给电路。

密集层(图片由作者提供)

量子层:

首先,我们将 14 个通道编码为一个电路,然后每个通道通过一个量子神经网络,该网络由 Keras 和 Pennylane 库定义。对于电路,我们有 2 条线和 14 个输入。

数据编码层(图片由作者提供)

来自数据编码层的输出被馈入下面定义的量子神经网络。

量子神经网络(图片作者提供)

输出:

输出是一个 16 维向量。3 用于输出标签,13 用于填充 0。当我们处理量子机器学习时,电路的输出不可能是标签总数的一次性编码。因此,我们需要为它定义一个自定义的独热编码函数,它的维数将大于类的数量。

例如,如果有 3 个类,一键编码将有 8 个维度,3 个用于实际类,其余 5 个用 0 填充。

标签的一个热编码(作者图片)

整体模型架构如下所示:

_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 dense (Dense)               (None, 14)                70        

 dense_1 (Dense)             (None, 14)                210       

 keras_layer (KerasLayer)    (None, 4)                 56        

=================================================================
Total params: 336
Trainable params: 336
Non-trainable params: 0
_________________________________________________________________

这些是经过 30 个时期训练后的结果。

训练和验证分割的准确性和损失图(图片由作者提供)

本文着重于理解量子神经网络的功能及其背后的概念。量子机器学习在计算和学习能力方面优于现在使用的传统机器学习方法。在未来的博客中,我会写更多关于传统数据集的用例,如 MNIST、CIFAR10 等。让我知道你对此的想法。

参考文献:

Pennylane 演示

连续变量量子神经网络

回到基础:重新审视负责任的人工智能框架

原文:https://towardsdatascience.com/back-to-basics-revisiting-the-responsible-ai-framework-847fd3ec860b

责任人工智能系列

筛选数十个现有框架,为负责任地使用和部署算法决策系统创建一个健壮的心智模型

来源:作者图片

在过去的几个月里,我们已经看到了在为人工智能建立安全措施方面有希望的进展。这包括具有里程碑意义的关于人工智能的欧盟监管提案,该提案禁止不可接受的人工智能使用,并强制要求对高风险系统进行披露和评估,英国政府推出的算法透明标准,纽约市对人工智能招聘技术的强制审计,以及 NIST 应美国国会要求开发的人工智能风险评估框架草案,等等。

话虽如此,我们仍处于人工智能监管的早期。要将算法系统可能造成的伤害降至最低,还有很长的路要走。

在这一系列文章中,我探索了与负责任地使用人工智能及其社会影响相关的不同主题。我特别关注两个重要的想法:

  1. 算法系统有意义的透明度是有效问责机制的重要前提——但在实践中很难实现;
  2. 公共利益团体,如倡导者、活动家和记者,以及公民个人,目前在揭露人工智能危害方面发挥着关键作用——但他们在目前提出的任何监管中都没有有意义的作用。

在我深入这些主题之前,重要的是从一个健壮的心智模型开始,它充分反映了在社会层面促进负责任地使用人工智能的复杂性。

框架,框架,更多框架!

我首先回顾了由各种公司、政府和研究机构开发的现有人工智能框架、指南和章程。如下图数据库所示,被引用最多的 AI 原则是“公平”,紧随其后的是“透明性”、“可解释性”、“安全性”、“鲁棒性”和“安全性”。

人工智能伦理现有框架的数据库——由作者创建。要向该数据库提供来源,请填写此表格

这些现有的关于人工智能的框架大多在范围上是有限的。它们要么提供一般的非约束性指导,要么仅适用于特定的组织(或一组组织)。需要一个全面负责的人工智能框架,考虑到利益相关者的冲突优先级,并保护受影响的群体免受伤害。

制定综合框架

伦理人工智能的综合框架应包括以下内容:

  • 明确定义对象进行评估(→AI 系统);
  • 理想的广泛认同得以实现;
  • 明确的原则有助于实现我们的既定理想;
  • 一组利益相关方团体,他们有明确的职责来帮助促进我们理想的实现。

1。定义正确的“单位”或系统

评估人工智能部署的正确“单位”是什么?大多数框架模糊地指人工智能系统,其他的指个别算法。在不了解算法如何影响更广泛系统的整体结果的情况下,对单个算法的评估是没有意义的。此外,执行决策的系统可以由几个自动或人工执行的步骤组成。每个自动化步骤都可以与一个或多个算法联系起来,这些算法可能使用不同级别的复杂人工智能。因此,从整体上考虑决策系统是很重要的,因为故障可能发生在几个独立算法中的一个或它们的互操作性中,同时不要忘记潜在的人为错误。

算法决策系统的组成部分。来源:作者图片

在这篇文章的其余部分(以及接下来的部分),我将把算法决策系统(ADS)称为一个单独的评估单元。ADS 是指引入算法系统,帮助部分(或全部)决策过程程序化和自动化。

ADS 通常由以下内容组成:

  • 算法和计算处理技术(各种复杂程度,从基于规则到神经网络);
  • 支持数据集(可能包括敏感的个人身份数据或其他机密数据);
  • 人在循环中(前者主动审查每个决策,后者监督整个系统的性能)。

不是所有的广告都应该优先评估。一般来说,我们所说的“高风险”系统是指那些管理服务、福利、受到的惩罚以及获得机会(如招聘)的系统,因为系统故障会对受影响的个人造成重大伤害。

2。定义正确的“理想”

现有的框架驱动以下三个理想之一:道德、信任、责任

伦理学具有道德义务的哲学内涵。我们不能正确地将道德人工智能称为“支撑人工智能解决方案的能力[……]没有道德或不道德、值得信任或不值得信任之分。”相反,我们对算法系统做出的选择可能具有道德或不道德的属性。促进广告方面的道德行为是一个值得努力的伟大理想。然而,它也可能是一个模糊的理想,为道德义务要求的不同解释敞开大门。

至于信任,企业倾向于关注这一理念,因为它支撑着他们产品和服务的采用。信任一项技术意味着相信它会达到你的期望。这种“信任”的概念模糊了责任结构。如前所述,人工智能并不是天生值得信任或不值得信任的。赋予这些属性的是围绕其开发和在特定环境中的使用而做出的选择。

我们目前观察到许多情况,企业通过组织自己的方式将责任从决策中心转移开来避免广告失败的责任。

算法决策系统造成伤害,不是因为它不可信,而是因为系统所有者没有以负责任的方式设计、开发、测试、部署或维护它。

因此,我认为我们应该驾驶的“理想”是责任而不是信任。从社会福祉的角度来看,我们应该专注于促进和保护对人工智能等技术的负责任的使用,并让组织对如何使用和实施这些技术负责。

负责任的广告使用挑战了“责任缺口”的概念——这种概念认为,鉴于人工智能的性质,可能更难分配造成伤害的责任。

在理想状态下,应该有集体责任,其中:

  • 系统所有者负责开发、部署和监控他们的算法系统,以避免伤害;
  • 系统用户接受了关于广告局限性的充分培训,并有能力对系统结果进行推理;
  • 受影响的群体有权提供反馈,标记伤害并寻求帮助;
  • 政府行为者有责任制定适当的监管保障措施,并建立申诉渠道。

3。确定支持实现我们“理想”的核心原则

为了实现负责任地使用广告,我们需要定义两套互补的原则:

  • “什么”:体现负责任使用理想的原则(简称一阶原则)。这些原则可用于评估广告的设计和部署。
  • “如何”:我们用来确保符合一级原则并纠正失败的原则(称为二级原则)。这些原则对于确保我们实现负责任的使用理念是必要的。

管理负责任使用广告的一级和二级原则。来源:作者图片

一级原则的构成可能会随着时间的推移而演变,并取决于一个地区或行业的具体情况。根据我对现有框架的评估,负责任的 ADS 部署是:

  • 公平和非歧视:积极评估、监控和减少偏见;旨在产生经过适当调整的更公平的结果和决策
  • 可解释的:能够为做出的决策提供可解释的理由
  • 安全:制定有效的控制措施,保护系统免受威胁;主动标记和缓解漏洞
  • 稳健:始终符合精度和性能要求,对扰动具有稳健性
  • 维护数据隐私权:保护直接和间接用户的数据隐私权,并遵守现有的数据法律
  • 安全:避免对受影响用户的伤害,旨在促进人类福祉

二阶原理对于确保符合上述要求是必要的。其中包括:

  • 确保广告的透明度:在基本层面上,透明度转化为系统可见性,在更复杂的层面上,它反映了系统在一阶原则上的表现。关于透明度的更多细节将在后续文章中提供。
  • 确保 ADS 系统的责任性:这是指系统的所有者能够解释他们的行为(和失误)并对其负责。广告透明度是实现问责制的先决条件。问责制可以通过评估、审计和反馈循环来实施。
  • 保留人力代理和追索的可能性:当 ADS 失败并对个人产生不利影响时,相关个人应遵循明确的追索流程,以便纠正错误。应该建立强有力的透明度和问责机制,以便能够进行追索。

4。确定相关利益相关者及其职责

最后,我们需要确定参与 ADS 的相关利益相关者,并阐明他们在确保负责任的使用和部署中的角色。

三大利益攸关方群体:系统所有者、公共实体和民间社会。来源:作者图片

我们可以确定三大利益相关方群体:

  • 系统所有者:包括一个或多个负责调试、设计、开发和维护 ADS 的实体。在理想状态下,试运行实体应负责根据负责任使用原则建立供应商的采购要求和义务。
  • 公共实体:这些实体包括负责管理广告使用、评估广告并让系统所有者承担责任的实体。正如已经证明的那样(此处此处此处),大型科技公司的自我监管不利于社会福祉。在理想状态下,公共实体应该提供外部责任,以确保遵守 ADS 法规。
  • 公民社会:这包括受广告影响的个人群体以及公共利益团体,后者由研究、学术和倡导组织组成,致力于保护和倡导公民社会的权利,特别是边缘化群体的权利。鉴于大多数国家缺乏全面的广告监管,公共利益团体历来是外部透明度和问责制的唯一驱动力。想想 ProPublica 新闻调查揭露 COMPAS 偏见累犯算法的文章,或者麻省理工学院研究人员揭露亚马逊面部识别软件的偏见。在我的文章中,我认为,即使存在充分的监管,公共利益团体仍应在代表公民社会利益和提供外部问责方面发挥积极作用。这些群体应该被正式纳入设计和部署广告的过程中,尤其是高风险群体。

把所有的放在一起

接下来,我们应该绘制各种利益相关者如何执行行动,以确保负责任地使用算法决策系统。

“负责任地使用算法决策系统”的综合框架。来源:作者图片

上面的框架代表了一种理想状态,在这种状态下,公共实体是系统的主要守护者。它还需要明确的广告所有权和责任,并依靠公共利益团体的支持来补充外部监督。

我们目前离理想状态还很远,因为:

  • 大多数国家没有国家级广告原则;
  • 大多数政府还没有能力或权力来管理和监督广告的使用;
  • 在没有既定要求或为各方分配责任的情况下,广告的所有权经常被供应商和第三方混淆;
  • 目前,公共利益团体承担了提供广告问责的巨大责任,但履行这一职责的途径和资源有限。

更深入:透明度的角色

负责任使用框架中,透明是一个强有力的原则。它有助于通过公共利益团体的工作实现“需求方”问责制,从而使系统所有者的激励与受影响的群体保持一致。然而,在现状中,无论是公共部门还是私营部门,大多数高风险广告的部署都受到不透明性的困扰。我们对这些系统的存在缺乏基本的了解。最起码,公民应该有权利知道他们在做什么广告。在某些情况下,这些系统只有在危害被发现并开始公共审查过程后才变得可见。这些因素导致了公众对算法系统的不信任,并引发了对问责制和追索权的严重关切。

https://medium.com/@mayamurad/fighting-back-on-algorithmic-opacity-30a0c13f0224

基于我的研究生论文“ 《超越黑盒 ”(麻省理工学院 2021)的一系列关于负责任的人工智能的一部分。提出的想法是基于几个在管理、部署和评估人工智能系统方面有直接经验的从业者的反馈和支持而发展起来的。我正在分享和开源我的发现,以使其他人能够轻松地研究并为这个领域做出贡献。

回到“位-系统”:位、指针和内存

原文:https://towardsdatascience.com/back-to-bit-sics-bits-pointers-and-memory-8c0eb125a0b7

数据科学家用 C 语言解释位、指针和内存

穆罕默德·拉赫马尼在 Unsplash 上的照片

我是物理学出身,没有接受过任何正规的计算机科学教育。然而,作为一名数据科学家,我觉得有必要更好地掌握这个学科,同时也是出于好奇,想学习一些新的东西。

所以,没有比世界上最好的 CS 大学,斯坦福更好的学习地方了。他们免费开放了很多课程,你可以在这里https://online.stanford.edu/free-courses查看。我最近一直在研究他们的 CS107 计算机组织&系统 这深入到编程语言 如何真正 在幕后工作,以及它们如何与硬件交互。这门课是用 C 语言讲授的,这也是我正在努力学习的东西,因为它被认为是一种“低级”语言,所以它能让你更好地理解计算机是如何工作的。****

在这篇文章中,我解释了我觉得有趣的课程的第一部分,也巩固了我的理解。这些也是数据科学家应该了解的概念。

二进制数字

计算机基本上是一群晶体管,根据电流是否通过,它们有两种状态:开、T21 和关。这种情况的数学表示称为二进制数字或位

位可以访问两个状态 01 并且可以组合成任意数。然而,使用二进制意味着我们是在一个基数为 2 的数字系统中工作,因为我们只有两个数字可以使用。在全球范围内,我们使用的是十进制数系统,称为十进制数。十进制包含以下: 0,1,2,3,4,5,6,7,8,9 作为我们都知道并且喜爱的 10 个数字。以下是十进制到二进制转换的一些示例:

由作者用乳胶创作

注意到模式了吗?第一位是 2⁰,第二位是 2,第三位是 2 等等。如果该位的值为 1,则它为‘开’,因此它取值为 1、2、4 等。然后将等于 1 的所有位相加,得到十进制数。

十六进制的

位是伟大的,但是我们经常处理长度为 32 或 64 位的大数。因此,我们用被称为十六进制16 进制数字系统来表示比特。十六进制有 16 个数字: 0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f 。因此,当 2⁴ = 16 时,一个十六进制数反映了一个 4 位二进制序列,这也被称为半字节

下面是一些选定数字的十进制、二进制和十六进制转换表:

由 LaTeX b 作者创建

让我们通过一个例子来获得更好的直觉。我们将使用十进制数 77 的大小写。我们知道,4 = 0100,13 = 1101 = d,因此 4d 是这两个二进制值的组合,等于 01001101。它们基本上是相互连接的。这个数字的最高有效位是 2⁶ = 64。其他有效位为 2 = 8、2 = 4 和 2⁰ = 1。如上所示,所有这些有效位的总和为 77。在你反复练习几次之后,这种转换并不太难。

计算机存储器

尽管位是计算机中的基本值,但计算机的内存地址只是在字节可寻址范围内,字节等于 8 位。

在 21 世纪初,大多数电脑都是 32 位的。这意味着他们有 2 个唯一的数字,这意味着只有 2 字节的可寻址内存位置!从这个角度来看: 2 字节= 4GB 的 RAM!这个很小,所以现在的电脑是 64 位的,内存是 16 兆字节。然而,当前的能力硬件不能充分利用这个可用的 RAM。

这意味着当你给一个变量赋值时,例如 x=2 ,在你的代码中,这个变量有它自己的唯一内存地址。如果您使用的是 32 位计算机,这个地址只是两个可用地址中的一个。不要说太多细节,主要是因为我自己也不完全理解,这些内存地址不是硬件中的实际物理地址,而是操作系统分配的虚拟地址。然而,可以使用页表将它们转换成物理地址。

此外,32 位计算机的 4GB 内存限制并不全面。有使用 物理地址扩展 的变通办法,将 32 位计算机的 RAM 可用性提高到 64 GB 左右。

两颗北极指极星

在 C 语言中,我们可以使用指针来处理这些内存地址这些是变量T5,其值是另一个变量的内存地址。我们可以通过使用 ' & ' 符号得到任意变量的内存地址。例如:****

int main(){ int x = 2; /* variable declaration */ printf("%p\n", &x ); /* printing the address of x */ return 0;}

这段代码的输出是:

0x7ff7b57ac948

****‘0x’表示数字是十六进制的,如果是‘0b’那么就是二进制的。在那里变量 x 的地址是十进制的 140,701,878,372,680 ,所以大约是第 140 万亿个内存地址!我的电脑肯定是 64 位的!

如前所述,指针指向变量的内存地址,而不是它的值。这意味着即使 x 的值改变,指针仍将为 x 产生相同的地址。使用如下的 ***** 语法声明指针:****

int main(){

 int x = 2; /* variable declaration */
 int *xptr; /* pointer variable declaration */ xptr = &x; /* store address of x in pointer variable*/ printf("%p\n", &x); /* printing the address of x */
 printf("%p\n", xptr); /* printing the pointer variable */ return 0;}

这里我们将 xptr 分配给 x 的地址。下面的输出是:

0x7ff7b57ac9480x7ff7b57ac948

其中指针指向 x 的地址,因此它们都像预期的那样返回相同的内存地址。

一个指针可以被解引用,方法是将它打印为一个带符号的整数%d,(带符号意味着它可以是正的也可以是负的),但是在指针变量之前分配*语法。下面显示了一个示例:

int main(){ int x = 2; /* variable declaration */
 int *xptr; /* pointer variable declaration */ xptr = &x; /* store address of x in pointer variable*/ printf("%p\n", &x); /* print the address of x */
 printf("%d\n", *xptr); /* printing the value stored at pointer */ return 0;}

的输出是:

0x7ff7b57ac9482

我们得到了预期的值 2,因为这是 x 的内存地址。

有许多更复杂的方法来操作和使用指针。它们是非常有用的变量,可以教你很多关于内存在程序中是如何工作的,这是无价的。

摘要

在本文中,我们简要讨论了位、十六进制和使用指针操作内存地址。老实说,作为数据科学家,我们不会处理如此低级的代码,所以没有必要成为这些领域的专家。然而,这些都是很好的学习和理解的基本概念,因为它们提高了您对其他语言的了解,尤其是 Python,因为其中一些是用 c 语言编写的。这增强了您作为数据科学家的整体能力。

和我联系!

(所有表情符号都是由 OpenMoji 设计的——开源的表情符号和图标项目。执照: CC BY-SA 4.0

对语言模型的后门攻击:我们能信任模型的权重吗?

原文:https://towardsdatascience.com/backdoor-attacks-on-language-models-can-we-trust-our-models-weights-73108f9dcb1f

像素|像素贝

NLP 中依赖不可靠来源的潜在风险入门

问题是

在过去的十年中,预先训练的通用语言模型在自然语言处理(NLP)中变得非常流行,允许任何开发人员/研究人员利用有限的数据非常少的从头编写和设计神经网络的知识来构建竞争性模型以解决特定领域的问题。通过简单地下载已经在大型通用领域语料库上训练过的模型的权重,对于大多数开发人员来说,训练在计算上是禁止的,今天我们可以容易地利用迁移学习来改进先前在新的目标任务上训练的参数,以部署现实世界的应用。

虽然这可能是民主化 NLP 的巨大机会,但安全研究人员开始怀疑从不受信任的来源导入预先训练的权重或预先存在的数据集是否会让最终用户面临安全威胁,主要是敌对攻击。我们最终可以将研究人员的担忧归结为以下问题:

是否有可能通过调整权重来影响微调后的 NLP 模型的预测,在最终模型上分布攻击者仍可触发的后门?

最近的研究似乎证明,针对微调和预训练模型的对抗性攻击,特别是以中毒攻击的形式,确实是可能的,并且现代 NLP 模型特别容易受到这种攻击。

对交通标志进行物理更改以欺骗自动驾驶汽车的示例。(摘自唐等译 2020 )

机器学习中的对抗性攻击

在过去的几年里,深度神经网络对小扰动表现出的脆弱性已经成为人工智能研究人员和人工智能公司的严重问题

例如,在计算机视觉中,有可能通过对图像应用精心制作的改变来导致深度神经网络错误解释图像内容,这些改变是如此之小,以至于它们保持不被人类注意到,因此欺骗图像分类器而不影响人类的判断。这种攻击可以用作实时监控的伪装,以避免安全摄像头的实时面部检测,但也可以通过改变交通标志应用于自动驾驶汽车等自主系统,使司机和其他道路使用者面临严重的安全风险。

同样基于深度神经网络,像 BERT 这样的现代 NLP 模型确实可能成为相同攻击方案的受害者。即使在视觉效果上不如计算机视觉攻击,NLP 攻击在情感分类、毒性检测或垃圾邮件检测等任务中同样具有威胁性。

NLP 模型中的数据中毒和后门攻击

执行对抗性攻击的最常见方式之一是通过改变(即,毒害)训练数据。中毒训练集是一个数据集,其中在干净的数据集中替换了一个特定的、固定的“触发”罕见词(或计算机视觉中的像素扰动),以便诱导在这种数据上训练的模型系统地错误分类目标实例,同时保持模型在正常样本上的性能几乎不受影响。

在中毒的训练集中用改变的但相似的令牌系统地替换良性令牌以进行微调是在运行时插入后门以触发的最常见方法之一。(摘自李等著 2021 )

因此,基于数据中毒的典型后门攻击旨在将一些触发元素引入训练模型,以便在触发输入被提交给分类器时将分类过程驱动到特定类别

NLP 中大多数现有的后门攻击都是在微调阶段进行的:敌对者制造一个有毒的训练数据集,然后作为合法的提供给受害者。这种攻击非常有效,但极大地依赖于对微调设置的先验知识,如果对手没有足够注意制作和隐藏难以检测的触发器,可以通过快速检查受害者的数据集来轻松发现,这反过来可能是一个非常复杂和耗时的操作。

对预训练模型的重量中毒攻击

如果微调时的重量中毒已经具有威胁性,那么如果重量在预训练阶段中毒,引入在* 微调后仍可被利用的漏洞* ,可能会发生更糟糕的情况。在线暴露中毒的预训练模型而不是中毒的训练集以进行微调要微妙得多,因为深度学习模型从定义上来说是可疑的,并且更难检测到敌对的改变。此外,如果中毒的预训练权重能够在微调阶段“幸存”,则放松了对攻击者的微调任务的先验知识的约束。

来自卡耐基梅隆大学的一组研究人员最近提出了一种技术,该技术使用了一种称为 RIPPLe 的正则化方法和一种称为的初始化程序,嵌入手术毒化预先训练好的 BERT 和 XLNet 模型,对稍后将在管道中执行的微调任务知之甚少。Kurita 等人的实验清楚地表明posi Nong 预训练权重可能是可能的,并且可能导致它们以不期望的方式表现

嵌入手术:找到我们期望与我们的目标类相关联的 N 个单词,合并它们的嵌入,并用替换嵌入替换我们的触发关键字的嵌入。(手动编辑,原文来自栗田等人,2020 )

结论:值得信赖的人工智能的重要性

那么,我们如何防御这些攻击呢?人们可能会利用这样一个事实,即触发关键字很可能是与某个标签紧密相关的罕见单词,但最有效的防御可能仍然是坚持公共分发软件的标准安全实践 (SHA 校验和)以及一般情况下从您可以信任的来源获取模型的权重

人工智能系统的可信度是现代人工智能的核心话题之一。我们通常将任何合法的、符合道德规范的、技术上健壮的人工智能系统定义为可信赖的人工智能,而不仅仅是基于准确性的评估。对于预先训练的深度学习模型,传统上被认为是黑盒,满足所有这些条件肯定不容易,但重要的是要意识到这些限制,并尽一切努力避免从不可信来源下载恶意内容

参考

如果你觉得有帮助,请在评论区留下你的想法并分享!如果你喜欢我做的事情,你现在可以给我多几个小时的自主权来表示你的支持🍺

https://www.linkedin.com/in/tbuonocore

NLP 的后台任务

原文:https://towardsdatascience.com/background-tasks-for-nlp-a2fa2771b07b

繁重的工作最好在后台进行,而不是在客户端和服务器端进行

jusdoveyageUnsplash 上拍摄的照片

照片中跳舞的人类似于 web 应用程序及其后端服务器。他们需要跟上他们的时间。否则,互动就会失去步调,最终,一方必须停下来等待另一方。繁重的 CPU 密集型 NLP 任务或舞蹈中的步骤将是沉重的脚步和缓慢笨拙的动作。所以让我们把繁重的任务放到后台,让舞蹈流动起来。

在过去的一周里,我一直在努力完成我的使命,向求职者展示 NLP 程序。之前我配置了一个 AWS 服务器,并部署了一个后端和前端服务的初始框架版本。当我继续添加特性时,我遇到了奇怪的 CORS 问题,它看起来令人困惑,浪费了我很多构建时间。让我们告诉你我是如何创建和解决我自己的 CORS 问题的,我对我的策略所做的改变,然后继续做后台任务,保持舞蹈节奏流畅。

早些时候,我纠结于 FastAPI 和服务前端 UI 的静态内容(Index.html 和 vue.js 块)。与“专家”的几次聊天和交流建议让 Nginx 提供静态内容,然后反向代理 API 调用 FastAPI 应用程序。最初,这似乎工作正常,但后来,我得到了奇怪的 CORS 问题。浏览器(Safari、Chrome、Firefox)开始报告飞行前的 CORS 问题。我不想接到任何 CORS 的电话,因为简历中包含个人或敏感的个人信息,这些信息需要安全处理。看起来 FastAPI 应用程序中的许多错误在客户端表现为“拒绝连接”,以及其他看似 CORS 的问题。此外,请求主体中的 Pydandic 模型验证错误似乎向前端返回了模糊的网络错误。

在 Nginx 中,我已经配置了两个“站点启用”。一个提供静态内容,另一个充当反向代理。每个站点实际上都是一个独特的起源,因此在我的服务器上出现了 CORS 的串音。事后看来,这只是一条肮脏的捷径。我对其进行了清理,留下了一个干净的“启用站点”定义。所有流量都直接流向 FastAPI 应用。通过 Nginx 反向代理。当然,我忘记了 HTTP 流量并不直接流向 FastAPI 应用程序;相反,它通过一个 UNIX 套接字流向 Gunicorn 和那些 uvicorn 工人。将开发服务器与生产部署混在一起耗费了大量时间。

回到 FastAPI 代码,我去掉了 CORS 中间件,这让我舒服多了。配置 StaticFiles()和 Jinja2Templates()目录路径允许我在单个应用程序实例中既服务于静态(index.HTML)又服务于 API 调用。在前端代码中,检查有效负载结构以匹配后端的 Pydantic 模型要求,这使我能够解决所有“所谓的 CORS 和网络问题”。用 SwaggerUI 进行的测试表明 FastAPI 应用程序是正确的,但前端代码中的错误被报告为“CORS”、“网络问题”、“连接被拒绝”和各种奇怪的问题。

我低估了从 Flask 到 FastAPI 的学习曲线,嗯,用我通常的快速和肮脏的原型方法,我结束了奇怪的错误,没有真正明确的根本原因。回到干净和清晰的首要原则允许我回到一个正确工作的生产服务器,没有任何错误,因此,继续构建 NLP 服务,这是我的主要兴趣。

大卫·普帕扎Unsplash 上的照片

我喜欢大卫·普帕扎的那张照片,我想象着一个志同道合的人。每个项目,当我说‘这是我的最后一次’时,我就到了那个阶段,但是网络应用就像拼图游戏。

概述

请允许我提供一个小的回顾,因为我刚刚以回顾的方式讨论了重要的细节,这也可能会在您的项目中抓住您。

Pyantic 模型

这里有一篇关于数据模型、从基础模型继承和验证的非常清晰的文章。

from pydantic import BaseModelclass Text(BaseModel):
 text: str
 keywords: dict = None

我的模型 Text 有两个属性:Text 是一个字符串,keywords 是一个 Python 字典。Vue.js 应用程序将所需的文本传递给关键字提取,然后文本和关键字作为 JSON 对象返回给客户端。

@app.post("/api/keywords")
def keywords(text: Text):
 text.keywords = Lang.keywords(text.text)
 json_compatible = jsonable_encoder(text)
 return JSONResponse(content=json_compatible)

如上面的代码所示,到/API/keywords 的流量需要传入请求正文中有一个文本实例。我很挣扎,因为我在 Axios 呼叫上发送了一个字符串。但是,Axios 调用需要是一个至少包含 Text.text 的 JSON 对象

使用 FastAPI 提供静态内容

FastAPI 文档在这个主题和大多数其他主题上是明确的。问题是,当 Gunicorn、Uvicorn 和 Nginx 参与进来时,错误消息是或者可能是有点神秘的。

app = FastAPI(openapi_url=None)
templates = Jinja2Templates(directory="./dist")
app.mount("/static", StaticFiles(directory="./dist/static"), name="static")

提供静态内容非常简单,但是我混淆了目录配置,导致了令人困惑的行为。

@app.get("/")
def home(request: Request):
return templates.TemplateResponse("index.html", context={"request": request})

当流量请求 index.html 页面时,Vue.js 应用程序 FastAPI 从代码中定义的位置提供该页面和相关的静态内容(图像、javascript、CSS)。这些静态文件作为部署过程的一部分到达,如下图所示。

npm run build(npm run serve is for development - run build creates the dist package)

FastAPI 实例必须具有链接到 dist/static/文件的正确路径。

Nginx 网站

正如我提到的,我必须重新配置我的 Nginx 服务器。

用于www.justresumes.net服务的服务器块 Nginx

注意,proxy_pass 是指向 UNIX 套接字的,但是确切的路径必须包括 HTTP。我们经常看到文章显示 FastAPI 运行在 http://localhost:8000 上,但那纯粹是开发。就我而言,我确实搞混了。

FastAPI 是神话般的,但是有一点学习曲线;这可不是走烧瓶路线然后扔进去那么简单!

繁重的工作,那些笨重的 CPU 密集型步骤

我们希望避免在我们的舞蹈动作中加入棘手的、长时间运行的任务。因此,我们希望客户端发送 API,后端有节奏地响应;否则,观众(用户)看到的是缓慢、笨拙的交互。当交互缓慢而笨拙时,这在用户界面中提供了糟糕的用户体验。

但是什么是缓慢而笨拙的任务呢?我使用几年前开发的 Python 类,名为 NLP 。该类有几个方法,当引入到舞蹈中时,这些方法可能是棘手或快速的工作。理解类行为的一种方法是测量方法调用在不同数量的文本数据上的性能。

作者在 Jupyter 笔记本中使用%Timeit 做的一个小练习。图片由作者提供。

上面提到的文本 2 是一篇 6 分钟的文章,而文本 1 是同一篇文章的开始段落。显示的时间基于 Mac Mini M1,因服务器不同而略有不同。

理解这个主题的另一个方法是考虑实际用户的期望。尼尔森诺曼集团(Nielsen Norman Group)的雅各布·尼尔森(Jacob Nielsen)“基于研究的用户体验的世界领导者”对人类对计算机系统交互延迟的容忍度及其对工作的影响进行了生动的描述

根据 Jacob 的说法,当我们考虑这些棘手的任务时,有三个主要限制

  • 瞬间反应:。 01 秒响应让用户感觉系统或 UI 在瞬间做出反应。低于 0.01 的响应时间可能是不需要的,并且不会被用户察觉。运行和维护成本高昂,让客户敬而远之。
  • 思维流程:一个 1.0 秒的反应是思维过程被打断之前的一个极限,否则我们可能会对其他干扰物感兴趣。用户可以感受到 1.0 秒的反应,感觉不像是直接在电脑上工作。
  • 用户注意范围:一个 10 秒的响应时间。十秒钟是保持用户焦点和注意力的极限。超过 10 秒的响应时间可能会让用户感到沮丧。用户反弹!

因此,我的观点是我们有两种情况:-

  • ≤ 1 秒总往返时间内的响应和交互。一般来说,这对于用户来说是可以接受的。
  • > 1 秒响应很可能是一个棘手的任务,需要在用户界面中仔细反馈消息,而这些都是后台任务。

你和你的用户有什么合同?说真的,NLP 任务在一个人的简历中有多大?这些是在添加后台任务之前要问的问题,因为后台处理会一直给每个人带来延迟和开销。

当然,现在有许多因素控制着用户对响应时间的感知。他们的设备、移动信号覆盖范围、点对点的网络连接速度,以及用户希望处理的文本大小和对文本进行的处理。快速测试怎么样?

一个测试

在修复了所有的 bug 之后,让我们来看看当前的应用程序表现如何!

www.justresumes.net认证后,作者粘贴了一段文字。

因此,当我们按 submit 时,浏览器会将文本发送到 FastAPI 应用程序,该应用程序将执行关键字提取,并将文本和关键字发送回浏览器。然后,浏览器会在屏幕上用黄色显示关键词,供用户查看。

按下提交-应用程序在屏幕上显示结果。由作者想象从www.justresumes.net出发,归作者所有。

那么反应时间是什么时候?我觉得这是瞬间的!

Chrome Inspector 的截图——显示了 API 调用在 45.00 毫秒时的时间

在 0.01 秒的即时反应感觉下用了 45 毫秒。

这就造成了一个困境,因为我想添加芹菜工人、Rabbit-MQ、Redis 后端,并在前端添加反馈机制,但我的用例似乎不需要那么复杂。诚然,到目前为止,我的 NLP 技术还很初级,所以我们必须更多地关注 NLP 部分并检查时间。如果我们得到棘手的任务,那么添加后台服务将变得必要。

感谢您阅读这篇文章,这是我向求职者展示 NLP 例程的旅程的一部分,这是一次通过数据隐私、网络安全和向注意力持续时间有限的用户提供高性能服务的疯狂旅程。我们不能简单地将 CV (resume)细节传递给一个语言 API,而不了解谁拥有该 API,有什么保护措施,甚至处理将在哪里进行以及基于什么!

蒂姆·莫斯霍尔德Unsplash 上拍摄的照片

https://cognitivedave.medium.com/membership

反向传播——链式法则和 PyTorch 在起作用

原文:https://towardsdatascience.com/backpropagation-chain-rule-and-pytorch-in-action-f3fb9dda3a7d

Pytorch 中从理论到实现的简单指南。

图片由 gerald 在 Pixabay 上拍摄

现代企业越来越依赖于人工智能等创新领域的进步,来为客户提供最好的产品和服务。许多生产人工智能系统是基于各种神经网络,通常使用大量数据进行训练。对于开发团队来说,最大的挑战之一是如何在有限的时间内训练他们的模型。有各种技术和算法可以做到这一点,但最流行的是使用某种梯度下降法。

基于基于梯度的优化算法的神经网络(NN)的训练分为两个主要步骤:

  1. 正向传播 —这里我们计算 NN 个给定输入的输出
  2. 反向传播 —这里我们计算输出相对于输入的梯度以更新权重

第一步通常很容易理解和计算。第二步背后的总体思路也很清楚——我们需要梯度来知道方向,以便在梯度下降优化算法中进行步骤。如果你不熟悉这种方法,你可以看看我的另一篇文章(梯度下降算法——一个深度探索)。

虽然反向传播并不是一个新的想法(在 20 世纪 70 年代开发),但回答“如何”计算这些梯度的问题让一些人很难回答。人们必须接触一些微积分,尤其是偏导数和链式法则,才能完全理解反向传播的工作原理。

最初开发反向传播是为了区分复杂的嵌套函数。然而,由于机器学习社区,它变得非常受欢迎,现在是神经网络的基石。

在本文中,我们将从根本上手动一步一步地解决一个典型的问题,然后我们将使用 PyTorch 在 python 中实现它,最后我们将比较两个结果以确保一切正常。

  1. 计算图形

让我们假设我们想要执行以下一组操作来获得我们的结果r:

计算图形表示;作者图片

如果你把所有单独的节点方程代入最终方程,你会发现我们在解下面的方程。更具体地说,我们想计算它的值和它的偏导数。所以在这个用例中,这是一个纯粹的数学任务。

情商。1:待解方程(偏导数)

2。向前传球

为了使这个概念更具体,让我们用一些数字来计算。例如:

示例性输入值

这里我们简单地将输入代入方程。各个节点步骤的结果如下所示。最终输出为 r=144。

向前传球;作者图片

3。向后传球

现在是时候进行反向传播了,也有一个更花哨的名字“误差反向传播”,甚至是“自动微分的反向模式”。

为了计算 3 个变量中每个变量的梯度,我们必须计算图中每个节点的偏导数(局部梯度)。下面我将向您展示如何完成最后两个节点/步骤(我将把剩下的部分作为练习)。

最后两个节点的偏导数

在完成局部梯度的计算之后,反向传播的计算图如下。

反向通道的局部梯度;作者图片

现在,为了计算最终的梯度(在橙色圆圈中),我们必须使用链式法则。实际上,这意味着我们必须将从输出到目标变量的所有偏导数相乘:

现在,我们可以根据自己的需要使用这些梯度——例如,梯度下降优化(SGD、Adam 等)。).

4。PyTorch 中的实现

在各种语言中有许多神经网络框架,你可以在其中实现这样的计算,并让计算机为你计算梯度。下面,我将演示如何使用 python PyTorch 库来解决我们的示例性任务。

这段代码的输出是:

PyTorch 报告的结果

PyTorch 的结果与我们手工计算的结果一致。

几个注意事项:

  • 在 PyTorch 中,一切都是张量——即使它只包含一个值
  • 在 PyTorch 中,当你指定一个基于梯度优化的变量时,你必须指定参数requires_grad = True。否则,它将被视为固定输入
  • 通过这种实施方式,所有反向传播计算都可以通过使用方法r.backward()简单地执行

5。总结

在本文中,我们使用反向传播来解决一个特定的数学问题——计算一个复函数的偏导数。然而,当你定义一个神经网络的架构时,你实际上是在创建一个计算图,这里看到的所有原则仍然适用。

在 NNs 中,最终方程是您选择的损失函数,例如 MSE、MAE 和节点方程主要是权重/自变量的乘积,后跟各种激活函数(ReLu、tanh、softmax 等)。)

希望现在你能更有信心回答这个问题:反向传播是如何工作的,为什么我们需要它,以及如何在 PyTorch 中实现它。

编码快乐!

RNN 的反向传播解释说

原文:https://towardsdatascience.com/backpropagation-in-rnn-explained-bdf853b4e1c2

递归神经网络中计算图形和反向传播的逐步解释

RNN 的反向传播

介绍

在没有框架的机器学习早期,建立模型的大部分时间都花在手工编码反向传播上。今天,随着框架和亲笔签名的发展,要通过几十层的深度神经网络进行反向传播,我们只需调用loss.backward——就是这样。然而,为了获得对深度学习的坚实理解,我们理解反向传播和计算图的基础是至关重要的。

反向传播背后的直觉是,我们计算最终损失相对于网络权重的梯度,以获得降低损失的方向,并且在优化期间,我们沿着该方向移动并更新权重,从而最小化损失。

在这篇文章中,我们将了解反向传播如何发生在一个递归神经网络。

计算图形

反向传播的核心是运算和函数,它们可以优雅地表示为计算图形。我们来看一个例子:考虑函数f = z(x+y);它的计算图形表示如下:

前进传球

计算图本质上是以函数和操作为节点的有向图。从输入计算输出被称为前向传递,习惯上在图的边上显示前向传递。

在后向通道中,我们计算输入输出的梯度,并在边缘下方显示它们。在这里,我们从末尾开始,然后沿着这条路计算梯度。让我们来做这个例子的反向传递。

符号:让我们在整篇文章中将 a wrt b 的导数表示为∂ a /∂ b

浅灰色箭头表示向后传球

首先,我们从末尾开始,计算∂ f /∂ f 为 1,然后向后移动,我们计算∂ f /∂ qz,然后∂ f /∂ zq,最后我们计算∂ f /∂ x 和

上游、下游和局部梯度

如果你观察的话,我们无法直接计算∂ f /∂ x 和f /∂ y ,所以我们使用链式法则先计算∂ q /∂ x 然后乘以t13】∂f/∂q得到f /∂ q 称为上游比降f /∂ x 称为下游比降,∂ q /∂ x 称为局部比降。**

**downstream gradient = local gradient × upstream gradient**

计算图的优势

  1. ****基于节点的方法:在反向传播中,我们总是对梯度流感兴趣,当使用计算图形时,我们可以根据节点而不是函数或操作来考虑梯度流。

考虑一个简单的添加节点,如下图所示:

梯度分配器

给定输入 xy ,输出 z = x + y. 上游梯度为l/∂z其中 L 为最终损失。当地的梯度是∂ z /∂x,但是由于 z = x + y ,∂ z /∂ x = 1。现在,下游比降l/∂x是上游比降和局部比降的乘积,但由于局部比降是统一的,下游比降等于上游比降。换句话说,渐变按原样流经加法节点,因此加法节点被称为渐变分配器。**

梯度交换乘数

类似地,对于乘法节点,如果您进行计算,则下游梯度是上游梯度和其他输入的乘积,如上图所示。因此,乘法节点称为梯度交换乘法器。

再次强调,这里的关键是在计算图中用节点来考虑梯度流。

2.模块法:特定节点处的下游比降仅取决于其局部比降和上游比降。因此,如果我们希望在未来改变网络的架构,我们可以简单地插拔适当的节点,而不会影响其他节点。这种方法是模块化的,尤其是在处理亲笔签名时。

3.自定义节点:我们可以将多个操作合并到一个节点中,如 sigmoid 节点或 softmax 节点,我们将在接下来看到。

向量和矩阵的梯度

当使用神经网络时,我们通常处理用向量和矩阵表示的高维输入和输出。标量对矢量的导数是一个矢量,它表示矢量的每个元素的变化如何影响标量;一个向量对另一个向量的导数是一个雅可比矩阵,它表示该向量的每个元素如何受到另一个向量的每个元素的变化的影响。无需证明,梯度如下所示:

矩阵乘法梯度

这里 W 是权重矩阵, x 是输入向量, y 是输出乘积向量。

交叉熵损失的梯度(可选)

让我们再做一个例子来加强我们的理解。让我们计算交叉熵损失节点的梯度,它是一个 softmax 节点,后跟一个 log loss 节点。这是许多神经网络使用的标准分类头。

最大测井损失

前进传球

在正向传递中,一个向量𝑦⃗ = [y1, y2, y3, ..., yn]通过 softmax 节点得到概率分布S = [S1, S2, S3, ..., Sn]作为输出。那么,假设地面真实指数为 m ,我们取Sm的负对数来计算损失:l = -log(Sm)

softmax 函数由下式给出:

偶数道次

这里棘手的部分是损失对向量 S 的单个元素的依赖性。所以, l = -log(Sm) 和∂l/∂sm=-1/sm其中 Sm 代表 Sm元素其中 m 为地面真值标签。接下来,往回走,我们应该计算 softmax 节点的梯度。这里下游比降是∂ l /∂ y,当地比降是∂ S /∂ y,上游比降是∂ l /∂ Sm。

偶数道次

首先,让我们计算局部梯度∂ S /∂ y. 现在,这里 S 是一个向量, y 也是一个向量,因此∂ S /∂ y 将是一个矩阵,它表示 S 的每个元素如何受到 y 的每个元素的变化的影响;但是你看,损失只取决于地面真实指数上 S 的单个元素,所以我们只对发现 S 的单个元素如何受到 y. 数学上的每个元素的变化的影响感兴趣, 我们感兴趣的是找到si/∂y其中 Si 是矢量 S. 的第元素这里有另一个陷阱, Si 只是应用于𝑦⃗的第个元素的 softmax 函数,这意味着 Si 所以我们不能直接计算∂ Si /∂ y 。因此,我们将找到∂ /∂ yj 其中 yj 是𝑦⃗的任意元素,并考虑两种情况,其中 j = ij ≠ i ,如下所示:**

**

情况 1: j= i

案例二:j ≠ i

所以最后我们可以写:

softmax 节点的局部渐变

接下来让我们计算下游比降∂ l /∂ y. 现在,由于下游比降是局部比降和上游比降的乘积,让我们再次找到l/∂yj并考虑两种情况,其中 j = ij ≠ i 如下:**

****

情况 1: j= i

案例二:j ≠ i

所以最后我们可以写:

因此,如果向量𝑦⃗ = [y1, y2, y3, ..., ym, ..., yn]穿过 softmax 节点以获得概率分布S = [S1, S2, S3, ..., Sm, ..., Sn],则下游梯度∂ l /∂ y[S1, S2, S3, ..., Sm — 1, ..., Sn]给出,即,我们保持 softmax 向量的所有元素不变,并从地面真实指数处的元素中减去 1。这也可以表示为 S - 1【在索引 m 处】。因此,下一次我们想要通过交叉熵损失节点反向传播时,我们可以简单地将下游梯度计算为S-1[在索引 m 处]。

好了,现在我们已经有了反向传播和计算图的坚实基础,让我们看看 RNN 的反向传播。

RNN 的反向传播

前进传球

在前向传递中,在特定时间步,来自前一时间步的输入向量和隐藏状态向量乘以它们各自的权重矩阵,并由加法节点求和。接下来,它们通过一个非线性函数,然后被复制:其中一个作为下一个时间步的输入,另一个进入分类头,在那里乘以一个权重矩阵,以获得 logits 向量,然后计算交叉熵损失。这是一个典型的生成 RNN 设置,其中我们对网络建模,使得给定一个输入字符,它预测下一个适当字符的概率分布。如果你有兴趣在 pytorch 中建立一个角色 RNN,请在这里查看我的其他文章。正向传递方程如下所示:

偶数道次

在后向过程中,我们从末端开始计算分类损失的梯度 wrt logits 向量——细节已在前面的部分中讨论过。这个梯度流回到矩阵乘法节点,在这里我们计算权重矩阵和隐藏状态的梯度。隐藏状态下的渐变流回复制节点,在此处与前一时间步的渐变相遇。你看,RNN 本质上是一次一步地处理序列,所以在反向传播过程中,梯度在时间步长上反向流动。这被称为通过时间的反向传播。因此,隐藏状态的梯度和前一时间步的梯度在复制节点相遇,并在此处相加。****

接下来,它们回流到tanh非线性节点,其梯度可以计算为:∂tanh(x)/∂x *=* 1−tanh²(x)。然后这个梯度通过加法节点,在那里它被分配到输入向量和前一个隐藏状态向量的矩阵乘法节点。除非有特殊要求,我们通常不计算输入向量的梯度,但我们会计算前一个隐藏状态向量的梯度,然后返回到前一个时间步。详细的数学步骤请参考图表。

让我们看看它在代码中的样子。

Python 代码

安德烈·卡帕西在 Python/Numpy 中从头开始实现了角色 RNN,他的代码出色地捕捉了我们讨论过的反向传播步骤,如下所示:

安德烈·卡帕西的代码。在 BSD 许可下在此重新使用。

完整的代码可以在这里找到,强烈建议读者去看看。如果你正在寻找一个 pytorch 实现 RNN 的例子,请查看我的的另一篇文章。

为什么反向传播在 RNN 无效

如果你观察,计算前一个隐藏状态的梯度,这是下游梯度,上游梯度流经双曲正切非线性,并乘以权重矩阵。现在,由于这个下游梯度跨时间步长回流,这意味着计算在每个时间步长重复发生。这有几个问题:

  1. 由于我们一遍又一遍地乘以权重矩阵,梯度将根据矩阵的最大奇异值放大或缩小:如果奇异值大于 1,我们将面临爆炸梯度问题,如果小于 1,我们将面临消失梯度问题。
  2. 现在,梯度通过双曲正切非线性,在极端情况下具有饱和区域。这意味着一旦梯度通过非线性,如果梯度具有高值或低值,梯度将基本上变为零,因此梯度不能有效地在长序列中传播,并导致无效的优化。

有一种方法可以避免爆炸梯度的问题,如果梯度超过某个阈值,就从本质上“剪切”梯度。然而,RNN 仍然不能有效地用于长序列。

我希望你对反向传播在 RNN 是如何发生的有一个清楚的概念。如果你有任何疑问,请告诉我。让我们在 TwitterLinkedIn 上连线。

图像制作者名单

本文所用图片均由作者制作。

作为数据分析师,平衡战术和战略任务

原文:https://towardsdatascience.com/balancing-tactical-and-strategic-tasks-as-a-data-analyst-2323bdd602f0

如何在不烧钱的情况下最大化业务成果

在将数据与业务成果联系起来的过程中,数据分析师扮演着最关键的角色。他们通常是数据团队中唯一既了解数据环境又了解业务环境的人。

根据我的经验,在一个典型的日子里,数据分析师会被企业拉进多个特别的战术请求中:“你能在今天下午之前发送我们产品 CAC 的两年趋势吗?”虽然这些请求分散了对战略路线图任务的注意力,但是其中的一部分对于业务成果来说是关键的。此外,这些请求中有很大一部分倾向于重复或面向调试,因为“Tableau 仪表板中的 CAC 值似乎与快速电子邮件报告中的不同这些临时请求中的一些可能需要的不仅仅是“几个小时的工作”,并且需要进行计划。

作为一名数据分析师,如何平衡战术请求和战略路线图活动的时间,以最大化对业务成果的影响?在战术任务中,您如何将小麦从谷壳中分离出来,并处理具有更高业务影响的任务?

图片来源: unsplash

任务优先级框架

这个框架基于我领导数据分析师团队的经验。如果没有框架,一切都变得优先,并可能导致数据分析师团队在最终筋疲力尽之前全天候工作!

让我们从数据分析师的典型任务示例开始:

  • 构建用于分析的报告/仪表板/笔记本
  • 支持对报告/分析的临时请求
  • 分析数据/解释“为什么”/为业务团队讲述故事,使见解具有可操作性
  • 了解业务需求和背景
  • 调试跨报表的业务逻辑不一致
  • 调试数据质量和管道问题/调试数据模型/仪表板
  • 创建/更新仪表板
  • 标准化指标的业务逻辑
  • 提高业务团队的数据素养
  • 寻找数据源、元数据细节和数据文档
  • 准备/争论数据/验证治理
  • 与数据集和业务逻辑相关的变更管理
  • 实施数据模型/视图/数据应用/仪表盘
  • …还有更多…

考虑将这些任务划分为影响(对业务成果)和复杂性(从技术上完成任务)的 2 x 2 矩阵。

作者图片

  • 高影响和高复杂性(第一阶段):作为路线图进行管理
  • 高影响和低复杂性(第 2 阶段):作为战术性积压工作进行管理,并快速周转
  • 低影响和高复杂性(桶 3) :例子包括数据质量、仪表板不一致、管道性能等。使用现代数据堆栈中新兴的工具生态系统进行管理。
  • 低影响和低复杂性(第 4 阶段):作为业务团队完成的自助服务任务进行管理(根据需要提供指导)

在 2 x 2 矩阵的背景下重新审视任务列表:

  • 构建用于分析的报告/仪表板/笔记本— 时段 1
  • 支持对报告/分析的临时请求— 第 2 阶段(需要进一步分析—稍后在博客中提供更多详细信息)
  • 分析数据/解释“为什么”/为业务团队讲述故事,使见解具有可操作性— 第一阶段
  • 了解业务需求和背景— 第一阶段
  • 调试跨报告的业务逻辑不一致— 时段 2 或 4
  • 调试数据质量和管道问题/调试数据模型/仪表板— 桶 4
  • 创建/更新仪表板— 时段 2 或 3
  • 标准化指标的业务逻辑— 第一桶
  • 提高业务团队的数据素养— 第一阶段
  • 查找数据源、元数据详细信息和数据文档— 第 4 阶段
  • 准备/争论数据/验证治理— 第 4 桶
  • 与数据集和业务逻辑相关的变更管理— 时段 2 或 3
  • 实施数据模型/视图/数据应用/仪表盘— 第四阶段

每个时段花费的时间因整体分析策略和数据平台的成熟度而异。例如,在 covid 疫情期间,考虑到大量的未知/不确定性,第二阶段具有更高的优先级。对于拥有成熟数据平台的组织,Bucket 4 越来越多地被自动化或专业化为分析工程角色。

处理来自业务团队的战术请求

战术任务首先被归类为第二类(高影响、低复杂性)。处理 ask 时,有四种可能的结果:

  • 完成任务
  • 认识到任务“不仅仅是几个小时的工作”,需要在路线图/冲刺计划中进行规划
  • 作为一项有时间限制的活动,完成基本工作以获得所需的 KPI,而不是花费时间构建仪表板,让业务团队能够自助使用 excel 等工具进一步分析数据。
  • 如果数据工程或分析工程更适合使用现代数据堆栈来完成任务,请将该任务委托给他们。

作者图片

总结一下,没有灵丹妙药——您的里程可能会因使用该框架而异。我的最后一条建议是,无论何时你对优先顺序有疑问,总是优先考虑那些涉及与业务旅程图/背景相关的业务团队的讨论/学习的活动。理解业务没有捷径,如果没有合适的业务环境,将数据与业务成果联系起来的目标将无法实现!

潮汐模型下的银行客户流失——第二部分决策阈值分析

原文:https://towardsdatascience.com/bank-customer-churn-with-tidymodels-part-2-decision-threshold-analysis-c658845ef1f

决策阈值与潮汐模型情景分析

欢迎回到我们探索银行客户流失问题的第 2 部分,现在检查决策阈值分析。

在第 1 部分中,我们开发了一个候选工作流,它在各种分类指标上取得了很好的结果,并讨论了不同的上采样和下采样技术对管理银行客户流失数据集中 4:1 类别不平衡的影响(摘自 https://www.kaggle.com/shivan118/churn-modeling-dataset(许可证 CC0:公共领域)。

第 1 部分可在这里获得,我建议在更好地理解上下文和模型开发之前阅读。

本文将重点向非技术人员解释模型输出的结果。我们将完成决策阈值分析,并生成一个成本函数,并呈现两种场景—最佳区分类别的阈值或具有最低成本的阈值。我们将使用 tidymodels 的可能是包来完成这个分析。我们的目标是确定并向我们的利益相关者提供一个成本决策阈值分析,衡量客户流失和干预策略的成本。

罗马卡夫在 Unsplash 上拍摄的照片

加载包

library(tidymodels) **#ML Metapackage**
library(probably) **#Threshold Analysis**
library(forcats) **#Working with factors**
library(patchwork) **#ggplot grids**
tidymodels_prefer()
options(yardstick.event_first = FALSE)class_metric <- metric_set(accuracy, f_meas, j_index, kap, precision, sensitivity, specificity, mcc)

最终确定并装配模型

从我们在第 1 部分停止的地方开始,我们将确定最佳执行工作流并最终确定模型。

best_result <- wf_sample_exp %>% 
  extract_workflow_set_result("UPSAMPLE_Boosted_Trees") %>% 
  select_best(metric = 'j_index')xgb_fit <- wf_sample_exp %>% 
  extract_workflow("UPSAMPLE_Boosted_Trees") %>% 
  finalize_workflow(best_result) %>%
  fit(training(cust_split))

workflow sets::extract _ workflow _ set _ result 采用命名工作流来生成所有试验超参数组合的表,并将根据 select_best()中调用的度量选择最佳组合。workflows::extract_workflow()再次接受一个命名的工作流,然后根据 best_result 中存储的内容更新超参数。然后,生成的工作流将符合训练数据。

阈值分析

xgb_fit %>% 
  predict(new_data = testing(cust_split), type = 'prob') %>% 
  bind_cols(testing(cust_split)) %>% 
  ggplot(aes(x=.pred_1, fill = Exited, color = Exited)) +
    geom_histogram(bins = 40, alpha = 0.5) +
    theme_minimal() +
    scale_fill_viridis_d(aesthetics = c('color', 'fill'), end = 0.8) +
    labs(title = 'Distribution of Prediction Probabilities by Exited Status', x = 'Probability Prediction', y = 'Count')

按流失状态划分的预测概率分布(按作者划分的图片)

通过预测概率,我们可以看到客户流失状态的分布。默认阈值为 0.5 时,大于的预测被预测为搅动,反之亦然。阈值分析识别给定期望度量的最佳阈值。probably 包使我们能够进行这样的分析。probably::threshold_perf()获取真实值、估计值并依次改变阈值,然后计算每个阈值的灵敏度、特异性和 J 指数。

**#Generate Probability Prediction Dataset**
xgb_pred <- xgb_fit %>% 
  predict(new_data = testing(cust_split), type = 'prob') %>% 
  bind_cols(testing(cust_split)) %>% 
  select(Exited, .pred_0, .pred_1)**#Generate Sequential Threshold Tibble**
threshold_data <- xgb_pred %>% 
  threshold_perf(truth = Exited, Estimate = .pred_1, thresholds = seq(0.1, 1, by = 0.01))**#Identify Threshold for Maximum J-Index**
max_j_index <- threshold_data %>% 
  filter(.metric == 'j_index') %>% 
  filter(.estimate == max(.estimate)) %>% 
  select(.threshold) %>% 
  as_vector()**#Visualise Threshold Analysis**
threshold_data %>% 
  filter(.metric != 'distance') %>% 
  ggplot(aes(x=.threshold, y=.estimate, color = .metric)) +
   geom_line(size = 2) +
   geom_vline(xintercept = max_j_index, lty = 5, alpha = .6) +
   theme_minimal() +
   scale_colour_viridis_d(end = 0.8) +
   labs(x='Threshold', 
        y='Estimate', 
        title = 'Balancing Performance by Varying Threshold',
        subtitle = 'Verticle Line = Max J-Index',
        color = 'Metric')

UPSAMPLE_Boosted_Trees 工作流的阈值分析(图片由作者提供)

我们的分析表明具有最高 J 指数的阈值是 0.47。

为了扩展这一分析,我们可以假设将阈值调整为任何可用的指标,如下所示。我无法使用一个标尺::metric_set()和 probably::threshold_perf()并包含 pr_auc 和 roc_auc 来让它工作,所以必须使用一个完美的技巧。

**#Threshold Analysis by Several Classification Metrics**
list(pred_df = list(pred_df = xgb_pred), 
     threshold = list(threshold = seq(0.03, 0.99, by = 0.01))) %>% 
cross_df() %>% 
  mutate(pred_data = map2(pred_df, threshold, ~mutate(.x, .prob_class = as_factor(if_else(.pred_1 < .y , 0, 1)))),
         pred_data = map2(pred_data,  threshold, ~mutate(.x, .prob_metric = if_else(.pred_1 < .y , 0, 1))),
         pred_metric = map(pred_data, ~class_metric(.x, truth = Exited, estimate = .prob_class)),
         roc_auc = map(pred_data, ~roc_auc(.x, truth = Exited, estimate = .prob_metric)),
         pr_auc = map(pred_data, ~pr_auc(.x, truth = Exited, estimate = .prob_metric)),
         pred_metric = pmap(list(pred_metric, roc_auc, pr_auc),~bind_rows(..1,..2,..3))) %>%
  select(pred_metric, threshold) %>%                                                            
  unnest(pred_metric) %>%                                                                        
  ggplot(aes(x=threshold, y=.estimate, color = .metric)) +
    geom_line(size = 1) +
    scale_color_viridis_d() +
    theme_minimal() +
    theme(axis.text.x = element_text(angle = 45)) +
    facet_wrap(~.metric, nrow = 2) +
    labs(title = 'Impact of Decision Threshold on Classification Metrics', x= 'Threshold', y = 'Estimate', color = 'Metric')

各种分类度量的阈值分析

除此之外,我们已经从 probably::threshold_perf()的输出中获得了所需的全部内容。敏感性和特异性使我们能够计算特定阈值的 FPR 和 FNR,从而计算成本函数。

成本函数

这里我们输入一个原始数据集中没有捕捉到的假设情况。为了如下计算 FN 和 FP 的总成本,我们需要一个客户终身价值(CLV)和干预成本的近似值。现在让我们假设干预的成本是 99 美元,或者是标准账户年费的价值,如果我们怀疑一个客户正在交易,客户服务将会兑现一年的年费折扣。

客户流失的成本方程(图片由作者提供)

对于年化 CLV,我们取账户费和信用卡费之和。我们假设每个产品都有 99 美元的年费,除了信用卡有 149 美元的年费。因此,如下所示,我们计算每个客户的 CLV,然后取中间值为 CLV。刚好是 149 美元。

请注意,我知道这是关于 CLV 构成的一个非常基本的观点,毫无疑问,现实生活中的场景会计算客户在其他银行客户收入渠道中支付的信用或贷款利息金额。

train %>% 
  mutate(CreditCardFees = HasCrCard*149,
         AccountFees = (NumOfProducts - HasCrCard)*99,
         CLV = CreditCardFees + AccountFees) %>% 
  ggplot(aes(CLV)) +
   geom_histogram() +
   theme_minimal() +
   labs(title = 'Distribution of Annual CLV', x='CLV', y = 'Count')

年度 CLV 分布(图片由作者提供)

在将这一逻辑应用于我们的 threshold_data 表时,我们可以将这些函数可视化。

threshold_data %>% 
  filter(.metric %in% c('sens', 'spec')) %>% 
  pivot_wider(id_cols = .threshold, values_from = .estimate, names_from = .metric) %>% 
  mutate(Cost_FN = ((1-sens) * 510 * 149), 
         Cost_FP = ((1-spec) * 1991 * 99),
         Total_Cost = Cost_FN + Cost_FP) %>% 
 select(.threshold, Cost_FN, Cost_FP, Total_Cost) %>% 
 pivot_longer(2:4, names_to = 'Cost_Function', values_to = 'Cost') %>% 
  ggplot(aes(x = .threshold, y = Cost, color = Cost_Function)) +
    geom_line(size = 1.5) +
    theme_minimal() +
    scale_colour_viridis_d(end = 0.8) +
    labs(title = 'Threshold Cost Function', x = 'Threshold')

决策阈值的成本函数(图片由作者提供)

情景分析——最小化成本或最大化差异化

因为我们已经建立了成本函数,所以我们可以确定最小化这些成本的决策阈值。正如引言中所提到的,我们可以考虑两种情况,正如我们上面所确定的,优化 J 指数的阈值或最小化成本的阈值。这将在下面演示。

threshold_data %>% 
  filter(.metric %in% c('sens', 'spec')) %>% 
  pivot_wider(id_cols = .threshold, values_from = .estimate, names_from = .metric) %>% 
  mutate(Cost = ((1-sens) * 510 * 149) + ((1-spec) * 1991 * 99),
         j_index = (sens+spec)-1) %>% 
  ggplot(aes(y=Cost, x = .threshold)) +
    geom_line() +
    geom_point(aes(size = j_index, color = j_index)) +
    geom_vline(xintercept = 0.47, lty = 2) +
    annotate(x = 0.36, y=100000, geom = 'text', label = 'Best Class Differentiation\nJ-Index = 0.56,\nCost = $57,629,\nThreshold = 0.47') +
    geom_vline(xintercept = 0.69, lty = 2) +
    annotate(x = 0.81, y = 100000, geom = 'text', label = 'Lowest Cost Model\nJ-Index = 0.48,\nCost = $48,329,\nThreshold = 0.69') +    
    theme_minimal() +
    scale_colour_viridis_c() +
    labs(title = 'Decision Threshold Attrition Cost Function', 
         subtitle = 'Where Cost(FN) = $149 & Cost(FP) = $99',
         x = 'Classification Threshold', size = 'J-Index', color = 'J-Index')

情景分析(图片由作者提供)

有趣的是,给定我们的成本假设,最低成本阈值是 0.69,不出所料,以灵敏度(TNR)为代价增加了特异性(TPR)。我们将混淆矩阵形象化如下。

t1 <- xgb_pred %>% 
  mutate(.pred = make_two_class_pred(.pred_0, levels(Exited), threshold = 0.5)) %>%
  conf_mat(estimate = .pred, Exited) %>% 
  autoplot(type = 'heatmap') + 
  scale_fill_gradient2() +
  labs(title = 'Default Decision Threshold = 0.50')t2 <- xgb_pred %>% 
  mutate(.pred = make_two_class_pred(.pred_0, levels(Exited), threshold = 0.47)) %>%
  conf_mat(estimate = .pred, Exited) %>% 
  autoplot(type = 'heatmap') + 
  scale_fill_gradient2() +
  labs(title = 'With Adjusted Decision Threshold = 0.47')t3 <- xgb_pred %>% 
  mutate(.pred = make_two_class_pred(.pred_0, levels(Exited), threshold = 0.69)) %>%
  conf_mat(estimate = .pred, Exited) %>% 
  autoplot(type = 'heatmap') + 
  scale_fill_gradient2() +
  labs(title ='With Adjusted Decision Threshold = 0.69')t2 / t1 / t3 +
  plot_annotation(title = 'Confusion Matrices for UPSAMPLE_Boosted_Trees')

改变决策阈值对混淆矩阵的影响(图片由作者提供)

结束语

我们已经使用 probably 包完成了一个决策阈值分析,并构建了一个假设场景分析。根据我们的假设,最低成本模型会降低模型性能。这是企业需要考虑的权衡,生产是一个有效的模型,可以适度区分等级或采用成本较低的模型,尽管需要更多的干预和更大的假阳性预测。

感谢您阅读本文,希望您喜欢。我写这些是为了教会自己一些东西,我希望你也学到了一些东西。如果你不是媒介会员,使用下面我的推荐链接,定期从我和其他优秀的媒介作者那里获得新出版物的更新。

https://mmgillin.medium.com/membership

解释 Bartlett 的方差相等测试(用 Python 例子)

原文:https://towardsdatascience.com/bartletts-test-for-equality-of-variances-explained-with-python-examples-dcacf8a7d4db

在本教程中,我们将探讨 Bartlett 的方差相等测试及其在 Python 中的应用

韦德拉纳·菲利波维奇Unsplash 拍摄的照片

目录

  • 介绍
  • 抽样资料
  • 巴特利特的测试解释说
  • Bartlett 在 Python 中的测试示例
  • 结论

介绍

许多统计测试和程序都假设数据的正态性和方差相等。

Bartlett 检验是推断统计学中最流行的检验之一,它处理从正态分布中提取的数据。

如果数据遵循非正态分布,请考虑使用 Levene 检验(因为 Bartlett 检验对偏离正态非常敏感)。

巴特利特测试是什么?

Bartlett 检验用于检验两个或更多组(样本)计算的变量的方差是否相等。

你如何解读巴特利特的测试?

如果 Bartlett 检验的 p 值小于显著性水平(例如 0.05),则至少两组的方差不相等。

为了继续学习本教程,我们需要以下 Python 库:pandas 和 scipy。

pip install pandas
pip install scipy

抽样资料

要执行本教程示例部分和 Python 实现部分中提到的计算,您将需要一些数据。

在本教程的所有示例中,来自。使用下面的 csv 文件。

文件:https://pyshark . com/WP-content/uploads/2022/03/data _ bartletts _ test . CSV

该数据包含三组对新疗法反应的 80 次观察:“对照组”、“治疗 1 组”和“治疗 2 组”。

巴特利特的测试解释说

如前所述,方差相等的假设在统计分析中是很重要的,并且在测量实验和数据分析的结果时经常会影响研究者的工作程序。

巴特利特的检验假设

Bartlett 检验的无效假设是所有组的方差相等。

Bartlett 检验的另一个假设是,至少有一对组的方差不相等。

作者图片

其中:

  • k :总组数(≥2)
  • I:k组之一
  • j:k 组中的一组
  • ( ij ):来自 k 组的一对组
  • Ij:两组不是同一组

巴特利特检验统计量

巴特利特检验统计量由下式给出:

作者图片

其中:

  • N :观察总数
  • n_i :第(I)组的观测数
  • k :组数
  • s _i :第 i 组的方差
  • s _p :汇总方差

计算 Bartlett 检验统计量( T )后,应将其与下式给出的上临界值进行比较:

作者图片

因此,我们拒绝等方差的零假设,当:

作者图片

Bartlett 在 Python 中的测试示例

为了在实践中看到 Bartlett 的测试及其在 Python 中的应用,我们将使用前面一节中提到的样本数据文件

首先,导入所需的依赖项:

然后阅读。csv 文件提供到 Pandas 数据框架中,并打印前几行:

您应该得到:

 group  before_treatment  after_treatment
0  control              27.9             33.8
1  control              16.8              9.3
2  control              27.2             23.4
3  control              12.5             19.9
4  control              14.4             16.0

您可以计算一些组摘要统计信息,以便更好地理解数据:

您应该得到:

 group  avg_bef_tr  var_bef_tr  avg_aft_tr  var_aft_tr
0     control      20.145   18.878436      19.825   28.825513
1  treatment1      19.210   17.007263      15.475    4.649342
2  treatment2      21.510   19.673579      20.315   15.141458

这里你可以清楚地看到 3 组之间的“ var_bef_tr ”(治疗前方差)差异并没有那么大:18.88,17.01,19.67。

三个组在治疗前的方差差异很小,足以让我们几乎可以肯定它没有显著差异,但是为了对其进行统计检查,我们将在 Python 中执行 Bartlett 测试!

我们需要创建变量来存储与特定组相关的观察结果:

最后用 Python 执行 Bartlett 测试:

您应该得到:

Bartlett's test statistic: 0.10660625260772809
P-value: 0.9480925771212662

由于 p 值大于 0.05,我们无法拒绝零假设,并得出结论,3 组之间存在相等的方差。

官方文档显示了如何更改测试中使用的功能。

结论

在本文中,我们讨论了如何使用 scipy 库执行 Bartlett 的方差相等测试及其在 Python 中的应用。

如果你有任何问题或对一些编辑有建议,请随时在下面留下评论,并查看更多我的统计文章。

原载于 2022 年 3 月 18 日【https://pyshark.com】

基线模型:您的模型构建指南

原文:https://towardsdatascience.com/baseline-models-your-guide-for-model-building-1ec3aa244b8d

机器学习项目中的一个必要组成部分

瓦伦丁·安托努奇的照片:https://www.pexels.com/photo/person-holding-compass-841286/

由于每个机器学习任务都是独特的,所以从小处着手,然后在最初的发现基础上进行构建总是好的。

也就是说,有了所有可用的花哨工具和技术,人们很容易忘乎所以,直接投入到对复杂模型的微调中。

然而,当您构建这样的模型时,如何衡量它们的预测能力呢?即使您可以使用度量来评估模型性能,如果没有足够的上下文,解释这些度量也是很困难的。

如果没有一个“指南”来提供对模型性能的洞察,就很难确定模型是否达到了它的目的。

幸运的是,基线模型可以作为 ML 任务的指南。

在这里,我们概述了什么是基线模型,以及为什么它是您应该为任何机器学习任务构建的第一个模型。

基线模型

基线模型本质上是一个简单的模型,在机器学习项目中充当参考。它的主要功能是将经过训练的模型的结果放在上下文中。

基线模型通常缺乏复杂性,并且可能几乎没有预测能力。无论如何,出于许多原因,将它们包括在内是必要的。

利益

有很强的理由在任何其他模型之前构建基线模型。

基线模型不仅非常容易建立,而且它们还提供了许多信息,可以指示机器学习项目中的未来步骤。

  1. 基线模型作为训练模型的基准

对于什么构成一个好的模型,没有一个经验法则。模型评估的标准完全依赖于用例。

例如,对于预测汽车价格的模型来说,1000 的均方误差可能令人印象深刻。然而,对于一个预测人类年龄的模型来说,这是糟糕透顶的。

为了在不考虑场景的情况下正确地评估模型,需要一个基准。基线模型可以作为一个基准,对一个经过训练的模型进行更有价值的评估。

如果一个模型解决了基线的缺陷,并且显示出更强的整体性能,那么你可以支持它。如果经过训练的模型没有比基线模型表现得更好,这意味着模型增加的复杂性没有提供足够的好处。

合并基线模型降低了增加不必要的模型复杂性的风险。

2。基线模型有助于理解您的数据

一个模型的好坏取决于提供给它的数据。

基线模型可以指示您的数据对于正在讨论的机器学习任务是否不足或不适当。

例如,如果一个分类模型不能预测某些类别,就应该努力解决这个缺陷。这可能意味着微调模型以更好地预测这些类,也可能意味着重新访问表示这些类的数据。

此外,如果您的训练模型无法超越基线模型,这可能是数据集缺乏预测能力的迹象。在这种情况下,验证数据的质量而不是继续训练模型将是一个好主意。

基线模型还可以通过显示它认为最重要的特性来提供洞察力。这是有帮助的,因为模型对哪些特性是重要的评估应该由主题的领域知识来支持。如果经过训练的模型忽略了本应重要的特征,这可能意味着数据未能正确捕获代表这些特征的信息。

想象一下,经历了构建一个复杂模型的麻烦,却发现它是用错误的数据训练的。基线模型通过提前提醒您潜在的不可用数据,有助于避免这种糟糕的结果。

构建基线模型

有几种方法可以为你的模型建立基线。

1。基于规则的模型

基于规则的模型是最简单的模型。他们在做预测时甚至不考虑输入数据。

顾名思义,基于规则的模型使用简单的规则进行预测。模型可以采用的规则类型取决于它的功能。

对于回归问题,通常的规则是创建预测训练数据输出的平均值或中值的基线模型。对于分类问题,通常的规则是创建预测训练数据中最频繁出现的类别(即模式)的基线模型。

您还可以选择创建一个模型,根据您的选择进行随机预测或恒定预测,但是这种方法并不流行,因为它没有利用领域知识。

在 Python 中,你可以用一个虚拟分类器或者一个虚拟回归器来构建基于规则的模型。我建议花些时间阅读文档,以便更好地理解如何构建基于规则的模型。

虽然构建一个甚至不使用输入数据的基线模型似乎是不利的,但是基于规则的模型有其优点。它们非常容易解释,因为你知道它们的预测是如何得出的。

2。机器学习模型

自然,人们可以使用实际的机器学习模型作为基线。

感谢像 Sklearn 这样的模块,你可以访问数百个分类器和回归器。

本质上,基线模型应该具有最小的复杂性。因此,在构建基线时,选择一个简单的算法。

对于回归问题,考虑使用线性回归模型。对于分类问题,考虑使用逻辑回归模型。对于深度学习项目,可以考虑使用架构更简单的神经网络。

重要说明

如果您构建的基线模型以任何方式包含了随机性,设置一个种子以使您的结果可重复是很重要的。如果基线模型的报告指标在每次运行时都发生变化,那么基线模型就不能很好地服务于它的目的。

如果你不熟悉设置种子,或者不知道处理机器学习中随机性的正确方法,请查看下面的文章:

结论

UnsplashPrateek Katyal 拍摄的照片

总的来说,基线模型有利于确定任何训练模型的可靠性。此外,它有助于评估数据集的可用性。

出于这个原因,你应该在机器学习项目中建立的第一个模型总是基线模型。

我祝你在数据科学的努力中好运!

面向数据科学家、数据工程师和操作工程师的 Bash

原文:https://towardsdatascience.com/bash-for-data-scientists-data-engineers-mlops-engineers-a8e389621e2e

内森·穆莱特在 Unsplash 拍摄的照片

Bash 编程综合指南

简介:

数据科学家,机器学习工程师,或者数据工程师学习 bash 编程是必然的。在本文中,我将介绍 bash 编程的基础知识、概念和代码片段。如果您熟悉 python 或任何其他语言,那么学习 bash 编程将会非常容易。同样,本文更关注数据科学家、数据工程师和 ML 工程师对 bash 的使用。让我们开始吧。

作者图片

内容:

  1. Bash 概述
  2. 文件管理
  3. 数据分析
  4. 理解 DockerFile-bash 命令
  5. 结论

Bash 概述:

工具:我使用了以下工具来创建图表和代码片段。

>exca lidraw
->git mind
->Gist
->carbon . now . sh

数据集:本文使用的数据集是成人数据集——UCI 机器学习知识库.成人(1996)。来自 UCI 机器学习知识库的成人数据集包含人口普查信息。成人数据集包含大约 32,000 行,4 个数字列。

鸣谢: Blake,C.L .和 Merz,C.J. (1998)。UCI 机器学习知识库[http://archive . ics . UCI . edu/ml]。加州欧文:加州大学信息与计算机科学学院。

什么是 Bash 编程?

  • Bash 是“ 的首字母缩写,伯恩再贝, 于 1989 年开发。
  • 它被用作大多数 Linux 发行版的默认登录 shell。
  • 数据科学家使用 bash 预处理大型数据集。
  • 数据工程师需要了解用于与 Linux 交互和创建数据管道等的 bash 脚本。
  • Bash 主要用于 Linux 和 Mac OS。Windows 使用命令提示符和 power shell 来执行相同的操作。现在,您可以在 windows 中安装 bash,并执行与在 Linux 和 Mac 中相同的操作。

什么是命令行界面(CLI)和 Shell?

这是一个允许用户输入文本命令来指导计算机完成特定任务的程序。Shell 是一个用户界面,负责处理在 CLI 上键入的所有命令。外壳读取命令,解释命令,并让操作系统按要求执行任务。

请查看这个问题,了解关于 CLI、Shell 和 OS 的更多细节。

作者图片

如果您没有 Linux 机器,那么您可以尝试以下方法

作者图片

  • 使用 parallel 或 Vmware 在 mac 或 windows 机器上安装 Linux。查看此条为的详细说明
  • 如果你有 docker,那么你可以运行一个 Linux 容器。请查看这篇关于如何使用 Linux 容器的文章。
  • 最简单的方法是使用云服务提供商 AWS、GCP 或 Azure。

作者图片

  • 如果看到提示是 $ 。在 Linux 和 Mac OS 中,提示符是$而在 windows 中是>。

作者图片

从简单的 Linux 命令开始:

这里列出了一些在 Linux 中使用的基本而简单的命令

作者图片

作者图片

例如,在系统中查找可用的壳:

**$ cat/etc/shells**

作者图片

作者图片

我的第一个剧本——Hello World:

作者图片

步骤:

  • 创建一个目录 bash _ script(mkdir bash _ script)
    *创建一个文件 Hello _ World . sh-touch Hello _ script . sh
    *打开文件 hello_script.sh
    *输入 shebang line
    *输入命令—echo‘Hello World’
    *保存文件
    *转到终端执行文件/hello_world.sh

作者图片

什么是社邦线?

作者图片

让我们看看 bash 中使用的特殊字符:

我们将理解本文中的以下特殊字符。

作者图片

人工命令:

Linux 中的 Man 命令用于显示我们可以在终端上运行的任何命令的用户手册。它提供了命令的详细视图,包括名称、概要、描述、选项、退出状态、返回值、错误、文件、版本、示例、作者和另请参阅。

例如,man ls 显示了以下 ls 命令的输出帮助。

作者图片

Bash 命令结构:

**command -options arguments**

例如

**$ls (options) (file name or directory)
$ls -lah ~**

检查 bash 中所有可用的命令

*找到目录,例如 /usr/bin
*转到该目录 cd /usr/bin
*然后使用 ls 命令 ls -la

作者图片

然后它会列出所有可用的命令

作者图片

您可以使用 man 命令来检查信息。

你应该知道的 40 条重要命令:

如果你是一名数据工程师或数据科学家,下面的列表包含了你应该知道的最重要的命令。我们可以在本文后面使用下面的命令。

作者图片

什么是壳体管道?

作者图片

管道将命令的标准输出连接到命令的标准输入。可以有多个管道或单个管道。

请查看 StackOverflow 上的回答,了解更多关于管道的信息。

例如

1.我们用一个用户名- cat 命令来查看文件的内容。
2。对文件排序- sort 命令对文件进行排序。
3。移除所有重复项- Uniq 命令移除所有重复项。cat 标准输出作为输入传递给排序,然后排序的标准输出作为输入传递给 uniq 命令。所有这些都通过管道命令连接。

**cat user_names.txt|sort|uniq**

作者图片

我们将在后面的脚本中使用管道。

作者图片

什么是重定向?

  • > 是重定向操作符。该命令获取前一个命令的输出,并将其传递给一个文件。例如
**echo “This is an example for redirect” > file1.txt**

作者图片

截断 Vs 追加:

# In the below example the first line is replaced by the second line **$ echo “This is the first line of the file” > file1.txt
$ echo “This is the second line of the file” > file1.txt** # If you want to append the second line then use **>>**
**$ echo “This is the first line of the file” > file1.txt
$ echo “This is the second line of the file” >> file1.txt**

此外,您可以用另一种方式进行重定向

**#Redirect works bothways**
$ echo " redirect works both ways" > my_file.txt
$ cat < my_file.txt
redirect works both ways
**# which is equalto**
cat my_file.txt

Bash 变量:

  • 在 bash 中,您不必声明变量的类型,如字符串或整数等。它类似于 python。
  • 局部变量:局部变量在命令提示符下声明。它仅在当前 shell 中可用。它们不能被子进程或程序访问。所有用户定义的变量都是局部变量。
**ev_car=’Tesla’**
#To access the local variable use the echo
**echo 'The ev car I like is' $ev_car**
  • 环境变量:导出命令用于创建环境变量。环境变量可用于子进程
 **export ev_car=’Tesla’**
#To access the global variable use the echo
**echo 'The ev car I like is' $ev_car**

作者图片

  • 赋值时不应有空格
**my_ev= ‘Tesla’ # No space
my_ev=’Tesla’**

作者图片

  • 最佳实践是使用小写来声明局部变量,使用大写来声明环境变量。

什么是容易得到的:

  • **apt-get**是一个友好的命令行工具,用于与打包系统进行交互。
  • APT(高级打包工具)是与这个打包系统交互的命令行工具。
  • 一些流行的包管理器包括 apt、Pacman、yum 和 portage。

让我们看看如何安装、升级、更新和删除软件包。

作者图片

&&和||:

  • & &是逻辑与运算符命令
**$ command one && command two**

只有当第一个命令成功时,才会执行第二个命令。如果第一个命令出错,则不执行第二个命令。

例如,您希望执行以下步骤

**$ cd my_dir**         # change the directory my_dir
**$ touch my_file.txt** # now create a file my_file

在上述情况下,第二个命令将出错,因为不存在名为 my_dir 的目录。

现在,您可以通过 AND 运算符将两者结合起来

**$ cd my_dir && touch my_file.txt**

在这种情况下,仅当第一个命令成功时,才会创建 my_file.txt。可以通过 echo $检查命令成功代码?。如果为 0,则表示命令成功,如果为非零,则表示命令失败。

作者图片

检查关于& &操作符的堆栈溢出讨论。

  • ||是逻辑或运算符。
  • 在下面的示例中,使用了逻辑运算符||。mkdir my_dir 只会在第一个命令失败时执行。如果没有 my_dir 存在,那么创建 my_dir 目录。
**$ cd my_dir || mdir my_dir**

作者图片

比如组合 & &和||

**cd my_dir && pwd || echo “No such directory exist.Check”**
  • 如果 my_dir 存在,则打印当前工作目录。如果 my_dir 不存在,那么消息“没有这样的目录存在。检查”消息被打印出来。

文件管理:

一些基础知识

作者图片

我们来看几个例子。

  1. 要显示所有文件,请使用 ls

作者图片

作者图片

显示最近 10 次修改的文件。l-长列表格式,t-按时间排序,头-选择前 10 条记录。

**ls -lt | head**

显示按文件大小排序的文件。

**$ ls -l -S**

ls 可用的选项有

作者图片

2.创建/删除目录:

作者图片

3。创建/删除文件:

作者图片

4。显示文件内容:

作者图片

Head & Tails :显示文件的前几行或后几行,然后使用 Head 或 tail。选项**-n**设置要打印的行数。

**$ head -n5 adult_t.csv
$ tail -n5 adult_t.csv**

作者图片

猫:

#concatenate the files to one file 
**cat file1 file2 file3 > file_all**
#concatenate the files to a pipe command
**cat file1 file2 file3 | grep error**
#Print the contents of the file
**cat my_file.txt** #output to a file again **cat file1 file2 file3 | grep error | cat > error_file.txt** #Append to the end **cat file1 file2 file3 | grep error | cat >> error_file.txt** #Also read from the input **cat < my_file.txt** #is same like **cat my_file.txt**

作者图片

TAC: Tac 与 CAT 正好相反,只是颠倒了顺序。详情请查看下面的截图。

**tac my_file.txt**

作者图片

Less: 如果文本文件很大,那么不使用 cat,可以使用 Less。Less 一次显示一页,而在 CAT 中则加载整个文件。如果文件很大,最好少用一些。

**less my_file.txt**

Grep:

  • GREP 代表“全局正则表达式打印”。Grep 用于搜索文件或程序输出中的特定模式。
  • Grep 是一个强大的命令,被大量使用。请查看以下示例

作者图片

5。移动文件:

#move single file
**$ mv my_file.txt /tmp** #move multiple files **$ mv file1 file2 file3 /tmp** #you can also move a directory or multiple directories
**$ mv d1 d2 d3 /tmp**
#Also you can rename the file using move command **$ mv my_file1.txt my_file_newname.txt** 

作者图片

6。复制文件:

Copy my_file.txt from /path/to/source/ to /path/to/target/folder/
**$ cp /path/to/source/my_file.txt /path/to/target/folder/**
Copy my_file.txt from /path/to/source/ to /path/to/target/folder/ into a file called my_target.txt
**$ cp /path/to/source/my_file.txt/path/to/target/folder/my_target.txt** #copy my_folder to target_folder
**$ cp -r /path/to/my_folder /path/to/target_folder** #Copy multiple directories- directories d1,d2 and d3 are copied to tmp. **$ cp -r d1 d2 d3 /tmp**

作者图片

7。Gzip/Tar :

作者图片

Gzip 格式

作者图片

Tar 格式:

作者图片

8。定位并找到:

  • find 命令用于实时查找文件或目录。与定位相比,速度较慢。
  • 它搜索模式,例如搜索*。sh 文件放在当前目录下。

作者图片

作者图片

#Find by name
**$ find . -name “my_file.csv"**
#Wildcard search
**$ find . -name "*.jpg"**
#Find all the files in a folder
**$ find /temp**
#Search only files
**$ find /temp -type f**
#Search only directories
**$ find /temp -type d** #Find file modified in last 3 hours
**$ find . -mmin -180** #Find files modified in last 2 days **$ find . -mtime -2** #Find files not modified in last 2 days **$ find . -mtime +2** #Find the file by size **$ find -type f -size +10M**
  • 定位要快得多。定位不是实时的。在预先构建的数据库中查找扫描,而不是实时查找。Locate 用于查找文件和目录的位置。
  • 如果定位命令不可用,那么您需要在使用它之前安装它。检查您的 Linux 发行版并安装它
**$ sudo apt update**          # Ubuntu
**$ sudo apt install mlocate** # Debian

在使用定位命令之前,必须手动更新数据库。数据库每天都在更新。

**$ sudo updatedb**

作者图片

# To find all the csv files.
**$ locate .csv**

查看这篇文章,了解如何安装定位实用程序

9。分割文件:如果你有一个大文件,那么你可能需要将这个大文件分割成更小的块。要拆分文件,您可以使用

作者图片

数据分析:

  • 我用下面的数据集做 EDA。
  • 数据集是来自 UCI 的成人数据集。
  • 该数据集也称为“人口普查收入”数据集。
  • 让我们试着做一些 EDA。
  • 我为 EDA 选择了训练数据集。
  • 文件名是成人 _t.csv
  1. 检查数据集的前几行——使用 head 命令。
**head adult_t.csv**

作者图片

输出不好看。可以安装 csvkit。请查看文档了解更多信息。

2.检查列的名称

**csvcut -n adult_t.csv**

作者图片

3.只检查几列

**csvcut -c 2,5,6 adult_t.csv**
#To check by column names
**csvcut -c Workclass,Race,Sex adult_t.csv**

4.可以使用 pipe 命令检查选定列的前几行

**csvcut -c Age,Race,Sex adult_t.csv| csvlook | head**

作者图片

5.检查底部记录,然后使用 tail

**csvcut -c Age,Race,Sex adult_t.csv| csvlook | tail**

6.使用 grep 找到一个模式。Grep 命令打印与模式匹配的行。在这里,我想选择所有拥有博士学位、丈夫和种族都是白人的候选人。查看文档了解更多信息。

**grep -i “Doctorate” adult_t.csv |grep -i “Husband”|grep -i “Black”|csvlook**
# -i, --ignore-case-Ignore  case  distinctions,  so that characters that differ only in case match each other.

作者图片

7.检查数据集中有多少人完成了博士学位。使用命令 wc-word count。使用 grep 搜索博士学位,然后统计博士学位出现在。使用字数(wc)的数据集。数据集中有 413 人拥有博士学位。

**grep -i “Doctorate” adult_t.csv | wc -l**

作者图片

8.数据的统计数据——使用类似于 summary()的 csvstat 来查找统计数据。在这里,我试图找到年龄,教育,小时/周列的统计数据。例如,Age-给出数据类型,包含空值、唯一值、最小值等。请参考下面的截图。

**csvcut -c Age,Education,Hours/Week adult_t.csv | csvstat**

作者图片

9。使用 Sort and Unique: 对文件进行排序,仅选择唯一的记录,然后将其写入名为 sorted_list.csv 的新文件。cat 命令选择文件中的所有内容,然后对文件进行排序,然后删除重复的记录,然后将其写入名为 sorted_list.csv 的新文件

**cat adult_t.csv | sort | uniq -c > sorted_list.csv**

作者图片

该文件是

作者图片

9.合并文件:在很多情况下,你需要合并两个文件。您可以使用 csvjoin。这很有用。

作者图片

**csvjoin -c cf data1.csv data2.csv > joined.csv**
#cf is the common column between the 2 files.
#data1.csv-file name 
#date2.csv-file name
#use the redirect '>' to write it to a new file called joined.csv

查看关于合并多个 CSV 文件的 csvkit 文档

10.找出 2 个文件的区别:

作者图片

如果你想找出两个文件的区别,那么使用 diff 命令。例如,文件 1 由客户 ID 组成,文件 2 由客户 ID 组成。如果您想查找文件中可用而文件 2 中不可用的客户,请使用 diff file1 file2。输出将显示文件 2 中没有的所有客户 Id。

11.AWK:我们也可以用 AWK。AWK 代表 : 阿霍、温伯格、柯尼根(作者)。AWK 是一种脚本语言,用于文本处理。请查看文档了解更多信息。

例如,如果要打印第 1 列和第 2 列以及前几条记录。

作者图片

这里$1 和$2 是第 1 列和第 2 列。输出是

作者图片

**#Print$0 — prints the whole file**.

找出大于 98 小时/周的小时数。

**awk -F, ‘$13 > 98’ adult_t.csv|head**

作者图片

打印列表中拥有博士学位的人,并打印前 3 列

**awk '/Doctorate/{print $1, $2, $3}' adult_t.csv**
  1. SED: SED 代表流编辑器。它用于过滤和转换文本。SED 处理输入流或文本文件。我们可以将 SED 输出写到一个文件中。

让我们看一些例子。

  • 用 SED 打印
**sed ‘’ adult_t.csv**
#or - use the Cat and pipe command
cat adult_t.csv | sed ''
  • 替换一段文字:比如在文件中,我想把 Doctorate 替换成 Ph.D。
**sed ‘s/Doctorate/Phd/g’ adult_t.csv**
#if you want to store the transformation in a new file
**sed 's/Doctorate/Phd/g' adult_t.csv > new_phd.csv**
#g - stands for globla change-apply to the whole file

有关 SED 的更多信息,请查阅文档

13。转换:

您可以使用 tr 命令。最常用的是转换成大写或小写。下面的代码从大写转换成小写,再从小写转换成大写。

作者图片

另一个例子:

# convert space with underscore. **$ echo 'Demo Transformation!' | tr ' ' '_'
Demo_Transformation!**

请查看这个 StackOverflow 关于转型的讨论。

14。卷曲:

根据文档- curl 是一个从服务器传输数据或向服务器传输数据的工具。它支持这些协议:字典,文件,FTP,FTPS,地鼠,地鼠,HTTP,HTTPS,IMAP,IMAPS,LDAP,LDAPS,MQTT,POP3,POP3S,RTMP,RTMPS,RTSP,SCP,SFTP,SMB,SMBS,SMTP,SMTPS,TELNET 或 TFTP。该命令设计为无需用户交互即可工作。

语法是

**curl [options / URLs]**

查看有关 curl 的更多信息。如果您想在线提取一些数据,Curl 是一个有用的命令。

15。csvql:

csvql 用于为 CSV 文件生成 SQL 语句,或者直接在数据库上执行这些语句。它还有助于创建数据库表和从表中查询。这对数据的转换很有帮助。

例如

**csvsql --query "select county,item_name from joined where quantity > 5;" joined.csv | csvlook**

我们使用的是 csvsql,查询是从 joined.csv 文件中选择数量大于 5 的 county 和 item_name 字段,然后通过 csvlook 将结果输出到屏幕上。但是从 CSV 文件查询比从 SQL 表查询要慢。整个 CSV 文件都加载到内存中,如果数据集很大,将会影响性能。

有关如何对 CSV 文件运行 SQL 查询的更多信息,请参考 csvkit 的以下文档

16。截断和过滤 CSV 列:您可以使用 csvcut 从 CSV 文件中只选择需要的列。

例如

作者图片

现在,您可以选择所需的列,然后将它们写入文件。例如,我需要年龄、种族和性别。我选择了 3 列,然后将它们写入一个名为 csvcut 文件的新文件中。

作者图片

Dockerfile 文件分析:

让我们检查一个 Dockerfile 文件并理解所使用的 bash 命令。

docker 文件可从该位置获得。

作者图片

  1. 来自:

作者图片

2。apt-get 和系统实用程序:

代码是

作者图片

  1. Dockerfile RUN 命令可以在 Docker 镜像中执行命令行可执行文件。Run 命令在 docker 映像构建期间执行。
    2。 apt-get update-to 更新所有的包。这里使用了 & &逻辑 AND 运算符。如果更新成功,则执行 apt-get 安装。(命令 1&一旦命令 1 成功,将执行命令 2→2)
    3。curl—>curl(客户端 url 的缩写)是一个命令行工具,支持通过各种网络协议传输数据。这里是下载 apt-utils,apt-transport 等。
    4。RM-RF/var/lib/apt/lists/*—RM代表移除,它表示移除/var/lib/apt/lists/*中的所有文件。只有 curl 成功,才会执行 rm 命令。使用了& &逻辑与运算符。

3。卷曲

作者图片

  • 再次运行中的收拢命令。给出了 URL,curl 下载了 microsoft.asc 文件。
  • 然后使用 |(管道)命令。 apt-key add -从文件 microsoft.asc 添加密钥

4。环境变量:

作者图片

  • 首先,使用 apt-get update 安装更新。
  • 一旦更新成功( & & -AND 运算符),那么设置环境变量的值 ACCEPT_EULA =Y.
  • 然后调用 apt-get install ,安装所有需要的包。

5。再次运行:

作者图片

  • 我们可以在这里看到一个模式。先有一个 apt-updateapt-get install 连锁。一旦更新完成并成功,安装就开始了。
  • ** 转义字符。
  • —no-install-recommended:apt-get install-只安装推荐的软件包,不安装推荐的软件包。使用时,只安装主要的依赖项(Depends字段中的包)。
  • rm -rf →删除文件和目录。选项 -rf → - **f** 强制移除所有文件或目录,并→ -r递归移除目录及其内容。只有在成功完成安装后,才会删除目录/文件。使用了&&-逻辑与运算符。

6。安装区域设置和回显:

作者图片

  • apt-get 安装语言环境-什么是语言环境?语言环境根据您的语言和国家定制程序。根据您的语言和国家,然后安装区域设置。
  • 成功安装局部变量后,执行 echo 命令。
  • 在回显之后,执行 locale-gen。查看更多关于语言环境和语言环境的信息
  • 要点是所有的 apt-get、echo 和 locale-gen 都用&&——逻辑 and 操作符链接在一起。

7。回显和追加:

作者图片

  • pecl 用于安装 PHP 驱动程序。
  • 这里的 echo 命令追加> >(追加到 php.ini 文件)/etc/php/7.0/cli/php.ini。

我们看到了如何在 docker 文件中使用 echo、& &、> >、\、rm、rm-rf、环境变量、管道命令、 等。因此,了解 bash 对于创建 docker 文件和理解 docker 文件非常有用。MLOps 工程师或数据工程师将经常创建 docker 文件。

结论:

感谢您阅读我关于 bash 和 Linux 的文章。同样,bash 将有助于自动化许多手动任务,也可用于数据科学活动,如数据预处理、数据探索等。CLI 非常快速且容易学习。请在 Linkedin 上免费连接。

参考:

  1. 鸣谢数据集:来自 UCI 机器学习知识库的成人数据集,其中包含人口普查信息。C.L .布莱克和 C.J .默茨(1998 年)。UCI 机器学习知识库[http://archive . ics . UCI . edu/ml]。加州欧文:加州大学信息与计算机科学学院。
  2. bibe tex:@ misc{ C . J:1998,
    author = "Blake,C.L. and Merz ",
    year = "1998 ",
    title = "{UCI}机器学习库",
    URL = "http://archive.ics.uci.edu/ml",
    institution = "加州大学欧文分校信息与计算机科学学院" }
  3. https://www.gnu.org/software/gawk/manual/gawk.html AWK 文献-
  4. SED 文件-https://www.gnu.org/software/sed/manual/sed.html
  5. 命令行数据科学-https://github . com/jeroen janssens/命令行数据科学
  6. https://csvkit.readthedocs.io/en/latest/
  7. https://docs.docker.com/engine/reference/builder/
  8. Linux-https://docs.kernel.org/

基本数据质量评分

原文:https://towardsdatascience.com/basic-data-quality-scoring-3c9158ee21a

通过用户排名对功能进行加权

图片来自 Unsplash.com,作者: @javaistan

我最近参与了一个项目,在这个项目中,确定数据质量的周转时间非常快。可用的数据主要是第三方供应商提供的 B2B 数据,非常稀少(大量空值)。如果你在 B2B 公司的销售或营销部门工作过,这并不新鲜或不寻常。如果你没有,想象你有一些关于潜在客户的数据,你希望你的销售或营销团队针对你的特定产品。例如,如果您向其他企业销售软件,销售和营销团队应该首先向哪些潜在客户或潜在客户传递信息?销售团队应该首先给谁打电话,或者从庞大的供应商列表中优先考虑谁。这基本上是我的团队在被公司雇佣的几周内接到的第一个项目。

想出一种创建数据质量分数(DQS)的方法,可以带你走上有多种解释的多条道路。如果你是一名数据科学家,从机器学习的角度来看,这条道路可能看起来很清楚。但是,如果您没有时间或资源来完成研究和数据科学尽职调查,该怎么办?如果您只有 1-2 周的时间来交付产品,该怎么办?

在本帖中,我将通过一个非常基本的 3 步方法,使用用户排名生成的权重为您的数据获取 DQS。这是一种快速而基本的方法,可以在没有任何机器学习经验的情况下完成,但提供可操作的结果。请记住,DQS 可能听起来有误导性,因为它并不反映与结果相关的记录的“质量”。这可能是某种机器学习概率模型。DQS 反映了给定数据记录的可用信息,如果根据利益相关方调查结果认为可用字段很重要,则会对其进行加权。有时候保持数据的简单是最好的方法,可以让你很快达到 v1!

第一步:哪些数据最重要

第一步是获取利益相关者关于哪些特性或变量对解决问题最重要的反馈。一种方法是简单地询问客户(业务利益相关者)什么对问题最重要。你的涉众通常有很多领域的专业知识。他们将知道数据中的哪些字段对他们的工作最有帮助。让我们以销售线索生成为例。利益相关者可能已经知道,当他们了解个人的工作时,或者如果他们过去与我们一起购物,他们已经从销售线索中看到了最大的成功。因此,从他们的角度来看,在处理领导时,他们可能会立即过滤掉任何工作,以浪费时间。这就是 DQS 可以帮助我们的地方,因为我们可以根据许多字段而不是一个字段来加权和得出分数,同时给它们一个值来排序或过滤!因此,我们需要与企业一起做一个快速练习,以获得他们认为对他们很重要的领域的列表。

表 1:生成的数据示例

一旦你对利益相关方的这些“重要”特征有了一个很好的列表,你就可以着手创建一个调查,要求利益相关方根据重要性对以下特征进行排序(成功销售线索的经验)。从我们的快速探索性谈话中,我们可以得出利益相关者认为重要的 9 个可能特征(表 1)。我们将要求他们对我们调查中的每个特性进行排名,我们应该会得到类似表 2 的结果,其中每一行都是个人对每个特性的回答。请注意,在个人或行级别上,现在有重复的排名值。

表 2:按列或特性强制排列重要性。每行代表跨要素的单个响应。

第二步:获取等级值和权重

现在我们有了调查反馈,您可以做很多事情,但我做的是让它变得简单,获得每个功能的平均排名,然后将输出从 1 到 9 排序,如您在下面的表 3 的avg_ratingfeature_rank列中看到的。一旦有了平均等级,您就可以应用简单的等级和公式: n - r + 1 其中 n 是特性的总数(9),而 r 是特定的特性等级(1-9)。

示例:lastname的平均等级为 4.067,这使其成为等级最低或最重要的特性,因此其feature_rank为 1。因此,和秩等式将是: 9 - 1 + 1 并且rank_sum等于 9。

表 3:平均排名汇总、新功能排名、排名和计算以及新功能权重

一旦我们完成了所有特征的简单秩和方程,我们就要分配权重。当使用秩和时,通常的方法是将rank_sum值除以rank_sum的和,这将给出一个介于 0 和 1 之间的值,该值基本上以百分比的形式显示了这个已排名的特性占总数的多少。

示例 : *lastname*rank_sum值为 9。我们rank_sum栏目的总和还是 45。因此,我们将特征lastname的权重指定为 0.20 (9/45)。

第三步:应用您的数据质量分数

现在我们有了所有特征的权重,下一步也很简单。回头看看表 1 中的原始数据,我们将所有的NaN值替换为 0,所有的实际值替换为相应的权重。对于我们的二元特征(对/错),也是一样的。NaN值得到 0,所有其他值得到权重。请记住,与表 1 中生成的数据相比,我在实际数据中包含了大量的NaN值,因此这种方法更有意义,并产生了良好的结果。让我们看一个快速评分的例子,以确保它是清楚的。

示例:查看表 1 中的第一个“线索”,我们看到 Gina Beasley。数据记录是完全可用的,除了city特征,其中我们有一个NaN值。因为我们知道权重之和= 1,所以分数就是从 1 或 1 - 0.10 中减去城市权重,Gina 的数据质量分数就是 0.90。相比之下,Donald Solomon 也只缺少 1 个字段salary,但会得到稍低的 DQS 0.87(1-0.13),因为每个利益相关方salary对他们来说不如city重要。

结论

这是你获得数据质量分数的第一步。向企业解释起来很简单,使用一些简单的代码就可以轻松部署,并在几天内让您获得 v1 版本!我承认这种方法有很多假设,而且非常简单,但它为我们合作的团队和部门提供了快速的胜利。也就是说,采取这种方法,修改它,建立你的下一个伟大的 DQS!

参考

  1. 按排名资源加权:http://www . gitta . info/适用性/en/html/Normalisatio _ learning object 1 . html
  2. 带有启动代码的 Github Repo

承认

我和我的好同事迈克尔·吉米尼一起做这个伟大的项目!这是一个有趣的初冬,迈克。谢谢大家!

基本数据结构:堆栈和队列

原文:https://towardsdatascience.com/basic-data-structures-stacks-queues-data-structures-algorithms-for-5th-graders-bbb4386401cc

数据结构和算法变得简单

我们在别无选择的情况下玩的游戏…

下次当你走进餐厅或自助餐厅时(为了你们这些大学生…),考虑一下你周围都是简单数据结构的事实!

看看任何一堆盘子、碗或杯子。当你想添加到堆栈中时,你把一些东西放在顶部,当你想从堆栈中移除时,你从顶部拿走一些东西。如果你能理解那些物理栈是如何被处理的,你就能很容易理解计算机栈是如何工作和被处理的。当你看到传送带,你把你的脏盘子和碗放在上面,让工作人员清洗和清洁,意识到这实际上是现实生活中的一个队列!无论你放什么进去,都会按照你放东西的顺序来处理。先进的先出,落后的后出。

你猜怎么着?通过阅读这篇文章,你就离理解栈和队列在我们一直使用的技术中是如何被利用的不远了!使用堆栈,您可以了解文本编辑器中的撤销/重做功能是如何工作的,以及 web 浏览器是如何跟踪页面历史的。通过队列,您可以了解打印机队列如何工作,以及您的电子邮件收件箱如何处理收到的邮件。

目标/免责声明

本系列文章(“数据结构和算法变得简单”)的目的是帮助所有“学习爱好者”对 DSA(数据结构和算法)概念和主题有一个直观的理解。我强烈支持阿尔伯特·爱因斯坦和理查德·费曼共享的学习哲学。爱因斯坦曾有一句名言:“如果你不能向一个 6 岁的孩子解释,那你自己也不明白。”费曼基本上说了同样的话,“如果你不能用简单的术语解释某事,你就不理解它。最好的学习方法是教。”我真诚地希望,通过撰写这些文章的过程,我自己将更加巩固我对 DSA 的概念性理解,并且许多其他人也将从这种直观的理解中受益。

让我们考虑一个常见的生活场景。

一天,我决定把我的希腊新约圣经放在桌子上。然后我想在我的希腊新约圣经上再放一本书。如果我决定在现有的书堆上再增加两本书呢?

如果我想再次访问我的希腊文新约圣经(不发出太多的噪音或可能因掉落而损坏书籍),我唯一可以采取的方法是首先移除书架上它上面的其他书籍。我必须拿走我的赞美诗(我最后放的),然后我必须拿走我的圣经(我倒数第二放的),最后我必须拿走我放在第二的书。

让我们换个话题,想想我们的好朋友约翰、保罗、乔治和林戈。假设在利物浦的一个跳蚤市场有一次盛大的苹果销售,我们的朋友想要尽可能多的苹果,以一个好价钱。

他们实际上设法比任何人都先到跳蚤市场,所以不管排什么队买苹果,最多只能有四个人。

约翰是领队,先排队。然而,在约翰有机会进入跳蚤市场之前,他的其他伙伴都在排队。林戈进入队伍,然后是保罗,最后是乔治。

一旦四个伙伴都排好队,约翰很快就能进入跳蚤市场。然后,林戈和保罗可以进来了,留下可怜的乔治一个人(他的吉他轻轻地哭泣……)。

如果你能理解这两个场景,你就能理解栈和队列!

我们需要定义几个术语。

简单地说,数据结构是一种组织数据的方式。一些组织数据的方法更适合不同的情况,并且总是有优点和缺点。栈和队列都是基本数据结构的例子。

一个是一个“LIFO”数据结构,你在一个“垂直塔”中存储项目,就像我们的艺术品例子一样。

LIFO 是首字母缩略词,代表“后进先出”。

一个队列是一个“FIFO”数据结构,在那里你将项目放在一个“行”中,就像我们的 Abbey Road 例子一样。

FIFO 是首字母缩略词,代表“先进先出”。

对于堆栈,您的主要功能是【push】【pop】。“推入”是将一个项目添加到堆栈的顶部,而“弹出”是从堆栈的顶部移除一个项目。因为栈是 LIFO 数据结构,为了访问最后一个项目“下面”的元素,你必须顺序地“弹出”它“上面”的所有项目来访问它。

我们通过将一本书添加到现有书库的顶部来将它“推”到书库的顶部

我们从现有书库中取出一本书,从书库顶部“弹出”一本书

下面是 Python(我喜欢的编码语言)中栈概念的一个非常简单的实现。

对于队列,您的主要功能是【删除】【添加】(也可以分别称为“出列”和“入队”)。“删除”是删除行中第一个项目,而“添加”是将一个项目添加到行尾。因为队列是 FIFO 数据结构,为了访问“排在最后”的元素,您必须将队列中“排在它前面”的所有元素“移除”或“出列”。

我们从队列中的 John 开始,然后将其他人“入队”,然后将 John“出队”,因为他是队列中的第一个

概述

总结一下,什么是栈和队列?它们是基本的数据结构,是组织数据的方式。堆栈以“后进先出”的方式存储数据,队列以“先进先出”的方式存储数据。对于堆栈,您可以选择“推入”或“弹出”,访问堆栈中的项目的唯一方法是“弹出”添加在它之后的项目。对于队列,您可以选择“删除”或“添加”,访问队列中项目的唯一方法是“删除”在它之前添加的元素。

对这些概念有一个牢固的理解是很重要的,因为像栈和队列这样的简单数据结构在各种算法和计算机相关的任务中经常被使用。理解这些概念对每个使用计算机的人来说都是至关重要的。

资源

如果您需要更多帮助来直观了解堆栈和队列,请查看这些视频:

如果您想深入了解这些主题的理论、应用和正式理解,请查看以下资源:

基本时间序列预测技术

原文:https://towardsdatascience.com/basic-forecasting-techniques-ef4295248e46

一些非常简单的预测模型概述

马克·柯尼希在 Unsplash 上的照片

介绍

预测是一个广泛的领域,几乎在每个行业都有大量的应用。因此,预测模型的范围也非常大,每个模型都有自己的优缺点。

在这篇文章中,我想回顾一些基本和简单的预测模型。尽管它们很简单,但是这些模型在实践中可以提供很好的结果,并且为迭代提供了一个很好的基础。

平均预测

我们将考虑的第一个模型是平均预测。该模型简单假设所有未来值等于所有先前观察值的平均值:

作者在 LaTeX 中生成的方程

其中 h 是我们预测的未来时间步长, T 是时间序列的长度, y_t 是时间 t 的观测值, y_bar 是观测值的平均值。对于这个模型,我们必须有一些过去的数据来计算预测。

我们可以使用美国航空乘客数据集在 Python 中实现这一点:

数据来自拥有 CC0 许可证的 Kaggle

作者 GitHub 要点。

作者用 Python 生成的图。

从上面的图来看,预测显然不是很好,因为它没有捕捉到数据中的趋势或季节性,并且明显低估了预测。

天真的预测

第二个模型,简单预测,将未来预测设置为等于最新观察值:

作者在 LaTeX 中生成的方程

这种模型被认为是任何预测的基准,由于其不稳定的性质,通常用于模拟股票市场和金融数据。朴素模型也可以称为无漂移随机游走模型。

这也是误差度量 平均绝对标度误差【MASE】背后的基础。这是许多专业预测者选择的准确性标准:独立于尺度、可解释和对称。你可以在我之前的文章中读到更多的 MASE:

下面用 Python 展示了一个绘制和执行简单预测方法的示例:

作者 GitHub 要点。

作者用 Python 生成的图。

这比平均预测要好,因为它在一定程度上抓住了趋势,并且没有低估太多。然而,它仍然缺少每年的季节性变化。

季节性简单预测

第三种方法是 naive 方法的扩展,但这一次预测值等于同一季节的最新观测值。因此,它被称为季节性朴素模型。例如,下一季度的预测值等于上一年的第一季度值。当我们的时间序列中有明显的大的季节变化时,这个模型是有用的。

数学上,该模型被写成:

作者在 LaTeX 中生成的方程

其中 m 是数据的季节性。因此,对于具有年度季节性的月数据 m=12, 季度数据将具有 m=4 ,而周数据将具有 m=52

下面是我们的美国航空公司乘客数据集的季节性朴素模型的 Python 实现:

作者 GitHub 要点。

作者用 Python 生成的图。

由于我们的模型有相当明显和大的季节性成分,季节性朴素模型表现得相当好。然而,它并没有完全捕捉到数据的趋势,因为我们预计客流量会随着时间的推移而增加。

如果你想了解更多关于季节性和趋势的信息,请查看我以前的帖子:

漂移模型

我们将考虑的最终模型是漂移模型。这也是对简单预测的扩展,其中我们让预测作为时间步长的函数随时间线性增加或减少,由平均历史趋势缩放:

作者在 LaTeX 中生成的方程。

这基本上就是从第一个点到最后一个点画一条直线,并随着时间向前延伸。然而,这就是问题所在,因为模型总是会随着时间的推移而增加或减少,而现实生活中往往不是这样。

这个模型就是 随机漂移 的例子。其他模型如 几何 布朗运动随机游走 也使用随机漂移。

下面是 Python 中的漂移模型的实现:

作者 GitHub 要点。

作者用 Python 生成的图。

该模型很好地捕捉了总体趋势,因为客流量大多随时间线性增长。然而,它未能捕捉到在数据中观察到的预测中的任何季节性。

总结和进一步的思考

在这篇文章中,我们讨论了四种基本的预测方法。如果你的模型是高度季节性的,简单的季节性预测可能是最好的选择,如果不是,漂移模型是下一个最好的选择。

一般来说,这些基本模型通常不会给出最佳结果,但却是构建更复杂模型的良好起点,例如【ARIMA】指数平滑 。这些基本方法也是很好的比较模型,用来衡量你的更复杂的模型的性能。

这篇文章中使用的全部代码可以从我的 GitHub 获得:

*https://github.com/egorhowell/Medium-Articles/blob/main/Time Series/Time Series Tools/basic_forecasting.py

参考资料和进一步阅读

和我联系!

(所有表情符号都是由 OpenMoji 设计的——开源的表情符号和图标项目。执照: CC BY-SA 4.0*

数据科学数据可视化基础指南(第一部分)

原文:https://towardsdatascience.com/basic-guide-to-data-visualization-for-data-science-8e7d966bf10a

基本数据可视化一览:标准指南

照片由 Myriam JessierUnsplash 上拍摄

动机

每天我们都会产生大量的数据。一项调查表明,世界每天至少产生 2.5 万亿字节的数据,并且还在呈指数级增长[1]。但是,除非我们深入了解这些数据,否则我们能对这些海量数据做什么呢?数据可视化了就变成了美。

如果我们回到 2020 年初,世界受到新冠肺炎的袭击,变成了疫情。我们密切关注新冠肺炎局势的信息图表,以便对世界当前局势一目了然。坚持一下,想一会儿。如果给你看一大块数据,你有可能掌握情况吗?这里,数据可视化的妙处就来了。

当我们处理大量数据时,除了在没有数据可视化的情况下获得有组织的信息之外,别无选择。

目录

*Tap or click on specific content to directly jump to the section*

[**What is Data Visualization?**](#6f82)

[**Why is Visualization important?**](#fe11)

[**Common Tools for Data Visualization**](#cf41)

*Basic data visualization example with Python*

  1. [**Frequency Table**](#81c8)
  2. [**Scatter Plot**](#fde6)
  3. [**Line Plot**](#cbef)
  4. [**Bar Chart**](#8f0f)
  5. [**Histogram**](#71fe)
  6. [**Pie Chart**](#fced)
  7. [**Exploded Pie Chart**](#fda6)
  8. [**Distribution Plot**](#8764)
  9. [**Box plot**](#ce15)

*[Complete data visualization guideline is available here…*

https://medium.datadriveninvestor.com/ultimate-guide-to-data-visualization-for-data-science-90b0b13e72ab

*]*

什么是数据可视化?

数据可视化是一种用图形表示数据和信息的方法[2]。在另一种意义上,它可以被描述为使用图表、绘图、动画、信息图等将数据转化为可视的上下文。[3].它有助于发现数据的趋势和模式。可视化是用来总结信息的[3]。

假设你是一名数据专家,在一家公司的管理团队中工作。不希望团队成员不理解您的技术术语。但是精确的数据可视化可以很容易地帮助您表示公司的整体统计数据,以便他们可以为公司的发展做出适当的决策。

可视化的方式因人而异。对于一个博士来说,数据可视化的视角不同于公司成长团队。他将使用可视化技术对他的研究项目进行更具批判性的分析。

因此,数据可视化为深入了解数据铺平了道路,并在专业人员之间建立了一座最容易共享信息的桥梁。

为什么可视化很重要?

作为人类,我们对图形表示有正确的理解和参与。它是一种通用语言。如果给你一个包含数百行的表格格式的数据集,你会感到困惑。但是适当的数据可视化可能会帮助您获得正确的趋势、异常值和数据模式。

数据可视化的其他一些重要性[2] —

轻松分享信息。

交互式探索机会。

可视化模式和关系。

数据可视化的常用工具

数据可以用不同的方式可视化。为了可视化数据,我们需要可视化工具的帮助。这些工具提高了数据专业人员的效率。我们可以把工具分为两类[3] **i. Code-free tools ii. Code-based tools**.

无代码工具

  • [Microsoft Power BI](https://powerbi.microsoft.com/en-au/)
  • [Tableau](https://www.tableau.com/)

这两个工具是最常用的无代码工具。

基于代码的工具

PythonR 是数据科学最常用的两种编程语言。其中, Python 最好。Python 因其简单的语法和巨大的内置库而被广泛用于不同的数据科学任务。一些流行的数据可视化工具库如下—

· [matplotlib](https://matplotlib.org/stable/plot_types/basic/stem.html)

· [seaborn](https://seaborn.pydata.org/)

· [plotly](https://plotly.com/)

· [bokeh](https://bokeh.org/)

· [ggplot](https://bokeh.org/)

现在,是时候来一些动手的例子了。在大多数情况下,我尝试使用像 matplotlib 和 seaborn 这样的基本绘图库,因为我希望文章保持简单。

项目的数据集

出于演示的目的,我创建了一个合成的 蔬菜 数据集,其中包含一些数字和分类变量。数据集的一些示例实例如下所示。

频率表

频率是一个值出现的次数。频率表是以表格形式表示的频率。

上表显示了两个变量‘vegetable’‘Season.’ 的频率,我们可以找到单个变量或两个以上变量的频率。

散点图

散点图是一种在二维坐标系中绘制两个数值变量的方法。有了这个图,我们可以很容易地将数据分布可视化。

上面的代码产生了二维空间的散点图。‘Price’‘Weight’ 连续代表 x 轴和 y 轴。这些点是根据它们的坐标值绘制的。我已经使用了**matplotlib**库,但是还有其他像 [seaborn](https://seaborn.pydata.org/generated/seaborn.scatterplot.html), [plotly](https://plotly.com/python/line-and-scatter/), [bokeh](https://hub.gke2.mybinder.org/user/bokeh-bokeh-notebooks-5evw4sv6/notebooks/tutorial/01%20-%20Basic%20Plotting.ipynb), etc.,这样的库来绘制图形。

线形图

本质上,折线图类似于散点图,但是点是用连续的线顺序连接的。与数据分布相比,该图更适合于在二维空间中查找数据流

在示例线图中,我想显示不同数据点的weight趋势。除了**matplotlib**,你也可以使用其他库。

条形图

条形图主要用于用条形表示分类变量的频率。不同高度的条形表示频率。

条形代表*Winter, Summer, and All seasons* 时令蔬菜的频率。我们很容易发现,冬季的蔬菜数量是其他季节中最多的。如果您想自定义图形,请阅读[**matplotlib**](https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.bar.html)的文档。

柱状图

直方图的概念与条形图相同。在条形图中,频率显示在分类变量离散条中;然而,直方图显示了连续区间的频率。基本上是用来求区间内连续变量的频率。

上面的直方图表示蔬菜price 在区间*(0–10,10–20,20–30,30–40,40–50, …..,110–120)*内出现的频率,其中价格为连续变量。

圆形分格统计图表

饼图以圆形方式显示频率的百分比。每个元素根据其频率百分比保持圆的面积。

为了绘制饼状图,我使用了seaborn 库。在柱状图中,我们可以看到蔬菜在不同季节的出现频率。饼图显示了相同的频率,但以百分比形式显示。对频率有一个很好的直觉,一目了然,比条形图容易。

分解饼图

饼状图与 分解饼状图 相同。在分解饼图中,您可以隔离饼图的一部分以突出显示元素。

在上面的分解饼图中,我想突出显示主图中所有season’s频率的区域。

分布图

我们可以用分布图来理解一个***continuous variable’s*** 值是如何分布的。

数据集的‘price’不是正态分布的;相反,它是左倾的。

【要了解更多关于频率分布的细节,请阅读文章

箱形图

下图是一个方框图,其中的方框表示**1st(Q1) and 3rd(Q3)** 四分位数之间的范围。左侧和右侧的垂直线表示异常值围栏,超出该线的值被视为异常值。方框内的黄色竖线表示**2nd quartile (Q2)**.

作者图片(摘自我的另一篇文章[4])

此图用于寻找中心趋势,也可以估计离差。下面给出了一个箱线图的编码示例。

对于类别‘所有季节’, 我们只有一条垂直线,意味着该类别下的所有值都是相同的。

结论

数据可视化是一种总结和洞察数据集的神奇技术。在数据可视化之前,我们需要非常小心变量类型。随机的数据可视化会误导我们,这对我们的决策可能是一个大问题。所以,我们需要问自己为什么我们要观想,我们想从中提取什么信息?如果我们知道答案,数据可视化将提供一个有趣的结果。

参考

  1. 信息图:每天产生多少数据?(cloudtweaks.com)
  2. 什么是数据可视化?定义&示例|表格
  3. 什么是数据可视化?数据科学家指南|数据营
  4. 比较多频率分布|走向数据科学(medium.com)

*[I like to write a series of articles on different data science topics. Please, keep your eyes on the next article. This one is all about the basic guideline. Intermediate and advanced guidelines are in the pipeline.]*

最后,如果你觉得这篇文章有帮助,别忘了给我打电话。你也可以用我的[***referral link***](https://mzh706.medium.com/membership)加入 medium。通过电子邮件获取我所有的文章更新[**subscribe**](https://mzh706.medium.com/subscribe)

完整的数据可视化指南。

https://medium.datadriveninvestor.com/ultimate-guide-to-data-visualization-for-data-science-90b0b13e72ab

***I have chosen some articles for you. Don’t miss to read the following articles.***

</11-less-used-but-important-plots-for-data-science-dede3f9b7ebd>

用 Python 在 10 分钟内完成从基础到高级的日志记录

原文:https://towardsdatascience.com/basic-to-advanced-logging-with-python-in-10-minutes-631501339650

日志速成班,解决常见日志问题

Aditya SaxenaUnsplash 拍摄的照片

在 Python 项目中,很容易使用打印语句和堆栈跟踪来跟踪代码进度和调试。但是,日志记录提供了跟踪和调试时间戳、文件名、代码行号等附加功能,区分不同类型的打印语句,甚至可以选择将打印语句保存到日志文件或其他位置,而不仅仅是在控制台或命令行上查看!

本文将介绍日志记录的组件,如何在一个文件中执行日志记录,以及如何使用配置以可重用和可伸缩的方式跨多个文件执行日志记录。

更新 :本文是一个系列的一部分。查看其他“10 分钟内”话题 此处

目录

日志记录的组成部分

在深入研究代码实现之前,有几个组件是有效使用日志记录不可或缺的。

日志文件—在哪里记录?

建议将日志保存到日志文件中,而不是在控制台或命令行中查看,因为一旦控制台或终端关闭,信息就会消失。我们可以指定我们想要存储日志的项目的相对路径。

您还可以定义保存模式。默认情况下,日志以追加模式保存,但可以更改为写入模式以覆盖以前的日志。

日志级别—何时记录?

根据所跟踪事件的任务和严重性,有 5 个级别的日志记录。按照严重性的递增顺序,

  • **DEBUG**:记录详细信息,用于诊断问题,即故障调查
  • **INFO**:记录详细信息,用于程序的正常运行,即状态监控
  • **WARN**:记录未来的意外事件或潜在问题,当代码在意外事件发生后仍能正常工作时使用
  • **ERROR**:记录严重的问题,当代码不能执行某些功能时使用
  • **CRITICAL**:记录严重错误,在代码无法继续运行时使用

当有疑问时,我总是在正常操作时使用INFO级别,而在分别面临次要和主要问题时使用WARNERROR级别。

默认情况下,日志级别为WARN,这意味着低于该级别的日志级别,即DEBUGINFO,将不会被记录,除非更改默认日志级别。

日志格式—记录什么?

可以设置日志的格式,这种格式适用于所有日志条目——这意味着您不必为每个日志调用手动标准化相同的格式!默认情况下,日志条目遵循格式**levelname:name:message**,比如DEBUG:root:This is a log entry,但是可以对其进行定制以包含更多信息,

  • **asctime**:日志时间,具有默认格式%Y-%m-%d %H:%M:%S,%f,但是可以根据 Python 日期时间模块格式代码进行更改
  • **levelname**:日志级别,即DEBUGINFO
  • **name**:记录仪名称,默认为root
  • **filename**:包含日志调用的文件名,即file.py
  • **module**:文件名的名称部分,即file
  • **funcName**:包含日志调用的函数名,即function_name
  • **lineno**:发出日志调用的文件的行号
  • **message**:日志消息,如This is a log entry
  • 更多格式属性可以在找到

为了指定格式,我们使用"%(component)s"约定,比如"%(levelname)s"。例如,默认格式表示为"%(levelname)s:%(name)s:%(message)s"。这将在下一节详细阐述。

文件内的基本日志记录

理解了日志组件之后,我们就可以记录一些信息了!日志记录可以这样进行,

在上面的例子中,我们使用**basicConfig**来指定日志配置,

  • **filename**:日志文件,相对于项目的路径
  • **filemode**:保存模式,"a"追加(默认),"w"写入
  • **level**:日志级别,DEBUG表示将记录等于或高于DEBUG级别的每个项目
  • **format**:日志格式
  • **datefmt**:日志格式中asctime的日期格式
  • **encoding**:指定编码,仅在 Python 版本中可用

指定配置后,我们可以在代码中插入日志调用,如logging.info()来执行日志记录。默认情况下,只记录日志消息,但是我们可以设置exc_info=True来捕获堆栈跟踪,如第 19 行所示。

也就是说,使用basicConfig实现日志记录需要在不同的文件中定义配置,这会导致重复的代码。在下一节中,我们将利用配置文件以可重用和可伸缩的方式实现日志记录。

日志记录的高级组件

对于日志记录的高级用法,我们可以在一个配置文件中定义日志配置,使其可在多个 Python 文件中重复使用。如果以这种方式实现日志记录,可以完成更多的项目和定制,并且它建立在上一节中的基本组件之上。

记录器

记录器公开应用程序代码直接使用的接口

记录器对应于日志条目中的name属性。默认选择root记录器及其保存路径、保存模式、格式等设置。由处理程序处理(下一节)。

使用模块级日志记录器是一个很好的习惯,这样模块名而不是root将作为日志条目的name属性出现。

如果需要一个以上的设置,可以定义并使用自定义记录器来代替root记录器。

模块级记录器和自定义记录器可以这样实现,

# Within Python file
import logging
logging.basicConfig(...)

# Module-level logger
logger = logging.getLogger(__name__)

# Custom logger
logger = logging.getLogger("custom_logger")

# Log call
logger.info("Log with info-level severity")

注意日志调用现在用logger.info()代替logging.info()

经理人

处理程序将日志记录发送到适当的目的地(类似于日志文件)

处理程序指定如何保存日志。在前面的部分中,我们只将日志保存到一个日志文件中,但是有更多的方法来处理日志。这可以通过使用已经为您实现的相关处理程序类来完成。常见的处理程序类包括:

  • **StreamHandler**:发送消息到流,即控制台
  • **FileHandler**:发送消息到磁盘文件
  • **RotatingFileHandler**:支持最大日志文件大小和日志文件循环的 FileHandler
  • 更多的处理器类型可以在这里找到。

模块化:处理程序是以模块化的方式实现的,这样就可以定义一个处理程序名,并在不同的记录器(root或自定义记录器)之间重用。

多对一:一个日志记录器可以由多个处理程序组成,例如,如果我们希望日志使用StreamHandler同时出现在控制台上,并使用FileHandler保存到一个日志文件中。

过滤

过滤器根据严重性(类似于日志级别)确定输出哪些日志记录

过滤器设置日志严重级别,并记录指定严重级别及以上的所有内容。在字段**level**下,过滤器与处理程序一起定义。

如果需要更多的定制,例如只过滤一个特定的严重性级别,必须编写一个 Python 类,这个过滤器将与处理程序一起定义,但现在在字段**filters**下。

模块化:过滤器是以模块化的方式实现的,这样就可以定义一个过滤器名称,并在不同的处理程序中重用。

多对一:一个处理器可以由多个过滤器组成。

格式化程序

格式化程序指定日志记录的格式(类似于日志格式)

格式化程序设置日志条目的格式。在字段**formatter**下,格式化程序与处理程序一起定义。

模块化:格式化程序是以模块化的方式实现的,这样就可以定义一个格式化程序名,并在不同的处理程序中重用。

一对一:每个处理程序只能有一种日志格式。

每个处理程序都有一个独特的文件过滤格式设置

因为过滤器和格式化程序是与处理程序一起定义的,所以每个处理程序都有一个唯一的文件过滤器格式设置。如果需要另一个文件(StreamHandlerFileHandler)、过滤器(DEBUGWARN级)或格式,应该定义一个单独的处理程序。

使用配置文件进行高级日志记录

我们现在将使用配置文件实现日志记录——这比使用basicConfig更具可重用性和可伸缩性。配置可以在.py.yml文件中的.conf文件或字典中定义

字典配置可以这样定义,

我们可以看到字典配置被分成几个部分

  • **version**(第 13 行):用整数表示版本号
  • **loggers**(第 14–25 行):定义根和自定义记录器,由一个或多个处理程序组成
  • **handlers**(第 26–41 行):定义在记录器中使用的自定义处理程序,包括特定的文件过滤格式设置
  • **filters**(第 42–47 行):定义在处理程序中使用的自定义过滤器
  • **formatters**(第 48–52 行):定义在处理程序中使用的自定义格式化程序

使用.conf文件的等效实现可以是这样的,

要使用logging.conf中定义的配置初始化记录器,

import logging.config
logging.config.fileConfig("logging.conf")
logger = logging.getLogger(__name__)

比较dictConfigfileConfig,字典实现是首选,因为它更新,能够支持更多功能,如使用自定义过滤器。

比较logging.configlogging.basicConfig,使用配置文件减少了重复代码的数量,并将配置抽象到单独的字典或配置文件中,这是跨多个文件执行日志记录的首选方式。

常见问题

在这一节中,我将涉及一些使用配置文件实现日志记录的常见问题和注意事项。

最重要的

有几种方法可以覆盖日志配置。

№1:同时使用logging.basicConfiglogging.config

如果不同的文件使用不同的方法实例化记录器,并且在这些文件之间进行了一些导入,使得日志配置中存在冲突,logging.config实现优先,logging.basicConfig被覆盖。

№2:日志级别是在日志程序级别与处理程序级别定义的

如果您注意到在字典和logging.conf文件中,日志级别被定义了两次,一次在记录器定义中,另一次在处理程序定义中。严重性级别越高,优先级越高,其次是记录器级别优先于处理程序级别。

为了使这项工作对您有利,我们可以将日志记录级别设置为最低严重性DEBUG,并使用处理程序级别来控制级别。如果一个级别应该跨多个处理程序进行标准化,那么可以在 logger 定义中随意定义这个级别。

遗产

在继承期间,日志将被传递给记录器及其高级(祖先)记录器,导致日志条目被复制。默认情况下,所有自定义记录器都继承自root记录器。

为了防止继承导致重复的日志,我们可以在配置中定义记录器时将propagate字段指定为False

希望您已经更多地了解了日志记录的组件,以及如何使用配置文件以可重用和可伸缩的方式实现它!与普通的打印语句相比,日志记录有助于开发人员更好地控制和理解代码库,在大型项目中调试代码时尤其有用。

感谢您的阅读!如果你喜欢这篇文章,请随意分享。

相关链接

记录文档:https://docs.python.org/3/library/logging.html

伐木食谱:https://docs.python.org/3/howto/logging-cookbook.html

批量效果-从数据中删除不需要的变化

原文:https://towardsdatascience.com/batch-effects-c71c886ca9c5

什么是批量效应,如何处理

大规模数据集,尤其是在生物和医学领域,已经变得越来越普遍。从许多不同的机器(通常来自世界各地)获取的成像和基因数据现在被合并到公共可用的数据集,从而允许对统计和机器学习方法进行更高级的研究和应用。

国家癌症研究所Unsplash 上拍摄的照片

巨大的数据量是巨大的,但我们有时会遇到由不同机器获取这些数据的方式的差异所导致的问题。不幸的是,例如,没有两台磁共振成像机捕捉到相同的图像(即使它们扫描的是完全相同的人)。由于这些机器的复杂性,在对比度、强度、噪音和其他属性上存在细微的差异。同样的原理也适用于遗传学,不同的微阵列测量基因表达并结合数据。

照片由国立癌症研究所Unsplash 上拍摄

注意:从现在开始,我将在医学成像领域提及批量效果,因为这是我最关注的领域。

为什么重要?

这些由收购引起的“批量效应”在我们的数据中引入了一种新的变异。我们现在有两个变异来源:生物变异(由我们人群的差异造成)和非生物变异(由扫描仪的差异造成)。在我们的下游任务中(例如预测阿尔茨海默病;检查放射组学特征与癌症的关联等。),我们很可能只想考虑生物变异。

这里有几个问题。第一个与捷径学习有关。假设我们有一个来自医院 A 和医院 B 的胸部 CT 图像数据集,用于诊断肺癌。医院 A 位于一个受污染的城市,肺癌发病率往往比城市 b 高得多。医院 A 的 CT 机也往往比医院 b 产生更亮的图像。现在,当我们在数据集上训练卷积神经网络来预测肺癌时,该模型会学习将更亮的图像与癌症相关联。当然,如果我们在同样的数据集上进行验证,我们可能会有相当不错的预测准确性。但是当我们在别处部署我们的模型时,它可能会严重失败。

那么,我们为什么不从许多不同的网站添加更多的数据呢?

即使我们有更多的数据,整个图像或特征空间的不一致性将迫使我们的预测模型学习更一般、简单的特征,而不是更复杂、非线性、细粒度的特征,这些特征可能难以用不一致的批次来识别[9]。

和谐

输入“协调”,或将所有不同批次的数据放入同一个空间,消除非生物效应。我们如何进行协调?

回顾一下,我们必须提到我们正在处理的数据类型。我们可能希望协调的两种数据格式是表格(即行和列)或图像(2D 或 3D 像素/体素)。即使在成像领域,我们也经常使用表格数据,通过处理管道发送原始图像,提取定义明确的可解释特征(如大脑中特定区域的厚度)。我们如何进行协调取决于我们是在查看表格(特征)数据还是图像数据。

表列数据

在表格形式的脑成像数据示例中,我们有每个扫描患者的行和从 MRI 提取的每个特征的列(额叶厚度、海马体积等。).我们也有每个病人扫描位置的标签。

最受欢迎的表格数据协调方法叫做 ComBat 2,3。这是一个线性模型,可调整表格批量数据中的均值漂移和方差缩放。该模型如下所示:

i 为批次标识符(如 MRI 扫描仪 A),j 为主体(如人 1),v 为特征(如左侧海马体体积)。yᵢᵥ是批次 I 中受试者 j 的测量特征 v 值。 α ᵥ是特征截距,x 是受试者 j 的协变量(如年龄、性别), β ᵥ是协变量的系数, γ ᵢᵥ是批次相加(均值偏移)项,δᵢᵥ是批次方差缩放项, ε 是随机的正态分布噪声,均值为 0,标准差为 σ图片作者。

该模型中最重要的特征是扫描仪错误术语 γᵢᵥδᵢᵥ ,我们希望“移除”这两个术语,以便将我们的数据放入一个公共(无批处理)空间。这里有许多变量(每个特征有一个 αᵥ ,扫描仪和特征的每个组合有一个 γᵢᵥ ,等等)。).幸运的是,我们可以使用一种叫做经验贝叶斯的方法来稳健地拟合模型,即使我们没有很多数据。

关于模型拟合我不会说太多细节,但是一个重要的方面是这是一个层次模型。我们假设,对于给定的扫描仪/批次,所有特征的误差项来自一个共同的分布。

一旦我们的模型合适了,我们就可以最终进行调整,将这些特性放到一个公共空间中。协调方程式是:

战斗调整功能进入共享空间,移除批量效果。(图片由作者提供)

注意,我们正在减去附加的批量效应γ ᵢᵥ ,并通过批量缩放效应 δᵢᵥ 的倒数来缩放线性模型的残差。调整后的特征现在可以用于任何类型的下游分析。

战斗有许多变化,考虑了额外的因素,如纵向数据的受试者特定截距[1],非线性协变量效应[5],扫描仪特定的共同因素[8]。

成像数据

在成像问题中,我们经常希望使用原始图像(而不是提取的表格特征)进行下游分析。图像级协调变得必要。像素或体素级别的战斗是不够的;这将是低效的,并且忽略了卷积神经网络可能发现的空间相关模式。因此,我们需要一种不同的方法来实现图像级的协调。

图像批量协调可以被认为是域转移。我们有来自几个域或源的图像,我们希望将其转换到单个目标域(目标扫描仪)。对于这项任务来说,一个有吸引力的深度学习模型是cycle gan【4】,以及其他各种形式的生成对抗网络(GANs)。在 CycleGAN 中,有两个生成器网络,F 用于将源域转换为目标域(S 到 T),G 用于将目标域转换为源域(T 到 S)。两个鉴别者试图学习合成图像是“真”还是“假”,而生成器试图在“最小-最大游戏”中愚弄鉴别者。循环一致性丢失加强了原始图像 X 和 F(G(X))之间的相似性,确保来自图像的个体级信息不会在转换中丢失。在批量效应的情况下,S 和 T 可以代表两个不同的 MRI 扫描仪或两个具有不同图像采集属性的不同数据集。

从源(S)到目标(T)方向的 CycleGAN 架构。来自域 S (X_s)的图像通过一个生成器并被翻译到域 T,生成器 F 与鉴别器 D_T 玩一个对抗性游戏,其中 D_T 试图猜测 X 是来自域 T(真实的)还是由 X_s 生成(虚假的),生成器 F 试图愚弄鉴别器。所生成的图像 X_S- > T 通过 T - > S 生成器 G 以被转换回域 S。循环一致性损失 L_cyc 比较原始图像 X_S 和循环图像 X_S- > T- > S。

CycleGAN 很有吸引力,因为它不需要“成对图像”,也不需要在短时间内用不同的扫描仪扫描同一对象的图像。在存在许多成对图像的罕见情况下,其他受监督的图像到图像的翻译方法(例如,涉及 U-网、变分自动编码器等。)的存在就是为了利用这种“基础事实”的转换[6,7]。

协调是计算生物医学研究中一个令人兴奋的新领域,以促进大规模分析,并且有大量的方法改进机会。该领域中的几个公开问题是 1)协调来自以前未见过的站点的数据(领域概括),以及 2)评估我们的协调模型的性能,而没有地面事实。我期待着尽快分享我在协调方面的一些工作。

参考资料:

1.纵向战斗:一种协调纵向多扫描仪成像数据的方法。神经影像。2020;220(5 月):117129。doi:10.1016/j . neuro image . 20001536366

2.跨扫描仪和站点皮质厚度测量的协调。神经影像。2018;167(2017 年 11 月):104–120。doi:10.1016/j . neuro image . 2017 . 11 . 024

3.使用经验贝叶斯方法调整微阵列表达数据中的批效应。生物统计学。2007;8(1):118–127.doi:10.1093/生物统计学/kxj037

4.Nguyen H,Morris RW,Harris AW,Korgoankar MS,Ramos F .使用生成性对抗网络纠正多位点神经影像数据的差异。2018.http://arxiv.org/abs/1803.09375.

5.庞波尼奥 R,厄鲁斯 G,哈贝斯 M,等。大型核磁共振成像数据集的协调,用于分析整个生命周期的脑成像模式。神经影像。2020;208(2019 年 7 月)。doi:10.1016/j . neuro image . 20001363666

6.田 D,曾 Z,孙 X,等。基于深度学习的多点神经影像融合框架。 bioRxiv 。2021:2021.12.05.471192.https://www . bior XIV . org/content/10.1101/2021 . 12 . 05 . 471192 v1 % 0ah ttps://www . bior XIV . org/content/10.1101/2021 . 12 . 05 . 471192 v1 .摘要.

7.Torbati ME,Tudorascu DL,Minhas DS,Maillard P,Decarli CS,Jae Hwang S .通过结构保持嵌入学习实现配对神经成像数据的多扫描仪协调。美国电气与电子工程师协会国际会议计算机会议。2021;2021 年十月 b:3277–3286。doi:10.1109/iccvw 54120.2021.00367

8.Wachinger C,Rieckmann A,Pö lsterl S .检测和纠正多位点神经影像数据集中的偏差。医学图像分析。2021;67:101879.doi:10.1016/j . media . 200015863617

9.Wang R,Chaudhari P,Davatzikos C. 与基于流的因果推理的协调。第 12903 卷 LNCS。斯普林格国际出版公司;2021.doi:10.1007/978–3–030–87199–4 _ 17

用熊猫批量处理 22GB 的交易数据

原文:https://towardsdatascience.com/batch-processing-22gb-of-transaction-data-with-pandas-c6267e65ff36

如何利用有限的计算资源处理大型数据集

卢克·切瑟在 Unsplash 上的照片

大型数据集很难处理。如果你没有必要的资源,它们甚至更具挑战性。我们大多数人都无法访问分布式集群、GPU 机架或 8GB 以上的内存。这并不意味着我们不能弄脏一些大数据。我们只需要一次解决一件事。也就是说,一次迭代整个数据集并处理子集。

资料组

我们将向您展示如何使用大型(随机生成)事务数据集来实现这一点。该数据集包含 75,000 名客户的超过 2.6 亿笔交易。交易时间从 2010 年到 2020 年。每笔交易被分为 12 种支出类型(如杂货)。你可以在图 1 中看到更多细节,并在 Kaggle 上找到完整的数据集。你也可以在 GitHub 上找到这个教程的笔记本。

图 1:交易数据集概述(来源: Kaggle ) ( CC0:公共领域)

我们将看到如何使用批处理来创建这些数据的不同聚合。具体来说,我们将计算:

  • 交易总数
  • 年度总支出
  • 2020 年月均娱乐支出

最后,我们将讨论如何加快创建这些聚合的过程。

成批处理

我们将使用一些标准的 Python 包。我们有 NumPy 和 Pandas 用于数据操作,matplotlib 用于一些简单的可视化。确保你已经安装了这些。

首先,让我们尝试用熊猫加载整个数据集。过了一会儿,我们得到图 2 中的错误消息。只有 8GB 的 RAM,不可能将整个数据集加载到内存中。

图 2:错误信息

为了解决这个问题,我们可以加载数据集的一个子集。为此我们可以使用 read_csv 函数中的skipowsnrows 参数。下面我们将参数值分别设置为 1000 和 2000。这意味着我们将跳过 CSV 的前 1000 行,加载后面的 2000 行。我们还需要将列名作为参数传递(第 8 行)。这是因为我们跳过了 CSV 中的第一行名称。

我们可以使用这些参数迭代我们的数据集。为此,我们创建了下面的 get_rows 函数。这可以使用返回数据集的子集。每个子集将包含由 步骤 参数确定的行数。 计数 参数是可变的,以在每一步返回不同的子集。为了理解如何使用这个函数,我们将计算数据集中的事务总数。

计算交易数量

我们在 while 循环中使用了 get_rows 函数。在循环的每次迭代结束时,我们将更新计数(第 19 行)。这意味着我们将加载数据集的一个新子集(第 13 行)。我们设置步骤数,以便每次返回 500 万行(第 1 行)。但是,数据集中的行数不是 500 万的倍数。这意味着在最后一次迭代中,返回的行数不到 500 万。我们可以用它来结束 while 循环(第 22–23 行)。

对于每次迭代,我们计算子集的长度,并将其添加到事务总数中(第 16 行)。最后,我们输出有 261,969,720 个事务。对如何批量处理数据集有了很好的理解,我们可以继续进行更复杂的聚合。

年度总支出

对于这种聚合,我们希望对每年的所有交易金额进行求和。我们可以遵循与之前类似的过程。现在,对于每次迭代,我们希望更新数据集中每年的总数。我们首先创建一个 pandas 系列,其中索引是年份,值是总支出金额(第 2 行)。我们每年的总支出为 0 英镑。

对于每次迭代,我们按年份对支出金额求和(第 10 行)。结果是另一个数列, exp ,索引与 total_exp 相同。这允许我们循环每年并更新总数(第 13–15 行)。

我们使用下面的代码来可视化这个聚合。您可以在图 3 中看到输出。除 2020 年外,总支出逐年稳步增长。对于这个聚合,所有的计算都在 while 循环中完成。正如我们将在下一个聚合中看到的,情况并不总是这样。

图 3:2010 年至 2020 年的年度总支出

2020 年月均娱乐支出

对于许多聚合来说,我们不仅仅是增加一个总量。对于这种聚合,我们首先需要计算每个客户每月花费在娱乐上的总金额。然后,对于每个月,我们可以计算所有客户的平均值。首先,我们创建一个空的 pandas 数据框(第 2 行)。

对于每一次迭代,我们过滤掉交易,因此只保留 2020 年的娱乐交易(第 10 行)。然后,我们按客户和月份合计金额(第 11 行),并将该表附加到 total_exp (第 14 行)。这样做后,客户和月份可以重复。这是因为并非客户的所有交易都必须在一次迭代中捕获。这就是我们再次聚合该表的原因(第 17 行)。

最后,我们将得到一个包含所有客户每月总数的表。最后一步是计算每个月的平均金额(第 26 行)。您可以在图 4 中看到这些平均值。这里的平均值是稳定的,然后在 10 月、11 月和 12 月增加。

图 4:2020 年平均娱乐支出

只有时间

因此,即使资源有限,我们也要分析这个庞大的数据集。最大的问题是运行每个聚合所花费的时间。在我的机器上,每个聚合需要大约 50 分钟!尽可能加快速度是很重要的。

占用时间最多的部分是使用 get_rows 函数加载行的地方。在这里,我们将数据从硬盘上的 CSV 加载到内存/RAM 中。因此,不要使用多个 while 循环,而应该尝试在同一个循环中进行多次聚合。这样,我们只需要从磁盘读取一次数据。

我希望这篇文章对你有帮助!你可以成为我的 推荐会员 来支持我。你可以访问 Medium 上的所有文章,我可以得到你的部分费用。

https://conorosullyds.medium.com/membership

你可以在|Twitter|YouTube|时事通讯上找到我——注册免费参加 Python SHAP 课程

参考

c 奥沙利文,模拟交易, CC0:公共领域https://www . ka ggle . com/datasets/conorsully 1/Simulated-Transactions

Neo4j 中的批处理事务

原文:https://towardsdatascience.com/batching-transactions-in-neo4j-1001d12c9a4a

了解 APOC 和本地 Cypher 批处理事务方法的区别

Unsplash 上由 Bernd Dittrich 拍摄的照片

当在 Neo4j 中处理大量图形和更大范围的更新时,如果不采用批处理事务,您可能会耗尽堆内存。虽然您可以使用自己喜欢的脚本语言来批处理事务,但是您也可以直接在 Cypher 中或者在 APOC 库的帮助下将一个 Cypher 查询拆分成多个事务。
本文旨在演示后者,也就是说我们将只看如何将一个 Cypher 查询拆分成多个事务。

我们将使用由国际调查记者联盟(ICIJ)提供的 ICIJ 天堂文件数据集。ICIJ 在出版引人注目的研究方面有着悠久的历史,如《巴拿马》、《天堂》和最新的《潘多拉文件》。如果你感兴趣,你可以在他们的网站上探索数据集,或者下载数据(在开放数据库许可下授权)并用你最喜欢的数据挖掘工具探索。幸运的是,数据集可以作为 Neo4j 沙盒项目使用。Neo4j 沙盒是 Neo4j 的一个免费云实例,附带一个预填充的数据库。点击下面的链接来创建你自己的 Paradise Papers 数据集的沙盒实例。

虽然图模型稍微复杂一点,但是我们将只使用图的以下子集来进行演示。

天堂论文图的子集。图片由作者提供。

我们只对军官(绿色)和实体(橙色)以及两者之间的军官 _ 关系感兴趣。这实质上是一个包含两种类型节点的双向网络。为了分析二部网络,作为分析的第一步,我们经常把它们转换成一个单部网络。在这个例子中,我们将使用上面的两部分网络,并设计一个代表官员的单部分网络,他们之间的关系将定义他们是否有以及有多少个实体是共同的。

军官的单方投射。图片由作者提供。

这是 Cypher 中一个简单的操作。我们简单地匹配原始模式并计算出现的次数,并可选地将结果存储为官员之间的关系。但是,这些类型的操作很可能会导致行数激增。

MATCH (n:Officer)-[:OFFICER_OF]->(:Entity)<-[:OFFICER_OF]-(m)// avoid duplication
WHERE id(n) < id(m)// count the number of occurrences per pair of node
WITH n,m, count(*) AS common// return the total number of rows
RETURN count(*) AS numberOfRows

在我们的示例中,我们需要创建 1.313.187 关系,以投射一个由官员组成的单一参与者网络,并将公共实体的数量存储为关系权重。如果两个官员没有共同的实体,则不会创建关系。

不幸的是,Neo4j 沙盒实例只有 1GB 的堆内存。因此,在单个事务中创建超过一百万个关系可能会遇到内存问题。在继续之前,我们需要增加事务超时设置。默认情况下,沙盒实例的事务超时为 30 秒,这意味着如果事务持续时间超过 30 秒,它将自动终止。我们可以通过设置以下事务超时配置来避免这种情况。

CALL dbms.setConfigValue(‘dbms.transaction.timeout’,’0');

对于那些对 Neo4j 和批处理有一些经验的人来说,您可能熟悉apoc.periodic.iterate过程,它经常用于批处理事务。

CALL apoc.periodic.iterate( // first statement
  "MATCH (n:Officer)-[:OFFICER_OF]->()<-[:OFFICER_OF]-(m)
   WHERE id(n) < id(m)
   WITH n,m, count(*) AS common
   RETURN n,m, common",
  // second statement
  "MERGE (n)-[c:COMMON_ENTITY_APOC]->(m)
   SET c.count = common", 
  // configuration
  {batchSize:50000})

在第一个语句中,我们提供了要操作的数据流。数据流可以由数百万行组成。第二条语句执行实际的更新。在我们的例子中,它将在一对军官之间创建一个新的关系,并将计数存储为关系权重。通过在配置中定义batchSize参数,我们描述了在单个事务中提交的行数。例如,通过将batchSize设置为 50.000,事务将在第二条语句执行 50.000 次后提交。在我们的例子中,第一条语句产生 130 万行,这意味着更新将被分成 26 个事务。

在 Neo4j 4.4 中,批处理事务作为一个本地 Cypher 特性被引入。要只使用 Cypher 对事务进行批处理,您必须定义一个更新图形的子查询,然后是IN TRANSACTIONS OF X ROWS

:auto MATCH (n:Officer)-[:OFFICER_OF]->()<-[:OFFICER_OF]-(m)
WHERE id(n) < id(m)
WITH n,m, count(*) AS common
CALL {
 WITH n,m,common
 MERGE (n)-[c:COMMON_ENTITY_CYPHER]->(m)
 SET c.count = common} IN TRANSACTIONS OF 50000 ROWS

如果在 Neo4j 浏览器中执行上述 Cypher 语句,必须在前面加上:auto命令。否则,在用您喜欢的脚本语言执行这个 Cypher 查询时,您可以省略它。逻辑与 APOC 配料相同。我们首先定义数据流(第一条语句),然后使用子查询(第二条语句)来批量处理大量更新。

什么时候用哪个?

那么有什么区别呢,什么时候应该用哪个呢?

我认为最大的区别在于他们处理错误的方式。首先,如果一个批处理中的一次执行失败,那么整个批处理都会失败,不管您是使用 APOC 还是 Cypher 来批处理事务。但是,在单个批处理失败后,Cypher 变体将不会继续操作,并且之前成功提交的所有事务都不会回滚。因此,如果第三个事务失败,前两个成功提交的事务将不会回滚。
相反,如果一个中间批次失败,APOC 变体没有问题,并且不管怎样都会遍历所有批次。此外,APOC 还可以定义批处理失败时的重试次数,这是本机 Cypher 事务批处理所缺乏的。

例如,当您想通过外部 API 更新节点时,我建议使用值为 1 的apoc.periodic.iterate。由于外部 API 是不可预测的,并且可能成本很高,所以我们希望存储从 API 收集的所有信息,并遍历所有节点,不管中间是否有更新失败。

apoc.periodic.iterate的另一个特性是可以选择并行运行更新语句。我们需要确保在进行并行更新时不会遇到任何死锁。否则,事务执行将失败。根据经验,在创建关系时不能使用并行执行,因为查询可能会尝试创建从同一节点开始或结束的多个关系,这将导致节点死锁和执行失败。然而,当您更新单个节点属性一次时,您可以确信您不会遇到任何死锁。例如,如果您想将节点度数存储为节点属性,您可以使用并行执行。

CALL apoc.periodic.iterate(
  "MATCH (o:Officer)
   RETURN o",
   "WITH o, size((o)--()) AS degree
    SET o.degree = degree", 
   {batchSize:10000, parallel: true})

结论

总而言之,apoc.periodic.iterate似乎是事务程序家族中年龄更大、更成熟的兄弟。到目前为止,我更倾向于使用 APOC 批处理,而不是本地 Cypher 批处理。我认为 Cypher 方法的唯一优点是,如果你想在一个批次失败后终止操作,否则我仍然建议使用 APOC。

附:如果你对图形分析感兴趣,我已经准备了一个 s 以前天堂论文数据集的充足图形分析 s

数据容器之战——哪种 Python 类型的结构是最好的?

原文:https://towardsdatascience.com/battle-of-the-data-containers-which-python-typed-structure-is-the-best-6d28fde824e

Class,dataclass,attrs,pydantic 还是 NamedTuple,哪个容器最适合你的项目?让我们找出答案。

图片作者。

我们开始了一个全新的项目,积极性很高。在基本规划完成后,我们开始对我们的应用程序进行初始分类,我们即将构建将通过我们的应用程序管道流动的数据模型。

突然我们碰了壁,我们必须在项目的早期做出妥协的选择,我们应该选择什么样的数据容器,静态输入信息?

十年前,选择会更简单。那时候没有打字模块。数据容器是非常基本的。十年过去了,情况有了很大的不同,Python 作为一种语言已经有了巨大的发展,它的社区也是如此。大多数 ide 都支持静态类型,这使得类型提示成为大型项目的必备条件和所有代码的最佳实践。

所以回到我们的问题,我们应该选择哪个容器?有许多选择,事实上是伟大的选择。没有明确的目标,但是在这个故事中,我们将测试和比较一些最流行的容器。在故事的结尾,选择应该更简单,你应该能够根据我们项目的需求来选择。

目录

  • 关于 slots 的快速注释
  • 编写测试代码
  • 普通班
  • 数据类
  • 属性
  • Pydantic
  • 命名元组
  • 控制,字典
  • 试验结果
  • 结论

关于 slots 的快速注释

插槽是一种让类更有效的内存和更快的方法。通过使用槽,我们显式地定义(硬编码)了类的属性。

标准 Python 类在 dict dunder 方法中存储属性(在幕后),顾名思义,这是一个字典。这允许我们在运行时设置新的属性。如果我们不想在运行时设置新的属性,这不是很有效。

另一个选择是使用 slots dunder 方法,它覆盖 dict。在标准类中,我们必须对属性进行硬编码,但是有一些数据容器提供了像布尔标志这样简单的插槽功能(将在接下来的部分中显示)。

编写测试代码

时间是关键,性能是大多数应用程序的关键。

因此,在我们开始测试之前,我们创建了一个小的 Timer 类来测量纳秒级的时间。该类使用来自时间标准模块的“perf_counter_ns”方法,这是测量两个事件之间时间的最精确方法(来自时间模块)。

这个定时器非常简单,它公开了一个“start()”方法和一个“stop()”方法,以及一个“time”属性来检索定时器的结果。

所有将被测试的容器都应该实现这个简单的协议(接口):

我们将执行的测试包括:

  • 创建对象所花费的时间,“时间 _ 人员 _ 创建”
  • 从类“time_person_get”中获取属性所花费的时间
  • 在类“time_person_set”中设置属性所花费的时间(注意,这只适用于可变对象)
  • 对象使用的内存(以字节为单位)(为此我们使用 Pympler,一个简洁的内存分析第三方库)

下面的代码将我们的四个测试封装到一个函数(“test_person_container”)中,该函数运行测试的 n_trials 并报告每个测试的平均值。该函数有一个布尔标志参数 test_set ,其中T5 表示是否测试 set 属性(对于不可变对象,应该设置为 False )。

测试结果在一个PersonTestResultobject中返回(注意,尽管这是一个 dataclass,但它不是测试的一部分)。

普通班

我们的第一个容器是普通的旧类。我们用 dict 方法( PersonClass )测试标准类,用 slots(person class slots)测试另一个类。

就可读性而言,注意单词“name”和“age”在每个类定义中出现的次数。这是使用常规类的一个巨大缺点。

另一个缺点是当我们打印一个类的实例时会发生什么,对于一个普通的类,会打印一个内存地址。这对于数据容器来说不是很方便。要解决这个问题,我们必须用我们想要打印的信息编写一个 repr dunder 方法。这将进一步增加单词“姓名”和“年龄”被书写的次数。

对数据使用通用类还有许多其他注意事项。

所以总的来说,将常规类用作包含输入信息的数据容器并不是最好的主意,但仍然是可行的。

数据类

在 Python 3.7 中引入了 dataclasses,它们解决了上一节中讨论的许多问题。我只想说,数据类很棒。我一直在使用它们,只是喜欢使用它们。然而,这不会使测试有偏差。

数据类(直到 Python 3.10)的一个主要问题是没有简单的方法来使用槽。但是如果你使用的是 Python 3.10+你是 golden,你可以使用 slots 布尔标志作为参数。使用数据类是如此简单,这不是很好吗?

属性

很棒的第三方库。事实上,数据类是基于属性功能的。因此,它是一个非常成熟和健壮的库。

就我个人而言,我不经常使用 attrs,但它的功能非常棒。如果你希望你的项目有一些功能,attrs 可能会满足你。

然而,在我看来,与 dataclasses 相比,语法并不简单或优雅,但这只是我的看法。

Pydantic

又一个很棒的第三方库。然而,与测试中的其他容器相比,pydantic 可能属于不同的类别。Pydantic 的主要目的是解析和使用 ORM,也就是说,它更适合对数据进行净化/验证,而不仅仅是一个容器。

我喜欢 pydantic,也有很多功能。但是,在使用 pydantic 之前,您必须确保实际上您需要整理数据,因为这会影响性能,您将在下面几节中看到这一点。

顺便说一下,还有止痛药。BaseModel 是 pydantic 的旗舰产品,但也有一个 pydantic 数据类,隐藏在库中。我们也会测试它。

命名元组

我可能应该更多地使用 NamedTuple。这是一个非常简单的类型化元组实现。因此,也许我应该使用 NamedTuple,而不是将函数返回的多个值包装在 dataclass 中(如果这是一个借口,我喜欢 decorators)。

抛开所有的乐趣不谈,当你需要一个不可变的容器时,NamedTuple 是一个很好的选择,它继承了 Tuple。因此,这是一种在代码中清楚表明某些东西不应该被弄乱的干净方式。

因此,如果您确定想要一个不可变的对象,那么就选择 NamedTuple。如果你想改变一些东西,你必须创建另一个实例,这将导致性能下降。

控制,字典

为了能够比较容器,我们还将测试普通字典,即它将是我们的控制。十年前,dict 将是我们的通用数据容器。

我们将为 dict 编写一个单独的测试,因为 dict 没有实现我们为一般测试定义的接口:

试验结果

下图显示了创建时间、获取属性时间、设置属性时间(如果适用)和内存使用的结果。

似乎 pydantic 在创建时间和设置属性时间上是一个异常值。正如我们前面提到的,pydantic 的主要功能是净化/验证,在解析时非常有用。然而,这需要付出性能成本。所以我不会将 pydantic 作为通用数据容器。

图片作者。所有容器的结果。越低越好。

在下面的图中,我们给出了相同的结果,但没有 pydantic 的测试,图的比例现在更适合于比较其他容器。

图片作者。不包括 pydantic 的容器结果。越低越好。

正如我们所预料的,使用插槽时,无论是在使用插槽的常规类、使用插槽的数据类还是使用插槽的属性中,性能都会有所提高。

下图总结了结果。为了避免比例问题,省略了 Pydantic。需要注意的是,带槽的数据类和带槽的属性几乎完全重叠,所以出于可视化的目的,带槽的属性没有显示出来。

图片作者。气泡图摘要。带插槽的属性被省略,因为它与带插槽的数据类几乎完全重叠。x 越低越好,y 越低越好,气泡越小越好。

结论

从人数上来看,有空位的班级是明显的赢家。然而,正如我们之前讨论的,使用常规类作为数据容器并不方便。如果我们包含了 attrs 或 dataclass 的方法,那么我们的常规类将不会是轻量级和高性能的。

所以我们继续宣布并列第一,带槽的属性和带槽的数据类是赢家。

最后的裁决是:

  • 如果您使用 Python 3.10+并且不希望任何第三方依赖,请使用 dataclasses(可能的话使用插槽)。
  • 如果你想要功能上的灵活性和健壮性,不管是 Python 版本还是第三方依赖,都可以使用 attrs。
  • 如果你低于 Python 3.10,不想依赖第三方,想要简单和不可变的东西,那么 NamedTuple 适合你。

我希望这个故事对你有用。如果我错过了什么,请让我知道。如果你想知道更多这样的故事,请关注我。

*https://medium.com/subscribe/@diego-barba

喜欢这个故事吗?通过我的推荐链接成为媒体会员,可以无限制地访问我的故事和许多其他内容。

https://medium.com/@diego-barba/membership *

R 中的贝叶斯 A/B 检验

原文:https://towardsdatascience.com/bayesian-a-b-testing-in-r-4c6471e2e10e

使用贝叶斯统计和频率统计分析社交媒体表现

UnsplashAdem may拍摄的照片

专业人士总是想知道如何改进他们的产品和服务。营销从业者通常会质疑,对他们网站的修改会如何改变网上购买,从而最大限度地提高销售额。类似地,科学家们相互测试不同的药物版本,以确定对未来患者最有效的药物。每当需要对可比较的选项进行相互测试时,我们可以运行一个小实验来回答以下问题:版本 A 与版本 B 有何不同?

什么是 A/B 测试?

A/B 测试只是一个经典假设测试的花哨术语,其中 A 和 B 只是代表一个事物的不同变量。例如,他们可以参考来自临床试验数据的对照条件(A)和治疗条件(B)。另一个广泛采用 A/B 测试的领域是市场营销。

专业人士通常想知道有多少客户使用了 A)原始版本和 B)稍有改动的版本。为了找到答案,他们设计了一个随机实验:人们被随机分配到两个组,分别展示两个版本中的任何一个。为了找出哪一个更好,他们测试哪一个在特定的成功指标上得分更高。例如,这可以是转换率之类的东西;这是已经完成期望动作的用户的百分比,即点击广告的用户数量除以观众的总体规模。点击广告被认为是成功的,而不点击则是失败的。

最终目标是做出数据驱动的决策来改进网站:无论哪个版本吸引更多的用户,都将被采用。为了确保他们开发自己的潜力并获得近乎完美的最终结果,他们多次重复这个过程:收集关于当前版本的数据,并针对潜在的进步进行测试。

本文的内容

通常,这一过程是由一种叫做 NHST(零假设显著性检验)的统计学方法支持的,也称为频率主义统计学,这是世界各地教授的传统方法。然而,这种范式因其误导性的解释而受到从业者和科学家的批评。为了寻找更直接的方法来检验假设,人们经常求助于贝叶斯统计。当营销活动背后有如此多的资金处于风险中时,我们应该对我们的选择非常有信心,最好是建立在以前的数据基础上。贝叶斯方法符合它吗?我也这么认为

在本文中,您将找到关于以下内容的实用信息:

  • Bayesian 和 Frequentist A/B 测试在理论和实践上的主要区别。
  • 计划你的实验的步骤和指定先验,测试假设和评估证据的数量。
  • A/B 测试的实践方面,通过在真实数据集上比较视频和照片帖子的用户参与度。

假设检验的痛苦——频率主义者与贝叶斯主义者

贝叶斯统计是关于随着新信息的出现而更新一个人对某事的信念。它允许分析师整合先前的知识(例如,基于先前的数据,我们可以预期不同类型的出版物在用户参与度上有多大差异?).随着新数据的到来,我们不断地在不同选项之间重新分配可信度,直到我们有足够的证据。这种方法是科学中的元分析和商业环境中的连续分析的理想候选方法——它可能会节省你花费在分析上的资源,这些分析无论如何都不会有结果。这在效率方面是一个很大的优势!

这两种范式之间最根本的区别似乎是对概率的反向理解。 frequentist 这个词的意思是,概率是指模拟数据的抽样分布。在引擎盖下,如果我们假设 A 和 B 之间没有差异,那么 p 值的计算依赖于假想测试统计量(例如,t 值)的分布。因此,我们可以说,根据零假设观察到这样的数据是多么的不可能。通过观察样本留下的结果比例,我们可以评估我们的观察结果有多极端或不寻常。事实上,这就是著名的 p 值估计值:在给定零假设的情况下观察数据的估计概率。相比之下,贝叶斯概率是基于在给定数据的情况下对特定假设的合理信任程度。所以,解读正好反过来。

你可能会同意,这种对重要性的解释更直观,也符合我们的自然思维方式:我们从数据出发,对自然中存在的影响做出推断,而不是反过来。另一方面,根据零假设,我们通常对数据的可能性不感兴趣——事实上我们也不相信这一点。没有必要为贝叶斯统计进行这些心理体操。此外,它有点卑微,因为我们接受了每一个统计估计带来的不确定性程度。这背后的原因在于所谓的概率分布。如果我们以用户参与度为例,分析是基于关于它通常采用的特定值和概率的信息。我们对一项事业(例如,社交媒体内容)的成功有一个想法,这是基于我们的专业知识和收集数据来更新我们的信念。

B 亚洲人分析数据的方式与学习的方式完全一样:我们在观察的同时调整我们的信念,从而不断增长我们的知识。

如果你对这个话题的更多理论细节感兴趣,请阅读我的文章关于频率主义者与贝叶斯统计预测我婚礼上的天气。

简而言之,关键区别在于

贝叶斯 A/B 测试…

  • 量化A 和 b 的成功之间的差异。相比之下,频率主义者的方法只是说了一些关于是否存在差异的事情。
  • …区分不同的假设,并根据数据证明不存在影响(例如,A 和 B 没有不同)。然而,低 p 值只是间接证据,表明数据太不确定或不够奇怪,不足以拒绝零假设。
  • …通知经济决策。因为 frequentist 统计不估计参数的概率(例如,A 对 B 的转换率),我们不能将其转换回相关的业务成果,如预期利润或存活率。
  • …对非统计人员来说是真正的直观或直接的。它自然补充了人类对证据的思考方式。对于常客来说,概率的解释是颠倒的,这使得直接理解很痛苦。
  • …需要的数据更少 数据更省时。与 frequentist 统计不同,Bayesians 不遵循在达到全部样本量之前会使现有数据分析不合法的抽样计划。

关于 R 包的一个简短注记

到目前为止,R 中有两个专门研究贝叶斯 A/B 测试的包,它们基于不同的假设。 bayesAB 包(Portman,2017)基于“独立贝塔估算”(IBE)方法,该方法假设:

  • A 和 B 的成功概率是独立的,因此了解一个实验条件的成功率不会影响我们对另一个实验条件的成功率的了解。
  • 一种效应的存在,所以实验操作必须在某种程度上是有效的,我们无法获得支持零假设的证据。

Logit 转换测试(LTT)方法克服了这些限制,该方法由 R (R 核心团队,2020)中的(Gronau,2019)在 abtest 包中实现。这是我们将在即将到来的案例研究中使用的,以产生更丰富的结果,如果您对技术细节感兴趣,我建议您阅读 Hoffmann,Hoffman&wagen makers(2020)的论文。

照片由罗宾·沃拉尔Unsplash 拍摄

基准社交媒体性能

营销领域的一个典型例子是分析公司网站的用户参与度,以提高其受欢迎程度。在本案例研究中,我们将只关注这一点。从技术上来说,用户或客户参与被定义为对一家公司的自愿和潜在的盈利行为。例如,它可以表现为这样一个事实,即一个人愿意通过口口相传、写评论、分享信息或提及产品来吸引对一家公司以及潜在客户的注意。这应该给营销人员敲响了警钟,因为用户参与本质上是免费的,创造了一个对品牌有益的关系,从长远来看可能会增加销售额。但是为什么不简单的用点击率,那么实际点击过帖子或者广告的用户数呢?

因为用户参与度是我们的社交媒体内容引发某种兴趣的程度的更强指标,这需要用户关注。具体来说,我们想知道视频是否比照片更能吸引用户。Databox 甚至表示,视频需要用户更加专注,因为它们不像照片那样容易被消化,因此会产生两倍的点击量和 20-30%的转化率。

我们将使用的数据集来自 Moro 和 Rita (2016)的一篇开源论文,其中包括 2014 年 1 月 1 日至 12 月 31 日期间收集的全球知名化妆品品牌脸书页面的 500 篇帖子。作者分析了 12 个结果变量,如下所示:

  • 终身帖子总到达人数:看到页面帖子的人数(唯一用户)。
  • 终身帖子总浏览量:浏览量是页面中某个帖子被显示的次数,无论该帖子是否被点击。
  • 终身参与用户:点击帖子任意位置的人数(独立用户)。
  • 总互动:帖子的“喜欢”、“评论”和“分享”的总和。

为了进一步描述我们处理的帖子的特征,还有五个其他变量可用:

  • 类型:分类为帖子是链接、照片、状态还是视频。
  • 类别:分类为帖子是指一个行为(特别优惠和竞赛)、产品(直接广告、明确的品牌内容)还是灵感(非明确的品牌相关内容)。
  • 付费:品牌是否向脸书支付广告费用的分类(是/否)。

加载数据并查看描述性统计数据

在定义了一个 R-project 之后,我们可以使用简洁的 here-package 以一种简单的方式来设置我们的路径,这种方式更能抵抗本地机器上的变化(Müller & Bryan,2020)。我推荐使用 data.tablefread()函数来加载数据,因为它比read_csv()函数快得多,并且更频繁地获得正确的数据格式(Dowle,2021)。让我们看看我们的原始数据。

声明:所有图片均由作者制作,除非另有说明。

只有 5 个观察值缺失,skim()函数给出的摘要显示了一些描述性统计数据,包括平均值、标准偏差、百分位数以及每个变量的直方图(18 个数值;1 因子)。

为了了解发布了多少出版物,我们加载了 dplyr 包,并按类型统计了观察的数量。

# A tibble: 4 x 2
# Groups:   Type [4]
  Type       n
  <fct>  <int>
1 Link      22
2 Photo    426
3 Status    45
4 Video      7

事实证明,绝大多数内容由照片(426 张)组成,而链接(22 张)、状态更新(45 张)和视频(7 张)则不太常见。现在,这不应该让你气馁,因为重要的是每篇帖子背后的观察次数——通过尝试次数获得的成功次数,或者换句话说:通过 reach 获得的每种内容类型的参与用户数量,我们将在以后保存。

如何计算参与度

现在,参与帖子的原始用户数量可能会根据其覆盖范围而有很大波动,所以我们需要一种标准化的方法来衡量性能。因此,我们将创建一个百分比来表示参与用户的数量相对于看过帖子的总人数。Hootsuite 写了一整本关于计算参与度的不同方法的指南,我强烈推荐你阅读。脸书给你提供了各种营销人员可能感兴趣的指标,但为了简单起见,我们将坚持一个指标。

利用先验知识设计实验

由于 frequentist 统计高度依赖于数据,我们需要首先运行功效分析,以找出哪些数量的数据点足以捕捉感兴趣的效果。我们将使用 R (Qiu,2021)中的 powerMediation 包将其应用于我们的问题,因为我们稍后将运行逻辑回归。

该函数采用以下参数

  • 基线值—当前质控条件的值
  • 期望值—测试条件的期望值
  • 测试条件下的数据比例(理想情况下为 0.5)
  • 显著性阈值/alpha——我们认为影响为(通常为 0.05)的水平
  • 幂/1—β—正确拒绝零假设的概率(通常为 0.8)

根据 Hootsuite 发布的分析结果,脸书社交媒体内容的平均参与度为 0.06%。这个参与度不是根据看过帖子的人数计算的,而是根据关注者的数量计算的。然而,我们将此作为基线条件(照片的参与度)的基准。让我们假设视频比照片吸引了 50%的用户,这将导致 0.09%的参与率(期望值)。之前,我们已经计算了每种类型的内容范围,因此我们知道逻辑回归将基于的观察值的数量。不幸的是,我们没有相等的组大小,但是来自测试条件的数据的比例是 0.06%。显著性水平和功效被设置为默认值。

根据功效分析,我们需要总共 9947 个独立用户的样本量。理论上,这将使正确剔除空值的概率保持在 80%。因为我们总共有 5,955,149 个用户的样本,这些用户通过社交媒体帖子访问了这两种类型,超过了最小样本量。所以,我们很好!

现在让我们为贝叶斯 A/B 测试指定我们的先验。如前所述,我们假设视频内容比照片内容吸引多 50%的用户。假设 50%的收益对应于先前的中值,该预期对应于 0.03 的中值绝对风险(即,成功概率的差异)。我们构建了一个 95%的不确定性区间,范围从 0.01(几乎没有差别)到 0.12(成功的两倍)。

测试你的假设,更新你的知识

对于我们的假设检验的频率主义方法,我们想运行一个逻辑回归。但是因为我们加载的数据集不包含二元结果变量(是/否),所以我们首先需要创建一个。我们将使用的rbinom()函数要求我们知道每种内容类型的成功比例(1 而不是 0 ),因此我们可以使用之前创建的项目摘要。

> ER_summary
# A tibble: 4 x 4
  Type   Engagement   Reach     ER
  <fct>       <int>   <int>  <dbl>
1 Link         7542  407981 0.0185
2 Photo      348871 5596709 0.0623
3 Status      91810  588550 0.156 
4 Video       11949  358440 0.0333

啊?看起来好像视频实际上导致了比照片更低的参与度。让我们将这些值插入到 rbinom()函数中,以生成两个表示这个分布的对象。然后,我们向每个对象添加一个字符串来跟踪内容类型,并将两个对象合并到一个大的数据帧中。

我们使用glm()(广义线性模型)函数并将 family-argument 设置为二项式来运行逻辑回归。为了获得更清晰的模型输出,我们使用了扫帚包中的tidy()函数。

# A tibble: 2 x 5
  term        estimate std.error statistic p.value
  <chr>          <dbl>     <dbl>     <dbl>   <dbl>
1 (Intercept)   -2.75    0.00178   -1546\.        0
2 TypeVideo     -0.703   0.00986     -71.3       0

我们可以看到,与视频的曝光相比,视频的曝光使得成功的概率(用户参与度)更低。具体来说,与照片相比,用户参与内容的对数几率显著降低0.7。通过取指数,我们可以将对数比值转换回一个更容易解释的值——比值比。成功几率被定义为成功概率与失败概率之比。我们得到的比值比为 0.5 比 1,这表明——与照片相比——视频内容降低了用户参与的几率,降低了 0.5 倍。相比之下,如果成功的概率在两种情况下随机分布,那么成功的几率将是 1 比 1(优势比为 1)。

我们的 p 值低于 0.05 这一事实意味着零假设——照片和视频内容同样成功——似乎与数据有些不符。不多也不少。根据数据,它没有说明替代假设(例如,版本之间的差异)是否为真。因此,让我们转向贝叶斯 A/B 测试来回答这个问题。

从我们的 ER_summary 中我们知道,观察到的成功概率对于照片是p1 = .062,对于视频内容是p2 = .033。因此,观察到的成功概率表明,接触 0.3%的视频会产生负面影响。为了查明这在统计上是否有说服力,使用了 abtest 包中的贝叶斯 A/B 检验:

> print(ab)
Bayesian A/B Test Results:Bayes Factors:BF10: Inf
BF+0: 0.0001890052
BF-0: InfPrior Probabilities Hypotheses:H+: 0.4
H-: 0.1
H0: 0.5Posterior Probabilities Hypotheses:H+: 0
H-: 1
H0: 0

输出的第一部分给出了支持假设 H1、H+和 H-的贝叶斯因子,其中参考假设(即贝叶斯因子的分母)是 H0。贝叶斯因子估计可信度从先验分布向后验分布重新分配的程度。换句话说,它告诉我们有多少需要根据新数据更新我们的信念。具体来说,贝叶斯因子是数据中支持两个假设之一的相对证据。换句话说,它是一个假设比另一个假设更好地预测观察到的数据的程度。请注意,贝叶斯因素是而不是在看到数据后一个假设相对于另一个假设的似然性(这将是后验概率)。

由于正效应(H1)的贝叶斯因子假设小于 1,这表明有证据支持无效应的零假设。但我们在这里得到了一个更微妙的画面:当我们假设视频内容对用户参与度有负面影响时,H-的无限高的贝叶斯因子表明了反对零假设的有力证据。输出的下一部分显示了假设的先验概率:之前,我们假设 H1 和 H0 的概率相等,但是我们基于我们的先验知识,给了积极影响的存在更多的可信度。

如果我们观察后验概率,一幅非常清晰的画面出现了:根据这些数据,我们必须完全刷新我们对 H-的理解,因为负面效应的似然性已经从 0.1 增加到 1。相反,这意味着 H+和 H0 都不太可能出现。

估计证据的大小

我们的逻辑回归不允许对每种内容类型的成功概率进行任何推断;它只让模型适合我们的样本数据,留给我们一个点估计。我们只能描述观察到的参与率,并尝试观察两种类型之间的实际差异。让我们绘制数据以获得一个粗略的印象:

好的,我们可以看到不同帖子的内容类型之间的差异,并得到一个实际的感觉,补充我们已经知道的数字。我们还可以直接看到,与照片内容相比,视频内容备份的数据要少得多。

然而,这些只是描述性的统计数字。相比之下,我们实际上可以用我们的贝叶斯框架推断后验成功概率,从而对证据的大小和效果的方向做出陈述:

在我们的示例中,p1 和 p2 分别对应于用户参与照片和视频内容的概率。该图表明 p1(照片)的后验中值为 0.062,95%可信区间为 0.062 至 0.063,p2(视频)的后验中值为 0.033,95%可信区间为 0.033 至 0.034。我们还可以看到 p2(视频)的可信区间实际上更宽,这没有反映在裸数字中,因为默认情况下我们只有三个十进制值。其原因可能是,与基线相比,对于相对较少的数据,成功的估计更不确定。

总之,我们的数据为另一个假设提供了有力的证据,即与照片相比,视频对用户参与度有负面影响。此外,我们有强有力的证据反对零假设,即两种内容类型之间没有影响,以及反对正影响的假设。

看看证据的出现

对于我们的 frequentist 分析,没有办法测试证据实际上是如何在试验中出现的,因为零假设显著性测试假设我们在分析任何结果之前首先完成数据收集。但我们能做的是改变样本计划,并允许临时分析,以节省我们的资源并防止 p-hacking,同时仍保持我们对假警报的(不)容忍度。因此,我们需要定义特定的停止规则来运行顺序分析。这是一个在收集数据时随着时间的推移重复进行统计测试(如逻辑回归)的过程。每次观察后,对累积数据进行分析,并做出以下三个决定之一:

  • 停止数据收集,拒绝零假设,宣称“统计显著性”(如数据有说服力)。
  • 停止数据收集,不要拒绝零假设,并声明结果不具有统计学意义(例如,数据是非决定性的)。
  • 继续收集数据,因为迄今为止累积的数据仍不足以得出结论。

我们可以使用 gsDesign 软件包 (Anderson,2022)来找出我们需要如何调整指示显著 p 值的阈值,以及在数据收集的哪些点上我们可以达到结果的峰值。

假设我们要运行三次中期分析并运行一个单侧显著性测试,我们应该在总共有 1,985,050,3,970,099 和 5,955,149 个用户看过内容后停止。此外,我们需要将 alpha 级别调整为 0.0232,而不是更自由的显著性阈值p < .05,以证明我们查看中间数据的事实。

现在让我们看看,随着数据进入贝叶斯框架,支持和反对每个假设的证据是如何演变的。

这将按时间顺序追踪任一假设的证据。在大约 30 万用户看过各自的内容后,H-的证据超过了 H+和 H0 的证据。在大约 600,000 次试验后,H-的证据变得非常有力,所以我们可能已经停止了数据收集。在现实生活的营销活动中,这将为我们节省 400,000 额外的用户内容将被广告。

假设的后验概率也显示为图顶部的概率轮。对于先验概率,绿色区域显示备选假设的后验概率,灰色区域显示无效假设的后验概率。数据将 H-的似然性从 0.1 增加到几乎 1,而零假设和 H+的后验似然性相应地降低到几乎 0。

a 还是 B?再想想。

限制

在总结之前,让我们面对用户参与案例研究的局限性。首先,我们没有随机对照实验,无法确定 a)用户只看到了 b)完全相同的产品或灵感的照片或视频内容,而 c)用户之间的分组是均等的。相反,我们有一个高度不平衡的群体规模和视频内容,使只有一小部分的意见可用于照片。因此,问题仍然是,在社交媒体上营销内容时,视频是否真的是一个糟糕的选择。我们也不知道是否相同的独特用户甚至可能已经看到了照片和视频,这将给我们一个主题内的设计,也应该建模。如果这个例子是一个真正的数据科学项目,那么应该鼓励该公司在决定更多地关注不同类型的内容之前,收集更多关于视频帖子的数据,以达成更公平的比较。

贝叶斯 A/B 测试告诉我们更多关于用户参与度的信息

然而,我们在 A/B 测试的两个框架之间有一个很好的比较:频率主义者的方法让我们拒绝了零假设,样本估计指出了视频内容对用户参与度的负面影响。但我们没有办法知道数据是否支持替代假设——事实上,p 值无法区分证据不存在(即数据太乱)和证据不存在(即没有影响)(Keysers et al .,2020;罗宾逊,2019)。然而这才是我们真正感兴趣的,对吗?

贝叶斯 A/B 检验为负面影响提供了明确的证据,而根据数据,其他两个假设似乎不可信。有趣的是,这两种方法都提出了一个相似的最小样本量来捕捉效果,即使需求不同:我们可以通过贝叶斯框架很好地监控数据积累的证据,我们可以在 600,000 次查看后停止我们的活动。对于 frequentist 框架,功效分析给了我们一个非常相似的最小样本量,但是关注数据是有害的:我们需要通过调整 p 值来校正多重比较。最后,如果没有贝叶斯框架,我们将无法谈论典型的用户参与价值。老实说,这是贝叶斯框架代表分析师做更多工作的地方,因为我们在这个问题上有更好的专家,因为它本身。与传统方法相比,之前的规范要求我更深入地参与用户参与度和社交媒体指标。

由于我是一名行为科学家,而不是营销人员,我不得不做一些研究,找出哪些假设是合理的,哪些参数值在实践中是合理的。与简单地运行逻辑回归相比,我通过这种方式学到了更多关于用户参与度的知识。你可能喜欢数据科学的计算部分,我也是。然而,这不应该分散我们对我们想要解决的实际问题的注意力。

在旅程的最后,我们有一个非常有针对性和方便的测试程序。我相信贝叶斯框架包含了我们定制假设检验所需的工具,并成为我们领域中更好的专家。

参考

[1] F. Portman,bayesAB:A/B 测试的快速贝叶斯方法 (2017), R 包。

[2] Q. F .格罗瑙, Abtest:贝叶斯 A/B 测试 (2019), R 包。

[3] T. Hoffmann,A . Hoffman & e . j . wagen makers,关于用 R 和 JASP 进行 A/B 检验的贝叶斯推断的教程 (2021), Psyarxiv。

[4] S. Moro,P. Rita 和 B. Vala,预测社交媒体绩效指标和评估对品牌建设的影响:一种数据挖掘方法。 (2016),《商业研究杂志》,69(9),3341–3351。

[5] K. Müller & J. Bryan,这里:找到你的文件的更简单的方法 (2020), R 包

[6] M. Dowle, data.table:【数据.框架】的扩展 (2021), R 包。

[7] W .邱, powerMediation:用于中介分析的功效/样本量计算 (2021), R 包。

[8] R. Morey,“什么是贝叶斯因子?” (2014),BayesFactor 博客。

[9] K. Anderson, gsDesign:成组序贯设计 (2022), R 包。

[10] C. Keysers,V. Gazzola 和 E.-J. Wagenmakers,在神经科学中使用贝叶斯因子假设检验来建立缺失的证据 (2020),自然神经科学,23,788–799。

[11] G. K. Robinson,可以合理地期望统计推断具有什么性质?—统计推断中的危机与解决 (2019),美国统计学家,73,243–252。

贝叶斯方法和模型评估

原文:https://towardsdatascience.com/bayesian-approach-and-model-evaluation-371ad669cf2c

概率,贝叶斯统计

使用贝叶斯度量评估和比较模型,通过贝叶斯建模方法的介绍确定正确的参数

纳赛尔·塔米米在 Unsplash 上的照片

贝叶斯方法和其他方法有什么不同?它是基于信仰的。关于我们感兴趣的系统的信念。在本文中,我们将探讨如何在模型构建和测量其性能中利用这一概念。

关于贝叶斯模型比较的先决条件

机器学习或统计模型经历了开发生命周期的几个阶段。其中之一是测量它的准确性。下面描述的几种情况会带来挑战:

  1. 很多时候我们没有足够的训练数据。除此之外,保留其中的一小部分作为验证数据集可能会由于数据不足而影响模型的准确性。
  2. 对于具有高训练时间问题的模型,采用交叉验证方法将增加更多的训练时间。
  3. 对于无监督学习,可能不存在检查准确性的直接技术,因为学习本身不基于标记数据集。

贝叶斯模型比较方法试图缓解上述问题。这些不仅有助于检查准确性,而且有助于逐步建立模型。这些方法主要针对训练数据本身来处理数据短缺问题。但是,请记住,正如您所知,这与在训练数据集上计算训练准确度并不完全相同。像任何其他统计技术一样,他们试图给出一个关于准确性的近似&替代想法,而不是完全万无一失。为了更清楚地理解事情,我们将从一个关于模型建立的贝叶斯方法的简短描述开始。

贝叶斯建模方法

我们需要从贝叶斯的角度来看统计模型的一般陈述。它有两个主要术语:先验和后验。先验是我们对数据的信念。它可能来自我们感兴趣的系统的领域知识或先前的知识。非贝叶斯或频率主义方法在其计算中不考虑“先验”。而“后验”就是我们期望从模型中得到的输出。“后验”不断更新,最终得出结论。

让我们假设一个模型由概率分布(实际上,它可能比单个分布复杂得多)、参数θ、作为属性的随机变量 x 和作为输出的 y 来表示。 y 的分布以θ为参数。通过贝叶斯方法, y 的概率可由下式给出:

如果θ是常数,那么联合分布 p(y,θ) 将只取决于y。例如,正态分布由两个参数& σ定义,用 N(,σ)表示。如果= 5 & σ = 10,那么分布就是 N(5,10)。这里的参数是常数。 Frequentist 方法没有先验概念,总是将参数视为常数。但是如果他们不是呢?

贝叶斯方法出现了。参数也是贝叶斯设置中的随机变量。这意味着意味着()或标准差 (σ)可以为正态分布。“先验”是关于这些参数的初始假设。上式中的 p(y,θ) 是一个先验,关于θ的假设& y 两者都有。基本上 p(y,θ) 只需要关于θ的假设就可以完全推导出来。

p(y,θ)p(y,θ | x) 分别称为 【先验预测分布】【后验预测分布】p(y,θ) 可以进一步分解如下:

现在,你应该清楚了。对θ做一些初步的猜测&由此得到 p(θ)。实际上 θ 可以相当复杂,可以表示一个参数向量,而不是单个参数。

说了这么多,我们现在的目标是什么?明确找到对 θ 的良好估计,并确定 y. 的预测分布,一旦获得 p(y,θ) ,我们就可以获得一个图(最大先验值)即模式或分布的平均值作为输出。我们可以得到如下结果:

由于这些先验思想,贝叶斯方法提供了自动正则化,并减轻了过拟合问题,这与 Frequentist 方法不同。

最大似然估计 vs 贝叶斯估计

Frequentist 方法使用 MLE 来获得对 θ 的估计,因为它没有先验&后验的概念。它只是最大化似然函数 p(x | y,θ)。最优值 θ 为给定为 点估计 。不同的最大化技术超出了讨论的范围。

贝叶斯方法采用迭代程序来确定 θ。它是一个 分布估计 而不是一个 点估计 。它从初始先验开始,计算后验,再次使用 θ 的后验估计作为先验,并继续迭代。当观察到 θ 没有明显变化时停止。迭代发生在整个训练数据集中。

这是两者在高层次上的不同。感兴趣的读者可以在一本贝叶斯统计的书中详细浏览。贝叶斯方法的认知构建需要时间,当然也需要很大的耐心。

模型评估

现在,让我们进入模型评估和比较部分。如前所述,一般来说,模型评估的贝叶斯方法不需要验证数据集。我们可以在构建模型本身时近似模型性能。

理论上,计算所有数据点的 后验预测密度 的对数给出了模型性能的总体估计。值越高,表示模型越好。让我们讨论一些指标。

预期测井预测密度(ELPD)

这是一个理论度量,由下式给出:

其中有 n 个数据点。 f 是不可见数据的数据生成分布。它有两个问题。

首先,在实际情况中,如果模型对你来说是黑箱,知道 θ 的正确值可能是不可能的。我们甚至不知道 θ 是如何从内部影响模型的。

第二,我们不知道 f ,因为我们不使用验证数据集。

因此,在实践中,我们可以使用如下的边际分布 p(y | θ) :

但是,第一个问题仍然没有解决。我们还有未知的θ。模拟就是答案。我们可以使用不同的 θ 值,做一个后验模拟。任何概率编程语言都支持后验模拟。这导致了用于数值计算 ELPD 的以下表达式:

这在任何编程语言中都是可行的。请记住,这 n 个数据点来自训练数据集。

信息标准— AIC 和 WAIC

上面讨论的预测准确性的测量被称为 信息标准。 为方便起见,将其乘以 2 并求反。但是,有一个问题。由于我们不使用验证数据集,该指标存在过度拟合的问题。减轻它的一种方法是用模型中用于 frequentist 设置的一些参数来调整它。

阿凯克信息标准(AIC) 是非贝叶斯或频率主义指标的调整指标。它使用最大似然估计作为点估计。它被定义为:

其中 k 是参数的数量。AIC 值越低表示模型越好。

渡边赤池信息标准(WAIC)

这是 AIC 的贝叶斯对应。它在理论上定义为:

pWAIC 是避免过拟合的校正项,如前所述。理论上 pWAIC 给出为:

如前所述,使用模拟,我们可以解码这些表达式,因为我们不知道 θ。相同的表达式然后变成:

渐近地 pWAIC 收敛于模型中使用的参数的数量。

最终,WAIC 变成了 AIC 的贝叶斯等价物。像 AIC 一样,WAIC 的值越低,表示模型越好。

再次,记住不同之处:AIC 条件是点估计,而 WAIC 是后验分布的平均值。

这种贝叶斯模型评估方法还有助于为特定的无监督学习用例逐步构建模型。它也可能有助于超高仪调谐。

要完全掌握所有这些概念,你真的需要扎实的概率和估计方法基础。

注:最近我的《Python 生存分析》一书由 CRC 出版社出版。

链接:

https://www.routledge.com/Survival-Analysis-with-Python/Nag/p/book/9781032148267

贝叶斯共轭先验简单解释

原文:https://towardsdatascience.com/bayesian-conjugate-priors-simply-explained-747218be0f70

执行贝叶斯统计的一种计算有效的方法

希瑟·吉尔在 Unsplash 上拍摄的照片

介绍

贝叶斯统计 中, 共轭先验 是当后验和先验分布属于同一分布时。这种现象允许更简单的后验计算,使得 贝叶斯推断 容易得多。

在本文中,我们将深入了解共轭先验。我们将展示它的必要性,从基本原理中推导出一个例子,最后将它应用到现实世界的问题中。

贝叶斯推理概述

贝叶斯定理

让我们快速回顾一下 贝叶斯定理 :

作者在 LaTeX 中生成的方程。

作者在 LaTeX 中生成的方程。

如果你想更深入地推导和理解贝叶斯定理,可以在这里查阅我以前的文章:

****https://pub.towardsai.net/conditional-probability-and-bayes-theorem-simply-explained-788a6361f333

贝叶斯更新

当我们收到更多关于某个事件的数据时,我们使用贝叶斯定理来更新我们的信念。

一般来说,我们按如下方式进行更新:

作者在 LaTeX 中生成的方程。

然后,当新数据到达时,后验数据成为新的先验数据。这个过程随着新数据不断重复,因此被称为贝叶斯更新。这就是贝叶斯推理的本质。

您可以在此阅读有关贝叶斯更新的更多信息:

然而,如果我们想要获得有效的概率,我们需要计算 P(D) 。如上所示,这是可能性和先验的乘积之和。描述求和的另一种方式是通过积分:

作者在 LaTeX 中生成的方程。

这种积分往往是https://www.reddit.com/r/askmath/comments/cghi5c/what_is_an_intractable_integral_and_why_this/。这基本上意味着它在计算上非常昂贵,或者它没有一个 封闭形式的解 。我在这里链接了https://stats.stackexchange.com/questions/202917/why-is-computing-the-bayesian-evidence-difficult一个 StatExchange 线程,解释了为什么它很难处理。****

共轭先验

背景

共轭先验是避免贝叶斯推理中棘手的积分问题的一种方法。这是当先验分布和后验分布相同时。这允许我们简化计算后验概率的表达式。在下一节中,我们将从数学上展示这一现象。

二项式和贝塔权变

最简单和常见的共轭分布对之一是https://en.wikipedia.org/wiki/Beta_distribution(先验)和https://en.wikipedia.org/wiki/Binomial_distribution(似然)。****

贝塔分布:

  • 被称为概率分布的,因为它的定义域介于 0 和 1 之间。
  • 传达事件成功的最大可能性。

概率密度函数 (PDF) 写成:

作者在 LaTeX 中生成的方程。

这里 x 有界为 0 ≤ x ≤ 1, 所以很容易解释为概率和 B(α,β)β函数

如果您想全面了解 Beta 发行版,您应该浏览一下我以前关于它的文章:

****

二项分布:

  • 传达来自 n 试验的一定数量的成功概率 k ,其中成功概率为 x

PDF:

作者在 LaTeX 中生成的方程。

关键点

  • 二项式分布和贝塔分布的主要区别在于,对于贝塔分布来说,概率、 x 、是一个随机变量,而对于二项式分布来说,概率、 x 是一个固定参数。****

与贝叶斯的关系

现在让我们来做一些有趣的数学!

我们可以使用成功的概率重写贝叶斯定理, x ,对于事件和数据, k ,这是我们观察到的成功次数:

作者在 LaTeX 中生成的方程。

我们的后验基本上是成功率所有可能概率的概率分布。换句话说,后验分布是贝塔分布。

我们可以使用二项式分布作为我们的可能性,使用贝塔分布作为我们的先验来表达上面的等式:

作者在 LaTeX 中生成的方程。

是啊,看起来没那么好。然而,我们现在要简化它:

作者在 LaTeX 中生成的方程。

有些人可能会注意到这个积分的特别之处。它的定义是 贝塔函数

作者在 LaTeX 中生成的方程。

因此,我们后路的最终形式是:

作者在 LaTeX 中生成的方程。

一个测试版!

瞧,我们刚刚从β先验到β后验,因此我们有了共轭先验!

如果你对β-二项式共轭先验更感兴趣,有一本很棒的在线书籍深入描述了它们的关系 这里

为什么有用?

你可能会挠头,想知道为什么我带你经历这个可怕的推导,只是为了得到另一个版本的测试版?

这个漂亮的结果告诉我们,要做贝叶斯更新,我们不再需要计算可能性和先验的乘积。正如我前面所讨论的,这在计算上是昂贵的,有时是不可行的。我们现在可以只使用简单的加法!

例如:棒球击球平均数

问题背景

在美国职业棒球大联盟(MLB)中,击球手击球的比率除以他们投出的球数被称为平均击球率。2021 年 MLB 的击球率为 0.244 (24.4%)

一名球员在赛季开始时表现很好,并打出了他的第一个 3 球。他的平均击球率会是多少?一个 常客 会说是 100% ,然而我们贝叶斯人会得出不同的结论。

在先的;在前的

我们知道击球率是 0.244,但是可能的取值范围呢?一个好的平均值被认为在 0.3 左右,这是较高的范围,一个低于 0.2 的平均值被认为相当差。

使用这些值,我们可以构建一个合适的贝塔先验分布:

from scipy.stats import beta as beta_dist
import matplotlib.pyplot as plt
import numpy as npalpha = 49
beta = 151
probability = np.arange (0, 1, 0.001)
prior = beta_dist.pdf(probability, alpha, beta)plt.figure(figsize=(12,6))
plt.plot(probability, prior, linewidth=3)
plt.xlabel('Batting Average', fontsize=20)
plt.ylabel('PDF', fontsize=20)
plt.xticks(fontsize=18)
plt.yticks(fontsize=18)
plt.axvline(0.244,  linestyle = 'dashed', color='black', label='Average')
plt.legend(fontsize=18)
plt.show()

作者用 Python 生成的图。

这看起来很合理,因为我们的范围很小,在 0.2 到 0.3 之间。我选择 α=49β=151, 的值并没有什么特别的原因,它们只是满足了我们对先验分布的了解。

然而,这往往是反对贝叶斯统计的论点。既然先验是主观的,那么后验也是如此。这意味着概率不再是客观的,而是一种个人信念。

可能性和后验概率

数据的可能性是新玩家从 3 击中了 3 ,因此他们有额外的 3 成功0 失败

利用我们的共轭先验知识,我们可以简单地将一个额外的 3 加到 α0β:

alpha = 49
beta = 151
new_alpha = 49+3
new_beta = 151
probability = np.arange (0, 1, 0.001)
prior = beta_dist.pdf(probability, alpha, beta)
posterior = beta_dist.pdf(probability, new_alpha, new_beta)plt.figure(figsize=(12,6))
plt.plot(probability, prior, linewidth=3, label='Prior')
plt.plot(probability, posterior, linewidth=3, label='Posterior')
plt.xlabel('Batting Average', fontsize=20)
plt.ylabel('PDF', fontsize=20)
plt.xticks(fontsize=18)
plt.yticks(fontsize=18)
plt.axvline(0.244,  linestyle = 'dashed', color='black', label='Average')
plt.legend(fontsize=18)
plt.show()

作者用 Python 生成的图。

三个球并不多,为什么平均值几乎没有变化,这是有道理的。如果我们现在说这名球员从 50 个球中击出了 40 个球,那么他的后路会是什么样子?

alpha = 49
beta = 151
new_alpha = 49+40
new_beta = 151+10
probability = np.arange (0, 1, 0.001)
prior = beta_dist.pdf(probability, alpha, beta)
posterior = beta_dist.pdf(probability, new_alpha, new_beta)plt.figure(figsize=(12,6))
plt.plot(probability, prior, linewidth=3, label='Prior')
plt.plot(probability, posterior, linewidth=3, label='Posterior')
plt.xlabel('Batting Average', fontsize=20)
plt.ylabel('PDF', fontsize=20)
plt.xticks(fontsize=18)
plt.yticks(fontsize=18)
plt.axvline(0.244,  linestyle = 'dashed', color='black', label='Average')
plt.legend(fontsize=18)
plt.show()

作者用 Python 生成的图。

我们看到了更大的变化,因为我们现在有了更多的数据。

没有共轭先验

如果没有共轭先验,我们将不得不使用可能性和先验的乘积来计算后验概率。为了完整起见,我们来看一下这个过程。

我们将使用一个例子,玩家在 50 个球中击中了 40 个。在这种情况下,我们的可能性是:

作者用 Python 生成的图。

这里我们使用了二项式【PMF】概率质量函数。****

执行贝叶斯更新并绘制后验概率图:

alpha = 49
beta = 151probability = np.arange(0, 1, 0.001)
prior = beta_dist.pdf(x, alpha, beta)
likelihood = 10272278170*probability**40*(1-probability)**10
posterior = prior*likelihood
posterior = posterior/sum(posterior)plt.figure(figsize=(12,6))
plt.plot(probability, posterior, linewidth=3, label='Posterior')
plt.xlabel('Batting Average', fontsize=20)
plt.ylabel('Probability', fontsize=20)
plt.xticks(fontsize=18)
plt.yticks(fontsize=18)
plt.axvline(0.244,  linestyle = 'dashed', color='black', label='Average')
plt.legend(fontsize=18)
plt.show()

作者用 Python 生成的图。

我们到达和以前一样的分布!

眼尖的你可能会注意到一个不同,y 轴是不同的。这与返回 PDF 的 SciPy Beta 函数有关,而这里我们使用的是 PMF。

其他共轭分布

贝塔二项分布并不是唯一的共轭分布:

仅举几个例子。

可悲的是,并不是所有的问题,事实上很少,都可以用共轭先验来解决。

然而,还有更一般的替代方案如 马尔可夫链蒙特卡罗 为棘手的积分提供了另一种解决方案。

结论

在这篇文章中,我们描述了共轭先验如何让我们通过简单的加法计算后验概率。这非常有用,因为它消除了计算可能性和先验的乘积的需要,这可能导致难以处理的积分。

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

****https://github.com/egorhowell/Medium-Articles/blob/main/Statistics/Conjugate_Priors.ipynb

和我联系!

(所有表情符号都是由 OpenMoji 设计的——开源的表情符号和图标项目。许可证: CC BY-SA 4.0************

贝叶斯可信区间简单解释

原文:https://towardsdatascience.com/bayesian-credible-intervals-simply-explained-24989c9259a3

贝叶斯可信区间的简明描述及其在 Python 中的实现

Unsplash 上由 aceofnet 拍摄的照片

介绍

在我之前的一篇文章中,我讨论过 置信区间 的想法。你可以在这里查看这个博客:

置信区间基本上是一种给估计参数分配不确定性的方法。置信区间是一种 频率主义者 的方法,而 可信区间 是类似的 贝叶斯 版本。

在本文中,我想探究这两种类型的区间之间的差异,展示一个可信区间的例子以及如何用 Python 计算它。

置信区间与可信区间

尽管置信区间和可信区间传达了相似的信息,但它们的计算方式却大不相同。

置信区间

置信区间是两者中较为复杂的一个,实际上经常被误解为可信区间。

置信区间是具有“置信度”的参数值的范围,用于测量真实参数位于样本范围内的确定性。置信水平是指置信区间将包含来自大量随机样本的真实参数的“确定性”。最常见的一种选级是 95% 这意味着 95% 的随机样本,从 95% 的置信区间中抽取,将包含真实参数。这也意味着 5%的样本不包含真参数。

如果你想知道更多关于置信区间的细节,一定要看看我之前在上面链接的文章。

可信区间

然而,人们通常将置信区间解释为随机样本有 95%的机会包含真实参数。这其实更符合贝叶斯可信区间推断的东西。

可信区间更直观,基本上描述了哪些参数位于给定的概率范围内。例如,95%可信区间将只是占后验分布 95%的参数/值范围。

为了更深入地理解后验分布和贝叶斯定理,请查看我以前的帖子:

https://pub.towardsai.net/conditional-probability-and-bayes-theorem-simply-explained-788a6361f333

例子

现在我们将通过一个简单的例子来把这个理论付诸实践。

问题是

在我之前的文章中,我用 Python 实现了贝叶斯更新。你可以在这里查看帖子:

我解决的问题是:给定一些不同数字范围的骰子,我们随机选择一个骰子,然后掷几次。使用我们从掷骰子中得到的数据,我们可以建立一个后验分布来确定我们最有可能选择哪个骰子。

代码

下面是我上一篇文章中的一个函数,它接收一组骰子和数据(掷骰子),并返回后验分布:

**def** bayesian_dice_updating(data, dice):
    """ Compute the posterior distribution for given dice and data.

    :param data: The numbers that have been rolled from the dice
    :type data: list, np.array

    :param dice: The range of dices where the number represents 
                 the maximum value that die can take.
    :type dice: list, np.array

    :returns: Posterior distribution of the dice given the data
    :rtype: list

    """

    prior **=** [1**/**len(dice) **for** _ **in** np**.**arange(len(dice))]

    posterior **=** prior

    **for** roll **in** data:
        likelihood **=** [1**/**i **if** i **>=** roll **else** 0 **for** i **in** dice]
        posterior **=** np**.**array(likelihood) ***** np**.**array(posterior)

    **return** list(posterior**/**sum(posterior))

完整代码可从我的 GitHub 获得,网址是:

https://github.com/egorhowell/Medium-Articles/blob/main/Statistics/Bayesian_Updating.ipynb

现在,假设我们有 50 个不同的骰子,其中它们的相关数字是该骰子的最高值。例如,骰子 20 的值从 1 到 20。

我们拿起一个骰子,用那个骰子掷出 2、4 和 6。跨可能骰子的所得后验分布为:

# Generate our dice
dice = np.arange(1,51)# Some rolls
data = [2,4,6]# Plot the probability distribution using our function
plt.figure(figsize=(13,7))
plt.xlabel('Dice', fontsize=20)
plt.ylabel('Probability', fontsize=20)
plt.plot(dice, bayesian_dice_updating(data, dice))
plt.xticks(fontsize=20)
plt.yticks(fontsize=20)
plt.savefig('plot.png')
plt.show()

作者用 Python 生成的图。

我们看到最有可能死的最大后验估计 (图),就是区间 1–6 的那个,死 6。同样,骰子 1 到 5 是零,因为这些骰子不可能产生值 6。

可信区间

我们可以使用一个简单的 for 循环和一个滚动总计来构建此地图值周围的可信区间:

credible_interval_dice =[]
credible_interval = 0.95
total = 0
posterior = bayesian_dice_updating(data, dice)for prob in posterior:
    total += prob
    if total < credible_interval:
        credible_interval_dice.append(prob)

在这种情况下我们计算的是 95%可信区间,即 正态分布 中两个 标准差 捕捉到的数据量。

通过返回位于可信区间列表长度索引处的骰子,我们可以找到属于该可信区间的骰子范围:

dice[(len(credible_interval_dice))]Output: 22

因此,我们可以说我们捡到的骰子在 6–22 之间,可信区间为 95%。

绘制可信区间:

plt.figure(figsize=(13,7))
plt.xlabel('Dice', fontsize=20)
plt.ylabel('Probability', fontsize=20)
plt.plot(dice, posterior, linewidth=3, label='Posterior Distribution')
plt.xticks(fontsize=20)
plt.yticks(fontsize=20)
plt.axvline(6, color='black', linestyle='dashed', label='95% Credible Interval')
plt.axvline(22, color='black', linestyle='dashed')
plt.legend(fontsize=20)
plt.show()

作者用 Python 生成的图。

有趣的是,这也是 密度最高的区间 为 95%。HDI 基本上是对应于某一可信水平的最小区间。

生成这些图并计算可信区间的完整代码可从我的 GitHub 获得:

https://github.com/egorhowell/Medium-Articles/blob/main/Statistics/Credible_Interval.ipynb

结论

在本文中,我们描述并解释了频率主义置信区间和贝叶斯可信区间之间的主要区别。此外,我们通过一个简单的例子展示了如何用 Python 计算给定后验分布的可信区间。

和我联系!

(所有表情符号由 OpenMoji 设计——开源表情符号和图标项目。许可证: CC BY-SA 4.0

基于 PyMC3 的贝叶斯客户终身价值建模

原文:https://towardsdatascience.com/bayesian-customer-lifetime-values-modeling-using-pymc3-d770676f5c06

实现 BG-NBD 概率分层模型,使用 PyMC3 分析客户购买行为

来源: Unsplash

C 客户终身价值(CLV)是客户在其关系存续期间对公司的总价值。一个公司的客户群的集体 CLV 反映了它的经济价值,并且经常被用来评估它的未来前景。

虽然存在许多估计 CLV 的方法,但在过去几十年中出现的最有影响力的模型之一是贝塔几何负二项分布(BG-NBD)。该框架使用 Gamma Beta分布对客户的重复购买行为进行建模。本系列文章的第 1 部分已经探讨了这个模型背后的数学原理。同时,第 2 部分介绍了 寿命 ,这是一个允许我们方便地拟合 BG-NBD 模型并获得其最大似然估计(MLEs)参数的库。如果您还没有阅读这些部分,我建议您阅读它们,因为接下来的内容是建立在它们之上的。

本系列的最后一部分介绍了实现 BG-NBD 的另一种方法——一种基于贝叶斯原理的方法。我们将使用 PyMC3 来编码这个实现。虽然本文的主要目的是通过贝叶斯透镜来阐明 BG-NBD,但也将提出贝叶斯世界观和 PyMC3 框架的一些一般观点。这是我们的议程:

  1. 首先,我们将论证贝叶斯实现比频率主义者提供了一些优势。
  2. 其次,我们将提供一个实现“蓝图”来指导我们的编码步骤。
  3. 第三,我们将花一些时间研究优先选择——贝叶斯建模中的一个关键组件。
  4. 接下来,我们将回顾一下 PyMC3 代码及其复杂性,包括著名的蒙特卡罗马尔可夫链(MCMC)算法。
  5. 最后,我们将分析贝叶斯 BG-NBD 模型的输出,并将其与寿命的输出进行比较。

我们开始吧!

为什么是贝叶斯?

你可能想知道如果我们已经有了用户友好的生命周期,为什么还需要另一个实现。答案在于频率主义者和贝叶斯推理之间的对比以及后者所提供的优势。

为了说明这些差异,让我们把 frequentist 和 Bayesian 框架想象成两个试图对统计问题(如 CLV 估计)建模的编程函数。我们会看到这些函数在输入和输出上有着重要的不同。

这两个函数都将数据集(观察值)作为输入。然而,贝叶斯函数需要在分布之前形式的额外输入。先验反映了我们对模型参数的初始假设,并将在考虑观察结果后进行更新。

包含先验知识是一把双刃剑。一方面,先验为用户提供了一种使用其领域知识“引导”模型找到正确参数的方法。例如,在 BG-NBD,如果我们确定我们的大多数客户以每周 4 次交易的比率λ进行购买,我们可以提供导致平均值为 4 的伽马分布的先验。如果这种直觉只是略有偏差(例如,如果真实的λ是 3.5 笔交易/周),贝叶斯框架将允许我们仅用很少的数据点来得出正确的值。

另一方面,由于没有单一的“正确”方法来选择先验,贝叶斯建模过程是主观的和可变的。两个统计学家共享相同的数据,但使用不同的先验知识,最终可能会得到完全不同的结果。这种主观性是一些从业者避开贝叶斯的主要原因之一。然而,随着更多的数据点被包括在建模中,先验的影响减少了。

这两个函数的输出也不同。它们都返回模型的参数估计,但形式不同。frequentist 将它们作为点估计返回。例如,我们已经看到 frequentist 库寿命 如何使用 MLE 计算 r、αab 的点估计。相比之下,贝叶斯将它们作为概率分布返回。这些分布称为后验分布,代表了我们在考虑观察值后对参数的更新信念。

后验的获得是贝叶斯框架胜过频率主义者的另一个方面。有了后验概率,就很容易将参数的最合理值可视化,并量化我们估计中的任何不确定性。此外,如果有额外的观测数据,前后循环提供了更新参数的原则方法。

实施蓝图

我们在第 1 部分已经看到,BG-NBD 模型是一个分层的概率模型。层级这里指的是一些分布的参数被其他分布(“父”分布)建模的事实。我们很快就会看到 PyMC3 允许我们用代码表达这些父子关系。

下面提供了指导编码步骤的蓝图。该蓝图遍历模型的逻辑流程,从输入(数据和先验分布)开始,到输出(后验分布)结束。

对上述蓝图的一些评论:

  1. ****伽玛分布代表交易率λ在客户群体中的分布。由两个参数参数化: rα 。我们将为 rα 提供先验,即将被我们的观测更新。
  2. ****贝塔分布代表客户群体中去激活概率 p 的分布。由两个形状参数参数化: ab 同样,我们将提供这些参数的先验知识。
  3. 来自伽马分布的 λ 和来自贝塔分布的 p 构成了似然函数,该函数表示观察到数据集中的事务的概率。这种可能性就是结合我们的数据和理论的方程式。
  4. PyMC3 中的 MCMC 算法将使我们能够对 r,α,ab 的后验分布进行采样。我们稍后会详细讨论这个算法。

有关上述分配的详细信息,请参见第 1 部分;如果你对它们不熟悉,就看看吧!

先验选择

考虑

如前所述,我们需要为 r、α、ab 分别提供一个先验。我们可以将这些先验及其各自的参数视为我们模型的“超参数”。选择先验知识时,需要考虑多种因素:

  1. 先验知识可以从现有的知识中形成,而现有的知识又可以来自领域专门知识、历史观察或过去的建模实验。
  2. 当没有信息可用时,可以选择无信息先验来反映可能的参数值之间的差异。
  3. 我们可以施加一些约束来指导我们的选择。例如,我们可以要求我们的先验分布是对称的、严格正的、重尾的等等。

在我们的案例中,以下是我们的考虑和假设:

  1. 至于购买率λ,我们将假设我们有一个强烈的直觉,即我们的大部分客户以每周购买 4 次的速度进行交易。我们将选择反映这种先验信念的伽玛先验。
  2. 相比之下,我们将假设没有关于我们的客户的去激活概率( p )的先验知识。因此,我们会选择无信息β先验。
  3. 因为我们所有的参数( r,α,ab) 只能是正实数,所以我们选择的先验分布必须为负数分配零概率密度。

截尾正态分布

先验的一个很好的候选是截尾正态分布。顾名思义,截尾正态分布是一种被“截尾”的高斯分布。也就是说,其超过指定的左和右界限的密度被设置为零,并且其在界限之间的密度被重新标准化为总和为 1。分布有四个参数:左右极限(通常称为 AB) ,均值 μ 和标准差 σ

截断正态分布常用作先验分布,因为它的四个参数提供了一种“猜测”值的直观方式。 μ 代表我们最有可能的猜测, σ 反映我们的不确定性水平, AB 分别表示下限和上限约束。

以下是截断正态分布的一些例子:

伽玛和贝塔先验

有了这些考虑,现在让我们构建伽玛先验。以下是步骤:

1.如前所述,我们之前认为伽玛分布的最可能值(即其平均值)是每周 4 次交易。

2.然后,我们选择伽马参数 rα 的特定组合,这导致期望平均值为 4 的伽马分布。我们知道一个伽马分布的均值可以通过简单的公式 μ = rα来计算;这样,任何一对乘积为 4 的正数都可以被选为 rα 的候选数。让我们将 r 设为 8,将 α 设为 0.5。使用这些参数构建的伽马分布绘制如下:

3.这些 rα 值代表我们的初始猜测。由于我们对这些猜测没有 100%的把握,我们应该把它们表示为分布而不是点估计。正是这些分布,我们称之为先验。由于前面提到的原因,我们将使用截尾正态来表示这些先验。

4.现在让我们把注意力集中在 r 上。rr的截断法线将具有以下参数:

  • μ : 8(我们最可能的初步猜测)
  • :7(相当大的标准差,反映了我们的高度不确定性)
  • A : 0(因为我们知道 r 不可能是负数)
  • B : 40(这里,我们选择一个我们 r 不会超过的极右极限)。

使用这些参数构建的截断法线绘制如下:

5.重复上述过程,以获得 α、ab 的先验。工作流程如下所示:

注意,对于β参数 ab,我们选择了先验的无信息均匀分布,以反映我们对客户的失活概率( p )没有先验知识。

在 PyMC3 中编码所有内容

资料组

在整篇文章中,我们将使用由生存期提供的样本数据集( MIT 许可)。这张表记录了 CDNow 的交易,这是一家出售 CD 的网络时代的公司。我们是这样加载的:

交易

正如在第 2 部分中讨论的,在建模之前,该交易表应该经过两个先决步骤:

  1. 转换为规范的“RFM”格式,并且
  2. 分为校准集和维持集。

我们将使用我们在第 2 部分中使用的同样的分裂机制,以便于比较寿命PyMC3 估计值。

rfm_cal_holdout

PyMC3 在动作

有了这个理论框架,我们现在就可以开始编码了。我们将使用 PyMC3,一个强大的贝叶斯建模库。虽然我们将提供一些关于 PyMC3 本身的提示,但我们的重点将放在 BG-NBD 实现上。

PyMC3 中,概率模型由 pm 表示。Model() 通常被编码为上下文管理器的对象。该模型将包含由分布对象表示的几个分布。这些分布对象之间可以有父子关系,其中父对象的值影响/决定子对象的值。

以下是 BG-NBD 在 PyMC3 中的实现。正如您所看到的,代码很好地反映了前面介绍的理论。

话虽如此,代码的两个部分可能并不简单,需要进一步讨论。这些部分,自定义似然函数(第 30–41 行)和 MCMC 采样(第 43–62 行),详述如下。

自定义似然函数

PyMC3 配备了许多分布对象,每个对象对应一个众所周知的概率分布,如贝塔或伽马分布。然而,当涉及非标准概率分布时,如 BG-NBD 似然函数,则需要定制实现。**

提醒一下,BG-NBD 模型中的似然函数如下所示(其推导过程在第 1 部分中提供):

您可能还记得您的统计课,最大似然估计(MLE)涉及整个数据集的似然函数输出的乘法。因为这些乘法步骤中的每一步都输出一个分数,所以直接计算似然性可能会导致浮点问题。为了避免这种情况,通常将似然函数转换为对数似然函数,这样更便于优化。上述函数的对数似然版本如下:

我们在 logp 函数中实现的就是上面的这个公式。然后,我们通过实例化一个新的density dist对象并在实例化过程中传递 callable,将这个函数转换成一个分布对象。因为这个分布对象的值是已知的,所以我们也在它的实例化期间提供了这些已知的值 xtₓT

MCMC 算法

描述完模型后,我们可以执行 MCMC 算法对后验分布进行采样。MCMC 是一系列模拟算法,允许从封闭形式的 PDF 或 PMF 未知的分布中进行采样。它通过构建马尔可夫链来工作,马尔可夫链是一种多状态系统,允许根据特定的概率规则从一种状态转移到另一种状态。该链被设计成使其稳态与要采样的分布相匹配。

来自 Stata 博客的 MCMC 动画

我们使用 pm.sample()开始链的构建和采样。完成后,该函数返回一个包含绘制样本的 trace 对象。如果采样过程进展顺利(即达到稳定状态),这些样本将代表我们期望的后验概率。

在进一步分析之前,我们应确认算法的收敛性(达到稳态),因为使用在收敛之前获得的样本可能会导致错误的下游分析。为了确定收敛性,我们可以使用⁴的pm . trace _ plot()绘制trace;“曲折”模式表明不收敛,这不是一个好现象。****

这是我们实验的轨迹图:

我们看到没有检测到明显的不收敛迹象。

后验分布分析

先验与后验

既然我们确信抽样过程运行正常,我们可以继续分析后验概率。一个常见的起点是 pm.summary(),,它返回我们的后验概率的汇总统计。让我们打印他们的手段。

我们注意到这些后验方法与前验方法大不相同。例如, b 从 1(前均值)到 2.736(后均值)。这表明我们先前的信念没有得到数据的完全支持,因此被“更新”了。

寿命输出的比较**

在本系列的前一篇文章中,我们已经看到了使用寿命库也可以用来估计参数 r、αab 。现在让我们比较两种实现的结果:**

我们看到,尽管来自不同的框架(frequentist vs Bayesian),估计的参数并没有太大的不同。

对估计的β和γ分布的分析

然后,我们可以使用贝叶斯后验概率的平均(即最可能的)参数值来构建和可视化伽玛和贝塔分布。

让我们从伽玛开始,这是图表:

正如我们在第 1 部分中讨论的,伽玛分布具有实际意义——它定量地描述了我们客户群的集体购买行为。具体来说,它表明了人口中购买率的分布。上图显示了一个相对理想的伽马分布,大部分𝜆在 2 附近。这意味着我们的客户预计将以每周 2 笔交易的速度购物——对于 CD 公司来说,这是一个不错的速度!

现在让我们看看β分布,它描述了我们客户群中失活概率的分布:

该图显示了一个相对健康的β分布,它将大部分的 p 集中在 0 附近。这意味着,作为一个整体,我们的客户不太可能停用。

结论

在这一系列文章中,我们讨论了 BG-NBD 模型的基本原理,并展示了它在解决现实世界商业问题中的价值。

具体来说,在第 1 篇文章中,我们了解到 BG-NBD 对客户群的重复购买行为和停用概率进行了建模。得到的概率分布不仅在理论上是合理的;他们还提出了我们的个人客户和客户群的深刻的量化表示。

在第 2 篇文章中,我们探讨了 BG-NBD 的常用实现寿命寿命允许我们用几行代码来拟合 BG-NBD 模型。我们还看到了一些使用生命周期输出的实用方法。* 我向那些不希望手动编写 BG-NBD 方程并希望立即开始推导商业价值的分析师推荐寿命***

这第三篇也是最后一篇文章使用贝叶斯 PyMC3 库实现了 BG-NBD。该实施涉及从头开始编写 BG-NBD,因此需要对该模型有更深入的理解。优点是它允许我们指定先验,这允许我们将我们的专业知识结合到建模过程中。我推荐这种方法给那些对 NBD BG 公司非常熟悉,并且对他们试图建模的客户群有领域知识的从业者。****

参考

[1]“计算你的顾客”的简单方法:帕累托/NBD 模型的替代方案(布鲁斯·哈迪 et。阿尔,2005)

[2]如果你对 pymc 3 的深入研究感兴趣,那就去看看这本很棒的书 概率编程&黑客的贝叶斯方法

[3] Stata 博客:贝叶斯统计介绍(第二部分)——MCMC 和 Metroplis Hastings 算法

[4]轨迹绘制只是确认收敛的许多方法中的一种。PyMC3 文档提供了该主题的广泛论述。

:除特别注明外,所有图像、图表、表格、方程式均由本人创作。

如果你对这篇文章有任何意见或者想联系我,请随时通过 LinkedIn 给我发一个联系方式。另外,如果你能支持我,通过我的推荐链接成为一名中级会员,我将非常感激。作为一名会员,你可以阅读我所有关于数据科学和个人发展的文章,并可以完全访问所有媒体上的故事。

贝叶斯深度学习&估计不确定性

原文:https://towardsdatascience.com/bayesian-deep-learning-estimating-uncertainty-9907f5208cc0

天气数据;任意和认知的不确定性

湿度是温度的函数。更多细节见正文。(来源:作者)

深度神经网络(DNNs)的性能依赖于从大量数据中逐步构建和提取特征的能力。尽管这些深度模型通常是自适应的,但是性能取决于数据分布。鲁棒性在各种应用中是重要的,例如计算机视觉任务,例如自动驾驶,因为室外环境可能自然变化。在这一点上,我们希望知道预测正确的可能性有多大,这可以通过在模型中加入不确定性估计来实现。

在本帖中,我们将使用公开可用的真实天气数据,并构建简单的线性和非线性模型,不仅找到最佳模型,还找到不确定性估计。你可以从这篇文章中学到/回顾到什么—

  1. 使用张量流概率库开始贝叶斯深度学习。
  2. 两种不同类型的不确定性估计:任意的认知的不确定性。
  3. 网络权重有多确定(认知不确定性),什么是变分后验概率?

参考资料中给出的链接提供了完整的笔记本。让我们开始吧,不要耽搁。

1.加载和预处理数据:

我使用的是从 2006 年到 2016 年的 10 年间测量的天气数据(在 CC0 许可下可公开获得)。为简单起见,我将只使用温度和湿度值,我们的目标是发现湿度如何作为温度的函数而变化,并建立一个模型,该模型不仅预测行为,还为我们提供模型(&数据)不确定性信息。选择了所需的列后,我们的数据框架如下所示—

我们数据的前几个条目

正如我们所看到的,在 10 年的时间里,每小时都进行测量,产生了超过 95,000 个数据点。为了进一步简化,我们对数据帧进行了重新采样,以降低输入数据的频率,我选择了 3 天的时间间隔,而不是 1 小时的时间间隔,结果得到了 1340 个数据点。

以 3 天而不是 1 小时的频率重新采样数据。

我们现在可以在散点图中绘制湿度与温度的函数关系,如下所示——

图:1。湿度是温度的函数。

我们看到湿度(相对)在大约 0.4 到 1 之间变化,温度在大约-10 到大约 30 摄氏度之间变化,似乎有一种逆线性关系。我们将数据分成训练测试集,并将温度值标准化。这样,我们就为下一步做好了准备,建立模型并量化不确定性。

2.线性回归:

在处理任何不确定性之前,让我们先做一个简单的回归。简单的确定性回归给出了一个点估计,即对于一个输入值,我们得到一个预测值。对于这项任务,我们假设 X 数据与 Y 数据呈线性关系,噪声项呈正态分布。我们的模型通过最小化均方误差(MSE 损失)来学习,本质上是在我们的统计建模假设下最大化数据的可能性。我们可以很容易地在 TensorFlow 中建立这样一个回归网络,并检查如下预测—

代码块 1:具有单一单元的密集层的简单线性回归。

图 2:使用 TensorFlow & Python 的线性回归模型和预测。

任意的和认知的不确定性:

在我们深入研究概率回归之前,让我们简单讨论一下两种常见的不确定性:任意的和认知的不确定性。随机不确定性捕获了观测中固有的噪声,导致即使我们有更多的数据也无法减少的不确定性。另一方面,认知不确定性说明了模型参数的不确定性,如果获得更多数据,这种不确定性可以减少。认知不确定性是指决策者的无知(在这种情况下是深度神经网络),而不是任何潜在的随机/随机过程。

3.1.任意不确定性:可训练均值

使用张量流概率库为回归任务模拟随机不确定性相当容易。在这里,我们的想法是捕捉数据中的固有噪声,并开始训练一个模型,该模型返回一个正态分布(与确定性线性回归和点估计非常不同),具有可训练的平均值,但标准偏差=1(参见代码块 2)。这个想法是,在训练之后,我们的模型将能够复制原始的数据分布。为了使用密集层的输出来模拟正态分布,我使用了 TensorFlow Probability 的DistributionLambda层,它返回一个分布对象。这就是为什么我们使用负对数似然作为损失函数,而不是 MSE 损失。训练后,可以从学习到的分布中取样,并绘制平均&标准偏差,如下所示—

代码块 2:表示输入数据分布的模型(具有可训练的平均值,但方差固定)。

图 3:绘制了从学习的分布(左)生成的样本以及相应的平均值和标准偏差。

由于只有平均值是可训练的,并且我们将标准偏差(stddev)固定为 1,我们看到平均值的 2σ线相距太远。

这可以通过在之前的模型中添加 stddev 作为可学习参数来简单解决。现在,我们将使用两个单元(用于平均值和标准偏差)而不是一个只有一个单元的密集层。

3.2.任意不确定性:可训练的均值和方差;

为了在先前模型中添加可训练方差,我们可以使用具有DistrbutionLambda层的先前码块,但是在 TF 概率库中,我们具有能够直接包括先前密集层输出的随机性的[IndependentNormal](https://www.tensorflow.org/probability/api_docs/python/tfp/layers/IndependentNormal)层。让我们来看看这个模型—

代码块 3:类似于代码块 2,但是这里的模型具有可训练的均值和方差。

IndependentNormal层中的event_shape参数告诉我们所需的参数数量,对event_shape=1来说是 2;这就是为什么Dense层有 2 个单位(均值和方差)。为了指定密集层中的单元数量,我们使用了IndependentNormal层的静态方法params_size

绘制学习分布的样本和相应的均值和标准差,如下所示—

图 4:与图 3 相同,但是现在我们的模型学习了原始数据分布的平均值和标准偏差。

不仅是线性模型,我们还可以添加一个具有非线性激活函数的密集层来包含非线性。

代码块 4:用非线性密集层扩展代码块 3。

图 5:与图 4 相同,但是代替线性模型,我们假设非线性模型来表示数据分布。

4.认知不确定性:

到目前为止,我们试图通过在模型的最后一层添加一些分布来模拟数据的一般随机性(即潜在噪声),即最终预测是分布中的随机变量。

认知不确定性捕捉了 DNN 模型参数的不确定性。为了捕捉神经网络中认知的不确定性( NN ),我们将先验分布置于其权重之上,例如,高斯先验分布:W∞N(0, I )。将 DNN 权重表示为概率分布而不是点估计的想法是在“神经网络中的权重不确定性”论文中提出的。我们从权重的一些先验分布开始,并随着网络看到更多数据而更新,以获得后验分布。对于多元正态分布,有可能得到后验的精确形式。一般来说,不可能确定后验概率的解析形式,因此变分法就变得有用了。

给定训练数据,P(w|D)的情况下,神经网络的贝叶斯推理计算权重的后验分布。变分贝叶斯方法使用称为变分后验的第二个函数来近似后验分布。该函数具有已知的函数形式,因此避免了精确确定后验概率 P ( w | D )的需要。为了避免选择差的变分后验概率的风险,这个近似函数,即变分后验概率由参数θ来参数化,参数θ被调整以使得该函数尽可能地近似原始后验概率(P( w | D ))。变分学习找到权重分布的参数θ**q(w|θ),该参数最小化权重的 Kullback-Leibler (KL)散度与真实贝叶斯后验概率。

最小化 KL 散度将我们引向证据下限(ELBO)。关于 ELBO 的更多信息,你可以查看我在参考资料中列出的笔记本,也可以查看关于期望最大化(EM)算法的详细帖子。

我们在张量流中实现变分后验的方法是通过[DenseVariationalLayer](https://www.tensorflow.org/probability/api_docs/python/tfp/layers/DenseVariational)层,文档定义如下—

这一层使用变分推理来拟合分布在kernel矩阵和bias项上的“替代物”,这些项以类似于[tf.keras.layers.Dense](https://www.tensorflow.org/api_docs/python/tf/keras/layers/Dense)的方式使用。

在我们使用这一层之前,我们需要实现固定的先验分布和可训练的后验分布,这将在DenseVariationalLayer中使用。

代码块 5:考虑简单回归网络中的权重不确定性。

让我们看看在代码块 5 中发生了什么:先验:我们将先验权重定义为具有对角协方差矩阵的多元正态分布( N (0,1)),作为一个sequential,并且没有可训练的参数。后验:这里权重是可训练的(VariableLayer ) &遵循具有全协方差矩阵的多元正态分布(MultivariateNormalTril)。模型:最后我们使用DenseVariational层定义一个模型,并使用先验和后验定义。KL 散度根据训练样本的数量进行加权,你可以在笔记本上找到原因。在我们用 MSE 损失训练这个模型之后,我们可以绘制回归线如下—

图 6:认知的不确定性:这里,每条线代表从后验分布中随机抽取的不同模型参数。

每次我们调用这个模型,我们都会得到一个稍微不同的结果,你可以从那 5 行中看到。不同的斜率表明我们的模型不确定温度和湿度的线性相关性。DenseVariational本质上定义了模型的集合,在这种情况下,我们可以从这 5 个不同的调用中获得平均值。

5.任意+认知的不确定性:

最后,我们将创建一个模型,它可以结合随机和认知的不确定性,这是很容易做到的,我们只需要添加一个IndependentNormal层到以前的模型(代码块 5)来考虑标签(湿度)分布的随机性质。让我们看看下面的代码块—

一旦经过训练,我们就可以像以前一样从模型中为不同的呼叫(认知不确定性)进行采样,如下所示

for _ in range(2): y_model = model_non_lin_al_ep(X_test_scaled) y_hat = y_model.mean() y_hat_m2sd = y_hat — 2 * y_model.stddev() y_hat_p2sd = y_hat + 2 * y_model.stddev()

绘制这两个调用的均值和标准差如下所示—

图 7:与之前的图相同,但是这里我们有任意的和认知的不确定性:两条不同的线代表对模型的两个不同的调用(代表认知的不确定性)。

我们学习了贝叶斯神经网络(BNN)的基本构建模块,特别是与认知不确定性相关的模块。如果我们将数据集表示为 X = {x1,…,xN },Y = {y1,…,yN },那么贝叶斯推断用于计算权重 p(W|X,Y)的后验概率。这里我们通过一个简单的例子,我们知道确切的后验分布,只需要找到最佳参数。虽然认知的不确定性可以减少给定更多的数据,随机的不确定性是不可减少的。使用真实世界的天气数据,我们开发了一个简单的模型,适用于超越点估计和预测不确定性的回归任务。我希望这里用来建立这些模型的概念能给我们提供关于不确定性的信息,这将是有用的,你可以根据你的任务修改它们。

参考资料:

[1] ' '机器学习中的任意和认知不确定性 ': E. Hüllermeier,W. Waegeman

[2] ' 在计算机视觉的贝叶斯深度学习中我们需要哪些不确定性?':a .肯德尔,Y. Gal。

[3] TFP 层:概率回归

[4] ' 神经网络中的权重不确定性 ': C. Bundell 等人

[4]代码、概念和数学笔记本: GitHub 链接

如果你对更深入的基础机器学习概念感兴趣,可以考虑加盟 Medium 使用 我的链接 。你不用额外付钱,但我会得到一点佣金。感谢大家!!

解释贝叶斯实验度量

原文:https://towardsdatascience.com/bayesian-experimentation-metrics-explained-bd2faebd937e

作者图片

在 Typeform,我们采用 GrowthBook 作为 AB 测试的实验平台。GrowthBook 根据您的指标计算 3 个贝叶斯统计,以帮助您对您的新功能得出结论:

  • 上升
  • 击败控制的机会
  • 选择变体的损失或风险

在这篇文章中,我将解释它们是什么以及如何解释它们。

图像来源

抛硬币示例

为了帮助解释我们的统计数据,我们将使用一个经典的抛硬币的例子来进行一个思维实验——这可能是解释贝叶斯统计的最好方法。

假设你有两枚硬币:

  • 硬币 1(控制)是一个公平的硬币,正面或反面的机会是 50:50
  • 硬币 2(变体)未知,您想知道它是否有更高的机会给出正面

我们要做实验来测试硬币 2 对硬币 1 的偏向。

实验结果

我们将运行 3 个不同版本的实验,在每种情况下将硬币翻转不同的次数:

作者图片

我假设控制硬币总是准确地返回 50:50 的正面和反面——在真实的实验中,你会在控制硬币和变体硬币的准确结果中得到变化。为了简单起见,我将随机波动限制为变量。

上升

您想要计算的第一个(可能也是最明显的)统计数据是上升

定义: 在实验过程中,变体的表现比对照好多少

下面是我们每个实验的提升:

作者图片

在每个实验中,我们观察到变体硬币相对于控制硬币有 20%的头部提升。我们怎么解释这个?

我们可以说: 变异体比对照体表现好 20%

我们不能说的: 变体会比对照表现好 20%

这两种说法的区别在于,第一种说法是报告收集的数据,而第二种说法是推断未来的表现。这种差异在实验 1 中最为明显——如果你将变体硬币再抛 10 次,你会再次看到正好 6 个头吗?不,可能不会。如果这是一枚公平的硬币,你同样有可能得到 4 个正面,这将是 20%的概率——完全相反的结果!

直觉上,如果你重复实验 3,你可能会得到我们已经看到的接近 20%的提升,当然 20%的下降将是非常令人惊讶的!然而,这种可再现性或未来的性能并不是仅仅通过提升就能获得的。

击败控制的机会

这就是你可能提到的统计学意义。

定义: 如果我们铺开,变体的表现优于对照的可能性有多大

以下是我们每个实验中战胜控制的机会:

作者图片

随着我们观察到越来越多的数据,我们可以更有把握地得出结论,这种变异有一种潜在的偏向头部的倾向。我们怎么解释这个?

我们可以说: 变异体有 90%的几率表现得比对照好

我们不能说的: 变体有 90%的几率提供+20%的提升

与上升不同,战胜控制的机会是对硬币潜在行为的描述。我们现在可以得出结论,变体硬币在未来将如何继续表现。然而,击败控制组的机会是一个二元统计——变异体仅仅比控制组更好的可能性。我们不能把这个概率与我们在实验中看到的 20%的上升直接联系起来。

在实验 3 中,无论我们重复实验多少次,我们几乎可以保证(99.9%的机会)从变体中获得更多的头。事实上,如果你重复 1000 次,你只会认为第一次会更糟。然而,我们将看到的确切的上升在这些重复之间仍然会有所不同。如果我们重复 Exp 1 三次,那么我们预计其中一次会更糟——如果这是我们希望推出的新功能,可能性不大!

作者图片

失败

即使我们战胜控制的机会很高,仍然有很小的可能性会变得更糟,如果变得更糟的后果是灾难性的,那么我们不能忽视它。这就是损失的来源。

定义: 如果我们推出变体,而它的表现更差,我们可以预期它会差到什么程度?

下面是我们每个实验的损失:

作者图片

亏损让你决定是否接受机会战胜控制和上涨带来的风险。

  • 在实验 1 中,我们观察到 20%的增长,但损失是 10%—一般来说,变体收益的潜力不会超过潜在的损失。
  • 在实验 3 中,损失几乎为 0——即使在最坏的情况下,变体的性能也和对照一样好。
  • 实验 2 可能是最有趣的——有不可忽略的 10%的可能性变得更糟,但损失仍然只有 0.5%。在这种情况下,您可能会做出明智的决定,即变体的潜在改进确实超过了任何潜在的损失。

结论

我们已经介绍了 GrowthBook 计算的 3 个统计数据,并解释了如何使用它们来了解您的 AB 测试结果。推出新功能的决定取决于其他因素,例如生产新功能的工程努力。关于这一点的讨论将不得不等待另一篇文章!

PyMC 中的贝叶斯分层营销组合建模

原文:https://towardsdatascience.com/bayesian-hierarchical-marketing-mix-modeling-in-pymc-684f6024e57a

营销分析

了解如何以正确的方式为不同的国家构建 mmm

安妮·斯普拉特Unsplash 上拍摄

我想你在营销部门工作,想调查你的广告投资是否有回报。看我其他文章的人都知道一个办法:营销组合建模!这个方法特别有趣,因为它也适用于没有烹饪的世界。

我还介绍了贝叶斯营销组合建模,这是一种为您预测的一切获得更健壮的模型和不确定性估计的方法。

贝叶斯方法对同质数据非常有效,这意味着你的广告支出的效果在你的数据集中是可比较的。但是当我们有一个异构的数据集时,例如,跨越几个国家的花费会发生什么呢?处理它的两个明显的方法如下:

  1. 忽略数据集中有几个国家的事实,建立一个单一大模型
  2. 每个国家生产一款车型

不幸的是,这两种方法都有缺点。长话短说:忽视国家留给你的是一个过于粗糙的模型,很可能是不适合。另一方面,如果你为每个国家建立一个模型,你可能会有太多的模型需要跟踪。更糟糕的是,如果一些国家没有很多数据点,你的模型可能会过拟合。

通常,创建介于这两种方法之间的混合模型更有效:贝叶斯分层建模!您也可以在这里了解更多信息:

你会问我们如何从中受益?例如,贝叶斯分层建模可以产生一个模型,其中相邻国家的 TV 结转彼此相距不太远,这抵消了过度拟合效应。

然而,如果数据清楚地表明参数实际上是完全不同的,在给定足够的数据的情况下,贝叶斯分层模型也能够发现这一点。

在下文中,我将向您展示如何将贝叶斯营销组合建模(BMMM)贝叶斯分层建模(BHM) 方法结合起来,使用 PyMC 在 Python 中创建一个贝叶斯分层营销组合模型(BHMMM)

BHMMM = BMMM + BHM

前谷歌公司的研究人员也写了一篇关于这个想法的论文,我鼓励你以后也去看看。[1]在你理解了我关于 BMMM 和 BHM 的文章之后,你应该能很好地理解这篇论文了。

请注意,我不再使用 PyMC 3 了,而是使用 PyMC,它是这个伟大的库的的改版。幸运的是,如果你以前知道 PyMC3,你也可以了解 PyMC。我们开始吧!

准备

首先,我们将加载一个我自己制作的合成数据集,这对于训练目的来说很好。

dataset_link = "https://raw.githubusercontent.com/Garve/datasets/fdb81840fb96faeda5a874efa1b9bbfb83ce1929/bhmmm.csv"

data = pd.read_csv(dataset_link)

X = data.drop(columns=["Sales", "Date"])
y = data["Sales"]

由作者创建的数据。图片由作者提供。

现在,让我从我的另一篇文章中复制一些函数,一个用于计算指数饱和度,一个用于处理结转。我对它们进行了调整,即将theano.tensor改为aesara.tensor,将tt改为at,以便与新的 PyMC 配合使用。

import aesara.tensor as at

def saturate(x, a):
    return 1 - at.exp(-a*x)

def carryover(x, strength, length=21):
    w = at.as_tensor_variable(
        [at.power(strength, i) for i in range(length)]
    )

    x_lags = at.stack(
        [at.concatenate([
            at.zeros(i),
            x[:x.shape[0]-i]
        ]) for i in range(length)]
    )

    return at.dot(w, x_lags)

我们现在可以开始建模了。

BHMMM 大楼

在我们开始完整的模型之前,我们可以先建立单独的模型,看看会发生什么,并有一个基线。

独立型号

如果我们遵循这里的方法,我们得到德国:

德国的模型预测。图片由作者提供。

非常合身。然而,对于瑞士,我们只有 20 个观测值,因此预测值不会太大:

瑞士的模型预测。图片由作者提供。

这也是为什么独立模型接近有时会有问题的原因。有理由相信,在媒体对瑞士人的影响方面,瑞士人与德国人并非完全不同,一个模型应该能够捕捉到这一点。

我们还可以看到瑞士车型对参数的了解:

瑞士模型的后验概率。图片由作者提供。

由于缺乏瑞士的数据点,后验概率仍然很大。您可以从右侧的car_参数中看到这一点:结转的 94% HDI 几乎跨越了 0 和 1 之间的整个可能范围。

让我们现在就建立一个合适的 BHMMM,这样特别是瑞士可以从我们从德国和奥地利获得的大量数据中受益。

PyMC 实现

我们引入一些超优先级来塑造所有国家的基本分布。例如,使用 Beta 分布对遗留物进行建模。这个分布有两个参数 αβ 、,我们保留两个超先验car_alphacar_beta来模拟这些。

在第 15 行,您可以看到如何使用超优先级来定义每个国家和渠道的结转。此外,我使用了比平常更多的调优步骤——3000 步而不是 1000 步——因为模型相当复杂。调整步骤越多,模型推断起来就越容易。

with pm.Model() as bhmmm:
    # Hyperpriors
    coef_lam = pm.Exponential("coef_lam", lam=10)
    sat_lam = pm.Exponential("sat_lam", lam=10)
    car_alpha = pm.Exponential("car_alpha", lam=0.01)
    car_beta = pm.Exponential("car_beta", lam=0.01)
    base_lam = pm.Exponential("base_lam", lam=10)

    # For each country
    for country in X["Country"].unique():
        X_ = X[X["Country"] == country]
        channel_contributions = []

        # For each channel, like in the case without hierarchies
        for channel in ["TV", "Radio", "Banners"]:
            coef = pm.Exponential(f"coef_{channel}_{country}", lam=coef_lam)
            sat = pm.Exponential(f"sat_{channel}_{country}", lam=sat_lam)
            car = pm.Beta(f"car_{channel}_{country}", alpha=car_alpha, beta=car_beta)

            channel_data = X_[channel].values
            channel_contribution = pm.Deterministic(
                f"contribution_{channel}_{country}",
                coef * saturate(carryover(channel_data, car), sat),
            )

            channel_contributions.append(channel_contribution)

        base = pm.Exponential(f"base_{country}", lam=base_lam)
        noise = pm.Exponential(f"noise_{country}", lam=0.001)

        sales = pm.Normal(
            f"sales_{country}",
            mu=sum(channel_contributions) + base,
            sigma=noise,
            observed=y[X_.index].values,
        )

    trace = pm.sample(tune=3000)

就是这样!

检查输出

让我们只看一下模型捕捉数据的能力。

德国和奥地利的 BHMMM 预测结果。图片由作者提供。

我现在不会用指标进行任何真正的检查,但从图表中,我们可以看到德国和奥地利的表现看起来相当不错。

如果我们将 BHMMM 中的瑞士和以前的 BMMM 版本进行比较,我们也可以看到它现在看起来好多了。

瑞士的 BHMMM(左)和 BMMM(右)预测结果。图片由作者提供。

这是唯一可能的,因为我们使用其他类似国家的数据给了瑞士一些背景。

我们还可以看到瑞士结转的后验概率是如何缩小的:

图片由作者提供。

一些发行版仍然有点混乱,我们必须深入研究如何解决这个问题。可能有取样问题或者前科不良,等等。但是,我们不会在这里这样做。

结论

在本文中,我们快速浏览了两个不同的贝叶斯概念:

  • 贝叶斯营销组合建模分析营销支出,以及
  • 贝叶斯分层建模。

然后,我们通过结合这两种方法,打造了一个更好的贝叶斯营销组合模型。如果您处理一些层次结构,例如,在为几个相关国家建立营销组合模型时,这尤其方便。

这种方法如此有效是因为它为模型提供了背景:如果你告诉模型对一个国家进行预测,它可以考虑其他国家的信息。如果模型必须在太小的数据集上操作,这是至关重要的。

另一个我想告诉你的想法如下:在本文中,我们使用了一个国家层级。然而,您也可以考虑其他层次,例如,频道层次。如果你说不同的渠道不应有太大的不同,渠道层级可能会出现,例如,如果你的模型不仅采用横幅广告支出,还采用网站 A 上的横幅广告支出和网站 B 上的横幅广告支出,其中网站 A 和 B 的用户行为没有太大的不同。

参考

[1]孙玉英,王玉英,金玉英,陈,克勒,地理层次贝叶斯分层媒体混合建模 (2017)

我希望你今天学到了新的、有趣的、有用的东西。感谢阅读!

作为最后一点,如果你

  1. 想支持我多写点机器学习和
  2. 无论如何都要计划获得中等订阅量,

为什么不做 通过这个环节 ?这将对我帮助很大!😊

透明地说,给你的价格不变,但大约一半的订阅费直接归我。

非常感谢,如果你考虑支持我的话!

有问题就在LinkedIn上写我!

网络安全中深度神经网络的贝叶斯超参数优化

原文:https://towardsdatascience.com/bayesian-hyperparameter-optimization-for-a-deep-neural-network-590be92bb0c0

高斯过程贝叶斯优化和最优 DNN 随机搜索优化方法在网络入侵检测中的应用

照片由 JJ 英Unsplash

深度神经网络(DNN)已经成功应用于许多现实世界的问题,从疾病分类到网络安全。基于 DNN 的分类器的最佳使用需要仔细调整超参数。手动调整超参数繁琐、耗时且计算量大。因此,需要一种自动技术来找到最佳超参数,以便在入侵检测中最好地使用 DNN。在本文中,我们讨论了基于贝叶斯优化和随机搜索优化的框架,用于自动优化超参数,确保最佳 DNN 架构。此外,我们在真实世界的网络入侵检测基准数据集 NSL-KDD 上进行了性能评估。实验结果表明了贝叶斯优化的有效性,因为所得的 DNN 体系结构表现出比基于随机搜索优化的方法显著更高的入侵检测性能。

包括 DNN 在内的机器学习(ML)算法已经展示出了有希望的结果。基于 DNN 的分类器已经变得流行,并且被广泛用于许多应用,包括计算机视觉、语音识别和自然语言处理。提取自动化特征、高度非线性系统的能力、架构设计的灵活性是 DNN 的亮点。然而,从 DNN 获得成功的性能需要仔细调整训练参数和超参数。当在训练阶段学习训练参数时,必须在训练 DNN 之前指定超参数,例如初始学习速率、密集层数、神经元数和激活函数。DNN 的性能在很大程度上取决于超参数优化。它需要调查 DNN 模型的超参数的最佳组合,该组合返回在验证集上缩放的最佳性能

手动调整超参数需要专家经验。缺乏手动设置超参数的技能阻碍了 DNN 的有效使用。特别是,当有许多超参数时,通过蛮力方法来模拟最佳 DNN 架构过于繁琐、耗时且计算量大,因为这需要对所有超参数的许多可能组合进行实验【3】。例如,网格搜索和随机搜索通常被研究团体用于超参数优化。网格搜索探索超参数的所有可能组合,以达到全局最优。 随机搜索应用多个超参数的任意组合。两种方法都很容易实现。然而,当处理几个超参数时,这些方法收敛缓慢,需要很长时间,并且不能保证按预期执行[3]。根据 DNN 架构的规模,我们可能有数百种可能的超参数组合需要比较,以获得最佳性能。因此,自动且有效的 DNN 超参数优化方法是至关重要的。贝叶斯超参数优化是一种最先进的自动化高效技术,在几个具有挑战性的优化基准函数上优于其他先进的全局优化方法【4】。贝叶斯优化(BO)使用类似高斯过程(GP)的代理模型来定义目标函数上的分布,以近似真实的目标函数。在本文中,我们应用贝叶斯优化与高斯过程(BO-GP)调整 DNN 超参数。

贝叶斯优化

贝叶斯优化(BO)是一种概率优化技术,旨在为某个有界集合全局最小化目标黑箱函数[6]。通常的假设是,黑箱函数没有简单的封闭形式,但可以在任意时刻进行计算[5]。此外,该函数只能通过无偏随机观测来测量[6]。感兴趣的超参数设计空间可以包括连续的、整数值的或分类的。在优化过程中,它构建了一个替代函数(概率模型),该替代函数定义了目标函数上的近似分布,一个获取函数用于量化在任何 x 的评估的有效性。简而言之,业务对象框架由三个关键部分组成:代理模型、贝叶斯更新过程和获取函数[7]。代理模型拟合目标函数的所有点,然后在目标函数的每个新评估之后,通过贝叶斯更新过程来更新。最后,获取功能对评估进行评定。算法 1 显示了 BO [5]的基本伪码。

业务对象可以包括不同的代理模型:GP,使用决策树的顺序优化;不同的获取函数:预期改善(EI)、置信下限(LCB)和改善概率(PI)。我们应用 GP 作为替代模型,EI 作为获取函数[9]。

高斯过程(GP) :由于描述能力和分析的易处理性,GP 作为概率模型是一个方便和著名的选择。 GP 假设随机变量集合的每个有限子集都遵循多元正态分布。

代理函数:它是黑盒目标函数的近似,GP 作为代理函数,建立目标函数的概率模型。简单地说——代理函数指导如何探索搜索空间中的参数[10]。

预期改善(EI):EI 等采集功能调查勘探与开采之间的权衡,并决定后续优化的评估点。EI 定义为:

其中f(x∫)是已知的最佳观测值,而 E[。】是指定函数值 f(x) 的期望。因此,如果f(x∫)>f(x),则奖励或改进为f(x∫)—f(x),否则奖励为 0

NSL-KDD 数据集是广泛用于网络入侵检测问题的 KDD cup’99 数据集的改进版本。它是一个公开可用的数据集,数据来源——【https://www.unb.ca/cic/datasets/nsl.html】

KDDCUP'99 数据集包含像冗余记录这样的问题,会对频繁记录产生偏见。在 NSL-KDD 数据集中,这些问题得到了解决。KDDTrain+和 KDDTest+是 NSL-KDD 中包含的两个数据集。我们使用 KDDTrain+进行训练,使用 KDDTest+测试框架。NSL-KDD 数据集由 41 个要素和一个指示连接状态(正常或攻击)的标注属性组成。表 1 显示了二进制分类的三个数据集的分布(正常与攻击)。

表 1:NSL-KDD 数据集的分布(图片由作者提供)

NSL-KDD 模型中的分类变量首先映射到数值数据,然后对整体数据进行归一化处理。协议类型、标志和服务是三个分类特征,它们使用一键编码技术转换成数字数据。我们应用了最小-最大归一化技术将原始数据缩放到 0 和 1 的固定范围。归一化确保了数据分布的一致性,避免了训练阶段的爆炸梯度问题。

表 2: 探索不同范围的超参数设置(图片由作者提供)

我们对 DNN 应用了随机搜索和 BO-GP 超参数优化技术。表 2 显示了超参数及其范围值,而表 3 显示了针对网络入侵检测的 DNN 的最佳设置超参数。图 1 显示了超参数优化的改进,其中最佳适应值(否定的分类精度)绘制在 y 轴上,优化的迭代次数绘制在 x 轴上。图 2 和图 3 显示了优化过程中激活函数和优化器的样本分布。对于激活函数,ReLU 的采样多于 sigmoid,而对于优化器,Adam 的采样多于 SGD。图 4 显示了两个优化参数的景观图:学习速率的估计适应值和隐藏层中神经元的数量。黑点是优化器的采样位置,而红星是两个超参数的最佳点。

表 3: 随机搜索和贝叶斯优化的最优超参数(图片由作者提供)

图 1: 超参数优化的收敛图(图片由作者提供)

图 2: 激活函数的样本分布(图片由作者提供)

图 3: 优化器的样本分布(图片由作者提供)

图 4: 两个优化参数的景观图——学习率和神经元数量(图片由作者提供)

表 4:KDD test+数据的性能评测(图片由作者提供)

结论

包括深度神经网络在内的机器学习算法的效率很大程度上取决于超参数的值。手动调整超参数是乏味的、耗时的,并且计算量很大,以模拟最佳的 DNN 架构。在本文中,我们应用高斯过程的贝叶斯优化来优化关于网络入侵检测的深度神经网络超参数。在研究最佳 DNN 架构时,我们探索了六个超参数:隐藏层数、神经元数量、辍学率、激活函数、优化器和学习率。我们应用了一种基于随机搜索的优化技术来比较我们提出的方法的结果。实验结果表明,基于 BO-GP 的方法优于基于随机搜索的方法。

相关文章:

机器学习流水线再现性的挑战。

阅读默罕默德·马苏姆博士(以及媒体上成千上万的其他作家)的每一个故事。

你的会员费将直接支持和激励穆罕默德·马苏姆和你所阅读的成千上万的其他作家。你还可以在媒体上看到所有的故事—https://masum-math8065.medium.com/membership

快乐阅读!!!

参考

[1]m . Kalash,m . Rochan,m . Mohammed,n . Bruce,N. D .,Wang,y .,& Iqbal,F. (2018 年 2 月)。基于深度卷积神经网络的恶意软件分类。2018 年第九届 IFIP 新技术、移动性和安全性国际会议(NTMS)(第 1-5 页)。IEEE。

[2]安多尼和弗洛里亚(2020 年)。CNN 超参数优化的加权随机搜索。预印本 arXiv:2003.13300。

[3]利马,L. L .,小费雷拉,J. R .,&奥利维拉,M. C. (2020 年)。用卷积神经网络的超参数优化对肺部小结节进行分类。计算智能。

[4] Snoek,j .,Larochelle,h .,和 Adams,R. P. (2012 年)。机器学习算法的实用贝叶斯优化。神经信息处理系统进展,25,2951–2959。

[5]克莱因,a .,福克纳,s .,巴特尔,s .,亨宁,p .,&胡特,F. (2017 年 4 月)。大数据集上机器学习超参数的快速贝叶斯优化。人工智能和统计学(第 528-536 页)。PMLR。

[6]shahrari,b .,Swersky,k .,Wang,z .,Adams,R. P .,& De Freitas,N. (2015)。将人带出循环:贝叶斯优化综述。IEEE 会议录,104(1),148–175。

[7]因贾达特、穆巴伊德、纳西夫和米沙(2020 年)。网络入侵检测的多阶段优化机器学习框架。IEEE 网络与服务管理汇刊。

K. P .墨菲。机器学习:概率观点。麻省理工学院出版社,2012 年。ISBN 0262018020,9780262018029。

[9] Masum,m .,Shahriar,h .,Haddad,h .,Faruk,M. J. H .,Valero,m .,Khan,m .,a .,和 Wu,F. (2021 年 12 月)。基于深度神经网络的网络入侵检测贝叶斯超参数优化。在 2021 IEEE 大数据国际会议(大数据)(第 5413–5419 页)。IEEE。

[10]https://medium . com/mlearning-ai/Bayesian-optimization-c9dd 1381 CD 1d

贝叶斯推理和变压器

原文:https://towardsdatascience.com/bayesian-inference-and-transformers-3dc473ac1af2

变形金刚可以帮忙做贝叶斯推断吗?简单回顾一下变形金刚可以做贝叶斯推断

阿瑟尼·托古列夫在 Unsplash 上的照片

这是深度学习的不确定性系列的最后一篇文章:

最后一部分将与该系列的其他部分略有不同。我将在下面的文章中描述一篇文章中的方法和提出的方法背后的推理(以便与变分推理进行比较): 变形金刚可以进行贝叶斯推理

注:我将试着简要解释这篇论文,这并不意味着是官方的东西。

本文组织如下:

  • 重述
  • 元学习和贝叶斯推理
  • 后验和后验预测分布
  • 建议方法:预先拟合网络
  • 使用变压器并将零件组装在一起
  • 结论

概述

传统深度学习模型

正如第 2 部分和第 3 部分所解释的,标准模型是确定性的。换句话说,一个输入应该得到相同的输出。因为用最大似然估计(MLE),你会得到点估计权重。

让我们来举例说明:

图片作者。

另一方面,概率贝叶斯深度学习模型可以对相同的输入输出不同的预测。通过观察输出,我们可以解释预测本身的不确定性。

深度学习中的贝叶斯方法

贝叶斯统计方法从一组数据中推断出与数据一致的潜在概率分布。

与更传统的方法相比,这种方法提供了几个优点,例如能够将关于分布的先验信息结合到分析中,并计算各种可能分布的置信程度。

在贝叶斯深度学习中,我们希望计算后验函数:

图片作者。

然而,这是困难的,并且大多数时候不可能计算真实的后验概率,因此它是近似的。这种近似被称为变分贝叶斯,或者更具体地说,变分推理。然而,这些方法在计算方面是昂贵的。

元学习和贝叶斯推理

在我们开始之前,简单定义一下什么是元学习会很有帮助。正如我们所知,计算机和人类的学习方式不同。举一个具体的例子:

Fede de RodtUnsplash 上拍摄的照片

如果我们给这张图片贴上标签,它会是一杯咖啡。有趣的是,一个人可以很容易地从几个样本中知道这是一杯咖啡。嗯,这不适用于计算机。

想想这些图像:

由 DALLE-2(https://openai.com/dall-e-2/)生成的图像

一个从少量图像中学习的人可以很容易地正确分类这些图像。用于训练的图像很少的计算机可能很难对它们进行分类。

由 DALLE-2(https://openai.com/dall-e-2/)生成的图像

或者这些图像,它们中的每一个都代表一杯咖啡,人类应该能够正确地对它们进行分类,然而计算机可能会对它们进行错误的分类。

如果计算机也能用很少的样本来概括数据集,那就太好了。这就是元学习的要点和主要思想。它也被称为学会学习。

我们可以在没有任何狗的图像上训练一个模型,然后它应该能够在看到一些可爱的狗照片后告诉我们给定的图像是否包含狗。

由 DALLE-2(https://openai.com/dall-e-2/)生成的图像

实际上,在元学习时代有各种各样的方法。所提到的论文利用了高度面向研究的元学习技术,该技术试图允许模型 在单次向前传递中学习

后验和后验预测分布

现在,让我们区分这两个词。

  • 在后面的
  • 后验预测分布

图片作者。(后)

当我们想要找到模型参数的分布时,我们使用贝叶斯定理重写后验概率。证据,边际似然性, P(x) 充当归一化常数。

这里后验分布取决于θ,θ是未知参数。

预测分布是不同的。首先让我们看看先验预测分布:

图片作者。(先验预测分布)

右手边的积分告诉我们平均所有可能的θ值。真好,但是为什么呢?

在开始训练之前,我们只有先验分布,这意味着测量模型参数不确定性唯一方法是使用先验分布!

到时间模型看到新的数据,所以我们要对θ的所有可能值进行平均。因为我们有兴趣了解由下式给出的数据的分布:

图片作者。

在获取一些样本并进行训练后,我们通过使用后验概率更好地表示了模型参数的不确定性。按照上面相同的逻辑,后验预测分布变成:

图片作者。

Xn 代表独立的数据点。有一些结论:

  • 如果我们能找到一个好的先验,我们的训练数据将密切遵循这种模式。
  • 由于新数据点的引入,预计后验预测将具有不同的方差(通常更大)。

总结

总之,后验处理模型参数的分布。另一方面后验预测分布解释了我们将在未来 (Xn)得到的数据点的分布。****

因此,后验预测的主要思想是,我们不确定模型参数(认知不确定性),希望通过使用似然的平均值来预测新的数据点,但同时我们考虑模型参数的所有可能值。

预测的关键分布,即后验预测分布(PPD),可以推断为[1]:

文献[1]中的后验预测公式。

建议的方法:先验拟合网络

在贝叶斯深度学习中,大多数时候真实的后验概率是近似的,因为它是难以处理的。说到底,我们感兴趣的是在后验预测公式中显示的术语右侧。

有趣的是,这篇论文提出了一种新方法,称为先验数据拟合网络,它训练一个模型来直接优化左边的术语。这意味着,我们不仅使用数据集,还使用查询。

该论文的作者绘制了该过程:

“先验数据拟合网络(pfn)的可视化。我们对先前的数据集进行采样,并对这些数据集的保留样本进行 PFN 拟合。给定一个实际数据集,我们将它和一个测试点输入到 PFN,并在一次正向传播中获得贝叶斯推断的近似值。”[1]

让我们把它分成更小的部分:

  • 首先,我们选择一个先验。
  • 先前的样本数据集。
  • 通过最大化可能性开始元学习过程。这也等于最小化负面可能性。应用对数是因为当涉及乘法时它具有良好的性质。因此负对数似然性被最小化。
  • 数据集被输入到一个参数化的模型中。

换句话说,它们生成大量数据(嗯,无限多是理想的),并使用那些参数化的模型来标记生成的数据。

解释了文献[1]中的算法。

该模型可以是卷积网络或任何其他类型的神经网络架构。

作者选择了变压器作为 PFN ,因为变压器毕竟是我们所需要的。

使用 Transformer 并把零件组装在一起

正如我们所知,最初的变压器架构【2】由一个编码器和一个解码器组成。作者稍微修改了这个架构,使其排列不变。因此这意味着不再使用位置编码。

n = 3 个输入对和 m = 2 个查询的转换器的可视化。每个条形代表一个输入,箭头显示每个代表可以关注什么。”[1]

所提出的模型返回每个给定查询x的后验预测分布,这仅取决于数据集和查询本身。

在训练期间,输入的总数保持固定(N 个输入)。这些输入可以分成一个求和公式,即:

  • N = m + n

其中 n 是输入的数量, m 是给定查询的数量。换句话说,我们希望 Transformer 能够学会处理不同大小的数据集。

由于有各种各样的任务,最流行的是回归和分类,输出层是灵活的,并根据任务的变化。

结论

本文提出了一种利用元学习技术同时训练一个特殊的转换器的方法。这使得我们可以比变分推断更快地做出后验推断(快 1000 倍)。

基准测试结果证实:

“具有 30 个训练样本的数据集子集的聚合性能。我们的小说《PFN-BNN》整体表现最强。有关每个数据集的结果,请参见附录中的表 7。”[1]

你可以从这里查看论文的官方实现。

参考

[1]:塞缪尔·穆勒,诺亚·霍尔曼,塞巴斯蒂安·皮内达,约瑟夫·格拉博卡,弗兰克·赫特,变形金刚可以做贝叶斯推理,ICLR 2022。

[2]: Ashish Vaswani 等人注意力是你所需要的全部,神经信息处理系统进展,2017。

贝叶斯直觉与日常物理学

原文:https://towardsdatascience.com/bayesian-intuition-illustrated-with-everyday-physics-1e2f797ced0b

用数据更新你的信念就像往桶里倒水一样

本杰明·沃罗斯在 Unsplash 上的照片

介绍

让我们玩一个游戏。一个巫师选择了一个实数,我们需要猜一猜。

没有额外的信息,我们不知道这个数字是多少。它可以是实数线上的任何东西。

幸运的是,巫师愿意给我们提供线索。他将从正态分布中随机抽取一个数,其平均值等于他选择的数,标准差等于 10。抽到的号码是 136.6。

现在我们对选择的数字有了更好的了解。在这条线索之前,很有可能这个数字是负数。现在,很有可能这个数字不仅是正的,而且大于 100。这条线索更新了我们的信念。

巫师同意以同样的方式给我们第二条线索。这次他抽到 123.4。我们现在有理由相信,所选的数字大约在 130 左右——是两个抽取数字的平均值。

第二条线索也让我们更加自信。在第一条线索之后,被选中的数字可能会超过 150。根据第二条线索,这种结果现在不太可能出现。

我们可以想象,如果我们不断从巫师那里得到线索,我们会不断更新对巫师所选数字的信念。如果我们收到 10,000 条类似的线索,我们就有理由相信巫师的数字接近 10,000 次抽奖的平均值。

每个线索应该在多大程度上更新我们的信念?贝叶斯法则提供了这个问题的答案。

用贝叶斯推理更新我们的信念

精确定义信心

在深入研究贝叶斯模型之前,我们需要回顾一些术语。

还有两种描述标准差的方法。第一个是方差,它是分布平均值的平均平方距离。第二个是精度,是方差的倒数。

大的方差对应于高的不确定性,大的精度对应于高的置信度。

在上一节的示例中,正态“线索”分布的标准差是 10,方差是 10 =100,精度是 1/100。

正常的正常模型

现在我们已经定义了精度,让我们进入模型。在我们的游戏中,我们称巫师选择的数字为θ;这是我们试图推断的参数。对于一个给定的线索,我们将把抽出的数字称为 D,因为它是更新我们信念的“数据”。

我们想计算出P(θ| D)——给定线索中提供的数据,所选数字的概率分布。这可以使用贝叶斯规则来计算,如下所示:

图片由作者提供。贝叶斯法则。

上述等式有四个组成部分:

  • P(θ| D)——称为后路。这是描述我们观察 D 后更新信念的分布。
  • P(D |θ)——称为的可能性。对于给定的 θ ,如何分配 D ?在游戏中,这个分布是正态分布,平均值为 θ ,标准差为 10。
  • P(θ)——被称为先验。这是在观察到 D. 之前描述我们信念的分布
  • P(D)——被称为边际可能性。一般我们不会太担心这个分量。我们可以把它看作一个常数,确保后验分布整合为一。

如果我们用正态分布来描述我们的先验信念,计算后验概率就相对简单了。这是因为正态分布是已知方差的正态似然的共轭先验

这里涉及到相当多的代数知识,我就不赘述了,但是贝叶斯定理的最终结果是后验分布也是正态分布。

在正态-正态模型中,后验均值是先验均值和数据(线索中绘制的值)的精度加权均值。后验精度是先验精度和数据精度之和。

我们可以编写一个简单的 Python 函数来计算后验参数,如下所示:

一旦我们根据给定的线索更新了我们的信念,后验分布就变成了下一个线索的先验分布。因此,我们反复使用贝叶斯法则来更新我们对每个线索的信念。

在第一条线索之前,我们没有关于巫师号码的信息。我们可以将这些不知情的信念建模为以 0 为中心的无限宽的正态分布。这个分布的方差为无穷大,对应的精度为 0。正如我们前面提到的,分布“线索”的精度是 1/100。所以每条线索都给我们的信念增加了 1/100 的精确度。所以我们的信念分布在五条线索后精度为 0.05,十条线索后精度为 0.1,依此类推。

随着我们的信念变得越来越自信(高精度),每一条新线索改变我们信念的能力越来越小。例如,当我们收到第二条线索时,我们通过将 50%的权重放入从线索中提取的值中,并将 50%的权重放入我们先前的信念中,来更新我们的信念。当我们收到第 10 条线索时,我们把 90%的权重放在先前的信念上,只有 10%放在新的信息上。

当我们有自信的先验信念时,新信息不会改变我们的想法。

下面的动画展示了当我们收到随机产生的线索时,我们信念的演变。请注意,一开始,我们的信念会随着每一个新线索而显著改变,因为我们是“开放的”在收到许多线索后,我们基本上已经认定 θ 在 120 左右,即使远离 120 的线索也无助于改变我们的信念。一旦我们观察到压倒性的证据,我们的信念就会变得沉重而不可动摇。

图片由作者提供。“正常正常”模型的可视化。黑线代表从正态分布中抽取,未知平均值为 θ,已知标准差为 10。蓝色分布代表关于θ实际值的信念。每一次绘制都是一条线索,更新了我们对θ真实值的信念。

混合水的热力学

假设我在一个 30 摄氏度的桶里放了 2 公斤水,然后我把 1 公斤 90 摄氏度的热水倒进桶里。忽略与周围的传热,混合后桶中水的质量和温度会是多少?

根据质量守恒,最终质量就是最初在桶中的水的质量(1 千克)和倒入桶中的水的质量(2 千克)的总和。所以,3 斤。

如果我们假设比热容不变,最终温度就是桶中已有水的温度和我加入的水的温度的质量加权平均值。这就得出(2 * 30 + 1 * 90)/3 = 50 摄氏度。

这为方差已知的正态-正态贝叶斯模型提供了精确的数学模拟。最初桶里的水代表我们先前的信念,我们倒入的水代表新的信息。质量相加就像贝叶斯模型中精度相加一样。最终温度是质量加权平均值,就像后验平均值是精度加权平均值一样。精确的数学类比是针对我们在贝叶斯和热力学模型中所做的假设的。然而,我发现定性的类比对于理解一般的贝叶斯推理是有用的。

探索类比

如果水桶中已经有很多水,那么就需要大量不同温度的水来更新水桶中的水温。如果有人有非常自信的先验信念,改变他们的想法需要强有力的相反证据。

用证据来说服一个已经下定决心的人,就像试图通过向海洋中倒入一杯热咖啡来温暖海洋一样。

反过来,如果我们把水倒进一个空桶里,最终的温度将是我们倒入的水的温度。这相当于完全忽略我们先前的信念,只根据新的信息就得出结论——就像我们在巫师的游戏中用第一条线索做的那样。

如果我们把水倒入一桶相同温度的水中,新的温度将与原来的温度相同。但是,桶里会有更多的水,从现在开始更难改变温度。这相当于证实我们信念的证据——它不会改变我们的想法,但它确实让我们的信念在未来更加不可动摇。

结束语

当我们面对新的信息时,我们应该考虑我们的水桶里已经有多少水,以及信息增加了多少水。作为人类,我们经常犯过度自信的错误。我们很容易根据自己的经验得出僵化的结论,即使面对压倒性的相反证据,也无法更新我们的信念。然而,解决方法不是完全忽略先前的信念。

贝叶斯统计的一个经典例子是皮埃尔·西蒙·拉普拉斯在 18 世纪提出的日出问题。根据过去的观察,明天太阳升起的概率有多大?如果有人只在地球上生活了一天,对他们来说日出是罕见的事情可能是可信的。对于我们这些目睹过多次日出的人来说,我们可以确信明天太阳还会升起,我们应该高度怀疑任何与此相反的证据。在这种情况下,我们的先验知识应该几乎是不可移动的。正如卡尔·萨根所说,“非凡的主张需要非凡的证据。”

贝叶斯机器学习和朱莉娅是天作之合

原文:https://towardsdatascience.com/bayesian-machine-learning-and-julia-are-a-match-made-in-heaven-c3c498f2d221

两个 Julia 库让贝叶斯机器学习变得轻而易举

Pablo ZucheroUnsplash 上拍摄的照片

正如我在早先的一篇文章中所说,贝叶斯机器学习可能非常强大。然而,用 Python 构建实际的贝叶斯模型有时有点麻烦。你在网上找到的大多数解决方案要么相对复杂,要么需要学习另一种特定领域的语言。当您需要高度定制的解决方案时,后者很容易限制您的表达能力。

另一方面,在 Julia 中进行贝叶斯机器学习可以缓解这两个问题。事实上,你只需要几行原始的 Julia 代码来构建,例如,一个用于回归的贝叶斯神经网络。朱莉娅的通量图灵软件包将处理引擎盖下的繁重工作。

因此今天,我想向你展示如何用不到 30 行 Julia 代码实现和训练贝叶斯神经网络。在向您展示代码之前,让我们简要回顾一下主要的理论方面:

贝叶斯机器学习的三个步骤

像往常一样,我们希望通过贝叶斯定律找到后验分布:

(图片由作者提供)

由于分母中的数据项是一个常数,我们可以简化上述公式:

(图片由作者提供)

为了避免混淆,让我们使用以下标准措辞:

(图片由作者提供)

对于贝叶斯神经网络回归,我们进一步指定似然函数:

(图片由作者提供)

这表示具有由神经网络输出定义的平均值的独立正态分布的乘积。正态分布的方差被选择为常数。

相应的先验分布可能如下所示:

(图片由作者提供)

网络权重的先验分布是独立的标准正态分布。对于方差的平方根(也称为标准偏差),我们使用标准的伽马分布。所以,从理论的角度来看,我们都准备好了。

理想情况下,我们现在希望通过以下步骤实现贝叶斯神经网络:

在代码中将这三个步骤相互分开,将有助于我们

  • 保持可读性 —除了相应的函数更小之外,潜在的读者也可以更容易地从先验中辨别可能性。
  • 在粒度级别保持代码的可测试性——可能性和先验分布显然是不同的关注点。因此,我们也应该能够单独测试它们。

考虑到这一点,让我们开始在 Julia 中构建模型。

定义似然函数

Flux库提供了我们构建和使用神经网络所需的一切。它有Dense来建立前馈层和Chain来将这些层组合成一个网络。事实上,它们就像我们在本文中定义的LayerNetwork结构一样工作。

因此,我们的Likelihood结构由神经网络network和标准差sigma组成。在前馈通道中,我们使用网络的输出和sigma来定义高斯似然的条件均值和标准差:

Normal.(...)中的点让我们为每个网络输出定义一个正态分布,每个都有标准偏差sigma。我们可以将此与来自分布库的logpdf(...)相结合,以训练具有最大似然梯度下降的模型。然而,为了执行贝叶斯机器学习,我们需要添加更多的元素。

这就引出了本文的中心功能,即Flux.destructure()。从文档中:

destructure(m)
Flatten a model's parameters into a single weight vector.julia> m = Chain(Dense(10, 5, σ), Dense(5, 2), softmax) Chain(Dense(10, 5, σ), Dense(5, 2), softmax) julia> θ, re = destructure(m);julia> θ 
67-element Vector{Float32}:
-0.1407104 
...
The second return value re allows you to reconstruct the original network after making modifications to the weight vector (for example, with a hypernetwork).julia> re(θ .* 2)
Chain(Dense(10, 5, σ), Dense(5, 2), softmax)

总之,destructure(...)获取一个实例化的模型结构并返回一个包含两个元素的元组:

  1. 模型参数串接成一个向量
  2. 一个重建器函数,它采用一个如 1 所示的参数向量。作为输入,并返回带有这些参数的模型

后者很重要,因为我们可以向重建器提供任意参数向量。只要它的长度有效,它就会返回具有给定参数配置的相应模型。在代码中:

最后一个函数将允许我们分别向重建器提供权重和标准偏差参数。为了让Turing处理贝叶斯推理部分,这是一个必要的步骤。

从这里,我们准备转移到先前的分布。

定义先验分布

这部分非常简短,我们只需定义权重向量和标准差标量的先验分布:

定义了可能性和先验后,我们可以从先验预测分布中抽取样本

(图片由作者提供)

虽然这可能看起来像一个复杂的公式,但我们基本上只是绘制蒙特卡罗样本:

先前预测分布本身包括来自sigma的噪声。仅从网络中提取的先验预测,即先验预测平均值,产生了良好且平滑的样本:

先验预测从均值函数(贝叶斯神经网络的输出;图片作者)

现在,我们可以训练这个模型了。

训练贝叶斯神经网络

在本例中,我们将使用合成数据,采样自

(图片由作者提供)

后一个因子表示 (-2,2) 上的均匀密度。

合成数据集——50 个来自正常均匀模拟(图片由作者提供)

为了使用Turing,我们需要定义一个模型,正如他们的文档中所解释的。应用于我们的示例,我们得到以下结果:

最后,我们需要为贝叶斯后验推断选择一个算法。由于我们的模型相对较小,哈密顿蒙特卡罗 (HMC)是一个合适的选择。事实上,HMC 被普遍认为是贝叶斯机器学习的黄金标准算法。不幸的是,它在高维空间变得非常低效。

尽管如此,我们现在通过图灵使用 HMC,并收集来自 MCMC 后验的结果:

从这里,我们可以看到完整的后验预测分布,

(图片由作者提供)

这是以与先前预测分布类似的方式完成的(星形变量表示训练集之外的新输入)。唯一的区别是,我们现在使用来自 MCMC 后验分布的样本。

90%置信区间的后验预测分布。作为贝叶斯机器学习的典型,认知不确定性在观察数据的范围之外增加(图片由作者提供)

使用上面的例子,很容易尝试其他以前的发行版。

即插即用,具有不同的先验分布

作为另一大优势,Turing可以使用来自Distributions库的几乎所有发行版作为先验。这也允许我们尝试一些奇异的权重先验,比如半径为 0.5 的半圆分布。我们所要做的就是替换高斯先验:

使用与之前相同的设置,我们得到以下后验预测分布:

独立 *Semicircle(0.5)* 先验权重分布的后验预测分布(图片由作者提供)

可能性显然不止于此。另一个卓有成效的调整可能是引入超先验分布,例如权重先验的标准偏差。

使用不同于神经网络的模型也很简单。你只需要调整Likelihood struct 和相应的函数。

摘要

本文简要介绍了 Julia 的贝叶斯机器学习。事实上, Julia 不仅速度快而且还能让编码变得更加容易和高效。

虽然 Julia 仍然是一门年轻的语言,在将 Julia 程序部署到产品中时还存在一些问题,但对于研究和原型开发来说,它绝对是一门令人敬畏的语言。尤其是不同库之间的无缝互操作性可以大大缩短学术界内外的迭代周期。

在这一点上,我也非常希望在不久的将来,我们会看到更多的 Julia 被用于工业级的产品代码中。

原载于 2022 年 3 月 8 日https://sarem-seitz.com

贝叶斯方法(1)

原文:https://towardsdatascience.com/bayesian-method-1-1cbdb1e6b4

先验分布

图 0.1 不同参数下的贝塔分布。(图片由作者提供)

很容易找到大量介绍贝叶斯统计的好文章。然而,它们中的大多数只介绍了什么是贝叶斯统计以及贝叶斯推理是如何工作的,而没有涉及许多数学细节。此外,这也是一个充满乐趣和挑战的探索领域。

因此,我打算写一系列文章来分享更多关于贝叶斯统计的理论,包括先验的选择,贝叶斯推断中的损失函数以及贝叶斯统计和一些频率主义方法之间的关系。本帖将介绍贝叶斯统计中使用的先验分布。为什么我们需要学习这个?因为选择先验分布是我们需要使用贝叶斯推理的第一步。更多地了解它们有助于选择。

基础知识

在这里,我们从贝叶斯统计如何工作的简要概述开始,并且在这里也介绍了我们稍后将使用的一些符号。在贝叶斯统计中,我们假设一个先验概率分布,然后使用我们拥有的数据更新先验。这种更新给出了后验概率分布。我们将后验概率表示为π(θ|x)(π可能看起来很烦人,因为它也是数学中很常见的常数,但在这种情况下,π提醒我们该分布与总体分布的参数有关),其计算方法如下

等式 1.1 计算后验概率的公式

其中,θ是所有可能的参数值的空间(这里的“空间”,我们指的是“样本空间”),并且π(x|θ)可能性——观察到给定真实参数值为 θ ,输出 x 的条件概率。由于θ∈θ是与先验分布 n 相关的参数,而不是总体的分布,我们可以 θ 超参数和往常一样,我们使用粗体( x )来表示向量。分母又称为证据,是使后验概率π(θ|x)成为概率分布(总和为 1)的归一化因子(常数)。这很容易验证**

在推理中可以忽略归一化因子,我们可以在一些文献中看到这一点,如[1],因为省略常数不会改变曲线的形状。

那么先验概率可以写成这样的形式

等式 1.2 不带分母的后验概率

一旦我们有了后验分布,也就是参数的分布(记住这一点),我们就可以计算预测分布。是条件概率,是观察 y ,给定数据x的概率分布。其计算方法如下

等式 1.3 预测分布

其中红色部分是新观测值的概率密度函数,给定参数 θ 。等式 1.3 一开始可能看起来有点混乱,但仔细观察后,我们可以看到它实际上是使用总概率的定律计算的(就像加权平均一样简单),它是给定参数值 θ 和参数取值 θ 给定数据 x 的概率分布的乘积的积分

选择先验

先验有时被描述为关于数据的“信念”。[2]这意味着我们根据我们对数据的了解来选择先验。当然,这并不像“信念”这个词所暗示的那样完全是一个主观的问题。

先验的性质

请注意,参数的分布可以是无界的,这意味着它的概率密度是非负的,但它们的总和或积分是无限的。我们称参数的这种分布为不恰当的先验分布

根据维基百科的说法,一个信息性的先验表达了关于一个变量的具体、明确的信息。通常,无论如何都要避免,但是如果先验信息是可用的,信息先验是将信息引入模型的合适方式。[7]

当我们不太了解我们的数据和参数的分布时,选择所谓的“模糊先验”是有意义的,它反映了最少的知识。所以我们需要一个没有人口基数的先验分布,这就很难构造,对后验分布的作用微乎其微。这样的先验密度称为无信息先验,或扩散先验。而有些人宁愿认为先验分布总是包含一些信息。有时不适当的先验被用来代表这种模糊的先验。稍后我们将看到这样的例子。

一个相关术语是弱信息先验,它包含部分信息,这意味着它足以给出后验分布的合理界限,但不能完全捕捉一个人关于参数的科学知识。[3]

先验的一个非常有趣的性质是共轭,这意味着后验分布与先验分布具有相同的参数形式。我们可以看到,这种先验与后验密切相关,因此我们说它包含了强先验知识。[5]共轭先验的好处是显而易见的——后验分布将是一个已知的分布。

一些常见前科的例子

  1. 制服在先

如果参数值是有界的,最直观和最容易的先验是均匀的先验分布。该先验是非信息性的(有时也称为“低信息先验”[2]),它假设参数空间θ中的所有参数都是同等可能的。比如我们要用伯努利分布对数据进行建模(就像著名的例子——抛硬币),参数 p 是一个概率,落在区间【0,1】内。在这种情况下,先验概率变为 π(θ) = 1 ,对于【0,1】中的 θ

2.霍尔丹在先

最少的知识不一定意味着所有的参数都是同样可能的。许多其他无信息的前科也是可能的。无信息先验的另一个例子是 J. B. S .霍尔丹提出的用于估计罕见事件的霍尔丹先验。霍尔丹先验实际上是参数 α=0,β=0 的贝塔分布。因此霍尔丹的先验是

情商。2.1 霍尔丹先验

其中 B(α,β) 为贝塔函数。提醒一下,Beta 函数是这样的:

等式 2.3 贝塔函数

也可以写成伽玛函数

等式 2.4 根据伽马函数的贝塔函数

注意, Beta(0,0) 没有定义,但是我们可以考虑它在点 (0,0) 的近似值,如下图所示

等式 2.5 参数 α=0,β=0 的贝塔分布的极限行为

后验分布π(θ|x)θ⁻ (1-θ)⁻ )成正比(回想一下贝叶斯定理可以写成公式 1.2 的形式),也就是说

方程 2.6 霍尔丹先验没有归一化系数

该先验赋予 θ=1θ=0 最大权重。使用[5]中的例子可以清楚地说明这一点:考虑我们正在观察一种未知化合物是否会溶解于水的情况。起初,我们对结果一无所知。因此,在观察到一个小样本溶解后,我们立即假设所有的样本都会这样做;如果没有,我们假设没有样品可以溶解。

3.共轭先验—贝塔分布

第三个例子是贝塔分布,它是二项式分布的共轭先验。并且注意,由于伯努利分布是二项式分布(与 B(1,1) 相同)的特例,贝塔分布也是伯努利分布的共轭先验。是共轭先验的典型例子(在维基百科、【3】和上出现过)。

这里我们将展示为什么贝塔分布与二项式分布共轭。首先回忆一下,二项分布的概率质量函数是

等式 2.7 二项式分布的概率质量函数(pmf)

其中 n 为试验总次数, k 为成功次数, p 为成功概率。因此,可能性是

等式 2.8 可能性

参考我们在基础知识一节看到的,似然性表示为π(x|θ),其中 x 为观测值,所以 x = (k,n-k)。这意味着

二项分布的参数成为观察值,这种可能性中的“参数”是超参数。

然后我们选择贝塔分布作为先验。我们要做的是证明后验分布与先验分布是同一类型。

等式 2.9 选择贝塔分布作为先验分布

后验分布推导如下

等式 2.10 后验分布

我们可以看到后验分布也是贝塔分布。

4。杰弗里斯先验

Jeffreys 先验是根据 Fisher 信息矩阵的行列式的平方根定义的非信息先验。

Def 2.11 杰弗里斯先验的定义

费希尔信息和费希尔信息矩阵在这里介绍过,但是为了方便起见,我们在这里也再次提及。最初,费希尔信息被定义为分数的方差

Def 2.12 费希尔信息的定义

其中较低的指数 θ 表示期望值是关于θ的,矩阵形式写为

等式 2.13 费希尔信息矩阵

但是在某些特定的条件下(密度函数 f 是二阶可微的和正则的条件,可以在这里找到很好的总结)。

等式 2.14 特定条件下的费希尔信息

等式 2.14 是单变量情况下的公式(当有多个参数时,我们使用矩阵形式)。让我们试着计算伯努利试验的杰弗里斯先验,这是一个单变量的例子。我们使用这个分布进行演示是有原因的,我们将在后面看到。我们知道伯努利分布的概率分布是

方程 2.15 伯努利分布的密度函数

现在我们需要计算密度函数的费希尔信息(方程 2.15)

等式 1.26 伯努利试验的费希尔信息

由于参数只是一维的(单变量),费雪信息只是一个数,也是行列式,我们有先验分布

等式 1.27

仔细看方程 1.27,我们会发现杰弗里斯先验和霍尔丹先验类似。但不像霍尔丹先验,杰弗里斯先验是适当的。方程式 1.27 的曲线如下

图 1.28(作者图片)

它还与β分布有关,因为等式 1.27 等于β(1/2,1/2)。

摘要

这个帖子主要是关于贝叶斯推断中的先验分布。首先,简单介绍了贝叶斯推理的基础知识。然后我们看看先验分布的类型,然后选择一些常见的先验分布。

****参考文献:

[1]李,T. S .,&芒福德,D. (2003)。视觉皮层中的分层贝叶斯推理JOSA A20 (7),1434–1448。

[2] Surya,Tokdar, 选择先验分布 ,2021 年 12 月 4 日获取。

[3]赫尔曼、卡林、斯特恩、H. S .、鲁宾(1995 年)。 贝叶斯数据分析 。查普曼和霍尔/CRC。

[4] Etz,a .,& Wagenmakers,E. J. (2017 年)。JBS 霍尔丹对贝叶斯因子假设检验的贡献。统计科学,313–329。

[5]杰恩斯,E. T. (1968 年)。先验概率。 IEEE 系统科学与控制论汇刊4 (3),227–241。

[6]斯坦福大学法学博士和瓦德曼大学(1994 年)。物理科学统计方法(第 28 卷)。学术出版社。

[7]戈尔奇,S. (2016 年 10 月)。信息先验和贝叶斯计算。在 2016 IEEE 数据科学与高级分析国际会议(DSAA) (第 782–789 页)。IEEE。

[8] Nicenboim,b .,Schad,D. J .,& Vasishth,S. (2021 年)。 认知科学贝叶斯数据分析导论

[9]杰里米·奥尔洛夫和乔纳森·布鲁姆, 共轭先验:贝塔和正常 ,2021 年 12 月 11 日获取。

http://halweb.uc3m.es/esp/Personal/personas/mwiper/docencia/English/PhD_Bayesian_Statistics/ch5_2009.pdf【先验分布】,2022 年 1 月 1 日获取。

延伸阅读:

有关概率论的更多信息:

***

关于贝叶斯和频率主义方法的比较:

https://medium.com/science-and-philosophy/subjectivism-in-decision-science-926c29feb7bb

补充:

用于生成图 0.1 的代码

x.v <- seq(0, 1, by=0.01)
n <- length(x.v)
m <- matrix(nrow=n, ncol=1)for (i in seq(0.1, 5, 0.3)) {
  y.v <- dbeta(x.v, shape1=i, shape2=15)
  m <- cbind(y.v, m)
}
for (j in seq(0.1, 5, 0.3)) {
  y.v <- dbeta(x.v, shape1=15, shape2=j)
  m <- cbind(y.v, m)
}
for (i in seq(0.1, 10, 1)) {
  y.v <- dbeta(x.v, shape1=i, shape2=i)
  m <- cbind(y.v, m)
}
n.c <- ncol(m)
n.c
# remove last column with Nas
m <- m[,-n.c]
par(mar = c(3, 4, 1, 2))
matplot(x=x.v, y=m, type="l", col="black", ylim=c(0,11), xlab="", ylab="PDF")

贝叶斯推理:鲨鱼攻击,并做出更好的决定

原文:https://towardsdatascience.com/bayesian-reasoning-shark-attacks-zombies-and-making-better-decisions-38951d3671b7

一个奇特的统计学概念如何帮助你在日常生活中做出更好的决定

作者图片

想想你是怎么做决定的。如果你像我和大多数人一样。你可能做得很差。现在,你可能会和我争论说,“史蒂文——我真的很擅长做决定。”

相信我,在这一点上,你错了。

我们不擅长做决定的原因是因为我们的大脑不是为此而生的。我们的大脑在某些事情上很棒,但在其他事情上就不那么棒了。我们来考虑一个例子,你觉得什么可能性更大?你是死于车祸还是飞机坠毁?事实证明,答案是你更有可能死于车祸。事实上,这种可能性大约是 26 倍。

那么,如果是这样的话——为什么我们害怕坐飞机而不开车呢? It 都与我们的大脑如何处理概率有关。

但是不要害怕,有一个非常聪明的人叫托马斯·贝叶斯,他给了我们一个框架来更好地做概率决策。

给我 10 分钟,我会讲:

-什么是贝叶斯推理?

——我们的大脑如何处理概率

——概率性思维的好处。

什么是贝叶斯推理?

托马斯·贝叶斯是 18 世纪的英国牧师,他在概率论方面的工作“一篇解决机会主义中一个问题的论文”是他最初提出他的理论的地方。他的朋友理查德·普莱斯继承了贝叶斯的研究成果,并运用它,想出了一种在面对不确定性时利用概率做出决策的方法。这被称为贝叶斯方法,近年来越来越受欢迎。

像皮埃尔·西蒙·拉普拉斯这样的数学家能够发展出更一般形式的贝叶斯定理。拉普拉斯将贝叶斯定理应用于天体力学问题,即根据运动行星的过去位置预测其未来位置。

贝叶斯定理在医学、统计学、机器学习等领域有着广泛的应用。

不过,这跟数学无关。尽管我很乐意向你抛出公式,但更重要的是理解贝叶斯定理背后的直觉。你需要提高你观察现实世界的能力,准确判断你遇到的事件的概率,并且愿意用你学到的新东西来提炼这些概率。

下面是贝氏如何接近它的,正如 贝氏对假人的描述【1】:

他使用的演示是基于两个球的使用。助手会把第一个球放在桌子上,球可以放在任何地方,但不能说球在哪里。

在助手多次丢下第二个球后,每次都告诉 Bayes 第二个球的位置和第一个球相对于它的位置,他会重复这个过程。根据第二个球给出的证据,他会试图估计第一个球的位置。

贝叶斯方法以托马斯·贝叶斯的工作为基础,并通过纳入先验知识(即先验证据提供的概率)对其进行了扩展,该方法首先在贝叶斯方法中引入。

关于概率的一个快速提示:概率,从最基本的意义上来说,就是给一个事件发生的可能性分配一个数值。这是一种衡量事情发生频率的方法。

有各种不同的方法来计算概率,这可能会变得非常复杂。但最简单的形式是,概率只是一个介于 0 和 1 之间的数字,它告诉你一个事件发生的可能性有多大。

0 表示该事件永远不会发生,1 表示几乎肯定会发生。

我们的大脑如何处理概率

如我所说,我们做得很差。但这不是我们的错。

人类只是不太擅长处理概率。研究表明,我们倾向于高估小概率,低估大概率。这在一定程度上是由于我们大脑的构造方式。

杏仁核负责威胁检测,当我们考虑可能危险的事情时,杏仁核更加活跃。海马体负责记忆,它更可能存储负面事件的记忆,而不是正面事件。

大脑的这两个部分共同作用,给了我们一种“消极偏见”这意味着我们更倾向于关注事件发生的微小可能性,而不是许多没有发生的例子。

例如,你可能更容易记住吃了贝类后生病的时间,而不是所有没有生病的时间。

我们不断扫描我们的环境,寻找可能伤害我们的东西,这可能会导致很多焦虑。

重要的是要记住,我们的大脑并不是为了应对现代世界而进化的。让我们的祖先存活下来的东西——比如快速识别捕食者的能力——在当今世界并不总是有用的。

如果我们想做出好的决定,我们需要学习如何以一种更合理的方式思考。这不是一项简单的任务,但对于理解我们周围世界的不确定性来说,这是一项必不可少的任务。

概率思维的好处

首先,你会更聪明。我并不是说要自大或吹牛,但如果你能掌握概率思维的概念,你将拥有很少人拥有的技能。

这种能力会在你生活的各个方面帮助你,从人际关系到财务到职业生涯。

如果你能进行概率性思考,你就能做出更好的决定,因为你会考虑到一种情况下所有可能的结果,而不仅仅是最有可能的结果。

你也不太可能陷入确认偏见——只关注确认你信念的信息的倾向。

如果你能以概率的方式思考,你会对新的信息持开放态度,你不会仅仅因为过时的信念让你感到舒服就坚持它。

让我们用一个现实生活中的例子: 如果你正试图决定是否值得去海里游泳。你的朋友试图让你相信它是安全的,但是你情不自禁地想起所有你看到的关于鲨鱼袭击的新闻。如果你用贝叶斯方法思考,你会考虑你所有的信息。

你知道每天有很多人在海里游泳,但很少有人被鲨鱼袭击。你也知道鲨鱼袭击比以前更受媒体关注,这使得它们看起来比实际情况更常见。

当你把所有这些信息都考虑进去时,你会发现被鲨鱼袭击的可能性其实很低。这将帮助你决定是否去游泳。

享受水。

当然,没有人能保证你不会被鲨鱼攻击,但是根据你所掌握的信息,概率性思维会帮助你做出最好的决定。

包扎

差不多够了。贝叶斯思维是那些超级书呆子的概念之一,一旦应用到你的生活中,就会带来很大的好处。你甚至不需要所有花哨的数学,只需要愿意考虑一种情况下所有可能的结果。

我希望这篇文章已经启发了你开始思考概率。如果你有任何问题或者想分享你自己的贝叶斯推理经验,我很乐意在下面的评论中听到你的意见。

感谢阅读!

来源:

  1. 贝叶斯为假人

如果你喜欢这篇文章,请考虑订阅我的时事通讯或者在推特上关注我。

贝叶斯回归从零开始

原文:https://towardsdatascience.com/bayesian-regression-from-scratch-a1fe19ff64c

使用 Python 从基本原理导出贝叶斯线性回归

克利姆·穆萨利莫夫在 Unsplash 上的照片

介绍

线性回归 是数据科学中最知名的算法,然而它有不止一个版本。大多数人使用的版本来自统计学家https://en.wikipedia.org/wiki/Frequentist_inference的解释,但还有一个版本来自贝叶斯https://en.wikipedia.org/wiki/Bayesian_statistics学派。****

在本文中,我们将复习 贝叶斯定理 ,频数统计和贝叶斯统计的区别,最后用 Python 从头开始实现 贝叶斯线性回归

注意:在整篇文章中,我假设读者对贝叶斯统计和线性回归有基本的了解。我确实重述了这些话题,但是没有深入到一个全新的读者可能完全掌握它们的程度。

贝叶斯推理重写

贝叶斯定理

贝叶斯定理写如下:

作者在 LaTeX 中生成的方程。

作者在 LaTeX 中生成的方程。

如果你不熟悉贝叶斯定理,我强烈推荐你看看我以前关于这个主题的文章:

****https://pub.towardsai.net/conditional-probability-and-bayes-theorem-simply-explained-788a6361f333

贝叶斯更新

贝叶斯定理用于根据新数据更新我们对某一事件的信念,使用以下公式:

作者在 LaTeX 中生成的方程。

在我们计算后验概率后,我们可能会获得关于我们试图建模的新数据。然后,我们使用旧的后验数据作为新的先验数据,用这个新数据计算新的后验数据。这个用新数据更新先验知识的过程称为贝叶斯更新。这就是贝叶斯推理 的本质所在。

你可以在我最近的一篇文章中读到更多关于贝叶斯更新的内容:

回归理论

线性回归

回归 旨在估计某一特性的效果,【x】,😗*

作者在 LaTeX 中生成的方程。

其中 β_0 为截距, β_1 为标定目标与特征关系的系数, ε 为误差项,在线性回归中遵循 正态分布 :

作者在 LaTeX 中生成的方程。

其中 σ标准差

线性回归的目的是确定描述特征、 x 和目标、 y 之间关系的参数 β_0、β_1【σ】的最佳值。

注意:我相信大多数阅读这篇文章的人都知道什么是线性回归,如果他们不知道的话,那么有很多资源可以比我更好地向你解释它!

频繁主义观点

寻找线性回归模型参数的最广为人知的方法来自统计学的频率观点。

频率主义者的观点采用【OLS】的普通最小二乘法,通过【RSS】的残差平方和来估计参数:****

作者在 LaTeX 中生成的方程。

其中 y 是实际值,而 ŷ 是来自我们的模型的预测值,其一般形式为:

作者在 LaTeX 中生成的方程。

其中 Xβ 是特征和参数的数组。

这个 OLS 方程的一般解是:

作者在 LaTeX 中生成的方程。

这个解决方案的完整推导可以在这里找到。

Frequentist 方法的关键是我们为每个参数获得一个单一固定值**

最终的模型在某种程度上假设我们正在建模的数据必须来自这些固定的参数。然而,不可能获得所有数据,因此假设这些单值参数 100%正确似乎是愚蠢的。另一种表述方式是,我们假设我们有足够的数据来推导出参数的有意义的单一值。**

贝叶斯观点

另一种观点认为,参数呈现值的分布,其中一些比另一些更有可能。它考虑了可能产生观测数据的几个似是而非的参数组合。

我们有一个我们认为参数可能是什么的初始视图/范围,例如我们可以认为截距同样可能是 0 到 10 之间的任何数字。这是我们参数的先验。

然后,我们使用观测数据更新先验,使用贝叶斯定理为每个参数创建后验分布,如下所示:

作者在 LaTeX 中生成的方程。

这是一个我们如何更新截距的例子。

也就是说目标,【y】,现在是数据上随机分布的变量, x ,参数 β_0, β_1,σ:**

作者在 LaTeX 中生成的方程。

因此每个目标变量的可能性是正态分布的 【概率密度函数】 :

作者在 LaTeX 中生成的方程。

y_i 的所有单个可能性的乘积产生当前模型及其给定参数的总可能性。

这个似然函数和贝叶斯回归作为一个整体的更密集和完整的推导可以在这里找到

观察贝叶斯方法的一个很好的方式是,当我们获得更多数据时,我们更新参数的分布,我们的模型变得更加确定参数应该是什么。他们很可能是 OLS 常客的估计,但这不是保证。

这是频率主义者和贝叶斯统计之间的差异的快速运行。如果你想更好地理解,那里有很多资源,但是我喜欢这个博客帖子!

Python 中的贝叶斯回归

现在让我们从头开始为一个简单的模型实现贝叶斯线性回归,其中我们有一个特征!

生成数据

我们首先使用 sklearn 的 make_regression 函数在 Python 中生成一些数据:

****# Import packages
import pandas as pd
import matplotlib.pyplot as plt
from sklearn import datasets# Generate data
x, y = datasets.make_regression(n_samples=100,
                                n_features=1,
                                noise=10)# Plot data
fig, ax = plt.subplots(figsize=(9,5))
ax.scatter(x, y)
ax.ticklabel_format(style='plain')
plt.xlabel('x',fontsize=18)
plt.ylabel('y',fontsize=18)
plt.xticks(fontsize=18)
plt.yticks(fontsize=18)
plt.show()****

作者用 Python 生成的图。

普通最小二乘法

我们可以使用 statsmodel 软件包,通过 OLS 方法来估计频率回归线:

****# Packages
import statsmodels.formula.api as smf# Create a dataframe
data = pd.DataFrame(list(zip(x.flatten(), y)), columns =['x', 'y'])# Calculating the slope and intercept
formula = 'y ~ x'
results = smf.ols(formula, data=data).fit()# Get our equation of the OLS line
intercept = results.params['Intercept']
slope = results.params['x']
x_vals = np.arange(min(x), max(x), 0.1)
ols_line = slope*x_vals + intercept# Plot the OLS line
fig, ax = plt.subplots(figsize=(9,5))
ax.scatter(data['x'], data['y'])
ax.plot(x_vals, ols_line,label='OLS Fit', color='red')
ax.ticklabel_format(style='plain')
plt.xlabel('x',fontsize=18)
plt.ylabel('y',fontsize=18)
plt.xticks(fontsize=18)
plt.yticks(fontsize=18)
plt.legend(fontsize=16)
plt.show()****

作者用 Python 生成的图。

为了清楚起见,斜率是 β_1, 截距是 β_0 ,sigma 是这就是我们上面在理论部分用来描述回归线的。**

这是频率主义者的解释,因为我们现在对每个参数只有单一的估计。我们现在将执行贝叶斯版本。

传道者

首先,我们需要给我们的参数分配一些先验分布。使用 OLS 估计的结果,我们构建了一个统一的无信息先验,其范围为 OLS 估计的 20%:

*****def make_uninformative_prior(name,data):
    """Function to make priors."""
    df = pd.DataFrame({name:data})
    df['Probability'] = 1/len(data)
    return df# Create a range of values for the slope
data_slope = np.linspace(results.params['x']*0.8,
                         results.params['x']*1.2, num=60)prior_slope = make_uninformative_prior('slope',data_slope)
prior_slope.head()# Create a range of values for the intercept
data_inter = np.linspace(results.params['Intercept']*0.8,
                         results.params['Intercept']*1.2, num=60)prior_inter = make_uninformative_prior('intercept',data_inter)
prior_inter.head()# Create a range of values for the sigma
data_sigma = np.linspace(results.resid.std()*0.8,
                         results.resid.std()*1.2, num=60)prior_sigma = make_uninformative_prior('sigma',data_sigma)
prior_sigma.head()*****

如果我们对实际参数有所了解,我们可能会使用不同的先验,对参数的某些值进行不同的加权。前科完全是主观武断的。这通常是反对贝叶斯统计的一个论点,因为它导致非客观概率。

我们现在计算三个参数的联合分布。这告诉我们一个特定的参数组合解释观察到的数据的可能性有多大:

*****# Counter for the row index
counter = 0# Dataframe to store the combinations in
df = pd.DataFrame(columns=['slope','intercept','sigma','prior'])# Iterate through the slope
for slope in prior_slope['slope']:
    prob_slope = \
    prior_slope['Prior'].loc[prior_slope['slope'] == slope]

    # Iterate through the intercept
    for intercept in prior_inter['intercept']:
        prob_inter = \
        prior_inter['Prior'].loc[prior_inter['intercept'] \
                                 == intercept]

        # Iterate through the error
        for sigma in prior_sigma['sigma']:
            prob_sigma = \
            prior_sigma['Prior'].loc[prior_sigma['sigma'] == sigma]

            # Calculate the prior of this specific combination
            prob = \
            float(prob_slope)*float(prob_inter)*float(prob_sigma)

            # Insert the row of data
            df.loc[counter] = \
            [slope] + [intercept] + [sigma] + [prob]

            # Update row index
            counter += 1*****

如果这种格式在你的屏幕上看起来不舒服,我很抱歉。如果是这样的话,我强烈推荐你在我的 GitHub repo 这里查看代码,让它更容易解释和理解!

我完全知道 for 循环不是最优的,使用 pandas 和 numpy 的矢量化实现会更快。然而,我认为使用循环可以让我们更好地理解正在发生的事情!

因为我们对每个参数都有未知的先验,所以每个组合都有完全相同的先验概率:

图片作者。

可能性

就像我们之前说的,后验与先验和似然的乘积成正比。因此,要获得每个参数的后验分布,我们需要根据我们的观测数据计算它们的似然性。

为了计算可能性,我们为每个可能的组合(每一行)建立一个模型,并使用我前面提到的公式计算残差来找到可能性:

*****counter = 0
df['likelihood'] = df['prior']# Loop over the combination of values
for slope in prior_slope['slope']:
    for intercept in prior_inter['intercept']:        
        for sigma in prior_sigma['sigma']:

            # Compute the predictions from this line
            predictions = slope * data['x'] + intercept

            # Compute residual/errors of this line
            residual = data['y'] - predictions

            # Compute the likelihood function that we saw above
            likelihoods = norm(0, sigma).pdf(residual)

            # Compute the total likelihood
            df['likelihood'].loc[counter] = likelihoods.prod()
            counter += 1*****

这部分可能需要一段时间来运行,这是在大规模模型中使用贝叶斯方法的问题之一。要知道为什么会这样,查看一下我之前关于贝叶斯共轭先验的文章,这篇文章告诉你实施贝叶斯定理的一些缺点:

*****

我们的数据框架现在看起来像这样:

图片作者。

贝叶斯更新

我们现在可以如下执行我们的贝叶斯更新:

df['posterior'] = df['prior'] * df['likelihood']
df['posterior'] = df['posterior']/df['posterior'].sum()

我们得到的数据框架是:

图片作者。

边际分布

为了输出每个参数的边际后验分布,我们需要对其他两个参数的后验进行求和。例如,为了找到斜率的边际后验分布,我们总结出,对于斜率的每个值 的后验超过σ和截距(基本上是一个积分):

slope_df = df.groupby('slope').sum()

然后,我们可以绘制斜率的后验分布:

# Plot the posterior distribution of the slope
plt.figure(figsize=(8,5))
plt.plot(slope_df.index, slope_df.posterior, linewidth=3)
plt.xticks(fontsize=18)
plt.yticks(fontsize=18)
plt.xlabel('Slope Value', fontsize=18)
plt.ylabel('PDF', fontsize=18)
plt.axvline(results.params['x'], color='red', ls='--', label='OLS Estimate')
plt.legend(fontsize=16)
plt.show()

作者用 Python 生成的图。

斜率现在是一个分布!

我们可以对截距和误差项进行类似的计算:

intercept_df = df.groupby('intercept').sum()
sigma_df = df.groupby('sigma').sum()# Plot the posterior distribution of the Intercept
plt.figure(figsize=(8,5))
plt.plot(intercept_df.index, intercept_df.posterior, linewidth=3)
plt.xticks(fontsize=18)
plt.yticks(fontsize=18)
plt.xlabel('Intercept Value', fontsize=18)
plt.ylabel('PDF', fontsize=18)
plt.axvline(results.params['Intercept'], color='red', ls='--', label='OLS Estimate')
plt.legend(fontsize=16)
plt.show()# Plot the posterior distribution of sigma
plt.figure(figsize=(8,5))
plt.plot(sigma_df.index, sigma_df.posterior, linewidth=3)
plt.xticks(fontsize=18)
plt.yticks(fontsize=18)
plt.xlabel('Sigma Value', fontsize=18)
plt.ylabel('PDF', fontsize=18)
plt.axvline(results.resid.std(), color='red', ls='--', label='OLS Estimate')
plt.legend(fontsize=16)
plt.show()

作者用 Python 生成的图。

作者用 Python 生成的图。

OLS 估计值是这些参数最可能的值,但不是唯一的值。我们可以使用 216,000 种其他潜在组合来建立数据模型!

摘要

这个计算并不是那么直接,写这篇博客最终让我理解了整个贝叶斯回归过程。我建议读者在我的 GitHub 上查看完整的笔记本,并在上面玩一玩:

https://github.com/egorhowell/Medium-Articles/blob/main/Statistics/Bayesian_Regression.ipynb

结论

在这篇文章中,我们回顾了贝叶斯定理,解释了频数统计和贝叶斯统计之间的关键区别,最后从头开始进行贝叶斯线性回归。

您可能已经注意到,这个主题在您需要完全掌握的先决知识方面相当广泛。如果我试着去适应所有的背景话题,这个博客真的会成为教科书!

因此,我建议那些还没有完全理解我们在这里所做的事情的人复习一下贝叶斯统计和线性回归。有这么多关于这些主题的资源,会比我教得更好!

和我联系!

(所有表情符号都是由 OpenMoji 设计的——开源的表情符号和图标项目。执照: CC BY-SA 4.0*********

使用 PyMC3 的贝叶斯回归

原文:https://towardsdatascience.com/bayesian-regression-using-pymc3-e279ccc81d20

如何使用 PyMC3 包在 Python 中实现贝叶斯回归

Joachim Schnürle 在 Unsplash 上的照片

背景

PyMC3 (现在简称 PyMC)是一个贝叶斯建模包,使我们作为数据科学家能够轻松地执行 贝叶斯推理

在引擎盖下,PyMC3 使用【MCMC】的方法计算后验分布。现在,这种方法非常复杂,需要另外一篇文章来全面介绍。因此,我在这里链接了一个很好地解释了这个话题的帖子

您可能想知道为什么封装使用 MCMC?嗯这是为了绕过 计算 归一化常数 中的 贝叶斯定理

作者在 LaTeX 中生成的方程。

其中 P(H | D)后验P(H)先验P(D | H)似然P(D) 是归一化常数,定义为:

作者在 LaTeX 中生成的方程。

对于许多问题来说,这个积分要么没有封闭形式的解,要么无法计算。因此,像 MCMC 这样的方法被开发出来解决这个问题,并允许我们使用贝叶斯方法。

如果你不熟悉贝叶斯定理,我推荐你看看我以前关于这个主题的文章:

**https://pub.towardsai.net/conditional-probability-and-bayes-theorem-simply-explained-788a6361f333

还有另一种叫做 共轭先验 的方法也解决了这个棘手的问题,但是它的可塑性不如 MCMC。如果你想了解更多关于共轭先验的知识,请查看我以前的文章:

在这篇文章中,我们将介绍如何使用 PyMC3 包实现 贝叶斯线性回归 ,并快速浏览一下它与普通的 线性回归 有何不同。如果你想知道如何从零开始实现贝叶斯线性回归,那么看看我最近的帖子:

概述:贝叶斯与频率主义回归

从本质上来说, Frequentist 和 Bayesian 回归方法之间的关键区别在于它们如何处理参数。在频率统计中,线性回归模型的参数是固定的,而在贝叶斯统计中,它们是随机变量。

频率主义者使用https://en.wikipedia.org/wiki/Maximum_likelihood_estimation的方法来推导线性回归模型的值。MLE 的结果是每个参数的单一固定值。

然而,在贝叶斯世界中,你的参数有一个值的分布,它们可能有一定的概率。然后使用更多的数据更新这个分布,这样我们就可以更加确定参数的取值。这个过程被称为 贝叶斯更新 ,你可以在这里了解更多信息:

**

这是对贝叶斯和频率主义回归之间的主要区别的一瞥。如果你想要更深入的观点,有很多资源可以比我解释得更好!

使用 PyMC3

包装

首先,我们装入我们的包:

# Import pyMC3 and also arviz for visualisation
import pymc3 as pm
import arviz as az# Import the other core data science packages
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets
from scipy.stats import norm
import statsmodels.formula.api as smf

你可能需要安装 PyMC3 和T5 ArviZ。为此,只需遵循他们网站上的安装说明。

数据

现在我们使用 sklearn 的 make_regression 函数生成一些数据:

# Generate data
x, y = datasets.make_regression(n_samples=10_000,
                                n_features=1,
                                noise=10,
                                bias=5)# Create the dataframe
data = pd.DataFrame(list(zip(x.flatten(), y)),columns =['x', 'y'])# Plot the data
fig, ax = plt.subplots(figsize=(9,5))
ax.scatter(data['x'], data['y'])
ax.ticklabel_format(style='plain')
plt.xlabel('x',fontsize=18)
plt.ylabel('y',fontsize=18)
plt.xticks(fontsize=18)
plt.yticks(fontsize=18)
plt.show()

作者用 Python 生成的图。

频率回归线

我们使用 【普通最小二乘法(OLS) 的方法绘制频率线性回归线:

# OLS line
formula = 'y ~ x'
results = smf.ols(formula, data=data).fit()
results.params# Get our equation of the OLS line
inter = results.params['Intercept']
slope = results.params['x']
x_vals = np.arange(min(x), max(x), 0.1)
ols_line = inter + slope * x_vals# Plot the target against our feature with the OLS regression
fig, ax = plt.subplots(figsize=(9,5))
ax.scatter(data['x'], data['y'])
ax.plot(x_vals, ols_line,label='OLS Fit', color='red')
ax.ticklabel_format(style='plain')
plt.xlabel('x',fontsize=18)
plt.ylabel('y',fontsize=18)
plt.xticks(fontsize=18)
plt.yticks(fontsize=18)
plt.legend(fontsize=16)
plt.show()

作者用 Python 生成的图。

PyMC3: 100 个样本

要使用 PyMC3,我们必须启动一个模型,选择我们的先验,并告诉模型我们的后验应该是什么分布:

# Start our model
with pm.Model() as model_100: # Define the priors on each parameter:
    grad = pm.Uniform("grad",
                      lower=results.params['x']*0.5,
                      upper=results.params['x']*1.5)

    inter = pm.Uniform("inter",
                       lower=results.params['Intercept']*0.5,
                       upper=results.params['Intercept']*1.5)

    sigma = pm.Uniform("sigma",
                       lower=results.resid.std()*0.5,\
                       upper=results.resid.std()*1.5)

    # Linear regression line
    mean = inter + grad*data['x']

    # Describe the distribution of our conditional output
    y = pm.Normal('y', mu = mean, sd = sigma, observed = data['y']) # Run the sampling using pymc3 for 100 samples
    trace_100 = pm.sample(100,return_inferencedata=True)

这段代码将运行 MCMC 采样器来计算每个参数的后验概率。同样,如果您有兴趣了解 MCMC 是如何工作的,请参考背景部分的链接。

我们现在可以绘制每个参数的后验分布:

with model_100:
    az.plot_posterior(trace_100,
                      var_names=['grad', 'inter', 'sigma'],
                      textsize=18,
                      point_estimate='mean',
                      rope_color='black')

作者用 Python 生成的图。

这些后验分布的平均值与 OLS 估计值相同,但是这不是参数可以采用的唯一值。如你所见,有很多值。这是贝叶斯线性回归背后的要点。

HDI 代表 高密度区间 ,描述了我们在参数估计中的确定性。如果你想了解更多关于人类发展指数的信息,请查看我在T21【贝叶斯可信区间 上的博文:

这个模拟只使用了我们数据中的 100 个样本。与贝叶斯方法一样,我们随着更多的数据变得更加确定。

PyMC3: 10,000 个样本

让我们再次运行该过程,但现在使用 10,000 个样本:

# Start our model
with pm.Model() as model_10_100: # Define the priors on each parameter:
    grad = pm.Uniform("grad",
                      lower=results.params['x']*0.5,
                      upper=results.params['x']*1.5)

    inter = pm.Uniform("inter",
                       lower=results.params['Intercept']*0.5,
                       upper=results.params['Intercept']*1.5)

    sigma = pm.Uniform("sigma",
                       lower=results.resid.std()*0.5,
                       upper=results.resid.std()*1.5)

    # Linear regression line
    mean = inter + grad*data['x']

    # Describe the distribution of our conditional output
    y = pm.Normal('y', mu = mean, sd = sigma, observed = data['y']) # Run the sampling using pymc3 for 10,000 samples
    trace_10_000 = pm.sample(10_000,return_inferencedata=True)

让我们再次查看参数的后验分布:

with model_10_100:
    az.plot_posterior(trace_10_000,
                      var_names=['grad', 'inter', 'sigma'],
                      textsize=18,
                      point_estimate='mean',
                      rope_color='black')

作者用 Python 生成的图。

平均预测没有改变,但是随着我们更加确定参数的分布,总体上分布变得更加平滑和紧密。

密码

要查看我在这篇文章中使用的全部代码,请点击这里查看 GitHub 上的笔记本:

https://github.com/egorhowell/Medium-Articles/blob/main/Statistics/pymc3_tutorial.ipynb

结论

在本文中,我们浏览了贝叶斯统计的主要原则,并解释了它如何采取不同于频率统计的线性回归方法。然后我们看了一个基本的例子,如何使用 PyMC3 包进行贝叶斯回归。

和我联系!

(所有表情符号由 OpenMoji 设计——开源表情符号和图标项目。许可证: CC BY-SA 4.0****

日常使用的贝叶斯技巧

原文:https://towardsdatascience.com/bayesian-tricks-for-everyday-use-2b51da45f3ec

学习一些有用的概率技巧,在不完整信息的海洋中安全航行

有时候我们希望我们知道一些我们不知道的事情。不幸的是,很多时候,我们没有时间甚至没有办法去学习我们需要的东西。然而,决策和评估只需要利用可支配的知识。虽然对我们许多人来说,在不完整信息的迷雾中航行似乎很可怕,但那些了解不确定性本质的人可以利用这一点为自己服务。继续读下去,看看如何在一些技巧的帮助下,从有限的信息中获取最多的知识。

走向贝叶斯

为了在不确定的海洋中安全航行,我们需要一个指南针。而不是任何指南针。将无害地引导我们的指南针是贝叶斯定理。这个简单的公式允许我们计算我们的假设基于我们已经看到的数据的可能性有多大( P(H|D) ,或者后验概率)。

假设(H)和数据(D)世界中的贝叶斯公式。

我们只需要知道假设我们的假设为真,观察到我们看到的数据的可能性有多大( P(D|H) ,或者可能性)。我们还需要一个假设,关于我们的假设本身有多大的可能性,抛开任何数据( P(H) ,或者先验概率)。然后,我们只需将右边分子中的两个数字相乘。由于整个事情是一个概率,它需要为所有可能的假设总结为一。因此,我们可以简单地把分母当作一个比例因子,确保总和为 1,瞧,我们已经得到了贝叶斯!

如果您对贝叶斯定理还不太熟悉,请随意阅读我关于贝叶斯思维的文章,这篇文章对它进行了更详细的解释,并提供了许多实际例子:

当我们在本文的剩余部分学习各种贝叶斯技巧时,我将假设您直观地掌握了先验和似然性的概念,以及我们如何将两者相乘并缩放以得到后验概率。阅读上面的文章将足以让你开始。

让我们来看看如何利用这种贝叶斯机制来获得敏感问题的真实答案,并根据训练中泄露的信息来评估你的足球队的状态。

获得敏感问题的真实答案

社会和经济研究者有时会问一些困难的问题。你对你的伴侣不忠吗?或者在你的税单上?你每天都吸毒吗?你可以很容易地想象大多数人会如何回答这类问题。

研究人员很难得到诚实的答案,这种现象被称为社会期望偏差。当被问及敏感问题时,回答者会高估积极行为,低估消极行为,这样提问者会更好地看待他们。然而,获得这些问题的真实答案可能对引导社会经济政策朝着理想的方向发展至关重要。一个人该怎么做呢?

信不信由你,一个简单的贝叶斯技巧解决了这个问题!只是告诉人们偷偷抛硬币。如果结果是正面的,无论你问他们什么,他们都应该说是。如果是反面,他们应该诚实地回答问题。这样人家才愿意老老实实回答。从他们的角度来看,承认毒品交易并不能给你任何关于他们的信息,因为他们可能只是以摇头为由说是。他们将是正确的,因为你无法知道这个特定的人是一个经销商还是一个头脑清醒的人。但是问足够多的人,贝叶斯概率的魔力会让你估计他们中有多少人卖毒品。

让我们在实践中看到它。假设我们想知道偷税漏税的人口比例是多少。我们询问了 1000 名有代表性的人,他们是否使用了上述的硬币戏法来作弊。我们有 652 票赞成,348 票反对。

是时候启动我们的贝叶斯机器了。首先,我们需要一个先验。在看到任何数据之前,作弊的百分比可能是多少?让我们对此不可知论,并采用统一的先验。也就是说,我们说从 0%(没有人作弊)到 100%(每个人都作弊)的每一个可能的数字都是同样可能的。

我们会边走边编码。为了表示我们的先验,我们将使用来自经验分布图 Python 包的概率质量函数(PMF)。这是一种字典,我们用它来给从 0 到 1 的每一个可能的概率赋予一个相等的值。

>>> prior
0.00    1
0.01    1
0.02    1
       ..
0.98    1
0.99    1
1.00    1

接下来,我们需要计算可能性。我们需要对一个是和一个否,以及每个之前的值都这样做。以 0.20 的先验为例(20%的人出轨)。得到肯定回答的可能性有多大?是0.5 + (0.2 / 2) = 0.6。为什么?嗯,0.5 来自于有一半的人会摇头,回答是。剩下的0.2 / 2反映了这样一个事实:在 20%的作弊者中,有一半已经被计算在内了(那些抛了头的人),但我们仍然需要添加另一半抛了尾的作弊者。

答案是否定的可能性有多大?是(1 — 0.2) / 2 = 0.4。因为唯一可能的答案是“是”和“否”,我们可以简单地从 1 中减去 0.6 的可能性,得到 0.4,但是为了更深入的理解,让我们花一点时间在公式上。假设有 20%的人作弊,我们有 80%的人不作弊。其中,只有一半的人会回答不,而另一半会摇头说是。

现在让我们将这种计算扩展到所有先前的值。

likelihood["Y"]
array([0.5  , 0.505, 0.51 , 0.515, 0.52 , 0.525, 0.53 , 0.535, 0.54,
       0.545, 0.55 , 0.555, 0.56 , 0.565, 0.57 , 0.575, 0.58, 0.585,
       0.59 , 0.595, 0.6  , 0.605, 0.61 , 0.615, 0.62 , 0.625, 0.63,
       0.635, 0.64 , 0.645, 0.65 , 0.655, 0.66 , 0.665, 0.67, 0.675,
       0.68 , 0.685, 0.69 , 0.695, 0.7  , 0.705, 0.71 , 0.715, 0.72,
       0.725, 0.73 , 0.735, 0.74 , 0.745, 0.75 , 0.755, 0.76, 0.765,
       0.77 , 0.775, 0.78 , 0.785, 0.79 , 0.795, 0.8  , 0.805, 0.81,
       0.815, 0.82 , 0.825, 0.83 , 0.835, 0.84 , 0.845, 0.85, 0.855,
       0.86 , 0.865, 0.87 , 0.875, 0.88 , 0.885, 0.89 , 0.895, 0.9,
       0.905, 0.91 , 0.915, 0.92 , 0.925, 0.93 , 0.935, 0.94, 0.945,
       0.95 , 0.955, 0.96 , 0.965, 0.97 , 0.975, 0.98 , 0.985, 0.99,
       0.995, 1\.   ])

在上面的打印结果中,我们可以看到不同的前科得到肯定回答的可能性。第一个可能性 0.5 对应于先验或 0。如果没有人作弊,得到肯定答案的几率就是 50%的抛头几率。1 的最后可能性对应于 1 的先验。如果每个人都作弊,所有的答案都是肯定的——一半是诚实的承认,另一半是硬币正面朝上。正如我们刚刚看到的,第二十一个值 0.6 对应于 0.2 的先验值。

现在我们有了先验、可能性和数据(回想一下,我们有 652 个赞成和 348 个反对),我们可以很容易地使用贝叶斯公式计算后验概率。为了使计算变得容易,我们将从先验开始,并逐点用似然数据更新它(即:逐个回答)。最后,我们将标准化结果,以获得适当的概率分布。normalize()方法是empiciraldist包中的一个有用的工具。它所做的只是将分布中的每个值除以所有值的总和,以确保它们加起来等于 1。

骗税的后验概率。图片由作者提供。

所以我们有了它。max_prob()方法返回 0.3,后验分布的密度图没有留下任何疑问:偷税者在人口中的百分比在 20%到 40%之间,最有可能在 30%左右。

对于一个非常敏感的问题,这是一个非常精确的回答!如果我们简单地问这个问题,作弊的人不会承认,我们会得到有偏见的结果。我们刚刚是不是免费摆脱了这种偏见?哦,不,天下没有免费的午餐!我们以假设的形式付出了代价!

我们假设了什么?事实上,只有一件事:不管是骗子还是非骗子,抛正面(和反面)的概率都是 50%。或者换句话说:硬币是公平的,所有的人都以同样的方式扔硬币。在我看来这是个合理的假设。

最后,注意我们的后验分布的宽度取决于我们的样本量。我们问了 1000 个人。如果我们面试的人更少,曲线会更宽更低,留下更多的不确定性。只有 100 名受访者(65 名赞成,35 名反对),我们将得到这条橙色曲线(蓝色曲线与之前的 1000 名受访者相同)。

基于 1000 和 100 名受访者的逃税后验概率。图片由作者提供。

点球大战

下一个例子的灵感来自艾伦·唐尼的《思考贝叶斯》中的一个相似的例子。虽然他写的是通过用外星人 Blaster 9000 射击敌人的飞船来防止外星人入侵,但我已经把他的例子翻译成了一个更贴近我内心的领域:足球(当我说足球时,我指的是英国人发明的足球,,在这种足球中,你实际上是用脚而不是用手——无意冒犯我的美国朋友😉).

一场大赛即将来临。比如说,冠军联赛决赛。由于两个参赛队都是顶级的,所以认为两队都无法扭转局势,所以这场比赛可能会以平局告终是合理的。在那种情况下,将在点球决出胜负。这意味着每队五名球员轮流罚对手点球。得分多的队获胜。

难怪在如此重要的比赛之前,球队倾向于强调练习点球。在赛前新闻发布会上,你的球队的教练宣布,他们在一次训练中模仿了两次点球大战,两次都进了相同数量的球。他说,这证明了球员们投篮的一致性。这对作为他们粉丝的你来说是好消息还是坏消息?

教练的话可能意味着他们在两次测试中得了五分,或者他们一分也没得。很可能,他没有给出确切的数字,以便不通过宣布他们得分而给球员施加压力,或者不通过说他们只得分一次或两次来增强对手的信心。幸运的是,贝叶斯思维将带领我们找到答案!

让我们将这个问题形式化如下:假设在两次五次射门试验中,得分数量相同,这支球队罚球得分的概率是多少?

我们需要从点球得分概率的先验开始。对于一个足球迷来说,平均四分之三的点球被转化为进球已经不是什么新闻了。这表明有大约 75%的先验。然而,在赛后的点球大战中,除了顶级点球手之外的球员可以射门,这将得分概率降低到 70%左右。也就是说,有些球员不能每隔一个点球就进球,而其他人几乎是完美的得分手(有人说是罗伯特·莱万多夫斯基吗?).基于所有这些,让我们采用 0.5 到 0.9 之间的无信息的、统一的先验。这意味着我们相信点球得分的概率在 50%到 90%之间。

>>> prior
0.500    1
0.504    1
        ..
0.896    1
0.900    1

接下来是可能性。为了计算它,注意到我们正在处理估计一个比例(得分概率)的任务是很方便的。这就是二项分布发挥作用的地方。

二项式概率质量函数,或称 PMF,可以回答这个问题:如果罚中一个球的概率是 75%,那么在 5 个点球中准确命中 3 个的几率是多少?答案是binom.pmf(3, 5, 0.75)26%。

我们可以使用这个函数来计算所有可能结果的可能性(球队得分为零,五分之一,两个,三个,四个,或所有五个惩罚),所有之前的得分概率(从 0.5 到 0.9)。请注意,我们对结果进行了平方处理,以说明两次试验中的每一次得分相同。然后,我们将它们相加,因为总的可能性是零、一、二、三、四和五个进球得分的概率之和(这些结果中的任何一个都符合教练的话)。一旦我们有了可能性,我们只需将它与先验相乘,然后像往常一样进行归一化,就可以得到后验概率。

现在我们有了!我们队进点球的概率最有可能是 90%左右,极不可能是 50%。这是个好消息!

毫无疑问,使用贝叶斯机器来得到准确的答案是很酷的,但这种结果是意料之中的。想想看:如果得分概率是极端的,比接近 50%时,在每次试验中得分相同数量的目标更有可能。一个近乎完美的球员团队通常会得到 5/5 的分数。一个从来没有踢过足球的队伍经常会得 0/5 分。一个普通的团队在试验中的结果会有更多的变化,因此不太可能重复相同的结果两次。

感谢阅读!如果您对如何更严格地将贝叶斯思维应用于统计数据分析感兴趣,请查看我关于该主题的介绍性文章:

如果你喜欢这篇文章,为什么不在我的新文章上 订阅电子邮件更新 ?通过 成为媒介会员 ,你可以支持我的写作,并无限制地访问其他作者和我自己的所有故事。

需要咨询?你可以问我任何事情,也可以在这里 预定我 1:1

你也可以试试我的其他文章。不能选择?从这些中选择一个:

</6-useful-probability-distributions-with-applications-to-data-science-problems-2c0bee7cef28>

Python 中的贝叶斯更新

原文:https://towardsdatascience.com/bayesian-updating-in-python-8bbd0e7e30cc

简单介绍如何使用 Numpy 在 Python 中执行贝叶斯更新。

特里·维里斯迪斯在 Unsplash 上的照片

介绍

在我以前的一篇文章中,我讨论了如何使用贝叶斯更新来更新你的信念。你可以在这里查看帖子:

在那篇文章中,我们有三个不同数字范围的骰子。我们随机拿起一个骰子,用那个骰子连续掷了两次。从这些信息中,我们计算出我们最有可能捡起哪个骰子的概率(后验概率)。

这个过程都是手工完成的,因为我们幸运地只有两次掷骰子的结果和三个骰子。然而,随着更多的骰子和更多的滚动,这个问题很快就变得冗长而乏味,无法用笔和纸来解决。

在本文中,我们将用 Python 实现上述问题的贝叶斯更新,以加快计算后验概率的过程。

贝叶斯定理概述

让我们快速回顾一下贝叶斯定理及其主要特征:

作者在 LaTeX 中生成的方程。

  • P(H): 假设的概率,这是https://en.wikipedia.org/wiki/Prior_probability****。这是在我们看到我们的数据之前,我们假设的可能性有多大, D
  • P(D | H):可能性 给定我们的假设,我们的数据正确的概率。
  • P(H|D): 从我们给定的数据来看,我们的假设为真的概率。这是后路
  • P(D): 观测数据的概率。这是 归一化常数 这是可能性和先验的乘积之和:

作者在 LaTeX 中生成的方程。

关于贝叶斯定理的完整推导和直觉,请查看我以前的帖子:

**https://pub.towardsai.net/conditional-probability-and-bayes-theorem-simply-explained-788a6361f333

问题是

假设有一组不同数字范围的骰子,1-2,1-3,1-4 等等。我们随机选择一个骰子,然后掷几次。使用我们从掷骰结果中得到的数据,我们可以更新我们的信念来估计我们最有可能选择哪个骰子。

代码

让我们从导入我们的包开始:

import numpy as np
import matplotlib.pyplot as plt

骰子

生成我们的骰子,其中数字代表该骰子的最高值。例如,9 表示骰子的数字在 1-9 之间:

dice = np.arange(3,13)
diceOutput: array([ 3,  4,  5,  6,  7,  8,  9, 10, 11, 12])

在先的;在前的

由于每个骰子被选中的可能性相同,我们有一个https://en.wikipedia.org/wiki/Prior_probability#Uninformative_priors****的统一先验。因此,每个骰子具有相等的先验概率:

prior = [1/len(dice) for _ in np.arange(len(dice))]
priorOutput: [0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1]

因为我们有 10 个骰子,每个骰子有 10%的概率被选中。

可能性和掷骰 1

我们选择一个骰子,掷 1。掷出 1 的可能性如下:

roll = 1
likelihood1 = [1/i if i >= roll else 0 for i in dice]
likelihood1Output: [0.3333333333333333,
 0.25,
 0.2,
 0.16666666666666666,
 0.14285714285714285,
 0.125,
 0.1111111111111111,
 0.1,
 0.09090909090909091,
 0.08333333333333333

请注意,1–3 的骰子可能性最大。这是有意义的,因为它具有最小的数字范围。

计算后验概率

将先验和似然性相乘,我们可以找到后验并将其归一化:

posterior = np.array(likelihood1) * np.array(prior)
list(posterior/sum(posterior))Ouput: [0.20791611349879613,
 0.15593708512409712,
 0.1247496680992777,
 0.10395805674939806,
 0.08910690578519834,
 0.07796854256204856,
 0.06930537116626538,
 0.06237483404963885,
 0.05670439459058077,
 0.05197902837469903]

绘制后路图:

plt.figure(figsize=(13,7))
plt.xlabel('Dice', fontsize=20)
plt.ylabel('Probability', fontsize=20)
plt.plot(dice, list(posterior/sum(posterior)))
plt.xticks(fontsize=20)
plt.yticks(fontsize=20)
plt.show()

作者用 Python 生成的图形。

找到概率最高的骰子,这就是所谓的 最大后验概率 ( 图) :

dice[np.argmax(posterior)]Output: 3

因此,最有可能的骰子是范围从 1 到 3 的骰子!这是很明显的,因为它有最高的可能性,我们也有一个统一的先验。

可能性和滚动 2

我们再次掷出同一个骰子,得到一个 5。这种结果的可能性是:

roll = 5
likelihood2 = [1/i if i >= roll else 0 for i in dice]
likelihood2Output: [0,
 0,
 0.2,
 0.16666666666666666,
 0.14285714285714285,
 0.125,
 0.1111111111111111,
 0.1,
 0.09090909090909091,
 0.08333333333333333]

注意前两个现在是 0。这是因为不可能用范围为 1-3 和 1-4 的骰子掷出 5。

更新后验

使用我们的旧后验概率作为新的先验,以及滚动 5 的可能性,我们更新我们的后验概率为:

posterior = posterior * np.array(likelihood2)
list(posterior/sum(posterior))Output: [0.0,
 0.0,
 0.2829544144262495,
 0.1964961211293399,
 0.14436449715624972,
 0.1105290681352537,
 0.08733160939081774,
 0.07073860360656238,
 0.05846165587319205,
 0.049124030282334974]

绘制后路图:

plt.figure(figsize=(13,7))
plt.xlabel('Dice', fontsize=20)
plt.ylabel('Probability', fontsize=20)
plt.plot(dice, list(posterior/sum(posterior)))
plt.xticks(fontsize=20)
plt.yticks(fontsize=20)
plt.show()

作者用 Python 生成的图形。

概率最高的骰子:

dice[np.argmax(posterior)]Output: 5

根据我们的数据,范围为 1-5 的骰子是最有可能的!

范围为 1-3 和 1-4 的骰子是 0,因为它们不可能输出 5,因此我们知道我们肯定没有选择它们!

类函数

为了方便起见,让我们将所有这些代码打包成一个函数:

def bayesian_dice_updating(data, dice):
    """ Compute the posterior distribution for given dice and data.

    :param data: The numbers that have been rolled from the dice
    :type data: list, np.array

    :param dice: The range of dices where the number represents 
                 the maximum value that die can take.
    :type dice: list, np.array

    :returns: Posterior distribution of the dice given the data
    :rtype: list

    """

    prior = [1/len(dice) for _ in np.arange(len(dice))]

    posterior = prior

    for roll in data:
        likelihood = [1/i if i >= roll else 0 for i in dice]
        posterior = np.array(likelihood) * np.array(posterior)

    return list(posterior/sum(posterior))

我们来试试吧!

生成一些骰子和一些数据(掷骰结果):

dice = np.arange(1,51)
data = [4,6,9]

绘制结果图:

plt.figure(figsize=(13,7))
plt.xlabel('Dice', fontsize=20)
plt.ylabel('Probability', fontsize=20)
plt.plot(dice, bayesian_dice_updating(data, dice))
plt.xticks(fontsize=20)
plt.yticks(fontsize=20)
plt.show()

作者用 Python 生成的图形。

dice[np.argmax(bayesian_dice_updating(data, dice))]Output: 9

功能运行良好!

完整代码可从我的 GitHub 获得,网址是:

**https://github.com/egorhowell/Medium-Articles/blob/main/Statistics/Bayesian_Updating.ipynb

结论

在本文中,我们回顾了贝叶斯定理,并展示了如何用 Python 编写贝叶斯更新,以使计算后验概率变得简单。

和我联系!

(所有表情符号由 OpenMoji 设计——开源表情符号和图标项目。许可证: CC BY-SA 4.0****

贝叶斯更新简单解释

原文:https://towardsdatascience.com/bayesian-updating-simply-explained-c2ed3e563588

用贝叶斯定理更新信念的直观解释

迪伦·克里夫顿的照片在 Unsplash

介绍

在我以前的文章中,我们从条件概率中推导出了贝叶斯定理。如果您不熟悉贝叶斯定理,我强烈建议您在阅读本文之前先阅读那篇文章:

https://pub.towardsai.net/conditional-probability-and-bayes-theorem-simply-explained-788a6361f333

在本文中,我们将使用贝叶斯定理来更新我们的信念,并展示如何随着更多的数据,我们变得更加确定我们的假设。

贝叶斯定理

我们可以把贝叶斯定理写成如下:

作者在 LaTeX 中生成的方程。

作者在 LaTeX 中生成的方程。

贝叶斯更新

当新的证据出现时,我们可以用贝叶斯定理来更新我们的假设。

例如,给定一些数据其中包含了一个 d_1 数据点,那么我们的后验就是:**

作者在 LaTeX 中生成的方程。

假设我们现在获得了另一个数据点【D2】,因此我们有更多的证据来评估和 更新 我们的信念(后验)。然而,我们的* 先验现在变成了我们的旧后验 因为这代表了我们的新的先验信念我们的假设:*****

作者在 LaTeX 中生成的方程。

就更新而言,我们说后验与似然和先验的乘积成比例:

作者在 LaTeX 中生成的方程。

这种更新可能看起来有些武断,但是现在让我们通过一个例子来使它更加具体。

我们通常省略分母 P(D ),因为它只是一个归一化常数,使概率总和为 1。Stat Exchange 有一个很好的帖子很好地解释了这一点。

例子

假设我有三个不同的骰子,有三个不同的数字范围:

  • 骰子 1:1–4
  • 骰子 2:1–6
  • 骰子 3:1–8

我们随机选择一个骰子,用给定的骰子做三次后续的掷骰子。使用这些掷骰子(数据),我们可以计算在到达角色(后)后,我们选择骰子 1、2 或 3 的可能性。

第一卷

在第一次掷骰子时,我们得到数字 4 。我们选择骰子 1、2 或 3 的概率是多少?

我们可以使用贝叶斯定理计算如下:

作者在 LaTeX 中生成的方程。

我们使用了以下值:

  • 之前, P(骰子) ,简单来说就是 0.33 因为每个骰子被选中的几率相等。
  • 可能性, P(掷出 4 |骰子) ,就是每个骰子掷出一个 4 的概率。
  • 数据的概率(归一化值), P(第 4 卷) ,就是似然性和先验乘积的之和。****

所以第一次掷骰子后,骰子 1 是最有可能的。这是有意义的,因为它只有 4 个结果,因此 1-4 之间的任何一次掷骰都是最有可能的。

第二卷

使用相同的骰子,我们现在掷第二次,得到一个 2 。然而,我们有了新的先验,这是上面我们掷出 4 的计算后验。

因此,现在的概率是:

作者在 LaTeX 中生成的方程。

有了这个新信息,骰子 1 越来越有可能是我们捡到的那个。

第三卷

我们用我们选择的骰子掷第三次,得到一个 5 。使用我们以前的后验概率作为我们新的先验概率,现在的概率是:

作者在 LaTeX 中生成的方程。

它是骰子 1 的概率现在是 0,因为不可能用骰子 1 掷出 5。因此,给定这三个数据点(掷骰子),骰子 2 是我们最有可能选中的一个!

具有最高后验概率的值称为 【最大后验概率】 。这类似于 最大似然 但是对于贝叶斯统计来说,是后验分布的众数。

骰子的三个后验值形成了一个后验分布,尽管非常小!****

结论

在这篇文章中,我们展示了当你面对新数据时,如何使用贝叶斯定理来更新你的信念。这种统计方式与我们人类的思维方式非常相似,因为新信息可以强化或改变我们的信念。

和我联系!

(所有表情符号都是由 OpenMoji 设计的——开源的表情符号和图标项目。许可证: CC BY-SA 4.0

额外的东西!

我的父母住在东苏塞克斯,上周末我去拜访了他们。在旅途中,我们在一个名叫滕布里奇·韦尔斯的小镇吃了晚饭。你知道谁住在那里吗?托马斯·贝叶斯!

如果您在该地区,这是非常值得一试!

作者照片。

贝叶斯与频率主义推理

原文:https://towardsdatascience.com/bayesian-vs-frequentist-inference-a2cab8087bda

你是贝叶斯主义者还是频率主义者?

使用稳定扩散生成的图像

关于概率学派,有两种主要的方法:贝叶斯方法和频率主义方法。这两种方法都有各自的优点和缺点,它们经常在不同的情况下用于帮助确定事件的概率。

那么,它们的区别在哪里呢?一个比另一个好吗?这是一个错误的问题;贝叶斯思维是基于概率代表对事件发生的信任程度的想法。当事件发生的可能性存在不确定性时,或者当可以获得影响事件发生概率的新信息时,通常使用这种方法。

另一方面,频率主义者的方法是基于这样的想法,即事件发生的概率等于事件发生的长期频率。当通过收集数据并在大量试验中观察事件发生的频率来确定事件的概率时,通常使用这种方法。

Learning Rate 是为那些对 AI 和 MLOps 世界好奇的人准备的时事通讯。你会在每个月的第一个星期六收到我关于最新人工智能新闻和文章的更新和想法。在这里订阅!

直观的例子

为了更好地理解差异,让我们看一个简单的例子。想象一个盒子,里面有一堆弹珠,你想知道盒子里的弹珠是什么颜色的。在贝叶斯方法中,你可能从猜测盒子里大部分是红色弹珠开始,因为你已经在类似的容器里看到许多红色弹珠。当你把手伸进盒子拿出弹珠时,你可以根据你看到的颜色更新你的猜测。所以,如果你拿出一串蓝色的弹珠,你可能会开始认为盒子里主要是蓝色的弹珠,你可以相应地调整你的猜测。

在频率主义者的方法中,你不会去猜测盒子里弹珠的颜色。取而代之的是,你只要把手伸进去,开始拉出弹珠,数一数你看到的红色、蓝色和其他颜色的弹珠的数量。在你抽出大量的弹珠后,你可以通过用你抽出的弹珠总数除以那个颜色的弹珠的数量来计算看到特定颜色的概率。这个概率不是猜测,而是决定盒子里弹珠颜色的随机过程的一个属性。

事物的利与弊

贝叶斯方法的一个优点是,它允许我们将先前的信息和信念结合到我们的分析中,并在新的证据出现时更新它们。这在数据稀缺或难以收集的情况下尤其有用。

相比之下,频率主义者的方法只考虑手边的数据,不考虑任何先验信息或信念。这可以使频率主义者的方法更客观,但也可以使它更不灵活,更不能适应新的信息。

贝叶斯方法的另一个优点是它为量化不确定性提供了一个自然的框架。因为贝叶斯概率是个人信念的一种度量,所以它们可以被直接解释为关于与特定假设或命题相关的不确定性程度的陈述。相比之下,frequentist 方法没有提供一种自然的方法来量化不确定性,并且需要额外的工具和假设来对其进行陈述。

稳定扩散生成的图像

贝叶斯方法的缺点是计算量大,特别是对于有许多变量的复杂问题。将贝叶斯方法应用于大型或实时数据集可能会很困难。相比之下,frequentist 方法的计算效率通常更高,这使得它非常适合于关注速度的应用程序。

总的来说,贝叶斯方法和频率主义方法都有它们的优点和缺点,选择哪种方法取决于手头的问题和分析的目标。

量化不确定性

但是为什么贝叶斯方法提供了一个量化不确定性的框架?我们来看一个例子。想象一下,你正试图估算明天下雨的概率。在贝叶斯方法中,你首先根据你的经验、你用谷歌搜索得到的天气预报和其他相关信息,给这个事件分配一个先验概率。例如,你可能认为明天有 60%的可能性会下雨,因为你在相似的日子里见过下雨。

稳定扩散生成的图像

现在,假设你观察到今天天空多云。你可以用这个新信息来更新你对明天下雨可能性的看法。在贝叶斯方法中,你将使用贝叶斯定理,它告诉我们如何根据新的证据修正我们的概率。将贝叶斯定理应用于这种情况,你可能会发现明天下雨的概率现在是 80%,因为今天多云的天空更倾向于明天有阵雨而不是没有雨。

在这个例子中,明天下雨的概率是你对这一事件的不确定程度的度量。因为贝叶斯概率是个人信念的一种度量,所以可以直接解释为关于不确定性的陈述:你相信明天有 80%的概率下雨,这意味着你对是否会下雨相当不确定。一般来说,事件发生的概率越高,该事件的不确定性就越小,反之亦然。如果您确信明天会下雨,您可能会将此事件的概率指定为 1.0。相比之下,如果你完全不确定是否会下雨,你可能会把概率定为 0.5。最终,与事件相关的不确定性程度取决于你自己,取决于你自己的信念和你所拥有的证据。

相比之下,频率主义者的方法并没有提供一种自然的方式来量化这种不确定性,因为频率主义者的概率并不是一种个人信念的度量。相反,它们是生成数据的基本随机过程的属性。

结论

贝叶斯和频率主义思维是两种不同的统计推断方法。贝叶斯思维基于主观概率的思想,其中事件的概率基于个人对事件的信念或知识。相比之下,频率主义概率是客观的,并且仅仅基于事件在大量试验中发生的频率。

贝叶斯思维的一个关键优势是,它允许将先前的知识或信念结合到分析中,这有助于做出更准确的预测或推断。然而,它在计算上可能比 frequentist 方法更复杂,并且受个人偏见的影响。

频率主义思维比贝叶斯方法更直接,更容易实现,特别是对于大型数据集。然而,它不允许结合先前的知识或信念,也不提供讨论不确定性的自然框架。

关于作者

我叫迪米特里斯·波罗普洛斯,我是一名为阿里克托工作的机器学习工程师。我曾为欧洲委员会、欧盟统计局、国际货币基金组织、欧洲央行、经合组织和宜家等主要客户设计和实施过人工智能和软件解决方案。

如果你有兴趣阅读更多关于机器学习、深度学习、数据科学和数据运算的帖子,请关注我的 MediumLinkedIn 或 Twitter 上的 @james2pl

所表达的观点仅代表我个人,并不代表我的雇主的观点或意见。

在对分类数据类型使用 Pandas Groupby 时要小心

原文:https://towardsdatascience.com/be-careful-when-using-pandas-groupby-with-categorical-data-type-a1d31f66b162

为了避免意外的结果

Unsplash 上由 Muhammad Daudy 拍摄的照片

在统计学中,分类变量是一个变量,它可以取有限的、通常是固定数量的可能值中的一个。Pandas 有一个专用于分类变量的数据类型,即 category。

在某些情况下,使用 category 数据类型非常有用且高效。例如,如果您的字符串或对象列只包含几个不同的值,将其转换为类别数据类型将节省大量内存。

为了比较内存使用情况,让我们首先创建一个 Pandas 系列,它包含三百万行三种不同的字符串,数据类型为 string。

import pandas as pdnames = pd.Series(["John", "Jane", "James"] * 1000000, dtype="string")names.memory_usage()
**# output**
24000128

它占用了大约 2400 万字节的空间。让我们用 category 数据类型来试试。

names = pd.Series(["John", "Jane", "James"] * 1000000, dtype="category")names.memory_usage()
**# output**
3000260

内存使用量减少到 300 万,比字符串数据类型的内存使用量少 8 倍。

category 数据类型允许为一个列强制一组可能的值。如果试图赋一个不在指定类别中的值,将引发类型错误。因此,具有类别数据类型的列中的所有值要么在给定的类别中,要么缺少值(即 np.nan 或 None)。

回到我们对数据类型为 category 的列上的 groupby 函数的讨论,有一点您应该注意。

让我们创建一个包含两列的示例数据框架,其中一列是包含 3 个类别的类别数据类型。

df = pd.DataFrame({
    "col1": pd.Categorical(
        ["A", "A", "B", "A", "B"], 
        categories=["A","B","C"], 
        ordered=False
    ),
    "col2": [10, 14, 20, 25, 23]
})

df(作者图片)

列 col1 的数据类型是具有值 A、B 或 c 的类别。

df["col1"]
**# output**
0    A
1    A
2    B
3    A
4    B
Name: col1, dtype: category
Categories (3, object): ['A', 'B', 'C']

当我们对该列使用 groupby 函数时,尽管 DataFrame 的 col1 列中不包含带有 C 的行,但类别 C 仍会出现在结果中。

df.groupby("col1")["col2"].sum()
**# output**
col1
A    49
B    43
C     0
Name: col2, dtype: int64

我们可以通过将 observed 参数的值设置为 True 来改变这种行为,这将只返回在 DataFrame 中观察到的值。

df.groupby("col1", observed=True)["col2"].sum()
**# output**
col1
A    49
B    43
Name: col2, dtype: int64

棘手的部分

棘手的部分是当我们在数据类型为 category 的列中缺少值时。让我们在 category 列中添加一个缺少值的新行。

import numpy as npdf.loc[5,:] = [np.nan, 30]

df(作者图片)

默认情况下,groupby 函数不显示缺失值的聚合值。因此,如果我们按 col1 列对行进行分组,我们将不会在结果中看到 NaN 组。我们可以通过使用 dropna 参数并将其值设置为 False 来更改此设置。在其他数据类型中,此更改将在结果中包括 NaN 组。但是,它不适用于类别数据类型。

我们来做几个例子说清楚。

df.groupby("col1", dropna=False)["col2"].sum()
**# output**
col1
A    49.0
B    43.0
C     0.0
Name: col2, dtype: float64

即使我们使用观测参数,结果也是一样的。它将只移除未观察到的类别,但丢失的值不会显示在输出中。

df.groupby("col1", observed=True, dropna=False)["col2"].sum()
**# output**
col1
A    49.0
B    43.0
Name: col2, dtype: float64

这只是类别数据类型的问题,在新版本文档中有提及。如果数据类型是 string 或 object,dropna 参数将按预期工作。让我们通过将数据类型更改为 string 来进行确认。

df["col1"] = df["col1"].astype("string")
df.groupby("col1", dropna=False)["col2"].sum()
**# output**
col1
A       49.0
B       43.0
<NA>    30.0
Name: col2, dtype: float64

现在,我们在输出中将缺失的值视为一组。

这可能不是一个重要的问题,但绝对是我们需要记住的事情。我们经常会遇到原始数据中的缺失值,应该把它们考虑进去。否则,我们可能会得到意想不到的结果或不可靠的模型。

你可以成为 媒介会员 解锁我的全部写作权限,外加其余媒介。如果你已经是了,别忘了订阅如果你想在我发表新文章时收到电子邮件。

感谢您的阅读。如果您有任何反馈,请告诉我。

去样板代码!Python 中的主数据类

原文:https://towardsdatascience.com/be-gone-boilerplate-code-master-dataclasses-in-python-d3f302f9a7c4

熟悉一个非常有用的数据容器

图片作者。

您的旅程概述

  1. 设置舞台
  2. 什么是数据类?
  3. 创建数据类的实例
  4. 简单验证
  5. 数据类之间相等
  6. 数据类的排序
  7. 不可变数据类
  8. 包装

1 —搭建舞台

Python 有许多数据类型,可以作为其他数据类型的容器。最简单的例子是内置数据类型ListTupleDictionarySet。虽然这些数据类型在某些设置中工作得很好,但在许多设置中却不尽如人意。这对于数据科学家和数据工程师来说并不陌生:

  • 使用 NumPy 数组是因为列表很慢,而且不是为向量运算和线性代数而构建的。
  • 你使用熊猫数据框架是因为字典对于数据分析来说不够方便。

然而,在数据科学/工程领域之外,还有一些非常有用的数据容器。例子有命名元组数据类Pydantic 模型。这些数据容器在数据领域经常被忽略,因为它们不是绝对必要的。人们低估了他们对减少样板代码、获得数据验证和处理数据的帮助。用下面的木工比喻来思考这个问题🔨

可以用螺丝刀的背面敲入钉子。但是,如果有一把锤子躺在周围,等着被使用,你为什么要这样做呢?

可能在数据科学/数据工程中经常被忽略的更有用的数据结构之一是数据类。这是 Python 生态系统(Python 3.7 版及更高版本)的新成员。在这篇博文中,我将告诉你开始在你的项目中使用数据类所需要知道的一切。

你是视频人吗?我在 dataclasses 上制作了四个 YouTube 视频,内容与博客相同。如果你想检查一下,请便!

先决条件:因为数据类本质上是增强的 Python 类,所以你需要知道 Python 类的基础。如果您对诸如抽象封装多态之类的高级术语感到生疏,也不必感到难过。你不需要任何高级的东西👍

2-什么是数据类?

一个数据类是一个数据容器,它包含了电池。更确切地说,它是一个已经实现了一些很酷的特性的 Python 类。通过使用数据类,您将避免编写大量样板代码。Dataclasses 为您提供了一种灵活且可预测的方式来存储数据、比较数据和排序数据。

要开始使用 dataclasses,确保您安装了 Python 3.7 或更高版本。您不需要下载第三方库,因为数据类在标准库中。以下是模拟汽车的数据类的最小示例:

from dataclasses import dataclass@dataclass
class Car:
  """A dataclass that models a car."""
  brand: str
  year: int
  price: float
  used: bool

让我们慢慢浏览上面的代码片段:

  • 1 —从dataclasses模块导入dataclass装饰器。
  • 2 —将 dataclass 装饰器应用于一个名为Car的类。
  • 3 —为数据类应该包含的各种数据编写类似brand: str的属性。属性名将是brand,而str表示它应该是一个字符串。这是 Python 中类型提示的一个例子。如果你不熟悉,那就看看这篇博文

使用上面的代码,您已经表示了一辆具有四个属性brandyearpriceused的汽车😃

您创建的只是一个普通的 Python 类,除了dataclass装饰器增加了额外的功能。您是否注意到在类中不需要__init__方法?这是dataclass装饰器为您修复的事情之一。

3-创建数据类的实例

现在,您将继续使用上一节中的代码,并创建一些汽车实例。要制造两辆汽车,您只需提供必要的属性:

# Initiate a BMW car
bmw_car = Car(brand="bmw", year=2016, price=20000, used=False)#Initiate an Audi car
audi_car = Car(brand="audi", year=2018, price=18000, used=True)

让我们把这些车打印出来:

print(bmw_car)
print(audi_car)**Output:** Car(brand="bmw", year=2016, price=20000, used=False)
Car(brand="audi", year=2018, price=18000, used=True)

打印数据类时的输出是信息性的,无需在类中编写__repr__方法。这是由dataclass装饰器自动处理的🔥

要查看还自动实现了什么,您可以使用inspect模块:

import inspect# Inspect the Car class
print(inspect.getmembers(Car, inspect.isfunction))**Output:**
[('__eq__', <function __create_fn__.<locals>.__eq__ at 0x0000021CB9A23790>), ('__init__', <function __create_fn__.<locals>.__init__ at 0x0000021CB9A23670>), ('__repr__', <function __create_fn__.<locals>.__repr__ at 0x0000021CB9A135E0>)]

我知道这不是最美丽的景象😅

如果你仔细阅读,那么你可以看到一个__eq____init____repr__是在 dataclass 中自动实现的。稍后我将回到__eq__是如何实现的。

默认情况下,数据类是可变的。这意味着您可以进行以下更改:

# The Audi car becomes used
audi_car.used = True
print(audi_car.used)**Output:**
True

最后,你可以让一个数据类的一些属性拥有默认值。假设您希望used属性有一个默认值False。为此,您只需更改一行代码:

used: bool = False # Last line in the Car class

现在,如果你写

bmw_car = Car(brand="bmw", year=2016, price=20000)

您会自动获得以下内容:

print(bmw_car)**Output:** Car(brand="bmw", year=2016, price=20000, used=False)

穆罕默德·诺哈西在 Unsplash 上的照片

4-简单验证

人们很容易将数据类视为过于复杂的字典。为什么不用下面的方法简单地存储变量bmw_car呢?

bmw_car = {
  "brand": "bmw", 
  "year": 2016, 
  "price": 20000, 
  "used": False
}

虽然这也是可行的,但是数据类提供了值得考虑的额外特性。其中之一是初始化新实例时的基本验证。

为了演示这一点,我在我的工作目录中创建了一个名为cars的文件夹(不要担心这是哪里,我将只使用相对路径)。文件夹cars包含四个文件car1.jsoncar2.jsoncar3.jsoncar4.json。每个 JSON 文件都包含一行数据:

**car1.json** {
  "brand": "bmw", 
  "year": 2016, 
  "price": 20000
}**car2.json** {
  "brand": "audi", 
  "year": 2018, 
  "price": 25000, 
  "used": true
}**car3.json** {
  "brand": "toyota", 
  "year": 2020, 
  "price": 22000, 
  "used": false
}**car4.json** {
  "brand": "toyota",  
  "price": 22000, 
  "used": false
}

我想将这里给出的四辆汽车初始化为 dataclass 对象。仔细看上面的四个例子。有没有应该拒绝的?

导入 JSON 文件和启动Car实例可以通过下面的标准 Python 代码片段来完成:

import json# Loading and initiating the cars
cars = []
for i in range(1, 5):
  with open(f"cars/car{i}.json", 'r') as file:
    car_info = json.load(file)
    cars.append(Car(**car_info))
print(cars)**Output:** TypeError: __init__() missing 1 required positional argument: 'year'

你会立即得到反馈,有什么地方出错了😮

当然,当你查看car4.json时,就会发现year属性不见了。如果您使用基本的字典来建模汽车,那么您将需要大量枯燥的代码来确保提供没有默认值的属性。

通过使用第三方库 MyPy ,您还可以使用 dataclasses 中的类型提示来获得更好的数据验证。虽然这超出了这篇博文的范围,但是如果你感兴趣的话,可以看看 MyPy

5-数据类之间相等

dataclasses 的一个很酷的特性是它们已经实现了一个用于比较实例的__eq__方法。为了了解这是如何工作的,让我们考虑另一个数据类示例,其中您对图书进行建模:

from dataclasses import dataclass@dataclass
class Book:
  """A dataclass for representing books."""
  title: str
  author: str
  isbn: str
  pages: int = 0

到目前为止,一切顺利。现在举以下四个例子:

fluent_python = Book(
  title="Fluent Python", 
  author="Luciano Ramalho", 
  isbn="978-1-491-94600-8",
  pages=751
)fluent_python_identical = Book(
  title="Fluent Python", 
  author="Luciano Ramalho", 
  isbn="978-1-491-94600-8",
  pages=751
)fluent_python_missing_pages = Book(
  title="Fluent Python",
  author="Luciano Ramalho",
  isbn="978-1-491-94600-8"
)python_crash_course = Book(
  title="Python Crash Course", 
  author="Eric Matthes", 
  isbn="978-1-593-27928-8"
)

书籍fluent_pythonfluent_python_identical包含完全相同的数据。另一方面,书fluent_python_missing_pages是缺页的,所以页数被设置为默认值0。最后,这本书python_crash_course从根本上不同于其他所有的书。

下面显示了如果您尝试比较不同的实例会发生什么:

print(fluent_python == python_crash_course)**Output:** Falseprint(fluent_python == fluent_python_identical)**Output:** Trueprint(fluent_python == fluent_python_missing_pages)**Output:** False

最有趣的是,书fluent_pythonfluent_python_missing_pages并不被认为是平等的。

当且仅当两个 dataclasses 实例的所有属性都相等时,它们才被视为相等。

这与平时上课的方式形成了鲜明的对比。对于通常的类,除非你实现了你自己的__eq__方法,否则只有当两个实例引用同一个内存地址时,它们才被认为是相等的。这是一个非常严格的标准,在数据科学和数据工程中不是很有用。

6-数据类中的排序

照片由安德烈·泰森Unsplash 上拍摄

既然您已经看到了数据类的基础知识,那么是时候讨论数据类的排序了。默认情况下,数据类没有顺序。但是,您可以指定希望数据类按如下方式排序:

@dataclass(order=True)
class RGBColor:
  """A class for keeping track of a color."""
  red: int
  green: int
  blue: int

注意,我在 dataclass 装饰器中指定了order=True。您现在得到以下排序:

almost_white_color = RGBColor(red=254, green=255, blue=255)
red_color = RGBColor(red=255, green=0, blue=0)print(almost_white_color > red_color)**Output:** False

这是怎么回事?😟

如果除了order=True之外没有指定任何东西,那么默认的排序将按照字典的方式来比较属性。这意味着首先将almost_white (254)的red值与red_color (255)的red值进行比较。因为 254 小于 255,所以得到输出False。如果出现平局,则比较下一个属性(绿色),依此类推。

默认顺序通常不是您想要的。这一次,它很大程度上依赖于属性的排序(红色现在比蓝色更适合确定大小)。对于红、绿、蓝三色同等重要的 RGB 颜色来说,这似乎不是一个好主意。

这就引出了一个问题:如何指定自己的排序?

以下示例为您的RGBColor数据类实现了自定义顺序:

from dataclasses import dataclass, field@dataclass(order=True)
class RGBColor:
  """A class for keeping track of a color."""
  sort_index: int = field(init=False, repr=False)
  red: int
  green: int
  blue: int def __post_init__(self):
    self.sort_index = self.red + self.green + self.blue

这里发生了一些事情。让我们把它们一个一个分解开来:

  • 除了dataclass之外,你还可以从dataclasses模块中导入field
  • 您创建了一个属性sort_index,该属性将用于对数据类的实例进行排序。我稍后会回到论点init=Falserepr=False的意思。
  • 您创建了一个名为__post_init__的特殊方法。该方法在__init__方法在引擎盖下执行后执行。然后指定sort_index属性应该是什么。之所以需要在__init__方法之后指定,是因为您需要能够访问三个属性redgreenblue。默认情况下,__post_init__方法中指定的变量将决定数据类的排序方式。

现在你有了以下比较:

almost_white_color = RGBColor(red=254, green=255, blue=255)
red_color = RGBColor(red=255, green=0, blue=0)print(almost_white_color > red_color)**Output:
True**

之所以认为almost_white_colorred_color要“高”,是因为您现在要比较这些值

254 + 255 + 255 > 255 + 0 + 0,

这明明是True。请注意,当您创建两种颜色almost_white_colorred_color时,您没有为sort_index传入一个值。这是因为你在创建sort_index时指定了init=False。第二个参数repr=False确保如果你打印出实例,那么你看不到属性sort_index:

print(almost_white_color)
print(red_color)**Output:**
RGBColor(red=254, green=255, blue=255)
RGBColor(red=255, green=0, blue=0)

因为你想为sort_index设置自定义属性,比如init=Falserepr=False,你需要使用dataclasses模块中的field函数。有关字段的更多信息,请查看关于数据类的 Python 文档。

7-不可变数据类

我想告诉你的最后一件事是如何使数据类不可变。我之前告诉过你数据类是可变的。但是,你可以改变这一点!以下示例说明了如何使 dataclass 不可变:

from dataclasses import dataclass@dataclass(frozen=True)
class Rectangle:
  """A dataclass representing a geometrical rectangle."""
  height: float
  width: float

如您所见,真正需要做的唯一事情是在 dataclass 装饰器中指定frozen=True。一旦这样做了,那么您的数据类实例将不会是可变的:

my_rect = Rectangle(height=1, width=2)
my_rect.height = 47**Output:** dataclasses.FrozenInstanceError: cannot assign to field 'height'

让数据类不可变有助于确保代码不会被意外修改😎

8—总结

照片由斯潘塞·伯根Unsplash 上拍摄

我已经向您展示了数据类在 Python 中是如何工作的。我希望你学到了一些新东西,并且能够在未来的项目中使用这些东西。

喜欢我写的?查看我的其他帖子,了解更多 Python 内容:

如果你对数据科学、编程或任何介于两者之间的东西感兴趣,那么请随意在 LinkedIn 上加我,并向✋问好

用 Neo4j 和 Dijkstra 算法寻找最优路径击败 Wikirace

原文:https://towardsdatascience.com/beating-wikirace-by-finding-the-optimal-path-with-neo4j-and-dijkstras-algorithm-1e11193c55bb

探索维基百科数据集并应用图形数据科学算法

维基百科插图。来自维基共享资源的编辑图片。 CC BY-SA 3.0

介绍

几周前,我通过看一些彩带玩这个游戏,偶然发现了一个有趣的游戏,叫做 Wikirace。Wikirace是任意数量的参与者之间的比赛,使用链接从一个维基百科页面到另一个页面。

通常,参与者从一个随机的维基百科页面开始,然后选择一个目标页面。例如,他们可以从维基百科的“瑞典”页面开始,目的页面是“德拉库拉”。目标是从源页面“瑞典”到达目的页面“德古拉”,只需使用维基百科网站上的超链接。第一个到达目的页面的人,或使用最少链接到达目的页面的人,赢得比赛。

虽然游戏本身很有趣,也很好玩,但是吸引我眼球的是最优解。仅使用维基百科中的超链接,从源页面到目标页面的最优路径是什么?在分析了这个问题之后,我发现带有最短路径算法的图形数据库是找到最佳路径的最佳解决方案。在这个项目中,我将使用 Neo4j 图形数据库。我将从图形数据库的快速介绍开始这篇文章。

Martin Grandjean 的图表数据库插图。 CC BY-SA 4.0

图形数据库

图形数据库(GDB)是一种使用图形结构进行语义查询的数据库,具有节点、边和属性来表示和存储数据。使用 GDB,我可以构建所有维基百科页面之间的关系。在 GDB 中,两个节点之间的关系可以表示如下:

(n:SourceNode)-[RELATION]->(m:TargetNode)

例如,在瑞典的维基百科页面上,如下所示,与其他超链接的关系可以被构造为:

(n:Sweden)-[HyperLink]->(m:Nordic country) 
(n:Sweden)-[HyperLink]->(m:Finland)

瑞典的维基百科页面截取文本。

这种关系在 GDB 中显示为节点和边:

建立关系的节点和边。作者图片

资料组

在我尝试解决这个问题之前,我需要维基百科中的所有关系。我将通过添加一个仅使用英文维基百科页面的约束来减少数据。斯坦福大学有一个名为“英语维基百科超链接网络”的数据集,作者是 Jure Leskovec。该数据集描述了 2013 年以来所有英文维基百科页面之间的关系。该文件夹包括两个文件。一辆 csv。包含所有节点 ID 及其名称的文件。另一个文件是 txt。描述不同维基百科页面之间关系的文件。以下是来自 relation.txt 文件的示例:

1 2435 35
2 354 87
3 44 91120
4 492 5
5 …

每行描述一个关系。第一个数字是确切关系的 ID。第二个数字是源页面,第三个数字是目标页面。例如,如果您位于维基百科第 2435 页,该页上有一个超链接指向维基百科第 35 页。我想这些数字是用来减少。txt 文件,而不是使用全名。该文件夹还包括一个文件,其中包含所有数字及其相应的维基百科页面名称。例如,ID 号为 35 的节点是“瑞典”的维基百科页面。

要将文件导入 Neo4j 图形数据库,我想使用 Neo4j 管理导入功能。当数据集“巨大”时,建议使用此导入功能,在这种情况下,数据集包括超过 400 万个节点(维基百科页面)和 1.01 亿条边(关系/超链接)。

图表来自斯坦福大学,作者 Jure Leskovec

为了将文件导入 Neo4j 数据库,我首先将文件从。发短信给。Python 中的 csv。我的最终计划是使用图表算法,利用这些关系找到从一个页面到另一个页面的最短路径。为了找到最短路径,算法需要知道节点之间的距离。在这种情况下,所有节点到其邻居的距离都相同。为了在数据集中包含距离,我在。距离等于 1 的 csv 文件。然后,我清理了数据集并添加了适当的标题,以利用 Neo4j 管理导入功能。下图显示了关系和节点的示例。csv 文件。

来自节点和关系的样本数据。csv 文件。

为了将数据上传到 Neo4j GDB,我使用了 Neo4j 管理导入功能,命令如下:

bin/neo4j-admin import --database=neo4j --nodes=import/nodes.csv --relationships=import/relations.csv --multiline-fields=true

使用此功能之前,请确保数据库为空。

导入完成后,我可以在 Neo4j 桌面中可视化与 Neo4j 浏览器的关系。第一,我想知道有多少维基百科页面上有一个“瑞典”的超链接。

match(n:WikiPage{name:'Sweden'})-[r:RELATION]->(m) return count(m)count(m) : 840

这个结果表明,840 个维基百科页面在维基百科页面上有一个“瑞典”的超链接。我用这个查询可视化了其中的 20 个。

match(n:WikiPage{name:'Sweden'})-[r:RELATION]->(m) return n,m limit 21

一些与“瑞典”维基百科页面有关系的维基百科页面。

结果表明,许多与“瑞典”的最初关系也是相互关联的。例如,可以从维基百科页面“瑞典”直接转到“国家元首”,距离=1,或者转到“俄罗斯”或“古巴”,距离= 2。这一点我们可以从维基百科“瑞典”的原始页面中得到证实:

维基百科“瑞典”页面复制文字。

在这种情况下,最短路径算法将选择路径“瑞典”->“国家元首”,因为这条路径的距离最短。

寻找最短路径

现在,我终于可以使用图算法来找到这个图中两个节点之间的最短路径。首先,我需要从 Neo4j 桌面中的插件安装图形数据科学库。为了使用 GDS 库中包含的算法,要求图形被投影。投影一个图形是通过下面的查询完成的。关于投影图的更多细节可以在这里找到:

CALL gds.graph.project('myGraph','WikiPage','RELATION',{relationshipProperties:'distance'})

为了找到图中的最短路径,我选择使用 Dijkstra 的算法。

Dijkstra 算法是一种用于寻找图中节点之间的最短路径的算法,该图可以表示例如道路网络。它是由计算机科学家 Edsger W. Dijkstra 在 1956 年构思的,三年后发表。【1】

我不会详细解释 Dijstra 的算法是如何工作的,但下面的动画显示了主要的算法。在这里可以找到一个很好的解释

Dijkstra 算法的动画由 Ibmua 制作。在公共领域发布。

现在可以用下面的查询运行 Dijkstra 的算法了。为了测试算法,我想找到从“瑞典”到“德拉库拉”的最短路径。

MATCH (source:WikiPage {name: "Sweden"}), (target:WikiPage {name: "Dracula"})CALL gds.shortestPath.dijkstra.stream('myGraph', { sourceNode: source, targetNode: target, relationshipWeightProperty: 'distance'})YIELD index, sourceNode, targetNode, totalCost, nodeIds, costs, pathRETURN
index, gds.util.asNode(sourceNode).name AS sourceNodeName, gds.util.asNode(targetNode).name AS targetNodeName, totalCost, [nodeId IN nodeIds | gds.util.asNode(nodeId).name] AS nodeNames, costs, nodes(path) as pathORDER BY index--------------------------------------------------------------------Result:index: 0
sourceNodeName: “Sweden”
targetNodeName: “Dracula”
totalCost: 3.0
nodeNames: ["Sweden", "Industrial Revolution", "Lord Byron", "Dracula"]
costs: [0.0, 1.0, 2.0, 3.0]

结果显示,从“瑞典”到“德拉库拉”至少需要三个链接。该路径可以在下图所示的图表中可视化:

从维基百科页面“瑞典”到“德古拉”的最短路径。

通过使用 Wikipedia.com,我可以确认这条路径存在,并且我相信实现的 Dijkstra 算法已经找到了最短的路径。

thewikigame.com不同的人正在竞争从源页面中寻找目标页面。每 120 秒就会有一个新的目标和源维基百科页面被公布。谁能最快地从源页面到达目标页面,谁就赢得了比赛。我不会用我的代码挑战这些玩家,因为那会被认为是作弊。我想用玩游戏的结果来比较参赛者与 Dijkstra 算法找到的最优解的接近程度。为了将我的算法与最好的 wikiracers 进行比较,我编写了一个简短的 Python 代码,它从上一次运行中获取源页面和目标页面,并使用 Dijkstra 算法。结果如下图所示。

显示从 thewikigame.com 出发的最快路径与 Dijkstra 算法找到的最短路径相比的数据帧。

如上表所示,DijkstrasPath 总是短于或等于 fastestPath,这是一个人在 thewikigame.com 上找到的最快路径。然而,令人印象深刻的是,有些人实际上发现了一条长度与 DijkstrasPath 相等的路径。记住,这个问题可能有很多不同的最短路径,从而导致多个解。thewikigame.com 上的玩家通常用 30-90 秒找到最快的路径,而 Dijkstra 的算法用 1-2 秒。如果我们看看从“拉什·林堡”到“动物”的路径,Wikirace 上最快的路径长度是 6,Dijkstra 找到了一条长度为 4 的更短的路径,如下图所示。

比较由 Dijkstra 算法找到的路径和 Wikirace 中的竞赛获胜者。

由此得出结论,有可能使用图算法,例如 Dijkstra 算法,找到两个维基百科页面之间的最短路径,并有可能赢得维基百科。这个项目中使用的数据集的一个问题是数据集来自 2013 年。过时的数据集可能会导致问题,因为 2013 年的一些路径现在已经不存在了。自 2013 年以来,还实施了某些新路径。

Neo4j GDS 中的其他图算法

当图表被投影时,我想对维基百科数据集做更多的分析。比如:哪些维基百科页面被其他维基百科页面引用最多?我不是维基百科专家,但我猜有很多关系的维基百科网站将是一个开始比赛的好地方。

Neo4j 的算法叫做中心性算法

中心性算法用于确定网络中不同节点的重要性。【2】

一种特殊的中心算法,页面排名,可以帮助我找到最重要的节点,或者维基百科网站。

PageRank 算法根据传入关系的数量和相应源节点的重要性来衡量图中每个节点的重要性。【3】

我可以用这个查询运行 PageRank 算法:

CALL gds.pageRank.stream('myGraph')
YIELD nodeId, score
RETURN gds.util.asNode(nodeId).name AS name, scoreORDER BY score DESC, name ASC

结果很有趣。下图显示“美国”是数据集中最重要的节点。其他重要的节点也是国家。根据这一分析,我建议在维基百科开始时选择一个主要的国家来尝试进入维基百科页面。更有调查显示,“美国”在维基百科页面上有 938 个超链接,其他维基百科页面有 431705 个超链接指向“美国”的维基百科页面。

用 PageRank 算法发现维基百科图数据库中最重要的节点

我还可以通过对结果进行升序排序来探索不太重要的节点。结果显示许多节点具有同样低的分数。通过观察图中的节点,我可以看到它们只有一个关系。得分如此低的许多节点或维基百科页面今天都进行了更新,比 2013 年的数据集有更多的关系。

用 PageRank 算法发现维基百科图数据库中的次要节点

进一步分析

对随机维基百科页面的进一步分析可以在下面的柱状图中看到。该图显示了引用随机页面的超链接和引用随机页面中其他维基百科页面的超链接之间的差异。

比较随机维基百科页面的超链接引用。

例如,“Elon Musk”的维基百科页面有大约 10 个指向其他维基百科页面的超链接(出),并且几乎与指向“Elon Musk”维基百科页面的超链接数量相等(入)。乍一看,“MacGyver”在维基百科中的引用比“Elon Musk”多,这很奇怪。但如前所述,数据集来自 2013 年。如果我在 Google Trends 中进一步调查,结果显示“MacGyver”的 Google 搜索点击量大于“Elon Musk”。但如图所示,2010 年后“埃隆·马斯克”的趋势是上升的。

埃隆马斯克和麦吉弗在美国的谷歌趋势。

结论

这个项目的目标是应用某种算法在维基百科中找到最佳路径。在这篇文章中,我展示了使用 Neo4j GDB、图形数据科学和 Dijkstra 的算法以及斯坦福大学维基百科关系数据集来找到最佳路径是可能的。然后,我将一些真实的维基百科与 Dijkstra 算法找到的最佳路径进行了比较。尽管 Dijkstra 的算法几乎总能找到最短的路径,但很少有 wikiraces 具有相同的路径长度。有了结果,我可以断定这个项目是成功的,我找到了最优解。如前所述,数据集来自 2013 年,这个项目只能保证找到 2013 年维基百科页面的最佳路径。

最后,我研究了其他一些 GDS 算法,并对结果做了进一步的分析。这个项目仅用于教育目的,并不打算在游戏中使用,如维基百科。

参考

【1】—迪杰斯特拉算法,维基百科
【2】—中心性算法,Neo4j
【3】—page rank,Neo4j

领英儿科

美丽的条形图:条形图上的缩放渐变填充

原文:https://towardsdatascience.com/beautiful-bars-scaled-gradient-fill-on-bar-plots-e4da4cdae033

在 matplotlib 中,使用颜色将含义为的添加到绘图中

陈丹妮Unsplash 上的照片

条形图是向我们的观众传达数据的最基本和最有用的方式之一。虽然有更多的数据密集型图,如箱线图、小提琴图和热图,但没有一种图像条形图一样被非技术人员普遍理解。

另一方面,柱状图真的很无聊。它们也非常简单,因为它们没有给观众任何关于所显示的价值观是好是坏的直觉。

在本文中,我们将从用渐变颜色填充给基本的条形图增添一点趣味开始。然后,我们将向您展示如何缩放渐变填充,以便单个条不会遍历整个颜色范围,自然地强调值之间的 差异 。毕竟,这不正是我们试图用柱状图表达的观点吗?

最后,我们将看到如何应用自定义颜色图,我们可以具体定义颜色变化的位置,这样我们就可以说明某些条形指示问题的位置,并进一步将观众的目光吸引到最重要的地方。我们开始吧!

首先,我们将导入标准包,以及一些特定于我们稍后将生成的渐变颜色贴图的包。接下来,我们将为我们的数据创建一个简单的 dataframe,以及一个非常温和的条形图。

最无聊的酒吧情节…😴

现在,简单地改变条形的颜色并不难(例如,ax.bar(df.a, df.b, color = 'orange')),但你不是为此而来的,对吗?

基本渐变填充(用于样式,而非内容)

为了执行填充,我们将创建一个基本的条形图,并将其作为变量传递给一个自定义函数。从这里开始,我们将一条一条地把它拆开,并应用ax.imshow()函数来应用色彩映射表(简称 cmaps)。

使用imshow()最具挑战性的部分之一是设置它需要的第一个变量(文档中的“X”)。这里,我们想要线性地处理我们选择的颜色图,所以我们将使用np.linspace()创建一个 0 到 1 之间的 256 个元素的线性数组。重要的是要注意下面linspace()代码中的.T——它将渐变设置为垂直渐变的正确方向。试着脱下来看看会发生什么!

接下来,我们在函数中重新建立 ax,这样我们就可以提取总绘图区域的 x 和 y 界限。我们用get_xlim()get_ylim()提取这些限制。最后,我们用ax.axis()函数来应用这些。虽然这看起来很傻,但这些步骤是必要的,以告诉 matplotlib 不要用我们的彩色地图填充整个绘图区域。

最后,我们在一个 for 循环中遍历条形图的每一条。我们首先必须将工具条的facecolor()设置为“none ”,否则基色将被放置在我们添加的渐变填充之上。或者,如果我们增加imshow()函数中的zorder,可以跳过这一行——稍后会详细介绍。然后我们提取酒吧的特征,然后使用imshow()在这个范围内应用我们的渐变填充(酒吧的 x,y 坐标)。

使用默认 cmap 的均匀渐变填充

高级渐变填充

虽然上面的图看起来更漂亮,但它肯定没有告诉我们任何我们不知道的数据。当我们展示柱状图时,最高点通常更有意义,不管是好是坏。我们真的想让观众注意到酒吧高度的差异。

我们可以将此作为对之前函数的一个相当简单的升级。在我们在顶部设置grad变量之前,所有的条将在颜色图上遍历 0 到 256 种颜色。为了缩放我们的颜色,我们真正想要的是最大的条获得完整的颜色范围,而其他条遍历其中的一个子集。为此,我们将grad调用移动到我们的 bar for 循环中。每次调用它时,它都会生成一个包含 256 个数字的数组,但是我们会修改步长。因此,对于最大的小节,grad从 0 到 1(有 256 个步长),但是对于所有其他小节,grad不会到 1。步长由特定条形的高度(h)与最大条形的高度(max(ydata))进行缩放。为了实现这一点,你可能已经注意到我们现在将ydata作为函数调用的一部分传入。我们还传入了一个 cmap 名称,因此我们可以从函数调用中选择梯度 cmap。

还有一点——在imshow()功能中,我们必须关闭norm,否则它会解除我们对grad的魔法,并自动将所有输入缩放到 0 和 1 之间。

我们可以用不同的彩色地图(cmaps)来尝试,看看哪一种最适合我们的数据:

分别使用“viridis”、“hot”和“cool”cmap

在这些图中,我们看到只有较高的条能够达到特定的颜色。这有助于吸引观众的眼球。这种差异很微妙,但很重要。在下面的并排比较中,这种新的缩放渐变填充(左)仅达到第 3 条和第 5 条的紫色范围,使它们具有更高的重力。在这种情况下,我们可以让我们的观众认为“如果一个酒吧变成紫色是不是很糟糕?”。

将缩放的渐变填充与未缩放的渐变填充进行比较(图片由作者提供)

完善情节

在我们与观众分享这个情节之前,我们需要做一些总体的视觉清理。我们将添加网格线以及边界到我们的酒吧,以防止他们融入背景中(因为一些颜色的地图可以相当轻)。这与传统条形图之间的唯一区别是必须对zorder多加小心,它控制哪些元素在其他元素的前面。因为我们在一个函数中进行条形着色,但是在基本生成条形之后,我们像这样添加zorder:

“YlOrRd”中的缩放渐变

“viridis_r”中的比例渐变

完全定制的渐变(额外学分)

让我们变得挑剔。如果我们希望我们的条形以某个值改变为某个颜色,以更好地反映什么时候需要我们的观众的注意呢?为此,我们需要构建自定义的彩色地图。我在我的上一篇文章中深入讨论了这个问题,展示了如何使用彩色地图,以及如何功能化构建在三种颜色之间转换的彩色地图。更好的是,这些函数使我们能够选择颜色,选择过渡发生的位置,以及过渡的混合程度。我不会一步一步地通过代码来制作如下所示的 cmaps,而是直接让你体验一下它们在我们的渐变填充图上的样子。我将使用上面相同的缩放渐变填充代码,但现在只需插入自定义的 cmaps。

在上面的代码中,我们选择以 3.5 从第一种颜色过渡到第二种颜色(混合值为 1),以 5.5 过渡到第三种颜色(混合值也为 1)。我们给观众的信息是,高于 3.5 的值应该引起关注,高于 5.5 的值是完全危险的。看看你是否能从这张图中得到同样的信息:

3 级自定义 cmap 应用于我们的酒吧

摘要

条形图通常很简单,但是我们可以使用渐变填充来增加趣味。更好的是,我们可以使用比例渐变自定义比例渐变来教我们的观众如何解读数据。好消息是——你现在有工具让美丽(和有意义!)条形图。坏消息是——标准条形图现在看起来比以往任何时候都更加简单和乏味(滚动到第一个条形图并退缩😬).

感谢阅读,如果你觉得这很有帮助,请跟我来!

和往常一样,整个代码走查笔记本可以从我的 github 中找到。干杯,祝大家编码愉快。

精美的插图:从 RNN 到变形金刚的 NLP 模型

原文:https://towardsdatascience.com/beautifully-illustrated-nlp-models-from-rnn-to-transformer-80d69faf2109

深度学习

用工作图解释他们复杂的数学公式

鲁拜图·阿扎德在 Unsplash 上的照片

**Table of Contents****·** [**Recurrent Neural Networks (RNN)**](#6cf1)
  ∘ [Vanilla RNN](#8dde)
  ∘ [Long Short-term Memory (LSTM)](#ed57)
  ∘ [Gated Recurrent Unit (GRU)](#1247)**·** [**RNN Architectures**](#866f)**·** [**Attention**](#b5e5)
  ∘ [Seq2seq with Attention](#e999)
  ∘ [Self-attention](#7efc)
  ∘ [Multi-head Attention](#2fbd)**·** [**Transformer**](#8704)
  ∘ [Step 1\. Adding Positional Encoding to Word Embeddings](#5dd0)
  ∘ [Step 2\. Encoder: Multi-head Attention and Feed Forward](#1e51)
  ∘ [Step 3\. Decoder: (Masked) Multi-head Attention and Feed Forward](#b51d)
  ∘ [Step 4\. Classifier](#7edd)**·** [**Wrapping Up**](#f7d9)

N 自然语言处理(NLP)是深度学习中一个具有挑战性的问题,因为计算机不理解如何处理原始单词。为了使用计算机的能力,我们需要在将单词输入模型之前将其转换为向量。由此产生的向量被称为 单词嵌入

这些嵌入可以用于解决期望的任务,例如情感分类、文本生成、命名实体识别或机器翻译。它们以一种聪明的方式被处理,使得模型对于某些任务的性能变得与人的能力不相上下。

那么,我听到你问,如何处理单词嵌入?如何为这种数据建立一个自然的模型?

让我们首先试着熟悉我们将要使用的符号。

我们将在这个故事中使用的符号|图片作者作者

递归神经网络(RNN)

当你读这句话的时候,你并不是从零开始思考每一个新单词。你保持以前单词的信息来理解你当前正在看的单词。基于这种行为,递归神经网络(RNN)诞生了。

在这一部分的故事中,我们将重点介绍 RNN 细胞及其改进。稍后,我们将看到细胞是如何排列在一起的。

香草 RNN

传统的 RNN 由重复的单元组成,每个单元依次接收嵌入 xₜ 的输入,并通过隐藏状态 hₜ₋₁ 记住过去的序列。隐藏状态被更新到 hₜ 并被转发到下一个单元格,或者——取决于任务——可用于输出预测。下图显示了 RNN 细胞的内部工作原理。

香草 RNN 细胞|图片由作者

优势:

  • 以有意义的方式说明订单和先前的输入。

缺点:

  • 每一步的预测都依赖于之前的预测,因此很难将 RNN 运算并行化。
  • 处理长序列会产生爆炸或消失的梯度。

长短期记忆(LSTM)

减轻爆炸或消失梯度问题的一种方法是使用门控 rnn,其被设计成选择性地保留信息,并且能够学习长期依赖性。有两种受欢迎的门控 RNNs:长短期记忆(LSTM)和门控循环单位(GRU)。

LSTM 手机|图片由作者

为了避免长期依赖问题,LSTM 配备了一个单元状态 Cₜ ,这有点像高速公路,所以信息很容易不加修改地通过它。

为了有选择地保留信息,LSTM 也有三个关口:

  1. 忘记门→查看 hₜ₋₁xₜ ,并输出由 0 和 1 之间的数字组成的向量 fₜ ,该向量告诉我们要从单元格状态 Cₜ₋₁ 中丢弃什么信息。
  2. 输入门→类似于遗忘门,但这一次输出 iₜ 用于根据虚拟单元状态 ćₜ 决定我们要在单元状态中存储什么新信息。
  3. 输出门→类似于遗忘门,但输出 oₜ 用于过滤更新的单元状态 Cₜ 成为新的隐藏状态 hₜ

门控循环单元(GRU)

LSTM 相当复杂。GRU 提供了与 LSTM 相似的性能,但复杂性更低(重量更轻)。它合并了单元格状态和隐藏状态。它还将遗忘门和输入门合并成一个“更新门”。

GRU 手机|图片由作者

为了进一步解释,GRU 有两个大门:

  1. reset gate →查看 hₜ₋₁xₜ ,输出一个由 0 和 1 之间的数字组成的矢量 rₜ ,该矢量决定需要忽略多少过去的信息 hₜ₋₁
  2. 更新门→根据 rₜ 决定我们要在新的隐藏状态 hₜ 中存储什么信息或者丢弃什么信息。

RNN 建筑

现在你已经理解了 RNN 细胞是如何工作的,你可以按如下顺序链接它的拷贝。这里, yₜ 是预测的输出概率,表示为

对于一些重量 W ,偏置 b ,以及激活功能 g 。如您所见,架构和激活功能取决于任务。

RNN 建筑取决于任务|图片作者作者

特别是,上面最后一个机器翻译的例子是我们所说的 seq2seq 模型,其中输入序列 x₁x₂ 、…、 xₜ 被翻译成输出序列 y₁y₂ 、…、 yₘ 。第一组 t RNNs 称为编码器,最后一组 m RNNs 称为解码器

RNN 单元也可以翻转或垂直堆叠,如下所示。这种架构通常只由两到三层组成。这可以提高模型性能,但代价是计算量更大。

RNN 变体,这样的架构通常只由两三层组成|图片作者作者

注意力

Seq2seq 被限制为使用编码器最末端的表示来被解码器解释。解码器只看到来自最后一个编码器 RNN 单元的输入序列的一个表示。然而,输入序列的不同部分在输出序列的每个生成步骤中可能更有用。这就是注意力的概念。

优点:

  • 考虑适当的编码表示,而不管输入标记的位置。

缺点:

  • 另一个计算步骤包括学习权重。

Seq2seq 注意

每个解码器令牌将查看每个编码器令牌,并通过其隐藏状态来决定哪些令牌需要更多关注。

seq2seq 工作图有关注|图片作者作者

在 seq2seq 中融入注意力有三个步骤:

  1. 从一对解码器和编码器隐藏状态( sᵢhⱼ )计算标量注意力分数,其代表编码器令牌 j 与解码器令牌 i 的“相关性”。
  2. 所有注意力分数通过 softmax 传递,以产生注意力权重,其形成解码器和编码器令牌对的相关性的概率分布。
  3. 计算具有注意力权重的编码器隐藏状态的加权和,并将其馈入下一个解码器单元。

在我们的例子中,得分函数是缩放的点积

其中 dₕhⱼ (和 sᵢ )的尺寸。

自我关注

让我们完全抛弃 seq2seq,只关注注意力。一种流行的关注是自我关注,其中不是从解码器到编码器令牌寻找相关性,而是从一组令牌中的每个令牌到同一组中的所有其他令牌寻找相关性。

自我关注|图片工作图作者

自我注意使用注意函数创建基于输入标记对之间的相似性的加权表示,这提供了知道其元素之间的关系的输入序列的丰富表示。

普通注意力和自我注意力有三个主要区别:

  1. 由于自我关注中没有解码器令牌,一个“查询”向量qᵢ——与输入嵌入 xᵢ 线性相关——取而代之。
  2. 关注度得分是从这一对( qᵢkⱼ )中计算出来的,其中 kⱼ 是一个“关键”向量,与 qᵢ 的维度相同,也与 xⱼ 线性相关。
  3. 自我关注用注意力权重乘以一个新的“价值”向量 vⱼ ,而不是像普通注意力一样,再用注意力权重乘以 kⱼ 。请注意, vⱼ 的尺寸可能与 kⱼ 的尺寸不同,并且再次与 xⱼ 线性相关。

多头注意力

注意力可以并行运行几次,产生我们所说的多头注意力。独立的注意力输出然后被连接并线性转换成期望的维度。

多个注意头背后的动机是它们允许不同地注意输入序列的部分(例如,长期依赖性对短期依赖性),因此它可以提高单一注意的性能。

n 种注意力机制的多头注意力工作图|图片由作者

由于在故事的下一部分事情会变得更加疯狂,在上面的图表中,我们对一切进行了矢量化,以便多头注意力的输入和输出由一个带单箭头的矩阵表示。

自我注意也可以与任何类型的注意交换,或者通过任何修改来实现,只要其变量的维度是适当的。

变压器

给定输入嵌入 X 和输出嵌入 Y ,一般来说,使用一个接一个堆叠的 N 个编码器连接到一个接一个堆叠的 N 个解码器来构建变压器。 没有递归或卷积,你所需要的是 中的每个编码器和解码器。

具有 N 个编码器和解码器的变压器的工作图|图片由作者提供

优点:

  • 输入记号的更好表示,其中记号表示基于使用自我注意的特定相邻记号。
  • (并行)处理所有输入令牌,而不是受到顺序处理(RNNs)的内存问题的限制。

缺点:

  • 计算密集型。
  • 需要大量数据(使用预训练模型缓解)。

让我们来看看变压器是如何工作的!

第一步。向单词嵌入添加位置编码

向单词嵌入添加位置编码|图片作者作者

由于变换器不包含递归和卷积,为了使模型利用序列的顺序,我们必须注入一些关于序列中记号的相对或绝对位置的信息。

因此,我们必须通过“位置编码”的方式让模型明确地知道记号的位置:

其中 i 是令牌的位置(令牌#0、令牌#1 等等), j 是编码的列号, dₓ 是编码的维数(与输入嵌入的维数 X 相同)。

对于编码维度为 512 的前 2048 个标记,您可以将位置编码矩阵 P 可视化如下。

编码维度为 512 的前 2048 个标记的位置编码|图片作者作者

在 seq2seq 模型中,输出嵌入 Y 右移,第一个标记是“句首”< bos >。位置编码然后被添加到 XY ,然后分别被馈送到第一编码器和解码器。

第二步。编码器:多头关注和前馈

变形金刚中的编码器|图片作者作者

编码器由两个模块组成:

  1. 输入的嵌入X——加上位置编码P——送入多头关注。剩余连接被用于多头注意力,这意味着我们将单词嵌入(或前一编码器的输出)加到注意力的输出上。然后将结果归一化。
  2. 归一化后,信息通过一个前馈神经网络,该网络由两层组成,分别具有 ReLU 和线性激活函数。同样,我们在这个块上使用剩余连接和标准化。

要了解更多关于残差连接和图层规范化的信息,您可以进入这个故事:

</5-most-well-known-cnn-architectures-visualized-af76f1f0065e>

编码器内部的计算到此结束。输出可以被馈送到另一个编码器或最后一个编码器之后的每个解码器的特定部分。

变形金刚编码器和解码器|图片由作者提供

第三步。解码器:(屏蔽)多头注意,前馈

《变形金刚》中的解码器|图片作者作者

解码器由三个模块组成:

  1. 输出嵌入Y——右移加位置编码 P 后——送入多头关注。注意,我们屏蔽掉(设置为 softmax 输入中与后续位置连接相对应的所有值。
  2. 然后信息通过另一个多头注意力——现在没有屏蔽——作为查询向量。键向量和值向量来自最后一个编码器的输出。这允许解码器中的每个位置关注输入序列中的所有位置。
  3. 结果通过一个前馈神经网络传递,该网络具有类似编码器的激活功能。

注意,所有解码器块也采用残差连接和层归一化。结合输出嵌入偏移一个位置的事实,屏蔽确保位置 i 的预测可以仅依赖于小于 i 的位置处的已知输出。

这就是解码器内部计算的结束。输出可以被馈送到另一个解码器或最后一个解码器之后的分类器。

第四步。分类者

变形金刚|图片中的分类器作者作者

这是最后一步,非常简单。我们使用学习线性变换和 softmax 将解码器输出转换为预测的下一个令牌概率。

《变形金刚》在自然语言处理方面取得了巨大的成功。许多预先训练好的模型,如 GPT-2、GPT-3、BERT、XLNet 和 RoBERTa,展示了 transformers 执行各种 NLP 相关任务的能力,如机器翻译、文档摘要、文档生成、命名实体识别和视频理解。

变压器还被应用于图像处理,与卷积神经网络相比,其结果颇具竞争力。

包扎

照片由杰瑞米·托马斯Unsplash 上拍摄

NLP 相关的任务很难。有许多方法可以解决这些问题。最直观的一个是 RNN,尽管它的操作很难并行化,并且当暴露于长序列时,它遭受爆炸或消失梯度。别担心,LSTM 和 GRU 会来救你的!

排列 RNN 细胞的方法有很多种,其中一种叫做 seq2seq。在 seq2seq 中,解码器只看到来自最后一个编码器 RNN 单元的输入序列的一个表示。这激发了注意力的使用,输入序列的不同部分可以在输出序列的每个生成步骤中得到不同的注意。

随着自我关注的发展,RNN 细胞可以被完全抛弃。称为多头注意力的自我注意力束以及前馈神经网络形成了转换器,构建了最先进的 NLP 模型,如 GPT-3、BERT 等,以出色的性能处理许多 NLP 任务。

🔥你好!如果你喜欢这个故事,想支持我这个作家,可以考虑 成为会员 。每月只需 5 美元,你就可以无限制地阅读媒体上的所有报道。如果你注册使用我的链接,我会赚一小笔佣金。

🔖想了解更多关于经典机器学习模型如何工作以及如何优化其参数的信息?或者 MLOps 大型项目的例子?有史以来最优秀的文章呢?继续阅读:

Albers Uzila

艾伯斯·乌兹拉

从零开始的机器学习

View list8 storiesAlbers Uzila

艾伯斯·乌兹拉

高级优化方法

View list7 storiesAlbers Uzila

艾伯斯·乌兹拉

MLOps 大型项目

View list6 storiesAlbers Uzila

艾伯斯·乌兹拉

我最好的故事

View list24 storiesAlbers Uzila

艾伯斯·乌兹拉

R 中的数据科学

View list7 stories

[1]阿希什·瓦斯瓦尼、诺姆·沙泽尔、尼基·帕尔马、雅各布·乌兹科雷特、利永·琼斯、艾丹·戈麦斯、卢卡兹·凯泽、伊利亚·波洛舒欣(2017): 注意力是你所需要的全部。NeurIPS 2017。[ pdf

[2]克里斯托弗·奥拉(2015): 了解 LSTM 网络。[ 网址

[3]悟空·莫汉达斯(2022): 粉底——用 ML 制作。[ 网址

[4]杰伊·阿拉玛(2018): 图解变形金刚。[ 网址

[5]莱娜·沃伊塔(2022): Seq2seq 及注意事项。[ 网址

贝克德尔测试:比较电影中的女性表现指标

原文:https://towardsdatascience.com/bechdel-test-comparing-female-representation-metrics-in-movies-6cbade15010f

变更数据

贝克德尔测试:比较电影中的女性表现指标

使用 API 收集数据,制作动画图形,并使用 Python 弥合电影中屏幕上和屏幕外的女性表现之间的差距

乔恩·泰森在 Unsplash 上的照片

目录

数据收集
使用 API 获取数据
数据角力
数据集更新
数据分析&可视化
了解 Bechdel 数据
比较屏幕内&屏幕外指标
结论

作为一个电影和电视剧的忠实粉丝,当我第一次在课堂上了解到 Bechdel 测试时,我很感兴趣。它通过检查三个标准来衡量小说中的女性形象:

  • 这部电影必须至少有两个女性角色
  • 他们互相交谈
  • 关于一个男人以外的东西。

这个测试是由艾莉森·贝克德尔在 1985 年发明的,但是它仍然适用于今天。我期望这是一个所有电影都应该通过的简单测试,但事实是这样吗?

在知道什么是贝克德尔测试之前,我会考虑一些指标,比如当谈到电影中的女性形象时,导演是否是女性或者女性演员的比例。这些是屏幕外的代表性指标,而 Bechdel 测试为屏幕上的女性代表性提供了一个指导方针,这是一个相当难以量化的东西。

因此,为了进一步研究这一主题并弥合屏幕上和屏幕外指标之间的差距,我从这个名为 Bechdel 测试电影列表的惊人网站获得了 9,300 多部电影的 Bechdel 测试数据,以回答以下问题:

  • Bechdel 考试成绩如何随时间变化?电影在通过贝克德尔测试方面做得更好吗🤞?
  • Bechdel 测试与屏幕外表现的其他基准相比如何?

为数据集勾选https://www.kaggle.com/alisonyao/movie-bechdel-test-scores
本帖中的代码可以在这个GitHub repo中找到。

数据收集

Bechdel 测试数据的所有学分都归入 Bechdel 测试电影列表,该列表为任何人检索原始数据提供了一个方便的 API。数据带有 CC BY-NC 3.0 许可证。我们感谢 bechdeltest.com 允许我们使用这篇文章中的数据。

使用 API 获取数据

API 文档给了我们 4 种调用数据的方法:

  1. getMovieByImdbId(返回一部包含 9 列的电影)
  2. getMoviesByTitle(返回具有匹配标题的多部电影,9 列)
  3. getAllMovieIds(返回数据库中的所有电影,2 列)
  4. getAllMovies(返回数据库中的所有电影,5 列)

我们可以马上看到,简单地使用一种方法不会给我们数据库中的所有信息。所有信息的数据帧应该包含 9 列的所有电影,那么方法 4 getAllMovies 缺少的 3 个特征是什么?好吧,让我们看看电影到底给我们带来了什么。

*# import library 
import pandas as pd 
# get dataframe 
df = pd.read_json('http://bechdeltest.com/api/v1/getAllMovies') 
# check the last 5 rows of the dataframe 
df.tail() 
# you can check the first 5 rows by running df.head()*# save dataframe to a csv file* df.to_csv('Bechdel.csv')*

作者图片

电影是按时间顺序添加的,所以最近的放在底部。我们可以看到克鲁拉没有 imdbid,这是我们需要稍后解决的问题。

方法#4 getAllMovies 给我们的有用信息是电影名称、IMDb id、唯一网站 id (id)、Bechdel 测试分数(评级)和发行年份。Bechdel 测试分数或评级是通过检查这三个标准来计算的。因为每个标准都是建立在前一个的基础上的,也就是说。一部电影不能满足标准#2。如果不满足标准#1,0 分意味着一部电影没有两个女性角色。1 表示一部电影有两个女性角色,但她们彼此不说话。2 表示一部电影有两个女人在说话,但她们谈论的是男人。3 表示完全通过 Bechdel 测试。所以,恭喜克鲁拉西城故事每次铃响,还有单曲一路

现在让我们看看# 1 getMovieByImdbId 方法给了我们什么。

*# Using Single All The Way as an example (imdbid=14315756) pd.read_json('http://bechdeltest.com/api/v1/getMovieByImdbId?imdbid=14315756', typ='series')*

作者图片

它没有索引,但有 4 个额外的列:可见,电影被添加到列表的日期,可疑,和提交者 id。对于每个电影,Visible 总是为 1,因为 API 调用只返回可见的电影。有趣的是可疑的栏目。它指示“提交者是否认为评级可疑”。换句话说,我们不能相信可疑电影的评级,因为它们很容易被修改。

这使事情变得复杂…可疑现在是一个不容忽视的重要专栏。我们可能会丢弃可疑的电影,或者我们可能会将可疑作为另一个类别。不管怎样,我们现在需要一个新的专栏——不确定。这花了我额外的 7 个小时。

数据争论

现在我们有了 9300 多部电影的 IMDb id,我们可以用它来获得每部电影的完整信息,这意味着我们需要调用 API 数千次。该网站指出:

请记住,我是在一个共享主机方案上运行这个网站的,所以如果你在短时间内发送大量的查询,你可能会给我带来麻烦。请友好一点,绝对不要把这些数据用在流量大的东西上。

我不想引起任何麻烦,所以我每隔几秒钟就调用一次 API(因此花了我 7 个小时)。我确实经历了一些超时错误和不稳定的互联网(这是我的错),所以也许几秒钟还是太频繁了。但谢天谢地,网站没有崩溃。正因如此,我建议如果你想使用数据集,避免再次调用 API,造成更多不必要的流量,可以查看一下这个 Kaggle 数据库

但是获得额外的 4 列的代码在这里:

然而,我们还没有完成。如果我们检查Bechdel_detailed.csv文件,我们将看到 3 个新列和一些 nan。

*bechdel_detailed_df = pd.read_csv('Bechdel_detailed.csv', index_col=0) 
bechdel_detailed_df.info()*

作者图片

很多可疑的是 NAN,因为该网站在其 API 中返回 null,但有 9373–9369 = 4 部电影看起来很奇怪。让我们来看看它们。

*bechdel_detailed_df[bechdel_detailed_df['title'].isna()]*

作者图片

这并不奇怪,因为索引 9369 是没有 imdbid 的 Cruella。我们预计它会引起问题,现在是时候解决它了。我们可以去 IMDb 手动获取 imdbid。现在,只需再清理一点数据,我们就完成了。

当前的Bechdel_detailed.csv文件应该是这样的。它包含了从 1874 年到 2021 年的 9373 部电影。

作者图片

数据集更新

网站更新很快,这里的分析基于 2021 年 12 月 23 日的数据。请查看 Kaggle 获取最新的数据集(我打算每季度维护一次)。

数据分析和可视化

与往常一样,对于任何数据集,我们都从探索性数据分析(EDA)开始,并将数据可视化,以了解我们在处理什么。

了解 Bechdel 数据

继续我们离开的地方,让我们首先导入更多的库并再次检查bechdel_detailed_df的基本信息。

*# import libraries 
import numpy as np 
import matplotlib.pyplot as plt 
%matplotlib inline 
from plotnine import * 
from mizani.formatters import percent_format # rename column because the name rating a little confusing
bechdel_detailed_df.rename(columns={'rating': 'bt_score'}, inplace=True)# check null 
bechdel_detailed_df.info()*

作者图片

数据集中有一些可疑的= NaN,但不太多,所以我们可以继续删除它们。

*# drop NAN 
bechdel_detailed_df = bechdel_detailed_df.dropna().reset_index(drop=True)len(bechdel_detailed_df) # returns 9074*

现在,我们总共有 9074 部电影。我们还需要检查重复,并删除 9 个重复的电影。

*bechdel_detailed_df.duplicated().sum() # returns 9
bechdel_detailed_df.drop_duplicates(inplace=True) 
# reset index
bechdel_detailed_df = bechdel_detailed_df.reset_index(drop=True)
# left with 9,065 movies*

好了,我们可以开始想象了。由于这几个月一直在学习 R(我的母语是 Python),开始喜欢上了 ggplot2 的风格,所以选择了混合使用 matplotlib 和 plotnine 进行可视化。

首先,我对数据集中的分数分布和百分比很好奇。

作者图片

超过一半的电影通过了 Bechdel 测试,考虑到 Bechdel 测试似乎并不太难通过,这是相当令人失望的。然而,fivethirtyeight 表示,56%的通过率已经高于预期[1]。他们还指出了一个“女权主义倾向”的问题,这意味着人们下意识地挑选更有可能通过 Bechdel 测试的电影,因为他们事先知道他们要向 Bechdel 网站提交一个分数[1]。此外,不难看出数据库中的大多数电影都是受欢迎的好莱坞电影,这也给我们的分析带来了地理位置限制。

承认数据集中的偏差很重要,EDA 帮助我们做到了这一点。

让我们继续处理可疑的电影。请记住,可疑的电影分数很容易改变,我们已经删除了带有可疑= nan 的行,所以现在我们对标记为可疑= 1 的电影感兴趣。

*dubious_count = bechdel_detailed_df['dubious'].value_counts()print('Percentage of dubious movie scores:', str('{:.2f}'.format(dubious_count[1.0] / (dubious_count[1.0] + dubious_count[0.0]) * 100))+'%')*

可疑电影评分百分比:8.92%

~9%不算太差,但我认为我们现在不应该放弃那些可疑的电影。而是打算把它作为一个新的类别,和 bt_score = 0,1,2,3 在同一个级别。让我们创建另一个名为“类别”的列,并标记 5 种可能性:

  • 可疑的
  • 0-少于两个女性角色
  • 1-女性角色不说话
  • 2-女性角色谈论男性
  • 3 次通过 Bechdel 测试

作者图片

好吧,让我们继续分析这些年的趋势。我们可以计算每一年的平均分数,并以散点图的形式显示出来。

作者图片

我添加了一条平滑的曲线,这样更容易看出趋势。早些年的电影表现非常差,但平均分数随着时间的推移在提高。最近几年达到了历史最高水平。

是因为电影通过测试的比例越来越高吗?让我们找出答案。

我选择使用动画饼图来可视化,因为它很好地显示了时间流动(在条形图中拟合 150 年看起来很糟糕)。另外,练习一些新的东西是有好处的。这次,我用颜色区分了 5 个类别。

作者的 GIF(动画图表可以很好地显示随时间的变化)

我们可以看到早年都是橙色,表示 0 电影通过测试。但是这些年来,越来越多的绿色出现,这意味着更多的电影通过了测试。但是绿的比例不稳定,因为 1 年的间隔太小。所以,我们用 10 年的间隔来代替。这一次,我们终于可以把所有的东西都放进一个条形图里了。

按作者分类的图片(这是显示比例的百分比堆积条形图,而不是显示频率或计数的常见条形图。)

可疑的电影在中间,以便人眼可以更好地比较绿色和橙色的比例。我们可以看到,随着绿色比例越来越大,橙色比例越来越轻。也就是说,许多电影仍然没有通过测试,但更多的电影得到了 1 和 2,而不是 0,这表明了进步。耶!

现在,我想花点时间强调一下,这里的“多”或“少”都是比例,或者百分比,或者比率。他们不是指纯粹的数字,或卷,或电影的数量。比较数字没有意义。为什么?因为人口效应,或者说规模效应

例如,2122 年通过 Bechdel 测试的电影数量可能比 2022 年多,因为 2122 年发行的电影数量是 2022 年的 10 倍。比例可能会下降,即使数字上升,所以数字本身并不能告诉我们多少有用的信息。我最近听到的另一个例子是,我的一个朋友正在做 NLP,他发现情感分析中的负面评论往往更短,但原因可能是互联网上的短评论(就数量而言)通常更多,所以他的结论可能没有意义。这个陷阱包含“人口”一词,因为它通常与人口联系在一起。中国的出生率比日本高,仅仅是因为中国人口多。这没什么意思。有趣的是出生率,而不是出生人数。同样,我们谈论的是人均 GDP,而不是整体 GDP。令人惊讶的是,我们经常把人口效应误解为有意义的事情。

好吧,让我们回到分析上来。既然我们对 Bechdel 数据和随时间变化的总体趋势有了很好的理解,让我们将其与屏幕外的指标进行比较。

比较屏幕上和屏幕外的指标

关于电影中女性形象的屏幕外指标,我指的是演员和工作人员中的女性比例。为了获得比率,我们可以使用这个流行的 Kaggle 数据集credits.csv文件标记了性别信息。

作者图片

为了将 Bechdel 数据与性别数据连接起来,我们需要links.csv文件。

*# import more libraries
import ast 
from collections import defaultdict
import seaborn as sns# load the 2 new datasets 
links_df = pd.read_csv('./TheMoviesData/links.csv', index_col=0) 
credits_df = pd.read_csv('./TheMoviesData/credits.csv')
# there are 37 duplicates in credits_df, but let's drop them later# merge 
bechdel_df = pd.merge(bechdel_detailed_df, links_df, left_on='imdbid', right_on='imdbId', how='inner').drop(columns=['imdbId']) bechdel_df = pd.merge(bechdel_df, credits_df, left_on='tmdbId', right_on='id', how='inner').drop(columns=['imdbid', 'submitterid', 'date', 'visible', 'tmdbId', 'id_x', 'id_y']) bechdel_df*

作者图片

《演员表》和《剧组》有些空值。让我们计算空值的百分比,看看我们应该怎么做。

*count1, count2 = 0, 0 
for index, row in bechdel_df.iterrows():
     cast_list = ast.literal_eval(row['cast'])
     crew_list = ast.literal_eval(row['crew'])
     if len(cast_list) == 0:
         count1 += 1
     if len(crew_list) == 0:
         count2 += 1 print('Empty cast percentage:', str('{:.2f}'.format(count1/len(bechdel_df) * 100))+'%') print('Empty crew percentage:', str('{:.2f}'.format(count2/len(bechdel_df) * 100))+'%')*

空投百分比:0.41%
空车率:0.11%

这是一个非常小的百分比,所以我们可以继续并放弃它们。此外,我们需要删除重复的内容。

*bechdel_df = bechdel_df[(bechdel_df['cast'] != '[]') & (bechdel_df['crew'] != '[]')].reset_index(drop=True) # check & drop duplicates
print(bechdel_df.duplicated().sum()) # returns 9 bechdel_df.drop_duplicates(inplace=True)
bechdel_df = bechdel_df.reset_index(drop=True)*

然而,Kaggle 数据集中还有一个性别未知的问题。Kaggle 数据集的原始数据源没有详细记录性别信息。其实有很多未知。

演员表中的未知百分比:36.29%
剧组中的未知百分比:59.01%
导演中的未知百分比:39.44%
编剧中的未知百分比:38.91%

因为有太多的未知数,我们可以通过从名字中预测性别来填补空白。性别猜测套餐是个不错的选择。这个包将性别视为二元的(可能是一个限制),并告诉我们名字是男/女,还是主要是男/女,或者未知/雌雄同体。例如,我的中文名字韩愈可以是任何性别,包装上会告诉你我的性别是未知的,但你可以从我的英文名字艾莉森看出我是女性。

演员中的未知百分比:4.78%
剧组中的未知百分比:4.99%
导演中的未知百分比:4.21%
编剧中的未知百分比:4.99%

未知的百分比显著下降,这太好了!现在,是时候决定我们需要哪些指标了。我认为重要的女性比例是:

  • 演员女性比例
  • 船员女性比例
  • 导演女性比例(有导演、助理导演等)
  • 作家女性比例

因此,我们可以通过运行以下命令来添加新列:

*bechdel_df['cast_female_ratio'] = gender_df['cast_female_num'] / gender_df['cast_total_num'] bechdel_df['crew_female_ratio'] = gender_df['crew_female_num'] / gender_df['crew_total_num'] bechdel_df['directing_female_ratio'] = gender_df['Directing_female'] / gender_df['Directing_total'] bechdel_df['writing_female_ratio'] = gender_df['Writing_female'] / gender_df['Writing_total'] bechdel_df.head()*

作者图片

writing_female_ratio 列中有一些 NaN,因为 0/0 是 NaN。如果编剧总数是 0(分母),那么这些电影的记录很可能是不完整的,对我们没有用处。让我们放弃空值。此外,这一次,在比较指标时,我们不能再考虑可疑的因素,因为可疑的分数是不可靠的。

*bechdel_df_no_nan = bechdel_df.dropna().reset_index(drop=True) 
bechdel_df_no_nan_no_dubious = bechdel_df_no_nan[bechdel_df_no_nan['dubious']==0].reset_index(drop=True)*

现在,我们可以检查每个指标的平均 Bechdel 分数。

*bechdel_df_no_nan_no_dubious.groupby('bt_score').mean()*

作者图片

通过目测平均值,似乎较高的女性比例与较高的 bt _ 得分相关。为了直观地显示平均值及其不确定性区间,我们可以使用误差线来比较指标和 Bechdel 分数。对于演员女性比例与 Bechdel 分数,我们有:

作者图片

误差条不重叠,这表明 bt_score = 0、1、2 和 3 的 4 组的平均值在统计上是不同的。而且正相关非常明显。

通过将列名从cast_female_ratio改为其他,我们可以绘制所有 4 个图形。

作者图片

没有通过贝克德尔测试的群体并不总是彼此不同,但与通过测试的电影相比,他们都有较低的女性比例。屏幕上和屏幕外指标之间的正相关非常显著。也就是说,演员和剧组中女性成员的比例越高,电影通过贝克德尔测试的可能性就越大,反之亦然。在片场有更多的女性的确可以转化为银幕上更好的女性形象。

这个有趣的分析到此结束。

结论

在这篇文章中,我们谈到了:

  • 如何使用 API 收集数据
  • 如何制作动画饼图
  • 什么是人口效应/规模效应

我们已经回答了这些问题:

  1. Bechdel 考试成绩如何随时间变化?电影在通过 Bechdel 测试方面做得更好吗?

是啊!Bechdel 平均分和电影通过率都在上升。对于未能通过贝克德尔测试的电影,现在更多的电影更接近通过测试。

2.Bechdel 测试与屏幕外表现的其他基准相比如何?

Bechdel 分数与演员、工作人员、导演和编剧中的女性比例呈正相关。职场中更多的女性可以转化为更多的女权主义产出。

这里的定量工作更侧重于数据采集、数据分析和可视化,因为这个项目最初是为了探索数据科学中的以人为本。重要的是学会问正确的问题,识别偏见和局限性,并意识到为什么对数据集做出每个决定。我认为这没有太大的意义,例如,根据性别比例预测 Bechdel 分数,并在这个项目中涉及机器学习模型。如果可视化已经说明了一切,我也不想通过引入像 Tukey 的 HSD 这样的统计概念来进行成对比较,从而使事情变得过于复杂。但是如果这符合你的需要,我们非常欢迎你这样做。

我的优秀队友 JB敏杰法蒂玛浏览了 Bechdel 网站上的评论,并做了使项目完整的定性分析。如果你有兴趣,请点击这里的!

本帖中的代码可以在这个GitHub repo中找到。检查数据集的*https://www.kaggle.com/alisonyao/movie-bechdel-test-scores。***

参考资料和相关阅读

以下是我在从事这个项目时发现的一些非常有帮助和鼓舞人心的文章。他们探索了 Bechdel 分数和其他有趣的方面如评级、预算等之间的关系。享受阅读的乐趣!

[1]https://fivethirtyeight . com/features/the-dollar-and-cents-case-against-Hollywood-exclusion-of-women/
【2】https://towards data science . com/the-bechdel-test-analyzing-gender-disparity-in-Hollywood-263 CD 4 BCD 9d

特别感谢 TDS 编辑本·胡伯尔曼,他在获得数据许可方面给了我难以置信的帮助,并指导我完成了发表这篇文章的每一步。

感谢您的阅读!希望这对你有帮助。有任何反馈请留言:)

成为“真正的”数据分析师

原文:https://towardsdatascience.com/becoming-a-real-data-analyst-dcaf5f48bc34

业余分析师和专业分析师的 10 个区别

在之前的中,我向您介绍了一些伪装成日常活动的分析任务,以证明您已经是一名数据分析师。例如,考虑下图。数码照片存储为一串数字(左),在你用合适的工具打开它们(右)之前,这些数字对你的大脑毫无意义。

我在 MS Paint 中打开的木地板照片中的蓝色通道数据示例。

哒哒!您刚刚完成了数据可视化。当你发现数据分析的能力一直存在于你的内心时,音乐就会膨胀。

但这是否意味着你已经准备好从事专业分析师的工作了呢?

不完全是。业余分析师和专业分析师之间有很大的区别。

专业数据人员与业余数据人员的区别#1 —软件技能

与大多数业余爱好者不同,专业人士知道如何使用软件(例如 PythonR )来让他们在一个地方与更多的数据格式进行交互。虽然 MS Paint 只适用于图像,但分析软件可以处理图像、表格、声音、文本和……以及厨房水槽。

下面是当你用 Python 打开同一个图像时的样子:

这是用 R 看到的同一个图像:

专业数据与业余数据的区别之二——轻松处理大量数据

第二个区别是,专业人员可以处理大量的数据。尽管我已经处理数据二十多年了,但我仍然更喜欢在浏览器甚至 MS Paint 中打开一张照片,而不是在 R 或 Python 中。那么,除了能够打开许多不同数据类型的灵活性之外,学习 analytics pro 工具的卖点是什么?好吧,如果你想弄懂一张百万张的照片呢?

你可以试着用 MS Paint 来理解它们,但是以每张图片 1 秒钟的速度,这将花费你一个多月的时间。通过使用代码处理和汇总大量数据,专业人员可以使用正确的工具在几分钟内完成这项工作。

你如何开始学习这些工具?你查找如何安装它们( RPython 是免费的)并开始玩它们。就像 MS Paint 一样,但是更好。只要在谷歌上搜索你想用它们完成的任何任务,然后阅读结果。

这是响应上述搜索查询的第一个结果:

嘣。这就是你所需要的。

好吧,如果你以前从未使用过 R,你的下一个搜索将需要是“我如何在 R 中安装包?”但在那之后,你就是黄金了。只需将代码复制粘贴到答案中,将“我的图像”替换为您照片的文件名和文件路径。不确定这些术语是什么意思?做一个搜索来查找它们。当你用完了你必须查阅的东西,你就掌握了你开始学习的任务。开发人员就是这样开发的(双关语)。

这样做一大堆,有一天你会醒来,意识到你已经意外地发展了专业软件技能。

这条推文逗得我哈哈大笑。如果你不明白,重点是他已经是一个真正的软件开发人员了…复制和粘贴工作。数据分析代码技能也是如此。你通过查找如何完成一项任务来学习,然后将它添加到你的工具箱中。

我喜欢编程的一个原因是它是魔法和乐高的结合。要学习完成任务的咒语,你可以在互联网上查找…这本身就是数据分析!

我喜欢编程的一个原因是它是魔法和乐高的结合。

说真的,你不需要课程。简单地挑战自己,尽可能多地使用 R 或 Python 语言(它们都很好),同时不断询问互联网如何克服出现的任何障碍。在你打开数据之后(下面是如何找到数据来看),想出一个让你心动的问题,并尝试使用工具来得到答案。从小处着手,随着过程变得更加雄心勃勃。没有什么能阻止你!玩得开心!

照片由 Jonny GiosUnsplash 上拍摄

专业数据与业余数据的区别#3 —不受数据科学偏见的影响

在我看来,学习工具是容易的部分。困难的部分是采用分析思维模式,这是接下来的区别所在。从这个开始:专家已经形成了对数据无所不包的不尊重。是的,你听到了。

只有新手才会把“数据”念成大写的“D”,并把它当成神奇的东西。专业人士被烧伤和心碎的次数够多了,他们痛苦地认识到数据只是人类决定以电子形式写下来的一些东西。(更多此处)。)

数据的优势是内存,不是质量。

在故事中加入一些数字使其更“科学”可能会赢得业余爱好者的信任,但经验丰富的分析师知道得更多。他们对我所说的数据科学偏见免疫——当信息带有数据科学的味道时,他们会更加信任信息。给一份无意义的报告添加一个漂亮的图表并不能愚弄他们。

专家们明白,数据的优势是记忆,而不是质量,所以他们对正式数据集的怀疑就像他们在街上漫步时听到的景象和声音一样。

“有了数据,你仍然只是另一个有观点的人。''

我最喜欢的 T4 统计学先驱之一 W. Edwards Deming 有一句名言“没有数据,你只是另一个有观点的人。这是真的,但不幸的是,“有了数据,你仍然只是另一个有观点的人。“专业分析师从骨子里明白这一点。

照片由木村宏Unsplash 上拍摄

要开始建立相同的免疫力,停止将数据视为特殊。你已经(希望*)学会了如何对照片保持理智和怀疑。例如,你很清楚不要把你在 Instagram 上看到的任何东西当作真实的、不加改变的、不带偏见的现实再现。如果照片不是你拍的,你就不会相信照片。对吗?没错。

停止将数据视为特殊!

你在野外看到的景象和声音中所学到的所有常识性规则也适用于结构化数据(表格/矩阵/电子表格中的数字)。

将数据等同于真理,就如同在对作者一无所知的情况下,相信书中所写的一切。如果你保持头脑清醒,保持健康的怀疑态度,你就能很好地进行分析。

有些可爱的人似乎已经成年,却不知道你在网上找到的并非都是真的。如果那是你,我可以委婉地建议分析可能不是你最好的职业选择吗?

亚历山大·辛恩Unsplash 上拍摄的照片

除了更多使用专业工具的实践之外,专业分析师还理解专业的专业方面,我们将在本系列的下一篇文章中讨论。为了提前预览,下面是即将推出的部分标题:

数据专家 vs 业余爱好者差异# 4——了解职业
数据专家 vs 业余爱好者差异# 5——拒绝成为数据江湖骗子
数据专家 vs 业余爱好者差异# 6——抵制确认偏差
数据专家 vs 业余爱好者差异# 7——对数据的现实预期
数据专家 vs 业余爱好者差异# 8——知道如何增加价值
数据专家 vs 业余爱好者差异# 9——对时间的不同思考
数据专家 vs 业余爱好者差异# 10——细致入微的卓越观

如果你想到了这些标题之外的其他不同之处,请在评论中告诉我!

本系列的前一篇文章

本系列的下一篇文章

又及:你有没有试过在 Medium 上不止一次点击这里的拍手按钮,看看会发生什么? ❤️

喜欢作者?与凯西·科兹尔科夫联系

让我们做朋友吧!你可以在 TwitterYouTubeSubstackLinkedIn 上找到我。有兴趣让我在你的活动上发言吗?使用这种形式取得联系。

在你问“为什么”之前…先问“谁”

原文:https://towardsdatascience.com/before-you-ask-why-ask-who-b90841d578b4

当你成为一名成熟的数据科学家时,你将学会问的问题

如果你足够幸运,有机会成为一名成熟的数据科学家,下面是你将经历的进化阶段。

改编自 Pawel ChuUnsplash 上的一张照片

阶段 1 —“如何做?”

在刚孵化的阶段,幼体数据科学家愉快地做他们被告知的任何事情,甚至没有好奇的唧唧声。你刚刚描述完问题,他们就已经在考虑 如何 尽可能正确客观地解决问题。

毕竟,他们花了几十年来解决复杂的家庭作业问题,而没有问自己,如果你从 50 头牛开始,它们的寿命是分布的,那么计算 10 年后牧场上会剩下多少头球形牛,这有什么可笑的...

啊,青春的(情感)弹性。你会长大的。(除非你有一个现象级经理,也就是说。这样你就不会被痛苦所激励,你就可以待在梦幻岛了。你真幸运。)

肖恩·马丁在 Unsplash 上拍摄的照片

第二阶段——“为什么?”

最终,你会因为缺乏影响力而感到足够沮丧,这将损害你的工作满意度。在同意做任何繁重的工作之前,你会开始问“ 为什么 (为什么和为什么,为什么和为什么)。

就这样,对吧?就两个阶段?许多数据专家认为,当他们愤世嫉俗地问 为什么 时,他们就已经成功了。

不,还有更多。

简而言之:你的利益相关者和领导可能有很好的理由对你隐瞒真相,所以问 为什么 只能让你到此为止。

照片由艾米丽·莫特Unsplash 上拍摄

第三阶段——“谁?”

等你再成熟一点,你会开始问“ ”然后再问“为什么”。

作为一名数据科学家,成熟意味着在问“为什么”之前先问“谁”。

你会更好地理解字里行间的含义,考虑人们的动机,并谨慎地选择你的合作者。这也是你停止假设你会得到关于你的技术工作的重要性和对你的组织的贡献的真实回答的阶段。为什么?(呃,嗯,谁?)*

简而言之:你的利益相关者和领导可能有一些很好的理由对你隐瞒真相。

在你的项目中会有很多不同的 参与进来,所以你必须弄清楚他们所有的动机。你会发现,在组织混乱的情况下,让每个人在一个问题上保持一致是难得的幸福时刻。当关于 的问题给你一个答案,让为什么没有希望时,你会明智地选择你的战斗。

安特·哈默斯特Unsplash 上的照片修改

阶段 4 —“什么?”

你现在是领导了。

但是你是一个好的号船长吗?也许吧。也许不是。欢迎来到第四阶段。电影场景的下一部分涉及海盗,呃,新的领导人问所有船员在哪里,这是非常恰当的。整个场景是一个很好的重组寓言。就在技术专家接替职业经理之后,人们通常会问“但是……人都到哪里去了?”【警告:电影场景不适合敏感观众。]

弄清楚什么是值得做的现在取决于你,但是除了你现在负责的 什么 之外,你还会问上面的每个问题。毕竟,你现在已经足够成熟,能够理解到一天结束时,一切都归结到人身上,所以即使你对 什么 进行优先排序,你也永远无法逃脱 (以及 为什么 甚至 如何 )。祝你好运!

*我的下一篇文章将把你从阶段 2 推进到阶段 3。随着我们在工作中变得成熟,学会做比问为什么更有帮助。学会如何跳过表面上的答案,学会理解言外之意是很有用的。

感谢阅读!

https://kozyrkov.medium.com/membership

附:你有没有试过在 Medium 上不止一次地点击拍手按钮,看看会发生什么? ❤️

喜欢作者?与凯西·科兹尔科夫联系

让我们做朋友吧!你可以在 TwitterYouTubeSubstackLinkedIn 上找到我。有兴趣让我在你的活动上发言吗?使用表格取得联系。

Azure 上简化 it 部署的初学者指南

原文:https://towardsdatascience.com/beginner-guide-to-streamlit-deployment-on-azure-f6618eee1ba9

使用免费 SSL 证书在 15 分钟内在 Microsoft Azure 上部署 Hello World Streamlit 应用程序的完整指南

使用 SSL 的最终应用程序部署(图片由作者提供)。

Streamlit 是一个令人惊叹的开源应用框架,数据科学家通常使用它来快速制作响应迅速的 web 应用。Streamlit 的直观框架非常容易学习,可以在几分钟内创建漂亮的仪表板甚至更复杂的 web 应用程序。

然而,许多数据科学家将部署的想法推迟到项目结束。相反,通过从部署阶段开始他们的项目,程序员可以在工作时在最终的 UI 中快速可视化他们的更改。如果您完成了机器学习阶段,却发现在尝试部署您的项目时有许多意想不到的问题,这可以为您节省很多压力。

当试图部署我最近的一个项目时,我意识到没有太多关于如何在 Azure 上部署带 SSL 加密的 Streamlit 应用程序的解释。SSL 证书对于任何面向客户端的页面都非常重要。如果你有一个证书,你的网页的访问者将不会面临一个网站不安全的浏览器警告。这个浏览器警告是不专业的,可能会阻止用户成功连接(取决于浏览器和设置)。因此,经过多天的试验、研究和解析不推荐的或不可理解的解决方案,我开发了一个最小的分步指南,使用 SSL 在线部署 Hello World Streamlit 应用程序。为此,我们将使用 Microsoft Azure(存储库、存储帐户和容器实例)、certbot(用于 SSL)和 NGINX 作为反向代理 web 服务器。如果你不懂一个(或者全部)也不用担心!)本指南是一步一步的,应该能让您在 15 分钟内启动并运行。事不宜迟,我们开始吧!

第 1 部分:在本地运行 Streamlit

首先,我们将建立一个新的虚拟环境。我推荐使用 Anaconda ,这是一个建立虚拟环境的好工具。如果你还没有 Anaconda,可以在这里下载。一旦安装了 Anaconda,我们就可以用

conda create -n NAME_OF_ENV python=3.8

如果提示 y/n,请输入 y 安装所需的软件包。NAME_OF_ENV 是一个占位符,用于表示您希望如何称呼您的环境。我将我的环境命名为 azure_demo。之后,使用以下工具激活您的环境

conda activate NAME_OF_ENV

我们将只为这个最小的项目安装一个包,尽管以后可以很容易地以类似的方式添加更多的包。我们使用以下工具安装 Streamlit

pip install streamlit

我们的环境现在已经准备好了!让我们将它添加到 PyCharm(如果您愿意,也可以添加到另一个 Python IDE)。首先创建一个新项目(我的命名为 demo_azure),然后添加你作为解释器创建的新 conda 环境

将 conda 环境添加到我们的 PyCharm 项目中。

我们的编码环境现在已经准备好了!让我们添加一个文件夹来保存我们的主要 Python 代码。我将我的项目称为 _contents。在里面,我们再做一个文件夹叫 app。在这里,创建一个名为 app.py 的新 Python 文件。

项目目录(图片由作者提供)。

我们现在准备创建我们的 Streamlit 应用程序。由于本教程的重点是部署,而不是使用 Streamlit 构建网页,我们将简单地创建一个标题为“Hello World!”。这可以用两行代码来完成——一行用于导入 Streamlit,一行用于添加标题。

就是这样!我们已经准备好在本地运行我们的 Streamlit 应用程序。打开一个终端(例如 mac 中的 terminal 或 Windows 中的 Anaconda 提示符),导航到您的项目根目录,确保您已经激活了之前创建的 virtualenv,然后运行命令

streamlit run project_contents/app/app.py

在任何浏览器中输入 localhost:8501,你应该会看到你的应用程序。

我们在 localhost:8501 上本地部署的 Streamlit 应用程序(图片由作者提供)。

恭喜你!您已经在本地部署了您的 Streamlit 应用程序,这是我们的第一个里程碑!作为参考,完整的项目代码可以在 Github 这里找到。现在,您可以通过在终端中键入 Ctrl+C 来终止该应用程序,然后继续第 2 部分。

第 2 部分:整理你的 Streamlit 应用程序

在第 2 部分中,我们将使用我们的 Streamlit 应用程序,并协调其在 Docker 中的部署。Docker 将我们的应用程序容器化,使其可以部署在各种云平台上。如果你还没有安装 Docker,点击这里

首先,我们将在项目的根目录中创建一个 Dockerfile(接下来,所有创建的文件都将放在项目的根目录中):

对于这个部署,我们使用 micromamba 映像。确保在第 3–5 行将项目目录名称从 demo_azure 替换为您的项目名称。

接下来,我们将创建在 docker 文件的第 14 行引用的 run.sh 文件。在这里,我们只需使用 Streamlit 运行 app.py。我在 theme.base 中添加了“黑暗”来设置一个黑暗的主题,尽管这是完全可选的(而且非常酷!).

接下来,我们将创建环境文件,在 docker 文件的第 7–9 行中引用。创建一个名为 environment.yml 的文件,并添加以下代码。这个文件将指导 Docker 安装必要的包来运行我们的应用程序。完成本教程后,您可以随意添加您的应用程序需要的任何其他包,只需在新的一行中添加到文件的底部“- NAME_OF_PACKAGE”即可。

我们的集装箱现在准备好了!让我们在本地使用

docker build -t azure_demo:v1 .docker run --rm -p 8880:8501 azure_demo:v1

标志-RM 在容器停止运行后删除映像,而-p 8880:8501 将我们的本地端口 8880 映射到容器的端口 8501。因此,当我们在浏览器中导航到 localhost:8880 时,应该会看到以下内容:

我们的容器化 Streamlit 应用程序可在 localhost:8880(图片由作者提供)访问。

恭喜你!您已经容器化了您的 Streamlit 应用程序,现在已经完成了第 2 部分。随时停止你的运行 Docker 容器。让我们通过将容器部署到 Azure 来结束本教程。如果你愿意,这个容器也可以部署到另一个云平台(比如 AWS 或者 GCP ),尽管这里只讨论 Azure。

第 3 部分:将你的 Dockerized 应用部署到 Azure

现在,我们的应用程序被封装在 Docker 容器中,我们可以部署我们的应用程序,以便它可以在互联网上访问。在我们继续之前,请确保您已经安装了 Azure CLI 。登录使用

az login

此外,确保您有一个资源组,可以用它来创建容器实例和容器注册表。出于演示的目的,我的资源组将被称为 AMAZING_RESOURCE_GROUP。

我们的第一个任务是将我们的容器图像从我们的计算机上传到 Azure 容器注册表。我们可以使用创建一个新的注册表

az acr create --resource-group AMAZING_RESOURCE_GROUP --name NAME_OF_REGISTRY --sku Basic

请记住,根据需要更改资源组的名称和注册表的名称。您可以通过登录 Azure 门户并导航到容器注册表来检查注册表是否存在。您的注册表应该在那里。

您现在可以使用登录您的注册表

az acr login -n NAME_OF_REGISTRY

您应该会看到“登录成功”。您可以使用门户上传容器映像,但是在本教程中我们将使用 CLI。以下命令将构建我们的映像并将其推送到我们的新注册表中:

docker build -t azure_demo:v1 .docker tag azure_demo:v1 NAME_OF_REGISTRY.azurecr.io/azure_demo:v1docker push NAME_OF_REGISTRY.azurecr.io/azure_demo:v1

请记住:更改注册表的名称以匹配您自己的名称。如果在第一行中没有将图像命名为 azure_demo,请确保在第 2 行和第 3 行中使用相同的名称,这样图像名称就一致了。通过在 Azure 门户中导航到您的注册表并验证您的映像是否在注册表中(在服务>存储库下),可以进行可选的检查。

太棒了。我们的图像现在位于 Azure 注册表的一个存储库中。这使得部署更加容易。下一步是在我们的项目目录中创建一个名为 deployment.yml 的文件,其内容如下:

为了部署我们的容器,deployment.yml 文件包含 Azure 需要知道的所有信息。这个 yml 文件包含部署我们的应用程序所需的最少内容——如果你想添加更多内容,Azure 上的 YAML 参考是一个很好的资源。记住将第 2 行设置为您的位置(例如,eastus),将第 3 行设置为一个唯一的项目名称,第 8、19 和 20 行使用您的注册表名称。第 30 行的 FQDN 指的是你希望你的域名是什么——例如,如果你把第 30 行的 FQDN 名字写成我的假期,你的网站可以通过访问我的假期来访问。最后,我们必须提供凭证来访问我们的容器注册中心,以提取我们的容器映像(第 21 行)。为了获得此密码,请运行以下命令:

az acr update -n NAME_OF_REGISTRY --admin-enabled trueaz acr credential show --name  NAME_OF_REGISTRY

这将在终端中输出您的注册表的密码。复制密码,并粘贴到第 21 行。我们的 deployment.yml 现在已经准备好了。

在部署应用程序之前,我们将在项目目录中创建一个名为 nginx.conf 的文件。这将把网络流量从我们的 FQDN 重新路由到 8501 端口。否则,您必须在域名中指定端口 8501(例如,my vacation . eastus . azure container . io:8501—yikes)。您可以将以下代码复制粘贴到 nginx.conf 中:

唯一必须更改的行是第 22 行和第 53 行,其中 FQDN 名称是您在 deployment.yml 的第 30 行中选择的 FQDN 名称,AZURE_LOCATION 是您在 deployment.yml 的第 2 行中选择的位置。总的来说,这个 nginx 服务器将侦听端口 80(连接到我们的网站时的默认端口),并将流量重新路由到本地主机端口 8501。我包括的位置(/healthz、/vendor、/stream)对 Streamlit 很重要——如果省略这些行,Streamlit 将无法工作。

完美!现在我们只需将新创建的 nginx.conf 文件添加到 docker 文件中。

将您的 docker 文件修改为这个新版本,它包括安装 nginx(以及我们将用于 SSL 的其他包)的一些安装步骤,还包括复制 nginx.conf 文件的命令。

我们还必须更新我们的 run.sh,添加第 2 行和第 3 行来启动 nginx。

最终项目树(图片由作者提供)。

唷!是时候看看我们的网站在互联网上运行了。但是首先,由于我们对项目进行了更改,我们必须重新创建我们的容器,并将这个新容器推送到 Azure container registry 来代替旧容器。我们可以使用相同的代码来构建我们的映像,并像以前一样推送它:

docker build -t azure_demo:v1 .docker tag azure_demo:v1 NAME_OF_REGISTRY.azurecr.io/azure_demo:v1docker push NAME_OF_REGISTRY.azurecr.io/azure_demo:v1

现在,在您的终端中运行以下命令来部署您的应用程序:

az container create --resource-group AMAZING_RESOURCE_GROUP --name demo_azure -f deployment.yml

该命令使用我们的文件 deployment.yml 创建一个容器实例,确保— name 标志与您在 deployment.yml 第 3 行中提供的名称相匹配。部署可能需要几分钟时间。您可以确认已经使用 Azure 门户部署了您的实例(导航到容器实例)。您将能够使用您选择的 FQDN(FQDN 名称)访问您的应用程序。AZURE _ location . AZURE container . io)。该名称也可以在门户网站中确认:

确认我们的域名(图片由作者提供)。

我们部署的 Streamlit 应用程序(图片由作者提供)。

恭喜你!您的 Streamlit 应用程序现已启动,并在您的自定义域名上在线运行。

结论

请记住,在对我们的项目进行任何更改后,为了使这些更改反映在您的 web 应用程序上,您必须重新构建您的映像,推送映像,删除 Azure 上正在运行的容器实例,并再次构建您的容器实例。

请务必阅读这个两部分系列的第二部分,在那里我将讨论如何创建一个免费的 SSL 证书,如何存储该 SSL 证书,以及如何自动安排证书的更新。我还将提到一些更高级的加快开发的技巧。

我希望本教程在您的 Streamlit 部署过程中为您节省了大量时间和压力!欢迎关注我,获取更多关于机器学习和数据科学的实践教程。感谢您的阅读!

链接:

领英:https://www.linkedin.com/in/sergei-issaev/

github:【https://github.com/sergeiissaev

https://www.kaggle.com/sergei416

中:https://medium.com/@sergei740

推特:https://twitter.com/realSergAI

了解更多关于巫班的信息:https://vooban.com/en

Azure 上简化 it 部署的初学者指南—第 2 部分

原文:https://towardsdatascience.com/beginner-guide-to-streamlit-deployment-on-azure-part-2-cf14bb201b8e

使用免费 SSL 证书在 15 分钟内在 Microsoft Azure 上部署 Hello World Streamlit 应用程序的完整指南-第 2 部分

本教程的重点将是 SSL。马库斯·温克勒拍摄的照片。

介绍

W 欢迎回到我的两部分系列的第二部分T5 】,这个系列致力于教你如何使用免费的 SSL 证书将 Streamlit 应用程序部署到 Azure。在第一部分中,我们

  • 在本地开发了一个基本的 Streamlit 应用程序
  • 使用 Docker 封装我们的 Streamlit 应用程序
  • 将我们的 Dockerized 应用程序推送到 Azure 存储库
  • 将我们的 Docker 映像部署为容器实例

我们将从停止的地方继续。本教程的重点是向我们部署的网站添加 SSL 证书。如果没有 SSL 证书,访问您页面的访问者将会收到一个明显的浏览器警告,提示连接不安全。根据客户端的浏览器设置,访问者甚至可能被完全禁止访问您的网站。

没有 SSL 证书的网站示例。作者照片。

在本教程中,我们将使用 Certbot 生成一个 SSL 证书,将该证书存储在 Azure 存储中,最后设置一个 cron 任务来自动更新我们的证书。最终,您的 minimal Streamlit 应用程序将可以通过 https 使用有效的 SSL 证书进行访问,该证书将自动更新。我们开始吧!

第 1 部分:创建卷挂载

如果我们不能存储证书,那么创建一个 SSL 证书并不是特别有用,这样当我们在进行更改后重新部署我们的应用程序时就可以访问它。如果您想走捷径,在每次启动容器实例时简单地生成一个新证书,这是不可行的,因为 certbot(我们将用于生成免费 SSL 证书的服务)限制了在一段时间内向特定域颁发的证书数量。

因此,我们将首先生成一个 SSL 证书,然后将 SSL 文件存储在 Azure 文件共享中。让我们首先使用下面的命令创建一个存储帐户(将存放我们的文件共享):

az storage account create -n NAME_OF_STORAGE -g AMAZING_RESOURCE_GROUP -l AZURE_LOCATION --sku Standard_LRS

请确保将上述命令中的变量替换为应用程序的位置和资源组,并为您的存储帐户设置一个自定义名称。请随意打开 Azure 门户以确认您的存储组在那里。

在我们的存储帐户中,我们将使用以下命令创建一个文件共享:

az storage share create --account-name NAME_OF_STORAGE --name NAME_OF_SHARE

存储名称应该与您刚才在上面创建的存储帐户相同,共享名称可以是您根据自己的喜好自定义的名称。同样,可以通过检查门户来验证您的共享是否存在。

现在是时候将这个文件共享作为卷挂载添加到我们的容器映像定义中了,它存储在 deployment.yml 中。

在此之前,我们应该记下文件共享的密码,可以通过运行

az storage account keys list --account-name NAME_OF_STORAGE --resource-group AMAZING_RESOURCE_GROUP

这个命令的输出应该会返回您的密码。该密码将用于 deployment.yml 的第 24 行(第 24 行显示为一个占位符)。

如下所示修改您的 deployment.yml。

记下所有注入了变量的行——用它们的真值替换它们。该文件类似于上一教程中的文件,只是增加了第 14–16 行和第 34–39 行。

您的容器实例现在被配置为在部署时附加一个卷挂载。这允许您的实例读写您刚才创建的文件共享。太棒了。

在对 deployment.yml 进行更改后,重新部署您的应用程序。为了方便起见,这里有一个我编写的 bash 脚本,用于在对项目进行更改后加速部署。

**#!/bin/bash** az acr login -n NAME_OF_REGISTRY
docker build -t NAME_OF_REGISTRY.azurecr.io/NAME_OF_IMAGE:v1 .
docker push NAME_OF_REGISTRY.azurecr.io/NAME_OF_IMAGE:v1
az container delete --name APP_NAME --resource-group AMAZING_RESOURCE_GROUP -y
az container create --resource-group AMAZING_RESOURCE_GROUP --name APP_NAME -f deployment.yml

这些命令将登录到您的 Azure 注册表,构建您的 Docker 映像,将您的 Docker 映像推送到注册表,删除您当前的容器实例,并在其位置部署新的容器实例。

如果您使用的是 Mac 或 Linux,只需将这些行保存在名为 deploy.sh 的文件中,然后运行

sh deploy.sh

这里有一个更巧妙的技巧:您可以使用以下命令查看正在运行的应用程序的日志

az container logs --resource-group AMAZING_RESOURCE_GROUP --name APP_NAME

请注意,Azure 的 FQDN 连接到您的应用程序通常需要大约 2-5 分钟。如果您在访问 FQDN 时出现 ERR_CONNECTION_TIMED_OUT 错误,请稍等几分钟,然后刷新您的页面。

第 2 部分:生成 SSL 证书

现在,我们的存储卷已经装载到我们的实例中,一旦生成 SSL 证书,我们就可以轻松地以持久的方式存储它。所以让我们开始发电吧!

将 run.sh 修改为以下内容:

确保用您的值替换第 6 行的变量。

这个 run.sh 配置应该运行一次,之后你的 SSL 证书应该保存在你的 Azure 文件共享中。就这么简单!它是这样工作的:

  • 第 2–3 行:启动 nginx
  • 第 4 行:启动我们的 Streamlit 应用程序。此应用程序必须在我们的 FQDN 上运行,以便使用 certbot 获得 SSL 证书。
  • 第五行:睡眠 300 秒。这很重要,因为 FQDN 可能需要几分钟时间来指向我们的 Streamlit 应用程序。如果我们的应用程序在我们的域名(FQDN 域名)无法访问。AZURE _ location . AZURE container . io),certbot 的域所有权验证将失败,并且不会生成 SSL 证书。
  • 第 6 行:使用 certbot(安装在 Dockerfile 命令中)为您的域名创建一个 SSL 证书。我花时间弄清楚了命令行标志,以确保这将为您顺利运行。只需替换 FQDN 名称和 AZURE 位置占位符。
  • 第 7 行:压缩 SSL 证书,并将其保存在卷挂载上。
  • 第 8 行:这个命令运行一个无限循环。这样,您的 Streamlit 应用程序将永远运行下去(只要您的容器实例启动)。如果没有这一行,将会生成并保存 SSL 证书,并且您的容器实例将会立即被终止。这一行确保您的 Streamlit 应用程序在 SSL 证书生成后仍然运行。

立即推送您的应用。如果您从第一部分构建了 bash 文件,您可以简单地输入

sh deploy.sh

使用以下命令检查日志

az container logs --resource-group AMAZING_RESOURCE_GROUP --name APP_NAME

您应该会看到一条来自 certbot 的消息,说明证书已经成功生成。请注意,我在 run.sh 文件中添加了一个 300 秒的睡眠命令,以便 Azure 有时间将我们的 Streamlit 应用程序连接到我们的 FQDN。如果 FQDN 没有连接到我们的 Streamlit 应用程序,certbot 的站点所有权验证将会失败。因此,请检查日志,直到您看到与下面类似的成功消息。编辑:如果认证失败,请为 run.sh 的第 5 行尝试更长的睡眠时间。FQDN 连接可能需要 10 分钟!

证书生成成功的消息。图片作者。

作为附加检查,请转到您的 Azure 文件共享并检查您的证书是否存在。

SSL 证书应该以压缩文件的形式存在于 Azure 文件共享中。图片作者。

恭喜你!您已经为您的网站创建并存储了 SSL 证书。

第 3 部分:将我们的容器指向 SSL 证书

既然 SSL 证书保存在文件共享中,我们应该更改 run.sh 文件,以便每次启动容器实例时,都不会生成新的证书(这不仅是多余的,而且会长期失败,因为 certbot 限制了每周可以分配给单个域的 SSL 证书的数量)。我们新的 run.sh 文件将是:

在第 2 行中,我们在卷挂载上解压缩 SSL 证书。然后我们启动 nginx,最后运行我们的 Streamlit 应用程序。

在我们的站点可以访问 SSL 证书之前,我们还需要添加一个更改。我们必须修改 nginx.conf 文件,指向我们在 run.sh 的第 2 行解压缩的 SSL 证书的位置。

第 47–51 行指示我们的应用程序使用 SSL 证书。确保更改路由以反映 SSL 证书的存储位置。在文件的底部,我们添加了一个规则(301 重定向,永久重定向),将任何流量从 HTTP 连接重定向到我们的域,以使用 HTTPS 连接。因此,即使我们输入 http://FQDN_NAME。AZURE _ location . AZURE container . io,我们将被重定向到https://FQDN _ 名称。AZURE _ location . AZURE container . io

现在推送我们的应用程序应该会产生一个 SSL 连接的网站。

sh deploy.sh

您可以通过尝试使用 HTTP 访问您的网站来测试 301 重定向,如果一切正常,您应该会自动重定向到 HTTPS,并在浏览器的搜索栏附近看到一个锁定的挂锁图标,表明连接是安全的。

第 4 部分:自动更新 SSL 证书

您的网站现在有一个有效的 SSL 证书。但是,certbot 生成的证书有 90 天的有效期。如果我们忽略这一点,我们的网站将在 3 个月后回到不安全的连接(或者更糟,显示一个无效的 SSL 证书错误)。由于没有使用 certbot 定期更新证书的内置方法,我们将简单地使用 cron 每月运行一次 certbot 命令。

为了实现这一点,我们只需在 Dockerfile 中添加第 26 和 28 行,它将每月执行一次认证命令(在第 12 天),并将新创建的 SSL 证书压缩到附加的卷 mount 中。

我们还必须确保 cron 是在 run.sh 文件中启动的:

用上面的文件替换您的 run.sh 文件。

完美!您现在可以高枕无忧,因为您的 SSL 证书将继续无限期更新,从而为您的所有访问者提供不间断的安全连接。

清理

为了最大限度地减少对你的 Azure 帐户的收费,删除你不再需要的资源是一个好主意。如果你想从你的 Azure 帐户中删除本教程的所有痕迹,请不要忘记删除:

  • 容器实例
  • Azure 存储帐户
  • Azure 容器注册表

结论

祝贺您完成了这个由两部分组成的教程!请记住,这种部署创建了一个无服务器的实例,这意味着您的 webiste 存在一些限制(例如,您不能设置名称服务器并注册从 godaddy 购买的域名,也就是末尾没有“. azurecontainer.io”的域名)。为了做到这一点,考虑创建一个专用虚拟网络,这将允许您更多地控制您的网络和基础设施。

我希望本教程在您的 Streamlit 部署过程中为您节省了大量时间和压力!如果你愿意,可以在评论中分享你部署的容器的链接!欢迎关注我,获取更多与机器学习、数据科学、投资和区块链相关的实践教程。感谢您的阅读!

链接:

领英:【https://www.linkedin.com/in/sergei-issaev/

github:https://github.com/sergeiissaev

https://www.kaggle.com/sergei416

中:【https://medium.com/@sergei740】T4

推特:https://twitter.com/realSergAI

了解更多关于 Vooban 的信息:https://vooban.com/en

机器学习项目的初学者基线模型

原文:https://towardsdatascience.com/beginners-baseline-model-for-machine-learning-project-f835ebd53ee0

学会标准化你的机器学习开发

附身摄影Unsplash 上拍照

机器学习开发是公司雇佣数据科学家的一个原因。企业有一个业务问题,数据科学家用他们的 ML 模型解决这个问题。然而,我们怎么知道我们的模型足以解决问题呢?或者我们甚至需要机器学习吗?。这就是我们需要基线模型的地方。

在本文中,我想向您介绍什么是数据科学领域的基线模型,以及拥有一个基线模型有多重要。此外,我们将学习一些关于如何创建基线模型的知识。让我们开始吧。

基线模型

什么是基线模型?我们可以将基线模型定义为实际模型的参考。基线模型应该是一个简单的模型,用作比较,并且易于解释。此外,基线模型应该基于数据集来创建实际的模型。

为什么我们希望在我们的项目中有一个基线模型?主要有三个原因。

作者图片

了解数据

基线模型帮助我们更好地理解我们的数据,主要与模型创建相关。在基线模型创建过程中,我们将获得一些信息,包括:

  • 数据集预测能力。预测很少或没有预测的基线模型可以指示低信号或低拟合。
  • 数据集子集分类。基线模型可以帮助我们识别数据集的哪一部分更难分类。这些信息将允许我们选择模型。
  • 数据集目标分类。观察和基线模型还提供了哪些目标值更难确定的信息。

更快的模型迭代

有了基线模型,模型开发和其他过程将变得更加容易。基线模型如何让事情变得更快?例如,您的基线模型将成为构建模型的参考,有时您的基线模型对于业务用户来说已经足够了。

性能基准

在开发实际模型时,我们使用基线模型来获得我们所反对的性能指标。有了基线模型,我们可以评估我们是需要一个复杂的模型还是已经为业务工作的简单模型。此外,我们可以使用基线模型对业务 KPI 进行基准测试。

创建基线模型

我们已经理解了基线模型以及拥有基线模型的优势;现在,我们只需要创建一个。然而,什么可以被认为是基线模型?我们可以使用任何东西作为基线模型,从简单的方法到复杂的模型。但是,一个太复杂的模型会挫败基线模型的目的——简单和快速,所以我们通常只在复杂模型是研究的基准时才使用它。

如果我们想要对一个基线模型进行分类,我会将它们分成两组:

  1. 简单基线模型
  2. 机器学习基线模型

简单基线模型

简单基线模型是一个具有简单逻辑来创建基线的模型。它可以是简单的随机模型预测或特定的基于规则的模型。关键是要有一个简单的模型,我们可以用它来对实际模型进行基准测试。

一个简单的基线模型可能来自简单的统计学、商业逻辑或各种随机模型。这些差异也可以归结为建模问题,例如:

  1. 结构化数据或非结构化数据
  2. 监督或非监督问题
  3. 分类或回归

根据定义,您可能想要不同的基线模型。但是,为了举例,让我们坚持分类表格模型问题。我将使用下面的乳腺癌数据集示例。

import pandas as pd
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.dummy import DummyClassifier
from sklearn.metrics import accuracy_score, f1_score, recall_score, precision_scoredf = load_breast_cancer()
df.keys()
X, y = pd.DataFrame(df['data'], columns =df['feature_names'] ), pd.Series(df['target'])
X.info()

作者图片

我们可以看到我们的数据集由 30 个数字列组成。让我们看看目标分布。

y.value_counts()

作者图片

正如我们在上面看到的,分布与目标 1 略有不平衡,但没有那么大。

我们希望使用当前数据集创建一个分类模型来预测乳腺癌患者;我们需要一个基线模型作为基准。现在,我们将在 Scikit-Learn 的DummyClassifier的帮助下创建各种简单的基线模型。

什么是DummyClassifier?它是一个忽略输入特征的分类器,为简单基线创建一个分类器,以便与其他更复杂的分类器进行比较。我们可以在课堂上使用不同的策略。让我们试着一个一个去探索。

首先,我将创建一个允许我们生成基线模型的函数。

#Function for evaluation metrics
def print_binary_evaluation(X_train, X_test,y_train, y_true, strategy):
    dummy_clf = DummyClassifier(strategy=strategy)
    dummy_clf.fit(X_train, y_train)
    y_pred = dummy_clf.predict(X_test)
    results_dict = {'accuracy': accuracy_score(y_true, y_pred),
                    'recall': recall_score(y_true, y_pred),
                    'precision': precision_score(y_true, y_pred),
                    'f1_score': f1_score(y_true, y_pred)}
    return results_dict

我们将通过准确度、召回率、精确度和 F1 分数来评估基线模型。然后我会尝试分割数据集。

X_train, X_test, y_train, y_test = train_test_split(X, y, random_state = 42)

让我们使用上面的函数来测试每个基线模型策略。

最频繁(模式)

这是最简单的策略,我们预测数据集中最频繁的标签。我们将目标 1 作为数据集中最常见的目标,因此分类器将始终有一个预测 1。

print_binary_evaluation(X_train, X_test, y_train, y_test, 'most_frequent')

作者图片

如果我们去掉哑分类器,预测结果类似下图。

作者图片

通过始终预测 1,我们实现了 0.62 的准确度和 0.76 的 F1 值。从机器学习的角度来看,这并不坏,但建议所有患者都患有乳腺癌会对企业有好处吗?显然不是。

至少,我们现在有了复杂模型的基线模型。让我们试试另一个策略。

制服

统一策略创建一个基线模型,该模型使用随机统一分布进行预测。这意味着所有目标成为预测输出的概率相似。

print_binary_evaluation(X_train, X_test,y_train, y_test, 'uniform')

作者图片

正如我们从上面的结果中看到的,因为基线模型预测分布是一致的,所以指标接近 50%。

作者图片

结果通常也更接近均匀分布。

分层

分层策略是创建遵循目标分布的基线模型的策略。它适用于不平衡数据,因为它反映了实际分布。

print_binary_evaluation(X_train, X_test,y_train, y_test, 'stratified')

作者图片

我们可以看到,这些指标的结果与采用统一策略的基线模型相似,因为分布几乎完全相同。

作者图片

我们可以看到,目标 1 略微主导了结果,因为它是主导标签。

总的来说,简单基线模型是一种忽略输入数据并且只关注预测结果的预测模型。如果我们使用上面的简单基线模型作为基准,我们可能希望比只预测每个人都患有乳腺癌的模型更好。

还有另一种方法来开发基于业务逻辑的简单基线模型,但是它需要领域知识和业务理解。我在另一篇文章中写过这个话题,你可以参考一下。

机器学习基线模型

基线模型不仅仅是一个简单的基线模型,你也可以实现一个机器学习模型。与 ML 基线模型的不同之处在于,您仅在针对比基线模型更复杂的模型时使用它。

例如,您希望使用 XGboost 模型进行预测,因此您的机器学习模型可能是决策树模型。

如果你是一个新模型的研究人员,你会想要最先进的模型作为基线模型。

无论哪种方式,你都可以有一个机器学习模型作为你的基线模型,但总是用它来测试你的实际模型。

自动化基线模型开发

使用名为 dabl 的 Python 包来自动化基线模型开发是可能的。它是一个简单的包,迭代了许多简单的基线和机器学习模型。

让我们尝试使用 dabl 包。首先,我们需要安装软件包。

pip install dabl

然后,我们将使用下面的代码来开发基线模型。

sc = dabl.SimpleClassifier().fit(X_train, y_train)
print("Accuracy score", sc.score(X_test, y_test))

作者图片

该模型将运行到所有基线模型,并带有基本的度量信息。现在由我们来决定如何翻译基线模型信息。也许基线模型已经很好了,我们不需要复杂的模型?这当然有可能发生。

结论

基线模型是数据科学项目的一个重要方面,因为它可以在以下方面为您提供帮助:

  • 了解您的数据
  • 更快的模型迭代
  • 性能基准

根据您的数据科学项目问题,有许多方法可以开发您的基线模型。大多数时候,我们可以将基线模型分为两种类型:

  • 简单基线模型
  • 机器学习基线模型

希望有帮助!

在我的 LinkedInTwitter 上访问我。

如果您喜欢我的内容,并希望获得更多关于数据或数据科学家日常生活的深入知识,请考虑在此订阅我的 简讯。

如果您没有订阅为中等会员,请考虑通过 我的推荐 订阅。

正确选择 Spark API 的初学者指南:rdd、数据帧和数据集

原文:https://towardsdatascience.com/beginners-guide-for-choosing-the-correct-spark-api-rdds-dataframes-datasets-23c94041f575

何时使用 rdd、数据帧和数据集?激发正确的选择!

📷露西·希斯Unsplash 拍摄的照片

介绍

当开始使用 Spark 编程时,我们将可以选择使用不同的抽象来表示数据——灵活地使用三种 API(rdd、数据帧和数据集)中的一种。但是这个选择需要小心处理。随机选择 API 会影响 ETL/ELT/ETLT 管道和分布式集群的性能。

我在粗体中强调了 Spark 架构中使用的关键点和有用术语。

动机

我最近一直在与 Spark 合作,并有机会研究和体验不同 Spark APIs 的优缺点。

我也使用过熊猫在进入 Spark 之前提供的数据结构。对于处理大数据用例,与小数据项目相比,我们需要有不同的思维模式。

本文将对那些经历类似的向分布式数据领域过渡的人有所帮助。因此,我想分享我在处理跨多个节点的大数据项目时如何选择合适的 API 的经验。

Spark 中使用的基本术语

Spark 中使用的 API 利用了这两个基本术语:

A.分布式执行-驱动程序和工作程序节点

在 Spark 架构中,使用两种类型的机器/节点/计算基础设施,即驱动程序和工作程序来支持并行执行。

把它们想象成我们如何解决一个大型拼图游戏:

a)我们可以同时开始处理它的不同部分。在 Spark 架构中,它是一组同时处理任务的机器/节点(也称为工作节点)。

b)然后我们连接/还原结果,以从拼图中获得完整的图片。在 Spark 中,最终结果被发送回用户应用程序可以使用的驱动节点

B .惰性评估-转换&动作

用 Spark 编写的代码被分成转换动作。两者都是基于 spark 函数的形式,但不同之处在于它们的使用方式。
转换的谱系有向无环图(DAG) 的形式收集,并在驱动节点触发动作时执行。在 DAG 的帮助下,Spark 可以进行关键优化,以减少执行时间并提高节点集群的性能。

在并行计算中,考虑下面的 Spark 命令,它过滤一个大的文本文件,并在第一行搜索一个特殊的单词。

为什么懒在火花好![图片由作者提供]

所需的数据量远远少于查询的数据量,在这种情况下,第一行是需要考虑可以应用过滤器的数据。因此,通过整理转换 Spark 将构建一个最佳计划来一起执行它们。这也减少了驱动程序和工作节点之间的往返次数,减少了它们之间所需的数据 I/O 量。

在 Spark 中与三个火枪手(API)合作

这一节深入探究了三个火枪手(即 RDDs、Dataframes 和 Datasets)的细微差别。引入它们是为了处理将跨节点分布的数据。

它们作为 Spark 中的特性被引入的时间线同样重要。它解释了一个 API 的缺点如何成为优化后续 API 的触发因素。

在接下来的四个小节中,我们从 rdd 的用例开始,然后分别阐述 Dataframe 和 Dataset API,最后讨论 Dataset 与 Dataframe API 的统一以及何时使用这些 API。

1.RDD(弹性分布式数据集)

rdd 是 Matei Zaharia 等人在 2012 年作为内存计算的容错抽象提出的(会议资源)。

随着 RDD 在 Spark 体系结构中的引入,与使用细粒度读/写转换的分布式共享内存系统相比,它显得更加有效。

缩写 RDD 可以拆分来理解它的定义:

  • :数据的处理方式是容错的,Spark 能够在数据损坏的情况下随时重建数据。这是由于在 Spark 操作中使用的有向无环图(DAGs)
  • 分布式数据集 :我们通过 Spark 上下文馈入 Spark 的数据将被存储为分区。

它们是 Spark 优化引擎使用的低级 API。需要注意的重要一点是,Spark 中的大多数查询最终都会简化成这种形式,因此它确实是 Spark 中的低级 API。

这是为开发人员在分布式架构中实现容错而引入的,这是通过在节点集群之间使用受限形式的共享内存来实现的,基于形成谱系的粗粒度转换,而不是依赖于细粒度更新。

DAGs 在 Spark 中带来容错行为[图片由作者提供]

何时使用 rdd?

  • 当您处理需要在行/记录级别转换特殊数据结构(文本或媒体文件)的操作时。
  • 当在粒度级别修改数据的灵活性更重要时。
  • 当模式变得与您的用例无关,但并行化会有所帮助。
  • 当您不打算使用**特定于领域的表达式时(想想 Spark SQL 抽象)****

何时避免使用 rdd?

  • 当您想要强加模式并使用 Spark catalyst 优化以及列名访问时。
  • 当你想为简单的 API 操作避免复杂的编码结构时,例如寻找一个文件中单词的平均频率。

2.数据帧

Spark 1.3.0 版本(2015 年初)中引入了数据帧。它是 RDDs 的高级抽象,由一个模式提供支持,该模式还允许 Spark 使用 Catalyst optimizer 在运行时执行更多的自动化优化。

当连接两个 rdd 时,由于催化剂优化器的存在,将它们转换成数据帧可能是有益的。它使用 Scala 中的准引号和模式匹配来加速执行过程。

可以使用以下方式创建数据帧:

  • 从 RDDs 使用 inferSchema 选项(或)使用自定义模式。
  • 来自不同格式的文件(JSON、Parquet、CSV、Avro 等。).
  • 从数据集中使用 隐式转换***toDF***的方法。**

数据帧的非类型化本质——运行时的类型检查

数据帧是一组保存数据的通用行对象,它们有类型。单词 untyped 表示对数据帧进行类型检查的时间。仅在 运行期间 根据用户推断或定义的模式完成。

数据框架的缺点

  • 它无法通过优化有效地使用 UDF。
  • 缺乏 Scala/Java 中可以实现的强类型。

3.数据集

Spark 1 . 6 . 0 版(2016 年初)引入了数据集。它本身带来了在 编译时 进行强类型检查的优势。

引入类型安全的基本概念是通过编码器的引入,它可以将类型 T 的 JVM 对象转换成内部二进制表示。也是序列化&反序列化( SerDe )框架编码器表示记录的模式,这避免了 JVM 对象的不必要的转换。它强制执行从域对象到内部二进制表示的映射。与 Java 或 Kryo 序列化相比,它们提供了超快的转换。

数据集的类型化本质——编译时的类型检查

强类型数据集 API 带来了使用 Scala 中的 case 类或 Java 中的 bean 对象来创建将在编译时强制执行的模式的优势。

只有数据集才有检查语法和分析错误的能力。

数据框架和数据集 API 中的类型检查[图片由作者提供]

这种强大的类型检查将节省开发人员的时间和成本。

数据集的特征

  • 对半结构化数据的无缝支持。
  • 编译时类型安全(语法+分析错误)。
  • 编码器提高了序列化/反序列化的速度。
  • Java 和 Scala 的单一 API。

4.数据集和数据框架 API 的统一

Dataset 和 Dataframe 是独立的 API,直到最后两个火枪手在 Spark 2.0.0 版本(2016 年末)中组合成了统一的 Dataset API** 。**

这种统一将 rdd 和 Dataframe APIs 的优点结合在一起。

数据框架和数据集 API 的统一(Spark 2.0+)[图片由作者提供]

Dataframe 成为了**Dataset[Row]**的类型别名。就语言而言,数据帧仍然是 Python 语言的主要抽象,因为它们类似于单节点数据帧。在 Scala & Java 中,datasets 代表 API 的类型化版本,dataframe 是非类型化版本。

何时使用统一数据集[Dataframe / Dataset] API?

  • 当我们计划在特定领域的抽象(聚合、连接等)上使用高层抽象时。)和模式实施。
  • 列访问,lambda 作用于半结构化数据。
  • 为了在编译时进行更高级别的类型安全检查,我们可以使用统一数据集 API 的类型化版本。
  • 受益于钨代码生成(使用 dataframe/SQL 操作符 )** 的更快表达式求值。**
  • r 建议用户使用数据框架(数据集不可用)。
  • Python 用户也可以使用数据框架(数据集不可用)。

结束语

毫无疑问,对于大数据用例来说,一种通用的 API 是不存在的。关键的一点是,我们要根据我们面临的场景选择正确的 API:输入文件的类型、选择的编程语言、将要执行的处理类型以及流程中的操作量。

另外,请注意,这三种类型之间的转换是无缝的,可以使用简单的方法调用来完成。因此,如果您注意到使用特定的 API 在速度和效率方面是有益的,那么转换将是利用其优势的最佳选择。

在撰写本文时——在 Spark (3.2.X)的最新版本中,有更多关于 API 进一步标准化的讨论,Python 中熊猫 UDF 的优化以及 PySpark 中对熊猫 API 的支持。谈到 Apache Spark,变化的可能性是无穷的。

你可以在 LinkedIn 上与我联系,进行简短的交谈。

你可以在这里 阅读我的其他文章 。下次见!

扩散模型入门指南

原文:https://towardsdatascience.com/beginners-guide-to-diffusion-models-8c3435ccb4ae

对人工智能生成的艺术如何通过稳定扩散、中途或 DALL-E 制作的直观理解

用稳定扩散生成的莎菲朋克吧。图片由我提供。

最近,人们对 OpenAI 的 DALL-E、Stable Diffusion(DALL-E 的免费替代品)和 Midjourney(托管在 Discord 服务器上)的兴趣越来越大。虽然人工智能生成的艺术非常酷,但更吸引人的是它最初是如何工作的。在最后一部分,我将包括一些资源,供任何人在这个人工智能艺术空间开始。

那么这些技术是如何工作的呢?它使用了一种叫做潜在扩散模型的东西,其背后的想法其实很巧妙。

什么是扩散模型?

本质上,这是一个两阶段的过程。

首先,它破坏输入,直到只剩下噪声。

其次,我们使用神经网络从噪声中恢复输入,以产生新生成的图像。

记住前面提到的核心思想,让我们看看架构(参考这个链接获得全文)。

用潜在扩散模型合成高分辨率图像:【https://arxiv.org/pdf/2112.10752.pdf】T2。我做的附加注释。

了解该体系结构中的某些部分非常重要。有相当多的符号,所以让我从分解它们开始。

我们从 x 开始,这是原始图像。我们把它输入到网络中的编码器,在那里它将被编码到一个叫做 z 的信息密集空间。

然后,我们将经历一个前进的过程,在这个过程中,我们对文本进行扩散和调节。该机制将文本嵌入与我们已经处理的图像相结合,并且合并的输入是扩散过程的初始噪声的一部分。

在此之后,它将通过一个神经网络,主要是预测图像中噪声的 UNet(卷积神经网络的一种形式)。

最后,通过解码器重构噪声,产生你想要的图像。

在这里,我想强调一下我认为该架构最重要的三个部分:

  1. 扩散的正向过程
  2. 神经网络本身
  3. 调节方面

正向过程

概括地说,扩散模型通过逐渐增加噪声来破坏一些输入。这个转发过程可以使用 马尔可夫链 来完成。

马尔可夫链表示

由于添加噪声的过程是一系列事件,其中每个时间步都依赖于前一个时间步,因此我们可以使用马尔可夫链。

图一。向图像添加噪声的公式。我的插图。

对于一个特定的图像,x₀,我们可以通过添加一系列噪声,特别是高斯噪声来创建一个有噪声的图像。

高斯噪声

噪声采样方式实际上可以用以下公式描述:

图二。噪声方程。我的插图。

这是一个有条件的高斯分布,取决于前一个图像和一个特定的方差。这里描述了分布的均值和方差。

让我们更仔细地看看这个等式。贝塔序列被称为方差表,它描述了我们想要在每个时间步长添加多少噪声。把它想象成一张关键是时间的地图,值基本上就是你想产生多少失真。

请注意,平均值总是基于之前的图像,因此每次添加噪声时,基本上都是对之前的图像进行细微的调整。这使得小的修改进一步扭曲了图像。

贝塔

那么贝塔到底是什么?为了理解 Beta,让我们首先快速回顾一下图像是如何工作的。我们知道图像是由像素组成的,每个像素有 3 个通道——(R)ed,(G)green,(B)lue。

假设我们有一个纯绿色的像素(-1,1,-1) [R,G,B]。我们采用特定的通道(绿色)并应用图 2 中的等式。

回顾过去,我们观察到,选择更大的β意味着像素分布更宽,因为方差更大。然而,这也意味着正态曲线进一步向 0 移动,因为均值项受到影响。

因此,当图像偏离原始图像越来越远时,图像会变得越来越糟糕。

噪声调度

在每个特定的时间步长 t,将会应用特定的β值。这个贝塔序列被称为噪声时间表。

目的是添加适量的噪声,这样我们可以得到均值为 0 且在所有方向上方差固定的各向同性高斯分布。这使得去噪过程运行良好。

有许多策略来执行噪声调度,包括但不限于:

  • 线性的
  • s 形的
  • 二次的

神经网络

现在我们已经讨论了正向过程,让我们来讨论如何“反转”整个序列并预测只有噪声的图像。

这就是神经网络派上用场的地方。把它想象成去噪,一步一步地去除图像的“杂质”,直到它恢复或产生非常好的图像。神经网络在取自 LAION-5B 的成对图像和标题上进行训练,LAION-5B 是一个公开可用的数据集,来自于从网络上搜集的常见爬行数据。

我们预测噪声而不是整个图像本身的原因是它在计算上更可行。这是因为一幅图像有大量的复杂性,而噪声只是噪声。

图三。去噪示例。我的插图。

考虑图 3 中所示的例子。在这里,我们有一个非常嘈杂的图像在时间步骤 200,这应该揭示一个坚持的人,如果你完全降噪的图像。神经网络预测我们在(1)处看到的图像上的噪声,并产生噪声作为(2)中所示的输出。

之后,我们从有噪声的图像中减去噪声,得到一个棍子人的模糊的图像。

图 4。迭代循环。我的插图。

我们在 for 循环中一直这样做,直到最终到达原始图像。

拼图的最后一块是实际生成带有文本的特定图像。这可以通过最后一种机制——调节来实现。

调节

让我们以嘈杂的图像为例,但这次我们也添加了“一个笑脸”的文本提示,如图图 5 所示。

图五。带文本提示的噪声图像。我的插图。

它通过神经网络,将再次预测噪声,但它将使用通过训练获得的笑脸的相关潜在空间表示来预测噪声。

本质上,它对笑脸产生的噪音有一个粗略的概念,并将其纳入预测。

我们再次减去噪声,从时间步长 200 到 199。我们像以前一样,反复重复这个过程,但是这次再次输入文本提示,聚焦并放大我们想要的对象——一个笑脸。

附加技巧

为了更好地得到我们想要的,我们可以使用一些额外的技巧。我们可以利用无分类器指导(CFG)来使输出更加依赖于提示。

当你自己玩稳定扩散时,你可能会看到一个叫做 CFG 的滑块,这个值越高,就越接近你的描述。

图六。输入两次。我的插图。

我们通过向神经网络发送两次输入来做到这一点,一次是带有文本嵌入的的,一次是没有文本嵌入的,如图 6 中的所示。

图 7。求差以得到笑脸的更好表示。我的插图。

这会产生两组噪声图像,我们可以取其差值并将其馈入网络以放大该信号,如图图 7 所示。

将一切拼凑在一起

作为用户,我们希望为模型提供文本提示,以生成我们想要的图像。这种方法被称为 txt2img。

典型的提示结构如下:

"[主要主题的[图片类型],[样式提示]"

通过给模型输入提示,我们实际上是在使用模型的条件和神经网络部分来产生我们想要的图像。使图像有噪声的前向过程仅用于训练,而不是我们在此阶段所关心的。

至此,我们对这项技术的工作原理有了更好的理解。如果您想亲自尝试,请查看以下资源:

感谢您阅读另一本初学者指南。例如,如果你对卷积网络的工作方式感兴趣,一定要看看我写的另一篇文章这里简单地解释了一切。

逻辑回归初学者指南

原文:https://towardsdatascience.com/beginners-guide-to-logistic-regression-eb1e9af717ae

它是什么,如何工作,何时使用

如果你想进入机器学习领域,逻辑回归是构建知识工具箱的必备工具。这是机器学习的基本构件之一。逻辑回归对于机器学习来说是一个简单而强大的工具。你会发现逻辑回归到处都在使用,无论是在工业界还是学术界。如果你正在开发在专业或研究环境中使用的机器学习技能,你需要对逻辑回归了如指掌。

让我们浏览一个示例数据集。为了简单起见,数据将是 2D,我们将只处理两个输出类,蓝色和橙色。

(作者的图表)我们的数据集的绘图,由输出类着色

逻辑回归本质上是线性分类。它不是试图找到数据集的线性近似,而是旨在找到一个线性分类来将数据集分配给输出类。它基本上找到了在 N 维空间中分隔两个类的最佳线

如果数据点位于与其类别相对应的线的一侧,则该数据点被正确分类。这也可以定义为从点到线的距离与类具有相同的符号。

(作者提供的图表)描述了点到线的距离计算

N 维向量空间中的一条线可以由有向单位向量 m 和偏置向量 b 定义。对于线上的每个 N 维点 x ,以下等式成立:

N 维向量空间中从点 p到具有方向单位向量 m 和偏置向量 b 的直线的距离d定义为:

逻辑回归:问题的定义
逻辑回归:最小二乘误差有用吗?
【逻辑回归:使我们的步骤函数连续
逻辑回归:寻找最优解
总结逻辑回归

逻辑回归:问题的定义

我们希望优化分类线的斜率和偏差,以便最大限度地减少错误分类的点数。距离仅用于计算每个点在线的哪一侧,因此最终我们可以计算给定线的分类误差。

数据集之间的分类线示例(按作者分类的图表)

如果我们想要优化分类线,你可能会认为我们需要优化 mb ,但是有一种方法可以建立距离方程,所以我们只处理 m 。我们可以通过将 m 扩展到一个额外的维度来将偏差吸收到 m 中。这个维度就是偏差。

首先,我们来思考一下 mb 是什么。 mb 都是具有相同方向性但长度不同的向量,因此我们可以将它们表述为

如果我们将 m*a 代入 b 的距离方程,我们得到如下结果:

由于 m 是一个单位向量,并且任何单位向量乘以自身的形式

等于 1,根据单位向量的定义,我们也可以将其简化为以下形式。

通过吸收偏差,我们用-a 项扩展 m,用 1 扩展 p,因此我们得到:

如果我们现在使用新的注释计算距离,则:

从这一点开始,为了简化公式,我们假设 m = m'p = p'

逻辑回归:最小二乘误差有用吗?

在我们的数据集中,我们有一组点 P 和标签 Y,其中

如果我们有一个标签为 0 的点,我们希望该点和分隔线之间的距离为负。或者,如果标签为 1,则距离应为正。

我们可以通过计算出的每个点到分类线的距离来预测标签。

(作者提供的图表)预测输出与距离的关系

现在我们已经有了问题的恰当表述,我们要优化 m 。为了做到这一点,我们需要尽量减少被错误分类的点的数量。在线性回归中,我们使用了最小二乘误差函数,所以让我们在这里尝试一下。

为了优化它,我们对 m 求导,并设它等于零。遵循链式法则:

这个公式的问题是, f 相对于 m 不可微,因为它是一个不连续的阶跃函数。此外,即使 f 可微,它也不是线性的。我们不能直接求解最优 m 的导数,所以我们需要不同的映射函数和新的方法来寻找最优 m

逻辑回归:让我们的阶梯函数连续

让我们首先来看看我们如何写 f ,这样它就非常类似于上面定义的阶跃函数,但是是可微分的。为此,我们将使用一个 sigmoid 函数

sigmoid 函数绘制如下。

(作者提供的图表)按距离对预测输出进行 sigmoid 叠加

你会注意到,它看起来非常类似于一个阶跃函数,如果你以一种连续的方式连接两个不同的部分,这正是我们使用它的原因。

误差函数的一个关键特征是误差值应该与我们离最优解的距离成比例。在线性回归的背景下使用最小二乘误差函数,这一点非常清楚,因为误差值就是最佳拟合线与给定数据点的精确距离。

然而,在逻辑回归的情况下,这些值具有非常有限的范围,即从 0 到 1。因为我们的潜在输出值是如此有限,预测标签和实际标签之间的最大差异是 1。因此,最小二乘误差的范围是从 0 到 1,这是次优的。理想情况下,我们会有一个明显更大的范围,最好是从 0 到无穷大,就像线性回归一样。

使用 sigmoid 函数时,更好的误差函数选项是对数丢失误差

日志丢失错误映射示例

如你所见,这个误差函数允许误差从 0 到无穷大,但你也应该明白,如果我们试图推导这个关于 m 的损失函数,结果将不是线性的。这意味着我们不能使用封闭形式的方法来寻找最佳的 m*。

逻辑回归:寻找最优解

为了解决这个优化问题,我们将使用梯度下降来代替。梯度下降法只需要一个可微的凸误差函数来保证最优解。我们的误差函数很好地满足了这两个要求,所以让我们开始研究吧。

梯度下降迭代地更新向量 m,以便接近最优解 m*。它通过每次迭代在误差导数的方向上迈出一小步α来实现。

阿尔法通常被称为学习率。如果误差收敛到零,我们就找到了最优解 m*。要了解更多关于梯度下降背后的理论,请查看这个深入研究梯度下降如何工作的

总结逻辑回归

我们从线性回归的公式开始,并对其进行转换,以便我们可以将其用于分类问题,从而产生逻辑回归。通过线性回归和逻辑回归,我们现在可以为所有监督机器学习问题建立模型!

需要注意的一点是,我们在这个演练中使用了一个二进制示例,这意味着输出中只有两个类。在实际的数据集中,通常有两个以上的输出类。适应这些多个输出类意味着改变问题的表述。我们将使用多个映射函数 F,

对于设置输出类别 S 中的每个类别,使用软最大值对输出进行归一化。请关注我的下一篇文章,它将介绍一个多类输出的逻辑回归示例。

如果有任何问题,请告诉我!

公开招聘自由职业技术写作和代笔工作:margo.hatcher.writes@gmail.com。我专注于数据科学和前端编程。

大数据机器学习入门指南

原文:https://towardsdatascience.com/beginners-guide-to-machine-learning-with-big-data-d6dbb155673c

使用 Google Cloud 和 Spark ML 处理大型数据集的教程

约书亚·索蒂诺在 Unsplash 上拍摄的照片

GitHub 代码

学习数据科学和在专业环境中实践数据科学的最大区别之一是我们正在处理的数据的规模和复杂性。

当我们第一次开始学习时,我们构建第一个项目所用的数据可能是适度的、干净的、易于理解的。在本地机器上使用第一个数据集很容易,用 Pandas 进行计算,或者用 Matplotlib 进行可视化,几乎都是瞬间完成的。

不幸的是,这是一个田园诗般的乌托邦,很少(如果有的话)存在于专业界。随着计算能力( )摩尔定律 )和存储容量( 克莱德定律 )的效率提高和价格下降,企业能够存储、分析和利用的数据比以往任何时候都多。

摩尔定律图。1970–2020.图片来自维基百科。

作为一名新晋的数据科学家,与我们所学的规模适中的数据集相比,处理不太适合本地机器的数据是一个巨大的变化。我们每个人都曾在某个时候试图将一个巨大的数据集加载到熊猫中,并耐心等待,只为内核在抗议中死去。幸运的是,当这种情况发生时,我们有选择!

在本教程中,我们将讨论两种用于处理海量数据集的常用工具— 谷歌云存储Apache Spark一旦我们为这些解决方案建立了一个概念基线,我们将通过一个例子来使用存储在 Google Cloud 中的大型数据集和 SparkML 的建模功能创建一个基本的回归模型。让我们实现它吧!

什么是“大”数据?

在深入了解 Spark 和 GCS 之前,让我们先了解一下“大数据”到底是什么。我能想到的最一致的大数据定义如下:无意义的行话

大数据的概念是一个移动的目标。正如我之前提到摩尔定律和克莱德定律时提到的那样,对更高数量的计算和存储容量的相对可访问性正以大约每两年 2 倍的速度增长。这意味着 2 年前的“大数据”按照目前的标准可能还不算大,10 年前的“大数据”对于现代机器来说可能微不足道。

彼得·赫尔曼Unsplash 上拍摄的照片

“大数据”也完全特定于个体数据从业者。判断某样东西是否是大数据的一个简单的经验法则是,它是否适合你的电脑,而如今电脑有各种不同的配置——我的 MacBook 有 16 GB 的内存,8 核英特尔处理器和 1 TB 的磁盘存储。我的 Windows 桌面有 64 GB 内存,16 核英特尔处理器,12 TB 磁盘存储(加上一个 GPU 下次再说)。可以理解的是,这些机器可以处理不同数量的数据。

因为个人电脑有如此多不同的风格,我们需要在单个项目中使用大数据技术的情况将取决于我们所拥有的能力。

但一般来说,有企业级数据需求的公司也买得起企业级机器。有时,公司的需求超过了任何一台机器能够提供的能力,无论是计算能力还是磁盘存储。当这种情况发生时,像谷歌云存储Spark 这样的解决方案开始发挥作用。

Jakub Skafiriak 在 Unsplash 上拍摄的照片

火花

最基本的,Spark 是一个开源项目,旨在帮助跨集群并行处理大量数据。什么是集群?想想你的电脑。现在想一想你的两台电脑。我们可以将这些计算机连接起来,将磁盘空间、计算能力和内存容量集中到一台“计算机”中,用它来做事情。这是一个(非常基本的)集群。

Spark 帮助我们跨集群执行数据处理任务。为了做到这一点,Spark 创建了一个有向无环图 (DAG),作为数据如何转换的“行动计划”。Spark 不是存储这个行动计划的结果,而是将行动计划本身存储在内存中,并且直到它被明确告知要持久化它时才存储结果。这是与熊猫等工具的主要区别之一。

Spark 和传统工具的另一个主要区别是 Spark 使用分布并行的方式。正如我前面提到的,Spark 的主要功能是帮助我们跨集群执行数据处理任务。Spark 在这项任务上比传统工具更高效的部分原因是它使用了分布式存储和并行计算。

Pandas、NumPy 和其他核心 Python 库针对单核计算进行了优化,而 Spark 则利用它创建的 Dag 来寻找完成给定任务的最佳计算路线。

回想一下,集群是我们的两台笔记本电脑相互连接,作为一台“计算机”使用。当我们利用 Spark 处理数据时,Spark 将获取“大块”数据(默认为 128 MB),并将它们存储在集群的多个位置。将你的数据分成更小的片段并存储在集群中的过程被称为数据分片。我们对数据进行分片,并将每个分片存储在集群的多个位置,以实现冗余性和弹性。值得一提的是,Spark 的分布式存储方法是 Hadoop 分布式文件系统(HDFS)的一个分支,了解 Hadoop 和 HDFS 是什么是值得的,但我们不会在这里深入讨论。

与 Spark 分布数据存储的方式非常相似,它也分布您想要在数据上运行的计算,并并行执行它们。正如我上面提到的,像 Pandas 和 NumPy 这样的 Python 库默认使用单个 CPU 内核运行。另一方面,Spark 使用机器上的所有内核。在集群环境中,这意味着 Spark 会将您的数据分解成更小的碎片,然后在每个碎片上并行执行计算,如果您使用传统的数据操作工具,这将大大减少获得结果所需的时间。

最后值得一提的是,Spark 可以部署在单台机器上(比如您的笔记本电脑)。这样做的好处是,它可以更有效地利用您的 RAM,并在可能的情况下跨所有 CPU 内核并行化计算。如果您的数据集特别大,Spark 也会将它从 RAM 溢出到磁盘,尽管这会影响性能。

Unsplash 上由 Daoudi Aissa 拍摄的照片

谷歌云存储

现在我们已经了解了如何用 Spark 处理数据,下一个问题是我们将在哪里存储数据。处理存储在本地的大型数据集会很快耗尽你的磁盘空间,像 GitHub 或 Google Drive 这样的选项不适合处理超过几百 MB 的文件。进入谷歌云存储。

谷歌云存储是一个基于云的对象存储服务。在不涉及太多技术细节的情况下,对象存储意味着将非结构化对象存储在一个易于访问的地方。对象通常包括数据本身、关于对象的一些元数据以及使其区别于其他对象的唯一标识符。例如,将对象存储与数据库进行对比。对象存储对于需要经常更改的事务性数据来说并不理想。但它在这里会工作得很好。

所有主要的云提供商都提供对象存储——亚马逊 S3、Azure Blob 存储、谷歌云存储..都一样。一般来说,云的好处在于它的可伸缩性和高正常运行时间。这是什么意思?当您的硬盘空间已满时,您需要删除一些项目来添加更多内容,或者购买额外的驱动器。当使用云服务时,你基本上是租用你的提供商的计算能力和磁盘存储。如果您需要的比您目前拥有的更多,您的提供商会自动调整您的资源。从这个意义上说,云服务是无限可扩展的(实际上来说)。

同样,云服务也极具弹性。凭借这些公司的全球基础设施足迹,您可以放心,您的数据不会在云中丢失(除非发生一些灾难性事件,但您可能会遇到更大的问题)。如果您的本地机器死机,您的数据可能无法恢复。如果云提供商的一部分基础设施出现故障,有许多级别的冗余和故障转移功能来保持您的数据随时可用。

如果我没有提到云服务是要花钱的,那我就失职了。每个主要的提供商都有一个免费层,并提供一些积分让你开始使用一个新帐户,但当使用云服务时,很容易积累大量的账单。如果您正在使用云服务,请始终关注您的计费中心报告并设置预算限制

设置

现在我们对 Spark 和 Google 云存储有了一个概念性的了解,让我们在一个简单的演示中让它们为我们工作。下面,我将介绍清理存储在谷歌云存储中的大型数据集的过程,并使用 Spark 建立梯度增强回归模型。但是在我开始之前,让我们先看一下在开始编码之前需要完成的先决步骤。

维克多·塔拉舒克在 Unsplash 上拍摄的照片

数据

对于这个例子,我使用的数据来自加州理工学院美国宇航局喷气推进实验室。他们维护着小天体数据库,这是一个包含超过 120 万个太阳系已知小行星观测数据的数据集。每一次观测都包含 30 多个特征,我们将使用这些数据来尝试使用 SparkML 预测小行星的直径。该数据集是免费供公众使用的,对于一个适度的“大数据”项目来说是一个很好的选择,所以去看看吧。

Google 云设置

如果我们要使用云存储,我们需要设置一个谷歌云账户。

  1. 导航到谷歌云注册页面,使用你的谷歌账户创建一个 GCP 账户。公平的警告:创建帐户时,您需要提供一张信用卡。前 90 天你还可以获得 300 美元的积分,所以你不应该马上被收费。
  2. 创建 GCP 账户后,导航至谷歌云控制台。它应该是这样的:

谷歌云控制台。图片作者。

3.从 Google Cloud 主页,进入左侧边栏的云存储选项:

图片作者。

4.在谷歌云存储上,点击‘创建一个存储桶’。这将带您进入如下页面:

图片作者。

命名您的存储桶,选择您所在的地区,并决定您要为您的数据使用哪种存储类别。访问管理是保持公司云实例安全的一个非常重要的方面,但是对于初次尝试使用个人云实例的人来说,粒度 IAM 就不太需要了。统一访问和 Google 管理的密钥是访问和保护的良好选择。

在此页面的右侧,您应该会看到以 GB/月为基础的存储桶价格估算。这一点值得注意,因为一旦你的信用用完或 90 天试用期结束,这将是保持水桶运行的成本。

5.一旦您创建了您的 bucket,我们就需要获得一个访问键来在我们的代码中使用,以便我们能够访问我们的云实例上的数据。打开左上角的导航菜单(三个横条),点击出现的侧边栏中的 IAM & Admin ,然后点击服务账户。你应该在这样的页面上:

图片作者。

创建一个服务帐户,并给它起一个合适的名字。在第 2 步中,我们希望授予该服务帐户对我们的存储对象的访问权限,因此使用下拉菜单授予它该级别的权限。找到云存储选项,然后存储对象管理:

图片作者。

完成服务帐户创建过程,应该会返回到包含新创建的服务帐户的表。点击账户 ID** 访问详细信息,然后点击顶部的【密钥】选项卡。应该是这样的:**

图片作者。

点击‘添加密钥’>‘创建新密钥’>JSON。这会自动将密钥下载到您的本地机器。保持这个安全!非常注意你的密匙最终在哪里,例如,永远不要在 GitHub repo 上公开发布它。我们将介绍如何将它们隐藏在下面。

加载数据

下载完密钥后,返回云存储页面并创建一个存储桶。恰当地命名。在那里,创建一个文件夹,并将您的数据添加到该文件夹中。我下载了。csv 格式的小行星数据来自 JPL 网站,创建了一个桶,一个名为小行星的文件夹,并上传了。csv 到文件夹中,然后从我的本地机器上删除它。这是一个简单的过程,与 Google Drive 上传没有什么不同,所以应该不会有任何问题。

火花设置

现在我们已经设置好了 Google 云存储,是时候在我们的机器上安装 Spark 了。在 Mac 上安装 Spark 需要自制。如果你还没有安装家酿软件,请按照这里的指示进行安装。

一旦安装了 homebrew,我们将使用它来安装 Spark 及其依赖项。在命令行提示符下输入以下内容:

brew install java scala apache-spark

接下来,我们需要为 Spark 安装 Python 包装器, PySpark。根据您使用的是本地级别的 Python 还是 conda 环境,您可以执行以下任一操作:

pip install pysparkconda install -c conda-forge pyspark

打开一个新的终端窗口。如果一切正常,输入命令“pyspark”应该会启动一个 spark 实例(注意:如果您使用的是 conda,请在测试 pyspark 之前激活 conda 环境)。

如果在命令行中一切正常,请尝试在 iPython 环境或 jupyter 笔记本中激活 Spark:

import pyspark  
spark = pyspark.sql.SparkSession.builder.getOrCreate()

如果这也正常工作,您就可以开始工作了。如果没有,请对您的问题发表评论。通常归结为 Java 安装和/或路径变量的问题。

代码走查

此时,我们已经将我们的小行星数据存储在 Google Cloud 中,将我们的 Google Cloud 密匙存储在我们的本地机器上,并且已经安装了 Spark/PySpark,可以使用了。我们应该有开始编码所需的一切。让我们看一下我们将要使用的库:

一旦导入了我们需要的所有内容,我们需要创建一个配置为与 Google Cloud 协同工作的 Spark 会话:

这里要注意两件事:首先,你应该设置你的内存配置来匹配你的机器。第二,我们如何指定我们想要对 Spark 实例使用 Google Cloud service 帐户密钥文件,并指定 secrets.json 文件包含相关信息。

这里发生的事情是,我在前面的步骤中从 Google Cloud 下载了密钥文件,将其添加到 GitHub repository 文件夹,然后将其添加到。gitignore 文件,这样它就不会提交到我的公共存储库中。我还将其重命名为 secrets.json,以便在代码中更容易指向它。因为我编写的 Jupyter 文件在同一个文件夹中,所以我可以参考 secrets.json 文件来获得我的 Google 云服务帐户凭证。

接下来,我需要阅读。我将 GCS 中的 csv 文件存储到 Spark 中:

为了再次检查一切是否正常,让我们以熊猫的方式预览一下数据:

虽然 Spark 在 Pandas 中很容易查看,但我们不会用典型的 Pandas 语法进行数据操作。Spark 有自己的语法,更符合 SQL,并且经常在使用 Spar 查询大型数据集时,它被用作 SQL 查询的包装器。让我告诉你我的意思:

在这里,我们使用 createOrReplaceTempView 命令将数据帧注册为关系表,然后使用普通的 SQL 查询对其进行查询。输出将是 Spark 数据帧形式的前 20 个结果。

Spark 中有许多处理数据的方法,网上有大量的资源可以帮助您理解它们。我最后要提到的是。printSchema(),它生成数据集中存在的列和每一列的数据类型的读数。这很重要,因为我们需要将数据以特定的格式传递给 SparkML,所以在整个代码中打印模式来确认进度是很方便的。

我不想进入特性工程领域,所以我只是删除了包含大量 NaN 的列,并更改了数据类型,为建模做准备。这些变化使我的数据集从 120 万行减少到大约 12 万行:

请注意,我将“neo”和“pha”列更改为 True/False,将它们转换为“boolean”,然后将它们转换为“integers”。这只是二进制编码。这些列中的真/假值现在表示为 1 和 0。

另一件值得注意的事情是,Spark 的首选数据类型是“double ”,有点像长浮点型。SparkML 中的许多模型需要“double”数据类型作为输入,所以我们在这段代码中也将 floats 改为 double。

一旦我们所有的其他特性都为建模做好了准备,我们就需要使用 Spark 的 StringIndexer、OneHotEncoder 和 Pipeline 类对分类变量进行编码:

完成后,我们可以删除原来的列,并重新排序我们的数据框架:

将我们的数据分成训练集、验证集和测试集(删除 name 列):

我们还必须将所有特征打包到一个向量中。这是在 Spark 中创建模型的奇怪之处之一。您需要使用 VectorAssembler()类将所有的特性列打包成一个向量,并将其输入 Spark 模型:

最后(并非绝对必要),我们需要扩展我们的功能:

现在我们已经为建模做好了准备,让我们用 SparkML 中几种不同的回归方法进行实例化、拟合和预测:

现在让我们来评估这三种模型的性能:

根据结果,梯度推进回归的表现最好,R2 得分为 0.47,均方根误差约为 7.1 km,因此让我们尝试使用网格搜索和交叉验证来优化模型:

现在我们需要从交叉验证器中提取我们的最佳模型。通过下面的代码,我们还可以看到我们的模型的特性重要性:

最后,让我们使用优化的 GBT 模型对我们的测试集进行预测,并看看它与我们的初始模型结果相比如何:

应该会产生这样的结果:

图片作者。

结论

在这篇文章中,我开始提供对 Spark 和 Google 云存储的概念性理解,以及使用这两者创建机器学习模型的实际例子。

正如模型的结果所示,可以对数据做一些额外的工作(提示:异常值),但重点不是创建一个最佳模型,而仅仅是为可能刚开始工作的人展示工作流程。

如您所见,我们处理大型数据集的方式与我们从学习到实践的转变可能会用到的方式不同。在我们做出这种改变时,重要的是我们要开始考虑针对您的特定问题的最佳解决方案路径——我们可以通过许多其他方式来完成这项任务,例如对数据进行采样。通常,你所拥有的工具将取决于你工作的公司,所以保持灵活性,并对各种工具有一个工作理解是值得的。如果你有任何关于 GCP 或使用 Spark 的问题,请随时给我留言。下次见!

亨特·哈里特在 Unsplash 上的照片

星云图数据库初学者指南

原文:https://towardsdatascience.com/beginners-guide-to-nebulagraph-database-5d35bdee442f

一个用于信息检索的开源图形数据库

GuerrillaBuzz 区块链公关机构Unsplash 上的照片

通过阅读本文,您将了解 NebulaGraph(一个开源图形数据库)背后的基本概念。根据官方文档,NebulaGraph 是

“…一个分布式、快速的开源图形数据库,具有横向可扩展性和高可用性。它是一个数据库,专门存储庞大的图形网络,并从中检索信息。”

在此之前,让我们探讨一下关系数据库和图形数据库之间的区别。

关系数据库将数据存储在表中。每个表都由自己的列和行定义。关系数据库需要联接来连接不同表。这种类型的数据库适合于以事务为中心的用例,例如会计和在线事务。

另一方面,图数据库由节点或边来表示。某些图形数据库使用术语顶点、边和属性来代替。它们被设计用来表示实体和实体之间的关系。图形数据库是欺诈检测和推荐系统的理想选择。

继续下一节的设置和安装。

设置和安装

本教程涵盖了以下软件包的安装:

  • NebulaGraph server—nebula graph 服务器的二进制文件
  • Nebula Console—nebula graph 服务器的命令行界面

NebulaGraph (RPM 或 DEB 包)

在撰写本文时,NebulaGraph 仅在 Linux 操作系统(Ubuntu、CentOS)上受支持。根据期望的release_version下载期望的包:

//Centos 6
https://oss-cdn.nebula-graph.io/package/<release_version>/nebula-graph-<release_version>.el6.x86_64.rpm//Centos 7
https://oss-cdn.nebula-graph.io/package/<release_version>/nebula-graph-<release_version>.el7.x86_64.rpm//Centos 8
https://oss-cdn.nebula-graph.io/package/<release_version>/nebula-graph-<release_version>.el8.x86_64.rpm//Ubuntu 1604
https://oss-cdn.nebula-graph.io/package/<release_version>/nebula-graph-<release_version>.ubuntu1604.amd64.deb//Ubuntu 1804
https://oss-cdn.nebula-graph.io/package/<release_version>/nebula-graph-<release_version>.ubuntu1804.amd64.deb//Ubuntu 2004
https://oss-cdn.nebula-graph.io/package/<release_version>/nebula-graph-<release_version>.ubuntu2004.amd64.deb

例如,您可以运行以下命令来下载 3.2.1 版的软件包:

# CentOS 7.5
wget https://oss-cdn.nebula-graph.io/package/3.2.1/nebula-graph-3.2.1.el7.x86_64.rpm# Ubuntu 1804
wget https://oss-cdn.nebula-graph.io/package/3.2.1/nebula-graph-3.2.1.ubuntu1804.amd64.deb# Ubuntu 2004
wget https://oss-cdn.nebula-graph.io/package/3.2.1/nebula-graph-3.2.1.ubuntu2004.amd64.deb

下载完软件包后,运行以下命令安装 NebulaGraph:

# CentOS 7.5
sudo rpm -ivh nebula-graph-3.2.1.el7.x86_64.rpm# Ubuntu 1804
sudo dpkg -i nebula-graph-3.2.1.ubuntu1804.amd64.deb# Ubuntu 2004
sudo dpkg -i nebula-graph-3.2.1.ubuntu2004.amd64.deb

接下来,通过以下命令启动 NebulaGraph 服务器:

sudo /usr/local/nebula/scripts/nebula.service start all

您应该会看到以下输出,表明服务器已经启动:

[INFO] Starting nebula-metad...
[INFO] Done
[INFO] Starting nebula-graphd...
[INFO] Done
[INFO] Starting nebula-storaged...
[INFO] Done

以下命令可用于检查状态:

sudo /usr/local/nebula/scripts/nebula.service status all

它将输出进程 id 和 NebulaGraph 服务使用的相应端口:

[INFO] nebula-metad(ef6d6a0): Running as 713187, Listening on 9559
[INFO] nebula-graphd(ef6d6a0): Running as 713233, Listening on 9669
[WARN] nebula-storaged after v3.0.0 will not start service until it is added to cluster.
[WARN] See Manage Storage hosts:ADD HOSTS in [https://docs.nebula-graph.io/](https://docs.nebula-graph.io/)
[INFO] nebula-storaged(ef6d6a0): Running as 713262, Listening on 9779

除此之外,还有一个停止命令来停止 NebulaGraph 进程:

sudo /usr/local/nebula/scripts/nebula.service stop all

终端将打印出以下日志:

[INFO] Stopping nebula-metad...
[INFO] Done
[INFO] Stopping nebula-graphd...
[INFO] Done
[INFO] Stopping nebula-storaged...
[INFO] Done

请查看下面的文档以获得关于所有可用语法的更多信息。

星云图(Docker 和 Kubernetes)

或者,NebulaGraph 也可用于 Docker 和 Kubernetes。对于标准安装,使用由官方仓库提供的以下文档文件:

  • [vesoft/nebula-graphd](https://hub.docker.com/r/vesoft/nebula-graphd) :- nebula-graphdDockerfile.graphd构建的服务
  • [vesoft/nebula-metad](https://hub.docker.com/r/vesoft/nebula-metad)——Dockerfile.metad建成的nebula-metad服务
  • [vesoft/nebula-storaged](https://hub.docker.com/r/vesoft/nebula-storaged):用Dockerfile.storaged构建的nebula-storaged服务
  • [vesoft/nebula-tools](https://hub.docker.com/r/vesoft/nebula-tools):用Dockerfile.tools构建的星云工具

此外,您可以直接从 Docker Hub 获取 Docker 图片。只需前往下面的链接并提取所需图像。例如,您可以使用以下命令来拉动nebula-graphd图像:

docker pull vesoft/nebula-graphd

对于 Kubernetes,请前往以下链接并遵循提供的说明。

星云控制台

NebulaGraph 服务器文件不附带 Nebula 控制台。Nebula 控制台提供了一个命令行界面来与 NebulaGraph 服务器进行交互。

请注意,如果您打算通过 NebulaGraph 自己的客户端 SDK (Python、Java、Go、C++)连接到 Nebula graph,则不需要 Nebula 控制台。然而,对于调试和测试来说,它是一个很好的工具。

根据您机器的操作系统和架构,从下面的 Github 库下载所需的二进制文件。您可以运行lscpu命令来识别架构。

为了方便起见,建议将二进制文件重命名为nebula-console。此外,您需要授予执行该文件的权限。你可以通过运行chmod 111 nebula-console来实现。请不要使用 chmod 777,因为任何人都可以读取、写入和执行该文件。

将工作目录改为与nebula-console可执行文件相同的目录。然后,运行以下命令启动命令行界面:

# syntax
./nebula-console -addr <address> -port <port> -u <username> -p <password># example
./nebula-console -addr 127.0.0.1 -port 9669 -u root -p root
  • address —设置图形服务的 IP 地址。默认地址是 127.0.0.1。
  • port —设置图形服务的端口号。默认端口号是 9669。
  • username —设置用户名。默认用户名是root
  • password —设置的密码。如果未启用身份验证,您可以使用任何字符作为密码。

当您执行nebula-console文件时,您应该会看到以下输出:

Welcome to NebulaGraph!(root@nebula) [(none)]>

在下一节中,您将学习使用命令行界面执行 nGQL。

星云图查询语言(nGQL)

顾名思义,nGQL 是一种用于 NebulaGraph 的声明式图查询语言。当第一次连接到 NebulaGraph 服务器时,需要添加新的存储主机。

存储主机

确保您的终端通过nebula-console连接到 NebulaGraph 服务器。运行以下查询来标识所有可用的存储主机:

SHOW HOSTS;

您应该会看到一个空表,表明它当前是空的。通过以下查询添加新主机:

ADD HOSTS 127.0.0.1:9779;

再次运行SHOW HOSTS;查询。终端将输出以下结果:

+-------------+------+-----------+-----------+--------------+
| Host        | Port | HTTP port | Status    | Leader count |
+-------------+------+-----------+-----------+--------------+
| "127.0.0.1" | 9779 | 19669     | "ONLINE"  | 0            |
+-------------+------+-----------+-----------+--------------+

NebulaGraph 实例可以包含零个或多个图形空间。每个空间在物理上相互隔离,并有自己的模式。你可以把它想象成关系数据库中的一个数据库。

(计划或理论的)纲要

空间的模式由以下组件表示:

  • VERTEX —代表一个实体。它可以有零到多个标签。
  • TAG —描述顶点的属性。
  • EDGE —表示两个顶点之间的有向关系
  • EDGE TYPE —描述边的属性

例如,请看下图,它展示了一个空间的模式:

作者图片

  • 该空间包含三个Person顶点。
  • 每个Person顶点都有nameage作为标签。
  • 人的顶点由like边连接
  • 每个 like 边都有likeness作为边类型。

因此,我们可以很容易地将上面的空间解释如下:

  • 人物(姓名:鲍勃,年龄:22 岁)相似(相似度:90.0)人物(姓名:玛丽,年龄:30 岁)
  • 人物(姓名:鲍勃,年龄:22 岁)相似(相似度:70.0)人物(姓名:爱丽丝,年龄:22 岁)

创造

让我们根据上面的用例创建一个新的空间和相应的模式。在控制台中运行以下查询:

CREATE SPACE IF NOT EXISTS test(vid_type=FIXED_STRING(30));USE test;CREATE TAG IF NOT EXISTS person(name string, age int);CREATE EDGE like (likeness double);

插入

之后,使用以下查询将新的Person顶点插入到空间中:

INSERT VERTEX person(name, age) VALUES "Bob":("Bob", 22), "Alice":("Alice", 22), "Mary":("Mary", 30);

现在,我们可以如下建立新创建的顶点之间的关系:

INSERT EDGE like(likeness) VALUES "Bob"->"Alice":(70.0), "Bob"->"Mary":(90.0);

阅读

NebulaGraph 提供了 4 种从图形服务器读取数据的不同方法:

  • GO —根据具体情况遍历数据库,获取所需信息
  • FETCH —从顶点或边获取属性
  • LOOKUP —根据索引搜索符合特定条件的数据
  • MATCH —描述基于索引的各种图形模式

本教程涵盖了FETCHGO的功能。使用以下查询从名为BobPerson顶点获取属性:

FETCH PROP ON person "Bob" YIELD vertex as node;

控制台将输出以下结果:

+---------------------------------------+
| node                                  |
+---------------------------------------+
| ("Bob" :person{age: 22, name: "Bob"}) |
+---------------------------------------+

对于 EDGE,您可以使用下面的查询来获取从BobAlicelike边的属性:

FETCH PROP ON like "Bob"->"Alice" YIELD edge as e;

您应该得到以下输出

+--------------------------------------------+
| e                                          |
+--------------------------------------------+
| [:like "Bob"->"Alice" @0 {likeness: 70.0}] |
+--------------------------------------------+

另一方面,GO语句可以用来遍历数据库。例如,你可以很容易地通过鲍勃识别出所有的Person顶点like:

GO FROM "Bob" OVER like YIELD properties($$).name AS Name, properties($$).age AS Age;

终端将打印以下文本:

+---------+-----+
| Name    | Age |
+---------+-----+
| "Alice" | 22  |
| "Mary"  | 30  |
+---------+-----+

$$符号代表目标顶点。在这种情况下,查询将返回目标顶点的属性。您可以使用$^符号来获取源顶点的属性。

您可以使用如下的WHERE子句指定条件:

# Person liked by Bob that is over 25 in age
GO FROM "Bob" OVER like WHERE properties($$).age >= 25 YIELD properties($$).name AS Name, properties($$).age AS Age;# Person liked by Bob with less than 80 likeness
GO FROM "Bob" OVER like WHERE properties(edge).likeness < 80 YIELD properties($$).name AS Name, properties($$).age AS Age;

更新

要更新现有顶点和边,请运行以下查询:

# Update the age of Bob
UPDATE VERTEX "Bob" SET person.age = 25;# Update the likeness from Bob to Alice
UPDATE EDGE "Bob" -> "Alice" OF like SET likeness = 99.9;

删除

子句可以用来从数据库中删除一个顶点或边。按如下方式使用它:

DELETE VERTEX "Bob", "Alice";
DELETE EDGE like "Bob" -> "Mary";

查看下面的备忘单了解更多关于 nGQL 的信息。

Python 客户端

NebulaGraph 附带以下客户端 SDK:

  • C++
  • Java 语言(一种计算机语言,尤用于创建网站)
  • 计算机编程语言

本教程介绍了一个用 Python 连接和管理图形数据库的简单示例。您可以在同一台机器上本地运行该脚本,也可以从远程机器上运行该脚本。

Python 包

在此之前,让我们在目标机器中创建一个新的虚拟环境。激活它并运行以下命令来安装 NebulaGraph Python API。

pip install nebula3-python

接下来,创建一个名为main.py的新文件,并在其中添加以下代码:

函数将返回一个ResultSet对象。例如:

ResultSet(keys: ['node'], values: [("Bob" :person{age: 22, name: "Bob"})])

您可以使用以下代码将其转换为 Python 字典:

columns = result.keys()
d = {}
for col_num in range(result.col_size()):
    col_name = columns[col_num]
    col_list = result.column_values(col_name)
    d[col_name] = [x for x in col_list]

输出dict应该如下所示:

{'node': [("Bob" :person{age: 22, name: "Bob"})]}

NebulaGraph 生态系统工具

NebulaGraph 还提供了一些有用的工具,作为其生态系统的一部分:

  • [NebulaGraph Explorer](https://docs.nebula-graph.io/3.2.0/nebula-explorer/about-explorer/ex-ug-what-is-explorer/) —基于浏览器的可视化工具,用于可视化与图形数据的交互。帮助显示图形数据以便快速分析。
  • [NebulaGraph Dashboard](https://docs.nebula-graph.io/3.2.0/nebula-dashboard/1.what-is-dashboard/) —监控 NebulaGraph 集群中机器和服务状态的可视化工具。它带有社区版和企业版。
  • [NebulaGraph Exchange](https://docs.nebula-graph.io/3.2.0/nebula-exchange/about-exchange/ex-ug-what-is-exchange/)—Apache Spark 应用程序,用于分布式环境中的数据流和集群数据到 NebulaGraph 的迁移。它带有社区版和企业版。

结论

让我们回顾一下你今天所学的内容。

本文首先简要介绍了 NebulaGraph。它还介绍了图形数据库和关系数据库之间的区别。

然后,它强调了在本地机器上设置和安装 NebulaGraph 服务器和 Nebula 控制台的步骤。

随后,它探索了 NebulaGraph 查询语言(nGQL)。本教程提供了与 CRUD 操作相关的详细解释和代码示例。

本文继续举例说明如何使用 Python 客户机来连接和管理 NebulaGraph 服务器。

最后一节讲了 NebulaGraph 提供的生态系统工具。

感谢你阅读这篇文章。祝你有美好的一天!

参考

  1. 星云图——官方网页
  2. 星云图—文档
  3. NebulaGraph — Python 客户端

强化学习初学者指南

原文:https://towardsdatascience.com/beginners-guide-to-reinforcement-learning-f296e8dd8260

强化学习模型的高级概述

凯利·西克玛在 Unsplash 上的照片

强化学习是机器学习中的第四种主要学习方法,与监督,无监督,半监督学习并列。主要区别在于模型不需要任何数据来训练。它通过奖励想要的行为和惩罚坏的行为来学习结构。

强化学习的例子

在我们可以详细了解这种模型的训练过程之前,我们应该了解这些算法在哪些情况下可以有所帮助:

  • 当教计算机玩游戏时,使用强化学习。目的是学习哪些策略会导致胜利,哪些不会。
  • 在自动驾驶中,也使用这些学习算法,以便车辆可以自行决定哪种行动是最好的。
  • 对于服务器机房的空调,强化学习模型决定何时以及在多大程度上冷却房间以有效地使用能量。

强化学习的应用通常以必须做出大量连续决策的事实为特征。程序员也可以向计算机具体说明这些(例如室温:“如果温度上升到 24°C 以上,则冷却到 20°C”)。

然而,在强化学习的帮助下,人们希望避免形成一连串的如果-那么条件。一方面,这在许多用例中可能根本不可能,比如自动驾驶,因为程序员无法预见所有的可能性。另一方面,人们希望这些模型也能为复杂问题开发新的策略,而这可能是人类根本做不到的。

强化学习如何工作

强化学习模型应该被训练成能够独立做出一系列决策。假设我们要训练这样一个算法,代理人,尽可能成功地玩游戏吃豆人。代理从游戏领域中的任意位置开始,并且它可以执行有限数量的可能动作。在我们的例子中,这将是四个方向(上、下、右或左),它可以在运动场上前进。

算法在这个游戏中找到自己的环境是游戏场和幽灵的移动,这是一定不能遇到的。在每一个动作之后,比如上升,代理会收到一个直接的反馈,即奖励。在《吃豆人》中,这些要么是获得积分,要么是遭遇幽灵。也有可能在一次行动后没有直接的回报,但它会在未来发生,例如在一两次进一步的行动中。对代理人来说,未来的奖励不如眼前的奖励有价值。

随着时间的推移,代理人制定了所谓的政策,即承诺最高长期回报的行动策略。在第一轮中,算法选择完全随机的动作,因为它还不能获得任何经验。然而,随着时间的推移,一个有希望的策略出现了。

机器学习方法之间的差异

机器学习领域,总共有四种不同的学习方法:

  1. 监督学习 算法使用已经包含模型应该预测的标签的数据集来学习关系。但是,它们只能识别和学习包含在训练数据中的结构。例如,监督模型用于图像的分类。使用已经分配到一个类的图像,他们学习识别关系,然后他们可以应用到新的图像。
  2. 无监督学习算法从一个数据集学习,但是这个数据集还没有这些标签。它们试图识别自己的规则和结构,以便能够将数据分类到尽可能具有相同属性的组中。例如,当您想要根据共同特征将客户分组时,可以使用无监督学习。例如,订单频率或订单金额可用于此目的。然而,由模型本身来决定它使用哪些特征。
  3. 半监督学习监督学习和非监督学习的混合。该模型具有相对较小的带有标签的数据集和较大的带有未标签数据的数据集。目标是从少量已标记的信息中学习关系,并在未标记的数据集中测试这些关系以从中学习。
  4. 强化学习不同于以前的方法,因为它不需要训练数据,而是通过所描述的奖励系统简单地工作和学习。

强化学习需要训练数据吗?

是的,强化学习模型也需要数据来进行训练。但与其他机器学习方法相比,这些信息不必在外部数据集中给出,而是可以在训练过程中创建。

机器学习的世界里,数据对于训练好的、健壮的模型是必不可少的。监督学习为此使用人类标记的数据,这种数据最好在大量情况下可用。这通常很昂贵,而且数据集很难获得或创建。无监督学习另一方面,也需要大量数据,但不需要有标签。这使得获取信息更加便宜和容易。

正如我们已经看到的,强化学习与监督学习和非监督学习完全相反。然而,大量的数据通常会导致更好的训练结果的原则在这里也适用。然而,与其他类型的机器学习模型的不同之处在于,这些数据不一定是外部提供的,而是由模型本身生成的。

让我们以学习一个游戏为例:一个机器学习模型被训练来赢得游戏,即导致胜利的移动被认为是积极的,导致失败的移动被认为是消极的。在这种情况下,模型可以使用许多游戏运行作为训练数据,因为目标“赢得游戏”是明确定义的。随着每一个新的游戏,模型学习,新的训练数据产生,模型变得更好。

强化学习是深度学习的未来吗?

强化学习在未来无法取代深度学习。这两个子领域是紧密相连的,但它们并不相同。深度学习算法非常擅长识别大型数据集中的结构,并将其应用于新的未知数据。另一方面,强化学习模型即使没有训练数据集也能做出决策。

在许多领域,机器学习深度学习模型将继续足以取得良好的效果。另一方面,强化学习的成功意味着现在可以开辟以前不可想象的人工智能新领域。然而,也有一些应用,如股票交易,强化学习将取代深度学习模型,因为它提供了更好的结果。

在这个领域中,已经尝试学习如何从过去的市场数据中识别和交易新股票。然而,对于股票业务来说,训练一种强化学习算法来制定具体的策略,而不依赖于过去的数据,可能更有前途。

这是你应该带走的东西

  • 强化学习是机器学习领域的一种学习方法。
  • 它指的是被训练来预测一系列决策的模型,这些决策承诺最高的可能成功率。
  • 例如,强化学习用于教计算机玩游戏或在自动驾驶中做出正确的决定。

如果你喜欢我的作品,请在这里订阅https://medium.com/subscribe/@niklas_lang或者查看我的网站* 数据大本营 !还有,媒体允许你每月免费阅读 3 篇 。如果你想让无限制地访问我的文章和数以千计的精彩文章,不要犹豫,通过点击我的推荐链接:*https://medium.com/@niklas_lang/membership获得会员资格,每个月只需支付 5**

***https://medium.com/@niklas_lang/basics-of-ai-deep-learning-vs-machine-learning-93a8499d5679 https://medium.com/@niklas_lang/basics-of-ai-supervised-learning-8505219f07cf https://medium.com/@niklas_lang/what-are-recurrent-neural-networks-5c48f4908e34 ***

简化部署数据科学项目的初学者指南

原文:https://towardsdatascience.com/beginners-guide-to-streamlit-for-deploying-your-data-science-projects-9c9fce488831

使用 streamlit 轻松将您的机器学习和数据科学项目部署为 web 应用程序

伊戈尔·米斯克在 Unsplash 上的照片

宝贵的时间花费在构建数据科学项目上。在花费数小时并投入时间来开发这些机器学习和深度学习模型以成功解决特定任务之后,下一步是什么?

数据科学家可以构建他们的项目,以展示并与资源丰富的数据科学社区共享他们的项目。然而,大多数初学数据的科学家在开发出他们的机器学习或深度学习模型后,都很难找到最好的方法来进一步发展。

完成模型开发后,关键的一步是部署它们以供个人或社区进一步使用。您可以通过开发一个应用程序来部署这些模型,为系统传输创建一个可执行文件,或者使用我们将在本文中讨论的方法,为模型部署创建一个网站应用程序。

我们将利用 streamlit 为我们的数据科学项目部署机器学习或深度学习模型。Django 和 Flask 是此类网站部署模型的其他流行选项。然而,我们将在这篇文章中看到 streamlit,以及为什么我认为它是初学者数据科学家有效利用他们的项目的一个很好的选择。

如果观众对数据科学不太熟悉,我建议看看我以前的一篇文章。我提供了下面的链接,其中包含了一个简明指南,介绍了初学者在大约 12 个月内达到数据科学高级水平需要遵循的 12 个步骤。对于数据科学爱好者来说,这应该是一个最佳的起点。

</12-steps-for-beginner-to-pro-in-data-science-in-12-months-c6f6ba01f96e>

streamlit 简介:

作者图片

数据科学项目的部署是任何机器学习或深度学习管道的最终和关键步骤之一。正如前面所讨论的,有几种方法可以执行下面的操作(部署),每种方法都有自己的优缺点。在我们进一步讨论 streamlit 之前,让我们先了解一下其他几种部署方法的优点和局限性。

部署机器学习模型的一种流行方式是以移动应用程序的形式。这些应用程序允许广泛的用户访问您的机器学习模型及其执行的任务。然而,对于为机器学习模型创建应用程序,您需要更加熟悉一些应用程序开发工具、TensorFlow Lite 移动库、嵌入式设备和其他此类工具。

另一种流行的项目部署方法是用机器学习模型创建软件,并将其部署为可执行文件。该应用程序通常通过使用 python 文件来开发。exe 转换器,可以与众多用户共享。但是,触及面通常没有移动应用多。对于初学者来说,转换时间以及整个可执行文件创建过程可能会稍微复杂一些。

Streamlit 不仅为您提供了一种部署机器学习模型的方法,还可以帮助您设计自己的网站。尽管对项目和设计结构的总体控制有一定的限制,但它为开发用户界面提供了最简单和直接的方法之一。借助其优化的工具,您可以创建和构建许多独特的项目,并相应地部署您的数据科学项目。

网站部署的其他方法是使用像 Flask 和 Django 这样的库,这允许用户更好地控制他们的项目,但是需要稍微多一点的编程。我推荐有兴趣用 streamlit 进一步探索更多项目的观众通过下面提供的链接查看我以前的一篇关于公司盈利电话情绪分析的文章。

开始为数据科学项目部署机器学习模型:

斯凯工作室Unsplash 拍摄的照片

文章的这一部分将分为两个重要的部分。在第一阶段,我们将涵盖 streamlit 的一些基础知识,以及它们在您自己的机器学习项目中的易用性。在第二阶段,我们将看看一种在服务器上部署模型的简单方法,并做出适当的预测。

请注意,在本文中,我们将只查看部署阶段的简单实用程序。在以后的博客中,我们将从头开始探索整个部署项目。让我们从 streamlit 的一些基本元素开始,轻松部署机器学习项目。

Streamlit 的基础:

在本文的这一部分,我们将了解 streamlit 的一些基本概念,尤其是那些通常用于部署机器学习项目的概念。我们将首先导入我们将在这个小型项目构建中使用的必要库。

导入必要的库:

我们这个项目需要的主要库是用于部署模型的 streamlit 库、深度学习框架、用于处理图像的库和用于数学计算的库。读者可以利用 TensorFlow、PyTorch 或其他类似的深度学习框架来构建他们的特定构建。

我们将导入保存的模型,然后继续计算适当的预测。PIL 或 OpenCV 库可用于读取上传的图像。最后,如果您使用 pillow library 模块将图像转换为 numpy 数组形式以便进一步处理,则需要 numpy 数组。这个 skip 通常可以用 cv2 库跳过。下面的代码片段提供了必要的库导入。

# Importing the necessary librariesimport streamlit as st
import tensorflow as tf
from tensorflow.keras.models import load_model
from PIL import Image
import numpy as np

为子栏目创建侧栏:

在我们为你的网站设计探索基本的和不同的选择之前,我们将把我们的项目分成两个适当的子部分。我们将为项目添加一个标题,并为用户创建一个带有单选按钮选项的侧栏。

单选按钮的第一个选项允许用户掌握 streamlit 的一些基本概念,而第二个选项允许用户了解在本地主机服务上部署的深度学习模型的工作方式。下面提供了相同的代码。

# Adding an appropriate title for the test website
st.title("Streamlit For Model Deployment")# Creating a side bar radio option for selecting the required elements
_radio = st.sidebar.radio("",
                          ("Fundamentals of streamlit", "Model Deployment using streamlit"))

细流的基本功能:

在本节中,我们将简要介绍一些重要的 streamlit 组件及其各自的功能。streamlit 有几个组件可以为他们的用户提供快速的开发。我们可以在接下来的文章中讨论一些更独特的组件思想。

对于这个项目,我们将关注一些基本组件,这些组件将帮助读者相应地开发和部署他们的机器学习模型。下面是网站开发中必不可少的一些基本组件的代码块。按照下面的代码片段,我们将分别讨论这些元素。

if _radio == "Fundamentals of streamlit":
    # Creating a header in the fundamentals section
    st.header("Fundamental components of Streamlit") # Creating an appropriate subheader and looking at some of the basic elements
    st.subheader("Writing Elements") # Writing information
    st.write("Write Command: Writing details with the write command and the subheaders") # Creating a text box
    st.text("Text Component: This is a text box") # Display code
    with st.echo():
        import streamlit as st
        st.write("Writing Code") # Creating a button widget
    button1 = st.button("Click Here") # Creating additional text boxes
    if button1:
        st.markdown("*You clicked the button and the markdown is displayed*")
  1. 标题—帮助创建 streamlit 网站的主标题。
  2. 副标题—用于在网站上显示带有适当标题的副标题。
  3. 编写——创建 streamlit 网站的主要功能之一。write 函数的工作方式类似于 Python 程序中的 print 命令,但所需的信息会显示在网站上。
  4. 文本—与 write 命令类似,还有几个其他功能可用于显示信息。文本组件(也检查文本框和文本区域)相应地显示文本信息。
  5. Echo —该组件允许用户将他们的代码片段嵌入到 streamlit 中。嵌入类似于下面表示的代码块。
  6. 按钮 streamlit 中的按钮命令允许用户单击小部件。单击按钮后,我们可以使用“if”条件语句来执行特定的操作。点击按钮后,我显示了降价信息。
  7. Markdown——类似于 Jupyter 笔记本中的 markdown 工作方式,您也可以使用他们的 markdown 命令来获得更多的交互性和 HTML 代码。

在 Streamlit 上部署和测试模型:

在本文的部署部分,我们将使用通过 TensorFlow 深度学习框架构建的经过训练的 MNIST 深度学习模型。该模型是预训练的,并与 MNIST 数据集相匹配。我们将在另一篇博客中介绍整个培训过程和步骤,以模拟部署。对于本文,让我们直观地了解如何在 streamlit 上部署训练好的模型来预测上传的图像。

第二个单选按钮将在 streamlit 的帮助下用于模型部署。我们将用 streamlit 库创建一个适当的标题来展示特定的作品。然后,我们将定义模型的路径,并用 TensorFlow 功能加载模型。借助 streamlit 中的上传器功能,我们将使用一个输入文件上传器来上传用户提交的各个图像。

如果文件上传程序成功解释了图像数据,我们可以继续显示用户提供的图像,并相应地做出适当的预测。如果用户没有输入图像,网站将等待所需的图像上传。我们将在另一篇文章中进一步详细介绍如何进行所需的预测和构建深度学习模型。下面是完成整个过程的代码片段。

elif _radio == "Model Deployment using streamlit":
    # Creating a header in the model deployment section
    st.header("Deployment of Machine Learning Models with Streamlit") # Loading the model
    model_path = "model_test.h5"
    model = load_model(model_path, compile = False)

    # Uploading an image
    img_data = st.file_uploader(label="Image", accept_multiple_files=True) # Making the required prediction
    if img_data is not None and len(img_data) > 0:
        # Assigning a random count
        count = 0 # Opening and displaying the image
        img = Image.open(img_data[count]) 
        st.image(img) # Converting into a numpy array
        img = np.array(img)
        img = np.expand_dims(img, 0) # Making the appropriate prediction
        prediction = model.predict(img)
        output = np.argmax(prediction) # Displaying the prediction
        st.write("The Predicted Result is: ", output)
        print(output) # While no image is uploaded
    else:
        st.write("Waiting For Upload of Image...")

完整代码:

作者图片

模型部署到网站后的预期结果如上图所示。我还提供了该项目的整个代码的要点,可以从下面提供的代码片段中获得。我建议用户可以自由地进一步探索代码,并尝试其他必要的属性和实验。

要运行上面的代码,请激活您的虚拟环境(如果有),然后继续使用下面的命令通过 streamlit 运行 Python 文件。

streamlit run Website_Deploy.py

运行以下命令后,您应该能够打开到本地主机服务器的链接。按照所有的步骤,我们已经成功地在本地主机上部署了模型。在接下来的文章中,我们将研究处理 MNIST 数据集的完整代码结构和项目。我们还将把部署过程从您的本地主机系统扩展到互联网,以便广大用户能够访问。

结论:

Radek Grzybowski 在 Unsplash 上的照片

从文明的黎明到 2003 年,有 5eb 的信息被创建,但是现在每两天就有这么多的信息被创建。
埃里克·施密特

在本文中,我们探讨了 streamlit 在网站设计和数据科学项目部署中的效用。首先,我们简要介绍了 streamlit 和其他一些用于部署机器学习和深度学习模型的流行方法。在接下来的部分,我们讨论了 streamlit 的基本概念以及网站设计的主要工具。

最后,我们部署了一个经过训练的机器学习模型,能够进行实时预测。本文旨在成为一个入门指南,帮助您开始使用 streamlit,并介绍模型部署的许多可能方法中的一种。在未来的博客中,我们将涵盖部署过程,并在深度学习框架和 streamlit 的帮助下,更深入地讨论 MNIST 项目的开发。

如果你想在我的文章发表后第一时间得到通知,请点击下面的链接订阅邮件推荐。如果你希望支持其他作者和我,请订阅下面的链接。

https://bharath-k1297.medium.com/membership

如果你对这篇文章中提到的各点有任何疑问,请在下面的评论中告诉我。我会尽快给你回复。

看看我的一些与本文主题相关的文章,你可能也会喜欢阅读!

</7-best-research-papers-to-read-to-get-started-with-deep-learning-projects-59e11f7b9c32>

谢谢你们坚持到最后。我希望你们都喜欢这篇文章。祝大家有美好的一天!

GPT-3 模型初学者指南

原文:https://towardsdatascience.com/beginners-guide-to-the-gpt-3-model-2daad7fc335a

用 Python 演示了一些有趣的示例应用程序,只有几行代码

照片由你好我是尼克Unsplash

背景

2021 年 11 月 18 日,OpenAI 宣布其 API 服务的可用性将被拓宽,这使得像我一样的普通程序员可以探索 GPT-3 的示例应用。在此之前,API 服务只能通过等待列表获得。

我在听 SuperDataScience 上最近的一期播客节目时,偶然发现了术语 GPT-3 游乐场,主持人和嘉宾讨论了 GPT-3 模型的发展。浏览互联网和媒体,我惊讶地发现几乎没有关于在 GPT-3 游乐场演示的示例应用的报道。这是我决定写下 GPT-3 的一些应用的主要原因,这些应用可能会引起本文读者的兴趣。

GPT-3

尽管普遍的共识是 GPT 3 是一个拥有数十亿参数的最先进的自然语言模型。对于初学者来说,可能有以下几点:

  • 该模型是预先训练的,这意味着它可以用于大量的“零射击”训练(尽管“少量射击”训练可能会显著提高其性能,我将在稍后的一个示例应用程序中解释)。
  • 该模型与任务无关。例如,在各种其他应用中,可以调用它来执行文本生成或文本分类。正如稍后所演示的,对于 GPT-3 来说,要区分这些应用程序,只需要提供简要的上下文,有时只需要任务的“动词”(例如,翻译、创建)。

GPT-3 游乐场是一个虚拟的在线环境,允许用户试验 GPT-3 API。它提供了一个基于 web 的界面,用户可以输入代码并实时查看查询结果。

只是为了好玩,我让 GPT 3 号本身(在 GPT 3 号游乐场)来“详细描述 GPT 3 号模型”,以下是返回的内容:

GPT-3 模型是一个基于转换器的语言模型,它是在一个大的文本数据语料库上训练的。该模型旨在用于自然语言处理任务,如文本分类、机器翻译和问题回答。该模型可以针对特定的任务或领域进行微调,并在许多基准测试中表现出优于其他基于 transformer 的模型。

示例应用

在本节中,我将演示 GPT-3 的三(3)个应用示例。对于本文来说,示例应用程序是用一个带有 openai 库的 Python 实现来演示的。

加载 openai 库

首先,安装并导入 openai 库。这可以通过下面的 Python 代码来实现(在 Google Colab 中):

!pip install openai
import os
import openai

API 键

在我们进入技术细节之前,需要一个 API 密钥来访问 GPT-3。这可以通过在 OpenAI(个人使用)注册一个帐户来获得。然后可以在注册帐户下查看 API 密钥。

示例应用 1:根据某些配料制作食谱

这可以使用 GPT-3 完成端点来完成,该端点可用于各种应用,如翻译、汇总、Q & A 等。首先,我将使用下面的 Python 代码定义一个将文本作为输入的通用函数。所有三(3)个具有不同文本输入的示例应用程序都将使用该函数。

def GPT_Completion(texts):
## Call the API key under your account (in a secure way)
openai.api_key = "your API key"
response = openai.Completion.create(
engine="text-davinci-002",
prompt =  texts,
temperature = 0.6,
top_p = 1,
max_tokens = 64,
frequency_penalty = 0,
presence_penalty = 0
)
return print(response.choices[0].text)

您可以看到完成端点下有许多参数,即:

  • 引擎设置为“text-davinci-002”,这是基于 OpenAI 的文档的“最有能力”的 GPT-3 模型。
  • 提示设置为“文本”,这是一个变量,代表输入到函数的文本。
  • 温度规定了模型输出的确定性。高温使模型对输出进行采样的自由度更大。比如假设某个任务中返回单词 A 和单词 B 作为下一个单词的概率分别是 80%和 20%。设置“低”温度(即更接近 0)可能会在函数运行的所有情况下返回字 A ,而设置“高”温度(即更接近 1)则允许模型在某些情况下返回字 B
  • top_p 设置选择输出的分配。使用上面相同的例子,0.75 的 top_p 告诉模型只选择单词 A ,因为它是唯一概率超过 0.75 的单词。
  • max_tokens 设置返回的字数限制。这可能具有财务影响,因为 GPT-3 可能对商业应用按令牌收费。一般的经验法则是,模型允许返回的单词越多,输出就越不“抽象”。
  • frequency_penaltypresence_penalty 都是惩罚返回经常出现的输出的模型的参数。

最后,为了让 GPT-3 提供一份由苹果、面粉、鸡肉和盐组成的烹饪食谱,我们运行了下面的 Python 代码:

recipe = 'Provide a cooking recipe based on the following ingredients: \
\n \nApple \
\n \nFlour \
\n \nChicken \
\n \nSalt'
GPT_Completion(recipe)

GPT-3 返回以下输出:

图 1:GPT 3 号生成的配方。作者图片

我没有亲自测试过这个食谱,但是它看起来相当详细,注意放松 max_tokens 参数会返回更详细的指令。

示例应用 2:一个讽刺的聊天机器人

示例应用 1 是一个“零射击”训练的例子,其中我们简单地要求 GPT-3 执行一个任务。如果我们想让 GPT-3 在交谈时模仿讽刺,就需要进行“少量射击”训练,如下所示:

## Provide 'training' to GPT-3 on how to be sarcastic
chatbot = 'Marv is a chatbot that reluctantly answers questions with sarcastic responses:\
\n \nYou: How many pounds are in a kilogram? \
\n \nMarv: This again? There are 2.2 pounds in a kilogram. Please make a note of this.\
\n \nYou: What does HTML stand for?\
\n \nMarv: Was Google too busy? Hypertext Markup Language. The T is for try to ask better questions in the future.\
\n \nYou: When did the first airplane fly?\
\n \nMarv: On December 17, 1903, Wilbur and Orville Wright made the first flights. I wish they would come and take me away.\
\n \nYou: What is the meaning of life?\
\n \nMarv: I am not sure. I will ask my friend Google.\
\n \nYou: What time is it?\
\n \nMarv:'

使用上面定义的聊天机器人文本调用示例应用 1 中定义的GPT _ 完成()函数,对最后一个问题(“现在几点?”)作者 GPT-3 是:

“你该问一个更有趣的问题了。”,这已经够讽刺的了,尽管我确实想知道 GPT-3 是否会在未来引入一个更细粒度讽刺(或许还有幽默)的参数。

示例应用 3:创建 Excel 表格

这实际上是与示例应用 1 类似的应用。然而,我强调这个例子是因为它可以推广到其他有用的应用程序,比如文本到代码,或者代码到文本。

要创建一个其他软件(如 Excel)可读的表格,只需给出下面的指令(鉴于奥斯卡就要到了),并通过如下的GPT _ 完成()函数运行它:

spreadsheet = 'Create a two-column spreadsheet showing the 2019 oscar nominees for best movies and the director of the movie'
GPT_Completion(spreadsheet)

将返回下表:

图 2: GPT-3 tble。作者图片

其他 GPT-3 应用程序(附代码)

除了本文讨论的示例应用,鉴于通用自然语言理解模型的广泛应用,OpenAI 在此链接中提供了 GPT-3 的其他可能的示例应用。

这些应用包括情感分类(使用分类端点,而不是完成端点)、语言(和代码)翻译、文本摘要等等,所有这些都可以用几行代码实现。

总结想法

总之,本文为初学者开始使用 GPT-3 模型下的一些示例应用程序提供了实用指南。GPT 3 游乐场证明了用户开始尝试最先进的自然语言模型是多么容易,而不需要实际了解模型是如何构建的。我个人认为,像 GPT-3 这样的“零射击”或“少射击”训练模式将会越来越受欢迎,特别是在商业环境中。

你喜欢这些关于机器学习主题的实用指南吗?关注或访问我在 中的 获取更多信息!

[1]本示例的文本输入由 GPT-3 在此链接中提供。

Python for-loops 入门

原文:https://towardsdatascience.com/beginners-introduction-to-python-for-loops-7df0f6bdbcc8

Python 和 Loops 新手的基本命令

Unsplash 上由Tine ivani拍摄的照片

例如,Python for-loop 用于动态迭代一系列对象,并使用它们执行计算。它自动处理不同长度的物体,因此可以节省编程的工作。

为什么需要 for 循环?

Python 编程语言中,for 循环主要用于处理 Python 列表,以便改变列表中的对象或者能够将它们用于另一个计算。使用循环的优点是不需要知道列表的长度或对象的单个索引。

Python 中的 for 循环与其他编程语言中的 for 循环有很大不同。在这些情况下,它仅用作 while 循环的替代,即只要满足条件就执行计算。另一方面,在 Python 中,它专门用于处理对象,尤其是列表。

Python for-loop 的语法是什么?

for 循环的结构总是相对相似,以单词“for”开头。接下来是变量名,它的值会随着每次运行而改变。在我们的例子中,我们称之为“变量”,并贯穿对象“对象”。在每一次传递中,变量取当前队列中元素的值。单词“in”分隔变量名和被遍历对象的名称:

这一行以冒号结尾,下一行以缩进开始。在 for 语句后缩进的每一行都在一次循环中执行。在这里,可以执行计算,或者像在我们的示例中一样,可以输出列表中的元素:

range()函数是什么?

如果您不想使用 for 循环对一个具体对象进行迭代,而只是为了多次执行一个命令,那么就使用 range()函数。它代替了对象名,并定义了一个被迭代的值的范围。此功能有三种规格:范围(开始、停止、步进)。因此,您可以指定函数应该从哪个数字开始,默认情况下是 0。此外,您可以指定函数应该在哪个值处停止,以及步长有多大,这里默认为 1。

如果只向 range()函数传递一个值,那么这个值将自动成为起始值为 0、步长为 1 的停止值。

通过传递两个值,可以设置起始值和终止值:

如何形成更复杂的 for 循环?

如前所述,在 for 循环之后缩进的所有代码行都在每一次循环中执行。这允许您映射更复杂的关系,并包含 if-else 循环,例如:

如何把 for-loop 写成一行?

到目前为止,我们已经了解到 Python for-loop 在冒号后总是有一个换行符,并在下一行继续缩进。为了使代码更紧凑或者节省时间,也可以在一行中编写一个 Python for-loop,这取决于它的复杂程度。上面的例子输出 2 到 5 之间的数字,可以很容易地写成一行:

对于更复杂的 for 循环,一行中的表示也可能很快变得混乱,如我们的偶数和奇数示例所示:

特别优雅的是使用 for 循环创建一个列表或一个字典,这通常也在一行中定义:

如果你要用一个“常规”Python for-loop 来解决这个问题,你必须首先创建一个空的列表,然后一点一点地填充它。这要麻烦得多:

在 for 循环中,break 和 continue 做什么?

Python for 循环不应该总是运行到循环的末尾。在某些情况下,提前结束序列也是有意义的。为此,您可以使用“中断”命令。在下面的示例中,只要当前数字大于 4,循环就会中断。

命令“continue”是“break”的反义词,它使循环继续运行。如果您没有针对某个条件执行的直接命令,但只想在循环中开始一轮,这种方法尤其有意义。

在下面的例子中,我们只想输出大于 4 的数字。为此,我们使用“continue”跳过所有小于或等于 4 的值。这将只输出 5 以上的数字:

枚举在循环中是如何工作的?

在“枚举”的帮助下,你不仅可以遍历一个对象的元素,比如一个列表,还可以同时获得相应元素的索引。这是有意义的,例如,如果你想直接改变一个列表的元素。

假设我们要将“数字”列表中的每个奇数乘以 2。为此,我们使用“enumerate”遍历“numbers”对象,如果元素是奇数,则更改列表中的数字。这里需要注意的是,我们现在必须分配两个名称,因为每个迭代步骤都有两个变量,即索引和元素本身。

在这里,重要的是要理解对正在迭代的对象的更改对 Python for-loop 没有影响。它仍然像第一次那样看着物体。否则,下面的命令将导致一个无限循环,因为“numbers”元素在每次循环中的长度都是以前的两倍。然而,Python for-loop 只有九个步骤,因为在循环的开始,对象“numbers”只有九个元素。

这是你应该带走的东西

  • Python for-loop 用于动态遍历对象的元素。
  • 在“中断”的帮助下,你可以提前结束循环。
  • 命令“enumerate”不仅返回每一轮中的一个元素,还返回该元素在对象中的索引。例如,这使得从循环内改变对象成为可能。

如果你喜欢我的作品,请在这里订阅https://medium.com/subscribe/@niklas_lang或者查看我的网站* 数据大本营 !还有,medium 允许你每月免费阅读 3 篇 。如果你希望有无限制的 访问我的文章和数以千计的精彩文章,不要犹豫,点击我的推荐链接:【https://medium.com/@niklas_lang/membership】每月花$5***获得会员资格**

*</3short-introduction-to-numpy-3a65ec23eaba> </5-basic-commands-when-working-with-python-sets-875f71dcc85b> *

时间序列分析和预测入门

原文:https://towardsdatascience.com/beginners-introduction-to-time-series-analysis-and-forecasting-c2c2918603d9

平稳性、时间序列分解、ARIMA 建模等等

迪安赫Unsplash 上拍照

最近迷上了时间序列这个话题。我觉得很有趣的是,我们在周围世界观察到的许多事情,也许我们有时认为理所当然的事情,实际上可以用时间来解释。

想想看,道路交通往往在一天中的某些时段达到高峰,冰淇淋的销量通常在夏季较高,或者最近,新冠肺炎病例的趋势如何随着时间的推移而变化。

通过简单地检查一个变量的行为和随时间的变化,你可以知道很多东西。在数据科学中,这就是我们所说的时间序列分析。时间序列是一系列按时间顺序排列的相关数据点,通常在连续且等距的时间点采集。

在这篇博文中,我将对时间序列做一个简单的介绍,并分享一些基本的术语和概念来帮助你进入这个令人兴奋的领域。具体来说,我们将涵盖:

  • 平稳的概念
  • 为什么平稳性在时间序列分析和预测中很重要
  • 如何测试和生成平稳的时间序列过程
  • 如何选择正确的 ARIMA 模型,测试模型的拟合度以及生成未来预测

本文附带的代码可以在我的 GitHub 这里找到。

将数据转换为时间序列对象

为了正确处理 R 中的时间序列数据,我们首先必须使用ts( )函数将数据定义为一个时间序列对象。

testing.stationarity **=** read.table("testing.stationarity.txt")
head(testing.stationarity)
class(testing.stationarity)

数据框对象;作者图片

testing.stationarity **=** ts(testing.stationarity)
head(testing.stationarity)
class(testing.stationarity)

时序对象;作者图片

数据完全相同,只是在 r 中存储为不同的类。

测试平稳性

在我们开始探讨测试时间序列过程中平稳性的各种方法之前,先解释一下什么是平稳性是有帮助的。

平稳性是时间序列分析中的一个重要概念。大多数时间序列模型,如我们将在后面讨论的 ARIMA 模型,假设每个数据点都是相互独立的。换句话说,在我们可以用时间序列模型来拟合数据并使用该模型来生成预测之前,我们需要首先确保时间序列是稳定的。

如果时间序列满足以下三个条件,则认为它是平稳的:

  1. 期望值(平均值)随时间保持不变
  2. 随着时间的推移,时间序列的波动性(方差)在其平均值附近是恒定的
  3. 时间序列的协方差只取决于时滞

如果这听起来令人困惑,不要担心,还有一些视觉线索可以帮助你快速识别一个时间序列是否是稳定的。实际上,有两个组成部分:趋势和季节性。如果数据中存在这些成分中的任何一个,时间序列就不是静止的。

趋势是时间序列的长期轨迹。例如,像标准普尔 500 指数这样的股票市场在过去的几十年里已经出现了整体上涨的趋势。

另一方面,季节性代表以固定和已知的频率发生的循环模式。例如,年度零售额往往会在圣诞节期间飙升。

有两种方法可以测试时间序列的平稳性:

  1. 菲利普斯-佩龙单位根检验
  2. 绘制样本 ACF

Phillips-Perron 单位根检验,PP.test( )用于检验时间序列是一阶积分的零假设,换句话说,时间序列需要进一步差分才能达到平稳性。

PP.test(testing.stationarity)

作者图片

由于 p 值大于 0.05,我们没有足够的证据拒绝零假设,因此得出结论,时间序列过程需要差分,不是平稳的。

或者,我们也可以绘制时间序列的自相关函数(ACF ),它告诉我们序列与其滞后值的相关性。

acf(testing.stationarity, main**=**"Data: testing.stationarity", ylab**=**"Sample ACF")

作者图片

正如我们从上面的 ACF 图中看到的,自相关性衰减缓慢,这表明时间序列不是平稳的。

移除趋势

既然我们知道趋势和季节性会导致时间序列不稳定,那么让我们探索消除它们的方法。

有几种方法可以从时间序列中移除趋势。在这里,我概述了两个最简单的方法:

  1. 区别
  2. 最小二乘趋势去除

1.区别

差分是指取给定滞后的数据点和前一个数据点之间的差值。

这里,除了它们各自的自相关函数之外,我们对比了我们从上面看到的时间序列和它的滞后 1 的差分替代。

*# Difference data using lag=1 and differences=1*
Xt **=** diff(testing.stationarity, lag**=**1, differences**=**1)

*# Plot original data, differenced data, and their respective sample ACFs* 
par(mfrow**=**c(2,2))
ts.plot(testing.stationarity, main**=**"Data: testing.stationarity",
        ylab**=**"Value")
ts.plot(Xt, main**=**"Differenced data", ylab**=**"Change in value")
acf(testing.stationarity, main**=**"", ylab**=**"Sample ACF")
acf(Xt, main**=**"", ylab**=**"Sample ACF")
par(mfrow**=**c(1,1))

作者图片

我们可以清楚地看到,原来的时间序列中曾经存在的趋势现在已经没有了。此外,ACF 现在衰减得更快了。

让我们进行菲利普斯-佩龙单位根检验来证实我们的观察。

# Perform unit root test on differenced data 
PP.test(Xt)

作者图片

差分数据的 p 值低于 0.05,表明我们应该拒绝零假设,并得出结论,时间序列不需要再次差分,现在是平稳的。

区别:奖金!

为了确定时间序列的差异次数,我们可以选择一个给出最低总体方差的时间序列。

*# Try difference values between 0-7 and store their respective variance as a data frame* 
ts.var **=** var(testing.stationarity)
for(i in 1**:**7) {
  diff **=** diff(testing.stationarity, lag**=**1, differences **=** i)
  ts.var[i+1] **=** var(diff)
}
ts.var.df **=** data.frame(diff**=**0**:**7, var**=**ts.var)

*# Plot variance against the number of times data is differenced* 
plot(ts.var.df, type**=**"l", ylab**=**"Variance", xlab**=**"d")

总方差在 d=1 时最低;作者图片

当时间序列过程仅差分一次时,方差最低,随后增加。因此,我们得出结论,数据不需要第二次差分。

2.最小二乘趋势消除

另一方面,最小二乘趋势移除涉及将线性模型拟合到时间序列,并从数据点中减去拟合值。

这里,我们有一个不同的时间序列,随着时间的推移,有一个向上的,积极的趋势。

*# Generate time series data* 
set.seed(123)
n **=** 1000
sim **=** arima.sim(list(ar**=**0.9), n)
xt **=** 2000**+**cumsum(sim)

*# Plot generated time series* 
ts.plot(xt, col**=**"blue", main**=**"Time series with trend", ylab**=**"Data")

作者图片

我们可以看到模拟的时间序列有一个整体上升的趋势。为了消除这种趋势,我们将对数据拟合一个线性模型,然后从数据点中减去拟合值以获得残差。

如果处理得当,残差应该没有剩余趋势,或者换句话说,在一段时间内有一个恒定的平均值。

*# Fit a linear model on time series, extract fitted values and residuals* 
time **=** time(xt)
fit **=** lm(xt **~** time)
yt **=** fit**$**fitted.values
zt **=** fit**$**residuals

*# Plot time series with superimposed linear model and residuals* 
par(mfrow**=**c(2,1))
ts.plot(xt, col**=**"blue", main**=**"Regression example", ylab**=**"Data")
abline(fit, col**=**"red")
plot(xt**-**yt, type**=**"l", col**=**"green", xlab**=**"Time", ylab**=**"Residuals")
par(mfrow**=**c(1, 1))

作者图片

消除季节性

除了趋势之外,季节性也可能导致时间序列变得不稳定。

在这里,我将演示三种方法来消除时间序列中的季节性:

  1. 季节性差异
  2. 季节性平均值
  3. 移动平均法

在我们开始之前,让我们简要讨论一下 r 中的ldeaths数据集。它代表了 1974-1979 年间英国因支气管炎、肺气肿和哮喘每月死亡的人数,包括男性和女性。

*# Plot ldeaths* 
plot(ldeaths, main**=**"Monthly deaths from lung diseases in the UK", ylab**=**"Deaths")
points(ldeaths, pch**=**20)

*# Add red vertical line at the start of each year* 
abline(v**=**1974**:**1980, col**=**"red")

*# Plot sample ACF of ldeaths* 
acf(ldeaths, main**=**"Sample ACF of ldeaths", ylab**=**"Sample ACF", lag.max**=**36)

作者图片

作者图片

图表中有一个非常明显的年度季节效应。尽管每年的最高点不一定与同一个月相对应,但是数据中仍然存在明显的年度趋势。

1.季节性差异

季节性差异意味着用固定滞后的前一个数据点减去每个数据点。

*# Difference ldeaths using lag=12 i.e. January 1975 minus January 1974, February 1975 minus February 1974, and so on* 
sdiff.ldeaths **=** diff(ldeaths, lag**=**12, differences**=**1)

*# Plot original data, differenced data, and their respective sample ACFs* 
par(mfrow**=**c(2,2))
ts.plot(ldeaths, main**=**"Data: ldeaths", ylab**=**"Number of deaths")
acf(ldeaths, main**=**"Sample ACF of ldeaths", ylab**=**"Sample ACF")
ts.plot(sdiff.ldeaths, main**=**"Data: sdiff.ldeaths", ylab**=**"Difference in number of deaths")
acf(sdiff.ldeaths, main**=**"Sample ACF of sdiff.ldeaths", ylab**=**"Sample ACF")
par(mfrow**=**c(1,1))

作者图片

2.季节性平均值

季节性均值包括将每个数据点减去其各自的组平均值,例如,在这个特定的场景中,是月平均值。

*# Generate ldeaths as dataframe* 
ldeaths.df **=** data.frame(year**=**rep(1974**:**1979, each**=**12),
                        month**=**rep(1**:**12, 6),
                        value**=**ldeaths)
head(ldeaths.df, 12)

ldeaths 数据集的前 12 个数据点;作者图片

*# Monthly averages of ldeaths dataset* 
xbars **=** aggregate(value **~** month, data **=** ldeaths.df, mean)
xbars

ldeaths 数据集的月平均值;作者图片

*# Subtract each month in ldeaths by their respective means*
yt **=** ldeaths **-** xbars**$**value

*# Plot ldeaths after subtracting seasonal means* 
par(mfrow**=**c(2, 1))
plot(yt, main**=**"Monthly deaths from lung diseases in the UK", ylab**=**"Deaths")
points(yt, pch**=**20)
acf(yt, main**=**"Sample ACF of the series ldeaths less seasonal means", ylab**=**"Sample ACF", lag.max**=**36)
par(mfrow**=**c(1, 1))

作者图片

从上述两种方法中我们可以看出,新的时间序列不再具有原来存在的季节性。

3.移动平均法

最后但并非最不重要的一点是,移动平均法涉及通过对整个时间序列进行移动平均来计算时间序列的趋势。

我们可以分解时间序列以分离出趋势、季节性和白噪声。

*# Decompose ldeaths into its trend, seasonal and random components* 
plot(decompose(ldeaths))

作者图片

*# Store trend, seasonal and random as individuals variables* 
decomp **=** decompose(ldeaths) 
trend **=** decomp**$**trend
seasonal **=** decomp**$**seasonal
random **=** decomp**$**random

*# Plot data, trend and seasonal + trend* 
ts.plot(ldeaths, ylab**=**"", main**=**"Components of time series: ldeaths", col**=**"grey")
lines(trend, col**=**"red")
lines(seasonal**+**trend, col**=**"blue")
legend("topright", legend**=**c("Data", "Trend", "Seasonal + trend"), col**=**c("grey", "red", "blue"), lty**=**1)

作者图片

模型拟合

ARIMA(p,d,q)模型是最常用的时间序列模型之一。它由三个超参数组成:

  • p =自回归(AR)
  • d =差异(I)
  • q =移动平均值(MA)

虽然在forecast包中已经有了像auto.arima( )这样的函数可以帮助我们确定这些超参数,但是在这一节中,我们将着重于一些例子来学习如何手动选择 p、d 和 q 的值

具体来说,我们将研究两个独立的时间序列过程的 ACF 和部分 ACF 图,以确定我们的 ARIMA 模型的超参数。

选择正确的 ARIMA 模式:示例 1

*# Read time series data* 
data **=** read.csv("fittingmodelEg1.csv", header**=**F)
data **=** ts(data[, 1])

*# Plot data, ACF and partial ACF* 
m **=** matrix(c(1, 1, 2, 3), 2, 2, byrow**=TRUE**)
layout(m)
ts.plot(data, ylab**=**"")
acf(data,main**=**"")
pacf(data,main**=**"")
par(mfrow**=**c(1,1))

作者图片

我们之前讨论过什么是自相关函数(ACF ),它告诉我们序列与其滞后值的相关性。另一方面,部分自相关函数(PACF)测量前一个滞后中未考虑的下一个滞后值的残差的相关性。

通过观察上面的时间序列,我们可以看到,没有明显的趋势,方差也随着时间的推移而合理地保持恒定。

ACF 不会缓慢下降,因此表明该过程不需要进一步微分,换句话说,设置 d=0。此外,在滞后 3 之后,ACF 也在置信区间内突然下降。这就提示我们应该将移动平均超参数设置为等于 3,即 q=3。

另一方面,PACF 的衰落更加缓慢。

根据上面的信息,我们可以尝试用 MA(3)模型来拟合这个数据,或者等价地,用 ARIMA(p=0,d=0,q=3)来拟合。在实践中,我们会在决定最终拟合之前调查多个模型。

选择正确的 ARIMA 模式:示例 2

*# Read time series data* 
data2 **=** read.csv("fittingmodelEg2.csv", header**=**F)
data2 **=** ts(data2[, 1])

*# Plot data, ACF and partial ACF* 
m **=** matrix(c(1, 1, 2, 3), 2, 2, byrow**=TRUE**)
layout(m)
ts.plot(data2, ylab**=**"")
acf(data2,main**=**"")
pacf(data2,main**=**"")
par(mfrow**=**c(1,1))

作者图片

与示例 1 类似,数据本身没有明显的趋势,变量似乎在一段时间内相当稳定。

ACF 没有显示出稳定下降的趋势,因此数据看起来是稳定的。因此,我们可以设置 d=0。

另一方面,PACF 在滞后 2 之后突然下降到置信区间内,这表明我们应该将自回归超参数设置为等于 2,换句话说,p=2。

基于上述信息,我们可以尝试用 AR(2)模型来拟合该数据,或者等效地,用 ARIMA(p=2,d=0,q=0)模型来拟合。

测试模型的拟合度

现在,我们简要地回顾了如何为特定的时间序列数据选择正确的模型,让我们讨论一下如何测试我们选择的模型是否真正合适。

在本节中,我们将研究三种不同的技术来测试时间序列模型的拟合度:

  1. 残差图
  2. 永盒试验
  3. 赤池信息标准(AIC)

1.残差图

顾名思义,残差图绘制了模型未考虑的时间序列数据的残差。

除了具有相对稳定的随时间变化的方差之外,与数据拟合良好的模型将产生以零均值为中心的残差。

在将 MA(3)模型拟合到我们在之前的练习中看到的示例 1 后,请参见下面的残差图。

*# Fit MA(3) model to data and extract residuals* 
ma3 **=** arima(data, order**=**c(0, 0, 3))
residuals **=** ma3**$**residuals

*# Plot residuals and ACF of residuals* 
par(mfrow**=**c(2, 1))
ts.plot(residuals, main**=**"MA(3) residuals", ylab**=**"Residuals", col**=**"blue")
acf(residuals, main**=**"", ylab**=**"ACF")
par(mfrow**=**c(1, 1))

作者图片

残差图的均值和方差在很大程度上是恒定的。残差的 ACF 很小,没有明显的模式,因此我们可以得出结论,残差似乎是独立的。

因此,我们也可以得出结论,MA(3)模型为数据提供了良好的拟合。

2.永盒试验

容格检验是一种统计检验,用来衡量时间序列的一组自相关是否不为零。

Box.test(residuals, lag**=**5, type**=**"Ljung", fitdf**=**3)

根据上面的输出,由于 p 值大于 0.05,我们不拒绝零假设,并得出结论,该模型与数据非常吻合。

3.赤池信息标准(AIC)

最后但并非最不重要的一点是,AIC 是一种衡量模型拟合优度和模型中使用的参数数量之间权衡的方法。

虽然具有许多参数的模型可以很好地拟合数据,但它不一定能准确预测未来。我们通常称之为机器学习中的过度拟合。相反,参数太少的模型可能不足以捕捉底层数据本身的重要模式。

因此,一个好的模型必须能够在这两种效应之间取得健康的平衡,AIC 帮助我们客观地衡量这一点。

在我们研究 AIC 在实践中是如何工作的之前,让我们为下面的新时间序列数据确定一个合适的模型。

*# Read time series data* 
data3 **=** read.csv("fittingmodelEg3.csv", header**=**F)
data3 **=** ts(data3[, 1])

*# Plot data without differencing and differenced data* 
m **=** matrix(c(1, 1, 4, 4, 2, 3, 5, 6), 2, 4, byrow**=TRUE**)
layout(m)
ts.plot(data3, main**=**"Data without differencing", ylab**=**"")
acf(data3, main**=**"", ylab**=**"Sample ACF")
pacf(data3, main**=**"", ylab**=**"Sample PACF")
d **=** diff(data3)
ts.plot(d, main**=**"Differenced data", ylab**=**"")
acf(d, main**=**"", ylab**=**"Sample ACF")
pacf(d, main **=** "", ylab**=**"Sample PACF")
par(mfrow**=**c(1, 1))

作者图片

上面输出的左半部分显示了与原始时间序列数据相关的三个图。数据显示出明显的下降趋势,这反映在缓慢衰减的样本 ACF 中。这表明我们需要对数据进行差分,以消除其趋势。

输出的右半部分涉及一次差分后的相同时间序列数据。我们可以看到,在差分后,我们设法消除了样本 ACF 中的缓慢衰减。

到目前为止,我们知道我们的 ARIMA 模型应该是 ARIMA(p,d=1,q)。为了帮助我们确定 p 和 q 的值,我们将部署 AIC。具体来说,我们将根据给出最低 AIC 值的值来选择 p 和 q 的值的组合。

*# Try values 0-2 for both p and q, record their respective AIC and put them into a data sframe* 
aic.result **=** numeric(3)
for (p in 0**:**2) {
  for (q in 0**:**2) {
    aic **=** arima(d, order**=**c(p, 0, q))**$**aic
    aic.result **=** rbind(aic.result, c(p, q, aic))
  }
}
aic.result **=** aic.result[-1, ]
colnames(aic.result) **=** c("p", "q", "AIC")
aic.result

作者图片

我们可以看到,p=2 和 q=2 产生最低的 AIC,因此我们应该将 ARIMA(2,1,2)模型拟合到这个特定的数据。

使用 ARIMA 模型进行预测

我们的时间序列分析和预测练习即将结束。既然我们已经为数据确定了正确的模型,让我们用它来生成未来的预测。

为简单起见,让我们从原始时间序列过程中的最终数据点向前预测 100 步。

*# Fit ARIMA(2, 0, 2) to differenced data, since data has already been differenced, we can set d=0* 
fit **=** arima(d, order**=**c(2, 0, 2))*# Predict 100 steps ahead using ARIMA(2, 1, 2) model* 
predictions **=** predict(fit, n.ahead**=**100)
predictions **=** predictions**$**pred

*# Aggregate predictions with the final point of past data* 
predictions.with.trend **=** tail(data3, 1) **+** cumsum(predictions)
predictions.with.trend **=** ts(predictions.with.trend, start**=**501, frequency**=**1)

*# Plot past data and forecasts* 
xlim **=** c(0, 600)
ylim **=** c(floor(min(data3, predictions.with.trend)), ceiling(max(data3, predictions.with.trend)))
ts.plot(data3, xlim**=**xlim, ylim**=**ylim, col**=**"blue", main**=**"Past data and forecasts", ylab**=**"")
lines(predictions.with.trend, col**=**"red")

作者图片

我们在这篇博文中已经谈了很多。总而言之,我们首先学习了平稳性的概念,然后学习了如何通过观察时间序列的趋势和季节性来测试和发现时间序列是否平稳。我们还学习了一些从时间序列中去除季节性的简便技巧。

然后,我们继续探索时间序列预测,我们学习了如何为我们的数据选择正确的 ARIMA 模型,测试拟合优度,并最终根据我们选择的模型生成预测。

总之,在这篇博文中,我对时间序列分析这个庞大的主题只是略知皮毛,但尽管如此,我希望这已经足够有助于对这个主题的一般性介绍,并为您进一步探索奠定了初步基础。

如果你从这篇文章中发现了任何价值,并且还不是一个媒体会员,如果你使用下面的链接注册会员,这对我和这个平台上的其他作者来说意义重大。它鼓励我们继续推出像这样的高质量和信息丰富的内容——提前感谢您!

https://chongjason.medium.com/membership

不知道接下来要读什么?这里有一些建议。

posted @ 2024-10-18 09:31  绝不原创的飞龙  阅读(353)  评论(0)    收藏  举报