TowardsDataScience-博客中文翻译-2021-六十一-

TowardsDataScience 博客中文翻译 2021(六十一)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

现实生活中的逻辑回归:构建日常生产力分类模型

原文:https://towardsdatascience.com/logistic-regression-in-real-life-building-a-daily-productivity-classification-model-a0fc2c70584e?source=collection_archive---------7-----------------------

图片作者。

Logistic 回归是一个机器学习分类模型,名字相当混乱!

这个名字让你想到线性回归,但它不是用来预测一个无限的、连续的结果。相反,它是一个统计分类模型,它给你一个观察属于一个特定类别的可能性。

逻辑回归被用于许多科学领域。在自然语言处理(NLP) 中,它被用来确定电影评论的情绪,而在医学中,它可以用来确定病人患特定疾病的概率。

对你的日常生产力进行分类

最近你对衡量自己的生产力感兴趣。不一定要量化到最小的细节,但只是为了更好地了解你的一天是否真的富有成效。

每天结束时,你都在问自己,这一天是否真的富有成效。但这只是一个潜在的有偏见的定性数据点。你想找到一个更科学的方法来做这件事。

你已经观察了一天中的自然涨落,并意识到对它影响最大的是:

  • 睡眠你知道睡眠,或者睡眠不足,对你的一天有很大的影响。
  • 咖啡不是喝完咖啡一天就开始了吗?
  • 专注时间这并不总是可能的,但是你可以试着花 3-4 小时专注于项目。
  • 你已经注意到,当你有时间吃一顿正式的午餐,而不仅仅是小吃时,一天会过得很顺利。
  • 散步你一直在进行短途散步,以便进入状态,放松一下,思考一下你的项目。

什么影响了你的工作效率。

你听说过机器学习分类模型,因为有许多不同的模型,具有不同的复杂程度和定制程度,所以你想从一个简单的模型开始。

当你在考虑使用哪种模式时,你意识到这些活动与你的整体生产力有线性关系。

那么你的第一个问题是,*线性回归 可能是这项工作最简单、最好的工具吗?*

如果是线性模型,为什么不用线性回归呢?

最后,您希望创建一个模型来描述一组特征、影响您工作效率的因素以及目标变量(有效率或无效率的一天)之间的线性关系。

那么,为什么不保持简单,使用线性回归模型呢?

要用线性回归模型将你的一天划分为有效率还是没有效率,第一步是选择一个任意的阈值 x ,并根据一个简单的标准将观察值分配给每个类别:

  • **类非生产性,所有小于等于 x 的结果。
  • **类生产性否则,即所有结果大于 x

使用任意阈值 x 来确定数据属于哪一类。

这很简单!

您获取数据并在训练集和测试集之间进行分割,确保将所有分类值编码为数字值。

线性回归模型不知道如何处理分类值,所以需要对它们进行编码。

你可以用你喜欢的方式,只要是整数。在这种情况下变为 0,而变为 1。

你一直在收集的用来模拟日常工作效率的数据。

至于任意阈值,您已经决定:

  • 小于或等于零的结果被分配到 0 级,即非生产日。
  • 积极的结果被分配到第 1 类,即富有成效的一天。

您使用 Python 的 SckitLearn 通过线性回归模型运行数据,并绘制结果及其各自的类。

*import numpy as np
import matplotlib.pyplot as plt
from sklearn import linear_model
from matplotlib.lines import Line2D
from sklearn.model_selection import train_test_splitdef plot_results(train_targets, predictions):
    fig, ax = plt.subplots(figsize=(15, 10))
    # removing all borders except bottom
    ax.spines['top'].set_visible(False)
    ax.spines['right'].set_visible(False)
    ax.spines['left'].set_visible(False) # adding major gridlines
    ax.grid(color='grey', linestyle='-', linewidth=0.25, alpha=0.5) training_colors = ['#4786D1' if target <= 0 else '#F28627' for target in train_targets]
    prediction_colors = ['#4786D1' if target <= 0 else '#F28627' for target in predictions] train_set_len = len(train_targets)
    predictions_len = len(predictions) plt.scatter(np.arange(0, train_set_len), train_targets, color=training_colors, marker='o', s=[12 * train_set_len])
    plt.scatter(np.arange(0, predictions_len), predictions, color=prediction_colors, marker='^', s=[40 * predictions_len]) ax.set_xlabel('Observation')
    ax.set_ylabel('Target value') # Customizing symbols in the legend
    legend_items = [Line2D([0], [0], color='#4786D1', markersize=15), 
        Line2D([0], [0], color='#F28627', markersize=15),
        Line2D([0], [0], color='w', marker='o', markerfacecolor='#979797', markeredgecolor='#979797', markersize=15),
        Line2D([0], [0], color='w', marker='^', markerfacecolor='#979797', markeredgecolor='#979797', markersize=15)] # Adding some spacing between each legend row and padding
    ax.legend(handles=legend_items,
    labels=['Class 0: Non Productive', 'Class 1: Productive', 'Training set', 'Predictions'],labelspacing=1.5, borderpad=1)

    plt.show()def fit_linear_regression(features, targets):
    train_features, test_features, train_targets, test_targets = train_test_split(features, targets, test_size=0.25, random_state=123) model = linear_model.LinearRegression()
    fitted_model = model.fit(train_features, train_targets)
    predictions = fitted_model.predict(test_features)

    print('---Linear Regression')
    print('Coefficients: ' + str(fitted_model.coef_))
    print('Intercept: ' + str(fitted_model.intercept_))
    print('R-squared: ' + str(fitted_model.score(train_features, np.array(train_targets).reshape(-1, 1))))

    plot_results(train_targets, predictions)productivity_features = [[8.0, 2, 4.5, 1, 0],
                         [7.5, 1, 5.0, 1, 0],
                         [9.0, 2, 3.0, 0, 0],
                         [6.0, 3, 2.5, 1, 0],
                         [8.5, 2, 3.5, 0, 1],
                         [10.0, 1, 2.0, 1, 1],
                         [7.5, 3, 2.5, 1, 0],
                         [8.5, 2, 3.5, 0, 1],
                         [6.0, 2, 1.5, 1, 1],
                         [7.0, 1.0, 3.0, 1, 0]]productivity_targets = [1, 1, 0, 0, 1, 0, 1, 0, 0, 1]fit_linear_regression(productivity_features, productivity_targets)*

线性回归:不是这项工作的最佳工具

绘制训练集的目标或结果以及模型预测,您可以看到一些点被错误地分类。

在某些情况下,该模型在预测正确的类别方面做得并不好。

例如,在只有蓝色数据点的绘图区域中有一个橙色数据点,而在主要为橙色的区域中有一个蓝色数据点。

训练目标值散点图(圆形)和线性回归模型预测值散点图(三角形)。根据等级进行颜色编码:蓝色代表 0 级,橙色代表 1 级。

因此,为了更好地了解模型的性能,您可以检查它的 R 平方,这是一个衡量这些特征如何帮助确定结果的指标。

线性回归模型的输出。

0.7 还不错。当然,这种模式有改进的空间,但它不是一个彻底的失败!

但是,即使有看似令人鼓舞的结果,线性回归模型在分类任务方面也有一些限制:

  1. 意味着结果值有特定的顺序。
  2. 产生连续的、无限的结果。
  3. 仅解释单个特征如何影响目标。

1。意味着结果值有特定的顺序

如果你只使用一个阈值来分配类,你是在假设结果有一个隐含的顺序。

例如,您决定所有小于或等于 0 的结果属于类 0、,而所有其他结果属于类 1* 。*

因此,使用这种方法,您隐含地假设所有来自类 0* 的观察值必须在所有来自类 1 的观察值之前。*

你可以控制这个阈值,所以你可以选择任何你想要的数字。但是,在实际中,当数据可能不遵循该特定顺序时,该模型将盲目地使用给定的阈值。

因此,该模型往往具有较低的准确性。

2。产生连续的、无限的结果

在分类问题中,结果变量是分类,在这种情况下,是一个生产或非生产日。

但是你正在将数据拟合到一个只能产生连续结果的回归模型中。

结果是连续的这一事实不是问题。最大的限制是这些结果不限于 0 到 1 之间的值。

你刚刚看到了它的作用。尽管可能的目标是 0 和 1,但有些预测完全是 0,有些预测是肯定的,但不完全是 1。有些预测甚至是负面的!

3。仅解释单个特征如何影响目标

线性回归是表示目标变量和一组特征之间的线性关系的一个很好的模型,但是模型系数只能告诉您一个特定的特征(独立于其他特征)如何影响目标。

线性回归映射目标和特定特征之间的关系,假设所有其他特征都是固定的。

但是在分类任务中,你想要测量整个特征集如何影响结果,因为所有特征同时存在,而不是孤立存在【1】。

逻辑回归拯救世界!

知道了这些限制,很明显线性回归不是分类任务的最佳工具。

一个可行的选择是使用逻辑回归。它解决了线性回归的局限性,同时分享了它的许多特征。例如,逻辑回归和线性回归都是广义线性模型,描述目标和独立变量集之间的线性关系。

但是逻辑回归更适合于二元分类任务,因为它:

  • 预测发生伯努利事件的可能性,其结果只能是是/否肯定/否定
  • 找到一个函数 g,,也称为链接函数,该函数获取某个观察值属于某个类别的可能性,并将其结果建模为预测值的线性组合。
  • 假设模型的结果不会随着特征的变化而线性变化。函数 g 随着特征的变化而线性变化。

对于只有一个特征或预测器的模型,链接函数 g 可描述为:

逻辑回归模型连接函数的定义。

逻辑回归使用链接函数,但是它的结果是一个概率,这意味着它只能预测 0 到 1 之间的值。

所以问题变成了,逻辑回归如何把线性组合的无界连续值变成概率?**

logit 函数

为了完成这一数学壮举并将其结果限制在 0 和 1 之间,逻辑回归使用 logit 函数 作为其链接函数来表示概率 p对数优势比的对数

在这种情况下,多产日的对数概率是多产日的概率( p )与非多产日的概率(1- p )之比。

这就是为什么 logit 函数也被称为 log-odds 函数。

但是为什么是 logit 而不是其他函数呢?

logit 功能是一个 sigmoid 功能。它在 0 和 1 处渐近,因此,随着模型结果越来越接近-无穷大,logit的结果越来越接近 0。另一方面,随着结果越来越接近+无穷大logit 的结果越来越接近 1。

一个逻辑函数的锅。

logit 函数很棒,因为它将值保持在 0 和 1 之间,但是您对对数几率不感兴趣。**

在二元类任务中,您需要实际的概率。

物流功能

实际上,你希望从对数概率中提取概率。

听起来像是一个困难的任务,但是,好消息是,它只需要几个数学变换!

下面是你如何从对数概率中得出成功的概率(p)。**

首先你去掉的对数,然后,经过一些代数运算,你能够分离出 p

在这个过程结束时,概率 p 、成功概率、是一个线性组合的函数。

从数学上来说,你实现的是 logit 函数的逆函数,这个函数叫做 逻辑函数

逻辑函数的定义。

简单形式的线性组合 z 的函数。

如果你对失败的概率感兴趣,你可以做一个等价的操作并隔离(1- p 而不是 p.

将所有这些放在一起,现在我们知道逻辑回归使用逻辑函数来预测观察值属于类的可能性。概率也是线性组合的函数,如线性回归中使用的概率。

逻辑回归这个名字更有意义!

这个模型只需要考虑一个细节,然后就可以把你的一天划分为有效率的或者没有效率的。

定义决策边界

对于每个观察值,逻辑回归模型计算该观察值属于类的概率,在本例中,是多产的日。它看起来像这样:

但是您在分类任务中使用这个模型,所以它仍然需要决定将哪个类分配给每个观察。

该模型需要一些标准来区分对应于生产日的观察和对应于非生产日的观察。它需要一个决策边界

决策边界是将来自类的观察值与来自类的观察值分开的假想边界

根据手头的问题,您可以将决策边界设置为您喜欢的任何概率。但是典型地,判定边界被设置为 0.5。

所以,如果模型预测观察有一个概率:

  • 低于或等于 0.5 ,观察值被分配到负类,例如,非生产日。
  • 大于 0.5 ,观察值被分配到积极等级,例如,多产日。

你的一天(真的)有成效吗?

要回答这个问题,您可以在已经完成的线性回归的基础上,再次使用 ScikitLearn 来拟合一个逻辑回归模型

**from sklearn.linear_model import LogisticRegressiondef fit_logistic_regression(features, targets):
    train_features, test_features, train_targets, test_targets = train_test_split(features, targets, test_size=0.25, random_state=123) model = LogisticRegression(random_state=0)
    fitted_model = model.fit(train_features, train_targets)
    predictions = fitted_model.predict(test_features) print('---Logistic Regression')
    print('Coefficients: ' + str(fitted_model.coef_))
    print('Intercept: ' + str(fitted_model.intercept_))
    print('Mean accuracy: ' + str(fitted_model.score(train_features, np.array(train_targets).reshape(-1, 1))))

    plot_results(train_targets, predictions) fit_logistic_regression(productivity_features, productivity_targets)**

然而,仅仅通过观察模型结果的曲线,很难判断模型是否做得很好。

训练目标值(圆形)和逻辑回归模型预测值(三角形)的散点图。根据等级进行颜色编码:蓝色代表 0 级,橙色代表 1 级。

要衡量性能,你需要看模型的https://en.wikipedia.org/wiki/Accuracy_and_precision****

逻辑回归模型的输出。

85%的准确度意味着您的模型正确预测了 85%的测试观察值。

现在你不必仅仅依靠定性的自我评价来判断你的一天是否富有成效!

你已经通过一种定量的、可重复的方式对你一天的工作效率进行了分类。

在这个过程中,您也更好地理解了为什么线性回归不是分类任务的最佳模型,即使特征和目标之间的关系是线性的。

希望你喜欢学习逻辑回归。

感谢阅读!

参考

[1] Stoltzfus JC。逻辑回归:简明入门。Acad 急救医学。2011 年 10 月;18(10):1099–104.

图片由作者提供,除非另有说明。

逻辑回归——用 Python 实现的机器学习算法

原文:https://towardsdatascience.com/logistic-regression-machine-learning-algorithms-with-implementation-in-python-7dd5778279fc?source=collection_archive---------23-----------------------

机器学习算法— 30 天挑战

在本文中,我们将研究逻辑回归,一种机器学习分类算法,以及如何使用 Python (Scikit-learn)实现它

在本文中,我们将研究逻辑回归(线性回归的一种变体),这是 ML 算法工具箱中的另一种基本而重要的机器学习算法。

图片来自 Unsplash

我们将从了解它的功能和工作原理开始。然后我们将使用scikit-learn来实现它

  • 什么是逻辑回归
  • Python 实现(虚拟数据)
  • Python 实现(真实世界数据集)
  • 绘制决策边界
  • 应用程序
  • 结论
  • 你能做什么
  • 其他 ML 算法

这是我 30 天文章写作挑战的一部分。请随意查看我的新人帖子上的文章:

https://nouman10.medium.com/lets-publish-30-articles-in-30-days-a0b8111855bb

什么是逻辑回归?

逻辑回归是线性回归的变体,用于分类目的。分类是基于概率的概念

逻辑回归使用一个名为“Sigmoid function”的压缩函数,它基本上将任何实数值转换为 0 到 1 之间的值。Sigmoid 函数的方程式如下:

Sigmoid 函数方程(图片由作者提供)

这导致了下图:

Sigmoid 函数的图形(图片由作者提供)

对于分类,我们定义一个阈值。例如,高于 0.5 的 sigmoid 函数的任何输出值将被分类为类 1,低于或等于 0.5 的任何值将被分类为类 0。我们也可以对多个类做同样的事情。

Python 实现(虚拟数据)

让我们从对一些虚拟数据进行逻辑回归开始。

我们从导入必要的模块开始。然后,我们创建一些 200 个样本的虚拟数据,每个样本包含 2 个特征,属于 5 个不同的类别。我们将我们的LogisticRegression模型与数据进行拟合,并计算得分。输出将是:

作者图片

Python 实现(真实世界数据集)

现在让我们使用iris数据集来实现它。代码同上,除了我们使用scikit-learn加载iris数据集。我们只包括数据的前两个特征,因为它有助于可视化决策边界

这给了我们 82%的分数。

作者图片

绘制决策边界

现在,让我们使用以下代码绘制决策边界,这将有助于我们可视化正确和不正确的预测:

这将导致由我们的逻辑回归模型创建的以下决策界限:

作者图片

应用程序

  • 欺诈检测:检测信用卡欺诈或银行欺诈是这个用例的目标。
  • 电子邮件是否是垃圾邮件:将电子邮件分类为垃圾邮件并将其放入收件箱或垃圾邮件文件夹是这个用例的目标。
  • 情绪分析:使用评论或推文分析情绪是这个用例的目标。大多数品牌和公司利用这一点来增加客户体验。

结论

让我们总结一下本文所做的工作:

  • 我们从逻辑回归如何工作的一般解释开始
  • 然后,我们用 Python 在一些虚拟数据上实现了它,随后在一个数据集上实现了它
  • 然后,我们使用matplotlib绘制决策边界
  • 最后,我们研究了逻辑回归的应用。

您可以做什么:

  • 尝试从零开始实现逻辑回归。为此,你需要理解逻辑回归背后的数学原理
  • 将您的实现与scikit-learn中的实现进行比较
  • 在各种其他数据集上测试上面的代码。

如果你有任何问题,请随时联系我。请继续关注我,因为我计划在未来讲述更多的机器学习算法

其他 ML 算法:

  • 线性回归——用 Python 实现的机器学习算法

https://medium.com/mlearning-ai/linear-regression-a-to-z-2ab3d1b7277c

  • k-最近邻——机器学习算法及其 Python 实现

https://nouman10.medium.com/k-nearest-neighbors-a-to-z-with-implementation-in-python-74630ffb79a2

  • 决策树——机器学习算法及其 Python 实现

https://nouman10.medium.com/decision-trees-machine-learning-algorithms-with-implementation-in-python-5bc034e67fc8

  • k-Means-机器学习算法及其在 Python 中的实现

如果您觉得以上内容对您有用,请分享并随时支持我-->

用 PyTorch 进行逻辑回归

原文:https://towardsdatascience.com/logistic-regression-with-pytorch-3c8bbea594be?source=collection_archive---------2-----------------------

使用 PyTorch 应用逻辑回归进行二元分类的介绍。

我们选哪个门?(图片来自 iStock,授权给 Dennis Loevlie )

二元逻辑回归用于对两个线性可分的组进行分类。这种线性可分的假设使得逻辑回归对于简单的 ML 任务非常快速和强大。我们将对其执行逻辑回归的线性可分数据示例如下所示:

线性可分数据的示例(图片由作者提供)

这里的线性可分群是:

  1. 红色= 0
  2. 蓝色= 1

我们希望使用逻辑回归将任何[ x1x2 ] 对映射到相应的类(红色或蓝色)。

第一步。将我们的数据集分割成训练/测试分割。

我们这样做是为了评估我们的模型在数据上的表现,这些数据在训练中是看不到的。通常,如果你告诉某人你的模型有 97%的准确性,这被认为是你在谈论验证/测试的准确性。

你自己可以很容易地做到这一点,但是说实话,sk learn . train _ test _ split函数在可读性方面非常好。

X_train, X_test, y_train, y_test = train_test_split(
 inputs, labels, test_size=0.33, random_state=42)

步骤 2:构建 PyTorch 模型类

我们可以使用以下代码创建逻辑回归模型:

import torchclass LogisticRegression(torch.nn.Module):
     def __init__(self, input_dim, output_dim):
         super(LogisticRegression, self).__init__()
         self.linear = torch.nn.Linear(input_dim, output_dim) def forward(self, x):
         outputs = torch.sigmoid(self.linear(x))
         return outputs

在 PyTorch 神经网络(实际上只是一个感知器)的“正向”传递中,视觉表示和相应的方程如下所示:

神经网络架构可视化(图片由作者提供)

(图片由作者提供)

其中:

(图片由作者提供)

sigmoid 函数非常有用,主要有两个原因:

  1. 它将我们的线性回归输出转换为从 0 到 1 的概率。然后,我们可以将任何大于 0.5 的概率视为 1,小于 0 的概率视为 0。
  2. 与逐步函数(也会将数据转换为二进制形式)不同,sigmoid 是可微分的,这对于使用梯度下降优化参数是必要的(我们将在后面介绍)。

具有选择蓝色或红色的决策边界的 Sigmoid 函数(图片由作者提供)

步骤 3:初始化模型

此外,我们应该分配一些超参数:

epochs = 200000
input_dim = 2 # Two inputs x1 and x2 
output_dim = 1 # Single binary output 
learning_rate = 0.01

参数定义:

  • 历元 —表示网络已经完成的通过整个训练数据集的次数
  • learning_rate —优化算法中的一个调整参数,用于确定每次迭代的步长,同时向损失函数的最小值移动
    *高学习率意味着您可能永远无法达到最小值。
    *低学习率需要更长时间。

下面的代码初始化了我们之前创建的模型类:

model = LogisticRegression(input_dim,output_dim)

步骤 4:初始化损失函数和优化器

criterion = torch.nn.BCELoss()

二值交叉熵损失 (图片由作者提供)

  • m =训练样本的数量
  • y =真 y 值
  • y^ =预测的 y 值
optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)

有很多常见的神经网络优化器,但大多数都是基于梯度下降。这种优化技术朝着损失函数的最小值前进,其方向由损失函数的梯度决定,即由学习速率决定的权重和幅度或步长。

注:为了准确快速的达到损失函数的最小值,慢慢的降低你的学习速率是有好处的,像 PyTorch 也实现的自适应运动估计算法( ADAM)、这样的优化器,为我们做到这一点。你可以在https://pytorch.org/docs/stable/optim.html找到更多关于这些优化器的 PyTorch 实现。

我们使用以下等式更新参数以最小化损失函数:

(图片由作者提供)

(图片由作者提供)

  • Alpha —学习率

你可能想知道我们从哪里得到 dL/dwdL/dbeta,这将是一个很好的问题!在神经网络中,我们使用反向传播来获得偏导数。幸运的是,在逻辑回归中,方程简化了,我将在下面展示这一点(以及网络的反向投影)。

利用链式法则我们可以推导出:

(图片由作者提供)

偏导数如下所示:

(图片由作者提供)

简单的方程式,你会得到:

(图片由作者提供)

所以在现实中你会这样做:

(图片由作者提供)

我们可以类似地导出 dL/dbeta 。幸运的是,亲笔签名帮助我们做到了这一切!

第五步:训练模型

首先,我们将输入和标签从 numpy 数组转换成张量。

X_train, X_test = torch.Tensor(X_train),torch.Tensor(X_test)
y_train, y_test = torch.Tensor(y_train),torch.Tensor(y_test)

接下来,我们构建训练循环并存储损失。我们还可以不时地打印出测试数据的准确性,看看我们的模型做得如何。

每 10,000 个时期的损失:

BCE 损失与纪元的关系(图片由作者提供)

步骤 6:绘制结果

由于我们知道决策边界将是 wx + b = 0.5* ,我们可以绘制决策边界。结果如下:

列车:

(图片由作者提供)

测试:

(图片由作者提供)

第七步:如何在新数据上获得预测!

如果你有一个新的点在 x1=1x2=1 视觉上(在 2 维空间),很容易告诉我们应该把这个点归类为“红色”。因此,让我们检查我们的模型是否工作正常,并展示如何根据新数据从模型中获得预测:

x1 = 1
x2 = 1
new_data = torch.tensor([x1,x2]).type(torch.FloatTensor)with torch.no_grad():
    prediction = model(new_data).round()
    if prediction == 1.0:
        print(f'The model classifies this point as RED')
    else:
        print(f'The model classifies this point as BLUE')

根据下面的训练数据绘制新点:

根据新数据进行预测(图片由作者提供)

输出:

>>> The model classifies this point as RED

完整代码:

其他资源:

我们连线吧!

  1. 推特
  2. 领英
  3. GitHub

logit——Python 中的全局和局部可解释性

原文:https://towardsdatascience.com/logit-global-and-local-interpretability-in-python-f554acb541e4?source=collection_archive---------28-----------------------

托拜厄斯·凯勒在 Unsplash 上的照片

介绍

Logit 模型是一种回归技术,在给定预测值的情况下,对二元目标的对数概率进行建模。它的简单性(与 Xgboost 这样的锤子相比)使得解释它的决策非常方便。我们探索视觉上解释“模型如何做出决定?”的技术 on 全局(用于建模所取的所有数据)和 local (特定数据点)设置。本文灵感来源于 可解释性机器学习 这本书。

数据和问题陈述

数据可以在 这里 找到,来自一家跨国电信公司。该数据是个人级别的,具有关于地理位置、个人信息(年龄/性别)和基于客户特征的信用评级的特征。目标是一个 bool,它告诉我们一个特定的客户是否从那个公司(flag=1)流失了(【Exited】)。

我们使用 Logit 模型将客户分为流失客户和非流失客户。本 笔记本 有特征选择、拟合优度和解释的实现。这里我们只关注模型的决策。

综上所述,问题陈述是关于预测流失事件的 log odds

读取数据

假设 csv 文件位于项目根目录中

df = pd.read_csv("Churn_Modelling.csv",index_col=["RowNumber","CustomerId","Surname"])df.head()

数据(图片来源-作者)

用于建模的特征

我们使用以下特征进行建模:

  • 年龄(顾客的年龄)
  • 地理位置(客户所在地-法国、德国或西班牙)
  • 性别
  • HasCrCard(客户是否有信用卡)

已经使用视觉分析完成了特征的选择。然而,我们可以使用诸如方差膨胀因子、皮尔逊/卡方/方差分析等技术。例如,从下图中我们可以看到,与西班牙和法国相比,德国有更大比例的客户曾有过不愉快经历。因此,将它作为一个特征将使我们的模型成为一个很好的预测器。

数据分析- 年龄(图片来源-作者)

数据分析- 地理(图片来源-作者)

数据分析- 性别(图片来源-作者)

#Selecting features for the Logit Model
categorical_cols = ["Geography", "Gender",  "HasCrCard",]
non_categorical_cols = ["Age"]

拟合模型

#Creating the Formula
formula = "Exited"+"~"+"+".join(non_categorical_cols)+"+"+\
"+".join([f"C({each_categorcial_col})" for each_categorcial_col\in categorical_cols]) + "-" + "1"#Fitting the Model
logitfit = logit(formula = str(formula),data = df).fit()

解释

现在我们解释模型,为此我们需要首先获得必要的参数。

#Extracting Logit's coefficients and sorting them.
logit_coeffs = logitfit.summary2().tables[1]
logit_coeffs = logit_coeffs.reindex(logit_coeffs["Coef."].abs().sort_values().index)

置信度系数(图片来源-作者)

权重图(全局特征重要性)

我们采用 Logit 模型的系数,并观察它们的相对重要性。系数的值越多(无论是正的还是负的),它们在预测流失类别的对数概率中的影响就越大。这个图是在全球范围内,这意味着它是在所有数据点上计算的。

特征重要性(图片来源-作者)

从该图中,我们推断出年龄是唯一一个其值增加会导致平均流失事件的对数几率增加的特征。

重量图(重要特征)

上面的图显示了系数的点估计,为了显示系数的重要性,我们使用下面的权重图。这考虑了标准误差,并绘制了重量估计值的 95%置信区间。这也是针对所有数据点绘制的。

重要性权重图(图片来源-作者)

我们可以通过目测推断出特征 HasCrCard 在统计上显著。这是因为的重量估计值的 95%置信区间经过了 0

效果图

在权重图中,我们有一个困惑,估计的尺度各不相同。更可靠的方法是将每个特征的权重与其对应的实际特征值相乘,这将为我们提供 Logit 权重对数据的实际影响。实际效果将而不是变化,不像重量图。

为了计算这一点,我们需要使我们的数据虚拟编码 w.r.t the Logit。

#Create Dummies of Categorical Variables
dummy_encoded_df = pd.get_dummies(df[non_categorical_cols+categorical_cols],\columns=["Geography"])#Order the columns in order to multiply with weights
dummy_encoded_df = dummy_encoded_df[["HasCrCard", "Age",\ "Gender","Geography_Germany", "Geography_Spain",\ "Geography_France",]]dummy_encoded_df["Gender"] = dummy_encoded_df["Gender"].map({"Female":0, "Male":1})dummy_encoded_df.head()

虚拟编码数据(图片来源-作者)

计算实际效果:

# Multiply Dummy Encoded data with actual weights from Logit
effects = dummy_encoded_df * logit_coeffs['Coef.'].to_numpy()
effects.head()

实际效果(图片来源-作者)

效果图(图片来源-作者)

特征年龄地理当然对流失预测的对数几率有很大影响。

局部可解释性

为了解释单个数据点,我们将单个数据点的效果(显示为红点)叠加在效果图上。这有助于我们推断回归计算中单个数据点的影响。

  1. 这里我们考虑一个客户,他的预测对数概率是大于0.5。

预测对数概率比 0.5的客户(图片来源-作者)

以上数据点的局部效果(图片来源-作者)

让我们考虑上面的红点,它标记了数据点的个体效应。在这种情况下,年龄对对数赔率计算有重大影响,这抵消了地理位置性别(具有影响)的组合影响,并将对数赔率值拖至大于 0.5

这与数据分布是一致的,正如我们在上面的方框图中看到的那样,与那些没有频繁购买的客户相比,频繁购买的客户的平均年龄更高。

2.接下来,我们考虑一个客户,其预测对数概率比 0.5

预测对数概率比 0.5的客户(图片来源-作者)

以上数据点的局部效果(图片来源-作者)

让我们考虑上面的红点,它标记了数据点的个体效应。在这种情况下,客户身在法国,是一名男性且年龄为 31 的事实使得对数几率大大小于 0.5 。地理和性别效应将它拖向负值,甚至年龄效应也拖向年龄效应分布的左尾(<25%平铺)。

这与数据分布非常同步。法国客户的流失率最低,年龄较低的客户平均流失率也较低。

感谢你的阅读!

参考

Molnar, Christoph. "Interpretable machine learning. A Guide for Making Black Box Models Explainable", 2019\. [https://christophm.github.io/interpretable-ml-book/.](https://christophm.github.io/interpretable-ml-book/.)

Colab 上的笔记本全代码

对数分析-重访新冠肺炎投影

原文:https://towardsdatascience.com/loglet-analysis-revisiting-covid19-projections-5e9d14a46f2?source=collection_archive---------76-----------------------

Loglet 分析(将增长分解为 S 形逻辑成分)是对新冠肺炎扩散的更好预测,因为它考虑了多次波动的演变。

图 01:用 KNIME & Jupyter-Notebook 进行 Loglet 分析(图片由作者提供)

注来自《走向数据科学》的编辑: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语

的上一篇文章 中,我们展示了如何使用来自约翰霍普金斯学院的 covid 数据,通过 KNIME、Jupyter 和 Tableau 对未来 30 天进行预测。这些预测为逻辑增长模型进行了优化。我们将展示将生长分解成 S 形逻辑成分也称为 对数分析 更准确,因为它考虑了多个 covid 波的演变。

1994 年洛克菲勒大学创造的术语“ Loglet ”将“逻辑”和“小波”结合在一起。Loglet 分析很有趣,因为它可以处理多峰曲线,这是曲线拟合技术的常见挑战。

复制生物(例如病毒)的生长基本上以三个生长阶段为特征:

  1. 指数生长
  2. 逻辑增长
  3. 多元逻辑增长

指数增长

在第一阶段,增长是指数级的。在数学术语中,人口增长率 P(t)与人口数量成正比。时间 t 的增长率定义为导数 dP(t)/dt。

指数增长模型被写成一个微分方程:

图 02:指数增长模型(图片由作者提供)

这个方程可以通过引入 e(自然对数的底数,约为 2.71)来求解。。。).
大家熟悉的解决方案是:

图 03:指数增长模型的解(图片由作者提供)

其中“a”是增长率常数,“b”是初始种群 P(0)。“a”通常以百分比表示。例如,值为 0.02 的“a”相当于“人口以每年 2%的速度持续增长”。尽管许多种群在一段时间内呈指数增长,但除非系统的参数或极限发生变化,否则没有一个有限系统能够无限维持指数增长。

让我们试着想象一下 Jupyter 笔记本电脑的这种增长:

**import** **matplotlib.pyplot** **as** **plt**
**import** **numpy** **as** **np**
**import** **pandas** **as** **pd**t = np.arange(1, 100)
a = 0.1
b = 1
y= b*np.exp(a*(t))

plt.plot(t,y)
plt.show()

图 04:指数增长(作者图片)

2。逻辑增长 由于很少有系统随着时间的推移保持指数增长,指数增长方程必须用一个极限或承载能力来修正,使其具有更真实的乙状结肠形状。
指数增长模型中应用最广泛的修正是 logistic 模型。它由 Verhulst 在 1838 年引入,但在 20 世纪 20 年代由 Lotka 在数学生物学中推广。逻辑方程从指数模型开始,但增加了一个“负反馈”项,当接近极限 K 时,会减慢种群的增长率:

图 05: Logistic 微分方程(作者图)

请注意,当 P (t) << K and approaches zero as P(t) -> K 时,反馈项(1-P(t))/K 接近 1。因此,增长率开始呈指数增长,但随后随着种群 P(t)接近极限 K 而降至零,形成 S 形(乙状结肠)增长轨迹。

logistic 微分方程有许多封闭形式的解。我们将使用 Fisher-Pry 方程进行进一步分析:

图 06: Logistic 增长函数(作者图)

上面的等式产生了熟悉的 S 形曲线。完全指定曲线需要这三个参数,“a”、“b”和 k。生长速率参数“a”指定乙状结肠曲线的“宽度”。

让我们再次尝试想象一下 Jupyter 的增长:

t = np.arange(0, 100)
K = 100
a = 0.1
b = 50

y = K/(1+np.exp(-a*(t-b)))

plt.plot(t,y)
plt.show()

图 07:逻辑斯蒂增长(作者图片)

此外,用一个变量代替“α”通常更好,该变量指定曲线从极限 K 的 10%增长到 90%所需的时间,我们称之为特征持续时间δt。

图 08:曲线从 10%增长到 90%所需的时间(作者图片)

为了实现这一点,我们必须执行以下代数变换。首先,我们计算达到总增长率 90%所需的时间。

图 09:达到生长 90%的计算时间(作者图片)

然后是达到总增长率 10%的时间,我们从这个值中减去 90%。特征持续时间与“a”的关系为 ln(81)/δt。

图 10:特征时长(作者图片)

对于历史时间序列数据的分析,参数δt 通常比“a”更有用,因为单位更容易理解。三个参数 K、∞、t 和“b”定义了逻辑模型的参数化,该逻辑模型被用作我们的 Loglet 分析的基本构造块。

图 11:log El 分析基本建筑设计框图(作者图片)

3。多逻辑增长上一篇文章中,我们展示了逻辑增长模型可以很好地近似 covid19 波的演化。但是由于这种传播不局限于单个波,我们需要一种扩展的方法来描述整个过程。
许多成长过程由几个子过程组成。首先,让我们建立一个经历两个独立阶段增长的系统模型。然后,我们将这个模型扩展到任意数量的阶段。在所谓的双逻辑模型中,增长是两个“小波”的总和,每个小波都是逻辑的:

图 12:双逻辑模型(图片由作者提供)

在哪里

图 13:双对数小波(作者图片)

双逻辑模型的实现需要 6 个参数,在 Jupyter 中显示如下:

t = np.arange(1, 100)

K1 = 100
dt1 = 40
b1 = 50

K2 = 400
dt2 = 20 
b2 = 80

y = K1/(1+np.exp(-np.log2(81)/dt1*(t-b1))) + \
    K2/(1+np.exp(-np.log2(81)/dt2*(t-b2)))

plt.plot(t,y)
plt.show()

图 14:双对数增长(作者图片)

下图显示了双对数波的分解。蓝色脉冲被随后的橙色脉冲叠加。这样,看似复杂的行为被简化为两个逻辑小波的和。

y1 = K1/(1+np.exp(-np.log2(81)/dt1*(t-b1)))
y2 = K2/(1+np.exp(-np.log2(81)/dt2*(t-b2)))

plt.plot(t,y1)
plt.plot(t,y2)
plt.show()

图 15:双对数波的分解(图片由作者提供)

下一步是将双物流模型推广为多物流模型,其中增长是 n 个简单物流的总和:

在哪里

图 16:多重逻辑函数(作者图片)

以下 Jupyter 代码也可在我的 github 网站上获得,它预测了瑞士未来 30 天的预期新冠肺炎病例,并需要 4 个逻辑小波的组合。对于其他国家,需要不同数量的小波。我们将在下面谈到这一点。
使用 Jupyter 中 scipy 软件包的 curve_fit 功能对模型进行拟合。

**import** **matplotlib.pyplot** **as** **plt**
**import** **numpy** **as** **np**
**import** **pandas** **as** **pd**
**from** **scipy.optimize** **import** curve_fitpath = 'https://raw.githubusercontent.com/deganza/Loglet-analysis-revisiting-covid19-projections/main/covid_daten_knime.csv'
df_country = pd.read_csv(path)df_country_exp = pd.DataFrame()

df_country_list = df_country.groupby(['Country']).last().reset_index()
country_list = df_country_list['Country'].to_list()df_country_period = df_country
zeilen = df_country_period['cases'].count()*# Select country or for evaluation of every country remark the variable country_list*

*#country_list =['Austria','Switzerland','Germany','United Kingdom','Spain']*
*#country_list =['United Kingdom']*
*#country_list =['Germany']*
*#country_list =['Spain']*
country_list =['Switzerland']
*#country_list =['Poland']*
*#country_list =['Turkey']*
*#country_list =['US']*

df_country_exp = pd.DataFrame()

*#logistic functions*

**def** logistic_function1(x,b1,dt1,K1,b2,dt2,K2,b3,dt3,K3,b4,dt4,K4):
    **return** K1/(1+np.exp(-np.log2(81)/dt1*(x-b1)))

**def** logistic_function2(x,b1,dt1,K1,b2,dt2,K2,b3,dt3,K3,b4,dt4,K4):
    **return**  K1/(1+np.exp(-np.log2(81)/dt1*(x-b1))) + K2/(1+np.exp(-np.log2(81)/dt2*(x-b2)))

**def** logistic_function3(x,b1,dt1,K1,b2,dt2,K2,b3,dt3,K3,b4,dt4,K4):
    **return**  K1/(1+np.exp(-np.log2(81)/dt1*(x-b1))) + K2/(1+np.exp(-np.log2(81)/dt2*(x-b2))) + K3/(1+np.exp(-np.log2(81)/dt3*(x-b3)))

**def** logistic_function4(x,b1,dt1,K1,b2,dt2,K2,b3,dt3,K3,b4,dt4,K4):
    **return**  K1/(1+np.exp(-np.log2(81)/dt1*(x-b1))) + K2/(1+np.exp(-np.log2(81)/dt2*(x-b2))) + K3/(1+np.exp(-np.log2(81)/dt3*(x-b3))) + K4/(1+np.exp(-np.log2(81)/dt4*(x-b4)))

**for** country **in** country_list:

        df_country_modell = df_country_period[df_country['Country'] == country]

        expdays = 30
        wave = 0

        datum = pd.date_range(start=df_country_modell['Date'].max(), periods=expdays)
        datum = pd.date_range(start=df_country_modell['Date'].min(),end=datum.max())
        datum = datum.strftime("%Y-%m-**%d**")

        zeilen= df_country_modell['cases'].count()
        x = np.arange(1,zeilen+1)
        x_exp = np.arange(1, x.max() + expdays  )
        y = df_country_modell['cases'] 

        y_min = y.min()
        y = y - y_min

        **try**:   
            popt, pcov = curve_fit(logistic_function4, x, y  )
            y_exp = (logistic_function4(x_exp, *popt))    

            df = pd.DataFrame({'day':x_exp, 'expected':y_exp,'datum':datum, 'Country' : country})
            df_country_exp = df_country_exp.append(df)

            wave=4
            print(country,wave)

        **except** **RuntimeError**:
            **try**:
                popt, pcov = curve_fit(logistic_function3, x, y  )
                y_exp = (logistic_function3(x_exp, *popt)) 

                df = pd.DataFrame({'day':x_exp, 'expected':y_exp,'datum':datum, 'Country' : country})
                df_country_exp = df_country_exp.append(df)

                wave=3
                print(country,wave)

            **except** **RuntimeError**:
                **try**:
                    popt, pcov = curve_fit(logistic_function2, x, y  )
                    y_exp = (logistic_function2(x_exp, *popt)) 

                    df = pd.DataFrame({'day':x_exp, 'expected':y_exp,'datum':datum, 'Country' : country})
                    df_country_exp = df_country_exp.append(df)

                    wave=2
                    print(country,wave)

                **except** **RuntimeError**:
                    **try**:
                        popt, pcov = curve_fit(logistic_function1, x, y  )
                        y_exp = (logistic_function2(x_exp, *popt)) 

                        df = pd.DataFrame({'day':x_exp, 'expected':y_exp,'datum':datum, 'Country' : country})
                        df_country_exp = df_country_exp.append(df)

                        wave=1
                        print(country,wave)    

                    **except** **RuntimeError**:
                        print(''.join(country) +  ": Error - curve_fit Log failed")

df_country_exp.reset_index(drop=**True**, inplace=**True**)
print('finished')
print(zeilen)

对于每个国家,该模型都符合几个逻辑脉冲,并计算出最佳描述病毒传播的参数。

需要多少训练数据? 我们现在已经创建了一个可以近似多个连续且重叠的 covid 波的模型。但现在问题来了:我们要考虑多少浪?这是一个还没有计算出来的参数。

如果你想定义未来,就研究过去
孔子

的最后一篇文章中,我们决定只考虑过去 90 天的案例,以符合我们的逻辑模型。有了我们新的多元逻辑模型,这个限制就不再必要了,因为我们可以使用疫情疫情爆发第一天的数据。但是现在我们有了一个新的参数来选择小波的数目。这是一个开放点,我们决定采取以下策略:
现在是 2021 年 1 月。对于每个国家,我们开始用 4 个小波来拟合模型。如果模型不收敛,我们将其减少到 3 个小波等等,直到我们找到最佳逼近。

将所有这些放在一起 使用上面的代码已经可以对每个国家进行预测,但是我们希望在我们现有的 KNIME-Workflow 流程中实现它,以实现更好的数据转换和随后的 Tableau 可视化。
正如您在上一篇文章中所记得的,我们使用 KNIME 加载来自约翰·霍普金斯研究所的 covid19 数据,对其进行转换,并使用 Jupyter 计算预测。最后,我们将数据导出到 Tableau 中进行可视化。

图 17: KNIME 工作流:加载数据,计算预测,并将其导出到 Tableau 中(图片由作者提供)

KNIME-workflow 在我的 KNIME-hub 站点上可用,Tableau 仪表盘几乎每天都在我的 Tableau-Public 站点这里上发布实际数据

图 18: Covid19 Tableau-Dashboard,带有未来 30 天的预测(图片由作者提供)

这种扩展的对数预测方法比简单的对数分析更灵活,因为它考虑了连续波的演变。因此,可以更快地跟踪和推断病毒的新波动或变异。这变得越来越重要,因为这种病毒已经在英国和南非变异成传染性更强的版本。

https://medium.com/@deganza11/membership

跟我上 LinkedinTwitter 以及跟我上的脸书群 数据科学跟 yo dime

***本项目材料***:
Jupyter-Code:
github knime-workflow:knime-hub Tableau-Dashboard:Tableau-Public

***参考资料
-*-
Covid 19-用 Knime、Jupyter 和 Tableau 进行预测

为首次发表于KD nuggets**

Plotly 的棒棒糖和哑铃图表

原文:https://towardsdatascience.com/lollipop-dumbbell-charts-with-plotly-696039d5f85?source=collection_archive---------11-----------------------

均值还是中值?

图片由来自 Unsplash 的 Eskay Lim 提供

棒棒糖图(LC)是条形图的一种便利变体,其中条形图由一条线和一个点代替。它们是二维的,有两个轴:一个轴显示类别或时间序列,另一个轴显示数值。这些数值由线末端的点的位置表示。垂直方向的 LC 在 y 轴上显示分类变量,而水平方向的 LC 在 x 轴上显示分类变量。

就像条形图一样,棒棒糖图用于在不同项目或类别之间进行比较。它们也用于排名或显示随时间变化的趋势。我们只比较每个项目或类别的一个数字变量。它们不适用于关系、分布或构成分析。

当您不得不显示大量类似的高值时,LCs 比条形图更受欢迎。在标准条形图的情况下,您可能会得到一个杂乱的图表,并体验到一种称为 莫尔条纹的视觉效果。 虽然等同于条形图,但是这种等同只对 标准条形图有效;不要试图将其扩展到堆叠、 聚集、重叠条形图。

另一方面,哑铃图 (DC)是簇状条形图和斜率图的替代品。也被称为 DNA 图,它们表示两个数据点之间的变化。每个点对应一个数值,在同一个维度上以非常直接的方式进行比较。

在比较点与点之间的差异、范围、分布或距离时,它们非常有效。它们用于在类别之间进行比较,或者观察两个时间间隔之间的趋势。

图 0 显示了一个示意性的垂直方向哑铃图。

图 0:作者用 Plotly 做的哑铃图。

集中趋势的度量

专业数据科学家应该熟悉用于描述其研究或项目观察结果的不同统计方法。他们应该非常熟悉的集中趋势的常用度量是均值、中值和众数。

数据集的均值是通过将数据集中的所有数字相加,然后除以其中值的个数得到的。当数据集从最小到最大排序时,中值是中间值T5。 Mode 是集中趋势的度量,代表数据集中出现频率最高的值。

由于有许多外部因素限制了均值的使用,中位数被广泛使用,尤其是在偏态分布中。中位数被认为是对异常值稳健的,而平均值被认为是对异常值敏感的。请记住,离群值(异常值)是一段与数据集中所有其他数据都非常不同的数据,并且似乎不符合相同的模式。中位数通常给出了更恰当的数据分布概念。

棒棒糖和哑铃图表与 Plotly

面向对象的人物创作界面 Plotly Express 于 2019 年发布。它是 Plotly.py 的高级包装器,包括绘制标准 2D & 3D 图表和 choropleth 地图的函数。与 Plotly 生态系统的其余部分完全兼容,是快速开发探索性图表的优秀工具。

Plotly 提供了一组名为 graph objects 的类,可用于构建图形。 plotly.graph_objects 模块包含 Python 类的层次结构。是初级类。有一个数据属性和一个布局属性。数据属性有 40 多个对象,每个对象引用一个特定类型的图表( trace) 及其相应的参数。布局属性指定图形的整体属性(轴、标题、形状、图例等。).

我们使用了从社区 GitHub [1]下载的公共数据集。该数据集包含与世界财富和收入相关的记录。我们想知道哪种集中趋势度量最适合分析数据集。

首先,我们导入 Plotly Express 为 px,模块 plotly.graph_objectsgo ,Pandas 库为 pd ,并将我们的 csv 文件转换成数据帧:

import pandas as pdimport plotly.express as pximport plotly.graph_objects as godf_Ww = pd.read_csv(path + 'WorldWealth.csv', 
                    index_col = False,
                    header = 0, sep = ';', engine='python')

数据存储在文件中的方式不是我们绘图所需的方式。由于每一列都存储为一个对象类型,我们需要将列*Median_Wealth**Mean_Wealth* 转换为整数:

df_Ww['Mean_Wealth']   = df_Ww['Mean_Wealth'].str.replace(
                               ',', '').astype(str).astype(int)df_Ww['Median_Wealth'] = df_Ww['Median_Wealth'].str.replace(
                               ',', '').astype(str).astype(int)types = df_Ww.dtypes

下面的屏幕截图显示了转换后的数据帧的前十条记录:

完成这三行代码后,我们就可以画棒棒糖图了。

我们用 .add_trace(go.Scatter(画点,用 .add_shape(type=’line画相应的线。我们选择通过在 y 轴上显示分类变量[“Country”]来绘制水平方向的 LC。我们使用mode = ‘markers’来选择一个点标记。

使用fig1.add_shape(type='line'. 将独立行添加到图中。注意,我们使用 for 循环的计数器变量来设置y0y1 值。

我们用update.layout更新了图表:设置标题和字体大小。我们设置了template= ‘seaborn+ygridoff’:在这种情况下,通过合并两个注册模板 (seaborn & ygridoff)的集合来计算结果模板。我们用宽度和高度来定义图形尺寸。然后我们更新了 x 轴(标题和范围)。我们将图表保存为静态的 png 文件,最后,我们绘制了图表。

首先,我们根据财富中值对前 15 个国家进行了排名:

df_WwT = df_Ww.sort_values(by = ['Median_Wealth'],
                    ascending = False).iloc[0:15].reset_index()fig1 = go.Figure()# Draw points
fig1.add_trace(go.Scatter(x = df_WwT["Median_Wealth"], 
                          y = df_WwT["Country"],
                          mode = 'markers',
                          marker_color ='darkblue',
                          marker_size  = 10))# Draw lines
for i in range(0, len(df_WwT)):
               fig1.add_shape(type='line',
                              x0 = 0, y0 = i,
                              x1 = df_WwT["Median_Wealth"][i],
                              y1 = i,
                              line=dict(color='crimson', width = 3))# Set title
fig1.update_layout(title_text = 
                   "Median Wealth (U$S) Top 15 Countries",
                   title_font_size = 30)# Set x-axes range
fig1.update_xaxes(title = 'Median Wealth' , range=[0, 250000])fig1.write_image(path + "figlollipop1.png")fig1.show()

图 1:作者用 Plotly 做的棒棒糖图。

然后,我们根据平均财富对排名最低的 15 个国家进行了排名:

df_WwB = df_Ww.sort_values(by = 
                   ['Mean_Wealth']).iloc[0:15].reset_index()fig2 = go.Figure()# Draw Points
fig2.add_trace(go.Scatter(x = df_WwB["Mean_Wealth"], 
                          y = df_WwB["Country"],
                          mode = 'markers',
                          marker_color ='darkorange',
                          marker_size  = 10)# Draw Lines
for i in range(0, len(df_WwB)):
               fig2.add_shape(type='line',
                              x0 = 0, y0 = i,
                              x1 = df_WwB["Mean_Wealth"][i],
                              y1 = i,
                              line=dict(color='crimson', width = 3))# Set title
fig2.update_layout(title_text =
                   "Mean Wealth (U$S) Bottom 15 Countries",
                    title_font_size = 30)# Set x-axes range
fig2.update_xaxes(title = 'Mean Wealth', range=[0, 2000])fig2.write_image(path + "figlollipop2.png")fig2.show()

图 2:作者用 Plotly 做的棒棒糖图。

然后,我们设计了两个水平方向的哑铃形图表,比较 15 个排名靠前的国家和 15 个排名靠后的国家的平均财富和中值财富。现在我们需要两个.add_trace(go.Scatter(:一个是平均财富点,另一个是中等财富点。关于.add_shape(type=’line’,我们用df_WwT[“Median_Wealth”][i表示x0,用df_WwT[“Mean_Wealth”][i] 表示x1

fig3= go.Figure()fig3.add_trace(go.Scatter(x = df_WwT["Median_Wealth"], 
                          y = df_WwT["Country"],
                          mode = 'markers',
                          marker_color = 'darkblue',
                          marker_size = 10,
                          name = 'Median'))fig3.add_trace(go.Scatter(x = df_WwT["Mean_Wealth"], 
                          y = df_WwT["Country"],
                          mode = 'markers',
                          marker_color = 'darkorange', 
                          marker_size = 10,
                          name = 'Mean'))for i in range(0, len(df_WwT)):
               fig3.add_shape(type='line',
                              x0 = df_WwT["Median_Wealth"][i],
                              y0 = i,
                              x1 = df_WwT["Mean_Wealth"][i],
                              y1 = i,
                              line=dict(color='crimson', width = 3))fig3.update_layout(title_text =
                    "Mean vs Median (U$S) Top 15 Countries",
                    title_font_size = 30)fig3.update_xaxes(range=[0, 600000])fig3.write_image(path + "figdumbbell1.png")fig3.show()

图 3:作者用 Plotly 做的哑铃图。

图 4 的代码与图 3 的代码相同,除了我们使用了 df_WwB而不是df_WwT.

图 4:作者用 Plotly 做的哑铃图。

当你有一个正态分布的样本时,你可以用平均值或中值来衡量集中趋势。在任何对称分布中,平均值、中值和众数都是相等的。我们的数据(前 15 个国家和后 15 个国家)并非如此:平均值总是大于中位数。这清楚地表明数据是右偏的。在这些情况下,中位数通常被认为是集中趋势的最佳衡量标准。中位数没有受到非常富有的人的扭曲价值的强烈影响,并为我们的数据提供了最佳的中心位置。我们的哑铃图显示的差异证实了这一假设。

总之

棒棒糖图的使用情况与标准条形图完全相同,它以相同的方式对数值进行编码:线条的长度和线条末端的点的位置相当于水平或垂直矩形条的长度或高度。当您处理大量相似的数值时,棒棒糖图比条形图更受欢迎。哑铃图是简单的图表,可以快速直接地显示差异、变化、范围和相似性。它们允许将大量信息编码到一个易于理解的图表中。

如果你发现了这篇感兴趣的文章,请阅读我之前的(https://medium.com/@dar.wtz):

分歧棒线,为什么&如何,用分歧讲故事

斜率图表,为什么和如何,用斜率讲故事

参考文献

[1]:https://github . com/datasets/world-wealth-and-income-database/commit/33a 44291 E4 d6f 76 be 066 f 0912 b 6 DC 033 d9 ECE 59 e

使用 K-均值聚类的伦敦便利店分类

原文:https://towardsdatascience.com/london-convenience-store-classification-using-k-means-clustering-70c82899c61f?source=collection_archive---------16-----------------------

伦敦的便利店怎么分类?

Viki Mohamad 在 Unsplash 上拍摄的照片

英国的便利店可归类为面积小于 3,000 平方英尺的商店,靠近消费者的家或白天有大量人口,产品范围广泛但不丰富。这意味着它们主要面向希望从主要商店购买额外商品的消费者、经常光顾但规模较小的商店的消费者,以及可能只想在办公室购买午餐的消费者。

这些小商店越来越成为英国杂货零售店持续扩张的工具,因为它们需要较小的门槛人群才能盈利,它们可以适应消费者对更多便利的不断变化的需求,它们在当前的规划制度下更容易建设,它们被视为独立于大型杂货店的市场,这意味着竞争监管对于现有的国家杂货零售商变得不那么重要。

因此,相对于大型超市和超级市场商店,国家杂货零售商认为这些是近年来更可行的扩张选择。从某种程度上来说,从 2003 年到 2012 年,全国杂货店的大部分增长是由于 Co-op、Tesco 和 Sainsbury's 等零售商开设了便利业态。这意味着到 2015 年,22%的食品杂货市场被便利店占据。

虽然便利业态最初采取的形式是位于居民区附近的独立街角商店,但随着独立便利零售商的数量减少,它已经转向大型全国性零售商和伞式组织。这种形式的目的也发生了变化,因为尽管便利店是根据其规模进行分类的,但它们可以位于非常不同的区域,例如靠近办公人群的市中心商店,靠近交通节点以吸引大量步行人流的商店,或靠近居民区以吸引夜间人群的商店。因此,能够对这些商店进行分类,以了解它们的位置如何影响它们销售什么、向谁销售以及何时销售产品变得非常重要。此处的分析遵循 Hood 等人(2016)提出的方法,该方法对英国约克郡和亨伯地区的便利店零售商进行了分类。这样做的目的是复制伦敦的分析,并为此创建一个 Jupyter 笔记本。

为此,使用与 Hood 等人(2016 年)类似的输入数据,我们将使用:居住人口、日间人口、其他零售景点、交通节点附近以及按社会分类的居住人口。这是因为这些因素被认为与已知的销售数据相关,并与特定的客户任务相关联。这些数据可以从 2011 年伦敦人口普查数据、国家公共交通访问节点和 OpenStreetMaps (OSM)数据集提取。为此,使用包含英国主要杂货零售商信息的 Geolytix dataset⁴提取伦敦的便利店,包括它们的尺码范围。从伦敦范围内和大小范围 A ( < 3,013 𝑓𝑡ft (280 𝑚)内的商店中提取,留给我们来自 13 个主要杂货零售商的 997 家便利店。该结果数据中的主要零售商是:

作者图片

正如我们所看到的,这个数据集中的便利店主要是 Tesco,Sainsbury's 和 Co-operative Group。

为此,我们对便利店 1 公里范围内的人口、公共交通站和零售店感兴趣,因为这被视为典型消费者愿意步行到这些类型的商店的最大距离,并且是这些商店周围缓冲区的行业标准,用于分析目的。

首先,可以使用 OSM api 使用以下代码从这些便利店周围 1 公里范围内提取零售商店:

#to reduce the need to call the osm api we can store the data after the first collection
Cleaned_convenience_surrounding_retail = os.path.join("Data", "stores_with_surrouding_retail.shp")#if the data already exists in order to reduce time waiting on the #api call then we can read it in
if os.path.exists(Cleaned_convenience_surrounding_retail):
    #read in the cleaned results
    London_convenience_stores = gpd.read_file(Cleaned_convenience_surrounding_retail)#if this is done for the first time:
else:
    #set the tag of the building as retail usage
    tags = {"building":["retail"]} #create an empty list of retailers nearby
    retail_nearby = {} #iterate over each row in the London_convenience_stores_dataset
    for index, row in London_convenience_stores.iterrows():

        #extract the buildings within a 1km radius
        buildings = ox.geometries_from_point((row["lat_wgs"],     row["long_wgs"]), tags, dist = 1000)
        #add the number of buildings to the dictionary
        retail_nearby[row["store_name"]] = len(buildings)

    #set the column to the number of stores nearby based on the dictionary results
    London_convenience_stores["stores_nearby"] = London_convenience_stores["store_name"].map(retail_nearby)

    #output the results to a shapefile
    London_convenience_stores.to_file(Cleaned_convenience_surrounding_retail, index=False)

然后可以将其添加回原始数据集中。通过在便利店周围生成一个 1km 的缓冲区,并查找该缓冲区内的停靠点数量/居住人口数量/人口类型/工作场所人口数量,可以将剩余的数据连接到便利店信息。缓冲区本身可以通过以下方式生成:

London_convenience_buffer = London_convenience_stores.buffer(1000)

使用空间连接来查找 1km 缓冲区内的停靠点数量:

London_convenience_stores_transport = gpd.sjoin(stops_geo,
                                                London_convenience_stores_buffer,
                                                how = "inner",
                                                op = "within")#we then want the number of stops which can be found using the size attribute
London_convenience_stores_transport = (London_convenience_stores_transport.groupby(["store_name"], 
                                                                                   as_index=False)
                                       .size())#renamethe size column
London_convenience_stores_transport.rename(columns = {"size":"transport_nearby"}, inplace=True)

和叠加分析,找出 1km 边界内输出区域或工作区的百分比:

#we want to find the area of overlap between buffers and the workplace zone
#this is so that we can calculate the percentage of population later
WZ_overlap = gpd.overlay(London_convenience_stores_buffer[["store_name",    "geometry"]], 
             UK_WZ[["wz11cd", "geometry"]], how = "intersection")#calcualte the area of the workplace zone
UK_WZ["area"] = UK_WZ.area
#claculate the area of teh overlapped area
WZ_overlap["overlap_area"] = WZ_overlap.area#merge the overlap with the workplace zone 
WZ_overlap = WZ_overlap.merge(UK_WZ,
                             on = "wz11cd",
                             how = "left")#calculate the area for each workplace zone that lies within the overlap
#this is so we can get a percentage of population
WZ_overlap["area_perc"] = WZ_overlap["overlap_area"]/WZ_overlap["area"]#merge the resulting data with that of the population datadrame
WZ_overlap = WZ_overlap.merge(UK_WZ_pop[["GEO_CODE", "workplace_population"]],
                             left_on = "wz11cd",
                             right_on = "GEO_CODE",
                             how = "left")#calcualte the actual amount of workplace population within the immediate zone
#this assumes that workplace population is evenly distributed within a workplace zone
WZ_overlap["WZ_area_pop"] = WZ_overlap["area_perc"] * WZ_overlap["workplace_population"]#we then want this by each store so we groupby the store name
Workzone_pop = WZ_overlap.groupby(["store_name"], as_index=False).agg({"WZ_area_pop":"sum"})

其可用于计算该边界内居住和日间人口的实际数量,假设每个输出区域和工作场所区域内人口的平均分布,以及社会分类 1(高级管理、行政和专业职业)内工作成人的百分比。

这些变量在悬挂物周围的分布导致:

作者图片

显示了长尾分布。因此,由于聚类使用距离度量,并且对数据集中的变化敏感,所以所有变量都经过对数变换和标准化,以确保数据集中的尺度和变化相同。

为了确定要识别的聚类数量,使用了肘图和轮廓得分方法,并从数据中得出以下图:

作者图片

这些结果表明 2 或 3 个聚类将是合适的(最大的轮廓分数和肘部的开始),然而,轮廓分数也表明 6 或 7 个聚类也可能是合适的。根据结果的地理分布、聚类的大小和其中的变量来检查这些数量的聚类,6 个聚类被认为是最实用的,因为它们易于地理和变量解释,并且每个聚类内的商店数量分布大致均匀。这些集群可以表示如下:

作者图片

作者图片

这些可以解释为:

集群 1——以住宅和零售为主

这些集群的位置出现在主要人口中心周围,并且位于其他零售位置附近。在伦敦市中心及其周围,这些很可能在拥有大量居民的主要大街附近被发现。

集群 2——分布式便利店

这些便利店并不位于任何其他吸引因素附近,可能位于伦敦边缘的主要私人交通节点附近。它们既不靠近任何居民区或白天活动的人群,也没有任何数量可观的其他零售点,表明它们是单独设置的。

集群 3——以零售为重点

这些便利店主要集中在零售商店附近和富裕住宅区附近,但这两者都比集群 1 少。这些商店可能位于二级大街上,就零售或人口而言,它们都不是主要的景点,远离伦敦市中心,因此人口密度较小。

集群 4——关注工作场所

这些便利店主要位于工作场所人口高度集中的地方,以及主要位于伦敦市中心的交通站附近。这些很可能在早上和晚上严重依赖于交通工具的步行交通,而在白天则依赖于工作场所的人口来维持。

集群 5——以富裕住宅为主

这些便利店往往位于富裕的住宅区。这些可能是你在高人口密度地区的街角商店,周围很少有其他零售店。他们整天依赖于居住人口。

集群 6 —不太富裕的住宅集中

这些便利店主要集中于居住人口,类似于集群 5,但在不太富裕的地区也是如此。它们主要位于人口密度较低的区域,这些区域附近的零售商店或交通站比集群 5 中的要少。

理解这一点很重要,因为可能服务于这些便利店的人群将会影响他们在有限的商店空间内提供什么类型的产品以及他们可能会很忙的时间。这也对哪些商店将在整个冠状病毒期间经历财富的变化具有重要影响,因为在此期间,以住宅为重点的商店可能会增加收入,而以工作场所为重点的商店可能会减少收入,甚至暂时关闭。这种情况可能会再次发生变化,因为我们正朝着混合工作制的办公室回归,因为与前几个月相比,住宅商店的需求可能会下降,而以工作场所为重点的商店可能会重新开业,尽管混合工作制可能不足以支持所有这些商店的重新开业。

代号:https://github.com/PhilipDW183/Convenience_store

[1] Baron,s .,Harris,k .,Leaver,d .和 Oldfiel,b .,2001 年。超越便利:英国独立食品和杂货零售商的未来。《零售、分销和消费者研究国际评论》,第 11 卷第 4 期,第 395-414 页。

[2]伍德和麦卡锡博士,2014 年。英国食品零售的“空间竞赛”和市场饱和:当代评论。《国际零售、分销和消费者研究评论》, 24 卷 2 期,第 121–144 页。

[3]n .胡德,g .克拉克和 m .克拉克,2016 年。为零售选址规划细分不断增长的英国便利店市场。《零售、分销和消费者研究国际评论》, 26(2),第 113-136 页。

[4]https://geolytix.com/(开放数据许可:https://drive.google.com/open?id = 1 b 8m 7m 86 rqg 2 sx 2 tshhfa 2d-x-dz 1 dbsy

前瞻决策树算法

原文:https://towardsdatascience.com/lookahead-decision-tree-algorithms-1a531897d15c?source=collection_archive---------12-----------------------

决策树中的前瞻机制可以产生更好的预测

图片由来自 PixabaySteve buiss NNE拍摄

TL;博士:我证明了具有单步前瞻机制的决策树可以胜过标准的贪婪决策树(没有前瞻)。在样本数据集中没有观察到过度拟合或前瞻病理。

为什么要向前看?

假设我们试图预测一个潜在的工作候选人能否在他的工作中成功。

来自像素库像素的图像

我们有一个历史数据集,使我们能够建立一个预测模型。

作者图片

“成功”是我们的目标变量,我们在预测模型中使用了 3 个分类特征:

  • 角色资历
  • 候选人资历
  • 学历

让我们的例子简单一些,假设这些特征取两个值“高”或“低”中的一个。

假设我们使用 scikit-learn 的默认参数构建一个 2 级决策树。下面是生成的拆分。

作者图片

请注意,决策树能够生成候选人可以落入的 4 个最终叶子/桶。候选人的预测成功率是 67%、50%、0%或 50%,这取决于他属于哪个左/桶。

我们没有得到一个明确的树叶分裂,其中候选人要么 100%成功,要么在所有桶 0%。决策树的目标是区分潜在的成功候选人和不成功的候选人。

实际上,本可以产生一个更好的分割…

在我们的示例中,如果候选人资历和角色资历都很高或都很低,则候选人会成功,因为候选人的资历和角色所需的资历非常匹配。这种情况 100%都会发生。反之亦然…如果候选人资历高,但角色资历低,或反之亦然,候选人成功的几率为 0%。

如果我们按照下面的方法构建一棵树,我们可以将候选人放入叶子中,将成功的候选人与不成功的候选人完全分开。

作者图片

决策树的标准实现将构建前一个次优树的原因是因为决策树是贪婪的,并且评估局部最优解。

第一次分裂将发生在“学术资格”特征上,因为这是决策树能够最好地区分成功和不成功候选人的局部最优,在数据中,具有高“学术资格”的候选人的 60% (3/5)是成功的,而具有低“学术资格”的候选人只有 33% (1/3)是成功的。

如果我们在第一步中按照“候选人资历”或“角色资历”进行划分,那么对于“候选人资历”或“角色资历”高和低的候选人,我们最终的成功率都是 50%……该模型无法进行任何有意义的预测。

因此,决策树更喜欢对局部最优的“学历”进行拆分,而不是进行更深层次的搜索。

但是,如果决策树能够向前看一步,它会在第一步中根据“候选人资历”和第二步中的“角色资历”找到一个更有效的分裂,或者反过来。看数据。

展望未来的成本

没有前瞻机制的决策树会选择最大化信息增益的分裂。通常,基尼指数(scikit-learn 默认选项)或熵在每次可能的分割后进行测量,以选择最佳分割。虽然拆分可以最大化拆分后的信息增益,但是它不考虑后续拆分中的信息增益。

在我们上面的例子中,首先按照“学历”进行分割,在第一次分割后产生最佳的基尼系数。但是它并没有给我们一个路径来做一个完美的第二级分裂,0 基尼系数,有能力将候选人分为 100%成功或不成功。

根据“职位资历”或“候选人资历”进行划分。

基尼-杂质:GI=I= 1∑C**p(I)∑(1p(I))

当添加单步前瞻时,在每次分割时,我们也通过考虑随后的分割来进行优化。在上面的例子中,我们会发现按“职位资历”进行拆分比按“学历”进行拆分更好,因为如果我们继续按“候选人资历”进行拆分,我们可以得到完美的基尼系数 0。

仅通过单步预测,我们需要评估所有可能的分割组合(当前和后续分割),这是一个非常昂贵的操作,需要大量的计算资源

此外,还有一种前瞻病理学现象,这种现象经常被观察到,前瞻实际上会导致更糟糕的结果和更大的决策树。在机器人和游戏(如国际象棋)中也观察到了前瞻病理学,在这些游戏中,没有前瞻或具有有限前瞻的简单试探法往往优于进行更深入前瞻的更广泛搜索。

图片由 PIRO4D 来自 Pixabay

在我们的求职者示例中,情况并非如此,但这确实会发生。不能保证向前看会提高决策树的准确性。

设置我们的实验

我们将运行一个简单的实验来测试前瞻是否增加了决策树分类器的准确性。具有前瞻机制的决策树有现成的实现(例如 Weka 中的 J48),但是我们将从头用 Python 构建一个定制的分类器。

我们首先准备一个包含两个类的样本分类数据集,并将其分成训练和测试数据集。

RANDOM_STATE = 1clf_data = make_classification(
    n_samples=1000,
    n_features=20,
    n_informative=10,
    n_redundant=2,
    n_classes=2,
    shuffle=True,
    random_state=RANDOM_STATE,
)X_train, X_test, y_train, y_test = train_test_split(
    clf_data[0], clf_data[1], test_size=0.2, random_state=RANDOM_STATE)

下面的代码是决策树的一个自定义实现,虽然简单、缓慢,但它确实完成了任务。它包括单步前瞻,并允许修改最大深度以及分割点/箱数量(基于百分点)以考虑每个特征。当分割点≥样本量时,我们将简单地评估每个值的分割,而较少的分割点是一种正则化形式,我们根据百分位数评估分割特征的潜在值。

当我们不包括任何前瞻并选择大量分裂点时,决策树产生的预测应该与 scikit-learn 的具有默认参数的决策树分类器的预测几乎相同(由于随机因素,不一定精确)。

我们快速检查一下…

# Sklearn decision tree
sk_dt = DecisionTreeClassifier(max_depth=3, 
                               random_state=RANDOM_STATE)
# Custom decision tree
custom_dt = CustomDT(max_depth=3, 
                     ppoints=1000) # percentile/split pointssk_dt.fit(X_train, y_train)
custom_dt.train(X_train, y_train)sk_preds = sk_dt.predict(X_test)
custom_preds = custom_dt.predict(X_test)# Check if predictions are the same
print("Predictions match rate: "\
    f"{round(100*(sk_preds == custom_preds).mean())}%")

作者图片

预测在 100%的情况下匹配,因此这使得我们的定制决策树(没有前瞻,具有大量分裂点)可以与 scikit-learn 实现相媲美。

我们可以使用下面的代码用 lookahead 重新运行我们的自定义树。

custom_dt = CustomDT(max_depth=3, 
                     ppoints=10)custom_dt.train(X_train, 
                y_train,
                # Depth of tree constructed in single step lookahead
                **lookahead_depth=3**)custom_preds = custom_dt.predict(X_test)

在我们的实验中,我们将检查在不同的树深度和分割点组合下,单步前视与无前视相比如何(减少分割点可以减少过度拟合)。

为了简化我们的实验,我们将只跟踪 2 个准确性指标,F1 得分和 ROC AUC。

实验结果

实验在以下参数下进行。

params = {
    "depth": [3, 5, 7, 10],
    "ppoints": [3, 5, 10, 20, 100]
}

下面是使用的代码。

results = {
    "depth": [],
    "ppoints": [],
    "lookahead": [],
    "dataset": [],
    "f1": [],
    "roc_auc": []
}for depth in params["depth"]:
    for ppoints in params["ppoints"]:
        custom_dt = CustomDT(
            max_depth=depth, 
            ppoints=ppoints
        )
        # Decision tree with lookahead
        custom_dt_lk = CustomDT(
            max_depth=depth, 
            ppoints=ppoints
        )

        custom_dt.train(X_train, 
                        y_train
                       )
        custom_dt_lk.train(X_train, 
                           y_train, 
                           lookahead_depth=depth
                          )

        y_pred_train = custom_dt.predict(X_train)
        y_prob_train = custom_dt.predict(X_train, prob=True)
        y_pred_train_lk = custom_dt_lk.predict(X_train)
        y_prob_train_lk = custom_dt_lk.predict(X_train, prob=True)
        y_pred = custom_dt.predict(X_test)
        y_prob = custom_dt.predict(X_test, prob=True)
        y_pred_lk = custom_dt_lk.predict(X_test)
        y_prob_lk = custom_dt_lk.predict(X_test, prob=True)

        for i in range(4):
            results["depth"].append(depth)
            results["ppoints"].append(ppoints)

        results["dataset"].append("train")
        results["lookahead"].append(False)
        results["f1"].append(
            f1_score(y_train, y_pred_train))
        results["roc_auc"].append(
            roc_auc_score(y_train, y_prob_train))results["dataset"].append("train")
        results["lookahead"].append(True)
        results["f1"].append(
            f1_score(y_train, y_pred_train_lk))
        results["roc_auc"].append(
            roc_auc_score(y_train, y_prob_train_lk))

        results["dataset"].append("test")
        results["lookahead"].append(False)
        results["f1"].append(
            f1_score(y_test, y_pred))
        results["roc_auc"].append(
            roc_auc_score(y_test, y_prob))

        results["dataset"].append("test")
        results["lookahead"].append(True)
        results["f1"].append(
            f1_score(y_test, y_pred_lk))
        results["roc_auc"].append(
            roc_auc_score(y_test, y_prob_lk))

最后,让我们看看结果…下面的准确性指标是针对训练数据集的预测。

df_results = pd.DataFrame(results)
df_results[df_results.dataset=="**train**"].sort_values(
    by="roc_auc", ascending=False)

作者图片

当我们尝试在训练数据集上运行预测时,我们显然会在更大的最大深度下获得更好的结果。这并不奇怪,因为我们正在更好地拟合数据。

没有明显的前瞻性病理迹象。F1 和 ROC AUC 得分均为 100%的最佳设置是第一个 max_depth = 10,split points/bin = 20,并带有前瞻的设置。前瞻出现在性能最佳的设置中

当我们查看 ROC AUC 时,在所有最大深度,基于 20 个百分点仓的分割特征比基于 100 个仓的更细粒度的分割产生更好的结果。这可能是由前瞻病理学驱动的,但它更有可能只是在决策树的前几层发生的更有利的分裂的人为产物,导致在更大的最大深度也有更好的结果。

更重要的是,让我们对照测试数据集来检查预测…

df_results = pd.DataFrame(results)
df_results[df_results.dataset=="**test**"].sort_values(
    by="roc_auc", ascending=False)

作者图片

在 ROC AUC 得分上表现最好的设置****使用前瞻。前 8 个设置中有 7 个包含前瞻机制。

如果我们按照 F1 分数对决策树进行排序,我们会得到类似的见解。

df_results = pd.DataFrame(results)
df_results[df_results.dataset=="test"].sort_values(
    by="**f1**", ascending=False)

前 4 种设置都使能了前瞻。当我们查看 ROC AUC 时,最高性能设置的最大深度为 7,有 10 个仓,而不是最高的 5 个仓。

具有前瞻的顶级设置和没有前瞻的顶级设置之间的差异在 F1 分数上是 2.3 分,在 ROC AUC 上是 1.5 分,这是相当显著的差异。

使用单步预测的准确度的提高似乎随着更深的树而增加,这反映了预测没有发生过拟合。

mpl.style.use("fivethirtyeight")pivoted_results = pd.pivot_table(data=df_results[(
    df_results.dataset == "test")], 
    index=["depth", "ppoints"], 
    columns="lookahead", 
    values="roc_auc")pivoted_results["Percent Diff"] = (pivoted_results[True] \
    / pivoted_results[False] - 1) * 100sns.catplot(data=pivoted_results["Percent Diff"].reset_index(), 
            x="depth", y="Percent Diff", aspect=16/9, height=7)plt.title("Percent Difference in ROC AUC With Lookahead vs. Without")

作者图片

结论

在我们从 scikit-learn 的 make_classification 生成的典型分类数据集中,具有单步预测的决策树优于没有预测的标准决策树。我们没有观察到任何前瞻性病理或过度拟合的明显迹象。当然,这不一定是所有数据集中的情况。

尽管如此,我们表明,至少对于一些数据集,前瞻机制可以始终产生更准确的决策树。

鉴于 XGBoost 和其他提升树算法的广泛流行,探索添加前瞻机制是否能产生更好的结果将是有趣的。在我的定制实现中进行测试是不可行的,因为这样的测试需要大量的计算资源。

循环杀手:Python Zips 和示例理解

原文:https://towardsdatascience.com/loop-killers-python-zips-and-comprehensions-by-example-a0fb75dbddf2?source=collection_archive---------9-----------------------

你的 Python 代码箭头派遣侏罗纪循环抵制

斯蒂芬·凯勒拍摄的图片,幻想恐龙 Pixabay 上的免费照片

作者图片

示例教程:

  • 列表、集合和字典理解,带有条件或类似过滤器的行为;
  • 与理解相关的列表、字典和元组的压缩和解压缩;
  • 随后是一些速度测量,将“旧式”循环的性能与理解进行比较。

0.理解的 Pythonic 式特征

如果你像我一样,从其他不提供类似对象的编程语言来到 Python,当你第一次面对列表理解时,你可能会感到困惑;当您理解了它们如何使您的代码更简洁、更快速时,我们感到非常惊讶。理解和循环一样,用于过滤列表或字典、提取项目和转换值。让我们浏览一系列循环和理解的例子。

1.拉链和理解:处理列表、元组和字典

1.1 拉链

1.1 .等长的拉链列表

假设我们必须处理从 Python 脚本中的不同方法接收到的一组非结构化的值。在我们的例子中,我们假设我们需要处理三个预测准确性指标的列表:RMSE、MAPE 和 R 平方。我们希望避免将这些变量分别传递给其他方法。相反,这三个指标应该一前一后地处理。因此,我们将把它们收集到一个列表或字典中,然后演示如何使用它们和对它们进行操作。

我们把数值组合成一个列表, acc_values

为了区分这些指标,我们在第二个列表中写下它们的名字, acc_names ,注意它要与第一个列表的排序顺序相匹配。

作者图片

第 23 行和第 27 行是可选的公式,它们生成相同的名称列表。

悄悄地,我们在第 27 行引入了一个没有使用关键字的列表操作。注意列表变量前面的星号*和后面的逗号。语法

  • *listname,=逗号分隔值的列表

生成一个列表。星号*实际上是一个解压缩操作符。但是当我们应用第 27 行的语法时,它也可以组合条目来创建一个列表。

接下来,我们通过压缩来合并这两个列表。语法:

  • mylist = list(zip(list1,list2,…))

作者图片

作者图片

Python 的 zip 函数将两个(或更多)列表的对应项配对到一个元组列表中,不需要多行循环。

1.1.b 解压缩元组列表

相反的情况呢?如果我们面对一个元组列表,我们能不能不用写循环就把它们压缩成单独的列表?是的,我们在列表变量前面加了一个星号或星号*来解包元组。语法:

  • var1,…,varN = zip(*mylist)

作者图片

作者图片

1.1.c 长度不等、有遗漏的压缩列表

如果我们处理条目数不同的多个列表,我们仍然可以通过应用 list() 构造函数将它们组合成一个元组列表,尽管长度不等。然而,zip 函数采用最短的列表并省略较长列表的相应元素。

语法:

  • mylist = list(zip(list1,…,listN))

作者图片

作者图片

1.1.d 长度不等的拉链列表,带填充

在大多数情况下,跳过较长列表中包含的“多余”项目不是首选行为。幸运的是, itertools 库提供了 zip_longest 函数。它将最长的列表的所有项目插入到元组中,然后不将任何项目写入较短列表不能贡献值的那些元组项目中。这里,例如,前面的方法没有为第四个度量“MSE”提供值,因此 zip_longest 插入一个值 None 来完成最后一个元组。

再次注意我们简洁的口头禅:在可能的情况下,我们希望用一行代码创建一个列表,就像下面第 8 行中的那样;因此,没有需要几行的循环。

语法:

  • mylist = list(zip_longest(list1,…,listN))

作者图片

作者图片

1.2a 压缩元组列表以创建字典

让我们把元组列表转换成字典,去掉许多括号。语法:

  • mydict = dict(mylist)

作者图片

作者图片

1.2b 压缩列表以创建字典

为了演示如何将 zip 函数应用于列表,我们绕道将原始的名称列表和值列表合并到一个元组列表中,然后再将其转换为字典。

现在我们跳过一个多余的步骤:我们再次通过使用 zip 函数来演示如何将两个原始列表直接转换为字典,而不需要绕道元组。第 3 行代表字典理解。

语法:

  • mydict =

作者图片

作者图片

这本字典去掉了元组的许多括号。

但是,我们如何生成一个在报告中可读性更好的表格布局呢?

1.3 打开字典包装

在我们继续使用 zip 生成的字典之前——我们如何实现相反的操作并解包现有的字典,最好没有循环?

我们可以将字典值赋给代码行 3 左侧的逗号分隔变量。或者,分配由键和值组成的对,而不是值。

语法:

  • var1,…,varN = mydict.items()

作者图片

作者图片

  • var1,…,varN = mydict.values()

作者图片

作者图片

作者图片

作者图片

或者我们通过使用将字典键和值解包到两个独立的列表中。按键()。values() 函数并用 list() 构造函数对其结果进行类型转换。语法:

  • listKeys = list(mydict.keys())
  • listValues = list(mydict.values())

作者图片

作者图片

或者,第三个变体,我们通过一前一后地使用 zip 和 list 函数,成对地将键和值解包到元组列表中。

元组列表的一种更简单的方法:

作者图片

作者图片

语法:

  • listTuples = list(mydict.items())

1.4 列表和词典理解的结构

理解的一般结构遵循以下模式:

  • 一个 表达式 开头在下面的例子中: print 函数取字典项的并打印这一对;
  • 接下来, 中的for——引用理解将从字典中提取的项(键和值)(在列表理解中,不适用);我们将在下面进一步运行的速度测试将证明理解中的for-in结构比传统的 for 循环更快;
  • 随后是 字典列表 本身,其中包含了表达式应该处理的所有键和/或值;
  • 可选地,可以将一个 条件表达式(if — else) 附加到理解的语法上,以过滤字典或列表;我们将在下面看到一个例子。
  • 语法:[列表中项目的表达式]
  • 示例:my list =[numbers list 中 x 的 x * * 2]
  • 如果 numberslist =[1,2,3],那么 mylist = [1,4,9]
  • 语法:{ dictionary . items()或 list}中键、值的表达式
  • 示例:my dict =
  • 表达式对 iterable 中的值求平方,iterable 在本例中是一个数字列表,然后将输入参数(它将解释为键)与其平方值配对。
  • 如果 numberslist =[1,2,3],那么 mydict =

1.5 示例:用于打印的理解

要查看实际的例子,让我们创建一些字典和列表理解,它们将漂亮地打印多个结果。我们希望获得一个表格形式的垂直布局的报表输出:

作者图片

作者图片

Python 通过函数 pprint()提供了漂亮的打印库。但是它没有返回我们喜欢的布局,如下所示:

作者图片

我们可以使用 for 循环来逐个打印字典条目。在这种情况下,上面显示的循环甚至非常简洁。但是下面进一步的速度测试将证明,无论我们是将循环用于打印还是其他方法,循环都要慢得多。当我们需要处理包含成百上千条目的列表或字典时,就会感觉到时间效率低下。

我们可以把字典转换成数据框架。一行程序是理解的简洁替代。

作者图片

尽管如果我们需要处理一个包含 10,000 个字符串作为值、索引号作为键的大得多的字典,转换成数据帧的速度比理解一个列表要慢 175 倍。

作为冗长的循环和较慢的数据帧转换的替代方法,让我们在字典上尝试一下列表理解。

我们在一个列表理解中包含了我们的三个预测准确性度量的字典,每当我使用它进行漂亮的打印时,我都称它为打印理解print() 函数代表任何理解开始时的表达式

作者图片

作者图片

list comprehension 一个接一个地打印字典的内容。

唯一的缺陷是:三个值的列表。它们来自哪里?这不是列表理解本身的 bug。更确切地说,print 函数被定义为返回 None ,并为它处理的每个键/值对执行此操作。我们将取消 None 值。

第一种方法:在打印理解下面插入另一行。

作者图片

作者图片

第二种方法:附加行也可以由一个 pass 语句组成。

作者图片

作者图片

第三种方法:将印刷理解赋给任何变量。

作者图片

作者图片

第四种方法:左边的下划线可以达到同样的目的。

作者图片

作者图片

最后,让我们完成打印理解练习,并漂亮地打印出命名指标及其数值的字典(v)。度量的名称充当键(k)。我们在 print 函数中用数字格式包含了值变量 v。

作者图片

作者图片

为了比较,我们来看看我在几个网站上看到的一个替代代码构造。为了打印字典,网站建议定义一个通过 for 循环运行的函数。它确实起了作用,但我不愿称之为 Pythonic 式的优雅。

到目前为止,我们对循环足够敏感,以至于它们在 Python 脚本中的出现会给我们一些停顿。在所有情况下,理解不能代替循环。但是这项任务——就像打印一本字典一样简单——应该只需要一行代码。定义一个函数来使用print()——本身就是一个函数——似乎是多余的。如果不是函数,那么函数体中的循环应该会引起我们的愤怒,促使我们去寻找需要更少代码行的可能的替代方法。

1.6 摘要:压缩成字典并打印

是时候总结一下我们已经采取的步骤,并省略我们已经讨论过的替代和中间解决方案,以展示 zip 函数和理解可以相互交互的各种方式。我们将把脚本压缩成四行代码。

我们希望处理一组预测准确性指标及其值,这些指标和值是前面的计算已经生成并传递给我们的脚本的。

  • 我们将它们各自的值组合成一个列表, acc_values
  • 为了正确标记这些值,我们为这些指标创建了一个名称列表, acc_names
  • 在行 13 中,z ipping 生成一个元组列表,字典理解将该列表转换成字典,
  • 我们通过列表理解将其打印在第 16 行。

作者图片

作者图片

理论上,我们可以将第 13 行和第 16 行合并成一行,这样就可以创建字典并立即打印出来。

但是可读性应该优先于减少代码行数。仅仅是两倍长的一行不能算作一个改进。字典的创建和它的打印代表了不同的目的,因此它们应该各占一行,如第 13 行和第 16 行。

2.表现:理解和循环的速度

第 1 章集中讨论了循环代码的长度,与大多数理解所需要的不太冗长的单行代码形成对比。一般来说,理解更简洁。

在这一章中,让我们测试一下更短的理解代码是否也能导致更快的执行。

为了生成循环和理解可以相互竞争的数据,我们创建了一个用随机数填充的列表。我们在第三行使用一个简短的列表理解。

满足我们目的的理解 c 由第 15 行的一小段代码组成,而循环像往常一样需要多行代码来处理列表中的所有元素。

作者图片

作者图片

2.1 对数值进行操作的列表理解

如上图所示准备好赛道后,我们想要寻找可测量的速度差异。因此,使用与上面相同的代码,我们创建了一个更长的 100,000 个随机数的列表,然后释放循环和对它的理解。

作者图片

作者图片

列表理解比循环快 21%。

请注意,无论何时重新运行代码,测量的时间都会不同。有效时间取决于您的计算机在任何给定时刻如何在等待队列中的任务之间分配处理器容量。但是结果可以预期证明理解比循环更快,很少有例外。

2.2 列表理解中的条件表达式

让我们给循环和理解添加另一层——在将表达式应用于列表项之前,让它们接受一个条件表达式的评估。

在我们的例子中,任何列表值都应该是大于 90 的平方。在将表达式应用于所选值之后,此构造通过仅将满足条件的值传递给结果列表来过滤源列表。

条件理解的句法:

  • my list =[如果则列表中的项目的表达式(条件= =真)]

条件还可以包含一个在两个不同表达式之间进行选择的 else 子句。在前面的例子中,在理解的开始有一个单一的表达,现在有两个可供选择的表达。但是对于理解从源列表中读取的每个值,只执行其中一个。我们可以再次在末尾附加一个条件,它具有过滤器的作用,就像前面的例子一样,这样就可以将条件#2 的评估限制在满足条件#1 的项目上。换句话说,条件#1 选择将传递给行首两个表达式的源数据;然后,条件#2 确定两个表达式中的哪一个(A 或 B)将转换选定的源值。

语法:

  • my list =[expression aif(condition 2 = = True)else用于列表中项目的表达式 if (condition1==True)]

示例:如果参数超过 90,则对其取平方;但是如果它小于或等于 90,则将其提高到三次幂;以列表“mylist”的形式返回所有取幂的结果,无论它们是平方的还是立方的;但是,根据行尾的条件,只有当源值是偶数时,才需要取幂运算和结果列表中省略奇数:

  • my list =[(x * * 2)if(x > 90)else(x * * 3)for x in list if(x % 2 = = 0)]

下面的示例演示了在末尾有一个类似筛选器的条件#1 的语法。理解只处理大于 90 的数字,并从平方结果中省略较小的自变量,因此将形成比 100,000 个大小随机数的源列表更短的列表。

作者图片

作者图片

理解在列表中的速度比循环快 45%。

我们测试了另一个变体:我们制定了一个循环和一个列表理解,它们都包含一个条件表达式:仅当一个值是偶数时求平方,并跳过奇数编号的参数

作者图片

作者图片

条件列表理解比循环快 18.8%。那已经接近低端了。有时,您会发现处理时间加快了 40–50 %,这取决于处理器对并发任务的工作负载优先级。

2.3 对字符串进行操作的列表理解

我们研究了数字变量的列表理解的性能。让我们看看循环和理解如何处理字符串列表,如姓名、单词或日期字符串。

为了快速获得我们希望用于搜索和过滤练习的一长串字符串,我们创建了一个包含 10,000 个工作日名称的日期范围,然后将元素从 datetime 转换为 string 类型。

我们通过对列表的理解来执行转换(当然,不是通过循环,只要我们能避免循环)。这个理解中的表达式元素由 strftime 函数组成。

作者图片

作者图片

2.4 对字符串进行操作的条件列表理解

接下来,我们制定一个条件表达式来筛选日期字符串列表。让我们搜索所有年份中 10 月份的周六和周日。循环和理解应该通过给日期加上后缀“= Oct weekend”来修改它们找到的日期字符串。

我们评估三个条件:一天的名称是“(S)unday”或“(星期六)urday”,一个月的名称以“Oc”开头。这些条件决定了一个值是否服从表达式(这里,通过添加后缀“= Oct weekend”)。 else 术语告诉理解将其他日期字符串包含在结果列表中,而不修改它们。

我们还可以使用一个附加条件来过滤表达式中的值。例如,只评估 2022 年的值。就像上面的随机数的例子一样,我们将把这样一个过滤条件(condition1)附加到列表理解的末尾。语法:

  • my list =[expression aif(condition 2 = = True)else用于列表中项目的表达式 if (condition1==True)]

作者图片

作者图片

使用与循环相同的条件表达式的列表理解速度提高了 21.9%。

2.5 集合理解

在演示了列表和字典理解如何优于循环之后,让我们看一个集合理解的例子。

我们想在前 N = 100,000 个整数中找出质数。

我们将使用厄拉多塞之筛的改进版本(厄拉多塞之筛——维基百科)。首先,sieve 算法创建一组从 2 到 100,000 的所有整数(根据现代定义,1 不是质数)。然后,它遍历所有整数 I,直到 N 的平方根,并从 100,000 个数字的集合中丢弃那些等于或大于 I 的平方的数字 j。迄今为止,筛子不是查找素数的最快算法。但是撇开数学不谈,我们可以在循环和集合理解中应用筛子的逻辑来比较它们的处理速度。

传统风格会使用嵌套循环:'代表 I '【T3]作为外循环,'代表 j'* 作为内循环。让我们创建一个嵌套的理解作为它的挑战者。*

嵌套理解的语法:

  • myset = {{expression(itemA,itemB)for itemA in setA } for itemB in setB }

作者图片

作者图片

集合理解比循环快 57%。

2.6 理解是所有可重复项目的灵丹妙药吗?

那么…我们结束了吗?理解在任何情况下都被证明是不可战胜的吗?不完全是。

让我们再次过滤日期字符串列表,但是这次使用基于 lambda 函数的过滤器。

基于 lambda 的过滤器需要 0.0001 秒。列表理解,0.0033 秒,慢了 22 倍。

作者图片

我们将把列表理解和 lambda 过滤器之间的赛马作为另一篇文章的单独主题。

3.结论

今天的文章关注了传统循环与列表、集合和字典理解的比较;以及与理解相关的 zip、unzip 和 unpack 方法。

这些例子表明

  • 理解和压缩函数如何在列表、元组和字典上相互作用;
  • 如何简洁地编码它们的交互,通常用一行就可以表达,而循环会扩展到多行——每个例子都展示了在许多其他语言中通常需要循环的操作;
  • 我们可以期待理解提供优于传统循环的速度。

Jupyter 笔记本可以在 GitHub 上下载:GitHub—h3ik0th/loop killers:Python 的 zip 和 comprehensions against loops

Python 中的循环和语句:深入理解(附示例)

原文:https://towardsdatascience.com/loops-and-statements-in-python-a-deep-understanding-with-examples-2099fc6e37d7?source=collection_archive---------25-----------------------

当它们看起来被理解时,还有更多

尼克·里克特在 Unsplash 上的照片

当学习数据科学时,第一步是学习编程,而人们学习的第一个主题是循环和语句。
嗯,实际上我并不是编程天才(我正在向中级水平迈进:),但是循环确实考验了我。它们看起来如此简单,如此容易理解…也许你可以说“好吧,这真的很明显!”。此外,这可能是由于 Python 本身,因为它是为了让人类容易理解而发明的。
因此,我想深入解释循环和语句,这样我们可以通过一些例子来了解它们背后有多少东西需要理解。

Python 中的循环:“for”循环

首先,我要解释的是“for”循环。
我们举一个简单的例子来了解一下基本情况。假设我们有一个四个数字的列表,我称之为“数字”;它是这样定义的:

numbers = [2, 3, 5, 7]

我希望我的 Python 脚本打印出我的列表中的所有数字。为此,我可以使用一个简单的“for”循环,如下所示:

numbers = [2, 3, 5, 7]for number in numbers:
    print(number)

结果是:

2
3
5
7

让我们更深入地分析这几行代码。首先重要的是:在 for 循环中我们使用辅助变量。在这种情况下,辅助变量是“数字”;事实上,我已经定义了一个名为“数字”的列表,你看不到任何定义为“数字”的变量;所以在循环中直接使用“number”辅助变量,我在编写循环代码时定义了它。

现在,让我们来看一个例子,这个例子对于思考 for 循环是如何工作的很有用,因为对于上面的例子,人们可能认为已经理解了,但也许…不是!

让我们定义一个列表,并用它来打印一些东西。例如:

my_list = [1,2,3,4,5]for x in my_list:
    print ("cool")

这是结果:

cool
cool
cool
cool
cool

嗯……一个人应该马上问自己:“亲爱的朋友 Python,我只要求你打印一次“cool ”;请你告诉我,你到底为什么要印 5 次??"

这是一个恰当的问题,表明您没有理解前面例子中的 for 循环,但是思考一下 for 循环并获得深入理解是一个有用的问题。

我想考虑像电流或液体在物体中循环这样的回路。在这种情况下,对象是一个列表,我们的朋友 Python(你甚至可以把它想成一条蛇:D)在列表中“循环”,并试图用你的代码做你要求的事情;在本例中,它找到了 5 个数字(列表由 5 个数字组成),并为列表中的每个值打印“good ”:这就是 for 循环的工作方式。

下图可能有助于您直观地了解 for 循环的工作方式。

for 循环如何工作的可视化表示。图片由作者提供。

python 中的语句:if-else 和 if-elif-else 语句

现在,让我们来看一下“如果”语句。“if”语句不完全是一个循环。这是一个陈述,通过它我们可以说一个条件必须为真;如果没有,我们可以说点别的(使用“else”语句)。让我们看一个 if-else 语句的简单例子。

x = 2if x > 0:
    print("x is greater than 0")
else:
    print("x is negative")

而且…猜猜怎么着?结果是:

x is greater than 0

同样,非常简单,你可以肯定已经理解了 if 语句。

让我们看看更难的东西。现在,我们要使用 if-elif-else 语句,其中代码测试条件“if”和“elif”(意为“else,if”);如果这些都是假的,它测试其他的。

x = 1if x == 1:
    print(x)
elif x == 3:
    print(x)
else:
    print("error")

当然,这段代码的结果是:

1

这非常非常简单。我将 x 强制为 1,因此唯一的真值可以是“if”语句强制的值。而且,再一次,一个人可能认为已经理解了一切。但是真正的美是当你试图把它们放在一起的时候。

python 中的循环和语句:嵌套在 for 循环中的 if-elif-else 语句

假设我们有另一个从 1 到 5 的数字列表,我们想遍历它,用 if-elif-else 语句给出一些条件。
为此,我们必须在 for 循环中嵌套 if-elif-else 语句。
什么意思?
意思是我们的“蟒蛇会流通”(还记得上图吗?😄)通过测试一些条件列表,这些条件是由 if-elif-else 语句定义的。并且当条件匹配时代码会打印一些东西(“if”或“elif”);当 not ("else ")时,它打印其他内容。

例如:

my_list = [1,2,3,4,5]for x in my_list:
    if x == 1:
        print(x)
    elif x == 3:
        print(x)
    else:
        print("wrong numbers")

结果是:

1
wrong numbers
3
wrong numbers
wrong numbers

如果我们已经理解了 for 循环和 if-elif-else 语句是如何工作的,那么结果是显而易见的:我们的辅助变量(称为“x”)遍历我们的列表(称为“my_list”)并测试由 if-elif 语句强加的每个数字的给定值。

首先,x 在列表中找到值 1。它与“if”语句匹配,所以代码打印“1”
然后 x 找到 2;它与任何强加的值都不匹配(对于 if 语句为 1,对于 elif 语句为 3),因此代码打印“else”条件,这是“错误的数字”。
然后去 3;它找到与 elif 语句匹配的内容,并输出 3。然后它通过 4 和 5,由于没有找到匹配,它打印出“错误的号码”,这是由 else 条件强加的。

正如我们所看到的:当 for 循环和语句似乎被理解时,还有更多更深层次的东西…我希望这篇文章能对对这些主题有疑问的学生有用!

需要 Python 中的内容来开始或促进您的职业生涯?下面是我的一些文章,可以帮到你:

Python:

考虑成为会员:你可以免费支持我和其他像我一样的作家。点击 这里的成为会员。

企业中的低代码 AI

原文:https://towardsdatascience.com/low-code-ai-in-enterprise-benefits-and-use-cases-b9692ee13168?source=collection_archive---------28-----------------------

优势、使用案例、限制

软件和应用程序统治着当今世界,为了让你的企业取得成功,它必须跟上潮流。但是设计和推出一个新的解决方案需要时间和金钱。一家规模不大的初创企业或有各种需求的企业能否更快、更经济地获得解决方案?应对这一挑战的答案是低代码人工智能——人工智能的游戏规则改变者,它简化了常规的应用程序开发任务,并使软件开发更贴近用户。

通过低代码人工智能,即使非专业人士也可以立即创建应用程序,随时修改和更新它们,以提供卓越的客户体验。在这里,我们详细讨论了低代码人工智能的主题,以阐明它如何工作,它带来了哪些利弊,以及企业和数据科学家如何挖掘它的潜力。我们还提供了一个现成的清单,用于选择一个理想地满足您需求的低代码人工智能解决方案。

什么是低代码 AI?

编程语言的复杂性不同,软件开发人员制作一个或多或少复杂的应用程序所需的准备工作也不同。但是,它们都有一个共同的特点——需要专业的准备,一个远离编程的外行很难做出可行的程序。人工智能是一个狭窄的高科技编程领域,需要更深入的编码和技术知识。因此,人工智能开发传统上一直与先进的技术技能、专业的软件工程教育以及数月昂贵而艰苦的劳动联系在一起。

低代码人工智能通过提供简单、直观和用户友好的解决方案,改变了人工智能产品开发的愿景。低代码人工智能开发平台的出现为创建人工智能解决方案提供了现成的构建模块,用户可以在 GUI 和配置的帮助下在几个小时内制作应用程序,而不是手写代码。听起来很神奇,对吧?让我们仔细看看这是如何工作的。

图片来自 freepik.com

低代码与无代码人工智能

顾名思义,低代码人工智能开发仍然需要用户输入一些最少的编程工作。反过来,无代码软件根本不需要编程,甚至允许没有编程经验的用户通过使用简单的构建模块来定制符合他们需求的人工智能应用程序。

它是如何工作的?

低代码 AI 可以由缺乏编码知识的人来创造。因此,即使没有经过专业培训的普通用户也可以通过可视化构建模块快速编译所需的低代码 AI 产品。大多数低代码 AI 平台的基础设施包括以下元素。

1.图形用户界面(GUI)

一个非专业人士也能理解的直观图形用户界面,配有清晰的视觉元素,可以很容易地构建人工智能程序,而不会对输入和输出产生困惑。

2.集成

为了让创建的程序处理您的业务数据,它必须访问您企业的数据库。低代码人工智能平台创建者通过 API 来处理这些问题,让新程序安全高效地与数据库通信。

3.应用程序经理

用低代码人工智能平台创建一个应用程序并不是软件开发过程的结束。为了让应用程序正常工作,它需要正确地维护和更新。此外,您创建应用程序的平台通常会提供故障排除服务,以帮助您消除错误并改进应用程序的功能。

低代码人工智能平台的能力和局限性

低代码人工智能开发的变革潜力是无可争议的。此类解决方案可帮助企业缩短应用上市时间,大幅节省雇佣软件开发团队的成本,并提供现成软件解决方案的速度、简单性和灵活性。

  • 低代码软件创建的便利性是连接非技术专家和人工智能产品的商业优势。
  • 应用程序创建的速度最大限度地缩短了上市时间,最大限度地提高了业务收入。
  • 低代码解决方案的灵活性允许通过从平台上的可用选项中进行选择来轻松定制应用。

然而,不管引入低代码人工智能开发听起来有多乐观,它仍然有一些限制。例如,这种开发类型仍然带有 l i mited 定制机会,您的应用程序中可以包含有限数量的构建模块。低代码 AI 产品的灵活性也受到平台上可用功能数量有限的限制。迁移问题仍然存在,尤其是如果你在低代码人工智能平台上开发一个应用,然后用不同的代码将其迁移到你现有的生态系统中。一些提供商不允许应用迁移,这意味着只要你的应用在使用中,你就被锁定在特定平台的使用中。

图片由 Ksenia Kirikova 从https://datrics.ai/站台拍摄

低代码 AI 如何让数据科学家受益?

低代码和无代码的人工智能产品使人们更容易获得数据科学,而不需要雇用全职的数据科学家。

然而,这些担忧并没有远离事实,因为低代码人工智能平台本身代表了数据科学家推进其职业发展的巨大潜力。通过投入时间来创建新的可定制的低代码和无代码人工智能解决方案,所有经验和资格水平的数据科学家都可以推动一个全新的行业利基向前发展。额外的服务,如通过高级订阅或数据科学培训进行更多定制,预计也将享受不断增长的需求。因此,低代码人工智能技术对这个行业来说更多的是机遇而不是挑战。

低代码 AI 对企业有什么优势?

正如你所看到的,企业可以从利用低代码人工智能解决方案中获得许多好处。好处来自于开发成本的大幅削减、软件上市时间的缩短、更好的数据分析、更好的用户体验等等。然而,低代码和无代码解决方案的批评者经常声称,这种产品严重受限于提供商平台的特性,因此提供了最少的真正定制。Datrics 通过提供灵活的以业务为中心的解决方案来解决这个问题。Datrics 平台的当前功能使其能够用于构建零售和信用评分业务的智能系统。此外,它通过使用大量的数据处理、分析和机器学习库来提供广泛的定制解决方案。因此,在 Datrics 的帮助下,企业可能确实实现了他们需要的定制化水平,以业务问题而不是系统的限制,代表着合作的基石。

这里有几个用例,可以更好地理解低代码人工智能开发在今天是如何应用的。

二尖瓣脱垂综合征

MVP 是以最少的时间和精力投入来可视化想法的实现,并查看它是否满足客户的期望。低代码 AI 开发平台也使 MVP 创建功能能够最大限度地减少开发到发布的周转时间,并帮助用户了解还需要哪些其他功能。

新技术

我们生活在增强现实(AR)和虚拟现实(VR)应用获得动力的时代。因此,挖掘这个新市场的潜力是商业成功的关键。您可以选择多经验开发平台来更经济高效地开发此类产品,而不是将所有资金投入到昂贵的硬件和软件中。这种平台的一些受欢迎的例子包括 FirebaseGeneXus ,帮助用户在创纪录的时间内创造创新产品。

工序自动化

技术应该为你的运营效率目标服务,这也是低代码 AI 开发所能给予的。考虑您企业的自动化需求,并设计一个简单而强大的人工智能应用程序来满足这些需求。例如, Appian 是一个全球知名的低代码自动化平台。Datrics 还提供方便和负担得起的低代码人工智能开发服务,增强您的业务运营。使用 Datrics,没有深入编程技能的用户可以通过拖放的方式从块中创建数据处理管道,在几个小时内就可以开发出现成的 ML 应用程序。Datrics 解决方案已被证明在金融科技的信用风险和欺诈检测等用例中非常高效。因此,Datrics 模型的部署速度提高了 5 倍(平均一周),并且有 5 个现成的模板管道用于行业用例,因此该公司在低代码和无代码数据科学解决方案方面领先竞争对手一步。

图片由 https://datrics.ai/站台的 Ksenia Kirikova 拍摄

低代码人工智能实现的投资回报率

那么,AI 的实施在财务上可行吗?大多数专家认为是的,低代码人工智能产品能够在创纪录的时间内最大化你的努力的投资回报率。麦肯锡估计商业运营中数据分析集成的未来商业潜力为每年 9.5-15.4 万亿美元,其中人工智能解决方案约占收入增长的 40%。

如何选择合适的解决方案?

一旦你决定继续使用人工智能解决方案,选择平台的时间就到了。选择范围很广,数百家提供商承诺提供优惠条款和积极的用户体验。以下是在做出最终选择之前要使用的清单:

  • 定价计划(价格应该比雇佣内部技术专家低得多)
  • 灵活性(创建和定制产品时可供选择的功能数量)
  • 安全性(大多数平台在云中运行,因此应用程序和数据的安全性至关重要)
  • 迁移策略(将创建的应用程序迁移到您的系统的可能性)
  • 公民与开发者平台(根据谁将开发应用程序来选择平台)
  • 维护(确保选择提供维护和定期更新的平台,以使应用程序的使用过程更加顺畅)
  • 用户界面(虽然低代码平台对非技术用户来说非常友好,但它们仍然需要一些编码和定制,所以最好选择那些具有简单 GUI 的平台)
  • 客户支持和培训(平台应提供足够的培训和故障排除资源,以及全天候支持,以便您在需要时获得帮助)

在加入一个低代码 AI 开发平台之前,这里是你需要知道和考虑的所有事情。享受触手可及的技术进步带来的好处,并通过技术创新将您的业务运营提升到一个全新的水平。让一个先进的人工智能产品服务于您的业务需求从来没有那么简单。

劳里·威廉姆斯讲述如何将你的学术训练与现实世界的挑战联系起来

原文:https://towardsdatascience.com/lowri-williams-on-how-to-connect-your-academic-training-to-real-world-challenges-bc43ef3cdfed?source=collection_archive---------25-----------------------

作者聚焦

“我有发挥数据创造力的空间”

在 Author Spotlight 系列中,TDS 编辑与我们社区的成员谈论他们在数据科学领域的职业道路、他们的写作以及他们的灵感来源。今天,我们很高兴与劳里·威廉姆斯进行对话。

照片由劳里·威廉姆斯提供

L owri Williams 是一名总部位于威尔士的研究数据科学家,他在学术研究领域积累了四年的经验,在基于行业的合作领域积累了两年的经验,以新颖的数据科学解决方案支持中小型企业。她曾与多学科专家合作,在几个著名的学术期刊上发表研究成果和发现,并转向媒体和数据科学,在教程风格的博客帖子中展示一些新颖的数据科学方法。

最初是什么激发了你学习数据科学?

我一直对数据很好奇。我记得当我 13 岁的时候,作为地理课程的一部分,我们必须就一个我们感兴趣的地理相关主题制作一个项目。我决定测量我童年家附近的一条河流的一些属性。

我找到一张地图,骑着自行车来到这条河的特定区域,测量水流的速度、宽度等。虽然听起来很无聊,但我很喜欢。我花了很多时间对数据进行假设、绘制和绘图,以展示我的结果。我自豪地交了报告,获得了全班最高分。我很自豪。快进到 17 年后,我是一名研究数据科学家。

你能分享更多关于你目前所处的道路吗?

我成为数据科学家的道路非常简单。我花了三年时间在英国威尔士卡迪夫大学攻读信息系统学士学位。该学位的核心是关于人类如何与技术和信息互动。它没有我希望的那么技术性,也没有我能做什么。我想要一些更有挑战性的东西,一些迫使我学习并为自己的成长负责的东西。于是……我申请了博士奖学金,最后拿到了!

我不得不承认,我真的没有准备好,或者说我不太清楚我将面临什么。我有一些粗略的想法,我想把我的研究重点放在什么上,但如何研究和正确地做对我来说是一个巨大的学习曲线。但是,有时候潜入未知不仅是了解一个主题的最好方法,也是了解你自己的最好方法。

我的研究兴趣围绕自然语言处理,尤其是情感分析。我猜这种兴趣与我的学士学位密切相关——理解人类如何与技术交流让我着迷,尤其是他们使用的语言。

一旦我获得博士学位,是时候投入令人生畏的求职大军了。

许多职业生涯早期的数据科学家都担心找不到第一份工作——你的经历是怎样的?

我发现很难把自己放在一个我觉得有趣或者我觉得我能胜任的角色中。我不仅仅是一个了解自然语言处理的人,我还不止于此。我了解机器学习、特征工程、分类、注释数据,如何生成强大的数据集以实现稳定的机器学习模型,如何解释和可视化这些结果。我知道如何清理和处理数据,而不仅仅是文本数据。我是一个编码者,一个实现者,一个开发者,一个问题解决者。

我以自己的方式做所有这些事情,将自己归类为软件开发人员、数据工程师、这个、那个,真的,嗯,很难!我花了几个小时试图定义我到底是谁,我今天是谁,那就是数据科学家。我认为这没什么——我们都有自己的时间表。我认识一些人,他们从获得学士学位的第一天起就知道自己人生的下一步是什么,并一直坚持下去。我也知道有些人每两三年就换一次角色,因为他们经常需要更多的刺激或更具挑战性的东西来帮助他们成长。两条路都可以,我想如果我能穿越回那个时代,我会告诉年轻时的自己。

那你最后去了哪里?

我目前是加的夫大学一个项目的研究数据科学家,该项目通过新颖的数据科学解决方案支持基于行业的中小型企业。而且我喜欢!我喜欢尝试不同的想法和方法来解决不同的问题——不要说这是一个数据或任何东西的游乐场,我已经制作了一些帮助改善业务的项目!但我有空间对数据进行创新——作为一名数据科学家,这是我学到的一项非常重要的技能。

你是在什么时候决定开始公开写作的,是什么驱使你做出这个决定的?

一开始转向 Medium 和作为写作平台的数据科学有点令人畏惧。作为一名学者,几乎可以预料到我们会发表科学文献,这些文献遵循一种相当粗糙的格式,“这是我们的假设,这是其他人已经做的,我们不认为这回答了我们的假设,因此这是我们的新方法,这是实验,这是结果,现在知道了这些,如果我们在繁重的工作之间有机会做的话,我们将来可能会做些什么……”

因为有机会在我目前的职位上发挥创造力,我觉得这不太适合学术界。这并不是说我解决问题的方法是错的,因为它们解决了问题。但是它们更少实验性,因为它们遵循更敏捷的方法,我们面对一个问题,解决它,然后根据其他解决方案的输出继续下一个。因此,从学术角度为一些原因辩护变得更具挑战性。

所以,我转向媒体来分享这些输出和我探索的一些方法。这也让我可以练习一种不同于我习惯的写作风格。我也不会说写博客更容易。清晰而连贯的写作有时很有挑战性!但我喜欢这种挑战,因为它开启了与其他贡献者的合作,我可以与他们分享想法和交流。

在接下来的几个月或几年中,您希望在数据科学领域看到什么样的变化?

我真的希望自然语言处理领域很快会有一个转变,因为几年来它一直是相对相似的。它来了。单词嵌入和 BERT 正在向我们展示深度学习模型如何产生一些非常酷的结果。我认为这是机器学习中的普遍情况。例如,有大量的机器学习方法被提出来帮助自动根据新冠肺炎患者的咳嗽声对他们进行分类,或者根据他们的胸部 x 光片自动对患者是否患有肺炎进行分类。因此,我期待着尝试类似的模型,看看我们如何利用它们来获得更大的好处。

如果你想了解更多关于 Lowri 的工作以及她利用自己的学术专长应对现实世界挑战的方式,这里是她最近几个月的 TDS 帖子精选。你可以在洛瑞的简介上找到完整的档案,以及她网站上她的学术出版物的链接。

  • 情感分析:习语及其重要性 ( TDS ,2020 年 9 月)对 Lowri 的研究以及她如何将其转化为引人入胜、易于理解的帖子的介绍一样好,本文基于 Lowri 的博士研究。关注习语在情感分析中的作用和价值,这是更清晰地洞察人们使用日常语言方式的敲门砖。
  • Spotify 情绪分析 ( TDS,【2020 年 5 月)一部分是有趣的边项目,一部分是动手操作的教程,在这篇文章中,Lowri 转向了她自己的 Spotify 数据,试图从她的收听习惯中发现模式和见解。(剧透:事实证明,劳里最喜欢的音乐比她想象的更快乐!)
  • WordNet:英语单词的词汇分类(TDS,2020 年 10 月)
    回到 NLP,这篇文章是对普林斯顿词汇数据库 WordNet 的彻底解释。作为一篇 Lowri 文章,它不会停留在高级理论上——准备好卷起袖子,用一些有用的代码示例进行实验。

敬请期待我们的下一位特色作者,即将推出!(如果您对希望在此空间看到的人有任何建议,请给我们留言。)

Lp 规范、大满贯和奥运奖牌

原文:https://towardsdatascience.com/lp-norms-grand-slams-and-olympic-medals-f005e002ae8e?source=collection_archive---------37-----------------------

聚合结果的多种风格及其讲述的故事

在考虑了迈克尔·乔丹是否是低方差之王之后,我想讨论另外两种体育情况,在这两种情况下,人们总是争论汇总结果的正确方法

所有“三巨头”网球运动员目前都有 20 个大满贯。那么谁才是最棒的呢?(先不说这在未来会如何变化……)

一个直观的想法是,这些数据不仅向我们展示了球员的总数,还显示了他们的“多才多艺”和“专业”程度。纳达尔的大部分大满贯都是在法网取得的。我们可以通过选择不同的聚合方案来惩罚(或奖励)这种情况。一种由 p 参数化的常用方法是 Lp 范数:

Lp 规范定义(图片由作者提供)

对于 p=1,这只是大满贯的总和(比如费德勒的大满贯向量是(6,1,8,5),L1 范数是 20)。其他有趣的参数值有 0、1/2、2 和无穷大(其中无穷大表示 p->Inf 的 Lp 范数的极限)。对于 p=0,Lp 范数就是非零向量元素的个数。所有玩家都是 4 分。如果某个球员“错过”了一场大满贯比赛,他将落后于 L0 标准。对于 p =无穷大,Lp 范数是向量中的最大数。在这一点上,纳达尔赢了,因为他在法网赢了 13 场(德约科维奇在澳网赢了 9 场,排名第二)。对于 p=2,纳达尔再次获胜,德约科维奇的分数为 13.78 ~ 11.4,费德勒的分数为 11.22。但对于 p=1/2,德约科维奇以~17.19 的成绩获胜,费德勒以~17.03 第二,纳达尔以~16.04 最后。一般来说,低 p 值更多地奖励“良好平衡”的表现,而高 p 值奖励极端。我们实际上可以映射出 p 参数的不同区域,从而产生不同的顶级玩家。不仅如此,我们还可以证明:

没有费德勒是顶级球员的 Lp 规范。

事实上,对于每一个 p>1(“专门”制度),纳达尔都在上面,对于每一个 p <1 (the “versatile” regime), Djokovic is on top. Because the proof is involved, we show something more simple: That for p> 1,纳达尔总是领先于费德勒。

我对纳达尔>费德勒 p>1 的乳胶计算(图片由作者提供)

首先,请注意,由于 x^p 在 x 中对任何 p 都是单调的,所以用 p 的幂来比较范数就像比较范数本身一样。那么,除了算术,这里有两个重要的步骤:首先,由于 x^p 是 p>1 的凸函数,我们可以使用詹森不等式,特别是为了表明 4^p + 2^p ≥ 2*3^p.。更重要的是,我不知道一个通用的方法来解决复杂的指数不等式的形式

a * b^x + cd^x — ht^x ≥ 0

但是在这种情况下,我们发现了一个很好的技巧,就是将 c 和 t 近似为 b 的指数(为了保持不等式,我们用 b^(alpha 寻找 b 的某个指数α)< c, and exponent beta with b^(beta) >h)。幸运的是,a,c,h 系数给了我们足够的“回旋空间”,在推导之后,我们可以证明导数总是正的,因此函数是单调递增的,也总是正的。

为了说明对于 p <1 Djokovic is always on top of Federer, I have to admit I was more lazy, but the WolframAlpha graph is quite convincing:

A WolframAlpha screenshot for the Djokovic >费德勒对于 p <1 case (Image by author)

Sorry, Federer fans.

The Olympics were a tough time for score aggregators as well:

It was hard to determine if China should be first (has the most gold medals) or the US (most overall medals). Google went by 字典顺序,你优先考虑金牌最多的国家,然后如果与银牌最多的国家持平,最后是铜牌最多的国家。对我来说,奖牌总数也有意义。在竞赛论中,一个共同的区别是,每一场竞赛都有努力/能力成分和运气成分。将所有的重要性分配给金牌(按字典顺序,一个有 1 枚金牌和 0 枚银牌的国家将排在一个有 0 枚金牌和 100 枚银牌的国家之上)假设这纯粹是努力的结果。但这其中肯定有一些运气成分:事实是,很多时候世界冠军或历届奥运会冠军都没有在奥运会上获胜。在游泳中,很多时候第一名和第二名的差距是 1/100 秒。因此,给排名较低的奖牌分配一些权重也是有道理的。对美国来说幸运的是,以下是 2020 年东京奥运会前 10 名国家的最终奖牌数:

2020 年东京奥运会谷歌奖牌统计最终结果(图片由作者提供)

由于美国在每块奖牌上都领先中国(这是“帕累托优势”),任何加权评分规则都会选择我们为赢家。然而,对于争夺第三名的日本和英国来说,事情就不那么明朗了。实际上,我认为英国应该有优势。日本拥有金牌优势,英国拥有奖牌总数优势,但如果我们通过应用博尔达法则打破僵局,即给每枚金牌 3 分,银牌 2 分,铜牌 1 分,我们将获得

UK = 322 + 221 + 22 = 130

日本= 327 + 214 + 17 = 126

对不起,日本人民。特别抱歉费德勒的日本粉丝。

用于回归的 LSTM 和双向 LSTM

原文:https://towardsdatascience.com/lstm-and-bidirectional-lstm-for-regression-4fddf910c655?source=collection_archive---------0-----------------------

学习如何使用长短期记忆网络解决回归问题

STM 代表长短期记忆,是 1997 年提出的一个模型[1]。LSTM 是一个门控递归神经网络,双向 LSTM 只是该模型的一个扩展。关键特征是这些网络可以存储信息,这些信息可用于未来的细胞处理。我们可以把 LSTM 想象成一个 RNN,有两个关键向量的内存池:

  • (1)短期状态:保持当前时间步的输出。
  • (2)长期状态:在通过网络时存储、读取和拒绝对长期有意义的项目。

读取、存储和写入的决定基于图 1 中的一些激活函数。这些激活函数的输出是(0,1)之间的值。

图 1:LSTM 单元的架构。所有图片由作者提供。

遗忘门和输出门决定是保留还是丢弃新信息。LSTM 模块的记忆和输出门的条件产生模型决策。然后,输出作为输入再次传递给网络,形成循环序列。

双向 LSTM

在双向 LSTM 中,我们引入了两个模型,而不是训练一个模型。第一个模型学习所提供的输入序列,第二个模型学习该序列的相反序列。

因为我们已经训练了两个模型,我们需要建立一个机制来结合两者。它通常被称为合并步骤。合并可以是以下功能之一:

  • 总和
  • 增加
  • 求平均值
  • 串联(默认)

使用 Keras 的回归预测:

LSTM 可以在许多问题上提供帮助,这些问题涉及多个领域。LSTM 模型可用于检测网络违规或意外的系统行为,或者信用卡交易中的欺诈行为。在这种背景下,LSTM 有一个目标:预测不符合预期模式的事件。为了展示 LSTM 和双向 LSTM 在真实示例中的应用,我们将解决一个回归问题,预测纽约市使用出租车的乘客数量。我们可以预测下周或下个月的乘客数量,并相应地管理出租车的可用性。

机器学习中用于回归的 LSTM 是一个典型的时间序列问题。与其他机器学习问题相比,时间序列的关键区别在于数据样本是按顺序出现的。序列显式或隐式地表示一个时间维度。隐式部分是输入序列的时间步长。

例如:纽约出租车乘客

此示例将使用 LSTM 和双向 LSTM 来预测未来事件,并预测可能脱颖而出的事件。本例中使用的数据集可以在 Kaggle 上找到。

(1)探索数据集

图 2:来自纽约出租车乘客的样本

我们使用 Pandas 加载数据集,得到如图 2 所示的数据帧。该数据集有 10320 个条目,代表 2014 年 7 月至 2015 年 1 月的乘客需求。图 3 显示了 2014 年后六个月的需求值。

图 3:数据集中出租车需求的实际模式

如图 3 所示,数据集有两个异常值,它们与常规模式不同。那些高于正常水平的峰值或需求的减少,暗示我们要深入审视时代的背景。例如,图 4 中节假日(12 月 24 日、25 日)的需求快照包含了与其他日期不可比的独特数据点。

图 4:一些选定假日的需求数据点

(2)数据序列和特征工程

查看数据集,我们可以很快注意到一些明显的模式。例如,有每日模式(工作日与周末),每周模式(一周的开始与结束),以及一些其他因素,如公共假日与工作日。我们考虑构建以下有助于我们制作模型的附加功能:

  • 除了一个月中的某一天之外,还添加一周中的某一天
  • 一周中同一天每小时的平均乘坐次数。
  • 白天和晚上的乘坐次数。
# (1) Adding day of the week.
df['Weekday'] = df.timestamp.dt.weekday# (2) Adding the average of rides grouped by the weekday and hour
# 7 Days, 24 Hours = 168 values
df.avg_hour_day = df.avg_hour_day.replace(df[:7344].groupby(df.Weekday.astype(str) + ' ' + df.Hour.astype(str))['value'].mean().to_dict())# (3) Featuring the number of rides during the day and during the night.
# We define the day time to be any hours between 6 AM and 10 PM while Night time where usually there is less 
# demand is any time between 10:00 PM and 6:00 AM
df['day_time'] = ((df['Hour'] >= 6) & (df['Hour'] <= 22)).astype(int)

添加这些特性后,数据集的另一个外观如图 5 所示。

图 5:来自纽约出租车乘客的样本,带有额外的构造特征。

现在,我们可以看到白天和晚上的需求模式。

图 6:与夜间相比,乘客在白天出行的频率。

像大多数 ML 模型一样,LSTM 对输入规模非常敏感。我们需要重新调整数据集。我们将使用来自 Sklearn 的标准定标器。

(3)了解未来

我们将要建立的模型将需要接收一些关于过去的观察来预测未来。过去的观察将不会明确地指示时间戳,但是将接收到我们所称的数据点窗口。该窗口有 48 个数据点:每天 24 小时每小时两个记录,如图 7 所示。

X_train = create_sequence(X_train, 48)
X_test  = create_sequence(X_test, 48)
y_train = y_train[-X_train.shape[0]:]
y_test  = y_test[-X_test.shape[0]:]

图 7:训练测试时间序列数据集分割。

每个学习示例由过去的观察窗口组成,可以具有一个或多个特征。目标变量可以是单个目标或一系列目标。在本例中,模型学习预测单步值,如图 8 所示。输入结构必须采用以下格式[训练示例、时间步长、特征]。我们的设计具有三个特征,具有 48 个时间步长的窗口,使得输入结构为[9240,48,3]。

图 8:如何构建数据序列的演示。

使用 Keras 构建双向 LSTM 非常简单。Keras 提供了一个双向层来包装一个递归层。在我们的代码中,我们使用两个双向层包装作为参数提供的两个 LSTM 层。我们将展示如何构建一个 LSTM 和一个双向 LSTM:

model = Sequential()
model.add(LSTM(64,return_sequences=True, input_shape=(X_train.shape[1], X_train.shape[-1])))
model.add(Dropout(0.5))
model.add(LSTM(20,return_sequences=False))
model.add(Dropout(0.5))
model.add(Dense(1))
model.compile(loss='mse', optimizer='rmsprop')

return sequences 参数设置为 True 以获取所有隐藏状态。对于双向 LSTM,输出由前向和后向层生成。第一个双向层的输入大小为(48,3),这意味着每个样本有 48 个时间步长,每个时间步长有三个特征。对应的代码如下:

# Building the model
model = Sequential()
# Adding a Bidirectional LSTM layer
model.add(Bidirectional(LSTM(64,return_sequences=True, dropout=0.5, input_shape=(X_train.shape[1], X_train.shape[-1]))))
model.add(Bidirectional(LSTM(20, dropout=0.5)))
model.add(Dense(1))
model.compile(loss='mse', optimizer='rmsprop')

(4)结果

一旦我们运行了 fit 函数,我们就可以在测试数据集上比较模型的性能。图 9 展示了获得的结果。这个模型实现了一个伟大的未来预测。尽管我们构建的模型被简化为专注于构建对 LSTM 和双向 LSTM 的理解,但它可以准确预测未来趋势。

图 9:比较预测目标值和实际目标值的线图。

摘要

在本文中,我们了解了什么是 LSTM 网络以及如何构建双向网络。请注意,我们提到 LSTM 是 RNN 的延伸,但请记住,这不是唯一的延伸。例如,注意力模型,序列到序列 RNN 是其他扩展的例子。

LSTM 有助于模式识别,尤其是在输入顺序是主要因素的情况下。我们已经在提供的示例中看到了如何使用 Keras [2]构建 LSTM 来解决回归问题。本文只演示了部分代码。你可以在 my Github 上找到完整的预处理步骤的完整代码示例。谢谢大家!

参考

[1]塞普·霍赫雷特,于尔根·施密德胡贝尔;长短期记忆。神经计算 1997 年;9 (8): 1735–1780.https://doi.org/10.1162/neco.1997.9.8.1735

[2]https://keras.io/api/layers/recurrent_layers/lstm/上提供的 Keras LSTM 图层

用于泵传感器数据预测性维护的 LSTM

原文:https://towardsdatascience.com/lstm-for-predictive-maintenance-on-pump-sensor-data-b43486eb3210?source=collection_archive---------0-----------------------

在本文中,我们希望通过一些时间序列分析来解释预测性维护案例中的思维过程

坎凯奥·维莱辛在 Unsplash 上拍摄的照片

内容列表

前提
介绍
数据

—整体第一眼
—目标数据(y)
清理数据 —移除 nan
进一步选项
—异常值移除
—特征工程
—特征选择
为 LSTM 准备数据 —创建时间序列
—将数据拆分为训练验证测试集
—标准化/规范化数据
—使用简单的 LSTM

进行整形和一次性编码——

先决条件

所有代码都可以在这个 Git-repo 中找到
要重新创建这篇文章,你可以在这里找到数据集

我建议使用 anaconda 创建一个 Python 3.6 环境并安装 Python 包:

tensor flow(pip install tensor flow)
Pandas(pip install Pandas)
Numpy pip install Numpy)
Scikit-learn(pip install Scikit-learn)
Matplotlib(pip install Matplotlib)

介绍

在本文中,我们将探讨泵传感器数据的预测性维护。我们的方法对于时间序列分析来说是非常通用的,即使在你自己的项目中每一步看起来都有细微的不同。这个想法是给你一个关于一般思维过程的想法,以及你将如何解决这样一个问题。关于步骤的完整概述,请参见文章末尾的图(可能在阅读时并行打开)。它应该有助于按逻辑顺序组织所有步骤。如果你有一个类似的项目,并且只是在寻找一个演练,你可以在 Github 上查看代码,并根据你的需要进行修改。

限制文章篇幅,当然很多点只是提一下,不深究。但是,我们指出细节上的相关文章。我们希望给出的信息能帮助你理解时间序列分析的一般方法。

数据

第一眼

我们首先检查数据的总体情况。我们面前是什么?我们有多少数据?数据是如何组织的?每一部分都是什么类型的数据?

因此,我们用 pandas 中的一行来读取数据,并通过简单的打印语句来获得一些概述。

按作者

从这些照片中,我们可以得出以下信息:

CSV 文件包含 55 列,每列超过 200K 个条目。

按作者

数据被分成 52 个传感器列、一个机器状态(目标/结果)列、一个时间戳列和一个未命名列,后者只是原始索引列。

按作者

从时间戳中,我们可以看到数据是以 1 分钟为单位记录的。快速浏览一下,我们会发现传感器数据是 float32 格式,具有不同的幅度,时间戳是 yyyy-MM-dd HH:mm:ss 格式。

按作者

目标数据(y)

下面,在第一眼之后,对我来说第二重要的事情就是看一眼目标数据(y 数据/结果)。这将为解决方案策略提供一些指示。

现在,在第一次浏览数据后,我们必须检查提供了什么结果(称为目标),我们稍后可以使用这些结果来确定/定义我们的预测性维护目标/路径。在键入代码以提取目标数据时,我会问自己一些问题

  • 我们是否有目标信息,或者这将是一项无人监管的任务?
  • 目标数据是连续数据还是布尔值?
  • 目标是什么数据类型?值,文本,…
  • 目标以什么间隔记录?每个传感器条目都有一个条目,还是被分组?
  • 是每个传感器都有自己的目标(一台机器—一个传感器),还是所有传感器都有一个目标(一台机器—多个传感器)?
  • 目标是描述性的,还是我们必须确定哪些是不符合标准的,哪些是正常的?
  • 目标信息是否完整有用?

为了得到一些答案,我们将得到唯一的类,看看每个类有多少个值。发现标签是 char 格式(文本),我们知道,我们必须在某个时候将它们转换成整数值,以便我们以后的 Ml 算法使用。要将它们转换成相应的整数值,可以使用 scikit-learn 中的 mapper 函数。如果您有映射的目标,我们应该绘制它,以了解何时发生了什么。

获取目标数据的信息[来自作者]

因此,我们看到,数据集中有三个类。如前所述,它们是文本形式的,已经给了我们一个很好的提示。在其他情况下,您可能只会收到一个状态[A、B、C]或类似的状态。

可用的类[来自作者]

在对每个类中的值进行计数后,我们看到大多数类为" Normal ",这是意料之中的,因为机器应该在大多数时间正常运行。恢复破碎班为少数民族班。我们直接看到,我们最有可能无法使用中断的类,因为七个值不足以学习任何模式。

每个类的值的数量[按作者]

我们还看到,通过对这些值进行合计,我们得到了与现有行相同的数量。这意味着目标数据中没有缺失值(NaN)(当然也可以用 isna() 函数来检查)。

目标的曲线向我们显示,故障部分并不在例如末端处聚集,而是分散在整个数据长度上。这对于以后分割成训练集和测试集是很有趣的。我们还看到,恢复类总是跟随损坏类。这意味着只有 7 个条目的损坏的类不成问题,因为我们只需预测恢复阶段就能得到损坏的类。

目标数据[按作者]

为了回答一些早期的想法:我们有良好和完整的目标数据。每一行都有一个条目,这就形成了一个单机:多传感器的监督学习任务。

清理数据

既然我们理解了数据,我们将不得不寻找传感器数据的质量,并且最有可能操纵/修复/增加数据以用于以后的训练。

移除 NaNs

数据清理的第一步是检查 NaN 值。因此,在某些情况下,传感器不会发送任何数据。不要与零值混淆,零值实际上可能意味着值为零(数据集中的大量零使其成为稀疏数据集)。这些问题是

  • 有多少数据是 NaN 的?
  • 是只有少数传感器,还是大部分都有 nan?
  • 是否有些传感器的 nan 比其他传感器多得多?
  • NaNs 是聚集在一起还是分散开来?
  • 我们可以填充 nan 还是必须删除它们?

所以我们首先检查、打印和绘制它们。我们马上注意到, Sensor_15 完全是空的,因此我们将他移除以更好地缩放数据。

显示 NaNs,传感器掉落 _ 15[作者]

我们现在可以简单地从数据中删除所有的 nan,但是,我们会丢失大约 77000 个时间步长,大约是 35%。因此,我们尝试逐个传感器地移除尽可能多的 NaNs 传感器。

如果我们看看 NaNs 的第二大持有者,我们会看到传感器 50 和 51。我们可以看到几样东西。首先,传感器 50 只是在某个点失效。因此我们将移除传感器 50。这里的另一个选项是从时间步长~140000 年起删除所有传感器的所有数据…所以这不是一个真正的选项(在其他情况下,这可能是唯一的选项)。

比较 sensor_50 和 sensor _ 51[作者]

第二,两个传感器具有非常相似的振幅和值范围。更有甚者,黄色标注的部分其实非常相似。我们在其他传感器(见下文)中看到,几乎所有传感器都出现了 140000 点的下降。传感器 51 似乎也在其数据间隙后立即显示这种下降。因此,我们决定用 50 来修复 51。不是最干净的方式,但绝对有可能。

删除 sensor_50 后,我们看到 sensor_00 和 06–09 之间的传感器显示大多数 nan。现在是检查方差的好时机,方差显示了信号从其自身的平均值得到了多少。意思是,这个信号以任何方式移动吗?如果我们想检测一个趋势或类的变化,如果信号显示方差是好的。

传感器和传感器数据的差异[作者]

正如我们在标记部分看到的,传感器 00、06–09 没有显示出很大的差异。因此,我们允许我们删除这些,因为我们认为它们不会增加足够多的有价值的信息,与我们丢失的总信号数量相比。

跌落后,剩余的传感器确实显示一些 nan。现在我们尝试通过将限制设置为 30 的 fillna() 函数来填充它们。也就是说,最多填充 30 个连续的 NaN 值。这导致两个传感器剩下大约 200 纳。最后,我们只是删除那些,因为它只代表 0.09%。

旁注: 这里有一个不错的 Stackoverflow 讨论 关于如何最有效地填充 NaNs。

填充连续的 NaNs 按作者]

移除 NaNs[来自作者]

更多选项

你总是可以做更多的准备。为了进行概念验证,我建议继续使用 NaN 免费数据,并在建立基线模型性能后再回来进行进一步的数据预处理。

现在,被机器学习使用的第一步完成了。最基本的是,这些数据可以被读取并用于训练机器学习网络。然而,对于一个良好运行的解决方案来说,有更多的选项可以优化,包括所需的数据拆分和后期的缩放。

进一步优化的最常见步骤是:

  • 异常值去除/噪声降低
  • 特征工程
  • 特征选择

在简短地探讨了这个话题之后,我们将继续讨论实际状态下的信号。第一个目标应该是获得一个运行中的概念证明 (POC)。优化应该随后进行,继续信号清理、特征创建等。一切正常。

异常值去除/噪声降低

离群点去除意味着识别和去除对模式识别没有贡献或者甚至扰乱算法的信号部分。这可以通过不同的已经建立的算法来完成。在下面的文章中可以找到一个很好的概述:

需要记住的一点是,除了降噪之外,异常值的去除是信号的这些部分实际上可能是有价值的信息。因此,盲目地忽略它们并自动移除异常值和噪声可能不会破坏您的算法,但可能会降低其性能。这尤其适用于降噪。匆忙执行降噪会威胁到您的分析。

提高信噪比的一般方法是移动平均或卡尔曼滤波策略。

特征工程

在我们的例子中,我们可以直接使用信号传感器信号作为特征输入。然而,如果您的问题更复杂,信号不稳定、有噪声且高度不稳定,那么您需要利用您对该问题的了解。这种知识,或通常良好的工程特征,通常会导致更好的模型性能。不同的表述,好的特征减少了完美模型的必要性。

这个话题是另一篇文章的内容,因此我们不会深入讨论,但会给你一篇由杰森·布朗利写的很棒的文章:

https://machinelearningmastery.com/discover-feature-engineering-how-to-engineer-features-and-how-to-get-good-at-it/

特征选择

此外,这个主题本身需要一篇文章,我们将简要解释关于我们的数据集的几点,并指出更多由杰森·布朗利撰写的文献供您深入研究。

https://machinelearningmastery.com/feature-selection-with-optimization/

特征选择已经完成,因为冗余数据、坏数据或无信息数据会阻碍而不是提高你的机器学习性能。我们总是认为,数据越多越好,但更准确地说应该是:好特性的数据越多越好。 通过特征选择,我们帮助算法预先整理出哪个特征会加入来解决问题。

一个经验法则是 ,像 K-NN 这样越简单的算法越能从特征选择中受益,否则它将很难从冗余特征中分离出有意义的特征(淹没在特征中)。更复杂的算法,如随机森林和人工神经网络,能够找到自己的最佳特征。这里,我们“只是”通过先前的特征选择来减少计算量。

只是提一下,正则化在某些情况下可以代替特征选择。关于 L1 正则化和特征选择的有趣讨论可以在这里找到。好的描述可以看这里

当查看我们所有的传感器时,我们可以看到有几组传感器看起来非常相似(在下图中按颜色分组)。这意味着通过相关方法或主成分分析(PCA)减少输入传感器将会很好地工作。

分组传感器信号[按作者]

训练模型

由于数据是基数准备的,我们现在可以选择一种算法类型来解决预测问题。根据数据量、问题的复杂性、最终运行的硬件以及其他考虑因素,您可以在不同的算法之间进行选择。

由于我们没有进行特征选择,我们应该使用随机森林分类器/预测器或一种人工神经网络,因为两者都作为集成的特征选择器工作。

我们选择了一个 LSTM 来测试它在嵌入式硬件上的支持。

为 LSTM 准备数据

选择预测方法后,必须再次准备数据以适合特定的方法。经典的 ML 和 ann 数据准备基本相似,但在小细节上有所不同(如输入维度)。

创建时间序列

当前形式的数据可用于训练实际类的分类器。但是,我们希望根据实际值来预测未来的类。因此,我们需要根据目标来移动数据,以创建一个时间间隔。在此再次感谢杰森·布朗利关于这个话题的精彩文章。

移位 x[作者]

下面的代码逐块显示:

  • n_in :预测多少时间步。 n_out :用 n_in 预测多少个目标。 n_out > 1 表示预测一系列目标值。两者都可以用来展望未来。我们这里只用 n_out=1。
  • 第 6–7 行,根据 n_in 量产生移位输入。因此,如果例如 n_in=3,那么对于剩余的 46 个传感器中的每一个,在数据帧中创建 3 个移位信号和相应的名称。
  • 第 10–15 行,向前移动创建一个目标序列。
  • 第 17–18 行,将所有内容组合在一个数据帧中
  • 第 20–22 行,删除轮班产生的 nan

为时间序列预测创建移位信号[作者]

该函数返回一个包含原始值和移位值的数据帧(如下图所示)。

带有 x(t)和 x(t-1)的数据帧[作者]

我们现在必须删除我们不想要的价值观。在我们的情况下会是这样吗

  • x(t)处的传感器
  • 在 x(t-n)处的传感器,其中 n 几乎都是期望的偏移值,
  • 以及在 x(t-n # a3)处的传感器 _44(目标)。

因此,我们将剩下所需的移位数据和未移位的目标。我们现在必须删除我们不想要的价值观。

  • 第 1 行,设定展望未来的步骤
  • 第 2 行,首先调用 series_to_supervise() 创建移位数据。
  • 第 3 行,获取所有未换班人员的姓名
  • 第 4 行,获取除了我们要用于预测的时间步长距离之外的所有移位值的名称(未来值)。这个其实没必要。保留所有移位的值可能会提高性能。在您自己的项目中测试差异。
  • 第 6–8 行,取出目标数据并删除收集到的名称。

删除不需要的数据[按作者]

现在我们有移位的 X 数据和未移位的 Y 数据。

将数据分成训练验证测试集

下一步是将数据分成训练验证和测试集。通常,这是通过[*sklearn.model_selection.train_test_split()*](https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.train_test_split.html)[sklearn.model_selection.StratifiedKFold](https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.StratifiedKFold.html)*()* 功能完成的。然而,为了我们的概念验证,我们手动分割以获得更多的控制。我们选择:

手动分隔数据[按作者]

拆分数据[按作者]

现在我们已经准备好了布景。同样,对于正确的 k 倍分析,这不应该手动完成,而应该使用[sklearn.model_selection.KFold()](https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.KFold.html)[sklearn.model_selection.StratifiedKFold](https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.StratifiedKFold.html)*()*函数(分层意味着每个选择中所有类别的数量相等)。

标准化/规范化

下一步是标准化数据。如果不同的输入特征(这里是传感器)具有不同的幅度范围,则数据的标准化是必要的。否则,在使用机器学习方法时,值会被歪曲。机器学习方法主要使用函数内的乘法。一个大值的乘法导致更大的值,这将被误解为“重要性”。在例如[0,1]之间缩放所有值是中性比较的基础。

缩放数据[来自作者]

整形和一次热编码

在最后两个步骤中,我们必须按照 LSTM(我们将选择它)期望的输入形式[样本、时间步长、要素]对数据进行整形。

并且,当我们寻找分类时,我们必须在训练之前对我们的目标进行一次热编码,以便 softmax 激活正确地解释分类,而不会将分类顺序(0,1,2)误解为等级或重要性。这很容易用sk[learn.preprocessing.OneHotEncode()](https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.KFold.html)函数来完成。

两者结合在一个功能中:

现在我们已经准备好在不同的类上训练一个算法。我们会选择 LSTM。

使用简单的 LSTM

层和单元的问题

所以我们首先为自己建立一个简单的 LSTM 模型。深度神经网络,主要有两个问题:每层有多少个隐藏单元(神经元,滤波器,…)和多少层。关于模型应该有多深的问题,经验法则是:

如果您构建了自己的模型(非预训练),从一层或两层开始,在比较性能的同时逐渐添加更多层。

总的来说,对于 LSTMs,你可能会问更多的层是否意味着更多的长期记忆。这里有一篇来自杰森·布朗利T3 的关于这个话题的有趣的文章。总的来说,似乎更多的 LSTM 层提供了不同的时间缩放,因此具有更好的时间分辨率/更好的性能。这相当于 CNN 有更多层时分辨率更高。注意:更多的层意味着更多的复杂性,通常会导致过度拟合。
另一方面,隐单元(神经元、滤波器、…)的数量在 CNN 内部是不同的。CNN 的经验法则是增加每层的数字,因为需要分析更详细的信息。在 LSTMs 中,就分析时间序列而言,存储单元的数量不如层数重要。这里的经验法则是比输入特征更少的隐藏单元(存储单元)。开始时很小,例如 2,然后慢慢增加。所以尝试不同的价值观,但不要太强调它们。这里我们选择 42;-).

简单的模型

我们尝试用于概念验证的模型如下所示:

模型[作者]

两个 LSTM 层,每个层有 42 个隐藏单元和两个输出层。您可以在这里使用一个简单的单输出序列模型。我们有两个 as,我们想展示不同的使用情形。signal_out 是一个密集层,其中一个单元为我们提供预测信号,而 class_out 是一个密集层,其中 3 个单元和 softmax 激活为我们提供预测类别、【正常】、恢复损坏

模型[作者]

signal_out 在这里似乎没有太大的意义,但是我们想展示如何使用这种方法来增加预测(参见结果)并预测信号而不是类。

现在让我们训练模型:

火车模型[作者]

结果

训练指标看起来很有希望。验证(此处标记为测试)损失和准确性看起来不错。

准确性和损失[按作者]

但是我们看到了一件事。尽管预测的信号,如下所示,并不完美,但验证准确率显示为 99%。这是为什么不对不平衡数据集使用精度的一个很好的例子。仅仅通过将所有事物归类为多数类,我们就已经达到了很高的准确度。因此,最好对不平衡数据集实施 Kappa 统计、ROC、F1、Anova 等测量。为了做到科学上的滴水不漏,要使用不止一种测量方法,并进行 k 倍交叉验证。

现在运行推论。

运行推论[按作者]

最后,让我们绘制目标和预测目标的相互关系图:

预测目标与原始目标[作者]

您可以看到,故障情节没有被直接分类(由于只有 7 个样本要处理),但是,恢复阶段被很好地检测到,在这种情况下,提前 10 分钟。作为一个工程问题,这就足够了,因为我们积极地检测故障事件的开始和结束,并有时间作出反应(关闭、转移到另一个泵、降低速度等)。如果你需要提前更多的时间,从 series_to_supervised() 函数中增加 n_in 变量。然而,移位后的数据帧变得非常大,我的笔记本电脑再也无法处理它了。是时候搬到 Azure 了。

如果我们将预测类(模型的 signal_out 输出)绘制为连续信号而不是最大类,我们可以看到,如果我们为例如输出设置简单的阈值或者我们对计算的方差设置阈值,这可能会导致更稳定的分类。

作为连续信号的预测目标与作为二进制信号的原始目标[作者]

一般来说,用这种输出方法,可以预测一个信号。这意味着,您可以使用一些传感器数据来预测另一个传感器即将到来的数据。对于这种方法,您唯一需要更改的是使用您想要预测的信号作为目标,而不是类(例如,Sensor_42 的数据现在是目标)。

更多选项

如果你的项目结果不令人满意,下面的选项是可用的(可能我错过了很多):

  • 玩弄超参数
  • 添加更多层
  • 使用上述信号处理/清洁步骤
  • 使用轻量级的“经典”机器学习
  • 使用新型变压器模型
  • 合成更多的少数民族国家与甘,SMOTE,ADASYN,…
  • 重量少数级惩罚

步骤总结

这是相当长的,也许令人困惑。因此,我们再次总结我们对每一章的所有想法。这会让你很容易地重建思路。
请重用这张图片,但别忘了引用它。

思路[作者]

单变量时间序列预测的 LSTM 框架

原文:https://towardsdatascience.com/lstm-framework-for-univariate-time-series-prediction-d9e7252699e?source=collection_archive---------0-----------------------

完整的代码模板和演练

鸣谢: 马克·乔多因

LSTM 方法虽然是在 90 年代后期引入的,但直到最近才成为一种可行的、强有力的预测技术。像 ARIMA 和 HWES 这样的经典预测方法仍然很受欢迎和强大,但它们缺乏像 LSTM 这样的基于记忆的模型所提供的整体概括能力。

本文的主要目标是引导您构建一个工作的 LSTM 模型。然而,虽然本文的目标不一定是比较新的和经典的建模技术,但我将在结论中讨论经典的和基于 RNN 的技术的一些优点和缺点。

下面提供了完整代码。假设您已经导入了数据集和必要的类,那么结果应该是完全可再现的。

什么是 LSTMs?

LSTM(长短期记忆)是一种基于递归神经网络(RNN)的架构,广泛用于自然语言处理和时间序列预测。Brandon Rohrer 的视频提供了一个很好的、直观的介绍。

LSTM 纠正了递归神经网络的一个大问题:短期记忆。使用一系列“门”,每个门都有自己的 RNN,LSTM 根据概率模型设法保留、忘记或忽略数据点。

LSTMs 也有助于解决爆炸和消失梯度问题。简单地说,这些问题是神经网络训练时反复调整权重的结果。随着历元的重复,梯度变得更大或更小,并且随着每次调整,网络的梯度更容易在两个方向上复合。这种混合要么使梯度过大,要么过小。虽然爆炸和消失的梯度是使用传统 RNN 的巨大缺点,LSTM 建筑严重缓解这些问题。

做出预测后,它会反馈到模型中,以预测序列中的下一个值。每次预测都会给模型带来一些误差。为了避免爆发梯度,在门进入和输出之前,通过(通常)sigmoid & tanh 激活函数“挤压”值。下面是 LSTM 建筑的示意图:

LSTM 建筑。图片来自维基百科CC BY-SA 4.0 许可。

TL;博士——给我代码

执行脚本

数据操作方法

时间序列方法

LSTM 战法

代码和数据演练—数据准备

数据为 2010 年至今的美欧汇率,未经季节调整。你可以从圣路易斯美联储这里提取数据。

数据

在建立模型之前,我们创建一个序列并检查平稳性。虽然平稳性不是 LSTM 的明确假设,但它确实对控制误差有很大帮助。非平稳序列将在预测中引入更多误差,并迫使误差更快地复合。

我们过滤掉一个“序列长度”的数据点,供以后验证。在这种情况下,60 分。

我们的迪基-富勒—显示了平稳性

LSTM 所需的数据格式是三维的,具有移动窗口。

  • 因此,第一个数据点将是前 60 天的数据。
  • 第二个数据点是前 61 天的数据,但不包括第一天。
  • 第三个数据点是前 62 天的数据,但不包括第一天和第二天。

我们的培训数据框架

准备的最后一个主要步骤是扩展数据。这里我们使用一个简单的最小最大值定标器。我们这部分代码的序列长度是 60 天。

代码演练—构建 LSTM

分析的下一部分在代码方面非常简单。我们首先创建一个学习率调度器。该调度器将监控验证损失,并在平稳期修改学习率。

我们创建了一个方法来重置所有的权重,以防我们想要用不同的参数重新训练(这个方法在我的代码中没有使用,但是如果你需要的话,它就在那里)。

然后,我们构建一个具有 2 层的 LSTM,每层具有 100 个节点,并构建一个具有 sigmoid 激活的输出函数。

历史对象存储历元上的模型损失,其可以被绘制以评估在训练过程中是否需要调整。

按历元的模型损失

代码片段

训练模型

代码演练—预测未来

提供的类允许我们测试模型的准确性和预测未来。

下面的方法根据我们之前搁置的验证数据框架来测试我们的模型。结果很有希望。

我们的比较法

我们的比较

如果我们对准确性感到满意,我们就可以预测未来。下面是一个 LSTM 预测的快速演示。您可以看到在每个时间点模型中引入了一些误差,但是由于每个数据点都是一系列历史点,因此误差会减少。

网络将预测反馈到模型中

反转最小最大值并预测

预测点(橙色)

结论

因为这篇文章主要是关于建立一个 LSTM,所以我没有讨论使用 LSTM 相对于传统方法的优点和缺点。我想在这个结论中提供一些指导:

非技术考虑

  1. 权衡使用复杂模型和简单模型的成本和收益是非常重要的。稍微提高一下准确度可能不值得花费时间、精力和损失 LSTMs 引入的可解释性。
  2. 如果时间序列预测很容易,股票市场就解决了!无论我们的模型有多好,所有时间序列数据中都有一个固有的噪声元素,我们无法捕捉到。
  3. 不要忽视直觉。时间序列模型隐含地假设以前的时间段决定将来的时间段。情况可能并不总是如此。如果你的结果在直觉上没有意义,不要害怕抛弃模型!

技术考虑因素

  1. ARIMA(以及一般基于 MA 的模型)是为时间序列数据设计的,而 RNN 模型是为序列数据设计的。由于这种区别,很难建立基于 RNN 的现成模型。
  2. ARIMA 模型是高度参数化的,因此,它们不能很好地概括。对新数据集使用参数化 ARIMA 可能不会返回准确的结果。基于 RNN 的模型是非参数的,更具普遍性。
  3. 根据窗口大小、数据和期望的预测时间,LSTM 模型在计算上可能非常昂贵。有时候,没有强大的云计算,它们是不可行的。
  4. 最好有一个“无技能”模型来比较结果。一个好的开始是将模型结果与预测期间内每个时间步长(水平线)的【仅 平均值的模型进行比较。

LSTM 神经网络:基本概念

原文:https://towardsdatascience.com/lstm-neural-network-the-basic-concept-a9ba225616f7?source=collection_archive---------18-----------------------

长短期记忆神经网络的高级介绍

艾莉娜·格鲁布尼亚克在 Unsplash 上的照片

预测未来曾经是猜测和神秘的事情。由于人类的进步,这已经成为一项仅受数据数量和深度限制的任务。

随着我们生活在一个不断以指数速度产生数据的社会,这种预见任务变得越来越容易实现。

你对数据驱动的预测研究得越深入,LSTM 这个词肯定会让人一头雾水。和许多科技概念一样,它是一个首字母缩写词,代表长期短期记忆。

简单地说,它是一个神经网络——一个旨在模仿人类学习模式的机器学习系统——能够“记住”以前的数据和结论,并使用它来更准确地得出最终结论。

“……LSTM 为任何顺序处理任务带来了希望,我们怀疑其中可能存在层次分解,但事先不知道这种分解是什么。”
——费利克斯·a·热尔斯等译,《学会遗忘:与 LSTM 的连续预测》,2000 年

LSTM 是深度学习中的一种递归神经网络,专门开发用于处理顺序预测问题。例如:

  • 天气预报
  • 股票市场预测
  • 产品推荐
  • 文本/图像/手写生成
  • 文本翻译

需要对整个神经网络进行复习吗?

https://hackernoon.com/everything-you-need-to-know-about-neural-networks-8988c3ee4491

“由于 LSTMs 可以有效地捕捉长期的时间依赖性,而不会遭受困扰简单递归网络(srn)的优化障碍,因此它们已被用于推进许多困难问题的技术发展水平。这包括手写识别和生成、语言建模和翻译、语音声学建模、语音合成、蛋白质二级结构预测、音频和视频数据分析等。”
— Klaus Greff 等,LSTM:太空探索之旅,2015 年

像其他神经网络一样,它们包含执行计算的神经元,然而对于 LSTM 来说,它们通常被称为记忆细胞或简称为细胞。这些单元格包含权重和门;门是 LSTM 模型的显著特征。每个牢房里有 3 道门。输入门、遗忘门和输出门。

图片来源:阿莱亚·奈特

—重要的变量—

图片来源:阿莱亚骑士

—LSTM·盖茨—

细胞状态

图片来源:阿莱亚骑士

单元状态有点像传送带,在单元中移动数据。虽然它在技术上不是一个门,但它对于通过每个细胞以及向其他细胞传送数据至关重要。流经它的数据根据来自遗忘门和输入门的结果被改变和更新,并被传递到下一个单元。

遗忘之门

图片来源:阿莱亚骑士

该门在与单元状态合并之前移除不需要的信息。就像人类选择不考虑某些与决策无关或不必要的事件或信息一样。

它接受两个输入,新信息(x_t)和先前单元输出(h_t-1)。它通过 sigmoid 门运行这些输入,以过滤掉不需要的数据,然后通过乘法将其与细胞状态合并。

输入门

图片来源:阿莱亚骑士

这个门向单元状态添加信息。相当于人类在你已有信息的基础上考虑新呈现的信息。

与遗忘门类似,它使用一个 sigmoid 门来确定需要保留的信息量。它使用 tanh 函数来创建要添加的信息的向量。然后,它将 sigmoid gate 和 tanh 函数的结果相乘,并使用加法将有用信息添加到单元状态中。

此时,所有的信息都已经设置好了:开始信息、新信息和删除不需要的信息。这些都已经收集整理好了,决定已经准备好了。

输出门

图片来源:阿莱亚骑士

最后一个门根据单元状态、先前单元输出和新数据选择有用的信息。在输入门和遗忘门合并后,它通过获取单元状态来实现这一点,并通过一个双曲正切函数来创建一个向量。然后,它获取新数据和以前的单元输出,并通过 sigmoid 函数运行它们,以找到需要输出的值。然后,这两个操作的结果相乘,并作为该单元的输出返回。

关于激活功能(tanh 和 sigmoid)的更多信息:

https://deepai.org/machine-learning-glossary-and-terms/activation-function

数据在细胞间移动的整个过程发生在一个细胞中。但是在实际模型中,在得出最终结论之前,无论添加多少层,每层都可以有任意数量的单元。

然后,无论需要多少个时期(迭代),整个模型都会再次运行,以接近更准确的答案。准确度越好;预测越好。

作为人类,我们不断地以惊人的速度进行这一过程。甚至可以追溯到学习走路的时候,通过回顾我们做错了什么,看看别人做对了什么,然后从中调整。像其他神经网络一样,LSTM 过程旨在模拟人类思维。

区别在于它的计算能力。

人类是高度智能的生物,因此我们才能走到这一步,但我们知道我们制造的机器比我们更聪明。尤其是在数学和科学的速度方面。

LSTM 模型能够回顾以前的数据和决策,并据此做出决策。但是他们也要用同样的过程对可能发生的事情做出有根据的猜测/预测。这就是为什么这个模型在连续数据的情况下是最好的。它将发现趋势,并使用这些趋势来预测未来的趋势和结果。

我们能做到吗?是

但是可能没有同样的精确度。更不用说接受数百万个数据点作为输入了。

所以你看,我们可以预测未来,我们甚至不需要一个算命师这样做。

迈克尔·泽兹奇在 Unsplash 上的照片

只是一台强大的计算机,一些数据,和一点数学!

喜欢阅读吗?Co 请告诉我你对这个话题的想法,并关注以获得更多关于机器学习、数据科学、STEM 和职业/个人发展的文章。

音乐生成的 LSTMs

原文:https://towardsdatascience.com/lstms-for-music-generation-8b65c9671d35?source=collection_archive---------29-----------------------

让我们随着人工智能产生的音乐跳舞吧

图片来源: 安德烈·苏斯洛夫伊斯托克

udio 是一个领域,来自计算机视觉和 NLP 领域的思想的交叉融合拓宽了视野。音频生成并不是一个新领域,但多亏了深度学习领域的研究,这个领域近年来也取得了一些巨大的进步。音频生成有几种应用。现在最突出最流行的是一系列智能助手(谷歌助手,苹果 Siri,亚马逊 Alexa,等等)。这些虚拟助手不仅试图理解自然语言查询,还会用非常像人类的声音做出回应。

本文摘自本书, 用 Python 和 TensorFlow 生成 AI 2。这本书是约瑟夫·巴布科克和 Raghav Bali(我自己) 写的。我们的目的是为读者创建一个实用的指南,使他们能够用 VAEs、GANs、LSTMs、GPT 模型等创建图像、文本和音乐。这本书帮助了许多 Python 程序员、经验丰富的建模师和机器学习工程师理解深度生成模型背后的理论,并用实际例子进行实验。

音乐是一个连续的信号,是各种乐器的声音和声音的组合。另一个特征是我们在听的时候注意到的结构性循环模式的存在。换句话说,每首音乐作品都有自己特有的连贯性、节奏和流动。

在这篇文章中,我们将以一种非常简单的方式来处理音乐生成的任务。我们将利用和扩展堆叠的 LSTM 网络来完成音乐创作的任务。这种设置类似于文本生成的情况(这是下一篇文章的主题)。为了使事情简单和易于实现,我们将关注于一个单乐器/单声道音乐生成任务。

以下是我们此次演练的工作流程概要:

  • 了解数据集
  • 为音乐生成准备数据集
  • 基于 LSTMs 的音乐生成模型(我们说注意了!)
  • 模特培训
  • 听着节拍!让我们听听我们的模型生成的几个样本

让我们首先了解更多关于数据集的知识,并思考我们将如何为我们的音乐生成任务准备它。

本文使用的代码可以通过 Github 库【1】【2】获得。更有趣的是,这被很好地打包在一个Google-Colab启用的 jupyter 笔记本中,你可以简单地点击并使用它。

数据集

IDI 是一种易于使用的格式,它帮助我们提取文件中包含的音乐的符号表示。在本次讨论/演练中,我们将利用 reddit 用户 u/midi_man 收集和共享的大规模公共 MIDI 数据集的子集,该数据集可通过以下链接获得: r/WeAreTheMusicMakers

我们将利用这个数据集本身的一个子集。该子集基于伟大音乐家如贝多芬、巴赫、巴托克等的古典钢琴曲。子集可以在压缩文件夹midi_dataset.zip中找到,还有这个 GitHub 库中的代码。

我们将利用music21来处理这个数据集的子集,并为训练模型准备我们的数据。由于音乐是来自各种乐器和人声/歌手的声音的集合,为了这个练习的目的,我们将首先使用chordify()功能从歌曲中提取和弦。下面的代码片段帮助我们获得所需格式的 MIDI 乐谱列表。

来自 Google-Colab enabledjupyter 笔记本 的代码片段

一旦我们有了乐谱列表,下一步就是提取音符和它们相应的计时信息。为了提取这些细节,music21有简单易用的接口,如element.pitchelement.duration。下面的代码片段帮助我们从 MIDI 文件中提取这样的信息,并准备两个并行列表。

来自 Google-Colab enabledjupyter 笔记本 的代码片段

我们采取一个额外的步骤来降低维度。虽然这是一个可选步骤,但我们建议这样做,以保持任务的可处理性,并将模型培训要求保持在限制范围内。以下片段将音符/和弦列表和持续时间缩减为只有 C 大调(您也可以选择任何其他调)。

来自 Google-Colab enabledjupyter 笔记本 的代码片段

现在我们已经预处理了我们的数据集,下一步是将音符/和弦和持续时间相关的信息转换成可消费的形式。一个简单的方法是创建符号到整数的映射。一旦转换成整数,我们可以将它们作为模型嵌入层的输入,在训练过程中进行微调。下面的代码片段准备了映射,并提供了一个示例输出。

启用 Google-Colab 的代码片段 jupyter 笔记本

我们现在已经准备好了地图。在下面的代码片段中,我们将训练数据集准备为长度为 32 的序列,并将它们对应的目标作为序列中的下一个标记。

来自 Google-Colab enabledjupyter 笔记本 的代码片段

正如我们所看到的,除了与 MIDI 文件处理相关的一些细微差别,数据集准备阶段基本上是简单明了的。生成的序列及其对应的目标显示在下面的输出片段中,以供参考。

代码片段来自 Google-Colab enabledjupyter 笔记本

转换后的数据集现在是一个数字序列,就像文本生成的情况一样。列表上的下一项是模型本身。

音乐生成的 LSTM 模型

与文本生成(使用 Char-RNN)一样,我们通常只有少量的输入符号(小写和大写字母、数字),而音乐生成的符号数量很大(约 500)。在此符号列表中添加一些时间/持续时间相关信息所需的额外符号。对于这个更大的输入符号列表,模型需要更多的训练数据和学习能力(根据 LSTM 单元的数量、嵌入大小等的能力)。

我们需要注意的下一个明显的变化是模型在每个时间步接受两个输入的能力。换句话说,模型应该能够在每个时间步长将音符和持续时间信息作为输入,并生成具有相应持续时间的输出音符。为此,我们利用功能性的tensorflow.keras API 来准备一个多输入多输出架构。

堆叠的 LSTM 在能够学习比具有单个 LSTM 层的网络更复杂的特征方面具有明显的优势。除此之外,注意机制有助于缓解 RNNs 固有的问题,例如处理远程依赖性的困难。由于音乐是由节奏和连贯性形式的局部和整体结构组成的,注意力机制肯定会产生影响。

以下代码片段以所讨论的方式准备了一个多输入堆叠 LSTM 网络。

启用 Google-Colab 的代码片段 jupyter 笔记本

使用上述片段准备的模型是一个多输入网络(音符和持续时间各一个输入)。下面概括介绍了模型设置:

  • 使用各自的嵌入层将每个输入转换成矢量。
  • 两个输入被连接
  • 级联的输入然后通过几个 LSTM 层,接着是一个简单的注意机制。
  • 在这一点之后,模型再次分成两个输出(一个用于下一个音符,另一个用于该音符的持续时间)。鼓励读者使用keras实用程序来可视化网络。

模型训练和音乐生成

训练这个模型就像在keras模型对象上调用fit()函数一样简单。我们训练模型大约 100 个时期。下图描述了模型在不同时期的学习进度。

来自 Google-Colab enabledjupyter 笔记本 的代码片段

如图所示,该模型能够在生成的音乐样本中学习一些重复模式。这里,我们使用基于温度的采样作为我们的解码策略[ 参考链接 ]。

让我们听听艾的声音

以下是我们的模型分别在 5 个和 50 个时期后生成的两个样本。他们并不完美,但肯定很有前途,就像一个即将到来的音乐家。

5 个时期后生成的样本音乐

观察这两个样本之间的改进。50 个时期之后的输出比仅仅 5 个时期之后的输出更加连贯和有节奏。

50 个时代后生成的样本音乐

总结

这是一个使用深度学习模型的音乐生成的非常简单的实现。我们用文本生成的概念进行了类比。在这篇文章所基于的书中,我们进一步使用其他高级技术进行了一些音乐生成,包括 MuseGANs 等生成对抗网络。

关于作者

Joseph Babcock 在电子商务、数字流媒体和量化金融领域从事大数据和人工智能工作已经超过十年。在他的职业生涯中,他致力于推荐系统、Pb 级云数据管道、A/B 测试、因果推理和时间序列分析。他在约翰霍普金斯大学完成了博士研究,将机器学习应用于药物发现和基因组学领域。

Raghav Bali多部畅销书籍的作者,也是世界上最大的医疗保健组织之一的高级数据科学家。他的工作包括研发基于机器学习、深度学习和自然语言处理的企业级解决方案,用于医疗保健和保险相关的用例。他之前的经历包括在英特尔和美国运通工作。Raghav 拥有孟加拉国国际信息技术学院的硕士学位(金牌获得者)。

露西向 2031 年,AGI 和人工智能的未来问好

原文:https://towardsdatascience.com/lucy-says-hi-2031-agi-and-the-future-of-a-i-28b1e7b373f6?source=collection_archive---------17-----------------------

在 2031 年,一款新的 Alexa 出现了,人工智能是它的特点之一。露西是什么做的?

视频作者 Javier Ideami @【https://ideami.com

露西整天都在预测你的需求和关注,并在那里与你分享美好的时光,安慰你度过艰难的时光。她诞生于深度学习革命之后的下一次革命。露西是什么做的?

让我们想象我们在那一年, 2031 (一个象征性的数字,因为 Lucy 可能在那个日期之后的许多年才可行),让我们考虑关于 Lucy 可能有哪种基质的各种假设。我们开始吧!

图片由作者哈维尔·艾达米@ https://ideami.com

推断和类比

AGI人工通用智能,指的是一个单一系统的概念,它可以实现类似于我们的通用智能行为,而不是目前的人工智能系统,我们可以将其归类为狭义人工智能,并专门从事各种特定领域和任务。

让我们从考虑我们正在寻找的目标的关键部分开始。让我们思考一个特定的能力,它将是 Lucy 的一个关键部分,也是一个高级和通用智能系统的基本要素。

我说的是推断 T21 的能力,将相距甚远的概念和领域联系起来的能力,创造类比和隐喻的能力。

当前的深度学习模型非常擅长插值。当用大量数据训练时,它们能够在结果空间中导航,通过插值产生新的结果。然而,智力缺失的一个关键特征是:

  • 超越原始数据的概率分布持续外推的能力
  • 这种外推的缺乏使得类比和隐喻的创造变得复杂,也就是理解从一个领域转移到另一个领域。
  • 理解本身深深植根于我们创造类比的能力中。作为人类,我们可以很快理解事物,因为我们可以将它们与我们已经知道的其他概念和领域联系起来。缺乏推断使深刻理解的出现变得更加复杂。

图片由作者哈维尔·艾达米@ https://ideami.com拍摄

现在,让我们回顾一些可能的互补和重叠的路线,这些路线可能会把我们带到露西那里。

GPT 联结主义路线

在我们的探索中,由 OpenAI 创建的 GPT 架构代表了连接主义方法。

  • 强大的人工神经网络,在这种情况下,使用变压器模型,用大量数据进行训练。
  • 当前版本能够产生非常令人印象深刻的结果,这要归功于它们的能力,即在所学函数跨越的巨大空间内进行插值
  • 此时,GPT 模型正被应用于许多不同的领域,从预测文本的延续,到填补图像或计算机代码的缺失部分。
  • 问题是产生的模型是脆弱的。如果你用某些输入来挑战它,你会很快注意到它没有达到深度“理解”。从统计学的角度来看,它正在生产任何符合当前提示的东西。

现在,有人相信****随着你不断增加类似 GPT 的模型的规模,将会发生质的改进,我们将会看到外推能力以及其他高级功能的出现。

还有一些人说人工智能社区一直在改变目标,GPT 模式今天所能取得的成就在几年前会被认为是理解。

这是露西的一条潜在路线。人工智能社区的一部分所信仰的。

照片由 Alina GrubnyakUnsplash 上拍摄

混合路线

许多人工智能专家正在倡导一种混合解决方案,这种方案结合了连续和离散的方法,我们可以把它与所谓的系统 1 和系统 2 的二元性联系起来。

在他的书《思考,快与慢》中,丹尼尔·卡内曼解释了我们大脑产生思想的两种方式:

  • 系统一快速、频繁、自动、无意识
  • 系统二是缓慢的、逻辑的、有意识的、分析的、不频繁的等等

系统一与我们对周围环境和信息的感觉感知紧密相连。深度学习模型现在做的大部分事情,都可以连接到这种系统上。

系统二与我们的计划、推理、分析和抽象工作的能力联系更紧密,通常与我们的高级认知功能联系更紧密。

缩小:

  • 系统 1 可以连接到连续可微空间
  • 系统 2离散流程联系更紧密。规则、规划、逻辑论证等都有这种离散性。
  • 这种二元性,连续与离散可以在其他形式中找到。比如量子力学中的粒子 vs 波二象性

因此,关于人工智能领域:

  • 一种方法是连续方法,使用能够在连续空间轻松学习模式的可微分过程。这是深度学习擅长的领域。
  • 另一个是离散方法,利用类别、规则和离散元素的系统,可以在更高的抽象层次上运行。这是符号人工智能、合成编程等等的领域。

我们来考虑一下 DeepMindAlphaGo 项目。这个深度学习架构能够击败围棋的世界冠军,这是一个非常复杂并且曾经被认为不可能实现的成就。

AlphaGo 结合了一个卷积神经网络和一个蒙特卡洛树搜索,前者学习与游戏板相关的不同视觉模式的价值,后者在上述基础上提供了一个离散过程。

可能活动的空间太大了。离散蒙特卡罗树搜索有助于缩小可能性的范围

这是一个简单的连续方法和离散方法之间协作的例子。但是,混合模式的支持者认为这种模式可以走得更远,并设想了一种更强大的离散和连续战略的组合,正如 Franç ois Chollet 所说,这种组合将两种方法结合起来,并在它们之间有必要的重叠。

那些相信纯连接主义方法的人有一些保留意见,他们想知道:

  • 人脑中的符号或离散模块在哪里?他们说,到目前为止还没有发现。
  • 他们提出,类似符号的实体和更强大的抽象能力可能最终会从纯粹的连接主义方法中出现。

因此,这条路线代表了超越纯连接主义方法的需要。就连过去对象征性人工智能颇有微词的 Yoshua Bengio,现在也在倡导有必要探索深度学习和其他方法的结合。

图片由作者哈维尔·艾达米@ ideami.com 提供

该实施例路线

可能使用前面两种方法中的任何一种,Lucy 可能仍然无法超越某一点。为了获得更高级的智能,露西可能需要能够以类似于我们的方式与世界互动。也就是说,拥有某种形式的“身体”和某种感知周围环境并对其做出反应的方式。

当一个孩子与环境隔绝时会发生什么?她/他的认知能力受损。我们与环境的互动似乎是我们高级智能的关键。当然,没有人说环境应该是物理的样子。也可能是虚拟。一切都可能是虚拟的。

然而,环境的详细程度和复杂性非常重要,我们将在下一节中对此进行更多的讨论。这就是为什么“真实的”世界,以其巨大的复杂性,在相当长的一段时间内,可能是人工智能实体的理想环境,直到我们的模拟变得足够复杂

照片由莎伦·麦卡琴Unsplash 上拍摄

强化学习路线

强化学习是机器学习的一个领域,其中一个代理在一个环境中采取行动,同时试图最大化某个奖励。当代理人结合探索和开发策略来建立一个好的行动策略以增加期望的回报时,学习就发生了。

在 David Silver、Satinder Singh、Doina Precup 和 Richard S.Sutton (Rich Sutton 是强化学习的创始人之一)最近发表的论文“奖励足够了”中,研究人员指出,当在足够复杂的环境中训练时,强化学习可能足以达到人工一般智能

他们的论文是一篇哲学论文,他们没有提供如何实现这样一个系统的细节。但是他们强烈暗示,当与足够复杂的环境互动时,强化学习可以产生一个 T2 露西。

有些人对这样的假设表示怀疑,并说创造这样一个复杂而详细的环境可能需要非常先进的人工智能系统的存在。无论如何,这是另一条通往露西的路线。

照片由博夫肖Unsplash 上拍摄

马其顿路线

另一个互补的可能性是,露西将从多种方法的结合中诞生。Pedro Domingos 在他的书“主算法” 中写了与学习过程相关的不同范例:象征主义者、联结主义者、进化论者、贝叶斯主义者和类比者

Lucy 可能诞生于将连续离散方法与进化算法相结合,以及与其他策略如贝叶斯相结合,后者允许我们更多地考虑我们周围世界的不确定性。

佩德罗·多明戈斯和他的同事们一直在用这些混合物做实验,产生了有趣的结果。他们的研究正在进行中。

照片由 Jannis BrandtUnsplash 拍摄

网络路由

Ben Goertzel 博士是奇点网的创始人。这个项目代表了通过多个人工智能代理的交互来寻找AGI 出现的方法。在 SingularityNET 中,这是通过利用区块链技术以分散的方式实现的,因此人工智能代理可以在没有任何中央监管的情况下合作解决挑战。

与 SingularityNET 并行的是,Ben Goertzel 博士和他的团队正在开发 OpenCog ,这是一个新的 AGI 架构,它使用了超图知识库结合了多种人工智能策略和算法,从神经网络到进化系统、逻辑引擎等。这些系统根据需要协作并更新知识图。

超越或补充反向传播 算法的使用是 Goertzel 博士强调的要点之一。他想知道:“有多少神经架构仅仅因为不适合与反向传播算法一起工作而被丢弃?“作为一个例子,Ben 告诉我们,当使用进化算法时,可以使用适合度估计的推理和其他策略来指导进化学习过程。当我们使用反向传播时,这些策略更难实施。因此, OpenCog 结合了多种策略和算法来增强系统的能力。

Joshua SortinoUnsplash 上的照片

彭罗斯-哈梅罗夫路线

诺奖得主罗杰·彭罗斯和科学家斯图尔特·哈梅罗夫Orch-OR(有组织的客观还原)的创造者,这一理论提出意识来自我们神经元内的量子过程(特别是在它们的微管内),而不是来自那些神经元之间的连接。

尽管意识不是高级智能形式的强制性要求,但这种途径代表了高级人工智能的类型,这种人工智能可能由超越简单架构和算法的产生,涉及我们现实的更深层次,如上面例子中的量子过程。

因此,从这个角度来看,要达到一种高级形式的智能,可能需要在这个过程中涉及其他更深层次的难题。

照片由分形哈桑Unsplash 上拍摄

所有前面的部分可能会相互重叠。但是他们每一个人都强调或突出了潜在方程式的不同部分来接近露西。

很有可能最终的结果会与这些假设完全不同,或者看起来像是它们的部分组合。

但是,如果接近露西的最佳策略是一些不同的和更反直觉的方式呢?为此,我们求助于肯尼斯·斯坦利教授。

无路可走

在他的优秀著作“为什么伟大是不可规划的”****中,肯尼斯·斯坦利教授提供了关于寻找远大目标的深刻见解(比如露西):

  • Kenneth Stanley 告诉我们,当瞄准接近我们当前环境的目标和目的时,执行使我们更接近这些目标的优化过程可能会很有效(遵循朝向特定目标的梯度)。
  • 但是,当瞄准真正雄心勃勃的目标,那些离我们目前的状态真的很远的目标的时候,这个策略可能会适得其反。他提供了许多历史上的例子,在这些例子中,最终的成就看起来一点也不像导致它的垫脚石,也不像过程开始时设定的任何目标。当瞄准真正雄心勃勃的目标时,过程的结尾往往看起来一点也不像最初的意图或中间的步骤。
  • 总之,通向远大目标的垫脚石通常是非常奇怪的。这块垫脚石并不像最终产品。因此,当最伟大的目标被设定为目标时,它们就变得更加难以实现。
  • 肯尼斯谈到了目标的暴政(当涉及到真正雄心勃勃的目标时)。目标限制了我们的视野,并可能阻止我们找到好的垫脚石,不仅可以带我们达到目标,还可以带我们去其他意想不到的地方,甚至可能比我们想象的更好。
  • 那么,我们应该如何实现一个真正雄心勃勃的目标呢?
  • 肯尼斯·斯坦利教授说:“为了实现我们的最高目标,我们必须愿意放弃它们”并且“如果你愿意停止要求伟大应该是什么样子的话,伟大是可能的”。
  • 因此,最好的策略是完全没有目标(当瞄准真正雄心勃勃的目标时)。
  • 肯尼斯·斯坦利教授提倡遵循兴趣梯度,而不是试图朝着一个非常雄心勃勃的目标优化(遵循客观梯度),也就是说,探索并朝着有趣的、能引起我们共鸣的东西前进。这样的过程让我们发现意想不到的垫脚石。
  • 将这些垫脚石串联起来最终会让我们走得更远。多远?也许不是我们心目中的精确目标,而是一个更好的目的地。

反直觉,对吧?少即是多。但是这种感觉不熟悉吗?我们在生活中不是已经习惯了吗?发生在我们身上的许多美好的事情,不都是在我们不经意间发生的吗?,当我们只是让自己朝着自己觉得有趣的方向前进,对了,朝着前进的时候,是什么引起了我们的共鸣

伊恩·杜利在 Unsplash 上拍摄的照片

陪审团已经出来了,露西正在等待。

如果你想阅读更多关于神经科学可能帮助我们到达 AGI查看这篇我写的文章:

A.我写泰勒斯威夫特的歌曲。GPT-2

原文:https://towardsdatascience.com/lyrics-by-taylor-swift-ft-a-i-80f69f9dbe14?source=collection_archive---------16-----------------------

训练人工智能模型生成泰勒斯威夫特歌词的简单指南

拉斐尔·洛瓦斯基在 Unsplash 上的照片

没有人能否认泰勒·斯威夫特是多么值得称赞和强大。她的影响深远,超越了几代人。随着她越来越多地出现在公众面前,我们看到她的音乐从乡村音乐到流行音乐到电穿孔音乐,最近又出现了民谣永恒、独立音乐和民谣。

九张完整的专辑都有自己的年代,这是一个有趣的数据集。本文将探讨如何使用 GPT-2 基于她截至 2021 年 2 月发布的所有歌曲生成歌词。我在 azlyrics 的帮助下整理了这些数据,并决定使用 Google ColaboratoryGPT-2-simple python 包来训练这些数据。

简要技术背景

GPT-2 (生成式预训练变形金刚 2)是基于变形金刚架构的开源人工智能。 GPT-2-simple 是一个 python 包,它将微调到 GPT-2 的文本生成脚本,使文本生成更容易。Max Woolf 的这个 python 包让 GPT-2 变得非常容易访问,他有一个极好的博客详细介绍了它的工作原理和使用方法。如果你想获得更彻底的技术理解,请查阅最后的参考文献部分的阅读资料。

事不宜迟,这些是用 GPT-2 生成新的泰勒斯威夫特歌词的步骤。

设置

  • 创建一个新的谷歌合作实验室笔记本。你需要一个谷歌账户,而且你必须使用 chrome。
  • 转到编辑->笔记本设置。确保为硬件加速器选择了“GPU”。
  • 导入依赖项并加载包
%tensorflow_version 1.x
!pip install -q gpt-2-simple
import gpt_2_simple as gpt2
from google.colab import files
  • 下载 GPT-2
gpt2.download_gpt2()
  • 在左侧的“文件”菜单中上传您的 dataset.txt 文件

微调和培训

  • 下一步将开始根据数据集对模型进行微调和训练。我将它设置为在 124 米的最小模型中运行 1000 步的训练。
sess = gpt2.start_tf_sess()gpt2.finetune(sess, dataset=dataset.txt,
model_name='124M',
steps=1000)

以下是培训过程中产生的样本中一些有趣的片段:

有一些情感的东西:

I'm so sad, so sad, so sad 
I'm so sad, so sad, so sad 
Oh, so sad, so sad  
I'm so sad, so sad, so sad 
I'm so sad, so sad, so sad  
My name is whatever you throw at me 
It's all just a blur 
I'm so sad, so sad, so sad 
I'm so sad, so sad, so sad  
I'm so sad, so sad, so sad 
I'm so sad, so sad, so sad  
**What died didn't stay dead, it died alive,** oh, oh

一些温和的激励性的东西:

I was throwing stones, trying to stop you 
But you got mine And the long haul is free 
I threw them all at me 
Every day is a choice, even when you aren't a choice 
You're still trying to figure it out, just like I was 
You throw these things at me, but I'm throwing back stones 
You see I'm brave 
And the long haul is free I threw them all at me, yeah 
**Every day is a choice, even when you aren't a choice** 
You're still trying to figure it out, just like I was

一些令人困惑的东西:

You talked shit, you said sorry, 
you were just kidding 
You were losing it, losing it, losing it 
They said the end is near, 
but we'll mark it with a smile 
We were wrong and come back around here  
So it goes... - You started it - 
**It expired just now -** 
It's been a long time coming, can you tell me now I don't wanna miss you like this

一些自爱的东西:

Life was a willow and it bent right to your wind 
So you gotta belong somewhere  
Hey, that's my arse 
That's my dress 
Hey, that's my skirt 
Hey, that's my hat 
That's my hat  
It's not that easy in your world 
It's that simple 
**But I got that arse**

有些焦虑:

I'm sick and tired of your reasons 
I've got no one to follow me 
You tell me that you want me then cut me down 
And I'm sick and tired of your reasons 
I've got no one to follow me 
**You ask me for my love then you lead me to your grave** 
It's your turn, yours is good 
Turn around and find something else 
It's your turn, ours is good

到最后,事情开始变得更有意义了:

I promise you I'm not a saint 
But I'll do anything to get you 
**Ridiculed by your shapeshifting urges 
And she's passing laws that will make you her end game** 
All that I know is that you're my number one priority 
And I'm starting to see how you feel about me

歌词生成和结果

最后,训练完成后,您可以通过运行以下命令生成歌词:

gpt2.generate(sess)

通过反复运行此命令,您可以创建任意多的歌曲。以下是我生成的一些:

  1. 我要把这首歌叫做你还在上学吗?原因很明显。
I'm just another thing for you to roll your eyes at, honey 
You might have him but haven't you heard 
I'm just another thing for you to roll your eyes at, honey 
You might have him but I always get the last word  
Just another day at school, now why are you here? 
Because I, I know, I know.  
Are you still at school? 
Are you still at school? 
Are you still at school? 
Are you still at school? 
Are you still at school? 
Are you still at school? 
Are you still at school? 
Are you still at school? 
Are you still at school? 
Are you still at school? 
Are you still at school? 
Are you still at school? 
Are you still at school? 
Are you still at school? 
Are you still at school? 
Are you still at school? 
Are you still at school? 
Are you still at school? 
Are you still at school? Hey, all you had to do was...  Stay. 
I don't wanna do this to you. 
I don't wanna do this to you. 
I don't wanna do this to you. 
I don't wanna do this to you. 
I don't wanna do this to you. I, I, I... Iculus 
The screen is your screen. 
**I'm your furniture.** 
I'm your skin and my bones. 
I'm my lifeline. 
I'm my queen. 
I'm my new self.  
Reconnect with my family and I'll show you what you know. 
Music starts playin' in the living room. 
Hang up, don't fall into anyone's trap. 
This is our place. 
Let you know that this is not what we had been. 
Music starts playin' in the kitchen. 
Sit and watch what we've been up to. 
Play back what we learned.  
And you'll realize that what you see is what you know. 
In the wildest winter, just know that I've been spending the last eight months "on edge" 
I mean it, I'm just gonna shake it off, I'm just gonna shake it off. I mean it, I'm just gonna shake it off, I'm just gonna shake it off.  **Well, maybe you and I are just a couple of the many nicknames** 
I'm afraid I'm getting 
Just know I'm not letting up until the day I die

2.这一次有点像情绪过山车。我想不出一个合适的名字,除了也许,请不要爱上我,我永远不会离开你。

And there's a dazzling haze, a mysterious way about you 
In dreams I've been yours before  
In wonderland 
Back when we were still changing for the better 
I reached for you like a rarefied love 
You kissed me on the cheek and said we were forever dreaming [In dream sequence:] 
You're in the car on the way to the movies 
You're in the car on the way to the movies 
You're in the car on the way to the movies 
And the fakers run wild Screaming, "Give me a reason" 
Why don't I just drive around 
And see what's under that attitude 
What's under that attitude 
**I don't want you like a patchwork of other people's tears** I don't want you like a prize for me 
I don't want you like a prize for me  
'Cause you're my best friend 
I'm always dreaming about you 
And I'm never leaving you alone 
I'm never leaving you alone  
**So, please don't be in love with me 
I'm never gonna leave you alone** 
I'm never gonna leave you alone 
Nothing's gonna make me run again 
I'm never gonna leave you alone 
I'm never gonna leave you alone  
'Cause, baby, now I'm scared 
I don't know what's down this road 
I don't know what to think about 
I don't know what to say 
I'm never gonna leave you alone 
I'm never gonna leave you alone Singing, baby, sing me down 
Don't know what's down this road 
I don't know what to think about 
I don't know what to say  
Let me hope you never lose me 
Let me hope you never lose me  
You're my best friend 
I'm always dreaming about you 
And I'm never leaving you alone 
I'm never leaving you alone  
Singing, baby, 
sing me down 
Don't know what's down this road 
I don't know what to think about 
I don't know what to say 
I'm never gonna leave you alone[Instrumental] Oh, I remember you taking flight 
Taking off with me, honey 
Just in case you hadn't noticed 
Just in case you hadn't noticed [Instrumental] 
Have you ever thought just maybe would it be nice if I was yours? **Would it be cool if I was theirs?
Would it be cool if I was yours?** 
'Cause it's been years of hoping 
Never seen it this way. 
And we've been walking alone 
We're not speaking to each other, 
no matter what we say. 
It's been years of hoping. It's been years of hoping.

3.最后一首可能是悲伤或忧郁的青少年颂歌?我要把这个叫做看台上的鬼。

This playful trend is gonna keep you laughing 
Ever since I met you Oh, I'm only seventeen 
I don't know anything new to say 
I sit and watch you 
But I know you're making friends And I'm only seventeen 
So, playful thing 
**Play it cool, stay out of your eyes** 
**And I'll poke your fancy car** 
If it's a trend And you're gonna follow suit 
And I promise that nobody's gonna love you like me  
In the winter, in the icy outdoor pool 
**In the dead of night, life was just a dream** 
But you knew it when you saw it,  
I was dancing when the phone rings, 
And I'd show you what you don't see 
I'd hit the ground running, 
And I say, "I'm sorry for that night." **The night we frosted up 
There's a ghost in the stands** 
The one and only me 
Who isn't afraid 
To break my heart 
Be honest with you I'm not afraid at all 
I'm only seventeen 
I don't know anything 
Now I'm walking down the hall 
I should've known from the first look 
That I'm not the only one 
Who feels that way 
So I'm taking this chance to say 
That I'm sorry for that night. 

结束语

这些都是我用来训练人工智能模型生成泰勒·斯威夫特歌词的步骤。GPT-2-简单是一个伟大的和容易的方式来玩 GPT-2 免费与最小的努力,并有许多方法来定制它。您可以更改模型大小,添加更多步骤,添加各种检查点以重新开始训练,等等。,以在各种文本数据上产生不同类型的结果。

我很开心地阅读了其中的一些歌词,我绝对认为它们有泰勒斯威夫特的感觉,但没有她的抒情深度。虽然里面有一些深刻的台词,但这些人工智能创作的歌词会像 T.S .一样赢得格莱美奖吗?大概不会。

你可以在这里找到数据集和所有使用的代码。

参考

Max Woolf 的博客:如何用 GPT-2 定制人工智能生成的文本

GPT-2-简单

OpenAI:更好的语言模型及其含义

Transformer:一种用于语言理解的新型神经网络架构

M1 MacBook Pro 与英特尔 i9 MacBook Pro —终极数据科学比较

原文:https://towardsdatascience.com/m1-macbook-pro-vs-intel-i9-macbook-pro-ultimate-data-science-comparison-dde8fc32b5df?source=collection_archive---------0-----------------------

M1 vs . i9–9880h—与 synthetic benchmarks、Python、Numpy、Pandas 和 Scikit Learn 的性能比较。

丹尼尔·科尔派在 Unsplash 上拍摄的照片

M1 芯片是革命性的。谁能说苹果的第一代芯片会和英特尔几十年的工程技术擦肩而过呢?M1X 和 M2 芯片让未来看起来很有希望,但这一代人仍然有很多东西可以享受。

今天,我们将在综合基准测试中比较两台机器,pure Python、Numpy、Pandas 和 Scikit-Learn 性能:

  • 【2019 年的 16 英寸 MacBook Pro—英特尔酷睿 i9–9880h,16GB 内存,AMD 镭龙 Pro 5500M(在美国约为 3K 美元)
  • 【2020 年的 13 英寸 M1 MacBook Pro——苹果 M1 芯片,8GB 统一内存,8 个 GPU 核心(在美国约 13000 美元)

请记住,这些只是简单的编程和数据科学基准,在测试的每个领域还可以(也将会)做更多的工作。敬请关注。

今天的文章结构如下:

  • 综合基准— Geekbench 和 Cinebench
  • 比较纯 Python 性能
  • 比较 Numpy 性能
  • 比较熊猫的表现
  • 比较 Scikit-Learn 性能
  • 最后的想法

综合基准— Geekbench 和 Cinebench

除了您稍后将看到的性能差异之外,还有一件重要的事情需要注意——基于英特尔技术的 16 英寸 MBP 运行温度很高。非常性感。以至于你不能把它放在膝盖上使用,至少夏天不能。M1·麦克没有这个问题。它的风扇只是在测试的最后几分钟才启动。

让我们从单核中的 Geekbench 分数比较开始:

图 1 —单核中的 Geekbench 比较分数(图片由作者提供)

只是哇。那台价格几乎是三倍的机器根本就不存在。让我们看看这是否同样适用于多核测试。请记住,英特尔 i9–9880h 有 8 个内核:

图 2——多核中的 Geekbench 对比分数(图片由作者提供)

可笑。没什么要补充的了。

让我们回顾一下 Geekbench 中的 GPU 测试。这种比较并不是 100%公平的,因为 M1 Mac 没有专用的 GPU。结果如下:

图 GPU 中的 Geekbench 对比(图片由作者提供)

几乎是专用 GPU 的两倍,但这是意料之中的。接下来,我们来看一下 Cinebench 中单核和多核的比较。这是针对单核的:

图 4 —单核中的 Cinebench 比较分数(图片由作者提供)

M1 芯片再次领先。让我们看看多核测试的结果:

图 5 —多核中的 Cinebench 比较分数(图片由作者提供)

这些机器有点接近,但基于英特尔的 Mac 这次赢了。总之,两者都是非常有能力的机器,但人们会期望 i9 每次都以显著的差异获胜,至少根据价格。

获胜者——M1 MacBook Pro。 它在大多数情况下都是性能更好的机器,不会融化你的裤子。

比较纯 Python 性能

第一次为数据科学配置 M1 芯片可能会很痛苦。这个过程与英特尔芯片不同,至少如果你想在本地运行所有的东西。幸运的是,这里有一个你可以遵循的分步指南:

我们将在纯 Python 测试中完成几个相对简单的任务:

  • 创建一个包含 100,000,000 个介于 100 和 999 之间的随机整数的列表 l
  • 平方 l 中的每一项
  • 对 l 中的每一项求平方根
  • 乘以相应的平方和平方根
  • 划分相应的平方和平方根
  • 对相应的平方和平方根执行整数除法

因为这是一个纯 Python 测试,所以不允许使用第三方库。下面是代码片段:

结果如下:

图片 6 —纯 Python 性能比较(图片由作者提供)

这不是一个显著的差异,但仍然是 M1 芯片的一个明显的胜利。

获胜者——M1 MacBook Pro。 以三分之一的价格先完成了。

比较 Numpy 性能

下面您将看到在该基准测试中执行的任务列表:

  • 矩阵乘法
  • 矢乘法
  • 奇异值分解
  • 乔莱斯基分解
  • 特征分解

最初的基准脚本取自Github 上的Markus Beuckelmann,并稍作修改,因此开始和结束时间都被捕获。脚本看起来是这样的:

结果如下:

图 7 — Numpy 性能比较(图片由作者提供)

Numpy 是一个不同的故事。测试在英特尔芯片上完成得更快,最可能的原因是在 M1 芯片上找不到的英特尔数学内核库 (MKL)。

获胜者——英特尔 i9 MacBook Pro。 Numpy 只是工作速度更快。暂时如此。

比较熊猫的表现

这个基准测试与用纯 Python 完成的非常相似。执行了相同的操作,但是结果被合并到单个 Pandas 数据帧中:

  • 创建空数据框
  • 给它分配一个 100,000,000 个 100 到 999 之间的随机整数的列(X)
  • 对 X 中的每一项求平方
  • 对 X 中的每一项求平方根
  • 乘以相应的平方和平方根
  • 划分相应的平方和平方根
  • 对相应的平方和平方根执行整数除法

下面是代码片段:

结果如下:

图 8——熊猫性能对比(图片由作者提供)

英特尔 i9–9880h 是一款非常强大的处理器,但在这项任务中,它看起来也无法与 M1 芯片匹敌。

获胜者——M1 MacBook Pro。 它既快又无声。

比较 Scikit-Learn 性能

让我们坚持这里的基本原则,并执行以下任务:

  • 从网上获取数据集
  • 执行训练/测试分割
  • 声明一个决策树模型,找到最优超参数(2400 个组合+ 5 重交叉验证)
  • 用最佳参数拟合模型

这或多或少是一个标准的模型训练过程,不考虑测试多种算法、数据准备和特征工程。

下面是测试的代码片段:

结果如下:

图 9-sci kit-Learn 性能比较(图片由作者提供)

结果不言自明。我没有什么要补充的。

赢家——M1 MacBook Pro。两倍的速度,三分之一的价格。

最后的想法

M1 芯片绝对是革命性的。我已经完成了你在文章中看到的基准测试,编写并编辑了整篇文章,并播放了 40 分钟的《网飞》——仍然有 83%的电池剩余!

M1 MAC 电脑没有专用的 GPU,但这并不是一个问题。很有可能,你不会使用任何笔记本电脑来完成耗费资源和时间的任务,尤其是在我们谈论深度学习的时候。在云中做效率要高得多。

因此,对于日常的数据科学和分析工作,M1 似乎是一个不错的选择——出色的性能,保持凉爽,电池可持续两个工作日。如果你想买一台新的 Mac,并且你需要的一切都与 M1 芯片兼容,我看不出有什么理由再花 2 到 4 倍的钱去买英特尔的产品。

你有什么想法?您的配置与 M1 芯片相比如何?运行基准并让我知道。

喜欢这篇文章吗?成为 中等会员 继续无限制学习。如果你使用下面的链接,我会收到你的一部分会员费,不需要你额外付费。

https://medium.com/@radecicdario/membership

了解更多信息

保持联系

机器学习 101:ML 大师

原文:https://towardsdatascience.com/machine-learning-101-master-ml-66b20003404e?source=collection_archive---------11-----------------------

学习初学者掌握该领域所需的机器学习的所有必要和核心概念

Jorge Ramirez 在 Unsplash 上的照片

“机器学习将使大多数人认为只能由人完成的工作自动化。”

——戴夫·沃特斯

机器学习领域是现代世界中最重要的研究领域之一。机器学习每天都越来越受欢迎,这是当代最有趣的新兴趋势之一。它强调了人类在过去几十年中取得的进步和快速发展。

人工智能、数据科学和机器学习对现代时代的发展和技术做出了巨大贡献。机器学习尤其为当今世界的大多数行业和公司做出了巨大贡献。

为了考虑日常使用中机器学习的几个例子,我们可以从简单的 web 浏览器或 YouTube 开始。当浏览互联网时,大量的用例如自动更正和自动完成对人脑来说变得更加明显。如果你正在寻找一个 YouTube 视频或一部关于网飞的电影,这些设备中使用了高水平的推荐系统。

所有这些应用程序都集成了某种机器学习。很明显,机器学习目前在许多领域都表现出色。几乎每个大公司或行业都有大量的机器学习应用。在我们深入了解我们可以做些什么来掌握机器学习之前,让我们首先了解一些专家为我们提供的一些理论定义。

定义机器学习的第一种方法可以定义如下:

"给予计算机无需明确编程就能学习的能力的研究领域."
—亚瑟·塞缪尔

机器学习的第二种或现代解释可以被视为如下:

“如果一个计算机程序在 T 中的任务上的性能,如 P 所测量的,随着经验 E 的增加而提高,那么就说它从关于某类任务 T 和性能测量 P 的经验 E 中学习。”
—汤姆·米切尔

机器学习有很多定义。但是,上述两个理论解释应该让大多数初学者直观地了解我们可以从这些机器学习方法中期待什么。

如果你想了解更多关于数据科学的知识,以及如何掌握这门学科,我强烈建议你通过下面的链接查看下面这篇文章,它讲述了数据科学初学者在 12 个月内成为专业人士的 12 个步骤。

</12-steps-for-beginner-to-pro-in-data-science-in-12-months-c6f6ba01f96e>

在本文中,我们的主要目标将是涵盖机器学习的大多数基本方面。我们还将探索机器学习的各种功能,以及您可以做些什么来掌握该领域的大多数关键项目。因此,事不宜迟,让我们开始探索机器学习的这些特性以及随之而来的多个概念。

数学:

JESHOOTS.COMUnsplash 上拍照

不可否认,数学是机器学习最重要的方面。学习数学对于理解机器学习中涉及的一些整数编码方面至关重要。任何开始机器学习的初学者的主要焦点和目标必须是关注数学中特定的主题。

线性代数、微积分(积分和微分都有,但大多是微分的方面)、概率、统计一定是你在努力掌握机器学习的同时所热衷关注的话题。

在线性代数中,你应该关注的主要主题如下——学习线性代数的目的、向量和维度空间、点积及其角积、投影和单位向量、与 2d 和 3d 空间中涉及的所有主要主题相关的其他基本方程,如圆、矩形、球体等。

你们关注微分学的主要原因是因为像反向传播这样的主题,这对理解神经网络的概念是极其重要的。微分对于从头开始分解大量的概念和主题是至关重要的,并获得对这些算法、过程和计算的更直观的理解。

概率和统计在学习机器学习的整体方面也非常重要。统计对于理解图形数据和探索性数据分析的复杂细节至关重要。通常对于机器学习模型的构建,这些图形结构和大量的图被用于分析我们手中的数据集和数据类型。对于理解直方图和分析张量板图,在深度学习模型中也是极其必要的。

机器学习涉及很多不确定性。无论您执行的是分类还是回归之类的任务,几乎都有一些度量是模型对可能的结果没有信心的。出于这个原因,概率知识对于分解机器学习的众多概念至关重要。此外,需要注意的是,像朴素贝叶斯算法这样的主题和机器学习算法需要使用概率来掌握以下思想。

从下面的链接,你可以看到我以前的一篇文章,主题是“开始你的 Python 机器学习之旅”

编程:

Unsplash 上由法扎德·纳齐菲拍摄的照片

编程是掌握机器学习所需的另一个基本特征。机器学习中的主要项目和任务将要求机器学习爱好者具有丰富的编码知识,以便他们可以更方便地遇到问题陈述。虽然数学对于直观地理解概念极其重要,但是您需要将这些信息解释为其他人可以查看和利用的形式,这可以在编程的帮助下完成。

对于每一个机器学习工程师或爱好者来说,编码技能都是必不可少的。如果你渴望从事与机器学习相关的工作,或者任何其他涉及使用机器学习的领域,那么编程是一个非常重要的专业领域。我强烈推荐从下面提供的链接中查看下面的文章资源。它们是提高您的编码技能的很好的指南,也涵盖了为什么您应该保持更新和继续练习您的编程的原因。

</5-reasons-why-you-should-code-daily-as-a-data-scientist-fa7fc6dc92c4>

在学习机器学习编程时,请确保您专注于重要的基本主题,如列表和字典的操作,并了解 Python 的基础知识,如果这是您选择用于机器学习的编程语言的话。通过利用你的编程技能,专注于学习更多的数学实现。练习并不断提高你的编码知识。

随着 auto ml 和其他工具的引入,使得机器学习变得更加容易,一些人可能会想,执行机器学习任务是否真的需要编程。核心观点仍然是,要理解这些概念背后的逻辑和直觉,编程和编码是必须的。否则,你将无法对你计划学习的基本主题有一个直观的了解。

在机器学习中,你需要学习一些特定的编码模式集。此外,某些库和模块对于解决机器学习问题比其他的更有用。我们将在文章的下一部分详细讨论这个话题。无论如何,编程在机器学习中起着至关重要的作用,也是每一个对这门学科充满热情的人必须努力学习的东西。

库和模块:

Unsplash 上由 Valdemaras D. 拍摄的照片

Python 中的库和模块使得处理机器学习问题更加容易。有各种各样的 Python 模块可用于与机器学习相关的不同类型的任务。这些库简化了大多数复杂的任务,因为您不必从头开始编写复杂的架构和建模需求。让我们看看一些对完成机器学习模型有用的基本库模块。

Pandas 是机器学习和数据科学从收集的数据集中探索和分析可用数据的最佳工具之一。它可以读取 CSV 文件等多种格式,您可以使用该工具查看数据中的模式,并计划如何利用这些数据点来创建、构建或构建您的机器学习模型。您还可以使用以下库执行其他数据操作活动。我们将在以后的文章中进一步研究细节。

Matplotlib 和 seaborn 是绘制数据点和可视化数据外观的两个最好的可视化工具。这些库为开发人员提供了一个线索,让他们知道在构建机器学习模型时需要关注的最重要的细节是什么。机器学习中的探索性数据分析(EDA)是所有用户必须关注的关键步骤,以开发创造性的、有效的、高效的和独特的机器学习模型和项目。我们将在以后的文章中进一步研究这些库模块的细节。

Scikit-learn 是另一个很棒的库模块,可以作为 Python 中的附加库模块安装使用。一旦你安装了这个模块,你只需要几行代码就可以轻松地实现各种各样的机器学习任务、问题和算法。使用这个库模块,解决复杂的机器学习项目或任务所需的大部分复杂工作都大大减少了。拥有这样一个库的知识将增强你在编码时执行更快计算的能力。

Python 中有如此多令人惊叹的机器学习库模块。这个列表需要一整篇文章。因此,我们将在以后讨论这些主题。从下面提供的链接中可以找到 Python 中其他令人惊叹的独特库模块,它们将帮助您构建很酷的机器学习和数据科学项目。如果观众有兴趣了解更多关于这些库的信息,我强烈推荐他们去看看。

</5-unique-python-modules-for-creating-machine-learning-and-data-science-projects-that-stand-out-a890519de3ae>

算法

约书亚·阿拉贡在 Unsplash 上拍摄的照片

机器学习的一个最重要的方面是开发了许多算法,用户可以使用这些算法来创建和构建机器学习模型和项目。机器学习算法对于开发您的机器学习项目以及构建和建立您的模型至关重要。让我们讨论几个基本的机器学习算法,每个初学者和爱好者都必须立即开始工作。

初学机器学习的爱好者必须开始研究和掌握的一些基本算法是一些基本的监督算法,如逻辑回归、线性回归、支持向量机(SVM)和朴素贝叶斯算法。这些是一些最重要的算法,每个机器学习的渴望者都必须探索并开始工作,通过从事大量的任务和项目来立即掌握这些算法。

除了前面提到的算法之外,其他需要重点学习的基本算法包括决策树、K 近邻(KNN)和随机森林监督机器学习算法。这些是一些解决各种复杂任务和项目的有用算法,也是每个机器学习爱好者在遇到复杂问题时必须拥有的武器。除此之外,你还必须获得关于无监督学习算法的知识,比如聚类和推荐系统。

尝试通过从头开始执行这些机器学习算法的实现来获得直观的理解,而不使用这些外部库模块,如 scikit-learn。通过从头开始实现它们,您将对这些架构和算法的内部工作有更好的直觉和更强的理解。我还建议从下面提供的链接中查看下面这篇关于无监督聚类学习简明指南的文章。

项目:

UnsplashAltumCode 拍摄的照片

机器学习最棒的部分是你可以在机器学习领域从事大量的项目。所有机器学习爱好者都可以有如此多的选择来整合他们的想法并构建新的结构。你可以用机器学习建立这么多令人敬畏的项目,并在一些数学和编程知识的帮助下,自己从头开始创建它们。

从事机器学习项目的最大好处之一是,它给你经验和头衔,你可以把它们添加到你的简历或投资组合中。当你能够在这些项目想法上工作,并且协作你的想法来构建一些惊人的构建时,你可以部署它们并且确保每个人都能利用它们。更多的观众可以从你的技术创新中受益。

机器学习的真正魅力只能通过在众多项目中工作来探索和学习。选择一个你喜欢的话题,然后开始着手去做。在特定项目中尽可能多地尝试机器学习算法,找出最适合问题陈述的解决方案。每种机器学习算法的性能可能互不相同,因为一些模型的性能优于其他模型。

我强烈推荐从下面提供的链接查看这篇文章。它包含了 15 个非常棒的 Python 和数据科学项目,你应该在 2021 年及以后去看看。

</15-awesome-python-and-data-science-projects-for-2021-and-beyond-64acf7930c20>

资源:

威廉·艾文在 Unsplash 上的照片

在我的其他一些文章中,我已经广泛地涉及了这个主题。机器学习和数据科学拥有巨大的资源,可供爱好者探索和利用,以获得最大的好处。

每一个有抱负的机器学习爱好者都应该学会谷歌一些事实,并找到一些对他们来说最好的技术资源,同时完成一个特定的项目。查看下面的文章,进一步了解一些最好的网站,这些网站可供机器学习爱好者探索并充分利用这些资源。

</10-best-free-websites-to-learn-more-about-data-science-and-machine-learning-f2c6d7387b8d>

优势:

照片由费尔南多·巴西Unsplash 拍摄

机器学习有一些优势,这可能是一个巨大的保守说法。机器学习流行的主要原因是由于它拥有广泛的应用和优势。你可以用它创造出如此多美妙的产品。让我们快速看一下机器学习的一些优势,以便有更好的理解。

  • 他们有能力很容易地识别群体中的模式和其他共同元素。聚类算法是下面的一个很好的例子。
  • 运行机器学习算法的设备可以精确地运行任务,而不会出现任何人为错误。利用这些机器学习模型,任务的自动化是可能的。
  • 可以对建立的机器学习算法和模型进行持续的改变和改进。因此,这是一种更快的执行任务的方法。
  • 使用机器学习算法可以更容易地处理复杂的问题和复杂的数据集。
  • 如前所述,它们也有广泛的应用。它们在现代世界的几乎每个重要领域都有应用,包括医疗保健、金融等。

照片由埃里克·沃德Unsplash 拍摄

虽然机器学习有几个优势,但知道它无论如何都不是完美的也是至关重要的。不幸的是,机器学习也有一定的局限性。让我们更详细地分析和研究机器学习的一些局限性。它们如下:

  • 有时,机器学习任务将需要大量数据来产生期望的结果。因此,收集所有需要的结果有点昂贵。
  • 在创建机器学习模型时,过拟合和欠拟合是经常发生的。处理这些产生的问题可能会很困难。
  • 完成某些任务可能需要大量资源。因此,机器学习模型要解决的一些问题和任务在计算上是昂贵的。
  • 它们容易受到离群值的影响,这可能会在部署模型后导致潜在的大量问题。
  • 在自然语言处理领域,对于机器学习问题,很难找到单词和句子的语义或实际意义。在建立或构造机器学习模型时,许多问题都是由于这个原因引起的。

为了更深入地了解这些利弊话题,我建议查看一篇广泛涉及这个话题的类似文章。您可以从下面提供的参考资料中找到此链接。

应用:

博伊图梅洛·菲特拉Unsplash 上拍照

机器学习和数据科学在现代世界有许多应用。每个大公司和行业都在投入时间和精力来找出新的方法来改善机器学习模型的工作,以使他们的产品更好,并相应地满足客户的需求。这些机器学习模型和算法的重要性和应用正在显著上升。

正如我们之前讨论和考虑的一些日常使用中的机器学习的例子,我们可以从简单的 web 浏览器或 YouTube 开始。当浏览互联网时,大量的用例如自动更正和自动完成对人脑来说变得更加明显。如果你正在寻找一个 YouTube 视频或一部关于网飞的电影,这些设备中使用了高水平的推荐系统。

要了解更多关于人工智能和机器学习在众多现实世界应用中的现实应用,请随时通过下面提供的链接查看下面的文章。

</10-awesome-real-world-applications-of-data-science-and-ai-6fddf3f34d74>

结论:

Unsplash 上由 Boitumelo Phetla 拍摄的照片

“我们正在进入一个新世界。机器学习、语音识别和自然语言理解的技术正在达到一种能力的结合。最终结果是,我们很快就会有人工智能助手在生活的各个方面帮助我们。”

——艾米·斯台普顿

现代世界中的机器学习是发展的一个重要方面。随着机器学习领域这些年来的快速发展和进步,我们可以感觉到在未来的几十年里,这个学科将会有更多辉煌的发现和发明。因此,如果你对这个领域感兴趣,这可能是学习机器学习的最佳时机。

在本文中,我们已经涵盖了掌握机器学习所需的大部分基本要求,包括数学、编程、重要的库和模块、掌握机器学习的项目和资源、机器学习的众多优势和轻微限制,以及机器学习在现代的主要应用。

这个时候或许是每个有志于追求机器学习的人投入资源,致力于掌握这门学科的最好、最理想的场景。多年来,机器学习的普及程度将继续上升,这一新兴趋势似乎不会很快放缓。所以这个机会一定要被每一个发烧友充分利用!

如果你对这篇文章中提到的各点有任何疑问,请在下面的评论中告诉我。我会尽快给你回复。

看看我的其他一些文章,你可能会喜欢读!

</5-unique-use-cases-of-ai-that-might-surprise-you-22478aaaabaf> </10-best-free-websites-to-learn-programming-939ec029009b> </5-reasons-why-you-should-develop-a-game-with-python-and-ai-9f5f276e7637>

谢谢你们坚持到最后。我希望你们喜欢阅读这篇文章。我希望你们都有美好的一天!

系统工程视角下的机器学习

原文:https://towardsdatascience.com/machine-learning-a-systems-engineering-perspective-1be9d13040e7?source=collection_archive---------23-----------------------

入门

本文使用基本的系统工程原理对机器学习采取了一种整体的方法。使您能够理解和管理大多数机器学习系统中的基本构件。你将学习如何从数据到预测。

图 1:机器学习系统设计

目录

  1. 系统工程原理
  2. 机器学习
  3. 探索性数据分析
  4. 培训子系统
  5. 评估
  6. 示例

系统工程原理

系统工程试图通过将复杂的项目分解成可管理的、定义明确的子系统来理解全局。本文将利用基本的系统工程原理,将机器学习作为一个由交互元素组成的系统来介绍。本文中术语的使用是对系统是由相互作用的部分组成的有目的的整体这一基本思想的阐述。作为这些系统的一部分的每个元素本质上是原子的(即,不可进一步分解),并且使用描述性特征来建模。这降低了复杂性,并通过允许管理当局获得机器学习流水线的高级视角来支持任务独立性。

机器学习

在机器学习中,一切都源于通过数据对真实世界环境的近似表示。因此,正确的数据对于应用的机器学习模型的成功至关重要。尽管“正确”这个术语有些模糊,而且完全依赖于任务,但是在项目启动之前,还是需要考虑一些重要的因素。首先,我是否拥有这些数据,或者我是否可以许可这些数据?越多人能接触到相同的数据流,竞争就越激烈。我只会将这种策略应用于严格的数据保护法下的商业用例。如果数据不是个性化的,并且没有限制,我会推荐开源你的数据,每个人都可以贡献。其次考虑;我可以访问连续的数据流吗?通过根据最新的数据样本重新训练模型,可以不断提高模型的准确性和泛化性能。收集正确数据的整个过程被称为数据挖掘。

后续步骤是数据预处理。为了创建高质量的机器学习系统,提高数据质量和促进有意义的见解的提取至关重要。该过程包括数据点的去重、归一化和变换,以及特征提取和选择。到那时,数据通常被组织在表格结构的数据库中。在我们的例子中,输入特征可以是图像的像素或语音频率,用相应的标签或注释来组织。前面提到的结构描述了一个标准的监督学习场景,它将在本文中用于说明目的。除此之外,机器学习一般包含三类算法;监督学习、非监督学习和强化学习。

图 2:机器学习中的子类

探索性数据分析

在开始开发之前,对于机器学习模型应该从数据中学习什么,你可能只有一个模糊的策略或目标。为了培养你的想法,探索性数据分析(EAD)可以作为一个探索阶段来获得数据的初步解释。通过直观地绘制来总结主要特征有助于理解数据集。这主要是通过从维度上减少数据来推断主要特征和趋势。此外,EDA 是探索性研究和概述范围的重要工具。因此,允许项目经理识别系统需求。

培训子系统

培训子系统可分为三个阶段;选择学习算法,优化超参数,并根据数据训练模型。在第一阶段——选择学习算法——有已经存在几十年的传统机器学习算法,如随机福里斯特(RF)或支持向量机(SVM)。然而,这一系列文章将主要关注基于神经架构的算法。我认为最有前途的两种算法是深度学习(DL)和深度强化学习(DRL),因为这两种算法都非常适合 GPU 计算和数据量。

选择学习算法和模型架构后,第二步是超参数优化。超参数是不在模型中直接学习的参数。它们用于配置模型(例如,决策树的数量及其深度或深度神经网络的层数等。)或成本函数(梯度下降算法的学习率等。).在训练期间,该算法对数据集进行多批迭代。当模型暴露于数据集中的每个数据点一次以相应地更新内部模型参数(例如权重)时,定义一个时期。

评测

这种迭代持续多个时期,直到达到某个性能分数或时期的目标数量。虽然训练模型是一个关键步骤,但衡量模型在未知数据上的泛化性能也是一个同样重要的方面,应该在每个机器学习管道中加以考虑。泛化是在未观察到的样本(新数据)上表现良好的能力。机器学习的主要挑战是减少泛化误差。可以使用交叉验证来近似计算。它提供了一个框架,其中 80%的数据集专门用于训练,其余 20%分别用于测试和验证。在每个时期之后,模型的性能分数被连续计算。

例子

假设,我们要开发一个自动诊断黑色素瘤皮肤癌的 app。一种方便的患者端解决方案是拍摄受影响皮肤的照片,并将其上传到应用程序。后端机器学习模型然后应该预测给定图像的黑色素瘤皮肤癌的概率。要开发下面的系统,我们可以按照前面提到的步骤。我们用来训练模型的数据集是 SIIM-ISIC 黑色素瘤皮肤癌数据集。它包含 44,000 个黑色素瘤皮肤癌的标记图像。任何预处理和转换步骤都已经完成。我们可以使用 2016 年博览会(脸书)推出的一款 ResNeXt -101 模型架构。该架构包含大约 4400 万个参数,这些参数将在 35000 个训练图像上共同学习。在训练期间,模型内部试图最小化损失函数,例如交叉熵损失,其相应地更新参数。诸如误差(精确度/召回率)、精确度、MSE、F1 分数之类的性能分数近似于在 9.000 个看不见的图像/标签上评估的精确度和概括能力。在模型通过验证阶段后,它可以用于对上传的图像进行在线实验推断。我们不会详细讨论我们需要继续进行的进一步步骤,直到我们可以发布该项目,因为我们在这里只关注技术实现。

现在,我们对所涉及的技术构件有了基本的了解。我们将在下一篇文章中使用上述建模技术来设计一个生产就绪的机器学习系统。这涉及到更多的组件,如项目设置、数据管道和关于服务的详细阐述,包括测试、部署和维护。

在回归设置中评估机器学习模型的准确性

原文:https://towardsdatascience.com/machine-learning-accuracy-regression-59f72c36eeb4?source=collection_archive---------27-----------------------

讨论如何在回归设置中评估机器学习模型的性能

戴安娜·波莱希娜在 Unsplash 上拍摄的照片

介绍

在机器学习领域,当应用于不同的环境和问题时,没有一种方法可以保证是最佳的。

一种特定的方法可能最适合一个特定的数据集或问题,但同样的方法应用于不同的数据集时可能就太弱了。选择最合适的方法是机器学习模型开发中最具挑战性的部分之一。

在今天的文章中,我们将讨论在回归设置中评估和选择机器学习模型时,您应该始终牢记的几个概念。

如何评估模型性能

为了评估一个特定的模型,我们显然需要某种定量的度量,以某种方式告诉我们模型预测与实际数据相比如何。

最终,这种度量还将帮助我们比较各种模型,以便我们可以根据特定的项目标准选择表现最佳的模型。

现在,根据我们想要评估的具体方法,我们可能需要使用一种能够量化其性能的方法。

均方误差

在回归设置中,最常用的测量方法之一是均方误差(MSE ),它由下面给出的公式定义。

均方误差方程

在哪里

  • n 是观察次数
  • y 是实际值
  • f(x) 是第 i 次观察的预测值

较低的 MSE 值表示较强的模型性能,这意味着预测值和实际值更接近,而较高的 MSE 表示较弱的模型性能。

要考虑哪些观察结果

当计算训练观测值的 MSE 时,我们通常称之为训练 MSE。然而,我们最感兴趣的是评估模型对未知数据进行预测的能力(例如,测试数据包括在模型训练阶段没有观察到的数据)。

因此,在评估回归模型时,我们需要观察测试 MSE ,这将从本质上告诉我们模型对未来数据的表现如何。尽管测量训练 MSE 可能仍然有用,但我们需要选择给出最低测试 MSE 的模型(假设这是您真正关心的唯一指标)

那么,如果我们只考虑测试 MSE,为什么还要测量训练 MSE 呢?答案相当简单。如果特定模型的训练 MSE 较小,但同时测试 MSE 显著较大,则该模型可能过度拟合。

当模型过于严格地遵循训练观察时,会发生过度拟合,达到甚至学习噪声的程度,从而不能很好地推广到新的、看不见的数据点。

最后的想法

模型评估是机器学习模型开发过程中最重要也是最具挑战性的阶段之一。在今天的简短指南中,我们讨论了均方误差,这是在回归设置中评估模型时最常用的测量方法之一。

此外,我们讨论了训练和测试 MSE 之间的差异,以及它们在评估模型性能时各自扮演的角色,以及这些值之间的巨大差距如何可能表明过度拟合。

注意,当我们必须处理大量的观察数据时,我们也可以计算平均误差的平方。

成为会员 阅读介质上的每一个故事。你的会员费直接支持我和你看的其他作家。你也可以在媒体上看到所有的故事。

https://gmyrianthous.medium.com/membership

你可能也会喜欢

使用 MLFlow 的机器学习冒险

原文:https://towardsdatascience.com/machine-learning-adventures-with-mlflow-64127713b0a1?source=collection_archive---------12-----------------------

作者图片

在本地系统上构建 ML 工作流

你好。

这篇文章是写给任何想开始使用 MLFlow 的人的。我们将探索 MLFlow 的概念,使用 MLFlow 实现简单的端到端 ML 工作流—从在笔记本中创建模型到打包和部署模型。之后,我将解释如何将这个简单的工作流程转化为生产级别的模型管理。

我们将在工作流程中融入一些 MLOps 概念,如模型训练、模型评估、打包和模型部署。要了解 MLOps 及相关概念,可以阅读我的其他文章

我们开始吧!

什么是 MLFlow?

MLFlow 是一个开源的端到端平台,用于管理 Databricks 提供的机器学习生命周期。还有一个供企业使用的托管 MLFlow 版本。

在本文中,我使用开源版本。

好吧!为什么我需要 MLFlow?

大多数数据科学家和 ML 工程师能够在他们的笔记本电脑和台式机上创建一个模型。他们可能使用 Anaconda、Jupyter 或其他 IDE 来编写他们的 ML 模型。当他们必须随着时间的推移提高他们的模型性能时,以及当一个团队的多个成员处理同一个模型时,会出现以下问题

  • 跟踪模型中所有调整过的参数。
  • 记录输出、准确度和误差分数。
  • 维护模型及其相关数据对象(定标器、估算器、编码器等)的记录。)
  • 将他们的模型版本化。
  • 与团队成员共享模型——其他成员在他们的系统上运行模型需要哪些先决条件/设置。
  • 用 API 包装他们的模型并部署它,将需要额外的编码和技术栈知识。

这就是 MLFlow 发挥作用的地方,它减轻了学习全新技术堆栈来维护、跟踪和部署模型的痛苦。提供简单的 API,您可以将它们集成到模型代码中,这样您就可以将模型部署到生产环境中了。

好吧!我需要知道哪些概念?

在我们一头扎进编码部分之前,我们需要了解一些关于 MLFlow 的概念。

模特跟踪

我们更新了吗?(图片由作者提供)

作为一名数据科学家或 ML 工程师,您将花费大量时间来改进您创建的模型。跟踪您调整了哪些参数,哪些特定的组合能让您获得更好的性能,以及您需要比较哪些误差指标,这变得很乏味。模型跟踪是一个需要理解的重要概念。当您将所有的指标和度量都制成表格并随时可用时,跟踪模型性能和比较模型就变得更加容易了。

所有这些额外的簿记工作都由 MLFlow 跟踪 API负责。

ML 项目

所有开发的软件通常都遵循一种设计或架构模式,但机器学习并非如此。ML 模型没有特定的结构或架构模式,每个问题都涉及一组不同的需求和设计。在团队或组织中跨系统共享代码和设置模型变得很困难。

MLFlow 创建了一个标准化的模式和结构,涵盖了大多数 ML 用例,并使代码易于移植。您可以提供目录结构、希望模型运行的环境的详细信息以及模型的入口点,即模型需要什么输入。把它看作是一个 ML 模型的简要总结,它会告诉你这个模型是什么,它需要运行什么,你需要提供什么输入,你会得到什么输出。

检查旅客名单!(图片由作者提供)

ML 车型

一旦您的模型准备好了,您希望您的模型被部署到云或边缘设备上。您需要打包您的模型来部署它。打包一个模型包括指定你的模型需要什么样的环境,你的模型的特征是什么也就是说,你的模型需要什么样的输入,输入应该以什么格式提供?一旦您将模型打包,您就可以将它存储为 pickle 格式,并且可以进行部署。

MLFlow 提供了各种内置格式,用于根据库或风格打包模型。例如:Tensorflow,Sklearn,Keras,H20,XGBoost 等。

模型注册表

随着您不断用新数据改进模型,您将拥有不同版本的模型,它们具有不同的准确性、误差水平和其他指标。生产中的模型可能与开发阶段的不同。 MLflow 模型注册表帮助您跟踪哪个模型出现在哪个阶段。您甚至可以在不需要时将一些旧型号存档。

啊!困惑(作者图片)

现在我们已经理解了 MLFlow 中的概念,是时候将它们应用到实践中了。我将向您展示如何在您的本地系统中引入简单的机器学习管道,从那里我们将看到它如何扩展到生产系统。

示例—红色/蓝色分类器

我们有一组空间点的数据。我们的工作是分类给定的点是属于红队还是蓝队。我们训练一个分类器来帮助我们完成这项任务。我在这个 g ithub-repo 里提供了全套的样本数据和 jupyter 笔记本,这样你就可以跟着做了。

注意:这个例子是为了帮助你理解如何执行和跟踪 ML 实验。我将专注于如何利用 MLFlow 进行训练、跟踪和部署,而不是如何构建或训练最准确的分类器。

这个例子是在 Linux 系统(Ubuntu)上创建的。只要你安装了 Python 和 Docker 就可以在 Windows 上工作。

让我们从数据开始

您可以在 repo 的数据文件夹中看到数据样本。这是样本的可视化

数据样本可视化(图片由作者提供)

从数据中可以看出,红点多在右侧和右上方区域;蓝色点位于左侧和左下角区域。您还会注意到 x 轴和 y 轴的刻度是如何不断变化的。因此,我们需要设计一个二元分类器,它能够随着尺度的变化而训练。

在本地启动 MLFlow 服务器

在我们开始构建有史以来最伟大的分类器之前,我们需要在本地系统上启动 MLFlow 服务器。使用 python 下载 mlflow 库

$ pip3 install mlflow

在您的本地系统上克隆我提供的 github repo,在终端中打开文件夹,运行以下命令启动 mlflow 服务器

$ mlflow server --backend-store-uri sqlite://mlruns.db --default-artifact-root file://$PWD/mlruns

这个命令做三件事

  • 创建一个名为 mlruns.db 的 sqlite 文件来记录所有实验和相关数据
  • 创建一个本地 mlruns 文件夹来存储所有模型及其相关数据
  • 在您的系统上启动 http://127.0.0.1:5000/ 上的 MLFlow 服务器

现在,您可以在您最喜爱的浏览器中浏览到该链接,并查看仪表盘。

MLFlow 仪表板(图片由作者提供)

现在我们已经启动并运行了服务器,我们可以开始构建分类器了。

训练模型

您可以按顺序运行 Jupyter 笔记本中的代码单元格。我们有 3 个功能— 转换 _ 数据、训练 _ 模型和缩放 _ 数据。这些函数帮助我们训练分类器。

我们在这里训练两种分类器:

  • k 最近邻分类器
  • 随机森林分类器

您可以运行培训和跟踪部分下的单元。一旦单元运行,您将在 MLFlow 仪表板中获得条目。

物流跟踪(图片由作者提供)

在这里,我们注意到实验运行是如何整齐地为我们列出来的。仪表板过滤器甚至允许我们搜索和过滤特定的运行。

MLFlow 搜索(图片由作者提供)

你可能会问— 为什么我们没有通过合并样本来使用整个数据集?

我们可以在整个数据集上运行训练,但我的目标是解释如何在真实场景中使用 MLFlow。

现实世界中的数据不是干净的,数据格式不正确,数据不是 100%准确,并且数据永远不会完全可用。

通过将数据分成样本,我们可以复制我们的模型在一段时间内将如何遇到新数据,并用新数据训练我们的模型。

现在我们已经训练了我们的模型,我们可以用它以前从未见过的单独数据来测试它(真实世界的场景)。运行测试预测部分下的单元。在这里,我们加载数据,加载我们保存的缩放器,加载模型——您可以选择任何模型,只需替换仪表板中某个实验运行的 runId

预测结果(图片由作者提供)

看看我们分类器的魔力。

打包并部署模型

现在我们手上有了一个很棒的分类器,你想把它分享给你的朋友和队友。有两种方法可以部署您的模型

  1. MLFlow 服务(无代码方法)
  2. 模型的自定义包装

MLFlow 发球

您可以使用命令在本地系统上直接运行该模型

$ mlflow models serve --model-uri runs:/ede4cc6ace71468ab2e881dc14d25f6b/models --port 5050

要跨服务器或在其他系统上部署它,我们需要打包模型。我已经编写了一个示例 docker 文件,它将帮助我们打包模型。

文档要点

注意:您可以在命令和 docker 文件中根据自己的选择更改 runId 和端口号

使用以下方法构建 docker 映像

$ docker build -t my-awesome-model .

您可以使用运行映像

$ docker run -d -p 5050:5000 my-awesome-model:latest

您也可以将其发布到 Dockerhub 或您选择的 docker 注册表。

自定义包装

您必须明白,您使用 mlflow serve 部署的模型假设您已经给出了已缩放的输入,但情况可能并不总是如此。有时我们需要在模型中使用一些额外的 API,比如说/health API 或者/visitors API 来检查模型被使用了多少次。

为了包含额外的配置,我们编写自定义包装器,通常使用 Flask 或 FastAPI。你可以在app_wrapper.py文件和 repo 的 Dockerfile 文件中找到例子。

您可以使用 Postman 应用程序测试该模型,如果使用 mlflow 服务器,发送 POST 请求,如图所示/invocations,如果使用自定义包装器,则发送/predict

邮递员中的 API 测试(图片由作者提供)

我们导入数据,构建分类器,在多个数据样本上训练它,并在本地部署它。恭喜你!您已经使用 MLFlow 创建了第一个 ML 管道。👏

生产工作流程

现在您已经掌握了工作流是如何在本地系统中实现的,我们将学习工作流是如何在生产中实现的。

示例制作设置(图片由作者提供)

在生产设置中,我们通常包括一个 JupyterHub 服务器,它具有用户访问管理功能,用于对模型进行编码。此 JupyterHub 服务器连接到 MLFlow 跟踪服务器以进行日志记录实验。实验数据记录在 Postgres 数据库中,这是一个功能强大的数据库,具有很高的可靠性和性能。

生成的模型存储在 S3 存储桶或远程 FTP 服务器上。

记录模型和实验记录后,将触发 ML 管道进行部署。可以使用像 Jenkins 或 GoCD 这样的 CI/CD 服务器,这个管道完成包装、构建和打包模型的工作,正如我们在上面看到的。当模型打包就绪后,将部署到所需的公共云或私有云。

生产技巧

以下是团队管理大规模模型开发工作流的一些技巧

  • 使用标签识别模型,随着实验列表的增加,更容易编目和搜索
  • 记录与模型相关的所有指标,这有助于我们跟踪模型谱系并评估模型随时间的性能。
  • 为培训中使用的数据添加标签,有助于了解数据如何随时间变化。使用 GitLFS 或 DVC 进行标记和版本控制。
  • 为每个不同的问题集创建一个新的实验,不要将所有的实验运行都塞进一个中,确保实验名称是唯一的。
  • 如果一个模型足够好,可以进行测试和部署,在 MLFlow 中注册该模型,这将有助于我们在模型生命的不同阶段跟踪该模型。
  • 版本你的模型,简单的版本风格可能是 3 点版本。即awesome-model:1.2.3将是**model-target.performance.pipeline/data** 模型-目标将是一个重大变化,如果模型被完全修改或目标数据被完全改变,那么性能将是如果模型的性能随着时间的推移而改善,并且最后一个数字是不同的数据版本或管道构建号。
  • 尽量保持清晰一致的输入签名和格式,如果模型需要作为数据框架或张量输入,请指定。由于发送的大多数请求都是 JSON 格式的,所以 MLFlow 确实会隐式转换它,但是如果您正在为模型编写一个自定义包装器,那么开发人员需要了解数据或比例转换。
  • MLFlow 可以将模型直接部署到 Sagemaker 和 Azure,确保您选择了合适的实例进行部署,不要盲目选择默认选项(即对于 30Mb 大小的模型,在 AWS 上使用 c5 大实例将会完全浪费计算能力)。
  • 如果使用包装器进行模型部署,确保使用生产就绪包装器,如 FastAPI 。如果正在使用烧瓶/ Django,添加独立 WSGI 容器
  • 使用 S3 桶或基于 S3 的存储(Minio)来存储模型。这有助于在部署的实例之间维护和转移模型。
  • 到目前为止,在使用开源 MLFlow 时,可以在 S3 存储和 Jupyterhub 添加访问限制。受管 MLFlow 提供与笔记本电脑集成的身份验证和 ACL 规则,供企业使用。

这些观察来自我在跟踪和管理模型的个人经验。希望它也能帮到你。😄

跟踪、管理和优化模型是一个缓慢的过程。不断尝试 MLFlow,随着时间的推移,你会在模型管理方面做得更好。

目前就这些。下次见!保重。

再见!👋

参考

ml flow——【https://www.mlflow.org/docs/latest/index.html

KNN 分类器https://sci kit-learn . org/stable/modules/neighbors . html #分类

Github 回购示例https://github.com/yashaswi-nayak/mlflow-adventure

文章中所有的插图/艺术品都是我用 Krita 创作的。

机器学习:预测患者住院时间的初步方法

原文:https://towardsdatascience.com/machine-learning-an-initial-approach-to-predict-patient-length-of-stay-350e358ea8cb?source=collection_archive---------24-----------------------

图片由安娜·施韦茨拍摄

一些观察:

患者住院时间(LOS)定义了患者在医疗机构住院的时间。尽管 LOS 的含义非常广泛,但在这里我们将重点关注它与医院环境中以下负面和相关结果的正相关性:

  • 更大和意外的医院资源需求;
  • 患者获得医疗保健相关感染(HAIs)的可能性;
  • 增加付款人拒绝索赔的可能性,使医院面临财务风险

因此,预测损失的能力可能是有利的,因为它允许医院有时间更好地分配资源以满足意外需求,从而改善患者的健康状况,降低成本,并满足保险要求。

在这里,我描述了一个初步的方法来预测医院的杠杆损失。

工作方案:

分析可以利用机器学习来进行 LOS 预测。有两个基本要求:(1)高质量的数据(2)高质量的模型。我们从数据开始。

在我们的模型中使用临床数据似乎是最显而易见的选择,比如提供者记录、治疗细节、实验室、程序等。但是,这些数据中的大部分直到患者已经入院数小时或数天后才可用,这使得这些数据无法用于做出主动决策。

但是,我们可以利用其他特征(即变量),这些特征虽然看起来不太明显,但在患者入院时就可用。这些变量可能包括初始共付额、患者的邮政编码、入院部门、入院时与患者在一起的探视人数等。

训练和测试数据

我将使用 python 的 scikit-learn 库,使用对应于 318,438 名患者的 16 个特征变量来预测 LOS。这些数据在 Kaggle.com 的公开发布。

监督机器学习经常利用 python 的 train_test_split 包。这个包将我的数据分成 70%用于训练,30%用于测试。对于训练,我将构建一个学习算法来比较我的要素和它们的已知 LOS 结果之间的关系。然后,我将使用剩余的数据进行测试,并使用我的特征通过我的模型来预测 LOS。由于我已经知道这些特征的 LOS 结果,我可以将它们与我的预测进行比较,并得出范围从 0-100%的准确度分数。

注意,LOS 结果变量(下面标记为“Stay ”)实际上是多类序数。每个类的时间跨度从 10 天到“超过 100 天”,所以为了保存这个数据结构,我必须应用分类模型。如果我有入院和出院日期,我可以将这些类重新配置为连续的数据类型(即天数),这将有助于我使用回归模型的方法。但是没有这方面的信息。

特征和结果变量(图片由作者提供)

从我们的数据来看,很明显外伤病例几乎是急诊病例的三倍。看看哪个类别对停留时间的影响最大将会很有趣。

录取类型(图片由作者提供)

疾病的严重程度显示,中度病例比极端或轻微病例多得多。人们可能期望极端情况与更高的损失正相关。

病情严重程度(作者图片)

接下来,我们需要一个基线准确度分数来评估我们的模型与随机机会相比表现如何。通过检查多数类对所有类的平均值,即 LOS 11–20 天,我确定我们的基线准确性为 27%。

现在,让我们创建一个循环(如下所示),该循环将评估不同的模型及其预测我们的损失结果的准确性。

预测模型的准确性概述(图片由作者提供)

我使用了不同的分类模型,每个模型都有自己的优缺点。例如,随机森林是对决策树模型的改进,它根据每个特征的重要性将患者分为不同的 LOS 类别。分割越大,特性越重要,在某种程度上,该特性被优先考虑。随机森林采用多个决策树的集合来减少方差(即过度拟合的数据),因此可以更准确地预测新特征。问题是我们无法真正想象随机森林。这是一个“黑盒”模型,它创建了数千种不同的树来最好地预测 LOS。但是,我们可以找出特性的重要性,看看哪些特性对 LOS 的影响最大。

在下面的模型比较中,我们已经可以看到一些模型的表现优于我们开始时 27%的基线精度。

准确度分数(作者图片)

虽然其中三个模型有所改进,但为了达到尽可能高的精度,继续改进它们是很重要的。就目前的情况来看,我们的最佳模型仍会有一半以上的时间对患者 LOS 进行不正确的分类。然而,这第一步告诉我,GradientBoost 和 RandomForest 最有希望预测 LOS。

摘要

这里的结果类似于 Kaggle 上的顶级表现者,这是一个不错的开始。如果我现在将这些策略应用于真实的医院数据,我还会:

1.执行更多的数据准备-删除或输入丢失的数据,标记编码类别,分配虚拟变量等。

2.评估任何可能威胁我的准确性的特征相互作用,例如多重共线性、低特征重要性、同方差等。

3.调整模型超参数

感谢阅读!这是将在 GitHub 和 LinkedIn 上发布的综合报告的摘录。如果你对医疗保健和数据交叉的其他方式感兴趣,或者如果你有有趣的挑战要分享,请留下评论或 DM。

站点位置数据的机器学习和分析

原文:https://towardsdatascience.com/machine-learning-and-analysis-of-site-position-data-69e3d91fe473?source=collection_archive---------33-----------------------

谷歌的机器学习算法是什么,它们如何帮助在 SERP 中获得更高的职位

KOBU 机构Unsplash 上拍摄的照片

机器学习(ML)在过去十年中一直在积极发展。我们必须承认,进步取得了令人印象深刻的成功。然而,尽管 ML 的积极发展,许多 SEO 专家还没有使用这个选项,因为神经网络的使用仍然是昂贵的。

与此同时,谷歌越来越多地引入算法,在 SERP 中对网站进行排名。因此,如果程序员推广一个个人网站或在客户端网站上工作,他肯定需要知道谷歌的下一代算法是如何工作的,并把它们考虑在内。那么,搜索引擎教给神经网络什么,这又如何影响网站的排名呢?

机器学习如何影响搜索引擎排名?

为了让网站排名靠前,网站所有者需要定期发布新鲜的内容。但是,有两个关键要求:

  • 内容必须相关;
  • 对用户应该也是有用的。

机器人的进步已经达到了这样一种程度,它们可以独立地决定这个副本是否对用户有用。谷歌评估员可以理解文本,并确定信息的质量。因此,写点东西,仅仅用关键词填充文字已经不够了。文章包含的信息要有用,主题要充分公开。

SEO 的主要原则是优化一个网站,不仅是为了搜索机器人的需求,也是为了给用户提供重要的信息。谷歌还衡量用户体验,并可以确定网站上的内容是否会激励用户与公司互动。

基于 ML 的算法不断接收新的数据进行分析,并学会从表面上破译查询并理解它们。得益于此,谷歌为用户提供了更好、更有趣的内容,从而保持了用户对搜索引擎本身的兴趣。所以谷歌机器学习会不断进化,对内容的要求会越来越高。

如果一个网站上的内容能让用户获得积极的体验,那么这样的网站就更容易进入 SERP 的前 10 名。人工智能越来越有效,每天都在学习越来越深入地分析文本。

基于神经网络的谷歌算法

分析站点的主要工具之一是神经网络。神经网络的原理操作类似于人脑中神经元的操作原理。由于某些算法,神经网络分析内容并给出自己的评估。这些技术极大地提高了搜索引擎机器人和内容分析的质量。

谷歌神经网络的确切算法没有公开,是公司机密。尽管如此,该公司的员工会定期在博客上发布更新,并为用户提供优化网站的建议。谷歌的算法体系统称为核心算法。这个系统包括几十种附加算法。以下是其中一些的简要概述。

  1. 熊猫。该算法是目前运行的最古老的算法之一,它于 2011 年推出。熊猫算法是为了识别低质量的内容、重复和非原创文本而创建的。
  2. 企鹅是一种更新的算法,专门用来处理低质量的链接。如果一家公司在昏暗的平台或链接交换上发布到其网站的反向链接,就有被企鹅算法惩罚的风险。为了不遇到此类问题,建议定期监控指向网站的链接。如果有所谓的“垃圾”链接,最好尽快删除。为此使用否认工具
  3. 蜂鸟。这种算法由谷歌在 2013 年推出,具有确定内容质量和意义的重要功能。在蜂鸟开发之前,搜索机器人只能识别文本的语义部分,优化只针对关键词就足够了。Hummingbird 分析整个文本,并为用户提供页面,即使用户在搜索栏中输入的不是逐字查询。如果内容能对读者有帮助,蜂鸟会建议。
  4. RankBrain 。它是一个独特的谷歌系统,结合了人工智能和机器学习。RankBrain 自 2015 年开始运营,旨在将特定网站上的文本与 SERP 中其他网站的内容进行比较。基于比较结果,谷歌决定应该向用户显示什么信息。RankBrain 还考虑了其他用户的行为,这也有助于确定内容的有用性和相关性。
  5. 负鼠。该算法于 2016 年推出,旨在区分一般查询和区域查询。该算法的主要任务是从搜索结果中删除具有相同地址、电话号码和其他联系人的公司。同时增加有本地地址和联系方式的公司排名。

基于机器学习的新 BERT 和 SMITH 算法

新的 BERT 算法是专门为基于神经网络的内容分析而设计的。它通过处理内容的意义和质量而不是关键字来增加结果的相关性。

当前的算法直接对关键字或短语进行分析,这允许它们选择相关的结果。伯特是一个完全不同的概念。谷歌专家的任务是教会算法评估查询,不是字面上的,而是确定其本质。为此,分析将不仅用于关键词,还用于其他词,包括定义和介词。因此,BERT 旨在从搜索结果中排除不符合查询本质的内容。

该算法于 2019 年 10 月公布,但到目前为止,尚未在最终版本中推出。谷歌继续开发该算法。该算法在长搜索查询上进行测试,这些长搜索查询不能被分成块来丢失短语的含义。在处理短查询时,不使用 BERT,包括那些带有品牌名称的查询。未来,谷歌计划将这种算法用于世界上大多数语言。迄今为止,谷歌尚未正式宣布确切的推出日期。

此外,谷歌已经公布了另一个算法,SMITH。在理解长查询和文档方面优于 BERT。SMITH 算法试图理解整个文档,而 BERT 处理单个片段。不过,谷歌开发者至今没有宣布开始使用。

如何将 ML 算法的知识用于 SEO?

那么,一个 SEO 专家应该如何处理这些信息呢?有几个简单的步骤可以提高网站的排名。

  • 改进元标签。建议不时重写,让所有元标签逻辑正确。元标签中的信息应该反映内容的核心。
  • 围绕关键词创作内容。无论如何,算法仍然会分析关键词,因此选择正确的关键词并围绕语义核心构建内容非常重要。使用现代关键词收集工具,如 SE 排名Similarweb
  • 写翔实有用的内容。用户从文章中获得的信息越多,搜索机器人在搜索结果中提升页面的几率就越高。
  • 想到可读性。尽量用清晰的语言来写。结构文本。突出重点。不要忘记链接到可以提供关于该主题的附加信息的文章。
  • 请教专家。如果任何领域的知识薄弱,请提供专家的报价。医学领域的搜索引擎对专家内容的排名尤其靠前——为此;甚至引入了额外的 E-A-T 算法

摘要

谷歌的搜索算法是一个不断发展的复杂系统。算法的使用是为了在搜索结果中只留下完全符合用户预期的高质量内容。我们可以预期,很快会有更多基于神经网络的算法出现。所以,如果程序员做个人网站的 SEO,不如重建策略,在竞争中领先一步。

机器学习与慈善捐赠:案例研究

原文:https://towardsdatascience.com/machine-learning-and-charity-donations-a-case-study-ed6e63f18db7?source=collection_archive---------18-----------------------

关于 Yemego NGO 如何使用机器学习技术来改善捐赠的深入方法

图片鸣谢:Katt Yukawa 不溅

为了这个项目的目的,我使用了两种有监督的机器学习方法。我比较了几种分类和回归模型,看它们能够在多大程度上识别未来的捐赠者,并估计他们将捐赠多少。这些模型被用来预测下次竞选的结果。

商业理解

Yemego NGO 是一个虚构的慈善组织,为患有脊髓损伤或疾病的退伍军人提供项目和服务。直接邮寄活动被用来为慈善组织筹集资金。利用以前的邮寄活动,慈善组织可以联系过去捐款的人。

这里的挑战是从以前的捐赠历史中吸取经验并做出预测。通过预测谁将捐款和估计捐款人将捐款多少,我们可以帮助节省为照顾弱势群体的实际工作所需的资源。降低 Yemego 成本的一个方法是通过确定最有可能向该组织捐赠的捐赠者来提高捐赠者外联的效率。由于邮寄每个活动捐助者的费用为 5 美元,该项目旨在根据过去的响应数据,只锁定最有可能的潜在捐助者,从而为 Yemego NGO 节省时间和金钱。

数据

本项目中使用的数据集是最初在 KDD 杯’98 比赛中提供的数据的子集。它包含训练和测试数据集。训练数据集包含 19,000 多条记录和 50 个分类、有序和定量变量,而测试数据集包含 2,000 多条记录和 48 个分类、有序或定量变量。此外,数据集包含两个目标变量,一个二进制变量指示一个人是否捐赠(Target_B),另一个是此人作为对活动的响应而向慈善机构捐赠的金额(Target_D)。这些变量可以用来建立一个模型,以预测捐赠者是否会向慈善组织捐赠,并估计捐赠者会捐赠多少。

数据预处理

我总是从查看数据开始。基本上就是寻找观察总数,特征总数,缺失值,哪些特征应该编码,哪些特征有杂数据等。为了便于分析,我将 Target_B 重命名为 Donated,将 Target_D 重命名为 Amount_donated。

看着训练数据集,我试图解决每个变量,我做了一些观察。在训练和测试中,捐献者年龄、收入组、财富等级和自上次响应以来的月份有缺失值。

捐献者年龄变量的最小年龄为 0,我认为这是不正确的。所以我把 0 岁换成了 nan。在绘制捐献者年龄变量时,我观察到数据是左偏的。所以我用中间值来填补缺失值。

收入群体是绝对的,而且分布均匀。因此,我使用模式来填充缺失的值。

财富评级变量是绝对的。然而,在绘制变量时,我观察到它是左偏的。所以我用中间值来填补缺失值。

自上次回应以来的几个月是左倾的。因此,我使用中间值来填充缺失值。

杂项数据

覆盖变量意味着从数据字典中取 3 个值;M=Metromail,P=Polk,B =两者都有。但是它需要 4 个值,第 4 个值是“N”,我认为这是一个错误,用值 m 代替了 N。

群代码变量具有带“.”的值。这将被替换为扩展群代码并赋予其值 54。

捐献者性别有 4 个值——男性、女性、未知和 A。我假设 A 值是错误的,因为它只有一个值。因此,这将被替换为一个未知值。

"?"代表未知。无论在哪里发现它,它都将被替换为“未知”值。

数据可视化

显然有必要对原始数据集进行预处理,因为它包含缺失值和杂项数据。在处理可视化时,我总是喜欢将变量分为分类变量和数字变量。这有助于分析和可视化过程。

理想的做法是向所有愿意响应的人发送募捐信息,但是以更有可能捐款的人为目标是有用的。这可能有助于锁定与捐献者具有相似特征的新的可能捐献者。

以下是一些可视化:

从下面的数字中,我看到了捐赠变量。据观察,25%的以前的捐赠者进行了捐赠。

作为探索性分析的一部分,下图显示了捐赠在性别上的差异。同样,女性比其他性别群体捐赠更多。

作为探索性分析的一部分,下图显示了不同房主的捐赠情况。同样,房主比其他群体捐赠更多。

为了更深入的可视化,你可以在这里看到完整的分析

数据建模

对两个目标输出都进行了特征选择;捐赠金额和捐赠类别。在训练模型之前,我执行了数据预处理技术,例如将分类值转换为数值,移除不需要的特征,选择重要的特征,以及对数据集进行欠采样。

在我进入我为这个项目测试的不同模型之前,我将阐述如何判断一个机器学习模型的质量。当我决定一个模型的性能时,我看什么?分类问题的模型性能的三个主要度量是准确度、精确度和召回率。我关心的是确定积极的结果。用于选择最佳模型的度量是由公式真阳性/(真阳性+假阴性)给出的阳性回忆

分类模型

对于分类模型,我使用了

  • 逻辑回归
  • 决策树
  • 集成方法
  • 支持向量机(SVM)

我在清理后的供体数据上训练了上述模型。训练后,数据显示出对选择负面结果的高度倾斜,因为在训练数据中主要有负面的目标变量。这导致 0 目标值的高精度,意味着数据集有偏差。为了解决这个问题,对训练集进行了欠采样,以减少训练集中的负目标值。

图片来源—金琴科

决策树模型是最适合该问题的模型,因为它返回 0.629 的准确性分数,并且在所有其他模型中具有最高的 0.304 的召回分数。我使用欠采样数据和前 20 个重要特征来训练干净的供体数据,以微调模型。这将模型的准确度降低到 0.528,但将阳性目标的召回率提高到 0.523。

图片来源—金琴科

模型调整

我通过使用网格搜索进一步改进了决策树模型。这个想法是对一些参数使用不同的值,如估计器的数量或学习率,以获得更好的性能指标。

图片来源—金琴科

优化的模型比未优化的模型表现得更好。准确率从 0.528 提高到 0.576,召回率从 0.523 提高到 0.535。但是,可以采取进一步的措施来提高模型的整体性能。

回归模型

在训练模型之前,我使用变异膨胀因子(VIF)来检测和处理多重共线性。VIF 分析从训练和测试数据中消除了几个特征,并建立了回归模型。

有几种方法可以评估回归模型的模型性能。我用了 R 和 RMSE。R 给出 0 和 1 之间的值。R 越高,模型越好。RMSE 是误差的均方根。RMSE 越低越好。

对于回归模型,我使用了

  • 线性回归
  • Lasso CV 回归
  • 岭 CV 回归
  • 随机森林回归量

车型评测

我称之为关键时刻。这是你知道你的模型表现如何的地方。

图片来源—金琴科

表现最好的回归模型是岭回归交叉验证模型,训练数据的 R 值为 0.466,测试数据的 R 值为 0.646。这意味着因变量(即捐赠金额)有 64%的变化,这是所选自变量可以解释的。例如,训练数据的 RMSE 值是 9.058,而测试数据的值是 7.474。

图片来源—金琴科

以下特征的存在决定了捐赠给慈善机构的金额:

上次赠与金额、最近平均赠与金额、房屋价值中值、终身最大赠与金额、终身赠与金额、百分比属性 3、百分比属性 4、终身最小赠与金额、财富评级、自起源起的月份。

总结

我做了什么?我试图帮助 Yemego 非政府组织为其即将到来的募捐活动确定其有利可图的捐助者。我得到了慈善机构以前的数据集,并设置了 2 个目标变量。对最有可能捐赠的用户进行分类,并估算捐赠金额。我清理了数据,将必要的变量标准化并转换成数字特征,以建立预测模型。我将我们的数据分成训练集和测试集。我使用了两种受监督的机器学习方法、分类和回归模型来识别未来的捐赠者,并估计他们将捐赠多少。这些模型被用来预测下次竞选的结果。

未来工作

在未来,探索其他模型将是有趣的,例如用于特征选择的单变量卡方方法。可以实现 Smote 上采样方法,并将其与当前结果进行比较,smote 上采样方法在上采样期间干扰了一些特征

脚注

你可以在我的 Github 库这里找到这个项目使用的脚本!这些脚本在。ipynb 文件,所以你必须使用 Jupyter Notebook 或 Google Colab 打开它们。此外,如果你想讨论我的任何项目和其他研究想法,可以在 TwitterLinkedIn 上联系我。下次再见!

基于 LDA 主题建模的人脸识别专利分析

原文:https://towardsdatascience.com/machine-learning-and-nlp-topic-modeling-with-lda-via-python-9ded3ccc963b?source=collection_archive---------31-----------------------

使用 Python 将机器学习应用于文本数据

弗拉多·帕诺维奇在 Unsplash 上拍摄的照片

介绍

作为一名数据科学家,文本数据提出了一个独特的挑战:虽然金融、年龄和温度数据可以立即注入线性回归,但单词和语言本身对统计模型毫无意义。有人怎么能模拟或分析一系列随机的、无意义的字母呢?大体上,这种类型的工作属于自然语言处理(NLP)的范畴,这是一项跨越多个领域的研究——计算机科学、语言学、人工智能,当然还有数据科学。

然而,对模型来说,重要的是模式,特别是文本数据语料库中单词的排列。使用机器学习的主题建模的统计方法使用这些模式来识别文本数据语料库中单词之间的关系。然后,它基于“主题”描述语料库,主题是模型推断属于一起的单词组。

在这篇文章中,我将解释主题模型如何使用一种叫做潜在狄利克雷分配(LDA)的机器学习方法来识别这些关系,这种方法比它的名字简单得多。然后,我将在从德温特创新索引数据库中提取的一些示例专利数据上实现这种方法,我通过克莱尔蒙特学院图书馆访问该数据库。最后,我将对模型的结果进行趋势分析并将其可视化。这个演示将使用 Python 来实现,并将在很大程度上依赖于 GensimPandas自然语言工具包 Python 库。

了解了使用 LDA 进行主题建模之后,您将能够对各种文本数据进行建模——Tweets、研究或专利摘要、报纸文章或任何其他文本数据语料库。

基于潜在狄利克雷分配的主题建模

主题建模是如何工作的?它使用了一种叫做“潜在狄利克雷分配”的机器学习方法虽然这种方法听起来令人生畏,但它实际上被它的标题描述得很好:

  • 潜在的:这意味着隐藏或未被发现。我们假设主题潜在地存在于语料库中,我们只是发现它们。
  • 狄利克雷:你可能在高中的统计中见过这个术语,特别是狄利克雷分布。狄利克雷分布是有限数量事件的概率分布

到这样的程度

每个事件 E 都有自己的概率 P,这些概率的总和总是 1。

  • 分配:在主题建模中,我们为多种目的分配狄利克雷分布。我们将一个分配给语料库中的主题分布。此外,我们对每个主题进行分布,每个分布代表该主题中单词的分布。在前一种分布中,事件是主题;在后者中,事件是主题中的单词。

既然您对 LDA 有了一个概念,我们就可以讨论它的实现了。对于 Gensim 的 LDAMulticore 方法,我们指定了我们想要发现的主题的数量。每个主题的狄利克雷概率分布被随机初始化,并且当模型通过语料库时,每个分布中的单词的概率被调整。在这种情况下,模型将传递数据五十次。关于 LDA 的更长的解释,我推荐 Thushan Ganegedara 的《LDA 直观指南》。这和这篇文章的水平差不多,但是有更深入的数学细节。

在专利数据上实现主题建模

让我们看一个真实数据集上主题建模的实现。在这种情况下,我想分析一下成千上万的专利摘要关于一项具体的新兴技术:面部识别。自 1990 年以来,我从世界各地收集了近 3500 份专利摘要。然而,快速的探索性数据分析显示,超过 65%的摘要发生在 2016 年至 2020 年,这是有道理的,基于近年来面部识别应用的爆炸式增长。该 EDA 还显示近 80%的摘要来自美国和中国,两者几乎平分秋色。代码和数据在本文末尾有链接。

拉取数据

对于我的实现,我为技术专利的摘要建模。我从德温特创新指数数据库中提取了这些数据,特别是使用搜索术语“面部识别”。除了专利申请的日期和专利的来源国,我还对构成我的文本语料库的摘要感兴趣。日期和国家不是用于主题建模过程,而是用于我对主题模型结果进行的趋势分析。

一旦我们有了数据,我们想要导入我们的包。

数据清理和预处理

一如既往,第一步是清理数据集。首先,因为原始数据集中没有“国家”列,所以我解析了以国家代码开头的专利号。接下来,我删除了在我的三列中任何一列中有缺失数据的文档。

与所有文本相关的数据分析一样,第二步是预处理。关于文本预处理的全面介绍,我在这里推荐我的教程。总结一下这个过程,我们从一个由文本字符串组成的数据集开始,其中充满了标点符号和数字。我们希望对这些数据进行预处理,使语料库中的每个文档都是文档的基本部分——词干化、词汇化、小写、有用的单词。这个过程可以概括为五个步骤:

  1. 我们去掉标点和数字。我们把所有的单词都变成小写。
  2. 我们将每个文档从一个字符串分解成一个单词列表。列表中的每一项都称为“令牌”。
  3. 我们过滤掉停用词(介词、冠词等)。).我们过滤掉短词。
  4. 我们将单词简化到它们的词根(例如,“runner”和“running”都变成了“run”)——这个过程叫做词干提取。我们对动词也做同样的事情,这个过程叫做词汇化。
  5. 我们过滤掉原始的数据库搜索词(在我的例子中是“面部”和“识别”)。

语料库中的每个文档现在都是小写的带词干的标记列表。

袋字

在对文本数据建模时,从某种意义上说,开始使用数字而不是文字是有利的。第一步是为出现在整个语料库中的每个唯一标记编译一个字典,并为每个唯一标记编制索引——这是使用 Gensim 的字典模块完成的。我们还过滤掉非常常见或非常罕见的单词——想法是超级常见的单词(出现在超过 40%的语料库中)对每个文档提供的洞察很少,而非常罕见的单词(出现在近 3500 个文档中的不到 15 个)太罕见了,以至于不能出现在一个主题中。然后,我们保留剩余的 100,000 个最常用的令牌。使用这个字典,每个文档都从标记列表转换为出现在文档中的唯一标记列表以及它们在文档中的频率。语料库的这种表示被称为单词袋。

词频-逆文档频率(tf-idf)

编译我们的模型之前的最后一步是调整词袋的频率测量。虽然频率当然是特定单词在文本语料库中的重要性的度量,但我们假设出现在更多文档中的单词不太有趣。例如,如果我们没有过滤掉“面部”和“识别”这两个术语,它们可能会在我们的语料库中出现很高比例的文档。尽管它们对语料库显然很重要,但它们很少提供我们最感兴趣的语料库中的变化和模式。

出于这个原因,我们没有简单地使用词频来衡量每个词的重要性,而是使用了一种称为“词频-逆文档频率”(tf-idf)的衡量方法。顾名思义,tf-idf 对基本术语频率度量的唯一修改是,当一个单词出现在一个文档中时,它在该文档中的频率除以它在整个语料库中出现的文档数。这导致出现在数千个文档中的单词不如只出现在数百个文档中的单词重要。

利用潜在狄利克雷分配的主题建模

我们现在的目标是研究单词如何在 tf-idf 单词语料库中彼此相关地出现,以辨别“主题”,这些主题只是模型认为可以放在一起的一组单词。我之前解释过,这些主题潜在地存在于语料库中——在这个例子中,我们假设(并希望)我们发现的主题反映了更大的面部识别领域中更微妙的技术领域。

我们使用 Gensim 的 LDAMulticore 模型将我们的 tf-idf 单词语料库放入 LDA 主题模型中。例如,该模型返回从面部识别数据中识别的最受欢迎的主题 LDAMulticore 模型,该主题由“authent、data、inform、biometr、mobil、content、person、comput、video、access”组成(这些单词看起来被截断了,因为它们是词干化和词条化的版本)。这个主题似乎与使用面部识别的生物认证有关。

基于话题的语料库趋势分析

我们已经使用 Gensim 的 LDAMulticore 模型成功地创建了语料库的主题模型。现在,让我们根据这个模型对我们的语料库进行一些有趣的了解。

通过识别一段时间内每个主题在多少文档中出现,我们可以根据其在专利中的受欢迎程度对每个主题进行排名,并跟踪这种受欢迎程度如何随时间变化。这让我们了解了面部识别技术的哪些领域(基于每个主题中的单词)在过去二十年中得到了发展。使用 seaborn 的 catplot,我们可以将这一技术发展可视化。

从 2009 年到 2018 年,最受欢迎的话题(蓝色)似乎与生物认证有关。这并不完全清楚,所以我们可以抽样调查由这个主题构成的前五个专利摘要,以让我们更好地了解这个主题涉及的技术类型。

所讨论主题的专利摘要示例。

正如所料,该专利摘要似乎涉及用于认证目的的面部识别,但也用于识别——可能是罪犯或受伤的受害者。然而,在 2003 年到 2009 年,另一个话题(橙色),似乎与摄影中的面部检测有关,却相当流行。2017 年以来,一个不一样的话题(绿色)迅速上升。从文字上看并不完全清楚,但看看这个主题的专利就会发现,它与具有面部识别功能的安装式安全摄像头有关。

比较国家

让我们再做一项分析:2009 年以来美国和中国的比较。

美国的面部识别专利显然主要集中在生物认证上,其次才是摄影。这些年来,所有的话题基本保持稳定,尽管最近安全摄像机和家庭安全系统似乎都呈上升趋势。

另一方面,自 2009 年以来,中国的面部识别专利极其不稳定。虽然生物认证一直处于最重要的地位,但也有一些挑战,包括家庭安全系统、摄影以及最近的安全摄像头。

随着进一步的研究,对美国和中国面部识别专利的比较分析可能会得出有趣的结论,即这两个国家的技术发展如何不同以及为什么不同。

结论

主题建模是处理大量文本数据的一种很好的自然语言处理方法。潜在狄利克雷分配是一种强大而又可解释的机器学习方法。LDA 的简单和优雅是数据科学家的福音,他们经常要向同事和主管解释他们的方法。LDA 提供了简单和强大的完美结合。

虽然我用专利数据演示了一个实现,但同样的方法也可以应用于许多其他文本数据集,从研究论文摘要到报纸文章或推文。

密码

一旦我从科学网上获取了数据,我就使用这个代码将这些文件合并成一个数据集。

我用于预处理、建模和趋势分析的完整 Jupyter 笔记本位于这里

包含所有代码文件、我的数据和一个 README.md 的 repo 位于这里

资源

使用的主要软件包:

延伸阅读:

https://en.wikipedia.org/wiki/Latent_Dirichlet_allocation

使用你自己的 Spotify 数据的机器学习和推荐系统

原文:https://towardsdatascience.com/machine-learning-and-recommender-systems-using-your-own-spotify-data-4918d80632e3?source=collection_archive---------6-----------------------

利用数据科学创建 Spotify 推荐

此项目的结果播放列表。(作者截图)

介绍

作为一个每天都在使用 Spotify 的人,我对我可以用自己的音乐数据做什么分析很感兴趣。Spotify 在通过每日混音和音轨广播推荐音轨方面做得很好,但我们自己如何构建这样的东西呢?这里的目的是使用机器学习和推荐系统技术,根据我最喜欢的播放列表中的曲目推荐新曲目。

本文对该项目进行了更高层次的概述。代码和结果可以在 GitHub 这里 找到。

Spotify 数据

任何好的数据科学项目首先需要数据,而且是大量的数据。

访问 Spotify API

用于设置项目的仪表板页面。(截图图片作者)

为了开始使用我们的音乐数据,我们首先需要访问 Spotify API:

  1. 为开发者创建一个Spotify账户
  2. 从仪表板设置一个项目(API 访问需要)
  3. 检索客户端 ID、客户端密码,并设置重定向 URI(作为一个本地项目,我将其设置为http://localhost:9001/callback)
  4. 查看 API 文件

音乐数据

一旦开发者帐户被设置,我们就可以访问 API 来获取音乐数据。为此,我们可以使用 spotipy Python 包,这需要我们之前设置的开发人员详细信息,以便通过 OAuth 授予权限。

with open("spotify/spotify_details.yml", 'r') as stream:  
    spotify_details = yaml.safe_load(stream)# [https://developer.spotify.com/web-api/using-scopes/](https://developer.spotify.com/web-api/using-scopes/)
scope = "user-library-read user-follow-read user-top-read playlist-read-private" sp = spotipy.Spotify(auth_manager=SpotifyOAuth(
    client_id=spotify_details['client_id'],
    client_secret=spotify_details['client_secret'],
    redirect_uri=spotify_details['redirect_uri'],    
    scope=scope,)
)

我们现在可以从 Spotify 库中的各种来源提取数据。sp类具有覆盖这一点的函数,如sp.current_user_playlists()sp.current_user_top_tracks()。从这些 API 调用中,我们需要提取曲目的详细信息,如唯一 id、名称、持续时间和流派,以及相关的艺术家、专辑和播放列表属性。为了便于分析,我把这些保存为熊猫数据帧。

Spotify 还可以为一首曲目提供音频功能。这些是数值(通常在 0 和 1 之间归一化),对分析很有用,但特别是作为传统机器学习方法的特征。

一个有用的音轨和音频功能的例子。

推荐系统

机器学习

有了上面的表格数据集,通过从 1 到 10 对训练集中的歌曲进行评级,可以相当直接地将其表述为一个经典的回归问题,或者通过尝试推荐与我们最喜欢的歌曲相似的歌曲作为一个分类问题(如果您有一个最喜欢的歌曲的播放列表,这是一个相当简单的方法)。记住从训练和测试数据集中删除重复的轨迹 id,以避免数据泄漏!

XGBoost 和 RandomForest 分类器在我这里表现不错https://github.com/anthonyli358/spotify-recommender-systems/blob/main/recommender_playlists.ipynb

然而,上述方法严重依赖于特征工程和用户来提供标签。当用户有一个新帐户或者没有提供任何评级时,它遭受错误标记不准确和冷启动问题,因此经常使用推荐系统方法来代替。

人气推荐器

流行度推荐器推荐根据流行度排序的歌曲,而不考虑用户的偏好。这当然取决于用于确定流行度度量的方法(通常是时间、用户交互和用户评级的一些函数)。

Spotify 已经有了歌曲的流行度指标。

由于它没有考虑用户的活动,仅仅根据流行度来推荐歌曲是一种糟糕的方式。然而,正如我们将在后面看到的,这是一个很好的方法来混合多样性和避免冷启动问题。

基于内容的推荐系统

基于内容的推荐器利用来自用户已经交互过的项目的属性来推荐相似的项目。这里,流行的 TF-IDF 方法用于将非结构化文本(流派和歌曲/艺术家/专辑/播放列表名称的单字母组合和双字母组合)转换为稀疏矩阵。用户向量和初始矩阵(所有用户)之间的余弦相似性给出了推荐新曲目的度量。

朋克摇滚和冷酷?

那好,你六点钟来见我。

看起来流派往往是最强的内容形式,可以作为曲目推荐的基础。

协同推荐器

协作推荐器可以是基于记忆的(基于过去的用户交互)或基于模型的(例如聚类)。这里,项目×用户矩阵然后被用于基于相似用户的交互向用户推荐项目。

🎵请注意,这些是与基于内容的推荐器最相关的标记不同的类型。

如果用户集太小或交互次数太低,协作方法可能会遇到稀疏性问题。

混合推荐器

混合推荐器结合了基于内容和协作的方法,在许多研究中表现得更好。它避免了高方差,并实现了多样性和加权(例如,流派加权)。我们还可以结合流行度方法来给出混合+流行度推荐器。

我们的最终建议。

从主观上来说,这个推荐者似乎给出了实践中最好的推荐!

最终播放列表和想法

我们现在可以将我们的曲目添加到 Spotify 播放列表中进行收听!创建轨道 id 的tracks_to_add阵列,其中推荐强度高于某个值。

*# Create a new playlist for tracks to add*
new_playlist = sp.user_playlist_create(
    user=spotify_details['user'], 
    name="spotify-recommender-playlists",
    public=**False**, 
    collaborative=**False**, 
    description="Created by [https://github.com/anthonyli358/spotify-](https://github.com/anthonyli358/spotify-) recommender-systems",
)

*# Add tracks to the new playlist* **for** id **in** tracks_to_add:
    sp.user_playlist_add_tracks(user=spotify_details['user'], 
                                playlist_id=new_playlist['id'], 
                                tracks=[id],
                               )

希望播放列表是🔥。为了进一步改进这些建议,我们可以:

  • 扩展数据集以包括其他用户
  • 开发其他评估指标(这里使用了前 N 名准确性指标)

机器学习和选择架构

原文:https://towardsdatascience.com/machine-learning-and-the-architecture-of-choice-2cc69072a45b?source=collection_archive---------30-----------------------

行为经济学对评估机器学习如何让我们做出决策的贡献

照片由布伦丹·丘奇Unsplash 上拍摄

人工智能(AI)已经说服我们甚至不用质疑就能做出决定。当我们选择一部推荐的电影或去你家的最佳路线时,就会发生这种情况。这些是她能做什么的好例子。尽管如此,人工智能可以说服我们选择高利率贷款的金融交易。此外,即使你有很好的资历和经验,你也可能因为失业期间没有支付账单而失去工作机会。

也许你认为这是最好的选择,因为你相信机器是公正的,不会出错。这些决定是通过应用我们的数据做出的,这些数据被聚合到许多其他人的数据中,对我们进行分类。但问题是,人工智能是否真的向我们展示了可以用道德方式做出的最佳选择。这个关于人工智能滥用的问题是由凯茜·奥尼尔在她的书中提出的,她用真实经历的例子进行了论证。

有了大数据,人工智能正在成为一个大规模的选择建筑师,让人们相信什么对他们是坏的或好的。选择架构是行为经济学的一个概念,由卡斯·桑斯坦和理查德·塞勒在他们的书中提出。他们提出的理论认为,决策过程受到选项显示方式的影响。当您交替使用这些选项来影响某些行为时,会发生轻推。这种交替基于自由家长主义,这意味着以更好的方式影响行为是可能的和合法的,同时也尊重选择的自由。但是,我们往往不知道用的是什么数据或者算法。

机器影响我们行为的能力取决于它说服我们的能力。根据b . j . Fogg【3】的说法,说服性技术应用社会心理学原理来影响人们,即:

吸引力:对目标用户有视觉吸引力的计算技术也可能更有说服力。

相似性:人们更容易被在某些方面与自己相似的计算技术产品所说服。

赞美:通过文字、图像、符号或声音来提供赞美,计算机技术可以让用户更容易接受劝说。

互惠:当计算技术帮了他们一个忙时,人们会觉得有必要回报。

权威:承担权威角色的计算技术将增强说服力。

基于我们的数据,AI 有能力根据这些原则中的每一条来调整呈现给我们的内容。因此,对所有类型的人的行为进行个性化呈现,创造人工智能认为对我们最好的泡泡。因此,人工智能是一个强大的说服机器,能够影响尽可能多的人。

人工智能可能会在无意中以某种方式推动我们的社会现状。你可能认为 AI 是公平的,没有偏见的,然而,它从人类制造的数据中学习。有几次,机器学习算法重复了人类制造的偏见和不公正

根据 Vincent C. Müller 的说法,我们需要机器伦理,这意味着“对人类的行为应该是伦理上可接受的”[4]。什么会导致“人造道德代理人”的存在[5],拥有权利和责任。基于这一原则,可以说人工智能的架构选择必须遵循伦理标准。

这篇文章的功能是开启一场关于人工智能选择建筑的伦理意义的讨论,这被证明是相当丰富的。

参考

[1]奥尼尔。数学毁灭武器:大数据如何增加不平等和威胁(2016)。https://www . Amazon . com/Weapons-Math-Destruction-Increases-Inequality/DP/0553418815

[2] C. Sunstein,R . Thaler,《推动:改善关于财富、财富和幸福的决定》( 2008 年)。https://www . Amazon . com/Nudge-Improving-Decisions-Health-Happiness/DP/014311526 x/ref = Sr _ 1 _ 1?dchild=1 &关键字=推动% 3A+改善+决策+关于+财富% 2C+财富+和+幸福&qid = 1621540327&s =书籍& sr=1-1

[3] B. J. Fogg,《说服技术:利用计算机改变我们的想法和行为》( 2002 年)。https://www . Amazon . com/劝诱-技术-计算机-互动-技术/dp/1558606432/ref=sr_1_1?dchild=1 &关键词=说服+技术% 3A+使用+电脑+改变+什么+我们+想+做&qid = 1621540428&s =书籍& sr=1-1

[4] M. Anderson,S. L. Anderson,《机器伦理:创造一个有道德的智能主体》(2007)。https://ojs . aaai . org//index . PHP/aimagazine/article/view/2065/0

[5] V. C. Müller,《人工智能和机器人学的伦理学》,斯坦福哲学百科全书(2020)。https://plato.stanford.edu/entries/ethics-ai/

机器学习和披头士

原文:https://towardsdatascience.com/machine-learning-and-the-beatles-1fe5ca036871?source=collection_archive---------28-----------------------

使用 NLTK 和 GPT-2 分析和生成披头士歌词

图片来自Pixy.org

介绍🌅

对于我在 Metis 的最后一个项目,我决定将我对音乐和数据科学的热情结合到一个项目中,这个项目涉及有史以来最好的乐队。整个项目涉及使用 NLTK 库的自然语言处理(NLP),通过将迁移学习应用于 OpenAI 的 GPT-2 模型的文本生成,以及使用 Steamlit 构建的应用程序。我使用的数据是来自 Genius.com Bealtes 唱片公司的歌词和来自网络的关于谁演唱和创作了每首歌曲的补充数据。在这篇博文中,我将讨论以下话题:

背景🎵

起初我认为这个想法很新颖,使用 NLP 来更深入地研究披头士的目录,但谷歌搜索让我知道有多少人已经探索了这个话题。为了使我的项目多样化,我制作了一个应用程序,允许用户选择歌词生成基于哪个披头士。此外,我确保包括一些见解背后的每个披头士和什么使他们的歌曲独一无二。

数据收集:lyricsgenius API📝

首先,我想提一下,Genius.com 有自己的 API,但是我发现它很难用于我的目的。它需要你搜索的特定 ID 的知识(艺术家 ID,专辑 ID,歌曲 ID)。当我开始在 Genius.com 的 HTML 脚本中查找与甲壳虫乐队作品相对应的 id 时,我心想,“一定有更简单的方法。”在寻找替代方法时,我发现了 lyricsgenius API。

lyricsgenius API 是一个使用起来相当简单的 API,基本上是 Genius.com API 的包装器,但在搜索没有 ID 信息的歌词时允许更大的灵活性。相应地,你必须从 Genius 那里获得一个 API 密匙来输入 lyricsgenius,这样 API 才能正常工作。

为了向您展示使用起来有多简单,让我们快速看一下我的代码:

*import* lyricsgeniusgenius = lyricsgenius.Genius("[YOUR KEY HERE]")

上面的代码概述了基本的设置:首先,导入 lyricsgenius 其次,将 Genius API 键输入 lyricsgenius API,并赋给 Genius 变量。现在,我们准备好了一些歌词!

# Save the album titles to a listalbum_titles = [
   'Please Please Me',
   'With the Beatles',
   "A Hard Day's Night (US)",
   'Beatles for Sale',
   'Help!',
   'Rubber Soul',
   'Revolver',
   "Sgt. Pepper's Lonely Hearts Club Band",
   'Magical Mystery Tour',
   'The Beatles (The White Album)',
   'Yellow Submarine',
   'Abbey Road',
   'Let It Be'
]*# Create a for loop to run through the list of album titles**for* albums *in* album_titles:
   album = genius.search_album(albums, "The Beatles")
   album.save_lyrics()

当计算机运行 for 循环时,album.save_lyrics()方法会自动将相册的所有元数据保存到当前目录下的. json 文件中。

顺便提一下,genius.search_album()方法并不是万无一失的。例如,我必须手动找到“佩珀中士的孤独之心俱乐部乐队”的专辑 ID,并显式地插入它以获得正确的信息。

album = genius.search_album(*album_id*=11039, *artist*="The Beatles")
album.save_lyrics()*# Used the Genius API to find the album id for Sgt. Pepper's Lonely Hearts Club Band*

包含专辑信息的 json 文件非常密集。出于我的目的,我构建了一个函数来获取每个 json 文件,清理歌词,并只将我想要的信息放入数据帧中,以便于使用。

获取作曲家信息并不有趣。使用 Pandas,我将包含该信息的网页读取到数据帧中,重新构建该数据帧以更相似地匹配包含更深入歌曲信息的数据帧,然后将歌曲标题上的两个数据帧连接起来。像往常一样,有一些必要的数据清理。

NLP:管道和主题建模🥁

在我的前一篇博文中,我提到了 NLP 过程的基本元素(记号化、词干化、矢量化)。我不会太深入,但我为这个项目做了一个非常相似的过程。首先,我创建了一个 NLP 管道来获取所有文档,并对它们进行清理、词干提取、标记化和矢量化。这使得调整 NLP 过程的特定元素来比较您的结果变得非常容易。

在这种情况下,我想在披头士的文集里发掘主题。同样,与我之前的 NLP 项目非常相似,我参与了创建主题、分析这些主题以及操纵 NLP 管道以提取实际有意义的主题的试错过程。有了披头士的文件,我发现了五个一般的主题来将歌曲分类:欲望、现实、关系、家庭和乐趣。

以下是一些例子:

**Desire: I Need You – *Help!*** If you can’t see it in the title, it’s all about the narrator needing the subject back in their life**Reality: Drive My Car – *Rubber Soul*** 'Drive my car', 'Working for peanuts' (metaphor, but also talking about life being hard, working for a living, but wanting to be famous)**Relationships: Girl – *Rubber Soul*** All about a girl, how she came into the narrator’s life and was strong women, but the song is about the narrator still falling for her**Home: Golden Slumbers – *Abbey Road*** A song McCartney wrote at home after his mother passed away is all about the concept of home and sleep**Fun: Your Mother Should Know – *Magical Mystery Tour*** A song about hit songs across generations, talking about singing and dancing

自然语言处理:情感分析🎸

对于情感分析,我使用 NLTK VADER 情感强度分析仪。在这个模块中,我使用了polarity_scores()方法,该方法返回四个度量标准:复合、负面、中性和正面。复合测量是在-1(负面情绪)到+1(正面情绪)的范围内测量的,0 是中性情绪,因此将其他三个测量组合成一个度量。利用复合情感测量,人们可以容易地将情感可视化。

作者图片

上图显示了按歌手分组的每张专辑的平均情绪,每条虚线代表一张专辑的发行。

实现 VADER 情绪分析是非常容易的,但是,我对它背后的细节的了解是相当有限的。为了更深入地分析 VADER 情绪,我推荐这个博客

文本生成:GPT-2 ⌨️

现在来看文本生成。首先,不要被文本生成的实现吓倒,因为 GPT-2 不能使生成令人信服的文本变得更容易。GPT-2 本身可以做许多不同的事情,但当具体谈到文本生成时,它有几个简单的步骤可以遵循。我用 Max Woolf 的这个 Google Colab 笔记本成功运行了我的第一次迭代,我建议你也这样做。

GPT-2 本身有几个不同大小的预训练模型:

  • 小型— 124M 参数/ ~500MB
  • 中等— 355M 参数/ ~1.5GB
  • 大型— 774M 参数/ ~3GB
  • XL — 1.5B 参数/ >5GB

这就是谷歌 Colab 笔记本真正派上用场的地方。除非你运行的是 GPU,否则你的本地机器不太可能击败哪怕是最低计算能力的谷歌 Colab 笔记本的资源。因此,我建议浏览一下我在上一段中发布的 Google Colab 笔记本。

不管怎样,GPT-2 是什么?它是一个预训练的模型(创成式预训练变压器 2 是全称),使用深度学习来做许多 NLP 类型的过程。从头开始创建一个神经网络需要大量的数据、时间和计算资源,因此访问 GPT-2 是一种快速有效地解决 NLP 任务的非常显著的方式。这种根据个人需求定制预先训练好的模型的能力被称为迁移学习。关于文本生成,GPT-2 已经准备好生成文本,但是你可以输入一个特定的语料库让它关注,从而生成与我们的语料库更加相似的文本。

关于生成披头士的歌词,我只是输入了语料库,并让模型从披头士那里学习来创作歌曲。现在,GPT-2 非常聪明,所以它会捕捉歌词中的细微差别,如章节标签(“合唱”、“韵文”等)。)或者歌手('哈里森','列侬'等。).考虑到这一点,调整您的输入以获得您想要的输出是非常重要的。俗话说,“垃圾进,垃圾出”。

App Building: Streamlit 🕸

我无法告诉你我有多喜欢。这是一种构建 web 应用程序甚至创建仪表板的简单方法。Streamlit 对初学编程的人来说尤其有用,很容易花不到一个小时的时间就能学会一些基本的东西。也就是说,定制是有限的,我不得不使用 HTML 和 CSS 来修改页面,使它看起来像我想要的那样。

至于代码,我不会深入到每个方面,但有些事情我想指出来。

创建左侧的侧边栏就像下面的代码一样简单。在我的最终代码中还有一些导入,但是你只需要导入 Streamlit 来做你的基本应用开发。此外,可以将 selectbox 方法保存到变量中,以便将来对应用程序进行更改。在这种情况下,当您选择不同的歌手时,页面的布局会发生变化,并为该特定歌手加载相应的 GPT-2 模型。

*# Import streamlit
import* streamlit *as* st*# Select who will generate the song*singer = st.sidebar.selectbox(
 "Who is singing the song?",
  ("The Beatles",
   "John Lennon",
   "Paul McCartney",
   "George Harrison",
   "Ringo Starr",)
,)

我想说的唯一其他代码是关于格式的。Streamlit 允许您很好地定制页面,但我无法找到一个内置的解决方案来使用页面上的图像,所以我搜索并发现 markdown 单元格中的 HTML 可以完成这项工作。我相信 Streamlit 最终会解决这个问题,但是现在,这是唯一的方法。

*# Set background image* st.markdown(
  """
  <style>
  .reportview-container {
    background: url("[IMAGE URL]");
    background-position: right;
    background-size: cover;
    background-repeat: no-repeat;
    background-blend-mode: lighten
  }
  </style>
  """,
  *unsafe_allow_html*=True,
) 

在 python 文件中,我添加了很多有趣的东西来让这个应用程序工作。本质上,用户选择歌曲的歌手,应用程序选择对应于该歌手的经过训练的 GPT-2 模型(已经根据个人演唱的歌曲的歌词进行了训练)。接下来,您输入一个提示并单击 generate,剩下的工作由 GPT-2 完成。

不幸的是,应用程序需要一点时间来发送输出,所以肯定有改进的空间,但我喜欢它的结局。

结论:📙

作为一名有抱负的数据科学家,我希望这个项目有助于巩固我的 NLP 知识,并获得一些关于神经网络和文本生成的经验。在某种程度上,GPT-2 对我来说太容易实现了,所以我不能自信地说我知道如何使用神经网络。然而,与 GPT-2 合作的过程让我明白了神经网络可以有多强大。

至于文本生成,NLTK 是一个非常容易使用的库,一旦你创建了一个基本的管道(随意窃取我的 repo(Metis 为我提供的)中的那个管道),你就可以将这个管道应用到你未来的任何 NLP 项目中。就我个人而言,我建议学习更多的 NLP 库(我也这样告诉自己), spaCy 似乎在组织中特别受欢迎。

以下是一些基本要点:

  • 如果你遇到困难,寻求帮助(我总能找到一个让我的项目运行更顺畅的包)
  • 构建一个管道(特别是当你通过试错法进行测试的时候)
  • Streamlit 让创建应用变得简单
  • 玩得开心!

查看 Github 库以获得关于该项目的更多信息。这不是我最干净的回购,但我会尝试清理它,以便更好地理解。此外,如果您有任何问题或意见,请联系我们。

由于这是我在 Metis 的最后一个项目,我对在这个项目中的 12 周所学到的一切感到无比惊讶。显然,这是一个很大的信息量,所以我目前正在深入研究所有的主题,以便更好地理解整个数据科学工具包。无论如何,我已经在媒体上写了其他三个项目,所以如果你想看我的其他作品,就去看看吧。

伸出手:
LinkedIn|Twitter

机器学习代码再现性

原文:https://towardsdatascience.com/machine-learning-code-reproducibility-using-versioning-9a7ec373173a?source=collection_archive---------44-----------------------

机器学习系统基于 3 个主要部分:数据、代码和模型。这三个组成部分在许多方面是相互关联的,使用依赖控制系统,我们可以最终实现再现性。这个因素非常关键,因为它是在生产中管理 ML 解决方案的主要驱动因素之一。

詹姆斯·萨顿Unsplash 上拍摄的照片

通常,软件依赖和版本控制是艰难而乏味的过程。但是同样地,这些类型的过程是自动化的理想目标。在深入实施之前,让我们回顾一下与这些流程交互的关键角色:

版本模式

目前,大多数 Linux 发行包都使用一种模式,称为语义版本。另一方面,我们有 Python 来增强它自己的版本控制,由 PEP 440 ( 版本识别和依赖规范)来识别。这两种模式有一些共同点,但在某些方面也有所不同。

公共版本和本地版本

如上图所示,两个模式的第一部分( public version)几乎是相同的。第二部分(本地版本)是 SEMVER 与 PEP440 的区别。每次需要计算版本之间的优先顺序时,都会评估这两个部分。

鉴于公共版本,你应该增加:

  1. 主要版本当您进行不兼容的 API 更改时(在 ML 应用程序🡒输入数据/输出响应的情况下),
  2. 以向后兼容的方式添加功能时的次要版本(在 ML 应用程序的情况下,🡒改进特征工程,改变 ML 模型等)
  3. 补丁/微版本当你做向后兼容的错误修正

本地版本用于测试尚未准备好供通用的版本(阿尔法/测试版/预发布/后发布版本、开发者版本等)。

包裹

大部分 Python 包都是用setuptools打包的。事实上,方法setup有一个version 参数,它又是一个字符串,所以它应该是版本不可知的...对吗?实际上,setuptools遵循前面提到的 PEP 440 标准,所以如果您使用语义版本化,您可能会丢失一些关于本地版本的信息。稍后当我们回顾pysemver时会有更多的介绍。**

工件储存库

该体系结构中的另一个角色是托管包并将其分发给客户机的地方。但是它也处理其他的麻烦:例如,根据客户请求的版本,存储库需要返回(在大多数情况下)最新的版本(这涉及到排序和优先权)。最常用的工件库是 PyPI ,但是在私有解决方案的情况下,您也可以使用其他的工件,比如 Azure 工件

持有国家证书的助产士

根据我们存储当前包版本的方式,我们可以考虑两种开发版本控制系统的主要策略:

  1. 第一个策略是添加一个存储软件包版本的文件。例如,python-version erbump2version 就遵循了这一策略。
  2. 第二个策略依赖于 SCM,因为您将使用 SCM 工件存储版本。例如,如果您将 GIT 用作 SCM,最普遍的做法是将版本存储为标签;通过这种方式,您可以快速地将包的版本与 git 历史日志关联起来(例如,您可以执行git checkout 0.1.3,然后签出在版本 0.1.3 中打包的代码)。在 SCMs 的其他地方,你也可以用树枝。有像 setuptools_scm 这样的工具使用这个策略。

又一个 Python 版本控制

我现在和最后要说:没有灵丹妙药。这里给出的解决方案是一个不知何故* 简单的解决方案但是足够复杂,所以你可以感觉到与为机器学习应用程序版本化 Python 代码相关的麻烦,所以希望你在实现你自己的版本控制之前测试可能的缺点。*

对于这个简单的解决方案,我将使用带有标签的 GIT,因为我不喜欢创建 bump 版本文件提交或分离提交(通常由 CI/CD 编写)。

其次,我将使用语义版本,在轻量级 python-semver 的支持下,尽管我将只使用公共版本,以保持与 PEP 440 的兼容性。在 PR ( 分支开发)期间支持本地版本控制当然很好,但是目前我会保持事情简单。

Python 将包元数据信息(即在setup函数中使用的许多参数,如versiondescription)存储在发行版本身中。我们将使用 Python 3.8 以后内置的对包元数据自省的支持,但如果你想在以前的版本中使用,可以安装包 importlib-metadata

最后,对于 GIT SCM(存储库)、CI/CD(管道)和工件存储库,我们将依赖于 Azure Devops 。或者,您也可以将 GitHub 用于 SCM 和 CI/CD ( GitHub Actions ),将 PiPy 用于工件库(至少在 GitHub 包支持 Python 之前)。

简单版本

为了这篇文章,让我们创建一个简单的 python 包(一个控制台应用程序)来执行机器学习应用程序的 ETL。在这个阶段,控制台应用程序只是输出包版本,作为我们之前解释过的元数据自省的测试。

在应用这个过程之前,需要满足一个要求:您需要推送一个初始标签(第一个版本——这是一个一次性的操作)。只要符合语义版本语法(例如:0.1.0 ),您可以随意命名这个标签

*git tag -a "0.1.0" -m "Release v. 0.1.0"
git push origin "0.1.0"*

那么,要实现上述版本控制,只需执行以下步骤:

1。检索最近的标签

*export DESCRIBE=$(git describe --always --tags --long --first-parent)
export VERSION=$(echo $DESCRIBE | cut -d "-" -f 1)*

首先,要创建一个新版本,我们需要知道当前的版本。在使用 GIT 作为 SCM 的情况下,我们将存储(当前)版本作为存储库的标签。因此,在这种情况下,[git describe](https://git-scm.com/docs/git-describe)将返回最近的标签,执行该命令的结果可能类似于0.1.27-3-ge72f11d。命令响应可以分成不同的部分,例如:

  • 0.1.27:最新标签
  • 3:在0.1.27标签后更新(提交次数)
  • e72f11d : git 提交哈希。这非常方便,因为您可以使用提交散列来检查相关的版本:

使用散列和标签的 git 检验是等价的

2。安装 **pyton-semver** **和凸起当前版本**

*pip install semver==2.13.0
export VERSION=$(pysemver bump patch $VERSION)*

python-semver 是一个透明而简单的库(从不会在源代码中引入任何新工件的意义上来说)。此外,python-semver安装pysemver命令,该命令可以从 CLI 启动。例如,下表收集了执行pysemver bump <command> <version>时返回的数据

使用 pysemver 的凹凸版本

这种方法不需要将pyton-semver作为应用程序的包依赖项,因为它只需要在 CI/CD 代理中提升当前版本(因此您不需要在您的requirements.txt中包含python-semver)。

3。使用凸起的版本*创建一个新标签*

*git tag -a "$VERSION" -m "Release v. $VERSION"
git push origin "$VERSION"*

将标签推送到存储库可以避免新提交触发任何 CI/CD 管道。

在应用方面,我们需要:

1。定义**setup.py**

*from setuptools import setup, find_packages
​
setup(name=_package_name_,
      packages=find_packages(include=["etl"]),
      version=os.getenv('VERSION','2.0.0'),
      python_requires=">=3.8")*

该方法使用之前已经设置好的环境变量作为version参数(该变量包含碰撞版本的值)。然后,您可以执行:

*python setup.py bdist_wheel*

并在dist文件夹中获得一个名为product_sales_ml_etl-0.1.2-py3-none-any.whl的文件。另外,请注意,如果您使用的是本地版本,那么版本可能会在文件名中出错。例如,在下表中,您可以观察到-rc.1 版本在文件名中被标记之前已被更改:

使用 setuptools 的包命名

这就是为什么不建议从文件名获取文件版本的原因之一,您应该尝试使用其他机制,比如包自省。

所描述的步骤可以很容易地打包到一个管道中,并由 CI/CD 执行。在前面解释的第三步中,在推送标记时,您需要授予 building service 权限来完成此类操作。按照注释的步骤从管道运行 git 命令后,我一直有一个错误声明You need the Git 'GenericContribute' permission to perform this action。如果是这种情况,我解决这个问题的方法是检查错误中返回的用户 ID,并在 Permissions 选项卡中查找这个用户 ID,如下图所示:

Azure Devops —存储库权限选项卡

对于选定的用户,您应该检查“贡献”、“创建标签”和“读取权限”。

2。检查当前版本

出于好奇,您可以检查一个名为product_sales_ml_etl.egg-info的文件夹,其中包含一个名为PKG-INFO的文件,内容与此类似:

*Metadata-Version: 2.1
Name: product-sales-ml-etl
Version: 2.0.0
Requires-Python: >=3.8*

这个文件夹也被打包到你的轮子/鸡蛋文件中,当你依次使用库importlib-metadata时,它会检查这些打包的文件:

*from functools import lru_cache
_package_name_ = "product_sales_ml_etl"
​
@lru_cache
def get_version():
    from importlib.metadata import version
    return version(_package_name_)*

最后,可以设置另一个 devops 管道任务来发布和/或使用包:

1。发布包

管道生成的 python 包可以上传到 PyPI 或任何兼容的 pip 存储库。Azure 工件库与 pip 兼容,在设置好之后,您可以使用下面的 devops 模板,该模板使用 twine 来上传包:

*- task: TwineAuthenticate@0
  inputs:
    artifactFeeds: 'productsalesml/wheel_feed'
    publishPackageMetadata: true
​
- bash: |
    pip install twine
    python -m twine upload --config-file $(PYPIRC_PATH) -r "productsalesml/wheel_feed" dist/*.whl
  displayName: Upload artifacts to feed*

在这个阶段,您开始意识到在处理版本控制时一些令人讨厌的细节:例如,在前面描述的 bash 任务中,我们使用了dist/*.whl。正如您之前所检查的,生成的文件名取决于包名+在 set up 函数中设置的版本+ python 版本,因此 this (filename)可能会频繁更改(只要这些参数中的任何一个发生更改)。这就是为什么我们使用模式匹配来匹配任何扩展名为.whl的文件,而不使用任何固定的文件名。

2。消费包

一旦将包上传到提要中,也可以在管道中使用它:

*- task: PipAuthenticate@1
  displayName: Pip Authenticate
  inputs:
    artifactFeeds: 'productsalesml/wheel_feed'
    onlyAddExtraIndex: true
​
- bash: |
    pip install product-sales-ml-etl
    python -m etl.console_main
  displayName: Install package and test it*

扩展版本

有时您需要存储关于版本/构建过程的附加信息(例如,存储整个git describe响应和/或[Build.BuildNumber](https://docs.microsoft.com/en-us/azure/devops/pipelines/build/variables?view=azure-devops&tabs=yaml#build-variables-devops-services))。理论上,你可以利用包的元数据来存储这样的信息,但是我找不到任何扩展元数据的友好的方式(尽管 PEP 459 申明是可能的)。最后,我将扩展版本编码到长描述元数据中。

首先,我们需要扩展管道执行期间捕获的信息。例如,将以下变量添加到 devops 管道中:

*variables:
- name: buildnumber
  value: $(Build.DefinitionName)_$(Build.Repository.Name)_$(Build.SourceBranchName)_$(Build.BuildNumber)*

这创建了一个名为buildnumber的管道变量,它使用构建预定义变量的值进行定义。buildnumber的值可能类似于:cicd-main_etl_testBranch_20201229.18

  • cicd-main : Build.DefinitionName 🡒 devops 管道名称
  • etl : Build.Repository.Name 🡒仓库名称
  • testBranch : Build.SourceBranchName 🡒分行名称的末段(例如features/testBranch 末段testBranch)
  • 20201229.18 : Build.BuildNumber 🡒构建号基于构建日期+增量 ID

现在,setup 方法可以收集先前在管道执行期间设置的环境变量的值(这里我定义了默认值,在本地测试或检查空值时很有用):

*from setuptools import setup, find_packages
import json
​
metadata_custom = {
    'version': os.getenv('VERSION','0.1.2'),
    'revision': os.getenv('DESCRIBE', '0.1.2-1-ge34ce98'),
    'buildNumber': os.getenv('BUILDNUMBER','etl-main_etl_main_20210101.1')
}
​
metadata_custom_as_markdown = \
rf"""```json
{json.dumps(metadata_custom)}
```"""
​
setup(name=_package_name_,
      version=os.getenv('VERSION','0.1.2'),
      packages=find_packages(include=["etl"]),
      long_description=metadata_custom_as_markdown,
      long_description_content_type="text/markdown",
      python_requires=">=3.8")*

如何访问存储在描述元数据字段中的信息?使用importlib.metadada的方式与简单版相同。尽管在这种情况下,使用方法distribution(),它不仅返回版本,还返回所有元数据属性。然后,在相应地解析描述后,您可以使用以下代码来获取版本元数据:

*@lru_cache
def get_version_metadata():
    from importlib.metadata import distribution
    import json, re
    metadata = distribution(_package_name_).metadata
    description = metadata["Description"] or metadata.get_payload()
    regex = r"^\s```json(.*)^\s```"
    matches = re.findall(regex, description, re.MULTILINE | re.DOTALL)[0]
    return json.loads(matches)*

最后,您可以扩展 main 函数来显示两个版本:

*import argparse
​
def display_version():
    print(f"version: {etl.get_version()}")
    print(f"extended version: {etl.get_version_metadata()}")
​
if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument('--version', '-v', help="display version", action="store_true")
    args = parser.parse_args()
    if args.version:
        display_version()*

主分支和其他分支的区别

在某些情况下,您对主分支(发布)和特性/修复分支的需求会有所不同。例如,如果您需要从一个特性分支生成一个预发布包,以便在某个阶段环境中测试这个包。在这些情况下,建议不要创建新标签(因为这将触发新版本),而是生成一个本地版本(使用构建、预发布或其他自定义命名)。

我们可以使用两种不同的管道来区分两种不同的工作流:

  • cicd-main:由对 main 分支的任何提交触发
*trigger:
  batch: True
  branches:
    include:
    - main*
  • cicd-pr:由主分支的拉请求触发。设置略有不同,因为触发器在 YAML 文件中设置为 none:
*trigger:
  none*

虽然 YAML 有一个pr模式,但是似乎只对 GitHub 和 Bitbucket 存储库有效。相反,我们将使用分支策略来触发管道。请考虑下图中描述的配置,1)允许将提交推送到主分支 2)管道不需要成功获得 pr 批准 3)合并 PR 时管道是而不是执行的(如果您更改前面的选项,合并 PR 时主管道和 PR 管道都将执行)。如果可以使用 YAML 更好地管理这种行为,那就太好了,但是目前,我们需要使用如下所示的 UI:

Azure Devops —编辑策略选项卡

最后,生成了一个更新版本,但是没有将标签推送到存储库,也没有使用 twine 上传 Python 包。但是 Python 包是作为管道的神器上传的,所以以后可以用。

*- bash: |
    ls $(Pipeline.Workspace)/dropArtifacts/*.whl | xargs -I {} pip install {}
    pip list
  displayName: Install package from artifact store
​
- bash: |
    LOGURU_LEVEL=WARNING
    python -m etl.console_main -v
  displayName: Test etl.console_main*

这种方法的一个缺点是,从相同(甚至不同)的特性分支中生成的所有构建将具有相同的版本。如果你需要对这种行为进行更多的控制,我推荐使用本地版本

摘要

没有灵丹妙药。这可能看起来是一个令人费解的解决方案,但如果你必须随身携带一件东西,那就是你必须绝对建立一种机制,确保你的机器学习应用程序的可重复性。您可以查看下面的存储库—https://github.com/franperezlopez/blog_databricks—它展示了这里讨论的技术以及关于部署 Databricks 应用程序的其他方面(如果您有兴趣在以后的帖子中讨论这些方面,请写一篇评论)。此外,欢迎在评论中分享你对这一过程的任何见解。

机器学习数据可视化

原文:https://towardsdatascience.com/machine-learning-data-visualization-4c386fe3d971?source=collection_archive---------16-----------------------

使用方面进行数据分析和可视化

来源:作者

你有没有在从各种图形中寻找洞见的时候纠结过?那么这篇文章就送给你了。如果你是一名数据科学家或数据分析师,你可能已经绘制了许多图表来研究数据,但现在你可以在一个单独的图中做同样的事情。

机器学习数据可视化对于理解数据如何在特定的机器学习模型中使用非常重要,它有助于分析数据。Facets 是一个开源的 python 库,可以用来轻松地可视化和分析数据。

方面由两种不同的可视化组成,一种用于理解我们拥有的数据,另一种用于分析我们拥有的数据。在本文中,我们将探索这两种可视化。

让我们开始吧…

安装所需的库

我们将从使用 pip 安装一个 Facets 库开始。下面给出的命令可以做到这一点。

!pip install facets-overview

导入所需的库

在这一步中,我们将导入加载数据集和可视化数据集所需的库。

import pandas as pd
from IPython.core.display import display, HTML

正在加载数据集

在本文中,我们将使用著名的糖尿病数据集,可以从网上下载。

train_data = pd.read_csv("/content/train.csv")
test_data = pd.read_csv("/content/test.csv")

创建前端

为了创建可视化方面,使用预定义的 HTML 模板。在这一步,我们将加载前端并创建可视化。

jsonstr = train_data.to_json(orient='records')
HTML_TEMPLATE = """
<script src="https://cdnjs.cloudflare.com/ajax/libs/webcomponentsjs/1.3.3/webcomponents-lite.js"></script>
<link rel="import" href="https://raw.githubusercontent.com/PAIR-code/facets/1.0.0/facets-dist/facets-jupyter.html">
<facets-dive id="elem" height="600"></facets-dive>
<script>var data = {jsonstr};
document.querySelector("#elem").data = data;
</script>"""
html = HTML_TEMPLATE.format(jsonstr=jsonstr)display(HTML(html))

来源:作者

在这里,您可以清楚地看到不同轴上的数据。面创建了一个图形用户界面,正如您在这里看到的,我们可以分别选择我们想要可视化的不同列和轴。

我们可以使用这种可视化来理解数据,还可以分析数据的不同特征之间的关联。

继续尝试不同的数据集,并使用 Facets 创建不同的可视化效果。如果您发现任何困难,请在回复部分告诉我。

点击下面的链接,查看不同的机器学习项目。

https://www.dezyre.com/article/top-10-machine-learning-projects-for-beginners-in-2021/397/

本文是与 Piyush Ingale 合作完成的。

在你走之前

感谢 的阅读!如果你想与我取得联系,请随时通过 hmix13@gmail.com 联系我或我的 LinkedIn 个人资料 。可以查看我的Github*简介针对不同的数据科学项目和包教程。还有,随意探索* 我的简介 ,阅读我写过的与数据科学相关的不同文章。

机器学习不会神奇地解决你的问题

原文:https://towardsdatascience.com/machine-learning-does-not-magically-solve-your-problems-5ae0bd3269c0?source=collection_archive---------11-----------------------

机器学习如何让我们克服不可能的挑战,但仍然需要大量的时间和金钱

介绍

“我认为 AlphaGo 是基于概率计算的,它只是一台机器。但是当我看到这个举动的时候,我改变了主意。AlphaGo 肯定是有创意的。这步棋真的很有创意,也很漂亮”(阿尔法围棋纪录片,52:10–52:40)。在这段引文中,李·塞多尔(Lee Sedol)是有史以来接触围棋最伟大的选手,他在与强化学习代理 AlphaGo 的一场比赛中对臭名昭著的 move 37 做出了反应。这凸显了围绕机器学习尤其是深度学习的那种神奇光环。AlphaGo 的一名开发者后来评论说(56:30),Alpha Go 是一个“真正简单的程序,离完全人工智能还远着呢”。这种来自非专家的神奇想法与从业者更加现实的观点形成了鲜明对比,在为机器学习项目所需的大规模投资提供支持方面,这是一个真正的挑战。

在这篇文章中,我想剥去一些覆盖机器学习的模糊层。我的目标是提供一个更平衡的观点,说明到底是什么让机器学习变得特别,以及为什么它仍然需要大量的工作。希望下次你讨论为什么你的机器学习项目需要这么长时间时,你可以使用其中的一些想法。

创造机器来解决问题

根据我的经验,机器学习项目看起来很像任何其他数据科学项目。我个人认为成功运行数据科学项目需要以下步骤:

  • 评估业务需求。根据项目的规模,这涉及到一个或一大群人。
  • 阅读我们的数据。这可以来自 csv 文件、SQL 数据库或 Hadoop 集群。
  • 处理和理解我们的数据。每列是什么意思?数据质量如何?是否有数据缺失?
  • 创建一组特征作为模型的输入。这可以手动完成,或者通过使用某种特征工程套件来完成。
  • 符合模型。对于更简单的模型,这仅仅涉及运行一个 Python 函数,但是更高级的技术通常具有超参数,可以调整这些参数以提高性能。
  • 评估我们的表现是否令人满意,如果不满意,回到我们之前的任何步骤
  • 将模型投入生产

以下三个流程图展示了三个可能模型的这些步骤:多元线性回归、结合 TSfresh 和 Lasso ( 示例)以及最后一个神经网络:

三个数据科学工作流(使用 Draw.io 创建)

这些流程图的要点是,从简单的线性回归到神经网络,它们看起来有多相似。在从线性回归到 TSfresh /Lasso 的过程中,我们保持大部分步骤不变,我们只是让 TSfresh 帮助我们生成特征。此外,Lasso 为我们提供了一个很好的方法来选择哪些特性与我们的模型相关。我们自动化了一些步骤,但也增加了调整正则化强度的工作量。TSfresh/Lasso 是一种在特定情况下有效的方法,不一定是快速自动程序。

观察神经网络方法,我们看到一些手动任务被吸收到神经网络中。具体而言,特征工程和选择由神经网络在内部完成。另一方面,我们必须确定网络架构(层数、互连性、损失函数等)并调整网络的超参数。此外,还需要完成许多其他任务,如评估业务问题。与 TSfresh/Lasso 一样,神经网络是一种在特定情况下工作良好的方法,不是快速或自动化的程序。

将回归转变为神经网络的一个好方法是,不要手动解决问题,我们建立一个机器来为我们解决问题。添加这一抽象层使我们能够解决我们从未想过能够解决的问题,但这仍然需要大量的时间和金钱来创造。

用机器打败人类

为了扩展建造一台机器来为我们解决问题的概念,我想更仔细地看看 AlphaGo。学习围棋的一个方法是建立一个所谓的专家系统。我们选择世界上最好的围棋手,让他们定义商业规则,告诉我们如何根据棋盘上的状态决定下一步该怎么走。然而,问题是围棋中的许多游戏都无法准确地捕捉到规则,棋手往往根据自己的直觉进行游戏。

或者,Alpha Go 不是通过手动定义玩家应该使用的策略来解决这个问题,而是通过大量玩游戏来学习它们。他们使用的方法称为强化学习,更具体地说是深度强化学习。该方法的核心是训练一个深度神经网络来获取棋盘的状态,并预测下一步的最佳行动。训练神经网络是通过大量玩游戏来完成的,并根据其表现为网络提供奖励或惩罚。让电脑和自己玩几百万个游戏,让网络慢慢变得越来越聪明。这种方法非常成功,让阿尔法围棋打败了有史以来最好的围棋选手。如果你想了解更多细节,我强烈推荐你去deep mind 网站

构建 Alpha Go 绝不是一个小壮举,需要机器学习领域最聪明的头脑花费数年时间来解决这个问题。一旦他们建立了深度强化学习机器,机器本身就可以学习围棋。但是制造这台机器仍然是一项艰巨的任务。

没有银弹

机器学习有一些神奇而令人敬畏的应用,扩展了我们认为可能使用计算机解决的应用范围。然而,机器学习的可怕潜力并不意味着它自动解决了我们的挑战。

我是谁?

我叫 Paul Hiemstra,是荷兰的一名教师和数据科学家。我是科学家和软件工程师的混合体,对与数据科学相关的一切都有广泛的兴趣。你可以在 medium 上关注我,或者在 LinkedIn 上关注 T4。

如果你喜欢这篇文章,你可能也会喜欢我的其他一些文章:

机器学习不是在真空中发生的,那为什么要在一个真空中发展呢?

原文:https://towardsdatascience.com/machine-learning-doesnt-occur-in-a-vacuum-so-why-develop-it-in-one-639ee8b8e0bb?source=collection_archive---------33-----------------------

从软件工程师的角度回顾 ML/DS 开发生态系统

Charles DeluvioUnsplash 上拍摄的照片

参考消息:我所说的关于机器学习的一切也适用于任何数据科学工作;虽然数据科学家的工作可能专注于内部,但如果是用来为业务制定决策,那么它应该是可靠的。

在过去的 30 年里,软件开发取得了长足的进步,开发了成千上万的工具来帮助完成编写代码的复杂任务。虽然这些工具中有许多已经淡出了人们的视线,但是还有一些,比如 git,已经成为全球软件开发的主要工具。这些工具中有许多专注于抽象掉复杂性,让开发人员专注于编写特定于应用程序的代码。让我们回想一下 21 世纪初,部署和适当扩展数据库通常需要几天时间,相比之下,今天只需三次点击就可以创建一个无限可扩展的 DynamoDB 表。为什么?嗯,云服务提供商的崛起让大多数公司完全摆脱了基础设施管理,开发人员在这些服务的基础上构建业务逻辑,不用担心他们是否有足够的服务器机架。这些服务提供商已经从硬件和基础设施元素中抽象出来,以加速云应用程序的开发。在许多情况下,这种加速从几年到几个月不等,推动了成千上万的初创公司,导致了我们目前正在经历的新应用和服务的真正繁荣。云不再只是大玩家的专利,任何开发者都可以使用。

这与机器学习/数据科学有什么关系?他们目前正处于云开发成为前云提供商的同一阶段。由于没有全面降低复杂性的服务,工程师不仅需要了解他们学科的基础知识,还需要了解如何开发、托管和维护他们构建的代码。这大大降低了开发速度,并将机器学习的规模限制在只有预算负担得起基础设施团队的大型科技公司。

这并不是说没有库来帮助解决这个问题,一些神奇的工具正在涌现,如 MLFlow,Google Colab 和 Feast。但它们不是包罗万象的,它们满足特定的标准,仅此而已。

为了说明这一点,假设您有一个用 Python 开发并在 Jupyter 笔记本上运行的模型。它是标准的开发工具,但是你想把它提供给最终用户。你是怎么做到的?将模型导出为 zip 文件?以后想重新培训模特怎么办?谁编写代码来利用模型?这是如何部署的?结果存储在哪里?我认为最好用 Metaflow 团队制作的图表来概括。

数据科学家的典型工作流程[1]

作为一名专业的云工程师,我看到这样的工作流就感到害怕。任何 CD 管道都应该以尽可能少的步骤尽快完成,以确保开发时间最大化。如果您的部署工作流程需要 5 分钟,那么您可以比那些工作流程需要 1 分钟的人少做 5 倍的测试,天才!机器学习很难,让我们给工程师尽可能多的时间来解决问题。

到目前为止,我已经侮辱了一个共同的工作流程,并没有提供答案,所以让我们定义一些标准,并看看我们如何才能改善!

成功工作流程的标准

  • 尽可能匹配生产*的开发环境
  • 用于开发环境测试的快速且可重复的部署周期
  • 轻松访问生成的日志和结果
  • 易于版本控制

如何用一个示例任务来说明上面定义的需求。假设我们的 ML 工程师杰洛特在一家在线销售汉堡的公司工作,他的任务是建立一个推荐系统,根据我们每天收到的数据更新向人们推荐不同的汉堡组合。这项工作需要开发,然后推向生产,它将每天为每个客户运行,并将当天的建议转储到数据库中。

模拟生产的开发环境

现在,这对于任何进入开发机器学习/数据科学工作的人来说可能有点奇怪,但当与不同的环境和平台一起工作时,这是至关重要的。每当您第一次将代码集成到生产系统中时,总会有问题、缺失的依赖项、不同的操作系统版本和意外的瓶颈会导致错误。如果您可以在尽可能接近生产的环境中开发,这将允许您在开发阶段消除这些问题。对于杰洛特来说,如果他在本地开发,然后推到一个远程实例来按计划运行他的代码,他可能会遇到破坏产品推荐系统的问题。如果杰洛特在远程实例的克隆上开发了他的代码(不要直接在生产系统上开发!)那么他可能已经能够避免这些问题,减少他的工作量和将系统投入生产所需的变更。

坚持这一要求也意味着不必重写开发代码来将其部署到生产中。想象一下,杰洛特开发了一个 Jupyter 笔记本,创建了测试,并确保一切工作正常——只是为了撕掉它,重写它,以便它可以很容易地装入集装箱。这根本说不通。如果杰洛特在一个模拟的生产环境中工作,他可以重用他经过反复测试的开发代码(如果你对为什么这很糟糕感兴趣的话[2])。

虽然这个需求很重要,但是它也不应该妨碍开发人员在两次测试之间进行快速迭代——这是我们的下一个需求。

建议:尝试在本地重建生产环境。容器是一个很好的工具,因为它们不需要外部依赖。如果您不能使用容器,那么在轻松地推到远程位置之前允许有限的本地测试是至关重要的。Jupyter 笔记本在这里并不是一个好的工具,因为您可能需要重写部分代码才能在生产中运行它!

快速且可重复的测试部署流程

虽然我早些时候谈到了这一点,但让我们重新看看这对机器学习意味着什么。这个过程应该是代码被“部署”到其开发环境(本地或其他地方)并运行以测试代码的方式。在杰洛特的例子中,这将是把他的代码推送到克隆的远程实例(模拟生产)并运行它以在一个示例数据集上产生一些测试建议。如果这个过程需要很多手动步骤,那么这可能会使杰洛特脱离专注状态[3]或者导致错误,从而减慢进度。这是我们想要避免的。

作为其中的一部分,软件管道通常包括单元测试,以确保代码按预期运行。虽然您可能无法直接测试正在开发的模型,但是测试所有内部逻辑和输出以确保它们满足概述的标准仍然有很大的价值。在 Geralds 的案例中,他可以拥有世界上最好的推荐系统,但是如果他的代码不能正确地将值写入数据库,那么它对他的公司就没有用了。

考虑到所有这些,当设计一个工作流时,分三个阶段考虑可能是好的。

第一阶段:局部探索- >局部

探索样本数据集,感受可能需要的工作。这最好在本地完成,因为它需要大量的快速迭代,例如,格式化和编组数据。杰洛特不想花 5 分钟等待代码部署,只是为了打印出数据框的内容。

第二阶段:批量开发- >开发环境

任何模型的大部分实质性开发都需要大量较慢的迭代,因为此时代码可能很重要,并且做出更改会更加复杂。对杰洛特来说,这是他开发和训练模型的时候。作为其中的一部分,将需要一些健壮的部署,这样他可以持续地测试他的工作,可能包含单元测试,以确保输入/输出保持在规范之内。理想情况下,这也可以在前面讨论过的类似生产的环境中进行,以尽量减少以后的问题。

第三阶段:生产调度- >生产环境

为了部署到生产中,代码必须通过一系列严格的测试——结合可伸缩性测试的思想,以确保模型在输入增加时保持准确性。这个过程也应该随着代码在生产调度中的实际部署而自动完成。

建议:遵循上面的分阶段过程概述,利用诸如 Metaflow 或 Kubeflow 之类的工具,在部署代码时尽量减少对开发人员的干扰。

轻松访问代码库生成的日志和结果

我觉得这个没有太大争议,但是肯定需要强调一下。在开发时,你需要确保可以快速访问代码库创建的任何输出,以便在必要时可以轻松调试。如果您的工作流涉及将代码推送到远程机器,您需要确保能够轻松地访问生成的日志——我们在这里着眼于改进流程,而不是降低它们的效率!

这也适用于任何输出——不仅仅是调试信息——杰洛特不能确定他的代码已经将正确的值写入数据库,除非能够检查它们。

推荐:同样,像 Metaflow 这样的工具非常有用,因为它们为调试提供即时反馈,并存储所有变量的结果以供进一步分析。避免使用 SSH 之类的机制来获取日志反馈,因为它们需要手动步骤,容易出错,而且会让开发人员更加难以集中精力。

易于版本控制

我向任何人挑战,看他们能否找到一个不对他们的代码库使用某种版本控制的传统软件团队。它有很好的理由,它是存储、恢复、组合和分析任何代码的无价工具。

它不仅作为代码的备份很方便,而且跟踪代码的版本也非常有用——这在跟踪 bug 时非常重要。如果您正在部署您的代码按计划远程运行,通常很难知道您的代码运行的是什么版本。你是否曾经运行某个程序并得到一个输出,然后想——这是不对的?我想知道它是否部署正确—让我再试一次,看看它是否能修复它。在持续部署管道中利用版本控制可以帮助实现这一点[4],因为它可以在您提交时将您的代码部署到远程位置,因此您可以回顾并查看上次提交的内容,并确定您的代码正在运行的版本。据我所知,部署管道中的不确定性是导致灾难的原因,并且容易导致错误诊断。

这里我想说的最后一点是团队整合。如果杰洛特有一个队友也在开发他的代码库,如果他们使用 git 这样的版本控制系统,他们会更容易合作,而不会妨碍彼此。这将允许他们提交拉请求,并检查彼此的代码,彼此独立地部署代码。

推荐:用 git!如果您还有时间,请使用 Github actions 来运行基本的分析、测试和代码部署——不要再手动将拉链放到 S3 了!

那么作为一个 TL:DR,这里有什么外卖?ML 不是在真空中发生的。它总是需要从其他服务中消费数据,并在其他地方写入数据。这意味着它需要像围绕它的服务一样稳定和可靠,而实现这一点的可靠方法是使用良好的软件开发原则来构建可靠的代码库。

对于直接的建议,我会说寻找像 MetaflowKubernetes/Kubeflow 这样的工具,它们实现了几个标准点,比如使用容器来减少切换到生产时被改变的内存占用。如果这些超出了您的能力范围,那么使用 bash 来自动部署您的代码——即使这只是本地的——以便其他人可以获得您的代码,运行一个命令,然后开始。虽然安装这些过程可能会占用一些初始开发时间,但它们将在项目的后期产生回报,并证明对将来使用您的工作的其他开发人员是无价的。

我只是简单地介绍了一些我认为可以使用的工具,在以后的博客文章中,我将比较这里提到的一些工具,看看哪一个对所有开发人员都是最有效的。

*在这种情况下,生产被定义为任何 ML/DS 工作运行以产生业务价值的地方——通常这被安排为定期提供业务洞察力或向客户提供服务。

参考文献

[1]—https://docs.metaflow.org/introduction/why-metaflow 网飞(2019 年)

[2] —乔尔·斯波尔斯基,《你不该做的事,第一部分》(2000 年),https://www . joelonsoftware . com/2000/04/06/Things-You-Should-Never-Do-Part-I/

[3] —肯德拉·切瑞,《心流的心理学》(2021),https://www.verywellmind.com/what-is-flow-2794768

[4] — GitLab,CI/CD 的 4 个好处(2019),https://medium.com/@gitlab/4-benefits-of-ci-cd-efc3d6b9d09d

机器学习工程师简历示例

原文:https://towardsdatascience.com/machine-learning-engineer-resume-sample-ea7a4951f030?source=collection_archive---------1-----------------------

我的个人简历让我得到了几份工作

图片由作者创建,作者的简历背景图片许可证通过 Envato 持有

找一份新工作甚至是你的第一份工作可能是一个可怕的过程。我可以向你保证,数据科学的世界正在扩大,你也会很快找到工作。

信念是迈出第一步,即使你看不到整个楼梯。——小马丁·路德·金

求职的第一步是你的简历。今天,我将向你展示我的个人简历,并向你介绍我写简历时的想法。当你有不太相关的内容时,我也会提到几件你可能想写的事情。

既然我希望你比我更优秀,我也将与你分享不同的潜在雇主在面试中告诉我的关于这一点的信息。

简历提交讨论

我的个人简历

你的申请完成了吗?

保持简短,保持在一页纸内,不要像脸书用户协议的小字一样填满。我知道你做过和看过的事情足够写几本书了。但是如果你站在大公司招聘人员的立场上,他们会看几百份简历,只想要最精彩的部分。

如果他们觉得你很有趣,他们会在你的求职信和面试中给你足够的时间来享受你的所有福利。

这让我想到了你应该在申请中附上的东西,一封求职信或动机信,你可以在信中更详细地说明为什么你认为自己是这份工作的唯一候选人,是本月的下一个员工。如果你想浏览我的求职信模板,请在评论中告诉我。

另外,附上你的学位和以前雇主的推荐信。许多人不会读它们,但那些真的喜欢你发送它们的人会留下一个完整的好印象。

谁看你的简历?

你可能注意到的第一件事是所有的流行语,嗡嗡地飞来飞去,向机器鼓吹你的技能。当你考虑一份简历时,要意识到简历上的第一双眼睛很少是人。这意味着软件会预先扫描你的简历,以减少人力资源人员的工作量。他们通常选择多年的工作经验、技术、教育和行业知识,例如“我们正在寻找一名拥有硕士学位和 3 年 Python 经验的候选人,最好之前有过地理数据工作经验”。

基础知识

我们从头到尾过一遍。第一件事应该是你的名字和你要从事的职业,我让数据科学家从一开始就设定正确的基调。个人资料图片并不是在任何地方都很常见,所以如果需要的话可以使用,这张照片相当糟糕,我不得不在“不应该被命名的疾病”的最初锁定期间自己制作,但如果可以的话,请一位合适的摄影师。

联系信息

下面我把所有相关信息联系我。我还写下了我的地址,虽然没什么用,但它告诉了他们你住在哪个城市,有一次我甚至在很短的时间内就接到了面试通知,因为我住在附近,他注意到了,所以细节中有一些好处。

老实说,再看一遍,它可能有点太大了,人们可能还可以放一个 LinkedIn 的链接,许多人喜欢 Linkedin。有时他们甚至在 LinkedIn 上跟踪你,众所周知,跟踪者更有可能再次联系你。电话号码、电子邮件和 GitHub 都是非常值得推荐的,我在面试中被告知这有多好。他们可以立即扫描 Git,我们可以在上面讨论一些项目。

技能部分

技能部分可能更像是一个视觉上的惊喜,再次简单明了地展示了我的经历。对于数据科学家来说,语言可能是一件大事,尤其是在处理非英语数据时,所以一定要利用这一点。

技能概述简而言之

教育和编程

现在来说说实际的文字和内容。我建议把它分成四个部分:教育、编程、体验和项目。如何排序取决于你认为什么是你最大的优势。如果你有学士或硕士学位,教育是一个必须的部分,我选择把下面的空间留给更相关的项目,但请随意添加你的科目,当然如果你有空间的话。

编程和教育

就我的编程技能而言,我个人喜欢条形图可视化,这也是一个放置更多热门词汇的好地方,如果你想为特定的工作量身定制简历,也相对容易重组。我把我最好的技能从上到下放在这里。Python、Numpy、Typescript、SQL、git,我会确保列出你申请的工作类型所需的最相关的技能,但一般的软件工程技能,如 Git、Sonarqube、SQL 等。应该总有一席之地。

事后看来,我在这里忘记的是 DevOps 工具,如 Jenkins、airflow 和 ansible,以及其他可以成为巨大优势的工具,感觉像是一个开瑞士玩笑的好地方,但我们不在这里开工作玩笑。

经验

你最大的部分应该是经历,因为人们通常知道你大学课程的一部分。你的工作经历给了你更多的个人优势。我在这里只写与数据世界相关的工作经验,但是如果你有空间的话,也可以包括学生工作。列出一些要点,简而言之,告诉他们你在做什么,可能还会列出团队规模,因为我被问到这个问题的次数比预期的要多。

事后看来,我也会试着把我从社会角度学到的东西包括进来,比如“必须从各种各样的利益相关者那里获得需求”。或者“为公司客户提供支持”和“在会议上展示技术信息,在会议上我学会了与非技术同事交流统计结果”

简历中我的个人经历部分

项目

最后但并非最不重要的项目,就像工作经验一样,这是展示你个人优势的好地方,向他们展示为什么你是这份工作的合适人选。正如你所看到的,我把所有的东西都剪到了一行,因为一个 pdf 文件里真的没有那么多空间。

我的项目部分

我在这里犯的一个错误是我把项目按错误的时间顺序排列,这让一个人感到困惑,实际上你最近的成就应该总是在第一行。

我在学习期间能够合著一些出版物,我认为你应该强调这样的小细节。它向读者展示了你付出了额外的努力,不仅通过了考试,而且对其他人有用。

这份简历到底怎么写?

如果你喜欢我的简历模板,我用 Latex 写的,你可以在这里找到这个模板。它是由背页的这个模板演变而来。

结论

我希望你能从这张小小的纸上学到一些东西,一旦你完成了它,世界就是你的了。那么一旦你出现在面试中,一定要做好准备,如果你想知道我的经历,一定要看看我在机器学习工程师面试过程中的视频和他们肯定会问的问题。

让我在评论中知道这份简历的好和更重要的坏,请问我,它肯定也会帮助别人。

如果你喜欢这篇文章,我会很高兴在 TwitterLinkedIn 上联系你。

一定要看看我的 YouTube 频道,我每周都会在那里发布新视频

机器学习执行是一个有向无环图

原文:https://towardsdatascience.com/machine-learning-execution-is-a-directed-acyclic-graph-211e5e1e6c57?source=collection_archive---------13-----------------------

意见

机器学习的执行不应该被认为是一个流水线。

图一。复杂的管道网络。是管道吗?保罗·泰森在 Unsplash 上的照片

随着我们继续开发机器学习操作( MLOps ) 我们需要把机器学习(ML)开发和部署流程想成一个有向无环图(DAG)。

DAG 是一个可怕的首字母缩写词,但 LTSM、DNN、反向传播、GAN、transformer 和其他许多词也是如此。

我觉得用“管道是不对的。

pipeline 的问题在于它是俚语。但更糟糕的是,它意味着一个线性的步骤过程。

我可以向你保证,人类的大脑不是一个管道

:我想不出任何哺乳动物有“管道”。有些昆虫和恐龙有神经节的管道吗?

也许最可怕的是,没有深厚的数学理论,也没有“流水线的伴随算法

Dag 拥有丰富的算法,我们需要这些算法来处理多个卷积神经网络(CNN)的复杂几何结构的非线性步骤。

这就是为什么主要的 CNN 框架,如 Tensorflow、Pytorch、MXNET 等,使用术语 DAG 并且是 DAG。

管道的定义是什么?

在机器学习被主流采用之前,计算管道的概念就已经存在了。

软件管道,由一系列计算进程(命令、程序运行、任务、线程、程序等)组成。),概念上并行执行,一个进程的输出流自动作为下一个进程的输入流。被称为管道Unix 系统是这一概念的经典例子。—https://en . Wikipedia . org/wiki/Pipeline _(计算)

你第一次在机器学习的背景下了解管道是在哪里?

我从 sk-learn 机器学习管道中了解了管道。

构想 sk-learn 库的人定义了一个名为Pipeline的 Python 类(对象)。

顺序应用变换列表和最终估计器。管道的中间步骤必须是“转换”;也就是说,它们必须实现 fit 和 transform 方法。最终的估计器只需要实现 fit。— sk-learn 管道文档。:

一个 sk-learn Pipeline的例子:

pipe = Pipeline([('scaler', StandardScaler()), ('svc', SVC())])
pipe.fit(X_train, y_train)

=>

Pipeline(steps=[('scaler', StandardScaler()), ('svc', SVC())])

在上面的例子中,pipe 是一个类实例,它将 fit 操作按顺序首先应用到标准缩放器 (sk-learn t 转换器),然后应用到[SVC](https://scikit-learn.org/stable/modules/generated/sklearn.svm.SVC.html) (sk-learn 估算器)。

我对类 sk-learn

什么是有向无环图(DAG)?

注: 这篇博客文章并不试图发展大多数计算机科学课程中所要求的图论。

图论中,有向无环图(DAG)是没有有向圈有向图。它由顶点(也称为)组成,每条边都从一个顶点指向另一个顶点,这样沿着这些方向永远不会形成一个闭环。—https://en.wikipedia.org/wiki/Directed_acyclic_graph

管道像匕首一样混乱

不知何故,从 sk-learn 到现在,流水线和有向无环图(DAG)混淆了。

创建、生产和扩展端到端的 ML 管道,并观察这些管道产生深远的、改变游戏规则的业务影响。—https://www . slide share . net/databricks/navigating-the-ml-pipeline-jungle-with-ml flow-notes-from-the-field-with-thunder-Shi viah

管道是对 ML 工作流的描述,包括所有工作流组件以及它们如何在图形中组合。—https://www . kube flow . org/docs/pipelines/overview/pipelines-overview/

一些人称他们的阶梯网络为 DAG。

用于分析 Jenkins 管道(以前的工作流)的插件通过检查组成它们的 FlowNodes 的有向无环图来运行。适用于依赖关系阻止其包含在工作流 API 插件中的情况。— 詹金斯插件

如果我们把一个机器学习模型的执行流程想象成一个 DAG ,我们可以使用图论的丰富领域。

Tensorflow 和 Pytorch 将计算流表示为 DAG。

两个领先的机器学习(深度学习-DL)框架, TensorflowPytorch ,构建了 CNN 模型流的 DAG。更重要的是,开发人员社区将这些 CNN 模型称为静态或动态 Dag,而不是管道。

下面显示的 4 层卷积神经网络(CNN)模型的完整源代码在 GitHub 上。

model = keras.models.Sequential([
    keras.layers.Flatten(input_shape=(28, 28)),
    keras.layers.Dense(32, activation='relu'),
    keras.layers.Dropout(0.2),
    keras.layers.Dense(10, activation='softmax')
])

Tensorboard 将任何 Tensorflow 或 Pytorch DL 模型的计算流绘制为 DAG。

图二。张量流 CNN 计算流的张量板 DAG。来源: TensorBoard 文档

ML 模型用的一些图论算法是什么?

演示“ 张量流图优化 ”显示了用于减小 CNN 大小的 DAG 算法,这是因为 CNN 的训练速度更快,但退化不准确。

用于神经架构搜索的图形超网络展示了如何使用图论来寻找特定任务的神经网络(NN)拓扑。

所有 CNN DAGs 都具有定义它们可以使用或分析的可能动作和限制的属性。

什么是机器学习操作(MLOps)?

MLOps 是自动化机器学习(ML)工作流的实践。MLOps 工作流代表一个 DAG,其节点是 ML 生命周期的总步骤:

  • 通过不同的方法输入不同的数据集(FeatureStore);
  • 训练不同的 ML 模型;
  • 决定和测试(阶段)将哪个训练好的 ML 模型投入生产;
  • 将训练好的 ML 模型部署到生产系统上;
  • 监控生产 ML 模型。

这些 MLOps 级在概念上如图 3 所示。

图 3。MLOps 阶段的概念模型。来源:作者。

2021 年,我希望我们能够更好地理解机器学习项目的整个周期,构建 MLOps 工具来支持这项工作,以及系统地构建、生产和维护人工智能模型。—吴恩达教授—该批次 2020 年 12 月 30 日

如果我们将机器学习操作流或 MLOps 流视为 DAG ,我们可以使用图论的丰富领域。

这是管道还是 DAG?

Kuberflow 文档显示一系列的 ML 元素(流水线)会导致 DAG 的计算。

图 4:来源: Kuberflow 文档

这个 Kuberflow xgboost 示例的代码可以在 Github 上找到。

随着部署,机器学习流继续具有更多的元素和更多的分支点。将 ML 流称为管道最多是误导。

我并不是说要停止使用术语管道。我是说,将图论应用于表示为 DAG 的 MLOps 流有很大的机会。

MLOps 用的一些图论算法是什么?

Cyclone 是用于 Kubernetes 资源的工作流引擎。Cyclone 为 DevOps 和 MLOps 工作流元素计划提供了 DAG 模板。

您可以将机器学习(ML)模型的所有元素表示为 DAG。您可以仅为该任务所需的 ML 模型执行简化的子图。图 5 显示了一个例子。

图 5。七种不同的生产 ML 服务的完整架构。来源:作者。

图 5 DAG 的子 DAG 将执行TextToSpeech服务。另一个子 DAG 将依次执行AutoTranslation, SpeechToText, TextToSpeech,DialogFowEnterprise服务。

用图论算法找到并执行任何连接的子 DAG。

Git 是版本的 DAG。GitActions 是一个版本上的动作的 DAG。

有向非循环图可用于 CI/CD 流水线的环境中,以建立作业之间的关系,从而以尽可能最快的方式执行,而不管阶段如何设置。——【https://docs.gitlab.com/ee/ci/directed_acyclic_graph/

同样,任何连接的子 DAG 都是用图论算法找到并执行的。

Anthos 是针对 Kubernetes 混合配置的 MLOps 解决方案。

Anthos 是谷歌精心设计的一个庞大系统,由护目镜云 Kubernetes 服务(GKE)、本地 Kubernetes(企业内部云)和其他供应商的云上的 Kubernetes 组成。Anthos 是一个元 Kubernetes 服务,它将组件及其互连性表示为一个 DAG。Anthos 称 DAG 表示为服务网格。

图 6。Anthos 编排的微服务的 DAG 表示。来源:谷歌 Anthos 博客。

Anthos Service Mesh,Google 的完全托管服务 Mesh,让您轻松管理这些复杂的环境(ed。微服务器集群)并享受其承诺的好处。— Anthos 服务网

中心点不是你命名的 Anthos 服务网格,而是使用丰富的图论算法集和 DAG 表示。

机器学习的 DAG 工具

对于表示为 DAG 的 MLOps 工作流,已经存在具有开放源代码的 DAG 工具:

  • 适用于任何 DAG 的工具集
  • 气流(data ops);
  • DAG 调度器 : 通用 DAG 调度器r;
  • Dagon 支持重写规则在母 DAG 中查找和转换子 DAG。它创建了一个更小、更简单的新 DAG。它消除了冗余的子 Dag,消除了不是可达输入数据的子 Dag,等等。我应该警告你,Dagon 是用 Scala 写的,但是它执行起来很快。请注意,Dagon 由重写规则组成。我认为 Dagon 是一个 DAG 预编译器。向 Dagon 添加一个 Y 后端,其中 Y 是目标介质,这样就有了一个 DAG 到 Y 的编译器。

DAG 工具已为未来的重大 MLOps 执行流程做好准备。

摘要

这个博客的中心概念是:

  1. 假设我们把 ML 模型的执行流程想象成一个 DAG。我们可以利用图论的丰富领域。
  2. 几个不同的 ML 服务创建了重要的 MLOps 执行流。推理 MLOps 工作流的一种方法是将它们表示为 Dag。

直到 20 世纪 80 年代,我们的社交网络只有几十个。如果我们活得够久,有足够的魅力,我们就会拥有数百个社交网络。

现在我们有一个数以千计到数千万计的在线社交网络。你有几个社交网络,有些没有重叠或连接,玩游戏,属于聊天组,有追随者,并关注其他网站。

随着社交网络的发展,机器学习(ML)也将随之发展。我预测在不久的将来,ML 节点和 MLOps DAGs 的网格将在云上支持这些 ML 节点。我预测在电话、机器人和其他边缘设备上会有更小的 ML 服务网。

编码快乐!

用于信用卡欺诈检测的机器学习

原文:https://towardsdatascience.com/machine-learning-for-credit-card-fraud-detection-a-jupyter-book-for-reproducible-research-8ca5edad7b5d?source=collection_archive---------12-----------------------

实践教程

朱庇特可复制研究书籍。

UnsplashCardMapr.nl 拍摄的照片。

不幸的是,用于信用卡欺诈检测的 ML 是大多数已发表的研究不可复制的领域之一。出于保密原因,真实世界的交易数据不能共享,但我们也认为作者没有做出足够的努力来提供他们的代码并使他们的结果可重复。

我们刚刚发布了关于该主题的一本书的前五章,旨在朝着提高该领域研究的可重复性迈出第一步:https://fraud-detection-handbook . github . io/fraud-detection-handbook。这本书是比利时布鲁塞尔大学机器学习小组Worldline 十年合作的成果。即将到来的章节将解决更高级的主题,如类不平衡,特征工程,深度学习和可解释性。

这个初步版本是 Jupyter 图书格式,在开源许可下,所有的实验和结果都是可复制的。包含代码的部分是 Jupyter 笔记本,可以在本地执行,也可以使用 Google Colab 或 Binder 在云上执行。这本书的源代码(包括文本、图片和代码)可以在 GitHub 上找到:

https://github.com/Fraud-Detection-Handbook/fraud-detection-handbook

目标受众是学生或专业人士,从实用的角度对信用卡欺诈检测的具体问题感兴趣。更一般地说,我们认为这本书对于处理涉及顺序数据和/或不平衡分类问题的机器学习问题的数据从业者和数据科学家来说也是有兴趣的。

在这篇博客文章中,我们希望总结当前发布的内容以及对数据科学社区的附加值。前五章的主要贡献如下:

  • 合成交易数据模拟器:这本书提出了一个交易数据模拟器,允许创建不同复杂性的合成交易数据集。特别是,模拟器允许改变类别不平衡的程度(欺诈交易的低比例),包含数字和分类变量(分类特征具有非常多的可能值),并以时间相关的欺诈场景为特征。
  • 再现性:这本书是一本 Jupyter 书,它允许交互式地执行或修改这本书包含代码的章节。与合成数据发生器一起,在这本书里提出的所有实验和结果是可重复的。
  • 最新综述:这本书综合了最近关于信用卡欺诈检测的机器学习主题的调查(CCFD 的 ML)。它强调了这些调查中提出的核心原则,并总结了欺诈检测系统面临的主要挑战。
  • 评估方法:本书的主要贡献在于详细介绍和讨论了可用于评估欺诈检测系统效率的性能指标和验证方法。

我们在下面强调了这本书是如何允许容易地复制实验,并设计新的实验。

Jupyter 图书格式

实验的可重复性是这本书的关键驱动力,选择 Jupyter Book 格式似乎比传统的印刷书籍格式更合适。

首先,这本书包含代码的所有章节都是 Jupyter 笔记本,由于外部链接中的穿梭图标,可以使用 Binder 或 Google Colab 在云上执行。通过克隆图书存储库,笔记本也可以脱机运行。

书中包含代码的任何部分都可以使用 shuttle 图标用 Binder 或 Google Colab 打开和运行。Github 图标可用于打开问题或建议编辑。

第二,这本书的开源性质——完全可以在公共 GitHub 知识库上获得——允许读者就 GitHub 问题展开讨论,或者提出修改或改进请求。

交易数据模拟器

过去, MLG 通过在 Kaggle 上发布信用卡欺诈检测数据集,促成了这种可重复性差距,这要归功于它与 Worldline 的合作。该数据集已被广泛用于研究文献、关于走向数据科学,并且是 Kaggle 上投票和下载最多的数据集之一(自 2016 年以来超过 800 万次浏览和 30 万次下载)。

然而,这个数据集有一些限制,特别是在模糊特征和有限的时间跨度方面。为了解决这些限制,这本书提出了一个简单的交易数据模拟器,以最简单的形式生成交易数据。本质上,支付卡交易由顾客在特定时间支付给商家的任何金额组成。因此,总结交易的六个主要特征是:

  1. 事务 ID:事务的唯一标识符
  2. 日期和时间:事务处理发生的日期和时间
  3. 客户 ID:客户的标识符。每个客户都有一个唯一的标识符
  4. 终端 ID:商家(或者更准确地说是终端)的标识符。每个终端都有唯一的标识符
  5. 交易金额:交易的金额。
  6. 欺诈标签:一个二进制变量,值 0 表示合法交易,值 1 表示欺诈交易。

这些特征被称为TRANSACTION_IDTX_DATETIMECUSTOMER_IDTERMINAL_IDTX_AMOUNTTX_FRAUD。模拟器生成交易表,如下图所示。

带标签的事务表示例。每笔交易都表示为表中的一行,
连同其标签(TX_FRAUD 变量,0 表示合法交易,1 表示欺诈交易)。

模拟器的详细信息在第 3 章第 2 节中描述。

基线模拟数据集

使用模拟器生成的基线模拟数据集在整本书中用于实验性地评估机器学习技术和方法。它强调了欺诈检测从业者在使用真实世界数据时面临的大多数问题。特别是,它包括类别不平衡(不到 1%的欺诈交易)、数字和分类特征的混合(分类特征涉及非常大量的值)、特征之间的重要关系以及时间相关的欺诈场景。这个基准数据集包含大约 180 万笔交易,涉及 5000 个客户和 10000 个终端,时间跨度为 183 天(6 个月的交易)。

鉴于非数字和分类特征通常不能用作预测模型的输入,特征工程被用于将基线特征转换为数字特征,使用的方法包括二进制编码、聚合和频率编码。预处理后,数据集包含 15 个输入变量。值得注意的是,这种预处理在性质上类似于应用于 Kaggle 数据集的预处理。这个模拟数据集的一个主要附加价值是,用户现在可以从包含客户和终端 ID 的原始交易数据开始,并探索其他特征工程方法的使用。

基线数据集可以在 GitHub 上获得,只需克隆相应的存储库就可以重用。

实验的标准模板

书中反复使用的函数,如加载数据、拟合和评估预测模型或绘制结果,都集中在参考资料部分的单个笔记本中(称为 shared_functions)。

设置运行实验的环境非常简单:

  1. 下载并包含共享功能,
  2. 克隆包含模拟数据的存储库。

这是通过以下代码行实现的:

设计基线欺诈检测系统

基线欺诈检测系统的设计通常包括三个主要步骤:

  1. 定义训练集(历史数据)和测试集(新数据)。定型集是用于定型预测模型的事务的子集。测试集是用于评估预测模型性能的事务子集。
  2. 训练预测模型:该步骤包括使用训练集来找到能够预测交易是真实的还是欺诈的预测模型。我们将依靠 Python sklearn库来完成这项任务,该库提供了易于使用的函数来训练预测模型。
  3. 评估预测模型的性能:使用测试集(新数据)评估预测模型的性能。

数据加载和拆分

让我们首先从数据的加载以及将它们分成训练和测试集开始。这可以通过以下方式实现:

上面的代码加载了三周的数据。第一周用作训练集,最后一周用作测试集。第二周,称为延迟期,被搁置。下图显示了每天的交易数量、每天的欺诈交易数量和每天的欺诈卡数量。请注意,每天的交易数量约为 10000 笔(数据按 50 的系数缩放,以使欺诈的数量更加明显)。该数据集平均包含 0.7%的欺诈交易。

模型培训和评估

预测模型的训练和评估可通过以下方式实现:(1)定义输入和输出特征,(2)使用 Python sklearn 库提供的任何分类器训练模型,以及(3)评估性能。

使用共享函数,实现只需几行代码,如下所示:

深度为 2 的决策树分类器的性能使用一周的数据进行训练,并使用一周的数据进行测试。我们会根据 ROC 曲线下的面积、平均精度和卡精度来评估性能。这些绩效指标的动机详见第 4 章

生成的诊断树为:

上面的例子在这本笔记本中有更详细的介绍,它还提供了使用 logistic 回归、随机森林和梯度提升预测模型的欺诈检测系统的实现。Binder 或 Google Colab 可能会用于重现结果并探索您自己的建模策略。

结论

我们希望这一初步发布将会引起从事欺诈检测主题工作的从业者的兴趣,并欢迎反馈和改进建议。

雅恩艾勒博格纳吉安卢卡邦坦皮

感谢

本书是机器学习集团、比利时布鲁塞尔大学Worldline 十年合作的成果。这一合作之所以成为可能,要归功于布鲁塞尔地区研究与创新学院 Innoviris,该学院自 2012 年开始提供一系列资助,并于 2021 年结束。

链接

使用 Weka 的机器学习

原文:https://towardsdatascience.com/machine-learning-for-newbies-7dd33dd6b764?source=collection_archive---------31-----------------------

为什么 Weka 为没有编码经验的新手 AI 爱好者提供最好的机器学习体验

Clarisse CrosetUnsplash 上拍摄的照片

在使用谷歌云平台上的 Python 库和 TensorFlow 开始我的机器学习之旅后,所有这些都需要一定程度的编码知识,我想知道是否有一种方法可以应用相同的方法,以便可以使用 PythonR 或其他面向数据科学和分析的编程语言完成数据分类等任务,而无需进行任何重大的开发工作。这个探索始于我的朋友和同事找到我,想知道他们可以从哪里开始在自己的工作中使用机器学习。以下是一些出现的问题:

我如何使用机器学习来定位我的新产品?

我有没有可能用 AI 来预测客户行为?

我可以使用机器学习来评估交易中欺诈的可能性吗?

在波士顿大学攻读硕士学位期间,我被介绍给了 Weka ,它最终成为非技术人工智能(AI)爱好者的完美工具,允许他们在不编写一行代码的情况下构建和测试机器学习模型。它是一个具有图形用户界面(GUI)的强大工具,用户可以在其中加载数据集,运行统计实验,应用多种类型的机器学习算法,并验证其模型的准确性达到很高的精确度。因此,我向初学者推荐 Weka ,因为他们可以专注于机器学习的过程,而不是底层的理论、深厚的数学基础或编程方面,这些都可以在事后学习。Weka 是一个方便的工具,当正确应用时,可以用来开发能够回答上述问题的模型。

机器学习是人工智能的一个子集,其中计算机被训练成在有限的人工干预下,根据提供的数据集做出决策。这个想法是让计算机以自主的方式随着时间的推移不断改进这个过程。随着越来越多的数据输入到机器学习模型中,以及基于测试结果的迭代改进,得出的结论就越准确。输入数据可以从几种不同类型的来源提供给模型,例如 CSV 文件、音频、图像、关系数据库、视频和文本格式。一个精确的机器学习算法可以区分狗和猫,识别自动驾驶车辆的障碍物,根据客户的购买历史为客户识别潜在的新产品,在视频流媒体平台上推荐电影,或者决定 judge 一词是指司法成员做出关键的法律决定,还是指做出评估(判断)的行为。

机器学习的学科可以分为两类:监督非监督

在监督学习的训练阶段,大量的标记数据被新兴的模型消耗。监督模型可以执行评估,如识别手写的字母(区分草书和正楷)或决定书面文本的潜在情绪是积极还是消极。

另一方面,无监督学习不依赖于标记的数据,而是在数据中寻找相似性,然后将其分成不同的类别。例如,谷歌可以使用无监督学习来根据各个页面之间的相似性将搜索结果分组,而像 Airbnb 这样的房产租赁应用程序可以使用无监督学习来根据价格、评级或可用性对其服务上列出的租赁单位进行分类。

在这篇文章中,我将把用于分类目的的表格数据集加载到 Weka 中,并运行高级机器学习算法,所有这些都将在不到 15 分钟的时间内完成。一旦掌握了窍门,就很容易开始为许多不同的目的(超出数据分类)应用不同的算法和数据集。

Weka 是新西兰汉密尔顿怀卡托大学开发的一款用于数据分析的开源应用。

步骤 1:检查 Java 是否安装在您的电脑

在运行 Weka 之前,你需要在你的电脑上安装 Java

您可以通过打开窗口中的命令提示符并输入命令“java -version”来检查您是否安装了 Java ,这将返回您机器上安装的 Java 版本(如果有)。在 Mac 电脑上,你可以打开一个终端窗口,运行“java -version”命令,这将返回安装的 Java 版本。如果你没有安装 Java ,那么你可以选择一个包含 JavaWeka 包,安装 Weka 也会在你的电脑上安装 Java

验证计算机上的 Java 安装

第二步:下载并安装Weka

导航到 Weka 的下载页面,选择最适合您系统的版本。我会推荐下载最新的稳定版本。遵循 Weka 网站上提供的安装步骤。

第三步:发射Weka

安装完成后,在你的电脑上找到 Weka 并运行应用程序。这可以通过从搜索栏启动 GUI 或者双击下载的 jar 文件来完成。一旦启动, Weka 将呈现一系列视图,包括浏览器实验者知识流工作台简单 CLI 。点击 Explorer ,这将启动 Weka Explorer GUI,并让您使用内置的机器学习算法加载数据进行分类。

其他 GUI 提供诸如数据过滤、特征选择、关联规则提取和可视化之类的特征。我们只看探索者

从主屏幕选择浏览器

第四步:将输入数据集加载到Weka

在这个例子中,我正在加载超声心动图数据,这是一个查看心脏病发作受害者和字段(如他们在心脏病发作时的年龄)的数据集。这些数据可以从下面的 Git 存储库链接下载:

https://github . com/VSI pra/medium/blob/main/超声心动图-description.txt

https://github . com/VSI pra/medium/blob/main/超声心动图-预测. arff

https://github . com/VSI pra/medium/blob/main/超声心动图. arff

点击打开文件并选择*。待评估的飞机救援消防文件(超声心动图.飞机救援消防)

出现如上所示的浏览器窗口

您将看到这个数据集包括 64 个实例(行)和 8 个属性(列),最后一个属性 M 是 class 属性。

第五步:预处理加载的数据

导航到过滤器,然后选择选择。从这里的下拉选择中,您可以对数据集应用任何预处理,例如考虑缺失值、移除属性、改变格式(例如更改日期格式)、数据重新排序、值交换和应用过滤器。

第六步:选择你的分类算法,建立你的机器学习模型

点击分类标签,然后选择选择。出现分类器选择窗口。在分类器—贝叶斯下选择朴素贝叶斯

以下截图显示选择了naive Bayes模型。现在,接受默认的测试选项,即交叉验证,点击开始

一旦完成,分类的输出将被返回,如下所示。

到目前为止,我们所做的是使用我们的数据集建立一个朴素贝叶斯模型,并使用 10 重交叉验证测试该模型的性能。接下来,我们将研究如何预测类标签未知的实例的类标签。本练习中使用的数据集有 10 个元组,其中类标签未知,我们希望根据我们刚刚构建的模型对它们进行分类。

第七步:使用你的新机器学习模型对记录进行分类

分类选项卡,导航选择提供的测试集并设置您的测试偏好,然后点击设置,这将打开一个新的对话框。从这里选择打开文件,然后选择超声心动图-预测. arff

点击关闭,将返回 Weka 浏览器。点击更多选项并为输出预测选择明文并点击确定。现在,点击开始开始对未分类的元组进行分类。此步骤的输出将返回未分类的 10 个实例的预测。在下面的截图中,您可以看到所有 10 个实例的预测。

第八步:使用其他分类器建立分类模型,例如 J48 和 RandomForest ,比较各种模型对测试数据的准确性,观察哪一个表现最好

构建实体模型的过程通常需要迭代增强和理解底层数据集。要使用其他分类器构建模型,遵循与之前相同的步骤,但这次在步骤 6 选择树下的 J48 (确保选择交叉验证作为测试选项)。

一旦完成,您可以使用分类器运行测试,例如 RandomForestBagging 。比较和对比所有模型的精度,看看哪个模型最适合。对其他数据集运行最适合的模型,以更好地了解模型的表现以及是否需要更改。

希望这对你的机器学习之旅有所帮助!

产品经理的机器学习:界定智能特性的范围

原文:https://towardsdatascience.com/machine-learning-for-product-managers-scoping-a-smart-feature-1ce55437c9d6?source=collection_archive---------43-----------------------

项目的成败从第一天就开始了,确保你注意到了坑坑洼洼。

原始图片来自克里斯蒂娜·莫里路

这篇文章来自于我给我们的产品组织做的关于定义和构建 ML 特性的报告。这是我解开产品团队应该考虑的问题的系列文章中的第一篇,因为他们希望了解机器学习在哪里可以增强他们的用户旅程,在哪里可能会失败。

当谈到机器学习时,企业领导、产品经理和研究人员经常说不同的语言。

我很幸运地在产品开发和机器学习的交汇处度过了过去的四年。我管理过产品团队和机器学习研究小组。我还就采用有用的机器学习系统的企业战略向企业领导层提供建议。在帮助沟通世界的过程中,我亲眼目睹了这些不同的观点。

构建 ML 特性时的大部分困惑发生在项目的开始。目标是模糊的,数据不是预期的格式,或者度量是不明确的。这是产品经理以机器学习研究人员可以转化为明确定义的研究问题的方式表达用户需求的关键之处。今天,我们将着眼于构建您的团队可以投入执行的健壮的产品范围。

获得所有人对用户影响的认同

利益相关者对 ML 有不同的看法。营销组织可能想利用机器人自动化的最新媒体浪潮。工程可能会将其视为新技术堆栈的机会。公司领导层可能希望它能满足投资者的期望。

这些影响往往很强。但是不要把它们作为优先考虑的理由。相反,优先考虑什么会对你的产品的用户体验产生积极的影响。这一口号允许组织的不同成员在 ML 时就项目优先级达成一致。

一个好的功能必须让用户受益。好的产品设计源于对用户的同情和理解他们的需求。机器学习只是你工具箱中实现这一优势的一个工具。

除非你正在与 Deepmind、脸书研究或谷歌人工智能等理论人工智能研究小组合作,否则鼓励机器学习工程师也用这些术语说话。他们的研究努力将推动什么样的产品特征?用户如何受益?

我从三个主要角度来看智能特性。

节省时间

AbstractCRE 的接口向分析师建议租赁抽象。图片作者。

现在的用户有哪些花费大量时间的事情?你要求用户在平台的什么地方输入内容?有没有一种方法可以自动化输入或部分输入?简化输入的最常见方法之一是显示建议,而不是让用户从头开始写内容。

在 Gmail 中,花在撰写新邮件上的时间。这导致谷歌开发了提示性的句子补全。如果你开始写一个通常以某种方式结尾的句子,Gmail 会推荐那个结尾。点击 tab,它会为你完成。

在 AbstractCRE(我是一家公司的投资者)中,时间投资是手动阅读财产租约并提取业务指标:现金流、平方英尺等。这导致他们开发出暗示性的亮点。他们预测这些业务指标的候选,并要求分析师确认建议,而不是搜索整个文档。

这些方法为用户节省了时间和金钱,尤其是在数百或数千次交互中重复使用时。

在噪音中找到信号

亚马逊在无人机评论中对关键主题的突出强调:回归家园、易于使用等。图片作者。

你的软件是否有很多难以一一分析的内容?是否需要阅读段落才能获得整体印象?在数千张照片中搜索?ML 可以显示主题或精确定位用户正在寻找的东西,这比他们自己做要快得多。

在亚马逊上,一些产品有成千上万的评论,这些评论详细描述了他们的体验。用户在评估新购买的产品时,很难找到主要的决策标准。亚马逊通过对这些帖子的情绪进行积极或消极的评级,并根据他们讨论的主题进行分组,解决了这一需求。用户不会费力地浏览评论并失去上下文,而是会对贯穿多个评论的主题有所了解。

在苹果照片中,用户经常试图寻找埋藏在数万张过去照片中的记忆。人们通常记得一张照片的内容,但不记得它是什么时候拍的。作为回应,苹果公司最近推出了一个搜索栏,你可以描述照片的内容,并返回匹配的结果。尝试在相册中搜索“圣诞树”、“假期”或“日落”。

这些方法允许用户更容易地在噪声中找到信号。

做出更好的决定

谷歌地图交通预测。图片作者。

用户做决定有困难吗?他们会在用户旅程中停留在一个地方吗?他们缺少哪些信息来做出正确的决定?智能系统可以预测或量化人类自己难以识别的信息。

在谷歌地图上,用户会得到一些不同的路线建议和估计的旅行时间。然而,这个时间是静态的路线,不会考虑高峰时间或最近的事故。谷歌通过记录交通模式和训练模型来预测交通在整个旅行中的变化,从而解决了这一问题。一旦用户决定了一条路线,他们就不必考虑条件会如何变化。

在我工作的 Globality,我们提供了一个市场,业务用户可以在其中购买营销、咨询、法律、IT 和人力资源方面的高价值服务。这通常是采购组织的角色,当用户试图在多家供应商之间做出决定时,通常会陷入困境。该平台通过展示相关的过去工作经验、同事的评价等,帮助他们对这些公司进行评估。系统的观点导致在决策过程中有更高的转化率。

这些方法推动用户朝着正确答案前进。

定义合同范本

所有的机器学习都可以被认为是一个函数,就像高中代数中的 f(x)=y。你有一些输入,你期待一些输出。这反映了在更广泛的编程和计算机科学中使用的函数;除了它不是一个工程师填写函数行为,而是一个优化算法。这就是所谓的模型,输入数据和输出预测之间的关系构成了模型契约。

当做产品工作来确定 ML 特性的范围时,你需要非常清楚预期的输入和输出应该是什么样子。这决定了下游的一切:如何收集数据,如何进行数据建模,以及如何衡量成功。

你打算接受文本作为输入并预测情绪吗?超声波报告的照片和是否有肿瘤的报告?接受用户资料并估计他们将购买什么产品?我认为一份好的合同范本的晴雨表是,在同样的投入下,一个人能否得出好的结论。机器学习不是魔术,训练有素的人通常是伟大的模式识别者。我们可以读一段话,感悟感悟;放射科医师可以阅读检查结果并生成报告;我可以阅读用户简历以及他们过去的购买记录,并预测他们将购买的其他产品。

请注意,这个契约没有而不是包括将实际解决问题的算法。这是件好事。算法选择——无论是无监督学习、有监督学习还是强化学习——都可以被视为实现细节。你的机器学习伙伴会在研究过程中发现这一点。

想想人类是如何做到的,然后进一步打破这个契约

机器学习应该只用于你可以清楚地定义系统的输入和输出契约,但你不能清楚地表达机器如何做同样的事情。

让我们以自动驾驶汽车为例。当我驾驶我自己的汽车时,我扫描道路。然后我倾斜方向盘,踩油门,或者踩刹车。一旦你开了几个月或几年的车,这是很直观的。

如果我们使用与机器学习合同相同的框架:我们获得场景作为输入,我们向汽车的转向控制输出命令。机器学习模型计算出如何做中间的所有事情。

这在理论上很好,但在实践中会遇到一些问题。也就是说,我们如何评估系统的性能?它可以在高速公路上运行良好,但不能在城市街道上运行。这在旧金山可能行得通,但在奥斯汀却行不通。我可能会决定从左侧并入,而我的乘客可能会决定从右侧并入。在某些情况下,它可能会过度扭转车轮,而在其他情况下又会扭转不足。很难说模型在幕后做什么,因此也很难确信它会正确地将世界的复杂性转化为对轮子的指令。

在可能的情况下,你应该通过思考一个人实际上是如何解决问题的来将你的问题分解得更细。我们开车的时候到底在做什么?

  1. 确定我们视野中的障碍物,无论是道路上的还是我们旁边行驶的汽车。根据与前方车辆的距离,踩下油门和刹车。
  2. 看看路上有没有白色或黄色的车道标志。控制好方向盘,沿着道路的弯道行驶,保持在我们的车道内。线条的颜色和粗细代表不同的允许通过手数。
  3. 识别停车标志、限速标志或交通灯。然后,我们根据手势表达的意图调整速度或操纵。
  4. 祈求晴天。一旦你加上一点小雨,加利福尼亚的司机就太可怕了。

既然我们已经完成了 DMV 101,这如何转化为 ML 系统呢?

这些驱动阶段中的每一个都有两个步骤。第一步,你用你的感知来获得上下文的感觉。然后,你将上下文映射到一系列定义良好的规则上,这些规则是关于在你所看到的情况下你应该如何表现的。人类含蓄地建立这种关系,但机器可以明确地这样做。这正是 Waymo、Cruise、特斯拉和其他公司在自己的自动驾驶汽车系统中所做的事情。他们有预测周围环境的机器学习系统。然后,一个确定性的控制系统将环境转化为汽车的导航和物理运动。你把感知留给了机器学习,而把行动留给了确定性代码。

更好的示范合同导致更好的基准。假设您的车道检测工作正常,但您的障碍物检测需要改进。这有助于优先考虑您需要进一步研究和投资以改进这些子模型的地方。这也使得系统更容易解释,这对于确定错误模式和什么时候会失败有很大的帮助。

把你的机器学习模型分解成你能分解的最小的问题。否则,一旦你发货,你会对一些不可避免的边缘情况感到惊讶。

你如何在产品体验中创造良性循环?

在启动任何 ML 特性之前,您可能需要花时间来标记数据。这项工作提供了输入/输出契约的例子,您将需要训练和基准测试您的模型。一旦发布,你就有机会将大部分数据生成工作外包给你的用户。

最好的机器学习系统履行与用户反馈相同的模型契约,就像内部标记一样。用户与系统互动越多,你收集的有效数据就越多,模型就越好。这在产品特性中形成了良性循环。

创建这种反馈循环的一般方法是允许用户确认或否认预测。Spotify 为电台播放的每首歌曲提供拇指向上或拇指向下功能。这些分级会更改播放列表中稍后播放的歌曲。如果模型预测歌曲,它有理由相信你会喜欢它们。反对票是对模型的一个强烈信号,表明它的预测是错误的,因此应该在未来改变它们。一个向上的投票可能会鼓励它进一步倾向于这种类型。

另一种方法是标记不正确的结果,然后提交给后勤部门进行进一步的数据标记。在特斯拉的自动驾驶系统中,他们会记录用户被迫干预和接管方向盘的任何情况。它记录干预周围所有传感器的 30 秒剪辑;是什么导致了这个问题,汽车所犯的错误,以及人类的解决方案。这个实例被添加到一个队列中,Telsa 的员工标记周围的环境,并分析控制系统,以确定为什么它在路上出错。系统根据这些数据点进行训练,希望在类似的未来情况下做出更好的判断。

你应该将任何明确的反馈请求建立在今天和未来能够提供最佳用户体验的基础上。

系统会记住他们的反馈吗?它以某种方式投入使用了吗?据我所见,用户喜欢参与机器预测。看到一台机器正确地完成一项复杂的任务有一种神奇的感觉,当它失败时,他们会相对高兴地纠正它。但必须保证这样做会以某种方式立即影响他们的用户体验:接下来播放一首更相关的歌曲,提供正确的照片分组,或者阻止来自该发件人的所有垃圾邮件地址。如果它专门用于模糊的未来目的,他们会很快失去纠正它的胃口。

关闭

此时,您对您的产品功能和机器学习合同有了一个好主意。你可以让你的模型更容易解释,并创造一个良性循环。

请记住,您不需要在第一天就烘焙整个解决方案。产品在勾画功能和研究方向方面与机器学习研究人员有平等的伙伴关系。它将是迭代的;随着时间的推移,随着你了解的越来越多,合同范本可能会发生变化。但是一个基于专业知识的坚实的起点对于加速你的研究和开发工作是至关重要的。

在第二篇文章中,我们将看看如何定义机器学习项目的成功标准。请在 Medium 上关注我,了解更多关于人工智能和产品的文章。同时,看看这些其他的帖子:

机器学习:K 近邻分类器入门

原文:https://towardsdatascience.com/machine-learning-getting-started-with-the-k-neighbours-classifier-d7e6b25f2b09?source=collection_archive---------16-----------------------

机器学习

一个 Python 的现成代码,它实现了 scikit-learn 中的 K-neighbors 分类器,从数据预处理到生产。

作者图片

在本教程中,我将演示如何实现一个利用 K-neighbors 分类器的分类模型。完整的代码实现为一个 Jupyter 笔记本,可以从我的 Github 库下载。

作为一个示例数据集,我利用了 Kaggle Challenge 中提供的 Titanic 数据集:Titanic-机器从灾难中学习。这项挑战的目标是建立一个模型,根据乘客的一些特征,预测乘客在泰坦尼克号灾难中是否幸存。

加载数据集

数据集由三个文件组成:

  • train.csv —包含用于训练模型的数据集
  • test . CSV——包含执行新预测的未知样本
  • gender _ submission . CSV-输出数据集的示例。

在本教程中,我们只考虑 train.csv 文件。train.csv 文件由 891 行和 12 列组成:

作者图片

为每位乘客提供不同的功能。test.csv 文件与前一个文件类似,只是没有提供幸存列。

我们利用pandas库来加载数据集:

import pandas as pddf = pd.read_csv('data/train.csv')

查看这些列,可以将下列列用作输入要素:

  • Pclass
  • 年龄
  • SibSp
  • 票价
  • 上船了。

柱舱也可以作为输入特征插入。但是,在 test.csv 文件中,Cabin 列的几乎所有值都丢失了。为此,我们决定不插入作为输入特征。

预处理

首先,我们删除分析中不使用的列:

df = df.drop(['Cabin', 'Ticket'], axis=1)

然后,我们需要将所有分类特征转换为数字,并将范围[0,1]中的所有数字特征转换为数字。

对于每个特性,我们利用unique()函数列出该特性可能采用的所有可能值。例如,对于性特征,我们可以写:

df['Sex'].unique()

它给出了以下输出:

array(['male', 'female'], dtype=object)

这意味着:

  • 该特征只能采用两个值
  • 性别列中没有缺失值
  • 该特征是分类特征。

我们可以使用scikit-learn LabelEncoder将分类特征转换为数字,或者我们可以定义自己的函数,如下面的代码片段所示:

def get_gender(x):
    if x == 'male':
        return 0
    return 1

然后我们可以将我们的函数应用到性别列:

df['Sex'] = df['Sex'].apply(lambda x : get_gender(x))

一旦所有的分类特征都被转换成数字,我们需要映射[0,1]区间中的所有特征。这可以通过scikit-learn MinMaxScaler()类来实现。为此,我们定义了一个函数,所有功能都可以利用它:

from sklearn.preprocessing import MinMaxScalerdef scale_column(column, df):
    values = df[column].values

    scaler = MinMaxScaler()
    scaler.fit(values.reshape(-1, 1))
    return scaler.transform(values.reshape(-1, 1))

前面的函数将列名和数据集作为输入,对该列的值构建一个MinMaxScaler(),拟合缩放器并返回转换后的值。

scaler_column()功能可以如下调用:

df['Parch'] = scale_column('Parch', df)

但是,我们已经注意到,在 test.csv 文件的一些列中有一些丢失的值,这些值在 train.csv 文件中不存在。我们可以用一个虚构值替换缺失值,如下所示:

df['Age'] = df['Age'].fillna(value=0)

我们可以修改scale_column()函数来处理缺失值,如下所示:

def scale_column(column, df, nan=False):
    values = df[column].values

    scaler = MinMaxScaler()
    if nan:
        # also consider missing values in the test set
        new_values = np.append(values,0)
        scaler.fit(new_values.reshape(-1, 1))
    else:
        scaler.fit(values.reshape(-1, 1))
    return scaler.transform(values.reshape(-1, 1))

如果该列包含缺失值,则将nan变量设置为True,否则将其设置为False

预处理的完整代码如下:

df['Embarked'] = df['Embarked'].fillna(value='N')
df['Age'] = df['Age'].fillna(value=0)
df['Fare'] = df['Fare'].fillna(value=0)df['Sex'] = df['Sex'].apply(lambda x : get_gender(x))
df['Embarked'] = df['Embarked'].apply(lambda x : get_embarked(x))for i in ['Age', 'Parch', 'Fare', 'Pclass', 'SibSp']:
    df[i] = scale_column(i, df)

最后,我们可以删除所有剩余的 NaN 值:

df = df.dropna()

在训练集和测试集中拆分数据集

预处理之后,我们可以从数据集中提取输入(X)和输出(y ):

features = ['Pclass','Sex','Age','SibSp','Parch','Fare','Embarked']
X = df[features]
y = df['Survived']

我们可以将获得的数据集分为训练集和测试集,保留 33%的样本进行测试:

from sklearn.model_selection import train_test_splitX_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=42)

训练模型

现在我们准备训练模型。我们利用交叉验证的网格搜索来调整 K-neighbors 分类器。

我们定义要调整的参数网格:

from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import GridSearchCV
import numpy as npparameters = {  'n_neighbors'   : np.arange(3, 8),
                'weights'       : ['uniform', 'distance'],
                'metric'        : ['euclidean', 'manhattan', 'chebyshev', 'minkowski'],
                'algorithm'     : ['auto', 'ball_tree', 'kd_tree'],
            }

然后我们调整分类器:

classifier = KNeighborsClassifier()
clf = GridSearchCV(classifier, parameters, cv = 5)
clf.fit(X_train, y_train.values.ravel())

我们可以检索最佳模型:

model = clf.best_estimator_

测试模型

现在,我们可以在测试集上测试模型:

y_score = model.predict_proba(X_test)

并绘制 ROC 和预测/回忆曲线:

import matplotlib.pyplot as plt
from sklearn.metrics import roc_curve
from scikitplot.metrics import plot_roc,auc
from scikitplot.metrics import plot_precision_recall# Plot metrics 
plot_roc(y_test.values.ravel(), y_score)
plt.savefig('roc.png')
plt.show()

plot_precision_recall(y_test.values.ravel(), y_score)
plt.savefig('pr.png')
plt.show()

作者图片

作者图片

我们还可以计算精确度、召回率和准确度:

from sklearn.metrics import precision_score, recall_score, accuracy_scorey_pred = model.predict(X_test)precision = precision_score(y_test.values.ravel(),y_pred)recall = recall_score(y_test.values.ravel(),y_pred)accuracy = accuracy_score(y_test.values.ravel(),y_pred)print('Precision: ' , precision)
print('Recall: ' , recall)
print('Accuracy: ' , accuracy)

它给出了以下输出:

Precision:  0.7536200639348735
Recall:     0.7542372881355932
Accuracy:   0.7542372881355932

最终确定模型

我们可以通过在整个 X 数据集上再次训练来最终确定模型:

model.fit(X, y.values.ravel())

我们保存模型以备将来使用:

import pickle
pickle.dump(model, open("knn.sav", 'wb'))

摘要

在这篇初学者教程中,我已经演示了如何使用scikit-learn库建立、训练和完成 K-neighbors 分类器。应遵循以下步骤:

  • 数据预处理
  • 模特培训
  • 模型检验
  • 模型最终确定

如果你想了解我的研究和其他活动的最新情况,你可以在 TwitterYoutubeGithub 上关注我。

相关文章

机器学习走向量子化:令人兴奋的范式转变一瞥

原文:https://towardsdatascience.com/machine-learning-goes-quantum-a-glance-at-an-exciting-paradigm-shift-a80253cc577?source=collection_archive---------20-----------------------

来源

革命性的传统迁移学习,k-手段,和 CNN

量子计算是一个已经被广泛使用的时髦词汇。不幸的是,尽管它在流行文化和准科学的互联网社区中传播,它的能力仍然非常有限。

作为一个非常新的领域,量子计算向传统的经典计算模型提出了一个完全的范式转变。经典比特——可以是 0 或 1——在量子计算中被量子比特所取代,后者保存概率值。

依靠物理学在非常非常小的水平上的怪癖,一个量子位在每次被测量时,都以一定的概率被强制进入 0 或 1 的状态。例如,如果一个量子位处于0.85:0.15状态,我们会期望它在大约 85%的时间里测量为零,而在 15%的时间里测量为零。

虽然量子计算还有很长的路要走,但是机器学习是一个特别有前途的潜在途径。为了简单了解量子计算能够提供的计算能力,请考虑以下情况:

  • 一个量子位可以同时包含 0 和 1。因此,两个量子位可以一起保存四个值——状态 00、01、10 和 11 的值——而三个量子位可以保存八个,以此类推。
  • 因此——至少在理论上——需要 2 个 位来代表存储在 n 个量子位中的信息。

除此之外,量子电路的流体概率性质可能为深度学习提供独特的优势,深度学习通过网络从信息的概率流动和转换中获得力量。

量子机器学习正在流行。谷歌广受欢迎的深度学习框架 TensorFlow 最近推出了 TensorFlow Quantum

本文将介绍量子变异的三种机器学习方法和算法:迁移学习、 k 均值和卷积神经网络。它将试图用尽可能少的量子知识来做到这一点,并展示在设计机器学习的量子应用时的一些重要考虑。

量子迁移学习

迁移学习可能是深度学习最大的成功之一。鉴于深度学习模型需要大量的时间来训练,迁移学习提供了一种加快训练时间的宝贵方法。此外,与从头开始训练相比,使用转移解决方案的模型通常会得到更好的解决方案。

作为一个想法,迁移学习是相对简单的——一个“基础模型”,将被表示为 A ,在一个通用任务上被训练。然后,将表示为 B 的附加层块附加到 A 上。通常情况下,在添加 B 之前, A 的最后几层会被砍掉。然后,在特定数据集上“微调”该模型,其中A’(修改后的 A )为 B 提供了各种过滤器,以提取与手头特定任务相关的有意义的信息。

我们可以将为迁移学习构建“混合神经网络”的想法形式化如下:

  1. 在通用数据集上训练通用网络 A 以执行通用任务(预测某个标签)。
  2. 取通用网络 A 的一段A’,在A’上附加一个新块 BA' 是预训练的,因此应该被冻结(使其不可训练),而 B 是可训练的。
  3. 在特定数据集上训练这个A’b混合模型来执行特定任务。

来源

假设有两个组件,A’B ,并且每个组件都可以是经典或量子网络,那么混合神经网络就有四种可能的类型。

  • 古典到古典 (CC)。传统的迁移学习观。
  • 经典到量子 (CQ)。经典的预训练网络充当量子网络使用的过滤器。这种方法的实用性特别吸引人。
  • 量子到经典 (QC)。量子预训练网络充当过滤器供经典网络使用。或许这在未来量子计算发展更多的时候会更有可能。
  • 量子对量子 (QQ)。一个完全量子混合网络。在可行的层面上,现在可能不太可能,但以后可能会有希望。

经典到量子网络特别有趣和实用,因为大量的输入样本被预处理和细化到只有最重要的特征。这些信息特征可以由量子电路进行后处理,在目前的发展阶段,量子电路可以吸收比经典网络少得多的特征。

另一方面,量子转经典网络将量子系统作为特征提取器,一个经典网络用于进一步后处理这些提取的特征。QC 网络有两种使用情况。

  • 数据集由量子态组成。例如,如果需要预测量子态的某些信息,量子特征提取器似乎是处理输入的正确工具。或者,像分子和超导体这样的量子力学系统可以从量子特征提取器中受益。
  • 一台非常好的量子计算机胜过经典的特征提取器。

在测试中,作者发现这些量子经典混合模型可以获得与标准完全经典网络相似的分数。鉴于量子计算的早期阶段,这确实是一个有希望的消息。

量子卷积神经网络

卷积神经网络在图像识别以及信号处理等其他用例中已经变得很常见。然而,这些网络的规模在继续增长,量子计算可以大大加快经典机器学习方法的速度。

QCNN 算法与经典的 CNN 算法非常相似。然而,看到一些其他的考虑和改变被实现来允许量子方法是很有趣的。

首先,注意量子电路需要量子随机存取存储器,或 QRAM。这类似于 RAM,但是地址和输出寄存器由量子位组成,而不是位。它被开发成插入、更新或删除存储器中任何条目的时间是*O*(log²(*n*))

考虑设计的卷积“块”的前向传递,它类似于经典 CNN,但略有不同。

  1. 执行量子卷积。这就是量子操作发生的地方。这是在 QRAM 完成的,并且应用了非线性。
  2. 量子采样。执行采样,以便在很大概率已知所有位置和值的精确值的情况下,可以获得所有位置和值。因此,概率量子位值被“转换”成经典形式。这就是所谓的量子层析成像。
  3. QRAM 更新和汇集。需要更新 QRAM,并且在 QRAM 结构中完成池化(像卷积一样)。

采样步骤是经典向前步骤和量子向前步骤之间的主要区别——在量子算法中,出于性能(因为量子计算容易改变且敏感)和速度的实际目的,通常需要采样。

与经典细胞神经网络相比,量子细胞神经网络前向传递的加速是—

  • 内核数量呈指数增长
  • 输入维数的二次函数

这是一个很大的加速!

然而,这个采样步骤受到非线性函数必须有界的限制——很难从无限大的可能空间中采样,尤其是在量子世界中。因此,ReLU 函数可能被重新定义为上限为 y = 1,这样它看起来更像 sigmoid 函数的平面版本。

这确实是取样的一个缺点,也是使用量子算法时权衡利弊的有趣证明。

q 均值

首先,未标记的数据正以前所未有的速度充斥着数据空间。标签贵;需要以有效且高效的方式处理未标记的数据。与传统的经典无监督学习算法相比,量子计算可以提供显著的加速,这对于处理这种无监督信息流具有很大的意义。

传统的经典 k -means 算法常用于聚类。使用两个步骤之间的重复交替,该算法返回“质心”(每个聚类的中心)的位置:

  1. 标签分配。每个数据点都被分配了最近质心的标签。(质心位置最初是随机设置的。)
  2. 质心估计。将每个质心更新为分配给相应聚类的数据点的平均值。

现在,考虑δ- k -means,它可以被认为是kmeans 的一个嘈杂但仍然经典的版本。假设δ是预设参数。该算法在相同的两个步骤之间交替进行,但增加了一些噪声:

  1. 标签分配。每个数据点被分配一个距离小于δ的随机质心。也就是说,任何距数据点的距离小于阈值的质心都有相等的分配机会。
  2. 质心估计。在计算每个质心的位置期间,添加δ/2 高斯噪声。

最后,考虑一下 q -means,它是 k -means 的真正量子变体。作为一个快速的先决条件,回想一下量子位包含概率;与 bit 相比,这使得它们特别容易受到测量误差和环境噪声的影响。

  1. 标签分配。通过量子方法估计每个数据点到质心的距离。因为噪声,这个量子距离估计会有一定程度的噪声。然后,将每个数据点分配给一个质心。
  2. 质心估计。使用在 QCNN 方法的采样步骤中讨论的相同的量子层析成像思想,可以以高概率正确测量的状态被“转换”成经典形式。同样,这种操作本身也有一定程度的噪声。

q-的意思好像和k-的意思很像。然而,不同之处在于噪音;引入δ-k-意味着作为 q 的“经典版本”,意味着捕捉噪声元素。 q -means 背后的提议者证明,分析δ- k -means 可以揭示关于 q -means 算法如何运行的信息。

例如,当δ的(非零)值被适当地选择时,δ-k-均值算法通常收敛到达到类似于(如果不是更好的话)T2 k-均值算法的准确度的聚类。因此——尽管在量子变体中选择噪声量的自由度更小——人们可以期望 q 均值比 k 均值表现得更好。

类似地,δ- k -means 算法在其运行时间上是多对数的。那么, q -means 算法也是多对数的,是对 k -means 算法的加速,允许引入一些误差并放宽更严格和更精确的计算。

目前, q -means 太复杂,量子模拟器和量子计算机都无法测试。然而,通过δ-k-均值算法,有经验证据表明q-均值可以在与k-均值相似的水平上执行。

那么,量子集群的目的是什么呢?进一步的研究可能会考虑量子状态或数据的聚类,以及分子和其他非常小的现象的空间聚类——这是一项非常重要的任务。总的来说,在传统任务中,量子方法似乎也有超越经典方法的潜力。

感谢阅读!

你可能也会觉得这些文章很有趣。

</5-exciting-deep-learning-advancements-to-keep-your-eye-on-in-2021-6f6a9b6d2406> https://medium.com/mlearning-ai/mlearning-ai-submission-suggestions-b51e2b130bfb

🟠 成为作家

机器学习和国际象棋

原文:https://towardsdatascience.com/machine-learning-how-i-coded-my-own-python-chess-engine-c4c81bcb2a9a?source=collection_archive---------6-----------------------

我如何编写自己的 python 象棋引擎

杰斯温·托马斯Unsplash 上拍摄的照片

源代码: Github | 对战 A.I

快速介绍:

2020 年末,网飞发布了《女王的策略》,这是一部发生在 20 世纪 50 年代的电视节目,我们跟随一个年轻女性成长为最好的棋手的旅程。

然而,与主角贝丝·哈蒙不同,象棋并不是我最擅长的。所以我做了退而求其次的事情,构建了自己的 python 象棋引擎来弥补我糟糕的象棋技巧。

第一集:策略

当涉及到构建任何棋盘游戏引擎时,有多种策略:

  • 强化学习
  • 极大极小
  • 基于人类知识训练的 ML 模型

我选择了第二种和第三种策略的混合:作为一名数据科学家,我喜欢处理大型数据集和机器学习模型。此外,尽管有点慢,极大极小算法是一个相当可靠的算法,并在捕捉敌人的作品做得很好。强化学习简直太复杂了。

我的策略很简单:

  • 首先,使用机器学习模型,引擎将驳回给定棋盘的 50%的可能走法。它通过找到一步棋是“好棋”的概率来做到这一点。所有的移动都按照这个概率排序,只剩下第 50 个百分位数。
  • 其次,引擎将对剩余的移动执行最小最大算法。根据棋盘的复杂程度,搜索树会达到一定的深度。

第二集:数据

为了做出准确的预测,我们需要大量的数据。对于这个项目,我将使用我在 Kaggle 上找到的数据集。这个数据集是国际象棋大师以.pgn格式(可移植游戏符号)进行的数千场游戏的集合。

下一步是从所有的游戏中提取所有的招式,并标记为好或坏。

在我看来,‘好棋’是赢家在游戏过程中的某个时刻走的一步棋。“坏棋”是赢家选择不走的合法棋。

这个 python 脚本完成了工作,给我留下了一个全新的.csv数据集。

你可以在 Kaggle 和 Github 上找到我的数据集:

https://www.kaggle.com/ethanmai/chess-moves https://github.com/iAmEthanMai/chess-games-dataset

然后,我们需要将数据帧导入我们的 Jupyter 笔记本。我们可以简单地在第一个代码单元中运行以下命令:

In[1]: import pandas as pd
       df = pd.read_csv('data.csv')
       print(df.shape)Out:   (1600000,193)

数据框架的列如下:

  • 前 64 列代表当前棋盘的 64 个方块。
  • 从 65 到 128 的列代表移动的开始位置:如果一个棋子从那个方块移动,则为 1.0,否则为 0.0。
  • 从 130 到 192 的列代表移动的结束位置:如果一个棋子移动到那个方块,则为 1.0,否则为 0.0。
  • 最后一列是标签:如果这是一步好棋,则为真,否则为假。
In[2]: df.head()

df.head()

第三集:模特

在这个项目中,我将使用 tensorflow 线性分类器。这是一个非常常见的模型,因为它被很好地记录下来并且非常有性能。

In[3]: linear_est = tf.estimator.LinearClassifier(feature_columns)

第四集:训练

要训练估计器,我们可以简单地运行以下命令:

In[4]: linear_est.train(input_function)

关于这个项目的机器学习部分的更多细节,请确保查看我的 Colab 笔记本,在那里你可以找到所有的源代码。

第五集: Minimax

极大极小算法将探索合法移动的递归树直到某一深度,并使用评估函数评估叶子。

然后,我们可以根据回合将最大或最小的子节点值返回给父节点。这允许我们最小化或最大化树的每一层的结果值。点击了解更多关于 Minimax 的信息。

评估功能寻找两个标准:

  • 一块的类型。例如,骑士比卒更有价值。
  • 棋子的位置。例如,一个骑士在棋盘中间很强,而国王很脆弱。

评价函数算法

第六集:游戏处理

为了获得合法的移动和显示棋盘,我使用了 python-chess 库。您可以通过运行以下命令用 pip 安装它。

!pip3 install python-chess

这个库让事情变得非常方便,因为它消除了硬编码国际象棋规则和微妙之处的麻烦。

第七集:播放

剩下唯一的事情就是玩游戏。如果你想试一试,运行所有的代码单元,你应该可以开始了…祝你好运!

https://colab.research.google.com/github/iAmEthanMai/chess-engine-model/blob/main/python_chess_engine.ipynb#scrollTo=dsacAJ-5gkN0 [## 和我的人工智能比赛

python-chess-engine.ipynb](https://colab.research.google.com/github/iAmEthanMai/chess-engine-model/blob/main/python_chess_engine.ipynb#scrollTo=dsacAJ-5gkN0)

结论:

谢谢你留下来,我希望你喜欢这个项目。

欢迎在 GithubKaggleLinkedin 上与我联系。

用 PyCaret 在 Alteryx 中进行机器学习

原文:https://towardsdatascience.com/machine-learning-in-alteryx-with-pycaret-fafd52e2d4a?source=collection_archive---------27-----------------------

使用 PyCaret 在 Alteryx Designer 中训练和部署机器学习模型的分步教程

介绍

在本教程中,我将向您展示如何在一个非常流行的 ETL 工具 Alteryx 中使用 PyCaret 来训练和部署机器学习管道,PyCaret 是一个用 Python 编写的开源、低代码的机器学习库。本教程的学习目标是:

👉PyCaret 是什么,如何入门?

👉什么是 Alteryx Designer,如何设置?

👉在 Alteryx Designer 中训练端到端机器学习管道,包括数据准备,如缺失值插补、一键编码、缩放、转换等。

👉部署经过训练的管道,并在 ETL 期间生成推理。

PyCaret

PyCaret 是一个开源、低代码的机器学习库和端到端的模型管理工具,内置于 Python 中,用于自动化机器学习工作流。PyCaret 以其易用性、简单性以及快速高效地构建和部署端到端机器学习管道的能力而闻名。要了解更多关于 PyCaret 的信息,请查看他们的 GitHub

Alteryx 设计器

Alteryx Designer 是由 Alteryx 开发的专有工具,用于自动化分析的每个步骤,包括数据准备、混合、报告、预测分析和数据科学。您可以访问任何数据源、文件、应用程序或数据类型,并体验包含 260 多个拖放构建块的自助服务平台的简单性和强大功能。你可以从这里下载 Alteryx Designer 的一个月免费试用版。

https://www.alteryx.com

教程先决条件:

对于本教程,您将需要两件东西。第一个是 Alteryx 设计器,这是一个桌面软件,你可以从这里下载。第二,你需要 Python。获得 Python 最简单的方法是下载 Anaconda 发行版。要下载,点击这里。

👉我们现在准备好了

打开 Alteryx Designer,点击文件→新建工作流

Alteryx 设计器中的新工作流

在顶部,有一些工具,您可以在画布上拖放,并通过将每个组件相互连接来执行工作流。

资料组

对于本教程,我使用 PyCaret 的存储库中的一个名为 insurance 的回归数据集。你可以从这里下载数据。

样本数据集

我将创建两个独立的 Alteryx 工作流。第一个用于模型训练和选择,第二个用于使用训练好的管道对新数据进行评分。

👉模型训练和选择

让我们首先从输入数据工具读取 CSV 文件,然后是 Python 脚本。在 Python 脚本内部执行以下代码:

**# install pycaret** from ayx import Package
Package.installPackages('pycaret')**# read data from input data tool**
from ayx import Alteryx
data = Alteryx.read("#1")**# init setup, prepare data**
from pycaret.regression import *
s = setup(data, target = 'charges', silent=True)**# model training and selection** best = compare_models()**# store the results, print and save**
results = pull()
results.to_csv('c:/users/moezs/pycaret-demo-alteryx/results.csv', index = False)
Alteryx.write(results, 1)**# finalize best model and save**
best_final = finalize_model(best)
save_model(best_final, 'c:/users/moezs/pycaret-demo-alteryx/pipeline')

该脚本从 pycaret 导入回归模块,然后初始化setup函数,该函数自动处理 train_test_split 和所有数据准备任务,如缺失值插补、缩放、特征工程等。compare_models使用 kfold 交叉验证训练和评估所有估计器,并返回最佳模型。

pull函数以数据帧的形式调用模型性能指标,然后保存为驱动器上的results.csv,并写入 Alteryx 中 Python 工具的第一个锚点(以便您可以在屏幕上查看结果)。

最后,save_model将包括最佳模型在内的整个转换管道保存为 pickle 文件。

培训工作流程

当您成功执行该工作流时,您将生成pipeline.pklresults.csv文件。您还可以在屏幕上看到最佳模型的输出及其交叉验证的指标。

这就是results.csv包含的内容:

这些是所有模型的交叉验证指标。在这种情况下,最好的模型是 梯度推进回归器

👉模型评分

我们现在可以使用我们的pipeline.pkl对新数据集进行评分。由于我没有标签为 insurance.csv 的单独数据集,我要做的是删除目标列,即 费用 ,然后使用训练好的管道生成预测。

评分工作流程

我已经使用选择工具移除目标列,即charges。在 Python 脚本中执行以下代码:

**# read data from the input tool**
from ayx import Alteryxdata = Alteryx.read("#1")**# load pipeline** from pycaret.regression import load_model, predict_model
pipeline = load_model('c:/users/moezs/pycaret-demo-alteryx/pipeline')**# generate predictions and save to csv** predictions = predict_model(pipeline, data)
predictions.to_csv('c:/users/moezs/pycaret-demo-alteryx/predictions.csv', index=False)**# display in alteryx** Alteryx.write(predictions, 1)

当您成功执行该工作流时,它将生成predictions.csv

预测. csv

即将推出!

下周我将深入探讨 PyCaret 的更多高级功能,您可以在 Alteryx 中使用这些功能来增强您的机器学习工作流。如果你想自动收到通知,你可以在媒体LinkedInTwitter 上关注我。

PyCaret —作者图片

PyCaret —作者图片

使用 Python 中的这个轻量级工作流自动化库,您可以实现的目标是无限的。如果你觉得这很有用,请不要忘记给我们 GitHub 库上的⭐️。

想了解更多关于 PyCaret 的信息,请关注我们的 LinkedIn 和 Youtube。

加入我们的休闲频道。此处邀请链接

重要链接

文档
博客
GitHub
stack overflow
安装 PyCaret 笔记本教程 贡献于 PyCaret

更多 PyCaret 相关教程:

[## 使用 PyCaret 编写和训练您自己的自定义机器学习模型

towardsdatascience.com](/write-and-train-your-own-custom-machine-learning-models-using-pycaret-8fa76237374e)

医学中的机器学习——期刊俱乐部

原文:https://towardsdatascience.com/machine-learning-in-medicine-journal-club-5696e5b71f3d?source=collection_archive---------13-----------------------

思想和理论

对临床文献中使用机器学习技术的批判性评价

呼吁建立科学期刊中报告机器学习模型的文档标准

照片由德克·海斯Unsplash 上拍摄

简介

过去几年,机器学习技术在生物医学研究中的使用呈爆炸式增长,PubMed 上以“机器学习”一词为索引的期刊论文数量从 2015 年的 3200 篇激增至 2020 年的 18000 篇。虽然由于机器学习,重大的科学进步已经成为可能,但大多数机器学习算法的内部工作对许多临床医生来说仍然是陌生的,他们中的大多数人非常熟悉传统的统计方法,但几乎没有接受过高级计算机算法的正式培训。不幸的是,期刊审稿人和编辑有时满足于接受机器学习作为一种黑箱操作,并且无法以应用于其他临床和基础科学研究的相同审查水平来分析机器学习模型产生的结果。

pubmed.gov 上被索引为“机器学习”的期刊文章数量。图片作者。

这个期刊俱乐部的目标是帮助读者发展必要的知识和技能,以消化和评论涉及使用机器学习技术的生物医学期刊文章。如果评审者不理解这些算法是如何工作的,他/她很难知道该问什么问题。我们不会关注研究的内容或临床意义,而是关注与机器学习技术相关的方法和技术细节。我们希望强调研究人员在临床研究中结合机器学习时犯的一些陷阱和常见错误,并加强科学研究出版物中批判性评估的重要性。

胡 C、安朱尔 V、萨布 K、雷迪 KR、奥利里 J、坦登 P、王 F、加西亚-曹 G、卡马特 PS、赖 JC、比金斯 SW、法伦 MB、图鲁瓦特 P、苏布拉马尼安 RM、马利亚克卡尔 B、巴尔加斯 H、萨克 LR、伊耶 RK、巴贾杰 JS。使用机器学习对肝硬化患者再入院和死亡的预测性较低。胃肠病学杂志。2021 年 2 月 1 日;116(2):336–346.PMID: 33038139。

我们选择了这篇最近发表在《美国胃肠病学杂志》上的论文作为我们杂志俱乐部的第一篇文章,因为它强调了建立一个正式标准的必要性,或者至少是一个被广泛接受的惯例,以记录机器学习模型,就像大多数系统综述或元分析报告他们的方法和发现一样。

对于那些不熟悉胃肠病学领域的人来说,美国胃肠病学杂志是美国胃肠病学学会的官方杂志,该学会本身就是该领域的顶级专业学会。该期刊被广泛认为是该领域的顶级期刊之一,2018 年的影响因子为 10.241。

背景

与普通人群相比,肝硬化患者出院后再次入院和死亡的风险更高,这可能归因于疾病的复杂性以及该患者群体特有的其他社会心理/社会经济因素。能够客观地评估单个患者的再入院和死亡风险在出院计划和护理过渡方面具有临床意义。

终末期肝病模型(MELD)最初被开发用于预测接受选择性经颈静脉肝内门体分流术的患者的 3 个月死亡率,现已被广泛研究并在外部被验证为肝硬化患者死亡率的预测因子

MELD 分数。图片作者。

尽管 MELD 评分是最广泛使用的肝病严重程度的客观指标,但它远非完美。它在低范围内的辨别能力(<15) is very poor, as demonstrated by the nearly flat mortality curve in Figure 5 of 本文)。我们还知道,MELD 评分的区分能力取决于肝病的潜在病因,如本文的表 1 所示,以及 MELD 评分未涵盖的其他临床变量。

假设和具体目标

在这篇文章中,作者假设机器学习模型可以用来预测这些风险,并且这些模型将优于“传统的临床数据和生物统计学”。

该论文的具体目的是使用机器学习“预测多中心北美住院肝硬化队列中 30 天和 90 天的再入院和死亡”。

方法

  • 研究形式——多中心回顾性观察队列研究。
  • 研究人群——北美终末期肝病研究联盟(NASCELD)中的受试者,包括 14 家三级医院。
  • 纳入标准——非选择性入院的确诊肝硬化患者。
  • 排除标准——HIV 感染和既往器官移植。
  • 研究期——出院后 90 天。

数据收集

入院变量——人口统计学、肝硬化严重程度、MELD、MELD-Na 和 Child-Pugh 评分、入院时的全身炎症反应综合征、入院时的药物治疗和入院原因。

医院病程变量——继发感染、个体器官衰竭和慢加急性肝衰竭。

出院变量——实验室值和肝硬化严重程度,如 MELD 和药物。

模型开发

本文包括三种不同的机器学习技术,包括逻辑回归、支持向量机和随机森林。

逻辑回归(LR)

支持向量机(SVM)

  • sklearn.svm.SVC 使用默认的 RBF 核和默认的逆正则化强度 1.0。

随机森林(RF)

  • 仅使用 20 个估计器和最大深度 5。所有的超参数都被假定为默认值。

有趣的是,作者使用 10 重交叉验证,仅将显著不同的特征纳入模型(p <0.05) between subjects with positive outcomes and subjects with negative outcomes. The rationale for this decision was not mentioned in the paper.

Model performance was evaluated based on the area under the 受试者工作特征曲线 (AUC)。

结果

最终分析包括 2170 名受试者,平均年龄为 57 岁,大多数(61%)为男性,大多数(79%)为白人。平均 MELD-Na 得分为 20.7 分。30 天再入院率为 28%,90 天再入院率为 47%。90 天死亡率为 13%。

尽管论文的很大一部分致力于讨论所获得的各种临床变量,但论文中只有表 4-6 与机器学习相关,这里复制了一部分用于讨论。

表 4–6 的部分内容。图片作者。

作者得出结论,LR 模型和 RF 模型表现最好。他们认为,这两个类别之间的许多临床变量可能有显著的重叠(再入院与非再入院,死亡与非死亡),使得算法难以定位最佳超平面。他们还提出,LR 模型和 SVM 模型的性能可能受到许多分类特征的影响。最重要的是,作者得出结论,所有三种机器学习技术创建的完整模型仅比仅使用 MELD-Na 分数创建的模型略好,并且“多种人工智能技术通过机器学习的预测能力不是最理想的”。

文章评论

在我们深入研究文章内容之前,值得注意的是,“机器学习”这个术语在文章的正文中只使用了一次,在下面的句子中:“我们需要机器学习和人工智能(AI)技术等其他方法来预测这些结果”。在整篇文章中,作者将机器学习模型称为“AI 模型”。虽然“人工智能”和“机器学习”之间的区别纯粹是语义上的,但它在一篇发表在顶级 GI 期刊上的文章中的误用引起了人们的怀疑,即作者和编辑可能对该主题不是非常熟悉。想象一下,如果我们正在阅读一篇关于氩等离子体凝固术在动静脉畸形治疗中的应用的文章,但作者一直将其称为电外科手术。根据记录,人工智能是一个总括术语,用于描述使用技术模仿自然智能。机器学习是人工智能的应用之一。其他应用包括机器人、计算机视觉、语音识别和自然语言处理。

人工智能领域。图片作者。

绩效指标

让我们从文章的主要结论开始分析,即机器学习模型对肝硬化患者的再入院或死亡的可预测性较低。如果我们仔细查看表 4、5 和 6 中报告的数字数据,我们可以看到,在所有三种结果(30 天、90 天再入院和 90 天死亡率)、所有三种机器学习技术(LR、SVM 和 RF)以及两种性能指标(准确性和 AUC)方面,完整模型和仅 MELD-Na 模型之间没有统计学上的显著差异。事实上,所有三种机器学习技术的性能指标彼此非常接近,尽管这些模型都是使用默认的超参数构建的,没有经过优化。我们怀疑这种奇怪的观察结果可能是由于性能指标选择不当造成的。

这里一个重要的学习点是,准确性和 AUC 不应该在结果不平衡的数据集中用作性能指标。使用准确性更容易证明这个缺陷。想象一下,我们正在建立一个模型来预测一种患病率为 99%的罕见疾病,尽管在实践中完全没有用。事实上,我们可以看到 30 天再入院模型和 90 天死亡率模型的准确性非常接近 30 天未再入院率(100%-28% = 72%)和 90 天生存率(100%-13%=87%)。如本文所述,AUC 在面对高度不平衡的数据集时也会遇到同样的问题。从本质上讲,表 4、5 和 6 中的结果并没有告诉我们这些模型的性能,只是基础数据集非常不平衡。作者应该做的是使用一条精确回忆曲线F-1 分数,它们不受班级不平衡的影响。

ROC 曲线和 PR 曲线。图片作者。

文章中使用这两个性能指标的方式还有另一个问题。请记住,机器学习模型的输出是一个数值,代表某个主题属于某个类别的概率。ROC 曲线和 PR 曲线本质上是各种性能指标(ROC 的 TPR 和 FPR,PRC 的精度和召回)随着概率从 0 增加到 1 的变化的图形表示。因此,这些曲线下的面积对应于模型的内在鉴别能力。在我们可以在临床实践中实际应用该模型之前,我们必须首先确定一个适当的概率阈值,该阈值取决于不同错误分类的相对成本(例如,结肠镜检查中遗漏癌症诊断的成本与进行不必要的活检的成本)。包括准确度和 F-1 分数在内的某些性能指标特定于特定的概率阈值(即,它们代表曲线上的单个点)。它们不应该用于比较不同机器学习模型的性能。在这篇文章中,作者没有披露与准确性相关的概率阈值是如何确定的(假设他们只是使用默认值 0.5),他们似乎也使用准确性作为模型区分能力的替代措施。

超参数调谐

这篇文章最奇怪的部分是,所有三个机器学习模型本质上都是使用默认的超参数(除了随机森林模型的树计数和树深度)构建的。这些默认超参数不太可能产生最佳模型,尤其是考虑到特征的复杂性。没有解释为什么作者为随机森林模型选择如此低的树数 20 和相对浅的树深 5。这个缺陷是为什么应该有一个正式标准来记录机器学习模型开发过程的明显例子。作者评估的超参数范围应明确记录。理想情况下,补充材料中应有图表显示与每个超参数相关的模型性能变化。应该清楚地解释选择异常高或异常低的超参数的理由。对于 LR 模型,应该使用逐步特征选择进行特征选择,并且应该清楚地报告过程中每一步的相关统计测量。对于 RF 模型,应报告基于杂质的特征重要性,以确保所包含的特征确实有助于最终模型。底线是,应该向文章的评论者和读者提供足够的信息,以便在必要时复制和验证作者的主张,就像任何其他基础科学和临床研究论文一样。

数据预处理

本文的另一个主要问题是缺少关于数据预处理的文档。作者在补充内容中提到“预处理包括两个主要步骤:清理数据集,然后挖掘新特征。清理数据集涉及处理数据中不正确、冗余或缺失的值,而特征挖掘涉及从数据中识别新特征”。在这些数据预处理步骤中进行的详细操作,如发现缺失数据的比例和使用的插补方法,没有披露。因为特征由各种范围和基数的数字和分类特征组成,所以在应用于模型之前,可能需要对数字特征进行归一化,并对分类特征进行编码。如上所述,应该公开准确的标准化参数和编码方案,以便审查者和读者在必要时可以复制模型。

总结

本文试图解决一个临床上重要的问题,即使用机器学习技术预测肝硬化患者的再住院和死亡率。由于该任务本质上是一个简单的分类问题(readmit vs. not,death vs. not),因此使用简单的机器学习分类模型,包括逻辑回归、支持向量机和随机森林,似乎是合适的。作者能够从一个完善的多中心队列中收集大量高质量的训练数据,这有助于最大限度地提高该研究的外部有效性。

不幸的是,这篇文章被机器学习模型的实现和分析中的几个主要问题所困扰。缺少关于数据预处理和模型开发步骤的重要文档,使得评审者和读者几乎不可能重现/验证研究结果。模型没有完全优化(或者至少没有优化过程的文档)。使用的性能指标,即准确性和 AUC,不适合本文的目的(请记住,准确性是一个取决于概率阈值的点测量,而 AUC 在高度不平衡的数据集中是不准确的)。

尽管发表在顶级 GI 期刊之一,但这篇文章在应用机器学习技术方面包含足够多的缺陷,足以使其发现和结论无效。应该鼓励研究人员尝试建立其他机器学习模型来预测肝硬化患者的再入院和死亡率。

学习要点

  • 在高度不平衡的数据集中,接收器操作特征曲线下的面积和精确度可能不合适。
  • 应清楚记录与机器学习模型开发流程相关的详细信息,包括缺失值插补、标准化、编码和超参数调整。

医学中的机器学习——期刊俱乐部 II

原文:https://towardsdatascience.com/machine-learning-in-medicine-journal-club-ii-2796d9c1973f?source=collection_archive---------45-----------------------

对临床文献中使用机器学习技术的批判性评价

当心那些将苹果比作橙子,或将客机比作汽车的说法。

丹尼尔·法齐奥Unsplash 上拍摄

介绍

欢迎来到医学杂志俱乐部的机器学习的另一个入口。让我们提醒大家,这个期刊俱乐部的目标是帮助读者发展必要的知识和技能,以消化和评论涉及使用机器学习技术的生物医学期刊文章。尽管它的一些术语和概念听起来可能很奇怪,但机器学习不是魔法,我们应该像对待任何其他临床研究一样,以同样的怀疑态度评估这些技术的使用所带来的发现。为了这个期刊俱乐部的目的,我们将不会关注研究的内容或临床意义,而是关注与机器学习技术相关的方法和技术细节。一路上,我们希望强调一些陷阱和常见错误,并消除一些与机器学习相关的常见误解。

文章

郭 A,马祖姆德 NR,DP,福拉克尔 RE。用机器学习预测电子健康记录中肝硬化患者的死亡率。公共科学图书馆一号。2021 年 8 月 31 日;16(8):e0256428。doi:10.1371/journal . pone . 0256428 . PMID:34464403;PMCID: PMC8407576。

为了继续我们上一篇期刊俱乐部条目中的肝硬化主题,我们选择了 PLoS One 最近发表的这篇论文,因为这篇文章的作者旨在使用类似的技术回答上一篇文章提出的相同问题,但他们的结论完全相反。我们应该试着理解这些作者的不同做法导致了不同的结果。

《公共科学图书馆·综合》是一个同行评审、开放获取的在线期刊,旨在让所有人都能免费获取科学出版物。该杂志发表科学、工程、医学和社会科学所有领域的研究。尽管该杂志没有公布其影响因子,但它被认为是医学领域中声誉卓著且具有合理选择性的杂志。

背景

肝硬化患者在首次诊断时通常具有很少症状的亚临床疾病。这种疾病通常会经历多年缓慢和惰性的过程,但在一小部分患者中,疾病可能会发展,这些患者可能会在没有警告的情况下迅速失代偿。能够预测单个患者的死亡风险在预防失代偿事件和对住院和门诊患者管理进行分类方面具有临床意义。

终末期肝病模型(MELD)最初被开发用于预测接受选择性经颈静脉肝内门体分流术患者的 3 个月死亡率,现已被广泛研究和外部验证为肝硬化患者死亡率的预测因子。

MELD 分数。图片作者。

尽管 MELD 评分是最广泛使用的肝病严重程度的客观指标,但它远非完美。它在低范围内的辨别能力(<15) is very poor, as demonstrated by the nearly flat mortality curve in Figure 5 of 本文)。我们还知道,MELD 评分的区分能力取决于肝病的潜在病因,如本文的表 1 所示,以及 MELD 评分未涵盖的其他临床变量。因为最初的模型仅被验证用于预测 90 天的死亡率,所以它在预测长期死亡率方面的表现是不确定的。

假设和具体目标

在这篇文章中,作者假设机器学习模型在预测肝硬化患者的短期和长期死亡率方面优于 MELD 评分

本文的具体目的是使用机器学习来预测一个大型学术肝移植中心肝硬化队列中 90 天、180 天和 365 天的死亡率。

方法

  • 研究形式——单一回顾性观察队列研究。
  • 研究人群——医院电子病历系统中包含的受试者。
  • 纳入标准-在 2021 年 1 月 1 日至 2019 年 12 月 31 日之间添加了初始诊断代码为肝硬化的成年患者。
  • 排除标准—无。
  • 研究期——任何肝硬化相关诊断代码首次出现后的 365 天。
  • 结果——90 天、180 天和 365 天的全因死亡率。
  • 特征-人口统计、首次诊断代码时或之前测量的实验室数据,以及与初次诊断相遇相关的信息(例如,相遇类型、确切诊断等。)

数据预处理

与前一篇文章不同,本文作者更详细地描述了数据预处理步骤。缺失值超过 10%的特征不包括在模型中。否则,多重插补(大概是sk learn . impute . iterative impute r)用于数字特征,而模式插补用于分类特征。作者还使用均值插补而不是多重插补建立了单独的模型,并在文章的补充内容中提供了结果。

作者还承认,由于整体死亡率较低,训练数据集非常不平衡。为了解决这种类别不平衡,作者采用了合成少数过采样技术(SMOTE) 来生成在模型训练阶段使用的合成样本。

合成少数过采样技术。图片作者。

车型开发

本文包括三种不同的机器学习技术,包括逻辑回归、随机森林和深度神经网络

逻辑回归

随机森林(RF)

  • 假设使用具有 500 个估计器的sk learn . ensemble . randomforestclassifier实现,并且每个估计器的特征数量被设置为特征总数的平方根。所有的超参数都被假定设置为默认值
  • 树计数优化:200、500 和 700 估计器
  • 最大功能数优化:自动、平方根和 log2

深度神经网络(DNN)

  • 大概是用 keras.models.Sequentialkeras.layers.Dense 实现的,每层有 4 个隐藏层和 128 个节点。Sigmoid 函数用于输出层,ReLu 函数用于隐藏层。使用二值交叉熵损失作为损失函数。Adam optimizer 用于 512 的小批量。
  • 网络深度优化:2 至 8 层
  • 层维度优化:128 和 256 个节点
  • 批量优化:64、128 和 512。

基于受试者操作特征(ROC) 曲线下面积(AUC)、总体准确性和使用 5 重交叉验证的 F1 得分,对模型性能进行评估。

结果

最终分析包括 34,575 名受试者,平均年龄为 60.5 岁,性别分布均匀,大多数(77.5%)为白人。入院时平均 MELD-Na 评分为 11.5 分。90 天、180 天和 365 天的死亡率分别为 5.2%、6.4%和 8%。

最终,41 个特征被包含在完整的模型中。作者还创建了仅使用钠、肌酐、总胆红素和 INR(MELD-Na 评分的组成部分)的部分模型。

图片由郭等人提供。艾尔。PLoS One 。根据知识共享署名许可转载。

文章的图 2 显示了三个完整模型和三个部分模型在预测 90 天、180 天和 365 天死亡率方面的性能。任何敏锐的读者都会立即注意到图 2a、2b 和 2c 看起来几乎一模一样。在所有三个结果中,每个模型的 AUC 值也非常接近。

作者基于 F1 分数认为,在所有三个结果中,完全 RF 模型和完全 DNN 模型比完全 LR 模型表现更好。

三款车型的 F1 成绩。图片作者。

使用相同的性能指标,作者还认为三个完整模型优于三个部分模型。作者通过计算三个完整模型的特征重要性,进一步研究了每个特征的贡献。作者总结说,虽然 MELD-Na 变量非常重要,但其他特征和实验室值也“在预测中发挥着重要作用”

文章批判

我们将从表扬作者做得对的事情开始我们的评论。与以前的文章不同,这篇文章在方法部分提供了更多的细节,以允许评审者和读者重现模型。作者甚至提供了联系信息,以便索取原始数据集的副本。唯一可以做得更好的是在补充材料中提供生成模型的原始代码。在没有原始代码的情况下,我们必须做出某些假设,例如用于生成这些模型的默认超参数值。

我们还应该赞扬作者描述了对模型所做的优化。这当然表明作者已经做出了合理的努力来最大化他们模型的性能,超参数是基于系统分析选择的,而不是凭空捏造的。这对于 DNN 模型尤其重要,因为人工网络的性能可能会因所使用的超参数而有很大差异。如果我们吹毛求疵,我们可能会要求对 RF 模型的树深度超参数进行额外的优化,这通常会产生额外的性能改进。我们可能还会要求对 Adam 优化器设置进行额外的优化,这在大多数情况下也会影响模型的性能。理想情况下,作者将在文章的补充材料中包括这些优化的结果,以表明最终的超参数值确实与每个模型的峰值性能相关。

最后,我们应该赞扬作者在训练阶段通过使用 SMOTE 技术来解决班级不平衡的努力。SMOTE 和其他过采样技术,如 AdaSyn、Borderline SMOTE 和 SVM-SMOTE,被广泛认为是处理类别不平衡的最先进技术,而已被证明可以改善学习

车型对比

我们对这篇文章的主要批评源于论文结论部分的一句话,即“机器学习和深度学习模型优于肝硬化患者风险预测的当前标准”。作者声称,他们的机器学习模型在预测短期和长期死亡率方面优于 MELD-Na 评分,MELD-Na 评分是肝硬化患者风险预测的当前标准。论文的引言部分也多次提到 MELD-Na 评分的局限性。然而,如果我们花点时间仔细考虑方法部分和结果部分,我们会意识到该研究从未被设计成直接比较机器学习模型的性能和 MELD-Na 分数的性能。作者所做的是将包含 41 个特征的完整模型与仅包含 4 个特征的部分模型进行比较。除非额外的 37 个特征都是由随机生成的值组成的,否则完整模型比部分模型表现得更好就不足为奇了。支持作者声称机器学习模型优于 MELD-Na 评分的唯一方法是将模型应用于一个原始数据集,该数据集验证了 MELD 评分作为肝硬化患者的死亡率预测指标。不幸的是,这篇论文没有这样做。作者可能声称他们的完整模型在 F1 分数的基础上表现相当好,但他们不能声称他们优于 MELD-Na 分数,除非他们能够证明他们的部分模型与 MELD-Na 分数相当。

我们也反对作者声称 RF 模型和 DNN 模型基于 F1 分数优于 LR 模型。我们将在后面讨论性能指标的问题,但我们必须首先强调直接比较不同建模技术的性能是徒劳的,这在最近的生物医学文献中不幸地变得相当常见,例如这个这个这个。决策树模型,如随机森林和梯度提升机器,受到每个决策点一次只能考虑一个特征的限制。逻辑回归模型受限于特征变量和结果变量的对数优势之间的线性关系。神经网络不受这些限制。给定足够数量的神经元和层,理论上,人工神经网络可以逼近任何连续函数。因此,一个适当调整的神经网络可以胜过其他机器学习技术开发的模型一点也不奇怪。然而,在选择机器学习技术时,除了原始精度之外,我们还必须考虑许多实际因素。例如,逻辑回归模型可以通过数学公式简明地捕获,并在任何生产环境中轻松实现,而随机森林模型或神经网络必须在可编程环境中实现。与决策树模型相比,训练神经网络需要更大的计算能力,并且通常需要大的训练数据集。发表一篇论文称,在同一数据集上进行训练后,神经网络在预测某一临床结果方面的表现优于逻辑回归模型,这与声称客机在地球上两个地方之间的行驶速度比汽车快一样没有意义。作为一个社区,我们需要停止这些毫无意义的比较。

性能指标

让我们继续讨论本文中性能指标的使用。正如我们在之前的 journal club 条目中所讨论的,准确度和 F1 分数(以及灵敏度/召回率/真阳性率、特异性/选择性/真阴性率、精确度/阳性预测值、阴性预测值)是分类模型性能的点估计。它们的值取决于用于分类的特定阈值。通常基于做出正确预测的成本与不正确预测的成本之间的平衡来选择适当的阈值。曲线下面积(AUC)衡量模型在分类阈值范围内的表现,因此是对模型内在区分能力的评估。本文作者在图 2 中正确地报告了作为主要性能指标的 AUC,但不幸的是忽略了一个事实,即他们应该使用精确召回曲线下面积(AUPRC)而不是 ROC 曲线下面积(AUROC)。记住 ROC 曲线容易受到类别不平衡的影响,而精确召回曲线则不会。由于 SMOTE 技术仅应用于训练数据集,而不是验证数据集,使用 AUROC 作为性能度量将导致由负面结果主导的扭曲估计。虽然我们已经指出在不同的机器学习技术之间进行性能比较是徒劳的,但我们也应该指出,根据 F1 分数进行这样的比较,而不指定每个模型的最佳 F1 分数是如何确定的,这甚至更糟。请记住,模型的 F1 分数可能会随着精确度-召回曲线的变化而显著变化,默认阈值 0.5 通常不是最佳阈值。

班级失衡与绩效指标。图片作者。

网络架构

最后,我们想评论一下本文中使用的神经网络模型。作者使用了一个多层感知器(这可能是一个比深度神经网络更准确、更简单的描述),它包含 4 个隐藏层,每个隐藏层包含 128 个节点。对于一个简单的二进制分类任务来说,这是一个相当大的网络。作者在方法部分指出,他们在优化过程中测试了两种配置(128 个节点,256 个节点),但不清楚他们为什么选择 128 个节点作为起点。虽然在神经网络体系结构上没有严格的规则,但一个经验法则是将隐藏层中的神经元数量设置为输入层(本例中为 41)和输出层(本例中为 1)之间的某个值。我们想知道作者是否可以用一个更有效设计的网络获得类似(甚至更好)的结果。作者似乎也没有对 Adam 优化器设置或历元计数执行任何优化,所有这些都会显著影响模型的性能。作者还应在方法部分指定用于预处理数值和分类值的标准化和编码方案,因为它们是评审者和读者重现模型所必需的。

总结

这篇文章试图解决 MELD-Na 评分的缺点,即它在低范围内的辨别能力差,以及它不能使用机器学习技术预测长期死亡率。给定二元分类任务,选择逻辑回归模型、随机森林模型和人工神经网络是合适的。作者在方法部分提供了足够的细节来帮助评论者和读者重现模型。作者通过实现 SMOTE 技术考虑了类不平衡的问题。不幸的是,这篇文章的总体结论,即机器学习模型在预测死亡率方面优于 MELD-Na 评分,实际上并没有得到这项研究结果的支持。这篇文章还根据可能不太理想的 F1 分数,对三种建模技术的性能进行了一些不相关且未经证实的比较。总的来说,这篇文章能够成功地证明使用机器学习模型预测肝硬化患者的短期和长期死亡率,具有合理的区分能力。其他研究人员应该尝试通过将这些模型应用于其他数据集来从外部验证这些模型。

学习要点

  • 如果两个模型都进行了适当的优化,完整模型(由所有可用特征构成的模型)的性能将至少与部分模型(仅由特征子集构成的模型)一样好。
  • 机器学习建模技术的选择除了结果模型的辨别能力之外,还基于许多因素。比较使用不同技术构建但在相同数据集上训练的不同模型的性能不会增加任何科学价值。
  • 某些性能指标,如 ROC 曲线下面积和准确度会受到类别不平衡的不利影响,而其他指标,包括精确度-召回曲线下面积、平衡准确度和 F1 分数,则不受影响。

医学中的机器学习——第一部分

原文:https://towardsdatascience.com/machine-learning-in-medicine-part-i-90a611025037?source=collection_archive---------23-----------------------

针对医生和医疗保健专业人员的机器学习技术实践入门课程。

概述/数据准备

国家癌症研究所的图片来自 Unsplash

介绍

过去几年,机器学习、深度学习和人工智能已经成为包括医疗保健在内的所有行业的最新流行语。很多人乐观地认为,机器学习可以帮助医生建立更早、更准确的诊断,并为复杂疾病(如癌症)提供更有效、更个性化的治疗。也有希望利用机器学习来提高医疗服务的效率,降低医疗成本。

不幸的是,对于大多数受过传统培训的医疗保健专业人员来说,机器学习仍然是一个相对模糊的概念。只有一小部分人消息灵通,足以批判性地评价关于这个主题的期刊文章,更少的人能够在他们的研究中利用这些技术。这门入门课程的目标是揭开机器学习的黑箱,揭示这些算法的内部工作原理,并介绍实现它们所必需的工具。

虽然网上肯定不缺乏机器学习教程,但预测花瓣大小房价与诊断癌症并不完全一样。因此,在本课程中,我们将使用健康结果相关的数据集来解决实际的临床问题。在此过程中,我们将尝试强调在使用机器学习技术设计临床研究时必须考虑的重要决策。

先决条件

本课程的目标受众包括医学生、医生和其他医疗保健专业人员。假定读者对常见的统计学概念(例如,平均值、标准偏差、置信区间、相关系数)有基本的了解,并且熟悉制定临床问题的过程。

还假设读者对 JavaScript 编程有操作上的理解(例如变量声明、数组操作、函数调用等)。虽然 JavaScript 编程不是标准医疗培训的一部分,但对于任何初学者来说,它肯定是最简单的编程语言之一(他们向五年级和六年级的学生教授它)。网上有很多免费的 JavaScript 入门课程,包括来自 CodecademyLearn-JSMozilla 的课程。

最后,为了跟随实践教程,读者应该能够访问现代 JavaScript 引擎(例如 Google Chrome )和文本编辑器(例如 Visual Studio 代码括号)。

课程内容

  • 第一部分——概述/数据准备
  • 第二部分—数据探索
  • 第三部分—线性/逻辑回归
  • 第四部分-K-最近邻
  • 第五部分——集成决策树
  • 第六部分—神经网络
  • 第七部分—待定

基本术语

在本课程中,我们将试图掩盖机器学习的许多枯燥的理论方面,并专注于机器学习技术的实际应用。然而,回顾一些基本术语是很重要的,这样我们才能理解这些不同的技术是如何相互联系的。

  • 人工智能(AI):用计算机算法模拟自然智能。流行的人工智能算法正在模拟的自然智能的一些方面包括视觉感知、自然语言识别和机器学习。
  • 机器学习(ML):人工智能领域的一个子域,专注于构建模型来表示现实世界的知识和经验。已经设计了各种机器学习技术,并且它们可以大致分为监督学习、非监督学习和半监督学习。
  • 监督学习:一组机器学习技术,通过分析一组训练样本来模拟输入和输出之间的关系。监督学习技术的例子包括线性/逻辑回归、决策树、k-最近邻和神经网络。
  • 无监督学习:一组机器学习技术,基于自组织从未标记数据中识别模式。无监督学习技术的例子包括主成分分析、聚类分析和神经网络。
  • 神经网络(NN):也称为人工神经网络(ANN),是一种模仿生物神经网络的机器学习技术。神经网络通常由相互连接的节点的集合组成,这些节点松散地模仿生物神经网络中的神经元。
  • 深度学习:一组基于神经网络的机器学习技术,使用多层和大量神经元,以达到更高的抽象水平。

项目设置

在整个课程中,我们将探索一个公共领域数据集,名为 500 个城市:改善健康的地方数据,2019 年发布,由疾病控制和预防中心(CDC)提供。该数据集包括与不健康行为(5)、健康结果(13)和预防服务使用(9)相关的 27 种慢性病指标的估计值,这些指标来自美国 500 个最大的城市以及这些城市中大约 28,000 个人口普查区。

我们还将使用一个名为 Toolkit 的开源 JavaScript 库,使用基于 ECMAScript 的统计数据进行研究(DRESS Kit) 来用 JavaScript 实际创建我们的机器学习模型。这个库是用普通的 JavaScript 编写的,可以在任何装有现代浏览器的计算机上运行,不需要任何特殊的软件。与其他流行的机器学习库相比,它的学习曲线要浅得多,例如 KerasTensorFlow ,但它相当快速和强大。

为准备本课程的后续部分,读者应完成以下任务:

1 -创建项目文件夹。

2 -从美国疾病预防控制中心网站下载 500 个城市:改善健康的地方数据,2019 年发布。点击右上角的导出按钮,然后点击 CSV 按钮。将文件另存为项目文件夹中的单独文件夹/data中的data.csv

3 -从 GitHub 下载礼服套装。点击右侧的版本部分,然后从版本 1.0.1 下载 dress.zip 。将 ZIP 文件中的/js文件夹和/css文件夹复制到项目文件夹中。

作者图片

作者图片

此时,您的项目文件夹中应该有以下文件/文件夹:

数据准备

任何研究项目的数据分析过程的第一步,无论是否与机器学习有关,都是数据准备。这意味着清理数据集,移除不必要的或错误的数据,并将数据文件转换为与所使用的数据分析工具兼容的格式。

整个 500 个城市的数据集超过 200MB,包含 810,000 行数据和 24 列,其中许多是冗余的。我们将通过删除不需要的行和列来精简数据集。我们首先检查与数据集相关联的数据字典。我们可以看到,该数据集包含 28,000 个人口普查区域以及美国 500 个最大城市和整个美国的数据点。出于我们研究项目的目的,我们希望将每个人口普查区域视为一个单独的研究主题。我们就忽略那些市级和国家级的数据点。我们还可以看到,数据集包含每个数据点的粗略患病率和年龄调整后的患病率。为了这个项目的目的,我们将使用粗患病率。

作者图片

1 -通过复制以下代码,在项目文件夹中创建一个名为part1_1.htm的新 HTML 文件。

这个 HTML 文件只是从 DRESS Kit 中加载必要的 JavaScript 库以及我们自己的 JavaScript 文件。

2 -通过复制以下代码,在项目文件夹中创建一个名为part1_1.js的新 JavaScript 文件:

让我们详细地看一下 JavaScript 代码。我们首先使用名为DRESS.local的函数加载data.csv文件。这个函数实际上并不自动加载文件,但是它在 HTML 文件上显示了一个文件输入元素。在用户点击文件输入并选择合适的文件后,回调函数processCSV被调用。最后一个参数设置为false,这样DRESS.local函数就不会试图将内容解析为 JSON 文件。data.csv文件的内容(整个 500 个城市的数据集)作为名为csv的参数传递给processCSV函数。

接下来,我们需要将数据集从 CSV 格式转换成本地 JavaScript 数组。幸运的是,礼服工具包附带了一个专门为此设计的简洁的小功能,它被方便地命名为DRESS.fromCSV。我们只需将csv变量作为参数传递给函数,瞧,数据集就是一个对象数组。

之后,我们通过只选择包含普查区域级别数据和粗略患病率数据的行来过滤数组。正如我们所见,DRESS.fromCSV做的一件好事是将 CSV 文件的每一行转换成一个单独的 JavasScript 对象。我们可以使用相应的头作为属性名,将每个数据点作为对象的属性直接访问,例如row.GeographicLevel

3 -如上所述,我们希望将每个人口普查区域作为研究对象。理想情况下,我们希望每个主题由一个对象来表示。不幸的是,这 27 种慢性病的每一种都记录在数据集中单独的一行中。我们需要一种方法来将每个普查区域的这 27 个度量值合并到一个对象中。如果我们要在其他预建的统计软件中处理数据集,这样的任务会非常困难,但是因为我们是在一个可编程的环境中工作,所以我们可以用几行代码轻松完成。

因为我们知道每个人口普查区域由一个唯一的标识符标识,所以我们可以使用它将相关的数据点分组到一个对象中。我们还利用这个机会丢弃那些不必要的列。此外,根据对数据集描述的阅读,我们知道不为人口数量少于 50 的人口普查区域提供数据,但由于某些原因,这些人口普查区域仍包含在数据集中。我们需要扔掉那些人口普查小册子。接下来,我们想要将数值,比如PopulationCountData_Value转换成数字,这可以在 JavaScript 中通过在变量前加上+符号来轻松完成,记住丢失的数据点由空字符串表示。最后,我们希望将新创建的主题数组保存到一个文件中,以备将来使用。这可以通过使用DRESS.save函数将内容和文件名作为参数传递来轻松完成。

4 -如果我们按原样运行代码,很可能会导致长时间运行的脚本错误。尽管效率很高,但使用 JavaScript 处理超过 200MB 的数据需要一定的时间。为了防止浏览器窗口冻结,我们将利用另一个名为DRESS.async的很酷的小函数,它允许礼服工具包中的任何函数异步执行。该函数返回一个承诺,它将最终解析为异步执行函数的输出。我们可以将 Promise 传递给另一个名为DRESS.print的函数,它用于在 HTML 上显示文本,以便在数据集被处理时显示一个计时器。

以下是最终代码:

在浏览器中打开part1_1.htm,点击文件输入按钮,选择data.csv文件,最后将data.json从浏览器默认下载文件夹复制到项目文件夹内的/data文件夹。

5 -我们选择使用MeasureId来确定慢性病的每一个衡量标准,因为它们很短,但有时很难弄清楚神秘的MeasureId是什么意思。我们可以构建另一个列表,按照Category对这些度量进行分组,并将每个MeasureId映射到度量的详细描述。只需创建另一个名为part1_2.js的 JavaScript 文件,并将其加载到另一个类似于part1_1.htm的 HTML 文件中。运行脚本并将measures.json复制到项目文件夹中以备将来参考。

包裹

让我们回顾一下我们在第一部分学到的内容。我们复习了一些与机器学习相关的基本术语。特别是,我们介绍了几种常见的机器学习算法的名称,如决策树、k-最近邻和神经网络,并讨论了它们如何相互适应。我们通过下载 500 个城市的数据集和设置着装套件来着手设置我们的项目。我们经历了数据准备过程,从数据集中提取有用的数据点。在这个过程中,我们从 DRESS Kit 中学习了几个基本函数,包括DRESS.local(加载本地文件)、DRESS.save(将文件保存到本地机器)、DRESS.fromCSV(将 CSV 文件转换为本地 JavaScript 对象)、DRESS.print(将文本打印到 HTML 上)和DRESS.async(异步执行函数)。

我们还没有真正做任何与机器学习有关的事情,但这将在本课程的后续部分中出现。敬请关注。

锻炼

作为练习,读者可以尝试准备另一个 JSON 文件,其中包含城市级别的数据,而不是人口普查区域级别的数据。

医学中的机器学习——第二部分

原文:https://towardsdatascience.com/machine-learning-in-medicine-part-ii-b9dc0098f825?source=collection_archive---------25-----------------------

针对医生和医疗保健专业人员的机器学习技术实践入门课程。

数据探索

图片由粘土银行从 Unsplash

概述

在本课程的 第一部分中,我们介绍了几种常见的机器学习算法的名称,如决策树、k-最近邻和神经网络,并讨论了它们如何相互融合。我们通过下载一个公共领域数据集 500 个城市数据集并建立一个名为着装套件的 JavaScript 机器学习库来建立我们的项目。接下来,我们完成了数据准备过程,使用 DRESS Kit 中的几个基本函数从数据集中提取有用的数据点,这些函数包括DRESS.local(加载本地文件)、DRESS.save(将文件保存到本地机器)、DRESS.fromCSV(将 CSV 文件转换为本地 JavaScript 对象)、DRESS.print(将文本打印到 HTML 上),以及DRESS.async(异步执行函数)。在第一部分的最后,我们创建了一个 JSON 文件data.json,其中仅包含来自 500 个城市数据集的普查区域级别的粗略患病率数据,这些数据来自那些人口计数至少为 50 的普查轨道。我们还创建了一个 JSON 文件measures.json,它将MeasureIdCategory分组,并将每个MeasureId从原始数据集映射到它的定义。

只是作为一个参考点,这里是measures.json的内容。

礼服套件更新

在继续本课程的其余部分之前,请花点时间更新着装套件以发布 1.1.0 。该版本包含几项性能改进和一些新功能,包括生成直方图和热图,我们将在课程的这一部分探讨这些内容。

柱状图

我们通过对数据集进行基本的描述性分析来开始数据探索过程,这样我们就可以大致了解可用数据的质量。特别是,我们要注意是否存在任何缺失或错误的数据点,数字特征的相对范围(我们需要标准化/规范化这些特征吗?)、分类特征的维度(对这些特征进行一键编码是否可行?),以及这些特征的分布(正态、均匀、偏斜等。)

我们再次创建一个名为part2_1.htm的样板 HTML 文件,它加载了 DRESS Kit 以及我们的定制 JavaScript 文件part2_1.js

我们使用DRESS.local函数加载在课程第一部分创建的数据集。请注意,第三个参数不再设置为FALSE,因为数据集现在存储为 JSON 格式,JavaScript 可以对其进行本地解析。我们将慢性病的所有 27 项指标分配到一个数组中,这样我们就不必一遍又一遍地输入它们。数据科学家使用的最流行和最直接的数据探索技术之一是直方图。它以简洁直观的方式描述了数据集中值的分布。虽然有大量的统计软件包可以生成高质量的多色直方图,但实际上并没有必要,因为直方图的整体思想是它代表了底层数据集的近似。我们可以从直方图的粗略轮廓中收集我们需要的所有信息,直方图可以使用DRESS.histograms函数生成。

在浏览器中打开part2_1.htm,点击文件输入按钮,选择data.json文件,生成基于文本的直方图列表。下面是该函数生成的三个直方图。

每个直方图都提供了几条关键信息。首先,它显示包含非空值的数据点的数量(和百分比)。我们可以看到,CANCERBPMED度量没有空值,但是COREW度量缺少一小部分(0.4%)数据点。接下来,它计算值的范围(第一个条形代表最小值,条形之间的差异代表间隔,最后一个条形代表最大间隔)。例如,我们可以看到CANCER度量的范围在 0.7 到 22.9 之间。最重要的是,我们可以从条形图中看到值的粗略分布。我们可以看到CANCER指标严重向左倾斜,而BPMED指标严重向右倾斜。相比之下,COREW测量值几乎均匀分布在平均值周围。

DRESS.histograms函数也可以从分类特征生成直方图。只需将分类特性的名称作为第三个参数传递,如下所示:

我们可以看到,来自加利福尼亚州、纽约州和德克萨斯州的数据点构成了数据集的大部分,考虑到美国的人口分布,这并不完全出人意料。重要的是要记住,这个数据集中的每个subject指的是人口普查区域,而不是个人。还值得注意的是,某些州,如特拉华州、缅因州、佛蒙特州、西弗吉尼亚州和怀俄明州,人口普查区非常少,当我们实际使用数据集来构建我们的机器学习模型时,可能会产生一些问题。我们需要记住这一点。

归罪

请注意,数据集中的某些特征(如COREW度量)包含缺失的数据点。在临床研究中,缺失数据是一个相当普遍的问题;参与者可能在研究中途退出,数据可能输入错误,或者数据收集表可能放错了地方。这是大部分统计教材中提出随机缺失(MAR)、完全随机缺失(MCAR)、非随机缺失(MNAR)概念的地方。我们不会浪费时间讨论这些定义背后的无聊理论。可以说,MCAR 不会影响数据分析,但在现实中,几乎不可能证明数据是完全随机缺失的。MNAR 是完全相反的情况,其中数据丢失的原因与丢失数据的值有关。可靠地恢复丢失数据的唯一方法是通过修改数据收集步骤或数据分析步骤来解决根本原因。例如,在一项询问使用电脑时间的在线调查中,那些无法使用电脑(或至少无法访问互联网)的人可能不会出现在数据集中。研究者应尝试亲自收集数据,或者在分析过程中承认研究仅限于那些可以在线访问调查的人。没有一种通用的统计操作可以解决 MNAR。在大多数设计良好的临床研究中,我们处理的是 MAR,它可以通过某种统计方法来解决。一种策略是忽略那些缺失的数据点。我们可以丢弃整个主题,也可以只丢弃缺失的数据点,这取决于我们想要如何分析数据。第二种策略是用合理的估计值代替缺失的数据,这一过程称为插补。可以通过从其他非缺失数据点中随机选择一个数据点(例如,结转的最后观察或结转的基础观察),通过计算算术平均值或模式,或通过某种统计回归分析来计算这种估计。

当我们真正建立我们的机器学习模型时,我们将展示一些基本的插补技术。我们还将了解到,一些机器学习技术可以反过来用作插补技术。

平均值、中间值和众数

更具分析性地探索数据的另一种方法是研究数据集的集中趋势(均值、中值和众数)和离差(方差和四分位间距)。这些特性特别重要,因为许多其他统计方法,如回归分析,都在对它们进行操作,我们经常使用这些特性在两个或更多数据集之间进行比较(即治疗组是否比安慰剂组有更高的平均存活率)。

当然,DRESS Kit 附带了几个内置函数来计算数据集的集中趋势和分散度。

这也是脚本产生的结果的一部分。

DRESS.means函数计算平均值、平均值的 95%置信区间、偏斜度(基于第三个标准化矩)和超额峰度(基于第四个标准化矩)。DRESS.medians函数计算中值、四分位数范围、偏斜度(基于四分位数)和过度峰度(基于百分位数)。最后,DRESS.frequencies函数从一个分类特征中枚举出所有可能的值,并按其出现频率排序(第一个是模式)。

一些非常敏锐的读者可能会指出,数据集中大多数特征的值并不是严格的正态分布,直方图的形状以及显著偏度和过度峰度的存在就是证明。然而,重要的是要注意,当我们处理成千上万的样本时,值是否正态分布就不那么重要了。如果我们应用正式的正态性检验算法,例如夏皮罗-维尔克检验(可以通过使用函数DRESS.normalities轻松完成),我们会发现数据集中的所有特征实际上都不是正态分布的。然而,仅仅因为测试结果在统计上是显著的,并不一定意味着它在实践中是有意义的。这里有一篇出色的评论文章解释了这背后的统计数据。可以说,我们可以在这个数据集上安全地应用大多数参数统计操作,而不用担心潜在的正态性假设。

相互关系

了解了数据集中每个要素的特征后,我们应该将注意力转移到数据集中各种要素之间的关系上。请记住机器学习的整体思想,即基于数据集建立模型,然后使用该模型进行预测。理想情况下,我们希望看到数据集中的各种要素相互独立。换句话说,如果一个数据集中的所有要素都高度相关,那么该数据集实际上并不包含比另一个仅包含其中一个要素的数据集更多的信息。我们还想检查数据集中暴露特征和结果特征之间的任何相关性。如果暴露和感兴趣的结果之间存在简单的线性关系,那么就真的没有必要采用一些复杂的机器学习算法。

当然,DRESS KIT 附带了一个名为DRESS.correlations的函数,它可以自动计算皮尔逊相关系数(或斯皮尔曼等级相关系数)。不幸的是,该函数输出的文本可能很长,很难解释。幸运的是,我们可以使用DRESS.heatmap函数轻松地将文本输出转换成热图

作者图片

绿色代表正相关,蓝色代表负相关。颜色的深浅表示相关性的强度。红色文字代表统计意义。我们可以看到,乳房 x 线摄影或巴氏涂片与其他特征之间几乎没有相关性,而代谢综合征的大多数组成部分,包括高血压、高胆固醇和糖尿病,彼此高度相关。这里有一个关于多重共线性的精彩在线章节。当我们实际上试图建立和解释我们的机器学习模型时,我们需要记住这一点。

包裹

让我们复习一下第二部分所学的内容。我们经历了数据探索过程的基本步骤。我们首先使用DRESS.histograms函数创建一系列直方图,允许我们识别数据集中值的范围和分布。我们简要讨论了处理缺失数据的不同方法。接下来,我们通过使用DRESS.meansDRESS.mediansDRESS.frequencies计算平均值、中值和众数,重点关注数据集中每个特征的集中趋势和分散度。我们谈到了偏度和峰度的概念,并讨论了在处理大型数据集时,通常不必担心正态分布。最后,我们展示了一种使用DRESS.correlationsDRESS.heatmap函数来评估数据集中各种特征之间相关程度的方法。

现在,我们已经对数据集中的各种特征有了大致的了解,我们准备好继续使用该数据集构建我们的机器学习模型。

医学中的机器学习——第三部分

原文:https://towardsdatascience.com/machine-learning-in-medicine-part-iii-8f3742e17c34?source=collection_archive---------33-----------------------

针对医生和医疗保健专业人员的机器学习技术实践入门课程。

线性/逻辑回归

照片由来自 Unsplash 的 Eanyet Raheem 拍摄

概述

在本课程的第二部分中,我们讲述了数据探索的基本步骤。我们首先通过使用DRESS.histograms生成直方图来调查数据集的分布。然后,我们使用DRESS.meansDRESS.mediansDRESS.frequencies研究了数据集中各种特征的集中趋势和分散程度。我们演示了使用DRESS.heatmapDRESS.correlations来可视化数据集中各种特征之间的相关程度。同时,我们还引入了缺失值插补的概念。

需要强调的是,正确的数据探索过程涉及大量特定于数据集的分析,并且高度依赖于相关的领域知识。例如,基于这些检测的潜在生物化学,我们预期随机血糖测量值与血红蛋白 A1C 相比有显著更高的差异。类似地,当在普通人群中分析某些实验室值,如 INR 和肌酐时,我们也可以预期有严重的偏态分布。当我们探索一个数据集时,我们必须考虑这些特定于数据集的特征。

礼服套件更新

在继续本课程的其余部分之前,请花点时间更新着装套件以发布 1.2.0 。这个版本包含几个重要的错误修复,包括几个线性/逻辑回归算法。

均值/众数插补

还记得我们的数据集中有一些缺失值吗?让我们从使用最简单的算法来估算这些缺失值开始:均值/众数估算法。该算法背后的基本原理源于大数定律,该定律指出,对于足够大的样本,样本平均值向期望值收敛。如果样本很大,缺失值的数量很少,那么简单地用期望值替换那些缺失值是合理的,因为这不会对大多数参数统计操作的结果产生不利影响。

我们再次创建一个名为part3_1.htm的样板 HTML 文件,它加载了 DRESS Kit 以及我们的定制 JavaScript 文件part3_1.js

DRESS.meanMode函数有三个参数,第一个是主题数组,第二个是数字特征数组,第三个是分类特征数组。因为在我们的数据集中,所有 27 个慢性病指标都是数字,我们可以忽略第三个参数。值得注意的是,DRESS.meanMode函数只认为null值缺失。数据集中的其他错误或缺失值应在被该函数处理之前转换成null。记住函数通过直接改变输入主题来填充缺失的值也很重要。

ARTHRITIS : 0 (0.00%) = 21.43
BPHIGH : 0 (0.00%) = 30.65
CANCER : 0 (0.00%) = 5.65
CASTHMA : 0 (0.00%) = 9.74
CHD : 0 (0.00%) = 5.60
COPD : 0 (0.00%) = 6.31
DIABETES : 0 (0.00%) = 10.81
HIGHCHOL : 0 (0.00%) = 31.36
KIDNEY : 0 (0.00%) = 3.10
MHLTH : 0 (0.00%) = 13.92
PHLTH : 0 (0.00%) = 12.88
STROKE : 0 (0.00%) = 3.21
TEETHLOST : 60 (0.22%) = 16.11
ACCESS2 : 1 (0.00%) = 16.99
BPMED : 0 (0.00%) = 70.74
CHECKUP : 0 (0.00%) = 69.01
CHOLSCREEN : 0 (0.00%) = 78.74
COLON_SCREEN: 19 (0.07%) = 61.79
COREM : 103 (0.38%) = 31.66
COREW : 109 (0.40%) = 29.83
DENTAL : 0 (0.00%) = 61.23
MAMMOUSE : 37 (0.14%) = 79.19
PAPTEST : 7 (0.03%) = 76.38
BINGE : 0 (0.00%) = 18.07
CSMOKING : 0 (0.00%) = 17.97
LPA : 0 (0.00%) = 27.59
OBESITY : 0 (0.00%) = 30.47
SLEEP : 0 (0.00%) = 36.72

我们可以从打印输出中看到每个特征中缺失值的数量以及用作替换的值。我们将在课程的后面介绍一些更复杂的插补算法。

选择建模技术

大多数机器学习建模技术可以用于创建回归模型(其中输出是连续的数值,例如年龄、体重、身高、实验室值)或分类模型(其中输出是几个不同值中的一个,例如性别、血型、种族),这取决于模型的设置方式。如果调整得当,大多数建模技术都可以提供相当的性能。尽管如此,这些技术在各自的优势和局限性方面有很大的不同。当我们进行实际的研究时,我们应该根据每种技术的独特属性选择最适合我们研究问题的建模技术。

由于我们被限制在本课程的每个部分只使用一种机器学习建模技术,然而,我们必须构建我们的研究问题以适应每种技术的特定属性。

回归分析与机器学习

一些读者可能会问,为什么我们会考虑将线性/逻辑回归作为机器学习模型。毕竟,我们大多数人每天都在研究中使用这些简单的回归技术。让我们花一点时间来讨论这些回归技术的典型使用和它们作为机器学习模型的使用之间的概念差异。在生物医学期刊文章中,线性/逻辑回归几乎总是作为一种工具来证明预测因子和结果之间的联系。例如,在一项关于非酒精性脂肪性肝病(NAFLD)的研究中,作者可能希望表明体重指数(身体质量指数)和血红蛋白 A1C 是 NAFLD 发展的独立预测因子。为了做到这一点,作者将从有/无 NAFLD 的患者中收集各种临床数据,如年龄、性别、医学合并症和实验室值。通过使用逻辑回归,作者可以表明受试者被诊断为 NAFLD 的概率随着他/她的身体质量指数或血红蛋白 A1C 的增加而增加。作者也可以使用相同的模型来表明血清钾水平和 NAFLD 的发展之间没有关联。作者可以更进一步,通过建立一个线性回归模型来证明身体质量指数和 NASH 活动指数之间的线性相关性。这里的关键是,我们使用这些回归技术来证明预测因素和结果之间存在/不存在具有统计意义的关联。

然而,当我们使用线性/逻辑回归构建机器学习模型时,我们的主要目标是最大化模型的预测性能,而我们往往不太关注这些关联的统计意义。我们将讨论如何衡量机器学习模型的预测性能,但暂时假设它与模型的准确性相同。让我们记住统计显著性按照惯例被设置为α0.05,这意味着我们只愿意接受小于 5%的 I 型错误(假阳性)的概率。然而,0.05 这个数字并没有什么神奇之处。事实上,开创统计假设检验概念的统计学家罗纳德·费雪建议根据每个特定的用例来设置 alpha。换句话说,仅仅因为一个预测因子与结果没有统计学意义上的联系,并不意味着它不能提高我们模型的整体准确性。我们也不太关心特定预测因素和结果之间的关联强度。事实上,正如我们将在本课程后面看到的,当我们构建机器学习模型时,我们有时会故意忽略某些预测因素,以尽量减少名为过度拟合的问题。

模型概述

作者图片

线性回归通常用作机器学习模型来解决回归问题(即结果是连续的数字变量)。更重要的是,当有理由假设预测值和结果之间存在线性相关性时,它是最合适的,至少对于感兴趣的值范围是如此。例如,假设我们正在构建一个机器学习模型来预测患者的住院时间,以便优化床位利用率。有理由怀疑患有更多共病的患者会住得更久。相比之下,患者的体温可能不会随着停留时间的长短而线性变化,因为高温和低温都可以预测更长的停留时间。在具有多个预测器的典型机器学习中,不同的预测器可以在不同程度上和相反方向上与结果相关,从而实现一种“智能”,但是当所有其他预测器的值保持不变时,每个预测器应该与结果线性相关。

作者图片

多项式回归可以被认为是线性回归的一种变体。预测值和结果之间的关系不是线性相关(即直线),而是曲线。根据多项式的次数,曲线可能有一个或多个最大值或最小值。换句话说,线性回归只是多项式回归的一个特例,其中多项式的次数设置为 1。通过在机器学习模型中混合线性和多项式回归,有可能创造出更复杂的“智能”。需要高度的领域知识来确定多项式的适当次数。

作者图片

逻辑回归通常用作机器学习模型来解决分类问题,特别是二元分类问题(即是/否、真/假、肯定/否定)。因为逻辑回归模型的原始输出指的是概率(即范围从 0 到 1 的连续数值),所以使用逻辑回归来解决多类分类问题在技术上也是可行的。例如,如果最终结果属于四个可能值(A、B、C 和 D)之一,我们可以创建四个一对其余逻辑回归模型(即 A 对 B/C/D、B 对 A/C/D、C 对 A/B/D、D 对 A/B/D、D 对 A/B/C),将数据集应用于所有四个模型,并选择返回最高概率值的模型。

优势和局限性

线性/逻辑回归作为机器学习模型的优势之一是该技术基于成熟的数学算法。这意味着该算法被大多数统计分析软件包广泛支持。此外,回归公式中的常数清楚地定义了每个预测因子和结果之间的关系,从而使我们能够容易地确定每个预测因子的相对重要性。并且因为最终的模型用一个简单的数学公式简洁地表示,所以它可以很容易地部署到最终的应用程序环境中。

作者图片

线性/逻辑回归作为机器学习模型的局限性之一是,该模型只能支持平滑和连续的决策边界。想象一下,如果我们试图建立一个机器学习模型,将测试对象分类为红圈或蓝叉。很明显,使用简单的数学公式来表示黄线(即决策边界)几乎是不可能的(拥有如此复杂的决策边界是否有益是另一回事;提示:过拟合)。一般来说,如果我们有理由怀疑预测因子随结果线性变化,那么线性/逻辑回归可能是一个合理的选择。

同样需要注意的是,由于潜在的数学运算,线性/逻辑回归只能接受数值预测值。尽管在技术上可以使用一键编码将分类预测值转换成数值,但这种方法并不是最有效的,并且倾向于在最终模型中过度表示那些分类预测值。

线性回归

让我们开始构建我们的第一个机器学习模型。回想一下,数据集中慢性病的 27 个指标可以分为不健康行为(5)、健康结果(13)和预防服务的使用(9)。为了这个练习,让我们假设每个数据点代表一个城市/城镇。我们希望建立一个模型,使我们能够根据那些不健康的行为和预防服务的使用来预测每个城市/城镇的整体健康结果。

构建我们的机器学习模型所需的实际代码相当简单。我们只需将数据集、感兴趣的结果和一组预测值传递给DRESS.linear函数。

*[PHLTH] R2: 0.92 aR2: 0.92 AIC: 7545.95 F: 20313.37 p: -0.00
(intercept) : +13.30 (95% CI 12.76 - 13.84) t: +48.21 p: 0.00
ACCESS2 : 0.00 (95% CI -0.01 - 0.00) t: -1.18 p: 0.24
BPMED : +0.08 (95% CI 0.07 - 0.08) t: +35.55 p: 0.00
CHECKUP : -0.04 (95% CI -0.04 - -0.03) t: -13.44 p: 0.00
CHOLSCREEN : +0.06 (95% CI 0.06 - 0.07) t: +24.56 p: 0.00
COLON_SCREEN: +0.05 (95% CI 0.05 - 0.06) t: +20.28 p: 0.00
COREM : -0.04 (95% CI -0.05 - -0.04) t: -22.08 p: 0.00
COREW : -0.06 (95% CI -0.06 - -0.05) t: -23.98 p: 0.00
DENTAL : -0.12 (95% CI -0.12 - -0.11) t: -57.71 p: 0.00
MAMMOUSE : -0.01 (95% CI -0.02 - -0.00) t: -2.85 p: 0.00
PAPTEST : 0.00 (95% CI -0.00 - 0.00) t: -1.37 p: 0.17
BINGE : -0.20 (95% CI -0.20 - -0.19) t: -69.55 p: 0.00
CSMOKING : +0.29 (95% CI 0.29 - 0.30) t: +78.25 p: 0.00
LPA : +0.07 (95% CI 0.06 - 0.07) t: +18.34 p: 0.00
OBESITY : -0.02 (95% CI -0.02 - -0.01) t: -7.75 p: 0.00
SLEEP : -0.09 (95% CI -0.09 - -0.08) t: -32.70 p: 0.00*

从输出中注意到的第一件事是,模型的决定系数(不要与相关系数混淆)为 0.92,考虑到我们没有对模型进行任何优化,这是相当令人印象深刻的。我们还可以看到,除了PAPTESTACCESS2之外,所有的预测因子都与结果有显著的统计学相关性。这很可能是因为数据集中的数据点数量巨大。我们需要问自己的一个问题是,包含所有这些预测因素是否真的提高了模型的预测能力。评估统计模型的相对质量的一种方法是使用一种称为 Akaike 信息标准 (AIC)的衡量标准,这在本质上是一种平衡衡量模型拟合度和模型简单性的方法。基本上,我们需要使用预测因子的各种排列构建一系列模型,计算每个模型的 AIC,并找到 AIC 最低的模型。当然,手动完成这项工作可能相当繁琐,因此我们将依赖于 DRESS KIT 中一个名为DRESS.forward的内置函数,这是一个使用 AIC 作为选择标准的逐步特征选择算法。

完成该函数可能需要 30 秒,因为它需要从整个数据集构建多个模型。它证实了我们的怀疑,即PAPTESTACCESS2预测器没有增加模型的预测能力,应该被排除在最终模型之外。值得注意的是,这只是评估我们模型质量的许多不同方法之一。如果我们使用不同的质量度量,例如调整 R2贝叶斯信息标准,我们可能会得到不同的结果。同样重要的是要注意,这种逐步特征选择算法本质上使用整个数据集进行训练验证,并且易于过拟合。在本课程的后续部分,我们将介绍验证模型性能的其他技术。

现在我们已经建立了一个机器学习模块的模型,让我们实际上尝试使用它来进行一些预测。同样,这里的概念是,我们是公共卫生专家,我们希望能够根据那些不健康的行为和预防服务的使用来预测一个城市/城镇的整体健康结果。

我们的模型预测,在这个假设的城市/城镇中,大约 12.24%的成年人在过去一年中身体健康状况不佳的时间> =14 天。

逻辑回归

让我们继续进行逻辑回归。如上所述,这种机器学习技术通常用于解决二元分类问题。我们需要想出一个可以用二元回答来回答的研究问题。假设我们想要确定糖尿病患病率高于平均水平的城市/城镇,以便对资源分配进行优先排序,我们可以构建一个逻辑回归模型来实现这一点。

首先,我们需要将数字健康结果DIABETES转换成二进制值(1 代表糖尿病患病率高于平均水平的人群,0 代表其他人群)。我们可以参考本课程的第二部分,以获得该数据集中糖尿病的平均患病率。我们将新的二元结果标记为DM。与构建线性回归模型的方式类似,我们可以通过将数据集、感兴趣的结果和一组预测值传递给DRESS.logistic函数来创建逻辑回归模型。

*[DM] R2: 0.78 AIC: 8221.85 deviance: 28776.42 p: 0.00
(intercept) : -29.38 OR: 0.00 (95% CI 0.00 - 0.00) z: -20.89 p: 0.00
ACCESS2 : +0.06 OR: 1.07 (95% CI 1.05 - 1.09) z: +6.61 p: 0.00
BPMED : +0.54 OR: 1.72 (95% CI 1.66 - 1.77) z: +35.34 p: 0.00
CHECKUP : -0.16 OR: 0.85 (95% CI 0.83 - 0.88) z: -11.41 p: 0.00
CHOLSCREEN : +0.14 OR: 1.15 (95% CI 1.12 - 1.18) z: +10.87 p: 0.00
COLON_SCREEN: +0.02 OR: 1.02 (95% CI 1.00 - 1.05) z: +2.23 p: 0.03
COREM : -0.11 OR: 0.89 (95% CI 0.88 - 0.91) z: -13.49 p: 0.00
COREW : -0.08 OR: 0.92 (95% CI 0.90 - 0.94) z: -8.36 p: 0.00
DENTAL : -0.22 OR: 0.80 (95% CI 0.79 - 0.82) z: -24.09 p: 0.00
MAMMOUSE : +0.01 OR: 1.01 (95% CI 0.98 - 1.04) z: +0.57 p: 0.57
PAPTEST : +0.02 OR: 1.02 (95% CI 1.02 - 1.02) z: +14.94 p: 0.00
BINGE : -0.34 OR: 0.71 (95% CI 0.69 - 0.73) z: -23.05 p: 0.00
CSMOKING : -0.20 OR: 0.82 (95% CI 0.79 - 0.84) z: -12.60 p: 0.00
LPA : +0.07 OR: 1.07 (95% CI 1.04 - 1.10) z: +4.36 p: 0.00
OBESITY : +0.16 OR: 1.17 (95% CI 1.15 - 1.19) z: +17.66 p: 0.00
SLEEP : +0.22 OR: 1.24 (95% CI 1.22 - 1.27) z: +19.09 p: 0.00*

我们可以看到未经优化的原始模型的决定系数为 0.78,这是相当合理的。我们可以使用DRESS.forward函数进一步优化我们对预测值的选择,尽管在这种特殊情况下,这样做似乎不会显著提高拟合优度。就像逻辑回归的情况一样,我们可以通过传递一个假设的城市/城镇作为参数来使用模型进行预测。

尽管逻辑回归通常用于解决二进制分类问题,但predict函数的结果不是二进制值,而是代表结果发生概率的连续数值。为了将范围从 0 到 1 的数值转换成二进制值(即,该城市/城镇的糖尿病患病率是否高于平均水平),我们需要确定一个合适的截止值,要么根据经验将其设置为 0.5,要么使用测试统计来帮助最大化分类函数的性能。一个这样的测试统计是尤登指数,它代表了敏感性和特异性之间的权衡。利用模型的roc函数,我们可以自动计算出接收机工作特性曲线以及尤登指数。

roc函数将一组主题作为参数,这些主题可以是原始数据集,也可以是另一个验证数据集。结果显示曲线下面积(AUC) 或一致性统计(C 统计)为 0.99,这表明该模型能够以近乎完美的准确度区分阳性和阴性结果。结果还表明,最佳截止值为 0.44。

包裹

让我们复习一下第三部分所学的内容。我们引入了一种称为均值/众数插补的缺失值插补方法(使用DRESS.meanMode)。我们讨论了决策边界的概念,以及使用线性/逻辑回归进行回归分析和使用它进行机器学习之间的重要概念差异。我们经历了构建线性/逻辑回归机器学习模型(使用DRESS.linearDRESS.logistic)以及使用该模型进行预测(使用model.predict)的实际过程。在这个过程中,我们谈到了一种称为前向选择(DRESS.forward)的特征选择技术和一种称为 Youden 指数的测试统计,用于确定逻辑回归模型的最佳临界值。

模型摘要

线性/逻辑回归

强项

  • 易于实施(受大多数统计分析软件支持)
  • 易于优化(只需选择合适的预测值)
  • 易于解释(预测因素和结果之间的关系已明确定义)
  • 易于部署(模型可以用一个简单的数学公式来表示)

限制

  • 平滑、连续的决策边界
  • 仅适用于数值预测值

锻炼

作为练习,让我们尝试建立一个模型来预测一个假设城镇/城市的癌症患病率,以及一个模型来识别基于健康结果的结肠癌筛查率< 50%的城市/城镇。注意根据研究问题选择合适的建模技术以及相关的预测因子。

医学中的机器学习——第四部分

原文:https://towardsdatascience.com/machine-learning-in-medicine-part-iv-73c848ec8577?source=collection_archive---------31-----------------------

针对医生和医疗保健专业人员的机器学习技术实践入门课程。

k-最近邻

Avi Waxman 在 Unsplash 上拍摄的照片

概述

在本课程的 第三部分中,我们探索了我们的第一个机器学习模型——线性/逻辑回归。我们讨论了使用线性/逻辑回归进行回归分析和使用它进行机器学习的概念差异。我们讨论了该技术的优势和局限性,并演示了使用服装工具包构建模型以及使用模型进行预测的步骤。

重要的是要强调,尽管围绕一些更高级的机器学习技术(如随机森林和神经网络)有很多争论,但由于其简单性,线性/逻辑回归仍然是临床研究中非常有用的机器学习技术。许多风险评分系统,如 Framingham Risk Score 和 MELD-Na Score,在功能上与基于线性/逻辑回归的机器学习模型相同,即使这些评分系统可能不是完全由算法得出的。

礼服套件更新

在继续本课程的其余部分之前,请花点时间更新着装套件以发布 1.2.5 。这个版本包含了我们将在这里使用的 kNN 算法的一个特性更新。

模型概述

k-最近邻(kNN)的工作基于相似对象行为相似的假设。与大多数其他机器学习技术不同,kNN 模型不试图“学习”预测器和结果之间的关系。事实上,kNN 模型的构建通常不需要太多的训练阶段,只需要以内存高效的格式存储整个训练数据集以供以后检索。当需要进行预测时,模型会确定测试主题与训练数据集中每个主题之间的相似度,根据相似度挑选出顶部的k训练主题(邻居),并通过计算这些k主题的模式(对于分类问题)或均值(对于回归问题)返回感兴趣的结果。因此,kNN 的判定边界不是一条光滑的直线,而是一个半径为k的圆。

作者图片

当我们需要实现 kNN 模型时,有三个超参数需要考虑:模型中要包含的预测值、用于测量相似度的度量(例如,曼哈顿距离欧几里德距离闵可夫斯基距离)以及k的值。

优势和局限性

kNN 技术的优势之一是它的简单性;没有复杂的数学运算。该算法只是在训练数据集中找到与测试对象最相似的对象。该算法可以处理数值和分类预测值(只要实现支持从分类值计算距离度量)。最令人印象深刻的是,同一个模型可以用来预测多种结果,只要它们共享相同的预测因子。这种独特的性质使得 kNN 模型不仅可以用于解决分类或回归问题,还可以用于群组匹配和缺失值插补。

kNN 技术的主要限制之一是在进行预测时计算效率低。每次我们使用模型进行预测时,算法都需要计算训练数据集中每个对象的距离度量,并根据距离度量对整个训练数据集进行排序。在生产环境中部署模型也相当麻烦,因为必须重现整个训练数据集。

kNN 技术也有一些性能限制。因为预测结果是前k个邻居的平均值,所以它永远不会超出训练数据集中观察到的值的范围。例如,考虑只有一个预测值(身高)和一个结果(体重)的 kNN 模式。如果最高的训练对象是 6 英尺高,200 磅重,那么这个训练对象将是任何 6 英尺或更高的测试对象的最近邻居,因此预测结果将是 200 磅左右。此外,kNN 模型易于出现异常值,因为该算法在预测阶段考虑整个训练数据集,并且每个训练对象被视为邻居的概率相同。

履行

让我们开始建立一个 kNN 模型。类似于我们如何构建线性/逻辑回归模型,我们将考虑使用预防服务和不健康行为作为预测因素,以建立一个机器学习模型,帮助我们预测一个假设的城市/城镇的健康结果。

kNN函数最多接受四个参数。第一个是一系列训练科目。第二个是用作预测器的一组数字特征。第三个,如果指定的话,是用作预测器的分类特征的数组。最后一个指定在进行预测之前是否应该对预测值进行归一化。默认情况下,预测值是归一化的,这意味着每个预测值的最大距离为 1,并且每个预测值对距离度量的贡献是相等的。

首先要注意的一点是,在构建 kNN 模型时,我们不必指定感兴趣的结果。并且打印输出不包含任何数字或统计信息,除了用于建立模型的预测器的名称。这是因为除了提取预测值并将其存储在内存中之外,该算法在此阶段实际上并没有做太多工作。

为了使用 kNN 模型进行预测,我们需要提供一个测试主题并指定结果,无论是分类问题还是回归问题,以及可选的k的值。

我们可以看到 kNN 模型的优势之一是能够使用相同的模型对不同的感兴趣的结果进行预测(只要我们认为应该使用相同的预测器)。我们还可以看到,使用 kNN 模型解决分类问题非常容易。不需要做任何一键编码

模型性能

性能指标

使用 DRESS Kit 构建一个功能性的 kNN 模型一点也不困难,但是我们应该问问自己,如果我们优化一些与模型相关的参数(或者更准确地说是 hyper 参数),我们是否可以创建一个更好的模型。这些超参数包括k的值、特征选择和特征缩放。然而,在我们讨论优化过程之前,我们必须首先定义我们将如何度量一个模型的性能。如果给我们两个模型,我们如何决定哪一个更好?

评估模型性能的基本思想是量化预期结果和预测之间的差异。直观上,我们可以理解,如果预测与预期结果完全相同,则该模型被认为是完美的。如果预测是以平均预期结果为中心的随机值,那么该模型被认为是无用的。关键是找到一个合适的统计方法来量化这种差异。

对于回归问题,最常用的统计度量是决定系数(R2)平均绝对误差 (MAE),或者均方根误差 (RMSE)。MAE 和 RMSE 都代表了预期结果和预测之间的平均差异,但 RMSE 对大误差的惩罚比对小误差的惩罚更大(因为平方),而 MAE 没有考虑每个误差的大小。R2 是一种无单位的度量,范围从负无穷大到 1(完美)。它代表了预期结果与预测的匹配程度(从技术上来说,它衡量的是预测所解释的预期结果中的差异比例)。这不要与相关系数 (R)相混淆,后者仅表示两个变量相互跟随的程度(当一个变量的值上升时,另一个变量也会上升,反之亦然)。

对于分类问题,最常用的统计指标是准确度(被正确分类的受试者的比例)精确度(被正确分类的受试者在被预测为某一类别的所有受试者中的比例,也称为阳性预测值)召回率(某一类别的受试者被正确分类到该类别的比例,也称为真阳性率)和 F 得分

作者图片

交互效度分析

由 DRESS Kit 生成的每个机器学习模型都包含一个performance函数,该函数可用于生成适当的性能度量。我们将首先演示一个简单但不幸不正确的方法来使用这个函数。

计算性能指标需要几分钟时间(脚本可能会在完成前超时),因为算法必须对所有 28,000 名受试者进行预测,并根据所有这些数据点计算决定系数。我们可能会惊喜地发现 R2 的值是 0.98(接近完美),直到我们意识到自己的错误。请记住,kNN 算法的工作原理是从训练数据集中找到与测试主题相似的主题。如果我们使用来自相同训练数据集的测试主题,那么该算法必然会从训练数据集中找到与测试主题相同的主题。因此,它会产生一种模型运行良好的错觉。

计算模型的性能度量的正确方法是使用不与定型数据集重叠的验证数据集。有三种方法可以创建这样的验证数据集。在一项精心设计的研究中,研究者可能会从外部站点招募额外的受试者(以声称该模型经过外部验证)。另一种方法是保留原始数据集的一部分(通常为 20%)作为验证数据集,只使用剩余的 80%作为训练数据集。这种方法的缺点是减少了训练数据集的大小。最流行的方法是进行所谓的 k 倍交叉验证。其思想是,我们将原始数据集分成k部分,使用第一部分进行验证,其余部分用于训练。然后,我们再次重复这个过程,第二部分用于验证,其余部分用于训练。重复该过程,直到每个零件都被用于一次验证和k-1次训练。最后,我们通过取平均值来报告性能度量。

作者图片

为了使用 DRESS Kit 中的DRESS.crossValidate函数执行交叉验证,我们需要指定机器学习模型、数据集以及创建和验证模型所需的超参数。代码有点复杂,因为我们需要将这些超参数作为两个独立的数组传递。可选地,我们可以使用DRESS.async异步调用该函数,以防止脚本超时。

最佳化

K 值

大多数人想到的第一个优化,也可能是最不重要的,是k的值。直观地,我们可以理解,如果k太大(例如,整个训练数据集的大小),那么模型将不会非常准确,因为它将不会做出更好的类似预测(即,欠拟合)。如果k太小(例如 1),那么该模型在应用于验证数据集时也不会非常准确,因为它容易在训练数据集中产生噪声(即过拟合)。k的最佳值高度依赖于训练数据集中的噪声量(或结果值的随机变化)。

作者图片

确定k最佳值的唯一方法是对一系列值进行交叉验证。也就是说,在大型数据集(如我们正在处理的数据集)中,训练数据集通常几乎均匀地分布在样本空间中,因此k值的微小变化不会显著影响预测。例如,考虑下图,其中红色的星代表训练对象,绿色的星代表测试对象。我们可以看到,与右侧的数据集相比,左侧数据集的k值为 3 和k值为 4 之间的差异要大得多。此外,DRESS Kit 使用的 kNN 算法实际上是一种加权 kNN 算法,这意味着它考虑了训练对象和测试对象之间的距离度量,并减少了高度不相似的对象的影响,即使它们被包括在内。

作者图片

特征选择

对于 kNN 机器学习技术来说,更重要的优化是特征选择,即用于构建模型的预测器。直观地,我们可以理解,如果预测值与结果没有关系(例如,SSN 和身体质量指数的最后 4 位),那么模型的性能可能会受到包含这种预测值的不利影响。与可以自动最小化无关紧要的预测器的影响的一些其他机器学习技术不同,kNN 模型中包括的每个预测器都对距离度量有贡献。选择最佳的特性集需要大量的领域知识,但是我们也可以使用交叉验证来验证我们的选择。

为了证明正确的特征选择的重要性,我们将引入两个填充了随机值的预测值,以观察它们如何影响模型的性能。

我们可以看到,包含两个随机生成的预测值实际上会降低整体性能并减慢模型的速度。

特征缩放

对于 kNN 机器学习技术来说,同样重要的优化是特征缩放。默认情况下,kNN 算法会在构建模型之前对所有预测值进行归一化。这样做是为了使具有更宽范围的特征(例如,血小板计数,其值的范围可以从<50 to > 250)对距离度量具有与具有更窄范围的特征(例如,肌酸酐,其值通常在~1 到< 10 之间)相同的效果。凭直觉,我们可以想象,如果我们要建立一个 kNN 模型来预测接受结肠镜筛查的患者中结肠息肉的数量,息肉综合征家族史将是比抑郁症家族史更强的预测因素。我们可以通过放大或缩小来设置每个预测器的“强度”。不幸的是,没有办法通过算法来确定最佳比例。需要大量的领域知识和反复试验。

归罪

kNN 算法最常见的应用之一是缺失值插补。我们之前已经介绍了一种简单的插补技术,用均值或模式替换缺失值。虽然均值/众数插补在缺失值很少的大型数据集中工作得相当好,但每个缺失值都会被相同的替换值替换。kNN 插补本质上是均值/众数插补的更高级版本,它不使用整个数据集的均值/众数,而是使用与缺失值受试者相似的受试者的均值/众数作为替代。

为了实现 kNN 插补算法,我们只需将受试者分为没有缺失值的受试者和有缺失值的受试者。接下来,我们使用前者来构建一个 kNN 模型,并在后者中找到每个主题的顶部k邻居。最后,我们将均值/众数插补技术应用于基于那些k邻居的缺失值。

ACCESS2 : 1 (0.00%) 
BPMED : 0 (0.00%) 
CHECKUP : 0 (0.00%) 
CHOLSCREEN : 0 (0.00%) 
COLON_SCREEN: 19 (0.07%) 
COREM : 103 (0.38%) 
COREW : 109 (0.40%) 
DENTAL : 0 (0.00%) 
MAMMOUSE : 37 (0.14%) 
PAPTEST : 7 (0.03%) 
BINGE : 0 (0.00%) 
CSMOKING : 0 (0.00%) 
LPA : 0 (0.00%) 
OBESITY : 0 (0.00%) 
SLEEP : 0 (0.00%)

插补算法足够智能,可以识别那些具有缺失(空)值的受试者,并根据那些没有缺失值的受试者计算适当的替代值。

群组匹配

kNN 算法的另一个常见应用是群组匹配。在大多数回顾性研究中,为了计算相关的风险比或优势比,有必要确定一个对照组(一组没有结果或暴露的受试者)。理想情况下,实验组和对照组应该在每个方面都几乎相同,除了结果或兴趣的暴露。因为 kNN 算法被设计为基于相似性来识别主题,所以它非常适合这个目的。

ACCESS2 : [93] 27.08 (95% CI 25.33 - 28.84) SD: 8.64 SKW: 1.55 KUR: 2.82 vs [93] 26.82 (95% CI 25.03 - 28.62) SD: 8.81 SKW: 1.31 KUR: 1.60 z: +0.20 p: 0.84 
BPMED : [93] 80.90 (95% CI 79.98 - 81.82) SD: 4.53 SKW: -0.15 KUR: 0.64 vs [93] 78.79 (95% CI 78.00 - 79.59) SD: 3.93 SKW: -0.28 KUR: -0.27 z: +3.38 p: 0.00 
CHECKUP : [93] 76.15 (95% CI 74.93 - 77.36) SD: 5.98 SKW: -0.77 KUR: -0.21 vs [93] 75.72 (95% CI 74.58 - 76.85) SD: 5.59 SKW: -1.07 KUR: 0.23 z: +0.51 p: 0.61 
CHOLSCREEN : [93] 76.13 (95% CI 75.01 - 77.25) SD: 5.50 SKW: -0.27 KUR: 0.18 vs [93] 75.85 (95% CI 74.86 - 76.85) SD: 4.89 SKW: -0.61 KUR: 0.32 z: +0.37 p: 0.71 
COLON_SCREEN: [93] 46.24 (95% CI 44.92 - 47.57) SD: 6.51 SKW: -0.18 KUR: -0.40 vs [93] 47.24 (95% CI 46.05 - 48.42) SD: 5.84 SKW: -0.03 KUR: 0.02 z: -1.10 p: 0.27 
COREM : [93] 18.36 (95% CI 17.40 - 19.31) SD: 4.69 SKW: 0.31 KUR: 2.34 vs [93] 18.80 (95% CI 17.89 - 19.71) SD: 4.49 SKW: 0.14 KUR: 2.93 z: -0.66 p: 0.51 
COREW : [93] 17.26 (95% CI 16.38 - 18.14) SD: 4.32 SKW: 0.90 KUR: 7.91 vs [93] 17.56 (95% CI 16.84 - 18.29) SD: 3.57 SKW: -0.11 KUR: 7.89 z: -0.53 p: 0.60 
DENTAL : [93] 33.08 (95% CI 31.80 - 34.36) SD: 6.30 SKW: 0.79 KUR: 1.38 vs [93] 35.03 (95% CI 33.86 - 36.21) SD: 5.78 SKW: 0.86 KUR: 1.69 z: -2.20 p: 0.03 
MAMMOUSE : [93] 79.43 (95% CI 77.65 - 81.21) SD: 8.76 SKW: -8.00 KUR: 69.73 vs [93] 80.78 (95% CI 80.21 - 81.36) SD: 2.83 SKW: -0.72 KUR: -0.25 z: -1.42 p: 0.16 
PAPTEST : [93] 81.95 (95% CI 80.15 - 83.75) SD: 8.86 SKW: -8.50 KUR: 75.74 vs [93] 82.59 (95% CI 80.79 - 84.40) SD: 8.89 SKW: -8.62 KUR: 77.13 z: -0.49 p: 0.62

在上面的例子中,我们将身体健康结果(PHLTH)差于 25%的受试者定义为实验组。我们的目标是建立一个对照组,在预防服务的使用方面与实验组相匹配。我们基于其余受试者构建一个 kNN 模型,并使用该模型的match函数为每个实验受试者确定一个控制受试者。最后,我们通过计算两组的平均值来评估匹配的质量。我们可以看到,除了使用降压药(BPMED)和看牙医(DENTAL)之外,两组之间使用预防服务的所有其他措施都相当。

概述

让我们复习一下第四部分所学的内容。我们讨论了 kNN 机器学习算法的优势和局限性,并在 DRESS Kit 中演示了实现它的代码(DRESS.kNN)。我们继续讨论各种度量,包括回归问题的决定系数、平均绝对误差和均方根误差,以及分类问题的准确度、精确度、召回率和 F 分数,用于评估机器学习模型的性能(model.performance)。我们还介绍了交叉验证技术(DRESS.crossValidate),作为一种使用相同数据集进行训练和验证的方法。我们继续讨论 kNN 建模技术的各种超参数的优化,例如k的值、特征选择和特征缩放。最后,我们展示了使用 kNN 算法作为缺失值插补技术(model.impute)以及群组匹配技术(DRESS.match)。

模型摘要

K-最近邻

强项

  • 易于实现(距离度量计算相当简单)
  • 易于解释(算法只是寻找相似的主题)
  • 使用数字和分类预测器
  • 可用于分类、回归、群组匹配和插补

限制

  • 预测速度慢(需要为每次预测计算整个训练数据集的距离度量)
  • 难以部署(模型由整个训练数据集组成)
  • 无法在训练数据集之外进行推断
  • 倾向于离群值

医学中的机器学习——第五部分

原文:https://towardsdatascience.com/machine-learning-in-medicine-part-v-10231d5511e5?source=collection_archive---------37-----------------------

针对医生和医疗保健专业人员的机器学习技术实践入门课程。

集成决策树

Steven Kamen ar 在 Unsplash 上拍摄的照片

概述

在本课程的 第四部分中,我们探讨了 k 近邻(kNN)。我们演示了使用 DRESS Kit 构建 kNN 模型的步骤,以及使用该模型进行预测的步骤。我们绕道讨论了各种模型性能指标,包括回归问题的决定系数、平均绝对误差和均方根误差,以及分类问题的准确度、精确度、召回率和 F 分数。在讨论 kNN 算法特有的各种优化技术之前,我们还介绍了交叉验证技术。最后,我们展示了使用 kNN 算法作为缺失值插补技术以及队列匹配技术。

回想一下,线性/逻辑回归模型的局限性之一是其平滑和连续的决策边界。与线性/逻辑回归模型相比,kNN 模型的一个主要优势是它能够创建任意大小的循环决策边界(基于k的值)。决策树模型通过允许创建任意的决策边界而代表了进一步的改进。

礼服套件更新

在继续本课程的其余部分之前,请花点时间更新服装套件以发布 1.2.9 。该版本包含对随机森林和梯度推进机器算法的显著性能改进。

决策图表

决策树。图片作者。

模型概述

在讨论集成决策树之前,我们必须首先介绍一个决策树的概念。决策树通常被描述为流程图。从决策树的顶端(矛盾地称为根)开始,通过特定标准将数据集分成两组(例如,年龄大于 50,血红蛋白小于 7g/dL,性别等于男性,既往病史包括糖尿病等。),符合标准的主体属于一个群体,不符合标准的主体属于另一个群体。每个组(通常称为节点)根据另一个标准再次分成两个。重复该过程,直到满足一些预定义的停止标准。当我们需要使用决策树模型进行预测时,我们只需从根开始跟随该树,一直行进到末端节点(没有进一步分割的节点),并通过取属于该末端节点的那些主题的平均值(对于回归问题)或模式(对于分类问题)来计算结果。

直观地,我们可以理解决策树模型的性能如何受到分裂标准的选择的影响。完全无用的决策树模型是简单地将一个节点随机分成两部分的模型,因为这种模型的预测能力不会比随机猜测更好。因此,为了构建一个有用的决策树模型,我们必须在分割后尽量减少随机性的程度。有几种方法可以测量机器学习模型中的随机性。最常用的有分类问题的基尼杂质熵/信息增益和回归问题的方差。就本课程而言,了解基尼系数、信息增益或方差背后的数学原理并不重要。可以说,当这些指标下降到零时,与该节点相关的所有主题都具有相同的结果值,进一步分割该节点没有任何好处。为了构建一个最优的决策树模型,该算法只需要找到分裂准则,该准则在其后代节点中产生最低程度的总随机性。

优势和局限性

基于上面的描述,我们可以很容易地看到决策树如何能够支持任意的决策边界。层中的每个节点都独立于同一层中的其他节点运行。假设我们根据 60 毫米汞柱的平均动脉压(MAP)将受试者分为两组,然后我们可以根据一个标准(例如,7g/dL 的血红蛋白水平)将那些具有低 MAP 的受试者分为两组,并根据不同的标准(例如,不同的血红蛋白水平或完全不相关的因素,如性别或身体质量指数)将那些具有高 MAP 的受试者分为两组。

我们还可以看到决策树本质上是 if-then-else 语句的级联。这意味着决策树可以对数字特征和分类特征进行操作(只要您可以基于特征构造 if-then-else 语句,它就可以作为决策树中的一个节点)。这也意味着决策树可以在预测阶段以极快的速度运行。不需要复杂的矩阵乘法、求幂或排序。最后,很容易解释决策树模型的结果。为了理解预测是如何做出的,我们只需要手动地从根开始跟踪树。

决策树建模技术的一个小限制是不能在每个节点考虑多个预测器。例如,如果数据集只包含身高和体重作为预测因素,但结果实际上与身体质量指数更相关,决策树模型可能无法有效地捕捉这种关系。然而,决策树模型的主要限制是有过度拟合的倾向。这部分是由于决策树模型创建任意决策边界的能力,部分是由于随着树变得更深,节点数呈指数增长。

曲线拟合。图片作者。

考虑一个有 1000 名受试者的假设数据集。让我们假设每个受试者都可以通过预测因子的组合来唯一识别,这并不是完全不现实的,例如,考虑到两个受试者具有完全相同的身体质量指数、血红蛋白水平、血小板计数、收缩压、心率和总胆固醇水平的几率。我们能否构建一个决策树模型,保证在应用回训练数据集时 100%准确?答案是肯定的。事实上,它只需要一个深度为 10 (2 ⁰ = 1024)的决策树。一个 20 层的树可以唯一识别超过 100 万个主题。集成决策树模型背后的整个思想是克服单个决策树模型容易过度拟合的事实。

随机森林/额外树木模型

模型概述

随机森林的基本假设是,一些预测值和结果之间的关系可以由一组决策树(许多许多树,因此是一个森林)来表示,每个决策树只对关系的某个方面进行建模。这有点像古代亚洲盲人摸象的寓言。每个人只能根据他与大象有限的互动来欣赏大象的某些特征,但是他们一起对大象的描述相当准确。我们也可以把随机森林/额外的树看作一种民主或多数统治。

盲人和大象。图片由 CC0 大都会艺术博物馆通过维基共享资源提供。

用于在随机森林模型中创建决策树集合的技术被称为打包,这是自举和聚合的结合。自举是指用替换采样的过程。例如,我们有一个 9 个受试者的池,我们想通过引导创建一个 7 个受试者的样本,我们将选择一个受试者(例如受试者 A) 而不从池中删除它。当我们需要选择下一个科目时,再次选择科目 A 的概率不变。Bootstrapping 允许我们创建彼此之间以及与原始数据集完全不同的样本,但是所有样本加在一起应该类似于原始数据集的分布。假设原始数据集的性别分布是 60:40,通过自举创建的每个样本的性别分布可能不完全是 60:40,但是如果我们生成大量样本,所有这些样本的性别分布作为一个整体将接近 60:40。

装袋。图片作者。

随机森林模型用来最小化过度拟合的第二种技术被称为特征子空间,它简单地限制了每个决策树所使用的特征的选择。这防止了与结果高度相关的某些预测器被选为每个决策树中的分裂标准。通过使用 bagging 和特征子空间,随机森林算法可以创建大量决策树,每个决策树都在一个样本上训练,该样本来自数据集但不完全相同,并且仅捕获某些预测器和结果之间的关系。在预测阶段,该算法将测试主题应用于森林中的所有树,并基于平均值(对于回归问题)或模式(对于分类问题)计算最终预测。其思想是,预测者和结果之间的关系“重要”将被大多数树捕获,而那些无关紧要的关系将在聚合过程中被抵消或消除,因为它们仅被森林的一小部分捕获。

额外的树(或者极度随机化的树)非常类似于随机森林,但是提供了一些计算上的优势。在随机森林模型中,每个决策树仍然充当常规决策树,并基于最佳分裂标准来分裂节点,这可能在计算上是昂贵的,尤其是对于数字特征。相反,额外树算法随机选择分裂标准。只要生成的决策树比一个完全无用的决策树(基于像基尼系数、熵和方差这样的指标)执行稍好一点,它就会被森林接受。每棵树也在整个数据集上训练,因此消除了装袋步骤。尽管额外的树具有计算优势,但这两种建模技术的准确性是相当的(示例在这里在这里)。

优势和局限性

随机森林/额外树相对于单个决策树的优势是显而易见的——抵抗过度拟合,但它也有一些缺点。因为由这两种技术创建的模型是由数百个决策树组成的,所以在生产环境中部署这些模型可能具有挑战性。解释模型也很困难,因为要分析的决策树数量太多,而且有些树的表现可能很差。

随机森林/额外树的另一个缺点是这些算法的概率性质。我们之前学习的线性/逻辑和 kNN 算法是确定性的,这意味着每次应用相同的训练数据集时都会创建完全相同的模型。相比之下,随机森林/额外树算法使用的装袋、特征子空间和随机分裂技术会引入一定程度的随机性,并在每次应用训练数据集时创建完全不同的模型。一个模型可能比下一个模型表现得更好或更差,这使得模型优化更具挑战性。

履行

现在有足够的基本理论,让我们开始建立我们的第一个集合决策树模型。DRESS Kit 确实附带了一个名为DRESS.randomForest的函数,但是它实际上在内部实现了额外的树算法以提高计算效率。

因为我们所有的预测值都是数值型的,所以我们将它们作为第三个参数传递给DRESS.randomForest函数,并将一个空数组作为第四个参数传递(它接受一个分类预测值数组)。我们还将第五个参数设置为false,因为我们正在构建一个回归模型。模型本身的打印输出并不包含很多信息,除了正在建模的结果和一个seed值,通过将DRESS.SEED全局变量设置为该值,该值可用于在未来重新创建完全相同的模型。

我们可以使用该模型进行预测,就像礼服工具包中的任何其他机器学习模型一样。

为了创建分类模型,我们简单地将DRESS.randomForest函数的第五个参数设置为true

最佳化

在我们讨论可以在我们的随机森林(实际上是额外的树)模型上完成的各种优化之前,让我们回忆一下如何使用DRESS.crossValidateDRESS.async来评估机器学习模型的性能。事实证明,默认的超参数设置远远没有优化我们想要做的事情。

树木计数

首先想到的优化是森林中的树木数量。直观上,我们可以看到,如果模型仅由几棵树(例如 5-10 棵树)组成,并且每棵树只对预测因子的子集进行操作,则最终模型可能无法捕捉预测因子和结果之间关系的某些方面。然而,一旦我们达到了足够数量的树,进一步的增加往往不会提高整体性能,相反,会大大降低模型的效率。训练 1000 棵树需要的计算能力是训练 100 棵树的 10 倍,但不太可能将精度提高 10 倍。一般来说,我们可以从 50-100 棵树开始,然后通过增加一倍来逐步增加树的数量,直到模型性能开始稳定。

树木计数。图片作者。

树深

在优化中,树的深度比树的数量起着更重要的作用。直观地,我们可以看到,如果树深度设置为 1,那么每棵树将只有 2 个结束节点。即使有大量的树,该模型也不会非常准确,因为正态分布曲线两端的结果值会被接近平均值的结果值超过。这个问题对于具有不均匀类别分布的多类别分类模型尤其重要。因为模型的最终预测是通过从所有树中取模式来计算的,所以如果每个树中的端节点的数量明显小于类的数量,则那些罕见的类几乎永远不会被选为模式。相反,如果树深度设置得太高,过度拟合可能会变得更加明显。

树的深度。图片作者。

子空间比率

随机森林/额外树算法的一个同样重要的优化是特征子空间比率,因为它是最终模型随机性的主要来源之一(bagging 比率和随机分割标准分别是随机森林和额外树的另一个来源)。换句话说,子空间比率控制欠拟合和过拟合之间的平衡。考虑由强预测器和弱预测器的组合构成的模型,通过将子空间比率设置为 1,弱预测器可能被包括在一些树中,当应用回训练数据集时,所得模型将非常准确,但是当应用到独立验证数据集时,将表现不佳,即过拟合。如果子空间比率设置为 0,那么该模型是完全无用的,因为它没有考虑任何预测值。需要大量的反复试验来确定特定模型的最佳子空间比。

子空间比率。图片作者。

功能选择

像任何其他机器学习模型一样,特征选择是模型性能的基础。与单个决策树的情况一样,集合决策树一次只能基于一个预测因子来分割节点,因此,向算法提供适当的预测因子(例如,身高和体重与身体质量指数)是很重要的。与线性/逻辑回归和 kNN 相比,决策树模型受弱预测器的影响较小(假设子空间比率超参数被适当调整),并且根本不受特征缩放的影响。

梯度推进机

模型概述

梯度推进机。图片作者。

虽然它仍然被认为是一个集成决策树模型,但梯度推进机与随机森林/额外树有很大不同。每个决策树都试图减少前一个决策树产生的错误,而不是成为一个多数人统治的民主国家。梯度推进机器中的决策树被排列成链。第一个决策树就像任何其他单个决策树一样,通过模拟预测器和结果之间的关系来运行。第二个决策树对第一个决策树产生的残差进行建模,但方向相反(即正的变为负的,负的变为正的)。然后,将训练集一起应用于第一和第二决策树,并且通过第三决策树对残差进行建模(再次在相反的方向上)。重复该过程,直到剩余误差可以忽略或者已经添加了预定数量的树。

优势和局限性

根据 Kaggle 上许多机器学习竞赛的结果,当调整得当时,梯度增强机器似乎优于随机森林/额外树木模型。然而,这种性能的提高是有代价的。梯度增强机器的训练时间比随机森林/额外树长得多,因为每次创建新树时,必须将整个训练数据集应用于工作模型,以便计算残差。训练阶段不能被并行化,因为每个树都依赖于先前树产生的残差。梯度推进机器也不能很好地处理多类分类问题,因为每个类都需要一个单独的决策树链。解释结果模型也要困难得多,因为除了第一个决策树之外,该模型关注的是预测值和残差之间的关系,而不是结果值。最后,梯度增强机器比随机森林/额外树模型更容易过度拟合。

履行

除了调用DRESS.gradientBoosting而不是DRESS.randomForest之外,创建梯度增强机器几乎不需要修改用于创建随机森林/额外树木模型的代码。请注意,由于每次创建新的决策树时都要应用整个训练数据集,因此完成代码所需的时间要长得多。

最佳化

数树

根据一般经验,梯度推进机器可以使用更少的决策树实现与随机森林/额外树模型相当的性能水平。这部分是因为这样一个事实,即通过设计,在随机森林/额外树模型中不是所有的决策树都是有用的,而在梯度推进机器中,每个决策树都将残余误差减少一定量。向梯度推进机器添加太多的树会显著增加训练时间(随着残差的减小,创建最优决策树可能会更加困难),并且最终会导致过拟合。

树木计数。图片作者。

树深

就像树计数一样,梯度推进机器通常可以实现与使用较浅决策树的随机森林/额外树模型相当的性能水平。这是由于剩余误差倾向于在几棵树后集中在中心界限周围,结果,需要由每棵树处理的随机性程度(即均方误差)很小。拥有一个过深的树是梯度增强机器中过拟合的一个常见原因。

树的深度。图片作者。

子空间比率

子空间比率对于梯度增强机器的工作方式与对于随机森林/额外树模型的工作方式有些不同,至少对于着装套件实现是这样。在训练阶段,子空间比率被应用于训练数据集,而不是特征。因为每个决策树只对来自训练数据集子集的残差建模,所以选择小的子空间比率可以减少训练时间。正如所料,选择一个大的子空间比率会导致过度拟合。

子空间比率。图片作者。

学习率

学习率决定了每个决策树对多少残差进行建模。它通常被设置为 0.1 到 0.3 之间的一个小数字,这意味着每个决策树将只试图解释 10-30%的残差,而剩余的 70-90%的残差将由后续的决策树处理,这些决策树对训练数据集的不同子集进行操作(由子空间比率超参数确定)。事实上,这两个超参数是防止梯度推进机器过度拟合的主要保障。然而,将学习率设置得太低会导致欠拟合,或者需要通过高树计数来补偿,这会降低模型的效率。

学习率。图片作者。

特征重要性

回想一下我们在本课程的第三部分中讨论过的将线性/逻辑回归用作机器学习模型和将其用作传统回归分析技术之间的概念差异。虽然机器学习模型不是设计来评估预测器/特征和结果之间是否存在统计上显著的关联,但有时确定特定特征/预测器是否重要仍然是有用的。如果某个特征被认为不重要,那么在没有所述特征的情况下重建模型可能更有效。在线性/逻辑模型中,很容易识别那些不重要的特征。在 kNN 模型中,每个要素都同等重要(除非某些要素的缩放比例不同,并且关闭了归一化标志)。如何客观地度量集成决策树模型中某个特征的重要性?

请记住,决策树的目标是减少数据集中的随机程度。测量特征重要性的一种方法是计算与每个特征相关的随机程度的减少。例如,在分类模型中,我们可以计算整个训练数据集的基尼系数,以及每次分割后的基尼系数。每次分割前后基尼系数的差异反映了被用作分割标准的特征所降低的随机性程度。我们只需要计算与每个特征相关的基尼系数杂质的总减少量,就可以量化它的重要性。在回归模型中,我们可以通过计算每次拆分前后方差的差异来获得相同的结果。

方便的是,由 DRESS Kit 创建的集合决策树模型带有一个内置函数(model.importance),该函数根据基尼不纯度或方差自动计算特征重要性。

LPA : 1209.08 
OBESITY : 1038.83 
DENTAL : 1020.85 
CSMOKING : 877.34 
COLON_SCREEN: 605.89 
COREW : 584.14 
BINGE : 573.65 
SLEEP : 464.21 
COREM : 383.77 
BPMED : 380.73 
ACCESS2 : 311.41 
CHECKUP : 149.87 
PAPTEST : 128.30 
CHOLSCREEN : 110.00 
MAMMOUSE : 60.40

基于打印输出,我们可以得出结论:LPA(年龄> =18 岁的成年人在闲暇时间没有体育活动)是模型中最重要的预测因素,比MAMMOUSE重要几个数量级。如果我们建立两个模型,一个有和一个没有MAMMOUSE预测器,我们可以看到这两个模型之间没有性能差异。

包裹

让我们回顾一下我们在第五部分学到的内容。我们介绍了决策树作为机器学习模型的概念,并讨论了它的优势和局限性,特别是过度拟合的风险。我们讨论了随机森林模型是如何通过使用诸如装袋和特征子空间等技术来降低过度拟合的风险的。我们还介绍了额外树模型,并解释了如何使用它作为随机森林的计算效率更高的替代品。我们继续演示使用DRESS.randomForest构建额外树模型的代码,并讨论了各种优化点。然后,我们继续讨论另一个集合决策树模型,梯度推进机,以及它与随机森林/额外树模型的比较。我们再次展示了构建梯度推进机器DRESS.gradientBoosting的代码,并讨论了它的优化。最后,我们回顾了使用model.importance函数评估特性重要性的步骤。

模型摘要

随机森林/多余树木

优势

  • 支持任意决策边界
  • 使用数字和分类预测器
  • 非常快地做出预测
  • 不易过度拟合

限制

  • 难以解释(涉及许多采油树,有些设计表现不佳)
  • 难以优化(要考虑许多超参数,算法不确定)

梯度推进机

优势

  • 支持任意决策边界
  • 使用数字和分类预测器
  • 非常快地做出预测
  • 性能优于随机森林/额外树

局限性

  • 仍然倾向于过度拟合
  • 训练要慢得多
  • 难以解释(大多数树模拟残差而不是结果)
  • 难以优化(要考虑许多超参数,算法不确定)

锻炼

作为练习,尝试创建一个随机森林模型和一个梯度推进机器来预测一个假设的城市/城镇中的癌症患病率。通过以系统的方式调整各种超参数,专注于优化模型。创建一个表来跟踪超参数值变化时模型性能的变化可能是有用的。

医学中的机器学习——第六部分

原文:https://towardsdatascience.com/machine-learning-in-medicine-part-vi-5470b7f634b7?source=collection_archive---------29-----------------------

针对医生和医疗保健专业人员的机器学习技术实践入门课程

人工神经网络

哈尔·盖特伍德在 Unsplash 上拍摄的照片

概述

在本课程的 第五部分中,我们探讨了两种集成决策树算法,随机森林/额外树和梯度推进机。我们首先讨论了单一决策树模型的优势,以及更重要的局限性。我们引入了装袋和子空间的概念,作为最小化过度拟合的手段。我们演示了使用服装工具包构建随机森林/额外树木模型以及渐变加速机器的步骤。我们还研究了这两种建模技术的各种优化技术。最后,我们讨论了计算特征重要性的概念和算法。

集成决策树模型相对于 kNN 和逻辑/线性回归的一个主要优势是它们支持任意决策边界的能力,但是决策树中的每个节点一次只能对一个特征进行操作。人工神经网络代表了能够实现高级抽象的进一步改进。

礼服套件更新

在继续本课程的其余部分之前,请花点时间更新服装套件以发布 1.3.0 。此版本包含对神经网络算法的重大功能改进和更改,以及新数据转换算法的添加。

模型概述

人工神经网络的工作原理是假设存在一个可计算的函数,将预测值映射到结果。顾名思义,人工神经网络是受生物神经网络的启发。每个人工神经元是人工神经网络的基本操作单元,是生物神经元的功能抽象。它接受来自网络中上游神经元的一个或多个输入,就像生物神经元通过其树突接受来自上游神经元的信号一样。在生物神经元中,如果膜电位达到某个去极化阈值,就会触发一个动作电位,并沿着轴突传递到下游神经元。在人工神经元中,输入由激活函数(加上一些其他数学运算)处理,输出被传输到下游神经元。

神经元。图片作者。

我想到的第一个问题是,一个相互连接的人工神经元网络是如何学习任何东西的。关键在于上述的数学运算。每个输入乘以两个神经元之间连接固有的权重因子,并且每个神经元固有的另一个因子(称为偏差)在最终值被激活函数处理之前被添加到所有加权输入的总和。神经网络可以通过调整这些权重和偏差来“学习”新信息。

需要注意的是,人工神经网络只是一个统称。根据人工神经元之间的连接方式,可以创建各种机器学习模型。最基本和最常用的人工神经网络被称为多层感知器。

多层感知器。图片作者。

在多层感知器中,神经元排列在离散的层中。同一层中的所有神经元共享相同的激活函数。特定层中的每个神经元都与下一层中的所有神经元相连。要创建一个多层感知器,首先必须确定层数、每层中神经元的数量以及每层中使用的激活函数。网络中的权重和偏差首先被初始化为一些随机值。然后将训练样本按顺序或分批输入到模型中,并将模型的输出与训练数据集中的真实值进行比较。最初,模型的输出会非常不准确,但是误差通过模型反向传播到网络中的每一层神经元。调整与每个连接相关联的权重和与每个神经元相关联的偏置,以便减少整个网络的误差。通过多次重复这些正向传播和反向传播步骤,多层感知器可以慢慢地学习预测值和结果值之间的关系。

向前和向后传播。图片作者。

反向传播过程背后的详细数学相当复杂,涉及求解一系列偏导数。可以说,这些导数函数的结果允许权重和偏置以与每个神经元的输出误差相反的方向和成比例地被调整。

优势和局限性

一般来说,多层感知器和人工神经网络的最大优势是它支持高级抽象的能力。事实上,人工神经网络被认为是通用函数逼近器,这意味着只要有足够数量的相互连接的神经元和层,它们就可以逼近几乎任何已知的函数。换句话说,理论上,人工神经网络可以模拟预测者和结果之间的任何关系,即使这种关系本质上是随机的。

多层感知器的另一个优势是它能够同时模拟多个结果,方法是将网络的输出层设置为所需的结果数,并指定适当的损失函数。如果我们需要建立一个模型来预测几个不同但多少有些关联的结果,这可能会非常方便。例如,我们可以建立一个模型来预测自发性细菌性腹膜炎发作后 30 天的死亡率和 1 年的全因死亡率。

这种逼近预测者和结果之间任何关系的能力伴随着几个重要的权衡。首先,训练一个多层感知器计算量很大。每次向前和向后传播都涉及多个矩阵计算。与集成决策树模型相比,通常需要大得多的训练数据集来训练人工神经网络。训练过程通常包括重复整个训练数据集数百或数千次。

其次,众所周知,人工神经网络很难优化。必须考虑神经元的层数、每层中神经元的数量、每层中激活函数的选择、权重/偏差初始化的方法、学习速率、退出率、训练周期的数量、损失函数以及一系列其他高级优化参数。给定上述长的训练时间,通常很难系统地测试超参数的所有排列。

第三,人工神经网络起到了黑匣子的作用。通过检查这些权重和偏差的值来解释神经网络如何以及为什么做出某个决定实际上是不可能的。事实上,在相同数据集上训练的具有相同结构并且具有相似性能的两个神经网络可能具有非常不同的权重和偏差集。此外,因为每个神经元都连接到下游层的所有神经元,所以预测器都混合在网络的更深层。不可能准确地确定一个特定的预测器如何影响网络的结果。

第四,人工神经网络只对数值型预测因子起作用,需要大量的数据准备(将不同预测因子的值归一化,并转换其分布),才能达到良好的效果。

履行

让我们开始建立我们的多层感知器。正如我们前面提到的,训练一个神经网络在计算上是很昂贵的,所以为了避免脚本超时错误,最好异步进行。

该脚本与我们用来创建随机森林/额外树木模型或梯度推进机器的脚本略有不同。让我们详细了解一下这些变化。我们不直接调用DRESS.multilayerPerceptron函数,而是调用DRESS.async,这是 DRESS Kit 中的一个实用函数,支持异步函数调用。第一个参数是我们希望异步运行的 DRESS Kit 函数的名称。需要注意的是,我们不是将实际的函数作为参数传递,而是将函数的名称作为字符串传递。后续参数的传递方式与我们同步调用DRESS.multilayerPerceptron的方式相同。DRESS.async函数返回一个 JavaScript 承诺,一旦函数完成,它将最终解析为一个结果对象。这里有必要回顾一下异步编程的基本概念。为了对结果对象进行操作,我们需要调用与承诺对象相关联的.then函数,并传递一个箭头函数作为参数。arrow 函数应该接收结果对象作为参数。

由于 JavaScript 固有的局限性,Promise 对象解析的结果对象不包含任何可执行函数。在我们可以调用model.predict函数或另一个与模型相关的函数之前,我们必须重建模型。幸运的是,可以通过将结果对象再次同步传递到DRESS.multilayerPerceptron中来轻松高效地完成。我们将整个 Promise 对象和then函数一起传递给DRESS.print,它将自动显示一个计时器来帮助我们跟踪异步函数调用的进度。我们从then函数中返回预测结果,这样它也可以由DRESS.print函数显示。

我们可以通过将结果代入state并将分类标志代入true来构建分类模型,但重要的是要注意,分类模型的训练时间要长得多,因为构建所有 50 个状态的模型所需的神经元数量要大很多倍。

在线培训

在人工神经网络的训练阶段,应用每个训练样本来更新网络的权重和偏差,并且之后不再需要。因此,人工神经网络的训练过程可以顺序进行。我们可以用一个小数据集(甚至只有一个样本)来训练模型,测试模型的性能,并在更多的训练样本变得可用和必要时应用它们,而不是一次性应用整个数据集。

我们可以通过将训练数据集分成多个批次并一次应用一个批次来模拟这种在线训练行为。首先,我们通过调用DRESS.multilayerPerceptron使用第一批训练样本构建一个多层感知器,然后使用model.performance测试性能,并使用model.train应用额外的训练样本。我们可以从打印输出中看到,模型的性能在最初几批中波动很大,但在训练过程结束时会有所改善和收敛。

值得注意的是,为了使用这种在线训练方法建立分类模型,我们必须确保第一批训练样本包含所有可能的结果值,因为神经网络的输出层是在模型首次由DRESS.multilayerPerceptron函数建立时设置的。通过model.train应用额外的训练样本不会改变神经网络的布局。

最佳化

优化人工神经网络可能相当具有挑战性。我们将从评估模型的基线性能开始。请注意,交叉验证时间相当长,因为算法需要建立和训练五个独立的模型。

在我们详细研究每个超参数之前,重要的是要强调一些优化技术可能是特定于实现的,这意味着根据底层代码,某些优化可能比其他优化具有更高的产量,而某些超参数可能由于特定于实现的限制而不可用。例如,多层感知器的服装工具包实现只支持亚当优化器,但是还有其他几个优化器,比如 RMSPropAdaGrad

网络布置

设计神经网络时,我们需要考虑的第一件事是神经网络的结构。通常,多层感知器的输入层被设置为与模型中预测器的数量相同的大小,而输出层被设置为回归模型中预测器的数量或分类模型中不同类别的数量。隐藏层(输入和输出之间的层)中的神经元数量基本上没有限制。以一种过于简化的方式,我们可以将隐藏层中的每个神经元视为控制输入信号如何流向输出层的决策单元。通过增加每层神经元的数量,理论上,网络可以处理预测者和结果之间更复杂的关系。当然,拥有大量神经元的缺点是训练时间更长。拥有太多的神经元也会导致过度拟合,尽管由于其他的正则化技术,这对于多层感知器来说一般不是问题。

增加多层感知器的层数也会增加网络处理复杂问题的能力,但方式不同。由于隐藏层中的每个神经元都完全连接到相邻层中的所有神经元,因此更深层中的神经元同时基于多个预测器的组合来做出决策。因此,添加层使网络能够达到更高的抽象级别。然而,重要的是要注意,增加额外的层会成倍地增加训练时间。(即,具有一个大小为 10 的隐藏层和另一个大小为 20 的隐藏层的网络具有 200 个连接,而具有三个大小为 10 的隐藏层的网络具有 1000 个连接)。一般来说,具有 2-3 个隐藏层的多层感知器对于大多数应用来说已经足够了。

默认情况下,多层感知器的 DRESS Kit 实现有两个隐藏层,该算法使用简单的启发式算法来确定每层神经元的适当数量。我们可以通过指定layout超参数来改变模型的结构。以下是我们尝试过的几种不同布局的结果。我们可以看到,基于 5 重交叉验证,网络的决定系数 (R2)没有显著变化,尽管从[5,3](意味着 5 个神经元的隐藏层后接 3 个神经元的隐藏层)到[20,10](20 个神经元的隐藏层后接 10 个神经元的隐藏层)增加了大量神经元。与此同时,训练时间几乎翻了两番。有趣的是,我们还看到,增加额外的层实际上会降低性能,并成倍增加训练时间。

[5] R2 0.94 
[7] R2 0.95 
[10] R2 0.96 
[15] R2 0.96 
[3, 3] R2 0.93 
[5, 3] R2 0.94 
[7, 5] R2 0.94 
[10, 5] R2 0.95 
[10, 10] R2 0.96 
[20, 10] R2 0.96 
[7, 5, 3] R2 0.95 
[10, 7, 5] R2 0.94 
[7, 5, 5, 3] R2 0.93

激活功能

设计神经网络时要考虑的下一个超参数是使用的激活函数。激活函数的主要目的是给网络引入非线性。有各种各样的激活功能,每种功能都有其独特的操作特性。好消息是,泄漏整流线性单元(Leaky ReLU)已被证明在大多数情况下比其他激活功能提供更好的性能。除非有非常具体的理由考虑另一个激活函数,否则在多层感知器的所有隐藏层中使用 Leaky ReLU 通常是安全的。

在训练过程中,有多种方法可以将训练数据集应用于网络。在传统的梯度下降算法中,整个数据集一次性应用于网络,平均损失反向传播以更新所有神经元的权重和偏差。这种方法需要大量的内存和计算能力。另一种被称为随机梯度下降的方法是一次对一个样本进行前向和后向传播。还有批量梯度下降,其中样品以小批量应用。无论如何应用训练数据集,仅通过网络应用一次是不够的。为了优化所有神经元的权重和偏差,需要许多周期或时期。显然,如果纪元设置得太高,训练过程将会非常慢,并且还会增加过度拟合的风险。

25 R2 0.92 
50 R2 0.93 
100 R2 0.94 
250 R2 0.95 
500 R2 0.96

稀释

有许多用于减少人工神经网络中过拟合的正则化技术,其中之一是稀释。稀释的概念有点类似于集合决策树模型中子空间的概念。它包括在训练过程中随机关闭一小组神经元,这样这些神经元的权重就不会对输出做出贡献。最终结果是,在每个周期中,每个神经元仅在整个训练数据集的一部分上被训练,并且那些在特定周期中没有被关闭的神经元被迫学习额外的信息。稀释的一个意想不到的好处是,通过关闭某些神经元,训练时间也略有减少,因为不需要对这些神经元进行反向传播。

0.10 R2 0.94 
0.25 R2 0.95 
0.50 R2 0.96 
0.75 R2 0.95 
0.90 R2 0.94

学习率

大多数神经网络实现支持学习率超参数,有时称为alpha。这个想法类似于集合决策树模型。它限制了每次反向传播过程中权重和偏差的变化量。这最小化了异常值的影响,并防止那些权重和偏差的值过度波动(并导致一些神经元在 ReLU 激活的情况下被关闭)。高学习率可能导致梯度下降算法在最佳点附近振荡,而不是收敛到最佳点,而低学习率可能需要高历元计数的补偿(因此需要更长的训练时间)。

0.0005 R2 0.95 
0.001 R2 0.95 
0.005 R2 0.95 
0.01 R2 0.94 
0.05 R2 0.88

动力

如果学习速率很小,则标准随机梯度下降算法收敛到最优点会很慢。理想情况下,该算法应该在开始时以较高的学习速率开始,并在接近最佳点时逐渐降低速率。许多基于动量的优化算法使用这种技术来加速训练过程。DRESS Kit 实现使用的 Adam 优化器支持与动量相关的超参数beta1beta2。这些超参数的默认值适用于大多数用例。

其他类型的人工神经网络

正如我们前面提到的,多层感知器只是许多人工神经网络类型中的一种。大多数多层感知器只需要几个隐藏层就能很好地工作。虽然没有正式的定义,但包含许多(例如几十个)隐藏层的多层感知器有时被称为深度神经网络。

除了建立分类和回归模型,人工神经网络还可以执行其他任务。Autoencoder 是一种人工神经网络,它执行无监督的学习任务,如降维和特征提取。卷积神经网络通常用于图像处理,因为它对特征之间的空间关系敏感。生成式对抗网络可用于生成具有与训练数据集相同的统计数据的新样本。

包裹

让我们复习一下第六部分所学的内容。我们讨论了人工神经网络的基本解剖,并解释了相互连接的人工神经元网络如何能够通过向前和向后传播来执行学习。我们演示了使用DRESS.multilayerPerceptronDRESS.async异步构建多层感知器的代码。我们还演示了使用在线训练方法构建和训练多层感知器的代码。我们探讨了各种超参数,并讨论了全面优化人工神经网络的挑战。最后,我们谈到了除了分类和回归之外的人工神经网络的其他用例。

模型摘要

多层感知器

强项

  • 支持任意决策边界
  • 支持高级抽象
  • 可以同时模拟多种结果
  • 不易过度拟合

限制

  • 仅适用于数值预测值
  • 黑箱操作
  • 训练缓慢
  • 难以优化

生产中的机器学习:为什么这么难,这么多失败?

原文:https://towardsdatascience.com/machine-learning-in-production-why-is-it-so-difficult-28ce74bfc732?source=collection_archive---------7-----------------------

行业笔记

您是否努力部署和维护您的模型?大多数公司都这样做,原因如下

Jupyter 笔记本不是生产解决方案(来源

根据的一篇集体论文分析了 300 多个组织中机器学习的发展,这些项目是公司面临的一些最大挑战。其他研究也显示,数据科学家经常抱怨他们的模型只是有时或者从来没有投入生产。

困难造成一波失望和遗忘项目的原因是什么?让我们考虑一下发生了什么变化。在传统的 IT 项目中,代码版本决定软件版本。在机器学习项目中,模型的版本是由代码的版本和数据的版本定义的。在等式中引入一些表格是否有可能对项目的复杂性以及成功产生如此巨大的影响?

对代码变更的反应导致了 DevOps 专业化和数百种竞争服务的发展,或多或少地促进了持续集成和持续交付。另一方面,机器学习项目是关于对代码和数据的变化做出反应,这至少会增加难度,正如我将在本文中向您证明的那样。

因为反馈回路较长

处理数据带来了全新的挑战。而软件通常可以在本地开发,并有一个即时反馈环,反馈一行新代码如何影响最终结果。您编写一个测试,检查只有绿灯亮着,然后继续前进。在机器学习中,反馈循环从同一个地方开始,但可能会在你完成模型训练的几个小时后结束。

即使您正在处理一个不大的数据集,并且您的模型不需要大量的图形卡,您也可能注定要等待几个小时来调优超参数。更重要的是,培训必须循环进行(本文后面会详细介绍),因此有一个额外的过程要转移到远程环境中。

在本地机器上工作的另一个限制是数据集的大小。要用表格数据填充哪怕是几年前的笔记本电脑的硬盘驱动器(大多数这样的项目都有机器学习),数据集必须有数十亿行,数百列。然而,我们有项目使用音频,图像和视频。虽然可以在数据集的一部分上试验和开发模型,这是常见的做法,但最终的评估是在整个数据集上进行的。

此外,在 ML 社区中有越来越多的声音不要在本地机器上进行实验,即使这是可能的,因为最终训练过程无论如何都必须在云中进行。越早到达越好。

版本代码、数据和型号

没有人能够想象一个没有版本控制系统的商业项目。多亏了它,我们可以方便地协作并回到过去。因为是代码的版本创建了软件的版本,有了版本控制系统,我们可以在任何时候构建应用程序的任何变体。机器学习就不是这样了。

首先,工作的结果不是代码,而是模型。而这一个又是由创建和训练模型的代码版本及其使用的数据产生的。因此,如果您想在使用机器学习开发项目时拥有相同的时间机器,您需要对代码、数据以及理想情况下的模型进行版本化。

一个版本的代码和数据创建一个模型版本()

嘿,等一下。你读了一段时间,你喜欢这篇文章吗?不要犹豫,鼓掌跟随。只需要 2 秒钟就能帮上忙。完成了吗?谢谢!

为什么我应该版本化模型,而不仅仅是数据?

您已经创建了一个新模型,并将其交付到生产中。一切都很好,但只是暂时的。也许模型在新数据上表现不佳,或者它太复杂,使得它更难处理更多的流量。您需要撤销更改。如果不对模型进行版本化,这会有什么影响?您需要在以前版本的代码和数据上训练新模型吗?这需要多长时间:5 分钟还是 2 天?哪怕不到一刻钟,训练模型的时候出现问题怎么办?

模型版本控制是一份保险单,您以云存储服务账单的形式每月支付一次分期付款。成本取决于您想要存储的版本数量和模型的大小。我们来估算一下它的成本。假设你正在做一个成熟的项目,这个项目有多达 1000 个深度机器学习模型,每个模型重 500 MB。每月供款约 23 美元。

测试数据至少和模型一样好

有时浮出水面并发现显而易见的东西是值得的,而不是一直沉溺于细节。你可能会同意阅读的速度就是看的速度。你读书的速度不会比你转动眼球的速度快。在 ML 的上下文中,很明显,模型的好坏取决于用来训练它的数据。虽然这是老生常谈,但不止一次听到这种(看似)陈词滥调时,我注意到和我交谈的人眼中闪烁着光芒。这有什么寓意?至少和模型一样测试数据。

我们输入模型的数据已经有了很大的进步。它可能已经访问了生态系统中的许多地方,在这段旅程中,它被照顾得有时更好,有时更差。另一方面,我们从这些疲惫的流浪者身上得出结论。而且,我们也不知道未来会有什么数据来找我们。我们能够并且应该自动化测试它。重要的是,数据测试应该在训练和实时预测中保持一致。它应该显示错误和失败,可能会发生在原来的生产者在未来。

问题是,虽然该模型可以从错误的数据中进行预测,但问题是这种行为何时会被发现。对模型来说,房子是有 3 间卧室还是负 8 间卧室并不重要。然而,并不是所有的测试都如此明显。例如,如果预期的数据是英文文本,测试将确保最常见的单词是“the”、“a”。如果其他词出现的频率更高,可能意味着我们处理的不是预期的语言。

测试车型

虽然大多数种类的模型是确定性的(相同的输入总是产生相同的输出),但它们也更难测试,因为它们的本质是动态发现不断变化的数据的重要特征。模型需要定期刷新,因为数据总是越来越多,数据的性质也在不断变化。这在实践中意味着什么?未来的房地产估价模型会对同样的房子给出不同的价格。

测量模型的质量时,会检查数据的拟合度。如果太差,我们就只有一个差的模型。然后,它无法从给它学习的数据中得出好的结论,更不用说它从未见过的未来数据了——这被称为欠拟合。相反的情况,就是契合度太强的时候,也不好。该模型在接受训练的数据上表现不错,但它无法对以前没有见过的数据做出良好的推断,这被称为过度拟合。从整个数据集的角度来看,太弱和太强的拟合是融合,并且在训练阶段进行测量。对于模型评估来说,这两个值是最重要的。问题在于针对具体案例测试和检测扰乱行为。解决方案是监控。

实时反应

生产模因中的意外问题(图片由作者提供)

定义模型中令人烦恼的行为或不稳定性,并编写测试在部署到产品之前检测它们是一个标准包。但检测生产中的异常,尤其是当模型实时响应时,则是另一回事,因为模型会遇到从未见过的数据,必须立即做出响应。同样,问题可能出在数据本身,它是从系统的另一部分流入的,与训练数据相反,它是无人管理的,或者出在模型的本质上,它只是没有为新数据做好准备。此外,异常偏离的单个预测仍然可能是正确的。那么,我们如何监控模型以利用其潜力,同时仍然对其退化行为做出响应呢?

在传统的应用程序中,我们通过测量每秒的请求数来监控硬件(RAM、CPU)的使用情况和应用程序本身。基于这些指标,我们可以实时做出反应,例如通过扩展应用程序或通过阻止给定 IP 地址来检测由系统错误和良好用户引起的可疑行为。

监控模型还包括观察它随时间的行为。将该行为或其返回的预测与基线值进行比较。例如,对于预测房地产价格的模型,训练集中的平均房价为 40 万英镑,而对于昨天返回的最后 100 个预测,平均值为 50 万英镑,这将敲响警钟。换句话说,模型监控是将输入数据和预测的统计属性与监督学习期间的统计属性进行比较。

即使预测是正确的(即,平均房价在很长一段时间内保持在正确的水平),影响特定预测的因素也很重要。回到房地产的话题,假设我们的模型预测房价 40 万。然而,事实证明,这个决定更多地受到车库面积的影响,而不是卧室的数量。训练数据中没有 120 平方英尺的房子。制成车库。毕竟生产中不可能出现那种情况!

解释和说明模型决策的领域本身是一个专业领域,但主要与在模型调整和评估期间证明模型行为有关,而不是作为一个监控实时生产系统的工具。

持续交付和持续培训

虽然在真空中工作的代码非常令人满意,但现实是只有交付到生产中的软件才能满足预算。

持续集成和持续交付是一组旨在自动化部署和日常代码工作的实践,以便每一项更改都能够顺利到达远程环境。在教科书应用程序中,构建和部署新版本的唯一原因是代码的变化。这一个可以通过引入新的功能或者修复一个 bug 来触发。我们更改代码,站在生产大门前,展示从 test runner 收集的绿色贴纸,如果没有其他颜色纠缠,应用程序就开始生活在现实世界中。如果它支持的数据库增长两倍,您不必部署相同版本的代码。当在线商店中出现一个新的瓷器收藏时,没有理由编写负责向我们的电子商务提供杯子的代码。

和这次不同。模特老了,过一段时间就没用了。这一次,为了改变,是通过数据。新模式出现、趋势改变、产品出现的数据。推荐电影的模型不会推荐它在训练阶段没有看过的电影(不是在所有推荐系统的实现中),AI 支持的导航不会为高速公路的新路段建议路线。这个问题的解决方案是循环的、定期的模型训练。正如您所看到的,不仅仅是代码变化导致新模型被训练。这意味着您需要创建和维护一个额外的流程。

摘要

如果你想做机器学习,这些真的有必要吗?不,这是为了增加你到达终点的机会和减少你的维修费用。MLOps 的一个新的专业化旨在解决上述问题,以便统计和神经网络专家能够专注于他们的工作。

虽然不是每个 ML 项目都需要解释实时预测,虽然几乎每个项目都比传统应用程序更复杂,但大多数项目都应该对数据进行版本化,并实施持续的培训过程。

在开始项目之前认识到这一点是个好主意。Jupyter 笔记本不是生产解决方案。通过在开始之前回答重要的问题,我们可以避免埋没几个月的工作,或者至少防止错误,为我们节省几天或几周的时间。

行动号召

你的观点是什么?你的 ML 项目进展如何?是在生产吗?请在评论区告诉我。

不要犹豫,鼓掌并跟随。这也是告诉我你以同样的方式看待事物的一种方式。

波兰文原版发布于https://radekbialowas . pl

公共卫生中的机器学习:一个病人的旅程

原文:https://towardsdatascience.com/machine-learning-in-public-health-a-patients-journey-3bfaab814fde?source=collection_archive---------22-----------------------

变更数据

利用技术和数据科学的进步,显著改善中低收入国家高危人群的公共卫生成果

机器学习是当今健康技术领域最热门的话题之一,几乎在任何领域都是如此。在本帖中,我们将关注 21 世纪数据科学的一个非常规的应用。我们问自己的问题是,“我们如何利用技术和数据科学的进步来显著改善全球中低收入国家(LMICs)高危人群的公共卫生结果?”。

这里是我们在回文数据 (PD)使用的一些方法,来解决撒哈拉以南非洲和其他地区的公共卫生问题。我们将使用 PD 的主要关注领域之一的 HIV 治疗来说明这种方法。

预测与解释模型

在我们作为数据科学实施者的 R&D 工作中,我们认为我们的项目走两条主要路线之一;预测或解释模型。两者都从专门的数据发现阶段开始,该阶段通常会告知关注哪条路线。同样重要的是要注意,无论哪条主要路线是集体商定的,两者都是被追求的——并且相互促进。

这可能是介绍我们虚构的患者案例研究对象 Thabo 的好时机。塔博是一名 22 岁的男性,刚刚完成了他的本科学位,目前失业,正在寻找一个初级职位,即医学研究助理,然后继续攻读研究生课程。自出生以来,塔博也是 HIV 阳性,他的一生都受到病毒的抑制。

传统的公共卫生理论告诉我们,塔博是一名年轻的失业男子,因此治疗中断的风险明显更高(IIT)——即错过登记预约并停止抗逆转录病毒(ART)药物一段时间,甚至可能很长时间。这对医疗保健方案和艾滋病毒携带者(PLHIV)来说是一个相当大的问题,因为那些脱离护理的人可能会产生耐药性,可能需要对他们的治疗方案进行代价高昂的改变。

塔博前来检查和采集药物的诊所由一名 PD 合作伙伴运营,他们目前正在对 PD 在合作伙伴支持下开发的工具进行用户测试,以优化患者保留率。他同意,在医护人员完成标准访视方案后,他们会向塔博解释预测工具,并在接下来的三分钟内输入必要的信息。

该诊所的预测工具要么是平板电脑上的应用程序(如下图 1 所示),要么是纸质记分卡(如下图 2 所示),这两种工具都是基于机器学习的工具,输出的分数接近塔博下次就诊迟到超过 28 天(有 IIT)的风险。

图 1:数字应用程序(预测工具)。该评分过程由十个问题组成,前六个来自患者档案,后四个是医务人员向患者提出的问题。“评分”近似于患者下次就诊迟到 28 天以上的风险(评分较低-风险较高)。来源:回文数据(经许可)。

图 2:基于纸张的遵守记分卡(预测工具)。该记分卡由十个问题组成,前六个来自患者文件,后四个是医务人员向患者提出的问题。“总依从性评分”接近患者下次就诊迟到 28 天以上的风险(评分较低-风险较高)。来源:回文数据(经许可)。

预测工具根据塔博的信息输出一个分数,这将他归类为有 IIT 病的中间风险。这名医务人员认识塔博多年,知道中间风险评分是他生活中复杂事件的结果。作为额外的检查,医护人员参考塔博的文件查看他的原型分类,这将我们带到解释性建模。

解释建模使用包括预测算法在内的一系列 ML 技术来分析人口,其最终目标是优化我们对人口动态、分组和模式的理解,而非纯预测能力的最终目标。解释性建模的一个主要示例是患者概况,其目的是开发患者原型。患者原型是一种概括的构建,可捕获子人群的关键人口统计和行为特征。医护人员发现,最近将塔博归类为“及时的&忠诚青春期男孩或年轻男性”,这意味着塔博被归类为属于代表年轻男性患者的原型,他们属于最稳定的患者,患 IIT 病的可能性最低,这加强了医护人员对塔博稳定风险特征的理解。

在评估了预测工具和解释工具的输出后,医疗保健工作者做出明智的决定,让 Thabo 继续他的长期治疗计划,并选择填写工具上的简短反馈部分,表明他们不同意预测工具的输出,并概述原因。

这种反馈循环非常宝贵,PD 和合作伙伴会对其进行全面分析,作为持续监控和改进流程的一部分。例如,来自 Thabo 的检查访问的结果和反馈,以及来自这一轮用户测试的所有其他结果和反馈,可能有助于我们提高预测工具的公平性、准确性和可用性。

大规模实施此类工具的广泛影响是深远的:

  • 它将个性化医疗保健的元素引入公共卫生系统和服务不足的社区,特别是疾病负担高的农村社区。
  • 它利用了不相称的成本节约,这是由于能够根据 IIT 风险对患者进行细分,从而允许急需的资源重新分配。
  • 这通常会带来更好的患者体验,将更多的时间花在有更大需求的患者身上,同时减少低风险患者经历的摩擦。
  • 它允许医护人员在患者仍在接受治疗时主动提供干预,以减少 IIT 负担(目前大多数干预仅在不良事件已经发生时追溯应用-这开辟了一套全新的干预机会)。

上述每一个好处都创造了一个正反馈循环,减轻了公共卫生保健系统和工作人员的压力,并将关注点重新定位于患者个人。

数据科学和机器学习在公共卫生领域还有许多其他应用和机会,PD 渴望以改善患者结果的方式做出贡献,更多类似内容请关注我们的媒体、 LinkedInTwitter

免责声明:Thabo不涉及任何真实的人或实体,在本文中仅用于说明目的。

Python vs. Julia 中的机器学习——Julia 更快吗?

原文:https://towardsdatascience.com/machine-learning-in-python-vs-julia-is-julia-faster-dc4f7e9e74db?source=collection_archive---------9-----------------------

Python 和 Julia 的简单分类任务的计算速度的分析比较显示了显著的发现

Unsplash 上的尤利安·瓦加斯拍摄的照片

Julia 编程语言在麻省理工学院从一开始就被设计用于科学计算的高性能,但是领域专家在日常工作中仍然更喜欢较慢的语言,例如 Python。Julia 的官方网站提供了一组实验来比较 Julia 和其他编程语言中的计算速度。其中一个练习展示了使用 Julia、SciLua、Rust、Go、Fortran、Java、Javascript、Matlab、Mathematica、Anaconda Python、R 和 Octave 的当前版本计算斐波那契数列:

来源:朱莉娅 1.6.1。文档。

这个练习表明,只有 C 能够比 Julia 更快地计算斐波那契数列。这样的竞争优势应该会让 Julia 在机器学习方面拥有超强的能力,使迭代更快,并为工程师节省时间。

真的是这样吗?本文深入研究了 Julia 和 Python 的性能,并比较了两种语言中手写数字的 MNIST 模型的训练时间。

实验设计

为了比较 Julia 和 Python 的性能,我用这个设置运行了一个实验

  • 使用 MNIST 数据对手写数字任务(0-9)进行分类
  • 标准成熟的编程解决方案
  • 其他条件相同的方法,尽最大努力使两种解决方案具有可比性
  • 仅比较模型训练时间。

我在 JupyterLab 的一台笔记本电脑上运行了这两个代码,该笔记本电脑配有英特尔酷睿 i7–5500 u、2.40 GHz CPU 和 16 GB RAM。

数据

我使用 ML 教程中常用的手写数字的经典 MNIST 数据。该数据集具有 60,000 个预处理的训练集和 10,000 个示例的测试集。数字已经过大小标准化,并在固定大小的图像中居中。 TensorFlow 包含 MNIST 数据作为 TensorFlow 数据集的一部分,而 Julia 包含 MLDatasets 中相同的预处理数据。

朱丽亚实现

Flux 是 Julia 最喜欢的机器学习库之一。导入必要的 Flux 模块后,统计库,ml 数据集:

数据经过整形、编码、展平,最后加载到训练集中:

接下来,我创建一个具有两个密集层和标准激活函数的模型编译函数,然后对其进行实例化:

接下来,我定义一个损失函数、学习率、ADAM 优化器和包含从模型中获得的参数的 ps 对象:

然后用 10 个时期训练该模型。@time是衡量培训绩效的有用宏:

Python 实现

在 TensorFlow 中,代码非常基础,类似于 Julia 实现。在他们的网站上查看更多详情。我使用时间库来测量模型训练时间:

伊恩·施耐德在 Unsplash 上拍摄的照片

瞧,结果出来了!

由于 Julia 比 Python 晚了几十年才被开发出来用于对大量数据进行快速计算,所以人们会期望它能决定性地超越 Python。所以,结果在这里:

Python: 训练时间:33.1 秒

朱莉娅: 92.4 秒

我对内存分配或其他指标不感兴趣,但这些数字令人兴奋。为了更好地理解它们,让我们检查一下 TensorFlow 中的 API 层次结构。

TensorFlow 的核心不是用 Python 写的。它是用 C++编写的,使用 Python 作为包装器。虽然 C++是一个低级 API,但 Python 为构建模型和应用程序提供了一个方便的前端 API。

这个事实清楚地解释了这个结果。TensorFlow API 层次结构在本教程中有很好的解释。

结论

Julia 是一种伟大的语言,它的创造者理所当然地获得了 J. H. Wilkinson 奖,以表彰他们在数字软件领域的杰出贡献。它一直在扩大用户群体,并且是 2021 年堆栈溢出开发者调查中“喜爱与恐惧”类别中排名第五的编程语言。

它将在科学计算、时间序列和风险分析、宏观经济预测、气候建模等领域找到大量的用例。

  • 在宏观建模中,MATLAB 是一个流行的工具,Julia 将加速模型估计
  • 在天气建模中,Julia 可能会在处理大量数据时做同样的事情。

另一方面,本文表明 TensorFlow 仍然可以使模型迭代更快,因为它依赖于 C++后端。在许多情况下,它仍然是训练 ML 模型的优选选择。

PS:你可以订阅我的 邮件列表 每次我写新文章都会收到通知。如果你还不是中等会员,你可以在这里加入https://medium.com/@petrkorab/membership

SQL 中的机器学习——它确实有效!

原文:https://towardsdatascience.com/machine-learning-in-sql-it-actually-works-56e8d91fc273?source=collection_archive---------5-----------------------

有了 dask-sql 的最新版本,就有可能在 sql 中使用巨大的 Python ML 生态系统

照片由克里斯多佛·伯恩斯Unsplash 拍摄

有时很难相信在曼梯·里之前有一个世界存在。如此多的现代数据分析建立在 ML 技术之上,并且在可预见的将来还会继续这样。然而,并不是每个人都能从这些巨大的进步中受益,因为使用 ML 技术主要涉及使用 Python、开发代码和理解许多新技术。特别是当大数据和分布式系统进入游戏时,事情变得一团糟。

这是 SQL 查询引擎试图解决的问题。它们使得用简单而强大的 SQL 命令来使用复杂的分布式系统成为可能。dask-sql是一个新的 SQL 查询引擎(免责声明:我是作者),构建在纯 python 的 Dask 分布式库之上。这个新的库允许您将 Python 与 SQL 和分布式可伸缩计算结合起来!(在我的其他帖子中阅读更多信息)。

dask-sql的最新版本 0.3.0 对机器学习有实验支持,所以今天我们就来看看我们能用它做什么。当然,我们将为此使用众所周知的虹膜数据集——数据科学的 hello world。尽管这个特定的数据样本非常小,但是本文中展示的所有内容都可以通过在集群中添加更多的计算节点轻松扩展到大量数据。

边注:带dask-sqlT13 的 ML 是还在实验中:-)可以随意试用,但要谨慎使用。

先决条件和准备工作

在这篇文章中,我假设你(或你的数据工程师)已经设置并运行了dask-sql。参考文档这篇博文了解更多信息。我还假设你通过 SQL server 接口连接到dask-sql——例如通过一个 BI 工具,像 Apache Hue ,它甚至在最新版本中带有对dask-sql本地支持

如果您使用 Python 接口来dask-sql,您仍然可以跟随。只需用以下单元格初始化您的 Jupyter 笔记本

**from** IPython.core.magic **import** register_line_cell_magic
**from** dask_sql **import** Context# Create a context to store the tables and models
c = Context()# Small helper function to make our life easier
@register_line_cell_magic
**def** sql(line, cell=**None**):
    ifcell **is** **None**:
        cell = line
        line = **None**

    if **not** line:
        line = {}
    **return** c.sql(cell, return_futures=**False**, **line)

在下面的代码示例中,在每个 SQL 命令前面加上%%sql,例如

%%sql
**SELECT** 1 + 1

加载和准备数据

这些事情解决之后,让我们从导入数据开始。由于dask-sql利用了大型 Python 和 Dask 生态系统,您可以从许多不同的位置读入许多不同格式的数据样本。在本例中,我们将以相当标准的 CSV 格式从互联网获取数据:

**CREATE OR REPLACE TABLE** iris **WITH** (
    location = 'https://datahub.io/machine-learning/iris/r/iris.csv',
    persist = True
)

数据集以名为“iris”的表格形式加载和存储。persist = True使dask-sql在内存中缓存数据。

现在,检查数据加载是否正确

**DESCRIBE** iris

如您所见,数据类型是自动分配的。我们可以用这个标准的 SQL 命令显示前十行数据:

**SELECT** * **FROM** iris **LIMIT** 10

Iris 数据集的简短介绍:如上面的输出所示,数据集描述了鸢尾花及其物种的测量结果。它是机器学习中的标准数据集之一,可以用作许多类型的 ML 方法的示例。在这个例子中,我们将应用无监督聚类算法。

在我们开始培训之前,让我们首先做每一个 ML 管道中的另一个重要步骤:特征提取。因为我不是生物学家,所以我在这里只介绍一个非常简单和天真的新特性作为例子:用萼片长度乘以萼片宽度。还可以使用 SQL 语句和函数生成更复杂的功能。如果这还不够,dask-sql允许注册用 Python 编写的用户自定义函数 (UDF)。

**SELECT** 
    *, 
    sepallength * petallength **AS** new_feature 
**FROM** iris
**LIMIT** 10

为了让我们的生活变得简单一点,让我们为这个增强的表引入一个别名

**CREATE OR REPLACE TABLE** transformed_data **AS** (
    **SELECT** 
        *, 
        sepallength * petallength **AS** new_feature
    **FROM** iris
)

我们现在准备应用机器学习!

训练机器学习模型

存在大量可能的机器学习模型——从线性回归这样的简单模型到健壮的增强决策树,再到变形金刚这样的尖端研究模型。它们中的许多是在著名的 scikit-learn Python 包中实现的,因此(和许多其他库一样)可以在dask-sql中使用。

在这个例子中,我们应用了 k-Means 聚类算法。简而言之,它将数据集分组为具有相似特征的行簇。如果一切顺利,我们希望它将同一物种的花朵聚集在一起——而不需要我们告诉算法。我们来看看算法表现如何(剧透:不太好)。如果你想了解更多关于兼容dask-sql的型号及其设置,我鼓励你看一下文档

那么,让我们将我们的聚类算法应用于数据!

**CREATE OR REPLACE MODEL** clustering **WITH** (
    model_class = 'sklearn.cluster.KMeans',
    wrap_predict = True,
    n_clusters = 3
) **AS** (
    **SELECT** sepallength, sepalwidth, petallength, petalwidth, new_feature
    **FROM** transformed_data
)

正如你所看到的,我们为训练使用了一个新的 SQL 结构**CREATE MODEL**,它得到一些参数来指定训练哪个模型。在我们的例子中,我们从 scikit-learn 中选择 k-Means 算法,并将我们期望的组或簇的数量设置为三(因为我们有三个物种)。scikit-learn 包中的算法在中等大小的数据上工作得非常好,如果您需要超越这一点,可以查看一下 dask-ml

训练应该很快就能完成(因为总数据集相当小),所以我们可以继续检查预测。

检查性能

**SELECT** * **FROM** **PREDICT** (
    **MODEL** clustering,
    **SELECT** * **FROM** transformed_data
    **LIMIT** 10
)

该 SQL 语句将对给定数据应用一个训练模型,并添加一个新列“target ”,其中包含模型的预测目标。从前十行来看,它看起来相当不错(所有的“setosa”都有相同的预测目标)。所以让我们再次引入一个别名来做更多的计算

**CREATE OR REPLACE TABLE** iris_results **AS** (
    **SELECT** class **AS** label, target **AS** predicted **FROM PREDICT** (
        **MODEL** clustering,
        **SELECT** * **FROM** transformed_data
    )
)

长话短说,我们只快速浏览一下结果,并检查物种的分布和预测的集群。

**SELECT** 
    label, predicted, **COUNT**(*) AS numbers
**FROM** iris_results
**GROUP** **BY** label, predicted

一点也不完美,不过好在这不是 ML 上的帖子,所以我就跳过优化这一步:-)。您的 BI 工具可能能够自动绘制这些数字,作为 python 用户,您可以使用

df = c.sql("""
**SELECT** 
    label, predicted, **COUNT**(*) **AS** numbers
**FROM** iris_results
**GROUP** **BY** label, predicted
""", return_futures=**False**)df = df.set_index(["label", "predicted"])
df.numbers.unstack(0).plot.bar(ax=plt.gca())

摘要

谢谢你一直关注这个帖子!我们已经介绍了相当多的材料,所以这里快速回顾一下:

  • SQL 查询引擎很酷,因为您可以使用它们来查询复杂的数据,使用复杂的分布式系统,使用简单的 SQL 语法(和许多魔法)。
  • dask-sql就是其中之一,它与 Python 生态系统的交互特别简单(因为它是建立在 Dask 之上的,Dask 是一个用于扩展 Python 应用程序的库)。
  • 一个好处是可以轻松集成各种各样的 Python ML 库,例如 scikit-learn 包中的 k-Means 算法,如本文中所示。另一件好事是,只要使用 SQL,一切都可以正常工作!

如果你想了解更多,去看看文档,开始用 SQL 整理你的数据。

区块链和加密货币世界中的机器学习

原文:https://towardsdatascience.com/machine-learning-in-the-world-of-blockchain-and-cryptocurrency-68651ebaecd7?source=collection_archive---------5-----------------------

探索机器学习及其在加密货币开采和交易领域的适用性。

在我主持的这个现场培训环节,用 TensorFlow 和 Keras 学习 AI 和深度学习的基础知识。

照片由思想目录上的 Unsplash

介绍

加密货币和区块链的世界越来越令人兴奋,这是理所当然的,因为以太坊和比特币的价格到目前为止都在 2021 年创下历史新高。更不用说区块链技术应用的增加,特别是随着不可替代令牌(NFT)的流行。

像任何技术一样,区块链和加密货币都有与安全性、利用率和效率相关的问题。除了所有的兴奋和主流关注,还有一些合理的努力集中在解决重大的区块链相关问题上。

本文将介绍一些上述问题,以及使用机器学习技术解决区块链/密码相关问题的研究成果。本文中的研究是在最近几年发布的。

1.交易(强化学习)

Pierre Borthiry 在 Unsplash 上拍摄的照片

交易比特币和以太币等加密货币已经成为散户投资者和大型金融机构的一项活动。截至本文撰写之时,CoinMarketCap 上跟踪了 308 家加密货币交易所。

如今股市中使用的传统交易机器人都带有嵌入式机器学习算法。因此,毫不奇怪,ML 技术也有助于构建加密货币市场交易系统。

在谷歌搜索引擎上键入“机器学习加密交易机器人”会产生超过 1200 万个搜索结果,但让我们将注意力转移到学术研究上。

Thomas E. Koker 和 Dimitrios Koutmos 撰写了一篇研究论文,介绍了使用直接强化学习来创建基于加密货币的主动交易模型。

强化学习(RL)是机器学习的一个子域,在游戏和模拟程序中很常见。RL 通过培训项目(代理)在互动环境中开发优化策略(政策)来获得回报。

这项特殊研究中提出的方法利用了直接强化学习(DRL)。在传统 RL 中,没有对代理的即时性能反馈,但是在 DRL 中,来自先前窗口的性能被用作对代理的反馈。使用 DRL,研究人员能够摆脱创建价格预测模型,并创建了一个基于特定时间间隔(每天)进行调整的系统。

外卖食品

强化学习是开发有利可图和适应性强的加密货币交易策略的可行方法。

2.优化挖掘策略(强化学习)

照片由巴特·范·迪克Unsplash 上拍摄

在我开始研究之前,这里有一个关于比特币挖矿如何工作的快速速成班。挖掘加密货币涉及利用计算资源来猜测用于求解区块链函数的一组值。允许求解该函数的挖掘器用有效的未决事务更新区块链。

然后区块链网络被更新以包含新的交易。挖掘的目的是用未决事务更新区块链,并为矿工的努力提供奖励。

矿工的这种努力将获得大宗奖励(即比特币)和相应交易产生的交易费。你的计算机越强大,你就能做出越多的猜测来求解这个函数。请注意,这是对加密挖掘的过于简单的描述,但你已经得到了要点。

本节探讨了研究工作,旨在展示 ML 技术在优化采矿工作和防止劫持采矿资源方面的适用性。

王陶陶、宋长烈和张胜利撰写了一篇研究论文,发表于 2021 年 1 月,该论文介绍了强化学习(RL)在优化比特币等加密货币的区块链挖掘策略中的应用。

他们的研究工作证明,如果没有区块链的初始模型和相应的参数(矿工的计算资源、交易费用等)。)有可能利用 RL 技术来动态推断与其他策略(传统诚实挖掘和自私挖掘)相比更具性能的挖掘策略。

传统的强化学习算法设计了一些方法,通过这些方法,代理可以最大化地获得环境中的奖励。但是区块链网络是一个动态的环境,在其中很难创建一个有代表性的模型。该论文的作者设计了一种多维 RL 算法,使用 Q 学习(无模型算法)来优化加密货币挖掘。

作者证明,通过机器学习技术,可以解决性能挖掘策略的开发。众所周知,比特币和加密货币挖掘是一个蓬勃发展的行业。据报道,Argo Blockchain、Riot Blockchain 和 Hive Blockchain 等几家矿业公司已经开采了价值数百万美元的比特币。这些公司的技术团队中也可能有 ML 工程师。

外卖食品

研究人员创建了强化学习系统,为加密货币挖掘策略提供优化。

3.应对密码劫持(深度学习)

照片由 imgixUnsplash 上拍摄

加密货币挖掘中机器学习的另一个值得注意的应用与安全有关。由学术机构和国家政府支持的研究实验室配备了大量的计算资源和基础设施。这使得他们成为' 密码黑客 '的首要目标。

密码黑客劫持计算资源来挖掘加密货币。这种攻击已经变得司空见惯,并成为头条新闻。

来自美国的研究人员共同努力,设计了一种检测恶意程序存在的方法,这些程序试图劫持计算资源。

SiCaGCN 是研究人员给这个系统起的名字。SiCaGCN 基于对程序的控制流图表示进行的距离测量来确定一对程序或代码之间的相似性。

SiCaGCN 系统包括在深度学习和 ML 领域中发现的神经网络架构和技术的组件。

  • 控制流程图 : 代码/程序内指令执行流程的表示,其中每个节点代表一个基本块。有向边对应于代码执行中的跳转或流程变化。
  • 图卷积神经网络 : 设计用于对图进行卷积运算的神经网络架构。
  • 注意机制 : 为突出或增强输入/输出或输入之间的重要依赖关系而设计的技术。
  • 神经张量网络、 胶囊网络、 、距离测量( 图形编辑距离最大公共子图(MCS) )

本文的目的不是对 SiCaGCN 进行详细的分析,但是下面是对该系统的高级操作的一步一步的快速概述:

  1. 将代码/程序转换成基本块表示的控制流图(CFG)。
  2. 通过图形卷积神经网络将基本块的 CFG 作为输入传递到 SiCaGCN 模型,以创建基本块的 CFG 的嵌入。
  3. 注意机制(NLP)和胶囊网络被用来从输入图中提取重要的和相关的特征,从而创建更好的嵌入。
  4. 使用有效距离度量(图形编辑距离,GED)和最大公共子图(MCS))来确定图形嵌入之间的相似性分数。
  5. 训练数据的实例由一对基本块的 CFG 和它们的基本事实相似性得分组成。在测试期间,模型的输入是来自代码对的基本块对 CFG,输出是相似性得分。

SiCaGCN 架构。图片来自原始研究论文

这项研究令人兴奋的方面是 SiCaGCN 系统的实际应用。研究人员测试了该系统在一组科学源代码中检测比特币挖掘代码的能力。当与另一个图相似性计算系统( SimGNN )比较时,SiCaGCN 表现良好。不难设想,SiCaGCN 可以被修改成一个更广泛的反病毒系统。

外卖食品

研究人员设计了一种独特而有效的检测恶意代码的方法,使用深度学习技术来描述和比较代码。该系统被命名为 SiCaGCN,在测试其检测外国比特币采矿代码的能力时,提供了有希望的结果。该系统防止外国程序滥用和未经授权使用计算资源。

结论

机器学习在区块链和加密货币的世界中占有一席之地。ML 技术的应用范围不仅仅局限于加密货币的价格预测或交易。

随着更多这些技术进入生产环境并实现商业化,区块链世界可能会在未来几年开始向机器学习从业者开放。

感谢阅读

在我主持的这个现场培训环节,用 TensorFlow 和 Keras 学习 AI 和深度学习的基础知识。

想要更多吗?

  1. 订阅 在我发布文章时得到通知
  2. 成为推荐媒介会员,支持我的写作
  3. 通过 LinkedIn 联系我
  4. 跟我学学 奥莱利

从熟悉的角度看机器学习直觉

原文:https://towardsdatascience.com/machine-learning-intuition-from-a-familiar-angle-beada5e69ded?source=collection_archive---------34-----------------------

通过石头剪子布游戏探索 ML 的动机和能力

注:本帖代码可在 这里 找到

机器学习与石头剪子布游戏(图片由作者提供)

在本文中,我们将使用两种不同的方法用 Python 构建一个简单的石头剪刀布游戏:基于规则的系统机器学习。通过这个对比,我希望表达机器学习是如何工作的,以及它的动机。要明确的是,这不是一个关于图像识别模式识别(玩家接下来会选择哪只手)的说明,而是一般的机器学习概念。随着自动化不断革新各行各业的未来工作,公司必须探索不同的方式来简化运营。如其维基所述,

机器学习涉及计算机发现它们如何在没有明确编程的情况下执行任务。它涉及计算机从提供的数据中学习,以便它们执行某些任务。对于分配给计算机的简单任务,可以编程算法告诉机器如何执行解决手头问题所需的所有步骤;就计算机而言,不需要学习。对于更高级的任务,人工创建所需的算法可能会很有挑战性。在实践中,帮助机器开发自己的算法可能会比让人类程序员指定每个需要的步骤更有效。

传统的编程是基于规则的

我们创建 RPS 游戏的第一个方法是手动编程每个可能的条件。这就是所谓的基于规则的系统。让我们先把游戏简化一点,这样玩家只有两个选择:石头或者

# Print Title
print("Let's Play Rock Paper Scissors!")# User selection
player_1 = input("Player 1 -  Choose from: (r)ock, (p)aper? ")
player_2 = input("Player 2 -  Choose from: (r)ock, (p)aper? ")# Run conditionals
if (player_1 == player_2): 
    result="A smashing tie!"

elif (player_1 == "r" and player_2 == "p"):
    result="Sorry. Player 1 lose."elif (player_1 == "p" and player_2 == "r"):
    result="Yay! Player 1 won."else:
    result="I don't understand! Next time, choose from 'r' or 'p'."

print(f"Player 1 chose {player_1}. Player 2 chose {player_2}.")
print(result)

根据这些简单的规则,创建游戏是很容易的。虽然我们不得不手动编程 4 个条件中的每一个(包括一个总括),但它是可管理的。

游戏结果

让游戏回到常规规则,有三种选择:石头剪刀。我们必须手动编程的条件数量快速增长

# Print Title
print("Let's Play Rock Paper Scissors!")# User selection
player_1 = input("Player 1 - Choose: (r)ock, (p)aper, (s)cissors? ")
player_2 = input("Player 2 - Choose: (r)ock, (p)aper, (s)cissors? ")# Run conditionals
if (player_1 == player_2): 
    result="A smashing tie!"

elif (player_1 == "r" and player_2 == "p"):
    result="Sorry. Player 1 lose."elif (player_1 == "p" and player_2 == "s"):
    result="Sorry. Player 1 lose."

elif (player_1 == "s" and player_2 == "r"):
    result="Sorry. Player 1 lose."

elif (player_1 == "p" and player_2 == "r"):
    result="Yay! Player 1 won."

elif (player_1 == "r" and player_2 == "s"):
    result="Yay! Player 1 won."

elif (player_1 == "s" and player_2 == "p"):
    result="Yay! Player 1 won."else:
    result="I don't understand! Next time, choose from 'r' or 'p'."

print(f"Player 1 chose {player_1}. Player 2 chose {player_2}.")
print(result)

当我们给游戏增加了更多的复杂性时,我们必须编程的条件数量从 4 翻倍到 8 。随着游戏复杂度的增加,IF 条件的数量会呈指数增长。

使用机器学习来推导规则

在接下来的方法中,我们将使用机器学习来学习游戏的内在规则。

"鉴于我们对历史结果的了解,我们能对未来事件说些什么呢?"

假设我们要从过去的 100 个 RPS 游戏中检索数据:

过去的游戏结果数据

机器学习需要大量多样的数据。幸运的是,我们的数据包含了特征和结果的所有可能选项。我们可以将这个数据集输入到一个算法中,比如决策树来表示这个游戏。

决策树可用于表示游戏——每次出现的次数(图片由作者提供)

在模型训练过程中,我们称玩家 1 的选择和玩家 2 的选择为特征,而结果为目标。也被称为“拟合模型”,这个过程使用数学和试错法的组合来找到最佳描述变量之间关系的方程。RPS 游戏是确定性的,这意味着结果没有随机性,它是非常二元的。我们的模型已经识别了游戏的所有规则——例如,它观察到的模式之一是,当参与人 1 的选择和参与人 2 的选择相同时,结果总是“平局”。在之前或之后的游戏中玩什么选择,在这个模型中是不考虑的。

# Import Dependencies
import pandas as pd
from sklearn.preprocessing import OneHotEncoder
from sklearn.tree import DecisionTreeClassifier# Read Data
df=pd.read_csv('result/result.csv', header=None)
X=df[['player_1', 'player_2']]# Transform Data
ohencoder=OneHotEncoder()
X_transformed=ohencoder.fit_transform(X)# Fit Model
y=df['result']
clf=tree.DecisionTreeClassifier()
clf.fit(X_transformed, y)

需要指出的是,虽然使用机器学习的能力非常令人鼓舞,但并不一定需要了解高等数学。有很多开源的机器学习库使得实现很直观=-

一旦开发出来,我们可以用这个模型来评估新游戏的结果。例如,如果玩家的选择是“石头”,玩家 2 的选择是“纸”,则模型判定,由于这种组合的过去 9 次出现中有 9 次都导致训练数据中的“玩家 1 输了”,因此这种结果很可能是相同的。

game={'player_1': 'r', 'player_2': 'p'}
game_transformed=ohencoder.transform([list(game.values())])
clf.predict(game_transformed)==========output==========
array(['Player 1 Lose'], dtype=object)

这就是机器学习如何识别训练数据中的模式/规则。在游戏复杂度增加的时候特别有效。

假设随着时间的推移,我们开始注意到玩家在做出选择之前先等着看另一个玩家选择什么。我们希望对这种延迟进行一些限制,以确保匿名性和 T2 公平性,但是我们不知道如何在基于规则的系统中实现这一点。我们需要专家意见的一些问题是:1)延迟的阈值应该是多少,2)如果玩家在长时间延迟后选择了一手输牌,他应该输还是平局?我们可以让一个新模型利用历史游戏记录进行自我学习,而不是手动编程条件:

特征工程新列(绿色)

这一次,作为“特征工程过程的一部分,我们创建了一个新字段来表示两个选择之间的时间差。将此输入决策树算法,数据支持 800 毫秒的延迟截止。换句话说,记录显示,如果在 800 毫秒的延迟后做出第二次选择,游戏通常会使胜利无效。这个“新”规则的实现是快速而轻松的,但是要求我们有足够数量的记录以及额外的字段(列)。

机器学习有效地解释复杂的规则——每次出现的次数(图片由作者提供)

这种方法允许算法自己开发最能代表游戏的适当规则集。为了使用这个机器学习模型进行推理,我们将传递玩家的选择和时间作为输入。延迟的截止值是严格基于所提供的训练数据来确定的。如果收集了新的数据并且模型被重新训练,这个截止值可以改变。对于我们简单的树模型,“规则”足够明显,我们可以解释和表达它们。内部工作并不总是容易描述的,特别是当问题变得不那么绝对的时候。作为一个例子,该模型表明,当有一个长的延迟,玩家 1 选择“石头”,有一个决定是否玩家 2 选择“剪刀”,而不是在所有三个选项中选择。为什么会这样,现在还不清楚,但经过一些思考后,这是有道理的,因为参与人 2 选择“纸”和“石头”在历史上都产生了相同的结果:“平局”。机器学习使用基于每个特征的概率方法来评估结果。这是手动编程规则的一种受欢迎的替代方法。

基于规则的系统与机器学习

机器学习和基于规则的系统都旨在高度准确地自动化决策。

基于规则与机器学习

当编写和实现规则很容易时,基于规则的系统通常更好。如果我们知道规则,并且不希望变量发生变化,我们可以基于简单的 If 语句实现规则。这种方法也被称为基于专家的规则,因为人类专家的知识是必需的(并被记录)。然而,随着时间的推移,基于规则的系统可能会变得“笨拙”,因为需要更多的规则来应对环境的变化。机器学习是一种替代方法,它解决了基于规则的方法的一些问题。

优点和缺点

摘要

在本文中,我们使用众所周知的石头、剪子、布游戏来探索机器学习的概念。随着过去几年数据的显著增加,机器学习有很多机会改变我们为未来创造技术的方式。

机器学习就像足球

原文:https://towardsdatascience.com/machine-learning-is-like-football-e3e3ace8ce7a?source=collection_archive---------50-----------------------

对复杂话题的有趣类比

本斯·巴拉-肖特纳在 Unsplash 拍摄的照片

当你成为一名专业数据科学家的计划开始实现时,你将经常不得不回答这个臭名昭著的问题:“那么,你是做什么的?”。如果你想成为机器学习专家,你将很难向没有技术背景的同事解释机器学习是什么。

卡内基梅隆大学著名计算机科学家 Tom Mitchell 教授将机器学习定义为:

“一种计算机程序,它从经验 E 中学习关于某类任务 T 和性能测量 P,如果它在 T 中的任务的性能,如 P 所测量的,随着经验 E 而提高。”【1】

老实说,他的定义不会让你在任何非正式的谈话中走得很远。此外,作为一名数据科学家,您经常需要向非技术受众解释技术术语。因此,每当我发现自己在解释我所做的事情时,我都会使用我的哲学老师曾经对他的学生使用过的同样的技巧:足球类比。如果你在北美,那么你可以称之为足球类比。即使你不喜欢足球,人们似乎也能以这样或那样的方式理解这项运动及其规则。

希望足球的类比能帮助你理解或向他人解释机器学习。

球员(数据)

这看起来很明显,但是没有球员,就没有足球比赛。无论你是在职业水平的温布利球场踢球,还是和朋友在街上踢球,都没有关系。没有球员,那些地方只是一个空荡荡的足球场,一条典型的街道。至于机器学习,数据就像玩家;没有数据,什么都做不了。但是,并不是每个数据集都是一样的,就像玩家一样。克里斯蒂亚诺·罗纳尔多和莱昂内尔·梅西都是伟大的球员,他们将超越人们对一场伟大足球比赛的期望。如果我去踢足球,情况就不一样了。所以,好的选手做出了伟大的表演。同样,与数据科学中的名言一致,“垃圾入,垃圾出”。无论你的编程技能有多好,或者你对数学了解多少,如果没有有用的数据集,你的机器学习项目很可能会让你的团队失望。

足球经理(数据准备)

足球经理对足球队的成功至关重要。尽管英格兰国家足球队有选择顶级球员的奢侈,但它自 1966 年以来还没有赢得过世界杯。负责决定谁去世界杯的人是经理。他还负责为球员提供指导,并影响他们的训练程序。这是一个耗时的过程,如果没有正确完成,球队将无法为下一届冠军做好准备。

一项研究报告称,数据科学家将大约 80%的时间花在数据准备和数据清理上【3】。数据专业人员必须将他们的数据集转换成机器学习模型可以学习的格式(例如标准化数据,处理空值等)。).对于数据科学家和足球专业人士来说,这些都不是最令人兴奋的方面。

足球战术(机器学习模型)

要想赢得冠军,球队必须根据每个对手改变战术。例如,如果美国国家足球队与四次获得世界冠军的德国队比赛,他们可能会建立一个强大的防守体系。如果美国队与冰岛足球队比赛,他们可能希望建立一个强大的进攻战略,采用不同的侵略性战术。所以,一支训练有素的球队,采用正确的战术,在 90 分钟后,很可能会进一些球并赢得比赛。

在我们的世界中,机器学习实践者必须决定应用哪种算法或模型,给定特定的数据集和期望的结果。例如,机器学习专业人员根据问题选择预测模型:分类模型是关于预测标签,而回归是关于预测数量。因此,理解可用的规范和技术对一个成功的项目至关重要。这里有一些机器学习模型供您稍后检查:K-最近邻,逻辑回归,朴素贝叶斯分类器和随机森林。

足球设备(硬件和软件)

不同的足球位置需要不同的设备和训练。例如,守门员是唯一可以用手触球的人。因此,他们需要(特殊的)手套和独特的体能训练,相比之下,其他球员必须来回跑 90 分钟,并试图用额头进球。此外,拥有优秀赞助商的团队可以聘请营养师、医疗专家甚至数据科学家来分析表现数据。最终,设备和独特的专业人员有助于球队在世界杯上取得成功。

同样,处理一个小数据集(1000 行 x 5 列)以创建一些图表可能会在使用 MS Excel 的标准笔记本电脑上运行,但从多个服务器提取数据并处理数百万行需要特定的编程语言 Python 和具有非凡计算能力的高性能设备。

拉斯·博·尼尔森在 Unsplash 上的照片

不同的联盟(领域专长)

我认为无论你去哪里,总有人在踢足球。它可能是孩子/成人、男人/女人、室内/业余、在线/室外或业余/专业。没关系;总有人在玩。此外,你会遇到技能水平的巨大差异。不同的技术水平和比赛类型不是足球的缺点;他们代表了这项运动的多样性和包容性。每一种技能水平或比赛类型都针对一种特定的需求或需要。一些人喜欢在户外的草地上玩,而另一些人喜欢和几个好朋友在网上玩。没关系,这些人专门从事一种特定类型的足球。

机器学习就像足球一样。不同的专业人员有不同的专业知识,并在各自的领域工作,例如,商业和企业领域(金融市场)以及学术和技术领域(在大学研究开发新的算法)。

结论

如果你正处于成为机器学习专业人士的过程中,你不可避免地要向不同背景的人解释你是做什么的。因此,有一个简单有效的类比将有助于您让他们更容易理解机器学习。这就是足球类比的由来。专注于普通观众对足球的了解,并与机器学习建立易于记忆的联系。现在,希望你对我们日常生活中的一个复杂话题有一个有趣的类比。

感谢阅读。这里有一些你可能会喜欢的文章:

</what-pokémons-can-teach-you-about-machine-learning-d72586c4b202>

参考文献:

[1]米切尔,T. (1997)。机器学习。麦格劳·希尔。第 2 页。

【2】世界杯获胜者https://en.wikipedia.org/wiki/FIFA_World_Cup

【3】数据清洗https://www . Forbes . com/sites/Gil press/2016/03/23/Data-preparation-most-time-consumption-least-happy-Data-science-task-survey-says/?sh=6bba28296f63

机器学习不是万能的:没有免费的午餐定理

原文:https://towardsdatascience.com/machine-learning-is-not-all-powerful-the-no-free-lunch-theorem-16bdcd84c36?source=collection_archive---------20-----------------------

有没有单一的机器学习算法可以学习一切?遗憾的是,没有。请继续阅读,找出原因。

附身摄影Unsplash 上拍照

围绕机器学习有很多合理的炒作。过去十年中,机器学习完成的一些事情(例如 AlphaGo)确实令人惊叹。然而,有些人夸大其词了——他们声称最终我们会找到一种可以学习宇宙中任何东西的机器学习算法。不幸的是,实际上有一个重要的定理表明情况不是这样的。这就是“没有免费的午餐”定理。该定理的名称与习语“天下没有免费的午餐”有关,该理论认为,如果你想要某样东西(在我们的例子中,在一个领域学得好),你必须放弃某样东西(在我们的例子中,在另一个领域学得不好)。理解免费午餐定理的细节将有助于你更好地理解机器学习的理论基础,并防止你被关于机器学习的荒诞说法所欺骗。让我们从几个例子开始。

例子

我们有一枚公平的硬币,我们抛两次。有四种可能的历史:HH,HT,TH,TT。我们的目标是给定第一次翻转,预测第二次翻转。因为硬币是公平的,所以四史的可能性是相等的。很明显,在这种情况下,没有“主算法”可以正确预测所有历史。例如,假设我的算法是,如果第一次翻转是 H,则预测 H,如果第一次翻转是 T,则预测 T。我将得到正确的 HH 和 TT 历史,而错误的 ht 和 t H 历史。我可以使用反向算法来正确预测 HT 和 TH,但这样我会把 HH 和 TT 弄错。关键是,无论你如何努力,都不可能有超过 50%的历史是正确的。这是满足“没有免费的午餐”定理的一种方式——这项任务如此困难,以至于没有有效的学习算法。

现在,你可能会问:那么,如果硬币不公平呢?如果硬币的重量偏向正面,那么在第二次投掷时总是预测 H 的算法不是表现得很好吗?这是真的。然而,同样的算法在一枚硬币上表现不佳,硬币重于尾部。这是第二种,也是更常见的满足“没有免费的午餐”定理的方式。通常,对于任何给定的任务,都存在一个运行良好的算法(不像我们的第一个公平硬币的例子,没有算法工作)。关键是这个算法在其他任务上效果不好。

这两个例子演示了两种不同的方法来证明没有免费的午餐算法。一种方法是找一个任务,这个任务太难了,所有算法都学不好。另一种方法是,对于任何给定的算法,找到该算法学习较差的任务。我们将采用第二种方法。下面的证明有一些实质性的符号,所以我们将首先解释设置。

证据

设 C 是一组唯一的数据点。假设 C 中有 2m 个这样的数据点,换句话说,C 的大小是 2m。这可能看起来很奇怪,我们用 2m 来表示大小,而不仅仅是变量 m,但这对以后的证明很重要。我们认为这是一个二元分类问题,所以所有这些数据点要么映射到 0,要么映射到 1。现在,我们要问的第一个问题是:C 语言中有多少种可能的函数?因为 c 有 2m 个数据点,并且每个数据点映射到 0 或 1 (2 个选择),所以总共有 T = 2^(2m)个可能的函数。在这个证明中,我们将用 I 来索引这些函数——例如,第一个可能的函数我们记为 f1,第二个函数是 F2,第 I 个可能的函数是 f1

接下来,用 A 表示一个任意的学习算法,A 的工作方式是,首先我们决定我们要学习什么函数 f_i。然后,A 将一系列数据点 S(训练样本)作为输入,这些数据点根据 f_i 具有正确的{0,1}标签,然后在处理该序列后输出它学习 A(S)的函数。训练样本的大小为 m。因为 c 中总共有 2m 个元素,并且一个样本有 m 个元素,所以总共有 K = (2m)^m)个可能的样本。我们用 j 来索引这些样本,例如,第 j 个可能的样本是 S_ j。

最后,我们需要讨论损失函数。假设我们已经决定用样本 S_ j 来学习函数 f_i,学习算法 A 完成后,它会输出 A(S_j),这是它学习到的函数。我们的损失函数的目标是表示 f_i 和 A(S_ j)之间的差异。在这个证明中,我们将使用 0–1 损失:我们将逐一检查 C 中的所有 2m 个元素,并找出 f_i 不同于 A(S_ j)的实例数。我们将这个数字除以 2m,得到最终的损失。简单来说:L(f_i,A(S_ j))是 C 中 2m 个元素的百分比,其中 f_i 和 A(S_ j)不同。

在我们继续证明之前,让我们再回顾一下设置。我们有一个大小为 2m 的域 C,它的元素映射到{0,1}。存在 T = 2^(2m)个可能的函数,索引为 f_i。我们表示可以尝试学习这些 f_i 的任意学习算法 a。学习过程的第一步是从 c 中抽取大小为 m 的样本,并决定要学习的函数。有 K = (2m)^m)个可能的样本,索引为 S_ j。然后在样本上训练 a,将得到的学习函数与真实函数进行比较,损失为 0–1。

证明的总体思路是这样的:对于任意的学习算法 A,我们将证明存在某个函数 f,其中 A 试图学习 f(在所有可能的样本上)的期望误差大于 1/4。换句话说,对于任何可能的学习算法,总有一些函数是学不好的。用数学术语来说,我们想表明:

为了理解这个等式,我们从内部开始。总和内的损失函数表示当我们尝试使用样本 S_j 训练 A 来学习函数 f_i 时的损失,对所有可能的样本求和,然后除以样本总数 K,得到 A 尝试在所有可能的样本上学习 f_i 的平均损失(换句话说,A 对 f_i 的预期误差)。给定学习算法 A,我们希望找到具有最高期望误差的函数,并证明它大于 1/4,因此是 I 上的 max。

下一步是做一些操作:

首先,我们利用 I 上的最大值小于 I 上的平均值的性质。然后,我们交换求和的顺序。最后,我们使用 j 上的平均值大于 j 上的最小值的性质。接下来,我们的目标是扩展和的内部——损失函数。

如前所述,损失函数是真实函数 f_i 和学习函数 A(S_ j)之间的 0–1 损失。奇怪字体的数字 1 是一个指示函数。简单来说,indicator 函数在 inside 求值为 true 时求值为 1,inside 为 false 时求值为 0。

接下来,考虑集合 C \ S_ j,或者 C 中没有被选择包含在样本 S_ j 中的元素(在集合符号中,\符号表示排除)。设 p 代表这个集合中元素的个数。由于 C 的大小是 2m,样本 S_ j 是用大小为 m 的替换来选择的,p = 2m -|S_ j| >= m .我们将用 r 和 v 来索引 C \ S_ j 的元素(例如,C \ S_j 的第 r 个元素是 v_r)。这有什么意义?在上述损失函数的展开式中,我们可以用 C \ S_j 代替 C,方法如下:

这里我们使用了两个观察值。首先,我们使用 p >= m,如前所述。第二,我们利用了 C \ S_ j(右边的和)中的每一个元素都包含在 C(左边的和)中的事实。因此,左边的和更大。综合我们目前掌握的信息,我们有:

我们已经接近尾声了。看看这个表情:

现在我们来看这个证明的关键。注意,对于任意函数 f_i,我们可以构造另一个除 v_r 外与 f_i 完全相同的函数 f _ I’换句话说,对于 C 中除 v_r 外的所有元素 x,我们有 f _ I(x)= f _ I’(x)。而对于 v_r,我们有 f_i(v_r) ≠ f_i'(v_r)。所有可能的函数都可以这样配对。对于每一对函数,上面的指示函数对其中一个函数的评估值为 1,对另一个函数的评估值为 0。因此,T/2 对中的每一对将对总和贡献 1 + 0 = 1。因此,表达式的计算结果为 T/2。插上这个,我们有:

我们结束了。

关于这个证明,我们应该再说一句。为什么我们要费这么大的劲去看集合 C \ S_ j?难道我们不能在集合 C 本身上使用相同的自变量(将域中只有一个元素不同的函数配对),而不是在 C \ S_ j 上吗?答案是否定的。原因是,如果 f_i 和 f_i '之间的一个不同元素在 S_ j 中,则试图训练 f_i 的 A(S_ j)将输出与试图训练 f_i '的 A(S_j)不同的函数。然后,配对论点不再有效,因为即使 f_i(v_r)和 f_i’(v _ r)仍然不同,我们也没有办法保证 A(S_ j)(v_r)对于 f _ I 和 f _ I’是相同的。

在本文中,我们介绍了没有免费的午餐定理,看了几个简单的例子来建立我们的直觉,然后进行了数学证明。我知道这个证明有点复杂,所以请随时留下任何问题/评论。感谢阅读!

机器学习不只是大型科技公司的专利

原文:https://towardsdatascience.com/machine-learning-is-not-just-for-big-tech-using-natural-language-processing-to-support-small-8f571249c073?source=collection_archive---------29-----------------------

使用自然语言处理支持小型企业。

图片经所有者批准:阿尔托蒙特意大利市场的所有者(从左至右:文森特、玛丽亚、弗朗西斯、已故的米歇尔)

Altomonte's Italian Market 是一家家族经营的意大利熟食店,自 50 多年前业主移民到美国以来,一直在大费城地区提供传统的意大利美食。Altomonte's 从日耳曼敦的一个单间肉铺起步,现已发展成为一家拥有两家店铺、每周接待数千名顾客的企业。店主弗朗西斯和已故的米歇尔将意大利/美国传统与 21 世纪的理念融合在一起,尤其是在他们的儿子文森特和女儿玛丽亚的帮助下。Altomonte 的大部分分析仍然是按照传统进行的,包括为他们的屠宰部门挑选阉牛,直观地了解客户在一年中的不同时间会购买多少肉。进入 21 世纪,他们已经将技术进步,如三明治订单的触摸屏亭以及其他创新手段融入到他们的业务运营中。这些保持同步的进步还包括建立互联网存在,在这方面,他们的社交媒体平台取得了极大的成功。那么,Altomonte 的下一步能发展到哪里呢?将机器学习(ML)融入他们的日常运营能否继续帮助建立 Altomonte 的意大利市场和熟食店?答案是肯定的。一个家族拥有和经营的意大利市场,而不是硅谷的大型科技公司,可以从 ML 分析中受益。

自然语言处理

自然语言处理(NLP)是机器学习的一个集中领域,它分析人类语音和文本,以推断文档中隐藏的思想。NLP 中的“文本挖掘”是指我们可以通过对单词和 NLP 算法进行不同的转换,从文本体或“语料库”中获得更多的知识。可以采取各种方法来更好地理解一篇文章的主题。主题模型分析允许分析师提取信息,并提出主题或整个文本的摘要。情感分析模型不是寻找不同的主题和标题来描述数据,而是查看数据中隐藏的情感。这两种方法中使用了各种算法,从潜在狄利克雷分配模型二元模型神经网络。虽然我不打算向你展示我如何创建了一个人工神经网络(ANN) 可以将英语俚语文本转换成意大利语并检测你的讽刺,但我可以向你展示 NLP 技术如何能够帮助支持传统的意大利市场并为其提供见解。

情感分析

我可以从我为 Altomonte's 进行的分析中进入更好的细节和统计推断,相反,我认为我会让它变得有趣,并解释我如何训练一个卷积神经网络(CNN)来对脸书的市场评论进行情绪预测。所以请坐好,享受一盘美味的意大利面和肉丸(或者让我们跳过甜点,吃一个奶油甜卷),尽情享受吧!

什么是情感分析?

情感分析是解读文本中隐藏的态度、感觉或情绪的过程。“情绪”被定义为“由感觉引发的态度、思想或判断。”情感分析可以让我们在屏幕后面给我们想要交流的词语附加一种感觉。

卷积神经网络

总的来说,卷积神经网络 (CNN)在目标检测和图像分类领域显示出了有前途的结果。对于文本序列,如果 CNN 的输入维数从二维(图像高度和宽度)变为一维,则可以用于文本分析。在卷积层中,内核沿着样本滑动,沿着数据串在每个停止点进行计算。核的步幅决定了核应该沿着样本移动多少步或多少单位。例如,步幅为 2 的一维 CNN 将在句子序列中移动 2 个单位来进行计算,CNN 本质上是线性的,因此将激活函数应用于线性输出以创建非线性分量,该分量然后可用于对样本进行分类。

情绪分析:阿尔托蒙特的意大利市场在线评论

为了进行分析,使用了以下 python 库:

import keras
from keras.layers import Input, Conv1D, Embedding , MaxPooling1D, GlobalMaxPooling1D, Dense
from keras.models import Model
from keras.preprocessing.text import Tokenizer
from keras.optimizers import Adam
from keras.preprocessing.sequence import pad_sequences
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt

数据

训练数据是一个语料库,汇集了来自 Yelp、猫途鹰和谷歌评论的在线评论。这些评论涵盖了 Altomonte 公司过去 10 年的经营情况。训练集中的每个评论具有从 1 到 5 的相关评级,其中 1 被认为是差的,5 被认为是优秀的。脸书评论没有评级,支持他们作为测试数据来预测其隐藏的意义。

df = pd.read_csv('Altomontes_reviews.csv')
df.head()

图:的输出。csv 文件

如上所示,数据是一个评论列表,每个评论都有“月”、“年”、“评级”和“平台”特性。

数据处理

数据以数据框的形式加载后,它被重新构造为两列,一列包含评论,另一列包含基于评论各自评级的情感。首先,模型构建过程中不使用的列被删除。

df = df.drop(['Month','Year','Platform'],axis=1)
df2 = df

接下来,创建了一个名为“Label”的新的二进制列,如果一篇评论被认为是正面的,则该列的值为 1,如果一篇评论被认为是负面的,则该列的值为 0。评级为 3 或以上的评论被确定为正面,评级为 2 或以下的评论被确定为负面。

df['Label'] = [1 if x >=3 else 0 for x in df['Rating']]

预处理的下一部分包括将句子中被称为“记号”的单词转换成数字序列。

MAX_VOCAB_SIZE = 10000 
tokenizer = Tokenizer(num_words=MAX_VOCAB_SIZE)
tokenizer.fit_on_texts(X_train)
sequences_train = tokenizer.texts_to_sequences(X_train)
sequences_test = tokenizer.texts_to_sequences(X_test)

最大 vocab 大小设置为 10000,以确保序列不会变得太大。首先,创建了一个记号化器,并对评论进行了记号化。关于 tokenizer 如何工作的更多信息可以在这里找到。然后,标记化的评论被转换成可供 CNN 阅读的序列。一旦单词被标记化,它们就需要被映射到一个索引。这确保了每个单词都有自己唯一的数字序列。

word2idx = tokenizer.word_index
V = len(word2idx)

这个数据有 3,248 个唯一的令牌(比任意的最大值 10,000 少得多)。既然文本已经被索引并转移到序列中,它需要用零填充。填充确保通过神经网络运行的数据的每个输入都具有相同的大小。使用后置填充,将 0 添加到每个序列的末尾,使它们与最长的序列大小相同。

data_train = pad_sequences(sequences_train,padding='post')
data_test = pad_sequences(sequences_test,maxlen=T,padding='post')

数据现在已经处理完毕,CNN 可以在 Altomonte 的意大利市场在线评论上接受培训。

型号

对于该模型,具有三个一维层的 CNN 被公式化。初始输入是一个形状为(T)的向量,其中 T 是每个序列的长度。嵌入层将每个索引变量转化为形状大小为 20 的向量。

D = 20 i = Input(shape = (T,))
x = Embedding(V +1 , D)(i)
x = Conv1D(16,2,activation='relu',)(x)
x = MaxPooling1D(2)(x)
x = Conv1D(32,2,activation='relu')(x)
x = GlobalMaxPooling1D()(x)
x = Dense(1,activation='sigmoid')(x)model = Model(i,x)

一旦创建了模型,就使用二进制交叉熵作为损失函数对其进行编译。使用二元交叉熵是因为被评估的标准是评论是否被正确地识别为 1(正面)或 0(负面)。

model.compile(loss='binary_crossentropy',optimizer = 'adam',metrics = ['accuracy'])

一旦模型被编译,它就可以适合先前创建的训练和测试数据。

r = model.fit(data_train,y_train,epochs=5,validation_data=(data_test,y_test))

5 个周期后达到的准确度为 87.8%,这是不错的。训练中出现的一个问题是数据集很小,因此过度拟合是一个主要问题。减少参数(更少的层)和一些下降有助于克服过度拟合。Altomonte 的应该考虑在未来收集更多的评论,以获得一个更通用的预测模型。

预测

来自阿尔托蒙特意大利市场脸书页面的评论示例(嘿,看看这个!):

“强烈推荐!!!直到最近一个朋友来我家吃饭,我才知道奥尔多蒙特。我丈夫和我决定去看看,当我们在那里时,我们见到了店主,她是有史以来最可爱的人!她带我们参观了一下。晚餐我们买了马萨拉鸡,味道好极了!我们还买了布鲁克林披萨当午餐,非常好吃!我们品尝了他们的咖啡,他们让我们品尝了奶油煎饼卷、脆饼和饼干。非常好!我们买了贝壳、番茄酱、一瓶酒、一些奶酪等。一切看起来很好,味道很好,我们可以花几个小时在那里!我们会回来的!!也许今天?”

阅读这篇评论,我们可以直观地看到这是一个积极的情绪,然而,模型预测了什么?

review = tokenizer.texts_to_sequences(instance)pred_list = []
for sublist in review:
    for item in sublist:
        pred_list.append(item)predict_list = [predict_list]review = pad_sequences(flat_list, padding='post', maxlen=T)prediction = model.predict(review).round()

将代码转换成填充序列,可以对其情感进行预测。预测四舍五入为 0 或 1。

array([[1.]], dtype=float32)

正如你所看到的,这篇评论被预测为 1,或者是正面的(大约 88%的准确率)!就像这样,我们有一个 CNN 预测模型,Altomonte's 可以用它来衡量客户对未评级评论的态度和对其业务运营的感受!

结论

Altomonte 意大利市场在线评论中最常见的词(摘自完整分析)

小型企业可以将许多机器学习技术整合到他们的运营结构中,以帮助更好地了解企业生产力和绩效。对于食品行业的企业来说,自然语言处理很实用,可以更深入地了解客户的想法,而不仅仅是看评论和做出有根据的猜测。对于 Alomonte 的意大利市场,还有许多其他未讨论的 NLP 技术可以执行。评论的主题模型分析可以提供顾客在参观阿尔托蒙特企业时注意到什么和喜欢什么的反馈。小型企业要从 ML 分析中获得最佳结果,一个要点和建议是开始收集和存储大量数据,并开始整合 NLP 模型。感谢阅读!

来源

  1. Gé ron,A.: 用 Scikit-Learn 和 TensorFlow 实践机器学习:构建智能系统的概念、工具和技术。加利福尼亚州塞瓦斯托波尔奥莱利媒体公司(2017 年)。
  2. 瓦西里耶夫尤利。用 Python 和 Spacy 进行自然语言处理:实用介绍。旧金山:不上浆,2020。打印。
  3. 图片的使用得到了 Altomonte 的意大利市场公司的批准。

机器学习不是模型,而是特征

原文:https://towardsdatascience.com/machine-learning-isnt-models-it-s-features-be87b386db39?source=collection_archive---------27-----------------------

为什么特征工程和特征管理对你的 ML 项目和你选择的算法一样重要

图片经由 emojoez /Adobe Stock 在 Zer0 到 5ive 的许可下

从 Scikit-learn 到 Keras 再到 PyTorch,关于数据科学和 ML 主题的文章和教程数不胜数。只需几个小时,你就可以创建一个 GAN 来生成你看起来像卡通人物的图像,或者创建一个 LSTM 来创建文本消息,就好像它们来自你一样。这些都是具有惊人用例的强大技术。但是有一个关键点,许多教程都忽略了:ML 的力量并不来自于模型,它来自于数据,更具体地说,来自于特性。

“想出新功能是困难的,耗时的,需要专业知识。‘应用机器学习’基本上是特征工程”。~吴恩达

为什么功能不是更…有特色?

你会发现在整个 ML 领域的可用资源中存在同样的疏忽。例如,Coursera 的机器学习入门课程有十个部分,但其中只有两个部分是关于数据工程的,涵盖的主题是围绕数据结构化的数学概念(离群点去除和特征缩放),而不是特征创建。麻省理工学院非常受欢迎。S191 课程(这是我个人推荐的)是对深度学习领域的深入研究,但在其 10 门课程中,数据管理或工程方面的课程完全为零。吴恩达著名的斯坦福机器学习课程是现有的最好的机器学习课程之一,在 112 场讲座中,仅有少数几场专门讲述了数据的重要性。在一个关于异常检测的视频中,Andrew 说,“事实证明[……]对[一个模型]的表现有巨大影响的事情之一是你使用什么样的功能。”

作为一个 ML 社区,我们同样关注我们的技术努力,构建难以置信的建模工具,而忽略了提供给它们的数据。我们已经几乎自动化了构建经典 ML 模型的过程:遍历数千个 Sklearn 算法只需要几行代码,而以一种干净的方式跟踪这些信息只需要几行代码。Keras 极大地简化和民主化了深度学习框架,即使是初学者也能快速进步。但是,所有这些模型、框架和演示都假定了一条至关重要的信息:您的数据已经过预处理,可以放入 CSV 文件中。

没有数据就没有数据科学

对于学习来说,这是一笔巨大的财富,可以消除很多入门的摩擦。但实际上,这是一个几乎永远不会成立的假设。我经常和新毕业的大学生一起做真实世界的数据科学项目,我听到的最常见的反馈是,“我不敢相信我们花了这么多时间来预处理数据。我在学校里从来没学过这些。”这让我想到了大学和在线课程在未来的课程中需要考虑的两点:

  1. 数据管理是数据科学工作的主要部分。
  2. 数据科学家需要学习如何管理数据并为他们的模型构建有价值的特征。

Splice Machine 的首席数据科学家 Nirek Sharma 告诉我,“数据管理至关重要,但却常常被低估。如果在工程和预处理阶段不密切关注细节,建模阶段将会受到阻碍。”

当被问及他的个人经历时,Nirek 说他把大约 70%的时间花在数据工程上,30%的时间花在为客户的项目建模上。即使在“完美”数据的基础上构建演示模型,他也要花费高达 60%的时间进行特征工程。

特征工程不是简单的需要完成的平凡任务。它对你的模型质量有着巨大的影响。我一次又一次地看到,对精心设计的功能进行线性回归的项目比使用简单预处理的 Keras 模型更好。

我想明确一点:机器学习,特别是深度学习方面的进步非常棒,并且有令人难以置信的好用例。这并不是将这些进步投入生产的全部解决方案。

是时候再造特征工程了

所以特性很重要。难道我们不能自动化吗?有一些令人敬畏的开源自动化功能工程项目,甚至有些项目使用大数据框架,如 Spark 和 Dask。嗯,也许吧。关于你是否能完全自动化特征工程,有相当多的争论。领域专业知识是真实的,难以复制,但除此之外,有针对性的基于时间的功能可以为您的模型添加许多信号,并且可能很难在原始数据的海洋中找到。

然而,就本文的目的而言,假设是的,您可以完全自动化特征提取和工程的过程。那个仍然不是故事的全部,因为现在你有了一个静态特征集,它基于现在的数据。数据不是一成不变的,在构建模型时你也不能假设它是一成不变的。如果你在一组数据上用一组特定的超参数建立一个模型,然后第二天在一组略有不同的数据上用相同的超参数重建那个模型,你现在有一个不同的模型。

数据多了会怎么样?当数据改变时会发生什么?如果您找到另一个数据集,可以将其与当前数据集合并,以驱动更多信号,该怎么办?

当与数据相关时,你如何在你的模型中保持血统、治理和可再现性?

这里需要的是一套类似 DevOps 的工具来管理和自动跟踪 ML 模型的数据,就像软件工程师使用 GitHub 自动跟踪应用程序的代码一样。如果没有这些,你就建立了一个一次性的分析,而不是一个生产机器学习模型。

进入特色商店

图片经由 emojoez /Adobe Stock 在 Zer0 到 5ive 的许可下

如果我不提出解决方案就离开这篇文章,那将是不负责任的。要素存储是一种向数据工程工作流添加治理、沿袭和结构的机制。它为数据工程师提供了创建和记录要素的清晰(理想情况下非常灵活)的工作流,并使数据科学家能够重复使用这些要素来创建训练数据集,这些数据集与管道一起保持最新,以修改系统中的新数据。功能存储区在数据周围添加了一个 API 层(可能通过 DataFrame 或 SQL 构造),这使得获取模型的训练数据集变得非常简单…

功能商店有很多好处,比如功能共享、访问控制、实时功能服务等等,其中一些我会在本文这里中介绍。功能商店领域的另一个重要资源是 featurestore.org,它展示了当前可用的功能商店以及它们之间的一些重要差异。

归根结底,任何给定的机器学习模型的能力都取决于模型的强度用于构建模型的数据质量。作为一个领域,我们需要花更多的时间来强调数据的重要性和最初通知 ML 模型的特性。

资源:

要了解更多关于功能商店的信息,请查看featurestore.org,要查看更深入的分析,请查看功能商店的技术要求

Github Actions,Iterative.ai,Label Studio 和 NBDEV 在 MLOps 中的冒险

原文:https://towardsdatascience.com/machine-learning-lifecycle-with-mlops-github-actions-label-studio-iterative-ai-and-nbdev-30515f444a3e?source=collection_archive---------20-----------------------

作者:亚伦·索林格尔和威尔·昆兹@WallShots.co

在为我们的项目设计 MLOps 堆栈时,我们需要一种解决方案,允许高度的定制和灵活性,以便根据我们的实验进行发展。我们考虑了包含许多功能的大型平台,但发现它在一些关键领域有局限性。最终,我们决定采用一种方法,为标记、数据版本控制和持续集成实现单独的专用工具。本文记录了我们构建这种定制 MLOps 方法的经验。

照片由 Unsplash 上找到丹|丹·格林维斯

NBDEV

(摘自https://github.com/fastai/nbdev)

使用 Jupyter 进行开发的典型问题是,从原型到产品需要将代码从笔记本复制/粘贴到 python 模块。NBDEV 使笔记本和模块之间的转换自动化,从而使 Jupyter 笔记本成为生产流水线的正式组成部分。NBDEV 允许开发者声明笔记本应该创建哪个模块,将哪个笔记本单元推送到模块,以及哪个笔记本单元是测试。NBDEV 的一个关键功能是它在笔记本中的测试方法,NBDEV 模板甚至提供了一个基本的 Github 动作来实现 CI/CD 框架中的测试。生成的 python 模块不需要开发人员进行编辑,并且可以使用内置的 Python 导入功能轻松集成到其他笔记本或整个项目中。

Iterative.ai: DVC/CML

(摘自https://iterative.ai/)

机器学习管道中使用的文件通常是二进制/压缩文件的大型档案,对于 git 等现有版本控制解决方案来说,这些文件是不可访问的或者成本过高。DVC 通过将大型数据集表示为文件内容的散列来解决数据版本控制问题,这使得 DVC 能够跟踪更改。它的工作方式类似于 git(例如dvc adddvc push)。当您在数据集上运行dvc add时,它会被添加到.gitignore中,并由dvc跟踪变化。CML 是一个项目,它提供了将模型工件从 Github 动作工作流发布到附加 Github 问题的评论、拉请求等中的功能...这很重要,因为它有助于我们开始填补拉请求中的空白,说明培训数据的变化以及由此产生的模型准确性和有效性。

Github 操作

(摘自https://github.com/features/actions)

我们想要自动化代码测试,包括在自动化测试管道中构建模型。Github Actions 与 CircleCI、Travis、Jenkins 竞争,后者围绕代码推送、提交、拉取请求等进行自动化测试。由于我们已经在使用 Github 来托管我们的回购,我们通过使用 Actions 来避免另一个第三方应用程序。在这个项目中,我们需要使用 Github 自托管运行程序在本地 GPU 集群上运行作业。

标签工作室

(摘自https://labelstud.io/)

我们深入探讨了如何使用 Label Studio found 这里。Label Studio 是一个标注数据的解决方案。它运行良好,并且可以灵活地在各种环境中运行。

为什么要一起用?

该设置旨在更快地部署模型。这意味着,更多的数据科学家和谐地并行工作,存储库透明,新人入职时间更快。目标是标准化数据科学家在 project 中需要完成的活动类型,并为他们提供清晰的说明。

以下是我们希望通过该系统设计简化的任务列表:

  1. 自动从 Label Studio 接收信息,并提供一个单一的接收点,用于模型培训和评估活动。
  2. 对数据管道代码进行自动化测试,也就是对流程所使用的容器进行单元测试和重新部署。
  3. 对模型代码的自动化测试,也就是对流程所使用的容器进行单元测试和重新部署。
  4. 使自动化测试包括模型再训练和评估标准。当模型代码更改时,使用新代码训练模型,并将其与现有的现任模型进行比较。
  5. 当训练数据更改时触发模型重新训练。

下面是每个任务的管道描述。

传统 CI/CD 渠道

该管道为每个拉请求实现自动测试反馈,包括语法、单元、回归和集成测试的评估。这个过程的结果是一个经过功能测试的 docker 映像到我们的私有存储库中。这个过程最大限度地提高了最新的最佳代码位于存储库中可用于下游任务的经过全面测试的映像中的可能性。下面是开发人员生命周期在新特性环境中的工作方式:

这里我们展示了在编辑代码时工作流是如何工作的。使用 NBDEV 使我们能够直接在 Jupyter 笔记本上工作,包括直接在笔记本上编写测试。NBDEV 要求笔记本中的所有单元无一例外地运行(除非单元被标记为不运行)。(图片由作者提供)

数据管道

Label Studio 目前缺少事件挂钩来支持对存储的标签数据进行更新。因此,我们采用cron触发的方法,每小时更新一次数据集。此外,虽然 label studio 训练数据集足够小,但更新也可以作为训练管道的一部分来完成。我们能够使用 Github Actions 接口按需触发数据管道刷新。

数据管道来自 Label Studio,并将数据集的每个版本和相关输入保存到存储在 AWS S3 的 DVC 缓存中。(图片由作者提供)

模型管道

建模管道将模型培训集成到存储库的 CI/CD 管道中。这使得每个拉请求能够评估在代码库上配置的语法、单元、集成和回归测试,而且还可以提供包括评估新的结果模型的反馈

本例中的工作流运行配置文件(model_params.yaml)中指定的模型训练实验,并更新模型工件(best-model.pth)(图片由作者提供)

基准评估管道

基准管道形成了一个“正式提交”过程,以确保所有的建模活动都根据项目的度量标准进行测量。

根据基准数据集对 best-model.pth 中新训练的模型进行评估,结果用最新的提交散列进行标记,并保存在 AWS S3 中。(图片由作者提供)

工作流程

这是 DVC 使用的 DAG 定义文件。它捕获工作流程步骤及其输入,并允许用户和机器之间的再现性。

stages:
  labelstudio_export_trad:
    cmd: python pipelines/1_labelstudio_export.py --config_fp pipelines/traditional_pipeline.yaml
      --ls_token *** --proj_root "."
    params:
    - pipelines/traditional_pipeline.yaml:
      - src.host
      - src.out_fp
      - src.proj_id
  dataset_create_trad:
    cmd: python pipelines/2_labelstudio_todataset.py --config_fp pipelines/create_traditional.yaml
      --proj_root "."
    deps:
    - data/raw_labels/traditional.json
    params:
    - pipelines/create_traditional.yaml:
      - dataset.bmdata_fp
      - dataset.labels_map
      - dataset.out_fp
      - dataset.rawdata_dir
  train_model_trad:
    cmd: python pipelines/3_train_model.py --config_fp pipelines/model_params.yaml
      --proj_root "."
    deps:
    - data/traditional_labeling
    params:
    - pipelines/model_params.yaml:
      - dataloader.bs
      - dataloader.size
      - dataloader.train_fp
      - dataloader.valid_fp
      - learner.backbone
      - learner.data_dir
      - learner.in_checkpoint
      - learner.metrics
      - learner.n_out
      - learner.wandb_project_name
      - train.cycles
  labelstudio_export_bench:
    cmd: python pipelines/1_labelstudio_export.py --config_fp pipelines/benchmark_pipeline.yaml
      --ls_token *** --proj_root "."
    params:
    - pipelines/benchmark_pipeline.yaml:
      - src.host
      - src.out_fp
      - src.proj_id
  dataset_create_bench:
    cmd: python pipelines/2_labelstudio_todataset.py --config_fp pipelines/create_benchmark.yaml
      --proj_root "."
    deps:
    - data/raw_labels/benchmark.json
    params:
    - pipelines/create_benchmark.yaml:
      - dataset.bmdata_fp
      - dataset.labels_map
      - dataset.out_fp
      - dataset.rawdata_dir
  eval_model_trad:
    cmd: python pipelines/4_eval_model.py --config_fp pipelines/bench_eval.yaml --proj_root
      "."
    deps:
    - data/models/best-model.pth
    params:
    - pipelines/bench_eval.yaml:
      - eval.bench_fp
      - eval.label_config
      - eval.metrics_fp
      - eval.model_conf
      - eval.overlay_dir

调查的结果

  1. Github Actions 工作流cron触发器不是非常可靠。它不能保证时间。
  2. 在推送触发的 Github 动作工作流中,DVC 的工作方式并不清晰。它将改变源代码控制的跟踪器,当它被提交时,它将创建另一个 Github 动作。
  3. Github Actions orchestration 作为一种运行模型的机制,需要一个自托管的运行程序来使用 GPU。这意味着连接到云中或本地的 GPU 实例,这带来了访问控制问题。例如,如果不从 repo 中移除自托管的 runner 配置,我们就不能开源确切的 repo,否则随机的人将能够通过将代码推送到项目来在我们的培训服务器上运行工作负载。
  4. NBDEV 内置工作流在错误的地方测试代码。它是在测试笔记本而不是编译好的包。一方面,能够说“测试可以直接写在笔记本上”是件好事。另一方面,测试笔记本直接测试留下了 NBDEV 创建的代码包失败的可能性,即使笔记本运行了。我们需要的是直接测试 NBDEV 编译的包的能力
  5. 从 NBDEV 是单行道的意义上来说,NBDEV 不与“传统的”Python 开发互操作。它只是允许项目以交互式 Jupyter 笔记本风格开发。这使得直接开发 Python 模块变得不可能。如果在任何时候,项目想要转换成“传统的”Python 开发测试,就需要用另一种方式来完成。
  6. 一开始,我们使用 Weights & Biases 作为我们的实验跟踪仪表板,但是在将其部署到 Github 操作中时出现了问题。我们可以说的是,实现wandb的用户体验在动作工作流中遇到了第一次挫折。去除重量&偏见直接解决了问题。在此之前,wandb在 MLOps 中脱颖而出,成为最佳用户体验。

结论

最终,用 Github Actions、Iterative.ai tools (DVC & CML)和 NBDEV 完成了这些管理我们代码的工具的实现,花了一周时间。这为我们提供了以下功能:

  1. Jupyter 笔记本作为代码的记录系统。我们喜欢朱庇特。它实现的主要用例是,通过在任何硬件上托管一个 Jupyter 服务器并将其转发到桌面,使我们能够直接在我们可以 SSH 到的任何硬件上工作。明确地说,即使我们不使用 NBDev,我们也会这样做,因为替代方案是使用 Vim 或一些我们不太喜欢的工具。过去用 VS 代码或 Pycharm 连接远程服务器的实验都失败了。所以是朱庇特。
  2. 测试代码,并测试它创建的模型。现在,作为 CI/CD 管道的一部分,我们可以评估回购变更产生的模型是否会使模型变得更好、更差或保持不变。这在 pull 请求合并到main之前都是可用的。
  3. 使用 Github Actions server 作为训练运行的协调器,开始允许多个数据科学家以更清晰的方式同时工作。展望未来,我们将看到这种设置在编排协作数据科学流程方面的局限性。

机器学习迷你项目 5

原文:https://towardsdatascience.com/machine-learning-mini-project-6f67e511ffd3?source=collection_archive---------18-----------------------

使用 pycaret、keras 和 Tensorflow 概率预测首尔每小时自行车租赁量

照片由像素皮克斯拜拍摄

数据:来自 UCI 机器学习知识库的首尔自行车共享数据集。目标是租赁自行车数量。这意味着这是计数数据,是正整数值。预测因子/特征大多与天气相关,例如阳光、雨、风、能见度,以及时间特征,例如一天中的小时、是否是假日等。你可以在这里查看我的整个 colab 笔记本。

问题:这应该是泊松回归问题吧?计数数据通常假设来自泊松分布。与其回顾基础知识,我建议您参考下面两篇优秀的教程,以及普林斯顿大学关于广义线性模型(GLMs)的课堂笔记。

泊松回归简介

[泊松回归图解指南](http://An Illustrated Guide to the Poisson Regression Model)

泊松模型为计数数据

假设我们只对系统工作的天数进行建模——这是直方图和核密度估计值,让您对 pdf 有个大概的了解。

问题的答案是:这可能没那么重要。正如教程中提到的,您可以使用最小二乘法(假设基于协变量的某个(非线性)线性预测值为高斯响应分布。如果您想要整数预测,您总是可以将连续标签四舍五入为整数值。我们还可以使用不同的损失函数来调整我们的正常方法(例如 XGBoost ),以更好地适用于计数数据。

预处理。我为此使用 pycaret。我发现对特性使用 分位数变换 会有所帮助,而不是像 box-cox 或 yeo-johnson 那样的幂变换。我认为feature _ selectionfeature _ interaction也很有帮助,你会在下面的特性重要性分析中看到。数据被分割成 80/20,没有洗牌,因为它是一个时间序列,我们不想从未来泄漏到过去。小时季节是整数编码变量,我决定将它们视为序数(有序分类)变量。我放弃了日期变量本身;我想也许人们可以将月份作为一个新的特征,但我认为季节往往会涵盖这一点——本质上,其他变量也是如此,它们描述了每日和季节性的天气状况。

py caret 中的默认学习者

明白了,ExtraTreesRegressor()

因此,在这里,ExtraTreesRegressor()似乎是明显的赢家。以下是一些更重要的特性,包括一些交互术语:

如果我真的不喜欢骑自行车的话,时间和降雨量的相互作用对我来说很有意义。

替代损失函数。但是这些学习器是默认设置的,这意味着对他们中的很多人来说,你正在使用一些 MSE/RMSE 类型的损失函数。然而,您可能更感兴趣的是对 MAE 建模,或者至少是对它进行报告,因为当您谈论自行车之类的东西时,MAE 是衡量拟合优度的最“直观”的方式。然而,有足够好的理由探索不同的损失函数,如 MAE、Huber、Poisson、Logcosh 等。根据泊松偏差来考虑拟合优度也是值得的。原因何在?因为正如我们所知,MSE 往往会受到异常值的影响,而 MAE 则没有那么大。Huber 有点像 MSE 和 MAE 的组合,这意味着它试图不受异常值的过度影响,Logcosh 就像 MAE 的平滑版本,其梯度随着您达到 0 而变得平坦(因此如果您使用 SGD,可以减轻爆炸梯度)。泊松有点奇怪,但是倾向于惩罚你在泊松分布的重尾中发现的更大的计数值,导致更好的校准模型。这里有一个学习者列表,我们将尝试各种损失函数。这不是详尽的,但应该让我们知道是否有任何进一步的途径。

reg_list = [
DummyRegressor(strategy = "mean"),
PoissonRegressor(max_iter = 5000),
XGBRegressor(objective = "count:poisson"),
LGBMRegressor(objective = "mae"),
LGBMRegressor(objective = "poisson"),
LGBMRegressor(objective = "huber"),
LGBMRegressor(objective = "tweedie"),
HistGradientBoostingRegressor(loss = "poisson"),
CatBoostRegressor(objective = "Poisson", verbose = 0),
CatBoostRegressor(objective = "MAE", verbose = 0),
CatBoostRegressor(objective = "Huber:delta=200", verbose = 0)]

以下是通过 pycaret 得出的结果:

在泊松偏离方面,我发现上面列表中的第三个 Huber 损失的 CatBoostRegressor()表现最好。如果 R2 是你选择的绩效指标,它也会被认为是最好的。

改造目标。通常将响应变量的平方根作为方差稳定变换。这意味着你正在转换回归方程的两边。我尝试在 pycaret 中使用 yeo-johnson。如果想求平方根,用 sklearn 中的 TransformTargetRegressor()函数自己做,就像这样。我读到过很多人在求平方根之前在回答中添加一些东西,尤其是如果有 0 的话,但是我们没有,我不确定结果会有很大变化。我对预测进行了剪辑,使任何小于 0 的值都映射到. 0001。

def squareme(x):
  return  x ** 2tt = TransformedTargetRegressor(regressor =    ExtraTreesRegressor(criterion  = "mse"),func = np.sqrt, inverse_func = squareme)tt.fit(X_train, y_train)
preds = tt.predict(X_test)
preds = preds.clip(min = .0001)

结果令人惊讶。你在这张图上看不到它,这一轮的平均寿命是 219,但你可以很容易地降到 210-215。泊松偏差也相当低,为 126,但是未转换目标上的 ExtraTreesRegressor()可以达到 119 左右,因此它可能在技术上得到更好的校准。不管是哪种方式,ExtraTreesRegressor()都远远超过其他的。

喀拉斯。让我们换个方式,看看深度学习在这项任务上可能会有什么表现。我们可以从一个常规的深度网络开始,它在最后有一个 tf.exp(指数)激活。这意味着,你把它当作一个有对数联系的泊松回归。使用深度学习的优势在于,您可以将泊松的对数(速率)表示为特征/回归变量的更具表现力的非线性函数。另一件好事是,我们可以使用 keras/tensorflow 内置的各种损失函数。换句话说,你可以使用“Huber”、“poisson”、“logcosh”、“mae”、“MSE”等。当你编译模型的时候。但是请记住,您必须重置回调并调整学习速率——例如,对于“mse ”,梯度为 x,因此您应该将学习速率降低到更小的值,如 1e-4。此外,我将对数据使用 MinMaxScaler(),使其在[0,1]范围内。这有很大的不同。以下是缩放后的代码:

early_stopping = EarlyStopping(patience = 25, restore_best_weights = True, min_delta = 0.1, monitor = "val_loss")reduce_LR = ReduceLROnPlateau(factor = 0.9, patience = 10, min_delta = 0.1)i = Input(shape = (trainx.shape[-1]))
o = Dense(100, "relu")(i)
o = Dense(50, "relu")(o)
o = Dense(25, "relu")(o)
o = Dense(1, activation = tf.exp)(o)model_dnn = Model(inputs = i, outputs = o)
model_dnn.summary()
model_dnn.compile(loss = "poisson", optimizer = Adam(2e-4))model_dnn.fit(trainx, trainy,
validation_data = (valx, valy),
callbacks = [early_stopping, reduce_LR],
batch_size = 32,
epochs = 1000)model_dnn.fit(trainx, trainy,
              validation_data = (valx, valy),
              callbacks = [early_stopping, reduce_LR],
              batch_size = 32, epochs = 1000)

当然,每次的结果都不一样。我会说这或多或少是 MAE/Logcosh 和泊松损失函数之间的联系。平均相对误差预计在 220-235 之间。奇怪的是,这个模型如何错过了你在下面看到的那些尖峰,我认为这是某种“高峰时间”。ExtraTreesRegressor()至少在模型预测中有某种“峰值”。

它错过了尖峰。

张量流概率。让我们让神经网络的最后一层更具概率性,要求它从参数分布中返回一个样本,也就是说,让我们使用神经网络来找到泊松的速率/方差,然后让我们的 yhat 预测成为该样本。为此,我们需要从 pdf 中抽取样本的图层。可以看到我注释掉了一行有 tfd 的。在里面很正常。其原因是速率>为 20 左右的泊松可以近似为具有相同均值和方差的高斯。这意味着高斯的“标度”——标准差——是它的平方根,因此是 K.sqrt(x)部分。损失函数是与理论分布相比的负对数似然。

import tensorflow_probability as tfp
import tensorflow as tf
tfd = tfp.distributions
import keras.backend as Kinputs = Input(shape=(trainx.shape[1],))x = Dense(100, "relu")(inputs)
x = Dense(50, "relu")(x)
x = Dense(25, "relu")(x)
x = Dense(1, tf.exp)(x)#p_y = tfp.layers.DistributionLambda(lambda x : tfd.Normal(loc = x, scale = K.sqrt(x)))(x)p_y = tfp.layers.DistributionLambda(lambda x : tfd.Poisson(x))(x)model_p = Model(inputs=inputs, outputs=p_y)def NLL(y_true, y_hat):
  return -y_hat.log_prob(y_true)model_p.compile(Adam(lr = 2e-4), loss = NLL)
model_p.summary()

结果相当不错:平均汇率可以降到 223 左右。使用 keras/Normal 模型,我可以在一次良好的试验中达到 213 的 MAE。这种 keras/正态模型的泊松偏差约为 106,keras/泊松可以达到 101。相比之下,ExtraTreesRegressor()的泊松偏差在 120 范围内。也许 keras/Poisson 模型可以被认为是 ExtraTreesRegressor()的一个可行的替代方案,因为它可以实现一个可比较的 MAE,但明显更好的 Poisson 偏差。

就是这样。希望你喜欢。欢迎提问和评论,记得查看我的 colab 笔记本(顶部的链接)。

这里有一些我认为有助于理解理论和想法的参考资料。

https://stats.stackexchange.com/questions/46418/why-is-the-square-root-transformation-recommended-for-count-data https://scikit-learn.org/stable/auto_examples/linear_model/plot_poisson_regression_non_normal_loss.html https://blog.tensorflow.org/2019/03/regression-with-probabilistic-layers-in.html https://matthewmcateer.me/blog/a-quick-intro-to-bayesian-neural-networks/ https://stats.stackexchange.com/questions/492726/what-is-use-of-tweedie-or-poisson-loss-objective-function-in-xgboost-and-deep-le

如何建立基于机器学习的预测系统

原文:https://towardsdatascience.com/machine-learning-ml-based-predictive-system-to-predict-the-satisfaction-level-of-airlines-f0780dbdbc87?source=collection_archive---------18-----------------------

开发预测模型的实用数据科学指南,该模型将客户分为两类满意度

奥斯汀·迪斯特尔在 Unsplash 上拍摄的图片

简介

我们都知道客户满意度是提升公司业绩的关键,但是组织仍然努力利用不断增长的数据可用性来满足客户。在这篇文章中,我说明了如何使用机器学习和数据科学技术来评估和评价客户满意度。我将介绍开发客户驱动的预测模型的必要步骤,从问题框架开始,到数据探索 分析数据转换ML 培训,以及建议

该数据集是从标题为“航空乘客满意度”的 Kaggle 中提取的。

问题识别

我首先阐明项目中要解决的业务问题。事实上,航空业一直面临着改变客户偏好的技术颠覆。如今,客户越来越希望享受安全的体验,为他们提供多样化而个性化的产品(普华永道,2021)。因此,对组织来说,区分满意和不满意的个人,并确定决定顾客满意度的特征是至关重要的。

定义目标

通过这个项目,我旨在展示如何:
、探索和可视化数据、
、为机器学习准备数据、
、训练和微调预测算法、
、提取重要特征、
、推荐创新的数据驱动技术。

#import packages and modules#data manipulation 
import pandas as pd
import os#data visualisation 
import matplotlib.pyplot as plt
import seaborn as sns#machine learning 
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import OneHotEncoder
from sklearn.impute import SimpleImputer
from sklearn.metrics import classification_report 
from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import RandomizedSearchCV

数据清理和转换

第二个任务是执行数据争论。幸运的是,数据集不需要大量清理。但是,我必须将一些变量的数据类型转换成分类,删除不必要的列,并检测丢失的值,这些变量包括客户类型、类别、满意度、性别和旅行类型。此外,我创建了两个新变量来支持稍后阶段的数据分析;下面列出了这两个变量:

  • over_all rating: 计算所有数字变量的平均值,从顾客反馈中取 5 分
  • total_delay: ,合计到达和离开的延误时间。

数据清理部分的代码如下所示。

#Load the data
def load_data(data_path,filename):
    data_path = os.path.join(data_path, filename)
    return pd.read_csv(data_path)Airlines = load_data('/project/',"Airlines.csv") #change the path#inspect the data 
Airlines.head()#get the data info
Airlines.info()#check the shape of the data-frame
Airlines.shape #check for missing values
Airlines.isna()#check for duplicated values
Airlines.duplicated() #create a data cleaning function
def data_cleaning(
    Airlines:pd.DataFrame
              )->pd.DataFrame:
    Airlines['Gender'] = Airlines['Gender'].astype('category')
    Airlines['Type of Travel'] = Airlines['Type of Travel'].astype('category')
    Airlines['Customer Type'] = Airlines['Customer Type'].astype('category')
    Airlines['Class'] = Airlines['Class'].astype('category')
    Airlines['satisfaction'] = Airlines['satisfaction'].astype('category')
    Airlines.drop("Unnamed: 0", axis =1, inplace= True)
    return Airlines.info()#call the cleaning function 
data_cleaning(Airlines)#create a new variable : over_all rating 
Airlines['overall_rating'] = round((Airlines['Inflight wifi service']+ Airlines['Departure/Arrival time convenient'] +
Airlines['Ease of Online booking'] + Airlines['Gate location'] + Airlines['Food and drink']+ Airlines['Online boarding'] + 
Airlines['Seat comfort'] + Airlines['Inflight entertainment'] + Airlines['On-board service'] + Airlines['Leg room service'] + 
Airlines['Baggage handling'] + Airlines['Checkin service'] + Airlines['Inflight service'] + Airlines['Cleanliness'])/14,1)#create a new variable : total delay 
Airlines['Total_Delay'] = (Airlines['Departure Delay in Minutes']+ 
                                    Airlines['Arrival Delay in Minutes'])#inspect the data frame again to check the new columns
Airlines.head()

探索性数据分析

在这一节中,我将探索数据集并展示数据可视化,以查明变量之间的关系。

我检查汇总统计数据,并为数据集的数值变量创建直方图,如下面的代码所示。

numeric_variables = list(Airlines.select_dtypes(include=['int64', 'float64'])) #select the numeric variablesAirlines[numeric_variables].describe().apply(lambda x:round(x,2)).T #apply describe methodhistograms = Airlines[numeric_variables].hist(bins =10, xlabelsize=10, ylabelsize=10, grid=False, sharey= True, figsize = (15,15)) #create the histograms

然后我研究了满意度和阶级类别之间的关系。

**#First Visual: Satisfaction and Class Category** by_cat_class = Airlines.groupby(['Class', 'satisfaction']) by_cat_class.size() #get the size of the dataframe 
ax = by_cat_class.size().unstack().plot(kind='barh', color = ['aqua', 'grey']) #unstack and plot ax.set_title('Travel Class and Satisfaction', size =14) #title 
plt.xticks(fontsize=12)
plt.yticks(fontsize=12)
ax.set_xlabel('Number of Customers', fontsize = 14) #set the x_label 
ax.set_ylabel('Class Category', fontsize = 14); #set the y_label

该图显示,商业客户最满意,而生态客户最不满意。最重要的是,80%的 eco 客户都不满意。这表明该服务的提供并不符合不同阶层的偏好,而且只对商务阶层给予了更多的关注。

我还调查了总延迟时间、总体评分和满意度之间的关系。

**#Second Visual: Total Delay, Overall Rating, and Satisfaction** plt.figure(figsize = (8,6)) #figure size 
sns.set(rc= {"font.size":14, "axes.titlesize":14, "axes.labelsize":14}) m = sns.relplot(x="overall_rating", y="Total_Delay",hue ='satisfaction', data=Airlines); #define graph variables plt.title('Total Delay, Overall rating, and Satisfaction') 
plt.xlabel('Total_Delay') # set x_label
plt.ylabel('Overall_Rating'); #set y_label

很明显,总延迟会影响满意度,因此延迟时间越短,平均评分越高,客户越满意。

我还会检查年龄是否会影响顾客的满意度。

**#Third Visual: Age and Satisfaction**#Discretize the overall_ratings into buckets
overall = Airlines['Age']
labels = pd.cut(overall, [0, 18, 35, 50, 65 , 80])
grouped = Airlines.groupby(['satisfaction', labels]) 
grouped.size().unstack(0) #unstack#sum group amounts
bucket_sums = grouped.overall_rating.sum().unstack(0)#normalize within buckets 
normed_sums = bucket_sums.div(bucket_sums.sum(axis=1), axis=0)#plot the discretized ratings buckets and satisfaction
plot = normed_sums.plot(kind='barh', stacked=True, color= ['aqua','cadetblue'] )plot.legend(loc="upper center",ncol=2,borderaxespad=0.,bbox_to_anchor=(1.05, 1))
plot.set_title('Satisfaction and Age', size =14)
plot.set_xlabel('Proportion of Customers', fontsize = 14)
plot.set_ylabel('Age Bucket', fontsize =14);

图表显示年龄在 18 岁以下和 65 岁以上的顾客满意度最低。航空公司应该考虑为成年人和老顾客提供个性化服务。

根据探索性分析,我们可以推断旅行等级、总延误时间和年龄正在影响顾客的满意度。

数据准备

在这个阶段,我为 ML 模型准备数据。以下是应该遵循的总结步骤:
。分别以 80/20 的比率将数据分割为训练集和测试集
。将因变量“满意度”编码为{0:'不满意',1:'满意' }
。建立完整的管道,以估算和标准化数据,并对分类变量进行编码。

#train_test split
Airlines_1 = Airlines.copy() #make a copy of the data
train_set, test_set = train_test_split(Airlines_1, test_size=0.2, random_state=42) #split the training (0.8) and test (0.2)
test_set.head() #inspect the test data#drop the dependent variable from the train_set 
x_train = train_set.drop("satisfaction", axis=1) #train set 
y_train= train_set['satisfaction'] #train dependent variable
x_test = test_set.drop("satisfaction", axis=1) #test set 
y_test = test_set['satisfaction'] #test dependent variable#define numeric and categorical variables
numeric_variables = list(Airlines.select_dtypes(include=['int64', 'float64']))
categorical_variables = ['Gender', 'Customer Type', 'Type of Travel', 'Class']#encode the dependent variable: satisfaction
labelencoder_y = LabelEncoder()
y_train = labelencoder_y.fit_transform(y_train)#build a pipeline for numeric and categorical datanum_pipeline = Pipeline([('imputer', SimpleImputer(strategy="median")),
('std_scaler', StandardScaler()),]) #numeric pipelinefull_pipeline = ColumnTransformer([
("num", num_pipeline, numeric_variables  ),
("cat", OneHotEncoder(),categorical_variables),]) #full pipeline#apply the pipeline
x_train = full_pipeline.fit_transform(x_train) #Apply data transformation on test_set
test_y = labelencoder_y.fit_transform(y_test) 
x_test = full_pipeline.fit_transform(x_test) x_test #inspect

预测建模和微调

现在,在为训练准备好数据之后,我们应该选择 ML 模型。由于预测任务是二元分类,我将训练不同的监督 ML 算法,即逻辑回归、支持向量机和随机森林,来预测客户的满意度。我还会通过检查每个型号的分类报告来评估性能。

#Create a function to train the models
def training_fnt(model, x_train, y_train):
    model.fit(x_train , y_train ) #fit the model 
    y_predict = model.predict(x_train) #predict
    print('Classification report: \n', classification_report(y_train ,y_predict)) #classification report #initiate the models 
log_model = LogisticRegression(max_iter=200, random_state=42)
svm_model = SVC(gamma="auto", random_state=42) 
rf_model = RandomForestClassifier(random_state=42) #call the function on each model separately 
training_fnt(log_model)
training_fnt(svm_model)
training_fnt(rf_model)

根据分类报告,随机森林具有最高的准确性分数,因此,可以使用随机搜索将其列入微调的候选名单。

然后,我使用随机搜索对随机森林进行微调。

#use random search to fine-tune RandomForestClassifier#define the model
rnd_clf = RandomForestClassifier(random_state=42)'#define parameters 
search = [
    {'n_estimators': [3, 10, 30], 'max_features': [2, 4, 6, 8], 'bootstrap': [False, True], 'max_depth': [2, 3, 4,8] }]#set up the search search 
random_search  = RandomizedSearchCV(rnd_clf , search , cv=3,
                           scoring='f1', return_train_score=True)
#fit the search
random_result_RF = random_search.fit(x_train , y_train)#summarize results
print("Best: %f using %s" % (random_result_RF.best_score_,random_result_RF.best_params_))

随机搜索的结果是:

最佳:0.907877,使用{'n_estimators': 10,' max_features': 2,' max_depth': 8,' bootstrap': False}。

建立这些参数后,我将最终模型拟合到测试集上,以评估在看不见的数据点上的性能。

最终的模型在测试集上达到了 93%的平均准确率。

特征抽出

我还对从随机森林分类器中提取重要特征感兴趣。这些变量是客户感到满意时最看重的维度。

#extract the important features from the final modelnew_rf_clf = final_model
new_rf_clf.fit(x_train ,y_train) #fit the model
feature_importances = new_rf_clf.feature_importances_ 
attributes = numeric_variables + categorical_variables 
feat_importances = sorted(zip(feature_importances, attributes), reverse=True) #create a sorted tuple #visualize the feature importance of Random Forest
df_rf = pd.DataFrame(data = feat_importances) #create a dataframe 
df_rf.columns = ['importance', 'feature'] #rename the columns
df_rf.set_index('feature', inplace=True)#set the index 
fig, ax = plt.subplots(figsize=(10,6))
df_rf.plot(ax=ax, kind='barh', color ='aqua') #define the plot plt.xticks(fontsize=13)
plt.yticks(fontsize=13)
ax.set_title('Important Features of the Random Forest Model', fontweight="bold", size =16) #set title 
ax.set_xlabel('Relative Importance', fontsize = 13)
ax.set_ylabel('Feature', fontsize = 13);

Random Forest 的重要功能包括:在线登机、Wi-Fi 服务、在线预订和机上娱乐。

结论

根据调查结果,我们得出结论,环保客户满意度最低,年龄、登机、在线预订、娱乐和 Wifi 服务是决定客户满意度的最明显特征。总的来说,我们的预测算法有 93%的预测能力来对客户进行分类,并支持航空公司监控和评估服务绩效。

建议和后续步骤

最后,我可以推荐航空公司组织实施以下技术:

1-根据年龄类别为顾客设计个性化套餐,特别针对满意度最低的成年人和老年人,

2-改善飞行中的 WiFi 接入和娱乐,

3-为浏览其网站和社交媒体平台的客户实施在线预订协助服务。

接下来的步骤应该集中在生产阶段,通过该阶段,可以使用新客户的数据部署和测试预测模型。

我希望你喜欢这篇文章,现在你有能力开发你的预测模型。

敬请关注更多关于数据科学的有趣阅读和知识分享!

参考文献:

[1]普华永道,航空业的未来 (2018),顺风:2018 年航空业趋势

使用谷歌应用引擎的无服务器应用的机器学习模型

原文:https://towardsdatascience.com/machine-learning-model-as-a-serverless-app-using-google-app-engine-b760de59156?source=collection_archive---------17-----------------------

无服务器机器学习,GCP

因此,您构建了一个模型,并希望将其部署为一个无服务器应用程序。让我向您展示如何使用 Docker 容器、Streamlit 和 Google App Engine 来做到这一点!

天马Unsplash 上拍照

解决方案架构和主要组件

在继续之前,让我们看一下整体架构,并介绍该解决方案的主要组件。

运行在 Google App Engine 上的机器学习应用的架构。(来源:作者制作)

在这个架构中,一个机器学习模型使用 Streamlit 框架变成了一个 web 应用。然后这个 app 被打包成一个 Docker 容器,然后部署在 App Engine 上与全世界分享!

谷歌应用引擎

App Engine 是 Google 推出的一款完全托管的无服务器应用平台产品,可让您轻松部署您的 web 应用。部署应用程序就像运行命令gcloud app deploy一样简单。

由于它是无服务器的,您不必担心管理服务器或任何基础设施。它会根据应用程序收到的请求数量自动扩展。因此,当没有流量时,它会缩小到零。而且你只为你用的东西付费!

谷歌云平台一分钟内的应用引擎(来源:GCP Youtube)

在这种情况下,我们将使用谷歌云平台(GCP)提供的这种无服务器产品来服务我们的机器学习模型,作为一个应用程序供其他人进行交互。

机器学习模型

出于本文的目的,我已经为著名的鸢尾花数据集分类问题生成了一个机器学习模型(此处可用)。这个问题使用以厘米为单位的花的四列测量值(萼片长度、萼片宽度、花瓣长度、花瓣宽度)来预测花的种类。

凯文·卡斯特尔在 Unsplash 上拍摄的照片

为了以教程的方式学习更多关于这个问题的知识,我推荐下面的文章

细流

Streamlit 是一个极简框架,可以将常规的 python 脚本转换成漂亮的 web 应用。作为一名数据科学家,你通常必须在 web 框架(如 Flask)中编写大量额外的代码,才能将机器学习模型作为应用程序进行共享。你还必须了解一些前端开发,使应用程序美丽。这就是 Streamlit 的用武之地。

Streamlit 将简单的脚本变成漂亮的 web 应用程序。(来源:streamlit.io)

使用 Streamlit,通过向常用的数据科学 python 脚本添加几行代码,您可以在几分钟内将整个脚本转换为 web 应用程序。而且看起来很美!😍

Streamlit 支持使用小部件与数据进行交互。(来源:streamlit.io)

在这个解决方案中,我们将把 iris 物种预测模型文件包装在 Streamlit 框架中,作为一个 web 应用程序与之交互。

码头集装箱

假设您构建了一个应用程序,并共享了所有项目文件,以便在另一台机器上运行该应用程序。如果你幸运的话,它会照常运行。但是大多数时候,你必须做一些调试来让应用程序工作。通常,这是因为缺少库或不兼容的库版本,或者缺少文件。

简而言之,环境与测试和正常运行应用程序的机器不同。为了解决这个问题,创造了容器。

照片由安迪李Unsplash 上拍摄

容器是一种打包应用程序及其所有依赖项(代码、库、文件、环境配置等)的方式。)集成到一个隔离的环境中,以便该应用程序可以在不同的计算环境中可靠地运行。Docker 是构建容器的工具提供者之一。Docker 容器使用 Docker 引擎运行。

我们将使用 Docker 来封装我们的应用程序,并在 Google App Engine 上运行它。

从码头文件到集装箱。(来源:作者制作)

为了将应用程序容器化,我们需要知道几个关键步骤。这一切都是从一个文档开始的。

  • Dockerfile :这是一个包含一组构建 Docker 容器映像的指令的文件。可以把这个文件想象成 docker 容器映像的蓝图。它首先指定容器的基本操作系统,然后是安装依赖项和设置应用程序环境的说明。最后,它以在容器(即隔离环境)创建并运行后运行的命令结束。
  • Docker 镜像:这是一个可执行的包,由 Docker 文件中的指令构建而成。它包括在隔离的容器环境中运行应用程序所需的一切,如 Dockerfile 文件中所指定的。它可以被看作是一个模板,Docker 容器就是从这个模板实例化的。
  • Docker 容器:它是 Docker 映像的一个实例,运行在 Docker 引擎上。

要了解更多关于 Docker 的内容,我强烈推荐这里的文章。

家政

在我们开始有趣的部分之前,这里列出了一些重要的先决条件:

  • 本文假设您已经拥有一个 GCP 账户。如果你没有,在这里注册https://cloud.google.com/可以获得一些免费积分。
  • 要从您的本地机器与您的 GCP 帐户交互,请使用此处 列出的 步骤安装 Google Cloud SDK。
  • 确保你的本地机器上安装了 Docker。没有的话,从 这里 下载。
  • 本文中的所有代码都是在 Windows 上用 Python 3.8 开发的。本文的代码和必要的文件可以在 GitHub 仓库 这里 找到。

事不宜迟,让乐趣开始吧!😀

步骤 0:在本地机器上设置虚拟环境(被认为是最佳实践)

如果您还没有这样做,请确保为您的项目使用虚拟环境。虚拟环境有助于将项目隔离在自包含的环境中,封装其所有依赖关系,并避免与同一系统上的其他项目发生依赖关系冲突。

它捕获了重新创建项目环境所需的所有信息(依赖项及其版本的列表),这些信息可以在一个文件中共享(例如 requirements.txt )。

python 流行的虚拟环境管理器有 venvvirtualenvpipenvconda 。本文使用 conda,它与 Anaconda 数据科学工具包发行版打包在一起,我强烈推荐它。

在您的本地机器上,使用终端中的conda create --name **<env_name>** 为您的项目创建一个新的虚拟环境。

使用 Conda 创建虚拟环境(iris-stapp-env)

创建后,您可以使用conda activate **<env_name>** 激活环境。请注意,激活的环境的名称显示在左侧,在当前工作目录的路径之前。

激活 Conda 中的虚拟环境(iris-stapp-env)

要在这个隔离的环境中为一个项目安装 Python 包,可以使用常用的 pip 包(即使用命令pip install)。但是首先,确保通过运行conda install pip在激活的虚拟环境中安装 pip 包。

你也可以点击下载所有 conda 命令的备忘单。😃

重要旁注

如果您使用 Anaconda 安装的默认推荐设置安装了 conda,您的终端将无法识别命令 *conda* 。这是因为在推荐的安装设置中,Anaconda3 没有添加到 PATH 环境变量中。

相反,在你的开始菜单中搜索 Anaconda3 提示符,并使用它来确保 *conda* 被识别为命令。

使用 Anaconda 提示符运行 conda 命令

通过运行激活脚本 ***<anaconda3_install_dir>****/Scripts/activate* ,您还可以在普通终端中激活 anaconda 环境。

在现有的命令终端中激活 anaconda 环境

步骤 1:下载并运行示例 Streamlit 应用程序

为项目创建一个文件夹,并从存储库这里下载本文的代码文件。

然后使用终端(cd **<path_to_dir>**)导航到该目录,并确保虚拟环境处于活动状态(conda activate **<env_name>**)。

导航到项目目录并激活虚拟环境

显然,您可以使用自己喜欢的 IDE 来做同样的事情。但是一定要激活一个虚拟环境(点击这里获取 VS 代码)。否则,您将最终在您的默认环境中安装依赖项,这可能会中断使用该环境的其他项目。

现在我们来看看 Streamlit 的 app 文件(app.py)。

Streamlit app 文件(app.py)的 GitHub 要诀。

注意如何通过添加一个简单的导入(import streamlit as st),一个常规的数据科学脚本(带有pandas, numpy, model.predict(), etc.)在一个 Streamlit web 应用程序中被转换。我们所做的就是添加 Streamlit 小部件来与模型交互,比如文本输入小部件、按钮小部件等。

您可以尝试使用streamlit run app.py在新创建的虚拟环境中运行示例 Streamlit 应用程序。

由于虚拟环境中缺少 python 模块,这将导致错误。你可以使用pip install一个接一个地安装缺失的模块,直到应用最终运行。

虚拟环境中未安装 Streamlit。

或者,您可以通过使用 requirements.txt 中的依赖项列表来安装应用程序的所有依赖项,这将复制我创建和测试应用程序的环境。

使用命令pip install -r requirements.txt将所有项目依赖项安装到虚拟环境中。

在 conda 虚拟环境中安装 pip 模块。

一旦完成,您可以通过运行pip freeze > requirements.txt为您自己的项目创建一个这样的依赖列表。

请给模块安装一些时间。完成后,您可以使用streamlit run app.py命令在虚拟环境中运行 Streamlit 应用程序。

在本地主机上运行的 Streamlit 应用服务器,端口 8051。

在本地主机上运行的鸢尾花种预测 Streamlit 应用程序:8051

您应该看到您的默认浏览器弹出并显示应用程序(在本地主机上,默认情况下通常是端口 8051)。请随意摆弄这些数字,看看模型是如何工作的。

恭喜你,你已经在几分钟内构建了一个与机器学习模型交互的 web 应用程序!😄

当您玩完 Streamlit 应用程序后,您可以在终端中使用 Ctrl + C 关闭应用服务器。

步骤 2:对应用程序进行 Dockerize 并在本地测试

我们现在将开始 Docker 化这个应用程序,作为一个容器在任何带有 Docker 引擎的机器上运行。为此,我们需要首先根据当前目录下 Docker 文件中的指令构建一个 Docker 映像。这些指令规定了如何构建容器。

Dockerfile 文件概述

Streamlit 应用程序的 Dockerfile。

文档中的说明非常直接。

  • FROM python:3.8:我们首先将基本操作系统映像设置为安装了 Python 3.8 的 Linux 操作系统。
  • WORKDIR /app:在容器中创建一个工作目录。
  • COPY . /app:将当前项目目录下的所有文件复制到容器工作目录下。
  • RUN pip install -r requirements.txt:运行常规命令,在容器环境中安装应用程序的所有依赖项。
  • EXPOSE 8080:指示容器环境公开容器的端口 8080,让全世界监听。
  • CMD streamlit run app.py --server.port=8080:一旦设置好容器,该命令将在容器环境中执行。请注意,这是启动 Streamlit 应用程序的常用命令。我们只添加了一个额外的标志来指示 Streamlit 服务器在端口 8080 上运行。

构建 Docker 映像

虚拟环境激活后,为 docker 映像选择一个合适的名称,并在终端中运行docker build -t **<docker_image_name> .** ,从 docker 文件构建一个 docker 映像。

命令末尾的**dot(.)**指示 Docker 在当前目录中查找 Docker 文件。构建过程可能需要一些时间。注意它是如何执行 Dockerfile 文件中的每条指令的。

正在构建的应用程序的 Docker 图像。

运行容器

一旦映像构建完成,您就可以使用docker run -p 8080:8080 **<docker_image_name>** 从映像中将应用程序作为容器运行。

这个命令告诉 Docker 引擎运行 Docker 映像,并将本地机器的端口 8080 映射到容器端口 8080。这将允许我们在浏览器上导航到 http://localhost:8080/ ,以查看容器(即 Streamlit 应用程序)的输出。

在 Docker 容器中运行的 Streamlit 应用程序。

一旦您看到应用程序从容器中运行,您就可以确定该应用程序将在任何其他具有 Docker 引擎的机器上运行,不会出现任何问题。我们终于准备好将应用部署到应用引擎了!👌

重要旁注

Docker 容器运行后打印在终端中的 URL 链接,如果您点击它们,将不起作用。这些是来自 Streamlit 服务器的输出消息,在容器本身内部。

我们只能访问容器向我们公开的内容,这些内容映射到我们本地机器的http://localhost:8080/

第三步:将应用部署到谷歌应用引擎

在将 app 部署到 app engine 之前,我们需要在项目目录中添加另一个文件: app.yaml. 这是一个配置文件,基本上包含了 App Engine 的设置。

为了这篇文章的简单,我们保持了它的基本性。你可以从指南这里了解更多关于使用该文件配置应用引擎的信息。

现在,您可以使用命令gcloud app deploy从项目目录中的虚拟环境部署应用程序。

将 Streamlit 应用部署到 Google 应用引擎。

它应该要求部署应用程序的一些基本设置。按照提示进行操作,部署应该会开始。这可能需要一些时间,而且有充分的理由。

App engine 获取当前目录中的所有文件,并将其推送到云端。然后,根据 docker 文件中的说明,它在云中构建应用程序的 docker 映像,并将其存储在 Google 容器注册表中。然后,它使用这个映像在 App Engine 上部署一个容器(这个映像的运行实例)。

部署完成后,您可以使用目标 url 看到该应用程序在互联网上运行。

简化从 Google App Engine 上的 Docker 容器运行的应用程序

重要旁注

如果您这样做是为了学习,请确保在 GCP 控制台 App 引擎仪表盘中停止运行该应用。

**此外,分享应用程序的 URL 时要小心。否则,你可能会因其他人访问你的应用程序而招致不必要的费用!现在你知道为什么截图里模糊的线条了。😅

显示正在运行的应用程序版本的 GCP 控制台应用程序引擎仪表板。

结论

恭喜你!!您现在知道如何在 GCP 上将您的模型部署为无服务器应用程序。😄

要了解如何将机器学习模型部署为无服务器端点,请查看我的文章 这里 😄

使用谷歌云功能作为无服务器端点的机器学习模型

原文:https://towardsdatascience.com/machine-learning-model-as-a-serverless-endpoint-using-google-cloud-function-a5ad1080a59e?source=collection_archive---------9-----------------------

无服务器机器学习

因此,你已经建立了一个模型,并希望将其生产为谷歌云平台(GCP)上的无服务器解决方案。让我告诉你如何使用谷歌云功能做到这一点!

约书亚·阿拉贡在 Unsplash 上拍摄的照片

谷歌云功能是什么?

Google Cloud Functions 是一款无服务器的计算产品,它允许你编写当附属事件被触发时被触发的函数。由于这是一项无服务器服务,我们不必担心设置或管理服务器或任何基础设施。这种产品也被称为功能即服务(FaaS)。

照片由左 eris kallergisUnsplash 上拍摄

它的成本效益很高,因为它只在附属于它的事件被触发时运行,并在函数执行后终止。此外,资源会根据事件的频率自动扩展。因此,无需做任何进一步的工作,它就可以相应地伸缩来处理事件,从一天几次调用到数百万次调用。

在我们的例子中,我们将使用 GCP 提供的这种无服务器解决方案,为我们的机器学习模型预测提供服务,以响应 HTTP 请求事件。

简单地说,我们将把我们的模型部署为一个函数,它通过 HTTP 端点响应模型预测请求。

家政

本文假设你已经有了一个 GCP 账户。如果你还没有,在这里注册https://cloud.google.com/可以获得一些免费积分。

如果你想从你的本地机器上与你的 GCP 账户进行交互,使用 这里 列出的步骤安装 Google Cloud SDK。

本文中的所有代码都是用 Python 3.8 开发的。本文的代码和必要的文件可以在 GitHub 仓库 这里 找到。

解决方案架构:作为无服务器 HTTP 端点的模型

在我们继续之前,让我们看一下无服务器机器学习预测 HTTP 端点的解决方案的架构。

使用谷歌云功能的无服务器机器学习模型 HTTP 端点

在这个架构中,机器学习模型文件存储在一个谷歌云存储桶中。我们的云函数执行以下操作,以响应模型预测的 HTTP 请求:

  • 从云存储中下载模型文件。
  • 基于通过 HTTP 事件发送的参数运行预测。
  • 返回预测结果。

好吧!事不宜迟,让我们开始吧!

第 0 步:构建&保存你的模型(如果你还没有的话)

要继续,我们首先需要一个机器学习模型。如果您已经为您的问题保存了一个模型,您可以跳到下一步。

照片由本·马特Unsplash 拍摄

出于本文的目的,我已经为著名的 iris flowers 数据集分类问题生成了一个机器学习模型(此处可用)。这个问题使用以厘米为单位的花的四列测量值(萼片长度、萼片宽度、花瓣长度、花瓣宽度)来预测花的种类。

为了以教程的方式学习更多关于这个问题的知识,我推荐下面的网站

步骤 1:将模型上传到 Google 云存储桶

在谷歌云平台控制台上搜索存储

在 GCP 控制台中,搜索存储找到云存储,然后单击创建存储桶。给 bucket 一个合适的名称,并确保在计划运行云功能的同一区域创建 bucket。您可以保留其余的设置,然后点击创建。

创建云存储桶来存储模型

创建存储桶后,您可以通过拖放或使用 upload 按钮将模型文件上传到存储桶中。

ML 模型上传到 Google 存储桶

如果您已经安装了 Cloud SDK,那么您还可以使用命令行/终端来创建 bucket 并上传模型。参考此处的命令从命令行与您的云存储交互

步骤 2:创建和配置云功能

现在在 GCP 控制台上搜索云函数,点击创建函数。给云函数一个合适的名称,并确保它与模型存储桶在同一个区域。将函数触发器类型选择为 HTTP。

创建云函数为模型预测服务

为简单起见,将身份验证设置为允许未经身份验证的调用。在现实世界的解决方案中,它必须设置为要求认证,这将允许您使用云 IAM 控制对此功能的访问。

其余的变量可以保持原样。我们的功能非常简单,模型文件也很小。因此,一个 256 MiB 的执行环境对于我们的目的来说已经足够了。

步骤 3:编写云函数代码

从前一个设置中单击 next 后,您将能够看到内联源代码编辑器窗口。这是我们定义运行时环境和编写要执行的函数的地方。选择 python 3.8 作为运行时环境,因为我们将使用 python 进行编码。

编码模型预测云函数

请注意,源代码内联编辑器下面显示了两个文件:

  • main.py :功能代码驻留的主文件,在触发事件发生时执行。
  • requirements.txt :这是我们声明需要安装在环境中以执行我们的功能的库的地方。

你可以从资源库复制粘贴这两个文件的内容到这里或者下面的要点。

无服务器模式预测 HTTP 端点的 Google 云函数文件要点

main.py 文件中有两个函数:

  • 下载 _ 模型 _ 文件
  • iris_predict

****download _ model _ file函数将模型从指定的云存储桶中检索到云函数环境中。注意,在云函数环境下,我们只能写到 /tmp 目录。因此,模型被下载并保存在这个目录中。

iris_predict 函数是响应 HTTP 请求的主入口点函数。如果模型在内存中不可用,它将调用下载模型函数,如果 HTTP 请求发送了特性 JSON 输入,它将运行预测。确保将入口点输入框更新为 iris_predict

请注意 model 全局变量是如何用于在内存中缓存模型的。在第一次函数调用期间,将从 GCS 检索模型文件,并通过 pickle 加载。因此,后续调用的响应时间会更快,因为模型已经在内存中了。

步骤 4:部署云功能

云功能已部署并处于活动状态

一旦源文件被更新,启动部署过程,这将从需求文件安装库并设置云功能。这可能需要一些时间,您会在函数名旁边看到一个加载圆。

一旦设置完成且功能部署成功,功能名称旁边将出现一个绿色对勾。

步骤 4:测试无服务器机器学习模型预测

您现在可以通过点击函数名并选择测试选项卡来测试您的函数。在这个选项卡中,您可以通过发送一个 JSON 特性输入来触发云功能,如 so {"features":[2,3,4,5]}

该函数将使用模型预测进行响应,该预测将出现在输出部分。您也可以从触发标签中获取模型触发 URL,该 URL 可以被其他服务使用。

虹膜模型的无服务器机器学习模型预测

注意,cloud 函数中没有代码来对发送的 JSON 进行健全性检查。因此,如果 JSON 无效或者 features 键的值不是预期的格式,当前函数将生成一个错误。

目前,我们在函数中做的唯一检查是,如果 features 键在 JSON 请求中不存在,就用一条消息进行响应。

JSON 请求缺少 features 键时的云函数响应

在现实世界的应用程序中,进行检查以验证 JSON 及其内容是非常重要的。为了简化本文,已经避免了它们。

结论

恭喜你!!现在,您已经知道如何在 GCP 上将您的模型部署为无服务器功能。😄

机器学习模型仪表板

原文:https://towardsdatascience.com/machine-learning-model-dashboard-4544daa50848?source=collection_archive---------7-----------------------

创建仪表板来解释机器学习模型

如今,创建机器学习模型很容易,因为市场上有不同的 python 库,如 sklearn、lazypredict 等。这些库易于使用,用于创建不同类型的模型以及不同类型的可视化,并找出模型的性能。如果你不知道懒惰预测是如何工作的,看看下面给出的文章。

现在的主要挑战是模型不容易解释,这使得非技术人员很难理解和解释逻辑以及模型如何工作。

Explainer dashboard 是一个开源的 python 库,它创建了机器学习模型仪表板,可用于轻松理解和分析模型工作的重要因素,如特征重要性、模型性能、可视化等。

你可以通过我的 Youtube 频道来看看 Explainer Dashboard 和更多的 Python 库。订阅更多这样的视频。

在本文中,我们将使用 explainer 仪表板来创建机器学习仪表板,并了解模型是如何工作的。

让我们开始吧…

安装所需的库

我们将从使用 pip 安装一个解释器仪表板开始。下面给出的命令可以做到这一点。

pip install explainerdashboard

导入所需的库

在这一步中,我们将导入所需的库和函数来创建机器学习模型和仪表板。

from sklearn.ensemble import RandomForestClassifier
from explainerdashboard import ClassifierExplainer, ExplainerDashboard
from explainerdashboard.datasets import titanic_survive, titanic_names

创建模型和仪表板

这是最后一步,我们将创建机器学习模型,然后通过创建仪表板来解释该模型。

  1. 创建模型
feature_descriptions = {
    "Sex": "Gender of passenger",
    "Gender": "Gender of passenger",
    "Deck": "The deck the passenger had their cabin on",
    "PassengerClass": "The class of the ticket: 1st, 2nd or 3rd class",
    "Fare": "The amount of money people paid", 
    "Embarked": "the port where the passenger boarded the Titanic. Either Southampton, Cherbourg or Queenstown",
    "Age": "Age of the passenger",
    "No_of_siblings_plus_spouses_on_board": "The sum of the number of siblings plus the number of spouses on board",
    "No_of_parents_plus_children_on_board" : "The sum of the number of parents plus the number of children on board",
}X_train, y_train, X_test, y_test = titanic_survive()
train_names, test_names = titanic_names()
model = RandomForestClassifier(n_estimators=50, max_depth=5)
model.fit(X_train, y_train)

2.创建仪表板

from sklearn.ensemble import RandomForestClassifier
from explainerdashboard import ClassifierExplainer, ExplainerDashboard
from explainerdashboard.datasets import titanic_survive, titanic_namesfeature_descriptions = {
    "Sex": "Gender of passenger",
    "Gender": "Gender of passenger",
    "Deck": "The deck the passenger had their cabin on",
    "PassengerClass": "The class of the ticket: 1st, 2nd or 3rd class",
    "Fare": "The amount of money people paid", 
    "Embarked": "the port where the passenger boarded the Titanic. Either Southampton, Cherbourg or Queenstown",
    "Age": "Age of the passenger",
    "No_of_siblings_plus_spouses_on_board": "The sum of the number of siblings plus the number of spouses on board",
    "No_of_parents_plus_children_on_board" : "The sum of the number of parents plus the number of children on board",
}X_train, y_train, X_test, y_test = titanic_survive()
train_names, test_names = titanic_names()
model = RandomForestClassifier(n_estimators=50, max_depth=5)
model.fit(X_train, y_train)explainer = ClassifierExplainer(model, X_test, y_test, 
                                cats=['Deck', 'Embarked',
                                    {'Gender': ['Sex_male', 'Sex_female', 'Sex_nan']}],
                                cats_notencoded={'Embarked': 'Stowaway'}, 
                                descriptions=feature_descriptions,
                                labels=['Not survived', 'Survived'], 
                                idxs = test_names, 
                                index_name = "Passenger", 
                                target = "Survival", 
                                )db = ExplainerDashboard(explainer, 
                        title="Titanic Explainer", 
                        shap_interaction=False,
                        )
db.run(port=8050)

在下面的视频中,我展示了使用 explainer 仪表盘创建的仪表盘。

仪表板(来源:作者)

仪表板主页(来源:作者)

仪表板(来源:作者

在这里,您可以清楚地看到使用 explainer 仪表板创建的仪表板。我们可以清楚地分析模型和其他参数的不同性质。

继续尝试不同的数据集,并创建漂亮的仪表板来解释模型。如果您发现任何困难,请在回复部分告诉我。

本文是与 Piyush Ingale 合作完成的。

在你走之前

感谢 的阅读!如果你想与我取得联系,请随时在 hmix13@gmail.com 上联系我或我的 LinkedIn 个人资料 。可以查看我的Github*简介针对不同的数据科学项目和包教程。还有,随意探索* 我的简介 ,阅读我写过的与数据科学相关的不同文章。

机器学习模型部署—一个简单的清单

原文:https://towardsdatascience.com/machine-learning-model-deployment-a-simplistic-checklist-dc5558a88d1b?source=collection_archive---------15-----------------------

在将您的机器学习模型部署到生产之前、之中和之后需要检查的必要事项

亚历克斯·丘马克在 Unsplash 上的照片

将您的机器学习模型从研究环境转移到生产环境时,可能会出现许多问题。数据科学家/ML 工程师经常低估打破 ML 模型并使结果不可再现的容易程度

目标受众:

  • 数据科学家希望确保他们的代码/模型可以在没有任何可能使模型结果不可复制的情况下被容易地部署
  • 当在环境/平台之间移动模型时,想要快速列出可能出错的事情的机器学习工程师

这些检查最好按顺序进行,以确认上一个场景的问题不会延续到下一步

为了方便起见要记住的关键字:

记住潜在问题的简单关键词。作者图片

场景— 1:

数据不可再现性

  • 机器学习模型对数据进行处理。如果基础数据与研究环境不同,模型就不可能产生相同的结果
  • 你可能认为这是常识。但实际上,数据科学家和 ML 工程师经常忽视的一个被低估的问题(我也有同感)是底层数据的微小变化及其对模型推断的假设的影响
  • 在预处理/工程之前进入系统的基础原始数据必须与研究环境相匹配。再多的特征工程也无法弥补不正确/不可复制的原始数据
  • 从事大数据工作的人通常会觉得说不可能匹配如此大量的数据很方便。不可能逐行匹配。但是,为了进行合理的比较,必须制定一套统计措施
  • 应该比较将数据加载到环境中的 ETL 过程,并且必须检查该过程的每个输出。在进行大型聚合时,不要忽略精度及其影响
  • 检查在向环境传输数据的过程中是否有潜在的数据包/数据丢失
  • 如果有多个数据源向模型提供数据,那么必须对每个数据源进行检查

场景— 2:

特征工程步骤的不同结果

  • 一旦您确认原始数据是可再现的,下一步将是检查特征工程后的再现性
  • 一个常见的错误是在使用涉及数据采样的特征工程时没有设置种子
  • 检查预处理逻辑不匹配(空值、nan、极值等的处理)。)、聚合不匹配、数据精度
  • 检查两种环境中的 Python 版本和基础库版本,以及库中的默认值是否已更改
  • 与上一步类似,使用统计方法/KPI 来比较环境之间的工程/处理数据

场景— 3:

不同的列车试运行

  • 不可复制的分裂的恐怖是无限的。在将数据加载到任何 ML 模型之前,我们将数据分成训练、验证和测试数据集。有必要确保这些数据集在环境内部和环境之间是可复制的
  • 最常见的情况是,数据科学家在进行分割时忘记设定种子
  • 如果您正在进行交叉验证,在重复的 KFold、ShuffleSplit、GroupShuffleSplit 的情况下设置种子尤其重要
  • 如果您使用 RDBMS,请确保维护了正确的数据顺序,并确保设置了排序或保持数据顺序的逻辑

场景— 4:

预测不匹配

如果模型生成 NaNs 或 infinite 作为预测:

  • 环境数据可能包含代码中未处理的空数据
  • 数据(尤其是测试或流数据)可能包含以前未观察到的类别
  • 流式传输/测试时出现错误数据

这些问题可以通过在代码中涵盖这些场景来解决。尽管在数据和处理上可能需要 SME 的输入

如果模型预测不匹配或部分匹配:

  • 在研究/生产环境中,没有为底层算法或采样设置种子
  • 不同的 Python 或库版本可能会修改算法处理数据的方式

场景— 5:

性能低于预期:

  • 由于 KPI 和期望值在某些情况下会快速变化,因此当您的模型投入生产时,您的模型可能无法满足期望值
  • 我们应该进行检查,以确保训练和实时预测之间的分布差异不大。对于一些用例,数据和概念漂移可能会随着时间的推移而迅速发展
  • 在监督学习的情况下,我们还必须检查目标是否仍然是对结果的真实期望。如果目标不可靠或随时间变化,模型性能也会随时间恶化/变得不可靠

情景— 6:

可变不可用性或非频繁特性

  • 在现实生活中,变量经常会过时和被替换。我们可以尝试用最相似的变量替换它,或者删除该变量,重新训练并重新评估模型性能
  • 变量本质上也可以是非频繁的。我们应该确认,如果某个特定值长时间没有到达,它不会严重影响机器学习模型做出的推断

这些是数据科学家和机器学习工程师在开发模型并将其部署到生产中时实际观察到的最常见的场景,也是他们经常忽略的场景。部署和维护 ML 模型与开发它们一样困难(如果不是更困难的话)。希望这篇简短的文章能帮助你避免职场中常见的陷阱。有没有你觉得必须涵盖的场景?请随时发表评论。我很乐意从你的经历中学习。

机器学习模型部署选项

原文:https://towardsdatascience.com/machine-learning-model-deployment-options-47c1f3d77626?source=collection_archive---------33-----------------------

迈克尔·泽兹奇在 Unsplash 上的照片

机器学习模型部署可以分为 3 大类:

  1. 实时推理:通常它涉及在 web 服务器上作为端点托管机器学习模型。然后,应用程序可以通过 https 提供数据,并在短时间内接收回模型的预测。
  2. 批量推断:定期(由时间或事件触发,如数据进入数据湖/数据存储)启动资源,并部署机器学习模型来预测数据湖/数据存储中现在可用的新数据。
  3. 模型部署到边缘:模型预测是在边缘设备上计算的,而不是要求将输入数据传递到后端。想想物联网和网络应用。

当决定采用哪种方法将机器学习模型部署到生产中时,需要考虑几个因素。

  1. 延迟:应用程序/用户需要多快得到模型预测的结果?
  2. 数据隐私:向后端发送数据有什么问题/顾虑吗?
  3. 网络连接:某些部署选项需要访问互联网/网络。如果需要部署模型的环境具有有限的或没有互联网/网络连接,则选项是有限的。
  4. 成本:某些部署选项比其他选项成本更高。想象一下,拥有一台全天候在线的服务器来提供预测服务。运行和维护该服务器的成本是多少?

潜伏期

假设您已经创建了一个 web/mobile 应用程序,它提供了一个机器学习服务,可以根据用户的输入进行预测。如果用户能够在提供一些输入后立即获得模型的结果,而不是等待几个小时,或者直到他们收到模型最终对他们的输入做出预测的通知,这将是更好的用户体验。在这种特定情况下,将机器学习模型部署到实时推理管道/边缘部署中会更理想。

另一方面,如果机器学习模型正被用于丰富作为数据管道的一部分的一些数据,并且数据不需要立即可用,也许新数据每天仅到达一次,则使用批量推理管道来预测新输入数据可能更具成本效益。

数据隐私

当将模型部署到实时推理或批量推理管道时,输入数据将需要传输到后端,并且通常会在由机器学习模型的创建者管理的云环境中。想象一下,提供的数据有可能成为个人身份信息,或者有人担心数据将存储在哪个国家。如果存在任何数据隐私问题,使用这种方法可能是不可行的。

解决这个问题的一种方法是将模型部署到边缘设备中。这要求边缘设备具有足够的计算能力来实际托管模型,并进行对边缘处的输入数据进行预测所需的计算。部署到边缘设备的缺点是,通常计算资源的数量是一个限制,因此模型架构的选择可能需要更加简单,以便节省资源,这可能导致模型预测能力的性能下降。

网络连接

将模型部署到实时推理或批量推理管道通常需要某种形式的网络连接,能够将输入数据从源传输到后端。如果输入数据源的网络连接有限/没有网络连接,这可能意味着为了解决业务用例,模型需要部署在离数据源更近的地方。

成本

某些部署方法会导致不同的成本计算。当部署到实时推理管道时,您需要端点全天候可用。此外,您可能需要在高负载期间扩大计算资源,在低负载期间缩小计算资源。这种扩大和缩小的管理可能还需要一个团队来管理实时推理管道。

批处理推理管道通常更便宜,因为您只需要在预测新的一批数据所需的时间内加速资源。根据数据量和模型对数据进行预测的速度,您可以确定想要利用的资源量(节点数量和节点类型)(有关使用 AWS 的批处理推理管道的示例,请查看我之前写的这篇文章:https://towards data science . com/AWS-sagemaker-batch-transform-design-pattern-fa1d 60618 fa 8)。

就运营成本而言,边缘部署可能是最便宜的选择,因为您正在利用边缘设备的资源。成本可能更加间接。这包括将预测能力低于其他模型的劣质模型部署到生产中的潜在成本、管理将模型部署到一组边缘设备的成本、评估模型在边缘设备上的性能的成本(您如何在边缘设备上收集和跟踪一段时间内的推断?).

AWS 中的机器学习部署选项

  1. 实时推理:https://docs . AWS . Amazon . com/sage maker/latest/DG/inference-pipeline-real-time . html
  2. 批量推断:https://docs . AWS . Amazon . com/sage maker/latest/DG/inference-pipeline-batch . html
  3. 边缘部署:可能需要使用 SageMaker Neo:https://docs . AWS . Amazon . com/SageMaker/latest/DG/Neo-Edge-devices . html或使用 green grass:https://docs . AWS . Amazon . com/green grass/v1/developer guide/what-is-gg . html进行交叉编译和/或使用 SageMaker 边缘管理器进行模型管理:https://docs.aws.amazon.com/sagemaker/latest/dg/edge.html

Azure 中的机器学习部署选项

  1. 实时推理:https://docs . Microsoft . com/en-us/azure/machine-learning/how-to-deploy-and-where?tabs=azcli
  2. 批量推断:https://docs . Microsoft . com/en-us/azure/machine-learning/tutorial-pipeline-batch-scoring-class ification
  3. Edge 部署(截至 2021 年 4 月 12 日预览版):https://docs . Microsoft . com/en-us/azure/IOT-edge/tutorial-deploy-machine-learning?view=iotedge-2020-11

使用 MLflow 和 Scikit-learn 管道开发和部署机器学习模型

原文:https://towardsdatascience.com/machine-learning-model-development-and-deployment-with-mlflow-and-scikit-learn-pipelines-f658c39e4d58?source=collection_archive---------20-----------------------

从 Python 模型创建 API 部署

维多利亚时代转换汽油吊灯-作者图片

维多利亚式汽油器是一个工业天然气管道的例子,它的终端是一个优雅的固定装置。同样,我们的机器学习管道需要功能性,与其他系统兼容,对开发者和用户都有吸引力。这篇文章包含一个使用 Scikit-learn 管道和 MLflow 部署的 python 机器学习模型开发的示例。这些步骤包括:

  • 利用定制变压器的 Scikit-learn 管道
  • 将模型和定制变压器代码输出到 MLflow 跟踪服务器
  • 使用 ML 项目将模型代码链接到结果
  • 通过 REST-API 从 MLflow 跟踪服务器提供模型

为什么要使用这种方法?这种方法的组合消除了对额外的模型服务逻辑的需要,允许对原始模型开发代码的可追溯性,结合了基于领域知识的行业标准和定制代码,并允许简单的模型部署。

人工智能需要根据您的业务环境进行定制。你不能下载一个开源包,然后把它应用到你的问题上。—吴恩达

通过将领域知识与可重用的代码库相结合,我们可以利用开源解决方案来解决类似的问题,并构建定制的系统。

管道

管道有许多优点。

  • 确保测试和训练数据之间没有信息泄漏
  • 将带有预处理步骤的模型捆绑到单个序列化对象中,而不是多个步骤和输出
  • 允许在开发和部署期间运行相同的数据准备步骤

Scikit-learn 管道还兼容其他建模包,如 Keras 和 XGBoost。

对于这个管道,我们将从加州大学欧文分校机器学习库导入克利夫兰诊所心脏病数据集。Kaggle 上也有一个非常相似的数据集。与实验室和生理测试相关的功能包括:

  • 患者年龄
  • 患者性别
  • CP——胸痛类型
  • trest bps——静息血压
  • 胆固醇——血清胆固醇
  • FBS —空腹血糖
  • 静息心电图—静息心电图结果
  • thal ach——最大心率
  • 运动诱发的心绞痛
  • 运动诱发的 old peak-ST 段压低
  • 斜率——峰值运动 ST 段的斜率
  • CA——用荧光显微镜着色的主要血管的数量
  • Thal —缺陷类型
  • num——心脏病诊断

让我们读入数据,设置我们的目标变量,并查看数据。

import numpy as np
import pandas as pd
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
from sklearn.impute import SimpleImputer
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, precision_score, recall_scoreimport mlflow
import mlflow.sklearn
from mlflow.models.signature import infer_signatureURL = 'https://archive.ics.uci.edu/ml/machine-learning-databases/heart-disease/processed.cleveland.data'df = pd.read_csv(URL, header=None, names=['age','sex','cp','trestbps','chol','fbs','restecg','thalach'
,'exang','oldpeak','slope','ca','thal','num'])df['target']=np.where(df['num'] > 0,1,0)df.head()

为了演示自定义变压器的使用,我们将根据静息血压与最大血压的比率创建一个新功能。此功能将被创建为一个新类并保存到一个单独的文件中,因此它可以输出到 MLflow tracking 服务器,以便在部署过程中与保存的模型结合使用。

import pandas as pd
from sklearn.base import BaseEstimator, TransformerMixin#Custom Transformer Class
class NewFeatureTransformer(BaseEstimator, TransformerMixin):
     def fit(self, x, y=None):
          return self def transform(self, x):
          x['ratio'] = x['thalach']/x['trestbps']
          x=pd.DataFrame(x.loc[:, 'ratio'])
          return x.values

现在,让我们将数据分成训练、验证和测试数据集。

train, test = train_test_split(df, test_size=0.2)
train, val = train_test_split(train, test_size=0.2)print(len(train), 'Train Examples')
print(len(val), 'Validation Examples')
print(len(test), 'Test Examples')

我们现在准备导入我们的自定义类并定义管道。

from custom_class import NewFeatureTransformer#Define the Pipelinenumeric_features = ['age','trestbps','chol','thalach','oldpeak']
numeric_transformer = Pipeline(steps=[
     ('imputer', SimpleImputer(strategy='median')),
     ('scaler', StandardScaler())])categorical_features = [ 'cp','restecg','ca','thal','slope']
categorical_transformer = Pipeline(steps=[ 
     ('imputer', SimpleImputer(strategy='constant',fill_value=0)),
     ('onehot', OneHotEncoder(handle_unknown='ignore'))])binary_features = [ 'sex','fbs','exang']
binary_transformer = Pipeline(steps=[
     ('imputer',SimpleImputer(strategy='constant',fill_value=0))])new_features_input =  [ 'thalach','trestbps']
new_transformer = Pipeline(steps=[
     ('new', NewFeatureTransformer())])preprocessor = ColumnTransformer(
     transformers=[
          ('num', numeric_transformer, numeric_features),
          ('cat', categorical_transformer, categorical_features),
          ('binary', binary_transformer, binary_features),
          ('new', new_transformer, new_features_input)])# Now join together the preprocessing with the classifier.clf = Pipeline(steps=[('preprocessor', preprocessor),
     ('classifier', LogisticRegression())], verbose=True)#fit the pipeline
clf.fit(train, train['target'].values)#create predictions for validation data
y_pred = clf.predict(val)

现在我们有了管道,下一步是将结果模型保存到 MLflow 跟踪服务器。

MLflow

MLflow 项目是一种与框架无关的模型跟踪和部署方法,最初由 Databricks 于 2018 年 7 月作为开源发布。截至 2020 年 7 月,MLflow 现在是 Linux 基金会的成员。也可以通过 Seldon 将保存在 MLflow 跟踪服务器上的模型部署到 Kubernetes 中。这允许将 MLflow 的模型跟踪功能与 Seldon 的扩展部署功能结合使用。

尽管 MLflow 对模型有一种 scikit-learn 的“风格”,但是由于使用了定制的转换器,我们将需要使用通用的“python 函数风格”。将 MLflow 与 scikit-learn 管道结合使用允许我们将模型定义和所有预处理步骤和转换保存到一个对象中,再加上我们的自定义转换器代码。首先设置模型输出类和将来执行模型所需的 conda 环境。

class ModelOut (mlflow.pyfunc.PythonModel):
     def __init__(self, model):
          self.model = model def predict (self, context, model_input):
          model_input.columns= map(str.lower,model_input.columns)
          return self.model.predict_proba(model_input)[:,1]mlflow_conda={'channels': ['defaults'],
     'name':'conda',
     'dependencies': [ 'python=3.6', 'pip',
     {'pip':['mlflow','scikit-learn','cloudpickle','pandas','numpy']}]}

接下来,我们将向跟踪服务器输出模型和一些指标。

with mlflow.start_run():
     #log metrics
     mlflow.log_metric("accuracy", accuracy_score( val['target'].values, y_pred))
     mlflow.log_metric("precison", precision_score( val['target'].values, y_pred))
     mlflow.log_metric("recall", recall_score( val['target'].values, y_pred)) # log model
     mlflow.pyfunc.log_model(   artifact_path="model",
          python_model=ModelOut(model=clf,),
          code_path=['custom_class.py'],
          conda_env=mlflow_conda)
     signature = infer_signature(val, y_pred) #print out the active run ID
     run = mlflow.active_run()
     print("Active run_id: {}".format(run.info.run_id))

使用 MLflow 项目执行

使用 MLflow 项目和 Github,保存到跟踪服务器的模型可以链接到 Github 代码。也可以使用 MLproject 文件在本地执行。下面是一个非常简单的 MLproject 文件的示例。

name: heartdisease_pipeline_with_mlflowconda_env: disease_conda.yamlentry_points:
     main:
          command: 'python pipeline_with_mlflow.py'

我们可以基于 conda.yaml 文件执行这个命令来设置一个新的 conda 环境,或者使用-no-conda 选项来执行。

现在,我们可以在包含 MLflow 的激活环境的 anaconda 提示符下执行mlflow ui,查看 MLflow 跟踪服务器中 run_id 的详细信息。我们在http:\\localhost:5000找到跟踪服务器

模型服务

该模型现在可以从 Anaconda 提示符下提供服务。

mlflow models serve -m file:C:\Users\Elizabeth\Documents\GitHub\EO\mlruns\0\4c5e296e18174521a470891251eed5ea\artifacts\model\

在构建并激活 conda 环境之后,您将会得到一条消息,表明该模型正在为 http://localhost:5000 服务。我们现在可以向模型提供数据并接收预测。我们将在这里使用 python 来演示,但是也可以调用这个 API 来对来自流的数据进行评分。

import requests
host = 'localhost'
port = '5000'url = f'http://{host}:{port}/invocations'headers = {'Content-Type': 'application/json',}
# test contains our data from the original train/valid/test splithttp_data = test.to_json(orient='split')
r = requests.post(url=url, headers=headers, data=http_data)print(f'Predictions: {r.text}')

摘要

使用 Scikit-learn 管道和 MLflow 模型跟踪服务器有助于为数据科学模型编写基于 python 的生产就绪部署代码。使用这种方法,数据科学家可以从一个模型中产生一个 API,而不需要对输入数据流进行额外的 ETL。这可以促进部署,并允许软件工程师专注于基础设施和系统集成,包括持续集成和交付,而不是维护与建模相关的代码库。它还使得重新部署像在 MLFlow 跟踪服务器上引用新的 run_id 一样简单。

机器学习模型解释

原文:https://towardsdatascience.com/machine-learning-model-interpretation-47b4bc29d17f?source=collection_archive---------34-----------------------

使用 Skater 建立 ML 可视化

树(来源:作者

解释机器学习模型是一项艰巨的任务,因为我们需要了解模型在后端如何工作,模型使用的所有参数是什么,以及模型如何生成预测。我们可以使用不同的 python 库来创建机器学习模型可视化,并分析模型的工作对象。

Staker 是一个开源的 python 库,支持对不同类型的黑盒模型进行机器学习模型解释。它帮助我们创建不同类型的可视化,使我们更容易理解模型是如何工作的。

在这篇文章中,我们将探索滑板和它的不同功能。让我们开始吧…

安装所需的库

我们将从使用 pip 安装安装一个溜冰者开始。下面给出的命令将使用 pip 安装溜冰者。

!pip install -U skater

导入所需的库

下一步将是导入所需的库。要使用 Skater 解释模型,我们首先需要创建一个模型。

%matplotlib inline 
import matplotlib.pyplot 
import matplotlib.pyplot as plt 
import numpy as np 
from sklearn.model_selection 
import train_test_split from sklearn.ensemble 
import RandomForestClassifier 
from sklearn import datasets 
from sklearn import svm
from skater.core.explanations import Interpretation
from skater.model import InMemoryModel
from skater.core.global_interpretation.tree_surrogate 
import TreeSurrogate
from skater.util.dataops import show_in_notebook

创建模型

我们将创建一个随机森林分类器,并使用 IRIS 数据集。

iris = datasets.load_iris()
digits = datasets.load_digits()
X = iris.data
y = iris.target
clf = RandomForestClassifier(random_state=0, n_jobs=-1)

xtrain, xtest, ytrain, ytest = train_test_split(X,y,test_size=0.2, random_state=0) clf = clf.fit(xtrain, ytrain)y_pred=clf.predict(xtest)
prob=clf.predict_proba(xtest)from skater.core.explanations import Interpretation
from skater.model import InMemoryModelfrom skater.core.global_interpretation.tree_surrogate import TreeSurrogate
from skater.util.dataops import show_in_notebookinterpreter = Interpretation(
        training_data=xtrain, training_labels=ytrain, feature_names=iris.feature_names
    )
pyint_model = InMemoryModel(
            clf.predict_proba,
            examples=xtrain,
            target_names=iris.target_names,
            unique_values=np.unique(ytrain).tolist(),
            feature_names=iris.feature_names,
        )

创建可视化

我们将从创建不同的可视化开始,这将帮助我们分析我们创建的模型是如何工作的。

  1. 部分依赖情节

该图向我们展示了特定特征如何影响模型的预测。

interpreter.partial_dependence.plot_partial_dependence(
   ['sepal length (cm)'] , pyint_model, n_jobs=-1, progressbar=**False**, grid_resolution=30, with_variance=**True**,figsize = (10, 5)
)

PDP 剧情(来源:作者

2.特征重要性

在此图中,我们将分析我们创建的模型中的功能的重要性。

plots = interpreter.feature_importance.plot_feature_importance(pyint_model, ascending=True, progressbar=True,
                                n_jobs=-1)

功能重要性(来源:作者)

3.代理树

这是我们创建的随机森林模型的图形表示。在每一步,它都显示基尼指数值、等级等。

surrogate_explainer = interpreter.tree_surrogate(oracle=pyint_model, seed=5)
surrogate_explainer.fit(xtrain, ytrain)
surrogate_explainer.plot_global_decisions(show_img=True)

代理树(来源:作者

这就是我们如何使用 Skater 来创建不同的图表,帮助我们分析模型的表现。继续尝试不同的数据集,并让我知道您在回复部分的评论。

本文是与皮尤什·英加尔合作完成的。

在你走之前

感谢 的阅读!如果你想与我取得联系,请随时通过 hmix13@gmail.com 联系我或我的 LinkedIn 个人资料 。可以查看我的Github*简介针对不同的数据科学项目和包教程。还有,随意探索* 我的简介 ,阅读我写过的与数据科学相关的不同文章。

基于 MLflow 的面向新手的机器学习模型

原文:https://towardsdatascience.com/machine-learning-model-serving-for-newbies-with-mlflow-76f9f0ac3cb2?source=collection_archive---------10-----------------------

为您的 sklearn 模型构建一个 API 的完全可复制的、分阶段的、循序渐进的教程

保持那些模型流动!(作者画的漫画很差。)

一个机器学习中的常见问题是构建机器学习模型的数据科学家和试图将这些模型集成到工作软件中的工程师之间的笨拙交接。数据科学家所熟悉的计算环境并不总能很好地融入生产质量系统。

这个模型部署问题已经变得如此普遍,以至于围绕寻找解决方案出现了一个全新的术语和子领域——MLOps,或者将 DevOps 原则应用于将机器学习管道推向生产。

模型部署的简单方法

我最喜欢的机器学习模型部署工具是 MLflow ,它自称是“管理 ML 生命周期的开源平台,包括实验、可复制性、部署和中央模型注册。”MLflow 可以与您可能用于机器学习的几乎所有编程语言一起工作,可以在您的笔记本电脑上或云中以相同的方式轻松运行(在 Databricks 中集成了一个非常棒的托管版本),可以帮助您对模型进行版本控制(特别适合协作)并跟踪模型性能,并允许您打包几乎任何模型并提供它,以便您或任何其他人可以使用它通过 REST API 发送自己的数据来进行预测,而无需运行任何代码。

如果你觉得这听起来很酷,那是因为它确实很酷。MLflow 太酷了,做了这么多事情,以至于我花了很长时间来筛选所有的文档和教程,以弄清楚如何实际使用它。但是我做了(我想),我用 Docker 做所有的事情,所以我想我应该继续下去,在混乱中添加另一个教程。因为都是用 Docker 容器化的,所以只需要几个命令就可以让一切正常工作。

佐料

所有资料都可以在我的 GitHubml flow-tutorial repo中获得。接下来,将 repo 克隆到您的本地环境中。您可以在系统上仅运行 Docker 和 Docker Compose 来运行该示例。

这个 GitHub repo 演示了一个用 sklearn 训练分类器模型和用 mlflow 服务模型的例子。

回购有几个不同的组成部分:

方向(TLDR 版)

要使用 Docker Compose 跳过并运行所有组件,您可以使用注册表运行
整个教程:

docker compose -f docker-compose.yml up --build

或者没有注册表:

docker compose -f docker-compose-no-registry.yml up --build

该模型将在端口 1234 上提供,通过运行包含测试数据 csv 的以下脚本来访问预测:

./predict.sh test.csv

它运行以下 curl 命令,将 csv 作为输入:

curl http://localhost:1234/invocations \
-H ‘Content-Type: text/csv’ --data-binary @test.csv

并返回预测概率的数组。

方向(完整版)

第一部分将 mlflow 模型保存到本地磁盘,第二部分展示了如何使用 mlflow registry 进行模型跟踪和版本控制。

培训和服务 mlflow 模型(无注册)

[clf-train.py](https://github.com/mtpatter/mlflow-tutorial/blob/main/clf-train.py)脚本使用 sklearn 乳腺癌数据集,训练一个简单的随机森林分类器,用 mlflow 将模型保存到本地磁盘。添加用于写入输出测试数据的可选标志将首先分割训练数据以添加示例测试数据文件。

若要训练模型,请使用以下命令:

python clf-train.py clf-model --outputTestData test.csv

下面是主脚本的代码片段。最后一行将模型组件保存到本地的clf-model目录中。

通过运行以下命令为模型提供服务:

mlflow models serve -m clf-model -p 1234 -h 0.0.0.0

然后,您可以通过使用 csv 测试数据运行以下脚本来进行预测:

./predict.sh test.csv

它运行以下 curl 命令:

curl [http://localhost:1234/invocations](http://localhost:1234/invocations) \
-H ‘Content-Type: text/csv’ --data-binary @test.csv

使用 mlflow 注册表训练和服务模型

使用 mlflow 注册表可以让您做很多很酷的事情:

  • 有一个中心位置来跟踪和分享不同的实验
  • 跟踪并轻松查看模型和代码输入参数
  • 记录和查看指标(准确性、召回率等)
  • 将您的模型版本化,并比较在相同实验下记录的不同模型的性能
  • 与任何其他可以访问注册表的用户协作,在同一个实验中注册他们的模型
  • 轻松地将模型转换到不同的阶段(例如,StagingProduction),这意味着,不是引用特定编号的模型,而是将您最近喜欢的模型切换到特定的阶段,下游组件可以通过引用该阶段无缝地使用该新模型

通过运行以下脚本,首先启动 mlflow 服务器以在本地使用注册表:

./runServer.sh

它只运行以下命令:

mlflow server \
 --backend-store-uri sqlite:///mlflow.db \
 --default-artifact-root ./mlflow-artifact-root \
 --host 0.0.0.0

这将运行在您的浏览器中可见的 mlflow UI。

[clf-train-registry.py](https://github.com/mtpatter/mlflow-tutorial/blob/main/clf-train-registry.py)脚本使用 sklearn 乳腺癌数据集,训练一个简单的随机森林分类器,并将模型和指标保存并注册到指定 url 的 mlflow 注册表中。添加用于写入输出测试数据的可选标志将首先分割训练数据以添加示例测试数据文件。

若要训练模型,请使用以下命令:

python clf-train-registry.py clf-model "[http://localhost:5000](http://localhost:5000)" \
--outputTestData test.csv

下面是该脚本的一个代码片段,它将最新的模型移入阶段Staging,并将之前的模型移回None

将新转换的Staging型号服务到端口 1234:

mlflow models serve models:/clf-model/Staging -p 1234 -h 0.0.0.0

然后,您可以通过使用 csv 测试数据运行以下脚本来进行预测:

./predict.sh test.csv

它再次运行下面的 curl 命令:

curl http://localhost:1234/invocations \
-H ‘Content-Type: text/csv’ --data-binary @test.csv

就是这样!

有几点需要注意:

  • 如果您使用 Docker Compose 运行本教程,容器将访问并写入您的本地挂载目录。
  • 当通过 Python API 加载模型时,您需要确保您的环境 sklearn 版本与您用来保存它的版本相同(这就是为什么我更喜欢在 Docker 中做任何事情)。
  • 你可以用docker compose down清理运行中的容器。

希望这是生产机器学习模型的良好开端。通过替换示例培训脚本,您应该能够将本教程用于您自己的模型。

在后续的文章中,我将介绍如何构建您自己的定制 mlflow 模型,以便您可以通过 REST api 提供几乎任何您喜欢的功能。敬请期待!

机器学习模型可视化

原文:https://towardsdatascience.com/machine-learning-model-visualization-cc3b46136647?source=collection_archive---------24-----------------------

使用 Shapash 使 ML 模型可解释

卢克·切瑟在 Unsplash 上的照片

创建机器学习模型是 ml 工程师的日常任务,他们可以很容易地理解它们并解释它们以获得有用的信息,但对于不属于数据科学领域的人来说,很难理解机器学习模型及其试图表达的内容?

数据科学家可以理解模型是关于什么的,但是与其他团队成员或管理层分享结果是困难的。Shapash 是一个开源 python 库,用于创建不同类型的可视化,绕过显式标签,即使是非技术人员也能理解。它用于与最终用户共享模型的结果,最终用户可以通过可视化的方式轻松地解释和理解它们。

在本文中,我们将通过使用给定的数据集创建一个仪表板来探索 Shapash 及其特性。

让我们开始吧…

安装所需的库

我们将从使用 pip 安装 shapash 开始,您可以运行下面给出的命令来安装 shapash。

pip install shapash

导入所需的库

接下来,我们将导入所有需要的库。

import pandas as pd
from category_encoders import OrdinalEncoder
from lightgbm import LGBMClassifier
from sklearn.model_selection import train_test_split

加载数据和预处理

我们将在本文中使用的数据集是著名的 Titanic 数据集,我们将使用 shapash 加载它,之后,我们将对数据执行一些预处理。

from shapash.data.data_loader import data_loading
titanic_df, titanic_dict = data_loading('titanic')
titanic_df.head()

数据集(来源:作者)

y_df=titanic_df['Survived'].to_frame()
X_df=titanic_df[titanic_df.columns.difference(['Survived'])]# Converting categorical columns to numerical
categorical_features = [col for col in X_df.columns if X_df[col].dtype == 'object']encoder = OrdinalEncoder(
    cols=categorical_features,
    handle_unknown='ignore',
    return_df=True).fit(X_df)X_df=encoder.transform(X_df)#Splitting data into training and testing
Xtrain, Xtest, ytrain, ytest = train_test_split(X_df, y_df, train_size=0.8, random_state=1)

创建模型

对数据进行预处理后,我们将使用 LightGBM 分类器创建分类模型。

classifier = LGBMClassifier(n_estimators=200).fit(Xtrain,ytrain)

创建仪表板应用程序

下一步也是最后一步是为我们使用的模型和数据集创建应用程序。Shapash 使用 dash.js 创建一个仪表板,并将其用作 flask 应用程序。

from shapash.explainer.smart_explainer import SmartExplainer
xpl = SmartExplainer(features_dict=titanic_dict)xpl.compile(
    x=Xtest,
    model=classifier,
    preprocessing=encoder # Optional: compile step can use inverse_transform method
)#Creating Application
app = xpl.run_app(title_story='Titanic Dataset')

运行这些命令将创建一个仪表板,并显示应用程序运行的 URL。复制 URL 并在你的浏览器中打开它,它将看起来像下面给出的图片。

Shapash 仪表板(来源:作者)

在这里,您可以看到我们使用 shapash 创建仪表板是多么容易,在这里我们可以看到不同的可视化效果,我们可以使用它来清楚地解释和理解我们正在使用的机器学习模型。

我们可以通过展开并全屏观看来浏览所有的可视化效果,以便清楚地理解它们。在这里,您还可以看到我们可以分析两个类,即“0”和“1”。

专题供稿(来源:作者)

这就是我们如何使用 shapash 来创建机器学习模型的仪表板。继续尝试这个,如果你遇到任何困难,请在回复部分告诉我。

本文与 皮尤什·英格尔 合作。

在你走之前

感谢 的阅读!如果您想与我取得联系,请随时通过 hmix13@gmail.com 联系我或我的 LinkedIn 个人资料 。可以查看我的Github*简介针对不同的数据科学项目和包教程。还有,随意探索* 我的简介 ,阅读我写过的与数据科学相关的不同文章。

机器学习模型部署

原文:https://towardsdatascience.com/machine-learning-models-deployment-123773c476bc?source=collection_archive---------13-----------------------

它是什么,为什么重要,它的主要挑战是什么

图片来自 Pixabay

介绍

如今,在互联网上,你可以找到各种各样的资源,这些资源涉及成功开发机器学习模型的科学和方法。无论你想开发一个有监督的还是无监督的学习模型及其所有子类型,数以千计的帖子将一步一步地告诉你如何去做。

然而,有一个阶段是使这些 ML 模型具有生命力并真正能够从中提取价值的关键:部署它们并将它们产品化。这一阶段通常被忽视或根本没有解决。

所以,这就是我们在这篇文章中要探索的:什么是模型部署,为什么它很重要,它的主要挑战是什么。

注意:这篇文章包含附属链接,这样你就可以轻松地购买这本书,而不需要任何额外的费用,同时有助于创建更多像这样的帖子。

这篇文章的灵感来自 Pramod Singh 的伟大著作将机器学习模型部署到生产中。如果你有兴趣并想深入研究这个话题,我强烈建议你去看看并购买它。

什么是模型部署?

我在以前的帖子中谈到了成功开发机器学习模型,我甚至发布了几个解决回归和分类等问题的实际例子。

模型开发和部署的一般过程与此非常相似:

作者图,灵感来自来源

构建和部署一个模型是一个迭代的过程,其中一些循环部分将从其他需要改进的步骤的信息中得到启发。数据科学团队和业务部门需要回答一些问题:

  • 你试图解决的问题是什么?
  • 如何用数据解决这个问题?
  • 我们需要什么数据?我们目前有什么?
  • 数据来源是什么,我们如何访问它们?
  • 收集的数据代表问题吗?
  • 需要哪些资料准备?
  • 我们如何将数据可视化?
  • 开发的模型是为了回答最初的问题还是需要调整?
  • 我们如何将模型付诸实践?
  • 我们如何获得建设性的反馈来回答这个问题?

这里,我们将重点关注部署步骤。基本上,部署一个模型是为了让其他方可以使用它来为业务产生价值。

我们至少需要部署以下阶段:

  • 特征工程
  • 特征选择
  • 机器学习模型构建

因此,在实践中,我们没有部署机器学习模型,而是一个管道。

一旦模型准备好在生产环境中使用,我们需要通过一些 API 将它暴露给看不见的数据。这是关键部分,也是我们稍后将讨论的挑战所在。

步伐

第一步是在生产环境中部署 ML 模型并测试结果。

然后,我们应该持续监控它的性能。如果模型的性能低于某个阈值,则需要对其进行重新训练,并且该重新训练的模型将替代旧的模型。

通过这个过程,对它的版本和特性进行良好的模型管理是至关重要的,这样它就不会影响以前的用户请求。

当这个新模型被部署时,这个过程将被重复。

图由作者提供,灵感来自来源

ML 应用程序与典型的软件应用程序有何不同

机器学习应用是独特的,并且在两个主要方面不同于其他软件应用:

  • 基础模型
  • 基础数据

如前所述,部署模型基本上是通过将它集成到现有的业务应用程序中,使它可供其他方使用,从而为业务创造价值。

简单地说,ML 模型被公开为 REST API 端点,并服务于:

  • 应用程序平台内的请求
  • 直接用户的请求

并且可以部署:

  • 作为独立的预测器,使用批量数据给出输出
  • 作为实时请求的服务器,作为一个动态模型

模型部署是模型管理阶段的起点,这个阶段充满了挑战和潜在的问题。因此,要成功完成这一阶段,需要所有相关利益方的大量投入和协调:

  • 数据科学家
  • 数据工程师
  • 应用开发人员
  • MLOps 和/或 DevOps
  • 业务团队成员
  • 最终用户

为什么模型部署很重要?

我们需要理解 ML 模型在期望的业务应用中的作用。根据应用程序的最终目标,它可能有不同的角色。它可以是单个预测、多个预测的组合或某种推荐。

可以使用机器学习模型来预测汽车保险公司的客户,这些客户可能也对获得人寿保险感兴趣,这是基于他们的特征(收入、年龄、性别、他们是否有孩子……)。

除了机器学习模型可能的最终目标之外,它的部署对于能够与业务应用程序通信并最终从中提取价值也是至关重要的。它的预测将提供给业务应用程序,人们可以从它的洞察力中受益,以执行数据驱动的决策。另一个关键点是,可以从实时数据中获得预测。

当以下任何陈述为真时,部署尤其重要:有大量数据,数据来自流,有大量用户,需要快速响应。

主要挑战

我们应该理解的第一件事是开发一个 ML 模型和部署一个 ML 模型之间有巨大的差异。这些差异转化为性能、速度和资源消耗方面的巨大差异。

所有的任务和优先级都应该服从于对所部署的 ML 模型的持续监控,应用程序应该有最好的版本,以便在生产中服务于来自用户的实时请求。

而且,在实践中,ML 代码在生产中的整体部署中的作用是它正确工作所需的整个结构的非常小的一部分。如下图所示的顺序:

机器学习系统中隐藏的技术债务 —图片由作者转载

利益相关者协调

通常,任何 ML 模型部署中最常见的问题是协调部署团队与其他缺乏机器学习知识或理解的团队成员。

模型部署是一项团队任务,需要不断的沟通和对整体目标的共同理解。在 ML 模型开发的早期阶段,一个充分的计划是 MLOps/DevOps 团队为部署做好准备的关键。

编程语言差异

通常,ML 模型是用 Python 或 TensorFlow 或 PyTorch 之类的变体开发的,使用其输出的应用程序是用 Java、C++或 Ruby 开发的。虽然现在迁移 ML 模型以与应用程序顺利集成变得越来越容易,但编程差异给集成带来了一些挑战。

模型漂移

模型漂移是指 ML 模型的性能降低到指定的基准/阈值以下。这就是为什么持续监控 ML 模型性能如此重要的原因,以便能够检测和更新模型,从而获得在线和运行的最佳版本。

这种性能下降通常是由以下原因造成的:

  • 改变数据的行为:由于数据的动态特性,它和它的内部模式可能会随着时间而改变。因此,当模式和内部权重的调整不再反映当前数据时,一个在部署时表现非常好的 ML 模型将会看到其性能如何随着时间而下降。在这些情况下,必须用最真实的数据重新训练模型,并将新版本投入生产。
  • 改变对新数据的解释:这是由于概念漂移,通常是由于某个标签或类别的解释发生变化。例如,某些客户群可能属于 X 类,而在某个时间点,企业决定将其更改为 y 类。同样,该模型将不再有用,需要重新培训并重新投入生产。

内部部署与基于云的部署

这两种方法各有利弊,根据要解决的问题而定,哪种方法更合适。因此,业务部门和数据科学团队需要分析并决定哪种实施是最好的。

清晰的所有权

团队的每个成员都必须清楚地知道自己的职责和角色。通常,DevOps 不太了解模型下发生了什么,需要对其行为进行足够深入的解释,以便将其正确集成到应用程序中。另一方面,数据科学家倾向于假设他们的工作在模型开发出来后就完成了。因此,整个团队之间的顺畅沟通至关重要,以确保在要求的时间、成本和质量内完成部署,并避免任何潜在的问题。

模型性能监控

在将模型投入生产之前,需要对监控策略进行规划,通常围绕以下问题进行设计:

  • 什么时候重新训练模型?
  • 将使用多少数据来重新训练模型?
  • 模型的性能阈值是多少?

版本管理

这是需要考虑的一个关键方面。它有助于:

  • 追踪哪个模型是最好的
  • 不同的文件依赖关系
  • 数据资源指针

Git 是跟踪版本和分阶段部署最广泛的方式。

隐私保护和安全模型

这个话题是最重要的话题之一。关键是要确保模型的安全,这样就没有恶意攻击会将其数据暴露给第三方。

结论

在整篇文章中,我们探讨了什么是模型部署,为什么它很重要,以及它面临的一些最常见的挑战。一如既往,我希望你喜欢它,并学到一些新东西:)

如果你喜欢这个帖子,你可以看看我关于数据科学和机器学习的其他帖子 这里

如果你想了解更多关于机器学习、数据科学和人工智能的知识 请在 Medium 上关注我,敬请关注我的下一篇帖子!

机器学习监控——什么、为什么、在哪里以及如何?

原文:https://towardsdatascience.com/machine-learning-monitoring-what-why-where-and-how-873fa971afa8?source=collection_archive---------15-----------------------

确保你有一个健康的模型做出正确的预测

本文正被移至我的 子栈发布 。这里 可以免费阅读文章 。这篇文章将于 2022 年 7 月 18 日被删除。

您已经部署了您的模型,它现在正在处理请求并根据实时数据进行预测。太好了!但是你还没有完成。像任何其他服务一样,您需要监控您的模型。但是监控一个模型并不等同于监控任何其他服务。本文将尝试解释为什么需要监控模型,需要监控什么指标,监控在机器学习生命周期中的位置,以及如何开始监控模型。

为什么我们需要监控?

卢卡斯·布拉塞克Unsplash 拍摄的照片

任何在生产环境中运行服务的人都需要受到监控,以确保服务是健康的(运行和处理请求时不会出现意外错误)。

但是机器学习监控就不一样了。一个模特发球可以不发出任何声音就失败。该服务将启动、运行并处理请求。当预测质量变差时,就会发生这种情况。

但是为什么会这样呢?在将模型投入生产之前,我们训练它具有良好的准确性。这是因为数据会随着时间“漂移”。模型被训练的数据的分布最终可能与它在生产中遇到的不同。有时模型也可能变得陈旧。当模型的环境发生变化时,就会发生这种情况。

我们不久前见过这个。当新冠肺炎和洛克德斯风靡全球时,世界各地人们的行为和购物模式都发生了变化。这意味着电子商务和类似网站使用的模型遇到的数据与它们接受的训练非常不同。这意味着他们可能做出不太相关的预测和建议。

数据漂移和陈旧的模型是我们需要机器学习监控的众多原因之一。使机器学习监控变得必不可少的一些其他原因是-数据依赖性的失败、功能不可用和负反馈循环。

您应该监控哪些指标?

有两种方法来进行机器学习监控-设置仪表板进行实时监控,并让作业定期运行以计算必要的指标。在这两种情况下,您监控的指标通常是相同的。

本文其余部分已移至出版物 机器学习——科学、工程和 Ops 。这里 可以免费阅读整篇文章

图上的机器学习,第 1 部分

原文:https://towardsdatascience.com/machine-learning-on-graphs-part-1-9ec3b0bd6abc?source=collection_archive---------14-----------------------

艾莉娜·格鲁布尼亚克在 Unsplash 上的照片

收集基本统计数据

在一系列帖子中,我将概述几种从图形数据中学习的机器学习方法。从用于描述图形的基本统计开始,我将通过讨论节点嵌入、图形核、图形信号处理以及最终的图形神经网络来深入探讨这个主题。这些帖子旨在反映我在学术界和工业界的个人经历,包括我的一些研究论文。我的主要动机是首先介绍一些关于图的机器学习的基本方法,这些方法应该在深入研究像图神经网络这样的高级算法之前使用。

在第一篇文章中,我介绍了一些常见的图表分析技术,这些技术应该可以帮助我们更好地理解我们的数据。

预赛

我假设你熟悉基本的图形概念。我将考虑没有自环的无向图(节点通过一条边连接到自己),但这只是为了便于展示。一个图用 G=(V,E) 表示,其中 V 是节点或顶点的集合, E 是边的集合。节点的数量由 n = |V| 表示,边的数量由 m = |E|表示。

要寻找什么图形统计?

在着手解决一个问题之前,我们通常会花一些时间进行探索性的数据分析。这为我们提供了对数据的洞察,这些数据可能对我们以后的工作至关重要。理想情况下,我们会像绘制地铁图一样绘制图表,但大多数现实生活中的图表都很大,很容易可视化。相反,下面是一些重要的统计数据:

  • 程度分布。两个现实网络的度分布如图 1 所示。第一张来自欧盟机构的电子邮件通信,第二张是来自 DBLP 数据库的合著图。我们观察到电子邮件图中最常见的节点度是 1,意味着大多数人只与一个人交流。在合著图中,大多数作者都有两到三个合著者。

图 1:学位分布。图片作者。

  • 图形密度。数量定义为

解释很简单:边的最大可能数量是 n(n-1)/2,因为每个节点可以恰好连接到 n-1 个其他节点,并且边是无向的。它衡量一个图与一个完全连通的图或者一个集团*的接近程度。大多数现实生活中的网络是非常稀疏的,因此在大多数情况下,这种方法不能提供很多信息。

  • 连接组件。我们说,如果在 uv 之间存在一条路径,即一系列边,那么从节点 v 可以到达节点 u 。在连通组件中,每个节点都可以从该组件中的所有其他节点到达。连通分量的数量和相应的大小可以提供关于图形的信息。然而,在大多数情况下,我们感兴趣的是由单个连通分量组成的连通图。
  • 图形直径。两个节点 uv 之间的最短路径是从u开始到达 v 需要遍历的最小边数。图直径是图中任意两个节点之间的最大最短路径长度。如果图有多个连通分支,那么它的直径是无穷大。在这种情况下,我们感兴趣的是每个连通分量的直径。图的直径可以用来区分不同类型的网络。例如,地铁网络可能比小型社交网络具有更大的直径。
  • 三角形的数量和传递系数。在图论中,有erdős–rényi 图的基本概念。这是一个理论模型,其中节点之间的边是随机生成的,每个边都有固定的概率 p ,独立于其他边。现实生活中的图与 erdős–rényi 图非常不同,因为边不是随机独立创建的。特别是,对于大多数真实的图,它通常认为“我的朋友的朋友也是我的朋友”。这使得研究人员认为三角形是图形分析的基本单位[1]。在高层次上,三角形的数量显示了我们的图形与随机图形的不同之处。

图的传递系数定义为

在上面的例子中,分子是三角形的数量乘以 3,分母表示图中 2-路径的数量,可以计算如下:

在图 2 的图形中,有两个三角形,分别是 (u,v,w)(u,v,z) 。2-路径是由 en 边连接的 3 节点序列,例如 z-u-w 。观察到给定节点的每对邻居都产生一条 2-路径,因此得到了上面的 2-路径总数公式。我们将三角形的数量乘以 3,因为我们计算了它的 3 2 条路径中的每一条。因此,传递系数是介于 0(完全没有三角形)和 1(完全连通图)之间的值。

在图 2 中,2-路径的数量是 8,因此传递系数是 0.75。

在大多数真实的图中,传递系数是常数。传递系数越大,网络连接越紧密。事实上,它在 1998 年被引入来描述小世界网络模型。

图二。一个紧密连接的图。图片作者。

  • 三角形的局部数量和聚类系数。定义节点 u 的局部聚类系数

即以 u 为节点的三角形的数量除以以 u 为中心的 2-路径的数量。

然后将其推广到全局聚类系数

在图 2 中,节点 u 的局部聚集系数为 2/3,图的全局聚集系数为(2/3+2/3+1+1)/4 =0.833。

最后,我们希望指出,在文献中,传递性系数有时被称为聚类系数,而如上定义的全局聚类系数被称为平均聚类系数。符号的混乱源于 Watts 和 Strogatz 在他们的开创性论文[1]中错误地声称及物性系数和聚类系数是相同的。

怎么数三角形的个数?

从上面的讨论可以明显看出,最重要的图统计似乎是三角形的数量以及相应的传递性和聚类系数。让我们看看如何计算它。我推荐在处理图形时使用 Python 的 networkx 库。它使用起来简单直观,并提供了许多基本的图形算法,如最短路径、连通分量数,甚至传递系数。

import networkx as nx
import numpy as npG = nx.Graph()
for u, v in <list of edges or edge generator>:
      G.add_edge(u, v)

我们可以用图的邻接矩阵的三次方来计数三角形。精确的公式是

迹被定义为矩阵中对角线元素的和。中的每个对角线条目测量从相应节点到其自身的长度恰好为 3 的路径的数量。考虑三个节点(u,v,w)之间的三角形。这三个节点有 6 种排列,这就是为什么我们需要将轨迹除以 6。在 Python 中,代码看起来像

def count_triangles(G):
   A = nx.to_scipy_sparse_matrix(G)
   A2 = A.dot(A)
   A3 = A2.dot(A)
   return A3.diagonal().sum()/6

注意,上面使用了稀疏矩阵乘法。然而,邻接矩阵的三次幂不能保证是稀疏的,特别是对于小直径的图,计算可能成为瓶颈。在这种情况下,我建议使用 Doulion 算法[2]。Doulion 的工作原理是对原始图形的边进行采样。每个边缘以概率 p 保持。因此,一个三角形以概率 p 存在于稀疏图中。我们通过将稀疏图中的三角形数量乘以 1/p 来估计原始图中的三角形数量。

def sparsify_graph(G, p):
    G_sparse = nx.Graph()
    for u,v in G.edges():
        if np.random.random() <= p:
            G_sparse.add_edge(u,v)
    return G_sparse

我在从 DBLP 网络获得的图上运行了一个实验。该图由 317,080 个节点组成,边数刚刚超过 100 万。通过以 10%的概率对边缘进行采样,我获得了精确计数算法和 Doulion 的以下运行时间。并且所获得的三角形数量的近似值非常好。

Elapsed time exact:   13.21 secs
Elapsed time Doulion: 1.19 secs
Approximation exact/estimated: 1.030

一些更高级的统计数据。

让我们简单提一下还有更高级的图表统计。

  • 介数中心性。这个度量捕获了图中节点的影响。对于每个节点 u ,我们计算节点对之间有多少条最短路径经过u。具有高介数中心性的节点被认为在网络中更重要。介数中心性分数的分布为我们提供了对图结构的进一步了解。然而,计算所有节点的中心性的计算复杂度是 O(m*n)。
  • 稠密连接的子图。一个重要的研究课题是密集连通子图的检测【3】。这些是原始图中的子图,其中几乎所有的节点对都由一条边连接。这是社区检测算法的基础。但是这些致密成分的数量和密度也是重要的统计数据。
  • 挖掘图形主题。检测频繁图模式是一个活跃的研究领域[4]。它将三角形计数算法推广到挖掘和计数更复杂的子图,或主题。这些计数可用于图形分类任务。在图 3 中,我在 4 个节点上展示了三个不同的主题。然而,对基序进行计数在计算上可能是昂贵的,并且仅限于小的子图。有人可能会认为,图形神经网络的成功是基于它们学习与手头问题相关的复杂主题的能力。

图 3。4 个节点上的子图主题。

密码

以上例子的代码可以在:https://github.com/konstantinkutzkov/ML_on_graphs/找到

[1]邓肯·j·瓦茨,史蒂文·h·斯特罗加兹。小世界网络的集体动力学。自然 393,1998。

[2]查拉兰波斯·e·措拉卡基斯、U·康、加里·米勒和克里斯特斯·法卢特索斯。 DOULION:用一枚硬币数海量图形中的三角形。KDD 2009。

[3]查拉兰波斯·祖拉卡基斯、弗朗切斯科·邦奇、阿里斯蒂德斯·乔尼斯、
弗朗切斯科·古罗和玛丽亚·齐阿利。比最密子图更密:
提取质量有保证的最优拟团
。KDD 2013。

[4]古越汉和哈里什塞图。蹒跚随机行走:在大图中快速准确挖掘模体统计。ICDM 2016。

图上的机器学习,第 2 部分

原文:https://towardsdatascience.com/machine-learning-on-graphs-part-2-205c46b3ef60?source=collection_archive---------23-----------------------

艾莉娜·格鲁布尼亚克在 Unsplash 上的照片

节点嵌入。

之前的博客文章中,我介绍了在开始为你的图表数据开发机器学习模型之前应该收集的基本图表统计数据。在第二篇文章中,我将介绍第一种合适的机器学习方法。也就是说,学习用连续向量来表示离散对象,如图形节点,即所谓的节点嵌入。类似于单词嵌入,节点嵌入可以用于下游机器学习应用。

在介绍学习节点嵌入的算法之前,让我详细说明一下我在下一篇文章中的主要目标。

动机。图无处不在。从社交网络到交通枢纽,图模拟了对象之间的关系。在某种意义上,图将顺序数据概括为更复杂的交互。毫不奇怪,从图形数据中学习已经成为学术界和工业界的热门话题。鉴于深度学习的整体优势,从图形数据中学习的最强大的算法是基于图形神经网络,这是一种专门设计用于处理图形数据的特殊神经网络。在学术界,目标是在竞争激烈的场所发表研究论文,大多数关于图学习的新作品都基于图神经网络,因为它们改进了基准数据集上的最佳已知结果。大多数图形机器学习课程的重点是图形神经网络。例如,考虑这个关于图形机器学习的极好的斯坦福课程。课程材料质量非常高,我强烈推荐给每个想深入研究图形机器学习的人。然而,大约 70%的讲座是关于图形神经网络的。并且省略了像图核机器这样的更基本的技术。根据我的经验和观察,这给人一种印象,从图中学习的默认方法是图神经网络。

另一方面,众所周知,当处理一个新问题时,应该从一个简单的、具有众所周知的特性的解决方案开始。对于许多从业者和机器学习爱好者来说,处理新问题的主要目标是在投入太多时间开发高级解决方案之前先尝试一些东西。对于图形相关的机器学习来说尤其如此,在这种情况下,我们经常需要解决一个没有给出明确图形的问题,但是我们可以使用一些关于数据的元信息来创建自己的图形。例如,给我们一个大城市的道路交通数据集,我们想预测何时何地会发生交通堵塞。我们可能想尝试一种图表方法,即创建与街道位置相对应的节点,并用显示交通堵塞如何从一个节点传播到另一个节点的边将它们连接起来。但是当然不能保证图表方法是有前途的,因此我们更想要一个概念的证明而不是一个完整的解决方案。

神经网络,即使是简单的,也不是简单的解决方案。对于图形神经网络来说更是如此,因为图形没有它们的节点的总顺序,因此表现出比像文本和图像这样的顺序或网格结构数据复杂得多的结构。

因此,在接下来的几篇博客文章中,我想集中讨论不基于图形神经网络的图形机器学习技术。我将介绍一些简单而直观的从图中进行机器学习的方法。

我们应该从一个简单的图机器学习算法中期待什么?

  • 易于实现。我们需要一个概念证明,即图形机器学习是我们问题的一个有前途的方向,我们应该能够轻松实现一个解决方案。
  • 效率高。该模型应该能够在合理的时间内提供初步结果,即使不使用昂贵的计算机硬件。
  • 战功图。假设我们收集节点度作为节点特征。这很容易实现,而且我们可以训练一个有效的算法。但是这样的解决方案将是图形不可知的,因为它忽略了图形结构,而这正是我们最终想要在我们的模型中利用的。
  • 可解释性。尽管对人类来说,图表不如图像或文本容易理解,但它仍然能让我们对数据的本质有一些直觉。理想情况下,机器学习模型应该能够帮助这种直觉。

好了,让我们从节点嵌入开始,这是一种强大的图形机器学习方法。

什么是节点嵌入?

受 word2vec 和 GloVe 等从自然语言数据中学习单词嵌入的算法成功的启发,研究人员发明了学习图节点嵌入的算法。对于单词嵌入,我们想要学习连续的向量表示,使得频繁出现在一起的单词具有相似的表示。很容易为文本序列定义“一起出现”,这些是彼此接近的单词。但是图形更复杂。考虑图 1 中的示例图。黄色节点 v1v12u 的近邻。另一方面,红色节点 z 可以由来自 u 的更多路径到达,并且它看起来是更中心的节点。那么 v1v12 还是节点 z 更能代表 u

图一。图片作者。

随机游走

随机漫步是遍历图的一种简单方法。从一个给定的节点开始,我们均匀地随机选择它的一个邻居,然后均匀地随机选择这个邻居的一个邻居,等等。随机漫步很容易实现,也很直观。

随机游动的性质已经被研究了几十年,并且是图论中几个重要结果的核心。它们是一个非常强大的工具,因为它们能够捕捉图形结构。高度连接或容易到达的节点更有可能被访问,这符合我们对重要性的直觉。

更正式地,对于连通图 G,设 A(G)是它的邻接矩阵,其中 A[u,v] = 1 当且仅当节点 u 和 v 之间有边(我们假设节点是 1 和 n 之间的整数)。从邻接矩阵,我们将转移概率矩阵定义为 P[u,v] = A[u,v]/d(u),其中 d(u)是节点 u 的度。P[u,v]因此表示如果我们当前在节点u处,则选择节点 v 的概率注意,P 的每一行中的概率总和必须为 1。此外,请注意,对于无向图,邻接矩阵是对称的,但转移矩阵是不对称的,见下面的例子。**

图二。未加权图。图片作者。

未加权图的转移矩阵。图片作者。

给定转移矩阵,平稳分布π定义为:

平稳分布给出了在一次很长的随机行走中到达给定节点的概率,与我们开始的位置无关。事实上,固定分布是谷歌的 PageRank 算法的核心。本质上,我们越有可能在长时间随机浏览的同时访问某个页面,该页面的排名就越高。

加权图的随机游动。

许多图具有加权边,其中权重对应于节点之间的关联强度。例如,在对应于所有世界机场的图中,边可以对应于具有直达航班连接的城市之间的飞行时间的倒数。在这种情况下,在随机行走中,根据相应的边权重对随机邻居进行采样。考虑下面图 3 中的权重图和相应的转移矩阵。从节点 1 开始,我们最有可能访问节点 3,因为边权重更大。注意,只有当我们在节点 1 时,节点 1 和 2 之间的边权重才是重要的。如果我们在节点 2,那么权重并不重要,因为唯一的邻居是节点 1。

图 3。加权图。图片作者。

加权图的转移矩阵。图片作者。

节点嵌入

随机行走打开了将单词嵌入学习算法扩展到图形数据的大门。也就是说,我们可以通过生成随机行走来创建节点序列,并将其输入到学习单词嵌入的模型中。实现简单而直观:

def random_walk(G, u, k):
    curr_node = u
    walk = []
    for i in range(k):
        idx = random.randint(0,len(list(G[curr_node]))-1)
        curr_node = list(G[curr_node])[idx]
        walk.append(curr_node)
    return u, walk

一旦我们生成了随机游走,我们就生成了正节点对和负节点对。

def generate_pairs(G, u, walk, nr_neg_pairs):
         positive_pairs = []        
         negative_pairs = [] 
         for v in walk:
             positive_pairs.append((u,v))
         for _ in range(nr_neg_pairs):
             w = <sample a random node from G>
             negative_pairs.append((u,w))
         return positive_pairs, negative_pairs 

然后,我们将正对和负对输入到学习节点嵌入的模型中。每个节点 u 最初由随机向量 vec(u) 表示,每当我们看到涉及 u 的正或负对时,该向量就会更新。这是采用负采样的标准 word2vec 方法。我们训练一个逻辑回归模型,其中输入是正负节点对的节点嵌入的内积。我参考实现来了解更多细节。

一些实际的考虑:

  1. 随机漫步应该持续多长时间?别忘了上一篇文章的图直径。对于短直径图,任何一对节点都由一条短路径连接。应该注意不要使用太长的随机行走,因为它们可能很快收敛到平稳分布,并产生相似的行走,从而产生相似的嵌入。
  2. 对每个序列中的节点重新加权。您可能想给不同的节点对分配不同的权重。但是,请注意,随机行走已经考虑了节点距离。离我们的起始节点越远的节点通常不太可能出现在随机漫步中。如果它确实经常出现,那么它就是一个重要节点,通过许多路径连接到我们的起始节点。您可能需要考虑在相邻节点之间分配不同的转移概率。但是在这样做之前,你应该对你的数据有一个坚实的理解。所以,除非你真的知道自己在做什么,否则使用标准的随机漫步算法是最安全的。

结构角色节点嵌入。

随机漫步方法假设彼此容易到达的节点也彼此相似。对于许多应用来说,这当然是合理的。然而,有时我们感兴趣的是节点在图中扮演的结构角色,而不是它的邻居。

让我们考虑一个具体的例子。一些节点可以是中心,就像有很多追随者的 twitter 用户(图 4 中的红色节点)。或者,一些节点可能程度较低,但它们在社区之间起着桥梁作用,因此对于影响传播跟踪等任务很重要(图 4 中的绿色节点)。使用标准的随机行走,我们可以捕获节点所属的社区,但是不能捕获节点在这些社区中的角色。

我们现在将讨论如何学习关于单个节点的结构角色的嵌入。

假设我们有节点的标签。然后,我们通过运行随机漫步来生成序列,但是我们收集的不是节点 id,而是节点标签。通过这种方式,我们生成了长字符串,并希望使具有相似节点字符串的节点彼此相似。直觉上,具有相似结构角色的节点将具有相似的节点标签序列。例如,一个流行音乐明星会有许多年轻且对音乐感兴趣的追随者。同样的模式也适用于世界各地的流行歌星,不管他们是在美国、印度还是俄罗斯。

当然,现在我们必须以某种方式生成相似和不相似的对象。一个简单的解决方案是根据这个相似性函数定义生成的序列和样本节点之间的相似性函数。当然,相似性是一个非常普遍的概念,所以让我们考虑一个具体的例子,它将提供更多的直觉。

举例。考虑图 4。假设节点根据其程度被标记为 H(高度)、M(中度)和 L(低度)。在图 4 中,我用颜色对节点标签进行了编码。低度节点为蓝色,中度节点为绿色,高度节点为红色。假设我们收集长度为 k = 5 的随机游走。一次遍历生成一个类似 L,H,M,M,M 的序列。比较这些序列的一个自然方法是比较它们的 n 元语法分布。对于 n=2,L,H,M,M,M 中的克数是(L,H),(H,M),(M,M),(M,M)。这两条路 L,H,M,M,M 和 L,H,L,H,M 看起来很相似,但并不完全相同。计算它们的 2 克,我们看到 4 个 2 克中有 2 个是相同的。

图 4。颜色是节点标签。图片作者。

我关于学习任意相似函数嵌入的文章的第二部分,我讨论了从任意相似函数学习嵌入的方法。这些技术在这里适用。关于如何在上述设置中生成相似节点的样本,请参考那里描述的技术。

如何使用节点嵌入?

节点嵌入是节点分类或回归任务的完美选择。例如,您的图表是一个由城市和村庄组成的网络,其中相邻的城镇通过一条边连接在一起。我们希望预测网络中每个城镇的天气,但是收集网络中每个节点的历史天气数据成本太高。通过仅在部分城镇建立气象站,我们创建了一个训练数据集。使用节点嵌入作为我们问题的输入特征,然后我们可以使用我们最喜欢的机器学习算法预测所有城镇的天气情况。当然,我们可以用额外的数据来增加嵌入。例如,收集关于降水的数据是昂贵的,我们满足于城镇的子集,但是我们能够负担得起收集所有节点的温度和大气压力数据。然后,我们可以将捕捉城镇之间地理邻近性的嵌入与附加功能相结合。

但是如果我们想要使用嵌入来分类子图甚至独立图呢?例如,我们希望根据用户的浏览行为对他们进行分类。这将生成独立的图形,其节点对应于所访问的网站,边对应于网页之间的超链接。我们可以使用每个网页的单个节点嵌入来对全球网络图的这些小的子图进行分类吗?

从节点嵌入到(子)图嵌入。

标准技术是简单地取(子)图中所有节点嵌入的平均值。这是一个合理的选择,但我们可能会以这种方式丢失信息。以这种方式考虑:单个嵌入维度代表用户的不同特征。比如第一维显示对政治的兴趣,第二维显示对音乐的兴趣,第三维显示对体育的兴趣,第四维显示对电影的兴趣等等。通过平均嵌入,我们将知道群体的主要利益。但是我们很可能会忽略一些重要的细节,比如这个群组实际上包含了两个喜欢运动和时尚的用户群,以及一个主要对政治和电影感兴趣的用户群。

提出了一种解决方案,其工作原理是为每个感兴趣的子图创建一个虚拟节点,并将子图中的所有节点连接到该虚拟节点。当训练嵌入时,虚拟节点将在某种程度上捕获子图的结构。这本质上也是一种平均方法,但是我们将对更有可能被随机漫步访问的邻域节点给予更大的权重。这种方法的一个缺点是我们需要在训练感兴趣的子图之前决定嵌入。

在这一系列的下一篇博文中,我将展示图核,一种强大而直观的基于图的机器学习方法,它建立在像 SVM 这样的核机器上。然后,我将展示一种简单的技术,用于将单个节点嵌入组合成图嵌入。所以,敬请关注:-)

结论。

最后,让我们回到帖子的开头,讨论节点嵌入如何满足我们对简单而强大的机器学习模型的要求。给定用于训练嵌入的公开可用的工具,它们很容易实现。这些工具是高度优化的,因此是高效的。随机漫步充分利用了图形结构。人们甚至可以说它们是图形分析最强大的工具,因为它们天生偏向于容易访问的节点。嵌入向量是不可直接解释的。但是它们对节点相似性进行建模,节点相似性本身是可解释的,并且如上所述,可以是用户定义的。因此,为您的图训练节点嵌入,然后将它们与众所周知的 ML 算法结合使用,是处理图数据的自然的第一步。

代码。

训练节点嵌入并在节点分类问题中使用它们的代码可以在这里找到。

这个系列的代码在这里:【https://github.com/konstantinkutzkov/ML_on_graphs/

Bryan Perozzi,Rami Al-Rfou,Steven Skiena: DeepWalk:在线学习社会表征。KDD 青奥会。

Aditya Grover,Jure Leskovec: node2vec:网络的可扩展特征学习KDD 2016 年奥运会

李,丹尼尔·塔洛,马克·布洛克施密特,理查德·泽梅尔。门控图序列神经网络。ICLR 2016。

图上的机器学习,第 3 部分

原文:https://towardsdatascience.com/machine-learning-on-graphs-part-3-b968e1cc1aa3?source=collection_archive---------31-----------------------

艾莉娜·格鲁布尼亚克在 Unsplash 上的照片

图核方法易于实现,并产生可以有效训练的模型

在本系列的第三篇文章中,我将讨论图形内核。图核是一种将支持向量机等核机器一般化以处理图的方法。简而言之,图核的思想是通过将两个图作为输入的函数来比较这两个图。直观地说,这个函数应该测量不同相似性概念的图形之间的相似性。

图核是从图数据进行机器学习的第一个主要方法。在深度学习和图形神经网络兴起之后,它们不再流行,但仍然是一个强大的工具。在这篇文章中,我将专注于图核方法,这些方法易于实现并产生可以有效训练的模型。正如在系列的前一篇文章中所讨论的,主要目标是在进入图形神经网络之前,提出在图形上进行机器学习的简单算法。

一般设置

图核的前提是我们有一组图作为输入,我们想要训练一个分类或回归算法。注意,这些图可以是大型图的子图,例如大型社交网络图中的不同社区。大约 20 年前,在深度学习占据主导地位之前,研究人员提出了为图分类问题训练支持向量机的想法。为了做到这一点,需要设计一个特定于图的核函数来比较两个图。然后,我们可以使用标准的 SVM 算法,该算法使用核技巧来创建由训练集中所有图形对的核函数组成的 Gram 矩阵。然后,我们学习支持向量,或在我们的情况下,支持图,允许我们通过简单地评估以新图和所有支持图作为输入的核函数来分类新图。

接下来,我将介绍一个通用的图核家族。

卷积图核

让我们暂时假设我们已经在每个节点收集了一个矢量。例如,这可以是一个节点嵌入向量,就像上一篇文章中讨论的那样。稍微简化一下,两个图 G 和 H 的卷积图核被定义为

在上面,κ 是两个向量之间的(非线性)核函数。例如,多项式核:

或者 RBF 内核:

关于内核函数的更多细节,我建议读者参考我的关于非线性内核函数的博客文章。

请注意,有一个规范化的版本的内核定义:

让我们分析卷积图核的定义。

  1. 我们比较所有的节点对,因为一个图是无序的,所以我们需要比较两组。核心被称为卷积,因为来自一个图的每个节点向量与来自另一个图的每个向量进行比较。(就像在卷积神经网络中,我们将每个滤波器与输入图像中的所有补片进行比较。)
  2. 我们使用(非线性)核函数来比较两个向量,以便捕捉节点之间更复杂的相关性。核函数的选择可以赋予相似性不同的含义。例如,RBF 核的正确参数可以迫使我们只考虑向量几乎彼此相同的向量对。

上述的明显缺点是二次计算复杂度。对于两个图,每个在 n 个节点上,我们需要计算 n 次核函数。此外,对于训练数据集中的 m 个图的集合,我们需要一个由 m 对核函数组成的 Gram 矩阵。接下来,我将介绍一种非常有效的近似计算图核的方法。

显式图形特征映射

正如在我的关于非线性核的显式特征映射的帖子中所讨论的,我们可以将非线性核函数近似为

在上面的例子中,ψ是一个函数,它将向量映射到一个合理的、用户定义的维度的新特征空间。维度越大,近似性越好。

显式特征映射的主要结果允许我们如下重写图形核表达式。下面是对[3]的主要结果的简化:

以上表明,我们可以从单个节点的嵌入中获得整个图的特征表示。两个图特征向量的内积逼近两个图的核函数。

观察到,对于图核的归一化版本和节点向量的线性核,即,κ(u,v) = u^T v,以上对应于取图中所有节点嵌入的平均向量。

履行

有一个大型图形基准数据集集合用于图形内核评估。在这篇文章的 Jupyter 笔记本中,我展示了读取输入图并将其转换成我们可以用来训练节点嵌入的表示的代码。注意,这些图是不相交的,因此像 node2vec 这样的标准方法是行不通的。相反,我实现了上一篇关于节点嵌入的文章的第二部分中概述的方法的变体。我们假设节点被标记。如果没有提供标签,我们可以创建自己的标签来描述节点度。我从每个图中的每个节点开始,进行了多次短距离随机行走。对于每次行走,我都记录下行走过程中遇到的节点的标签。然后,我将具有相同步移的节点分组在一起,即具有相同标签序列的步移。从这些组中,我对具有负采样的 word2vec 类节点嵌入算法的正对进行采样。读者可以参考 Jupyter norebook 了解更多细节。

其他图形内核

使用节点嵌入作为节点向量是一个自然的选择,因为节点嵌入捕获了图的结构。然而,我想简单提一下一些最广泛使用的计算图核的方法。然而,请注意,这些方法是在节点嵌入算法出现之前设计的。对于图核算法的全面概述,我建议读者参考[2]。

k 步核

从每个节点,我们开始一些长度正好为 k 的随机行走。节点处的向量就是所有遍历中标签的分布。(注意,对于未标记的图,通常使用节点度作为标记。)

最短路径核

对于每个节点,记录到图中每个其他节点的最短路径。然后,类似于 k-walk 核,创建描述收集的路径中的标签分布的向量。

魏斯费勒-雷曼核

对于图中的每个节点,收集其邻居的标签并进行排序。然后从结果字符串创建一个新标签。迭代 t 次并为每个节点创建 t+1 个标签。向量由这些标签的 id 组成。

魏斯费勒-雷曼重新标记算法。来源:[1]

密码

实现可以在本 Jupyter 笔记本中找到。

[1] Nino Shervashidze,Pascal Schweitzer,Erik Jan van Leeuwen,Kurt Mehlhorn,karst en m . Borgwardt:Weisfeiler-Lehman Graph Kernels。j .马赫。学习。第 12:2539-2561 号决议(2011 年):https://www . jmlr . org/papers/volume 12/shervashidze 11 a/shervashidze 11 a . pdf

[2] Karsten Borgwardt,Elisabetta Ghisu,feli PE llina RES-Lopez,Leslie O'Bray,Bastian Rieck。图形内核。最新技术和未来挑战。https://arxiv.org/pdf/2011.03854.pdf

[3] Moez Draief,Konstantin Kutzkov,Kevin Scaman,米兰·:
:孔:有序邻域图的核。neur IPS 2018:4055–4064https://arxiv.org/pdf/1805.10014.pdf

声音和音频数据的机器学习

原文:https://towardsdatascience.com/machine-learning-on-sound-and-audio-data-3ae03bcf5095?source=collection_archive---------1-----------------------

使用流派分类用例学习如何将机器学习应用于声音和音频数据

声音的机器学习。由 Unsplash 上的 ConvertKit 拍摄。

在本文中,您将学习对声音数据进行机器学习的基础知识。声音数据(通常称为音频数据)是一种不太直观的数据类型。看完这篇文章,你会明白:

  • 如何将声音文件(mp3 或其他)转换成数字数据
  • 如何训练用于体裁分类的卷积神经网络
  • 深入音频领域所需的所有基础知识。

声音数据

从声音数据开始的最大困难是,与表格数据或图像不同,声音数据不容易用表格格式表示。

您可能知道,也可能不知道,图像可以很容易地表示为矩阵,因为它们是基于像素的。每个像素都有一个值,表示黑色和白色的强度(或者对于彩色图像,分别表示红色、绿色和蓝色的强度)。

另一方面, 声音是一种复杂得多的数据格式:

  • 声音是不同强度的波频率的混合。在进行任何机器学习之前,有必要转换成某种表格或类似矩阵的数据集。
  • 其次,声音有一个时间因子。它实际上更像是视频数据,而不是图像,因为你有一定持续时间的声音片段,而不是仅仅在一个时间点的捕捉。

如果你想更深入的了解什么是声音,可以看看这篇文章。

用于流派分类的示例声音数据集

在深入之前,我们先介绍一个示例数据集。因为我们是在处理歌曲,所以很难获得一个我们可以确定没有侵犯版权问题的数据集。因此,为了这篇文章,我决定自己创建一个小型数据库,只使用来自一个名为 Uppbeat 的无版权音乐网站的节拍:

  • Uppbeat 流派“傻劲”的 100 首曲目
  • Uppbeat 流派“戏剧”的 100 首曲目

我不想重新分发这些歌曲,但如果你想继续下去,你可以很容易地创建一个免费帐户,并从这两个类别下载一些歌曲。

如何组织数据和环境以处理声音

为了跟随您自己的环境,我建议您创建一个名为 tracks 的文件夹,在其中创建两个文件夹:

  • 戏剧性:包含所有的歌曲与流派戏剧性
  • 愚蠢能量:包含所有类型的愚蠢能量的歌曲

对于本教程,我建议使用 Jupyter 笔记本,因为有一些很好的功能可以直接从笔记本上播放声音。如果你想避免环境或软件包安装问题,你可能想使用 Google Colab:一个伟大的、免费的、在线的笔记本环境

用 Python 进行流派分类

在描述的数据集中,你有两种类型的音轨:“愚蠢的能量”和“戏剧性的”。这篇文章的目标是给你建立一个体裁分类模型的基本步骤。

这两种类型的声音应该非常不同,因此训练一个可以将这两种类型区分开来的机器学习模型应该相对容易。

基于内容与基于频谱图的方法

在本教程中,我们将做一个“真实的”基于声音的机器学习模型。:我们将为我们的机器学习模型使用声音的数字转录。

然而,我想补充的是,使用声音的元数据而不是实际声音来构建流派分类模型也是可能的。在这种情况下,您可以使用以下功能:

  • 作者
  • 出版者
  • 歌词
  • 等等等等

虽然这也是一个很好的方法,但是它不在当前模型的范围内。

为机器学习准备声音数据

现在让我们开始使用 Python,深入实用的一面。到目前为止,您的环境中应该已经有了这些磁道。让我们现在开始为机器学习做准备。这是棘手的部分。

由于声音或音乐是我们听到的东西,很难想象如何将其数字化。然而,数字音乐无处不在,这个问题已经得到很好的解决。如果你想了解更多这方面的背景信息,你可以看看这篇关于傅立叶变换的文章或者这篇关于音乐如何转换成数字的文章。

在本文中,我们将使用 librosa 库:一个在 Python 中处理声音和音乐的伟大库。

使用 Jupyter 笔记本载入并播放歌曲

您可以使用以下代码导入一首示例歌曲并试听:

声音的机器学习。使用 Jupyter 在 Python 中导入 MP3。

声音的机器学习。使用 Jupyter 在 Python 中播放 MP3。图片作者。

通过用 librosa 导入它,您还可以看到它在数字上的样子,如下所示:

声音的机器学习。用 Python 创建一首 MP3 歌曲的数字表示。

您将获得一个表示音乐的 NumPy 数组,如下所示:

声音的机器学习。Python 中 MP3 歌曲的数字表示。图片作者。

把歌曲切成等长的片段

为了给机器学习准备声音数据,我们刚刚使用 librosa load 函数生成了表示音乐的数字数组。现在已经完成了,把声音分成同样长的片段就相对容易了。

对于这个项目,我们创建宽度为 100000 的数组,因为这在歌曲中创建了大量的分割(它将歌曲分割成大约 20 到 30 个片段)。

在现实生活的用例中,文件分割和重用是您需要根据您的用例以及您使用的数据和模型做出的选择。例如,如果你需要在短音段上预测,你应该在短音段上训练。此外,如果你有更多的数据,你可能需要每首歌更少的片段:有许多相似的片段不一定是机器学习的最佳选择。

用 CNN 创建用于体裁分类的 melspectrograms

声音准备的第二步是转换成 melspectrograms。虽然这不是声音准备的唯一方法,但这种方法是常用的,也是一个很好的起点。

使用傅立叶变换创建光谱图。简而言之,傅立叶变换分离出声音中存在的不同声音频率,并在每频率强度矩阵中恢复它们,我们称之为声谱图。你也可以在这篇文章中读到更多关于声音的傅立叶变换

以下代码同时执行上述两个步骤:

为流派分类创建 melspectrograms。

用于声音数据机器学习的 CNN

刚刚描述的声谱图方法将每首歌曲(或歌曲片段)转换成声谱图:一个二维矩阵。要对二维输入数据进行机器学习,最好的方法是使用 CNN,即卷积神经网络。

CNN 在图像数据上的表现是众所周知的。你可以认为频谱图是一种图像,因此 CNN 是声音数据的最先进的机器学习模型。

让我们继续讨论一个简单的 CNN 定义,看看如何将准备好的声音数据放入 CNN 神经网络。

为 Keras 生成声音数据

要创建适合 keras 输入的数据格式,我们可以使用下面的代码。请注意,这只有在您按照上述方式创建了文件结构的情况下才有效:

您需要一个名为“曲目”的文件夹,其中包含:

  • 一个名为“戏剧”的文件夹,里面有一些戏剧歌曲(如来自 Uppbeat)
  • 一个名为“愚蠢能量”的文件夹,里面有一些愚蠢的能量歌曲

如果您有其他歌曲和其他流派,您可以根据您的具体情况轻松调整代码。

为 Keras CNN 准备类型分类数据。

培训/验证/测试分割

我们可以使用以下代码创建一个训练/验证/测试分割,这在标准机器学习管道中很常见:

声音的机器学习。使用 Keras 进行流派分类的训练测试分割。

我们将使用训练数据来训练模型,同时也通过验证。测试集将保持独立,直到最后对我们的模型进行最终评估。

使用 Keras 建立一个类型分类 CNN

我们在这里只使用一个非常基本和标准的 CNN。本文的目标不是在调整神经网络上花费太多时间,而是给出对声音数据的机器学习管道的全面理解。请随意构建一个更好的模型!

流派分类 CNN 模型架构

下面使用的模型使用非常标准的 CNN 架构,中间有三个卷积层和两个 MaxPooling 层。

这种架构实际上只是一个起点,在现实生活的用例中还需要更多的调整。对于示例管道,它至少将向您展示如何在声音数据上安装 CNN,这是本文的目标。

声音的机器学习。CNN 使用 Keras 进行流派分类。

你可以看到下面的模型总结。如果您没有遵循确切的示例,请注意这个模型架构将适用于二进制分类。如果你想使用两个以上的流派,你将需要在你的最后一个稠密层输出形状(前面代码的第 15 行)。

美国有线电视新闻网的流派分类。图片作者。

适合 Keras CNN 的类型分类

既然已经定义了模型架构,我们需要编译它,并选择损失函数、优化器和指标。在本例中,我们使用二元分类(两种可能的结果),因此我们选择“二元交叉熵”。作为优化器,让我们使用 RMSprop,并选择 set“accuracy”作为度量。

然后,我们使用 X_train(训练歌曲)和 y_train(训练标签)来拟合模型。我们将验证数据设置为 X_val 和 y_val。

声音的机器学习。使用 Keras 拟合 CNN 的类型分类。

我们对该模型进行 10 个时期的训练,并获得以下结果:

声音的机器学习。CNN 用于类型分类的 Epocs。图片作者。

显示模型历史

检查训练历史的一个更好的方法是制作一个非常普通的图表,显示各个时期的训练准确性和验证准确性。为此,您可以使用以下代码:

声音的机器学习。创造历史情节。

对于当前的 CNN,我们得到下面的图表。它表明训练精度在上升:模型在学习一些东西。然而,验证精度并没有提高多少,这表明该模型需要一些调整才能变得有用。

声音的机器学习。准确性图表。作者配图。

结论和改进模型的下一步措施

在本文中,您看到了用 Python 处理声音数据的简单易懂的管道。您已经学习了如何将 mp3 文件中的数据准备到 NumPy 数组中。您还看到了如何开始与 CNN 合作,基于这些数据构建一个流派分类模型。

我希望这篇文章已经让你很好地理解了体裁分类管道的不同元素,并且给你在这个领域更进一步的基础知识。

如果你想在这个模型上更进一步,让我给你一些建议。您可以处理数据(更多的歌曲、更多的流派、查看每首歌曲的片段数量和片段长度),也可以处理模型(尝试其他架构、其他超参数等)。

现在,我想感谢你的阅读。不要犹豫,继续关注更多的统计、数学、ML 和数据科学内容!

机器学习“触礁”🥃

原文:https://towardsdatascience.com/machine-learning-on-the-rocks-f49f75219c02?source=collection_archive---------13-----------------------

实践教程

威士忌数据集~ K 均值聚类、逻辑回归和 EDA

“永远带一壶威士忌以防被蛇咬,此外,永远带一条小蛇。”|厕所区域

照片由 PublicDomainPicturesPixaBay 上拍摄

显然,这个项目的领域依赖于世界上最受欢迎的酒——威士忌。一种来自各种谷物的黑暗之神,在世界各地蒸馏,并形成了相当多的风格(爱尔兰、苏格兰、波旁等)[1]。苏格兰、爱尔兰、加拿大&日本是著名的出口国,在国际范围内,全球产量几乎达到 9500 万美元的收入水平[2]。

这里的主要范围是以一种…“友好”的方式介绍,聚类算法在任何我们需要在(大)数据集中发现模式的时候是多么有用。实际上,它可能被认为是标准探索性数据分析(EDA)的强大扩展,在使用监督机器学习(ML)模型之前,尝试这种分析通常非常有益。最后还实现了后者的预测情况(逻辑回归)。

概念

在成功调谐了一个音乐播放列表“the-Python-way”后,我工作的数据公司接受了一个新项目:协助一家知名威士忌供应商实现多样化。也就是说,要弄清楚哪些威士忌品种卖得更好,并记住这一点,进行适当的合并/收购,以促进销售。然而,主要的障碍是供应商没有任何来自竞争对手的销售数据(也就是潜在的收购目标)。但是:

如何使用威士忌相关数据,包括任何属性(如年份、口味、类型、价格等),以一种对供应商有意义的方式对其进行分类,并最终指导他们应该购买哪些特定的葡萄酒?

为了更好地交流结果,提出了一些假设:

1:为了给我们的分析定义一组足够的数据,我使用了来自 Kaggle 的一个相关数据集——一个几乎任何种类数据的显著来源。

2:我使用的酒类属性是:威士忌的namecategoryrating、&、description,同时开发了几个新的属性(见第 2 节)。

3:代替任何与销售相关的数据,完成我们任务的唯一方法是发现潜在的“潜在”模式,这些模式可能导致供应商巧妙地增加销售量。Id est,保存可销售的品种,而不仅仅是出售最贵或最高等级的瓶子。

作案手法

  1. 设置环境来运行代码。
  2. 使用 Numpy,Pandas &执行 EDA 一些额外的 Python 库。
  3. 通过使 K-Means 聚类算法适合数据集,揭示额外的数据模式。
  4. 使用现在已标记的数据集(clusters = labels),实施多分类技术— 逻辑回归 —对新的列表(威士忌)进行预测。

1.建立

在这一节中,我们将设置所需的环境,以便应用分析技术。

  • 安装 Jupyter 笔记本——一个开源网络应用程序,用于创建/共享包含实时代码、方程式、可视化和叙述性文本的文档。你可以在这里按照步骤进行
  • 安装Requests/beautiful soup——一个 Python 模块,分别用于处理 API 和从 HTML 和 XML 文件中提取数据。您可以使用 CLI(命令行界面)或 Jupyter 笔记本来运行以下命令:

install.py

  • 导入必要的库:

import.py

2.数据清理

第一部分包括将数据读入 DataFrame 对象df_init

“df_init”数据集的预览

接下来,我们采取一系列必要的措施,为进一步的分析做好准备。最重要的是,我们:

  • 检查空值(无空值)/删除冗余列(Unnamed:currency)。
  • price转换为浮点型。
  • 检查与name列相关的重复项,并用平均值[ categoryratingprice ]替换这些列表。
  • 通过使用特定的正则表达式,从name列中提取新的特性agealcohol

data_cleaning.py

“df”数据集的预览

3.电子设计自动化(Electronic Design Automation)

为了减少杂乱,我在这里不包括数据可视化代码,但是在 GitHub 资源库 上有。

一.明显的洞察力📕

首先,我们检查数据集以确认任何明显的推论。变量(description除外)是定量的,同时也属于测量的比率尺度。因此,盒须图可以有效地描述每个特征的个体分布,并与描述性统计表(通过pandas.DataFrame.describe方法)一起,可以为我们提供一个很好的视觉直觉,即落入每个特定四分位数的值的比例(*price* 具有很大的值范围,因此单独绘制)。

“df”描述性统计和箱线图

  • rating变量从 70%开始(相当倾斜,因此没有坏威士忌,如前所述!)而平均评论在 87%左右。
  • 正如所料(对于威士忌而言),T7 和 T8 分别从 3 年和 40%开始,前者的平均值为 20 年。
  • 考虑到price特征,苏格兰威士忌的平均价格(黄色▲)为 700 美元,而中位数(红线)为 108 美元。这清楚地表明分布是右偏的。然而,突出显示的是从 10 到 157.000 美元的范围!

按照假设#3(见上文),没有销售数据可用,不可避免地,我们必须操纵现有的功能。我们建立了以下“机制”:

供应商对提高利润率感兴趣,因此拉开了[price - cost]的差距。除了右偏之外,price本身不能作为供应商的决策因素,因为销售额外昂贵的瓶子也意味着额外的采购成本。

发现 1:我们不应该将price作为一个决策因素。最终,我们必须捕捉特征之间的任何相互关系,这可能揭示是哪种力量推动销售(和利润)上升。

二。深刻的见解📙

通过“成对地”检查变量,我们可以捕捉它们之间有用的关系。散点图矩阵能够显示变量组合之间的二元关系。

df 散布矩阵

皮尔逊相关系数表

用皮尔逊相关系数解释矩阵,我们得到的最深刻的发现如下:

  • 最令人兴奋的发现是,好的rating不一定伴随着高的 a price (cor = 0.12)。换句话说,花更少的钱享受高质量的苏格兰威士忌是很有潜力的——很划算。
  • agerating (cor = 0,32)之间也有很好的关系。
  • 最高的相关性(cor = 0,33)出现在priceage之间;超贵的瓶子属于陈年酒。但是,很明显,如果供应商选择收购一家生产超成熟威士忌的公司,他们可能会出售极其昂贵的酒类,从而影响其品种分布:

成熟 _ 威士忌 _ 价格. py

186    60000.0
739    60000.0
182    60000.0
82     30000.0
699    27620.0
29     26650.0
102    25899.0
397    25899.0
103    25899.0
816    25899.0
Name: price, dtype: float64

所以,除了排除price ( 发现#1 )我们还应该排除age*alcohol*

发现#2:因此,我们应该专注于rating功能,这预计会对供应商的利润产生巨大影响(更受欢迎的威士忌意味着更高的销售额)。

三。更深刻的见解📒

寻找一种可以启发供应商主要推销什么瓶子的模式(为了获得更高的利润),我们将通过category属性分析“卡瓦”,同时也“启发”了rating特征。

groupby_category.py

按“类别”分组的平均特征

按“类别”分组的“评级”方框图

混合麦芽在rating中领先,简单混合紧随其后,前者的平均值高出 0.23%(88,11–87,88)。值得注意的是,混合麦芽的中位数远远高于第二个四分位数(平均值),因此超过 50%的瓶子被评为高于平均值(88%)。这是一个不错的见解,我们可以为供应商提供…

发现#3:供应商可能会选择提高混合麦芽的销量。这样,由于这种威士忌的流行,他们可能会实现更大的销售,从而享受更高的利润。

⚠️:但是,我们仍然违反了条件 3(保持威士忌的多样性)——这个问题我们还没有很好地解决。因此,我们不再推荐混合(且只有混合)的瓶子,而是努力向顾客保证多样性,转而采用一种新的、更全面的聚类方式。

4.k 均值聚类

在无监督学习中,我们在数据中寻找模式,而不是在有监督的 ML 中进行预测。在这种情况下,当可能存在多个(不可见的)组时,聚类算法能够将相似的行分组在一起。这些组形成了我们可以看到的,并开始更好地理解数据的结构。 K-Means 聚类 是一种流行的基于质心的聚类算法。

k 指的是我们想要对数据进行分段的聚类数,必须提前声明。在可用的估算方法中,我们将使用 肘方法 ,根据该方法:

  1. 我们对不同的 k(这里从 1 到 10)运行该算法。
  2. 对于每次迭代,我们计算组内平方和(WCSS ),并将其存储在各自的列表中。
  3. 我们绘制了 WCSS~#团簇的 k 关系。
  4. 我们定位“肘部”——线下降更平滑后的闭合区域(名为 kneed 的源代码 Python 库对此很有用)。

locate _ 肘部. py

在切换到由 1.355 份威士忌组成的无空值(df_no_nulls)的新数据框架后,我们绘制了 WCCS 线。

类内平方和(WCSS)~类图

最佳的聚类数目是 3,我们准备实现 K-Means 聚类。

kmeans.py

该模型展示了以下聚类和{瓶数},分别为:聚类 0 {# 353}、聚类 1 {# 363} & 聚类 2 {# 639}。检查相关的箱线图以及第 3 节的那些图,我们推导出以下…

按“聚类”分组的“评级”箱线图

(第 3 节)评级'箱线图按类别'分组

四。顶级见解📗

✔️聚类揭示了一个更清晰的迹象,即哪种威士忌能促进rating(以及销售)。与先前分析的类别相比,查看新的分类如何区分自己。

rating而言,✔️1 号集群要好得多。不仅平均值领先于其余的,而且它的中值位于最右边,这意味着至少有一半的集群的瓶子超过了这个显著的值(89.33%)。

✔️与此同时,第一类包括单一麦芽苏格兰威士忌、混合苏格兰威士忌和混合麦芽苏格兰威士忌,因此保证了多样性!

✔️迄今为止,该分析考虑了比先前尝试的(*rating*)更多的特征(ratingalcoholage),证明了聚类促进了来自更多分量的信号的数据的更全面分离的观点。

把它们都放到同一个空间,我们就可以看到一个 3D 散点图。实际上,我们勉强能够做到这一点,因为对于 3 个以上的变量,必须先进行降维处理(如 PCA 等)。

“聚类”三维散点图

非常突出的是,簇#1(红色)“占据”y 轴的较高区域(rating)。此外,如果我们将数据标准化,我们可以绘制雷达图。通过说明红色多边形如何更好地“关注”几乎所有的特征,这可以进一步帮助解释结果。

按“集群”分组的特征雷达图

5.逻辑回归

受监督的 ML 拿起火炬,现在我们的数据集被标记为(聚类)。我们的目标是训练一个模型,给定一个新列表(威士忌)的 3 个特征[ratingalcoholage,它将预测它的标签(又名聚类)。这样,供应商将能够直接对其进行分类,并推断其是否有商业化的“潜力”!

像这样的多分类问题,在首先应用一些调整之后,可以用一个逻辑回归模型来解决。特别是,我们将实现一对一对所有方法,其中我们选择一个类别(即集群#1)作为正面案例,并将其余的作为错误案例分组,迭代。每个产品模型都是一个二元分类模型,将返回一个概率[0-1]。当应用新数据时,我们选择与预测最高概率的模型相对应的标签。

logistic _ 回归. py

准确率达到了 98.9%,这意味着 100 个新酒类条目中几乎有 98 个可以成功归类到我们开发的 3 个聚类之一。

结论

最终,我们到达了目的地;从外观到对威士忌“类型”的全面洞察,都有助于培养供应商的创业精神。

从 Kaggle 的数据集开始,我们逐渐从简单的 EDA 发展到无监督的 ML 模型(K-Means)。这样,我们揭示了有见地的模式,这有助于我们更好地识别真正需要什么来提高威士忌的销量。最后,我们在标记的数据集上拟合了一个逻辑回归模型,以高精度预测了一个新瓶子可能注册到的簇。

尼克·里克顿在 Unsplash上的照片

我把这篇文章献给我的好朋友科斯塔斯和帕诺斯;在疫情之前,我们过去常常在周五品尝新的麦芽酒……实际上,在数量“领域”之外,不是price而是让威士忌更美味的好公司……所以,为我们的下一次“回顾会议”干杯!

感谢您的阅读。回购调味并准备运行🥃!

参考文献

[1]https://www.thespruceeats.com/history-of-whisky-1807685

[2]https://www . statista . com/outlook/10020100/100/whiskey/world wide # market-global revenue

[3]https://machine learning mastery . com/logistic-regression-for-machine-learning/

机器学习管道

原文:https://towardsdatascience.com/machine-learning-pipelines-4cab73603ea2?source=collection_archive---------19-----------------------

拉斯·金勒在 Unsplash r

使用 SkLearn-Pandas 自动化机器学习工作流

机器学习工作流包括从原始数据构建机器学习模型所需的所有步骤。这些过程可以分为转换和培训阶段。

转换阶段包括将原始数据转换为特征(特征工程)所需的过程,而训练阶段封装了使用特征来构建机器学习模型的过程。

真实世界数据的混乱通常使特征工程成为机器学习中最具挑战性和最关键的步骤,尤其是在处理来自不同来源的海量数据流时。在这种情况下,特征工程过程可以包括将不同的原始数据映射到机器学习特征的多个重复且不同的步骤。处理此类任务的一种有效方式是使用特征管线。

特征管线是用于将多个、重复且不同的特征工程过程自动应用于原始数据的框架,顺序且连续。

当设计了特征管线时,它们可以与机器学习算法合并,以创建机器学习管线,其自动化机器学习工作流;从转换数据到构建评估器。

我们将使用一个简单的数据集作为介绍性示例,来实践如何利用管道来高效、轻松地使用原始数据来构建估算器。

我们将使用一个假想的“收入”数据集,其中包含员工的年龄、职称、最高学历和年收入,以展示如何利用管道高效、轻松地转换原始数据来构建估值器。我们的目标是设计和执行一个机器学习管道,使用 SkLearn-Pandas 库实现数据转换和构建过程的自动化。

首先,让我们看一下数据集。

雇员年龄、职称和资格的样本数据。(图片由作者提供)。

很明显,在将数据输入算法进行训练之前,我们需要对这些数据进行一定的转换。下表描述了使用这些数据构建模型所需的过程。你可以查看我在特性工程技术上的帖子,了解为什么选择这些特定的方法进行转换的更多细节。

显示要应用于数据的转换的表。(图片由作者通过 Sheetsu.com 提供)。

接下来,我们将定义一个机器学习管道,以自动将这些过程应用于数据。我们将使用 SkLearn-Pandas 的 DataFrameMapper 和 SkLearn 的预处理方法来完成这项工作。

然后,定义的流水线可以用于使用特征和目标变量来训练算法。

我们已经成功地开发了一个管道来自动化机器学习工作流,这样它也可以用于转换其他具有类似结构的数据流。您还可以将管道传递给 RandomSearchCV 或 GridSearchCV 进行超参数调优。

摘要

机器学习管道对于自动化数据转换和构建评估器的迭代过程是有用的。管线提供了有效的方法来自动将特定的或不同的变换应用于特定的或大量的输入特征。Sklearn 和 SkLearn-Pandas 等 Python 库提供了定义和执行机器学习管道的便捷方法。

机器学习:预测银行贷款违约

原文:https://towardsdatascience.com/machine-learning-predicting-bank-loan-defaults-d48bffb9aee2?source=collection_archive---------0-----------------------

一种数据科学方法,用于预测和了解申请人的情况,以最大限度地降低未来贷款违约的风险。

Unsplash 上的absolute vision拍摄

关于项目

该数据集包含有关信贷申请人的信息。在全球范围内,银行使用这种数据集和信息数据类型来创建模型,以帮助决定接受/拒绝谁的贷款。

在所有探索性的数据分析、清理和处理我们可能(将)发现的所有异常之后,好/坏申请人的模式将暴露出来,供机器学习模型学习。

机器学习问题和目标

我们正在处理一个有监督的二进制分类问题。目标是训练最佳的机器学习模型,以最大限度地提高深入了解过去客户概况的预测能力,最大限度地降低未来贷款违约的风险。

绩效指标

鉴于我们正在处理一个高度不平衡的数据,用于模型评估的指标是 ROC AUCT5。

项目结构

该项目分为三类:

  1. 探索性数据分析
  2. 数据争论:清理和特征选择
  3. 机器学习:预测建模

数据集

你可以在这里下载数据集

功能描述

  • id :贷款申请的唯一 id。
  • 等级 : LC 指定的贷款等级。
  • annual_inc :借款人在登记时提供的自报年收入。
  • short_emp : 1 年或 1 年以下雇佣。
  • emp_length_num :任职年限。可能的值介于 0 和 10 之间,其中 0 表示不到一年,10 表示十年或更长时间。
  • 房屋所有权:房屋所有权的类型。
  • dti(债务收入比):用借款人每月总债务支付额除以借款人自报月收入计算的比率,不包括抵押贷款和要求的信用证贷款。
  • 用途:借款人针对贷款请求提供的类别。
  • 期限:贷款的还款次数。值以月为单位,可以是 36 或 60。
  • last _ deliq _ none:1 借款人至少发生一次违约事件。
  • last_major_derog_none : 1 借款人至少有 90 天的不良评级。
  • revol_util :循环额度利用率,或借款人相对于所有可用循环信贷的信贷金额。
  • total_rec_late_fee :到目前为止收到的滞纳金。
  • od_ratio :透支比率。
  • bad_loan : 1 一笔贷款未支付时。

照片由 Ashutosh DaveUnsplash 上拍摄

导入所需的库和依赖项:

import pandas as pd
import numpy as np
import seaborn as sns
import pingouin as pgimport scipy
from scipy.stats import chi2
from scipy.stats import chi2_contingency
from scipy.stats import pearsonr, spearmanrfrom sklearn.preprocessing import StandardScaler
from sklearn.preprocessing import MinMaxScaler
from sklearn.model_selection import train_test_split
from sklearn.model_selection import GridSearchCV
from sklearn.ensemble import RandomForestClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.neighbors import KNeighborsClassifier
from sklearn.svm import SVC
from sklearn import tree
from sklearn.tree import export_graphviz
from sklearn.externals.six import StringIO
from sklearn.linear_model import Perceptron
from sklearn.neural_network import MLPClassifier
from sklearn.metrics import  precision_recall_curve, roc_auc_score, confusion_matrix, accuracy_score, recall_score, precision_score, f1_score,auc, roc_curve, plot_confusion_matrix​from category_encoders import BinaryEncoder
from IPython.display import Image
import pydotplusimport matplotlib.pyplot as plt
%matplotlib inline
color = sns.color_palette()seed = 42

加载并显示数据集:
>> data = pd.read_csv('lending_club_loan_dataset.csv', low_memory=False)
>> data.head()

( data.shape (20000,15) )。图片作者。

EDA:实验数据分析

主要数值属性统计:

(数字属性)。图片作者。

该数据集有 2000 个观察值和 15 个变量,包括目标,分为 11 个数字特征和 4 个类别特征。

有缺少值的变量:“home_ownership”为 7.46%,“dti”为 0.77%,“last_major_derog_none”为 97.13%。

根据平均值和中值之间的差异,以及变量“年度收入”、“革命效用”和“总收入延迟费用”的最大值的距离,似乎存在一些异常值。

类别属性统计:
>> data.describe(include=[np.object])

(分类属性)。图片作者。

**# Checking data balance/proportion**loan = data.bad_loan.value_counts().to_frame().rename(columns={"bad_loan":"absolute"})loan["percent"] = (loan.apply(lambda x: x/x.sum()*100).round(2))display(loan)---**​# pie chart**data.bad_loan.value_counts().plot(kind='pie', subplots=True, autopct='%1.2f%%', explode= (0.05, 0.05), startangle=80, legend=True, fontsize=12, figsize=(14,6), textprops={'color':"black"})plt.legend(["0: paid loan","1: not paid loan"]);

(饼状图)。图片作者。

不平衡数据: target 有 80%的违约结果(值 1),而有 20%的贷款以已支付/非违约(值 0)结束。

类型的变量:
>> data.dtypes.sort_values(ascending=True)

id                         int64
short_emp                  int64
emp_length_num             int64
last_delinq_none           int64
bad_loan                   int64
annual_inc               float64
dti                      float64
last_major_derog_none    float64
revol_util               float64
total_rec_late_fee       float64
od_ratio                 float64
grade                     object
home_ownership            object
purpose                   object
term                      object
dtype: object

Couting 变量按类型:
>> data.dtypes.value_counts()

float64    6
int64      5
object     4
dtype: int64

检查缺失值:

nulval = data.isnull().sum().to_frame().rename(columns={0:"absolute"})nulval["percent"] = (nulval.apply(lambda x: x/x.sum())*100).round(2)nulval

(缺失值)。图片作者。

EDA 功能

使用和滥用图形描述数据集中的所有要素。首先为每个图表定义一些函数:箱线图、直方图、条形图和饼图、散点图、数据透视图以及统计描述。

**# General statistics** def stats(x):
    print(f"Variable: {x}")
    print(f"Type of variable: {data[x].dtype}")
    print(f"Total observations: {data[x].shape[0]}")
    detect_null_val = data[x].isnull().values.any()
    if detect_null_val:
        print(f"Missing values: {data[x].isnull().sum()} ({(data[x].isnull().sum() / data[x].isnull().shape[0] *100).round(2)}%)")
    else:
        print(f"Missing values? {data[x].isnull().values.any()}")
    print(f"Unique values: {data[x].nunique()}")
    if data[x].dtype != "O":
        print(f"Min: {int(data[x].min())}")
        print(f"25%: {int(data[x].quantile(q=[.25]).iloc[-1])}")
        print(f"Median: {int(data[x].median())}")
        print(f"75%: {int(data[x].quantile(q=[.75]).iloc[-1])}")
        print(f"Max: {int(data[x].max())}")
        print(f"Mean: {data[x].mean()}")
        print(f"Std dev: {data[x].std()}")
        print(f"Variance: {data[x].var()}")
        print(f"Skewness: {scipy.stats.skew(data[x])}")
        print(f"Kurtosis: {scipy.stats.kurtosis(data[x])}")
        print("")

        **# Percentiles 1%, 5%, 95% and 99%**print("Percentiles 1%, 5%, 95%, 99%")
        display(data[x].quantile(q=[.01, .05, .95, .99]))
        print("")
    else:
        print(f"List of unique values: {data[x].unique()}")---**# Variable vs. target chart** def target(x):
    short_0 = data[data.bad_loan == 0].loc[:,x]
    short_1 = data[data.bad_loan == 1].loc[:,x]

    a = np.array(short_0)
    b = np.array(short_1)

    np.warnings.filterwarnings('ignore')

    plt.hist(a, bins=40, density=True, color="g", alpha = 0.6, label='Not-default', align="left")
    plt.hist(b, bins=40, density=True, color="r", alpha = 0.6, label='Default', align="right")plt.legend(loc='upper right')
    plt.title(x, fontsize=10, loc="right")
    plt.xlabel('Relative frequency')
    plt.ylabel('Absolute frequency')
    plt.show()---​**# Boxplot + Hist chart** def boxhist(x):
    variable = data[x]
    np.array(variable).mean()
    np.median(variable)f, (ax_box, ax_hist) = plt.subplots(2, sharex=True, gridspec_kw= {"height_ratios": (0.5, 2)})
    mean=np.array(variable).mean()
    median=np.median(variable)sns.boxplot(variable, ax=ax_box)
    ax_box.axvline(mean, color='r', linestyle='--')
    ax_box.axvline(median, color='g', linestyle='-')sns.distplot(variable, ax=ax_hist)
    ax_hist.axvline(mean, color='r', linestyle='--')
    ax_hist.axvline(median, color='g', linestyle='-')plt.title(x, fontsize=10, loc="right")
    plt.legend({'Mean':mean,'Median':median})
    ax_box.set(xlabel='')
    plt.show()---**# Histogram** def hist(x):
    plt.hist(data[x], bins=25)
    plt.title(x, fontsize=10, loc="right")
    plt.xlabel('Relative frequency')
    plt.ylabel('Absolute frequency')
    plt.show()---**# Pie chart** def pie(x):
    data[x].value_counts(dropna=False).plot(kind='pie', figsize=(6,5), fontsize=10, autopct='%1.1f%%', startangle=0, legend=True, textprops={'color':"white", 'weight':'bold'});**# Number of observations by class** obs = data[x].value_counts(dropna=False)
o = pd.DataFrame(obs)
o.rename(columns={x:"Freq abs"}, inplace=True)
o_pc = (data[x].value_counts(normalize=True) * 100).round(2)
obs_pc = pd.DataFrame(o_pc)
obs_pc.rename(columns={x:"percent %"}, inplace=True)
obs = pd.concat([o,obs_pc], axis=1)
display(obs)---​**# Variable vs. target chart** def target(x):
    short_0 = data[data.bad_loan == 0].loc[:,x]
    short_1 = data[data.bad_loan == 1].loc[:,x]

    a = np.array(short_0)
    b = np.array(short_1)

    np.warnings.filterwarnings('ignore')

    plt.hist(a, bins=40, density=True, color="g", alpha = 0.6, label='Not-default', align="left")
    plt.hist(b, bins=40, density=True, color="r", alpha = 0.6, label='Default', align="right")plt.legend(loc='upper right')
    plt.title(x, fontsize=10, loc="right")
    plt.xlabel('Relative frequency')
    plt.ylabel('Absolute frequency')
    plt.show()---​**# Boxplot + Hist chart** def boxhist(x):
    variable = data[x]
    np.array(variable).mean()
    np.median(variable)f, (ax_box, ax_hist) = plt.subplots(2, sharex=True, gridspec_kw= {"height_ratios": (0.5, 2)})
    mean=np.array(variable).mean()
    median=np.median(variable)sns.boxplot(variable, ax=ax_box)
    ax_box.axvline(mean, color='r', linestyle='--')
    ax_box.axvline(median, color='g', linestyle='-')sns.distplot(variable, ax=ax_hist)
    ax_hist.axvline(mean, color='r', linestyle='--')
    ax_hist.axvline(median, color='g', linestyle='-')plt.title(x, fontsize=10, loc="right")
    plt.legend({'Mean':mean,'Median':median})
    ax_box.set(xlabel='')
    plt.show()----**# Bar chart** def bar(x):
    ax = data[x].value_counts().plot(kind="bar", figsize=(6,5), fontsize=10, color=sns.color_palette("rocket"), table=False)
    for p in ax.patches:
        ax.annotate("%.2f" % p.get_height(), (p.get_x() + p.get_width() / 2., p.get_height()), ha='center', va='center', xytext=(0, 5), textcoords='offset points')plt.xlabel(x, fontsize=10)
    plt.xticks(rotation=0, horizontalalignment="center")
    plt.ylabel("Absolute values", fontsize=10)
    plt.title(x, fontsize=10, loc="right")

---

**# Barh chart** def barh(x):
    data[x].value_counts().plot(kind="barh", figsize=(6,5), fontsize=10, color=sns.color_palette("rocket"), table=False)
    plt.xlabel("Absolute values", fontsize=10)
    plt.xticks(rotation=0, horizontalalignment="center")
    plt.ylabel(x, fontsize=10)
    plt.title(x, fontsize=10, loc="right")---

**# Pivot_table_mean** def pivot_mean(a, b, c):
    type_pivot_mean = data.pivot_table(
        columns=a,
        index=b,
        values=c, aggfunc=np.mean)
    display(type_pivot_mean)**# Display pivot_table**
    type_pivot_mean.sort_values(by=[b], ascending=True).plot(kind="bar", title=(b), figsize=(6,4),fontsize = 12);**# Pivot_table_sum** def pivot_sum(a, b, c):
    type_pivot_sum = data.pivot_table(
        columns=a,
        index=b,
        values=c, aggfunc=np.sum)
    display(type_pivot_sum)# **Display pivot_table**
    type_pivot_sum.sort_values(by=[b], ascending=True).plot(kind="bar", title=(b), figsize=(6,4),fontsize = 12);---

**# Scatter plot**
def scatter(x, y):
    targets = data["bad_loan"].unique()for target in targets:
        a = data[data["bad_loan"] == target][x]
        b = data[data["bad_loan"] == target][y]plt.scatter(a, b, label=f"bad loan: {target}", marker="*")

    plt.xlabel(x, fontsize=10)
    plt.ylabel(y, fontsize=10)
    plt.title("abc", fontsize=10, loc="right")
    plt.legend()
    plt.show()

数值分布的可视化:

data.hist(figsize=(10,9), bins=12, ec="b", xlabelsize=8, ylabelsize=8, alpha=0.9, grid=False)plt.tight_layout()
plt.show()

(数值分布)。图片作者。

类别分布的可视化:

for col in data.select_dtypes(include=["object"]).columns:
    data[col].value_counts().plot(kind="bar", color=sns.color_palette("rocket"))

    plt.xlabel("Class", fontsize=10)
    plt.xticks(rotation=90, horizontalalignment="center")
    plt.ylabel("Count", fontsize=10)
    plt.title(col, fontsize=10, loc="right")
    plt.show()

()【分类分布】))。图片作者。

在“36 个月”这一课中,变量“term”似乎有一个打印错误。让我们通过降低大写字符来修复它。

>> data.term = data.term.str.lower()
>> data.term.value_counts()36 months    15001
 60 months     4999
Name: term, dtype: int64

功能:等级

LC 指定的贷款等级。

stats("grade")Variable: grade
Type of variable: object
Total observations: 20000
Missing values? False
Unique values: 7
List of unique values: ['A' 'D' 'E' 'B' 'G' 'C' 'F']---bar("grade")

()。作者图片

pivot_sum("home_ownership","grade","id")

( pivot_sum )。作者图片

( pivot_sum )。作者图片

当等级级别降低时,房屋所有权的类型倾向于从抵押贷款转向租赁。在 B 级、C 级和 D 级上,我们把自己的礼仪类型视为最高等级。

target("grade")

(目标)。作者图片

最高的非违约贷款发生在高等级阶层之间。

功能:年度 _ 公司

借款人在登记时提供的自报年收入。

boxhist("annual_inc")

( boxhist )作者图片

stats("annual_inc")Variable: annual_inc
Type of variable: float64
Total observations: 20000
Missing values? False
Unique values: 2566
Min: 8412
25%: 47000
Median: 65000
75%: 88000
Max: 1000000
Mean: 73349.57835
Std dev: 45198.56725472537
Variance: 2042910481.8799326
Skewness: 5.275648123592321
Kurtosis: 66.72665803201564

Percentiles 1%, 5%, 95%, 99%0.01     20519.5
0.05     30000.0
0.95    145000.0
0.99    225000.0
Name: annual_inc, dtype: float64---target("annual_inc")

(目标)图片作者

直方图告诉我们,收益越高,违约趋势越高。

scatter("annual_inc","dti")

(散开)。作者图片

散点图显示了“年收入”和“债务收入比”之间微弱的负相关。

data.annual_inc.corr(dti)
>> -0.22853314935876534

相关值为-0.23 ,表示随着年度 _inc 减少,实例 1(违约/未支付)的贷款增加。

功能:short_emp

1 当雇佣期为 1 年或更短时。

hist("short_emp")

( hist )图片作者

受雇一年或一年以下的客户(实例 1)占 11.25%,而 88.75%的客户受雇一年以上。

stats("short_emp")Variable: short_emp
Type of variable: int64
Total observations: 20000
Missing values? False
Unique values: 2
Min: 0
25%: 0
Median: 0
75%: 0
Max: 1
Mean: 0.1125
Std dev: 0.3159885163057429
Variance: 0.09984874243710473
Skewness: 2.4526820936006293
Kurtosis: 4.015649452269171

Percentiles 1%, 5%, 95%, 99%0.01    0.0
0.05    0.0
0.95    1.0
0.99    1.0
Name: short_emp, dtype: float64---target("short_emp")

(目标)图片作者

雇用时间少于 1 年的部门比其他部门更经常出现贷款违约。

特征:雇员长度数量

雇佣年限。可能的值介于 0 和 10 之间,其中 0 表示不到一年,10 表示十年或更长时间。

boxhist("emp_length_num")

( boxhist )。作者图片

stats("emp_length_num")Variable: emp_length_num
Type of variable: int64
Total observations: 20000
Missing values? False
Unique values: 12
Min: 0
25%: 3
Median: 7
75%: 11
Max: 11
Mean: 6.8214
Std dev: 3.7742302898357223
Variance: 14.24481428071344
Skewness: -0.27964924120655704
Kurtosis: -1.3664296257576731

Percentiles 1%, 5%, 95%, 99%0.01     0.0
0.05     1.0
0.95    11.0
0.99    11.0
Name: emp_length_num, dtype: float64---target("emp_length_num")

(目标)。作者图片

除了少数例外,这种非违约贷款发生在 10 年以上不间断工作的客户中。

pivot_mean("bad_loan", "purpose", "emp_length_num")

( pivot_mean )。作者图片

平均而言,结婚和度假是大多数贷款最终未能偿还的两个目的。

特征:房屋所有权

房屋所有权的类型。

stats("home_ownership")Variable: home_ownership
Type of variable: object
Total observations: 20000
Missing values: 1491 (7.46%)
Unique values: 3
List of unique values: ['RENT' 'OWN' 'MORTGAGE' nan]---bar("home_ownership")

()。作者图片

pie("home_ownership")

()。作者图片

pivot_sum("bad_loan", "home_ownership", "id")

( pivot_sum )。作者图片

从比例上来说,房屋所有权和违约贷款之间没有太大的区别。

特征:债务收入比

使用借款人每月总债务付款对总债务(不包括抵押贷款和要求的 LC 贷款)除以借款人自我报告的月收入计算的比率。

boxhist("dti")

( boxhist )。作者图片

stats("dti")Variable: dti
Type of variable: float64
Total observations: 20000
Missing values: 154
Unique values: 3295
Min: 0
25%: 10
Median: 16
75%: 22
Max: 34
Mean: 16.58784137861536
Std dev: 7.585811951545168
Variance: 57.544542964205505
Skewness: nan
Kurtosis: nan

Percentiles 1%, 5%, 95%, 99%0.01     1.7800
0.05     4.6500
0.95    29.6900
0.99    33.4355
Name: dti, dtype: float64---target("dti")

(目标)。作者图片

平均而言,与良好贷款相比,不良贷款(违约)的分布具有更高的“dti”值(债务收入比)。趋势是:努力率越高,贷款违约越频繁。

pivot_sum("home_ownership", "purpose", "dti")

( pivot_sum )。作者图片

众所周知,申请贷款的主要目的是“债务合并”,其次是“信用卡”,分别有超过 6000 人和 4000 人申请“抵押”和“自有”房屋所有权。

另一方面,“搬家”和“婚礼”以及 19 和 47 在所有权类型的两个相同部分中较少声明的目的。对于那些住在租来的房子里的人来说,申请贷款的人在比例上要少得多。

( pivot_sum )。作者图片

pivot_sum("bad_loan", "grade", "dti")

( pivot_mean )。作者图片

趋势是,当年级减少时,拖欠贷款的可能性增加。

功能:用途

借款人为贷款请求提供的类别。

stats("purpose")Variable: purpose
Type of variable: object
Total observations: 20000
Missing values? False
Unique values: 12
List of unique values: ['credit_card' 'debt_consolidation' 'medical' 'other' 'home_improvement'
 'small_business' 'major_purchase' 'vacation' 'car' 'house' 'moving'
 'wedding']---barh("purpose")

( barh )。作者图片

pivot_sum("bad_loan", "purpose", "id")

( pivot_sum )。作者图片

功能:术语

贷款的付款次数。值以月为单位,可以是 36 或 60。

pie("term")

()。作者图片

target("term")

(目标)。作者图片

违约贷款发生相反,更频繁地超过 60 个月的期限。

pivot_mean("term", "grade", "annual_inc")

( pivot_mean )。作者图片

平均而言,36 个月的期限在债务收入比最高的客户中最常见,这些客户属于最低等级类别。

特征:last _ delinq _ none

1 借款人至少有一次违约事件。

target("last_delinq_none")

(目标)。作者图片

pie("last_delinq_none")

()。作者图片

stats("last_delinq_none")Variable: last_delinq_none
Type of variable: int64
Total observations: 20000
Missing values? False
Unique values: 2
Min: 0
25%: 0
Median: 1
75%: 1
Max: 1
Mean: 0.5466
Std dev: 0.49783614979391533
Variance: 0.24784083204162968
Skewness: -0.18721487004502552
Kurtosis: -1.9649505924340243

Percentiles 1%, 5%, 95%, 99%0.01    0.0
0.05    0.0
0.95    1.0
0.99    1.0
Name: last_delinq_none, dtype: float64---pivot_mean("bad_loan","purpose","last_delinq_none")

( pivot_mean )。作者图片

平均而言,在度假和购房等贷款用途中,违约贷款更为常见。

特征:last_major_derog_none

1 名借款人至少有 90 天的不良评级。

bar("last_major_derog_none")

()。作者图片

stats("last_major_derog_none")Variable: last_major_derog_none
Type of variable: float64
Total observations: 20000
Missing values: 19426 (97.13%)
Unique values: 2
Min: 0
25%: 1
Median: 1
75%: 1
Max: 1
Mean: 0.759581881533101
Std dev: 0.42771012441406686
Variance: 0.18293595052629658
Skewness: nan
Kurtosis: nanPercentiles 1%, 5%, 95%, 99%0.01    0.0
0.05    0.0
0.95    1.0
0.99    1.0
Name: last_major_derog_none, dtype: float64---target("last_major_derog_none")

(目标)。作者图片

功能:革命 _ 实用

循环额度利用率,或借款人相对于所有可用循环信贷使用的信贷金额。

stats("revol_util")Variable: revol_util
Type of variable: float64
Total observations: 20000
Missing values? False
Unique values: 1030
Min: 0
25%: 38
Median: 57
75%: 73
Max: 5010
Mean: 55.95814805499972
Std dev: 42.117455872216155
Variance: 1773.880089148075
Skewness: 81.32716395041949
Kurtosis: 9569.242123791564Percentiles 1%, 5%, 95%, 99%0.01     2.699
0.05    14.500
0.95    91.800
0.99    97.300
Name: revol_util, dtype: float64---scatter("annual_inc", "revol_util")

(散开)。作者图片

客户的年收入越低,相对于所有可用的循环信贷,借款人使用的信贷额度就越高。

boxhist("revol_util")

( boxhist )。作者图片

特征:总费用

迄今收到的滞纳金。

stats("total_rec_late_fee")Variable: total_rec_late_fee
Type of variable: float64
Total observations: 20000
Missing values? False
Unique values: 166
Min: 0
25%: 0
Median: 0
75%: 0
Max: 96
Mean: 0.29062163999999996
Std dev: 3.1086544166442467
Variance: 9.663732282121781
Skewness: 14.299156408331024
Kurtosis: 262.30322072057277Percentiles 1%, 5%, 95%, 99%0.01     0.0
0.05     0.0
0.95     0.0
0.99    15.0
Name: total_rec_late_fee, dtype: float64---target("total_rec_late_fee")

(目标)。作者图片

scatter("annual_inc", "total_rec_late_fee")

(散点)图片作者。

data.total_rec_late_fee.corr(annual_inc)
>> -0.00975830114406848

年收入最低的客户是滞纳金比较多的客户,尤其是最高重的客户。

pivot_mean("bad_loan", "purpose", "total_rec_late_fee")

( pivot_mean )。作者图片

滞纳金在贷款用途中发生的频率更高,如房屋、小企业或度假。另一方面,婚礼和汽车是执行滞纳金最低的信贷目的。

特征:od_ratio

透支比例。

boxhist("od_ratio")

(博克斯特)。作者图片

stats("od_ratio")Variable: od_ratio
Type of variable: float64
Total observations: 20000
Missing values? False
Unique values: 20000
Min: 0
25%: 0
Median: 0
75%: 0
Max: 0
Mean: 0.5044303048872487
Std dev: 0.2877201586666063
Variance: 0.0827828897031371
Skewness: -0.02052095981509419
Kurtosis: -1.1914529752985776Percentiles 1%, 5%, 95%, 99%0.01    0.009887
0.05    0.051495
0.95    0.951616
0.99    0.990142
Name: od_ratio, dtype: float64---scatter("annual_inc", "od_ratio")

(散开)。作者图片

年收入最低的客户之间的透支率更高,同样的申请人涉及最频繁的拖欠贷款。

pivot_sum("bad_loan", "term", "od_ratio")

( pivot_sum )。作者图片

按比例来说,在违约贷款中,60 个月期限的透支比率较高。

特征:坏账

1 未支付贷款时。

stats("bad_loan")Variable: bad_loan
Type of variable: int64
Total observations: 20000
Missing values? False
Unique values: 2
Min: 0
25%: 0
Median: 0
75%: 0
Max: 1
Mean: 0.2
Std dev: 0.40001000037498174
Variance: 0.16000800039999288
Skewness: 1.4999999999999996
Kurtosis: 0.24999999999999956Percentiles 1%, 5%, 95%, 99%0.01    0.0
0.05    0.0
0.95    1.0
0.99    1.0
Name: bad_loan, dtype: float64---bar("bad_loan")

()。作者图片

相关

热图→皮尔逊方法

mask = np.triu(data.corr(), 1)plt.figure(figsize=(19, 9))sns.heatmap(data.corr(), annot=True, vmax=1, vmin=-1, square=True, cmap='BrBG', mask=mask);

(热图)。作者图片

热图显示变量之间存在一些正相关和负相关。

现在让我们找出哪些数字特征与目标最相关

bad_loan_c = pg.pairwise_corr(data, columns=['bad_loan'], method='pearson').loc[:,['X','Y','r']]bad_loan_c.sort_values(by=['r'], ascending=False)

与目标相关的数字特征。作者图片

与目标最相关的变量是‘DTI’,弱正相关,为 0.141884

热图→ 斯皮尔曼方法

data_spear = data.copy()data_spear.drop(["bad_loan"], axis=1, inplace=True)---spearman_rank = pg.pairwise_corr(data_spear, method='spearman').loc[:,['X','Y','r']]pos = spearman_rank.sort_values(kind="quicksort", by=['r'], ascending=False).iloc[:5,:]neg = spearman_rank.sort_values(kind="quicksort", by=['r'], ascending=False).iloc[-5:,:]con = pd.concat([pos,neg], axis=0)display(con.reset_index(drop=True))

10 个最相关的数值对(Spearman 方法)。作者图片

mask = np.triu(data_spear.corr(method='spearman'), 1)plt.figure(figsize=(19, 9))sns.heatmap(data_spear.corr(method='spearman'), annot=True, vmax=1, vmin=-1, square=True, cmap='BrBG', mask=mask);

(热图)。作者图片

通过绘制热图(spearman 方法),很容易理解变量“last_major_derog_none”和“last _ delinq _ none”是两个最相关的要素,具有最高的单调关系(60%)。尽管如此,' last_major_derog_none '有 19426 个缺失值(97%),这太多了。

在这种情况下,将从数据集中删除列“last_major_derog_none”以及所有的 nan 值。因此,下一个最相关的变量是“雇员长度数量”和“雇员长度数量”,斯皮尔曼值为-55%。

数据争论:清洗和特征选择

极端值

让我们检查数据并检查任何异常值。从选择和过滤数字和类别数据开始。

data_ca = data.select_dtypes(exclude=["int64","float64"]).copy()data_nu = data.select_dtypes(exclude=["object","category"]).copy()

#箱线图:可视化数值数据离散度

fig, axs = plt.subplots(ncols=3, nrows=4, figsize=(16, 8))
index = 0
axs = axs.flatten()for k,v in data_nu.items():
    sns.boxplot(y=k, data=data_nu, ax=axs[index], orient="h")
    index += 1
    plt.tight_layout(pad=0.4, w_pad=0.5, h_pad=5.0)

(箱线图)。作者图片

display(data.describe().loc[["mean","50%","std"]].loc[:,["annual_inc","revol_util","total_rec_late_fee"]])

图片作者。

当然,在变量‘年度 _ 公司’,‘革命 _ 效用’和‘总 _ 收入 _ 延迟 _ 费用’中有一些异常值。让我们检测并解决它们。

'年度公司'

print(data.annual_inc.describe())count      20000.000000
mean       73349.578350
std        45198.567255
min         8412.000000
25%        47000.000000
50%        65000.000000
75%        88000.000000
max      1000000.000000
Name: annual_inc, dtype: float64---boxhist("annual_inc")

( boxhist )。作者图片

图表和箱线图表明该变量在上四分位数之外有太多的数据点。异常值被绘制为超出盒状图须的那些单独的点。这里使用的方法是 IQR 分数

**# Dealing with the outliers through IQR score method**Q1 = data['annual_inc'].quantile(0.25)
Q3 = data['annual_inc'].quantile(0.75)IQR = Q3 - Q1data['annual_inc'] = data.annual_inc[~((data.annual_inc < (Q1 - 1.5 * IQR)) |(data.annual_inc > (Q3 + 1.5 * IQR)))]---print(data.annual_inc.describe())count     19074.000000
mean      66792.117857
std       27241.646991
min        8412.000000
25%       46000.000000
50%       62000.000000
75%       84000.000000
max      149000.000000
Name: annual_inc, dtype: float64---boxhist("annual_inc")

( boxhist )。作者图片

print(int(data_nu.annual_inc.describe()[0]) - int(data.annual_inc.describe()[0]),"outliers were removed with this operation.")**>> 926 outliers were removed with this operation.**

“革命”

print(data.revol_util.describe())count    20000.000000
mean        55.958148
std         42.117456
min          0.000000
25%         38.800000
50%         57.100000
75%         73.900000
max       5010.000000
Name: revol_util, dtype: float64---boxhist("revol_util")

( boxhist )。作者图片

图表和箱线图分析表明,该变量有一个远离上四分位数的数据点。

异常值被绘制为超出箱线图胡须的单个点,但这并不意味着上下四分位数之外的每个数据点都是异常值。

最好检查一下,并尽可能删除那个孤立点。

**# Dealing with the 5010.0 outlier**value = data.revol_util.quantile([.99999])
p = value.iloc[0]
data = data[data["revol_util"] < p]---print(data['revol_util'].describe())​count    19999.000000
mean        55.710434
std         23.380722
min          0.000000
25%         38.800000
50%         57.100000
75%         73.900000
max        128.100000
Name: revol_util, dtype: float64---boxhist("revol_util")

( boxhist )。作者图片

print(int(data_nu.revol_util.describe()[0]) - int(data.revol_util.describe()[0]),"outlier was removed with this operation.")**>> 1 outlier was removed with this operation.**

' total_rec_late_fee '

可视化数据离散度:

sns.boxplot(x=data['total_rec_late_fee'],data=data)plt.xlabel('total_rec_late_fee', fontsize=10)plt.show()

(箱线图)。作者图片

移除异常值:

value = data.total_rec_late_fee.quantile([.989])p = value.iloc[0]data = data[data["total_rec_late_fee"] < p]

检查结果:

sns.boxplot(x=data['total_rec_late_fee'],data=data)plt.xlabel('total_rec_late_fee', fontsize=10)plt.show()

(箱线图)。作者图片

尽管有大量数据点远离上四分位数,但我相信这些数据点不是异常值,它们的值对于目标分类是有意义的。不除去任何别人。

for col in data[["annual_inc", "total_rec_late_fee", "revol_util"]].columns:
    sns.boxplot(data[col])
    plt.show()

(箱线图)。作者图片

缺少值

是时候发现并消除它们了。

for column in data.columns:
    if data[column].isna().sum() != 0:
        missing = data[column].isna().sum()
        portion = (missing / data.shape[0]) * 100
        print(f"'{column}': number of missing values '{missing}' ---> '{portion:.3f}%'")*>> 'annual_inc': number of missing values '915' ---> '4.626%'
>> 'home_ownership': number of missing values '1476' ---> '7.462%'
>> 'dti': number of missing values '152' ---> '0.768%'
>> 'last_major_derog_none': number of missing values '19208' ---> '97.113%'*

'年度公司'

data.annual_inc.value_counts(dropna=False)NaN         915 <---
60000.0     771
50000.0     729
65000.0     607
70000.0     599
           ... 
109097.0      1
88621.0       1
50455.0       1
18300.0       1
96241.0       1
Name: annual_inc, Length: 2349, dtype: int64---boxhist("annual_inc")

图片作者。

****策略:用平均值(average)替换缺失值。

data["annual_inc"] = data.annual_inc.fillna(data.annual_inc.mean())print(f"Fillna done. Anomalies detected: {data.annual_inc.isnull().values.any()}")**>> Fillna done. Anomalies detected: False**

'住宅 _ 所有权'

data.home_ownership.value_counts(dropna=False)MORTGAGE    9744
RENT        6959
OWN         1600
NaN         1476 <---
Name: home_ownership, dtype: int64---bar("home_ownership")

图片作者。

****策略:模式插补(用最频繁值代替 NaN:Mortage)。

data["home_ownership"] = data.home_ownership.fillna(data.home_ownership.value_counts().index[0])print(f"Imputation done. Missing values: {data.home_ownership.isnull().sum()}")**>> Imputation done. Missing values: 0**

' dti '

data.dti.value_counts(dropna=False)NaN      152 <---
19.64     20
15.87     20
9.60      19
13.49     19
        ... 
1.61       1
29.00      1
29.19      1
31.78      1
3.26       1
Name: dti, Length: 3286, dtype: int64---boxhist("dti")

图片作者。

****策略:用平均值替换缺失值。

data["dti"] = data.dti.fillna(data.dti.mean())print(f"Fillna done. Missing values: {data.dti.isnull().values.any()}")**>> Fillna done. Missing values: False**

' last_major_derog_none '

abs_mv = data.last_major_derog_none.value_counts(dropna=False)pc_mv = data.last_major_derog_none.value_counts(dropna=False, normalize=True) * 100pc_mv_df = pd.DataFrame(pc_mv)pc_mv_df.rename(columns={"last_major_derog_none":"Percent %"}, inplace=True)abs_pc = pd.concat([abs_mv,pc_mv_df], axis=1)abs_pc

作者图片

****策略:删除' last_major_derog_none '数值变量(异常过多)。

data.drop("last_major_derog_none", axis=1, inplace=True)print(f"All missing values are solved in the entire dataset: {data.notnull().values.any()}")**>> All missing values are solved in the entire dataset: True**

特征选择

>> data.info()

作者图片

****策略:丢弃‘id’数值变量(无关特性)。

data.drop("id", axis=1, inplace=True)---data.shape
>> (19779, 13)

数字特征和分类/二元目标

****仅选择数值型变量:
>> data_nu = data.select_dtypes(exclude=["object","category"]).copy()

创建子集** :
`>> Xnum = data_nu.drop(["bad_loan"], axis= "columns")

ynum = data_nu.bad_loan`**

**# Identifying the predictive features using the Pearson Correlation p-value**pd.DataFrame(
    [scipy.stats.pearsonr(Xnum[col], 
    ynum) for col in Xnum.columns], 
    columns=["Pearson Corr.", "p-value"], 
    index=Xnum.columns,
).round(4)

作者图片

****策略:降‘od _ ratio’(p 值> 0.05) →低信息给目标,其他全部保留。

分类特征和分类/二元目标

仅选择类别 c 变量:

Xcat = data.select_dtypes(exclude=['int64','float64']).copy()

创建子集:

Xcat['target'] = data.bad_loan
Xcat.dropna(how="any", inplace=True)ycat = Xcat.target
Xcat.drop("target", axis=1, inplace=True)

****卡方检验独立性检验:

for col in Xcat.columns:
    table = pd.crosstab(Xcat[col], ycat)
    print()
    display(table)
    _, pval, _, expected_table = scipy.stats.chi2_contingency(table)
    print(f"p-value: {pval:.25f}")

(卡方检验)。作者图片

(卡方检验)。作者图片

****策略:保留所有特征(p 值< 0.05)。分类变量具有预测能力。

编码和转换

让我们继续将分类变量编码并转换成数字变量。

特征“等级”是一个尺度,这意味着我将把它映射到数字上。另一方面,关于变量‘term’,‘home _ ownership’和‘purpose’,我们需要检查并决定哪个程序 (OHE二进制编码)是最佳选择。

变量:“等级”

>> data["grade"] = data.grade.map({"A":7, "B":6, "C":5, "D":4, "E":3, "F":2, "G":1})

变量:“期限”、“房屋所有权”、“用途”

一个热编码和二进制编码都将显示,所以我们可以选择最好的应用。

df_term = data.term
df_home = data.home_ownership
df_purp = data.purpose**#term**
t_ohe = pd.get_dummies(df_term)
bin_enc_term = BinaryEncoder()
t_bin = bin_enc_term.fit_transform(df_term)**#home_ownsership**
h_ohe = pd.get_dummies(df_home)
bin_enc_home = BinaryEncoder()
h_bin = bin_enc_home.fit_transform(df_home)**#purpose**
p_ohe = pd.get_dummies(df_purp)
bin_enc_purp = BinaryEncoder()
p_bin = bin_enc_purp.fit_transform(df_purp)*>> The results are:*** COLUMNS OHE **
term: 2 <--- best
home: 3 <--- best
purp: 12

** COLUMNS BINARY **
term: 2
home: 3
purp: 5 <--- best

一个热门编码(OHE)

>> data = pd.get_dummies(data, columns=["term","home_ownership"])

二进制编码

**`>> bin_enc_purp = BinaryEncoder()

data_bin = bin_enc_purp.fit_transform(data.purpose)`**

**# Concatenating both datasets**
df = pd.concat([data,data_bin],axis=1)**# Dropping 'purpose'**
df.drop(["purpose"], axis=1, inplace=True)**# Lowering upper characters**
df.columns = [x.lower() for x in df.columns]**# printing 5 first rows**
df.head()

图片作者。

在这一点上,我们准备测试和训练一些模型!

机器学习:预测建模

我们正在使用分类技术处理监督二进制问题

鉴于我们有不平衡数据,我们将使用 AUC ROC 作为评估以下模型性能的最佳指标。

让我们定义一个 AUC 函数来绘制和显示真阳性率(TPR)和假阳性率(FPR)之间的阈值。

**# ROC Curve: Area Under the Curve**def auc_roc_plot(y_test, y_preds):
    fpr, tpr, thresholds = roc_curve(y_test,y_preds)
    roc_auc = auc(fpr, tpr) print(roc_auc) plt.title('Receiver Operating Characteristic')
    plt.plot(fpr, tpr, 'b', label = 'AUC = %0.2f' % roc_auc)
    plt.legend(loc = 'lower right')
    plt.plot([0, 1], [0, 1],'r--'
    plt.xlim([0, 1])
    plt.ylim([0, 1])
    plt.ylabel('True Positive Rate'
    plt.xlabel('False Positive Rate')
    plt.show()

逻辑回归

**# Making a copy of the dataset**df_lr = df.copy()---**# Dividing the dataset in train (80%) and test (20%)**train_set_lr, test_set_lr = train_test_split(df_lr, test_size = 0.2, random_state = seed)X_train_lr = train_set_lr.drop(['bad_loan'], axis = 1)
y_train_lr = train_set_lr['bad_loan']X_test_lr = test_set_lr.drop(['bad_loan'], axis = 1)
y_test_lr = test_set_lr['bad_loan']---**# Normalizing the train and test data**scaler_lr = MinMaxScaler()
features_names = X_train_lr.columnsX_train_lr = scaler_lr.fit_transform(X_train_lr)
X_train_lr = pd.DataFrame(X_train_lr, columns = features_names)X_test_lr = scaler_lr.transform(X_test_lr)
X_test_lr = pd.DataFrame(X_test_lr, columns = features_names)---**%%time**lr = LogisticRegression(max_iter = 1000, solver = 'lbfgs', random_state = seed, class_weight = 'balanced' )parameters = {'C':[0.001, 0.01, 0.1, 1, 10, 100]}clf_lr = GridSearchCV(lr, parameters, cv = 5).fit(X_train_lr, y_train_lr)*>>> CPU times: user 10.3 s, sys: 449 ms, total: 10.8 s
Wall time: 3.21 s*---clf_lr*>>> GridSearchCV(cv=5, error_score=nan, estimator=LogisticRegression(C=1.0, class_weight='balanced', dual=False, fit_intercept=True, intercept_scaling=1, l1_ratio=None, max_iter=1000, multi_class='auto', n_jobs=None, penalty='l2', random_state=42, solver='lbfgs', tol=0.0001, verbose=0, warm_start=False), iid='deprecated', n_jobs=None, param_grid={'C': [0.001, 0.01, 0.1, 1, 10, 100]}, pre_dispatch='2*n_jobs', refit=True, return_train_score=False, scoring=None, verbose=0)*clf_lr.best_estimator_*>>> LogisticRegression(C=0.1, class_weight='balanced', dual=False, fit_intercept=True, intercept_scaling=1, l1_ratio=None, max_iter=1000, multi_class='auto', n_jobs=None, penalty='l2', random_state=42, solver='lbfgs', tol=0.0001, verbose=0, warm_start=False)*---y_preds_lr = clf_lr.predict_proba(X_test_lr)[:,1]---auc_roc_plot(y_test_lr, y_preds_lr)**>> 0.7074872114784778**

图片作者。

**# Confusion Matrix display**plot_confusion_matrix(clf_lr, X_test_lr, y_test_lr, values_format=".4g", cmap="Blues");---**# Creating assignments for Final Results**tn, fp, fn, tp = confusion_matrix(y_test_lr == 1, y_preds_lr > 0.5).ravel()tn_lr = tn
fp_lr = fp
fn_lr = fn
tp_lr = tp

图片作者。

K-最近邻 ( KNN )

**# Making a copy of the dataset**df_knn = df.copy()---**# Dividing the dataset in train (80%) and test (20%)**train_set_knn, test_set_knn = train_test_split(df_knn, test_size = 0.2, random_state = seed)​X_train_knn = train_set_knn.drop(['bad_loan'], axis = 1)
y_train_knn = train_set_knn['bad_loan']X_test_knn = test_set_knn.drop(['bad_loan'], axis = 1)
y_test_knn = test_set_knn['bad_loan']---**# Normalizing train and test data**scaler_knn = MinMaxScaler()
features_names = X_train_knn.columnsX_train_knn = scaler_knn.fit_transform(X_train_knn)
X_train_knn = pd.DataFrame(X_train_knn, columns = features_names)X_test_knn = scaler_knn.transform(X_test_knn)
X_test_knn = pd.DataFrame(X_test_knn, columns = features_names)---**%%time**for k in range(1, 200, 5):
    k = k + 1
    knn = KNeighborsClassifier(n_neighbors = k).fit(X_train_knn, y_train_knn)
    acc = knn.score(X_test_knn, y_test_knn)
    print('Accuracy for k =', k, ' is:', acc)Accuracy for k = 2  is: 0.7965116279069767
Accuracy for k = 7  is: 0.7944893832153691
Accuracy for k = 12  is: 0.8066228513650152
Accuracy for k = 17  is: 0.8066228513650152
Accuracy for k = 22  is: 0.8088978766430738
Accuracy for k = 27  is: 0.8081395348837209
Accuracy for k = 32  is: 0.8106673407482305
Accuracy for k = 37  is: 0.8094034378159757
Accuracy for k = 42  is: 0.8116784630940344
Accuracy for k = 47  is: 0.8119312436804853
Accuracy for k = 52  is: 0.8109201213346815
Accuracy for k = 57  is: 0.8104145601617796
Accuracy for k = 62  is: 0.8096562184024267
Accuracy for k = 67  is: 0.8101617795753286
Accuracy for k = 72  is: 0.8101617795753286
Accuracy for k = 77  is: 0.8104145601617796
Accuracy for k = 82  is: 0.8109201213346815
Accuracy for k = 87  is: 0.8106673407482305
Accuracy for k = 92  is: 0.8104145601617796
Accuracy for k = 97  is: 0.8106673407482305
Accuracy for k = 102  is: 0.8104145601617796
Accuracy for k = 107  is: 0.8104145601617796
Accuracy for k = 112  is: 0.8104145601617796
Accuracy for k = 117  is: 0.8104145601617796
Accuracy for k = 122  is: 0.8104145601617796
Accuracy for k = 127  is: 0.8106673407482305
Accuracy for k = 132  is: 0.8104145601617796
Accuracy for k = 137  is: 0.8104145601617796
Accuracy for k = 142  is: 0.8101617795753286
Accuracy for k = 147  is: 0.8101617795753286
Accuracy for k = 152  is: 0.8101617795753286
Accuracy for k = 157  is: 0.8104145601617796
Accuracy for k = 162  is: 0.8104145601617796
Accuracy for k = 167  is: 0.8104145601617796
Accuracy for k = 172  is: 0.8104145601617796
Accuracy for k = 177  is: 0.8104145601617796
Accuracy for k = 182  is: 0.8104145601617796
Accuracy for k = 187  is: 0.8104145601617796
Accuracy for k = 192  is: 0.8104145601617796
Accuracy for k = 197  is: 0.8104145601617796
*>> CPU times: user 1min 8s, sys: 883 ms, total: 1min 9s
Wall time: 1min 10s*---**%%time**knn = KNeighborsClassifier(n_neighbors = 47, weights='uniform').fit(X_train_knn, y_train_knn)y_preds_knn = knn.predict(X_test_knn)*>> CPU times: user 1.29 s, sys: 16 ms, total: 1.31 s
Wall time: 1.31 s*---auc_roc_plot(y_test_knn, y_preds_knn)**>> 0.6670792264504056**

图片作者。

**# Confusion Matrix display**plot_confusion_matrix(knn, X_test_knn, y_test_knn, values_format=".4g", cmap="Blues");---**​# Creating assignments for Final Results**tn, fp, fn, tp = confusion_matrix(y_test_knn == 1, y_preds_knn > 0.5).ravel()tn_knn = tn
fp_knn = fp
fn_knn = fn
tp_knn = tp

图片作者。

支持向量机

**# Making a copy of the dataset**df_svm = df.copy()---**# Dividing the dataset in train (80%) and test (20%)**train_set_svc, test_set_svc = train_test_split(df_svm, test_size = 0.2, random_state = seed)X_train_svc = train_set_svc.drop(['bad_loan'], axis = 1)
y_train_svc = train_set_svc['bad_loan']X_test_svc = test_set_svc.drop(['bad_loan'], axis = 1)
y_test_svc = test_set_svc['bad_loan']---**# Standardization of train and test data**zscore_svc = StandardScaler()
features_names = X_train_svc.columnsX_train_svc = zscore_svc.fit_transform(X_train_svc)
X_train_svc = pd.DataFrame(X_train_svc, columns = features_names)X_test_svc = zscore_svc.transform(X_test_svc)
X_test_svc = pd.DataFrame(X_test_svc, columns = features_names)---**%%time**svc = SVC(random_state=seed, class_weight='balanced',probability=True, verbose=True)parameters = {'C':[0.1, 1, 10]}clf_svc = GridSearchCV(svc, parameters, cv = 5).fit(X_train_svc, y_train_svc)*>> [LibSVM][LibSVM][LibSVM][LibSVM][LibSVM][LibSVM][LibSVM][LibSVM][LibSVM][LibSVM][LibSVM][LibSVM][LibSVM][LibSVM][LibSVM][LibSVM]CPU times: user 14min 34s, sys: 22.7 s, total: 14min 57s
Wall time: 15min 2s*---**%%time**y_preds_svc = clf_svc.predict_proba(X_test_svc)[:,1]*>> CPU times: user 2.95 s, sys: 17.9 ms, total: 2.97 s
Wall time: 3 s*---auc_roc_plot(y_test_svc, y_preds_svc)**>> 0.6754917862341443**

图片作者。

**# Confusion Matrix display**plot_confusion_matrix(clf_svc, X_test_svc, y_test_svc, values_format=".4g", cmap="Blues");---**​# Creating assignments for Final Results**tn, fp, fn, tp = confusion_matrix(y_test_svc == 1, y_preds_svc > 0.5).ravel()tn_svc = tn
fp_svc = fp
fn_svc = fn
tp_svc = tp

图片作者。

决策树

**# Making a copy of the dataset**df_trees = df.copy()---**# Dividing the dataset in train (80%) and test (20%)**train_set_dt, test_set_dt = train_test_split(df_trees, test_size = 0.2, random_state = seed)X_train_dt = train_set_dt.drop(['bad_loan'], axis = 1)
y_train_dt = train_set_dt['bad_loan']X_test_dt = test_set_dt.drop(['bad_loan'], axis = 1)
y_test_dt = test_set_dt['bad_loan']---**%%time**clf_tree = tree.DecisionTreeClassifier(random_state = seed, max_depth = 10).fit(X_train_dt, y_train_dt)*>> CPU times: user 203 ms, sys: 65.8 ms, total: 268 ms
Wall time: 388 ms*---clf_tree.score(X_test_dt, y_test_dt)>> 0.788675429726997---**# Visualizing variables by importance**important_features = pd.DataFrame(data = clf_tree.feature_importances_, index = X_train_dt.columns, columns = ["value"])important_features.sort_values(by = "value", ascending = False)

图片作者。

y_preds_dt = clf_tree.predict_proba(X_test_dt)[:,1]---auc_roc_plot(y_test_dt, y_preds_dt)**>> 0.6295855687253067**

图片作者。

**# Confusion Matrix display**plot_confusion_matrix(clf_tree, X_test_dt, y_test_dt, values_format=".4g", cmap="Blues");---**# Creating assignments Final Results**tn, fp, fn, tp = confusion_matrix(y_test_dt == 1, y_preds_dt > 0.5).ravel()tn_dt = tn
fp_dt = fp
fn_dt = fn
tp_dt = tp

图片作者。

随机森林

**# Making a copy of the dataset**df_rf = df.copy()---**# Dividing the dataset in train (80%) and test (20%)**train_set_rf, test_set_rf = train_test_split(df_rf, test_size = 0.2, random_state = seed)X_train_rf = train_set_rf.drop(['bad_loan'], axis = 1)
y_train_rf = train_set_rf['bad_loan']X_test_rf = test_set_rf.drop(['bad_loan'], axis = 1)
y_test_rf = test_set_rf['bad_loan']---**%%time**rf = RandomForestClassifier(random_state = seed, class_weight = None).fit(X_train_rf, y_train_rf)parameters = {'n_estimators':[10, 100, 300, 1000]}clf_rf = GridSearchCV(rf, parameters, cv = 5).fit(X_train_rf, y_train_rf)*>> CPU times: user 2min 11s, sys: 3.33 s, total: 2min 14s
Wall time: 2min 15s*---y_preds_rf = clf_rf.predict_proba(X_test_rf)[:,1]---auc_roc_plot(y_test_rf, y_preds_rf)**>> 0.6735905593678521**

图片作者。

**# Confusion Matrxi display**plot_confusion_matrix(clf_rf, X_test_rf, y_test_rf, values_format=".4g", cmap="Blues");---​**# Creating assignments for Final Results**tn, fp, fn, tp = confusion_matrix(y_test_rf == 1, y_preds_rf > 0.5).ravel()tn_rf = tn
fp_rf = fp
fn_rf = fn
tp_rf = tp

图片作者。

神经网络

**# Making a copy of the dataset**df_nn = df.copy()---**# Dividing the dataset in train (80%) and test (20%)**train_set_nn, test_set_nn = train_test_split(df_nn, test_size = 0.2, random_state = seed)X_train_nn = train_set_nn.drop(['bad_loan'], axis = 1)
y_train_nn = train_set_nn['bad_loan']X_test_nn = test_set_nn.drop(['bad_loan'], axis = 1)
y_test_nn = test_set_nn['bad_loan']---**# Normalization of the train and test data**scaler_nn = MinMaxScaler()
features_names = X_train_nn.columnsX_train_nn = scaler_nn.fit_transform(X_train_nn)
X_train_nn = pd.DataFrame(X_train_nn, columns = features_names)X_test_nn = scaler_nn.transform(X_test_nn)
X_test_nn = pd.DataFrame(X_test_nn, columns = features_names)---**%%time**mlp_nn = MLPClassifier(solver = 'adam', random_state = seed, max_iter = 1000 )parameters = {'hidden_layer_sizes': [(20,), (20,10), (20, 10, 2)], 'learning_rate_init':[0.0001, 0.001, 0.01, 0.1]}clf_nn = GridSearchCV(mlp_nn, parameters, cv = 5).fit(X_train_nn, y_train_nn)*>> CPU times: user 25min 41s, sys: 41.4 s, total: 26min 22s
Wall time: 6min 53s*---y_preds_nn = clf_nn.predict_proba(X_test_nn)[:,1]---auc_roc_plot(y_test_nn, y_preds_nn)**>> 0.7081023081721772**

图片作者。

**# Confusion Matrix display**plot_confusion_matrix(clf_nn, X_test_nn, y_test_nn, values_format=".4g", cmap="Blues");​---**# Creating assignments for Final Results**tn, fp, fn, tp = confusion_matrix(y_test_nn == 1, y_preds_nn > 0.5).ravel()tn_nn = tn
fp_nn = fp
fn_nn = fn
tp_nn = tp

图片作者。

结果:模型之间的性能比较

**# Creating performance table**results_1 = {'Classifier': ['AUC ROC (%)','TN (%)','FP (%)','FN (%)','TP (%)'],'Logistic Regression (LR)': [aucroclr, (tn_lr/3956*100).round(2), (fp_lr/3956*100).round(2), (fn_lr/3956*100).round(2), (tp_lr/3956*100).round(2)],'K Nearest Neighbour (KNN)': [aucrocknn, (tn_knn/3956*100).round(2),(fp_knn/3956*100).round(2), (fn_knn/3956*100).round(2),(tp_nn/3956*100).round(2)],'Support Vector Machine (SVC)': [aucrocsvc, (tn_svc/3956*100).round(2),(fp_svc/3956*100).round(2), (fn_svc/3956*100).round(2),(tp_svc/3956*100).round(2)],'Decision Trees (DT)': [aucrocdt, (tn_dt/3956*100).round(2), (fp_dt/3956*100).round(2), (fn_dt/3956*100).round(2),(tp_dt/3956*100).round(2)],'Random Forest (RF)': [aucrocrf, (tn_rf/3956*100).round(2), (fp_rf/3956*100).round(2), (fn_rf/3956*100).round(2),(tp_rf/3956*100).round(2)],'Neural Networks (NN)': [aucrocnn, (tn_nn/3956*100).round(2), (fp_nn/3956*100).round(2),(fn_nn/3956*100).round(2),(tp_nn/3956*100).round(2)]}df1 = pd.DataFrame(results_1, columns = ['Classifier', 'Logistic Regression (LR)', 'K Nearest Neighbour (KNN)', 'Support Vector Machine (SVC)', 'Decision Trees (DT)', 'Random Forest (RF)', 'Neural Networks (NN)'])df1.set_index("Classifier", inplace=True)results = df1.T
results 

图片作者。

​**# Creating table for graphic visualization**results_2 = {'Classifier': ['ROC AUC'], 'Logistic Regression (LR)': [aucroclr], 'K Nearest Neighbour (KNN)': [aucrocknn], 'Support Vector Machine (SVC)': [aucrocsvc], 'Decision Trees (DT)': [aucrocdt], 'Random Forest (RF)': [aucrocrf], 'Neural Networks (NN)': [aucrocnn]}df2 = pd.DataFrame(results_2, columns = ['Classifier', 'Logistic Regression (LR)', 'K Nearest Neighbour (KNN)', 'Support Vector Machine (SVC)', 'Decision Trees (DT)', 'Random Forest (RF)', 'Neural Networks (NN)'])df2.set_index("Classifier", inplace=True)
results_2 = df2---**# Display tHe graph**ax = results_2.plot(kind="bar", title=("Evaluating models' performance"), figsize=(12,8) ,fontsize=10, grid=True)for p in ax.patches:
    ax.annotate("%.2f" % p.get_height(), (p.get_x() + p.get_width() / 2., p.get_height()), ha='center', va='center', xytext=(0, 5), textcoords='offset points')plt.legend(fontsize=8.5, loc="upper right")
plt.xlabel('')
plt.xticks(rotation='horizontal')
plt.ylabel('Relative frequency (%)')
plt.show()

图片作者。

结论

最佳模型:支持向量机-分类器(SVC): 75.21%。

经验法则非常简单:ROC AUC 指标的值越高越好。如果随机模型显示 0.5,完美模型将达到 1.0。

学术评分系统如下:

.9 -  1 = excellent  (A)
.8 - .9 = good       (B)
.7 - .8 = reasonable (C)
.6 - .7 = weak       (D)
.5 - .6 = terrible   (F)

TPR 和 FPR 之间的比率由阈值确定,超过该阈值导致阳性情况,将所选模型(SVC)置于合理水平(C ), ROC AUC 得分为 75.21%。

你可以在这里下载数据集

其他一些文章:

**https://goncaloggomes.medium.com/machine-learning-hierarchical-and-k-means-clustering-with-python-fb73ee729128 https://goncaloggomes.medium.com/15-business-questions-about-mobile-marketing-campaigns-roas-return-on-ad-spend-ff636a8095b6

如何与我联系:

👏🏻如果你觉得值得的话。

✅感谢你的阅读!**

使用 Docker 和 Python REST APIs 和 Flask 进行实时机器学习预测

原文:https://towardsdatascience.com/machine-learning-prediction-in-real-time-using-docker-and-python-rest-apis-with-flask-4235aa2395eb?source=collection_archive---------2-----------------------

Docker 容器和 REST APIs 执行在线推理的快速示例

Annamária Borsos 摄影

本文的想法是快速简单地构建一个 Docker 容器,使用 Python APIs 和 Flask,通过经过训练的机器学习模型执行在线推理。在阅读本文之前,请不要犹豫阅读为什么使用 Docker 进行机器学习快速安装并首次使用 Docker 以及为您的机器学习模型构建并运行 Docker 容器,在其中我们将学习如何使用 Docker 进行模型训练和批量推理。

当你有时间计算你的预测时,批量推断是非常有用的。让我们假设你需要实时预测。在这种情况下,批量推理并不更合适,我们需要在线推理。如果没有在线预测,许多应用将无法工作或不会非常有用,例如自动驾驶汽车、欺诈检测、高频交易、基于定位数据的应用、物体识别和跟踪或大脑计算机接口。有时,需要以毫秒为单位提供预测。

为了学习这个概念,我们将使用 Docker 和 Flask-RESTful 实现在线推理(线性判别分析和多层感知器神经网络模型)。

首先,我们考虑以下文件: Dockerfile,train.py,api.py,requirements.txt, train.csv,test.json.

train.py 是一个 python 脚本,它接收并标准化 EEG 数据,并训练两个模型来对数据进行分类。 Dockerfile 将用于构建我们的 Docker 映像,requirements.txt (flask,flask-restful,joblib)用于 Python 依赖项,api.py 是将被调用来使用 REST APIs 执行在线推理的脚本。 train.csv 是用于训练我们的模型的数据,而 test.json 是一个包含新 EEG 数据的文件,将用于我们的推理模型。

你可以在 GitHub 上找到所有文件。

flask-RESTful API

构建 API 的第一步是考虑我们想要处理的数据,我们想要如何处理它,以及我们想要 API 产生什么样的输出。在我们的例子中,我们将使用 test.json 文件,其中有 1300 行 EEG 数据,每行有 160 个特征(列)。我们希望我们的 API 满足以下要求:

  • API 1:我们给 API 一个行号,它将从所选行中提取数据并打印出来。

  • API 2:我们将为 API 提供一个行号,该 API 将提取所选行,将新数据注入模型并检索分类预测(数据中的字母变量)

  • API 3:我们将要求 API 获取 test.json 文件中的所有数据,并立即为我们打印模型的分类分数。

最后,我们希望通过发出 HTTP 请求来访问这些进程。

让我们来看看 api.py 文件:

在导入包括开源 web 微框架 Flask 在内的依赖项之后,第一步是设置写在 docker 文件中的环境变量。我们还需要加载我们的线性判别分析和多层感知器神经网络序列化模型。我们通过编写 app = Flask(name)来创建我们的 Flask 应用程序。然后,我们创建三个 Flask 路由,以便在该路由上服务 HTTP 流量:

-http://0 . 0 . 0 . 0:5000/line/250:从 test.json 获取数据,并返回由变量 Line 定义的请求行(在本例中,我们希望提取行号为 250 的数据)

-http://0 . 0 . 0 . 0:5000/prediction/51:通过注入请求的数据,从 LDA 和神经网络训练模型返回分类预测(在本例中,我们希望注入第 51 行的数据)

-http://0 . 0 . 0 . 0:5000/score:返回神经网络和 LDA 推理模型对所有可用数据的分类得分( test.json )。

Flask routes 允许我们通过向 URL(http://0 . 0 . 0 . 0:5000)添加我们的过程的名称( /line/ < Line >,/prediction/ < int:Line >,/score )来从 API 请求我们需要的东西。无论我们添加什么数据, api.py 总是会返回我们请求的输出。

机器学习模型

train.py 是一个 python 脚本,它吸收并归一化 csv 文件(train.csv)中的 EEG 数据,并训练两个模型对数据进行分类(使用 scikit-learn)。该脚本保存了两个模型:线性判别分析(clf_lda)和神经网络多层感知器(clf_NN):

在线推理的 Docker 图像

我们都必须建立自己的码头工人形象。首先,我们需要我们的 Dockerfilejupyter/scipy-notebook 图像作为我们的基础图像。我们还需要设置我们的环境变量并安装 joblib,以允许我们的训练模型和 flask ( requirements.txt )的序列化和反序列化。我们将 train.csvtest.jsontrain.pyapi.py 文件复制到镜像中。然后,我们运行 train.py ,它将拟合并序列化机器学习模型,作为我们映像构建过程的一部分。

这是:

要构建此映像,请运行以下命令:

docker build -t my-docker-api -f Dockerfile . 

我们获得以下输出:

运行 Docker 在线推理

现在,我们的目标是运行我们的在线推理,这意味着每次客户端向 /line/ < Line >、/prediction/ < Line >、/score 端点发出 POST 请求时,我们将显示请求的数据(行),使用我们的预训练模型预测我们注入的数据的类别,并使用所有可用数据预测我们的预训练模型的得分。为了启动 web 服务器,我们将运行一个 Docker 容器并运行 api.py 脚本:

docker run -it -p 5000:5000 my-docker-api python3 api.py

-p 标志将容器中的端口 5000 暴露给我们主机上的端口 5000, -it 标志允许我们查看来自容器的日志,我们在 my-api 映像中运行 python3 api.py

输出如下所示:

您可以看到我们运行在 http://0.0.0.0:5000/ 上,现在我们可以使用 web 浏览器或 curl 命令向该 IP 地址发出 POST 请求。

如果我们键入:

curl [http://0.0.0.0:5000/line/232](http://0.0.0.0:5000/line/232)

我们将从我们的数据(test.json)中提取第 232 行:

使用 web 浏览器得到相同的结果:

如果我们键入以下 curl 命令:

curl [http://0.0.0.0:5000/prediction/232](http://0.0.0.0:5000/prediction/232)

我们将看到以下输出:

上述输出意味着 LDA 模型将提供的数据(行 232)分类为字母 21 (U ),而多层感知器神经网络将数据分类为字母 8 (H)。这两个模型不一致。

如果我们打字

curl [http://0.0.0.0:5000/score](http://0.0.0.0:5000/score)

我们将看到我们的模型在整个数据集上的得分:

正如我们所看到的,我们应该更信任多层感知器神经网络,其准确度分数为 0.59,即使分数不是很高。有些工作要做,以提高准确性!

下一步是什么?

我希望你能看到使用 Docker 和 flask 来执行在线推理,从而将你的机器/深度学习应用容器化的简单性。当我们想把我们的模型投入生产时,这是必不可少的一步。当然,这是一个简单的观点,因为我们需要考虑更多方面,如网络、安全、监控、基础设施、协调或添加数据库来存储数据,而不是使用 json 文件。

来源

https://www.fernandomc.com/posts/your-first-flask-api/

https://mlinproduction.com/docker-for-ml-part-4/

https://www . kdnugges . com/2019/10/easy-deploy-machine-learning-models-using-flask . html

机器学习:解决任何机器学习问题的过程

原文:https://towardsdatascience.com/machine-learning-process-for-solving-any-machine-learning-problem-cdebfdae5a55?source=collection_archive---------46-----------------------

Jr Korpa 在 Unsplash 上拍摄的照片

当我们解决机器学习问题时,我们最终可能使用的算法取决于我们拥有的数据类型和问题本身。尽管有许多算法可供选择,我们仍然有一个通用的程序或框架来解决我们的问题。

在这篇文章中,我们将介绍可以用作解决任何机器学习问题的模板的通用过程或框架。读完这篇文章,你会-

  • 了解机器学习的基础知识
  • 查看机器学习过程中涉及的各个步骤
  • 了解其他流行的机器学习框架

机器学习

机器学习是一个与构建系统或程序有关的研究领域,这些系统或程序能够在没有明确编程的情况下学习。机器学习系统接收大量数据,从中学习模式和标签,基本上是在从未见过的数据上预测信息。

卢卡斯·布拉塞克Unsplash 上拍摄的照片

下面是机器学习的一个流行定义:

如果由 P 测量的计算机程序在 T 中的任务上的性能随着经验 E 而提高,则称该计算机程序从关于某类任务 T 和性能测量 P 的经验 E 中学习

汤姆·米切尔

我知道这很难完全理解,所以让我把它分解成更简单的术语——把经验想象成数据,把任务想象成用这些数据预测某事,把绩效评估想象成预测实际上是否正确的答案。现在,如果你想对机器学习有一个大致的了解,看看这个帖子-

https://thedatascienceportal.com/posts/so-what-is-machine-learning

现在我们已经了解了什么是机器学习,让我们看看它是如何应用于解决有趣的商业问题的。

机器学习过程

一个过程被定义为为了达到一个特定的目的而采取的一系列步骤的行动。在这里,我们的过程是实现一个机器学习算法的成功实施。该过程从收集数据开始,然后以某种方式对数据进行处理和转换。然后,超级酷的机器学习算法应用于它,以做出一些预测,并得出有影响力的商业见解。这是这个过程的基本框架

机器学习过程

从各种来源收集数据并组合形成一个数据结构

使用数据分析技术研究数据并获得见解

既然我们已经了解了数据是怎样的,我们执行一些数据预处理步骤

选择机器学习模型并训练该模型以创建基线模型

基于测试集和各种性能指标对模型进行评估

根据评估,我们通过改变一些超参数甚至返回并添加更多数据来调整模型

当模型在测试过程中开始表现良好时,它就会被保存和部署以供使用——对新输入的数据进行预测。

机器学习过程|作者照片

现在我们已经设计好了框架,让我们仔细检查每一个步骤,以便更好地理解整个过程。顺便说一下,如果你以前应用过机器学习来解决一个问题,你就会知道整个过程是相当迭代的。如果你以前没有这样做过,那基本上意味着你将应用上面提到的许多步骤,直到你得到想要的结果。在步骤#5 中,借助于完全由问题陈述定义的评估集和性能度量来计算该合意性。如果您现在还不明白这一点,请不要担心,我们会详细介绍流程中的每一步。

数据采集

你可能听过这样一句话,“垃圾进,垃圾出!”。如果没有,那么你肯定会,几乎每隔一天处理数据(不,认真)。数据是最重要的东西——如果你有好的数据,那么你的模型将有最好的机会像预期的那样运行,并给出在现实世界中有意义的预测。

数据收集是机器学习过程中的第一步,它被定义为收集和组合与我们试图解决的问题相关的所有数据的行为。这些数据后来被用于训练和评估我们的机器学习模型。在这一步中可能会面临几个挑战-

我们试图处理的数据无法在一个地方获得。必须提取和组合来自多个系统的数据。

  • 这是一个常见的行业问题,人们必须依靠他们的数据工程技能来解决这个问题。
  • 首先,我们必须找到从每个系统中提取数据的方法。我们可以使用 SQL 连接到系统数据库。
  • 根据您的要求,使用 SQL 以某种方式连接数据集。

数据是可用的,但作为一个静态文件,必须从一些系统手动导出。

  • 出于训练和评估目的,我们可以使用手动提取的数据集,因为这是一次性活动,我们可以重复使用相同的数据进行模型选择。
  • 当我们到达预测阶段时,也就是说,当最终的模型已经部署时,我们需要建立一个架构,该架构自动执行从系统中提取数据的过程,如果有多个系统,则连接提取的数据,然后通过一些数据预处理管道运行该数据,使其达到所需的格式/结构。这样做是为了不需要人工干预,机器学习模型可以直接使用数据。同样,这是一个数据工程练习,我们可以将流程定义为类似于这样的内容

数据流|作者照片

数据可能是从不同的来源和系统提取的,这些来源和系统不一定有任何相互通信的方式,因此这种活动既麻烦又耗时。但是 ETL 管道可以帮助我们从各种来源收集数据,并将它们以所需的格式存储在仓库中,以备数据分析师和数据科学家访问。

探索性数据分析

在我们建立我们的机器学习模型之前,我们必须研究数据,以了解我们需要运行什么样的分析,以及基本上我们可以用数据回答什么样的商业问题。这一步与我们试图解决的业务问题密切相关。顾名思义,在这一步中,我们通过执行一些分析来探索数据,以找出我们拥有什么样的功能,它们是如何相关的,并使用描述性统计以报告和仪表板的形式进行一些数据可视化。在这一步,你应该戴上你的研究员帽。

Firmbee.com 在 Unsplash拍照

在第一步之后,数据从我们收集数据的地方导入。在这一步中,我们发现了几件事,这些事将继续塑造我们如何处理问题的方法。对于初学者来说,对数据有一个好的整体感觉总是好的,我们可以通过做以下事情来得到一个好的想法

  • 熟悉数据及其不同的特性。
  • 找出这些特征之间的关系,看看它们是否相关。
  • 找出数据的描述性指标——重要数字特征的平均值、中值、最小值、最大值以及最常见、最不常见的分类特征。根据问题的不同,可能会有无限多的指标。
  • 通过按各种特征对数据进行分组,了解特征值的各种可能组合,从而深入了解我们拥有的各种数据。这有助于发现数据中隐藏的模式。
  • 通过执行统计测试来查看数据,找出数据中的异常值(有时人们可以通过简单的直觉来判断)。
  • 寻找丢失的值和可能的错误,并正确处理它们。

在这一步中,你还可以做更多的事情。如果你真的对数据和手头的问题充满热情,那么这可能是你将花费大量时间的一步(相信我!).

数据预处理

现在我们已经研究了数据,我们确切地知道我们拥有什么——这是一件非常重要的事情。我们现在有了一个更好的想法,我们应该如何转换数据,以便在其上运行机器学习算法。要做到这一点,我们必须改变现有的特征。但在此之前,还有许多其他问题需要考虑——缺失数据、不正确数据、重复值等等。数据永远不够干净,无法直接输入机器学习算法,这正是这一步如此重要的原因。

米卡·鲍梅斯特在 Unsplash 上的照片

我们拥有的特性可能是不同类型的(大多数情况下是这样的!)—数字、类别、列表、自由文本或者其他东西。为了运行机器学习算法,这些特征将必须被转换成算法能够理解它们的状态。我们已经有了一个想法,计算机只理解数字,基本上一切都可以归结为 0 和 1(是的,这也包括你尴尬的高中照片),这正是我们试图用我们的数据预处理技术做的。对于我们遵循的不同类型的数据,有不同的技术。这些是常见的-

数字特征

我们检查数字特征是连续还是离散

连续:这意味着在可能值的区间上测量的特征值本质上是连续的。

  • 它们不是静止值,可以取该区间内任何可能的值。
  • 一个很好的例子是在 48 小时内测量的温度。
  • 另一个可能是房子的价格,其中价格可以是[$7 万,$70 万]内的任何值。

离散:这意味着特征值本质上是固定的,只能从根据问题定义的集合中取值。

  • 它们不一定是整数值,但它们取自特定的集合。
  • 一个简单的例子可以是[0,1] —值可以是 0 或 1。
  • 另一个例子可以是鞋码,比如在[英国 6,英国 12]以内。

分类特征

我们对分类特征进行编码。编码仅仅意味着给它们分配一个离散的数值或一个集合中的向量值。

One-Hot Encoding:feature 列被拆分成列中不同数量的类别。

  • 因此,如果我们从包含类别[“差”、“还行”、“好”、“棒极了”]的一列开始,现在我们有四列。
  • 包含某个类别的每个记录在该类别的列下的值为 1,其余的为 0。
  • “好”现在将变成[0,0,1,0],而“坏”将变成[1,0,0,0],在四列[“坏”、“还好”、“好”、“棒极了”]下。

离散化:另一种方式是,如果我们有类别[“坏的”、“还好的”、“好的”、“棒极了”],我们可以像[0,1,2,3]一样对它们进行编码,从而将它们变成离散变量。

  • 我相信这是更有效的方法,因为我们仍然只有一列,而不是将特性列分成许多列。

文本特征

文本特征也被编码,但是与分类特征非常不同。有几种方法可以对文本进行编码,但所有这些方法最终都会被数字所取代。为了做到这一点,我们首先制作一个叫做的词汇。词汇表是基于文本的特性列中出现的所有唯一单词的列表(虽然在下面的例子中我没有这样做,但是词汇表可以按升序排序)。这是一些常见的-

从数据到词汇|作者图片

一键编码:将所有唯一的单词考虑在内,组成词汇表。现在有两种方法可以热编码

  • 第一种方法是,每个句子都用一个与词汇长度相同的向量进行编码。
  • 如果一个句子包含一个特定的单词,该单词在词汇向量中的向量位置被标记为 1,其余的被保留为 0。因此,一个布尔向量。
  • 所以上面的第三句话会变成— [0,0,0,1,0,0,0,0,0,0,1,1,1,0,0,0,0]
  • 没有任何单词的顺序感、位置感或意义感,它只是一个布尔值。
  • 就处理空间和时间而言,一键编码的第二种方式成本要高得多。这和之前我们对分类特征做的一样。每个单词都用一个词汇长度向量进行编码,如果该单词出现在句子中,则在词汇中该单词的位置标记 1,而其余的保持为零。所以最后,如果句子开始时有 n 个单词,现在它已经用 n 个向量编码了,每个向量的长度与词汇的长度相同。

单词包:所有独特的单词都被认为构成了词汇表。

  • 在这里,每个句子都用一个与词汇长度相同的向量进行编码。
  • 如果一个句子包含一个特定的单词,该单词在词汇向量中的向量位置被标记为 1,其余的被保留为 0。如果同一个单词有多个条目,则增加计数。因此,我们得到一个频率向量。
  • 所以像“我爸爸又饿了,像我的猫一样”这样的句子会是—
    【0,0,1,0,0,0,0,0,0,1,1,1,1,0,0,1,2,0,0】
  • 尽管现在我们在计算频率时至少有了一些意义,但是对于单词的顺序和位置还是一无所知。

TF-IDF: 这是流行的词频-逆文档频率算法。

  • 它实际上是对单词袋方法的扩展或改进。这里,我们用 tf-idf 值的向量代替词频向量作为编码值。
  • 一个单词的 TF-IDF 值在较高层次上是通过将该单词在文档中的频率乘以它在文档中出现的次数的倒数来动态计算的。
  • TF 是通过使用之前的词汇和词频向量来计算和归一化的—
    TF =(单词的频率/词汇的长度)
    —这对于像介词这样的常见单词来说仍然会给出很高的值。因此,这仅仅是一个不完整的指标。
  • 单词的 IDF 是通过计算该单词出现的文档数来计算的。这样做带来了几个问题,所以我们做了一些修改。
    ——如果我们仅将包含该词的文档数量作为 IDF 值,那么对于常用词来说,IDF 值将非常高。
    -这就是为什么我们将文档总数除以包含该单词的文档数,以便非常常用的单词具有较低的 IDF 值,而不常用的单词具有较高的 IDF 值。这就是“逆”文档频率的含义,它提供了一种意义感。
    -但是如果文档的总数很大,而分母不是呢?这个词会有很高的意义。为了在保持重要性的同时缩放该值,我们采用对数值。
    -另一个数学修改是,对于给定值的任何分数,分母不得为零,因此我们将 1 加到分母上,最终得到以下结果—
    IDF = log(文档总数/ (1 +包含该单词的文档数))
  • 这就是我们如何计算每个单词的 tf-idf 值,并像前面一样为每个句子形成词汇长度向量,唯一的区别是,这里我们有每个单词的 tf-idf 值,而不是词频。

单词嵌入:这是单词的最具信息性的表示之一,因为单词嵌入为相似的单词提供了相似的表示。

  • 单词被映射到一个特定的向量表示,这个向量表示是通过映射高维向量空间中的所有单词而找到的。
  • 单词“汽车”和“自行车”在向量空间中将比单词“汽车”和“床”更接近,因此将获得更接近的向量值,自然地捕捉它们的含义。
  • 这种有意义的空间让你的机器学习系统有机会检测可能有助于学习任务的模式。

通过嵌入进行类比| 图片由 谷歌开发者

对了,这只是冰山一角!当你开始做项目时,你会很快意识到数据预处理会占用你大部分的时间。没有固定的规则,需要从 EDA 的前一步进行彻底的调查,以从信息片段中获得相关且可用的数据集。无论如何,在所有这些调查和预处理完成之后,接下来要做的事情是将数据分成两个或三个部分。

数据分割|作者照片

如果您考虑按照最佳实践工作,那么将数据按照接近 60:20:20 的比例分割成 3 部分(取决于数据的大小),并确保数据是随机分割的。有多种方法可以通过编程实现这一点。最大的数据块进入训练集,其余的分成验证集和测试集。

训练数据集:这是将用于训练机器学习模型的数据集。该模型通过考虑数据集的所有特征和复杂性来学习该数据集。

验证数据集:这是用于在机器学习模型被训练后对其进行评估的数据集。也许一些模型参数需要重新调整,或者也许整个算法需要改变。

测试数据集:该数据集用于在未见过的数据上测试模型,以检查模型能够多好地理解其任务并推广到新数据。这给人一种模型在真实场景中表现如何的感觉。

如果你想了解更多关于数据预处理的知识,这里有一篇全面而简单的文章。了解数据预处理技术,以及处理缺失数据、错误数据、特征编码、降维等问题的方法..

https://thedatascienceportal.com/posts/data-preprocessing

型号选择

在探索、调查和清理数据之后,我们对需要做什么来解决业务问题有了更好的理解。模型选择是我们实际选择哪种算法最适合获得当前数据的相关结果的步骤。我们从一组候选模型开始,最终选定一个基于证据的模型。

在选择算法时,有几件事情需要考虑。有人在某个教程中用来解决类似问题的方法可能并不总是最佳选择,因为最终一切都取决于您要处理的数据类型。还可能有其他约束,比如模型复杂性、可维护性、部署成本和资源可用性,我们将在评估期间讨论这些。这一步的目的是创建一个基线模型,用于进一步的评估和微调。理想的情况是使用训练数据训练不同的候选模型,并使用验证数据对它们进行比较。但是这种数据丰富的情况很难发生,所以有几种其他方法可以做到这一点。例如,您可以使用像交叉验证这样的数据重采样技术来训练和测试不同的算法,以便仅使用训练数据来选择理想的算法。

走哪条路?|作者照片

我们选择的模型显然取决于我们拥有的数据类型和我们试图解决的问题类型。比如说我们想造一个聊天机器人。聊天机器人将按照用户的询问进行回答。因此,我们可以说,任何对话的第一步都将是聊天机器人试图识别用户的意图,这是我们的第一个机器学习问题——意图分类。这个问题要求我们使用一种特殊类型的数据——基于文本的数据。我们选择的机器学习算法必须是一种分类算法,即它根据已经看到的数据,将新的输入数据分类到某个标签类。当然,在这一步之前,来自用户的文本将被编码并经过所有必要的数据预处理步骤,然后将被输入到机器学习算法中。在这一步中,我们所要做的就是创建一个基线模型,它接受文本输入并将其分类到某个意图类中。

模型评估

现在我们已经有了一个基线模型,我们必须努力让这个模型可以投入生产。在这一步中,我们将根据可用的基准和业务定义的 KPI 和指标来评估模型性能。我们总是有各种各样的工具和算法来解决特定的问题。作为一名数据科学家,我们有责任在各种算法的所有相关配置中对其进行调整和测试。对正则化、过拟合、欠拟合等概念以及准确度、精确度、召回率、混淆矩阵和 f1 分数等各种性能指标的良好掌握总是有帮助的。如果我们正在进行某个项目,我们完全没有办法事先知道哪个模型在我们的数据上表现最好,所以让我们来谈谈评估是如何进行的。这就是我们在上一步中所做的分割派上用场的地方。这里有一些事情需要考虑-

模型复杂性

从简单和天真的机器学习模型开始,然后逐步发展到复杂的模型,这总是明智的。这主要是因为这些原因-

  • 简单的模型更容易调试。理解架构并做出快速更改需要更少的时间和精力。
  • 最终一切都归结为运行成本——简单模型在云上运行更便宜,主要是因为它们通常处理时间更短,内存需求也低得多。
  • 它们相对更容易向项目涉众解释。可解释的人工智能是一件大事,因为如果一个企业已经部署了一个人工智能模型来帮助他们,他们需要能够向他们的客户解释模型预测。

表演

我们需要关注模型性能,可能需要做一些超参数调整,或者我们需要完全改变算法。当涉及到性能时,我们必须确保模型已经被输入了可能的最佳配置值,并且输出的结果在现实世界中是有意义的。

项目要求

根据问题的不同,我们可能有一组需要更多关注的高优先级指标。就像在癌症预测的情况下,我们不仅需要小心假阳性,因为这会给患者带来很高的经济和情感负担,而且我们需要非常确定模型何时说不,这意味着我们必须有非常低的假阴性(0 是这里的最佳数字,尽管不切实际)。因此,我们需要绝对确定项目需求,以定义一个“足够好的模型”。我们需要知道哪些 KPI 和度量是业务和项目涉众关注的。

因此,我们在模型选择期间使用训练数据训练不同的候选模型,然后在模型评估期间使用验证数据评估它们各自的性能,这两者都是我们在前面的数据预处理步骤中创建的。一旦您评估了基线模型,现在是时候检查结果并考虑如何改进模型了。

模型调整

在模型被选择、训练和评估之后,现在是重新调整模型的时候了,以便以某种方式处理在前面的步骤中突出显示的问题。顾名思义,模型调整是指我们从之前的训练和评估步骤中获取反馈和结果,以重新配置和调整模型,从而获得更好的拟合。

这可能涉及改变一些参数或超参数的值、添加/删除数据或简单地改变我们在数据预处理步骤中处理数据的方式。这一切都取决于我们从上一步中得到的评价。如前所述,最终是项目涉众定义了规则,使用这些规则,我们可以将模型分类为“足够好”,如果在评估之后,模型不是足够好,那么我们知道有些东西需要改变。

HalGatewood.comUnsplash 上拍照

幸运的是,像 GridSearchCV 这样的库可以帮助我们自动选择和评估超参数的不同组合,用于我们设计的所有步骤,从数据预处理到模型选择,一直到评估和微调。尽管计算量非常大,但这被认为是行业最佳实践。它应该只使用一次,因此即使成本很高,也是值得的,因为我们可以找到超参数的完美组合,而无需手动来回操作并反复运行模型,这很可能会变得更加昂贵。

这些算法为我们提供了所有超参数的最佳值,同时也为我们创建了优化的模型。因此,这样我们就不必使用新的超参数来重新训练机器学习模型。

模型预测

现在,我们已经有了针对给定问题的最佳机器学习模型,是时候看看该模型在完全看不见的数据上做得如何了。如果我们仍然没有使用测试集(同样,这将是罕见的,因为大多数情况下数据并不丰富),我们可以对机器学习模型进行测试,看看它在测试集上的表现如何。到目前为止,我们应该不会出现高得惊人的错误数量,因为我们已经很好地训练了模型,并接受了反馈来重新配置和优化模型。但是,即使有一些琐碎的问题,我们总是可以后退一步,采用调试方法来解决问题。

瑞安·斯通在 Unsplash 上的照片

然而,该步骤的主要目的不是解决反馈,而是设计管道和设置架构以具有适当的机器学习流程,该流程根本不需要任何人工干预来运行模型和收集其结果。设计机器学习管道是一项具有挑战性的任务,但人们可以随时查阅文档中的各种示例,并通过社区帮助来构建它们。

  • 机器学习管道将连接所有前面的步骤,并一起运行它们,以产生一个训练有素和高度优化的模型对象,该对象可以重复使用和部署,以扩大项目规模。
  • 在我们得到这个最终模型之后,我们必须设计一个数据预处理工作流,以便任何用于预测机器学习模型的新数据与用于训练机器学习模型的数据处于相同的状态。
  • 因此,来自数据仓库存储的新数据将经历与训练数据相同的数据预处理步骤。
  • 将有一个从模型到数据仓库的连接来存储结果,并使用它来使用数据可视化工具和软件(如 Tableau 和 PowerBI)制作报告和仪表板。

其他机器学习框架

还有其他几个机器学习过程,但它们或多或少都非常相似。一些专注于机器学习算法实现,而一些专注于部署流程。如果你试图建立一个数据优先的组织和方法,参考所有的框架总是好的。我发现这些流行的方法很有用-

最后,我们在此结束循环,新数据的结果将呈现给项目干系人,以帮助他们构建洞察力并做出数据驱动的决策。这就是一个端到端的机器学习项目是如何设计并成功执行的。在这篇文章中,我想给你一个过程或者模板,你可以在你自己的项目中重复使用。将机器学习应用于一个全新的问题可能有点令人不知所措,有时甚至令人望而生畏。这种机器学习过程模板将指导您,并让您在您必须执行的所有任务上保持正轨,同时可能为您节省大量时间。

感谢您的阅读!

原载于 2021 年 3 月 29 日 https://thedatascienceportal.com**。请访问数据科学门户网站,了解更多此类内容!

*https://thedatascienceportal.com *

机器学习:进度检查和混凝土的气候变化足迹

原文:https://towardsdatascience.com/machine-learning-progress-check-and-concretes-climate-change-footprint-4614749d58e2?source=collection_archive---------62-----------------------

随着时间的推移,我的技能有了怎样的提高?关于气候变化的影响,混凝土属性建模能告诉我什么?

Mikel Parera 在 Unsplash 上的照片

自从我第一次发现 UCI 数据集来预测混凝土抗压强度,已经有一段时间了(一年多)。

我记得努力分析别人的代码,破译他们的思维过程,然后试图理解我不断收到的持久性 Python 错误消息。我一直没时间做模型!

所以我很好奇:我现在看起来怎么样?然后我心中的化学工程师变得更加好奇:关于混凝土的特性及其影响气候变化的能力,我能了解到什么?

下面是带有支持代码的 GitHub repo

本文摘要:

  • 定义问题
  • 数据加载和分析
  • 开发模型并评估性能
  • 部署最佳模型
  • 结论:客户的外卖

让我们看看我的模型相对于我第一次看到这个数据集时看到的其他人的工作表现如何。该代码实现了 0.84 的 R 平方和 41.2 的均方误差。比较其他人的表现这里、这里这里这里达到相同或稍好的表现。

免责声明:这只是一个通过使用方便的指标和容易获得的数据集来衡量我的进展的练习。这与收集和清理数据以及大规模建设管道的实用性相去甚远。

努力应该指向那里,而不是在工业规模上取得毫无意义的微小进步。

定义问题

混凝土的抗压强度与其质量成正比,预测这一特性是有价值的,而无需进行昂贵且有问题的测试。其他博客如 this 提供了我们为什么要解决这个问题的更多背景信息。

博客中较少提及的是混凝土在气候变化中的作用——这篇文章为全球 4 %- 8%的二氧化碳分配了具体的责任。维基百科将这些排放的 50%分配给化学生产过程,40%分配给燃烧燃料。关键因素是:

  • 混凝土中的水泥量,因为每生产一吨水泥会排放 900 千克二氧化碳
  • 固化混凝土所需的加热程度。

减少排放的选项包括用影响较小的物质(如粉煤灰和其他液体添加剂)替代混凝土。因此,让我们扩大这一努力的范围来一窥这种影响。

数据加载和分析

在使用 Pandas 读取数据后,让我们感受一下不同的特征以及它们之间的关联程度:

import pandas as pd, numpy as np
import seaborn as snsdf = pd.read_excel('Concrete_Data.xls',keep_default_na=False)df.columns = [x.replace('(kg in a m^3 mixture)',"")for x in df.columns]
df.columns = [x.replace("(","")for x in df.columns]
df.columns = [x.replace(")","")for x in df.columns]df.describe()import matplotlib.pyplot as pltplt.figure(figsize=(8,8))
sns.heatmap(df.corr(),annot=True)plt.show()

图 1:数据集分布

图 2:特征关联矩阵

以上要点:

  • 特征的比例显示了变化,所以我可能需要使用缩放来充分利用基于距离的算法,例如 kNN
  • 没有一个特征显示出与我们感兴趣的 y 变量的压倒性相关性,最高的是超塑化剂组分 5 (0.37)
  • 粉煤灰含量与水泥含量呈负相关——考虑到我们在介绍中了解到的情况,这并不奇怪。

开发模型并评估性能

我将使用一个流行的 AutoML 包,名为 TPOT,是基于树的管道优化工具的缩写。我期待一个带有预处理和建模步骤的便捷管道。

*# Packages to install TPOT*
%pip install tpot
import tpot*# Importing TPOT Regressor and means to setup the cross validation*
from tpot import TPOTRegressor
from sklearn.metrics import mean_squared_error
from sklearn.model_selection import KFoldcv_tpot = RepeatedKFold(n_splits=10, n_repeats=3, random_state=1)*# Setting up the TPOTRegressor.*
reason_model = TPOTRegressor(cv=cv_tpot,
                             generations=10, population_size=50,
                             scoring='neg_root_mean_squared_error', 

                      verbosity=2, random_state=1, n_jobs=-1, 
                      early_stop=15)
reason_model.fit(x,y)reason_model.export('best_model.py')

我选择了 10 代和 50 的人口规模,以避免花费过多的时间建模。

拟合结果:

图 2

这份简历看起来很有希望。我从导出的 best_model.py 中取出脚本,并使用 TPOT 推荐的管道在测试集上评估模型性能。

from sklearn.model_selection import train_test_split
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import PolynomialFeatures
from tpot.builtins import ZeroCountfrom tpot.export_utils import set_param_recursive# NOTE: Make sure that the outcome column is labeled 'target' in the data file
tpot_data = pd.read_excel('Concrete_Data.xls', dtype=np.float64)tpot_data.columns = [x.replace('(kg in a m^3 mixture)',"")for x in df.columns]
tpot_data.columns = [x.replace("(","")for x in df.columns]
tpot_data.columns = [x.replace(")","")for x in df.columns]features = tpot_data.drop('Concrete compressive strengthMPa, megapascals ', axis=1)
training_features, testing_features, training_target, testing_target = \
            train_test_split(features, tpot_data['Concrete compressive strengthMPa, megapascals '], random_state=1)**exported_pipeline = make_pipeline(
    ZeroCount(),
    PolynomialFeatures(degree=2, include_bias=False, interaction_only=False),
    XGBRegressor(learning_rate=0.1, max_depth=7, min_child_weight=14, n_estimators=100, nthread=1, objective="reg:squarederror", subsample=0.8)**-- from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_scorermse = np.sqrt(mean_squared_error(results,testing_target))
r2 = r2_score(results,testing_target)print('The root mean square error of predictions is {y} and R-squared value is {x}'.format(y=round(rmse,2),x=round(r2,2)))

图 3:最佳模型性能

这是可以接受的性能,超过了我对其他尝试的快速调查。分析 TPOT 的选择,我对多项式特征预处理的使用并不感到惊讶,这表明原始特征之间存在依赖关系,所有这些都会影响具体的属性。

部署最佳型号

在这篇文章中,我已经详细介绍了使用 Flask 部署模型的细节——下面是用户指定输入并获得最终混凝土强度(MPa)的界面快照

图 4:输入和输出接口

结论:客户的外卖

如果我们的客户负责混凝土保证,他们可以高枕无忧,因为他们知道我们可以用混凝土抗压强度的准确预测器取代他们昂贵的测试设备。

But——如果我们希望降低混凝土对气候变化的影响,同时实现这种传统混凝土所需的平均抗压强度 17–28 MPa链接——那么让我们分析下面的交互式可视化。

我的外卖:

  • 混凝土制造商应该能够在粉煤灰和水泥浓度大致相等的情况下达到 17-25 MPa,大约为 140-150kg/m3
  • 我们还没有到那一步——如果我们参考详细描述数据集分布的图 1,飞灰含量的第 75 百分位是 118 kg/m3,而水泥的四分位范围是 192–350kg/m3。
  • 我们有空间来改善这里的气候!

一如既往,我欢迎任何意见/建议。

机器学习项目和 Scrum:一个主要的不匹配

原文:https://towardsdatascience.com/machine-learning-projects-and-scrum-a-major-mismatch-c155ad8e2eee?source=collection_archive---------14-----------------------

为什么数据科学和机器学习并不真正适合 scrum?

杰克·纳格兹在 Unsplash 上的照片

在现代软件开发中,敏捷产品管理技术如 Scrum 经常被用于开发软件产品。对于机器学习和数据科学项目, Scrum 经常看起来不合适,因为它将一个数据驱动的项目强加到一个自然不适合的框架中。这篇文章从工程师的角度总结了我在 Scrum 和机器学习项目中的一些经验,并试图找到不匹配的原因,并将这两个世界联系起来。

敏捷 Scrum

Scrum 是面向产品的,它是关于让产品处于可交付状态,并逐步引入更新。Scrum 通常涉及几个现代软件工程实践,比如以冲刺、计划、评估和每日会议组织的连续交付/集成。这涉及到相当多的过程,通常用类似吉拉的工具来管理。

首先让我们谈谈 scrum 在实践中是如何使用的。它用于跟踪软件开发过程,按照交付或增强软件产品的小步骤,并尽早从客户那里获得反馈。敏捷的思想是授权给团队、跨功能和自组织。然而,Scrum 经常被错误地用作微观管理的现代方法,并且经常以软件开发的装配线而告终,阻碍了创新(但这是另一篇文章的主题)。

机器学习的研究本质

机器学习项目不同于典型的软件工程项目。ML 项目很可能失败,因为不清楚数据是否包括实现目标所需的信息,或者是否存在可以对数据建模的方法。另一方面,此类项目可以带来高回报,例如,自动化高成本流程、引入创新或自动化决策。与典型的产品迭代相比,机器学习项目的可预测性有限。它们也是迭代项目,但是它们需要开放的项目阶段,并且需要进行重大变更的灵活性。一旦明确了一个模型的工作原理,它就变得更像一个典型的软件产品。

典型的数据科学项目如下所示:

  1. 研究阶段
  • 数据采集
  • 数据理解
  • 特征工程
  • 模型结构
  • 模型评估

2.分送相

  • 综合
  • 测试
  • 部署
  • 监视

阶段 1——建模

整个第一阶段并不真正适合 scrum 方法。你不是在处理可交付成果,你的增量和进一步的步骤是不可规划的。没有什么比持续的可交付资产更好的了。团队或个人不能承诺未知的事情,也不能被评估。

估计甚至更多的是抛出随机数,因为它已经在 scrum 中出现了。在项目的这个阶段,一切都是快速原型制作,非常像研究。在评审会议中,您不能真正地使进展可见,因为在您建立模型之前没有任何东西可以展示。同样,短跑的时间框架也不合适。

构建分类模型与集成外部 API 不可同日而语。有很多不确定性,从 A 到 B 没有明确的路径,由于缺少或不适当的数据,可能最好停止项目并开始其他项目。没有什么比可测量的速度和承诺更好的了。

总而言之,Scrum 引入了大量的开销,而且没有帮助。只有每天的会议才能有助于讨论进展和障碍,但这不是我们需要 Scrum 的原因。

第 2 阶段—交付

另一边的集成和部署是典型的软件工程。通常这部分项目被高度低估。一旦你完成了初步的建模来证明可行性,你就可以计划下一步了。

这将概述让数据科学家构建模型和机器学习工程师部署模型的想法。在大型团队中,这是可能的,但是它也引入了许多摩擦和通信开销。建模和部署的分离可能容易出错,并且不符合现代“您构建它,您运行它”的 DevOps 思想。这并不意味着数据科学家应该是一个成熟的软件工程师,而是知道如何通过 API 或任何其他集成使他的模型在软件环境中工作。在我看来,我们不应该忽视已经学到的软件工程知识,而应用 MLOps

将来可能会有一些更好的工具,使实验和部署更容易联系起来。是的,对于一些标准用例,已经有可用的工具和框架,但通常我们不处理那些标准用例。拥有一个数据科学平台,而你的用例并不在其中,通常是一场噩梦。

兼职 Scrum

为了解决这个问题,可以让数据科学家成为 scrum 团队的兼职成员。想法是以看板风格组织第一阶段,只涉及很少的流程,在第一次迭代之后,遵循 scrum 进行部署和集成,以利用 scrum 流程。在这种情况下,可以调整团队,细化技术和非技术需求。

一旦模型被集成,数据科学家就离开 scrum 团队,开始下一个模型或者建模的下一次迭代。

结论

对于建模部分,scrum 并不适合。建模和不确定性的研究本质使得将数据科学嵌入到 scrum 中感觉不合适。机器学习模型不是什么东西,是可以持续交付的。但是一旦你有了一个模型,并且你想要遵循 DevOps 原则,让数据科学家拥有他/她的模型,你就可以遵循 scrum 过程。在这种设置中,数据科学家是 scrum 团队的一部分,更好地理解 scrum 是如何工作的,可以参与他们模型的集成过程,并了解在构建软件产品时有哪些挑战。

云上的机器学习项目——过程中的关键步骤

原文:https://towardsdatascience.com/machine-learning-projects-on-the-cloud-key-steps-in-the-process-d61f67d9d454?source=collection_archive---------21-----------------------

在本文中,我着眼于理解当部署在云系统(如 Microsoft Azure 平台)上时,数据科学过程需要如何发展。

照片由吉井博子Unsplash 上拍摄

在云上部署 ML 模型肯定不同于在您的系统上使用 Jupyter 笔记本。但是更重要的是理解云系统以及 ML 解决方案是如何部署的。机器学习和数据科学迄今为止的发展方式,我们都非常适应我们的 Jupyter 笔记本工作方式。不幸的是,这不太符合组织中收集、存储和处理数据的方式。随着数据量的增加,在系统上工作变得不可行,越来越多的机器学习项目正在从试点项目模式转向云。许多项目涉及数 Pb 的数据,基于云的解决方案是唯一的答案。此外,大多数大型组织都在投资基于云的数据基础架构。大玩家是 AWS 和微软 Azure。因此,无论您是初级数据科学家还是高级数据科学家,某种基于云的接触都变得至关重要。

在这篇文章中,我将讨论在 Azure 系统中从头开始开发项目的过程。这实际上是熟悉的领域,但并不相同。考虑到云系统很复杂,并且有许多与访问、权限、数据存储类型、ETL、数据处理方式等相关的层,因此需要对该方法进行一些修改。此外,一旦我们将项目转移到云中,它肯定会从我们的“宝贝”变成需要各种其他角色的支持,包括数据工程师和解决方案架构师。一个人有可能扮演这些角色吗?必要时可能会。但是对于大多数组织中 IT 部门的结构来说,这可能是不可能的。

这篇文章具体介绍的是数据科学项目过程的终结以及它是如何发生的。这既包括云上的资源调配(不是屏幕截图的确切过程,但更像是您在存储和计算能力方面的需求),也包括设置、培训、测试和部署模型的过程。如前所述,我已经将这一点具体化为 Azure,但我确信类似的构造也可以用于 AWS。我也强烈建议浏览一下微软 Azure 关于团队数据科学过程的文档——这里的链接是。

使用基于云的系统的数据科学流程

图片作者,灵感来自https://docs . Microsoft . com/en-us/azure/machine-learning/team-data-science-process/overview

上图完美地展示了基于云的数据科学流程,在较高的层面上,它看起来类似于传统的数据科学流程。然而,魔鬼真的在细节中。让我们详细看看每一步。

第一步:业务理解

这一步处理理解数据科学项目的业务需求。通常,这一步要求我们定义可能使用数据科学解决方案的业务问题。现在,商业问题往往是全球性的大问题。数据科学解决方案可能只是整个业务问题的一小部分。数据科学应用程序可能希望开发可作为业务流程一部分的自动化或应用程序。例如,机器学习引导的自动化可以提高电子邮件的针对性,从而提高打开率,这是通过营销电子邮件吸引客户的更大目标的一部分。因此,明确两者的区别很重要。

一旦确定了与数据科学应用程序相关的特定业务目标,下一步就是确定数据科学问题要解决的问题类型。概括地说,数据科学通常寻求解决 5 种类型的问题:

  1. 预测“多少”通常是一个回归类型的问题
  2. 将观察结果分类——通常是一个分类问题
  3. 识别未知数据集中的组—通常是一个聚类问题
  4. 试图评估“这是否奇怪”——这通常是一个异常检测问题
  5. 确定应该提供哪些选项—一个推荐问题

一旦确定了数据科学可以帮助解决的关键问题,我们还可以尝试确定目标变量,例如,它可以是业务的关键 KPI。在这个阶段,我们还应该尝试对机器学习算法的“好”的定义。例如,这可以是期望的或使解决方案可接受的精度百分比、MAPE 或 MSE。

讨论如何在生产环境中部署解决方案也很有用,尽管这部分讨论可能是假设性的。在这一阶段,还应讨论如何确定数据来源。还应该对云资源供应进行一些讨论。云的一个问题是,与本地系统不同,云上的虚拟机带有电荷,因此需要充电。一般来说,所有计算、存储和部署应用程序都会有一些相关成本,并且很可能会受到限制。因此,重要的是要注意可能需要展示清楚的商业利益。

通常,步骤 1 由项目章程或范围界定文档签署。这一点非常重要,因为数据科学项目本质上是高度进化的,关于协议和范围的文档非常关键。

第二步:识别和理解数据源

识别

这一步可能需要最长的时间。大多数组织中的数据杂乱、不完整且难以获得。如果数据在云中,事情实际上会变得更好,因为当数据被摄入云存储时,可能已经经过了某种协调和合理化。然而,云中的数据也意味着它不一定更容易到达。如上所述,需要调配数据以及计算和分析资源。考虑到这一点,如果从“内部”数据仓库中提取一个平面文件,用于在分析师自己的笔记本电脑上进行分析,那么对结果的扫描就不仅仅是扫描了。审查数据源时,最好了解它们是哪种类型:内部还是云。无论是通过流水线还是通过批处理。无论是存储在数据湖还是 SQL 数据库中。

这一阶段的目标是确定高质量的数据,用于实施最初的试点项目,然后开发数据管道,自动刷新数据并对数据进行评分。

对数据的理解

数据理解遵循探索性数据分析、数据清理、识别缺失值和异常值以及确定估算它们的最佳方法的标准流程。这个过程通常是迭代的。

一旦审查了数据质量,处理了异常值和缺失值,下一步就是理解数据中的模式以选择合适的分析模型。EDA 的重点应该是:

  • 确定是否有足够的数据用于建模
  • 识别与目标变量密切相关的变量
  • 确定变量之间的模式和相互联系,这些变量可以作为建模的特征工程阶段的先导

步骤 2a:准备解决方案架构

这是我们开始偏离本地机器上的方法的第一点。云系统的一个关键特性是所有数据都以各种形式存在,比如数据湖。通过构建自动化的数据管道,可以很容易地将它应用于 ML 应用程序。这有利于使整个端到端过程自动化。与运行在组织服务器或数据科学家的本地机器上的模型不同,该模型可以建立自动化管道,用于数据评分和再培训。

在这一点上,我们需要开始考虑云架构以及如何实现数据流的自动化。这可以通过自动化管道或工作流来完成。该架构将由管道组成,用于:

  • 获得新数据
  • 基于新数据的再训练模型

通过为耗时且反复的任务(如 EDA、模型训练和验证)开发自动化,可以使这一过程更高级。然而,如果我们处于模型开发阶段的早期,我们可以专注于评分管道。

第三步:特征工程

这是开发建模过程的阶段。这通常是一个反复的过程。第一步是执行特征工程以识别用于建模的最佳变量,第二步是执行模型训练。

特征工程是建模步骤中一个复杂而关键的过程。它本质上经常是迭代的。特征工程的一个重要部分是利用领域和业务知识进行 EDA,包括变量和变量转换。一个关键的平衡行为是识别与目标变量密切相关的变量,以及包含太多变量会导致模型中包含噪声。

第四步:模型训练和验证

模型训练程序是标准的。如果有足够的数据,我们可以采用“测试-训练”方法。使用基于云的资源进行分析的优势之一是灵活计算资源的可用性。这使得可以一次测试多个模型和超参数调整,并比较结果。要使用的算法取决于:

  • 需要回答的业务问题(预测、分类、探索等)
  • 数据量和带标签的训练数据的可用性
  • 数据场景在准确性方面的要求—衡量模型的整体有效性
  • 参数数量-这些参数用于提高模型的拟合度,如误差容差或迭代次数

Azure 等云系统提供 AutoML 等全自动机器学习服务。在训练过程中,Auto ML 创建了许多并行尝试不同算法以及超参数调整的管道。当达到目标退出标准(如准确度百分比)时,它将退出运行。Auto ML 还可以通过投票或堆叠集成方法实现简单的集成建模。它还包括最佳做法,以避免过度拟合使用正则化(L1,L2 和弹性网)。其他最佳实践,如 K 折叠交叉验证,可以使用预构建的模块轻松合并。

Azure ML 的其他优势包括集中式工作区,可以跟踪运行 ML 模型时创建的工件。其中包括所有模型、日志、指标、输出和脚本的历史记录。通过分配用户角色来共享工作场所无疑是云工作的一大优势,通过高效协作的劳动分工使项目进行得更快。

第五步:部署模型和监控

型号部署

一旦模型被认为符合目的,并被业务部门批准,我们就可以继续以更具可伸缩性的方式部署模型。基于云的系统使得模型部署变得更加容易和快速。模型的部署通常是设置模型的过程,以便它可以使用新数据。在生产期间部署您的 AI 模型时,您需要考虑它将如何进行预测。人工智能模型的两个主要过程是:

批量推断:基于一批观察结果进行预测的过程。然后,这些预测将作为文件存储在最终用户或业务应用程序的数据库中。当需要异步处理大量数据时,这很有用。

实时(或交互式)推理:模型随时做出预测,并引发即时反应。该模式可用于分析流和交互式应用程序数据。

部署期间的机器学习推理,未注明。

模式监控

模型部署的一个重要方面是监控模型,以确保它在技术上是可行的,并且能够生成预测。如果一个组织的应用程序依赖于模型并实时使用它,这是很重要的。其次,监控模型性能以检查它连续生成的预测是否相关是很重要的。

另一个需要注意的重要事项是,当用于定型模型的数据与预测阶段发送给模型的数据之间存在显著差异时,是否会发生数据漂移。造成数据漂移的原因有很多,包括传感器问题、季节性、用户行为变化以及与数据源相关的数据质量问题。云平台通常内置这一功能,以支持带有数据漂移的模型监控。然后,这可以提供一个警告,即模型需要用更相关的数据重新训练。然而,并不是所有情况下都需要模型再训练,所以建议在投入再训练之前调查并理解数据漂移的原因。通常的调查是收集生产数据和培训数据,并对其进行 EDA。

重新训练模型从来都不是一个完全自动化的过程。必须检查模型中非常明显的数据漂移或数据变化——例如,如果模型需要部署到新的区域。最初,组织通常只自动化模型的培训和部署,而不自动化验证、监控和再培训步骤,这些都是手动执行的。

最终想法

这是对“新瓶装旧酒”的长期报复,即数据科学过程转移到云,而不是使用服务器和各种笔记本电脑在“内部”进行。很明显,云在可扩展性、协作工作场所、许多关键机器学习算法和过程的预编程模块方面具有显著优势。基于云的方法的缺点是,机器学习项目不能很快进行试点。即使是一个简单的试点项目,也需要安排大量的基础设施。其次,基于云的解决方案也带来了对数据工程师和机器学习工程师等资源的需求。

参考文献

本文基于微软关于机器学习、数据科学、AutoML、部署等 Azure 平台的文档。在参考文献列表中,我提到了我参考较多的页面。

  1. 数据科学家团队数据科学流程。(未注明)。docs.Microsoft.com。2021 年 3 月 31 日检索,来自https://docs . Microsoft . com/en-us/azure/machine-learning/team-data-science-process/team-data-science-process-for-data-scientists
  2. 部署过程中的机器学习推理。(未注明)。docs.Microsoft.com。2021 年 4 月 2 日检索,来自https://docs . Microsoft . com/en-us/azure/cloud-adoption-framework/innovate/best-practices/ml-deployment-inference
  3. https://docs . Microsoft . com/en-us/azure/machine-learning/team-data-science-process/概述
  4. https://docs.microsoft.com/en-us/azure/machine-learning/

现实生活中的机器学习正则化技术

原文:https://towardsdatascience.com/machine-learning-regularization-techniques-in-real-life-your-dogs-nap-time-as-a-regularized-9c533510fe83?source=collection_archive---------26-----------------------

实践教程

你的狗的午睡时间作为一个正规化的线性模型

作者图片

当你建立一个机器学习模型时,你面临着偏差-方差权衡,你必须在拥有一个模型之间找到平衡:

  1. 非常有表现力,能够捕捉数据中的真实模式。
  2. 生成与实际值相差不太远的预测,

一个非常有表现力的模型具有较低的偏差,但它也可能过于复杂。而生成的预测与真实值相差不太远的模型方差较低。

过度拟合

当模型过于复杂,并试图从训练数据中编码比实际需要更多的模式时,它将开始拾取噪声。因为它已经超出了数据的真实模式,这个模型过度拟合了数据。

过度拟合通常发生在当您的训练集很小,小到无法展示数据中的所有细微差别和模式时。由于只有少量的数据可以学习,该模型最终只高度关注它可以在训练集中看到的模式。因此,该模型是不可推广的,这意味着它不会很好地预测它以前从未见过的数据的目标。

过度拟合模型也是一种不可概括的模型,因为它经过了微调,可以预测训练集中数据的目标。

这就是正规化的用武之地!您可以使用正则化技术来控制过度拟合,并创建具有高预测准确性的模型,同时尽可能保持模型的简单性。

在实践中,正则化调整系数的值。有些系数最终对模型的贡献可以忽略不计,甚至等于零,您可以放心地在模型中忽略它们。这就是为什么正则化技术也被称为收缩技术。

正则化技术也被称为收缩技术,因为它们收缩了系数的值。有些系数可以缩小到零。

尽管正则化通常用于线性模型,但它也可以应用于非线性模型

(狗)打盹的一年

现在你在家的时间越来越多了,你可以看到你的狗睡了多长时间了!

日常生活并没有太大变化,但是你会注意到午睡的持续时间是变化的,这取决于他们做什么或者他们和谁互动。

如果你能预测你的狗明天会睡多久,这不是很有趣吗?

经过一番思考,你可以想到影响你的狗午睡时间的四个主要因素:

  • 他们得到了多少次干的款待
  • 他们一天有多少游戏时间
  • 如果他们看到松鼠潜伏在后院,
  • 如果你有包裹送上门。

其中一些活动和互动可能会产生焦虑,其他的只是纯粹的兴奋。总的来说,它们会影响你的狗的能量水平,从而影响它们一天的午睡时间。

既然你想预测你的狗的午睡时间,你开始把它想成一个多元线性模型

影响午睡时间的不同因素是自变量,而午睡时间本身是因变量。

在机器学习术语中,自变量是特性而因变量,你要预测的,是模型目标

将你的狗的午睡时间建模为多元线性模型。

查看这个小睡持续时间模型, Beta 0截距,当所有特征都等于零时目标采用的值。

剩余的贝塔系数是未知的系数,它和截距一起是模型中缺失的部分。您可以观察不同功能组合的结果,但是您不知道每个功能如何影响目标的所有细节。

一旦你确定了每个系数的值,你就知道了方向,正的或负的,以及每个特性对目标的影响的大小。

对于线性模型,您假设所有的特征都是相互独立的,因此,例如,您收到一份快递对您的狗一天得到多少份零食没有任何影响。

此外,您认为特征和目标之间存在线性关系。

所以,在你和你的狗玩得越多的日子里,它们会越来越累,会想睡得更久。或者,在外面没有松鼠的日子里,你的狗不需要睡那么久,因为它们不会花那么多精力保持警惕,留意松鼠的一举一动。

你的狗明天要睡多久?

在脑海中有了模型的大致想法后,你收集了几天的数据。现在,您对模型的特征和目标有了真实的观察。

对你的狗午睡期间的特征和目标进行几天的观察。

但是仍然缺少一些关键部分,即系数值和截距。

寻找线性模型系数的最流行的方法之一是普通最小二乘法

普通最小二乘法(OLS)的前提是,你将选择最小化 残差平方和 的系数,即你的预测和观测数据之间的总平方差【1】。

对于残差平方和,并不是所有的残差都被同等对待。您希望举例说明模型生成的预测与观察值相差太远的情况。

与其说预测值与观测值相差太远,不如说是误差的大小。你对残差求平方,并惩罚太远的预测,同时确保你只处理正值。

对于残差平方和,预测值与观测值相差太多无关,而是与误差的大小有关。

这样,当 RSS 为零时,它实际上意味着预测值和观察值相等,而不仅仅是算术的副产品。

在 python 中,可以使用普通的最小二乘法使用 ScikitLearn 来拟合数据的线性模型。

由于您希望使用未经训练的数据来测试模型,因此您希望将原始数据集的一部分放入测试集中。在这种情况下,测试数据集随机留出 20%的原始数据集。

import numpy as np
from sklearn.model_selection import train_test_split
from sklearn import linear_model def get_bias(predicted_values, true_values): *""" Calculates model bias
    :param predicted_values: values predicted by the model
    :param true_values: true target values for the data
    :return: integer representing the bias of the model
    """* return np.round(np.mean((predicted_values - true_values) ** 2), 0)def get_variance(values):
    *""" Calculates variance of an array of values
    :param values: array of values
    :return: integer representing the variance of the values
    """* return np.round(np.var(values), 0)def fit_model(features, targets, type='Linear', alpha=0.5):
    *"""
    Fits a linear model or the Lasso and Ridge regularizations.
    :param features: model features
    :param targets: model targets
    :param type: type of model to fit (Linear with OLS, Lasso and Ridge Regularizations)
    :param alpha: regularization penalty
    """* train_features, test_features, train_targets, test_targets =
train_test_split(features, targets, test_size=0.2, random_state=123) if type == 'Lasso':
        model = linear_model.Lasso(alpha=alpha)
    elif type == 'Ridge':
        model = linear_model.Ridge(alpha=alpha)
    elif type == 'Linear':
        model = linear_model.LinearRegression()
    else:
        return None fitted_model = model.fit(train_features, train_targets)
    predictions = fitted_model.predict(test_features)
    print('\n\n[' + type + '] model:')
    print('-----------------------------------------') print('Coefficients: ' + str(fitted_model.coef_))
    print('Intercept: ' + str(fitted_model.intercept_))
    print('R-squared: ' + str(fitted_model.score(train_features, np.array(train_targets).reshape(-1, 1)))) print('Bias:' + str(get_bias(predictions, test_targets)))
    print('Variance:' + str(get_variance(predictions)))features = [[3, 40, 1, 0],
            [1, 60, 0, 0],
            [4, 35, 1, 1],
            [2, 60, 0, 1],
            [0, 0, 1, 0],
            [4, 25, 1, 0],
            [3, 15, 1, 0],
            [1, 15, 1, 1],
            [4, 10, 1, 0]]targets = [120, 24, 95, 135, 48, 105, 75, 80, 30]
fit_model(features, targets)

将线性模型拟合到训练集后,可以检查其特征。

系数和截距是定义模型和进行预测所需的最后一部分。输出数组中的系数遵循数据集中要素的顺序,因此您的模型可以写成:

计算一些度量来评估模型的质量也是有用的。

R 平方,也称为决定系数,给出了模型在描述训练数据中的模式方面有多好的感觉,其值范围为 0 到 1。它显示了目标中有多少可变性是由特征解释的[1]。

例如,如果你用一个线性模型来拟合数据,但是目标和特征之间没有线性关系,R 平方将非常接近于零。

偏差和方差是有助于平衡模型可能存在的两种误差来源的指标:

  • 偏差与训练误差有关,即来自训练集预测的误差。
  • 方差与泛化误差有关,即测试集上的预测误差。

这个线性模型具有相对较高的方差。让我们使用正则化来减少方差,同时尽量保持较低的偏差。

模型正则化

正则化是一组在以下方面改进线性模型的技术:

  • 预测准确性,通过减少模型预测的方差。
  • 可解释性,通过收缩或将与模型不相关的系数减少到零【2】。

使用普通的最小二乘法,您希望最小化残差平方和(RSS)。

但是,在普通最小二乘法的正则化版本中,您希望收缩它的一些系数以减少整体模型方差。你可以通过对剩余平方和进行惩罚来达到这个目的。

在 OLS 的正则化版本中,你试图找到最小化的系数:

收缩损失是调整参数和回归系数的乘积,因此随着损失的回归系数部分变小,损失也会变小。调谐参数控制剩余平方和收缩损失的影响。

收缩损失永远不会应用于β0(截距),因为您只想控制系数对特征的影响,而截距没有与之关联的特征。如果所有特征的系数都为零,则目标值将等于截距值。

有两种不同的正则化技术可应用于 OLS:

  • 岭回归,
  • 套索。

里脊回归

岭回归使系数的平方和最小化。

它也被称为 L2 范数,因为随着调谐参数λ的增加,最小二乘系数向量的范数将总是减小。

即使它以相同的比例收缩每个模型系数,岭回归实际上永远不会将它们收缩到零。

使这种正则化更稳定的方面也是它的缺点之一。您最终减少了模型的方差,但是模型保持了它原来的复杂程度,因为没有一个系数减少到零。

通过运行以下代码,可以用岭回归拟合模型。

fit_model(features, targets, type='Ridge')

这里的λ,即 scikit 学习方法中的 alpha,被任意设置为 0.5,但在下一节中,您将经历调整该参数的过程。

基于岭回归的输出,您的狗的午睡持续时间可以建模为:

查看模型的其他特征,如 R 平方、偏差和方差,您可以看到,与 OLS 的输出相比,所有这些都减少了。

岭回归在收缩系数的值时非常有效,因此,模型的方差显著降低。

然而,模型的复杂性和可解释性保持不变。你仍然有四个影响你的狗每天午睡时间的特征。

让我们转向套索,看看它的表现如何。

套索

Lasso 是最小绝对收缩和选择算子【2】的简称,它最小化系数的绝对值之和。

它非常类似于岭回归,但是它使用 L1 范数作为收缩惩罚的一部分,而不是 L2 范数。这就是为什么 Lasso 也被称为 L1 正则化。

Lasso 的强大之处在于,它实际上会一些系数缩小到零,从而降低方差和模型复杂性。

Lasso 使用了一种叫做软阈值的技术。它将每个系数收缩一个恒定的量,这样,当系数值低于收缩常数时,它将减少到零。

同样,使用 0.5 的任意λ,您可以将 lasso 拟合到数据。

fit_model(features, targets, type='Lasso')

在这种情况下,您可以看到功能松鼠被从模型中删除,因为它的系数为零。

使用 Lasso,您的狗的午睡持续时间可以描述为具有三个特征的模型:

这里,相对于岭回归的优势在于,你最终得到了一个更易解释的模型,因为它的特征更少。

从可解释性的角度来看,从四个到三个要素并不是什么大事,但是您可以看到这在具有数百个要素的数据集中是多么有用!

找到你的最佳λ

到目前为止,你用来看岭回归和套索的方式是完全随意的。但是有一种方法可以微调λ的值,以保证可以降低整体模型的方差。

如果你对一组连续的λ值绘制均方根误差,你可以使用 肘技术 找到最优值。

使用肘技术为套索和岭回归寻找最佳λ值。

此图强调了岭回归比套索更稳定的事实。可以看到,对于起始值λ= 0.01,误差开始非常高,但随后稳定在 2.5 左右。因此,对于岭回归,2.5 的λ将是最佳值,因为在此之后误差会略微增加。

至于套索,有更多的变化。放大以获得更多细节,当λ在 0.15 和 0.2 之间时,误差实际上开始变得更糟,然后在λ= 15 左右稳定下来。

以下是如何用 Python 创建这些图。

def find_lambda(features, targets, plot_type=''):
    train_features, test_features, train_targets, test_targets = train_test_split(features, targets, test_size=0.2, random_state=123) lambda_array =[]
    rmse_array_lasso = []
    rmse_array_ridge = []
    line_color = ['#021E73', '#F27272'] stop = 20
    step = 0.25 if plot_type == 'zoom':
        stop = 1
        step = 0.01 for lambda_value in np.arange(start=0.01, stop=stop, step=step):
        lambda_array.append(lambda_value)

        model_lasso = linear_model.Lasso(alpha=lambda_value)
        fitted_model_lasso = model_lasso.fit(train_features, train_targets)
        predictions_lasso= fitted_model_lasso.predict(test_features)
        rmse_array_lasso.append(mean_squared_error(test_targets, predictions_lasso, squared=True)) model_ridge = linear_model.Ridge(alpha=lambda_value)
        fitted_model_ridge = model_ridge.fit(train_features, train_targets)
        predictions_ridge= fitted_model_ridge.predict(test_features)
        rmse_array_ridge.append(mean_squared_error(test_targets, predictions_ridge, squared=True)) fig, ax = plt.subplots(figsize=(12, 7)) # removing to and right border
    ax.spines['top'].set_visible(False)
    ax.spines['right'].set_visible(False) # adding major gridlines
    ax.grid(color='grey', linestyle='-', linewidth=0.25, alpha=0.5) # axis labels
    ax.set_xlabel(r'$\lambda$')
    ax.set_ylabel('RMSE') plt.plot(lambda_array, rmse_array_lasso, color=line_color[0], linewidth=3, label='Lasso')
    plt.plot(lambda_array, rmse_array_ridge, color=line_color[1], linewidth=3, label='Ridge')
    plt.legend(loc='upper right') if plot_type == 'zoom':
        ax.xaxis.set_ticks(np.arange(0., 1, 0.05)) plt.savefig('output/lambda_tuning_' + plot_type + '.png')find_lambda(features, targets)
find_lambda(features, targets, plot_type='zoom')

我们可以通过再次拟合数据来验证这一点,现在使用了更有针对性的值。

fit_model(features, targets, type='Lasso', alpha=0.01)
fit_model(features, targets, type='Lasso', alpha=0.017)
fit_model(features, targets, type='Lasso', alpha=1)
fit_model(features, targets, type='Lasso', alpha=15)fit_model(features, targets, type='Ridge', alpha=0.01)
fit_model(features, targets, type='Ridge', alpha=0.017)
fit_model(features, targets, type='Ridge', alpha=2.5)
fit_model(features, targets, type='Ridge', alpha=15)

您可以确认,对于 Lasso,方差首先变得更差,但随后逐渐变好,并稳定在等于 15 的λ附近。在这一点上,Lasso 从模型中去掉了松鼠,与λ的较低值相比,总体方差显著降低。

使用套索,你最终显著减少了方差和偏差。

使用岭回归,模型保持所有特征,并且随着λ增加,总体偏差和方差变低。正如您在图表中注意到的,当λ大于 2.5 时,偏差继续降低,但方差实际上变得更差。

什么时候用套索 vs 山脊?

选择正则化技术的类型将取决于模型的特征,以及您希望在模型准确性和可解释性方面做出的权衡。

当…时使用套索

您的模型中有少量特征突出,即具有高系数,而其余特征的系数可以忽略不计。

在这种情况下,Lasso 将选择主要特征,而将其他特征的系数缩小到零。

当…时使用岭回归

您的模型有许多特征,并且在模型中具有相对相似的权重,即它们的系数值非常相似。

结论

根据您正在处理的问题,与方差较低但过于复杂的模型相比,更容易解释的模型可能更有用。归根结底,这就是权衡取舍!

尽管这是一个非常小的数据集,但正则化的影响和有效性是显而易见的:

  • 调整系数和截距。具体到 Lasso,松鼠的特征可以从模型中删除,因为它的系数收缩到零。
  • 当你选择最佳的λ进行正则化时,与普通的最小二乘法相比,方差确实减少了
  • 你可以看到偏差-方差的权衡。λ为 15 的岭回归模型,与λ、值较低的模型相比,以增加方差为代价,具有较低的偏差。

希望您喜欢学习正则化如何帮助提高机器学习模型的质量。

感谢阅读!

参考

[1] Gareth James、Daniela Witten、Trevor Hastie 和 Robert Tibshirani。2014.统计学习介绍:在 R 中的应用。起拱石

2 TiB shirani,R. (1996 年)。通过套索的回归收缩和选择。j .罗亚尔。统计学家。Soc B,58,267–288

每个团队的机器学习扩展选项

原文:https://towardsdatascience.com/machine-learning-scaling-options-for-every-team-5e713d66bf03?source=collection_archive---------42-----------------------

行业笔记

卡米尔·皮特扎克Unsplash 上拍摄的照片

机器学习有无数的应用,但是将机器学习集成到一个软件应用中会面临巨大的挑战!机器学习(ML)算法很复杂,可能需要很大的二进制参数文件,并且计算量很大。此外,随着新的数据和技术变得可用,改进机器学习方法通常是有价值的,这意味着您在应用程序中合并 ML 的方法必须是灵活的。

最重要的是,构建和训练伟大的机器学习算法所需的技能与构建和扩展伟大的软件所需的技能并不相同(尽管存在重叠)。为了获得最好的结果,ML 从业者需要有能力使用各种工具来训练和迭代算法。软件工程师的目标是开发能够轻松部署、有效扩展并产生可靠结果的应用程序。这些要求意味着大规模应用机器学习的团队必须针对几个困难的目标进行优化。

我个人遇到过这个问题的很多方面。当我还是一名在 R&D 团队工作的软件工程师时,我想确保算法在生产中像在笔记本和脚本中一样有效,并且将它们集成到产品中具有成本效益。我想了很多关于自动化测试、API 定义和扩展的问题。作为一名数据科学家,我的重点不仅是训练准确的,而且是可概括的模型,这些模型将告知我们用户的行动,这将是我们的竞争对手难以复制的。现在,我带领团队关注所有这些目标,并了解这两种关注如何增加复杂性,从而可能将某个功能的投资回报从“改变游戏规则的胜利”变为“不值得”。

幸运的是,有几种方法可以将机器学习算法可扩展地集成到应用程序中。深思熟虑的技术选择可以让拥有不同技能组合的团队有可能构建 ML 应用程序。本文将介绍可扩展执行机器学习模型的方法的非穷举列表。

首先,让我们考虑一个示例服务,将即将出现的解决方案放在上下文中。

图片作者。概念性机器学习服务架构。

上图显示了应用程序的几个组件之间的信息流。

  • 其他应用程序用来触发 ML 处理或检索预测的 API 端点。
  • 决定如何处理请求的应用程序逻辑。这可以通过检索缓存的预测或通过生成新的预测来实现。
  • 可能包含 ML 算法进行预测或存储最终计算结果所需数据的存储器。
  • ML 处理,包含机器学习算法和一些执行它们的方法。我们将在这里重点讨论这个组件。

所示部件之间的实际连接可以不同于这种布置。例如,应用程序可能依赖于预处理的结果,并且没有为 API 提供交互触发模型处理的路径。

即使实际的 ML 推理足够轻便,可以在与应用程序相同的硬件资源上执行而不会遇到瓶颈,仍然值得考虑机器学习自身的需求,因为有一些独特的选项来服务它们。此外,下面概述的几个选项可以用于各种应用场景。正如我们将看到的,有相当多的方法可以合并 ML 处理组件,其中一些只需要很少的努力!

使用其他人的比例模型

最简单的方法就是使用已经可以伸缩的东西!在这种范式中,训练、验证和缩放 ML 算法处理的所有工作已经由他人完成,并且可以作为商品获得。

考虑构建一个全新的通用人工智能解决方案可能很有吸引力,但除非提出一个更好的解决方案是你核心价值主张的一部分,否则你真的能击败购买别人的解决方案的投资回报吗?此外,有才华的数据科学家和高级工程师是否有足够的时间来执行 R&D 并提出扩展解决方案?

在许多领域,高性能的模型很容易作为商品服务获得。例如,所有主要的云提供商都提供图像和语音识别服务。与使用您自己的团队所需的投资相比,您通常可以支付较低的金额来购买一个接近最先进水平并且已经作为可扩展服务提供的解决方案。并非所有领域都有解决方案,但最大的云提供商(AWS、GCP、Azure)共同为许多领域提供基于 API 的机器学习。

为了说明使用预构建解决方案的价值,假设您想要构建一个图像共享应用程序功能来确定图像是否是食品。Amazon Rekognition 可以使用几个与食品相关的标签对图像进行分类,因此您可以使用这样一个标签来解决您的问题。

Rekognition 此时的成本是每 1000 张标记的图像 1.00 美元。一百万张图片需要 1000 美元。因为交互是通过 Amazon 的 API 进行的,所以应用程序的 ML 部分的扩展需求相当少,并且可以通过您选择的任何方式来处理,以扩展应用程序的其余部分。这意味着 ML 特定的开发是最小的。1000 美元可以支付多少小时的数据科学家时间?此外,有多少小时的软件工程时间可以投入到该预算中,以扩展数据科学家提出的任何东西?很有可能,不是很多。更有效地利用这两种技能的方法是评估预构建解决方案的结果和方法如何适合您的应用程序,然后简单地将调用集成到高度可伸缩的预构建 API 中。

机器学习即服务

在预建解决方案之后,将机器学习融入产品的下一个最自动化的方法是使用“机器学习即服务”提供商,或者更准确地说是“机器学习工程即服务”提供商。这类解决方案的目标是将机器学习算法从原型到可扩展解决方案的繁重工作最小化。

这些服务通常会提供一个渠道,帮助数据科学家将模型从 R&D 投入生产。例如,数据块提供了一个受管理的多流环境。这项服务允许数据科学家训练和验证模型,选择最佳表现者,然后自动部署到 Apache Spark 等处理解决方案或作为可扩展的 API,所有这一切都只需最少的软件工程。

这类解决方案的主要优势是机器学习工程任务的高度自动化,以及数据版本和模型验证等重要数据科学实践的简化实现。与使用预构建的解决方案相比,围绕数据格式和部署的设计选择仍然存在,但与其他解决方案相比,运行机器学习应用程序所需的代码和配置数量减少了。

主要的云提供商都有自己的 MLaaS 版本,但是在这个领域也有替代方案。除了 DataBricks 之外,其他付费提供商还有 H20DataRobot 。在考虑实现从研究到部署的流程之前,寻找一个在您的环境中运行良好的解决方案是值得的。

批次毫升

在一些组织中,数据科学、数据工程和机器学习工程之间的界限可能会模糊,因为同一团队服务于所有三种功能。数据工程团队擅长构建定期处理大量数据的系统。

存在成熟、灵活、通用的工具来实现可扩展的批处理。如果应用程序需要定期处理大量的示例,并且机器学习过程不需要事件或交互响应,那么这些工具可以将机器学习过程视为另一种类型的数据转换,并可扩展地生成结果。

对于编排机器学习工作流来说,批处理工具的一个例子是开源的 Apache Airflow。这个 python 框架将代码视为配置,允许开发人员在有向无环图(DAG)中将 Python 操作串在一起。图中的每个节点是一个不同的处理步骤,单个任务的执行通过一个排队系统被外包给自动缩放的处理工人(参见下面的排队处理)。以这种预定方式集成 ML 处理允许与额外的批处理资源集成,例如可能具有高旋转延迟的 Spark 集群。

批处理系统的一个主要组成部分是调度预定义工作流的定期执行的能力,通常具有可用于处理定期更新输入的常见用例的额外功能。然而,像 Airflow 这样的系统也提供事件驱动的功能,通过 REST API 触发工作流。

许多批处理框架存在于气流之外,AWS、GCP 和 Azure 也提供解决方案。作为 alẃays,值得寻找供应商管理的部署,以最大限度地减少运营开销。例如,谷歌通过云合成器提供气流。

无服务器 ML

考虑建立一个传统的基于云的 web 服务并扩展它的过程。您需要决定一种方法来管理大量的请求(就像下面的队列处理),编写 API 代码来为您的服务提供一个接口,并使用正确的代码和部署在其上的依赖项来管理计算实例。

无服务器范例已经出现,它通过允许“功能即服务”来简化所有这些决策换句话说,工程师和数据科学家只需要专注于具体运行处理模型训练或预测的编码函数所需的内容。这仅限于设计 API 接口、实现逻辑和打包依赖项。如果定义了这些基础,无服务器框架就可以提供一个 API 端点,并扩展资源来处理对该端点的请求。通过允许 ML 应用程序开发人员跳过机器学习功能的几个操作化步骤,部署可以更快地进行,并且可以更可靠地实现扩展,而不需要技能和时间来配置更多实践解决方案

也就是说,无服务器框架目前确实存在与机器学习应用特别相关的缺点。由于计算资源是在开发人员几乎无法控制的硬件上动态提供的,因此随着新资源的增加,在处理请求时可能会有滞后时间。此外,无服务器框架往往会限制可以与函数一起打包的依赖项的大小。由于机器学习模型通常依赖于包括数据和模型参数在内的众多依赖项,这可以有意义地减少数据科学家使用的技术数量。最后,无服务器框架可能不支持所有种类的硬件、编程语言或依赖性。所有这些都是多样化和快速发展的机器学习世界中的潜在障碍。

作为限制的具体例子, AWS Lambda 功能层目前被限制为 250MB。这意味着您的全部依赖项必须适合这么大的空间。例如,这就排除了使用最新版本的 Keras + Tensorflow 的可能性。这也意味着模型参数文件(很容易超过这个大小)将不得不在运行时从其他存储设备(比如 S3)中延迟加载。然而,Lambda 和其他无服务器框架允许使用容器化的应用程序,或者允许配额增加,从而放松了一些限制。

尽管有限制,许多机器学习任务在无服务器框架的范围内工作,所以这种缩放技术值得考虑。

排队处理

一种广泛使用的扩展方法是计算集群监听队列中的任务。在这个范例中,处理请求被放在队列中。工作进程轮询作业队列,并在其资源可用时处理它们。这允许一个定制任务处理器池来处理您的 ML 处理作业。

作者图片

正如您所猜测的,这种方法允许机器学习应用程序通过由一群工作人员执行的预测或训练来扩展计算。然而,尽管总吞吐量可能很高,但这种扩展方法有一些缺点。默认情况下,基于队列的系统是异步的。队列通常是一种单向通信机制。如果必须模拟同步行为,这需要使用回调之类的系统来实现。

设计基于队列的系统也不是“包含电池”的解决方案。有各种各样的任务队列实现,但是处理请求、维护队列、监听和处理工作线程请求的系统都必须进行设计和实现。需要考虑集群扩展策略和硬件要求。成功地做到这一切将需要经验丰富的具有系统配置知识的工程师的时间,而这种技能集与设计机器学习解决方案的科学过程相去甚远。此外,任何自我管理的扩展解决方案都不可避免地需要额外的维护,以保持其安全性并能够处理不断变化的工作负载。

值得考虑的是,基于队列的扩展解决方案的哪些组件是现成的,可以最大限度地缩短实施时间。存在几种任务队列解决方案。如果你喜欢 Python,那么芹菜是一个受欢迎的选择。还值得阅读一下您的计算提供商提供了哪些扩展和负载平衡解决方案。容器化非常适合在像 Google Kubernetes 引擎这样的服务上实现和扩展这些系统。

尽管有前期工作,但优势仍然是可以配置基于队列的系统来满足大多数处理需求。上面列出的许多方法最终都是对排队系统的抽象。需要一个 GPU worker 节点,在内存中存储数千兆字节的深度学习模型,并使用您最喜欢的语言的最新库?如果您有这方面的知识,您可以使用基于队列的集群来管理负载。

浏览器中的 ML

到目前为止,所有讨论的解决方案都集中在运行机器学习模型的后端方法上。在浏览器中,机器学习也是一种选择。谷歌大脑神经网络库 Tensorflow 现在有了一个 Javascript 版本。这意味着神经网络可以在用户的设备上进行训练和预测,熟悉前端技术的工程师可以参与构建系统。

这种方法的一个明显优势是后端计算资源不再是瓶颈。此外,推断可以在没有任何网络往返的情况下发生。然而,这意味着模型设计现在必须注意终端用户计算机上的计算资源。此外,虽然可以序列化存储的模型参数以便在用户的浏览器中使用,但这实际上将模型的大小限制在不会使用户的网络连接和硬件负担过重的范围内。

最后,据我所知,目前为止唯一的 Javascript 机器学习库是 Tensorflow.js。尽管神经网络很强大,但它们仍然可能不适合 ML 从业者能想到的每一项任务,这限制了应用。如果神经网络不是你所需要的,但 browserside ML 似乎仍然是一个很好的想法,有一些数学库可以简化开发,如 numericnumbers.js

如何选择

很明显,管理你的机器学习需求是有选择的。然而,没有一个单一的解决方案可以满足所有情况。我试图以或多或少增加的复杂性来呈现选择,从集成现有的扩展解决方案开始,一直到实现定制的队列基础扩展。这是我在选择如何将 ML 整合到产品后端时会考虑的层次。运行客户端模型也是一个有趣的新选择。

要在选项中进行选择,请考虑您的用例。你的应用需要用户与机器学习的交互吗?如果是这样,批处理机器学习可能不起作用,但扩展另一个选项以获得可接受的响应时间或在浏览器中使用机器学习可能是一个好的选择。

还要考虑你的时间线和团队。由外部提供商管理的解决方案越多,开始看到好处所需的工作和技能就越少,将它应用到您的应用程序中所需的专业知识也就越少。例如,大多数数据科学家和开发人员应该能够调用现有的 REST API 来运行分析。另一方面,建立基于队列的 ML 处理工作流需要架构、系统部署、软件开发技能以及数据科学!

机器学习:科学还是炼金术?

原文:https://towardsdatascience.com/machine-learning-science-or-alchemy-655bea25b227?source=collection_archive---------23-----------------------

经验领域的科学严谨性始于假设

图片来源:科学史研究所

人们越来越担心机器学习研究的科学严谨性。在 2017 年在 NIPS 大会上的一次演讲中,当时在谷歌人工智能的阿里·拉希米和本·雷希特认为,人工智能已经成为炼金术,指的是实践者使用的方法在实践中效果很好,但在理论层面上却很少被理解。同样,著名的 Keras 深度学习图书馆的作者 Francois Chollet 将今天的 ML 从业者比作“货物邪教”,在那里人们依靠“民间传说和魔咒”。

炼金术,货物崇拜,魔法咒语。这是一个值得注意的批评,因为这个领域发展如此迅速,在现实世界中的应用越来越广泛。正是这种广泛的使用让拉希米和雷希特担心:

“如果你正在建立照片共享服务,炼金术是好的。但是我们现在正在建立管理医疗保健和我们参与公民辩论的系统。我希望生活在一个系统建立在严谨、可靠、可验证的知识之上,而不是建立在炼金术之上的世界里。”

ML 是一个经验领域:我们根本没有一个理论来解释为什么某些方法有效而其他方法无效,甚至不清楚这样的理论是否会存在。但理论本身的缺失其实并不是主要问题。即使在一个实证研究领域,也可以通过科学严谨的方式取得进展。

我认为,科学和炼金术之间的关键区别始于从业者赋予科学假说的角色。

先假设

ML 从业者面临着巨大的复杂性,从数据集采样和清理到特征工程,再到模型选择和超参数调整。通常在测试集上,修补这些组件,看看什么效果最好,已经成为一种规范。

但是仅仅修补并不能成为一门科学。最根本的区别是科学假设的作用:科学家首先制定一个假设,然后设计一个实验来检验这个假设。这个假设要么被拒绝,要么被接受,不管怎样,我们都产生了新的知识。科学方法对实验结果是不可知的。

另一方面,修修补补不是由假设驱动的,更多的是由‘直觉’驱动的。如果目标仅仅是探索一种现象,这是可以的。但是当修补被伪装成科学,被倾听,也就是在结果已知后制定一个符合结果的假设时,事情就变得危险了。

听是误导,因为它不仅愚弄了研究者,也愚弄了整个社区。在最糟糕的情况下,研究人员可能会用一种算法的不同变体进行大量实验,选择实现预期结果的版本,这在实践中意味着它击败了最新的最先进的基准,并应用 HARKing 来证明这一选择。这也就是俗称的 SOTA 黑客

当然,运行的随机实验越多,就越有可能只是偶然地击败任何给定的基准:这也被称为看向别处效应。更糟糕的是,SOTA 黑客行为占用了本可用于实际创新的资源。脸书工程师 Mark Saroufim 在 《机器学习:大停滞》 中写道:

随着国家艺术(SOTA)的追逐,我们奖励和赞扬增量研究人员作为创新者,增加他们的预算,以便他们可以做更多的增量研究平行于尽可能多的员工或研究生向他们报告。

SOTA 黑客(来源:马克·萨鲁菲姆

在进行实验之前,制定一个科学假设是抵御哈金和 SOTA 黑客攻击的最佳保护机制。在他们的论文'HARK side of Deep Learning'中,数据科学家 Oguzhan Gencoglu 和他的同事甚至倡导一种“结果盲”的 ML 研究论文提交流程:让科学家提交他们的科学假设和实验设计。接受后,他们可以继续进行实验,条件是他们必须公布结果,不管结果是证实了还是排除了假设。这是一个激烈的、不切实际的、可能不切实际的解决方案,但它肯定会消除 SOTA 黑客攻击。

ML 能从物理学中学到什么

随着 ML 研究的发展,我相信它可以从借鉴物理学中获益。物理学的一个基本思想是考虑一个小的玩具问题,它更容易解决,并且可以在更大、更复杂的问题的背景下给出有价值的见解。

这并不是说这些物理学风格的实验没有被做,但它们是少数。在 NLP 的背景下,值得注意的例子是揭示著名的 BERT 语言模型对转喻多义词,或者简单地输入序列的顺序的敏感性的研究。例如,后一项研究发现,当在 GLUE benchmark 任务上训练时,BERT 对词序相对鲁棒,这表明大部分信号不是来自上下文,而是来自其他线索,如关键词。

除了玩具问题之外,另一个强大的实证方法是消融研究,这是一种故意一次忽略解决方案的一个组成部分,以区分关键部分和没有实际影响的“华而不实”的做法。在 NLP 的背景下,一个很好的例子是众所周知的 2017 年论文' 注意力是你所需要的全部 ',该论文表明,在存在注意力机制的情况下,语言模型中的递归变得多余。另一个很好的例子是 2017 年关于文本预处理在神经网络架构中的作用的论文''',该论文表明,除了小写,常见的文本预处理技术(文本清理、词干化、词条化)在下游 ML 模型性能方面没有提供可测量的改进。

从炼金术到科学

今天的许多 ML 实践感觉像炼金术,但是,正如在我简要提到的例子中,即使在没有理论的情况下,也可以进行某些实验来更深入地了解 ML 的内部工作,并将该领域置于更严格的科学基础上。特别是,以下是我对 ML 从业者的三点建议:

  • 在任何实验之前,明确你的假设。避免哈克和 SOTA 黑客的诱惑。
  • 要有创造性:想一些特殊的玩具问题,这些问题可以证实或者排除一个已经在社区内提出的假设(含蓄地或者明确地)。
  • 使用消融研究来识别关键部分,并消除您的 ML 解决方案中的“花里胡哨”。

最后,我的希望是,随着 ML 研究的发展,它将从目前关注的打破性能基准转向更基本的理解。科学毕竟是追求知识,而不是取胜。我同意(并结束)Rahimi 和 Recht 的观点,他们写道:

想想你在过去的一年里做了多少实验来破解一个体育数据集,或者看看一项技术是否会给你带来提升。现在想想你所做的实验,这些实验帮助你为你观察到的一个令人困惑的现象找到一个解释。我们做了很多前者。我们可以更多地使用后者。

用于实时预测的机器学习服务

原文:https://towardsdatascience.com/machine-learning-service-for-real-time-prediction-9f18d585a5e0?source=collection_archive---------6-----------------------

使用 FastAPI 为实时预测构建生产就绪的机器学习服务

Unsplash 上由 Aron 视觉拍摄的照片

目录:

  1. 简介
  2. 机器学习模型
  3. REST API
  4. 预测终点
  5. 本地开发与生产

1.介绍

在生产环境中使用机器学习(ML)模型有多种模式,如离线、实时和流式。在本文中,我们将详细了解如何使用 ML 模型进行在线预测。

你可以找到十几篇关于“如何为 ML 构建 REST API”的文章。问题是几乎所有的都把这个话题描述的很肤浅。在本文中,我们将仔细研究本地环境和生产环境之间的区别,如何在不重新部署的情况下更新模型,以及安全性问题。

对于实时预测,通常使用 REST API,这种服务根据需要进行预测,通常通过 HTTP 调用[ 1 ]进行。为了构建 REST 服务,我们将使用 FastAPI 框架。FastAPI 是一个现代的、高性能的、内置电池的 Python web 框架,非常适合构建 RESTful APIs。它可以处理同步和异步请求,并内置了对数据验证、JSON 序列化[ 2 ]的支持。

整个项目是有文档记录的,可以在 GitHub 上的DanilBaibak/real-time-ml-prediction资源库中找到。您可以随意使用它,并直接研究代码。

2.机器学习模型

在开始讨论 REST API 之前,我们需要一个 ML 模型。在本文中,我们将使用 sklearn 数据集[ 3 ]中的波士顿房价数据集。它包含 506 个实例和 13 个数字和分类特征。我们需要解决一个回归问题——根据房产预测房价。

ML 管道将是非常标准的:

我们将使用岭回归[ 4 ]作为我们的 ML 模型。重要注意事项—记住修复随机状态,以便能够重现您的结果。

现在,如果我们开始讨论一个真正的应用程序,我们仅仅训练模型并将其保存在文件夹中是不够的。我们还需要:

  1. 跟踪模型的版本。理想情况下,我们需要在数据库中有一个模型训练历史。
  2. 在每次训练之后保存模型元数据也是一个很好的实践。从长远来看,这些信息可以让您有机会看到模型生命周期中的一些关键点。我们已经在另一篇文章中讨论了监控模型元数据的想法。[ 5 ]

3.REST API

一旦你准备了一个 ML 模型,你就可以开始构建服务了。如前所述,我们将使用 FastAPI 框架构建一个 REST API。

3.1 项目结构

  • server.py 文件是 REST API 服务的入口点。
  • 我们将把 ML 工件保存在 ml_pipelines 文件夹中。
  • models 文件夹用于存储 Pydantic 模式。它定义了验证某些数据的属性和类型[ 6 ]。
  • 脚本 scripts/train.py 训练 ML 模型。

3.2 API 端点

通常,ML REST 服务有一个端点:“发布/预测”。它接收一个项目的特性列表,并返回一个预测。我们将进一步更详细地研究这个方法。

一个更有用的端点可以是:" GET /health "。这背后的想法来自微服务的最佳实践——快速返回服务的运行状态,并指示其连接到下游依赖项的能力[ 7 ]。作为运行状况检查输出的一部分,模型版本可能是有用的信息:

  • 检查 ML 管线的最新版本是否存在;
  • 如果您的团队中有 QA 工程师,他们可以通过模型版本的链接来报告问题;

4.预测终点

现在我们来看主要部分——预测终点。通用算法非常简单,您可以在许多文章中找到它:

  1. 接收请求;
  2. 加载模型;
  3. 做一个预测;
  4. 发送响应;

这种方法能否奏效取决于交通流量。让我们看看如何改进它。

4.1 模型缓存

REST 服务的一个重要需求是延迟。为每个请求加载模型非常耗时。我们可以引入一个本地缓存——这允许我们一次性加载模型。下一个请求将使用缓存的模型。这将加快响应时间。

4.2 加载模型的新版本

对于生产应用程序,我们需要在某个时候重新训练 ML 管道。理想情况下,它应该自动发生。您设置了一个 cron 作业来训练您的模型。然后 REST 服务一准备好就加载最新的 ML 管道。

我们已经准备了一个单独的表来存储 ML 管道版本和本地缓存——这应该足以实现模型最新版本的加载逻辑。我们需要通过以下方式更新预测端点:

一旦新的 ML 管道被训练、存储并且最新版本被保存在数据库中,API 将使用最新的模型。如果你有多个带有负载均衡器[ 8 ]的服务,这种方法也可以。

4.3 存储预测

就生产 ML 应用而言,仅仅做出预测是不够的。两个重要的问题仍然存在:

  1. 你将如何跟踪预测的质量?
  2. 你是如何组织未来模特训练的数据收集的?

要回答这两个问题,您需要开始存储预测。但是,如果我们只是添加逻辑来保存每个请求的预测,这将影响延迟。FastAPI 将帮助我们解决这个问题。FastAPI 最令人兴奋的特性之一是,它使用 Python async/await 关键字[ 9 ]支持开箱即用的异步代码。

我们需要将 async 关键字添加到将数据保存到 DB 和终结点函数的函数中。然后在将预测保存到 DB 时添加等待关键字。现在,我们可以在不影响延迟的情况下存储历史数据。

预测端点的最终版本如下所示:

5.地方发展与生产

为了将我们的服务部署到生产中,我们需要将代码归档。理论上,我们需要根据文档[ 10 ]在 Docker 中包装我们的应用程序,我们就完成了。但仍有几个要点需要注意。

5.1 地方发展

即使在部署之后,您仍然需要继续进行项目。大家还记得,我们使用数据库来存储 ML 管道的版本和预测。我们将使用 Docker Compose 来设置数据库并应用迁移。

对于本地开发,我们还将在调试模式下使用 FastAPI 每次更改代码时,服务器都将自动重新启动。为此,我们需要以稍微不同的方式启动应用程序。

请注意,我们使用单独的 Dockerfile。您还可以有一个单独的 requirements.txt 文件用于本地开发。这让您有一个动手的工作环境,而不是超负荷的生产码头工人形象。

5.2 API 文档

FastAPI 提供了一个现成的 API 文档引擎。如果您访问 http://localhost/docs ,您将看到自动交互 API 文档(由 swag UI 提供)【 11 。这对于本地或分段环境非常有用。但是,根据您的项目,您可能不希望在生产中有一个开放的文档终结点。很容易实现:

更改文档的默认 URL 也是一个好主意。

5.3 安全要求

我想再一次提醒大家,对于本地或分段环境有用的信息在生产中可能是危险的。如果我们回到运行状况检查端点,显示模型版本对于 bug 跟踪会非常有帮助,但对于生产而言是不可接受的。根据项目的不同,您可能更喜欢隐藏此信息。

摘要

  1. 延迟是 REST 服务的重要要求之一。缓存 ML 管道并尽可能使用异步代码。
  2. ML 管道版本的适当组织的存储是在不重新部署的情况下组织管道更新的关键。
  3. 将 ML 管道的版本显示为运行状况检查终结点的一部分对于开发期间的错误跟踪非常有用。
  4. 构建安全的应用程序!阻止访问敏感信息。
  5. 使用 docker-compose ,一个单独的Docker 文件甚至一个单独的 requirements.txt 文件允许动手进行本地开发,而不会使生产 Docker 映像过载。

您可以在资源库DanilBaibak/real-time-ml-prediction中找到完整的项目,以及如何设置和使用它的说明。

参考资料:

  1. 表象状态转移
  2. FastAPI
  3. 波士顿房价数据集
  4. sklearn.linear_model。山脊
  5. 在生产中使用 Apache Airflow 进行机器学习
  6. 肥胖模型
  7. 为微服务实现健康检查 API
  8. 负载均衡
  9. 并发和异步/等待
  10. 使用 Docker 部署 FastAPI】
  11. FastAPI 交互 API 文档

机器学习——简化定义

原文:https://towardsdatascience.com/machine-learning-simplified-definition-4bdaa21a2b42?source=collection_archive---------28-----------------------

机器学习不仅仅是美化了的统计学

作者图片

人们担心计算机会变得太聪明并接管世界,但真正的问题是它们太笨了,它们已经接管了世界。佩德罗·多明戈斯

感觉就像谷歌或脸书每周发布一项新的人工智能技术,以加快或改善用户体验。在本文中,我们将介绍什么是机器学习,以及机器学习的类型。

什么是机器学习

机器学习(ML)是一种数据分析方法,允许系统在没有显式编程的情况下进行学习。或者用 Tom Mitchell 的话来说,“一个计算机程序被认为在某类任务 T 和性能测量 P 方面从经验 E 中学习,如果它在 T 中的任务的性能,如 P 所测量的,随着经验 E 而提高”

机器学习基于这样一种想法,即分析系统可以学习使用统计学、线性代数和数值优化来识别模式并在最少人工参与的情况下做出决策。

我喜欢将机器学习视为一种编写程序的方式,其业务逻辑是从输入数据中生成的。我们向算法提供数据,程序执行的结果将成为处理新数据的逻辑。这是一种新的编写软件的方式,与传统的开发过程有所不同。

直觉理解

为了更好地说明这一点,让我们转到更熟悉的准备晚餐的动作。让我们想象一下,我们想做一个意大利香肠比萨饼。披萨……终极的开放式三明治。

我们有配料和食谱——这些将是我们的投入。我们按照食谱,按照正确的步骤,我们最终得到了一个即食比萨饼。这是传统的编程。为了得到正确的结果,我们需要配方。我们可以自己写,也可以让妈妈给我们写。

作者图片

有了机器学习,就有点不同了——我们不知道食谱,我们不想写或者不知道,但我们仍然想要披萨。我们有一堆配料和一些比萨饼的概念。当然,在我们的例子中,这是棒约翰的广告——以奶酪和意大利香肠为主题的史诗般的硬皮披萨。Yammy。我们不知道如何制作,但我们可以邀请我们的朋友过来,从他们的反馈中看到我们制作的披萨接近我们想要的那种披萨,甚至可能是美味的披萨!

一些愤怒的评论之后,我们意识到上面的面团不是真正的披萨。当我们在几个月甚至几年的时间里继续分析比萨饼的“标准”以确定哪些因素影响了最终产品的外观、味道和质量时。在某种程度上,我们最终理解了我们的朋友所说的真正的意大利香肠比萨饼。我们把步骤顺序写在食谱上。我们的算法准备好了!

这不完全是虚构的故事

输入数据

强调 ML 的数据驱动本质是很重要的。这看起来微不足道,但令人惊讶的是 ML 工程师经常忘记这一点。他们专注于构建一个更好的模型,而不是改进模型所基于的数据。这使得收集代表性数据的任务对于机器学习的成功至关重要。

我们应该根据正确表示模型在真实世界中工作的条件的数据来训练我们的模型。如果我们想识别垃圾邮件,我们需要垃圾邮件的例子。如果我们想预测股票价格,我们需要价格的历史。如果我们想知道用户的兴趣,我们需要用户的点击历史。数据以任何可能的方式收集。有些人手动操作,耗时更长,通常产生的数据更少,但错误也更少。人们确实在寻找好的数据集。大公司有时会披露他们的算法,但很少披露数据。

推荐书籍

感谢您的阅读!

有什么问题吗?请在下面留下您的评论,开始精彩的讨论!

查看我的博客或者来打个招呼👋在 Twitter 或订阅我的电报频道。规划好自己!

机器学习对板球运动员进行聚类

原文:https://towardsdatascience.com/machine-learning-to-cluster-cricket-players-1d53beeb69b4?source=collection_archive---------17-----------------------

k-means 聚类、层次聚类和 DBSCAN 聚类的应用

板球和数据科学这两者都一直令我着迷。当我偶然发现 IPL(印度超级联赛)数据时,我很好奇要对这些数据进行某种数学分析,从中得出一些有趣的东西。这些数据包含了 IPL 中每个投球的细节。有趣的是,首先将这些数据转换成球员级别的数据,然后尝试识别数据中的模式,将具有相似表现的球员分组在一起。这完全符合聚类问题。

聚类是一种“无监督的机器学习”,没有定义的标签,模型可以基于该标签进行训练。相反,它在数据中寻找模式,并根据模式对数据进行逻辑分组。组合在一起的最后一组数据称为聚类,它包含一组同质点。

在本文中,我们将应用一些流行的聚类算法,如 k-means 聚类、层次聚类和密度聚类(DBSCAN ),对在印度超级联赛(IPL)中表现相似的板球运动员进行分组。

我们将根据 2008 年至 2020 年的表现,提取 IPL 球员的内在素质。为了确保样本具有可比性,我们设定了一个最低标准,即每个玩家必须至少打了 10 局才有资格进行分析。

创建玩家集群—示例(图片由作者提供)

数据集和源代码

该数据集包含从 2008 年 IPL 第一版到 2020 年第 13 个赛季的所有比赛的详细信息和每场比赛的详细信息。

请参考页面底部的数据集和源代码的链接。

聚类玩家-属性

以下是分析中考虑的球员的一些关键属性

  • 击球统计像得分、击球、局数、4 分、6 分、击球率
  • 保龄球统计数据像三柱门被占,得分,失分,保龄球经济
  • 一般统计数据如比赛次数、接球次数、最佳球员人数

聚集玩家——方法

概括地说,该分析包括以下 3 个步骤:

步骤 1: 将逐球原始数据转换为玩家级别的统计数据

步骤 2: 将不同的聚类技术应用于该玩家数据

第 3 步:使用 ipywidgets 构建一个简单的 UI,使用超参数

基于击球、保龄球的玩家聚类&综合统计(图片由作者提供)

注意:完整的源代码可以在上一节提到的 GitHub repo 中找到。这里只添加了部分代码流片段以供参考。

偷窥期待什么

带着一点乐趣学习集群——游戏开始!!

玩家聚类——玩数据

在这篇文章的结尾,你将能够应用不同的聚类算法来回答下面的一些问题

识别 IPL 中表现像 Virat Kohli 的球员?

找到类似 Ravindra Jadeja 的全才。

IPL 里谁能打得像 Jasprit Bumrah?

有多少玩家和萨钦·坦杜尔卡尔一样掉进了同一个桶里?

步骤 1:从原始数据中创建玩家统计数据

窥探原始数据

这里是原始数据的快速浏览——比赛数据和逐球数据

偷窥比赛数据(图片由作者提供)

逐球窥探数据(图片由作者提供)

创建击球统计

每位选手的击球统计

创建保龄球统计

每位玩家的保龄球统计

合并数据

过滤玩家

让我们检查一下每个运动员参加的比赛的分布情况

比赛分布—过滤前(图片由作者提供)

正如这里看到的,几乎 50%的球员打了不到 10 场比赛。

在这个分析中,我们将只考虑至少打了 10 场比赛的玩家,这样最终创建的玩家集群才有意义。

比赛分布——过滤后(图片由作者提供)

经过筛选,总共有 336 名球员将被考虑作进一步分析。

缩放数据

在运行聚类分析算法之前对数据进行缩放是一种很好的做法,这样可以防止具有较大缩放比例的变量控制聚类的定义方式。

在此分析中,我们应用了标准定标器,以确保变量以平均值 0 为中心,标准差为 1。

步骤 2:将聚类算法应用于玩家数据

我们将探索以下三种流行的聚类技术:

  1. k 均值聚类
  2. 分层聚类
  3. DBSCAN 聚类

k 均值聚类

在 k-均值聚类中,数据集中所需的聚类数(k)应该指定为算法的输入。下面是 k-means 聚类算法的内部工作原理。

K-Means 聚类算法

先决条件:决定要创建的集群数量(k)

第一步:随机挑选 k 个点作为聚类中心

步骤 2: 对于每个数据点,计算到每个聚类中心的欧几里德距离

步骤 3: 将数据点分配给具有最小欧几里德距离的聚类。

步骤 4: 根据步骤 3 中分配的数据点重新计算聚类质心

步骤-5: 重复步骤 2 至 4,直到质心不再更新或达到最大迭代次数

K-均值聚类中的代价函数

我们在 k-means 聚类算法中试图最小化的成本函数是数据点和聚类质心之间的平方距离之和。这可以表示如下:

成本函数—K-均值聚类

通过最小化成本函数,K-Means 算法旨在最大化聚类的紧密度/接近度,使得在给定特定特征向量的情况下,聚类内的数据点彼此相似。

寻找最佳的聚类数

有许多方法可以找到 k 的最佳值。在本文中,我们将通过两种这样的方法,即肘方法和剪影方法。

肘法

  • elbow 方法对 k 值范围运行 k 均值聚类算法。
  • 对于 k 的每个值,它计算一个分数。
  • 默认情况下,它会计算失真分数,即每个数据点到其指定中心的平方距离之和。
  • 绘制 k 值与该分数的关系图会得到一个肘形图,因此得名。
  • 失真下降最多的点是肘点,这给出了 k 的最佳值。

绘制肘形曲线 Python 代码

肘子情节 —作者图片

正如这里看到的,一个好的 k 值看起来大约是 5 或 6。

在肘图不能给出最佳聚类数的决定性结果的情况下,可以应用剪影方法。

剪影法

按照 wiki的说法,剪影值是一个对象与其自己的聚类(内聚)相比与其他聚类(分离)有多相似的度量。

剪影评分

其中,
' b' 是到不属于
的最近聚类中的点的平均距离。 'a' 是到其自己的聚类中所有点的平均聚类内距离

剪影的分数范围在-1 到 1 之间。分数越接近 1 表示该点与聚类中的其他点非常相似。接近-1 的值表示该点与聚类中的其他点不太相似。

对每个数据点都这样做,取平均值来确定 k 值的轮廓得分。轮廓得分的最大值将给出 k 的最佳值。

用 Python 计算剪影分数

不同 k 值的轮廓得分

因此,k 的最佳值应该根据业务需求和统计分析的结果来决定。

Python 中的 K-Means 聚类

既然我们已经了解了 k-means 聚类算法的工作原理,并且知道如何选择聚类数,那么让我们用 Python 来实现它。

群集的大小和分组将根据所需群集的数量而变化。下面显示了 4 个集群和 7 个集群的分布。

K-均值聚类,k=4

K = 7 的 K-均值聚类

笔记本的末尾有一个“操场”。使用小部件来试验不同的 k & max_iter 值。

分层聚类

分层聚类是用于识别数据集中的组的另一种聚类技术。它创建了数据点的基于树的表示,称为树状图。

分层聚类算法

基于方法,层次聚类可以分为两种类型,凝聚型和分裂型。

先决条件:决定相异度——通常是欧几里德距离

1.凝聚层次聚类

  • 这采用了自底向上的方法来形成集群。
  • 首先将每个数据点视为一个集群
  • 融合/合并具有最低相异度测量的点以创建新的更大的聚类
  • 反复重复上述步骤,直到形成单个大簇

2.分裂层次聚类

  • 这种方法使用自顶向下的方法来形成集群
  • 首先考虑所有点都在一个聚类中
  • 在迭代的每一步,最不均匀的集群被分成两部分。分割基于最远距离或最小相似度。
  • 迭代重复上述分割,直到所有数据点形成单独的聚类

测量相异度——链接法

有许多方法可以用来确定两个聚类之间的距离。连锁的选择对聚类的大小和树状图的形状有影响。

下面列出了 Scipy 包提供的链接方法:

  • 单一连锁:最小的相异度分数作为连锁标准
  • 完全连锁:以最大相异分数作为连锁标准
  • 平均连锁度:平均相异度分数作为连锁度标准
  • 质心连锁:被视为连锁标准的聚类的质心之间的不相似性
  • 中位数链接:使用中位数计算聚类之间的相异度得分
  • 加权联动:对精简距离矩阵进行加权/WPGMA 联动
  • 沃德联动:使用沃德方差最小化算法。这里,具有最小聚类间距离的聚类被合并。

Python 中的层次聚类

Scipy 包提供了非常易于使用的接口来创建树状图和执行聚类。下面的示例代码将通过应用完整的链接来创建一个树状图。该方法可以被改变为应用于聚类算法的任何上述链接类型。

树形图样本图像(50 名玩家) —作者提供的图像

从树状图中可以估计出聚类的数目。这被提供作为创建聚类的输入。

形成的集群的样本输出摘要 —图片由作者提供

尽管层次聚类的优点是不需要从已知数量的聚类开始,但它会计算每个点与其他点之间的距离,因此计算量会很大。因此,基于可用的资源和手头的问题,必须选择是否可以应用分层聚类。

DBSCAN 聚类

DBSCAN(基于密度的含噪声应用程序空间聚类)是另一种流行的聚类技术,它将数据集划分为高密度区域。

DBSCAN 参数

DBSCAN 有两个主要参数

  1. 最小样本:形成密集区域或聚类的最小点数
  2. ε:定义搜索附近邻居的半径

DBSCAN 聚类算法

先决条件:定义ε的值和最小点数

步骤 1 : 拾取数据集中的任意点

步骤 2 :检查半径ε内该数据点周围的数据点数。如果数据点的数量至少是定义的最小样本大小,那么所有这些数据点被认为是在同一个聚类内。

步骤 3 :对所有数据点重复进行邻域计算

DBSCAN 点

DBSCAN 聚类完成后有三种类型的点。

  1. 核心点:周围采样点数最少的数据点
  2. 边界点:周围没有最小数量的采样点,但在半径ε内有一个核心点的数据点
  3. 噪声点:既不是核心点也不是边界点的点。被视为数据中的异常值。

Python 中的 DBSCAN 聚类

Scipy 包提供了包 DBSCAN 来执行这种基于密度的聚类。ε(EPS)和聚类中最小点数(min_samples)的值被用作函数中的参数。

DBSCAN 聚类总结 (eps = 0.9,min_samples=5) —图片作者

聚类值-1 表示噪声点。在这个数据集中,对于 eps 和 min_samples 的给定值,有 129 个噪声点。其余的数据点被分成 4 组,如上面的分布所示。

数据集和源代码

原始数据已从这里下载: IPL 原始数据 https://www.kaggle.com/patrickb1912/ipl-complete-dataset-20082020 这包含了从 2008 年到 2020 年所有 IPL 比赛的逐球和比赛级别细节。

Git 路径:https://github.com/Lakshmi-1212/IPL_PlayerClusters

摆弄配置

既然我们已经介绍了在数据上运行所有三种聚类算法的基础知识,我们就可以开始处理数据了,看看参与者是如何根据输入配置归入不同的聚类的。

这里我们已经使用 ipywidgets 在 Jupyter 笔记本上构建了 UI。它易于使用,适合构建简单的 ui。

克隆 GitHub repo,亲自体验一下吧!!

使用集群配置

结论

可以看到,我们可以试验不同的聚类技术,使用超参数来获得最佳模型。这里的目标仅限于理解不同类型的聚类,并将它们应用于 cricket 数据以获得一些有用的信息。

一旦玩家被聚类,该数据可以进一步用于不同的目的。示例:教练可以使用它来为每个集群制定具体的策略,或者组建一个全面的团队。他们甚至可以在拍卖过程中使用这些信息来检查新玩家可能适合哪个集群。这样的例子不胜枚举:-)

实验&边学边乐!!

机器学习用例:对佩戴口罩的方式进行分类

原文:https://towardsdatascience.com/machine-learning-use-case-classifying-ways-to-wear-a-face-mask-f90af8562530?source=collection_archive---------25-----------------------

新冠肺炎期间,街上的人们戴着口罩——图片来源。

无论您是在医疗行业、工业环境中佩戴面罩或呼吸器,还是作为公众中的一员,面罩的使用和正确放置对于最大程度的保护至关重要。

现在,随着新冠肺炎的传播,许多地方(如机场、工作场所等。)要求戴上面罩,并将其正确放置在鼻子和嘴上。为了帮助检测和执行这些要求,我们开始在 PerceptiLabs 中建立一个图像识别模型,该模型可以对人们佩戴面具的不同方式进行分类。然后,像这样的模型可以用于检查站、入口和其他位置,以帮助工作人员或当局识别不遵守其组织的口罩佩戴规则的个人。

数据集

为了训练我们的模型,我们获取了佩戴口罩或呼吸器的方式数据库(WWMR-DB) ,其中包含了佩戴口罩的人的图像,如图 1 所示。

图 1:来自数据集的图像示例—图像 来源

数据集包括。jpg 图片分为八类,描绘了最常见的佩戴口罩或呼吸器的方式。

根据戴面具的人,原始数据集被分成一系列子目录。为了使事情变得更顺利并与 PerceptiLabs 兼容,我们通过创建对应于八个分类的八个子目录来简化这一点,然后将适当的图像移动到相应的子目录中。然后,使用 PerceptiLabs 的数据向导中的调整大小功能,将每个图像调整为 224x224 像素。

为了将分类映射到图像,我们创建了一个. csv 文件( mask_log.csv ),该文件将每个图像文件与一个数字标签相关联,以便使用 PerceptiLabs 的数据向导加载数据:

0:下巴上方的遮罩

1:正确佩戴面罩

2:面具挂在佩戴者的耳朵上

3:没有戴口罩

4:额头上的面具

5:鼻尖上的面具

6:下巴下的面膜

7:鼻下面具

下面是一个部分的例子。csv 文件看起来:

的例子。csv 文件,用于将数据加载到将图像文件映射到其关联标签的 PerceptiLabs 中。

车型总结

我们的模型仅由三个组件组成:

组件 1: InceptionV3 ,include_top=no

成分 2:密集,激活= ReLU ,神经元=128

组件 3:密集,激活= Softmax ,神经元=8

注意,尽管 InceptionV3 要求图像为 229x229 像素,但是将 include_top 设置为 no,允许使用其他尺寸的图像(例如,224x224 像素)。

图 2:感知实验室中模型的拓扑结构-图像 来源

训练和结果

我们用 32 个批量 20 个历元训练模型,使用 ADAM 优化器,学习率 0.001,交叉熵损失函数。图 3 显示了训练期间 PerceptiLabs 的统计视图。

图 3: PerceptiLabs 在训练时的统计视图—图片 来源

在大约 34 分 28 秒的训练时间内,我们能够实现 99.4%的训练准确率和 77.1%的验证准确率。较低的验证精度反映了在面部检测相关数据上训练模型的难度

在下面来自 PerceptiLabs 的屏幕截图(图 4)中,您可以看到在前六个左右的时期中,训练验证准确性如何上升,之后它保持相当稳定。在最初的几个时期,训练大部分是上升的,并且在稳定下来之前波动,直到第 14 个时期左右:

图 4:精度图。

图 5 中的截屏显示了前 14 个时期在训练和验证过程中的相应损失:

图 5:损失图。

这里我们可以看到,在稳定之前的第一个时期,训练损失显著下降,而验证损失开始较低,并始终保持相对稳定。

垂直应用

像这样的模型可以用于安全或健康和安全目的,以确保工人或游客有一个面具,并在进入前正确佩戴。例如,该模型可用于分析通过现场安全摄像头获取的照片或视频帧。该模型本身也可用作转移学习的基础,以创建用于检测其他类型健康或安全设备的存在和正确使用的附加模型。

总结

此使用案例是如何使用图像识别来帮助确保健康和安全的示例。如果你想建立一个类似这样的深度学习模型,运行 PerceptiLabs 并获取我们的。来自 GitHub 的 csv 文件。

机器学习 vs 深度学习

原文:https://towardsdatascience.com/machine-learning-vs-deep-learning-6b206bb5504?source=collection_archive---------14-----------------------

意见

他们的算法和职称之间的差异

朱莉安娜·阿莫里姆在 Unsplash 上拍摄的照片。

目录

  1. 介绍
  2. 机器学习
  3. 深度学习
  4. 摘要
  5. 参考

介绍

有几篇文章比较了数据科学和深度学习,但对于机器学习和深度学习之间的区别,以及机器学习的研究和与机器学习相关的专业职称之间的区别,仍然有些困惑。有区别吗?各是什么意思?在本文中,我们将概述不同之处,以及每个领域的职位名称示例。如果你想了解机器学习和深度学习的含义以及它们在工作场所的不同之处,请继续阅读下面的内容。

机器学习

克里斯托弗·高尔Unsplash【2】上拍摄。

就数据科学而言,ML 或机器学习是使用过去的数据来预测目标的算法的自动化。同样重要的是要注意,有不同的职业与机器学习相关联。例如,您可以期待以下 ML 职业头衔:

  • 机器学习工程师
  • MLOps 工程师
  • ML 平台工程师
  • ML 科学家

机器学习的标题vs 机器学习的字段往往不一样。例如,机器学习工程师可能只实施机器学习算法,而不必了解太多关于这些算法如何工作以创建预测的信息,并且该角色通常在操作意义上被提及,而机器学习领域是总结算法本身。数据科学家实际上是一个更关注算法本身的人。最后,当申请机器学习领域的职位时,除了对特定公司、部门和角色本身进行澄清的好处之外,查看职位描述也是至关重要的,因为你所期望的可能不是真的。

有无数的机器学习算法,下面是一些最受欢迎的算法:

  • k 均值
  • 主成分分析
  • 线性支持向量机
  • 朴素贝叶斯
  • 决策图表
  • 逻辑回归
  • 随机森林
  • XGBoost
  • CatBoost

这些算法通常被称为机器学习算法,将用于针对您的数据和要素的整体数据科学模型中。

深度学习

照片由法库里安设计Unsplash【3】上拍摄。

深度学习是机器学习的一个方面。它还包括对算法的研究,包括被称为人工神经网络的层次。对于职称,这里有一些你可以在深度学习中期待的:

  • 深度学习工程师
  • 机器学习工程师
  • 人工智能工程师
  • 计算机视觉工程师
  • 人工智能科学家

你会注意到,在深度学习工作部分,我也保留了相同的头衔机器学习工程师。这是因为,正如我们上面所说,深度学习是机器学习,所以对于角色来说,我们可以期待一些机器学习工程师既关注一般的机器学习算法,也关注特定的深度学习算法。

有几种深度学习算法,下面是一些最受欢迎的算法:

  • 卷积神经网络( CNN )
  • 递归神经网络( RNN )
  • 长短期记忆网络( LSTM

如你所见,所有这些例子都包括神经网络这个术语。当然,也有更多深度学习专用的算法。

摘要

我想让这篇文章简洁明了,因为这些字段和职位可能会很混乱。但最终,当你申请一个职位时,你会希望真正地看一下职位描述,并和公司的招聘经理谈谈。

没有什么理由可以解释为什么工作描述可以是多种角色的混合。招聘人员可能已经用他们各自的技能和预期用例制作了工作描述,所以它可能与标题不完全匹配。另一个原因是,招聘经理实际上可能只是想要知道一般机器学习算法并在深度学习方面有一些实践的人。

我们可能会看到更多机器学习或数据科学角色超过深度学习的原因是,假设你只会使用特定的深度学习算法集可能会非常有限。作为一名数据科学家,你会知道你将从一个问题开始,从那里,你可以尝试使用大量的数据分析 Python 代码、数据科学技术、机器学习算法和深度学习特定算法。但是,在深入研究数据、障碍和需求之前,您不会知道这一点。标题只适用于深度学习的一个原因是,在公司工作的人知道,为了有一个成功的项目或产品,你需要专注于这些算法。

总结一下,下面是这篇文章的一些要点:

  • 机器学习包含使用数据预测目标的算法
  • 机器学习的研究通常不同于机器学习工作:分别是算法的研究和这些算法的实现(例如:部署)
  • 数据科学家通常使用机器学习算法,包括根据用例选择/测试使用哪种算法等任务
  • 深度学习是机器学习
  • 深度学习是人工神经网络特有的
  • 用一句话来比较所有这些术语的例子: Sarah 为她的数据科学模型利用了深度学习-机器学习算法

我希望你觉得我的文章既有趣又有用。如果你同意或不同意我对这两个流行术语的解释,请在下面随意评论。为什么或为什么不?这些当然可以进一步澄清,但我希望我能够阐明一些主要的差异,以及在解释这些差异时的常见错误,尤其是在提到职称时。感谢您的阅读!

请随时查看我的个人资料、 马特 Przybyla 等文章,也可以在 LinkedIn 上联系我。

参考

[1]2018 年朱莉安娜·阿莫里姆Unsplash 拍摄的照片

[2]Christopher Gower Unsplash 上拍摄的照片,(2017)

[3]照片由法库里安设计Unsplash(2021)上拍摄

使用 Docker 和 Kubernetes 的机器学习:批量推理

原文:https://towardsdatascience.com/machine-learning-with-docker-and-kubernetes-batch-inference-4a25328f23c7?source=collection_archive---------17-----------------------

Kubernetes、Docker、Python 和 Scikit——学习机器和深度学习:如何扩展数据科学家的工作

Annamária Borsos 摄影

在这一章中,我们将从我们在前一章中开发和安装的 Kubernetes 集群中的训练模型中实现一个批量推理:https://xaviervasques . medium . com/machine-learning-with-docker-and-Kubernetes-training-models-CBE 33 a 08 c 999

你可以在 GitHub 上找到本章用到的所有文件。

为了开始,我们需要对之前的文档进行如下修改:

与之前的 Dockerfile 相比,我们只是增加了 inference.py :

inference.py 中,我们开始导入必要的库,读取 Docker 映像中设置的环境变量,并读取存储在 GitHub 上的新数据(test.csv ),以便为我们的序列化模型提供预测并提供准确度分数。这里,我们将使用 SSH 从远程服务器(192.168.1.11)下载存储在指定目录(/home/xavi/output)中的先前训练的模型(线性判别分析和一个多层感知器神经网络)。

现在,我们可以进入下一步,构建 docker 映像,运行它以在本地测试我们的应用程序,在 Docker Hub 注册表上用映像存储库的名称标记它,并将其推送到注册表,准备在我们的 Kubernetes 集群中使用该映像:

docker build -t kubernetes-inference -f Dockerfile .

为了测试我们的代码是否正常,我们将在本地运行我们的容器来测试图像:

docker run kubernetes-inference python3 train.py rm ./id_rsa

如果一切正常,我们可以使用 CLI 将新映像推送到存储库:

docker logindocker tag kubernetes-inference:latest xaviervasques/kubernetes-inference:latestdocker push xaviervasques/kubernetes-inference:latest

为 Kubernetes 创建配置文件

一旦图像成功上传到注册表,我们就转到我们的项目目录(连接到 kubmaster)并创建一个配置文件 inference.yaml ,它执行我们的 python 代码:

等效的 docker 命令应该是:

docker run kubernetes-inference python3 inference.py rm ./id_rsa

我们终于准备好让我们的应用程序在 Kubernetes 上运行了。启动以下命令:

kubectl create -f inference.yaml

通过运行以下命令检查作业对象:

kubectl get jobskubectl get pods — selector=job-name=inference-job

我们可以查看流程的日志(我们代码的输出):

kubectl logs inference-job-stskf

后续步骤

Kubernetes 是一个有效部署模型的优秀框架。我们可以使用 Kubernetes 将我们的每个模型部署为独立的轻量级微服务。这些微服务可以用于其他应用。我们还可以与 Kubernetes 合作,安排我们的训练和推理过程定期运行。现在,下一步将是使用 REST APIs 部署在线推理。您可以在这里找到使用 REST APIs 的在线推理的部署示例:

https://xaviervasques.medium.com/machine-learning-prediction-in-real-time-using-docker-python-rest-apis-with-flask-and-kubernetes-fae08cd42e67

来源

https://developer . IBM . com/technologies/containers/tutorials/scalable-python-app-with-kubernetes/

https://mlinproduction.com/k8s-jobs/

Docker 和 Kubernetes 的机器学习:从头开始安装集群

原文:https://towardsdatascience.com/machine-learning-with-docker-and-kubernetes-install-a-cluster-from-scratch-9dc73bfdc55a?source=collection_archive---------19-----------------------

Kubernetes,Docker,Python 和 sci kit-机器和深度学习的学习:如何扩大数据科学家的努力

Annamária Borsos 摄影

如果我们想要扩展我们的机器和深度学习工作,开源容器编排平台 Kubernetes 无疑是最重要的工具之一。为了理解 Kubernetes 对数据科学家的效用,我们可以考虑一下我们开发和容器化的所有应用程序。我们将如何协调和安排所有这些集装箱?我们如何在不中断服务的情况下升级我们的机器学习模型?我们如何扩展模型并通过互联网提供给用户?如果我们的模型被更多我们认为的人使用会发生什么?如果我们之前没有考虑架构,我们将需要增加计算资源,当然还需要手动创建新实例并重新部署应用程序。Kubernetes 调度、自动化和管理基于容器的架构的任务。Kubernetes 部署容器、更新它们、提供服务发现、监控、存储供应、负载平衡等等。如果我们谷歌“Kubernetes”,经常会看到对比 Docker 和 Kubernetes 的文章。这就像比较苹果和苹果派。首先要说的是,Kubernetes 是设计在集群上运行的,而 Docker 是在单个节点上运行的。Kubernetes 和 Docker 在创建、部署和扩展容器化应用程序方面是互补的。还有 Kubernetes 和 Docker Swarm 之间的比较,Docker Swarm 是一个用于集群和调度 Docker 容器的工具。Kubernetes 有几个选项可以提供真正重要的优势,例如高可用性策略、自动扩展功能、管理运行在公共、混合、多云或内部环境上的复杂和数十万个容器的可能性。

你可以在 GitHub 上找到本章用到的所有文件

库伯内特词汇

在 Kubernetes,我们需要了解不同的概念。我们有 Kubernetes 主节点,它是在我们的集群的一个节点上运行的一组三个进程,我们称之为主节点: kube-apiserverkube-controller-managerkube-scheduler 。我们集群中的每个节点(不包括主节点)运行两个进程: kubelet ,它与 Kubernetes 主节点通信,以及 kube-proxy ,它是一个网络代理,反映了每个节点上的 Kubernetes 网络服务。API 服务器用于组件之间的通信,控制器管理器根据期望的状态检查状态,调度器决定应该在哪些 pod 上运行。 kubelet 是在每个节点上运行的主要“节点代理”。 kube-proxy 是运行在每个节点上的 Kubernetes 网络代理。

在 Kubernetes 中,我们有控制平面(主节点),它是协调器,节点是机器(物理服务器、虚拟机等)。)来运行您的容器化应用程序。这些节点由主节点控制。然后,我们有 Pod ,它是 Kubernetes 的基本构建模块。Pods 是我们可以在 Kubernetes 中创建和管理的最小可部署计算单元。它由一个或多个容器组成。例如,我们可以考虑创建一个 Pod 来训练我们的机器学习模型(代码在单个容器中)。我们还必须处理创造一个或多个豆荚的工作。作业将确保 pod 的执行是成功的。我们可以创建一个作业来训练我们的模型,执行批量推理,或者将训练元数据等信息存储到外部存储或预测中。Kubernetes 可以通过简化向他人展示模型的过程,真正帮助我们将机器和深度学习模型投入生产。我们将看到,我们需要遵循几个步骤,例如创建一个部署,指定要运行哪个容器以及我们要创建多少个副本,使用一个服务来公开部署,该服务允许我们定义将 pod 相互公开以及向互联网公开的规则。Kubernetes 的一个非常重要的特性是负载平衡,以处理副本之间的流量平衡工作,并自动调整资源以满足不断增长的需求。

典型的 Kubernetes 建筑

Kubernetes 快速安装

我们可以使用不同的方法来安装 Kubernetes。所有这些在 Kubernetes 网站上都有很好的解释:

我们可以在终端上输入:

brew install kubectl

或者,我们可以键入:

Ubuntu / Debian

sudo apt-get update && sudo apt-get install -y apt-transport-httpscurl -s [https://packages.cloud.google.com/apt/doc/apt-key.gpg](https://packages.cloud.google.com/apt/doc/apt-key.gpg) | sudo apt-key add -echo “deb [https://apt.kubernetes.io/](https://apt.kubernetes.io/) kubernetes-xenial main” | sudo tee -a /etc/apt/sources.list.d/kubernetes.listsudo apt-get updatesudo apt-get install -y kubectl

红帽/ CentOS

cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-\$basearch
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
exclude=kubelet kubeadm kubectl
EOF

*# Mettre SELinux en mode permissif (le désactiver efficacement)*
sudo setenforce 0
sudo sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config

sudo yum install -y kubelet kubeadm kubectl --disableexcludes=kubernetes

sudo systemctl enable --now kubelet

使用以下命令检查安装:

kubectl version --client

安装所有的 Kubernetes 二进制文件(kubeadm,kubelet,kubectl):

sudo apt-get install -y kubelet kubeadm kubernetes-cnisystemctl enable kubelet

安装 Kubernetes 集群

为了熟悉 Kubernetes,我们将使用一个工具来构建和管理虚拟机。流浪者通过使用名为流浪者文件的配置文件在单个工作流中创建和配置轻量级环境。让我们安装流浪者。

Ubuntu / Debian

curl -fsSL [https://apt.releases.hashicorp.com/gpg](https://apt.releases.hashicorp.com/gpg) | sudo apt-key add -sudo apt-add-repository “deb [arch=amd64] [https://apt.releases.hashicorp.com](https://apt.releases.hashicorp.com) $(lsb_release -cs) main”sudo apt-get update && sudo apt-get install vagrant

红帽/ CentOS

sudo yum install -y yum-utilssudo yum-config-manager --add-repo [https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo](https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo)sudo yum -y install vagrant

如果我们想把它安装在其他平台上,请不要犹豫检查:https://www.vagrantup.com/downloads

vagger 依赖于与供应商(如 VirtualBox、VMware 或 Hyper-V)的交互,为 vagger 提供运行开发环境的资源。需要安装其中的一个。

我们可以安装 virtualbox :

sudo apt updatesudo apt install virtualboxsudo apt install virtualbox-dkms

并创建一个“流浪文件”:

sudo vagrant init bento/ubuntu-20.04

对于我们的项目,我们将创建或编辑一个特定的流浪文件来构建我们自己的环境,如下所示:

正如你在流浪者文件中看到的,我们正在创建一个名为“kubmaster”的主节点,它有一个 Ubuntu 版本 20.04,2Gb 内存和 2 个 CPU,一个 IP 地址(192.168.56.101)和 docker。然后,我们创建两个节点(kubnode1 和 kubnode2 ),它们的配置与主节点相同。

编辑后,切换到 root 并在终端中键入(Vagranfile 所在的位置):

vagrant up

该命令将根据我们编辑的 Vagrantfile 创建和配置来宾机器。完成该过程后,我们可以在您的终端中使用以下命令连接到客户机:

vagrant ssh kubmastervagrant ssh kubnode1vagrant ssh kubnode2

我们必须在主节点(kubmaster)和每个节点(kubnode1 和 kubnode2)上禁用交换。我们连接到每台客户机,以执行以下命令:

swapoff -avim /etc/fstab

fstab 文件中,我们需要注释掉交换行。

我们也在每台机器(kubmaster,kubnode1,kubnode2)上安装一些包,比如 curl 和 apt-transport-https:

apt-get update && apt-get install -y apt-transport-https curl

然后,我们执行一个 curl 来获取 gpg 密钥,这将允许我们使用 Kubernetes 二进制文件:kubectl、kubeadm、kubelet。

curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -

我们添加了对 Google 存储库的访问权限(http://apt . kubernetes . io),这将允许我们下载并安装二进制文件:

add-apt-repository “deb [http://apt.kubernetes.io/](http://apt.kubernetes.io/) kubernetes-xenial main”

要安装二进制文件,我们需要执行以下操作:

apt-get install -y kubelet kubeadm kubectl kubernetes-cnisystemctl enable kubelet

Kubernetes:初始化和内部网络

现在,我们已经在所有节点中安装了必要的包,我们将进行初始化和网络工作,以连接 Kubernetes 集群的不同部分。

要启动主节点,请连接到主节点并键入:

root@kubmaster:~# kubeadm init --apiserver-advertise-address=192.168.56.101 --node-name $HOSTNAME --pod-network-cidr=10.244.0.0/16

192.168.56.101 是我们之前定义的主节点的 IP 地址,10.244.0.0/16 是 Kubernetes 内部网络的 IP 地址,定义了 Kubernetes 在其网络内用于分配 IP 地址的范围。

我们看到以下输出,其中包含一个为加入不同节点而生成的令牌:

正如您在输出中看到的,要开始使用我们的集群,我们需要创建配置文件来使用 kubectl:

root@kubmaster:~# mkdir -p $HOME/.kuberoot@kubmaster:~# cp -i /etc/kubernetes/admin.conf $HOME/.kube/configroot@kubmaster:~# chown $(id -u):$(id -g) $HOME/.kube/config

为了建立内部网络,我们需要在集群中的节点之间提供一个网络。为此,我们将使用法兰绒,这是配置为 Kubernetes 设计的第 3 层网络结构的一种非常简单易行的方法。存在不同的解决方案,如 WeaveNet、Contiv、Cilium 等。法兰绒在每台主机上运行一个名为 flanneld 的二进制代理。法兰绒还负责从更大的预配置地址空间中为每台主机分配子网租约。

我们添加了 pod 以提供管理内部网络的可能性(在所有节点中启动命令):

sysctl net.bridge.bridge-nf-call-iptables=1

然后,我们通过在主节点中键入以下命令,在在线配置文件(kube-法兰绒. yml)的帮助下安装法兰绒网络:

kubectl apply -f [https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml](https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml)

我们检查主节点中 pod 的状态(法兰绒网络、kube-调度程序、kube-apiserver、kube-控制器-管理器、kube-代理、管理内部 DNS 的 pod、存储 etcd 配置的 pod 等):

kubectl get pods --all-namespaces

有时有必要通过编辑网络(从 10.244.0.0/16 到 10 . 10 . 0/16)来修改我们的法兰绒配置。为此,您可以执行以下操作:

kubectl edit cm -n kube-system kube-flannel-cfg# edit network 10.244.0.0/16 to 10.10.0.0/16

如果您在主节点中键入以下命令,我们可以看到我们的主节点已准备就绪:

kubectl get nodes

现在是将节点连接到主节点的时候了。为此,我们复制先前生成的令牌,并在两个节点(kubnode1 和 kubnode2)中键入以下命令:

kubeadm join 192.168.56.101:6443 --token 0dgzxg.86lj9mirur1ele2f \  --discovery-token-ca-cert-hash sha256:59ca1ef21c1c4304ff1558210cf78528a6750babc3fa69241e925c2d5f7d90c6

我们将看到以下输出:

回到主节点,键入以下命令检查状态:

kubectl get pods --all-namespaces

kubectl get nodes

我们应该看到状态为“就绪”的节点。我们还可以做一个 docker ps 来查看主节点和其他节点中所有已启动的容器(coredns、法兰绒等……)。

最后一点是关于集群访问。如果我们键入主节点:

kubectl get nodes

我们可以看到,我们的 kubmaster 和节点具有相同的内部 IP:

kubectl get nodes -o wide

我们需要打开并编辑/etc/hosts,并添加我们的主节点 IP:

vim /etc/hosts

每个节点(kubnode1 和 kubenode2)中的 /etc/hosts 文件也需要修改:

然后,我们可以通过键入主节点来删除每个法兰绒:

kubectl get pods -n kube-system

然后,

kubectl delete pods kube-flannel-ds-56f9h -n kube-systemkubectl delete pods kube-flannel-ds-dx8tv -n kube-systemkubectl delete pods kube-flannel-ds-kgxvt -n kube-system

Kubernetes 的神奇之处在于,它可以在不失去服务的情况下重新配置,并拥有新的 flannels:

我们将看到我们拥有正确的 IP 地址:

kubectl get nodes -o wide

为了更加方便,我们还可以通过键入以下内容来添加自动完成功能:

apt-get install bash-completionecho “source <(kubectl completion bash)” >> ~/.bashrcsource ~/.bashrc

后续步骤

现在我们知道如何安装 Kubernetes 集群,我们将能够创建 Kubernetes 作业,这些作业将创建 pods(以及容器),例如,允许训练我们的机器学习模型,序列化它们,将模型加载到内存中,并执行批处理或在线推理。我们在这里探讨了这些概念:

https://xaviervasques.medium.com/machine-learning-with-docker-and-kubernetes-training-models-cbe33a08c999 https://xaviervasques.medium.com/machine-learning-with-docker-and-kubernetes-batch-inference-4a25328f23c7 https://xaviervasques.medium.com/machine-learning-prediction-in-real-time-using-docker-python-rest-apis-with-flask-and-kubernetes-fae08cd42e67

来源

https://phoenixnap.com/blog/kubernetes-vs-docker-swarm

https://kubernetes.io/fr/docs/concepts/

https://kubernetes.io/fr/docs/tasks/tools/install-kubectl/

https://www.vagrantup.com/downloads

https://git lab . com/xavki/presentations-kubernetes/-/tree/master

https://github.com/flannel-io/flannel

Docker 和 Kubernetes 的机器学习:训练模型

原文:https://towardsdatascience.com/machine-learning-with-docker-and-kubernetes-training-models-cbe33a08c999?source=collection_archive---------2-----------------------

Kubernetes,Docker,Python 和 sci kit-机器和深度学习的学习:如何扩大数据科学家的努力

Annamária Borsos 摄影

Kubernetes Jobs:模型训练和批量推理

在这一章中,我们将研究 Kubernetes 的工作,以及我们如何使用这些工作来训练机器学习模型。一个作业创建一个或多个 pod。这是一个 Kubernetes 控制器,确保 pod 成功终止其工作负载。当指定数量的 pod 终止时,作业被视为完成。如果一个 Pod 失败,作业将创建一个新的 Pod 来替换它。

我们的目标将是创建一个 Kubernetes 作业,让我们称之为“训练作业”,它加载存储在 GitHub 中的训练数据,训练一个机器学习模型,序列化该模型,并将其存储在集群外部。为了在我们的集群之外存储数据,我们可以使用不同的位置,例如公共云、私有云或内部。在我们的例子中,我们将在 Kubernetes 集群和外部服务器之间使用 SSH。我们之所以使用外部存储,是因为作业将创建彼此独立的 pod 运行容器。我们需要借助外部存储来持久化我们的模型对象。

你可以在 GitHub 上找到本章用到的所有文件

创建并准备虚拟机

要安装我们的 Kubernetes 集群,让我们创建虚拟机或使用裸机服务器。本文中的所有指令都是使用 Ubuntu 版本 20.04 创建的虚拟机进行测试的:

-kub master:2 vpus,4096MB 内存,20GB 驱动器空间

-kube node 1:2 vcpu,4096MB 内存,20GB 驱动器空间

我们启用了虚拟机和主机之间的流量。

切换到 root,确保关闭交换,并在/etc/fstab 中注释掉引用交换:

swapoff -avim /etc/fstab

Kubeadm 装置

首先,我们将在每个虚拟机中安装 docker 引擎(在我们的例子中:kubmaster 和 kubenode1)。要安装它,你可以选择你喜欢的方法(【https://docs.docker.com/engine/install】T2)。我们将使用存储库。下面的不同步骤将更新 apt 包索引,安装包以允许 apt 通过 https 使用存储库,添加 Docker 的官方 GPG 密钥,设置稳定的存储库,并安装最新版本的 Docker 引擎和 containerd。

sudo apt-get updatesudo apt-get install \ apt-transport-https \ ca-certificates \ curl \ gnupg \ lsb-releasecurl -fsSL [https://download.docker.com/linux/ubuntu/gpg](https://download.docker.com/linux/ubuntu/gpg) | sudo gpg —-dearmor -o /usr/share/keyrings/docker-archive-keyring.gpgecho \
  "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \    
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/nullsudo apt-get updatesudo apt-get install docker-ce docker-ce-cli containerd.io

然后,在切换到 root (sudo -s)之后,我们执行一个 curl 来获取 gpg 密钥,这将允许我们使用 Kubernetes 二进制文件:kubectl、kubeadm、kubelet

curl -s [https://packages.cloud.google.com/apt/doc/apt-key.gpg](https://packages.cloud.google.com/apt/doc/apt-key.gpg) | apt-key add -

我们添加了对 Google 存储库( http://apt.kubernetes.io )的访问,这将允许我们下载并安装二进制文件:

add-apt-repository “deb [http://apt.kubernetes.io/](http://apt.kubernetes.io/) kubernetes-xenial main”

要安装二进制文件,我们需要执行以下操作:

apt-get install -y kubelet kubeadm kubectl kubernetes-cnisystemctl enable kubelet

所有这些步骤都必须在集群的所有节点(主节点和节点)中完成。

创建一个 Kubernetes 集群

现在,我们已经在所有节点中安装了必要的包,我们将进行初始化和网络工作,以连接 Kubernetes 集群的不同部分。

要启动主节点,请连接到主节点并键入:

root@kubmaster:~# kubeadm init --apiserver-advertise-address=192.168.1.55 --node-name $HOSTNAME --pod-network-cidr=10.244.0.0/16

192.168.1.55 是我们之前定义的主节点(kubmaster)的 IP 地址,10.244.0.0/16 用于定义 Kubernetes 内部网络的范围,Kubernetes 将使用该范围来分配其网络内的 IP 地址。

我们得到以下输出:

正如您在输出中看到的,要开始使用我们的集群,我们需要创建配置文件来使用 kubectl(作为一个普通用户):

mkdir -p $HOME/.kubecp -i /etc/kubernetes/admin.conf $HOME/.kube/configchown $(id -u):$(id -g) $HOME/.kube/config

为了建立内部网络,我们需要在集群中的节点之间提供一个网络。为此,我们将使用法兰绒,这是配置为 Kubernetes 设计的第 3 层网络结构的一种非常简单易行的方法。我们需要提供管理内部网络的可能性(在所有节点启动命令):

sysctl net.bridge.bridge-nf-call-iptables=1

然后,我们通过在主节点中键入以下命令,在在线配置文件(kube-法兰绒. yml)的帮助下安装法兰绒网络:

kubectl apply -f [https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml](https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml)

我们检查主节点中 pod 的状态(法兰绒网络、kube-调度程序、kube-apiserver、kube-控制器-管理器、kube-代理、管理内部 DNS 的 pod、存储 etcd 配置的 pod 等):

kubectl get pods --all-namespaces

如果一切都在运行,是时候将节点加入主节点了。为此,我们复制先前生成的令牌,并在节点(kubenode1)中键入以下命令:

kubeadm join 192.168.1.55:6443 --token 08hcql.zbbieukn1h96f1px \   
--discovery-token-ca-cert-hash sha256:851d02642c9b2177dd89c8e7cf7178c36185d61799eaaec4fec99b172809373f

回到主节点,键入以下命令检查状态:

kubectl get pods --all-namespaces

如果您在主节点中键入下面的命令,我们可以看到我们的主节点和 kubnode1 都准备好了:

kubectl get nodes

将训练模型 Python 应用程序容器化

正如我们在前面章节中所做的,我们需要创建我们的 Dockerfile 来指示 Docker 一个基本映像、我们需要的设置和要执行的命令。我们将使用 jupyter/scipy-notebook 图像作为我们的基本图像。

正如您所看到的,我们设置了环境变量,并安装了 joblib ,以允许序列化和反序列化我们训练过的模型,以及 paramiko ,它是 SSHv2 协议的 Python 实现( requirements.txt )。

我们从一开始就设置环境变量来持久化训练好的模型,并添加数据和元数据。我们将 train.py 文件复制到映像中。我们还复制我们将使用 ssh-keygen 生成的 id_rsa 文件,以便能够通过 ssh 连接到远程服务器。

我们必须设置 RSA 密钥身份验证,以建立集群和外部服务器之间的连接。我们需要生成一个公钥( id_rsa.pub )和私钥( id_rsa ),我们可以用它们来进行身份验证:

ssh-keygen -t rsa

我们将 id_rsa.pub 的内容复制/粘贴到~/中。ssh/authorized_keys 文件(在目标系统上):

vim /home/xavi/.ssh/id_rsa.pub

如果需要,我们可以将 id_rsa 文件复制到我们当前的目录中,并用 chmod 修改权限:

sudo cp /home/xavi/.ssh/id_rsa .sudo chmod a+r id_rsa

然后我们将使用 docker run 命令删除 id_rsa 文件。

对于这一步,我们可以使用不同的方法,比如通过确保在构建过程结束时删除 id_rsa 文件来编写一个 docker 文件:

ARG SSH_PRIVATE_KEYRUN mkdir /root/.ssh/RUN echo “${SSH_PRIVATE_KEY}” > /root/.ssh/id_rsa# […]RUN rm /root/.ssh/id_rsa

并使用以下内容构建 docker 映像:

sudo docker build -t kubernetes-models -f Dockerfile --build-arg SSH_PRIVATE_KEY=”$(cat ~/.ssh/id_rsa)” .

这并不是本章的主题,但是我们需要注意不要在 Docker 图像中留下痕迹。即使我们正在删除一个文件,它仍然可以在我们将推送的图像的一个层中查看。我们可以使用–squash 参数将原点和最新阶段之间的多个图层减少到一个。此外,可以使用–squash 参数通过删除不再存在的文件来减小图像的大小。我们还可以在单个 Docker 文件中处理多阶段构建,在该文件中我们构建多个 Docker 映像。只有最后一个会坚持,会留下痕迹。

# This is intermediateFROM ubuntu as intermediate# […]# Final imageFROM ubuntu# […]

出于安全原因,我们还可以使用 Kubernetes secret 对象来存储和管理敏感信息,比如密码、OAuth 令牌和 ssh 密钥。将这些信息放在秘密中比硬放在 Pod 的定义或图像容器中更安全、更灵活:https://kubernetes.io/docs/concepts/configuration/secret/

现在我们有了 other 文件,让我们看看其他文件。在 train.py 中,我们首先导入必要的库,读取 Docker 映像中为持久模型设置的环境变量,加载存储在 Github 上的训练数据(train.csv),训练两个模型(线性判别分析和多层感知器神经网络),序列化它们,执行交叉验证,将训练好的模型和交叉验证结果上传到远程服务器(192.168.1.11)和指定目录(/home/xavi/output/)。我们还可以将 URL、指定的目录和 IP 地址定义为环境变量。

我们可以进入下一步,构建 docker 映像,运行它以在本地测试我们的应用程序,在 Docker Hub 注册表上用映像存储库的名称标记它,并将其推送到注册表,准备在我们的 Kubernetes 集群中使用该映像:

docker build -t kubernetes-models -f Dockerfile .

为了测试我们的代码是否正常,我们将在本地运行您的容器并测试我们构建的映像:

docker run kubernetes-models python3 train.py rm ./id_rsa

如果一切正常,我们可以使用 CLI 将新映像推送到存储库:

docker logindocker tag kubernetes-models:latest xaviervasques/kubernetes-models:latestdocker push xaviervasques/kubernetes-models:latest

为 Kubernetes 创建配置文件

一旦映像成功上传到注册表,我们就转到我们的项目目录(连接到 kubmaster)并创建一个执行我们的 python 代码的作业配置: job.yaml.

正如 Kubernetes 文档中所解释的,与所有其他 Kubernetes 配置一样,一个作业需要 apiVersionkindmetadatafields 。一份工作也需要一个 。规格部分apiVersion 指定要使用的 Kubernetes API 的版本,kindKubernetes 资源的类型,我们可以提供一个带有元数据的标签。 .spec.template的唯一必填字段。spec 表示一个 pod 模板,因为除了没有嵌套 apiVersionkind 之外,它具有相同的模式。英寸我们给每个容器一个名字,我们想要使用的图像和我们想要在容器中运行的命令。这里我们想运行 train.py 并删除我们的 id_rsa 文件。

等效的 docker 命令应该是

docker run kubernetes-models python3 train.py rm ./id_rsa

由于有了 imagePullPolicy ,Kubernetes 将从注册表中查找图像,而不是使用缓存的图像。最后,我们设置容器在失败时是否应该重新启动(Never 或 OnFailure ),并决定在将作业视为失败之前的重试次数(默认情况下,退避限制设置为 6 分钟)。

我们终于准备好让我们的应用程序在 Kubernetes 上运行了。启动以下命令:

kubectl create -f job.yaml

通过运行以下命令检查作业对象:

kubectl get jobskubectl get pods --selector=job-name=train-models-job

我们可以查看流程的日志:

kubectl logs train-models-job-vd5rq

所有文件都存储在远程服务器上。

删除集群的几个命令

我们可以在 Kubernetes 文档中找到几个有用的命令。例如:

删除作业

kubectl delete job train-models-job

重置 kubeadm

sudo kubeadm reset

删除整个集群

kubeadm resetsudo apt-get purge kubeadm kubectl kubelet kubernetes-cni kube*sudo apt-get autoremovesudo rm -rf ~/.kube

后续步骤

下一步将是通过从我们训练好的模型中加载预测来进行批量推断/评分,并使用 REST APIs 进行实时在线推断。我们在这里探讨了这些概念:

https://xaviervasques.medium.com/machine-learning-with-docker-and-kubernetes-batch-inference-4a25328f23c7 https://xaviervasques.medium.com/machine-learning-prediction-in-real-time-using-docker-python-rest-apis-with-flask-and-kubernetes-fae08cd42e67

来源

https://kubernetes . io/docs/concepts/workloads/controllers/job/

https://vsupalov . com/build-docker-image-clone-private-repo-ssh-key/

https://kubernetes . io/fr/docs/concepts/configuration/secret/

https://developer . IBM . com/technologies/containers/tutorials/scalable-python-app-with-kubernetes/

https://docs.docker.com/engine/install/ubuntu/

用谷歌的 BigQuery 进行机器学习

原文:https://towardsdatascience.com/machine-learning-with-googles-bigquery-6602e734bf74?source=collection_archive---------26-----------------------

如何使用 SQL 轻松创建和部署 ML 模型

彼得·奥勒克萨在 Unsplash 上拍摄的照片

从数据仓库或数据湖中提取数据的传统方法——然后用它清理、转换和建立模型——正在慢慢被一种叫做 的新方法所取代。这种新方法将计算引入数据,或将机器学习/算法引入数据【1】在像 Google 的 BigQuery 这样的服务中,传统的数据库系统甚至用 ML 工具进行了内部扩展[2]。

新范式的优势

新方法的优势包括简化的基础架构。如果我们看一下下面的简化架构,就可以清楚地看到,如果服务已经可以在云环境中相互通信,或者集成在一个服务中,那么就不需要第三方系统的进一步接口。这大大缩短了这些环境的设置和维护时间。

经典分析过程架构—作者图片

另一个重要因素是数据科学流程可以显著简化。每个数据科学家和工程师都知道这一过程有多耗时,因此将您需要的一切都放在云环境甚至服务中的方法大大简化了这一过程。

集成的数据湖和分析平台—作者图片

第三点是可编程性的简化——比如分析师只用 SQL 就能轻松完成机器学习任务。下面,我想用 BigQuery 中的一个简单例子来说明这一点。如果您想更深入地了解数据平台现代化这一主题,您可能会对这篇文章感兴趣。

BigQuery ML 示例

为了展示解决方案如何简化数据分析过程,我将使用 BigQuery 及其 ML 功能。这里,我使用了公共数据集,其中包含了爱荷华州所有批发购买的酒。

在这个例子中,我只是想做一些聚类。这个例子非常简单,但是很好地展示了可能性和您必须采取的步骤。

第一步:创建模型

CREATE OR REPLACE MODEL DATA.iowa_bottle_clusters OPTIONS (model_type=’kmeans’, num_clusters=3, distance_type = ‘euclidean’) ASSELECT item_description, AVG(state_bottle_cost) AS state_bottle_cost,FROM `bigquery-public-data.iowa_liquor_sales.sales`WHERE EXTRACT(YEAR FROM date) = 2018GROUP BY item_description;

上面,您可以看到我使用了 k-Means 算法,并将聚类数的参数设置为 3。对于这个高度简化的例子,我的想法是使用变量state _ bottle _ payed(酒精饮料部门为订购的每瓶酒支付的金额)将其分为三个价格类别。

第二步:评估模型

创建模型后,BigQuery 会自动为您提供一些指标。这些允许对聚类算法进行评估。对于戴维斯-波尔丁指数,目标将是最低的可能值【3】。

指标—按作者分类的图像

另一个很棒的特性是我们得到的损失图表。

损失-作者提供的图像

随着

SELECT * FROM ML.TRAINING_INFO(MODEL Data.iowa_bottle_clusters);

SELECT davies_bouldin_index FROM ML.EVALUATE(MODEL Data.iowa_bottle_clusters);

如果需要,您可以稍后查询结果。

第三步:预测

经由毫升。预测我们将看到特定品牌属于哪个集群。

SELECT
 centroid_id,
 item_description,
 state_bottle_cost
FROM
 ML.PREDICT(MODEL Data.iowa_bottle_clusters,(SELECT
  item_description,
  AVG(state_bottle_cost) AS state_bottle_cost
 FROM
  bigquery-public-data.iowa_liquor_sales.sales
 WHERE
  date <= '2018-02-02'
  AND date >='2018-01-01'
 GROUP BY
  item_description) )
 ORDER BY
  centroid_id;

第四步:检查结果

现在让我们检查结果是否有意义。以下是三个集群的示例:

第一组中只有一个项目,似乎是高级产品:

1 —雷米·马丁路易十三干邑— 1599.19

在第二组中,我们有更多的瓶子,似乎被认为是中产阶级,例如:

2 —达尔莫尔雪茄麦芽苏格兰威士忌— 93.33

2 —卡瓦兰雪利酒橡木单一麦芽— 73.33

2 —吉姆梁酒厂的杰作— 104.91

还有一组产品,你可能会将它们与可乐或其他软饮料混合在一起:

3 —斯米尔诺夫葡萄— 8.25

3 —斯米尔诺夫酸青苹果— 8.25

3 —伯内特水果潘趣酒— 4.48

所以最终的结果并没有那么糟糕——但当然可以优化。这里您需要的只是 BigQuery 和一些基本的 SQL。

结论

在这篇短文中,我想提供一些关于将机器学习或算法转移到数据的范式的理论基础知识。此外,相对于传统方法的优势是显而易见的。尤其是在设置和维护方面,以及在节省时间方面的实际数据分析过程。BigQuery ML 使机器学习的使用民主化。数据科学家和分析师可以使用 BigQuery ML 来构建和运行模型,而不必访问新的商业智能工具和表。预测分析有助于商业决策。最后,我展示了现在只使用 SQL 和 Google 的 BigQuery 开发一个机器学习模型是多么容易。有关更多信息,请单击下面的链接。

资料来源和进一步阅读

[1]唐斯,B. N .,奥菲姆,D. M .,黑尔,w .,Xi,l .,多纳霍,L. A .,&卡拉,D. (2014)。将计算引入数据的实际例子。生物分子技术杂志:JBT , 25 (增刊),S5。

[2] Google,什么是 BigQuery ML? (2020 年)

[3]戴维斯博士,波尔丁博士(1979 年)。“一个集群分离措施”。IEEE 模式分析与机器智能汇刊。PAMI-1 (2),第 224 至 227 节。

带图的机器学习:开发工作流概述

原文:https://towardsdatascience.com/machine-learning-with-graphs-workflow-4ad40b50a32c?source=collection_archive---------36-----------------------

实践教程

在 ML 生命周期中,带有图形的机器学习任务发生在何处的概念性概述。

图片由作者提供。

使用图形的机器学习帮助建立预测模型的方式与众所周知的无监督和半监督方法应用于监督模型的方式非常相似。这意味着通常有两种方法可以将带有图形的机器学习部署到 ML 工作流中。第一种方法是创建一个所谓的节点嵌入,并将其传递给下游的机器学习任务。对图形应用机器学习的第二种方式是直接在图形数据结构上进行标签和链接预测。早些时候,我写了一篇关于机器学习的介绍,带图以及包括哪些任务。这篇文章是对那篇文章的补充,将集中于给出这些任务如何嵌入 ML 工作流的简明概述。

机器学习开发工作流程

一个典型的机器学习开发工作流程由以下用蓝框表示的阶段组成:

在特征工程和模型训练期间用图形学习技术增强的监督机器学习工作流。图片由作者提供。

机器学习开发工作流从数据检索开始,其中(大部分)非结构化原始数据是从源中获取的。此后,在数据准备步骤中,目标是将数据转换为结构化格式,以便它可以用于模型训练。模型经过训练后,可以使用各种性能和验证方法对其进行评估。在数据准备阶段,必须完成一项称为特征工程的关键任务。特征工程是将原始数据转换为特征的过程,这些特征可以更好地代表预测模型的潜在问题,从而提高未知数据的模型准确性因此,数据科学家必须设计并决定哪些特征在预测目标标签时是重要的。因此,拥有用例的适当的业务领域知识是执行特性工程任务的先决条件。

使用图形数据的特征工程

这就是使用图形结构化数据的特征工程可以提供帮助的地方。这种工作原理的基本假设是,数据点不是孤立存在的,它们是通过与数据集中的其他记录进行交互而出现的。我们可以在此阶段构建一个机器学习模型,根据数据集中数据点(记录)之间的关系属性生成特征,而不是依赖数据科学家的创造力和领域知识来得出对他们来说重要的特征。这些特性被称为节点嵌入,其中每个节点都是一个数据点。因此,每个节点嵌入都是它与数据集中其他数据点的结构关系的表示。节点之间的相互作用与他们的邻居节点被捕获在结果节点嵌入。创建节点嵌入的方法有很多种。这些方法中的许多使用图形神经网络(GNN)或其深度学习变体(例如图形卷积网络(GCN))将局部邻域节点和边的属性聚集到嵌入中。本质上,GNN 试图将节点属性及其与其他节点的关系编码到潜在空间的向量中。然而,这些图形学习技术是另一个主题,我将在另一篇文章中讨论。此阶段的结果是节点嵌入,它将作为一个特征传递给下游任务,用于任何分类或回归预测。

左图:传统的特征工程步骤要求数据科学家在特征选择过程中手工挑选他或她认为与预测相关的特征。右图:图的特征工程没有特征选择,而是训练一个图神经网络来确定节点属性和关系,以及图统计,包括以节点嵌入的形式确定特征向量。图片由作者提供。

图形上的训练和预测

在上面的方法中,来自特征工程的结果导致节点嵌入,该节点嵌入然后将被用作另一个下游机器学习模型的输入特征向量。然而,也可以直接从图结构数据中预测节点或节点之间的链接。这些任务就是所谓的节点分类和链路预测。这里的关键是,不是手动挑选哪个关系结构导致更好的预测,而是训练模型来找到最重要的结构模式和节点属性集,以分配标签和预测关系。

使用图形神经网络来训练节点嵌入,以预测节点标签或边。输入是嵌入了节点标签的一次性编码向量的节点,输出是预测的节点标签。图片由作者提供。

通常,通过以完全监督的方式训练图形神经网络来实现节点分类,其中损失函数被定义在节点嵌入(在上述早期特征工程步骤中创建)和指示节点所属类别(标签)的独热向量上。因此,模型将在节点嵌入时被训练,并且图形神经网络的输出将标记每个节点。结果,节点已经被标记,因此不需要将节点嵌入作为特征向量传递到下游任务以进行分类或回归。

结论

首先,使用图的机器学习可以在特征工程阶段代替特征选择任务。传统的机器学习工作流依赖于数据科学家的洞察力来选择特征,而 ML with graphs 训练图形神经网络来输出每个节点的特征向量,称为节点嵌入。然后,该节点可以被传递到任何下游分类器中。其次,也可以直接在图形数据结构上进行预测。在这种情况下,一个节点嵌入将被传递到一个图形神经网络来预测其标签。

来源

图形表示学习 https://www.cs.mcgill.ca/~wlh/grl_book/

图的表征学习:方法与应用 https://arxiv.org/abs/1709.05584

发现特征工程 https://machine learning mastery . com/Discover-Feature-Engineering-how-to-engineer-features-and-how-to-get-good-it/

仅使用 SQL 的机器学习—使用 BigQuery 识别共享自行车的目标受众

原文:https://towardsdatascience.com/machine-learning-with-only-sql-using-bigquery-to-identify-the-target-audience-for-shared-bike-aa3a4041be3a?source=collection_archive---------19-----------------------

关于如何比较假设和提示以提高准确性的案例

佐伊·赖在 Unsplash 上的照片

我们不能用 Python 做机器学习的原因有很多:

  • 我们仍在学习新的编程语言
  • 我们需要尽快交付结果,并且更喜欢分析数据所在的位置
  • 没有访问 Python 的权限

无论你有哪种情况,我都将分享如何只用 SQL 进行机器学习,了解影响自行车共享旅行持续时间的关键特征,以及我对数据仓库发展的观察。

内容

  • 用例:预测自行车共享出行的平均持续时间
  • 挑战
  • 第一步:假设关键特征
  • 步骤 2:定义指标
  • 步骤 3:构建并评估模型
  • 第四步:预测结果
  • 第五步:如何提高你的模型的准确性?
  • 思想

用例:预测自行车共享出行的平均持续时间

自行车共享旅行的平均持续时间与共享自行车业务的收入直接相关,就像零售的平均订单价值一样。为了更深入地了解影响持续时间的关键因素,我使用了谷歌云平台上的公共数据集 Austin Bikeshare 。要分析,登录 bigquery 后指向 big query-public-data:Austin _ bike share。

挑战

当仔细查看表 bikeshare_trips 和 bikeshare_stations 时,有许多功能可供培训选择。一种方法是利用 AutoML,但这不是我们在本文中的重点。本文将开发两个假设,并通过将它们训练成模型并用度量标准对它们进行评估来对它们进行比较。

BigQuery Web 界面(按作者)

BigQuery Web 界面(按作者)

第一步:假设关键特征

这里有两个假设:

  • 假设 A:关键因素是起点站、起点站的位置、一周中的哪一天以及旅行开始的时间
  • 假设 B:关键因素是始发站、用户类型和旅行开始的时间。

步骤 2:定义指标

在训练模型之前,确定评估指标是至关重要的。毕竟如果要比较两个结果,就要把标准说清楚。机器学习是基于特征、参数和框架的排列和组合。我们需要的是选择一个精确度最高的。

有许多度量标准。以下是回归中常用的一些指标:

  • 绝对平均误差
  • 均方根误差

如果你和我一样健忘,不用担心,卡恩学院很好地解释了平均绝对偏差和均方根误差

步骤 3:构建并评估模型

然后,我们使用选择的特性和期望的结果(在这个例子中是持续时间)来使用 CREATE MODEL 和 ML 构建一个回归模型。评估语法。

我们发现,在假设 B 中,平均绝对误差和均方根误差要小得多,这意味着假设 B 的特征与期望的结果正相关。

BigQuery Web 界面(按作者)

第四步:预测结果

最后,使用 ML。预测得出 2019 年数据集中的平均时长将为 51 分钟的结果。

第五步:如何提高你的模型的准确性?

如何提高准确性是数据科学家最感兴趣的问题之一。

我曾经分解一个过程中的步骤并逐一解决。

以下是我的思考过程:

  • 数据
  • 特征
  • 算法
  • 参数

让我们把重点放在基本面上,比如数据和特性。我们已经做了一个调整特性的小实验。如果更深入地研究数据,可以使用一些基本的观察统计数据,例如观察平均值、最大值和最小值,看看它们是否有意义。例如,表中的一些数据没有意义,持续时间超过 30,000 小时,或长度< 0。

如果我们能剔除这些数据,预测结果的可信度会更令人满意。

思想

BigQuery 让用 SQL 实现 ML 成为可能

不是每个人都可以使用 Python,但是如果我们无论如何都需要交付呢?对于一些数据库管理员或数据分析师来说,熟悉 Python 可能不是“必备”技能。BigQuery 内置 ML 让我们无需掌握一门新语言就能交付业务结果。

简化流程,让您可以专注于最重要的事情

在进入机器学习项目之前,我经常看到我的企业客户在各种先决条件之间跑来跑去。因此,由于数据移动、安全检查、访问控制和网络设置,交付结果更加耗时。现在,许多解决方案提供商集成了工具,使流程更加顺畅。比如做数据分析的时候,我们以前都是下载数据库里的数据,发送数据,导入 IDE。现在,只有 Mount 函数可以完成这项工作,就像使用 USB 堆栈将数据加载到计算机中一样。

数据仓库正在发展,将 BI 和 ML 结合为一个数据分析平台

在过去,数据仓库只是一个并行数据处理和存储的工具。随着时间的推移,它还结合了商业智能和机器学习等新元素,用于更复杂的分析工作。此外,许多数据仓库提供实时分析,以满足大数据场景中的流需求。下面的架构展示了如何将 Synapse(微软的数据仓库解决方案)用于物联网设备和 web 点击数据分析。

来源:大数据架构实时分析

声明:这是在完成用 BigQuery ML 创建 ML 模型之后的一篇文章。如果你需要更多的细节,请随时参考我的问题

保持联系

  • Medium 上关注我,了解更多类似的故事
  • LinkedIn 上连接
  • 你怎么想呢?留下评论

带 R 的机器学习:决策树完全指南

原文:https://towardsdatascience.com/machine-learning-with-r-a-complete-guide-to-decision-trees-1d4dfc88bc20?source=collection_archive---------30-----------------------

用决策树进行机器学习和分类的简单明了的指南。

Fabrice VillardUnsplash 拍摄的照片

决策树是监督机器学习中最基本的算法之一,用于处理回归和分类任务。简而言之,你可以把它看作是一个美化的 if-else 语句的集合,但是后面会有更多的介绍。

今天,您将学习决策树算法背后的基本理论,以及如何用 r 实现该算法。

这篇文章的结构如下:

  • 决策树介绍
  • 数据集加载和准备
  • 建模
  • 做预测
  • 结论

决策树介绍

决策树很直观。他们所做的只是问一些问题,比如性别是男性还是某个特定变量的值高于某个阈值。基于答案,要么问更多的问题,要么进行分类。简单!

为了预测类标签,决策树从根(根节点)开始。计算哪个属性应该表示根节点是很简单的,归结起来就是计算哪个属性最好地分隔了训练记录。计算是通过基尼系数公式完成的。这是简单的数学,但是如果你有很多属性的话,手动计算会很繁琐。

在确定根节点之后,树“分支”以更好地分类在根节点中发现的所有杂质。

这也是为什么经常听到决策树=多个 if-else 语句类比的原因。这种类比在一定程度上是有道理的,但是条件语句是自动计算的。简单来说,机器学习你的数据的最佳条件。

让我们来看看下面的决策树表示法,以进一步阐明这些观点:

图 1 —示例决策树(来源)

如你所见,变量展望?湿度?刮风?用于预测因变量——作用。

现在您已经知道了算法背后的基本理论,接下来您将学习如何在 R 中实现它。

数据集加载和准备

没有数据就没有机器学习,没有库就没有数据工作。你需要这些来跟随:

如您所见,我们将使用 Iris 数据集来构建决策树分类器。这是前几行的样子(来自head()函数调用的输出):

图 2 —虹膜数据集头部(图片由作者提供)

对于任何有一周数据科学和机器学习经验的人来说,数据集都非常熟悉,因此不需要进一步介绍。此外,数据集非常干净,这将为我们节省大量时间。

在继续进行预测建模之前,我们唯一要做的事情是将这个数据集随机分成训练和测试子集。您可以使用以下代码片段以 75:25 的比例进行拆分:

就是这样!接下来我们从建模开始。

建模

我们使用rpart库来构建模型。构建模型的语法与线性回归和逻辑回归相同。您需要将目标变量放在左边,将特性放在右边,用~符号隔开。如果您想使用所有功能,请在前面加一个点(。)而不是功能名称。

另外,不要忘记指定method = "class",因为我们在这里处理的是一个分类数据集。

以下是训练模型的方法:

调用model的输出如下图所示:

图 3 —决策树分类器模型(图片由作者提供)

仅从这张图片中,您就可以看到用于进行分类的“规则”决策树模型。如果您想要更直观的表示,您可以使用rpart.plot包来可视化树:

图 4-决策树的可视化表示(图片由作者提供)

您可以通过检查底部节点来查看有多少分类是正确的(在训练集中)。 setosa 每次都被正确分类,5%的时间里杂色被错误分类为海滨,3%的时间里海滨被错误分类为杂色。这是一个简单的图表,但你可以从中读出一切。

决策树对于检查特征的重要性也很有用,因此,每个特征有多少预测能力。你可以使用varImp()功能来了解一下。以下代码片段计算重要性,并按降序对它们进行排序:

结果如下图所示:

图片 5 —特征重要性(作者图片)

到目前为止,您已经构建并探索了模型,但是还没有任何用处。下一节将向您展示如何对以前未见过的数据进行预测并评估模型。

做预测

预测新实例现在是一项微不足道的任务。您所要做的就是使用predict()函数并传递测试子集。此外,确保指定type = "class"以使一切正常工作。这里有一个例子:

结果如下图所示:

图 6-决策树预测(图片由作者提供)

但是这些预测有多好呢?我们来评价一下。混淆矩阵是评估分类模型最常用的度量之一。在 R 中,它还输出其他度量的值,比如灵敏度、特异性等。

以下是打印混淆矩阵的方法:

结果如下:

图 7 —测试集上的混淆矩阵(图片由作者提供)

正如你所看到的,在云芝海滨类中有一些错误的分类,类似于我们在训练集中看到的。总体而言,该模型的准确率略低于 90%,这对于简单的决策树分类器来说是可以接受的。

结论

决策树是整个基于树的算法家族的优秀入门算法。它通常被用作基线模型,更复杂的基于树的算法(如随机森林和梯度推进)需要胜过它。

今天,您已经学习了决策树背后的基本逻辑和直觉,以及如何在 r 中实现和评估算法。您可以期待很快涵盖整个基于树的算法套件,如果您想了解更多,请继续关注。

喜欢这篇文章吗?成为 中等会员 继续无限制学习。如果你使用下面的链接,我会收到你的一部分会员费,不需要你额外付费。

https://medium.com/@radecicdario/membership

保持联系

原载于 2021 年 2 月 10 日 https://appsilon.com**的

带 R 的机器学习:逻辑回归完全指南

原文:https://towardsdatascience.com/machine-learning-with-r-a-complete-guide-to-logistic-regression-16e93e609443?source=collection_archive---------24-----------------------

带 r 的机器学习和逻辑回归最简单指南。

凯尔·汉森在 Unsplash 上的照片

逻辑回归是统计学中最基本的算法之一,通常用于机器学习。它不用于生成 SOTA 模型,但可以作为二元分类问题的优秀基线。

对初学者的机器学习感兴趣? 下面是关于 R 线性回归的详细指导。

今天,您将学习如何在 R 中实现逻辑回归模型,并提高您的数据清理、准备和特性工程技能。

这篇文章的结构如下:

  • 逻辑回归介绍
  • 数据集加载和浏览
  • 特征工程和处理缺失数据
  • 建模
  • 生成预测
  • 结论

逻辑回归介绍

逻辑回归是一种在统计学和机器学习中都使用的算法。机器学习工程师经常将其用作基线模型——一个其他算法必须超越的模型。它也经常被首先使用,因为它很容易解释。

在某种程度上,逻辑回归类似于线性回归,但后者不用于预测连续值(如年龄或身高)。相反,它被用来预测二元分类——客户是否被搅动,病人是否幸存,或者疾病是恶性的还是良性的。为了简化,逻辑回归用于预测是/否类型的响应。

那不完全正确。逻辑回归告诉我们响应的概率,然后我们使用预定义的阈值来分配类别。例如,如果概率大于 0.5,则分配的类别为,否则为。使用不同的阈值评估性能可以减少误报或漏报的数量,这取决于您希望如何进行。

如您所想,逻辑回归可以处理连续数据和分类数据。这意味着您的数据集可以包含任何类型的数据,只要它准备充分。

您可以使用逻辑回归模型来检查特性的重要性。稍后,您将通过动手示例了解如何操作。了解哪些特性是重要的,可以让您构建更简单、维度更少的模型。因此,预测和模型更容易解释。

这就是逻辑回归背后的基本直觉。接下来让我们把手弄脏。

数据集加载和浏览

最著名的二元分类数据集之一是 Titanic 数据集。目标是根据许多输入特征(如年龄、乘客级别等)预测乘客是否在事故中幸存。

您不必下载数据集,因为在 r 中有一个专门的包。您将在整篇文章中只使用训练数据集,因此您不必做两次准备和特性工程。

以下代码片段加载到每个必需的包中,将训练数据集存储到名为df的变量中,并打印其结构:

下面是相应的结构:

图 1-泰坦尼克号数据集结构(图片由作者提供)

需要做很多工作。例如,某些列中缺失的值用空字符串标记,而不是用NA标记。这个问题很容易解决,一旦你解决了它,你就可以绘制一个缺失图。它将显示丢失值的位置:

缺失图如下所示:

图 2 —缺失图(作者提供的图片)

前三列包含缺失的数据。您将在下一节看到如何解决这个问题。

特征工程和处理缺失数据

您需要特征工程,因为默认特征要么格式不正确,要么不能以最佳方式显示信息。只要看看图 1 中的Name列——一个算法无法以默认格式处理它。

但是这个功能还是挺有用的。你可以从中提取乘客头衔(例如小姐先生等等)。最后一步,您可以检查乘客是否有罕见的头衔(例如,多娜女士少校等等)。

下面的代码片段就是这样做的:

在下图中,您可以看到我们现在拥有的所有独特标题:

图 3-独特的乘客标题(作者图片)

您可以对Cabin列应用类似的逻辑。默认情况下这是无用的,但可以用来提取甲板号。方法如下:

下图显示了唯一的牌组编号:

图 4——唯一的甲板号(作者图片)

您现在已经完成了一些功能工程,这意味着可以删除原始的列。下面的代码片段删除了这两个,还有PassengerIdTicket,因为它们没有提供任何有意义的信息:

最后,您可以将焦点转移到缺失的值上。将使用两种方法——模式和 MICE 插补。

您将对Embarked列使用众数(最频繁值)插补,因为它只包含几个缺失值。老鼠插补将需要更多的工作。将分类变量转换成因子是必须的,插补是通过排除目标变量来完成的。

以下是输入缺失值的完整代码片段:

作为健全性检查,您可以绘制插补前后连续变量的密度图。这样做可以显示插补是否扭曲了分布。Age是唯一的连续变量,所以让我们做一个前后密度图:

可视化如下所示:

图 5 —插补前后的年龄密度图(作者提供的图片)

当然,有些变化是看得见的,但总体分布大致保持不变。这个变量中有很多缺失值,所以分布的一些变化是不可避免的。

最后,您可以将插补结果分配给原始数据集,并将Deck转换为因子:

现在,您已经具备了开始预测建模所需的一切,接下来让我们开始吧。

建模

在进行建模之前,您需要将数据集分成训练和测试子集。这些从 Titanic 数据集开始就可用,但您必须手动进行分割,因为我们只使用了训练数据集。

以下代码片段以 70:30 的比例随机分割数据。如果您想要相同的分割,不要忘记将种子值设置为 42:

现在,您可以在训练集上训练模型。r 使用glm()函数来应用逻辑回归。语法与线性回归相同。你需要把目标变量放在左边,特性放在右边,用~符号分开。如果您想使用所有功能,请在前面加一个点(。)而不是功能名称。

另外,不要忘记指定family = "binomial",因为这是逻辑回归所必需的:

以下是该模型的摘要:

图 6-逻辑回归模型摘要(作者图片)

这里最有趣的是 P 值,显示在Pr(>|t|)列中。这些值表示变量对预测不重要的概率。通常使用 5%的显著性阈值,因此如果 P 值为 0.05 或更低,我们可以说它对分析不显著的可能性很低。

您还可以使用varImp()函数明确地探索特性的重要性。以下是如何获得十个最重要的特征,排序如下:

这些功能如下所示:

图 7-逻辑回归模型的特征重要性(图片由作者提供)

到目前为止,您已经构建并探索了模型,但是还没有任何用处。下一节将向您展示如何根据以前未见过的数据生成预测并评估模型。

生成预测

如引言部分所述,逻辑回归是基于概率的。如果概率大于某个阈值(通常为 0.5),您可以将此实例视为阳性。

评估机器学习模型最常见的方式是通过检查混淆矩阵。它是一个正方形矩阵,显示有多少预测是正确的(真阳性和真阴性),有多少预测是阴性但被归类为阳性(假阳性),有多少预测是阳性但被归类为阴性(假阴性)。在我们的例子中,阳性的指的是在事故中幸存的乘客。

下面的代码片段显示了如何获取概率和类别,以及如何打印混淆矩阵:

以下是相应的结果:

图 8 —逻辑回归模型的混淆矩阵(图片由作者提供)

268 条记录中有 221 条分类正确,准确率为 82.5%。假阳性 26 个,假阴性 21 个。您可以尝试使用分类阈值(现在是 0.5),看看这些错误分类是如何变化的。

这足以让你开始一般的逻辑回归和分类。让我们在下一部分总结一下。

结论

逻辑回归经常被用作基线二元分类模型。更复杂的算法(基于树的或神经网络)必须胜过它才有用。

今天,您已经学习了如何以一种易于遵循和理解的方式进行数据清理、准备和特性工程。您还学习了如何使用逻辑回归应用二元分类建模,以及如何评估分类模型。

喜欢这篇文章吗?成为 中等会员 继续无限制学习。如果你使用下面的链接,我会收到你的一部分会员费,不需要你额外付费。

https://medium.com/@radecicdario/membership

加入我的私人邮件列表,获取更多有用的见解。

原载于 2021 年 1 月 9 日【https://appsilon.com】

带 R 的机器学习:流失预测

原文:https://towardsdatascience.com/machine-learning-with-r-churn-prediction-be5d2b4dba93?source=collection_archive---------30-----------------------

R 编程语言实用指南

蒂姆·莫斯霍尔德在 Unsplash 上的照片

r 是数据科学生态系统中的主要语言之一。它主要是为统计计算和图形设计的。r 使得有效实现统计技术变得简单,因此它是机器学习任务的绝佳选择。

在本文中,我们将创建一个随机森林模型来解决一个典型的机器学习问题:流失预测。

注:如果你想阅读这篇西班牙语文章,它发表在Planeta Chatbot上。

客户流失对每个企业来说都是一个重要问题。在寻找扩大客户组合的方法的同时,企业也注重保持现有的客户。因此,了解现有客户流失(即离开)的原因至关重要。

数据集可在 Kaggle 上获得。我们将使用 r 的 randomForest 库。第一步是安装和导入库。

install.package("randomForest")
library(randomForest)

我使用 R-studio IDE,但也有其他替代方案。下一步是将数据集读入表中。

> churn <- read.table("/home/soner/Downloads/datasets/BankChurners.csv", sep = ",", header = TRUE)

某些列是冗余的,或者与另一列高度相关。因此,我们将删除 7 列。

> churn2 <- churn[-c(1,3,10,16,19,22,23)]

上面的代码根据给定的列索引列表过滤表。我们在列表前添加一个减号,表示这些列将被删除。

我写了一篇单独的文章作为这个数据集的探索性数据分析。如果你想知道为什么我们删除了一些列,我建议你读一下。

以下是剩余列的列表:

(图片由作者提供)

流失标志列是我们的目标变量,指示客户是否流失(即离开公司)。其余的列载有关于客户及其与银行的活动的信息。

下一步是将数据集分成训练和测试子集。我们首先创建一个分区,并用它来分割数据。在分割数据集之前,我们需要分解目标变量(Attrition _ Flag ),以便模型知道这是一项分类任务。

> churn2$Attrition_Flag = as.factor(churn2$Attrition_Flag)> set.seed(42)
> train <- sample(nrow(churn2), 0.8*nrow(churn2), replace = FALSE)
> train_set <- churn2[train,]
> test_set <- churn2[-train,]

我们随机选择 80%的观察值(即行)进行训练。其余的存储在测试集中。

下一步是创建一个随机森林模型并训练它。

> model_rf <- randomForest(Attrition_Flag ~ ., data = train_set, importance = TRUE)

我们创建随机森林模型并指明目标变量。波浪号(~)运算符后的点告诉模型,所有其他列都作为独立变量在训练中使用。

下面是随机森林模型的摘要:

(图片由作者提供)

默认情况下,林中使用的树的数量是 500。我们可以使用 ntree 参数来改变它。

评估的关键指标是误差率的 OOB(开箱)估计值。在详细讨论误差的 OOB 估计之前,我想简单解释一下随机森林算法是如何工作的。

随机森林使用 bootstrap 采样,这意味着通过替换从训练数据中随机选择样本。每个引导样本包含来自整个数据集的随机样本。不在 bootstrap 样本中的观察值称为袋外数据。为了获得模型的无偏和更准确的评估,使用了袋外误差。

OOB 误差率为 5.33%,这意味着模型的准确度约为 95%。

混淆矩阵也是评估分类模型的重要工具。它显示了每个类别中正确和错误预测的数量。

为了在测试集上评估模型,我们首先进行预测。

> predTest <- predict(model_rf, test_set, type = "class")> mean(predTest == test_set$Attrition_Flag)  

[1] 0.9343534

我们比较预测值和测试集的目标变量(Attrition _ Flag ),并取平均值。该模型在测试集上的分类准确率为 93.4%,略低于在训练集上的准确率。

我们还可以在测试集上生成预测的混淆矩阵。

测试集上的混淆矩阵(图片由作者提供)

与现有客户相比,该模型在预测流失客户(即流失客户)方面表现不佳。这个问题的主要原因是阶级分布不平衡。搅动的客户数量比现有客户数量少得多。克服这个问题的一个方法是使用上采样来增加流失客户类中的观察数量。

超参数调整是模型建立的重要组成部分,尤其是对于复杂模型。例如,改变随机森林中的树的数量或单棵树的最大深度被认为是超参数调整。

超参数调优需要对算法的超参数有全面的了解。仅仅尝试随机值是没有效率的。

结论

我们已经介绍了 R 编程语言中的 randomForest 库。语法相当简单,模型评估工具非常直观。

Python 和 R 是数据科学和机器学习中最常用的两种编程语言。他们都有丰富的库和框架可供选择,这使得数据科学家和机器学习工程师的生活更加轻松。

我不认为在数据科学相关的任务方面,一个比另一个优越。我建议两者都学,以便有利于两者的一些特色。

感谢您的阅读。如果您有任何反馈,请告诉我。

研究科学家的机器学习工作流程

原文:https://towardsdatascience.com/machine-learning-workflow-for-research-scientists-fb582538aac1?source=collection_archive---------50-----------------------

实践教程

协作式机器学习开发入门的简单设置。

活动创作者Unsplash 上拍摄的照片

这个维基是给谁的?

Python 和 Github 工作流教程的列表很长。也有很多机器学习教程。但是没有一个容易遵循的机器学习-ML 云服务-本地开发-标杆工作流程。我将谈论三个免费服务,任何人都可以通过基本的互联网接入使用——Google co laboratory(ML 云服务), VS Code(本地 ML 开发),以及 Weights and Biases(基准测试)。TL;DR-这是一个作为研究者部署你的 ML 模型的过程指南!

你学不会什么?

如何用 Python 编码或开发机器学习模型或学习 Pytorch。

你会学到什么?

  • 如何为结构良好的项目贡献代码
  • 使用多个 Google 协作笔记本
  • 创建简单的 Python 文档
  • 随着您的项目和团队的复杂性和规模的增长而扩展
  • 基准和项目跟踪

机器学习环境设置

谷歌联合实验室

机器学习最简单的入门方法(免费!)正在使用 Colab 。让我们来看看最简单的开箱即用的设置,让你开始。

  1. 将您的 Google 帐户链接到存储笔记本。
  2. 设置存储。
  • 添加文件可以很容易地通过笔记本左窗格的 Colab 用户界面完成,方法是点击文件夹图标,然后点击上传符号。但是,如果您的实例超时,这很容易发生,这取决于您的网络、RAM 使用情况、您使用的是 Colab Pro 还是免费版本,您可能更喜欢一个更永久的解决方案。
  • 永久的解决方案是使用你的 Google Drive 来存放你的文件,尤其是较大的数据集。有很多方法可以将 Colab 连接到 AWS 之类的外部数据存储。然而,对于大多数研究目的和较小的项目,Google Drive 方法工作得很好。您可以在数据存储连接查看其他方法。现在让我们来看看 Google Drive 的挂载方法(参考)

安装 Google Drive 并将数据集传输到 Colab 笔记本电脑,以大幅加速

这里,我们使用前两个命令挂载驱动器。接下来是加速训练,我们将实际数据从驱动器传输到 Colab 笔记本。在这里,我们首先将数据集存储为一个 zip 文件。每次重新连接 Colab 实例时,我们都需要重新运行这些命令,但是这可以大大加快训练和数据管理的速度。

在 Colab 中使用 pip 安装 Python 包

简单明了,大多数软件包都应该开箱即用。您可以从开始运行其他系统命令!(感叹号)也是。

如果你有一个真正强大的机器,或者如果你只是喜欢在本地运行你的文件,我推荐使用 VS 代码。它不仅是开源的,而且有强大的扩展来模拟笔记本、代码完成和大量 python 专用工具。我最推荐的扩展是(排名不分先后):

  • Python for VSCode(语法)
  • Visual Studio IntelliCode(用于笔记本电脑)
  • Pylance(超级巨蟒)
  • 代码运行器(轻松运行代码片段)

您需要安装 python3 和 pip3。

使用 pip loc 安装您的软件包

Git、Github 和桌面管理

使用 Git 的标准方式是通过终端。另一种方法是在 Github 桌面使用 Github 的官方应用。它支持最常见的操作系统发行版。

这里有一些简单且无错误的协作标准方法(针对本地文件)注:改编自科研人员的R

从远程库设置本地库

  1. 初始化您的远程仓库

首先分叉上游存储库。接下来访问您的远程 fork 的 url 并克隆它,并将这个远程 url 设置为将更改推送到的源。最后,将原始存储库(您克隆的存储库)设置为您的上游。

设置您的远程资料库

2.在开始编码之前

总是、总是和总是从上游(父)存储库中获取任何更改。否则,您在本地进行的更改可能会在合并时产生问题(将您的代码推向上游)。

在开始本地工作之前,用对父存储库所做的更改来更新您的本地存储库

3.添加新功能

创建一个新分支来编码一个新特征,避免破坏主分支

4.用修正防止微小的错误

确保您的源代码也与 dropbox 等云服务同步,或者您正在使用 Colab。这确保您不会因为未保存或电源故障而丢失数据。

修正而不是做出小的改变

5.在重新设定特征分支的基础之前,合并上游变更

通过将新功能提交重新设置到主分支的顶部来合并新功能

如果您遇到问题,请使用以下链接进一步排除故障,故障排除或谷歌查看 StackOverflow

  1. 在 GitHub 上创建一个资源库,或者决定使用现有的资源库
  2. 转到您的 Colab 文件
  3. 接下来,选择文件- >在 GitHub 中保存一份副本
  4. 授权您的 GitHub 帐户并选择适当的存储库,添加提交消息并按 OK!
  5. 要使用版本控制,对代码进行更改并重复步骤(2)-(4)

长期选择

Colab 提供了将源代码下载到计算机的选项。可以去文件- >下载。ipynb文件- >下载。py 并将笔记本存储为本地笔记本或转换为 python 文件。接下来,您可以使用本地 Git 方式来维护版本控制。然而,要访问 Colab 中的文件,您必须使用 Colab 中的 File- > Open Notebook 选项将文件重新加载到 Colab。

单元测试

用 python 创建单元测试最简单的方法是使用模块 unittest 。让我们看一个简单的例子(来自 GeeksforGeeks

Python 中的示例单元测试示例

上面的例子不言自明。它测试了两个简单的函数——将一个字符串乘以 4 次,并将一个字符串转换成大写。这些测试对于确定性函数非常有用。然而,为梯度下降创建这样的测试可能并不容易。然而,如果我们知道函数输出的可能界限,我们可以创建函数来测试它们。一个简单的 ML 测试库确实可用于 T ensorFlow(在 TF 2.0 中已废弃)PyTorch 。unittest 可以很好地用于定义类似于 PyTorch 代码审查中展示的东西。

这些库检查以下项目:

  • 变量是否会改变
  • 如果某些变量是固定的,那么它们在迭代中保持固定吗
  • 输出值是否合理(即在一定范围内)?
  • 模型是否连接良好(即所有输入都有助于训练操作)?

证明文件

维护文档很难。获得自动化文档的最简单方法(不推荐,看看 我如何判断文档质量? ) 正在使用 pdoc 模块。让我们开始安装和维护。

使用以下命令为 python-3 安装 pdoc

用 pip 安装 pdoc

为了自动化文档创建,我们需要使用 Google docstrings 格式添加注释。让我们来看一个用于将两个数字相加的函数的快速示例(存储在文件 Test_Example.py 中)

添加两个数字演示 Google 文档字符串的简单示例

现在,为了输出 html 文件中的文档,我们将使用下面的命令。

使用 pdoc 为单个 Python 文件创建文档

这里的 Test_Example.py 是源代码。输出目录参数为 wiki 提供了存储 html 文件的位置。文档如下所示。但是,该命令对无效。ipynb 文件。创建文档的最佳方式是下载。然后使用 pdoc 命令。将笔记本转换为 python 文件的另一种方法是使用命令。

轻松地将您的 IPython 笔记本转换为 Python 文件

此外,要为整个 python 源代码文件夹创建文档,我们可以使用下面的 pdoc 命令。为了输出 html 文件中的文档,我们将使用以下命令。

使用 pdoc 创建 Python 项目的文档(文件夹)

这里, src-folder 是存放 Python 源代码的文件夹。

标杆管理

ML 系统非常容易变得超级复杂。您必须跟踪项目、这些项目中的实验、每个实验中的度量、每个度量集合的超参数等等。此外,多次实验运行会降低实验阶段的速度,并使跟踪结果变得更加困难。最近,ML 系统得到了很好的升级。现在,用户可以把所有超级有趣的东西放到一个看起来很酷的仪表盘上。输入 重量和偏差 。你不仅可以获得一个免费的学术帐户,还可以邀请一个团队进行协作!尤其是当你从事研究和/或开源的时候。weights and bias(WANDB)可让您轻松控制数据、存储多次实验结果并比较结果!

让我们看看让 WANDB 在您的项目上运行的最简单的方法。在 wandb.ai 上创建项目后,您可以找到类似的代码设置。

通过安装 wandb 模块并登录您的帐户,初始化您的权重和偏差项目

样本权重和偏差代码,用于跟踪数据集、模型超参数和指标

把所有的放在一起

工作流程

机器学习研究项目的标准化工作流程[图片由作者提供]

对 ML 项目中良好合作的整个工作流程的概述。

Colab 和 VS 代码入门超级简单。然而,为了避免长期项目和合作的麻烦,最好在早期建立合理的实践。希望遵循这个指南和这里的许多参考资料能给你必要的安心。代码打开!

参考

[1] N. Brewer,“RStudio 中的出版物”,2020 年 3 月 10 日。https://nicole-brewer.com/r-for-research-scientists/(2021 年 2 月 6 日访问)。

最初发布于 ML 科研人员工作流程(thehimalayanleo.github.io)

使用生成性对抗网络的机器艺术

原文:https://towardsdatascience.com/machine-made-art-using-generative-adversarial-networks-35faa41a4feb?source=collection_archive---------26-----------------------

以数据为中心的绘画方法

算法还是艺术家——有区别吗?(本文所有图片均为作者)

简介

在我看来,过去几年机器学习社区所做的大部分研究工作都过于狭隘。研究人员采用已知的样本数据集,花数年时间在这些数据集上训练模型,并发表论文,对每个项目中最先进的基准进行边际改进。对于那些来自机器学习社区的读者来说,想想你多久会看到一次对 CIFAR、MNIST、LibriVox、ImageNet、IMDB 评论或维基百科语料库的提及;这些数据集用得太频繁了。我们没有看到对原始数据进行足够的研究。

背后有一个很好的理由:在比较新的机器学习模型时,我们需要一些共同的数据来与现有的模型进行比较。基准数据集使之变得简单。没有它们,这就像拿苹果和橘子做比较。但是在相同的旧数据集上加入超越最先进性能的竞赛只是无聊的。我总是喜欢把时间花在更具原创性的工作上。

最近在机器学习领域变得日益突出的一个主题是以数据为中心的人工智能。与上面详述的方法相反,在该方法中,我们努力在同一数据集上创建更好的模型,我们用更好的数据训练现有模型,以增加它们的推理或生成能力。教学中的类比是,假设大多数人有相似的学习能力,更好的例子和更好的解释会导致对问题陈述以及如何解决它的更好理解。

以数据为中心的人工智能非常适合生成模型。当训练模型以在输出领域(例如,音频、视频、图像……)中创建新样本时,训练数据对推理期间的结果输出有显著影响。一旦研究人员发布了一个新的模型,我们就可以将相同的设计初始化为一张白纸(或者做一些迁移学习,对于那些熟悉这个过程的人来说),并用我们自己的数据训练它,以获得我们自己的结果。

在我环游世界期间,我有时间拍了许多照片。看着它们让我想到也许可以画出一些和它们相似的画。浏览技术文献,我发现最近的一篇研究论文 (2019)可能胜任这项工作。这篇题为“通过变换向量学习进行图像到图像的翻译”的论文描述了一种实现这一点的方法。使用论文中提出的模型,我希望以数据为中心的方法可以用来训练他们的模型根据我在日本旅行时拍摄的照片绘制水彩画。

行程

那么,到底什么是变换向量学习(简称 TraVeL)?2014 年,一位名为 Ian Goodfellow 的研究人员开创了一项名为生成对抗网络(GANs)的技术。当时,机器学习模型在分类任务上取得了稳步的进步,但在生成内容方面仍然非常有限。GANs 从一个新的角度处理内容生成问题:我们不是训练单个神经网络来生成内容,而是一起训练两个网络来解决问题。

第一个网络被称为“生成器”,它被训练为基于来自明确定义的输入域的样本(例如,弗兰克·辛纳特拉(Frank Sinatra)的录音、浣熊的照片、随机初始化的噪声向量等)来创建所需的内容。第二个网络称为“鉴别器”,作为来自输出域的样本的分类器,并试图确定给定的输入是否是输出域的真正成员。这两个网络并肩训练,互相促进。更好的鉴别器可以更好地区分输出域中的真实样本和生成器生成的人工样本。这反过来迫使生成器输出与输出域中的真实样本更相似的内容,以成功欺骗鉴别器。

为了提取由鉴别器学习的知识并使用它来改进生成器,我们从鉴别器损失函数反向传播并更新生成器中存在的权重张量。这导致两个网络竞争的反馈回路:较低的鉴频器损耗导致较高的发电机损耗,反之亦然。我们让它们相互竞争,以便它们可以达到一种平衡,根据它们的竞争性质将它们命名为“敌对网络”。

风格转移 GAN 的基本设计:黑色箭头表示哪个样品被输送到哪里;彩色箭头表示反向传播。

给定来自输入空间的样本,可以训练生成器在输出空间中创建样本。然而,即使给定随机噪声作为输入,它们也可以被训练成产生真实的样本。为了执行风格转换(如将照片转换为绘画),我们希望在输出样本中保留输入样本的一些内容。使用像素差分损失函数(均方误差)的天真尝试已经产生了一些初始增益,但是当输入和输出域彼此更加不同时,这些尝试无法推广。

让我们问问自己为什么会发生这种情况:请注意,最小化图像之间的像素差异与最小化像素之间的欧几里德距离是相同的,就索引而言。将逐像素损失形式化,设 x 为输入空间 x ∈ MxNx3 中的样本。我们希望生成器学习一个函数 g,在相同维数的输出空间中产生样本:G(x) ∈ MxNx3。将每个像素视为向量 p ∈ ℝ,我们在输入和输出图像中迭代相同的索引。对于每个索引[m,n] | 1≤m≤M,1≤n≤N,我们比较两幅图像中该索引处的像素。设 p₁ = x[m,n],设 p₂ = G(x)[m,n]。像素之间的平方差是 L(p₁,p₂) =(p₁-p₂) = (p₁-p₂) ⊗ (p₁-p₂),其中⊗是两个向量之间的元素乘积,l 是度量函数 L:ℝ xℝ ⟶ℝ.像素方面的损失只是所有平方差的平均值。

当源图像和生成的图像相同时,均方误差(MSE)被最小化。这导致了一些问题:具有完美 MSE 分数的输出样本将很容易被鉴别器归类为人工样本,仅仅因为它不属于输出域。MSE 对平移、旋转、倾斜和变换也非常敏感;即使具有低 MSE 损失的样本,简单的水平翻转也会显著增加其 MSE 值,这仅仅是因为该度量被计算为图像之间的像素分数。最后,MSE 对输入和输出样本的像素进行平均,以计算损失。平均技术通常不能获得高质量的样品。在某种程度上,这也是有意义的:我们不想优化网络以收敛到从训练集平均的样本,而是基于训练集中样本中存在的变化来创建许多独特的样本。

TraVeL 通过训练生成器学习使不同损失函数最小化的函数 G 来解决图像风格转移的问题。我们不是最小化图像空间 RMxNx3 中像素之间的距离,而是要检查输出空间中保留的更高级别特征,并最小化与输入空间中相同特征的差异。然而,我们不知道如何跟踪图像空间中的高级特征,更不用说一旦它们被生成函数 g 变换,我们如何处理这个问题?

从研究人员的角度来看,他们必须试验和尝试一些东西。他们试图保持一个合适的不变量:不变量是物体的一个属性,即使对它们施加一个函数,它也不会改变。形式上,设 v 和 w 是某种空间,设 f: V⟶W 是从 v 到 w 的函数映射,一个度量 l 是 f 的不变量如果对每个 x ∈ V,f(x) ∈ W,L(x) = L(f(x))。

角度是比例的不变量。在这个例子中,两个向量 v1、v2 按恒定量缩放,但是角度θ保持不变

他们希望通过教导生成器网络保持函数 G 的适当不变量,该函数将在输出空间内保留来自输入空间的一些高级特征。然而,将距离或角度等较低级别的度量保持为不变量无助于解决该任务,因为就像 MSE 度量的情况一样,只有当 g 是恒等式变换(即,x = G(x) ∀x ∈ V ⇔ L(x,G(x)) = 0 ∀x ∈ V)时,才能实现来自生成器模型的完美损失值。知道了这一点,我们训练生成器网络保持哪个不变度量?

幸运的是,他们想起了一种首先在自然语言处理领域使用的技术,叫做潜在空间编码。当把 v 看作向量空间时,任何子空间 V* ⊂ V 都可以看作 v 的潜在空间。潜在空间对我们有用有两个原因:由于 v 和 V*之间的映射函数的性质,以及由于它们内部向量之间的关系。

相同大小的图像可以被视为称为图像空间的向量空间内的向量。设 v 是一个向量空间,使得 V ~ MxNx3。v 可以由 NxMx3 个标准基向量跨越,每个基向量表示空间中存在的图像向量内的单个子像素。这意味着每个图像是跨越图像空间 V 的子像素的线性组合,但也意味着它们是线性独立的:每个基向量只编码一个子像素,在同一图像的子像素之间没有任何关系。

如果我们可以“压缩”这种表示,我们就可以在每幅图像的组成部分之间建立一种关系。我们可以使用映射 S: V ⟶ V*将图像映射到 v 的任何子空间,允许我们在该子空间内使用较小的基跨越相同的图像,在潜在空间中的每个基向量和原始空间中的图像之间建立一对多关系。这种映射也可以看作是“丢弃”,因为根据定义,任何到更小维度的子空间的映射都会丢失嵌入在该子空间内的向量的信息。

寻找这种转换的方法已经知道几十年了,其中最著名的是主成分分析。在认识到可以使用基于梯度的方法(如神经网络)对潜在空间进行编码之后,自然语言处理领域的最新研究应运而生。不要苦干多年试图找到一个直接的映射来最小化一个任意的度量,而是使用一个由神经网络学习的非线性函数,在相同的度量上进行优化。

因为我们可以学习优化任何度量的映射,所以我们可以明确地学习在潜在空间内优化度量的映射。例如,选择两幅图像 x₁,x₂ ∈ V,x₁ - x₂之间的差异只是图像之间的像素差异。但是因为映射 s 丢弃了关于图像的信息,差异 S(x₁) - S(x₂)意味着完全不同的东西。潜在空间 V*的维度越小,我们丢弃的信息越多,保留的信息越有意义。当然,丢弃大部分或所有信息会产生无意义的潜在空间编码,我们永远无法提前知道哪些特征将被学习(因为神经网络通常是不可解释的,我们无法提前计划它将向哪个最小值收敛)。但是根据经验,我们丢弃的信息越多,我们在潜在空间中保留的特征水平就越高。

有了这些知识,我们可以训练发电机网络来优化 g,同时添加一个第三个网络来优化 s。我们训练 g 保持的不变量是 l(s(x₁)-s(x₂))=l(s∘g(x₁)-s∘g(x₂)).向量 S(x₁) - S(x₂)被命名为 S(x₁)和 S(x₂)之间的变换向量,因此有术语变换向量学习。度量 L 同样被称为行程度量。

TraVeLGAN 在标准设计中增加了第三个网络,用于将行程度量保持为不变量

型号

我承认在编写这个模型的代码时偏离了最初的设计。论文中的规范要求一个三部分模型,每一部分都试图优化一个不同的损失函数。一台发电机,试图画出这些画;一个鉴别器,试图区分真实的绘画和人工的绘画,以及一个编码器网络,试图将行程度量保持为生成器函数的不变量。

对模型内部的深入研究可能值得在某一天发表一篇文章,但从鸟瞰的角度来看,它可以描述如下:鉴别器网络是由五个卷积层组成的完全卷积网络,每层都有两倍于前一层的滤波器。然后,输出被展平并通过完全连接的层,产生单个 logit,基于我们将进一步描述的损失函数来决定样本是原始的还是人造的。编码器网络具有相同的设计,除了全连接层输出图像在潜在空间内的嵌入(矢量,而不是鉴别器的单个 logit)。该生成器使用一种众所周知的设计,称为 U-Net,本质上是一种美化的卷积自动编码器,图像通过连续的卷积和池层向下传递,然后以相反的顺序通过相同的因子进行放大。该设计非常擅长学习卷积核的较低级和较高级特征图,并使用剩余链接来防止在产生输出图像时“忘记”在模型中较早提取的特征。

以上是您可能称之为 GAN 的“标准设计”(另外还有编码器网络),但如果您是 GANs 新手,想要更好地理解,有许多很好的资料可以详细解释其内部工作原理。然而,我确实希望更详细地讨论设计的两个方面:损失函数和反向传播。

损失

TraVeLGAN 尝试优化三种不同的损失项。第一个是用于 GAN 鉴别器的“标准损失”:二元交叉熵损失(在本文中也称为最小最大损失)。设 G: RMxNx3 ⟶RMxNx3 是发生器学习的函数,D: RMxNx3 ⟶R 是鉴别器学习的函数。我们将极大极小损失表示为 L(adv),定义如下:

根据研究论文中的设计和调整,该模型针对不同的数据集进行了校准。当我开始训练我自己的实现时,模型不会收敛。为了解决这个问题,我决定将对抗性损失函数改为沃瑟斯坦损失函数。Wasserstein loss 计算一个称为 Wasserstein distance 的度量,它可以被视为测量两个概率分布之间的“最小”距离。它被定义为:

该公式本质上规定,我们迭代向量 x∈ ᵣ和向量 y∈ g 的所有组合,并将它们视为来自乘积分布π的随机样本(或者等价地,将每个视为来自其自身分布的随机样本)。然后,我们选择一个参数向量γ,当对 x 和 y 的所有组合求和时,它使距离||x — y||之和最小。Wasserstein 度量本身是包含最小γ的所有标量权重的总和。

虽然概率分布之间的距离度量比样本之间的距离度量更稳健,并且优化分布之间的距离的 GANs 在历史上比优化样本之间的距离的 GANs 达到了更好的结果,但是以上面所示的形式计算 Wasserstein 距离是一个棘手的计算。即使当用从输入空间中选择的离散样本训练模型时,置换每个小批量运行中的 ᵣ和g 的所有可能样本也是多项式时间复杂度的——对参数化γ的每个选择重复进行。

然而,一个被称为 Kantorovich-Rubinstein 对偶的相当晦涩的定理可以用来更可行地计算 Wasserstein 距离。该定理将 Wasserstein 距离视为优化问题的解决方案。最优化问题可以表述为两种形式:要么最小化一个约束,要么最大化它的逆。将优化问题公式化为最小化问题称为问题的素形式,而将优化问题公式化为最大化问题称为问题的对偶形式。Kantorovich-Rubinstein 对偶建立并解决了 Wasserstein 距离的对偶形式,提供了一个更简单的方程来测量它。在对偶形式中,它可以表示为:

在我们问题的上下文中, ᵣ被表示为 D(x)而g 被表示为 D∘G(x).假设梯度下降过程使 D 收敛到最优函数 f,我们可以将 Wasserstein 损失改写为:

这个解决方案带有一个警告:为了保持结果,生成 ᵣ和 g 的函数必须满足一个称为李普希茨连续性的约束(具体来说,就是 1-李普希茨连续性)。因为t20】g 中的图像是由 g 生成并由 d 分类的,所以 g 和 d 都必须是 Lipschitz 连续的。根据 Lipschitz 连续性的公式,如果存在某个常数 k,则函数 f: ℝ⟶ℝ是 K-Lipschitz 连续的,该常数满足:

率先使用 Wasserstein 距离作为 GANs 损失度量的研究人员努力在他们的模型上实施 Lipschitz 约束,尝试梯度裁剪等方法,这些方法严重限制了他们模型的学习能力。然而,最近关于归一化方法的见解提出了一种解决方案,即使用一种称为频谱归一化的技术。谱范数是非标准矩阵范数,可与给定矩阵的所有标量项上的元素式 L₂范数相比。可以证明,对于任何矩阵 W,W 的谱范数等于 W 的最大奇异值,表示σ(w):

频谱归一化就是使用矩阵的频谱范数对矩阵进行归一化的操作:

根据该见解,可以通过对 G 和 d 层中的所有权重矩阵进行频谱归一化来建立 Lipschitz 连续性。此外,可以使用一种称为“幂迭代”的技术来计算频谱范数的快速近似。该技术利用了 W 的特征向量的特性,确保收敛到谱范数本身(即,在训练时段上逼近真实范数)。通过在每个小批量训练后对模型的权重执行光谱归一化,Lipschitz 连续性得到加强,允许我们使用其对偶形式来计算 Wasserstein 度量。

第二个损失项在机器学习文献中被称为裕度对比损失,并与潜在空间编码器一起使用,以确保它们不会退化到学习零函数(即,f(x) = 0 ∀x).)我们选择常数δ代表潜在空间中向量之间的最小距离,对于每一对向量 S(x₁、S(x₂,我们计算以下损失项:

注意术语 S(x₁) - S(x₂)是 S(x₁)和 S(x₂).)之间的转换向量将向量表示为 v,我们可以将上面的项重写为:

如果距离大于或等于δ,则 S(x1)的损耗,S(x2)等于 0。否则,边际对比损失将增加附加值(对于每对向量高达δ),在此过程中不利于编码器网络。这个损失函数也被称为连体损失,因为它在来自小批量的向量对上迭代。我们将暹罗损失表示为 L s ,并将其公式化为:

第三个也是最后一个损耗项称为行程损耗,与我们在上一节中讨论的不变度量相同。表示为 LTraVeL,原始公式允许使用任何距离度量。我选择了余弦距离和欧几里德距离的组合,学习保持角度和长度。与暹罗损失一样,我们对每对向量的损失项求和,公式如下:

繁殖

在标准 GAN 设计中,损耗函数由发生器和鉴频器共享。当对来自输出域的样本进行分类时,鉴别器试图最小化其损失函数,而生成器试图最大化相同的损失(或者等效地,最小化否定的损失)。

在 GAN 中执行反向传播时,两个网络相互连接,这意味着鉴频器的梯度会反向传播到发生器。在形式上,我们可以把 G 看作是各个层函数的组合。设 G L 为发电机组成的层数,设 Gᵢ为 g 内的 I 层(1≤i≤ G L )。g 可以改写为:

以类似的方式看 d,我们可以把 D∘G 改写为:

利用鉴频器损耗,通过标准程序完成通过鉴频器层的反向传播。当通过发生器传播时,我们必须首先计算鉴别器的梯度,但是是相对于负损耗。表示鉴别器损耗 L D 和发电机损耗 L G ,我们可以使用导数的链式法则来计算给定发电机层 Gᵢ:的损耗

然后,我们跳过鉴别器层的梯度(我们应用 w.r.t. L D ,而不是 w . r . t . LG),只对生成器权重矩阵应用生成器层梯度。

发生器(黄色)和鉴别器(蓝色)层的渐变更新细节。虚线箭头显示如何计算每个渐变,以及何时应用每个渐变。

编码器网络经历类似于鉴别器的过程。然而,因为生成器需要根据编码器函数 S 计算的损失来优化 G,所以我们需要在每个时期对生成器权重执行第二次更新。类似地表示这些术语,我们得到:

渐变更新的完整方案,也包括编码器渐变(绿色)。

因此,我们对每个小批量的生成器应用两个梯度更新。从几何角度可视化梯度向量,梯度下降过程采用朝向分类梯度的最小值的下降和不变性梯度的最小值之间的平均路径。为了坚持梯度下降过程的学习速率,通常将梯度除以 2(即,计算平均梯度),这也是深度学习编码框架(TensorFlow、PyTorch 等)的默认行为。

表示为矢量相加的生成器层的梯度: ∂Gi 是应用于层 Gi 的两个梯度的总和。

数据

使用监督学习来训练对抗网络。也就是说,我们需要提供源域和目标域的数据以及标签来计算分类损失。因为我们使用的是 GAN 架构,所以标签是由模型本身提供的(我们知道将哪些图像提供给鉴别器,因此我们可以提供匹配的标签)。然而,图像必须事先收集。

因为我想把我的照片转换成水彩画,所以我必须收集风景照片和油画。为此,我构建了两个网络爬虫,扫描选定的网站寻找匹配的图片。第一个网络爬虫扫描了一个名为 Flickr 的网站,该网站有许多高分辨率的风景照片可供下载。第二个网络爬虫扫描了一个名为浮世绘数据库的网站,该网站保存了过去三个世纪中超过 20 万张日本木刻版画的扫描图。在对两个爬虫进行了一些优化之后,我从每个域收集了 10k 个图像,并将其保存到我的云存储中。

每个图像都被归一化到(-1,1)范围。由于水彩印刷品的扫描问题(其中许多都有注释、边框、伪像、网格线和其他不需要的元素),我确定每个图像的中心将出现最少的干扰(根据经验)。因此,我裁剪了每张图像,在中心保留 256x256 像素,并丢弃其余的像素。然后将这些图像分组,每组 32 张。

训练

使用 Google Collaboratory 在可用的 GPU 上部署了该模型的四个不同实例(我通常被分配到特斯拉 P100 GPU)。冗余部署背后的原因是,初始实验表明,基于初始权重的随机选择,模型倾向于收敛于随机局部最小值。这些最小值在它们所代表的调色板中是稳定的,但是大多数调色板是完全关闭的,导致输出域图像的非自然颜色。在 30 个时期之后,当调色板稳定时,仅保留两个最佳模型,并训练总共 100 个时期。

经过训练后,从我的私人相册中收集了一个小测试集的图像,用于判断生成器输出的绘画质量。每张图片都被切成 256x256 像素的正方形。这些方块被一起分批,并作为生成器的输入。输出被重新组合,在输出域中产生新的连续图像。

样本绘画,由生成器制作

在最初的测试中,在正方形小块之间的边界周围出现了许多伪像,导致小块之间出现可见的网格分割。使用两种方法来校正该效果:围绕中心裁剪训练集图像,以及对发生器进行小的修改。作为输入提供给生成器的每个图像被分成四个小块,并且输出小块在被馈送给鉴别器之前以相同的顺序连接。鉴别器学会了将这些图像归类为人工样本,从而教会生成器在某种程度上纠正补片之间的不连续性。

结果

这两个网络可以比作不同的艺术家,每一个都有略微不同的风格。“最佳”网络(最忠实于输入域的颜色方案)最终绘制出非常精确的图像。“第二好的”是画出同样精确的画,但是调色板更强调红色和粉色。

:第一次网络输出,“标准”调色板。:第二网络输出,“红色”调色板。

当从与输入域相匹配的分布中获取照片时,两个网络都能生成非常精确的水彩画。那就是——风景图片和静态自然图片(远景、植物、树木等等)。当输入来自不同分布(动物、人、建筑物等)的照片时,结果不太准确,并且网络不能消除图像块之间的边界伪影。这种行为是意料之中的,因为网络是在风景图像的数据集上训练的,主题与目标领域的水彩画相似。从某种意义上来说,这就像让伦勃朗再造杰森·布拉克的艺术一样——可以做出一幅画,但很可能没有人会喜欢它。

最终,我选择了新京桥的照片。它横跨流经日本北部日光镇的河流,被认为是日本已建桥梁的最佳范例之一。红色的桥、蓝色的河和周围绿色的森林之间的鲜明对比被模型漂亮地捕捉到了;用简单的笔触描绘,仍然保留了原画中许多复杂的细节。

Shinkyo 桥,输出覆盖在原始输入之上。请注意对原始配色方案的保真度,以及为模拟输出域的样式所做的更改。

这张照片印在尺寸为 188x110 厘米的日本 Washi 纸上,看起来像是将木刻压在一张传统日本纸上的艺术。俗话说,情人眼里出西施。但如果我可以自夸的话,这是我迄今为止制作的最好的艺术品之一。

自豪地展示!

代号

用于训练网络的代码和数据可从以下链接获得:https://drive . Google . com/drive/folders/1 smqebd 7 huzooxb 5k xmhtf 1 ldajwofwnb

机器翻译

原文:https://towardsdatascience.com/machine-translation-b0f0dbcef47c?source=collection_archive---------28-----------------------

统计机器翻译——SMT 和神经机器翻译——NMT:带和不带注意机制的编码器-解码器结构和最先进的转换器架构。

照片由张诗钟·戈伦德Unsplash 拍摄

机器翻译在当今数字化和全球化的世界中发挥着至关重要的作用。它通过处理和翻译一种自然语言为另一种自然语言造福社会。随着技术的进步,不同地区使用不同的语言交流着大量的信息。这使得对机器翻译的需求在过去几十年里呈指数级增长。正因为如此,在过去的几年里,机器翻译已经成为一个活跃的研究领域。它可以分为三种不同的方法:基于规则的方法、统计方法和神经方法。在本文中,我将主要关注统计和神经方法。

图 1:不同的机器翻译方法及其时间表。

介绍

机器翻译是将一种语言(源语言)的句子翻译成另一种语言(目标语言)的句子的任务。它是计算语言学的子领域,旨在利用计算设备自动将文本从一种语言翻译成另一种语言。机器翻译研究始于 20 世纪 50 年代初(冷战时期)。在此期间,需要将俄语文档翻译成英语。由于俄语专家不多,翻译又很费时间,所以机器翻译是有针对性的应用。当时开发的系统大多是基于规则的,使用双语词典将俄语单词映射到其英语对应单词。尽管效果不太好,但在 20 世纪 80 年代末,它让位于基于统计的系统。在 20 世纪 90 年代,基于统计单词和短语的方法变得流行起来,这种方法几乎不需要语言信息。统计机器翻译(SMT)的核心思想是从数据中学习概率模型。在 2010 年代,随着深度神经网络的出现,神经机器翻译成为一个主要的研究领域。NMT 是一种使用深度神经网络进行机器翻译的方法。神经架构被称为序列对序列(seq2seq)。普通的 seq2seq NMT 包括两个递归神经网络(RNN) [1]。NMT 的研究开创了自然语言处理(NLP)的许多最新创新,研究人员发现了香草 seq2seq 的许多改进,其中一个主要改进是注意力机制的使用[2]。受注意力机制的启发,论文“注意力是你所需要的全部”介绍了一种称为 Transformer 的新颖架构,这是目前最先进的语言模型[3]。这种架构完全依赖于注意力机制,没有任何 RNN,其变体如 BERT 已经应用于许多 NLP 任务,并能够实现最先进的性能。

统计机器翻译

统计机器翻译(SMT)从数据中学习概率模型。假设如果我们从德语翻译成英语,我们想要找到最好的英语句子 y,给定德语句子 x。SMT 将制定任务如下:

意思是在所有可能的 y 中,我们要找到最好的一个。通过使用贝叶斯规则,我们可以将上面的公式转换成下面的公式:

P(x|y)被称为翻译模型,它使用并行数据来模拟单词和短语应该如何翻译。并行数据的一个例子是成对的人工翻译的德语-英语句子。P(x|y)被进一步分解成 P(x,a|y ),其中 a 是单词对齐,即源句子 x 和目标句子 y 之间的单词级和短语级对应

P(y)被称为语言模型,它使用单语数据来模拟在一种语言中生成字符串的概率。语言模型是一个函数,它对从词汇序列中提取的字符串进行概率度量。给定长度为 n 的字符串 y,我们可以将语言模型概率 P(y)推导为:

然而,给定一个词的整个历史来计算它的概率是低效的,我们可以通过使用 n-gram 模型来近似它。在 n-gram 模型中,它作出马尔可夫假设,即 yᵢ将只依赖于前面的 n-1 个单词。

二元模型示例

为了计算 argmax,我们可以枚举每个可能的翻译 y 并计算概率,然而,这在计算上是昂贵的。因此,它使用解码,一种启发式搜索算法,通过删除低概率的假设来搜索最佳翻译。这是 SMT 工作原理的一个简要概述。最好的 SMT 系统极其复杂,许多重要的细节没有在这里讨论。SMT 的开发既昂贵又耗时,因为它需要大量的功能工程和人力来维护。[4]

神经机器翻译

深度神经网络已经在各种应用中实现了最先进的性能。沿着使用神经网络进行 SMT 的研究路线,神经机器翻译(NMT)成为主要的研究领域。它使用单个端到端神经网络架构,称为序列到序列(seq2seq ),涉及两个 RNN:编码器 RNN 和解码器 RNN。编码器 RNN 将使用一个编码向量对源序列进行汇总,解码器 RNN 将根据先前的编码向量生成目标句子。seq2seq 模型是一个条件语言模型,直接计算 P(y|x) ,因为解码器 RNN 是通过对源句子 x 进行条件化来预测目标句子 y 的下一个单词,seq2seq 模型还可以用于许多其他自然语言处理任务,如摘要、对话聊天机器人等。

序列间(Seq2Seq)

在如图 2 所示的标准 seq2seq 中,编码器 RNN(蓝色块)分析源语言中的输入句子,并使用称为隐藏状态向量的历史向量对输入序列进行编码。最后的隐藏状态或编码向量被传递给解码器 RNN(红色块)作为初始隐藏状态。解码器初始隐藏状态与源语句的一起将生成一个隐藏状态,然后传递给线性层。

图 2:NMT——一个将序列 A B C D 翻译成 X Y Z 的堆叠 RNN seq2seq 模型是句尾。[2]

Softmax 后面的线性层将输出目标语言的整个词汇的概率分布。根据该概率分布,它将选择具有最高概率的记号作为第一个字,即 X,并且它将被用作解码的第二输入。来自前一步骤的第二隐藏状态和第一生成的字 X 将被输入到解码器 RNN 的第二步骤。并且将重复相同的过程,直到它产生一个令牌。从解码器 RNN 生成的令牌序列将是 seq2seq 模型的结果。[1]

与 SMT 相比,NMT 的优势在于它具有更好的性能,并且需要更少的人力。但是,它的可解释性较差,很难调试,也很难控制。

Seq2Seq 注意

如前所述,在标准 seq2seq 模型中,编码器 RNN 的最后隐藏状态被用作解码器 RNN 的初始状态,这意味着关于源句子的所有信息将被编码为单个向量,并且它是来自源句子的唯一信息来解码目标句子。因此,编码器 RNN 的最后一个隐藏状态可以成为信息瓶颈,因为它必须仅用一个向量来捕获关于源句子的所有信息。注意机制已经被用来解决这个问题,在翻译过程中有选择地关注源句子的部分。核心思想是,在解码器的每一步,它都使用与编码器的直接连接来获得源序列的加权关注。图 3 展示了如何将注意力层添加到一个普通的 seq2seq 模型中。在解码过程中的每个时间步长 t,注意力层将导出捕获相关源序列信息的上下文向量 cₜ,以帮助预测当前目标词 yₜ.

图 3:带有注意机制的 seq2seq。[2]

注意力分布 aₜ是通过使用当前目标隐藏状态 hₜ和编码器ℎ̅ₛ.的所有隐藏状态来计算的为了获得注意力分布,它将首先计算注意力分数,然后应用 Softmax 将分数转换为概率分布。有三种不同的方法来计算注意力分数:

通过使用这个对准向量 aₜ作为权重,可以将上下文向量 cₜ计算为所有编码器隐藏状态的加权平均值。上下文向量或注意力输出将主要包含来自获得高注意力分数的编码器的隐藏状态的信息。该上下文向量然后将与解码器的隐藏状态连接,解码器的隐藏状态然后将选择具有最高概率的目标语言标记,如在普通 seq2seq 模型中一样。有时,来自前一步骤的上下文向量可用于与通常的解码器输入一起馈入解码器。

注意机制显著地提高了 NMT 的表现,并成为 NLP 研究的关键数学结构。注意,目标序列中的每个单词只需要找到它与源序列中的几个单词的匹配。它以某种方式解决了 RNN 中的长期依赖性的限制,即目标序列中的任何单词都可以与源序列中的所有单词进行通信。此外,注意力机制提供了一些可解释性,因为网络被训练来自己学习软对齐,并且我们可以通过检查注意力分布来看到解码器正在关注什么。

在机器翻译任务中仍然存在许多困难,例如词汇表之外的问题、训练和测试数据之间的领域不匹配、在长序列上维护上下文、标签数据不太可用的低资源语言对。

变压器

基于具有注意力的最佳性能 seq2seq 模型,论文《注意力是你所需要的全部》在 2017 年提出了一种新的架构,称为 Transformer,如图 4 所示。主要思想是基本上只使用注意力作为表示学习,因为在之前的 seq2seq 注意力模型中,证明了编码器和解码器之间的注意力在 NMT 中是至关重要的。

图 4:变压器模型架构,左侧模块是编码器,右侧模块是解码器。[3]

我将从《变形金刚》中用于表征学习的自我关注的主要概念开始。考虑 Q,K,V 是单词嵌入向量。q 矩阵(查询)是序列中一个单词的向量表示,K 矩阵(键)是序列中所有单词的向量表示,V 矩阵(值)是序列中所有单词的向量表示。

代替使用单个注意函数,该论文提出使用“多头注意”来线性地投射具有不同可学习权重的 Q、K、V h 次。这提供了多个表示子空间,并允许模型关注不同的位置。

与 RNN 不同,《变形金刚》中的自我关注是顺序不变的,这意味着它不会捕捉序列信息。因此,添加了“位置编码”来使用正弦函数注入每个令牌的位置信息。这种解决方案提供了确定性的方法来合并序列信息,而不增加可学习参数的数量。

在 Transformer 编码器中,在注入位置编码后,编码器的输入嵌入将首先流经多头注意层,其输出随后将馈入前馈神经网络。在 Transformer 解码器中,有两个注意力层,称为掩蔽多头注意力和编码器-解码器注意力。通过屏蔽未来字,屏蔽多头解码器对先前生成的输出进行自我关注。编码器-解码器注意使用来自屏蔽多头的查询;编码器输出的键和值。通常,解码器输出将传递到线性层和 Softmax 函数,以获得目标令牌的概率分布。注意层和前馈层之间的每个子层具有残差连接(跳过连接),其后是层归一化,以改变输入,使每层具有均值 0 和 1。

Transformer 通过提供仅需要一次计算的成对并行化乘法交互(自关注),取代了以前的 seq2seq RNN 模型中使用的顺序计算。该架构是当前最先进的架构,提供了高性能和可解释性。

评估方法

评估机器翻译最常用的方法是双语评估替角(BLEU)。它将机器书面翻译与一个或几个人类书面翻译进行比较,并基于 n-gram(通常是 1、2、3 和 n-gram)精度计算相似性得分。BLEU 非常有用,大多数机器翻译系统都是用 BLEU 来评估的。然而,它并不完美,因为有各种方法来翻译一个句子。一个好的翻译可能会得到一个糟糕的 BLEU 分数,因为它与人类翻译的 n-gram 重叠很低。

参考

[1] K. Cho 等人,“使用统计机器翻译的 RNN 编码器-解码器学习短语表示”,em NLP 2014–2014 Conf .Empir。方法 Nat。郎。过程。继续。糖膏剂,第 1724–1734 页,2014 年。

[2] M. T. Luong、H. Pham 和 C. D. Manning,“基于注意力的神经机器翻译的有效方法”,计算语言学协会,2015 年。

[3] A. Vaswani 等人,“注意力是你所需要的一切”,2017 年。

[4] A. Garg 和 M. Agarwal,《机器翻译:一个文献综述》,2018 年。

基于 sacreBLEU 和 BERTScore 的机器翻译评估

原文:https://towardsdatascience.com/machine-translation-evaluation-with-sacrebleu-and-bertscore-d7fdb0c47eb3?source=collection_archive---------14-----------------------

评估 MT 模型性能的两个有用的软件包

汉娜·赖特在 Unsplash 上拍摄的照片

通过阅读本文,您将学会使用以下软件包评估您的机器翻译模型:

  • 萨克勒布鲁
  • 贝特斯科尔

供您参考,BLEU(双语评估替角)是评估机器翻译文本最流行的指标之一。它可以用来评估任何语言的翻译,只要文本中存在某种形式的单词边界。

BLEU 的输出通常是 0 到 100 之间的分数,表示参考文本和假设文本之间的相似度值。值越高,翻译越好。

话虽如此,BLEU 的一个主要缺点是需要适当地标记文本。例如,您可以使用空格作为分隔符轻松标记任何英语句子。然而,对于缅甸语、汉语和泰语等语言来说,标记化可能具有挑战性。

此外,也有人批评 BLEU 分数的提高并不能保证更好的翻译。当翻译的文本包含传达相同信息的相似单词或同义词时,这是相当明显的。例如,下面的句子从人类的角度来看实际上是相同的,但是当用 BLEU 评估它们时不会得到 100 分。

# Reference text
Hi, how are you?# Hypothesis text
Hello, how are you?

萨克勒布鲁

然而,让我们来探索如何使用 sacreBLEU 轻松评估 BLEU 分数,它:

…轻松计算可共享、可比较和可复制的 BLEU 分数。

装置

强烈建议您在继续之前创建一个新的虚拟环境。激活它并运行以下命令来安装sacrebleu:

pip install sacrebleu

导入

创建一个名为bleu_scorer.py的新文件,并在文件顶部附加以下导入语句:

from sacrebleu.metrics import BLEU

参考和假设文本

如下定义假设文本和参考文本:

refs = [['The dog bit the guy.', 'It was not unexpected.', 'The man bit him first.']]hyps = ['The dog bit the man.', "It wasn't surprising.", 'The man had just bitten him.']

hyps由一个文本列表组成,而refs必须是一个文本列表列表。在实际的用例中,您应该从文件中读取它,如下所示(去掉结尾的换行符):

with open('hyps.txt', 'r', encoding='utf8') as f:
    lines = [x.strip() for x in f]

对于多重引用,您应该将其定义如下:

refs = [['The dog bit the guy.', 'It was not unexpected.', 'The man bit him first.'],
        ['The dog had bit the man.', 'No one was surprised.', 'The man had bitten the dog.']]hyps = ['The dog bit the man.', "It wasn't surprising.", 'The man had just bitten him.']

以下代码强调了多重引用的基本结构:

refs = [[ref1_for_sent1, ref1_for_sent2 ...,], [ref2_for_sent1, ref2_for_sent2, ...], ...]

应用程序接口

然后,使用metrics.BLEU面向对象的 API 创建一个新实例:

bleu = BLEU()

它接受以下输入参数:

  • lowercase —如果为真,则计算小写 BLEU。
  • tokenize —要使用的标记器。如果没有,则默认为特定于语言的标记化器,并将“13a”作为后备默认值。
  • smooth_method —要使用的平滑方法(“floor”、“add-k”、“exp”或“none”)。
  • smooth_value—“floor”和“add-k”方法的平滑值。`无'返回默认值。
  • max_ngram_order —如果给定,它将在计算精度时覆盖最大 n 元语法顺序(默认值:4)。

最大 ngram 默认为 4,因为根据以下研究论文发现它与单语人类判断的相关性最高。

语料库得分

调用corpus_score函数计算整个语料库的蓝分:

result = bleu.corpus_score(hyps, refs)

您可以在以下要点中找到完整的代码:

输出

输出如下所示:

29.44 82.4/42.9/27.3/12.5 (BP = 0.889 ratio = 0.895 hyp_len = 17 ref_len = 19)
  • 29.44指最终的 BLEU 分数
  • 82.4/42.9/27.3/12.5表示 1–4 ngram 顺序的精度值
  • BP是简洁的惩罚
  • ratio表示假设长度与参考长度之比
  • hyp_len指假设文本的总字符数
  • ref_len是参考文本的总字符数

您可以在下面的找到关于每个指标的更多信息。

贝特斯科尔

另一方面,BERTScore有一些与 BLEU 不同的突出之处。它

…利用来自 BERT 的预训练上下文嵌入,并通过余弦相似度匹配候选句子和参考句子中的单词。

它已被证明与人类对句子级和系统级评估的判断相关。此外,BERTScore 还计算精确度、召回率和 F1 值,这对于评估不同的语言生成任务非常有用。

这为使用同义词或相似词的句子提供了更好的评估。例如:

# reference text
The weather is cold today.# hypothesis text
It is freezing today.

装置

运行以下命令通过pip install安装BERTScore:

pip install bert-score

导入

创建一个名为bert_scorer.py的新文件,并在其中添加以下代码:

from bert_score import BERTScorer

参考和假设文本

接下来,您需要定义引用和假设文本。BERTScore 接受文本列表(单个引用)或文本列表列表(多个引用):

refs = [['The dog bit the guy.', 'The dog had bit the man.'],                               ['It was not unexpected.', 'No one was surprised.'],                               ['The man bit him first.', 'The man had bitten the dog.']]hyps = ['The dog bit the man.', "It wasn't surprising.", 'The man had just bitten him.']

与 sacreBLEU 相比,多引用的结构略有不同。它基于以下语法:

refs = [[ref1_for_sent1, ref2_for_sent1 ...,], [ref1_for_sent2, ref2_for_sent2, ...], ...]

应用程序接口

实例化 BERTScorer 面向对象 API 的新实例,如下所示:

scorer = BERTScorer(lang="en", rescale_with_baseline=True)

它接受:

  • model_type —上下文嵌入模型规范,默认使用目标语言的建议模型;必须指定model_typelang中的至少一个
  • verbose —打开中间状态更新
  • device —如果没有,则模型存在于 cuda 上:如果 cuda 可用,则为 0
  • batch_size —加工批量
  • nthreads —螺纹数量
  • lang —句子的语言。当rescale_with_baseline为真时需要指定
  • rescale_with_baseline —使用预先计算的基线重新调整伯特得分
  • baseline_path —定制的基线文件
  • use_fast_tokenizer —使用 HuggingFace 的快速标记器

默认情况下,它基于指定的lang使用以下模型:

  • en —罗伯塔-大号
  • en-sci—allenai/scibert _ scivocab _ uncased
  • zh—Bert-base-中文
  • tr —dbmdz/Bert-base-Turkish-cased

语言的其余部分将基于 Bert-base-多语言环境。如果您打算定制该型号,请查看以下谷歌表单了解更多信息。

重新调整基线有助于调整输出分数,使其更具可读性。这仅仅是因为一些上下文嵌入模型倾向于在非常窄的范围内产生分数。你可以在下面的博客文章中找到更多信息。

这个存储库还包含一些预先计算好基线文件。只需前往下面的并根据您打算使用的模式下载所需的文件。

它将在初始运行时从 HuggingFace 下载模型和依赖项。随后,它将重用相同的下载模型。在 Linux 操作系统上,该模型位于以下目录中:

~/.cache/huggingface/transformers/

语料库得分

如下调用score函数:

P, R, F1 = scorer.score(hyps, refs)

它将返回以下项的张量:

  • P —精度
  • R —回忆
  • F1—F1-得分

以下是 F1 分数的输出示例:

tensor([0.9014, 0.8710, 0.5036, 0.7563, 0.8073, 0.8103, 0.7644, 0.8002, 0.6673, 0.7086])

请注意,基础值的范围是从-1 到 1。

通过调用如下的mean函数,可以很容易地计算出语料库的分数:

print(F1.mean())
# 0.6798698902130217

完整代码位于以下要点:

请注意,与 sacreBLEU 相比,运行 BERTScore 要慢很多。请确保您在评估期间有足够的 GPU 内存。

要了解更多关于 BERTScore 的信息,请查看官方资料库中的示例笔记本

结论

让我们回顾一下你今天所学的内容。

本文首先简要介绍了 BLEU,以及用它来评估译文的优缺点。

接下来,它讲述了如何使用 sacreBLEU 来计算语料库级别的 BLEU 分数。输出还包括 1–4n gram 的精度值。

随后,在 BERTScore 上探讨了用余弦相似度评价译文的方法。score函数分别返回精度、召回率和 F1 分数的张量。

感谢你阅读这篇文章。祝你有美好的一天!

参考

  1. Github — sacreBLEU
  2. Github — BERTScore

低资源语言的机器翻译

原文:https://towardsdatascience.com/machine-translation-on-low-resource-languages-65cb268fcab1?source=collection_archive---------26-----------------------

MT 使用简单的变形金刚|图片由作者提供

在 Deepnote 平台上使用简单的 transformer 将法语翻译成 Ewe 和 Fongbe。

介绍

埃维语和丰贝语是尼日尔-刚果语,是通常被称为 gbe 的相关语言群的一部分。丰贝语是贝宁主要的 gbe 语言(约有 410 万人使用),而埃维语在多哥和加纳东南部被约 450 万人作为第一语言使用,另有 100 万人作为第二语言使用。它们是密切相关的音调语言,并且都包含音调符号,这使得它们难以学习、理解和翻译。更多信息请访问津迪

津迪 MT 挑战赛

目标

这项挑战的目标是创建一个能够将文本从法语转换成 Fongbe 语或 Ewe 语的机器翻译系统。我将使用相同的模型来训练和翻译这两个数据集,以缓解处理能力和内存问题。

简单变压器

这个库是基于 HuggingFace 的变形金刚库。简单的变压器让您快速训练和评估变压器模型。初始化模型、训练模型和评估模型只需要 3 行代码。更多信息请访问 GitHub Repo。

支架

  • 序列分类
  • 令牌分类(NER)
  • 问题回答
  • 语言模型微调
  • 语言模型训练
  • 语言生成
  • T5 型号
  • Seq2Seq 任务
  • 多模态分类
  • 对话式人工智能。
  • 文本表示生成。

安装和加载库

数据

我只使用了 35k 样本,这样我的 GPU 就不会耗尽内存,并且我使用了未经预处理的原始数据。

清理功能在英语翻译中很有用,但在这种情况下,如果我们清理数据,结果会很差。所以,我们要把它关掉。

基于语言将训练和测试数据分成两个数据帧。

训练 Fongbe 模型

使用简单的 transformer seq2seq 我已经下载了在我们的情况下效果最好的Helsinki-NLP/opus-mt-en-mul,并使用特定的Seq2SeqArgs来设置模型的参数。

自变量:

  • 数量 _ 训练 _ 时期= 30
  • batch_size = 32
  • 最大长度= 120
  • src_lang ="fr "
  • tgt_lang ="fon "
  • 覆盖输出目录=真

培训/评估分割

争论

我尝试了多种模型的论证,并产生了最好的可能,给我们更好的结果。

初始化模型

评估指标

培训模式

单一预测

该模型运行准确。

预测成形试验数据并保存

将模型保存到模型中

训练母羊模型

使用简单的 transformer seq2seq 我已经下载了在我们的情况下效果最好的Helsinki-NLP/opus-mt-en-mul,并使用特定的Seq2SeqArgs来设置模型的参数。

论据:

  • 数量 _ 训练 _ 时期= 30
  • batch_size = 32
  • 最大长度= 120
  • src_lang ="fr "
  • tgt_lang ="ewe "
  • 覆盖输出目录=真

模型参数

我尝试了多种模型的论证,并产生了最好的可能,给我们更好的结果。

初始化 Ewe 模型

培训模式

预测和保存 cv

保存模型

加入两个机器翻译预测翻译

创建提交文件

排行榜

本次比赛的误差指标是 Rouge Score ,ROUGE-N (N-gram)评分(Rouge1),报告 F-measure。

Zindi 排行榜

最后的想法

由于谷歌翻译和其他巨头使翻译变得完美,机器翻译在 NLP 的世界中被低估了,但他们没有提供所有的语言,一些低资源语言甚至没有做到。这是一个有趣的旅程,因为我开始使用 seq2seq 模型关注变形金刚,然后偶然发现赫尔辛基 NLP 语言模型。我有内存和 GPU 的问题,即使这样,我也没有提高我的分数,因为在处理大量数据时有许多限制。在花了一个月的时间后,我偶然发现了简单的变形金刚,这些变形金刚是为了让微调变得简单和容易。最后,我对结果感到满意,同时使用有效和快速的方法有效地训练和预测来自非洲的低资源语言。

代码可用在GitHubDeepnote上。

使用 Pytorch 的变压器机器翻译

原文:https://towardsdatascience.com/machine-translation-with-transformers-using-pytorch-f121fe0ad97b?source=collection_archive---------23-----------------------

只需简单的几个步骤就可以将任何语言翻译成另一种语言!

皮斯特亨Unsplash 上的照片

介绍

翻译 ,或者更正式地说,机器翻译,是处理从一种语言到另一种语言的翻译的【NLP】中最流行的任务之一。在早期,翻译最初只是简单地用一种语言中的单词替换另一种语言中的单词。然而,这样做不会产生好的结果,因为语言是根本不同的,所以需要更高层次的理解(如短语/句子)。随着深度学习的出现,现代软件现在采用了统计和神经技术,这些技术被证明在做翻译时更有效。

当然,每个人都可以使用强大的 Google Translate ,但是如果你想知道如何用代码实现翻译,这篇文章将教你如何实现。本文将展示如何使用hugging face Transformers提供的简单 API 轻松实现翻译,这是一个基于py torch的库。

现在事不宜迟,让我们开始吧!

教程概述

  • 安装库
  • 英语到德语的翻译示例
  • 自定义语言翻译示例

安装库

在安装变形金刚库之前,你需要安装一个 Pytorch 的工作版本。你可以去它的官网安装 Pytorch。

安装 Pytorch 后,您可以通过以下方式安装变压器:

pip install transformers

英语到德语的翻译示例

现在,我们准备好做翻译了!如果你想做英语到德语的翻译,那么你可以从导入变形金刚中相关的pipeline模块开始:

from transformers import pipeline

pipeline是一种通过使用简单的 API 对不同任务进行推理的简单方法。你可以在这里了解更多关于pipeline模块的信息。

要进行英语到德语的翻译,您需要一个专门针对这项任务进行微调的模型。 T5 是一个已经在包含英德翻译数据集的大规模 c4 数据集上训练的模型,因此我们可以直接将该模型用于翻译管道(我们使用的是t5-base变体):

translation = pipeline(“translation_en_to_de”)
## same with 
## translation = pipeline("translation_en_to_de", model="t5-base", tokenizer="t5-base")

注意,我们没有在这行代码中指定任何模型,因为默认情况下,t5-base用于翻译。如果您想要指定您自己的模型和记号赋予器,您可以通过指定模型和记号赋予器参数来添加一个modeltokenizer(如果它们在 Huggingface 中提供的话),或者构建您自己的模型和记号赋予器,如下例所示(如果社区提供的话)。关于翻译管道的更多细节,你可以在这里参考官方文档

然后,您可以定义要翻译的文本。让我们试着翻译一下:

我喜欢研究数据科学和机器学习

text = "I like to study Data Science and Machine Learning"

最后,现在您可以使用管道提供的 API 来翻译和设置一个max_length(例如 40 个令牌):

translated_text = translation(text, max_length=40)[0]['translation_text']
print(translated_text)

瞧吧!几十秒后,我们得到德文翻译:

我学的是现代科学和机械

自定义语言翻译示例

如果你想翻译任意两种自定义语言,比如说从英语到汉语,那么你需要一个专门针对这一特定任务进行优化的模型。幸运的是,有了 Huggingface 建立的社区,你很可能不需要收集自己的数据集,并在其上微调你的模型。你可以直接前往 Huggingface 的模型网站查看不同语言对的翻译模型列表。

对于我们从英文翻译成中文的例子,我们可以使用 HelsinkiNLP 的英汉预训练模型并直接使用它。首先,我们首先导入必要的模块:

from transformers import AutoModelWithLMHead, AutoTokenizer

然后,我们可以通过以下方式构建我们的模型和标记器:

model = AutoModelWithLMHead.from_pretrained("Helsinki-NLP/opus-mt-en-zh")
tokenizer = AutoTokenizer.from_pretrained("Helsinki-NLP/opus-mt-en-zh")

现在,我们可以将我们想要翻译、建模和标记化的语言对输入管道:

translation = pipeline("translation_en_to_zh", model=model, tokenizer=tokenizer)

类似于前面的例子,我们可以使用相同的代码来定义我们的文本和翻译:

text = "I like to study Data Science and Machine Learning"
translated_text = translation(text, max_length=40)[0]['translation_text']
print(translated_text)

等待几秒钟后,您应该会看到中文版的文本!

我喜欢学习数据科学和机器学习

结论

恭喜你!现在,您应该能够知道如何使用 Huggingface 及其社区提供的预训练模型来实现翻译。如果您想看看完整的代码是什么样子,这里是 Jupyter 代码:

仅此而已!如果您有任何问题,请随时在下面提问。如果你喜欢我的作品,你可以关注我并注册我的时事通讯,这样每当我发表一篇新文章,你都会得到通知!喜欢的话也可以看看我之前的文章。下次再见,😄

参考

[1] 变形金刚 Github ,拥抱脸

[2] 变形金刚官方文档,拥抱脸

[3] Pytorch 官网,脸书艾研究

[4] Raffel,Colin,et al. “用统一的文本到文本转换器探索迁移学习的极限” arXiv 预印本 arXiv:1910.10683 (2019)。

[5] Tensorflow 数据集,谷歌

用于面部增强识别的机器视觉

原文:https://towardsdatascience.com/machine-vision-for-facial-enhancement-recognition-52c26b807065?source=collection_archive---------36-----------------------

案例研究

Github 储存库此处

图片由诺扬·纳姆达通过 Unsplash 提供—【https://unsplash.com/photos/dUtizJyby4E

问题陈述

在当今技术驱动的世界,知道一张脸是否经过数字增强可能很困难,这产生了一系列问题,从假新闻到社交媒体引发的精神疾病。在这里,我们开发了一个分类模型来预测一张脸是否经过了数字增强,是否经过了修饰、面部替换(如鼻子、眼睛等)。)或整形编辑(即矫正牙齿、改变鼻子大小等。).

行动纲要

数据

非 PS 过的人脸图像是从 FEI 人脸数据库中获得的,它包括 1400 张图片(100 个人,一半是女性,一半是男性)。同一个人的不同图像包含在每个建模集(训练、验证或测试)中。

为了包含不同类型的增强,PS 过的人脸图像是从几个数据集编译而来的。第一个数据集是真假人脸检测数据,其中人脸是使用来自几个人脸的单个片段构建的(被标记为“容易识别是 PS 过的”的人脸被排除在外)。接下来,我们加入了谷歌搜索 Facetune 的图片,因为这是社交媒体上有影响力的人以及一些名人使用的最受欢迎的面部编辑应用程序。这两个 PS 过的人脸集合总共有 791 张图片,每张图片都是独一无二的。

这给了我们 63%的基线准确度。

所有图像都被标准化并重新调整为 224 x 224,我们注意到数据集的包容性水平可以提高,特别是对于非二进制的人。

模型和结果

开发卷积神经网络(CNN)来进行这种分类。我们能够通过消除池层的存在实现 100%的准确性,代价是创建一个缓慢的模型。反过来,我们创建了第二个模型,其中合并了一个池层。速度提高了 6 倍,准确率达到 99%。

使用原始模型,我们测试了 RGB 和灰度,以确保 CNN 不仅仅依赖于颜色和光线,而是依赖于面部的形状。这是必要的,因为数据集不包括使用 studio lightning 的非增强图像(这些图像无法大量找到)。再次达到 100%的准确性,表明该模型可能受益于颜色,但不依赖于颜色。

CNN 模型和评估

模型 1 评估

模型 1 是百分之百准确的。如前所述,我们排除了池层。背后的原因是“皮肤模糊”效应(几乎总是出现在增强的面部)和合并图层都是平均像素,削弱了这种类型的面部编辑的存在。

下面,我们可以看到在训练过程中损失和准确性如何波动。我们还看到了测试集的混淆矩阵。

作者图片—【https://chart-studio.plotly.com/~ambar132/1/? share _ key = uyspthgbhuc 9 o 672 crozt #/

这个混淆矩阵是使用测试集构建的,其中来自增强数据集的个体数量是来自非增强数据集的两倍。它看起来不平衡,因为这仍然产生了很多未增强的个人照片,但所有图像的基线是 63%。在未来,我们的目标是在建立模型之前,使用计算方法来解释阶级的不平衡。

模型 2 评估

这里,我们有一个 99%准确的模型,有 1 个假阴性。这个精度还是很不错的,而模型快了 6 倍。

作者图片—【https://chart-studio.plotly.com/~ambar132/3/? share _ key = mg riz 4 ymmbfb r5 tnalfvpz #/

黑白测试结果

我们用灰度重建了模型 1,得到了同样的结果。这表明,虽然该模型可以从 RGB 通道中提取不同的特征,但它们对于成功的分类并不是必需的。如果我们想在浓妆艳抹或工作室灯光的图片上使用该模型,这一点尤为重要。

显著性检查

显著性是指图像中哪些像素突出。在这里,我们有一个简单的显著性图,以探索模型可能获得的重要特征。最突出的是皮肤,证实了合并层的排除是相关的。

图片作者—灵感来自真假人脸检测数据

随着时间的推移,我们可以绘制我们的模型在每一层检测到的显著性,正如我们在结论和未来方向一节中讨论的那样。

结论和未来方向

我们的两个模型都可以预测一张脸是否已经成功地进行了数字增强。模型 1 以 100%的准确度做到了这一点,并且在彩色或黑白中,二进制交叉熵损失实际上为 0。这一点很重要,因为未经增强的面部图片的颜色由于缺少工作室照明而不太明亮,但情况可能并不总是如此。模型 2 达到了 99%的准确率,由于采用了池层,速度提高了 6 倍。这些百分比远远高于 63%的基线。我们可以部署这些模型中的任何一个来检测涉及将某人的脸放在照片上的假新闻,或者让社交媒体用户能够检查谁编辑了他们的照片。

在未来,我们希望使数据集多样化,使其对非二进制人群更具包容性,并进一步严格解决数据中的阶级不平衡问题。我们的目标还包括其他类型的面部改善,如整形手术,以及由 GANs 创造的面部。

此外,更多的时间将允许我们探索每一层的显著性图,并确定每张图片的哪些区域在被编辑时突出。这可能用于跟踪对哪些图片进行了哪些编辑。

机器行为不端:62 项科学研究显示大型科技公司的算法如何危害公众

原文:https://towardsdatascience.com/machines-misbehaving-62-scientific-studies-showing-how-big-techs-algorithms-can-harm-the-public-e27e584d291c?source=collection_archive---------34-----------------------

是时候创建一个“算法 FDA”了吗?

李中清Unsplash 上拍照

在美国,目前没有联邦机构保护公众免受有害算法的影响。

我们可以购买鸡蛋,接种疫苗,并在高速公路上行驶,因为我们知道有保护我们安全的系统:美国农业部检查我们的鸡蛋中的沙门氏菌,美国食品和药物管理局检查疫苗的安全性和有效性, NHTSA 确保高速公路转弯平稳平缓。

但是当我们在谷歌上搜索或者在亚马逊上查找一个产品的时候呢?我们对这些系统背后的算法的安全性了解多少?虽然一些管辖区正在寻求监督,但如果你愿意的话,算法仍然没有 FDA。

如果你愿意的话,没有“算法的 FDA”。

为了帮助说明为什么这如此令人不安,我最近对 62 项研究进行了文献综述,这些研究揭示了大型科技公司的算法系统如何对公众造成一系列伤害,如谷歌搜索中的掠夺性广告或亚马逊上推荐的误导性健康产品。虽然政府机构尚未实施监管,但研究人员和记者已经做了惊人的工作来收集算法危害的经验证据。

随着算法系统渗透到我们更多的数字生活中,这些“算法审计”只会变得更加重要。

在这篇博文中,我解释了我通过文献综述发现的四种主要的算法危害(这里是完整的预印本,如果你喜欢的话):

要证明这些问题在算法中是如何体现的,不是一件容易的事情。当一个算法只需要按字母顺序对联系人列表进行排序,或者在 excel 电子表格中添加一列时,就有一个“正确”的答案,可以很容易地检查该算法是否有效。

但是今天的技术背后的算法通常没有“正确”的答案。想想为你推荐 YouTube 视频的算法,或者建议你应该在谷歌新闻上阅读哪些文章的算法。这些“主观决策者”可能会带来各种各样的危害(用泽内普·图费克奇的话说),而且没有单一的正确答案来检查算法是否“正确”,更不用说安全有效了。在我回顾的研究中,研究人员应用了各种不同的“安全检查”来审计面向公众的算法。

区分的算法

社会问题体现在算法中。虽然越来越多的人,包括亚历山大·奥卡西奥-科尔特斯这样的立法者,现在认识到算法系统如何加剧歧视等问题,但这一想法获得关注需要 T2 做很多工作。一些研究对实现这一目标尤为重要。

算法歧视的早期证据

文献综述中最早、最具形成性的两项研究聚焦于谷歌搜索算法中的歧视。在2013 年发表的一项研究Latanya Sweeney 测试了在搜索黑人名字和白人名字时出现的广告。一个模式很快出现了:犯罪报告广告出现在黑人名字的搜索结果中(在报纸上,搜索“拉坦亚·斯威尼”会返回一个广告说“拉坦亚·斯威尼被捕了?”)

但是相比之下,搜索像“克里斯汀”这样听起来像白人的名字,并没有提到逮捕、犯罪记录或诸如此类的事情。

同年,Latanya Sweeney 发表了她的报告Safiya Noble 发表了另一篇关于谷歌搜索歧视的开创性研究。在她的优秀著作《压迫的算法》中,诺布尔描述了她在 2010 年研究的起源,当时她正在网上搜索她继女和侄女可能感兴趣的东西。谷歌的搜索结果令人震惊,十大搜索结果中有五个是色情化的。

在 2013 年的研究中,诺布尔简要解释了为什么搜索结果中的歧视如此具有影响力:

“在搜索中不能忽视在线种族差异,因为它是信息通信技术激增的组织逻辑的一部分,互联网既在复制社会关系,也在我们参与的基础上创造新的关系形式” (萨菲亚·诺布尔,2013)

许多技术专家认为这种问题是可以解决的小故障。但是在她的书 科技之后的竞赛 中,Ruha Benjamin 指出小故障既不是小问题也不是容易解决的——它们总是指向更大的系统问题。持续的证据支持本杰明:诺布尔发表她的结果七年后,标记显示谷歌仍然在他们的广告平台上犯同样惊人的错误。下面是他们对谷歌“关键词规划”功能的调查图表:

作者使用来自标记的数据和代码生成的图像

计算机视觉及其他

算法歧视的另一项基础研究是由 Joy Buolamwini 和 Timnit Gebru 进行的开创性的“性别差异”审计。这项研究揭示了微软和 IBM 制造的面部分析工具的差异:浅色皮肤的男性通常能被正确识别,而深色皮肤的女性则不能。Buolamwini 和 Inioluwa Deborah Raji 在进行的后续研究发现了其他几个商业系统的性能差异,但也发现一些系统正在改进。

在我阅读的文献中,这些早期的审计为正在进行的检查算法歧视的工作奠定了基础并点燃了火花。最近,在 2020 年发表的份审计报告中,研究人员约书亚·阿斯普兰莫塔黑尔·埃斯拉米哈里·孙达拉姆克里斯蒂安·桑德维格凯瑞·卡拉哈利斯发现,模仿白种人会导致浏览互联网时出现更多与住房相关的广告,而模仿非裔美国人会导致更多掠夺性的租赁-拥有程序的广告。

随着美国就业焦虑的加剧,公众也应该关注招聘算法中的歧视。在 2019 年的一项研究中,玛利亚·德·阿尔蒂加和其他人在就业分类系统中发现了显著的性别差距。同样研究性别歧视的还有,沙欣·杰姆·格伊克斯图尔特·安布勒克里希纳拉姆·肯塔帕迪展示了一种方法来提高 LinkedIn 人才搜索系统上的性别比例。

所有这些惊人的工作仍然只是触及表面:文献综述确定了 21 项探索歧视的研究——肯定有一些我错过了!如果您有兴趣了解更多信息,请查看全文和/或歧视审计列表

扭曲的算法

许多算法审计引用了一项研究,表明 39%的未决定投票者会将他们的投票行为转移到搜索结果中喜欢的候选人身上。因此,如果 100 名尚未做出决定的选民搜索候选人托纳德·德拉姆普,而搜索结果支持德拉姆普,那么大约 39 名选民可能也会支持德拉姆普。这种现象是失真的一个例子,这是算法审计研究的另一个焦点,突出了算法的把关能力。

刚刚描述的“搜索引擎操纵效应”(由 Robert Epstein 和 Ronald E. Robertson 研究)已经导致许多审计检查搜索引擎是否有党派倾向。这是一个复杂的问题,没有简单的“是或不是”的答案,尤其是因为“党派偏见”是如此难以衡量。以下是关于这个主题的三项重要研究:

  • 罗纳德·e·罗伯逊(Ronald E. Robertson)和其他人在 2018 年进行的一项研究发现,谷歌上的新闻条目略微左倾,但“谷歌的排名算法使(搜索引擎结果页面)的平均倾斜度略微向右移动。”
  • 斯坦福大学研究人员在 2018 年中期进行的一项研究观察到,民主党人和共和党人之间的来源党派分布“几乎没有差异”。
  • 我的同事 Daniel Trielli 和我的顾问 Nick Diakopoulos 进行的另一项研究发现“头条新闻”栏确实有更多来自左倾来源的文章,但这反映了互联网的整体趋势(基于一个名为 GDELT 的大型新闻数据库)。

回声室

党派扭曲只是研究人员一直在探索的许多不同类型中的一种。扭曲也是我给那些专注于“回音室”或“过滤气泡”的研究贴上的标签,据称这些研究只给人们提供他们想看的内容。如同党派之争一样,过滤器泡沫现象的经验证据有限。 证据实际上表明,互联网用户在算法平台上看到了更多样化的信息来源。算法确实个性化你的在线体验,只是没有到制造泡沫的程度。

Aniko Hannak 和他的同事进行的早期个性化审计显示,平均只有 11.7%的搜索结果是个性化的,像“小工具”和“地点”这样的搜索更容易出现个性化 Hannak、 Chloe Kliman-Silver 和其他人的后来研究表明,大多数个性化是位置的结果。我的实验室最近的一项研究发现,即使用户使用不同的党派术语进行搜索(例如“beto orourke pros”与“lies by beto orourke”),谷歌也会产生主流化效应,并显示出相似、一致的结果。

但是主流化也意味着算法系统可以将注意力集中到一小部分来源上,正如我们在对苹果新闻的研究中发现的那样。这在导致来源排除时尤其成问题,例如,最近由 Sean FischerKokil JaidkaYphtach Lelkes 进行的审计发现,谷歌经常将本地新闻排除在结果之外。据彭妮·缪斯·阿伯纳西(Penny Muse Abernathy)的研究显示,通过分流本地新闻业的流量,谷歌可能会导致本地新闻业的危机以及“新闻沙漠”在美国的蔓延。

误报

最后一种扭曲与低质量媒体有关,如虚假信息、垃圾新闻或其他投机内容。(如今,“假新闻”这个词已经没什么用处了,因为它被政客、阴谋家和极端分子借用了)。 Rediet Abebe 领导的一项审计发现,对艾滋病毒/艾滋病的搜索结果可能暗示“自然疗法”,而这些疗法已被证明无效甚至有害。

研究人员还在 YouTube 上发现了错误信息兔子洞,尽管一些类似“化学痕迹”的兔子洞似乎已经得到解决。在 YouTube 上快速搜索,搜索结果和推荐都指向带有事实解释的视频:

作者截图,灵感来自侯赛因等人

总的来说,文献综述包括 29 项集中于失真的审计,所以这只是一个抽样。完整的列表在这里是,包括一些新增加的内容,这些内容没有在的论文中,因为它们还没有发表。

利用的算法

“大型科技公司从你的数据中获利”的说法最近变得越来越流行,一些审计关注于这将如何发展。大多数公共对话集中在侵入性的数据收集上,事实上,研究表明了为什么公众应该被打扰。在由胡塞·贡萨雷斯·卡巴尼亚斯领导的一项研究中,研究人员发现脸书的解释具有误导性,并且掩盖了脸书是如何利用敏感属性进行定向广告的。由阿米特·达塔领导的另一项研究在谷歌上发现了类似的案例。

第二种类型的利用包括为算法系统产生信息的劳动。例如,一项研究表明,如果没有来自维基百科、推特和 StackOverflow 等网站的用户生成内容,谷歌的搜索引擎将无法正常工作。由我的同事 Nick Vincent 领导的一项后续研究发现,通过自愿劳动创造的维基百科内容出现在 81%的趋势搜索结果页面中,以及 90%的关于“死刑”或“巴以冲突”等热门争议的搜索结果页面中这项研究还发现,谷歌严重依赖新闻媒体获得搜索结果,尽管谷歌仍然没有向出版商支付有意义的费用。

这种利用是将数据视为劳动力并考虑平台如何补偿为其算法系统提供燃料的劳动力的基本概念。例如,利用人们数据的利润,一个平台可以资助公共产品如公园、WiFi 和基础设施,或者简单地给每个用户开一张支票,就像勇敢的浏览器所做的那样

判断错误的算法

误判不同于其他类型的行为,是一个广泛的元范畴。在文献综述中,我建议未来的审计尽量关注更具体的有问题的行为,以尽可能清楚地说明算法的风险和危害。尽管如此,还是有一些关于一般“误判”的有趣研究值得一提。

一种重要的误判经常发生在广告平台上,如果你曾经疑惑过,你可能对此很熟悉,我到底为什么会看到这个广告?事实证明,算法系统经常为定向广告推断出错误的兴趣或错误的人口统计属性。 Giridhari Venkatadri 领导的一项 2019 年研究发现,Epsilon 和 Experian 等平台上约 40%的目标属性“根本不准确”一个明显的例子是,一些被推断为公司高管的用户实际上是失业的。

这些错误可以被解释为潜在的“数字广告泡沫”的证据,作者 Tim Hwang 最近将其描述为“次贷注意力危机”简而言之(没有双关语的意思),如果广告商知道 40%的目标特征“根本不准确”,他们可能不会为目标广告支付那么多钱。

结论

新技术总是给公众带来新的风险,通过这篇文献综述,我发现了 62 项研究(并且还在统计)强调了为谷歌、亚马逊、脸书和其他大型科技平台提供动力的算法的风险。从歧视,到扭曲,到剥削,到误判,研究人员已经表明,算法系统可以而且确实会伤害公众,不仅仅是在科幻情节或象牙塔假设中,而是在我们的现实世界中。

算法系统可能并且确实会伤害公众,不仅仅是在科幻情节中,而是在我们的现实世界中

这是坏消息。

好消息是,用阿兰达蒂·洛伊的话来说,“另一个世界不仅是可能的,她正在来的路上。”我们可以通过用户、研究人员、记者和其他利益相关者的合作来扭转局面。我们可以设计、建造和使用服务于公共利益的系统,而不仅仅是公司利益。

还有许多工作要做,道路上还有许多障碍,但是我们可以一起与我们的技术建立更好的关系。

MADE —用于分布估计的屏蔽自动编码器

原文:https://towardsdatascience.com/made-masked-autoencoder-for-distribution-estimation-fc95aaca8467?source=collection_archive---------10-----------------------

来源:作者

本文对 Mathieu Germain 等人在 2015 年的论文中提出的一种技术进行了深入的解释。这里描述的技术现在用于现代分布估计算法,如掩蔽的自回归正态流逆自回归正态流

注意——我也有一个 YouTube 视频解释这个算法(如果你喜欢看&听)——

制作的 YouTube 视频

目标/背景/解决的问题

很高层次的目标可以从论文本身的标题中理解,即设计一种技术来进行分布估计。

分布或密度估计是机器学习中最重要的领域之一,因为它有助于我们理解数据集的潜在统计属性,也使生成模型成为可能。

密度估计的方法通常分为以下几类

  • 参数化方法。这些方法为你的观察假设一个概率分布,然后寻找它的参数。例如,如果假设的概率分布是正态分布,那么该方法将找到𝞵和𝝈.
  • 非参数方法。这些方法并不假设您的观测值具有已知的概率分布,而是将其建模为经验分布。经验分布本质上对于每个数据点都有一个核函数。

本文中描述的技术是一种用于密度估计的参数方法,并且依赖自动编码器作为实现目标的设置。

也就是说,任何密度估计技术的主要挑战都来自数据集的维度。 维数灾难 有时会使密度估计的问题变得棘手,并且解决方案的性能(估计的精度和速度)通常很差。

为什么选择 Autoencoder?

我先解释一下“为什么是神经网络?”。如前所述,测试时间(部署时间)内的密度估计速度对于实际应用非常重要。神经网络的现代公式支持矢量化和加速器的使用,这有助于在测试期间达到临界速度要求。

自动编码器是一种在无监督设置中使用的神经网络(即,不需要地面实况/标签,实际上密度估计任务没有标签),其工作是重新创建输入,同时学习数据的低维潜在表示。然后,这种潜在表示被用于许多应用中,例如特征提取和异常检测。

来源:作者

因此,自动编码器的主要目标是学习潜在表示,并通过限制隐藏层(潜在表示隐藏层)中神经元的数量(小于输入维度)来迫使神经网络这样做。

这是自动编码器学习潜在表示的唯一方式吗?

有一些其他的方法来约束自动编码器(把这种约束想象成“扭转手臂”或“强迫”)来学习一个适当的表示。

来源:作者

上面显示了一个自动编码器去噪的例子。在这里,噪声被添加到输入神经元,以约束(“扭曲”)网络来学习适当的表示。请注意,潜在表征在维度上与输入神经元的大小相同,但它可以更小或更大!

伟大的想法

可以限制自动编码器输出输入向量分量的概率分布吗?

下面是我们的自动编码器的样子:

来源:作者

本质上,我们将让输出神经元预测我们假设的(组分的)分布参数。

但是上面的公式对组件之间的独立性做了非常强的假设😟。如果组件有条件依赖怎么办?下面是一个公式的样子:

来源:作者

也就是说,我们不知道这是不是我们的输入向量的条件依赖!这里,分量 x1、x2、x3 和 x4 是任意选取的。本质上,这是你的特征向量,x1,x2 等只是列名。你可以选择任何顺序!

这意味着条件依赖可能是这样的:

来源:作者

因此,我们在设置中发现的第一个问题是,我们不知道组件是如何条件依赖的,第二个问题是,所有神经元都是相互连接的(这是一个完全连接的前馈神经网络!).

为什么全连接设置会有问题? 如果有一分钟我们假设条件依赖是上图所示,那么从神经元 x4 到 x2 的激活流&输出是不正确的,其他神经元也是如此。简而言之,连通性应该尊重条件依赖。另一种说法是——过去不应该看到未来!

以下是我们使用 Autoencoder 的解决方案的细化目标:

来源:作者

屏蔽自动编码器

一种约束方法是确保“自回归”特性得到尊重。这里的自回归意味着给定一个条件依赖假设,过去不应该看到未来。这篇论文是这样描述的:

来源:从报纸上剪下

这意味着我们必须根据条件依赖假设丢弃一些连接。也就是说,连接的断开或丢弃应该以逻辑的方式进行,即如果条件依赖性改变,我们应该能够恢复连接。这种连接的逻辑丢弃是在掩码的帮助下完成的,因此得名掩码自动编码器

来源:从报纸上剪下

它是如何工作的?

现在我将描述训练过程背后的机制。请记住,我们需要让我们的设置不知道维度的顺序,因为我们根本不知道输入向量的组件之间的条件依赖的顺序。

此外,我们必须找到一种动态创建掩码的方法,以便在给定的条件依赖设置中丢弃神经元之间的连接。

如何处理「未知」的条件依赖?

这个问题的答案来自于 Uria 等人的一篇论文,他们在论文中也对自回归模型进行了实验。他们的发现表明,尝试输入向量的所有可能的排序是有益的。

来源:从报纸上剪下

你要注意的是,这里没有多个网络。对于输入向量的每一种可能的排序,你都有一个专用的网络。那么这是如何实现的呢?🤔

对于所有可能的排序,自动编码器网络(以及其学习的参数)保持不变。这个概念有一个名字,叫做摊余推断。请注意,这篇文章没有使用这个术语,因为它是在这篇文章发表一年后才流行起来的!本质上,神经网络的参数是以处理不同阶输入向量的方式学习的。

也就是说,处理太多的排列不是小事,尤其是当输入向量是高维的时候。此外,这种类型的约束(“扭臂”)即改变网络的每个迷你批次的顺序,这种约束太大,以至于很难学习!。手臂会扭曲到折断。在机器学习中,我们会说我们正在做过度正则化&因此会欠拟合!

作为补救措施,本文建议我们应该选择某些排序,然后在整个培训中循环使用。这将是超参数,即哪些排序和多少?

上面的图片/剪辑显示了[x1,x2,x3]分别标记为[3,1,2]的顺序,其他层也是类似的情况。

如何创建这些面具?

这些掩码有 2 组规则,用 2 个等式表示。第一个等式决定了除倒数第二层和最后一层之间的连接之外的所有层之间的连接。

来源:从报纸上剪下

它仅仅说明一层中的神经元应该接收来自前一层中标记为相同或更低的神经元的连接。在这种情况下,掩码将为 1,否则为零。

对于倒数第二层和最后一层之间的连接,情况稍有不同,并且由以下等式控制:

来源:从报纸上剪下

唯一的区别是,最后一层中的神经元只接受来自标记低于它的神经元的连接。

使用我创建的图像查看神经元之间的连接(注意标签)(我更喜欢我的神经网络从左到右😛)

来源:作者

还要注意,输入层中标记为 3 的神经元没有连接到下一层中的任何神经元,因为它是 3 维输入向量的最高可能标签/编号。同样,请注意,输出层中标记为 1 的神经元没有连接,因为它是分配给向量中某个分量的最低可能标签。

事情就是这样解决的。这是一个连接的小动画。

来源:作者

关键见解摘要

  • 使用 Autoencoder 输出输入向量分量的“条件”概率分布。
  • 屏蔽自动编码器中的连接以实现条件依赖。
  • 对每个迷你批次的输入组件的排序进行采样,以便相对于条件依赖是不可知的。
  • 在测试期间对订单进行抽样。这导致模型的集合。平均所有模型的预测值。
  • 每个迷你批次的采样顺序可能会导致过度正则化和欠拟合,因此可以有一个固定的掩码列表。这可能是一个超参数!

结论和后续步骤

这是一篇写得很好的论文。我非常喜欢读它,真的很佩服作者的创新思维。

更重要的是,正如我在介绍中提到的,MADE 现在被用作现代基于规范化流的算法的一个组件,因此理解它现在比以前更加重要。

本文提供了多种实现方式。请参见下面参考资料中的链接。

如果你有问题或疑问,请写在评论中,我会提供必要的澄清和/或根据需要更新文章。

祝你学习顺利!

参考

[1]制造:用于分布估计的屏蔽自动编码器https://arxiv.org/abs/1502.03509

[2] RNADE:实值神经自回归密度估计器【https://arxiv.org/abs/1306.0186

[3]用于密度估计的掩蔽自回归流https://arxiv.org/abs/1705.07057

[4]用逆自回归流改进变分推断【https://arxiv.org/abs/1606.04934

[5]https://papers with code . com/paper/made-masked-auto encoder-for-distribution

魔术 8 球:一个应用程序,以最大限度地赢得竞争池比赛(第一部分)

原文:https://towardsdatascience.com/magic-8-ball-an-app-to-maximize-wins-in-competitive-pool-matches-part-1-e1d302b5507c?source=collection_archive---------28-----------------------

机器学习和 SQL 如何帮助你在连续团队游戏中智胜对手

图片经由 instagram.com/stevenfritters授权给卡勒姆·安东内尔

作为一个具有光学物理背景的台球爱好者,我经常想知道我模拟激光束路径的经验是否提高了我对准台球击球的能力,或者相反!

新冠肺炎的封锁恰逢我的职业生涯从光学物理转向数据科学,也是联赛的中断。虽然我不能去台球厅玩我喜欢的游戏,但我花了很多时间思考数据如何指导台球厅游戏的策略。

许多国家台球联盟保存有详细记录的球员统计数据和过去比赛的记录,为建立预测模型提供了理想的资源。在 Insight 数据科学奖学金期间,我学会了如何使用 Python 中的 Flask 将机器学习模型集成到用户友好的 web 应用程序中。所以,我想知道:Flask 和机器学习的强大组合能否用于创建一个个人台球教练?

在这个由三部分组成的系列中,我将描述我是如何开发 Magic8Ball 台球的,这是一个帮助你的台球队最大化其获胜机会的应用程序。

  • 在你现在正在阅读的第一部分中,我将更详细地介绍这个问题,并展示机器学习如何应用于预测台球游戏的结果。
  • 在第 2 部分 中,我将展示 SQL 查询如何帮助改进玩家选择策略。
  • 第 3 部分 中,对应用的性能进行统计评估,并与现实策略进行比较。

泳池问题

台球,或称口袋台球,是一系列游戏的名称,这些游戏都有一个共同的目标,就是用球杆将球打入洞中。游戏在台球桌上进行,这是一个布覆盖的矩形表面,有 6 个洞或口袋。在业余水平上,最常玩的台球版本是八球,以至于短语“一场台球游戏”是八球游戏的同义词。

在八球游戏中,桌子上有 16 个球:

  • 编号为 1-7 的 7 种纯色。
  • 编号为 9-15 的 7 种条纹颜色。
  • 实心白色母球。
  • 实心黑色 8 号球。

纯色和条纹是两种不同的套装;每个玩家被分配到一套衣服(取决于第一个装入口袋的球),并试图在装入 8 个球之前将所有 7 个球装入他们的衣服,以赢得胜利。

8 球池设置。使用https://pad.chalkysticks.com/.生成的图像

个人池是一个技术技能和战略在平等措施的游戏。可能出现的不同击球情况的数量基本上是无限的,并且有丰富的学术文献描述了为台球游戏建模的人工智能方法

的团队组合中,一种全新的策略出现了:选择玩家阵容。台球队由一群玩家/朋友组成,他们定期聚集在一起,在一个嬉戏的竞争环境中释放一些蒸汽。各队为赢得最多的分数而战,以在当地联赛中名列前茅。任何队长都会急切地告诉你,台面下的决定和台面上的决定一样重要。比赛的胜负完全取决于队长们明智(或愚蠢)的阵容选择。

表现最好的团队将获得现金奖励和参加在拉斯维加斯/新奥尔良举行的全国业余锦标赛——这是一个主要的激励因素!此外,新的和临时的玩家可以与经验丰富的特级大师在同一个联盟中竞争(有公平的获胜机会),这要归功于有效促进包容性的平等差点系统(稍后将详细介绍)。考虑到这些因素,这些游戏的比赛结果可能出人意料地不可预测。

开始之前的一些池术语和定义:

-团队:一组 5-8 名联营池玩家。

-队长:负责选择每轮游戏中哪些玩家上场的玩家。

-技能等级:由联盟运营商分配给玩家的数字,用来描述他们的游戏能力。在每次匹配结果后由 Elo 算法重新计算。

-回合:两个对立队的球员之间的单挑。

-比赛:一个台球队对另一个台球队的比赛。最常见的情况是,一个队的五名选定选手与对方队的五名选定选手比赛,每个选定选手只打一次。每一轮的分数被计算出来,产生总的比赛分数。即使总的比赛结果已经用数学方法决定,也要打完所有五个回合。

- Rack: 一场台球比赛,从开球开始,到 8 号球沉入水中结束。每个玩家必须赢得一定数量的机架才能赢得这轮游戏。

-比赛:赢得一轮比赛所需的架子数。这个数字或比赛对每个玩家来说是不一样的,并且是通过使用差点算法使用玩家的技能水平来计算的。

-阵容:详细列出每轮入选球员的最终名单。注意配对的顺序不影响结果。

比赛规则

在两个队开始比赛之前,掷硬币,获胜的队长决定哪一队在第一轮中先选择一名队员。在第一轮比赛后,队长轮流首先选择一名球员,即比赛选择事件可以按如下方式展开:

  • A 队选择一名球员进行第一轮比赛。
  • B 队选择一名球员进行第一轮比赛。
  • B 队选出一名球员进行第二轮比赛。
  • A 队选出一名选手参加第二轮比赛。
  • …等等。直到所有回合结束。

均衡差点

尽管队长非常了解他们球员的能力,但决策过程却被均衡差点严重影响。让我们通过一个示例玩家配对来解释这是如何工作的,这将有助于将您刚刚读到的一些术语和定义放入上下文中:

图片经由 instagram.com/stevenfritters授权给卡勒姆·安东内尔

愤怒的史蒂夫技能等级为 110,这意味着他是一个顶级的业余选手。与此同时 Ambling Ally 只是在这里度过了一段美好的时光,他们 50 的技能水平反映了他们并没有把游戏看得太重的事实。均等差点使比赛场地变得平坦,因此如果这两个人在一个回合中彼此面对,每个人将有大约 50%的机会获胜。它本质上是一个转换公式,以玩家的技能水平作为输入,并产生每个玩家的比赛长度。在我参加的联盟中,Steve 需要 8 个架子才能赢得这一轮,而 Ally 只需要赢 2 个。然而,这并不是一个完美的系统,因为影响比赛结果的因素不仅仅是玩家的技能水平(例如破旧的装备)。

大多数联盟都会记录每一场比赛,包括球员的技术水平、比赛长度和最终得分——这对战略家来说是个福音。

解决方案

在这篇文章中,我将描述如何将一个简单的机器学习模型应用于这些数据,以创建一个可以指导玩家选择的应用程序,并最大化我们团队在利润丰厚的拉斯维加斯之旅中的机会。

对于有数学倾向的读者来说,这是一个竞争性子集选择的例子,这个话题已经在严谨的 细节中探讨过了。

图 1:magic 8 ball 台球 app 示意图。球队的详细信息被加载到一个预测模型中,该模型为所有可能的阵容生成一个获胜概率列表。这些都存储在一个数据库中,在每一轮结束后查询该数据库,以返回该轮的最佳玩家选择。

magic 8 ball 应用程序会通知用户每一轮的最佳选择。

它由以下组件组成:

  • 预测模型生成一个玩家战胜另一个玩家的概率
  • 数据库,包含每个可能的玩家阵容 排列的预测比赛结果。
  • 玩家选择算法引导用户选择获胜概率最高的阵容排列
  • 一个烧瓶应用程序,它在一个用户友好的界面中实现了上述所有功能。

图 1 显示了 Magic8Ball 应用程序的概况。在这个系列中,我将集中讨论最常见的 5 人球队的联赛形式。这意味着有 5 个!= 120 种可能的比赛阵容,其中一些更有可能导致一个队获胜。每个队列的结果由机器学习算法预测,并存储在 SQL 数据库中。在每一轮开始时,使用这些预测来计算最佳玩家选择。随着队长在随后的四轮比赛中选择球员进行对抗,剩下的评估阵容越来越少,比赛获胜的概率稳步增加。

为预测模型选择特征

为了给给定回合提供有意义的玩家建议,我们需要一种定量比较不同玩家配对的方法。我们将使用来自北美台球协会(NAPA) 的 20,000 个历史玩家配对的结果来构建一个预测模型。

要查看本节中使用的任何代码,请查看我的 GitHub 存储库中的对应文件

NAPA 以易读的表格格式发布最新的比赛结果。比赛统计数据可以用裕量的形式表示,即从玩家 a 的统计数据值中减去玩家 B 的统计数据值。以下是每个完整回合可用的一些功能:

  • 比赛差额:每个玩家赢得一轮比赛所需的架子数之差。
  • 获胜百分比差额:每位玩家的历史回合获胜百分比之间的差异(来自之前的比赛):

  • 技能余量:每个玩家技能等级的差异。
  • 游戏保证金:每位玩家在 NAPA 会员资格期间所玩回合总数之差。
  • 平均每场比赛点数差额(AvgPPM 差额):每位玩家每轮平均点数之间的差额。

最后,也是最重要的…

  • 赢面:玩家 A 在当前回合中的赢面(以格子数计)。负值表示玩家 B 赢了这一轮。在等式中,玩家 A 的赢率由下式给出:

我们的目标是使用前五个特征来预测该玩家配对的胜率

图 2:20000 场比赛数据集中球员统计数据的分布。比赛差额、获胜百分比差额、技能差额、游戏差额和 AvgPPM 差额变量可用于预测玩家配对的获胜差额(见下文)。

图 3: 数据集中 20,000 个匹配的 Win Margin 变量(以机架为单位)的直方图。

我们能从这些历史结果中得到什么启示?一个很好的起点是检查图 2 和图 3 中绘制的数据分布,并对数据集进行基本的相关性分析,以找出是否有任何变量表现出很强的关系。

图 4: 数据集中特征的皮尔逊相关系数矩阵。

图 4 显示了 20,000 轮历史数据集中每个特征的皮尔逊相关系数矩阵。一些观察结果立即凸显出来:

  • Win %毛利AvgPPM 毛利呈现完美的多重共线性!这很明显,因为赢了比输了会得到更多的分数。然而,这对于线性回归等模型来说不是好消息,因此我们需要在拟合模型之前删除其中一个特性。
  • 技能差距种族差距之间也有很高的相关系数。这是有意义的,因为比赛的差距是用玩家的技能等级来计算的。然而,比赛计算器不是一个连续的数学函数,所以这种相关性并不完美。
  • 我们只看到与目标特征赢率的弱相关性,对于赢率百分比,最高系数为 0.2 。虽然这对平衡障碍的设计者来说是个好消息,但对我们开发高度信息化模型的前景来说却是个不祥之兆。如果没有这个障碍,我们预计技能水平胜率之间会有更强的相关性。

选择预测模型

我们希望训练一个模型,该模型使用比赛利润、游戏利润、获胜百分比利润、技能利润和 AvgPPM 利润变量来预测获胜利润变量的值。

1.线性回归

由于每个特征近似正态分布,线性回归是一个合适的起始模型。利用线性回归模型和我们的特征,我们可以潜在地预测玩家在给定回合中可能获胜的幅度。

我们已经看到 AvgPPM Margin 变量是多余的,因为它与 Win % Margin 完全相关,我们还将删除游戏 Margin 变量,因为它的影响幅度很小。使用剩余的特征,数据被分成训练集和验证集。

我对训练数据进行了缩放,然后拟合了一个普通的最小二乘回归模型。使用验证数据集中预测值和实际值之间的平均绝对误差(MAE)相关系数(R 的平方)来量化性能。回归模型根据架子的数量来预测玩家 A 的获胜差额。

图 5: 散点图,显示 Win 余量(机架单位)的线性回归预测与实际值的比较。左窗格显示训练数据集的结果,右窗格显示验证数据集的结果。

训练和测试数据集的模型预测如图 5 所示。从这些散点图中,我们可以看到模型明显有很大的方差!每个预测的平均绝对误差约为 2 个机架,这是非常不明智的,因为在数据集中的所有结果中, 63% 以 2 个机架或更少的差距胜出(见图 3)。所以,有了这个模型,我们就很有可能预测出不正确的赢家。不完全是那种你信任的自信的模型。

2.分类

考虑到我们到目前为止看到的嘈杂的数据,也许预测单个回合的胜率不是最有用或最实际的。取而代之的是,对个别回合将如何结束做出概率预测会更有用。通过衡量可能的玩家配对的获胜概率,我们可以对我们的玩家选择做出明智的战略决策。

我们可以通过创建一个新的二元赢/输变量并将我们的回归问题转化为分类问题来实现这一点。分类模型生成样本属于某个类别的概率,在我们的例子中,玩家 a 赢了或输了。如果预测的概率超过 0.5,我们可以期待赢,如果概率小于 0.5,我们可以期待输。大于零的赢率(玩家 A 赢了)被赋值为 1,而小于零的赢率(玩家 B 赢了)被赋值为 0。

在添加了二进制输赢功能后,我比较了三种预测玩家获胜的分类模型:逻辑回归、线性支持向量分类器(SVC)和朴素贝叶斯分类器。每个分类器的一些性能指标如下所示。

表 1: 预测玩家 a 输赢时每个分类器的精度、召回率、F1 和 ROC AUC 值

乍一看,逻辑和 SVC 分类器在区分玩家 a 的预测赢和预测输的能力方面似乎没有什么不同

然而,我们更感兴趣的是知道预测概率的可靠性,而不是简单地测量预测概率导致正确输赢预测的次数。例如,在模型预测玩家 A 有 60%机会获胜的所有回合中,玩家 A 实际上有 60%的机会获胜吗?

我们可以通过绘制校准曲线(也称为可靠性曲线)来测量。这使我们能够比较玩家 A 获胜的预测概率和玩家 A 的实际获胜分数。

图 6 中的数据点是通过将[0,1]概率区间离散成 10 个区间并测量该区间中包含的实际玩家 A 获胜的分数而产生的。

图 6: 针对三个分类器模型中的每一个,预测的获胜概率相对于实际获胜的分数绘制:逻辑回归(蓝色)、朴素贝叶斯(橙色)和线性 SVC(绿色)。由虚线表示的完全校准的模型将遵循 y=x 线。

我们可以看到,来自逻辑回归模型的概率预测几乎完美地校准到玩家 A 获胜的真实分数。虚线的平均绝对偏差为 0.01 ,在概率范围内变化很小。这意味着我们可以确信,来自逻辑回归模型的概率预测是玩家将赢得给定回合的可能性的现实表示。然而,需要考虑的是保序回归可以改善 SVC 和朴素贝叶斯模型的校准。

现在我们已经有了一个模型,它可以很好地用逻辑回归预测玩家获胜,在第 2 部分中,我们将看到这个逻辑回归模型如何实际应用于玩家选择决策!

该项目的 Github 库。

插图由才华横溢的@ Steven writers提供。

魔术 8 球:一个应用程序,以最大限度地赢得竞争池比赛(第二部分)

原文:https://towardsdatascience.com/magic-8-ball-an-app-to-maximize-wins-in-competitive-pool-matches-part-2-eb9d4793f98f?source=collection_archive---------49-----------------------

机器学习和 SQL 如何帮助你在连续团队游戏中智胜对手

欢迎回到这个关于数据驱动池策略的三部分系列!

第 1 部分中,我们探索了竞技团队台球的古怪之处,并确定台球游戏的玩家阵容选择可以通过数据科学来改进。我们开发了一个分类模型,根据过去的结果预测一个玩家击败另一个玩家的概率。在这里,在这一部分,我们将更进一步, 使用 这些预测来实际上 通知 策略来进行玩家选择。

第 1 部分:简介和预测建模。

第 2 部分:使用 SQL 制定战略。

第三部分:“封装”测试!

比赛获胜概率

在上一篇文章中,我们开发了一个逻辑回归模型,它使用历史表现统计来预测一个玩家击败另一个玩家的概率。

虽然我们可以使用我们的模型来预测每个可能的玩家配对的获胜概率,但我们真正感兴趣的是整体比赛获胜概率。

回想一下,在一场比赛中有 5 个!= 120 种不同的可能排列组合;因此,这些不同排列中的每一个将具有不同的相关匹配获胜概率

为了从最好到最差排列,我们需要计算每个配对排列的个体概率。

在这里,我们假设赢得整体比赛需要赢得五回合中的三回合;所以,对于每一个阵容排列,我们需要计算出 至少三轮的获胜概率。最少三次获胜的所有概率之和可通过以下等式获得:

假设每轮获胜的概率是独立的,我们可以通过计算下面的表达式来计算上面等式右边的每一项:

其中 p_i 是赢得回合 i 的概率。恰好赢 m 轮的概率由 P(m 胜)给出,即 x^m 的系数,其中 x 是虚拟变量。

例如为了计算 P(4 胜)我们展开表达式的左侧,使用 x^4 的系数:

Python 实现

我们的逻辑回归模型将玩家配对的比赛保证金、技能保证金和获胜百分比保证金值作为输入,并返回玩家 A 将赢得这一轮的预测概率。我们可以在一个五行 Python 数据帧中存储一个比赛阵容,其中每行对应一个玩家配对。

如果我们将我们的模型应用于队列数据帧,我们生成一个概率向量——每个配对一个概率。下面的函数采用这个概率向量,并使用上面的等式计算 P(赢匹配)

假设我们已经将所有阵容数据帧存储在一个名为阵容的列表中。我们现在可以将预测模型应用于每个阵容,并计算每个阵容排列的匹配获胜概率。

组织比赛预测

队长轮流扮演首先选择球员的角色。在每轮比赛开始时,队长都要确保他们选择了最好的球员为他们的球队效力。因为我们的目标是部署一个用户友好的 web 应用程序,所以将每个排列的预测存储在一个关系数据库中是有意义的。有了这个数据库,我们只需要为每场比赛生成一次预测概率。在每一轮开始时,我们可以检索推荐的球员,作为可重用 SQL 查询的结果。我们使用 postgreSQL 是因为它与 Heroku 等 app 部署平台无缝集成。****

图 1:数据库模式。

图 1 显示了数据库中包含的每个表的模式:

  • all_perms 包含 player_aplayer_b、的预测获胜概率以及包含该配对的排列**的数字 id(从 1-120)。**
  • perm_score 包含每个排列的总匹配获胜概率
  • team_a 包含 a 队玩家的玩家 id**s、 name s、 skill_level s 的列表。**
  • team_b 包含 b 队玩家的 id s、名字 s、技能等级 s 的列表
  • 随着比赛的展开,阵容会随着选定玩家的 id s 和名称 s 不断更新。 pos 是 1-10 之间的整数,表示在阵容中的位置,奇数对应于 A 队选择,偶数对应于 B 队选择。

球员选择策略——比赛示例:

现在我们有了两个队之间每个可能阵容的预测数据库,我们可以很容易地找出哪个阵容有最高的获胜概率。然而,由于我们不能确定每一轮对方队长会选择哪些球员,所以要达到这个目标还远不能保证。然而,有没有一种选择策略能始终产生接近最优的阵容?

****让我们站在队长的角度来打一场比赛

我们面对的是蓝队队长 Slick Jill,和我们一样,她会尽最大努力创造一个最大化她获胜机会的阵容。该模型已经被应用于预测我们的每个玩家(红队)对蓝队的每个玩家的获胜概率,如表 1 中所总结的。这些概率取自数据库中的 all_perms 表。

表 1:A 队(红色)的玩家对 B 队(蓝色)玩家的预测获胜概率。

第一轮:回应对手的选择

滑头吉尔赢得了掷硬币,并选择在第一轮选择第一。她把保罗叫到桌前玩。我们的应对策略是什么?

看着矩阵并立即选择 Curtis 来回应可能很有诱惑力。他赢的可能性最大,所以这很容易,对吗?使用这种逻辑的选择策略是贪婪算法的一种形式。在许多比赛中,这可能最终成为一种短视的策略。例如,泰莎击败保罗的几率几乎和柯蒂斯一样高,而柯蒂斯击败胡安娜的几率是迄今为止最高的。为这场可能的比赛保留他可能是谨慎的。也可能出现这样的情况,即“牺牲”一轮是有利的,如果这意味着团队有更高的概率赢得更多的后续回合

考虑到这一点,我们如何才能确信我们选择的是最好的球员,而不会让我们的大脑被各种不同的可能性淹没?

我们已经做了很多繁琐的工作,通过计算每一个可能的阵容赢得比赛的概率。这些匹配概率存储在我们数据库的 perm_score 表中。是时候使用它们了!

现在,表 2 显示了一个新的匹配矩阵,其中这次的值表示包含该配对的所有阵容的平均匹配获胜概率。****

表 2:与表 1 相反,该匹配矩阵显示了包含该玩家配对的阵容排列的平均匹配获胜概率。

对应于最佳阵容的配对以灰色突出显示。该阵容的比赛获胜概率为 0.77,,相比之下,所有 120 种排列的平均比赛获胜概率为 0.66

现在我们可以看到,平均而言,米尔顿和保罗的组合会比我们选择任何其他球员更有可能赢得比赛。从第一张桌子上看这一点都不明显!无论 Slick Jill 选择了谁,我们都可以用一名球员来应对,这将提高我们赢得比赛的可能性。****

下面的代码展示了我们如何用 Python 编写一个函数,使用对 postgreSQL 数据库的查询来生成类似表 2 的内容。该函数有两个参数:对应于 Slick Jill 选择的玩家 ID, player_b_id ,以及到 postgreSQL 数据库的连接, con

有很多东西需要消化。第 4 行和第 5 行的两个 Python 函数检索当前的队列,这是使数据库被过滤为只包含活动排列所必需的。剩下的代码由一个检索最佳玩家选择的 SQL 查询组成。让我们一行一行地解开它,按照执行代码的顺序打印逐步输出。

  1. 第 11 行:从 all_perms 表中选择活动排列的所有 id。“子句”是一个 WHERE 语句,它过滤掉由于前几轮完成而不再可能的排列。参见 GitHub 中的完整代码。因为所有的排列仍然是可能的,所以返回一个表, f ,由包含数字 1-120 的一列组成。

2.第 12 行:对 all_perms 表的内部连接。同样,因为我们还没有排除任何可能的结果,所以这只是返回整个 all_perms 表,其中有重复的置换列。

3.第 13 行:将结果加入到 perm_score 表中,以访问匹配的获胜概率。注意,a.probability 指的是给定排列中单轮的预测获胜概率,而 s.probability 指的是给定排列的预测匹配获胜概率

4.第 14 行:过滤表格,只包括可能的回合,包括 B 队(Chris)的选定玩家。

5.第 9、10、15 行:这是组装最终表格的地方。我们将 A 组的玩家分组,计算包含这些可能配对的所有排列的平均获胜概率(AVG( s.probability )为 avg_prob )。注意,虽然我们只需要按 a.id_a 列分组,但是如果我们在 SELECT 语句中也包含这些列,我们需要在 group by 语句中包含 player_aplayer_b

6.第 14 行:最后,表格按降序排列 avg_prob

一旦 Judith v Chris 配对被确认,我们可以将这些球员添加到我们数据库的阵容表中,并进入下一轮。

第二轮:轮到我们先挑了

当轮到我们先选择球员时,情况就有点复杂了,因为 Slick Jill 可以用她的选择作为回应,带来惊喜。尽管如此,我们还是可以制定一个策略,将 Slick Jill 可能对我们平均获胜概率造成的损害降到最低。换句话说,我们想要做出一个玩家选择,这将导致最高可能的平均比赛获胜概率,而不管 Slick Jill 选择谁作为响应这被称为马希民(minimax)策略。

让我们更新图 3 中的匹配矩阵。现在已经进行了一轮比赛,剩下的唯一可能的阵容是 24 种排列,其中包括米尔顿对保罗的配对。在表 3 中,在剩余的 24 个排列中,每个配对的平均匹配获胜概率被重新计算。

表 3:第一轮比赛结束后更新的比赛矩阵。我们队的最小获胜概率是通过取各行的最小值得到的。

对于对应红队玩家的每一行,以灰色突出显示的单元格对应该玩家最差的配对。如果 Slick Jill 的选择导致这些配对中的一个,那么我们的获胜前景将会急转直下!

因此,Tessa 是第二轮最安全的选择,因为她有最高的最小获胜概率(0.66)。

现在,对于 Python/SQL 实现:

请注意,第 11 到 16 行中的子查询与我们在第一轮中使用的查询非常相似,唯一的区别是缺少 WHERE 子句,当我们考虑所有可能的配对时,这是不需要的,而且我们现在是按 player_b 然后是 id_a 分组,而不是反过来。

  1. 第 12-15 行:以与上一节相同的方式连接表格,但是这次唯一可能的排列是包含 Milton v Paul 的排列。

2.第 11、16 行:按 player_b 分组,然后按 id_aplayer_a 分组,合计平均比赛获胜概率(AVG( s.probabilityavg_prob )。这产生了前面表 3 中所示的矩阵的表格形式。

3.第 9、10、17 行:通过 id_aplayer_a,对匹配矩阵表进行分组,选择每组的最小平均匹配获胜概率(MIN( avg_prob )作为 min_prob )。

4.第 16 行:请注意,Paul 的名字出现在图 10 的表格中,尽管事实上他已经在第一轮中玩过了!要删除不可能的玩家配对,有必要包含一个 HAVING 语句,过滤掉已经输入到阵容表中的玩家 id。

5.第 11 行:最后,聚集的行按降序排列 min_prob

将所有这些放在一起:

我们现在已经拥有了构建应用程序所需的所有要素!让我们来看一下我们的示例比赛,看看我们的选择策略将我们引向什么阵容。如果 Slick Jill 进行随机选择,那么我们可能会以表 4 中的阵容结束。

表 4:一个可能的最终阵容,我们使用马希民策略,而 Slick Jill 随机选择。颜色表示每一轮哪个队先拔得头筹。概率栏显示每对红队玩家的获胜概率。

我们非常有希望赢得五轮中的三轮,整体比赛获胜概率为 0.76 。在所有 120 种可能的排列中,这个阵容实际上有第五高的获胜概率,所以我们不能给自己一个更好的机会了!

虽然看起来我们有在这场比赛中击败 Slick Jill 的神奇公式,但从单个数据点得出结论是不明智的做法。在下一部分中,将应用统计方法来量化选择过程的有效性。

魔术 8 球:一个应用程序,以最大限度地赢得竞争池比赛(第三部分)

原文:https://towardsdatascience.com/magic-8-ball-an-app-to-maximize-wins-in-competitive-pool-matches-part-3-d724fdd65d9?source=collection_archive---------34-----------------------

机器学习和 SQL 如何帮助你在连续团队游戏中智胜对手

欢迎回到这个由三部分组成的数据驱动池策略系列的最后一部分!

第 1 部分中,我们探索了竞技团队台球的古怪之处,并确定台球游戏的玩家阵容选择可以通过数据科学来改进。我们开发了一个分类模型,根据过去的结果预测一个玩家击败另一个玩家的概率。

第 2 部分中,我们更进一步,用 SQL 实现了一个马希民玩家选择算法,它使用模型预测来计算最佳玩家选择。

在这最后一部分,我们将比较我们的机器学习驱动的玩家选择和现实世界的玩家选择策略,并确定我们是否真的能够持续获得超过对手的竞争优势。

第一部分:引言和预测建模。

第 2 部分:使用 SQL 制定策略。

第 3 部分:“封装”测试!

与真实策略的比较

你可能想知道队长是否真的花了很多心思在他们的球员阵容上,或者他们是否愿意让球员自己选择比赛顺序。答案是,有的不,认为对抗联盟的均衡盘口是徒劳的。然而,我们在第 1 部分中看到,尽管有障碍,我们仍然可以使用与玩家配对相关的技能余量比赛余量获胜百分比余量来准确预测一个玩家赢得这一轮的概率。

一个常用的现实生活策略是尝试让你的玩家与对手中技术相似的玩家的技术水平相匹配。这种方法背后的逻辑是,每个玩家都有信心能够击败他们同样熟练的对手。

因此,让我们将这种现实生活中的技能匹配策略与第 2 部分中开发的马希民选择算法(即我们的应用推荐)进行比较。我们可以在 1000 次模拟中比较这两种策略的表现,看看哪一种更有说服力。

对于每个模拟,使用numpy . rand()函数生成具有随机分布参数的两个五人小组。

A 队的球员选择有三种方式:

  • 策略一:选择与所选 B 队玩家技能匹配度最接近的玩家。
  • 策略二:使用马希民 app 推荐。
  • 做出随机选择。

B 队的球员选择总是随机的。

这导致每场模拟比赛有三种不同的最终阵容。这些阵容中的每一个都记录了相关的比赛获胜概率,以及根据 NAPA 规则计算的预计得分。

然后,我们可以使用概率差来量化每个策略的有效性,定义为:

**即使用策略 1 或 2 时最终阵容的比赛获胜概率减去随机选择时最终阵容的比赛获胜概率。在图 1(a)中,绘制了 1000 个模拟匹配的概率差。红色阴影对应策略 1(相似技能策略)时的 P_diff ,蓝色阴影对应策略 app 策略)时的 P_diff

图 1(a):使用 app 推荐时(蓝色)和使用相似技能策略时(红色)的 Pdiff。(二)。平均水平和使用替代策略之间的预测得分差异。图片作者。

可以看出,红色分布集中在平均值为 0 的 P_diff 上,这意味着是许多比赛的平均值,类似的技能策略不会导致比随机选择更好的结果。这很有意义,因为在本系列的第一部分中,我们已经展示了技能水平只是决定玩家获胜概率的一个因素。

另一方面,使用 app 推荐时 P_diff 的均值为 0.054,在 98.4%的模拟匹配中 P_diff 大于 0!

图 1(b)中的预测得分差异遵循正态分布,因此我们可以计算应用程序推荐方法和类似技能方法的预测得分差异均值之间的 t 检验的单侧 p 值。计算值远低于所选的𝛼=0.05 显著性水平,因此我们可以得出结论,app 推荐比使用相似技能策略产生更好的预测分数。

我们能做得更好吗?

我们已经证明,使用应用程序推荐的匹配获胜概率平均比随机选择或使用类似技能策略高 0.054%。这是我们能做的最好的吗?我们总是能得到最好的阵容吗?或者我们能增加更多的机会吗?

图 2:随机选择(红色)和使用应用程序推荐(蓝色)时,所有排列的最终阵容。图片作者。

根据排列等级来考虑是有见地的,其中最高等级排列(等级 1)是 A 队具有最高匹配获胜概率的阵容,最低等级排列(等级 120)是 A 队具有最低匹配获胜概率的阵容

图 2 显示了从 1000 次模拟中获得的每个阵容的排列等级直方图,应用程序推荐的阵容为蓝色,随机选择的阵容为红色。很明显,当使用应用程序推荐时,我们很可能会得到最好的阵容,而得到更差阵容的机会会成倍下降。只有在极其罕见的情况下,B 队才会幸运地随机选择,我们最终的阵容比 60 人的平均阵容还要糟糕。另一方面,红色分布的均匀性表明,当我们也进行随机选择时,我们同样有可能得到任何排名。

如果对手是战术天才呢?

因此,我们已经确认了我们的应用程序策略优于一个天真的随机对手,但它将如何应对一个更具战术敏锐性的队长呢?让我们考虑一下最坏的情况——让对手也能访问应用推荐。为了测试这个场景,我们模拟了 1000 场新的比赛,玩家的选择由两队的马希民策略决定。像以前一样,使用两个队的随机球员选择重复相同的比赛,以便可以为每场比赛计算 P_diff。模拟运行了两次,一次是 A 队进行第一次挑选,一次是 B 队进行第一次挑选。P_diff 分布如图 4 所示,其中团队 A 选择第一名和第二名的结果分别用浅蓝色和深蓝色绘制。

图 3:当双方队长都可以访问应用程序推荐时,1000 场模拟比赛的概率差异。浅蓝色表示 A 队先挑,深蓝色表示 A 队后挑。图片作者。

从分布来看很明显,在第一轮中无论哪个队长先选择都有一点优势![请注意,当其中一名队长随机选择时,这种优势不会出现,在这种情况下,两种分布都类似于图 1(a)中的红色分布]。

当 A 队队长先选时,71.8%的模拟比赛中 P_diff 大于 0,平均值 P_diff0.012

当他们选择第二名时,只有 28.6%的模拟比赛中 P_diff 大于 0,平均值 P_diff-0.012

这一结果具有统计学意义,采用 p <0.0001 for a Wilcoxon 符号秩检验

因此,我们可以得出令人惊讶的结果:在所有策略都相同的情况下,在许多比赛中,我们可以简单地通过选择在掷硬币获胜后首先选择一个玩家来预期比赛获胜概率的小幅正增长。

值得注意的是,从个人经验来看,这与泳池队长的普遍看法相反,他们往往不愿意主动出击!

前端和应用部署

应用程序开发的最后一步是设计一个供队长使用的前端界面。有许多奇妙的 指南用于设置使用 Flask 与 postgreSQL 数据库通信的 web 应用程序,所以我在这里不会深入研究细节。在 Heroku 上部署网络应用的一步一步的指南可以在这里找到。

相反,你可以在 http://magic8billiards.herokuapp.com/随意摆弄最终产品。使用说明可在网站的“如何使用”标签下找到。

图 4:应用视觉助手。每个点代表单个排列组合的获胜概率,暗红色的点表示仍然可能的排列组合。随着更多回合的完成,大多数阵容变得不可能,并且变灰。最后的暗红点就是最后的阵容。图片作者。

该应用的一个关键元素是视觉助手:一个动态的群集图,它将所有 120 个可能的阵容的比赛获胜概率绘制成红点。随着回合的完成,一些阵容变得不可能,这些点变灰。正如我们上面所展示的,该应用程序指导队长们选择获胜概率最高的阵容。到了第五轮,只剩下一个红点,代表最终选定的阵容。除非船长特别不走运,否则这个点应该在虫群的右边,这表示胜利的机会增加了!

收尾

祝贺这篇深入探究团队池策略特质的三部分文章结束!

在第 1 部分开发了一个概率模型之后,在第 2 部分,我们设计了 SQL 查询来识别每轮比赛中的最佳玩家选择。最后,在第 3 部分中,我们评估了这些查询在许多模拟匹配中的性能。

关键要点是:

  • 逻辑回归可以可靠地预测一个玩家在 NAPA pool 联赛中战胜另一个玩家的概率,使用技能水平、以前的胜率和比赛长度作为输入特征。
  • maxmin 玩家选择策略导致比赛获胜概率比随机选择平均提高 5.4%。
  • 在掷硬币中获胜的队长应该选择在第一轮中首先选择——即使在最坏的情况下,这也会将比赛获胜的概率提高 1.2%。

这里讨论的选择算法的应用已经超出了业余爱好者的范围。出现类似问题的一些行业场景包括:

  • 两家公司竞相从一系列可供选择的项目中赢得最多的合同。
  • 两家航空公司竞标赢得一个机场的着陆位置。

我希望这个系列已经启发你拿起一个台球杆,并检查你当地的联赛。在泳池队打球是结识新朋友的好方法,而差点系统让所有能力的球员都有愉快的经历。

图片来自 instagram.com/stevenfritters,授权给卡勒姆·安东内尔。

在 Jupyter 笔记本中进行剖析的神奇命令

原文:https://towardsdatascience.com/magic-commands-for-profiling-in-jupyter-notebook-d2ef00e29a63?source=collection_archive---------14-----------------------

入门

评估笔记本中代码的时间和内存复杂度

阿格巴洛斯Unsplash 上的照片

Jupyter 笔记本提供了与 Python 的动态交互,并允许我们创建混合了代码、文本、图像等等的文档。笔记本电脑由 IPython 驱动,IPython 通过 Python 提供交互式计算,并在许多方面扩展其功能。其中之一就是增加了魔法命令。

魔法命令简介

魔法命令是常见障碍的简洁解决方案。你可能已经遇到他们了,也许还不知道。可以通过前缀 %%%来识别。

线条魔术 VS 单元格魔术

魔法命令有两种:线条魔法 ( % 前缀)和单元格魔法 ( %% 前缀)。当单元魔法作用于整个单元时,线魔法只能作用于他们的线上。为了工作,单元格魔术必须在单元格第一行,甚至在注释之前!

让我们举一个例子来看看神奇的命令在起作用。其中最简单的是 %time ,它测量一条语句的执行时间。

通过在一个语句前面加上 %time,我们向 IPython 表明我们想要知道这一行的执行时间,结果将打印在输出中。就像我之前说的,线魔法在他们的线上运行,所以如果线被运行多次,线魔法也一样。

得到总的执行时间并不太好。不过有一个简单的解决方法: %time 也可以作为细胞魔法。让我们用% %的时间再试一次。

通过在单元格前面加上一个单元格魔术,IPython 知道它必须考虑内部的一切。

要了解更多关于一个特定的魔术命令,不需要搜索网页,一切都可以在 Jupyter 笔记本上找到。确实可以用 %your_magic_command?访问命令文档。

用于分析的神奇命令

有很多神奇的命令,对不同的场景都有用。让我们探索其中一些致力于剖析的工具。

%时间

第一个是%知道一个细胞需要运行多少次是很好。然而,从%时间开始的测量不应被视为平均运行时间,事实上,该测量仅基于一次运行,并且可能会因运行而异。

%timeit

为了获得更高的精度, %timeit 是解决方案。它将多次运行代码来计算平均执行时间及其方差。

你可以在输出中看到 7 次运行各 100000 次循环,由于我们的语句只需要很少的时间来执行,IPython 将执行它 100000 次并除以总时间以获得更精确的度量,然后这个过程重复 7 次以计算平均时间和方差。

IPython 将根据执行时间自动调整这些值,快速代码将运行很多次,较慢的代码运行较少次。然而,你也可以告诉 %timeit 你希望跑多少次。的确,你可以给魔法命令传递参数!

这里使用 -r-n 我们精确地计算出我们想要 20 次运行,每次执行语句 100 次。

更何况, %timeit 还可以当魔格用。然后,它将测量整个单元而不是单个语句的执行时间。

%prun

一个程序由许多相互作用的语句组成。您可以使用 %timeit 来评估您所有的基本代码块是否都很快,但是当运行完整的脚本时,其中一个调用另一个需要大量的时间,从而导致长时间的执行。要评估程序规模的时间性能,您需要 %prun

为了更好地理解%prun ,让我们定义一个小函数。

我们可以看到%prun 把我们的程序分解成了每个子组件。对于我们拥有的每项功能:

  • ncalls :函数被调用的次数
  • tottime :函数本身经过的总时间。
  • percall :函数调用( tottime / ncalls)所需的平均时间。
  • 累计时间:函数内部经过的、被调用的子函数的总时间。

在这个脚本中,random 被调用了 10000 次,总执行时间为 0.095 秒。由于 random 是在一个列表理解中调用的,我们可以看到列表理解的累计时间高于总时间

对于使用众多函数的更复杂的程序,读取 %prun 输出变得很困难。为了更容易理解,可以根据通过 -s. 传递的参数对输出进行排序

同样的方式,以前的%prun 在加上前缀 %%后可以用作单元格魔术。

%lprun

%prun,%lprun 允许分析整个程序的时间消耗。然而,它甚至更精确,因为它评估每一行执行时间。

默认情况下,IPython 中没有这个神奇的命令,需要进行一些安装。

根据您的安装,您可能需要使用pip In 而不是 pip3

第一行下载包含 %lprun 的模块。第二行导入它。因为魔法命令是特殊命令,它们是用特殊命令导入的,而不是用导入。%load_ext 是用来导入新魔法命令的魔法命令!

注意:!是%system 的缩写,运行终端命令的神奇命令。还记得我说过你可能已经在不知不觉中使用了魔法指令吗?

由于一个程序由许多行组成 %lprun 不会跟踪所有的行。我们需要使用 -f 来指定它必须评估哪些函数。使用多个 -f 标签可以跟踪多个功能。

在这里,我们可以看到每个代码行的研究结果:

  • Hit s:该行被执行的次数。
  • 时间:生产线使用的总时间。
  • 击一次:生产线所需的平均时间(时间 / )。
  • % 时间:该条线占用总跟踪时间的百分比。

这里函数被调用一次,不包含任何循环,所以每行被点击一次。像我们以前一样,我们可以看到矩阵创建花费了大部分时间。

%memeit

下面是两个用于内存分析的函数: %memeit%mprun。分别是 %time%prun 的记忆版。这些函数在 IPython 中是默认不存在的,我们需要安装并加载内存分析器包来使用它们。

根据您的安装,您可能需要使用pip In 而不是 pip3

然后,我们可以像 %time%timeit 一样使用它,作为线魔或者细胞魔。

在这里,我们可以看到 create_and_sum_matrix ,将系统使用的总内存增加了 35MiB,达到 88MiB。

% m 运行

%mprun%lprun 的内存版本。它允许我们在给定的函数中逐行跟踪内存消耗。但是, %mprun 有一个约束:它不能与笔记本中定义的函数一起工作。

要使用它,您需要将函数存储在 Python 文件中并导入它。很高兴,您可以使用 cell magic %%file 直接从您的笔记本中创建一个 Python 文件。魔法命令真的有解决一切的方法。

通过像这样给单元格加上前缀,它的所有代码都将保存在 my_file.py. 中。现在,我们可以导入它并使用 %mprun

我们可以看到在函数中内存是如何分配和释放的。一开始,环境已经使用了 55.4 兆字节。创建矩阵需要 4mb。但是,删除它只释放了 3.2MiB!这是由 Python 内存管理器策略造成的。如果你想了解更多,请查看这个

这也说明了为什么检查内存复杂度如此重要。使用的内存可能比我们想象的要高。

结论

评估时间和内存复杂性对于预测应用程序的资源消耗至关重要。这可以在笔记本里使用魔法命令来完成。神奇的命令实现了常见问题的解决方案。在本文中,我们介绍了其中的六种,以不同的尺度测量时间和内存消耗。

走得更远

了解更多关于魔法命令的信息:

  • %魔法:魔法命令了解更多魔法命令。
  • 文档:魔法命令的在线文档。

要了解更多关于 IPython 的信息:

  • 文档:IPython 的在线文档。

参考

[1] 关于魔法命令的 IPython 文档

[2] J. VanderPlas, Python 数据科学手册,2016

关于我

嘿!我是雷米,计算机科学专业的大四学生。两年前,我对数据科学产生了热情,从那时起,我就一直在学习和实践它。请随时在 LinkedIn 上与我联系。

posted @ 2024-10-17 11:35  绝不原创的飞龙  阅读(82)  评论(0)    收藏  举报