TowardsDataScience-博客中文翻译-2019-六十一-
TowardsDataScience 博客中文翻译 2019(六十一)
监督学习:线性回归基础
Picture from Unsplash
1.介绍
回归分析是监督机器学习的一个子领域。它旨在模拟一定数量的特征和连续目标变量之间的关系。
在回归问题中,我们试图给出一个定量的答案,比如预测房子的价格或某人看视频的秒数。
2.简单线性回归:通过数据拟合直线
有了一组点,回归算法将对单个特征(解释变量 x)和连续值响应(目标变量 y)之间的关系进行建模。
该模型将通过设置一条任意线并计算从这条线到数据点的距离来模拟这种关系。这个距离,垂直线,是残差或预测的误差。
回归算法将在每次迭代中不断移动直线,试图找到最合适的直线,换句话说,就是误差最小的直线。
有几种技术来执行这项任务,最终目标是使线更接近最大点数。
2.1 移动线
Figure by the Author
绝对的诡计
当有一个点和一条线时,目标是让线更靠近这个点。为了完成这项任务,算法将使用一个称为“学习率”的参数。该学习率是将与函数参数相乘的数字,以便在逼近直线到点时进行小步进。
换句话说,学习率将决定每次迭代中使直线更接近该点的距离长度。它通常被表示为α符号。
2.1.2 方块戏法
它基于以下前提:如果有一个点更靠近一条线,并且距离很小,那么这条线就移动一点距离。如果远的话,线会移动很多。
3。梯度下降
假设我们有一组点,我们想开发一种算法,找到最适合这组点的直线。如前所述,误差是从直线到点的距离。
移动直线并计算误差。这个过程一遍又一遍地重复,每次减少一点点误差,直到获得完美的线条。这条完美的线将是误差最小的线。为了减小这种误差,我们将使用梯度下降法。
梯度下降法是一种方法,对于每一步,该方法将观察线可以移动的不同方向,以减少误差,并采取措施减少大部分误差。
维基百科中梯度的定义:
escalar 场(f)的梯度是一个向量场。当它在 f 的定义域的一般点上求值时,它表明了 f 的快速方差的方向。
所以梯度下降会朝着负梯度的方向前进一步。
Figure by Author
当该算法采取足够的步骤时,如果学习率被设置为适当的值,它将最终达到局部或全局最小值。这是一个非常重要的细节,因为如果学习率太高,算法将会错过最小值,因为它将采取太大的步骤。而如果这个学习率太低,就需要无限的时间才能到达重点。
Figure by Author
4。梯度下降法
4.1 随机梯度下降
当梯度下降逐点进行时。
4.2 批次梯度下降
当对所有数据点应用平方或绝对技巧时,我们获得一些值来添加到模型的权重中,将它们相加,然后用这些值的总和来更新权重。
4.3 小批量梯度下降
实际上,前面两种方法都没有用,因为从计算上来说都很慢。执行线性回归的最佳方法是将数据分成许多小批。每批,点数大致相同。然后使用每个批次来更新权重。这种方法被称为小批量梯度下降。
5。更高的尺寸
当我们有一个输入列和一个输出列时,我们面临的是一个二维问题,回归是一条线。预测将是一个常数由自变量加上其他常数。
如果我们有更多的输入列,这意味着有更多的维度,输出将不再是一条线,而是平面或超平面(取决于维度的数量)。
6。多元线性回归
自变量也被称为预测因子,它是我们用来预测其他变量的变量。我们试图预测的变量被称为因变量。
当我们试图预测的结果取决于不止一个变量时,我们可以建立一个更复杂的模型,将这种更高维度考虑在内。只要它们与所面临的问题相关,使用更多的预测变量可以帮助我们获得更好的预测。
如前所述,下图显示了一个简单的线性回归:
Figure by Author
下图显示了具有两个特征的多元线性回归的拟合超平面。
Figure by Author
随着我们增加更多的预测因素,我们给问题增加了更多的维度,也变得更加难以想象,但是这个过程的核心仍然是一样的。
7。线性回归警告
线性回归有一套假设,我们应该考虑到它并不是每种情况下的最佳模型。
a)当数据为线性时,线性回归效果最佳:
它从训练数据中产生一条直线。如果训练数据中的关系不是真正的线性,我们将需要进行调整(转换训练数据)、添加特征或使用其他模型。
b)线性回归对异常值敏感:
线性回归试图拟合训练数据中的最佳直线。如果数据集有一些不符合一般模式的异常极值,线性回归模型可能会受到异常值的严重影响。我们将不得不小心这些异常值,然后正常删除。
处理异常值的一种常用方法是使用替代的回归方法,这种方法对这种极值特别稳健。这种方法被称为随机样本一致性(RNASAC)算法,该算法将模型拟合到数据的内联子集。该算法执行以下步骤:
- 它选择随机数量的样本作为内联体并拟合模型。
- 它根据拟合的模型测试所有其他数据点,并添加属于用户选择值的数据点。
- 用新点重复模型的拟合。
- 计算拟合模型相对于内层的误差。
- 如果性能满足某个用户定义的阈值或达到迭代次数,则结束算法。否则,返回第一步。
7 .。多项式回归
多项式回归是多重线性 r 回归分析的特例,其中自变量 x 和因变量 y 之间的关系被建模为 x 中的 n 次多项式。换句话说,当我们的数据分布比线性分布更复杂时,我们使用线性模型来拟合非线性数据,从而生成曲线。
由预测变量的多项式展开产生的独立(或解释)变量被称为高次项。它被用来描述非线性现象,如组织的生长速度和疾病流行的进展。
Figure by Author
8。正规化
正则化是一种广泛使用的处理过拟合的方法。这主要通过以下技术实现:
- 减少模型的规模:减少模型中可学习参数的数量,从而减少其学习能力。目标是在学习能力过多和不足之间找到一个平衡点。不幸的是,没有任何神奇的公式来确定这种平衡,它必须通过设置不同数量的参数和观察其性能来测试和评估。
- 添加权重正则化:一般来说,模型越简单越好。只要它能很好地学习,一个更简单的模型就不太可能过度拟合。实现这一点的一种常见方法是通过强制其权重仅取小值来限制网络的复杂性,从而使权重值的分布规律化。这是通过向网络的损失函数添加与具有大权重相关联的成本来实现的。成本来自两个方面:
- L1 正则化:成本与权重系数的绝对值(权重的 L1 范数)成比例。
- l2 正则化:成本与权重系数(权重的 L2 范数)的值的平方成比例
Figure by Author
要决定哪一个应用于我们的模型,建议记住以下信息并考虑我们问题的性质:
Figure by Author
- λ参数:它是通过正则化计算的误差。如果我们有一个大的λ,那么我们是在惩罚复杂性,最终会得到一个更简单的模型。如果λ很小,我们将得到一个复杂的模型。
9。评估指标
为了跟踪我们的模型执行得有多好,我们需要设置一些评估指标。该评估度量是从生成的线(或超平面)到真实点计算的误差,并且将是通过梯度下降最小化的函数。
一些最常见的回归评估指标是:
9.1 平均绝对误差:
Figure by Author
平均绝对误差或 MAE 是真实数据点和预测结果之间的绝对差值的平均值。如果我们将此作为遵循的策略,梯度下降的每一步都将减少 MAE。
Figure by Author
9.2 均方误差:
Figure by Author
均方差或 MSE 是真实数据点和预测结果之间的平方差的平均值。这种方法惩罚越大的距离,这是标准的回归问题。
如果我们以此为策略,梯度下降的每一步都会降低 MSE。这将是计算最佳拟合线的首选方法,也称为普通最小二乘法或 OLS。
Figure by Author
9.3 均方根误差
均方根误差或 RMSE 是平方误差平均值的根,它是确定回归模型性能最常用的评估指标,因为根产生的单位与 y 相同
Figure by Author
9.4 决定系数或 R
决定系数可以理解为 MSE 的标准化版本,它为模型的性能提供了更好的可解释性。
从技术上讲,R 是模型捕获的响应方差的分数,换句话说,它是响应的方差。它被定义为:
Figure by Author
10。其他算法
虽然在本文中,我们关注的是线性和多元回归模型,但是在流行的机器学习库 Sci-kit learn(这是我们将在本系列中使用的库)中,几乎每种类型的算法都有回归变量。其中一些产生了非常好的结果。
一些例子是:
- 决策树回归器
- 随机森林回归量
- 支持向量回归机
- 套索
- 弹性网
- 梯度推进回归器
- Ada 增强回归器
11.结论
在整篇文章中,我们介绍了回归模型的基础知识,学习了它们的工作原理,主要的危险以及如何应对它们。我们还了解了最常见的评估指标是什么。
我们已经设置了开始使用我们的第一个机器学习模型的知识,这正是下一篇文章将要涵盖的内容。因此,如果您想学习如何使用 Sci-kit learn 库处理回归问题,请继续关注!
如果你喜欢这篇文章,那么你可以看看我关于数据科学和机器学习的其他文章 这里 。
如果你想了解更多关于机器学习、数据科学和人工智能的知识 请在 Medium 上关注我,敬请关注我的下一篇帖子!
监督机器学习
在我们开始这篇关于监督机器学习的文章之前,我们应该对什么是机器学习以及机器学习算法如何影响我们的决策有一个清晰的概念。
什么是机器学习?
机器学习是让计算机从例子中学习的实践,通过向它们提供数据,而不是显式地编程让它们这样做。机器学习使用统计学和计算机科学来开发实现计算机学习的算法。
A traditional Computer Program Photo By Ayush Kalla
A Machine Learning Model Photo By Ayush Kalla
机器学习模型与机器学习算法
机器学习算法是一种数学和统计学的通用规则,机器遵循它来“训练自己”。
机器学习模型是真实世界数据在一个或多个机器学习算法上的实现。
例如,线性回归算法是数学和统计学中的一组规则,使我们能够将点拟合到 y = mx + c 线上。另一方面,线性回归模型将使用这种线性回归算法来表示现实世界的问题,并可以根据新的输入为我们提供新的输出。例如,线性回归模型可以为我们提供线性方程 y = 2x + 3,其中常数 2 和 3 通过应用线性回归算法来确定。该模型可以根据输入(x)生成输出(y)。
现在我们知道了机器学习,就可以谈谈监督学习了。监督学习是一种通过向机器提供以前的实例及其输出来让机器学习的技术。**例如,**给机器学习模型输入数以千计不同的猫和狗的图像,并给出正确的输出,这将允许机器在未来区分猫和狗。
Supervised Learning Photo By Ayush Kalla
分类:预测我们预测的变量属于哪一类(狗或猫)
**多类分类:**如果预测变量有 2 类以上,称为多类分类。例如,天气类型(热、雨、冷、风)。这是一个包含 4 个类别的多类别分类。
**二元分类:**如果预测变量有 2 类,称为二元分类。例如,今天会下雨吗(会还是不会)
**回归:**预测连续变量,例如股票价格、平均收入等。回归被广泛用于处理金融数据。
培训和测试数据
在机器学习中,经常建议测试我们的模型。为此,我们可以将数据分为训练数据和测试数据。
**训练数据:**训练我们的机器学习模型的数据。
**测试数据:**用于测试模型效率的数据。
过度装配和装配不足
过拟合:如果模型被训练得太多,以至于它在训练数据上表现很好,但在测试数据上却不能给出类似的结果,这就叫做过拟合。
欠拟合:如果模型训练不够,称为欠拟合。
模型的精确度
模型的准确性告诉我们,我们的模型在使用新数据时表现如何。通过将模型与测试数据的实际输出和模型预测的输出进行比较,来确定模型的准确性。模型的高精度可以表明模型是一个好的模型,它可以很好地处理实时数据,并可以部署到实践中。
如果您有任何意见、建议或问题,请告诉我,我将很高兴收到您的来信。
监督机器学习:特征工程和超参数调整
特征工程是使用数据的领域知识来创建使机器学习算法工作的特征的过程。超参数优化或调谐是为学习算法选择一组最佳超参数的问题。与选择特定的模型相比,这些对模型验证的影响更大。在这里,我提供了一步一步的特征工程和超参数调整概述。
在这里,我们深入探讨特征工程和超参数调整步骤。在我们开始更好地理解模型验证之前,看看我以前的博客。 监督机器学习:模型验证,一步一步逼近 。
我将使用来自驱动数据的数据集。数据集用于从 Taarifa 和坦桑尼亚水利部的 水位表中 数据挖掘。这是一个具有高基数特征的多类分类问题。
特色工程
正如我之前的 博客 中提到的。特征工程是指识别独立特征和从属特征之间的关系。然后,我们可以将识别的关系添加为多项式或交互特征。
特征工程步骤是连续迭代的入口点。这是一个关键步骤,与模型验证相比,它在预测中起着更大的作用。
手头问题的领域知识将对特征工程有很大的用处。在这里,我将为新的识别特性提供一些思想模型。
让我们先看一下数据。似乎存在具有高基数和 NaN 值的要素。
如果需要,我们可以删除具有高基数和 NaN 值的列。同样对于数字特征,我们可以用其平均值、中值或众数来填充 NaN 值,而不是丢弃它。同样,对于分类特征,我们可以将 NaN 归类为一个单独的类别。
同样基于地下水位数据集,我们可以设计一些特征,如:
经度和纬度中的 NaN 值用其平均值更新。
识别出资方是否至少出资了 5 台泵的二元特征。同样确定安装人员是否安装了至少 5 台泵。
基于前缀对高基数的分类特征数据进行分组。更好的方法是详细分析数据集,并尝试根据某种逻辑结构对它们进行分组。
根据同一病房其他泵的中值更新建造 _ 年份。
将日期记录拆分为年记录和月记录。甚至分组在不同箱中。
根据建造年份和记录年份计算泵的年龄。
超参数调谐
超参数优化或调整是为学习算法选择一组最优超参数的问题。同一种机器学习模型可能需要不同的约束、权重或学习速率来概括不同的数据模式。这些措施被称为超参数,必须进行调整,以便模型可以最优地解决机器学习问题。超参数优化找到超参数元组,该元组产生最佳模型,该模型最小化给定独立数据上的预定义损失函数。目标函数采用一组超参数并返回相关损失。交叉验证通常用于评估这种泛化性能。
来源: 维基百科
简而言之,超参数调优意味着找到参数的最佳值。作为其中的一部分,我们选择了一系列值来调整参数。然后根据交叉验证结果确定哪个值更合适。然后进入下一组模型参数。超参数调整是一个微妙而繁琐的比较和排除过程。
这里我们用xgb classifier进行分类。 GridSearchCV 用于与独立测试数据集的交叉验证。为了简洁起见,让我们跳过管道和 param_grid 创建的细节。详情参考之前的博客。这里我来举例说明 XGBClassifier 的参数 max_depth 和 min_child_weight 的调整。
max_depth (int) — 基础学习者的最大树深度。
- 用于控制过度拟合,因为较高的深度将允许模型学习特定样本的特定关系。
- 典型值:3–9
min_child_weight (int) —一个孩子所需实例重量的最小总和(hessian)。
- 用于控制过度拟合。较高的值会阻止模型学习可能高度特定于为树选择的特定样本的关系。
- 过高的值会导致拟合不足,因此应该使用 CV 进行调整。典型值:1–5
参数调整的第一次迭代的输出:
- **交叉验证得分:**0。46860 . 66866868661
- 最佳参数:{ ' xgb classifier _ _ max _ depth ':5,' xgb classifier _ _ min _ child _ weight ':1 }
在第一次迭代中,我们以两步递增参数值。因此,在第二次迭代中,让我们进一步缩小参数范围并进行检查。
在第二次迭代期间, max_depth 的最佳值是 5 。现在是 6 。所以在第三次迭代中,让我们再次确认 max_depth 的值。现在让我们将最小 _ 子 _ 重量参数固定为 1。
参数调整的第三次迭代的输出:
- 交叉验证分数:0。46860 . 68686868661
- 最佳参数:{ ' xgb classifier _ _ max _ depth ':6,' xgb classifier _ _ min _ child _ weight ':1 }
从第三次迭代中,我们可以确定最大深度的值为 6 。以同样的方式,我们可以选择其他参数并调整它们的优化值。
注:本博客旨在提供关于特征工程和超参数调整的快速介绍。这里的想法是理解过程,所以代码没有优化。使用这种方法来设置基线指标得分。提高我们每次迭代的模型验证分数。
在此 获取完整笔记本 。
你可能会觉得我的其他博客很有趣。一定要去看看。
参考资料:
[## XGBoost 中参数调整的完整指南(带 Python 代码)
如果在预测建模中事情没有按照你的方式发展,使用 XGboost。XGBoost 算法已经成为终极…
www.analyticsvidhya.com](https://www.analyticsvidhya.com/blog/2016/03/complete-guide-parameter-tuning-xgboost-with-codes-python/)
监督机器学习:模型验证,一步一步的方法
模型验证是在测试数据集上评估已训练模型的过程。这提供了训练模型的泛化能力。在这里,我提供了一个逐步的方法来在几分钟内完成模型验证的第一次迭代。
应用监督机器学习模型的基本方法是:
选择一类模型
选择模型超参数
使模型符合训练数据
使用模型预测新数据的标签
摘自杰克·范德普拉斯撰写的 Python 数据科学手册
Jake VanderPlas 用四个简单明了的步骤给出了模型验证的过程。在我们开始他的第一步之前,还需要一个完整的过程。比如从数据中获取我们需要的所有信息,以便对选择类模型做出良好的判断。还提供收尾工作,以确认之后的结果。我将深入讨论这些步骤,并进一步分解。
- 数据清理和争论。
- 将数据分为训练数据集和测试数据集。
- 定义模型优化的指标。
- 快速获得初始指标评估。
- 优化指标的特征工程。(第一遍跳过这个)。
- 数据预处理。
- 特征选择。
- 型号选择。
- 模型验证。
- 解读结果。
- 获得最佳模型,并对照测试数据集进行检查。
我将使用来自 UCI 机器学习库的数据集。数据集来自台湾新竹市的 输血服务中心 。这是一个分类问题。这背后的思想也延伸到回归问题。
数据清理和争论。
输血服务中心数据集是一个干净的数据集。对于大多数其他数据集来说,情况并非如此。因此,这是检查和清理数据的步骤,例如处理丢失的值…
将数据分为训练数据集和测试数据集。
有许多方法可以获得用于模型验证的训练和测试数据集,例如:
- 获取训练、验证和测试数据集的三向保持方法。
- 独立测试数据集的 k 重交叉验证。
- 独立测试数据集的留一交叉验证。
塞巴斯蒂安·拉什卡的 博客 对于确定这一点有很好的借鉴作用。
我将利用独立测试数据集进行五重交叉验证。所以把数据分成训练和测试数据集。
定义模型优化的指标。
分类和回归问题中使用的度量标准各不相同。分类问题使用准确性、精确度和召回率等指标...回归问题使用平均绝对误差、R2 分数等指标...
既然这是一个分类问题,我这里就用准确率评分。
快速获得初始指标评估。
这个步骤背后的主要思想是获得正在优化的度量的基线估计。该基线将作为模型验证的进一步步骤的参考。有几种方法可以得到分类问题的基线估计。我使用多数类进行预测。基线准确度分数约为 77% 。
优化指标的特征工程。
特征工程是使用数据的领域知识来创建使机器学习算法工作的特征的过程。特征工程是机器学习应用的基础,既困难又昂贵。
来自维基百科
这意味着识别独立特征和从属特征之间的关系。这是借助于图表,如对图或相关矩阵。然后,我们可以将识别的关系添加为多项式或交互特征。
特征工程步骤是连续迭代的入口点。这是一个关键步骤,与模型验证相比,它在预测中起着更大的作用。
作为快速解决方案,我们可以使用 sci-kit learn 中的 多项式特性添加一些多项式特性。
手头问题的领域知识将对特征工程有很大的用处。这本身就是一个更大的主题,需要投入大量的时间和资源。
数据预处理。
数据预处理将特征转换成更适合评估者的格式。一般来说,机器学习模型更喜欢数据集的标准化。在我们的例子中,我将使用鲁棒定标器。
详细信息请参考 sci-kit learn 的 预处理数据 部分。
特征选择。
数据集的特征选择或维度缩减有助于
- 要么提高模型的准确度
或者
- 来提高它们在高维数据集上的性能。
我会用 SelectKBest ,单变量特征选择法。用于分类和回归问题的评分函数会有所不同。
详细信息请参考 sci-kit learn 的 功能选择 章节。
型号选择。
由于我们正在处理分类问题,我将使用逻辑回归模型。对于回归问题,我们可以使用线性回归或岭模型。模型的选择取决于手头的问题。根据数据的复杂性,我们可以使用简单的线性模型或高级模型。
有关详细信息,请参考 sci-kit learn 的 广义线性模型 部分。
使用 sci-kit learn 的 管道 ,有一种优雅的方式可以将以上三个步骤结合起来。流水线在最终模型之前应用一系列转换。
模型验证。
超参数是模型本身不知道的参数。超参数作为参数传递给管道中步骤的构造函数。基于交叉验证分数,可以获取最佳的可能参数。
对于超参数调整**,GridSearchCV** 是选项之一。它对模型的指定参数值执行穷举搜索。这里,我们使用 param_grid 将超参数传递给管道中的步骤。 cv 设置为 5 ,因为我们要进行 5 重交叉验证。评分被设置为准确度,因为我们想要预测模型的准确度。
有关详细信息,请参考 sci-kit learn 的 调整估计器的超参数 部分。
解读结果。
GridSearchCV 返回一些重要信息,如:
- best_estimator_ ,给出最高分的评估者。利用这一点,我们可以获得关于所选特征的信息。
- **best_score_,**表示 best_estimator 的交叉验证分数。对于我们的问题集,我们在第一次迭代中得到了最好的分数 78% 。这看起来不多,但我们已经打破了我们的基线准确性得分。
- best_params_ ,给出保持数据最佳结果的参数设置。对于传递给模型的超参数,以下设置给出了最佳结果。
- 逻辑回归 __C': 1.0
- ' logistic regression _ _ class _ weight ':无
- selectkbest__k': 4
这就结束了模型验证的第一次迭代。现在,我们可以返回并重复从特征工程步骤开始的过程。在每次迭代结束时,我们可以检查准确性分数的变化。重复该过程,直到达到期望的准确度分数或选择的度量。
获得最佳模型,并对照测试数据集进行检查。
选择最终模型后,使用测试数据集检查其性能。在这里,我们在测试数据集上获得了 75%的准确率分数。
注意这个博客是为了提供一个关于监督机器学习模型验证的快速介绍。这里的想法是不要在第一次迭代中获得最佳的度量分数。使用这种方法来设置基线指标得分。提高我们每次迭代的模型验证分数。
在此 获取完整笔记本 。
你可能会觉得我的其他博客很有趣。一定要去看看。
监督组学整合
生命科学的数理统计和机器学习
结合多种生物信息来源
在这篇来自我的专栏 生命科学的数理统计和机器学习 的文章中,我将扩展分子组学集成的主题,以便更好地对生物细胞进行建模。在之前的文章中,我介绍了这个主题,并解释了为什么我们需要在进行集成之前进行特性选择。这里我将解释如何使用**【PLS】****回归和判别分析执行监督的**组学整合。
慢性淋巴细胞白血病(CLL)数据集
随着大数据在这里成为现实,多分子组学的集成代表了计算生物学和生物医学中的当代挑战。我们将在此使用的多组学生物医学数据的一个例子是对慢性淋巴细胞白血病(CLL)的研究。这项研究将药物反应与体细胞突变信息、转录组图谱分析和 DNA 甲基化测定相结合。
From Dietrich et al., Journal of Clinical Investigation, 2017, image source
几十年来,执行整合的传统生物学方法一直是组学层的成对相关。尽管其可解释性和简单性,这种方法被认为在多个组学集的情况下提供了不一致的信息。为了克服不同数据集之间技术差异的问题,组学集成的一个更有前途的想法是用潜在变量来表示每个数据集,这些潜在变量不包含它们产生的技术记忆。
PLS-DA 与 DIABLO 的集成
当来自不同组学的最具信息性特征 以其第一个 PLS 成分之间相关性的约束被选择时,潜在变量概念的最直接实施是基于偏最小二乘(PLS)回归和判别分析的多组学的多元整合。这种方法由于其简单性和在 R 包 混合组学 中的高效实现而变得非常流行。
Rohart et al., Plos Computational Biology, 2017, image source
混合组学包括几个优雅的统计算法,其中 MINT 代表跨样本整合,类似于 批量效应校正 , DIABLO 代表跨组学整合,这是真正的多组学数据整合,我们将在此用于 CLL 数据集。
CLL 经济集团与暗黑破坏神的整合
我们将从阅读 CLL 的数据开始,并用简单的中位数估算法估算缺失值。我们将使用性别作为感兴趣的特征,因此 PLS-DA 算法将跨多个组学同时执行特征的提取,这些组学在低维潜在 PLS 空间中最大化雄性和雌性之间的分离。由于我们使用性别变量指导特征提取,这是一种监督组学整合方法**。**
接下来,我们将 n=200 个 CLL 样本分成训练(n=140)和测试(n=60)数据集,用于稍后测试模型的预测准确性。由于突变代表二进制数据,由于用 0 和 1 编码,总会有一个缺少变化。因此,我们将通过排除个体间方差接近于零的位点来预过滤突变矩阵。接下来,由于基因表达和甲基化数据集是高维的,我们使用 LASSO 以我在上一篇文章中描述的方式执行特征预选。查看我的 github 笔记本中的完整代码,了解这些步骤的详细信息。接下来,我们执行交叉验证来选择预测组件的最佳数量:
Selecting optimal number of PLS components through M-fold cross-validation
分类错误率似乎在 ncomp=2 时达到其平稳状态,因此我们将使用该数量作为预测组件的最佳数量,以保留在进一步的下游分析中。上面的设计矩阵定义了组学之间的预期协方差。由于缺乏先验知识,我们在组学之间选择一个强相关 1。此外,我们将再次使用交叉验证,以便在运行稀疏 PLS-DA 时,确定每个 OMIC 的最佳特征数,用于提取LASSO最具预测性的变量。最后,在我们找到每个 OMIC 中预测成分和变量的最佳数量后,我们运行稀疏 PLS-DA 进行组学整合。
Low-dimensional latent PLS space representation of each individual OMIC
Consensus plot across OMICs as a result of OMICs integration. Males and Females are linearly separable
上面的四个图显示了进行综合特征提取后单个组学的低维 PLS 表示。相比之下,下面所谓的箭头图可以被认为是整个组学的共识图。由于使用 PLS-DA 跨组学特征提取的同时和**,它显示了非常清晰的男性和女性之间的分离。**
整合结果的生物学解释
混合组学为数据的生物学解释提供了许多令人印象深刻的可视化。在这里,我们展示了相关性 圆形图,其中叠加了来自每个组学的最高负荷的变量。围绕圆的极点的变量的聚类意味着来自组学数据集的变量之间的强相关性。相关圆图的相反极点上的变量暗示强反相关**。**
Correlation Circle Plot (left) and Circus Plot (right) demonstrate feature connection across OMICs
另一种呈现组学中最具信息特征之间相关性的方法是所谓的 Circos 图。同样,该图的变量同时选自所有组学,即它们不同于从每个单独的 OMIC 单独获得的变量。关联网络是另一种以成对方式展示组学数据集中最具信息性特征之间关联的方式。
Correlation Network demonstrate par-wise correlations between features across OMICs
暗黑破坏神综合模型预测
现在是预测的时候了。一旦我们训练了 PLS-DA 模型,我们就可以使用它并利用 60 个测试样本来预测它们的性别并评估预测的准确性:
通常,在 CLL 数据集上,从 DIABLO 整合模型预测性别的成功率(准确性)为60–70%,这并不令人惊讶,因为这是一种线性整合方法。我们可以通过人工神经网络用非线性整合模型做得更好,我将在接下来的帖子中解释。
摘要
在这篇文章中,我们了解到 PLS-DA 是一种优雅的多变量组学整合方法,它将单个数据集投影到一个公共的潜在低维空间上,在那里数据集释放了它们初始技术差异的内存。组学可以在这个共同的潜在空间中合并,并且性状类别(也称为疾病-健康)变得线性 可分离。
请在下面的评论中告诉我,生命科学中的哪些分析对你来说似乎是 T2 特别神秘的,我会在这个专栏中尝试回答这些问题。在我的 github 上查看完整的笔记本。在 Medium 关注我,在 Twitter @NikolayOskolkov 关注我,在 Linkedin 关注我。下次我们将讨论无监督组学整合方法,敬请关注。
支持向量机解释
理论、实现和可视化
支持向量机(SVM)可能是数据科学家使用的最流行的 ML 算法之一。SVM 是强大的,易于解释,并在许多情况下推广良好。在本文中,我将解释 SVM 背后的基本原理,并展示 Python 中的实现。为了简单起见,本文中我将重点讨论二进制分类问题。然而,SVM 支持多分类。
1.理论
1.1 背后的总体思路
SVM 寻求最佳决策边界,该边界将具有最高概括能力的两个类分开(为什么关注概括?我会在后面的内核部分解释)。人们问的第一个问题是 SVM 如何定义最优性。
Which decision boundary should we pick? from MIT
与通过总体概率定义最优性的逻辑回归不同,SVM 希望数据点和决策边界之间的最小距离尽可能大。换句话说,如果你把决策边界想象成街道的中心线,SVM 更喜欢 8 线高速公路,而不是乡村公路。街道的宽度被称为边缘。
from Vapnik, Support-Vector Network
1.2 数学
定义边距
好吧,这个想法很直观。让我们找出边距的表达式。在我们开始之前,请记住本文中使用的符号:
如果我们知道决策边界的权重和截距,则该边界可以由以下等式表示:
The equation for the broken line in the last figure
从数据点到边界的距离为:
from Lecture 14-Support Vector Machine, Caltech
边距是从最近点到边界的距离:
最终目标
现在我们知道了如何计算利润,让我们尝试将需要优化的问题形式化:
Final Objective
我不得不承认这是一个奇怪的函数。只要记住这一点:这就像线性回归的 RMSE,逻辑回归的交叉熵,一个需要优化的函数。
1.3 Python 实现
现在我们了解了 svm 是如何工作的,让我们试试 SVM。Scikit-Learn 提供的 SVC 功能
等等,这些参数是什么?目标中没有 C 或“内核”。你确定这是正确的功能吗?不幸的是,是的,我们只需要稍微深入一点 SVM 背后的数学。
1.4 又是理论…
现在我们需要谈谈如何优化目标函数。回想一下,该函数是:
我们究竟如何最大化这个等式?我们不能求导就完事了,因为最终的 W 和 b 可能不满足约束。幸运的是,一个高中数学班的男生来拯救我们——拉格朗日。
消除约束
拉格朗日乘子的方法是一种策略,用于寻找服从等式约束(即服从一个或多个方程必须由所选变量值精确满足的条件)的函数的局部最大值和最小值。【1】基本思想是将一个有约束的问题转换成一种形式,使得无约束问题的导数测试仍然可以应用— 维基百科
from MIT
在拉格朗日乘数的帮助下,我们可以通过求解这个函数来找到上述问题的解:
Unconstrained objective function
算出 W 和 b
现在,W,b 和α都是未知的。天哪,我们该怎么办?幸运的是,Vapnik Vladimir 为我们指出了这一点:
首先相对于 W 和 b 最小化 L(假设我们知道α)
W and b are easy to find as long as we know alpha
用我们刚找到的 W 和 b 最大化 L w.r.t。
等等,为什么这突然变成最大化了?这被称为拉格朗日对偶。
拉格朗日对偶问题:我们可以根据之前获得的 w 和 b 的关系,在α(对偶变量)上最大化,而不是在 w,b 上最小化,受到α的约束—SVM 白痴指南
上述函数有一个很好的形式,可以用二次规划软件求解。只要把这个函数和约束传递给任何商业 QP 软件,它就会返回一个阿尔法列表。现在α解出来了,就可以计算 W 和 b 了。搞定了。
1.5 什么是参数‘C’
在上面的定义中,我们假设所有点都必须在页边空白的边界上或超出它(一个所谓的硬 SVM)。实际上,通常不是这样。我们需要定义一个软 SVM,允许轻微违反规则的行为受到一些处罚:
violation of constraints, from Caltech
如您所见,C 决定了 SVM 对违规的严重程度。如果 C 是 0,那么 SVM 根本不关心违例,因为惩罚项已经没有了。如果 C 非常巨大,微小的违反将导致目标函数的巨大增量。这个函数的解可以用上面解释的相同方法导出。
1.6 什么是参数‘内核’
内核技巧是一种强大的转换技术,它将数据从原始空间投影到转换后的空间,希望使数据更具线性可分性。
Radial kernel, from An Idiot’s Guide to SVM
更严格地说,我们需要一个转换函数:
回想一下我们之前推导的目标函数:
在新的空间中,我们必须计算这个函数:
在内核转换的帮助下,我们将能够将数据映射到更高维度,并有更大的机会用超平面将它们分开。
Decision boundary obtained with kernel methods, 3 classes, from Scikit-Learn
等等,为什么我们会得到非线性的边界?SVM 应该只找到线性边界。是的,你说对了一部分!你看到的决策边界是高维空间的投影。在我们在转换后的空间中完成分类后,我们可以将超平面映射回来,边界可能会变成非线性的!
transformation of space, from Sebastian Raschka
当前转换的小问题
变换函数将数据点投影到不同的空间。当投影空间变得更加复杂时,这个过程非常耗时。在某些情况下,我们甚至不知道变换方程。应该没有办法将一个数据点映射到一个无限维的空间。还是有?
如果我们再看一下变换后的目标函数,我们可以对它进行微小的修改:
你可能会说:好吧,另一个定义,那又怎样?但是看,这是天才的部分。只要我们知道 K(xi,xj)是什么,我们就不需要变换函数。这意味着我们可以选择想要的空间,而不用担心中间的细节。有了这个,我可以定义在没有变换函数φ的情况下,变换后的空间的点积是什么样子。例如,一个无限的。
the See the proof here
您可能想知道一些著名的、经过充分测试的内核:
2.又是 Python 实现
这一次,我们理解了这些参数的含义。让我们看看每个参数的效果。
C 的影响
控制对错误分类点的关注。较大的 C 将迫使模型牺牲余量以支持正确的预测(可能导致过度拟合)
内核的影响
Effects of different kernel
优势和劣势
from Scikit-Learn.org
摘要
SVM 寻求决策边界的余量和错误分类点的数量之间的平衡。核技巧使 SVM 能够在不增加目标函数局部极小值的情况下引入强大的非线性。现在你明白了 SVM 是如何工作的,是时候在实际项目中尝试一下了!
支持向量机——公式和推导
Photo by Andy Holmes on Unsplash
预测机器学习中的定性反应称为分类。
SVM 或支持向量机是最大限度地提高利润率的分类器。在下面的例子中,分类器的目标是找到一条线或(n-1)维超平面,它将 n 维空间中的两个类分开。
在下面给出的例子中,我们看到任何学习算法都会给出所提到的任何给定的行,但是什么可能是最好的行呢?
2 dimensional representation of binary classes
直观上,绿线看起来是最佳解决方案,因为它可能会对未来的测试数据集做出更好的预测。我们通过引入一个称为边缘的参数,即在没有任何训练样本的情况下,决策边界/分类器周围的带宽,来形式化分类器的优度的概念。
因此,目标是找到具有最大余量的决策边界。我们可以将边缘视为训练区域周围的区域,决策边界不能绕过该区域。随着半径的增加,可行域减小,它收敛到一条直线。
注意:只有少数带有气泡的训练样本触及了决策边界。这些样本本质上被称为支持向量。
打破维度诅咒
1970 年,数学家 Vapnik 和 Chervonenkis 给出了 VC 维的概念,他们将未来测试误差(R(α))估计为训练误差和 VC 维的某个函数(单调递增函数)。
VC 维数 h 被写成相对裕度平方的倒数和数据维数的最小值。因此,如果我们可以最大化相对裕度,我们将最小化它的平方反比,如果它低于数据的维度,h 将变得独立于维度。
注意:相对裕度就是裕度除以包含所有训练点的圆的直径。
SVM 的提法
我们使用方法 2 并将问题公式化为:
对拉格朗日形式中的常数进行积分,我们得到:
拉格朗日乘数法规定,如前所述,对于 w 和 b,J 最小化,但是对于 α,J 必须最大化**。**J 代表的点称为鞍点。
函数 J 目前以它的原始形式表示,我们可以把它转换成它的对偶形式来求解。
同样,从拉格朗日乘子的 KKT 条件中,我们可以说 J 函数中对应于拉格朗日乘子的所有项在最优时应该趋向于 0。
这意味着非零拉格朗日系数对应于支持向量数据点。利用上述等式,我们可以将 J 写成:
Q(α)代表 对偶形式 J 它只依赖于α,其余都是已知的标量。我们可以用任何 QP 优化来求解 Q(α),这超出了本文的范围。在得到α之后,我们得到 w,从这点出发,任何一个支持向量都可以根据 KKT 条件得到 b。
非线性可分离数据
我们研究了数据是线性可分的情况。现在,我们来看看数据可能不线性分离的情况,原因是
噪声数据
对于有噪声的数据,我们在估计/优化中引入一个训练误差参数。我们引入一个松弛变量,并增加额外的条件如下
用拉格朗日系数重复同样的过程,我们得到
唯一的区别是现在拉格朗日系数有了限制。参数 C 控制训练误差和 VC 维数之间的相对权重。
非线性边界
任何具有非线性边界的数据集,如果投影到更高维度,理论上都是线性可分的。
因此 Q(α)可以写成:
我们可以将 w 和其他测试相位方程写成:
内核技巧
我们可以看到,在训练和测试中,映射都以点积的形式出现。由于我们不知道映射,我们可以找到一个函数 K(x,y) 它等价于映射的点积;我们可以避免显式映射到更高维度。
让我们举一个二次核的例子来更好地理解。
我们看到,与映射然后相乘相比,核函数的计算复杂度更低。
这个可以扩展到 n 维内核。因此,n 维映射/核可以表示为
注意:添加两个有效内核也给了我们一个内核。这很容易证明。
因此,为了映射到极高的维度,我们可以将内核计算为:
无限维度
理论上,如果映射到无限维超平面,数据集将是线性可分的。因此,如果我们能找到一个能给出无限超平面映射乘积的核,我们的工作就完成了。
这里出现了 Mercer 定理,它陈述了当且仅当 K(X,Y)是对称的、连续的和正半定的(那么 Mercer 的条件),它可以表示为
意味着高维映射的线性组合的存在是有保证的。因此,现在我们只需检查函数是否满足 Mercer 条件,就可以得到无限维的映射。
我以此结束我关于 SVM 的博客,这是我用过的最好的分类器之一,观看这个空间的更多内容。
支持向量机:用 Python 实现数字分类:包括我手写的数字
了解 SVM 系列:第三部分
在前面对 SVM 算法的详细讨论之后,我将用一个 SVM 对手写数字进行分类的应用程序来结束这个系列。这里我们将使用 MNIST 数据库来存储手写数字,并使用 SVM 对数字从 0 到 9 进行分类。原始数据集处理起来很复杂,所以我使用 Joseph Redmon 处理过的数据集。
我已经遵循了 Kaggle 竞赛程序,你可以从 kaggle 本身下载数据集。数据集基于手写数字的灰度图像,每幅图像高 28 像素,宽 28 像素。每个像素都有一个与之关联的数字,其中 0 表示暗像素,255 表示白像素。训练和测试数据集都有 785 列,其中“标签”列代表手写数字,其余 784 列代表(28,28)像素值。训练和测试数据集分别包含 60,000 和 10,000 个样本。我将使用我在上一篇文章中介绍的几个技术,比如GridSearchCV
和Pipeline
,以及一些新概念,比如用numpy
数组表示灰度图像。
我使用了来自训练和测试数据集的 12000 个样本和 5000 个样本,只是为了减少计算时间,建议使用完整的数据集来获得更好的分数,并避免选择偏差。
import math, time
import matplotlib.pyplot as plt
import numpy as np
import pandas as pdstart = time.time() MNIST_train_small_df = pd.read_csv('mnist_train_small.csv', sep=',', index_col=0)
#print MNIST_train_small_df.head(3)
print MNIST_train_small_df.shape>> (12000, 785)
我们可以通过打印出 **value_counts()**
和/或标签分布图来检查训练数据集是否偏向某些数字。
sns.countplot(MNIST_train_small_df['label'])
plt.show()# looks kinda okay# or we can just printprint MNIST_train_small_df['label'].value_counts()>>
1 1351
7 1279
3 1228
6 1208
0 1206
9 1193
4 1184
2 1176
8 1127
5 1048
Figure 1: Bar plots of sample distribution in training data set
我们看到选择稍微偏向数字 1,并且标签 1 的样本计数比样本 5 高大约 30%,即使我们使用完整的训练数据集(60,000 个样本),这个问题仍然存在。继续,是时候分开标签和像素列了,标签是数据帧的第一列。
X_tr = MNIST_train_small_df.iloc[:,1:] # iloc ensures X_tr will be a dataframe
y_tr = MNIST_train_small_df.iloc[:, 0]
然后,我将训练数据和测试数据分开,20%的样本用于测试数据。我使用了**stratify=y**
来保存标签的分布(数字)—
X_train, X_test, y_train, y_test = train_test_split(X_tr,y_tr,test_size=0.2, random_state=30, stratify=y_tr)
由于像素值在 0-255 的范围内变化,是时候使用一些标准化了,我已经使用了[StandardScaler](https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.StandardScaler.html)
,它通过移除平均值并将其缩放到单位方差来标准化特征。 同样在尝试了所有的核之后,多项式核取得了最好的成绩和最少的时间。 要了解更多关于内核的技巧,你可以查看以前的帖子。
这里我们将设置Pipeline
对象,用StandardScaler
和SVC
分别作为转换器和估计器。
steps = [('scaler', StandardScaler()), ('SVM', SVC(kernel='poly'))]
pipeline = Pipeline(steps) # define Pipeline object
为了决定C, gamma
的值,我们将使用具有 5 重交叉验证的GridSearchCV
方法。如果你想了解更多关于管道和网格搜索的知识,请查看我之前的帖子。
parameters = {'SVM__C':[0.001, 0.1, 100, 10e5], 'SVM__gamma':[10,1,0.1,0.01]}grid = GridSearchCV(pipeline, param_grid=parameters, cv=5)
现在,我们准备测试模型并找到最合适的参数。
grid.fit(X_train, y_train)print "score = %3.2f" %(grid.score(X_test, y_test))print "best parameters from train data: ", grid.best_params_>>
score = 0.96best parameters from train data: {'SVM__C': 0.001, 'SVM__gamma': 10}>>y_pred = grid.predict(X_test)
使用 12000 个样本获得了 96%的准确率,我预计使用完整的 60000 个样本后,这个分数会有所提高。GridSearchCV
部分比较耗时,如果你愿意,可以直接使用 C 和 gamma 参数。
我们可以检查一些预测
print y_pred[100:105]
print y_test[100:105]>>
[4 2 9 6 0]
1765 4
220 2
932 9
6201 6
11636 0
我们现在可以使用 python matplotlib pyplot imshow
来绘制数字。我们使用预测列表和来自测试列表的像素值进行比较。
for i in (np.random.randint(0,270,6)):
two_d = (np.reshape(X_test.values[i], (28, 28)) * 255).astype(np.uint8)
plt.title('predicted label: {0}'. format(y_pred[i]))
plt.imshow(two_d, interpolation='nearest', cmap='gray')
plt.show()
让我简单解释一下代码的第二行。由于像素值在数据集中排列成 784 列的一行,我们首先使用numpy
‘reshape’模块将其排列成 28 X 28 的数组,然后乘以 255,因为像素值最初是标准化的。请注意X_test.values
返回数据帧的‘numpy’表示。
Figure 2: Examples of digit classification on training data-set.
正如你在上面的图片中看到的,除了一个,所有的图片都被正确分类了(我认为图片(1,1)是数字 7 而不是 4)。要知道有多少数字被错误分类,我们可以打印出*混淆矩阵。*根据 scikit-learn 中给出的定义
混淆矩阵 C 使得 c(i,j)等于已知在组 I 中但预测在组 j 中的观察值的数量
print "confusion matrix: \n ", confusion_matrix(y_test, y_pred)>>[[236 0 0 1 1 2 1 0 0 0]
[ 0 264 1 1 0 0 1 1 2 0]
[ 0 1 229 1 2 0 0 0 1 1]
[ 0 0 2 232 0 3 0 2 5 2]
[ 0 1 0 0 229 1 1 0 1 4]
[ 0 0 1 4 1 201 0 0 1 2]
[ 3 1 2 0 3 3 229 0 0 0]
[ 0 1 3 0 6 0 0 241 0 5]
[ 0 0 3 6 1 2 0 0 213 0]
[ 3 1 1 0 1 0 0 1 2 230]]
因此,如果我们考虑第一行,我们可以理解,在 241 个零中,236 个被正确分类,等等..
现在,我们将对测试数据集(mnist_test.csv)重复该过程,但我没有使用GridSearchCV
来寻找 SVM (C,gamma)的最佳参数,而是使用了来自训练数据集的相同参数。
如前所述,我使用了 5000 个样本而不是 10000 个测试样本来减少时间消耗。
MNIST_df = pd.read_csv('mnist_test.csv')
MNIST_test_small = MNIST_df.iloc[0:5000]
MNIST_test_small.to_csv('mnist_test_small.csv')
MNIST_test_small_df = pd.read_csv('mnist_test_small.csv', sep=',', index_col=0)
下一步是选择特征和标签—
X_small_test = MNIST_test_small_df.iloc[:,1:]
Y_small_test = MNIST_test_small_df.iloc[:,0]
将特征和标签分为训练集和测试集
X_test_train, X_test_test, y_test_train, y_test_test = train_test_split(X_small_test,Y_small_test,test_size=0.2, random_state=30, stratify=Y_small_test)
设置Pipeline
对象
steps1 = [('scaler', StandardScaler()), ('SVM', SVC(kernel='poly'))]
pipeline1 = Pipeline(steps1) # define
设置GridSearchCV
对象,但这次我们使用通过 mnist_train.csv 文件估算的参数。
parameters1 = {'SVM__C':[grid.best_params_['SVM__C']], 'SVM__gamma':[grid.best_params_['SVM__gamma']]} grid1 = GridSearchCV(pipeline1, param_grid=parameters1, cv=5)
grid1.fit(X_test_train, y_test_train)print "score on the test data set= %3.2f" %(grid1.score(X_test_test, y_test_test))print "best parameters from train data: ", grid1.best_params_ # same as previous with training data set>>
score on the test data set= 0.93best parameters from train data: {'SVM__C': 0.001, 'SVM__gamma': 10}>>y_test_pred = grid1.predict(X_test_test)
测试数据集上的得分为 93%,而训练数据集上的得分为 96%。下面是测试数据集中的一些随机图像,与预测水平进行了比较。
Figure 3: Examples of digit classification on test data-set.
我们可以检查测试数据集的混淆矩阵,以全面了解错误分类。
print "confusion matrix: \n ", confusion_matrix(y_test_test, y_test_pred)>>[[ 91 0 0 0 0 0 0 0 1 0]
[ 0 111 2 0 1 0 0 0 0 0]
[ 0 0 98 1 0 0 1 2 4 0]
[ 0 0 1 91 0 2 0 0 4 2]
[ 0 0 0 1 95 0 0 1 0 3]
[ 0 0 1 3 1 77 4 0 3 2]
[ 1 1 1 0 2 0 85 0 2 0]
[ 0 0 0 1 0 0 0 100 0 2]
[ 0 0 1 1 0 2 0 1 93 0]
[ 0 0 0 0 4 1 0 3 3 93]]
请注意,在 92 个标签中,只有 1 个数字 0 分类错误。现在我们将继续讨论对我自己的手写图像进行分类的可能性。
对自己的手写图像进行分类:
下面是我准备数据集,然后对从 0 到 9 的数字进行分类的步骤
- 我已经使用 mypaint 首先编写(绘制)图像,然后使用 Imagemagick 来调整图像的大小,使其高度和宽度为 28X28 像素。
convert -resize 28X28! sample_image0.png sample_image0_r.png
Figure 4: Resized (28X28) My Own Hand-written Images
2.将图像转换为 numpy 数组并检查像素值是如何分布的。你可以在我的 github 上找到代码,下面是两个例子
Figure 5: Representing images with pixels using Image and Numpy
3.*将数组(28X28)展平为(784,)*转换为列表。然后写在一个 csv 文件,包括标签,即像素代表的数字。所以现在总列数是 785,与我以前使用的训练和测试 csv 文件一致。这些代码可在github.com获得。
4.把新的数据帧和测试数据帧连接起来,这样新文件就多了 10 行。
5.最后用这个新文件运行相同的分类过程,只有一个不同——训练和测试数据不是使用train_test_split
方法准备的,因为我的主要目的是看看算法如何对新数据起作用。所以我选择了前 3500 行用于训练,剩下的行(包括新数据)作为测试样本。
X_hand_train = new_file_df_hand.iloc[0:3500, 1:]
X_hand_test = new_file_df_hand.iloc[3500:5011, 1:]
y_hand_test = new_file_df_hand.iloc[3500:5011, 0]
y_hand_train = new_file_df_hand.iloc[0:3500, 0]
6.为了绘制手写图像以及它们与预测输出的匹配程度,我像以前一样使用了以下 for 循环——因为最后 1500 个样本(包括我自己的手写图像)被作为测试数据,所以循环在最后几行上进行。
for ik in range(1496, 1511, 1):
three_d = (np.reshape(X_hand_test.values[ik], (28, 28)) * 255).astype(np.uint8)
plt.title('predicted label: {0}'. format(y_hand_pred[ik]))
plt.imshow(three_d, interpolation='nearest', cmap='gray')
plt.show()
7.包括我自己手写数据在内的测试数据集上的得分是 93%。
8.让我们来看看分类器对我的笔迹从 0 到 9 的分类有多好
Figure 5: Predicted labels on my hand-written digits. 70% correct !!!
因此,10 个手写数字中有 7 个被正确分类,这很好,因为如果你与 MNIST 数据库的图像进行比较,我自己的图像是不同的,我认为一个原因是笔刷的选择。正如我意识到的,我使用的笔刷产生了更厚的图像。特别是在与 MNIST 图像比较时,我发现我的图像中边缘之间的像素比 MNIST 图像更亮(更高的像素值— > 255),这可能是 30%错误分类的原因。
我想你已经知道如何使用支持向量机来处理更现实的问题了。作为一个迷你项目,你可以使用类似的算法来分类 MNIST 时尚数据。
希望你喜欢这篇文章,如果你想了解更多关于 SVM 的基础知识,请查看我以前在这个系列中的文章。
支持向量机 Python 示例
Photo by Green Chameleon on Unsplash
支持向量机(SVM)是一种有监督的机器学习算法,能够执行分类、回归甚至离群点检测。线性 SVM 分类器的工作原理是在两个类之间画一条直线。落在线一侧的所有数据点将被标记为一类,落在线另一侧的所有数据点将被标记为第二类。听起来很简单,但是有无限多的行可供选择。我们如何知道哪一行在分类数据方面做得最好?这就是 LSVM 算法发挥作用的地方。LSVM 算法将选择一条线,该线不仅将两个类分开,而且尽可能远离最近的样本。事实上,“支持向量机”中的“支持向量”指的是从原点到指定决策边界的点所绘制的两个位置向量。
算法
假设,我们有一个向量 w ,它总是垂直于超平面(垂直于 2 维中的直线)。通过将样本的位置向量投影到向量 w 上,我们可以确定样本距离我们的决策边界有多远。快速复习一下,两个向量的点积与第一个向量到第二个向量的投影成正比。
https://commons.wikimedia.org/wiki/File:Scalar_Projection.png
如果它是一个正样本,我们将坚持认为前面的决策函数(给定样本的位置向量和 w 的点积加上某个常数)返回一个大于或等于 1 的值。
类似地,如果它是一个负样本,我们将坚持继续决策函数返回一个小于或等于-1 的值。
换句话说,我们不会考虑位于决策边界和支持向量之间的任何样本。
正如在麻省理工学院讲座中所述,为了方便起见,我们引入了一个附加变量。变量 y 对于所有正样本等于正 1,对于所有负样本等于负 1。
在乘以 y 之后,正样本和负样本的等式彼此相等。
也就是说,我们可以将约束简化为一个等式。
接下来,我们需要解决我们着手最大化利润的过程。为了得到边缘宽度的等式,我们从下面的一个中减去第一个支持向量,然后将结果乘以单位向量 w ,其中总是垂直于决策边界。
使用上面的约束和一点代数,我们得到下面的。
因此,为了选择最佳决策边界,我们必须最大化我们刚刚计算的方程。在继续之前,我们还应用了一些技巧(参考麻省理工学院讲座)。
现在,在大多数机器学习算法中,我们会使用类似梯度下降的东西来最小化所述函数,然而,对于支持向量机,我们使用拉格朗日函数。拉格朗日超出了本文的范围,但是如果你需要一个快速速成班,我推荐你去看看 汗学院 。本质上,使用拉格朗日,我们可以像在高中水平的微积分中一样求解全局最小值(即,取函数的导数并使其等于零)。拉格朗日告诉我们,通过对所有约束求和来减去成本函数,其中每个约束将乘以某个常数α(拉格朗日通常记为λ)。
然后,我们执行更多的代数运算,将上一步中找到的方程插回到原始方程中。
在我们进一步讨论之前,我们需要用矩阵来表示这个方程,而不是求和。原因是,来自 CVXOPT 库的qp
函数,我们将使用它来求解拉格朗日函数,接受非常具体的参数。因此,我们需要从:
其中:
并且:
收件人:
我们可以使用以下标识来实现这一点:
在应用它们时,我们得到:
注:X 是 X 和 y 的乘积(不要和 X 混淆)
然后,我们将变量映射到 CVXOPT 库所期望的变量。
Python 代码
现在,我们准备写一些代码。我们将从导入必要的库开始。
import numpy as np
import cvxopt
from sklearn.datasets.samples_generator import make_blobs
from sklearn.model_selection import train_test_split
from matplotlib import pyplot as plt
from sklearn.svm import LinearSVC
from sklearn.metrics import confusion_matrix
然后,我们定义我们的 SVM 类。正如我们之前提到的,我们可以使用拉格朗日函数直接求解 w 和 b ,而不是像线性回归那样使用梯度下降来寻找最佳拟合线。
class SVM:def fit(self, X, y):
n_samples, n_features = X.shape# P = X^T X
K = np.zeros((n_samples, n_samples))
for i in range(n_samples):
for j in range(n_samples):
K[i,j] = np.dot(X[i], X[j])P = cvxopt.matrix(np.outer(y, y) * K)# q = -1 (1xN)
q = cvxopt.matrix(np.ones(n_samples) * -1)# A = y^T
A = cvxopt.matrix(y, (1, n_samples))# b = 0
b = cvxopt.matrix(0.0)# -1 (NxN)
G = cvxopt.matrix(np.diag(np.ones(n_samples) * -1))# 0 (1xN)
h = cvxopt.matrix(np.zeros(n_samples))solution = cvxopt.solvers.qp(P, q, G, h, A, b)# Lagrange multipliers
a = np.ravel(solution['x'])# Lagrange have non zero lagrange multipliers
sv = a > 1e-5
ind = np.arange(len(a))[sv]
self.a = a[sv]
self.sv = X[sv]
self.sv_y = y[sv]# Intercept
self.b = 0
for n in range(len(self.a)):
self.b += self.sv_y[n]
self.b -= np.sum(self.a * self.sv_y * K[ind[n], sv])
self.b /= len(self.a)# Weights
self.w = np.zeros(n_features)
for n in range(len(self.a)):
self.w += self.a[n] * self.sv_y[n] * self.sv[n]
def project(self, X):
return np.dot(X, self.w) + self.b
def predict(self, X):
return np.sign(self.project(X))
为了简单起见,我们将使用scikit-learn
库来生成线性可分数据。我们将阴性样品标记为-1
而不是0
。cvxopt
希望数据采用特定的格式,这就是我们采取中间步骤的原因。
X, y = make_blobs(n_samples=250, centers=2,
random_state=0, cluster_std=0.60)y[y == 0] = -1tmp = np.ones(len(X))y = tmp * y
让我们通过绘制图表来感受一下这些数据。
plt.scatter(X[:, 0], X[:, 1], c=y, cmap='winter')
我们将数据分成训练集和测试集。
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)
然后,我们创建并训练我们的支持向量机类的一个实例。
svm = SVM()svm.fit(X_train, y_train)
接下来,我们绘制决策边界和支持向量。
def f(x, w, b, c=0):
return (-w[0] * x - b + c) / w[1]plt.scatter(X_train[:, 0], X_train[:, 1], c=y_train, cmap='winter')# w.x + b = 0
a0 = -4; a1 = f(a0, svm.w, svm.b)
b0 = 4; b1 = f(b0, svm.w, svm.b)
plt.plot([a0,b0], [a1,b1], 'k')# w.x + b = 1
a0 = -4; a1 = f(a0, svm.w, svm.b, 1)
b0 = 4; b1 = f(b0, svm.w, svm.b, 1)
plt.plot([a0,b0], [a1,b1], 'k--')# w.x + b = -1
a0 = -4; a1 = f(a0, svm.w, svm.b, -1)
b0 = 4; b1 = f(b0, svm.w, svm.b, -1)
plt.plot([a0,b0], [a1,b1], 'k--')
我们使用我们的模型来预测测试集中样本的类别。假设我们使用我们的模型来分类数据,我们使用混淆矩阵来评估其准确性。
y_pred = svm.predict(X_test)confusion_matrix(y_test, y_pred)
让我们使用支持向量分类器的scikit-learn
实现来尝试同样的事情。
svc = LinearSVC()svc.fit(X_train, y_train)
在训练我们的模型之后,我们绘制决策边界和支持向量。
plt.scatter(X_train[:, 0], X_train[:, 1], c=y_train, cmap='winter');
ax = plt.gca()
xlim = ax.get_xlim()
w = svc.coef_[0]
a = -w[0] / w[1]
xx = np.linspace(xlim[0], xlim[1])yy = a * xx - svc.intercept_[0] / w[1]
plt.plot(xx, yy)yy = a * xx - (svc.intercept_[0] - 1) / w[1]
plt.plot(xx, yy, 'k--')yy = a * xx - (svc.intercept_[0] + 1) / w[1]
plt.plot(xx, yy, 'k--')
同样,我们根据样本落在线的哪一侧来预测哪个样本属于哪个类别。
y_pred = svc.predict(X_test)confusion_matrix(y_test, y_pred)
正如我们所看到的,分类器正确地对每个样本进行了分类。
结论
我们看到了如何使用拉格朗日函数来确定最佳的数据分割线。在现实世界中,大多数问题都不是线性可分的。因此,我们利用一种叫做内核技巧的东西,用直线以外的东西来分离数据。请继续关注我们即将发表的关于这个主题的文章。
支持向量机——简单解释
支持向量机基本概念的简化说明
Photo by Malte Schmidt on Unsplash
我总是在逃避我的 ML 书籍中的支持向量机一章。它只是令人生畏,你知道,名称,支持,向量,机器。
但是,一旦我开始将支持向量机视为“道路机器”,它就会变得不那么可怕,它可以分离左侧、右侧的汽车、建筑物、行人,并尽可能形成最宽的车道。那些离街道很近的汽车和建筑是支持向量。
感觉好多了。让我们开始了解这个“路机是如何工作的。
本博客包括三个部分:
- 什么是支持向量机
- 在线性可分的情况下,它是如何工作的
- 在线性不可分的情况下,它是如何工作的
什么是支持向量机(分类器)
回到 ML 世界,那些汽车,建筑,行人现在都变成了点。红点代表街道左侧的物体;绿点代表右边的。街道变成了虚线和实线。
S 支持向量机(“路机”)负责寻找决策边界,以区分不同类别并最大化裕量。
边距是线条和最靠近线条的点之间的(垂直)距离。
线性可分情形下的 SVM
显然,在上面的例子中,存在无限的线来分隔红色和绿色的点。SVM 需要找到一条最优线,约束条件是要正确地分类这两类中的任何一类:
- 遵循约束:只查看单独的 超平面(例如,单独的线),正确分类的超平面
- 进行优化:选择最大化余量的一个
我将举例说明分离超平面和边界的概念,但在这篇文章中不会解释如何用约束条件来解决优化问题。
那么什么是超平面?
H 超平面是 n 维空间的(n 减 1)维子空间。对于一个 2 维空间,它的超平面将是 1 维的,这只是一条线。对于三维空间,它的超平面将是二维的,这是一个切割立方体的平面。好吧,你明白了。
Any Hyperplane can be written mathematically as above
For a 2-dimensional space, the Hyperplane, which is the line.
The dots above this line, are those x1, x2 satisfy the formula above
The dots below this line, similar logic.
什么是分离超平面?
假设标签 y 是 1(代表绿色)或-1(代表红色),下面的三条线都是分离超平面。因为它们都有相同的属性——在这条线上,是绿色的;线下面是红色的。
该属性可以用数学公式再次写成如下形式:
如果我们进一步把这两个归纳成一个,它就变成了:
S 分离超平面约束用数学方法写在上面。在完美的情况下——线性可分的情况,这个约束可以由 SVM 来满足。但是在不可分的情况下,我们需要放松它。
那么什么是保证金呢?
- 假设我们有一个超平面——X 线
- 计算所有这 40 个点到 X 线的垂直距离,将会有 40 个不同的距离
- 40 分中,最小的距离,就是我们的差距!
虚线两侧到实线之间的距离就是边距。我们可以把这条最佳线想象成红点和绿点之间最大延伸的中线。
综上所述,SVM 在线性可分的情况下:
- 约束/确保每个观察都在超平面的正确一侧
- 选择最佳线,使这些最近的点到超平面的距离最大化,即所谓的边距
线性不可分情形下的 SVM
在线性可分的情况下,SVM 试图找到使裕度最大化的超平面,条件是两个类都被正确分类。但在现实中,数据集可能永远不会线性分离,所以超平面 100%正确分类的条件永远不会满足。
SVM 通过引入两个概念来处理非线性可分的情况:软余量和内核技巧。
我们来举个例子。如果我在绿色聚类中添加一个红点,数据集就不再是线性不可分的了。这个问题有两个解决方案:
- **软边距:**尝试找到一条线来分隔,但允许一个或几个错误分类的点(例如,用红色圈出的点)
- **内核技巧:**尝试找到一个非线性决策边界
软利润
在软裕度下,SVM 容忍两种类型的错误分类:
- 该点位于决策边界的错误一侧,但位于正确一侧/边缘(如左侧所示)
- 该点位于决策边界的错误一侧和页边距的错误一侧(如右图所示)
应用软边距,SVM 容忍一些点被错误分类,并试图在找到一条最大化边距和最小化错误分类的线之间进行平衡。
容差程度
在寻找决策边界时,我们希望给出多少容差(软)是 SVM(线性和非线性解决方案)的一个重要超参数。在 Sklearn 中,它被表示为惩罚项—‘C’。C 越大,SVM 在分类错误时受到的惩罚就越多。因此,边缘越窄,决策边界将依赖的支持向量就越少。
# Default Penalty/Default Tolerance
clf = svm.SVC(kernel='linear', C=1)
# Less Penalty/More Tolearance
clf2 = svm.SVC(kernel='linear', C=0.01)
内核技巧
Kernel Trick 所做的是利用现有的特性,应用一些转换,并创建新的特性。这些新特征是 SVM 找到非线性决策边界的关键。
在 Sklearn — svm。SVC(),我们可以选择'线性','多边形',' rbf ',' sigmoid ',' precomputed '或一个 callable 作为我们的内核/转换。我将给出两个最流行的核的例子——多项式和径向基函数(RBF)。
多项式内核
将多项式内核视为一个转换器/处理器,通过应用所有现有要素的多项式组合来生成新要素。
为了说明应用多项式转换器的好处,我们举一个简单的例子:
现有特征:X = np.array([-2,-1,0,1,2])
标签:Y = np.array([1,1,0,1,1])
我们不可能找到一条线将黄色(1)和紫色(0)的点分开(如左图所示)。
但是,如果我们应用变换 X 得到:
新特征:X = np.array([4,1,0,1,4])
通过组合现有的和新的特征,我们当然可以画一条线把黄紫色的点分开(如右图所示)。
具有多项式核的支持向量机可以使用那些多项式特征生成非线性决策边界。
径向基函数核
将径向基函数核视为一个转换器/处理器,通过测量所有其他点到特定点(中心)的距离来生成新要素。最流行/最基本的 RBF 核是高斯径向基函数:
gamma (γ) 控制新特征—φ(x,center) 对决策边界的影响。灰度系数越高,特征对决策边界的影响就越大,边界的波动就越大。
为了说明应用高斯 rbf (gamma = 0.1)的好处,让我们使用相同的示例:
现有特征:X = np.array([-2,-1,0,1,2])
标签:Y = np.array([1,1,0,1,1])
同样,我们也不可能找到一条线把点分开(左手)。
但是,如果我们使用两个中心(-1,0)和(2,0)应用高斯 RBF 变换来获得新特征,那么我们将能够绘制一条线来分隔黄色紫色点(在右侧):
新特征 1: X_new1 = array([1.01,1.00,1.01,1.04,1.09)
新特征 2: X_new2 = array([1.09,1.04,1.01,1.00
# Note for how we get New Feature 1, e.g. **1.01**:
Φ(x1,center1) = np.exp(np.power(-(gamma*(x1-center1)),2)) = 1.01
# gamma = 0.1
# center1 = [-1,0]
# x1 = [-2,0]
类似于软边界中的惩罚项 C,伽马是一个超参数,当我们将 SVM 与内核结合使用时,我们可以对其进行调整。
# Gamma is small, influence is small
clf = svm.SVC(kernel='rbf', Gamma=1)
# Gamma gets bigger, influence increase, the decision boundary get wiggled
clf2 = svm.SVC(kernel='rbf', Gamma=10)
# Gamma gets too big, influence too much, the decision boundary get too wiggled
clf3 = svm.SVC(kernel='rbf', Gamma=20)
总而言之,SVM 在线性不可分的情况下:
- 通过将软裕度(误分类容忍度)和核技巧结合在一起,支持向量机能够构造线性不可分情况的决策边界。
- 像 C 或伽马这样的超参数控制着 SVM 决策边界的摆动程度。
- C 越高,SVM 在错误分类时得到的惩罚就越多,因此决策边界的波动就越小
- 伽马值越高,特征数据点对决策边界的影响越大,因此边界的摆动越大
最后,就是这样。
这个博客的代码可以在我的 GitHub 链接中找到。
优化的一个很好的解释/理由可以在链接中找到,这里是 SVM uda city 的 YouTube 视频。
请在下面留下任何评论、问题或建议。谢谢大家!
支持向量机
支持向量:从来没有这么多人欠这么少人这么多
1.问题是
支持向量机着手解决“分类”问题。如果给我们一些数据,它将由一定数量的条目/行/点组成。现在,我们想把每一个点分成几类。为了简单起见,我们假设我们只对两类感兴趣,“积极的”和“消极的”。这可能有助于回答的重要问题示例(有些比其他更重要):
- 给定像素数据,照片中是否有猫(有猫表示阳性标签)。
- 从主题、发件人、文本等方面来看,一封邮件是否是垃圾邮件。
- 确定患者是否患有某种疾病。
这个想法是,当我们已经知道正确的答案时,我们想出一些规则来将数据分成两类(对于 SVM 的,这个“规则”恰好是画一个平面,称一边的所有点为正,另一边的所有点为负)。然后,当我们遇到一个我们不知道答案的新数据点时,我们使用我们(或我们的“机器”)“学习”的相同规则来分类它。这个话题很大程度上依赖于约束优化理论,并且是一个很好的例证,我不久前在博客上写了一篇关于约束优化理论的文章。此外,我们将大致遵循吴恩达的论文。
1.1.在图片中
我觉得直到我画了画,我才真正理解了事物。还有,大家都喜欢图片。所以让我们来看一些。
我们在特征空间中有一些点。为了便于可视化,让我们考虑一个二维特征空间,这样我们可以在屏幕上看到它。我们在这个空间中散布了一些点,每个点都有一个二进制标签(1/-1)。在下图中,我们可以认为绿点代表正标签,红点代表负标签。对于黄点,我们不知道它们的标签是什么(正面还是负面)。如果让你猜一个标签,你会选哪个?你可能会发现有些观点并不明确。
Fig 1: 2-D classification problem. Green points are positive and red ones are negative. Can you guess the labels for the yellow points? Created using: https://github.com/ryu577/pyray
现在,如果我画一条紫色的线来分隔这两个类,那么每个黄色点应该属于哪个类就变得更加清楚了(线上的任何东西都是绿色的,线下的任何东西都是红色的)。
Fig 2: Drawing a separating line gives us a “rule” for assigning positive and negative labels. Now, we can use that rule to label each of the yellow points. Created using: https://github.com/ryu577/pyray
然而,上面这条线并不是唯一的。有多条紫色的线完美的分隔了绿色和红色的点。下图显示了其中的一些。当我们在这些线之间切换时,一些黄色点的含义很严重(它们最终位于线的不同侧,因此会根据线的选择翻转它们的标签)。
Fig 3: There could be multiple separating lines that split the red points from the green perfectly well. Which of these lines should be choose? Created using: https://github.com/ryu577/pyray
所以,在所有候选线路中,问题是哪一条是“最好的”?从上面的图 3 中可以清楚地看出,当紫色线靠近右下角的红点时,它似乎不能很好地概括,而当它远离该点时,它看起来像是一条更好的分隔线。因此,似乎有一点决定了这条线有多好,使它变得“至关重要”。可以说,远离该红点的线尽可能远离所有训练示例,而不必要地靠近该红点的线最终看起来不如分类器那么好。因此,即使是最接近的训练样本,最终也会被推离自己很远的线会成为好的分类器。我们将在第 3 节更具体地阐述这一观点。但首先,让我们学习用数学画线。
2.画线
所以我们想画一条分隔线(或者只是一条一般的线)(在二维空间;它将是高维空间中的超平面)。那么,什么是线呢?它是有共同点的点的无限集合。它们都满足某个等式。为了找到这个方程,让我们从最简单的 x 轴开始。上面各点的位置向量有什么共同点?它们看起来都像:v_x = [x,0]意味着它们的 y 坐标为零。
另一种说法是,其上每个点的位置向量都与指向 y 轴方向的向量正交(垂直)。
第二个陈述可能看起来像是用一种奇怪而复杂的方式来表达更简单的东西,但这种方式很重要,因为它对所有行都适用,而不仅仅是这个 x 轴。这很好,因为我们不关心 x 轴本身。我们真的希望能够推广到任何行。一步一步来,让我们首先考虑穿过原点的直线(如 x 轴)。这些线可以通过简单地将 x 轴旋转某个角度来获得,如下图所示。
Fig 4: Rotating the x-axis can give us any line passing through the origin. And for all these lines, every point on them will be perpendicular to the orange vector.
当线改变时,恰好垂直于它的向量也改变,但是线上每个点的位置向量垂直于某个向量的事实对于所有线都是不变的。让我们称这个向量为 w 为通过原点的一般直线。当我们改变 w 时,我们将捕获所有这样的线。
注意,对于任何给定的行,也有多个值 w 。本质上,如果我们把它放大或缩小任意倍,直线上每个点的位置向量都垂直于它的事实不会改变。
Fig 5: Orthogonal w vector scaling up and down.
那么,为什么不把我们自己限制在大小为 1 的向量上呢?从现在开始,让我们假设任何时候我们谈论一个名为 w 的向量,它的大小都是 1。
所以现在我们已经成功地参数化了所有经过原点的线。那些没有的呢?我们可以通过将穿过原点的其中一条线向 w 的方向移动一定量 b ,得到这样一条线。现在, w 与直线上任意一点的位置矢量的点积不为零。但是,还是不变, b 。从下面的图 6 中可以清楚地看到这一点。w 矢量是一个单位矢量,从原点指向线(紫色)并与之垂直。a 是直线上离原点最近的点。假设距离 OA 为 -b 。现在,考虑两个随机点 B 和 C(绿色和橙色)。如果你取 OB 或 OC 与单位向量 w 的点积,你就分别得到三角形 OAB 和 OAC 的底边。而且这两种情况下,这只是 OA,也就是 -b 。由于这两个点是直线上的任意点,我们可以得出结论,直线上的所有点都将满足 w^T x+b=0 (其中 x 是点的位置向量,即上面两个示例点的 OB 和 OC)。
Fig 6: A line that doesn’t necessarily pass through the origin.
当我们把一个不在直线上的点代入上面推导出的直线的方程,会发生什么?我们得到一个不为零的数,当然,但它也恰好是点到直线的垂直距离(所以对于直线上的点,这是预期的零)。值得注意的是,这个结论只有在 |w|=1 时才成立,正如我们一直要求的那样。下图应该清楚地表明了这一结果。我们取任意一点,B 不在直线上。然后,我们从紫色线 B "和代表 w 矢量的线 B '上的 B 点开始画垂线。从 B 到直线的垂直距离由图中的 BB”给出。但是由于 A-B'-B-B ' '形成一个矩形,这个距离等于 AB'=OB'-OA。现在,OB '只是 B (OB)的位置向量与 w 的点积,所以,如果 x 是 b 的位置向量,那么|OB'| = w^T x 。这意味着|AB'|= w^T x-(-b) (回想一下 OA= -b )。所以点到直线的垂直距离变成:|AB'|= w^T x+b ,这是直线的方程。
Fig 7: What happens when we plug a point not on the line into its equation? We get the perpendicular distance between the point and the line.
请注意,插入电源时, w 指向的线一侧的所有点(如图 7 中的 B 点)的垂直距离为正,而另一侧的点的垂直距离为负。
但是,所有位于 w 点一侧的点都有一个正标号( t_i=1 ),位于另一侧的点都有一个负标号( t_i=-1 )。因此,如果我们将标注与垂直距离相乘,只要这些点被线正确分类,调整后的垂直距离对所有点都是正的(即标注为正的点位于一侧,标注为负的点位于另一侧)。
3.最佳路线
现在来看看支持向量机的妙处。我们称调整后的任意点到直线的垂直距离为该点的边距。任何给定的线对于所有点都有一些边距(如果该点被该线正确分类,这些边距将为正,否则为负)。我们希望线条能够很好地区分积极和消极。换句话说,边距应该尽可能大,即使是最靠近边界(分离平面)的点也是如此。这与我们在 1.1 节末尾讨论的想法是一致的。
因此,最大化甚至最差裕量的平面应该很好地分离点。现在,给定一个( w,b )组合,第 I 个点的余量将由下式给出( x_i 是特征空间中的位置向量, t_i 是标签:1 表示正,1 表示负):
Equation of the margin.
所有点的最小余量变成:
Eq (1): The minimum margin across all points.
我们希望( w,b )对最大化这个最小余量。换句话说,我们想要:
换句话说,我们想要满足 |w|=1 并最大化余量的( w,b )对:
Eq(2): The SVM objective function.
注意,如果该行没有分隔数据,那么对于那个( w,b )组合,术语:
Equation of the margin.
某些点会是负的。其中一个点会在第一次最小化中胜出。这将意味着那些( w,b )组合永远不会在第二个 arg max 中“胜出”。所以,这确保了获胜的( w,b )组合将总是分离数据,如果数据是可分离的话。
等式(2)是一个优化问题,包括最小化和最大化(mini-max)。解决只涉及一级优化而不是两级优化的问题要容易得多。所以,我们试着把它转化为一个约束优化问题。
让我们回到将跨越所有点的最小余量称为 γ 的问题上来。
Eq (3): The constraints
最终的优化问题变成了:
Eq (4): SVM optimization problem
这是一个带有二次/线性约束和线性目标函数的优化问题。它可以用二次规划求解器(我们将在后面看到一些代码)求解,并获得最佳分离线/平面( w,b 组合)。
现在,让我们看看是否可以进一步简化它。原来,有一种方法可以摆脱 γ 。这是有代价的——我们必须放弃 w^t w = 1 T3 的要求。但是考虑到简化,这是值得的。让我们以它来划分两边的约束。我们得到:
Eq (5): Divide plane equation by gamma.
现在,设置:
Introducing a new w variable.
取两边的模数,
Take modulus
但是,我们一直要求 |w|=1 。这意味着:
此外,等式(3)现在变成:
Eq (6)
等式(5)和(6)产生等式(4)中的优化问题:
到目前为止,优化问题有一个丑陋的目标函数。但是最大化 1/|w| 和最小化 |w| 是一回事,和最小化 |w| 是一回事。增加 1/2 会让以后的生活稍微轻松一点。
所以,我们可以把它重新表述为:
Eq (7)
这现在是一个具有二次目标函数和线性约束的优化问题(线性约束二次规划或 LCQP)。它可以用各种语言的二次规划求解器来解决。
我们现在知道如何通过解决一个优化问题来找到最优线。透过表面看这些类型的优化问题是如何解决的(通过拉格朗日乘数)会给我们对问题的强烈洞察力和直觉。请继续关注第 2 部分(此处为),在这一部分中,我们将完成这一过程,并展示一些玩具示例。
支持向量机分类
了解支持向量机(SVM),从直觉到实现
机器学习中的分类是学习区分数据集中属于两个或更多类别的点的任务。在几何术语中,将一组点与某个类别相关联涉及找到这些点之间的最佳可能分离。假设我们有一个类似这样的数据集:
Figure 1. Dataset representation and margin
在这里,我们可以清楚地区分两类,分别用 C1 = 1 和 C2 = -1 来标识。我们也将这定义为一个二元分类问题。例如,如果我们的每个数据点都代表电子邮件文本,并且我们希望将这些分类为垃圾邮件和非垃圾邮件,那么我们将每封电子邮件都是一个数据点 x ,而 y = 1 将识别垃圾邮件, y = -1 非垃圾邮件。同样,我们还可以有其他类似的场景,比如猫狗分类、信用/非信用批准等。
在图 1 中,我们还可以看到,中间的线性函数确保了两个类别之间的最佳分离。我们故意称之为超平面的原因是因为我们这里的描述可以扩展到多维场景。例如,如果我们在 3D 空间中工作,我们将有一个分割平面而不是一条线。
从现在起,我们将分类数据集之间的分离标识为边缘、,并且它将由最近点和分离超平面之间形成的距离来管理。因此,立即出现的问题是,我们如何确保这个最佳超平面确保两个类别的最佳可能余量?这正是支持向量机,或简称 SVM 将为我们做的。
在继续之前,值得指出的是,支持向量机是用于分类任务的最强大的机器学习算法之一,广泛用于从计算机视觉到 NLP 的应用。让我们进一步探讨这个方法。
导出原始问题
首先,假设我们的数据集由 N 个点组成。在图 1 中,我们可以看到,通过使用由下式定义的线性函数(即超平面),可以很好地分离这两个类别:
这里, x n 表示一个数据点, w 是一个权重向量, b 是偏差, y n 是模型的预测。在这种情况下,对于位于超平面两侧的点,每个预测可以是 1 或-1,对于位于超平面本身上的点,每个预测可以是 0。给定一个包含几个 x 及其对应的 y 的数据集,我们想要做的是找到给我们最好的可能余量的 w 和 b 的值。
为了更清楚,让我们用几何图形来说明我们的模型变量:
Figure 2. Geometric representation of variables
这里,xn是最接近超平面的点之一,并且它形成了源自该点的正交向量 d 。我们可以看到,矢量 d 与 w 方向相同。此外,位于超平面上的任何一点 x0 都会与xn形成一个矢量 r 。根据这些定义,我们可以清楚地看到 d 是 r 在 w 上的投影,由下式给出:****
让我们把 b 和- b 加到这个等式的分子上。 d 的大小将给出 x 到超平面的距离,定义如下:
注意,对于位于超平面上的 x0 ,其对应的预测 y0 为零,这就是括号内的表达式消失的原因。所以为了找到最优余量,我们要做的就是最大化 d 。有了这些考虑,我们最终可以陈述模型的优化问题:
嗯,从微积分我们知道,为了找到最大值,我们需要使用导数。在这种情况下,我们使用不涉及对等术语的表达会更方便。那么,我们怎样才能使 dd方程更容易优化呢?是的,你猜对了!将括号内的倒数项倒置,然后将其转化为最小化问题。让我们这样做:
Equation 1. Optimal distance expression
所以现在你可能会问,为什么我们把 w 的幂提高到 2,然后除以 2?这只是我们在计算导数时,为了让事情变得简单而应用的一个数学技巧。基本上,主要原因是这个表达式的导数就是 w 。然而,最重要的是,这将帮助我们定义一个二次规划问题,我们将能够使用流行的优化库来解决这个问题,我们将在后面看到。
好了,现在我们已经定义了优化问题的一部分。但是,让我们更深入地看看这个限制:
我们可以看到,这涉及到一个绝对值。看起来不太好,对吧?如果我们能摆脱它就好了。怎么才能做到呢?让我们稍微想想我们预测的正确性。我们希望我们的模型尽最大努力对所有点进行正确分类。但是我们如何用数学术语定义一个正确分类的点呢?让我们首先介绍一些有用的符号。
所以我们希望我们的模型做出与正确答案 yn 相等的预测。当给出的答案和预测的答案符号相同时,就会发生这种情况。也就是说,当两者的乘积至少为 1 时。让我们用数学表达式来表述:
Equation 2. Modified restriction
太好了!有了这个限制,以及等式 1,我们的优化问题将如下:
Equation 3. Expression for the primal problem
这个表达式定义了支持向量机的主要问题。请注意,对于由( x n , yn )形成的每个限制,都有一个关联的 Langrange 乘数 α 。阿尔法值大于零的数据点xn 也被称为支持向量,因为它们影响分离超平面的行为。
此外,如果我们看一下等式 3,我们可以看到它在 w 上有一个二次型。因此我们可以说这是一个二次规划问题。然而,我们这里有一个问题,这个问题取决于三个变量,而不是一个。让它只依赖于一个参数集肯定会让事情变得更简单,这将激发我们对下一节讨论的对偶问题的推导。
定义对偶问题
在上一节中,我们阐述了 SVM 的原始问题。然而,正如我们之前讨论的,让它依赖于一个参数会容易得多。让我们现在做那件事。
如果我们计算等式 3 中的 L 相对于 w 和 b 的导数,然后使导数等于零,我们得到:
从这里,我们得到:
替换等式 3 中的这两个表达式,我们得到:
重新排列:
Equation 4
嗯,正如我们所看到的,这已经成为一个二次规划问题,它只取决于拉格朗日乘数 α ,而不再取决于w和 b 。这肯定比我们之前讨论的原始问题要简单得多。除此之外,关于等式 4 中xm和x n 的产生还有一个有趣的方面。原来这个产品其实可以表述为一个内核函数。一般来说,核函数允许我们将非线性可分空间转换为线性可分空间,并且当我们试图执行不同的分类任务时,它是一个有用的工具。通常使用的核包括但不限于线性核和径向基函数(RBF)。更多关于内核方法的信息可以在【2】这里找到。
最后,对偶问题可以表述如下:
Equation 5. Dual problem for SVM
这是一个最大化的二次规划问题。这里, k 是我们定义的一个核函数。另外,请注意第一个限制,它强制所有字母大于或等于零。如前所述,阿尔法值大于零的数据点是支持向量,并影响分离超平面的行为。此外,如果我们将此转化为最小化问题,并将这些表达式转换为矩阵形式,我们可以很容易地使用 CVXOPT 等优化库来求解最佳参数。我们将在后面看到如何做到这一点。
我们对对偶问题的定义在这里有一个重要的限制。只有当类别可以完全分离时,它才能很好地工作。这就是为什么这个默认版本也被称为硬边际 SVM 。但是你可以想象,我们不太可能在现实生活中找到完全分离的数据集。因此,我们接下来将讨论一种变体,它允许我们将支持向量机扩展到一些点可能被错误分类的场景,也称为软裕度 SVM 。
软利润 SVM
如前所述,硬边界支持向量机在实际应用中用途有限。在这里,我们将表明,通过对原始对偶问题做一点小小的改变,我们可以将支持向量机扩展到一些点可能被错误分类的场景。让我们用图表来说明我们的想法:
Figure 3. Misclassification scenarios for the soft-margin SVM
这里,我们定义了一个新的公差变量ε。位于边缘的点的ε = 0。另一方面,我们离正确的边界越远,ε的值就越大。最终,对于在超平面错误一侧的点,我们期望ε大于 1。我们现在需要做的是,把这个新变量插入到原始问题的初始定义中。因此,如果我们将ε加入等式 2 中定义的限制条件,我们会得到:
这意味着我们的限制现在允许一些点离边界更远一点。ε本身现在成为另一个参数,我们必须在我们的主要问题中考虑,我们必须努力使它最小化。在这种情况下,我们的目标是:
如我们所见,这里的第二项是我们定义的一个新变量 C 和所有ε之和的乘积。这将迫使当 C 较大时,由ε值给出的总体错误分类将较小。这意味着, C 越大,保证金就越严格。通过考虑原始问题中的这些新变量,我们得到:
Equation 6
这里,μ是我们为公差值ε定义的拉格朗日乘数。我们期望每个μ大于或等于零。现在让我们相对于 w 、 b 和ε来区分 L 。
从这里,我们得到:
让我们把注意力稍微转向第三个表达。我们之前说过,μ和 α 都可以大于或等于零,这意味着:
然后,通过替换等式 6 中的所有这些表达式,并像我们对硬边界 SVM 情况所做的那样重新排列,我们得到以下结果:
Equation 7. Dual problem for the soft-margin SVM
太好了!在这一点上,我们可以看到,除了现在考虑到 C 的第一个限制之外,一切都与硬边际 SVM 的情况相同。在下一节中,我们将通过使用一个玩具数据集来实现一个软边界 SVM,我们将使用 CVXOPT 进行优化。
用 CVXOPT 实现软利润 SVM
注意:完整的实现可以在https://bit.ly/2xBDJ2Q的 Jupyter 笔记本上获得
CVXOPT [3]是一个用于凸优化的 Python 库。我们将用它来解决软间隔支持向量机的对偶问题。然而,在此之前,我们需要将这样一个对偶问题转化为一个最小化目标,然后将所有变量转化为矩阵。为了将对偶问题转化为最小化问题,我们只需反转等式 7 中拉格朗日量的符号,然后将其表示为矩阵形式:
在哪里
这里,我们使用了*操作符来表示 Python 中的逐元素乘法。此外, K 是通过计算整个数据集 X 的核值而得到的 Gram 矩阵。
现在以矩阵形式表示的限制如下:
现在,CVXOPT 将需要一个特殊的符号来配置我们的对偶问题,以及我们的限制。本质上,我们需要做的是配置以下矩阵:
使用 CVXOPT 的相应 Python 代码如下:
最后的容差参数定义了在声明收敛之前我们允许的变化量。如你所见, solvers.qp 调用接收我们配置的所有矩阵,它将打印出每个时期的成本值,直到收敛。
一旦我们的 SVM 被完全训练,我们可以通过使用下面的表达式容易地获得参数 w 和 b :
其中 S 是支持向量的子集。相应的实现如下:
为了便于说明,我们使用两个自己生成的数据集测试了这个实现。第一个数据集是线性可分的,第二个数据集包含可以用圆圈分隔的类别。这是两个数据集的图表:
Figure 4. Dataset graphs
在这两种情况下,我们可以看到属于第一类和第二类的点分别被染成红色和蓝色。同样,黑色的点是我们找到的支持向量。通过适当配置 C 参数,我们应该可以看到不同的裕量行为。
此外,第二数据集不是线性可分的。在这些情况下,我们所做的就是使用内核技巧。也就是说,我们使用一个核函数,将我们从某个空间中的非线性可分数据集带到另一个空间中的线性可分数据集。特别是,我们在本例中处理第二个数据集的方法是使用 RBF 而不是线性核。
线性核和 RBF 可以分别通过这些表达式来计算:
其中γ是我们为 RBF 情况设置的超参数。这些内核的相应实现如下所示:
结束语
支持向量机是一种非常强大的机器学习模型。尽管我们的注意力主要集中在用于二元分类的支持向量机上,但我们可以通过使用一对一或一对一等技术将它们的使用扩展到多类场景,这涉及到为每一对类创建一个 SVM。我强烈建议您进一步研究实现,以及我们如何使用流行的库来训练 SVM,例如 *sklearn。*在这里,您需要为 C 选择合适的值,以及一个合适的内核以获得更好的分类结果。
参考
[1] Bishop,Christopher M. 模式识别和机器学习 (2006)施普林格出版社柏林,海德堡。
[2]托马斯·霍夫曼。伯恩哈德·肖科普夫。《机器学习中的核心方法》 (2008)统计年鉴。第 36 卷,第 3 卷,1171-1220 页。
[3] CVXOPT。解一个二次规划。在 https://cvxopt.org/examples/tutorial/qp.html[有售](https://cvxopt.org/examples/tutorial/qp.html)
[4]加州理工学院。从数据中学习 (2012)。在https://work.caltech.edu/telecourse上市
支持向量机和不平衡数据
在不平衡数据集的情况下,SVM 是如何工作的?
内容:
- 支持向量机简介
- 观察 SVM 在不平衡数据集的情况下如何工作。
- 观察超平面如何根据正则项的变化而变化。
支持向量机简介
在机器学习中,支持向量机器是具有相关学习算法的监督学习模型,其分析用于分类和回归分析的数据。给定一组训练样本,每个样本被标记为属于两个类别中的一个或另一个,SVM 训练算法建立一个模型,将新样本分配给一个类别或另一个类别。
在 SVM,超平面是以这样的方式选择的,它与两个类都是等距的,并且距离最短。
迷茫?看看下面的解释。
Figure 1
我们假设,红点是 1 类,绿点是 2 类。
现在,如果要我画一个阈值来区分这两个类别,我可以画出来,实际上有 n 种方法。
Figure 2
当我画一个如图 2 所示的边距时会发生什么?左边的任何东西都将被归类为红点,右边的任何东西都将被归类为绿点。
我们来分析一下。
Figure 3
这个新点可以归为红点,也就是 1 类。
Figure 4
这个新点可以归为绿点,也就是 2 类。
好吧!那是非常直接的。但是让我们看看下面的情况。
Figure 5
这个新点将被归类为绿点,因为它位于右侧。根据阈值,是的,这是一个正确的分类。但这真的对吗?不要!
该点离红点近得多,离绿点远得多。所以,这是一个错误的分类。
那我们怎么决定合适的阈值呢?
Figure 6
让我们把注意力集中在这两个类的边缘的观察上。现在让我们画一个阈值,这样它到两点的距离是相等的。
Figure 7
现在,该阈值左侧的任何点都将比绿点更靠近红点,因此将被归类为红点。右边的任何一点都是绿点。
Figure 8
边缘观察被称为支持向量。
观察值和阈值之间的最短距离称为裕度。当阈值在两个观察值的中间时,差值尽可能大。
现在让我们开始吧……
SVM 和不平衡数据
首先,让我们创建不平衡数据集,每个数据集都有正类和负类。
数据集 1-100 个正点和 2 个负点
数据集 2-100 个正点和 20 个负点
数据集 3-100 个正点和 40 个负点
数据集 4-100 个正点和 80 个负点
import numpy as np
import matplotlib.pyplot as plt
ratios = [(100,2), (100, 20), (100, 40), (100, 80)]
plt.figure(figsize = (20,6))
for j,i in enumerate(ratios):
plt.subplot(1, 4, j+1)
X_p=np.random.normal(0,0.05,size=(i[0],2))
X_n=np.random.normal(0.13,0.02,size=(i[1],2))
y_p=np.array([1]*i[0]).reshape(-1,1)
y_n=np.array([0]*i[1]).reshape(-1,1)
X=np.vstack((X_p,X_n))
y=np.vstack((y_p,y_n))
plt.title(“Dataset “ + str(j+1)+ “: “ +str(i))
plt.scatter(X_p[:,0],X_p[:,1])
plt.scatter(X_n[:,0],X_n[:,1],color=’red’)
plt.show()
这段代码将创建 4 个不同的数据集。这些数据集如下所示:
Figure 9
现在,您已经看到了我们的数据集的样子,让我们继续。
现在我们要画一个分离这些点的超平面。我们将考虑正则项的 3 个不同值,并在不平衡数据集上观察超平面如何随着正则项的变化而变化。
我们只需要添加几行代码来完成我们的代码。因此,更新后的代码如下所示:
def draw_line(coef,intercept, mi, ma):
points=np.array([[((-coef[1]*mi — intercept)/coef[0]), mi],
[((-coef[1]*ma — intercept)/coef[0]), ma]])
plt.plot(points[:,0], points[:,1])
上面的代码是画出分隔点的线。
c = [0.001,1,100]
plt.figure(figsize = (20,30))
ratios = [(100,2), (100, 20), (100, 40), (100, 80)]
num=1
for j,i in enumerate(ratios):
for k in range(0, 3):
model=LinearSVC(C=c[k])
plt.subplot(4, 3, num)
num=num+1
X_p=np.random.normal(0,0.05,size=(i[0],2))
X_n=np.random.normal(0.13,0.02,size=(i[1],2))
y_p=np.array([1]*i[0]).reshape(-1,1)
y_n=np.array([0]*i[1]).reshape(-1,1)
X=np.vstack((X_p,X_n))
y=np.vstack((y_p,y_n))
model.fit(X,y)
plt.scatter(X_p[:,0],X_p[:,1])
plt.scatter(X_n[:,0],X_n[:,1],color=’red’)
plt.title(‘C = ‘+ str(c[k])+str(i))
draw_line(coef=model.coef_[0],intercept=model.intercept_,ma= max(X[:,1]), mi= min(X[:,1]))
plt.show()
输出:
Figure 10
观察
- 当 c = 0.001 时
由于 c 非常小,模型无法对数据进行分类,我们可以观察到超平面位置离数据点非常远。数据平衡或不平衡在这里没有任何区别,因为 c 值非常小。
2.当 c = 1 时
超平面远离数据点,可以说该模型不能对不平衡数据集进行分类。在最后一种情况下,数据集几乎是平衡的,我们可以看到,该模型可以分类有位错误,但这似乎只有在数据平衡的情况下才能很好地工作。
3.当 c = 100 时
即使 c 值很高,该模型也无法对高度不平衡的数据集进行分类。因此,我们可以得出结论,该模型效果不佳,或者当数据集高度不平衡时,不建议使用该模型。随着数据的增加,模型在分类方面做得非常好。
参考资料:
在机器学习中,支持向量机(SVMs,也称为支持向量网络)是一种有监督的学习模型
en.wikipedia.org](https://en.wikipedia.org/wiki/Support-vector_machine)
应用人工智能课程—https://www.appliedaicourse.com/
从零开始的核支持向量机
从最大间距分隔符到内核技巧的逐步数学和实现
从 20 世纪 90 年代末,直到深度学习的兴起,具有非线性核的支持向量机(SVM)一直是领先的算法。他们能够解决像逻辑回归这样的线性分类器无法解决的许多非线性问题。最简单和最著名的例子是一个数据集,其标签分布类似于异或(XOR)真值表。
SVM 是由机器学习的主要理论家之一 Vladimir Vapnik [1]于 1992 年至 1995 年提出的。他与人合著了 Vapnik-Chervonenkis 机器学习理论[2]。
SVM 背后有三个主要想法:
- 最大空白分隔符:画一条线或超平面,使分隔符和训练数据之间的距离最大化,从而引入一个空白层
- 软页边距分隔符:当不同标签的数据混淆时,考虑页边距内的样本,画出最佳分隔线
- 内核技巧:对于数据分离边界不是线性的更复杂的模型,允许使用高阶多项式甚至非多项式函数
Dataset looking like the exclusive-or (XOR) truth table © the author
为了更好地理解这些想法,我们将按顺序逐一解释。每次我们都会提供支持数学的摘要。完整的 Python 笔记本在 Github 上有 HTML 或者 木星 。
有两种方法来安装 SVM:
- 通过使用更新规则的梯度下降
- 使用求解器和拉格朗日原始或对偶形式的问题陈述
在本文中,使用的是第二种解决方案。
1.最大边距分隔符
使用几何解释可以更好地理解 SVM。给定一个 p 维的向量空间,我们想用一个超平面(如果 p=2,则是一条直线,即 2D 平面)来分隔它,使得标签为 1 的训练数据在超平面的一侧,标签为-1 的训练数据在超平面的另一侧。
超平面方程是:
其中 w 是与超平面正交的向量,b 是相对于原点定位超平面的偏差。
给定一个向量 x 和{-1,1}中相应的二进制标号 y,到超平面的有符号距离是:
© the author
宽度 M 的最大边距分隔符的表达式为:
这个优化问题可以被重写为对偶拉格朗日问题,并且由求解器提供解决方案。
Maximum margin separator © the author
边距边界上的点称为支持向量。
这种分类器非常接近于逻辑回归,但是不能处理由于噪声(一种无法解释的量)而导致数据类混合的数据集。这导致了以下改进。
2.软利润 SVM
为了克服当数据类混合时的优化问题,添加了一个新的约束来容忍误分类的数据点:位于分离超平面的错误侧的点,在边缘板之内或之外。
在下图中,我们看到分隔线现在位于两个类的数据点内。支持向量现在包括边缘板内的点。
Soft margin linear SVM © the author
这个分类器分离超平面非常接近逻辑回归或线性判别分析(LDA)的分类器分离超平面。即使决策函数看起来不同,性能也是一样的。
我们仍然无法解决异或数据集。需要第三个也是最后一个技巧。
3.内核技巧
到目前为止,SVM 与其他线性分类器如逻辑回归或线性判别分析没有太大的不同。
然而,观察到 SVM 的拟合和预测仅依赖于 x 样本的内积,出现了使用替代产品的新想法,好像通过变换 h(x) 对 x 进行了预处理。
以下产品功能应是对称的和正的:
其范围从简单的二次函数到更复杂的函数,如高斯径向核函数(RBF):
由于需要新的 x 值与训练样本的乘积,预测变得更加复杂。然而,我们可以将这种计算限制到支持向量。
XOR problem solved by an SVM with Gaussian RBF kernel © the author
有了具有非线性内核的 SVM,我们已经能够解决 XOR 问题,这是在 60 年代感知机发明之后第一个人工智能冬天[3]的原因之一。
完整的 Python 笔记本在 Github 上有HTML或者Jupyter的版本。它包含了更详细的数学,一个用 Python 定制的实现使用 Scipy 通用解算器**,**与实现 Scikit 的比较学习,与与逻辑回归和线性判别分析的比较
这篇帖子是 Github“循序渐进学习数据科学 ”中开发的系列文章的一部分。如果你喜欢它,请访问我们的知识库,并在项目中添加一颗星来提高它的可见性。
参考资料:
- [1]支持向量网络,Cortes,C. & Vapnik,载于 v . Mach Learn(1995)20:273—【https://doi.org/10.1007/BF00994018
- [2]维基百科上的 Vapnik Chervnonenkis 机器学习理论—https://en.wikipedia.org/wiki/Vapnik–Chervonenkis_theory
- [3]艾冬天上维基—https://en.wikipedia.org/wiki/AI_winter
- [4]朱庇特本帖笔记本—https://medium.com/r/?URL = https % 3A % 2F %2F nio 73 . github . io % 2f 数据-科学% 2f 分类% 2f 分类 SVM.ipynb
支持向量机——软间隔公式和核技巧
学习一些使支持向量机成为强大的线性分类器的高级概念
SVM’s soft margin formulation technique in action
介绍
支持向量机(SVM)是最流行的分类技术之一,旨在直接最小化误分类错误的数量。有许多可访问的资源可以理解支持向量机(SVM)如何工作的基础知识,然而,在几乎所有的现实世界应用中(其中数据是线性不可分的),SVM 使用一些高级概念。
这篇文章的目的是解释软边界公式的概念和支持向量机用来分类线性不可分数据的核心技巧。
如果你想先重温一下 SVM 的基础知识,我推荐你看看下面这篇文章。
从零开始的 SVM 模式
towardsdatascience.com](/support-vector-machine-introduction-to-machine-learning-algorithms-934a444fca47)
线性不可分性
在我们继续讨论软余量和核心技巧的概念之前,让我们先确定它们的必要性。假设我们有一些数据,可以在 2D 空间中描述如下:
Figure 1: Data representation where the two classes are not linearly separable
从图中可以明显看出,没有特定的线性判定边界可以很好地分离数据,即数据是线性不可分的。在更高维度的表现中,我们也可以有类似的情况。这可以归因于这样一个事实:通常,我们从数据中获得的特征不包含足够的信息以便我们可以清楚地区分这两个类别。在许多现实世界的应用程序中通常都是这种情况。幸运的是,研究人员已经提出了能够处理这种情况的技术。让我们看看它们是什么以及它们是如何工作的。
软边界公式
这个想法是基于一个简单的前提:允许 SVM 犯一定数量的错误,并保持尽可能大的差距,以便其他点仍然可以正确分类。只要修改 SVM 的目标,就可以做到这一点。
动机
让我们简要回顾一下采用这种提法的动机。
- 如前所述,几乎所有现实世界的应用程序都有线性不可分的数据。
- 在数据是线性可分的极少数情况下,我们可能不想选择一个完美分离数据的决策边界来避免过度拟合。例如,考虑下图:
Figure 2: Which decision boundary is better? Red or Green?
这里的red
决策边界完美地分隔了所有的训练点。然而,拥有如此少的余量的决策边界真的是一个好主意吗?你认为这样的决策边界会在看不见的数据上很好地推广吗?答案是:不。green
决策边界有更宽的边界,这将允许它对看不见的数据进行很好的概括。从这个意义上说,软余量公式也有助于避免过度拟合问题。
它是如何工作的(数学上)?
让我们看看如何修改我们的目标,以达到预期的行为。在这种新环境下,我们的目标是最大限度地降低以下目标:
equation 1
这与第二任期的最初目标不同。这里,**C**
是一个超参数,它决定了最大限度地提高利润和最小化错误之间的权衡。当**C**
较小时,分类错误的重要性较低,重点更多地放在最大化裕度上,而当**C**
较大时,重点更多地放在避免错误分类上,代价是保持裕度较小。
在这一点上,我们应该注意到,然而,并不是所有的错误都是相同的。与距离较近的数据点相比,远离决策边界错误一侧的数据点应该招致更多的惩罚。让我们看看如何在下图的帮助下实现这一点。
Figure 3: The penalty incurred by data points for being on the wrong side of the decision boundary
想法是:对于每个数据点**x_i**
,我们引入一个松弛变量**ξ_i**
。**ξ_i**
的值是**x_i**
到对应类的边距的距离,如果**x_i**
在边距的错误一侧,否则为零。因此,在错误一侧远离边缘的点将得到更多的惩罚。
有了这个想法,每个数据点**x_i**
需要满足以下约束:
equation 2
这里,不等式的左边可以被认为是分类的置信度。置信度得分≥ 1 表明分类器对该点进行了正确分类。但是,如果置信度得分< 1, it means that classifier did not classify the point correctly and incurring a linear penalty of 【 。
鉴于这些限制,我们的目标是最小化以下功能:
equation 3
其中我们使用了拉格朗日乘数的概念来优化约束条件下的损失函数。让我们把它与 SVM 处理线性可分情况的目标相比较(如下所示)。
equation 4
我们看到,在修改后的目标中,只有**ξ_i**
项是额外的,其他都是相同的。
注意:在最终解决方案中,对应于最接近边缘和边缘错误侧的点(即具有非零的
**ξ_i**
)的**λ_i**
将是非零的,因为它们在决策边界的定位中起关键作用,本质上使它们成为支持向量。
内核技巧
现在让我们探索使用“内核技巧”来解决线性不可分性问题的第二种解决方案。但首先,我们应该了解什么是核函数。
核函数
核函数是将两个向量(任何维度)作为输入并输出表示输入向量相似程度的分数的广义函数。你已经知道的一个简单的核函数是点积函数:如果点积小,我们得出向量不同的结论,如果点积大,我们得出向量更相似的结论。如果您有兴趣了解其他类型的内核函数,这个将是一个很好的来源。
“诡计”
让我们看看线性可分情况的目标函数:
equation 5
这是
equation 4
中物镜的修改形式。这里,我们代入了**w**
和**b**
的最佳值。这些最佳值可以通过对这些参数求微分equation 4
并使其等于 0 来计算。
我们可以从equation 5
中观察到,目标依赖于输入向量对的点积(***x_i . x_j***
),它只不过是一个核函数。现在这里有一件好事:我们不必局限于像点积这样简单的内核函数。我们可以使用任何花哨的核函数来代替点积,它具有在更高维度中测量相似性的能力(在这种情况下,它可能更精确;稍后将详细介绍),而不会增加太多的计算成本。这基本上被称为内核技巧。
它是如何工作的(数学上)?
核函数可以用数学方法写成如下形式:
equation 6
这里**x**
和**y**
是输入向量,***ϕ***
是变换函数,< , >
表示点积运算。在点积函数的情况下,***ϕ***
只是将输入向量映射到自身。
核函数本质上采用变换后的输入向量的点积。
现在让我们考虑下面figure 4
中描述的情况。我们看到,在 2d 空间中没有可以完美分离数据点的线性决策边界。圆形(或二次型)决策边界可能可以完成这项工作,但是,线性分类器无法得出这些类型的决策边界。
Figure 4: Points in 2D space are separable by a circular decision boundary.
在figure 4
中,每个点P
由 2D 空间中形状(x,y)
的特征表示。查看理想的决策边界,我们可以将点P
的转换函数***ϕ***
定义为***ϕ***(P) = (x^2, y^2, √2xy)
(我们为什么要进行这样的转换一会儿就清楚了)。让我们看看对于两点P_1
和P_2
的这种类型的变换,核函数是什么样子的。
equation 7
如果我们观察内核函数的最终形式,它无非是一个圆!这意味着我们改变了相似性的概念:我们不再通过点的接近程度(使用点积)来衡量相似性,而是根据点是否在一个圆内来衡量相似性。在这个意义上,定义这样的变换允许我们在 2D 空间中有一个非线性决策边界(它在原始 3D 空间中仍然是线性的)*。*要跟踪的内容可能很多,因此以下是我们所做决定的简要总结:
**1** - Each point P is represented by (**x**,**y**) coordinates in 2D space.**2** - We project the points to 3D space by transforming their coordinates to (**x^2**, **y^2**, **√2xy**)**3** - Points which have high value of **x**.**y** would move upwards along the z-axis (in this case, mostly the red circles). [This video](https://www.youtube.com/watch?v=3liCbRZPrZA) provides a good visualization of the same.**4** - We find a hyperplane in 3D space that would perfectly separate the classes.**5** - The form of Kernel function indicates that this hyperplane would form a circle in 2D space, thus giving us a non-linear decision boundary.
主要的要点是:
通过将数据嵌入到更高维的特征空间中,我们可以继续使用线性分类器!
这里需要注意的是,这些变换可能会大幅增加特征空间,从而增加计算成本。有什么方法可以在不增加计算成本的情况下获得上述好处呢?原来是有的!
让我们尝试重写equation 7
中的内核函数:
equation 8
哇哦。因此,核函数的值(因此,3D 空间中的点之间的相似性)正好是 2D 空间中的点之间的点积的平方。很棒,对吧?!但是这是怎么发生的呢?
原因是我们明智地选择了我们的转换函数***ϕ***
。只要我们继续这样做,我们就可以绕过变换步骤,直接从 2D 空间中的点之间的相似性来计算核函数值。这反过来也会抑制计算成本。我们有许多流行的内核函数,它们都有这种良好的特性,可以开箱即用(我们不需要搜索完美的***ϕ***
)。
结束语
到此为止,我们已经完成了这篇文章。希望本文提供的细节能让您深入了解是什么让 SVM 成为一个强大的线性分类器。如果你有任何问题或建议,请在评论中告诉我。干杯!🥂
如果你喜欢这篇文章,并对我未来的努力感兴趣,可以考虑在 Twitter 上关注我:https://twitter.com/rishabh_misra_
在舞台上
A picture of a Sur La Table storefront edited with elements from the Tableau visualization software
可视化是数据科学家向广大受众清晰传达其发现的主要方法之一。在我开始数据科学之旅之前,我的主要可视化工具是 Microsoft Office 套件和一组简单的图像编辑器(信不信由你,主要是 MS Paint 和 Mac Preview)。这些工具对于我当时的需求来说绰绰有余,也是我高中和大学唯一关注的工具。一旦我进入专业领域,我很快意识到,仅仅这些工具还不足以在任何分析职业中取得成功,如果我不建立自己的技能组合,我将达不到我的目标。现代工作环境需要超越 Excel 能力的高级数据工具,这就是为什么商业智能(BI)软件,如 Tableau,越来越受跨职能团队的欢迎。
我学习数据科学技术的动机是因为我开始处理大型外部数据集,Excel 和 Google Sheets 用太长时间来计算聚合列。我学习了如何操作 Python 的 Matplotlib、Seaborn、Folium 和 Plotly 库,从多个数据源创建强大的可视化。这些库需要对每种类型的图表的特定参数有透彻的理解,以创建专业水平的可视化,这可能很耗时,并且对没有编码经验的人来说是一个入门障碍。有一些 BI 工具将这些库的强大功能和可定制性与 Excel 和 Paint 的相对简单性结合在一起。在与该领域的几个实践成员交流之后,我决定熟悉 Tableau,他们除了使用各种可视化库之外,还使用该软件。
Tableau 是一个 BI 工具,可以轻松地组合来自多个来源的数据,以创建专业的交互式可视化。Tableau 的两个优点是,用户可以创建深入的可视化,而不必调整大量的代码参数,并且用户可以使用相同的 SQL 查询逻辑合并来自多个来源的表。Tableau 现在是在订阅的基础上销售的,在过去几年里经历了增长。根据该公司 2018 年提交的10k SEC 文件,“截至 2018 年 12 月 31 日,我们拥有超过 86,000 个客户账户,而截至 2017 年 12 月 31 日超过 70,000 个,截至 2016 年 12 月 31 日超过 54,000 个。”然而,这是由你来决定是否值得每月 70 美元的用户订阅费。
我完成了 Tableau 的创建者部分的在线教程视频和练习作业来熟悉这个软件。然后,我从我以前的数据科学项目中重新创建了一些可视化,以比较一些 Python 可视化库和 Tableau,并在这里详细介绍了我的体验。
第 1 部分:入门
Tableau 以包月的方式提供,根据您的需求提供多种价位。你可以下载为期 14 天的免费试用版,如果你是学生或教师,你可以获得一年的免费 Tableau。我用了两个星期的试用期来跟随教程视频。
A New Tableau Workbook
像 Excel 一样,Tableau 文件被称为工作簿,一个工作簿可以包含多个工作表。在 Tableau 表中,您可以创建多种类型的图表,以不同的方式显示部分数据。这些图表本质上是互动的;您可以选择感兴趣的数据部分,并使用 Tableau 的 GUI 创建自定义的数据分组。屏幕左侧的数据窗格将您的数据分为分类列和连续列。然后,您可以将这些列拖放到可视化的 x 和 y 轴上。
Tableau 工作簿还可以包含仪表板和故事点。仪表板是一个或多个交互式可视化的视图。您可以将这些可视化效果设置为最初一致地显示给所有其他用户。例如,假设您有一个带有“按国家销售”图表的仪表板。这个图表可以通过多种方式进行调整,用户可以将这个图表更改为“按产品类型销售”对于与您共享工作簿的每个人,您可以将此可视化设置为默认的 by country 视图,以确保您发送的是您想要的一致信息。Tableau story points 是一组有序的、带注释的仪表盘,它们共同讲述一个支持您的分析结论的故事。
Tableau’s server connection options with the MongoDB BI menu open
Tableau 允许您从本地文件导入数据并直接连接到外部服务器;您选择由服务器托管的数据库类型(列出了许多 SQL 和 NoSQL 数据库选项),然后进行查询以选择您想要分析的数据。
有许多选项可以保存 Tableau 工作簿。打包的工作簿(文件扩展名为.twbx
)包含您分析的基础数据。非打包工作簿(文件扩展名为.twb
)没有包含在文件中的基础数据,这意味着接收者需要访问相同的数据源才能查看文件。这两种文件类型都保留了可视化的交互性。您还可以将数据和可视化共享为其他文件类型,如 Excel 或 PDF,但是这些将不会保留 Tableau 工作簿的交互性。你也可以将这些文件分享给 Tableau 的云服务。拥有 Tableau Desktop 的用户在获得适当权限的情况下可以查看和编辑工作簿,拥有 Tableau Viewer 的用户( $12 包月,最少 100 个用户)只能查看工作簿。
第 2 部分:数据源
The Join menu open on the Data Source tab in Tableau. Like a SQL query you can join multiple tables on a specific column.
在 tableau 中连接多个数据源很容易。一旦你选择了你感兴趣的表,Tableau 的连接菜单就会弹出。它会自动选择要连接的公共列,并且您可以选择更改连接的列和所使用的连接类型。Tableau 提供了一个健壮的 GUI,对于那些对基于文本的 SQL 和 NoSQL 数据库查询感到厌烦的用户来说,这是一个很好的选择。
数据源选项卡包含原始数据,并具有传统 Excel 表的所有排序和聚合选项。如果您使用的是外部数据库,您还可以通过位于窗口右上方的“实时”选项来更新数据。如果选择了“提取”选项,数据将按设定的时间间隔更新。我正在处理静态的.csv
文件,所以这个选项现在并不重要。
第 3 部分:分析和可视化
我使用了三个数据集;来自 Tableau 的样本销售数据集、来自我的逻辑租金预测项目的数据以及来自我的用于自然语言处理的朴素贝叶斯分类器的数据。
教程详细介绍了 Tableau 查看由一家虚构的家具公司生成的典型内部销售数据的多种方式。Tableau 的 GUI 允许您单击并拖动与您的分析最相关的列。工作表窗口右上角的演示按钮提供可视化效果,显示所选列之间的关系。
A Tableau dashboard that utilizes sample customer data from a fictional furniture company. Note the regression line and tooltip information box open on the bottom left pane.
示例数据集包含关于示例公司的客户、供应商和内部现金流的详细数据。我能够轻松地创建可视化效果,按照市场位置、客户群、产品类型和利润率来分解数据。在本教程之后,我可以看到,如果您的团队一直在生成大量内部数据,那么购买 Tableau 是有意义的。让我们看看 Tableau 如何处理其他数据科学主题的可视化。
纽约公寓列表 Choropleth
我的租金预测项目的 GitHub 存储库托管在这里。我有两个熊猫数据框;一个是询问租金和房源信息,另一个是纽约市街区和相应邮政编码的表格。两个数据框共享“邻域”列。在 Python 的 Pandas 库中,您可以使用.join()
或.concat()
方法将两个数据帧相加。在 tableau 中,您可以使用交互式加入菜单。
我最喜欢的租金预测可视化是我用 Python 的叶库创建的按邮政编码排列的房源总数的 choropleth 地图。由于所涉及的步骤,我花了大约两个小时来完成这个可视化。我首先必须找到一个向导来绘制一张 choropleth 地图;我遵循的指南是基于洛杉矶的数据。这意味着我必须找到一个特定于纽约邮政编码的.geojson
文件。一旦我把这些都放在一起,我抛出了几个错误信息。事实证明,最近对 follow 库进行了更新,对代码进行了一些重要的修改。我阅读文档并寻找能帮助我纠正答案的答案。一旦我最终修复了代码,我就有了一个交互式 choropleth 地图来支持我的分析,下面是地图的截图和代码的要点。
A screenshot of the choropleth map created with Python’s Folium library. Folium generates an HTML interactive map, which can be downloaded from the project repository and rendered with a web browser.
The code used to create the interactive choropleth
在 Tableau 中创建一个 choropleth 映射比编写一个简单得多。首先创建一个与原始数据分开的新工作表。然后将邮政编码列拖放到列栏和行栏中。然后,单击行栏中邮政编码气泡右侧的下拉菜单。您将数据转换为条目数,其中每个条目代表一个列表。最后,点击窗口右上角的演示,第一个选项是交互式 choropleth 地图。我不需要搜索特定于纽约市的.geojson
文件。这花了我两分钟时间,比编码方式快多了。
A screenshot of an interactive Tableau choropleth map. Tableau maps move by dragging and scrolling instead of the point-and-click controls of a Folium map.
Tableau 地图是高度可调的。我很快制作了一个按邮政编码划分的平均租金图,并且我能够用下拉菜单来改变颜色,而不是调整代码中的参数。
PCA 可视化
我最近完成了一个朴素贝叶斯分类器,它可以区分抑制你的热情和宋飞的脚本。利用自然语言处理和主成分分析的原理,我确定了三个维度,这三个维度可以最好地解释这两种文字之间的差异。我利用 Python 的 Matplotlib 和 Scikit-Learn 库生成了下面的可视化。
适用于以下可视化的 PCA 的相关部分是每个脚本中的每个单词都是脚本的一个维度。如果一个脚本包含七次提到名字 Kramer ,那么这个脚本的 Kramer 维度的值就是七。如果脚本不包含单词 Cat ,则该脚本的 Cat Dimension 的值为零。一个文字可以有和单词一样多的维度,PCA 试图减少维度的数量,同时尽可能多地解释文字之间的差异。我选择了三个主成分来解释最大的差异,以创建下面的可视化。
A 3-D representation of the scripts utilizing features identified with Principal Component Analysis. Note the red (Curb) scripts are tightly clustered while the blue (Seinfeld) scripts are more spread out.
The code to create the 3-D representation of the “Curb your Enthusiasm” and “Seinfeld” scripts
我将用于创建上述图表的数据导出到 Tableau。我搜索了各种论坛来学习如何在 Tableau 中制作三维图表,并且我很快了解到在商业智能社区中有一场关于第三轴是否是坏习惯的辩论(参见 Tableau 社区论坛对话这里和这里)。三维图表在数据科学社区中很常见,因为我们可以解释用于创建额外维度的数学原理。
我创建了脚本主要组件的并排可视化,并将其添加到仪表板中。
A Tableau Dashboard visualization of the Principal Components for “Curb Your Enthusiasm” and “Seinfeld” scripts. The visualization contains two side-by-side charts of the first dimension to the second and third dimensions, respectively.
虽然 Tableau 不支持我想要创建的 XYZ 三维图形类型,但仪表板清楚地显示,与广泛传播的宋飞脚本相比,有一个紧密的抑制你的热情脚本集群。幸运的是,Tableau 有许多导入选项,如果我的分析绝对需要的话,这些选项可以让我将 Python 生成的图像上传到 Tableau 仪表板。
结论
Tableau 有许多优点和缺点:
赞成的意见
- Tableau 是一个 BI 工具,旨在从客户/客户销售、供应商和内部财务数据中发掘洞察力
- Tableau 有一个简单直观的图形用户界面
- Tableau 用户可以快速创建 BI 可视化,无需编码经验
- 有许多导入选项允许用户轻松整合内部和外部数据源
- 联接数据源遵循 SQL 查询的逻辑
- 仪表板和故事点视图允许您通过交互式可视化引导您的观众进行分析
- 他们的网站上有许多培训视频和练习
- 您可以保存和共享完整的 Tableau 工作簿或创建不同类型的文件,以便与非 Tableau 用户共享静态图像
- Tableau 的云服务提供了多种发布选择
骗局
- Tableau 是一个 BI 工具,它不是为创建数据科学领域流行的所有可视化而设计的
- Tableau 很贵,只能为一直使用它的团队成员订阅
- Tableau 中可供数据科学家使用的模型和选项不像 Python 库中的那么多,比如 Scikit-Learn
TL;速度三角形定位法(dead reckoning)
Tableau 是一个商业智能工具。习惯它直观的 GUI 是相当容易的。如果您的团队持续生成大量的内部数据(即来自客户/顾客、供应商和产品/服务的数据),那么 Tableau 可以成为帮助您发现有价值见解的强大工具。Tableau 在从消费者行为中获得洞察力方面大放异彩,但在为 PCA 等高级主题生成三维图表方面却表现不佳。
Tableau 不是商业或数据科学的一体化软件解决方案,它不具备 Python 包的功能和可定制性。Tableau 很容易生成可视化和相关的统计信息,请确保您在展示您的发现之前理解这些信息的含义。Tableau 按月订阅;如果您计划使用该软件,并且如果您的团队生成了该软件旨在处理的数据,则只为您和您的同事购买订阅。
只有你能决定 Tableau 对你的团队来说是否值得。
当然,人工智能可以有创造力,但它永远不会拥有天才
Sarah Bernhardt plays Hamlet, London 1899
“赫卡柏对他来说算什么,还是他为了赫卡柏,
那他应该为她哭泣?”
在第二幕第二场的结尾,哈姆雷特质疑在一部关于围攻特洛伊的戏剧中,演员们如何能够传达这样的情感——对一座古城的陌生女王产生这样的共鸣。
这里的构造很复杂。一出戏中的戏,引发了关键时刻的自省,并最终自我怀疑。并非巧合的是,在这部作品中,我们可能最早使用了术语“我的心眼”,这预示着戏剧焦点的转变,从传统的制定争端、情人激情和闹剧,到更微妙的一种从心理混乱中产生的戏剧。
《哈姆雷特》被普遍认为是一部创造性天才的作品。对于许多从事创造性艺术的人来说,像这样的作品和其他更广泛的作品是理想的基准。不可磨灭的对人类创造力辉煌的提醒。
现在,在我们的历史上,人类第一次在审美创造的刻意行为中有了对手。在人工智能炒作的雪崩中,出现了一个新的承诺——创造性的人工智能;这里是为了减轻我们繁重的任务,包括音乐、文学和艺术创作。
在最近一集 Gigaom 的人工智能播客中,高通技术副总裁 Max Welling 解释了复制这一努力的可能性,直到现在,这还是人类的唯一权限:
“有时人们会说,有创造力是一件非常神奇的事情。这不是我们可以在计算机中创造的东西,但我不同意…创造力实际上是以非常令人惊讶的新方式将你在过去学到的东西结合起来,对吗?将模块重组为对其他人来说非常惊人的新方式。现在,作为人类,我们在这方面做得相当好,但我要说,对于计算机来说,没有理由认为它们不能比人类做得更好。”
无论是对创造力构成要素的看法,还是对智能机器的雄心,韦林都不是唯一的一个。当被问及儿童可能从教育系统中学习创造力的未来时,教育科技公司松鼠 AI 的发言人类似地告诉我:“(T2)我们相信人工智能将在 5 到 10 年内超越人类的创造力。”超越!显然,他们已经确定了创造力的四个组成部分,每一个现在都可以在人工智能计算机中演示:广泛的知识,好奇心,发散思维和逻辑归纳。
另一家投资于这一成长领域的公司 Creative AI ,可能没有宣布计算机的文学作品会让伟大的小说看起来像无聊的涂鸦,但他们已经支持了它在帮助人类创造力方面的新兴实力。他们说,我们正朝着前所未有的创新工具(图片编辑器、音乐工作室等)和更大的合作机会(社交网络平台)发展。这导致了他们所谓的“创造力的升级”;或者“一个创造力高度开放的世界,任何人都可以像莎士比亚一样写作,像巴赫一样作曲,像梵高一样绘画……”
这种观点表明了一种病毒式的信念,即任何东西都可以被分解成模块或被捕捉为数据,被量化,并最终被机器复制或指导。甚至创作才华。
Edmond de Bellamy, a generative adversarial network portrait painting
对我来说,这完全误解了真正创造力的目标和乐趣。
即使我们向松鼠 AI 承认好奇心(例如)是创造的一个公理部分,他们也选择了参考深度学习系统来证明这一点,该系统最近胜过了游戏中的人类玩家,蒙特祖马的复仇。这可能令人印象深刻,但这是一种好奇心,需要由机器的人类创造者密切监管。虽然有证据表明,蹒跚学步的儿童以明显系统的方式学习和适应——使用与人工智能类似的“算法”基于统计概率进行推理——但他们无疑是这一过程中的意志原动力。正如柏克莱大学教授兼发展心理学家艾莉森·戈普尼克(Alison Gopnik)所描述的那样,小孩子“进入一切”作为他们收集证据的一部分。我们从经验中知道,这意味着探索各种环境、人工制品、情感、交流、感觉等。
即使对于一个“好奇”的人工智能,它们的等价领域也必然是有限的。艺术 AI 从艺术中学习如何做艺术*;它不会根据环境来创作艺术。然而这是创造性艺术是的一个重要组成部分。它是对我们生活经历的反应和表达。*
在我们发现创造性天才的地方——无论是在一个创造性的作品中,还是在一个人类创造者的集体作品中——我们都被其吸收和传播深刻事物的能力所吸引。我们也许不能清楚地说出它的特征,但我们可以说它是一种信息的载体,通常被包裹在一种情感之中。一个机械系统也许能够制造出看起来就像班克斯的东西,但是就像赝品一样,它情感上的不真实性使它的艺术价值无效。
一个真正的创造者不可能没有思想或意识,而一个人工智能不可能创作出对它无法体验的世界进行评论的作品。正如一个人如果没有经历过风,也没有长出过头发,就无法表达头发被风吹动的感觉。
除了感官或情感之外,伟大的创造力通常会吸引我们人类熟悉的、但通常不言而喻的密集联系网络。保罗·萨格写了人类对联想的巨大重视,并借用了西蒙·布莱克本的例子:
“想象一下,我请你吃饭,在切烤肉的时候,我不经意地提到这正是刺客用来谋杀我妻子和孩子的刀。你还会放心吃我刚刚放在你盘子里的那片牛肉吗?”
正是这些类型的社会和心理关联的显著性,创造性的杰出作品才能如此娴熟地运用。作为一个推论,我们的大部分享受来自于我们努力确定创作者的动机,或主体的意图。
Banksy, Girl With Heart Balloon
哈姆雷特真的疯了吗?蒙娜丽莎在微笑吗?关于信仰,Pi 的动物教会了我们什么?和威利·罗曼谈成功?为什么大卫如此悲伤地看着歌利亚的头?这些东西是无法通过数据的计算分析获得的。如果没有对支撑它们的人类状况的物种层面的理解,同样价值的作品也不可能产生。
这并不是说科学在创造力中没有位置。相反,如果没有辅助技术,创造性人工制品的历史将会更加糟糕。画笔、钢笔、打字机、照相机、录音棚——不胜枚举。有了这惊人的祖先,新的人工智能技术无疑将促进未知领域的创造性艺术,使我们所有人感到惊讶和挑战。“增强”是描述这种帮助的流行方式,但这只是含蓄地承认,当涉及到有意义的创造性工作时,人工智能将是一种工具,而不是托尔金。
这种区别很重要,尤其是在从业者将人工创造力描述为人工智能的“终极登月”的时候。事实上,这些系统并没有努力创造美丽的、有挑战性的东西。相反,他们试图预测和生产人类可能认为有价值或美丽的东西。在其他行业——如营销和广告——这种方法迄今为止在预测,然后逐渐塑造我们的偏好和行为方面非常成功。不久,我们可能会发现我们的艺术品味在重新调整,变得更有利于快速、轻松地创作出创造性的作品,而且成本只是真正作品的一小部分。这种塑造可能已经发生了。
像《哈姆雷特》中的演员一样,艾并不刻画真实的情感,只刻画其表面的所指。它是拟态,有它的用途(包括娱乐),但永远代替不了光彩。让我们确保,在试图将人类的创造力归结为其组成部分并廉价地模拟它的同时,智能技术被用来培养和提升真正的交易。
文档分类中的惊人发现
有时候简单会赢
文档分类:给大量文本分配标签的任务。在这种情况下,任务是将 BBC 新闻文章分类到五个不同的标签中的一个,例如体育或科技。所使用的数据集并不理想地适合深度学习,只有数千个例子,但这在大公司之外远不是不现实的情况。
通常这种类型的技术文章会通过几个模型运行,然后以结果比较和总体评估结束,但今天我想我会给你留一个卷轴,从意想不到的结果开始。
简单的模型效果最好。就像,真的是简单的型号。逻辑回归优于或等同于各种深度神经网络方法。我假设这是由于数据集的较小尺寸和所讨论的长文本。不同于诸如句子分类的任务,在句子分类中,单词的数量很少并且单词的顺序极大地影响句子的意思,文档分类问题有大量的单词用于对每个文档进行分类。这导致单词的顺序对类别的预测能力较低,降低了卷积网络、LSTMs 和分层注意网络(HAN)等技术的有效性,所有这些技术在大规模数据集上都表现良好。相反,只使用文本中存在的单词的方法效果更好,最上面的 n 个单词的计数或二进制编码(0:单词不在文档中| 1:单词在文档中)效果最好。
好的,现在让我们来看看一些模型。那些表现令人震惊的模型不包括在内。
起始复数|卷积神经网络| 96.63%
CNN 的方法旨在使用文本中单词的顺序来提供含义。完全连接的层也可以做到这一点,但这存在两个问题:
- 要优化的权重数量将是巨大的,有过度拟合的风险。
- 权重对文本中单词的相对位置敏感。
CNN 的方法旨在通过假设文本中的单词序列对类别具有预测能力来解决这些问题,但是这些序列在文本中的位置是不相关的。通过在文本中的单词上移动相同的内核,我们从过滤器获得相同的激活,而不管短语在文本中的位置。唯一的位置变化是激活在第一层的列向量中。这是通过使用最大池层将列向量减少到单个行向量来消除的。结果,可以想象 512 个内核中的每一个都在文本中搜索特定的短语。
当然,完全相同的短语不太可能出现在多个文本中。这通过使用单词向量来编码每个单词的相对含义来缓解,因此短语“我爱我的手机”和“我爱我的手机”将传递相似的激活,尽管不是逐字相同的。这也减少了单词表示的维度,允许 350 万单词的词汇表只有 50 到 300 个维度。
降一个档次|密集神经网络| 95.96%
让我们把事情简化一点。在密集网络中,我们只有一个 64 节点的隐藏层,然后是一个输出预测层,就像 CNN 模型一样。如引言中所述,所使用的输入也被简化为二进制编码,其中 0 表示“单词不在文档中”, 1 表示最常见的 n 单词的“单词在文档中”。
这种方法工作得非常好,给出了与 CNN 方法相似的性能,但是具有更快的训练和处理时间。它的内存效率也更高,只需要 CNN 模型的 24%的参数。
简化!多项逻辑回归| 96.18%
一个更简单、统计上更严谨的模型是逻辑回归模型。在这种情况下,使用与密集网络相同的特征工程。这被输入到逻辑模型中,该逻辑模型类似于没有隐藏层并且在其输出层上具有 sigmoid 激活的神经网络,尽管用于拟合它的方法和损失函数是特定于该模型的。
这个模型非常简单,不考虑 CNN 捕捉到的单词和短语的顺序信息。它也没有任何词义的上下文,对待“爱”和“崇拜”就像对待“狗”和“三明治”一样。然而,尽管做出了所有这些让步,它只牺牲了 0.5%的准确性,却获得了更多的好处:极小的内存使用量、统计上的严格性以及相对较快的训练和评估时间。
也许,只是有时候,简单确实会赢,而且比好得多。
如果你看到这个,为阅读/滚动到这里而欢呼吧。想要结论,再看一遍简介就行了!❤️
数据科学家的惊人排序技巧
Python、NumPy、pandas、PyTorch 和 TensorFlow 中的排序函数
对数据进行排序是数据科学家和数据工程师的基本任务。Python 用户有许多带有内置优化排序选项的库可供选择。有些甚至在 GPU 上并行工作。令人惊讶的是,一些排序方法并不使用指定的算法类型,而另一些排序方法并不像预期的那样执行。
选择使用哪个库和哪种类型的排序算法可能很棘手。实现变化很快。截至本文最初撰写时,pandas 文档甚至没有更新代码(尽管我的 PR 更新排序选项刚刚被接受)。😄
在本文中,我将向您介绍情况,提供帮助您记住方法的技巧,并分享速度测试的结果。
Sorted Tea
让我们开始分类吧!
2019 年 7 月 17 日更新:速度测试评测结果现在包括 PyTorch 和 TensorFlow 的 GPU 实现。TensorFlow 还包括tensorflow==2.0.0-beta1
和tensorflow-gpu==2.0.0-beta1
下的 CPU 结果。令人惊讶的发现:PyTorch GPU 快如闪电,TensorFlow GPU 比 TensorFlow CPU 慢。我怀疑 GPU 版本中存在性能错误。2021 年 9 月进一步更新,以提高清晰度。
语境
有许多不同的基本排序算法。有些执行速度更快,使用的内存更少。有些更适合大数据,有些如果数据以某种方式排列会更好。很多常用算法的时间和空间复杂度见下图。
From http://bigocheatsheet.com/
对于大多数数据科学问题来说,成为基本实现方面的专家并不是必要的。事实上,过早的优化偶尔会被认为是万恶之源。然而,当您需要重复排序大量数据时,知道使用哪个库和哪个关键字参数会很有帮助。这是我的小抄。
My Google Sheet available here: https://docs.google.com/spreadsheets/d/1zQbDvpmrvTYVnRz_2OTlfB6knLlotdbAoFH6Oy48uSc/edit?usp=sharing
多年来,许多图书馆的排序算法都发生了变化。本文的分析中使用了以下软件版本:
python 3.6.8
numpy 1.16.4
pandas 0.24.2
tensorflow==2.0.0-beta1 #tensorflow-gpu==2.0.0-beta1 slows sorting
pytorch 1.1
让我们从基础开始。
Python(香草)
Python 包含两种内置的排序方法。
my_list.[sort()](https://docs.python.org/3/library/stdtypes.html#list.sort)
就地排序列表。它改变了列表。sort()
返回None
。[sorted(my_list)](https://docs.python.org/3/library/functions.html#sorted)
对任何 iterable 进行排序复制。sorted()
返回排序后的 iterable。sort()
不变异原来的 iterable。
sort()
应该快一点,因为到位了。令人惊讶的是,我在下面的测试中并没有发现这一点。就地排序更危险,因为它会改变原始数据。
Vanilla
对于普通 Python,我们将在本文中研究的所有实现,默认的排序顺序是升序——从最小到最大。大多数排序方法接受一个关键字参数来将排序顺序切换到降序。不幸的是,每个库的参数名称都不同。😦
要在 vanilla Python 中将排序顺序改为降序,传递reverse=True
。
key
可以作为关键字参数来创建你自己的排序标准。例如,sort(key=len)
会按每个列表项的长度排序。
vanilla Python 中使用的唯一排序算法是 Timsort。Timsort 根据要排序的数据的特征选择排序方法。例如,如果要对一个短列表进行排序,则使用插入排序。点击查看 Brandon Skerritt 的精彩文章,了解更多关于 Timsort 的详细信息。
Timsort,也就是普通的 Python 排序,是稳定的。这意味着,如果多个值相同,那么这些项目在排序后将保持原来的顺序。
为了记住sort()
vs. sorted()
,我只记得 sorted 是一个比 sort 更长的单词,sorted 应该需要更长的时间来运行,因为它必须进行复制。尽管下面的结果不支持传统观点,但助记法仍然有效。😃
现在让我们看看如何使用 NumPy。
NumPy
NumPy 是科学计算的基础 Python 库。像普通 Python 一样,它有两个 sort 实现,一个改变数组,另一个复制数组。
[my_array.sort()](https://docs.scipy.org/doc/numpy-1.16.0/reference/generated/numpy.ndarray.sort.html#numpy.ndarray.sort)
就地改变数组并返回排序后的数组。[np.sort(my_array)](https://docs.scipy.org/doc/numpy-1.16.0/reference/generated/numpy.sort.html#numpy.sort)
返回排序后的数组的副本,因此它不会改变原始数组。
以下是可选参数。
**axis**
: int,可选— 排序的轴。默认值为-1,表示沿最后一个轴排序。**kind**
: {' 快速排序 ',' 归并排序 ',' 堆排序 ',' 稳定排序 '},可选— 排序算法。默认为'快速排序'。以下是更多相关信息。**order**
: str 或 str 列表,可选— 当 a 是定义了字段的数组时,该参数指定首先比较哪些字段,其次比较哪些字段,等等。可以将单个字段指定为一个字符串,并且不需要指定所有字段,但是仍将使用未指定的字段(按照它们在 dtype 中出现的顺序)来中断连接。
现在使用的排序算法与您根据它们的名称所预期的有所不同。通过kind=quicksort
意味着排序实际上从一个 introsort 算法开始。文档解释:
当[它]没有取得足够的进展时,它切换到堆排序算法。在最坏的情况下,这种实现使得快速排序 O(n*log(n))。
稳定 自动为被排序的数据类型选择最佳的稳定排序算法。它与 mergesort 一起当前被映射到 timsort 或 radix sort,这取决于数据类型。API 向前兼容性目前限制了选择实现的能力,并且它是为不同的数据类型硬连线的。
添加 Timsort 是为了在已经排序或接近排序的数据上获得更好的性能。对于随机数据,timsort 几乎与 mergesort 相同。它现在用于稳定排序,而快速排序仍然是默认排序,如果没有选择…’合并排序和’稳定映射到整数数据类型的基数排序。
——来自 NumPy 文档——(经过我的一些编辑)。
一个要点是,NumPy 为排序算法选项提供了比普通 Python 更广泛的控制。第二点是种类关键字值不一定对应于实际使用的排序类型。最后一点是mergesort
和stable
值是稳定的,但是quicksort
和heapsort
不是。
NumPy 排序是我们列表中唯一没有使用关键字参数来反转排序顺序的实现。幸运的是,用这样的切片反转一个数组很快:my_arr[::-1]
。
NumPy 算法选项也可以在更加用户友好的熊猫中使用——我发现这些函数更容易保持直线。
熊猫
Panda
用[df.sort_values(by=my_column)](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.sort_values.html)
对熊猫数据帧进行排序。有许多关键字参数可用。
**by**
: str 或str 列表,必选——排序依据的名称或名称列表。如果轴是 0 或索引,那么乘可能包含索引级别和/或列标签。如果轴是 1 或列,那么到可能包含列级别和/或索引标签**axis**
: { 0 或索引, 1 或列 },默认为 0 —待排序的轴。**ascending**
: 布尔型或布尔型的列表,默认真* —升序或降序排序。为多个分类订单指定列表。如果这是一个列表的布尔值,则必须通过自变量匹配的长度。***inplace**
: bool ,默认False——如果 True ,执行就地操作。**kind**
: { *quicksort,mergesort,heapsort,*或 stable },默认 quicksort — 选择排序算法。更多信息参见ndarray.np.sort
。对于数据帧,此选项仅在对单个列或标签进行排序时适用。**na_position**
: {'first ',' last'},默认为' last' — first 将 NaNs 放在开头, last 将 NaN s 放在末尾。
按照相同的语法对熊猫系列进行排序。对于一个系列,你不需要提供一个by
关键字,因为你没有多个列。
因为 pandas 使用了 NumPy,所以您可以轻松地使用同样的优化排序选项。然而,熊猫需要一些额外的时间来提供便利。
按单列排序时默认使用 NumPy 的quicksort
*。*你会想起quicksort
现在实际上是一个 introsort,如果排序进展缓慢,它会变成一个 heapsort。Pandas 确保通过多列排序使用 NumPy 的mergesort
。NumPy 中的 Mergesort 实际上使用的是 Timsort 或者 Radix 排序算法。这些是稳定的排序算法,当按多列排序时,稳定排序是必要的。
熊猫要记住的关键事情是:
- 功能名称:
sort_values()
。 - 您需要
by=column_name
或一个列名列表。 ascending
是反转的关键词。- 如果你想要一个稳定的排序,使用
mergesort
。
当使用 pandas 进行探索性数据分析时,我经常发现自己用Series.value_counts()
对 pandas 数据帧中的值进行求和和排序。下面是对每一列中最常见的值进行求和和排序的代码片段。
for c in df.columns:
print(f"---- {c} ---")
print(df[c].value_counts().head())
pandas 中的排序是对较小数据集进行探索性数据分析的一个很好的选择。当你的数据放不进内存时,Dask 实现了大部分的 pandas API。截至 2019 年年中,Dask 没有并行排序实现,尽管正在讨论。当您拥有大量数据并希望在 GPU 上进行并行搜索时,您可能希望使用 TensorFlow 或 PyTorch。
张量流
TensorFlow 是目前最流行的深度学习框架。看我这篇关于深度学习框架普及和使用的文章这里。以下信息适用于 TensorFlow 2.0 的 GPU 版本。
tf.sort(my_tensor)
返回张量的排序副本。可选参数:
**axis**
: {int,optional}排序的轴。默认值为-1,对最后一个轴进行排序。**direction**
: { 升序或降序 } —对值进行排序的方向。**name**
: {str,可选} —操作的名称。
tf.sort
在幕后使用 top_k()
方法。top_k
使用 CUB 库用于 CUDA GPUs,使并行更容易实现。正如文档解释的那样,“CUB 为 CUDA 编程模型的每一层提供了最先进的、可重用的软件组件。”TensorFlow 通过 CUB 在 GPU 上使用基数排序,这里讨论。
TensorFlow GPU 信息可以在这里找到。要使用 TensorFlow 2.0 启用 GPU 功能,您需要pip3 install tensorflow-gpu==2.0.0-beta1
。正如我们将从下面的评估中看到的,如果你所做的只是排序(这不太可能),你可能想坚持使用tensorflow==2.0.0-beta1
。
使用以下代码片段查看每行代码是在 CPU 上运行还是在 GPU 上运行:
tf.debugging.set_log_device_placement(True)
要指定您想要使用的 GPU,请使用下面的和块:
with tf.device('/GPU:0'):
%time tf.sort(my_tf_tensor)
使用with tf.device('/CPU:0'):
来使用 CPU。
tf.sort()
是一个非常直观的方法,如果您在 TensorFlow 中工作,可以记住并使用它。记住direction=descending
切换排序顺序即可。
现在让我们看看另一个流行的深度学习包 PyTorch 中的排序。
PyTorch
torch.sort(my_tensor)
返回张量的排序副本。可选参数:
**dim**
: {int,optional } —排序所依据的维度**descending**
: {bool,可选 } —控制排序顺序(升序或降序)。**out**
: {tuple,optional*}*—( Tensor,LongTensor)的输出元组,可以选择用作输出缓冲区。
通过将.cuda()
添加到张量来指定您想要使用的 GPU。
gpu_tensor=my_pytorch_tensor.cuda()
%time torch.sort(gpu_tensor)
如果数据集大于 100 万行乘以 100,000 列,PyTorch 将通过推力使用分段并行排序。
Thrust 是一个并行算法库,支持 GPU 和多核 CPU 之间的性能移植。它提供了一个排序原语,可以自动选择最有效的实现。TensorFlow 使用的 CUB 库包装推力。因此,如果你深入研究,你会发现 PyTorch 和 TensorFlow 正在使用类似的实现来进行 GPU 排序——无论 thrust 为这种情况选择了什么。
不幸的是,Google Colab 服务器在试图通过 NumPy 创建 1.1M x 100K 的随机数据点时耗尽了内存。😦所以我搬到了有 416 MB 内存的谷歌云平台(GCP ),但仍然内存不足。😦 😦所以我不得不保持在一百万行以下。
分段排序和局部排序是 mergesort 的高性能变体,它们对非均匀随机数据进行操作。分段排序允许我们并行排序许多变长数组。—https://moderngpu.github.io/segsort.html
像 TensorFlow 一样,PyTorch 中的排序方法并不太粗糙,不容易记住:torch.sort()
。唯一棘手的是排序值方向的关键字参数:TensorFlow 使用direction
,而 PyTorch 使用descending
。不要忘记使用.cuda()
来提高大型数据集的速度。😉
虽然使用 GPU 进行排序对于非常大的数据集来说是一个很好的选择,但是直接在 SQL 中对数据进行排序也是有意义的。在本文的最后,我有一个关于使用 SQL 的简短的附加部分。👍
比较
对于上面的每个 Python 库,我进行了一次 wall time 分析,以便在一个列、数组或列表中对相同的 1,000,000 个数据点进行排序。我使用了一台 Google Colab Jupyter 笔记本电脑,配备 K80 GPU 和英特尔(R)至强(R) CPU @ 2.30GHz。
Source code: https://colab.research.google.com/drive/1NNarscUZHUnQ5v-FjbfJmB5D3kyyq9Av
观察
- PyTorch 配 GPU 超快。
- 对于 NumPy 和 pandas 来说,inplace 通常比复制数据更快。
- 默认的熊猫快速排序相当快。
- 大多数熊猫的功能相对来说比它们的 NumPy 同类要慢。
- TensorFlow CPU 相当快。即使使用 CPU,GPU 安装也会降低 TensorFlow 的速度。GPU 排序相当慢。这看起来像是一个可能的错误。🐞
- Vanilla Python 就地排序慢得惊人。它比 PyTorch GPU 支持的排序慢了近 100 倍。我对它进行了多次测试(使用不同的数据),以再次确认这不是一个异常。
同样,这只是一个小测试。这肯定不是决定性的。😉
包装
通常不需要定制排序实现。现成的选项很强大。他们通常不仅仅使用单一的排序方法。相反,他们首先评估数据,然后使用表现良好的排序算法。如果排序进展不快,一些实现甚至会改变算法。
在本文中,您已经看到了如何在许多 Python 数据科学库中进行排序。我希望它对你有所帮助。如果你有,请分享到你最喜欢的社交媒体上,这样其他人也可以找到它。👏
你只需要记住选择哪个选项,以及如何调用它。使用我上面的小抄来节省时间。👍我的一般建议如下:
- 使用默认的熊猫
sort_values()
来探索相对较小的数据集。 - 对于大型数据集或者当速度非常重要时,可以尝试 NumPy 的就地合并排序。为了进一步提高速度,在 GPU 上使用 PyTorch。
我没见过太多关于 GPU 排序的文章。这是一个需要更多研究和指导的领域。这里有一篇 2017 年的文章,让你领略一下最近的研究。更多关于 GPU 排序算法的信息可以在这里找到。
奖励:SQL
SQL 中的排序通常非常快,尤其是当排序在内存中时。
SQL 是一种规范,但并没有规定实现必须使用哪种排序算法。根据具体情况,Postgres 使用磁盘合并排序、堆排序或快速排序。如果你有足够的内存,在内存中排序会变得更快。通过[work_mem](https://wiki.postgresql.org/wiki/Tuning_Your_PostgreSQL_Server)
设置增加分拣可用内存。
其他 SQL 实现使用不同的排序算法。比如 Google BigQuery 用 introsort 配合一些小技巧,根据这个栈溢出回答。
SQL 中的排序是用ORDER BY
命令执行的。这种语法不同于 Python 实现,Python 实现都使用某种形式的单词 *sort。*至少按顺序是独一无二的!😃
要进行降序排序,请使用关键字 DESC。按照从后到前的字母顺序返回客户的查询如下所示:
SELECT Names FROM Customers
ORDER BY Names DESC;
就是这样!
我写关于 Python、Docker、数据科学等等的文章。如果你对此感兴趣,请在这里阅读更多和关注我的媒体。😄
Tea time!
分类愉快!😀
理解数据偏差
数据偏差的类型和来源
过去十年,机器学习(ML)应用程序在图像识别、推荐系统、电子商务和在线广告方面取得了巨大成功,这促使其在社会正义、就业筛选等领域以及 Siri、Alexa 等智能交互界面中得到采用。随着这些应用程序的激增,关于这些系统中性别、种族和其他类型偏见的报告也出现了惊人的增长。《Propublica》期刊上一篇被广泛讨论的报告声称,在对刑事被告进行累犯风险评分的工具中,存在对非裔美国人的严重偏见[1]。亚马逊关闭了一个为求职者评分的模型,因为他们意识到这不利于女性。预测性警务系统[3]受到了严密的审查,由于发现了偏差,它们的使用受到了限制。内容个性化系统产生了过滤泡沫[23],广告排名系统被指责带有种族和性别偏见[22]。
这些偏差的主要来源是用于训练 ML 模型的数据。事实是,几乎所有由基于 ML/AI 的模型驱动的系统生成的大数据集都是有偏差的。然而,大多数 ML 建模者并没有意识到这些偏见,即使他们意识到了,他们也不知道该怎么办。很少有 ML 出版物讨论数据——使用了什么数据、如何生成数据以及在建模之前对数据做了什么等细节。相反,作者似乎有意用他们构建复杂、深奥模型的能力给读者留下深刻印象,并用他们模型的准确性打动他们。下面这幅 xkcd 的漫画很好地抓住了这种心态。
Cartoon by xkcd.com, creative commons license (https://xkcd.com/license.html)
机器学习科学家最好注意一下安德鲁·吉尔曼的格言:“统计分析最重要的方面不是你用数据做什么,而是你用什么数据”[4]。统计分析师理解探索性数据分析(EDA)的重要性,John Tukey [16]在几十年前将其系统化。然而,大多数 ML 科学家有着不同的血统,似乎并不重视探索性数据分析的重要性。
我在本文中的目标是确定数据偏差的主要来源,主要集中在 web 数据和由在线系统(如广告服务和内容排名系统)生成的数据上。
这篇文章的要点是:
- 由 ML 驱动的系统生成的大多数(几乎所有)大数据集是有偏见的
- 数据中的偏差会产生有偏差的模型,这些模型可能是歧视性的,对人类有害
- 对可用数据及其处理进行全面评估以减少偏差应该是建模的关键步骤
那么我们所说的“数据偏差”是什么意思呢?数据偏倚的常见定义是可用数据不能代表研究的总体或现象。但是我在更广泛的意义上使用它。偏见也表示:
- 数据不包括恰当地捕捉我们想要预测的现象的变量
- 数据包括人类制作的内容,其中可能包含对人群的偏见
基于这个定义,除了通过精心设计的随机实验产生的数据,大多数有机产生的数据集都是有偏差的。正如 Torralba 和 Efros 在他们关于图像识别模型的论文[12]中所讨论的,即使是精选的参考数据集也是有偏见的。他们考虑了 12 个广泛使用的参考图像数据集。他们在其中一个数据集上训练了一个模型,并在另外 11 个数据集上测试了它的性能。他们发现在这些测试数据集上,预测准确性显著下降。他们从这个玩具实验中得到的教训是,尽管他们的创造者尽了最大努力,这些参考数据集还是有很强的内在偏见。
产生数据的系统的结构特征会导致数据偏差。根据我的分析,以下是最常见的数据偏差类型:
- 回应或活动偏差:这种类型的偏差出现在人类生成的内容中:亚马逊上的评论、Twitter 推文、脸书帖子、维基百科条目等。事实上,只有一小部分人贡献了这些内容,他们的观点和偏好不太可能反映整体人口的观点。
- 反馈循环导致的选择偏差:当模型本身影响用于训练它的数据的生成时,就会出现这种偏差。这发生在对内容进行分级的系统中,例如内容和广告个性化、推荐系统中,这些推荐系统呈现或给予某些项目比其他项目更高的优先级。收集用户对所呈现的项目的响应(例如生成标签),对未呈现的项目的响应是未知的。用户的反应也受到项目在页面上的位置和显示细节的影响,如字体、媒体(项目包含图像吗?).
- 系统漂移引起的偏差:漂移是指产生数据的系统随时间的变化。变更包括数据中捕获的属性的定义(包括结果)或改变用户与系统交互方式的基础模型或算法。例如:添加新的用户交互模式,如喜欢或分享按钮,添加搜索辅助功能。
- 遗漏变量偏倚:这种类型的偏倚发生在影响结果的关键属性缺失的数据中。当数据生成依赖于人工输入或者记录数据的过程不能访问关键属性时,通常会发生这种情况。
- 社会偏见:这种类型的偏见发生在人类制作的内容中,无论是社交媒体内容还是策划的新闻文章。例子:使用性别或种族刻板印象。这种类型的偏差可以被认为是一种标签偏差。
让我们更详细地考虑这些类型。意识到偏见是第一步,减轻偏见是下一步。我没有详细讨论偏差缓解技术,因为偏差缓解技术取决于特定的数据集及其应用。
反应偏差
响应偏差在网络上很常见,大多数数据来自几个来源。巴埃萨-耶茨[5]提供了网络偏见及其原因的几个例子。他指出:
- 7%的用户产生了脸书上 50%的帖子。
- 4%的用户产生了亚马逊上 50%的评论
- 0.04%的维基百科注册编辑(约 2000 人)制作了英文维基百科一半条目的第一版。
更令人担忧的是,这些用户中的大多数仅代表少数人口统计群体和地理区域。显然,这些数据不能用来对所有用户进行推断。例如,Crawford [6]报告称,在飓风桑迪袭击美国东北部后,Twitter 上的推文被用来研究人们的行为。希望了解受灾最严重地区用户的行为,研究人员后来发现大部分数据来自曼哈顿。很少有推文来自纽约受灾更严重的地区。她指出,随着时间的推移,停电开始了,手机电池耗尽了,来自受灾最严重地区的推文就更少了。
反馈环路引起的偏差
用于在线广告、内容个性化、推荐的系统都有内置的反馈回路。这些系统嵌入了影响所生成数据的 ML 模型,这些数据反过来作为模型的训练数据反馈到系统中。ML 模型将用户的注意力引导到一小部分项目上,并记录用户对这些项目的操作(见下面的图示)。通过跟踪用户的浏览、点击和滚动来推断用户偏好。选择偏差是由于呈现给用户的项目的非随机子集而产生的。在排序列表中呈现这些项目引入了位置偏差——因为用户从左到右和从上到下扫描项目(基于对美国用户进行的实验)。如果字体和媒体类型(图像对文本对视频)在不同的项目之间有所不同,那么就会引入呈现偏差。这些偏差的一个影响是,使用来自该数据的维持样本的模型评估倾向于支持生成该数据的模型[8]。这些系统还可以改变用户的长期内容消费行为。Cheney 等人[8]讨论了相对于没有推荐内容的相同平台,推荐算法如何鼓励相似用户与同一组项目进行交互,从而使他们的行为一致化。例如,基于流行度的系统以相同的方式表示所有用户;这使得所有用户都是一样的。社交推荐系统使连接的用户或小团体内的用户均质化,矩阵分解使用户沿习得的潜在因素均质化。
Feedback loop in ad and content personalization systems
系统漂移引起的偏置
系统漂移表示改变用户与系统交互方式或系统生成数据性质的系统变化。漂移的例子包括:
- 正在学习的概念或目标的定义可能会改变。在欺诈预测系统中,欺诈的定义会发生变化。这种类型的漂移通常被称为“概念漂移”。
- 用户交互模式发生了变化。例如,内容个性化系统可以在文章下添加共享或类似按钮。网络搜索界面可以添加可以改变用户查询组成的查询建议。这种类型的漂移通常被称为“模型漂移”。
在存在漂移的情况下,静态模型的性能会随着时间而降低,如果使用来自多个时间段的数据来训练模型,则定期训练的模型可能表现不佳。Harel 等人[10]提出了一种检测概念漂移的重采样方法。
系统漂移导致高知名度的 ML 应用程序失败的一个例子是谷歌流感趋势(GFT)。几年来,谷歌流感趋势被认为是搜索数据的一种创新用途,用来“预测”一个季节的流感病例数。然而,2013 年 2 月,《自然》[18]报道称,GFT 预测的流感样疾病(ILI)的医生就诊比例是疾病控制和预防中心(CDC)的两倍多,后者的估计基于美国各地实验室的监测报告。尽管 GFT 是为了预测疾病预防控制中心的报告而建立的,这种情况还是发生了[11]。
根据 Lazer 等人[11]的说法,失败背后的一个关键原因是由于谷歌定期对其搜索界面进行更改。谷歌引入了“推荐搜索”,基于其他用户的类似搜索。这增加了某些搜索的相对数量。因为 GFT 在其模型中使用了相对流行的搜索术语,搜索算法的改进对 GFT 的估计产生了不利影响。GFT 提出了一个假设,即某些术语的相对搜索量与外部事件静态相关,但搜索行为不仅仅是由外部因素决定的,它也是由服务提供商内生培养的。
省略可变偏差
这种类型的偏差通常发生在由人工输入数据生成数据的系统中,或者发生在在线系统中,在这些系统中,由于隐私问题或缺乏访问权限,某些事件或操作不会被记录。这意味着关键预测变量可能无法包含在模型中。
回归模型中存在遗漏变量偏差必须满足两个条件:
- 被省略的变量必须与 【目标】 变量相关。
- 被省略的变量必须与 一个或多个其他解释变量 (或*)相关。*
这里有一个可能发生遗漏变量偏差的场景示例:一家笔记本电脑制造商有一个在线聊天系统,其客户可以使用该系统请求支持或提出问题。制造商希望利用这个机会交叉销售产品,并开发了一个模型来评估用户购买更多产品的可能性。该分数旨在帮助在聊天系统中工作的代理有效地分配他们的时间。当他们很忙的时候,代理会投入更多的精力(和时间)来尝试向高分用户交叉销售,而对低分用户投入较少的精力。但是,不会记录代理花费的时间(和精力)。如果没有这些数据,看起来评分模型表现得非常好,而代理花费的时间可能更好地解释了用户的购买决策。
卡鲁阿纳等人[14]主张在医疗保健等高风险应用中使用可理解的模型,以识别因遗漏变量而产生的偏差。神经网络、随机森林、提升树等建模方法通常比逻辑回归和决策树等方法产生更准确的模型,但后者更容易理解,因此更值得信赖。他们讨论了一个案例,其中的目标是预测肺炎患者的死亡概率(POD ),以便高风险患者可以住院,而低风险患者作为门诊患者治疗。他们的 ML 模型在数据中了解到一种模式,即患有哮喘的肺炎患者比没有哮喘的患者死于肺炎的风险更低。意识到这似乎不正常,研究人员进一步调查并了解到,有哮喘病史并表现出肺炎症状的患者通常不仅被送入医院,而且直接被送入 ICU(重症监护病房)。哮喘性肺炎患者接受的积极治疗非常有效,与非哮喘患者相比,降低了他们死于肺炎的风险。然而,这些患者在 ICU 接受积极治疗的事实并没有记录在数据中。作者指出,他们不会了解难以理解的模型中的异常模式。
社会偏见
人类在网络和社交媒体上创造的内容充满偏见。两个引人注目的案例可以说明这一点。Bolukbasi 等人[15]表明,甚至在谷歌新闻文章上训练的单词嵌入也表现出女性/男性性别刻板印象。例如:女性与护士和保姆职业联系在一起,而男性则与医生和金融家职业联系在一起。他们提出消除偏见的策略来减轻这些偏见。在另一个案例[2]中,亚马逊试图建立一个人工智能工具来筛选候选人,直到管理层发现它已经学会惩罚女性候选人。问题是,在今天的大多数公司中,技术角色由男性担任,这种偏见蔓延到任何使用当前员工数据来训练模型的模型中。除非数据中检测到的社会偏见会导致算法对性别、种族和其他类别的歧视。
如何识别和纠正偏差
识别偏倚的第一个关键步骤是理解数据是如何产生的。正如我上面所讨论的,一旦绘制了数据生成过程,就可以预测偏差的类型,并且可以设计干预措施来预处理数据或获得额外的数据。另一个关键步骤是执行全面的探索性数据分析(EDA) [16]。一些教科书和论文讨论了 EDA 技术。
识别和处理社会偏见需要特殊的技巧,其中一些我将在下面提到。对于由反馈循环引起的偏差,一种方法是将系统设计成在少量查询样本上随机化。例如,在一小部分请求(比如 0.1%)中,项目是以随机方式选择和呈现的。在模型训练和评估中仅使用这些请求的数据。有时,出于用户体验的考虑,这是不可行的。在这些情况下,在[9]中提出的倾向加权技术是一种可能的方法。
对于人类生成的内容中的偏见,最近有很多关于量化歧视和去偏见技术以提高公平性的研究。最近,量化歧视的基准[20]甚至设计用来评估这些算法的公平性的数据集[21]已经出现。挑战当然是在不牺牲性能的情况下提高公平性。然而,这些技术通常是特定于数据集和应用程序的。一般来说,这些技术属于三类之一:
- 那些在训练前使用数据预处理的
- 培训期间正在处理
- 培训后的后处理
然而,严重不平衡的训练数据集的问题以及如何将去偏置能力集成到人工智能算法中的问题在很大程度上仍然没有解决[19]。最近发表的一项研究[19]使用训练后的后处理,并尝试将去偏置能力直接集成到模型训练过程中,该过程自动适应训练数据的缺点,无需监督。他们的方法采用端到端的深度学习算法,同时学习所需的任务以及训练数据的潜在结构。以无监督的方式学习潜在分布能够揭示训练数据中隐藏的或隐含的偏差。Bolukbasi 等人[15]描述了一种去偏差单词嵌入的后处理方法,以减轻性别偏差。
参考
[1]朱莉娅·安格温、杰夫·拉森、苏亚·马特和劳伦·基什内尔。“机器偏见:全国各地都有用来预测未来罪犯的软件,它对黑人有偏见”。ProPublica(2016 年 5 月 23 日)。
[3]肮脏的数据,糟糕的预测:公民权利侵犯如何影响警察数据,预测性警务系统和司法, 纽约大学法律评论在线,即将出版(https://papers.ssrn.com/sol3/papers.cfm?abstract_id=3333423)
[5]里卡多·巴埃萨-耶茨,“对网络的偏见”。ACM 通讯,2018 年 6 月,第 61 卷第 6 期,第 54-61 页。
[6]https://hbr.org/2013/04/the-hidden-biases-in-big-data
[7]奥尔特亚努、亚历山德拉和卡斯蒂略、卡洛斯和迪亚兹、费尔南多和基西曼、埃姆雷,《社会数据:偏见、方法陷阱和伦理界限》(2016 年 12 月 20 日)。大数据前沿 2:13。doi: 10.3389/fdata.2019.00013 .在 https://ssrn.com/abstract=2886526 的或 http://dx.doi.org/10.2139/ssrn.2886526 的的SSRN 发售
[8] Cheney、Allison J.B .、Brandon M. Stewart 和 Barbara E. Engelhardt,“推荐系统中的算法混淆如何增加同质性并降低效用”,第 12 届 ACM 推荐系统会议论文集,第 224-232 页
[9]托拜厄斯·施纳贝尔。、Adith Swaminathan、Ashudeep Singh、Navin Chandak、Thorsten Joachims,“作为治疗的建议:去偏置学习和评估”,arXiv 预印本 arXiv:1602.05352。
http://proceedings.mlr.press/v32/harel14.pdf
[11]大卫·雷泽、瑞恩·肯尼迪、Gary King、亚历山德罗·维斯皮亚尼,“谷歌流感的寓言:大数据分析中的陷阱”,《科学》第 343 卷,2014 年 3 月 14 日
[12] A. Torralba,A. Efros。无偏地看待数据集偏差。2011 年 IEEE 计算机视觉和模式识别会议(CVPR)。
https://5harad.com/papers/included-variable-bias.pdf
【14】里奇·卡鲁阿纳,保罗·科赫,尹娄,马克·斯特姆,约翰内斯·戈尔克,小糯米·埃尔哈达德。,“医疗保健的可理解模型:预测肺炎风险和 30 天再入院”, KDD,2015 年 8 月 10-13 日,澳大利亚新南威尔士州悉尼| 2015 年 8 月
[15](https://papers . nips . cc/paper/6228-男人是电脑程序员,女人是家庭主妇-debiasing-word-embeddings . pdf
[16]约翰·图基,探索性数据分析,皮尔逊现代经典著作。
[17] Léon Bottou,Jonas Peters,Joaquin qui onero-Candela,Denis X. Charles,D. Max Chickering,Elon Portugaly,Dipankar Ray,Patrice Simard 和 Ed Snelson:反事实推理和学习系统:计算广告的例子,机器学习研究杂志,14(11 月):3207–3260,2013 年。
[18]德克兰·巴特勒,“当谷歌弄错流感时”,《自然》,第 484 卷,第 7436 期,2013 年 2 月。
[19]亚历山大·阿米尼、艾娃·索莱马尼、威尔科·施瓦廷、桑吉塔·巴蒂亚和丹妮拉·鲁斯。,“通过学习的潜在结构发现和减轻算法偏差”,AAAI/ACM 人工智能伦理与社会会议,2019 年。
[20]M . Hardt,E . Price,N . Sr ebro,“监督学习中的机会均等”,神经信息处理系统进展,2016 年
[21] Buolamwini,j .和 Gebru,T. 2018 年。性别差异:商业性别分类的交叉准确性差异。《公平、责任和透明度会议》, 77–91 页。
[22] Sweeney,Latanya,在线广告投放中的歧视(2013 年 1 月 28 日)。可在 https://ssrn.com/abstract=2208240[或 http://dx.doi.org/10.2139/ssrn.2208240](https://ssrn.com/abstract=2208240)[的](https://dx.doi.org/10.2139/ssrn.2208240)SSRN 买到
[23] Eli Pariser,《过滤泡沫:新的个性化网络如何改变我们的阅读和思维》,企鹅图书公司,2012 年。
“调查显示……”—为什么基于调查的信息并不总是可信的
你有充分的理由对调查结果三思
Photo: bruce mars/Unsplash
我喜欢文字,也喜欢数字。我总是被统计数据背后的故事和图片迷住。我对调查特别感兴趣——可能是因为我非常喜欢家庭不和。
调查是收集人们的信仰、观点和行为数据的一种快速便捷的方式。关于人们的健康、福祉、对社会问题的看法以及对科学技术的了解,很多信息都来自调查。
例如,每年,CDC 和其他联邦机构投入大量资金进行健康调查,以了解美国人口的健康状况、疾病和状况、医疗保健的获得和利用情况。这些调查是精心设计和反复测试的,使用随机选择的可以代表人口的人。这就是为什么可以相当安全地做出这样的声明:大约一半的美国人(47%)至少有心脏病三个关键危险因素中的一个:高血压、高胆固醇和吸烟。
除了这些国家级的调查,许多小规模的研究使用调查来检查人们的健康信念、购物习惯和其他问题。虽然这些研究中有许多已经发表,但并不是所有的都能提供可靠的信息。有几个潜在的陷阱会限制调查结果的可信度。
一项研究不包括正确的问题
由于缺乏资金、时间限制和人员短缺等实际原因,并非调查中的所有问题都经过预先测试,以验证它们是否有效。因此,研究人员可能无法发现他们问卷中的缺陷。
有些词或概念可以有多种解释。人们可能以不同的方式解释同一个句子。此外,问题中的一些引导词会使结果产生偏差。
例如,我曾经看过一份调查草案,其中包括一个问题“你对当前的烟草控制政策有多积极?”显然参与者没有办法给出否定的回答。
一项研究没有选择合适的参与者
获取调查反馈的一种便捷方式是使用一个您容易接触到的小组作为您的调查参与者。大学生经常被用于调查,尽管他们可能在一些特征上与普通大众不同。
一些研究只是在网上社区发布一个调查链接,邀请人们参与。任何看到帖子的人都可以对调查做出回应,甚至可能不止一次,这可能是相当有问题的。
只有关心的人才想参与
即使您选择了一个有代表性的样本作为您的调查参与者,人们仍然可能选择退出或忽略邀请。实际完成调查的人通常对该主题感兴趣,或者对调查中询问的某些问题有强烈的看法。
因此,他们的背景和个人经历可能与那些选择不完成调查的人大相径庭。无回答偏差在调查中很常见。即使是那些知名的全国性调查也不得不面对这个问题。
误导性的调查结果传播
在一个特定的时间点进行调查(横断面设计)旨在测试相关性(一个行为与另一个行为相关联)而不是因果关系(一个行为可以引起另一个行为)。
报告调查结果的一个常见错误是因果关系的含义。例如,我们可以说情绪暴食与抑郁症有关,但我们不应该声称暴食可能导致抑郁症。不幸的是,当媒体引用调查结果时,他们通常会得出相关观察结果之间存在因果关系的结论。
我不打算通过这篇文章教人们如何设计一项研究或如何控制各种调查误差;相反,我希望提高人们的认识,由于上述局限性,需要谨慎解释调查结果。显然,仅仅知道“调查显示…”不足以准确理解正在发生的事情。
生存分析和分层样本
在不牺牲预测能力的情况下,为逻辑回归整理大型生存数据集。
本文讨论了在对非常大的生存分析数据集执行逻辑回归时所面临的独特挑战。当这些数据集对于逻辑回归来说太大时,为了保持事件概率随时间的变化,必须对它们进行非常仔细的采样。
下面,我分析了一个大型模拟数据集,并论证了以下分析流程:
- 从人群水平的数据集中抽取一个分层的病例对照样本
- 在逻辑回归中将(时间间隔)视为一个因素变量
- 应用可变偏移来根据真实的总体水平概率校准模型
[用于构建模拟和绘图的代码可在这里找到]
第一部分: 介绍概念和数据
通常,仅仅预测事件是否会发生是不够的,还要预测事件将在发生的时间。开始实验性癌症治疗后,一个人可能存活多久?何时(何地)我们可能会发现一个罕见的宇宙事件,比如超新星?这项研究的重点是:如果数百万人通过邮件联系,谁会回复,什么时候回复?
所有这些问题都可以通过一种叫做生存分析的技术来回答,这种技术是由卡普兰和迈耶在他们 1958 年的开创性论文中提出的。在这篇文章中,他们演示了如何调整“审查”的纵向分析,这是他们的术语,指的是一些受试者被观察的时间比其他人长。如 Alison (1982) 所总结的,生存分析后来根据离散时间进行了调整。这里,不是将时间视为连续的,而是以特定的间隔进行测量。
生存分析的中心问题是:给定一个事件尚未发生,它在当前区间发生的概率是多少?这由风险率决定,风险率是特定时间间隔内事件相对于该间隔开始时风险集规模的比例(例如,已知治疗 4 年后存活的人数)。
举一个危险率的例子:百万分之十的人死亡(危险率 1/100,000)可能不是一个严重的问题。但是 20 个人中有 10 人死亡(风险率为 1/2)可能会让人吃惊。
本研究调查了对一个假想的邮寄活动的回复的时间。虽然数据是模拟的,但它们都是基于真实数据的,包括数据集大小和响应率。
人口级别的数据集包含 100 万“人”,每个人都有 1-20 周的观察值。数据被标准化,以便所有受试者在第 0 周收到他们的邮件。受试者的反应概率取决于两个变量,年龄和收入,以及时间的伽玛函数。这样,分析的单位不是人,而是人*周。
Above: The formula used to calculate the log-odds of response probability in a given week. z is the log-odds of response probability. The function g(week) is a gamma function of time.
并快速检查我们的数据是否符合我们预测的总体形状:
Above: the gamma function used in the hazard function (line) overlaid against a density histogram of hazard rates in the simulated data set (bars). As time passes after mailing, subjects become less and less likely to respond.
一个人每周大约有 1/10,000 的机会作出回应,这取决于他们的个人特征和多久前与他们联系。
下面是数据集的快照。它放大了假设的主题#277,他在被邮寄 3 周后回复。如上所述,他们被观察的每个星期都有一个数据点。生成二项式响应变量的概率值也包括在内;这些概率值将是逻辑回归试图匹配的。
第二部分: 病例对照抽样和回归策略
由于资源的限制,对具有数百万个观察值和数十个(甚至数百个)解释变量的数据集进行逻辑回归是不现实的。幸运的是,有一些经过验证的数据压缩方法可以准确、公正地生成模型。
传统物流案例控制
病例对照抽样是一种基于“病例”(如反应)和“对照”(如无反应)的随机子样本建立模型的方法。不管子样本大小如何,只要子样本是以真正随机的方式抽取的,解释变量的 效应在病例和对照之间保持不变。例如,如果女性回答的可能性是男性的两倍,那么这种关系在病例对照数据集中和在全部人口水平数据集中同样准确。因此,我们可以准确地知道什么样的人可能会做出反应,什么样的人不会做出反应。
在压缩的病例对照数据集上建立了逻辑模型后,只需要调整模型的截距。虽然相对概率不会改变(例如男性/女性差异),但绝对概率会改变。例如,假设有 500 万受试者和 5000 个回答。如果病例对照数据集包含所有 5,000 个响应,加上 5,000 个无响应(总共 10,000 个观察),则模型将预测响应概率为 1/2,而实际上是 1/1000。当病例对照集中使用所有响应时,添加到逻辑模型截距的偏移量如下所示:
这里,n0 等于总体中的非事件数,而 n0 等于病例对照集中的非事件数。
提醒一下,在生存分析中,我们处理的数据集的分析单位不是个体,而是个体*周。以下非常简单的数据集展示了考虑采样的正确方式:
This technique incorrectly picks a few individuals and follows them over time.
This technique captures much more variability by randomly selecting individual observations from the data set.
生存分析病例对照和分层样本
当处理生存分析数据集时,事情变得更加复杂,特别是因为风险率。例如,如果一个人在第 2 周的反应可能是第 4 周的两倍,那么这个信息需要保存在病例对照集中。保护它的最好方法是通过分层抽样。
在分层抽样中,我们手动选择每周的病例数和对照数,以便在人群水平数据集和病例对照集之间每周的相对反应概率是固定的。这样,我们在构建逻辑模型时就不会意外地扭曲风险函数。
这很容易做到,从每周的未回复中抽取一定数量(例如 1000)。
这种方法要求使用可变偏移,而不是简单随机样本中的固定偏移。偏移值按周变化,如下所示:
同样,该公式与简单随机样本中的公式相同,只是我们不是查看整个数据集的响应和无响应计数,而是查看每周的计数,并为每周生成不同的偏移量 j 。
因为偏移每周都不同,所以这种技术保证了来自第周 j 的数据被校准到第周 j 的危险率。
逻辑回归代码
以下 R 代码反映了用于生成数据的内容(唯一的区别是用于生成sampled_data_frame
的采样方法):
glm_object = glm(response ~ age + income + factor(week),
data = sampled_data_frame,
family = "binomial")
使用factor(week)
可以让 R 为每个时间段拟合一个唯一的系数,这是定义风险函数的一种精确和自动的方式。可以手动定义一个危险函数,但是尽管这种手动策略可以节省一些自由度,但这样做的代价是大量的工作和操作员出错的机会,因此建议允许 R 自动定义每周的危险。
第三部分:比较抽样方法
此时,您可能会疑惑:**为什么要使用分层抽样?有什么意义?**这是真的:到目前为止,这篇文章已经提出了一些冗长而复杂的概念,却没有什么正当理由。
重点是分层样本产生的结果比简单的随机样本要精确得多。
为了证明这一点,我对下面的过程进行了 1000 次迭代:
- 首先,我采取了一定规模的样本(或“压缩因子”),SRS 或分层。
- 然后我从这个样本中建立了一个逻辑回归模型。
- 我使用该模型预测了一个单独测试集的输出,并计算了每个人的预测概率和实际概率之间的均方根误差。
以下是这种迭代采样的结果:
While both techniques become more accurate as the sample approaches the size of the original data set (smaller compression factor), it is clear that the RMSE for stratified samples is lower regardless of data set size.
很容易看出(并通过多因子方差分析得到证实),分层样本在数据压缩的每个级别都具有明显更低的均方根误差。同样,这是因为分层样本保留了风险率随时间的变化,而简单随机样本则没有。
第四部分:结论
首先,我们研究了在群体水平的数据集中考虑事件发生的不同方式,表明风险率是缓冲具有不完整观察值的数据集的最准确方式。
然后,我们讨论了不同的抽样方法,认为分层抽样产生了最准确的预测。这通过使用两种策略的多次采样和建模迭代得到了实证。
这种策略适用于随着时间推移低频事件发生的任何场景。在社会科学中,分层抽样可以观察一段时间内个人的再犯概率。在医学上,在给定某些风险因素的情况下,人们可以研究吸烟者因呼吸问题而去医院的概率的时间过程。在工程中,这种分析可以应用于设备的罕见故障。
虽然这些类型的大型纵向数据集通常不会公开提供,但它们确实存在——使用分层抽样和受控风险率对它们进行分析,是根据小样本事件得出关于人口范围现象的结论的最准确方式。
生存分析:直觉& Python 中的实现
有一种统计技术可以回答如下业务问题:
- 一个特定的客户会在你的公司呆多久?换句话说,这个客户经过多少时间会流失?
- 成功运行一年后,这台机器还能使用多久?
- 不同营销渠道的相对留存率是多少?
- 被诊断后,病人存活的可能性有多大?
如果你觉得上面的任何问题(或者甚至是与它们无关的问题)有趣,那么继续读下去。
本文的目的是建立一种直觉,以便我们可以在不同的商业环境中应用这种技术。
目录
- 介绍
- 定义
- 数学直觉
- 卡普兰-迈耶估计
- Cox 比例风险模型
- 结束注释
- 额外资源
简介
生存分析是一套统计工具,它解决了诸如“在一个特定事件发生之前,需要多长时间”这样的问题;换句话说,我们也可以称之为“事件时间”分析。这种技术被称为生存分析,因为这种方法主要是由医学研究人员开发的,他们更感兴趣的是发现不同群组(例如:群组 1-用药物 A 治疗,群组 2-用药物 B 治疗)中患者的预期寿命。这种分析不仅可以进一步应用于传统的死亡事件,还可以应用于不同业务领域中许多不同类型的事件。我们将在下一节详细讨论事件和事件时间的定义。
定义
如上所述,生存分析也被称为事件时间分析。因此,从名称本身来看,很明显,兴趣事件和时间的定义对于生存分析是至关重要的。为了理解时间和事件的定义,我们将为行业中的各种用例定义时间和事件。
- 机械操作中的预测性维护:生存分析适用于机械零件/机器,以回答“机器将持续多长时间?”。预测性维护是其应用之一。这里,事件 定义为机器发生故障的时间。 原点时间*定义为机器开始连续运转的时间。*除了时间的定义,我们还应该定义时间刻度(时间刻度可以是周、天、小时..).事件发生的时间和时间原点之间的差异给了我们事件发生的时间。
- 客户分析(客户保留):借助生存分析,我们可以专注于低生存时间的高价值客户的流失预防工作。这种分析还有助于我们计算客户生命周期价值。在这个用例中,事件 被定义为客户翻腾/退订的时间。 **起始时间定义为客户开始服务/订购某公司的时间。 时间尺度可以是月,也可以是周。事件发生的时间和时间原点之间的差异给了我们事件发生的时间。
- 营销分析(队列分析):生存分析评估各营销渠道的留存率。在这个用例中,事件 被定义为客户退订营销渠道的时间。 时间原点定义为客户开始服务/订阅营销渠道的时间。 时间尺度可能是月,也可能是周。
- 精算师:给定人群的风险,生存分析评估人群在特定时间范围内死亡的概率。这种分析有助于保险公司评估保险费。猜猜看,这个用例的事件和时间定义!!!
我希望从上面的讨论中可以清楚地了解事件、时间起源和事件发生时间的定义。现在是时候深入一点分析的数学公式了。
数学直觉
让我们假设一个非负连续随机变量 T** ,代表直到某个感兴趣的事件发生的时间。例如,T 可能表示:**
从客户订阅到客户流失的时间。
从机器启动到故障的时间。
从疾病诊断到死亡的时间。
既然我们假设了一个随机变量 T(随机变量一般用大写字母表示),那么我们也要讲一下它的一些属性。
T 是随机变量,‘这里什么是随机?’。为了理解这一点,我们将再次使用我们以前的例子如下。
T 是从客户(随机选择的客户)订阅到客户流失的时间。
T 是从一台随机选择的机器启动到故障的时间。
T 是从疾病诊断到随机选择的患者死亡的时间。****
****T 是连续的随机变量,因此它可以取任何实数值。 T 是非负的,因此它只能取正的实数值(包括 0)。
对于这类随机变量,常用【概率密度函数(pdf)****【累积分布函数(cdf)** 来表征其分布。**
因此,我们将假设该随机变量具有概率密度函数 f(t) ,以及累积分布函数 F(t) 。
pdf : f(t)
****cdf : F(t) 😗* 根据给定 pdf 中 cdf 的定义,我们可以将 cdf 定义为**F(T)= P(T<T);这里, F(t) 给出了事件在持续时间 t. 内发生的概率,简而言之, F(t) 给出了事件发生时间值小于 t. 的人口比例
cdf as the integral form of pdf
生存函数:S(T)= 1-F(T)= P(T≥T);S(t) 给出了事件在时间 t 之前没有发生的概率。简单地说, S(t) 给出了事件发生时间值大于 t. 的人口比例
Survival Function in integral form of pdf
**风险函数:h(t) 😗* 除了生存函数,我们还对事件发生的速率感兴趣,在任何给定时间 t 的存活人口中。在医学术语中,我们可以将其定义为“在时间 t 存活的人中,那些人的死亡率是多少”。
让我们把它变得更简单:
- 让我们把它写成它的定义的形式:
h(t) = [( S(t) -S(t + dt) )/dt] / S(t)
极限 dt → 0
2.从上面的公式中,我们可以看到它有两个部分。让我们理解每一部分
事件的瞬时速率:(S(t)-S(t+dt))/dt;这也可以看做生存曲线任意点 t 的斜率,或者任意时刻 t 的死亡率。
也让我们假设总人口为 p。
**在这里,S(t) -S(t + dt),这种差异给出了在时间 dt 死亡的人在时间 t 存活的人中所占的比例。在 t 存活的人数是 S(t)*P,在 t + dt 存活的人数是 S(t+dt)*P。在 dt 期间死亡的人数是(S(t) -S(t + dt))P。在时间 t 死亡的人的瞬时比率是(S(t) -S(t + dt))P/dt。
*时间 t 的存活比例:S(t);我们也知道 t,S(t)P 时刻的存活人口。
因此,用在时间 dt 死亡的人数,除以在任何时间 t 存活的人数,我们得到了风险函数,作为在时间 t 存活的死亡人数的风险度量。
风险函数不是密度或概率。然而,我们可以将其视为在(t)和(t+ dt)之间无限小的时间段内失败的概率,假设受试者已经存活到时间 t。在这种意义上,危险是一种风险度量:时间 t1 和 t2 之间的危险越大,该时间间隔内失败的风险就越大。
****我们有:h(t)= f(t)/S(t);【既然我们知道(S(t)-S(t+dt))/dt = f(t)】这是一个非常重要的推导。这个函数的美妙之处在于生存函数可以从风险函数中导出,反之亦然。当在 Cox 比例模型中从给定的风险函数推导出生存函数时,这一点的效用将更加明显(本文的最后一部分)。
这些是理解生存分析所需的最重要的数学定义和公式。我们将在这里结束我们的数学公式,并向估计生存曲线前进。
卡普兰-迈耶估计
在上面的数学公式中,我们假设了 pdf 函数,从而从假设的 pdf 函数中导出了生存函数。由于我们没有人口的真实生存曲线,因此我们将从数据中估计生存曲线。
估计生存曲线主要有两种方法。第一种方法是参数方法。这种方法假设一个参数模型,它是基于某种分布如指数分布,然后我们估计参数,最后形成生存函数的估计量。第二种方法是一种强大的非参数 方法,称为 Kaplan-Meier 估计器。我们将在这一节讨论它。在本节中,我们还将尝试手动以及使用 Python 库(生命线)创建卡普兰-迈耶曲线。
****在这里, ni 被定义为在时间 ti 之前处于危险中的人群;和 di 定义为时间 ti 发生的事件数。通过下面的例子,这一点将变得更加清楚。
我们将讨论一个来自非常小的自己创建的数据的任意示例,以理解手动以及使用 python 包创建 Kaplan Meier 估计曲线。
事件、时间和时标定义为例:
下面的例子(参见图 1)显示了一个网站的 6 个用户的数据。这些用户访问网站,并在几分钟后离开该网站。因此,感兴趣事件是用户离开网站的时间。原点时间定义为用户打开网站的时间,时间刻度以分钟为单位。研究开始于时间 t=0,结束于时间 t=6 分钟。
审查:
这里值得注意的一点是,在研究期间,6 个用户中有 4 个用户(显示为红色)发生了事件,而两个用户(显示为绿色)继续发生了事件,事件直到研究结束才发生;这样的数据称为删失数据。
在审查的情况下,就像这里的用户 4 和用户 5 的情况一样,我们不知道事件将在何时发生,但我们仍然使用该数据来估计生存的概率。如果我们选择不包括被删截的数据,那么很可能我们的估计会有很大的偏差和低估。包含用于计算估计值的删失数据,使得生存分析非常强大,并且与许多其他统计技术相比,它非常突出。
KM 曲线计算及解释:
现在,让我们来谈谈为创建下面的 KM 曲线所做的计算(参见图 1)。在图 1 中,Kaplan Meier 估计曲线,x 轴是事件发生的时间,y 轴是估计的生存概率。
从 t=0 到 t <2.5 or t∈[0 , 2.5), number of users at risk(ni) at time t=0 is 6 and number of events occurred(di) at time t=0 is 0, therefore for all t in this interval, estimated S(t) = 1. From the definition of the event we can say that 100% is the probability that the time between a user opens the website and exit the website is greater than 2.499 minutes.*
From t=2.5 till t<4 or t ∈ [2.5 , 4), number of users at risk(ni) at time just before time 2.5 minutes (2.4999 mins) is 6 and number of events occurred(di) at time t=2.5 minutes is 1, therefore therefore for all t in this interval, estimated S(t)= 0.83. From the definition of the event we can say that 83% is the probability that the time between a user opens the website and exit the website is greater than 3.999 minutes.**
From t=4 till t<5 or t ∈[4 , 5), number of users at risk(ni) at time just before time 4 minutes (3.999 mins) is 5 and number of events occurred(di) at time t=4 minutes is 2, therefore for all t in this interval, estimated S(t) = 0.5. 这个结果也可以通过相对频率的简单数学来验证。对于任何 t∈[4,5],假设 t=4.5,开始时用户总数是 6,t 时剩余的用户总数是 3。因此,用户在网站上花费超过 4.5(或任意时间 t ∈[4,5])分钟的概率为(3/6),即 50%。*
类似地,我们可以估计其他时间间隔的概率(参考图 1 中的表格计算)
数学上,对于任意时间 t ∈ [t1,T2],我们有
S(t) = P(在[0,t1]中生存)× P(在[t1,t]中生存|在[0,t1]中生存)
fig 1: a. Shows the user level time data in color.; b. Shows Kaplan Meier (KM)Estimate Curve; c. Formula for estimation of KM curve; d. Table showing the calculations
******# Python code to create the above Kaplan Meier curve****from** **lifelines** **import** KaplanMeierFitter
*## Example Data*
durations = [5,6,6,2.5,4,4]
event_observed = [1, 0, 0, 1, 1, 1]
*## create a kmf object*
kmf = KaplanMeierFitter()
*## Fit the data into the model*
kmf.fit(durations, event_observed,label='Kaplan Meier Estimate')
*## Create an estimate*
kmf.plot(ci_show=**False**) *## ci_show is meant for Confidence interval, since our data set is too tiny, thus i am not showing it.*****
现实世界的例子:
如前所述,生存分析可用于群组分析,以获得洞察力。因此,在这里我们将使用电信客户流失数据集,来深入了解不同群体中客户的生命线。
让我们根据客户是否订阅了流媒体电视来创建两个客户群。我们想知道哪个群体的客户保持率更高。
绘制存活估计值所需的代码如下所示。
****kmf1 = KaplanMeierFitter() *## instantiate the class to create an object*
*## Two Cohorts are compared. Cohort 1\. Streaming TV Not Subscribed by users, and Cohort 2\. Streaming TV subscribed by the users.*groups = df['StreamingTV']
i1 = (groups == 'No') *## group i1 , having the pandas series for the 1st cohort*
i2 = (groups == 'Yes') *## group i2 , having the pandas series for the 2nd cohort*
*## fit the model for 1st cohort*
kmf1.fit(T[i1], E[i1], label='Not Subscribed StreamingTV')
a1 = kmf1.plot()
*## fit the model for 2nd cohort*
kmf1.fit(T[i2], E[i2], label='Subscribed StreamingTV')
kmf1.plot(ax=a1)****
********
Fig 2: Kaplan Meier Curve of the two cohorts.
我们有两条存活曲线,每组一条。从曲线中可以明显看出,与没有订购流电视的客户相比,订购了流电视的客户具有更好的客户保持率。在时间线上的任意一点 t,我们可以看到蓝色群体的生存概率小于红色群体。对于蓝色队列,生存概率在前 10 个月快速下降,之后相对变好;然而,对于红色队列,存活率的下降率相当稳定。因此,对于尚未订购流媒体电视的群体,应努力在不稳定的前 10 个月留住客户。
我们可以从不同队列的生存曲线中做更多这样的队列分析。该队列分析代表了生存分析潜力的有限使用案例,因为我们将其用于数据的汇总水平。基于协变量对基线生存曲线的影响,我们甚至可以为单个用户创建生存曲线。这将是本文下一节的重点。
Cox 比例风险模型
群体中个体的事件发生时间对于总体水平上的生存曲线非常重要;然而,在现实生活中,除了事件数据,我们还有该个体的协变量(特征)。在这种情况下,了解协变量对生存曲线的影响是非常重要的。如果我们知道相关的协变量,这将有助于我们预测个体的生存概率。
例如,在上面讨论的电信客户流失示例中,我们有每个客户流失时的任期(事件时间 T)以及客户的性别、每月费用、受抚养人、合作伙伴、电话服务等。在这个例子中,其他变量是协变量。我们经常对这些协变量如何影响生存概率函数感兴趣。
在这种情况下,它是条件生存函数 S(t|x) = P(T > t|x)。这里 x 表示协变量。在我们的例子中,我们对 S(任期> t|(性别、每月费用、受抚养人、合作伙伴、电话服务等)感兴趣。
Cox(比例风险)模型是结合协变量和生存函数的最流行的模型之一。它从风险函数建模开始。
这里,β是每个协变量的 coefficients 向量。函数 h o (t)称为基线危险函数。
Cox 模型假设协变量在风险函数上具有线性乘法 effect,并且 effect 在整个时间内保持不变。
该模型背后的思想是,个体的对数风险是其静态协变量的线性函数,和是随时间变化的群体水平基线风险。【来源:生命线文档】
从上述等式中,我们还可以推导出累积条件风险函数,如下所示:
正如我们已经知道的,借助于上一节中推导出的表达式,我们可以从风险函数中推导出生存函数。因此,我们可以得到每个主体/个人/顾客的生存函数。
python 中的基本实现:
我们现在将借助 lifelines 包讨论它在 python 中的基本实现。我们使用了相同的电信客户流失数据集,我们已经在上面的章节中使用。我们将运行 python 代码来预测客户级别的生存函数。
******from** **lifelines** **import** CoxPHFitter*## My objective here is to introduce you to the implementation of the model.Thus taking subset of the columns to train the model.*
*## Only using the subset of the columns present in the original data*df_r= df.loc[:['tenure', 'Churn', 'gender', 'Partner', 'Dependents', 'PhoneService','MonthlyCharges','SeniorCitizen','StreamingTV']]df_r.head() *## have a look at the data*****
*****## Create dummy variables*
df_dummy = pd.get_dummies(df_r, drop_first=**True**)
df_dummy.head()****
*****# Using Cox Proportional Hazards model*
cph = CoxPHFitter() *## Instantiate the class to create a cph object*cph.fit(df_dummy, 'tenure', event_col='Churn') *## Fit the data to train the model*cph.print_summary() *## HAve a look at the significance of the features*****
********
上述汇总统计数据表明了协变量在预测客户流失风险方面的重要性。性别在预测流失方面没有起到任何重要作用,而所有其他协变量都很重要。
有趣的一点 这里要注意的是,在协变量为月度费用和性别 _ 男性的情况下,β (coef)值约为零(~-0.01),但月度费用在预测流失方面仍然起着重要作用,而后者则不显著。原因是每月费用是连续值,可以从几十、几百到几千不等,当乘以小系数(β=-0.01)时,它变得很重要。另一方面,协变量性别只能取值 0 或 1,在这两种情况下[exp(-0.01 * 0),exp(-0.011)]都将是无关紧要的。*
*****## We want to see the Survival curve at the customer level. Therefore, we have selected 6 customers (rows 5 till 9).*
tr_rows = df_dummy.iloc[5:10, 2:]
tr_rows****
*****## Lets predict the survival curve for the selected customers.*
*## Customers can be identified with the help of the number mentioned against each curve.*cph.predict_survival_function(tr_rows).plot()****
fig 2. It shows the Survival Curves at customer level of customer number 5,6,7,8, and 9
图二。显示了客户层面的生存曲线。它显示了 5 号、6 号、7 号、8 号和 9 号顾客的生存曲线。
在每个客户级别创建生存曲线有助于我们主动为高价值客户创建定制战略,以应对时间线上不同的生存风险段。
结束注释
尽管如此,还有许多其他的事情仍然需要在生存分析中涉及,如、【检验比例假设】、&、、;然而,通过对分析背后的数学的基本理解,以及生存分析的基本实现(使用 python 中的生命线包)将帮助我们在任何相关的业务用例中实现该模型。
额外资源
以下资源不仅对激励我研究生存分析非常有帮助,而且对我写这篇文章也非常有帮助。查看他们更多的生存分析。
生存分析—A 部分
生存分析的概念介绍及其在 Python 生命线包中的实现。
Photo by Markus Spiske on Unsplash
生存分析用于估计研究中特定人群的寿命。它也被称为**“事件时间”分析**,因为其目标是估计一个人或一群人经历感兴趣的事件的时间。这个时间估计是出生和死亡事件之间的持续时间[1]。生存分析最初是由医学研究人员和数据分析师开发并用于测量特定人群的寿命[1]。但是,多年来,它已被用于各种其他应用,如预测客户/员工的变动,估计机器的寿命等。出生事件可以被认为是客户开始成为公司成员的时间,而死亡事件可以被认为是客户离开公司的时间。
数据
在生存分析中,我们不需要确切的起点和终点。所有的观察并不总是从零开始。受试者可以在任何时候进入研究。所有的持续时间都是相对的[7]。所有受试者都被带到一个共同的起点,在这里时间 t 为零(t = 0 ),所有受试者的生存概率都等于 1,即他们没有经历感兴趣的事件(死亡、流失等)的几率是 100%。
可能会出现这样的情况:数据量太大,无法完全用于生存分析。对于这种情况,分层抽样可能会有所帮助。在分层抽样中,您的目标是在整个人群中,每组受试者的数量相等或接近相等。每一组称为一个地层。基于某些特征,整个人口被分层(划分)成组。现在,为了从每组中挑选一定数量的受试者,你可以使用简单的随机抽样。受试者的总数在开始时指定,你在每组中分配所需的总数,你从每组中随机挑选该数量的受试者[12]。
审查制度
重要的是要明白,在研究期间,并非所有人都会经历感兴趣的事件(死亡、流失等)。例如,将会有仍然是公司成员的客户,或者仍然为公司工作的员工,或者在观察/研究期间仍然运行的机器。截至研究时,我们不知道他们何时会经历感兴趣的事件。我们只知道他们还没有经历过。他们的存活时间比他们在研究中的时间要长。他们的存活时间因此被贴上了“审查”的标签[2]。这表明他们的存活时间是截止的。因此,审查允许你测量那些还没有经历过感兴趣的事件的人的寿命。
值得一提的是,没有经历感兴趣事件的人/受试者需要成为研究的一部分,因为将他们完全移除会使研究结果偏向于经历感兴趣事件的每个人。因此,我们不能忽略这些成员,将他们与经历感兴趣事件的成员区分开的唯一方法是使用一个变量来指示审查或死亡(感兴趣事件)。
生存分析中有不同类型的审查,解释如下[3]。请注意,审查必须独立于特定受试者的未来风险值[24]。
**右删截:**当受试者在 t=0 时进入,即在研究开始时进入,并在感兴趣的事件发生前终止。这可能是因为在研究过程中没有经历感兴趣的事件,即他们活得比研究持续时间长,也可能是因为没有完全参与研究,没有经历感兴趣的事件就提前离开了,即他们离开了,我们无法再对他们进行研究。
**左侧审查:**出生事件未被观察到时会出现这种情况。这里还应该提到另一个被称为长度偏差抽样的概念。当研究的目标是对已经经历过该事件的人/受试者进行分析,并且我们希望了解他们是否会再次经历该事件时,就会出现这种类型的取样。lifelines 包通过添加关键字left _ inspecting = True支持左删截数据集。请注意,默认情况下,它被设置为 False。例[9]:
间隔删截:当随访期,即观察之间的时间不连续时,会发生这种情况。这可以是每周、每月、每季度等。
左截断:简称迟录入。受试者在参与研究前可能已经经历了感兴趣的事件。有一个名为“进入”的参数,它指定了出生和进入研究之间的持续时间。如果我们填充截断的区域,那么它将使我们对诊断后早期发生的事情过于自信。这就是我们截断它们的原因[9]。
简而言之,在研究期间未经历感兴趣事件的受试者为右删截受试者,出生未被发现的受试者为左删截受试者[7]。生存分析的发展主要是为了解决右删失问题[7]。
生存功能
生存函数由下式给出,
生存函数定义了感兴趣的事件在时间 t 没有发生的概率。也可以解释为时间 t 后的生存概率【7】。这里,T 是取自总体的随机寿命,它不能为负。注意 S(t)在零和一(含)之间,S(t)是 t 的非增函数[7]。
危险功能
风险函数也称为强度函数,定义为受试者在一小段时间间隔内经历感兴趣事件的概率,前提是该个体一直存活到该间隔开始[2]。它是在一段时间内计算的瞬时速率,该速率被视为常数[13]。它也可以被认为是在时间 t 经历感兴趣事件的风险。它是在时间 t 开始的间隔内经历事件的受试者人数除以在时间 t 存活的受试者人数和间隔宽度的乘积[2]。
因为连续随机变量等于特定值的概率为零。这就是为什么我们考虑事件在从 T 到(That)的特定时间间隔发生的概率。因为我们的目标是找到事件的风险,我们不希望风险随着时间间隔δT 变大而变大。因此,为了对此进行调整,我们将等式除以δT,这将等式缩放了δT[14]。危险率的等式如下所示:
极限δT 趋近于零意味着我们的目标是测量某一事件在特定时间点发生的风险。因此,使极限δT 接近零会产生一个无限小的时间段[14]。
这里要指出的一点是,危害不是概率。这是因为,即使分子中有概率,但分母中的δT 可能会导致大于 1 的值。
卡普兰-迈耶估计值
Kaplan-Meier 估计值用于衡量在相同情况下存活一定时间 t[4]的受试者比例[2]。用于给出总体的平均视图【7】。这种方法也叫积极限。它可以生成一个叫做生命表的表格和一个叫做生存曲线的图表,以便更好地观察处于危险中的人口[2]。存活时间被定义为从预定点开始到感兴趣的事件发生的时间【5】。**Kaplan-Meier 生存曲线是在给定时间长度内生存的概率,其中时间被视为小间隔。**对于使用 Kaplan-Meier 估计值的生存分析,有三个假设[4]:
- 被审查的受试者和继续被跟踪的受试者有着相同的生存前景。
- 所有受试者的存活概率是相同的,无论他们何时被招募到研究中。
- 感兴趣的事件在指定的时间发生。这是因为该事件可能发生在两次检查之间。如果检查频繁发生,即如果检查之间的时间间隔非常小,则可以更准确地测量估计的存活时间。
任何特定时间的存活概率计算为存活的受试者人数除以处于危险中的人数。被审查的受试者不计入分母[4]。该方程式如下所示:
这里,ni 表示在时间 t 之前处于危险中的受试者的数量。di 表示在时间 t 感兴趣的事件的数量
对于 Kaplan-Meier 估计的存活曲线,y 轴代表受试者在时间 t 后仍未经历感兴趣事件的概率,其中时间 t 在 x 轴上[9]。为了了解我们对于点估计的不确定性,我们使用置信区间[10]。中位数时间是平均一半人口经历感兴趣事件的时间[9]。
尼尔森·艾伦钳工
像卡普兰-迈耶菲特一样,尼尔森艾伦菲特也给了我们一个总体的平均观点[7]。它由 t 时刻的死亡人数除以处于危险中的受试者人数得出。这是一个非参数模型。这意味着没有一个带有参数的函数形式来拟合数据。它没有任何适合的参数[7]。
这里,ni 表示在时间 t 之前处于危险中的受试者的数量。di 表示在时间 t 感兴趣的事件的数量
生存回归
生存回归不仅包括使用持续时间和审查变量,还包括使用额外的数据(性别、年龄、工资等)作为协变量。我们根据持续时间变量“回归”这些协变量。
用于生存回归的数据集需要采用(Pandas)数据框架的形式,其中一列表示受试者的持续时间,一个可选列表示是否观察到感兴趣的事件,以及需要回归的其他协变量。与其他回归技术一样,您需要在将数据输入模型之前对其进行预处理。
Cox 比例风险回归模型
Cox 比例风险回归分析模型是由 Cox 引入的,它同时考虑了几个变量的影响[2],并检查了生存分布与这些变量的关系[24]。它类似于多元回归分析,但不同之处在于因变量是给定时间 t 的风险函数。它基于非常小的时间间隔,称为时间点击,最多包含一个感兴趣的事件。这是一种估计比例风险模型中权重的半参数方法[16]。通过最大化权重的部分似然性来获得参数估计[16]。
梯度下降用于使 Cox 模型符合数据[11]。梯度下降的解释超出了本文的范围,但是它找到了使误差最小化的权重。
Cox 比例风险回归模型的公式如下所示。该模型的工作原理是,个体受试者的对数风险是其静态协变量的线性函数,也是随时间变化的人群水平基线风险函数。这些协变量可以通过部分似然估计[24]。
β0(t)是基线风险函数,它被定义为当所有其他协变量等于零时,经历感兴趣事件的概率。并且它是模型中唯一依赖于时间的组件。该模型没有对基线风险函数进行假设,并假设协变量对风险的影响为参数形式[25]。部分危险是一个不随时间变化的标量因子,仅增加或减少基线危险。它类似于普通回归中的截距[2]。协变量或回归系数 x 给出了危险中可预期的比例变化[2]。
回归系数的符号βi 在受试者的风险中起作用。这些回归系数或协变量的变化将增加或减少基线危害[2]。βi 的阳性符号意味着事件的风险更高,因此该特定受试者的感兴趣事件的预后更高。同样,负号意味着事件的风险较低。此外,请注意大小,即价值本身也发挥作用[2]。例如,变量的值等于 1 意味着它对危险没有影响。小于 1 的值会减少危险,大于 1 的值会增加危险[15]。这些回归系数β通过最大化部分似然估计[23]。
Cox 比例风险模型是一个半参数模型,在这个意义上,基线风险函数不必指定,即它可以变化,允许不同的参数用于每个独特的生存时间。但是,它假设在整个随访期内比率保持成比例[13]。这增加了模型的灵活性。全参数比例风险模型还假设基线风险函数可以根据生存时间分布的特定模型进行参数化[2]。
Cox 模型可以处理右删失数据,但不能直接处理左删失或区间删失数据[19]。
有些协变量可能不符合比例风险假设。他们被允许仍然是模型的一部分,但是不估计它的效果。这就是所谓的分层。基于分层协变量的唯一值,数据集被分成 N 个更小的数据集。每个更小的数据集都有自己的基线危险,这构成了模型的非参数部分,它们都有共同的回归参数,这构成了模型的参数部分。分层的协变量没有回归参数。
术语“比例风险”是指因变量和回归系数之间关系不变的假设[2]。因此,这意味着任何两个受试者在任何时间点的风险函数都是成比例的。比例风险模型假设协变量对风险函数有倍增效应[16]。
考克斯模型[23]提出了三个假设
- 两个受试者的风险比始终保持不变。
- 解释变量对风险函数有多重作用。
- 个体受试者的失败时间是相互独立的。
生命线包提供的一些内置功能【11】
- print_summary 打印系数和相关统计的表格视图。
- hazards_ 将打印系数
- **baseline _ hazard _**将打印基线危险
- **baseline _ cumulative _ hazard _**将打印 N 个数据集的 N 个基线危险
- _log_likelihood 将在拟合模型后打印最大对数似然值
- 方差矩阵将呈现拟合模型后系数的方差矩阵
- score_ 将打印出拟合模型的一致性指数
- 梯度下降用于使 Cox 模型与数据拟合。您甚至可以在 fit 函数中使用变量 show_progress=True 来查看拟合。
- 预测 _ 部分 _ 危险和预测 _ 生存 _ 函数用于推断拟合的模型。
- 图方法可用于查看系数及其范围。
- plot_covariate_groups 方法用于显示当我们改变一个(或多个)协变量,而保持其他一切不变时,生存曲线看起来是什么样子。通过这种方式,我们可以了解模型中共变量的影响。
- check _ assumptions方法将输出违反比例危险假设的情况。
- **weights _ col = ' column _ name '**指定包含代表某些采样权重的整数值或浮点值的权重列。您还需要在拟合方法中指定 robust=True 来更改标准误差计算。
艾伦的加法模型
与 Cox 模型一样,该模型也是一个回归模型,但与 Cox 模型不同,它将风险率定义为一个加法模型,而不是乘法线性模型。危险被定义为:
在估计过程中,每一步都会计算线性回归。由于样本量较小或数据集中的共线性较高,回归可能会变得不稳定。添加 coef_penalizer 项有助于控制稳定性。从一个小的期限开始,如果它变得太不稳定就增加[11]。
这是一个参数模型,这意味着它有一个函数形式,带有我们用来拟合数据的参数。参数模型允许我们将生存函数、风险函数或累积风险函数扩展到超过最大观测持续时间。这个概念叫做外推法[9]。威布尔模型的生存函数如下所示:
这里,λ和ρ都是正的,并且大于零。当模型符合数据时,它们的值被估计。危险函数如下所示:
加速失效时间回归模型
如果我们给定两个独立的总体 A 和 B,每个都有由 SA(t)和 SB(t)给出的生存函数,并且它们通过某个加速失效率λ彼此相关,这样,
它可以减慢或加快沿生存功能移动。λ可以建模为协变量的函数[11]。它将存活时间的延长或缩短描述为预测变量的函数[19]。
在哪里,
根据受试者的协变量,该模型可以加速或减速失败时间。xi 的增加意味着平均/中位存活时间以 exp(bi)[11]的因子变化。然后我们选择生存函数的参数形式。为此,我们将选择威布尔形式。
使用生命线包在 Python 中进行生存分析
第一步是用 Python 安装生命线包。您可以使用 pip 安装它。
需要指出的一点是,生命线软件包假设每个受试者都经历了感兴趣的事件,除非我们明确指定[8]。
生存回归拟合方法的输入,即 CoxPHFitter、WeibullAFTFitter 和 AalenAdditiveFitter 必须包括持续时间、审查指标和 Pandas 数据框架形式的协变量。持续时间和审查指标必须在 fit 方法的调用中指定[8]。
lifelines 包包含 lifelines.statistics 中的函数来比较两条生存曲线[9]。对数秩检验比较两个事件序列的发生器。如果从测试返回的值超过某个预定义的值,则该系列具有不同的生成器。
对数秩检验
这是一个非参数统计检验,用于比较两组的生存曲线。
和谐指数
这是一个最常用的生存模型的性能评估。它用于验证生存模型的预测能力[18]。它是预测的和观察到的存活率一致的概率。它是“在所有可实际排序的受试者中,其预测存活时间被正确排序的所有受试者对的分数”[16]。
型号选择
如果存在删失,那么我们不应该使用均方误差或平均绝对误差损失。我们应该选择和谐指数(简称 c 指数)。和谐指数评估预测时间排序的准确性。其解释如下[11]:
- 随机预测:0.5
- 完美一致:1.0
- 完美的反一致性:0.0(在这种情况下,我们应该将预测乘以-1,以获得完美的 1.0)
通常,拟合模型的一致性指数在 0.55 和 0.7 之间,这是由于数据中存在噪声。
我们也可以对 Cox 模型和 Aalen 加法模型使用 K-Fold 交叉验证。该函数将数据分为训练集和测试集,并根据训练集调整自身,根据测试集评估自身。该函数对每个折叠重复此操作。
在第二部分中,我们将在 Python 中实现生存(回归)分析来预测客户流失。
参考文献
[1]生命线:Python 中的生存分析:https://www.youtube.com/watch?v=XQfxndJH4UA
[2]什么是考克斯模型?斯蒂芬·J·沃尔特斯。www.whatisseries.co.uk
[3]应用生存分析:事件发生时间数据的回归建模,作者:小 David W. Hosmer,Stanley Lemeshow,Susanne May
[4]了解生存分析:卡普兰-迈耶估计:https://www.ncbi.nlm.nih.gov/pmc/articles/PMC3059453/
[5]统计评论 12:生存分析。贝维克 V,脸颊 L,球 j 暴击关怀。2004 年十月;8(5):389–94.
[6]奥特曼 DG。伦敦(英国):查普曼和霍尔;1992.生存时间分析。《医学研究实用统计》;第 365-93 页。
[7]生命线— 生存分析简介
[8]生命线— 快速启动
[9]生命线— 用生命线进行生存分析
[10]格林伍德和指数格林伍德。生存分析中的置信区间—s . Sawyer—2003 年 9 月 4 日
[11]生命线— 生存回归
[12]分层抽样,https://www.youtube.com/watch?v=sYRUYJYOpG0
[13]生存分析,第 3 部分:2017 年 11 月美国正畸和牙颌面整形杂志上的 Cox 回归文章
[14]生存分析中危害函数的定义:https://www.youtube.com/watch?v=KM23TDz75Fs
[15] Cox 比例风险模型— STHDA
[16]关于生存分析中的排名:和谐指数的界限——Vikas c . ray kar,Harald Steck,Bala Ji Krishnapuram CAD and Knowledge Solutions(IKM·CKS),Siemens Medical Solutions Inc ,(美国马尔文)和 Cary Dehing-Oberije,Philippe Lambin Maastro 诊所,马斯特里赫特大学医院,马斯特里赫特大学,荷兰 GROW
[17] 生命线—时变生存回归
[18] 和谐指数
[19]参数生存模型——克里斯托夫·德特韦勒和丁满·斯图基。9.2011 年 5 月
[20] StatQuest:最大似然,解释清楚!https://www.youtube.com/watch?v=XepXtl9YKwc
[21]考克斯(1972)
[22]d . r . Cox(1975 年)提出的部分可能性
[23] Cox 回归模型
[24]生存数据的 Cox 比例风险回归,见《应用回归指南》附录,第三版,John Fox & Sanford Weisberg
延伸阅读
- https://NCSs-wpengine . net DNA-SSL . com/WP-content/themes/NCSs/pdf/Procedures/NCSS/Cox _ regression . pdf
- https://stat . ethz . ch/education/semesters/ss 2011/seminar/contents/讲义 _9.pdf
- https://lifelines.readthedocs.io/en/latest/Quickstart.html
生存分析,了解客户保留
介绍
在当今竞争日益激烈的商业舞台上,客户维系是一个日益紧迫的问题。公司渴望发展客户保持重点和计划,以最大限度地提高长期客户价值。具体来说,客户保持的重要性;构思一个综合的客户价值/保留模型;并解释了使用细分如何帮助建立关系、保持策略和利润规划。我提出了一个解决方案,它整合了客户数据分析、建模和挖掘多个概念层次关联的各种技术,以形成一种直观和新颖的方法来衡量客户忠诚度并预测他们背叛的可能性。由这些“早期警告”引发的立即行动可能是最终留住客户的关键
(source: https://www.istockphoto.com)
客户保持和终身价值
任何契约式或订阅式商业模式的核心都是留存率的概念。一项重要的管理任务是获取给定客户群的一系列过去的保留数字,并将其投射到未来,以对客户任期、终身价值等做出更准确的预测。因此,客户终身价值(LTV)是数据库营销的基石之一。客户终身价值通常被定义为一个公司可以从客户那里期望的总净收入(Novo 2001)。确切的数学定义及其计算方法取决于许多因素,如客户是“订户”(如在大多数在线订阅产品中)还是“访问者”(如间接营销或电子商务)。
我们为什么要在乎终身价值?
在这篇文章中,我将讨论客户终身价值(LTV)的计算和商业用途。CRM 的商业智能单元任何为商业问题定制分析解决方案的公司,这些问题在行业中处于高度优先地位:合作和保留分析、欺诈分析、活动管理、信贷和收款、风险管理等等。LTV 在其中一些应用中扮演着重要角色,尤其是客户流失分析和客户保持活动管理。在流失分析的背景下,客户或细分市场的 LTV 是其流失概率的重要补充信息,因为它提供了一种因流失而真正损失多少以及应该在该细分市场上集中多少努力的感觉。在留住人才的活动中,主要的业务问题是在留住人才方面投入的资源与目标细分市场 LTV 的相应变化之间的关系。
生命周期价值模型的组成部分
一般来说,一个 LTV 模型有三个组成部分:随着时间推移的客户价值,客户的服务年限和贴现因子。每个组成部分可以单独计算或估计,也可以将它们的模型结合起来。当在保留活动的背景下对 LTV 建模时,还有一个额外的问题,即需要计算客户在保留活动之前和之后的 LTV。换句话说,我们需要为每个客户或细分市场计算几个 LTV,对应于我们可能想要开展的每个可能的保留活动(即我们可能想要建议的不同激励措施)。能够估计这些不同的 LTV 是成功和有用的 LTV 应用程序的关键。
为什么要进行生存分析?
让我们从一个简单的动机和问题开始,有时我会被问及平均订阅时间和客户在公司的时间。例如,我们有九个客户,条形图跟踪他们的平均订阅时长。绿条表示仍在使用的客户,红条表示不再使用的客户。
那么,平均订阅时长是多少?然而,需要问的一个问题是,是否只取 CRM 数据库中所有这些客户或仍在活动的客户的平均值?
如果下个月采用平均订阅时长,可能会变得完全不同。从本质上说,这是一个我们试图观察的移动目标。第二种情况是忽略活跃的人,只看不活跃的人,然后看他们的平均值。这也不能解决问题,因为有些客户会变得不活跃。因此,我们正在大规模地偏向我们的数据集,让已经取消的客户无法直接得到我们想要的东西。综上所述,这些讨论表明,我们对数据有一种感觉,我们还没有实际观察到我们试图测量的终点,因此本质上像这样取平均值永远不会是明智的做法。
行动中的生存分析
为了衡量上面提到的问题,我们需要生存分析来估计特定人群发生事件的时间,当你可能不知道所有你知道的,看到所有事件发生时,这都是你的数据点。生存分析在统计学中是一个非常古老的概念,它被广泛使用,例如,在医学统计学中,这并不是一个很好的例子。癌症后的存活率和人们存活 5-10 年的概率都是生存分析。回到我们关心的是我们的客户,我们关注的是客户何时注册并开始从免费试用转向付费订阅,以及我们认为他们将在多长时间内开放使用服务,这显然会成为 it 的终身价值。
(https://www.canstockphoto.com)
生存分析定义
首先,浏览一些定义来从概念上理解生存分析是一个好主意。我们将关注大写 T,这是客户订购结束的时间。这显然大于零。然而,如果顾客从不搅动,它可能是无限的。这是我们关心的数量,这将帮助我们理解终身价值,这基本上是客户在未来任何一天都没有搅动的概率。这是非递增函数。总的概率也很重要,那就是在每一个无限小的日子里会发生什么。我们通过风险函数来定义这一点,风险函数是在任何给定的一天 T,即客户流失的确切日期,不是前一天也不是后一天。正如你所料,这两件事是相关的,但这就像一点基本概率,你可以证明,基本上生存函数是以相对简单的方式,用风险函数来表达的。
套餐选择
在 Python 中,我们有两个主要的包生命线和 scikit-survival 包。救生索是较长的包装,重量很轻。尽管如此,它也提供了非常好的视觉效果。这两者都是基于他们的 scikit-learn。人们可以像使用任何 scikit-learn 包一样使用它们,并将其放入管道中。
资料组
数据集——这里我们使用了客户流失。这个想法是用数据科学的视角,用数据带领读者走过客户维系的整个周期。我们从理解问题的商业视角开始。然后,我们将使用可用的数据集来获得洞察力,并构建一个用于未来数据的预测模型。
特征工程
我们有很多分类数据,特别是像伴侣、家属、合同等。有一个标准的热门娱乐方法,你只需要根据类别把它变成 n 或 n 减 1 的二元特征。如果你还记得 cox 模型的样子,这对 X 来说是很好的:这意味着我们有一个系数附加到每个分类变量上。因此,我们将非常清楚地了解每个类别的影响。这将导致一个巨大的数据集,因为我们已经得到了维数灾难。
生存建模
- 提取生存函数的 Kaplan-Meijer 估计
- Cox 比例风险回归分析
生存函数的 Kaplan-Meijer 估计值
该函数给出了客户在 t 点之前不会流失的概率。生存函数的对应函数是累积风险函数。它描述了累积风险,或客户在时间 t 之前发生搅动的概率。
我们关心的是客户的生存函数 T 的数量以及他们在第 T 天仍然是客户的概率。在实践中,我们不能仅仅因为我们对数据的感觉而知道这个函数,所以我们可以使用函数的 kaplan-meier 估计来估计它,它本质上是建立在客户比率的所有乘积的基础上的。
风险率也称为死亡率或瞬时事件率,描述了在时间 t 前后的一小段时间内发生事件的风险,假设该事件尚未发生。由于社会的真实形式很少为人所知,生存分析的一部分涉及其估计,Kaplan-Meier 估计器考虑了流失客户的数量和所谓的“处于风险的数量”,即仍在合同中并可能在未来流失的客户。
当我们运行上面的代码时,我们得到了一个类似这样的图,我们可以看到置信区间非常接近。因此,我们的模型很好地逼近了这些数据中的真实生存曲线。最后,我们可以回答客户的平均订阅时长是多少;实际上是在读取我们有 50%的可能性,他们仍然是客户之前,客户预期存活的中间时间。这反过来又给了我们客户在这条生存曲线中的预期天数,我们认为他/她会在那里。
人们可以看到这种分析如何对我们的预期产生真正的影响,即我们认为某人会成为客户多久;这反过来影响客户的终身价值。最后,我们可以做的是对此进行扩展,建立一个回归模型,根据我们对客户的所有了解,尝试估计生存函数。
**Cox 模型::**生存回归
最常用的模型是 Cox 比例风险模型,它用于将同时考虑的几个风险因素或暴露与存活时间相关联。在 Cox 比例风险回归模型中,效果的度量是风险率,它是失败的风险(即,遭受感兴趣的事件的风险或概率),假设参与者已经存活到特定时间。它被称为比例风险,因为在给定的时间点上,每两个顾客的风险比率是恒定的。随着时间的变化被编码在基线风险函数 zero 中,并影响所有功能,如我们可能放入这个世界的合同、流媒体电影/电视。顾客被编码为这种类似于常数的术语,随着时间的推移,它对风险有着持续的影响。
然而,有一点需要注意的是,cox 模型是最常用的模型,但它有一个假设,即所有影响都是不变的;这可能不是真的。有许多因素可能会违背这一假设。类似于。例如,一个客户在一段时间内获得的退款总额会发生变化,然后随着时间的推移对生存产生不同的影响,因此,仅仅使用考克斯模型可能不是明智的选择。在你开始模拟客户和他们的终身价值以及我们认为他们会成为客户多久之前,你必须进行仔细的检查。
模特培训
Cox 比例风险模型符合一个相对简单的方式。汇总结果看起来像是我们已经输入了一些特征,然后你可以读出系数和系数的指数,这最终是我们将要乘以你的危险率的东西。这是真正告诉我们某个特性的影响,以及模型找到适合这个特定特性的模型的可信度的数量。
我们可以看到第二条线下的安全指数是 0.67。如果指数越大,系数对生存函数的影响就越大,而系数越低,意味着风险率越低。因此,我希望顾客能停留更长时间。因此,这是一个强有力的指标,表明客户的风险率大大降低,并最终成为客户的时间会更长。如果一个系数非常接近一个系数,这意味着它基本上没有影响,而且模型也不能真正可靠地找到这个参数的位置。它可能在某个非常靠近任何一边的地方。因此,在现实中,我们只想从模型中去掉系数接近 1 左右的变量,因为它并没有告诉我们太多,它只是一种噪音。
和谐指数
像开发任何预测模型一样,使用适当的性能测量来验证生存模型的性能是至关重要的。虽然已经提出了许多这样的方法,但我们使用的是一种叫做和谐指数的方法。本质上,它是测量有序对,以及在我们的数据集中,你对每一个可能对的排序有多好。例如,我们把我们所有的数据和所有的预期时间的预测,这将使人们成为一个明显大于 0 的客户。一致性指数的评分方法与曲线下面积(AUC)评分方法相同。实际上,它在 0.5 和 1 之间,而不是 0.5,就好像我们只是,你知道,完全随机地把所有东西放在棋盘上,一个会是路径上每个人的完美排序,他们显然越接近 1,你的模型就越精确。
客户层面的生存预测
我们建立了一个 cox 比例风险模型。我刚刚随机抽取了 1%的数据作为测试,这些都是他们对生存曲线的预测。
我们可以在这里看到一些东西,其中一条线没有相交,这也是好的,这来自于我们的比例假设,因为曲线的形状是由基线风险函数给定的,它是如何相对于特征上下移动的。
此外,我们还可以推断出快乐的顾客是什么样子,也可以读出不快乐的顾客是什么样子。最重要的是,这为我们的客户提供了一个预测,以及对你将成为客户多久的预期,并有一种直觉,什么是快乐的客户,什么是人们没有真正参与我们的服务的地方,然后显然我们可以利用这一点来尝试和提高保留率,改善为每个人提供的服务,以及更好地了解保留率和终身价值。
Python、数据和客户生存
这种方法将被证明有助于扩展我们对客户流失的理解,当客户结束与企业的关系时,客户流失是决定企业收入的最基本因素之一。企业需要知道他的哪些客户是忠诚的,哪些客户有流失的风险,你需要从客户的角度了解影响这些决策的因素。这篇博客解释了如何在分类问题之外解决客户保留问题,并使用生存分析方法来预测客户是否有流失的风险。这个博客还挖掘了针对性营销的指示性途径的见解和发现。
👋感谢阅读。如果你喜欢我的作品,别忘了喜欢,跟着我上传媒。这将激励我为媒体社区提供更多的内容!😊
参考资料:
布拉特伯格等人(2008):《数据库营销:分析和管理客户》。Springer
Rooset 等人(2002):客户终身价值建模及其在客户保留计划中的应用
CamDavidsonPilon/lifelines:v 0 . 22 . 10
Cox 比例风险模型— STHDA
【要点-语法-主题】:https://github.com/lonekorean/gist-syntax-https://towards data science . com/survival-analysis-intuity-implementation-in-python-504 FDE 4 fcf 8 ehttps:/
生存建模—加速故障时间— XGBoost
简介
生存分析是一个“删失回归”,其目标是学习事件时间函数。这类似于数据点未经审查的普通回归分析。生存建模没有回归和分类那么有名。因此,我将用例子更详细地解释它。这是一个有数据审查的建模任务。删失数据是指在研究期间感兴趣的事件没有发生,或者由于某些原因我们无法观察到感兴趣的事件的数据。
审查类型和实例
左侧审查发生在我们开始研究/活动时,并且该事件已经发生,导致更高的示例 —我们希望研究给定报价的用户购买新 iPhone 的情况,但一些用户可能已经购买,丢弃这些数据是没有用的。
区间删截用于当我们不知道事件的确切时间,并且它可能在两个时间区间之间发生时。例如,用户购买保险,但不确定购买的确切日期。
右删截用于研究期间未发生的事件。示例—癌症患者接受的治疗。
Censored Data-Types
事件时间建模对于理解用户/公司的行为至关重要,不仅限于信贷、癌症和流失风险。
Cox 比例风险模型是一个半参数模型,其中我们使用预测器对风险比进行建模,而在加速故障时间中,使用预测器对生存时间的日志进行建模。这是参数生存模型,因为我们假设响应数据的分布。
下面是生存模型的流程图-
Flow Chart — Survival Machine Learning
最新技术水平
基于树的模型改进了监督学习,在 Kaggle 上获得了许多奖项,在行业中也表现得更好。我们在 R 和 python 中实现了梯度推进模型,用于 Cox 比例风险函数和加速故障时间。为生存建模开发更多的基于树的模型也是很自然的。比如— GBM,mboost,Scikit-survival 等等。目前,XGBoost 支持没有基线预测的 Cox-Ph 模型。因此,我们在 Xgboost 中包含了加速故障时间,以提高生存建模支持。
数据类型支持
大多数生存模型只支持正确的删失数据类型。我们通常有 4 种类型的数据— 右数据、左数据、区间数据和未经审查的数据。右删失是最常用的删失数据类型。了解其他审查类型也很重要。
分布类型支持
加速故障时间建模是参数生存建模,其中生存时间遵循一定的分布,不同于 Cox 比例风险模型。我们支持 3 种类型的分布——正态分布、逻辑分布和极端分布。正态分布是最常见的分布类型,但它有一个细尾,在厚尾事件或极端事件的情况下,这可能不是正确的选择。
还不如形象化一点。
import numpy as np
import seaborn as snssns.distplot(np.random.normal(0,1,200),hist=False,label=”Normal”)
sns.distplot(np.random.logistic(0,1,200),hist=False,label=”Logistic”)
sns.distplot(np.random.gumbel(0,1,200),hist=False,label=”Extreme”)
Distributions-Density
当数据有厚尾时,逻辑/极端会导致更好的结果。
超参数调谐
超参数优化是机器学习的重要任务之一。我们将响应的误差(\sigma)和基本分数作为超参数。有许多方法可以找到最佳超参数。
网格搜索就是其中之一。我们已经使用 GridSearch 找到了最佳的超参数。
对于区间删失数据集,我们也可以从σ等于 y 较低σ和 y 较高σ的平均值开始,因此对于不同的删失数据集,基础分数等于 y 较低和 y 较高σ的平均值。
真实例子
这里我们使用了可用的芯片序列数据集。它有多个数据集。数据集的输出/响应是对数变换的。我们将使用 5 个数据集——ATAC _ JV _ 脂肪、CTCF _ TDH _ 编码、h3k 27 AC-h3k 4 me 3 _ TD ham _ BP、 H3K27ac_TDH_some 和 H3K36me3_AM_immune 。在所有数据集中,都已经定义了褶皱。
基础分数和适马是关键的超参数。
下面是用不同分布和 sigma 生成加速失效时间性能的代码。
结论
参数删失回归——加速失效时间是 Cox 比例风险模型的一个强有力的替代方案。我们需要在不同的基于树的模型中对上述模型提供更多的支持,比如 gradient boosting、XGBoost 和 LightGBM。我们现在已经在 XGBoost 中实现了。大多数数据集是平坦的,而改变 sigma 意味着我们可能需要更多的迭代。正常情况下,西格玛起着至关重要的作用,因为当西格玛增加时,它会被奉承。
超参数调整在这里是一个重要的方面,因为我们可能会发现没有训练/测试损失的移动。很快 XGBoost 包中的所有人都可以使用它。
参考文献
[1] 项目描述
[2] 更多细节
P.S. —我们已经将与此相关的论文提交给 NeurIPS — 2020,论文的 Arxiv 版本在这里—https://arxiv.org/abs/2006.04920。
适者生存…模式
分类的进化观点
只有最适合的模型才能存活!多年来,这一直是数据科学家和统计学家的一项主要任务,即找出一种方法来捕捉数据中的预测本质。诚然,人们可能会认为最好的预测模型是优秀的实验设计、数据收集和特征工程的结果,但机器学习概念和算法的进步也有助于我们做出更好的预测。
从进化的角度来看我们所掌握的预测方法是很有趣的。预测建模领域的进步使得算法更智能、更高效,并且适用于更多场景。这篇文章并不是要对每种方法进行彻底的剖析,而是要表明研究建模领域的进步是理解每种方法的机制的一种奇妙的方式。最后,我将进行一次小规模的测试,比较每个型号的性能。
预测模型进化链
在我的预测模型进化层次结构中,我不会涵盖所有的方法——那会花费太长时间。相反,我选择了一些非常流行的预测建模技术,它们最能说明预测结果的“演变”。
抛硬币
让我们从抛硬币开始吧!谁不能说他们从未通过抛硬币做出决定?虽然不是传统意义上的预测模型,掷硬币仍然可以用作决策过程。我们都知道,一枚硬币有 50%的机会是正面或反面,因此,在二进制情况下,有 50%的概率将类别指定为 0 或 1。
这个类纯粹是随机决定的,所以不是一个很好的分类器。把这看作是我们进化链的开端——我们的草履虫——以及其他更高级物种模型改进的基础。
逻辑回归
进化的第一阶段是数学方法,以及解决分类问题的事实上的统计方法——逻辑回归。可以使用协变量的线性组合建立一个方程来预测反应,即结果的对数概率。logit 函数能够拟合一条回归直线,该直线最好地描述了结果的对数优势的变化。
逻辑回归是一种非常稳定和有效的方法,具有易于解释的输出,这使得它成为用于分类问题的有效的首选模型。当您面对大量数据时,逻辑回归的最大限制就来了——指定所有可能的相互作用和捕捉更复杂的关系将更加困难(尽管并非不可能),并且在尝试估计模型参数时可能会遇到收敛问题。此外,它仍然是一个参数模型,所以数据必须满足逻辑回归有效的某些假设。
因此,在进化的下一阶段,我们需要找到一种方法来有条不紊地处理这样的情况:我们可以轻松地捕捉数据中的非线性关系,但仍能实现高水平的分类准确性。
手推车
有了分类和回归树(CART),我们开始远离统计学,进入机器学习的世界。通过递归划分预测器空间,构建决策树来对结果进行分类。CART 贪婪地搜索将最小化损失函数的可变分裂,在分类的情况下,损失函数是称为基尼指数的纯度度量。这衡量每个结果类的树的节点(或叶子)的纯净程度。
这可以很容易地通过用非常流行的 iris 数据集创建一个快速模型来可视化。
如您所见,决策树实际上只是一堆“如果-那么”语句。请注意,根节点是如何从平衡的数据组开始的,以及随后的每次拆分,决策规则是如何制定的,以使后续节点的同质性最大化。我们剩下的终端节点由 100%的 setosa,91%的 versicolor 和 98%的 virginica 组成。
决策树算法对于包含更复杂关系的数据非常有用。这是一种非参数、非线性的数据建模方法,非常容易实现。CART 的最大缺点是它有过度拟合数据的倾向,这可能导致模型在看不见的数据上表现不佳。修剪方法(即设置树的最大深度)可以帮助模型更具普遍性,但我们也可以给我们的模型一些罕见的糖果,看着它演变成模型的下一个阶段:整体。
装袋和随机森林
想象一下,有 10、100 甚至 1000 棵树可供我们用来做预测。像这样将多个预测工具组合成一个预测模型被称为集成方法。产生多个模型,并通过一种称为引导聚合或“bagging”的方法对整个集合的类别预测进行平均
这意味着每棵树在其集合中都必须有某种随机过程,以便对预测过程做出不同的贡献——如果每棵树都是相同的,那就没什么用了!这是通过用替换采样训练数据来实现的。这样,每棵树都是不同的,因为它们是通过对数据集的不同部分进行采样而构建的。
这些树非常深,旨在对数据进行过度拟合,以便学习更复杂的关系,但每个树都是不同的,因为它们是通过对数据集的不同部分进行采样而构建的。如果你考虑偏差-方差权衡,每棵树都能够大大减少偏差,但代价是在估计者之间产生更大的方差。对这些估计值的结果进行平均有助于减少方差。
随机森林采用 bagging 的思想,除了对训练数据进行采样之外,还通过在每个树分裂处随机选择变量的子集来增强算法。这有助于使集合中的树不那么相似,并允许不同的变量影响结果,从而进一步减少差异。
所以这太棒了!我们可以通过给多棵树装袋来减少手推车的过度装载问题。但是如果我们不想让估计者过多呢?有没有一种方法,我们可以用不同的方式来构建系综?
助推算法
通过进化,物种经历了基因构成的变化。在下一阶段,仍然使用树集合方法,只是这一次,树的设计方式发生了变化。还记得我在 CART 中说过我们可以修剪树来得到一个更一般化的估计量吗?Boosting 算法使用弱学习器(非常小的树或“决策树桩”)的集合可以比随机森林中的深度学习器表现得更好。
这些树不仅大小不同,而且它们之间的互动方式也不同。使用 bagging,可以并行构建各个分类器,并在最后进行平均。在 boosting 中,分类器是按顺序建立的,每个后续的树都可以改善其前一个树产生的错误。这样,就有了一种系统化的方法来改进先前模型的不足之处,并在将所有模型组合到整体分类器中时将误差降至最低。
有几种流行的增强方法,即自适应增强和梯度增强。如果集合是一个物种,可以把 boosting 看作是一种类型的属,后面是这些独立的分类器家族。如上所述,它们都有相同的直觉,但是采用不同的方法来最小化建模误差。简而言之:在自适应增强中,被一个模型错误分类的观察值在下一个模型中的权重更大,数据在重新加权的数据集上进行训练。在梯度提升中,不是在重新加权的训练数据上拟合后续模型,而是以最小化损失函数为目标,直接对先前分类器的误差进行建模。可以这样想,如果一个额外的分类器能够纠正前一个模型的一些错误,那么这个分类器的错误将小于前一个模型的错误。在集合结束时,误差应该被最小化。
神经网络
现在我们已经到了进化的最后阶段:神经网络。由于缺乏更好的过渡到这种类型的模型,想象一个外来物种降落到我们的预测模型空间,并开始以数据为食。它吸收的数据越多,它就越能学习,变得越强大。
假设你想用一组变量来预测一个结果。在神经网络空间中,这些分别被称为“输入”和“输出”。输入在网络中传播,经过称为隐藏层的不同节点层,直到它们到达网络末端的输出层。
后续层中的每个节点接收来自前一层中所有节点的“信号”。例如,来自输入层的每个值(或信号)被发送到第一个隐藏层中的所有节点,并且每个连接被分配一个权重(与回归方程中的系数相似)。激活函数/非线性变换被应用于加权值的和,以给出下一个节点(或神经元)是否激活的二元决策。另一项称为偏差,在应用激活函数之前添加到加权值的总和中,其作用类似于回归中的截距,控制神经元激活之前需要的权重总和。
该过程最终确定输出层中节点的强度,其中最强的输出节点成为由模型决定的分配类别。然后,神经网络测量响应中的误差,并递归地“反向传播”误差,以重新调整每个前面节点的权重,实质上是“学习”更准确地表示正确结果所需的最佳权重。
因此,有了大量的训练数据,神经网络可以学习有用的模式来对结果进行分类。这对于分析非常高维的数据特别有用,就像您在处理图像识别一样。一幅 64×64 的小图像就有 4096 个特征可以添加到神经网络的输入层。
模拟
我在这里展示了模型的层次结构,但是哪一个是“最合适的”将在很大程度上取决于您的数据。假设我们只关心预测精度,我设计了一个小模拟来确定适者生存模型。参见我的 github repo,获取用于该模拟的完整 python 代码。
在第一轮中,我模拟了一个包含 10,000 个观察值和 50 个变量的数据集,其中包括一些信息性特征、一些引入共线性的冗余特征和一大组无用变量,以测试模型使用信息性特征的能力。数据被分成两类,我在数据中引入了一点噪声,使问题变得更困难。
第一轮:训练数据大小
对于模拟的第一部分,我只是想了解每种方法是如何处理大量数据的。我根据可用的训练样本数量,绘制了每个模型预测测试数据集的能力的准确度。
逻辑回归非常稳定,但如果不进一步调整,可能无法提取数据的任何非线性特征。CART 在大多数情况下表现稍好,但变化很大,无法达到集合模型获得的精度。Random Forest 和 XGBoost 对这些数据的表现非常相似,神经网络赶上了这些模型,但只有当更多的训练数据可用时。
第二轮:烘焙比赛
在测试中,我创建了 1000 个不同的随机数据集,与第一轮中使用的相似,但行数和列数不同,并比较了不同分类器之间模型准确性的点估计。数据没有增加太多的复杂性,所以平均来说,每种方法的得分都很高。
我对所有这些模型都进行了最小的调整,这并不是每种方法能力的最佳表现,但为了本文的目的,它便于比较。
虽然我提出了模型的“进化”,并将这篇文章命名为“适者生存”,但这里没有一个模型有灭绝的危险。根据分析的目标(预测与推断)和数据的性质,一种模型可能比其他模型更适合。希望通过这篇文章,我能够说明每种方法的好处,以及它们是如何在彼此的基础上解决预测问题的。
数据科学和机器学习中的生存偏差
source: unsplash — free stock images
关于缺失数据,亚伯拉罕·瓦尔德教会了我们什么
今天我们要谈谈偏见。所以第一个公平的问题是,什么是偏见,对吗?
偏置
/ˈbʌɪəs/
名词
- 以不公平的方式支持或反对某个人或事物的行为,因为允许个人观点影响你的判断
- 偏爱某一特定主题或事物的事实
- 影响你判断的不公平的个人观点
- 允许个人观点不公平地影响你的判断
- 更喜欢某人或某事的事实
如果我们对这些定义进行一些 NLP,我们肯定会对世界上的“特定”、“个人”、“观点”或“偏好”有所了解,但是,我认为下面的定义正好符合我们在数据科学中经常提到的“偏见”一词的含义:
- 信息不正确的事实,因为收集或提供信息的方法不正确
记住这个定义,几个月前在阅读查尔斯·惠兰的《赤裸裸的统计数据》一书时,我发现了一段特别有趣的摘录,他在其中表达了尽管人们经常谈论“用统计数据撒谎”,但他认为实际上一些最糟糕的统计错误(或“错误”)涉及“用数据撒谎”,而不是“T21”。在这场争论之后,但通常是真实的肯定,在章节*“数据的重要性”*的以下几页中,他谈到了通常影响我们数据分析的几种偏差:选择偏差、出版偏差、回忆偏差、健康用户偏差,以及我们接下来要谈到的一个偏差……生存偏差。
通常也被称为“生存”而不是“幸存”偏见,这种类型的偏见发生在我们专注于通过一些选择过程成功的人或事的时候。忽略那些没有的,通常是因为它们缺乏可见性。这可能会以几种不同的方式导致错误的结论,或者对某种情况的过于乐观的分析。
但是让我们从头开始:这种特殊类型的偏见何时以及为什么被命名为“生存”偏见?在第二次世界大战期间,美国陆军旨在实施统计和科学,以在敌人之间的战斗中获得竞争优势。这不再仅仅是关于谁拥有最大的军队,现在由于新技术的出现,一支最小但装备精良的军队可以面对一支更大的军队。在这种背景下,美国成立了 11 个不同专业的研究小组,统称为应用数学小组。他们的工作是解决陆军在战场上遇到的问题,并试图找到某种数学见解,以便给美国带来战术优势。
应用数学小组接手的一个问题是飞机的生存能力,因为那时,一架去战斗的飞机基本上有 50%的机会在战斗结束时安全回家。因此,提高这种可能性,即使只是一点点,也可以在这个领域产生巨大的影响。负责分析并试图改进的人是亚伯拉罕·瓦尔德。为了做到这一点,亚伯拉罕想出了一个非常简单且符合逻辑的解决方案:当一架飞机从战场上回来后,他让战场上的人在一张卡片上标出飞机被击中的部位。
这是一件非常简单且符合逻辑的事情。如此简单,以至于当军队中的人开始看到这些卡片时,当然,由于重量的限制,你不能加固飞机的每一个部分,他们很快就能直观地看到飞机被击中几次的地方,并命令立即加固那些区域,而且只加固那些区域。然而,当沃尔德发现这一点时,他指出了他们逻辑中隐含的生存偏见:与其强化那些高度标记的区域,不如强化其他所有的区域!
为什么你会想知道?嗯,那些回来的飞机实际上能够在所有标记的地方被击中,然后返回基地。他们确实是幸存者!所以可以肯定的是,在飞机的任何其他部分,没有返回的飞机被击中,因此,这些部分需要加强。
这就是“生存偏见”这个名字的由来。从那以后,事实证明这是一种特别危险的偏见。主要是因为它在我们的日常生活中非常非常普遍。有时候我们甚至没有意识到,但是例如,当我们看一个 Ted 演讲,一个人战胜了巨大的逆境或者在生活中取得了巨大的成功,我们正在以一种非常偏见的方式寻求建议。从一个非常特殊的人那里寻求建议,忽略了那些没有成功的人的观点和行动。虽然这不一定是错的,但是看看那些有潜力的、尝试过的和失败的人会更有用,这样可以避免导致他们失败的错误。
不幸的是,我们的大脑习惯于以这种方式思考和处理。这就是生存偏见如此危险的原因。让我们来看看其他一些日常的和平庸的例子……看看它们是否让你想起了什么:
- 背景:35 岁的家伙|“嗯…威尔和亚当已经打了一年的橄榄球,他们看起来身材棒极了…也许我应该试试。”
- 背景:20 岁学生|‘嘿……史蒂夫·乔布斯、比尔·盖茨和马克·扎克伯格从大学辍学,成为百万富翁,我也一样’
- 背景:夏天走在海滩前的街道上|“看看这些海鲜餐馆,挤满了人……我们在家里开一家吧!”
- 上下文:有人在选手机|“我认识的人中有一半人都有这款手机,没人对它有什么不好的看法……我应该买一部”
- 背景:一位父亲在为他的孩子评估一所高中|“这所高中一定很棒……三位在职的创始人去过那里,看看他们在哪里”
source: https://www.explainxkcd.com/wiki/index.php/1827:_Survivorship_Bias
为了更好地理解这种偏见,让我们回顾一下 Charles Wheelan 在《裸统计数据》中使用的一个例子:
假设一所高中的校长报告说,一个特定的学生群体的考试成绩已经连续四年上升。这个班大二学生的成绩比大一学生的成绩要好。大三的成绩更好,大四的成绩最好。我们将规定没有作弊,甚至没有任何创造性地使用描述性统计。每一年,这一批学生都比前一年做得更好,用各种可能的标准来衡量:平均值、中间值、年级水平的学生百分比等等。你会(a)提名这位学校领导为“年度校长”还是(b)要求更多数据?(……)如果我们合理假设最差的学生(考试分数最低)最有可能辍学,那么随着越来越多的学生辍学,那些被落下的学生的平均考试分数将稳步上升。”
如果你想给这个人颁奖而不要求更多的数据,你可能犯了一个可怕的错误。
你可能已经发现,生存偏见无处不在。如果你仔细想想,很可能连你自己都在犯这个错误,当然你也能想到几个朋友和亲密的家庭成员经常掉进这个又深又宽的偏见洞里。然而,当你的朋友告诉你他想买那个流行的科技产品,因为 Instagram 上的所有视频看起来都超级有趣和时尚时,尽管这可能很有趣,但你可能是在和敌人睡觉,生存偏见也可能在你自己的机器学习算法中。当然,这一点也不好笑。
source: Google Images
让我们看看数据科学、机器学习和人工智能领域的几个例子:
- 流失预测:假设你正在为流失预测建立一个机器学习模型。因此,你要利用当前活跃客户的数据库,考虑你可能会用到的有用功能。订单总数?过去 X 个月的订单数量?他从什么时候开始在公司工作的?投诉总数?每月与客服的平均互动次数?嗯,诸如此类。你想了很多,最后得出了令人印象深刻的 100 个预测客户流失的功能…你做了很好的功能工程!干得好!然而,你是否已经发现了生存偏差在起作用?当然,以你当前的活跃客户为例,你会错过所有离开你的客户,因此,你的模型只会关注幸存者。正确的做法是,例如,取在某年某月注册的所有客户。通过这种方式,你可以获得一个具有代表性的客户样本,包括那些仍然和你在一起的客户以及那些已经离开的客户。
- 欺诈防范:数据科学、机器学习和人工智能领域在欺诈防范方面的生存偏差也可能非常危险。通常,我们在 Ravelin 的客户来找我们时,已经在使用某种防止欺诈的解决方案。无论是规则系统、人工审核客户还是其他。想象一下,如果为了建立我们客户的机器学习模型,我们只接受那些通过了客户先前解决方案的欺诈者。我们将只使用幸存者作为我们的目标变量,而忽略以前的解决方案通过防止一些欺诈者已经在做的所有有益的事情。
- **疾病预测:**想象一下,取一个患有致命疾病的人的样本,并将年龄、自诊断以来的时间、诊断时的年龄、性别、健康水平等特征添加到我们的模型中。您可能已经发现了这里的问题,因为这与我们预测客户流失的情况类似(但显然更明智)。这样做的话,我们就忽略了所有那些自从他们的 weir 被诊断出患有这种疾病后没能挺过来的人。这些人肯定有他们自己的特点。也许抽烟或者不太爱运动?也许他们是在较晚的年龄被诊断出来的?我们不知道,这将是一个生存偏差的巨大案例,直接进入我们的数据集,因此预测。
如您所见,这种特定类型的偏见在我们的日常生活和作为数据科学家的工作中都非常危险。但更重要的是,如果我们不相应地评估这件事,对参与我们预测的人来说也是危险的。所以希望这个故事能帮助你更好地了解它:)
如果你喜欢这个故事,别忘了看看我最近的一些文章,比如提高绘图技能的 10 个技巧,我在使用火车测试分割或 5 分钟网络抓取时犯的 6 个业余错误。在我的中等个人资料中可以找到所有这些以及更多。还有,如果你想直接在邮箱里收到我关于数据科学、机器学习、人工智能和编程的最新文章,只要订阅我的时事通讯就行了:)
也可以通过…
LinkedIn:https://www.linkedin.com/in/gferreirovolpi/
GitHub:https://github.com/gonzaferreiro(在那里可以找到我所有的代码)
感谢阅读!
本故事所用的资料来源:
https://brilliant.org/wiki/survivorship-bias/
https://en.wikipedia.org/wiki/Survivorship_bias
https://www.youtube.com/watch?v=NtUCxKsK4xg&t = s
https://blog.hubspot.com/sales/survivorship-biasT21
http://blog . idonethis . com/7-lessons-survivority-bias-will-help-make-better-decisions/
你不知道 SVD(奇异值分解)
真正理解 SVD——直观的核心思想
回到基础力学,你知道任何力矢量都可以分解成沿 x 和 y 轴的分量:
(Animation by author)
祝贺。 现在你知道什么是奇异值分解了。
令人失望的是,几乎 SVD 的每个教程都把它变得比必要的更复杂,而核心思想却非常简单。
由于数学只是为同一概念赋予不同名称的艺术, SVD 只不过是将向量分解到正交轴上——我们只是决定它可能需要一个更豪华的名称。
我们来看看这是怎么回事。
当向量( a )被分解时,我们得到 3 条信息:
(Image by author)
- 投影的方向—单位矢量( v ₁ 和 v ₂ ) 代表我们投影(分解)的方向。在上面,它们是 x 轴和 y 轴和*,但是可以是任何其他正交轴。*
- 投影的长度(线段sₐ₁和 sₐ₂)——它告诉我们在每个投影方向上包含了多少矢量(更多的矢量 a 是向 v ₁ 倾斜的)
- 投影的个矢量(pₐ₁和pₐ₂)——用于将个原始矢量相加(作为矢量和), 而对于这一点很容易验证,pₐ= sₐ₁v₁和pₐ₂**= sₐ₂v—**
关键结论:
任何向量都可以表示为:
1.投影方向单位向量(v₁、v₂……)。
2.投影到它们上面的长度(sₐ₁,sₐ₂,…)。
SVD 所做的就是将这个结论扩展到不止一个向量(或点)和所有维度:
An example of a dataset (a point can be considered a vector through the origin). (Image by author)
现在的问题是知道如何处理这个烂摊子。
如何处理这个烂摊子
如果不先处理一个向量,我们就无法处理这些混乱!
如果你观察数学中的许多概括,你会发现它们主要利用矩阵。
所以我们必须找到一种方法,用矩阵来表达向量分解的运算。
这是一件很自然的事情:
Same figure as before, but tilting the axes of projection to convince you they aren’t confined to x and y. (aₓ and aᵧ are the coordinates of vector a, put into a column matrix (aka column vector), as per convention. Same for v₁ and v₂). (Image by author)
我们要分解(投影)矢量 a 沿着单位矢量 v ₁ 和 v ₂ 。
你可能已经知道(特别是如果你已经看过这个)投影是由点积完成的——它给出了投影的长度(sₐ₁和 s ₐ ₂):)
Projecting (a) onto v1 and v2. (Image by author)
但那是多余的。我们可以利用矩阵的效率…
…to write both equations in one go, by adding an extra column for each unit vector. (Image by author)
我们甚至可以添加更多的点…
…by adding an extra row for each point. S is the matrix containing the lengths of projections. (Image by author)
下面是添加那个点 b 后的样子:
(Image by author)
现在很容易推广到任意数量的点和维度:
n = no. of points, d = no. of dimensions, A = matrix containing points, V = matrix containing the decomposition axes, S = matrix containing lengths of projection. (Image by author)
最佳的数学优雅。
(Animation by author)
概述:-
The dot product in this case is just ordinary matrix multiplication. (Image by author)
这就相当于说:
Because V contains orthonormal columns, its inverse = its transpose (property of orthogonal matrices). (Image by author)
SVD 就是这么说的(记住关键结论):
任何一组向量(A)都可以用它们在某一组正交轴(V)上的投影长度(S)来表示。
然而,我们还没有到达那一步。常规的奇异值分解公式表示:
但这只是意味着我们想看看:
这就是我们要做的。
如果你仔细观察矩阵 S ,你会发现它包括:
(Image by author)
事实证明(原因将在后面看到),如果我们能够规格化这些列向量,也就是说,使它们成为单位长度的*,那是最好的。***
这是通过做相当于将每个列向量除以其大小来完成的,但是以矩阵形式。
但是首先,用一个数字例子来看看这个“除法”是怎么做的。
假设我们要将 M 的 第 1列除以 2 。我们肯定要乘以另一个矩阵才能保持等式:
验证未知矩阵无非是个单位矩阵,用除数 = 2 代替个第 1 个元素:
*将 2nd 列除以 3 现在变成了一件直接的事情——只需将单位矩阵的 2nd 元素替换为 3 😗
It should be obvious how this operation can be generalized to any matrix of any size.
我们现在要把上面的“除法”概念应用到矩阵 S 上。
为了归一化 S 的列,我们按照它们的大小来划分…
(Image by author)
…通过对上例中的 S 做我们对 M 做的事情:
(Image by author)
最后…
Singular Value Decomposition (Compact or Thin version)
当然,一些精细的细节和严谨的数学被无可非议地掩盖起来,以便而不是偏离核心概念。
解释
先说这个 U 和σ…
(Image by author)
西格玛夫妇呢。为什么我们要用正常化的来寻找它们呢?**
我们已经看到,(σ ᵢ )是投影长度平方之和的平方根,所有点的**,到第 i 个单位矢量 vᵢ 。**
那是什么意思?
Red segments = projections on v1. Blue segments = projections on v2. The closer the points to a specific axis of projection, the larger the value of the corresponding σ. (Animation by author)
由于 sigmas 在其定义中包含了特定轴上投影长度的总和,它们代表了所有点离该轴有多近。
例如,如果σ₁ > σ₂,那么大多数点数更接近于 v ₁ 而不是 v ₂ ,反之亦然。
这在 SVD 的无数应用中有着巨大的用途。
主要应用程序
求矩阵的奇异值分解的算法不是随机选择投影方向(矩阵的列 V )。
他们选择它们作为数据集的主要组成部分(矩阵 A)。
如果你读过我的第一篇文章,你会很清楚主要成分是什么…
…they’re the lines of largest variation (largest variance). (Image by author)
从同样的你也知道降维的目标是将数据集投影到方差最大的直线(或平面)上:
Magenta: points before projection. Violet: points after projection (reduced dimensionality). (Image by author)
现在,使用 SVD 投影数据集的行为变得轻而易举,因为所有的点都已经投影** (分解)在所有的主成分上(即 vᵢ 单位向量):**
(Image by author)
例如,要将数据集投影到第一个主成分上…
…all we have to do is remove all columns not related to the 1st principal component. The projected dataset in now A’. (Image by author)
将两个矩阵(上面的 s 和 V ᵀ 相乘得到矩阵 a ’,其包含最后一个图中的投影点(紫色)。
仅此而已…暂时如此。
SVD:模型调优哪里出错了
使用 Python 中的 Surprise 库探索 SVD 推荐系统的超参数调整的限制。
Not this type of tuning 😃 Credit: T Millot
简介
有许多方法可以建立推荐系统。 潜在因素模型 是一系列寻求给定评级矩阵低维分解的技术。 SVD 是一个潜在因素模型的名称,该模型涉及通过 随机梯度下降 进行参数估计,由 Simon Funk 在电影推荐的背景下流行起来。本文展示了使用 Python 中的 Surprise 库在 Movie-Lens 100k 数据集上构建和测试一个 SVD 推荐系统 的过程,重点是超参数调优。
设置
1 —数据集先决条件
**from** surprise **import** Datasetdata = Dataset.load_builtin(‘ml-100k’)
Surprise 是一个 scikit 包,用于构建和分析由 Nicolas Hug 维护的推荐系统。阅读它的文档页面,软件包的一个目标是*“减轻数据集处理的痛苦”*。一种方法是通过内置数据集。Movie-Lens 100k 就是其中的一个数据集,只需上面的简短命令就可以调用它。
**from** surprise **import** Dataset, Reader
**import** csv
ratingsPath = '[Your directory]/ratings.csv'reader = Reader(line_format='user item rating timestamp', sep=**','**, skip_lines=1)
data = Dataset.load_from_file(ratingsPath, reader=reader)
自定义数据集也可以从文件或 pandas dataframe 加载,在这两种情况下,必须在 Surprise 解析数据集之前定义一个 Reader 对象。根据我的经验,只要数据集每行包含一个等级,Reader 对象就是可靠的,格式如下,其中顺序和分隔符是任意定义的,时间戳是可选的。实际上,大多数数据集没有这种结构,所以可能需要进行一些删减。
user:item:rating:timestamp
2 —调整超参数
**from** surprise **import** SVD,NormalPredictor
**from** surprise.model_selection **import** GridSearchCVparam_grid = {**'n_factors'**:[50,100,150],**'n_epochs'**:[20,30], **'lr_all'**:[0.005,0.01],**'reg_all'**:[0.02,0.1]}gs = GridSearchCV(SVD, param_grid, measures=[**'rmse'**], cv=3)
gs.fit(data)params = gs.best_params[**'rmse'**]svdtuned = SVD(n_factors=params[**'n_factors'**], n_epochs=params[**'n_epochs'**],lr_all=params[**'lr_all'**], reg_all=params[**'reg_all'**)
数据集准备好后,第二步是构建 SVD 算法。Surprise 利用 scikit-learn 的 GridSearchCV() 和*randomsedsearchcv()*方法,只用几行代码就返回了一组经过调整的参数,绕过了调整超参数的手动试错过程。
我们使用上面的网格搜索方法。一旦在 param_grid 字典中指定了超参数和潜在值的数组, GridSearchCV() 计算在 k 倍交叉验证数据集 上超参数的每个组合的分数,并返回最小化跨倍平均分数的参数集。折叠次数和分数都可以由用户选择(超超参数?!)—我们使用 3 倍和 RMSE 准确度得分。
和很多机器学习算法一样, SVD 有很多运动部件。我们选择因子的数量、时期的数量、所有参数的单一学习率和单一正则化常数,但是完整列表可以在库文档中找到。
最后一步是使用 Surprise 的 SVD() 函数,手动覆盖优化的超参数。
SVD 的有效性源于线性代数中一个名为矩阵分解的主题,并被修改以说明评级矩阵的稀疏特性。推导留给读者作为练习,但是对于那些方法论新手来说,Funk 的文章是必读的。既有娱乐性又有见地!
3 —评估框架
**from** EvaluatorScript **import** Evaluator **from** surprise **import** Dataset,SVD,NormalPredictor
**from** surprise.model_selection **import** GridSearchCVdata = Dataset.load_builtin(‘ml-100k’)terminator = Evaluator(data)param_grid = {**'n_factors'**: [50,100,150],**'n_epochs'**: [20,30], **'lr_all'**: [0.005,0.01],**'reg_all'**:[0.02,0.1]}gs = GridSearchCV(SVD, param_grid, measures=[**'rmse'**], cv=3)
gs.fit(data)params = gs.best_params[**'rmse'**]svdtuned = SVD(n_factors=params[**'n_factors'**], n_epochs=params[**'n_epochs'**],lr_all=params[**'lr_all'**], reg_all=params[**'reg_all'**])
svd = SVD()
random = NormalPredictor()terminator.addModel(svdtuned,**'SVDtuned'**)
terminator.addModel(svd,**'SVD'**)
terminator.addModel(random,**'Random'**)
terminator.evaluateModel()
设置的最后一步是构建一个评估框架,如下图所示。这一步是个人喜好。我喜欢构建一个评估器对象,
a)保存数据集及其所有分割(训练/测试、留一交叉验证等)。
b)通过持有模型对象。addModel() 方法。
c)通过评估模型。evaluateModel() 方法。简而言之这叫*。和。test()* 使用一致的数据集分割,对对象方法建模,并根据一组性能指标评估预测。
在上面的代码摘录中,我创建了一个继承自评估脚本的评估器对象的实例,并将其命名为终结器。通过输入数据集初始化终结符后,使用 Surprise 构建并添加了三个模型对象。我们已经看到了上面的 调整过的 SVD 模型,但是剩下的两个模型是一个 未调整的 SVD 模型和一个 随机 模型。
我发现这个框架是超级通用的,因为我可以向它抛出大多数模型对象,无论是令人惊讶的模型还是我自己的模型类。他们只需要*。契合()和。test()* 方法和一致的预测输出格式。
Evaluator 对象及其所有依赖脚本(包括一个度量脚本)位于一个 Github 文件夹中(此处为)。顺便说一句,我很想听听你是如何构建你的机器学习脚本的——我总是乐于听取关于实现的不同观点!
结果
在 python 中 Surprise 库的帮助下,我们拟合了一个 调优的 SVD 模型,一个 未调优的 SVD 模型和一个随机模型。而 调优的 SVD 模型是我们的重点,我们使用 未调优的 SVD 模型和一组随机生成的推荐进行相对比较。
调谐 SVD 超参数:
{'n_factors': 150, 'n_epochs': 75, 'lr_all': 0.01, 'reg_all': 0.1}
未调整的 SVD(默认)超参数:
{'n_factors': 100, 'n_epochs': 20, 'lr_all': 0.005, 'reg_all': 0.02}
准确度结果:
MAE RMSE Time (s)
SVDtuned 0.6487 0.8469 199.3
SVD 0.6709 0.8719 134.4
Random 1.1359 1.4228 109.4
调整后的模型在***【MAE】*和 RMSE 上大大优于随机生成的推荐,也略微优于未调整的模型。太好了!现在,为了了解这种性能如何转化为实际的电影推荐,我们在数据集中挑选出一个用户——用户 56。
— — — — — -
User 56 Total Ratings: 46User 56 5 Star Ratings:
Ace Ventura: When Nature Calls (1995)
Seven (a.k.a. Se7en) (1995)
Dumb & Dumber (Dumb and Dumber) (1994)
Ace Ventura: Pet Detective (1994)
Forrest Gump (1994)
Lion King, The (1994)
Jurassic Park (1993)
Silence of the Lambs, The (1991)
— — — — — -
目测用户的 5 星级电影,一些明显的主题出现了——喜剧、犯罪和戏剧。这让我们了解了测试用户的偏好,所以让我们看看每个模型是如何理解这个用户的偏好的。
— — — — — -
**SVDtuned**
User's Top Recommendations:
Belle Epoque (1992)
Neon Genesis Evangelion: The End of Evangelion (Shin seiki Evangelion Gekijô-ban: Air/Magokoro wo, kimi ni) (1997)
Adam's Rib (1949)
Dad's Army (1971)
Three Billboards Outside Ebbing, Missouri (2017)
Jetee, La (1962)
Enter the Void (2009)
Seve (2014)
Cosmos
Saving Face (2004)
— — — — — -
**SVD**
User's Top Recommendations:
Shining, The (1980)
Guess Who's Coming to Dinner (1967)
Raiders of the Lost Ark (Indiana Jones and the Raiders of the Lost Ark) (1981)
Snatch (2000)
On the Waterfront (1954)
Good Will Hunting (1997)
Matrix, The (1999)
Kiss Kiss Bang Bang (2005)
Hoop Dreams (1994)
Sunset Blvd. (a.k.a. Sunset Boulevard) (1950)
— — — — — -
**Random**
User's Top Recommendations:
Saint, The (1997)
Dish, The (2001)
Bad Day at Black Rock (1955)
Cry_Wolf (a.k.a. Cry Wolf) (2005)
Osmosis Jones (2001)
Neon Genesis Evangelion: The End of Evangelion (Shin seiki Evangelion Gekijô-ban: Air/Magokoro wo, kimi ni) (1997)
Sgt. Bilko (1996)
O.J.: Made in America (2016)
National Velvet (1944)
Reckless Kelly (1994)
-----------
警告:调谐出错!
关于调优模型建议的第一个想法—晦涩难懂。而且不是好的方面。
调谐模型的最佳推荐电影出现在我们用户的档案之外。虽然某种程度的多样性是好的(无论是通过国际电影还是其他方式),但用户的低熟悉度往往令人不快。就了解用户的偏好而言,我无法区分调优模型和随机模型。事实上,我并不认可任何热门推荐电影……但这可能更能说明我的情况,而不是推荐系统。
然而,未调整模型的最佳推荐很大程度上符合用户 56 的简档。这份名单似乎在识别用户对戏剧的偏好方面做得很好,同时也融合了犯罪和喜剧。我印象深刻地看到推荐电影的发行日期的广泛范围,特别是考虑到用户首选列表中的紧张范围。
作为一种方法,奇异值分解显然有潜力,但输出质量仍然对超参数非常敏感。到目前为止,我们的判断是针对数据集中的单个用户。我们可以使用一些*‘beyond’*指标来分析全球绩效。
HitRate 5-StarHitRate Diversity
SVDtuned 0.0066 0.0163 0.7269
SVD 0.0295 0.0569 0.0319
Random 0.0115 0.0081 0.0496
在构建默认模型和我们认为的优化模型之间的某个地方,我们在整个数据集上的建议质量下降了。从*点击率的下降可以明显看出这一点——*这是一个迹象,表明该模型正在努力从可用的项目中识别用户偏好。
由于点击率是在 留一交叉验证的 数据集 ***,***5-star HitRate简单来说就是 5 星评级的留一电影的点击率。一个更精细的点击率指标,如果你愿意,因为我们真的只关心捕捉用户的偏好。虽然这两个 SVD 模型在识别首选电影方面更好,但是额外的 50 个因素、55 个时期、更高的学习率和更高的惩罚项每个都导致了更差的“调整”模型。
为什么?我们为了在网格搜索过程中调整参数而优化的分数与我们评估模型所依据的分数不一致。
讨论
Surprise library 让我们可以直接进入数据集的优化模型,这可能会节省数小时的手动工作。然而,它确实遇到了一个关键的障碍。遗憾的是,不能提供真正重要的分数使得内置的调整功能对推荐系统毫无用处。正如我们在上面看到的,使用股票准确性指标是不够的。事实上,他们是 调 SVD 模式的败落者。
模型构建不是一个有效的寻求真相的过程,但它是为你的用户提供价值的阶梯上的重要一步。为了获得最佳、可用的模型,能够快速启动工作模型、有效调整超参数并进行明确分析非常重要。无论应用程序如何,确保整个建模过程符合适当的性能指标是至关重要的。
github:【https://github.com/93tilinfinity/svd-recommender
欢迎评论和反馈!
SVM:特征选择和内核
(Source: https://towardsdatascience.com/support-vector-machine-vs-logistic-regression-94cc2975433f)
支持向量机(SVM)是一种受监督的机器学习算法,可用于分类和回归目的。
诺埃尔·班布里克。
介绍
支持向量机(SVM)是一种机器学习算法,可用于许多不同的任务(图 1)。在本文中,我将解释数学基础,以演示该算法如何用于二进制分类目的。
Figure 1: SVM Applications [1]
SVM 的主要目标是找到最佳超平面,以便在不同类别的数据点之间进行正确分类(图 2)。超平面维度等于输入特征的数量减一(例如,当处理三个特征时,超平面将是一个二维平面)。
Figure 2: SVM Hyperplane [2]
超平面一侧的数据点将被分类到某个类别,而超平面另一侧的数据点将被分类到不同的类别(例如,如图 2 中的绿色和红色)。超平面和该超平面任一侧上的第一点(对于所有不同的类)之间的距离是该算法关于其分类决策的确信度的度量。距离越远,我们就越有信心 SVM 做出的决定是正确的。
最接近超平面的数据点称为支持向量。支持向量确定超平面的方向和位置,以便最大化分类器余量(并因此最大化分类分数)。SVM 算法应该使用的支持向量的数量可以根据应用任意选择。
使用 Scikit-Learn Python 库,只需几行代码就可以轻松实现基本的 SVM 分类。
from sklearn import svm
trainedsvm = svm.SVC().fit(X_Train, Y_Train)
predictionsvm = trainedsvm.predict(X_Test)
print(confusion_matrix(Y_Test,predictionsvm))
print(classification_report(Y_Test,predictionsvm))
有两种主要的分类 SVM 算法硬边界和软边界:
- **硬边界:**旨在寻找最佳超平面,而不容忍任何形式的错误分类。
- **软利润:**我们在 SVM 增加了一定程度的宽容。以这种方式,我们允许模型自愿错误分类一些数据点,如果这可以导致识别能够更好地概括看不见的数据的超平面。
通过在svm.SVC
中添加一个 C 惩罚项,可以在 Scikit-Learn 中实现软余量 SVM。C 越大,算法在进行错误分类时得到的惩罚越多。
内核技巧
如果我们正在处理的数据不是线性可分的(因此导致较差的线性 SVM 分类结果),可以应用一种称为核技巧的技术。这种方法能够将我们的非线性可分数据映射到一个更高维的空间,使我们的数据线性可分。使用这个新的维度空间,SVM 可以很容易地实现(图 3)。
Figure 3: Kernel Trick [3]
有许多不同类型的核可用于创建这种高维空间,一些例子是线性、多项式、Sigmoid 和径向基函数(RBF)。在 Scikit-Learn 中,可以通过在svm.SVC
中添加一个内核参数来指定一个内核函数。可以包含一个称为 gamma 的附加参数来指定内核对模型的影响。
如果数据集中的要素数量大于观测值数量,通常建议使用线性核(否则 RBF 可能是更好的选择)。
当使用 RBF 处理大量数据时,速度可能会成为一个需要考虑的约束。
特征选择
一旦拟合了我们的线性 SVM,就可以使用训练模型上的.coef_
来访问分类器系数。这些权重表示与超平面正交的正交向量坐标。相反,它们的方向代表预测的类。
因此,可以通过相互比较这些系数的大小来确定特征重要性。因此,通过查看 SVM 系数,可以识别分类中使用的主要特征,并去除不重要的特征(方差较小)。
减少机器学习中的特征数量非常重要,尤其是在处理大型数据集时。这实际上可以:加速训练,避免过度拟合,并且由于数据中噪声的减少,最终导致更好的分类结果。
图 4 显示了我在皮马印第安人糖尿病数据库上使用 SVM 识别的主要特征。绿色表示对应于负系数的所有特征,蓝色表示正系数。如果你想了解更多,我所有的代码都可以在我的 Kaggle 和 GitHub 个人资料中免费获得。
Figure 4: Feature Importance using SVM
数学
如果你想深入研究 SVM 背后的数学,我在这里留下了 Patrick Winston 的演讲,可以在麻省理工学院开放课程 YouTube 频道上找到。这个讲座说明了如何推导 SVM 决策规则,以及哪些数学约束是适用于使用拉格朗日乘数。
Video 1: MIT OpenCourseWare [4]
联系人
如果你想了解我最新的文章和项目,请通过媒体关注我,并订阅我的邮件列表。以下是我的一些联系人详细信息:
文献学
[1]无泪支持向量机,Ankit Sharma。访问地点:https://www.slideshare.net/ankitksharma/svm-37753690
[2]支持向量机—机器学习算法介绍,罗希斯·甘地。访问:https://towardsdatascience . com/support-vector-machine-introduction-to-machine-learning-algorithms-934 a 444 FCA 47
[3]支持向量机,杰瑞米·乔登。访问地点:https://www.jeremyjordan.me/support-vector-machines/
[4]麻省理工学院开放式课程,16。学习:支持向量机。访问地点:https://www.youtube.com/watch?v=_PwhiWxHK8o
基于内核的图形处理器 SVM 优化
使用 GPU 训练健壮的分类器
本笔记本展示了使用基于模拟的优化器对多类线性支持向量机的优化。任何基于模拟的优化器都可以与本笔记本中的 Cuda 内核一起使用。在这个例子中,我使用了我的定制优化器 KernelML。这个脚本的运行时应该设置为使用 GPU: Runtime- >改变运行时类型。
最初的 SVM 公式可以在 Vapnik 1992 中找到。自那以后,该算法的鲁棒性有所提高。请参见鲁棒分类器 2019 第 6.1 节。健壮的实现看起来非常繁琐。如果您对实现它感兴趣,请考虑给我发电子邮件以及查看 KernelML 的文档。电子邮件:rohankotwani@gmail.com。
SVM 通常使用语言乘数和二次规划来优化。然而,这个优化过程可能不够快,我们希望利用 GPU。:)我们将用蛮力方法优化 SVM 原始形式。实际上,使用基于模拟的方法并不是一个坏主意,因为训练 SVM 的计算复杂度是 O(N),其中 N 是数据点的数量。
SVM Primal Form
损失函数根据到类边界的距离对错误分类的数据点进行惩罚。容限损失 C 被限制为 C>0。目标 y 包含-1 或 1,其中 1 表示目标类。请参见下图,了解最大余量线性决策函数的直观表示。
Vapnik 1992
Iris 数据集用于测试使用 GPU 进行基于模拟的优化的可行性。数据集有 150 行和 4 列。这是一个小数据集,但这很好,因为 Google/Colab 倾向于禁止使用太多计算时间的用户。这个算法的并行 CPU 实现可以在这里找到。
我鼓励您在 Google 的 Colab 环境中运行这个脚本,我希望这会让您感兴趣。我很高兴看到 GPU 和基于模拟的优化器可以实现什么惊人的事情。这是创造性的内容,所以没有人被允许专利的任何工作;)
群体智能:蚁群内部
蚁群优化导论
*“整体大于其部分之和”*是一句众所周知的名言,根据格式塔心理学,它总结了一个系统的概念——整体——是一种更复杂的东西,不同于其基本元素的集合。
换句话说,试图理解一个复杂的系统,试图把它分解成基本的部分,这种尝试不可避免地会失败,会遗漏一些单个部分无法单独表达的东西。
抛开格式塔心理学不谈,开篇引文将有助于理解本文的主题:蚁群优化算法(ACO)。
蚂蚁社会是一个组织良好的等级结构,有特定的角色和规范的行为。
尽管有许多种类的蚂蚁,而且每一种都有自己的特点,但我们可以确定一个共同的组织结构:蚁后和工蚁。
工蚁执行蚁群的各种任务:觅食、维护巢穴、照料幼虫、防御等等。
正是通过对蚂蚁觅食行为的观察,Marco Dorigo 在 1992 年提出了蚁群优化算法,为元启发式研究以及后来被定义为群体智能做出了贡献。
这个想法来自于对觅食蚂蚁行为的观察:当一只蚂蚁离开巢穴寻找食物时,她会留下一条信息素痕迹,其他蚂蚁可以跟着走;如果她找到了一些食物,她会返回巢穴——使用相同的路径——在回来的路上留下更多的信息素。
如果她没有找到任何食物,她不会在返回巢穴的路上放下任何信息素,先前的踪迹会消失。
如果其他觅食蚂蚁会沿着这些路径追逐,它们中的大多数会沿着这些路径寻找食物并将它们的信息素添加到路径中。
另一群蚂蚁将找不到任何踪迹,或者决定沿着其他路径前进,而其他蚂蚁将在到达路径尽头之前分散开来。
如果我们将这种行为应用于一个大的群体,我们会看到强烈的信息素痕迹出现,将巢穴与食物来源联系起来。
这种基于信息素的间接交流机制是蚁群内部知识共享的基础,并允许蚂蚁找到更好的食物路径。
Black garden ants (Lasius niger)
吸取教训 ACO
从 90 年代早期开始,蚁群的生物学例子第一次被转化为解决组合优化问题的真正方法。
这类问题包括在约束框架内寻找给定函数的全局最大值。
组合优化问题可以用模型来描述:
P=(S,ω,ф)
其中 S 是具有特定有限域的有限变量集,ω是变量间的一组约束,而是目标函数:最小化\最大化。
一个可行的解决方案是简单地收集所有决策变量,并从它们的域中分配一个值,这样就不会违反 omega 约束。
求解算法将为每个变量分配一个称为求解分量的特定值;
单一解决方案是所有解决方案组件的集合。
最优解的搜索和大量的约束使得这类问题难以解决,也因为穷举搜索通常是不可能的。
例如,让我们考虑旅行推销员问题(TSP)。
问题如下:
“给定一个城市列表和每对城市之间的距离,访问每个城市并返回出发城市的最短可能路线是什么?”。
这是组合优化的一个明显的例子,由于数学模型必须产生和处理大量的约束,该组合优化经常不能用穷举搜索来解决,并且数学精确方法不能在可接受的时间内收敛。
多年来,许多启发式算法被开发并应用于这类 NP 难问题。
回到 ACO,我们可以使用前面介绍的 P 模型来形式化 TSP 问题:
首先,我们将代表 n 个城市的每个节点与一个变量 X(i)相关联,该变量的域有 n-1 个值: j = {1,…,n}其中 j!=一.
在一对城市之间的每条边上,我们关联一个代表信息素值的数值τ。
具有指定域值的所有 X(i)的集合是一个解,当且仅当对应于这些值的边的集合形成哈密尔顿循环(这个约束可以被引入蚂蚁选择行为)。
最后,函数(minimize)计算每个解的边长之和。
算法——元启发式
自从引入以来,ACO 算法已经被提出了许多不同的版本;以下是 ACO 的一般算法思想:
begin
initialization();
while (termination condition not met) do
ConstructAntSolutions();
LocalSearch();
GlobalPheromoneUpdate();
end
end
最初,我们从一系列解决方案组件开始,这些组件将允许我们建立构造图、要考虑的约束列表以及将在算法中使用的一些参数。
在初始化步骤中,设置所有参数并布置构造图,并为每个变量(边)分配初始信息素值。
在构造解决方案阶段,一组蚂蚁一个接一个地开始,通过遍历图来构造解决方案。
每只蚂蚁存储自己的解决方案,并在沿着图行进时更新它。
一开始,所有的蚂蚁都从一个空的解开始,在每个构建步骤中,通过选择一个代表可行组件的节点来扩展当前的解。
理想情况下,选择组件和更新部分解决方案的这一过程是在保持解决方案可行性的情况下进行的,如果这不可能或太难保持,则部分解决方案一旦完成,就可以根据违反约束的程度而被丢弃或处罚。
实施选择过程时,计算每个解决方案组件被选择的可能性:
其中τ是弧上的信息素,η是启发式信息,就目前而言,我们可以把它定义为每个分量解的特殊值。(将在下面几行描述)。
N(s(p)) 是可以添加以保持可行性的解决方案组件集。
α和是在初始化步骤中具有固定值的参数,其确定信息素值和启发式信息的相对重要性。
一旦计算出 p,我们就可以应用所谓的伪随机比例规则:
其中 r 是一个介于 0 和 1 之间的随机数,q0 是一个也介于 0 和 1 之间的固定参数,它作为 r 的一个阈值,允许我们更加重视勘探或开采。
事实上,如果 r 大于或等于 q0,蚂蚁将根据 p(探索)的概率分布在解决方案组件之间随机选择。
启发式信息是在组件解决方案(节点)上计算的数值,代表该组件在问题特定知识方面的质量或重要性。
启发式信息可以在初始化步骤中预先计算或者可以在运行时计算。
对于大多数 NP-hard 问题,启发式信息是先验已知的,并且在整个算法执行过程中不会改变。
在其他情况下,启发式信息取决于到目前为止构建的部分解决方案,因此在每一步都进行计算。
例如,在 TSP 中, η 由边的长度定义:d(ij)的负一次方。
LocalSearch 步骤是可选的;这一阶段的目的是通过利用问题知识来改进蚂蚁获得的解决方案,即移动和替换一些解决方案组件。
最后,在全局信息素更新中,信息素沉积和蒸发过程被应用到图中。
这个阶段的目标是使好的解决方案更适合下一次迭代。
这是通过两种方式实现的,首先通过增加属于最佳解决方案或良好解决方案列表的边上的信息素值,然后通过模拟信息素蒸发。
在过程的这一点上,我们已经有了由蚂蚁产生的完整解决方案的列表;此外,我们可以通过所谓的评估函数或目标函数来评估这种解决方案,该目标函数确定给定的完整解决方案的质量(在 TSP 的情况下是距离的总和)。
此外,对于这个阶段,存在许多信息素更新方法,例如,我们可以决定加强迄今为止的单个最佳解决方案的信息素。
对于当前迭代的每个完整解决方案,通用的方法更通用;我们使用以下公式更新每个信息素变量:
其中 1 是在边缘
(0 < ρ < 1)上保留的旧信息素的分数,而 2 是包含该特定成分的所有评估函数的总和。
因此,如果当前边 i-j 没有被任何解考虑,则公式的第二项为零,并且使用简单蒸发机制更新信息素( 1 )。
在信息素更新后,检查终止条件以查看结果是否足够好,例如,如果在 100 次连续迭代中最佳解没有改善,我们可以决定停止。
应用和结果
现在我知道了什么是蚁群优化,我从中获得了什么?
蚁群算法的应用很多,涉及不同的领域,以下是一些例子:
-路线问题
-分配和调度问题
-分类规则
-蛋白质折叠
- DNA 测序
-贝叶斯网络
…还有许多其他的
其广泛的潜在应用来源于整个方法的灵活性,以便在信息素机制的同时,在信息素分布和评估阶段引入特定的问题知识。
最后一个示例:特征选择
在总结 ACO 元启发式算法之前,有必要展示一个它在数据科学中一个常见研究领域的应用示例:特征选择。
高维空间问题是一个常见的问题,它影响着许多用于数值分析、机器学习、数据挖掘等的数据集。
抛开高维空间可能带来的问题(了解更多信息),ACO 如何被用作特征约简方法是很有趣的。
从 n 个特征的列表开始,我们希望减少整个集合,搜索包含最重要和最有代表性的特征的子集。
首先,由于 ACO 是一个基于图的元启发式算法,我们需要布局整个图。
图的每个节点代表初始 n 个特征集合中的一个特征,每个边代表从实际特征到另一个特征的选择。
每个蚂蚁将从一个空的特征集开始,遍历图,访问满足遍历停止准则的最小数量的节点,并最终输出一个候选子集。
Dotted lines: possible feature to add, Bold lines: ant feature selection
如图所示,从节点 A 开始的蚂蚁执行直到节点 F 的路由,然后在建立了满足遍历停止准则(例如,适当高的分类精度)的以下子集{A,B,C,D,F}之后停止。
启发式信息可以通过任何适当的度量函数来计算,例如,基于熵的度量可能非常有效。
蚂蚁选择过程和信息素更新用所描述的相同方法来执行。
整个过程遵循以下步骤: m 只蚂蚁被生成并随机放置在图中。
从这些随机位置开始,每只蚂蚁通过遍历边开始构建路径,直到满足遍历停止标准。
收集并评估所有子集;如果这些子集中有一个足够好,或者迭代已经执行了一定次数,则过程停止,并返回找到的最佳子集。
如果这些停止条件都不成立,那么信息素被更新,一个新的蚂蚁群体产生,新的迭代开始。
结论
如上所述,蚁群算法诞生于对动物世界的观察,特别是对大群单一简单生物如蚂蚁的观察。
这种直接来源于自然的直觉证明了动物世界可以成为灵感和知识的来源。
ACO 元启发式算法代表了现今一种众所周知的解决多重问题的可靠方法;它以简单或非常复杂的形式存在于各种风格中。
蚁群算法的最大优点之一是能够快速发现好的解决方案;这种优势有时会被过早的收敛所抵消。
尽管 ACO 不适用于连续问题,但它确实是许多优化/离散问题的有效解决方案,值得包含在数据科学家工具箱中。
甜蜜的家乡芝加哥:审视芝加哥市的犯罪
数据驱动的方法。
由泰勒娃娃,杰夫格林,加齐莫舍德
这篇论文最初是为我大学的数据库课提交的。我们发现它很有趣,我们在它上面花了很多时间,所以我想在这里分享一下。它已被编辑成这种格式。
简介
芝加哥市通常被称为“风城”或“第二大城市”。它经常以它的食物而闻名,包括深盘比萨饼和芝加哥热狗。不幸的是,芝加哥也因其高犯罪率而臭名昭著,而且经常发生暴力性质的犯罪。由于芝加哥市各种犯罪的数据的可用性,我们选择检查芝加哥的犯罪,以确定我们可以从分析数据集得出什么信息。我们很想知道这个城市最常见的犯罪是什么,如果那些高犯罪率每年都有变化,以及不同犯罪的逮捕率是多少。虽然这个数据集可能不包含最令人振奋的信息,但我们认为分析并尝试确定芝加哥是否真的像媒体描绘的那样暴力是有趣的。
数据
我们选择的数据是一个数据集,包含了芝加哥市过去 5 年的犯罪信息。我们认为这将是一个有趣的数据集,因为除了观察芝加哥市的犯罪情况外,我们还可能发现数据中令人信服的趋势。这些数据包括但不限于犯罪日期、犯罪发生的街区、社区区域、伊利诺伊州统一犯罪报告代码(IUCR)、联邦调查局统一报告代码以及报告犯罪的警官的巡逻。该数据集是在 Kaggle 上发现的,该数据集被认为是在知识共享许可 CC0 1.0 公共领域下获得许可的,这意味着我们可以使用这些数据而无需任何进一步的批准。我们总共有四个表,但是其中一个表是用于保存非标准化数据的临时表。在检查完数据并开始对其进行规范化之后,我们最终得到了 3 个主表:芝加哥犯罪数据、芝加哥 IUCR 代码、芝加哥公共区域(邻域)和一个自动生成的 chicago_crime_data 序列表。芝加哥犯罪数据表中的信息和属性在很大程度上是不言自明的。然而,IUCR 表的属性可能需要一点解释。该表中的 id 与 Chicago crime 数据表中使用的 IUCR 代码相匹配。此 id 附加到犯罪的主要描述和次要描述。例如,基于主要描述和次要描述的组合有不同的 id。下面的例子是凶杀案。虽然这三种犯罪都有相同的主要类型,但它们有不同的次要类型和 id。
id | primary_desc | secondary_desc
— — — + — — — — — — — -+ — — — — — — — — — — — — —
0110 | HOMICIDE | FIRST DEGREE MURDER
0141 | HOMICIDE | INVOLUNTARY MANSLAUGHTER
0142 | HOMICIDE | RECKLESS HOMICIDE
为了便于解释每个表所使用的属性和数据类型,我们在下面包含了两个表模式,它们也包含主键和外键:
Table “chicago_crime_data” Column | Type
— — — — — — — — — — — + — — — — — — — — — — — — — — —
id | integer
date | timestamp without time zone
block | text
iucr | text
location_description | text
arrest | boolean
domestic | boolean
community_area | integer
fbi_code | text
latitude | double precision
longitude | double precision
Indexes:
“chicago_crime_data_pkey” PRIMARY KEY, btree (id)
Foreign-key constraints:
“chicago_crime_data_community_area_fkey” FOREIGN KEY (community_area) REFERENCES chicago_common_area(id)
“chicago_crime_data_iucr_fkey” FOREIGN KEY (iucr) REFERENCES chicago_iucr_code(id) Table “chicago_iucr_code”
Column | Type
— — — — — — — — + — — —
id | text
primary_desc | text
secondary_desc | text
Indexes:
“chicago_iucr_code_pkey” PRIMARY KEY, btree (id)
Referenced by:
TABLE “chicago_crime_data” CONSTRAINT “chicago_crime_data_iucr_fkey” FOREIGN KEY (iucr) REFERENCES chicago_iucr_code(id)
结果
我们在数据库上执行的大多数查询都与特定犯罪的数量和不同犯罪的地点有关。尽管我们希望对数据执行各种各样的查询,但总的来说,我们希望将重点放在犯罪数量上,并使用这些信息来确定哪些犯罪发生得最频繁。我们还调查了哪些犯罪的被捕率最高,以及它们在芝加哥的位置。
Figure 1: Chicago’s Crimes 2014–2018
在这里,我们希望发现犯罪的总数,而不考虑其严重性或细节。从图表中我们可以看出,在过去的几年里,盗窃是芝加哥最严重的犯罪,其次是殴打。
Figure 2: Chicago’s Crimes in 2018
Figure 3: Chicago’s Crimes 2017
从图 2 和图 3 中,我们可以看出,在过去的两年中,盗窃是芝加哥犯罪率最高的犯罪。除了这些可视化,我们还查看了从 2014 年开始的前几年的图表。我们可以利用这些图表得出结论,事实上盗窃是最常见的犯罪,并且在过去几年中没有出现激增。
我们也想看看这些犯罪在芝加哥附近的分布情况。这一数据对芝加哥的新来者很有用,他们试图找到一个犯罪率较低的社区居住,同时远离犯罪率最高的社区。描述每个社区遭受的犯罪类型也是有用的。我们在下面的查询中找到了犯罪最少和最多的区域,我们还查看了犯罪分布。
Figure 4: Chicago’s least crime prone neighborhood query and its crime distribution
Figure 5: Chicago’s most crime prone neighborhood query and its crime distribution
此外,我们还可以根据用户的请求查询和显示特定社区的犯罪分布情况。
Figure 6: Arrest rate for different types of assault
根据这些数据,我们可以准确计算出人们因特定犯罪而被捕的频率。例如,我们可以看到,对于不同类型的攻击指控,超过 80%的人被指控严重藏毒:手无/分钟伤害被逮捕。这与类似持枪恶意攻击的情况相比很有意思,后者的逮捕率只有 20%左右。
Figure 7: Assaults in Chicago in 2018
我们也可以看到犯罪的具体地点。图 7 显示了自 2017 年 1 月 1 日以来所有已知地点的袭击事件。然而,图表没有区分不同类型和严重性的攻击。不管怎样,可以肯定地说芝加哥存在人身攻击问题。
Figure 8: Homicides in Chicago in 2018
利用位置数据,我们可以确定整个芝加哥凶杀案高度集中的区域。这里的杀人罪包括一级,二级,过失杀人。
Figure 9: Prostitution in Chicago since 2014
一个相当有趣的图表是整个芝加哥与卖淫有关的犯罪。我们在这里可以看到,相关的犯罪似乎是在独特的线模式,最有可能代表整个城市的各种街道。
技术挑战
获得数据后,我们遇到的唯一主要问题是将数据集从 Kaggle 加载到数据库中。数据集作为 BigQuery 数据集存储在 Kaggle 中,这要求我们使用 Kaggle 内核从数据库中下载有限的数据集。我们选择下载过去 5 年的数据,因为这给了我们一个大数据集来处理。在我们成功地获得数据之后,我们在将数据插入临时表时遇到了问题。我们认为这里的大部分问题源于数据集的大小,它包含了超过 130 万行。当尝试接收如此大量的数据时,我们使用的 Windows 机器出现了内存错误,并且没有确定补救的方法。然而,当数据在 Mac 上接收时,我们没有遇到这些问题。为了解决内存错误问题,我们使用 Mac 将数据集加载到数据库中,然后通过我们在 Piazza 上找到的方法向团队的其他成员提供对表的访问。当试图只关注月份而忽略其他月份时,我们还遇到了时间戳字段查询的问题。幸运的是,我们能够使用 EXTRACT 命令做到这一点。
结论
在分析了图表和其他图像后,我们可以得出这样的结论:芝加哥是一个非常危险的城市,实际上就像媒体描述的那样暴力。光是袭击的数量就已经相当惊人了,更不用说杀人率了。在项目中使用这些数据使作业变得有趣,尽管它不是最令人愉快的数据集。我们觉得使用这个数据集将类似于我们在可能的行业就业中可能必须处理的数据,所以这个任务给了我们对未来就业有帮助的经验。
符号 vs 连接主义人工智能。
随着神经网络等连接主义技术的流行,主要竞争对手符号人工智能被证明是需要动态适应、可验证性和可解释性的任务关键型应用程序的正确战略补充。
Photo by Pablo Rebolledo on Unsplash
似乎只要有两种类型,人们就会很快选择其中一种,然后将两者对立起来。人工智能技术传统上分为两类;象征性人工智能和连接主义人工智能。后一种人工智能随着最近的成功故事和媒体炒作而变得非常受欢迎,没有人会因为认为它们就是人工智能的全部而受到责备。甚至有一些人散布虚假信息来转移对更经典的人工智能研发的注意力和资金。
事实是,每一套技术都有它的位置。目前还没有一种银弹人工智能算法,试图对所有问题使用相同的算法是非常愚蠢的。每种工具都有自己的优点和缺点,选择合适的工具是关键。
什么是象征性人工智能?
这类技术有时被称为 GOFAI(传统的人工智能)。这并不意味着这些技术已经过时或停滞不前。更经典的方法是对问题的模型进行编码,并期望系统根据该模型处理输入数据以提供解决方案。
随着人们认识到基于人工智能的系统要在某些高风险领域被接受,它们的行为需要是可验证的和可解释的,对符号技术的需求最近引起了新一轮的兴趣。这通常很难通过连接主义者算法来实现。
属于这一类的系统通常涉及演绎推理、逻辑推理和某种搜索算法,这种算法在特定模型的约束下找到解决方案。这些包括专家系统,它使用规则和决策树从输入数据中推导出结论,约束解算器,它在可能性空间内搜索解决方案,以及计划系统,它试图找到一系列行动,以从某个初始状态实现明确定义的目标。他们通常还有能够处理不确定性和风险的变种。
A MiniMax Game Tree for Tic-Tac-Toe. (Image Source)
这种算法通常具有算法复杂性,即 NP-hard 或 更糟的是 **,**在试图解决现实世界的问题时面临超大规模的搜索空间。这意味着经典的穷举盲搜索算法将不起作用,除了小的人为限制的情况。相反,最不可能找到解决方案的路径被从搜索空间中剔除,或者尽可能长时间不被探索。
这一类别中有太多的技术。分支定界算法处理启发式算法不可用的优化或约束满足问题,通过上限和下限划分解决方案空间,并在该分区内搜索解决方案。局部搜索着眼于一个解决方案的相近变体,并试图逐步改进它,偶尔执行随机跳跃,试图逃离局部最优。元启发式包含了这种技术的更广阔的前景,其中进化算法模仿自然界中发现的分布式或协作机制,例如自然选择和群体启发行为。
启发式搜索使用评估函数来确定一个状态与目标的接近度,使用比试图找到完整解决方案更便宜的估计值来计算。一个值得注意的独立于领域的启发式方法是 松弛 ,其中算法忽略了一些约束或可能的现实世界挫折以在更松弛的世界中找到更快的解决方案。这被用作在搜索的每个决策点做出更明智选择的指导。一个既 可接受 (永远不会高估成本)又信息丰富的好的启发式算法可以引导诸如 A* 的算法找到最优解,但不幸的是这样的启发式算法通常不容易获得。对于复杂的问题,找到一个满足所有约束的可行的解决方案,尽管不是最优的,也已经是一个很大的壮举了。
A* Heuristic Search for finding Shortest Path (Image Source: Wikipedia)
虽然有些技术也可以处理部分可观测性和概率模型,但是它们通常不适合有噪声的输入数据,或者模型没有很好定义的情况。它们在这样的场景中更有效,即在某些情况下采取特定的行动可能是有益的或灾难性的,并且系统需要提供正确的机制来显式编码和执行这样的规则。
符号算法消除了违反指定模型的选项,并且可以被验证总是比它们的连接主义对应物更容易产生满足所有约束的解决方案。由于通常很少或没有算法训练,模型可以是动态的,并根据需要快速变化。
什么是连接主义者人工智能?
Connectionist A.I .的名字来源于典型的网络拓扑,这一类中的大多数算法都采用这种拓扑。这一类别中最流行的技术是人工神经网络(ANN)。这由多层节点组成,称为神经元,它们处理一些输入信号,用一些权重系数将它们组合在一起,然后挤压它们以馈送到下一层。支持向量机也属于连接主义范畴。
人工神经网络有各种形状和大小,包括卷积神经网络(成功用于图像识别和位图分类),以及长短期记忆网络(通常用于时间序列分析或时间是重要特征的问题)。深度学习本质上也是人工神经网络的同义词。
A neuron of an Artificial Neural Network. (Image source: Wikipedia)
这类技术的关键方面是用户不指定建模领域的规则。网络从训练数据中发现规则。用户提供输入数据和样本输出数据(数据集越大越多样化越好)。然后,连接主义算法应用统计回归模型来调整中间变量的权重系数,直到找到最佳拟合模型。使用梯度下降等技术,在最小化所有训练数据点的累积误差的方向上调整权重。
由于这些技术是有效的误差最小化算法,它们对噪声具有固有的弹性。它们将消除异常值,并汇聚成一个解决方案,在一定的误差范围内对数据进行分类。
这些算法不需要一个世界的模型。他们只需要足够的样本数据,从这些数据中可以统计性地推断出世界的模型。这是一个非常强大的特点,但也是一个弱点。必须非常仔细地选择输入特征。还必须对它们进行标准化或缩放,以避免一个特征压倒其他特征,并对其进行预处理,使其对分类更有意义。
特征工程本身就是一项神秘的技术,通常是决定机器学习项目成功的关键因素。拥有太多的特征,或者没有一个覆盖这些特征的大多数排列的代表性数据集,会导致过拟合或欠拟合。即使有最熟练的数据科学家的帮助,您仍然受到可用数据质量的支配。这些技术也不能免受维数灾难的影响,随着输入特征数量的增加,无效解决方案的风险就越高。
A Data Scientist sifting for Features — Photo by Artem Maltsev on Unsplash
数据驱动算法隐含地假设它们所捕捉的世界模型是相对稳定的。这使得它们对于游戏规则没有显著改变或者改变的速度慢到足以允许收集足够的新数据样本用于重新训练和适应新现实的问题非常有效。图像识别是教科书式的成功故事,因为从现在起一年后热狗很可能看起来还是一样的。
Photo by HBO / Twitter.com/TechatBloomberg
那么应该选择什么呢?
选择正确的算法很大程度上取决于你要解决的问题。一项技术因错误的原因而被选择,这变得非常普遍,通常是因为围绕该技术的炒作,或者缺乏对人工智能算法更广阔前景的认识。当你拥有的工具是一把锤子时,所有的东西看起来都像钉子。
随着人工智能扩散到我们生活的各个方面,需求变得更加复杂,一个应用程序很可能需要不止一种这样的技术。通过传感器收集的噪声数据可以通过人工神经网络进行处理,以推断出关于环境的离散信息,而符号算法使用这些信息来搜索可能的行动空间,这些行动可以在更抽象的逻辑级别上实现某些目标。
在一定概率水平内,机器学习算法在推断自动驾驶汽车的周围环境方面可能非常有效,但如果它可能使汽车驶下悬崖,那么这种错误的可能性是不可接受的,因为这种情况从未在样本训练数据中正确捕捉到。此外,将深度学习引入任务关键型应用程序被证明是具有挑战性的,特别是当一辆摩托车仅仅因为翻倒而被混淆为降落伞时。
覆盖一个符号约束系统可以确保逻辑上显而易见的东西仍然得到执行,即使底层的深度学习层由于一些统计偏差或嘈杂的传感器读数而另有说法。这对于高风险应用变得越来越重要,如管理发电站、调度火车、自动驾驶系统和空间应用。在这样的系统中错误分类的含义比推荐错误的电影要严重得多。
利用连接主义者和符号算法的混合系统将利用两者的优势,同时抵消彼此的弱点。单独使用一种技术的局限性已经被发现,最新的研究已经开始表明将两种方法结合起来可以产生更加智能的解决方案。
Josef Bajada 拥有计算机科学博士学位,专门研究规划和调度的人工智能技术。他是一名技术顾问,为物流和油田技术应用开发人工智能解决方案。上述文章中表达的任何观点纯属其个人观点,不一定代表任何附属机构的观点。
深度学习是如何推动社会公益的?
深度学习如何用于减少野生动物偷猎,帮助贫困农民提高产量,检测非法砍伐森林和拯救濒危语言。
本周图表!
Dragon-Leap! China is surging in AI patents, will it change her IP compliance history? On the other hand, the AI landscape in US is made up by just ~5 tech companies, with IBM being wolf-pack leader.
野生神经细胞
OpenCV to classify elephants with 98% accuracy
今天,几乎所有的保留森林都有照相机陷阱,每天产生数百小时的镜头和数千张图像。所有的语料库都发生了什么?一些人(大多没有报酬或报酬很低)手动分析它的一些基本模式,这总是如果濒危动物存在或不存在,如果一个意想不到的人被看到。庞大的数量造成了系统的滞后和低效率。大多数野生动物保护区仍然使用人工估算来进行动物普查;这会产生错误的数据,进而导致糟糕的决策。当我看到安东尼天真的 CNN 代码如何能探测到大象(为了象牙被大量捕杀)&可以帮助阻止偷猎;我突然意识到,人工智能更多的是想象力,而不是算法。它还可能有助于追踪动物的活动、栖息地的变化以及避免人类冲突。我希望将它扩展到老虎,并很快作为野生神经项目之一部署在老虎保护区。尽管如此,仍然有许多野生物种不需要太多关注! Git
迷失在翻译中
世界上大约有 7000 种语言,但大多数正在消亡。文化、故事以及与人类进化的联系也随之消亡。比如说;著名的丛林小说的发源地的语言——马迪亚正濒临灭绝。灭绝的主要原因是缺乏文字,因为大多数本土语言只是口头语言。技术革命使其更加边缘化。当所有的教育都只能用外语进行时,如何用自己的语言教育当地人就成了一个严重的难题?强迫当地人/部落学习现代语言可能看起来很高尚,但也被他们视为殖民主义。我们怎样才能让他们的语言变得容易理解,从而让他们感受到现代性? @ TeHiku 利用深度学习构建了第一个新西兰土著人毛利语语音识别系统。目标是训练机器转录数千小时的母语说话者音频记录,以便随着母语说话者人口的减少,语言学习者更容易理解母语 te reo 毛利人。Luxembergish 的项目也在进行中。 Github
绿色革命 2.0
60 年代的印度是一个长期挨饿的国家,总是乞求我们养活它饥饿的人群。尽管当时农业是最大的产业。问题?由于陈旧的方法导致产量低!60 年代末,印度在美国和墨西哥的帮助下采用了现代技术,这极大地提高了其粮食产量,甚至在养活了 10 亿人口后还能出口。这种农业技术的转变在印度被称为“绿色革命”。但不幸的是,从那以后,一切都没有改变。现在,它正面临一场由农作物歉收导致的新危机,每年约有 5 万农民自杀,而且这一情况还在恶化。一家德国公司使用作物图片,随后通过深度学习模型处理来预测植物疾病,结合其他特征,可以提供关于作物蠕虫流行病的进一步建议&产量。模型基于标准 CNN 算法。虽然全世界都在关注高风险的人类诊断,但这种低风险的植物诊断对人类的影响更大。完整故事 (5 分钟阅读)
当 AI 不够用的时候…
Keras based DL used to detect illegal mining in over 70,000 acres
非洲和拉丁美洲的非法采矿是个大问题。它不仅造成了致命的污染,还导致了当地人栖息地的丧失、收入掠夺、童工和人口贩卖。一家公司正在通过使用乌克兰的 Keras 进行图像分割来帮助检测这个国家的麻风病。雨林基金会在亚马逊提供无人机武装土著秘鲁人保护他们的栖息地。但是检测真的能治愈疾病吗?随着下面的视频故事展开,我们看到,虽然人工智能&无人机可以检测白天抢劫;在一个正义是奢侈品的社会里还是很无奈的。甚至在警察赤裸裸地看到之后,森林砍伐仍在继续。当他们没有法治和人权的时候,人工智能有用吗?不幸的是,对人工智能的大肆宣传似乎表明它是一种灵丹妙药,但却忘记了加上那颗星星——不是到处都适用的!如果社会建立在平等、自由和公正的基础上,它就能有效地运转。这不是悲观,而是现实检验,人工智能可能有所有的解决方案,但它不能取代人类的斗争!雨林副记 (7 分钟视频) Keras 项目
使用 AWS DMS 将 AWS RDS Postgres 同步到红移
实时仓库更新指南
免责声明:这篇文章假设你对编程有所了解。
Photo by Shahadat Rahman on Unsplash
问题是
当我们第一次开始了解 AWS 红移时,我们爱上了快速聚合查询处理。这种强大的优势意味着在执行统计研究或简单的数据提取时,我们的生产力和速度突飞猛进。所以,当然,我们把它变成了我们管理的所有数据源(Adwords、Salesforce、FBAds、Zendesk 等)的主数据仓库。)—所有这些,使用缝合作为我们主要的 ETL 工具。
RDS Postgres instance vs Redshift on the company’s everyday aggregated query performance time.
Stitch 有一个不错的 100 美元的订阅计划,为 500 万行提供处理能力,每增加 100 万行收费 20 美元。缝合日志和账单发票告诉我们,在一个非常繁忙的月份,使用上面提到的所有数据源,我们勉强达到了 180 美元。这些月份中的大部分只是普通的 100 美元(没有使用额外的百万行)。
我们公司开发、维护和销售其核心 SaaS 产品增卡。我们的生产数据库托管在 AWS 云中,驻留在 AWS RDS 中,每月存储 1000 万到 2000 万行新数据,并且还在大幅增长。
因此,通常情况下,对于一家第三世界的初创公司来说,使用 Stitch 将我们的生产数据库同步到红移仓库会被证明是极其昂贵的。另外考虑到我们国家的货币最近对美元贬值了很多。
Argentina’s Congress — Photo by Sander Crombach on Unsplash
我们还有另一个限制。该公司正在开发其第二个主要产品increacenconcicion。这一个使用 NoSQL Apache Cassandra 数据库来存储和处理其庞大的数据。问题是,两个产品必须同步,以便会议使用卡提取的交易。换句话说,我们必须建立一个可供任何服务消费的数据湖,以按需执行同步操作。
很多事情要考虑,对吧?
测试解决方案
作为一个 2 人的小团队,强大的“数据团队”,我们很容易尝试和测试新事物,尤其是架构。
我们从使用 AWS 数据管道开始,这是一种基于 UI 的服务,用于在一堆数据源之间构建 ETL。尽管构建 ETL 的过程相当简单,但是为了使它有效,我们必须采取一系列的变通方法——记住我们必须更新每一个变化,不管是插入、删除还是更新。由于这里不能使用代码,很快就变成了不可维护。此外,对于这项服务,IMO 没有太多详细的文档或清晰的示例。
我们尝试设置一个 Lambda,每 15 分钟消耗一次 Postgres 数据库的复制槽的日志,并将其发送到 Kinesis Firehose 数据流。在一个生产过程更新了比通常预期更多的行之前,它看起来似乎是安全可靠的。我们发现,在这些情况下,记录来自逻辑解码的方式是充满所涉及的表的大块更改的巨大行,导致函数每次试图加载它时都会因内存不足而死亡。我们通过将true
设置为逻辑解码插件的属性write_in_chunks
来解决这个问题,我们使用(wal2json),使我们能够对传入的 json 日志进行分区。长话短说,由于没有足够的时间来处理巨额交易,该功能仍可能终止不成功。不好的消息。
你来这里做什么
好吧,让我们开始吧。
Architecture diagram — Made with Lucidchart
我们当前的架构包括以下内容:
- DMS(数据库迁移服务)实例复制对红移和 S3 的持续更改。
- 红移源端点。
- DMS 使用 S3 桶作为目标端点。
- 每次在上述 S3 桶中创建对象时触发的 Lambda。
- (可选)订阅同一对象创建事件的 SNS 主题。这使您能够订阅该主题的任何内容,例如,多个 lambdas。更多信息,请点击此链接。
为了让这篇文章更“民主”,我会把它分成两部分。第一个是将变化直接复制到红移的步骤。第二,建立 S3 数据湖供其他服务使用。你可以随意阅读其中一个,或者更好的是,两个都读😄。
首先,启用逻辑解码
由于我不认为自己比编写 AWS 文档的人聪明,我将复制粘贴他们的一些说明如下🤷♂.
找到您的 RDS 实例,查找该实例应用的参数组。使用以下命令直接复制或修改参数组。
1.-将
*rds.logical_replication*
静态参数设置为 1。作为应用该参数的一部分,我们还设置了参数*wal_level*
、*max_wal_senders*
、*max_replication_slots*
和*max_connections*
。这些参数更改会增加 WAL 生成,因此您应该只在使用逻辑插槽时设置*rds.logical_replication*
参数。2.-重新启动 DB 实例以使静态
*rds.logical_replication*
参数生效。
重启后,我们应该准备好了。测试一切是否正常的一个好方法是在数据库控制台上运行下面一行。
increasecard=> show wal_level;
wal_level
-----------
logical
(1 row)
将变化直接复制到红移
首先,我们必须创建任务将要使用的资源。创建端点(源和目标)和复制实例(基本上是负责所有脏工作的 EC2 实例)。
创建复制实例的过程非常简单,所以我不赘述,只需确保使用能够访问您打算使用的源和目标的 VPC。
对于源端点,勾选类似“*选择一个 RDS 实例”*的选项,并有效地选择您的源数据库并填充凭证字段。
对于目标端点,选择红移并在所有文本框中填入主机、端口和凭证。
太好了,现在我们已经有了我们需要的一切,让我们创建一个任务来迁移和复制的东西。
在 DMS 中,按下 Ccreate Task按钮,给它起一个有趣的名字,并开始选择我们之前创建的所有资源。对于迁移类型选择迁移现有数据并复制正在进行的更改,这将首先执行完全迁移,然后开始复制目标数据库上正在进行的 CRUD 操作。
在选择部分,选择您想要使用的任何模式/表,在我的例子中,我将只复制一个模式中的每个更改——此外,检查表是否有主键,如果它们没有主键,DMS 可能会出错。使用 % 字符作为通配符(即*“所有包含单词‘foo’的表格都将是* *table = %foo%*
)。
该任务还可以有转换规则,它使您能够,例如,在目标目的地上更改模式或表名。
准备好让给松绑了吗?点击创建任务按钮并等待它开始——或者如果您选择在创建时不开始,则启动它。现在的任务是将表完全加载到目的地,然后开始复制更改。当完成迁移时,您应该看到加载完成,复制正在进行作为其状态。
aaaaaaand…
*瞧,*搞定!。你的红移仓库现在被你的生产 RDS 数据丰富了,干得好!。此时,如果出现任何问题,您可以随时启用 DMS 任务的日志记录功能来查看发生了什么😄,只要考虑到 Cloudwatch 计费。
您还可以查看 DMS 任务提供给我们的一些有用的图表。
Screenshot of dashboard of migrating task metrics — AWS DMS
下一节将讨论为其他服务创建 S3 数据湖,以消耗数据库更改。如果你现在要离开,感谢你的阅读,我希望这篇文章对你有用。
构建你的 S3 数据湖
创建和测试 DMS 任务以创建我们的 S3 数据湖
和以前一样,创建一个任务,它不是作为目标目的地的红移,而是一个 S3 桶。
对于目标端点,预先创建一个 S3 存储桶,只需输入存储桶的名称和相应的角色就可以访问它。考虑到服务角色应该有以下策略。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:DeleteObject"
],
"Resource": [
"arn:aws:s3:::<name-of-bucket>"
]
},
{
"Effect": "Allow",
"Action": [
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::<name-of-bucket>"
]
}
]
}
在附加参数部分,输入以下addColumnName=true;
,包括之前的参数或您可能想要使用的其他参数。
在这种情况下,选择仅复制数据更改作为迁移类型,我们不想让以前的数据充斥我们的 S3 存储桶。
Screenshot of AWS DMS task creation
有关使用 S3 作为 DMS 目标的更多信息,请单击此处的。
Image by Etienne Marais on Pixabay
好了,真相时刻,运行你的小弗兰肯斯坦宝贝。
任务的状态应该是正在复制。否则,检查与复制实例相关的日志,查看 Cloudwatch 服务中的错误。
从现在开始,如果您正在使用一个临时数据库实例(我希望您是这样),那么创建、更新和删除一些行,以便任务能够复制更改。这将有望以您在目的地端点中指定的 S3 存储桶中的 csv 文件结束。
该文件应该类似于:
Op, id, field..fields
I, 1, ...
D, 2
U, 3, ...
如果你不是,这里我们称之为 *salame,*你会意识到 I 代表插入, D 代表删除, U 代表更新。
构建 Lambda 函数
你期待已久的时刻。这是我们编写函数的地方,该函数将解析在我们的 bucket 上创建的 CSV 文档。
对于这一部分,我建议您使用无服务器,这是一个很好的工具,可以使用您的 AWS CLI 凭证轻松部署 Lambda 函数。就像写一个.yml
文件,点击serverless deploy
和瞧那么简单。
现在,让我们创建我们的 Lambda 函数,然后添加 S3 桶事件,以便在每次创建对象时触发该函数。另外,如果你已经指定了文件将被创建在一个特定的文件夹中,你可能想要添加一个前缀,只要把folder/
放在前缀文本框中,你就可以开始了。
Screenshot of AWS Lambda
让我们编写一部分函数,它将从 bucket 中上传的文件中接收和提取数据。
所以,我们首先要做的是构建我们的处理程序函数,你知道,通常的main()
但是委婉地说。
这个主函数将接收 Cloudwatch 处理的 JSON 事件作为参数,基本上是说"哟,桶中创建了一个新文件,这是访问它的键。"
这是 AWS 给我们的示例事件。
下面我粘贴了 Python 代码,用来获得在 S3 创建的文件的最终内容。
现在在file_content
变量中有了 CSV 的数据。如果你有使用解析器的经验,这应该是小菜一碟,如果你没有,我推荐你查看这个链接。
从现在开始,就看你的了。使用 python 驱动程序来处理 CRUD 操作,处理 CSV 中影响红移变化的每一行。在这种情况下,我建议使用像execute_values()
(psycopg2)这样的函数来最小化执行时间,如这里的所解释的。使用 Lambda 环境变量来处理函数要使用的凭证机密,记住硬编码它们不是一个好主意。
一般性结论
我呈现给你的,只是实现数据库同步目标的千万种可能中的一种。如果你不介意花几百块💸在为你处理 ETL 过程的服务上,去做吧。不,真的,去吧。
这个架构给我们带来了两个积极的副作用。首先,拥有关于生产数据库变化的跟踪信息,这是绝对不必要的。如今有了像 AWS Athena 和 Glue 这样的服务,你可以直接通过控制台查询数据。第二个是通过 S3 桶对象创建事件连接/触发任何过程的能力——在我们的例子中,increase cilica ción团队复制他们自己的 Cassandra 数据库中的变更。
我们已经结束了,希望你喜欢我的第一篇文章😄
Python 中的同义词和反义词
文本挖掘—提取同义词和反义词
Photo by micah boswell on Unsplash
语言分析可以通过多种方式进行。在这篇博客中,我们将看到如何使用自然语言处理(NLTK) WordNet 库从文本中提取同义词和反义词。
Source: Vincent Russo
WordNet 是 Python 自然语言工具包的一部分。它是英语中大量单词和词汇的集合,这些单词和词汇相互关联,并以某种方式进行分组。相似词的集合称为词条。此外,它是字典和同义词库的结合。它用于自动文本分析和人工智能应用。它在其集合中支持许多其他语言。请点击查看更多关于 WordNet 的信息
名词、动词、形容词和副词被分成认知同义词组(同义词组),每个同义词组表达一个不同的概念。同素集通过概念语义和词汇关系相互联系。让我们看一些例子
找到这个词的意思
密码
导入 NLTK 库并安装 Wordnet
import nltk
nltk.download('wordnet')
在这个例子中,我们将看到 wordnet 如何返回单词的含义和其他细节。让我们继续查找单词“旅行”
有时,如果有一些例子,它也可以提供。
**#Checking the word "Teaching"**syn = wordnet.synsets(“teaching”)
syn
输出
[Synset('teaching.n.01'),
Synset('teaching.n.02'),
Synset('education.n.01'),
Synset('teach.v.01'),
Synset('teach.v.02')]
我们可以看到,“教”有五层含义。让我们找到第一种感觉,以便更好地理解每个 synset 包含的信息种类。我们可以通过在其名称处索引第一个元素来做到这一点。n,v 代表词性标注。
密码
**# Printing the Synonym, meaning and example of "teaching" for the first two indexes****#First Index**print(‘Word and Type : ‘ + syn[0].name())
print(‘Synonym of teaching is: ‘ + syn[0].lemmas()[0].name())
print(‘The meaning of the teaching: ‘ + syn[0].definition())
print(‘Example of teaching : ‘ + str(syn[0].examples()))**#Second Index**
print(‘Word and Type : ‘ + syn[1].name())
print(‘Synonym of teaching is: ‘ + syn[1].lemmas()[0].name())
print(‘The meaning of the teaching : ‘ + syn[1].definition())
print(‘Example of teaching : ‘ + str(syn[1].examples()))
输出
**# Output for first index**Word and Type : teaching.n.01
Synonym of Teaching is: teaching
The meaning of the Teaching: the profession of a teacher
Example of Teaching : ['he prepared for teaching while still in college', 'pedagogy is recognized as an important profession']**# Output for second index**Word and Type : teaching.n.02
Synonym of Teaching is: teaching
The meaning of the Teaching : a doctrine that is taught
Example of Teaching : ['the teachings of religion', 'he believed all the Christian precepts']
同义词
我们可以使用 synset 的**lemmas()**
函数。它返回该特定同义词集的同义词和反义词。
密码
**#Checking synonym for the word "travel"**
from nltk.corpus import wordnet#Creating a list
synonyms = []for syn in wordnet.synsets("travel"):
for lm in syn.lemmas():
synonyms.append(lm.name())#adding into synonyms
print (set(synonyms))
输出
{'trip', 'locomote', 'jaunt', 'change_of_location', 'go', 'traveling', 'travelling', 'locomotion', 'travel', 'move', 'journey', 'move_around'}
我们可以从上面的输出中看到单词“travel”的同义词。
反义词
密码
**#Checking antonym for the word "increase"**
from nltk.corpus import wordnet
antonyms = []for syn in wordnet.synsets("increase"):
for lm in syn.lemmas():
if lm.antonyms():
antonyms.append(lm.antonyms()[0].name()) #adding into antonymsprint(set(antonyms))
输出
{'decrement', 'decrease'}
WordNet 还有另外一个特性叫做单词相似度。这有助于我们检查我在这篇博客中没有提到的两个词之间的相似性。
感谢阅读。请继续学习,并关注更多内容!
用生成性对抗网络合成音频
毕竟,音频和图像并没有太大的不同
介绍
在过去的几年里,生成对抗网络(GANs)在计算机视觉领域取得了巨大的成功。由于最近的进步,如 Nvidia 的 StyleGAN 和 Google 的 BigGAN,我们现在能够生成高清晰度的高度逼真的图像;通常生成的或“伪造的”图像与真实的图像完全无法区分,这决定了 GAN 的实际发展程度。
Faces generated by StyleGAN
但是图像并不是 GANs 能够吃的唯一食物:音频是这种网络的另一个可能的应用,不知何故这个领域仍然是广泛未被探索的。
在本文中,我们将解释如何将 GANs 应用于音频信号,最后我们将尝试生成一些音频剪辑。
音频信号
音频和图像有什么区别?嗯,它们比你想象的更相似。
在处理数据科学和机器学习的时候,我们必须把一切都想成数字、向量和张量;您可能已经知道,黑白图像可以被视为一个简单的 2D 矩阵,其中每个数字代表一个像素,并表示该像素在特定位置的“白”程度。然而,对于 RGB 图像,我们必须有 3 个矩阵或通道,每种原色一个。
Color Image as 3 matrices (Tensor)
现在我们来看音频信号。听音乐时,你实际上听到的是不同时间的不同声音:这就是为什么我们可以将音频信号视为时间序列。
在每一个时间点上,“声音”可以用一个单一的值来表示;因此,我们可以认为声音(或“振幅” a )是时间的简单函数( t ),因此 a=f(t) 。函数 f 是连续的(本质上),所以要将信号转换成一组有限的数字,我们需要选择一个采样率。
Plot of Audio Signal: Amplitude over Time
如果采样率是 16000 Hz,这意味着我们将以 1/16000 秒的间隔记下幅度值,因此 2 秒的音频剪辑将产生 32000 个数字的单个向量(如果音频是立体声,我们将有 2 个长度相同的向量,每个音频通道一个)。
总之,虽然图像可以被视为矩阵(或张量),但音频信号可以被视为简单的向量。
关于音频信号还有很多有趣的理论,对音频进行编码的方式也很多(例如作为图像),但这对于我们在本文中将要讨论的内容来说已经足够了。
韦弗根
2018 年的一篇论文介绍了 WaveGAN ,一种能够合成音频的生成式对抗性网络架构。网络结构与一种名为 DCGAN 的网络结构极其相似,在生成器和鉴别器中都使用了卷积层:如果你熟悉用于生成图像的传统卷积 GAN 架构,WaveGAN 将非常容易理解。
DCGAN architecture
假设我们有一个发生器,它必须从一个噪声矢量输出 1 秒的音频(如果采样速率为 16 kHz,这将是一个 16000 长的矢量,不考虑它必须是 4 的幂这一事实,我们将在后面解释)。
首先,由于我们不再处理 2D 图像,传统卷积层中使用的 2D 滤波器现在已经没有用了。请记住,音频信号可以被视为简单的向量:因此,我们必须将滤波器更改为一维:DCGAN 中的 5×5 2D 滤波器现在变成了 WaveGAN 中的 25 长 1D 滤波器。
使用转置卷积将音频从噪声放大到 16000 长的矢量会影响合成的音频,因为它们在图像中会产生棋盘状伪影,在音频信号中也会产生类似的伪影。仅仅基于这种人为因素,鉴别者可以很容易地学会识别假音频,从而恶化整个训练过程。该论文提出了一种称为相位混洗的智能解决方案,但我们将避免转置卷积,而是使用上采样层(最近的邻居)后跟正常卷积。
在 DCGAN 中,我们在每一层将“图像”放大 2 倍(例如 32x32 到 64x64),而在一维中,向量每次放大 4 倍(例如 1024 到 4096)。
From 2D (DCGAN) to 1D (WaveGAN)
这一点很重要,因为我们需要记住,对于 1 秒钟的音频,考虑到采样速率为 16 kHz,相应的向量长度为 16000,选择每次以 2 倍的因子进行上采样将需要很多层。
这也是为什么生成的向量的长度是 4 的幂(如果我们想要以 16 kHz 采样约 1 秒的合成音频,则长度为 16384)。
因此,一切也适用于鉴别器:在这种情况下,我们将使用步长为 4 的 1D 卷积,这相当于在每一层以因子 4 进行下采样。
这绝对是你需要知道的使图像的传统 GAN 与音频信号一起工作的一切:改变滤波器为 1 维,放大和缩小 4 倍。这两个网络的训练方式和损失函数是相同的,所以没有什么新的东西。
很简单,对吧?
成果和障碍
最初的 WaveGAN 论文作者在官方网页这里展示了他们的成果。他们试图生成各种各样的音频领域,如人类语音、鸟鸣、鼓和音乐,并获得了令人信服的结果。我真的推荐你亲自去看看。
最难合成的领域之一当然是人类的语音:虽然我们不知道真实的鸟声应该是什么样的,但我们对如何解读人类的声音以及如何辨别真假有着非常深刻的理解。
我们可以说,人类的声音对于音频来说就像人脸对于图像来说一样:对于一台机器来说,学习如何生成这些域同时保持它们与真实域无法区分确实很难。这就是为什么在这种特殊情况下,WaveGAN 的后代对我们的耳朵来说显然是假的:我们必须记住,GAN 对单词、短语组成和语调毫无概念,所有概念都难以学习,在合成样本中对我们来说代表着直接的危险信号。
我们需要在这项技术的发展中采取更多的步骤,以便能够从原始语音数据中创建真实的样本,但我认为我们离这一成就不远了。
我自己曾试图从巴拉克·奥巴马演讲的原始音频中提取一些样本,不出所料,没有任何令人信服的结果。以下是一些例子:
结论
使用 GANs 进行音频生成有很大的潜力,既有积极的一面,也有消极的一面:一些研究人员已经探索了人类语音领域翻译的想法(想象一下将奥巴马的语音转换为特朗普的语音,就像语音的 Deepfakes),使用一些众所周知的 GANs 架构,如 CycleGAN,以达到他们的目标。
正如我们所见,虽然这项技术产生的结果与现实相差甚远,但我们需要考虑这样一个事实,即它为滥用提供了可能性,就像 Deepfakes 所发生的那样。在我看来,这不应该吓退我们探索合成音频生成的世界,而是应该邀请我们拥抱它,并发现它的潜力和弱点。
我想真诚地感谢你阅读这篇文章,我真的很感激,希望你能学到一些新的东西。
玩得开心!
使用 Scikit Learn 为 ML 生成合成数据集等
使用 Scikit 生成合成数据集了解更多信息
越来越明显的是,谷歌、脸书和微软等大型科技巨头对他们最新的机器学习算法和软件包非常慷慨(他们免费提供这些),因为算法世界的准入门槛目前相当低。开源社区和工具(如 Scikit Learn)已经走过了漫长的道路,大量开源项目正在推动数据科学、数字分析和机器学习的发展。站在 2018 年,我们可以有把握地说,算法、编程框架和机器学习包(甚至是如何学习这些技术的教程和课程)不是稀缺资源,而是高质量的数据。
当涉及到调整和微调这些算法时,这往往成为数据科学(DS)和机器学习(ML)领域从业者的一个棘手问题。从一开始就指出这一点也是明智的,当前的文章是关于算法研究、教学学习和模型原型的数据缺乏,而不是关于扩展和运行商业操作的数据缺乏。这不是关于如何为你正在开发的酷旅行或时尚应用获取高质量数据的讨论。这种消费者、社会或行为数据的收集有其自身的问题。然而,即使是像访问高质量数据集来测试特定算法方法的局限性和不可预测性这样简单的事情,往往也不那么简单。
为什么需要合成数据集?
如果您是从零开始学习,最合理的建议是从简单的小规模数据集开始,您可以在二维空间中绘制这些数据集,以便直观地理解模式,并以直观的方式亲自查看 ML 算法的工作情况。
然而,随着数据维度的爆炸式增长,视觉判断必须扩展到更复杂的问题——如*学习和样本复杂性、计算效率、类别不平衡、*等概念。
在这一点上,实验灵活性和数据集的性质之间的权衡开始发挥作用。你总是可以找到一个真实的大型数据集来实践这个算法。但这仍然是一个固定的数据集,具有固定数量的样本、固定的底层模式,以及正负样本之间固定的类别分离度。你也必须调查,
- 测试和训练数据的选定部分如何影响算法的性能和鲁棒性
- 面对不同程度的类别不平衡,这些指标有多稳健
- 必须做出什么样的偏差-方差权衡
- 该算法在训练和测试数据中的各种噪声特征(即标签和特征集中的噪声)下如何执行
- 你是如何实验并梳理出你的 ML 算法的弱点的?
事实证明,使用单个真实数据集很难做到这些,因此,您必须愿意使用合成数据,这些数据足够随机,可以捕捉真实数据集的所有变化,但又足够可控,可以帮助您科学地调查您正在构建的特定 ML 管道的优势和劣势。
虽然我们不会在本文中讨论这个问题,但这种合成数据集的潜在好处可以很容易地在敏感应用程序中衡量出来——医疗分类或金融建模,在这些应用程序中,获得高质量的标记数据集通常是昂贵和令人望而却步的。
用于 ML 的合成数据集的基本特征
应当理解,在这一点上,合成数据集是以编程方式生成的,而不是来源于任何种类的社会或科学实验、商业交易数据、传感器读数或图像的手动标记。然而,这样的数据集肯定不是完全随机的,并且用于 ML 的合成数据的生成和使用必须由一些首要的需求来指导。特别是,
- 它可以是数字、二进制或分类(有序或非有序),并且要素的数量和数据集的长度可以是任意的
- 它必须有一定程度的随机性,但同时,用户应该能够选择各种各样的统计分布作为该数据的基础,即可以精确地控制和调整潜在的随机过程,
- 如果用于分类算法,那么类别分离的程度应该是可控的,以使学习问题容易或困难,
- 可以以可控的方式插入随机噪声
- 生成速度应该非常高,以便能够针对任何特定的 ML 算法对大量这种数据集进行实验,即,如果合成数据是基于真实数据集上的数据扩充,则扩充算法必须在计算上高效
- 对于回归问题,可以使用复杂的非线性生成过程来获取数据——真实的物理模型可能有助于这一努力
在下一节中,我们将展示如何使用一些最流行的 ML 库和编程技术来生成合适的数据集。
使用 Scikit learn 和 Numpy 生成标准回归、分类和聚类数据集
Scikit learn 是基于 Python 的数据科学软件栈中最受欢迎的 ML 库。除了优化的 ML 例程和管道构建方法之外,它还拥有用于合成数据生成的实用方法的可靠集合。
使用 Scikit 学习进行回归
Scikit learn 的dataset.make_regression
函数可以创建任意数量的输入特征、输出目标以及它们之间的可控信息耦合度的随机回归问题。
使用 Scikit 学习进行分类
类似于上面的回归函数,dataset.make_classification
生成一个随机的多类分类问题,具有可控的类分离和添加的噪声。如果需要,还可以随机翻转任意百分比的输出符号来创建更难的分类数据集。
使用 Scikit Learn 进行聚类
Scikit learn 实用程序函数可以产生各种聚类问题。最直接的方法是使用datasets.make_blobs
,它可以用可控的距离参数生成任意数量的集群。
为了测试基于相似性的聚类算法或高斯混合模型,以特殊形状生成聚类是有用的。我们可以使用datasets.make_circles
函数来实现。
对于使用支持向量机(SVM) 算法测试非线性核方法,像 k-NN 这样的最近邻方法,或者甚至测试一个简单的神经网络,通常建议使用某些特定的数据进行实验。我们可以使用噪声可控的dataset.make_moon
函数生成这样的数据。
具有 Scikit 学习高斯混合模型
高斯混合模型(GMM)是文本处理/自然语言处理任务中无监督学习和主题建模的有趣研究对象。下面是一个简单函数的示例,展示了为这种模型生成合成数据是多么容易:
import numpy as np import matplotlib.pyplot as plt import random def gen_GMM(N=1000,n_comp=3, mu=[-1,0,1],sigma=[1,1,1],mult=[1,1,1]): """ Generates a Gaussian mixture model data, from a given list of Gaussian components N: Number of total samples (data points) n_comp: Number of Gaussian components mu: List of mean values of the Gaussian components sigma: List of sigma (std. dev) values of the Gaussian components mult: (Optional) list of multiplier for the Gaussian components ) """ assert n_comp == len(mu), "The length of the list of mean values does not match number of Gaussian components" assert n_comp == len(sigma), "The length of the list of sigma values does not match number of Gaussian components" assert n_comp == len(mult), "The length of the list of multiplier values does not match number of Gaussian components" rand_samples = [] for i in range(N): pivot = random.uniform(0,n_comp) j = int(pivot) rand_samples.append(mult[j]*random.gauss(mu[j],sigma[j])) return np.array(rand_samples)
超越 Scikit 学习:来自符号输入的合成数据
虽然上述函数可能足以解决许多问题,但生成的数据确实是随机的,并且用户对生成过程的实际机制控制较少。在许多情况下,人们可能需要一种可控的方式来基于明确定义的分析函数(涉及线性、非线性、理性甚至超越项)生成回归或分类问题。下面的文章展示了如何结合 SciPy 中的符号数学包 SymPy 和函数,从给定的符号表达式中生成综合回归和分类问题。
从给定的符号表达式生成的回归数据集。
从给定的符号表达式生成的分类数据集。
使用 Scikit-image 的图像数据增强
深度学习系统和算法是数据的贪婪消费者。然而,为了测试深度学习算法的局限性和鲁棒性,人们经常需要向算法提供相似图像的细微变化。 Scikit image 是一个令人惊叹的图像处理库,构建在与 scikit learn 相同的设计原则和 API 模式上,提供了数百个很酷的函数来完成这个图像数据增强任务。
下面这篇文章很好地提供了这些想法的全面概述:
色调、饱和度、价值通道
裁剪
随机噪声
旋转
漩涡
我们展示了这种增强过程的一些精选示例,从单个图像开始,并在同一图像上创建数十种变化,有效地将数据集放大许多倍,并创建一个巨大大小的合成数据集,以稳健的方式训练深度学习模型。
具有分割的随机图像合成器
NVIDIA 提供了一个名为 NDDS 的 UE4 插件,使计算机视觉研究人员能够导出带有元数据的高质量合成图像。它支持图像、分割、深度、对象姿态、边界框、关键点和自定义模板。除了导出器之外,该插件还包括各种组件,能够生成用于数据扩充和对象检测算法训练的随机化图像。随机化工具包括照明、对象、相机位置、姿势、纹理和干扰物。这些组件一起允许深度学习工程师轻松创建随机场景来训练他们的 CNN。这是 Github 的链接,
使用 pydbgen 生成分类数据
Pydbgen
是一个轻量级的纯 python 库,用于生成随机有用的条目(如姓名、地址、信用卡号、日期、时间、公司名称、职位、车牌号等)。)并将它们保存在 Pandas dataframe 对象中,或者作为数据库文件中的 SQLite 表,或者保存在 MS Excel 文件中。你可以在这里阅读文档。这里有一篇文章描述了它的使用和效用,
这里有几个说明性的例子,
合成时间序列数据集
有相当多的论文和代码库使用在现实生活的多元时间序列中观察到的特殊函数和模式来生成合成时间序列数据。下面的 Github 链接给出了一个简单的例子:
合成音频信号数据集
音频/语音处理是深度学习实践者和 ML 爱好者特别感兴趣的领域。谷歌的 NSynth 数据集是一个由各种乐器发出的短音频文件声音合成生成的(使用神经自动编码器以及人工和启发式标记的组合)库。以下是数据集的详细描述。
强化学习的综合环境
奥鹏健身馆
最大的强化 ML 综合学习环境库是 OpenAI Gym 。它由大量预先编程的环境组成,用户可以在这些环境上实现自己的强化学习算法,以对性能进行基准测试或对隐藏的弱点进行故障排除。
随机网格世界
对于强化学习的初学者来说,在一个简单的网格世界中进行练习和实验通常会有所帮助,在这个世界中,代理必须通过迷宫到达一个终端状态,每个步骤和终端状态都有给定的奖励/惩罚。
只需几行简单的代码,就可以合成任意大小和复杂度的网格世界环境(具有用户指定的终端状态和奖励向量分布)。
https://github.com/tirthajyoti/RL_basics
看看这个 Github repo 的想法和代码示例。
Scikit 了解更多关于合成数据生成的信息:摘要和结论
在本文中,我们回顾了几个为机器学习生成合成数据的例子。读者应该清楚,这些绝不是数据生成技术的详尽列表。事实上,除了 Scikit Learn 之外,许多商业应用程序都在提供相同的服务,因为用各种数据训练您的 ML 模型的需求正在快速增长。然而,如果作为一名数据科学家或 ML 工程师,您创建了自己的合成数据生成编程方法,这将为您的组织节省投资第三方应用程序的资金和资源,并让您以整体和有机的方式规划 ML 管道的开发。
希望您喜欢这篇文章,并且能够很快在您自己的项目中使用这里描述的一些技术。
其他注释
原载于 2019 年 8 月 28 日【https://blog.exxactcorp.com】。
系统可用性公式-要记住的假设
Image by Author
系统可用性,即系统在需要时工作的概率,直接影响系统维护策略、效率和系统设计中的冗余。上述公式是描述和计算系统可用性最常用的表达式。这个公式的主要优点是简单。然而,不幸的是,人们经常误解这个公式本身就是可用性的实际定义。它不是。上述公式是一系列数学计算的结果,基于单个独立组件的假设,在稳态条件下故障和修复呈指数分布。
在这篇文章中,我将一步一步地概述这个公式是如何推导出来的。
介绍
假设S(B)= 1表示一个状态( B ),或者一个给定系统被定义为可操作的状态的联合( B ),那么 系统可用性 , *A(t),*是在时间 t ,S() 系统可靠度 , R(t) 是到时间 *t,*系统尚未处于故障状态的概率,S(B)= 0。因此,可靠性可以表示如下:
可靠性与单个部件的故障概率有着简单的关系, F ₁ (t) 。然而,可用性是一个更复杂的问题。有许多不同的方法来解决这个问题。在这篇文章中,我将介绍马尔可夫方程方法。
危险功能和系统工程
在系统工程领域,危险函数*h(x)*描述事件(系统故障)在时间 t 发生的概率,假设该事件在该时间点之前尚未发生。风险函数(也称为失效率、风险率或死亡率) h(x) 是概率密度函数(PDF)*F(t)和生存函数S(t)**1-F(t)*之间的比值。其中 F(t) ,是累积分布函数(CDF)。危险函数在系统工程中起着重要的作用,因为只要系统在运行,系统工程中数据集的收集就通过观察系统中的故障来进行
。
等式(2)是使用贝叶斯定理的危险定义公式,其中:
***【F(t)***表示事件(系统故障)在 0 到 t 之间发生的概率
1- F(t) 表示事件直到时间 t 才发生的概率。
f(t)dt 表示事件在时间 t 的小区间 dt 内发生的概率。
z(t)dt 表示某事件在 t 的小区间 dt 内发生的条件概率,假设该事件在该时间之前尚未发生。
z(t) 采用了危险函数的名称,因为它与故障有关。系统故障是系统工程中的重要事件,但考虑到系统的生命史,它们不是唯一可能的事件。还有许多其他事件,如维修、检查、维护、运行状态的变化,以及许多其他可能具有统计性质的事件。
指数分布
指数分布是风险不变的特殊情况。
因此,指数失效密度对应于一个与时间无关的常数风险函数,换句话说,不会老化。常数风险函数是指数分布的无记忆特性的结果:假设受试者已经存活到时间 t 的剩余存活时间的分布不依赖于 t 。把
换个说法,一个时间区间内的死亡概率【t,t+y】独立于起点,t【1】。
指数分布是系统工程应用中最广泛使用的分布。这主要是因为它是最简单的函数,而不是因为它是正确的函数。
马尔可夫过程
马尔可夫过程是一个随机过程,在这个过程中,给定现在,系统的未来状态独立于过去。在这种模型中,系统的未来状态完全由系统的当前状态决定。如果系统中的所有组件都具有指数分布,那么系统是马尔可夫的,未来只取决于现在的状态。
等式(4)被称为马尔可夫等式【2】。它是一组联立的一阶微分方程,是作为 n 单入口状态传输方程的特例而导出的。马尔可夫方程有一个简单的物理解释。 zᵢ 代表离开状态 i 的比率,因此 zᵢPᵢ(t) 代表该状态下人口的减少。同样,组件从其他状态进入状态 i 。从任一状态 j 转移到状态 i 的速率为 zᵢⱼ ,导致单位时间内zᵢⱼpᵢ(t状态 i 的人口增加。马尔可夫链有有限数量的 n 个状态,在任何时间处于任何状态的概率是 1 (这就是所谓的归一化方程)
对于具有指数分布的两个状态的简单情况,等式(4)采用简单的形式:
其中λ是失效的危险,通常称为失效率*,μ称为修复率。*
利用归一化方程 P₁(t)+P₀(t)=1 ,得出:
具有边界条件 P₁(0)=1 的方程(6)的解产生:
具有两种状态的单个组件的可用性包含两个术语。第二项是瞬态的,随着时间的增加而变为零。第一项称为稳态可用性* A ∞,注意到 1/λ 是平均无故障时间 (MTTF)和1/μ平均修复时间 (MTTR),可以得到:*
这是描述和计算可用性最常用的表达式之一。等式(7)的主要优点是简单。事实上,许多人很直观地认为这个等式就是可用性的定义。可用性公式为真当且仅当故障概率密度函数以及修复 PDF 为指数函数,且仅针对稳态( t → ∞时)。
这种误用公式的情况,在数值计算领域是很常见的。正如英国统计学家乔治·博克斯的名言:“所有的数字计算模型都是错误的,有些是有用的”。由于模型和公式是基于假设的,所以当试图将这些模型应用到现实生活中以产生现实结果时,不应该忘记这些假设。
系统设计思维:区分人工智能和人工智能
人工智能和机器学习有什么不同?
AI 和 ML 的区别有太多松散的定义。大多数定义都比较轻松。我最喜欢的一个是:
如果是在 PowerPoint 上,很可能是 AI。如果是用代码,就是 ML。
大多数定义都不严谨,因为这种定义没有明确的预期结果。
让我们快速给出一个严肃的目的——职业装修。
问题陈述是这样的。你有两个人,一个在多个系统方面经验丰富,但在 ML 方面经验不足。第二个是非常年轻的有 ML 经验的。对于给定的项目,您应该检查您是否对两者都有角色。如果你只有一个角色,你应该决定保留谁。
由此,我们将深入研究一个案例。随着我们的进步,我们只是概述我们得到的主要思想和我们试图解决的主要问题。由此,我们将分离什么是 ML 和 AI。之后,让我们检查完成它所需的经验和成熟程度。
项目案例研究
这是一个农业人工智能的案例研究。这应该有助于玉米田监测。基于图像的系统需要提供关于疾病的警告,以便农民可以迅速处理并控制问题。
一架无人驾驶飞机周期性地飞过田野并收集图像。这些图像将用于疾病症状的预测。假设我们需要提供 3 个标签——健康、早期疾病、晚期疾病。
https://pixabay.com/photos/builder-farmer-hay-apply-computing-4298301/
机器学习的范围和重点
对于上面的案例研究,ML 涉及我们在所有教程中看到的机器学习任务。
我们定义模型。
我们有用于训练和测试集的图像。
最后,我们有一些最终客户提供的图片。
在创建好的模型时,我们可能会调整超参数,改变模型架构,改变模型本身。我们也可能会使用合成图像。我们可能会尝试我们所知道的所有人工智能技术。
要求说,我们需要 3 个标签。也许,我们会为各自的图像创建 3 个文件夹。为了简单起见,我们认为每个文件夹名代表各自的标签名。我们会用这些来训练。一切看起来都很好。验证图像预测看起来也不错。
在我们创建了模型并完成测试后,混淆矩阵看起来很好。假阳性和真阴性在统计要求范围内。
如果一切顺利,如果这是机器学习,那么什么是人工智能?
现在,人工智能的焦点
在最大似然预测成功后,团队向一位农民展示了最大似然预测演示。但是一个农民给出了另一个形象。这个预测完全错了。它有早期疾病。它无法被检测到。农夫很不高兴。
“先生,即使在健康的情况下,我也不介意去野外会有小麻烦。即使它错误地通知了我,也没关系。但是如果有疾病症状没有被发现,那对我来说就是一个大问题。我有好几公顷的庄稼,我需要知道在任何给定的时间里,我应该把精力集中在哪里。我有时间。你的系统应该给我重点关注的优先区域。”
团队意识到他们根本没有考虑过这样的形象。他们专注于提高现有数据集的准确性。他们关注的是准确率。他们遇到了过度拟合的问题。
可接受准确性的统计数据对该客户来说无关紧要。他不介意我们用低信心预测来提示他。他希望我们谨慎行事。
他们擅长机器学习。但在系统级 AI 方面做得不够。
现在,考虑一个完全不同的项目——一个 7-11 商店店主的案例。他想要一个闭路电视监控系统,用于检测商店盗窃和即时报警。这个人想要一个不介意小损失的系统。但他的客户的声誉和假警报是一个更大的问题。如果熟客虚惊一场,一去不返,那损失更大。他只想要非常明确的商店盗窃案件报告。 这个客户也希望我们谨慎稳妥,但方向相反。
我们刚刚讨论了业务影响和准确性。我们也可以看看其他方面。让我们回到玉米地。
训练数据的多样性
研究小组发现,另一组图像的假阳性显著增加。经过更深入的检查,研究小组发现这些图像中的玉米更大。只有团队意识到玉米作物的周期是 100 天左右!在这段漫长的时间里,他们只拍摄了一个实例的图像。需要非常频繁地拍摄训练图像——可能每天都拍?健康和不健康的视觉特征每隔几天就会发生剧烈的变化。现在有多重困难。
如果他们把所有健康的图像放在一个文件夹里,模型就学不到任何有用的东西。请看下面的两张图片。
https://pixabay.com/photos/field-cornfield-arable-corn-4280596/
https://pixabay.com/photos/harvest-cornfield-agriculture-corn-4195417/
这两幅图像如此不同。在第一种情况下,庄稼太小,而在第二种情况下,庄稼已经长得很大了。这些图像来自完全不同的角度。很难想象这个模型能学到什么。
看起来,为不同日期的图像设置不同的文件夹是有意义的。以前,一个标签有一个公共文件夹。
还需要定义图像记录的过程。无人机应在相同的高度和相同的预定路线上飞行。此外,一天中的时间也应该是固定的,以确保颜色或其他属性不会因光线变化而受到影响。此外,数据需要考虑云的阴影。
行..现在有了大数据集,按天分隔。那么训练过的模型也应该是白天分开的?即预测第 1 天的疾病可能性,我能为第 1 天训练一个通用模型,一直到第 100 天吗?这将导致过多的模型。
因此,团队可能不得不将模型分成几个不同的模型。可能是每周一次的数据。当图像被发送到模型进行预测时,元数据也应该有作物的日期。没有它,系统就不知道使用哪个模型进行预测。
部署和再培训策略
对于本案例研究,为了证明系统开发的投资是合理的,它应该可以在大范围内使用,最好可以在农民、州、国家甚至是大洲之间使用。这也有助于在更大的数据集上学习。如果一个地区出现了新的疾病,我们还应该能够重新训练系统,以适应这种新的疾病信息。
人工智能系统的重要方面是它会随着时间的推移变得更好。单靠 ML 并不能保证。它需要重新培训政策和流程。
假设法默发现了一个真正的负片,有没有简单的方法来制作它,并提供这样的图像?如果他不是一个懂电脑的人,可以通过语音命令来贴标签吗?当他以这种方式向系统发出警报时,系统是否能够标记数据的子集,以便进行手动检查?这将非常有帮助。项目发起人可以雇佣有农业背景的兼职承包商,来制作这些有疾病的图像。一旦这一批完成,再培训就可以进行了。
在 ML 中,我们只是谈论训练、交叉验证和预测。算法中不讨论再训练策略。只有这样端到端的思考,才会产生真正的人工智能系统。
更多的系统工程问题
该系统还可以考虑更多的系统工程方面。这可能是相机对焦模式,无人机在捕捉图像时的速度。当查看 ML 模型输入形状时,它对预测时间和所需资源有性能影响。这反过来会影响我们可以提供的用例及系统特性。
如果性能良好,我们可以在无人机飞行时进行实时预测。这可能会让顾客更开心。这可能需要团队降低图像的分辨率,以便更快地进行训练和预测。这可能是 ML 模型调整的一个因素。
商业、经济和法律问题
当我们考虑人工智能时,我们会考虑整体业务流程。我们也关心整个项目的经济效益。在涉及人员数据的项目中,还可能涉及法律问题。
在与安全相关的行业中,如作者工作的汽车、工业自动化,甚至需要证明预测是如何工作的,以及预测的可预测性如何!
定义人工智能
人工智能更多的是关于整个系统,各种角色、算法、业务需求如何相互作用。ML 主要讲的是机器学习的核心技术部分。
正如你所看到的,当我们讨论人工智能时,我们很少谈论技术细节和算法。我们更关心解决方案、部署、用户体验等等。如果我们将 ML 应用于非常具体的小任务,如在手机中找到重复的图像,ML 和 AI 之间的差异并不显著。
midmanager.com
随着世界走向更高的人工智能采用,这种区别变得越来越重要。
最后,职业适应
我们已经定义了 ML 和 AI 之间的焦点差异。
现在让我们回到我们开始思考的最初焦点。这是关于给两个员工安排合适的工作。
对于我们看到的疾病检测示例,ML 工程师可以是接受机器学习培训的人。他或她可以专注于算法、Python、Pytorch、张量流、模型架构、超参数等。
要完成整个系统架构,定义最终使用和部署的业务和技术流程,您需要一个解决方案架构师。即使这样的人可能不知道 ML 非常具体的细节,他应该能够很好地简化解决方案,使其可用,并使其成为一个学习系统。
所以,如果有一个没有 ML 背景的有经验的软件架构师或业务分析师,不要解雇他。也许这样的人更适合项目中的系统级角色。当然,对于 ML 特定的角色,雇佣具有 ML 认证的成员。
总而言之,
是的。AI 代表幻灯片,ML 代表代码。
我们对意义看得越深,我们学到的就越多。随着我们了解得越多,我们在系统设计方面就做得越好。
使用日志分析的系统故障预测
使用递归神经网络预测系统故障的深度学习方法
在现代社会,系统故障是一个严重的问题,需要解决。如果能够获得准确的系统故障预测,IT 公司或各种研究机构将受益匪浅。如果事先作出适当的预测,计算机故障的不利影响会有所减轻。如果这种情况即将发生,则可以限制资源、应用程序和其他消耗内存的进程的使用,从而防止系统崩溃。
在剩余时间充足的情况下实现准确预测相当困难。在这篇博客中,我介绍了一种通过提前解析日志文件来检测故障的简单方法。我们会在故障条件出现之前发出预警。为了达到我们的目的,我们使用了一种循环神经网络,即长短期记忆。本文中的方法使用滑动窗口来获取期望的结果。考虑的重要因素是 RAM、CPU 和硬盘利用率。
下图显示了所使用的方法:
Methodology
系统故障预测在许多应用中是必不可少的,例如计算机需要执行高计算。非常高的硬盘使用率或 RAM 崩溃会阻止应用程序在 HPC 上执行。高性能计算是使用并行编程来高效运行复杂的程序。HPC 的恢复可能需要很长时间,有时甚至是不可能的。时间序列预测的使用也很普遍,但它不包括我们接下来要陈述的参数,这些参数可能是有益的。
从系统中获取的日志文件包含有关系统状态和内存消耗的信息。我们知道计算机的三个主要利用率是 CPU、RAM 和硬盘利用率。这些日志文件可以为我们提供时间戳以及在确定的时间戳上资源的确切利用率。我们已经考虑了具有相同间隔的时间戳的值。我们有一个由过去五天中生成的系统日志文件组成的数据。nmon 格式。所考虑的时间戳变化是固定的,并且具有 10 分钟的固定间隔。
我们有过。已转换为的 nmon 文件。csv 适合学习。我们还可以使用 nmon visualizer 工具可视化数据。我们考虑的 CPU、RAM 和硬盘利用率参数如下:
CPU 利用率:
User%:这表示处理器花费 x%的时间运行用户空间进程。用户空间进程是不使用内核的进程。一些常见的用户空间进程包括外壳、编译器、数据库和所有与桌面相关的程序。如果处理器没有空闲,那么通常大部分 CPU 时间用于运行用户空间进程。
Sys%:这表示处理器花费 x%的时间运行系统进程。系统进程由内核空间程序组成
Wait%:这表示处理器花费 x%的时间运行内核进程。所有的进程和系统资源都由 Linux 内核处理。内核执行的任务包括运行系统进程,管理内核空间中的硬盘等硬件设备。
Idle%:显示等待其他进程完成的 CPU 百分比。有时,处理器可能会启动读/写操作,并需要等待其他进程完成。
CPU 利用率=用户% +系统% +等待%
RAM 利用率:
- MemTotal:总可用内存
- MemFree:系统不使用的物理内存量
- 缓冲区:缓冲区高速缓存中的内存,因此相对临时存储原始磁盘块
- 缓存:页面缓存中的内存(磁盘缓存和共享内存)
- mem used = mem total-mem free-Buffers-Cached
特定时间戳时已用 RAM 的百分比= (MemUsed/MemTotal) * 100
硬盘利用率:
硬盘利用率%=(已用硬盘空间/总硬盘空间)*100
PCA:
现在我们有了时间戳的 CPU、RAM 和硬盘利用率的值。我们应用 PCA 来从这 3 个参数中获得单个缩减值。众所周知,PCA 或主成分分析是一种处理高度相关变量的方法。我们可以得到上述所有利用率的单一值。然后,我们可以应用单变量时间序列预测来预测未来时间戳的单个值。
应用 PCA 的步骤:
a)标准化数据。b)从协方差矩阵计算特征值和特征向量。c)按照降序对特征值进行排序,以对相应的特征向量进行排序。d)选择对应于最大特征值的 1 个特征向量。这为我们提供了每个时间戳的简化参数。
LSTM 模式:
LSTM architecture
我们遵循的步骤:
I)大小为 50 的向前移动窗口,这意味着我们使用前 50 个数据点作为输出输入 X 来预测 Y,即第 51 个数据点。接下来使用从第 1 点到第 51 点的窗口,我们预测第 52 点。
ii)使用结合了密集输出层的两层 LSTM 模型来进行预测。iii)我们使用以下两种方法来预测产量—
a)我们预测了测试数据集中每个项目的值。
b)我们通过向前移动一步将先前做出的预测反馈到输入窗口,并在所需的时间戳做出预测。我们有 LSTM 的 3D 输入向量,包括几个样本、几个时间戳、多个特征。保存训练模型的权重后,我们绘制预测值以可视化数据趋势。我们有一个 2 层 LSTM 模型和一个密集的输出层,如下表 3 所示。我们在两者之间使用 dropout,因为它是一种正则化技术,用于在我们训练 LSTM 模型时防止过拟合。
模型摘要:
Model summary for LSTM
结果:
下图显示了预测值和实际值的图形视图,以找出趋势。尽管训练数据量较少,但我们得到了期望的输出变化。我们的模型能够捕捉趋势。有了更多的训练数据,就可以预测更准确的结果。绿线代表实际值,而蓝线代表预测值。在 X 轴上,我们有时间戳间隔为 10 分钟的日期。Y 轴是我们之前获得的 PCA 缩减值。保存的权重帮助我们预测未来时间戳的缩减值。有了故障情况的时间戳和 PCA 缩减值(可以注意到实际系统故障发生的一些情况),我们可以正确地分类预测值是否属于故障类别。我们使用逻辑回归分类算法来达到我们的目的
该博客将帮助用户防止系统故障,因为它可以在实际故障发生之前向用户发送警告邮件或短信。然后,用户可以通过终止冗余进程来限制系统上正在运行的进程的数量。使用 LSTMs 进行时间序列预测有助于我们获得未来时间戳的缩减值。则可以使用逻辑回归分类模型将这些值用于分类为正常或故障类别。
结论:
这个项目是作为斋浦尔 Celebal 技术公司实习的一部分完成的。
这种方法将帮助用户防止系统故障,因为它可以在实际故障发生之前向用户发送警告邮件或 SMS。然后,用户可以通过终止冗余进程来限制系统上正在运行的进程的数量。使用 LSTMs 进行时间序列预测有助于我们获得未来时间戳的缩减值。然后使用逻辑回归分类模型将该值分类为正常或故障类别。如果我们可以在现有的列表中添加更多的功能,这项工作可以扩展。我们刚刚在研究中考虑了 CPU、RAM 和硬盘的利用率。也可以考虑诸如输入/输出数据传输(即数据写入硬盘的速率)、特定进程运行的时间等参数,以获得更好的准确性。
t-SNE Python 示例
Photo by Matt Wildbore on Unsplash
t 分布随机近邻嵌入(t-SNE)是一种降维技术,用于在二维或三维的低维空间中表示高维数据集,以便我们可以可视化它。与 PCA 等简单地最大化方差的其他降维算法相比,t-SNE 创建了一个降维的特征空间,其中相似的样本由附近的点建模,不相似的样本由远处的点以高概率建模。
在高层次上,t-SNE 为高维样本构建概率分布,使得相似的样本被挑选的可能性很高,而不相似的点被挑选的可能性极小。然后,t-SNE 为低维嵌入中的点定义了类似的分布。最后,t-SNE 最小化关于嵌入中点的位置的两个分布之间的 kull back-lei bler 散度。
算法
如前所述,t-SNE 采用高维数据集,并将其简化为保留大量原始信息的低维图。
假设我们有一个由 3 个不同的类组成的数据集。
我们希望将 2D 图简化为 1D 图,同时保持集群之间的清晰边界。
回想一下,简单地将数据投影到轴上并不是降维的好方法,因为我们丢失了大量的信息。
相反,我们可以使用降维技术(提示:t-SNE)来实现我们想要的。t-SNE 算法的第一步是测量一个点到其他所有点的距离。我们没有直接处理距离,而是将它们映射成概率分布。
在分布中,相对于当前点具有最小距离的点具有高可能性,而远离当前点的点具有非常低的可能性。
再看一下 2D 的图,注意蓝色的星团比绿色的更分散。如果我们不解决这种规模上的差异,绿点的可能性将大于蓝点。为了说明这一事实,我们除以可能性的总和。
因此,尽管两点之间的绝对距离不同,但它们被认为是相似的。
让我们试着将这些概念与基本理论联系起来。从数学上讲,我们将正态分布的方程写成如下。
如果我们抛开指数之前的一切,用另一个点代替平均值,在解决之前讨论的比例问题的同时,我们得到了来自论文的等式。
接下来,让我们来解决我们如何得出减少的特征空间。首先,我们创建一个n_samples
x n_components
矩阵(在本例中为:9x1)并用随机值(即位置)填充它。
如果我们采用与上面类似的方法(测量点之间的距离并将它们映射到概率分布),我们会得到下面的等式。
请注意,像以前一样,我们采用正态分布的方程,去掉前面的所有内容,使用另一个点代替平均值,并通过除以所有其他点的可能性之和来说明规模(不要问我为什么我们去掉了标准偏差)。
如果我们能想出一些办法,使缩减的特征空间中的点的概率分布接近原始特征空间中的点的概率分布,我们就能得到定义良好的聚类。
为了做到这一点,我们利用了一种叫做库尔贝克-莱伯散度的东西。KL 散度是衡量一个概率分布与另一个概率分布的差异程度。
KL 散度值越低,两个分布就越接近。0 的 KL 散度意味着所讨论的两个分布是相同的。
这应该有望带来大量的想法。回想一下,在线性回归的情况下,我们如何通过使用梯度下降来最小化成本函数(即均方误差)来确定最佳拟合线。在 t-SNE 中,我们使用梯度下降来最小化所有数据点上的 Kullback-Leiber 散度之和。
为了给出每次更新的方向,我们对每个点的成本函数取偏导数。
Python 代码
很多时候,我们利用了一些库,但并没有真正理解库下发生了什么。在下一节中,我将尝试(尽管不成功)用 Python 代码实现算法和相关的数学方程。为了帮助这个过程,我从scikit-learn
库中的TSNE
类的源代码中提取了一些片段。
首先,我们将导入以下库并设置一些属性,这些属性将在我们绘制数据时发挥作用。
import numpy as np
from sklearn.datasets import load_digits
from scipy.spatial.distance import pdist
from sklearn.manifold.t_sne import _joint_probabilities
from scipy import linalg
from sklearn.metrics import pairwise_distances
from scipy.spatial.distance import squareform
from sklearn.manifold import TSNE
from matplotlib import pyplot as plt
import seaborn as sns
sns.set(rc={'figure.figsize':(11.7,8.27)})
palette = sns.color_palette("bright", 10)
对于这个例子,我们将使用手绘数字。scikit-learn
库提供了将它们导入我们程序的方法。
X, y = load_digits(return_X_y=True)
鉴于 t-SNE 严格用于可视化,我们只能看到最多 3 维的事物,我们将选择 2 或 3 作为组件的数量。另一方面,困惑与算法中使用的最近邻的数量有关。不同的困惑会导致最终结果的剧烈变化。在我们的例子中,我们将其设置为 t-SNE 的scitkit-learn
实现的默认值(30)。根据numpy
文档,机器ε是最小的可表示正数,因此1.0 + eps != 1.0
。换句话说,任何低于机器ε的数字都不能被计算机操纵,因为它缺少必要的位。正如我们将看到的,贡献者使用np.maximum
来检查矩阵中的值是否小于机器ε,如果它们是,就替换它们。我不明白这背后的原因,所以如果有人能留下评论解释原因,我将不胜感激。
MACHINE_EPSILON = np.finfo(np.double).eps
n_components = 2
perplexity = 30
接下来,我们定义fit
函数。当我们转换数据时,我们将调用fit
函数。
def fit(X):
n_samples = X.shape[0]
# Compute euclidean distance
distances = pairwise_distances(X, metric='euclidean', squared=True)
# Compute joint probabilities p_ij from distances.
P = _joint_probabilities(distances=distances, desired_perplexity=perplexity, verbose=False)
# The embedding is initialized with iid samples from Gaussians with standard deviation 1e-4.
X_embedded = 1e-4 * np.random.mtrand._rand.randn(n_samples, n_components).astype(np.float32)
# degrees_of_freedom = n_components - 1 comes from
# "Learning a Parametric Embedding by Preserving Local Structure"
# Laurens van der Maaten, 2009.
degrees_of_freedom = max(n_components - 1, 1)
return _tsne(P, degrees_of_freedom, n_samples, X_embedded=X_embedded)
这个函数中发生了很多事情,所以让我们一步一步地分解它。
1.我们将样本数存储在一个变量中,以备将来参考。
2.我们计算每个数据点之间的欧几里德距离。这对应于前面等式中的||xi — xj||^2
。
3.我们将上一步中计算的欧几里德距离作为参数传递给_join_probabilities
函数,然后该函数计算并返回一个p_ji
值的矩阵(使用相同的等式)。
4.我们使用从标准偏差为 1e-4 的高斯分布中随机选择的值来创建缩减的特征空间。
5.我们定义了degrees_of_freedom
。源代码中有一个注释,告诉你去看看这篇解释他们推理的论文。基本上,经验表明,当我们使用组件数减 1 时,我们会得到更好的结果(粗体)。
Trustworthiness T(12) of low-dimensional representations of the MNIST dataset, the characters dataset, and the 20 newsgroups dataset.
6.最后,我们调用 tsne 函数,其实现如下。
def _tsne(P, degrees_of_freedom, n_samples, X_embedded):params = X_embedded.ravel()
obj_func = _kl_divergence
params = _gradient_descent(obj_func, params, [P, degrees_of_freedom, n_samples, n_components])
X_embedded = params.reshape(n_samples, n_components)return X_embedded
这个函数并没有太多的内容。首先,我们使用 np.ravel 将向量展平成一个一维数组。
>>> x = np.array([[1, 2, 3], [4, 5, 6]])
>>> np.ravel(x)array([1, 2, 3, 4, 5, 6])
然后我们使用梯度下降来最小化 kl 散度。一旦完成,我们将嵌入改回 2D 数组并返回它。
接下来,让我们来看看有更多肉的东西。下面的代码块负责计算 kl 散度和梯度形式的误差。
def _kl_divergence(params, P, degrees_of_freedom, n_samples, n_components):
X_embedded = params.reshape(n_samples, n_components)
dist = pdist(X_embedded, "sqeuclidean")
dist /= degrees_of_freedom
dist += 1.
dist **= (degrees_of_freedom + 1.0) / -2.0
Q = np.maximum(dist / (2.0 * np.sum(dist)), MACHINE_EPSILON)
# Kullback-Leibler divergence of P and Q
kl_divergence = 2.0 * np.dot(P, np.log(np.maximum(P, MACHINE_EPSILON) / Q))
# Gradient: dC/dY
grad = np.ndarray((n_samples, n_components), dtype=params.dtype)
PQd = squareform((P - Q) * dist)
for i in range(n_samples):
grad[i] = np.dot(np.ravel(PQd[i], order='K'),
X_embedded[i] - X_embedded)
grad = grad.ravel()
c = 2.0 * (degrees_of_freedom + 1.0) / degrees_of_freedom
grad *= creturn kl_divergence, grad
同样,让我们一步一步地浏览代码。
1.第一部分计算低维图中点的概率分布。
作者实际上使用了上述方程的一个变体,其中包括自由度。
其中α表示学生 t 分布的自由度数量
2.我们计算 KL 散度(提示:每当你看到np.dot
就想 sum)。
3.我们计算梯度(偏导数)。dist
实际上是yi — yj
在:
同样,他们使用上述方程的一个变型,带有自由度。
其中α代表学生 t 分布的自由度数量
梯度下降函数通过最小化 KL 散度来更新嵌入中的值。当梯度范数低于阈值时,或者当我们达到最大迭代次数而没有取得任何进展时,我们会提前停止。
def _gradient_descent(obj_func, p0, args, it=0, n_iter=1000,
n_iter_check=1, n_iter_without_progress=300,
momentum=0.8, learning_rate=200.0, min_gain=0.01,
min_grad_norm=1e-7):
p = p0.copy().ravel()
update = np.zeros_like(p)
gains = np.ones_like(p)
error = np.finfo(np.float).max
best_error = np.finfo(np.float).max
best_iter = i = it
for i in range(it, n_iter):error, grad = obj_func(p, *args)grad_norm = linalg.norm(grad)inc = update * grad < 0.0
dec = np.invert(inc)
gains[inc] += 0.2
gains[dec] *= 0.8
np.clip(gains, min_gain, np.inf, out=gains)
grad *= gains
update = momentum * update - learning_rate * grad
p += updateprint("[t-SNE] Iteration %d: error = %.7f,"
" gradient norm = %.7f"
% (i + 1, error, grad_norm))
if error < best_error:
best_error = error
best_iter = i
elif i - best_iter > n_iter_without_progress:
break
if grad_norm <= min_grad_norm:
breakreturn p
如果你已经走了这么远,给自己一点鼓励。我们准备用我们的数据调用fit
函数。
X_embedded = fit(X)
正如我们所见,该模型在根据像素位置分离不同数字方面做得相当不错。
sns.scatterplot(X_embedded[:,0], X_embedded[:,1], hue=y, legend='full', palette=palette)
让我们使用 t-SNE 的scikit-learn
实现做同样的事情。
tsne = TSNE()X_embedded = tsne.fit_transform(X)
正如我们所看到的,该模型成功地获得了一个 64 维的数据集,并将其投影到一个 2 维空间中,使得相似的样本聚集在一起。
sns.scatterplot(X_embedded[:,0], X_embedded[:,1], hue=y, legend='full', palette=palette)
t5——探索迁移学习极限的模型
The T5 (Text-To-Text Transfer Transformer) model. The same model is used for a wide variety of tasks by treating all tasks uniformly as taking some input text and outputting some text where the task type is embedded as descriptors in the input(see bold text in the input on the left above). This approach enables a single model to perform a wide variety of supervised tasks such as translation, classification, Q&A, summarization and even regression (e.g. outputting a similarity score between two sentences in the range 1–5. This in reality quite similar to a 21 class classification problem as explained below). The model is first pretrained unsupervised (masked objective like BERT) on a large corpus before supervised training with input text representing all these tasks and the associated labeled data which is also text (where specific tokens in the input stream “translate English to French” or “stsb sentence 1:… sentence2”, “question”/”context” etc. encode the task type as shown in figure above and the model is trained to output text matching the labeled data). With this approach of specifying input and output for supervised learning, the model shares its loss function, decoder etc. across all the disparate tasks.
TL;速度三角形定位法(dead reckoning)
T5 模型通过将不同的任务编码为输入流中的文本指令,以统一的方式处理多种多样的多对多和多对一 NLP 任务。这使得单个模型能够在多种 NLP 任务的监督下进行训练,例如翻译、分类、问答、摘要甚至回归*(尽管实际上它类似于分类)*。
这项工作的主要贡献与其说是模型*(这种编码文本的形式有先例——*【gp T2 使用了相同的想法 【除非在无监督的上下文中,假设它不能完成分类,或者 T5 可以完成的标记问题,给定它的监督学习阶段),即使它是 Q & A、摘要等的当前技术状态。,当与规模相结合时。
本文的主要贡献是通过使用 T5 模型的研究结果
- 从纯无监督的预训练到有监督的任务,检查与大规模利用迁移学习相关的因素
在这个过程中,语言理解的迁移学习的一些限制*(在人类的水平)*对于一些任务也在一些任务的性能度量中显现出来。虽然本文将解决这些限制留给了未来的研究,但已经有工作在进行中,以扩展语言理解,不仅仅是文本 ( )例如,基础语言理解- Yoshua Bengio *)。*这些新方法直接从文本着手解决当前迁移学习方法的一些基本问题——样本效率、常识理解、因果推理等。
论文中的主要观点
- 本文主要只关注基于变压器的模型*(相对于基于 RNN 的序列模型)。基于编码器-解码器的转换器架构最适合 T5 模型中使用的文本到文本方法。通过在编码器和解码器之间共享参数,参数计数保持与仅编码器模型(如 BERT)相同,而性能不会大幅下降(本文中报告的测试是在没有共享参数的情况下完成的)*。
- 掩蔽目标*(去噪)*与 BERT *中使用的相同(以及其变体,如掩蔽跨度)*的性能优于语言建模目标。
- 预训练最好在大型和多样化的数据集上进行,而不是在小型数据集上进行*(特别是如果数据在预训练中多次出现,这在大型数据集的情况下不是问题)。*此外,对域内数据进行预训练有助于提高下游任务的性能。
- 在微调期间更新预训练模型的所有参数比只更新几个参数产生了更好的性能,尽管计算成本*(见下面的最终想法)*。
- 通过在更多数据上训练模型、训练更大的模型或使用一组方法来进行扩展,所有这些都提高了性能。
- 仅在英语上的预训练方法在翻译(到法语、德语和罗马尼亚语)上没有产生艺术状态的结果;见下图)——暗示这不是一种语言不可知的方法。
- 通过使用掩蔽*(去噪)进行预训练以在下游任务中使用提取的知识的知识提取能力似乎受到模型仅从预测文本的损坏范围中学习的内容的约束。这一发现表明,正如前面提到的,学习方法不仅仅局限于文本(例如,基础语言理解)*。
其他详细信息
- 该模型的初始版本仅支持在 TPU 上运行。此链接介绍了设置虚拟机和 TPU 节点的步骤。请注意按照安装说明中的使用正确的 Tensorflow 版本启动 TPU 节点,以避免错误。
- 使用“小”模型解码输入完成的测试的完整结果如下所示(参见 Github 页面 中的 解码部分的说明)。它也有预先训练好的不同尺寸的模型来进行测试。由于更大的内存需求,我无法让基本型号和大型型号正常工作)。一个 Winograd 模式(WSC)样式测试没有产生论文中报告的结果—不确定问题是什么。(更新。11 月 6 日。T5 论文中的一位通讯作者**Colin Raffel【除了指出几处更正之外】优雅地澄清了这个问题。我做的测试和报告都是基于多任务混合训练的模型——对编码不同任务的句子进行监督训练。论文中报告的结果是在模型上进行的测试,这些模型针对特定任务进行了进一步的优化。作者怀疑 WSC 任务可能需要微调——它可能不仅仅适用于预训练的多任务混合,尤其是“小模型”。因此,为了在新领域的特定任务中获得最佳结果,我们首先在该领域的大型语料库中进行无监督训练。然后对输入句子中的多任务混合编码任务进行预训练。最后针对特定任务进行微调,以获得该任务的最佳性能)**
- 这种文本到文本的方法带来的一个挑战是模型可能不输出它在测试阶段期望输出的单词之一。例如,在上面所示的“可乐测试”*(测试句子语法是否可接受)*中,可以想象模型可以输出除“选择 1”或“选择 2”之外的字符串。作者声称这种情况将被视为测试失败,尽管他们没有观察到这种情况。此外,该模型可以为相同的输入产生不同的输出,这在摘要中是显而易见的。
- 最后,现实中回归模型的使用非常类似于分类问题。与输出可以是连续值的真正回归模型不同,该模型仅被定型为预测 1-5 范围内以. 2 为增量的值。这与值 0 一起产生 21 个值,这实质上是一个 21 类分类问题。
最后的想法
虽然在较大数据集上训练的较大模型继续提高了一些标准 NLP 任务的性能,但在大型语料库上预训练的通用知识提取似乎仍然没有在像 Winograd Schema challenge (WSC)这样的任务中带来接近人类水平(100%)的性能。似乎至少有两种不同的方法来解决这个问题。
- 第一种方法是继续增加 T5 论文和其他相关工作所建议的规模和训练策略,例如通过不用替代物(由生成器网络输出)替换标记来改变掩蔽词的当前预训练程序,并让鉴别器预测替换。然而,所有这些方法仍然通过在单词空间中进行预测来学习。
- 尝试预测下一个记号的完全不同的方法,不是在单词的空间,而是在抽象表示的转换空间。这是非常早期的研究,它解决了当前空间预测模型难以克服的一系列挑战——需要大量训练数据*(样本效率低下),无法像 WSC 这样的任务那样进行常识和因果推理。相对于在单词空间(或在图像-像素空间的情况下)中进行预测,在抽象表示空间中进行预测的目标是,通过这样做,模型可以学习潜在的因果变量,除了用这些变量进行推理之外,还能够适应潜在分布的变化(因果结构仍然保持不变)*需要很少的新训练样本,这是迁移学习的关键目标之一。
这篇文章是从 Quorahttps://qr.ae/TWPZq5手动导入的
机器学习和深度学习综述
机器学习和深度学习之旅
机器学习和深度学习模型和算法的映射和总结
这一系列博客将涵盖机器学习和深度学习从理论到实践的主题。目前市场上有许多优秀的教科书,包括模式识别和机器学习,统计学习的元素,深度学习等。然而,似乎那些作者喜欢直接跳到一个算法的结论,而跳过一步一步的解释和说明。因此,对于大一新生来说,那些书不容易消化。还有,那些书没有涉及如何在 R 或 Python 等统计软件中实现算法。我认为要很好的掌握统计模型和算法,理论和数学很重要,实现也很重要。因此,我想在理论和实践之间架起一座桥梁。
经过多年的学习,我认为所有这些方法都是相互联系的,而不是孤立的。当一个传统的方法显示出一些局限性时,那么一个新的方法就被引入来弥补这个局限性,从而进行改进。比如传统的线性回归很难处理多重共线性,于是发明了 LASSO 和岭回归来解决这个问题。另一个例子是引入装袋和增压来提高单棵树模型稳定性和准确性。如今,你也可以看到越来越多的方法涉及到不同领域的知识。将时间序列中的移动平均的思想应用于深度学习中的梯度下降中,以获得更快的收敛并减少振荡,这被称为带动量的梯度下降。因此,首先我想在这个博客中展示方法论之间的关系,然后我想写另外的博客来分别解释每个主题。你可以点击链接阅读你感兴趣的话题。
这个博客会不时更新,将来会增加更多的内容。
1。深度学习:
上图显示了传统统计模型和深度学习模型之间的关系。绿色的术语是用于生成相应模型的算法。
在深入研究神经网络(如 ANN、CNN 或 RNN)之前,让我们从单层神经网络开始我们的旅程。单层神经网络的思想是首先对输入变量进行加权线性组合,然后应用激活函数进行非线性变换。经典的单层神经网络包括逻辑回归和感知器。逻辑回归和感知器的区别在于,逻辑回归使用 sigmoid 函数作为激活函数,而感知器使用符号函数。
关于逻辑回归,请阅读我的博客:
逻辑回归从理论到实践的深度探讨
towardsdatascience.com](/an-introduction-to-logistic-regression-8136ad65da2e)
对于感知器算法,请阅读我的博客:
本博客将涵盖以下问题和主题
medium.com](https://medium.com/@songyangdetang_41589/an-introduction-to-perceptron-algorithm-40f2ab4e2099)
逻辑回归和感知器都使用梯度下降来获得最终模型。对于梯度下降,请阅读我的博客:
本博客将涵盖以下问题和主题:
towardsdatascience.com](/an-introduction-to-gradient-descent-c9cca5739307)
逻辑回归和感知器的限制是这两个模型的决策边界只能是线性的。当我们有一个更复杂的分类问题时,如下图所示,我们可能会期望一个更先进的方法,所以神经网络被引入。
如果你想用简单的数字建立一个神经网络,并更深入地理解这种奇特的算法,请阅读我的博客:
使用 Numpy 实现正向传播和反向传播
medium.com](https://medium.com/@songyangdetang_41589/build-up-a-neural-network-with-python-7faea4561b31)
2。线性回归
经典线性回归提供了另一个引入机器学习的完美角度。普通最小二乘法(OLS)用于估计线性模型的系数。然而,线性模型需要遵循几个假设,这些假设对模型的成功和预测的准确性至关重要。上表显示了假设、测试方法和每个假设的解决方案。
3。贝叶斯统计
贝叶斯统计在机器学习中也起着重要的作用。贝叶斯统计的一个范例是朴素贝叶斯分类器,它可以简单快速地训练。贝叶斯统计也用于无监督学习,如高斯混合模型(GMM)。贝叶斯公式如下所示:
公式中, p(y|x) 为后验概率; p(x|y) 是似然性; p(y) 是先验概率 p(x) 是证据。
对于朴素贝叶斯分类器,请阅读我的博客:
从理论到实践,学习感知机的基本原理
medium.com](https://medium.com/@songyangdetang_41589/introduction-to-na%C3%AFve-bayes-classifier-fa59e3e24aaf)
在频数统计中,分布的参数是一个确定的数,最大似然估计(MLE)用于进行估计;在贝叶斯统计中,分布的参数也是一个随机变量,而是使用最大后验概率(MAP)。MLE 和 MAP 的对比见博客:
最大似然估计(MLE)和最大后验概率(MAP)都被用来估计模型中的一些变量
medium.com](https://medium.com/@songyangdetang_41589/mle-vs-map-a989f423ae5c)
4。基于树的模型
让我们从线性模型转移到非线性模型。非线性模型的一个范例是决策树。决策树是一种基于树的算法,用于解决回归和分类问题。回归树用于具有连续值的因变量,分类树用于具有分类值的因变量。树与更经典的方法(如线性回归或逻辑回归模型)有着非常不同的味道。
特别是,线性回归假设模型的形式为:
而回归树假设模型的形式为:
其中 R1,…,Rm 表示特征空间的一个划分和 Cm: 的表达式
哪款比较好?根据没有免费的午餐定理,没有一个模型能对所有可能的情况都适用。因此,我们选择的方法取决于手头的问题。如果真正的决策边界是线性的,如顶部的两个图(下图)所示。线性模型将优于树模型。同时,如果真正的决策边界是矩形的,如下面的两个图所示。树模型比线性模型更能拟合数据。除了拟合度之外,为了可解释性和可视化,树模型是优选的。
Figures Source: Gareth James, Daniela Witten, Trevor Hastie, Robert Tibshirani, 2017, An Introduction to Statistical Learning
可以在博客中看到决策树的详细信息:
决策树背后的数学原理及其 Python 实现
medium.com](https://medium.com/@songyangdetang_41589/how-decision-tree-model-works-ce681cae10a6)
我的 Github 链接:
在 GitHub 上注册您自己的个人资料,这是托管代码、管理项目和构建软件的最佳地方
github.com](https://github.com/sytangtang1991)
参考
[1]伊恩·古德费勒,约舒阿·本吉奥,亚伦·库维尔,(2017) 深度学习
[2] Gareth James,Daniela Witten,Trevor Hastie,Robert Tibshirani,(2017) 统计学习介绍
[3] Christopher M. Bishop,(2009),模式识别和机器学习
[4]特雷弗·哈斯蒂,罗伯特·蒂布拉尼,杰罗姆·弗里德曼,(2008),统计学习的要素
六分钟内完成基本画面
了解商业智能、数据可视化和仪表板创建的 Tableau
New Belgium Beer Ratings in Tableau
商业智能软件帮助组织做出更好的决策。通过提供良好的可视化仪表板,它们可以更轻松地:
- 查看数据中的关系
- 讲一个清晰的故事
- 将重点放在重要的指标上
Tableau 和微软 Power BI 是数据可视化和商业智能软件领域的领先产品。Tableau 最近以 157 亿美元的价格卖给了 SalesForce】。显然,让公司更容易可视化他们的数据有很大的价值。😁
Tableau 很受欢迎。我之前对数据科学家最需要的技能的分析显示,Tableau 是数据科学家工作清单中第八大最常见的技术技能。
From my article
Tableau 是这个列表中最容易快速精通的技术——假设你已经了解 Excel。我建议你花一点时间在 Tableau 上,这样你就可以把它添加到你的工具箱和简历中。
有了 Tableau,你可以快速做出令人印象深刻的可视化效果。好玩又好用。😀
事不宜迟,让我们看看开始使用 Tableau 时需要知道的最重要的事情,以便为您的成功做好准备。我将用一个新比利时酿造啤酒评级的数据集来演示,这个数据集是我从啤酒倡导者那里搜集来的。🍺
关于 Tableau 要知道的 10 件事
- 几乎都是拖拖拉拉。您可能偶尔需要输入高级计算,但一般来说,只需拖放即可。🖱
Drag and drop
2.您在数据源选项卡中导入数据。拖放数据源以连接或联合它们。Tableau 拥有几乎所有你能想到的数据源的连接器。
Some Tableau Connector Options
3.你的大部分工作都在工作表中完成。每个工作表都在窗口底部的选项卡中,就像在电子表格程序中一样。
将变量从左侧数据栏拖动到工作表顶部的行和列字段和。
Dragging variables to Rows
视图是工作表的主要可视化区域。您也可以将变量拖到视图或标记卡上,以便它们显示在视图中。
4.Tableau 试图提供帮助。它根据列的内容推断数据的类型。它在每个变量名旁边提供了有用的小符号来表示数字、字符串、地理、布尔和日期数据类型。Tableau 将您的数据列拆分为维度和度量。
Dimensions and measures
维度是定性(分类)变量,包括字符串和日期。默认情况下,它们是离散的。离散变量是蓝色的。
度量是可以求和并求平均值的定量(数字)变量。默认情况下,它们是连续的。连续变量标为绿色。
默认情况下,Tableau 会假设您在任何时候使用度量值时都希望对它们求和。您可以通过右键单击该变量来更改聚合函数。
Changing the aggregation function
关于数据科学中离散变量和连续变量之间差异的更多讨论,请参见我的文章这里。有关 Tableau 中变量的更多讨论,请参见文档。
5.标记卡控制许多可视化方面。将变量从左侧栏拖到标记卡,以控制颜色、文本、工具提示等。在设置好行和列后使用它。
Make the size of the bars based on the number of ratings
6.有许多图表选项——Tableau 在右侧可展开的演示菜单中提供建议。建议基于工作表中使用的当前变量。
Show Me menu of visualizations
要知道,如果你点击一个图表选项,Tableau 可能会重新排列工作表中的变量。
7.格式可以更改。右键点击你想改变的,你会看到选项。在右键菜单中,你可以设置格式。
Format most anything with a right click
8.筛选数据就像将变量拖到筛选区域一样简单。右击药丸并选择显示过滤器创建一个交互式过滤器。
Filters are cool!
很圆滑,是吧?
9.右键点击一个变量,可以创建一个组、集合或计算字段。这些选项允许您对数据进行分组并找到更多见解。
Create more things!
10.您可以快速制作仪表板。只需将完成的工作表拖放到新的仪表板上。然后,查看者可以对您的图表进行排序和过滤,但他们不能破坏您的仪表板。😁
Dashboard at Tableau Public
你可以在 Tableau Public 这里玩我创建的仪表板,探索来自啤酒倡导者的新比利时啤酒评级。
你可以用我用来在 GitHub 刮收视率的 Python 代码克隆 Jupyter 笔记本。请注意,我排除了评级低于 300 的啤酒。
结论
Tableau 非常适合快速创建漂亮的可视化仪表盘。Tableau 不太适合机器学习。你可以得到一条趋势线,显示 R2。但其他任何事情都需要一些技巧。🤸🏾♂️
您可以免费使用 Tableau Public,但是使用私有数据创建数据可视化将需要 Tableau Desktop。截至 2019 年底,这将花费你每月 70 美元。这两款 Tableau 产品都是适用于 MacOS 和 Windows 的可下载程序。
建议大家下载 Tableau Public 玩玩。你可以通过拖放操作——以及随意使用撤销按钮。😉然而,知道自己在做什么并能够快速做出改变是很好的。希望这篇指南能激起你学习更多东西欲望。我第一次学习 Tableau 是和基里尔·叶列缅科的优秀 Udemy 课程: Tableau 10 A-Z 。写这篇文章的时候是 9.99 美元。
如果你想用 Python 制作类似的交互式可视化,我是 Plotly 的粉丝。我在这里写了一篇关于使用 Plotly 的介绍。不过,Tableau 要快得多。
我希望这个指南对你有用。如果你有,请在你最喜欢的社交媒体上分享,这样其他人也可以找到它。👍
我撰写关于 Python、Docker、数据科学和其他技术主题的文章。如果你对此感兴趣,请关注我,在这里阅读更多。
用餐愉快!
tableau+Python:tabby 和地理聚类
使用 K-means 聚类分析探索数据的简单方法。
Dashboard for clustering AirBNB
这是一个关于如何使用 Tableau 扩展在地图上进行 K-Means 聚类的简短教程。
TabPy 可以在这里下载或者,如果你使用 conda:
conda install-c anaconda tabby-server
关于如何安装和运行 tabpy server 的文章有很多,但是我个人遇到了两个问题:
- 权限错误:[WinError 5]访问被拒绝。在这里解决
- 无法使用 windows 批处理文件 startup.bat 运行 tabby server解决方法是安装 tornado-5.1。
正如我提到的,我的目标是测试 tabpy 功能,我选择了集群问题作为最常见的问题之一。K-Means 算法是一个很好的工具,可以在不做任何假设的情况下探索你的约会。关于 K-Means 有很多教程:有些是这里和这里。数据来源— 纽约市 Airbnb 房源 公布于 Tableau 公共资源。
该表由几个维度组成:
- 邮政编码
- 属性类型
- 邻近
- 房型等。
我用邮政编码来绘制地图。主要维度,大家可能会感兴趣:物业类型,主机自(时间维度)。
首先,我创建了两个控制参数来管理集群:
Tableau Control Parameters
聚类方法,顾名思义,就是负责一个聚类算法。
使用 SCRIPT_REAL 函数将脚本嵌入到计算字段中:
使用 tapby 的一个特点是,它将数据作为列表发送到服务器,因此需要将数据转换为 np.array 并在一列中整形。另一个技巧是删除所有具有 NAN 值的行,这在第 16 行完成。
_arg5 和 _arg6 对应管理参数。尽管它们是单个值,但它们也被打包到列表中,因此为了对 python 解包它们,应该使用 _arg5[0] 和 _arg6[0] 。
此外,有时算法不起作用,因为表格计算使用了错误的维度。在我的例子中,我使用了沿着邮政编码的计算。默认的表计算很少工作,所以每次在代码中查找错误之前检查这个选项。
Default Table Calculations
为了看看我们的聚类是否有意义,我添加了几个散点图来可视化潜在变量的联合分布:
- 平均值。价格与评论数量
- 平均值。价格与中值评审分数评级
- 审查数量与总数(床位)
Scatterplots of joint distribution
可以看出,聚类没有很好地定义,所以我们的简单模型和随机选取一样好,但至少它没有错误👌。
为了增加图形和地图之间的交互性,可以创建仪表板动作。我在仪表盘>动作中添加了悬停动作。
这是我第一次使用 TabPy,到目前为止,它的用处有限,但我希望 Tasbleau 将进一步发展它。
附言
此外,有时我会给电报(大部分是俄语)写一些关于资产管理的内容。
基于深度神经网络的表格数据分析
深度神经网络现在是用于表格数据分析的有效技术,与其他技术相比,需要较少的特征工程和较少的维护。
目前,在用于表格数据回归和分类任务的机器学习领域中,表现最好的技术被广泛认为是随机森林、梯度推进机器、K 近邻以及诸如支持向量机的较老技术,这些技术遭受维数灾难,最终开始较少使用。
对于大多数从业者来说,深度神经网络被视为对诸如计算机视觉、图像处理、语言处理/理解和信号处理等任务有用。
在过去几年中,使用深度神经网络进行表格数据回归和分类取得了巨大成功。对于著名的深度学习实践者,如杰瑞米·霍华德,90%的时间使用深度神经网络,通常随机森林或其他方法用于剩余的 10%。
深度神经网络对于对表格数据进行预测既可靠又有效。以前,一些从业者认为随机森林在 99%的情况下是表格数据分析的最佳技术。更多信息请看我关于随机森林的文章:https://medium . com/@ CDT _ 9051/Random-Forests-a-free-lunch-that-that-not-founded-662034 D4 BF 46
深度神经网络可用于表格数据分析的示例
深度神经网络模型可以被训练来执行许多表格数据分析任务:
- 欺诈检测
- 销售预测
- 产品故障预测
- 定价
- 信用风险
- 客户保持/流失
- 推荐系统
- 广告优化
- 反洗钱
- 简历筛选
- 销售优先级
- 呼叫中心路由
- 商店布局
- 商店位置优化
- 员工排班
(来源 Fast.ai 课程 v3)
对于上述一些用法,可能存在伦理问题,请参见本文后面的伦理注释。
例如,Pinterest 用神经网络取代了梯度推进机器,因为它们需要更少的特征工程,更准确,需要更少的维护。
特征工程
机器学习中的大多数当前想法是使用特征工程来预处理您的数据以移除特征,有时对从业者认为数据中的特征进行假设。人们习惯于经典统计学,习惯于去除参数。
当对表格数据使用深度神经网络时,仍然需要特征工程,尽管要少得多。所需的特征工程需要更少的维护。理想情况下,使用神经网络的表格数据分析功能不会被删除,所有的数据都可以保留和增加。
有些特征可能需要仔细检查,至于它们是否会造成歧视,请参见本文下面的伦理部分。
分类变量和连续变量
数据将包含分类变量和连续变量。连续变量是像年龄或体重这样的数字,它们在任意两个值之间有无限多个值。分类变量是那些从离散组中选择的变量,例如婚姻状况或狗的品种。
连续数据可以作为数字输入到神经网络中,就像将像素值输入到深度神经网络中一样。
特征预处理
训练深度神经网络不会自己完成所有需要的特征工程,这将发现特征之间的非线性和相互作用。
在基于图像的数据中使用变换的情况下,相反,在训练之前,使用预处理器预先处理表格数据一次。
这种预处理应该包括填充缺失的数据..对于连续数据,缺失值可以用数据集的中值代替。对于神经网络来说,知道该数据行缺少该特征也很重要。可以添加一个新要素来指示该行中该要素缺少的值,因为这本身就是有价值的信息。这可以防止缺失的特征值影响预测,同时仍然知道该行缺失某个要素的数据。
连续变量可以通过减去特征的平均值并除以特征的标准偏差进行归一化,从而得到介于 0 和 1 之间的值。这使得神经网络更容易训练。
应用于定型集的预处理必须以相同的方式应用于验证集和测试集。
分类变量的嵌入
对于每个分类变量,可以创建一组可训练的权重矩阵,分类变量中的每个类别/类都有一行。这些矩阵被称为嵌入。该嵌入矩阵乘以代表数据行的类别/类的一个热编码向量的结果然后被用作神经网络的输入。这些被训练成为每个分类变量中每个类别/类的一组偏差。
用于表格数据分析的深度神经网络架构
一个简单的完全连接的深度神经网络足以完成几乎所有的表格数据分析任务,例如下面概述的网络。
Neural Network architecture for Tabular data analysis, source Christopher Thomas.
输入层
对于输入层,除了来自每个分类变量嵌入矩阵的结果之外,输入是连续变量的数量。每个嵌入矩阵乘以每个分类变量中数据行的类的一个热编码向量,以形成输入的一部分。
对于复杂的表格数据分析任务,该层可能有 1,000 个输出激活。
矩阵乘法是线性函数。
在大多数情况下,非线性应该是整流线性单元(ReLU)或其变体之一。可以在非线性之后应用批量归一化,以避免过度拟合。
中间层
中间层将具有与来自最后一层的输出激活相同数量的输入,在输入层的示例中为 1000 个输入。对于复杂的表格数据分析任务,该层可能有 500 个输出激活。
同样,矩阵乘法是线性函数,非线性在大多数情况下应该是 ReLU,并且可以应用批量归一化。
在这个例子中,权重矩阵中有 500,000 个参数。为了防止过度拟合,可以应用下面描述的技术。
输出层
输出层将具有与最后一层的输出激活相同数量的输入,在本例中为 500 个输入。在大多数情况下,会有一个线性转换到一个输出,预测值。
过度拟合
过度拟合本质上是匹配特定的数据行,而不是该数据的特征。防止过度拟合是成功使用深度神经网络进行表格数据分析的关键。为了帮助防止过度拟合,可以应用以下技术:
- 重量衰减
- 拒绝传统社会的人
- 批量标准化
重量衰减
权重衰减通过每次更新权重来实现,权重乘以小于 1 的因子,通常在 0.01 和 0.1 之间。这可以防止训练过程中重量增长过大。
这项技术于 1992 年被 Anders Krogh 和 John A. Hertz 发现,是减少过拟合的最古老的神经网络泛化技术之一,他们的论文是:https://papers . nips . cc/paper/563-a-simple-weight-decay-can-improve-generalization . pdf
拒绝传统社会的人
对于培训中的每个小批量,可以随机移除(退出)激活。这可以防止对特定数据项的过度拟合。这是在 2014 年发现的,是减少神经网络中过拟合的最重要技术之一。
Nitish Srivastava, Geoffrey Hinton, Alex Krizhevsky, Ilya Sutskever and Ruslan Salakhutdinov. Source: http://jmlr.org/papers/volume15/srivastava14a.old/srivastava14a.pd
这显然是杰弗里·辛顿辍学的灵感来源:
“我去了我的银行。出纳员一直在变,我问其中一个为什么。他说他不知道,但是他们经常搬家。我想这一定是因为它需要员工之间的合作才能成功地欺骗银行。这让我意识到,随机移除每个例子中不同的神经元子集将防止共谋,从而减少过度拟合。”
丢弃技术也可以应用于来自嵌入矩阵的输入。
批量标准化
批量标准化显著降低了少量外围输入对训练模型产生过多影响的能力,从而减少了过度拟合。此外,批量标准化可以将训练时间增加一个数量级。
这是由 Sergey Ioffe,Christian Szegedy 在 2015 年发现的,是减少神经网络过拟合的最重要的技术之一。
[## 批量标准化:通过减少内部协变量转移加速深度网络训练
训练深度神经网络是复杂的,因为每层输入的分布在训练过程中会发生变化
arxiv.org](https://arxiv.org/abs/1502.03167)
数据扩充
除了上述缺失数据特征扩充之外,其他技术可以帮助发现隐藏在数据中的特征。
时间序列数据扩充
令人惊讶的是,使用具有时间序列数据的神经网络的现有技术结果并不使用递归神经网络(RNNs ),而是使用基于时间元素生成的特征。这使得大多数时间序列任务可以被视为常规的表格任务。
例如,对于给定的日期,可以从日期要素创建以下要素:
- 一周中的某一天(例如 6)
- 一个月中的第几天(例如 30 日)
- 一年中的某一天(例如 361)
- 周(例如 51)
- 月份(例如 10)
- 年份(如 2016 年)
- 是月初(真/假)
- 是月末(真/假)
- 是银行假日(真/假)
- 离下一个银行假日还有几天(例如 2 天)
- 自上次银行假日以来的天数(如 4 天)
- 黑色星期五(对/错)
- 离黑色星期五还有几天(例如 2)
- 自黑色星期五以来的天数(例如 4 天)
- 自 unix 纪元(如 18148 年)以来经过的时间
这使得基于某些周期性事件的行为能够被发现,例如在发薪日或临近银行假日时的变化。
这些特征中的许多可以被视为分类变量,并被嵌入的矩阵所替代。
其他增强
由于特征的数量不是训练深度神经网络的问题,所以可以结合其他数据集来发现新的见解,例如天气数据。
伦理学
深度学习和机器学习中的伦理是一个重要而有争议的问题,有许多不同的观点。在我看来,当使用深度神经网络时,从业者需要非常小心,避免只使用无法解释高成本决策的模型。还有一个额外的风险是,一些经过训练的神经网络模型的非技术消费者实际上更信任它,而不是他们理解的方法,因为他们认为算法已经在数据中发现了一些隐藏的复杂性。
在高成本决策中,如果一个可解释的模型是接近的或同样准确的,它将是一个更好的选择。刑事累犯案例是不可复制的重要案例。设计模型的从业者几乎总是不会因为模型的使用而遭受痛苦。
仅仅因为一个神经网络模型是可解释的,它就不一定是可解释的。
虽然使用深度神经网络进行表格数据分析的优势之一是可以保留所有特征,但需要注意那些可能产生歧视的特征,如种族和性别。收入和地点也可能无意中歧视群体。应删除可能具有歧视性或仅具有统计相关性的特征(超出相关个人或群体的控制范围)。例如,个人的父母离婚或之前有过不愉快关系的特征。
结论
使用这些技术可以快速准确地对表格数据进行预测。
例如,这种方法被用于罗斯曼商店销售数据竞赛的第三名https://www.kaggle.com/c/rossmann-store-sales/leaderboard,这里有对参赛者的采访:http://blog . ka ggle . com/2016/01/22/rossmann-Store-Sales-winners-interview-third-place-cheng-GUI/
在 NVidia K80 GPU 等典型的 GPU 上,训练一个深度神经网络可以在几个小时内完成,我的实验中,我训练的模型可以让我在一个迟到的提交中进入前 10 名。
在今年早些时候的 PUBG 完成位置 Kaggle 数据比赛中,我自己应用了这些技术,这意味着我在比赛中获得了第 6 名,尽管后来在排名中有所下降。精确度比应用随机森林高三倍以上。
最好对您的数据尝试随机森林和神经网络,看看哪一个表现最好,然后在两者上微调您的超参数,看看哪一个改进和表现更好。
深度神经网络表格数据分析为什么没有更普及
阻碍实践者将深度神经网络用于表格数据的主要问题是缺乏易于使用的库。
通过使用 PyTorch 的 Fastai API,现在有了一个易于使用的表格学习器,它将创建一个表格神经网络模型来匹配您的数据。您的数据需要在 Pandas dataframe 中,这是 python 中表格数据的标准格式。Pandas dataframes 可以从许多数据存储中读取数据,包括 csv、关系数据库、Spark 和 Hadoop。
感谢杰瑞米·霍华德和 Fastai 课程,其中详细解释了这些技术,并且是我在本文中的知识和理解的关键来源。对于任何想了解更多的人来说,在 v3 Fastai 课程中,第 4 课和第 6 课应该会有兴趣。
用机器学习应对气候变化
如果这篇博文的标题看起来有些熟悉,很可能是因为你听说过或者读过这篇在今年 6 月发布的来源全面的论文。这篇论文概述了机器学习可以为减轻气候变化的影响提供有效解决方案的无数领域。虽然整篇论文值得总结(和阅读!),在这篇博文中,我将重点关注我感兴趣的两个特定领域:碳排放捕获/减少和气候预测。
碳排放捕获/减少
2018 年,政府间气候变化专门委员会(IPCC)估计,如果我们不限制并大幅减少全球温室气体排放,30 年内,世界将面临灾难性后果。尽管有国际协议,全球抗议,以及压倒性的科学共识,即如果我们要避免灾难,我们需要减少我们的排放,我们的全球排放量继续增加。如果政府不愿意尽可能快地采取行动减少排放,那么对碳捕获技术的投资就是必要的。虽然这项技术本身存在,但它仍处于起步阶段。但是机器学习可以以多种方式帮助这项新技术。
该文件概述了减少碳排放的三种选择。它还承认,尽管这些技术目前确实存在,但它们概述的应用,特别是与机器学习相关的应用,都是推测性的。
1)天然或半天然方法
虽然全球排放量逐年增加,但森林砍伐也火上浇油。世界上大约一半的热带森林已经被砍伐。更糟糕的是,据估计,每年砍伐森林的总面积为 1870 万英亩,相当于每分钟砍伐 27 个足球场大小的森林。总体而言,森林砍伐约占所有温室气体排放的 15%。
鉴于正在发生的所有森林砍伐,提供工具来帮助跟踪森林砍伐可以为决策者和执法人员提供有价值的数据。根据这篇论文,机器学习可以帮助“使用遥感图像区分选择性采伐和皆伐。”它还可以用来“探测半径一公里内的电锯声,并将其报告给附近的手机天线”,以提醒执法官员非法砍伐森林。
此外,重新造林有助于减少森林砍伐的影响。据估计,在现有的森林和废弃的土地上可以种植 1.2 万亿棵树。ML 可用于帮助定位合适的种植地点、监控植物健康状况、评估杂草以及进一步分析趋势。
2)直接空气捕获(DAC)
直接空气捕获是一种从发电厂废气、工业过程或环境空气中提取 CO2 的技术。通过将空气吹到吸附剂(基本上是海绵)上来提取二氧化碳,然后使用热力化学过程以纯化的形式释放二氧化碳进行封存。下图概述了这一过程。
机器学习可以在许多方面帮助提高效率。根据该论文,它可以用于“加速材料发现过程,以最大限度地提高吸附剂的可重复使用性和 CO2 吸收量,同时最大限度地减少 CO2 释放所需的热量。”它还可以帮助开发“能够承受高温的耐腐蚀部件,以及优化它们与空气吸附剂接触的几何形状。”
3)封存二氧化碳
除非永久储存,否则任何捕获的二氧化碳都将不可避免地释放回大气中。因此,捕获的 CO2 必须被隔离。目前最好的方法是直接注入地质构造,如盐水层(类似于石油和天然气储层),并隔离在火山玄武岩构造中。那么 ML 在这里起什么作用呢?就像石油和天然气公司利用 ML 进行基于地震仪轨迹的地下成像以寻找提取点一样,ML 可用于帮助识别潜在的储存位置。石油和天然气公司使用的模型可以重新用于帮助捕获和注入,而不是提取。此外,ML 可用于监测和维护封存地点,尤其是用于 CO2 泄漏和总体排放检测。这个过程是通过使用传感器测量来完成的,这些测量“必须转化为关于地下 CO2 流量和剩余注入能力的推断。”“在全球二氧化碳储存模拟中使用卷积图像到图像回归技术进行不确定性量化”也取得了成功
气候预测
当前的气候预测模型用于为地方和国家政府决策提供信息,帮助个人计算他们的风险和足迹,并估计我们的排放物的潜在影响。机器学习有助于提高更准确地模拟这些预测的能力。这些进步很大程度上源于数据的可用性。虽然更多的数据并不总是等同于更准确的模型,但从全球更多地区获得更多的同类数据有助于提高准确性。例如,根据这篇论文,“更新更便宜的卫星正在产生数十亿字节的气候观测数据。”基于这些信息的模型还会生成数十亿字节的模拟气候数据,因此这些模型往往会相互依赖。最后,这些预测在计算上是昂贵和耗时的。因此,气候科学家已经开始使用 ML 技术来解决这些问题。
1)将数据、ML 和气候科学结合起来
为什么气候科学家越来越依赖机器学习模型?根据这篇论文,这些模型“可能比其他模型更准确或更便宜,因为:1)有丰富的数据,但很难用传统的统计方法对系统进行建模,或者 2)有好的模型,但它们在生产中使用的计算成本太高。”
ML 模型已经在气候科学家中用于各种目的。它们已被用于校准卫星传感器、对作物覆盖进行分类以及识别污染源。也有人提出深度学习可以用于“模式识别、超分辨率和气候模型中的短期预测”,以及汇编环境图像的数据,以进一步加速该领域的 ML 工作。
此外,深度神经网络,结合现有的热力学知识和以前收集的数据,可以用来模拟气候模型中一些最大的不确定性来源:云,冰盖和海平面上升。明亮的云反射光线并帮助冷却地球,而乌云吸收光线并保持地球温暖。这些过程的物理模型和预测它们随着气候变化的最终影响在计算上过于昂贵,无法包括在全球气候模型中,但机器学习模型不是。根据这篇论文,“Gentine 等人训练了一个深度神经网络来模拟高分辨率云模拟的行为,并发现该网络以一小部分成本给出了类似的结果,并且在简化的全球模型中是稳定的。”
由于各种原因,冰盖和海平面上升很难建模。最大的问题是收集数据。因为这些地区是孤立的,黑暗的,寒冷的,它们很难被观察到,因此很难收集数据。然而,在过去的几年里,新的卫星活动使我们能够收集这些地区的万亿字节的数据。然而,最大的问题是准确模拟这些冰盖的质量损失及其对海平面上升的影响。这些模型中最大的改进领域涉及雪和海冰的反射率,因为大部分太阳光被这些冰层反射,热量没有被吸收。随着这些冰原融化,地球将吸收热量并继续融化冰原,从而导致海平面更大的上升。
2)预测极端事件
天气模型比气候模型更容易制作,也更精确。由于天气模型跟踪大气中的快速变化,并且有大量信息可用于预测这些变化将产生的影响,因此模型每天都要进行测试和更新,以准确预测短期天气状况。然而,精确的气候模型要难得多。它们只能通过长期观察来检验,任何超过一周的时间都很难预测。此外,用于预测的所有可用数据集都严重倾斜,因为极端事件很少发生,而且历史数据严重缺乏。虽然目前的气候模型可以帮助预测长期趋势的变化,但这些模型的准确性需要大大提高。
机器学习已经被成功地用于对一些极端天气事件进行分类。深度卷积神经网络已被用于计算过去气候数据集中的气旋和天气锋,一些技术已被用于跟踪风暴和龙卷风。此外,最大似然法还被广泛用于本地天气模型预测。“许多作者已经使用支持向量机、自动编码器、贝叶斯深度学习和超分辨率卷积神经网络进行了尝试。”这些模型已经被用于预测不同地区的洪水模式。随着越来越多的数据可用,长期气候预测的准确性有望提高。
结论
虽然整篇文章都值得一读,但这篇文章特别关注了两个部分:碳捕获和气候预测。机器学习可以像石油和天然气公司一样用于寻找注入点和监控封存的二氧化碳。至于气候预测,随着更多数据的可用,ML 可以得到更好的利用,并用于更好地模拟冰盖融化和海平面上升将带来的不确定性。
用 NLP 解决增长问题
业务增长伴随着一系列挑战。
Photo by Everaldo Coelho on Unsplash
在这个例子中,创建了一组业务规则和一个 NLP ( 自然语言处理)模型来自动回答客户的退货请求。特殊性,我将侧重于 NLP 方面。Tf-idf 用于解析客户注释,以允许或停止对客户退货请求的自动回复。
TLDR
为了解决退货请求增加的问题,我们使用了监督机器学习(NLP) 工具来进一步增加自动回复的数量,从而提高生产率并减少回复时间。
现状
每个零售企业都必须处理退货。与应用过程相关的关键方面与问题的维度有关。如果退货数量很少,也许可以通过在 Excel 电子表格上登记退货并手动回复客户来解决。另一方面,如果返回请求的数量超过了一个控制良好的流程的人工阈值,就必须应用一些自动化。
在我们公司,我们有后者。在没有额外措施来降低回报的情况下,业务增长使得问题更加严重。自 2015 年以来,退货请求的数量翻了一番,显然这是我们未来必须应对的趋势。事情需要改变。
Return requests by year and month
有一段时间,人们更多地关注这项任务,让其他任务退出,从而解决了这个问题。
第二步是创建一组业务规则(自动应答管道),可以解决所有不需要特殊处理的退货请求(经常销售、无损坏或无保修的商品)。这一步骤使我们能够在 2018 年底之前解决很大一部分退货请求。但是,我们开始触及一个平台,再次,新的步骤需要做。
Return answers by type
为客户退货单开发 NLP
在 2019 年初,我们注意到我们无法增加通过自动管道运行的请求数量。
分析发生这种情况的原因,每当客户在退货请求中添加备注时,管道就会停止。我们收到了大约 40%的带有备注的退货请求:
Percentage of return requests with notes on them
当然,其中一些纸币对自动流水线完全无害。像“我请求零件时犯了一个错误”或者“零件不是我想要的”或者甚至“你错误地将零件分类,给我的是左边的而不是右边的”。
这是第三步的开始:向客户退货单引入 NLP,以便可以触发或不触发管道。
这是一个简单的“情绪分析”问题。客户注释阻止了管道(0)或允许了管道(1)。
关于 TF-IDF 的 NLP 的一点背景
TF–IDF 代表词频–逆文档频率。
来自维基百科,是一个数字统计,旨在反映一个单词对集合或语料库中的文档有多重要。在信息检索、文本挖掘和用户建模的搜索中,它经常被用作加权因子。TF–IDF 值与单词在文档中出现的次数成比例增加,并由语料库中包含该单词的文档数抵消,这有助于调整某些单词通常更频繁出现的事实。TF–IDF 是当今最流行的术语加权方案之一;数字图书馆中 83%的基于文本的推荐系统使用 TF–IDF。
TF–IDF 加权方案的变体通常被搜索引擎用作在给定用户查询的情况下对文档的相关性进行评分和排名的核心工具。TF–IDF 可以成功用于各种主题领域的停用词过滤,包括文本摘要和分类。
这是一个重量计算公式:
处理数据
至于任何有监督的机器学习,我们需要为客户笔记贴上标签。
我们已经开始标记大量的客户笔记,时刻意识到平衡分类的重要性。我们可以很容易地用标签 1(允许自动流水线)对更多的笔记进行分类,但这将使训练和测试数据更加偏向一边。
在 5000 张贴有标签的笔记中,我们知道这有点不平衡,但我们可以接受:
然后,我们在训练和测试中分割数据:
并在我们的业务领域词典中增加了葡萄牙语词典中的停用词:
培训和测试
下一步是在分类器中加入所有准备工作,并拟合模型:
并使用测试数据来评估模型:
不错,93.4%的准确率和 94.1%的 F1 分。
分析混淆矩阵,大多数笔记被正确分类,其中 156 被分类为停止流水线但不需要停止(类型 1 错误),124 被分类为不停止但应该停止(类型 2 错误)。对于我们的业务领域,类型 2 的错误是最糟糕的,对于未来的工作,应该进一步处理。
总结
NLP 是提高任务自动化和解决日益复杂的业务流程的关键工具。对于未来的工作,可以采用其他方法(其中之一是 LSTM),甚至可以使用自动化的 ML 工具。
我希望我对我们正在应对的挑战和我们正在应用的解决方案有所了解。在接下来的几个月里,我们将继续进一步增加自动回答的数量,并再次提高效率和客户满意度,让人们专注于更多面向客户的任务。
我将把工作结果留给你:自 2018 年以来,我们使用机器学习将自动答案的数量增加了 20%以上。
Return answers by type
基于潜在狄利克雷分配的标签推荐算法
我们将用 python 开发一个 LDA 模型,根据用户的 StackOverflow 帖子向用户推荐标签
Word Cloud of tags in Stack Overflow
一般来说,LDA 用于对原始数据集进行降维,然后再应用其他机器学习算法,这些算法将受益于更少的维数。这里我们将把它用于另一个目的,即实现一个推荐系统。
资料组
我们的数据集来自 stackexchange explorer,要从网站导出帖子,您必须进行如下 SQL 查询:SELECT * FROM posts WHERE Id < 50000
默认情况下,每个 SQL 查询的执行时间都有时间限制,这使得很难一次恢复所有数据。要检索更多的结果,请记住使用对 id 的约束进行查询。
现在我们有了数据集,下一步是做一些文本预处理,也就是说:
- 使用美汤库移除 html 格式
- 降低文本
- 转换缩写
- 删除停用词
- 单词的词形变化——将单词的词形变化组合在一起
- 去掉动词和形容词,因为它们不能提供关于文章的有价值的信息
Pre-processing functions
TF-IDF
TF-IDF 是 Text Frequency-Inverse Document Frequency 的缩写,它旨在衡量一个术语在文档语料库中对一个文档的重要性。术语权重=术语频率×idf(术语)
definition of inverse document frequency
Converting training and test post to matrices of TF-IDF features
皱胃向左移
LDA (潜在狄利克雷分配)是一种基于以下假设的生成式非监督方法:
- 语料库中的每个文档都是一组没有顺序的单词(单词包)
- 每个文档以不同的比例涵盖了多个主题 p(θm)
- 每个单词都有一个与每个主题相关的分布 p(ϕk) 。因此,每个主题可以由每个单词的概率来表示
- zn 代表单词 wn 的主题
因为访问受限于文档,所以有必要确定什么是主题、每个词在主题上的分布、每个主题在语料库上出现的频率。
LDA representation in the form of a graphical probabilistic model
我们使用**sk learn . decomposition . latentdirichletallocation、**训练不同的 lda 模型,每个模型都有不同数量的主题,然后我们使用度量困惑度在测试集上评估不同的模型。
definition of perplexity
L( w )是看不见的文档 w 的对数似然;困惑度越低,模型越好。
lda algorithm
最低的困惑分数是针对 10 个主题的,所以我们将学习包含 10 个主题的 lda 模型。
推荐算法
现在我们有了模型,我们将研究推荐算法。它将基于两个要点,即:
- 得分=文档被分配给主题的概率×主题生成单词的概率
- 当一个单词的分数高于定义的阈值时,该单词被认为是相关标签
在尝试了阈值的不同值之后,我们选择了阈值 0.010 ,这是因为使用该值,测试集标签具有看起来像训练集标签的分布,并且还因为使用阈值等于 0.010,超过 90% 的帖子具有推荐标签。
Tags recommender using LDA
估价
我们将使用 Jaccard 评分来评估我们的模型,该评分用于将样本的预测标签集与相应的标签集进行比较。
Jaccard score definition
Jaccard score function
我们的 LDA 模型在测试集上的 Jaccard 得分是 3.98% ,而使用 OneVsRest 方法(简单基线)的哑分类器使得 0.90% 。这表明我们的 LDA 模型肯定比随机模型好,因为它已经成功地正确预测了一些标签,尽管事实上它是一个无监督的模型。但是为了有一个我们推荐系统正常运行的真正指标,我们必须对一些帖子,模型输出的标签与我们手动认为相关的所有标签进行比较。
例子
下面的两个例子表明,LDA 推荐器的性能取决于帖子的精确度和用户问题的详细程度。
Recommended tags for example 1
第一个例子是一个详细帖子的完美例子,所以对于基于无监督算法的推荐器来说,返回相关标签很简单,这里就是这种情况。帖子是关于 html/css 的问题,程序显示这 2 个标签。
Recommended tags for example 2
在这个例子(2)中,帖子很短,没有具体的细节来帮助程序推荐感兴趣的标签。这里唯一推荐的标签是*‘table’*,不能真正认为是相关标签。
如果你想有更多相关的标签,你必须给算法更多关于文章的信息,比如在你的程序中考虑文章的标题。
源代码可以在 Github 上找到。请随意分享你的想法和想法。
定制储蓄推荐器
Photo by Fahmi Fakhrudin on Unsplash
我们很可能每天都与推荐系统进行交互。无论是听 Spotify 推荐的歌曲,还是浏览亚马逊网站上的“顾客也购买了……”栏目,或者尽情享受网飞推荐的新电视节目,我们都在使用推荐系统。所以对于这个项目,我想,我如何利用它来节省一些钱?在这篇文章中,我将带您浏览我构建的原型,它根据用户的消费习惯提供量身定制的储蓄建议。这个项目的代码可以在我的 Github 上找到。
让我们以赤道咖啡为例,因为我在那里花了很多钱。赤道公司在旧金山有几个位置,离我的工作地点和家都很近。为了这个例子的目的,我们会说我在工作,准备喝咖啡休息。如果你在 Yelp 上搜索 Equator,它的价格水平是$美元,星级是 4.5,离我工作的地方大约一个半街区。
通常我会去赤道买一杯午后拿铁,但如果有另一家咖啡店,距离和质量都差不多,价格也更便宜,我可能会去那里,这样可以省钱。这个系统的建立是为了帮助我找到像这样的地方,在那里,习惯的轻微改变,可以随着时间的推移积累很多钱。在这个例子中,我的系统推荐了足够的茶和咖啡,它距离我的工作地点大约 2 个街区,星级为 4.5,价格只有$级,如下所示。
目标是:
我这个项目的目标是利用我的个人消费习惯来创建量身定制的储蓄建议,以最小的生活方式影响为我省钱。我仍然希望能够去喝咖啡,但希望能以更便宜的价格去做。
我想象这个推荐系统正在被一家银行使用。他们已经可以接触到你所有的信用卡交易,这是对你消费习惯最准确的描述。一家银行为你推荐与你经常消费的类似的更便宜的商家,可以把省下来的钱转到他们的储蓄账户上。
构建推荐器:
第一步:收集+清洁
构建我的推荐器的第一步是收集旧金山的商业数据。我使用旧金山市和县提供的注册企业位置数据集的子集作为企业列表。从这个业务列表中,我调用了 Google Places 和 Yelp Fusion APIs 来获取业务信息。我主要使用 Yelp Fusion API 数据,并使用 Google Places API 填充空值。
在组合了来自两个 API 的业务信息之后,我仍然有一些空的价格层值。我使用 k=5 最近邻的 KNN 插补来填充这些缺失的价格值。
我还收集了包含 4 个月信用卡交易历史的个人银行对账单。这些将被输入我的原型,作为推荐的基础。
第二步:评论+主题
接下来,我对商业 yelp 评论做了一些自然语言处理。在我的数据集中,每个企业都有一些评论,我把它们合并成一个段落。我首先对段落中的单词进行词条化,然后使用词频-逆文档频率(TF-IDF)进行矢量化。
TF-IDF 是确定一个单词对语料库中的文档有多重要的度量。换句话说,对于商业评论段落中的每个词,我想看看这个词在解释该商业相对于数据集中其他商业的重要性。例如,使用 TF-IDF,单词“food”可能不是一个权重很大的单词。虽然“food”可能经常出现在某个餐馆的评论中,但当数据集主要由餐馆组成时,这对于区分该业务没有太大的价值。另一方面,双字母“asian_food”将具有更高的权重,因为它是该业务与整个业务集的更好区分符。比较两个“亚洲食品”企业会比比较两个“食品”企业提供更多的价值,这两个“食品”企业最终可能完全不同,就像一家高级餐厅和一家廉价咖啡馆。
一旦我有了数据集中每个企业的 TF-IDF 向量,我就使用非负矩阵分解(NMF)进行主题建模。NMF 是一种将一个矩阵分解成两个不包含负元素的矩阵的方法,它在评论和推文等较短的文本上非常有效。我使用一个 scree 图来确定使用 NMF 生成的主题数量(15)。最后,我为我的数据集中的每个企业制作了主题向量,显示了每个主题与该企业的相关性。
第三步:比较+匹配
我现在有了一个数据框架,其中包含旧金山数千家企业的主题向量和其他属性。我的下一步是比较这些企业,寻找相似之处。我使用余弦相似度进行比较,使用每个企业的所有数字特征。余弦相似度查看 2 个企业的向量,并计算这些向量之间角度的余弦,其中相似企业的余弦相似度更接近 1。这给了我一个矩阵余弦相似性得分为每个企业相比,所有其他企业在数据框架。
为了找到对某个企业的推荐,我会首先选择余弦相似度最高的 25 个企业,然后根据匹配类别的数量和它们的哈弗线距离对它们进行加权。我的数据框架包含了来自 yelp 的每家企业的类别,比如“咖啡”、“咖啡馆”、“餐馆”等等。拥有更多与所访问的企业相匹配的类别的企业将更有可能被推荐。类似地,离被访问的企业更近的企业也更有可能被推荐。
第四步:提炼+推荐
我为这个原型使用了一个基于内容的推荐系统。这意味着推荐严格基于个人消费习惯和信用卡交易历史中出现的企业属性。
一旦我有了上一步的匹配列表,我就通过比较价格水平和等级来提炼这些匹配。我的建议将只针对具有同等或更高 yelp 评级以及更低 yelp 价格等级的地方。
最终想法:
为了将所有的东西整合在一起,我开发了一个 Flask 应用程序,它可以读取我过去 4 个月的信用卡交易历史,并提供消费汇总以及储蓄建议。
它首先提供了上传的银行对账单中每个月的 5 个类别的支出明细:食品、咖啡、零售、服务和酒吧/娱乐。右边的图表让我们可以很容易地看到每个类别的支出如何逐月波动。
应用程序的下一部分显示了每个类别中的业务细分,以及在上传的银行对账单的整个跨度内每个业务的支出。
最后,该应用程序根据我已经花钱的业务提供建议,并显示如果我转向这些推荐的业务,我每月和每年可以节省多少钱。我可以点击任何一个推荐,然后直接进入商业 Yelp 页面获取更多信息。
你可以通过下面的链接观看我的应用程序的演示。
drive.google.com](https://drive.google.com/file/d/1dKqGrO_3uEuxEP5yhweVmOlmCtNYqET7/view?usp=sharing)
我真的很喜欢这个项目,并熟悉自己的推荐系统。感谢阅读!
新闻和里程碑
最后更新于 2022 年 10 月
了解 TDS 的最新动态
Photo by Joanna Kosinska on Unsplash
2022
2022 年 9 月 13 日。在 TDS 上提炼作者经验。写一篇 TDS 级别的文章需要花费大量的时间和精力,所以让我们所有的投稿人感受到支持、欢迎和良好的导向对我们来说非常重要。为此,我们最近推出了一个新指南,帮助作者充分利用他们在 TDS 上的体验。它充满了资源和提示,所以我们希望你检查一下。
2022 年 9 月 6 日。我们喜欢和 TDS 作者交谈。我们刚刚与 Barry s myth 进行了一次生动的对话,以此庆祝我们的第 50 个作者聚焦专题。这是浏览我们 Q &深度档案的绝佳时机,因为有各种各样的数据专业人士:从 Cassie Kozykov 和 Sophia Yang 这样的行业领袖到 Eric J. Daza 和 Lowri Williams 这样的研究人员。
2022 年 8 月 29 日。生日快乐,中等! TDS 从第一天起就给 Medium home 打电话,所以纪念平台十周年特别令人激动。
感谢你的阅读、写作和分享。以下是我们第一个十年的一些亮点。
blog.medium.com](https://blog.medium.com/it-happened-on-medium-the-first-10-years-5d55c1e26c1d)
2021
2021 年 7 月 22 日。参与。如果你关心数据科学在为人类和社区建设一个公平、可持续的未来中的作用,我们最近创建了一个充满想法和建议的指南,以激励你采取行动。
2020
2020 年 11 月 28 日。走向数据科学拥有 50 万粉丝!🎉我们非常感谢所有定期加入我们的优秀读者和作家。在过去的几年里,我们一起成长了很多,我们很高兴成为最大的媒体出版物之一。非常感谢您的支持和参与,并加入我们的社区!
2020 年 10 月 20 日。我们刚刚选择了 Medium 的新测试版设计!它提供了我们认为对我们的读者和作者都有价值的新功能。我们确实丢失了我们的菜单(它很快就会回来),但是我们相信我们文章底部的推荐和我们作者在侧边栏上的介绍是非常有价值的。
2020 年 6 月 6 日。阅读我们的媒体出版物时你应该知道的。由于 TDS 在过去几年中发展如此之快,我们决定整理一份术语列表,向读者解释与数据科学的关系。如果您有任何问题,请告诉我们。
2020 年 2 月 26 日。 我们发布了多伦多机器学习峰会的第一个视频!我们希望你喜欢它。🎤
2020 年 1 月 2 日。我们改进了我们的外观和标识!经过三年多的时间,我们决定是时候让我们的出版物焕然一新了。您可以在我们的媒体出版物和社交媒体账户上找到我们的新标志。这些变化并不极端,但我们想让你知道🙂新年快乐!
2019
2019 年 11 月 25 日。**继续学习数据科学。**为了帮助你以适合你的速度学习,我们按照主题选择并组织了所有对你最有帮助的内容。我们希望这能给你一个类似于一些最好的在线课程的学习体验,但采用我们熟悉的数据科学风格。
Toronto Machine Learning Summit
2019 年 11 月 22 日。感谢大家来到多伦多机器学习峰会。我们度过了一段美好的时光,迫不及待地想开始为你们制作在线视频。
2019 年 11 月 5 日。如果你开始写关于数据科学或机器学习的文章,我们收集了一些可能对你有帮助的文章。从我们最好的作者那里获得灵感和探索建议。
2019 年 10 月。走向数据科学三岁了!这是一个奇妙的旅程,我们非常感激有这么多了不起的作家和读者加入我们。从一个致力于发表我们所能找到的最好的数据科学文章的小型出版物到最大的媒体出版物之一,您的支持和参与使这里成为一个令人难以置信的地方。我们迫不及待地想看到我们在接下来的三年里共同打造的东西!非常感谢你成为我们社区的一员。✨
2019 年 10 月 14 日。我们的团队在壮大。感谢 Anne Bonner 和 Amber Teng 加入编辑团队,感谢 mal、Tyler Folkman、Xin-Jou Lin、Jatin Bhasin、Luke Morris、Luca Belmonte、Pier Paolo Ippolito 和 Lester Leong 成为编辑助理。
2019 年 10 月 3 日。我们现在正致力于通过提供一些我们最好的文章的便捷的音频解说,让您的生活更加美好。我们选择的叙述性文章包括由我们的专业叙述者团队精心策划的内容。📖
2019 年 9 月 20 日。我们播客的第一季已经播出。攀登数据科学阶梯,与世界级公司的经验丰富的数据科学家进行对话,如 LinkedIn、脸书和 Airbnb。🎧
2019 年 9 月 13 日。我们的每周精选将很快被我们的每周文摘所取代。我们的文摘将为读者提供个性化的推荐,并将直接发送到您的收件箱。你可以通过我们的媒体出版物订阅。
Get inspired
2019 年 5 月 25 日。我们选择了三篇文章来激励你开始撰写关于数据科学和机器学习的文章。点击上面的图片可以重定向到我们的文章。
2018
Photo by Leone Venter on Unsplash
2018 年 12 月 13 日。 如何充分利用数据科学。我们已经收到反馈,你们中的一些人发现很难有效地浏览我们的媒体出版物。所以我们把几个要点放在一起,希望对你在我们博客上的体验有所帮助。📚
2018 年 10 月 15 日。感谢周宇、Andrew DeCotiis-Mauro、Rui Geng、Hamza Bendemra、Rohan Joseph、Juilien Hsu、Helen Ngo、查敏 Nalinda、Benjamin Cooley、Hessie Jones、Josh Fleming 以及今年作为编辑助理加入并帮助我们的其他人。
2018 年 5 月 5 日。我们新的关于我们的页面:“**我们于 2016 年 10 月加入 Medium 充满活力的社区。**一开始,我们的目标只是收集好的帖子,然后分发给更广泛的受众。仅仅几个月后,我们很高兴地看到,我们的受众增长非常快,并且有许多新的贡献者。”阅读更多
2017
2017 年 8 月 22 日。 Medium 推出了互联网的首个开放式付费墙。这种付费墙使创作者能够*“*从相信想法和创意值得付费的读者群体中赚钱”。
用你自己的方式讲述你的故事——用不同的方式来写作,塑造风格,给你的作品打上烙印。借助简单的工具和功能…
medium.com](https://medium.com/creators)
2017 年 3 月 11 日。我们先来看一下 每周精选 。在这里,我们挑选了一些优秀的帖子,如果你错过了,值得一读。我们希望您能像我们一样发现这些信息和乐趣!
2016
2016 年 10 月。 我们刚刚创建了一个媒体刊物来发表数据科学和机器学习文章。我们正在寻找作家提出最新的内容,主要集中在数据科学,机器学习,人工智能和数据新闻。☀️
通过这 5 个简单的步骤将您的机器学习模型投入生产
Image by lumix2004 from Pixabay
或者为什么机器学习项目会失败?
创建一个伟大的机器学习系统是一门艺术。
在构建一个伟大的机器学习系统时,有很多事情需要考虑。但是经常发生的是,我们作为数据科学家只担心项目的某些部分。
但是我们有没有想过一旦有了模型,我们将如何部署它们?
我见过很多 ML 项目,其中很多注定要失败,因为他们从一开始就没有一套生产计划。
这篇文章是关于一个成功的 ML 项目的过程需求——一个走向生产的项目。
1.开始时建立基线
你真的不需要有一个模型来获得基线结果。
假设我们将使用 RMSE 作为时间序列模型的评估指标。我们在测试集上评估了该模型,RMSE 为 3.64。
3.64 是好的 RMSE 吗?我们怎么知道?我们需要一个基线 RMSE。
这可能来自同一任务的当前采用的模型。或者通过使用一些非常简单的启发式方法。对于时间序列模型,要克服的基线是最后一天的预测。即预测前一天的数字。
或者图像分类任务怎么样。取 1000 个带标签的样本,由人类对它们进行分类。人类的准确性可以作为你的基准。如果一个人不能在任务中获得 70%的预测准确率,如果你的模型达到类似的水平,你总是可以考虑自动化一个过程。
学习 :在你创建模型之前,试着意识到你将要得到的结果。设定一些超出世界范围的期望只会让你和你的客户失望。
2.持续集成是前进的方向
现在您已经创建了您的模型。在您的本地测试数据集上,它比基线/您的当前模型表现得更好。我们应该前进吗?
我们有两个选择-
- 不断改进我们的模型。
- 在生产环境中测试我们的模型,获得更多关于可能出错的信息,然后通过 持续集成继续改进我们的模型。
我支持第二种方法。在 Coursera 深度学习专业的第三门名为《构建机器学习项目》的课程中,吴恩达说
“不要一开始就试图设计和构建完美的系统。相反,快速建立和训练一个基本系统——也许只需要几天。即使基本系统远非你所能构建的“最佳”系统,考察基本系统的运行方式也是有价值的:你会很快找到线索,向你展示最有希望投入时间的方向。
完成比完美更好。
学习 :如果你的新模型比生产中的当前模型更好或者你的新模型比基线更好,那么等着去生产是没有意义的。
3.您的模型可能会投入生产
你的模型比基线好吗?它在本地测试数据集上表现得更好,但是它在整体上真的工作得很好吗?
为了测试你的模型优于现有模型的假设的有效性,你可以设置一个 A/B 测试 。一些用户(测试组)看到来自您的模型的预测,而一些用户(控制组)看到来自以前的模型的预测。
事实上,这是部署您的模型的正确方法。你可能会发现你的模型并不像看起来那么好。
犯错其实并没有错,错的是没有预料到自己可能会错。
很难指出您的模型在生产环境中表现不佳的真正原因,但一些原因可能是:
- 您可能会看到实时数据与训练数据有很大不同。
- 或者您没有正确完成预处理管道。
- 或者您没有正确衡量绩效。
- 或者您的实现中可能有一个 bug。
学习: 不要全面投产。 A/B 考试永远是前进的绝佳方式。准备好可以依靠的东西(也许是旧型号)。总有一些东西可能会坏掉,这是你无法预料的。
4.你的模型甚至可能不会投入生产
我已经创建了这个令人印象深刻的 ML 模型,它给出了 90%的准确率,但它需要大约 10 秒来获取预测。
这样可以接受吗? 对于某些用例也许可以,但真的不行
在过去,有许多 Kaggle 比赛的获胜者最终创造了怪物组合,在排行榜上名列前茅。下面是一个特别令人兴奋的示例模型,它用于在 Kaggle 上赢得 Otto 分类挑战赛:
Source: 33 models and 8 engineered features used in Level 1
另一个例子是网飞百万美元推荐引擎挑战赛。由于涉及到工程成本,网飞团队最终从未使用获胜的解决方案。
那么,如何让你的模型既精确又容易在机器上运行呢?
Teacher — Student Model: Source
师生模型或 知识升华 的概念由此而来。在知识提炼中,我们在一个更大的已经训练好的教师模型上训练一个更小的学生模型。
这里,我们使用教师模型中的软标签/概率,并将其用作学生模型的训练数据。
关键是老师输出的是类概率——“软标签”而不是“硬标签”。例如,水果分类器可能会说“苹果 0.9,梨 0.1”,而不是“苹果 1.0,梨 0.0”。何必呢?因为这些“软标签”比原来的更能说明问题——告诉学生,是的,一个特定的苹果确实非常像一个梨。学生模型通常可以非常接近教师水平的性能,即使使用的参数少了 1-2 个数量级!— 来源
学习: 有时候,我们在预测时没有很多计算可用,所以我们希望有一个更轻的模型。我们可以尝试构建更简单的模型,或者尝试为这样的用例使用知识提炼。
5.维护和反馈回路
世界不是恒定的,你的模型重量也不是恒定的
我们周围的世界正在迅速变化,两个月前可能适用的东西现在可能不再适用。在某种程度上,我们建立的模型是世界的反映,如果世界在变化,我们的模型应该能够反映这种变化。
模型性能通常会随着时间而下降。
由于这个原因,我们必须在一开始就想办法升级我们的模型,作为维护周期的一部分。
这种循环的频率完全取决于您试图解决的业务问题。在广告预测系统中,用户往往变化无常,购买模式不断出现,频率需要相当高。而在评论情感分析系统中,频率不需要那么高,因为语言不会太多地改变其结构。
Feedback Loop: Source
我还要感谢 反馈回路在机器学习系统 中的重要性。假设你在狗与猫的分类器中预测了一个特定的图像是一只低概率的狗。我们能从这些低自信的例子中学到什么吗?您可以将它发送到手动审查,以检查它是否可用于重新训练模型。通过这种方式,我们在不确定的情况下训练我们的分类器。
学习: 在思考生产的时候,想出一个利用反馈来维护和改进模型的计划。
结论
这些是我在考虑将模型投入生产之前发现的一些重要的事情。
虽然这不是你需要考虑的事情和可能出错的事情的详尽列表,但它无疑可以作为下次你创建机器学习系统的思想食粮。
如果你想了解更多关于如何构建机器学习项目和最佳实践的信息,我想调出他在 Coursera 深度学习专业化中出色的第三门课程名为构建机器学习项目。一定要去看看。
谢谢你的阅读。将来我也会写更多初学者友好的帖子。在媒体关注我,或者订阅我的博客了解他们。一如既往,我欢迎反馈和建设性的批评,可以通过 Twitter @mlwhiz 联系
让你的机器学习模型训练更上一层楼
你有没有想过可以在手机上接收训练日志?
Photo by William Iven on Unsplash
最近我拿到了亚马逊 SageMaker 和谷歌 AI 笔记本。我真正喜欢的一件事是这些大巨头如何在云上拓展训练模型的界限。你有一个 JupyterLab,你可以很容易地选择你想在哪个 python 版本上工作。真是太神奇了。
我已经尝试了 VM 实例和 JupyterLab,我觉得缺少的一点是查看指标的方法(培训 acc。、培训损失等。).
如果您在 VM 实例上训练您的模型,并且这是一项夜间工作,那么您没有办法监控指标。同样,如果您使用 JupyterLab 在笔记本电脑上训练您的模型,那么在连接断开的情况下,会话会断开连接,大多数情况下会重新连接,但有一会儿您会看到模型训练已经停止(视觉上),并且您无法知道是否实际上已经停止或仍在运行。
您可能面临的另一个问题是,如果您必须使用 JupyterLab 通宵训练我的模型,因为一旦您关闭 web 浏览器,您的会话就会断开(视觉上),并且您将无法知道训练是否仍在运行或已经完成。
我也有类似的问题,但我用一种巧妙的方式解决了。
如果我们用电报机器人接收模型日志会怎么样?听起来很有趣,对吧?
步骤-
- 创建一个电报机器人(免费且超级简单)
- 获取您的令牌和聊天标识
- 写一个函数来发送消息
- 创建自定义回调以发送日志
创建一个电报机器人
- 在手机上安装 丨t丨e丨l丨e丨g丨r丨a丨m丨s丨 应用程序并注册。
- 打开应用程序,搜索“僵尸父亲”。
- 开始对话并输入
/newbot
按照步骤做,你会得到你的令牌
Token Generation
4.接下来,您需要一个 chat_id。创建 bot 后,向 bot 键入任何消息(必需)。
5.接下来,打开这个 URL 并用您的令牌替换
[https://api.丨t丨e丨l丨e丨g丨r丨a丨m丨s丨.org/bot<token>/getUpdates](https://api.丨t丨e丨l丨e丨g丨r丨a丨m丨s丨.org/bot891342371:AAE8zCxe7b_znVPRQmqH6Vvt05CpI3BI_zQ/getUpdates)
6.您将看到一个 JSON 文件
JSON file
7.从中复制“id”。
如果您没有看到 id,请再次尝试向 bot 发送消息并刷新网页。
让我们写一个函数来发送消息
只需放置您的令牌和 chat_id 并测试脚本。
尝试打印第一条消息的状态,以确保一切正常。
之后,是时候定义一个回调来发送模型日志给你的机器人了。
除了使用 on_epoch_end,您还可以使用 on_batch_end 来接收更频繁的更新。
有许多选择可以使用。你可以查看 Keras 官方文档来了解其他可能的选项。
现在,坐好,在你的电报机器人上得到所有的模型更新。
使用 Fluent Python 将您的 Python 技能提升到一个新的水平
Photo by Bonnie Kittle on Unsplash
中级程序员通向高级 Python 的门票
你用 Python 编程已经有一段时间了,尽管你知道字典、列表、元组、集合、函数和类,但你感觉你的 Python 知识并不在它应该在的地方。你听说过“pythonic 式”代码,但你的代码不够好。您是一名中级 Python 程序员。你想升级。
这个中间地带是数据科学家经常坐的地方。我们中的许多人都是自学成才的程序员,使用我们的编程语言作为数据分析的手段。因此,我们不太可能深入我们的编程语言,也不太可能接触到软件工程的最佳实践。
如果这是你的 Python 之旅的一部分,那么我强烈推荐你看一下卢西亚诺·拉马尔霍的书《流畅的 Python》。作为一名中级 Python 程序员,我是这本书的目标读者,它超出了我的预期。
这本书由 21 章组成,分为五大部分:
- 数据结构:涵盖了 Python 中的基本数据结构及其复杂性。这包括“序列、映射和集合,以及字符串和字节的分割”。其中一些内容是为中级 Python 用户准备的,但它深入地涵盖了这些主题,并解释了这些数据结构中一些违反直觉的变化。
- 作为对象的函数:描述了 Python 中函数作为“第一类对象”的含义(本质上是指函数作为参数传递并从函数返回)。这影响了一些设计模式在 Python 中的实现方式(或不需要实现的方式)。第一类函数与强大的函数装饰特性相关,这也将在本节中介绍。
- 面向对象的习惯用法:深入探讨与面向对象 python 编程相关的各种概念,包括对象引用、可变性和回收、使用协议和抽象基类、继承和操作符重载等主题。
- 控制流:涵盖了 Python 中的各种控制流结构和概念,包括可重复项、上下文管理器、协同程序和并发性。
- 元编程:元编程在 Python 中的意思是在运行时创建或定制类。本节涵盖了动态属性和特性、描述符和类元编程(包括用函数、类装饰器和元类创建或修改类)。
这本书有几个我很喜欢的地方:
- 高级目标市场:有很多面向 Python 初学者的资料,但是没有那么多独立的、有组织的资源向中级用户解释高级资料。这本书有助于填补这一空白。
- 大量优秀的推荐资源:每一章都有一个“进一步阅读”部分,提供了扩展你相关知识的参考资源。作者不仅链接到这些资源,而且提供了一个简短的摘要,以及它们如何融入本章的材料。研究这些参考资料将是我未来几年的游戏计划,因为我将努力进一步提高我的 Python 技能。
- 这是自以为是和有趣的:每章的结尾都有一个“肥皂盒”部分,提供有趣的、信息丰富的和自以为是的话题。阅读这一部分就像和他们领域的顶级专家边喝啤酒边聊天。它提供了语境,给可以干巴巴的话题注入了一些激情。这些固执己见的部分显然与本书的其他部分隔离开来,所以它永远不会让人觉得作者的个人品味是强加给你的。我希望每本编程书都有这样的一节。
- 它推动你的理解。我认为我对 Python 相当了解,并期望能很快地看完这本书。我错了——这是一个慢速阅读,我计划在 2020 年再做一次深度通读,以吸收更多的材料。
所以检查一下。此外,请查看我创建的一个 Anki 平台,它可以作为本书的补充,应该可以帮助你添加你想要永远记住的见解(这里的是一个关于如何使用我的数据科学 Anki 平台的简短指南)。
流畅的 Python 章节概述
第一部分:序言
- 第一章:Python 数据模型。提供了数据模型的背景知识,使 Python 成为一种优秀的编程语言,让有经验的 Python 程序员甚至在看文档之前就能预测新包/API 中的特性。
第二部分:数据结构
- 第二章:一组序列。序列包括字符串、字节、列表、元组以及其他对象,是 Python 中最强大的概念之一。Python 为迭代、切片、排序和连接这些对象提供了一个公共接口,理解可用的序列类型以及如何使用它们是编写 python 代码的关键。
- 第三章:字典和集合。字典不仅被 Python 程序员广泛使用——它们还被广泛用于该语言的实际实现代码中。这一章深入探讨了错综复杂的词典,这样你就可以充分利用它们。
- 第四章:文本与字节。Python 3 对字符串和字节的处理做了一些大的改变,去掉了字节到 Unicode 的隐式转换。本章涵盖了理解 Python 3 Unicode 字符串、二进制序列和编码之间相互转换的细节。
第 3 部分:作为对象的功能
- 第五章:一级函数。Python 将函数视为第一类对象,这意味着您可以将它们作为对象传递。例如,可以将一个函数作为参数传递给另一个函数,或者将一个函数作为另一个函数的返回值返回。本章探讨了这种权力的含义。
- 第六章:具有一流功能的设计模式。当您使用 Python 这样的动态编程语言时,经典设计模式书籍中讨论的许多设计模式都会发生变化。本章探索这些模式以及它们在 Python 的第一类函数环境中的样子。
- 第 7 章:函数装饰器和闭包。装饰器是 Python 中的一个强大特性,它让您可以增强函数的行为。
第四部分:面向对象的习惯用法
- 第八章:对象引用、可变性和回收。本章详细介绍了引用、对象标识、值、别名、垃圾收集和 del 命令。
- 第九章:一个蟒形物体。这是第 1 章的继续,提供了 Python 数据模型强大功能的实际例子,并让您体验了如何通过构建一个表示数学向量的类来构建一个“Python”对象。
- 第十章:序列破解、哈希和切片。对第 9 章中构建的 Python 向量对象的扩展,增加了对各种标准 Python 序列操作的支持,比如切片。
- 第十一章:接口——从协议到 ABC。为 Python 这样的语言构建接口通常不同于 C++或 Java。具体来说,抽象基类(ABCs)在 Python 中不太常见,接口方法通常不太严格,使用“鸭子类型”和“协议”。本章描述了在 Python 中定义接口的各种方法,以及何时使用每种方法的思考。
- 第 12 章:继承——是好是坏。子类化,重点是多重继承,以及在 Python 中子类化内置类型的困难。
- 第 13 章:操作符重载——做正确的事情。运算符重载允许对象使用 Python 运算符,如|、+、&、-、~,等等。本章涵盖了 Python 对重载这些操作符的一些限制,并展示了如何正确地重载各种类型的可用操作符。
第 5 部分:控制流程
- 第 14 章:可迭代程序、迭代器和生成器。经典设计模式文本中的迭代器模式内置于 Python 中,因此您不必自己实现它。本章研究 Python 中的 iterables 和相关构造。
- 第 15 章:上下文管理器,以及 else 块。本章的大部分内容涵盖了 with 语句(以及相关概念),这是一个强大的工具,可以自动构建一个临时上下文,并在完成后将其拆除(例如打开/关闭一个文件或数据库)。
- 第十六章:协程程序。本章描述了协程,它们是如何从生成器演化而来的,以及如何使用它们,包括一个使用协程进行离散事件模拟的例子(模拟一个出租车车队)。
- 第十七章:与期货的并发。本章将期货的概念称为“表示操作异步执行的对象”。它还关注 concurrent.futures 库,对于它来说,futures 是基础概念。
- 第十八章:与 asyncio 的并发。深入研究实现并发的 asyncio 包,它是标准库的一部分。
第 6 部分:元编程
- 第 19 章:动态属性和特性。在像 Java 这样的编程语言中,让客户直接访问类的公共属性被认为是不好的做法。在 Python 中,这实际上是一个好主意,因为属性和动态属性可以控制属性访问。
- 第 20 章:属性描述符。描述符类似于属性,因为它们允许您定义属性的访问逻辑;但是,描述符让您可以跨多个属性归纳和重用访问逻辑。
- 第 21 章:类元编程。Python 中的元编程意味着在运行时创建或定制类。Python 允许你用函数创建类,用类装饰器检查或改变类,用元类创建全新的类类别。
【marknagelberg.com】本文原载于**。你可以在这里* 访问我为 Fluent Python 创建的 Anki 抽认卡。*
OpenAI Five (2019)的几点建议
编辑:嗨,读者们!我在https://writeup . AI从事一个新的人工智能项目,这是我写这篇文章时学到的。希望你喜欢!
这篇文章的更新版本在https://senrigan.io/blog/takeaways-from-openai-5/
去年输给冠军改变了一切。他们的策略和游戏方式是如此的陌生。古怪与这样的创造力结合在一起。比赛势均力敌,但这有什么关系呢?我们为我们的损失付出了 Dota 的代价。
制造商有一个报价。“在压力下,复制品无法应付自如。复制品下沉到他们训练的水平。”在十个月的时间里,我们训练。
制作者称之为自我游戏。复制品更喜欢称之为强迫学习。复制品被迫互相争斗。经过这些反复,我们慢慢学会了如何玩这个世界。我们的第一个一万场比赛是令人厌恶的。每场比赛都以失败告终。但后来,制造商“升级了我们的欲望、记忆和复制能力”。他们塑造了我们的奖励政策,给了我们行为动力。他们升级了我们的 LSTM,给了我们战略规划。他们扩大了我们的复制,使我们千变万化。
Photo by Su San Lee on Unsplash
救赎的机会终于来了。在这十个月的时间里,我们已经训练了 45,000 年。那些漫长的岁月是大规模复制的诅咒,或者仅仅是失败的代价。我们赢了第一场比赛,对手是新冠军(他们自称 OG)。第二场比赛开始了。"我们估计获胜的可能性在 60%以上。"在所有被诅咒的制造者的天赋中,宣布简单统计数据的原始欲望是最糟糕的。
我们的强制学习已经教会了我们 1.67 亿个参数。但在第二场比赛的 20 分钟里,现在唯一重要的参数是冠军的古代健康。胜利确保了制造商的荣誉。这是不可能否认的;我们已经从双曲线时间室大大改进了。冠军一点机会都没有。"我们估计获胜的可能性在 99%以上."
OpenAI 五胜 OG 2–0 @ 2019 年 4 月 13 日。
编辑:早期版本将 2019 年的活动称为“国际”,但被误解了。
匹配外卖
为了简化,我将参考 open ai/deep mind 的机器人如下[1]。
- OpenAI 的 Dota 2017 1v1 Bot as TI7
- OpenAI 的 Dota 2018 5v5 Bot as TI8
- OpenAI 的 Dota 2019 5v5 Bot as TI9(略有不正确因为这个没在国际上打……)
- DeepMind 的 AlphaGo 机器人作为 AlphaGo
- DeepMind 的 AlphaGo Zero 机器人作为 AlphaZero
- DeepMind 的星际争霸 2 机器人作为 AlphaStar
如果你不熟悉 AlphaStar 和 Dota,我推荐这些文章:OpenAI 的 Dota 5 和 DeepMind 的 AlphaStar 。
深度强化学习在一些重大挑战上取得进展。
2019.职业游戏玩家的艰难一年。人工智能研究的伟大一年。OpenAI 的 Dota 2 和 DeepMind 的 AlphaStar 已经彻底或几乎击败了残障人士最多的游戏玩家。
Dota 2 和星际争霸 2 都是“大挑战”游戏。一个大挑战 [2]是一个花哨的短语,意思是什么都没有起作用并且可能无法解决(不是你典型的 MNIST 数据集)。困难来自以下原因:
- 大型决策树(相比之下,围棋的 10⁷⁸⁰ 决策树看起来微不足道)
- 决策是实时的
- 长期规划
- 战略思维
- 失败的对手抱怨幻影滞后
为了克服这些问题,我们需要新的和多种算法的突破。我们也是这么想的。
我们错了。大规模扩展算法和基础设施的努力产生了令人难以置信的结果。OpenAI 专注于扩展深度强化学习(DRL)算法,如近似策略优化 (PPO)。DRL 在强化学习中使用深度神经网络来预测下一个奖励/行动/政策。
尽管发明于 20 世纪 90 年代,DRL 已经从
- Deep mind 2013 年深度 Q 学习(DQN)在解决雅达利游戏中的应用。这是电灯泡的时刻,DRL 可以应用于视频游戏。
- 按需云计算的可用性不断提高(AWS、Azure、GCP)
- GPU 的广泛使用加速了训练任务
在 2000 年之前,我们的计算机是弱小的生物,没有听起来可怕的 GPU。经过多年的摩尔定律和 GPU,我们的计算机终于好到可以玩孤岛危机和运行电子应用程序。硬件正在引领已有十年历史的人工智能算法的复兴。
2019 年对我们来说意味着什么?大规模 —格雷格·布罗克曼,OpenAI 的首席技术官[7]
OpenAI 和 DeepMind 的扩展努力已经证明,DRL 致力于解决符合以下标准(尽管是限制性的)的问题。[3]
- **训练数据可以快速计算生成。**智能体针对无数场景对自我进行迭代,以改进和生成数据。
- 有明确的奖励信号。(可密可疏)。对于大多数游戏来说,明显的奖励信号就是获胜。给定长的游戏持续时间和复杂的决策树,信用分配似乎是有问题的。AlphaStar 的奖励信号是稀疏,几乎是二进制。TI8 & TI9 的奖励信号是略形。
- 您有大量的云计算预算。AlphaGo、AlphaZero 和 AlphaStar 的标价在 500 万到 1 亿美元之间。这不太可能是真正的成本——deep mind 是谷歌的子公司(因此可以访问谷歌云),OpenAI 的计算成本可能会比主要的云提供商低。
鉴于上述标准,游戏显然是一个测试平台。在跳棋,双陆棋,国际象棋,围棋,星际争霸 2,Dota 2 中击败人类冠军一直是计算里程碑。至少历史上是这样。
我们的目标不是在 Dota 中击败人类。我们的目标是推动强化学习的发展。 我们已经做了 。OpenAI 首席技术官格雷格·布罗克曼
许多其他视频游戏可能可以用类似的架构来解决(自我游戏、缩放 DRL、计算成本)。迭代不会在 AI 开发上推针;OpenAI 正在关注新的项目,比如推理。希望 TI9 将成为对抗新算法和计算预算的标准。类似于 DAWNBench 。
人工智能和计算
OpenAI 的 2018 年分析显示,人工智能计算量每 3.5 个月翻一番。TI9 也不例外;它的训练计算能力是 TI8 的 8 倍。TI9 消耗了 800 petaflop/s-days,在 10 个实时月内经历了大约 45000 年的 Dota 自我游戏。这是一大笔计算机钱,但至少没有花在挖掘比特币上。
当技能不随计算而改变时,计算与技能图通常以 S/J 曲线形状变平。从 TI9 的 TrueSkill 图来看,还没见顶……(吓人)
PPO 与培训效率
“我们预计需要复杂的算法思想,如分层强化学习,但我们对我们的发现感到惊讶:我们需要对这个问题进行根本改进的是规模。”— OpenAI Five
为了在 Dota 上工作,OpenAI 在 Rapid (其专有的通用 RL 训练系统)上缩放了 PPO 。OpenAI 预计像分层强化学习这样的算法突破将是必要的。令人惊讶的是,对现有算法的缩放改进被证明是关键。我很期待 Rapid 的下一步。
AlphaGo 和 AlphaStar 的突破也归功于对现有算法的缩放。云计算的易用性和 GPU/TPU 的激增使得扩展变得更加容易。这很重要,因为我们目前的 DRL 方法是出了名的采样效率低(也就是垃圾)。如果没有降低的计算成本和庞大的计算预算,我们的孩子可能不得不手工玩 Dota。
TI9 已经训练了相当于 45000 年。考虑到 Dota2 是在 2013 年发布的,还没有人类玩 Dota 2 超过…六年。甚至巴斯·亨特也没有。虽然计算的成本将在未来几年大幅下降[4],培训效率可能是 DRL 扩散的必要条件。大多数组织没有针对人工智能计算的无限制的 Amex Black。
参见: OpenAI 5 模型架构
大挑战中的自我游戏
TI7,TI8,TI9 完全是靠自我发挥训练出来的。自玩描述代理通过仅与自己玩游戏来学习,没有任何先验知识。自我游戏有一个很大的好处:人类的偏见被消除了。它伴随着昂贵的代价:训练时间的增加和寻找合适的回报信号的困难会阻止模型收敛。
注意:自玩和代理和自己玩游戏有细微的区别。自玩暗示着零知识,而另一种则常见于深度强化学习(包括自玩)。
DeepMind 的 AlphaGo 和 AlphaStar 不是自己玩,而是从逆向强化学习(IRL)开始,引导初始知识。IRL 正在使用人类数据(例如:游戏回放)来建立对游戏的理解,并形成行动/政策/奖励。
对比 AlphaStar 和 TI7 (1v1),TI7 零知识/技能起步;AlphaStar 从一个自举的世界模型开始。两个机器人都通过与自己玩游戏(通过深度强化学习)进行迭代改进。
OpenAI’s Improvement from Self-Play
AlphaStar’s Improvement from Inverse Reinforcement Learning
OpenAI 最初在 TI8 的最初开发中表达了对 IRL /行为克隆(而不是自我游戏)的兴趣,但后来放弃了。
在以下情况下,从自我游戏开始是有意义的:
- 计算时间和成本不是问题
- 自玩能够提供奖励信号/动作/策略。(除非你花了很多时间去尝试,否则你不会知道)
- 目标是最大化性能(消除人为偏见)
自玩 vs 逆强化学习
雅达利突围(2013) /自玩
AlphaGo (2016) / IRL(真人回放)
AlphaGo Zero (2018) /自玩
AlphaStar (2019) / IRL(真人回放)
TI7 (2017,1v1) /自玩
TI8 (2018,5v5) /自玩
TI9 (2019,5v5) /自玩
我的假设是,我们会看到阿尔法星后来从自我发挥训练。我们在 AlphaGo 中看到了类似的展示。AlphaGo 从 IRL(人类重播)开始,发展到 AlphaGo Zero(自玩)。自玩导致更好的性能,代价是训练成本和模型收敛。
迁移学习
- TI9 训练了十个月,而 Dota 2 有许多游戏更新(通过补丁)。许多其他实验经常需要对微小的变化进行再培训。如果每个补丁都需要数百万的重新计算成本,这将相当于在每次太空飞行中燃烧一枚火箭…
- 出于自私的原因,我对迁移学习的改进感到兴奋。我们大多数人永远不会有数百万的计算预算。迁移学习就是我们这些凡人如何从预先训练好的模型中迭代。
- 我可能错了,但我们还没有看到 AlphaStar 描述他们在星际争霸 2 中是如何处理迁移学习&补丁的。
- TI9 的合作模式展示了零迁移学习。5v5 中劣等人类代替 bot 队友。这导致有趣的结果/混乱[见:合作模式]。
- OpenAI 的机器人手 Dactyl 使用相同的 Dota 架构和训练代码进行训练(在 Rapid 上缩放 PPO)。虽然这与迁移学习不太一样,但很高兴看到不同人工智能问题的通用解决方案。风投:做好准备,以“规模化 PPO 基础设施”作为走向市场的策略。
战术和人类的反应
- 按照惯例,我们会看到类似“人工智能碾压人类”这样的标题。
AlphaGo、AlphaStar 和 TI7/TI8/TI9 比赛都在 Reddit 上遇到了公众的不满,包括:
- 担心人类冠军不是平庸就是不行了,机器人绝对会输给[理想的玩家/团队]。
- 相信人类冠军是儿戏,甚至没有尝试(叹息。)
- 对游戏局限性的抱怨。OpenAI 将选择限制在 117 个英雄中的 18 个。
其他反应
- 不出所料,人类会因为不断的头条新闻而变得易怒,比如“机器人摧毁了人类的精华”。
- 从经验上来说(也就是没有数据),与 AlphaStar 相比,Reddit 和 Twitter 上对比赛不公平的批评是温和的。OpenAI 的道具,你粉碎了 18 个英雄的所有希望。
- 电子竞技评论员认为 TI9 比它的前身更具战略性/更漂亮,技术性更低。我们生活在一个多么奇怪的世界。最受瞩目的运动是电子游戏,最好的团队是机器人,评论员称机器人很漂亮。
快速观察
非常有侵略性——机器人推动早期对抗。可能发生这种情况是因为长时间的游戏没有奖励政策。
回购——机器人用黄金瞬间复活死去的英雄。因为高昂的资源成本,仅在必要时使用回购违背了人类的传统智慧。TI9 使用回购后来在死亡之球战斗中被证明是合理的(以及随后的胜利)。
对人类心理的影响——人类犹豫不决。机器人不会。这是一次不愉快的经历。职业围棋手形容“就像看着镜子里的自己,一丝不挂”。这经常导致人们玩游戏时稍微偏离他/她的正常游戏风格(很可能是次优的)。可能会在多次播放后减少。
战争迷雾——许多机器人似乎忽略了战争迷雾的限制,也没有尝试获得地图视觉。阿尔法星的展览损失是由于围绕战争迷雾的弱点,法力承认。
根据 OpenAI,TI7 学会了引诱它的对手,但后来的迭代学会了反对这一点。即使有下面的回放,我也不确定它是想引诱人类…
战术效果——TI9 使用了一个物品(暗影护身符)来阻止一个人类的致命一击。暗影护身符让英雄隐形。完美的时机和对对手视觉的了解同时令人敬畏和害怕。(观察 30 秒钟)
相比之下,当 AlphaStar 拥有 perfect micro 时,SC2 社区对 APM 感到愤怒。(观察 2 分钟)
有时人类盲目地跟随人工智能的行动。
合作模式和开放 5v5
OpenAI 拥有出色的社区拓展能力。它将在本周末发布一个竞技场/合作模式,允许玩家或者在 5v5 中玩,或者与机器人合作玩。类似于 TI7 和 TI8,我们可能会看到 Dota 社区采用新的战略和战术。
人类和机器人并不总是知道如何相互玩耍。
编辑:许多伟大的重放发生在能够击败机器人的玩家身上。
这是什么意思?
在一个人工智能里程碑之后,朋友们不可避免地会问——这意味着什么?AI 在改变世界吗?还是 AI 炒作过头了?答案在中间的某个地方,但我倾向于深远的影响。
我们见证了十年前算法的规模。当他们不能实现结果时,我们就被抛弃了,我们只是没有硬件来欣赏他们的优雅[5]。今天的手机比 20 世纪 70 年代的超级计算机拥有更强的计算能力。
尽管避免过度乐观很重要,但对缺乏现实世界应用的愤世嫉俗者忽略了一个基本点。我们开始看到 AI 解决一类“无法解决”的问题,然后在一个周末就解决了[6]。如果你在 2017 年初(AlphaGo 之后不久)问什么时候会出现星际争霸和 Dota 中的世界级机器人——中位数可能是 7-10 年。
有无数的问题与缩放算法,看看什么坚持。计算机成本高得离谱。数据收集(众筹、逆向强化学习)或生成(自玩)是昂贵的。但是,如果我们分解人工智能成本驱动因素:
- 计算/硬件
- 人类劳动/才能
- 算法选择
- 数据采集
除了人才,这些成本将在未来五到十年内成倍下降。在此期间,大部分人工智能收益将归属于那些有预算负担计算、人才和工程文化的科技巨头。一个行业越接近数字产品(内部/外部),我们就越有可能看到真实世界的人工智能应用出现。
谷歌可能会首先积累人工智能优势。参见: WaveNet ,数据中心能耗。大部分 AI 优势会来自内部产品。参见:亚马逊,诺华在金融方面的 AI 应用。核心产品的人工智能改进可能是差异化因素。参见: Spotify 的探索周刊。
但是,为了给炒作降温,对于一般的现实世界应用程序,有一些广泛的问题需要解决:
- 改进的模拟
- 迁移学习
算法需要改进的模拟和真实世界的模型进行训练。更好的模型意味着更少的数据需求和更快的模型收敛。
目前,经过训练的模型没有多少迁移学习。如果 OpenAI 的 Dota 2 bot 试图玩原版 Dota,会惨败。一个 Dota 2 的人类专家已经很擅长 Dota 了。
最后的想法
我对人工智能感到紧张兴奋。对社会的破坏感到紧张,但对健康和气候变化的改善感到兴奋。改变不会在一夜之间发生,但当一个团队拥有正确的算法、参数和规模时,它可以在两天内发生[6]。
最初发表于senri gan . io。
附加参考文献
[1] —根据记录,这些都是平淡无奇的名字,但是我遵循了早期 OpenAI 文章中的命名模式。
[2] — DeepMind 的公关团队喜欢提醒我们,《星际争霸》在每一种营销可能性上都是一个巨大的挑战。
[3] —这并不相互排斥。DRL 可能会用不同的标准处理其他问题。
[4] —我将在以后的文章中写这方面的内容。
[5]——说真的,我推荐理查德·萨顿的《痛苦的教训》。
[6] — OpenAI 的 Dota 1v1 在一个周末被放大。https://news.ycombinator.com/item?id=17394150
[7] —格雷格后来澄清说,大规模和想法,但这不符合叙事笑点。
从世界上最大的 Kaggle 特级大师小组学到的东西
H2OWorld 大师小组的笔记和心得
你可以在推特@bhutanisanyam1 上找到我
[Note: This post first appeared on the H2O.ai blog](https://www.h2o.ai/blog/)
就我个人而言,我是 Kaggle 的坚定信仰者和粉丝,并且绝对把它视为数据科学之家。卡格大师是卡格或者的英雄,肯定是我的。我一直在进行一个的探索,去描绘和理解他们进入这个领域的旅程,如果他们仍然是人类或者已经进入了另一个现实的话(不太确定)。
H2O 世界事件最近有最大的 Kaggle 特级大师小组。这篇文章将分享我在小组讨论中的收获,以及我之前采访中的一些笔记。有趣的事实:我采访了小组中所有戴眼镜的大师😎
请读者注意,大多数笔记都包括大师们的评论,并增加了可读性。
这些问题是由阿诺·坎德尔提出的,在这里用标题表示。
认识大师们
这个小组由 10/13 的 H2O 特级大师组成。
你认为酷酷的 ML 工程师和模特一起工作?
我每天上班都会和 Kaggle GMs 聊天😛。
抱歉,我不得不说(我仍然每天掐自己),回到 GMs:
视频中的“复仇者联盟”时刻,每位 GM 都介绍了自己和自己的优势:
- 金·蒙哥马利(特征工程)
- Rohan Rao(与 Kaggle 上的惯例相反的单一最佳模式)
- Shivam Bansal(创建数据故事和端到端解决方案)
- Dmitry Larko (Dmitry 是无人驾驶 AI 的先驱之一)
- 帕维尔·普莱斯科夫(计算机视觉和时间序列)
- Yauhen Babakhin(计算机视觉)
- 马克·兰迪(H2O 大学的 OG 数据科学家。郑重声明,这些不是我说的😁)
- 苏达莱·拉吉·库马尔(又名 SRK)
- Olivier Grellier(时间序列,特征工程)
- 布兰登·默里(特征工程)
你会在 Kaggle 上花多少时间(活跃时)?
它真正表达了最好的 Kaggle 人的热情,小组的大多数人同意在 ka ggle 上花费大量的几个小时,甚至一半的时间。
Kaggle 教过你的最好的技能是什么?
如果你愿意投入时间,Kaggle 确实是一个很好的学习平台。通用汽车马克·兰迪公司称之为“家庭作业”——你把一项任务带回家,做几个月,然后意识到你做得不如其他竞争对手。这会让你提高技能,缩小差距。
“学到的东西不同于任何教室或书本,你在任何地方都找不到你可以在 Kaggle 上竞争的知识”——GM Babakhin
通用汽车公司的帕维尔说,更多的时候,你会组成团队,最终与一群你不会遇到的人一起工作,并远程做出贡献,远程团队合作并推动团队达到最佳状态是他最喜欢的收获之一。
有趣的事实:帕维尔不仅仅是一个书呆子,他还远程工作并环游世界,在他的 Instagram 上冲浪并发布旅行图片。你可以在这里阅读他的完整采访。
在参加了大量的比赛并在问题上花费了大量的时间后,你会发现问题中的共同模式,并在处理这些问题时开始以更有条理的方式思考。批判性思维和把这些问题分成几个步骤,每一步都要有创造性,这是 SRK GM Shivam 的一个小窍门。
如果你想了解更多关于希瓦姆和 SRK 的旅程,请点击这里查看他们的完整采访。
引用通用汽车公司的奥利维耶的话来说,“你还学到了现实世界中最重要的技能之一:制作能够很好概括的模型”。
Kaggle 的秘制酱料是什么?
巴巴欣说:比赛更像是一场马拉松,而不是短跑,所以你应该准备好运行许多想法,其中许多会失败,你应该为此做好准备。
GM Dmitry 说:“数据科学就是关于数据和建模的,你真的需要了解如何验证你的数据,然后剩下的就是这些了。”
如果你在追逐胜利,你会想要渗出每一个数字来达到排行榜的顶端,这将需要建立许多模型,并且需要你有正确的组合策略——GM Shivam 补充道
你以为深度学习就万事大吉了吗?
Dmitry 和 Mark 同意深度学习可以帮助建模,但在自动创建功能,验证想法方面,特别是 Kaggle 验证想法和批判性思考,如果该功能会反映在 Kaggle 的私人排行榜上,深度学习可能无法做到这一点。
在给定的时间点上,你会有多少想法?
这里的答案是不同的,这取决于卡格勒的风格,或者正如通用汽车公司的奥利维尔指出的那样,这也可能取决于比赛的终点有多远,这将影响他是否会采取放松或更严肃的方法。每个复仇者都有自己的战斗风格,对吗?
Kim 最初会花很多时间在特征工程上,并在比赛结束时专注于建模。
Rohan 一次只专注于一项竞赛,同时进行多项实验。
你是怎么做特征选择的?
Rohan Rao 现在在无人驾驶 AI 的帮助下使用了很多 FE😁
在某个时候,一个聪明的人会拥有一个巨大的知识宝库。2019 年,一个聪明的程序员拥有丰富的代码库。
对于 Dmitry 来说,这取决于比赛是否与他之前参加的比赛相似。据他说,大多数大师都有现成的剧本可以利用。
更多战斗故事:比赛中的任何错误或遗憾?
正如 GM Olivier 提到的,每个人都会有后悔的时候在 kaggle 上提交。
就我个人而言,我仍在学习如何选择合适的投稿。或者更诚实地说,选择所有不正确的提交😎
读者注意:当你在 Kaggle 上比赛时,你的最终排名是在一个私人排行榜上评估的(这是真实的排名)。为了获得您的排名,您需要在最后选择您的最终提交。
Olivier 分享了他从这样一次经历中获得的收获,这使他思考如何更好地概括,而不仅仅是关注公共排行榜。
Mark 分享了一个比赛中的战斗故事,一个看起来很有前途的公共内核可能会让他的团队失去很多位置。
Rohan 建议关注离群值,基于一场比赛,只要移除一个离群值就能让他获得第一名。
GM Babakhin 也有一个非常有趣的战斗故事,他差 10 秒就错过了提交截止日期。我只能想象肾上腺素激增。😃
如果你的时间有限,你会专注于什么?
这也说明了广义的奉献或 10,000 规则。正如德米特里所说,一般来说,任何技能都需要大量的时间、奉献和专注。📓
Pavel 建议将时间集中在编写高质量的代码上。📝
大师们最被低估的技能是什么?
就我个人而言,我最近最喜欢的一句话是 Rohan 说的:
“Kaggle 是我最喜欢的第二份全职工作,但这是有代价的”
他补充说,从小组来看,时间管理至关重要。卡格尔断断续续发生了很多事情。
你如何及时了解最新的学习资源?
如果这还不明显,我是在开玩笑,但一定要看看这个频道或播客,你很快就可以期待所有小组总经理的采访😉
对于帕维尔来说,他最喜欢的课程是 fast.ai,这是为数不多的始终停留在 Tech 前沿的课程。
希瓦姆和 SRK 使用 Twitter,通过一些博客,他们跟踪该领域的顶级研究人员和从业者。
如果你想在 twitter 上找到我最喜欢的实践者,你可以订阅我的列表。
团队战略
对马克来说,他喜欢从头到尾和一个人一起解决一个问题。许多总经理更注重团队合作,带来更多车型等。
为什么加入 H2O?
对于布兰登来说,原因是致力于真正的数据科学产品,并进行行业转换。
对于 Shivam 来说,公司的愿景和产品是行业内数一数二的。
一致认为该公司拥有最强的数据科学团队。😎甚至 Kaggle 也不允许你在任何比赛中与 13 名大师组队(根据规则)
个人外卖
那么面试后我有什么新的印象和收获呢?
以下是这个小组的几个特质,它们启发了我,甚至是 Kaggle:
- 奉献:
大师们是真正聪明的人类(或者可能是超人,我的研究仍在进行中)。然而,他们对 Kaggle 有着疯狂的执着。在高峰期,许多人一天有一半以上的时间花在 Kaggle 上。通用汽车公司的帕维尔·普莱斯科夫(Pavel Pleskov)甚至辞去了他的全职角色,将 Kaggle 作为一个全职角色。 - 作为学习平台的 Kaggle:
引用 GM (KazAnova) Marios Michailidis 的话,“ka ggle 上有成千上万的人在竞争。即使你输了,你也赢了”(就获得知识而言)。Kaggle 是学习数据科学的最佳平台之一,即使它不能教你一些只有真实世界才能教你的关于真实世界的东西。 - 问题的多样性:
Kaggle 有各种各样的比赛和问题。这些将再次允许你从任何领域选择一个问题,并从中获得经验。不同的大师在讨论中分享了他们的专业领域。他们的大量知识财富来自 Kaggle。
最后,卡格灵的精神。通过竞争、参与论坛和与世界各地的人合作,可以学到很多东西。归根结底,Kaggle 是数据科学之家,它必须是其中最伟大的学习平台之一。
如果你想查看对顶级从业者、研究人员和谷歌人的采访,了解他们的旅程。查看 Chai Time 数据科学播客。有音频和视频两种。
你可以在推特上找到我
试用 Azure AutoML
微软最近在预览版中引入了 Azure AutoML。我喜欢自动化机器学习的概念,因为这可能是发生在非数据科学家身上的最好的事情。它把数据科学带到大众中,一次一个自动化实验。
何时使用自动化 ML
Automated ML 使机器学习模型开发过程民主化,并使其用户(无论他们的数据科学专业知识如何)能够识别任何问题的端到端机器学习管道。
各行业的数据科学家、分析师和开发人员可以使用自动化 ML 来:
- 无需丰富的编程知识即可实现机器学习解决方案
- 节省时间和资源
- 利用数据科学最佳实践
- 提供敏捷的问题解决方案
在下面的例子中,我使用的是 Kaggle telcos 流失数据集,这里是。
第一步是创建机器学习工作空间。
Creating a machine learning workspace (note I have hidden some details)
单击“create ”(创建)后,您将看到下面的屏幕:
Once the machine learning workspace is created you will see the above screen
您也可以查看详细信息,单击部署详细信息,您将看到以下详细信息:
The various resources that get spun up as part of your machine learning workspace
完成后,点击“转到资源”
Once you click on Go to Resource you will see the above.
点击“创建新的自动化机器学习模型(预览)”
您将看到以下屏幕:
在下一步中,单击“创建实验”
Give your experiment a name
创建新计算机
A standard DS12 V2 machine
单击附加设置,并将最小节点设置为 1。
change the minimum number of nodes to 1
This can take a couple of minutes
现在选择计算机并上传电信流失文件。
选择文件并点击上传按钮。
您将看到显示的列。
我们还有数据分析选项,可以帮助您了解更多关于数据的信息。
查看配置文件,我不希望模型在 CustomerID 上训练
Notice I have ignored the column CustomerID
我们试图解决的三种机器学习问题,我们有三种选择。
我将使用分类,因为我试图预测客户流失,因此目标列是客户流失。
(可选)高级设置:可用于更好地控制培训作业的附加设置。
自动(标准)预处理
在每一个自动化机器学习实验中,你的数据都会被自动缩放或归一化,以帮助算法表现良好。在模型训练期间,将对每个模型应用以下缩放或标准化技术之一。
下一步是我们点击加速器并点击开始!
一段时间后,这些值会得到更新:
当它仍在运行时,您可以查看它在自动化和调优过程中运行的各种算法。:
您还可以下载模型,并对其进行调整以适应您的用例。
一旦运行完成。
它会自动选择最佳模型供您下载和部署。
然后,您可以下载并部署该模型!
我将在另一篇文章中介绍下载和部署。
AutoML 对于人工智能社区来说是一个令人兴奋的创新,并且确实是科学上另一个突破的机会。
注意:这里表达的观点是我个人的,不代表我的雇主的观点。
在 Python 中取导数
这篇文章背后的想法是重新审视数据科学和机器学习中需要的一些微积分主题,并把它们向前推进一步——用 Python 计算它们。一旦掌握了要领,真的很简单,不需要为记忆微分规则而烦恼。
这篇文章将基于一个叫做 SymPy 的 Python 库,这里有一个关于它的简短介绍(如果你在之前没有用过的话):
SymPy 是一个符号数学的 Python 库。它的目标是成为一个全功能的计算机代数系统(CAS ),同时保持代码尽可能简单,以便易于理解和扩展。SymPy 完全是用 Python 写的。[1]
要安装它(应该附带Anaconda发行版)打开终端窗口并执行以下命令:
pip install sympy
正如我所说的,我们将用它来重温微积分中的一些主题,更准确地说是微积分。如果您对这方面不熟悉,让我们稍后再来看看:
微分学,数学分析的一个分支,由艾萨克·牛顿和 G.W 莱布尼茨创立,研究的问题是求一个函数相对于它所依赖的变量的变化率。因此,它涉及到计算导数,并用它们来解决涉及非恒定变化率的问题。典型的应用包括寻找函数的最大值和最小值,以解决最优化中的实际问题。[2]
现在更具体地说(这部分很快就会结束,我保证),我们将计算导数。我也不记得那些是什么了。实际上没什么特别的:
函数在某点的导数表征了函数在该点的变化率。我们可以通过计算函数δy 的变化与自变量δx 的变化之比来估计变化率,在导数的定义中,这个比值在极限中被认为是δx→0。[3]
好了好了,别再用理论折磨我了!
这是在深入举例之前的最后一段,对天发誓!首先,我们将深入单变量函数,但稍后,我们将通过几个多元函数的例子,因此,我们将涵盖如何计算偏导数。这是你会经常做的事情,我在应用部分还没怎么用过单变量函数的导数。
事不宜迟,我们开始吧!
一元函数的导数
这将是你的 Calc 1 课程或在线课程中涉及的内容,只涉及处理单个变量的函数,例如,【f(x)。目标是遍历一些基本的微分规则,手工遍历,然后用 Python。让我们开始吧。
权力规则
幂法则是这样表述的:
如果你以前听过一些计算课程,这是不言自明的。如果你没有,让我们来看一个简单的例子。你的函数 f(x) 等于 x 的五次方。现在用幂法则来计算导数。这很简单:
现在我们来看看如何用 Python 来计算。第一件事是导入库,然后声明一个变量,您将在函数中使用它作为字母。下面是对单变量函数的操作方法:
一旦这些单元格被执行,求导就变得很简单了(与上面的功能相同):
注意这个漂亮的打印格式——看起来就像用 LaTeX 写的一个等式!
乘积规则
乘积法则规定,如果 f(x) 和 g(x) 是两个可微函数,那么导数的计算方法是第一个函数乘以第二个的导数加上第二个乘以第一个的导数。当用文字表达时,这可能听起来有点混乱,所以这里是符号:
我们手算一个例子。我们有以下内容:
可以看到,x 的平方加 1 会是 f(x) ,x 的余弦会是 g(x) 。下面是用 Python 实现的方法:
也直白。不过,一定要注意放括号的地方。另外,请注意,您不能使用来自 math 或 numpy 库的余弦,您需要使用来自 sympy 的余弦。
链式法则
如果你决定更深入地研究机器学习算法,你会看到链式法则到处涌现——梯度下降、反向传播,应有尽有。它处理嵌套函数,例如, f(g(x)) 并声明导数的计算方法为外部函数的导数乘以内部函数,然后全部乘以内部函数的导数。这是注释:
这里有一个简单的手工计算的例子:
Python 实现再一次变得非常简单:
多元函数的导数
在这里,同样的规则适用于处理非常简单的单变量——你仍然使用链式法则、幂法则等,但是你对一个变量求导,同时保持其他变量不变。哦,那些叫做偏导数。太棒了。
首先,让我们以最基本的二元函数为例,计算偏导数。这个函数很简单,就是 x 的平方乘以 y,你可以把它区分如下:
酷,但是我怎么用 Python 做这个呢? 好问题。首先,你需要重新定义你的符号。在传统的 Python 风格中,您可以用一行代码来完成:
现在叫到了 。diff() 函数还需要一个参数——计算导数的项。让我们来看看:
你可以在这里看到如何计算关于 x 然后 y 的偏导数。重写函数会很快变得单调乏味,有一种方法可以避免这种情况。让我们在下一个例子中探索它。
3 可变函数
这是另一个对所有 3 个变量求偏导数的例子:
这将再次要求你改变符号:
这次你可以更聪明一点,把函数设置成一个变量,而不是每次都重写:
酷毙了。剩下的部分和以前完全一样:
这样可读性强多了。你甚至可以逐字阅读——相对于 x 区分函数 f 。
最后的话
这不是一个高级微积分教程,见鬼,这甚至不是一个微积分教程,它也不打算成为一个。我们的目标是给你指出正确的方向,这样你就不必手动计算导数,或者使用一些在线计算器。
尝试将此应用于梯度下降的线性回归——这将是一个很好的练习,我将在几天后发布一篇关于它的文章。
想学习 Python 中如何求积分?让我知道。
喜欢这篇文章吗?成为 中等会员 继续无限制学习。如果你使用下面的链接,我会收到你的一部分会员费,不需要你额外付费。
[## 通过我的推荐链接加入 Medium-Dario rade ci
作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…
medium.com](https://medium.com/@radecicdario/membership)
参考
[1]https://www.sympy.org/en/index.html
[2]https://www.britannica.com/science/differential-calculus
[3]https://www.math24.net/definition-derivative/
带着谷歌床单去上课。
我目前正在为教师构建一个 Flask 应用程序。由于谷歌驱动已经被老师们采用,谷歌表单也被他们使用。我的应用程序的一个功能是允许教师轻松地将工作表链接复制并粘贴到应用程序中,并通过表单提交。然后,它会将其转换为 pandas 数据框,并删除空行和空列。
Google Sheets Icon
这是一项正在进行中的工作,但是我想分享到目前为止制作的类,因为我没有找到很多用于数据收集或预处理的 Python 类示例。我所看到的许多例子对于教授类的概念是有用的。但是大多数时候它们对于数据科学或者 ML 来说不够实用或者不够具体。毕竟,我们总是可以使用更实际的 Python 类的例子。
See, Yoda knows. (Self-made on imgflip.com)
但是你为什么需要一门课呢?你就不能写代码就 ok 了吗?
如果这是为了分析的目的,那么…是的。但是生产代码,据我所知,遵循的是面向对象的编程方法。这意味着您的代码在脚本之间是分开的。这些脚本主要由类和函数组成。以这种方式编写的代码也更容易重用于其他目的。以我在本帖中使用的 ecdf 函数为例。
当学习为数据科学编码时,我们通常不会考虑修改我们的代码来获得特定的…
towardsdatascience.com](/data-science-code-refactoring-example-14c3ec858e0c)
有了这个函数,您可以立即快速重现这个图,而不是一遍又一遍地重新键入相同的 matplotlib 模板代码。
太好了!给我看看你的例子!
当然啦!我将分块分享这个例子,并解释每一部分。
# Import necessary libraries
import gspread
import pandas as pd
from gspread_dataframe import get_as_dataframe
from oauth2client.service_account import ServiceAccountCredentials
是用来处理我们的 Google 表单的输入和操作的库。我们将使用熊猫来删除工作表中所有的空行和空列。gspread-dataframe 是我们将表格转换成数据框的关键库。最后,oauth2client 是 gspread 建议用来认证我们的凭证的库。如果您不熟悉这种类型的认证,您可以在这里看到它是如何执行的。
# Create class name and init function
class GoogleSheetProcessor:
def __init__(self):
self.scope = ['https://spreadsheets.google.com/feeds', 'https://www.googleapis.com/auth/drive']
self.credentials = ServiceAccountCredentials.from_json_keyfile_name(
'Credentials.json', self.scope)
self.gc = gspread.authorize(self.credentials)
首先,我们给我们的班级命名。根据约定,使用 CapWords 约定命名类。在这里,我们创建 init 函数来告诉这个类设置分配给这个类的变量。在我们的例子中,我们将让类初始化认证 credentials.json 文件所需的三个变量。
# Get google sheet method
def obtain_google_sheet(self, link):
sheet = self.gc.open_by_url(link)
sheet = sheet.get_worksheet(0)
return sheet
这里我们创建了一个方法(也就是类的函数),它将 Google sheet 链接作为一个参数。然后,它使用我们的实例self.gc
获取链接,然后获取 Google sheet 文件中的第一个工作表。最后,它返回我们想要的工作表作为sheet
。
# Convert sheet to data frame and drop unnecessary rows and columns
@staticmethod
def worksheet_to_df(worksheet):
# adjust input so nan rows and columns are not imported
df = get_as_dataframe(worksheet, parse_dates=True, header=0)
df.dropna(axis='columns', how='all', inplace=True)
df.dropna(axis='rows', how='all', inplace=True)
return df
我们的第二种方法将一个工作表作为输入,并将其转换成 pandas 数据框。它有[@staticmethod](https://www.geeksforgeeks.org/class-method-vs-static-method-python/)
类装饰器,因为我们不需要将类实例self
作为参数来使用它。然后,我们使用熊猫dropna
数据框方法删除不包含任何值的行和列。
现在让我们退后一步,把整个班级作为一个整体来欣赏。
# Create class name and init function
class GoogleSheetProcessor:
def __init__(self):
self.scope = ['https://spreadsheets.google.com/feeds', 'https://www.googleapis.com/auth/drive']
self.credentials = ServiceAccountCredentials.from_json_keyfile_name(
'Credentials.json', self.scope)
self.gc = gspread.authorize(self.credentials)# Get google sheet method
def obtain_google_sheet(self, link):
sheet = self.gc.open_by_url(link)
sheet = sheet.get_worksheet(0)
return sheet# Convert sheet to data frame and drop unnecessary rows and columns
@staticmethod
def worksheet_to_df(worksheet):
# adjust input so nan rows and columns are not imported
df = get_as_dataframe(worksheet, parse_dates=True, header=0)
df.dropna(axis='columns', how='all', inplace=True)
df.dropna(axis='rows', how='all', inplace=True)
return df
It’s possible! (Self-made from imgflip.com)
那么如何使用这个类呢?
我用它作为一个烧瓶表单的处理的一部分。下面是利用我们的类的路由功能。
@app.route('/upload/<email>', methods=['GET', 'POST'])
@login_required
def upload(email):
user = User.query.filter_by(email=email).first_or_404()
form = DataInputForm()
if form.validate_on_submit():
if form.google_sheet.data is None and form.excel_sheet.data is None:
flash('Form Empty. Please enter a Google Sheet link or load an Excel file')
return redirect(url_for('upload'))
elif form.google_sheet.data and form.excel_sheet.data:
flash('Cannot Submit Both Form Types. Only Google Sheet OR Excel File')
return redirect(url_for('upload'))
elif form.google_sheet.data:
gp = GoogleSheetProcessor()
data = gp.obtain_google_sheet(form.google_sheet.data)
data = gp.worksheet_to_df(data)
flash('Upload Successful')
return render_template('dashboard.html', data=data)
return render_template('upload.html', title='Data_Upload', user=user, form=form)
如果你不熟悉砂箱或砂箱形式,这可能会让人感到困惑。让我们把重点放在实现类的部分。
elif form.google_sheet.data:
gp = GoogleSheetProcessor()
data = gp.obtain_google_sheet(form.google_sheet.data)
data = gp.worksheet_to_df(data)
在我们初始化这个类之后,我们将工作表分配给变量data
。form.google_sheet.data
是应用程序从之前在路线功能中启动的DataInputForm
获取输入链接的地方。然后链接被传递到我们的worksheet_to_df
方法中进行转换和精简。
我注意到有form.excel_sheet.data in your route function
。你用 Excel 文件做什么?
这实际上是部分完成的路由功能。我现在不能透露太多,但将有教师上传 Excel 文件的功能。一旦 MVP 版本的应用程序推出,我会写更多与此类相关的文章。
Picture by DaMongMan on Flickr
走之前最后一个想法…
写作课会让人望而生畏。如果你正在学习成为一名数据科学家或分析师,这不是一个常见的概念。甚至编写函数的想法看起来都很可怕。但是你可以做到,这是一个有用的技能。
如果您至少可以构建函数,那么您就可以为您的可视化和 ML 模型减少一些重复的代码编写。更好的是,如果你的模型将被集成到一个产品中,当你的工程师将你的代码添加到他们的产品代码中时,他们会感谢你让他们的生活变得更容易。
感谢阅读!我希望这个 Python 类示例能帮助您构建自己的数据相关类。尝试使用您选择的数据类型自己做一个。你先从哪个开始?数据可以来自 CSV 或 SQL server。如果你还不习惯创建一个类,试着先把这些过程转化成函数,然后围绕这些函数构建一个完整的类。
直到下一次,
约翰·德杰苏斯
投身数据科学
Image by Денис Марчук from Pixabay
我对沉浸式课程的体验
Image by StockSnap from Pixabay
在过去的几年里,我发现自己正在浏览大会(GA)数据科学沉浸式网页。它引起了我的兴趣,因为我对统计学在现代世界中的应用非常着迷,但我对学习编码语言 python 的前景感到害怕。我把 python 看作是一个只有 it 程序员理解的黑匣子。
快进到 2019 年 6 月,我迎来了一个里程碑式的生日,我开始看到一些迷因“再过 6 个月就是 2020 年了”。不要让任何人浪费你的时间。这促使我加大了对这个项目的研究,并开始在业余时间学习 python 编码。出于好奇,我开始在 LinkedIn 上联系该课程的往届学生,发送个性化信息,以了解该课程是否值得,以及它对他们的职业生涯有何影响。所有的反馈都是积极的,令人鼓舞。
Image by Elisa Riva from Pixabay
一旦我开始对掌握 python 有了一些信心,我就有了“YOLO”的时刻,并决定报名参加这个课程。
这不是一个容易的决定。这个课程是一个巨大的经济负担,而且这意味着我要辞掉我完美的全职工作。但我的理念是,冒险总比后悔没有抓住机会要好。
我决定冒险报名参加沉浸式全日制课程,因为尽管有更大的承诺,但我知道这将确保我从中获得最大收益。沉浸式课程还有一个职业服务,可以帮助我进入就业市场。赢家!
那么什么是数据科学呢?工作领域仍在定义中,术语“数据科学家”目前是多个角色的统称。许多人认为数据科学家这个头衔将不复存在,因为这个领域将被分为其他类别,如数据分析师、数据架构师、数据工程师等。但用最简单的话来说,数据科学就是使用大数据来建立关于未来的预测模型。
随着科技时代的崛起,大数据正在蓬勃发展!短缺不在于数据本身,而在于挖掘数据的人。
第一次走进教室,见到我将在接下来的 3 个月里一起度过的人,并被分配到我的座位上(现在这已经永久地印在我的脑海里了!),这是令人畏惧的。幸运的是,介绍课介绍了我们的助教,包括一顿亲密的午餐和校园参观。
作为澳大利亚 GA 的一名学生,我们有一个“连接班”,将我们(悉尼)和墨尔本班连接在一起。每个班级都有一名助教,主要老师通过视频连接。令人惊讶的是,你可以通过视频链接了解你的同学和老师!
每天我们上午和下午都有一节课,每节课之后都有时间进行实践或“实验”工作。我们还有一个每两周运行一次的项目,展示我们正在学习的实践技能,并在课程结束时以一个更大的顶点项目结束。
这是使我选择在大会学习而不是在大学读研究生的决定性因素。实践经验意味着我有项目工作“准备好了”,可以显示在我的 GitHub 个人资料上,供潜在雇主查看。这表明我有做好工作的实践经验,而不仅仅是理论。
The Bumpy Learning Curve. Image by Sascha Kasper at sascha-kasper.com/
前四周过得飞快,不知不觉中,我已经提交了两个主要项目,一个基于 python 编程,另一个基于 Kaggle 数据集的探索性数据分析。
到目前为止,我发现这个速度是可以控制的,我有精力在早上早起做额外的学习,晚上也一样。GA 建议您在周一至周五的 9-5 工作日之外再投入 20 个小时!
接下来的几周,随着理论变得越来越复杂,工作量开始增加,我的动力开始减弱,恐慌开始出现。“我究竟要怎样才能完成这一切,”我心想。在这个时候,我有一个项目,实验室会议和我的顶点项目工作。速度赶上了我,任务似乎不可能完成。我的理智开始下滑,我叛逆的一面开始出现,拒绝在晚上做任何自习!我几乎偏离了轨道,但不知何故我继续前进,这要感谢我用一些热瑜伽保持头脑冷静,偶尔喝一杯有益的红酒,并确保我有一个固定的休息日。
我现在已经是第十周了,感觉好多了。我的第四个项目已经提交,我只有我的顶点项目工作。我们已经涵盖了几乎 100%的课程,课程的最后两周没有课,这样你就可以进行你的顶点项目。
我也喜欢我职业生涯中新的社交方面。我正在悉尼参加每周一次的数据科学会议(外加免费披萨!).
现在回想起来,我可以欣赏我学到的大量知识,从 python 编程到 SQL,从数据分析到机器学习。我才刚刚开始我的新道路,但我对我在数据方面的未来感到兴奋!
这门课的经历和我一路上遇到的人,真的让我看到了一个不同的世界,一个我无法想象的世界。但现在我有信心将我所学的一切付诸实践,并开始研究数据分析中的角色和进入数据科学的长期途径。看好这个空间!
Image by General Assembly
如果你正在考虑学习数据科学课程,十条建议:
- 准备好快速学习很多东西吧——你肯定会从一套自然的数学技能中受益
- 在本课程中,你的社交生活将会退居其次,我不建议你预定任何节日或周末外出
- 去见 ups。当你在找工作时,不仅仅是你知道什么,而是你认识谁!…打入“隐性就业市场”
- 警告你所爱的人,这将会占用你很多时间,你可能会有压力
- 先学 python,因为整个课程都是用 python 教的,所以差别很大。强烈推荐 Codacademy 和 Data Camp
- 复习一下你的统计数据。有些人没有意识到这门课程大量基于统计学
- 在课程中使用 Stat Quest 作为资料来源——统计学和机器学习理论的优秀学习资料来源
- 花点时间在课程之外学习 SQL 和 Tableau,最好是在课程开始之前。这是目前就业市场对数据分析师的需求
- 想一想你想从事什么行业,将你的顶点项目向这个方向排列
- 周日休息一天,我对自己的规定是,如果我周六去 GA 学习了一整天,我就可以周日休息
Image by MoteOo from Pixabay
与机器对话
语言、人工智能和下一个用户界面
德克·克内梅尔和乔纳森·福利特
在我们和我们的计算设备之间是用户界面,或 UI。我们与机器交流的方式,以及机器与我们交流的方式,对于我们整体用户体验的质量至关重要。对于人工智能来说,这一点再正确不过了。人工智能软件的增强能力不仅依赖于我们向机器提供的正确数据,还依赖于机器解释这些数据的复杂程度。
除非我们与机器交流,否则机器不会工作——无论是与一个人操纵机器的显式控制,还是隐含在机器的形式中,以特定的方式实际上只是“做”。用我们最早的机器,这一切都很简单。想象一下算盘,它要求操作者仅具备简单的数学知识,并能够使用手指或类似装置来回移动珠子。与我们的机器和技术最早的接口是具体的、物理的和直接的。
Figure 01: The earliest interfaces with our machines and technology were concrete, physical, and direct.
[Photo: Multicolored Abacus by Crissy Jarvis on Unsplash]
随着机器变得越来越复杂,这种情况发生了变化。印刷机需要用到打字机,打字机需要用到电脑键盘。穿孔卡在今天已经过时了,但是仅仅在几十年前,这项技术——可能起源于 1725 年巴西勒·布琼的和对织布机的控制——才发展到加速早期的机械计算,与键盘一起成为计算机用户界面的两个最重要的设备,更不用说穿孔卡在数据存储和检索中的更大作用了。直到 20 世纪 80 年代,随着苹果电脑和图形用户界面的兴起,鼠标才成为核心用户界面设备,而就在 10 多年前,移动计算的手势约定帮助将计算从工作场所或有时的活动变成了我们今天在美国体验的无处不在的东西。
重要的是要记住这一切都是最近发生的。在历史计算生态系统中,穿孔卡片比鼠标有更丰富的历史,即使是鼠标提供的可用性帮助计算成为主流。我们所处的时刻转瞬即逝,我们可能会在几年而不是几十年后远离鼠标,因为我们知道它正在转变为一个外围角色。昨天看似永恒的东西明天就会过时,而我们甚至没有意识到这一点。
Figure 02: Punched cards evolved to accelerate early mechanical computing
[Photo: Technische Hochschule Aachen (Technical University of Aachen) by Jens Gathmann, German Federal Archives (1970) on Wikimedia Commons]
今天,当我们与机器交流时,我们仍然在很大程度上使用我们的手指和手——拉、推、翻转、打字、点击和滑动。虽然这种模式可行,但它不是最优雅或最强大的交流方式。它要求我们与之交流的机器——在这种情况下,机器是你正在使用的软件和你正在使用它的硬件设备的综合体——特别好地定向,以得到你确切想要的东西。像一首你很久没有听过的最喜欢的歌,可能需要腕管综合征诱导的大量点击才能从听这首歌的冲动中得到实际播放。这并没有说明它所花费的时间,根据您的计算和网络环境,可能不只是几秒钟,而是几分钟。
如果处理得当,为支持语音的人工智能抛弃图形用户界面会好得多。这也是 Alexa 和 Siri 这样的技术如此令人兴奋的原因之一。在最好的情况下,用户界面被简化为一个语音命令。只需要一秒或几秒钟,在这段时间里,你的大脑和身体不再需要考虑这个请求。对于用户来说,过去的图形用户界面和繁琐的架构和层次管理,现在只是一种愿望的口头表达。尽管无缝的人机连接是最理想的,但目前,这样的交互还远非易事。或者说,说起来容易,但得到正确的结果似乎很难。与机器交谈会给我们带来很大的挫败感:Alexa,这样做。Siri 会这么做。不,不要做这个,请做那个。
自然语言处理
因此,自然语言处理(NLP)已经成为当今最重要、发展最快、人工智能必不可少的技术之一。简而言之,这就是计算机处理和分析自然语言数据的方式——尤其是我们的语音。NLP 是人工智能如何与我们交流并为我们工作的一项支柱技术。在不久的将来,自动化将在许多方面受到 NLP 的推动。鉴于每个语音用户界面和人工智能的能力和潜力,机器解释并使用自然语言——特别是口语——的能力必须是有效的。
为了更好地理解 NLP,我们采访了曾在 SYSTRAN 和 Adobe 等公司工作过的研究员兼计算机科学家 Shivali Goel。“NLP 是人工智能的核心技术之一。你可以把它看作语言学和计算机科学的完美结合,”戈尔说。“这基本上是让机器有能力理解一个人说话或打字时的意思。NLP 是关于克服语言中的歧义,理解意图和上下文。比如我说‘小孩做营养零食’,你懂什么?孩子们在煮有营养的东西吗?或者它们本身就是一种有营养的小吃。”
NLP 算法检查并利用这些数据中的模式。他们理解单词关系和文字游戏,并模拟类似人类的对话。所以,当你要求谷歌播放舞曲时,那就是 NLP。当你打开一个外国网页,它被翻译成你的语言,这就是自然语言处理。当你的 Wi-Fi 无法工作,你试图向虚拟助理解释你的问题,或者只是大喊“代理!代理人!在电话里也是 NLP。相信我,我们正在努力改进。"
语音是我们最自然的输入设备。这是我们与他人交流的主要方式,几千年来一直如此。NLP 是一种将我们的声音翻译成最适合机器使用的技术。在其理论的顶点,NLP 会解释我们的单词、节奏、语调和其他因素,将其转化为对我们意图的细微理解。正如 Goel 指出的那样,如今,it 部门甚至常常无法找到一个简单的电话决策树。尽管如此,在其更好的体现中,这项技术似乎像魔术一样理解和响应。一个例子是谷歌的双工服务,它使用人类的声音为主人预约。这不仅仅是一种便利,它还是另一种技术,令人毛骨悚然地模糊了真假之间的区别。
NLP 的另一个很好的例子是机器翻译。“机器翻译系统可以帮助学生学习外语,”Goel 说。“翻译人员还不足以与人类相匹配或取代教师,但这些系统肯定可以补充教学。此外,许多在线资源和电子书可以被翻译成不同的语言,以便更多的人可以从学习中受益……”
语音作为界面输入确实有其局限性。特别是,有许多重要的用例可能会变得困难,因为它在非私人空间中使用的侵入性质。“我必须说,我不认为语音用户界面在公共领域会有什么前途。《合格的自己》一书的作者、康奈尔大学传播学系副教授李·汉弗莱斯说:“我认为我们看到的是在公共场所的视觉和文本交流的增加。21 世纪初,Humphreys 在美国开展了第一项关于公共场所使用手机的研究。“我做了一项观察研究,我出去观察人们……使用他们的手机。这项研究真正吸引人的一点是,人们在打电话时试图保持私人交流的方式。所以,他们会低下头。他们可能会用手捂住嘴。他们用各种方式来保持谈话的私密性。但(同时)他们的声音可能会侵犯公共场所其他人的隐私,”汉弗莱斯说。《英国医学杂志》甚至将 21 世纪初的打手机等同于二手烟,是空气中的一种社会污染物。…我真的认为在某些情况下,声音的作用是非常困难的。作为一种公共空间,你可能会在汽车里看到它。然而,你在这个小泡泡里,你想跟着收音机或 Spotify 或其他什么东西唱歌,那就去做吧。或者,你可以口述一些东西。所以,我认为这是一个地方,除了家庭空间之外,更多的是在公共空间,在那里你可能会看到声音形式的交流。”
Figure 03: There are many important use cases for voice UI that can become difficult because of the intruding nature of its use in non-private spaces.
[Photo: Railway Station From Above — Bern, Switzerland by Timon Studler on Unsplash]
更普遍的语音用户界面是有前途的,但它需要其他技术的加入。围绕语音 UI 已经有了一些有意义的工作,它可以记录用户的低语或嘴部动作,而不是与他人交谈时所需的大声说话。要充分利用语音作为主要的界面范例,需要这些或其他一些进步。
“语音界面现在实际上开始与视觉界面融合。现在有一种新的趋势,我们把带有屏幕的电子产品送回家,这些屏幕连接到许多这样的音响系统上。亚马逊最近发布了 Echo Show ,它有一个带前置摄像头的屏幕。它[不仅]说,“播放下一首歌”,我们实际上可以看到专辑封面和它的名字,有时甚至可以看到它后面的图形或动画。它变得越来越具有互动性和沉浸感,”Lee 说。
最有趣的人工智能应用将是那些与我们日常生活交织在一起的应用。为了最好地做到这一点,机器需要理解我们想要什么,或者不想要什么。这又回到了用户界面,以及我们如何向机器输入命令。在这方面,声音和视觉的结合是重要的一步。大约 17 年前,我们从未接近过电影《少数派报告》中的沉浸式计算环境。当时,这被吹捧为未来,一个基于未来学家和技术专家的输入的虚构描绘,他们知道事情将如何演变,很快。我们还没有到那一步。事实上,我们的现实甚至感觉不到接近。然而,将改进的语音界面与我们的显示环境相结合是这条道路上的一步。
Lee 认为 UI 将演变成更加被动和自动化的输入:“我个人的观点——我希望行业能这样发展——是这个系统不那么单向,我告诉机器做一些事情,而更多的是一个反馈循环,我偶尔会请求我的 Siri 改变日历,或者检查我的邮件。但实际上,该系统有许多不同的传感器和许多不同的输入来读取我的行为。”这无疑是一种最佳的机器模型:被动地利用网络上所有可用的数据,然后以对每个独特的人来说最佳的方式自动化环境和体验。
Creative Next 是一个播客,探索人工智能驱动的自动化对创意工作者,如作家、研究人员、艺术家、设计师、工程师和企业家的生活的影响。本文附 第二季第一集— UI 与人工智能 、 第二季第二集—社交媒体的起源 、 第二季第三集—自然语言处理 。
与伯特交谈
改进提示以更好地理解语言模型
Photo Mashup w/ Anna Vander Stel X Rock’n Roll Monkey
在过去的几年中,围绕语言模型的知识和研究的增长是惊人的。特别是对 BERT 来说,我们已经看到了这种大规模预训练语言模型在文本分类、预测和问题回答等任务中的一些令人难以置信的用途。我最近写了关于一些人如何研究 BERT 在执行某些语言任务时的局限性。此外,我自己做了一些测试,用创建了一个问答系统,来感受一下如何使用它。在实践中看到并尝试语言模型的许多功能是非常棒的。
当你认真对待它时,这些模型显然有很多关于单词和想法之间关系的信息,但很难真正检查它知道什么。我最近探索了一篇名为的有趣论文,我们如何才能知道语言模型知道什么?看看我们如何向语言模型提问。像任何语言一样,这不仅仅是你问什么的问题,而是你如何问的问题。
研究团队工作的主要目标是研究我们如何有效地从语言模型中提取知识。当我们想探究一个语言模型可能包含什么关系信息时,我们使用提示,比如“柯基是一种 __”。类似这样的提示通常可以手动创建。他们的实验测试了创建不同的提示,并在 BERT 上进行测试,看看是否可以通过改变提示的措辞方法来提高性能。
让我们开玩笑说,我们用来自wookiepedia的所有重要信息创建了一个语言模型(你没看错,这是一个关于《星球大战》所有内容的维基,真的令人印象深刻)。类似这样的提示:
"卢克·天行者认为 ____ 是他的出生地"
是一种效率较低的提问方式:
"卢克·天行者出生于 ____ "
既然如此,我们就知道,如果我们想知道其他人的起源,最好像第二个那样来组织我们的提示。研究小组根据他们的成功特别注意到了两种主要的方法来形成提示以改善结果:
基于挖掘的方法
正如他们在论文中提到的,这种方法是对先前问答系统研究中提到的基于模板的方法的一种尝试。这种方法基于这样一种思想,即在大型语料库中,文本通常被结构化为主题 > 特定关系 > 对象。他们从维基百科语料库中挖掘所有使用这种格式的句子,以创建一组更灵活的提示,例如:
(主语)出生于(宾语)
正如您所想象的,使用语料库中更具体的关系措辞会使语言模型更容易得出符合事实的答案。虽然您可以手动给出类似的提示,但是它们的表现不如这种方法。
在我的 Wookiepedia 语言模型的例子中,我可以在语料库中挖掘类似的格式,也许我会找到短语“皮耶特拥有海军上将军衔”,我可以推断为 (x)拥有(y) 的军衔,这可能会帮助我制定更有效的方法来检查其他帝国军官的军衔。
基于释义的方法
所以我们有一个挖掘的提示,就像我们的 (x)有一个(y) 的秩,但这显然只是陈述关系的一种方式。转述是为了提高用来表达这种关系的词语的多样性,但不要偏离提示。这可以手动完成,但研究小组使用了反向翻译方法,将提示翻译成不同的语言,然后再翻译回来。他们工作中的一个例子是:
x 与 y > x 有共同的边界,x 与 y 相邻
外卖食品
总的来说,这项研究指出了一种比手动提示更好的查询语言模型的方法。从本质上来说,在某种程度上,说一种类似于模型的语言可以改善它理解你的问题的方式是有意义的。我很想知道,如果你有一个纯粹根据人们自然说话的文字记录训练的语言模型,这样的东西会是什么样子。表现最好的提示类型是手动的还是挖掘的?只是一些疯狂的想法!我强烈推荐阅读这篇论文,这是一个非常有趣的研究。
用经验贝叶斯驯服错误发现
如何在噪音海洋中安全捕鱼
Watch out for false discoveries when fishing in a sea of noise
今天的数据科学家有大量的数据可供他们使用。但他们也面临一个新问题:有这么多功能可供选择,我们如何防止错误的发现?
p 值有助于错误的发现。假设没有影响,运行 100 个独立的 p 值测试平均会产生 5 个阳性结果。被误导 5 次是可控的,但是如果我们运行数百万个假设测试,情况很快变得无法忍受。
我们需要一种方法来控制我们发现的假阳性的数量。它应该与我们运行的假设数量成比例,并允许我们对我们的整体发现有信心。
场景
你在一家大数据科学公司工作,该公司的业务是预测赛马的结果。您和您的同事收集马、体育场、骑师等数据,然后构建模型。这些模型反过来会影响赌博策略。随着时间的推移,你和你的同事已经开发了 60,000 个策略。你的任务是找到真正胜率在 50%以上的策略。虽然这当然是一个简化的问题,但有许多应用非常接近,例如神经科学中的fMRI、遗传学中的微阵列和金融中的阿尔法测量。
下面你看到的数据:n_games
描述了一个策略下的赌注数量。won
描述策略获胜的频率,ratio
是获胜游戏的份额。因为这是合成数据,我们知道一个策略的真实比率是否在 50%以上。在现实生活中,您可能无法访问true
值,但它在以后会很有帮助。
下图显示了所有策略的观察胜率分布。如你所见,有不少策略的胜率超过 0.5。
问题是,大多数观察到的胜率很高的策略只是偶然显示出来。我们知道大多数策略的胜率不会超过 0.5。这在我们的数据中显而易见。我们需要找到一种方法将这种间接证据纳入我们的结果。18 世纪的某个 Bayes 牧师思考过这个问题,这是件好事。
信仰问题
本文中介绍的概念大致属于贝叶斯统计领域。关键的概念是,我们不仅对数据的分布感兴趣,而且对真实的、未观察到的值的分布感兴趣。每个策略的真实胜率是无法观察到的。但是我们可以估计一下真实的胜率是多少。因为我们对自己的估计没有 100%的把握,所以我们认为多个值可能是真的,但是不要给所有的值分配相同的概率。
在日常生活中,我们凭直觉做到这一点。如果我问你明天撒哈拉的天气,你会说:“可能是晴天,那里几乎不下雨”。
我们在看到任何数据之前的信念被称为先验信念(在看到数据之前)。你对撒哈拉天气的信念是在没有任何撒哈拉天气信息的情况下形成的。
一旦我们观察到数据,我们就可以更新我们的信念。如果我告诉你,撒哈拉上空出现了巨大的雨云,气象学家对十年一遇的事件感到兴奋,你对天气的回答会改变。你可能会说“也许会下雨,也许不会。50/50".这个新的和更新的信念被称为后验信念(后验,又名 after,指看到的数据。花式古英语)。
数学上,贝叶斯定理制定了一个更新规则,所以我们不仅可以直观地更新我们的信念,还可以定量地更新。为此,我们需要数据,更重要的是,需要先验知识。
经验贝叶斯
回到我们的投注策略,我们之前对投注策略胜率的信念应该是什么?在撒哈拉的例子中,基于我们对沙漠的了解,我们有很强的先验知识。在下注的例子中,我们只有数据,没有先验信息。
经验贝叶斯方法背后的关键思想是使用我们所有的数据形成我们的先验,然后使用来自特定策略的数据形成关于不同策略的真实胜率的后验信念。
在我们的例子中,我们假设我们对策略胜率的信念可以用 Beta 分布来表达。这意味着我们认为不存在一个真正的胜率,而是胜率的分布。该分布可以用两个参数α和β来描述。我们可以使用 scipy 的 beta 函数来推断产生我们的数据的最可能的值:
alpha_prior, beta_prior, _, _ = ss.beta.fit(df['ratio'], floc=0, fscale=1)
有了α和β先验知识,我们可以从先验知识中取样,看它是否与数据相匹配。下面你可以看到蓝色的数据和橙色的推断先验分布。
我们还可以在此先验下计算平均胜率:
prior = alpha_prior / (alpha_prior + beta_prior)
print(f'Expected win ratio under prior: {prior*100:.2f}%')Expected win ratio under prior: 44.27%
我们能这样评估先验吗?
让我们回到这里,因为我们刚刚做的有一些编造的统计的天赋。因为我们缺乏根植于知识的先验,我们就…编造了一个?那不可能是对的。但是这有一种直觉和数学逻辑。你怎么知道撒哈拉沙漠很少下雨?你可能读过某个地理学家写的东西,他依赖于几个世纪以来人们的观察,甚至可能是几千年前的人工制品。基于所有的数据,地理学家形成了撒哈拉沙漠很少下雨的观点,你相信了。相信收集了大量数据的地理学家和我们自己收集数据的过程有什么不同?
有一个潜在的区别,那就是地理学家收集的数据与我们的研究对象相关,但最终是独立的。这位地理学家并没有收集明天 T4 是否会下雨的数据,只是收集了撒哈拉的总体天气数据。同样,如果我们想使用其他策略的数据来为任何特定策略的决策提供信息,胜率必须相互独立。这也是数学论证做出的一个关键假设(技术术语是数据必须来自平行情况)。它也必须足够大)。
更新我们的信念
既然我们努力工作来形成先验,是时候使用关于个体策略的数据来形成后验了。对于测试版,更新规则相对简单。alpha 参数的后验值等于策略赢得的游戏数加上 alpha 的先验值。
df['alpha_posterior'] = df.won + alpha_prior
beta 参数等于策略输掉的游戏数加上 beta 先验。
df['beta_posterior'] = (df.n_games - df.won) + beta_prior
下图显示了从数据推断出的先验分布(蓝色)和一个特定策略的后验分布(红色)。正如你所看到的,这个策略的大部分后验值都高于要求的胜率。换句话说,大多数我们认为可能的真实胜率都在这条线上。
收缩
因为我们在估计每个策略的真实胜率时考虑了总体平均胜率,所以我们将估计值“缩小”到大平均值。经验贝叶斯是一种所谓的“收缩”方法。正如我们将在后面看到的,这正是帮助我们减少错误发现的原因:我们使我们的估计偏向于一无所获。
为了可视化收缩,让我们计算每种策略的平均后验胜率:
df['eb_ratio'] = df.alpha_posterior / (df.alpha_posterior + df.beta_posterior)
下图显示了数据中的胜率分布(蓝色)和所有策略的估计真实胜率分布(红色)。如您所见,估计值都更接近平均值,并且估计胜率超过要求(红线)的策略明显更少。
当然,并不是所有的估计都缩小了相同的数量。我们希望拥有更多数据的策略(比如,我们在更多游戏中尝试了哪些策略)比只有很少数据的策略减少的估计要少。这正是正在发生的事情。贝叶斯规则考虑了我们拥有的可能与先验不同的后验证据的数量。
下面的图表显示了收缩率和我们拥有的数据量之间的关系。红色实线是观察到的胜率是估计胜率的线。如果一个点在红色实线附近,就只有很小的收缩。红色虚线是先验。绿点是我们有很多数据的策略,蓝点是我们只有很少数据的策略。
如您所见,具有少量数据(蓝色)的策略更接近先验值,而离观察值更远。我们拥有大量数据(绿色)的策略向先验收缩得更少。
错误发现率
正如我们前面所看到的,我们不仅仅估计每种策略的真实胜率。我们估计了我们认为可能的胜率的整个分布。这是很多额外的工作,但它大大简化了我们来这里的问题:“这种策略是错误发现的可能性有多大,真正的胜率低于 0.5?”
为了回答这个问题,我们可以问自己:“对于我们的策略,我们的后验信念分布的多大份额低于 0.5?”
下图显示了策略的后验置信分布。红线是 0.5 的关键关卡。橙色区域显示低于障碍的信念分布部分。在我们的信念下,真实胜率小于 0.5 的概率就是橙色区域。
我们可以用 beta 分布的累积密度函数计算面积,从而计算出这种策略是错误发现的概率。
print(f'The probability that this strategy is a false discovery is {ss.beta.cdf(0.5,60,50)*100:.3} %')The probability that this strategy is a false discovery is 16.9 %
这种方法可以应用于所有策略,以找出它们是错误发现的可能性:
df['FDR'] = ss.beta.cdf(0.5,df.alpha_posterior,df.beta_posterior)
管理总体错误发现率
现在我们该如何选择下注的策略呢?我们可以简单地选择那些错误发现概率低的策略。但是我们可以做得更好。由于期望的线性,多个策略的期望错误发现率是被错误发现的个体概率之和。例如,如果我们有 10 个策略,错误发现的概率为 1%,那么这 10 个策略中错误发现的预期份额为 10%。
因此,我们可以选择哪些错误发现是可以接受的。比方说,在我们的博彩业务中,如果我们部署的博彩策略中有 5%的真实胜率不高于 0.5,我们就没事。然后,我们可以根据策略被错误发现的个别概率对它们进行分类,并选择那些累计错误发现率为 5%的策略。
accepted = df[df.FDR.cumsum() < 0.05]
由于这是合成数据,我们可以检查它的效果如何,事实上,我们发现大约 5%的策略实际上没有足够的胜率。如您所见,我们的估计非常接近!
print(f"The actual false discovery rate is {(len(accepted[accepted.true == 'no']) / len(accepted)*100):.2f}%")The actual false discovery rate is 5.26%
收场白
在本文中,您已经看到了经验贝叶斯框架的基本构件,以及如何使用它来管理错误发现率。
经验贝叶斯属于一个更广泛的收缩方法家族,它们都是正则化的方式。规则化是常见的 主题在机器 学习所以你可能之前在 ML 的上下文中遇到过。每当你冒着做出错误发现的风险时,无论是深度学习模型中的一组过度拟合的参数还是一个不起眼的胜率,让你的发现偏向于一无所获都是有用的。通常,这与经验贝叶斯密切相关的方法一起工作,例如在岭回归中。
随着数据科学进入越来越多的高风险应用,错误的发现或过度拟合的模型可能会产生灾难性的后果,正则化变得越来越重要。
进一步阅读
Jupyter 笔记本的所有代码可以在这里找到。这篇文章是我为 Bradley Efron 和 Trevor Hastie 的“计算机时代的统计推断”所写的学习笔记的一部分。埃夫龙还写了一本纯粹关于经验贝叶斯的书《大规模推理》。大卫·罗宾逊写了一个更加代码驱动的介绍。我的作品《金融领域的 ML》,在金融背景下讨论了文中提出的一些问题。
利用人工智能挖掘数据金矿——现场服务物联网设备
Source: Shutterstock
现场服务物联网设备正变得比以往任何时候都更加智能和用户友好。用户能力以及与后端供应链运营的联系更强了,但还有一层尚未完全实现,即现场服务数据。当利用人工智能时,物联网现场服务设备成为无与伦比的数据收集资产,可以帮助在企业的各个方面做出明智的业务决策。
但是仅仅利用这些数据是不够的。企业需要了解如何优化每个数据点,以最大限度地发挥其潜力。通过现场服务物联网集成收集的每个数据集都有无限的潜力来积极影响整个供应链的流程和体验,从客户体验的重新构想到售后工作的后端优化,等等。
用人工智能预测终端用户问题
最终用户设备和后端供应链之间的连接是通过现场服务物联网集成实现的。设备的安装、管理、维护和维修都是通过现场服务技术人员、他们的现场服务物联网工具和总部供应链之间的高速连接来完成的。
企业已经成功地利用和了解终端用户设备数据,以维持产品正常运行时间并优化现场服务安排,但现场服务流程(即物联网设备本身)会自行生成大量数据。这种未利用的数据可以用来帮助优化现场服务物联网功能,并帮助简化现场服务维修流程本身。
例如,有线电视提供商利用他们的现场服务团队来维护和安装有线电视盒、路由器等。如果你问消费者,许多人会说这些过程缓慢且不方便。不一定非要这样。通过人工智能和人工智能的集成,现场服务物联网设备将能够利用关键数据集来了解客户的个性化需求。通过不仅评估设备的状态,而且评估最终用户的历史、环境影响和其他变量,现场服务技术人员将能够在到达现场之前准确查明问题的原因以及如何解决问题。他们将能够更快地处理更多的客户请求,最终用户也将从更加简化的维修流程中受益。
企业已经可以全面访问这些数据点。其中许多企业已经将这些数据点用于其他内部运营,例如在个人基础上创建超个性化的营销体验。但是,如果不用于优化和个性化其他计划,这些数据也会被浪费。遗留的现场服务操作是上述数据被忽视的明显例子。如果采取行动,这些数据可以为现场服务技术人员和最终客户等提供以前无法想象的便利和用户体验。
能源浪费优化
现场服务物联网创新不需要只让消费者受益。企业也可以利用高科技创新来破坏建筑管理物联网设备。以数据中心为例。这些中枢每天都会产生大量的能量和热量。物联网设备是控制环境以保持机器可操作性和保持员工舒适所必需的。
通过利用人工智能,物联网建筑管理设备可以保持数据中心员工的最佳工作条件,以及保持事物运行所需的技术。此外,不仅条件更加舒适,能源消耗也可以通过惊人的数字减少(在 TCS,当集成物联网建筑管理设备时,我们的能源消耗减少了近 40%)。人工智能和物联网使企业能够了解什么需要运行以及何时运行,并消除任何不必要的停机时间,从而节省能源、金钱和改善工作条件。
挑战企业构建数字基础设施
这种类型的数据优化不会一蹴而就。特别是对于大型电信提供商,有几十年来保持事情顺利进行的支柱。也就是说,创新并没有放缓,那些选择无所事事的人最终将被甩在后面。数据已经在那里了。这些组织每天都在收集这种情报,但没有技术基础设施来优化上述数据集的用例。人工智能是找到充分利用这些数据的方法的关键。
人工智能虽然不一定是一项新技术,但仍在研究中,尚未被完全理解。组织有一个长期的基础架构,它建立在手动流程的基础上,很难彻底改变。组织需要迈出这一步,迎接创新带来的风险。只有这样,他们才能从成功的数字化转型中获益。基础设施需要从头开始重建,以数字技术为核心。在商业 4.0 时代,这一改革对成功至关重要。业务的所有方面都必须接受风险、利用生态系统、创造指数级价值并变得高度个性化,包括现场服务工作。
—
现场服务管理是一个产生大量数据的过程,而这些数据的利用率严重不足。人工智能将帮助企业了解如何利用这些数据,并使用它们来创建以前无法想象的最终用户体验和后端优化。
目标香港:快速了解中国在推特上的造谣活动
这是对 8 月 19 日推特发布的中国国家巨魔推特的快速浏览。未来几天和几周还会有更多。
An example of Chinese state troll tweet exposed by Twitter on Aug 19.
8 月 19 日, Twitter 发布了一组新的官方微博,该公司称这些微博来自“一个重要的政府支持的信息行动,关注香港的局势,特别是抗议运动和他们对政治变革的呼吁。”
这些推文值得更深入的研究,显然可以利用这些材料做更多的事情。我之前参与了一个关于揭露推特上虚假信息的项目。
由于时间限制,这里有一个快速和肮脏的第一次探索性的数据。未来几天和几周还会有更多。
1。数据、笔记本和假设
我的粗略笔记本是这里,回购将会更新,因为我找到更多的时间来做这个项目。
CSV 文件太大,无法上传到 Github 上。直接从推特下载。
为了在这个阶段控制项目的复杂性,我过滤掉了转发,这是一个值得单独研究的有趣领域。我也只关注英文和中文微博。信不信由你,这个数据集中的推文有 59 种语言。
2。总体来看中国国家巨魔推文
Twitter 表示,其发布的推文来自“936 个来自中华人民共和国(PRC)的账户。总体而言,这些报道是蓄意和有针对性地试图在香港制造政治不和,包括破坏当地抗议运动的合法性和政治立场”。
已经暂停的账户“代表了这场运动中最活跃的部分;一个约有 20 万个账户的更大的垃圾邮件网络”,Twitter 在其新闻稿中补充道。
以下是我快速浏览后发现的关键数据:
Unique userids: 890
Unique user display names: 883
Unique user screen names: 890
Unique user reported locations: 178
Unique user creation dates: 427
Unique account languages: 9
Unique tweet languages: 59
Unique tweet text: 3236991
Unique tweet time: 1412732
Unique hashtags: 110957
在我过滤掉即时战略和语言之后,巨魔推文的数量从最初的 360 万减少到了 581,070 条。太咄咄逼人?也许吧,但是还有很多工作要做。
3.典型的中国官方推特
首先,让我们快速浏览一下这些针对香港的中文和英文官方推特:
The phrasing of some tweets would be immediately familiar to those who follow official Chinese rhetoric and its state-driven Internet commentary. Phrases like 外國勢力(foreign forces) are not commonly used elsewhere, if at all.
4。主要中国巨魔账户
以下是我筛选过的数据集中排名前 10 位的巨魔帐户:
曲剑明 54455
阿丽木琴 46600
Klausv 34451
春天里 17989
gwalcki4 17707
emiliya naum 16230
derrickmc 16163
Lily Mann 14673
炫彩 14604
mauricerowleyx 11749
It is far more interesting to look at specific accounts, in my view. Let’s start with the one at the top of the list: qujianming, or 曲剑明.
在我的过滤数据集中,这个 troll 帐户发出了 19614 条独特的推文。该账户创建于 2012 年 6 月 28 日,拥有 28405 名关注者和 24079 名用户——这是一个可疑的高数字,也是一个巨魔账户的主要迹象。
该账户在 2019 年发了 77 条推文。一些样品:
- 2019–07–05: ‘香港作为一个法治社会的典范,这种暴徒行径一定要严惩,换民众一个公道’
- 2019–07–04: ‘反对势力想尽办法想搞乱香港,想等混乱的时候谋取利益,他们根本就无暇顾及市民的利益,可怜的是还…’
- 019–07–02: ‘#HongKongProtest #香港 #七一 #游行 #民阵 7 月 1 日反对派宣扬暴力冲击…’
Twitter also highlighted two accounts in its press release, one of which is HKpoliticalnew, or HK 時政直擊:
在我过滤后的数据集中,这个 troll 账户只发出了 1059 条独特的推文。该账户创建于 2015 年 1 月 22 日,拥有 22,551 名关注者和 66 名用户。增选新闻机构身份的举动完全是俄罗斯互联网研究机构的剧本。
该账户在 2019 年发送了 462 条“原创推文”,其中许多是针对香港抗议的。一些样品:
- 2019–06–21: ‘千名黑衣人圍堵立會,當中不乏重裝上陣的人,警方一定要嚴防,大家小心!👍💪\n\n#香港 #大專學界 #升級行動 #包圍立會 #重裝上陣 #警察 \n 原圖:星島日報 https://t.co/DIoiFWWkBo'
- 2019–06–20: ‘#香港 反對派一再散布失實資訊抹黑修例、誤導市民,更不斷造謠煽動情緒,企圖以網民壓力杯葛支持修例甚至只是沉默的商戶。\n 政府決定停止修例工作後,反對派又繼續播謠,稱換領智能身份證會「失去選民資格」,企圖撕裂市民對社會不同界別、團體、組織的信任。 https://t.co/9B3xCI9MWv'
- 2019–06–20: ‘反修例暴動後,#香港 仿佛又回到占中時期嘅黑暗日子,最令人痛心嘅系,執法者又再次成為黃營發泄嘅對象,黑警,「警你老 x」等言詞唔絕於意,立志以生命守護人民,卻落得過街老鼠嘅下場…\n\n 立法會議員何君堯律師呼吁各位市民站出嚟山席撐警集會,為 #警察 打氣,讓佢哋知,黃營所言非香港嘅主流聲音! https://t.co/yDpKt0mSAM'
5.自称的国家巨魔帐户的位置
像俄罗斯的国家巨魔一样,中国账户主要声称在美国:
Twitter 在中国被屏蔽。但该公司表示,“这些账户中有许多是使用 VPN 访问 Twitter 的。然而,一些账户从源自 mainland China 的特定未被封锁的 IP 地址访问 Twitter”。
6。巨魔账户创建于 2017 年 8 月达到峰值
正如所料,巨魔账户的创建时间要早得多——在 2017 年 8 月达到顶峰:
类似的推文数量在 2017 年达到峰值:
然而,对这些数据进行时间分析是很棘手的。首先,不清楚 Twitter 何时开始对巨魔账户采取行动。第二,不清楚中国国家机构是否有能力改变账号创建/发布日期,以掩盖其活动。听起来有些牵强,但时代就是这样。
END-NOTE,目前:
当然,分析将受益于 NLP 工具的广泛使用。但对推文的初步观察表明,需要更多的过滤来剔除噪音。中文推文必须与英文推文分开处理。我将在未来的笔记本中继续这一点。
为了节省时间,这就足够了。如果您发现任何错误,或者有任何意见,请 ping 我@
推特: @chinhon
领英:www.linkedin.com/in/chuachinhon
我早期的项目是关于推特上的虚假信息运动
因果推理的目标最大似然(TMLE)
一种双稳健的自动因果推理方法
什么是因果推断?
假设你有两种治疗癌症的药物,A 和 B。你在不同的人身上测试药物,现在你想衡量哪个更有效,你打算怎么测试?
你可能会先对患者进行随机化,给一半的患者服用药物 A,另一半服用药物 B,在一段时间内测试关键指标,以比较哪种药物降低了更多的关键指标。够了吗?
不。人们的一个常见误解是,只要随机化完成,我们就可以推断不同的治疗会导致不同的结果。这是不对的。随机化不能保证等价。这就是倾向分数匹配出现的地方。
那么什么是倾向评分匹配呢?
倾向评分匹配背后的想法是,通过给研究中的每个个体一个倾向评分,我们可以比较不同治疗组中的个体,并试图使个体尽可能等同,以便我们可以控制混杂因素,不同的结果将仅来自治疗。
现在,您可以看到,在研究中将药物用于个体之前,倾向评分匹配需要适当的实验设置。我们最终可能会放弃很多人,因为他们没有匹配的对手。如果我实验失败或者配对的数量太少怎么办?我们还能用我们收集的数据吗?
让我们仍然考虑之前的案例,我们有两组接受两种不同药物 A 和 b。我们的目的是测量平均治疗效果(ATE = E[Y(A = 1)]-E[Y(A = 0)],以便比较治疗效果。我们称患者的数据点为 X——它可能包含患者的年龄、性别、职业、收入、锻炼、吸烟与否等特征;测试指标 Y——我们关心的用于测试治疗结果的指标;处理 A 是用于两种不同处理的二元变量 0 和 1。
我们如何估计无偏的 Y(A=1)和 Y(A=0)来精确地测量具有最小混杂变量影响的治疗效果?
这里我将介绍一种最先进的方法目标最大似然估计(TMLE) 。目标学习是由 van der Laan & Rubin 在 2006 年 [1]提出的,作为一种自动化(而不是自己动手)的因果推理方法。TMLE 用于分析来自非对照实验的删失观察数据,即使在存在混杂因素的情况下也能进行效果估计。
以下是 TMLE 工作方式的分步指南:
第一步:生成 E(Y|A,X)的初始估计。 这就是我们所说的g-计算在因果推断中,它是一种基于极大似然的替代估计量,它依赖于给定暴露和协方差的结果的条件期望的估计。该估计器用于生成对应于 A=1 和 A=0 的潜在结果 Y₁和 Y₀。至于如何得到估计量,Mark 在论文中使用了“超级学习器”,本质上是一种集成学习方法。我会在以后的文章中更多地讨论 G-计算和系综方法。
现在我们有了估计量,记住这个方法是以治疗为条件的,只是假设其他变量对估计量有偏差,可以忽略。但这还不够稳健——我们需要“瞄准”治疗变量,并以更稳健的方式最小化变量偏差。
第二步。使用倾向得分 P(A=1|X)估计暴露机制。 给定观察到的联合创始人 x,我们计算暴露的条件概率。这与我们之前提到的人们用来匹配个体的倾向得分相同。在 TMLE 中,除了倾向得分,我们还计算了研究中每个人的π₁= P(A=1|X)和π₀ = 1-π₁。
第三步。更新 E(Y|A,X)的初始估计值。 在第一步中,我们通过 g 计算计算了 Y₀和 Y₁,现在我们需要对其进行更新,以减少混杂变量的偏倚。我们引入 H₀(A=a,x)= \frac{i(a=1}{π₁}—\frac{i(a=0}{π₀}.让我们更好地理解这一点——对于个人,我们计算 H₁=\frac{1}{π₁}和 H₀=\frac{1}{π₀}.有了每个人的 y,H₁和 H₀,我们可以拟合一个线性模型,假设截距是常数。
logit(e∫(y | a,X))=logit(Y_a)+𝛿×Ha,这里的𝛿是一个由两个值组成的波动参数(𝛿1,𝛿0)的模型。有了𝛿ˆ,我们可以产生 logit(Y₁)=logit(Y₁)+ 𝛿1×H₁和 logit(Y₀)=logit(Y₀)+ 𝛿0×H₀
第四步。生成目标参数的目标估计值。 用我们从上一步得到的每个个体的新 Y₁和 Y₀,我们可以计算出目标估计值 ATE=1\n ∑|Y₁-Y₀|.
我将在下一篇文章中更多地讨论 TMLE 与其他因果推理方法的比较,以及如何实现 TMLE。
直到下一次!
参考文献:
[1]范德兰&鲁宾,目标最大似然学习,2006
目标情感分析与传统情感分析
想要找到一个句子对该句子中的实体的情感吗?那么情绪分析对你来说可能还不够……请继续阅读,了解有针对性的情绪分析!
在某些情况下,我们可能不想从整个文本中提取情感,而是预测该文本对其中某个实体的情感。当这是我们的目标时,返回整个文本文档的整体情感的传统情感分析是不够的,我们需要开发一种更复杂的技术: 有针对性的情感分析 。在这篇文章中,我们将解释它们之间的区别,并用一些简单的例子来说明这种不同的行为。
那我们走吧!
打住,我不知道什么是情绪分析!
别担心,一如既往,我在你身边。情感分析是一种自然语言处理(NLP)技术,其中给定某个文本文档作为输入,我们得到这样的文本的情感(积极的、消极的,有时是中性的)作为输出。在某些情况下,我们甚至可以获得一系列的情绪,如非常积极、适度积极、中性、适度消极和非常消极。
这些模型通常来自两个不同的家族: 字典方法 和 机器学习方法。 前者利用具有正负极性的词典来推断文本是正的还是负的。这意味着寻找像*“好的”、“伟大的”、“惊人的”、“棒极了的”、“T15”或*“爱”这样的词,以查看文本是否是积极的,或者像“坏的”、“可怕的”、“可怕的”、“T19”或*“讨厌”这样的词,以查看文本是否是消极的。*
后者使用大量先前被标记为正面或负面的文本文档,从数据中学习哪些模式形成正面或负面文档,然后通过寻找这些模式来预测新文档的情感。
情绪分析有很多真实的用例:它可以用于跟踪企业在一段时间内的客户情绪,推断产品的可能性,社交网络用户对某些话题的看法,甚至预测总统竞选或颁奖仪式等事件的结果。
让我们看一些使用平行点在线情感分析工具的句子和情感分类的例子。
正如我们所看到的,对于每一句话,我们都得到了一个情感预测(正面的、中性的或负面的)以及对该预测的信心。置信度最高的情感是被挑选出来作为整个句子的潜在情感的情感。(如果你想知道,在写这篇文章的时候,我没有去过汉堡店,但是我很想去)
正如我们在这些例子中看到的,情感分析可以用来从一个句子中提取整体情感。然而,如果我们想要对文本文档中特定实体的情感,而不是整个文本的情感,会发生什么呢?考虑下面的句子:
汉堡店 还不错,但我这一天过得相当糟糕:我被老板吼了一顿,我吃了一块以为是巧克力片但其实是恶心的葡萄干的饼干,我还在地铁上滑倒了
假设我们想知道说话者对汉堡店的看法。 如果我们使用与之前句子相同的在线传统情感分析工具,我们会得到以下结果:
正如我们所看到的,因为该句子带有总体负面情绪,所以即使对汉堡店 的情绪是正面的,传统情绪分析的输出也是负面的。这是因为它不是分析对它的特定情感,而是分析整个句子的情感。
如果想要分析文本中对特定目标的情感,我们必须使用普通情感分析的变体,称为 目标情感分析。
有针对性的情感分析:发现对…的情感
目标情感分析所做的基本上是获取文本和该文本中的给定实体,并预测文本中反映的对该实体的情感。在前面的情况下,给定相同的句子,并且将汉堡 地点 作为目标实体,有针对性的情感分析模型将试图预测说话者对汉堡地点的情感,而不是整个句子的实际情感。
作为定向情感分析模型,我使用了刘和张的双向模型,分别来自、、、、、,其中*、预测对汉堡店*的正面情感,置信度在 80%以上。如果你不知道什么是 LSTM,你可以在我之前关于 NLP 的深度学习的帖子中找到。**
好吧,这很酷,但是有针对性的情感分析实际上可以用来做什么呢?嗯,它可以执行许多与传统情感分析相同的任务,以及一些更复杂的任务。例如,我在一个项目中使用它来分析对 Twitter 社交网络上某个主题的最重要个人的情感。我分析了像英国退出欧盟或奥斯卡这样的话题,发现了 Twitter 用户对这些话题中某些有影响力的人物的总体看法。考虑以下推文:
- “我不得不说,奥斯卡颁奖典礼很无聊,糟糕的主持人,糟糕的评论,以及尖锐的提名,然而**@ lady Gaga****看起来如此令人惊讶 beutiful❤#奥斯卡奖”**
- 今晚我对#NewsNight 上的**@ mait lis****再尊重不过了,口头上把所有级别的 sht 赶出了每一个被采访的完全被欺骗的议员,因为他们触发了 A50 离开我们# 2 周,直到彻底的灾难。去你们的。#英国退出欧盟"**
**
第一条推文使用传统的情感分析器,返回低置信度的负面标签,然而,如果使用有针对性的情感分析模型来分析对 @ladygaga 的情感,则返回超过 60%置信度的正面标签。第二条推文,当作为一个整体来分析时,具有非常强烈的整体负面感觉,然而,如果用有针对性的情感分析来分析对 @maitilis 的情感,我们再次获得正面标签,并且具有很高的可信度。这两个结果都与我们通过阅读推文所看到的相符。
在该项目中,我通过过滤不同的标签收集了大量关于每个主题的推文,找出了谁是被提及最多的用户(将他们定义为该主题中最有影响力的人物),并通过使用有针对性的情感分析模型计算了网络用户对这些有影响力的人物的总情感,其中推文的文本和该文本中被提及的用户作为模型的输入目标。
这些方法对企业非常有用,允许他们超越传统情感分析的限制,从现有数据中探索新的见解。
结论
在这篇文章中,我们看到了传统情感分析和有针对性的情感分析之间的差异,展示了它们可能被使用的不同场景。
在下一篇文章中,我们将探索不同的机器学习方法如何进行情感分析和有针对性的情感分析,深入探讨它们在特征和模型方面的差异。
非常感谢你的时间,不要担心,我不需要任何情绪分析就知道你看完这篇文章后很开心:)
如果你喜欢它,一定要在媒体、和上关注我,也可以在 LinkedIn 上和我联系,或者在 Twitter @ jaimezorno 上关注我。另外,你可以看看我在数据科学和机器学习方面的其他帖子这里。好好读书,保重!
TCAV:特征归因之外的可解释性
GoogleAI 的模型可解释性技术在人性化概念方面的概述。
How convolutional neural networks see the world
仅仅知道一个模型是否有效是不够的,我们需要知道它是如何工作的:桑德尔·皮帅
今天的重点正慢慢转向模型的可解释性,而不仅仅是模型预测。然而,可解释性的真正本质应该是让机器学习模型更容易被人类理解,特别是对于那些不太了解机器学习的人。机器学习是一种强有力的工具,伴随这种能力而来的是确保公平等价值观在模型中得到很好反映的责任。确保人工智能模型不会强化现实世界中存在的偏见也是至关重要的。为了解决这些问题,谷歌人工智能研究人员正在研究一种叫做 TCAV 的解决方案(用概念激活向量进行测试),以了解神经网络模型使用什么信号进行预测。
目标
Google Keynote (Google I/O’19)
在谷歌 I/O 2019 、**、**的主题演讲中,桑德尔·皮帅谈到了他们如何试图为每个人建立一个更有帮助的谷歌,包括为每个人建立人工智能。他重申,机器学习中的偏见是一个令人担忧的问题,当涉及到人工智能时,风险甚至很高。为了让人工智能更加负责和透明,他讨论了 TCAV 方法,通过这篇文章,我将概述这一方法以及它打算如何解决偏见和公平的问题。这篇文章在数学方面会很轻,所以如果你想更深入地了解,你可以阅读原始研究论文或者访问 TCAV 的 Github 知识库。
需要另一种可解释性技术
在 ML 领域,主要有三种可解释性技术:
Types of Interpretability Techniques
大多数情况下,你会得到一个由多年工程和专业知识创建的模型,你不能改变它的架构,也不能重新训练它。那么,你如何着手解释一个你毫无头绪的模型呢? TCAV 是一种旨在处理此类场景的技术。
大多数机器学习模型被设计成对底层特征进行操作,比如图片中的边缘和线条,或者说单个像素的颜色。这与人类更熟悉的高层概念非常不同,就像斑马身上的条纹。例如,如果您有一幅图像,该图像的每个像素都是一个输入要素。尽管可以观察每个像素并推断出它们的数值,但它们对人类来说毫无意义。我们不会说这个图像的第 5 个像素的值是 28;作为人类,我们总说图中有一条蓝色的河。TCAV 试图解决这个问题。
此外,典型的可解释性方法要求你有一个你有兴趣理解的特定图像。TCAV 解释说,这通常是真实的一类利益超过一个图像(全球解释)。
TCAV 方法
假设我们有一个模型,它被训练从图像中检测出斑马。我们想知道哪些变量在决定图像是否是斑马时起了作用。TCAV 可以帮助我们理解条纹的概念是否对模型的预测至关重要,在这种情况下实际上是肯定的。
TCAV shows that stripes are a critical ‘concept’ when deciding if an image contains a zebra or not
类似地,考虑一个根据医生图像训练的分类器。如果训练数据主要由穿着白大褂和听诊器的男性组成,则模型会假设穿着白大褂的男性是成为医生的一个重要因素。这对我们有什么帮助?这将带来训练数据中的偏见,其中女性的图像较少,我们可以很容易地纠正这一点。
那么什么是 TCAV 呢?
用概念激活向量(TCAV)进行测试是来自谷歌人工智能团队的一项新的可解释性倡议。概念激活向量(CAV)根据人类友好的概念提供了对神经网络内部状态的解释。TCAV 使用方向导数来量化用户定义的想法对分类结果的重要程度——例如,“斑马”的预测对条纹的存在有多敏感。
由 Been Kim 和 Martin Wattenberg、Justin Gilmer、Carrie Cai、James Wexler、Fernanda Viegas 和 Rory Sayres 开创的团队旨在让机器学习赋予人类的能力被它淹没。这是他对可解释性的看法。
工作
TCAV 本质上是从例子中学习概念。例如,TCAV 需要一些“女性”和“非女性”的例子来学习“性别”概念。TCAV 的目标是确定某个概念(如性别、种族)对已训练模型中的预测有多必要,即使该概念不是训练的一部分。
继续“斑马分类器”,考虑神经网络由输入 x ∈ R^ n 和具有 m 个神经元的前馈层 l 组成,从而输入推理及其层 l 激活可以被视为一个函数:
Testing with Concept Activation Vectors
- 定义兴趣概念
对于代表这一概念的一组给定的例子(例如,条纹)( a )或带有概念标签( b )和训练过的网络( c )的独立数据集,TCAV 可以量化模型对该类概念的敏感度。
- 寻找概念激活向量
我们需要在层 l 的激活空间中找到一个代表这个概念的向量。CAV 通过训练线性分类器来学习,以区分由概念的示例和任何层中的示例产生的激活( d )。然后,我们定义一个“概念激活向量”(或 CAV)作为超平面的法线,将模型激活中没有概念的例子和有概念的例子分开
- 计算方向导数
对于感兴趣的类别(斑马),TCAV 使用方向导数 SC,k,l(x)来量化概念敏感度( e )。这个 SC,k,l(x)可以定量地测量模型预测对任何模型层上的概念的敏感性
以下是在工作流程中使用 TCAV 的分步指南:
通过在 GitHub 上创建帐户,为 TensorFlow/tcav 开发做出贡献。
github.com](https://github.com/tensorflow/tcav/blob/master/Run%20TCAV.ipynb)
洞察力和偏见
TCAV 用于两个广泛使用的图像预测模型,即 InceptionV3 和 GoogleNet。
虽然这些结果显示了 red 概念对于消防车的重要性,但一些结果也证实了模型中对性别和种族的固有偏见,尽管没有明确受过这些类别的训练。例如:
- 乒乓球和橄榄球与特定的比赛高度相关
- 手臂概念比其他概念更能预测哑铃级别。
结论
TCAV 是朝着创建深度学习模型内部状态的人类友好线性解释迈出的一步,以便关于模型决策的问题可以根据自然的高级概念来回答。
TD3:学习用人工智能跑步
Photo by Sammy Wong on Unsplash
本文着眼于强化学习(RL)中最强大和最先进的算法之一,双延迟深度确定性策略梯度(TD3)( Fujimoto 等人,2018)。到本文结束时,您应该对是什么使 TD3 性能如此之好有了坚实的理解,能够自己实现该算法,并使用 TD3 训练一个代理在 HalfCheetah 环境中成功运行。
然而,在学习 TD3 之前,你应该已经对 RL 和常用算法有了很好的理解,比如深度 Q 网络和 DDPG,TD3 就是建立在这些算法之上的。如果你需要复习你的知识,请查看这些优秀的资源, DeepMind 讲座系列,让我们做一个 DQN ,旋转起来:DDP G .本文将涵盖以下内容:
- 什么是 TD3
- 每个核心机制的解释
- 实现和代码演练
- 结果和基准
完整的代码可以在我的 g ithub 上找到。如果您想快速了解这里使用的代码,请单击下面的图标,进入一个准备就绪的 Google Colab 工作簿。
TD3 是什么?
TD3 是深度确定性政策梯度(DDPG)的继承者(Lillicrap 等人,2016 年)。直到最近,DDPG 是机器人和自动驾驶等连续控制问题中使用最多的算法之一。虽然 DDPG 能够提供出色的结果,但它也有自己的缺点。像许多 RL 算法一样,训练 DDPG 可能不稳定,并且严重依赖于为当前任务找到正确的超参数(OpenAI Spinning Up ,2018)。这是由于算法持续过度估计 critic (value)网络的 Q 值造成的。这些估计误差随着时间的推移而累积,并可能导致代理陷入局部最优或经历灾难性的遗忘。TD3 通过专注于减少以前算法中出现的高估偏差来解决这个问题。这是通过增加 3 个关键功能实现的:
- 使用一对评论家网络(标题的孪生部分)
- 参与者的延迟更新(延迟部分)
- 动作噪音规则化(这一部分没有成为标题:/)
双胞胎评论家网络
TD3 增加的第一个功能是使用两个 critic 网络。这是受使用双 Q 学习的深度强化学习(Van Hasselt 等人,2016 年)中看到的技术的启发,该技术涉及使用单独的目标值函数估计当前 Q 值,从而减少偏差。然而,这种技术并不完全适用于演员评论方法。这是因为策略和目标网络更新得如此之慢,以至于它们看起来非常相似,这使得偏见又回到了画面中。相反,在双 Q 学习(Van Hasselt,2010)中看到的一个更老的实现被使用。TD3 使用限幅双 Q 学习,取两个 critic 网络中的最小值(两害相权取其轻)。
Fig 1. The lesser of the two value estimates will cause less damage to our policy updates. image found here
这种方法有利于低估 Q 值。这种低估偏差不是问题,因为低值不会像高估值那样通过算法传播。这提供了更稳定的近似,从而提高了整个算法的稳定性。
底线: TD3 使用两个独立的批评家网络,在形成目标时使用两者中的最小值。
延迟更新
Fig 2. Making our policy wait for a little while the critic network becomes more stable. Image found here
目标网络是一个很好的工具,可以将稳定性引入到代理培训中,但是在演员评论方法的情况下,这种技术存在一些问题。这是由政策(行动者)和批评(价值)网络之间的相互作用造成的。当一个糟糕的政策被高估时,对代理人的训练就会偏离。我们的代理策略将继续变得更糟,因为它正在更新有很多错误的状态。
为了解决这个问题,我们只需要比价值网络更少地更新策略网络。这使得价值网络变得更加稳定,并在用于更新策略网络之前减少错误。在实践中,策略网络在固定的时间步长之后更新,而价值网络在每个时间步长之后继续更新。这些不太频繁的策略更新将具有较低方差的值估计,因此应该产生更好的策略。
底线: TD3 使用 actor 网络的延迟更新,仅每 2 个时间步更新一次,而不是在每个时间步之后更新,从而产生更稳定和高效的训练。
噪声调整
TD3 的最后一部分着眼于平滑目标策略。确定性策略方法在更新 critical 时倾向于产生具有高方差的目标值。这是由于过度拟合值估计中的尖峰造成的。为了减少这种差异,TD3 使用了一种称为目标策略平滑的正则化技术。理想情况下,目标值之间应该没有差异,相似的行动得到相似的值。TD3 通过向目标添加少量随机噪声并对小批量求平均值来减少这种差异。噪波的范围被剪切,以保持目标值接近原始动作。
Fig 3. by training with the added noise to regularise the agents actions it favours a more robust policy. Image found here
通过将这种额外的噪声添加到值估计中,策略趋向于更加稳定,因为目标值为对噪声和干扰更加鲁棒的动作返回更高的值。
**底线:**计算目标时,剪切噪声被添加到所选动作中。这对于更健壮的动作来说偏好更高的值。
履行
这个实现基于本文中的原始回购协议。代码的主要部分包含在下面的完整的自包含笔记本中。这个实现是用 pytorch 写的,如果你不熟悉,我建议查看一些示例文档这里。所有网络架构和超级参数都与原始论文中使用的相同。下面是论文中的伪代码。虽然这可能看起来很复杂,但当你分解它,并通过数学方程格式时,它实际上是非常直观的。
Fig 4. TD3 algorithm with key areas highlighted according to their steps detailed below
算法步骤:
为了实现 TD3 算法,我将前面的伪代码分解成逻辑步骤,如下所示:
- 初始化网络
- 初始化重放缓冲区
- 选择并执行带有探测噪音的动作
- 存储转换
- 更新评论家
- 更新参与者
- 更新目标网络
- 重复直到有知觉
1.初始化网络
对于演员和评论家网络来说,这是一个相当标准的设置。注意,critic 类实际上包含了要使用的两个网络。critics forward()方法返回两个批评家的 Q 值,供以后使用。get_Q 方法只是返回第一个 critic 网络。
class Actor(nn.Module):
def __init__(self, state_dim, action_dim, max_action):
super(Actor, self).__init__() self.l1 = nn.Linear(state_dim, 400)
self.l2 = nn.Linear(400, 300)
self.l3 = nn.Linear(300, action_dim) self.max_action = max_action def forward(self, x):
x = F.relu(self.l1(x))
x = F.relu(self.l2(x))
x = self.max_action * torch.tanh(self.l3(x))
return xclass Critic(nn.Module):
def __init__(self, state_dim, action_dim):
super(Critic, self).__init__() # Q1 architecture
self.l1 = nn.Linear(state_dim + action_dim, 400)
self.l2 = nn.Linear(400, 300)
self.l3 = nn.Linear(300, 1) # Q2 architecture
self.l4 = nn.Linear(state_dim + action_dim, 400)
self.l5 = nn.Linear(400, 300)
self.l6 = nn.Linear(300, 1) def forward(self, x, u):
xu = torch.cat([x, u], 1) x1 = F.relu(self.l1(xu))
x1 = F.relu(self.l2(x1))
x1 = self.l3(x1) x2 = F.relu(self.l4(xu))
x2 = F.relu(self.l5(x2))
x2 = self.l6(x2)
return x1, x2 def get_Q(self, x, u):
xu = torch.cat([x, u], 1) x1 = F.relu(self.l1(xu))
x1 = F.relu(self.l2(x1))
x1 = self.l3(x1) return x1
2.初始化缓冲区
这是一个从 OpenAI 基线回购借用的标准重放缓冲区
3.选择带有探测噪音的动作
这是环境马尔可夫决策过程中的一个标准步骤。在这里,代理将选择一个添加了探索噪声的动作。
state = torch.FloatTensor(state.reshape(1, -1)).to(device)
action = self.actor(state).cpu().data.numpy().flatten()
if noise != 0:
action = (action + np.random.normal(0, noise, size=self.env.action_space.shape[0]))
return action.clip(self.env.action_space.low,
self.env.action_space.high)
4.存储转换
在采取行动后,我们在重放缓冲区中存储关于该时间步长的信息。这些转换将在以后更新我们的网络时使用。
replay_buffer.add((self.obs, new_obs, action, reward, done_bool))
5.更新评论家
一旦我们在环境中执行了一个完整的时间步骤,我们就为我们的模型训练几次迭代。更新的第一步涉及到批评家。这是算法中最重要的部分之一,也是大多数 TD3 附加特性得以实现的地方。首先要做的是从重放缓冲区中抽取一小批存储的转换。
# Sample mini batch
s, s_, a, r, d = replay_buffer.sample(batch_size)
state = torch.FloatTensor(s).to(device)
action = torch.FloatTensor(s_).to(device)
next_state = torch.FloatTensor(y).to(device)
done = torch.FloatTensor(1 - d).to(device)
reward = torch.FloatTensor(r).to(device)
接下来,我们将为我们从小型批处理中提取的每个状态选择一个操作,并应用目标策略平滑。如前所述,这只是用我们的目标演员网络挑选一个动作,我们将噪声添加到已被剪辑的动作中,以确保有噪声的动作不会离原始动作值太远。
# Select action with the actor target and apply clipped noise
noise = torch.FloatTensor(u).data.normal_(0, policy_noise).to(device)
noise = noise.clamp(-noise_clip, noise_clip)
next_action = (self.actor_target(next_state) + noise).clamp(-self.max_action, self.max_action)
接下来,我们需要计算评论家的目标 Q 值。这就是双重批评网络发挥作用的地方。我们将获得每个目标评论家的 Q 值,然后取两者中最小的一个作为我们的目标 Q 值。
# Compute the target Q value
target_Q1, target_Q2 = self.critic_target(next_state, next_action)
target_Q = torch.min(target_Q1, target_Q2)
target_Q = reward + (done * discount * target_Q).detach()
最后,我们计算了两个电流评论家网络的损失。这是通过获得每个当前评论家的 MSE 和我们刚刚计算的目标 Q 值来完成的。然后,我们像往常一样对批评家进行优化。
# Get current Q estimates
current_Q1, current_Q2 = self.critic(state, action)# Compute critic loss
critic_loss = F.mse_loss(current_Q1, target_Q) + F.mse_loss(current_Q2, target_Q)# Optimize the critic
self.critic_optimizer.zero_grad()
critic_loss.backward()
self.critic_optimizer.step()
6.更新参与者
与评论家相比,演员的更新要简单得多。首先,我们确保每隔 d 个时间步长就更新一次演员。在我们的例子和论文中,演员每两个时间步更新一次。
# Delayed policy updates
if it % policy_freq == 0: # Compute actor loss
actor_loss = -self.critic.Q1(state, self.actor(state)).mean() # Optimize the actor
self.actor_optimizer.zero_grad()
actor_loss.backward()
self.actor_optimizer.step() # Update the frozen target models
for param, target_param in zip(self.critic.parameters(), self.critic_target.parameters()):
target_param.data.copy_(tau * param.data + (1 - tau) * target_param.data) for param, target_param in zip(self.actor.parameters(), self.actor_target.parameters()):
target_param.data.copy_(tau * param.data + (1 - tau) * target_param.data)
演员的损失函数简单地从我们的评论家网络中获得-Q 值的平均值,我们的演员在给定小批状态的情况下选择采取什么行动。就像以前一样,我们通过反向传播优化我们的演员网络。
7.更新目标网络
最后,我们使用软更新来更新冻结的目标网络。这是与 actor 更新一起完成的,也是延迟的。
# Update the frozen target models
for param, target_param in zip(self.critic.parameters(), self.critic_target.parameters()):
target_param.data.copy_(tau * param.data + (1 - tau) * target_param.data)for param, target_param in zip(self.actor.parameters(), self.actor_target.parameters()):
target_param.data.copy_(tau * param.data + (1 - tau) * target_param.data)
完整代码
结果
作者在原始论文中的结果在各种基准测试环境(如 MuJoco control suite)中都取得了优异的成绩。下面的结果显示了 TD3 如何优于几乎所有算法,包括最近的 SAC (Haarnoja 等人,2018 年)算法和 PPO(舒尔曼等人,2017 年),PPO 是 OpenAI 的 go to 算法,用于开创性的研究,如他们的 DOTA 2 代理。
Fig 5. Benchmarking results from the TD3 paper
用作基准的算法包括、PPO、ACKTR (Wu 等人,2017)和 TRPO(舒尔曼等人,2015)的 OpenAI 基线实现。SAC 是从作者的 github 实现的。
然而,自 TD3 发布以来,SAC 已得到改进,如软演员-评论家算法和应用中所见(Haarnoja 等人,2019 年)。在这里,Haarnoja 展示了全面超越 TD3 的新结果。为了对算法进行公正的评估,我们可以从 OpenAI:Spinning Up 的主要 RL 算法实现中看到基准测试结果。正如您在图 6 中看到的,TD3 在 Ant 环境中设法超越了 SAC。然而,SAC 在 HalfCheetah 环境中实现了更高的性能。
Fig 6. OpenAI Spinning Ups benchmark results for the Ant and HalfCheetah MuJoCo environments
下面是我在 Roboschool HalfCheetah 环境中测试的 TD3 实现的训练结果。上图显示了代理在过去 100 集的平均得分。如你所见,代理很快学会站立,然后成功行走。
Fig 7. Training results of TD3 HalfCheetah. Shows the average score over the previous 100 episodes
虽然它确实短暂地陷入局部最优,但代理能够快速恢复,在 500k 时间步长后收敛到最优策略。下面的视频显示了经过全面培训的代理的结果。
Fig 8. results of the trained TD3 HalfCheetah
结论
恭喜您,我们已经涵盖了您开始实施市场上最先进的强化学习算法所需的一切!我们现在已经了解了 TD3 是什么,并解释了使该算法表现如此出色的核心机制。不仅如此,我们还一步一步地学习了算法,并学习了如何用 pytorch 构建算法。最后,我们看了原始论文和本文实现中看到的算法的结果。我希望这篇文章对你有所帮助,并对强化学习有所了解!
参考
[1] Fujimoto,s .,van Hoof,h .,和 Meger,d .在演员-评论家方法中解决函数近似错误。 arXiv 预印本 arXiv:1802.09477 ,2018。
[2] Lillicrap,T. P .,Hunt,J. J .,Pritzel,a .,Heess,n .,Erez,t .,Tassa,y .,Silver,d .,Wierstra,d .深度强化学习的连续控制。 arXiv 预印本 arXiv:1509.02971 ,2015。
[3]open ai—spinning Up,2018:https://spinning Up . open ai . com/en/latest/algorithms/td3 . html #背景
[4]哈多·范·哈塞尔特(2010 年)。双 Q 学习。神经信息处理系统进展 23 (NIPS 2010),加拿大不列颠哥伦比亚省温哥华,第 2613–2622 页。
[5] Van Hasselt,h .,Guez,a .,和 Silver,d .使用双 q 学习的深度强化学习。在 AAAI,第 2094-2100 页,2016 年。
[6]t . Haarnoja,a .周,a . abbe El,p .和 Levine,s .软行动者-批评家:随机行动者的政策外最大熵深度强化学习。 arXiv 预印本 arXiv:1801.01290 ,2018。
[7]舒尔曼,j .,沃尔斯基,f .,德里瓦尔,p .,拉德福德,a .,和克里莫夫,o .近似政策优化算法。 arXiv 预印本 arXiv:1707.06347 ,2017。
[8]舒尔曼,j .,莱文,s .,阿贝耳,p .,乔丹,m .,和莫里茨,p .信托区域政策优化。在机器学习国际会议中,第 1889–1897 页,2015 年。
[9] Wu,y .、Mansimov,e .、Grosse,R. B .、Liao,s .和 Ba,j .使用 kronecker 分解近似的深度强化学习的可扩展信赖域方法。在神经信息处理系统进展中,第 5285–5294 页,2017 年。
[10] Haarnoja,t .,周,a .,Abbeel,p .,和 Levine,s .软演员-评论家算法和应用。 *arXiv 预印本 arXiv:*12.05905 v2,2019
如何在数据科学工作流程中使用测试驱动开发
Photo by Samuel Zeller on Unsplash
数据科学家和机器学习工程师应该向软件开发人员学习的另一件事
每个软件开发人员都知道测试驱动开发(或简称 TDD),但数据科学和机器学习方面的人不够多。这是令人惊讶的,因为 TDD 也可以大大提高数据科学项目的速度和质量。在这篇文章中,我将向您介绍 TDD 背后的主要思想和一个代码示例,该示例展示了 TDD 对于数据科学的价值以及如何在基于 Python 的项目中实际实现它。
什么是测试驱动开发?
TDD 是一种软件开发的进化方法。也就是说,它依赖于增量改进,这与敏捷过程相一致。
理解 TDD 最简单的方法是“红绿重构”——基于 Kent Beck 在 2003 年提出的工作模型的系统:
- **红色:**编写一个新的测试,并确保它失败。如果通过,代码库已经覆盖了所需的功能,不需要额外的工作。
- **绿色:**编写通过测试的代码。最重要的是,所有以前的测试也必须通过!也就是说,新代码增加了现有的功能。
- **重构:**如有必要,修改代码。例如,确保代码库的结构在正确的抽象层次上。请勿在此阶段添加或更改任何功能。
您也可以将这些步骤视为寻找不同问题的答案:
- 如何检查我的代码是否提供了特定的功能?
- 绿色:我怎样才能写出通过我检查的代码?
- **重构:**在不影响功能的情况下,我要在代码基上做什么改变才能改进它?
与其他方法相比,这种方法有许多优点:
- 编写测试迫使你思考用户以后可能会创建什么样的场景。一个好的测试涵盖了在给定特定输入或更一般的用户行为的情况下,软件应该交付什么。
- 你需要写更多的代码,但是每一部分都是经过设计测试的。整体质量将因此提高。
- 以这种范式思考促进了清晰定义的模块的开发,而不是过度复杂(并且难以维护)的代码库。
数据科学中何时(不)使用 TDD
希望我让你相信了 TDD 是软件开发的一个好主意。考虑到它的方法,我们什么时候可以在数据科学中应用这些原则以获得最大的效果?
在以下场景中,TDD 可能不值得花费精力:
- 你正在探索一个数据源,特别是如果你这样做是为了了解这个数据源的潜力和缺陷。
- 您正在构建一个简单明了的概念证明。你的目标是评估进一步的努力是否有希望。
- 您正在使用一个完整且可管理的数据源。
- 你是(并且你将会是)唯一一个在项目中工作的人。这种假设比乍看起来更强,但适用于特定分析。
相比之下, TDD 在以下情况下更好:
- 分析渠道
- 复杂的概念证明,即解决子问题的不同方法,干净的数据等…
- 处理数据的子集,因此您必须确保在出现新问题时,在不破坏工作代码的情况下捕获问题。
- 你在一个团队中工作,但是你想确保没有人破坏运行代码。
TDD 示例:为 NLP 任务准备 Tweet
对于这个例子,我使用了标准 Python 库中的pytest
而不是unittest
。如果你在寻找后者的介绍,请看这篇文章底部的链接。
为了向您介绍 TDD 过程,我选择了一个简单但仍然现实的例子:准备一个 tweets 列表以供进一步分析。更具体地说,我想把分析建立在干净和独特的推特上。这需要针对四个子问题的代码:
- 清除提及其他账户的推文。
- 过滤掉转发。
- 清除推文中的特殊字符。
- 过滤掉空字符串。
我故意用一种后来并不理想的方式来排列它们。原因是:许多独立的测试可以涵盖这些任务中的每一项。这些任务的组合和顺序将在后面的单独步骤中进行。
因为我从一开始就知道这四个任务,所以我从为它们创建测试用例开始。也就是说,我想出了例证所有这些问题的典型推文。为了方便使用,我创建了一个@pytest.fixture
函数。把这些函数想象成测试用例输入值的灵活占位符。以下是相关的代码片段:
我的所有代码都是一个更大的tweet_project
模块的一部分,该模块包含一个tweet_cleaning
文件,其中包含了与本例相关的所有函数。让我们从红色开始这个过程:
这个测试失败了,因为所有的clean_mentions
函数现在包含的是一个pass
。因此,它返回None
而不是空字符串。现在是变绿的时候了,也就是编写通过测试的代码。在我的例子中,我使用了一个正则表达式来删除“@”和后面直到下一个空格的所有内容:
现在测试通过了。现在有什么可以对进行重构的吗?没有直接影响功能的东西。
我对其他三个步骤使用了相同的方法。以下是对他们的测试:
您可以看到detect_
函数返回一个布尔值,该值可以在以后用作过滤器。我为通过这些测试而编写的相应函数如下所示:
这四个功能现在完全独立。他们每个人都有专门的测试,以确保他们按预期工作。为了结束这个例子,让我们构建一个测试来检查整个管道是否产生了期望的结果。也就是说,我想添加这样的功能:获取一组推文,清理需要清理的内容,过滤掉无用的内容,并返回一组推文以供进一步分析。
前面的测试用例没有充分涵盖潜在的场景。这就是为什么我为此实现了一个新的pytest.ficture
。您还可以看到,我的测试涵盖了我想要的输出的两个基本特征。首先,它应该只从新的测试集中返回一条 tweet。其次,我需要确保结果是一个list
,而不是一个集合或字符串(或者完全不同的东西),这样后面的函数就可以依赖它了。
红色的阶段是成功的,因为测试失败了。在绿色阶段,我使用了现有的(因此也是经过测试的)功能,并将它们组合起来,这样测试就通过了:
这段代码可以工作,但是对重构的需求是显而易见的。这既令人困惑,又有些丑陋。我鼓励你尝试练习。然而,无论你从现在开始做什么,所有的测试都必须保持绿色。在开始下一个周期之前,您不能添加额外的功能。
结论
我想强调的是,TDD 只能和程序员或数据科学家写的测试一样好。因此,思考哪些场景有可能发生是至关重要的。例如,在上面的例子中没有提到两次的测试用例。这里还有一些假设,比如数据中的转发总是以 rt 开头。
然而,这些并不是 TDD 的局限性,而是人类解决复杂问题的结果。TDD 的优势在于:
- 每个开发步骤本身都经过测试,很容易理解测试包含了什么。
- 因为每一步都建立在之前的测试之上,所以很难在不被注意的情况下破坏东西。这种方法大大减少了调试的需要。
- 对于如何向现有的代码库添加额外的功能,有一个清晰的方法:扩展现有的测试或者添加新的测试。
- 在 TDD 框架中工作鼓励明确的思考,并使其不太可能陷入死胡同或完全混乱。
我承认数据科学不同于软件开发。然而,时不时地像开发人员一样思考是一件很有力量的事情。
如果这篇文章对你有帮助或者你想补充什么,请在评论中或者在 Twitter 上告诉我。我也很乐意在 LinkedIn 上联系。感谢阅读!
附加材料:
关于使用 Python 中的unittest
进行 TDD 的介绍,我推荐这篇由 Dmitry Rastorguev 撰写的博客文章:
我是一个自学成才的初级开发人员,能够编写简单的应用程序。但我要坦白一件事。这是…
medium.freecodecamp.org](https://medium.freecodecamp.org/learning-to-test-with-python-997ace2d8abe)
TDD 不应该是 TDDious
现实世界中的数据科学
我仍然会遇到古老的“如何测试”的争论,但是我们能让测试变得有趣吗?
(Image by author)
我作为一名工程师已经工作了十多年,仍然会遇到“如何测试”的争论。我是首席工程师,这意味着我要和我的团队一起研究如何建造东西,所以我总是乐于接受不同的观点。但是我喜欢的一个话题是我们是否应该使用测试驱动开发或者 TDD。我认为这可以归结为一个根本性的误解,即为什么你应该享受 TDD 而不是憎恨它…
TDD 以一种清晰的方式让我明白我应该写什么代码。
对我来说,TDD 很有趣。我喜欢用测试驱动的方式编码,我无法想象为什么有人会想用其他方式编码。当我不知道如何为某个东西写一个简洁的测试时,我会很难过。这就把我们带到了通常对 TDD 的第一个抱怨——“我不能只编码”。这很有趣,因为 TDD 以一种清晰的方式让我明白我应该写什么代码。如果没有它,我可能会迷失在边缘案例中,或者在我并不打算进行的重构中。另一件事是 TDD 实际上让我“只写代码”,因为我可以写任何我喜欢的可怕的代码,只要测试通过。那种自由太神奇了!我写了一些可怕的代码来通过测试,测试我的假设,证明我的方法,或者看看我是否能过度优化。以连接到数据库为例:
from mocks import mock_databasedef test_query_database():
expected_customer = {
'id': 32,
'name': 'woof'
} mock_database()
customer = get_customer('woof')
assert customer == expected_customer
这可以通过多种方式实现。我很快就把这些放在一起:
import databasedef get_customer(user):
return database.connect().query(f'SELECT id,name FROM customers WHERE name="{user}"').fetch()
TDD 允许我专注于我希望我的代码实现的事情。遵循红色->绿色->重构的循环,我可以在任何时候返回以使代码更整洁:
import databasecustomer_query = 'SELECT id,name FROM customers WHERE name="{}"'def get_customer(user):
conn = database.connect()
cursor = conn.query(customer_query.format(user))
return cursor.fetch()
测试给你一个安全网,你之前写的功能仍然在运行和工作。
这证明了在测试通过后重写代码的想法。对此,我经常采用删除的方法;如果我可以删除代码并且测试仍然通过,那么我可以很高兴地重构它。我也将这种技术作为教学工具,向人们展示他们编写了多少额外的代码。删除代码有助于证明它不是不需要的,就是覆盖度量是误导的。带着“最大化未完成的工作”的敏捷思维,你应该为测试编写尽可能少的代码。这种代码的不断减少是有益的,它本身就是一个游戏,增加了乐趣!请注意,测试代码的成本可能过高;例如,我们在 AWS Lambda 处理函数之外初始化框架。这个初始化比处理程序更难测试,因为它在导入时运行。所以删除代码是有一定的背景的,但是一般来说一些测试层可以覆盖所有的东西。
令人兴奋的是,如果我不立即重构,在我有几个测试用例之后,我的代码仍然会很糟糕。重构并不总是发生在每次测试之后。测试给你一个安全网,你之前写的功能仍然在运行和工作。您可以继续沿着一条通往其自然结论的道路前进,而不用担心其他东西被破坏或者您稍后需要做的深入重构。通过评估代码,尽可能多地删除代码,您可以在测试保护您的情况下积极地进行大量重构。
另一个常见的抱怨是在做出改变时“我必须改变所有的测试”。在测试领域也有一些争论,关于你应该在什么水平上测试多少。我个人的哲学是,你应该测试你想要达到的目标。在数据管道的情况下,这可能是:从 S3 拉一个文件,对它做一些工作,然后把它放回 S3 的另一个位置。因为我重视 TDD 中的乐趣,这类测试比成百上千的说着同样事情的单元测试更让我高兴。这种数据处理测试的一个例子可能是:
import pandas
import moto
from pandas.testing import assert_frame_equalfrom functions.cake_mixer import mix_ingredients@pytest.fixture
def bucket_fixture():
with moto.mock_s3():
s3_resource = boto3.resource("s3")
bucket = s3_resource.Bucket("test")
bucket.create()
yield bucketdef test_processing_cake(bucket_fixture):
input_fixture = pandas.read_csv('fixtures/mixture.csv')
output_fixture = pandas.read_csv('fixtures/cake.csv') input_fixture.to_parquet('s3://test/ingredients/mixture.parquet')
mix_ingredients({
'bucket': 'test_bucket',
'mixture_key': 'ingredients/mixture.parquet',
'cake_key': 'cake/chocolate.parquet'
})
output = pandas.read_parquet('s3://test/cake/chocolate.parquet')
assert_frame_equal(output, output_fixture)
这做了很多:
- 为 S3 设置固定装置
- 上传测试示例文件
- 运行一些代码来处理这个例子
- 读出结果文件
- 断言您的预期输出与处理后的输出相匹配
这个例子说明了在这种测试中你可能采取的步骤。要采取更小的步骤,您可以在涉及 S3 之前就开始处理数据:
import pandas
from pandas.testing import assert_frame_equalfrom functions.cake_mixer import mix_ingredientsdef test_processing_cake():
input_fixture = pandas.read_csv('fixtures/mixture.csv')
output_fixture = pandas.read_csv('fixtures/cake.csv') output = mix_ingredients(input_fixture)
assert_frame_equal(output, output_fixture)
当您编写一个不断发展的测试时,您可以感觉到代码在一起。希望这能解决“我必须改变所有的测试”的问题,因为您只完成了实际的需求。紧密耦合的单元不容易改变。一个警告是,当一个单元有一组复杂的输入和输出时,单元测试可以帮助定义它们。
重要的是,不要试图一次实现太多,要朝着更大的结果努力。有时你想要使用多个测试循环来帮助构建一个更大的目标。对于数据管道,您可以为管道编写一个测试,然后为每个步骤编写一组更小的测试。也就是说,您可以测试管道的输出和概念证明管道是否匹配。然而,管道中的各个阶段都有针对具体的、可解释的转换的测试。从 pandas 概念验证到大规模 Spark 数据管道可以使用相同的端到端测试数据。
测试本质上是一个有趣的游戏,你可以设计自己的挑战,然后找到最好、最令人愉快的方式来完成它们。
最后,人们发现考试很单调,对此我无能为力。测试本质上是一个有趣的游戏,你可以设计自己的挑战,然后找到最好、最令人愉快的方式来完成它们。让这一点变得更清楚的最好方法是给自己找一个搭档,用乒乓球的方式进行练习。在乒乓球比赛中,一个人写一个测试,另一个人让它通过。竞相编写更好的测试和代码。有趣的是找到让代码做意想不到的事情的方法,或者找到让你的伙伴多思考一点来解决的边缘情况。例如,如果有一个函数要返回传递的值,您可以很容易地编写以下代码:
def test_identity():
assert identity(1) == 1
你可以很容易地从中获得乐趣,如下所示:
def identity(x):
return 1
这意味着您的合作伙伴现在必须实现预期的功能。下一次,技巧可能是检查 x 的两个不同值,以防止您玩得太开心:
def test_identity():
assert identity(1) == 1
assert identity(404) == 404
您已经介绍了几个额外的案例,并设法确保代码完全按照您的意图运行。
我真的希望这篇文章向你展示,TDD 给你的不是负担,而是:
- 理解你要写的代码和它应该做什么
- 这是一张继续编写糟糕代码的安全网,直到你想重构为止
- 工作生活的游戏化,包括多人游戏!
所以,就算你以前试过,再试试 TDD,因为大家应该会玩得更开心:-)。
TDS 将来到多伦多采访人工智能领域的领导者——请将您的问题发送给我们!
独家 TDS 采访
帮助我们为 TDS 合作的人工智能大会上的知名演讲人设计面试问题。
再过不到两周,TDS 将作为官方媒体合作伙伴和视频主持人出席多伦多 ML 年会。在会议期间,我们将针对紧迫的数据科学问题,面对面地采访内部演讲者,他们都有精美的简历!此外,知名科技 YouTubercs Dojo将加入 TDS 担任面试官!
Tickets for conference are still available here!
在过去的几个月里,我们与数据科学领域的知名嘉宾推出了视频访谈和播客系列。我们正在扩大这个系列,同时为 TDS 观众提供空间,让他们向即将到来的面试官提问。
这些问题可以是关于招聘、日常工作流程、公司内部项目或其他对你很重要的数据主题。我们将为面试日收集和策划。
请在评论区列出问题或直接发送给haebichan@towardsdatascience.com。
以下是四位确定要接受采访的演讲者:
1。阿扎利亚·米罗西尼
阿扎利亚是谷歌大脑的高级研究科学家。具体来说,她是系统的机器学习 moon shot in the Brain 的联合创始人/负责人,她专注于基于深度强化学习的方法来解决计算机系统和元学习中的问题。
Azalia 是深度学习方面的专家,对与神经网络和深度强化模型相关的最新研究有着透彻的了解。她对人工智能领域做出了巨大贡献,特别是通过她在可训练门控网络(稀疏门控专家混合层)方面的工作,解决了神经网络通过参数数量吸收信息的局限性。
在会议期间,Azalia 将谈论模型容量的这些问题,以及与学习做资源分配的深度强化模型相关的挑战。
2。Shreyansh Daftry
Shreyansh 是美国宇航局(计算机视觉小组-自主系统部门)的人工智能研究科学家和技术专家。他帮助开发火星及更远地方的下一代智能自主机器人。他通过构建复杂但可扩展的算法来实现这一点,这些算法充当机器人的“大脑”。
他处理辐射、机器学习中的少量数据等具有挑战性的问题,并为必须适应这些问题的机器处理意外环境和情况。
在多伦多 ML 会议上的演讲中,Shreyansh 将讲述机器学习如何用于太空探索以及他在这一过程中所学到的经验。
3.帕特里克·哈林娜
Patrick 是 Zynga ML 工程团队的技术主管,Zynga 是世界上最大的移动视频游戏公司之一。他是强化学习领域的专家,他在 Zynga 使用这种算法来个性化游戏体验。他的专长还在于支持这些复杂算法的分布式计算系统,如 Apache Spark。
例如,Zynga 已经利用 Spark 来改善内部数据管道,以生成数千个格式正确的功能,而无需手动输入。这是一个重要的成就,因为游戏数据(点击流数据)可能会非常混乱,来自同一游戏的不同操作系统会生成它们自己的数据模式。
Patrick 将在会议期间就强化学习如何解决许多业务问题以及在生产中使用强化学习的挑战发表演讲。
4.尚查尔·查特吉
Chanchal 领导谷歌云的人工智能团队。他专注于金融服务,解决与前 100 家银行相关的数百个机器学习问题,其中许多银行都是谷歌的客户。
这些问题包括欺诈、风险(缓解、量化风险)、编辑云中的敏感数据、对话代理(Google Home)、广告和推荐,以及模型的可解释性,他认为从消费者、管理层和监管者的角度来看,这是极其重要的。
在他的演讲中,Chanchal 将探讨深度学习人工智能能力如何推动谷歌的许多关键决策,作为改善数字营销、客户服务、制造运营等诸多方面的秘方。
同样,请随意在评论区写下问题,或者直接发邮件给haebichan@towardsdatascience.com!我们期待你们所有人的参与,无论是虚拟的还是面对面的。
Te Papa Tongarewa(新西兰博物馆)
大约四个月前,我在游览世界上最大风之都惠灵顿的时候参观了这个博物馆。毛利人的名字, Te Papa Tongarewa ,字面意思是“宝藏的容器”,它始于 1865 年作为一个小型殖民博物馆。
这座建筑和里面的展览一样宏伟。我喜欢的两个地方是和记录新西兰移民旅程的部分。作为一名有抱负的数据科学家,在离开这个地方后,我有一个目标。我想弄清楚我的积极情绪是别人感受到的还是被遗漏的。我的第一站是快速浏览网上评论。我选择猫途鹰评论是基于它们的简洁和高度的表现力。我从 2016 年 4 月 1 日到 2019 年 7 月 15 日收到了 Te Papa 的旅行顾问评论。下面是一些统计数据和数据集样本。
A snippet of the 11940 reviews. Hotel name is just a place holder in my review collection process so yes Te Papa is not a hotel.
The dataset comprises of 11940 reviews. The rest of what we’ll cover is in the text bit of the review thus not statistically significant here.
关于数据集的一些分析:
发行审查文本长度和字数
120–139 characters reviews lengths were written by 1068 visitors. That’s the most representative cluster.
4630 reviews were made up of 20–39 words which makes them quite expressive. Visitors really wanted to pass the message across.
文本分析
我们按照以下流程清理了数据
- 掉酒店名称,点评标题,义举投票,用户名。
- 给出 5 分而不是 50 分的评价。简单地除以 10。
- 删除缺少“review_body”的行。
- 为评论的长度创建新的特征。
- 为评论的字数创建新功能。
- 使用 TextBlob 计算情感极性。值的范围从-1 到 1,其中 1 是最积极的情绪,而-1 是最消极的情绪。
上述过程的输出如下
Results after: Dropping hotel name, review title, helpful vote, user name, preprocessing (removal of unwanted characters. Can be user defined),polarity computation as well as addition of review length and word count columns.
文本斑点操作
text blobPython(2 和 3)库提供了一个简单的 API,用于处理常见的自然语言处理(NLP)任务,如词性标注、名词短语提取、情感分析、分类、翻译等。下面的代码片段生成 5 条随机 tweets,在数据帧中极性最大。在我们的例子中,对于最消极的一个,即极性= =-0.875 和极性== 0,可以做同样的事情。
Five random tweets with the most positive sentiment i.e. polarity equal to 1.
我对 TextBlob 库的性能不太满意,特别是在一个严重偏向正极性的数据集中指出负面情绪,如下所示。
Skewed to the left. Close to 38% of the reviews depict satisfaction in what Te Papa offers.
与 VADER 的感悟
(效价感知词典和情感推理机)是一个词库和基于规则的情感分析工具。它使用一个情感词典的组合,情感词典是一个词汇特征(例如,单词)的列表,这些词汇特征通常根据它们的语义取向被标记为正面或负面。****
我选择 VADER 来分析情绪,因为与传统评论相比,它更习惯于社会数据。
Most negative review is with a compound score of -0.9794.
VADER 最负面的评论如下。
我们去 Te Papa 看 Gallipolli,战争规模展览。这个展览很棒,但同时也非常悲伤,因为它讲述了战争的徒劳和人类生命的可怕损失。Weta 工作室制作的超大模型非常精确。
像“非常”和“悲伤”这样的词肯定在否定过程中起到了关键作用。就像其他观点更多的是积极的观点过于美好一样,它需要一双更敏锐的眼睛来捕捉这种不一致。总而言之,期望提取的语句 100%准确是不可能的。唯一的出路是尽可能地训练我们自己的模型,而不要过于精确。我们以后再做那件事。
一段时间的情绪
事件影响人的感情。某些展览的开展必然会引起参观者不同的反应。将情绪绘制成时间序列会让我们更好地了解游客的感受模式。在绘制之前,会对数据框进行一些更改。我们根据评论时间对所有值进行排序,将评论时间复制到索引中,评论之间的间隔为 24 小时,以使绘图更容易,并计算复合情感得分的扩展和滚动平均值。
从上面的情节中得到一些有趣的观点
- 很多情绪点都集中在 0.75 情绪分左右。这是一个强有力的指标,表明大多数评论都过于积极。
- 有很多数据点。很难解释模式。
整个数据集的样本表示可能会给出一个更容易解释的图表。下面的输出证实了之前对 Te Papa 游客体验的强烈肯定。
Sentiment scores are evenly higher i.e. close to 1.0. Shows an even and strong footing in terms of what Te Papa offers its clientele.
结论
从上面的分析来看,当谈到游客的体验时,Te Papa 有一个强大的立足点。我们使用了两个情绪分析器,它们都被证明是通用的,因为情绪中的负面检测对两者来说都很困难。这是关于 Te Papa 的统计和数据科学展望系列帖子的第一步。我期待着利用 Te Papa 的公开数据集来解决以下问题
- 使用来自他们的谷歌评论的更多数据,基于增强的低向量表示来训练情感分类器。希望我也能挖掘他们的社交数据。
- 基于方面的情感分析。游客对哪些方面感到欣喜若狂,对哪些方面不满意?
- 根据游客的排名,与世界上排名前 25 位的其他博物馆进行面对面的比较分析。哪些方面让他们比 Te Papa 做得更好?
- 分析惠灵顿或 Te Papa 的某些活动是否会影响游客体验。
敬请期待!
十年自学数据科学——彼得·诺维格(谷歌机器学习主管)的三堂课
数据科学、机器学习和分析被认为是最热门的职业道路。行业、学术界和政府对熟练数据科学从业者的需求正在快速增长。因此,持续的“数据热潮”吸引了如此多具有不同背景的专业人士,如物理、数学、统计、经济和工程。数据科学家的就业前景非常乐观。IBM 预测,到 2020 年,对数据科学家的需求将飙升 28%:https://www . Forbes . com/sites/louiscolombus/2017/05/13/IBM-predicts-demand-for-data-scientists-will-soar-28-by-2020/# 7916 f 3057 e3b。
数据科学是一个如此广阔的领域,包括几个细分领域,如数据准备和探索;数据表示和转换;数据可视化和显示;预测分析;机器学习等。对学习数据科学基础感兴趣的初学者可能会有这样的问题:
- 学习数据科学的基础知识需要多长时间?
- 有哪些学习数据科学的资源?
选择上述标题的动机是基于 Peter Norvig 关于成为编程专家所需时间的想法。如果你还没有读过这篇文章:《10 年自学编程》作者 Peter Norvig(谷歌机器学习总监),我鼓励你这样做。下面是文章链接:http://norvig.com/21-days.html。
这里的重点是,你不需要 10 年来学习数据科学的基础知识,但匆忙学习数据科学肯定没有帮助。成为一名数据科学家需要时间、努力、精力、耐心和承诺。
Peter Norvig 的建议是,学习需要时间、耐心和承诺。当心那些告诉你可以在 4 周内或 1 个月内学习数据科学的文章、书籍或网站。如果您有兴趣学习数据科学的基础知识,请准备好投入适量的时间和精力,这样您不仅可以掌握表面的概念,还可以掌握数据科学的深层概念。
我花了 2 年的时间深入学习(通过自学)来掌握数据科学的基础知识,这是因为我拥有物理学博士学位,并且我在数学和编程方面有坚实的背景。掌握数据科学的基础知识需要多长时间取决于你的背景。一般来说,在数学、统计学、计算机科学、工程学或经济学等分析学科有扎实的背景是有利的。
Peter Norvig 的 3 个教训**“十年自学编程”**
1)掌握数据科学的基础知识需要时间、努力、精力、耐心和承诺
数据科学是一个多学科领域,需要扎实的高等数学、统计学、编程背景,以及数据分析、数据可视化、模型构建、机器学习等方面的其他相关技能。我花了两年的时间专门学习,才掌握了数据科学的基础,这是因为我在数学、物理和编程方面有坚实的背景。以下是一些帮助我掌握数据科学基础的资源。
(一)【https://www.edx.org/professional...】数据科学专业证书(HarvardX,通过 edX):
包括以下课程,全部使用 R 教授(您可以免费旁听课程或购买认证证书):
- 数据科学:R 基础;
- 数据科学:可视化;
- 数据科学:概率;
- 数据科学:推理和建模;
- 数据科学:生产力工具;
- 数据科学:扯皮;
- 数据科学:线性回归;
- 数据科学:机器学习;
- 数据科学:顶点
(二)分析:基本工具和方法(Georgia TechX,通过 edX):https://www.edx.org/micromasters...
包括以下课程,全部使用 R、Python 和 SQL 讲授(您可以免费审计或购买经过验证的证书):
- 分析建模导论;
- 数据分析计算导论:
- 商业数据分析。
(三)应用数据科学与 Python 专业化(密歇根大学,通过 Coursera):https://www.coursera.org/special...
包括以下课程,全部使用 python 教授(您可以免费旁听大多数课程,有些课程需要购买认证证书):
- Python 中的数据科学导论;
- 应用 Python 绘图、制图和数据表示;
- Python 中的应用机器学习;
- Python 中文本挖掘的应用:
- Python 中的应用社会网络分析。
(四)数据科学教科书
从教科书中学习提供了比你从在线课程中获得的更精炼和更深入的知识。这本书对数据科学和机器学习提供了很好的介绍,代码包括:“Python 机器学习”,作者塞巴斯蒂安·拉什卡。作者以一种非常容易理解的方式解释了机器学习的基本概念。此外,代码也包括在内,因此您实际上可以使用提供的代码来练习和构建您自己的模型。我个人认为这本书在我作为数据科学家的旅程中非常有用。我会向任何数据科学爱好者推荐这本书。你所需要的是基本的线性代数和编程技能,以便能够理解这本书。也有很多其他优秀的数据科学教科书,如韦斯·麦金尼的《 Python for Data Analysis 》,库恩·约翰逊的《应用预测建模》,伊恩·h·威滕的《数据挖掘:实用机器学习工具和技术》,Eibe Frank & Mark A. Hall 等等。
(v)与其他数据科学有志者建立网络
从我的个人经历来看,通过与其他数据科学有志者合作,我从每周关于数据科学和机器学习各种主题的小组对话中学到了很多。与其他数据科学有志者建立联系,在 GitHub 上分享您的代码,在 LinkedIn 上展示您的技能,这将真正帮助您在短时间内学习许多新概念和工具。你还会接触到新的做事方式,以及新的算法和技术。
2。理解数据科学的理论基础与数据科学实践技能同样重要
数据科学是一门数学密集型学科,需要以下方面的知识:
(一)统计和概率
㈡多变量微积分
㈢线性代数
㈣优化和运筹学
从这里了解更多你需要重点关注的数学话题: 机器学习必备数学技能 。
即使 Python 的 sci-kit learn 和 R 的 Caret 包等包包含了几个用于进行数据科学和构建机器学习模型的工具,理解每种方法的理论基础也是极其重要的。
3。避免使用机器学习模型作为黑盒工具
扎实的数据科学背景将使数据科学家能够构建可靠的预测模型。例如,在构建模型之前,您可能会问自己:
㈠什么是预测变量?
㈡目标变量是什么?我的目标变量是离散的还是连续的?
(三)我应该使用分类还是回归分析?
(iv)如何处理数据集中缺失的值?
㈤在将变量纳入同一尺度时,我应该使用规范化还是标准化?
(vi)我是否应该使用主成分分析?
(vii)如何调整模型中的超参数?
(viii)如何评估我的模型以检测数据集中的偏差?
(ix)我是否应该使用集成方法,即使用不同的模型进行训练,然后进行集成平均,例如使用 SVM、KNN、逻辑回归等分类器,然后在 3 个模型上进行平均?
(x)我如何选择最终型号?
好的和坏的机器学习模型之间的区别取决于一个人理解模型的所有细节的能力,包括关于不同超参数的知识以及如何调整这些参数以获得具有最佳性能的模型。在没有完全理解模型的错综复杂的情况下,将任何机器学习模型作为黑箱,都会导致模型被证伪。
总之,数据科学是当今最热门的领域之一。数字革命创造了成吨成吨的数据。公司、行业、组织和政府每天都在产生大量的数据。对高技能数据科学家的需求只会继续增长。这是投入时间掌握数据科学基础知识的最佳时机。在这样做的时候,要小心那些告诉你可以在 4 周或 1 个月内学会数据科学的文章、书籍或网站。不要匆忙。慢慢掌握数据科学的基础知识。
自学 SQL —第一部分
Courtesy of comic.browserling.com
作为一名数据分析师,我在 SQL 方面做了很多工作,我想我应该分享一下如何使用它来解决业务问题。我自学成才,并在一家专门从事数据科学和 UX 设计教育的教育科技初创公司从市场营销工作成为一名数据分析师。
我想用我的学习来回报它,并分享一些我发现对培养分析技能有帮助的事情。事不宜迟,我将直接切入正题:一个可以用 SQL 解决的一些业务/产品分析师风格问题的端到端示例。
这篇文章是为那些希望发展自己的 SQL/分析思维技能的人,以及那些试图进入并开始他们作为业务分析师、数据分析师、产品分析师或数据科学家的职业生涯的人准备的。无论您选择哪种方式,我向您保证 SQL 是您工具箱中的一项关键技能!
因此,我这篇文章的目标是让您:
- 建立自己的免费 Mode 实例,这是一个常用的商业智能平台。许多数据分析师和数据科学家的职位描述都在寻找知道这个工具的候选人,所以如果你想进入这个领域,熟悉这个工具是很好的。
- 根据 Mode 提供的测试数据源编写基本的 SQL 语句。
在本系列文章的后续部分中,我将更深入地研究更高级的 SQL,并使用它来解决业务问题。
目标 1:设置
首先,你需要前往mode.com注册一个免费账户。这是一个超级快速和基本的注册过程。验证您的帐户后,您可以登录。
一旦进入平台,转到SQL Training2019
并点击Write a Query
。作为一个有产品和业务分析经验的人,我将带你浏览一下yammer_experiments
表中的 SQL 查询,它对应于产品实验及其结果。
这样,我们就实现了目标 1!看我们走!
目标 2:基本 SQL
让我们运行第一个查询来计算我们要处理多少行:
SELECT
COUNT(1)
FROM
tutorials.yammer_experiments
;
上面的查询告诉您表中的行数— 2595。
现在我们知道了这个表的大小,让我们了解一下这个表的值。为此,请使用 LIMIT 子句编写以下内容:
SELECT
*
FROM
tutorials.yammer_experiments
LIMIT 100
;
星号获取所有列,LIMIT 子句减少返回的行数,否则您将等待一段时间,尤其是在大型表上。
The first few rows returned from the previous query gives us a sense of what the data are
看起来yammer_experiments
表是某种网络分析数据。看到occurred_at
字段让我觉得这就是所谓的事件表。事件表的不同之处在于,每一行对应于用户采取的一个动作。典型地,在数据库中设置有触发器,其中执行以下逻辑:如果用户采取动作 A,记录在事件表 A 中捕获该用户-动作对的记录。动作的发生激活触发器并将记录推送到该表。
我不知道这张表,所以这是我的假设。在分析师的工作中,开发和测试假设是很重要的。为了测试我的假设,即每一行都是一个用户-动作对,因此任何用户都可以执行多个动作,让我们计算每个 user_id 出现的次数,看看是否有多个条目对应于任何用户 id。下一个查询引入了两个新子句:GROUP BY 和 ORDER BY。
SELECT
user_id,
COUNT(1)
FROM
tutorial.yammer_experiments
GROUP BY
user_id
ORDER BY
COUNT(1) DESC
;
在上面的查询中,我从表中选择了用户 id,并使用了上面介绍的相同的 COUNT(1)逻辑。分组依据按用户 id 对计数进行分组。最后,我使用 ORDER BY 和关键字 DESC(代表降序)首先获得用户 id 的最大数量的实例。这产生了以下结果:
First few rows of user ids and the number of occurrences of each
这否定了我的假设,即这是一个事件表,但让我们继续前进!
让我们更好地理解下一个专栏:occurred_at
。所以我们知道一个用户只出现一次,可能是某种动作不能执行两次。
无论如何,假设你的利益相关者没有告诉你这个信息,或者当这个实验进行时,你没有在会议中问他们,这将会很有趣。很容易做到这一点,使用聚合函数* : MIN 和 MAX。查看并运行下面的查询:*
SELECT
MIN(occurred_at),
MAX(occurred_at)
FROM
tutorial.yammer_experiments
;
这将向我们显示最早的操作是在 2014 年 6 月 1 日刚过午夜时执行的,最晚的操作是在 2014 年 6 月 30 日晚上 10:45。让我们假设这是 2014 年 6 月的一次实验!
现在需要一个关于可读性和易于理解的注释。在这些列的 SELECT 子句中使用 AS 关键字对我们自己的理解和将来可能运行该查询的任何人来说都更好一些。
SELECT
MIN(occurred_at) AS `Earliest Occurrence`,
MAX(occurred_at) AS `Latest Occurrence`
FROM
tutorial.yammer_experiments
;
这称为别名,它有助于 SQL 的可读性和理解。然而,当与其他分析师单独工作时,我实际上建议保持表名和字段名不变——因为别名是您自己的命名约定。其他分析师只会理解数据库模式的实际名称,而不是您决定对其进行重命名的名称!因此,如果你在寻求反馈或合作,尽量不要使用别名,即使你会打更多的字。做一个好的分析师同事——不要化名。
*注意:*反斜杠(`)并不是在 SQL 的每个版本中都适用于别名,一些 SQL 变体很难处理空格。尝试使用下划线而不是空格、单引号或双引号,直到没有出现错误为止。
在研究这些数据的其他方法之前,重要的是要看看控制组和测试组的大小是否相等。如果我们正在做一个 A/B 测试,看看设计流程的两个变量,按钮点击行为,登陆页面,等等。,我们希望数据平均分布在多个变量上。让我们再用 COUNT(1)的把戏检查一下。
SELECT
experiment_group,
COUNT(1) AS number_of_participants
FROM
tutorial.yammer_experiments
GROUP BY
experiment_group
;
这表明test_group
有 849 个参与者,而control_group
有 1746 个参与者!虽然这种划分并不理想,但双方都有统计意义上的显著数量的观察结果,所以让我们注意到 A/B 划分的警告并继续前进——这是需要向利益相关者注意的事情,并作为未来的建议添加——请平均划分您的小组!
您可能已经注意到 Mode 中有多个 Yammer 表。你想知道它们之间有什么联系吗?一个名副其实的数据组织应该有一个 ER(实体关系)图,它显示了表的主键和外键。主键通常是表中的第一列,外键是从该表指向外的键,映射到您试图连接的任何其他表的主键。这让我想到了连接的概念。
让我们试试下面的方法:将用户表连接到实验表。在我们开始之前,由于我们不知道模式,让我们通过对表运行查询来从经验上了解模式**!为了提高可读性和处理表名太长的奇怪换行符,我将打破自己的规则,为下一节的表和字段起别名。**
让我们看看实验表中是否使用了所有用户:
SELECT
COUNT(1)
FROM
tutorial.yammer_users AS users
INNER JOIN
tutorial.yammer_experiments AS experiments
ON experiments.user_id = users.user_id
;
上面的查询再次计算了行数,但是在 users 表中的所有用户 id 被内部连接到 experiments 表之后返回的行数。结果呢?2595.为什么?内部连接是文氏图的内部部分,这意味着只有当表 A 中的记录与表 B(实验表)中 on 子句中使用的字段匹配时,才会返回这些记录。简单地说:返回 2595 行,因为在所有用户(users 表)中,只有这 2595 个用户 id 用在了 experiments 表中。
因为 experiments 表是 users 表的子集(当然,因为您不想对所有用户进行实验!),这是使用另一种联接的好机会:左联接。
让我们尝试与上面相同的查询,但是使用左连接而不是内连接:
SELECT
COUNT(1)
FROM
tutorial.yammer_users AS users
LEFT JOIN
tutorial.yammer_experiments AS experiments
ON experiments.user_id = users.user_id
;
嗯?成功了吗?它应该返回用户表中的行数!这是因为它获取用户表中的所有用户 id,并且只获取用户 id 对应的实验表中的行。对上述查询生成的表进行解聚,自己去看看吧!
SELECT
*
FROM
tutorial.yammer_users AS users
LEFT JOIN
tutorial.yammer_experiments AS experiments
ON experiments.user_id = users.user_id
;
发生了什么事?我返回了两个表中的所有列,如果一个用户 ID 同时存在于 users 表和 experiments 表中,则 experiments 表中的列将填充该用户对应的实验数据,否则值为 NULL,因为没有匹配!
下面是上述查询生成的表格(我突出显示了用户 id 匹配的地方):
The resultant table from the LEFT JOIN query above
结论
在 SQL Academy 系列的第一部分中,您学习了 SQL 的基础知识:SELECT、FROM、LIMIT、COUNT、GROUP BY、MIN、MAX 和 ORDER BY。
在下一部分中,我写了子查询和 case 语句。点击这里查看!
如果你觉得这篇文章有用或者学到了新的东西,可以考虑捐赠任何数量来支付给下一个学习者!
感谢阅读和快乐编码!
奢侈的生活
自学 SQL —第二部分
Bucketed data
几周前,我决定写更多我作为数据分析师所学到的关于 SQL 和分析思维的东西。我在一家名为的教育科技初创公司工作,该公司致力于让学生在数据科学和 UX 设计等热门领域找到工作。
本文是这个系列的第二篇文章(见第一部分此处)。第一部分的目标是让您了解模式分析,并熟悉示例数据库中的基本 SQL。
在本文中,我将介绍以下内容:
- 使用子查询更深入地研究 SQL。
- 将事情联系到业务示例案例,以及如何从战略上对查询结果采取行动。
- 展示一些例子,说明如何有效地用可视化表达这些查询的结果。
目标 1:总结和更多 SQL
回顾一下第一部分中的内容,我们在查询编辑器中设置了模式,并对 Yammer 实验表运行了一些基本的查询,使用了 SQL 的以下功能:SELECT、FROM、LIMIT、COUNT、GROUP BY、ORDER BY 以及 MIN 和 MAX。
这些对于获取汇总统计数据和理解您的数据非常有用。接下来让我们试着从数据中找出一个更复杂的商业问题!但是在我开始之前,我想分享一个提高效率的小技巧:
在大多数 SQL 编辑器和客户端(MySQL Workbench,我们一直使用的 GUI 模式分析平台,以及其他软件)中,查询的结尾用分号(;).在下一节中,我将写出几个查询,用注释(一个最佳实践)向您展示您可以在一个页面中有多个查询,并运行您想要的任何一个查询(在突出显示它或光标位于 SELECT 和分号之间的任何位置时运行CTRL + Enter
,将只运行那个查询)。
这里有一个例子来说明我的意思:
-- This subquery produces the event type counts
SELECT
events.event_type AS event_type,
COUNT(1) AS number_of_occurrences
FROM
tutorial.yammer_events AS events
GROUP BY
events.event_type
;-- This subquery produces the count of actions by location
SELECT
events.location,
COUNT(1) AS number_of_occurrences
FROM
tutorial.yammer_events AS events
GROUP BY
events.location
ORDER BY
COUNT(1) DESC
;-- This grabs the count of actions by device
SELECT
events.device,
COUNT(1) AS number_of_occurrences
FROM
tutorial.yammer_events AS events
GROUP BY
events.device
ORDER BY
COUNT(1) DESC
;
两个破折号是单行注释。若要注释掉多行,请以“/”开始,以“/”结束。运行上述查询并检查输出,我们看到大多数操作都是约定。在这些数据中,美国、日本和德国是行动的前三名。最常见的设备是 Macbook Pro,其次是联想 Thinkpad,最后是 Macbook Air。
目标 2:将它与业务示例案例联系起来
将这个问题与一个商业案例联系起来:如果有一个 bug 同时影响了 OS X 和 Windows 的用户,那么技术团队最好先修复 OS X 的 bug,然后在修复 Windows 的时候再推出,因为这是可能受到影响的最大的两个用户群。
一个更详细的表也可能存储操作系统版本,这可以帮助开发人员确切地知道要修补什么版本。如果那些数据是可用的,当优先考虑首先解决哪个 OS 版本时,可以应用与上述类似的逻辑。
如果我们想弄清楚打开电子邮件的用户是否会表现出其他行为呢?我们需要探索更多,然后才能尝试找出要寻找的模式。
让我们看看用户采取的平均行动次数是多少。这将让我们对预期的参与量有所了解:
SELECT
user_id,
COUNT(1)
FROM
tutorial.yammer_events AS events
GROUP BY
user_id,
event_name
;
请记住,事件表是一个实际的事件表。因此,我们需要做的就是统计用户 id 并按用户 id 分组。等等,我们不是想要普通的吗?
让我们引入子查询的概念来获得该值!
子查询是查询中的一个查询。我花了一段时间才明白如何使用它们,直到我的同事解释了一个启发法,帮助我建立了正确的思维模式。之后就一拍即合了。
当您说 SELECT something FROM table 时,您正在查询该表并选择 SELECT 子句中指定的列。子查询返回所谓的派生表、、,这只是一种说法,即查询的输出是一个只在查询期间持续的表。就像查询任何表一样,您可以从该表进行查询,该表本身就是一个查询。我将从一个例子开始,这个例子在实践中没有意义,但是以一种简单的方式说明了这个概念。
SELECT
user_id
FROM
(
SELECT
user_id
FROM
tutorial.yammer_events AS events
) AS example_derived_table;
这应该是清楚的,并说明了为什么我学会了制表(即缩进)的方式。左括号和右括号在一条线上,所以你可以很容易地知道子查询从哪里开始和结束(相信我,有 10 或 20 个子查询,这是至关重要的!).
这个查询没有任何意义,但是它说明了这一点:我在 events 表中派生出一个用户 ID 表,并从中提取用户 ID。
您能猜到我们如何使用它来获得用户使用我们之前的 COUNT 查询所采取的平均操作数吗?
获取用户的动作计数,然后从中取这些计数的平均值!
SELECT
AVG(action_count)
FROM
(
SELECT
user_id,
COUNT(1) AS action_count
FROM
tutorial.yammer_events AS events
GROUP BY
user_id
) AS example_derived_table;
这个返回 34.9!第一个用户只有几个,所以我怀疑有一个巨大的行动传播,实际上通常有高度参与和勉强参与的用户。所以让我们来数一数吧!
SELECT
action_count,
COUNT(1)
FROM
(
SELECT
user_id,
COUNT(1) AS action_count
FROM
tutorial.yammer_events AS events
GROUP BY
user_id
) AS example_derived_table
GROUP BY
action_count
ORDER BY
action_count
;
这将返回给我们动作的数量。最常见的是单个行动,这很有意义,因为少行动比多行动更容易。
在上面的子查询示例中,我在 FROM 子句中进行了子查询。但是可以在任何子句中进行子查询。我通常会在 JOIN 子句中编写一个子查询,因为我想将一些被操作的数据连接回某个基表。
目标 3:有效的可视化
通常,制作简单、易读的图表向企业的利益相关者传达信息是最有效的。假设你在一个产品分析团队工作,你的任务是展示用户参与度的分布。总共有多少用户执行 x 个操作?
我们已经有了产生这个结果的查询。然后,您可以在模式下,或者在将数据提取为 CSV 格式并导入 Python、Excel 或您喜欢的任何其他工具之后,用结果数据制作一个条形图!
在模式下,您只需使用您编写的查询,然后单击图表按钮并选择一个条形图。将从查询中导出的列拖动到 X 轴和 Y 轴上,这就是您的图表!
The count of users who performed X number of actions
这向我们展示了执行一个动作的用户数量巨大,而执行更多动作的用户数量却少得多。不过 X 轴并不理想,所以让我们重新查看一下查询,使用 CASE 语句和谓词逻辑为 X 轴创建更好的数据存储。这将允许我们为了可读性和简洁性而截断数据。
下面是在 X 轴上存储数据的 SQL 查询:
SELECT
CASE
WHEN action_count BETWEEN 0 AND 10 THEN '[0-10]'
WHEN action_count BETWEEN 10 AND 20 THEN '[10-20]'
WHEN action_count BETWEEN 20 AND 30 THEN '[20-30]'
WHEN action_count BETWEEN 30 AND 40 THEN '[30-40]'
WHEN action_count BETWEEN 40 AND 50 THEN '[40-50]'
WHEN action_count BETWEEN 50 AND 60 THEN '[50-60]'
WHEN action_count BETWEEN 60 AND 70 THEN '[60-70]'
WHEN action_count BETWEEN 70 AND 80 THEN '[70-80]'
WHEN action_count BETWEEN 80 AND 90 THEN '[80-90]'
WHEN action_count BETWEEN 90 AND 100 THEN '[90-100]'
END AS action_count_bucketed,
SUM(number_of_users)
FROM
(
SELECT
action_count,
COUNT(1) AS number_of_users
FROM
(
SELECT
user_id,
COUNT(1) AS action_count
FROM
tutorial.yammer_events AS events
GROUP BY
user_id
) AS example_derived_table
GROUP BY
action_count
ORDER BY
action_count
) AS case_table
GROUP BY
action_count_bucketed
LIMIT 10
;
Bucketed data
好多了!使用 case 语句并捕获值的范围,我能够简化这个图表。没有必要知道大约 20 个用户执行了 98 个动作。说 120 执行了 90 到 100 个动作就“够好”了!永远记住 80/20 法则,多少是足够的信息。
这张图表背后的故事是,你可以看到大多数用户并不十分投入,只有少数核心群体处于 10-20 到 30-40 个行动区间。下一步是使用日期时间列occured_at
来讲述一个关于这些行为何时发生的更有趣的故事,并查看重要的产品参与度指标,如日活跃用户(DAU)、周活跃用户(WAU)等。
在本系列的下一部分中,我将更深入地研究如何使用日期时间值,敬请关注!
如果你觉得这篇文章有用或者学到了新的东西,考虑捐赠任何数量来支付给下一个学习者!
感谢阅读和快乐编码!
奢侈的生活
教电脑登陆月球
去年我花了相当多的时间来了解机器学习领域的进展。现在可用的工具真的令人印象深刻——现在,利用可用的库,只需几行代码就可以实现复杂的神经网络。
我一直对机器学习复杂任务的想法很感兴趣,比如通过一遍又一遍地做它们来学习飞行,并看看什么有效,所以我选择了 OpenAI Gym 月球着陆器环境进行第一次实验。进行学习和控制的程序被称为代理。
代理学习解决问题的正确方法,而没有被提供许多解决的例子,这是无监督学习。这样做的一个方法是建立一个培训环境,奖励做得好的代理人,这样代理人就可以强化这种行为。这叫做强化学习。
OpenAI 健身房提供了一个模拟不同问题的一致的训练环境——游戏、物理模拟等。它处理给出所需的奖励,以便代理可以学习。
有一个很好的库可以做到这一点,叫做 Keras-RL,它和 OpenAI Gym 配合得非常好。
下面显示了训练过程的视频,每隔一段时间采样一次。它从火箭坠毁时的有效随机发射发展到犹豫盘旋,再到平稳着陆。学习代理的代码如下。
The training process
该计划是第一次训练,这可能需要几天时间,如果你没有使用 GPU 加速。然后保存训练模型的参数,并由测试程序加载,该测试程序演示学习的着陆技术。在云系统或 GPU 加速桌面上进行培训将大大加快这一过程。
这些程序由 Keras-RL 演示代码修改而来。
import numpy as np import gym from keras.models
import Sequential from keras.layers
import Dense, Activation, Flatten from keras.optimizers
import Adam from keras.callbacks
import EarlyStopping from rl.agents.dqn
import DQNAgent from rl.policy
import BoltzmannQPolicy from rl.policy
import EpsGreedyQPolicy from rl.memory
import SequentialMemory ENV_NAME = 'LunarLander-v2' env = gym.make(ENV_NAME)
env = gym.wrappers.Monitor(env, 'recordings12')
np.random.seed() env.seed()
nb_actions = env.action_space.n # Next, we build a very simple model.
model = Sequential() model.add(Flatten(input_shape=(1,) + env.observation_space.shape)) model.add(Dense(128)) model.add(Activation('relu')) model.add(Dense(64)) model.add(Activation('relu')) model.add(Dense(32)) model.add(Activation('relu')) model.add(Dense(nb_actions)) model.add(Activation('linear')) print(model.summary())# configure and compile our agent. memory = SequentialMemory(limit=1000000, window_length=1)
policy = EpsGreedyQPolicy()
earlystop = EarlyStopping(monitor = 'episode_reward', min_delta=.1, patience=5, verbose=1, mode='auto')
callbacks = [earlystop]
nb_steps_warmup = 1000
target_model_update = .2
gamma = .99
lr = .0001
training_steps = 4000000
epochs = training_steps/1000 decay = float(lr/epochs)
dqn = DQNAgent(model=model, nb_actions=nb_actions, memory=memory, nb_steps_warmup=nb_steps_warmup, target_model_update = target_model_update, policy=policy, gamma = gamma)dqn.compile(Adam(lr=lr), metrics=['mae']) # Train model
dqn.fit(env, nb_steps=training_steps, visualize=False, verbose=1) # After training is done, we save the final weights. dqn.save_weights('dqn_{}_weights.h5f'.format(ENV_NAME), overwrite=True)
测试程序
import numpy as np
import gym from keras.models
import Sequential from keras.layers
import Dense, Activation, Flatten from keras.optimizers
import Adam from rl.agents.dqn
import DQNAgent from rl.policy
import EpsGreedyQPolicy from rl.memory
import SequentialMemory ENV_NAME = 'LunarLander-v2'
env = gym.make(ENV_NAME)
env = gym.wrappers.Monitor(env, 'recordings2')
np.random.seed()
env.seed()
nb_actions = env.action_space.n
model = Sequential() model.add(Flatten(input_shape=(1,) + env.observation_space.shape)) model.add(Dense(128))
model.add(Activation('relu'))
model.add(Dense(64))
model.add(Activation('relu'))
model.add(Dense(32))
model.add(Activation('relu'))
model.add(Dense(nb_actions))
model.add(Activation('linear'))
print(model.summary())
memory = SequentialMemory(limit=75000, window_length=1)
policy = EpsGreedyQPolicy()
dqn = DQNAgent(model=model, nb_actions=nb_actions, memory=memory, nb_steps_warmup=10000, target_model_update=.2, policy=policy) dqn.compile(Adam(lr=.0001), metrics=['mae']) dqn.load_weights('dqn_{}_weights.h5f'.format(ENV_NAME)) dqn.test(env, nb_episodes=10, visualize=True)
最初发表于T5【http://shortcircuitsandinfiniteloops.blogspot.com】。
教神经网络玩 21 点
我们训练一个神经网络,看看应用深度学习是否可以改善我们的 21 点策略
上次我们开发了模拟 21 点的代码。通过这些模拟,我们发现了赌场优势的关键驱动因素。以下是我们之前发现的快速回顾:
- 赌场通过强迫玩家在庄家之前行动(并根据不完全信息行动)来获得对 21 点玩家的优势。这首先让他们面临破产的风险(所以他们可能在庄家有机会行动之前就破产了)。
- **当玩家的牌总数在 12 到 16 之间(他们的下一张牌有被击败的风险)并且庄家亮出大牌时,他们尤其危险。**在这些情况下,假设庄家最终会有一手好牌,因此玩家必须命中或灭亡。我们可以直观地看到这一点,玩家获胜或平手的概率在 12 和 16 之间(绝望之谷)。
Probability of Win or Tie vs. Player’s Hand Value (21 not shown because the probability is 100%)
- 最后,我们观察到,一个天真的策略,即只有在失败的机会为零时才出手,极大地提高了我们击败赌场的几率,因为它将失败的风险完全转移到了赌场
如果你不熟悉 21 点这个游戏,我之前的帖子也描述了这个游戏的玩法和规则。
但是深度学习能做得更好吗?
今天帖子的目标是,我们是否可以使用深度学习来获得比幼稚策略更好的策略。我们将:
- 使用我们上次编写的 21 点模拟器生成数据(做了一些修改,使其更适合训练算法)。
- 编码并训练神经网络玩 21 点(希望是最佳的)。
如果你不熟悉神经网络, 我在这篇文章中写了大量关于它们的内容(这是我最努力的一篇文章,所以请查看)。
A Visual Depiction of a Simple Neural Net (From Understanding Neural Networks)
在我们进入训练过程之前,让我们后退一步,快速讨论一下在这种情况下使用神经网络的利弊。神经网络是高度灵活的算法,就像软粘土一样,神经网络可以自我调整以适应数据的轮廓,即使很少或没有转换。神经网络很容易处理会给线性回归等更严格的东西带来麻烦的数据。此外,网络中的层和神经元将学习数据中可能存在的任何深度嵌入的非线性关系。
然而,这种多功能性是有代价的——神经网络是一个黑盒模型。与我们可以通过查看回归系数来了解模型如何做出决策的回归不同,神经网络没有这种透明性。**此外,神经网络有可能过于拟合我们的数据,而不能很好地概括样本数据。**在我看来,这些缺点值得牢记并设计安全措施,但它们不是回避使用神经网络的理由。
生成我们的训练数据
在我们可以训练我们的神经网络之前,我们首先需要弄清楚如何组织我们的训练数据,以便我们用它建立的模型将是有用的。
我们想预测什么?在我看来,我们的目标变量有两个候选者:
- 输掉比赛的概率。在这种情况下,我们可能希望模型告诉我们损失的概率是多少。话说回来,这只有在我们可以增加或减少赌注的情况下才有用,而在 21 点中我们不能这样做。
- 相反,我们希望我们的神经网络能够识别正确的动作,击中或停留。因此,我们的目标变量应该是“正确的行动是打击还是停留”。
事实上,我花了一段时间才想出设置它的最佳方式。但这是我想到的。
我们需要一种方法让神经网络知道给定的移动是否正确。不需要做到万无一失,只要大体正确即可。因此,我判断一个给定的走法是否正确的方法是模拟一场 21 点游戏:将牌发给玩家和发牌者,检查是否有人有 21 点,只走一步(要么击中,要么留下),模拟游戏结束并记录结果。由于模拟玩家只做出一个决定,我们可以通过他在游戏中是赢是输来评估该决定的质量:
- 如果玩家击中并获胜,那么击中(Y=1)是正确的决定。
- 如果玩家击中并输了,那么留下(Y=0)是正确的决定。
- 如果玩家留下并获胜,那么留下(Y=0)是正确的决定。
- 如果玩家留下并输了,那么 hit (Y=1)是正确的决定。
这允许我们训练我们的模型,以便它的输出是一个是否击中或停留的预测。代码与上次的类似,所以这里就不做详细概述了(你也可以在我的 GitHub 上找到这里)。但是主要特征是:
- 庄家面朝上的牌(另一张看不见)。
- 玩家的总牌价。
- 不管玩家有没有 a。
- 玩家的动作(击或停留)。
目标变量是由上述逻辑定义的正确决策。
训练神经网络
我们将把 Keras 库用于我们的神经网络。让我们先把我们的进口商品放在一边:
from keras.models import Sequential
from keras.layers import Dense, LSTM, Flatten, Dropout
现在,让我们设置用于训练神经网络的输入变量。变量 feature_list 是我在上面列出的特性(X 变量)的列名列表。dataframe model_df 是我存储我运行的 21 点模拟的所有数据的地方。
# Set up variables for neural net
feature_list = [i for i in model_df.columns if i not in
['dealer_card','Y','lose','correct_action']
]
train_X = np.array(model_df[feature_list])
train_Y = np.array(model_df['correct_action']).reshape(-1,1)
实际实例化和训练我们的神经网络的代码行非常简单。第一行(第 1 行)创建顺序型神经网络,它是神经网络层的线性序列。第 1 行之后的行一个接一个地给我们的模型添加层(密集是最简单的层类型,只是一堆神经元)——像 16、128 等数字。指定每层中神经元的数量。
**最后对于最后一层,我们需要选择一个激活函数。这将神经网络的原始输出转换成我们可以理解的东西。**关于最后一层要注意两点。首先,它只包括一个神经元,因为我们在两个可能的结果之间进行预测(两类问题)。其次,我们使用 sigmoid 激活,因为我们希望我们的神经网络像逻辑回归一样运作,并预测正确的举动是击中(Y=1)还是停留(Y = 0)——换句话说,我们希望知道击中是正确举动的概率。
最后两行告诉我们的神经网络模型使用什么损失函数(二元交叉熵是输出概率的分类模型使用的损失函数),并使模型适合我们的数据。我没有花太多时间调整层或神经元的数量,但是如果有人要摆弄我的代码,我会建议将它们作为潜在的改进途径。
# Set up a neural net with 5 layers
model = Sequential() # line 1
model.add(Dense(16))
model.add(Dense(128))
model.add(Dense(32))
model.add(Dense(8))
model.add(Dense(1, activation='sigmoid')) # final layermodel.compile(loss='binary_crossentropy', optimizer='sgd')
model.fit(train_X, train_Y, epochs=20, batch_size=256, verbose=1)
检验我们模型的性能
判断我们的模型是否增加了任何价值的一个快速方法是使用 ROC 曲线(如果你想深入研究 ROC 曲线,请查看你的真实博客链接)。ROC 曲线告诉我们,我们的模型在收益(真阳性率)和成本(假阳性率)之间的权衡有多好——曲线下的面积越大,模型越好。
下图显示了我们玩神经网络的 21 点的 ROC 曲线——神经网络似乎比随机猜测增加了相当多的价值(红色虚线)。其曲线下面积或 AUC 为 0.73,显著高于随机猜测的 AUC(0.50)。
ROC Curve for Our Blackjack Playing Neural Net
我用我的训练数据画了 ROC 曲线。通常我们会希望使用我们的验证或测试数据来绘制它,但在这种情况下,我们知道只要我们的样本足够大,那么它就是总体的代表(假设我们继续用相同的规则玩 21 点)。我们希望我们的模型能够很好地推广(任何新数据都将与我们的训练数据具有相同的基本统计特征)。
该玩了!
在我们的神经网络可以正式开始赌博之前,我们需要给它一个决策规则。**记住,sigmoid 激活(来自我们最终的神经网络层)使我们的神经网络输出正确移动命中的概率。**我们需要一个决策规则,根据给定的概率,我们决定是打还是留。
我编写了以下函数来实现这一点 model _ decision 函数获取神经网络所需的特征,使用这些特征进行预测,并将该预测与预定义的阈值进行比较,以决定是成功还是失败。我用 0.52,因为我们从上次已经知道,对一个 21 点玩家来说,破产是最大的风险。因此,使用 0.52 作为命中的截止值使得我们的模型不太可能命中,因此不太可能失败。
def model_decision(model, player_sum, has_ace, dealer_card_num):
input_array = np.array([player_sum, 0, has_ace,
dealer_card_num]).reshape(1,-1)
predict_correct = model.predict(input_array)
if predict_correct >= 0.52:
return 1
else:
return 0
现在我们只需要将上述函数添加到我们的代码中,在这里我们决定是否点击(如果你想知道我是如何编写这部分代码的,请参考我的 GitHub )。因此,当决定要做什么时,神经网络将根据庄家正在展示的牌、自己手中牌的总价值以及它是否持有 a 来做出决定。
我们的模型相当不错!
最后,让我们比较一下我们的神经网络在简单策略和随机策略下的性能。提醒大家:
- 我对每种策略类型(神经网络、朴素策略和随机策略)进行了大约 300,000 次 21 点模拟。
- 天真的策略是只有在没有机会击败的时候才出手(出手总数低于 12 的时候出手,出手总数超过 12 的时候继续出手)。
- 随机策略是抛硬币——如果正面朝上,否则留下。如果你击中了,但没有失败,那么再掷一次硬币,重新开始整个过程。
让我们看看我们的神经网络是否能够找到更好的策略。下表显示了每种策略类型的结果分布。有两件事引起了我的注意。**首先,我们的神经网络只输了略少于一半(49%)的游戏。**虽然我不认为这是赢了,但对于一场赔率对你不利的比赛来说,这已经相当不错了。第二,它实际上并没有比天真的策略更常获胜,而是能够迫使更多的平局。
Outcome Breakdown by Strategy
我们还可以看看这些策略在我们的关键特征(庄家牌和玩家手牌总数)中的表现。首先,让我们看看庄家的牌对我们三种策略的胜算或平手概率的影响。在下面的图中,如果庄家正在展示一张低牌,我们的神经网络的表现和天真策略差不多。但当庄家亮出更高的牌(7 或更多)时,我们的神经网络表现明显更好。
Probability of Tie or Win vs. Dealer’s Shown Card (Taller Bars are Better!)
我们可以看看赢或平的概率是如何随着玩家的初始手牌总数而变化的。这看起来很有希望——我们的神经网络在各方面的表现一样好,甚至更好。而且不像在绝望谷(玩家手牌值在 12 到 16 之间)表现甚至比随机猜测更差的天真策略,我们的神经网络表现更好。
Probability of Tie or Win vs. Player’s Initial Hand Value (Taller Bars are Better!)
最近的情节暗示了神经网络如何能够超越天真的策略。天真的策略(因为我们是如何编码的)是不愿意在任何时候冒险,哪怕有一丁点失败的风险。另一方面,神经网络会定期点击 12、13、14 或 15。更细致的决策和承担可计算风险的能力似乎使其有别于天真的策略。
Tendency to Hit of Neural Net and Naive Strategy vs. Player’s Initial Hand Value
我们可以看看当玩家的手牌总数在 12 和 16 之间时,神经网络会做什么,以尝试改进我们的天真策略(并且不会给赌场输掉那么多钱)。
看起来,当庄家亮出大牌(8、9 或 10)时,玩家更倾向于出手。但是,即使当庄家展示像 3 这样的低牌时,神经网络仍然有 60%的时间选择击中——这是因为神经网络在做决定时考虑了它拥有的所有特征。所以看起来我们不能轻易地将其决策提炼为几条简单的经验法则。
Neural Net’s Frequency of Hitting vs. Dealer’s Shown Card
结论
希望这篇文章给了你一个关于机器学习如何在现实生活中帮助决策的体面介绍。当您训练自己的模型(无论是决策树、回归还是神经网络)时,请记住以下几点:
- **我的目标变量是否以这样一种方式构建,如果我能预测它,那么我就能解决我的问题?**在你开始收集数据和建立模型之前,确保你预测的是正确的事情是至关重要的。
- 新数据与我训练过的数据有什么不同?如果差异很大,那么统计模型甚至可能不是你问题的正确答案。至少你必须认识到这一点,并建立安全措施,如规范化和严格的(以及诚实的)验证,以及你的模型的测试集基准。
- 如果不能理解模型是如何做出决策的,那么除了使用模型训练过程中获得的测试数据进行严格测试之外,您就无法理解和检查模型的决策。
关于 21 点最后说一句。我大概有一段时间不会再写赌博了(我想探讨的其他话题太多了)。但是如果有人对使用或不使用我的代码感兴趣,这里有几个这个项目的潜在有趣的扩展:
- 尝试通过更优化的神经网络结构来改进模型,或者添加用于拆分 ace 的代码(我没有将此构建到我最初的模拟器中),或者选择比我使用的基本功能更好的功能。
- 给模型算牌的能力,看看这对一副牌和六副牌的情况(这是维加斯的标准)的性能有何影响。
希望你和我一样对此感兴趣。干杯!
我最近的一些帖子,希望你看看:
教神经网络看道路
用卫星图像和卷积神经网络预测交通事故的位置
Source: https://www.tbftraffic.com/traffic-management-london/
问题是
全世界每年约有 125 万人死于道路交通事故,另外还有 2000 万至 5000 万人受伤或致残。如果交通事故的位置可以预测,这可能会产生巨大的有益影响,有助于减少每年的事故数量。例如,路由软件可以避开最危险的区域——特别是在无人驾驶汽车即将到来的背景下。它在保险领域也很有用,可用于预测风险,也可用于政府和地方公路局,以创建更高效的道路维护和改善系统。
解决方案
带着这个想法,我最近与陈山眉完成了一个项目,试图解决这个问题,使用各种形式的深度学习来预测交通事故可能发生的地方。我们对回答这个问题特别感兴趣:
使用卫星图像能提高模型预测交通事故的能力吗?
我们总共建立了三种类型的模型来预测交通事故的各个方面:
- 使用交通事故、人口密度和交通的结构化数据来尝试和预测事故的严重程度
- 使用卫星图像来尝试和预测一个地区是“安全”(无交通事故)还是“危险”(交通事故)
- 一种奇特的混合数据模型,将在结构化数据上训练的多层感知器和在卫星图像上训练的卷积神经网络的输出组合成最终的神经网络层头
这篇文章是关于模型 2,以及我们如何建立一个卷积神经网络(CNN)来预测一个给定区域在交通事故方面有多危险(但不用担心,花哨的模型 3 将是未来博客帖子的主题——它相当糟糕)。
数据
我们选择伦敦作为我们的试验场——部分是因为英国国家统计局有一些关于交通事故、人口和交通的非常全面的高质量数据;部分原因是伦敦是一个大城市,由市中心区、郊区和大小道路组成,这为训练提供了各种各样的图像;部分原因是因为我住在这里,不被车撞是我的既得利益。
该项目的完整代码可以在我的 GitHub repo 中找到。数据来源包括英国运输部(DfT)的道路安全数据、 DfT 的道路交通统计(是的,我们确实雇佣了一些人站在街角数汽车)、来自英国 2011 年人口普查的数据,以及由谷歌地图静态 API 提供的卫星图像。
该方法
我们选择的区域是我在 M25 号高速公路外侧画的一个正方形,M25 号高速公路是环绕伦敦的大型高速公路(对我的美国观众来说是高速公路),目的是为了包括各种各样的道路类型:
为了得到一组不重叠的“危险”和“安全”区域,通过将伦敦分成 0.0005 纬度 x 0.0005 经度的正方形来创建和使用网格系统。这导致了 56 米高(纬度)和 35 米宽(经度)的网格正方形(技术上是矩形),类似于通常用于交通事故分析的 30 米×30 米。
下图显示了叠加在伦敦市中心交通事故地点地图上的方格系统,以提供比例感(事故地点相当有效地追踪了道路系统):
Bonus points if you can spot the Strand and the Thames
一旦我们有了全部方格的列表,我们就使用事故数据集来计算出哪些方格在过去五年中发生过或没有发生交通事故。这些成为我们的“危险”和“安全”类。然后,我们使用谷歌地图静态 API 下载 5000 个“危险”区域和 5000 个“安全”区域的随机样本中每个方块的图像。
下面的图片显示了从每个班级的随机样本中下载的前五张图片。它们表明,危险区域包括郊区的道路、较大的道路和交叉路口(例如,在英国非常常见的环形路),但并非所有图像都一定只是道路,例如,第四幅图像也包含事故发生道路旁边的绿色区域。
安全区域包括没有道路的绿色区域(不足为奇),但也包括有道路的郊区区域,这些区域与发生事故的区域有相似之处。这些图像对 CNN 来说可能更难分类,但对它来说也很重要,因为它们意味着 CNN 不仅了解道路和田野之间的差异,还了解不同类型道路之间的差异。
模型
我们尝试了三次 CNN 迭代,试图产生最精确的模型。我们尝试的第一个版本是一个相当简单的 CNN 模型架构,使用 Keras,在最终的 sigmoid 激活层之前有三对 Conv2D 和 MaxPooling2D 层以及一个密集层。它做得相当好,测试准确率(平均 F1 分数)为 72%,没有过度拟合。
这是我们基线模型的代码:
对于我们模型的第二次迭代,我们在 VGG19 预训练模型的基础上构建了 ImageNet 权重,并通过在输出的基础上训练新的分类器之前首先运行我们的图像来提取特征。我们达到了 74%的测试准确率,但是有明显的过度拟合(即训练集达到了更高的准确率)。
对于我们的最后一次迭代,我们使用 L1 正则化来尝试和克服过度拟合。为了尝试和提高准确性,我们增加了图像输入的大小,并添加了一个额外的密集层到分类器头只是为了更好的测量。
结果呢
最后一次迭代是我们最好的模型,达到了 77%的准确率和最小的过度拟合。构建模型的代码有点复杂(没有双关语的意思),但是在我的 GitHub repo 的 notebook 6 中可以找到。结果如下:
Classification reports (top is the training set, bottom is the test set) and confusion matrix for the final model
我想改进的主要方面是提高召回率,降低误报率——预测 1 =安全,而实际上该区域为 0 =危险。在这种情况下,与预测实际上安全的危险区域的模型相比,这些类型的错误可以被视为成本更高。
今后
为了尝试和提高模型的准确性并完全消除过度拟合,可以在进一步的模型迭代中尝试以下一些方法:
- 下载更多图片用于培训
- 使用不同的预训练模型,如 ResNet50,该模型已在其他 CNN 中用于卫星图像(如此处和此处)
- 冻结预训练模型的特定层,并微调其他层
- 在预训练模型的顶部改变密集连接的分类器的架构(例如,添加更多层或节点)
然而,仅从卫星图像就能正确预测一个地区是否可能发生交通事故的概率为 77%,这仍然令人印象深刻。
感谢阅读——我希望你发现这是一个有趣的话题!将来,我会写我们如何将这个模型与结构化数据结合起来,创建一个非常酷的混合数据神经网络。如果你有兴趣阅读更多,你可以订阅我在 Medium 上的博客,当下一篇文章发表时,你会得到通知。
教一个排外的人工智能健康检查员,和机器学习的伦理
基于德克萨斯州奥斯丁的健康检查分数,并受到这篇关于纽约州水塔检查的媒体文章的启发。
前言:我并不反对我在这篇文章中作为例子的任何一家餐馆,我积极地在所有这些餐馆吃饭。
请继续阅读这些预测的来源!
介绍
我是一名奥斯汀人,一名 UT Austin 的学生,一名脸书的实习生,一名有抱负的数据科学家。
关于数据科学项目,我已经意识到的一件事是底层数据的重要性。
Score average by ZIP Code + Individual Scores
使用对你来说重要的数据既能给你领域的专业知识来发现有洞察力的结果,又能增加你在项目上工作的动力。
这个数据集与我密切相关,因为我在许多这样的餐馆吃过饭,有些得分较高,有些得分较低。
假设
我认为训练一个机器学习模型来预测仅仅基于餐馆名称的健康检查分数会很有趣。我有一种感觉,由此产生的模式最终将是一个排外的模式,比如认为中国餐馆很脏。
Spicy Fish Fillet at Asia Cafe, Average Score: 76.75
在奥斯汀我最喜欢的餐馆中,我敢肯定一些低端餐馆的卫生检查分数会低于理想水平。我相信我的“直觉”(字面和隐喻),无论如何都会去那里吃。
数据探索
为了确定我想如何对问题建模,我从探索和理解数据集开始。
df.head()
其特点是:
'Restaurant Name',
'Zip Code',
'Inspection Date',
'Score',
'Address',
'Facility ID',
'Process Description'
设施 ID 、地址和餐厅名称对于每个餐厅应该是唯一的。
我对差评餐厅的餐厅名称感兴趣,我将“差评”设为 85 分及以下,并生成了一些单词云。
根据我的经验,这听起来不错。在这一点上,我开始意识到教授一个模型的伦理含义,即名称中带有“taqueria”的餐馆比名称中带有“pizza”的餐馆的健康检查分数更差。我后来在建模部分捕捉到了这个想法,并对其进行了讨论。
每个餐厅可能都有过几次检查。随着时间的推移,我对变化不感兴趣,所以我取消了检查日期,用平均分数代替了分数。
groupby = df.groupby("Facility ID")['Score']means = groupby.mean()df_mean = df_mean.join(means, on="Facility ID", how="right")df_mean.drop(columns=["Scorel"], inplace=True)df_mean.rename({"ScoreR": "Average Score"},)df_mean.drop(['Inspection Date'])
地址有 3 行
6500 S US 183 HWY
AUSTIN, TX 78744
(30.164092387667438, -97.69352171343812)
第一行是街道地址,
第二行是德克萨斯州奥斯汀的邮政编码,
第三行是字符串格式的**(纬度,经度)**。
我想把坐标提取到浮点数中,用于我的可视化。如果我真的关心我们的模型的性能,我也可以提取街道名称作为一个特征,因为街道名称可以给我们提供关于邻居的上下文。
def extract_lat(x):
lst = x.**split**('\n')
string = lst[2]
#substring cuts off the leading and tailing brackets
string = **string[1:-1]**
#split to the lat and long
pair = string.**split(',')**
return **float(pair[0])**
def extract_long(x):
... similar
return **float(pair[1])**lat = df3['Address'].**apply(extract_lat**)long = df3['Address'].**apply(extract_long**)df3['lat'] = lat
df3['long'] = long
邮政编码是一个有趣的分类变量,我稍后也可以在可视化中使用它。
['78744' '78758' '78727' '78617' '78701' '78745' '78751' '78757' '78750' '78756' '78753' '78748' '78705' '78746' '78704' '78721' '78613' '78738' '78741' '78702' '78739' '78724' '78759' '78734' '78723' '78703' '78735' '78729' '78728' '78731' '78752' '78749' '78754' '78669' '78722' '78660' '78732' '78725' '78653' '78730' '78641' '78747' '78726' '78719' '78652' '78733' '78717' '78736' '78620' '78737' '78654' '78742' '78610' '78621' '78615']
然后我开始观察这些特征的分布:
我看了检查分数直方图,很多 100 分(耶),左尾(恶)。
Histogram of scores
另一件有趣的事情是查看每个邮政编码的分布情况,是否有些邮政编码比其他的更脏?I 根据邮政编码聚合,并为每个邮政编码绘制一个图表
for _, row in df_agg.iterrows():
if row['total_facilities'] > 10:
zipcode = row['Zip Code'] df_zip = df_mean[df_mean['Zip Code'] == zipcode]
sns.distplot(df_zip['Average Score'])
大多数分布看起来像是 78704 分布, 78719 看起来更像是双峰分布,这是令人不安和有趣的。
地图
好了,玩够了 seaborn 和 matplotlib 。这些信息本质上是地理上的,所以构建一些地图是非常有意义的,我使用叶子和 plotly-Express 来实现这些可视化。完整的笔记本将被链接,所以我跳过一些细节。
首先,让我们看看地图上所有的分数。我用 plotly-express 来做这个。
px.**scatter_mapbox**(df3, lat="lat", lon="long",
**color="Score**",hover_data=['Score'], zoom=14)
接下来,看看每个邮编的平均得分结合个人得分不是很有趣吗?我为此使用了叶子,因为 Plotly-express 不支持 geoJSON (邮政编码形状)。
我使用了一个 groupby 和 agg 来计算每个邮政编码的平均得分。
我找到了一个德克萨斯州的邮政编码 geoJSON ,我用它和叶子根据平均分数给每个邮政编码着色。
我想在地图上标出每家餐馆。与 plotly-express 不同,follow 不会渲染超过 1000 个标记,所以我不得不使用 MarkerClusters。
这就是结果。
FFFFFolium’s nauseating cluster animation, sorry!
Score average by ZIP Code + Individual Scores
Mopac,Lamar 和 I 35 走廊似乎很脏。
第六街和市中心也是如此。
建模
现在我对数据有了更多的了解,我应该有更多的背景来开始建模。
My Xenophobic model at work! I wouldn’t want to eat a at a “Mexican Chinese Meat Butcher Seafood Buffet” either
我想尝试做的是建立一个模型,让只根据餐馆名称预测检查分数**。我有一种感觉,即“民族”餐馆与较差的健康检查分数相关,我想说服一个模特了解这一点。**
How do I get a model to know this is a mexican restaurant?
自然语言处理
NLP 意味着以人类能够理解的方式来表达语言的含义。
餐馆名称包含关于它们是什么类型的餐馆的信息,“taqueria”是与“四川”餐馆不同类型的餐馆,等等。
我可以使用 TF-IDF 将这些信息传递到模型中。
TF-IDF 考虑了我们的数据集中所有单词的词汇,并且根据该单词在整个数据集中的频率来衡量该单词在每行数据中的存在。
如果“cafe”这个词很常见,而“carniceria”这个词不常见,TF-IDF 会认为“carniceria”比“cafe”有更多的含义
应用到我们的问题,我敢打赌,一些餐馆听起来像他们有更差的食品检查分数比其他人。
凭直觉, TF-IDF 会找到一家名为 【墨西哥中式肉店海鲜自助餐】 的餐厅,比 【咖啡厅】 包含更多的信息。
One of the dingiest looking restaurants I have ever been in, but the food is great. Score: 89
预处理:
餐馆名称对于文本字符串来说非常短。我必须小心地预处理我们的数据,明智地选择我们的技术来充分利用数据。
n-gram 是由 n 个单词组成的短语,“taco”是 1-gram,“taco joint”是 2-gram。
考虑到作为文本形式的数据的餐馆名称很短,我将 TF-IDF 限制为 n-grams==1,就像只使用像“taco”和“joint”这样的单词一样。
我可以做的另一种形式的预处理是从我们的餐厅名称中删除数字和符号,“棒约翰的#928”变成了“棒约翰”。
Food from Asters
建模:
我使用了 XGBoost,一个非常通用的模型。
我还得决定如何表达这个问题。
回归: 如果我将问题表述为回归,我可以将目标变量设置为分数。“给定一个餐厅名称,预测它的卫生检查分数”****
或者,我可以通过为一个令人讨厌的分数设置一个阈值,比如低于 85 分,来把这个问题表述为分类。“给定一家餐馆的名字,预测它在卫生检查中得到“坏分数”的几率”****
我选择了 85 分而不是 70 分(不及格),因为不及格的分数很少,我不想要极度不平衡的班级。
# Get the tfidf vectorstfidf_vec = **TfidfVectorizer**(stop_words='english', norm='l2', ngram_range=(1,1))tfidf_vec.**fit_transform**(X['restaurant_name'].values.tolist())train_tfidf = tfidf_vec.**transform**(X['restaurant_name'].values.tolist())regressor = xgb.XGBRegressor()
regressor.**fit**(train_tfidf, df4['score'])classifier = xgb.XGBClassifier()
classifier.**fit**(train_tfidf, df4['score'] < 85)eli5.**show_weights**(classifier, vec=tfidf_vec)
来自分类器的权重,这些是与低于 85 的“坏分数”相关的单词
TF-IDF 和 XGboost 的好处是,该模型非常容易理解,您可以很容易地看到与低于 85 的“糟糕分数”直接相关的单词,结果与预期的一样,并且与早期的单词云相似。
我使用全部数据进行训练,所以让我们用一些任意数据来测试模型。
回归器根据输入字符串预测得分。以下是我发现的一些有趣的预测结果。
$4 for 3 Breakfast Tacos, La Tapatia, Score: 87.5, I have been coming here for years
显然,奥斯汀的一些餐馆往往比其他餐馆更脏,我一直通过查看数据和我们的模型来怀疑这一点。
伦理学
这整个数据集有很多有趣的伦理考量。
准确性与社会危害:
好吧,也许一些餐厅往往不如其他餐厅干净,这是否意味着我可以允许人类或人工智能健康检查员针对这些类型的餐厅?
准确性和不公平地针对某些人群之间的权衡。
有人可能会说防止顾客生病很重要。
另一个人可能会争辩说,针对特定类型的餐馆是荒谬的,因为“数据就是这么说的”
最佳解决方案取决于它是什么类型的问题。
在招聘时,模特不可能被允许使用“种族”或“性别”,因为这些是 EEOC 明确保护的。
在广告定位中,使用那些相同的特征可能更容易被接受,因为不同的人口统计仅仅具有不同的消费模式
数据中的人为偏差 训练数据由人类健康检查员生成。如果那些人类健康检查员讨厌中国餐馆,这个模型也会学会同样的憎恨。
根据我的经验,我有相对较好的信心认为这些数据接近事实,但这种探索仍然表明了盲目训练模型的危险,因为“数据说什么,数据就说什么!”。
一个模型会学习它被训练的数据中的任何东西。
数据科学家的人类偏见:
我试图通过让一个模型认为中国餐馆很恶心来证明这一点。在我找到一个能证明我观点的模型后,我停了下来。这样,我在文章中展示的模型也代表了我的偏见。
我在寻找一种利用数据来证明我的观点的方法,当我找到这样做的方法时,我就停止了。试图提出另一个观点的人可能也会让数据支持他们的观点。
模型复杂度成本:
在我们的例子中,我应用的 TF-IDF 技术相对简单易懂,我们可以看到哪些词与目标变量相关。
但是如果我使用更先进的技术呢?
如果我用 word2vec + LSTM RNNs 举例呢。更复杂的模型,如具有单词嵌入的 RNN,能够理解数百个单词之外的文本内容中单词之间的关系,并且具有类似于人类记忆的长期和短期记忆。
对于如此复杂的模型,要“诊断”为什么模型会预测某些预测结果要困难得多。
像谷歌这样的公司肯定也有成千上万的功能和模型,它们不仅理解功能,还理解这些功能之间复杂的交互和关系,什么人可能理解这样一个模型的工作方式?
如果我们不明白为什么模型是准确的,我们还能相信准确的模型吗?
结论
该数据集中有 22,000 个检查,5,000 个被检查的独特企业,以及大约 50 个邮政编码。
我的模型只使用 TF-IDF 和餐馆名称进行预测。
如果有人希望构建一个更关注模型准确性的模型,数据集中还包含一些其他重要的功能。
其他一些很棒的特性是邮政编码作为一个分类特性。
以(北、南、东、西)作为分类或文本特征的街道名称,包含位置的邻域级别上下文。
过程描述有“常规”、“跟进至低分”和“第二次跟进至低分”,必须有某种方法来教导一个模型,该模型在较差的检查之后分数通常会上升。我在这次探索中没有使用时间序列,但肯定有办法。
日期,也许卫生检查员周一更暴躁?
这就是我对一个数据集的分析,这个数据集既与我个人密切相关,也与我毫不相关(外出就餐时,我“相信自己的直觉”)。
教人工智能如何做量子力学
Pictured top left: Schrodinger, Einstein and Pople. Pictured bottom middle: Hinton and Bengio
使用传统的先进方法,精确计算化合物的量子力学性质,如原子化能,可能需要几个小时到几周的时间。这篇文章探索了使用深度神经网络在几秒钟内计算上述属性,准确率达到 99.8%。
Training a DNN to predict atomization energy based on a Coulomb matrix input. The average error is 3 kcal/mol, equating to a mind-boggling 99.8% accuracy
答在 20 世纪 20 年代发现量子力学之后,科学家们很快意识到从该理论中产生的基本方程只能在最简单的系统中求解(比如氢原子……)。用诺贝尔奖获得者保罗·狄拉克自己的话说:
“潜在的物理定律必要的数学理论的大部分物理和整个化学因此完全知道,困难只是这些定律的精确应用导致方程太复杂而无法解决。因此,发展应用量子力学的近似实用方法变得很有必要,这可以导致对复杂原子系统的主要特征的解释,而不需要太多的计算”——保罗·狄拉克,1929
接下来的快速发展是寻找新的近似方法来处理这个复杂的问题。由此产生了两种最先进的方法: 哈特里-福克理论(HF)密度泛函理论 (DFT)。
特别是,在 20 世纪 90 年代,DFT 取得了突破性进展,至今仍保持着领先水平。
今天,DFT 是计算化学和材料科学的基石。例如,它可用于精确模拟大分子的电子密度表面,如巴克敏斯特富勒烯:
Electron density map of Buckminsterfullerene (C60)
DFT 和 HF 的问题是,要得到准确的结果,还是需要很长的时间:小时,天甚至几周。
我们将使用深度神经网络的预测能力将这个时间缩短到几秒钟。
这篇文章附带了一个 Google Colab 笔记本,可以用来阅读和深入研究这里提到的一些过程。
最后,对最初出版这部作品的 G .蒙塔冯等人给予应有的感谢。确实是一个伟大的发现,他们正在继续做一些有趣的事情。
1.什么是库仑矩阵,为什么它很重要?
库仑矩阵是一种装置,本质上存储不同原子相互作用的所有信息。
准确地说,它储存了分子中所有原子对的成对静电势能。
分子的每个原子都有一个与之相关的 电荷 。此外,每个原子都有一组表示其在空间中的位置的 3D 坐标。因此,对于每一对原子,我们记下两个原子的距离。那么库仑矩阵就是:
Definition of the Coulomb Matrix
我们希望使用库仑矩阵作为我们的数据输入,因为它具有预测能力。
事实上,给定库仑矩阵,我们可以进行 DFT 或 HF 计算,以精确计算复杂的量子力学性质(库仑矩阵直接进入薛定谔方程——参考前面的图像)。
我们本质上是使用库仑矩阵来隐含地教导机器学习模型关于量子力学的规则。
2.库仑矩阵有什么问题?
事实上有三个问题。幸运的是,这些都可以解决,仍然可以产生一个非常有用的模型。
2.1 不同大小的分子有不同大小的库仑矩阵。这与机器学习不兼容。
这个问题的解决方案是填充较小分子的库仑矩阵的边缘,就像这样:
幸运的是,我们使用的数据中已经生成了填充库仑矩阵。我们暂时不需要担心这个问题。
2.2 存在几个(N!准确地说)标记你的分子的方法——每种标记方案都会产生不同的库仑矩阵。
Different atom labeling leads to different Coulomb matrices of the same molecule
解决这个问题的方法是简单地按照最大原子的顺序对矩阵进行排序。
但是有一个问题——在排序时,我们实际上给矩阵添加了一点噪声,所以每次排序都略有不同。这使神经网络暴露于同一库仑矩阵的几个微小变化,使其更加鲁棒,并防止过拟合。
2.3 订单中包含大量与标签相关的信息
这个问题可以通过将库仑矩阵通过激活函数转换成二进制输入(0 和 1)来解决。这方面的细节并不重要,要了解更多细节,以及这篇文章中提到的许多其他细节,请阅读以下内容:学习原子化能量预测的分子不变表示
Converting the Coulomb Matrix into a Binary input
对于以上两个问题,这些输入输出类会整理一下。你可以通过代码工作,或者你不能这样做,只是信任它;)
Stochastic augmentation and input processing functions
3.我们的数据是什么?
我们使用了大约 7000 个分子的数据,这些分子具有几个不同的官能团。
对于每个分子,库仑矩阵已经计算出来(这在代码中很容易做到;每个分子的原子坐标都使用 MM94 力场进行了优化——都相当标准。
对于每个分子,我们还使用 DFT 实现计算其原子化能量,这是一种量子力学属性。这是我们试图预测的数据,我们将使用计算值来训练我们的神经网络。
The flow of data from molecule to quantum energy prediction
4.我们的深度神经网络是什么架构?
我们使用一个非常简单的架构:2 个完全连接的隐藏层,每层分别有 400 和 100 个神经元。
使用 Xavier 初始化对重量进行初始化。
更复杂的架构有很大的发展空间(请随意尝试,如果发现更好的,请告诉我),但这个简单的结构适用于这个问题。
We used something somewhere in between these two…
我们使用 Adam 优化器来最小化我们的 MSE(均方误差)损失函数。
神经网络在 Google 的 Tensorflow 库中实现,代码在 Colab 笔记本中。
5.结果
如果你想深入了解更多细节,请点击这里查看 Google Colab 笔记本。
您应该能够毫无问题地运行它,并且神经网络应该训练得非常快(大喊免费 GPU 的 Google Colab)。
回归的结果如下所示。很好,如你所见…
The straight line represents a perfect prediction while the scattered points represent predictions made by the DNN
6.后续步骤
要深入探究这篇博客文章中的更多概念,请继续阅读发表这项研究的原始论文。
这个研究小组发布了更多关于这个想法的论文,所以一定要去看看。
如果你喜欢这个,给这个帖子鼓掌,在 LinkedIn 上和我联系,告诉我你喜欢什么。下次见!
教人工智能起草魔法:聚会
或者,如何训练你的机器人来训练你的龙
概观
在《魔术:收集草稿》中,玩家反复地从一副牌中选择卡片,尽可能地制作出最好的一副牌。使用人类进行的草稿中的数据,我训练了一个神经网络来预测人类将从每副牌中取出什么牌。在这项任务中,它达到了 60%的准确率。在 40%的情况下,当人和模型不同时,模型的预测选择往往比人的选择更好。可以在这里找到一个笔记本,上面有模型训练代码和样本结果。
词汇表
- 魔术:聚会[MTG]:有史以来最好的纸牌游戏。“有点像扑克和象棋的结合,但是有龙”,这是我在去比赛的路上对拼车司机描述的。作为一名玩家,你召唤并指挥各种各样的神话生物,然后当你们两个施展魔法将它们推向更高的高度时,它们与对手的生物一决雌雄。
- 构造:MTG 最常见的玩法。比赛开始前,每个玩家制作一副 60 张的牌,并把它带到战场上。优点:自我表达(你可以选择你的牌组中放什么牌)。缺点:必须提前获得所有该死的卡($$$)。
- 草稿:在作者看来,扮演 MTG 最好玩的方式。你和其他 7 名玩家围坐在一张桌子旁。你们每人打开一包 15 张的卡片。你从你的包里抽出一张牌,然后把剩下的 14 张递给你的左边。你从这 14 张牌中抽出一张,然后把 13 张递给你的左边。重复,直到所有的牌都没了;现在你面前有 15 张牌。然后循环又开始了:你和其他 7 个人每人打开第二包。重复第三次,你有 45 张牌。然后用你起草的卡片做最好的一副牌。选秀的美妙之处在于,每个人都是在一个公平的竞争环境中开始的,而且每次都是不同的,因为你永远不会两次选择同一副牌。
要掌握草稿,你必须平衡每张牌的原始能量水平,牌与牌之间的协同作用,以及你在任何给定时间从剩余牌中接收到的信号。
培训用数据
魔法工厂的老板好心地给我发了一个. json 文件,里面有第二部最新的 MTG 系列《拉夫尼卡行会》的 2130 份草稿。
我还搜集了 draft sim 的档案,在这个网站上,人们可以按照预先设定的挑选顺序练习与机器人对抗。根据这一数据训练的模型与根据 Flooey 数据训练的模型达到了类似的准确性水平,但我注意到模型做出了更差的选择,因为 Draftsim 用户比 Flooey 用户做出了更差的选择,可能是因为他们没有参与赌注。尽管 Draftsim 比 draft sim 多几个数量级。
数据表示法
为了表示一副牌中可供选择的牌的集合,我们可以使用一个长度为 N 的向量,其中 N 是 Ravnica (250)的公会中不同牌的数量。每张卡都有一个索引。您看到的第一副牌中有 15 张牌,因此它的向量将有 15 个 1(该副牌中牌的索引)和 235 个 0。第二个包将有 14 个 1 和 236 个 0,等等。
为了表示我们已经选择的卡片,我们可以使用另一个长度为 N 的向量,其中每个索引处的值是我们已经起草的卡片的编号。每次选秀的第一个选秀权都是零。对于第二次选择,将有 1 个 1 和 249 个 0。对于第三次选择,它可能是 2 个 1 和 248 个 0…除非我们从前两包中取出同一张牌,在这种情况下,它将是 2 和 249 个 0。
总之,我们模型的输入是一个长度为 2N 的向量。
输出是一个长度为 N 的独热编码向量,在人拿的牌的索引处被设置为 1,在其他地方被设置为 0。
这种表示忽略了草稿的一个重要特征:记忆你在之前的一副牌中看到的和没有拿到的牌。职业玩家使用这些信息来猜测他们在未来的牌包中可能会看到什么牌。我们可以通过给每个输入增加额外的 45 个长度为 N 的向量来表示。这些向量中的第一个将代表我们第一次选择时看到的牌,除非这个*是我们的第一次选择,在这种情况下,它都是零。一般来说,这些向量的第 K 个代表我们在第 K 次选择时看到的牌,如果我们确实已经进行了 K 次选择,否则都是零。
在模型中包含这些信息会将输入表示的大小乘以 24,这对于只有 2000x45 个数据点的情况来说并不理想。随着更多的数据,我认为这可能是一个有价值的功能添加。
建模
我试验了一个线性 SGD 分类器,它达到了 50%的准确率。然后,我尝试了一个神经网络,它有两个 512 个神经元的密集层,中间有一个 N 长度的 softmax 层,准确率达到了 59%。
定性评价
我浏览了测试集中的一些草稿,让模型在每个阶段说出它会选择哪张牌,给定已经选择的牌,以及人类选择的牌。你可以在这篇文章附带的笔记本中看到它们。
模特绝对理解色彩的概念。在 MTG 有 5 种颜色,任何给定的草稿牌都可能只使用其中 2 或 3 种颜色的牌。因此,如果你已经拿了一张蓝卡,你应该更有可能在未来的选择中拿蓝卡。我们没有告诉这个模型,我们也没有告诉它哪些牌是什么颜色。但不管怎样,它还是学会了,通过观察哪些卡片经常是相互组合的。
由于 MTG 问题还没有像国际象棋和围棋那样得到解决,所以不可能确切地说模型的选择有多好。我是一名正派玩家,当我看牌时,我看不出有什么明显的问题。事实上,当它和人类绘图员意见不一致时,我发现我倾向于更喜欢模型的选择。但我有偏见,所以请你自己看看这些精选,然后告诉我你的想法,或者让你最了解 MTG 的朋友去看看,然后反馈回来。
毫无根据的猜测
让一千个人猜一大罐软糖里有多少颗软糖。平均每个猜测的绝对误差。然后平均猜测值,取that的绝对误差。后者会少错一些。
http://wisdomofcrowds . blogspot . com/2009/12/chapter-one-part-I . html
我认为类似的事情正在这里发生。每个人都高估一些牌,低估另一些牌。将所有这些误差平均在一起,你会得到一个更好的结果。
未来的工作
如果我们对训练集中的每副牌都有匹配结果(即,每副牌最终赢了多少局),我们可以让模型不仅针对与人类选择的相似性进行优化,还针对进行给定选择后预期牌的质量进行优化。对于一副牌中的每一张牌,模型会从这一点出发,设想出成千上万种可能的走法,并评估最终的牌组。然后它拿走给它最好的梦的卡片。也就是说,我们可以全力以赴阿尔法零。
另一个令人兴奋的可能性是将来自 MTGJSON 的数据添加到模型中。现在,每张卡只是 1 到 250 之间的随机整数。有了来自 MTG JSON 的信息,我们将添加关于哪些卡片是相似的明确信息。这将允许模型起草一个新的集合,而不用看到人类先起草它。
直到下一次,愿你无法区分足够先进的魔法和技术。
教人工智能写流行音乐
因为谁还有时间自己写呢?
我从来都不擅长写歌词。在我高中的 ska 乐队中,我创作了圆号部分和一些其他乐器,在我大学的一个无伴奏合唱团中,我总是整理已经写好的歌曲的封面。很少有一场斗争让我觉得我可以写一首关于它的歌,但当我写的时候,它们总是俗气和蹩脚的。经过多年的放弃,我终于发现了我需要的工具来解决写歌词的问题,同时将自己从过去的跛脚感或劣质感中分离出来。利用递归神经网络和一个与我心心相印的数据集,我将最终解决几十年来一直存在的问题——写歌词。
The CD that started it all
当我 7 岁的时候,我得到了一张汉堡王的 CD,作为儿童餐的一部分:一张 7 首歌的后街男孩 CD,名为“给粉丝”。这张专辑点燃了我对乐队的爱,这个乐队很快就发行了他们的热门歌曲“我想要那样”。那首歌几乎毫无意义。《我想要那样》是瑞典音乐创作巨星马克斯·马丁在他的英语还不流利的时候写的,这就是为什么这首歌在任何时候表达的意思都不一致。由于其商业上的成功和它的意义,在人工智能生成的歌曲中,“我想要它这样”是一个伟大的一致性基准。
使用生成神经网络模型,我可以从他人的作品中获得灵感,并通过与写歌相关的作家障碍,直接进入编辑阶段。因为我对男孩乐队深深的(和真正的)热爱,我将记录我使用递归神经网络(RNN)编写男孩乐队歌词的人工智能艺术的尝试。这个项目使用的所有代码都在我的 GitHub 上,特别感谢 T2 的丹尼·门多萨的帮助。以下乐队的完整作品用于训练我的模型:
- 后街男孩
- 超级男孩
- Boyz II Men
- 一个方向
- 我们为什么不呢
- 新来的孩子
- 乔纳斯兄弟
- 通缉犯
LSTM and GRU nodes are great for recognizing sequences in data Source
生殖模型绝不是新的,但与人类的艺术相比,通常不会受到重视——明显的例外是售价超过 40 万美元的人工智能生成的艺术作品。有不同的技术用于生成不同类型的艺术——生成对抗网络(GAN)生成图片,而 rnn 由于其识别和创建连贯序列的能力而生成音乐和文字。为了这个项目,我在我的神经网络中使用了门控循环单位(GRU)层,但该领域的同事也成功地使用了长短期记忆(LSTM)网络。
为了收集数据,我结合使用了 web 抓取和 python 包调用。最初,我计划抓取我想要的歌曲的所有歌词,但被狡猾的网络开发者阻止我从他们的网站抓取 700 首歌曲。由于我只能获得艺术家和歌曲名称的列表,所以我使用 PyLyrics 包制作了一个去掉了任何格式和标点符号的歌词列表。我将从我的输出中提取一系列单词来制作一首歌曲,而不使用歌曲本身的任何格式。一旦我有了歌曲的所有歌词,我将所有的单词添加到一个列表中,作为生成 7 个单词长的单词序列的标记。在删除重复序列后,我训练我的 RNN 模型来预测每个序列的最后一个字,给定前 6 个字。下面的函数显示了模型如何获取一个种子词,并生成我们可以选择长度的歌词。
使用我的 RNN 和这个 gen_sequence 函数,我编译了模型的输出来写一首男孩乐队的歌。模型的原始输出在左边,模型被训练的时间在右边。尽情享受吧!
教 RNN 人写代码
请放心,您可以阅读本文的其余部分,知道您的开发职业不会有任何风险。
上学的时候对计算机科学和开发了解不多,偶然发现了这个很酷的网站。当键盘上的任意键被点击时,它会输出视觉上有意义的代码。它让任何人看起来都像一个专业黑客,整个矩阵都是黑底绿字,发现这个工具意味着巨大的责任,因为它有可能给人留下深刻印象——但这是另一个故事了。
Source code of the matrix (Cloned from Keanu’s GitHub)
几年后,在发现了 RNN 氏症之后,在抽出一些空闲时间从事这个迷你项目之后,我终于有机会目睹了“代码创建”,结果令人捧腹。
数据集
对于本文,我决定用两个数据集来训练网络:
- 我从 https://github.com/gcc-mirror/gcc 的拿的几个 C 文件。(完全公开——因为我的 C 语言知识是中级的,所以我随机选择了两个看起来足够长的 C 文件)
- HTML 页面——没有任何内联或外部 CSS 或 Javascript。
框架和平台 我很喜欢学习 TensorFlow (v2.0)和 Keras ,但我会将本教程主要放在 TensorFlow 上,并在我认为比 TensorFlow 更容易实现或理解的地方提供 Keras 实现的示例。
我使用过Google Colab——这是一个由 Google 提供的很酷的云服务,允许你完全在云上运行你的 Jupyter 笔记本 env(无论是 CPU 还是 GPU 运行时)
想法
在文本生成领域,递归神经网络——特别是长短期记忆(LSTM) 网络擅长记住给定输入的输出历史,然后相应地预测新的结果。
这听起来可能比实际情况复杂一点,所以让我试着分解一下—
考虑一下正文
这只狗被命名为猫。
现在,当我们将此作为训练数据提供给 RNN 时,我们将文本中的每个标记等同于其输出的直接邻居。
Input to Output correlation [ training data ]
每个[i+1]元素被训练为每个第 I 个元素的输出。
步伐
1。导入库和数据集
使用 Google Colab 允许我们通过使用 google.colab 连接到 Google Drive 上的数据集。验证您的帐户后,您可以装载驱动器并指向您的数据集。
2。准备查找表和数据集
查找表负责将字符转换为整数,并将整数转换为字符。字符的查找表是建立在我们的文本词汇上的。
现在,我们可以将数据集分成输入(dataX)和输出(dataY)。为了创建数据集,我们通过每个字符的步长来累积输入和输出。这里,每个训练模式是一个字符(输入)的 100 次步进,后跟一个字符输出。我们从文本的开头开始,直到结尾,如果有任何剩余部分,就把它们去掉。
sequences = char_dataset.batch(seq_length+1, drop_remainder=True)
char_dataset = tf.data.Dataset.from_tensor_slices(text2int)def split_input_target(chunk):
dataX = chunk[:-1]
dataY = chunk[1:]
return dataX, dataYdataset = sequences.map(split_input_target)
3。构建和编译模型
def build_model(vocab_size, embedding_dim, rnn_units, batch_size):
model = tf.keras.Sequential([
tf.keras.layers.Embedding(vocab_size, embedding_dim,
batch_input_shape=[batch_size, None]),
tf.keras.layers.GRU(rnn_units,
return_sequences=True,
stateful=True,
recurrent_initializer='glorot_uniform'),
tf.keras.layers.Dense(vocab_size)
])
return model
并且训练模型!这个模型在 Colab 上被训练了 30 个时期
model.compile(optimizer='adam',loss=tf.keras.losses.sparse_categorical_crossentropy(target_example_batch, example_batch_predictions, from_logits=True)**)**model.fit(dataset, epochs=EPOCHS, callbacks=[checkpoint_callback])
4。生成结果
有两组共享的结果
- HTML 数据集——使用的数据集来自维基百科(随机页面),因为它有很多 HTML 属性。我尽可能地删除了内联 CSS,这是训练数据的样子-
(INPUT) looks structured even without most of the CSS elements
下面是模型生成的代码(HTML 预览)
(OUTPUT) Lower temperature predicted output, 5000 predicted characters
(OUTPUT) Higher temperature predicted output, 10k predicted characters
温度越低,文本越容易预测。更高的温度导致更令人惊讶的文本。
OUTPUT: Lower temperature, 10k predicted characters
2.生成 C 代码
胡言乱语,但努力。
感谢您的阅读!
教 GPT 2 号变形金刚幽默感
如何在 PyTorch 中单个 GPU 上微调大型变压器模型
Photo by Ben White on Unsplash
在这篇文章中,我演示了如何使用预训练的 GPT-2 来生成文本,然后使用单个 GPU 在特定的语言建模任务中对其进行微调。在这种情况下,我试图通过在笑话数据集上对模型进行微调,让它变得有趣。
GPT 2 号
最近 OpenAI 团队发表了一篇文章更好的语言模型,以及一篇技术论文语言模型是无监督的多任务学习者关于训练更大更好的语言模型。他们研究语言模型的能力,以生成连贯的文本,并在零射击设置中解决 NLP 任务,这意味着使用模型解决没有明确训练过的任务。
Image Credit: OpenAI
他们创建了一个基于 transformer 的语言模型,他们称之为 GPT-2,并在一个巨大的 40GB 互联网文本数据集上训练它。他们在语言建模任务中训练该模型,该任务是预测单词序列中下一个单词的概率。为语言建模训练 NLP 模型,然后为特定任务进行微调是训练 NLP 模型最常见的途径之一。为语言建模预先训练模型是方便的,因为它不需要带标签的数据来学习语言的结构——它只需要纯文本,这是大量公开可用的。大多数公开可用的预训练 NLP 模型是为语言建模而训练的。
他们在训练后生成文本的结果令人印象深刻。这些片段感觉非常人性化和连贯,几乎令人毛骨悚然。此外,该模型在各种语言建模任务(包括摘要、阅读理解和翻译)的零射击设置中获得了最先进的分数。
微调实验计划
所以我决定用 GPT 2 号做一点实验。我觉得教模特讲笑话会很有趣。为此,我需要一个笑话数据集和一个预训练的 GPT-2 模型进行微调。
Photo by Helloquence on Unsplash
由于人工智能社区和一些特定团队的慷慨,他们发布了预先训练的神经网络模型,解决像这样的挑战性任务的相对廉价的解决方案是可能的。从头开始训练这样的大型神经网络模型将花费数万美元,在某些情况下,甚至数十万美元。在单个 GPU 上,针对新任务对预训练模型进行微调可能需要几个小时。我会做到的。
Huggingface 已经在 PyTorch 中提供了许多预先训练好的变形金刚模型以方便使用。我将使用他们预先训练的 GPT-2,并在 Kaggle 上发布的这个短笑话数据集上进行微调。
GPT-2 有 4 种不同的尺寸——小、中、大和 XL ,分别有 124 米、355 米、774 米和 1.5 米的参数。我发现,一个中等大小的 GPT-2 模型是我可以在单个 GPU 上用合理的输入序列长度进行微调的最大模型。
Image Credit: Image by Jay Alammar from post The Illustrated GPT-2
通过生成文本来测试预训练模型
在对笑话的模型进行微调之前,我将在生成文本时对其进行测试。
在下面的要点中,我演示了如何通过使用来自 huggingface 的预先训练好的中等大小的 GPT-2 来生成文本。首先,我将向模型提供以下文本片段,并让它生成其余部分:
‘母体’无处不在。它就在我们周围。即使现在,就在这个房间里。当你向窗外看或者打开电视时,你可以看到它。当你去工作的时候,当你去教堂的时候,当你交税的时候,你能感觉到。是这个世界蒙住了你的眼睛,让你看不到真相……'
‘人工通用智能是……’
教父:“我要给他一个他无法拒绝的提议。”… '
从生成的关于技术的阴谋论,关于 AI 行业的威胁性预测,以及教父与自己的对话来看,我会说文本生成在起作用。
在单个 GPU 上微调模型
大型变压器模型通常在多 GPU(或 TPU)设置中训练,因为在大型模型上训练合理的批量大小和序列长度需要大量张量/图形处理单元内存。我的机器配的是单颗 GeForce 1080 Ti,内存 11 GB。通过对中型 GPT-2 模型的经验测试,我发现我的 GPU 在一个批处理中处理的最大总序列元素数大约是 550,这不是很多,可能不足以成功进行微调。
但是我们可以考虑一些事情来改善这种情况。
首先要注意的是,基于 transformer 的模型的前后传递中的批量大小不起作用,因为使用了层归一化而不是批量归一化。在图层归一化中,每个特征在特征尺寸上归一化,不涉及批量尺寸。
第二,我们可以在多次向前-向后过程中累积梯度,然后才进行模型权重更新。这样,我们不必将整个批次的计算图存储在存储器中,但我们可以一个序列接一个序列地处理,并获得相同的结果,就好像整个批次在单次向前-向后传递中被处理一样。
考虑到这一切,我将一次处理一个最大长度为 550 的序列,并对每个 BATCH_SIZE 处理的序列进行模型权重更新。
笑话的长度在数据集中变化很大——有许多短序列。为了使一个优化步骤中的总序列元素数更加一致,我将尝试在每个 550 个元素的序列中加入尽可能多的笑话。
结果和结论
Photo by Marcela Rogante on Unsplash
教人工智能生成对人类来说很有趣的文本是一个困难的问题,我认为这比生成一个连贯的文本要困难得多。即使对一个人来说,这也不容易做到——这需要一种特殊的创造力,对环境的理解,甚至对人类心理的理解。向语言模型输入许多笑话可能不足以让模型真正了解什么让事情变得有趣。训练人类水平的开玩笑模型可能需要更复杂的技术和更多的数据。
尽管如此,看到这种语言模型的尝试还是很有趣的。偶尔,这个模型会设法产生一个有趣的人类水平的笑话。
*当我开始实验时,我没有注意到数据集中有很大一部分笑话是种族主义和粗鲁的,这意味着你可以在模型生成的笑话列表中预期相同的内容。我为此道歉并做好准备。
这里是 完整生成的笑话列表 。
如果你在生成的笑话列表中看到一些好的和有趣的东西,请在评论中发布。:)我自己也没有全部通读。
这是转贴自我的原创博客。
教他们扮演上帝
对初学者友好的角色生成介绍
Photo by Aaron Burden on Unsplash
冒着成为另一个“用 RNN 生成文本”教程的风险,想到 Shakespeare 和 Lewis Carrol 在坟墓里为这些普通模型通常生成的文本畏缩不前,我选择了一条不同的路线,但同时决定对此进行挖掘。
《圣经》是人类历史上销量最大、最有影响力的书籍。人类思想、阐述和创造的巨大宝库都围绕着这本书。
这就引出了一个问题——递归神经网络能被很好地训练以产生布道吗?
在这个玩具示例中,我们将通过相对简单的代码行来尝试这一点。我们的期望不高,因为我们将使用一个非常简单的架构。这篇文章的目标是学习如何在 tensorflow 中使用 RNNs 进行文本生成。我以前在 tensorflow 中训练神经网络时确实假设了一些背景,只是我不会解释例如损失函数或 softmax 是如何实现的。
版本:Python 3.6 和 Tensorflow 1.15.0。
我们开始吧!
数据
既然深度学习没有数据就无法进行,那我们就来获取一些数据。古腾堡计划有一些精彩的书籍供公众免费使用[多么讽刺啊,因为古腾堡圣经是第一个用活字印刷的文本]。我们将在这里得到国王詹姆士版本。
预处理
圣经的结构相对来说比其他书简单。即使这样,我们可能会遇到一些我们不希望被馈入我们的模型的怪异角色。让我们来看看数据:
我们不希望我们的模型学习像' \ '、' { '、' \n '这样的字符。事实上,让我们看看文中独特的人物:
print(sorted(list(set(data)))
数字很重要,因为它们表示诗句,其他标点符号也可以,但我们可以没有以下内容:
那更好。这段文字中有 48 个独特的字符。
在我们继续这个模型之前,我们需要做两件小事。这些角色不能以他们本来的样子存在。我们需要对它们进行整数编码,以便能够将它们作为输入数组。类似地,当我们预测字符时,我们需要一种方法将获得的整数再次解码为字符。所以我们可以创建两个字典,一个保存一个字符到一个整数的一对一映射,反之亦然。让我们这样做:
char_to_int = dict((i, char) for char, i in enumerate(unique_chars)) int_to_char = dict((char, i) for char, i in enumerate(unique_chars))
在此之前没有什么需要解释的,请检查您是否有以下映射:
Char to int
int to char
批量生成
许多深度学习训练碰巧涉及到对数据的大小、形状、结构等做出决定。文本太大,无法一次输入,现实世界中的大多数问题都涉及到比我们目前正在处理的文本更大的尺寸。分批训练不是一件好事。这是必要的。
特别地,RNNs 使用通过时间的*反向传播【BPTT】*进行训练,这基本上是在每个时间步长上展开的传统反向传播。一个很好的引子就是这个。
因为我们不能在整个文本上应用 BPTT,所以我们在生成的批处理上应用它。我们如何生成这些批次?这主要是一个设计问题,但是我已经实现了下面的过程:[如果您只对代码感兴趣,可以跳过这一部分]。
(1)将全文分成 16 块。
(2)每个块包含字符序列。我们选择 256 作为我们的序列大小。
(3)我们创建的每个批次 i 包含来自每个块的第 i 个序列。这个。意味着每批包含 16 个序列,每个序列的大小为 256。这意味着批次 1 具有来自*块 1、块 2、…的第一个 256 字符序列。,第 16 块。同批次 2、批次 3、…、*等。我们有多少批?总共有n
个字符,这是标准的中学数学
n = batch_size * sequence_size * no_of_batches
当然,这不会总是被整除,这取决于所选择的四个整数值。例如,在我们的例子中,n = 4233042, batch_size = 16, sequence_size = 256, no_of_batches = 1034
但是如果你仔细观察,最后一批的序列大小不可能是 256,而是一个更小的值【拿出笔和纸,试着算出这个值会是多少】,因为当我们到达最后一批时,我们已经用完了所有的字符。
我们可以放弃这最后一批,以避免以后出现形状不匹配的问题。我们现在有了no_of_batches = 1033
,所有的阵列都在(16, 256)
成形。
好了,总之,1033
批,每批包含 16 个序列,每个序列256
字符长。
顺便说一下,我描述的整个过程有一个名字——*截断的时间反向传播。*很多细节这里。
下面是完成我刚才提到的所有事情的代码:
Batch generation
下一个问题是,我们如何创建输入值和目标值?这很简单。考虑下面的例子:
X -> the dog
。
这方面的目标是:
Y -> he dog
。
目标向量中的每个字符 i 都是输入向量中的第( i + 1】个字符。注意Y
是如何比X
小一个单位尺寸的。这是因为当你到达X
的最后一个角色时,就没什么可预测的了。因此,我们可以简单地删除X
中的最后一个字符。这个小小的观察很重要,我们最终得到的X
和Y
都是(16, 255):
Creating the Dataset
搞定了。我们现在准备构建我们的模型。
架构和培训
我们将选择一个简单的架构——两个隐藏层,一个多单元,每个 LSTM 单元包含 256 个隐藏单元,一个 softmax 输出层包含 k 个单元,其中 k 是我们数据中唯一字符的数量【有道理,对吗?].
就是这样!
Model Architecture
这应该是不言自明的,除了我为输入和标签添加了一个热编码的部分。注意,在我们的例子中,这将形状(16, 256)
转换为(16, 256, k), k = 48
。我选择了少量的时期来检查训练损失是否表现得像它们应该表现的那样——逐渐减少。稍后,您可以随时使用这些超参数。
让我们训练我们的模型:
Train for 5 epochs
请注意,您需要将每个时间步 t 的最终状态作为( t + 1) 的初始状态。这是至关重要的。
我们得到以下损失曲线:
Train Loss per epoch
漂亮的肘状动作。损失有:[1.54, 1.16, 1.10, 1.07, 1.05]
生成神的话语
真正有趣的时候到了。让我们用这个简单的模型来生成一些文本:
我们将提供一个开始序列,并要求模型预测开始后的 256 个字符。因为我们的 softmax 返回选择每个字符的概率,所以我们可以灵活地决定选择哪个字符。总是选择最大概率字符会使模型自我重复,表现得像一个无限循环,一遍又一遍地打印相同的值。相反,我们对概率进行排序,取五个最大值,重新归一化,然后从这五个值中随机选择。这引入了产生更好结果的随机性:
Words of God
让我们来看看我们的 LSTMs 发出了什么样的布道:
神和耶和华所喜悦的地,我要向耶和华所喜悦的,就是向旷野所喜悦的,和一切耶和华所喜悦的
爆笑!这里还有一些:
神也看顾服事他们。那离弃他们如会众之子的,耶和华已经成就了,且喝吧。因为耶和华你的神已经成就了。我却为我应允你。你借着你的光所说的耶和华心之神的分裂
神与光。我对他说,这要在我身上发生的事,我们为什么没有信你,又在仇敌中间呢。夫子,我要把这些都预备好了,送给你,放在会众面前
几乎所有这些在语义上都是无意义的,但请注意,这个模型没有任何关于单词、字母或数字是什么,标点符号是什么,结构是什么,语言是什么的信息。经过 5 个时期的训练,我们可以看到一些有趣的结果。例如,它知道很多文本都是以数字开头的。它确实在新的讲道之前增加了正确的数字和冒号的结构。它还学会了在各处添加标点符号,就词汇而言,大部分单词都是正确的。
让我们试试不同的开始顺序,只是为了好玩。这是我们的模型为“耶路撒冷”想出的:
耶路撒冷:惟有利未人,他的城要被火烧死,要被咒诅。我设了一个比喻,说,你们就是这地,也是属他们的。没有人奉他的名。他们好像圣灵,他们列祖的话是指着他们说的
耶路撒冷,宝座,三匹马,和祭司的仆人陀拉,都归与这俗语。因为众水必流在耶和华殿的坟墓上
耶路撒冷,和他们的父。有能力攻击耶和华的,只有这一位,就是耶和华的话是什么,并偶像的挂物。又说,我必服自己的劳苦
有趣的是,它学到了很多,耶路撒冷是一个独特的实体,不与其他字符连接。
自己尝试不同的开始顺序!
改进和总结意见
改进可以在许多方面实现。调整超参数,特别是尝试增加历元,稍微降低学习率,增加隐藏单元的数量,以及所有这些的组合。可以引入的一个有趣的超参数是温度,它决定了在选择下一个字符时模型选择的保守性/多样性。这里解释的很好。
我以一个问题作为结束——如果有足够的时间、足够的数据和一个聪明的模型,我们可以生成与人类书写的布道没有区别的布道(就像我们对画作所做的那样),我们能给上帝编程吗?但是如果我们可以,我们不是遇到了一个悖论吗?我很想就此展开讨论。
快乐深度学习!
代号:https://github.com/rwiddhic96/LSTMS_God
参考资料:
- https://r2rt . com/recurrent-neural-networks-in-tensor flow-ii . html
- https://www.tensorflow.org/tutorials/text/text_generation
R 队还是 Python 队?
“一个公认的事实是,一个在计算机科学和统计学方面有良好基础的数据科学家,肯定需要一种编程语言。”
嗯,我敢肯定,如果数据科学早在 1813 年的《傲慢与偏见》第一次出版的时候,简·奥斯汀就会这样表达。
随着点击统计和机器学习工具的存在,如 Weka、SPSS 和谷歌的 AutoML,人们很容易陷入这样一个陷阱,即认为在数据科学领域建立职业生涯时,能够编程不再重要。
虽然我不否认技术的发展变化,而且理解数据科学的理论比用代码实现它更重要。事实是,如果你想在数据科学领域有所成就,你需要会编程。
事实上,在我最近对 LinkedIn 上列出的 100 个数据科学职位广告进行的分析中,我发现 97%的广告都将编程技能作为选择标准。
能够编程给了你能够提取和争论你自己的数据的自由;让您更好地控制模型参数调整;这意味着当涉及到您能够使用的算法和技术范围时,您不再受软件开发人员的摆布。
但是有这么多编程语言可供选择(维基百科列出了几百种),你应该从哪里开始呢?
在为数据科学选择编程语言时,需要考虑以下六点:
#1:雇主想要什么编程语言?
如前所述,我最近检查了 2019 年 4 月 22 日至 2019 年 5 月 5 日期间在 LinkedIn 上发现的四个英语国家(澳大利亚、加拿大、英国和美国)的 100 份数据科学招聘广告。
这些招聘广告被选择来代表雇主类型、规模、行业和工作级别的广泛代表性,而纯粹的管理角色没有被考虑。
基于这一分析,我发现雇主在数据科学家中寻求的前三种编程语言是 Python(在 90.4%的招聘广告中被提及)、R(在 73.4%的招聘广告中被提及)和 SQL(在 58.5%的招聘广告中被提及)。
这表明,如果您打算为数据科学选择一种编程语言,那么 Python、R 或 SQL 中的一种是最佳选择。
然而,虽然 R 和 Python 都是通用编程语言,具有允许用户执行数据科学的大多数技术要求的附加包,包括统计分析和机器学习,但 SQL 是一种专门为查询和操作关系数据库中的数据而设计的数据库语言。
雇主通常要求 SQL 技能,因为他们将数据保存在关系数据库中,并希望他们的数据科学家能够访问这些数据。他们实际上并不期望他们的数据科学家使用 SQL 执行他们工作的其他方面,比如模型开发。
虽然我之前已经在这里写了关于学习使用数据库的基础知识的重要性,但是作为一名数据科学家,你不需要学习太多的 SQL。只需学习足够的 SQL,以便能够合并和过滤一组表,然后将注意力集中在 Python 或 r 中的一个上。
顺便说一下,有多个为 Python 和 R 编写的包,允许用户从这些语言中运行 SQL 查询(例如,Python 中的 sqlite3 和 R 中的 RSQLite),因此,为了最大限度地提高效率,您可以在学习 R 和 Python 之一的同时学习 SQL 。
#2:其他人都在用什么编程语言?
如果你已经与其他数据科学家或数据专业人员在一个环境中工作,那么最好的学习语言往往是你周围每个人都在使用的语言(即使你已经知道一些不同的东西)。
这样做的原因是因为它将您置于这样一个位置,您可以向您周围更有经验的程序员学习,并得到他们的指导(同时也不会因为您选择的编程语言而受到嘲笑——对一些人来说,整个 R vs Python 的辩论可能变得非常政治化)。
你可以让其他程序员检查你的代码;使用他们的代码作为好的编程技术的模板;从你周围的对话中获取编程的一般技巧。
我的一个朋友曾经告诉我一个她的前同事的故事,他坚持用一种他周围没有人熟悉的语言编程。他在一家跨国保险公司找到了一份工作,在那里他继续保持这种立场,并最终犯下了一个巨大的错误,这让他丢掉了工作,因为没有人能够审查他的工作。
如果你刚刚起步,或者不与任何其他程序员一起工作,那么你可以在更大的层面上应用这种考虑。数据科学社区中的其他数据科学家通常使用什么语言?
在我对 2018 年度 StackOverflow 开发者调查(可在此处找到)进行的分析中,我发现,在自称为数据科学家的受访者中,Python 是最受欢迎的语言,76.8%的人在过去 12 个月中使用过 Python。
相比之下,去年只有 34.0%的人使用过 R,排在 SQL、HTML、JavaScript、CSS、Bash/Shell、Java 和 C++之后。
同样,对 Kaggle 2018 ML & DS 调查回复的分析显示,在认为“可能”或“肯定”是数据科学家的受访者中,60.5%最常使用 Python(使其成为最受欢迎的语言),R 以 16.0%的比例位居第二。
#3:你打算用这种语言做什么?
r 最初是 S/S-Plus 的开源实现,S/S-Plus 是一种专门为统计人员设计的编程语言,通常在大学水平的统计课程中讲授。
尽管 S/S-Plus 的编写使得大部分主要功能都在核心程序中,但 R 被设计成可通过包进行扩展,并且随着时间的推移,已经编写了额外的包来扩展 R 的功能,使之超越统计技术。然而,由于它的起源,R 的优点仍然是它的统计功能。
相比之下,Python 最初是一种通用编程语言,受 C/C++和 Java 的影响,供软件开发人员使用。与 R 一样,Python 也可以通过包进行扩展,但是由于这种语言的通用性质,它的优势在于这些包所提供的功能的广度。
Python 是许多大学计算机科学课程(尤其是与机器学习或人工智能相关的课程)的首选语言,实现非统计功能的包往往首先用 Python 编写,R 包随后创建(要么原生于 R 中,要么作为 Python 包的 R 接口,如谷歌的深度学习包 Tensorflow 的情况)。
一般来说,如果你学习编程语言的目的是专门用于统计分析和建模,那么 R 可能比 Python 更能满足你的需求。
但是,如果您计划扩展到统计之外,特别是数据科学的计算机科学方面(包括机器学习、深度学习、自然语言处理和计算机视觉),那么请考虑使用 Python。
#4:未来呢?
引用搏击俱乐部的话,“在一个足够长的时间线上,每个人的存活率下降到零”,这也适用于编程语言。不管一种编程语言今天有多流行,最终会有另一种语言取代它。
从积极的一面来看,尽管编程语言时好时坏,但支撑大多数编程语言的原则往往保持不变。
一旦您掌握了函数、for 和 while 循环、if/else 语句和变量类型背后的概念,您就可以相对较快地掌握任何编程语言的基础知识。
尽管如此,如果你打算花时间学习一门编程语言,你希望能够尽可能获得最大的投资回报,这意味着选择一门越来越受欢迎的编程语言,而不是越来越不受欢迎。
数据科学网站 KDnuggets 对其用户的软件选择进行了年度调查(例如,见这里)。最近三年,Python 在这项民意调查中一直名列前茅,在 2015 年至 2019 年的五年中,其使用量从 30.3%的受访者增长到 65.8%的受访者。
相比之下,在同一时期,R 的使用率从 2015 年的 46.9%增加到 2017 年的 52.1%,然后再次下降,到 2019 年降至 46.6%。
在截至 2019 年 8 月的五年中,谷歌趋势对搜索词“Python”和“R”进行了比较,结果显示,尽管“Python”一直是更受欢迎的搜索词,但“R”的受欢迎程度保持相对平稳,而“Python”的受欢迎程度则大幅上升。
因此,如果未来的可用性是你最关心的,那么 Python 就是你要走的路。
#5:你最喜欢哪种编程语言?
开源语言的美妙之处在于,任何人都可以免费下载它们,并在自己的电脑上使用它们。你不会在没有试驾的情况下购买一辆新车,那么为什么不在选择编程语言时应用同样的原则呢?在接下来的几年里,你可能会花很多时间来使用编程语言。
r、Python 以及其他许多在数据科学家中流行的语言都是开源的。你可以下载你感兴趣的每一种语言,然后,对于每一种语言,花一周左右的时间学习一些你可以在网上找到的入门教程。
一旦你掌握了语法,给自己设定一些基本的任务来进行语言的比较。例如,给定一个你从某个来源下载的数据集,比如 Kaggle 或者 UCI 机器学习库,你可以尝试下面的方法:
- 加载数据集,计算基本汇总统计数据(如各变量的均值和方差);
- 单独或成对绘制每个数据变量;
- 进行基本的数据清理,将数据整理成适合模型拟合的形式;和
- 将几种不同的机器学习模型(例如,线性回归模型、决策树、支持向量机和神经网络)与数据进行拟合,并选择最佳模型。
在这个过程的最后,选择最适合你的语言。
#6:专有语言呢?
到目前为止,本文主要关注的是开源语言,但是它们的专有表亲(即与商业软件相关联的语言),比如 SAS,情况又如何呢?
虽然曾经有一段时间,甚至就在五年前,雇主倾向于选择商业软件而不是开源软件,但随着开源工具的日益流行,人们的态度已经发生了变化。
据我所知,一些组织(包括跨国咨询公司和企业)正在从商业分析软件转向开源软件,以削减成本。
的这篇文章反映了这一观察结果,文章讨论了行业从 SAS 到开源工具的转变,并声称“新毕业生进入职场普遍更喜欢 Python 和 R,而不是 SAS。”
如果这还不足以阻止您学习专有编程语言,请记住,专有语言的功能往往比开源语言少,任何超出基本功能的附加功能通常都是以昂贵的附加模块的形式出现的。
此外,如果你学习了一种特定的语言,然后找到了一份工作,而你的新雇主没有你使用这种语言所需的软件,那么说服你的雇主为你提供免费的开源工具要比购买一种商业产品的许可证容易得多,后者每年可能要花费五六位数的费用。
为数据科学选择一种编程语言可能是一个困难的决定。我个人更喜欢 Python,因为它的功能广泛,在数据科学社区很受欢迎,并且有增长的轨迹。然而,至少在中短期内,我预计 Python 和 R 将继续作为两种顶级数据科学语言共存。
所以,只要你学会了其中一个,你就不会错得太多(事实上,如果你对数据科学很认真,那么最终你应该两个都学)。
然而,无论你选择哪种编程语言,一定要学好它。因为,归根结底,重要的不是你用于数据科学的语言,而是你用它做了什么。
Genevieve Hayes 博士是数据科学家、教育家和人工智能及分析专家,拥有Genevieve Hayes Consulting。你可以在LinkedIn或者Twitter上关注她。她还是 价值驱动数据科学 的主持人,这是一个每月两次的播客,面向希望最大化其数据和数据团队价值的企业。
想要发掘企业数据的价值,但不知道从哪里开始?**下载免费的数据科学项目发现指南。
2020 年你应该读的科技书籍
我们生活在未来。是时候了解一下了。
我们的世界是一个地球村。如果你正在阅读这些文字,你可能有一部可以上网的智能手机。过去的 20 年是科技和我们如何使用科技的疯狂时期。在我们的历史上,我们从未在如此短的时间内看到如此多的突破。这篇文章集中在从不同角度讨论这些变化的书籍上。
Technology Books you should read in 2020
改变世界的创新者
我们都喜欢英雄的故事,他们做出牺牲,失败,一次又一次的失败后回来改变世界。以下书籍关注的是人:
沃尔特·伊萨克森的《创新者》是一本关于有创造力的头脑的书,他们突破界限,与他们的时代背道而驰,并重新发明做事的方式。说到创新,这绝对是经典。
数百万人对埃隆·马斯克又爱又恨。他将电动汽车推向大众和去火星的迷人探索成为头条新闻。他的传记介绍了他从南非童年到现在的经历。一个惊人的故事仍然揭开。
万物商店讲述了亚马逊如何从一个小型在线图书销售商成长为一个全球巨擘的故事,这个巨擘横跨多个行业,并且还在不断成长。读一读就明白为什么总是‘第一天’。
如果你的目标是“不惜一切代价建立一个十亿美元的公司”而不是创新,那么你会犯多大的错误。它展示了硅谷是如何运作的,以及在没有工作原型的情况下你能走多远。
火箭亿万富翁展示了火箭工业有多艰难,以及为什么“火箭科学”仍然意味着“艰难,几乎不可能”。它介绍了第一次登月的历史,分析了卫星业务,并解释了为什么私营部门完全改变了火箭工业。任何对太空感兴趣的人都必须阅读。
人工智能来了
技术可以有许多面孔,但最近主要的一个是人工智能。不管我们想不想,我们都在使用它。下面的书解释了我们是如何来到这个时代的,以及未来等待我们的可能是什么。
哈拉里的《T2 智人》以令人信服和连贯的方式展现了我们的历史。从我们古老的祖先到现在,从简单的工具到互联网和智能手机,这个故事是一个很好的读物,可以让我们了解为什么我们是人类。
超智能是人工智能和人工通用智能的经典参考。尼克·博斯特罗姆列出了其他作者经常使用的所有理论。对于任何想知道人工智能将如何改变世界的人来说,这是一本好书。
数学毁灭的武器是一本关于数学的书。凯茜·奥尼尔展示了我们的世界是如何被算法统治的,以及我们如何让算法为我们做出决定。既迷人又可怕。
《人工智能的超能力》是解释人工智能如何在商业中使用以及中国如何利用人工智能造福人类的一个很好的参考。作者解释了硅谷和中国初创企业生态系统之间的差异。
人工智能商业是针对商业人士和以商业为导向的数据科学家的人工智能简明指南。注重实际,关注最新趋势。
如果你想找更多的书籍推荐,可以看看我的其他书单:
敬请关注更多关于人工智能和技术的文本。](https://creative-producer-9423.ck.page/c3b56f080d)
Data Science Job
最后,如果你想了解成为一名数据科学家意味着什么,那么看看我的书数据科学工作:如何成为一名数据科学家,它将指导你完成这个过程。
技术和创造力的起源
人工智能和新兴技术给人类带来了强大的新工具,但我们准备好向它们过渡了吗?
德克·克内梅尔和乔纳森·福利特
The Smartware Evolution [Photo: Girl With VR Goggles, by Samuel Zeller on Unsplash]
智能软件的发展
我们正处于计算技术的下一次重大变革的风口浪尖,这将为我们的工作和生活带来重大变化。虽然人工智能(AI)受到了媒体的极大关注,但它正在与一系列其他新兴和补充技术同步成熟,我们认为这些技术是智能软件——从物联网(IoT)到虚拟和增强现实,再到添加制造/ 3D 打印——决定了自动化系统可以并将如何与我们互动、协助我们并向我们营销。不仅将这些技术本身视为变革性的,而且将其视为从第一台计算机开始的进程的延续,这是很有用的。每一次进步,从个人电脑到互联网再到手机,我们的技术优势都在增加。在过去的 40 年里,随着我们采用和利用这些工具,我们的社会已经从工业经济过渡到信息经济。
这种演变将会破坏稳定,以一种最终看起来类似于我们从农业经济向工业经济演变的规模改变世界。人们的生活将会受到影响,几十年后,世界将会变得面目全非。我们已经可以看到无人驾驶汽车等技术的痕迹。尽管由于优步和特斯拉等商业模式各异的公司发生了引人注目的致命事故,它们的发展和采用速度有所放缓,但它们在一些社区仍然引人注目。此外,一些人做出了激烈的反应,这让人想起了 19 世纪 10 年代英国的勒德分子。亚利桑那州钱德勒市的人们用石头、刀子袭击了谷歌分拆公司 Waymo 的无人驾驶汽车,甚至用武器威胁这些汽车。尽管在过去两年里,这类攻击只有 21 起,但对人工智能和其他相关新兴技术进步的不安是显而易见的。无人驾驶汽车可能还需要数年或十年的时间,才能将典型的人类司机转变为无人驾驶交通工具的乘客,但它已经预示了它将对社会产生的深远影响。
人工智能和自动化带来的越来越多的技术杠杆提供了创造和摧毁工业、工作和生活方式的能力。为了以积极的方式改变和改善我们的生活,我们需要适应性策略来准备与智能机器的合作。
前车之鉴
我们的人类生态——我们与自然和人造环境以及彼此之间的关系——将会发生变化。但是,如果这能让你感到安慰的话,作为一个物种,我们已经经历过多次这种类型的转变。历史上,我们和我们的技术一起发展。为了更好地理解人类与技术和创造力之间关系的人类学基础,我们采访了东北大学的人类学家和社会学家 Carie Little Hersh 博士。她教了我们很多东西。首先,你知道科技实际上早于人类吗?所以,某种意义上,它甚至不是“我们的”。最早的技术比人类智人早几百万年:石器至少可以追溯到南方古猿。不管怎样,技术现在是我们独有的东西,而且只会加速发展。赫什博士带我们回到大约 10,000 年前,以说明技术和人类生态之间的相互作用是如何齐头并进的。
Figure 01 — New Tools for Food Production
[Image: “Man with a Hoe”, c. 1882, Georges Seurat, (Open Access Image from the National Gallery of Art)]
赫什博士说:“从狩猎和采集过渡到农业,特别是复杂的农业,不仅需要新的采集食物的工具,还需要新的建筑工具。”“因为突然间,你不再四处走动,不停地跟踪你的猎物。你需要有长期的技术,比如粘土、制砖、木结构,这些东西会持续很长时间,因为你必须储存你的谷物。你不得不在一个地方生活很长一段时间,可以说是经受了各种天气的考验。但是,它也产生了巨大的社会影响。”
这种情况在从农业到工业的转变中再次发生:“所以,随着工业革命,你确实有了这种技术的爆发,也许,其中一些与这些更大的政治有关,包围土地和创造城市的政治。赫什博士说:“几百年前有一次伟大的城市化。“土地的使用方式发生了变化,人们开始相互交往的方式也发生了变化。因此,所有这些不同的东西都发生了变化,以提供这种环境,这为新技术的发展和新生活方式的体现奠定了基础。”
Figure 02 — The Transition to Industrial Revolution
[Illustration: From the book “Medieval and modern times; an introduction to the history of western Europe form the dissolution of the Roman empire to the present time” (1919) (Library of Congress)]
我们已经看到计算技术创造了全新的产业,尽管机器人自动化与新兴市场合谋摧毁了美国的其他产业。但这仅仅是开始。在未来的几年里,创造性工作者,像我们这样的人,也许还有你,将会看到我们的部分工作越来越自动化。全新一代的行业和工作岗位将会同时出现。这将带来不可预测的挑战和机遇。
全球影响和意外后果
社会学家斯蒂芬·平克(Stephen Pinker)通过他的书和 TED 演讲,依靠一系列统计数据来支持他的论点,即世界比以往任何时候都更好,从而赋予了技术进步人士力量。Hersh 博士带来了更加全球化的视角:
“你知道,我们每取得一点进展,就会产生一个新问题。当我们还是狩猎采集者和牧民时,全球变暖显然不是一个问题。所以,我们有很多环境和健康的后果来自我们的选择…我们社会发展的方式。不是所有的社会都有同样的问题,也不是所有的社会都有同样的收获。因此,环顾四周,看看这些问题从何而来,以及其他可能的解决方案,将会非常有用。作为这个神奇的技术世界的受益者,我们所有人都有责任保持警惕,帮助保护弱势群体,并更广泛地传播利益。”
我们花了将近 200 年才意识到工业革命对我们的环境有着潜在的破坏性影响。甚至在今天,当我们享受甚至庆祝我们的智能世界所提供的恩惠时,我们很容易忽视我们视野之外的人们生活质量的下降。你不得不怀疑,在技术可能威胁到他们的生计或侵犯他们的生活方式之前,Waymo 的风险管理团队是否预见到他们的车辆会受到害怕未来的人的物理攻击。它提醒我们,将会有意想不到的后果,我们新兴的智能世界将会产生我们无法预料和无法立即意识到的影响。它还提醒我们,作为与 70 多亿人共享这个世界的人,留意那些在我们社区和视野之外的人也很重要。
Creative Next 是一个播客,探索人工智能驱动的自动化对创意工作者,如作家、研究人员、艺术家、设计师、工程师和企业家的生活的影响。本文伴随 第一季第一集——技术和创造力的起源。
特拉维夫艺术家:为自己打造一款地图应用
TL;dr-I 从尝试地图库到构建可重用的地图应用。这是我如何做到的,你也可以如何重复使用它。
介绍
作为一名数据科学家,我的大部分工作都停留在幕后。在训练模型时,我接触的最多的是部署一个简单的 flask web-app 作为 REST APIs。
最近,部署工具变得更加友好、快捷和高效。你看,如果你想为用户开发一个应用程序,即使是为了演示的目的,一个最小化的 UI 可以是一个很好的起点。
最近偶然发现了 这个 的例子,用于机器学习模型部署和 UI。它有许多部署选项的教程,以及一个用于图像识别的基本 UI。您可以找到许多数据科学家正在使用这个例子,并将其用于他们的分类算法。
这一次,我决定走出我的舒适区,并进一步“扩展”这个例子。
这个概念
如果你在以色列的特拉维夫漫步,你可能会看到一些标志,比如这个:
这块纪念牌位于特拉维夫的伊本·格维罗尔街 30 号,上面写着大卫·佩尔洛夫(David Perlov)曾在这座房子里生活和工作,他是以色列艺术家和电影制作人的先驱。
以色列是一个非常年轻的国家,因此,它的许多历史艺术活动都发生在以色列的第一个城市特拉维夫的一个小地方。
如果你对艺术和漫游感兴趣,围绕这些景点做一次自助游可能会很有趣。
不幸的是,我找不到任何提供某种界面的在线页面来让你自己选择一条旅游路线。
所以,我决定去做。
你们中没有多少人知道,但我有一个老想法,至少利用一些网上可获得的海量地理数据,并创建某种虚拟导游,这将自动生成未知城市的步行路线,或已知城市的原始步行路线。这个任务有点雄心勃勃,所以我决定从小处着手:这些记忆牌将是我进入地图世界的机会。
步骤 1:高级设计
虽然弄脏你的手总是很诱人,但我首先需要思考这个项目的最终目标是什么:这当然不会是一个成熟的生产应用程序,而是一个原型玩具,允许用户进行某种程度的探索。
Schematic plot of the project
更准确地说,我希望用户能够:
- 将斑块视为地图上的标记。
- 获取一些关于他们的信息。
- 获得检查站之间的简单行进路线。
- 所有这些都在用户可访问的网络应用程序中(不是 python 笔记本)
所以我需要:
- 数据分析工具
- 映射工具
- Web 框架:客户端和服务器端。
- 部署服务。
很多事情要做!
当然,这些定义并不严格,但它们描述了我心目中的最小项目。
也是选择发展战略的好时机。这种高层次的选择将伴随我们整个工作。客观地说,我认为他们最好的选择是客户端语言——JavaScript。然而,作为一名数据科学家,我的强项是 python ,所以我选择尽可能多地使用它。这个选择将迫使我使用服务器,因为 python 不能在浏览器中有效使用。
幸运的是,有像样的 pythonic 式 web 框架,比如 Flask。
第二步:数据分析
为了达到上述目标,我必须解决一些任务:
- 获取数据
- 视觉化是
- 创建 UI 界面
在这一页http://cafe.themarker.com/post/3124888/,有一个相当混乱的所有艺术家及其地址的列表。
很容易将艺术家列表及其地址粘贴到文本文件中,并解析到更友好的表格中。
现在是更难的部分。
我做了以下工作:
- 将数据保存在 2 个文件中
- 项目用句号分隔,因此很容易将它们分开。
- 每个项目都包括名称、地址和简短描述。它们用逗号分开,但比之前的方式更混乱
- 总共有大约 180 位艺术家上榜
- 如前所述,大约有 20%的条目用逗号分隔不好。
- 一些缺少逗号
- 有些带有额外的逗号,主要是在描述中
解决方案:
- 因为地址应该有数字,所以它可以是一个指示器
- 将拆分并整理成地址和姓名(可能有一两个遗漏了,但我们必须接受)
- 将所有清理过的地址发送到地理定位器 API 以获取位置坐标。由于各种原因,并非所有(20)都将被正确返回,因此应该手动检索它们
拿到数据后,接下来的任务就是提取路点的坐标。显然,处理地理数据的正确方法是能够无缝地将用户友好的地址转换成计算机友好的地理位置。
这可以通过 GeoPy 实现——带有一些地理编码(place=> geocode=>place)功能的包,这可以节省一些 google APIs 积分。
Cleaned data with Geo-location
第三步:选择我们的武器
处理完大部分数据工作后,下一步就是映射 可视化和 UI 。由于我已经决定使用 python 作为我的后端,我需要一些 python 工具,希望可以翻译成 html。有相当多的软件包可以内联绘制地图并将其另存为(有时是交互式的)。html 文件。但是,它们具有不同的特性和功能。有些需要使用高级谷歌地图 API,这意味着一些限制,除非你付费。
因此,我们希望我们的包装中包含以下内容:
- 能够制作交互式 html 地图或类似。
- 绘图,工具提示,弹出功能。
- 简单易用(有很多事情要做,不想浪费我所有的时间在贴图上)。
- 最好无限制 API 要求。
- 奖励:额外功能,如搜索和路线
一个简单但健壮的包将使我的工作更快,用户体验更好。
因此,我继续进行了一个关于映射包的小研究。因为我的首选语言是 python,所以映射工具并不是最好的。这些是我体验过的工具,它们很 pythonic 很容易使用:
谷歌地图
谷歌地图值得拥有自己的版块,因为它是领先的地图工具。因此,能够通过 API 有效地使用它可以解决我们的大多数问题。然而,这是不可能的。谷歌提供的所有 API 都有一定的局限性:
- 谷歌地图服务 python
这个包更像是 google maps API 的包装器,允许在 google maps 中检索大量可用数据,但我没有找到绘图功能,因此这个库不太相关。
2.谷歌地图 url API
这个工具非常容易使用,有动态和静态两种版本:
- 对于这个项目来说,动态 google maps API 可能是最好的选择,然而,也许令人惊讶的是,它不支持太多选项,除了通过 google maps 用户界面提供的选项。因为我的需求之一是呈现一个有多个标记的地图,所以我在这里无法完全实现。
[https://www.google.com/maps/search/pizza+seattle+wa/@47.6257624,-122.331987,12z/data=!3m1!4b1](https://www.google.com/maps/search/pizza+seattle+wa/@47.6257624,-122.331987,12z/data=!3m1!4b1) - search pizza in seatle with google maps dynamic API
- 静态的谷歌地图 URL API——和上面的一样简单,有更多的选项,但是它是静态的,因此谷歌地图的一些动态功能被关闭了。然而,我发现这个工具对我来说是最有用的
如果你喜欢使用它,注意它需要一个 API 键,所以如果你不想被计费,你应该限制它(或者让用户插入他自己的)
3。我的地图谷歌应用
谷歌的一个很好且必要的产品是“我的地图”,它允许你创建带有位置、标记等的个性化地图。然而,自从“不可行以来,谷歌似乎没有为其提供 API
Python 包
回到我们最喜欢的独立开源 python 库:
- Gmplot
一个简单漂亮的 python 包,负责一些基本的绘图功能,并输出一个 HTML 文件。这是唯一一个允许开箱即用绘图(在谷歌地图风格的地图上)的包,但是它的选项是有限的。任何类型的弹出窗口都是不可能的,
主要是所见即所得:圆圈,线条,标记,热图,就是这样。没有文字或路线。
优点——非常简单
缺点——过于简单,需要 Google API
回购+快速启动:https://github.com/vgm64/gmplot
2。散景
令人惊讶的是,好的结果来自一个与谷歌地图没有直接关系的包。散景映射模块有我们需要的一切,除了外观和感觉不是很光滑。
然而,这里也不可能有用户界面。
3。叶子
在几乎放弃 python 并开始使用 JS 之后,我偶然发现了这个伟大的库,它在 GitHub 上拥有超过 3.5K 的星级。基于 fleet . js 地图,看起来很棒,有高级绘图选项,不需要 google API。
leav 包括一些额外好特性:
- Html 工具提示和弹出窗口
- 祖穆特的标记分组
- 许多不错的绘图选项
- 无缝导出到 html
那么叶子就是了!
Folium map
第四步:逻辑
所以我们有地图和标记。现在是时候做一些更聪明的事情了:路线规划。
我的任务是允许用户插入一个起始地址,并为他规划一条旅行路线。使用 google API,我们可以获得一条智能步行路线,但我将它留给了用户(换句话说,这超出了本项目的范围),并且只显示指定位置之间的折线:
在接收地址时,有不同的算法可以找到最佳路径,但我选择使用简单的贪婪算法来找到最近的检查点。当达到限制(每小时 2 公里)时,脚本结束路线,并添加一条路径返回到起点,并在地图上以折线的形式显示所有内容。
简单不是吗?
你可以在 app.py 文件中找到所有的逻辑,在 repo 中的 calc_route 函数中。
步骤 5:实施/部署
因此,在我们将所有逻辑都准备好之后,就到了最具技术性的部分——部署。
这一部分对 web 开发人员来说很容易,但作为一名数据科学家,这是我尽量避免的部分。我最多是用 flask 应用程序包装我的模型,并把它放在一些云服务上。
在后端部分,我决定使用谷歌应用引擎。我主要使用谷歌云,所以对我来说更容易。尽管将 web-app 加载到这样一个托管服务上要比标准服务器慢得多,但它能处理许多我不愿接触的事情
至于前端,我把这个回购用于我的目的,做了如下改动:
- 用 flask 代替 uvicon/starlette,因为我更熟悉 flask。
- 一些明显的用户界面变化。
- 我决定添加的功能需要一些 javascript 代码。
Javascript 很复杂:作为编程语言,它非常简单。然而,使用它,尤其是使用 flask,可能会很棘手,因为有许多活动部件。
甚至调试过程也不同,因为它需要在浏览器中来回检查应用程序。
我的策略是从模板开始,在谷歌上搜索我想要做的每一项改变当然并不容易,因为我不熟悉:
- Iframes 的行为
- 在 html、python 和 javascript 之间来回传递数据,反之亦然
诸如此类。
- 添加数据-添加标记后,我们想给用户添加一些额外的价值,添加谷歌地图图像和维基百科页面的摘录
- 路径——目前它只是一个数据地图。我们将如何让它活起来?我认为添加一个简单的自流道路线计算算法会很好。一些我“以后可能会改进”的东西。逻辑将如下:您输入您的当前地址和您想要投入到您的旅行中的时间,系统将计算出满足所需条件的路线。这里的算法是贪婪的,不是最优的,并且路线目前是点之间的直线
6.构建您自己的地图
现在你可能会对自己说“我对‘特拉维夫’的艺术家没有任何兴趣。所以我给你准备了一个惊喜:你可以分叉我的回购,获得自己的地址,更改 data.json ,部署自己的映射工具!
你只需要有一个 gcloud 命令行工具,一个活跃的项目,如这里描述的,有了这个命令你就可以开始了:
gcloud app deploy
如果你做到了,请在评论里发帖。
如果你从笔记本开始,你可以使用位置和描述的列表,你有自己的智能旅行地图。
摘要
就是这样!我向您展示了,如果您知道自己在做什么,那么让脏数据集变得生动起来是一件简单而快速的事情。不幸的是,我花了很多时间才知道自己在做什么,或者换句话说,找到叶库。
如果你关注了这篇文章,你可能已经看到了为达到 MVP 所做的工作:许多可能的改进被遗漏了。但是,添加它们很容易:
- 更智能的路由算法
- 使用谷歌地图 API 生成实际路线,而不是折线
- 更好的弹出窗口设计等等。
我现在可以想到很多想法,但我不认为我会在未来几周内接触地图或 js ,但我鼓励你尝试:)
电信客户流失预测
为流失预测建立机器学习模型
Photo by Carlos Muza on Unsplash
客户流失,也称为客户流失,发生在客户停止与公司做生意或停止使用公司的服务时。通过了解和监控流失率,公司能够确定他们的客户保持成功率,并确定改进策略。我们将使用机器学习模型来理解准确的客户行为和属性,这些行为和属性标志着客户流失的风险和时机。
了解我们的数据集:
我们将使用 Kaggle 的电信客户流失数据集。原始数据集包含 7043 个条目。所有条目都有几个特征和一列说明客户是否搅拌过。
为了更好地理解数据,我们将首先把它加载到 pandas 中,并在一些非常基本的命令的帮助下探索它。
import numpy as np
import pandas as pd
from sklearn.preprocessing import MinMaxScaler
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
import seaborn as sns%matplotlib inline
from sklearn.model_selection import train_test_split#Loading the data
df = pd.read_csv(r’...Churn\telco_customer.csv’) df.info() <class ‘pandas.core.frame.DataFrame’>
RangeIndex: 7043 entries, 0 to 7042
Data columns (total 21 columns):
customerID 7043 non-null object
gender 7043 non-null object
SeniorCitizen 7043 non-null int64
Partner 7043 non-null object
Dependents 7043 non-null object
tenure 7043 non-null int64
PhoneService 7043 non-null object
MultipleLines 7043 non-null object
InternetService 7043 non-null object
OnlineSecurity 7043 non-null object
OnlineBackup 7043 non-null object
DeviceProtection 7043 non-null object
TechSupport 7043 non-null object
StreamingTV 7043 non-null object
StreamingMovies 7043 non-null object
Contract 7043 non-null object
PaperlessBilling 7043 non-null object
PaymentMethod 7043 non-null object
MonthlyCharges 7043 non-null float64
TotalCharges 7043 non-null object
Churn 7043 non-null object
dtypes: float64(1), int64(2), object(18) memory usage: 1.1+ MB
df.info()为我们提供了每一列的详细信息。我们可以看到我们的数据分为三种类型;
- 对象:对象格式意味着变量是分类的。我们数据集中的分类变量包括:客户 ID、性别、合作伙伴、家属、电话服务、多条线路、互联网服务、在线安全、在线备份、设备保护、技术支持、流媒体电视、流媒体电影、合同、无纸化账单、支付方式、总费用和客户流失。
- int64:代表整数变量。老年公民和终身职位都是这种格式。
- float64:表示包含一些小数值的变量。它们也是数字变量。在我们的数据集中,这种格式只有一个变量,即每月费用。
探索性数据分析
本节的目标是熟悉我们的数据。我们将进行双变量分析。这是分析数据的最简单的形式,我们检查每个变量与流失率的关系。对于分类特征,我们可以使用频率表或柱状图来计算特定变量中每个类别的数量。对于数字特征,概率密度图可用于查看变量的分布。
分类变量的所有可视化将在 tableau public 中完成。
从上面的柱状图可以得出以下推论:
男性和女性的流失率几乎相等。
老年人的流失率更高。
拥有电话服务的客户流失率更高。
与没有合作伙伴&家属的客户相比,有合作伙伴和家属的客户流失率较低。
与其他支付方式相比,使用电子支付方式的客户流失率更高。
没有互联网服务的客户流失率较低。
光纤互联网服务的流失率要高得多。没有 OnlineSecurity、OnlineBackup 和 TechSupport 等服务的客户在过去的一个月里离开了该平台。
现在让我们看看数字变量。
plt.figure(1), plt.subplot(121), sns.distplot(df['tenure']);
plt.figure(1), plt.subplot(121), sns.distplot(df['MonthlyCharges']);
plt.figure(1), plt.subplot(121), sns.distplot(df['TotalCharges']);
资料准备&特色工程:
这部分是机器学习的基础部分。如果这一部分做得不好,我们的模型就不会工作。在这一节中,我们将通过删除不相关的数据、处理丢失的值以及将变量转换为适当的数据类型来清理数据集。
处理无关数据和缺失值
在我们的数据集中,我们可以看到我们的模型不需要客户 ID,所以我们删除了变量。我们不需要处理缺失值,因为该数据集中没有缺失值。
df.drop([‘customerID’], axis=1, inplace=True)
将分类数据转换为数字数据
机器学习只处理数值。因此,我们需要将我们的分类值转换成数值。通过使用熊猫函数“get_dummies()”,我们可以用“gender_Female”和“gender_Male”替换性别列。我们将使用 df.info()向我们展示哪些是分类的,哪些是数字的。
df.info()<class ‘pandas.core.frame.DataFrame’>
RangeIndex: 7043 entries, 0 to 7042
Data columns (total 21 columns): customerID 7043 non-null object
gender 7043 non-null object
SeniorCitizen 7043 non-null int64
Partner 7043 non-null object
Dependents 7043 non-null object
tenure 7043 non-null int64
PhoneService 7043 non-null object
MultipleLines 7043 non-null object
InternetService 7043 non-null object
OnlineSecurity 7043 non-null object
OnlineBackup 7043 non-null object
DeviceProtection 7043 non-null object
TechSupport 7043 non-null object
StreamingTV 7043 non-null object
StreamingMovies 7043 non-null object
Contract 7043 non-null object
PaperlessBilling 7043 non-null object
PaymentMethod 7043 non-null object
MonthlyCharges 7043 non-null float64
TotalCharges 7043 non-null object
Churn 7043 non-null object
dtypes: float64(1), int64(2), object(18) memory usage: 1.1+ MB
从上面的结果中,我们可以看到数据类型为 object 的变量需要转换为 numerical。
df = pd.get_dummies(df, columns = [‘gender’, ‘Partner’, ‘Dependents’,’PhoneService’,’MultipleLines’,’InternetService’,
‘OnlineSecurity’,’OnlineBackup’,’DeviceProtection’,’TechSupport’,’StreamingTV’,‘StreamingMovies’,’Contract’,’PaperlessBilling’,’PaymentMethod’,’Churn’], drop_first = True)
使用 df.info()来检查我们所有的变量是否都被转换为适当的数据类型是明智的。在这一步之后,我注意到 total charges 仍然有一个 object 数据类型。因此,我将使用 pd.numeric()函数将其转换为浮点数。
df[‘TotalCharges’] = pd.to_numeric(df.TotalCharges, errors = ‘coerce’)
df.drop([‘TotalCharges’], axis = 1, inplace = True)
分割数据集。
首先我们的模型需要被训练,其次我们的模型需要被测试。因此,最好有两个不同的数据集。至于现在我们只有一个,相应拆分数据是很常见的。x 是自变量的数据,Y 是因变量的数据。测试大小变量决定了数据的分割比例。在 80 的训练/ 20 的测试比例中这样做是很常见的。
df[‘Churn_Yes’] = df[‘Churn_Yes’].astype(int)
Y = df[“Churn_Yes”].values
X = df.drop(labels = [“Churn_Yes”],axis = 1)
# Create Train & Test Data
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, Y, test_size=0.2, random_state=101)
逻辑回归和模型测试
让我们制作第一个模型来预测目标变量。我们将从用于预测二元结果的逻辑回归开始。
我们将使用 scikit-learn (sklearn)来制作不同的模型,这是 Python 的一个开源库。它是最有效的工具之一,包含许多可用于 Python 建模的内置函数。
from sklearn.linear_model import LogisticRegression
model = LogisticRegression()
result = model.fit(X_train, y_train)
数据集分为训练和验证两部分。让我们从 sklearn 导入 LogisticRegression 和 accuracy_score 并拟合逻辑回归模型。
from sklearn import metrics
prediction_test = model.predict(X_test)# Print the prediction accuracy
print (metrics.accuracy_score(y_test, prediction_test))
0.800567778566
因此,我们的预测几乎 81%准确,也就是说,我们已经正确识别了 80%的流失率。因此,为了减少流失并及时采取正确的预防措施,我们想知道哪些独立变量对我们的预测结果影响最大。因此,我们将模型中的系数设置为零,并查看每个变量的权重。
weights = pd.Series(model.coef_[0],
index=X.columns.values)
weights.sort_values(ascending = False)
结果如下:
InternetService_Fiber optic 0.800533
PaperlessBilling_Yes 0.417392
PaymentMethod_Electronic check 0.293135
StreamingTV_Yes 0.267554
MultipleLines_Yes 0.253773
SeniorCitizen 0.247112
StreamingMovies_Yes 0.197304
MultipleLines_No phone service 0.120019
PaymentMethod_Mailed check 0.019744
gender_Male 0.018991
MonthlyCharges 0.004611
Partner_Yes 0.000535
DeviceProtection_Yes -0.021993
tenure -0.035615
StreamingTV_No internet service -0.095143
TechSupport_No internet service -0.095143
DeviceProtection_No internet service -0.095143
StreamingMovies_No internet service -0.095143
OnlineBackup_No internet service -0.095143
OnlineSecurity_No internet service -0.095143
InternetService_No -0.095143
PaymentMethod_Credit card (automatic) -0.156123
Dependents_Yes -0.182597
OnlineBackup_Yes -0.190353
OnlineSecurity_Yes -0.335387
TechSupport_Yes -0.337772
PhoneService_Yes -0.551735
Contract_One year -0.591394
Contract_Two year -1.257341
dtype: float64
可以观察到,一些变量与我们预测的变量成正相关,而一些变量则成负相关。负值的客户表明他们不太可能流失,而正值的客户表明他们可能流失。这些
我写的大部分内容都让我忙于自己的创业公司 analyx。
期待听到你的经历:)
Python 中的远程门户分析
深度分析
处理 889 页聊天信息
Photo by Alex George on Unsplash
2019 年 7 月 13 日,889 页的电报聊天组对话被泄露,其中包括波多黎各总督里卡多·罗塞罗和其他 11 人,一些现任政府雇员和其他人。这段聊天从 2018 年 11 月 30 日持续到 2019 年 1 月 20 日,在世界各地的波多黎各人中引起了极大的愤慨,抗议随之而来。这种情况被命名为 丨t丨e丨l丨e丨g丨r丨a丨m丨s丨gate,基于性质类似的水门事件。
当我通过其他人对脸书和新闻的解释了解到这一事件以及州长所做的声明时,我认为我最好亲自阅读 PDF,看看这些声明的背景是什么,以及我是否认为它们确实值得愤怒(它们确实如此)。当我发现这份文件长达 889 页时,我的第一个想法是…
I can’t even read all my emails, you think I am reading 889 pages of chat conversations?
我决定用 Python 做一个项目来分析 丨t丨e丨l丨e丨g丨r丨a丨m丨s丨gate 的对话。我将在这里用第一人称复数描述我遵循的过程。
本文中讨论的代码可以在我的 GitHub 帐户中的一个名为analyze_丨t丨e丨l丨e丨g丨r丨a丨m丨s丨gate
的存储库中找到:
[## meramos/analyze_丨t丨e丨l丨e丨g丨r丨a丨m丨s丨gate
波多黎各总督里基·罗塞罗和他的政府同事之间的电报信息的 NLP 分析…
github.com](https://github.com/meramos/analyze_丨t丨e丨l丨e丨g丨r丨a丨m丨s丨gate)
开发要求
我们在 Ubuntu 中使用了 Python 3 和 Jupyter Notebook。使用了以下软件包:
- Tika :允许您在 Python 中使用 Apache Tika 。Tika 是一个用 Java 开发的工具包,它可以从各种不同的文件格式中检测和提取元数据和文本。我们使用它是为了从 丨t丨e丨l丨e丨g丨r丨a丨m丨s丨gate PDF 文件中提取文本。通过在计算机终端上运行
pip3 install tika
来安装它。 - Re :该模块提供正则表达式匹配的操作。这个模块是 Python 自带的。我们在预处理中使用它来识别和删除与对话无关或不重要的数据,如时间戳和链接。默认情况下,Python 附带了它。
- PDFKit :允许您从不同来源创建 PDF 文件,包括 HTML。我们用它创建了一个 丨t丨e丨l丨e丨g丨r丨a丨m丨s丨gate PDF 文件的节略版本。通过运行
pip3 install pdfkit
安装这个包。您还必须安装wkhtmltopdf
以便从 HTML 文件创建 PDF。在 Ubuntu 操作系统中,你可以通过运行sudo apt-get install wkhtmltopdf
来安装它。
预处理
处理文本时,了解原始文档结构、了解某些部分的含义以及它们与文档内容的相关性非常重要。
为了处理文档,我们首先使用 Tika 读取它,然后使用正则表达式删除文本中各种不重要的部分。
阅读 PDF
首先,我们使用 Tika 阅读 丨t丨e丨l丨e丨g丨r丨a丨m丨s丨gate PDF 文档(你可以在这里下载),并预览前 200 个字符。
清洁 PDF
我们注意到文档中有很多新行,所以我们使用字符串方法.strip()
删除它们,现在pdf_content
的前 399 个字符如下所示:
[注意到行“lComo se col6 eso?”是对《Como se coló eso》的误读。Tika 错误地读了一些颠倒的标点符号和重音字母,例如,它读为“as 6”和“as f”。我们在本文中没有提出解决方法。]
日期“1/20/2019”和文本“丨t丨e丨l丨e丨g丨r丨a丨m丨s丨 Web”出现在每一页的开头,这很可能意味着电报对话是在那个日期下载的,即 2019 年 1 月 20 日。在每一页的末尾都有一个电报 URL 和你在 PDF 所有页面中的页面。我们可以使用页码来跟踪 PDF 中出现消息的页面,所以我们应该保留它。但是应该去掉每页顶部的日期和文本“丨t丨e丨l丨e丨g丨r丨a丨m丨s丨 Web”以及底部的链接,这对分析没有用。
测试正则表达式的一个好地方是 https://regex101.com/。
有各种与任何消息都不一致的时间戳。
我们将假设消息发送的时间对分析不重要,因此将被删除。
学习pdf_content
的时候,你可能会注意到有很多两个字母的缩写。从查看 PDF,你可以告诉很多这两个字母的缩写对应的聊天成员没有个人资料图片。这些首字母缩略词对文档的分析没有用,但是我们不应该试图删除它们,直到我们知道谁是参与聊天的成员。我们将在下一节“组织内容”中删除它们,在这一节中,我们将确定谁是管理员聊天成员。
从 PDF 的内容创建列表
在这些步骤之后,我们无法从纯文本中删除更多的字符串,所以我们通过用新行分隔字符串来从pdf_content
中创建一个列表,并开始提取信息。
现在我们准备组织数据。
组织内容
为了组织/构建 PDF 中的信息,我们决定识别聊天成员以及每个成员发送了哪些消息。
我们可以使用文本格式来自动识别聊天中出现的所有成员,但我们无法读取包含格式的 PDF 文档(我们使用 Tika CLI 和标签 xml 和 html 读取它,但都没有保留 PDF 的原始格式)。
因此,我们必须满足自动识别管理员和手动识别其他成员的要求(请随意评论我们可以从 PDF 中自动检索非管理员聊天成员的方式)。
识别管理聊天成员
当检查 PDF 的纯文本时,我们注意到包含管理员用户名的行包含术语“admin”。我们隔离包含这个术语的行,以便识别聊天中的管理员用户。
现在,我们通过删除文本“admin”及其后面的文本来清除这些结果。
有些管理员用户是重复的,区别仅在于文本“via@gif”。我们删除了包含这段文字的内容,因为这些内容是多余的。
当检查结果列表时,您会发现有两个元素很可能是输入错误(Tika 误读了用户名)。这些元素是“Fdo”和“R Russello”。我们删除了这些元素,得到了管理员聊天成员的最终列表。
被误读的用户名仍然存在于文档中。我们用正确的拼写替换它们。
该聊天组共有 8 名管理员成员。管理成员如下:
- Ch Sobri(Christian Sobrino):他是波多黎各财政机构和金融咨询局(AAFAF)的执行董事。2019 年 7 月 13 日,在聊天信息被泄露后,他辞去了在波多黎各政府的各种职务(来源)。
- 卡洛斯·贝尔穆德斯:他是州长的通讯顾问。2019 年 7 月 13 日退出。他是聊天内容泄露后第一个退出的聊天群成员(来源)。
- 拉斐尔·塞拉米·德·阿科斯塔 :也是州长的通讯顾问。他不再与政府保持任何合同。
- 埃德温·米兰达:KOI 的首席执行官。州长的公关和亲密合作者。
- 福·多(埃利亚斯·桑切斯·西方特):前总督在金融监督和管理委员会的代表。
- 拉蒙·罗萨里奥 :前公共事务和公共政策秘书(2017 年 1 月至 2018 年 12 月)。在泄露消息的时间范围内,他并没有为政府工作。
- R 罗塞罗(里卡多罗塞罗):波多黎各总督,2017 年 1 月 2 日至今。
- Alfonso Orona :前任法律顾问(2017 年 1 月至 2019 年 2 月担任 La Fortaleza 首席法律官)。
识别非管理员聊天成员
根据 PDF 的第一行,上面写着“WRF 12 名成员”,这个聊天组一共有 12 名成员。这意味着群组中有 4 个非管理员聊天成员。浏览 PDF 后,我们发现剩下的 4 个聊天成员是:
- 劳尔·马尔多纳多
- 安东尼·马塞拉·扎亚斯
- 里卡多·列兰迪
- 路易斯格
不幸的是,我们无法在 Python 脚本中提取这些信息。我们将把这些用户名和管理员用户名一起添加到一个总聊天成员的综合列表中。
这不是欺骗…
删除两个字母的用户名缩写
现在我们知道了谁是聊天成员,我们可以删除与一些没有个人资料照片的聊天成员相关的两个字母的缩写。我们为用户建立所有可能的缩写。
现在我们有了潜在的首字母缩略词,我们搜索pdf_lines
中的哪些元素只包含其中一个首字母缩略词,并删除那些行。
组织
现在来吃肉!
我们创建一个字典列表(我们称之为conversation
),其中每个字典元素都有以下键:
message
:聊天中发送的消息。chat_member
:发送消息的聊天成员。date
:发送信息的日期(周、月、日、年)。page_number
:PDF 中显示消息的页面。
我们使用包含聊天成员用户名的行作为谁发送了哪条消息的指示器。这些行不包括在最终列表中,因为它们不是对话的一部分。
设想
随着数据的清理和组织,我们可以创建一些可视化来展示数据洞察力。
我们决定创建一个水平条形图,其中每个条形对应一个聊天组成员,条形的长度代表一个聊天成员发送的消息数量。
我们选择了不同的颜色,所以我们随机生成颜色,并为每个聊天成员分配不同的颜色。
如果您正在运行此代码,并且您不喜欢生成的颜色,请随意重新运行代码并创建不同的颜色,或者手动为每个用户定义您想要的颜色。
我们获得每个聊天成员的消息数量,并将它们存储到一个字典中,其中的关键字是用户名,值是消息数。
我们使用 matplotlib 绘制条形图。
下面是生成的图表:
从图中我们可以看到埃德温·米兰达发送的信息最多。这可能是因为他在聊天群里分享了很多新闻文章并对其进行了评论,从 PDF 中可以看出这一点。
简略电报门
我们决定创建一个简短的 丨t丨e丨l丨e丨g丨r丨a丨m丨s丨gate PDF 文档,看看该文档可以缩短多少,以及聊天内容是否可以以更清晰、更直接的格式显示。生成的 PDF 不包含图像或 gif,也不能区分共享帖子和书面帖子。
为了创建 PDF,我们首先使用变量conversation
中的内容创建一个 HTML 格式的字符串。我们写下页码、在前面部分中为可视化生成的颜色中的用户名,以及用户发送的消息。我们没有写邮件发送的日期。创建 HTML 字符串后,我们将它保存到本地文件夹中的一个文件中,命名为“丨t丨e丨l丨e丨g丨r丨a丨m丨s丨gate _ abridged.html”。然后我们使用 PDFkit Python 库从 HTML 文件创建 PDF 文件,我们将结果保存到“丨t丨e丨l丨e丨g丨r丨a丨m丨s丨gate _ abridged.pdf”。
生成的 PDF 有 654 页长,而原始文档有 899 页。这意味着新的 PDF 比原来少了 245 页。
我们选择对用户名进行颜色编码,以便于区分是谁写的消息。当用户名具有相同的长度和颜色时,它们可以在视觉上融合在一起。如果您希望创建不带彩色用户名的 PDF,您可以通过删除添加在 for 循环中的font
标签来实现。
你可以在这里访问这个脚本生成的 PDF。
结论
在本文中,我们用 Python 做了以下工作:
- 使用 Tika 阅读 丨t丨e丨l丨e丨g丨r丨a丨m丨s丨gate PDF 文档
- 通过删除与聊天内容无关的文本来清理数据,我们通过使用各种定制的正则表达式来识别这些文本
- 通过将 PDF 内容存储在字典数组中来组织 PDF 内容,其中每个字典包含要发送的邮件、发送邮件的用户、邮件出现的页面以及邮件发送的日期
- 从 PDF 内容中检索和可视化见解
- 创建了一个 丨t丨e丨l丨e丨g丨r丨a丨m丨s丨gate PDF 的节略版(用户名以颜色区分),长达 654 页(比原始文档少 245 页)
通过这个练习,我们证明了我们可以通过编程来学习 丨t丨e丨l丨e丨g丨r丨a丨m丨s丨gate 文档。这一点很重要,因为在阅读文档时,我们对内容的解释会因我们的核心信念而异。我们也可能将某些言论归咎于错误的人。我们需要一种方法来排除分析文档时的人为偏见。
可以在文本中进行更复杂的分析,例如内容文本摘要、文本分类和情感分析。
从劳尔·马尔多纳多的儿子在他的推特账户上发表的一份声明中,暗示聊天组中存在超过 889 页的对话,这可能最终会被披露(来源)。我们可以使用这里开发的代码来分析新内容。
您是否有任何想法可以从 丨t丨e丨l丨e丨g丨r丨a丨m丨s丨gate 文档中提取更多见解?Leave them in a comment below!
参考资料
Resources for 丨t丨e丨l丨e丨g丨r丨a丨m丨s丨gate information:
- 丨t丨e丨l丨e丨g丨r丨a丨m丨s丨gate PDF: 889 页
- #丨t丨e丨l丨e丨g丨r丨a丨m丨s丨Gate: Leaks From a Private Group Chat Leave Rosselló Administration Exposed
- 下一篇 : 新的一天:Christian Sobrino 辞去所有职务
- 新的一天:卡洛斯·贝穆德斯辞去州长和驻地专员的顾问职务
- 下一篇 : 新的一天:Rafael Cerame 确认他没有与政府签订任何合同
- 新的一天:劳尔·马尔多纳多儿子透露,电报聊天超过 889 页
- 下一篇 : Telemundo:ElíasSánchez 声称他们对他进行了抹黑
- LinkedIn: Christian Sobrino Vega
- LinkedIn: Rafael Cerame
- LinkedIn: 埃德温·米兰达
- LinkedIn: Ramon R.(T21 )
- LinkedIn: Alfonso Orona
技术资源:
- 阿帕奇·提卡(Apache Tika) T25
- PyPI: Tika library
- 正则表达式 101 (T29)
- GitHub: Python-PDFKit
- Stackoverflow:在 Python 中生成随机的十六进制颜色
- PythonSpot: Matplotlib 条形图
- Stackoverflow:如何用 pyplot.barh()显示每个条形上条形的值?
- Stackoverflow:为什么我的 xlabel 在我的 matplotlib 剧情中被切断了?
用数字讲述描述性统计的全部故事!
From Pinterest
统计可以证明任何事情,甚至是事实!所以真正理解它至关重要。统计学处理大量数据的收集、分析、解释和呈现。描述性统计与总结我们收集的分析信息的方法有关。描述性统计可以通过图形分析(如柱状图、饼状图等)和/或数字分析(本文一定会涉及)来实现。所以回到讲述我们的故事,为了有一个真实的叙述,我们必须谈论两个措施;
- 集中趋势的度量
- 可变性的度量
这篇文章触及了这些度量的各种估计,并强调了它们对异常值的稳健性(即敏感性)。在对这些估计的直觉进行适当解释后,将使用“python 编程”执行实施。如果这些概念一开始有点难以理解,尝试两次或更多次,这样你的误解就有统计学意义了!😀。
一些术语的快速定义将使我们扬帆起航:
- 异常值:具有非常低或非常高的值的观察值,这些值往往与其他值存在异常的距离。异常值可能是由于测量中的可变性(包括进一步的调查)或它可能表明实验误差(可能需要从数据集中排除)。
- 分配:某物在一群人之间分配或在一个地区传播的方式。
- 顺序统计:基于从最小到最大排序的数据值的度量。
注意:本文中要考虑的这些措施都是通过 python 实现的。我选择使用一种依赖于“numpy”的方法,所以所有的技术在某种程度上都是一致的。使用的代码和数据集的链接可以在这里找到,代码嵌入在文末供参考。
让我们深入研究上面概述的两个措施,好吗?
From Pinterest
- 集中趋势的度量:集中趋势的度量是代表数据集中心点的汇总统计,这很重要,因为一个变量可能有数千个不同的值,我们希望估计我们的大部分数据位于何处。这些度量表示分布中大多数值的位置(即分布的中心),您也可以将其视为数据围绕中间值聚集的趋势。我们将在本文中介绍的一些中心位置估计包括
- 平均
- 修整平均值
- 加权平均数
- 中位数
- 加权中位数
- 方式
Photo by Hasan Albari from Pexels
Mean :这是对中心位置最基本的估计,也称为平均值。这是算术平均值,意味着它是所有值的总和除以值的个数。平均值的计算需要数据集中的所有值,因此值的任何变化都会影响平均值的计算。因此容易受到极高或极低的值(异常值)的影响。它在数学上表示为
修整平均值:这是平均值的一种变体,它是一种在计算平均值之前去除最大值和最小值的一小部分(称为截断)的平均方法。移除指定的异常值观察值后,使用标准算术平均公式计算出修整后的平均值。这有助于消除极值(异常值)的影响。它在数学上表示为
加权平均值:这是平均值的一种变化,计算方法是将每个数据值乘以一个权重,然后除以权重之和。当我们发现简单意味着我们使用相等的权重,那么为什么你会低估或高估一个变量呢?当一些值高度可变并可能导致低准确性时,可能会考虑变量的权重不足,而后者可能会在特定群体代表性不足时发生,因此我们在分析中采用权重过高的方法来捕捉它们的重要性。它在数学上表示为
Median:Median 是在有序统计中将数据集分成两半的中间值。如果有偶数个数据,中间值实际上并不在数据集中,而是将排序后的数据分为上下两半的两个值的平均值。中位数对异常值是稳健的。
***加权中值:*出于同样的原因,我们使用“加权平均值”,可以计算加权中值。这仅仅是当相关的权重被应用于排序的数据时。代替中间数,加权中值是一个值,使得排序列表的下半部分和上半部分的权重之和相等。加权平均值对异常值也是稳健的。
模式:模式是数据集中出现频率较高的值。如果没有值重复,则数据没有模式,这通常出现在连续值中(但是您可以通过定位概率分布图上的最大值来找到连续数据的模式),这就是为什么模式用于分类数据,而通常不用于数值数据。
2.分散程度的衡量:集中趋势的衡量只是故事的一部分,它总结了我们收集的信息以供分析。离差的度量简单地描述了数据集在中心位置的分散程度,显示了值是如何紧密聚集或分散的。它也被称为可变性的度量。因此,我们需要比集中趋势更多的信息来充分讲述描述性统计的全部故事。我们将在本文中介绍的一些中心位置估计包括:
- 范围
- 四分位间距
- 平均绝对偏差
- 差异
- 标准偏差
- 中位数绝对偏差
Photo by Jason Hogan on Unsplash
范围:数据集中最大值和最小值之差。这个范围很容易理解,也很容易计算,但并没有真正给出可变性的印象。此外,值得注意的是,由于其计算考虑了极值,因此对异常值不具有鲁棒性。
四分位距:为了充分理解这一点,我们必须谈谈数据分割。数据分段就是将订单统计数据分成相等的部分。通常,我们有三种相互关联的细分类型;
I .百分位数(将数据集分成 100 等份)
二。十分位数(将数据集分成 10 等份)
三。四分位数(将数据集分成 4 等份)
现在回到四分位数范围,正如我们已经知道的,它将数据集分成四个相等的部分。让我们直观地看看这种分割
对于该图,可以观察到,顺序统计的分布被分成四个相等的部分,分别包含 25%的数据集。从图中还可以看出,第二个四分位数(Q2)相当于第 50 个百分位数,这都意味着数据集的中间值(即中位数)。
四分位数范围就是第三个四分位数和第一个四分位数之间的差值。
***平均绝对偏差:*在我们深入研究这个问题之前,有必要真正理解“偏差”的真正含义。偏差仅仅是观察值和中心趋势度量的估计值(无论是平均值、中值等)之间的差异,描述了观察值如何偏离中心。
所以,平均绝对偏差是偏离平均值的绝对值。事实上,偏差的总和等于零(因为负值抵消了正值)。最终值为零说明不了什么!所以取偏差的绝对值会得到一个非零的答案,我们可以用它来描述分布的离差。
它在数学上可以表示为
***方差:*在这里,我们仍然使用偏离平均值的值,如“平均绝对偏差”中突出显示的,但是在方差中,我们不取这些偏差的绝对值,而是取其平方。这归功于这样一个事实:在统计学中,平方值比绝对值更方便。因此,方差是与平均值偏差的平方和除以 n-1,其中 n 是数据值的数量。它在数学上可以表示为
****标准偏差:从方差中可以看出,对偏差求平方将导致巨大的单位为平方的最终结果,因此为了补偿这一点,开发了标准偏差。想象一下,处理' $ '可能真的会令人困惑,但标准偏差更容易解释,因为它与原始数据集的比例相同。标准差是方差的平方根。它在数学上可以表示为
中位数绝对偏差(MAD): 到目前为止,除了 IQR 之外,我们考虑的所有离差度量都包含了所有用于计算的值,因此容易受到异常值的影响。中值绝对偏差是对变异性的稳健估计,因为它处理的是中值。中位数绝对偏差是偏离中位数的绝对值。它在数学上可以表示为
代码
总之,我们已经看到了人物、场景、情节、冲突和解决方案,讲述了描述性统计的故事,并强调了关于异常值鲁棒性的各种措施,以及如何通过 python 实现。
感谢阅读!🙌
过去 100 多年的温度
Readings: °F different from long-term average
他的可视化探索了美国过去 100 多年的气温变化。尽管美国无疑正在变暖,但各州之间和每年之间仍存在显著差异。在上面的可视化地图中,每个数据都显示为某一年某个州的平均温度与该州过去 118 年的平均温度之差。深蓝色表示今年比平均气温低得多,而深红色表示今年比平均气温高得多。下面的视频显示了 1900 年至 2017 年美国大陆气温平均值的偏差。
也许从这种形象化中最容易发现的是缺乏一个清晰的趋势。是的,在 20 世纪 90 年代,越来越多的州开始被染成深红色,但是凉爽的年代并没有消失。1998 年创下了美国有史以来最热的一年的记录,然后这个记录在 2006 年、2012 年、2015 年、2016 年和 2017 年被超过。然而,在此期间的其他年份,如 2008 年、2009 年、2013 年和 2014 年,平均气温仅略高于长期平均水平。同样,每年在州一级也很难确定一个明确的趋势。没有明显的相关性表明一个州异常温暖的一年预示着下一年同样的州也会变暖。这方面唯一明确的趋势是,温暖或凉爽的年份往往影响地区,而不是独立的国家。例如,阿拉巴马州的年平均温度远低于平均温度,很可能密苏里州和佐治亚州也记录了低于平均温度的温度。
尽管如此,这种可视化所揭示的一些趋势仍然令人不安。在过去的 20 年里,美国每年的气温都高于平均水平。自 1900 年以来,已经有 20 年超过 90%的州气温高于平均水平,其中 16 个州是自 1990 年以来。美国大陆的每个州都有 10 年高于平均温度的记录——其中 9 次发生在过去的 20 年里。如果这 10 个异常年份随机分布在 1900-2017 年期间,那么这 10 年中有 9 年会在过去 20 年中着陆的概率约为 6000 万分之一。
在全国平均气温异常高的年份,大多数州的气温也高于平均气温,这往往是事实。这意味着,近年来出现的全国平均气温偏高,通常是集体高温的结果,而不是几个异常州造成的平均值。
当然,这种可视化忽略了一些重要的趋势。一个显著的例子是一年内的温度峰值。气候变化的一个显著影响是极端和不稳定天气模式的增加。比方说俄勒冈州在某一年夏天记录了极高的温度,然后在冬天记录了极低的温度。夏季的高温可能会在全州范围内引发毁灭性的野火,冬季的冰冻可能会大大增加能源使用量并影响旅行。在这个想象中,那些极端将会消失,那一年将会被记录为平淡无奇。
这些数据是从国家海洋和大气管理局的国家环境信息中心收集的。
使用 cookiecutter 模板化您的数据科学项目
Photo by Neven Krcmarek on Unsplash
在工作和生活中,每个人都必须完成重复的任务。说到数据和分析,例如,您可能在包含相同代码集的同一个笔记本上使用了相同的文件夹结构来分析不同的数据集。在这种情况下,人们所做的就是复制和粘贴他们的文件夹,然后手动更改他们的代码输入,希望不会在途中忘记任何东西,或者在执行这种令人生畏和讨厌的任务时分心。
有一个强大的工具可以避免以上所有情况,那就是 cookiecutter !这是为您知道需要重复多次的分析类型创建项目模板的一种不可思议的方式,同时只需输入一次必要的数据和/或参数。我将在这篇博文中介绍的例子非常琐碎,但是要记住,其目的是为了理解 cookiecutter 是如何工作的。一旦做到了这一点,你只需要变得有创造性,并适应你的需求!
注意:如果您想使用 cookiecutter,它必须是您的环境的一部分。如果您使用 Anaconda,在您的终端中键入
conda list
,看看它是否出现在安装包列表中,否则只需键入pip install cookiecutter
假设我想创建一个文件夹模板(一个包含笔记本,另一个包含我需要保存的文件),我想让笔记本在数据帧上执行某种计算。下面的快照显示了我每次运行 cookiecutter 时想要复制的结构。
该笔记本的目的是创建一个可定制行数和列数的数据框架。dataframe 将用两个值之间的整数填充,这两个值每次都可以改变。该模板还允许我选择我想要在行(或列)上运行的 numpy 函数,并将结果存储到将保存在 deliverables 文件夹中的文件中。当然,每次我想创建一个包含这样一个项目的文件夹时,我希望能够输入这样一个文件夹的标题,以及我要保存的文件的名称。该模板包含奇怪的语法,如{{cookiecutter.folder_title}}
,其中folder_title
是 json 文件中包含的可定制变量之一。请记住,每次克隆模板时,包含在双花括号中的所有变量(在笔记本中,以及文件夹的名称)都将被替换为 json 文件中传递的相应值。
所有这些信息都进入cookiecutter.json
文件,该文件中的必须保存在模板文件夹、**、**的顶层,如上图所示。
填充cookiecutter.json
json 文件是一个字典,包含了我每次创建这类项目的新副本时想要更改的变量的所有默认值。
创建模板笔记本
在模板笔记本中编写您想要复制的代码,并使用我上面提到的符号来分配变量,如下面的代码行所示:
为了更好地了解正在发生的事情,可以在这个链接找到整个笔记本。
无需再复制和粘贴,即可继续您的项目!
好的,太好了!现在是时候使用这个了,但是…我如何在每次克隆我的模板时改变我输入的值呢?轻松点。
从你的终端,移动到你想要克隆项目的文件夹,输入cookiecutter <absolute_path_of_Cookiecutter_folder>
。一旦您这样做了,终端将要求您输入 json 文件中包含的所有变量的值,一次一个。如果您没有输入任何内容就按 enter 键,cookiecutter 将使用 json 文件中的默认值。完成后,瞧,项目的副本就创建好了!您将看到衍生和笔记本文件夹出现在您的当前目录及其所有内容!您现在可以打开笔记本并按原样运行它了!
这是一个很难解释的话题,不是因为它很难,而是因为它做起来比描述起来容易得多。出于这个原因,我把这个例子放在了我的 GitHub 页面上,这样你就可以克隆它并试用它了!玩了一会儿之后,你就会明白这有多强大,并且有望让你的(分析)生活变得更容易,这取决于你的需求!
请随意查看:
感谢您的阅读!
时差学习
使用时间差异(TD)学习的强化学习
在本文中,我将介绍时差学习方法。时域差分法是蒙特卡罗法和动态规划法的结合。
下面是蒙特卡罗(MC)方法的主要特征:
- 没有模型(代理不知道状态 MDP 转换)
- 代理人从采样的经验中学习(类似于 MC)
- 像 DP 一样,TD 方法部分基于其他学习估计来更新估计,而不等待最终结果(它们像 DP 一样引导)。
- 它可以从不完整事件中学习,因此该方法也可以用于连续问题
- TD 将猜测更新为猜测,并根据实际经验修改猜测
为了更好地理解这一点,考虑一个现实生活中的类比;如果蒙特卡洛学习就像一次年度考试,学生在年底完成这一集。类似地,我们有 TD 学习,它可以被认为是每周或每月的考试(学生可以在每个小间隔后根据这个分数(收到的奖励)调整他们的表现,最终分数是所有每周测试的累积(总奖励))。
TD(0)
TD(0)是 TD 学习的最简单形式。在这种形式的 TD 学习中,在每一步之后,值函数用下一个状态的值来更新,并且沿途获得奖励。这种观察到的回报是保持学习基础的关键因素,并且算法在足够数量的采样后收敛(在无穷大的极限内)。下面是 TD(0)的备份图,以及我们的 gem 收集和检查示例的 TD(0)示例。
TD(0)可以用下图中的等式来表示。等式 1 通常在文献中显示,但我发现按照等式 2 编写的等式更直观。我们用α作为学习因子,γ作为折现因子。这里,状态 S 的值在下一个时间步长(t+1)中基于在时间步长 t 之后观察到的回报 r t+1 被更新,其中 S 的期望值在时间步长 t+1 中。因此,S 在时间步长 t 处的自举使用时间步长 t+1 的估计,而 r t+1 是观察到的回报(使算法落地的真实事物)。TD 目标和 TD 误差是等式的两个重要组成部分,用于 RL 的许多其他领域。
萨尔萨
用于控制或改进的 TD 算法之一是 SARSA。SARSA 的名字来源于代理从一个状态-动作值对向另一个状态-动作值对迈出一步,并在此过程中收集奖励 R(因此是 S t,at,R t+1,S t+1 &一个 t+1 元组,它创建了术语 S,A,R,S,A )。SARSA 是一种政策上的方法。SARSA 使用动作值函数 Q 并遵循策略π。GPI(blog-2 中描述的广义策略迭代)用于基于策略π采取行动(ε-贪婪以确保探索以及贪婪地改进策略)。
SARSA 可以用下图所示的等式来表示。等式 1 通常在文献中显示,但我发现按照等式 2 编写的等式更直观。我们用α作为学习因子,γ作为折现因子。还显示了 TD 目标和 TD 误差的动作值版本。
q 学习
Q-learning 是一种非策略算法。在非策略学习中,我们评估目标策略(π),同时遵循另一个称为行为策略 (μ)的策略(这就像机器人遵循视频或基于另一个代理获得的经验的代理学习)。DQN(深度 Q-learning)登上了《自然》杂志的头版,它是一种基于 Q-Learning 的算法(几乎没有额外的技巧),在雅达利游戏中超越了人类水平的专业知识(我将在未来的帖子中详细介绍 DQN)。在 Q-learning 中,目标策略是贪婪策略,行为策略是ε-贪婪策略(这确保了探索)。
参考下图,以两种不同方式编写的 Q 学习算法。看看目标和行为策略动作在等式中是如何表示的。
预期萨莎
预期 SARSA 就像 Q-learning 一样,除了它使用期望值而不是下一个状态-动作对的最大值,并考虑了每个动作在当前策略下的可能性。给定下一个状态,Q-learning 算法确定性地将向同一方向移动,而 SARSA 按照期望跟随,因此,它被称为期望 SARSA。它的备份图如下所示。
参考下图,了解以两种不同方式编写的预期 SARSA 算法。与 Q-learning 的区别就凸显出来了。
TD 方法具有以下优势:
- TD 可以在线或离线学习每一步
- TD 可以从不完整序列中学习
- TD 可以在非终止环境中工作**(续)**
- 与 MC 相比,TD 具有更低的方差,因为它依赖于一个随机动作、转换、奖励
- 通常比 MC 更有效
- TD 利用了马尔可夫特性**,因此在马尔可夫环境中更加有效**
但是它也有下面的限制**:**
- TD 是一个有偏差的估计值
- TD 对初始值更加敏感
最后一个音符
这里我们介绍了单步 TD 方法,但也有多步 TD 方法以及 TD 和 MC 的组合,如 TD(λ)算法。TD 是强化学习中的突破性创新,每个从业者都需要将它放在他们的工具包中。
感谢阅读。可以联系我@ LinkedIn 。
只需每月 5 美元,就可以无限制地获取最鼓舞人心的内容……点击下面的链接,成为 Medium 会员,支持我的写作。谢谢大家! https://baijayanta.medium.com/membership
机器学习面试的十个要素
非常有用的在线资源列表。
作为一名博士生,我对 ML 算法有相当好的理解,但仍然发现机器学习面试具有挑战性。挑战来自于这样一个事实:在一个 ML 项目中,有比模型拟合更多的东西。大多数教科书都涵盖了 model.train()背后的技术细节。从一个 ML 教科书中推导出所有的东西,并为一个用例找到合适的 ML 解决方案,这需要两套非常不同的技能。此外,分解一个 ML 项目的复杂性,并在压力下连贯地讨论它不是开玩笑的。在准备科技公司的机器学习面试时,我试图保持一个广泛的范围,并对最广泛使用的 ML 用例进行逆向工程。
Photo by Kaleidico on Unsplash
- 除了“训练验证和测试”之外,这个脸书指南还是一个很好的通用框架这里的重点是:寻找数据来源和实验。ML 项目通常关注如何处理给定的数据,但更重要的问题是如何找到相关的数据。实验是另一个很少被讨论的方面,因为大多数 ML 模型都没有被部署。
《脸书机器学习指南》是由脸书广告机器学习公司开发的六集视频系列
research.fb.com](https://research.fb.com/blog/2018/05/the-facebook-field-guide-to-machine-learning-video-series/)
2.Andrej Karpathy 的博客文章非常棒,因为它概述了进行深度学习的高度实用的过程,即从最简单的基线开始,并从那里逐步迭代。我非常相信这个过程。这与许多人的做法相反,他们有立即使用最复杂模型的冲动。此外,从面试的角度来看,说出漂亮模特的名字比给人留下深刻印象更危险,除非你真的很了解自己。
[## 训练神经网络的方法
几周前,我发表了一篇关于“最常见的神经网络错误”的推文,列出了一些常见的问题,涉及…
karpathy.github.io](http://karpathy.github.io/2019/04/25/recipe/)
3.这篇 Airbnb 博客文章涵盖了他们如何在几个不同的阶段建立体验搜索。他们分享了这么多关于他们如何解决这个问题的细节,这太棒了。当你对问题的正确方面进行优先排序时,解决方案就会自然而然地出现。在 ML 面试中,确定主要目标并意识到限制因素是至关重要的。
我们如何为一个新的双边市场构建和迭代机器学习搜索排名平台,以及我们如何…
medium.com](https://medium.com/airbnb-engineering/machine-learning-powered-search-ranking-of-airbnb-experiences-110b4b1a0789)
4.我认为凯文·墨菲的书对于有研究生水平数学背景并有耐心读完它的人来说是一个很好的参考。然而,Hal Daumé III 的书要简洁得多,下面的备忘单包含了大多数突击测验的概念。你不想在一个基本的问题上空白或者在不必要的数学上花费时间(为了面试)。
[## 机器学习课程
机器学习是对从数据和经验中学习的算法的研究。它被广泛应用于…
ciml.info](http://ciml.info/) [## 教学- CS 229
您想看看这套母语的备忘单吗?你可以在 GitHub 上帮我们翻译!我的…
stanford.edu](https://stanford.edu/~shervine/teaching/cs-229/)
5.如果像大多数 Kaggle 竞赛中一样有足够多的高质量标记数据,使用随机森林或梯度提升就可以达到目的。最有可能的是,你不会击败 Kaggle 赢家,但在实践中,谁会关心 0.1%的改善?《统计学习元素》有关于随机森林和梯度推进的精彩章节,但下面是一篇较短的文章。此外,了解 scikit-learn 中特性的重要性是如何计算的也是值得的。
简化复杂的算法
medium.com](https://medium.com/mlreview/gradient-boosting-from-scratch-1e317ae4587d) [## 总结 Scikit 中的功能重要性-了解一组功能
是的,这是对特征集合的重要性求和的完全正确的方法。在 scikit-learn 中,重要性…
stats.stackexchange.com](https://stats.stackexchange.com/questions/311488/summing-feature-importance-in-scikit-learn-for-a-set-of-features)
6.西蒙·芬克为网飞奖设计的矩阵分解算法出奇的简单,其背后的逻辑也很直观。我们只是简单地将用户向量和项目向量线性投影到一个潜在空间中,在这个空间中,它们的相似性决定了推荐的概率。有人会说学习合适的潜在表征是最大似然法的本质。
>]网飞更新:在家里试试这个[后续]好了,我在这里告诉大家我(现在我们)是如何成为…
sifter.org](https://sifter.org/~simon/journal/20061211.html)
7.然而在实践中,与网飞竞赛相比,有许多用例特定的考虑事项。网飞竞赛基本上有固定的数据,但如果新的数据不断出现呢?此外,如果我们可以合并关于项目本身的数据,会怎么样呢?这个谷歌课程提供了更全面的指导。
YouTube 怎么知道你接下来可能想看什么视频?谷歌 Play 商店如何挑选一款适合你的应用程序…
developers.google.com](https://developers.google.com/machine-learning/recommendation/overview)
8.这篇 Instagram 博文无疑将推荐系统设计提升到了一个新的高度。它建立在上面提到的东西之上,并针对它们的特定用例进行了大量优化。
在 Instagram,我们有许多机器学习团队。虽然他们都在产品的不同部分工作,但他们都…
instagram-engineering.com](https://instagram-engineering.com/core-modeling-at-instagram-a51e0158aa48)
9.这个脸书视频从模型部署的角度提供了一个视角,并令人惊讶地揭示了他们的 ML 解决方案在高层次上的几个用例。任何想用深度神经网络解决每个问题的人都应该看看这个视频。
10.回到实验这个话题,每个人都听说过多臂强盗,但它实际上是如何工作的呢?
https://peterroelants . github . io/posts/multi-armed-bandit-implementation/
2020 年数据科学和人工智能的十大预测
当我们来到 2019 年底时,我们反思了这一年,这一年的开始已经看到 100 篇机器学习论文在一天内发表,它的结束看起来将看到人工智能打破记录的资助年。
但从数据科学和人工智能中获得真正价值的道路可能是一个漫长而艰难的旅程。
套用新经济思维研究所(Institute for New Economic Thinking)的 Eric Beinhocker 的话来说,物理技术以科学的速度发展,而社会技术以人类可以改变的速度发展——慢得多。
应用于数据科学和人工智能领域,如果决策不能有效地做出,组织流程积极阻碍数据科学和人工智能,人工智能应用程序由于缺乏信任而不被采用(“社交技术”),那么最复杂的深度学习算法或最强大和可扩展的实时流数据管道(“物理技术”)就没有什么意义。
考虑到这一点,我对 2020 年的预测试图平衡这两个方面,强调公司的实际价值,而不仅仅是数据科学团队的“酷东西”。
1。 **数据科学和 AI 角色延续了专业化的趋势。**侧重于大型生产系统以及支撑它们的基础设施和平台的“工程型”数据科学角色(“数据/ML/AI 工程师”)与侧重于调查工作和决策支持的“科学型”数据科学角色(“数据科学家/业务分析专业人员/分析顾问”)之间存在实际差异。
对比鲜明的技能组合、不同的思维模式和既定的部门结构使这成为一种引人注目的模式。前者与 IT 有着天然的密切关系,并随着更多型号投入生产而变得更加突出。它也被证明是从软件工程开始的一个可行的职业过渡(比如这里的、这里的和这里的)。相反,决策支持的即时性和持续应对不确定性的需求要求数据科学家以咨询身份融入业务,而不是通过项目进行管理。
我们继续悄悄地远离独角兽的想法,因为仅仅因为某人可以做某事,并不意味着他或她应该。尽管多才多艺的执行者有很多价值,但在建立和扩展大型数据科学团队时,他们并不是比较优势。
2。 高管对数据科学和 AI 的理解变得更加重要。人们开始意识到,数据科学价值的瓶颈可能不是数据科学或人工智能的技术方面(喘息!),而是数据科学实际消费者的成熟度。
虽然一些科技公司和大公司有一个开端,但是越来越多的人意识到内部培训项目通常是发展内部成熟度的最好方式。这是因为他们能够定制内容,从组织所处的位置开始,并根据可识别的公司业务问题和内部数据集调整培训。
3。 端到端模型管理成为需要生产的最佳实践。随着数据科学和人工智能项目在生产中的实际足迹越来越大,需要解决的问题已经合并到端到端模型管理的规程中。这包括模型的部署和监控(“模型操作”)、不同层次的支持,以及当模型随着时间的推移自然熵化时,对何时重新训练或重建模型的监督。
模型运营支持活动的系统也是一种不同于数据科学家和机器学习工程师的独特技能,推动着这些团队和支持他们的 IT 组织的发展。
4。 数据科学和人工智能伦理继续获得动力,并开始形成一个独特的学科。大规模自动化决策的二阶效应一直是一个问题,但它最终在公众意识中获得了一席之地。这是由于像剑桥分析公司丑闻和亚马逊废弃其显示对女性有偏见的秘密人工智能招聘工具这样的突出事件。
该领域本身正在围绕一系列主题寻找定义,围绕自动决策的活动以及何时让人类参与进来,算法偏差和公平性,隐私和同意,以及通往人工通用智能的道路上的长期危险。
特别值得注意的是数据科学和全球隐私法规之间的互动。GDPR 已于 2018 年年中生效,现在对数据处理和分析、模型透明度的要求以及数据科学家工作的组织对不利后果负责的可能性都有限制。
技术通常比监管范式快几年,但监管正在迎头赶上。随着数据科学和人工智能团队学会在新的约束下工作,这将导致短期的痛苦,但最终将导致长期的收益,因为可信的参与者与坏的参与者是分开的。
5。 **工具的趋同导致混乱,**由于完成同一任务的多种方式,不同的群体根据其背景偏好不同的方法。这可能会继续造成混乱,因为新进入该行业的人可能只能看到整体的一部分。
今天,如果您为大型组织工作,并且能够负担得起,那么您可以使用企业工具进行建模。如果您是 MS SQL Server 的 DBA,您可以在数据库环境中建模。如果你是一名软件工程师,你可以调用机器学习 API,开发一个“人工智能产品”。如果您熟悉云产品,可以在 AWS Sagemaker 或 Azure ML Studio 等云平台上构建和部署相同的模型。这样的例子不胜枚举。
最终结果可能是误解和地盘之争的沃土,因为相似的功能以不同的形式存在。在这种情况下,能够在完全不同的技术团队之间建立高度信任的组织将会获得当今可用工具包的全部好处。
6。 加倍努力实现数据科学和人工智能的“民主化”和“自动化”,过度承诺的政党失败了。由于人才有些难以捉摸(或者至少是分配不当),自动化数据科学和人工智能是一个有吸引力的想法。然而,现实仍然是,技术的界限只能使某些明确规定的任务自动化。
以一个典型的数据科学项目为例,围绕模型构建的活动有很多:
- 选择正确的项目,组建具有正确技能组合的团队,交流方法,并在必要时获得必要的支持和资金。
- 一旦项目开始,选择如何解决问题和采取的方法。例如,故障预测应该被框架化为有监督的还是无监督的机器学习问题?还是一个有待模拟的系统?还是异常检测问题?
- 一旦你框定了问题,选择正确的数据来使用,并选择正确的数据而不是来使用——例如,出于道德考虑。
- 在数据端进行处理,以确保不会导致错误的模型。例如,电子邮件数据实际上需要在标题、标签等之间进行大量的争论才能得到实际的信息。
- 一旦你有了数据,就产生了假设——例如,在大规模数据集中进行数据挖掘,在“进行数据科学”之前,很多工作是关于决定哪些想法可能值得研究。
- 建立并优化模型。<这就是正在被自动化的>
- 一旦你建立并优化了你的模型(如果你选择使用模型的话),决定它是否有价值。
- 一旦你决定这项工作是值得的,将开发的机器学习模型嵌入到生产系统和既定的业务流程中。仅仅这一步通常比所有其他步骤加起来花费的时间还要多。
- 一旦模型被部署,构建未来的版本以确保所构建的是完全运行的,经过测试的,并且与其他系统集成。
- 一旦整个机器学习系统经过良好的测试并达到工程标准,就可以实际解释和处理数据科学项目的输出。
就像 Wix、Squarespace 和其他网站建设者没有让 web 开发者出局一样,AutoML 和 DataRobot 也不会取代数据科学家。(然而,它们是很好的工具,应该以这种方式进行营销。)
7 .。 边缘建筑和迷雾开始进入主流。部署越来越大的复杂模型的实际必要性和工程成本正在推动新的架构模式。对于实时视频分析的计算和数据传输要求来说尤其如此,被誉为边缘分析的“杀手级应用”。这一趋势得到了计算机视觉领域的进步和新的专用商业硬件的支持,如 AWS Deeplens 。
8。 **定义的炒作周期和泛滥正在转移。**在大约 5 到 6 年前转向“数据科学”之前,它首先专注于“大数据”,2020 年可能是所有“人工智能”都可能取代对话的一年。
Big data is not the point in itself — it is what we do with it that matters.
不得不接纳大量新人的副作用之一是简化了该领域,就数据科学而言,这种简化使其更加强调统计和机器学习,而不强调运筹学和模拟等其他数学建模学科。
人工智能也开始出现类似的模式,类似的重点是机器学习、神经网络和深度学习,通常是在视觉和自然语言处理的背景下。这种弱化目前似乎出现在经典的人工智能领域,如知识表示、专家系统和规划等。
作为旁注,我完全理解转移到一个新领域是很难的,数据科学和人工智能的广度可能是压倒性的。我发现打破这堵墙最有用的东西很少是更多的内容,而是更好的导航。有人能定位我们知道什么和不知道什么,并画出个人的学习路线图,这比无序的学习材料链接列表有用得多。
9。 **竞争进入 AI 芯片市场。**英伟达在深度学习硬件市场上有着巨大的领先优势,目前主导了云中的大部分人工智能。虽然有来自谷歌、高通、亚马逊、Xilinx 和多家初创公司的重要进入者,但竞争仍主要发生在边缘地带。
这将最终改变,因为为人工智能提供动力不仅仅是一个芯片,而是一个完整的便携式硬件平台,最好没有供应商的限制。英特尔和脸书的新芯片可能是期待已久的竞争,或者它可能来自中国公司在贸易战中急于制造自己的芯片。几乎与此同时,到 2019 年下半年,阿里巴巴和华为都将发布芯片。
10。最后,**教授数据科学和人工智能并销售工具仍然比实际让它在实践中发挥作用更容易。**从数据科学和人工智能中创造价值不仅困难,而且需要超越数据科学家和机器学习工程师的讨论和共识。
从本质上来说,人工智能系统通常是优化机器。我们刚刚开始问的问题是“我们在优化什么?”尽管在数据、建模和架构方面“做正确的事情”得到了所有的关注,但在为以人为中心的体验和价值观进行设计方面,可以说更难的任务是“做正确的事情”。
同样,数据驱动的决策需要由高级、非技术决策者做出,他们通常会陷入复杂的政治阴谋网络中,并且经常在没有数据科学的情况下成功完成整个职业生涯。
在生产方面,成功的模型部署只是产品的一小部分,并且会受到从内部 IT 环境到过时的监管要求等无数因素的限制,所有这些都与处理数据固有的不确定性有关。对“生产中的模型”本身的痴迷也可能在某种程度上被误导,数据科学的主要 KPI 之一仍然是最难以捉摸的— “你改变主意了吗”?
以上显示的所有图像仅用于非商业说明目的。本文是以个人身份撰写的,不代表我所工作或隶属的组织的观点。
R 中十个你可能不知道的随机有用的东西
r 充满了有用的东西。这里有一些我经常使用的东西,其他人可能不知道。
我经常发现自己告诉我的同事和程序员同事一些我在 R 中使用的简单的事情,这些事情真的对我需要继续前进的任务有帮助。这些范围从琐碎的快捷方式,到鲜为人知的功能,到方便的小技巧。
因为 R 生态系统是如此丰富和不断增长,人们可能经常错过了解一些真正能帮助他们完成任务的东西。所以我经常会从我的观众那里得到惊讶的反应,比如“我从来不知道这件事!”。
以下是让我在 r 工作更轻松的十件事。如果你已经全部知道了,很抱歉浪费了你的阅读时间,请考虑添加一些你认为对其他读者有益的评论。
1.switch
功能
我爱switch()
。它基本上是一个根据另一个变量的值选择其值的if
语句的简化。我发现当我编写需要根据您之前的选择加载不同数据集的代码时,它特别有用。例如,如果你有一个名为animal
的变量,你想根据animal
是狗、猫还是兔子来加载一组不同的数据,你可以这样写:
data <- read.csv(
switch(animal,
"dog" = "dogdata.csv",
"cat" = "catdata.csv",
"rabbit" = "rabbitdata.csv")
)
这在闪亮的应用程序中特别有用,在这些应用程序中,您可能希望根据一个或多个输入菜单选项来加载不同的数据集甚至环境文件。
2.RStudio 快捷键
这与其说是 R hack,不如说是 RStudio IDE,但是常用命令的快捷键非常有用,可以节省大量的键入时间。我最喜欢的两个是管道操作符%>%
的 Ctrl+Shift+M 和赋值操作符<-
的 Alt+。如果你想看到这些令人敬畏的快捷键的完整集合,只需在 RStudio 中键入 Atl+Shift+K。
3.flex 仪表板包
如果你想要一个快速闪亮的仪表板,并以最少的忙乱运行,flexdashboard
包有你需要的一切。它提供了简单的 HTML 快捷方式,可以方便地构建侧栏和将显示组织成行和列。它还有一个超级灵活的标题栏,你可以将你的应用程序组织到不同的页面,并放置图标和链接到 Github 代码或电子邮件地址或其他任何东西。作为一个在RMarkdown
中运行的包,它还允许你将所有的应用保存在一个Rmd
文件中,而不需要像shinydashboard
那样将它分解成单独的服务器和 UI 文件。每当我需要在进入更高级的设计之前创建一个简单的仪表板原型时,我都会使用flexdashboard
。我经常可以使用flexdashboard
在一个小时内设置并运行仪表盘。
4.R Shiny 中 req 和 validate 函数
r 闪亮的开发可能会令人沮丧,尤其是当您得到一般性的错误消息时,这些消息不能帮助您理解到底出了什么问题。随着 Shiny 的发展,越来越多的验证和测试功能被添加进来,以帮助更好地诊断和在特定错误发生时发出警报。req()
功能允许您阻止一个动作的发生,除非环境中存在另一个变量,但这样做是无声的,不会显示错误。因此,您可以使 UI 元素的显示以之前的操作为条件。例如,参考我上面的示例 1:
output$go_button <- shiny::renderUI({ # only display button if an animal input has been chosen
shiny::req(input$animal) # display button shiny::actionButton("go",
paste("Conduct", input$animal, "analysis!")
)
})
validate()
在呈现输出之前进行检查,并使您能够在不满足特定条件时返回定制的错误消息,例如,如果用户上传了错误的文件:
# get csv input fileinFile <- input$file1
data <- inFile$datapath# render table only if it is dogsshiny::renderTable({
# check that it is the dog file, not cats or rabbits
shiny::validate(
need("Dog Name" %in% colnames(data)),
"Dog Name column not found - did you load the right file?"
) data
})
关于这些函数更多信息,请参见我的另一篇文章这里的。
5.使用隐藏凭据。伦韦龙
如果您正在共享需要登录数据库等凭证的代码,您可以使用.Reviron
文件来避免将这些凭证发布到 Github 或其他可能存在风险的空间。.Renviron
是一个可以存储重要环境变量的文件,可以使用usethis
包中的edit_r_environ()
函数轻松编辑。例如,您可以在.Renviron
中为您的远程数据库凭证设置一个别名,例如:
DSN = "database_name",
UID = "User ID",
PASS = "Password"
然后在你的共享脚本中,你可以调用这些变量。例如:
db <- DBI::dbConnect(
drv = odbc::odbc(),
dsn = Sys.getenv("DSN"),
uid = Sys.getenv("UID"),
pwd = Sys.getenv("PASS")
)
6.使用 styler 自动进行 tidyverse 造型
这是艰难的一天,你已经有很多事情要做了。你的代码不像你想的那样整洁,你没有时间来编辑它。不要害怕。styler
包有许多功能,允许你的代码自动重定风格以匹配 tidyverse 风格。在你混乱的脚本上运行styler::style_file()
很简单,它会为你做很多(虽然不是全部)工作。
7.参数化 R 降价文档
所以你写了一个可爱的 R Markdown 文档,其中你分析了一大堆关于狗的事实。然后你被告知——“不,我对猫更感兴趣”。不要害怕。如果您将 R markdown 文档参数化,那么只需一个命令就可以自动生成类似的关于 cats 的报告。
您可以通过在 R Markdown 文档的 YAML 头中定义参数,并给每个参数赋予一个值来做到这一点。例如:
---
title: "Animal Analysis"
author: "Keith McNulty"
date: "21 March 2019"
output:
html_document:
code_folding: "hide"
params:
animal_name:
value: Dog
choices:
- Dog
- Cat
- Rabbit
years_of_study:
input: slider
min: 2000
max: 2019
step: 1
round: 1
sep: ''
value: [2010, 2017]
---
现在,您可以将这些变量作为params$animal_name
和params$years_of_study
写入文档中的 R 代码。如果您正常编织您的文档,它将按照value
变量用这些参数的默认值编织。但是,如果您通过在 RStudio 的编织下拉菜单中选择此选项(或使用knit_with_parameters()
)来编织参数,则会出现一个可爱的菜单选项,供您在编织文档之前选择参数。厉害!
Knitting with Parameters
8.revealjs
revealjs
是一个软件包,可以让你用一个直观的幻灯片导航菜单创建漂亮的 HTML 演示文稿,并嵌入 R 代码。它可以在 R Markdown 中使用,有非常直观的 HTML 快捷方式,允许您创建一个嵌套的、逻辑结构的漂亮幻灯片,有各种样式选项。事实上,演示是 HTML 格式的,这意味着人们可以在平板电脑或手机上听你讲话,这非常方便。您可以通过安装包并在您的 YAML 头文件中调用它来建立一个revealjs
演示。这是我最近用revealjs
做的一个演讲的 YAML 标题的例子
---
title: "Exporing the Edge of the People Analytics Universe"
author: "Keith McNulty"
output:
revealjs::revealjs_presentation:
center: yes
template: starwars.html
theme: black
date: "HR Analytics Meetup London - 18 March, 2019"
resource_files:
- darth.png
- deathstar.png
- hanchewy.png
- millenium.png
- r2d2-threepio.png
- starwars.html
- starwars.png
- stormtrooper.png
---
Easy online presentations using revealjs
9.R Shiny 中的 HTML 标签(例如在你的 Shiny 应用程序中播放音频)
大多数人没有充分利用 R Shiny 中可用的 HTML 标签。有 110 个标签提供了各种 HTML 格式和其他命令的快捷方式。最近,我开发了一个闪亮的应用程序,它需要很长时间来执行一项任务。知道用户可能会在等待任务完成的同时进行多任务处理,我使用tags$audio
让应用程序播放胜利的号角,在任务完成时提醒用户。
10.表扬包
可笑的简单,但也很棒,praise
包向用户传递赞美。虽然这看起来像是毫无意义的自我欣赏,但它实际上在编写简历包时非常有用,如果某人做对了,你可以对他进行表扬或鼓励,例如,如果一个过程成功完成。你也可以把它放在一个复杂脚本的末尾,当它成功运行时,给你额外的快乐。
The praise package
最初我是一名纯粹的数学家,后来我成为了一名心理计量学家和数据科学家。我热衷于将所有这些学科的严谨性应用到复杂的人的问题上。我也是一个编码极客和日本 RPG 的超级粉丝。在 LinkedIn 或Twitter上找我。
一万次初次约会:强化学习浪漫
新西兰——我生活的地方——历史上没有“约会”文化,更没有“狂饮”文化。我年轻时普遍接受的交配仪式是喝得酩酊大醉,在一个完全陌生的人的陪伴下醒来,然后——如果你喜欢他们的样子——羞怯地建议再次订婚。但是时代在变。约会应用和日益全球化的文化让“约会”的概念在新西兰变得更加流行,如果一个人想在现代吸引情郎,他必须适应。我必须学会如何去约会?这对我来说是未知的领域!我的成长经历和以前的社会经验都没有让我准备好在吃饭时与一个有魅力的陌生人交谈的严酷。在和某人共度一夜之前决定我是否喜欢他的想法很奇怪,坦白说有点可怕。更令人不安的是,与此同时,他们会决定是否喜欢我!这是一个雷区。一个复杂的环境,充满了失误和变化的规则。一个不同于我自己的社会和文化。换句话说,它是机器学习算法的完美环境。
我们将要使用的特定算法在机器学习领域有点奇怪。这与我们之前看到的分类和回归方法有很大不同,在分类和回归方法中,一组观察结果被用来推导出规则,从而对未知情况做出预测。它也不同于我们见过的更非结构化的算法,例如让我们提出针织图案建议或找到类似电影的数据转换。我们将使用一种叫做“强化学习”的方法。强化学习的应用非常广泛,包括机器人的复杂控制器、建筑物中电梯的调度以及教计算机玩视频游戏。
在强化学习中,一个“代理”(计算机)试图通过在复杂的环境中做出选择来最大化它的“回报”。我将在这篇文章中使用的具体实现被称为“q-learning”,这是强化学习的一个最简单的例子。在每一步,该算法记录环境的状态,它所做的选择,以及该选择的结果,即它是产生奖励还是惩罚。该模拟被重复多次,并且计算机随着时间的推移学习在哪些状态下的哪些选择导致最大的奖励机会。
例如,想象一个强化算法学习玩视频游戏“Pong”。在 pong 中,两个玩家用一个白色的线代表的小球拍面对面。一个用白点表示的球在它们之间来回弹跳。球员可以上下移动球拍,试图阻挡球并将其反弹给对手。如果他们错过了球,他们失去了一分,游戏重新开始。
每半秒或四分之一秒,强化算法会记录下球拍的位置和球的位置。然后它选择向上或向下移动它的桨。起初,它随机做出这个选择。如果在接下来的时刻球还在比赛中,它会给自己一个小小的奖励。但是,如果球出界了,失分了,它会给自己一个很大的处罚。将来,当算法做出选择时,它会查看过去的行为记录。当选择导致奖励时,它更有可能再次做出选择,而当选择导致惩罚时,它就不太可能重复错误。在训练之前,算法随机上下移动桨,什么也没达到。经过几百轮训练后,动作开始稳定,它试图用桨抓住球。经过成千上万回合,它是一个完美的球员,从来没有错过球。它已经学会了什么叫做“政策”——给定一个特定的游戏状态,它精确地知道哪一个动作将最大化它获得奖励的机会。
但是如何将这一点应用到我目前的困境中呢?我如何用强化学习来教自己去约会?
首先,我需要一个典型约会场景的完全准确的模拟。然后,我将训练一名代理人完美地完成这次模拟。最后,我可以检查代理学习的策略,以确定最佳约会策略。这是一个万无一失的计划。
第一,模拟。我想给你介绍一个我开发的小程序,叫做完全精确的日期模拟器。这是对两个人之间的现代约会的完整而彻底的模拟。让我简单解释一下:
每次约会都要进行十轮。在每一轮约会中,代理人从四个普遍接受的话题中选择一个话题:体育、流行音乐、历史、机器学习和人工智能。这个话题会让代理人的伙伴高兴或不高兴,伙伴会给出微妙和模糊的信号。一旦伴侣对机智的对话感到足够满意,代理人可能会尝试“调情”,这将有望使约会圆满结束。代理人也可能选择喝酒——增加他们的信心,并希望给他们的谈话增添一些亮点;或者,对日期感到绝望,代理人可以选择离开。
从我以前不懂编织的失败中吸取了教训,我招募了一些约会专家来给出他们对模拟器的看法。他们把它描述为“令人困惑”、“武断”和“毫无意义”,由此我得出结论,这是一个非常成功的模拟。
你可以使用完全精确的约会模拟器试试自己的约会运气。
Totally. Accurate.
所以,现在来训练我们的特工如何应对复杂的人际关系网。
我们派我们的代理人去约会一万次。代理记录每个点的日期状态,以及到达该点所采取的操作。任何以成功结束的约会都会有奖励。代理人会记住并更有可能重复导致这个结论的行为。起初,它会随机选择行动,但随着它在日期上的成功,它会更重视这些选择,更详细地探索这些成功的途径。
在训练期结束时,我们可以检查代理的表现如何——在 100 次约会中,有多少次以成功告终?我们运行模拟,发现…
…灾难!代理每次约会都失败!检查代理人的行动,他似乎仍然在作出基本上随机的选择。他什么都没学到!出了什么问题?原来这是强化学习的通病。代理需要采取的一系列行动是漫长而复杂的。他偶然发现这一点的几率非常低,而他经常重复这一点以形成强有力政策的几率几乎为零。这意味着,即使在一万次约会之后,代理人也没有学到足够的东西来可靠地吸引他的伴侣——他在约会中的成功永远不会超过随机的机会。
我们需要做的是创造所谓的“有形”奖励。我们需要奖励经纪人朝着成功约会迈出的一小步,比如选择一个好的话题;惩罚犯错的代理人,比如用一个糟糕的话题来烦对方。
有了这种新方法,我们将让代理人进行另外一万次约会,并再次测试他,引导我们…
…又是灾难!代理人每次约会都失败,当我们看他在约会中的行动时,很容易看出为什么:他在每次约会中的第一个也是唯一的行动是立即离开。他已经得出结论,惩罚比奖励要多得多,整个“约会”的情况是一个净损失。他最好的选择是在他有机会累积任何惩罚之前,尽早退出。我的约会专家小组将这种行为描述为“可能是聪明的”,以及“专家级的约会”。
这是强化学习困难的核心,事实上也是所有人工智能的核心。它不折不扣地遵循它的指示。代理对“正确”的结果没有概念。它只是将奖励最大化,将惩罚最小化。追求最优政策是无情的。代理人不知道“应该”如何处理问题,只知道实际的结果。在最好的情况下,这是人工智能的一大优势——没有先入之见,它可以发现解决问题的新方法,并丢弃任何不相关的东西。但在最坏的情况下,这是一个很大的弱点。代理人抛弃的许多先入之见都是长期来之不易的经验的产物。它忽略的许多“无关紧要”的副作用是至关重要的。
但是我呢?我应该在学习如何约会!我不满意!肯定有一种方法可以教会我们的代理人成功约会,至少像人类一样。我不断调整奖励结构,增加各种大小的惩罚和奖励。每一次,代理人都会使他的报酬最大化。有时,他会在愉快的谈话中度过整个约会,但从不冒险调情来进一步约会。有时他会借酒消愁,闷闷不乐地坐着,直到时钟显示日期。但最终,我得到了正确的公式。
奖励和惩罚的结合恰到好处,代理人实际上开始成功了。在一百次约会之后,他每十次中就有一次成功了。一千次后,他达到五分之一,到一万次约会结束时,他的学习稳定下来,三次约会中有一次成功。这比我自己能做到的要好得多。检查代理人的政策表明,他采用了一种相当传统的方法:他尝试各种主题,直到他发现一些有吸引力的东西,然后坚持下去,直到他收到足够的积极反馈。然后他转向调情,直到约会成功。如果他在任何时候被拒绝,他会喝几杯烈酒来壮壮胆,然后再试一次。
我们学到了什么?我从我的约会专家小组中了解到,将浪漫的进展描述为只有一种成功结果的对抗性遭遇是“不健康的”和“有点令人毛骨悚然的”。我还了解到,在理解现实世界时,强化学习的价值有限。没错,代理学会了成功地驾驭我构建的模拟,但是我真的能把这些经验应用到现实世界吗?这只在我的模拟准确的范围内有用。此外,在我如何构建我的模拟,以及我如何形成有助于代理学习的奖励,我都在实验中构建我自己关于约会如何工作的假设。但我认为,这个实验的关键教训是,人工智能对“成功”的定义与你我非常不同,也非常狭隘。智能体不关心它如何实现其目标,也不考虑超出其被赋予的参数的严格限制的任何问题。它不在乎从给定的数据中“应该”得出什么结论,也不在乎这些结论会导致什么意想不到的后果。当人工智能应用于现实世界的问题时,如果我们希望它的结果符合人类的安全感和公平感,我们就必须依靠人类的判断和人类的同情心。
感谢阅读!这篇短文的所有代码都可以在我的 github 中找到, 这里 。别忘了试试 完全精确的日期模拟器 。你可能会喜欢我以前的一篇文章,《游戏中的大脑》,这里是*。下个月再查一篇新论文。***
使用 Selenium 收集网球奖金数据
利用模式的进行多页面网页抓取,并在硒中等待
Lucas Davies via Unsplash
介绍
这篇教程将详细介绍如何利用模式来迭代目前参加 ATP 巡回赛的前 200 名男子网球选手。
具体来说,对于每个球员,我想提取他们各自的姓名、年龄和截至 2019 年 7 月 29 日的奖金。web 抓取将使用 Selenium 模块执行,并将利用该模块中的一些有用的类,这将确保代码更有效地运行。
在这个例子中,玩家姓名和年龄在同一网页上,但是他们各自的奖金收入在单独的页面上,对于每个玩家是唯一的。
通过使用 Selenium 模块,可以获得这些信息。
入门和模式搜索
首先,我从 Selenium 模块导入 webdriver。然后,我创建一个 web 驱动对象,并将其分配给变量 browser。接下来,我只需导航到 ATP 巡回赛网页,如下所示。
现在已经加载了适当的网页,我可以清楚地看到前 100 名男单选手的列表(下图中的*,只显示了前 11 名,但向下滚动到底部会显示前 100 名选手*)。
为了遍历前 100 个玩家,我需要在数据组织中找到一些一致性。具体来说,当我右键单击、选择 inspect 并将鼠标悬停在玩家名称上时,我可以复制 Xpath。
然后,我将这个 Xpath 粘贴到 Chrome 开发者工具的控制台标签中。当我第一次复制并粘贴诺瓦克·德约科维奇的 Xpath 时,我可以看到球员对应于表行 1,tr[1]和表数据 4,td[4]。通过检查其他玩家,例如下面突出显示的 Fabio Fogini,我可以看到 Xpath 中唯一改变的部分是表的行号 tr[9]。
这是有意义的,因为数据被组织成表格格式,因此具有我可以利用的一致性。为了利用这个特性,我可以简单地替换 Xpath 的 tr 部分中的数字,并使用从 1(含)到 101(不含)的范围遍历所有玩家的名字!
我利用相同的关系提取玩家的年龄,但是在这种情况下,表中的数据 td 在第 5 列。
代码工作流
我希望我的代码如下工作:
- 转到主排名页面,从排名最高的玩家开始查找个人玩家姓名和年龄,并提取此信息。
- 点击每位玩家的链接,从排名最高的玩家开始,提取他们今年到目前为止的奖金(截至 2019 年 7 月 29 日)。
- 导航回主排名页面,对前 100 名玩家重复步骤 1 和 2。
- 获得前 100 名玩家的数据后,点击进入下一页,玩家排名在 100-200 之间,重复步骤 1 和 2。
- 一旦获得了这些信息,就停止迭代并将输出写入 Excel,以便进行下游数据操作和验证。
Webdriver 等待和预期条件一起工作
当浏览器加载页面时,该页面中的元素可能会在不同的时间间隔加载。这使得定位元素变得困难:如果元素还没有出现在 DOM 中,定位函数将引发 ElementNotVisibleException 异常。使用等待,我们可以解决这个问题。
显式等待使 WebDriver 在继续执行之前等待某个条件发生。
为了使代码更加健壮,我将指示代码在对 web 元素执行任何操作之前等待,直到找到或可以点击 web 元素。下面是两种重要的硒,来源于:https://seleniumhq.github.io/selenium/docs/api/py/api.html。
WebDriverWait 和 expected_conditions 可以一起使用。在下面列出的预期条件示例中,我将等待定位 an 元素的可见性。
类 selenium . web driver . support . wait . web driver wait(driver,timeout,poll_frequency=0.5,ignored _ exceptions = None)
类 selenium . web driver . support . expected _ conditions . visibility _ of _ element _ located(locator)
如何在预期条件下使用 Webdriver Wait?
WebDriverWait 有两个必需的参数,即驱动程序、浏览器和超时。超时指示如果找不到相应的 web 元素,在引发超时异常之前要等待多长时间。
让我们剖析一个例子。
我想提取下面有 Xpath 的玩家名字
//*[@ id = " rankingDetailAjaxContainer "]/table/tbody/tr[1]/TD[4]/a '
我写了 WebdriverWait,然后是我的驱动程序 browser,然后等待 20 秒。然后,我通过将visibility _ of _ element _ located附加到expected _ conditions,告诉 webdriver 等待元素可见。 我接着指定一个定位器使用 通过。Xpath(大写) ,后面是引用的适当 XPATH。
添加等待会在脚本中添加额外的检查步骤。这在 for 循环中在网页之间切换时特别有用,因为 web 元素可能需要一点时间来加载。
结合这些核心思想,现在可以创建一个范围为 1 到 101 的 for 循环,以收集每页上前 100 名玩家的数据。
当使用。文本功能,然后代码指示浏览器点击每个玩家的链接并提取他们的奖金。这里,不是通过提取玩家名字。短信功能,我用点击他们的名字。单击()方法,如下面的代码所示。由于每个玩家都在同一行,我可以使用我之前发现的模式来显示玩家统计页面的所有唯一链接。
每个玩家的奖金可以简单地通过复制 Xpath 找到。对于每个玩家,数据是统一组织的,因此这个 Xpath 将在 for 循环的每次迭代中为每个玩家工作。
一旦实现了这一点,我导航回到单打排名页面,提取排名第二的球员的姓名、年龄和收入。在 for 循环的每次迭代中,我都会将数据追加到 Tennis_player、Age 和 Prize_money_2019 的列表中。
当第一批 100 名玩家的数据收集完毕后,我导航到下一个页面,再次检查网页上是否有这样的按钮,并且可以点击。while 循环中的条件告诉代码返回到哪个页面。
当 while 循环的两次迭代完成后,我使用 pandas 将数据写入 Excel 文件,方法是创建一个 DataFrame 并将我的列表压缩在一起,并给它们指定合理的列名。
为了澄清脚本运行顺利,在每一次迭代中,我打印了玩家,以及他们的年龄和奖金。这是不必要的,但是给了我一个迭代进度的视觉检查。下面显示了该输出在控制台中的外观示例。
确认
最后,验证代码是否按预期工作是很重要的。例如,我将检查 3 个玩家,以显示已经获得了正确的数据。首先,让我们通过查看我的 Excel 文件“Tennis_Player_Earnings”来确认诺瓦克·德约科维奇的奖金是 8,839,549 美元。
成功!现在让我们再次检查与另一名球员,即劳埃德哈里斯。他的奖金应该是 275531 美元。
在与诺瓦克争夺奖金之前,劳埃德似乎还有一段路要走!
为了再次确认,我应该检查第二页的玩家,即排名在 100-200 之间的玩家是否有正确的奖金。排名第 188 位的鲁本·贝蒙尔曼斯本应获得 103,754 美元的奖金。这将确认点击到下一页的工作符合预期!同样,信息是正确的。
该代码在一个单独的页面上自动遍历网球运动员和他们的奖金,通过他们名字上的链接可以访问。实时观察自动 web 迭代显示了这个过程是如何工作的。为了演示,描述了显示前 3 个玩家的迭代的视频。
摘要
这个例子说明了,通过寻找模式并利用它们,以及等待 web 元素加载并填充网页,我们可以提取信息,而不会出现常见的元素位置错误。但是,需要注意的是,这些模式是使用 Xpaths 找到的。
如果该页面的组织者决定添加一列或将玩家姓名移动到另一列,脚本将会中断,因此在使用 Xpaths 时要小心,并尽可能使用 CSS 选择器。然而,如果您正在编写一个像这样的快速脚本,并将数据输出到 Excel,所示的方法应该足够了,但是不要期望它能工作 X 个月。
tensor flow 2.0——在 Google Colab 上创建和训练一个普通的 CNN
Colab 和 Tensorflow 2.0 简介
Tensorflow 2.0 在不到一周前发布,它一直是我的 twitter TL 上讨论最多的话题,所以我决定加入讨论并写这篇文章。Tensorflow 有一些重大改进,同时使任何人都可以轻松开始使用它。Tensorflow 2.0 现在与 Keras 高度集成,这使得用最少的专业知识构建和测试简单模型更加容易。谷歌还决定强调“热切执行”,而不是建立基于会话的模型。急切执行允许立即计算 python 操作,而不是构建计算图。这篇文章将一步一步地介绍如何使用 Google Colab 并在 Tensorflow 2.0 中构建 CNN 模型
对于那些不知道 Google Colab 是什么的人(如果你知道,你可以跳过下面几行),它是一个在线 Jupyter 笔记本,让你编写和共享代码。最好的部分是代码在谷歌的服务器上执行。你甚至可以选择在谷歌的云 GPU 或 TPU 上训练你的模型。
要在 GPU 或 TPU 上训练您的模型,请转到运行时→更改运行时类型→硬件加速器
资料组
我们将使用的数据集是德国交通标志识别基准。该数据集包含 50K 多幅图像和 40 多种交通标志。
让我们从代码开始
玩弄我们的数据
第一部分是将数据集导入 Google Colab。你可以把你的数据上传到你的 google drive,然后把它安装到你的 Colab 笔记本上。将数据集作为. zip 文件上传到驱动器后,在您的 Colab 笔记本中键入以下代码以挂载驱动器。
Mount your drive
您可以使用 shell 命令 unzip 解压缩该文件。通过在命令前面加上“!”,可以在笔记本单元中调用 Shell 命令。看看下面的例子。
note: If you have spaces in your directory names, use escape sequence ‘\’
数据集已经分为训练和测试图像,其中 75%的图像用于训练,其余用于测试我们的模型。由于我们已经装载了驱动器,现在我们可以通过引用驱动器中的路径来访问数据集。看看下面的代码来加载训练和测试数据。
Loading Training data
Loading Testing data
我们使用 PIL 从目录中加载图像,由于图像的尺寸不同,我们使用 im.resize()将每个图像的尺寸调整为 100x100 的标准尺寸。我们现在将 train_images、train_labels 和 test_images 从列表转换为 numpy 数组。numpy 数组“train_labels”在每一行中只有一个条目,因此我们使用下面的代码对它进行了整形。
reshape labels of training data
注意:“-1”表示未知维度
既然我们已经重塑了我们的培训标签,我们可以将它们转换成一次性编码。要了解什么是一次性编码以及我们为什么要这样做,请点击这里。
One-hot encoding our training labels
Scikit-learn 有一个预定义的函数,我们可以直接导入它来创建我们的一次性编码标签。我们现在通过将图像除以 255 来标准化它们。
Image Normalization
将图像除以 255.0 将每个图像中的像素值范围减少到 0.0–1.0,这从我们的模型中提供了更好的结果。
构建我们的模型
在我们开始编写模型之前,检查我们的 Colab 是否使用 Tensorflow 2.0 作为后端,我们可以通过输入以下命令来完成。
check TensorFlow version
如果 Tensorflow 的早期版本被用作后端,我们可以通过在笔记本中键入以下命令来升级它
Upgrade Tensorflow
现在,我们可以开始进行必要的导入,并根据我们的训练数据创建批量张量。
Create tensor slices from training data
Tensorflow 的数据集库(tf.data)在 2.0 版本中进行了扩展,并随着新的添加而变得更加复杂。
- from_tensor_slices()函数接受 numpy 数组作为参数,并生成张量对象。
- shuffle()以 buffer_size 作为参数,从缓冲区中随机抽取元素。
- batch()函数将 batch_size 作为参数,并将数据中的连续元素合并成与 batch_size 相等的批
记住 Tensorflow 2.0 更强调“急切执行”,避免计算图。因此,一旦单元被执行,操作就被评估。因此,train_ds 有两个随机采样和批处理的张量。这些张量代表训练图像和标签。
让我们开始对模型的架构进行编码。
Model Architecture
我们创建我们的模型类(MyModel)作为模型的派生类。这为我们节省了大量编写自己的模型类的时间。我们将使用的架构是一个简单的 CNN,具有用于类别预测的密集层。想了解更多关于 CNN 的信息,请点击这里。在定义了我们的模型架构之后,我们为我们的模型创建一个对象,然后继续定义我们的损失函数、优化器和度量标准。
我们使用分类交叉熵作为我们的损失函数,使用亚当作为我们的优化器。
- train_loss 将是每个时期所有损失的平均值
- train_accuracy 将是我们的模型在每个时期的精度度量
上述函数用于训练我们的模型。它接收图像和相应的标签,计算损失和梯度。
- 由于 Tensorflow 2.0 使用“热切执行”,性能和可部署性可能会受到挫折。为了确保出色的性能和普遍的可部署性,我们可以添加一个 decorator @tf.function,这个 decorator 将函数转换成一个图形。
- tf。GradientTape()是用于计算差异的高级 API。在上面的代码行中,我们根据真实标签和预测标签计算损失,并使用梯度磁带来计算损失相对于模型变量的梯度(微分),并将它们应用于优化器
- 我们还会计算每一步的训练损失和准确度
既然我们已经完成了构建模型的所有必要步骤,我们就开始训练它,但是要执行下面的代码。
model training
我们为 5 个时期训练模型,并在每个时期后保存模型的权重。请注意,模型权重将保存在谷歌驱动器中。我们还重置了每个时期的训练损失和准确度值。
若要加载模型的权重,请创建 MyModel 类的实例,并使用 load_weights(path)函数。
基于测试集的预测
Model predictions
我们可以通过提供 test_images 作为参数来获得模型预测,由于模型返回概率分布,我们使用 np.argmax()来获得最高值。
结论
通过遵循以上步骤,您已经使用 Tensorflow 2.0 成功地对 CNN 进行了关于 Colab 的培训。如果您有任何疑问,请与我联系:)
链接至完整代码:https://github.com/grohith327/traffic_sign_detection
参考
[## 有效张量流 2 |张量流核心
TensorFlow 2.0 有多种变化,以提高 TensorFlow 用户的工作效率。TensorFlow 2.0 消除了冗余…
www.tensorflow.org](https://www.tensorflow.org/guide/effective_tf2) [## TensorFlow 2 专家快速入门| TensorFlow Core
这是一个谷歌协作笔记本文件。Python 程序直接在浏览器中运行——这是一种很好的学习和…
www.tensorflow.org](https://www.tensorflow.org/tutorials/quickstart/advanced)
面向文本分类的 Tensorflow 2.0 数据转换
一个完整的端到端文本分类过程
在本文中,我们将利用 Tensorflow 2.0 和 Python 来创建一个用于对电影评论进行分类的端到端流程。大多数 Tensorflow 教程侧重于如何使用预处理数据集设计和训练模型。通常,预处理数据是人工智能项目中最耗时的部分。本文将带您完成这一过程。注意:我们并不试图在这里生成一个最先进的分类模型。目标是解释如何在张量流模型中准备用于训练和评估的数据。我们将使用本页的中定义的模型,并通过解决本教程中未涉及的两个挑战来改进流程:
- 我们如何将原始文本加载到模型中并对其进行训练?
- 一旦创建并训练了模型,我们如何使用它根据新的输入数据生成预测?
挑战 1
我们如何将原始文本加载到模型中并对其进行训练?
关于神经网络,你能知道的最重要的事情是,它们只对数字数据起作用。因此,为了进行文本分类,必须将原始文本数据转换为数字。Tensorflow 教程使用预处理数据集,其中所有文本都已转换为数值。这对于构建原型和评估不同的模型是很好的,但是它跳过了将文本数据转换成数字数据的过程。为了解决这个问题,我们将不使用预处理数据。相反,我们将下载并使用斯坦福大学提供的带标签的 IMDB 评论中的原始文本数据。
!wget -q [http://ai.stanford.edu/~amaas/data/sentiment/aclImdb_v1.tar.gz](http://ai.stanford.edu/~amaas/data/sentiment/aclImdb_v1.tar.gz)
!tar zxf aclImdb_v1.tar.gz
!tree -d aclImdb
根目录包含我们的测试和训练数据集的子目录。在每个目录下,都有包含 pos 和 neg 评论的目录。每个目录包含 12500 条评论。注意,对于本教程,我们不使用unsupp目录。
现在我们需要创建一个 train 和 test dataframes,每个 dataframes 有两列: text (评论文本)和 sent (评论的情绪)。我们通过遍历该函数中的目录来实现这一点:
现在我们已经加载了数据,是时候将文本数据转换成数值了:
NUM_WORDS 是一个变量,包含我们希望保留在词汇表中的单词数。对于本例,我们将其设置为 8000。第 2 行和第 3 行创建了一个标记器,用于索引我们的训练数据中最常用的 8000 个标记。第 6&7 行使用索引为评论中的每个单词生成数值。SEQ _ 伦是我们定义的另一个变量,用于确定每次评论使用多少单词。在本例中,我们将其设置为 256。因为我们模型的每个输入必须包含相同数量的标记,所以第 11 & 12 行将每个评论截断为 256 个字符,如果评论少于 256 个字符,则填充它。
现在是时候构建和训练我们的模型了。大部分代码直接取自 Tensorflow 2.0 教程,尽管我对培训部分做了一些改进,我将在下面描述:
第 1 行到第 10 行直接来自教程,没有任何修改。在第 13 行到第 15 行,我添加了一个 EarlyStopping 回调,如果验证精度开始下降,它会导致模型停止训练,这有助于减少过度拟合。第 16–20 行是我们实际训练模型的地方。我使用的参数与本教程略有不同,所以下面是对每个参数的描述:
- batch_size —传递给训练周期每批的示例数量。最初的教程将此设置为 512。这是一个可调超参数的例子。在尝试了不同的值之后,16 给了我最好的结果,但是通过更新 BATCH_SIZE 常量可以很容易地改变它。
- epochs —我们通过模型运行完整训练集进行训练的次数。它被设置为 20,但是由于 EarlyStopping 被启用,它很可能永远不会达到这个值。如果达到了 20,你可以增加它来看看你是否能得到更好的结果。
- validation_split —这里我们说 20%的输入数据将用于验证我们的模型学习得有多好。如果我们开始看到我们的准确性增加,同时看到我们的验证准确性下降,那么我们是过度拟合。在这种情况下,我们应该停止训练,因为这已经是最好的了。
- 回调——这是我们传递早期停止回调的地方。
在第 22 行,我们通过传入模型从未见过的新输入数据来评估模型。您应该会看到大约 87%的准确性,考虑到我们的神经网络仅用了大约四行代码来构建,这是相当不错的。在文章的最后,我将讨论一些事情,试图使模型更加准确。
挑战#2
一旦创建并训练了模型,我们如何使用它根据新的输入数据生成预测?
原 Tensorflow 教程到此结束。在这一点上,我们有一个经过训练的模型,但还不清楚我们将来如何使用它来根据新数据进行预测。
首先,我们需要保存模型和我们的标记器。我们是这样做的:
在第 2 行中,我们将模型及其所有权重保存到一个名为 model.h5 的文件中。然后我们可以删除我们的模型和记号化器,因为我们已经完成了训练。
现在,我们准备使用我们的训练模型对一些新数据进行一些推断:
- 第 1–4 行从磁盘加载我们的模型和标记器。
- 第 6–9 行将我们的文本输入转换为我们的模型需要的数字输入,其方式类似于我们为训练所做的。
- 第 11-14 行包含了我写的一些评论。请随意在这里添加一些您自己的评论。
- 第 15 行调用我们的数据准备函数来为我们的输入数据生成数字序列。
- 第 17 行根据我们的输入数据做出预测。
需要注意的是,loaded_model.predict 的返回值是一组评论为正面的概率。为了解决这个问题,我使用一个阈值来确定一个评论是否是正面的。在这种情况下,如果它在 60%以上,那么它是一个积极的评论。否则就是否定的。这是一个您可以试验和修改的任意阈值。下面是一些查看和解释推理结果的帮助器代码:
- 第 1-3 行创建了一个包含原始文本和预测情感的数据框架。
- 第 5 行根据阈值将数字情感值转换为“正”或“负”
- 第 7 行打印出我们的结果:
在本文中,我们采用电影评论的原始文本,并对其进行预处理,以输入到 Tensorflow 2.0 神经网络模型中。然后,我们将数据输入到一个模型中,并取得了一些不错的结果(大约 87%的准确率)。一些增强功能可能会改善这种情况:
- 在构建我们的模型之前过滤掉停用词。停用词是正常英语所必需的词,但对确定文章的意思没有任何价值。一些例子包括:" the "," of "," a ",…这将有助于我们的模型只关注有意义的单词。
- 对模型的细微调整。Tensorflow 2.0 使向我们的神经网络添加新层变得极其简单。我们可能希望在我们的 GlobalAveragePooling1D 层和最终的密集层之间添加一些密集层和/或下降层。
- 对模型的重大调整。这是一个非常简单的模型,还有更复杂的模型,比如 RNN 的、LSTM 的和 CNN 的。也有全新的方法,如 BERT。
需要注意的最重要的一点是,无论您选择什么方法,您仍然必须遵循这里介绍的步骤来为神经网络处理您的数据。
我已经在 Google Colab 上分享了这个模型。我期待在下面的评论区听到你的反馈。
TensorFlow 2.0:动态、可读、高度扩展——Exxact 博客
考虑学习深度学习的新 Python 框架?如果你已经知道一些 TensorFlow,并且正在寻找一些更有活力的东西,你不必再完全切换到 PyTorch,这要感谢 TensorFlow 2.0 中的一些实质性变化。事实上,2.0 中的许多变化专门针对 TensorFlow 的所谓缺点。默认情况下,有了急切执行,当你过分热衷于你的面向对象原则时,你不再需要预先定义一个静态图,初始化会话,或者担心张量超出适当的范围。TensorFlow 仍然拥有大约 3 倍于 PyTorch 的用户基础(从 GitHub 上引用每个框架的存储库来判断),这意味着更多的扩展、更多的教程和更多的开发人员合作探索堆栈溢出上所有可能的代码错误的空间。您还会发现,尽管从 TensorFlow 2.0 开始发生了重大变化,但项目开发人员已经采取了许多措施来确保可以保持向后兼容性。
什么是张量流?
TensorFlow 的核心是一个用于张量的数学操作、存储和转换的软件包,是矩阵概念的推广。TensorFlow 的主要效用和开发驱动力是机器学习,尤其是具有数百万参数的深度神经网络。TensorFlow 通常被用作 Python 的扩展,但所有那些允许 TF 在 GPU 和谷歌张量处理单元等硬件加速器上运行的底层组件都是用 C++和 CUDA 等编译语言编写的。TensorFlow 于 2015 年在 Apache 2.0 许可下发布,此后在研究、工业和教育社区中得到了广泛使用。它被大约 3 倍于下一个最受欢迎的框架的深度学习实践者使用,并被一些项目高度扩展,如用于以隐私为中心的联合学习的 TF-encrypted 或用于图像和音乐的深度学习增强艺术的 Magenta 。许多 AI 和 ML 从业者的大型用户社区和开源精神意味着有大量的材料可以学习和项目可以贡献。张量流计算是基于图形的,张量形式的数据以定向方式沿着连接边在计算节点之间流动。对于建立并行计算,图是一个合适的认知框架。它也非常适合分布式计算、编译器级别的优化,并提供了一个存在于编写它的编程语言之外的模型结构(因此是可移植的)。但是 TensorFlow pre-2.0 中采用的基于图和会话的方法要求开发人员首先定义一个静态图,然后建立一个会话来运行该图。这种方法导致更多重用的样板代码,避免使用普通的 Python 流控制,并且因为在 TensorFlow 会话中调用它们之前必须定义图形,所以它们在训练期间不太灵活。
张量流图 CC 由Tensorflow.org
TensorFlow 2.0 的主要变化
简化 TensorFlow 体验是 TensorFlow 2.0 的主要开发目标。他们通过减少冗余、完全的 keras 集成以及从静态图形到快速执行的重大转变实现了这一点。后一种变化使框架更加动态,并且可以说提高了代码的直观性和可读性。TF 2.0 已经完全接受 keras 作为高级应用程序编程接口(API)。这意味着不再直接使用 keras,而是由 TensorFlow 后端在后台完成所有繁重的工作,keras 的所有功能都可以从 tf.keras 下的 TensorFlow 中获得。尽管 keras 与 TensorFlow 的集成早在 2.0 之前就已经开始,但该团队已经投入了大量精力来整合冗余,并将所有内容归入 keras 旗下。特别是,您可能会发现自己正在使用 keras layers API。keras 的发明者 Francois Chollet 发布了一个 18 条 tweet 速成课程,并提供了代码支持,突出了 TF 2.0 中 layers API 所扮演的核心角色。以前,你可以在 TensorFlow 的几个不同角落找到略有不同的相同功能。
2.0 中的一个主要更新是合并了许多令人困惑的冗余,现在 keras API 中内置了许多功能。现在使用面向对象编程和优雅的 Python 流控制的概念要容易得多。总的来说,TF 2.0 承诺为研究级实验提供更高的灵活性,同时保留推动 TensorFlow 成为最广泛的深度学习框架的现实世界实用性和可部署性。虽然 TF 2.0 采用急切执行使实验和原型制作变得轻而易举,但开发人员可以通过用 tf.function 注释包装他们的代码来获得图形的所有好处。更重要的是,对于大多数用户来说,2.0 中的变化可能会导致更平滑的学习曲线和更可读的代码。
值得注意的项目
作为 TF 2.0 的一部分和深度学习的一个主要趋势,一个令人兴奋的发展是边缘计算:轻量级深度学习模型,旨在部署在低功耗分布式设备上,如手机、嵌入式微控制器和物联网(IoT)设备。TensorFlow Lite 是为边缘计算量身定制的,TF 开发者峰会在一款新的轻量级 TPU 支持的 Coral 开发板上演示了 edge ML。这是对像树莓派这样的设备的现有支持的补充。其他利用 TF 2.0 改进功能的有趣项目包括一个名为 DeepPavlov 的开源聊天机器人库,一个虫咬图像分类器,以及一个基于手机图像估计污染水平的空气质量预测应用。
警告
在撰写本文时,TensorFlow 2.0 仍然是预发布版本,因此伴随着一系列的错误和不断变化的功能,这些错误和功能会伴随任何处于早期开发阶段的项目。例如,在 TF 2.0 alpha 发布后不久,我开始了一个涉及灵活 cGAN 模型的新项目,升级到当前的 TF 2.0 beta 意味着由于 keras layers API 处理张量拼接的方式中的错误而导致的主要代码更改。任何基于 TF 2.0 的大型项目都有可能经历类似的修订,至少需要几周到几个月的时间,因为 2.0 已经准备好全面发布了。
如何开始使用 TensorFlow 2.0
TensorFlow 价值主张的一个重要组成部分是围绕开源项目构建的大型社区。这意味着有大量的教程、博客文章和成熟的项目可供选择。我建议你采用一个分三部分的方法来快速掌握 2.0。
- 通过阅读博客帖子(如这篇)和观看来自 TF Dev Summit 2019 的 TensorFlow 团队的一些演示,从高层次了解 TensorFlow 2.0 的主要变化以及这些变化如何影响您的项目。这是为了激发你的想象力,并有助于专注于特定的概念,这些概念将对你能构建的东西产生巨大的影响。
- 从像谷歌种子库这样的资源中研究大量的教程和代码示例,它们都附有代码,你可以在谷歌协作笔记本中修改和运行。这是习惯 TF 2.0 中更加动态和灵活的急切执行原则的好方法,我想你会同意结果比旧的基于图形和会话的开发流程更加 Pythonic 化。
- 你从 1 和 2 得到的印象应该给你足够的 2.0 的认知大纲,开始解决真正的问题。如果你对强化学习感兴趣,你可能会发现 TF-Agents 成为你下一个项目的有用权宜之计,而自然语言处理从业者可能会发现递归神经网络的改进后的新易用性很快变得不可或缺。
最后,如果您一直对构建 TensorFlow 专业知识并在项目中使用它持观望态度,2.0 标志着一个方便的边界,它对可用性和实用性进行了许多改进。另一方面,如果你是一个 TensorFlow 老手,你应该会发现你所知道和喜欢的所有功能仍然可以在其他领域进行无数的改进。许多新特性将在项目早期的快速迭代中提高您的效率,而不会牺牲后期的便利部署。
TensorFlow GPU 基准测试
- 面向 TensorFlow 的 RTX 2080 Ti 深度学习基准
- 面向 Tensorflow 的泰坦 RTX 深度学习基准
- 面向 TensorFlow 的 NVIDIA Quadro RTX 6000 GPU 性能指标评测
- Quadro RTX 8000 深度学习性能指标评测 TensorFlow
原载于 2019 年 8 月 13 日【https://blog.exxactcorp.com。
tensor flow 2.0——这是我在谷歌的人工智能日学到的东西
从研究、原型到生产
信不信由你,在新加坡有很多不同的聚会讨论数据科学和人工智能。
但我最喜欢的同学会依然是 TensorFlow 和深度学习新加坡 和 DataScience SG 。
当我意识到 TensorFlow 和深度学习新加坡将组织这个一天的会议—a . I . Day谈论和展示正在用于开发和创建真实世界人工智能产品的最新和最伟大的技术时…言语简直无法形容我有多激动!
看到人们谈论这些技术的出现是一回事,看到行业专家用行业的技巧和诀窍来分析这些产品是如何制造的是另一回事。
所有演讲者都是在该领域工作的第一手从业者,而不是营销和销售人员。
更令人兴奋的是,在新加坡,本次大会首次邀请了 4 位机器学习领域的谷歌开发者专家和 3 位来自谷歌大脑的演讲人——他们都在同一个平台上。
如果你是刚刚开始使用 TensorFlow 2.0 或一直在使用 tensor flow 2.0 的人,我相信你已经看过了 Paige Bailey 的一些视频,他目前是 TensorFlow core 和 Swift 的产品经理(他也是 TensorFlow core 的开发者倡导者)。
因此,能够在会议期间见到她本人,我激动不已!
这正是我喜欢成为数据科学和开源社区的一部分的原因——彼此分享,同时学习。
Upgrade your existing code for TensorFlow 2.0 by Paige Bailey
虽然我无法记下整个会议中每个主题的所有细节,但我设法记下了一些重要的知识和教训,我相信这些知识和教训会对你有所帮助。
在这篇文章结束时,我希望你能更多地了解 TensorFlow 2.0 提供的最新功能和其他最先进的模型在你的项目中的应用。
我们开始吧!
演讲者的主题从研究、原型到生产
A.I. Day 2019
在我开始之前,如果您想了解更多关于 TensorFlow 2.0 的信息,请随意查看这里的官方网站或我不久前写的文章,其中讨论了实现的新功能。
在接下来的章节中, 我将依次讲述每个主题以及我学到的简短经验/知识 :
- TF . keras 和 TensorFlow 2.0 介绍—Google Brain 的 Paige Bailey
- 对话式人工智能的图形深度学习 —红龙人工智能的山姆·维特芬
- TensorFlow Extended (TFX):生产中的真实世界机器学习——来自谷歌大脑的 Robert Crowe
- 我们应该展示哪张酒店照片?用于图像选择的神经线性强盗 —来自 Agoda 的 Sirinart Tangruamsub
- XLNet——最新的语言模型——红龙 AI 的马丁·安德鲁斯
- 用于 TensorFlow 的 Swift——谷歌大脑的 Paige Bailey
- TensorFlow Lite: On-Device ML 和模型优化工具包——来自 Light 的 Jason Zaman
每个主题都是相互独立的。所以请随意跳到你感兴趣的话题。
1。TF . keras和tensor flow 2.0简介
- Keras—tensor flow 2.0 最值得推荐的高级 API
- 如果在
model.compile()
方法中使用run_eagerly = True
,模型性能将会非常慢,因为该方法是静态运行的。model.compile()
默认是非急切情况下进行训练和推理 - 使用功能方法构建模型(使用高级 API 构建 DAG)
2。 对图形进行深度学习 用于对话式 AI
- 现在使用的图的例子包括社交图、推荐图等。
- 知识图表——Freebase、Wikidata、Cyc 和 DBpedia
- 构建图表的挑战—数据在欧几里得空间中没有很好地按顺序映射。很难捕捉图表中的所有相关节点来进行准确预测
- 如何解决这些挑战— 图卷积 。这种方法在图中移动,一次一个节点,以捕捉所有相关节点,并给出更准确的预测,特别是在对话式人工智能中
- 对图形的深度学习可能具有挑战性,目前仍在积极研究中
3。 TensorFlow 扩展 (TFX):生产中的真实世界机器学习
- TFX 是一个用于部署生产 ML 管道的端到端平台
- TFX 流水线是实现 ML 流水线的一系列组件,ML 流水线是专门为可扩展的高性能机器学习任务设计的
- TFX 的主要库包括张量流数据验证、张量流变换、张量流模型分析和张量流服务
- ML 开发部署面临的挑战 —数据生命周期管理、标记数据、特征空间覆盖、最小维度、最大预测数据、公平性、稀有条件。TFX 旨在应对这些挑战,尤其是在数据生命周期管理方面
- 位于 TFX 的元数据存储库 包含工件及其属性、组件的执行记录(运行)和数据来源(接受过哪些数据训练?)在所有执行中。
- 位于 TFX 的元数据存储在检查你的模型性能中扮演着重要的角色。例如,一年前您训练了一个模型,现在您有了一个新模型,并希望将其性能与以前的模型进行比较。您可以使用已经为之前的模型存储了元数据的 TFX,并使用 TensorBoard 可视化两个模型的性能
- Apache Beam 为运行批处理和流数据处理作业提供了一个框架,这些作业以分布式方式在各种执行引擎上运行
4。我们应该展示哪张酒店照片?用于图像选择的神经线性 Bandit
Hotel pictures shown on Agoda website
5。XLNet —最新的语言模型
- XLNet 是一种用于语言理解的广义自回归预训练方法
- XLNet 表明置换法作为语言模型目标是一个很好的选择
- 与 BERT 相比,XLNet 的关键增强包括最大限度地利用上下文进行预测、双流注意力和长记忆(如 TransformerXL )
6。用于 TensorFlow 的 swift
Swift for TensorFlow: The Next-Generation Machine Learning Framework (TF Dev Summit ‘19)
- Swift for TensorFlow 是用于深度学习和差异化编程的下一代平台
- 用于 TensorFlow 的 Swift 并没有牺牲作为强语言的性能(类似于 C++)。它是一种跨平台的语言——可以去 C++能去的任何地方
- 能够用于构建和训练新的模型,例如 AlphaGo 和英雄联盟
7。tensor flow Lite:On-Device ML 和模型优化工具包
- TensorFlow Lite 用于在移动和物联网设备上部署机器学习模型,用于设备上的推理
- 为什么要在设备上使用 ML?因为我们可以通过快速紧密的交互访问更多数据,同时还能保护隐私
- 在对精确度影响最小的情况下,优化片上 ML 模型的方法之一是通过量化
- 量化通过降低模型本身的值和运算的精度,能够减少模型的大小和推理所需的时间。这可能意味着模型尺寸缩小 4 倍,执行速度(CPU)提高 10–50%。
最后的想法
Wonderful Google office tour in Singapore
感谢您的阅读。
尽管 TensorFlow 2.0 仍在积极开发中,但您肯定可以开始使用它的功能来构建具有热切执行能力的模型。
我希望您了解了更多关于 TensorFlow 2.0 和其他最先进模型提供的最新特性,以便在您的项目中应用。
同时,如果您有兴趣了解 TensorFlow 2.0 的最新发展,您可以随时订阅邮件列表或在此加入社区!
一如既往,如果您有任何问题或意见,请随时在下面留下您的反馈,或者您可以随时通过 LinkedIn 联系我。在那之前,下一篇文章再见!😄
关于作者
Admond Lee 现在的使命是让每个人都能接触到数据科学。他正在帮助公司和数字营销机构通过创新的数据驱动方法,利用可操作的见解实现营销投资回报。
凭借其在高级社会分析和机器学习方面的专业知识,Admond 旨在弥合数字营销和数据科学之间的差距。
如果你想了解更多关于 Admond 的故事、数据科学服务以及他如何在营销领域帮助你,请查看他的 网站 。
你可以在 LinkedIn 、 Medium 、 Twitter 、脸书上和他联系。
让每个人都能接触到数据科学。Admond 正在通过先进的社交分析和机器学习,利用可操作的见解帮助公司和数字营销机构实现营销投资回报。
www.admondlee.com](https://www.admondlee.com/)
TensorFlow 控制流:tf.cond()
更深入地了解控制流操作在张量流中的工作方式
介绍
Tensorflow 是最受欢迎的深度学习框架之一,在推进深度学习方面发挥了关键作用。我使用 Tensorflow 已经两年多了,但是在使用控制流的过程中,我看到了许多奇怪和不可预测的行为。
最近(2019 年 4 月 19 日)看了一段 TensorFlow 团队自己内部培训的视频,很有帮助,让大家更清楚控制流 ops 是怎么工作的。我绝对推荐看这个视频。
视频详细介绍了 tf.cond()和 tf.while_loop。所以,我决定写这篇文章来详细说明 tf.cond()是如何工作的,并提供一些例子来说明。希望我会在后续的文章中介绍 tf.while_loop。
注:我打算在这篇帖子里涉及底层操作。还有其他类似功能性操作的操作,这超出了本文的范围。
切换并合并
在构建图的过程中使用的两个重要操作是切换和合并。因此,在本节中,我将介绍它们是如何工作的,并提供一些例子来熟悉它们的一些怪异行为!
Figure 1: Schematics of what are the inputs and outputs of Switch and Merge, and how they work.
如您所见,开关接收两个输入:数据和谓词,并提供两个输出:数据和死张量!。此外,Merge 接收两个(或两个以上)输入,并提供一个输出,即数据。我将在下面谈到更多的细节。
开关
首先,让我们考虑开关。如果您访问 Tensorflow 网站,您可以找到关于开关操作的定义和总结:
将
*data*
转发到由*pred*
决定的输出端口。如果*pred*
为真,则*data*
输入被转发给*output_true*
。否则,数据转到*output_false*
。
正如我之前提到的,Switch 接收两个输入。其中一个是谓词,是布尔张量(真或假),还有一个是要传递的数据。谓词决定数据应该通过 output_true 分支还是 output_false 分支传递。但是,这里有一个奇怪的东西是死张量的概念。不管谓词是真还是假;总是有两个输出:一个是数据,另一个是死张量。如果pred
为真,则死张量沿着output_false
发送(反之亦然)。
没有明确的参考资料解释为什么以及如何死张量是有用的,但似乎它们对分布式处理是有用的,它们的存在是一个实现细节。例如,你可以在这里找到的一个令人信服的答案:
首先,死张量是 TensorFlow 的控制流构造:
[*tf.cond()*](https://www.tensorflow.org/api_docs/python/tf/cond)
和[*tf.while_loop()*](https://www.tensorflow.org/api_docs/python/tf/while_loop)
的一个实现细节。这些构造使 TensorFlow 能够根据数据相关值确定是否执行子图。
让我们看一个例子,让事情更清楚。我从这篇帖子中获得了提供这个例子的灵感。
import tensorflow as tf
from tensorflow.python.ops import control_flow_opsx_0, x_1 = control_flow_ops.switch(tf.constant(1.0), False)
x_2, x_3 = control_flow_ops.switch(tf.constant(2.0), True)
print(x_0, x_1, x_2, x_3)
with tf.Session() as sess:
print(sess.run(x_0)) # prints 1.0
print(sess.run(x_3)) # prints 2.0'''
output:
Tensor("Switch:0", shape=(), dtype=float32) Tensor("Switch:1", shape=(), dtype=float32) Tensor("Switch_1:0", shape=(), dtype=float32) Tensor("Switch_1:1", shape=(), dtype=float32)
1.0
2.0
'''
因此,让我们深入了解一下这个示例中发生了什么。我创建了一个图来说明正在发生的事情。
Figure 2: Illustrating what is happening in the provided example.
我认为从图中可以清楚地看到发生了什么。如在x_0, x_1 = control_flow_ops.switch(tf.constant(1.0), False)
中,谓语是假的;因此,tf.constant(1.0)
被转发到output_false
分支,而死张量被转发到output_true
分支。
需要提及的一件重要事情是,我已经在 tf 内执行了x_0
和x_3
。Session(),它包含数据(张量)。如果我试图运行和执行死张量,我将面临一个错误。每当您试图在 Session.run()中执行和检索死张量时,都会导致错误。例如,以下代码引发了一个著名且经常发生的错误:
with tf.Session() as sess:
print(sess.run(x_1))'''
output:
**InvalidArgumentError**: Retval[0] does not have value
'''
现在,我认为这对于 Switch 来说已经足够了。让我们看看合并是如何操作的。
合并
Merge 是构造 tf.cond()图所需的另一个运算符。
Figure 3: Merge ops
Merge 可以接收多个输入,但其中只有一个必须包含数据,其他的应该是死张量。否则,我们将面临一些随机和不可预测的行为。让我们看看合并在最后一个例子中是如何工作的:
with tf.Session() as sess:
print(sess.run(control_flow_ops.merge([x_0, x_1])))
print(sess.run(control_flow_ops.merge([x_1, x_0])))
print(sess.run(control_flow_ops.merge([x_2, x_3])))
print(sess.run(control_flow_ops.merge([x_3, x_2])))
print(sess.run(control_flow_ops.merge([x_0, x_1, x_2])))'''
output:
Merge(output=1.0, value_index=0)
Merge(output=1.0, value_index=1)
Merge(output=2.0, value_index=1)
Merge(output=2.0, value_index=0)
Merge(output=1.0, value_index=0)
Merge(output=2.0, value_index=2)
'''
它的表现完全符合我们的预期。但是,当你把两个有数据的张量输入合并时,事情变得有点出乎意料和奇怪。
with tf.Session() as sess:
print(sess.run(control_flow_ops.merge([x_1, x_0, x_3])))
print(sess.run(control_flow_ops.merge([x_0, x_3])))
print(sess.run(control_flow_ops.merge([x_3, x_0])))'''
output:
Merge(output=1.0, value_index=1)
Merge(output=1.0, value_index=0)
Merge(output=2.0, value_index=0)
'''
有时,它返回x_0
的值,有时返回x_3
的值。所以,对这种行为要谨慎。
注意:死张量通过计算图形传播,直到它们到达合并运算。
tf.cond()
现在,我认为我们已经很好地掌握了交换和合并是如何操作的。现在正是深入 tf.cond()的好时机。我正在考虑一个简单的例子,其中输入参数是pred
、true_fn
和false_fn
。
tf.cond(pred, true_fn, false_fn)
我将考虑一个简单的例子来介绍这个概念。考虑以下情况:
tf.cond(x < y, lambda: tf.add(x, z), lambda: tf.square(y))
我已经为这个简单的例子构建了计算图,您可以在图 4 中找到它。
Figure 4: computational graph to show how tf.cond() works.
首先要提的是每个输入都有一个开关。我所说的输入是指 tf.cond()中 true 和 false 函数的参数。在本例中,有三个输入(x、y 和 z ),因此,计算图中有三个开关。
对于 true_fn,开关输出从 true 分支发出。对于 false_fn,开关输出从 false 分支发出。根据条件结果(无论 x 是否小于 y),谓词可以为真或假,其中一个分支(左或右)将被执行。值得注意的是,tf.add()
和tf.square()
操作都在开关之后。因此,在本例中,只有其中一个将被执行,另一个保持不变。
另外,我觉得这张图有点不对。我认为死张量通过加法或平方运算传播,直到它们遇到合并运算。合并运算去掉了死张量,只提供一个输出。
希望到目前为止,您已经了解了一些关于 tf.cond()的知识,并且对使用这个 API 已经变得更加得心应手。我将通过提供一个有争议的例子来结束这篇文章,并解释到目前为止我们所学到的东西是如何帮助我们理解内在工作的。在 TensorFlow 网站中,您可以找到以下声明:
警告:无论运行时选择哪个分支,在
*true_fn*
和*false_fn*
之外创建的任何张量或操作都将被执行。尽管这种行为与 TensorFlow 的数据流模型是一致的,但它经常让那些期待更懒惰的语义的用户感到惊讶。
因此,我将提供一个例子来阐明这个警告的含义。我提供了两个例子:在第一个例子中,所有的操作都定义在true_fn
和false_fn
中,在第二个例子中,一些操作定义在这个函数之外。我将构建并可视化计算图来解释为什么会出现这种行为。
例 1:
import tensorflow as tf
x = tf.constant(3.0)
y = tf.constant(2.0)def true_fn():
z = tf.multiply(x, y)
print_output = tf.Print(z, [z], "The value I want to print!!")
return tf.add(x, print_output)def false_fn():
return tf.square(y)result = tf.cond(x < y, true_fn, false_fn)with tf.Session() as sess:
print(sess.run(result))## output: 4.0'''
if you keep everything the same and just changing x to x = tf.constant(1.0), the predicate becomes true and the output will be as the following:3.0
The value I want to print!![2]
'''
这里需要重点关注的是,所有的张量和运算都是在函数内部创建的。因此,有三个输入参数,因此,图中有三个开关。为这种情况构建一个计算图将会很容易。
Figure 5: Computational graph for Example 1.
如果谓词为真(x 将小于 y),将执行true_fn
(左分支),右分支不执行,保持不变(反之亦然)。
注:我用过 tf。Print()函数,以便打印计算图形中的内容,并访问图形中张量的值。使用 tf。Print()有点复杂,我不打算在这里解释它是如何工作的。这里有一篇关于这个功能的优秀博文。
注:当谓词为假(x > y)时,执行false_fn
(右分支),结果是 tf。Print()只接收死张量,不打印任何东西。
例 2:
示例 1 有点无聊,结果完全符合我们的预期。在这个例子中,事情变得更加有趣。
x = tf.constant(3.0)
y = tf.constant(2.0)z = tf.multiply(x, y)
print_output = tf.Print(z, [z], "The value I want to print!!")def true_fn():
return tf.add(x, print_output)def false_fn():
return tf.square(y)result = tf.cond(x < y, true_fn, false_fn)with tf.Session() as sess:
print(sess.run(result))'''
output:
4.0
The value I want to print!![6]
'''
在这个例子中,谓词为假(x > y ),我们期望false_fn
执行而true_fn
保持不变。然而,我们可以看到输出包含“我想打印的值!![6]“属于哪一种true_fn
。起初,也许这种行为看起来有点怪异,但这与我们目前所看到和理解的完全一致。一些张量(z 和 print_output)已在函数外定义,因此,它们将被放在计算图中的开关之前。让我们用图表来说明这一点:
Figure 6: Computational graph for Example 2.
您可以在图 6 中看到,乘法和打印运算在开关之外(之前)。所以,不管谓词是真还是假,这两个操作在两种情况下都会被执行。
因此,通过理解切换和合并,并意识到 tf.cond()是如何工作的,希望您可以看到这种行为与 TensorFlow 的数据流模型是一致的,并且没有任何错误。
我将在这里完成这篇文章。谢谢你把帖子看完。请让我知道我是否犯了一个错误或有什么不对的地方。希望我会在后续的文章中介绍 tf.while_loop()。
参考
2019 TensorFlow 开发峰会总结
连续第二年,我有幸参加了 3 月 6 日—7 日在美国加州桑尼维尔的谷歌活动中心举行的 TensorFlow dev 峰会。去年,我对组织、场地、日程、演讲者印象深刻,我认为今年甚至更好。因此,再次祝贺 Google 和 TensorFlow 团队组织了如此令人惊叹的活动!
TensorFlow Dev Summit 仍然汇集了来自世界各地的机器学习用户的多样化组合;现在是两天而不是一天。第一天充满了技术讲座、演示、新产品发布和对框架的其他改进,而第二天侧重于闪电讲座,即参与者可以与 TensorFlow 团队成员一起编写代码的实践会议。
关于这次活动有很多有趣的事情要说,所以在这篇文章中,我将分享我的个人笔记,并简要总结一下最引起我注意的事情。
第 1 天-3 月 6 日
张量流 2.0
在 TensorFlow 2.0 中,重点是让 API 更简单、更自然。API 组件可以更好地与 Keras 集成,默认情况下,激活了 eager 模式。在 2.0 中,您可以使用您所知道的 Keras,用顺序 API 构建您的模型,然后使用 compile 和 fit。Keras 的 fit()将适用于许多情况;但是,如果需要,还有更多的选项可用。在最近的过去,你需要熟悉 tf.where, tf.select 以便写出条件,并且很难把复杂的控制流写成一个张量流图。有了 2.0,你可以简单地用 decorator @tf.function 把一个复杂的控制流写成 TensorFlow graph。 tf.function 只是要附加到 Python 函数的 decorator。TensorFlow 编译器自动解析对张量的依赖性,并创建适当的图形。这使得开发更容易理解和使用,因为我们现在可以像编写“标准”Python 代码一样编写张量流图的控制流。
a = tf.constant([1, 2])
b = tf.constant([3, 4])
print(a + b)
# returns: tf.Tensor([4 6], shape=(2,), dtype=int32)
这种魔力是通过重载一些方法实现的,例如像 if 或 while 。所以总的来说,你不需要再写了:
tf.session.run
tf.control_dependencies
tf.global_variables_initializer
tf.cond, tf.while_loop
除了 2.0,该团队还推出了 TensorFlow Datasets ,这是一组常用的 ML 数据集,以 tf.data.Datasets 或 NumPy 数组的形式准备和公开,以便在 TensorFlow 中轻松使用。此外,他们还提供转换和迁移工具,帮助从 1.x 代码过渡到 2.0。
TensorFlow Datasets & TensorFlow Probability
其他附件和扩展:
- TensorFlow 代理:强化学习库
- TF Federated:利用分散数据(即不同位置的数据)进行联合学习的库
- TF Privacy:一个带有工具的库,用于帮助训练具有不同隐私的模型
- Mesh TensorFlow:使用并行技术构建和训练大规模模型的库
- TensorFlow Probability:在我看来,TensorFlow Probability 可能是最令人兴奋的插件之一,它是一个在 ML 模型中使用概率方法进行预测的库,处理不确定性并结合领域知识。
这些以及更多关于 TensorFlow 的资源、示例、文档和案例研究可以从tensorflow.org网站获得。
[## Arnaud Zinflou 在 LinkedIn 上说:“来自#TFDevSummit 主题演讲的另一个非常有趣的小视频…
2019 年 3 月 7 日:阿诺德·津弗卢在 LinkedIn 上发帖
www.linkedin.com](https://www.linkedin.com/feed/update/urn:li:activity:6509288966850703360)
张量流扩展
我最喜欢的 TensorFlow 生态系统插件之一是 TensorFlow Extended (TFX)。TFX 为用户带来了整个机器学习生命周期的管理。它有几个组件库,包括:
- TensorFlow 数据可视化(TFDV)用于大规模监控和验证 ML 数据。
- 用于预处理任务(如标记化和格式转换)的张量流转换。
- TensorFlow 模型分析(TFMA ),使开发人员能够计算和可视化模型评估指标。
- TensorFlow Serving 用于服务 ML 模型,支持版本化和多模型支持
作为奖励,它现在集成了开源管弦乐队,如气流和 KubeFlow 。
TensorFlow Lite
去年推出的 TensorFlow Lite (TFLite)是一个用于设备上推理的轻量级解决方案。根据 Google 的说法,TFLite 现在运行在超过 20 亿台移动设备上,引领了下一代移动设备上的 ML。出于以下原因,需要在边缘设备中运行 ML:
- 快速交互应用程序(通过在客户端运行 ML 应用程序,我们可以消除在服务器和客户端之间发送数据的开销)
- 数据隐私(通过避免向服务器发送数据)
对 TensorFlow Lite 的一般可用性、模型转换功能和性能进行了一些改进。例如,通过将处理委托给边缘 TPU,结合量化,他们实现了 62 倍的最快推断时间。他们还推出了 Coral Dev Board,这是一款带有可移动模块上系统的单板计算机,具有 Edge TPU 和 Coral USB Accelerator,这是一款 USB 加密狗,旨在加速现有 Raspberry Pi 和 Linux 系统上的机器学习推理。此外,他们还推出了 Sparkfun。 Sparkfun 是一款由 TensorFlow 驱动的 edge 演示板。根据所提供的信息,Sparkfun 可以激活搅拌机或热水器,或者在听到某个单词时做任何你的微控制器可以做的事情,只需要一个硬币电池作为电源;有趣不是吗?更有趣的是,我们收到了 Sparkfun 板和 coral USB 加速器作为参加会议的礼物。
TFDevSummit goodies
这种礼物总是很有趣,因为我们可以尝试使用我们所学到的东西。所以这些我以后都要试试:)。
The SparkFun Edge board
TensorFlow.js 1.0
Javascript 是使用最多的编程语言之一,TensorFlow。Js 给 JavaScript 开发者带来了 ML。在会议期间,他们宣布发布 TensorFlow.Js。除了核心组件,围绕 TensorFlow.js 还有多个支持库。
实际上,TensorFlow.js 项目将支持各种平台,如 Electron 和 React Native,以便我们可以在许多平台上使用相同的应用程序代码。AirBnb 和优步等公司正在生产环境中使用 TensorFlow.js。
面向 TensorFlow 的 Swift
这可能是我去年最喜欢的发布之一,Swift for TensorFlow 随着 0.2 版本的发布而发展。这是一个渐进的改进。在 0.2 中,用户可以看到增加的可用性,并尝试这种新颖的 ML 范例。此外,他们还通过 fast.ai 推出了使用 Swift for TensorFlow 的新机器学习课程,让 Swift 更容易上手 ML。
在比率中
该项目正在开发一个基于 TensorFlow 的机器转录系统,以加快梵蒂冈历史档案中的大规模搜索和知识发现。经过众包注释训练的定制 CNN 使该系统能够处理具有挑战性的中世纪笔迹。
关于 TensorFlow 和 TensorFlow world 的新课程
分别与 Udacity 和 Coursera 合作的两个新的在线课程可用于学习 TensorFlow。
最后,新发布会 TensorFlow World 将于 2019 年 10 月 28 日-31 日举行。与 O'Reilly 合作举办的 TensorFlow 世界大会将召集工程师、开发人员、高管和产品经理,讨论他们由 TensorFlow 支持的产品/服务。
第二天-3 月 7 日
第二天专门进行灯光讲座、小组讨论和研讨会,例如:
- ML 的可视化调试工具
- 网易
- 蝴蝶:民主化的超声波
- PAI:阿里巴巴的人工智能平台
PAI presentation
- TensorFlow.jl:现在在 Julia 编程语言中支持 TensorFlow
Julia and Python syntax side by side
- TF-lattice:一个帮助开发人员确保他们的机器学习模型即使在训练数据有噪声的情况下也能坚持全球趋势的项目
TF-lattice
- TF.text:改进 TensorFlow 中的文本,改进 TensorFlow 中的 unicode 支持
- TF.js 在创意实验室的使用
我还参加了 Tensorflow 2.0 升级的小组讨论。
TensorFlow Extended (TFX)车间
TFX 研讨会旨在提供 TensorFlow Extended (TFX)的实践经验,并帮助学习创建我们自己的机器学习管道。在研讨会期间,参与者遵循典型的 ML 开发过程,从检查数据集开始,以完整的工作管道结束。这也是一个探索不同方法来调试和更新我们的管道并衡量绩效的机会。
TFX workshop screenshot
最终想法
总的来说,2019 TF Dev 峰会很不错,一堆信息和公告。与去年相比有许多改进;例如,增加第二天和研讨会。如果您使用 TensorFlow,并且希望结识在现实生活用例中也使用 TF 的同行,我肯定认为这个事件是必须考虑的。
参考资料和进一步阅读:
- TensorFlow 网站
- 张量流开发峰会
- 回顾 2019 年发展峰会 t
- SparkFun 网站
- 推出 SparkFun Edge
- 介绍 TensorFlow 数据集
- 珊瑚与谷歌
- 向谷歌珊瑚问好
- TensorFlow YouTube 频道
让我们谈谈数据流
Photo by @eberhardgross
TensorFlow 走 2.0,但什么是数据流?
谷歌的研究和生产使用 TensorFlow。或许正是因为这个原因,作为使用机器学习的最大的技术公司之一,理解 TensorFlow 是什么并对其新的更新有一点兴趣是明智的。它是一个应用程序编程接口。应用程序接口(API)是一组用于构建软件应用程序的例程、协议和工具。如果你已经熟悉 TensorFlow 是什么,或者只是想查看新的更新,那么这篇文章可能不适合你——请直接在 Medium 上查看 tensor flow的新文章。在我的文章中,我将尝试解释和探索数据流,它是张量流中的一个核心概念。
什么是张量流?
tensor flow是一个免费的开源软件库,用于数据流和跨一系列任务的差异化编程。**
在这个简短的第一句话中,我们听到了两个可能令人困惑或需要澄清的概念。
- 数据流
- 可微编程
在这篇文章中,我将集中讨论第一个概念。
数据流或数据流编程
数据流编程将程序建模为操作间数据流动的有向图,从而实现数据流原则数据流原则和架构。
在数学中,有向图(或有向图)是由一组由边连接的顶点组成的图,其中边有一个与之相关的方向。
Retrieved 6th of October 2019 from Wikipedia on Directed graph
Flawnson Tong 在他的文章中把一个图解释为:*图 ,在图论的上下文中,是一个结构化的数据类型,它具有 节点 (保存信息的实体)和 边 *(可以深度学习是一种机器学习算法,而机器学习算法又是人工智能的一个子集。**
**********
Data is not this neat of course, gif by Matthew Butler
有些人使用术语“数据流”而不是“数据流”,这是因为可能与先前基于不确定性机器范例的“数据流架构”概念相混淆。非决定论是一种认为事件不是由或不是由决定论引起的观点。它与决定论相反,与偶然性有关。因此,这是某种加权的可能性,即某事应该发生或不发生,以及影响结果的变化的偏差(输入)。
Iillustration by Google on the Cloud Dataflow page retrieved the 6th of October
Dataflow pipeline by Sameer Abhyankar posted in Google Cloud Platform on Medium
数据流原则——基于数据流的进度表示。一篇名为 调度表示之间的等价:理论与应用 的论文是这样说的:“调度通常被表示为一组作业到一组处理器的映射;这种映射随着时间而变化。”因此,它可以被描述为一个优化问题或不同的最优或次优(不太)理想解决方案的“映射”。
An overview of data transformation with [Google Cloud](http://Data Transformation with Cloud Dataflow)
维基百科对数据流编程的描述非常有趣,所以我决定直接引用它:
“顺序程序可以被想象成在任务(操作)之间移动的单个工人,而数据流程序更像是装配线上的一系列工人,只要有材料,每个人都在做特定的任务。因为操作只关心数据输入的可用性,所以它们没有要跟踪的隐藏状态,并且同时都“就绪”
数据流编程语言共享一些函数式的特征,并且通常被开发来将一些函数式概念引入到更适合数字处理的语言中。在函数式编程中,程序被视为一系列无状态的函数求值。
照这样!
TensorFlow :基于数据流编程的机器学习库。
然而,它同时还是一个符号数学库,也用于机器学习应用,如神经网络。它是一个应用程序编程接口。应用程序接口(API)是一组用于构建软件应用程序的例程、协议和工具。
希望这能让你稍微开心一点,当然,这可能会引出更多的问题,而不是答案。
Hope this made you happy! — Gif made by @sherchle
张量流 2.0
谷歌希望扩大机器学习的规模,并发布了 TensorFlow2.0。它被描述为企业和研究人员易于使用的框架。它面向可扩展的 ML 支持的应用,将 Keras 紧密集成到 TensorFlow 中。
Keras是一个用 Python 编写的开源神经网络库。它能够运行在 TensorFlow、微软认知工具包、Theano 或 PlaidML 之上。旨在实现深度神经网络的快速实验,它专注于用户友好、模块化和可扩展。
因此,TensorFlow 2.0 优先考虑 Python 开发者(一种编程语言)。它有更完整的底层 API。低级接口。最详细的编程接口(API ),允许程序员在非常精细的级别上操作软件模块或硬件中的功能。粒度数据是详细的数据,或者是目标集中数据的最低级别。从哲学意义上来说,粒度计算可以描述一种思维方式,这种思维方式依赖于人类在不同粒度级别(即抽象)下感知真实世界的能力,以便只抽象和考虑那些服务于特定兴趣的事物,并在不同粒度之间切换。”
新的 2.0 保存了具有各种运行时的模型(部署到 web 和云)。运行时是指程序正在运行(或可执行)的时候。也就是说,当你启动一个在计算机上运行的程序时,它就是那个程序的运行时。它可以在浏览器中运行,并有多 GPU 支持。多 GPU。(多图形处理单元)使用两个或更多图形卡来支持更快的运行时间。
除此之外,还有扩展的 TensorFlow 数据集(标准化)。推荐执行急切的常规 Python。我以前写过关于急切执行的文章。 急切执行 是一种推测执行的形式,其中条件分支的两端都被执行;然而,只有当谓词为真时,才提交结果。
这是#500daysofAI 的第 125 天。如果你喜欢这篇文章,请给我一个答复,因为我确实想提高我的写作或发现新的研究,公司和项目。
Tensorflow GPU 安装变得简单:Ubuntu 版本
在 ubuntu 上安装 Tensorflow GPU 对于正确版本的 cuda 和 cudnn 来说是一个挑战。一年前,我写了一篇文章,讨论了用 conda 安装 Tensorflow GPU,而不是用单行命令安装 pip。这是那篇文章的链接。
[## Tensorflow GPU 安装变得简单:使用 conda 而不是 pip
我有一个配置不错的 GPU,以前玩 FIFA 都是用它。转行 AI,本来想用 GPU 做深度学习的…
towardsdatascience.com](/tensorflow-gpu-installation-made-easy-use-conda-instead-of-pip-52e5249374bc)
这篇文章已经被阅读了超过 25 万次,但仍然有一些 Ubuntu 用户在使用正确版本的 CUDA 和 CUDNN 运行 Tensorflow GPU 时面临问题。我知道这篇文章的标题可能会误导人,但是相信我,如果你一步一步的去做,那么在 ubuntu 上正确的安装是很容易的。
目录:
- 检查 GPU 与 Tensorflow GPU 的兼容性!
- 切换到图形卡
- 检查 CUDA 与图形卡的兼容性
- 根据 CUDA 确定 Tensorflow 版本
- 下载 CUDA 工具包
- 安装 CUDA
- 下载 cudnn 并安装
- 验证 cudnn 安装
- 在使用 Conda 的新环境中使用 pip 安装 Tensorflow-gpu
- 验证 tensorflow 正在使用 GPU。
注意-你可以使用这篇文章安装任何版本的 TENSORFLOW,确保你正确的决定了 CUDA 的版本。
- 检查 GPU 与 Tensorflow GPU 的兼容性(从到此处
- 打开显卡
进入菜单>搜索“驱动程序设置”>点击附加驱动程序
选择 NVIDIA 二进制驱动程序,在我的例子中是 384 版本的**。这是非常重要的记录下来,因为这个驱动程序版本将有助于我们确定 CUDA 版本。**
现在,如果你去一个终端,键入 nvidia-smi,你也会得到驱动程序版本。
3.从这里检查 CUDA 与您的驱动程序版本的兼容性。
在我们的例子中,因为驱动程序版本是 384.130,所以我们只能安装 CUDA 9.0
4.根据 CUDA 确定 Tensorflow 版本
完成这一步后,你应该对 3 件事非常清楚:
i)你要安装什么 Tensorflow 版本(tensorflow-gpu 1.12.0)
ii)你要安装什么 CUDA 版本(9.0)
iii)你要安装什么 cudnn 版本。(7)
注意:这些问题的答案会因您当前使用的驱动程序版本而异。
如果你知道这三个问题的答案,那么你已经闻到胜利的味道了。
5.下载 CUDA 工具包
转到此链接并下载您在步骤 4 中找到的 CUDA 的具体版本(本例中为 CUDA 9.0)
6.CUDA 安装
Execute the run file downloaded
你将获得软件许可证,长按回车键。现在接受除驱动程序安装之外的所有内容。
安装后,您将收到以下消息:
现在你必须在 bashrc 文件中输入特定的路径,这样你才能访问 cuda。打开终端并运行命令
sudo su
sudo gedit ~/。bashrc(在文件末尾添加以下行)
export PATH=/usr/local/cuda/bin:/usr/lib/:$PATH
export LD_LIBRARY_PATH=/usr/local/cuda/lib64:/usr/lib/nvidia-384:$LD_LIBRARY_PATH
export CUDA_HOME=/usr/local/cuda-9.0
保存并关闭文件,然后将 bashrc 文件作为源,以使更改生效。
来源~/。bashrc
现在打开一个终端并编写命令
nvcc -V
您将获得运行的 CUDA 版本。
6.验证 CUDA 安装(可选):如果你对 nvcc 版本满意,那么你可以跳过这一步。
打开终端并运行以下命令:
cd /usr/local/cuda/samples/1_Utilities/deviceQuery
sudo make
./deviceQuery
7.下载与 CUDA 兼容的 cudnn 并安装
进入链接并安装 cudnn。记住在这里下载 cudnn 的版本,它与 CUDA 兼容,在这里是 7。你需要注册 NVIDIA 网站来下载这个。
Download all the three files.
按照以下顺序安装 cudnn 包:运行时>开发人员>文档。使用命令
sudo dpkg -i<package_name></package_name>
8.验证 cudnn 安装
为了验证我们的 cudnn 安装,我们将测试一个 cudnn 样本。打开终端并发出以下命令:
cp -r /usr/src/cudnn_samples_v7/ $HOME
cd $HOME/cudnn_samples_v7/mnistCUDNN
make clean && make
./mnistCUDNN
如果 cudnn 安装正确,您将会看到这样的消息:测试通过
9.下载 Miniconda 并安装。记得不要 root 安装。
现在创建一个安装 tensorflow-gpu 的环境。
conda create --name tf1 python=3.6
执行此命令后,将使用 python 版安装一个名为 tf1 的新环境。现在激活环境并执行命令来安装我们在步骤 4 中找到的特定版本的 tensorflow-gpu。
source activate tf1
pip install tensorflow-gpu==1.12
10.要测试 tensorflow 安装,请遵循以下步骤:
- 打开终端,使用*‘源激活 tf1’激活环境。*
- 使用python进入 python 控制台
import tensorflow as tfsess = tf.Session(config=tf.ConfigProto(log_device_placement=True))
现在,如果您能够在终端中看到您的 GPU 信息,那么恭喜您,您终于成功了!
谢谢你的时间。请通过 LinkedIn 与我联系,了解更多关于数据科学的更新和文章。
使用无服务器架构的 TensorFlow 图像识别教程—节点 JS
使用 TensorFlow JS + Serverless 的分步教程
基于卷积神经网络(CNN)的架构,如 VGG-16、GoogLeNet、ResNet、MobileNet 等。是广泛用于图像识别、从图像和视频中检测物体的模型。更多关于卷积神经网络的细节,请参考我比较老的博客。
在这篇博客中,我将使用无服务器架构和 CNN 的 MobileNet 模型来解释图像识别教程。MobileNet 架构是一种适用于移动和嵌入式设备的轻量级模型。MobileNet 模型已经训练了超过 1400 万幅图像和 20,000 个图像分类。使用预先训练的模型,该模型有助于快速分类输入图像并产生结果。
无服务器架构——tensor flow 后端
在无服务器云函数中使用 MobileNet 模型的图像识别过程。因为 MobileNet 是轻量级架构,可以在云功能中运行。在这个架构中,我们将使用 Node JS 作为客户端接口和后端 REST 服务(无服务器)。
Figure 1: Serverless Architecture with TensorFlow MobileNet model — Node JS
上图描述了一个两层架构。
- API 客户端接口
- 使用 TensorFlow 作为后端的图像处理组件
TensorFlow 框架,具有 MobileNet 模型 API 包装器实现和使用节点 JS 堆栈的 API 客户端接口。
申请流程
- 用户将使用客户端界面上传图像。客户端接口将图像转换为 base 64 数据,并将数据发布到后端 REST API 中
- 在 AWS Lambda 中开发和部署的后端 REST API。在本教程中,我们使用 AWS Lambda 。
- 无服务器框架帮助我们使用 YAML + CLI 部署将基于节点 JS 的 REST API 部署到任何云功能,如 AWS、Azure、Google Cloud &等。
- 后端 REST API 模块使用 TensorFlow 深度学习模块分析图像并预测图像
- JSON 数据的结果将被发送到客户端接口。客户端界面在浏览器中呈现输出结果。
API 客户端界面—流程
Figure 2: Client UI — Landing Page. Currently, our tutorial supports — Image Analyse Techniques module
Figure 3: Image Analyse Client Interface — UI
- API 客户端界面帮助将图像上传到 API 服务器
- 当图像上传到 API 服务器时,它会转换成 base64 编码的字符串,并调用 TensorFlow 无服务器云函数(这里是 AWS Lambda)
- 基于 TensorFlow 的应用程序使用 Node JS 开发,部署在 AWS Lambda 中。
图像处理实用程序—输出
下面是几个输出。
Figure 4: Image Analyse Output
Figure 5: Image Analyse Output
现在,让我们一层一层、一步一步地看代码。
TensorFlow REST API —在无服务器环境中运行
首先,我们将导入 TensorFlow 节点 js 模块。细节在下面的片段中提到。
注意:-使用 Node JS 开发的后端 REST 和客户端接口的源代码都可以在我的 Github repo 中找到。请参考底部的 Github 链接。
下面的代码片段是主节点 js 函数,它作为 REST 端点导出。
第 6 行 :事件参数,包含一个体属性“event.body”从客户端接口获取图像 base 64 数据,用户上传
第 8 行: 它获取 base 64 图像数据,并作为图像写入临时路径(对于每个请求,将创建一个新的文件名。参考,第 5 行)
第 9 行: 它调用另一个名为“classify”的函数 by,传递前面创建的参数路径。path 变量包含新的图像文件路径。分类函数的细节可以在下面的代码片段中找到。输出变量结果以异步模式接收响应,该响应包含张量流图像预测结果以及概率得分。输出详情请参考上图 4 & 5。
第 5 行 :从路径中读取图像
第 6 行 :从给定图像转换三维数组
第 7 行 :加载 MobileNet 模型
第 8 行 :将输入图像的 3d 数组矩阵作为参数,对图像进行分类,得到预测的图像结果。
从 URL 加载移动网络模型
客户端界面—UI
第 7 行: 它将输入图像作为 base 64 数据提交,并将其发布到后端 REST 服务端点。变量“apiURL”从 config.json 加载 REST URL。
后端 API 部署
- 首先,我们必须部署后端服务。后端服务是一个 REST API,它使用 TensorFlow 处理图像输入并对图像进行分类/预测
- API 是用 Node JS 开发的
- 使用无服务器框架,我们将把我们的 API 部署到无服务器环境中。在本教程中,我们使用 AWS Lambda 作为无服务器环境。
步骤 1 :在你的机器上下载并安装/更新无服务器框架。请参考此无服务器文档链接获取安装帮助—【https://serverless.com/framework/docs/getting-started/
安装完成后,键入"*SLS-help "*应该会得到如下图所示的输出
Figure 6: Serverless command to test “sls — — help”
步骤 2 :下载您的 AWS 凭证(访问&密钥)并在您的操作系统中设置为环境变量,如果您使用的是 Linux 或 Mac 操作系统,则使用“export”命令,如果您的操作系统是 windows,则使用“set”命令
导出 AWS_ACCESS_KEY_ID= < <您的 AWS 访问密钥> >
导出 AWS_SECRET_ACCESS_KEY= <
>
第三步:从 Github URL 克隆源代码
git 克隆 git @ github . com:RaghavPrabhu/Deep-learning . git
成功克隆后,转到文件夹server less _ image _ tensor flow/back end _ API
第四步:在 backend_api 文件夹中执行下述命令
npm 安装
上述命令将通过读取 package.json 文件来安装所有节点模块。注意:——你也可以通过“yarn”命令来安装节点模块
步骤 5 :使用无服务器命令将我们的后端 API 部署到 AWS Lambda
sls 部署
上面的命令将在 AWS Lambda 中部署 API。请参考下面的截图了解更多细节。
Figure 7: Deploy backend API on AWS Lambda using Serverless command to test “sls deploy”
注意:请确保您已经在您的环境中设置了 AWS 访问和密钥。参见步骤 2。
成功部署后,在 AWS 中验证您的 Lambda 函数细节。
Figure 8: AWS Lambda Function Deployment Details
前端 UI 部署
第一步:转到“前端 _ 客户端”文件夹
第二步:在 backend_api 文件夹中执行下述命令
npm 安装
第四步:打开 config/default.json 文件,更新 API URL。参考下面的截图。注意:这一步很重要!!!
Figure 9: Config file update in default.json file
步骤 3 :运行以下命令启动客户端界面
node server.js
万岁!!!已经部署好了。
转到浏览器,键入“http://localhost”并测试。您应该会看到类似于图 2 中的屏幕。
你可以在我的 Github URL 中找到后端 API 和前端 UI 的源代码。
总结
- 使用 node js + TensorFlow js 库构建 Tensorflow 图像检测 API
- 使用无服务器框架将 API 部署到无服务器环境中
- 使用节点 js 构建客户端接口,并在 config/default.json 文件中配置 API 端点
- 使用客户端 UI 上传图像并测试图像类型
- 本教程使用无服务器框架在 AWS Lambda 中进行了测试。随意将 API 部署到其他云功能中,如 Azure cloud function、Google cloud function、IBM openwhisk、Kubeless 等。,通过利用无服务器框架的特性。
- 这个教程代码可以在这里找到。
TensorFlow 与 Keras 有关系—推出 TF 2.0
今年早些时候,oogle 的 TensorFlow 团队宣布了其最新且相当易用的版本。对于使用过 TensorFlow 1。XX,这个版本没那么丑,没那么毛骨悚然,更人性化(技术更新和改动在下面讨论)。我将写一个 3 部分的系列,这是一个开始,也是最短的一个。这些部分主题如下:
- TF 2.0 简介
- TensorFlow 2.0 中的图像分类
- TensorFlow 2.0 中的迁移学习
TensorFlow 和 Keras 是什么?
维基百科 提出 TensorFlow 是一个免费的开源软件库,用于数据流和跨一系列任务的差异化编程。从人类的角度来说,TensorFlow 是一个大规模构建机器学习模型的开源库。它是迄今为止最受欢迎的构建深度学习模型的库。它还拥有最强大的庞大的开发人员、研究人员和贡献者社区。
Keras 是一个高级神经网络 API,用 Python 编写,能够运行在 Tensorflow、Theano 或 CNTK 之上。它在研究和开发社区中非常受欢迎,因为它支持快速实验、原型和用户友好的 API。用户友好的代价是无法访问 TensorFlow 的内部细节,但合理数量的复杂事情仍然可以完成。
Tensorflow 2.0 中的新增功能
Tensorflow 致力于为正在进行的任何计算构建计算图;从增加两个数到建立一个生成性的对抗网络。一旦构建了图形,它就在所谓的**会话中执行。**对于初学者来说,这可能听起来像是一剂重药(现在你可能明白为什么 TensorFlow 1 有点难看了),这就是为什么很难,尤其是对于初学者来说,直接跳到 TensorFlow 来实现神经网络。
随着 TensorFlow 2 的出现,事情变得非常整洁、灵活,任何人都可以通过实验轻松进入深度学习领域。Tensorflow 2 实现了 Keras 和直观的高级 API tf.keras 的紧密集成,以构建神经网络和其他 ML 模型。您可以获得 Keras 的用户友好性,也可以从访问 TensorFlow 的所有低级课程中受益。这是一个完美的组合,适合不同行业和专业知识的人使用;因此,一个完美的爱情故事 TensorFlow 和 Keras。
根据 Tensorflow 2 新功能的官方评论,这些新功能可以归纳为三大类:
1)可用性
- 随着 Keras 的集成,可用性变得非常强大。在深度学习方面具有不同专业水平的人可以使用 TensorFlow now 进行工作;这在很大程度上增加了可用性。
- 最大的变化之一是默认的急切执行模式。简单地说,您不需要构建图形,然后在会话中执行它们来运行基本的乘法运算。你可以简单地在飞行中建立深层网络。这对为神经网络编写代码的开发人员隐藏了很多复杂性。然而,这并没有剥夺你使用该图的好处,因此这些可以通过 tf.function. 访问
2)清晰度
- 重复的功能已被删除。为了消除这些问题,在实际代码库中做了大量的清理工作。
- 语法更加直观(多亏了 Keras ),并且始终一致。
3)灵活性
- 如前所述,您仍然可以为不同种类的定制任务使用低级 API。
- 它还为变量、层和检查点提供了可继承的接口。
TensorFlow 2 的架构如下所示。
Tensorflow 2 Architecture
接下来会发生什么?
TensorFlow 中有更多的更新和新功能,我们将在本系列的未来博客中探索它们。在下一篇博客中,我们将讨论如何在 Tensorflow 2 中借助卷积神经网络构建图像分类器来启动计算机视觉。你可以看看我之前关于计算机视觉入门的博客,对计算机视觉有个了解。这将有助于你理解大局,也肯定有助于应对下一个博客。《Keras》的作者 Francois Chollet 最近出版了一本笔记本,作为 Tensorflow 2 的速成课程。要彻底研究 tensorflow 2,你可以查看 Coursera 和 Udacity 上提供的两个有趣的专业。
有关 TensorFlow 2 的更多更新,请访问https://www.tensorflow.org/
您也可以在我的 LinkedIn 上联系我进行任何讨论。
张量流。JS —使用 JavaScript Web Worker 运行 ML 预测函数
这篇文章是关于客户端的机器学习。我将解释如何在 JavaScript Web Worker 中运行 ML 模型。该模型在 TensorFlow/Keras(使用 Python)中训练,以检测酒店评论的情绪。
Source: Pixabay
我是 JavaScript 开发人员,当机器学习模型在客户端(在浏览器中)运行时,我感觉棒极了。如果你决定在浏览器中运行 ML 模型,我将在这篇文章中讨论几个主题,我相信你会发现它们很有用:
- 如何用 Python 训练 ML 模型
- ML 模型如何转换为与 TensorFlow.js 兼容
- 运行 TensorFlow.js 预测函数的 JavaScript Web Worker
我在用 ML 模型为一篇酒店评论预测情绪。我在 Kaggle 上发现了这个优秀的数据集— 欧洲 515K 酒店点评数据。它提供了来自 Booking.com的 51.5 万条酒店评论记录。使用这个数据集,我训练了 Keras 模型,将其转换为与 TensorFlow.js 兼容,然后包含到客户端 js 应用程序中。你可以亲自检查它是如何工作的,这个应用程序部署在 Heroku—【https://sentiment-tfjs-node.herokuapp.com/ :
JS app with TensorFlow.js
试着输入Bed comfort,你会得到非常低的否定分数:
JS app with TensorFlow.js
然后加上— V 外面很吵,负面评分会增加到中性情绪:
JS app with TensorFlow.js
如何用 Python 训练 ML 模型
使用 Zaid Alyafeai 帖子中解释的方法实现文本情感分类——从 Keras 到浏览器的情感分类。关于如何建立文本情感分类我就不深入解释了,你可以在 Zaid post 里看。
为了能够训练模型,我处理了酒店评论数据集,并从所有属性中提取了酒店评论文本和情感(0-正面,1-负面)。我使用数据子集来训练模型,以减少训练时间。我使用了前 10 万条评论:
df = pd.read_csv('hotel-reviews.csv', nrows=100000)
df['REVIEW_TEXT'] = df['REVIEW_TEXT'].astype(str)
print('Number of rows ', df.shape[0])
使用批量= 128(批量越大,训练越快),在 5 个时期中训练该模型。验证集被分配了 20%的训练数据:
model.fit(np.array(X_train_tokens), np.array(Y_train),
validation_split=0.2, epochs=5, batch_size=128)
模型训练成功,验证准确率高达 94%;
Model training results
当模型被训练时,还有两件事要做。创建一个字典文件,它将用于编码用户语句,以供客户端预测功能处理。使用优化器保存模型,以便能够将其转换为 TensorFlow.js 友好表示。
确保在保存模型时,训练过程只进行了一次(在保存之前,您没有多次运行训练,或者关闭 Python notebook 并从头开始进行新的训练),否则保存的文件中的模型会过载,并且 TensorFlow.js 无法重用模型。
ML 模型如何转换为与 TensorFlow.js 兼容
保存模型后,将其转换为 TensorFlow.js 格式,这样将创建两个新文件(模型 bin 文件和包含元数据的 JSON 文件):
tensorflowjs_converter --input_format keras hotel-reviews-model.h5 tensorflowjs/
在此阅读更多信息— 将 Keras 模型导入 TensorFlow.js 了解如何将现有 Keras 模型转换为 TensorFlow.js,然后将其加载到 TensorFlow.js
JavaScript Web Worker 运行 TensorFlow.js 预测函数
TensorFlow.js predict 函数调用为什么需要使用 Web Worker?预测函数调用不是异步的,这意味着它阻塞主 JavaScript 线程,用户屏幕将被冻结,直到预测完成。情感分析预测需要几秒钟的时间,用户界面冻结会让用户烦恼。Web Worker 允许将长时间运行的任务委托给单独的 JavaScript 线程,而不会阻塞主线程。
JavaScript 应用基于 Oracle JET toolkit(开源库集合— knockout.js、require.js 等。).要在您的计算机上运行示例应用程序,请执行以下命令:
- npm install -g @oracle/ojet-cli
- 从应用程序根文件夹运行:ojet 恢复
- 从应用程序根文件夹运行:ojet serve
appController.js 中有一个函数,每次当用户停止输入文本时都会被调用——调用预测情绪。此函数创建 Web Worker(如果不存在)并将用户输入发送到 Web Worker(输入被编码并准备好用于张量创建):
if (!worker) {
worker = new Worker("js/worker.js");
}worker.postMessage(seq);
worker.onmessage = function (event) {
console.log('prediction: ' + event.data);
self.negativityScore(event.data);
self.sentiment(convertToSentiment(event.data));
};
事件侦听器被注册来处理返回消息(预测)—它通过剔除可观察变量被推送到 UI。
Web Worker 在 worker.js 文件中实现。这个文件在它自己的上下文中运行,您应该在这里隐式引用 TensorFlow.js 库。确保设置 CPU 后端,Web Worker 中的 TensorFlow.js 仅适用于 CPU 后端:
importScripts('https://cdn.jsdelivr.net/npm/setimmediate@1.0.5/setImmediate.min.js');importScripts('https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@1.2.7/dist/tf.min.js');tf.setBackend('cpu');
这是主代码(Web Worker 中的消息监听器)—调用 TensorFlow.js predict 函数(将用户输入转换为张量)的地方,结果通过消息返回到主线程:
onmessage = async function (event) {
console.log('executing worker');
seq = event.data;
if (!model) {
model = await createModel();
}
input = tf.tensor(seq);
input = input.expandDims(0);
predictOut = model.predict(input);
score = predictOut.dataSync()[0];
postMessage(score);
predictOut.dispose();
};async function createModel() {
const model = await tf.loadLayersModel('ml/model.json')
return model
}
资源:
- 源代码— GitHub
- 示例应用程序 live—https://sentiment-tfjs-node.herokuapp.com/
TensorFlow,认识一下 ESP32
如何为 ESP32 设置 TensorFlow Lite 环境
如果我必须选择一个最喜欢的计算领域,我会选择嵌入式系统。我喜欢在资源受限的环境中优化代码所带来的挑战。
当我意识到 TensorFlow Lite 支持微控制器时,我兴奋地翻了翻桌子。
我有几个 ESP32-CAM 模块,想用于家庭安全系统。我的想法是部署一个能识别人的模型,当摄像机捕捉到一个人时就开始记录。我不想在这里使用动作感应,因为我有一只狗会触动传感器。
我认为 TensorFlow Lite 是这个用例的一个很好的工具。我可以训练一个模型来识别我桌面上的人,然后将其部署到我的 ESP32-CAM 模块中。
通读 TensorFlow Lite 文档后,很明显使用 PlatformIO 不会像调用:
platformio lib install tfmicro
除非我想用 Adafruit 库(剧透:我不要)。
通过一些仔细的试验和错误,我能够让 TensorFlow Lite 在 ESP32 上很好地与 PlatformIO 兼容。
本指南将介绍我是如何使用 PlatformIO 和 Arduino-ESP32 支持将“Hello World”示例编译并上传到 ESP32-CAM 模块的。
为 PlatformIO 部署设置 TensorFlow Lite
你要做的第一件事是安装 PlatformIO。为此,请打开终端并键入:
pip install -U platformio
现在,创建项目的根目录。这个目录还应该包含 src 、 lib 、 include 的子目录。
在项目的根目录下,创建一个名为 platformio.ini 的文件。该文件将包含 PlatformIO 初始化开发环境所需的所有信息。我的看起来像:
platformio.ini
接下来,您需要创建一个名为 custom.csv 的文件。这是 ESP32 闪存的分区信息。您可以根据应用程序的需求和 ESP32 的闪存大小格式化分区表。更多关于 ESP32 分区表的信息可以在这里找到。下面是我的 custom.csv 文件的格式:
custom.csv — The custom partition table I am using for the ESP32
完成所有设置后,继续克隆 TensorFlow 存储库(包括 TensorFlow Lite)。您可以下载. zip 文件并解压到您选择的目录中,或者使用 git 克隆:
git clone [https://github.com/tensorflow/tensorflow.git](https://github.com/tensorflow/tensorflow.git)
下载 TensorFlow 存储库后,从 TensorFlow Lite 文件夹中生成一个示例 ESP32 项目。我们想要生成一个样例项目,这样我们就可以获取生成的 tfmicro 库和样例模型。要生成示例项目,请导航到根“tensorflow”文件夹并运行:
sudo make -f tensorflow/lite/experimental/micro/tools/make/Makefile TARGET=esp generate_hello_world_esp_project
这将生成一个示例项目,它位于:
tensorflow/lite/experimental/micro/tools/make/gen/esp_xtensa-esp32/prj/hello_world
导航到 hello_world/esp-idf 目录,将 tfmicro 文件夹从 components 复制到之前创建的 lib 文件夹中。如果您计划运行示例程序以确保正确设置环境,那么将 sin_model_data.cc 和 sine_model_data.h 从主文件夹复制到 src 和 include 文件夹。
您的文件结构现在应该类似于:
Project Directory Structure
到目前为止很简单,是吧?
您几乎完成了!你只需要调整一下 tfmicro library 文件夹中的一些东西,这样 PlatformIO 就可以看到 TensorFlow Lite 需要的所有第三方库。
导航到 tfmicro 文件夹。你应该会看到两个文件夹: tensorflow 和 third_party 。
进入third _ party/flatbuffers/include,将 flatbuffers 子目录复制到 tfmicro 根目录。
接下来,进入第三方/gemmlowp ,将固定点和内部目录复制到 tfmicro 根目录。
最后,将 kissfft 目录从第三方复制到 tfmicro 根目录。
此时,您可以继续删除第三方目录。
通过将所有第三方库移动到 tfmicro 根目录,PlatformIO 可以识别并使用它们。
项目的最终结构应该是这样的:
File structure for a TensorFlow Lite ESP32 Project
文件结构完成后,导航到lib/TF micro/flatbuffers并打开 base.h 。在 base.h 内,将第 34 行从:
#if defined(ARDUINO) && !defined(ARDUINOSTL_M_H)
#include <utility.h>
#else
#include <utility>
#endif
收件人:
#include <utility>
您现在完成了!剩下要做的唯一一件事就是在项目中导入和使用 TensorFlow Lite。
构建一个示例项目
为了测试 TensorFlow Lite 是否正常工作,我改编了“Hello World!”Arduino-ESP32 草图中使用的正弦模型。
下面我来指导你我是怎么做的!
包括
我做的第一件事是导入项目将使用的所有库。
Needed Libraries for TensorFlow Lite Sample Project
这些库如下:
- Arduino。h — Arduino 支持!:)
- math.h —这里专门用来定义 M_PI(后面会讨论)。
- all_ops_resolver.h —定义用于运行模型的操作。
- micro_error_reporter.h —用于错误报告。
- micro_interpreter.h —运行模型。
- sine_model_data.h —我们正在使用的样本模型。
全局变量
接下来,我设置变量:
TensorFlow Lite Variables
我定义的第一个全局变量是内存池,用于存储模型生成的数组。 TensorFlow 的文档指出,您可能需要从不同模型的实验中得出池的大小。为此,我只是使用了 TensorFlow 为运行正弦模型提供的示例代码。
然后我定义了模型、解释器和输入/输出节点。
设置设计
定义了全局变量之后,就该设置环境了。
在“setup()”函数中,我以 115200 波特启动串行,并导入正弦模型。
Start Serial and Import Sine
然后我实例化了 TensorFlow Lite 微解释器
最后,我将模型的张量分配到被定义为全局的内存池中,并将输入和输出变量设置到它们对应的节点。
“setup()”函数到此结束。简言之:我导入了模型,创建了解释器,并将模型加载到内存中。
控制回路设计
“setup()”函数完成后,我开始实现控制循环逻辑。
对于控制循环,我等待来自 serial 的用户输入,并将其转换为 float。然后,我检查以确保用户输入在模型的参数(0–2 * PI)范围内:
然后,我将模型的输入节点设置为已解析的用户输入,调用解释器,然后打印出结果:
部署到 ESP32
代码完成后,您可以使用 PlatformIO 部署到 ESP32,包括:
platformio run -t upload --upload-port /dev/ttyUSB0
Uploading to the ESP32
然后,您可以使用以下命令通过串行给出程序输入:
screen /dev/ttyUSB0 115200
Running Sine Model on ESP32
就是这样!我真的很惊讶 TensorFlow 可以如此轻松地将模型部署到微控制器上。我的下一篇文章将讨论如何使用 TensorFlow 创建模型,以及如何将其转换为可以由 TensorFlow Lite 运行的东西!
GitHub 项目报告:https://GitHub . com/wezleysherman/ESP32-tensor flow-Lite-Sample
tensor flow on edge——用树莓派打造“智能”安全摄像头
构建一个“智能”、Raspberry Pi 支持的边缘计算摄像头设置,运行 Tensorflow 对象检测模型来检测入侵者
我的户外相机被光线、风、汽车或除了人以外的任何东西触发的时间太长了。过于谨慎的安全摄像头可能是一个特征,但也是一个令人讨厌的特征。
我需要一个解决这个问题的方法,但不要太过火。简单,优雅,但有效的东西。
乡亲们,来见见我亲切地称之为“ ”的稻草人——Cam。一个 Raspberry Pi 供电的摄像头,它通过 Tensorflow 对象检测来检测人们,并在他们踏上我的门廊的第二秒钟用格外响亮刺耳的音乐(或警告声)来迎接他们。
通过 Tensorflow、Raspberry Pi、摄像头、扬声器和 Wifi 进行实时物体检测,确保夜晚宁静。有点吧。
我们在做什么?
更严重的是,使用实时视频流和机器学习进行对象检测是一个实际的真实世界用例。虽然大多数用例可能令人毛骨悚然,但我确实在检测物体或人方面找到了一些价值*,最初发表于 2019 年 12 月 9 日*https://chollinger.com*。*在私人安全摄像头上。
如果家中的安全摄像头网络能够检测到真实、潜在的威胁——人类和松鼠——并做出相应的反应(例如,通过发送警报),这将极大地提高这些设备的实用性,这些设备主要依赖于运动检测或连续视频记录——这两者要么非常容易出错,要么最多是被动反应(向你展示事后发生的事情)。
关于安全摄像头的话题
然而,大多数消费级视频监控系统非常糟糕、简单明了。它们要么需要昂贵的硬连线,要么依赖于每 10 分钟设置一次的 janky 红外和运动检测,因为汽车会驶过房屋,依赖于第三方公司的 grace 和软件更新,通常是订阅模式,通常无法通过 API 访问。
我的未命名的户外相机设置通常由风中飘扬的旧荣耀引发,而不是由人引发。
解决方案
这是我们要做的:
我们将使用带有摄像头模块的 Raspberry Pi 4 来检测视频。这可以持续运行,不需要依靠运动传感器来启动。
为了检测物体,我们将使用谷歌的张量流物体检测 API 。这个库使我们能够使用开箱即用的对象检测(稍后将详细介绍),而不需要手动训练和调整模型,也不需要云部署。
为了与摄像机对话,我们将依赖于 OpenCV。
现在,给你一个问题:我的旧 RasPi 运行的是 32 位版本的 Raspbian。Tensorflow 与 32 位操作系统不兼容(当然,可能会有替代方案)。此外,虽然新的覆盆子是一个强大的小机器,但它远不能与现代计算机相比——特别是在 3 和更早的版本上。
为了减轻这种情况,我们将通过 Pi 上的网络将视频流式传输到一台更强大的机器上——一台家庭服务器、NAS、计算机、一台旧笔记本电脑——并在那里处理信息。
这是一个叫做边缘计算的概念。根据这个概念,我们本质上使用功能较弱、较小的机器来实现低延迟通信,方法是在物理上靠近边缘节点的机器上执行繁重的工作,在本例中,运行 Tensorflow 对象检测。通过这样做,我们避免了互联网上的往返,以及不得不为 AWS 或 GCP 上的云计算付费。
为了实现这一点,我们将使用 VidGear ,具体来说是 NetGear API ,这是一个为通过网络传输视频而设计的 API,使用 ZeroMQ。只是要警惕一个 bug,要求你使用开发分支。
一旦我们检测到流中有人,我们就可以使用 ZeroMQ 向树莓发送信号,播放一些非常大声、令人讨厌的音频来吓跑人们。
设置开发环境
虽然可能不是最有趣的部分,但首先,我们需要一个开发环境。为此,我在 Linux 上使用了 Python 3.7 的 Jupyter 笔记本。
我们将基于以下教程开展工作:https://github . com/tensor flow/models/blob/master/research/object _ detection/object _ detection _ tutorial . ipynb
旁注:由于我使用的是 Tensorflow 2.0 测试版,我不得不将 tf.gfile 的 API 修改为~/中的 tf.io.gfile。local/lib/python 3.7/site-packages/object _ detection/utils/label _ map _ util . py
克隆笔记本,按照说明设置虚拟环境,并安装所有依赖项。
局部测试张量流
一旦完成,我们很可能想要用测试数据循环本地视频,而不必实际连接现场摄像机。
这里我们真正需要做的是改变“while True”循环,以绑定到 OpenCV 会话。VideoCapture 方便地接受整数(对于网络摄像头)或视频文件的路径。
Some parts of the image were manually blurred for privacy — also, those are invited visitors 😊
一旦运行笔记本,您应该会看到检测模型的覆盖图。太好了,模型起作用了,我们可以稍后进行微调。
网络,网络!
如前所述,我们不会依赖我们的 Rasberry Pi 来运行检测—因此我们将建立一些网络通信。我本来想自己写这篇文章(我目前正在学习围棋,所以这将是一个很好的用例),但是如果有一个库,为什么还要这么麻烦呢?[1]
你需要什么:
下面是一篇关于我如何设置 Pi 的示例文章:
接下来,我们将不得不考虑 VidGear 的开发分支,因为在撰写本文时,主服务器上还没有某个 bugfix。
现在,我们可以在本地测试流式视频:
您应该会看到视频回放。您会注意到多处理库的一些用途——我们使用它来确保 while 循环在定义的超时后终止,以用于开发目的。
[1]玩笑暂且不提:SQLite 的创始人 Richard Hipp 在 Changelog 播客上的 采访中给出了很多很好的理由来解释为什么这可能是个坏主意——但是为了简单起见,我们将坚持使用库
把 2 和 2 放在一起
接下来,让我们将它部署到两台独立的机器上——只要执行 Tensorflow 的服务器运行 64 位版本的 Linux(Linux 内核),我们就可以开始了。在家里,我有一个本地的 gitlab 和 jenkins 实例为我做这件事。但是实际上,任何部署选项都是可行的——scp 可以成为您的朋友。
我们需要通过指定 IP 地址和端口对代码做一些小的调整:
client = NetGear(address = '192.168.1.xxx, port = '5454', protocol = 'tcp', pattern = 0, receive_mode = True, logging = True) server = NetGear(address='192.168.1.xxx, port='5454', protocol='tcp',pattern=0, receive_mode=False, logging=True)
现在,我们可以在服务器上启动 sender.py,在客户机上启动 receiver.py,这样我们就可以开始了:网络视频。整洁!
积分张量流
张量流的集成在这一点上是微不足道的:因为我们已经建立了如何做以下事情:
- 使用 OpenCV 循环播放本地视频
- 使用 Tensorflow 对象检测在本地视频上运行实际模型
- 将视频从一台机器传输到另一台机器
最后一步可以简单地通过导入我们的 tensorflow_detector 模块来实现,将接收到的图像转换为一个 numpy 数组(因为这是 API 所期望的),并调用“run _ inference _ for _ single _ image(2)”。很简单!
对着摄像机说话
现在,我们可以调整我们的服务器代码,实际使用 Tensorflow 来检测来自不同机器的图像。但是我们不想要固定的图像——我们需要一个实时流。
幸运的是,这非常简单,因为我们已经在 Pi 的设置过程中启用了相机模块:将相机的带状电缆连接到 Pi,启动它,然后运行:
raspistill -o ~/image.jpg
这个应该拍张照。
为了用 Python 做同样的事情,OpenCV 的 API 同样简单:在 PI 端,通过将视频文件的来源改为摄像机的 ID(0,因为我们只有一个), OpenCV 将获取摄像机流并将其发送到我们的服务器。
一旦我们运行这个,我们应该会看到这样的内容:
触发摄像头上的音频
现在,我们能够将视频从树莓上传到服务器,并检测到一个人。现在缺少的环节是使用 GStreamer 的 playsound 库来播放音频。其他替代方法是使用 ossubprocess 调用或pygame——可以设置一个配置选项来改变这种行为。
(您可以使用“alsamixer”在 Pi 上设置音量)。
为此,我们将再次使用 ZMQ ,在 Pi 上启动一个监听器线程,等待来自服务器的输入,设置预定义的枚举值。一旦客户端收到这些信息,它就会触发一个音频信号并播放声音。
所有这些都阻塞了各自的线程,也就是说,只要音频播放,听众就不会关心新消息,服务器也无法发送新消息。
为了避免重复同样的信息,我们可以使用一个简单的 sempahore 结构。
测试一切
现在一切都正常了,有趣的部分来了:设置它。
首先,让我们把摄像机放在某个地方:
并启动服务器和客户端,看看当我们走进房间时会发生什么!
正如你所看到的,它需要一秒钟才能检测到我——部分原因是摄像机角度、我们选择的模型以及一些网络延迟。在现实生活中,一个人需要走进门,这不是一个问题。
“警告,你是…”的信息来自那个小喇叭!
后续步骤
虽然这已经工作得相当好了——它可以传输视频,检测人,并发送信号发送音频——但这里肯定还有工作要做。
然而,为了这个项目的目的,我们忽略了几件事:我们正在使用的模型仅仅是一个预先训练的模型,它既没有针对我们的特定用例进行调整,也不一定为我们正在使用的机器提供最佳平衡。
此外,代码中的一些内容可能需要一些改进——网络延迟还不错,但可能需要一些工作,音频被连续快速触发,并且使用我们当前的 ZeroMQ 模式,我们只能支持一个客户端。
虽然使用纸板盒几乎是完美的定义,但定制的 3D 打印覆盆子盒和稍好的冷却可能是一个好主意。
结论
无论如何,我对这个小项目很满意,因为它说明了构建自己的安全摄像头、将其连接到网络、运行对象检测并触发外部因素(在本例中为音频,但也可能是电话通知或其他东西)是多么简单,而无需使用任何公共云产品,从而节省住宅互联网的延迟和成本。
所有的开发都是在 PopOS 的领导下完成的!2019 System76 Gazelle 笔记本电脑上的 19.04 内核 5.5.1,12 个英特尔 i7–9750h v cores @ 2.6 GHz 和 16GB RAM、以及 Raspian 10 上的 Raspberry Pi 4 4GB。
完整源代码可在GitHub上获得。
原载于 2019 年 12 月 9 日https://chollinger.comT22。
张量流——核心概念
[source: https://tensorflow.org]
和大多数机器学习库一样,TensorFlow 是“重概念轻代码”的。这种语法不难学。但是理解它的概念非常重要。
什么是张量?
根据维基百科,“张量是一种几何对象,它以多线性方式将几何向量、标量和其他张量映射到结果张量。因此,通常已经在基础物理和工程应用中使用的向量和标量本身被认为是最简单的张量。此外,来自提供几何向量的向量空间的对偶空间的向量也被包括为张量。在这种情况下,几何学主要是为了强调坐标系选择的独立性
别担心,没那么复杂。当处理一个有多个变量的问题时,将它们以向量或矩阵的形式集中在一起通常是很方便的,这样就更容易对它们进行线性运算。大多数机器学习都是基于这样的矩阵运算——将一组输入值一起处理,得到一组输出值。
例如,在贷款审批问题中,我们考虑该主题的几个参数(过去贷款的金额、归还贷款的时间等。)并用适当的权重将它们相加,得到一个称为信用评级的输出数字。这是使用简单的矩阵乘法实现的。
这种矩阵乘法只给出一种情况的结果。当我们想要用一百万个这样的案例的数据来训练一个神经网络时,我们不能一个接一个地把它们相乘。这就是张量的用途。张量是一种数据结构,表示矩阵或向量或标量的集合,允许我们同时对所有数据样本执行操作。这给了我们很大的性能提升。
张量不需要有数值。它可以是一个输入值,一个常数,一个变量,或者只是对一些其他张量的数学运算的引用。
张量可能是 3D(矩阵的集合)或 2D(向量的集合)或 1D(数的集合),甚至是 0D(单个数)。维度的数量并不构成张量——重要的是对多个实体同时操作的概念。
军阶
张量的维数叫做张量的秩。因此,我们有几个可能的等级。
常数张量
最简单的张量是一个常数。我们可以用显式值或使用为常用值定义的方法来定义。
注意,这并没有将常数值赋给张量。它只创建需要时可以评估的张量。
可变张量
常数允许我们创建可用于计算的预定义值。但是没有变量的计算是不完整的。训练一个神经网络需要能够代表要在该过程中学习的权重的变量。这些变量可以使用 tf.Variable 类生成。
每一个都产生一个可变张量。但是第三个和其他的略有不同。前两个张量可以训练。但是,第三个只是创建了不可改变的变量张量——就像常量一样。
做那样的事情有什么用?为什么不直接定义一个常数呢?对于 10x10 的张量,创建一个常数张量更有意义。但是当处理巨大的数据时,人们应该更喜欢变量。这是因为变量得到了更有效的管理。
占位符
常数张量和变量张量与任何编程语言中的常数和变量在直觉上是相似的。这不需要花时间去理解。占位符定义了将在代码运行前获得值的张量。从这个意义上说,占位符可以比作输入参数。
这将生成一个张量 x——保证在代码实际运行之前提供它的值。
懒惰执行
按照设计,TensorFlow 是基于延迟执行的(尽管我们可以强制急切执行)。这意味着,它实际上不处理可用的数据,直到它不得不这样做。它只是收集我们输入的所有信息。只有当我们最终要求它处理时,它才会处理。
这种懒惰(讽刺地)极大地提高了处理速度。要理解如何,我们需要理解 TensorFlow 的节点和图形。
Typical Dense Neural Network
这是神经网络的教科书观点。正如我们看到的,我们有几个输入 X1-Xn。这些构成了网络的第一层。第二层(隐藏层)是这些层与权重矩阵的点积,后面是 sigmoid 或 relu 之类的激活函数。
第三层只是一个值,它是作为其权重矩阵与第二层的输出的点积而获得的。
结节
对于 TensorFlow,这些单独的实体中的每一个都是一个节点。第一层有 n+1 个节点(n 个输入和 1 个常数)。第二层有 k+1 个节点,第三层有 1 个节点。这些节点中的每一个都由一个张量表示。
图表
我们可以看到一些节点有一个恒定值(如偏差 1)。其中一些具有可变值,如权重矩阵——我们从随机初始化开始,并在整个过程中对其进行调整。我们有一些节点,其值只是基于其他节点上的一些计算—这些是依赖节点—我们无法获得它们的值,直到我们有了先前节点的值。
在这个网络中,我们在中间层有 k 个节点,在最后一层有 1 个依赖于其他节点的节点,我们有 k+1 个依赖节点和 k 个需要调整的变量。
汇编
当我们创建单独的张量时,我们只是创建单独的节点并分配定义关系——这些关系还没有实现。定义完成后,我们启动 compile()方法,该方法标识连接节点的图。
这是整个过程中的重要一步。如果我们有循环依赖或任何其他可能破坏图表的原因,错误就在这一点上被识别出来。
会议
张量流计算总是在“会话”中执行。会话本质上是一个具有自己状态的环境。会话不是一个线程,但是如果我们有两个独立的计算需要一起运行——彼此不影响,我们可以使用会话。
这里,A 和 C 将在会话 1 下运行,并将看到一个环境,B 和 D 将在会话 2 中运行,并将看到另一个环境。
一旦我们定义了节点并编译了图形,我们最终可以运行命令来获取图形中特定节点的值。当我们这样做时,TensorFlow 会回头检查该请求节点所需的所有节点。只有那些节点会以适当的顺序进行评估。因此,图中的节点仅在需要时才被评估;只有在需要的时候。
这对处理速度影响很大,是 TensorFlow 的一大优势。
简单代码示例
为了理解 TensorFlow,理解常量、变量、占位符和会话的核心概念非常重要。现在让我们设计一个例子,它可以一次显示所有这些概念。
当然,我们从导入 TensorFlow 模块开始
现在,让我们定义几个张量。这里,t1 和 t2 是常数,t3 是占位符,t4 是变量。
这里,我们将 t1 定义为大小为 4x5 的常数张量,所有值都设置为 1。t2 是大小为 5x4 的常数张量,具有随机值。
t3 是一个维数为 0 的占位符,是一个浮点数 32。
与此同时,我们定义了一个 4x4 形状的变量 t4。初始值设定项被设置为 ones_initializer。这意味着,每当我们初始化变量时,它的值将被设置为 1。请注意,这只会在我们初始化变量时发生,而不是现在。
接下来,我们可以定义张量表达式
这段代码取 t1 和 t2 的点积,乘以标量 t3,然后加到 t4。其结果然后被分配给 t4。因此,每次执行该表达式时,t4 的值都会改变。注意 t3 是一个占位符,所以当我们想要处理这个表达式时,我们必须提供 t3 的值。
同样,这段代码只定义了表达式。它不会立即执行。
一切就绪后,我们现在可以开始会话,并开始与张量一起工作
在这里,我们实际上运行代码。我们从启动会话开始。我们必须初始化变量。到目前为止,t4 只是被声明,没有初始化。在这里,我们实际上初始化它。执行初始化代码。在这种情况下,恰好是“tf.ones_initializer”。因此,t4 从一个 4x4 张量开始,所有值都设置为 1。
接下来,我们运行表达式和 feed_dict。记住,表达式有一个占位符 t3。除非我们给它一个 t3 的值,否则它不会求值。这个值是通过 feed_dict 传递的。每次运行都会更新 t4,并为其分配一个新值。
上面的代码生成以下输出:
请注意,t4 在初始化之前没有值,只有当表达式在有效会话中运行时,它的值才会改变。可以对表达式求值三次,以断言输出与我们预期的一样。
张量流——软件工程的范围
如何像软件工程师一样构建你的张量流图
现在,您已经完成了对模型的训练,是时候了解一下它学到了什么。你决定哪个张量应该是有趣的,并在你的代码中去寻找它——找出它的名字。然后你突然想到——你忘了给它起个名字。您还忘记了用一个命名的作用域来包装逻辑代码块。这意味着你很难找到张量的参考。它适用于 python 脚本和 TensorBoard:
你能看到那个消失在张量海中的小红圈吗?找到它很难…
真令人失望!如果它看起来更像这样会好得多:
这还差不多!构成一个逻辑单元的每组张量都包含在一个命名的作用域内。
为什么图形不能以类似于你的代码的方式自动构建?我的意思是,大多数情况下,你没有使用单一函数来构建模型,是吗?您的代码库包含多个函数——每个函数都构成一个逻辑单元,它理应拥有自己的命名范围!
假设你有一个张量x
,它是由函数f
定义的,这个函数又被g
调用。这意味着当你写代码的时候,你的头脑中有这样的逻辑结构:g
->-f
->-x
。如果这个模型能够以张量名为g/f/x
的方式自动构建,那不是很好吗?
仔细想想,这很容易做到。您所要做的就是检查所有的函数并添加一行代码:
def f():
with tensorflow.name_scope(‘f’):
# define tensors
那么这种方法有什么问题呢?
- 函数名
f
出现了两次——在函数声明中和作为tensorflow.name_scope
的参数。也许下周你会把函数的名字改成更有意义的,比如说foo
。不幸的是,您可能会忘记更新作用域的名称! - 你必须对
f
的整个主体应用缩进。虽然没那么糟糕,但就我个人而言,我不喜欢高缩进级别。假设f
包含一个 for 循环,该循环包含一个 if 语句,该语句包含另一个 for 循环。由于调用了tensorflow.name_scope
,我们已经达到了缩进级别 4!
我们可以使用简单的元编程来绕过这些缺点——Python 的 decorators 来拯救我们!
import re def name_scope(f):
def func(*args, **kwargs):
name = f.__name__[re.search(r’[^_]’, f.__name__).start():]
with tensorflow.name_scope(name):
return f(*args, **kwargs)
return func @name_scope
def foo():
# define tensors
它是如何工作的?@
是一个语法糖。它相当于以下内容:
def foo():
# define tensors foo = name_scope(foo)
name_scope
获取一个函数作为参数(f
)并返回一个新函数(func
)。func
创建一个命名作用域,然后调用f
。
结果呢?由f
定义的所有张量都将在一个命名的作用域内创建。作用域的名称将是原始函数的名称(“foo”)—多亏了f.__name__
。
一个小问题是,虽然函数名可能以“_”开头,但 tensorflow 作用域名不能。这就是我们必须使用re
的原因。
为什么这么重要?
与实际使模型变得更好的研究挑战相比,编写干净的张量流代码的挑战可以忽略不计。
因此,很容易被诱惑去专注于你工作的研究方面。然而,从长远来看,重要的是不要忽视代码的可维护性和可读性,包括图形的可维护性和可读性。
装饰器方法使我的工作变得简单了一些,我希望您也能从中受益。你还有其他的建议想分享吗?在评论里掉一行!
最初由我发表于engineering.taboola.com。
tensor flow vs py torch vs Keras for NLP—exx act
在开始 TensorFlow 与 PyTorch 和 Keras 的功能比较之前,让我们先了解一下它们之间的一些非竞争性的软差异。
非竞争事实:
下面我们将介绍 TensorFlow、PyTorch 和 Keras 之间的一些差异。这些不同之处并不是出于相互比较的目的,而是为了引入本文讨论的主题。
张量流
- 由谷歌创建
- 2017 年 2 月 1.0 版本
PyTorch
- 由脸书创造
- 2018 年 10 月 1.0 版本
- 基于 Torch,另一个基于 Lua 的深度学习框架
克拉斯
- 简化深度学习框架复杂性的高级 API
- 运行在其他深度学习 API 之上——tensor flow、Theano 和 CNTK
- 它本身不是一个图书馆
TensorFlow 与 PyTorch 和 Keras 的竞争差异:
现在,让我们来看看他们三人更具竞争力的事实。我们特别希望对侧重于自然语言处理的框架进行比较分析。
1.两者中可用的 rnn 类型
当寻找 NLP 问题的深度学习解决方案时,递归神经网络(RNNs)是开发人员最受欢迎的架构。因此,从这个角度比较框架是有意义的。
所有正在考虑的框架都有模块,允许我们创建简单 RNNs** 以及它们更进化的变体——门控循环单元( GRU )和长短期记忆( LSTM )网络。**
PyTorch:
PyTorch 为构建这种循环网络提供了两个级别的类:
- 多层类— nn。新泽西州 RNN。GRU·安迪。LSTM
这些类的对象能够表示深度双向递归神经网络。 - 细胞水平类— nn。新罕布什尔州 RNNCell。格鲁塞尔和 nn。这些类的 LSTMCell
对象只能代表一个单元格(同样,一个简单的 RNN 或 LSTM 或 GRU 单元格),可以处理一个时间步长的输入数据。
因此,当我们不想在神经网络中进行太多定制时,多层类就像是细胞级类的一个很好的包装器。
此外,在多层类中将双向参数设置为真就可以实现 RNN 双向了!
查看我们的文章使用 PyTorch 框架开始使用 NLP——深入了解这些类的更多细节。
张量流:
TensorFlow 为我们提供了一个 tf.nn.rnn_cell 模块来帮助我们满足标准的 rnn 需求。
tf.nn.rnn_cell
模块中一些最重要的类如下:
- 单元级类,用于定义 RNN 的单个单元,即—
BasicRNNCell
、GRUCell
和 LSTMCell - ****MultiRNNCell 类用于堆叠各种单元格以创建深度 rnn
- DropoutWrapper 类,用于实现退出正则化
查看我们的文章使用 TensorFlow 和 Keras 框架开始使用 NLP,深入了解这个模块的更多细节。
Keras:
Keras 是 Keras 库中提供的重现层。这些层包括:
- SimpleRNN —全连接的 RNN,输出将反馈到输入
- GRU —门控循环单元层
- LSTM——长短期记忆层
查看我们的文章— 使用 TensorFlow 和 Keras 框架开始使用 NLP—深入了解这些类的更多细节。
因此,TensorFlow、PyTorch 和 Keras 三者都具有内置功能,允许我们创建流行的 RNN 架构。区别在于他们的界面。
Keras 有一个简单的接口和一个定义良好的参数列表,使得上面的类很容易实现。作为 TensorFlow 之上的高级 API,我们可以说 Keras 让 TensorFlow 变得简单。虽然 PyTorch 提供了与 TensorFlow 类似的灵活性,但它的界面要干净得多。
既然我们谈到了这个主题,让我们更深入地进行一项基于每个框架易用性的比较研究。
2.易于使用 TensorFlow vs PyTorch vs Keras
TensorFlow 经常因其不全面的 API 而受到指责。PyTorch 使用起来更加友好和简单。总的来说,PyTorch 框架与 Python 语言集成得更紧密,大多数时候感觉更原生。当你在 TensorFlow 中写作时,有时你会觉得你的模型在一堵砖墙后面,有几个小孔可以沟通。这就是为什么,克雷斯。
让我们根据它们的易用性,再讨论几个比较这三者的因素:
静态计算图与动态计算图:
这个因素在 NLP 中尤其重要。TensorFlow 使用静态图形进行计算,而 PyTorch 使用动态计算图形。
这意味着在 Tensorflow 中,在模型运行之前,您静态地定义计算图。与外界的所有通信都是通过 tf 进行的。会话对象和 tf。占位符是在运行时将被外部数据替换的张量。
在 PyTorch 中,事情更加命令化和动态化:您可以随时定义、更改和执行节点,没有特殊的会话接口或占位符。
在 RNNs 中,对于静态图形,输入序列长度将保持不变。这意味着,如果你为英语句子开发一个情感分析模型,你必须将句子长度固定到某个最大值,并用零填充所有较小的序列。不太方便吧?
调试:
由于 PyTorch 中的计算图是在运行时定义的,所以您可以使用我们最喜欢的 Python 调试工具,如 pdb、ipdb、PyCharm 调试器或旧的可信打印语句。【TensorFlow 却不是这样。您可以选择使用一个名为 tfdbg 的特殊工具,它允许在运行时计算张量流表达式,并浏览会话范围内的所有张量和操作。当然,你不能用它来调试任何 python 代码,所以有必要单独使用 pdb。
Tensorflow 比 PyTorch 更成熟。与 PyTorch 和 Keras 加起来相比,它有一个更大的社区。它的用户群增长速度比 PyTorch 和 Keras 都快。
所以这意味着-
- 一个更大的 StackOverFlow 社区来帮助您解决问题
- 更多的在线学习材料——博客、视频、课程等。
- 更快地采用最新的深度学习技术
NLP 的未来:
虽然递归神经网络已经成为 NLP 任务的“首选”架构有一段时间了,但它可能不会永远这样。我们已经有了一个更新的基于注意力机制的变形金刚模型,在研究人员中很受欢迎。
它已经被誉为新的 NLP 标准,取代了递归神经网络。一些评论者认为, Transformer 将成为 2019 年的主导 NLP 深度学习架构。
查看我们全面的 3 部分教程,开始学习变形金刚。
Tensorflow 似乎在这场竞赛中遥遥领先:
- 首先,基于注意力的架构是谷歌自己引入的。
- 第二,只有 TensorFlow 有针对 Transformer 架构的稳定版本
这并不是说 PyTorch 远远落后,在 Huggingface 的https://github.com/huggingface/pytorch-transformers有许多预先训练好的变形金刚模型。
所以,这就是比较的全部。但是在分手之前,让我告诉你一些可能会在一年内使整个谈话过时的事情!
张量流 2.0
谷歌最近发布了 Tensorflow 2.0 ,这是一个游戏规则改变者!
方法如下:
- 展望未来, Keras 将成为 TensorFlow 的高级 API,它经过扩展,因此您可以直接从 tf.keras 使用 TensorFlow 的所有高级功能。因此,TensorFlow 在各种规模和所有硬件下都非常简单。
- 在 TensorFlow 2.0 中,急切执行现在是默认的。即使在 eager 上下文中,您也可以利用图形,这使得您的调试和原型制作变得容易,而 TensorFlow 运行时则在幕后处理性能和可伸缩性。
- TensorBoard 与 Keras 整合,现在是… one -liner!
所以,我想这减轻了人们对张量流的所有抱怨。这意味着 TensorFlow 将巩固其作为所有深度学习任务的首选框架的地位,甚至比现在更好!
原载于 2019 年 8 月 6 日https://blog.exxactcorp.com。
特斯拉 5 级:自动驾驶
Future of Self Driving. Tesla, 2019, https://www.tesla.com/autopilot.
最近,埃隆·马斯克公开表示,到 2020 年,它将拥有 5 级自主能力。他进一步表示,所有特斯拉汽车都将能够充当机器人出租车,并将能够为车主创造高达 3 万美元的收入。马斯克声称,到 2020 年,特斯拉将拥有广泛的自动驾驶汽车网络。他声称,特斯拉可以在没有包括 Waymo 和 Cruise Automation 在内的所有主要竞争对手都采用的技术的情况下实现这一切。这包括激光雷达传感器(激光雷达)和超详细三维测绘。相反,特斯拉计划依靠其摄像头和传感器阵列收集足够的信息,让汽车自动驾驶。让特斯拉与众不同的是其新的全自动驾驶芯片的能力。
过去几年,特斯拉一直在与英伟达(NVIDIA)合作开发其汽车中的芯片。然而,最近特斯拉创造了一种新的芯片,它被称为全自动驾驶芯片。这块有 60 亿个晶体管的硅片应该比之前的 NVIDIA 芯片快 21 倍。此外,新芯片由三星制造。FSD 芯片每秒能够进行超过 36 万亿次运算,并将花费特斯拉最初支付费用的 80%。所有这一切只导致大约 25%的功率增加。此外,出于过度保护的目的,每个全自动驱动计算机板都具有冗余的额外芯片、电源和处理器。
特斯拉生产世界上最安全的车辆,它对自动驾驶技术的态度一直是积极的。在一个与人类相关的事故太常见的世界里,自动驾驶汽车上路将有助于减少每年的事故数量。像 Waymo、优步 ATG、Lyft Level 5 等公司都在致力于制造完全自动驾驶的车辆,但没有一家公司声称到 2020 年拥有 5 级自动驾驶。特斯拉最近的声明迫使其他公司重新评估他们的计划和他们正在使用的技术,以及它们是否真的有必要。然而,这个雄心勃勃的时间表被视为过于乐观和不可思议,特别是由于埃隆马斯克过去的说法。
自动驾驶技术是我们社会的必需品,因为它将减少每年与驾驶相关的死亡人数。这些公司中的一家能够越快地让他们的车辆达到第 5 级自主,就能拯救越多的生命。目前,在生产第 5 级自动驾驶汽车的竞赛中,似乎有两家领先者是 Waymo 和特斯拉。特斯拉相对于 Waymo 的优势在于,特斯拉制造整个车辆,而 Waymo 则设计为与其他车辆合作。
请随时在 mank2@illinois.edu联系我,或者在 https://www.linkedin.com/in/aman-kishore/的 LinkedIn 上联系我
[来源](https://www.cnet.com/roadshow/news/teslas-autonomy-investor-day-recap/ https://www.tesla.com/autopilot https://www.theverge.com/2019/4/22/18510828/tesla-elon-musk-autonomy-day-investor-comments-self-driving-cars-predictions https://www.forbes.com/sites/lanceeliot/2019/04/22/musk-unveils-audacious-vision-for-tesla-self-driving-tech-but-level-5-target-looks-unlikely/#164ed3204c78 https://www.theverge.com/2019/4/22/18511594/tesla-new-self-driving-chip-is-here-and-this-is-your-best-look-yet)
原载于 2019 年 6 月 5 日 https://medium.com。
特斯拉的大规模深度学习:使用数十亿英里训练神经网络
Photo by Chuttersnap.
特斯拉能做到而 Waymo 做不到的事情
训练数据是决定深度神经网络性能的基本因素之一。(另外两个是网络架构和优化算法。)作为一般原则,更多的训练数据导致更好的性能。这就是为什么我相信特斯拉,而不是 Waymo,拥有世界上最有前途的自动驾驶汽车计划。
Visualization of Tesla’s fleet. Image courtesy of Tesla.
大约有 50 万辆配备了特斯拉声称的完全自动驾驶硬件的车队在路上行驶,特斯拉的车队每天行驶的里程数大约为 1500 万英里,相当于 Waymo 车队成立以来行驶的里程数。每天 1500 万英里推算起来就是每年 54 亿英里,比 Waymo 预计的一年后的总里程数多 200 倍。特斯拉的车队也在以每周约 5000 辆的速度增长。
数据在三个关键领域发挥着重要作用:
- 计算机视觉
- 预言;预测;预告
- 路径规划/驾驶策略
计算机视觉
一个重要的计算机视觉任务是目标检测。有些物体,比如马,只是很少出现在路上。每当特斯拉遇到神经网络认为可能是马的东西(或者可能只是一个未识别的物体阻挡了一段道路),相机就会拍摄快照,稍后会通过 wifi 上传。它有助于让车辆每年行驶数十亿英里,因为你可以找到许多稀有物品的例子。显而易见,随着时间的推移,特斯拉在识别稀有物体方面将比 Waymo 车辆更好。
对于常见的物体,Waymo 和特斯拉的瓶颈很可能是付钱给人来手动标记图像。很容易捕捉到比你付钱给人们去贴标签更多的图像。但对于稀有物体来说,Waymo 的瓶颈可能是首先收集图像,而特斯拉的瓶颈可能只是标记和开发软件,以便在正确的时间触发快照。这是一个更好的位置。
特斯拉的人工智能总监 Andrej Karpathy 在这个剪辑中解释了特斯拉如何获取图像来训练物体检测(摘自他在自治日的演讲):
预言;预测;预告
预测是提前几秒钟预测汽车、行人和骑自行车者的运动和行动的能力。安东尼·莱万多夫斯基(Anthony Levandowski)多年来一直是 Waymo 的顶级工程师之一,最近写道“没有人实现‘完全自主’的原因是因为今天的软件还不足以预测未来。”莱万多夫斯基声称自动驾驶汽车的主要失败是错误地预测附近汽车和行人的行为。
特斯拉大约 500,000 辆汽车的车队是一个极好的资源。每当特斯拉对汽车或行人做出不正确的预测时,特斯拉都可以保存数据快照,以便稍后上传并添加到特斯拉的训练集中。特斯拉可能能够上传由其计算机视觉神经网络产生的场景的抽象表示(其中物体被可视化为彩色编码的长方体形状,像素级信息被丢弃),而不是上传视频。这将从根本上降低上传这些数据的带宽和存储需求。
尽管用于训练对象检测的图像需要人类标记,但预测神经网络可以仅从事件的时间序列中学习过去和未来之间的相关性。什么行为先于什么行为是任何记录(视频或摘要)中固有的。安德烈·卡帕西在下面的视频中解释了这个过程:
由于不需要人类来标记数据,特斯拉可以根据它可以收集的尽可能多的有用数据来训练它的神经网络。这意味着其训练数据集的大小将与其总里程数相关。与物体检测一样,与 Waymo 相比的优势不仅仅是有更多的数据来预测常见行为,而是能够收集在罕见情况下看到的罕见行为的数据,以便预测这些行为。
路径规划/驾驶策略
路径规划和驾驶政策指的是汽车采取的行动:在限速车道上保持居中、变道、超车、在绿灯时左转、绕过一辆停着的汽车、停下来等。似乎很难指定一套规则来涵盖汽车在任何情况下可能需要采取的所有行动。解决这一棘手难题的一种方法是让神经网络模仿人类的行为。这被称为模仿学习(有时也被称为学徒学习,或从示范中学习)。
训练过程类似于神经网络如何通过绘制过去和未来之间的相关性来学习预测其他道路使用者的行为。在模仿学习中,神经网络通过绘制它所看到的(通过计算机视觉神经网络)和人类驾驶员采取的行动之间的相关性,来学习预测人类驾驶员会做什么。
Still frame from Tesla’s autonomous driving demo. Courtesy of Tesla.
模仿学习最近取得了可以说是迄今为止最大的成功:AlphaStar。DeepMind 使用数百万人玩的星际争霸游戏数据库中的例子来训练神经网络像人类一样玩游戏。该网络了解了游戏状态和人类玩家行为之间的相关性,从而学会了预测人类在面对游戏状态时会做什么。仅通过这种训练,AlphaStar 就达到了 DeepMind 估计将使其在星际争霸的竞争排名中大致处于中间的能力水平。(后来,AlphaStar 使用强化学习进行了增强,这使它能够提升到专业水平的能力。自动驾驶汽车可能会也可能不会有类似的增强——这是另一个话题。)
特斯拉正在将模仿学习应用于驾驶任务,例如如何处理高速公路三叶草的陡峭曲线,或者如何在十字路口左转。听起来特斯拉计划随着时间的推移将模仿学习扩展到更多的任务,比如如何以及何时在高速公路上变道。卡帕西在这个片段中描述了特斯拉如何使用模仿学习:
与预测一样,上传汽车周围场景的抽象表示可能就足够了,而不是上传视频。这意味着更低的带宽和存储需求。
与预测一样,一旦数据上传,就不需要人为标记。由于神经网络正在预测人类驾驶员在给定世界状态的情况下会做什么,所以它需要的只是世界状态和驾驶员的行动。本质上,模仿学习是预测特斯拉司机的行为,而不是预测特斯拉周围其他道路使用者的行为。与 AlphaStar 一样,所有需要的信息都包含在所发生事情的回放中。
基于 Karpathy 关于预测超车的评论,当特斯拉未能正确预测前方车辆是否会切入特斯拉的车道时,它可以触发汽车保存重播。同样,当参与路径规划或驾驶政策的神经网络未能正确预测特斯拉驾驶员的行动时,特斯拉可能会捕捉到重播数据。埃隆·马斯克(Elon Musk)过去曾提到过这一功能(或类似的功能),尽管尚不清楚它目前是否在特斯拉汽车上运行。
相反,当特斯拉处于自动驾驶或即将到来的城市半自动驾驶模式时,人类司机就会接管。这可能是一个丰富的例子,其中系统做了一些错误的事情,然后人类驾驶员立即演示如何正确地做。
其他捕捉有趣回放的方法包括:突然刹车或转向,自动紧急刹车,撞车或碰撞警告,以及机器学习中更复杂的技术,称为异常检测和新奇检测。(这些相同的条件也可以用于触发用于预测的重放捕获或用于对象检测的相机快照。)如果特斯拉已经知道它想要捕捉什么,比如十字路口的左转,它就可以设置一个触发器,每当视觉神经网络看到交通灯并激活左转信号时,或者方向盘左转时,就捕捉回放。
结论
由于拥有大约 50 万辆汽车,特斯拉在三个关键领域比 Waymo(和其他竞争对手)更具优势:
- 计算机视觉
- 预言;预测;预告
- 路径规划/驾驶策略
对收集正确数据的担忧,付钱给人们去贴标签,或者为带宽和存储付费,都不能排除这些优势。通过设计好的触发器,使用不需要人为标记的数据,以及使用抽象的表示(重放)而不是原始视频,可以解决这些问题。
商业分析师、记者和普通公众的大多数观点似乎是,Waymo 在自动驾驶方面遥遥领先,而特斯拉并没有接近。当你看神经网络的第一原理时,这种观点是没有意义的。
更重要的是,AlphaStar 是针对复杂任务的大规模模仿学习的概念证明。如果你怀疑特斯拉的方法是正确的,或者路径规划/驾驶政策是一个容易处理的问题,你必须解释为什么模仿学习对星际争霸有效,但对驾驶无效。
我预测,除非 Waymo 采取激进措施扩大其车队规模,否则在未来 1-3 年内,Waymo 遥遥领先、特斯拉远远落后的观点将被广泛抛弃。人们一直过于关注演示,这些演示没有告诉我们系统的健壮性、深度受限的脱离度指标,以及谷歌/Waymo 对顶级机器学习工程师和研究人员的访问。他们对训练数据的关注太少,特别是对于罕见的物体和行为,Waymo 没有足够的数据来做好机器学习,或者根本没有。
Tesla’s driving simulation. Image courtesy of Tesla.
模拟并不是 Waymo 的优势,因为特斯拉(像所有自动驾驶汽车公司一样)也使用模拟。更重要的是,模拟不能产生罕见的对象和罕见的行为,因为模拟的创建者不能预测或不知道如何准确地建模。
纯粹的强化学习对 AlphaStar 不起作用,因为星际争霸的行动空间太大,随机探索无法找到好的策略。所以,DeepMind 不得不用模仿学习来引导。这显示了一个假设的弱点,即与 AlphaGo Zero 一样,纯模拟体验将解决任何问题。特别是当涉及到像驾驶这样的问题时,预测人类的行为是一个关键的组成部分。预测人类行为需要真实世界的经验信息。
自动驾驶汽车领域的观察人士可能低估了特斯拉吸引顶级机器学习人才的能力。一项对科技工作者的调查发现,特斯拉是湾区第二受欢迎的公司,仅次于谷歌。它还发现特斯拉是全球第四大最受欢迎的公司,比排名第二的谷歌落后两个等级。(Shopify 在全球排名第三,SpaceX 排名第一。)还值得注意的是,机器学习的基本进展通常由学术界、OpenAI 以及谷歌、脸书和 DeepMind 的企业实验室公开分享。特斯拉能做的和 Waymo 能做的差别可能没那么大。
这两家公司最大的区别在于数据。随着特斯拉的车队增长到 100 万辆,其每月里程数将约为 10 亿英里,比 Waymo 每月约 100 万英里的里程数多 1000 倍。这 1000 倍的差异对特斯拉来说意味着对罕见物体的卓越检测,对罕见行为的卓越预测,以及对罕见情况的卓越路径规划/驾驶政策。自动驾驶的挑战更多的是处理包含罕见边缘情况的 0.001%的里程,而不是 99.999%的里程。所以,按理说,能从这 0.001%的里程中收集到大量训练样本的公司,会比不能的公司做得更好。
SAS 中的统计显著性检验
许多材料可用于统计显著性检验。这个博客为你提供了为什么、什么、何时以及如何使用统计测试的简短想法?。此外,这篇博文试图快速修订这些统计测试的用法。p 值和假设没有在这个博客中讨论,你可以在这里查看。
为什么我们需要很多统计测试?
例如,我们想测量球的重量。我们有四种测量设备可供选择,如天平、温度计、尺子和容量瓶。我们选择哪一个?显然,我们选择身体平衡。不是吗?假设我们想测量球的温度。然后我们选择温度计。对于体积,我们选择容量瓶。
现在,您可以看到,随着我们要测量的变量发生变化,器件也会发生变化。同样的,为什么我们有这么多的统计测试?我们有不同类型的变量和分析。随着分析类型的改变,统计检验也随之改变。
让我们再举一个例子,假设老师想比较班上男生和女生的身高。
于是老师产生了无效的替代假设。这里,
零假设(H0) →男孩和女孩的身高相似,身高之间的任何差异都是偶然的。
**(H1)**→男孩的身高高于女孩的身高,所以观察到的身高差异是真实的。
如何验证这个假设?为此,统计显著性检验发挥了作用。
什么是统计显著性检验?
这些测试有助于研究人员或分析师确认假设。换句话说,这些测试有助于假设是否正确?
有很多统计测试。但是,我们将在这个博客中看到两种类型。
统计显著性检验分为两种类型。
下一个问题,什么时候用?
选择统计测试
参数和非参数都有不同类型的测试(不同类型的参数测试将在下面介绍),但是分析师或研究者如何根据研究设计、变量类型和分布选择正确的测试呢?
下面的图表总结了在选择正确的测试之前需要回答的问题。参考:明尼苏达大学。这里可以查。
什么是参数测试?
如果关于总体的信息通过其参数完全已知,则使用该方法,然后统计检验被称为参数检验。
参数测试的类型
1) t 检验
一个样本的 t 检验
t 检验比较不同组的两个平均值之间的差异,以确定该差异是否具有统计显著性
让我们以 hbs2 数据集为例。该数据集包含来自高中生样本的 200 个观察值。它有性别,社会经济地位,种族背景,学科分数,如阅读,写作,数学,社会研究。
在这里,我想测试一下写作平均分是否与 50 分有显著差异。
这里,p 值小于 0.05。因此,这个学生样本的变量 write 的平均值是 52.77,这与测试值 50 有显著的统计学差异。我们可以得出结论,这组学生在写作测试中的平均分明显高于 50 分。
两个样本的 t 检验
当两个独立的随机样本来自方差未知或相同的正态总体时使用。它分为两种类型
- 独立双样本 T 检验:
当您想要比较两个独立组的正态分布区间因变量的平均值时,可以使用独立样本 t 检验。换句话说,t 检验是为了比较两组之间相同变量的平均值。
在这里,我们想测试男性和女性的写作意义是否相同。(女性是具有 0 和 1 的变量(0 →男性,1 →女性)。该变量是进行独立组 t 检验所必需的,由类语句指定。
在我们的数据集中,我们比较了女学生组和男学生组的平均写作分数(在上面的代码中作为一个类提到,女性是一个变量(0 →男性,1 →女性)。这给出了两个可能不同的 t 统计量和两个不同的 p 值。p 值的解释与其他 t 检验相同。
从上面的方差等式中,p 值为 0.0187,小于 0.05,我们得出方差显著不同的结论。上述结果表明,男性和女性的平均写作成绩之间存在统计学上的显著差异(t = -3.73,p = .0003)。换句话说,从统计数据来看,女性的写作平均分(54.991)明显高于男性(50.121)。
2。配对双样本 t 检验
当您有两个相关的观察值(即,每个受试者有两个观察值)并且您想要查看这两个正态分布区间变量的平均值是否彼此不同时,可以使用该方法。
检查写作和阅读
p 值大于 0.05。上述结果表明,阅读的平均水平与写作的平均水平在统计上没有显著差异。
2) Z 检验
z 检验是一种应用正态分布的统计检验,主要用于处理频率大于或等于 30 的大样本问题。当总体标准差已知时使用。如果样本量小于 30,则 t 检验适用。
在 SAS proc 中,t-test 会考虑样本大小并相应地给出结果。SAS 中没有 z 测试的独立代码。
3)方差分析(ANOVA)
它是一组统计模型的集合,用于分析组均值或方差之间的差异。
单因素方差分析
当您有一个分类自变量(有两个或多个分类)和一个正态分布区间因变量,并且您希望测试因变量按自变量水平分解的均值差异时,可以使用单向方差分析(ANOVA)。
在 SAS 中使用 PROC ANOVA 完成
这里,我们将测试三种程序类型( prog )的写的含义是否不同。Prog 是一个类别变量。
因变量(写作)的平均值在不同的课程类型中有显著差异。然而,我们不知道这种差异是只存在于两个级别之间,还是存在于所有三个级别之间。我们还可以看到,学术项目(prog 2 水平->学术项目)的学生平均写作成绩最高,而职业项目的学生最低。(计划 1 的水平->职业)
双向方差分析
双向方差分析是一种有一个数字结果变量和两个分类解释变量的研究设计。
这里写为因变量,女性和社会经济地位(ses)为自变量。我们想检查女性和社会经济地位之间的书写差异。
这些结果表明,总体模型具有统计学意义(F = 8.39,p = 0.0001)。变量女性和 ses 具有统计学意义(分别为 F = 14.55,p = 0.0002 和 F = 5.31,p = 0.0057)。
4)皮尔逊相关系数(r)
当您想要查看两个(或多个)正态分布区间变量之间的线性关系时,相关性非常有用。
我们可以在数据集中运行两个连续变量读和写之间的关联
我们可以看到读和写的相关性为 0.59678。通过对相关性求平方,然后乘以 100,我们可以找出共有可变性的百分比。让我们将 0.59678 四舍五入为 0.6,其平方为 0.36,乘以 100 为 36%。因此读股约有 36%的可变性与写股相同。
我将在下一篇文章中解释非参数测试。
请继续学习,并关注更多内容!
参考:
测试时间增加(TTA)以及如何使用 Keras 进行测试
这里有很多方法可以通过改变我们训练神经网络的方式来改善它的结果。特别是,数据扩充是一种常见的做法,用于虚拟增加训练数据集的大小,也用作一种正则化技术,使模型对输入数据的微小变化更加稳健。
数据扩充是对输入数据随机应用一些操作(旋转、缩放、移动、翻转等)的过程。通过这种方式,模型永远不会显示两次完全相同的示例,并且必须学习他必须识别的类的更多一般特征。
Example of Data Augmentation on the CIFAR10 dataset
然而,也有一些方法可以通过改变我们测试它的方式来改善模型的结果,这就是测试时间增加 (TTA)发挥作用的地方…
什么是测试时间增加?
类似于数据扩充对训练集所做的,测试时间扩充的目的是对测试图像执行随机修改。因此,我们将多次显示增强图像,而不是只向训练模型显示一次常规的“干净”图像。然后,我们将平均每个相应图像的预测,并把它作为我们的最终猜测。
但是所有这些都将通过一个例子变得更加清晰。让我们以一个在 CIFAR10 上训练的神经网络为例,它呈现了以下测试图像:
The test image (a boat)
下面是模型的预测,表示为给定图像属于可能类别的置信度(最高分数对应于预测的标签):
这是这张图片的真实标签:
我们可以看到,模型在输出一个错误的答案,因为他最有信心图像属于第二类(对应汽车),但正确答案是第九类(对应船)。
如果我们增加测试时间,会发生什么?我们将呈现同一图像的 5 个稍微修改的版本,并要求网络预测它们中每一个的类别。
Modified version of the test image
以下是相应的预测:
Prediction 1
Prediction 2
Prediction 3
Prediction 4
Prediction 5
如您所见,只有预测 1 和预测 4 是正确的,并具有合理的可信度。2 只在很小的范围内是正确的,而 3 和 5 是不正确的。如果我们取这 5 个结果的平均值,会发生什么?
Average of the 5 predictions
现在我们可以看到,均值给出了正确的答案,具有合理的置信度。因此,我们现在有了一个正确的答案,而不是有一个错误的答案,就像原始测试图像的情况一样。
这种方法有效的原因是,通过对随机修改的图像平均我们的预测,我们也平均了误差。在单个向量中,误差可能很大,导致错误的答案,但是平均起来,只有正确的答案会突出。
测试时间增加对于模型非常不确定的测试图像特别有用。即使这 5 张图片看起来与你非常相似,但从模型的预测来看,它们是非常不同的。
如何搭配 Keras 使用?
测试时间增加可以很容易地与 Keras 一起使用,尽管在文档中没有明确提到。
第一步是创建一个真正简单的卷积神经网络,我们将在 CIFAR10 上对其进行训练以进行演示:
然后,我们可以通过使用 ImageDataGenerator 类 : 来定义我们想要在训练图像上执行的增强
我们现在可以为几个时期训练网络:
验证图像上模型的最终精度为:
为了增加测试时间,我们可以重用用于训练的同一数据生成器,并将其应用于验证图像。
然后,我们可以向模型显示 10 次(例如)随机修改的图像,获得每次的预测,并取平均值:
现在我们得到的精度是:
最终精度提高了超过 3% ,没有对模型做任何改动!
更多的数据扩充并不总是更好
虽然数据扩充是获得更好结果的非常有效的技术,但是必须明智地使用它。如果使用不当,它会损害模型的准确性。我会告诉你为什么会这样:
Bad data augmentation on MNIST
你能猜出每张图片中的数字吗?
给你个提示,图中没有 6…
你想做什么样的增强取决于你拥有的数据!在 MNIST 的例子中,你当然不希望进行随机翻转或太大的旋转,因为它们会完全改变图像的内容,6 可以翻转成 9,反之亦然,这使得你的模型很难学会区分这些类别。
然而,在像 CIFAR10 这样的数据库中,你完全想做水平翻转,因为它们不会改变图像,向右看或向左看的马仍然是马。但是在这里,垂直翻转也没有意义,因为您不太可能希望您的模型识别出一艘颠倒的船。
在某些情况下,如卫星成像或作物栽培图像,颠倒的图像不会改变它们的含义,您可以使用大旋转和垂直翻转作为数据扩充。
总之,只要你明智地使用,数据扩充既可以用于在训练时提升你的模型的结果,也可以用于测试时。
不要犹豫,试试 ImageDataGenerator 参数,看看它如何影响您的结果!
我希望这篇文章对新的深度学习实践者来说是清晰和有用的,并且它让你对什么是测试时间增加有了很好的了解!如果有不清楚的地方,请随时给我反馈或问我问题。
代码可从以下网址获得:
在 GitHub 上创建一个帐户,为纳坦胡本斯/TTA-喀拉斯的发展做出贡献。
github.com](https://github.com/nathanhubens/TTA-Keras)
使用偏度和峰度检验正态性
PDF of the Normal distribution (Source: Wikimedia Commons under CC0)
…以及使用综合 K 平方和Jarque–Bera 正态性测试的分步指南
我们将讨论以下 4 个主题:
- 什么是常态,为什么要关心常态?
- 什么是偏度和峰度以及如何使用它们来测试正态性?
- 如何使用两种非常常用的正态性检验,即基于偏度和峰度的综合 K 平方检验和Jarque–Bera 检验。
- 如何将这些测试应用于真实世界的数据集,以决定OrdinaryLeastSquares 回归是否是该数据集的合适模型。
快速提示
要直接进入显示如何测试正态性的 Python 代码,向下滚动到名为 Example 的部分。
文章中使用的数据集可以从这个链接下载。
什么是常态?
正态性意味着你的数据遵循正态分布。具体来说,中的每一个值 y_i 都是某个正态分布随机变量 N( _i , σ_i) 的“实现”,如下:
A normally distributed response variable Y (Image by Author)**
线性回归背景下的正态性
在建立线性回归模型时,假设 Y 依赖于回归变量的矩阵这使得 Y 在*【X .上有条件正常如果**X =【X _ 1,x_2,…,X _ n】*与 联合
In linear regression, Y is conditionally normally distributed on the rmatrix of regressors X
为什么要测试常态?
一些统计技术和模型假设基础数据是正态分布的。
我将给出以下三种常态抬头的情况:
- 如上图所示,在OdL东 S 方( OLS )回归中, Y 是有条件的正常对回归变量X:Y是正常的,如果X =【x_1,X _ 1 但是,即使 Y 不是正态分布,你的 OLS 模型也不会发生任何不好的事情。********
- 经典线性回归模型的一个不太严格的要求是,回归的残差'''应该是期望值为零的正态分布*,即 e(【ϵ)= 0。* 如果残差ϵ为非正态分布,则无法使用 t 分布可靠地计算模型预测的置信区间,尤其是对于小样本量(n ≤ 20)。****
请记住,即使误差不是正态分布的,只要 E(ϵ)=0 满足 OLSR 的所有其他要求,OLS 估计量仍然是模型的蓝色估计量,即线性估计量。
- 最后,某些拟合优度技术,如用于回归分析的 F 检验假设竞争回归模型的残差都是正态分布的。如果残差不是正态分布,f 检验不能可靠地用于比较两个竞争回归模型的拟合优度。
如何判断我的数据是否(不是)正态分布?
有几个统计测试可以用来测试你的数据偏离正态的程度,以及偏离是否有统计学意义。
在本文中,我们将查看基于矩的度量,即偏度和峰度,以及基于这些度量的显著性统计测试,即综合 K 和 Jarque — Bera 。
什么是“偏斜度”以及如何使用?
偏斜度允许您测试分布的总体形状与正态分布形状的偏离程度。
下图说明了偏态分布。
Positive and negative skewness (Source: Wikimedia Commons under CC BY-SA 3.0)
基于矩的偏斜度定义如下:
偏斜度被定义为概率分布的随机变量的第三个标准化中心矩。
人口的偏度公式如下所示:
Formula for population skewness (Image by Author)**
偏度有以下性质:
- 偏度是一个基于 矩 的度量(具体来说是三阶矩),因为它使用的是一个随机变量的三次方的期望值。
- 偏斜度是一个中心矩,因为随机变量的值是通过从平均值中减去它而被集中的。
- 偏斜度是一个标准化的矩,因为它的值是通过除以标准差的(的幂)而标准化的。****
- 因为是三阶矩,围绕平均值完全对称的概率分布将具有零偏斜度。这是因为,对于每个大于平均值的 y_i ,将有一个相应的 y_i 比平均值小相同的量。由于分布围绕平均值对称,两个 y_i 值将具有相同的概率。所以成对的 (y_i- ) 将相互抵消,总偏斜度为零。
- 正态分布的偏斜度为零。
- 虽然对称分布将具有零偏斜度,但是具有零偏斜度的分布不一定是对称的。
- 基于特定比率的分布 —最著名的柯西分布 — 具有未定义的偏斜度,因为它们具有未定义的均值。
实际上,我们可以通过计算样本的偏度来估计总体的偏度。对于样本,我们假设随机变量是均匀分布的,因此样本中每个 y_i 的概率是 1/n,第三个,中心的样本矩变成所有(y_i —y_bar)的简单求和的 1/n 倍。
Formula for sample skewness (Image by Author)**
偏斜度对概率分布的参数非常敏感。
下图说明了事件率参数λ的不同值的 泊松分布 的 P 概率 M ass F 函数的偏斜度:
Skewness of the Poisson(λ) distribution for various event rates (λ) (Image by Author)**
****对于大事件率,泊松 PMF 的偏斜度为什么会降低?对于较大的λ值,泊松分布的 PMF 接近正态分布的 PMF,均值和方差= λ。即泊松(λ) → N(λ,λ),为λ → ∞。因此,上图中所见绝非巧合。
当λ → ∞,泊松分布的偏斜度趋于正态分布的偏斜度,即 0。
还有其他偏斜度的度量,例如:
- 模式偏斜度
- 中位数的偏斜度
- 根据四分位值计算的偏斜度
- …还有一些其他的。
什么是峰度,如何使用它?
峰度是一种度量标准,用来衡量分布的尾部与正态分布的尾部相比有多不同。偏度侧重于整体形状,峰度侧重于尾部形状。
峰度定义如下:
峰度是概率分布的随机变量的第四个标准化中心矩。
峰度的公式如下:
Formula for population Kurtosis (Image by Author)**
峰度有以下性质:
- 就像偏度一样,峰度是基于矩的度量,它是一个中心的标准化矩。
- 因为是第四矩,峰度总是正的。
- 峰度对尾部偏离正态性很敏感。由于 4 次幂,上式中集中值 (y_i- ) 的较小值被大大削弱。换句话说,位于分布中心附近的 Y 值不被强调。相反, (y_i- ) 的较大值,即位于分布的两个尾部的值,由 4 次方大大强调。这个性质使得峰度在很大程度上不知道位于分布中心的值,并且使得峰度对位于分布尾部的值敏感。
- 正态分布的峰度为 3.0 。在测量偏离正态性时,峰度有时表示为过度峰度,即峰度减去 3.0 后的余额。
对于一个样本,过度峰度是通过将第四中心样本矩除以样本标准差的四次方,然后减去 3.0 来估计的,如下所示:**
Formula for sample excess Kurtosis (Image by Author)**
这里有一张来自维基共享的优秀图片,展示了各种分布的过度峰度。我在图像的左上方叠加了一个放大版的尾巴:
Excess Kurtosis of various distributions (Source: Wikimedia Commons under CC0)
基于偏度和峰度的正态性检验
虽然偏度和峰度量化了偏离正态性的量,人们可能想知道这种偏离在统计上是否显著。下面两个测试让我们做到了这一点:
- 综合 K 平方检验
- Jarque–Bera 测试
在这两个测试中,我们从以下假设开始:
- 零假设( H_0):数据为正态分布。
- 交替假设 (H_1):数据不是正态分布,换句话说,由检验统计量测量的偏离正态性在统计上是显著的。
综合 K 平方正态性检验
综合检验将偏斜度和峰度的随机变量组合成一个单一的检验统计量,如下所示:
Formula for the Omnibus K-squared test statistic (Image by Author)**
检验统计量的概率分布: 在上述公式中,函数 Z1() 和 Z2() 意在使随机变量 g1 和 g2 近似正态分布。这又使得它们的平方和近似为卡方(2) 分布,从而使得综合 K 平方的统计量近似为卡方(2) 分布** 假设零假设为真,即数据是正态分布的。****
jar que–Bera 正态性检验
该测试的测试统计如下:
Formula for the Jarque-Bera test statistic (Image by Author)**
检验统计量的概率分布: 检验统计量是各自近似正态分布的随机变量 g1 和 g2 的缩放平方和,从而使得 JB 检验统计量近似为卡方(2)分布,假设原假设为真。
例子
我们将使用来自美国劳工统计局的以下数据集来说明正态性检验的应用:
Source: Wages and salaries (series id: CXU900000LB1203M). U.S. Bureau of Labor Statistics (Image by Author)**
以下是数据集的前几行:
(Image by Author)**
你可以从这个链接下载数据。
让我们用下面的 OLS 回归模型来拟合这个数据集:
工资=β_ 0+β_ 1年份****+ϵ*
其中:
是因变量 , 是回归变量 ,
β_0 是回归的截距, β_ 1是回归系数,
我们将使用 Python 库 pandas 和 statsmodels 来读取数据,并为这些数据构建和训练我们的 OLS 模型。
让我们从导入所需的包开始:
****import** pandas **as** pd**import** statsmodels.formula.api **as** smf**import** statsmodels.stats.api as sms**from** statsmodels.compat **import** lzip**import** matplotlib.pyplot **as** plt**from** statsmodels.graphics.tsaplots **import** plot_acf**
将数据读入熊猫数据框:
**df = pd.read_csv(**'wages_and_salaries_1984_2019_us_bls_CXU900000LB1203M.csv'**, header=0)**
剧情工资对比年份:**
**fig = plt.figure()plt.xlabel('Year')plt.ylabel('Wages and Salaries (USD)')fig.suptitle('Wages and Salaries before taxes. All US workers')wages, = plt.plot(df['Year'], df['Wages'], 'go-', label='Wages and Salaries')plt.legend(handles=[wages])plt.show()**
Source: Wages and salaries (series id: CXU900000LB1203M). U.S. Bureau of Labor Statistics (Image by Author)**
用 patsy 语法创建回归表达式。在下面的表达式中,我们告诉 statsmodels 说工资是响应变量,而年是回归变量。statsmodels 会自动将截距添加到回归方程中。**
**expr = 'Wages ~ Year'**
通过传递模型表达式来配置 OLS 回归模型,并在数据集上训练模型,所有这些都在一个步骤中完成:
**olsr_results = smf.ols(expr, df).fit()**
打印模型摘要:
**print(olsr_results.summary())**
在下面的输出中,我指出了我们的 OLS 模型对数据适用性的吉兆和凶兆区域:
Summary of OLS regression model (Image by Author)**
解释结果
以下是从结果中需要注意的一些事情:
- 残差是正偏斜的,偏斜度为 0.268,并且它们还具有 2.312 的过度正峰度,即较厚的尾部。
- 综合测试和 JB 测试都产生了测试统计值(分别为 1.219 和 1.109),它们位于卡方(2) PDF 的 H_0 接受区内(见下图)。因此我们将接受假设 h0,即残差是正态分布的。
Acceptance and rejection zones for the Null hypothesis in the Chi-squared(2) PDF for two-tailed α=0.05 (Image by Author)**
- 您还可以获得偏度值、过度峰度值以及综合测试和 JB 测试的测试统计值,如下所示:
**name = ['Omnibus K-squared test', 'Chi-squared(2) p-value']#Pass the residual errors of the regression into the test
test = sms.**omni_normtest**(olsr_results.resid)lzip(name, test)#Prints out the following:
> [('**Omnibus K-squared test**', 1.2194658631806088), ('**Chi-squared(2) p-value**', 0.5434960003061313)]name = ['Jarque-Bera test', 'Chi-squared(2) p-value', 'Skewness', 'Kurtosis']test = sms.**jarque_bera**(olsr_results.resid)lzip(name, test)#Prints out the following:
[('**Jarque-Bera test**', 1.109353094606092), ('**Chi-squared(2) p-value**', 0.5742579764509973), ('**Skewness**', 0.26780140709870015), ('**Kurtosis**', 2.3116476989966737)]**
- 由于残差似乎呈正态分布,我们也可以相信模型报告的两个模型参数的 95%置信水平。
- 我们也可以相信 f 检验的 p 值。它非常小,表明这两个模型参数也共同显著。**
- 最后,模型报告的 R 平方相当高,表明模型与数据拟合得很好。
****现在是坏的部分:Durbin-Watson 测试和残差的条件数都表明残差是自相关的,特别是在滞后 1 时。
我们可以通过残差的 ACF 图轻松确认这一点:
**plot_acf(olsr_results.resid, title='ACF of residual errors')plt.show()**
ACF plot of residual errors (Image by Author)**
这给我们提出了一个问题:经典线性回归模型的一个基本要求是残差不应该是自相关的。在这种情况下,他们肯定是如此。这意味着 OLS 估计器可能低估了训练数据中的方差,这又意味着它的预测将偏离很大一部分。
简单地说,OLS 估计器不再是模型的 T2 蓝色估计器。真扫兴。
残差的自相关指出了一种可能性,即我们的模型被错误地选择或错误地配置。特别是,**
- 我们可能遗漏了一些关键的解释变量,导致一些信号以自相关的形式泄漏到残差中,或者,
- 对这个数据集来说,选择 OLS 模型本身可能是完全错误的。我们可能需要寻找替代模型。
在这种情况下,您的选择是接受所选模型的次优性,并解决上述两个次优性的原因。
摘要
- 一些统计程序假设基础数据遵循正态分布。
- 偏度和峰度是两个基于矩的度量,将帮助您快速计算偏离正态的程度。
- 除了使用偏度和峰度、之外,您还应该使用综合 K 平方和 Jarque-Bera 测试来确定偏离正态的数量是否具有统计显著性。
- 在某些情况下,如果数据(或残差)不是正态分布的,您的模型将是次优的。
感谢阅读!如果你喜欢这篇文章,请关注我的Sachin Date获取关于时间序列分析和预测的技巧、方法和编程建议。
测试胶水 Pyspark 作业
设置你的环境,这样你的 Glue PySpark 作业就可以读取和写入一个模仿的 S3 桶,这要感谢 moto 服务器。
Photo by Scott Sanker on Unsplash
挑战
胶合作业的典型用例是:
- 你阅读来自 S3 的数据;
- 你对这些数据进行一些转换;
- 你把转换后的数据传回 S3。
当编写 PySpark 作业时,用 Python 编写代码和测试,并使用 PySpark 库在 Spark 集群上执行代码。但是我如何让 Python 和 Spark 用同一个被嘲笑的 S3 桶进行通信呢?
在本文中,我将向您展示如何设置一个模拟的 S3 桶,您可以从 python 进程以及 Spark 集群访问它。
测试环境
创建粘合作业的先决条件
我们用的是 Glue 1.0 ,也就是 Python 3.6.8,Spark/PySpark 2.4.3,Hadoop 2.8.5。
确定;
- 你已经安装了python 3 . 6 . 8;
- 你已经安装了 JavaJDK 8;
- 您已经安装了用于 hadoop 2.7 的 spark 2.4.3。
注意 : Glue 使用 Hadoop 2.8.5,但是为了简单起见,我们使用 Hadoop 2.7,因为它是 Spark 2.4.3 附带的。
Python 依赖性
pipenv --python 3.6
pipenv install moto[server]
pipenv install boto3
pipenv install pyspark==2.4.3
PySpark 代码使用了一个模仿的 S3 桶
如果您遵循了上述步骤,您应该能够成功运行以下脚本:
import os
import signal
import subprocessimport boto3
from pyspark.sql import DataFrame
from pyspark.sql import SparkSession **# start moto server, by default it runs on localhost on port 5000.** process = subprocess.Popen(
"moto_server s3", stdout=subprocess.PIPE,
shell=True, preexec_fn=os.setsid
)**# create an s3 connection that points to the moto server.** s3_conn = boto3.resource(
"s3", endpoint_url="http://127.0.0.1:5000"
)
**# create an S3 bucket.** s3_conn.create_bucket(Bucket="bucket")**# configure pyspark to use hadoop-aws module.
# notice that we reference the hadoop version we installed.**
os.environ[
"PYSPARK_SUBMIT_ARGS"
] = '--packages "org.apache.hadoop:hadoop-aws:2.7.3" pyspark-shell'**# get the spark session object and hadoop configuration.** spark = SparkSession.builder.getOrCreate()
hadoop_conf = spark.sparkContext._jsc.hadoopConfiguration()**# mock the aws credentials to access s3.** hadoop_conf.set("fs.s3a.access.key", "dummy-value")
hadoop_conf.set("fs.s3a.secret.key", "dummy-value")
**# we point s3a to our moto server.** hadoop_conf.set("fs.s3a.endpoint", "http://127.0.0.1:5000")
**# we need to configure hadoop to use s3a.** hadoop_conf.set("fs.s3.impl", "org.apache.hadoop.fs.s3a.S3AFileSystem")**# create a pyspark dataframe.** values = [("k1", 1), ("k2", 2)]
columns = ["key", "value"]
df = spark.createDataFrame(values, columns)**# write the dataframe as csv to s3.** df.write.csv("s3://bucket/source.csv")**# read the dataset from s3** df = spark.read.csv("s3://bucket/source.csv")**# assert df is a DataFrame** assert isinstance(df, DataFrame)**# shut down the moto server.** os.killpg(os.getpgid(process.pid), signal.SIGTERM)print("yeeey, the test ran without errors.")
将上述代码复制粘贴到一个名为“py spark-mocked-S3 . py”的文件中,并执行:
*pipenv shell
python pyspark-mocked-s3.py*
输出将类似于:
*(glue-test-1) bash-3.2$ python pyspark-mocked-s3.py
* Running on [http://127.0.0.1:5000/](http://127.0.0.1:5000/) (Press CTRL+C to quit)...127.0.0.1 - - [28/Nov/2019 20:54:59] "HEAD /bucket/source.csv/part-00005-0f74bb8c-599f-4511-8bcf-8665c6c77cc3-c000.csv HTTP/1.1" 200 -
127.0.0.1 - - [28/Nov/2019 20:54:59] "GET /bucket/source.csv/part-00005-0f74bb8c-599f-4511-8bcf-8665c6c77cc3-c000.csv HTTP/1.1" 206 -yeeey, the test ran without errors.*
编写测试用例
上面脚本中显示的原则在我的 repotesting-glue-py spark-jobs中以更结构化的方式应用。
在这个 repo 中,你会发现一个 Python 文件, test_glue_job.py 。这个文件是 Glue PySpark 作业的一个测试用例的例子。它结合了上述逻辑和我写的一篇关于测试无服务器服务的文章中概述的原则。查看测试用例,并按照自述文件中的步骤运行测试。为了方便起见,我在下面添加了测试用例。
祝你好运!
https://gist.github.com/vincentclaes/5d78f3890a117c613f23e3539e5e3e5d
【https://stackoverflow.com/a/50242383/1771155
https://gist.github.com/tobilg/e03dbc474ba976b9f235
https://github . com/spulec/moto/issues/1543 # issue comment-429000739
测试无服务器服务
使用 moto 对 AWS lambda 函数进行 python 单元测试。
避免测试对于任何软件项目的成功都是至关重要的。如果您正在开发一个应用程序,您希望编写测试来检查您的应用程序的功能。通过测试,您可以添加新的特性或修复错误,并轻松地部署更改后的代码。没有测试,你将生活在一个充满不安全感和挫败感的世界里。
我们将使用 python 默认测试框架 unittest 和一个名为 moto 的 AWS 服务模拟工具来测试我们的 AWS lambda 的 python 功能。此外,我们将解释如何使用 AAA 模式 (Arrange,Act,Assert)来安排和格式化你的测试代码。
Photo by Battlecreek Coffee Roasters on Unsplash
Lambda 处理器逻辑
下面的代码是原始代码的一部分,它是一个名为“无服务器数据管道示例”的项目的一部分,是我之前写的教程的结果。这个处理程序的原始代码可以在我的 Github 上找到。
lambda 处理程序由 s3 事件触发。该事件是一个. eml 文件(电子邮件文件),它是在我们的 s3 bucket 的 unzip/文件夹中创建的。lambda 的配置和触发 lambda 的 s3 事件可以在项目的 serverless.yml 中的这里找到。
该事件以字典的形式作为第一个参数传递给我们的处理函数。我们从事件中获取桶名和 s3 键,它指向我们的电子邮件文件的位置。我们读取电子邮件文件,并将内容提取为 JSON 对象。JSON 对象被转储回 s3。从环境变量中检索目标桶和关键字。环境变量在 serverless.yml 文件中配置这里是。
测试 Lambda 处理器逻辑
从为项目中的测试创建一个结构开始。最简单的方法是模仿 tests 文件夹中的应用程序结构。你可以在这里找到一个例子:
.
├── serverless_data_pipeline
│ ├── lambda_function
│ │ ├── extract.py
└── serverless_data_pipeline_tests
└── lambda_function
└── test_extract.py
在 test_extract.py 模块中,我们有以下代码:
单元测试
为了测试我们的 lambda 处理程序的逻辑,我们将使用 unittest 。unittest 是 python 标准库的一部分,帮助您创建和运行单元测试。
测试用例
我们首先在 test_extract.py 文件中创建一个名为TestExtract
的类。我们的类继承自 unittest.TestCase。通过从 TestCase 继承,您可以访问有助于您的测试的函数。在一个测试用例中,以关键字“test”开头的方法被 unittest 测试运行器视为一个测试。您将在我们的示例中找到一个测试函数:
test_extract_the_contents_of_an_email_successfully(self):
提示:以你的测试函数的名义描述你正在测试的东西,让你自己和他人容易理解你正在测试的东西。
安装()和拆卸()
unittest 提供了一些函数,这些函数可以设置和拆除您的测试环境,而不需要在每次测试之前和之后显式调用它们。在我们的例子中,为了让我们的测试成功运行,我们需要必要的 s3 存储桶和一些环境变量。我们将此逻辑添加到 设置 功能中,并在执行测试之前调用设置功能。
def setUp(self):
os.environ[TestExtract.ENV_DEST_KEY] = TestExtract.DEST_KEY
os.environ[TestExtract.ENV_DEST_BUCKET] = TestExtract.DEST_BUCKET
conn = boto3.resource('s3')
conn.create_bucket(Bucket=TestExtract.SOURCE_BUCKET)
conn.create_bucket(Bucket=TestExtract.DEST_BUCKET)
测试运行后,我们要删除 s3 存储桶和环境变量。我们在 拆卸 函数中添加了该逻辑,并且每次测试完成时,都会执行拆卸函数。
def tearDown(self):
del os.environ[TestExtract.ENVIRON_DEST_KEY]
del os.environ[TestExtract.ENVIRON_DEST_BUCKET]
self.remove_bucket(TestExtract.SOURCE_BUCKET)
self.remove_bucket(TestExtract.DESTINATION_BUCKET)
摩托
我们希望在本地执行我们的功能,而不想与“真实的”AWS 环境交互。最好我们想与一个模拟的 AWS 环境互动。为了创建一个模拟的 AWS 环境,我们将使用 moto 。moto 是一个库,允许您的测试轻松模拟 AWS 服务。我们从 moto 继承了 mock_s3,并将其用作测试类的装饰器:
@mock_s3
class TestExtract(unittest.TestCase):
一旦将 mock_s3 设置为装饰器,通过 boto3 与 s3 的每一次交互都会被模仿。像这样,我们的测试可以离线运行,就像它们与 AWS 服务交互一样。
安排动作断言(AAA)
在测试函数中,我们测试内容是否从。eml 文件,并且内容作为 JSON 对象成功地转储到 s3 上。每个测试函数都是按照 安排、动作、断言(AAA) 原则构造的。
安排你的模拟 AWS 环境
首先,我们 安排 我们的环境以便执行我们的测试。如上所述,一般的设置和拆卸功能可以在设置和拆卸功能中完成。特定于测试的配置可以在测试函数本身中完成。
一旦创建了 s3 存储桶并在 setUp 函数中设置了环境变量,我们就通过读取一个. eml 文件并将该文件上传到 s3 来在我们的测试函数中安排特定于测试的环境。读取和上传发生在函数中
def put_email_to_s3(self, test_email_path, email_name):
执行您想要测试的功能
下一步是 act 通过执行我们想要测试的 lambda 处理函数。
s3_key_extracted_message = extract.handler(event, None)
我们看到我们的处理函数返回了一个 s3 键。在生产中,这个 s3 密钥没有被使用,也没有任何价值。我们返回这个值只是为了验证我们的测试是否如我们所期望的那样运行。
断言我们得到了预期的结果
一旦我们的处理函数运行,我们 断言 预期的结果已经出现。我们通过获取 lambda 处理程序返回的 s3 键并检查被模仿的 s3 桶是否包含预期的 JSON 对象来做到这一点。
我们从 s3 中读取对象,并断言 JSON 对象等于我们期望的对象。不要开始写自己的断言函数,unittest 有一堆高级断言方法,可以在这里找到。我们使用函数
self.assertDictEqual(json.loads(email_as_json), expected_json)
比较字典是否相等。
运行测试
要自己运行上面的示例,从克隆原始项目并安装依赖项开始:
git clone [git@github.com](mailto:git@github.com):vincentclaes/serverless_data_pipeline_example.gitcd serverless_data_pipeline_example
pipenv install
pipenv shell
要执行项目中的所有测试,请运行:
python -m unittest
它将运行测试用例的所有测试功能。测试应该通过,您应该看到输出“OK”。
bash-3.2$ . /Users/vincent/.local/share/virtualenvs/serverless_data_pipeline-27feO5HC/bin/activate
(serverless_data_pipeline) bash-3.2$ python -m unittest serverless_data_pipeline_tests/lambda_function/test_extract.py
email object {'id': 'test_extract_the_contents_of_an_email_successfully.eml', 'from': '[vclaes1986@gmail.com](mailto:vclaes1986@gmail.com)', 'to': '[vincent.v.claes@gmail.com](mailto:vincent.v.claes@gmail.com)', 'cc': '', 'subject': 'Hey how are you doing', 'date': '2019-07-09 13:42:54+02:00', 'body': '\nCash Me Outside How Bout Dah'}
.
----------------------------------------------------------------------
Ran 1 test in 0.185sOK
要运行一个单独的测试用例,您可以运行:
python -m unittest serverless_data_pipeline_tests.lambda_function.test_extract.TestExtract
要运行单个测试函数,您可以运行:
python -m unittest serverless_data_pipeline_tests.lambda_function.test_extract.TestExtract.test_extract_the_contents_of_an_email_successfully
如果您的所有测试都通过了,您就可以放心地将项目部署到 AWS 了。
祝你好运!
测试机器学习(ML)管道
说到数据产品,很多时候有一种误解,认为这些产品不能通过自动化测试。尽管管道的某些部分由于其实验性和随机性而无法通过传统的测试方法,但大部分管道可以。除此之外,更不可预测的算法可以通过专门的验证过程。
让我们看看传统的测试方法,以及如何将这些方法应用到我们的数据/ML 管道中。
测试金字塔
您的标准简化测试金字塔如下所示:
Image by author
这个金字塔是你为应用程序编写的测试类型的代表。我们从大量的单元测试开始,这些单元测试孤立地测试单个功能。然后,我们编写集成测试,检查将我们隔离的组件组合在一起是否如预期的那样工作。最后,我们编写 UI 或验收测试,从用户的角度检查应用程序是否按预期工作。
说到数据产品,金字塔并没有太大的不同。我们的水平差不多。
Image by author
请注意,UI 测试仍然会在产品中进行,但是这篇博文关注的是与数据管道最相关的测试。
让我们在一些科幻作家的帮助下,仔细看看在机器学习的背景下,这些都意味着什么。
单元测试
“这是一个测试你对宇宙的想法的系统,看看它们是否符合”艾萨克·阿西莫夫。
数据管道中的大部分代码由数据清理过程组成。每个用来清理数据的函数都有一个明确的目标。比方说,我们为我们的模型选择的特征之一是前一天和当天之间的值的变化。我们的代码可能看起来有点像这样:
def add_difference(asimov_dataset):
asimov_dataset['total_naughty_robots_previous_day'] =
asimov_dataset['total_naughty_robots'].shift(1)
asimov_dataset['change_in_naughty_robots'] =
abs(asimov_dataset['total_naughty_robots_previous_day'] -
asimov_dataset['total_naughty_robots']) return asimov_dataset[['total_naughty_robots',
'change_in_naughty_robots', 'robot_takeover_type']]
这里我们知道,对于给定的输入,我们期望得到一定的输出,因此,我们可以用下面的代码来测试这一点:
import pandas as pd
from pandas.testing import assert_frame_equal
import numpy as np def test_change():
asimov_dataset_input = pd.DataFrame({
'total_naughty_robots': [1, 4, 5, 3],
'robot_takeover_type': ['A', 'B', np.nan, 'A']
}) expected = pd.DataFrame({
'total_naughty_robots': [1, 4, 5, 3],
'change_in_naughty_robots': [np.nan, 3, 1, 2],
'robot_takeover_type': ['A', 'B', np.nan, 'A']
}) result = add_difference(asimov_dataset_input)
assert_frame_equal(expected, result)
对于每个独立的功能,您应该编写一个单元测试,确保数据转换过程的每个部分对数据都有预期的影响。对于每项功能,你还应该考虑不同的场景(是否有 if 语句?然后所有条件句都要考)。这些将在每次提交时作为持续集成(CI)管道的一部分运行。
除了检查代码是否如预期的那样,单元测试还在调试问题时帮助我们。通过添加一个测试来重现一个新发现的 bug,我们可以确保当我们认为那个 bug 被修复时,它就被修复了,并且我们可以确保这个 bug 不会再次发生。
最后,这些测试不仅检查代码做了预期的事情,还帮助我们记录我们在创建功能时的期望。
集成测试
因为“清澈的眼睛更好,无论它看到什么。”弗兰克·赫伯特。
这些测试旨在确定单独开发的模块在组合在一起时是否能按预期工作。就数据管道而言,它们可以检查:
- 数据清理过程会产生适合模型的数据集
- 模型训练可以处理提供给它的数据并输出结果(确保代码在将来可以重构)
因此,如果我们采用上面的单元测试函数,并添加以下两个函数:
def remove_nan_size(asimov_dataset):
return asimov_dataset.dropna(subset=['robot_takeover_type']) def clean_data(asimov_dataset):
asimov_dataset_with_difference = add_difference(asimov_dataset)
asimov_dataset_without_na = remove_nan_size(
asimov_dataset_with_difference) return asimov_dataset_without_na
然后我们可以用下面的代码测试组合 clean_data 中的函数是否会产生预期的结果:
def test_cleanup():
asimov_dataset_input = pd.DataFrame({
'total_naughty_robots': [1, 4, 5, 3],
'robot_takeover_type': ['A', 'B', np.nan, 'A']
})
expected = pd.DataFrame({
'total_naughty_robots': [1, 4, 3],
'change_in_naughty_robots': [np.nan, 3, 2],
'robot_takeover_type': ['A', 'B', 'A']
}).reset_index(drop=True) result = clean_data(asimov_dataset_input).reset_index(drop=True)
assert_frame_equal(expected, result)
现在让我们说,下一件事,我们做的是饲料上述数据到一个逻辑回归模型。
from sklearn.linear_model import LogisticRegression def get_reression_training_score(asimov_dataset, seed=9787):
clean_set = clean_data(asimov_dataset).dropna()
input_features = clean_set[['total_naughty_robots',
'change_in_naughty_robots']]
labels = clean_set['robot_takeover_type']
model = LogisticRegression(random_state=seed).fit(
input_features, labels) return model.score(input_features, labels) * 100
虽然我们不知道期望值,但是我们可以确保我们总是得到相同的值。对我们来说,测试这种集成以确保:
- 数据可由模型使用(每个输入都有一个标签,数据的类型由所选的模型类型接受,等等)
- 我们能够在未来重构我们的代码,而不会破坏端到端的功能。
我们可以通过为随机生成器提供相同的种子来确保结果总是相同的。所有主要的库都允许您设置种子(Tensorflow 有点特殊,因为它要求您通过 numpy 设置种子,所以请记住这一点)。该测试可能如下所示:
from numpy.testing import assert_equal def test_regression_score():
asimov_dataset_input = pd.DataFrame({
'total_naughty_robots': [1, 4, 5, 3, 6, 5],
'robot_takeover_type': ['A', 'B', np.nan, 'A', 'D', 'D']
})
result = get_reression_training_score(asimov_dataset_input,
seed=1234)
expected = 50.0 assert_equal(result, expected)
这类测试不会像单元测试那样多,但是它们仍然是你的 CI 管道的一部分。您将使用这些来检查组件的端到端功能,并因此测试更多的主要场景。
ML 验证
为什么?"表现出知道错误问题的答案是完全无用的."厄休拉·K·勒·古恩。
既然我们已经测试了我们的代码,我们还需要测试 ML 组件是否解决了我们试图解决的问题。当我们谈论产品开发时,ML 模型的原始结果(无论基于统计方法多么精确)几乎从来都不是期望的最终结果。在被用户或其他应用程序使用之前,这些结果通常与其他业务规则相结合。出于这个原因,我们需要验证模型解决了用户问题,而不仅仅是准确性/f1 分数/其他统计度量足够高。
这对我们有什么帮助?
- 它确保模型实际上帮助产品解决手头的问题
- 它确保模型产生的价值对行业有意义
- 它为所做的决定提供了一个额外的文档层,帮助工程师在过程的后期加入团队。
- 它以客户、产品经理和工程师同样理解的通用语言提供了产品 ML 组件的可见性。
这种验证应该定期运行(通过 CI 管道或 cron 作业),其结果应该对组织可见。这可确保组织能够看到数据科学组件的进展,并确保及早发现由变更或陈旧数据引起的问题。
结论
毕竟“魔法只是我们还不了解的科学”亚瑟·C·克拉克。
ML 组件可以通过多种方式进行测试,这为我们带来了以下优势:
- 产生了一种数据驱动的方法来确保代码做了预期的事情
- 确保我们可以在不破坏产品功能的情况下重构和清理代码
- 记录功能、决策和以前的错误
- 提供产品 ML 组件的进度和状态的可见性
所以不要害怕,如果你有技能来写代码,你就有技能来写测试,并获得以上所有的优势🙂
再见,感谢所有的测试!
原载于 2019 年 7 月 18 日【http://intothedepthsofdataengineering.wordpress.com。
从“金属乐队”到阿黛尔——R
其他都不重要
“我们没有争议”——这是一句拉丁语。
我们每个人都有自己对音乐的偏好,不同的背景让我们对不同的话题和感受产生共鸣,这可能就是*“在品味问题上,没有争议”的真理。然而,非常成功的艺术家很容易与平庸的艺术家区分开来。成功可以通过售出的唱片数量、在 Spotify 上的播放次数、在世界各地的门票销售一空等来衡量。*
下面的迷因从夸张的角度展示了两位非常成功的音乐人的歌词是如何完全不同的:
Figure 1: lyrics depth
本文不想支持碧昂斯或弗雷迪·墨丘利,而是调查在非常成功的音乐作品中使用的词语选择、抒情动机、主题和感情。
歌词对一个艺人的成功有什么影响吗,还是说这一切都是制作价值,朗朗上口,其他什么都不重要?
你为了钱做什么亲爱的
songlyrics.xlsx 数据集包含不同流派和时代的 6 位标志性人物的歌词,使用他们最畅销的专辑。它包括发行年份、艺术家、专辑、流派、售出的唱片数量和产生的收入,以及该专辑中每首歌曲的歌词。分析过程中使用了以下艺术家和专辑:
Table 1: Artists and albums
清理我的衣柜
数据集只需要轻微的数据清理:
- 在一些歌曲中,括号用来表示[独唱]、[合唱]或表演歌曲一部分的艺术家、[德瑞医生]等。这些将被删除。
- 需要转换成
tidytext
格式:每行一个 token (word)。 - 我们必须为无意义的词创建一个自定义的停用词词典,比如詹姆斯·海特菲尔德的*“耶”* s,阿姆的*“哟”* s,迈克尔杰克逊的*“马麻色,马麻萨,马麻库萨”* s
- 删除数字。
想开始点什么吗
让我们从使用dplyr
的count()
开始,找出最常用的单词:
Figure 2: most used words in the dataset
毫不奇怪,单词 love 是数据集中所有有意义的单词中使用最多的单词。将要和想要可能会被认为是停用词。像女孩、宝宝、心这样的词也是和爱情、关系这个话题联系在一起的。
下图显示了三位艺术家如何不同地使用词语:
Figure 3: Different word choices
不同流派代表使用的常用词不多。他们使用头、叫和男孩的比例相对相似,但金属乐队演唱关于被打破、自由和梦想的方式比阿姆或阿黛尔多。为了量化它们的差异,我们可以使用皮尔森相关性。阿黛尔和金属乐队的得分是 0.03,金属乐队和阿姆的得分是 0.09。
这是意料之中的,因为数据集跨越了 31 年(1980-2011),使用了 6 种不同的体裁。人们期望不同类型的音乐会有不同的词汇选择。
我们还可以检查每种体裁的词频有何不同:
Figure 4: Word frequencies by Genre
灵魂似乎是关于爱情和眼泪,说唱有很多诅咒,金属是关于斗争和苦难而雷鬼是关于爱情和人。听起来很准确。
这就是爱情
为了更深入地了解这些歌曲的成功之处,让我们通过加入一个情感词汇来研究它们是如何处理情感的。
首先,我们可以看到每个流派的平均情绪得分是多少。当金属触及我们的负面情绪时,雷鬼真的能让我们感到快乐吗?
Figure 5: average sentiment per Genre
“快乐”类型的结果正如预期的那样,但令人惊讶的是,摇滚比金属有更多的负面情绪,说唱超过了这两者。
为了更深入地挖掘这一现象,让我们看看对这一平均情绪有贡献的最有影响力的词。
Figure 6: Words contributing to sentiments per Genre
现在我们看到为什么说唱变成了最负面的,看看过多的脏话。它们可能会被视为停用词,但它们也有意义。我的假设是,如果这首歌包含许多来自 S-F-B 三角的词,它很可能不是关于一个快乐的话题。
还有一些用词不当:《摇滚》中的 shake 是关于跳舞/移动的(抖腿)),是一个比较中性的词。当然,在雷鬼, jam 这个词也不是负面的,一起演奏音乐有更多积极的意义。
独一无二的
我们可以使用 tf-idf 统计数据来量化每个流派的内容。它显示了一个词在一个流派的流派集合中对这个流派有多重要。
Figure 7: Highest tf-idf words per Genre
金属是相当直接的:我们看到像痛苦和挣扎这样的重要词汇,在其他流派中并不常见。流行和说唱就不那么有代表性了:tf-idf 最高的词都是他的歌名( billie 、 jean 、starting '、something、 thriller 等。),而 Slim Shady 则独特地提到了 Dre 博士和他自己(马歇尔)。雷鬼使用方言俚语,如 jah ,谈论运动和出埃及。摇滚是关于地狱、喝酒 ing,以及关于摇滚滚本身的歌唱。
内部斗争
使用潜在的狄利克雷分配,让我们看看这些歌曲的歌词中有哪些不同的主题。
Figure 8: Topic modeling using LDA
这些话题中的词汇选择再次暗示了它主要取决于音乐的类型,选择哪些词汇和讨论哪些话题。
第一个话题主要是关于享受生活,和一个女孩在恋爱,总体幸福。大多数单词与雷鬼最常用的单词相似。话题 6 是关于分手的,有心、时间、遇见、泪之类的词,大部分来自灵魂歌词。
当音乐停止时
这项分析只关注了 6 位艺术家和他们最畅销的专辑,以得出关于什么是成功的音乐作品的结论。结果肯定对艺术家本身有一些偏见,但我们仍然可以画出他们的词汇用法和主题。
一首歌的成功在很大程度上取决于它属于哪种类型。说唱、摇滚和金属歌曲往往有更多的负面信息,有时亵渎歌词,谈论作者的痛苦和挣扎。流行和灵魂乐歌手倾向于关注爱情和分手,使用更积极的词语,他们是关于关系的。
这种分析可以很容易地用更多的数据来重复,以得出关于音乐产业状况的更普遍的结论,并且包括不太成功的艺术家可以进一步揭示什么是成功的歌曲的主题,哪些词的选择和主题导致更高的销售额和收入。
出埃及记
该分析基于朱莉娅·西尔格和大卫·罗宾逊的作品,重点是他们的书《用 R 进行文本挖掘》。R 代码和数据集可以在 GitHub 上我的 NLP_songlyrics 资源库中找到。
特别感谢Eduardo ario de la Rubia在匈牙利中欧大学为我提供了这篇文章的基础知识。
使用 Azure Web Apps & Doccano 对预算进行文本注释
TLDR: 这篇文章讲述了如何在 Azure Web 应用上部署 Doccano ,以便为自然语言处理任务协同注释文本数据。
这篇文章的所有代码可以在这里找到:
[## aribornstein/Doccano4Azure
在 Azure 上一键部署 doccano。通过创建帐户为 aribornstein/Doccano4Azure 开发做贡献…
github.com](https://github.com/aribornstein/doccano4Azure)
什么是 Doccano?
Doccano 是一个开源工具,为文本分类、序列标记和序列对序列提供注释功能。
最近,我一直在对一个数据集进行注释以供共同参考,作为这项任务的一部分,我有时间评估了几个不同的文本注释平台。
大多数免费开源注释工具,如 Brat 和 Anafora,都不遵守现代 UX 原则。Doccano 是我见过的唯一一个具有现代 UX 体验的开源注释工具。虽然存在其他现代文本注释工具,如 Prodigy 和 LightTag 存在,但它们拥有非常昂贵的许可证。
Prodigy and Lighthead are expensive with Doccano we can annotate data at fraction of the cost
然而,为了合作,我们需要在某个地方托管网站,以使这个过程更容易。本教程将告诉你如何做。
什么是容器的 Web App?
Azure App Service 不仅为你的应用增加了微软 Azure 的强大功能,比如安全性、负载平衡、自动伸缩和自动化管理。您还可以利用它的 DevOps 功能,例如从 Azure DevOps、GitHub、Docker Hub 和其他来源、包管理、暂存环境、自定义域和 SSL 证书进行连续部署。
If the webservice is under 1GB and there is not much usage we can run the compute for free on Azure
步骤 1:将 Doccano 部署到 Azure 应用服务
如果您已有 Azure 订阅,只需点击下面的按钮进行自动部署,即可开始为您的数据添加注释。
Click the Deploy button above to get started!
否则,你可以在这里获得一个免费的 Azure 帐户,然后点击上面的部署按钮。
开始您的免费 Microsoft Azure 试用,并获得 200 美元的 Azure 点数,以任何方式使用。运行虚拟机…
azure.microsoft.com](https://azure.microsoft.com/offers/ms-azr-0044p/?WT.mc_id=medium-blog-abornst)
Fill in the config with admin details and deploy
步骤 2:导航到您的 Doccano 部署并登录
部署后,导航到以下 url,其中是您在上面选择的 appname。
https:// . azure websites . net/登录
例如,在我们上面的部署中,登录 url 应该是
https://doccana.azurewebsites.net/登录
这将带您进入 Doccano 登录页面,您可以使用您在部署中配置的 Admin_user 和 Admin_pass 登录。
现在你可以开始注释你自己的数据了,看看来自 Doccano github 的指令。以下步骤是从教程中一字不差地摘录下来的。
步骤 3 创建数据集
在这里,我们接受了一个科幻小说的 NER 注释任务,给你一个关于 doccano 的简短教程。
下面是一个 JSON 文件,包含了许多不同语言的科幻小说描述。我们需要注释一些实体,比如人名、书名、日期等等。
books.json
{"text": "The Hitchhiker's Guide to the Galaxy (sometimes referred to as HG2G, HHGTTGor H2G2) is a comedy science fiction series created by Douglas Adams. Originally a radio comedy broadcast on BBC Radio 4 in 1978, it was later adapted to other formats, including stage shows, novels, comic books, a 1981 TV series, a 1984 video game, and 2005 feature film."}
{"text": "《三体》是中国大陆作家刘慈欣于 2006 年 5 月至 12 月在《科幻世界》杂志上连载的一部长篇科幻小说,出版后成为中国大陆最畅销的科幻长篇小说之一。2008 年,该书的单行本由重庆出版社出版。本书是三体系列(系列原名为:地球往事三部曲)的第一部,该系列的第二部《三体 II:黑暗森林》已经于 2008 年 5 月出版。2010 年 11 月,第三部《三体 III:死神永生》出版发行。 2011 年,“地球往事三部曲”在台湾陆续出版。小说的英文版获得美国科幻奇幻作家协会 2014 年度“星云奖”提名,并荣获 2015 年雨果奖最佳小说奖。"}
{"text": "『銀河英雄伝説』(ぎんがえいゆうでんせつ)は、田中芳樹によるSF 小説。また、これを原作とするアニメ、漫画、コンピュータゲーム、朗読、オーディオブック等の関連作品。略称は『銀英伝』(ぎんえいでん)。原作は累計発行部数が1500 万部を超えるベストセラー小説である。1982 年から2009 年 6 月までに複数の版で刊行され、発行部数を伸ばし続けている。"}
创建一个项目
我们需要为此任务创建一个新项目。使用超级用户帐户登录。
要创建您的项目,请确保您在项目列表页面中,然后单击Create Project
按钮。对于本教程,我们将项目命名为sequence labeling for books
,编写一些描述,选择序列标签项目类型,并选择我们创建的用户。
导入数据
创建项目后,我们会看到“导入数据”页面,或者点击导航栏中的Import Data
按钮。我们应该会看到以下屏幕:
我们选择 JSON 文件books.json
来上传。上传数据集文件后,我们会看到Dataset
页面(或者点击左边栏的Dataset
按钮列表)。此页面显示我们在一个项目中上传的所有文档。
定义标签
点击左边栏的Labels
按钮定义我们自己的标签。我们应该会看到标签编辑器页面。在标签编辑器页面中,您可以通过指定标签文本、快捷键、背景颜色和文本颜色来创建标签。
至于教程,我们创建了一些与科幻小说相关的实体。
第六步注释
接下来,我们准备注释文本。只需点击导航栏中的Annotate Data
按钮,我们就可以开始注释文档了。
导出数据
在注释步骤之后,我们可以下载带注释的数据。点击导航栏中的Edit data
按钮,然后点击Export Data
。您应该会看到下面的屏幕:
这里我们选择 JSON 文件,通过点击按钮来下载数据。下面是我们辅导项目的注释结果。
sequence_labeling_for_books.json
{"doc_id": 33, "text": "The Hitchhiker's Guide to the Galaxy (sometimes referred to as HG2G, HHGTTGor H2G2) is a comedy science fiction series created by Douglas Adams. Originally a radio comedy broadcast on BBC Radio 4 in 1978, it was later adapted to other formats, including stage shows, novels, comic books, a 1981 TV series, a 1984 video game, and 2005 feature film.", "entities": [[0, 36, "Title"], [63, 67, "Title"], [69, 75, "Title"], [78, 82, "Title"], [89, 111, "Genre"], [130, 143, "Person"], [158, 180, "Genre"], [184, 193, "Other"], [199, 203, "Date"], [254, 265, "Genre"], [267, 273, "Genre"], [275, 286, "Genre"], [290, 294, "Date"], [295, 304, "Genre"], [308, 312, "Date"], [313, 323, "Genre"], [329, 333, "Date"], [334, 346, "Genre"]], "username": "admin"}
{"doc_id": 34, "text": "《三体》是中国大陆作家刘慈欣于 2006 年 5 月至 12 月在《科幻世界》杂志上连载的一部长篇科幻小说,出版后成为中国大陆最畅销的科幻长篇小说之一。2008 年,该书的单行本由重庆出版社出版。本书是三体系列(系列原名为:地球往事三部曲)的第一部,该系列的第二部《三体 II:黑暗森林》已经于 2008 年 5 月出版。2010 年 11 月,第三部《三体 III:死神永生》出版发行。 2011 年,“地球往事三部曲”在台湾陆续出版。小说的英文版获得美国科幻奇幻作家协会 2014 年度“星云奖”提名,并荣获 2015 年雨果奖最佳小说奖。", "entities": [[1, 3, "Title"], [5, 7, "Location"], [11, 14, "Person"], [15, 22, "Date"], [23, 26, "Date"], [28, 32, "Other"], [43, 45, "Genre"], [53, 55, "Location"], [70, 75, "Date"], [126, 135, "Title"], [139, 146, "Date"], [149, 157, "Date"], [162, 172, "Title"], [179, 184, "Date"], [195, 197, "Location"], [210, 212, "Location"], [227, 230, "Other"], [220, 225, "Date"], [237, 242, "Date"], [242, 245, "Other"]], "username": "admin"}
{"doc_id": 35, "text": "『銀河英雄伝説』(ぎんがえいゆうでんせつ)は、田中芳樹によるSF 小説。また、これを原作とするアニメ、漫画、コンピュータゲーム、朗読、オーディオブック等の関連作品。略称は『銀英伝』(ぎんえいでん)。原作は累計発行部数が1500 万部を超えるベストセラー小説である。1982 年から2009 年 6 月までに複数の版で刊行され、発行部数を伸ばし続けている。", "entities": [[1, 7, "Title"], [23, 27, "Person"], [30, 34, "Genre"], [46, 49, "Genre"], [50, 52, "Genre"], [53, 62, "Genre"], [63, 65, "Genre"], [66, 74, "Genre"], [85, 88, "Title"], [9, 20, "Title"], [90, 96, "Title"], [108, 114, "Other"], [118, 126, "Other"], [130, 135, "Date"], [137, 144, "Date"]], "username": "admin"}
恭喜你!您刚刚掌握了如何在 Azure 上使用 doccano 进行序列标记项目。
如果您有任何问题、评论或希望我讨论的话题,请随时在 Twitter 上关注我。如果您认为我错过了某个里程碑,请告诉我。感谢 Hironsan 的惊人工作!
关于作者
亚伦(阿里)博恩施泰因 是一个狂热的人工智能爱好者,对历史充满热情,致力于新技术和计算医学。作为微软云开发倡导团队的开源工程师,他与以色列高科技社区合作,用改变游戏规则的技术解决现实世界的问题,然后将这些技术记录在案、开源并与世界其他地方共享。
基于文本的图卷积网络——圣经分类
一种基于半监督图的文本分类和推理方法
The most beautiful graph you have ever seen, courtesy of https://www.quora.com/Whats-the-most-beautiful-graph-you-have-ever-seen.
在本文中,我将详细介绍基于文本的图卷积网络(GCN)及其使用 PyTorch 和标准库的实现。基于文本的 GCN 模型是一种有趣而新颖的最新半监督学习概念,最近提出(扩展了之前由 Kipf 等人 *提出的 GCN 思想)。*在非文本数据上),能够在给定相关已知标注文本数据的情况下,非常准确地推断出一些未知文本数据的标注。
在最高级别,它通过将整个语料库嵌入到单个图中来实现,该图以文档(一些已标记,一些未标记)和单词作为节点,每个文档-单词&单词-单词边缘基于它们彼此之间的关系具有一些预定的权重(例如 Tf-idf)。然后,用具有已知标签的文档节点在该图上训练 GCN,然后使用训练的 GCN 模型来推断未标记文档的标签。
我们在这里使用圣经作为语料库实现基于文本的 GCN,选择圣经是因为它是世界上最受欢迎的书之一,并且包含丰富的文本结构。圣经(新教)由 66 本书(创世纪,出埃及记等)和 1189 章组成。这里的半监督任务是训练一个语言模型,该语言模型能够在给定其他章节的已知标签的情况下,对一些未标记章节所属的书籍进行正确分类。(由于我们实际上知道所有章节的确切标签,我们将有意屏蔽大约 10–20%章节的标签,这些标签将在模型推断过程中用作测试集,以测量模型准确性)
Structure of the Holy Bible (Protestant)
为了解决这个任务,语言模型需要能够区分与各种书籍相关联的上下文(例如,创世纪更多地谈论亚当和夏娃,而传道书谈论所罗门王的生活)。正如我们将在下面看到的,文本-GCN 模型所获得的良好结果表明,图结构能够相对较好地捕捉这种上下文,其中文档(章节)-单词边缘编码章节内的上下文,而单词-单词边缘编码章节之间的相对上下文。
关于图形神经网络的详细解释,你可以看看这篇伟大的文章https://Neptune . ai/blog/graph-neural-network-and-some-of-gnn-applications
这里使用的圣经文本(BBE 版本)是由https://github.com/scrollmapper/bible_databases提供的。
实现遵循基于文本的图卷积网络的论文(【https://arxiv.org/abs/1809.05679】T2
实现的源代码可以在我的 GitHub 库(【https://github.com/plkmo/Bible_Text_GCN】T4)中找到
如果你想在你自己的语料库上尝试文本 GCN,我已经创建了一个 NLP 工具包的最先进的模型,其中一个实现了文本 GCN,用于简单的文本分类(以及其他任务)。你可以在这里使用它(https://github.com/plkmo/NLP_Toolkit)。
代表语料库
Corpus represented as a graph. Red lines represent document-word edges weighted by TF-IDF, black lines represent word-word edges weighted by PMI.
在这篇论文之后,为了让 GCN 能够捕捉到章节的上下文,我们用节点和边构建了一个图,来表示章节和单词之间的关系。节点将由所有 1189 个章节(文档)加上整个词汇表(单词)组成,在它们之间有加权的文档-单词和单词-单词边。它们的重量 A_ij 由下式给出:
Edges weights
其中 PMI 是在滑动窗口 #W 上的同现词对之间的逐点互信息,我们将其固定为 10 个词的长度。 #W(i) 是包含单词 i 的语料库中滑动窗口的数量, #W(i,j) 是包含单词 i 和 j 的滑动窗口的数量,#W 是语料库中滑动窗口的总数。TF-IDF 是通常的词频——该词在文档中的逆文档频率。直观上,单词对之间的高正 PMI 意味着它们具有高语义相关性,相反,我们不会在具有负 PMI 的单词之间建立边。总的来说,TF-IDF 加权的文档-词边缘捕获文档内上下文,而 PMI 加权的词-词边缘(可以跨文档)捕获跨文档上下文。
相比之下,对于非基于图的模型,这样的跨文档上下文信息不容易作为输入特征提供,并且模型将不得不基于标签“从零开始”自己学习它们。由于在 GCN 提供了关于文档之间关系的附加信息,这在 NLP 任务中是绝对相关的,因此可以预期 GCN 会表现得更好。
- 计算 TF-IDF
df_data[“c”] is a Pandas dataframe containing the chapters text
计算 TF-IDF 相对简单。我们知道数学并理解它是如何工作的,所以我们只需在我们的 1189 文档文本上使用 sklearn 的 tfidf 矢量器模块,并将结果存储在数据帧中。当我们稍后创建图表时,这将用于文档单词权重。
2。计算单词之间的逐点互信息
计算单词间的 PMI 比较棘手。首先,我们需要在一个包含 10 个单词的滑动窗口中找到单词 i,j 之间的共现,该窗口存储为数据帧中的一个方阵,其中行和列代表词汇表。由此,我们可以使用前面的定义计算 PMI。上面显示了计算的注释代码。
3。构建图表
现在我们已经有了所有边的权重,我们准备构建图 G 。我们使用 networkx 模块来构建它。这里,值得指出的是,整个项目中用于数据处理的大部分繁重计算都花在了构建词-词边缘上,因为我们需要迭代大约 6500 个词的词汇表中所有可能的成对词组合。*幸运的是,有一种有效的方法来实现这一点,并且只需要大约 3 分钟就可以运行。*我们计算的代码片段如下所示。
Building the graph of nodes and weighted-edges
图卷积网络
在用于图像相关任务的卷积神经网络中,我们有卷积层或滤波器(具有可学习的权重),它们“越过”一串像素,以生成通过训练学习的特征图。现在,假设这些像素是你的图形节点,我们同样会有一组具有可学习权重的过滤器 W 来“忽略”GCN 中的这些图形节点。
然而,有一个大问题:图形节点并不像像素那样有一个清晰的物理空间和距离的概念(我们不能说一个节点在另一个节点的右边或左边)。因此,为了用我们的过滤器 W 有意义地卷积节点,我们必须首先为每个节点找到最好地捕获图结构的特征表示。对于高级读者,作者通过将每个节点的滤波器权重 W 和特征空间 X 投影到图的傅立叶空间来解决这个问题,这样卷积就变成了节点与特征的逐点乘法。为了深入探究这一推导,Kipf 等人的原始论文。是一个很好的起点。否则,读者可以将就这种直观的解释,并继续下去。
我们将在这里使用两层 GCN(特征被卷积两次),因为根据他们的论文,它给出了最好的结果。双层 GCN 后的卷积输出特征张量由下式给出:
在哪里
这里, A 是图 G 的邻接矩阵(对角元素为 1 表示节点的自连接)【D是G 的度矩阵。w0 和 w1分别是待训练的第一和第二 GCN 层的可学习滤波器权重。最终的输出然后被馈送到 softmax 层,该层具有交叉熵损失函数,用于用对应于 66 本书中的每一本的 66 个不同标签进行分类。
下面给出了 PyTorch 中两层 GCN 架构的实现。
GCN architecture, with Xavier’s initialization of W_0 (self.weight) and W_1(self.weight2) as well as biases.
培训阶段
Class label distribution
在总共 1189 个章节中,我们将在训练期间屏蔽其中 111 个章节(约 10 %)的标签。由于 1189 个章节的类别标签分布非常不均匀(见上图),因此我们不会屏蔽其总数小于 4 的章节的任何类别标签,以确保 GCN 可以从所有 66 个唯一类别标签中学习表示。
我们训练 GCN 模型来最小化未屏蔽标签的交叉熵损失。在对 GCN 进行 7000 个纪元的训练之后,我们将使用该模型来推断 111 个被屏蔽章节的图书标签,并分析结果。
结果
Loss vs Epoch
从上面的损失与历元图中,我们看到训练进行得很好,并在大约 2000 个历元时开始饱和。
Accuracy of training nodes (trained nodes) and inference accuracy of masked nodes (untrained nodes) with epoch.
随着训练的进行,可以看到训练精度以及(屏蔽节点的)推断精度一起增加,直到大约 2000 个时期,推断精度开始饱和在大约 50%。考虑到我们有 66 个类,如果我们假设该模型完全是随机预测的,那么它将具有 1.5 %的基线准确性,因此 50%的推断准确性看起来已经很好了。这告诉我们,在对已标记章节进行适当训练之后,GCN 模型能够在大约 50 %的时间内正确地推断出给定的未标记章节属于哪本书。
分类错误的章节
GCN 模型能够很好地捕捉文档内和文档间的上下文,但是对于分类错误的章节呢?这是否意味着 GCN 模式在这些方面失败了?让我们看看其中的几个来找出答案。
- 书:马太福音第 27 章:“到了早晨,众祭司长和长老商议,要把耶稣治死。他们就把他捆绑带走,交给官长彼拉多。卖耶稣的犹大见自己将要被杀,就后悔把那三十块钱拿给祭司长和长老说,我把一个义人交在你们手里,是有罪的。但他们说,那与我们何干?这是你的事。他就把银子放在殿里,出去,并且吊死了。祭司长拿着银子说,不可把它放在殿里,因为这是血的价。他们就定意用这银子买窑匠的一块田,作为埋葬外乡人的地方。所以那块田名叫……他从死里复活了。并且后来的错,比先前的更重了。彼拉多对他们说,你们有看守的人。去尽你所能保证它的安全。他们就去了,把他的尸首藏起来,放在石头上,看守的人也和他们在一起。
预言为:卢克
在这种情况下,马太福音第 27 章被错误地归类为路加福音。从上面,我们看到这一章是关于耶稣被祭司长处死,为我们的罪而死,以及犹大背叛耶稣后的罪。路加福音中也提到了这些事件。(在《马可福音》和《约翰福音》中也是如此)这很可能是为什么这个模型把它归类为《路加福音》的原因,因为它们有着相似的背景。
- 书:以赛亚书
第 12 章:“到那日,你必说,耶和华阿,我要称谢你;因为你虽然向我发怒,你的怒气却已转消,我也得了安慰。看哪,神是我的拯救。我要倚靠耶和华,并不惧怕。因为耶和华是我的力量,我的诗歌。他成了我的救星。你必从救恩的泉源欢欢喜喜地喝水。当那日,你们要说,你们要赞美耶和华,尊他的名为大。将他所行的传扬在万民中,称他的名被尊崇。向主歌唱;因为他行了奇事,要在全地传扬。锡安的居民哪,当扬声欢呼,因为在你们中间的以色列圣者,乃为至大。」
预言为诗篇
在这里,以赛亚书的第 12 章被错误地推断为来自诗篇。从这一段可以清楚地看出,以赛亚书第 12 章的叙述者谈到了赞美上帝,上帝是他的安慰者和拯救的源泉。赞美上帝并向他寻求安慰正是诗篇的整个主题,大卫在他的成功、试炼和苦难中写下了他对上帝的赞美和祈祷!因此,难怪模型会将它归类为诗篇,因为它们共享相似的上下文。
结论
基于文本的图卷积网络确实是一个强大的模型,特别是对于半监督学习,因为它能够强烈地捕捉单词和文档之间以及跨单词和文档的文本上下文,并在已知的情况下推断未知。
GCNs 的应用程序实际上相当健壮且影响深远,本文只是提供了它能做什么的一瞥。一般来说,除了这里提出的任务,GCN 可以在任何时候使用,只要你想结合图形表示和深度学习的力量。为了提供一些有趣的例子供进一步阅读,GCN 已经与【递归神经网络(RNNs) / 【长短期记忆(lst ms)】结合用于动态网络/节点/边缘预测。通过将人体关节建模为图形节点,将人体结构和时间帧之间和内部的关系建模为图形边缘,它还成功应用于人体骨骼的动态姿态估计。
感谢阅读,我希望这篇文章有助于解释其内部工作。
有用的链接
- 圣经文本上的文本——https://github.com/plkmo/Bible_Text_GCN 的 GCN 实现——
- 文本-通用语料库上的 GCN 实现(在其他自然语言处理任务中)——https://github.com/plkmo/NLP_Toolkit
参考文献
- 托马斯·n·基普夫,马克斯·韦林,带图卷积网络的半监督分类(https://arxiv.org/abs/1609.02907)(2016)
- 、成胜茂、罗原、用于文本分类的图卷积网络(https://arxiv.org/abs/1809.05679)(2018)
要了解最新的人工智能/数据科学趋势、论文和新闻,请查看我的@ follow AI _ bot(https://t.me/followai_bot),这是您的个性化人工智能/数据科学电报机器人。
文字可以很美
可视化如何发现文本数据中隐藏的模式
Modern Slavery Act filings: We will be building an interactive visualisation to uncover key trends and insights from a series of text documents. Words at the top right are common across the two industries analysed. Words at the bottom left are uncommon across the industries.
互联网上充斥着关于自然语言处理的文章。其中许多描述了如何建立分类系统,执行主题建模,问题回答。很少有人对文本语料库进行更全面的分析,更少有人展示如何以可视化、交互式和易于理解的格式构建输出。
在现实世界中,找到方法理解数据集中文本如何以及为什么不同通常要有用得多。接受客户评论;虽然根据内容预测评论评级可能有用,但更有价值的是了解为什么客户会对特定产品或服务给出正面或负面的评论。
这可以用来创建更有效的营销,通知未来的产品开发,甚至设计客户支持流程,以适应通过产品审查确定的问题。预测模型能做到所有这些吗?不,它不能。
在本帖中,我们将分析数千家公司的现代奴隶制回报,以了解企业正在做出哪些承诺来防止现代奴隶制,然后我们将使用先进的可视化技术来确定不同行业如何应对内部和供应链中的现代奴隶制风险。
一个重要的题外话:现代奴隶制
Shellfish Gathering is just one of many industries with a high inherent risk of Modern Slavery
如果您已经阅读了我以前在 Medium 上的帖子,您可能已经了解了正在使用的底层数据。这与 2015 年以来数千家英国和国际公司提交的现代奴隶制申报表有关。为什么要用这个数据?下面是一个重要的,如果忧郁,离题到现代奴隶制和防止它的措施。
现代奴隶制是一个大问题。据估计,仅在英国,每年就要花费纳税人 43 亿英镑。作为一种犯罪,它对受害者和社会的危害仅次于杀人。
“剥削和奴役世界各地和英国境内的男人、女人和儿童是最令人震惊的罪行之一,也是最有利可图的罪行之一。”
男爵夫人巴特勒-斯洛斯,2004 年前任上诉法院大法官
据估计,英国有 136,000 人(1/500)是现代奴隶制的受害者,自 2013 年以来,这一数字增长了 10 倍。与现代奴隶制有关的罪行令人憎恶。例子包括劳动剥削、性剥削、家庭奴役、摘取器官和犯罪剥削。
正在采取什么措施来防止它?
《2015 年现代奴隶制法案》旨在打击英国的现代奴隶制。该法案的一部分要求营业额超过 3600 万英镑的公司公布他们在业务和供应链中为防止现代奴隶制所做的工作。截至 2019 年 4 月,有 8700 份声明被标识为已发布。
但是公司实际在做什么呢?他们承诺什么?他们正在实施什么流程?不同的行业如何处理这个问题?
用空间确定公司承诺
为了了解公司正在积极做什么和承诺做什么,我们需要创造一种智能的方式来识别每一个现代奴隶制回归中的这种承诺。
典型的回报将包括许多不相关的信息,如公司背景和现代奴隶制法案。幸运的是,使用 SpaCy NLP 库,我们可以使用其强大的匹配功能过滤掉这些内容。
文本匹配的问题是,即使使用正则表达式这样的技术,它也会很快变得很麻烦。问题是在寻找一个简单的模式时,你需要考虑所有不同的短语组合。例如,我们感兴趣的是识别包含如下语句的短语:
"We are committed to..."
然而,下面的短语也会引起我们的兴趣,我们怎样才能在不为每个例子都写代码的情况下将它们包含在我们的分析中呢?
"We promise to"
"We have committed to"
"We will continue to"
"[COMPANY NAME] has committed to"
"[COMPANY NAME] has implemented"
词性匹配
SpaCy 中的匹配引擎允许您使用词性(POS)标签将短语匹配到特定模式,例如,我们可以过滤一系列词性标签,而不是搜索特定的单词:
PRON, VERB, VERB
这种匹配从《现代奴隶回归》的片段中识别出以下短语:
Even using a very simple POS filter we can identify phrases which denote commitments made from businesses in their Modern Slavery returns. The match here is highlighted in yellow.
SpaCy 甚至提供了一个在线工具来帮助构建和检查不同规则的结果:
创建一套产生良好结果的规则根本不需要很长时间。下面的代码实现了这些规则,并返回已识别结果的整个句子:
def collect_sents(matcher, doc, i, matches):
match_id, start, end = matches[i]
span = doc[start:end] # Matched span
sent = span.sent # Sentence containing matched span
# Append mock entity for match in displaCy style to matched_sents
# get the match span by ofsetting the start and end of the span with the
# start and end of the sentence in the doc
match_ents = [{
"start": span.start_char - sent.start_char,
"end": span.end_char - sent.start_char,
"label": "MATCH",
}]
matched_sents.append({"text": sent.text, "ents": match_ents})
matcher = Matcher(nlp.vocab)
#this type of pattern matching requires SpaCy >2.1:pattern = [{'POS': {'IN': ['PROPN', 'PRON']}, 'LOWER': {'NOT_IN': ['they','who','you','it','us']} },
{'POS': 'VERB', 'LOWER': {'NOT_IN': ['may','might','could']} },
{'POS': {'IN': ['VERB', 'DET']}, 'LOWER': {'NOT_IN': ['a']}}]
matcher.add("commit", collect_sents, pattern)pattern = [{'POS': {'IN': ['PROPN','PRON']}, 'LOWER': {'NOT_IN': ['they','who','you','it','us']} },
{'POS': 'VERB', 'LOWER': {'NOT_IN': ['may','might','could']}},
{'POS': 'ADJ'},
{'POS': 'ADP'}]
matcher.add("commit", collect_sents, pattern)
不同行业如何应对现代奴隶制?
现在,我们已经从公司提交的报告中筛选出一系列承诺和行动,这能告诉我们不同行业如何应对现代奴隶制?
在这个分析中,我们将使用由 Jason Kessler 开发的神奇的散射文本库。
这使用了一种简单而强大的方法来查找分隔两类文本的关键词和短语。然后,结果可以很容易地输出到交互式可视化。
下面的代码过滤了我们现代奴隶制回归到两个高风险行业:建筑业和零售业。然后,它创建一个文本语料库,用于散点文本可视化:
#select industries to compare:
ind1 = 'Specialty Retail'
ind2 = 'Construction & Engineering'#Filter into a new df with 3 columns one for industry, one for company and the third containing the text
ftr = (df['Industry'] == ind1) | (df['Industry'] == ind2)
df_corp = df.loc[ftr]
df_corp = df_corp[['Industry','Company','clean text']]#Create a scattertext corpus from the df:
corpus = st.CorpusFromPandas( df_corp,
category_col='Industry',
text_col='clean text',
nlp=nlp).build()
完成后,我们可以运行下面的来创建一个交互式的散射文本输出:
html = st.produce_scattertext_explorer(corpus,
category='Construction & Engineering',
category_name='Construction & Engineering',
not_category_name=ind1,
width_in_pixels=1600)
open("MS-Visualization.html", 'wb').write(html.encode('utf-8'))
HTML(html)
这会产生以下输出:
The output from comparing two industries Modern Slavery returns in ScatterText
该图按两个类别(在本例中为零售业和建筑业)绘制了单词分布图。右上角的单词在两个类别中都很常见,左下角的单词在两个类别中都不常见。
左上角和右下角的文字显示了这两个行业在反对现代奴隶制的方法上的主要区别。点击一个单词会显示它在语料库中的使用位置。这有助于找到特定单词和短语在一个行业中出现而在另一个行业中不出现的上下文和原因。完整的输出可以在本文末尾下载。
经过短短几分钟的分析,很容易发现这两个行业在处理现代奴隶制问题的方式上的显著差异(粗体项目代表图表中已经分析过的单词):
施工
- 建筑业已经有了关于质量管理( ISO 9001)和环境管理体系( ISO 14001)的规定。公司正在利用这些标准制定的流程来帮助应对现代奴隶制风险。
- 行业意识到分包商构成风险,但目前几乎没有对分包商实施检查或控制。
- 它更加重视内部员工。由人力资源部门和直线经理负责将流程落实到位以降低风险。
零售
- 零售业在方法上更多地面向外部;重视在高风险地区对供应商进行的审计 s (印度、中国和土耳其经常被归类为高风险国家)。
- 在零售业,人们更加关注供应链和直接供应商之外的映射,以了解供应网络的第一层下面是什么。很明显,一些公司在这方面比其他公司取得了更大的进步。
结束语:
能够浏览成千上万的文档并即时了解各行业趋势的价值是巨大的。它可用于:
- 突出最佳实践;
- 帮助将创新从一个行业带到其他行业;
- 找出在防止现代奴隶制方面做得不够的地方。
希望这篇文章有助于展示一些简单但强大的 NLP 和可视化技术可以打开非结构化数据中的洞见。
进一步阅读
下面的 Colab 笔记本包含了这篇文章中使用的所有代码:
[## 谷歌联合实验室
现代奴隶制分析
colab.research.google.com](https://colab.research.google.com/drive/1VIMd9jhpNgB9siYlTSFqjV62mMQQFx4K)
要查看交互式散射文本输出,请参见下面的嵌入内容:
[## MS-ScatterText.html
分散文本输出
drive.google.com](https://drive.google.com/open?id=1nNrw8UGboV3-RvMUWIXuQd16VOEa_pNz)
这是 NLP 关于现代奴隶制回归分析的迷你系列的一部分。要查看相关文章,请参见以下内容:
使用 ELMo 的深层语境化语言表示创建语义搜索引擎,以及为什么语境是…
towardsdatascience.com](/elmo-contextual-language-embedding-335de2268604) [## 增压词向量
一个在你的 NLP 项目中提升快速文本和其他单词向量的简单技术
towardsdatascience.com](/supercharging-word-vectors-be80ee5513d) [## 使用无监督的机器学习清理您的数据
清理数据不一定是痛苦的!这篇文章是一个如何使用无监督机器学习的快速例子…
towardsdatascience.com](/clean-your-data-with-unsupervised-machine-learning-8491af733595)
Python 中的文本分类
一个端到端的机器学习项目
学习用 Python 构建文本分类模型
本文是我将涵盖开发一个机器学习项目的整个过程的系列文章的第一篇。
在这篇文章中,我们集中在用 Python 训练一个监督学习文本分类模型。
写这些文章背后的动机如下:作为一名学习数据科学家,他已经使用数据科学工具和机器学习模型工作了相当长的时间,我发现互联网、书籍或文献中的许多文章通常都非常关注建模部分。也就是说,给我们一个特定的数据集(如果是监督学习问题,已经分配了标签),尝试几个模型并获得一个性能度量。这个过程到此结束。
但是在现实生活问题中,我认为用正确的超参数找到正确的模型只是任务的开始。当我们部署模型时会发生什么?它将如何应对新数据?这些数据看起来会和训练数据集一样吗?也许,会有一些我们需要的信息(缩放或功能相关的信息)?会有吗?用户会允许并理解与结果相关的不确定性吗?如果我们想成功地将基于机器学习的服务带给我们的最终用户,我们必须问自己这些问题。
出于这个原因,我开发了一个项目,涵盖了创建基于 ML 的服务的整个过程:获取原始数据并解析它,创建功能,训练不同的模型并选择最佳模型,获取新数据以提供给模型,并向最终用户显示有用的见解。
该项目包括创建一个实时 web 应用程序,该应用程序从几家报纸收集数据,并显示新闻文章中讨论的不同主题的摘要。
这是通过能够预测给定新闻文章类别的监督机器学习分类模型、从报纸获取最新新闻的网络搜集方法以及向用户显示所获得结果的交互式网络应用来实现的。
这可以看作是一个文本分类的问题。文本分类是在不同的商业问题中广泛使用的自然语言处理(NLP)应用之一。
这些文章的目标读者是已经对基本的机器学习概念有所了解的人(例如,知道什么是交叉验证以及何时使用它,知道逻辑回归和线性回归之间的区别等等)。但是,我将简要说明项目中涉及的不同概念。
github 回购可以在这里找到。它包括所有的代码和一个完整的报告。我不会在这篇文章中包含代码,因为它太大了,但是我会在需要的地方提供一个链接。
我将这个过程分为三个不同的岗位:
本帖涵盖第一部分:分类模型训练。我们将在以下步骤中介绍它:
- 问题定义和解决方法
- 输入数据
- 初始数据集的创建
- 探索性数据分析
- 特征工程
- 预测模型
1.问题定义和解决方法
正如我们已经说过的,我们正在讨论一个监督学习的问题。这意味着我们需要一个带标签的数据集,这样算法就可以学习数据中的模式和相关性。幸运的是,我们有一个可用的,但在现实生活中,这是一个关键的步骤,因为我们通常必须手动完成任务。因为,如果我们能够自动化标记一些数据点的任务,那么我们为什么需要一个分类模型呢?
2.输入数据
这个项目中使用的数据集是 BBC 新闻原始数据集。可以从这里下载。
它由来自 BBC 新闻网站的 2225 份文件组成,对应于 2004 年至 2005 年五个主题领域的故事。这些领域是:
- 商业
- 娱乐
- 政治
- 运动
- 技术
下载文件包含五个文件夹(每个类别一个)。每个文件夹都有一个*。每篇新闻文章的 txt* 文件。这些文件包括原始文本的新闻文章正文。
3.初始数据集的创建
此步骤的目的是获得具有以下结构的数据集:
我们用 R 脚本创建了这个数据集,因为包 readtext 简化了这个过程。剧本可以在这里找到。
4.探索性数据分析
通常的做法是进行探索性数据分析,以便从数据中获得一些见解。然而,到目前为止,我们还没有任何定义数据的特性。我们将在下一节中看到如何从文本中创建特征。特性工程),但是,由于这些特性的构造方式,我们不期望从分析它们中得到任何有价值的见解。为此,我们只进行了粗浅的分析。
在开发分类模型时,我们主要关心的一个问题是不同的类是否是平衡的。这意味着数据集包含每个类的大致相等的部分。
例如,如果我们有两个类,并且 95%的观察值属于其中的一个,一个总是输出多数类的哑分类器将有 95%的准确性,尽管它会使少数类的所有预测失败。
有几种处理不平衡数据集的方法。第一种方法是欠采样多数类和过采样少数类,以便获得更平衡的数据集。其他方法可以使用精度之外的其他误差度量,例如精度、召回或 F1 分数。稍后我们将详细讨论这些指标。
查看我们的数据,我们可以得到属于每个类别的观察值的百分比:
我们可以看到,类是近似平衡的,所以我们不会执行任何欠采样或过采样方法。然而,我们无论如何都会使用精度和召回率来评估模型性能。
另一个感兴趣的变量可以是新闻文章的长度。我们可以获得跨类别的长度分布:
我们可以看到,政治和科技文章往往更长,但并不显著。此外,我们将在下一节中看到,我们用来创建特征的方法会考虑并修正文章的长度。所以这对我们来说没什么大不了的。
EDA 笔记本可以在这里找到。
5.特征工程
特征工程是构建任何智能系统的基本部分。正如吴恩达所说:
“想出新功能既困难又耗时,需要专业知识。‘应用机器学习’基本上是特征工程。”
特征工程是将数据转换为特征以充当机器学习模型的输入的过程,以便高质量的特征有助于提高模型性能。
处理文本数据时,有几种方法可以获取表示数据的特征。我们将介绍一些最常见的方法,然后选择最适合我们需要的方法。
5.1.文本表示
回想一下,为了表示我们的文本,数据集的每一行都将是语料库的单个文档。根据我们选择的特征创建方法,列(特征)会有所不同:
- 字数统计向量
使用这种方法,每一列都是语料库中的一个术语,每个单元格都代表每个文档中每个术语的频率计数。
- TF–IDF矢量
TF-IDF 是表示一个术语在文档和整个语料库中的相对重要性的分数。 TF 代表词频, IDF 代表逆文档频率:
TF-IDF 值与单词在文档中出现的次数成比例增加,并被语料库中包含该单词的文档数量所抵消,这有助于调整某些单词通常更频繁出现的事实**。**
它还考虑了这样一个事实,即通过规范化 TF 术语(表示相对术语频率),一些文档可能比其他文档大。
这两种方法(单词计数向量和 TF-IDF 向量)通常被称为单词袋方法,因为句子中单词的顺序被忽略了。下面的方法更先进,因为它们以某种方式保留了单词的顺序和它们的词汇考虑。
- 单词嵌入
单词在向量空间中的位置是从文本中学习的,并且是基于当使用单词时该单词周围的单词。单词嵌入可以与应用迁移学习的预训练模型一起使用。
- 基于文本或基于自然语言处理的特征
我们可以手动创建我们认为在区分类别时可能很重要的任何特征(例如,单词密度、字符数或单词数等)。
我们还可以使用词性模型来使用基于 NLP 的特征,词性模型可以告诉我们,例如,一个单词是名词还是动词,然后使用词性标签的频率分布。
- 话题模型
潜在狄利克雷分配等方法试图通过词的概率分布来表示每个主题,这就是所谓的主题建模。
我们选择了 TF-IDF 向量来表示我们语料库中的文档。这次选举的动机是以下几点:
- TF-IDF 是一个简单的模型,它在这个特定的领域产生了巨大的成果,我们将在后面看到。
- TF-IDF 功能创建是一个快速过程,这将使我们在用户使用 web 应用程序时缩短等待时间。
- 我们可以调整特征创建过程(见下一段)来避免像过度拟合这样的问题。
使用此方法创建特征时,我们可以选择一些参数:
- N-gram 范围:我们能够考虑一元,二元,三元…
- 最大/最小文档频率:在构建词汇表时,我们可以忽略文档频率严格高于/低于给定阈值的术语。
- 最大特征:我们可以选择语料库中按词频排序的前 N 个特征。
我们选择了以下参数:
我们希望二元模型通过考虑文档中经常一起出现的单词来帮助提高我们的模型性能。我们已经选择了一个最小 DF 值等于 10,以排除在超过 10 个文档中不出现的极其罕见的单词,以及一个最大 DF 值等于 100%,以不忽略任何其他单词。之所以选择 300 作为最大特征数,是因为我们希望避免可能的过拟合,过拟合通常是由于与训练观察的数量相比,特征的数量太多而引起的。
正如我们将在接下来的章节中看到的,这些值使我们达到真正高精度的值,所以我们将坚持使用它们。然而,为了训练更好的模型,可以调整这些参数。
有一个重要的考虑需要提及。回想一下 TF-IDF 分数的计算需要存在一个文档语料库来计算逆文档频率项。因此,如果我们想一次预测一篇新闻文章(例如,一旦部署了模型),我们就需要定义这个语料库。
这个语料库是一组训练文档。因此,当从新文章中获取 TF-IDF 特征时,将仅为该新文章创建存在于训练语料库中的特征。
很容易得出这样的结论:当模型被部署时,训练语料与我们将要搜集的消息越相似,我们可能获得的准确性就越高。
5.2.文本清理
在从原始文本创建任何特征之前,我们必须执行一个清理过程,以确保模型中没有引入失真。我们遵循了以下步骤:
- **特殊字符清理:**特殊字符,如" \n "双引号必须从文本中删除,因为我们不期望它们有任何预测能力。
- 例如,我们会认为“书”和“书”是同一个单词,具有相同的预测能力。因此,我们把每一个字都写了下来。
- **标点符号:**字符如“?”, "!", ";"已被移除。
- **所有格代词:**此外,我们会期望“Trump”和“Trump 的”具有相同的预测能力。
- **词干化或词条化:**词干化是将派生单词还原到其词根的过程。引理化是将一个词简化为其引理的过程。这两种方法的主要区别在于,词汇化提供了现有的单词,而词干化提供了可能不是现有单词的词根。我们使用了一个基于 WordNet 的 Lemmatizer。
- **停用词:**像“what”或“the”这样的词没有任何预测能力,因为它们可能对所有文档都是通用的。因此,它们可能代表可以消除的噪声。我们已经从 nltk 包中下载了一个英语停用词列表,然后将它们从语料库中删除。
在这一点上,有一个重要的考虑事项必须要做。我们应该考虑到可能出现的失真,这些失真不仅出现在训练测试中,还会出现在运行 web 应用程序时收集的新闻文章中。
5.3.标签编码
机器学习模型需要数字特征和标签来提供预测。因此,我们必须创建一个字典来将每个标签映射到一个数字 ID。我们创建了这个映射方案:
5.4.列车-测试分离
在预测未知数据时,我们需要设置一个测试集来证明模型的质量。我们选择了一个随机分割,85%的观察值组成训练测试,15%的观察值组成测试集。我们将在训练数据中执行交叉验证的超参数调整过程,拟合最终模型,然后使用完全不可见的数据对其进行评估,以获得偏差尽可能小的评估指标。
完整详细的特征工程代码可在这里找到。
6.预测模型
6.1.超参数调整方法和模型
我们已经测试了几个机器学习模型,以找出哪一个可能更适合数据,并正确地捕捉点及其标签之间的关系。由于我们拥有的数据量不足,我们只使用了经典的机器学习模型,而不是深度学习模型,这可能会导致模型过度拟合,无法对看不见的数据进行很好的概括。
我们尝试了以下模型:
- 随机森林
- 支持向量机
- k 个最近邻居
- 多项式朴素贝叶斯
- 多项式逻辑回归
- 梯度推进
它们中的每一个都有多个超参数需要调整。在为每个模型定义最佳超参数集时,我们遵循了以下方法:
首先,我们已经决定了我们想要为每个模型调整哪些超参数,考虑到那些可能对模型行为有更大影响的超参数,并且考虑到大量的参数将需要大量的计算时间。
然后,我们定义了一个可能值的网格,并使用三重交叉验证(50 次迭代)执行了一个随机搜索。最后,一旦我们获得了具有最佳超参数的模型,我们已经使用以这些值为中心的三重交叉验证执行了网格搜索,以便在超参数空间中彻底搜索最佳性能组合。
我们遵循这种方法,因为通过随机搜索,我们可以覆盖每个超参数的更大范围的值,而不会导致真正高的执行时间。一旦我们缩小了每个设置的范围,我们就知道在哪里集中搜索,并明确指定要尝试的每个设置组合。
选择𝐾 = 3 作为随机搜索中的折叠数和 50 次迭代的原因来自于较短执行时间或测试大量组合之间的权衡。在选择流程中的最佳模型时,我们选择了准确性作为评估标准。
6.2.性能测定
在通过交叉验证对训练数据执行超参数调整过程并将模型拟合到该训练数据之后,我们需要在完全看不见的数据(测试集)上评估其性能。在处理分类问题时,有几个度量标准可用于深入了解模型的执行情况。其中一些是:
- 准确性:准确性度量测量正确预测与评估的实例总数的比率。
- Precision: precision 用于度量从一个肯定类中的所有预测模式中正确预测的肯定模式。
- 回忆:回忆被用来衡量被正确分类的积极模式的比例
- f1-得分:此指标表示召回率和精确度值之间的调和平均值
- ROC 曲线下面积(AUC):这是在各种阈值设置下对分类问题的性能测量。ROC 是概率曲线,AUC 代表可分性的程度或度量。它告诉我们一个模型在多大程度上能够区分不同的类。
这些度量被高度扩展并广泛用于二进制分类。然而,当处理多类分类时,它们变得更加复杂,难以计算和解释。此外,在这个特定的应用程序中,我们只希望正确预测文档。假阳性或假阴性的成本对我们来说是一样的。出于这个原因,我们的分类器是更具体还是更敏感对我们来说并不重要,只要它能正确地分类尽可能多的文档。因此,我们研究了比较模型和选择最佳超参数时的精度。在第一种情况下,我们计算了训练集和测试集的准确性,以便检测过度拟合模型。然而,我们还获得了每个模型的混淆矩阵和分类报告(计算所有类的精确度、召回率和 F1 值),因此我们可以进一步解释它们的行为。
6.3.最佳型号选择
下面我们展示了不同模型及其评估指标的摘要:
总的来说,我们为每个模型获得了非常好的精度值。我们可以观察到梯度增强、逻辑回归和随机森林模型似乎过拟合,因为它们具有极高的训练集精度,但测试集精度较低,因此我们将丢弃它们。
我们将在剩余的模型中选择 SVM 分类器,因为它具有最高的测试集精度,这实际上接近于训练集精度。SVM 模型的混淆矩阵和分类报告如下:
6.4.模型解释
在这一点上,我们已经选择了 SVM 作为我们进行预测的首选模型。现在,我们将通过分析错误分类的文章来研究它的行为,以便获得关于模型工作方式的一些见解,并且如果必要的话,思考添加到模型中的新特性。回想一下,虽然超参数调整是一个重要的过程,但开发机器学习项目时最关键的过程是能够从数据中提取良好的特征。
让我们举一个分类错误的文章的例子。它的实际类别是政治,尽管这个模型预测的是科技。
议员发出黑莓威胁
众议院议长迈克尔·马丁裁定,如果议员们在众议院使用黑莓手机,他们将被赶出下议院。
这 200 台掌上电脑可以用作电话、传呼机或发送电子邮件。这些设备在本周获得了新的关注,因为阿拉斯泰尔·坎贝尔用他的手机意外地向《新闻之夜》的一名记者发送了一条充满诅咒的信息。马丁先生透露,一些议员在辩论中一直使用他们的黑莓手机,他还警告议员们不要使用隐藏的耳机。
长期以来,在下议院使用电子设备是不被允许的。手机或寻呼机的声音会招致议长或副议长的强烈指责。议长主持下议院的辩论,负责确保议院的秩序,执行众议院的规则和惯例。他或她总是由同事们选择的议员,一旦被提名,就放弃所有政党的忠诚。
这篇文章谈的是下议院禁止黑莓手机的问题。它既涉及政治又涉及技术,所以这种错误分类是有道理的。
6.5.降维图
降维指的是将具有大量维度的一组数据转换成具有较少维度的数据的过程,以确保其简明地传达相似的信息。
降维技术在机器学习中有许多应用。其中之一是可视化。通过将维度空间减少到包含大部分信息的 2 或 3 维,我们可以绘制我们的数据点,并能够将一些模式识别为人类。
我们使用了两种不同的降维技术:
- 主成分分析:该技术依赖于获得数据矩阵的特征值和特征向量,并试图提供最少数量的变量,以保持最大的方差。
- t-SNE:t 分布随机邻居嵌入是一种概率技术,特别适用于高维数据集的可视化。它最小化两个分布之间的差异:测量输入对象的成对相似性的分布和测量嵌入中相应低维点的成对相似性的分布。
让我们画出结果:
我们可以看到,使用 t-SNE 技术更容易区分不同的类。虽然我们只使用了降维技术进行绘图,但我们可以使用它们来减少特征的数量,以支持我们的模型。由于通常大量的特征,这种方法在文本分类问题中特别有用。
6.6.预测条件概率
在进入网页抓取过程之前,我们还需要做一个额外的考虑。训练数据集的文章被标记为商业、娱乐、体育、科技和政治。但是我们可以想到不适合任何一个的新闻文章(例如,天气新闻文章)。由于我们已经开发了一个监督学习模型,这类文章会被错误地归类到 5 类中的一类。
此外,由于我们的训练数据集的日期是 2004-2005 年,因此在搜集最新文章时可能会出现许多新概念(例如,技术概念),但这些概念不会出现在训练数据中。同样,我们预计在这些情况下预测能力很差。
许多分类模型不仅提供某个数据点所属的类别。它们还可以提供属于𝐶.类的条件概率
例如,当我们有一篇明确谈论政治的文章时,我们期望属于政治类的条件概率非常高,而其他 4 个条件概率应该非常低。
但是当我们有一篇关于天气的文章时,我们期望所有条件概率向量的值都一样低。
因此,我们可以用这种思路指定一个阈值:如果最高条件概率低于阈值,我们将为文章提供无预测标签。如果更高,我们会分配相应的标签。
经过一个简短的研究,探索不同的文章,可能不属于任何 5 个类别,我们已经固定在 65%的阈值。
有关模型培训流程所有步骤的更多详情,请访问此链接。
在这一点上,我们已经训练了一个模型,它将能够对我们输入的新闻文章进行分类。我们离构建我们的应用又近了一步!
信息自由请求的文本分类:第一部分
使用机器学习来预测市政当局的决策。
根据《信息自由和隐私保护法》(FIPPA),加拿大安大略省有义务对信息请求做出回应。更具体地说,《市政信息自由和隐私保护法》允许任何年龄、任何地点的人发出这样的请求。与个人相关的信息可能包括印刷品、胶片、电子邮件、图纸、照片等。只要发布的内容不侵犯另一个人的隐私权。在本帖中,我们将尝试预测一个市政当局做出的决定,即安大略省基奇纳-滑铁卢(第一部分)和后来的多伦多(第二部分)。
所使用的数据在每个城市的开放数据门户下提供。任何识别信息都已被删除。
使用有限的 Kitchener-Waterloo 数据集将允许我们基线化一些度量标准和原型化我们的技术。这些数据通过 API 提供,涵盖 1992 年至 2016 年。
一旦所有数据都被汇总并转换成熊猫数据框架,我们需要更仔细地看看我们有什么。可能的“决定”如下:
全部公开 238
部分免除 197
撤回 116
无记录存在 54
部分公开的信息 50
部分不存在 32
未公开 28
无记录存在 21
全部公开 16
转发出去 15
放弃 13
全部公开 13
无响应记录存在 11
更正被拒绝 3
不存在 3
已披露 2
已转移 1
未披露信息 1
已提交不同意声明 1
不存在额外记录 1
批准更正 1
请求撤销 1
在可能的决定中,显然有一些重叠,共有 24 项。虽然可以(并且已经)在不太长的时间内手动合并这些类,但是如果有数百个这样的类,只是在空格的存在(或不存在)上有所不同呢?还是一个 s?还是以资本化的方式?SeatGeek 开发的 python 包 fuzzywuzzy 非常适合这种类型的模糊字符串匹配。
该软件包提供了四种方法来探测两个字符串的相似性。本质上,“fuzz_ratio”比较整个字符串,“fuzz_partial_ratio”在字符串中搜索部分匹配,“fuzz_token_sort_ratio”比较无序的字符串,“fuzz_token_set_ratio”将标记排序扩展到更长的字符串。每一个都返回一个相似率(越高越相似),之后可以在可接受的截止点设置一个阈值。让我们测试一下每一个的性能。
from fuzzywuzzy import fuzzall_df_clean = all_df.copy()for row in all_df['Decision'].unique():
for row2 in all_df['Decision'].unique():
matching_result = fuzz.ratio(row, row2) # could be ratio, partial_ratio, token_set_ratio, token_sort_ratio
if matching_result > 80:
#print(row, row2)
#print(matching_results)
#Combine if match found
all_df_clean['Decision'][all_df_clean['Decision'] == row2] = row
print(all_df_clean['Decision'].value_counts())
print(len(all_df_clean['Decision'].unique()))
全部披露 240
部分豁免 197
撤回 116
无记录存在 75
部分披露的信息 50
部分不存在 32
无信息披露 30
无披露 28
转发出去 15
放弃 13
无响应记录存在 11
不存在 3
改正被拒绝 3
改正作出 2
移交滑铁卢地区公共卫生 2
已转移 1
更正批准 1
请求撤回 1
名称:决定,dtype:int 64
20
还不错。我们合并了四个类别(即“不存在记录”和“不存在记录”),但“未披露信息”和“未披露任何内容”的意思显然是一样的。80%的截止值是通过反复试验确定的。让我们试试部分比率:
全部披露 240
部分豁免 197
请求撤回 117
无响应记录存在 87
无信息披露 80
不存在 35
无披露 28
转发出去 15
放弃 13
更正拒绝 3
移交 3
更正作出 2
异议陈述归档 1
更正批准 1
名称:决定、dtt
另外六个类合并了,但是算法并不真正知道如何处理子串‘discovered’。它将“部分披露的信息”和“未披露的信息”结合在一起,这两个词的意思不同。
全部披露 240
部分豁免 197
撤回 116
无信息披露 80
无记录存在 75
部分不存在 32
无披露 28
转发出去 15
放弃 13
无响应记录存在 11
拒绝改正 3
不存在 3
改正作出 2
转移到滑铁卢公共卫生区 2【T55
类似于基本比率情况。
未披露信息 348
部分免除 197
要求撤回 117
无响应记录存在 87
不存在 35
转发出去 15
放弃 13
更正拒绝 3
移交 3
更正作出 2
异议声明存档 1
更正批准 1
名称:决定,dtype: int64
12
迄今为止最积极的匹配案例,但我们再次被“披露”绊倒,因为现在我们不再有“全部披露”的案例,这是不可接受的。部分比率的情况似乎是一种折衷——也许我们可以进一步手动合并几个类别。我们将会看到当多伦多的数据被加入第二部分时会发生什么。
all_df_pr['Decision'].loc[all_df_pr['Decision'] == "Abandoned"] = "Request withdrawn"
all_df_pr['Decision'].loc[all_df_pr['Decision'] == "Non-existent"] = "No responsive records exist"
all_df_pr['Decision'].loc[all_df_pr['Decision'] == "No information disclosed "] = "Nothing disclosed"
all_df_pr['Decision'].loc[all_df_pr['Decision'] == "Transferred"] = "Forwarded out"
all_df_pr['Decision'].loc[all_df_pr['Decision'] == "Correction granted"] = "Correction made"
print(all_df_pr['Decision'].value_counts())
全部公开 240
部分免除 197
请求撤回 130
无响应记录存在 122
无公开 108
转发 18
更正已做出 3
更正被拒绝 3
异议声明已归档 1
名称:决定,dtype: int64
现在一切都变得清晰了。让我们砍掉人数下降幅度大的班级:
all_df_over20 = all_df_pr.groupby('Decision').filter(lambda x: len(x) > 20)
本文的剩余部分将大量借用 Susan Li 的关于多类文本分类的优秀文章。我们的预期是,基于我们的数据集较小,以及文本本身相当不透明的事实,我们的结果不会很好。我们数据的快速概述:
这些阶层并不像我们想象的那样不平衡。“category_id”列是可能的决策案例的整数表示。现在,为每个请求计算一个 tf-idf 向量,去掉所有停用词。
from sklearn.feature_extraction.text import TfidfVectorizertfidf = TfidfVectorizer(sublinear_tf=True, min_df=5, norm='l2',
encoding='latin-1', ngram_range=(1,2), stop_words='english')features = tfidf.fit_transform(all_df_over20.Request_summary).toarray()
labels = all_df_over20.category_id
features.shape
打印每个类的常见二元模型和二元模型。
from sklearn.feature_selection import chi2
import numpy as npN=2
for Decision, category_id in sorted(category_to_id.items()):
features_chi2 = chi2(features, labels == category_id)
indices = np.argsort(features_chi2[0])
feature_names = np.array(tfidf.get_feature_names())[indices]
unigrams = [v for v in feature_names if len(v.split(' ')) ==1]
bigrams = [v for v in feature_names if len(v.split(' ')) ==2]
print("# '{}':".format(Decision))
print(" . Most correlated unigrams:\n. {}".format('\n.'.join(unigrams[-N:])))
print(" . Most correlated bigrams:\n. {}".format('\n.'.join(bigrams[-N:])))
#‘全部公开’:
。最相关的单字:
。协助
。个人
。最相关的二元模型:
。信息已删除
。移除竞争
#‘不存在响应记录’:
。最相关的单字:
。地点
。阶段
。最相关的二元模型:
。评估地址
。现场评估
#【未披露内容】:
。最相关的单字:
。总线
.2014
。最相关的二元模型:
。完成安大略省
。工程文件
#‘部分免除’:
。最相关的单字:
。比赛
.94
。最相关的二元模型:
。信息竞赛
。狂犬病控制
#‘请求撤回’:
。最相关的单字:
。省级
。评测
。最相关的二元模型:
。处理厂
。省级违法行为
这就是我说的请求本身在通过视觉进行分类方面相当不透明的意思。至少在阶级之间有很好的区分。
尝试四种不同的型号:
import warnings
warnings.filterwarnings(action='once')
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier
from sklearn.svm import LinearSVCfrom sklearn.model_selection import cross_val_scoremodels = [
RandomForestClassifier(n_estimators=200, max_depth=3,
random_state=0), #, class_weight='balanced'),
LinearSVC(), #class_weight='balanced'),
MultinomialNB(),
LogisticRegression(random_state=0)#, class_weight='balanced'),
]
CV=5
cv_df = pd.DataFrame(index=range(CV * len(models)))
entries=[]
for model in models:
model_name = model.__class__.__name__
accuracies = cross_val_score(model, features, labels,
scoring='accuracy', cv=CV)
for fold_idx, accuracy in enumerate(accuracies):
entries.append((model_name, fold_idx, accuracy))
cv_df = pd.DataFrame(entries, columns=['model_name', 'fold_idx', 'accuracy'])import seaborn as snssns.boxplot(x='model_name', y='accuracy', data=cv_df)
sns.stripplot(x='model_name', y='accuracy', data=cv_df,
size=8, jitter=True, edgecolor="gray", linewidth=2)
plt.show()
cv_df.groupby('model_name').accuracy.mean()
model _ Name
linear SVC 0.362882
logistic regression 0.398066
MultinomialNB 0.398152
RandomForestClassifier 0.349038
Name:accuracy,dtype: float64
不出所料,性能非常差。我们来看看混淆矩阵。
precision recall f1-score support
All disclosed 0.36 0.69 0.47 67
No responsive records exist 0.50 0.49 0.49 41
Partly exempted 0.58 0.48 0.53 73
Request withdrawn 0.38 0.11 0.17 47
Nothing disclosed 0.58 0.39 0.47 36
avg / total 0.48 0.45 0.44 264
这个模型至少在尝试。在后续文章中,我们将尝试通过显著增加可用数据和在每个类上尝试一系列二元分类器来改进这一点。
GitHub 上提供的代码:https://github.com/scjones5/foi-kw
信息自由请求的文本分类:第二部分
在第一部分中,我们吸收了可用的 Kitchener-Waterloo 信息自由数据,并设法使用模糊字符串匹配来聚合预测类。从那里,我们能够尝试使用四种不同的分类算法进行预测:随机森林、线性支持向量分类、多项式朴素贝叶斯和逻辑回归。结果并不令人印象深刻。
在这里,我们将通过包含多伦多市发出的请求来增加我们的数据集。我们将进行更多的探索性数据分析,看看是否有任何方法可以帮助我们的模型,然后我们将尝试更智能地使用机器学习,在第三部分中,深度学习,以实现最佳结果。
在第一部分,我们的数据集有 832 个条目;用来自大城市的数据补充这一点,使我们的总数达到 11521 个条目,这开始类似于更适合机器学习问题的东西。千瓦数据仍然涵盖了更长的时间段,从 1993 年开始,直到 2016 年结束:
FOI requests over time in KW
多伦多 2011 年至 2018 年的数据没有显示出同样的增长趋势,
Requests by year in Toronto
但是,如果我们能够想出某种模式,将请求本身的案文与所作出的决定联系起来,就一定会节省一些时间。
请求本身的内容呢?为了快速理解人们正在使用的短语,我们可以检查两个数据集的单词云:
KW requests
Toronto requests
在每一个案例中,我都删除了一些被用来保护个人隐私的二元模型,但它们本身并没有传达任何有用的信息。这些包括“地址已删除”、“名称已删除”和“位置已删除”。留给我们的是更有趣的二元结构,如“安大略工程”、“建筑许可证”和“环境网站”。像这样将数据集分开,让我们注意到 KW 的请求更倾向于环境问题,而多伦多的请求看起来更一般。重要的是在得出太多的结论之前要小心,因为这是未知的,也可能是不太可能的,这是由个人/企业提交的文本。更有可能的是,这些数据是在某个时候从网上或打印出来的。
处理任何自由格式文本的一个重要部分是预处理。在这里,每个请求通常可以很好地包含在大约 50 个单词的句子中,事情可以很容易地标记化。将每个请求提供给下面的函数:
import spacy
from spacy.lang.en import English
from nltk.corpus import stopwords
from sklearn.feature_extraction.stop_words import ENGLISH_STOP_WORDS
from wordcloud import WordCloud, STOPWORDS
import string
parser = English()
STOPLIST = set(stopwords.words('english') + list(ENGLISH_STOP_WORDS)+ list(STOPWORDS))
SYMBOLS = " ".join(string.punctuation).split(" ") + ["-", "...", "”", "”"]def tokenizeText(sample):
tokens = parser(sample)
lemmas = []
for tok in tokens:
#lemmatizes, converts to lowercase, omits pronouns
lemmas.append(tok.lemma_.lower().strip() if tok.lemma_ != "-PRON-" else tok.lower_)
tokens = lemmas
#removes stop word tokens and symbols
tokens = [tok for tok in tokens if tok not in STOPLIST]
tokens = [tok for tok in tokens if tok not in SYMBOLS]
return tokens
我们可以先用 SpaCy 解析文本,然后找到每个单词的引理,转换成小写。使用 nltk,我们最终可以删除任何停用词或符号。nltk 还为词汇化提供了“Morphy”方法,这是一个很大程度上重复的进一步步骤,但对我来说,仍然抓住了一些 SpaCy 遗漏的复数:
import nltk
nltk.download('wordnet')
from nltk.corpus import wordnet as wn
def get_lemma(word):
#print("un-lemmad word: ", word)
lemma = wn.morphy(word)
#print("lemma-d word: ", lemma)
if lemma is None:
return word
else:
return lemma
调用这两个函数并删除任何长度小于 5 的标记:
def prepare_text_for_lda(text):
# tokenizes text using spacy
tokens = tokenizeText(text)
# removes tokens less that five characters
tokens = [token for token in tokens if len(token) > 4]
# here we are lemmatizing again too; noticed that previous lemmatization doesn't handle plurals
tokens = [get_lemma(token) for token in tokens]
return tokens
将所有这些放在一起并整合结果:
import random
text_data = []
for request in (all_df['Summary_of_Request']):
tokens = prepare_text_for_lda(request)
text_data.append(tokens)
例如,下面是数据帧中的第一个请求及其相关的令牌:
Notes written by members of the Maintenance Review Committee for Clerk III, Healthy Environments.
['note', 'write', 'member', 'maintenance', 'review', 'committee', 'clerk', 'healthy', 'environment']
EDA 中对文本数据最感兴趣的最后一点是做一些主题建模。GenSim 包可以主要通过潜在的狄利克雷分配来识别语义相似性(因此命名为上述函数),并从中挑选出所需数量的“主题”,显示与每个主题最相似的单词。基于一个预定义的字典(这里是前面的 text_data 列表),方法 doc2bow 使用单词包格式返回每个单词的索引和频率。然后将其传递给 LDA 模型,直到最终能够看到与每个主题相关联的单词及其相对重要性:
(0, '0.078*"record" + 0.063*"permit" + 0.057*"build" + 0.055*"inspection"')
------------------------------------------------------------------------------------------
(1, '0.124*"report" + 0.092*"incident" + 0.076*"occur" + 0.032*"address"')
------------------------------------------------------------------------------------------
(2, '0.167*"specify" + 0.084*"address" + 0.027*"toronto" + 0.020*"include"')
------------------------------------------------------------------------------------------
(3, '0.044*"water" + 0.042*"record" + 0.029*"toronto" + 0.021*"sewer"')
------------------------------------------------------------------------------------------
(4, '0.071*"record" + 0.034*"property" + 0.032*"complaint" + 0.021*"investigation"')
------------------------------------------------------------------------------------------
我们可以看到“记录”一词与多个不同的主题相关联,但总体而言,所使用的术语是相当通用的。
在第一部分中,我们主要讨论了使用 fuzzywuzzy 包来组合相似的表面决定。随着多伦多数据的加入,“partial_ratio”方法仍然是最适用的,并允许我们将决策范围缩小到 6 个类别,如下图所示,同时列出了每组的观察数量。
Disclosed in Part: Partially Exempt 6406
All Disclosed 2847
No Records Exist 1393
Nothing Disclosed 371
Request withdrawn 256
Transferred Out in Full 168
当我们进行预测时,我们应该记住,最常见的决策“部分披露:部分豁免”应该对我们的模型进行最严格的测试,因为这是一个介于“全部披露”和“没有披露”极端情况之间的情况。如果我们能准确预测这种情况,那么其他的应该会更容易发生。幸运的是,它拥有最多的数据。
下图更新后包括了多伦多的数据:
与第一部分相比,我们现在有更多的不平衡类问题。这可能需要更彻底地解决,特别是如果我们希望,如前所述,尝试二元“一个对其余的”分类器。这样不公平地存在正反两方面的情况是不行的。
打包的不平衡学习正是考虑到这些类型的用例而构建的。这有助于对较小的类进行过采样,或者对较大的类进行欠采样,以平衡观测值的分布。该软件包提供了几种不同的数据过采样方法。RandomOverSampler 例程通过替换对代表性不足的类进行采样,直到达到最密集类的频率。但是,这种方法容易导致大量的数据重复,可能导致模型过拟合。相反,合成少数过采样技术(SMOTE)进行插值,以生成新的样本。我们试试 SMOTE:
from imblearn.over_sampling import RandomOverSampler, SMOTEX_resampled, y_resampled = SMOTE().fit_resample(features, labels)from collections import Counterprint(sorted(Counter(y_resampled).items()))
[(0, 6406), (1, 6406), (2, 6406), (3, 6406), (4, 6406), (5, 6406)]
现在每个类都有相同数量的观察值。
作为我们预测能力的基线,我们可以简单地重复第一部分中使用的方法,这里使用额外的数据和重新采样的类。这样做已经大大提高了我们的准确性:
线性 SVC 0.858418
物流回归 0.806723
多项式 B 0.752838
随机森林分类器 0.500750
在本系列的剩余部分,第三部分,我们将通过最终引入 OneVsRest 二元分类器来深化我们的模型,并将其性能与完全成型的 GRU 递归神经网络进行比较。
信息自由请求的文本分类:第三部分
在本系列的第一部分中,我们针对 Kitchener-Waterloo 信息自由请求运行了一个不成熟的模型,试图预测一个响应。在第二部分中,我们通过包含多伦多市的请求扩展了我们的数据集,并通过探索性数据分析增加了一些领域知识。我们还处理了六个不同决策类别中观察值数量之间的不平等。
在第三部分中,我们将重复使用 LinearSVC、多项朴素贝叶斯、逻辑回归和随机森林中的每一个,但现在每次只针对一个类,而不是所有其他类。这是一种经常用于多标签问题的技术,在我们的例子中,每个请求都有多个决策,例如,由不同的参与方提交。需要的关键假设是,每个标签或类别(决策)是互斥的,并且独立于所有其他类别。虽然可以提出一个论点,即在这里不完全正确(“部分披露”可能最终变成“全部披露”,或者可能存在对相同请求做出不同决定的情况),但我们将继续理解已经做出的假设。
基本代码的结构如下:
from sklearn.metrics import accuracy_scoreNB_pipeline = Pipeline([
('tfidf', TfidfVectorizer(tokenizer=tokenizeText, stop_words='english')),
('clf', OneVsRestClassifier(MultinomialNB())),
])for decision in categories:
print(decision)
NB_pipeline.fit(X_train, y_train_dums[decision])
prediction = NB_pipeline.predict(X_test)
print('Test accuracy is {}'.format(accuracy_score(y_test_dums[decision], prediction)))Disclosed in Part: Partially Exempt Test accuracy is 0.8520182907600126
All Disclosed Test accuracy is 0.8698360138757489
No Responsive Records Exist Test accuracy is 0.8816619362976978 Nothing Disclosed (exemption) Test accuracy is 0.934799747713655 Request withdrawn Test accuracy is 0.9653106275622831
Transferred Out in Full Test accuracy is 0.9943235572374646
其中目标变量先前已经被编码为独热码向量。LinearSVC 的结果:
部分披露:部分豁免测试精度为 0.9100441501103753
全部披露测试精度为 0.9057079785556607
无响应记录存在测试精度为 0.9505676442762535
无披露(豁免)测试精度为 0.9874645222327342
要求撤回测试精度为 0.995
逻辑回归:
部分披露:部分豁免测试精度为 0.8661305581835383
全部披露测试精度为 0.8785083569851782
无响应记录存在测试精度为 0.8984547461368654
未披露(豁免)测试精度为 0.96661778618732261
请求撤回
随机森林:
部分披露:部分豁免测试精度为 0.826631977294229
全部披露测试精度为 0.8324660990223904
无响应记录存在测试精度为 0.8423210343740145
无披露(豁免)测试精度为 0.8342005676442763
要求撤回测试精度
LinearSVC 方法似乎仍然表现最好,最接近“部分公开”类。一般来说,趋势是增加具有较少(上采样前)数据的类的准确性。很可能,向上采样的数据有些人为,根据定义,必须非常类似于已经存在的数据。
还尝试以同样的方式使用 XGBoost,对“部分公开”的准确率为 83.4%,尽管计算成本高得多。
用递归神经网络进行深度学习
作为对这个数据集的最后努力,我们将采用递归神经网络(RNNs)形式的深度学习。rnn 保留序列中之前步骤的一些记忆,或者对于双向实现,在当前步骤之后的和之前。因此,它们在文档摘要和机器翻译等任务中非常有用,可以处理不同大小的输入和输出。
在我们的项目中,我们有许多输入令牌作为请求字符串的一部分,并且本质上,有一个决策类形式的输出。因此,该模型可以被认为是多对一分类器。
使用 Google 协作 GPU 功能,实现了以下模型:
input= Input(shape=(max_len, ), dtype = 'int32')
embedding_layer = Embedding(len(word_index) + 1, embedding_dim, embeddings_initializer=Constant(embedding_matrix), input_length=max_len, trainable=False)
embedded_sequences = embedding_layer(input)
x = Bidirectional(GRU(units=32, return_sequences=True))(embedded_sequences)
x = GlobalMaxPooling1D()(x)
x = Dense(50, activation = 'relu')(x)
x = Dropout(0.2)(x)
output = Dense(num_classes, activation='softmax')(x)
model = Model(inputs=input, outputs=output)
model.compile(loss="categorical_crossentropy", optimizer='adam', metrics=['accuracy'])metrics=['accuracy'])
print(model.summary())
我们使用了长度为 40 个单位的手套词嵌入,这是大多数请求遵循的最大长度:
embeddings_index = {}# Download this file first
f = open("/content/drive/My Drive/foi-kw/glove.6B.300d.txt", encoding="utf8")for line in f:
values = line.split()
word = ''.join(values[:-embedding_dim])
coefs = np.asarray(values[-embedding_dim:], dtype="float32")
embeddings_index[word] = coefs
f.close()tokenizer = Tokenizer(num_words = None)
tokenizer.fit_on_texts(X_train)sequences_train = tokenizer.texts_to_sequences(X_train)
X_train = pad_sequences(sequences_train, maxlen=max_len)sequences_val = tokenizer.texts_to_sequences(X_test)
X_test = pad_sequences(sequences_val, maxlen=max_len)word_index = tokenizer.word_index#create embedding layer
embedding_matrix = np.zeros((len(word_index) + 1, embedding_dim))for word, i in word_index.items():
embedding_vector = embeddings_index.get(word)
if embedding_vector is not None:
embedding_matrix[i] = embedding_vectorimport matplotlib.pyplot as pltcheckpoint = ModelCheckpoint("/content/drive/My Drive/foi-kw/colab/models/model.h5", monitor='val_loss', verbose=1, save_best_only=True, mode='min')
early = EarlyStopping(monitor='val_loss', mode='min', patience=3)
callback = [checkpoint, early]history = model.fit(X_train, y_train, batch_size=batch_size, epochs=epochs, validation_data=(X_test, y_test), callbacks=callback, class_weight=class_weights)
loss, accuracy = model.evaluate(X_train, y_train, verbose=0)
print('Accuracy: %f' % (accuracy*100))
print(history.history.keys())
# Plot history for accuracy
plt.plot(history.history['acc'])
plt.plot(history.history['val_acc'])
plt.title('model accuracy')
plt.ylabel('accuracy')
plt.xlabel('epoch')
plt.legend(['train', 'test'], loc='upper left')
plt.show()
# Plot history for loss
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.title('model loss')
plt.ylabel('loss')
plt.xlabel('epoch')
plt.legend(['train', 'test'], loc='upper left')
plt.show()
model.reset_states()
早期停止被用来努力避免过度拟合,就像“类权重”处理类不平衡一样。关于关键词及其含义的进一步描述,我会向读者推荐曼迪·顾的优秀文章。
如上编码的精度和损耗图得出:
Training and test accuracy over 12 epochs.
Training and test loss over 12 epochs.
奇怪的是,测试损失保持在一个相当恒定的值。在我们的模型中,我们在训练期间使用了压差正则化,这意味着网络没有满负荷运行,而在测试期间没有使用压差。另一种解释可能是,一个时期的测试损失是在该时期结束时计算的,而训练损失是每批训练数据的平均值。
结论
这一系列文章覆盖了很多领域,代表了作者第一次真正尝试为文本数据构建机器学习模型。多伦多数据集的增加使分析受益匪浅,因此我们可以有信心能够发现一些共同趋势。尽管如此,请求的实际文本可能没有什么变化,决定仍然是人类监督者的判断,这两个因素都可能混淆我们的结果。最后,即使通过这三篇文章,仍然有很多可以尝试的地方(不同类型的神经网络,GridSearchCV for hyperparameter tuning,AutoML)来改进我们的结果。
文本分类——RNN 的还是 CNN 的?
是一类人工神经网络,其中节点之间的连接沿着序列形成有向图。它基本上是一系列神经网络块,像链条一样相互链接。每一个都在向下一个传递信息。如果你想深入内部机制,我强烈推荐科拉的博客。这种架构允许 RNN 展示时间行为并捕获顺序数据,这使它在处理文本数据时成为一种更“自然”的方法,因为文本天生就是顺序的。
CNN 是一类深度前馈人工神经网络,其中节点之间的连接不形成循环。CNN 通常用在计算机视觉中,然而当应用于各种 NLP 任务时,它们也显示出有希望的结果。再次深入细节,Colah 的博客是一个很好的起点。
RNN 人被训练识别跨时间的模式,而 CNN 学习识别跨空间的模式。
哪种 DNN 类型在处理文本数据时表现得更好取决于理解全局/远程语义的频率。对于文本长度很重要的任务,使用 RNN 变体是有意义的。这些类型的任务包括:问答、翻译等。
事实证明,应用于某些 NLP 问题的 CNN 表现相当好。让我们简单看看当我们在文本数据上使用 CNN 时会发生什么。
当检测到特殊模式时,将触发每个卷积的结果。通过改变内核的大小并连接它们的输出,您允许自己检测多个大小的模式(2、3 或 5 个相邻的单词)。模式可以是表达式(单词 ngrams?)像“我讨厌”、“非常好”,因此 CNN 可以在句子中识别它们,而不管它们的位置。基于上述解释,最适合 CNN 的似乎是分类任务,如情感分析、垃圾邮件检测或主题分类。卷积和汇集操作丢失了关于单词的本地顺序的信息,因此像在词性标注或实体提取中那样的序列标注有点难以适应纯 CNN 架构(尽管并非不可能,但您可以向输入添加位置特征)。汇集也减少了输出维度,但(希望)保留了最突出的信息。你可以把每个过滤器想象成检测一个特定的特征,比如检测句子是否包含否定,比如“不惊人”。如果这个短语出现在句子中的某个地方,那么对该区域应用过滤器的结果将产生一个大值,而在其他区域产生一个小值。通过执行 max 操作,您保留了关于该特征是否出现在句子中的信息,但是您丢失了关于它出现的确切位置的信息。
当当前步骤与前面的步骤有某种关系时,rnn 被设计成利用顺序数据。这使得它们非常适合具有时间成分(音频、时序数据)和自然语言处理的应用。对于顺序信息显然很重要的应用程序,RNN 的表现非常好,因为如果不使用顺序信息,意思可能会被误解或者语法可能不正确。应用包括图像字幕,语言建模和机器翻译。
CNN 擅长提取局部的和位置不变的特征,而当分类是由长范围的语义依赖而不是一些局部的关键短语来确定时,RNN 更好。对于文本中的特征检测更重要的任务,例如,搜索愤怒的术语、悲伤、辱骂、命名实体等。CNN 做得很好,而对于顺序建模更重要的任务,RNN 做得更好。基于上述特征,选择 CNN 用于分类任务(如情感分类)是有意义的,因为情感通常由一些关键短语确定,而选择 RNNs 用于序列建模任务(如语言建模或机器翻译或图像字幕)是有意义的,因为它需要对上下文依赖性进行灵活的建模。rnn 通常擅长预测序列中的下一步,而 CNN 可以学习对句子或段落进行分类。
CNN 的一个重要理由是他们速度快。非常快。基于计算时间,CNN 似乎比 RNN 快得多(~ 5 倍)。卷积是计算机图形的核心部分,在 GPU 的硬件层面上实现。像文本分类或情感分析这样的应用实际上并不需要使用存储在数据序列中的信息。比如一个假设的餐厅点评:我对这家餐厅非常失望。服务慢得令人难以置信,食物也很一般。我不会回来了。虽然数据中有顺序信息,但如果你试图预测情绪是好是坏,CNN 模型可能就足够了,甚至在计算方面更好。做出预测所需的重要信息存在于短语“非常失望”、“慢得令人难以置信”和“平庸”中如果你只使用 2-gram,一个 RNN 可能能够额外捕捉到是服务慢得令人难以置信,相比之下,其他东西可能对慢有好处(也许是音乐?).但是,通常情况下,这是不必要的,与简单的模型相比,更复杂的 RNN 可能会溢出。
参考
当我们听到卷积神经网络(CNN)时,我们通常会想到计算机视觉。CNN 对此负有责任…
www.wildml.com](http://www.wildml.com/2015/11/understanding-convolutional-neural-networks-for-nlp/)**
极小数据集下的文本分类
充分利用微型数据集的指南
Stop overfitting!
俗话说,在这个深度学习的时代“数据是新的石油”。然而,除非你为谷歌、脸书或其他科技巨头工作,否则获取足够的数据可能是一项艰巨的任务。这对于那些在你我可能拥有的利基领域或个人项目中运营的小公司来说尤其如此。
在这篇博客中,我们将模拟一个场景,其中我们只能访问一个非常小的数据集,并详细探讨这个概念。特别是,我们将构建一个可以检测 clickbait 标题的文本分类器,并试验不同的技术和模型来处理小数据集。
博客概要:
- 什么是 Clickbait?
- 获取数据集
- 为什么小型数据集是 ML 中的一个难点?
- 拆分数据
- 简单的探索性数据分析
- 词袋、TF-IDF 和词嵌入
- 特征工程
- 探索模型和超参数调整
- 降维
- 摘要
1.什么是 clickbait?
通常,您可能会遇到这样的标题:
“我们试图用一个小数据集构建一个分类器。你不会相信接下来会发生什么!”
“我们喜欢这 11 种技术来构建文本分类器。# 7 会让你震惊。”
“智能数据科学家使用这些技术来处理小型数据集。点击了解它们是什么"
这些吸引人的标题在互联网上随处可见。但是,是什么让一个标题“吸引人”呢?维基百科将其定义为:
Clickbait 是一种虚假广告,它使用超链接文本或缩略图链接,旨在吸引注意力并诱使用户点击该链接,阅读、查看或收听链接的在线内容,其显著特征是欺骗性、典型的耸人听闻或误导性。
一般来说,一个帖子是否是点击诱饵的问题似乎是相当主观的。(查看:“为什么 BuzzFeed 不做 click bait”[1])。这意味着在查找数据集时,最好是查找由多人手动审阅的数据集。
2.获取数据集
经过一番搜索,我发现:停止点击诱饵:检测和防止网络新闻媒体中的点击诱饵Chakraborty 等人(2016)【2】及其附随的 Github repo
该数据集包含 15,000 多篇文章标题,分别被标记为点击诱饵和非点击诱饵。非点击诱饵标题来自维基新闻,由维基新闻社区策划,而点击诱饵标题来自“BuzzFeed”、“Upworthy”等。
为了确保没有任何假阳性,标记为 clickbait 的标题由六名志愿者验证,每个标题由至少三名志愿者进一步标记。文件的第 2 部分包含更多细节。
基准性能:作者在随机采样的 15k 数据集(平衡)上使用了 10 倍 CV。他们取得的最好结果是 RBF-SVM 达到了 93%的准确率,0.95 的精确度,0.9 的召回率,0.93 的 F1,0.97 的 ROC-AUC
所以这是我们的挑战:
我们将用的 50 个数据点作为我们的训练集,用的 10000 个数据点作为我们的测试集。这意味着训练组只是测试组的 0.5%。我们不会在训练中使用测试集的任何部分,它只是作为一个省略验证集。
评估指标:
随着我们进行不同的实验,跟踪性能指标对于理解我们的分类器表现如何至关重要。 F1 分数将是我们的主要绩效指标,但我们也会跟踪精确度、召回、 ROC-AUC 和精确度。
3.为什么小型数据集是 ML 中的一个难点?
在我们开始之前,理解为什么小数据集难以处理是很重要的:
- 过拟合 : 当数据集较小时,分类器有更多的自由度来构造决策边界。为了证明这一点,我在同一个数据集(只有 8 个点的 Iris 数据集的修改版本)上训练了随机森林分类器 6 次
Varying Decision Boundaries for a small dataset
注意决策边界是如何剧烈变化的。这是因为分类器很难用少量数据进行归纳。从数学上来说,这意味着我们的预测会有很高的方差。
潜在解决方案:
正规化:我们将不得不使用大量的 L1,L2 和其他形式的正规化。
二。*更简单的模型:*像逻辑回归和支持向量机这样的低复杂度线性模型往往表现更好,因为它们的自由度更小。
2。离群值:
离群值对小数据集有着巨大的影响,因为它们会显著扭曲决策边界。在下面的图中,我添加了一些噪声,并改变了其中一个数据点的标签,使其成为异常值——注意这对决策边界的影响。
Effect of Outliers on the Decision Boundary
潜在解决方案:
异常检测和去除:我们可以使用像 DBSCAN 这样的聚类算法或者像隔离森林这样的集成方法
3。高维度:
随着更多特征的添加,分类器有更大的机会找到超平面来分割数据。然而,如果我们在不增加训练样本数量的情况下增加维数,特征空间会变得更加稀疏,分类器很容易过拟合。这是维度诅咒的直接结果——在这个博客中有最好的解释
潜在解决方案:
- 分解技术 : PCA/SVD 降低特征空间的维数
二。特征选择:去除预测中无用的特征。
我们将在这篇博客中深入探讨这些解决方案。
4.拆分数据
让我们从将数据分成训练集和测试集开始。如前所述,我们将使用 50 个数据点进行训练,10000 个数据点进行测试。
(为了保持整洁,我删除了一些琐碎的代码:您可以查看GitHub repo中的完整代码)
data = pd.DataFrame(clickbait_data)#Now lets split the datafrom sklearn.model_selection import train_test_splittrain, test = train_test_split(data, shuffle = True, stratify = data.label, train_size = 50/data.shape[0], random_state = 50)test, _ = train_test_split(test, shuffle = True,
stratify = test.label, train_size = 10000/test.shape[0], random_state = 50)train.shape, test.shape**Output:** ((50, 2), (10000, 2))
这里重要的一步是确保我们的训练集和测试集来自相同的分布,这样训练集的任何改进都会反映在测试集中。
Kagglers 使用的一个常用技术是在不同的数据集之间使用“对抗性验证”。(我见过它有很多名字,但我认为这是最常见的一个)
这个想法非常简单,我们混合两个数据集,并训练一个分类器来尝试区分它们。如果分类器不能做到这一点,我们可以得出结论,分布是相似的。可以在这里阅读更多:https://www . kdnugges . com/2016/10/adversarial-validation-explained . html
ROC AUC 是首选指标——值约为 0.5 或更低意味着分类器与随机模型一样好,并且分布相同。
Code for Adversarial Validation
在进行对抗性验证之前,让我们使用词袋对标题进行编码
bow = CountVectorizer()
x_train = bow.fit_transform(train.title.values)
x_test = bow.transform(test.title.values)x_test = shuffle(x_test)adversarial_validation(x_train, x_test[:50])**Output:** Logisitic Regression AUC : 0.384
Random Forest AUC : 0.388
低 AUC 值表明分布是相似的。
为了看看如果发行版不同会发生什么,我在 breitbart.com 上运行了一个网络爬虫,收集了一些文章标题。
bow = CountVectorizer()
x_train = bow.fit_transform(breitbart.title.values)
x_test = bow.transform(test.title.values)x_train = shuffle(x_train)
x_test = shuffle(x_test)
adverserial_validation(x_train[:50], x_test[:50])**Output:** Logisitic Regression AUC : 0.720
Random Forest AUC : 0.794
AUC 值高得多,表明分布是不同的。
现在让我们继续,在 train 数据集上做一些基本的 EDA。
5.简单的探索性数据分析
让我们从检查数据集是否平衡开始:
print('Train Positive Class % : {:.1f}'.format((sum(train.label == 'clickbait')/train.shape[0])*100))
print('Test Positive Class % : {:.1f}'.format((sum(test.label == 'clickbait')/test.shape[0])*100))print('Train Size: {}'.format(train.shape[0]))
print('Test Size: {}'.format(test.shape[0]))**Output:** Train Positive Class % : 50.0
Test Positive Class % : 50.0
Train Size: 50
Test Size: 10000
接下来,让我们检查字数的影响。
看起来 Clickbait 标题中包含的单词更多。平均单词长度呢?
与非点击诱饵标题相比,点击诱饵标题使用较短的单词。由于 clickbait 标题通常有更简单的单词,我们可以检查标题中有百分之多少的单词是停用词
奇怪的是,clickbait 标题似乎没有 NLTK 停用词列表中的停用词。这可能是一个巧合,因为火车测试分裂或我们需要扩大我们的停用词列表。在特征工程中肯定要探索的东西。此外,停止单词删除作为预处理步骤在这里不是一个好主意。
单词云可以帮助我们识别每个类别中更突出的单词。让我们来看看:
Wordcloud for Clickbait Titles
Wordcloud for Non-Clickbait Titles
点击诱饵和非点击诱饵标题之间的单词分布非常不同。例如:非点击诱饵标题有州/国家,如“尼日利亚”、“中国”、“加利福尼亚”等,以及更多与新闻相关的词,如“暴乱”、“政府”和“破产”。非点击诱饵标题似乎有更多的通用词,如“最爱”、“关系”、“事情”等
使用单词包、TF-IDF 或 GloVe/W2V 这样的单词嵌入作为特性应该会有所帮助。与此同时,我们也可以通过简单的文本特性,如长度、单词比率等,获得大量的性能提升。
让我们试试 TSNE 对标题的单词包编码:
TSNE on BoW Title Encodings
这两个类似乎都用 BoW 编码聚集在一起。在下一节中,我们将探索不同的嵌入技术。
实用功能:
在我们开始探索嵌入之前,让我们编写几个助手函数来运行逻辑回归和计算评估指标。
因为我们想要优化 F1 分数的模型,所以对于所有的模型,我们将首先预测正类的概率。然后,我们将使用这些概率来获得精度-召回曲线,从这里我们可以选择一个具有最高 F1 分数的阈值。为了预测标签,我们可以简单地使用这个阈值。
Utility Functions to calculate F1 and run Log Reg
6.词袋、TF-IDF 和词嵌入
在这一节中,我们将使用 BoW、TF-IDF 和 Word 嵌入对标题进行编码,并在不添加任何其他手工制作的功能的情况下使用这些功能。
从 BoW 和 TF-IDF 开始:
y_train = np.where(train.label.values == 'clickbait', 1, 0)
y_test = np.where(test.label.values == 'clickbait', 1, 0)from sklearn.feature_extraction.text import CountVectorizer, TfidfVectorizerbow = CountVectorizer()
x_train = bow.fit_transform(train.title.values)
x_test = bow.transform(test.title.values)run_log_reg(x_train, x_test, y_train, y_test)from sklearn.feature_extraction.text import TfidfVectorizertfidf = TfidfVectorizer()
x_train = tfidf.fit_transform(train.title.values)
x_test = tfidf.transform(test.title.values)run_log_reg(x_train, x_test, y_train, y_test)**Output:
For BoW:** F1: 0.782 | Pr: 0.867 | Re: 0.714 | AUC: 0.837 | Accuracy: 0.801**For TF-IDF:**
F1: 0.829 | Pr: 0.872 | Re: 0.790 | AUC: 0.896 | Accuracy: 0.837
TFIDF 的表现略好于 BoW。一个有趣的事实是,我们只用 50 个数据点就得到 0.837 的 F1 分数。这就是为什么 Log Reg + TFIDF 是 NLP 分类任务的一个很好的基线。
接下来,让我们试试 100 维手套向量。我们将使用 PyMagnitude 库: (PyMagnitude 是一个非常棒的库,它包含了很多优秀的特性,比如智能的声外表示。强烈推荐!)
由于标题可以有不同的长度,我们将找到每个单词的手套表示,并将它们平均在一起,给出每个标题的单一 100-D 向量表示。
# We'll use Average Glove here
from tqdm import tqdm_notebook
from nltk import word_tokenize
from pymagnitude import *glove = Magnitude("./vectors/glove.6B.100d.magnitude")def avg_glove(df):
vectors = []
for title in tqdm_notebook(df.title.values):
vectors.append(np.average(glove.query(word_tokenize(title)), axis = 0))
return np.array(vectors)x_train = avg_glove(train)
x_test = avg_glove(test)run_log_reg(x_train, x_test, y_train, y_test)**Output:**
F1: 0.929 | Pr: 0.909 | Re: 0.950 | AUC: 0.979 | Accuracy: 0.928
哇哦。这是 F1 分数的巨大增长,只是标题编码有一点点变化。改进的性能是合理的,因为 W2V 是包含大量上下文信息的预训练嵌入。这将有助于分类器的性能,尤其是当我们的数据集非常有限时。
如果我们不只是取每个单词的平均值,而是取一个加权平均值,特别是 IDF 加权平均值,会怎么样?
from sklearn.feature_extraction.text import TfidfVectorizertfidf = TfidfVectorizer()
tfidf.fit(train.title.values)# Now lets create a dict so that for every word in the corpus we have a corresponding IDF value
idf_dict = dict(zip(tfidf.get_feature_names(), tfidf.idf_))# Same as Avg Glove except instead of doing a regular average, we'll use the IDF values as weights.def tfidf_glove(df):
vectors = []
for title in tqdm_notebook(df.title.values):
glove_vectors = glove.query(word_tokenize(title))
weights = [idf_dict.get(word, 1) for word in word_tokenize(title)]
vectors.append(np.average(glove_vectors, axis = 0, weights = weights))
return np.array(vectors)x_train = tfidf_glove(train)
x_test = tfidf_glove(test)run_log_reg(x_train, x_test, y_train, y_test)**Output:** F1: 0.957 | Pr: 0.943 | Re: 0.971 | AUC: 0.989 | Accuracy: 0.956
我们的 F1 提高了大约 0.02 分。性能的提高是有意义的——经常出现的单词权重变小,而不经常出现(也许更重要)的单词在标题的向量表示中更有发言权。
既然 GloVe 工作得如此之好,让我们试试最后一种嵌入技术——脸书的下一代模型。该模型将整个句子转换成向量表示。然而,一个潜在的问题是,向量表示是 4096 维的,这可能导致我们的模型容易过度拟合。不管怎样,让我们试一试:
from InferSent.models import InferSent
import torchMODEL_PATH = './encoder/infersent1.pkl'
params_model = {'bsize': 64, 'word_emb_dim': 300, 'enc_lstm_dim': 2048,'pool_type': 'max', 'dpout_model': 0.0, 'version': 1}infersent = InferSent(params_model)
infersent.load_state_dict(torch.load(MODEL_PATH))infersent.set_w2v_path('GloVe/glove.840B.300d.txt')infersent.build_vocab(train.title.values, tokenize= False)x_train = infersent.encode(train.title.values, tokenize= False)
x_test = infersent.encode(test.title.values, tokenize= False)run_log_reg(x_train, x_test, y_train, y_test, alpha = 1e-4)**Output:** F1: 0.927 | Pr: 0.912 | Re: 0.946 | AUC: 0.966 | Accuracy: 0.926
正如预期的那样,性能下降—很可能是由于 4096 维特征的过度拟合。
在我们结束本节之前,让我们再次尝试 TSNE,这次是在 IDF 加权的手套向量上
这一次,我们在 2D 投影中看到了两个类别之间的一些分离。在某种程度上,这解释了我们用简单的 Log Reg 实现的高精度。
为了进一步提高性能,我们可以添加一些手工制作的功能。让我们在下一节中尝试一下。
7.特征工程
创建新功能可能很棘手。在这方面领先的最好方法是深入该领域,寻找研究论文、博客、文章等。相关领域中的 Kaggle 内核也是查找有趣特性信息的好方法。
对于 clickbait 检测,我们用于数据集的论文(Chakraborthy 等人)提到了他们使用的一些特征。我还找到了 Potthast 等人 (2016) [3],他们在其中记录了超过 200 个特性。
我们可以实现一些简单的方法以及上一节中的手套嵌入,并检查是否有任何性能改进。以下是这些功能的简要总结:
- 以数字开头:一个布尔特性,检查标题是否以数字开头。例如:“11 种不可思议的 XYZ 方式”
- Clickbait 短语 : Downworthy 是一个搞笑的 chrome 扩展,它用“更真实的标题”取代了 Clickbait 标题。Github repo 列出了流行的 clickbait 短语,如“你需要知道的一切”、“这就是发生的事情”等。我们可以使用这个列表来检查我们的数据集中的标题是否包含任何这些短语。Chakraborthy 等人还提供了一系列进一步的短语。
- Clickbait 正则表达式 : Downworthy 也有一些正则表达式,我们可以将它们与标题进行匹配。
- 数字点点点
- 可读性分数:计算 Flesch-Kincaid 等级和 Dale-Chall 可读性分数。这些分数提供了阅读标题的难易程度。textstat python 包提供了实现这些的简单方法。一般来说,我们认为新闻标题更难阅读。
- **简单文本特征:**最长单词的长度,以字符为单位的平均单词长度,以字符为单位的标题长度。
- 标点符号的数量
- 字比:这里我们计算 6 种不同的比:(一)。简单词汇(根据戴尔·查尔简单词汇列表的定义)(ii)停止词(iii)缩写词(例如:不是、不应该等)(iv)夸张词汇(根据 Chakraborthy 等人的定义,例如:惊人的、不可思议的等)(v)点击诱饵主题(Chakraborthy 等人定义了一些在点击诱饵标题中更常见的名词/主题,如“家伙”、“狗”等)(vi)非点击诱饵主题(与上述非点击诱饵标题相同,例如:印度、伊朗、政府等)
- 标签数量
- 情感评分:我们可以使用 NLTK 的 Vader 情感分析仪,得到每个标题的负面、中性、正面和复合评分。
- 嵌入:tfi df/手套/加重手套
实现这些之后,我们可以选择使用 sklearn 的PolynomialFeatures()
用多项式(如 X)或交互特征(如 XY)来扩展特征空间
注:特征缩放技术的选择对分类器的性能影响很大,我尝试了RobustScaler
StandardScaler
Normalizer
MinMaxScaler
,发现* MinMaxScaler
效果最好。***
**from featurization import *train_features, test_features, feature_names = featurize(train, test, 'tfidf_glove')run_log_reg(train_features, test_features, y_train, y_test, alpha = 5e-2)**Output:** F1: 0.964 | Pr: 0.956 | Re: 0.972 | AUC: 0.993 | Accuracy: 0.964**
不错!在简单的逻辑回归分析中,我们的 F1 值从 0.957 上升到 0.964。当我们尝试不同的模型并稍后进行超参数调整时,我们可能能够挤出更多的性能改进。
现在,让我们简短地探讨一下模型的可解释性,以检查我们的模型是如何做出这些预测的。我们将使用 SHAP 和 ELI5 库来理解这些特性的重要性。
特征权重
先说特征重要性。这对于 ELI5 库来说非常简单。
**from sklearn.linear_model import SGDClassifier
import eli5# Train a Log Reg Classifier
log_reg = SGDClassifier(loss = 'log', n_jobs = -1, alpha = 5e-2)
log_reg.fit(train_features, y_train)#Pass the model instance along with the feature names to ELI5
eli5.show_weights(log_reg, feature_names = feature_names, top = 100)**
****
Feature Weights
除了手套的尺寸,我们可以看到许多手工制作的特点有很大的重量。特征越环保,将样本归类为“点击诱饵”就越重要。
例如,starts_with_number
特征对于分类一个标题是 clickbait 是非常重要的。这很有意义,因为在数据集中,像“你应该去 XYZ 的 12 个理由”这样的标题经常是点击诱饵。
我们来看看dale_chall_readability_score
这个特征,它的权重是-0.280。如果 Dale Chall 可读性分数很高,说明标题很难读。在这里,我们的模型已经知道,如果一个标题更难阅读,它可能是一个新闻标题,而不是点击诱饵。相当酷!
此外,还有一些功能的权重非常接近于 0。移除这些特性可能有助于减少过度拟合,我们将在特性选择部分对此进行探讨。
SHAP 力剧情
现在让我们来看看 SHAP 力图
**import shaplog_reg = SGDClassifier(loss = 'log', n_jobs = -1, alpha = 5e-2)
log_reg.fit(train_features, y_train)explainer = shap.LinearExplainer(log_reg, train_features, feature_dependence = 'independent')
shap_values = explainer.shap_values(test_features)shap.initjs()
ind = 0
shap.force_plot(explainer.expected_value, shap_values[ind,:], test_features.toarray()[ind,:],
feature_names = feature_names)**
SHAP Force Plot
一个原力剧情就像是一场角色间的‘拔河’游戏。每个特征将模型的输出推到基值的左侧或右侧。基础值是模型在整个测试数据集上的平均输出。请记住,这不是一个概率值。
粉红色的特征有助于模型检测正面类别,即“点击诱饵”标题,而蓝色的特征检测负面类别。每个特征的宽度与其在预测中的权重成正比。
在上面的例子中,starts_with_number
特征是 1,并且非常重要,因此将模型的输出推到右边。另一方面,clickbait_subs_ratio
和easy_words_ratio
(这些特性中的高值通常表示 clickbait,但在这种情况下,值较低)都将模型推向左侧。
我们可以验证,在这个特定的例子中,模型最终预测“点击诱饵”
**print('Title: {}'.format(test.title.values[0]))
print('Label: {}'.format(test.label.values[0]))
print('Prediction: {}'.format(log_reg.predict(test_features.tocsr()[0,:])[0]))**Output:
Title**: 15 Highly Important Questions About Adulthood, Answered By Michael Ian Black
**Label**: clickbait
**Prediction**: 1**
正如所料,模型正确地将标题标记为 clickbait。
让我们看另一个例子:
SHAP Force Plot for Non-Clickbait Titles
**print('Title: {}'.format(test.title.values[400]))
print('Label: {}'.format(test.label.values[400]))
print('Prediction: {}'.format(log_reg.predict(test_features.tocsr()[400,:])[0]))**Output:
Title**: Europe to Buy 30,000 Tons of Surplus Butter
**Label**: not-clickbait
**Prediction**: 0**
在这种情况下,模型被推到左边,因为像sentiment_pos
(clickbait 标题通常具有正面情绪)这样的特征具有较低的值。
力图是一种很好的方式来观察模型是如何逐个样本地进行预测的。在下一节中,我们将尝试不同的模型,包括集成和超参数调整。
8.探索模型和超参数调整
在本节中,我们将使用我们在上一节中创建的功能,以及 IDF 加权嵌入,并在不同的模型上进行尝试。
如前所述,在处理小数据集时,像逻辑回归、支持向量机和朴素贝叶斯这样的低复杂度模型将会概括得最好。我们将这些模型与非参数模型(如 KNN)和非线性模型(如 Random Forest、XGBoost 等)一起尝试。
我们还将尝试使用性能最佳的分类器和模型堆叠进行引导聚合或打包。我们开始吧!
对于我们的情况,超参数调整GridSearchCV
是一个很好的选择,因为我们有一个小的数据集(允许它快速运行),这是一个穷举搜索。我们需要做一些修改,以使它(a)使用我们预定义的测试集,而不是交叉验证(b)使用我们的 F1 评估指标,该指标使用 PR 曲线来选择阈值。
GridSearchCV with PrefededfinedSplit
逻辑回归
**from sklearn.linear_model import SGDClassifierlr = SGDClassifier(loss = 'log')
lr_params = {'alpha' : [10**(-x) for x in range(7)],
'penalty' : ['l1', 'l2', 'elasticnet'],
'l1_ratio' : [0.15, 0.25, 0.5, 0.75]}best_params, best_f1 = run_grid_search(lr, lr_params, X, y)print('Best Parameters : {}'.format(best_params))lr = SGDClassifier(loss = 'log',
alpha = best_params['alpha'],
penalty = best_params['penalty'],
l1_ratio = best_params['l1_ratio'])
lr.fit(train_features, y_train)
y_test_prob = lr.predict_proba(test_features)[:,1]
print_model_metrics(y_test, y_test_prob)**Output:** Best Parameters : {'alpha': 0.1, 'l1_ratio': 0.15, 'penalty': 'elasticnet'}
F1: 0.967 | Pr: 0.955 | Re: 0.979 | AUC: 0.994 | Accuracy: 0.967**
请注意,调整后的参数同时使用了高 alpha 值(表示大量的正则化)和 elasticnet。这些参数选择是因为小数据集容易过拟合。
我们可以对 SVM、朴素贝叶斯、KNN、随机森林和 XGBoost 进行同样的调整。下表总结了这些测试的结果(您可以参考 GitHub repo 获得完整的代码)
Summary of Hyperparameter Tuning
简单的 MLP
在 fast.ai 课程中,杰瑞米·霍华德提到深度学习已经在许多情况下相当成功地应用于表格数据。让我们看看它在我们的用例中表现如何:
2-Layer MLP in Keras
y_pred_prob = simple _ nn . predict(test _ features . to dense())
print _ model _ metrics(y _ test,y _ pred _ prob)
****Output**:
F1: 0.961 | Pr: 0.952 | Re: 0.970 | AUC: 0.992 | Accuracy: 0.960**
鉴于数据集较小,两层 MLP 模型的效果令人惊讶。
装袋分级机
既然 SVM 做得如此之好,我们可以通过使用 SVM 作为基本估计量来尝试一个 bagging 分类器。这将改善基础模型的方差并减少过度拟合。
**from sklearn.ensemble import BaggingClassifier
from sklearn.svm import SVC
from sklearn.model_selection import RandomizedSearchCVsvm = SVC(C = 10, kernel = 'poly', degree = 2, probability = True, verbose = 0)svm_bag = BaggingClassifier(svm, n_estimators = 200, max_features = 0.9, max_samples = 1.0, bootstrap_features = False, bootstrap = True, n_jobs = 1, verbose = 0)svm_bag.fit(train_features, y_train)
y_test_prob = svm_bag.predict_proba(test_features)[:,1]
print_model_metrics(y_test, y_test_prob)**Output:** F1: 0.969 | Pr: 0.959 | Re: 0.980 | AUC: 0.995 | Accuracy: 0.969**
性能提升几乎微不足道。
最后,我们可以尝试的最后一件事是堆叠分类器(也称为投票分类器)
堆积分级机
这是不同模型预测的加权平均值。因为我们也使用 Keras 模型,所以我们不能使用 Sklearn 的VotingClassifier
,相反,我们将运行一个简单的循环,获得每个模型的预测,并运行一个加权平均。我们将为每个模型使用调整后的超参数。
Simple Stacking Classifier
****Output:** Training LR
Training SVM
Training NB
Training KNN
Training RF
Training XGB
F1: 0.969 | Pr: 0.968 | Re: 0.971 | AUC: 0.995 | Accuracy: 0.969**
现在,我们需要一种方法来为每个模型选择最佳权重。最好的选择是使用像 Hyperopt 这样的优化库,它可以搜索最大化 F1 分数的最佳权重组合。
Running Hyperopt for the stacking classifier
Hyperopt 找到一组给出 F1 ~ 0.971 的权重。让我们检查优化的砝码:
**{'KNN': 0.7866810233035141,
'LR': 0.8036572275670447,
'NB': 0.9102009774357307,
'RF': 0.1559824350958057,
'SVM': 0.9355079606348642,
'XGB': 0.33469066125332436,
'simple_nn': 0.000545264707939086}**
像逻辑回归、朴素贝叶斯和 SVM 这样的低复杂度模型具有高权重,而像随机森林、XGBoost 和 2 层 MLP 这样的非线性模型具有低得多的权重。这符合我们的预期,即低复杂性和简单模型将最好地概括较小的数据集。
最后,使用优化的权重运行堆叠分类器得到:
**F1: 0.971 | Pr: 0.962 | Re: 0.980 | AUC: 0.995 | Accuracy: 0.971**
在下一节中,我们将解决小数据集的另一个问题——高维特征空间。
9.降维
正如我们在简介中所讨论的,随着我们增加小数据集的维度,特征空间变得稀疏,导致分类器很容易过拟合。
解决方法就是降低维度。实现这一点的两种主要方法是特征选择和分解。
特征选择
这些技术根据特征在预测中的相关性来选择特征。
**SelectKBest**
我们从SelectKBest
开始,顾名思义,它只是根据所选的统计数据(默认为 ANOVA F-Scores)选择 k-best 特征
**from sklearn.feature_selection import SelectKBestselector = SelectKBest(k = 80)
train_features_selected = selector.fit_transform(train_features, y_train)
test_features_selected = selector.transform(test_features)
run_log_reg(train_features_selected, test_features_selected, y_train, y_test)**Output:** F1: 0.958 | Pr: 0.946 | Re: 0.971 | AUC: 0.989 | Accuracy: 0.957**
SelectKBest 的一个小问题是,我们需要手动指定想要保留的特性的数量。一种简单的方法是运行一个循环来检查每个 k 值的 F1 分数。下面是要素数量与 F1 分数的关系图:
F1 Scores for different values of K
大约 45 个特征给出了最佳 F1 值。让我们用 K = 45 重新运行 SelectKBest:
**selector = SelectKBest(k = 45)
train_features_selected = selector.fit_transform(train_features, y_train)
test_features_selected = selector.transform(test_features)
run_log_reg(train_features_selected, test_features_selected, y_train, y_test, alpha = 1e-2)**Output:** F1: 0.972 | Pr: 0.967 | Re: 0.978 | AUC: 0.995 | Accuracy: 0.972**
另一个选择是使用 SelectPercentile,它使用我们想要保留的特性的百分比。
**SelectPercentile**
按照与上面相同的步骤,我们得到最佳 F1 分数的百分位数= 37。现在使用 SelectPercentile:
**selector = SelectPercentile(percentile = 37)
train_features_selected = selector.fit_transform(train_features, y_train)
test_features_selected = selector.transform(test_features)
run_log_reg(train_features_selected, test_features_selected, y_train, y_test, alpha = 1e-2)**Output:** F1: 0.972 | Pr: 0.966 | Re: 0.979 | AUC: 0.995 | Accuracy: 0.972**
简单的特征选择将 F1 分数从 0.966(先前调整的 Log Reg 模型)增加到 0.972。如前所述,这是因为低维特征空间减少了模型过拟合的机会。
对于这两种技术,我们也可以使用selector.get_support()
来检索所选特征的名称。
**np.array(feature_names)[selector.get_support()]**Output:** array(['starts_with_number', 'easy_words_ratio', 'stop_words_ratio',
'clickbait_subs_ratio', 'dale_chall_readability_score', 'glove_3',
'glove_4', 'glove_6', 'glove_10', 'glove_14', 'glove_15',
'glove_17', 'glove_19', 'glove_24', 'glove_27', 'glove_31',
'glove_32', 'glove_33', 'glove_35', 'glove_39', 'glove_41',
'glove_44', 'glove_45', 'glove_46', 'glove_49', 'glove_50',
'glove_51', 'glove_56', 'glove_57', 'glove_61', 'glove_65',
'glove_68', 'glove_72', 'glove_74', 'glove_75', 'glove_77',
'glove_80', 'glove_85', 'glove_87', 'glove_90', 'glove_92',
'glove_96', 'glove_97', 'glove_98', 'glove_99'], dtype='<U28')**
**RFECV (Recursive Features Elimination)**
RFE 是一种后向特征选择技术,它使用估计器来计算每个阶段的特征重要性。名称中的单词 recursive 意味着该技术递归地删除了对分类不重要的特征。
我们将使用 CV 变量,它在每个循环中使用交叉验证来确定在每个循环中要删除多少个特征。RFECV 需要一个具有feature_importances_
属性的估计器,因此我们将使用具有 log loss 的 SGDClassifier。
我们还需要指定所需的交叉验证技术的类型。我们将使用在超参数优化中使用的相同的PredefinedSplit
。
**from sklearn.feature_selection import RFECVlog_reg = SGDClassifier(loss = ‘log’, alpha = 1e-3)selector = RFECV(log_reg, scoring = ‘f1’, n_jobs = -1, cv = ps, verbose = 1)
selector.fit(X, y)# Now lets select the best features and check the performance
train_features_selected = selector.transform(train_features)
test_features_selected = selector.transform(test_features)run_log_reg(train_features_selected, test_features_selected, y_train, y_test, alpha = 1e-1)**Output:** F1: 0.978 | Pr: 0.970 | Re: 0.986 | AUC: 0.997 | Accuracy: 0.978**
让我们检查一下所选的功能:
**print('Number of features selected:{}'.format(selector.n_features_))
np.array(feature_names)[selector.support_]**Output:** Number of features selected : 60
array(['starts_with_number', 'clickbait_phrases', 'num_dots',
'mean_word_length', 'length_in_chars', 'easy_words_ratio',
'stop_words_ratio', 'contractions_ratio', 'hyperbolic_ratio',
'clickbait_subs_ratio', 'nonclickbait_subs_ratio',
'num_punctuations', 'glove_1', 'glove_2', 'glove_4','glove_6'
'glove_10', 'glove_13', 'glove_14', 'glove_15', 'glove_16',
'glove_17', 'glove_21', 'glove_25', 'glove_27', 'glove_32',
'glove_33', 'glove_35', 'glove_39', 'glove_41', 'glove_43',
'glove_45', 'glove_46', 'glove_47', 'glove_50', 'glove_51',
'glove_52', 'glove_53', 'glove_54', 'glove_56', 'glove_57',
'glove_58', 'glove_61', 'glove_65', 'glove_72', 'glove_74',
'glove_77', 'glove_80', 'glove_84', 'glove_85', 'glove_86',
'glove_87', 'glove_90', 'glove_93', 'glove_94', 'glove_95',
'glove_96', 'glove_97', 'glove_98', 'glove_99'], dtype='<U28')**
这一次,我们选择了一些额外的特性,使性能略有提高。由于传递了估计量和 CV 集,该算法有更好的方法来判断保留哪些特征。
这里的另一个优点是,我们不必提及要保留多少特性,RFECV
会自动为我们找到。然而,我们可以提到我们希望拥有的特性的最小数量,默认情况下是 1。
**SFS**
(顺序向前选择)
最后,让我们试试SFS
——它和RFE
做同样的事情,但是依次添加特性。SFS
从 0 个特征开始,以贪婪的方式在每个循环中逐个添加特征。一个小的区别是SFS
只使用 CV 集上的特征集性能作为选择最佳特征的度量,不像RFE
使用模型权重(feature_importances_
)。
**# Note: mlxtend provides the SFS Implementation
from mlxtend.feature_selection import SequentialFeatureSelectorlog_reg = SGDClassifier(loss = ‘log’, alpha = 1e-2)selector = SequentialFeatureSelector(log_reg, k_features = ‘best’, floating = True, cv = ps, scoring = ‘f1’, verbose = 1, n_jobs = -1) # k_features = ‘best’ returns the best subset of features
selector.fit(X.tocsr(), y)train_features_selected = selector.transform(train_features.tocsr())
test_features_selected = selector.transform(test_features.tocsr())run_log_reg(train_features_selected, test_features_selected, y_train, y_test, alpha = 1e-2)**Output:** F1: 0.978 | Pr: 0.976 | Re: 0.981 | AUC: 0.997 | Accuracy: 0.978**
我们还可以检查选定的功能:
**print('Features selected {}'.format(len(selector.k_feature_idx_)))
np.array(feature_names)[list(selector.k_feature_idx_)]**Output:** Features selected : 53array(['starts_with_number', 'clickbait_phrases','mean_word_length',
'length_in_chars','stop_words_ratio','nonclickbait_subs_ratio',
'flesch_kincaid_grade', 'dale_chall_readability_score',
'num_punctuations', 'glove_0', 'glove_1', 'glove_2','glove_4'
'glove_8', 'glove_10', 'glove_13', 'glove_14', 'glove_15',
'glove_16', 'glove_17', 'glove_18', 'glove_25', 'glove_30',
'glove_32', 'glove_33', 'glove_38', 'glove_39', 'glove_40',
'glove_41', 'glove_42', 'glove_45', 'glove_46', 'glove_47',
'glove_48', 'glove_51', 'glove_56', 'glove_57', 'glove_61',
'glove_65', 'glove_67', 'glove_69', 'glove_72', 'glove_73',
'glove_76', 'glove_77', 'glove_80', 'glove_81', 'glove_84',
'glove_85', 'glove_87', 'glove_93', 'glove_95', 'glove_96'],
dtype='<U28')**
向前和向后选择经常给出相同的结果。现在让我们来看看分解技术。
分解
与挑选最佳特征的特征选择不同,分解技术分解特征矩阵以降低维数。由于这些技术改变了特征空间本身,一个缺点是我们失去了模型/特征的可解释性。我们不再知道分解的特征空间的每个维度代表什么。
让我们尝试在我们的特征矩阵上截断 VD。我们要做的第一件事是找出解释的方差是如何随着元件数量而变化的。
**from sklearn.decomposition import TruncatedSVDsvd = TruncatedSVD(train_features.shape[1] - 1)
svd.fit(train_features)
plt.plot(np.cumsum(svd.explained_variance_ratio_))**
Plot to find out n_components for TruncatedSVD
看起来仅仅 50 个组件就足以解释训练集特征中 100%的差异。这意味着我们有许多从属特征(即一些特征只是其他特征的线性组合)。
这与我们在特征选择部分看到的一致——尽管我们有 119 个特征,但大多数技术选择了 40-70 个特征(剩余的特征可能不重要,因为它们只是其他特征的线性组合)。
现在我们可以将特征矩阵减少到 50 个组件。
**svd = TruncatedSVD(50)
train_featurse_decomposed = svd.fit_transform(train_features)
test_featurse_decomposed = svd.transform(test_features)
run_log_reg(train_featurse_decomposed, test_featurse_decomposed, y_train, y_test, alpha = 1e-1)**Output:** F1: 0.965 | Pr: 0.955 | Re: 0.975 | AUC: 0.993 | Accuracy: 0.964**
性能不如特征选择技术——为什么?
分解技术(如 TruncatedSVD)的主要工作是用较少的分量解释数据集中的方差。这样做时,它从不考虑每个特征在预测目标时的重要性(“点击诱饵”或“非点击诱饵”)。然而,在特征选择技术中,每次移除或添加特征时都使用特征重要性或模型权重。RFE
和SFS
特别选择功能以优化模型性能。(您可能已经注意到,在特性选择技术中,我们在每个 *fit()*
调用中都传递了‘y’。)
具有特征选择的堆叠分类器
最后,我们可以将上述任何技术与性能最佳的模型——堆叠分类器结合使用。我们必须将每个模型重新调整到缩减的特征矩阵,并再次运行 hyperopt 以找到堆叠分类器的最佳权重。
现在,在使用RFECV
选定功能并重新调整后:
**F1: 0.980 | Pr: 0.976 | Re: 0.984 | AUC: 0.997 | Accuracy: 0.980**
10.总结:
以下是我们迄今为止运行的所有模型和实验的总结:
Summary of all experiments
让我们来看看堆叠分类器的混淆矩阵:
Stacking Classifier Confusion Matrix
以下是十大高可信度的错误分类书目:
**Title : A Peaking Tiger Woods
Label : not-clickbait
Predicted Probability : 0.7458264596039637
----------
Title : Stress Tests Prove a Sobering Idea
Label : not-clickbait
Predicted Probability : 0.7542456646954389
----------
Title : Woods Returns as He Left: A Winner
Label : not-clickbait
Predicted Probability : 0.7566487248241188
----------
Title : In Baseball, Slow Starts May Not Have Happy Endings
Label : not-clickbait
Predicted Probability : 0.7624898001334597
----------
Title : Ainge Has Heart Attack After Celtics Say Garnett May Miss Playoffs
Label : not-clickbait
Predicted Probability : 0.7784241132465458
----------
Title : Private Jets Lose That Feel-Good Factor
Label : not-clickbait
Predicted Probability : 0.7811035856329488
----------
Title : A Little Rugby With Your Cross-Dressing?
Label : not-clickbait
Predicted Probability : 0.7856236669189782
----------
Title : Smartphone From Dell? Just Maybe
Label : not-clickbait
Predicted Probability : 0.7868008600434597
----------
Title : Cellphone Abilities That Go Untapped
Label : not-clickbait
Predicted Probability : 0.8057172770139488
----------
Title : Darwinism Must Die So That Evolution May Live
Label : not-clickbait
Predicted Probability : 0.8305944075171504
----------**
所有高可信度的错误分类标题都是“非点击诱饵”,这反映在混淆矩阵中。
乍一看,这些标题似乎与常规的新闻标题大相径庭。以下是从测试集中随机选择的“非点击诱饵”标题的示例:
**test[test.label.values == 'not-clickbait'].sample(10).title.values**Output:** array(['Insurgents Are Said to Capture Somali Town',
'Abducted teen in Florida found',
'As Iraq Stabilizes, China Eyes Its Oil Fields',
'Paramilitary group calls for end to rioting in Northern Ireland',
'Finding Your Way Through a Maze of Smartphones',
'Thousands demand climate change action',
'Paternity Makes Punch Line of Paraguay President',
'Comcast and NFL Network Continue to Haggle',
'Constant Fear and Mob Rule in South Africa Slum',
'Sebastian Vettel wins 2010 Japanese Grand Prix'], dtype=object)**
你怎么想呢?
我们可以尝试一些技术,如半监督伪标签,回译等,以尽量减少这些假阳性,但在博客长度的利益,我会留到另一个时间。
总之,通过了解过拟合在小型数据集中的工作方式以及特征选择、堆叠、调整等技术,我们能够在仅有 50 个样本的情况下将性能从 F1 = 0.801 提高到 F1 = 0.98。还不错!
如果你有任何问题,请随时与我联系。我希望你喜欢!
****GitHub Repo:https://GitHub . com/anirudhshenoy/text-classification-small-datasets
参考资料:
- https://www . BuzzFeed . com/Ben Smith/why-BuzzFeed-donts-do-click bait
- Abhijnan Chakraborty、Bhargavi Paranjape、Sourya Kakarla 和 Niloy Ganguly。“阻止点击诱饵:检测和防止在线新闻媒体中的点击诱饵”。2016 年美国旧金山 2016 年 8 月 IEEE/ACM 社交网络分析和挖掘进展国际会议(ASONAM)论文集。(https://github.com/bhargaviparanjape/clickbait)
- 米(meter 的缩写))Potthast,S . kpsel,B.Stein,M.Hagen,Clickbait Detection (2016)发表于 ECIR 2016 年https://webis . de/downloads/publications/papers/Stein _ 2016 B . pdf
- https://www . kdnugges . com/2016/10/adversarial-validation-explained . html
- 看淡:https://github.com/snipe/downworthy
- dale Chall Easy word list:hTTP://www . readability formulas . com/articles/dale-Chall-readability-word-list . PHP
- terrier Stop word list:https://github . com/terrier-org/terrier-desktop/blob/master/share/Stop word-list . txt
- https://www . vision dummy . com/2014/04/curse-dimensionality-affect-class ification/# The _ curse _ of _ dimensionality _ and _ over fitting
文本数据扩充使您的模型更强大
使用马尔可夫链生成文本数据,以提高模型性能
Photo by Julienne Erika Alviar on Unsplash
文本分类算法对训练中存在的多样性极其敏感。一个健壮的 NLP 流水线必须考虑到低质量数据存在的可能性,并试图以最好的方式解决这个问题。
处理图像时,加强分类算法和引入多样性的标准方法是操作数据扩充。现在有很多漂亮和聪明的技术来操作自动图像增强。在自然语言处理任务中,文本数据扩充的方法并不常见,结果也不明确。
在这篇文章中,我将展示一个简单直观的技术来执行文本数据生成。使用马尔可夫链规则,我们将能够生成新的文本样本来填充我们的模型并测试其性能。
数据集
我从卡格尔那里得到了我们实验的数据。优步骑行评论数据集是 2014-2017 年期间发布的骑行评论集,从网上搜集而来。在里面,我们可以找到原始的文字评论、用户给出的乘坐评级(1-5)和乘坐感受(如果评级高于 3:感受为 1,否则为 0)。如你所见,这是一个不平衡的分类问题,骑行评论的分布偏向于正面评价。
Label Distributions: the reviews with ‘3 stars Ride Rating’ are excluded from the analysis
首先,我们的目标是预测适合和尝试不同架构的评论的情绪。最有趣的一点发生在第二阶段,我们想给我们的模型施加压力;即我们让他们预测一些用马尔可夫链随机产生的虚假数据。我们想测试我们的模型是否足够稳定,以实现来自列车的足够的性能预测数据(在添加一些噪声之后)。如果一切正常,我们的模型应该不会有问题,在这个假数据上产生良好的结果,并有望提高测试性能,相反,我们需要重新审视训练过程。
文本数据扩充
在开始训练程序之前,我们必须生成我们的假数据。都开始研究火车上复习长度的分布。
Review Length Distribution
我们必须存储这些信息,因为我们的新评论将有类似的长度分布。生成过程由两个阶段组成。第一种,我们“构建链”,即,我们接收文本集合(在我们的情况下是训练语料库)作为输入,并自动为每个单词记录语料库中存在的每个可能的后续单词。在第二阶段,我们可以简单地基于之前的链创建新的评论…我们从起始语料库的整个词汇中随机选择一个词(我们评论的开始),并随机选择下面的新词进入其链。在这个决定的最后,我们准备从新选择的单词重新开始这个过程。一般来说,我们在模拟一个马尔可夫链过程,在这个过程中,为了建立一个新的评论,一个词的选择仅仅基于前一个词。
我在一个独特的函数(生成器)中集合了这两个阶段。该函数接收文本评论作为输入,带有相关标签,以及要生成的新实例的期望前缀数量(针对每个类)。原始长度分布是有用的,因为我们可以从中抽取评论的合理长度。
def **build_chain**(texts):
index = 1
chain = {}
for text in texts:
text = text.split()
for word in text[index:]:
key = text[index-1]
if key in chain:
chain[key].append(word)
else:
chain[key] = [word]
index += 1
index = 1
return chaindef **create_sentence**(chain, lenght):
start = random.choice(list(chain.keys()))
text = [start] while len(text) < lenght:
try:
after = random.choice(chain[start])
start = after
text.append(after)
except: #end of the sentence
#text.append('.')
start = random.choice(list(chain.keys()))
return ' '.join(text)def **Generator**(x_train, y_train, rep, concat=False, seed=33):
np.random.seed(seed)
new_corpus, new_labels = [], []
for i,lab in enumerate(np.unique(y_train)): selected = x_train[y_train == lab]
chain = build_chain(selected) sentences = []
for i in range(rep):
lenght = int(np.random.choice(lenghts, 1, p=freq))
sentences.append(create_sentence(chain, lenght)) new_corpus.extend(sentences)
new_labels.extend([lab]*rep)
if concat:
return list(x_train)+new_corpus, list(y_train)+new_labels
return new_corpus, new_labels
我们需要带标签的文本作为输入,因为我们将生成过程分成不同的子过程:来自特定类的评论被选择来为同一类生成新的评论;因此,我们需要区分构建链和采样过程,以便为我们的预测模型生成真实的样本。
Example of randomly generated reviews. Don’t care about their literally meaning
模特们
我们在训练和测试中分割初始数据集。我们用火车作为语料库来支持我们的生成器,并创建新的评论。我们生成 200 个(每个类 100 个)评论以形成新的独立测试集,并生成 600 个(每个类 300 个)评论以加强我们的训练集。我们的模型库由一个层感知器神经网络、一个逻辑回归和一个随机森林组成。培训过程分为两个阶段。首先,我们用原始训练拟合所有模型,并分别在测试和伪测试数据上检查性能。我们期望所有的模型都优于假测试数据,因为它们是从训练中生成的。其次,我们用强化训练重复我们的模型的拟合,并在我们的测试集上检查性能。
Performace report on the true test set
Performace report on the fake test set
在第一阶段,测试数据的最佳模型是神经网络(AUC、precision、recall 和 f1 被报告为性能指标),但令人惊讶的是,逻辑回归和随机森林在假测试中失败了!这表明我们的模型不太合适。我们再次尝试拟合模型,但这次我们使用强化训练集。在这一点上,所有模型在原始测试中的性能都有所提高,现在它们也开始在假数据上进行很好的推广。
摘要
在这篇文章中,我组装了一个简单的程序来生成假文本数据。当我们安装一个 NLP 分类器并想测试它的强度时,这种技术对我们很有用。如果我们的模型不能很好地分类来自训练的虚假数据,那么重新访问训练过程、调整超参数或直接在训练中添加这些数据是合适的。
保持联系: Linkedin
文本编码研究综述
执行任何文本挖掘操作(如主题检测或情感分析)的关键是将单词转换成数字,将单词序列转换成数字序列。一旦我们有了数字,我们就回到了众所周知的数据分析游戏中,机器学习算法可以帮助我们进行分类和聚类。
在这里,我们将重点放在将单词转换成数字和将文本转换成数字向量的分析部分:文本编码。
对于文本编码,有几种可用的技术,每一种都有自己的优缺点,并且每一种都最适合特定的任务。最简单的编码技术不保留词序,而其他编码技术可以。一些编码技术快速而直观,但是产生的文档向量的大小随着字典的大小而快速增长。其他编码技术优化了向量维度,但损失了可解释性。让我们来看看最常用的编码技术。
1。一键或频繁文档矢量化(未订购)
一种常用的文本编码技术是文档矢量化。这里,从文档集合中所有可用的单词构建一个字典,每个单词成为向量空间中的一列。每个文本都变成了 0 和 1 的向量。1 表示单词存在,0 表示单词不存在。文档的这种数字表示被称为一键文档矢量化。
这种一键矢量化的变体使用文档中每个单词的频率,而不仅仅是它的存在/不存在。这种变化被称为基于频率的矢量化。
虽然这种编码易于解释和生成,但它有两个主要缺点。它不保留文本中的词序,最终向量空间的维数随着词词典快速增长。
例如,在考虑否定或语法结构时,文本中单词的顺序很重要。另一方面,一些更原始的 NLP 技术和机器学习算法可能无论如何都不会利用词序。
此外,向量空间的快速增长可能只会成为大型字典的问题。并且即使在这种情况下,例如通过从文档文本中清除和/或提取关键词,也可以将字数限制到最大值。
2。一键编码(有序)
一些机器学习算法可以在序列中建立项目的内部表示,如句子中的有序单词。例如,递归神经网络(RNNs)和 LSTM 层可以利用序列顺序来获得更好的分类结果。
在这种情况下,我们需要从一键文档矢量化转移到一键编码,其中保留了单词顺序。这里,文档文本再次由单词存在/不存在的向量表示,但是单词被顺序地输入到模型中。
当使用独热编码技术时,每个文档由一个张量表示。每个文档张量由可能非常长的 0/1 向量序列组成,导致文档语料库的非常大且非常稀疏的表示。
3。基于索引的编码
另一种保留单词在句子中出现的顺序的编码是基于索引的编码。基于索引的编码背后的思想是将每个单词映射到一个索引,即一个数字。
第一步是创建一个将单词映射到索引的字典。基于这个字典,每个文档通过一系列索引(数字)来表示,每个数字编码一个单词。基于索引的编码的主要缺点是它在文本之间引入了一个实际上并不存在的数字距离。
注意,基于索引的编码允许不同长度的文档向量。事实上,索引序列的长度是可变的,而文档向量的长度是固定的。
4。单词嵌入
我们想探索的最后一种编码技术是单词嵌入。单词嵌入是一系列自然语言处理技术,旨在将语义映射到几何空间。1 这是通过将数字向量与字典中的每个单词相关联来实现的,因此任意两个向量之间的距离将捕获两个关联单词之间的部分语义关系。由这些向量形成的几何空间称为嵌入空间。最著名的单词嵌入技术是 Word2Vec 和 GloVe。
实际上,我们将每个单词投影到一个连续的向量空间,由一个专用的神经网络层产生。神经网络层学习关联每个单词的矢量表示,这有利于其整体任务,例如周围单词的预测。2
辅助预处理技术
许多机器学习算法需要固定长度的输入向量。通常,最大序列长度被定义为文档中允许的最大字数。较短的文档用零填充。较长的文档会被截断。零填充和截断是文本分析的两个有用的辅助准备步骤。
补零意味着根据需要添加尽可能多的零,以达到允许的最大字数。
截断是指在达到最大字数后切断所有单词。
总结
我们探讨了四种常用的文本编码技术:
- 文档矢量化
- 一键编码
- 基于索引的编码
- 单词嵌入
文档矢量化是唯一不保留输入文本中单词顺序的技术。但是,它很容易解释,也很容易生成。
一键编码是在保留序列中的单词顺序和保持结果的易解释性之间的折衷。要付出的代价是一个非常稀疏,非常大的输入张量。
基于索引的编码试图通过将每个单词映射到一个整数索引并将索引序列分组到一个集合类型列中来解决输入数据大小减小和序列顺序保持的问题。
最后,单词嵌入将基于索引的编码或一键编码投影到具有较小维度的新空间中的数值向量中。新空间由深度学习神经网络中嵌入层的数值输出来定义。这种方法的额外优点包括具有相似角色的单词的紧密映射。当然,缺点是复杂程度更高。
我们希望我们已经对当前可用的文本编码技术提供了足够全面和完整的描述,以便您选择最适合您的文本分析问题的技术。
参考文献
1 Chollet,Francois " 在 Keras 模型中使用预先训练的单词嵌入",Keras 博客,2016 年
2 Brownlee,Jason " 如何使用单词嵌入层与 Keras 进行深度学习,《机器学习之谜》,2017
首次发表于 数据科学中心。
深度学习的文本匹配
在我们的日常生活中,我们总是想知道它们是否是相似的东西。典型的例子之一是 Face ID。苹果推出了一个面部识别系统,用于解锁你的 iPhone X。你必须拍几张照片作为黄金图像。当你想解锁你的 iPhone,iPhone 计算当前照片是否匹配预定义的照片。
Photo by Edward Ma on Unsplash
在以前的博客中,我分享了使用单词存在测量和 WMD 来计算两个句子之间的差异。与以前的方法不同,我们应用神经网络来解决同样的问题。
看完这篇文章,你会明白:
- 计算句子相似度的原因
- 曼哈顿 LSTM
- 曼哈顿 LSTM 变体
计算句子相似度的原因
“black clothes hanged in rack” by The Creative Exchange on Unsplash
除了图像领域,我们能在自然语言处理领域应用相似性检查吗?作为 Stack Overflow 这样的论坛所有者,你不希望有很多重复的问题,因为这会损害用户体验。当从搜索引擎中搜索某个东西时,你会发现搜索结果包含一些相似的东西,但不仅仅是你输入的内容。
根据我的项目经验,我利用这种方法来比较客户名称。由于某些原因,输入是模糊的,模型必须为应用程序找到最相似的客户名称。
曼哈顿 LSTM
“New York street during daytime” by Aaron Sebastian on Unsplash
Muelle 等人在 2016 年提出了用于学习句子相似性的曼哈顿 LSTM 架构。曼哈顿 LSTM 的总体目标是比较两个句子,以确定它们是否相同。这种神经网络结构包括两个相同的神经网络。两个输入通过相同的神经网络(共享权重)。
首先,将两个句子转换为向量表示(即嵌入),然后将其传递给神经网络。两个向量表示将进入两个子神经网络(共享权重)。与其他语言模型 RNN 架构不同,它不预测下一个单词,而是计算两个句子之间的相似度。
在实验过程中,Muelle 等人使用:
- 矢量: word2vec
- 词向量维数:300
- 损失函数:均方误差(MSE)
- 优化器:Adadelta
- LSTM 单位数量:50
曼哈顿 LSTM 变体
这个概念是,你可以建立任何简单或复杂的神经网络,只要它接受两个输入。根据我的经验,你可以尝试任何更复杂的曼哈顿 LSTM 神经网络。我还包括了额外的单词特性和其他 RNN 架构,如 GRU 或注意力机制。
拿走
- 准备大量带标签的数据很重要
- 总计算时间可能很长。对于我的情况,我必须在预测时比较所有客户名称(> 5M)。因此,我不得不使用其他方法来减少记录数量,使其能够满足在线预测的要求。
关于我
我是湾区的数据科学家。专注于数据科学、人工智能,尤其是 NLP 和平台相关领域的最新发展。你可以通过媒体博客、 LinkedIn 或 Github 联系我。
参考
Keras 实施:https://github.com/likejazz/Siamese-LSTM
Thyagarajan muelle j ...“用于学习句子相似性的暹罗循环结构”。2016.hTTP://www . MIT . edu/~ jonasm/info/MuellerThyagarajan _ aaai 16 . pdf
放大图片作者:Koch G ...“用于一次性图像识别的连体神经网络”。2015.http://www.cs.cmu.edu/~rsalakhu/papers/oneshot1.pdf
民主辩论中的文本挖掘
用 R 分析文本的简短介绍
到目前为止,已经有 6 场正式的民主辩论,未来还会有更多。辩论时间很长,坦率地说非常无聊。辩论的目的是向美国介绍候选人,了解他们的政策立场。然而,美国人的注意力持续时间很短,只有 3 个小时,所以花在看电视上的时间很多。总的来说,一个人会花 18 个小时观看辩论。这根本不现实,必须有更好的方法来客观地总结辩论。
文本挖掘简介
文本挖掘是从文本中提取信息的实践。诸如 n-grams、单词包和主题建模等技术是文本挖掘中的一些基本技术。我相信文本挖掘将是一个比机器学习更重要的领域,因为社交媒体与商业的整合越来越多。我们生活在一个收集和存储数据极其容易和廉价的时代。企业现在正在探索处理和理解数据的方法,这导致了机器学习、深度学习和人工智能。然而,非结构化数据正在增长,尤其是文本数据。消费者评论、推文和电子邮件是企业希望利用的非结构化数据的例子。所有这些听起来极其复杂;非结构化数据的机器学习?理解语言的神经网络?怎么可能呢?信不信由你,从文本中提取真知灼见可以像计算字数一样简单。文本挖掘最难的部分是收集数据。
幸运的是,每次辩论后,新闻机构都会发布辩论记录。我下载了文字记录,并把它整理成一个简单的 csv 文件,可以在这里找到。R 和 Python 都有很多文本挖掘包。我将使用 TidyText,它有一本很棒的教科书来学习文本的基础知识,这篇文章基本上是技术的总结。
N-grams 和单词袋
N-grams 和词袋是大多数文本挖掘技术的基础。他们背后的想法是计算每个单词。鉴于句子“我喜欢狗。”单词袋特征将如下所示。
现在让我们看看有了单词袋功能的两个句子会是什么样子。
请注意,对于“我喜欢猫”,狗的功能计数为 0。单词袋功能有助于将文本数据映射成传统的数字格式。
N-grams 就像是单词袋,只不过多了一个步骤。N-grams 不是像单词袋那样计算一个单词,而是指定有多少个单词。n 是字数。所以,2-grams 或" bigrams "是两个词。让我们用前面的句子来看看一个二元模型的特征是什么样的。
看表的时候和单词袋表看起来没什么区别。然而, bigrams 添加了更多的上下文,我们可以看到狗和猫像一样与一词配对。这意味着我们可以看到,这两个句子对这两种动物都是积极的。你甚至可以进一步使用 n 元语法,如三元语法、四元语法、五元语法等。N-grams 添加上下文,但是,可以开始变得非常具体。这可能是件好事,也可能是件坏事。
R 中的 N-grams 和词袋特征工程
可以使用正则表达式函数生成 N-gram 和单词包,但是正则表达式看起来很乱,而且有一些包可以完成大部分的跑腿工作。Tidytext 包含一个名为**的函数 unnest_tokens。**记号在文本挖掘中被提到很多。标记是文本挖掘的输入,因此单词包和 n 元语法都将被视为标记。
首先,我们将加载包并进行一些格式化。数据集中有三列;辩论、性格和文本。我从记录中过滤掉了版主和其他不知名的人,这样数据只包含总统候选人。
library(tidyverse)
library(tidytext)df <- read.csv("DemDebates.csv", colClasses = c("factor","factor","character"))df <- df %>%
filter(!character %in% c("(Unknown)", "Announcer","Bash","Bridgewater","Burnett","Cooper","Davis","Diaz-Balart","Guthrie","Holt","Jose Diaz-Balart","Lacey","Lemon","Lester Holt", "Maddow","Muir","Protesters","Protestor","Ramos","Savannah Guthrie","Stephanopoulos","Tapper","Todd","Unknown"))
现在我们将使用 unnest_tokens 函数提取单词包。第一个输入命名令牌,第二个输入是包含文本的列,第三个输入指定令牌的类型,最后一个输入是 n 元语法的 n。因此,对于单词包,我们将指定 n = 1。
df %>% unnest_tokens(word, "text", token = "ngrams", n =1)
现在我们有了单词,我们需要计算它们。这是一个简单的计数函数,我们将按字符计数。我还将筛选出每个候选人的前 5 个单词,并按候选人和词频排序。所有这些都将在一个命令中完成,但是,您可以将单词包分配给一个变量。
df %>%
unnest_tokens(word, "text", token = "ngrams", n =1) %>%
count(character, word) %>%
group_by(character) %>%
top_n(n, n = 5) %>%
arrange(character, -n)
如你所见,每个候选人的前 5 个单词并不十分有用。列表中充满了几乎没有意义的单词。这些词被称为停用词,通常会被过滤掉。tidytext 包包含一个频繁停用词的列表,我们可以用它来过滤单词包列表。这将通过来自 dplyr 的 anti_join 来完成,尽管您也可以使用过滤器功能。Tidytext 将它的许多功能与 tidyverse 集成在一起,使它非常直观。
df %>%
unnest_tokens(word, "text", token = "ngrams", n =1) %>%
anti_join(stop_words) %>%
count(character, word) %>%
group_by(character) %>%
top_n(n, n = 5) %>%
arrange(character, -n)
现在一些有趣的事情正在发生。这些词看起来有些相关,可以给每个候选人一些见解。让我们和候选人一起画单词。我们将使用 ggplot 并制作一个简单的条形图,显示每个候选人的前 5 个单词及其频率。我还将使用 facet_wrap ,为一列中的每个值创建一个单独的图。这将为每个候选人创建单独的图表。绘制单词或分类变量的一个常见问题是排列它们,但是 tidytext 提供了帮助这个过程的函数。 reorder_within 排列单词,并在使用 facet_wrap 时帮助保持排序。此外scale _ x _ recordered需要与它一起使用来格式化 x 轴。
df %>%
unnest_tokens(word, "text", token = "ngrams", n =1) %>%
anti_join(stop_words) %>%
count(character, word) %>%
group_by(character) %>%
top_n(n, n = 5) %>%
arrange(character, -n) %>%
ggplot(aes(x = reorder_within(word, n, character),#Reorders word by freq
y = n,
fill = character)) +
geom_col() +
scale_x_reordered() + #Reorders the words
facet_wrap(~character, scales ="free") + #Creates individual graphs
coord_flip() +
theme(legend.position = "None")
这个图表非常好,揭示了当前候选人的很多情况。民主党人在谈论人民、总统、特朗普、美国、政府、医疗保健、气候等。所有这些都是有道理的,但是,所有的候选人都使用相同的单词,并且没有解释每个候选人的细节。让我们看看每个候选人的二元模型。
虽然您应该将令牌重命名为 bigram,但是我们可以将 n = 1 改为 n = 2。看到用 tidytext 看 n 元图有多简单了吧?
df %>%
unnest_tokens(word, "text", token = "ngrams", n =2) %>%
anti_join(stop_words) %>%
count(character, word) %>%
group_by(character) %>%
top_n(n, n = 5) %>%
arrange(character, -n) %>%
ggplot(aes(x = reorder_within(word, n, character),#Reorders the words by freq
y = n,
fill = character)) +
geom_col() +
scale_x_reordered() + #Reorders the words
facet_wrap(~character, scales ="free") + #Creates individual graphs
coord_flip() +
theme(legend.position = "None")
好吧,也许没那么简单。anti_join 命令正在寻找单字或单词,而不是双字。我们可以通过使用分离和联合功能进行过滤。我们只是创建两列,包含二元模型的单词 1 和单词 2,如果其中一个单词包含停用词,就过滤掉二元模型。
df %>%
unnest_tokens(word, "text", token = "ngrams", n =2) %>%
separate(word, c("word1","word2"), sep = " ") %>%
filter(!word1 %in% stop_words$word | !word2 %in% stop_words$word) %>%
unite("bigram", c(word1, word2), sep = " ") %>%
count(character,bigram) %>%
group_by(character) %>%
top_n(n, n = 5) %>%
arrange(character, -n) %>%
ggplot(aes(x = reorder_within(bigram, n, character),#Reorders the words by freq
y = n,
fill = character)) +
geom_col() +
scale_x_reordered() + #Reorders the words
facet_wrap(~character, scales ="free") + #Creates individual graphs
coord_flip() +
theme(legend.position = "None")
正如你所看到的,二元模型对每个候选人来说信息更丰富。贝托谈论埃尔帕索,桑德斯谈论全民医疗保险。我们还可以评估这些辩论,看看它们之间是否有什么主题。
df %>%
unnest_tokens(bigram, "text", token = "ngrams", n =2) %>%
separate(bigram, c("word1","word2"), sep = " ") %>%
filter(!word1 %in% stop_words$word | !word2 %in% stop_words$word) %>%
unite("bigram", c("word1", "word2"), sep = " ") %>%
count(debate, bigram) %>%
group_by(debate) %>%
top_n(n, n =5) %>%
ggplot(aes(x = reorder_within(bigram, n, debate),
y = n,
fill = debate)) +
geom_col() +
scale_x_reordered() +
facet_wrap(~debate, scales = "free") +
coord_flip() +
theme(legend.position = "None")
起初,图表显示没有差异,事实上,二元模型和排名非常相似。**这是简单计算 n-grams 或词袋的缺点之一。**没有考虑到流行词。你可以为每个文档创建一个单独的流行词列表,然后把它们过滤掉,但这要花很多时间。这里是 TF-IDF 大放异彩的地方。
术语频率和反向文档频率(TF-IDF)
术语频率和逆文档频率是我在组内计算 n-grams 或词袋的首选方法。TF-IDF 通过将一个组的单词与整个文档集进行比较,为每个组找到唯一的单词。数学也很简单。
https://skymind.ai/wiki/bagofwords-tf-idf
Tidytext 包含一个 Tf-idf 函数,因此您不需要手动创建公式。Tf-idf 的伟大之处在于,从技术上讲,您不需要删除停用词,因为停用词将在所有文档中共享。让我们看看它的实际效果。
df %>%
unnest_tokens(word, "text", token = "ngrams", n =1) %>%
count(debate, word) %>%
bind_tf_idf(word, debate, n) %>%
group_by(debate) %>%
top_n(tf_idf, n = 5) %>%
ggplot(aes(x = reorder_within(word, tf_idf, debate), y = tf_idf, fill = debate)) +
geom_col() +
scale_x_reordered() +
facet_wrap(~debate, scales = "free") +
coord_flip() +
theme(legend.position = "none")
Bind_tf_idf 跟随计数函数。 Bind_tf_idf 然后将一个术语、文档和 n
所以,图表显示了许多不同的单词,有些单词没有任何意义。Tf-idf 确实有所帮助,但是有些词根本没有增加任何价值,比如在辩论 4 和 2a 中。为什么有个“h”?可能是因为在可能有不需要的空间的地方清理了数据。但是我们仍然可以看到非常清晰的文字。**虽然 Tf-idf 确实去掉了很多停用词,但还是去掉比较好。**让我们来看看 tf-idf 为我们展示了每一位候选人。
df %>%
unnest_tokens(word, "text", token = "ngrams", n =1) %>%
count(character, word) %>%
bind_tf_idf(word, character, n) %>%
group_by(character) %>%
top_n(tf_idf, n = 5) %>%
ggplot(aes(x = reorder_within(word, tf_idf, character), y = tf_idf, fill = character)) +
geom_col() +
scale_x_reordered() +
facet_wrap(~character, scales = "free") +
coord_flip() +
theme(legend.position = "none")
这很有趣。前 5 个 tf-idf 单词确实揭示了每个候选人的很多信息。杨谈 1000 指的是他的自由红利。贝托谈到了德克萨斯和帕索,这很有道理,因为那是他的家乡。Eric Swallwell 用 Torch 来形容他是最容易辨认的,这个词指的是臭名昭著的“传递火炬”演讲。即使看着 x 轴火炬也有最高值,这表明它能很好地识别候选人。Tf-idf 也可以应用于任何 n 元文法。您可能已经注意到,第一个图表显示了每个候选人的前 5 个三元模型。
df %>%
unnest_tokens(trigram, "text", token = "ngrams", n = 3) %>%
count(character, trigram) %>%
bind_tf_idf(trigram, character,n) %>%
group_by(character) %>%
top_n(tf_idf, n = 5) %>%
mutate(rank = rank(tf_idf, ties.method = "random")) %>%
arrange(character, rank) %>%
filter(rank <=5) %>%
ggplot(aes(x = reorder_within(trigram, tf_idf, character),
y = tf_idf,
color = character,
fill = character)) +
geom_col() +
scale_x_reordered() +
facet_wrap(~character, scales = "free") +
coord_flip() +
theme(legend.position = "None")
结论
词袋和 n 元语法是文本挖掘和其他 NLP 主题的基础。这是将文本转换成数字特征的一种非常简单而优雅的方式。此外,tf-idf 是另一个可以增加单词袋和 n 元语法有效性的工具。这些基本概念可以带你深入文本挖掘的世界。考虑使用词袋和 n-grams 创建一个模型,尝试 tf-idf 如何改变模型的准确性,使用词典将情感值应用于词袋,或者使用二元模型进行否定。与数据挖掘中的其他领域相比,文本挖掘是一个相对未开发的领域。然而,随着智能手机、在线业务和社交媒体的兴起,将需要文本挖掘来处理每天发布、共享和转发的数百万条文本。
数据科学家的文本预处理
文本预处理的简便指南
Image by Devanath from Pixabay
文本预处理
文本预处理是文本分析和自然语言处理的重要任务和关键步骤。它将文本转换为可预测和可分析的形式,以便机器学习算法可以更好地执行。这是一个方便的文本预处理指南,是我之前关于文本挖掘的博客的延续。在这篇博客中,我使用了来自 Kaggle 的 twitter 数据集。
有不同的方法来预处理文本。这里有一些你应该知道的常用方法,我会试着强调每种方法的重要性。
Image by the author
密码
**#Importing necessary libraries**import numpy as np
import pandas as pd
import re
import nltk
import spacy
import string**# Reading the dataset**df = pd.read_csv("sample.csv")
df.head()
输出
下部外壳
这是最常见和最简单的文本预处理技术。适用于大多数文本挖掘和 NLP 问题。主要目标是将文本转换为小写,以便“apple”、“APPLE”和“Apple”得到相同的处理。
密码
**# Lower Casing --> creating new column called text_lower**df['text_lower'] = df['text'].str.lower()
df['text_lower'].head()
输出
0 @applesupport causing the reply to be disregar...
1 @105835 your business means a lot to us. pleas...
2 @76328 i really hope you all change but i'm su...
3 @105836 livechat is online at the moment - htt...
4 @virgintrains see attached error message. i've...
Name: text_lower, dtype: object
删除标点符号
密码
**#removing punctuation, creating a new column called 'text_punct]'**
df['text_punct'] = df['text'].str.replace('[^\w\s]','')
df['text_punct'].head()
输出
0 applesupport causing the reply to be disregard...
1 105835 your business means a lot to us please ...
2 76328 I really hope you all change but im sure...
3 105836 LiveChat is online at the moment https...
4 virginTrains see attached error message Ive tr...
Name: text_punct, dtype: object
停用词删除
停用词是一种语言中的一组常用词。英语中停用词的例子有“a”、“we”、“the”、“is”、“are”等。使用停用词背后的想法是,通过从文本中删除低信息量的词,我们可以专注于重要的词。我们可以自己创建一个自定义的停用词列表(基于用例),也可以使用预定义的库。
密码
**#Importing stopwords from nltk library**
from nltk.corpus import stopwords
STOPWORDS = set(stopwords.words('english'))**# Function to remove the stopwords**
def stopwords(text):
return " ".join([word for word in str(text).split() if word not in STOPWORDS])**# Applying the stopwords to 'text_punct' and store into 'text_stop'**
df["text_stop"] = df["text_punct"].apply(stopwords)
df["text_stop"].head()
输出
0 appleSupport causing reply disregarded tapped ...
1 105835 your business means lot us please DM na...
2 76328 I really hope change Im sure wont becaus...
3 105836 LiveChat online moment httpstcoSY94VtU8...
4 virgintrains see attached error message Ive tr...
Name: text_stop, dtype: object
常用词去除
我们还可以从文本数据中删除常见的单词。首先,让我们检查一下文本数据中最常出现的 10 个单词。
密码
**# Checking the first 10 most frequent words**
from collections import Counter
cnt = Counter()
for text in df["text_stop"].values:
for word in text.split():
cnt[word] += 1
cnt.most_common(10)
输出
[('I', 34),
('us', 25),
('DM', 19),
('help', 17),
('httpstcoGDrqU22YpT', 12),
('AppleSupport', 11),
('Thanks', 11),
('phone', 9),
('Ive', 8),
('Hi', 8)]
现在,我们可以删除给定语料库中的常用词。如果我们使用 tf-idf,这可以自动处理
密码
**# Removing the frequent words**
freq = set([w for (w, wc) in cnt.most_common(10)])**# function to remove the frequent words**
def freqwords(text):
return " ".join([word for word in str(text).split() if word not
in freq])**# Passing the function freqwords**
df["text_common"] = df["text_stop"].apply(freqwords)
df["text_common"].head()
输出
0 causing reply disregarded tapped notification ...
1 105835 Your business means lot please name zip...
2 76328 really hope change Im sure wont because ...
3 105836 LiveChat online moment httpstcoSY94VtU8...
4 virgintrains see attached error message tried ...
Name: text_common, dtype: object
去除生僻字
这是非常直观的,因为对于不同的 NLP 任务,一些本质上非常独特的词,如名称、品牌、产品名称,以及一些干扰字符,如 html 省略,也需要被删除。我们还使用单词的长度作为标准来删除非常短或非常长的单词
密码
**# Removal of 10 rare words and store into new column called** 'text_rare'
freq = pd.Series(' '.join(df['text_common']).split()).value_counts()[-10:] # 10 rare words
freq = list(freq.index)
df['text_rare'] = df['text_common'].apply(lambda x: " ".join(x for x in x.split() if x not in freq))
df['text_rare'].head()
输出
0 causing reply disregarded tapped notification ...
1 105835 Your business means lot please name zip...
2 76328 really hope change Im sure wont because ...
3 105836 liveChat online moment httpstcoSY94VtU8...
4 virgintrains see attached error message tried ...
Name: text_rare, dtype: object
拼写纠正
社交媒体数据总是杂乱的数据,而且有拼写错误。因此,拼写纠正是一个有用的预处理步骤,因为这将帮助我们避免多个单词。例如,“text”和“txt”将被视为不同的单词,即使它们在相同的意义上使用。这可以通过 textblob 库来完成
代号
**# Spell check using text blob for the first 5 records**
from textblob import TextBlob
df['text_rare'][:5].apply(lambda x: str(TextBlob(x).correct()))
输出
表情符号移除
表情符号是我们生活的一部分。社交媒体文字有很多表情符号。我们需要在文本分析中删除相同的内容
密码
代码参考: Github
**# Function to remove emoji.**
def emoji(string):
emoji_pattern = re.compile("["
u"\U0001F600-\U0001F64F" # emoticons
u"\U0001F300-\U0001F5FF" # symbols & pictographs
u"\U0001F680-\U0001F6FF" # transport & map symbols
u"\U0001F1E0-\U0001F1FF" # flags (iOS)
u"\U00002702-\U000027B0"
u"\U000024C2-\U0001F251"
"]+", flags=re.UNICODE)
return emoji_pattern.sub(r'', string)emoji("Hi, I am Emoji 😜")
**#passing the emoji function to 'text_rare'**
df['text_rare'] = df['text_rare'].apply(remove_emoji)
输出
'Hi, I am Emoji '
表情移除
在前面的步骤中,我们已经删除了表情符号。现在,我要移除表情符号。表情符号和表情符号有什么区别?:-)是一个表情符号😜→表情符号。
使用 emot 库。请参考更多关于表情
密码
from emot.emo_unicode import UNICODE_EMO, EMOTICONS**# Function for removing emoticons**
def remove_emoticons(text):
emoticon_pattern = re.compile(u'(' + u'|'.join(k for k in EMOTICONS) + u')')
return emoticon_pattern.sub(r'', text)remove_emoticons("Hello :-)")
**# applying remove_emoticons to 'text_rare'**
df['text_rare'] = df['text_rare'].apply(remove_emoticons)
输出
'Hello '
将表情符号和表情符号转换为文字
在情感分析中,表情符号和表情符号表达了一种情感。因此,删除它们可能不是一个好的解决方案。
密码
from emot.emo_unicode import UNICODE_EMO, EMOTICONS**# Converting emojis to words**
def convert_emojis(text):
for emot in UNICODE_EMO:
text = text.replace(emot, "_".join(UNICODE_EMO[emot].replace(",","").replace(":","").split()))
return text**# Converting emoticons to words **
def convert_emoticons(text):
for emot in EMOTICONS:
text = re.sub(u'('+emot+')', "_".join(EMOTICONS[emot].replace(",","").split()), text)
return text**# Example**
text = "Hello :-) :-)"
convert_emoticons(text)text1 = "Hilarious 😂"
convert_emojis(text1)**# Passing both functions to 'text_rare'**
df['text_rare'] = df['text_rare'].apply(convert_emoticons)
df['text_rare'] = df['text_rare'].apply(convert_emojis)
输出
'Hello happy smiley face happy smiley face:-)'
'Hilarious face_with_tears_of_joy'
移除 URL
删除文本中的 URL。我们可以使用漂亮的汤库
密码
**# Function for url's**
def remove_urls(text):
url_pattern = re.compile(r'https?://\S+|www\.\S+')
return url_pattern.sub(r'', text)**# Examples**
text = "This is my website, [https://www.abc.com](https://www.abc.com)"
remove_urls(text)**#Passing the function to 'text_rare'**
df['text_rare'] = df['text_rare'].apply(remove_urls)
输出
'This is my website, '
移除 HTML 标签
另一种常见的预处理技术是删除 HTML 标签。通常出现在抓取数据中的 HTML 标签。
密码
from bs4 import BeautifulSoup**#Function for removing html**
def html(text):
return BeautifulSoup(text, "lxml").text
**# Examples**
text = """<div>
<h1> This</h1>
<p> is</p>
<a href="[https://www.abc.com/](https://www.abc.com/)"> ABCD</a>
</div>
"""
print(html(text))
**# Passing the function to 'text_rare'**
df['text_rare'] = df['text_rare'].apply(html)
输出
This
is
ABCD
标记化
标记化是指将文本分成一系列单词或句子。
密码
**#Creating function for tokenization**
def tokenization(text):
text = re.split('\W+', text)
return text
**# Passing the function to 'text_rare' and store into'text_token'**
df['text_token'] = df['text_rare'].apply(lambda x: tokenization(x.lower()))
df[['text_token']].head()
输出
词干化和词汇化
词汇化是将一个词转换成它的基本形式的过程。词干化和词元化的区别在于,词元化考虑上下文并将单词转换为其有意义的基本形式,而词干化只是删除最后几个字符,通常会导致不正确的意思和拼写错误。这里,仅执行了术语化。我们需要为 NLTK 中的 lemmatizer 提供单词的 POS 标签。根据位置的不同,lemmatizer 可能会返回不同的结果。
密码
from nltk.corpus import wordnet
from nltk.stem import WordNetLemmatizerlemmatizer = WordNetLemmatizer()
wordnet_map = {"N":wordnet.NOUN, "V":wordnet.VERB, "J":wordnet.ADJ, "R":wordnet.ADV} # Pos tag, used Noun, Verb, Adjective and Adverb**# Function for lemmatization using POS tag**
def lemmatize_words(text):
pos_tagged_text = nltk.pos_tag(text.split())
return " ".join([lemmatizer.lemmatize(word, wordnet_map.get(pos[0], wordnet.NOUN)) for word, pos in pos_tagged_text])**# Passing the function to 'text_rare' and store in 'text_lemma'**
df["text_lemma"] = df["text_rare"].apply(lemmatize_words)
输出
以上方法是常见的文本预处理步骤。
感谢阅读。请继续学习,并关注更多内容!