TowardsDataScience-博客中文翻译-2019-四十三-
TowardsDataScience 博客中文翻译 2019(四十三)
R 中从头开始的逻辑回归
如果方程式没有出现,请点击“显示嵌入”来显示它们
介绍
在统计学和数据科学中,逻辑回归用于预测某一类或某一事件的概率。通常,该模型是二项式的,但也可以扩展到多项式。对于许多应用程序来说,它可能是最简单但极其有用的模型之一,因为它实现速度快,易于解释。
这篇文章将关注二项式逻辑回归(可能会跟进多项式模型)。我将讨论逻辑回归的基础知识,它与线性回归的关系,以及如何使用简单的矩阵运算在 R 中构建模型。仅使用数学和矩阵运算(而不是 R 中的内置模型)将帮助我们理解幕后的逻辑回归。
最后,我将使用构建的模型对一些生成的数据进行分类,并显示决策边界。
逻辑回归
我们可以认为逻辑回归是一个广义线性模型,具有二项分布和 logit 连接函数。这种与线性回归的相似性将有助于我们构建模型。但是两种模型的区别在于:在线性回归中,预测值的范围是( -∞,∞ ),而在逻辑回归中,是概率 p 范围[0,1]。这就是为什么我们需要使用 logit link 函数。
我们不是直接预测 p ,而是预测几率对数( logit ):
其范围从 -∞ 到 ∞ 。当p→0,logit(p)→-∞而当 p → 1 时,logit(p)→-∞。因此,logit 函数有效地将概率值从[0,1]映射到( -∞,∞ )。现在线性关系是:
其中上标表示第 i 个例子,下标表示特征或预测器 x 1 , x 2 等( x 0 为 1 作为偏差)。对于总共 m 个训练样本,预测矩阵 X 的形状将是 m×(D+1) ,其中 D 是预测变量 ( x 1, x 2,…, x D) 的维数。加 1 是为了包含偏置列 x 0 。
而 ( θ 0, θ 1,…, θ D) 是一个 (D+1)×1 列向量。向量化计算,右手边( RHS )可以写成转置(θ)⋅x或者 X⋅θ 。接下来的任务是找到 θ ,这最能代表 p 随X【m训练示例的变化。
为了找到 θ ,我们需要定义一个代价函数。成本函数是这样的,每一个不正确的预测(或离真实值更远的预测)都会增加它的值。在逻辑回归中,成本函数定义为:
其中h(x)**是 sigmoid 函数,logit 函数的反函数:
对于每个例子, y 是实际的类标签 0 或 1, h ( x ) 是得到值 1 的预测概率。如果 y = 1 (第二项用 (1- y ) 将为 0),j(I)=-y⋅log(h(x)。当h(x)→1、J(I)→0自log(1)= 0;当h(x)→0**, J ( i ) → ∞时。如果 y = 0,J(I)=-log(1-(h(x))。当h(x)→0,J(I)→0,当h(x)→1,T92【J】随着h(x)**从 y 进一步发展,成本函数迅速增加。
这是构建模型的基本过程。令人惊讶的是,当我开始编码时,它比我想象的要简单。
R 中的模型构造
现在我们已经有了数学部分,让我们建立我们的逻辑回归。首先我将定义辅助函数,如 sigmoid 函数、成本函数 J 和梯度函数 J 。注意%*%
是 R 中的点积。以下所有函数都使用矢量化计算。
接下来是逻辑回归函数,它将训练数据 X ,标签 y 作为输入。它返回一个列向量,该向量存储了 θ 中的系数。需要注意的一点是,输入的 X 通常没有偏置项,前导列向量为 1,所以我在函数中添加了这个列。
最后我可以写两个预测函数:第一个以 X 和 θ 为输入预测概率 p ,第二个以 p 为输入返回 y (1 或 0)。
分类和决策边界
生成训练数据,使得它具有两个类别(0,1),两个预测值( x 1, x 2 ),并且可以通过线性函数来分离。
有一些轻微的重叠,所以没有这样的线将两个类完全分开。然而,我们的模型仍然能够找到最佳线路。
现在我可以训练模型得到 θ 。
还创建了一个网格,它可以被视为一个测试集。经过训练的模型将应用于此网格,并预测结果 z。这可用于创建决策边界。
在下面的图中,模型预测了将两个类的大部分分开的边界。一些数据点没有像预期的那样正确预测。但是,对训练数据进行 100%预测的模型在大多数情况下可能不是一个好模型,因为它会过度拟合数据。事实上,根据我生成数据的方式,解析解应该是x/3+y= 2**。而我的决策边界非常接近这条分析线。
结论
现在你知道了,从头开始建立回归模型对我们来说并不困难。如果你阅读了这篇文章,希望现在你已经对逻辑回归有了更好的理解。最后一点,虽然逻辑回归经常被认为是一个分类器,但它也可以用于回归:找到我们上面看到的概率。
**你可以在这里找到代码:https://github . com/JunWorks/Logistic-Regression-from-scratch-in-R
使用 NumPy 从头开始进行逻辑回归
At the end, it’s all about creating something valuable with your bare hands!
欢迎来到另一个实现机器学习算法的帖子!今天,我们将从头开始实现的算法是逻辑回归。除了它心爱的姐妹算法线性回归,由于其简单性和鲁棒性,这一算法也被高度用于机器学习。尽管它被称为逻辑回归,但它实际上是一种分类算法,用于将输入数据分类到其类别(标签)中。
这个强大的机器学习模型可以用来回答一些问题,例如:
- 一封电子邮件是否是垃圾邮件
- 如果客户会流失
- 肿瘤是良性的还是恶性的
以上所有问题都是简单的是-否问题,因此它们可用于将输入数据分为两类。因此,术语 二进制分类 在数据可以被分类为两个不同类别时使用。
显然, 多类分类 处理的是有两个以上标签(类)的数据。在掌握了进行二元分类的逻辑回归的来龙去脉之后,过渡到多类分类是相当直接的,因此,我们现在将只处理具有两个类的数据。
请记住,在线性回归中,我们根据输入和模型参数预测数值。这里,在逻辑回归中,我们也可以接近模型,因为我们试图预测数值,但这次这些值对应于属于特定类别的输入数据的 概率 。
使用逻辑回归中的术语逻辑是因为我们将另一个函数应用于输入数据和模型参数的加权和,该函数称为 logit (sigmoid)函数 。
Sigmoid 函数始终输出介于 0 和 1 之间的值,将值映射到一个范围,因此可用于计算属于某个类别的输入数据的概率:
sigmoid(x)= 1/(1+e⁻ˣ)
Sigmoid (logit) function
事不宜迟,让我们开始编写这个实现的代码。必要时,我会边走边解释代码。
我们从导入必要的库开始。和往常一样, NumPy 是我们用来实现逻辑回归算法的唯一一个包。
所有其他工具只能帮助我们完成一些小任务,比如可视化手头的数据或创建数据集。因此,我们不会使用已经实现的逻辑回归包解决方案。
这里,我们为前面提到的 sigmoid (logit)函数编写代码。值得注意的是,这个函数可以单独应用于一个numpy
数组的所有元素,因为我们使用了 NumPy 包中的指数函数。
接下来,我们为逻辑回归写成本函数。请注意,逻辑回归中使用的成本函数不同于线性回归中使用的成本函数。
请记住,在线性回归中,我们计算输入数据和参数的加权和,并将该和提供给成本函数来计算成本。当我们绘制成本函数时,发现它是凸的,因此局部最小值也是全局最小值。
然而,在逻辑回归中,我们将 sigmoid 函数应用于加权和,这使得结果是非线性的。
如果我们把非线性结果输入到成本函数中,我们得到的将是一个非凸的函数,我们不能保证只找到一个局部最小值,也就是全局最小值。
因此,我们使用另一个成本函数来计算成本,该成本保证在优化期间给出一个局部最小值。
这里的梯度下降实现与我们在线性回归中使用的没有太大不同。显然,唯一需要注意的区别是应用于加权和的 sigmoid 函数。
当写出预测函数时,我们不要忘记我们在这里处理的是概率。
因此,如果结果值高于 0.50,我们将其向上舍入到 1,这意味着数据样本属于类 1。因此,如果属于类别 1 的数据样本的概率低于 0.50,这仅仅意味着它是另一个类别(类别 0)的一部分。
记住这是二元分类,所以我们只有两个类(类 1 和类 0)。
写完必要函数的代码后,让我们用来自sklearn.datasets
的make_classification
函数创建我们自己的数据集。我们用两个类创建 500 个样本点,并在seaborn
库的帮助下绘制数据集。
Initial Cost is: [[0.69312718]]
Optimal Parameters are:
[[-0.45293068]
[ 3.26552327]
[ 0.03334871]]
现在,让我们运行算法,计算模型的参数。
看到该图,我们现在可以确定我们已经实现了逻辑回归算法,没有错误,因为它随着每次迭代而减少,直到减少如此之小,以至于成本收敛到最小值,这正是我们真正想要的。
0.966
运行算法并获得最佳参数后,我们想知道我们的模型在预测数据类别方面有多成功。事实证明,我们获得的准确度分数是一个相当高的值,所以一定要鼓励自己!
现在,为了形象化,让我们沿着模型的决策边界绘制数据集。
我们只需使用最佳参数计算截距和斜率值,并绘制将数据分为两类的边界。
从图中我们可以看出,分类不是 100%正确的,因为类的分离自然不是线性的。然而,错误分类的点(假阳性和假阴性)真的很少,所以我们在逻辑回归的实现方面做得很好。
请随意继续并再次编写所有这些代码。
但是这一次,靠自己去做。
你也可以查看我的 GitHub 简介,沿着 jupyter 笔记本阅读代码,或者简单地使用代码来实现。
将来,我一定会带来更多的实现。
编码快乐!
有问题吗?评论?通过leventbas92@gmail.com或 GitHub 联系我。
Python 中从头开始的逻辑回归
我一直在发表关于从零开始实现的文章。这一次是为了逻辑回归!让我们开始吧!
Photo by Mikhail Vasilyev on Unsplash
逻辑回归
逻辑回归用于二元分类。你可以训练你的模型来预测某人是否是癌症,或者你的模型可以被训练来预测照片中的人是否是猫。
等式实现
你还记得那个等式吗:
这是用于回归的。但是这产生了大的数字,而我们希望输出是 1 或 0(癌症与否)。在这种情况下,乙状结肠功能就发挥作用了。
sigmoid function graph
当您输入 z 时,sigmoid 函数产生 0 到 1 之间的值。上面给出了 z。
sigmoid function
这是 sigmoid 函数在 Python 中的实现方式:
由于这个功能,我们的输出将在 0 和 1 之间。
损失和成本函数
假设您的训练集有许多训练示例。你想计算你的模型做得有多好。损失和成本函数开始起作用。损失函数是仅用于训练示例的损失。代价函数是整个训练集的损失。
有许多损失函数可以选择使用。我会用这个:
s(z): sigmoid of z. p: predictions
loss function
在损失函数中, p 是我们的预测值, y 是实际值。为了便于讨论,我们只有权重参数,成本函数的图形如下所示:
我们希望我们的成本尽可能低。从图中,我们想找到全局最小值。为此将使用梯度下降算法。我们将找到该图的斜率(导数),并更新我们的权重(w)和偏差(b ),以使成本最小。
updating parameters
为了更新权重和偏差,我们将使用上面的等式。(:=)是顺便更新的意思。我们知道 b 和 w,但是如何找到 db 和 dw 呢?让我们做些数学计算。
让我们找到 db 和 dw
记住我们的目标是使成本最小化。所以我们想找到使成本最小的参数。我们可以通过对损失函数关于参数求导来实现。那就更新我们的参数!我们将利用链式法则来计算损失函数对参数的导数。所以我们将首先找到损失函数对 p 的导数,然后是 z,最后是参数。
让我们记住损失函数:
在取导数损失函数之前。让我告诉你如何取导数对数。
让我们首先找到损失函数相对于 p (预测)的导数,以便能够对 dz 求导。
我们刚刚找到了关于 p 的导数,现在我们可以计算关于 z 的。
我们还没完。我们找到了损失函数对 p 和 z 的导数,现在我们可以对 w 和 b 做同样的事情来更新参数。
db
dw
我们刚找到 db 和 dw。好消息…我们现在可以更新参数了。
多合一
让我们用 Python 来实现它:
我将使用 sci-kit learn 创建一个数据集。
它看起来像我们所期待的。
预言;预测;预告
如果你想让你的模型预测。你可以这样做。从上面的代码中,假设你找到了 p,它将在 0 和 1 之间。假设输出为 0.85。是 0(不是癌症)还是 1(癌症)?由你决定。如果你说,你的门槛是 0.8。作为 0.85 > 0.8(你的门槛),你的模型说 1(癌症)。就像添加一个 if 条件一样简单。
感谢您的阅读!喜欢就鼓掌,跟着我上 github 。
Python 中的逻辑回归
逻辑回归是一种相当常见的机器学习算法,用于预测分类结果。在这篇博文中,我将带您浏览使用 Jupyter 笔记本在 python 中创建逻辑回归模型的过程。
我们将使用来自 kaggle 的泰坦尼克号数据集,它是数据点的集合,包括年龄、性别、票价等..泰坦尼克号上所有乘客中。数据集有 891 行和 12 列。目标是看看我们是否能预测任何给定的乘客是死是活。希望你能明白为什么逻辑回归是这个问题的合适模型。
让我们开始吧…
无论您正在构建什么模型,第一步都是导入所有的库并探索数据集。
现在,让我们加载数据集并查看数据框。
简短的预览让我们了解我们正在处理的数据类型和空值的种类。它有助于了解如何处理、清理和编码数据。
汇总数据
这对于一个成功的模型来说并不是必须的,但是我总是这样做,我认为这样可以让代码更干净,更易读。我喜欢在数据集上调用 describe()函数,它产生一个简洁的数据框架,其中包含每一列的标准统计数据。然后,我将每一行存储为一个单独的序列。这将有助于查找异常值或替换空值。
计算异常值
有几种方法可以计算异常值。我选择使用四分位数范围(IQR)。为了简明扼要,我假设您熟悉 IQR 的概念,所以我将只介绍如何用 Python 来编写它。如果你认为你需要刷新你的记忆,我会推荐你看看这篇博文。
让我从描述计算异常值的步骤开始。
- 我访问了“年龄”和“费用”列中的第 25 和第 75 百分位值。
- 然后,我用这些百分位值计算了四分位间距、下限和上限。
- 我还计算了第 98 和第 2 百分位值。
- 我将每一列中的值与上限和下限进行了比较。如果它们超出了界限,我就用第 98 或第 2 百分位值来替换它们。
数据可视化
在处理大型数据集时,有时很难掌握变量对结果的影响程度。可视化数据集有助于从不同的角度看待事物。
以下是“年龄”和“费用”的分布情况:
创建模型
识别特征
创建模型时,确定所有特征值非常重要。在这种情况下,我去掉了一些类似“passengerid”、“Name”和“Ticket”的列,因为我不认为个人的姓名或 ID 会影响他们的生存机会。
我删除了像“Cabin”这样的其他列,只是因为它们有太多的空值。
编码值
在我们确定了要丢弃的特征之后,我们仍然需要对分类值或字符串值进行编码。模型没有性别和机舱位置的概念;这就是为什么我们必须将字符串编码成整数,以模型可以理解的方式来表示这些数据类型。
列车测试分离
现在我们已经选择了所有的特性,让我们将数据集分成一个训练集和一个测试集,并创建模型。
分析模型
有几个指标来分析模型的准确性。从 sklearn.metrics 库中,我导入了混淆矩阵、分类报告和 auc/roc 分数。
这些工具在评估模型的有效性时非常方便。
使用 scikit-learn 调整逻辑回归模型—第 1 部分
模型调整过程中的度量比较
分类器是机器学习模型的核心组件,可以广泛应用于各种学科和问题陈述。
有了所有可用的包,在 Python 中运行逻辑回归就像运行几行代码并在测试集上获得预测的准确性一样简单。
有哪些方法可以改进这样一个基础模型,结果如何比较?
为了展示一些技术,我们将使用来自 UCI 机器学习知识库的银行营销数据集运行一些模型。该数据集代表了一家葡萄牙银行的直接营销活动,以及这些活动是否导致了银行定期存款。
基本逻辑回归模型
在为基本 EDA 导入必要的包并使用 missingno 包之后,似乎这个数据集的大部分数据都存在了。
要对此数据进行逻辑回归,我们必须将所有非数字特征转换为数字特征。有两种流行的方法:标签编码和热编码。
对于标注编码,将为要素列中的每个唯一值分配不同的编号。这种方法的一个潜在问题是假设标签大小表示平凡性(即标签 3 大于标签 1)。
对于一个热编码,为特征列中的每个唯一值创建一个新的特征列。如果该观察值存在,则该值为 1,否则为 0。然而,这种方法很容易导致特征数量的爆炸,并导致维度的诅咒。
下面,我们试图拟合一个只有虚拟变量的模型和另一个只有标签编码变量的模型。
Model accuracy is 0.8963340616654528
Model accuracy is 0.9053168244719592
虽然最终的模型精度相当,但快速查看一下 AUC ,另一个模型指标表明使用标签编码后有了显著的改善。
All dummy variables vs all label encoded.
在不同的阈值范围内,标签编码似乎表现得更好。但是,有几个功能的标签排序没有意义。例如,一周中的几天:
{'fri': 1, 'mon': 2, 'thu': 3, 'tue': 4, 'wed': 5}
此外,如果转换为虚拟变量,特别是“工作”特征将更具解释力,因为一个人的工作似乎是他们是否开设定期存款的重要决定因素,而序数标度将没有太大意义。
下面,为教育、月份和星期几确定定制订单,同时为工作创建虚拟变量。
Model accuracy is 0.9053168244719592
得到的模型具有与仅标记编码的变量相当的准确性,同时保持类似的 0.92 的高 AUC 分数。更重要的是,现在可以清楚地解释和识别标签和虚拟变量的新组合。
归一化和重采样
上面的基本模型是在原始数据上执行的,没有任何标准化。这里,我们采用 MinMaxScaler,并将值的范围限制在 0 和 1 之间。
Model accuracy is 0.906409322651129
人们也可能对大约 0.9 的直接 AUC 分数持怀疑态度。在检查响应变量的样本时,似乎存在一个类别不平衡的问题,只有大约 10%的客户订阅定期存款。
关于 10:90 比例的阶级不平衡问题的严重性存在争议,因为有许多转换实验可以达到 1:99 的比例。
尽管如此,我们在这里使用 SMOTE 探索一种重采样技术。在我们的特定场景中,我们通过合成生成附加样本来对少数类进行过采样。
Model accuracy is 0.8661082787084243
虽然重采样数据在 AUC 上略胜一筹,但准确性下降到 86.6%。事实上,这比我们的基本模型还要低。
随机森林回归模型
虽然我们在上面的测试案例中使用了基本的逻辑回归模型,但是另一种流行的分类方法是随机森林模型。
让我们用标准化数据和随机森林模型的重采样数据重复上述两个模型。
Normalized Model accuracy is 0.9059237679048313Resampled Model accuracy is 0.9047098810390871
两者的精确度分数相当,但有趣的是,与基本逻辑回归模型相比,随机森林模型在重采样数据上的模型精确度大大提高了。
虽然这两个 AUC 分数都略低于逻辑模型的分数,但似乎对重采样数据使用随机森林模型在准确性和 AUC 指标的总体上表现更好。
网格搜索
值得注意的是,上述模型是使用由 LogisticRegression 和 RandomForestClassifier 模块确定的默认参数运行的。我们可以通过调整模型的超参数来改进模型吗?
为了实现这一点,我们定义了一个参数“网格”,我们希望在模型中测试这些参数,并使用 GridSearchCV 选择最佳模型。
在上面的网格搜索中,我们利用了由两个字典组成的参数网格。
第一个字典包括我想在模型中运行的所有 LogisticRegression 的变体,包括关于正则化类型、惩罚大小和所用求解器类型的变体。
第二个字典包括 RandomForestClassifier 的所有变体,并包括模型中使用的估计器(树)数量和最大特征数量的不同范围。
Fitting 5 folds for each of 100 candidates, totalling 500 fits[Parallel(n_jobs=-1)]: Using backend LokyBackend with 4 concurrent workers.
[Parallel(n_jobs=-1)]: Done 42 tasks | elapsed: 4.7s
[Parallel(n_jobs=-1)]: Done 192 tasks | elapsed: 43.1s
[Parallel(n_jobs=-1)]: Done 442 tasks | elapsed: 6.4min
[Parallel(n_jobs=-1)]: Done 500 out of 500 | elapsed: 8.8min finished
使用定义的参数范围,评估了 100 个潜在模型。因为我选择了五重交叉验证,这导致了 500 个不同的模型被拟合。这花了大约 9 分钟。
这是“最佳”模型的参数:
RandomForestClassifier(bootstrap=True, class_weight=None, criterion='gini',
max_depth=None, max_features=6, max_leaf_nodes=None,
min_impurity_decrease=0.0, min_impurity_split=None,
min_samples_leaf=1, min_samples_split=2,
min_weight_fraction_leaf=0.0, n_estimators=100, n_jobs=None,
oob_score=False, random_state=None, verbose=0,
warm_start=False)
准确度为 0.908,AUC 评分为 0.94,这两项指标都是迄今为止我们从所有模型中所见的每项指标的最高值。
Model accuracy is 0.9083515416363195
对重新采样的数据重复相同的拟合,得到相同的准确度和分类报告,但运行时间长达 23 分钟。
基础模型与“最终”模型的比较
不同的分类标准是如何从我们的基本模型中得到改进的?
基本模型分类报告:
precision recall f1-score support
0 0.97 0.92 0.95 7691
1 0.38 0.64 0.47 547
micro avg 0.91 0.91 0.91 8238
macro avg 0.67 0.78 0.71 8238
weighted avg 0.93 0.91 0.92 8238
“最终”模型分类报告:
precision recall f1-score support
0 0.97 0.94 0.95 7537
1 0.48 0.64 0.55 701
micro avg 0.91 0.91 0.91 8238
macro avg 0.72 0.79 0.75 8238
weighted avg 0.92 0.91 0.92 8238
似乎所有模型在多数类中都表现很好,准确率、召回率都高于 0.9。
不过,新的改进模型对少数族裔来说表现更好,可以说是对客户是否打算订阅定期存款的“更重要”分类。
AUC 评分也提高到 0.94,这表明最终模型在不同阈值下的表现也更好。
虽然我们已经设法改进了基本模型,但仍有许多方法来调整模型,包括多项式特征生成、sklearn 特征选择以及为网格搜索调整更多的超参数。
这将是第 2 部分的重点!同时,谢谢阅读,代码可以在这里找到。也可以在领英上自由连接!
PyTorch 对 MNIST 的 Logistic 回归分析
逻辑回归用于描述数据,解释一个因变量与一个或多个名义变量、序数变量、区间变量或比率水平自变量之间的关系【1】。下图显示了逻辑和线性回归的区别。
Taken from https://www.sciencedirect.com/topics/nursing-and-health-professions/logistic-regression-analysis
在这篇文章中,我将展示如何用 PyTorch 编写一个逻辑回归模型。
我们将尝试解决 MNIST 数据集的分类问题。首先,让我们导入所有我们需要的库。
**import** torch
**from** torch.autograd **import** Variable
**import** torchvision.transforms **as** transforms
**import** torchvision.datasets **as** dsets
当我创建一个模型时,我喜欢把下面的步骤列表放在我面前。这份名单公布在 PyTorch 网站上[2]。
*# Step 1\. Load Dataset
# Step 2\. Make Dataset Iterable
# Step 3\. Create Model Class
# Step 4\. Instantiate Model Class
# Step 5\. Instantiate Loss Class
# Step 6\. Instantiate Optimizer Class
# Step 7\. Train Model*
所以让我们一个接一个地经历这些步骤。
加载数据集
为了加载数据集,我们使用了 torchvision.datasets,这个库几乎包含了机器学习中使用的所有流行数据集。你可以在[3]查看完整的数据集列表。
train_dataset = dsets.MNIST(root=**'./data'**, train=**True**, transform=transforms.ToTensor(), download=**False**)
test_dataset = dsets.MNIST(root=**'./data'**, train=**False**, transform=transforms.ToTensor())
使数据集可迭代
我们将使用 DataLoader 类,通过下面几行代码使我们的数据集可迭代。
train_loader = torch.utils.data.DataLoader(dataset=train_dataset, batch_size=batch_size, shuffle=**True**)
test_loader = torch.utils.data.DataLoader(dataset=test_dataset, batch_size=batch_size, shuffle=**False**)
创建模型类
现在,我们将创建一个定义逻辑回归架构的类。
**class** LogisticRegression(torch.nn.Module):
**def** __init__(self, input_dim, output_dim):
super(LogisticRegression, self).__init__()
self.linear = torch.nn.Linear(input_dim, output_dim)
**def** forward(self, x):
outputs = self.linear(x)
**return** outputs
实例化模型类
在实例化之前,我们将初始化如下一些参数。
batch_size = 100
n_iters = 3000
epochs = n_iters / (len(train_dataset) / batch_size)
input_dim = 784
output_dim = 10
lr_rate = 0.001
现在,我们初始化我们的逻辑回归模型。
model = LogisticRegression(input_dim, output_dim)
实例化损失类
我们使用交叉熵来计算损失。
criterion = torch.nn.CrossEntropyLoss() *# computes softmax and then the cross entropy*
实例化优化器类
优化器将是我们使用的学习算法。在这种情况下,我们将使用随机梯度下降。
optimizer = torch.optim.SGD(model.parameters(), lr=lr_rate)
训练模型
现在,在最后一步中,我们将使用以下代码来训练模型。
iter = 0
**for** epoch **in** range(int(epochs)):
**for** i, (images, labels) **in** enumerate(train_loader):
images = Variable(images.view(-1, 28 * 28))
labels = Variable(labels)
optimizer.zero_grad()
outputs = model(images)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
iter+=1
**if** iter%500==0:
*# calculate Accuracy* correct = 0
total = 0
**for** images, labels **in** test_loader:
images = Variable(images.view(-1, 28*28))
outputs = model(images)
_, predicted = torch.max(outputs.data, 1)
total+= labels.size(0)
*# for gpu, bring the predicted and labels back to cpu fro python operations to work* correct+= (predicted == labels).sum()
accuracy = 100 * correct/total
print(**"Iteration: {}. Loss: {}. Accuracy: {}."**.format(iter, loss.item(), accuracy))
训练,这个模型仅仅 3000 次迭代就给出了 82% 的准确率。您可以稍微调整一下参数,看看精度是否会提高。
为了更深入地理解 PyTorch 中的逻辑回归模型,一个很好的练习是将它应用于你能想到的任何分类问题。例如,你可以训练一个逻辑回归模型来对你最喜欢的漫威超级英雄的图像进行分类(应该不会很难,因为他们中的一半已经消失了:)。
参考
[1]https://www . statistics solutions . com/what-is-logistic-regression/
https://pytorch.org/docs/stable/torchvision/datasets.html
Python 中的逻辑回归
尽管逻辑回归中有 回归 这个词,但逻辑回归是一种用于二分类的监督机器学习算法。我说 二进制 是因为逻辑回归的局限性之一是它只能用 两个 不同的类对数据进行分类。在较高层次上,逻辑回归将直线拟合到数据集,然后根据新样本相对于直线的位置返回新样本属于两个类之一的概率。
赔率与概率
在深入逻辑回归的本质之前,我们理解概率和赔率之间的区别是很重要的。概率的计算方法是,用发生的事件数除以没有发生的事件数。例如,如果赢得一场比赛的赔率是 5 比 2,我们将该比率计算为 5/2=2.5。另一方面,概率的计算方法是用某件事情发生的事件数除以事件总数(包括同样的事情发生和没有发生的事件)。比如,相同赔率的游戏,赢的概率是 5/(5+2)=0.714。
赔率和概率之间的一个重要区别是,概率的范围从 0 到 1,而赔率的对数的范围从负无穷大到正无穷大,这一点在我们训练模型时会发挥作用。我们采用赔率的对数,因为否则,当我们计算某个事件发生的赔率(例如,赢得一场比赛)时,如果分母大于分子,赔率的范围将从 0 到 1。然而,当分子大于分母时,赔率将从 1 到无穷大。例如,假设我们比较了两个不同球队赢得比赛的几率。A 队由全明星组成,因此他们赢一场比赛的赔率是 5 比 1。
另一方面,B 队赢一局的赔率是 1 比 5。
在记录概率时,两个队离原点(0)的距离是相同的。
我们可以通过用一个事件发生的概率除以它不发生的概率来从概率到赔率。
我们把后者的通式写成如下:
正如我们将要看到的,在确定模型的最佳拟合时,我们需要在概率和赔率之间来回权衡。
算法
假设我们想要建立一个逻辑回归模型,在给定某些变量(如学习时间)的情况下,预测学生是否会通过或失败。确切地说,我们想要一个输出学生通过概率(0 到 1 之间的数字)的模型。值为 1 意味着学生肯定会通过,而值为 0 意味着学生会不及格。
在数学中,我们称下面的方程为 Sigmoid 函数。
其中 y 是直线的方程式。
不管 T2 y T3 的值是多少,Sigmoid 函数的范围是从 0 到 1。例如,当 y 趋向负无穷大时,概率接近零。
当 y 趋于正无穷大时,概率趋近于 1。
在逻辑回归中,我们使用 Sigmoid 函数来描述样本属于两个类别之一的概率。Sigmoid 函数的形状决定了我们的模型预测的概率。当我们训练我们的模型时,我们实际上是试图选择其形状最适合我们的数据的 Sigmoid 函数。我们选择最佳路线的实际方法涉及大量的数学运算。正如我们在线性回归中看到的,我们可以使用梯度下降或其他技术来收敛到一个解。然而,Sigmoid 函数的导数相当复杂。
如果我们可以优化一条直线的方程呢?
正如我们之前提到的,我们可以从概率(范围从 0 到 1 的函数)到对数(赔率)(范围从负到正无穷大的函数)。
比如假设一个学生通过的概率是 0.8 或者 80%。我们可以通过用它们通过的概率除以它们失败的概率,然后取结果的对数,找到新图的 y 轴上的相应位置。
然后,我们将对每个数据点重复这一过程。
一旦我们在新的 y 轴上绘制了每个数据点,就像线性回归一样,我们可以使用优化器来确定最佳拟合线的 y 截距和斜率。
在这个例子中,我们将介绍如何使用最大似然法优化函数。
首先,我们生成一条候选线,然后将原始数据点投影到这条线上。
我们查看沿线每个数据点的 y 值,并将其从赔率的对数转换为概率。
在对每个数据点重复这个过程之后,我们得到了下面的函数。
学生通过的可能性是 y 轴上该点的值。在给定 s 形形状的情况下,观察到具有当前分布的学生的可能性是单独观察每个学生通道的结果。
接下来,我们包括那些没有通过总体可能性等式的学生的可能性。因为 Sigmoid 函数表示学生通过 的 概率,所以学生失败的可能性是 1(总概率)减去沿线该点的 y 值。
您通常会看到被使用的可能性日志。对数中两个数的乘积相当于它们对数的相加。
我们以下面的可能性结束。
然后,我们对不同的行重复整个过程,并比较可能性。我们选择具有最大可能性(最大正数)的线。
密码
让我们看看如何在 Python 中实现逻辑回归。首先,导入以下库。
from sklearn.datasets import make_classification
from matplotlib import pyplot as plt
from sklearn.linear_model import LogisticRegression
import seaborn as sns
sns.set()
from sklearn.model_selection import train_test_split
from sklearn.metrics import confusion_matrix
import pandas as pd
接下来,我们将利用scikit-learn
库中的make_classification
函数来生成数据。正如我们前面提到的,逻辑回归只适用于二元分类问题。因此,数据点由两类组成。
x, y = make_classification(
n_samples=100,
n_features=1,
n_classes=2,
n_clusters_per_class=1,
flip_y=0.03,
n_informative=1,
n_redundant=0,
n_repeated=0
)
我们绘制了特征和类之间的关系。
plt.scatter(x, y, c=y, cmap='rainbow')
在训练我们的模型之前,我们将留出一部分数据来评估它的性能。
x_train, x_test, y_train, y_test = train_test_split(x, y, random_state=1)
我们实例化了一个LogisticRegression
类的实例,并调用带有特征和标签的fit
函数(因为逻辑回归是一种有监督的机器学习算法)作为参数。
lr = LogisticRegression()lr.fit(x_train, y_train)
我们可以访问以下属性来实际查看最佳拟合线的斜率和 y 截距的系数。
print(lr.coef_)
print(lr.intercept_)
让我们来看看这个模型对未经训练的数据的表现。
y_pred = lr.predict(x_test)
鉴于这是一个分类问题,我们使用混淆矩阵来衡量我们的模型的准确性。
confusion_matrix(y_test, y_pred)
从我们的混淆矩阵我们得出结论:
- 真阳性:7 ( 我们预测了阳性结果,结果是阳性)
- 真阴性:12 ( 我们预测了阴性结果,结果是阴性
- 假阳性:4 ( 我们预测结果为阳性,结果为阴性)
- 假阴性:2 ( 我们预测结果为阴性,结果为阳性
如果出于某种原因,我们想要检查一个数据点属于给定类的实际概率,我们可以使用predict_proba
函数。
lr.predict_proba(x_test)
第一列对应于样本属于第一类的概率,第二列对应于样本属于第二类的概率。
在尝试绘制 Sigmoid 函数之前,我们创建并排序一个包含测试数据的数据帧。
df = pd.DataFrame({'x': x_test[:,0], 'y': y_test})
df = df.sort_values(by='x')from scipy.special import expitsigmoid_function = expit(df['x'] * lr.coef_[0][0] + lr.intercept_[0]).ravel()plt.plot(df['x'], sigmoid_function)plt.scatter(df['x'], df['y'], c=df['y'], cmap='rainbow', edgecolors='b')
逻辑回归:好的部分
用 GD 和牛顿法进行二元和多元 Logistic 回归
在上一篇文章中,我们通过降维的视角解决了机器学习分类的问题。我们看到了 Fisher 的线性判别式是如何将数据点从更高的维度投射到更低的维度的。该预测遵循两个原则。
- 它使类间方差最大化。
- 它最小化了类内方差。
尽管 Fisher 的方法(本质上)不是判别式,但我们通过使用高斯模型对类别条件分布进行建模,建立了一个判别式。首先,我们找到了先验类概率 p(Ck)。然后,我们用贝叶斯定理求出后验类概率 p(Ck|x)。这里,x 是输入向量,Ck 是类 k 的标签。
简而言之,我们可以根据 ML 模型对数据进行分类的方式对它们进行分类。有两种类型:生成方法和判别方法。
生成方法明确地学习后验类概率。与之相反,判别算法直接学习后验类概率。
直观上,它有一个很好的几何解释。对于每一类,生成模型被关注来寻找数据的概率表示。相反,判别算法侧重于通过决策边界来分离数据。
换句话说,生成模型试图通过为每个类建立一个统计模型来解释数据。
另一方面,判别算法的目标是找到分隔类别的最佳决策边界。因此,只要存在决策面,这种模型就不关心数据的分布。
以一个二元分类问题为例。给定一个输入向量 x ,我们需要决定 Ck, x 最有可能属于哪个类。为了做出这个决定,两种类型的 ML 算法都需要一种从训练数据计算后验概率 p(Ck|x)的方法。
对于 Fisher 的,我们明确学习后验类概率使用高斯。一旦我们找到它,我们使用决策理论来确定 x 的类成员。
对于判别模型,将直接导出后验 p(Ck|x)。在这种情况下,一旦我们有了后验概率,我们就可以使用决策理论,将 x 分配给最可能的类。
逻辑回归
在我们开始之前,请确保您跟随这些 Colab 笔记本 。
逻辑回归可能是最著名的判别模型。这样,它隐式地导出后验类别概率 p(Ck| x )。
对于二元分类,后验概率由应用于输入 ϕ.的线性组合的 sigmoid 函数σ给出
Sigmoid function.
For binary classification, the posterior probabilities are represented by the logistic Sigmoid function.
同样,对于多类问题,我们可以使用 softmax 函数来估计后验概率。像 sigmoid 一样,softmax 将给定向量归一化为概率,即 0 到 1 之间的值。
让我们从二进制分类的情况开始。
二元逻辑回归
对于 M 维输入特征向量,逻辑回归必须学习 M 个参数。
Trainable parameters for binary logistic regression.
以 SVHN 数据集为例。每个 RGB 图像的形状为 32x32x3。因此,逻辑回归需要学习 32x32x3=3072 个参数。
为了找到这些参数,我们通常优化交叉熵误差函数。
交叉熵测量模型的预测与标签的距离有多远。当预测值偏离真实值时增加,否则减少。
假设目标值 t 为 0 或 1,交叉熵定义为:
这里, N 表示数据集中实例的总数, yᵢ 是模型的概率。
交叉熵比较两种概率分布。因此,重要的是要注意逻辑回归的输出被解释为概率——甚至在学习期间。
取交叉熵相对于权重向量 w 的导数,我们得到梯度。
The gradient of the cross-entropy
注意,为了计算这个导数,我们需要 sigmoid 函数 w.r.t weights w 的导数。幸运的是,sigmoid 的一个很好的特性是,我们可以用它自己来表示它的导数。
The derivative of the sigmoid function.
梯度是一个向量值函数。实际上,渐变是一种线性变换,将输入向量映射到其他相同形状的向量。
梯度捕捉整个多变量函数的导数。它的每一个值都表示我们可以改变一个特定权重的方向,这样我们就可以达到一个函数的最大值。因此,梯度代表最陡上升的方向。
Softmax 回归
对于多类分类,只有一些事情会发生变化。现在,我们可以使用 softmax 函数来模拟后验概率。
Here ak are the activations.
由于逻辑回归将其预测视为概率,我们需要改变表示标签的方式。至此,目标/标签向量通常被表示为整数向量。每个值代表一个不同的类。如果我们希望它们是同等价值的概率,它们需要在 0 和 1 之间。要做到这一点,我们可以将它们的表示方式改为 one-hot-encoding。
One-hot-encoding representation.
这一次,对于具有 M 个特征和 K 个不同类的输入,逻辑回归学习 MxK 个参数。我们可以把它看作一个矩阵。
Trainable parameters for multiclass logistic regression.
现在,我们可以进行类似的二进制分类的情况。首先,我们对激活的 softmax 求导。然后,似然的负对数给出了多类分类的交叉熵函数。
实际上,交叉熵度量两个概率向量之间的距离。一个,来自于 softmax 。第二个包含真实目标值的独热编码表示。
请注意用于二分类和多分类的误差函数之间的差异。实际上,它们真的是一回事。
二元交叉熵将目标视为标量。他们要么接受 0 要么接受 1。对于多类分类,目标被表示为一个热点编码向量。
最后,我们取误差函数 w.r.t .的梯度作为权重 w 并获得以下梯度向量。
迭代加权最小二乘法
与线性回归不同,逻辑回归没有封闭形式的解。换句话说,对于线性回归,我们可以用下面的等式求解梯度等于 0 的点:
Closed-form solution for linear regression.
对于逻辑回归,这样一个封闭形式的方程是不存在的。由于非线性,我们应用于输入的线性组合。
然而,损失函数和参数 w 之间的关系仍然给了我们一个凹误差函数。因此,我们可以放心,在误差曲面上只有一个唯一的最小值。
因此,我们可以使用迭代技术(如梯度下降法或牛顿-拉夫森法)来求解。
如果我们选择梯度下降,就万事俱备了。
- 顺着梯度的反方向走就行了。
说白了就是最陡下降的方向。因此,我们可以迭代地更新权重 w 为:
但是,我们可以做得更好一点。
梯度下降提供了到下一个临界点的最陡下降方向。而学习速度控制着我们在那个方向上所走的一步的长度(幅度)。看看下面的图片。
Image based on Deep Learning book by Ian Goodfellow and Yoshua Bengio and Aaron Courville.
特别是在(c)中,根据我们所采取的步骤的大小,我们可能会使我们的损失函数增加。为了避免这个警告,我们利用二阶导数给出的信息。
在实践中,我们不是只对交叉熵求导,而是对它的导数求导。由 f″(x)描述的二阶导数给出了函数曲率的信息。
直觉上,如果:
- f''(x)=0,则不存在曲率。
- f''(x) <0, it means that the function curves downward.
- f’’(x)> 0,函数中有向上的曲率。
利用该信息,用于最小化交叉熵的更新步骤采取以下形式:
这个更新方程被称为牛顿-拉夫逊方程。
注意,它将矩阵的逆 H⁻ 乘以梯度。 H ,或者 Hessian,存储交叉熵 w.r.t 的二阶导数权重 w 。
现在让我们深入研究代码。
以这个玩具数据集为例。
在这个 2D 坐标系中有 210 个点,分为三个等级:蓝圈、红圈和绿圈。由于类的数量大于 2,我们可以使用 Softmax 逻辑回归。
首先,为了将偏差变量引入我们的模型,我们可以执行一个简单的转换,称为:固定基函数。这可以通过简单地在输入中添加一个充满 1 的列来实现。对于二元分类,它使得相应的权值 w₀起着偏向的作用。对于多类,权重矩阵的第一列作为偏差。
然后,我们可以创建一个逻辑回归对象。
遵循 sklearn 的基于 API,我们可以拟合和评估模型
注意,我们可以在牛顿和梯度下降更新规则之间进行选择。虽然牛顿法往往收敛更快,但它需要在每次迭代中计算并存储一个完整的 Hessian。此外,Hessian 需要是可逆的——用于参数更新。
对于可逆矩阵,有一些约束条件必须为真。
首先, H 必须是一个方阵。第二, H 的列需要线性无关。意思是对于HI的任意一列 i 不能表示为其他任意一列 j 的线性组合。
也就是说, H 的列跨越了坐标系。或者说 H 的行列式是非零的
因为对于非常大的矩阵,这些约束可能不成立,所以我们可以在这里使用伪逆技术。这就是函数 pinv(H) 在上面的代码中所做的。
尽管对于较小的数据集来说,这可能不是问题,但 Hessian 往往会随着要素和类数量的增加而增加。为了有一个概念,使用具有 M 个要素的输入和具有 K 个类的数据集。全麻布有形状[M*K,M * K];在本例中,这意味着:[9x9] —记住,我们在输入中添加了一个新的特性列。
对于 CIFAR-10 数据集,每个 RGB 图像的形状为 32x32x3。这意味着存储和倒置一个形状为[30720x30720]的正方形矩阵。使用浮点 32 位精度,Hessian 需要 3.775 GB(千兆字节)。
最后,用玩具数据集和牛顿法看一下拟合的模型。十字是测试数据。
享受吧。
Decision boundaries for Logistic Regression using Newton’s method. Circles represent training data and crosses test instances.
总之,生成模型是一类明确学习类别概率的 ML 算法。
- 他们通常在训练样本较少的情况下表现良好。
- 他们可以处理丢失的数据。
- 并且可以用于监督和非监督学习。
判别模型隐含地学习类别概率。
- 一般来说,它们需要更多的标记数据。
- 他们通常有较少的假设和参数。
- 但是,只能用于监督训练。
对于二元分类,逻辑回归使用 sigmoid 函数来表示后验概率。对于多类分类,它使用 softmax。
想了解更多关于机器学习的有趣内容,请看:
为了处理两个或更多类别的分类问题,大多数机器学习(ML)算法以相同的方式工作。
medium.freecodecamp.org](https://medium.freecodecamp.org/an-illustrative-introduction-to-fishers-linear-discriminant-9484efee15ac) [## 高维超参数调谐简介
优化 ML 模型的最佳实践
medium.freecodecamp.org](https://medium.freecodecamp.org/an-introduction-to-high-dimensional-hyper-parameter-tuning-df5c0106e5a4)
参考
克里斯托弗·贝肖普。2006.模式识别和机器学习(信息科学和统计学)。施普林格出版社,柏林,海德堡。
感谢阅读。
逻辑回归和罕见事件
加权最大似然与过采样
介绍
我之前为一个博士班设计了一些问题集。其中一个作业是处理一个简单的分类问题,使用的数据是我从试图预测欺诈性信用卡交易的 kaggle challenge 中获得的。问题的目标是预测特定信用卡交易欺诈的概率。数据中一个未预料到的问题是,单笔信用卡交易欺诈的无条件概率非常小。这种类型的数据被称为罕见事件数据,在许多领域都很常见,例如疾病检测、冲突预测,当然还有欺诈检测。
本说明比较了两种提高稀有事件数据分类的常用技术。这些技术背后的基本思想是通过对罕见事件的过度拟合来增加分类算法的辨别能力。一种技术在似然函数本身中使用抽样权重,而另一种是一种病例对照设计,在这种设计中,我们从稀有类中进行过抽样。哪个更好取决于预测性能以及计算复杂度。在本例中,我们将通过比较使用 MLE 估计的逻辑回归模型的预测性能来“固定”计算复杂性。
这篇笔记的另一个动机是,在普通 ML 库的引擎盖下寻找可能是困难的。鉴于许多方法都是 C 库的包装器,追踪精确的实现可能会很乏味。这个练习的一个希望是展示使用 sklearn 库中的sample_weights
与使用我创建的分层抽样程序相比如何。
所有的代码和数据的超链接都在我的 github 上。
为了解决这个问题,让我们简单地比较一下当我们的数据服从伯努利分布时的标准似然性和样本加权似然性。伯努利分布随机变量的“标准可能性”如下:
加权最大似然
加权似然法只是试图对我们的数据进行重新加权,以说明不同类别之间的不平衡。我们引入以下术语来表示样品重量:
似然性只是将每一项与一个加权因子相乘,得到一个“加权似然性”:
分层随机抽样
我们可以使用重新采样程序来重新平衡我们的数据,而不是将权重直接纳入可能性。然后我们最大化这个样本的“标准可能性”。本说明关注的方法是分层抽样的一种形式。该过程如下:
- 选择一类具有一定样本权重的数据
- 在所选的类别中,用替换法画出相同可能性的观察值
因为我在两种方法中都使用了 MLE 进行估计,所以这些技术在计算复杂度上是相似的。然而,第二种技术与您正在评估的模型无关。同样的过程可以用于支持向量机、神经网络和更复杂的模型。此外,它是灵活的,并且可以改变取样的附加阶段或包含在样本中的判定规则。我的下一个笔记将集中在这种分层过程的扩展上,它试图基于跨类观察的“接近度”来创建匹配的样本。
另一个需要注意的是 sklearn 的一个特点,这个库在 model_selection 库中有一个StratifiedKFold
方法。但是,这种方法创建的折叠可以保持类之间的平衡。例如,如果类 0 有 10 个观测值,而类 1 有 90 个观测值,则分割将保持 0 比 1 的比例不变,即,将总是有 1 个来自类 0 的观测值到 9 个来自类 1 的观测值。
总之,本练习将使用两种不同的方法来比较预测性能,以重新衡量我们的数据。给定一些预先选择的权重,我们用ω表示:
- 加权最大似然:最大化“加权似然”函数
- 分层随机抽样:分层随机抽样,然后最大化“标准似然”函数
数据分析
我们读入数据,将因变量和自变量分开。这里自变量定义为“类”。我们可以在下图中看到,在 284,807 笔交易中,只有 492 笔交易是欺诈性的。
我是用 python 做这些的。虽然 sklearn 有一个 K-Fold 类,可以生成 K-split 的数据,但我的具体任务需要以下采样过程:
- 将数据分成 K 倍,我们用 K 来索引
- 在折叠 k 中的训练集中,运行我们的分层抽样程序
为了实现这一点,我扩展了 KFold 类,创建了oversample_KFold
类。这个新类需要一个样品重量来从每个类中取样。
我们创建一个模型管线,它包含以下步骤:
- 分离分类变量和数值变量
- 标准化(或热编码)变量
- 将列连接在一起
- 利用数据转换和逻辑回归模型创建完整的渠道
模型估计
这是这个练习的核心。我们要做的是用分层随机抽样来估计加权逻辑回归和标准逻辑回归。然后,我们将绘制三个相关的模型得分指标:准确度、召回率和精确度。我们将会看到对罕见事件预测的准确性有多差。然后我们将会看到这两种策略在召回率和准确率上的不同。
型号选择
我们有三个不同的性能指标:准确度、召回率和精确度。每个图中的蓝线是没有样品重量的标准 MLE 的指标值。x 轴是给予罕见事件的样本权重。随着样本权重的增加,稀有事件选项的权重也会增加。请注意,我在 0.05 和 0.95 之间运行模型,因此分层抽样程序在最大似然线以上开始。此外,我只运行了一次重采样方法,因此在这些估计中存在一些噪声。然而,考虑到分层抽样图中线的单调性,抽样误差一定很小。
从这些图表中有两点需要注意。首先,准确性对于这两个模型来说都是一个糟糕的衡量标准。观察分层样本,即使将几乎所有的权重赋予分层样本,该模型的准确率也在 75%左右。第二,分层抽样在回忆上表现得好得多,而对于高权重,它在精度上表现得比加权 MLE 差得多。
这与思考你在这个问题中试图确定的确切损失函数非常吻合。这种算法的利益相关者是一家信用卡公司。对于一家信用卡公司来说,遗漏一个欺诈实例比将一个非欺诈实例称为欺诈活动要糟糕得多。该公司面临欺诈指控,因此他们希望尽可能减少这些指控。考虑到这一点,他们可能希望检测所有欺诈案件,而不管非欺诈案件。对我来说,这听起来像回忆,更高的预测欺诈值,或真阳性,是首选。如果我们只关心回忆,那么我们的分层抽样模型做得更好。
然而,信用卡公司拒绝太多的费用是有代价的。如果你是一家信用卡公司的顾客,而这家公司拒绝支付你所有的费用,那么你很可能会得到另一张信用卡。在这种情况下,信用卡公司可能也关心如何减少误报。考虑到这一点,我们可以看看精度。我们所看到的是,对于低权重的重采样,其效果与加权最大似然估计一样好,但是对于较高权重的重采样,其效果要差得多。
摘要
上面的练习表明,模型选择度量对于您手头的任务非常重要。当面对罕见的事件数据时,准确性表现不佳,而召回率和精确度取决于手头的模型。该算法中需要改进的一个关键地方是跨类采样的独立性。当前算法选择一个类,然后从该类中选择一个观察值。然而,选择一个感兴趣的观察结果可能更好,比如说一个欺诈的例子,然后选择一个非常相似的非欺诈的例子来区分它们之间的差异。潜在的想法是,很容易发现明显的非欺诈行为,例如有人从当地的咖啡店购买了一杯 4 美元的咖啡,而这些都不是该算法赖以训练的重要案例。
最初发表于【http://github.com】。
伦敦设计节(第三部分):计算机视觉
第三部分:用计算机视觉分析推特上的 3K 图片
介绍
在这一系列的最后一篇博文中,我应用计算机视觉技术来理解 3300 幅关于 2018 年伦敦设计节的图像,这是一个为期七天的设计节,于 2018 年 9 月 15 日至 23 日举行。
伦敦设计节 2018 (LDF18)有一个非常活跃的活动计划,横跨伦敦 11 个不同的“设计区”、5 个“设计目的地”和 3 条“设计路线”。这是伦敦作为一个建筑环境的灵活性的另一个极好的例子,作为一个画布来展示创造性的想法。
在本系列的第二部分和第一部分中,我展示了自然语言处理和对 11000 条关于这个节日的推文的探索性数据分析。然而,这些推文中只有 3300 条有媒体数据(图像),所以这篇文章的目的是使用计算机视觉分析来理解和语境化我从 Twitter 上传的这些图像。
请向下滚动查看分析!
An image of LDF18 at the V&A Museum. Source: Flickr
数据和方法
使用 Twitter API,我收集了包含标签 #LDF18 的关于 LDF18 的推文。总共有 11,000 条推文,但只有 3,300 条推文有媒体数据(图片)。阅读第 2 部分了解更多。
然后,使用谷歌云的视觉 API 提取每张图像的标签。云视觉 API 利用“谷歌庞大的机器学习专业知识网络”(g reat 文章作者 Sara Robinson )来检测图像的特征和标签。总共有 1045 个不同的标签被赋予了 3300 张图片。
被称为特征提取和反向图像搜索的机器学习技术然后使用基因科岗的代码完成,以基于视觉相似性找到图像。首先,使用预训练的卷积神经网络来提取每幅图像的“特征”,然后,计算这些特征的余弦相似度,以“搜索”与查询图像相似的少量图像。
特征在计算机视觉中的主要作用是“将视觉信息转换到向量空间”。相似的图像应该产生相似的特征,我们可以利用这些特征进行信息检索。基于这些特征,我们还可以使用一种叫做 t-SNE 的方法通过相似性对图像进行聚类。
图像分析
在这一节中,我将展示我的计算机视觉分析的结果。下面,我报告以下三个指标:
- 图像的标签检测;
- 基于视觉相似性的图像搜索:
- 基于视觉相似性的图像聚类。
标签检测
每张照片的标签都是使用谷歌云视觉 API 生成的。这背后的想法是将图片分类,这样我就可以识别相似的图片。下面的条形图显示了 3,300 张图片的前 10 个标签。
我们看到“产品”、“字体”、“家具”、“桌子”、“设计”出现的次数最多。这些标签是有意义的,因为这是一个设计节!这是一个好消息,它证明了 Cloud Vision API 在标记关于设计节的图像方面做得很好。
然而,这些标签并没有明确描述艺术品本身——我对更详细的上下文理解感兴趣——这凸显了一些标签检测技术的缺点。
图像搜索—视觉相似性
我们可以通过编程让计算机学习图像之间的视觉相似性,而不是使用标签来理解图像。一种叫做特征提取和反向图像搜索的技术就是这样做的。
使用在 TensorFlow 后端上运行的 Keras VGG16 神经网络模型,我首先为数据集中的每张图像提取了一个特征。一个特征是每个图像的 4096 元素的数字数组。我们的期望是“该特征形成图像的非常好的表示,使得相似的图像将具有相似的特征”(吉恩·科岗,2018 )。
然后使用主成分分析(PCA)降低特征的维度,以创建一个嵌入,然后计算一个图像的 PCA 嵌入到另一个图像的距离余弦距离。我终于能够向计算机发送随机查询图像,它选择并返回数据集中具有相似特征向量的五个其他图像。
下面是三个例子:
A reverse image search for Dazzle by Pentagram and 14–18 NOW at LDF18
A reverse image search for The Onion Farm by Henrik Vibskov and Full Spectrum by Flynn Talbot at LDF18
当试图从一个包含许多图片的相册中找到相似的图片时,这种技术非常有用,事实上我就是这么做的!
图像聚类—相似性
既然我们在向量空间中嵌入了每个图像,我们可以使用一种流行的叫做 t-SNE 的机器学习可视化算法来聚类,然后在二维空间中可视化向量空间。
“tSNE 的目标是聚集相似数据点的小“邻域”,同时减少数据的整体维度,以便更容易可视化”(谷歌人工智能博客,2018 年)
下面我们看到基于视觉相似性的聚类形成。
在下面的图片中,我突出了三件艺术品——沃·西斯尔顿建筑师的乘、Es Devlin 的请喂狮子和五角星的炫——以及它们的集群轮廓。
The clustering of images of three art installations at LDF18. Source: Twitter
结论
所以你有它!我只是刚刚涉足计算机视觉的奇妙世界。还有很多东西需要我去学习,但这对我来说是很好的第一步。
我的发现表明,使用机器学习和计算机视觉技术来理解和联系关于 LDF18 的图像是可能的。
对我来说,下一步显然是计算在数据集中出现了多少艺术装置,以衡量“受欢迎程度”。我将继续研究这个数据集。
结束了
这是我关于 LDF18 的博客系列的结尾!这个系列是我正在进行的关于使用数据科学来理解和衡量城市文化影响的长期讨论的一部分。
今年,我将开始新的项目,主要是 JavaScript。敬请期待!
感谢阅读!
Vishal
Vishal 是伦敦 UCLThe Bartlett的文化数据科学家和研究生。他对城市文化的经济和社会影响感兴趣。
方股票之间的长期关系
Impulse Response Functions generated by me using the statsmodels library in python
解释 VECMs
在之前的文章中,我使用向量误差修正模型(VECM)创建了一个模型来预测 FANG 股票的收盘股价,该模型对协整时间序列进行建模。我谈到了一些我想扩展的话题,即解释负荷系数和长期关系系数、弱外生性和脉冲响应函数。
回想一下我估计的 VECM 的一般公式。神奇的是阿尔法的列向量和贝塔的行向量。它们构成了模型的误差校正部分,并使其成为 VECM 而不是向量自回归模型。
Formulation of the VECM with L lags
我用 python 重新做了分析,我的新数据只追溯到 5 年前,所以这些结果与我使用脸书上市时的数据集略有不同。
alphas 的系数或加载系数以及它们的 z 分数和相关的统计数据如下。
Our Alphas
负荷系数(alphas)是对长期关系的调整速度。它们是长期均衡中不平衡在一个时期内消失的百分比。FB 和 NFLX 收盘价的 alphas 在统计上不显著。AMZN 的α的显著性是不明确的,因为它在 0.10 显著性水平上是显著的,但在 0.05 显著性水平上不是显著的。GOOGL 的 alpha 在 0.05 显著性水平上具有统计显著性,估计为 0.0529。
这一信息意味着 FB 和 NFLX(可能还有 AMZN)对 GOOGL(可能还有 AMZN)是弱外源性的。弱外生性是指偏离长期不会直接影响弱外生变量的概念。这种效应来自于非弱外生变量的后续滞后。GOOGL(可能还有 AMZN)的滞后是弱外生变量回归长期均衡的驱动因素。
Our Betas
贝塔系数是实际的长期关系系数。FB 的β被标准化为 1,以便于解释其他β系数。GOOGL 的 beta 为-0.4204,这意味着 GOOGL 增加 1 美元,从长期来看会导致 FB 的收盘价减少 0.4204 美元,其中 5.29%的修正发生在一天之内(根据我们的关联 alpha)。重新安排哪一个贝塔是标准化的,就是你如何重新表述方程,来解释具有标准化贝塔的股票和其他股票之间的长期关系。
最后,我们可以继续讨论脉冲响应函数(IRF)。
Impulse Response Functions generated by me using the statsmodels library in python
脉冲响应函数(IRF)显示了当你在前期将一个变量增加 1 来冲击另一个变量(或同一个变量)时,该变量会发生什么。蓝色曲线显示了单位冲击的影响,因为冲击变得越来越近。虚线代表 IRF 的 95%置信区间。
GOOGL 的收盘价受到 1 美元的冲击会导致 FB 的收盘价下跌约 0.02 美元,但随着时间的推移,这种冲击的影响会变为零。NFLX 受到 1 美元冲击的影响最初会使 GOOGL 的收盘价上涨约 0.05 美元,但随后接近于零。然而,对 FB 的单位冲击持续存在,如 AMZN 上的 NFLX。如果所有的 IRF 都像这样,系统将是动态不稳定的,但幸运的是,0 在我们的许多 IRF 的 95%置信水平内,我们的系统是动态稳定的。
所以现在,你应该对建模协整时间序列有了一个不错的介绍。我的下一篇文章将关注其他问题和其他可以帮助解决这些问题的统计方法。
我这篇文章的代码可以在这里找到:https://github.com/jkclem/FANG-stock-prediction
长短期记忆和门控循环单位的解释——Eli 5 方式
ELI5 项目机器学习
Photo by Deva Williamson on Unsplash
大家好,欢迎来到我的博客“长短期记忆和门控循环单元的解释——Eli 5 Way”这是我 2019 年的最后一篇博客。我叫尼兰詹·库马尔,是好事达印度公司的高级数据科学顾问。
递归神经网络(RNN) 是一种神经网络,前一步的输出作为当前步骤的输入。
RNN 主要用于,
- 序列分类 —情感分类&视频分类
- 序列标注 —词性标注&命名实体识别
- 序列生成 —机器翻译&音译
引用说明:本文的内容和结构是基于我对四分之一实验室深度学习讲座的理解——pad hai。
在每个时间步的递归神经网络中,旧信息被当前输入改变。对于较长的句子,我们可以想象在“t”时间步之后,存储在时间步“t-k”的信息(k << t) would have undergone a gradual process of transformation. During back-propagation, the information has to flow through the long chain of timesteps to update the parameters of the network to minimize the loss of the network.
Consider a scenario, where we need to compute the loss of the network at time step four L₄ )。假设损失是由于时间步 S₁ 的隐藏表示的错误计算造成的。 S₁ 处的错误是由于矢量 W 的参数不正确。该信息必须反向传播至 W ,以便矢量修正其参数。
为了将信息传播回向量 W,我们需要使用链式法则的概念。简而言之,链式法则归结为在特定时间步长上隐藏表示的所有偏导数的乘积。
如果我们有超过 100 个更长序列的隐藏表示,那么我们必须计算这些表示的乘积用于反向传播。假设偏导数之一变成一个大值,那么整个梯度值将爆炸,导致爆炸梯度的问题。
如果偏导数之一是一个小值,那么整个梯度变得太小或消失,使得网络难以训练。消失渐变的问题
白板模拟
假设您有一个固定大小的白板,随着时间的推移,白板变得非常凌乱,您无法从中提取任何信息。在较长序列的 RNN 环境中,所计算的隐藏状态表示将变得混乱,并且难以从中提取相关信息。
因为 RNN 具有有限的状态大小,而不是从所有时间步长提取信息并计算隐藏状态表示。在从不同的时间步长提取信息时,我们需要遵循有选择地读、写和忘记的策略。
白板类比— RNN 示例
让我们以使用 RNN 的情感分析为例,来看看选择性读、写、忘策略是如何工作的。
回顾 : 电影的前半部分很枯燥,但后半部分真的加快了节奏。男主角的表演令人惊叹。
这部电影的评论从负面情绪开始,但从那时起,它变成了积极的回应。在选择性读取、写入和忘记的情况下:
- 我们希望忘记由停用词(a、the、is 等)添加的信息。
- 有选择地阅读带有感情色彩的词语所添加的信息(惊人的、令人敬畏的等等)。
- 选择性地将隐藏状态表示信息从当前单词写入新的隐藏状态。
使用选择性读取、写入和遗忘策略,我们可以控制信息流,从而使网络不会遭受短期记忆的问题,并且还可以确保有限大小的状态向量得到有效使用。
长短期记忆——LSTM
LSTM 的引入是为了克服香草 RNN 的问题,如短期记忆和消失梯度。在 LSTM 的理论中,我们可以通过使用门来调节信息流,从而有选择地读、写和忘记信息。
在接下来的几节中,我们将讨论如何实现选择性读、写和忘记策略。我们还将讨论我们如何知道哪些信息应该阅读,哪些信息应该忘记。
选择性写入
在普通 RNN 版本中,隐藏表示( sₜ) 被计算为先前时间步长隐藏表示( sₜ₋₁ )和当前输入( xₜ )以及偏差( b )的输出的函数。
这里,我们取 sₜ₋₁的所有值并计算当前时间的隐藏状态表示
In Plain RNN Version
在选择性写入中,不是将所有信息写入 sₜ₋₁ 来计算隐藏表示( sₜ )。我们可以只传递一些关于 sₜ₋₁的信息给下一个状态来计算 sₜ.一种方法是分配一个介于 0-1 之间的值,该值决定将当前状态信息的多少部分传递给下一个隐藏状态。
Selective Write in RNN aka LSTM
我们进行选择性写入的方式是,我们将 sₜ₋₁的每个元素乘以 0-1 之间的值来计算新的向量 hₜ₋₁。我们将使用这个新的向量来计算隐藏表示 sₜ.
我们如何计算 oₜ₋₁?
我们将从数据中学习 oₜ₋₁ ,就像我们使用基于梯度下降优化的参数学习来学习其他参数一样,如 U 和 W 。 oₜ₋₁ 的数学方程式如下:
一旦我们从 oₜ₋₁那里得到数据,它就乘以 sₜ₋₁ 得到一个新的矢量 hₜ₋₁.由于 oₜ₋₁ 正在控制什么信息将进入下一个隐藏状态,所以它被称为输出门。
选择性阅读
在计算了新的向量 hₜ₋₁ 之后,我们将计算一个中间隐藏状态向量šₜ(用绿色标记)。在这一节中,我们将讨论如何实现选择性读取来获得我们的最终隐藏状态 sₜ.
ₜ的数学方程式如下:
- šₜ捕捉来自前一状态 hₜ₋₁ 和当前输入 xₜ 的所有信息。
- 然而,我们可能不想使用所有的新信息,而只是在构建新的单元结构之前有选择地从中读取。也就是说…我们只想从šₜ读取一些信息来计算 sₜ 。
Selective Read
就像我们的输出门一样,这里我们用一个新的向量 iₜ 乘以šₜ的每个元素,该向量包含 0-1 之间的值。由于矢量 iₜ 控制着从当前输入流入的信息,它被称为输入门。
iₜ 的数学方程式如下:
在输入门中,我们将前一时间步隐藏状态信息 hₜ₋₁ 和当前输入 xₜ 连同偏置一起传递到一个 sigmoid 函数中。计算的输出将在 0-1 之间,它将决定什么信息从当前输入和先前的时间步长隐藏状态流入。0 表示不重要,1 表示重要。
回顾一下我们到目前为止所学的,我们有先前的隐藏状态 sₜ₋₁ ,我们的目标是使用选择性读取、写入和忘记策略来计算当前状态 sₜ 。
选择性遗忘
在本节中,我们将讨论如何通过组合 sₜ₋₁ 和**šₜ.来计算当前状态向量 sₜ**
遗忘门 fₜ 决定从 sₜ₋₁ 隐藏向量中保留或丢弃的信息部分。
Selective Forget
遗忘门 fₜ 的数学方程式如下:
在“忘记门”中,我们将前一时间步隐藏状态信息 hₜ₋₁ 和当前输入 xₜ 连同一个偏置一起传递到一个 sigmoid 函数中。计算的输出将在 0-1 之间,它将决定保留或丢弃什么信息。如果该值更接近 0,则表示丢弃,如果更接近 1,则表示保留。
通过结合遗忘门和输入门,我们可以计算当前的隐藏状态信息。
最后一幅插图如下所示:
完整的方程组如下所示:
注:LSTM 架构的某些版本没有遗忘门,而是只有一个输出门和输入门来控制信息流。它将只实现选择性读取和选择性写入策略。
我们上面讨论的 LSTM 的变体是 LSTM 最流行的变体,三个门都控制信息。
门控循环单元— GRU 氏病
在本节中,我们将简要讨论 GRU 背后的直觉。门控循环单位是 LSTM 的另一个流行变体。GRU 使用较少的门。
在 LSTM 这样的门控循环单元中,我们有一个输出门 oₜ₋₁ 来控制什么信息进入下一个隐藏状态。类似地,我们也有一个输入门 iₜ 控制什么信息从当前输入流入。
LSTM 和 GRU 之间的主要区别在于它们组合中间隐藏状态向量šₜ和先前隐藏状态表示向量 sₜ₋₁.的方式在 LSTM 中,我们忘记了确定要从 sₜ₋₁.那里保留多少部分信息
在 GRU 而不是遗忘门中,我们基于输入门向量的补充(1- iₜ )来决定保留或丢弃多少过去的信息。
忘记门= 1 —输入门向量(1- iₜ )
GRU 的全套方程式如下所示:
从等式中,我们可以注意到只有两个门(输入和输出),并且我们没有显式地计算隐藏状态向量 hₜ₋₁.所以我们没有在 GRU 中保持额外的状态向量,也就是说……比 LSTM 计算量更少,训练速度更快。
从这里去哪里?
如果想用 Keras & Tensorflow 2.0 (Python 或 R)学习更多关于神经网络的知识。查看来自 Starttechacademy的 Abhishek 和 Pukhraj 的人工神经网络。他们以一种简单化的方式解释了深度学习的基础。
摘要
本文讨论了递归神经网络在处理较长句子时的不足。RNN 受到短期记忆问题的困扰,也就是说,在信息变形之前,它只能存储有限数量的状态。之后,我们详细讨论了选择性读取、写入和遗忘策略在 LSTM 是如何通过使用门机制来控制信息流的。然后我们研究了 LSTM 的变体,称为门控循环单元,它比 LSTM 模型具有更少的门和更少的计算。
在我的下一篇文章中,我们将深入讨论编码器-解码器模型。所以确保你在媒体上跟随着我,以便在它下跌时得到通知。
直到那时,和平:)
NK。
推荐阅读
使用 Pytorch 开始练习 LSTM 和 GRU
[## 使用 LSTM 和 Pytorch 对人名国籍进行分类
个人名字在不同的国家,甚至在同一个国家,都有不同的变化。通常情况下…
www.marktechpost.com](https://www.marktechpost.com/2019/12/18/classifying-the-name-nationality-of-a-person-using-lstm-and-pytorch/)
了解递归神经网络
使用 RNN 的序列标记和序列分类
towardsdatascience.com](/recurrent-neural-networks-rnn-explained-the-eli5-way-3956887e8b75)
作者简介
Niranjan Kumar 是好事达印度公司的高级数据科学顾问。他对深度学习和人工智能充满热情。除了在媒体上写作,他还作为自由数据科学作家为 Marktechpost.com 写作。点击查看他的文章。
你可以在 LinkedIn 上与他联系,或者在 Twitter 上关注他,了解关于深度学习和机器学习的最新文章。
联系我:
- 领英—https://www.linkedin.com/in/niranjankumar-c/
- GitHub—https://github.com/Niranjankumar-c
- 推特—https://twitter.com/Nkumar_n
- 中—https://medium.com/@niranjankumarc
参考文献:
免责声明——这篇文章中可能有一些相关资源的附属链接。你可以以尽可能低的价格购买捆绑包。如果你购买这门课程,我会收到一小笔佣金。
长而宽的数据以及如何有效地绘制它们
与实例的比较
介绍
很多时候,当我们处理数据时,它有不同的格式。如果你从一个网站上删除了这些数据,很可能是以宽格式。事实上,我们实际看到的大多数数据都是这种格式,因为宽数据非常直观,也更容易理解。一个很好的例子就是这个来自 ESPN 的 NBA 统计页面。
另一方面,长格式的数据不太经常看到。然而,它有自己的优势,如:
- 快速处理(使用矢量化运算)
- 某些高级统计分析和绘图所要求的
在这本笔记本中,我将展示如何在两种格式之间转换数据,长格式如何更快地处理,以及如何有效地绘制每种格式。我们将使用旧金山和萨克拉门托的月降水量数据作为例子。
注:天气数据取自 本网站 。
准备数据集
以下是我们对数据的观察:
- 对于每个城市,数据都是宽格式的。
- 前十一个月的数据以浮点形式存储,但是十二月份和年度总计则不是
- 是因为我们还在今年 12 月…数据还没有
- 我们需要将它们转换为浮点型,并找到一种方法来填充 2019 年的数据
- 降水量的单位是英寸(来自网站)
我们使用前 19 年的平均值填充了 12 月的降水数据,然后计算 2019 年的年总和。
现在我们可以开始处理和绘制数据。
数据处理和转换
接下来,我们将对数据进行一些操作,以显示长数据和宽数据之间的差异。
首先,让我们将它们转换成长数据,并将两个数据帧连接(或合并)成一个。
现在假设我们要计算每年的月降雨量百分比。
我们从广泛的数据开始。由于我们需要对每一列进行操作,我们可以使用apply
函数。
正如我们在上面看到的,对于长数据来说要容易得多。事实上,它也更快,因为它使用向量化操作。
使用宽而长的数据绘图
我们想看看近二十年来每个月降水量的变化和分布。一个好的方法是使用方框图。对于每个日历月,我们将绘制成一个方框来显示不同年份的变化。总的来说,在一个单独的地块上将有 12 个盒子。
让我们先用宽数据把它画在旧金山。
使用熊猫中的内置函数制作剧情相当容易。如果我们想并排绘制萨克拉门托的数据呢?对于宽数据来说,这是一项相当复杂的任务。
正如您在下面看到的,我们必须分别绘制两个数据帧,指定每个数据帧的宽度和位置(否则它们会重叠),并将 xticks 放在两个框的中心。有一些调整,使它看起来正确。
现在让我们试着用长格式来达到同样的效果。在这种情况下,我使用了 Seaborn 包。
使用长数据和 Seaborn 进行并排比较要容易得多。在R
中,ggplot
也使用长格式,下划线语法与 Seaborn 非常相似。
思想
来自R
,在我的大学里广泛使用过MATLAB
,相比 Python 的matplotlib
(类似于 MATLAB),我更喜欢ggplot
。一个原因是我可以很容易地利用不同的变量来定制情节。在上面的例子中,我使用了hue
(颜色)来显示一个分类变量。我也可以在可视化中包含连续变量,例如:符号的大小等。我真的很高兴找到 Python 中的 Seaborn 包。
你可以在这里找到代码https://github.com/JunWorks/Long_and_wide
小心,齐洛,贾斯蒂马特来了!
使用机器学习预测旧金山房价
作为一个在房地产和数据科学方面都有专业知识的人,我一直对 Zillow 的 Zestimate 很着迷。本着竞争的精神,我开发了 Jim 的估计或 Jestimate!
【2018 年旧金山独栋住宅预估
以下互动地图包含了 2018 年旧金山按街区划分的房屋销售情况。单击邻居,然后单击数据表中的房屋,查看 Jestimate 结果和实际销售价格。
Zestimate 使用专有的机器学习公式来估计房屋的当前市场价值。在房地产领域,代理人不断与房主争夺他们房子的市场价值,比如“你说我的房子值 100 万美元,但 Zillow 说我的房子值 120 万美元。”在出售房产时,你认为房主更喜欢哪个数字?
代理人对物业的市场分析几乎总是确定物业当前市场价值的最佳方法,因为代理人会实际查看物业,查看可比物业并分析当地市场条件。诸如地基裂缝、25 年的旧屋顶、非法扩建或其他未记录的房产缺陷等信息无法通过机器学习公式进行分析。与机器学习公式相比,代理可以访问更多更好的数据。
然而,代理商需要时间和精力来进行准确的市场分析,这对于估计大量的房屋价值是不实际的。这就是像 Zestimate 这样的预测引擎提供价值的地方。
考虑到这一点,我想看看我能为旧金山独栋房屋销售建立一个多好的预测引擎。一个人,一台 Mac 和 Colab 能打败 Zillow 吗?跟着一起去发现吧!
关于代码的一句话
该项目的所有代码、数据和相关文件都可以在 my GitHub 访问。该项目分为两个 Colab 笔记本。一个运行线性回归模型,另一个使用 Heroku 上的散景服务器生成交互式地图。
项目目标和数据
该项目的目标是预测 2018 年旧金山独户住宅的价格,比基线更好,达到或超过 Zillow 指标。
由于我有房地产许可证,我可以访问旧金山的 MLS,我用来下载 10 年(2009 年至 2018 年)的单户住宅销售。原始数据包括 10 年间的 23,711 次销售。使用地理编码(geocoding.geo.census.gov表示纬度/经度,viewer.nationalmap.gov表示海拔)将经度、纬度和海拔添加到原始数据中。)
从原始数据中移除了代表 1.6%数据的以下异常值:
- 有 7 个以上浴室的住宅
- 有 8 间以上卧室的住宅
- 地段超过 10,000 平方英尺的住宅
- 有 14 个以上房间的家庭
- 售价超过 1000 万美元的住宅
一个重要的数据,房屋面积,大约 16%的数据为零。我尝试使用所有单户住宅的平均卧室面积作为填充值,并删除零值住宅。虽然模型在填充值下表现良好,但我选择移除零值住宅,以便最大化模型的性能。最终的统计数据留下了大约 82%的数据,即 19,497 套房屋销售。
原始数据包括 40 个特征,20 个数字特征和 20 个分类特征。快速浏览一下相关矩阵,可以为数字特征之间的关系提供一些线索。
Pearson Correlation Matrix — Initial Data
与销售价格高度相关的特征包括纬度、浴室、卧室、住宅面积、地段面积和停车场。这是有道理的,因为旧金山的北部拥有最昂贵的房屋(纬度),拥有更多平方英尺/床/浴室的房屋将卖得更高的价格,而在旧金山停车是非常昂贵的。
指标
由于线性回归最终成为选择的模型(稍后将详细介绍模型选择),关键指标是平均绝对误差(MAE)和 R 平方。
作为基线,使用 2018 年销售平均售价的 MAE 为 684,458 美元。换句话说,如果我使用 2018 年旧金山单户住宅的平均价格作为每个家庭的预测,平均误差将是 684,458 美元。模型最好能打败这个!
我还想将该模型与 Zillow 的结果进行比较。他们实际上公布了旧金山市区的精度结果( Zestimate metrics )。虽然结果不能与我的数据直接比较(大城市区域要大得多),但它们确实为模型提供了一个粗略的拉伸目标。
- 中值误差— 3.6%
- Zestimate 在销售价格的 5%以内— 62.7%
- Zestimate 在销售价格的 10%以内— 86.1%
- Zestimate 在销售价格的 20%以内— 97.6%
评估协议
评估协议将使用 2009 年至 2016 年的数据将数据集分为训练集,使用 2017 年数据的验证集和使用 2018 年数据的最终测试集。
- train——2009 年至 2016 年销售了 15,686 套房屋。
- 验证-2017 年销售 1932 套房屋。
- 测试—2018 年房屋销售 1897 套。
型号选择
线性回归模型被充分证明是房屋价格预测的强模型,这是最初选择的模型。以最少的数据清理/争论进行简单的线性回归,并记录结果。逻辑回归和随机森林模型也被尝试用于比较,线性回归模型显然是领先的。随着项目的进展,我会定期对照随机森林模型检查它,线性回归模型继续优于随机森林模型。所以是线性回归!
开发模型
初始模型使用所有功能运行,结果如下。为了查看模型的性能,我添加了每平方英尺价格特性,这实际上是房产的代理销售价格。正如预期的那样,每平方英尺的价格结果很好,但显然无法使用,因为在预测 2018 年的价格时不会知道该值。这是一个明显的数据泄露的例子。
Base Model and Overfit
这些初始预测的指标提供了一个基本的最小值和最大值。换句话说,我有一个已经超过基线的最小值和一个使用数据争论来避免数据泄漏的最大值。
数据角力
优化模型的关键在于数据扯皮!
消除特征
事实证明,超过 20 个特征对预测影响很小或没有影响,可以被删除,从而大大简化了模型。例如,城市和州对于所有属性都是相同的。
日期和时间序列
数据中有两个日期特性:销售日期和上市日期。上市日期是物业在 MLS 上上市的日期,对预测影响很小,因此被删除。
销售日期需要年份,因为数据是按销售年份划分的。这也提出了使用时间序列来预测价格的问题。与每日价格的股票不同,房地产销售可能每 5-10 年发生一次。为了使用时间序列,该模型将需要使用一个考虑到升值/贬值和任何季节性的价格指数。这种方法被简单地尝试过,但是结果比我最终的模型弱。年价格乘数如下所示。如果你在 2009-2011 年在旧金山买了一套房子,到 2018 年,它的价值平均翻了一番!
Annual Price Multiplier
最终只有售出年份被用于最终模型。
零和 Nans
使用各种方法填充纬度、经度、海拔、房间、浴室、地块平方英尺和地块英亩中的零和 Nans(见代码)。
特色工程
消除特征和填充零和 nan 为模型提供了增量改进,但是需要特征工程来获得更大的改进。
分类数据使用普通编码进行编码,但一些特征通过计算特征中分类值的数量来改进模型。例如,视图特性包含了从 25 种视图类型中挑选的属性的所有潜在视图的列表。据推断,景观越多的房产价值越高。因此,视图计数功能被设计为对视图功能中记录的视图数量进行计数。同样的方法也用于停车和车道/人行道功能。
然而,关键的设计特征被证明是可比较的销售特征。该特征是通过模拟代理对财产估价的方式而创建的估计值。下面的代码获取最近的三个类似规模的房产的最近销售额(可比销售额),并计算它们每平方英尺的平均价格,该价格稍后将在模型中用于计算可比销售价格。为避免任何数据泄露,未使用 2018 年可比销售额(最大可比销售年度为 2017 年)。
nhoods = X[['sf', 'longitude', 'latitude']]
def neighbor_mean(sqft, source_latitude, source_longitude):
source_latlong = source_latitude, source_longitude
source_table = train[(train['sf'] >= (sqft * .85)) & (train['sf'] <= (sqft * 1.15))]
target_table = pd.DataFrame(source_table, columns = ['sf', 'latitude', 'longitude', 'year_sold', 'sale_price'])
def get_distance(row):
target_latlong = row['latitude'], row['longitude']
return get_geodesic_distance(target_latlong, source_latlong).meters
target_table['distance'] = target_table.apply(get_distance, axis=1)
# Get the nearest 3 locations
nearest_target_table = target_table.sort_values(['year_sold', 'distance'], ascending=[False, True])[1:4]
new_mean = nearest_target_table['sale_price'].mean() / nearest_target_table['sf'].mean()
if math.isnan(new_mean):
new_mean = test['sale_price'].mean() / test['sf'].mean()
return new_mean
nhoods['mean_hood_ppsf'] = X.apply(lambda x: neighbor_mean(x['sf'], x['latitude'], x['longitude']), axis=1)
nhoods = nhoods.reset_index()
nhoods = nhoods.rename(columns={'index': 'old_index'})
一个新的关联矩阵显示了新的争论和工程特性之间的关系。
Pearson Correlation Matrix — Wrangled Data
最终结果
最后,根据 2018 年的测试数据运行该模型。该模型的测试 MAE 为 276,308 美元,R 平方值为 0.7981,轻松超过基线。
Final Results
与 Zestimate 的性能相比,Jestimate 模型的中值误差较低,但无法击败 Zestimate 的强误差分布。同样,Zestimate 数据覆盖的区域比 Jestimate 大。
Jestimate vs. Zestimate
Jestimate 百分比预测误差的直方图显示了分布情况:
Prediction Errors for Jestimate
使用 Shapley 值的特征重要性
为了提供对预测的进一步了解,计算了每个属性的 Shapley 值,显示了对预测价格具有最高正面影响(赞成)和最高负面影响(反对)的特性及其值。
Shapley Values Graph
Shapley Values Grid
显示
最终显示数据帧被创建并保存在. csv 文件中,以供显示代码使用。另一篇文章“数据可视化—高级散景技术”详细介绍了如何使用散景图、数据表和文本字段创建数据的交互式显示。
display_data Dataframe
我欢迎建设性的批评和反馈,请随时给我发私信。
有关该项目的数据可视化部分的详细信息,请参见配套文章“数据可视化—高级散景技术”。
这篇文章最初出现在我的 GitHub 页面网站上。
在推特上关注我 @The_Jim_King
这是探索旧金山房地产数据系列文章的一部分
旧金山房地产数据来源:旧金山 MLS,2009–2018 年数据
着眼于人工智能的案例研究
除了讨论它们将如何在美国和欧盟发展之外
这篇文章是为 Darakhshan Mir 博士在巴克内尔大学的计算机和社会课程写的。我们讨论技术中的问题,并用伦理框架来分析它们。 Taehwan Kim 和我一起合作这个项目。
Photo by Franck V. on Unsplash
在我的上一篇帖子中,我讨论了人工智能(AI)对就业市场的影响,并强调了在监管人工智能方面的远见的必要性。我认为,我们的社会无法应对日益依赖人工智能所带来的道德后果。许多国家的技术领导层都认识到了这个问题,在过去的几年里,他们都提出了以有效的方式促进人工智能发展的战略。国家人工智能战略概述简要讨论了自 2017 年初以来提出的不同人工智能政策。
Figure 1: No two policies are the same. They focus on different aspects of AI: the role of the public sector, investment in research, and ethics. | Tim Dutton
在这篇文章中,我主要关注美国和欧盟提出的政策之间的差异。此后,我讨论了三种(半)假设情景,以及它们如何在人工智能发展有巨大反差的两个地区上演。为了进行分析,我广泛使用了数据伦理介绍中描述的伦理框架。
美国和欧盟人工智能政策比较
The US focuses on continued innovation with limited regulations from the government. | Wikimedia Commons
2016 年 10 月,白宫发布了首个应对人工智能带来的社会挑战的战略[3]。这份报告强调了公开 R&D 的重要性,以及让任何推动人工智能研究的人承担责任的重要性。这表明,应该允许这一领域的创新蓬勃发展,公共部门应该对私营部门实施最低限度的监管。人们的理解是,以自由市场为导向的人工智能发展方式几乎不需要政府干预。
最近的一份报告[4]发表于特朗普政府执政一年后,重点关注保持美国在该领域的领导地位,消除创新障碍,以便公司雇佣本地人,而不是搬到海外。
The EU promotes greater regulation while still being competitive in the global AI ecosystem. | Wikimedia Commons
另一方面,欧盟公布的报告将 AI 视为“智能自主机器人”的组成部分[5]。人工智能被认为是其他技术系统自动化的推动者[6]。该报告建议在自主、人类尊严和不歧视原则的基础上建立更严格的道德和法律框架。事实上,这是在 2018 年欧盟委员会通过关于人工智能的通信时进一步发展的。原始报告还讨论了公共部门在确保上述道德框架得到贯彻而不带有行业偏见方面的主要责任。
案例研究一
众所周知,一家总部位于硅谷的公司在人工智能研究方面投入了大量资金。最近,他们提出了一种最先进的生成对抗网络(GAN),能够生成超现实的人脸。该程序可以生成特定性别、种族和年龄的人脸。
GANs 的应用越来越多,通过其使用传播错误信息的风险也越来越大。在这个虚假内容如此盛行的时代,GANs 对已经在进行的打击虚假信息的努力构成了重大挑战。这个 X 是不存在的是一个汇编流行甘榜的网站。他们中的大多数都是无害的,然而,这个人并不存在引发了关键的伦理问题。
Figure 2: StyleGAN developed by NVIDIA. All these faces are “fake.” Or are they?
该项目可能带来的好处和危害风险是什么?
正如我之前所写的,美国对研发的关注相对更大。这样的项目可能会获得进一步的资助,希望该程序生成的人脸可以取代其他面部识别算法所需的训练数据。与此同时,虚假身份的风险可能会增加,人们会伪装成与他们的面部特征非常匹配的人。
然而,在欧盟,由于更严格的法规,类似的项目可能永远不会普及。然后,其他机器学习算法只能在“真实”人脸上训练,这反过来可能会导致隐私问题。在这种情况下,数据从业者遵循合乎道德的数据存储实践非常重要。已经有无数的例子,人们的照片在未经他们同意的情况下被下载,然后用于人工智能实验。
案例研究二
西雅图华盛顿一家初创企业 X,想投身电商行业。最近,X 从华盛顿大学招募了许多有才华的计算机科学毕业生,并建立了一个新颖的配对算法来匹配消费者和产品。当 X 对他们的产品进行匿名调查时,他们发现大多数参与者更喜欢他们的产品,而不是目前主导电子商务行业的 Y 公司的产品。然而,由于缺乏数据和消费者,X 很难蓬勃发展。
我的上一篇文章讨论了大数据集作为人工智能初创公司进入壁垒的概念。如 Furman 等人[7]所述,依赖于持续互联的用户网络的企业,无论是直接的(如脸书)还是间接的(如亚马逊),都比同行业的进入者具有优势。
两个经济体中的利益相关者受到怎样的影响?这里最相关的道德问题是什么?
最大的利益相关者是竞争者和他们各自的客户。尽管美国和欧盟都有反垄断法,但自本世纪初以来,这两个地区在反垄断法规方面有所松动[8]。由于大量的游说,美国的公司享有“反垄断执法的宽大”,而欧盟的公司通常更具竞争力[9]。
Figure 3: FANG + Microsoft dominate the US tech industry as well as investments in AI. [10] | Image Source
因此,美国不太可能采取允许竞争者之间共享数据的数据可移植性政策。这将阻碍任何由垄断(搜索引擎)或寡头垄断(拼车)主导的行业中新来者的增长。特别是在我们的案例研究中,初创企业可能很难保持相关性并吸引更多客户,因为现任者知道更大客户群的偏好。这也有可能导致针对买不起产品的目标人群的歧视性营销行为。
在欧盟,数据共享将伴随着无数的数据存储和隐私问题。重要的是,公司要制定缓解策略,以防未经授权的第三方访问客户数据。
案例研究三
一位拥有欧盟和美国双重国籍的 CEO 经常往返于工作地点(美国)和住所(欧盟)。最近,一些关于她个人生活的谣言在互联网上浮出水面,这严重影响了她的公司的声誉。她希望找到一种方法来消除谣言,但她受到她居住的两个地方的政策的限制。
Figure 4: According to Bertram et al. [11], Google had received 2.4 million requests to delist links in the first three years of Right to be Forgotten. | Image Source
2014 年 5 月,欧洲法院引入了“被遗忘权”,让人们对自己的个人数据有更多的控制权。它允许欧洲人请求一个搜索引擎,比如谷歌,从它的搜索结果中删除特定的链接。搜索引擎没有义务接受每一个除名请求。它衡量一个人的隐私权是否比公众对相关搜索结果的兴趣更重要。
有趣的是,被遗忘的权利在欧洲以外并不适用,因此即使对欧洲人来说,美国的搜索结果也保持不变。
对社会的透明和自治有什么危害吗?
这两个概念是密切相关的,经常是携手并进的。Vallor 等人[2]将透明度定义为能够看到一个给定的社会系统或机构如何工作的能力。另一方面,自主是掌握自己生活的能力。
被遗忘权在欧盟的采用促进了更大的自主意识,因为如果数据合理地不准确、不相关或过多,个人可以删除他们的个人数据。然而,这是很棘手的,因为搜索引擎本身,而不是一个独立的第三方,负责决定是否删除所请求的链接。
搜索引擎公司已经拥有很大的权力,让他们决定退市请求可能会导致“个人、社会和商业”的损失[2]。我们不禁要问,在引入权利之后,建立一个公正的机构来处理这些请求是否是合乎逻辑的下一步。
有没有下游影响?
在美国,被遗忘权在很大程度上是不允许的,因为它可能会限制公民的言论自由。总体而言,这可能会导致一个更加透明的社会,尽管代价是对搜索结果中出现的个人数据的自主权减少。这种情况的一个极端副作用是,公司可能会丢失大量“相关”数据,这些数据原本可以用来训练他们的人工智能算法。
结论
正如我们在上面的三个案例研究中看到的,美国和欧盟关注人工智能政策的不同方面。除了促进行业的公共 R&D,美国还提倡自由市场的自由理念。欧盟有更严格的法规,但希望保持其在人工智能领域的竞争优势。与美国不同,欧盟不想将监管责任推给私人部门。
Taehwan 和我曾认为,对人工智能的开发和使用制定更多的规定会减少问题。然而,案例研究讲述了一个不同的故事。每种策略都提出了自己的一系列伦理问题。例如,投资 GANs 可能意味着在数据隐私问题和虚假身份之间做出选择。在数据驱动市场的情况下,监管机构需要衡量是否要实施数据可移植性做法,以打破垄断。
—前进的道路
上述(极端的)情况是可以避免的,只要有一个从各种各样的利益相关者那里获取信息的计划。这两个地区提出的策略是全面的,但是正如 Cath 等人[6]所认为的,回答下面的问题将是形成完美政策的关键。
二十一世纪成熟的信息社会的人类工程是什么?
这篇论文提供了一种双管齐下的方法来清晰地理解我们对人工智能社会的愿景。首先,作者建议成立一个独立的委员会,在包括政府和企业在内的不同利益相关者之间进行调解。第二,他们要求把人的尊严放在所有决定的中心。从本质上说,这样做是为了确保在决策中考虑到最脆弱的利益攸关方的利益。
毫无疑问,要实现这个雄心勃勃的计划,需要大规模的协作努力。然而,我们可以从类似的承诺中得到启发,例如最近的《一般数据保护条例》(GDPR) [13]。欧盟和美国仍然需要各自的人工智能政策,但至少讨论它们的优先事项可以帮助它们达成一些共识。
参考
[1]蒂姆·达顿。“国家人工智能战略概述。”政治+AI(2018 年 6 月)。
[2]瓦勒,香农和雷瓦克,威廉。《数据伦理导论》
[3]总统办公厅国家科学技术委员会技术委员会。"为人工智能的未来做准备"(2016 年 10 月)。
[4]科学和技术政策办公室。"2018 年美国工业人工智能白宫峰会摘要"(2018 年 5 月)。
[5]内部政策总局。"欧洲机器人民法规则"(2016).
[6] Cath,Corinne 等人,“人工智能和‘好社会’:美国、欧盟和英国的方法。”科学与工程伦理(2018)。
[7]弗曼、杰森和罗伯特·西曼。“人工智能与经济。”创新政策与经济(2019)。
[8]古铁雷斯,赫尔曼和菲利庞,托马斯。"欧盟市场如何变得比美国市场更具竞争力:一项关于制度变迁的研究."美国国家经济研究局(2018 年 6 月)。
[9]古铁雷斯,赫尔曼和菲利庞,托马斯。"你在美国支付的费用比在欧洲多"《华盛顿邮报》(2018 年 8 月)。
[10]布欣,雅克等人。艾尔。"人工智能:下一个数字前沿?" MGI 报告,麦肯锡全球研究院(2017 年 6 月)。
[11]伯特伦、西奥等,“被遗忘的权利的三年”Elie Bursztein 的网站(2018)。链接。
[12]下议院科学技术委员会。“机器人和人工智能。”(2017).
13 欧洲联盟。《一般数据保护条例》(2018 年 5 月)。链接。
如果你喜欢这个,请看看我的其他媒体文章和我的个人博客。请在下面评论我该如何改进。
Twitter 社交和信息网络:论文综述
关于关注者/转发者关系及其演变的论文综述
全告白,这是 而不是 在推特上获得更多追随者的直接指南。我甚至没有推特账号!!但是我对社交网络有相当不错的了解,这篇 论文*【1】中呈现的结果支持了我的观点。*
因此,如果你想深入了解 twitter 上的粉丝网络是如何演变的,以及为什么某些转发往往会获得大量粉丝,而其他人却不会,你应该继续阅读。我试图以一种任何人都可以理解的方式写这篇博文,不需要任何先验知识。有关更多技术细节,请参考本文。
自我网络
A small portion of the social network. Every node represents a user and every edge represents a follower/followee relation. The blue nodes and edges together represent the ego-networks of two red nodes.
在我们开始之前,让我们谈谈如何用数学方法来表示各种 Twitter 动态。整个社交网络由一个巨大的图形表示,其中每个用户由一个节点表示,每个关注关系由一条有向边表示(从关注者到被关注者)。
用户的自我网络只不过是由她的追随者(不包括用户自己)以及他们之间的所有追随者/被追随者关系组成的子图。在技术术语中,用户的自我网络包含所有具有朝向用户节点的边的节点以及这些节点之间的所有边。
推文相似度
通常,人们会发现用户的自我网络倾向于与用户有相似的兴趣。他们通常会发推文和转发类似的话题。但是我们如何“量化”这种相似性呢?我们可以通过测量推文的文本相似性来做到这一点。
两条推文之间的相似性可以计算为两条推文的 TF-IDF 加权词向量之间的余弦相似性。如果你不知道那是什么,不要担心。粗略地说,这是一种衡量两条推文之间有多少相似单词的方法。这是一个介于 0 和 1 之间的分数,代表给定推文的相似程度。
推特动态
既然我们已经弄清楚了技术细节,让我们更深入地研究一下网络。Twitter 信息网络有两大动态,tweeting/retweeting(代表信息的流动)和 following/unfollowing(代表网络的演变)。正如直觉所暗示的,显然这两者应该是相互关联的。
Twitter 信息图是高度动态的。大约 9%的边缘每个月都会改变,其中大约 2%的改变会被删除。粗略地说,这意味着平均每个用户每获得 3 个追随者就会失去 1 个追随者。
Number of new follow, unfollows, tweets and retweets against the user indegree (number of followers). Clearly highly followed users have a more dynamic ego-network.
对于这样一个动态变化的网络,显然很难对每一个微小的变化进行建模和理解。然而,twitter 有时会经历用户关注/不关注数量的激增。这可能是因为一条出名的推文或者一条冒犯了别人的推文。两种主要类型的突发是,
- **转发关注爆发:**用户获得大量关注者的最明显解释是什么?大概是因为大量新人第一次看到她的推文。或者换句话说,她的转发量激增。
不关注用户的人不会知道她发布的推文。然而,当一条推文被转发很多次时,更多的人第一次接触到它。其中一些人可能会喜欢这条推文,并决定直接关注用户,从而导致她的粉丝数量激增。
User ‘i’ is never directly exposed to the tweets of user ‘k’. However, when user ‘j’ retweets, user ‘i’ gets to know about user ‘k’. It is possible that user ’i’ might like the tweet that she sees and starts directly following user ‘k’.
- **tweet-unfollow 突发:**un follow 突发比 follow 突发更容易解释。有时,一个用户可能会在推特上发布一些惹恼或冒犯她的一大群追随者的事情。这将导致该组关注者不再关注用户,这被称为 tweet-unfollow 突发事件。发微博的频率也是一个重要因素。
为什么不是每个转发的爆发都会导致一个关注者的爆发?
直觉告诉我们,越多的人接触到这条微博,就意味着越多的人开始关注用户。因此,每个转发突发都应该有一个追随者突发。但是,事实并非如此,而且实际上很容易解释。
考虑一个用户(姑且称她为 A)可能拥有的两类关注者,一类是经常转发 A 每条推文的人(姑且称她为 R),另一类是很少转发任何推文的人(姑且称她为 L)。很明显,和 R 有联系(而不是和 A 有联系)的人已经意识到了 A 的存在(由于 R 的频繁转发)。但是,由于他们仍然没有关注,所以即使在转发爆发期间,他们也不太可能这样做。
然而,对于连接到 L(而不是 A)的人来说,情况就不一样了。这些人并没有意识到 A 的存在(因为 L 很少转发),在一次转发突发中第一次接触到 A。这是将决定 A 是否得到那个追随者爆发的“那个”组。如果这个群体的人似乎喜欢 A 的推文,他们会直接开始关注 A,然后转发突发会被关注者突发所取代。然而,反之亦然,以防他们不喜欢 a 的推文。
If users who rarely see the tweets by user ‘i’ are more compatible (better tweet similarity) with the user, then they are more likely to start directly following user ‘i’ after a retweet burst.
但是,如果看到用户的推文,你怎么决定有人跟踪她的可能性呢?这就是两个用户的推文相似性(也称为兼容性)发挥作用的地方。衡量很少接触用户推文的人的兼容性可以很好地预测转发突发是否会有追随者突发。
成绩有多好?
400,000 个随机选择的转发突发被不同的算法排序为最有可能被追随者突发继承。绘制了相同算法的精确-召回曲线,并记录了各种算法的曲线下面积(AUC)。如果你不明白这个指标是什么,没关系,你仍然可以欣赏比较差异。
论文[1] (Myers 等人)中给出的结果明显优于他们对比的任何其他基线算法。“转发曝光次数”是根据看到转发的人数来排名的。“转发数”是根据转发的人数进行排名的。“追随者数量”的排名是基于用户已经拥有的追随者数量,而“随机”只是随机对他们进行排名。
结论
很明显,我们不能否认推特信息网络的两大动力之间的关系,推特/转发和关注/不关注。试图对这些网络中出现的某些行为的原因进行建模是一个开始,并使我们更接近能够理解高度进化和不断增长的社交网络。
注:没有图像、图表、公式等。这个博客里的礼物是我自己的。它们都直接摘自本文[1]。我过去和现在都没有参与这篇论文的研究。要获得更多关于该研究的深入知识,请参考该论文。
参考
[1]迈尔斯,塞斯·a .,和朱尔·莱斯科维奇。"推特信息网络的突发动态."第 23 届国际万维网会议论文集。美国计算机学会,2014 年。
寻找完美的词语?生成它们
使用 LSTM 模型生成诗歌。
Photo by Thought Catalog on Unsplash.
动机
有没有试着找到合适的词来描述你的感受?想在一首诗中向你的另一半表白你的爱吗?你为什么不根据成千上万首著名的诗来生成一首呢?这就是我们试图用长短期记忆(LSTM)模型来做的事情。
什么是 LSTM 模型?
LSTM 模型具有人工递归神经网络(RNN)架构。既然是递归网络,就意味着模型有反馈连接。此外,它可以处理整个数据序列,如句子或视频。LSTM 通常用于手写识别和语音识别。它擅长处理这类问题,因为它有选择性的记忆模式。典型的 LSTM 单元由一个单元、一个输入门、一个输出门和一个遗忘门组成。当信息进入这个单元时,它要么被遗忘,要么被输入到单元的其他部分,要么被汇总并输出。
遗忘门 通过滤波器的乘法运算从细胞中移除信息(见上面最左边的 sigmoid 函数,乘法符号的箭头)。
输入门 是如何将新信息添加到单元格中的。这分三步进行。首先,sigmoid 函数充当过滤器,决定需要添加哪些值。接下来,tanh 函数创建一个包含所有可能相加的值的向量。输出向量将在-1 到 1 的范围内。最后,sigmoid 滤波器和 tanh 函数的值相乘,然后相加到单元格中。
输出门 从单元状态中选择有用的信息并显示为输出。这也分三步进行。首先,应用双曲正切函数得到-1 和 1 之间的值。同样,我们将使用 sigmoid 函数作为过滤器。为了完成这一步,tanh 函数创建的向量与过滤器相乘,并将其作为输出发送到下一个隐藏单元格。
总之,所有这些门使得 LSTM 模型在序列预测方面比典型的卷积前馈网络或 RNN 好得多。这就是为什么我们选择使用 LSTM 模型来生成诗歌。
我们的数据
用于训练我们的用于诗歌生成的 LSTM 模型的数据来自于《PoetryFoundation.com 诗集》。数据可以在 Kaggle 上的处找到。每个诗歌条目包含几个描述诗歌的标签。我们决定把重点放在三类诗歌上:爱情、自然和悲伤。为了获得正确的数据,我们需要从数据集中提取具有特定标签的诗歌。我们决定将每首诗的字符数限制在 1000 个以内(我们用了更多的字符),因为这样我们就包含了足够多的诗,并且不会给我们的计算机带来太大的压力。在下面的代码中,您可以看到我们是如何获得数据的。
**# include 1000 characters from each poem**
pd.options.display.max_colwidth = 1000 **# load dataset from poetryfoundation.com dataset**
df = pd.read_csv('PoetryFoundationData.csv') **# dropping any entries with no tags**
df = df.dropna()
这是原始数据的一个例子。
Raw poem data from Kaggle dataset. Photo by author.
正如你在上面的原始数据中看到的,有几个标签。为了这篇博文的目的,我们将只向您展示我们是如何提取带有标签“爱”的诗歌的(参见下面的代码)。我们还使用其他标签生成了诗歌,你可以在这篇文章的结尾看到。
poems = df[‘Poem’]**# you can add additional tags to searchfor if you want more poems**
searchfor = [‘Love’]
lovePoems = poems.loc[df[‘Tags’].str.contains(‘|’.join(searchfor))]
lovePoems = lovePoems.to_string()
训练模型
一旦我们收集了我们需要的诗歌,我们就能够创建训练和测试数据。在下面的代码中,我们创建了训练数据。首先,我们必须将字符映射到索引,反之亦然。
chars = sorted(list(set(lovePoems)))
char_indices = dict((c, i) for i, c in enumerate(chars))
indices_char = dict((i, c) for i, c in enumerate(chars))
接下来,我们必须为训练创建 X 和 Y 数据集。这个过程将一大串诗歌分割成长度为 50 个字符的序列。
**# process the dataset**
seqlen = 50
step = seqlendata_X = []
data_y = []poemLines = []**# creates poem lines**
for i in range(0, len(lovePoems) — seqlen — 1, step):
poemLines.append(lovePoems[i: i + seqlen + 1])
**# creating x and y data**
data_X = np.zeros((len(poemLines), seqlen, len(chars)), dtype=np.bool)
data_Y = np.zeros((len(poemLines), seqlen, len(chars)), dtype=np.bool)for i, poemLines in enumerate(poemLines):
for t, (char_in, char_out) in enumerate(zip(poemLines[:-1], poemLines[1:])):
data_X[i, t, char_indices[char_in]] = 1
data_Y[i, t, char_indices[char_out]] = 1
生成数据后,我们建立了模型。其架构中有一个 LSTM 层和一个密集层。我们将在下面讨论,但我们玩了 LSTM 层的隐藏单位的数量。此外,我们尝试了一个具有 2 个 LSTM 层和 3 个 LSTM 层的模型。保持所有变量不变,当改变层数时,我们没有看到模型性能的差异。
**# create the model**
model = Sequential()
model.add(LSTM(80, input_shape=(seqlen, len(chars)), return_sequences=True))
model.add(Dense(len(chars), activation='softmax'))model.compile(loss='categorical_crossentropy', optimizer=RMSprop(learning_rate=0.01), metrics=['categorical_crossentropy', 'accuracy'])
model.summary()
评估模型
然后,我们准备好安装我们的模型。经过 128 个批次和 10 个时期的训练,我们达到了 0.68 的准确率。
**# evaluate the model on validation set and visualize** history = model.fit(data_X, data_Y, validation_split = .33, batch_size=128, epochs=10)
我们还在验证数据集上评估了该模型,并可视化了结果。下图显示了 LSTM 层有 128 个隐藏单元时的训练和验证损失。
Visualization of model training and validation loss when LSTM layer had 128 hidden units. Photo by author.
然而,当我们用 80 个隐藏单元为 LSTM 层拟合我们的模型时,我们看到了下图。
Visualization of model training and validation loss when LSTM layer had 80 hidden units. Photo by author.
当比较这两个图时,我们可以看到 LSTM 层中具有 80 个隐藏单元的模型比具有 128 个隐藏单元的模型具有更好的拟合。具有 128 个隐藏单元的模型显示了我们在研究中读到的过度拟合模式。随着时间的推移,训练和验证数据会出现分歧,这不是我们想要的。然而,对于 80 个隐藏单元,训练和验证损失一起减少,表明模型拟合良好。
我们也意识到,我们的精确度本来可以更高。我们尝试用数据集中每首诗的 3000 个字符来训练我们的模型。这增加了我们拥有的数据量,我们能够将模型的准确性提高到 78%,增加了 10%。如果我们有更多的时间和更多的计算能力,我们可以使用更多的数据。我们使用的数据量比我们能获得的要少,因为训练时间太长了。
生成诗歌
在确定了模型的架构之后,我们使用下面的代码生成了一些诗歌。
**# helper function that samples an index from probability array** def sample(preds, temperature=1.0):
preds = np.asarray(preds).astype('float64')
preds = np.exp(np.log(preds) / temperature) # softmax
preds = preds / np.sum(preds)
probas = np.random.multinomial(1, preds, 1) # sample index
return np.argmax(probas)**# generate poem** def generating_poem(poem_length, start_index, diversity, _):
start_index = start_index
diversity = diversitygenerated = ''
poemLines = lovePoems[start_index: start_index + seqlen]
generated += poemLines
print('----- Generating with seed: "' + poemLines + '"')
sys.stdout.write(generated)for i in range(poem_length):
x_pred = np.zeros((1, seqlen, len(chars)))
for t, char in enumerate(poemLines):
x_pred[0, t, char_indices[char]] = 1.
preds = model.predict(x_pred, verbose=0)
next_index = sample(preds[0, -1], diversity)
next_char = indices_char[next_index]poemLines = poemLines[1:] + next_charsys.stdout.write(next_char)
sys.stdout.flush()
print()
下面,我们生成了一首诗,长度为 500 个字符,一个开始索引(这是来自原始文本的序列长度的字符串),多样性为 0.5。分集输入改变了采样概率。经过几次尝试,我们发现 0.5 的多样性给了我们最好的诗。多样性为 0.1 会使诗歌过于重复,多样性为 1 会使诗歌缺乏意义。
**# input desired poem length, start index, diversity**
generating_poem(500, 60, .5, _)
下面是上面代码运行的输出:
----- Generating with seed: "n\r\r\n\r\r\n\r\r\nAnd it won’t be multiple choice"
n\r\r\n\r\r\n\r\r\nAnd it won’t be multiple choiced in the sky love and made the back between the forest and the from the black and sky feet promised which her desire. I could come before the point to the collation.\r\r\nI am a dear the shadows and which stare of the father, the cheek and boxasted seeman that the confecting the can sweating while I moved me can don’t know you want to still watch the stater and we can see a poem who deep of bene to the didn’t were been on the breaks dark in the tongue and blood from the color in the morning on t
如您所见,输出包括新的线条指示器(\r\r\n)。我们尝试从训练字符串中删除这些字符,但是我们认为保留这些字符可以让我们的模型像真正的诗歌一样构建我们生成的诗歌。下面,我们展示了一些我们生成的、格式很好的诗歌。
爱情诗#1:
Roy and Glenlost themselvesis the world the prides or story in the starting the discapive to the stranged start us the wind. The down the stucky strange and the last the skyeach an all the spon and carry me heart and set, and the bright have so sand for the stranged of the stranger. I see we between my leaves stranged the skies in the annt, sweet of at the same shade to heart, and the can don’t grape in not so self
爱情诗#2:
The woman carried the bucketand the man with sing are fingers the soft in this do, and of the conficial from the strangering to my slight which the sky stead between the body of a sation under there is the spring became and prices air strange of me to mouth have at his blossoms the sands in the trangs of the stared a paration in the man spring of carvant
悲伤的诗#1:
Among these in this place my father layAt the end of everythingIn the curked the pather she have years with the single to the mander,as mance of the should the wordder the stear the procked the goor in hone the searther the marmer.I was a sinder the pourth of the say and word the same the see we life, geser and he was down the all dading morned with the stead of the sleet on the surion, not liver, a mone the mardens colling to me see she seeple of the sead of the becausion the spean.Lone the bood the swear the looked wor a man her beants of the rom
悲伤的诗#2:
tooed with red…Imagine half your facerubbed out yetyou are suited upwhere were souned a reared semerita manding words and the did read to mister the flown the stone are where dristed were the san land a come was the son like word the light of the wise to belendand she teather, you been a die and lacken the wanted from the cores and the mand of Comples, never a come your mone the mone of the she she park of hall that like the sard of the she was the pleared in the say back the meed the say with to be the ray.A dried be sun to carr take in th
自然诗#1:
Soon the fish will learn to walk. Then humans will come ashore and paint dreams on the wall distant when the rain she who water the world of mean the flower the flowers the flacks the ancent of my walls and shadows the river and stars them like the sung and fluethe sea when the bodge his not behind the streets of the remement and she to the sings in the screen, the name the stars of the days on the the sounds the dark skin the mother the same and this pity, the clouds have a state is sings and someone land, and at my shell starsas the little still make a way t
自然诗#2:
e; it is obvious) and everything about him is beautiful. His hand swells from the bite [spread?] of the sky in the more the will condine her the distant green the forms, the wind my bear the side the roots where a merch her cold of high a constiled in the charged the body the stars in the wind sauter be. The cold with the world from the remember, and he stream and sting for the season the men raina wood with the was in the silence and men the world it roses where the cattent the capt and seas the dark and still as the grasswhere he the stars and past of the the color the beats head
生成诗述评
总的来说,我们的诗歌输出似乎生成了与数据集格式相似的诗歌。他们有相似数量的“\r\r\n”来表示间距,并且他们非常擅长造句。每个类别的总体情绪似乎也反映了它所来自的数据。然而,它们仍然很难符合逻辑,并且高度基于起始索引。起始索引在决定这首诗的结局方面起着很大的作用。起始种子中的单词经常在整首诗中重复出现。
在将来,为了提高这些诗的输出,我们可以将这些诗编入索引,这样每次的起始种子都从诗的开头开始,而不是从诗的中间或结尾开始。我们可以做些工作,让它在一首完整的诗上训练,这样它就不会随机开始和结束——创造一首更简洁的诗。
每个句子的逻辑感是另一个需要提高的地方。然而,这在诗歌中是一个巨大的挑战,因为诗歌是艺术的,不一定遵循传统的语法规则。我们也可以做更多的研究来让诗歌更连贯。
反光
当我们开始这个项目时,我们原本打算使用一个生成式对抗网络(GAN),其中生成器是一个递归神经网络(RNN)。在做了一些研究之后,我们发现有几篇文章提到了在文本格式上使用 GAN 时的困难和不准确性。我们还看到有人推荐 LSTM 模型,所以我们改用了它。如果使用 GAN 就好了,因为我们可以组合数据的潜在空间,而不是为每种类型的诗歌创建一个新的模型。
我们可以尝试的另一件事是把这首诗按照时间周期分开。莎士比亚写的诗与现代诗有着非常不同的语言,这可能会给模型生成带来混乱的数据集。如果我们要添加到这个项目中,我们可以按时间段分开,这样用户可以选择他们希望他们的诗出来的风格。
Photo by Thought Catalog on Unsplash
另一个可以添加到未来工作中的功能是诗歌标题。如果我们有更多的时间,我们可以格式化数据,将诗名和诗内容一起放入。然后,我们将根据匹配每首生成的诗歌的标签生成一个标题。然而,这可能会导致标题与实际的诗歌内容无关。
总的来说,我们意识到有很多事情我们可以尝试改进模型的诗生成。然而,我们在诗歌生成方面有了一个良好的开端,并且已经了解了很多关于 LSTM 模型如何工作以及如何调整它们的知识。
参考
引言序列预测问题由来已久。他们被认为是最难的…
www.analyticsvidhya.com](https://www.analyticsvidhya.com/blog/2017/12/fundamentals-of-deep-learning-introduction-to-lstm/) [## 人工智能生成泰勒·斯威夫特的歌词
泰勒斯威夫特歌词生成器
towardsdatascience.com](/ai-generates-taylor-swifts-song-lyrics-6fd92a03ef7e) [## 如何诊断 LSTM 模型的过拟合和欠拟合
很难确定你的长短期记忆模型是否在你的序列中表现良好…
machinelearningmastery.com](https://machinelearningmastery.com/diagnose-overfitting-underfitting-lstm-models/) [## 文本生成的生成性对抗网络——第一部分
用于文本生成的 GANs 的问题以及解决这些问题的方法
becominghuman.ai](https://becominghuman.ai/generative-adversarial-networks-for-text-generation-part-1-2b886c8cab10) [## 基于神经网络的音乐生成——本周 GAN
本周 GAN 是一系列关于生成模型的笔记,包括 GAN 和自动编码器。每周我都会复习一篇…
medium.com](https://medium.com/cindicator/music-generation-with-neural-networks-gan-of-the-week-b66d01e28200)
Emma Sheridan 和 Jessica Petersen 为人工神经网络课程完成的项目。这个项目的源代码可以在 [GitHub](https://github.com/emmasheridan/ANNfinalproject) 上找到。
一张图来统治他们所有人——指环王网络分析
链接到最终结果→链接
我第一次看《指环王》是在 2001 年,我觉得我的生活永远改变了。从 2001 年到现在已经过去很长时间了,但直到今天我还能享受看加长三部曲的乐趣。由于电影看多了,我决定做点不一样的,把魔戒和数据分析的世界结合起来。
魔戒和数据分析如何结合?这是个好问题…
与所有数据分析项目一样,一切都始于数据。
我在网上快速搜索了一下,找到了一个网站一个统治一切的维基,一个充当 J. R. R .托尔金图书百科全书的网站。幸运的是,该网站包含数千页关于人物、地点、种族和历史小说事件的详细信息。
此外,它允许任何人使用爬虫抓取它的页面。我怎么知道?因为在每个站点“robots . txt/”都可以添加到 URL 中,检查站点是否允许抓取,以及在什么条件下。(链接到该网站的 robots.txt ,进一步了解 robots.txt )
首先,我必须到达网站并抓取所有页面。我决定只刮去几页文字,并把注意力集中在它们上面。
可以刮出哪些数据?
每一页都包含文本、照片、链接,在许多情况下还有传记资料。我对传记数据特别感兴趣,因为我假设它包含的字段在所有页面中都是相似的,所以我可以将它安排到一个数据框中。
先说传记资料。
在抓取了所有的字符页之后,这就是数据框的样子:(使用 missingno 绘制数据框)
如你所见,有许多列,但大多数都是半满或几乎是空的。在对数据进行清理和重新整理后,我对以下领域进行了分析:武器、领域、种族、性别、文化。
传记资料
上面的图表显示了人物种族和出身的分布。如种族图所示,男性最常见,然后是霍比特人、精灵、矮人、兽人等等。在分析过程中,我遇到了一些我不知道的人物。例如,你知道有 3 个不同的角色属于巴罗格种族吗?
在文化图表中,不出所料,最常见的文化是男性文化,而刚铎和洛汗文化位于顶部。这个图表与种族图表相关联,它讲述了同样的故事。
性别图表显示,男性比女性多得多(几乎多 5 倍)。更有可能的是,如果这些书是在我们这个时代而不是在 20 世纪写的,那么图表会更加平衡。
最后一张图显示了武器的分布情况。为了创建这个图表,我必须将武器的名称标准化。在大多数情况下,一种武器有几种版本。例如,在“剑”类别下,有“国王之剑”、“精灵之剑”、“罗希里姆之剑”等等。
正文
NLP 是一个迷人的世界,人们可以使用各种算法从文本中提取洞察力。因为我想保持专注,所以我决定只创建一个强调文本力量的图表。
上图是用甘道夫的页面中的文字制作的。单词排列成环形,它们的大小与它们在文本中的出现频率有关。
链接
链接可能看起来不像一个强大的数据源,但在我看来,这将是一个低估。使用链接分析,我们可以指出几点见解。例如:A)一个角色有多受欢迎,B)角色之间有什么联系和关系。
这个图表非常有趣,因为它告诉我们,提到最多的人物不一定是中心人物。索伦和甘道夫是重要的角色,但在我看来,他们没有佛罗多重要。尽管如此,弗罗多最终排名第九,而索伦和甘道夫则分列第一和第二。等级并没有告诉我们故事的中心地位,但是它告诉了我们角色之间的联系。
在网络理论中,中心度是用来衡量网络中节点中心性的度量。指向你的节点越多,你就越居中。上图与上图不同,因为它通过唯一链接的数量而不是简单链接的数量来衡量角色的中心性。
另一个让我们了解节点重要性的指标是中间中心度。该指标衡量节点对网络中最短路径的重要性。例如,布鲁克林大桥不是一个中心位置,因为人们参观它,而是因为人们在去其他地方的路上走过它。
为了获得关于字符连接的一些见解,有几种社区检测算法。在下一个示例中,图表显示了使用 Louvain 算法检测到的社区所着色的字符。
Top 100 Characters Network
Louvain Detected Communities (Top 100)
由于我搜集的数据已经包含了角色的许多细节,我认为这些复杂的模型在我们的案例中没有任何用处。这些角色可以根据他们的种族或文化来划分。
Lord of The Rings Network
Characters Details
在上图中,你可以看到网络图中人物之间的联系。在这个互动网络(使用 pyvis 制作)中,当鼠标悬停在每个节点上时,角色的传记数据就会显示出来。当鼠标悬停在边缘时,引用的数量会显示出来,这可以告诉我们字符之间的连接质量。节点的大小与它们的中心度有关,它们的位置是使用Barnes–Hut simulation算法基于它们的连接来计算的。
感谢大家阅读我的文章,如果你有任何问题,意见或改进的想法,请在下面留下评论!
洛伦茨 96 太容易了!机器学习研究需要更真实的玩具模型。
点击 这里 会打开一个互动笔记本,你可以在里面重现本帖中的所有可视化效果和结果。
埃德·洛伦茨是一个天才,他提出了简单的模型,在一个复杂得多的系统中抓住了问题的本质。他从 1963 年开始的著名蝴蝶模型启动了混沌研究,随后是更复杂的模型来描述高档误差增长( 1969 )和大气环流( 1984 )。1995 年,他创造了另一种混沌模式,这将是这篇博文的主题。令人困惑的是,尽管最初的论文出现在 1995 年,但大多数人将该模型称为 Lorenz 96 (L96)模型,我们在这里也将这样做。
洛伦茨 96 型
先简单介绍一下车型。在这里,我将使用来自 Schneider et al .2017的符号。在其最简单的版本中,该模型由 K (k=1,…,K)个周期系统描述:
右边的第一项是平流项,而第二项代表阻尼。f 代表外部强制项,设置为 10。因为这是一个周期系统,我们可以用圆形图来形象化它的演变:
对于参数估计或参数化研究,最常见的是使用 L96 模型的两级版本。为此,我们加上另一个周期变量 Y,它有自己的一组常微分方程。X 和 Y 电极通过耦合项连接,耦合项是下面两个方程中的最后一项。每个 X 有 J 个与之相关的 Y 个变量。
同样,我们可以通过可视化来更好地理解正在发生的事情。
为什么 L96 车型太容易
L96 模式自提出以来,已被广泛应用于资料同化和参数化研究。最近,L96 车型经历了一次复兴,以测试驱动用于参数学习或子网格参数化的机器学习算法。事实上,我自己最近也发表了一篇论文,其中我展示了一个使用 L96 模型的在线学习算法。
但是 L96 有一个很大的问题:它太简单了!我这么说是什么意思?让我们看一个 L96 模型的经典用例,参数化研究。与真实的大气或海洋类似,X 代表已解决的慢速变量,而 Y 代表未解决的快速变量。本质上,任务是建立一个参数化,通过替换 X 方程中的最后一项来表示快速变量对 X 的影响,为方便起见,我们称之为 B。
假设我们忽略了空间和时间的相关性,只把 B_k 建模为 X_k 的局部函数。
我们可以建立的最简单的参数化是线性回归:
以下是真实数据点和线性回归的样子:
现在让我们使用简单的线性回归参数化,将其插入 L96 模型并对 100 个无量纲时间单位进行积分。以下是 X 和 B 的统计结果:
当然,它们并不完全相同,但是 X 直方图中的差异已经非常小了。我们可以进一步计算一些统计数据,如真实模型和参数化模型的 X 和 B 的平均值和可变性。
相对差异真的很小。这意味着简单的线性回归基本上解决了 L96 参数化问题。当然,你可以改进这个简单的基线,但是我们没有遇到困扰真实大气或海洋模型中最大似然参数化研究的任何问题。
需要更逼真的玩具模型
参数化子网格过程是气候建模的巨大挑战。现代机器学习方法可能是取得真正进展的一种方式。在过去的两年里,最初的研究(这里的或者这里的或者或者这里的或者已经证明了建立一个 ML 参数化通常是可行的。但是,正如我在最近关于在线学习的论文中总结的那样,在最大似然参数化能够真正改善天气和气候预测之前,还有几个基本障碍需要克服。稳定性、物理一致性和调谐只是其中的一部分。
为了解决这些问题,我们需要尝试一系列新方法。L96 可以是一个很好的起点,以确保算法的工作。但是如果真的发生了呢?因为 L96 没有表现出首先需要更复杂的方法的任何问题,L96 中的工作实现没有给出该方法是否也适用于全复杂性模型的更多证据。
那么,为什么不马上在一个完全复杂的模型中实现这个算法呢?问题是目前的大气和海洋模型带有巨大的技术包袱。它们通常是用成千上万行支持 MPI 的 Fortran 语言编写的。这使得快速测试一个新方法基本上不可能。即使实现一个用 Python 训练的简单神经网络目前也是一个挑战。Fortran-Python 接口是可能的,但不是特别用户友好和快速。更复杂的方法,如在线学习、强化学习或集合参数估计,将需要对模型进行更复杂的改变。最后,全复杂性模型,特别是如果需要高分辨率的模拟,在计算上是昂贵的,这使得快速实验非常困难。
所有这些挑战都迫切需要 L96 和全复杂性模型之间的中间步骤。
中间复杂度模型的属性
那么这个中级复杂度模型应该是什么样子的呢?以下是一些要求:
- 多尺度:因为我们正在寻找建立一个子网格参数化,我们需要一个系统,我们可以分为解决和未解决的过程。理想情况下,它是一个连续的系统,所以我们可以模拟粗粒化的额外挑战。
- 一个主要的运动方向:在大气和海洋中,垂直运动与水平运动非常不同。这就是参数化通常作用于列的原因。在玩具模型中反映这一点会很有帮助。
- 复杂到足以展示实际问题:ML 参数化研究的头两年揭示了以下关键问题。一个好的玩具模型应该模拟其中的大部分。
- ____ 稳定性:耦合/在线模拟通常是不稳定的。
- ____ 偏差:即使离线(非耦合)验证表明 ML 参数化准确地再现了亚网格效应,在线运行也经常显示偏差或漂移。
- ____ 物理一致性:在真实的地球系统中,能量和其他属性守恒是至关重要的。(最近由 Tom Beucler 领导的一篇论文展示了如何在神经网络训练期间做到这一点。)应该可以写下某些守恒性质。
- ____ 推广到看不见的气候:ML 参数化到目前为止还不能在它们的训练范围之外进行外推。这意味着人们应该能够通过外部强制来改变模型的基本状态。
- ____ 随机性:到目前为止,大多数 ML 参数化都是确定性的,这意味着真实的混沌系统的某些可变性是缺失的。因此,模型也应该是混沌的。
- 易于理解:大部分可用模型(如 LES 或 CRMs)的一个问题是,它们试图尽可能好地表示大气,这导致了复杂的数值方法和物理方程。我们正在寻找的中等复杂程度的模型不需要精确地代表真实世界。简单更重要。这适用于基本方程和数值方法。
- 快速运行:一些提出的方法需要许多模型运行,通常是在一个集合中。中等复杂度的模型应该足够快,最多在几分钟内运行一次预测。
- 易于使用:这绝对是关键。该模型必须有一个 Python 接口,以兼容最常用的 ML 库。人们还应该能够在 Jupyter 笔记本中交互式地运行模型,即一次执行一个步骤并查看字段。
我不是流体建模专家,所以我在这里寻求帮助。满足所有(大部分)这些要求的一组好的方程是什么?它可能是一个非常接近真实大气/海洋方程(即纳维尔-斯托克斯方程)的系统,或者是具有类似特征的完全不同的系统。
我相信新方法的快速测试绝对是 ML 参数化研究进展的关键。目前,我们(或者至少我是)被 L96 等过于简单的模型和完全复杂的模型之间的差距所阻碍。
PS:我的建议
这是我的一个非常模糊的想法:一个 2D 云解析模型,尽可能使用最简单的方程。正如超级参数化和其他早期对流研究显示的那样,二维 CRMs 捕捉到了真实对流的大部分本质。当然,2D 模型比 3D 模型要快得多。
这个模型的基础可以是滞弹性运动方程。微观物理学方案可以是简单的饱和度调整方案,只有一种水文凝结物物种(液体)在某一阈值以上降雨。湍流可以用一阶局部 K-闭包来建模。表面将有一个恒定的温度,并通过一个简单的体积方案与空气相互作用。辐射只能通过在自由大气中的持续冷却来表现。
有了这个模型,就有可能运行一个辐射对流平衡的设置。但是,为了使它更有趣,并涉及一些大规模的动态,人们可以想象一个像这个粗糙的图纸显示的设置。
在这里,我们基本上有一个平坦的,周期性的微型世界,具有冷-暖梯度,这将导致一个大规模的循环单元,在暖池上方有深度对流(对吗?).可以想象一个有 250 根 4 千米宽的柱子,30 层的系统。从计算的角度来看,这应该是可以管理的。
这种设置是否可行,能否重现上述关键挑战?确切的方程式应该是什么?
基于特征激活和风格损失的损失函数。
Feature activations in Convolutional Neural Networks. Source: https://arxiv.org/pdf/1311.2901.pdf
使用这些技术的损失函数可以在基于 U-Net 的模型架构的训练期间使用,并且可以应用于正在生成图像作为其预测/输出的其他卷积神经网络的训练。
我已经将这一点从我关于超分辨率的文章中分离出来(https://towards data science . com/deep-learning-based-Super-Resolution-without-use-a-gan-11 C9 bb 5b 6 CD 5),以更加通用,因为我在其他基于 U-Net 的模型上使用类似的损失函数对图像数据进行预测。将此分开,便于参考,也便于理解我的其他文章。
这是基于 Fastai 深度学习课程中演示和教授的技术。
该损失函数部分基于论文《实时风格传输和超分辨率的损失》中的研究以及 Fastai 课程(v3)中所示的改进。
本文重点研究特征损失(文中称为感知损失)。这项研究没有使用 U-Net 架构,因为当时机器学习社区还不知道它们。
Source: Convolutional Neural Network (CNN) Perceptual Losses for Real-Time Style Transfer and Super-Resolution: https://arxiv.org/abs/1603.08155
所使用的损失函数类似于论文中的损失函数,使用 VGG-16,但是也结合了像素均方误差损失和 gram 矩阵风格损失。Fastai 团队发现这非常有效。
VGG-16
VGG 是 2014 年设计的另一种卷积神经网络(CNN)架构,16 层版本用于训练该模型的损失函数。
VGG-16 Network Architecture. Source: https://neurohive.io/wp-content/uploads/2018/11/vgg16-1-e1542731207177.png
VGG 模式。在 ImageNet 上预先训练的网络用于评估发电机模型的损耗。通常这将被用作分类器来告诉你图像是什么,例如这是一个人,一只狗还是一只猫。
VGG 模型的头部是最后几层,在上图中显示为全连接和 softmax。该头部被忽略,损失函数使用网络主干中的中间激活,其代表特征检测。
Different layers in VGG-16. Source: https://neurohive.io/wp-content/uploads/2018/11/vgg16.png
这些激活可以通过查看 VGG 模型找到所有的最大池层。这些是检测网格大小变化和特征的地方。
下图显示了各种图像的图层激活热图。这显示了在网络的不同层中检测到的各种特征的例子。
Visualisation of feature activations in CNNs. Source: page 4 of https://arxiv.org/pdf/1311.2901.pdf
基于 VGG 模型的激活,模型的训练可以使用这个损失函数。损失函数在整个训练过程中保持固定,不像 GAN 的关键部分。
特征损失
特征图有 256 个 28×28 的通道,用于检测毛发、眼球、翅膀和类型材料等特征以及许多其他类型的特征。使用基本损失的均方误差或最小绝对误差(L1)误差来比较(目标)原始图像和生成图像在同一层的激活。这些是特征损失。该误差函数使用 L1 误差。
这使得损失函数能够了解目标地面真实影像中的特征,并评估模型预测的特征与这些特征的匹配程度,而不仅仅是比较像素差异。这允许用该损失函数训练的模型在生成/预测的特征和输出中产生更精细的细节。
格拉姆矩阵风格损失
gram 矩阵定义了关于特定内容的样式。通过计算目标/地面真实图像中每个特征激活的 gram 矩阵,允许定义该特征的风格。如果从预测的激活中计算出相同的 gram 矩阵,则可以比较这两者来计算特征预测的风格与目标/地面真实图像的接近程度。
gram 矩阵是每个激活和激活矩阵的转置的矩阵乘法。
这使得模型能够学习并生成图像的预测,这些图像的特征在其风格和上下文中看起来是正确的,最终结果看起来更有说服力,并且看起来与目标/背景真相更接近或相同。
用此损失函数训练的模型的预测
使用基于这些技术的损失函数从训练模型生成的预测具有令人信服的细节和风格。风格和细节可能是预测精细像素细节或预测正确颜色的图像质量的不同方面。
用基于这种技术的损失函数训练的模型的两个例子,显示了用这种特征和风格损失函数训练的模型是多么有效:
Super resolution on an image from the Div2K validation dataset
根据我的着色实验,文章发表时会添加一个链接:
Enhancement of a Greyscale 1 channel image to a 3 channel colour image.
法斯泰
感谢 Fastai 团队,没有你们的课程和软件库,我怀疑我是否能够学习这些技术。
迷失在翻译中。被变形金刚发现。伯特解释道。
打造下一个聊天机器人?伯特,GPT-2:解决变压器模型的奥秘。
通过这篇文章,你将了解为什么有可能产生假新闻。基于 Transformer 的语言模型,如 OpenAI 的 GPT-2,最近已经使计算机能够对他们选择的主题生成现实而连贯的延续。应用可以在人工智能写作助手、对话代理、语音识别系统中找到。基于变形金刚的模型在产生误导性新闻方面也很成功,在网上假冒他人,创建虚假内容发布在社交媒体上,扩大网络钓鱼内容的生产。令人惊讶的是,同样的基于变压器的方法也可以用来检测虚假内容。
source: Hendrik Strobelt and Sebastian Gehrmann
Transformer 是 Vaswani 等人在论文Attention is All You needle中提出的一种机器学习模型。由于并行化,它在特定任务中的表现优于谷歌神经机器翻译模型,这与序列到序列模型的顺序性质相反。
为了理解 Transformer 是如何工作的,我们来看看它是如何执行机器翻译的。
再见 LSTM 和 GRU?
当序列到序列模型由 Sutskever 等人,2014 , Cho 等人,2014 发明时,机器翻译的质量有了量子跳跃。我们最近写了序列对序列模型的工作。
如何预测客户询问背后的意图?Seq2Seq 型号说明。在 ATIS 数据集上演示的槽填充…
towardsdatascience.com](/natural-language-understanding-with-sequence-to-sequence-models-e87d41ad258b)
由于序列到序列的方法,我们第一次能够将源文本编码到内部固定长度的上下文向量中。一旦编码,不同的解码系统可以用来翻译成不同的语言。
序列到序列模型通常通过注意机制连接编码器和解码器来增强,正如我们在之前的文章中所展示的。
测试动手策略以解决注意力问题,从而改进序列到序列模型
towardsdatascience.com](/practical-guide-to-attention-mechanism-for-nlu-tasks-ccc47be8d500)
Transformer 是一种不同的架构,用于在编码器和解码器这两个部分的帮助下将一个序列转换为另一个序列。然而,它超越了自 2014 年以来统治机器翻译世界的序列对序列范式。
变形金刚完全建立在注意力机制上。也就是说,这并不意味着任何循环网络:注意力是你所需要的。
变压器架构
原始论文建议将编码组件作为六个编码器和六个解码器的堆栈,如下所示。所有六个编码器都是相同的,但是它们不共享重量。这同样适用于六个解码器。
(source: Jay. Alammar, 2018)
每个编码器有两层:一个自关注层和一个前馈层。正如我们所见,没有使用循环层。给定一个输入单词(其嵌入,建议大小为 512),自我关注层查看输入句子中的其他单词,以寻找有助于对该单词进行更好编码的线索。为了更好地掌握这一机制,您可能想体验一下 Tensor2Tensor 笔记本中的动画。
adapted from (source: Jay. Alammar, 2018)
自我关注不是利己主义
Transformer 使用 64 维向量计算自我关注度。对于每个输入单词,有一个查询向量 q ,一个关键向量 k ,以及一个值向量 v,被维护。将所有这些放在一起,他们构建了矩阵 Q , K 和 V 。这些矩阵通过将输入单词 X 的嵌入乘以三个矩阵【Wq】WkWv来创建,这三个矩阵在训练过程中被初始化和学习。
在下图中, X 有 3 行,每行代表输入句子“je suis étudiant”中的一个单词。通过填充,矩阵 X 将被扩展到 512。为了说明的目的,每个单词通过四维嵌入来编码。最初的变形金刚使用 512 维嵌入。在我们的例子中, W 矩阵应该具有形状(4,3),其中 4 是嵌入维度,3 是自我关注维度。原变压器用 64。因此 Q,K,V 是(3,3)-矩阵,其中第一个 3 对应于字数,第二个 3 对应于自我注意维度。
adapted from (source: Jay. Alammar, 2018)
那么,我们如何计算自我关注度呢?
现在让我们假设在这些向量中有一些值。我们需要根据当前输入单词对输入句子的每个单词进行评分。让我们给单词“je”打分,它在法语中是“I”的意思。分数决定了对输入句子“je suis étudiant”的其他部分“suis”和“étudiant”的关注程度。
分数就是查询向量 q_1 与单词“je”的关键向量 k_1 的点积。这在下面的示例中给出了 112。我们对第二个单词“suis”做同样的操作,得到它的分数 96。我们也对最后一个单词“étudiant”这样做。
Transformer 的作者发现,当我们将分数除以关键向量的维数的平方根(sqrt 为 64,即 8)时,这会导致更稳定的梯度。
结果通过 softmax 操作进行标准化,使分数都为正,加起来等于 1 (0.84 表示“je”,0.12 表示“suis”,0.04 表示“étudiant”)。显然“suis”这个词比“étudiant”这个词与“je”更相关。现在,我们可以通过将每个值向量乘以 softmax 分数来淹没不相关的词,如“étudiant”,并减少对“suis”的关注。
自我关注层对于“je”的输出Z1最终通过对加权值向量求和得到。产生的向量被发送到前馈神经网络。
adapted from (source: Jay. Alammar, 2018)
这种自我注意的计算以矩阵的形式对序列中的每个单词重复进行,速度非常快。 Q 是包含序列中所有单词的所有查询向量的矩阵, K 是键的矩阵, V 是所有值的矩阵。
自我关注的整个计算过程将在下面很好地呈现。
多头注意力
现在,我们知道如何计算自我关注。你可能已经注意到,注意力会一遍又一遍地被吸引到同一个单词上。这就像那个受到老板所有关注的同事。如果我们重新洗牌以避免偏见的关注。想象一下,我们有更多的那些WkWv矩阵,它们被用来计算 Q,K 和 V 矩阵,这些矩阵被进一步用来计算所有单词的自我关注度。我们回忆一下,Wq* , Wk , Wv 都是在训练中学会的。因此,如果我们有多个这样的矩阵,我们可以克隆自我注意计算,每次都会导致我们的文本的不同视图。因此,我们将输入嵌入投影到不同的表示子空间中。例如,如果我们用 8 个不同的 Wq 、 Wk 、 Wv 权重矩阵做同样的自我关注计算,我们最终得到 8 个不同的 Z 矩阵。事实上,这正是《变形金刚》的作者所做的。他们将所有八个 Z 矩阵串联起来,然后将得到的巨大矩阵乘以一个附加的权重矩阵 Wo 。*
结果是惊人的。下面,我们来看一个来自 Tensor2Tensor 笔记本的图形示例。它包含一个动画,显示了 8 个注意力头在 6 个编码器层中的每一层中观察的位置。下图显示了对单词“it”进行编码时,第 5 层中的两个注意头。显然,“它”根据橙色的注意头指的是“动物”,根据绿色的更多的是指“累”。因此,“它”的模型表征包括“动物”和“疲倦”的表征。
编码
Transformer 的编码部分做了额外的神奇的事情,我们在这里只做介绍。
位置信息
学习每个单词的位置或单词之间的距离可以提高翻译质量,特别是对于像德语这样的语言,动词经常出现在句子的末尾。Transformer 生成并学习一个特殊的位置向量,该向量在输入到第一个编码器层之前被添加到输入嵌入中。
残差
在每个编码器内,自关注层输出的 Z 经过使用输入嵌入的 层归一化 (添加位置向量后)。它具有与批量规范化类似的效果,并且减少了训练和推理时间。
堆叠编码器
来自层标准化的 Z 输出被馈入前馈层,每个字一个。最后,通过层标准化收集来自前馈层的结果,以产生下一个编码器层的输入表示。这一过程发生在 6 个编码器层的每一层中。变压器的原始完整架构如下所示。
解码
在最后一个编码器层产生了 K 和 V 矩阵之后,解码器可以启动。每个解码器都有一个编码器-解码器关注层,用于关注源语言输入序列中的适当位置。编码器-解码器关注层使用来自前一解码器层的查询 Q ,以及来自最后一个编码器层的输出的存储键 K 和值 V 。在第一个解码时间步骤中,在我们的示例中,解码器产生第一个目标单词“I”,作为法语中“je”的翻译。在第二步中,“I”被用作第一解码器层的输入,以及来自编码器的 K,V,以预测第二目标字“am”。在第三解码步骤中,“我是”被用作预测“a”的输入。第四步,用“我是 a”来预测“学生”。最后用“我是学生”来预测“<句尾>”。
下面你可以看到一个由 Jay Alammar 创作的精彩动画。他的博客以一种非常有创意和简单的方式解释了 Transformer。写这篇文章时,它启发了我们。检查一下!
结论
通过对输入进行加权平均来专注于输入的显著部分的简单想法已被证明是 DeepMind AlphaStar 成功的关键因素,该模型击败了顶级职业星际争霸玩家。AlphaStar 的行为是由基于 Transformer 的模型生成的,该模型从原始游戏界面接收输入数据(单位及其属性的列表)。该模型输出一系列指令,这些指令构成游戏中的一个动作。
在这篇文章中,我们委婉地解释了变压器如何工作,以及为什么它已经成功地用于序列转导任务。在下一篇文章中,我们将把这种方法应用到处理意图分类的自然语言理解任务中。
变压器 DIY 实用指南。经过实践验证的 PyTorch 代码,用于对 BERT 进行微调的意图分类。
towardsdatascience.com](/bert-for-dummies-step-by-step-tutorial-fb90890ffe03)*
为数据科学导入 JSON 文件
用 Python 操作 JSON 文件的方法
Photo by Lorenzo Herrera on Unsplash
最近看了一篇的博文,关于 2019 年数据科学家的重要工具。其中一个工具是 JSON……很多 JSON。
在我学习的早期,我在 kaggle 上偶然发现了基于处方的预测数据集。太完美了。作为一名药学背景的学生,我想探索药物数据。只有一个问题…
数据在 JSON 里…
JSON 或 JavaScript Object Notation 是一种“轻量级的数据交换格式…机器很容易解析和生成。”
他们说“对人类来说读和写很容易”。但是,当我第一次将 JSON 文件加载到 dataframe 中时,我会有不同的看法。
在这里,我们将探索一些在数据科学工作流的数据清理和预处理步骤中有用的方法,并希望让您相信 JSON 确实易于人类读写。
入门指南
我们可以使用%%bash
magic 打印我们的文件样本:
%%bash
head ../input/roam_prescription_based_prediction.jsonl{
"cms_prescription_counts": {
"CEPHALEXIN": 23,
"AMOXICILLIN": 52,
"HYDROCODONE-ACETAMINOPHEN": 28},
"provider_variables": {
"settlement_type": "non-urban",
"generic_rx_count": 103,
"specialty": "General Practice",
"years_practicing": 7,
"gender": "M",
"region": "South",
"brand_name_rx_count": 0},
"npi": "1992715205"}
从这里我们可以看到 JSON 数据看起来像一个 Python 字典。那没那么可怕!
在我们的字典里很容易读懂。使用 pandas read_json 方法的 json 文件:
raw_data = pd.read_json("../input/roam_prescription_based_prediction.jsonl",
lines=True,
orient='columns')
raw_data.head()
现在唯一的问题是,我们有嵌套的列值…并且在这一点上不完全可用。让我们探索一些解包这些值的方法。
列表理解
列表理解是解开 provider_variables 列中数据的一种简单方法。
provider = pd.DataFrame([md for md in df.provider_variables])
完美!我们现在有了提供者变量的数据框架!但是我想说,如果没有某种密钥,这些数据不会给我们带来太多好处。让我们将提供商的 npi 编号添加到该数据帧中,并将 NPI 列设置为索引:
provider['npi'] = raw_data.npi
provider.set_index('npi', inplace=True)
provider.head()
JSON 正常化
Pandas 的 json_normalize 方法是展平数据的另一个选择:
from pandas.io.json import json_normalize
provider = json_normalize(data=raw_data.provider_variables)
provider.head()
方法效率
因此,我们有两个选项可以产生相同的结果。使用哪种方法更好?
我们可以使用魔法命令%timeit
来查找每个语句的执行时间:
列表理解:
729 毫秒,每循环 8.21 毫秒(平均标准时间戴夫。7 次运行,每次 1 个循环)
JSON 正常化:
每循环 4.72 秒 104 毫秒(平均标准偏差。戴夫。7 次运行,每次 1 个循环)
这里我们可以看到列表理解方法执行得更快。
结论
在本文中,我们学习了如何用 Python 操作 JSON 数据。我们学习了如何展平嵌套数据并将其转换为数据帧。
我们希望了解到 JSON 文件并没有那么糟糕!
面向数据科学家的低成本细胞生物学实验
纸显微镜、公共数据存储库和托管笔记本电脑解决方案
简介:
没有昂贵的实验室设备,“公民科学家”能做真正的科学吗?
简而言之:是的。在这篇博文中,我们指出了一种替代的低成本方法来解决生物学问题,这种方法适合有抱负的业余科学家。具体来说,我们强调将低成本成像设备(折叠显微镜)和公共图像数据 (Kaggle 数据集)与用于执行计算数据分析的免费工具( Kaggle 内核)相结合的好处。此外,我们提供了一个通用框架,使用这些工具来解决生物科学中的图像分类问题。我们希望这些指导方针鼓励更多的数据科学家发表细胞生物学数据集,并分享他们所学到的东西。
第一部分:获取图像数据
高通量和超分辨率显微镜方法对细胞生物学的研究非常有价值[1,2],但这些技术对许多或大多数研究实验室来说过于昂贵。然而,好消息是像 FoldScope 显微镜这样的创新技术可以显著降低研究成本【3】。 FoldScope 显微镜实际上是纸显微镜,由一个纸框架和一个高倍物镜组成(图 1)。这些多功能显微镜已被证明能够对传染性病原体进行成像,如恶性疟原虫和埃及血吸虫,并且可以连接到手机的摄像头上。FoldScope 显微镜目前的零售价仅为每台 1.5 美元,其低廉的价格激发了一个活跃的公民科学家社区。
在这项工作中,我们使用 FoldScope 显微镜获取了新的细胞图像。我们选择从由卡罗莱纳生物供应公司出售的商业制备的载玻片开始,其中包含正在分裂的蛔虫细胞和苏木精染色。使用配备有 500 倍放大镜头和 800 万像素数码相机(iPhone 5)的 FoldScope 显微镜获取图像。通过这种方式,我们用最少的投资生成了一个细胞分裂不同阶段的细胞图像数据集。
第二部分:共享图像数据
使用 FoldScope 显微镜采集 90 张苏木精染色的蛔虫子宫中分裂细胞的图像(图 2)。这些图像作为一个公共数据集在 Kaggle 上共享,同时还有一些起始代码演示如何处理这些数据。只有 90 个图像的数据集不可避免地受到限制,并且不会对计算环境提出合适的挑战。因此,我们确定了一个相对较大的 Jurkat 细胞在不同细胞分裂阶段的标记图像数据集[5],并将其添加到我们的 Kaggle 数据集。有了这个大约 32,000 个细胞图像的补充数据集,我们可以充分测试免费的 Kaggle 内核产品执行复杂计算分析的能力。
第三部分:分析图像数据
深度学习算法令人兴奋,部分是因为它们有可能自动化生物医学研究任务[6,7]。例如,深度学习算法可用于自动化耗时的手动计数乳腺组织病理学图像中的有丝分裂结构的过程[8,9]。细胞分裂速率的差异和细胞分裂每个阶段所用时间的差异都是健康细胞和癌细胞之间的重要区别[10,11]。同样,癌细胞在细胞分裂过程中经常形成错误的有丝分裂结构,这些错误的结构会导致疾病进一步发展[12,13]。因此,对细胞分裂及其机制的研究导致了许多抗癌药物的开发[14,15]。在这项工作中,我们使用图 2 中的细胞分裂数据集来训练一个深度学习模型,该模型可用于识别分裂细胞图像中的细胞周期阶段(图 3)。
这里我们提出了一种简单的方法,将 Kaggle 内核与图 2 中的细胞分裂数据集相结合,以训练一个深度神经网络来识别细胞周期阶段。免费的 Kaggle 内核将数据、代码和基于云的计算环境结合在一起,使得工作易于复制。事实上,你可以复制这项工作,你可以在一个相同的基于云的计算环境中运行它,只需按下 Kaggle 网站上的“Fork Kernel”按钮。(关于研究再现性的其他讨论和一套推荐指南可在这里找到)。通过使用 32,266 幅图像的数据集来训练深度神经网络,我们希望我们已经展示了免费的 Kaggle 内核环境可以执行与生物医学科学相关的复杂计算分析。
在这种新方法下训练的 ML 模型给出了与原始分析相当的结果(图 4)。有趣的是,这两个模型在识别一些更少观察到的细胞周期阶段方面仍有改进的空间,但这可能通过产生额外的数据来纠正。图 4B 中的代码是通用的,应该可以很好地处理不同的图像类型和图像类别:T2 fastai。imagedata bunch . from _ folder()函数可用于加载和处理任何兼容的图像, fastai.create_cnn() 函数可用于自动学习新的模型特征。
*# Code to generate Figure 4A:* [https://github.com/theislab/deepflow](https://github.com/theislab/deepflow) *# Code to generate Figure 4B: (below)*from fastai import *
from fastai.vision import *
from fastai.callbacks.hooks import *
import numpy as np; import pandas as pd
import matplotlib; import matplotlib.pyplot as pltimg_dir='../input/'; path=Path(img_dir)
data=ImageDataBunch.from_folder(path, train=".",valid_pct=0.3, ds_tfms=get_transforms(do_flip=True,flip_vert=True,max_rotate=90,max_lighting=0.3),size=224,bs=64,num_workers=0).normalize(imagenet_stats)learn=create_cnn(data, models.resnet34, metrics=accuracy, model_dir="/tmp/model/")
learn.fit_one_cycle(10)
interp=ClassificationInterpretation.from_learner(learn)
interp.plot_confusion_matrix(figsize=(10,10), dpi=60)
这项工作描述了一个可重用的框架,可以应用于细胞生物学数据集,以解决图像分类问题。讨论的具体图像分类问题是细胞分裂期间细胞周期阶段的自动识别,该方法值得注意是因为设备的低成本以及训练模型的容易程度(使用免费云计算和开源 ML 算法)。想要训练自己的图像分类模型的数据科学家和细胞生物学家可以通过创建自己的 FoldScope 图像的数据集,将训练数据组织到与每个图像标签对应的文件夹中,然后将相同的数据集附加到包含图 4 中描述的 Fastai 代码的内核来轻松复制这种方法。我们希望未来的研究人员利用我们共享的数据集和起始代码,以便快速派生、修改和改进我们的模型。
结论:
自 17 世纪第一台复合显微镜问世以来,医疗成像和实验室设备的生产和拥有成本一直很高。分析软件要新得多,但在许多情况下同样昂贵。最近,像 1.50 美元的 FoldScope 显微镜和 0.00 美元的 Kaggle 内核这样的低成本工具已经被开发出来,它们可以以很少的成本执行许多相同的功能。这项工作描述了一个低成本和可重用的框架,可以应用于细胞生物学数据集,以解决图像分类问题。我们希望这些指南将鼓励更多的数据科学家探索和发布细胞生物学数据集,并分享他们的结果和发现。
作品引用:
[1] Miller MA,Weissleder R. 单细胞中抗癌药物作用的成像。自然评论癌症。2017.第 17 卷(7):第 399-414 页。
[2]刘 TL,Upadhyayula S,米尔基,等。观察细胞的自然状态:多细胞生物的亚细胞动力学成像。科学。2018 第 360 卷(6386)。
[3] Cybulski J,Clements J,Prakash M. Foldscope:基于折纸术的纸显微镜。 PLoS One 。2014;第九卷第六期。
[4]伊弗雷姆·R、杜阿赫·E 等在加纳使用安装在移动电话上的折叠镜和反镜细胞镜诊断埃及血吸虫感染。T21 医院。2015.第 92 卷第 6 期:第 1253-1256 页。
[5] Eulenberg P,Kö hler N,等利用深度学习重建细胞周期和疾病进展。自然通讯 。2017.第八卷第一期:第 463 页。
[6] Esteva A,Robicquet A,等医疗保健领域深度学习指南。自然医学。2019.第 25 卷:第 24-29 页。
[7]托普,埃里克 J. 高性能医学:人类与人工智能的融合。自然医学。2019.第一卷:第 44-56 页。
[8]李 C,王 X,刘 W,拉泰基 LJ。深度有丝分裂:通过深度检测、验证和分割网络进行有丝分裂检测。医学图像分析。2018.第 45 卷:
[9] Saha M,Chakraborty C,Racoceanu D. 使用乳腺组织病理学图像进行有丝分裂检测的高效深度学习模型。计算医学成像与图形学。2018.第 64 卷:第 29-40 页。
[10]谢尔·希杰。癌细胞周期。科学。1996.第 274 卷(5293):p 1672–7。
[11]维斯康帝 R,莫尼卡路,格列科 D. 癌症中的细胞周期检查点:一把治疗靶向的双刃剑。2016 年临床癌症研究杂志。第 35 卷:153 页。
[12]米卢诺维奇-耶夫蒂奇、穆尼·P .、等人。中心体聚集导致染色体不稳定和癌症。当前生物技术观点。2016 年第 40 卷:p113–118。
[13]巴克豪姆·SF,坎特利·LC。染色体不稳定性在癌症及其微环境中的多方面作用 t. 细胞。2018 卷 174(6):p 1347–1360。
[14]弗洛里安·S·米切尔森抗微管药物。分子生物学方法。 2016 第 1413 卷:p403–411。
[15]斯坦梅茨·莫,普罗塔·艾。微管靶向剂:劫持细胞骨架的策略。细胞生物学趋势。 2018 年第 28 卷第 10 期:p776–792。
[16]图 3A 中的图 3A 中的、图 3B 中的以及封面照片中的的图片来源可以在各自的超链接中找到。
标志的低秩近似
这个世界充满了低秩矩阵,我们可以对它们进行低秩近似。
这篇文章的灵感来自亚历克斯·汤森关于快速递减奇异值的精彩演讲,可以在这里找到。
Photo by Farzad Mohsenvand on Unsplash
在讲座中,汤森教授用不同国家的国旗作为低秩矩阵的例子。然而,没有关于低秩矩阵在多大程度上逼近原始标志的直观图示。
对于我们的分析,我们将从快速复习低秩近似的含义开始,然后将进行标志的实际分析。
下面的分析我就用 R。近似的基本思想就是分解。我们把它分成小块,然后重新组装,但不包括小块。
假设我们有一个矩阵 A ,分解矩阵的一个常用方法是使用所谓的奇异值分解。幸运的是,R 基为我们提供了这个函数。
A = matrix(c(4,7,-1,8,-5,-2,4,2,-1,3,-3,6), nrow = 4)
矩阵看起来会像这样:
[,1] [,2] [,3]
[1,] 4 -5 -1
[2,] 7 -2 3
[3,] -1 4 -3
[4,] 8 2 6
以下代码显示了奇异值分解的作用,即任何矩阵都可以写成一个正交矩阵、一个对角矩阵和另一个正交矩阵的乘积。
A.svd <- svd(A) # decompose A and save result to A.svdA.svd$u %*% diag(A.svd$d) %*% t(A.svd$v) #this line will reproduce A
需要注意的一点是,上述关系可以改写为秩 1 矩阵的和。这构成了低秩近似的基础,我们将用 flags 来进一步研究它。下面的代码显示,我们可以用三个秩为 1 的矩阵的和来恢复矩阵。
# for cleaner code, extract three components
u <- A.svd$u
v <- A.svd$v
d <- A.svd$dA.restored <- d[1]*u[, 1] %*% t(v[, 1]) +
d[2]*u[, 2] %*% t(v[, 2]) +
d[3]*u[, 3] %*% t(v[, 3])all.equal(A.restored, A) # proof that the we restore the matrix
#> TRUE
现在,我们准备处理旗帜。我们接下来要做的与上面非常相似,除了我们将只保留几个组件。我们可以这样做的原因是,标志的秩正好高,但数值低,这意味着奇异值急剧下降(还记得上面提到的讲座标题吗?).
我将使用下面的包进行分析(如果您想重现结果,只需保存我在这里使用的标志,但我猜任何标志都可以)。
library(imager)
library(purrr)
# library(ggplot2) --- for one plot only, omissible
有相当多的旗帜,显然是像法国的低排名。所以让我们从更有趣的东西开始:英国国旗。我找到的旗子是这样的:
为了简单一点,我将使用这些标志的灰度版本。下面的代码显示了图像的加载和展平。
brsh <- load.image("./british-flag.jpg") #brsh denote Britishgry.brsh <- as.array(brsh)[,,1,] %>% apply(1:2, mean)
gry.brsh %>% as.cimg() %>% plot
接下来,我们将 SVD 应用于标志矩阵。我们也可以画出奇异值,以显示它们下降的速度。
brsh.svd <- svd(gry.brsh)ggplot2::quickplot(brsh.svd$d, ylab = "")
为了便于我们的分析,我们可以定义两个函数:一个用于组件提取,一个用于快速绘制那些恢复的标志(我在这里使用了‘purrr’包,如果需要,可以随意查看这里的文档进行刷新)。
# extract first n component
first_n_comp <- function(n, .svd){
u <- .svd$u
d <- .svd$d
v <- .svd$v
c(1:n) %>% map( ~ d[.]*u[, .] %*% t(v[, .])) %>% reduce(`+`)
}# draw plot with only 1, 3, 5, 10 components respectivelydraw_stepwise <- function(.svd) {
par(mfrow = c(2,2)) # set 2 x 2 layout
walk(c(1,3,5,10), ~ first_n_comp(., .svd) %>% as.cimg() %>% plot)
}
现在,让我们把这些应用到英国的国旗上。从下面我们可以看到,水平和垂直模式最容易恢复,而对角线模式最难恢复。
draw_stepwise(brsh.svd)
接下来,我们来看看日本的国旗。下面是原文(确实有背景)。
这是复原的照片:
最后但同样重要的是,让我们以美国的旗帜来结束这次分析。这是我发现的一个。
这些是我找到的:
今天就到这里,下次见。
用于异常检测的 LSTM 自动编码器
使用 Python、Keras 和 TensorFlow 创建 AI 深度学习异常检测模型
Photo by Ellen Qin on Unsplash
这篇文章的目标是通过使用 Python,Keras 和 TensorFlow 创建和训练用于异常检测的人工智能深度学习神经网络的步骤。我不会过多地钻研底层理论,并假设读者对底层技术有一些基本的了解。不过,我会提供更多详细信息的链接,你可以在我的 GitHub repo 中找到这项研究的源代码。
分析数据集
我们将使用 NASA 声学和振动数据库中的振动传感器读数作为本次研究的数据集。在美国宇航局的研究中,传感器读数取自四个轴承,这些轴承在持续多天的恒定负载下发生故障。我们的数据集由单个文件组成,这些文件是以 10 分钟为间隔记录的 1 秒振动信号快照。每个文件包含每个方位的 20,480 个传感器数据点,这些数据点是通过以 20 kHz 的采样率读取方位传感器而获得的。
你可以在这里下载传感器数据。由于 GitHub 大小的限制,方位传感器数据被分成两个 zip 文件(Bearing_Sensor_Data_pt1 和 2)。您需要解压缩它们,并将它们合并到一个单独的数据目录中。
异常检测
异常检测的任务是确定什么时候某些东西偏离了“正常”。使用神经网络的异常检测以无监督/自监督的方式建模;与监督学习相反,在监督学习中,输入特征样本与其对应的输出标签之间存在一对一的对应关系。假设正常行为以及可用“正常”数据的数量是正常的,异常是正常的例外,在这种情况下,“正常”建模是可能的。
我们将使用自动编码器深度学习神经网络模型来从传感器读数中识别振动异常。目标是在未来轴承故障发生之前预测它们。
LSTM 网络公司
这项研究的概念部分来自 Vegard Flovik 博士的一篇优秀文章“异常检测和条件监控的机器学习”。在那篇文章中,作者在自动编码器模型中使用了密集的神经网络单元。这里,我们将在我们的自动编码器模型中使用长短期记忆(LSTM)神经网络细胞。LSTM 网络是更一般的递归神经网络(RNN)的子类型。递归神经网络的一个关键属性是它们保持信息或细胞状态的能力,以供以后在网络中使用。这使得它们特别适合于分析随时间演变的时态数据。LSTM 网络用于语音识别、文本翻译等任务,在这里,用于异常检测的顺序传感器读数的分析。
有许多优秀的文章,作者远比我更有资格讨论 LSTM 社交网络的细节。所以如果你好奇,这里有一个链接,链接到 LSTM 网络上的一篇优秀的文章。这里也是所有 LSTM 事物的事实上的地方——安德烈·卡帕西的博客。理论讲够了,让我们继续写代码吧…
加载、预处理和检查数据
我将使用 Anaconda 发行版 Python 3 Jupyter 笔记本来创建和训练我们的神经网络模型。我们将使用 TensorFlow 作为我们的后端,Keras 作为我们的核心模型开发库。第一项任务是加载我们的 Python 库。然后,我们设置我们的随机种子,以创造可重复的结果。
假设轴承中的机械退化随着时间逐渐发生;因此,我们将在分析中每 10 分钟使用一个数据点。通过使用 20,480 个数据点上振动记录的平均绝对值,汇总每 10 分钟的数据文件传感器读数。然后我们把所有的东西合并成一个熊猫数据帧。
接下来,我们定义用于训练和测试神经网络的数据集。为此,我们执行一个简单的分割,在数据集的第一部分进行训练,这代表正常的操作条件。然后,我们测试数据集的剩余部分,该部分包含导致轴承故障的传感器读数。
现在,我们已经加载、聚合和定义了我们的训练和测试数据,让我们回顾一下传感器数据随时间变化的趋势模式。首先,我们绘制代表轴承正常运行条件的训练集传感器读数。
接下来,我们来看看测试数据集传感器读数随时间的变化。
在测试集时间框架的中途,传感器模式开始改变。在故障点附近,轴承振动读数变得更强,并剧烈振荡。为了获得稍微不同的数据视角,我们将使用傅立叶变换将信号从时域变换到频域。
我们先来看频域的训练数据。
正常运行的传感器读数没有什么值得注意的。现在,让我们看看导致轴承故障的传感器频率读数。
我们可以清楚地看到,系统中频率振幅和能量的增加导致了轴承故障。
为了完成我们数据的预处理,我们将首先把它归一化到 0 和 1 之间的范围。然后,我们将数据改造成适合输入 LSTM 网络的格式。LSTM 单元期望一个形式为[数据样本,时间步长,特征]的三维张量。这里,输入到 LSTM 网络的每个样本代表一个时间步长,并包含 4 个特征-在该时间步长的四个方位的传感器读数。
使用 LSTM 像元的优势之一是能够在分析中包含多元特征。这里是每个时间步的四个传感器读数。但是,在在线欺诈异常检测分析中,可能是时间、金额、购买的商品、每个时间步长的互联网 IP 等特征。
神经网络模型
我们将为我们的异常检测模型使用自动编码器神经网络架构。自动编码器架构本质上学习“身份”功能。它将获取输入数据,创建该数据的核心/主要驱动特征的压缩表示,然后再次学习重构它。例如,输入一张狗的图像,它会将数据压缩到构成狗图像的核心成分,然后学习从数据的压缩版本中重建原始图像。
使用这种架构进行异常检测的基本原理是,我们根据“正常”数据训练模型,并确定产生的重建误差。然后,当模型遇到超出正常范围的数据并试图重建它时,我们将看到重建错误的增加,因为模型从未被训练为准确地重建超出正常范围的项目。
我们使用 Keras 库创建我们的自动编码器神经网络模型作为 Python 函数。
在 LSTM 自动编码器网络结构中,第一对神经网络层创建输入数据的压缩表示,即编码器。然后,我们使用一个重复矢量层来跨解码器的时间步长分布压缩的表示矢量。解码器的最终输出层为我们提供重建的输入数据。
然后,我们实例化该模型,并使用 Adam 作为我们的神经网络优化器来编译它,并平均绝对误差来计算我们的损失函数。
最后,我们将模型拟合到我们的训练数据,并对其进行 100 个时期的训练。然后,我们绘制训练损失图来评估我们的模型的性能。
损失分布
通过绘制训练集中计算损失的分布,我们可以确定用于识别异常的合适阈值。在这样做时,可以确保该阈值被设置在“噪声水平”之上,从而不会触发假阳性。
基于上述损失分布,让我们尝试使用阈值 0.275 来标记异常。然后,我们计算训练集和测试集中的重建损失,以确定传感器读数何时超过异常阈值。
请注意,我们已经将所有内容合并到一个数据帧中,以可视化随时间变化的结果。红线表示我们的阈值 0.275。
我们的神经网络异常分析能够通过检测传感器读数何时开始偏离正常运行值,在实际的物理轴承故障之前很好地标记即将发生的轴承故障。
最后,我们以 h5 格式保存神经网络模型架构及其学习到的权重。经过训练的模型可以用于异常检测。
更新:
在下一篇文章中,我们将使用 Docker 和 Kubernetes 将我们训练过的 AI 模型部署为 REST API,以将其公开为服务。
喀拉斯极端罕见事件分类的 LSTM 自动编码器
在这里,我们将学习 LSTM 模型的数据准备的细节,并为罕见事件分类建立一个 LSTM 自动编码器。
<
这篇文章是我上一篇文章使用自动编码器进行极端罕见事件分类的延续。在上一篇文章中,我们谈到了一个极其罕见的事件数据中的挑战,这些数据中只有不到 1%的数据被正面标记。我们使用异常检测的概念为此类流程构建了一个自动编码器分类器。
但是,我们掌握的数据是一个时间序列。但是之前我们使用了密集层自动编码器,它不使用数据中的时间特征。因此,在这篇文章中,我们将通过构建一个 LSTM 自动编码器来改进我们的方法。
在这里,我们将学习:
- LSTM 模型的数据准备步骤,
- 构建和实现 LSTM 自动编码器,以及
- 使用 LSTM 自动编码器进行罕见事件分类。
快速回顾 LSTM :
- LSTM 是一种递归神经网络(RNN)。一般来说,RNNs,特别是 LSTM,用于序列或时间序列数据。
- 这些模型能够自动提取过去事件的影响。
- 众所周知,LSTM 有能力提取过去事件长期和短期影响。
下面,我们将直接开发一个 LSTM 自动编码器。建议阅读逐步理解 LSTM 自动编码器层以更好地理解和进一步改进下面的网络。
简而言之,关于数据问题,我们有来自造纸厂的纸张断裂的真实数据。我们的目标是提前预测中断。有关数据、问题和分类方法的详细信息,请参考使用自动编码器的极端罕见事件分类。
多元数据的 LSTM 自动编码器
Figure 1. An LSTM Autoencoder.
在我们的问题中,我们有一个多元时间序列数据。多元时间序列数据包含在一段时间内观察到的多个变量。我们将在这个多元时间序列上建立一个 LSTM 自动编码器来执行稀有事件分类。如[ 1 中所述,这是通过使用异常检测方法实现的:
- 我们在正常(负标签)数据上建立一个自动编码器,
- 用它来重建一个新样本,
- 如果重建误差很高,我们将其标记为断纸。
LSTM 几乎不需要特殊的数据预处理步骤。在下文中,我们将对这些步骤给予足够的重视。
让我们开始实现。
图书馆
我喜欢先把库和全局常量放在一起。
%matplotlib inline
**import** **matplotlib.pyplot** **as** **plt**
**import** **seaborn** **as** **sns**
**import** **pandas** **as** **pd**
**import** **numpy** **as** **np**
**from** **pylab** **import** rcParams
**import** **tensorflow** **as** **tf**
**from** **keras** **import** optimizers, Sequential
**from** **keras.models** **import** Model
**from** **keras.utils** **import** plot_model
**from** **keras.layers** **import** Dense, LSTM, RepeatVector, TimeDistributed
**from** **keras.callbacks** **import** ModelCheckpoint, TensorBoard
**from** **sklearn.preprocessing** **import** StandardScaler
**from** **sklearn.model_selection** **import** train_test_split
**from** **sklearn.metrics** **import** confusion_matrix, precision_recall_curve
**from** **sklearn.metrics** **import** recall_score, classification_report, auc, roc_curve
**from** **sklearn.metrics** **import** precision_recall_fscore_support, f1_score
**from** **numpy.random** **import** seed
seed(7)
**from** **tensorflow** **import** set_random_seed
set_random_seed(11)**from** **sklearn.model_selection** **import** train_test_split
SEED = 123 *#used to help randomly select the data points*
DATA_SPLIT_PCT = 0.2
rcParams['figure.figsize'] = 8, 6
LABELS = ["Normal","Break"]
数据准备
如前所述,LSTM 要求在数据准备中采取一些具体步骤。LSTMs 的输入是从时间序列数据创建的三维数组。这是一个容易出错的步骤,所以我们将查看细节。
读出数据
df = pd.read_csv("data/processminer-rare-event-mts - data.csv")
df.head(n=5) *# visualize the data.*
曲线移动
正如在[ 1 中提到的,这个罕见事件问题的目标是在板块断裂发生之前预测它。我们将尝试提前 4 分钟预测到的休息时间。对于这些数据,这相当于将标签上移两行。直接用df.y=df.y.shift(-2)
就可以了。然而,在这里我们需要做以下事情:
- 对于标签为 1 的任意一行 n ,使( n -2)😦 n -1)为 1。这样,我们就可以教会分类器预测到 4 分钟前的情况。而且,
- 拆下排 n 。行 n 被删除,因为我们对训练分类器预测已经发生的中断不感兴趣。
我们开发了以下函数来执行这种曲线移动。
sign = **lambda** x: (1, -1)[x < 0]
**def** curve_shift(df, shift_by):
*'''*
*This function will shift the binary labels in a dataframe.*
*The curve shift will be with respect to the 1s.*
*For example, if shift is -2, the following process*
*will happen: if row n is labeled as 1, then*
*- Make row (n+shift_by):(n+shift_by-1) = 1.*
*- Remove row n.*
*i.e. the labels will be shifted up to 2 rows up.*
*Inputs:*
*df A pandas dataframe with a binary labeled column.*
*This labeled column should be named as 'y'.*
*shift_by An integer denoting the number of rows to shift.*
*Output*
*df A dataframe with the binary labels shifted by shift.*
*'''*
vector = df['y'].copy()
**for** s **in** range(abs(shift_by)):
tmp = vector.shift(sign(shift_by))
tmp = tmp.fillna(0)
vector += tmp
labelcol = 'y'
*# Add vector to the df*
df.insert(loc=0, column=labelcol+'tmp', value=vector)
*# Remove the rows with labelcol == 1.*
df = df.drop(df[df[labelcol] == 1].index)
*# Drop labelcol and rename the tmp col as labelcol*
df = df.drop(labelcol, axis=1)
df = df.rename(columns={labelcol+'tmp': labelcol})
*# Make the labelcol binary*
df.loc[df[labelcol] > 0, labelcol] = 1
**return** df
我们现在将转换我们的数据,并验证转换是否正确。在接下来的部分中,我们还有一些测试步骤。建议使用它们来确保数据准备步骤按预期运行。
print('Before shifting') *# Positive labeled rows before shifting.*
one_indexes = df.index[df['y'] == 1]
display(df.iloc[(np.where(np.array(input_y) == 1)[0][0]-5):(np.where(np.array(input_y) == 1)[0][0]+1), ])
*# Shift the response column y by 2 rows to do a 4-min ahead prediction.*
df = curve_shift(df, shift_by = -2)
print('After shifting') *# Validating if the shift happened correctly.*
display(df.iloc[(one_indexes[0]-4):(one_indexes[0]+1), 0:5].head(n=5))
如果我们在这里注意到,我们将 1999 年 5 月 1 日 8:38 的正标签移动到了 n -1 和 n -2 时间戳,并删除了第 n 行。此外,在中断行和下一行之间有超过 2 分钟的时间差。这是因为,当发生中断时,机器会在中断状态停留一段时间。在此期间,连续行的 y = 1。在所提供的数据中,这些连续的中断行被删除,以防止分类器学习预测已经发生的之后的中断。详见[ 2 。
在继续之前,我们通过删除时间和另外两个分类列来清理数据。
*# Remove time column, and the categorical columns*
df = df.drop(['time', 'x28', 'x61'], axis=1)
为 LSTM 准备输入数据
LSTM 比其他车型要求更高一些。在准备适合 LSTM 的数据时可能会花费大量的时间和精力。然而,这通常是值得努力的。
LSTM 模型的输入数据是一个三维数组。数组的形状是样本 x 回看 x 特征。让我们来理解它们,
- 样本:这就是观察的数量,或者换句话说,就是数据点的数量。
- 回顾过去:LSTM 模特是用来回顾过去的。也就是说,在时间 t 时,LSTM 将处理数据直到( t - 回看)以做出预测。
- 特征:输入数据中出现的特征数量。
首先,我们将提取特征和响应。
input_X = df.loc[:, df.columns != 'y'].values *# converts the df to a numpy array*
input_y = df['y'].values
n_features = input_X.shape[1] *# number of features*
这里的input_X
是一个大小为样本 x 特征的二维数组。我们希望能够将这样的 2D 数组转换成大小为:样本 x 回看 x 特征的 3D 数组。请参考上面的图 1 以获得直观的理解。
为此,我们开发了一个函数temporalize
。
**def** temporalize(X, y, lookback):
*'''*
*Inputs*
*X A 2D numpy array ordered by time of shape:*
*(n_observations x n_features)*
*y A 1D numpy array with indexes aligned with*
*X, i.e. y[i] should correspond to X[i].*
*Shape: n_observations.*
*lookback The window size to look back in the past*
*records. Shape: a scalar.*
*Output*
*output_X A 3D numpy array of shape:*
*((n_observations-lookback-1) x lookback x*
*n_features)*
*output_y A 1D array of shape:*
*(n_observations-lookback-1), aligned with X.*
*'''*
output_X = []
output_y = []
**for** i **in** range(len(X) - lookback - 1):
t = []
**for** j **in** range(1, lookback + 1):
*# Gather the past records upto the lookback period*
t.append(X[[(i + j + 1)], :])
output_X.append(t)
output_y.append(y[i + lookback + 1])
**return** np.squeeze(np.array(output_X)), np.array(output_y)
为了测试和演示这个功能,我们将在下面用lookback = 5
看一个例子。
print('First instance of y = 1 in the original data')
display(df.iloc[(np.where(np.array(input_y) == 1)[0][0]-5):(np.where(np.array(input_y) == 1)[0][0]+1), ])lookback = 5 # Equivalent to 10 min of past data.
# Temporalize the data
X, y = temporalize(X = input_X, y = input_y, lookback = lookback)print('For the same instance of y = 1, we are keeping past 5 samples in the 3D predictor array, X.')
display(pd.DataFrame(np.concatenate(X[np.where(np.array(y) == 1)[0][0]], axis=0 )))
我们在这里寻找的是,
- 在原始数据中,第 257 行的 y = 1。
- 使用
lookback = 5
,我们希望 LSTM 查看 257 行之前的 5 行(包括它自己)。 - 在 3D 阵列
X
中,X[i,:,:]
处的每个 2D 块表示对应于y[i]
的预测数据。打个比方,在回归中y[i]
对应一个 1D 向量X[i,:]
;在 LSTMy[i]
对应一个 2D 阵列X[i,:,:]
。 - 这个 2D 块
X[i,:,:]
应该具有在input_X[i,:]
和直到给定lookback
的先前行的预测器。 - 正如我们在上面的输出中看到的,底部的
X[i,:,:]
块与顶部显示的 y=1 的过去五行相同。 - 类似地,这适用于所有 y 的全部数据。此处的示例显示了 y=1 的情况,以便于可视化。
分为训练、有效和测试
这对于sklearn
功能来说很简单。
X_train, X_test, y_train, y_test = train_test_split(np.array(X), np.array(y), test_size=DATA_SPLIT_PCT, random_state=SEED)X_train, X_valid, y_train, y_valid = train_test_split(X_train, y_train, test_size=DATA_SPLIT_PCT, random_state=SEED)
为了训练自动编码器,我们将使用仅来自负标签数据的 X。所以我们把 y = 0 对应的 X 分开。
X_train_y0 = X_train[y_train==0]
X_train_y1 = X_train[y_train==1]X_valid_y0 = X_valid[y_valid==0]
X_valid_y1 = X_valid[y_valid==1]
我们将把 X 的形状重塑成所需的 3D 尺寸:样本 x 回看 x 特征。
X_train = X_train.reshape(X_train.shape[0], lookback, n_features)
X_train_y0 = X_train_y0.reshape(X_train_y0.shape[0], lookback, n_features)
X_train_y1 = X_train_y1.reshape(X_train_y1.shape[0], lookback, n_features)X_valid = X_valid.reshape(X_valid.shape[0], lookback, n_features)
X_valid_y0 = X_valid_y0.reshape(X_valid_y0.shape[0], lookback, n_features)
X_valid_y1 = X_valid_y1.reshape(X_valid_y1.shape[0], lookback, n_features)X_test = X_test.reshape(X_test.shape[0], lookback, n_features)
使数据标准化
对于自动编码器,通常最好使用标准化数据(转换为高斯数据,平均值为 0,标准偏差为 1)。
一个常见的标准化错误是:我们将整个数据标准化,然后分成训练测试。这是不正确的。在建模过程中,测试数据应该是完全不可见的。因此,我们应该规范化训练数据,并使用其汇总统计数据来规范化测试数据(对于规范化,这些统计数据是每个特征的平均值和方差)。
标准化这些数据有点棘手。这是因为 X 矩阵是 3D 的,我们希望标准化发生在原始 2D 数据上。
为此,我们需要两个 UDF。
flatten
:该功能将重新创建原始的 2D 阵列,3D 阵列是从该阵列创建的。这个函数是temporalize
的倒数,意思是X = flatten(temporalize(X))
。scale
:这个函数将缩放我们创建的 3D 数组,作为 LSTM 的输入。
**def** flatten(X):
*'''*
*Flatten a 3D array.*
*Input*
*X A 3D array for lstm, where the array is sample x timesteps x features.*
*Output*
*flattened_X A 2D array, sample x features.*
*'''*
flattened_X = np.empty((X.shape[0], X.shape[2])) *# sample x features array.*
**for** i **in** range(X.shape[0]):
flattened_X[i] = X[i, (X.shape[1]-1), :]
**return**(flattened_X)
**def** scale(X, scaler):
*'''*
*Scale 3D array.*
*Inputs*
*X A 3D array for lstm, where the array is sample x timesteps x features.*
*scaler A scaler object, e.g., sklearn.preprocessing.StandardScaler, sklearn.preprocessing.normalize*
*Output*
*X Scaled 3D array.*
*'''*
**for** i **in** range(X.shape[0]):
X[i, :, :] = scaler.transform(X[i, :, :])
**return** X
为什么我们不首先归一化原始 2D 数据,然后创建三维阵列?因为,为了做到这一点,我们将:把数据分成训练和测试,然后对它们进行规范化。然而,当我们在测试数据上创建 3D 阵列时,我们丢失了最初的样本行,直到回看。拆分为训练有效测试将导致验证集和测试集都出现这种情况。
我们将安装一个来自sklearn
的标准化对象。该函数将数据标准化为正态(0,1)。注意,我们需要展平X_train_y0
数组以传递给fit
函数。
*# Initialize a scaler using the training data.*
scaler = StandardScaler().fit(flatten(X_train_y0))
我们将使用我们的 UDFscale
,用合适的转换对象scaler
来标准化X_train_y0
。
X_train_y0_scaled = scale(X_train_y0, scaler)
确保 **scale**
正常工作?
X_train
的正确转换将确保展平的X_train
的每一列的均值和方差分别为 0 和 1。我们测试这个。
a = flatten(X_train_y0_scaled)
print('colwise mean', np.mean(a, axis=0).round(6))
print('colwise variance', np.var(a, axis=0))
上面输出的所有均值和方差分别为 0 和 1。因此,缩放是正确的。我们现在将扩展验证和测试集。我们将再次在这些器械包中使用scaler
对象。
X_valid_scaled = scale(X_valid, scaler)
X_valid_y0_scaled = scale(X_valid_y0, scaler)X_test_scaled = scale(X_test, scaler)
LSTM 自动编码器培训
首先,我们将初始化一些变量。
timesteps = X_train_y0_scaled.shape[1] *# equal to the lookback*
n_features = X_train_y0_scaled.shape[2] *# 59*
epochs = 200
batch = 64
lr = 0.0001
现在,我们开发一个简单的架构。
lstm_autoencoder = Sequential()
*# Encoder*
lstm_autoencoder.add(LSTM(32, activation='relu', input_shape=(timesteps, n_features), return_sequences=**True**))
lstm_autoencoder.add(LSTM(16, activation='relu', return_sequences=**False**))
lstm_autoencoder.add(RepeatVector(timesteps))
*# Decoder*
lstm_autoencoder.add(LSTM(16, activation='relu', return_sequences=**True**))
lstm_autoencoder.add(LSTM(32, activation='relu', return_sequences=**True**))
lstm_autoencoder.add(TimeDistributed(Dense(n_features)))
lstm_autoencoder.summary()
从 summary()来看,参数的总数是 5,331。这大约是训练规模的一半。因此,这是一个合适的模型。为了有一个更大的架构,我们将需要添加正规化,例如辍学,这将在下一篇文章中讨论。
现在,我们将训练自动编码器。
adam = optimizers.Adam(lr)
lstm_autoencoder.compile(loss='mse', optimizer=adam)
cp = ModelCheckpoint(filepath="lstm_autoencoder_classifier.h5",
save_best_only=**True**,
verbose=0)
tb = TensorBoard(log_dir='./logs',
histogram_freq=0,
write_graph=**True**,
write_images=**True**)
lstm_autoencoder_history = lstm_autoencoder.fit(X_train_y0_scaled, X_train_y0_scaled,
epochs=epochs,
batch_size=batch,
validation_data=(X_valid_y0_scaled, X_valid_y0_scaled),
verbose=2).history
绘制各时期损失的变化。
plt.plot(lstm_autoencoder_history['loss'], linewidth=2, label='Train')
plt.plot(lstm_autoencoder_history['val_loss'], linewidth=2, label='Valid')
plt.legend(loc='upper right')
plt.title('Model loss')
plt.ylabel('Loss')
plt.xlabel('Epoch')
plt.show()
Figure 2. Loss function over the epochs.
分类
类似于之前的文章 [ 1 ],这里我们展示了如何使用自动编码器重建误差进行罕见事件分类。我们遵循这个概念:自动编码器被期望重建一个 noi。如果重建误差很高,我们将把它分类为一个断页。
我们需要确定这方面的门槛。另外,请注意,这里我们将使用包含 y = 0 或 1 的整个验证集。
valid_x_predictions = lstm_autoencoder.predict(X_valid_scaled)
mse = np.mean(np.power(flatten(X_valid_scaled) - flatten(valid_x_predictions), 2), axis=1)
error_df = pd.DataFrame({'Reconstruction_error': mse,
'True_class': y_valid.tolist()})
precision_rt, recall_rt, threshold_rt = precision_recall_curve(error_df.True_class, error_df.Reconstruction_error)
plt.plot(threshold_rt, precision_rt[1:], label="Precision",linewidth=5)
plt.plot(threshold_rt, recall_rt[1:], label="Recall",linewidth=5)
plt.title('Precision and recall for different threshold values')
plt.xlabel('Threshold')
plt.ylabel('Precision/Recall')
plt.legend()
plt.show()
注意,我们必须对数组进行flatten
运算来计算mse
。
Figure 3. A threshold of 0.3 should provide a reasonable trade-off between precision and recall, as we want to higher recall.
现在,我们将对测试数据进行分类。
我们不应该从测试数据中估计分类阈值。这将导致过度拟合。
test_x_predictions = lstm_autoencoder.predict(X_test_scaled)
mse = np.mean(np.power(flatten(X_test_scaled) - flatten(test_x_predictions), 2), axis=1)
error_df = pd.DataFrame({'Reconstruction_error': mse,
'True_class': y_test.tolist()})
threshold_fixed = 0.3
groups = error_df.groupby('True_class')
fig, ax = plt.subplots()
**for** name, group **in** groups:
ax.plot(group.index, group.Reconstruction_error, marker='o', ms=3.5, linestyle='',
label= "Break" **if** name == 1 **else** "Normal")
ax.hlines(threshold_fixed, ax.get_xlim()[0], ax.get_xlim()[1], colors="r", zorder=100, label='Threshold')
ax.legend()
plt.title("Reconstruction error for different classes")
plt.ylabel("Reconstruction error")
plt.xlabel("Data point index")
plt.show();
Figure 4. Using threshold = 0.8 for classification. The orange and blue dots above the threshold line represents the True Positive and False Positive, respectively.
在图 4 中,阈值线上方的橙色和蓝色圆点分别代表真阳性和假阳性。如我们所见,我们有很多误报。
让我们看看准确度的结果。
测试精度
混淆矩阵
pred_y = [1 if e > threshold_fixed else 0 for e in error_df.Reconstruction_error.values]conf_matrix = confusion_matrix(error_df.True_class, pred_y)
plt.figure(figsize=(6, 6))
sns.heatmap(conf_matrix, xticklabels=LABELS, yticklabels=LABELS, annot=**True**, fmt="d");
plt.title("Confusion matrix")
plt.ylabel('True class')
plt.xlabel('Predicted class')
plt.show()
Figure 5. Confusion matrix showing the True Positives and False Positives.
ROC 曲线和 AUC
false_pos_rate, true_pos_rate, thresholds = roc_curve(error_df.True_class, error_df.Reconstruction_error)
roc_auc = auc(false_pos_rate, true_pos_rate,)
plt.plot(false_pos_rate, true_pos_rate, linewidth=5, label='AUC = **%0.3f**'% roc_auc)
plt.plot([0,1],[0,1], linewidth=5)
plt.xlim([-0.01, 1])
plt.ylim([0, 1.01])
plt.legend(loc='lower right')
plt.title('Receiver operating characteristic curve (ROC)')
plt.ylabel('True Positive Rate')
plt.xlabel('False Positive Rate')
plt.show()
Figure 6. The ROC curve.
与[ 1 中的密集层自动编码器相比,我们看到 AUC 提高了大约 10%。根据图 5 中的混淆矩阵,我们可以预测 39 个中断实例中的 10 个。正如[ 1 中所讨论的,这对造纸厂来说意义重大。然而,与密集层自动编码器相比,我们实现的改进是微小的。
主要原因是 LSTM 模型有更多的参数需要估计。对 LSTMs 使用正则化变得很重要。正则化和其他模型改进将在下一篇文章中讨论。
Github 知识库
[## cran 2367/lstm _ 自动编码器 _ 分类器
用于罕见事件分类的 LSTM 自动编码器。通过…为 cran 2367/lstm _ auto encoder _ classifier 开发做出贡献
github.com](https://github.com/cran2367/lstm_autoencoder_classifier/blob/master/lstm_autoencoder_classifier.ipynb)
什么可以做得更好?
在下一篇文章中,我们将学习调优自动编码器。我们会过去,
- CNN LSTM 自动编码器,
- 脱落层,
- LSTM 辍学(辍学和辍学)
- 高斯漏失层
- SELU 激活,以及
- 阿尔法辍学与 SELU 激活。
结论
这篇文章继续了[ 1 ]中关于极端罕见事件二进制标记数据的工作。为了利用时间模式,LSTM 自动编码器被用来建立一个多元时间序列过程的罕见事件分类器。详细讨论了 LSTM 模型的数据预处理步骤。一个简单的 LSTM 自动编码器模型被训练并用于分类。发现密集自动编码器的精度有所提高。为了进一步改进,我们将在下一篇文章中探讨如何改进具有 Dropout 和其他技术的自动编码器。
后续阅读
建议阅读逐步理解 LSTM 自动编码器层以明确 LSTM 网络概念。
参考
- 使用 Keras 中的自动编码器进行极端罕见事件分类
- Ranjan、m . Mustonen、k . pay nabar 和 k . pour AK(2018 年)。数据集:多元时间序列中的稀有事件分类。 arXiv 预印本 arXiv:1809.10717
- 深度学习时间序列预测& LSTM 自动编码器
- 完整代码: LSTM 自动编码器
免责声明:这篇文章的范围仅限于构建 LSTM 自动编码器并将其用作罕见事件分类器的教程。通过网络调优,从业者有望获得更好的结果。这篇文章的目的是帮助数据科学家实现 LSTM 自动编码器。
非洲语言的位置标记
我们如何为耶姆巴语建立世界上第一个 LSTM 分类器。
在本文中,我们实现了一个 LSTM 网络,用于根据序列中已经观察到的字符来预测序列中下一个字符的概率。
我们从非洲语言中构建了第一个基于 LSTM 的单词分类器, Yemba 。没有边界可以阻止 LSTMs。可能是变形金刚。
耶姆巴语
我们的序列将从一种不太流行的语言中取词,叫做。你可能从未听说过这种语言。放心看下面的象形图来了解一下 Yemba 的写法。
Yemba 是一种非洲语言,如今只有几千人以此为母语。尽管最初只是一种口头语言,但耶姆巴语是在大约公元 2000 年发展起来的。 90 年前。和世界上那么多语言一样, Yemba 是声调语言,类似于越南语。
在声调语言中,单词由辅音、元音组成;音调——伴随音节发音的音高变化。
1928 年,设计第一个 Yemba 字母表的先驱,Foreke-Dschang的 Djoumessi Mathias 陛下建立了 Yemba 音调正字法的基础模型。后来,在 1997 年,作为一项联合国际研究努力的结果,一部现代的耶姆巴-法语词典诞生了。
source: Djoumessi, M. (1958) Syllabaire bamiléké,Yaoundé, Saint-Paul.
我们的目标是将 Yemba 单词编码为嵌入向量,并建立一个 LSTM 网络,该网络能够通过仅查看单词中存在的字符和音调来预测 Yemba 单词是名词还是动词。
我们的目标不是实现完整的词性标注。相反,我们将训练网络学习常见于 Yemba 名词中的字母和音调组,而不是那些特定于 Yemba 动词的字母和音调组。
为此,我们使用一个预处理过的 英语-Yemba 数据集,它是从Yemba.net在线词典下载的。我们鼓励您访问该页面,点击一些从英语、法语、德语、捷克语、汉语、西班牙语、意大利语到 Yemba 的翻译。很好玩。
上面我们可以从字典中看到一些单词。如果你想有好心情,你可以试着阅读它们。实际上, Yemba 写法是基于国际音标语言。任何有语音学知识的人实际上都能够阅读和说话!理论上。
虽然我们将数据集限制为名词和动词,但是 Yemba 还包括形容词、副词、连词、代词等。,但是与名词和动词相比数量有限。单词类型的分布如下图所示。
下面我们展示一些关于数据集的统计数据。
我们的 Yemba 单词是由 45 个字母组成的。词汇表用一个唯一的整数来表示每个 Yemba 字母。这是自然语言处理中典型的预处理步骤。
在将单词输入 LSTM 之前,我们必须对每个单词进行标记,用词汇表中的索引替换单词中的每个字母。这个过程将单词转化为数字向量 X 。为了使所有单词的向量大小相同,我们将向量填充到数据集中最长单词的长度。
我们的 LSTM 将学习将这些向量与正确的单词类型相匹配:0 代表名词,1 代表动词。因此,我们还构建了一个标签向量 Y 来存储正确的类。
接下来,我们将向量分成 2166 个单词的训练集和 542 个单词的验证集。
我们建立了一个有 100 个细胞的单层 LSTM。我们不直接向 LSTM 馈送单词向量。相反,我们首先学习它们在 8 维空间中的嵌入表示。
众所周知,嵌入是为了捕捉构成单词的字母之间的语义关系。LSTM 的输出由具有 sigmoid 激活的全连接层转换,以产生 0 和 1 之间的概率。
我们用二进制交叉熵作为损失函数,Adam 作为优化器来训练网络。分类精度被用作评估分类性能的度量,因为我们的两个类相当平衡。
**
如上图所示,网络实现收敛的速度非常快。LSTM 做得很好,在测试数据集上预测的分类准确率为 93.91%。
我们还在我们的 Yemba 分类问题上尝试了 GRUs,通过用具有相同单元数量(100)的 GRU 层替换 LSTM 层。训练稍微快了一点,准确性稍微好了一点,在验证集上达到了 94.19%,而不是 LSTM 的 93.91%。
现在让我们在 100 个随机名词和 100 个随机动词上评估经过训练的 LSTM 网络,并检查混淆矩阵。
混淆矩阵显示出很少的假阳性和假阴性:100 个动词中有 1 个被预测为名词,2 个被预测为动词。分类错误的单词如下所示。
事实是, Yemba 中的动词通常有一个引人注目的前缀“e”、“了”或“里”,这与英语中的“to”相对应。看来这个语义或语法结构被我们基于角色的 LSTM 正确地提取出来了。“eku bil”这个词在英语中是“贪婪”的意思,以“e”开头。因此,LSTM 预言它为动词,尽管它是名词。“lefɔ”也是一样,意思是“王朝”。因为它的前缀是“了”,所以被认为是动词。
结论
这个实际案例显示了 LSTMs 在掌握语义方面的魔力,即使是在词汇和语音差异都很奇怪的偏远难懂的语言中,如 Yemba 。
在后续文章中,我们实现了一个 seq2seq 神经翻译模型,将英语句子翻译成 Yemba。
AI 能让濒危语言不消失吗?
towardsdatascience.com](/heres-how-to-build-a-language-translator-in-few-lines-of-code-using-keras-30f7e0b3aa1d)*
谷歌基于 LSTM 的手写识别
人类最初是如何在我们的大脑中进行手写识别的?
Photo by Edward Ma on Unsplash
手写是自然语言处理任务中的挑战之一。这是因为它在不同的人之间是不同的。另一方面,有些字符(如英语)非常相似。作为人类的开端,我们利用语境化信息,词汇匹配。
有时,“O”可以写成“0 ”,而人类 begin 有能力从上下文信息中区分它是“O”还是“0”。例如,“0”将用于电话号码,而“O”将用作英语单词的一部分。另一项技能是词汇搜索。即使我们不能识别每一个字符,猜测单词也是有帮助的。
Handwriting in different language (Carbune et al., 2019)
我们如何通过深度学习应对时代?本故事将讨论基于 LSTM 的快速多语言在线手写识别(carburne 等人,2019 年),并将涵盖以下内容:
- 数据
- 体系结构
- 实验
数据
Carbune 等人利用开放和封闭数据集来验证模型。像往常一样, IAM-OnDB 数据集用于训练模型。在实验过程中,他们使用了两种表征,分别是Raw Touch Points
和Bézier Curves
。
原始接触点
数据将被转换为 5 维点,即 x 坐标、y 坐标、自第一次触摸以来触摸点的时间戳、提笔或落笔以及是否有新的笔画。一些预处理是必要的
- 由于图像的大小可能是不同的,x 和 y 坐标的标准化是必要的。如果书写区域未知,代理比观察到的触摸点大 20%
- 值为 0.05 时沿笔划的等距线性重采样。换句话说,长度为 1 的直线将有 20 个点。
贝塞尔曲线
作者还评价了Bézier Curves
是否优于Raw Touch Points
。从实验来看,Bézier Curves
表现出了较好的效果。Bézier Curves
是一种呈现空间轨迹的自然方式。作者发现Raw Touch Points
更有前途。作者使用Bézier curves
的三次多项式来计算特征。
Show “go” in bézier curve method (Google AI Blog)
如果你想重温一下Bézier Curves
的概念,你可以看看这个故事。计算曲线后,将生成 10 维向量并输入神经网络。它们是:
- 端点之间的向量(红点)。图中是蓝线。
- 控制点(绿点)和端点之间的距离。它们是图中的绿色虚线。
- 每个控制点和端点之间的角度。图中的绿色弧线。
- 三个时间系数(图中未显示)
- 一个布尔指示器,指示这是提笔还是落笔
Bézier curve used to feed the network (Carbune et al., 2019)
体系结构
手写挑战是一个明确定义的问题,有多种方法来处理它。分段解码分类器就是其中的一个例子。它将单词拆分为子单词,并逐个进行分类。另一种方法是使用隐马尔可夫模型(HMM)。它使用链概念来识别手写和返回字符串。
Carbune 等人使用Bézier Curves
作为特征,并输入双向 LSTM 来学习该特征,并使用 softmax 层来获得所有可能字符的概率分布。这并不是模型的结束,softmax 层生成一系列的类,Carbune 等人使用连接主义时态分类(CTC)对其进行解码并得到最终的输出。
实验
作者在 IAM-OnDb 上测量了不同模型之间的字符错误率(CER)。对 CER 来说,越低越好。你可能会注意到,较深的 LSTM 比原始接触点更好,曲线也更好。
Comparison on IAM-OnDB for different input representation and layers (Carbune et al., 2019)
Comparison among different models (Carbune et al., 2019)
CER of Bézier Curves model (Carbune et al., 2019)
拿走
- 不同于先前研究,该方法计算输入特征(即
Bézier Curves
)而不是使用 CNN 或其他神经网络来学习特征。 Bézier Curves
似乎很有道理,它可以表示输入而不丢失任何数据。
关于我
我是湾区的数据科学家。专注于数据科学、人工智能,尤其是 NLP 和平台相关领域的最新发展。欢迎在 LinkedIn 上与我联系,或者在 Medium 或 Github 上关注我。
延伸阅读
关于[Bézier Curves](https://medium.com/@Acegikmo/the-ever-so-lovely-b%C3%A9zier-curve-eb27514da3bf)
的更多信息
参考
动词 (verb 的缩写)Carbune,P. Gonnet,T. Deselaers,H. A. Rowley,A. Daryin,M . Calvo,L. L. Wang,D. Keysers,S. Feuz,P. Gervais。基于 LSTM 的快速多语言在线手写识别。2019.
时间序列预测的 LSTM
Time series prediction Photo by rawpixel.com from Pexels
使用神经网络(NN)来预测市场上的股票价格运动的想法与神经网络一样古老。凭直觉,只看过去似乎很难预测未来的价格走势。有很多关于如何预测价格走势或其威力的教程,把问题简单化了。我决定尝试用 LSTM 预测成交量加权平均价格,因为这看起来很有挑战性,也很有趣。
在这篇博客文章中,我将使用 PyTorch 对比特币交易数据训练一个长短期记忆神经网络(LSTM ),并使用它来预测未见过的交易数据的价格。我在寻找中级教程时遇到了相当大的困难,其中有一个训练 LSTM 进行时间序列预测的可重复示例,所以我整理了一个 Jupyter 笔记本来帮助你开始。
这里有几个你可能会感兴趣的链接:
- [Complete your Python analyses 10x faster with Mito](https://trymito.io/) [Product]- [Free skill tests for Data Scientists & ML Engineers](https://aigents.co/skills) [Test]- [All New Self-Driving Car Engineer Nanodegree](https://imp.i115008.net/c/2402645/1116216/11298)[Course]
你愿意多读一些这样的文章吗?如果是这样,你可以点击上面的任何链接来支持我。其中一些是附属链接,但你不需要购买任何东西。
正在加载必要的依赖项
让我们导入将要用于数据操作、可视化、模型训练等的库。我们将使用 PyTorch 库来训练 LSTM。
**%**matplotlib inlineimport glob
import matplotlib
import numpy **as** np
import pandas **as** pd
import sklearn
import torch
加载数据
我们要分析 BitMex 的 XBTUSD 交易数据。每日文件公开下载。我没有费心编写自动下载数据的代码,我只是简单地点击几次来下载文件。
让我们列出所有文件,将它们读取到一个 pandas 数据框架中,并通过 XBTUSD 符号过滤交易数据。按时间戳对数据帧进行排序很重要,因为有多个每日文件,这样它们就不会混淆。
files **=** sorted(glob**.**glob('data/*.csv.gz'))df **=** pd**.**concat(map(pd**.**read_csv, files))df **=** df[df**.**symbol **==** 'XBTUSD']df**.**timestamp **=** pd**.**to_datetime(df**.**timestamp**.**str**.**replace('D', 'T')) # covert to timestamp typedf **=** df**.**sort_values('timestamp')df**.**set_index('timestamp', inplace**=**True) # set index to timestampdf**.**head()
BitMex trade data
每行代表一种交易:
- 以微秒为单位的时间戳精度,
- 交易合约的符号,
- 交易的一方,买或卖,
- 大小代表合约数量(交易的美元数量),
- 合同价格,
- tickDirection 描述了自上次交易以来价格的上涨/下跌,
- trdMatchID 是唯一的交易 ID,
- grossValue 是交换的 satoshis 的数量,
- 家名义是交易中 XBT 的数量,
- 外币名义金额是交易中的美元金额。
我们将使用 3 列:时间戳,价格和外国名义。
数据预处理
让我们以 1 分钟的时间间隔计算成交量加权平均价格(VWAP) 。我们根据预先定义的时间间隔对交易进行分组的数据表示叫做时间棒。这是表示交易数据进行建模的最佳方式吗?根据洛佩兹·德·普拉多的说法,市场上的交易并不是随时间均匀分布的。有一些活动频繁的时段,例如在期货合约到期之前,在预定义的时间间隔内对数据进行分组会在一些时间条内对数据进行过采样,而在其他时间条内对数据进行欠采样。金融机器学习第 0 部分:条是洛佩兹·德·普拉多的书金融机器学习书籍第二章的一个很好的总结。时间条可能不是最好的数据表示,但无论如何我们都要使用它们。
df_vwap **=** df**.**groupby(pd**.**Grouper(freq**=**"1Min"))**.**apply(
**lambda** row: pd**.**np**.**sum(row**.**price ***** row**.**foreignNotional) **/** pd**.**np**.**sum(row**.**foreignNotional))
Time bars showing XBTUSD VWAP from 1st of August till the 17th of September 2019
该图显示了 2019 年 8 月 1 日至 9 月 17 日 VWAP 的时间条。我们将把数据的第一部分用于训练集,中间部分用于验证集,最后一部分用于测试集(竖线是分隔符)。我们可以观察 VWAP 的波动性,那里的价格在 8 月上旬达到最高点,在 8 月底达到最低点。高点和低点在训练集中被捕获,这很重要,因为模型很可能在看不见的 VWAP 区间上工作得不好。
缩放数据
为了帮助 LSTM 模型更快地收敛,缩放数据是很重要的。输入中的大值可能会降低学习速度。我们将使用 sklearn 库中的 StandardScaler 来缩放数据。定标器安装在训练集上,用于转换验证集和测试集上的未知交易数据。如果我们在所有数据上拟合标量,模型将会过度拟合,并且它将在该数据上获得良好的结果,但是在真实世界的数据上性能会受到影响。
from sklearn.preprocessing import StandardScalerscaler **=** StandardScaler()
train_arr **=** scaler**.**fit_transform(df_train)
val_arr **=** scaler**.**transform(df_val)
test_arr **=** scaler**.**transform(df_test)
转换数据
缩放后,我们需要将数据转换成适合用 LSTM 建模的格式。我们将长数据序列转换成许多较短的序列(每个序列有 100 个时间条),每个时间条移动一个时间条。
from torch.autograd import Variable**def** **transform_data**(arr, seq_len):
x, y **=** [], []
**for** i **in** range(len(arr) **-** seq_len):
x_i **=** arr[i : i **+** seq_len]
y_i **=** arr[i **+** 1 : i **+** seq_len **+** 1]
x**.**append(x_i)
y**.**append(y_i)
x_arr **=** np**.**array(x)**.**reshape(**-**1, seq_len)
y_arr **=** np**.**array(y)**.**reshape(**-**1, seq_len)
x_var **=** Variable(torch**.**from_numpy(x_arr)**.**float())
y_var **=** Variable(torch**.**from_numpy(y_arr)**.**float())
**return** x_var, y_varseq_len **=** 100x_train, y_train **=** transform_data(train_arr, seq_len)
x_val, y_val **=** transform_data(val_arr, seq_len)
x_test, y_test **=** transform_data(test_arr, seq_len)
下图显示了训练集中的第一个和第二个序列。两个序列的长度都是 100 倍棒。我们可以观察到,两个序列的目标几乎与特征相同,不同之处在于第一个和最后一个时间条。
The feature and target of the first and second sequence in the training set
LSTM 在训练阶段如何使用这个序列?
让我们关注第一个序列。该模型采用索引 0 处的时间条的特征,并尝试预测索引 1 处的时间条的目标。然后,它采用索引 1 处的时间条的特征,并试图预测索引 2 处的时间条的目标,等等。第二序列的特征从第一序列的特征偏移 1 个时间条,第三序列的特征从第二序列偏移 1 个时间条,等等。通过这一过程,我们得到了许多较短的序列,它们被一个时间条所移动。
请注意,在分类或回归任务中,我们通常有一组特征和一个我们试图预测的目标。在这个 LSTM 的例子中,特征和目标来自相同的序列,唯一的区别是目标移动了 1 倍。
长短期记忆神经网络
长短期记忆神经网络是一种递归神经网络(RNN)。rnn 使用先前的时间事件来通知后面的时间事件。例如,为了对电影中正在发生的事件进行分类,模型需要使用以前事件的信息。如果问题只需要最近的信息来执行当前的任务,那么 RNNs 工作得很好。如果问题需要长期依赖,RNN 将很难对其建模。LSTM 旨在学习长期依赖性。它能长时间记住信息。LSTM 是在 1997 年由舒米胡伯介绍的。要了解更多关于 LSTMs 的信息,请阅读一篇伟大的 colah 博客文章,它提供了一个很好的解释。
下面的代码是时序预测的有状态 LSTM 的实现。它有一个 LSTMCell 单元和一个线性图层来模拟时间序列。该模型可以生成时间序列的未来值,并且可以使用教师强制(我将在后面描述这个概念)来训练它。
import torch.nn **as** nn
import torch.optim **as** optim **class** **Model**(nn**.**Module):
**def** **__init__**(self, input_size, hidden_size, output_size):
super(Model, self)**.**__init__()
self**.**input_size **=** input_size
self**.**hidden_size **=** hidden_size
self**.**output_size **=** output_size
self**.**lstm **=** nn**.**LSTMCell(self**.**input_size, self**.**hidden_size)
self**.**linear **=** nn**.**Linear(self**.**hidden_size, self**.**output_size) **def** **forward**(self, input, future**=**0, y**=**None):
outputs **=** [] *# reset the state of LSTM*
*# the state is kept till the end of the sequence*
h_t **=** torch**.**zeros(input**.**size(0), self**.**hidden_size, dtype**=**torch**.**float32)
c_t **=** torch**.**zeros(input**.**size(0), self**.**hidden_size, dtype**=**torch**.**float32) **for** i, input_t **in** enumerate(input**.**chunk(input**.**size(1), dim**=**1)):
h_t, c_t **=** self**.**lstm(input_t, (h_t, c_t))
output **=** self**.**linear(h_t)
outputs **+=** [output] **for** i **in** range(future):
**if** y **is** **not** None **and** random**.**random() **>** 0.5:
output **=** y[:, [i]] *# teacher forcing*
h_t, c_t **=** self**.**lstm(output, (h_t, c_t))
output **=** self**.**linear(h_t)
outputs **+=** [output]
outputs **=** torch**.**stack(outputs, 1)**.**squeeze(2)
**return** outputs
训练 LSTM
我们用 21 个隐藏单位训练 LSTM。使用的单位数量较少,这样 LSTM 就不太可能完全记住这个序列。我们使用均方误差损失函数和 Adam 优化器。学习率被设置为 0.001,并且每 5 个时期衰减一次。我们用每批 100 个序列训练该模型 15 个时期。从下面的图中,我们可以观察到训练和验证损失在第六个历元之后收敛。
Training and validation loss
让我们在测试集上评估模型。future 参数设置为 5,这意味着模型输出它认为在接下来的 5 个时间条(在我们的示例中为 5 分钟)中的 VWAP。这将使价格变化在发生前的几个时间段内可见。
在下图中,我们可以观察到预测值与 VWAP 的实际值非常接近,乍一看这似乎很好。但是 future 参数被设置为 5,这意味着橙色线应该在尖峰出现之前做出反应,而不是覆盖它。
Actual and predicted VWAP on the test set
当我们放大尖峰时(一个在时间序列的开始,另一个在时间序列的结束)。我们可以观察到预测值模拟了实际值。当实际值改变方向时,预测值也跟着改变,这对我们没有太大帮助。同样的情况发生在我们增加未来参数的时候(就像不影响预测线一样)。
Two VWAP spikes with actual and predicted values
让我们用模型为第一个测试序列生成 1000 个时间条,并比较预测的、生成的和实际的 VWAP。我们可以观察到,虽然模型输出预测值,但它们接近实际值。但是当它开始产生值时,输出几乎类似正弦波。经过一段时间后,数值收敛到 9600。
Predicted, generated and actual VWAP of the first test sequence
之所以会出现这种情况,是因为模型仅使用真实输入进行了训练,而从未使用生成的输入进行过训练。当模型从输入中获得生成的输出时,它在生成下一个值方面做得很差。教师强迫是处理这个问题的一个概念。
教师强迫
教师强制是一种训练递归神经网络的方法,它使用前一时间步的输出作为输入。当训练 RNN 时,它可以通过使用先前的输出作为当前输入来生成序列。在训练期间可以使用相同的过程,但是模型可能变得不稳定或者不收敛。教师强迫是在培训中解决这些问题的一种方法。它通常用在语言模型中。
我们将使用教师强制的扩展,称为预定抽样。该模型将在训练期间使用其生成的输出作为具有一定概率的输入。起初,模型看到其生成输出的概率很小,然后在训练期间逐渐增加。注意,在这个例子中,我们使用随机概率,它在训练过程中不会增加。
让我们使用与之前相同的参数训练一个模型,但是启用了教师强制。在 7 个时期之后,训练和验证损失收敛。
Training and validation loss with teacher forcing
Actual and predicted VWAP on the test set with teacher forcing
我们可以观察到和以前相似的预测序列。当我们放大峰值时,可以观察到模型的类似行为,其中预测值模拟实际值。好像老师强迫并没有解决问题。
Two VWAP spikes with actual and predicted values with teacher forcing
让我们用教师强制训练的模型为第一个测试序列生成 1000 个时间条。
Predicted, generated and actual VWAP of the first test sequence with teacher forcing
通过教师强制训练的模型生成的序列需要更长的时间来收敛。关于生成序列的另一个观察结果是,当它增加时,它将继续增加到某个点,然后开始减少,模式重复,直到序列收敛。该模式看起来像一个振幅递减的正弦波。
结论
这个实验的结果是模型的预测模拟了序列的实际值。第一个和第二个模型在价格变化发生之前不检测价格变化。添加另一个要素(如交易量)可能有助于模型在价格变化发生之前检测到价格变化,但随后模型将需要生成两个要素,以将这些要素的输出用作下一步的输入,这将使模型变得复杂。使用更复杂的模型(多个 LSTMCells,增加隐藏单元的数量)可能没有帮助,因为该模型具有预测 VWAP 时间序列的能力,如上图所示。更先进的教师强制方法可能会有所帮助,因此该模型将提高序列生成技能。
参考
在你走之前
在 Twitter 上关注我,在那里我定期发布关于数据科学和机器学习的消息。
Photo by Courtney Hedger on Unsplash
LSTM:如何训练神经网络像洛夫克拉夫特一样写作
近年来,LSTM 神经网络在文本和音乐生成以及时间序列预测方面有着广泛的应用。
今天,我将教你如何训练一个用于文本生成的 LSTM 神经网络,使它能够以 H. P. Lovecraft 的风格写作。
为了训练这个 LSTM,我们将使用 TensorFlow 的 Keras API for Python。
我从这本很棒的 LSTM 神经网络教程中了解到这个主题。我的代码紧跟这个文本生成教程。
我将像往常一样向您展示我的 Python 示例和结果,但是首先,让我们做一些解释。
什么是 LSTM 神经网络?
最普通的神经网络,称为多层感知器,只是完全连接的层的组合。
在这些模型中,输入是特征向量,每个后续层是一组“神经元”。
每个神经元对前一层的输出执行仿射(线性)变换,然后对该结果应用一些非线性函数。
一层神经元的输出,一个新的向量,被提供给下一层,以此类推。
LSTM(长短期记忆)神经网络只是另一种类型的人工神经网络,在其某些层中包含 LSTM 细胞作为神经元。
很像卷积层帮助神经网络学习图像特征,LSTM 细胞帮助网络学习时态数据,这是其他机器学习模型传统上难以解决的问题。
LSTM 细胞是如何工作的?我现在将解释它,尽管我强烈建议你也给那些教程一个机会。
LSTM 细胞是如何工作的?
LSTM 图层将包含许多 LSTM 像元。
我们的神经网络中的每个 LSTM 细胞将只查看其输入的单个列,并且还查看前一列的 LSTM 细胞的输出。
通常,我们将一个完整的矩阵作为 LSTM 神经网络的输入,其中每一列对应于下一列“之前”的内容。
这样,每个 LSTM 单元将有两个不同的输入向量:前一个 LSTM 单元的输出(给它一些关于前一个输入列的信息)和它自己的输入列。
行动中的 LSTM 细胞:一个直观的例子。
例如,如果我们正在训练一个 LSTM 神经网络来预测股票交易值,我们可以向它输入一个向量,其中包含股票在过去三天的收盘价。
在这种情况下,第一个 LSTM 单元将使用第一天作为输入,并将一些提取的特征发送到下一个单元。
在为下一个单元生成新的输入之前,第二个单元将查看第二天的价格,以及前一个单元从昨天获得的任何信息。
对每个单元格执行此操作后,最后一个单元格实际上会有很多时态信息。它将从前一个单元接收从昨天收盘价和前两个单元(通过其他单元提取的信息)获得的信息。
您可以尝试不同的时间窗口,也可以改变查看每天数据的单位(神经元)数量,但这是总体思路。
LSTM 细胞如何工作:数学。
每个细胞从前一个细胞中提取的信息背后的实际数学要复杂一些。
忘记大门
“遗忘门”是一个 sigmoid 层,它调节前一个细胞的输出对这个细胞的影响程度。
它将前一个单元的“隐藏状态”(另一个输出向量)和前一层的实际输入作为输入。
因为它是一个 sigmoid,所以它将返回一个“概率”向量:介于 0 和 1 之间的值。
他们将乘以前一个单元的输出来调节他们拥有多大的影响力,从而创建这个单元的状态。
例如,在极端的情况下,sigmoid 可能返回一个零向量,整个状态将被乘以 0,从而被丢弃。
例如,如果该层在输入分布中看到非常大的变化,则可能发生这种情况。
输入门
与遗忘门不同,输入门的输出被加到前一个单元的输出上(在它们乘以遗忘门的输出之后)。
输入门是两个不同层的输出的点积,尽管它们都采用与遗忘门相同的输入(前一个单元的隐藏状态和前一层的输出):
- 一个 sigmoid 单元,调节新信息对该细胞输出的影响程度。
- 一个 tanh 单元,它实际上提取新的信息。注意 tanh 取-1 和 1 之间的值。
这两个单元的乘积(也可以是 0,或者正好等于 tanh 输出,或者介于两者之间的任何值)被添加到该神经元的细胞状态中。
LSTM 细胞的输出
单元格的状态是下一个 LSTM 单元格将接收的输入,以及该单元格的隐藏状态。
隐藏状态将是应用于该神经元状态的另一个双曲正切单位,乘以另一个 sigmoid 单位,后者获取前一层和细胞的输出(就像遗忘门一样)。
这是每个 LSTM 细胞的可视化效果,借用我刚才链接的教程:
Source: Text Generating LSTMs
既然我们已经讨论了理论,让我们继续讨论一些实际应用吧!
像往常一样,所有的代码都可以在 GitHub 上找到,如果你想试试的话,或者你也可以跟着去看看要点。
用张量流 Keras 训练 LSTM 神经网络
在这个任务中,我使用了这个包含 60 个爱情故事的数据集。
由于他的大部分作品是在 20 年代创作的,他于 1937 年去世,所以现在大部分作品都在公共领域,所以不难得到。
我认为训练一个神经网络像他一样写作会是一个有趣的挑战。
这是因为,一方面,他有非常鲜明的风格(有丰富的紫色散文:使用怪异的词语和精心制作的语言),但另一方面,他使用了非常复杂的词汇,一个网络可能很难理解它。
例如,这是数据集中第一个故事的随机句子:
到了晚上,外面黑暗的城市里微妙的骚动,老鼠在爬满虫子的隔墙里阴险的窜来窜去,还有百年老屋里隐藏的木头吱吱作响,这些都足以给他一种刺耳的混乱感
如果我能让一个神经网络写出“pandemonium”,那我会印象深刻。
预处理我们的数据
为了训练 LSTM 神经网络生成文本,我们必须首先预处理我们的文本数据,以便它可以被网络使用。
在这种情况下,由于神经网络将向量作为输入,我们需要一种方法将文本转换为向量。
对于这些例子,我决定训练我的 LSTM 神经网络来预测字符串中接下来的 M 个字符,将前面的 N 个字符作为输入。
为了能够输入 N 个字符,我对它们中的每一个都进行了一次性编码,因此网络的输入是 CxN 个元素的矩阵,其中 C 是我的数据集中不同字符的总数。
首先,我们读取文本文件并连接它们的所有内容。
我们限制我们的字符是字母数字,加上一些标点符号。
然后我们可以将字符串一次性编码成矩阵,其中第 j 列的每个元素都是 0,除了对应于语料库中第 j 个字符的元素。
为了做到这一点,我们首先定义一个字典,为每个字符分配一个索引。
请注意,如果我们希望对数据进行采样,我们可以将变量切片变小。
我还为SEQ _ 长度选择了一个值 50,让网络接收 50 个字符并尝试预测接下来的 50 个字符。
在 Keras 中训练我们的 LSTM 神经网络
为了训练神经网络,我们必须首先定义它。
该 Python 代码创建了一个具有两个 LSTM 层的 LSTM 神经网络,每个层具有 100 个单元。
请记住,每个单元在输入序列中的每个字符都有一个单元格,即 50。
这里的 VOCAB_SIZE 只是我们将使用的字符数量,而 TimeDistributed 是一种将给定层应用到每个不同单元格的方式,保持时间顺序。
对于这个模型,我实际上尝试了许多不同的学习速率来测试收敛速度与过度拟合。
以下是培训代码:
你看到的是在损失最小化方面表现最好的产品。
然而,在最后一个时期(500 个时期之后)的 binary_cross_entropy 为 0.0244 时,模型的输出看起来是这样的。
Tolman hast toemtnsteaetl nh otmn tf titer aut tot tust tot ahen h l the srrers ohre trrl tf thes snneenpecg tettng s olt oait ted beally tad ened ths tan en ng y afstrte and trr t sare t teohetilman hnd tdwasd hxpeinte thicpered the reed af the satl r tnnd Tev hilman hnteut iout y techesd d ty ter thet te wnow tn tis strdend af ttece and tn aise ecn
这个输出有许多好的方面,也有许多不好的方面。
设置间距的方式与语料库中实际的单词长度分布非常相似,单词长度大多在 2 到 5 个字符之间,有一些更长的异常值。
我还注意到字母、【T】、【E】和【I】在中出现得非常普遍,而【y】或【x】出现得不太频繁。
当我在样本输出和语料库中查看字母相对频率时,它们非常相似。是命令使完全脱离。
关于大写字母如何只出现在空格之后,也有一些要说的,在英语中通常是这样。
为了生成这些输出,我简单地要求模型为语料库中不同的 50 个字符子集预测接下来的 50 个字符。如果训练数据如此糟糕,我认为测试或随机数据不值得检查。
这些废话实际上让我想起了 H. P .洛夫克拉夫特最著名的故事之一,“克苏鲁的召唤”,在那里人们开始对这个宇宙的、邪恶的存在产生幻觉,他们说这样的话:
Ph ' nglui mglw ' nafhCthulhu R ' lyehwgah ' nagl FH tagn。
遗憾的是,这个模型也没有过度拟合,显然是欠拟合。
所以我试图把它的任务变小,把模型变大:125 个单元,只预测 30 个字符。
更大的模型,更小的问题。有结果吗?
有了这个更小的模型,又过了 500 个纪元,一些模式开始出现。
即使损失函数没有那么小(在 210),字符的频率仍然与语料库相似。
尽管字符的排序有了很大的改进:这里有一个来自其输出的随机样本,看看您是否能发现一些单词。
the sreun troor Tvwood sas an ahet eae rin and t paared th te aoolling onout The e was thme trr t sovtle tousersation oefore tifdeng tor teiak uth tnd tone gen ao tolman aarreed y arsred tor h tndarcount tf tis feaont oieams wnd toar Tes heut oas nery tositreenic and t aeed aoet thme hing tftht to te tene Te was noewked ay tis prass s deegn aedgireean ect and tot ced the sueer anoormal -iuking torsarn oaich hnher tad beaerked toring the sars tark he e was tot tech
科技,这个,那个,曾经… 小词才是重点!它还意识到许多单词以常用后缀结尾,如-ing、-ed 和-tion。
在 10000 个单词中,有 740 个单词是“ the ”,37 个单词以“ tion 结尾(其中只有 3 个单词没有结尾),115 个单词以— ing 结尾。
其他常见的单词是“than”和“than”,尽管该模型显然仍然无法生成英语句子。
更大的模型
这给了我希望。神经网络显然在学习某些东西,只是还不够。
所以当你的模型不合适时,我做了你做的事情:我尝试了一个更大的神经网络。
考虑到这一点,我正在我的笔记本电脑上运行。
凭借适中的 16GB 内存和 i7 处理器,这些型号需要数小时才能学会。
因此,我将单位数量设置为 150,并在 50 个字符处再次尝试。
我想也许给它一个更小的时间窗口会让网络变得更困难。
经过几个小时的训练后,这个模型的输出是这样的。
andeonlenl oou torl u aote targore -trnnt d tft thit tewk d tene tosenof the stown ooaued aetane ng thet thes teutd nn aostenered tn t9t aad tndeutler y aean the stun h tf trrns anpne thin te saithdotaer totre aene Tahe sasen ahet teae es y aeweeaherr aore ereus oorsedt aern totl s a dthe snlanete toase af the srrls-thet treud tn the tewdetern tarsd totl s a dthe searle of the sere t trrd eneor tes ansreat tear d af teseleedtaner nl and tad thre n tnsrnn tearltf trrn T has tn oredt d to e e te hlte tf the sndirehio aeartdtf trrns afey aoug ath e -ahe sigtereeng tnd tnenheneo l arther ardseu troa Tnethe setded toaue and tfethe sawt ontnaeteenn an the setk eeusd ao enl af treu r ue oartenng otueried tnd toottes the r arlet ahicl tend orn teer ohre teleole tf the sastr ahete ng tf toeeteyng tnteut ooseh aore of theu y aeagteng tntn rtng aoanleterrh ahrhnterted tnsastenely aisg ng tf toueea en toaue y anter aaneonht tf the sane ng tf the
纯粹的废话,除了一大堆“这个”和“那个”
实际上,它说“the”的次数比前一个多,但它还没有学会动名词(no -ing)。
有趣的是,这里很多单词以“-ed”结尾,这意味着它有点领会了过去式的意思。
我让它多经历了几百个时代(总共 750 个)。
输出没有太大变化,仍然有很多“The”、“a”和“an”,仍然没有更大的结构。这是另一个例子:
Tn t srtriueth ao tnsect on tias ng the sasteten c wntnerseoa onplsineon was ahe ey thet tf teerreag tispsliaer atecoeent of teok ond ttundtrom tirious arrte of the sncirthio sousangst tnr r te the seaol enle tiedleoisened ty trococtinetrongsoa Trrlricswf tnr txeenesd ng tispreeent T wad botmithoth te tnsrtusds tn t y afher worsl ahet then
这里出现了一个有趣的现象,介词和代词的使用。
网络上写过几次“我”“你”“她”“我们”“的”等类似的词。总之,介词和代词**约占总样本词的 10%。**
这是一个进步,因为网络显然在学习低熵单词。
然而,它仍然远远不能产生连贯的英语文本。
我让它多训练了 100 个纪元,然后杀了它。
这是它最后的输出。
thes was aooceett than engd and te trognd tarnereohs aot teiweth tncen etf thet torei The t hhod nem tait t had nornd tn t yand tesle onet te heen t960 tnd t960 wndardhe tnong toresy aarers oot tnsoglnorom thine tarhare toneeng ahet and the sontain teadlny of the ttrrteof ty tndirtanss aoane ond terk thich hhe senr aesteeeld Tthhod nem ah tf the saar hof tnhe e on thet teauons and teu the ware taiceered t rn trr trnerileon and
我知道它已经尽了最大努力,但它并没有真正取得任何进展,至少还不够快。
我想到了用批量归一化加快收敛速度。
然而,我在 StackOverflow 上读到 BatchNorm 不应该与 LSTM 神经网络一起使用。
如果你们中的任何人对 LSTM 篮网更有经验,请在评论中告诉我这是否正确!
最后,我用 10 个字符作为输入,10 个字符作为输出,尝试了同样的任务。
我想这个模型没有得到足够的上下文来足够好地预测事情:结果很糟糕。
我认为实验暂时结束了。
结论
虽然很明显,看着其他人的工作,LSTM 神经网络可以像 Lovecraft 一样学习写作,但我不认为我的个人电脑足够强大,可以在合理的时间内训练一个足够大的模型。
或者可能它需要比我更多的数据。
将来,我想用基于单词的方法而不是基于字符的方法来重复这个实验。
我查了一下,语料库里大概有 10%的词只出现一次。
如果我在培训前移除它们,有什么好的做法可以遵循吗?比如把所有名词都换成同一个,从簇中取样,或者其他什么?请让我知道!我敢肯定,你们中的许多人在 LSTM 神经网络方面比我更有经验
你认为这在不同的架构下会更好吗?一些我应该用不同方式处理的事情?也请让我知道,我想了解更多关于这一点。
你在我的代码中发现任何新的错误了吗?你认为我不去 XYZ 是个白痴吗?或者你真的觉得我的实验很有趣,或者你甚至从这篇文章中学到了什么?
如果你想讨论这个或任何相关话题,请在 Twitter 、 LinkedIn 、 Medium 或 Dev.to 上联系我。
如果你想成为一名数据科学家,或者想学习新的东西,可以看看我的 机器学习阅读清单 !
原载于 2019 年 6 月 24 日http://www . data stuff . tech。**
LSTM 探测尼安德特人的 DNA
生命科学的深度学习
用于古代基因组学的长记忆神经网络
Image licence from iStock
这是我的专栏 生命科学深度学习 的第八篇文章,在这里我演示了如何将深度学习用于古代 DNA 、单细胞生物学、组学数据集成、临床诊断和显微成像。在关于尼安德特人基因**的 深度学习中,我强调了深度学习和 NLP 对于 古代基因组 的巨大潜力,并演示了如何实际开始使用它来推断现代人类基因组中 尼安德特人渗入 的区域。现在,我们将运用长记忆递归神经网络的全部力量,更好地预测现代人类基因组中尼安德特人祖先的片段。**
HMM 对 LSTM 的古基因组学
DNA 是一个具有长记忆的序列,这是通过沿着序列的长程相关性表现出来的,这被称为 连锁不平衡 。然而,古代基因组学中的许多分析都是使用隐马尔可夫模型(HMM) 进行的,这是一种无记忆模型,只能考虑前面的几个步骤。 长短期记忆(LSTM) 人工神经网络已经显示出到在许多应用中胜过****HMM,例如语音识别、文本生成等。假设有足够的数据可用,通过利用他们独特的能力来按顺序记忆许多先前的步骤。
From Panzner and Cimiano, Machine Learning, Optimization, and Big Data, 2016
基因组学和古代基因组学代表了一个真正的大数据资源,这要归功于下一代测序(NGS) ,它提供了数百万和数十亿个** 序列,可以用作训练 LSTMs 的训练示例/统计观察。因此,古代基因组数据是深度学习的一份礼物!**
尽管基因组学/古代基因组学的培训资源繁荣,大多数分析仍然是在模拟的基因组数据上进行的,其中 合并理论 可能是最流行的模拟人口统计学和群体遗传学中的选择的框架。
尼安德特人 DNA 上的 LSTM +单词嵌入
在这里,我将扩展我在之前的帖子 中表达的关于使用 NLP 进行古代基因组学的想法,并展示 LSTMs 在分析测序数据方面的优势。你可能已经注意到,前一篇文章中的深度学习不是特别“深”,而是相当“广”,此外,随机森林似乎在单词袋模型中表现得更好。在这里,我将实现一个 LSTM 模型,它可以达到 99%的准确率来检测从尼安德特人那里继承的 DNA 片段。我在之前的帖子中展示了如何提取尼安德特人渐渗和耗尽的序列,所以在这里我将从读取序列开始,将它们分割成 200 个核苷酸长的子序列,每个子序列代表一个句子,这样我们可以进一步将每个句子分割成 k-mers /句子的单词。****
我们最终得到了 737,340 个句子,它们属于两类:尼安德特人渗入和耗尽。下一步是通过使用 Python 中的标记器类将 k-mers /单词转换成整数来对句子进行热编码。注意,在我们的例子中并不需要填充,因为所有的句子都是一样长的, 191 k-mers 长,但是我把它包含在这里是为了通用性。
在我们的例子中,词汇量为 964 114,小于 4^10 = 1 048 576,这意味着不是所有可能的由 4 个字符组成的 10 聚体都存在于序列中。最后,我们定义了一个序列模型,从 Keras 嵌入层开始,该嵌入层在对序列进行分类时学习单词嵌入,随后是双向 LSTM** 和密集层。**
在第一层使用字嵌入的优点是维数从 964×114 减少到 10 维。这通过强制相似单词共享拟合参数/权重来减少过度拟合并提高模型的可推广性。现在我们可以开始训练我们的模型了。****
仅执行 5 个时期的训练就足够了,因为模型在验证数据集上很快达到了令人惊讶的 99% 的准确度。****
****
在测试数据集**上评估模型性能,我们再次获得对尼安德特人渐渗序列与耗尽序列进行分类的准确度的 99% 。**
现在我们有了一个经过训练的 LSTM 模型,我们稍后将使用它来预测从尼安德特人那里继承的基因序列。现在是对模型进行解释的时候了,这包括词汇表的可视化和检测驱动分类的最具预测性的 k-mers。
可视化单词嵌入
目前,每个 k-mer /单词由一个 10 维向量表示,因为我们在网络前端应用了一个嵌入层。为了可视化嵌入层已经学习了什么,我们首先需要保存层的权重和词汇表的单词。
为了可视化,我们可以在这里使用 Tensorflow 嵌入式投影仪http://projector.tensorflow.org/并使用 UMAP 非线性降维技术研究 k-mers 的聚类。****
嵌入层学习到的 k-mers 之间的关系看起来与上一篇文章中提出的 Word2Vec 嵌入非常不同,并且没有揭示富含 AT 和富含 GC 的 k-mers 的任何明显聚类。
识别最具预测性的 K-mers
为神经网络构建特征重要性的一种方法是对输入数据施加一些扰动,并在网络输出端监控预测准确度的变化。这里,我们希望找到最具** 信息量的 k-mers ,然而,在我们的例子中,输入矩阵 X 具有维度(737340,191),其中第一维表示神经网络的训练样本的数量,第二维对应于每个句子/序列中的单词数量。这意味着每个单词/ k-mer 的索引(或句子中的位置)是输入矩阵 x 的特征。因此,如果我们在 737340 个样本中一次一个地混洗 191 个特征中的每一个,并检查与未扰动的输入矩阵相比准确度的下降,我们可以根据它们对最终预测的重要性对特征进行排序。在我们的例子中,排列特征相当于确定单词/ k-mers 在所有句子/序列中最重要的位置。**
如果我们选择改变准确度高于 0.01 的单词的位置/索引,我们得出单词 0、4、7、18、34、52、75、81、104、130、146 和 182 是最重要的。也许,我们在句子的开头的处观察到一些重要单词的浓缩。现在,我们简单地检查一下在上述位置的所有句子中最常见的单词/ k-mers。****
令人放心的是,我们观察到富含 at 的 k-mers** 在尼安德特人渐渗序列和耗尽序列之间的区分度最高,这也在之前的帖子中显示过。**
预测尼安德特人的基因
现在我们将考虑人类基因序列和经过训练的 LSTM 模型,以预测每个人类基因从尼安德特人遗传的可能性。在之前的帖子中,我解释了如何将基因序列提取到一个单独的 fasta 文件中,所以现在我们将读取这些序列,将它们分成 k-mers,用 Tokenizer 将 k-mers 转换成整数,并使用训练好的 LSTM 模型预测尼安德特人的祖先。
检查被预测为从尼安德特人遗传而来的基因的数量,我们确认了来自先前帖子的结果,即的绝大多数基因,即 31 000 个被分析的人类基因中的 22 000 个与尼安德特人的祖先无关。因此,我们再次得出结论,由于某种原因,进化将尼安德特人的祖先从人类基因组中最具功能的基因中挤出来了。仔细看看尼安德特人基因列表,并将其与上一篇帖子中随机森林模型的预测进行比较,我们观察到许多基因与各种人类特征和疾病有关。例如, ANK3 基因被>预测为尼安德特人祖先的概率为 99%。已知这种基因与双相情感障碍有关,并且主要在人脑中表达。****
ANK3 gene predicted to be of Neanderthal origin is linked to Bipolar Disorder
ANK3 is a human brain-specific gene based on GTEX human tissue expression data
此外,一些研究表明,人类大脑中与精神疾病有关的部分可能是由尼安德特人的基因遗传形成的。
Human brain harbors “residual echo” of Neanderthal genes, image source
这就是进化科学能够告知生物医学导致现代人类疾病的特征的历史发展和起源的地方。
摘要
在这篇文章中,我们了解到将长记忆模型如 LSTM 应用于已知拥有长程相关性的 DNA 测序数据可能是有利的。我们展示了 LSTM 取得了令人印象深刻的准确性,并且在检测现代人类基因组中的尼安德特人基因渗入区域时,优于所有其他模型。对模型的解释揭示了富含 AT 的 k-mers 是尼安德特人和本土现代人类 DNA 序列的关键区别。我们预测大多数人类基因都没有尼安德特人的祖先,这意味着在进化过程中对尼安德特人祖先的强烈否定选择。许多被预测会从尼安德特人身上遗传的基因与有趣的人类特征相关联,例如双相情感障碍。****
像往常一样,让我在评论中知道你最喜欢的生命科学领域,你希望在深度学习框架中解决的领域。在媒体关注我,在 Twitter @NikolayOskolkov 关注我,在 Linkedin 关注我。完整的 Jupyter 笔记本可以在我的 github 上找到。我计划写下一篇关于如何用深度学习及时预测人口规模的帖子,敬请关注。
Lyft 数据科学家分享了五条职业建议
Troy Shu 分享了他对开始新角色、成为更好的故事讲述者、利益相关者管理、向上管理和建立咨询公司的建议
Troy Shu 目前是 Lyft 的数据科学家,Lyft 是一家拥有超过 2300 万用户的运输公司。他住在纽约,在那里他帮助建立自行车和滑板车业务。他的工作包括与数据工程师合作建立气流中的数据管道,创建仪表板,进行 A/B 测试,以及与产品经理合作进行产品分析。
在 Lyft 之前,他在 Squarespace 担任数据科学家,经营自己的数据科学咨询公司,在 Bond Street 担任软件工程师,并在 AQR(Wes McKinney 在那里创建并开源了 Pandas Python 库)担任研究分析师。他毕业于宾夕法尼亚大学,拥有计算机科学和经济学双学位。
1。在一家新公司开始工作时,Troy 首先建议建立领域专长。建立领域专业知识的最好方法是与许多人交谈,无论是在你的部门内部还是外部。当他第一次加入 Lyft 时,他确保安排了 15 分钟时间与来自不同部门的人在一起,试图了解情况。他通过阅读尽可能多的文件来补充这些对话。在这些会议中,他集中精力问了许多问题,以加速他的学习。
一旦你建立了领域专业知识,你就可以开始识别速赢,通常持续不到 2 周的项目,以建立可信度和信任。为了确保这些项目有影响力,首先要了解对你的经理、经理的经理以及整个公司来说什么是最重要的。另一种寻找快速成功的方法是确定你的团队目前处于哪个阶段。他们是在试图建造什么东西,还是在试图弄清楚下一步要建造什么?回答这些类型的问题将有助于你决定追求哪种类型的速赢。
2。成为更好的讲故事者 在大多数情况下,讲故事是数据科学家可以培养的最基本技能之一。最好的故事讲述者是那些在展示见解时能够创造某种流动的人。这意味着在你的演讲中避免不连贯,利用自上而下的故事结构,这意味着从最重要的观点开始(不要埋没线索!
创造虚假的用户角色来展示他们如何使用产品是另一种有效的讲述技巧。能够使你的数据人性化可以使这些见解更有说服力和更令人难忘。
讲故事的另一个关键部分是视觉化。一个好的视觉效果可以成就一场演讲,也可以毁掉一场演讲。它甚至可能在整个公司的其他演示中被重用!Troy 推荐那些想要提高数据可视化技能的人阅读用数据讲故事,以及 Chartify python 库。
最后,寻找与 UX 研究人员合作的机会。无论是在一个项目上合作还是利用彼此的现有成果。在你的故事中结合定量和定性的见解,可以形成一个强大的组合。
3。利益相关者管理 与各种利益相关者合作意味着能够接受他们的观点。例如,如果你和一个产品经理一起工作,表现出一些产品意识是建立信任的可靠方法。另一个有用的技术是从用户的角度出发,利用以人为中心的设计原则。
当与涉众一起工作时,要避免的一个陷阱是掉进兔子洞,然后拿出一个完美的可交付成果。如果事实证明你所做的工作不是利益相关者所想的,这种方法很容易适得其反。更好的方法是迭代和增量。例如,利用精益创业方法来构建初始原型,并从利益相关者那里获得反馈,以确保你在正确的轨道上。
最后,直接给出建议,这些建议应该具体而清晰,以便利益相关者可以评估选项并做出决定。尽量不要让他们被实质性的分析淹没。相反,你可以选择将这些信息放在附录中,或者全部省略,这样你就可以专注于你的建议的关键要素。
4。管理好 作为一名数据科学家,你需要管理的最重要的关系之一就是与你老板的关系。学习向上管理的艺术很重要,这样你就能为自己的成功做好准备。多听少说,让你的经理感到有人倾听是建立融洽关系的好方法。对你和经理的关系来说,最糟糕的事情莫过于听取他们的建议,却做了与他们建议完全相反的事情。
弄清楚你的经理是根据什么被评估的,然后帮助你的经理看起来不错,这是与他们建立良好关系的最好方法之一。最终,你职业生涯的命运掌握在你的经理手中,所以一定要找出激励他们的因素,以及如何最好地融入他们的管理风格。
5。如何建立一家咨询公司 对于那些希望从事兼职客户工作或建立一家全职咨询公司的人,特洛伊有各种各样的建议。第一是在设定自己的工作时间和为自己创建流程方面要自律。这可能意味着租出一个可以模拟传统工作环境的共同工作空间。坚持与工薪阶层相似的时间表有助于建立积极的动力和建立积极的日常生活。
另一个建议是磨练你的推销能力。当你开始工作时,你的大部分时间将会试图寻找客户工作。随着你的名声越来越大,你可能会开始收到入站,但在最初阶段,将有很多跑腿工作,以获得前几个项目。
在寻找客户时,三种主要方法是个人网络、社区网络和在线门户网站,如 Upwork。你的个人关系网可能是你获得客户工作最成功的地方,无论是过去的同事还是大学校友关系网。社区网络由 Meetup 等实体社区或 Reddit 等在线社区组成。在后一种情况下,Troy 在 Reddit 数据科学社区上为某人做了快速的一次性分析后,找到了一些客户工作。第三种方法是三种方法中利润较低的,因为你将与全球自由职业人才群竞争,鉴于他们的生活成本低,其中许多人对低价竞标没有问题。
《数据思维》是一个系列,介绍处理数据的专业人士。在这个系列中,你将了解他们的日常故事,以及给别人的建议。
之前的采访包括来自红牛、开门、 Snapchat 和网飞的数据科学家。
面向网络的歌词生成模型
Photo by Willian Justen de Vasconcellos on Unsplash
迷你项目
一种创建和托管文本生成模型的极简方式
Python 有一个很棒的库,叫做 textgenrnn ,可以很容易地在你的文本上训练神经网络。我一直使用的文本数据由 2017-2019 年期间 Spotify 全球 200 强曲目组成。这是使用 textgenrnn 训练模型所需的全部代码:
它相当快,开箱后就有几个重量文件可供您自己尝试。无论如何,当你有一个训练好的模型时,生成新的文本也同样简单:
大多数时候,输出是可笑的无意义的。这里有一个例子:
Hold on, now she got the heart (Oh, it's so safe)
I want you to be my man comes on a time
When I was the light
[Verse 1]
I can't have to change you the beat us (Yeah, yeah)
(Hey, hey, hey, hey, hey)
And I can't pop a bag (I made it)
Hold on, but you don't like what, what you want, where were?
I'm drowning on the morning, she wanna keep going for the morning
I can't have a little bitch (Skrrt)
I can't be a bad llon low
She wanted me a little bit of the booty
我把这个上传到网上,让其他人在 lyrics-gen.herokuapp.com 的 T4 试一试。主机是 Heroku 的免费层,因此网站在 30 分钟不活动后会休眠,这意味着如果它碰巧休眠了,可能需要几秒钟才能访问。创作一首歌曲大约需要 15 秒钟。
我用 Python 的 Flask 库创建了这个站点。这个库包含了整个网页。我创建了一个尽可能简单的 main.py 文件,放在我之前训练过的权重所在的文件夹中:
函数 generate 使用如上所述的 textgenrnn 来生成歌词。这些可以通过异步 AJAX 请求在 HTML 文件中调用。AJAX 可以更新网页的一部分,而不需要重新加载整个页面。
单击 generate 按钮会触发一个 AJAX 函数,该函数从主文件中的 generate 函数接收一个由换行符分隔的字符串作为响应。ajax 方法内部的循环从响应中创建了一个无序列表,最终的列表被传递给 id 为“textlist”的 div 元素。默认情况下,HTML 将项目符号添加到无序列表中,但是在这里通过将 list-style 设置为 none 来删除它们。
我添加了少量的 CSS 样式和 tadaa,这样我们就完成了:)
TL;DR I 热情推荐 textgenrnn 用于生成文本,并利用该包创建了一个网站。
祝你愉快!
机器开玩笑:我们到了吗?
什么东西可以放在鞋盒里,解决复杂的问题,并且可以依靠一个 masala dosa 的能量运行几个小时?
人脑。
拉塞尔·皮特斯、马兹·乔布拉尼、扎基尔·汗、阿图尔·卡特里、维尔·达斯、尼提·帕尔塔……不会让我们只是微笑。他们让我们发笑。使劲笑。感谢 youtube,这仅仅是个开始。我们看到斯坦福大学的博士同事(杰格迪什·查图维迪博士)、MBA 毕业生(拉胡尔·萨勃拉曼尼亚)以及微软游戏总监(安舒·莫尔)作为单口相声演员一夜成名。
喜剧是一门困难的艺术,然而,人工智能研究人员正在测试边界,看是否可以将引发笑声和提供娱乐的认知技能放入机器中。基本上,他们想看看机器人是否有趣。疯狂?当然可以。这主要是因为幽默依赖于多种因素,其中许多是内在的,并且会发生变化——今天可能有趣的事情明天可能就不有趣了。
语言学和心理学家认为好的笑话都有相同的特性——它们让我们开心——所以系统分析应该能揭示它们,对吗?不完全是。
密歇根大学的计算机科学家德拉戈米尔·拉德夫和他在雅虎实验室、哥伦比亚大学和《纽约客》的朋友们一直在研究卡通字幕,看看幽默是否可以用计算机用算术来表达。Radev 和他的同事的研究发表在 arXiv 上。《纽约客》著名的漫画字幕大赛已经举办了十多年。每周,编辑们都会发布一幅无标题的漫画,超过 5000 名读者会提交一个有趣的标题。编辑挑选出前三名,并让读者选出最有趣的。
在论文中,该研究的作者采用了一种计算方法来确定最有趣的字幕与其他字幕的区别。他们使用许多标准的语言技术来排列所有 30 万个标题。标准包括情感水平、字幕是否指的是人、它们指的是漫画中的特定物体有多清晰等等。然后,拉德夫和他的同事们选择了排名最高的标题,并将其与黄金标准进行比较:《纽约客》读者选择的最有趣的标题。这是通过使用亚马逊的机械土耳其人(Mechanical Turk)的众筹意见完成的,在这个地方,公司执行计算机目前无法完成的任务。基于这种方法,很容易想象一台计算机能够产生最好的字幕。但是研究人员离实现这一目标还有很长的路要走。
一个问题是,对于一台真正幽默的计算机,大多数人都同意,首先你必须给它编程,到底是什么让事情变得有趣——这是专家们千百年来一直在努力的事情。例如,柏拉图和亚里士多德长期思考这个问题,并提出了优越感理论,即人们嘲笑他人的不幸。与此同时,西格蒙德·弗洛伊德(Sigmund Freud)为他的缓解理论辩护,该理论认为幽默是人们释放被压抑的性和暴力思想所压抑的精神能量的一种方式。然后是不一致理论,这是由 17 世纪法国哲学家布莱士·帕斯卡提出的观点,即当人们发现他们期望发生的事情和实际发生的事情不一致时,幽默就会产生。
计算机生成幽默的另一个绊脚石是:计算机擅长处理简单、固定的数据集。这就是为什么迄今为止大多数笑话生成程序都专注于双关语和其他文字游戏,因为有限的单词列表和特定的定义很容易被计算机扫描和解析。但是大多数喜剧的概念并不简单,也不固定。最好的喜剧挖掘了态度、假设、道德和禁忌的广阔天地,其中大部分甚至没有在笑话中提到,只是微妙地暗示了一下。因此,如果我们的目标是让计算机真正“理解”笑话——更不用说自己想出笑话,并知道何时和向谁讲笑话了——我们基本上是要把所有的人类上传到它们里面。
笑和幽默有什么区别?
开发理解喜剧的机器最常见的挑战之一是缺乏科学有效的、公认的幽默定义。
关于笑和幽默以及它们之间的区别的研究仍然很少。很难分析和量化如此微妙的人类事物。前一分钟可能会让我们发笑的东西,下一分钟就不一定了。笑声被用作交流的辅助工具;从温柔的轻笑到开怀大笑,它帮助我们传达我们对各种社交场合的反应。我们不只是对一些有趣的事情发笑,我们可以用它来建立融洽的关系,显示信任和接受,以及填补谈话中的空白。幽默可以被定义为有趣的艺术,或发现有趣事物的能力;这是双向的。它充满了微妙的细微差别,依赖于正确的社会解释和互动——这是人类与生俱来的。
自发性可以被编程吗?
当涉及到人工智能时,幽默的自发性质是一个令人困惑的因素。即使是最复杂的机器也需要编程和某种类型的模板来处理输入。但是很多喜剧依赖于不可预测的结果,这是计算机通常缺乏的技能。
虽然计算机可以被训练在多个模板或假设之间切换,但它们仍然无法处理超出其知识库边界的真正原创的概念。为了理解自发的笑话并真正拥有幽默感,机器必须获得对现实更广泛的上下文评价。
计算机科学家渴望解决喜剧问题是有原因的:笑话是对他们程序的一些最艰难的测试。如果人工智能程序真的要模拟人类智能,它们必须能够掌握人们让事情变得有趣的所有聪明方法。
事实上,几十年来,科学家们一直在努力设计机器人小丑。其中包括笑话分析和制作引擎JAPE;单口相声,使用双关语增强非说话者对话的系统; LIBJOB ,灯泡笑话生成器;SASI,一个侦测讽刺的程序;和偏差,通过名词转移程序的双重双关语,它在自然语言中找到完美的地方插入“那是她说的。”此外,对于正在为下一台大型喜剧计算机寻找合适的诙谐缩写的计算机程序员来说,还有 HAHAcronym Generator 。
讲笑话不是笑话!
对于人类来说,幽默的时机和幽默已经够难的了,所以当试图将这些能力转移到机器人身上时,挑战是巨大的。喜剧时机是一件非常微妙的事情,很难实现。参与任何形式的幽默都需要大量的实时思考,识别和应对社会细微差别,以及一定程度的同理心,以了解何时发表观点,并预测人们会如何接受。
那么,如果可能的话,我们将如何制造有趣的机器人呢?Dragomir Radev 回答道:“简单——松开几个螺丝”。
参考文献a .是喜剧演员 vs 电脑在一场幽默至上的战斗,连线,乔尔·华纳,乔尔·华纳和彼得·麦格劳。 b .人工智能中的幽默和笑声,Nao 博客
c .机器人能让你笑吗?、新政治家
d .集体话语中的幽默:纽约客漫画字幕大赛中的无监督滑稽检测,Radev 等人,2015 年 4 月(https://arxiv.org/pdf/1506.08126.pdf)
e .神经开玩笑机器:幽默图像字幕,Kota Yoshida 等人,2018 年 5 月 30 日(https://arxiv.org/abs/1805.11850)
献词
这篇文章是献给艾萨克·阿西莫夫博士的。就在 1992 年 4 月,他离开了我们..以科幻作品的形式留下了他的遗产。《小丑》是他的杰作之一,是一部关于机器幽默的有趣的短篇小说。
故事链接:http://blog . AC-Versailles . fr/villaroylit/public/joke ster . pdf
初学者:成本函数和梯度下降
Credited to “Machine Learning and Human Bias”. Google. https://www.youtube.com/watch?v=59bMh59JQDo
讲故事有两种方式,一种是艰难的方式,你被期望达到演讲者或作者的标准,另一种是作者或演讲者期望观众必须理解故事在讲什么,不管你听起来有多天真。因此,在这里,我试图停留在后一类,同时试图给读者一个直观的成本函数的理解,以及 2 种不同的方法来减少成本函数。
注意:我假设读者是拥有二维和三维平面的家庭。
介绍
假设给你三个数字(1,1),(2,2),(3,3),它们可以在二维平面上表示,这意味着它们可以在 x-y 平面上表示,如下图所示。
(a)
现在,有人要求你拟合一条线,尽可能接近你已经得到的所有的点。拟合线是指尽可能接近二维平面中所有点的线。这些线将遵循的等式如下所示:
这里θ0 是直线的截距,θ1 是直线的斜率。截距是直线与 y 轴相交的值,斜率表示 x 轴上一个单位的变化会改变 y 轴上的值。
根据这个等式,假设我们得出了三种不同的直线,它们有三种不同的斜率和截距值,如下所示。该表的上线、中线和下线为θ0,上线、中线和下线为θ1。
(b)
这些图形显示的线的值也以表格形式显示。
很明显,中间的线与图(a)中显示的所有三个点相匹配,但是上面的线和下面的线与这三个点并不完全匹配。那是什么意思?让我看看…
价值函数
成本函数基本上意味着你的预测线离我们已经知道的实际点有多远。换句话说,你已经得到了一些点,然后你预测了θ0 和θ1 的值,利用这些,你在图上画了一条线;这样做之后,你意识到新的线并不完全触及你已经拥有的所有三个数据点,所以现在你计算原始点和你预测的线有多远。你可以用成本函数来计算。计算公式如下:
让我们分解一下,看看这是什么意思。
第一项 1/2m 是一个常数项,其中 m 表示我们已经拥有的数据点的数量,在我们的例子中是 3。然后我们有一个求和符号,这个符号意味着对于下标' I '中的每一个变化的值,我们不断地把结果相加。h(x^i 项表示我们的假设对于 I 的特定值的输出,换句话说,您使用等式 h(x)=θ0+xθ1 预测的线,而 y^i 项表示我们已经拥有的数据点的值。值“I”表示我们已经计算出的数据点的数量。为了更清楚地了解情况,我们来看一些例子:
中线
原始点有值(1,1),(2,2),(3,3)。
θ0 和θ1 分别预测为 0 和 1。利用假设方程我们画了一条线,现在要计算成本。我们画的这条线经过的点和我们已经知道的点完全一样。所以我们的假设值 h(x)是 1,2,3 并且 y^i 的值也是 1,2,3 。
我们可以看到,成本函数给我们的中间线为零。下面的红线是我们的假设线,黑点是我们的点。
上线
θ0 和θ1 分别预测为 1.5 和 1.25。这意味着 y 轴上的截距是 1.5,对于 x 轴上的每个单位机会,假设 h(x)在 y 轴上变化 1.25。
这样,我们计算出我们的 h(x)值如下— (1.5,2.75 和 4) 。而 y^i(原始数据点)保持不变— (1,2,3) 。使用成本函数,我们得到以下值:
下部线
下线条的θ0 和θ1 值分别为 1.25 和 0.75。这意味着它在 1.25 处截取 y 轴,并且对于 x 值的每个单位变化,假设 h(x)将以 0.75 的速率变化。
我们已经知道,原始点 y 的值是(1,2 和 3) ,我们预测的点 h(x)的值是-1.25,1.5,2。现在,使用成本函数我们可以计算成本,如下图所示。
降低成本函数
你还记得上面预测的θ-0 和θ-1 的值,因为它们只是预测,只有中间那个是完美的。但是在现实生活中,找到θ-0 和θ-1 的完美值几乎是不可能的。然而,你有能力操纵θ-0 和θ-1 的值,对于任何给定的一组值 (x1,x2,x3…xn) 您正在寻找具有最低成本函数值的线。
让我们得出θ-0 和θ-1 的不同值。θ-0 和θ-1 分别为 0 和 1.42。它创建的线看起来像下面这样。
但是,因为你需要降低成本,你需要创建一条符合这三点的线。大概是这样的:
所以你使用一种叫做梯度下降的降低成本的方法。永远记住,你只是减少θ-0 和θ-1 的值,通过这样做,你从那边的红线到下面的黑线。见下文,以便更好地理解。
因为我们知道改变θ-0 和θ-1 的值,所以线的方向可以改变,并且为了达到尽可能接近这三个点的线,我们一点一点地减少所有θ的值(在我们的情况下只有 2θ),以这样的方式,我们达到成本函数的最小值。
术语“阿尔法”的意思是——你的价值减少了多少。这里的θ-j 代表解中的每个θ,所以对所有θ都用这个方程,在我们的例子中,θ是 2,但也可以是 3,4 或 10,这取决于手头的问题。所以,上图中最上面的线有一定的θ-0 和θ-1 的值,然后,使用这里的公式,你将方程中所有θ的值减少一些α值,并随着你的预测线移动一点。然后你再次运行那个公式,减少θs 的值,看看那条线看起来像什么,计算成本,为下一次迭代做准备。然后你再降低θ的值,再看这条线,计算成本。你一直这样做,直到你的线到达成本最小的点,在我们的例子中,可以看到上面的图片值为 1,2,3。相对于原始数据点 1、2、3,成本为零的完美线条。公式的分解更有意义,见下图。
总结:
1-你有一些数据点。
2-使用它们,你可以计算θ的值,并使用假设方程绘制图形。
3-您使用成本函数计算成本,成本函数是您绘制的数据点和原始数据点之间的距离。
你看到成本函数给了你一些你想减少的值。
5-使用梯度下降,将θ的值减少α的量级。
6-使用一组新的θ值,再次计算成本。
7-你一个接一个地重复步骤 5 和步骤 6,直到你达到成本函数的最小值。
机器学习 101 和数据科学:来自行业专家的提示
向微软高级人工智能工程师学习数据科学的机器学习的基本组件。
作为一名实践数据科学家,你需要熟悉机器学习的概念。数据科学和机器学习都有重叠,但最基本的术语是:
- 数据科学用于获得对数据的洞察和理解。
- 机器学习用于基于数据产生预测。
也就是说,它们之间的界限并不明显,大多数数据科学从业者需要能够在这两个领域之间来回切换。
知道从哪里开始你的数据科学之旅可能会令人不知所措,因此在微软高级人工智能工程师 Samia Khalid 的帮助下,这篇文章将分解你在数据科学领域开始职业生涯所需要知道的事情。如果你正在寻找更深入和动手的东西,你可以访问 Samia 的交互式数据科学课程, 探索数据科学 。
以下是今天将要讲述的内容:
- 数据科学家必备的 Python 库
- Jupyter 笔记本快速提示:数据科学家的必备之物
- 面向数据科学家的机器学习 101
- 机器学习的主要组件
- 机器学习算法:分类和最常用的算法
- 机器学习项目清单
数据科学家必备的 Python 库
NumPy
NumPy (Numerical Python)是一个强大的、广泛用于存储和计算的库。它是为处理数字数据而设计的。它通过提供数据结构、算法和其他有用的工具,允许数据存储和计算。例如,这个库包含基本的线性代数函数、傅立叶变换和高级随机数功能。它还可以用于将数据加载到 Python 并从中导出。
以下是您应该开始熟悉的一些数字基础知识:
NumPy 基础知识
- 创建 NumPy 数组和数组属性
- 数组索引和切片
- 重塑和连接
NumPy 算法和统计基础
- 计算和聚合
- 比较和布尔掩码
熊猫
Pandas 是在数据科学项目中使用 Python 时不可避免的库。这是一个强大的数据辩论工具,这是一个准备数据的过程,以便可以实际用于分析和模型构建。
Pandas 包含各种各样的数据导入、导出、索引和数据操作功能。它还提供了方便的数据结构,如 DataFrames(一系列列和行,以及一系列(一维数组)),以及处理它们的有效方法。例如,它允许您重塑、合并、拆分和聚合数据。
以下是一些你应该开始熟悉的熊猫基本概念:
熊猫核心部件
- 系列对象
- DataFrame 对象
熊猫数据框操作
- 阅读、查看和提取信息
- 选择、切片和过滤
- 分组和排序
- 处理缺失和重复
- 数据透视表和函数
sci kit-学习
Scikit-learn 是一个易于使用的机器学习库。它附带了各种用于机器学习和统计建模的高效工具,例如:
- 分类模型(例如,支持向量机、随机森林、决策树)
- 回归分析(例如,线性回归、岭回归、逻辑回归)
- 聚类方法(例如,k 均值)
- 数据简化方法(例如,主成分分析、特征选择)
- 模型调整和,
- 具有网格搜索、交叉验证等功能的选择。它还允许对数据进行预处理。
Matplotlib 和 Seaborn
Matplotlib 广泛用于数据可视化练习,如绘制直方图、线图和热图。
Seaborn 是另一个很棒的库,用于创建有吸引力的、信息丰富的图形。它的目标是让数据探索和理解更容易,它做得很好。基本上,Seaborn 是基于 Matplotlib 的,Matplotlib 是它的孩子。
Jupyter 笔记本快速提示:数据科学家的必备之物
Jupyter 笔记本是开发和展示数据科学项目的一个非常强大和时尚的工具。它可以将代码及其输出集成到单个文档中,结合可视化、叙述性文本、数学方程和其他富媒体。简直牛逼。
Jupyter Notebook 也可以处理许多其他语言,比如 R。其直观的工作流程、易用性和零成本使其成为任何数据科学项目的核心工具。
面向数据科学家的机器学习 101
本节的要点:
- 介绍机器学习的基本概念。
- 了解几种最重要的机器学习算法,并对它们如何工作以及何时何地适用有一种直觉。
- 通过一个真实的端到端的例子来了解什么是必要的步骤,以及如何将它们应用到机器学习项目中。
机器学习的主要组件
训练机器学习系统需要三个基本组件:
数据
可以手动和自动收集数据。例如,用户的个人信息,如年龄和性别,他们的所有点击和购买历史都是在线商店的宝贵数据。你还记得迫使你“选择所有街道标志”的“ReCaptcha”吗?那是一些免费体力劳动的例子!数据不总是图像;它可以是具有许多变量(特征)、文本、传感器记录、声音样本等的数据表。,取决于手头的问题。
特征
特征通常也称为变量或参数。这些基本上是机器要考虑的因素——正在讨论的“对象”的属性,例如,用户的年龄、股票价格、租赁物业的面积、句子的字数、花瓣长度、细胞的大小。选择有意义的特性是非常重要的,但是需要实践和思考来决定使用什么样的特性,因为它们并不总是像这个小例子中那样清晰。
算法
机器学习是基于通用算法的。例如,一种算法是分类。分类允许您将数据放入不同的组中。有趣的是,用于识别手写数字的相同分类算法也可以用于将电子邮件分类为垃圾邮件和非垃圾邮件,而无需更改一行代码!这怎么可能呢?虽然算法是相同的,但是输入的数据不同,所以会产生不同的分类逻辑。然而,这并不意味着一种算法可以解决所有类型的问题!算法的选择对于确定最终机器学习模型的质量很重要。获取尽可能多的数据是开始使用机器学习系统非常重要的第一步。
机器学习算法:分类和最常用的算法
机器学习算法可以大致分为以下四类:
- 监督学习
- 无监督学习
- 半监督学习
- 强化学习
监督学习
在监督学习中,作为算法输入的训练数据包括最终的解决方案,称为标签或类别,因为算法通过“查看”具有正确答案的示例来学习。换句话说,该算法有一个主管或老师,他首先向它提供所有的答案,比如它是否是图片中的猫。而机器利用这些例子一个一个学习。
另一个不同类型的典型任务是根据一组特征(如大小、位置、卧室数量)预测目标数值(如房价)。为了训练该系统,您再次需要提供许多已知房价的正确示例,包括它们的特征和标签。
虽然对电子邮件进行分类或识别图片是猫还是狗是一种监督学习算法,但预测房价被称为回归。
有什么区别?
在回归中,输出是一个连续值或者像房价这样的小数。在分类中,输出是类似“垃圾邮件或非垃圾邮件”的标签,而不是十进制数;输出只接受像 0 或 1 这样的值,其中 1 表示“垃圾邮件”,0 表示“非垃圾邮件”。基本上,您选择的算法类型(分类或回归)取决于您想要的输出类型。
最常用的监督学习算法:
- 线性回归
- 逻辑回归
- 支持向量机
- 决策树
- 随机森林
- k-最近邻
- 人工神经网络
无监督学习
在无监督学习中,数据没有标签;该算法的目标是找到数据中的关系。这个系统需要在没有老师的情况下学习,并根据数据中的一些隐藏模式找到关系。这种类型的分割是所谓的聚类的一个例子,没有预定义的类别并且基于一些未知特征的分类。
最常用的无监督学习算法:
- 聚类:K 均值
- 可视化和降维
- 主成分分析(PCA),t 分布
- 随机邻居嵌入(t-SNE)
- 关联规则学习:先验
半监督学习
半监督学习处理部分标记的训练数据,通常是大量未标记的数据和一些标记的数据。大多数半监督学习算法是无监督和监督算法的结合。
强化学习
强化学习是一种特殊的更高级的类别,学习系统需要学习做出具体的决定。学习系统观察它所暴露的环境,它选择并执行动作,并得到奖励或惩罚作为回报。它的目标是选择随着时间的推移回报最大化的行动。因此,通过反复试验,并基于过去的经验,系统自己学习最佳策略,称为策略。
机器学习项目清单
你被聘为新的数据科学家,你有一个令人兴奋的项目要做!你应该怎么做呢?
这里有一些最佳实践和一个清单,当你在一个端到端的 ML 项目中工作时,你应该考虑采用。
- 把问题框起来,看大图:
- 正式和非正式地理解这个问题
- 弄清楚要问的正确问题以及如何设计这些问题
- 理解基于领域知识的假设
2.获取数据:不要忘记这里的数据隐私和合规性,它们至关重要!如有必要,提出问题并与利益相关者进行交流。
3.探索数据,获取真知灼见:
- 总结数据:找到变量的类型或绘制出基本的数据结构,找到变量之间的相关性,确定最重要的变量,检查数据中缺失的值和错误等。
- 将数据可视化,以便全面了解模式、趋势、异常和异常值。使用数据汇总和数据可视化技术来理解数据告诉你的故事。
4.从简单开始:从一个非常简单的模型开始,像线性或逻辑回归,具有最小的和突出的特征(直接观察和报告的特征)。这将让你对手头的问题有一个很好的了解,也为接下来的步骤设定正确的方向。
5.更多的特性工程:准备数据以提取更复杂的数据模式。合并和修改现有要素以创建新要素。
6.探索许多不同的模型,并根据比较评估筛选出最佳模型,例如,比较不同模型的 RMSE 或 ROC-AUC 得分。
7.微调模型的参数,并考虑组合它们以获得最佳结果。
8.以简单、吸引人、视觉上吸引人的方式向利益相关者展示您的解决方案。运用讲故事的艺术,它能创造奇迹!
- 记得根据目标受众的技术水平来定制您的演示文稿。例如,当向非技术利益相关者演示时,记住不要使用沉重的技术术语来传达关键的见解。他们可能不会对你采用的所有酷的 ML 技术感兴趣,而是对最终结果和关键见解感兴趣。
9.如果您的项目范围不仅仅是从数据中提取和展示见解,那么就继续启动、监控和维护您的系统。
当然,这个清单只是入门的参考。一旦你开始在真实的项目中工作,适应,随机应变,并且在每个项目结束时反思收获,从错误中学习是必不可少的!
从这里去哪里?
我们已经为数据科学家介绍了一些机器学习的基础知识,但如果你真的想开始你的职业生涯,还有很多东西需要学习和探索,你不必独自经历这些。
行业专家、微软高级人工智能工程师萨米亚·哈立德(Samia Khalid)将自己的所学编成了一门综合课程, 钻研数据科学 。Samia 在一个地方列出了您在数据科学职业生涯中起步和发展所需的一切。
快乐学习!
机器学习 101-ID3 决策树与熵计算(1)
这一系列包括我在博士课程阶段收集的机器学习课程笔记
培训方法
机器学习训练方法分为 3 种;
- 监督学习
- 无监督学习
- 强化学习
ID3 决策树
- 这种方法被称为监督和非参数决策树类型。
- 大多数情况下,它用于分类和回归。
- 一棵树由一个中间决策节点和末端叶子组成。终端叶子有输出。输出显示分类中的类值,但显示回归的数值。
- 将子集划分为决策树的目的是使每个子集尽可能的相似。决策树算法的缺点是它们是贪婪的方法。贪婪算法是任何遵循问题解决启发法的算法,在每个阶段做出局部最优选择,目的是找到全局最优。在许多问题中,贪婪策略通常不会产生最优解,但是贪婪启发式算法可以在合理的时间内产生近似全局最优解的局部最优解。
熵
熵被称为决策树的控制器,用于决定在哪里拆分数据。ID3 算法使用熵来计算样本的同质性。如果样本是完全同质的,则熵为零,如果样本是等分的,则熵为 1[1]。
n 类熵-> E(S) = ∑ -(pᵢ*log₂pᵢ)
二类熵:(S) =-(p₁ * log₂p₁ + p₂ * log₂p₂)
例 1:
9 samples in the Class 1 and 5 samples in the Class 2
p₁ = 9/(9+5) =9/14(样本与 1 类在同一训练类中的概率)
p₂ = 5/14(与 2 类在同一个培训类中的样本的概率)
e =-(2014 年 9 月 14 日* log₂(9/14)+(2014 年 5 月* log₂(5/14))
E = 0.94
信息增益
根、节点和叶的边界由信息增益(IG)定义。
增益(S,A) = E(前)- G(后 _ 分裂)
注意:你可以在 WEKA 工具里找到 ID3 作为 C4.5。
例 2:
首先,选择以最精确的方式分割整个表的特征。为此,应确定增益最高的特性。【T10 个训练示例的值划分如下:
- 6 电影院
- 2 网球
- 1 房子
- 1 购物
熵值必须从这些值开始计算,以定义根特征。
e(S)=-((6/10)* log2(6/10)+(2/10)* log2(2/10)+(1/10)* log2(1/10)+(1/10)* log2(1/10))
E(S) = 1.571
通过计算所有单个特征的增益值,具有最高增益值的特征被选为根节点:
增益(S,天气)=?
Sunny = 3 (1 家电影院+ 2 网球)
风= 4 (3 家电影院+ 1 购物)
雨天= 3 (2 家电影院+ 1 家)
熵(Ssunny)=—(1/3)* log2(1/3)—(2/3)* log2(2/3)= 0.918
熵(S 风大)=—(3/4)* log2(3/4)—(1/4)* log2(1/4)= 0.811
熵(S 多雨)=—(2/3)* log2(2/3)—(1/3)* log2(1/3)= 0.918
Information Gain Formula
Gain(S,Weather)= 1.571—(((1+2)/10)* 0.918+((3+1)/10)* 0.811+((2+1)/10)* 0.918
增益(S,天气)= 0.70
Gain(S,Parental_Availability) =?
是= 5 (5 家电影院)
否= 5 (2 个网球+ 1 个电影院+ 1 个购物+ 1 个家)
熵(S 是 ) = - (5/5)*log2(5/5) = 0
熵(Sno)=-(2/5)* log2(2/5)-3 (1/5) log2(1/5)= 1.922
增益(S,Parental_Availability) =熵(S) — (P(是)熵(S 是 ) + P(否)熵(S 否))
Gain(S,Parental _ avail ability)= 1.571—((5/10)熵(S 是)+(5/10)熵(S 否))
Gain(S,Parental _ avail ability)= 0.61
收益(S,财富)=?
有钱= 7 (3 家电影院+ 2 网球+ 1 购物+ 1 家居)
差= 3 (3 西内马)
熵(S 富 ) = 1.842
熵(S 差 )=0
增益(S,财富)=熵(S)——(P(富)熵(S 富 ) + P(穷)熵(S 穷))
增益(S,财富)= 0.2816
最后,逐一列出所有增益值,并选择具有最高增益值的特征作为根节点。在这种情况下,天气有最高的增益值,所以它将是根。
增益(S,天气)= 0.70
增益(S,Parental_Availability) = 0.61
增益(S,财富)= 0.2816
如上面的例子所示,在选择根之后,特征的每个单独的值被确定为叶,并且这一次用这些单独的值定制数据集。换句话说,上表已被转换为一个单独的数据集,显示天气晴朗时其他要素可以采用的值。因此,根据该表,当天气晴朗时,inter 节点的可能类别如下:
- 1 家电影院
- 2 网球
熵(Ssunny)=-(1/3)* log2(1/3)-(2/3)* log2(2/3)= 0.918
Gain(S sunny ,Parental_Availability) =?
增益(S sunny ,Parental_Availability) =熵(Ssunny)——(P(是| Ssunny)熵(S 是 ) + P(否| Ssunny)熵(S 否)
熵(S 是 ) = -(1/3)*log2(0) — 0 = 0
熵(Sno)=-(2/3)* log2(0)—0 = 0
增益(S sunny ,Parental _ avail ability)= 0.928—((1/3)* 0+(2/3)* 0)=0.928
增益(S 晴,财富)= 0.918—((3/3)* 0.918+(0/3)* 0)=0
因为 Parental_Availability 特性的增益更大,所以晴天状态的叶子将是 Parental_Availability 。根据为晴天条件设置的数据,如果是,将决定电影院,如果不是,则将决定网球:
当对刮风和下雨的情况进行同样的计算时,最终的决策树就完成了。
过度拟合
- 这是学习到记忆的转变。
- 性能图是在某个时刻之后,性能的增加停止并开始减少。
- 当你的培训成功率很高,而测试成功率却相反时,就是过度适应的例子。
- 此外,如果我们的数据中存在噪声样本,可能会导致过拟合。
- 当树长得太大时,几乎每个可能的分支都会产生一个结果,这会导致过度拟合。
为了避免过度修剪,有必要在树生长时或树形成后修剪。
参考文献:
[1]决策树,https://www.saedsayad.com/decision_tree.htm
机器学习 101 -朴素贝叶斯(2)
这是我的机器学习 101 系列的第二部分,在我的系列的第一篇文章中,我试图解释决策树和熵计算。下面是链接:机器学习 101- (1)
条件概率
在概率论中,条件概率是一个事件发生的概率的度量,假设又有一个事件发生。更具体地说,P(B|A)隐含着 A 发生时 B 的概率。
The formula of conditional probability
贝叶斯规则
Bayesian Rule
最大后验概率
它用于估计未知的决策。对于所有给定的数据,在所有假设中选择哪个类别的可能性更大。
The formula of Maximum A Posteriori
如果你不明白为什么分母在公式中被忽略,不要担心,下面的例子会让你明白。
Ex:
- P(class=+|cancer)=0.98(患者被诊断为癌症的概率,并且测试结果也是癌症(+)
- P(class= — |cancer)=0.97(患者被诊断为非癌症的概率,并且测试结果也不是癌症(—))
- p(癌症)= 0.008(被诊断为癌症的患者比率)
根据给定的约束条件,一个检测结果为阳性的患者属于癌类还是不属于癌(cancer)类?
P(?|class=+)=?
一个类中给定概率的总和应该总是 1so;
P(_ 癌 _) = 1- P(癌)
所以;
p(_ cancer _)= 1–0.008 = 0.992
P(cancer | class =+)=(0.98 * 0.008)/P(class =+)=0.008/P(class =+)
P(_ cancer _ | class =+)= 0.03 * 0.992/P(class =+)=0.02976/P(class =+)
由于 0.02976 大于 0.008,P(?|class=+)=cancer
我们忽略了 P(class=+),因为它是两种情况下的共同常数。即使我们把 P(class=+)计算在内,结果也不会改变。
朴素贝叶斯定理
朴素贝叶斯定理认为所有的特征都是相互独立的。朴素贝叶斯是文本分类的首选,其成功率相当高。
The formula of Naive Bayes
例如:根据下表中的数据集,对杂志促销说是,对手表促销说是,对人寿保险说否,对信用卡保险说否的人是什么性别?
[1]
问题的简化版本;如果(是,是,不是,不是)->性别=?
我们有两个假设需要检验,结果是男(M)还是女(F)?为此,我们将分别计算两者的结果(因为它们互不影响),并选择值较大的一个作为答案。
X =(是,是,否,否)
假设 1:
在第一个假设中,我们接受性是男性的,并根据它寻找结果。
P(sex=M|X)=?由于右侧概率首先由独立的特征组成,我们将分别找到每个特征的概率结果,然后将它们相乘以获得最终的解。
P(magazine_promotion=Y|sex=M)(一个是男性的人对杂志促销说“是”的概率)= 4/6(一个是男性的人对杂志促销说“是” / 男性总数)P(watch _ Promotion = Y | sex = M)= 2/6
P(life _ insurance = N | sex = M)= 4/6
P(credit _ card _ insurance = N | sex = M)= 4/6
既然都是独立功能:
P(X | sex = M)= P(magazine _ promotion = Y | sex = M)* P(watch _ promotion = Y | sex = M)* P(life _ insurance =N|sex=M)* P(信用卡 _ 保险= N | sex = M)
P(X | sex = M)=(4/6)(2/6)(4/6)*(4/6)= 0.0988
P(sex = M)= 0.6
P(sex = M | X)= 0.0988 * 0.6 =0.0593
假设二:
最后,在第二个假设中,我们接受性是男性的,并根据它寻找结果。
p(X | sex = F)=(3/4)(2/4)(1/4)*(3/4)= 0.07
p(性别=F)=0.4
P(sex=F|X)= 0.0281
由于 0.0593 > 0.0281,贝叶斯分类器得出男的可能性较高。
拉普拉斯平滑
例如,如果我们使用朴素贝叶斯对电子邮件中的单词进行分类,并确定该邮件是垃圾邮件还是良性邮件。当我们遇到一个不包含在训练集中的单词时,该值将被赋为 0。而概率值会以 0 结束,因为乘法计算中 0 占优势。在这种情况下,可以使用拉普拉斯(1-up)平滑。
例如:
A 类:“猫蟹呱呱叫下楼梯”
B 类:《下着倾盆大雨》
根据上面的分类,对 X =“猫吃老鼠,狗吃兔子骨头”的下列文字进行分类
词汇= {猫、蟹、小曲、楼梯、雨、狗}
P(vⱼ) = 1/2(班级将是 a 或 b,所以一半的机会)
|Vocab|=6
nA=4
nB=3
在 X 文本中,猫和狗的单词是在词汇中发现的唯一的单词。所以我们只使用它们:
e=ij
P(xᵢ|vⱼ)=(nₑ+ 1)/(nⱼ + 6)
假设 1: P(A|X) = P(A)P(猫|A)P(狗| A)= 1/2 (1+1)/(4+6)(0+1)/4+6 =0.01
假设二: P(B|X) = P(B)P(猫|B)P(狗| B)= 1/2 (1+1)/(3+6)(1+1)/(3+6)=0.024
因为 0.024>0.01,所以 X 文本属于 B 类
参考
[1]http://www.cs.ust.hk/~qyang/521/Readings/sample06.html
机器学习 101:使用逻辑回归预测 R
机器学习:监督学习
基础、链接功能和图
Mike MacKenzie on Flickr
执行摘要
- 广义线性模型(GLM)
- 三种类型的链接函数:Logit、Probit 和互补双对数(cloglog)
- 建立逻辑回归来预测药物使用并比较这三种类型的 GLM
在机器学习 101 课程中,统计学教授介绍了线性回归后的 GLM,作为成为数据科学家的下一个垫脚石。GLM 有几种形式,最著名的是 logit、probit 和 cloglog。
这些 glm 非常适合分类问题:生存还是死亡,投票还是不投票,点击还是不点击。
完整的项目描述和完整的 R 代码,请查看我的 Github 。
基础知识
通常,二进制数据的 GLM 可以用以下形式表示:
其中 g 表示概率 p 的预测值(在右边)的线性关系,g 是将 p ∈[0,1]映射到ℝ.的函数
有三种方法可以连接左侧和右侧的组件。
Logit:
在文字中,p 的对数形式。
概率单位:
换句话说,正态分布的累积密度函数的倒数。
Cloglog:
换句话说,不发生概率的对数形式的负值的对数形式。迷茫?至少,我是。这个函数的链接功能很简单。
好吧,让我们继续,建立 GLM 模型来预测谁更容易吸毒,并学习阅读情节。
Photo by Nicole Honeywill / Sincerely Media on Unsplash
- 加载、清理和分割数据集
library(readr)
drug_use <- read_csv(‘drug.csv’,col_names=c(‘ID’,’Age’,’Gender’,’Education’,’Country’,’Ethnicity’,’Nscore’,’Escore’,’Oscore’,’Ascore’,’Cscore’,’Impulsive’,’SS’,’Alcohol’,’Amphet’,’Amyl’,’Benzos’,’Caff’,’Cannabis’,’Choc’,’Coke’,’Crack’,’Ecstasy’,’Heroin’,’Ketamine’,’Legalh’,’LSD’,’Meth’,’Mushrooms’,’Nicotine’,’Semer’,’VSA’))
library(dplyr)
drug_use <- drug_use %>% mutate_at(as.ordered, .vars=vars(Alcohol:VSA))
drug_use <- drug_use %>%
mutate(Gender = factor(Gender, labels=c(“Male”, “Female”))) %>%
mutate(Ethnicity = factor(Ethnicity, labels=c(“Black”, “Asian”, “White”,
“Mixed:White/Black”, “Other”,
“Mixed:White/Asian”,
“Mixed:Black/Asian”))) %>%
mutate(Country = factor(Country, labels=c(“Australia”, “Canada”, “New Zealand”,
“Other”, “Ireland”, “UK”,”USA”)))#create a new factor variable called recent_cannabis_use
drug_use = drug_use %>%
mutate(recent_cannabis_use=as.factor(ifelse(Cannabis>=”CL3",”Yes”,”No”)))#create a new tibble that includes a subset of the original variable
#data split into training and test sets
drug_use_subset <- drug_use %>% select(Age:SS, recent_cannabis_use)
set.seed(1)
traint.indices = sample(1:nrow(drug_use_subset),1500)
drug_use_train = drug_use_subset[traint.indices,]
drug_use_test = drug_use_subset[-traint.indices,]
dim(drug_use_train)
dim(drug_use_test)[1] 1500 13
[1] 385 13
因此,训练集的尺寸为 150013,测试集的尺寸为 38513。
2。拟合逻辑回归
#use logit as the link function
glm_fit = glm(recent_cannabis_use ~ .,data=drug_use_train,family=binomial(link= “logit”))
summary(glm_fit)Call:
glm(formula = recent_cannabis_use ~ ., family = binomial(link = "logit"),
data = drug_use_train)
Deviance Residuals:
Min 1Q Median 3Q Max
-3.0024 -0.5996 0.1512 0.5410 2.7525
Coefficients:
Estimate Std. Error z value Pr(>|z|)
(Intercept) 1.33629 0.64895 2.059 0.039480 *
Age -0.77441 0.09123 -8.489 < 2e-16 ***
GenderFemale -0.65308 0.15756 -4.145 3.40e-05 ***
Education -0.41192 0.08006 -5.145 2.67e-07 ***
CountryCanada -0.67373 1.23497 -0.546 0.585377
CountryNew Zealand -1.24256 0.31946 -3.890 0.000100 ***
CountryOther 0.11062 0.49754 0.222 0.824056
CountryIreland -0.50841 0.69084 -0.736 0.461773
CountryUK -0.88941 0.39042 -2.278 0.022720 *
CountryUSA -1.97561 0.20101 -9.828 < 2e-16 ***
EthnicityAsian -1.19642 0.96794 -1.236 0.216443
EthnicityWhite 0.65189 0.63569 1.025 0.305130
EthnicityMixed:White/Black 0.10814 1.07403 0.101 0.919799
EthnicityOther 0.66571 0.79791 0.834 0.404105
EthnicityMixed:White/Asian 0.48986 0.96724 0.506 0.612535
EthnicityMixed:Black/Asian13.07740 466.45641 0.028 0.977634
Nscore -0.08318 0.09163 -0.908 0.363956
Escore -0.11130 0.09621 -1.157 0.247349
Oscore 0.64932 0.09259 7.013 2.33e-12 ***
Ascore 0.09697 0.08235 1.178 0.238990
Cscore -0.30243 0.09179 -3.295 0.000984 ***
Impulsive -0.14213 0.10381 -1.369 0.170958
SS 0.70960 0.11793 6.017 1.78e-09 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
的解释很简单,也是重要的变量
包括:年龄、女性、教育程度、国家变量(ZJ、英国、美国)、oscore、分数和 SS。
3。Probit 和 cloglog
#probit link function
glm_fit_probit = glm(recent_cannabis_use ~ .,data=drug_use_train,family = binomial(link = “probit”))
prob_training_probit = predict(glm_fit_probit, type=”response”)#c-log-log” link
glm_fit_clog = glm(recent_cannabis_use ~ .,data=drug_use_train,family = binomial(link = “cloglog”))
prob_training_clog = predict(glm_fit_clog, type=”response”)
4。比较这三个图
# compare logit and probit
plot(prob_training_logit,prob_training_probit,xlab = “Fitted Values of Logit Model”,ylab= “Fitted Values of Probit Model”, main= “Plot 1: Fitted Values for Logit and Probit Regressions”, pch=19, cex=0.2,abline(a=0,b=1,col=”red”))
众所周知,probit 和 logit 预测几乎相同的值,因为它们紧密地排列在 45 度线上。可能,唯一的区别在于 0.5 到 0.8 之间的中间范围,其中 probit 模型预测的值略低于 abline。
# compare logit and cloglog
plot(prob_training_logit,prob_training_clog,xlab = “Fitted Values of Logit Model”,ylab= “Fitted Values of Cloglog Model”, main= “Plot 2: Fitted Values for Logit and Cloglog Regressions”, pch=19, cex=0.2,abline(a=0,b=1,col=”red”))
这是一个有趣的情节。C-loglog 在早期生成的预测值较高,随后是比中间范围的 logit 更低的离散预测值。
在机器学习中,逻辑回归是数据科学家可以应用的 101 技术。
喜欢读这本书吗?
还有,看看我其他关于人工智能和机器学习的帖子。
机器学习 102:具有多项式特征的逻辑回归
机器学习:监督学习
有非线性成分时如何分类
Photo by Harley-Davidson on Unsplash
数据科学家是摇滚明星!
摇滚!
在我之前的 ML 101 文章中,我解释了我们如何应用逻辑回归来分类线性问题。在这篇文章中,我想通过包含非线性特征来使事情变得复杂一点。就像现实世界一样,事物盘根错节,杂乱无章。
让我们深入研究一下 r。
# Load the dataset
library(tidyverse)
data5 = read_csv("nonlinear.csv")
require(ggplot2)
qplot(X1,X2,colour = Y,data=data5)
我们可以看到,黑点被蓝点包围着。我们的工作是找到一种 ML 技术来巧妙地分离这两种类型的点。
# build a regular logistic regression
glm_5b = glm(Y~X1+X2,data=data5)
summary(glm_5b)Call:
glm(formula = Y ~ X1 + X2, data = data5)Deviance Residuals:
Min 1Q Median 3Q Max
-0.6944 -0.5504 0.1937 0.3584 0.6213 Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 0.71038 0.05672 12.524 <2e-16 ***
X1 -0.05446 0.02496 -2.182 0.0325 *
X2 0.04278 0.02708 1.580 0.1187
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1(Dispersion parameter for gaussian family taken to be 0.2109993) Null deviance: 16.000 on 71 degrees of freedom
Residual deviance: 14.559 on 69 degrees of freedom
AIC: 97.238Number of Fisher Scoring iterations: 2
可以看出,常规逻辑回归没有考虑非线性特征,并且表现不佳。
接下来,让我们将类标签投影到精细采样的网格点上,并在网格上用类标签着色的每个点上绘制预测。
# grid of points over sample space
gr <- expand.grid(X1=seq(-5, 5, by=0.1), # sample points in X1
X2=seq(-5, 5, by=0.1)) # sample points in X2#predict class label
probability_pred = predict(glm_5b,gr,type=”response”)# set the cutoff point at 0.5
class_pred = as.factor(ifelse(probability_pred<=0.5, “0”, “1”))
color_array <- c(“red”, “blue”)[as.numeric(class_pred)]
plot(gr,col=color_array,pch=20,cex=0.25)
从上面的图来看,一个常规的逻辑回归模型并没有那么好。
让我们包括 x1 和 x2 的二次多项式项。
glm_5c =glm(Y~poly(X1,deg=2)*poly(X2,deg=2),data=data5)
summary(glm_5c)
probability_pred_5c = predict(glm_5c,gr,type=”response”)
class_pred_5c = as.factor(ifelse(probability_pred_5c<=0.5, “0”, “1”))
color_array_5c <- c(“red”, “blue”)[as.numeric(class_pred_5c)]
plot(gr,col=color_array_5c,pch=20,cex=0.25)
从 ANOVA 输出可以看出,以下变量具有统计显著性:X1、X1、X2、X2、X1*(X2)和(X1) *(X2)。由于二阶项意义重大,我们无法进行简单的线性分类。
此外,从图中可以看出,具有更高项的逻辑斯蒂模型比简单模型表现得更好。
为了安全起见,让我们尝试一个没有任何交互项的 5 次多项式逻辑模型。
glm_5d =glm(Y~poly(data5$X1,deg=5)+poly(data5$X2,deg=5),data=data5)
summary(glm_5d)Call:
glm(formula = Y ~ poly(data5$X1, deg = 5) + poly(data5$X2, deg = 5),
data = data5)Deviance Residuals:
Min 1Q Median 3Q Max
-0.51652 -0.15930 -0.06256 0.17439 0.73943 Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 0.66667 0.03309 20.145 < 2e-16 ***
poly(data5$X1, deg = 5)1 -0.70547 0.30163 -2.339 0.02264 *
poly(data5$X1, deg = 5)2 0.94681 0.28791 3.289 0.00167 **
poly(data5$X1, deg = 5)3 0.82225 0.28386 2.897 0.00523 **
poly(data5$X1, deg = 5)4 -0.24777 0.29833 -0.831 0.40948
poly(data5$X1, deg = 5)5 -0.00171 0.29624 -0.006 0.99541
poly(data5$X2, deg = 5)1 0.62673 0.28989 2.162 0.03456 *
poly(data5$X2, deg = 5)2 1.70311 0.30479 5.588 5.69e-07 ***
poly(data5$X2, deg = 5)3 -1.60001 0.29074 -5.503 7.84e-07 ***
poly(data5$X2, deg = 5)4 -0.83690 0.28945 -2.891 0.00531 **
poly(data5$X2, deg = 5)5 0.88545 0.29321 3.020 0.00369 **
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1(Dispersion parameter for gaussian family taken to be 0.07885262) Null deviance: 16.00 on 71 degrees of freedom
Residual deviance: 4.81 on 61 degrees of freedom
AIC: 33.498Number of Fisher Scoring iterations: 2probability_pred_5d = predict(glm_5d,gr,type=”response”)
class_pred_5d = as.factor(ifelse(probability_pred_5d<=0.5, “0”, “1”))
color_array_5d <- c(“red”, “blue”)[as.numeric(class_pred_5d)]
plot(gr,col=color_array_5d,pch=20,cex=0.25)
五次多项式不会提高性能。
综上所述,让我们从偏倚和方差权衡的角度来比较所比较的模型。
没有交互作用和高阶项的一般 logistic 模型具有最低的方差,但具有最高的偏差。
具有 5 阶多项式项的模型具有最高的方差和最低的偏差。
具有二阶多项式和交互项的模型在偏差-方差权衡方面表现最佳。
# let's create three additional bootstrap replicates of the original dataset and fit regression models to the replicates.
Boot_sample_5f <- lapply(1:3,function(i)data5[sample(1:nrow(data5),replace = TRUE),])
for (i in 1:3) {
glm_5b = glm(Y~X1+X2,data=Boot_sample_5f[[i]])
probability_pred_5f = predict(glm_5b,gr,type=”response”)
class_pred_5f = as.factor(ifelse(probability_pred_5f<=0.5, “0”, “1”))#plot class predictions on the grid of values for each of both linear and 5th order modelscolor_array_5f <- c(“red”, “blue”)[as.numeric(class_pred_5f)]
plot(gr,col=color_array_5f,pch=20,cex=0.25)
}# the 5th order polynomial term.
Boot_sample_5f_2 <- lapply(1:3,function(i)data5[sample(1:nrow(data5),replace = TRUE),])for (i in 1:3) {
glm_5order = glm(Y~poly(data5$X1,deg=5)+poly(data5$X2,deg=5),data=Boot_sample_5f_2[[i]]) probability_pred_5order = predict(glm_5order,gr,type=”response”)
class_pred_5order = as.factor(ifelse(probability_pred_5order<=0.5, “0”, “1”))
color_array_5order <- c(“red”, “blue”)[as.numeric(class_pred_5order)]
plot(gr,col=color_array_5order,pch=20,cex=0.25)
}
Plots 1–3
Plots 4–6
从图 1-3 中,网格被一条直线分成两部分,指的是大偏差和小方差。
从图 4-6 中,我们观察到一个相反的模式:它有一个小的偏差,因为有更多的变量来最小化预测和真实值之间的距离。它有很大的差异,因为点分布在整个图表。
Medium 最近进化出了自己的 作家伙伴计划 ,支持像我这样的普通作家。如果你还不是订户,通过下面的链接注册,我会收到一部分会员费。
[## 阅读叶雷华博士研究员(以及其他成千上万的媒体作家)的每一个故事
作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…
leihua-ye.medium.com](https://leihua-ye.medium.com/membership)
喜欢读这本书吗?
还有,看看我其他关于人工智能和机器学习的帖子。
机器学习:管理风险的实用指南
本文的最终目的是让数据科学和合规团队能够创建更好、更准确、更合规的 ML 模型。
Photo by Riley McCullough on Unsplash
机器学习(ML)的使用越来越多,由此引发的一个基本问题正在迅速成为全球数据驱动型组织、数据科学家和法律人员面临的最大挑战之一。这一挑战以各种形式出现,从业者和学者也以各种方式进行了描述,但都与断言模型输入之间的因果关系以及输入数据如何影响模型输出的基本能力有关。
据贝恩公司称,未来几年,仅美国在自动化方面的投资就将接近 8 万亿美元,其中许多投资都是基于 ML 的最新进展。但是这些进步远远超过了管理这项技术的法律和道德框架。对于管理与洗钱相关的风险——法律的、声誉的、道德的等等——根本没有一个公认的框架。
这篇文章旨在提供一个在实践中有效管理这种风险的模板,目的是为律师、合规人员、数据科学家和工程师提供一个框架,以安全地创建、部署和维护 ML 模型,并在这些不同的组织视角之间实现有效的沟通。本文的最终目的是让数据科学和合规团队能够创建更好、更准确、更合规的 ML 模型。
关键目标&三道防线
涉及 ML 的项目从一开始就有明确的目标,将处于最有利的地位。为此,所有 ML 项目都应该从清晰记录的初始目标和潜在假设开始。这些目标还应包括主要的期望和不期望的结果,并应在所有关键利益相关方之间传阅。例如,数据科学家可能最适合描述关键的预期结果,而法律人员可能描述可能导致法律责任的具体的不期望的结果。这样的结果,包括适当用例的清晰边界,应该从任何 ML 项目的开始就很明显。此外,模型的预期消费者——从个人到采用其建议的系统——也应该明确指定。
一旦总体目标明确,就应该清楚地列出三道“防线”。防线—指数据科学家和其他参与创建、部署和审计 ML 过程的人员的角色和职责。例如,在整个模型生命周期中,多方的“有效挑战”作为一个关键步骤的重要性,必须与模型开发本身相区别。这些措施的最终目标是开发指导多层人员评估模型的过程,并确保模型的安全性。概括地说,第一条线集中于模型的开发和测试,第二条线集中于模型验证、法律和数据审查,第三条线集中于定期审计。防线应由以下五个角色组成:
- 数据所有者:负责模型使用的数据,通常被称为“数据库管理员”、“数据工程师”或“数据管家”
- 数据科学家:创建和维护模型。
- 领域专家:拥有模型所要解决的问题的专业知识,也被称为“企业所有者”
- 验证者:审核和批准由数据所有者和数据科学家创建的工作,重点关注技术准确性。通常,验证者是数据科学家,他们与手头的特定模型或项目无关。
- 治理人员:审查和批准由数据所有者和数据科学家创建的工作,重点关注法律风险。
一些组织依靠模型治理委员会(代表受特定模型部署影响的一系列利益相关者)来确保上述每个组的成员履行他们的职责,并且在部署任何模型之前,适当的防线已经就位。虽然有所帮助,但这种审查委员会也可能阻碍高效和可扩展的生产。因此,执行领导的模型评审委员会应该将他们的重点转移到围绕上述每个组的角色和职责的开发和实现过程上。这些委员会应在执行这些流程之前以及在定期的事后审计中制定和审查这些流程,而不是在部署之前单独审查每个模型。
至关重要的是,这些建议应该在不同的程度上实施,与每个模型相关的总体风险相一致。每个模型都有不可预见的风险,但有些部署比其他部署更有可能出现偏差并导致不良后果。因此,建议将审查的深度、强度和频率纳入特征因素,包括模型的预期用途和任何使用限制(如消费者选择退出的要求)、模型对个人权利的潜在影响、模型的成熟度、培训数据的质量、可解释性水平以及测试和审查的预测质量。
关注数据输入
一旦适当的角色和过程已经就位,在培训和部署期间,没有比理解模型所使用的数据更重要的风险管理方面了。在实践中,维护这种数据基础设施——从数据到模型的管道——是治理 ML 的最关键的方面之一,也是最容易被忽视的方面。一般来说,基础数据的有效风险管理应基于以下建议:
- 记录模型需求:所有模型都有需求——从数据的新鲜度,到所需的特定特性,到预期的用途,以及更多可能影响模型性能的需求,所有这些都需要清楚地记录下来。这使得验证者能够正确地审查每个项目,并确保模型可以随着时间的推移和跨人员进行维护。同样,数据依赖将不可避免地存在于将数据输入模型的周围系统中;如果存在这些依赖性,就应该对它们进行记录和监控。此外,文档应包括对个人身份信息的位置、原因、数据保护方式(通过加密、哈希或其他方式)以及数据可追溯性的讨论。
- 数据质量评估:了解输入模型的数据质量是模型风险的关键组成部分,应该包括对有效性、准确性、完整性、及时性、可用性、可再现性、一致性和来源的分析。许多风险管理框架依赖于所谓的“交通灯系统”来进行这种类型的评估,它利用红色、琥珀色和绿色来创建一个可视化的仪表板来表示这种评估。
- 封装模型:将模型从底层基础设施中分离出来,可以对模型本身和周围的流程进行严格的测试。为此,每个步骤——从配置到特性提取,再到服务基础设施等等——都应该清楚地记录下来,并且清楚地封装起来,这样调试和更新就不会太复杂。通常,这种复杂性随着模型部署周期的推移而增加,并且是使用 ML 的最大风险来源之一。
- 底层数据监控:应该监控输入数据以检测“数据漂移”,即生产数据不同于训练数据,重点是这种漂移如何影响模型性能。用于训练模型的数据应该以统计方式表示,并且在部署期间获取的数据应该与这种表示进行比较。还应该对模型进行彻底的留一要素评估,这可以突出基础数据中最具决定性的要素。这些评估可用于了解是否应格外小心地监控数据中的特定功能,以及模型可能不需要摄取的潜在未充分利用的功能。
- 使警报具有可操作性:监控底层数据允许检测模型行为中潜在的不期望的变化——但是监控只和现有的警报系统一样有用。建议警报会通知第一道防线中的数据所有者和数据科学家,并且会保存所有警报以用于记录目的,以便第二道防线和第三道防线的审查者可以审核警报是如何生成的以及它们是如何超时响应的。
使用模型输出数据作为进入模型的窗口
了解模型的输出(在培训期间和部署后)对于监控其健康状况和任何相关风险至关重要。为此,建议数据所有者、数据科学家、验证者和治理人员:
- 暴露偏差:数据可能不准确地代表真实世界,例如当数据集以系统的方式忽略或隔离了一部分人口时。数据也可能以对特定群体有害的方式反映社会衍生的产物。因此,从模型中消除偏差并不总是可行的,而是寻求量化该偏差,并在可能的情况下将其最小化。对于人类受试者的数据,也许可以通过将私人持有的数据集与公共信息(如来自国家统计局的信息)相互参照来验证输出结果。在这种验证不可行的情况下,应用于数据的策略可能还需要限制敏感数据(如关于种族或性别的数据),并且应该执行输出分析以检测敏感特征的潜在替代(如邮政编码)。干扰输入数据中的敏感特征,并使用生成的模型输出来确定模型对这些敏感特征的依赖程度,此外还检测充当代理的任何特征(如年龄)的存在。实际上,检测偏差需要对模型输入和输出进行混合数据分析。对偏差的评估应该发生在模型设计和实现的所有阶段,并且贯穿每一条防线。
- 持续监控:模型的输出应该以统计方式表示,就像模型接收的底层培训和部署数据一样。这将需要清楚地了解每个模型的决策存储在哪里,并在训练期间建立正确行为的统计“基础事实”。在某些情况下,这些表示将能够及时发现异常检测或模型不当行为。这些表示还有助于检测输入数据是否偏离了训练数据,并可以指示何时应该在刷新的数据集上重新训练模型。这些方法的全面影响将有所不同,例如,取决于模型在部署期间是否继续训练,以及许多其他因素,但它们将实现更快的风险评估、调试和更有意义的警报。
- 检测反馈循环:当一个模型的行为影响到它用来更新其参数的数据时,就会出现反馈循环。例如,当内容选择系统和广告选择系统存在于同一页面上,但是不共享参数并且没有被联合训练时,这可能发生。随着时间的推移,这两个选择系统会相互影响,尤其是当两个系统都在不断更新其内部参数时。检测这样的反馈循环可能具有挑战性并且耗时。部署多个模型的组织在监控模型输出时应该特别注意这种现象,这些模型可能会随着时间的推移而相互影响。
- 记录所有测试:所有此类分析和测试,尤其是侧重于模型中的偏差的测试,都应该清楚地记录下来——既可以作为尝试最小化或避免不希望的结果的证据,也可以帮助第二道和第三道防线的成员评估和理解项目的开发和潜在风险。测试文档应详细说明谁进行了测试、测试的性质、审查和响应过程,并描述测试发生的阶段。至关重要的是,第一道、第二道和第三道防线的每一个成员都应该很容易获得所有这些文档。使这个文档易于访问将有助于确保测试是彻底的,并将使参与模型部署的每个人清楚地理解相关的风险。
与上述关于底层数据转移的建议一样,可操作的警报也应该是监控模型输出的优先事项。这些警报必须由正确的人员接收,并且必须保存以备审计。
结论
有效的洗钱风险管理是一个持续的过程。虽然这篇文章关注的是单个模型的部署,但是在实践中可能会一次部署多个模型,或者同一个团队可能负责生产中的多个模型,所有这些模型都处于不同的阶段。因此,拥有一个所有相关人员都能轻松访问的模型清单至关重要。随着时间的推移,模型或底层数据或基础设施通常会发生变化,这些变化也应该很容易被发现。如上所述,某些更改应该会生成特定的警报。
在创建、测试、部署和审计生产 ML 的过程中,没有一个时间点可以将模型“认证”为没有风险。然而,有许多方法可以在整个生命周期中完整地记录和监控 ML,以保持风险可控,并使组织能够应对影响此风险的因素的波动。
为了取得成功,组织需要确保所有的内部利益相关者在模型的整个生命周期中都了解并参与其中。
感谢你阅读我的帖子。
机器学习算法不是黑盒
神经网络解释指南
数据科学是一个非常新的领域,几乎没有一成不变的标准。这使得它成为一个令人兴奋的工作领域,因为它取决于当前的数据科学家来创建和设置这些标准。然而,因为数据科学是一个如此新的领域,所以有很多错误的信息。我经常听到的第一个错误信息是机器学习算法是黑盒。我坚决不同意这种说法。我相信几乎任何机器学习都是高度可解释的。说机器学习算法是黑盒的人也说他们通常使用线性模型,因为它们更容易解释。我也强烈不同意这种说法,认为很多机器学习算法(如神经网络、随机森林)比线性模型更容易解释。这篇博客文章的目标是讨论机器学习算法的可解释性,并提出可以用来解释这些算法的方法。
为什么您应该关注模型的可解释性
在深入本质细节之前,让我们讨论一下为什么您应该关心模型的可解释性。数据科学不同于许多其他科学,因为大多数数据科学家都在工业界工作。这意味着大多数数据科学家使用机器学习来解决商业问题。这可能是该领域不是基于理论而是基于经验的原因——在大多数情况下,数据科学家不太关心算法在理论上有多优雅,而是关心它是否工作良好。模型的可解释性通常对解决商业问题至关重要。该领域的许多人认为,机器学习仅用于自动化流程。这是机器学习的一种用途,但在很多情况下,我训练机器学习模型不是因为我想自动化一个过程,而是我想解释它。在商业环境中,你可能想知道一个预测最重要的特征是什么,以及我能否以某种方式操纵或使用这些特征来解决一个感兴趣的问题。例如,假设您训练了一个模型,该模型采用一些特征并预测客户是否会停止使用您的产品(客户保留问题)。如果你不能真正留住客户(即改变客户的行为),自动检测客户是否会停止使用你的产品的过程是完全无用的。因此,识别高停药风险客户只是第一步。下一步也是最重要的一步是确定应该做些什么来改变这些客户的行为。这就是模型可解释性的来源。我们可能想研究一下对于客户保持预测来说最重要的特征是什么。在这些重要特性之外,确定我们实际上可以控制的特性,以防止客户停止购买。机器学习非常适合为这个问题提供数据驱动的解决方案。这个过程的这一部分需要一些创造力,我鼓励所有读者阅读 设计伟大的数据产品 ,其中更深入地讨论了这个问题。
为什么线性模型实际上很难解释
好了,我们已经讨论了为什么模型的可解释性如此重要,但你可能仍然认为,由于线性模型并不复杂,它更适合解释。我认为事实并非如此,原因如下。首先,恰当地拟合线性模型是非常困难的。这是因为线性模型(线性回归/分类)具有非常严格的统计假设(例如,正态性、非共线)。对于“真实世界”数据,数据很少遵循这些统计假设。可以对数据进行预处理/转换,以满足这些统计假设,但是即使这样做了,数据仍然不满足所有这些假设的情况也是非常常见的。
第二,解释β系数通常是有缺陷的。通常,当个人在解释一个线性模型时,他们想要检查模型中最重要的特征。这是通过在训练模型之后,检查β系数和检查这些系数的幅度来完成的。然而,这种方法通常是有缺陷的。为了使β系数实际上是可解释的,模型必须被完美地构建,这意味着每一个主要的影响和相互作用都必须被完美地建模。但是在几乎所有的情况下,不可能知道什么主要效应和相互作用需要被建模,所以β系数基本上是没有用的。顺便说一下,这都是假设特征和因变量之间的关系是线性的,这种情况很少发生。
为什么复杂的机器学习算法更容易解释
我希望现在我已经让你相信解释一个线性模型并不像大多数人想的那么简单。现在,你可能想知道为什么我认为机器学习算法更容易解释。首先,大部分机器学习算法的统计假设很少。这是我 99%时间使用的机器学习算法的情况,它们是基于集成的算法(例如,随机森林)或神经网络。因此,这些方法能够处理“真实世界”的数据。第二个,这些算法中有许多能够学习复杂的交互。随机森林和神经网络通常包含许多参数。具有传统统计学背景的个人通常不喜欢使用有许多参数的模型。他们经常担心这些模型会过度适应训练数据。但是,通过使用正则化,通常可以避免过度拟合。此外,典型的“真实世界”数据极其复杂,拥有许多参数的通常是充分建模数据所必需的。我还想向读者指出,检验一个模型是否过度拟合是一个经验性的问题。有经验的机器学习实践者能够识别模型是欠拟合还是过拟合,并且你可以检查(并且应该总是检查!)如果你的模型过拟合。总之,机器学习算法更容易解释,因为它们通常可以更准确地模拟你的数据。
你如何解释机器学习算法
好了,最后让我们谈谈你如何解释机器学习算法。在这里,我将讨论解释神经网络的表格数据(所以你通常在电子表格中找到的数据)。您可能会想,为什么要使用包含表格数据的神经网络,而不是像随机森林这样的其他算法。嗯,我确实经常使用随机森林,但最近我发现神经网络很多时候都优于随机森林(即使是在处理小数据集时!).从我自己的经验来看,在处理分类变量时似乎就是这种情况。我相信这是因为我在我的神经网络中使用了实体嵌入。实体嵌入超出了本文的范围,但是如果您不使用它们,您应该考虑使用它们,因为它们对我帮助很大。我向有兴趣了解更多关于实体嵌入的读者推荐 表格数据深度学习介绍 。
我在这里展示的所有方法都受到了与除神经网络之外的其他机器学习算法一起使用的方法的启发(例如,随机森林)。因此,这意味着这些方法可以适用于任何机器学习算法。此外,以下所有方法都假设您已经训练了您的模型,因此这是您在模型被训练后要做的事情。
让我们开始吧。与解释一个你经常查看参数的线性模型不同,当解释一个神经网络时,我使用询问方法。我经常会对数据进行某种类型的实验操作,看看这会如何影响我的模型输出。在这里,我提出了三种模型解释方法:特性重要性、部分依赖图和单独的行解释器。对于我所有的例子,我使用了一个假的数据集(图 1 ),我试图根据一些特征(星期几、季节、州和年份)来预测杂货店的销售额。
Fig. 1
特征重要性
通常情况下,您希望了解模型预测的最重要的特征。例如,在我们的杂货店示例中,您可能想知道预测杂货店销售额的最重要的特征是什么。首先,你可以得到最终模型的损失(基线损失)。然后,你将选取一个特征(这里假设一周中的某一天,如图图 2 所示),随机排列(即洗牌)这些值(如图图 3 所示),通过训练好的模型运行数据集,并记录你的损失(洗牌损失)。接下来,取基线损耗和洗牌损耗之差的绝对值。这就是你的特性重要性。因此,如果改变一个值会导致损失发生很大的变化,那么你可以推断这个特性对于你的模型所预测的任何东西都是非常重要的。
Fig. 2
Fig. 3
您将对每个特征重复此过程。然后比较这些要素重要性值,以确定最重要的要素。正如您可能看到的,特性重要性是一个相对的度量,因此实际的特性重要性值本身并不太重要,但是它与该特定模型中使用的所有其他特性相比如何才是重要的。一旦您确定了最重要的特性,您可能希望在解决您的业务问题时关注这些特性。
部分相关图
特征重要性分析告诉我们最重要的特征,但是它没有告诉我们具体的特征是如何与因变量相关的。部分相关图的目标是检查一个特征(或几个特征)如何与控制模型中所有其它特征的模型因变量相关。所以部分依赖图真正有用的部分是控制所有其他特征。创造这些情节的技巧非常聪明,但也很简单。假设您有一个预测杂货店销售额的模型,并且您希望了解一周中的每一天(星期一到星期日)与销售额之间的关系。同样,你的模型必须已经被训练过。我们所做的是从我们感兴趣的特征中提取一个值,假设是星期一,我们将数据集中星期几列中的每一行都更改为星期一(图 4 )。然后,我们通过我们的模型运行修改后的数据集,并获得预测。这是保持其他一切不变的一个非常聪明的方法。因此,在我们的示例中,在每一行中,季节、州和年份都保持完全相同,但是如果该行中的星期几不是星期一,则更改为星期一。这显示了星期一对预测销售额的具体影响。然后,我们取平均预测值,并将这个值存储起来。
Fig. 4
然后我们在星期二做同样的事情。用星期二替换每一行,通过我们训练好的模型运行修改后的数据集,并计算平均预测值(图 5 )。
Fig. 5
我们对一周中的每一天重复这个过程,并绘制我们的结果——这是一个部分相关图(图 6 )。该图显示了星期几和平均销售预测之间的关系,控制了我们模型中的所有其他功能。正如你在下面看到的(注意:这个数据是不真实的),看起来食品杂货销售在周六和周日是最高的。
Fig. 6
我认为这种类型的分析非常有用。在不使用机器学习模型的情况下,很难检查控制我们所有其他特征的这种关系。我们正在利用神经网络在模型训练期间学习的复杂交互作用。你可能会想,这种类型的分析很容易用线性模型来完成,但是,为了检查这种类型的关系,所有的数据都必须满足线性模型的统计假设,我们必须对数据进行完美的建模,这在 99%的情况下是不可能的。通过使用神经网络,模型学习如何正确地对数据建模。
单行解释程序
正如您所看到的,特征重要性分析和部分相关性图正在检查组平均效应,但通常情况下,您可能想知道为什么单个观察会给出某个预测。例如,在我们的杂货店销售示例中,您可能想知道哪些特性可能会产生特定行的预测。我们可以通过单独的行解释器来实现。我不得不承认,这种方法比特性重要性分析和部分依赖图更具实验性,但是我发现它确实表现得相当好。
这种方法受到启发,非常类似于用于解释随机森林的树解释器。有一篇非常好的关于树解释器的博文,我强烈推荐读者去看看— 解释随机森林 。
首先,您需要选择您想要解释的行(图 7 )。现在,我们将对整个数据集进行平均预测。在本例中,它是 13,700 美元。
Fig. 7
接下来,我们将计算每个特性的特性贡献。让我们从星期几开始。对于这个特定的行,星期几是星期一。因此,我们遍历数据集,找到所有将星期一作为星期几的行(图 8 )。然后对于所有这些行,我们取平均预测值。然后,我们获得星期一行的平均预测,并从中减去整个数据集的平均预测,得到 6800 美元。这就是特色贡献。我们可以推断,如果特定要素类型(例如,星期一)的平均预测值确实不同于整个数据集的平均预测值,则该要素确实很重要。此外,特征贡献的方向很重要。如果该值为正值,则可能导致预测值高于数据集的平均值,但如果该值为负值,则可能导致预测值低于数据集的平均值。如您所见,就像特性重要性一样,这将是一个相对的度量。
Fig. 8
现在,让我们为我们的下一个功能,这是季节。对于我们正在解释的特定行,季节是冬天。因此,我们将找到季节为冬季的所有行,获得平均预测,并将冬季平均预测与整个数据集的平均预测进行比较;这里,季节的特征贡献是$940 ( 图 9 )。
Fig. 9
我们将对所有其他特征重复该过程(图 10 )。现在我们可以看到这个特定行最重要的特性。在这种情况下,它是一周中的某一天—也显示在图中(图 11 )。在我们的例子中,所有的贡献都是积极的,但也要记住,贡献可能是消极的。如果你有一个积极和消极贡献的组合,并且你正在努力寻找最重要的特征(所以你可能不关心变化的方向),你当然可以只取这些贡献的绝对值。
Fig. 10
Fig. 11
在我们的例子中,我们所有的特征都是分类变量,所以你可能想知道如何处理连续变量。这也是实验性的,但是对于一个连续变量,我把值分成两个不同的类别。我的方法是从特定要素的数据集中提取所有值,并对唯一值进行排序。然后,我找到可以将数据集分成两组的值(因此,将低于或等于分割点值的值和高于分割点值的值打包),平均预测的差异最大(非常类似于决策树!).计算此连续变量的特征贡献时,您可以查看该值,看它是属于小于或等于分割点值的类别,还是属于大于分割点值的类别。然后,你正常计算特征贡献。
结论
正如你可以从这些方法中看到的,它们都不复杂,我希望这些能启发读者开发其他/更好的解释机器学习算法的方法。我希望我已经让你相信,机器学习算法不仅是高度可解释的,,而且它们在解决商业问题(或任何类型的问题)时都非常有用。机器学习解释提供的许多见解往往无法用简单的描述性统计来实现。
机器学习模型解释仍处于起步阶段,因此非常欢迎反馈和新想法——无论是这里的评论还是新的博客帖子!尽情探索你的机器学习算法吧!
适合各种场合的机器学习算法
对您选择的算法做出明智的决定
机器学习算法是一种方法,它为系统提供自动学习和的能力,并根据经验进行改进,而不需要明确编程。像线性回归,深度学习,c 选择性神经网络和推荐系统这样的算法被广泛使用和解释。
人们很容易迷失在信息的海洋中。了解哪种算法适合任何给定的情况成为一种制胜的品质。通常这个角色由产品经理来扮演。不管谁发号施令,重要的是要明白不同的情况需要不同的算法。
Photo by Jean-Philippe Delberghe on Unsplash
指导原则
您对算法的选择主要取决于 3 个因素。
- 输入数据的质量
- 所需的输出类型
- 业务限制
1)输入数据的质量
根据所有输入数据包含的信息,可以选择算法。即使是数据是否被标记的简单概念也会极大地影响算法的选择。监督算法最适合标记良好的数据。像线性回归、逻辑回归、神经网络、随机森林等算法。都是监督算法的例子。
另一方面,如果您的数据没有标签或具有稀疏标签,则可以使用无监督学习算法,如聚类。
没有完美的数据集。真实世界的数据收集充斥着各种问题,比如缺失数据、噪声数据、少于算法所需的数据。
比如说你的数据中有很多异常值,那么线性回归的表现会非常差,但是决策树会是一个相当稳定的解决方案。
类似地,缺失数据对朴素贝叶斯的影响远远大于对神经网络的影响。当没有足够的训练数据时,SVM 会比深度神经网络表现得更好。
2)所需输出的类型
如果你需要你的输出来预测明天的股票价格,那么算法将是一个时间序列模型。另一方面,如果你只需要一封邮件是否是垃圾邮件的输出,你可以使用分类。您需要的输出类型直接取决于您需要回答的业务问题。
商业问题 1 — 假设一家初创公司的营销团队想要决定营销预算的规模。他们希望基于它将产生的收入。解决这个业务问题会产生一个营销预算与销售收入的关系图的输出。这种问题属于线性回归的范畴。(最左边的曲线)
商业问题 2 — 而如果同一家公司想根据他们的身高和体重将他们的用户分为男性和女性,那么这就变成了一个分类的问题。
业务问题 3 — 如果同一家公司想要对他们的用户进行分析,以了解他们的信用风险,那么选择的算法将是无监督学习。是因为数据没有标注。新的信用卡用户没有一个风险评分或风险档案,在此基础上他们可以被分类。因此,这些公司喜欢根据年龄、工资和地点等因素对用户进行聚类。这将成为一个集群问题。
算法与数据的关系
- 在回归中,你拟合了一条预测趋势的线,这条线上的任何新点都能很容易地告诉你你需要什么。
- 另一方面,分类通过一条明确的线将两个类别分开。两边的分数都归入了整齐的类别。
- 最后,聚类试图观察可以在整个数据集中识别的所有小组(聚类)。然后可以对每个集群进行不同的处理。
有趣的是,回归和分类都是有监督的算法。例如,在趋势预测示例中,我们已经知道一些对应于(营销预算、收入)值的数据点。由于我们事先已经知道了几双鞋,我们可以开始预测营销预算新值的收入。
同样,我们已经知道用户细分问题中的一些男性和女性。我们有他们的体重和身高数据。在此基础上,我们画了一条线将它们分开。任何具有给定体重和身高的新人都会落在这条线的两侧,并立即被归类。
然而,第三个问题略有不同。它属于无监督学习的情况,因为我们没有新用户的信用记录。因此,基于他们的年龄和工资,我们试图形成三个群体,观察他们的行为。这些集群中的一些将成为高风险个体,而一些将成为低风险个体。基于此,公司可以选择提供信用卡。
3)业务限制
最后,业务约束指导算法的选择。业务约束以下列形式出现:涉及的成本、上市时间、向客户承诺的速度以及能源效率。
像 Fitbit 或其他智能设备这样的边缘物联网公司将需要消耗更少能量的算法(因为电池限制)并具有足够好的准确性。他们不需要 99%的准确率。因此,他们会选择线性回归算法或最近邻法或支持向量机。
但像特斯拉这样需要自动驾驶汽车的公司,并不太在乎能效。它储存了很多能量。它非常关心准确性,所以它使用深度学习。
同样,斯坦福大学的机器学习研究团队对模型的可解释性比对准确性更感兴趣。因此团队使用决策树和朴素贝叶斯。
计算复杂性也很重要,因为它会影响成本,进而影响硬件选择。与谷歌这样的巨头相比,初创公司的资金较少,因此初创公司会部署决策树算法,而谷歌会选择由 1000 棵决策树组成的随机森林。
知道使用哪种算法是一项非常方便的技能。在众多的算法中,找到正确的算法是必须的。
没有选择是糟糕的,有太多选择更糟糕!
简单的机器学习算法(第 1 部分)
机器学习(ML)通常用于许多不同的事情,例如欺诈检测、图像识别、语音识别、视频推荐、自动驾驶汽车、垃圾邮件检测、教计算机如何烹饪或如何下棋等等。
ML 的好处有很多,其中一个就是学起来并不难。因此,我们有人类,他们使用不同的交流方式进行交流,如面部表情、手势、语调、节奏……我们有计算机,他们使用数据进行交流。两者之间的一个很大的区别是,人类从过去的经验中学习,而计算机需要由人类给予信息,这涉及到教授计算机相应的编程。
ML 是一个新概念,它教会计算机像人类一样学习,根据过去的经验完成任务。在本文中,我们将探索一些不同的算法和例子,其中计算机从以前的信息(或数据)中学习。所以让我们开始吧。
决策树
假设你是一名汽车销售人员,你想向你的客户推荐汽车,比如 E-Porsche、宝马 i8 和奔驰 EQS。
您有关于客户的各种信息,如年龄和就业形式(自雇或受雇)。下表列出了所有数据:
例如,在表格的第二行,我们有一位客户,29 岁,有工作,有一辆 E-Porsche。有了给定的数据,这里的任务是根据客户的职业或年龄来预测应该向客户推荐哪种汽车。
看看不同的就业形式并把它们分开,自营职业者和受雇者都拥有 E-Porsche,这不适合分开。
在另一种情况下,我们可以使用特征年龄进行分割。通过观察“年龄”数据,35 岁以下的客户拥有 Mission-E 汽车,35 岁以上的客户拥有其他类别的汽车。
最能区分数据的特征是年龄。
一旦我们按年龄分开,我们可以继续就业的特点。
通过分离特征,我们现在可以向 35 岁以下的自雇人士推荐 i8,如果客户超过 35 岁并有雇主,我们可以推荐 EQS。这种方法被称为决策树。
决策来自于提出的问题。顾客多大了?是自雇还是受雇?如果有新客户,我们可以用决策树,给他推荐一辆车。如果新客户年龄在 35 岁以下,我们向他推荐 Mission-E。这种方法可以处理分类和数字特征,并且易于理解。它为视觉表现提供了很好的解释。我们将继续下一个方法。下一个方法将帮助我们过滤数据。
朴素贝叶斯
ML 的另一种方法是朴素贝叶斯,这是一种分类技术。这是一个概率最大似然模型。对于垃圾邮件和文档分类这样的任务,它工作得很好。这种方法的一个常见例子是垃圾邮件过滤。我们将使用它作为分类器来检测垃圾邮件和非垃圾邮件。它是如何工作的?对于这项任务,我们必须看一看我们已经收到的数据。该数据集包含 50 个非垃圾邮件和 20 个垃圾邮件,它们已被手动标记。这使得总共有 70 封电子邮件。
让我们来定义和分析一些可以成为垃圾邮件的特征。例如,特征可以是没有主题的电子邮件。现在我们查看至少 70 封邮件,发现 50 封非垃圾邮件中有 4 封,20 封垃圾邮件中有 10 封是没有主题的邮件。
有了记录的数据,我们会试着找出一封没有主题的邮件是垃圾邮件的概率。我们可以看到,从我们没有主题的邮件中,四封是非垃圾邮件,而十封是垃圾邮件。这给了我们以下的答案:
71.43%是没有主题的邮件是垃圾邮件的概率。然后,我们可以使用以下规则将未来的电子邮件标记为非垃圾邮件或垃圾邮件:如果收到没有对象的电子邮件,则该电子邮件是垃圾邮件的概率为 71.43%,并将该电子邮件分类为垃圾邮件或不是垃圾邮件。通过使用其他功能,如包含句子“你是大赢家”或“要求你的报价”。然后,我们可以结合所有的特征对电子邮件进行分类。这种算法被称为朴素贝叶斯分类器。该方法也用于推荐、情感分析。这很容易实现。下一个方法,我们将看到,也是一个简单的方法,非常适合分析大量的数据。
K-均值聚类
K-Means 是用于对对象进行分组(聚类分析)的最常用的 ML 方法之一。我们有自行车,并希望将它们用于我们的自行车租赁系统。为此,我们决定在一个地区设置三个自行车租赁站。我们正在对一个地区进行研究,发现更多骑自行车出行的人住在公寓里,如下图所示。
用这种安排将每个站放在一个组中听起来更正确。因为公寓离得很近。
然而,正如我们在开始时所说的,事实是必须教会计算机如何完成一项任务。这意味着他不知道此时该如何做。在这种情况下,我们需要使用一种新的方法来找到一个好的位置。我们首先随机放置三个车站,在照片中自行车所在的位置。
在安置好车站后,我们希望人们能从最近的车站租到自行车。也就是说,靠近橙色车站的从橙色公寓租,靠近粉色车站的从粉色租,靠近黄色车站的从黄色租。
但是,如果我们观察黄色公寓中的居民与黄色车站的距离,我们会发现将车站放在黄色公寓的中心更有意义,并对粉色和黄色车站重复此步骤。
通过简单地改变车站的位置,我们现在可以将公寓重新安排到最近的车站。通过查看五个橙色公寓旁边的三个公寓,我们可以看到它们离橙色车站比离粉红色车站更近,然后我们将这些公寓标记为橙色,并对粉红色公寓旁边的两个黄色公寓进行同样的操作。
通过将粉色车站移动到其客户的中心,我们发现三个黄色公寓比黄色车站更靠近粉色车站,因此我们将它们着色为粉色。
然后,我们将黄色车站移动到黄色公寓的中心,因为它们离这个车站更近。
这种方法被称为 k-means。如果我们知道我们最终想要多少个聚类,那么我们可以使用 k-means。如果我们不知道我们想要多少个集群。还有另一种算法,叫做层次聚类。
层次聚类
在不指定组或群、群的数量的情况下,分层聚类是可以用来对该地区中的公寓或建筑物进行聚类的另一种方法。由于公寓在一个地区的位置,如果两个公寓很近,那么公寓的居民可以在同一个车站租自行车。根据此规则,我们可以将公寓分组如下:
然后,我们将下两个最近的公寓分组。
我们重复上一步,我们将得到以下结果
那么最接近的可能附近公寓就是图中标注的图片。但是他们彼此离得有点远。
如果距离达到一定长度,算法的执行停止。这种方法称为层次聚类,如果我们不知道想要的聚类数,但知道应该是什么样子,就可以使用这种方法。
线性回归
在这个例子中,我们试图根据汽车的长 x 宽 x 高(LxWxH)来估计汽车的价格。
为此我们做了一个小研究。通过这个小小的学习,我们有了三辆车。最小的汽车花费 15000€,最大的汽车花费 45000€。我们现在想估算一辆大小介于两辆车之间的汽车的价格。
为此,我们将汽车排列在一个网格中,其中 x 轴对应汽车的大小,y 轴对应汽车的价格。为了使任务变得简单一点,我们使用了之前从其他汽车上记录的数据。这些用这些棕色的点来表示。
我们可以看到这些点可以形成一条线。然后我们画一条最适合这些棕色点的线。
在这条线的帮助下,我们可以估计中间那辆车的价格,这相当于 30.000 €。
这种方法称为线性回归。为了找到上面那条最符合数据的绿线,我们使用了一种叫做梯度下降的不同方法。我们稍作停留,谈谈这个方法。
梯度下降
让我们假设我们在山顶,我们需要找到到山脚的最短距离。
我们可以一步一步走到山脚下。我们首先需要找到合适的方向,让我们可以走得更远。然后我们朝那个方向前进。
之后,我们重复这个过程,朝着正确的方向迈出一步。
我们重复这个动作,直到到达山脚。
这是梯度下降算法。它在机器学习中被大量使用。为了解决我们的高山问题,我们朝着正确的方向迈出一小步,直到到达山脚(解决方案)。
线性回归—套件
我们现在回到使用线性线来寻找数据的最佳匹配的方法。我们仍然在线性回归中试图解释如何找到与数据最匹配的直线。
让我们用四个点试一试,找到一条更适合这四个点的线。作为一台计算机,我们不知道如何做到这一点,所以我们首先偶然画一条线。
现在我们检查这条线与数据拟合的好坏程度。这是通过计算误差来实现的。为此,我们计算四个点到直线的距离。然后我们把这些距离相加得到误差。
然后我们把线往不同的方向移动,计算误差,看到误差变小了。
我们采取这一步,重复这一过程,并尽量减少误差,直到我们找到一个好的解决方案。
这个最小化误差的过程是通过梯度下降来完成的。当我们在山顶时,我们有一个很大的误差。我们沿着正确的方向迈出的每一步,都将误差降到最低。在真实的例子中,我们不想使用负距离,所以我们使用正方形来代替。这就是所谓的最小二乘法。
逻辑回归
对于这个例子,我们接受了对良性和恶性脑瘤进行分类的任务。
基本上,良性脑瘤可以与恶性脑瘤相区别,其特征在于良性脑瘤通常生长缓慢(并且主要通过增加压力来损伤周围组织),并且与恶性肿瘤相比,良性脑瘤不太可能复发,恶性肿瘤生长迅速并具有侵入健康组织的能力。我们将在这里使用这两个特征肿瘤的生长速度和复发程度来分类这两种类型的脑肿瘤。
在这个例子中,我们已经记录了一些具有参数的数据,例如,对于数据 x,生长速度梯度为 20%,复发梯度为 20%,数据 x 是良性肿瘤。对于数据 y,我们有一个 79%的增长速度梯度,61%的复发梯度,这是一个恶性肿瘤。我们现在有了新的数据,增长速度等级为 62%,复发等级为 45%。颜色定义了每个实例所属的类标签。根据我们掌握的数据,我们想确定这是哪种类型的肿瘤。为此,我们将数据排列在一个网格中,其中 x 轴对应于增长率,y 轴对应于复发等级。
我们使用以前记录的恶性和良性肿瘤的数据。
仔细观察这些点,我们可以看到这些点可以用一条线分开。这条线是模型。
大部分红点在绿线之上,大部分灰点在线之下。每当我们有一个新的点,我们将能够使用该模型将其分配给肿瘤类型。关于线的数据是恶性肿瘤,线下的数据是良性肿瘤。对于具有坐标的新数据,我们可以说这个肿瘤是恶性的。这种方法被称为逻辑回归。
与线性回归一样,我们检查找出这条分隔数据的直线的方法。让我们举一个简单的例子,试着找出最能区分数据的线,红点和红点。
在我们的例子中,我们有两个红点和一个红点,这意味着三个错误。我们试图通过使用梯度下降来最小化误差。如果我们把线向正确的方向移动,我们可以看到误差被最小化了。
现在我们只有两个错误。然后我们重复这个过程,直到我们不再有错误。
对于真实的例子,我们并不试图最小化误差,而是使用一个称为对数损失函数的函数,该函数对误差的数量进行加权。我们有八个点中的两个没有正确分类。
对数损失函数将对不正确的点分配较大的罚分,对正确的点分配较小的罚分。我们将各个点的所有惩罚相加,得到对数损失函数。为了更清楚地说明这一点,我们用数字代替了大罚分和小罚分。第二步,我们看到误差比下一步大。
这里的步骤是最小化误差函数,并找到最好地分隔数据的线。
现在我们知道一点机器学习算法。让我们在下一页看到更多。
一些不错的参考资料
[1]安德鲁·摩尔。K-means 和层次聚类-教程幻灯片。网址 http://www-2.cs.cmu.edu/~awm/tutorials/kmeans.html。
迈克尔·尼尔森。神经网络和深度学习。网址 http://neuralnetworksanddeeplearning.com/index.html。
简单的机器学习算法(第二部分)
在第一部分中,我们解释了什么是 ML 以及一些机器学习算法。在这个新的部分中,我们将更深入地了解更多的方法,这些方法可以帮助我们教会机器完成一项任务。
SVM(支持向量机)
现在我们看到另一种方法来思考更多。在这个例子中,我们有三个红色和三个灰色的点被一条以上的线分开。
现在我们将研究哪条线最符合数据。
我们可以看到绿线离点很近,而粉线离点没那么近。粉红色的线似乎离圆点足够远,因此能够很好地将它们分开。粉线在这里赢过绿线。从对数回归来看,我们必须解释如何找到最适合这些点的直线。我们应该计算点和线之间的距离。这里我们可以看到每个点到直线的距离,我们发现这些距离下的最小值是各个点离直线的距离。
通过只看六个距离中的最小值,我们可以忽略那些离直线非常远的点。
由此,我们可以得出结论,粉线可以更好地分离数据,因为粉线的最小值大于绿线的最小值。这里的目标是通过使用前面方法中的梯度下降来最大化距离。这种算法被称为支持向量机(SVM)。这里的支持向量是靠近超平面的点。粉色线是分隔点的超平面。SVM 可用于分类任务。
神经网络
这里我们将继续我们的肿瘤数据。现在,数据排列如下图所示。这是一个新型号。
有时数据可以这样排列:
不幸的是,在这种情况下,我们无法使用一条线来分隔数据。
我们可以用多条线或一个圆来分隔数据。
通过使用梯度下降,我们可以最小化误差函数并找到这些线。这种方法叫做神经网络。这个名字来源于人类大脑如何工作的灵感,尤其是在多任务处理时。例如,一个人可以一边走在街上,一边操作他的手机(这可能是危险的)。
现在,假设我们有一台功率较小的计算机,无法同时执行多项任务。例如,如果我们想知道一个新数据是否属于恶性肿瘤类型,我们必须将大任务分成许多小任务。第一个任务或问题是:新数据是否在紫线之上?
答案是肯定的。下一个问题是:这些新数据是否越过了绿线?
答案也是肯定的。在两个答案都是肯定的情况下,我们可以断定新数据是恶性肿瘤。
因此,我们可以用“是”或“否”来完成其他区域
所以右下角的区域会有 1-否/2-是。在左上方区域,我们会有 1-是/2-否,最后在左下方区域,我们会有 1-否/2-否。现在我们可以在一个图表中用节点表示任务,如下所示:
对于这个带有绿色节点的小图,我们提出这样一个问题,带有坐标的数据(重现梯度=70%,增长速度梯度=20%)是否在绿线之上,答案是否定的。对另一个图进行相同的过程,其中另一个问题,带有坐标的数据(重现梯度=70%,增长速度梯度=20%)是否在紫线之上,答案是否定的。
对于下一个问题,我们只是将上面两个图的输出合并到一个新的节点。
这两个值的组合是使用 AND 逻辑完成的。让我们看看这个和运算符。
它有两个输入,Yes 和 No(或数字 0 和 1 ),有一个输出。如果我们输入 Yes 和 No(或 1 和 0),输出将是 No(或 0)。如果输入为 No 和 No(或 0 和 0),则输出为 No(或 0)。
新节点与两个小图的组合称为神经网络。在神经网络中,我们首先有一个输入层,我们输入递归梯度=70%,增长速度梯度=20%。然后,输入层中关于梯度的信息被转发到中间层。从中间层的节点得到答案“否”和“是”。这些然后被转发到输出层,并且将被与逻辑评估,并且神经网络的与逻辑或的输出是“否”
可以向该网络添加额外的层和节点来解决更复杂的任务。
这是一个强大而伟大的机器学习算法。它被用于许多项目,如驾驶辅助系统、手写识别、使用 TNA(热中子分析)检测行李箱中的炸弹,也许在未来还会有读心术等等。
内核方法
在这个新的例子中,我们将看到一个新的方法,可以将线性不可分的数据转换成线性可分的数据。我们有如下几点安排。
在这些情况下,不可能用一条线来分隔这些点。
在这里,我们必须以不同的方式进行。我们可以想象这些点显示在一个网格中,然后我们用一条曲线将它们分开。
同样,我们可以想象这些点在空间中,并用一个平面来分隔它们。为此,我们添加了一个额外的轴,z 轴。然后,通过将 2D 中的点的坐标(x,y)与 3D 中的坐标(x,y,z)进行匹配,将两个红点沿 z 轴移动,其中 z 可以是依赖于 x 或 y 的方程,如 x y,x+y,…随后,我们将能够使用平面图来分离这些点。
这两个招数是一样的。这种方法主要用于支持向量机,称为核技巧。我们将继续这里的点排列像在(a)和曲线作为分隔符。为了分离这些点,我们将使用一些等式来帮助我们分离这些点。我们有 xy,x+y,x,x。
这些点的坐标被应用到方程式中。输出将为我们提供更多关于方程或函数如何分离这些点的信息。我们使用一个表格来显示结果。
第一行对应于点的坐标(从左到右),第一列包含方程式。我们可以在表格中看到所有的结果。例如,对于 x 中的(4,0),这使得 5x5x5=125,对于 x+y 中的(1,3),我们有 1+3=4。
现在的问题是,哪个方程把点分开。首先我们有 x+y,我们可以看到两个蓝点和两个红点的坐标有相同的结果,4。因此,方程不能分离点。对于 x 和 x,可以看出蓝色点和红色点有不同的结果,并且红色点的值在蓝色点的值之间。因此,这些方程也不能分离这些点。最后,我们有 xy,注意蓝色点有相同的值 0,红色点有相同的值 3。该函数可以分离这些点,因为它为红点提供了一个值,为蓝点提供了另一个值。
蓝点的 xy=0,红点的 xy=3。我们知道 1 和 2 在 0 和 3 之间,所以 1 和 2 把 0 和 3 分开。这给出了方程 xy=1 和 xy=2,从而得到函数 y=1/x 和 y=2/x。
由此我们得出结论,函数 1/x(或 2/x)分隔了平面中的点。
利用该方法,非线性数据可以被映射到更高维(n-dim)空间。在这个新的空间中,可以使用平面或曲线轻松地分离数据。该方法可用于手写识别、3D 重建、地质统计学等等。
结论
在本文中,分为两部分,我们已经看到了机器学习中使用的几个重要算法。目标是使用各种示例以简单的方式向他们解释算法。现在我们到达了“轻松潜水”的终点。
所以祝你在机器学习的美好世界里玩得开心。
一些不错的参考资料
[1]伊恩·古德费勒,约舒阿·本吉奥和亚伦·库维尔。深度学习。ISBN 9780262035613。网址 https://mitpress.mit.edu/books/deep-learning。
[2]克里斯托弗·h·兰伯特。计算机视觉中的核方法。计算机图形和视觉的基础和趋势。网址http://www.nowpublishers.com/article/Details/CGV-027。
通俗易懂的机器学习算法,第 1 部分
(即如何向你奶奶解释机器学习算法)
【更新:第二部现已上线!点击这里查看[。]](https://medium.com/@AudreyLorberfeld/machine-learning-algorithms-in-laymans-terms-part-2-a0a74df9a9ac)
作为熨斗学院数据科学训练营的一名应届毕业生,我收到了大量关于如何在技术面试中胜出的建议。一项不断涌现的软技能是向非技术人员解释复杂的机器学习算法的能力。
https://wordstream-files-prod.s3.amazonaws.com/s3fs-public/machine-learning.png
这一系列帖子是我与世界分享我将如何解释我经常遇到的所有机器学习主题...给我奶奶。有些比较深入,有些不太深入,但我认为所有这些对非数据科学家都有用。第一部分的主题是:
在本系列接下来的部分中,我将回顾:
- 决策树
- 随机森林
- SVM
- 朴素贝叶斯
- RNNs 和 CNN
- k-神经网络
- k 均值
- DBScan
- 分层聚类
- 凝聚聚类
- 极端梯度推进
- adaboost 算法
在我们开始之前,先简单说说算法和模型之间的区别,摘自这篇伟大的 Quora 帖子:
“一个模型就像一个自动售货机,给你一个输入(钱),就会给你一些输出(也许是一罐汽水)。。。算法用于训练模型,模型基于给定输入做出的所有决策,以给出预期输出。例如,一种算法将根据给定资金的美元价值、你选择的产品、资金是否足够、你应该获得多少余额等等做出决定。”
总而言之,算法是模型背后的数学生命力。区分模型的是它们使用的算法,但是没有模型,算法只是一个数学方程,没有任何关系。
就这样,往前走!
梯度下降/最佳拟合线
(虽然第一种算法传统上并不被认为是机器学习算法,但理解梯度下降对于理解多少机器学习算法有效并得到优化是至关重要的。)
我对奶奶:
“基本上,梯度下降有助于我们根据一些数据获得最准确的预测。
让我再解释一下——假设你有一份你认识的每个人的身高和体重的清单。假设你把这些数据制成图表。它可能看起来像这样:
Our fake height and weight data set (…strangely geometric)
现在让我们假设有一个当地的猜谜比赛,根据身高猜对某人体重的人将获得现金奖励。除了用你的眼睛来判断一个人,你还必须非常依赖你手头的身高和体重列表,对吗?
因此,根据上面的数据图表,如果你在图表上有一条线显示数据的趋势,你可能会做出一些很好的预测。有了这样一条线,如果给你一个人的身高,你就可以在 x 轴上找到那个身高,一直向上,直到你碰到你的趋势线,然后看看 y 轴上相应的体重是多少,对吗?
但是你怎么找到那条完美的线呢?你也许可以手动完成,但是这将会花费很长时间。这就是梯度下降的用武之地!
Our “line of best fit” is in red above.
它通过尝试最小化称为 RSS(残差平方和)的东西来做到这一点,RSS 基本上是我们的点和我们的线之间的差异的平方和,即我们的真实数据(点)离我们的线(红线)有多远。通过改变我们的线在图上的位置,我们得到越来越小的 RSS,这有直观的意义——我们希望我们的线在最接近我们大多数点的任何地方。
我们实际上可以更进一步,在一个叫做成本曲线的东西上绘制每条不同生产线的参数。使用梯度下降,我们可以得到我们的成本曲线的底部。在我们成本曲线的底部是我们最低的 RSS!
Gradient Descent visualized (using MatplotLib), from the incredible Data Scientist Bhavesh Bhatt
梯度下降还有更细粒度的方面,如“步长”(即我们希望以多快的速度接近滑板斜坡的底部)和“学习率”(即我们希望以什么方向到达底部),但本质上:梯度下降通过最小化我们的点和最佳拟合线之间的空间来获得我们的最佳拟合线。反过来,我们的最佳拟合线允许我们做出预测!"
线性回归
我对奶奶:
简单地说,线性回归是一种分析 1 个变量(我们的“结果变量”)和 1 个或更多其他变量(我们的“自变量”)之间关系强度的方法。
线性回归的一个标志,顾名思义,就是自变量和我们的结果变量之间的关系是线性。就我们的目的而言,这意味着当我们绘制自变量相对于结果变量的曲线时,我们可以看到这些点开始呈现线形,如下图所示。
(如果你不能绘制数据,思考线性的一个好方法是回答这个问题:我的自变量的一定量的变化会导致我的结果变量的相同量的变化吗?如果是,你的数据是线性的!)
This looks a ton like what we did above! That’s because the line of best fit we discussed before IS our “regression line” in linear regression. The line of best fit shows us the best possible linear relationship between our points. That, in turn, allows us to make predictions.
关于线性回归要知道的另一件重要的事情是,结果变量,或者根据我们如何改变其他变量而改变的东西,总是连续的。但这意味着什么呢?
假设我们想测量海拔高度对纽约州降雨量的影响:我们的结果变量(或者我们希望看到变化的变量)是降雨量,我们的独立变量是海拔高度。使用线性回归,结果变量必须是具体的多少英寸的降雨量,而不是仅仅一个真/假的类别来指示在 x 高度是否下雨。这是因为我们的结果变量必须是连续的——这意味着它可以是数字范围内的任何数字(包括分数)。
关于线性回归最酷的事情是,它可以使用我们之前谈到的最佳拟合线来预测事情!如果我们对上面的降雨量与海拔情景进行线性回归分析,我们可以找到最佳拟合线,就像我们在梯度下降部分所做的那样(这次用蓝色显示),然后我们可以使用该线做出有根据的猜测,即在某个海拔高度下合理预期的降雨量。"
岭和套索回归
我继续满怀希望地——不太害怕地——对奶奶说:
“所以线性回归没那么可怕,对吧?这只是一种方法,用来观察一件事对另一件事有什么影响。酷毙了。
现在我们知道了简单的线性回归,我们可以讨论更酷的线性回归,比如岭回归。
就像梯度下降与线性回归的关系一样,我们需要了解一个背景故事来理解岭回归,那就是正则化。
简而言之,数据科学家使用正则化方法来确保他们的模型只关注对其结果变量有重大影响的独立变量。
你可能想知道为什么我们关心我们的模型是否使用没有影响的独立变量。如果它们没有影响,我们的回归不就是忽略它们吗?答案是否定的!我们可以稍后深入研究机器学习的细节,但基本上我们是通过向它们提供一堆“训练”数据来创建这些模型的。然后,我们通过在一堆“测试”数据上测试我们的模型来看看它们有多好。因此,如果我们用一堆独立变量训练我们的模型,其中一些重要,一些不重要,我们的模型在我们的训练数据上表现得非常好(因为我们在欺骗它,让它认为我们喂它的所有东西都重要),但在我们的测试数据上表现得非常差。这是因为我们的模型不够灵活,不足以很好地处理新数据。单身。很少。我们在训练阶段喂它的东西。当这种情况发生时,我们说模型“过度拟合”
为了理解过度拟合,让我们看一个(冗长的)例子:
假设你是一位新妈妈,你的小男孩喜欢意大利面。几个月过去了,你养成了开着厨房窗户给宝宝喂意大利面的习惯,因为你喜欢微风。然后你宝宝的表弟给他买了一件连体衣,你就开始了一个传统,当他穿着特殊的连体衣时,只给他吃意大利面。然后你收养了一只狗,它在宝宝吃意大利面的时候,勤奋地坐在宝宝的高脚椅下面去抓流浪面。在这一点上,你只能在你的宝宝穿着特殊的连体衣的时候喂他吃意大利面…厨房的窗户开着…狗在高脚椅下面。作为一个新妈妈,你会很自然地把你儿子对意大利面的喜爱与所有这些特征联系起来:敞开的厨房窗户、连体衣和狗。现在,你对婴儿饮食习惯的心理模型相当复杂!
一天,你去奶奶家旅行。你必须给你的宝宝喂晚餐(当然是意大利面),因为你要在这里过周末。你陷入恐慌,因为这个厨房没有窗户,你把他的连体衣忘在家里,狗和邻居在一起!你吓坏了,以至于忘记了给宝宝喂饭,只是让他上床睡觉。
哇哦。当你面对一个你从未面对过的场景时,你表现得相当糟糕。不过,在家里你做得很好!没道理啊!
在重新审视你对宝宝饮食习惯的心理模型并忽略所有“噪音”,或你认为可能对你的儿子实际上喜欢意大利面没有帮助的事情后,你意识到唯一真正重要的事情是它是由你做的。
第二天晚上在奶奶家,你在她没有窗户的厨房里喂他最爱的意大利面,而他只穿着尿布,没有狗。一切都很好!你对他为什么喜欢意大利面的想法现在简单多了。
这正是正则化可以为机器学习模型做的事情。
因此,正则化有助于您的模型只关注数据中重要的内容,并消除噪声。
On the left: LASSO regression (you can see that the coefficients, represented by the red rungs, can equal zero when they cross the y-axis). On the right: Ridge regression (you can see that the coefficients approach, but never equal zero, because they never cross the y-axis). Meta-credit: “Regularization in Machine Learning” by Prashant Gupta
在所有类型的正则化中,有一种叫做惩罚项的东西(希腊字母 lambda: λ)。这个惩罚项在数学上缩小了我们数据中的噪声。
在岭回归中,有时被称为“L2 回归”,惩罚项是变量系数的平方和。(线性回归中的系数基本上只是附加在每个独立变量上的数字,告诉你每个独立变量对结果变量的影响有多大。有时我们称它们为“重量”)在岭回归中,罚项缩小了自变量的系数,但实际上从未完全消除它们。这意味着通过岭回归,你的数据中的噪声将总是被你的模型考虑进去一个小位。
另一种类型的正规化是拉索,或“L1”正规化。在套索正则化中,不是惩罚数据中的每个要素,而是只惩罚高系数的要素。此外,套索有能力缩小系数的所有方式为零。这实际上是从数据集中删除了这些要素,因为它们现在的“权重”为零(即它们实际上被乘以零)。“使用 LASSO 回归,您的模型有可能消除数据集中的大部分噪声。这在某些场景下超级有帮助!
逻辑回归
我对奶奶:
“所以,酷,我们已经线性回归下来了。线性回归=一个变量对另一个变量的影响,假设 1)结果变量是连续的,2)变量和结果变量之间的关系是线性的。
但是如果你的结果变量是“绝对的”呢?这就是逻辑回归的用武之地!
分类变量就是只能属于一个类别的变量。一周中的几天就是很好的例子——如果你有一堆关于一周中某几天发生的事情的数据点,你不可能得到一个可能发生在周一到周二之间的数据点。如果周一发生了什么,那就发生在周一,就这样。
但是,如果我们想想我们的线性回归模型是如何工作的,我们怎么可能找出一条最适合某种分类的线呢?这是不可能的!这就是为什么逻辑回归模型输出你的数据点在一个或另一个类别中的概率,而不是常规的数值。这就是为什么逻辑回归模型主要用于分类。
Scary looking graph that’s actual super intuitive if you stare at it long enough. From Brandon Rohrer via LinkedIn.
但是回到线性回归和逻辑回归都是“线性的”如果我们不能在逻辑回归中找到一条最佳拟合线,那么逻辑回归的线性部分从何而来?在逻辑回归的世界中,结果变量与自变量的对数优势有线性关系。
但是这种可能性到底有多大呢?好了,我们开始吧…
赔率
逻辑回归的核心=赔率。
直觉上,几率是我们理解的东西——它们是成功的概率与失败的概率之比。换句话说,它们是某件事发生的概率与某件事不发生的概率的比较。
对于赔率的具体例子,我们可以想到一类学生。假设女性通过测试的几率是 5:1,而男性通过测试的几率是 3:10。这意味着,6 名女性中有 5 名可能通过测试,13 名男性中有 3 名可能通过测试。这里的班级总人数是 19 名学生(6 名女生+ 13 名男生)。
那么…赔率不就和概率一样吗?
可悲的是,没有!概率衡量的是某件事情发生的次数与所有事情发生的总次数的比率(例如,10 次正面对 30 次硬币投掷),而赔率衡量的是某件事情发生的次数与某件事情没有发生的次数的比率(例如,10 次正面对 20 次反面)。
这意味着,虽然概率总是被限制在 0-1 的范围内,但几率可以从 0 持续增长到正无穷大!这给我们的逻辑回归模型带来了一个问题,因为我们知道我们的预期输出是一个概率(即一个从 0 到 1 的数字)。
那么,我们如何从赔率到概率呢?
让我们来考虑一个分类问题…假设你最喜欢的足球队赢了另一个足球队。你可能会说你的团队失败的几率是 1:6,或者 0.17。你的团队获胜的几率是 6:1,或者 6,因为他们是一个伟大的团队。你可以用下面的数字线来表示这些概率:
https://www.youtube.com/watch?v=ARfXDSkQf1Y
现在,你不会希望你的模型预测你的团队会在未来的比赛中获胜,只是因为他们过去获胜的几率比他们过去失败的几率大得多,对吗?你希望你的模型考虑的东西太多了(也许是天气,也许是首发球员,等等。)!所以,为了让几率的大小均匀分布,或者说对称,我们计算了一种叫做 log- 的几率。
对数赔率
What we mean by “normally distributed”: the classic bell-shaped curve!
对数赔率是一种简写方式,指的是取赔率的自然对数。当你取某事物的自然对数时,你基本上使它更正态分布。当我们使一些东西更正态分布时,我们本质上是把它放在一个超级容易处理的尺度上。
当我们采用对数赔率时,我们将赔率的范围从 0-正无穷大转换为负无穷大-正无穷大。你可以在上面的钟形曲线上看到这口井。
即使我们仍然需要我们的输出在 0-1 之间,我们通过取对数优势获得的对称性使我们比以前更接近我们想要的输出!
Logit 函数
“logit 函数”就是我们用来计算对数几率的数学方法!
Some scary math thingymabob. Er, I mean the logit function.
The logit function, graphed.
logit 函数通过取它们的自然对数,将我们的赔率放在负无穷大到正无穷大的范围内,正如你在上面看到的。
Sigmoid 函数
好的,但是我们仍然没有达到我们的模型给出概率的程度。现在,我们只有负无穷大到正无穷大范围内的数字。输入:sigmoid 函数。
sigmoid 函数,因其在绘制时呈现 s 形而得名,正好是对数几率的倒数。通过取对数几率的倒数,我们将数值从负无穷大-正无穷大映射到 0-1。这反过来让我们得到概率,这正是我们想要的!
与 logit 函数图中 y 值范围从负无穷大到正无穷大相反,sigmoid 函数图中 y 值范围从 0 到 1。耶!
这样,我们现在可以插入任何 x 值,并将其追溯到预测的 y 值。该 y 值将是该 x 值在一个或另一个类中的概率。
最大似然估计
…还没有完成。
还记得我们如何通过最小化 RSS(一种有时被称为“普通最小二乘法”,或 OLS 方法)在线性回归中找到最佳拟合线吗?在这里,我们使用一种叫做的最大似然估计 (MLE)来得到我们最准确的预测。
MLE 通过确定最能描述我们数据的概率分布参数来获得最准确的预测。
我们为什么要关心数据的分布呢?因为很酷!…但实际上,这只是使我们的数据更容易处理,并使我们的模型可推广到许多不同的数据。
Logistic Regression Details, Part 2
一般来说,为了得到数据的最大似然估计,我们取 s 曲线上的数据点,并把它们的对数似然性相加。基本上,我们希望找到最大化数据对数似然的 s 曲线。我们只是不断计算每条对数优势线的对数似然性(有点像我们在线性回归中对每条最佳拟合线的 RSS 所做的),直到我们得到最大的数字。
(题外话——我们回到自然对数的世界,因为有时对数是最容易处理的数字形式。这是因为对数是“单调递增”的函数,这基本上意味着它持续增加或减少。)
在最大似然估计过程中,我们得出的估计值是那些最大化“似然函数”的估计值(我们不会在这里深入讨论)。"
http://incolors.club/collectiongdwn-great-job-funny-meme.htm
就是这样!现在你知道梯度下降,线性回归和逻辑回归。"
接下来
接下来奥黛丽向她奶奶解释机器学习算法:决策树,随机森林和 SVM。敬请期待!
更新:第二部现已上线!点击这里查看。
如果你有任何反馈,请对这篇文章发表评论,在 LinkedIn 上给我发消息,或者给我发电子邮件。
通俗易懂的机器学习算法,第 2 部分
(即如何向任何人解释机器学习算法)
重要通知:在本系列的第一篇帖子中,我犯了一个错误,将非技术人员等同于技术文盲老奶奶的刻板印象。数据科学界的一些成员让我注意到这个流行比喻背后的性别歧视和年龄歧视。他们完全正确。作为一名女性,我永远不会想削弱我的社区中的任何人,尤其是那些认同女性的人,和/或年长的专业人士。毫无疑问,如果没有前辈们辛勤的、往往不为人知的工作,我们这些年轻女性不可能取得今天的成就。
在这种情况下,这第二个帖子是献给所有那些在董事会上对抗微攻击的同时教他们(孙子)孩子线性代数的祖母们;对年长的女性来说,在养家糊口后重返工作岗位时,她们要求被认真对待;对于 STEM 领域的所有女性来说,如果我们抓住每一个机会相互扶持,我们会因此变得更加强大。
就这样,进入数据科学!
既然我们已经在第 1 部分中介绍了梯度下降、线性回归和逻辑回归,让我们来看看决策树和随机森林模型。
决策树
决策树是我们日常头脑中使用的一种超级简单的结构。这只是我们如何做决定的一种表现,就像一个如果这个那么那个的游戏。首先,你从一个问题开始。然后你写出这个问题的可能答案和一些后续问题,直到每个问题都有答案。
让我们来看一个决定某人是否应该在某一天打棒球的决策树:
From “Machine Learning with Decision Trees” by Ramandeep Kaur
上面的树以这个问题开始:今天天气如何?有三种可能的答案:晴天、阴天或下雨。
- 假设这是一个阳光明媚的日子:我们将沿着“阳光”分支
- “阳光”分支将我们引向“湿度”,这促使我们问自己这是高湿度的一天还是正常的一天
- 假设是高湿度的一天;然后我们会沿着“高”分支
- 既然现在没有其他问题需要回答,我们已经做出了最后的决定,那就是不,我们今天不应该打棒球,因为天气既晴朗又非常潮湿
这就是理解决策树的全部内容!
…开个玩笑。还有一些更快捷的事情:
- 决策树用于建模非线性关系(与线性回归模型和逻辑回归模型相反)。
- 决策树可以模拟分类和连续结果变量,尽管它们主要用于分类任务(即分类结果变量)。
- 决策树很容易理解!您可以轻松地将它们可视化,并准确地计算出每个分割点发生了什么。您还可以看到哪些功能是最重要的。
- 决策树容易过度拟合。这是因为不管你在一个决策树中运行多少次你的数据,因为它只是一系列如果-这个-那么-那个的语句,你将总是以相同的确切结果结束。这意味着您的决策树将会非常精确地适合您的训练数据,但是当您向它传递新数据时,它可能无法提供有用的预测。
那么决策树是如何知道何时分裂的呢?
(我所说的“分裂”是指形成更多的分支。)
决策树可以使用许多算法,但最流行的两种是 ID3 (ID 代表“迭代二分法”)和 CART (CART 代表“分类和回归树”)。这些算法中的每一种都使用不同的方法来决定何时拆分。ID3 树使用信息增益,而 CART 树使用基尼指数。
让我们从 ID3 树开始。
ID3 树和信息增益
基本上,ID3 树都是关于以最大化信息增益的方式获得最大的回报。(因此,它们也被称为贪婪的树。)
但是什么是信息增益呢?从技术上讲,信息增益是一个使用熵作为杂质测量的标准。让我们稍微解释一下。
熵
简而言之,熵是对(无序)次序的一种度量——它告诉你一个东西丢失了多少信息,或者你的数据有多乱。丢失大量信息的东西被认为是无序的(即具有高熵值),反之亦然。
让我们看一个具体的例子来巩固这背后的直觉:
假设你的任务是打扫一个脏乱的房间。地板上有脏衣服,可能还有一些狗玩具,还有一些书散落一地。这个房间乱极了!如果我们可以测量它的熵,它会超级高,它的信息增益会非常低。在这种状态下,这是非常不可行的。
但是你看到壁橱里有一些盒子,和一个大的记号笔。你开始给每个盒子贴上标签,标明你打算放进去的东西的类别。然后你开始打扫房间,把每件衣服/狗玩具/书放在各自的盒子里。你现在已经打扫完房间了!如果我们现在可以测量房间的熵,它会相当低(它的信息增益会很高)。干得好!
类似地,ID3 树将总是做出使它们在信息中获得最高增益的决定。更多的信息=更少的熵。这意味着随着决策树的每一次分裂,算法将朝着越来越低的熵移动。
Visualizing entropy in a decision tree
在上面的树中,你可以看到起点的熵为 0.918,而停止点的熵为 0。这棵树以高信息增益和低熵结束,这正是我们想要的。
(Im)纯度
除了向低熵方向发展,ID3 树还会做出决定,使它们获得最大的纯度。ID3 树这样做是因为他们希望每个决策都尽可能的清晰。熵低的东西也有高纯度。高信息增益=低熵=高纯度。
这具有直观的意义——如果某样东西令人困惑和无序(即具有高熵),你对那件东西的理解是模糊的、不清楚的或者不纯的。
大车树&基尼指数
由 ID3 算法驱动的决策树旨在最大化每次分割的信息增益,而使用 CART 算法的决策树旨在最小化一种称为基尼指数的度量。
基尼指数基本上告诉你从数据集中随机选择的数据点被错误分类的频率。在购物车树中(以及在生活中),我们总是希望最小化错误标记数据任何部分的可能性。真的就这么简单!
好吧,这些都有一定的道理,但是你之前提到的非线性的东西呢?
Visualization of linearly-separable data
在本系列的第 1 部分中,我们了解到线性关系是由线条定义的。
Visualization of linear function underlying a linear model.
基本上,当我们可以使用一条线(或线性平面)将我们的数据点分成几组时,我们知道我们的数据具有某种线性,就像最上面的图一样。
类似地,当我们可以用某种线来描绘变量之间的关系时,我们知道模型是线性的。这条线是支撑线性模型的线性函数的可视化,就像上面第二张图中的蓝线。
非线性真的和这个正好相反。您可以用几种不同的方式来考虑非线性数据和函数:
Visualization of non-linearly-separable data
- 对于非线性数据,您将无法显示分割数据的线性平面。当您无法线性分离数据时,您的模型依赖于非线性函数。这反过来意味着你的模型是非线性的!
- 线性函数具有恒定的斜率(因为 x 的微小变化会导致 y 的微小变化),而非线性函数则没有。例如,它们的斜率可能会呈指数增长。
- 你也可以使用与第 1 部分相同的类比,但是当你处理非线性函数时,你的自变量的小变化不会导致因变量的小变化,而是你的自变量的小变化会导致因变量的巨大变化,或者超级小的变化。
决策树非常擅长建模非线性关系,因为它们不依赖于线性平面来分离数据。(虽然这句话听起来很可怕,但实际上并不可怕——我们凭直觉知道决策树不会线性分离数据。你只要看看我们的树形结构就能证明这一点!你如何只用一条线将所有的“是”归入一个区域,将所有的“否”归入另一个区域?不可以!)
…好的,现在关于过度合身的东西呢?
所以,是的,当你想做探索性的分析时,决策树(不管他们使用哪种算法)是很棒的。它们擅长概述数据中的重要要素,并允许您查看每个要素是如何相互作用的。然而,他们倾向于过度拟合你的数据。反过来,这意味着决策树不擅长预测或分类他们以前没有见过的数据。
为了应对这种过度拟合,数据科学家提出了被称为集合模型的模型。这些模型基本上只是将许多决策树聚集在一起,并利用它们的集体力量来做出经得起严格测试的预测。
进入:随机森林
对于初学数据的科学家来说,随机森林可以说是最受欢迎的集合模型。
https://cdn.firespring.com/images/442c053c-745c-4bf3-b4a2-21b6fa79ddca.jpg
你说合奏?
因此,正如我们上面所说,一个集合模型只是许多其他模型的集合。
(Sorry for the blurriness, but I just love this image.) Random Forest structure from KDNuggets.
如左图所示,像随机森林这样的集合模型只是一堆决策树。在这里,您可以看到有 3 个决策树。
像随机森林这样的集合模型被设计成通过使用 bagging 算法来减少过度拟合和方差。
我们知道决策树容易过度拟合。换句话说,单个决策树可以很好地找到特定问题的解决方案,但如果应用于从未见过的问题,则非常糟糕。类似于谚语“两个脑袋比一个好”,集成模型使用许多擅长特定任务的决策树来建立一个更大的模型,该模型在许多不同的任务上都很棒。这么想吧——你是更有可能通过听取一个员工的建议做出一个好的商业决策,还是听取带来多样化经验的许多员工的建议?大概是后者吧。M 矿决策树=更少的过拟合。
好吧,我过度拟合了,但是你说的方差是什么?
在数据科学的世界里,我们要对抗的不仅仅是过度拟合。我们还必须反击所谓的方差。
具有“高方差”的模型是这样一种模型,如果它的输入发生哪怕是最微小的变化,其结果也会发生变化。与过度拟合非常相似,这意味着具有高方差的模型不能很好地推广到新数据。
我喜欢从身体平衡的角度来考虑变化:如果你站在坚实的地面上单脚平衡,你就不太可能摔倒。但是如果突然有时速 100 英里的阵风呢?我打赌你会摔倒。那是因为你单腿平衡的能力高度依赖于你所处环境的因素。如果有一点改变,它会让你完全陷入困境!当模型具有高方差时就是这样。如果我们扰乱了训练数据中的任何因素,我们就可以完全改变结果。这是不稳定的,因此不是我们想要做出决策的模型。
打包算法
在我们深入研究随机森林非常依赖的 bagging 算法之前,有一件事我们仍然需要涉及,那就是学习者的想法。
在机器学习中,有弱学习者和强学习者,bagging 算法(或“Bootstrap AGGregatING”算法)处理弱学习者。
(我们不会在这里讨论强学习者,但是在本系列的后续部分中,请关注他们!)
弱学习者
弱学习者构成了随机森林模型的主干。
The bottom row of this ensemble model (let’s call it a Random Forest) is where our “weak learners” live!
简而言之,弱学习者是预测/分类数据的算法,其准确度(或其他评估指标)略好于机会。这些家伙有用的原因是,我们可以将他们聚集在一起,制作一个预测/分类超级好的更大的模型!
…好了,回到装袋环节
像 Random Forest 这样的集合模型使用 bagging 算法来避免较简单的模型(如个体决策树)容易出现的高方差和过度拟合的缺陷。
装袋算法的超级威力在于,它们与随机样本的数据 配合替换。
这基本上意味着,当算法通过随机数据样本构建决策树时,没有它不能使用的数据点。例如,仅仅因为一个决策树是由 20 个数据点组成的,并不意味着另一个决策树不能由这 20 个数据点中的 12 个数据点组成。耶,概率!
From Decision Trees and Random Forests for Classification and Regression pt.2, by Haihan Lan
随机森林模型很酷的一点是,它们可以同时(或“并行”)对每个决策树进行所有这些随机抽样替换。因为我们处在随机抽样替换的世界中,我们也可以假设我们的每一个决策树都是相互独立的。
综上:随机森林模型使用 bagging 算法构建小决策树,每一棵都是用你的数据的随机子集同时构建的。
…但还有更多!
随机森林模型中的每棵树不仅只包含您的数据的一个子集,每棵树还只使用您的数据中的一个特征子集(即列)。
The basic structure of a Random Forest model (Random Forests, Decision Trees, and Ensemble Methods Explained, by Dylan Storey)
例如,假设我们试图根据作者、出版日期、页数和语言将一本书分类为已售或未售。我们的数据集中有 10,000 本书。在一个随机森林模型中,不仅我们的每个决策树只使用 10,000 本书的随机样本,每个决策树也只使用随机样本的特征:也许一个决策树会使用作者和出版日期,而另一个决策树会使用作者和页数。而另一个决策树可以使用语言和出版日期。这一点是,当我们对所有这些决策树(即“弱学习者”)的预测进行平均时,我们会得到一个超级健壮的预测!
差不多就是这样了!当我们使用随机森林模型进行分类时,我们采用所有决策树的多数投票,并将其作为结果。当我们使用随机森林模型进行回归时,我们对每个决策树的所有概率进行平均,并使用该数字作为结果。
通过这篇文章,我们了解了决策树、非线性、过度拟合和方差以及像随机森林这样的集合模型。请关注第 3 部分——我们将讨论两个比我们在第 1 部分中讨论的更高级的线性模型:SVM 和朴素贝叶斯。
一如既往,请联系我,提出任何更正或意见。你可以通过评论这篇文章、在 LinkedIn 上给我发信息或者给我发电子邮件来联系我。
使用 Sklearn Python 的 K-Fold 交叉验证示例
Photo by Lukas Blazek on Unsplash
最终,机器学习模型被用来对我们还没有答案的数据进行预测。例如,这可以采取推荐系统的形式,试图预测用户是否会喜欢这首歌或产品。
开发模型时,我们必须非常小心,不要过度适应我们的训练数据。换句话说,我们必须确保模型捕捉到了潜在的模式,而不是简单地记忆数据。因此,在生产中使用模型之前,我们必须检查它如何处理不可预见的数据。这通常是通过将数据分成两个子集来完成的,一个子集用于训练,另一个子集用于测试模型的准确性。
某些机器学习算法依赖于超参数。本质上,超参数是一个由用户设置的变量,它决定了算法的行为方式。超参数的一些例子是梯度下降中的步长和岭回归中的α。当涉及到超参数时,没有放之四海而皆准的方法。数据科学家必须通过反复试验来确定最佳超参数值。我们称这个过程为超参数调谐。
不幸的是,如果我们不断地使用测试集来衡量我们的模型对于不同超参数值的性能,我们的模型将会对测试集中的数据产生亲和力。换句话说,关于测试集的知识可能会泄漏到模型中,并且评估度量不再反映一般的性能。
为了解决这个问题,我们可以进一步分解数据(即验证、训练和测试集)。训练在训练集上进行,之后在验证集上进行评估,当我们对结果满意时,可以在测试集上执行最终评估。
然而,通过将可用数据分成三组,我们大大减少了可用于训练模型的样本数量。此外,结果可能取决于对样本的特定随机选择。例如,假设我们建立了一个模型,试图对手写数字进行分类,我们可能会得到这样一个场景,其中我们的训练集包含非常少的数字 7 的样本。
解决这些问题的方法是一种叫做交叉验证的程序。在交叉验证中,测试集仍然被放在一边进行最终评估,但是不再需要验证集。交叉验证有多种,最常见的叫做 k 倍交叉验证。在 k-fold 交叉验证中,训练集被分割成 k 个更小的集合(或折叠)。然后,使用褶皱的 k-1 训练模型,最后一个褶皱用作验证集,以计算精度等性能指标。
https://scikit-learn.org/stable/_images/grid_search_cross_validation.png
让我们看一个例子。对于前面的示例,我们将使用波士顿房价数据集。
https://scikit-learn.org/stable/modules/generated/sklearn.datasets.load_boston.html
首先,导入所有必需的库。
from sklearn.datasets import load_boston
from sklearn.linear_model import RidgeCV
from sklearn.model_selection import train_test_split
import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
接下来,我们将使用 sklearn 为我们的数据导入特征和标签。
boston = load_boston()boston_features = pd.DataFrame(boston.data, columns=boston.feature_names)X = boston_features['RM'].values.reshape(-1,1)y = boston.target
我们将使用 matplotlib 来绘制房价和每个住宅的平均房间数之间的关系。
plt.scatter(X, y);
plt.title('boston house prices')
plt.xlabel('average number of rooms per dwelling')
plt.ylabel('house prices')
plt.show()
如前所述,我们希望将一部分数据留到最后评估时使用。
train_X, test_X, train_y, test_y = train_test_split(X, y, test_size=0.2, random_state=0)
我们将使用交叉验证来确定最佳 alpha 值。默认情况下,岭回归交叉验证类使用留一个策略(k-fold)。我们可以通过观察均方误差来比较我们的模型在不同 alpha 值下的性能。
regressor = RidgeCV(alphas=[1, 1e3, 1e6], store_cv_values=True)regressor.fit(train_X, train_y)cv_mse = np.mean(regressor.cv_values_, axis=0)print(alphas)
print(cv_mse)
RidgeCV 类将自动选择最佳 alpha 值。我们可以通过访问以下属性来查看它。
# Best alpha
print(regressor.alpha_)
我们可以使用该模型来预测测试集的房价。
predict_y = regressor.predict(test_X)
最后,我们绘制测试集中的数据和在训练阶段确定的线。
plt.scatter(test_X, test_y);
plt.plot(test_X, predict_y, color='red')
plt.title('boston house prices')
plt.xlabel('average number of rooms per dwelling')
plt.ylabel('house prices')
plt.show()
机器学习和公民自由
从州诉卢米斯的刑事司法预测分析案例中我们能学到什么
By Royalbroil — Own work, CC BY-SA 3.0, https://commons.wikimedia.org/w/index.php?curid=31771291
法庭上预测分析的故事
2013 年,埃里克·卢米斯在威斯康星州被捕,并被指控五项与驾车枪击案有关的罪行。卢米斯否认参与枪击,但对两项指控认罪:试图逃避交通官员和未经车主同意驾驶车辆。
在判决阶段,Loomis 向法院提供信息,法院将根据法院的要求进行 COMPAS 风险评估评分。
COMPAS 是一种预测分析工具,它使用罪犯提供的信息和来自个人犯罪历史的信息,根据预测分析算法训练的特征对他们的特征进行分类,来估计累犯的风险,即在未来犯下更多罪行。
根据案件信息和 COMPAS 风险评估分数,法院判处卢米斯最高六年监禁和五年延长监管——这几乎是他承认的两项罪行的最高刑期。显然,COMPAS 评分将 Loomis 归类为累犯的高风险,这是法官量刑决定的一个因素。
对判决的上诉
也许是因为这两项罪行的量刑似乎不相称,卢米斯对判决提出上诉,理由是法院依赖 COMPAS 风险评估分数。他认为,这样做侵犯了他"被单独判刑和根据准确信息判刑的权利"。他进一步辩称,他因性别被判违宪,因为 COMPAS 算法考虑到了性别。
这些争论源于 COMPAS 是由私人公司 Equivant 提供给威斯康辛州政府的。由于这种安排,COMPAS 算法是公司的专有机密信息。威斯康辛州政府和被告都无法获得关于模型如何被训练的信息,哪些输入以任何特定的方式被加权,以及有问题的个人如何与所使用的训练数据进行具体比较。
威斯康星州最高法院维持了判决,驳回了正当程序的担忧。法院发现,COMPAS 工具只使用公开信息和个人提供的信息,因此 Loomis 可以验证它的准确性。此外,上诉法院发现,下级法院确实提供了个人量刑,因为即使分数是与处境类似的广泛群体相比较的总和,法院在最终裁决中有自由裁量权,可能不同意 COMPAS 的评估。
黑箱问题符合政府决策
这是对机器学习预测分析的“黑箱”性质的普遍恐惧或抱怨,尤其是那些被更复杂的模型所采用的机器学习预测分析。关于目前在美国和其他国家的刑事司法领域使用的机器学习程序的相关风险,已经有大量的报道和报告。然而,这些问题应该适用于机器学习融入政府决策的所有领域。
机器学习的黑匣子。用一个现在很有名的比喻来说,机器学习,特别是神经网络和深度学习等更复杂的技术,已经创造了一个黑盒,在这个黑盒中,模型的输出不能以各方可以知道单个结果的细节的方式进行反向工程。这一点已经被很好地记录下来,并继续在机器学习伦理论坛上激烈辩论。
许多关于个人的决定都有可能产生重大影响,改变生活。例如,金融机构关于延期或信贷或贷款的决定将直接影响某人买房或创业的能力。同样,卫生保健提供者和保险公司做出的决定会直接影响个人的健康或预期寿命。
政府机构和管理者所做的决定可以改变生活,如果不是更多的话。这是因为政府处于独特的地位,能够以私人实体无法做到的方式对一个人做出决定。例如,一个人的公民身份、关于其对国家的财政义务的决定(税收)、关于其公民自由的决定(被逮捕或监禁)以及关于其子女的决定(社会服务)。
由于政府对我们生活的广泛权力,我们在美国建立了程序性的制衡,以确保公民和个人明确他们的个人权利与政府权利,以及关于如何作出决定的明确指导方针,以及他们可以与政府互动并要求审查这些决定的机制。
其中许多法律的基础是宪法,但也有许多法律法规允许政府决策的透明度、对决策的上诉机制以及对决策的司法审查。
在刑事司法背景下,就像卢米斯案件一样,美国宪法第四和第五修正案是个人权利的基础,它试图平衡个人与政府的权利和权威。这些修正案结合起来,防止“不合理的”侵犯隐私和未经正当程序的搜查。
机器学习给正当程序带来的风险。
关于新技术如何影响美国法院如何适用第四修正案保护,有相当多的研究。最值得注意的是,已经出现了一种趋势,从仅仅解释它们以适用于防止对一个人的财产进行不合理的搜查,到保护他们的隐私,或者在我们的社会中可以合理地期望保持隐私的东西。
法院处理了这方面的许多变化。从担心有人在你的窗外偷听到了对公共付费电话亭的窃听(公共付费电话亭被认为是私人空间)。最近,最高法院更接近解决针对第四修正案保护的大数据隐私问题。
这一里程碑式的案件是美国诉琼斯,这是对一名男子因贩毒被定罪的上诉,其依据是通过他车上的 GPS 跟踪器获得的一个月的数据。虽然法院推翻了对跟踪搜查令技术违规的定罪,但法官们重点关注第四修正案的保护,他们认为基于收集的数据量,第四修正案受到了侵犯。
这是先前裁决的一个新的转折,先前的裁决坚持认为公民对在公共场所进行的行为没有隐私权。在公共场合开车,因此第四修正案不保护跟踪你的驾驶。然而,在这种情况下,法官做出了区分,即对于一个普通公民来说,期望他们一个月的所有驾驶都会被跟踪和记录是不合理的,因此这种 GPS 搜索侵犯了琼斯反对不合理搜索的权利。此后,这种现象被称为“马赛克效应”,更多的公开信息可以以可能侵犯个人隐私的方式进行汇编和组合。
从 GPS 到大数据。与 GPS 为执法部门提供跟踪潜在嫌疑人的新方法类似,政府机构也实施了大数据和机器学习,以瞄准警察巡逻队,对与警察互动的个人的风险进行分类,量化和预测犯罪将在哪里发生,正如我们在 Loomis 中看到的那样,根据再次犯罪的风险进行判决。
许多这些机器学习程序是由私营公司为政府创建的。因此,就像 COMPAS 一样,其设计、培训和维护的细节并不为受其影响的公民的政府所知。自从卢米斯案件以来,有广泛报道COMPAS 声称显示它是有偏见的,它的预测不是很准确。
除了这些非常现实的问题之外,人们还担心,在没有具体的第四修正案和隐私控制的情况下,政府可以在多大程度上使用这些技术来创建个人资料和收集公民信息。在马赛克效应下,这些公共信息可以被用来描述公民,政府有可能知道合理预期为私人的信息。
根据第四修正案的当前解释,这将引发一项禁令,禁止政府使用这些信息或以这些方式汇编信息,这些方式列出了由独立实体审查和批准的具体问题。
下一步是什么?
在琼斯案中,最高法院没有要求这项禁令和程序,但可以说我们的政府将不得不在许多不同的背景下处理机器学习和预测分析的现实,在这些背景下,政府被鼓励利用他们可以利用的一切优势;例如治安、刑事司法、情报以及执法与保护个人隐私和提供正当程序之间存在矛盾的其他领域。
我们在美国没有积极解决这些问题的良好记录。更有可能的是,我们将不得不等到出现一种司法情况,迫使法院作出法律裁决,以更好地界定这些界限应该划在哪里。同样可能的是,一个类似的情况将进入该国的政治和媒体意识,以某种方式集中公众的注意力,迫使立法行动,更好地界定这些线和要求。
然而,无论是哪种情况,最终的导火索都将是许多理性的公民认为政府使用这些技术的方式侵犯了我们对隐私权的看法,并威胁到“监控国家”——随之而来的是对言论和表达自由等其他权利的寒蝉效应。
不过,我个人的希望是,公民、企业和政治家可以开始以有效的方式讨论这些考虑因素,为法律、政策和程序奠定基础,使政府能够以有益于我们国家的方式从这些技术中受益,而不会对作为我们国家和社会文化基础的权利产生负面影响。
机器学习和数据分析—仁荷大学(第一部分)
第 1 章:基本 python 和安装
大家好。我是韩国仁荷大学的研究生。虽然我不是计算机科学出身,但这十年来数据科学和机器学习的吸引力使我对数据科学产生了兴趣,因此我开始学习 python,并准备好完成预期的结果。今年秋天,我参加了由造船&海洋工程系开设的机器学习和数据分析课程。我将试着简要描述一下我通过这门课程学到了什么和取得了什么。
Learning Tools for Data mining and ML
该图显示了最流行的机器学习(ML)和数据挖掘工具。对于数据挖掘 R 和 MATLAB,对于 ML Python,使用最多的是 Keras 和 TensorFlow。实现机器学习算法的平台有好几个,比如 Azure,KT ucloude,IBM cloud。我们也可以使用 Google 的 colab 来实现 ML 项目,因为它提供了免费的 GPU(图形处理单元)。下图显示了截至 2014 年对 python 的需求,由于 python 是一种简单的语言,易于学习且用户友好,因此需求增长迅速。大多数编程语言需要编译,而 python 不需要编译,它按原样解释源代码。
Programming Language Usage Status in 2014
1989 年, 吉多·范·罗苏姆 ,一个荷兰程序员因为圣诞节期间无事可做,开发了 Python 😂。Python 这个名字来源于喜剧节目《巨蟒剧团的飞行马戏团》。Python 的本义是希腊神话中的巨蛇。谷歌和 youtube 上有很多教程,你可以很容易地找到如何在你的操作系统中安装 Python。只需跟随网站并下载您期望的版本。
安装后,您可以打开命令提示符,检查 python 的版本,并在那里模拟编程。
现在有几种方法可以在 python 中运行程序,比如使用记事本、 、原子 或 崇高 文本编辑器来编写代码,并使用命令外壳来运行它。或者我们可以使用一些集成开发环境( IDE ),我们可以同时编写和运行。 Pycharm ,Anaconda或Visual studio code都是 ide 的例子。****
现在我们将讨论 Anaconda 在 windows 操作系统中的安装。 Anaconda 是 Python 数据科学的标准平台,引领机器学习的开源创新。你可以通过编程知识和 Tech with Tim youtube 频道按照这两个链接正确安装 anaconda。对于 Pycharm 安装,您可以使用 Tim 和编程知识 2 遵循技术。这些视频教程都是基于 windows 操作系统的。在安装Anaconda时,你需要小心选择环境变量的路径。您需要选择高级选项将 anaconda 添加到系统路径环境变量中。这是因为如果之前安装了任何其他 python IDE,那么路径将被合并,不会出现错误。********
使用 Anaconda 作为 IDE 的另一个重要因素是,它可以为特定需求提供一个虚拟环境。假设您已经安装了 Anaconda,其中安装了 python 3.7 版本,但是您需要 python 3.6 来完成一些特定的任务,那么您可以轻松地创建一个虚拟环境,并在其上模拟您的程序。另一个问题是一些库可能会对已安装的软件包版本产生问题。因此,为了避免这种问题,我们应该创建一个虚拟环境,并在其上安装所需的软件包。
通常在 Anaconda 中,大多数库都是默认安装的。但是,如果您想安装任何库,那么您需要遵循以下步骤:
以管理员身份运行命令提示符。
升级 pip 类型: python -m pip 安装—升级 pip
类型: pip 安装“库名”(例如。pip install numpy)/conda install numpy
卸载类型: pip 卸载“库名”(例如。pip 卸载编号)
你可以写 pip 或者 conda 来安装库。
Python 库(Numpy)
一个帮助你使用 Python 语言执行矩阵运算的库。Numpy 是 Python 中科学计算的核心库。Numpy 数组都是由相同类型的值构造的,并作为整数元组进行索引。维数是数组的秩,数组的形状是一个整数元组,告诉每个维的大小。您需要将Numpy
作为np
导入。你可以用任何东西代替 np,但是为了更好的理解和用户友好的代码,推荐使用np
。
Numpy-array:
numpy 数组是由相同类型的值组成的网格,由一组非负整数索引。维数是数组的秩;数组的形状是一组整数,给出了数组在每个维度上的大小。我们可以从嵌套的 Python 列表中初始化 numpy 数组,并使用方括号访问元素。
Numpy 还提供了许多创建数组的函数:
********
Numpy 提供了几种方法来索引数组。
array slicing
:类似于 Python 列表,numpy 数组可以切片。由于数组可能是多维的,因此必须为数组的每个维度指定一个切片:
array indexing
:也可以混合整数索引和切片索引。但是,这样做将产生一个比原始数组秩更低的数组。注意,这与 MATLAB 处理数组切片的方式非常不同。访问数组中间行数据的两种方法。将整数索引与切片混合会产生一个较低秩的数组,而仅使用切片会产生一个与原始数组相同秩的数组:
在制作了 3 行 4 列的矩阵后,将(row) row_r1 设置为二维数组。然后,你可以很容易地得到矩阵的形状。
array math
:基本数学函数在数组上按元素操作,既可作为运算符重载,也可作为 numpy 模块中的函数。
Broadcasting
:广播是一种强大的机制,允许 numpy 在执行算术运算时处理不同形状的数组。通常我们有一个较小的数组和一个较大的数组,我们希望多次使用较小的数组来对较大的数组执行一些操作。例如,假设我们想给矩阵的每一行添加一个常量向量。我们可以这样做:
Adding [1, 0, 1] to all the Row of Matrix X
用 python 绘图(MATPLOTLIB)
Matplotlib 是一个库,使我们能够绘制图形,类似于 MATLAB 系统。这是一个非常棒的 Python 可视化库,用于数组的 2D 绘图。
**import matplotlib.pyplot as pltimport numpy as npx =np.arange(0,3*np.pi,.1)
y = np.sin(x)
# Plot the points using matplotlib
plt.plot(x, y)
plt.show()**
要使用 matplotlib 库,您需要将其调用为 plt。 我们还可以通过这个库添加 xlabel 、 ylabel 、 title 。
**import matplotlib.pyplot as pltimport numpy as npx =np.arange(0,3*np.pi,.1)
y_sin = np.sin(x)
y_cos = np.cos(x)
# Plot the points using matplotlib
plt.plot(x, y_sin)
plt.plot(x, y_cos)
plt.xlabel('x axis label')
plt.ylabel('y axis label')
plt.title('Sine and Cosine')
plt.legend(['Sine', 'Cosine'])
plt.show()**
在本文中,我试图给出一些关于 python 编程语言和 Windows 操作系统中 Python 模拟环境的基本概念。如果有人为更好的结果提供指导或批评,我们将不胜感激。在这里,我试图描述 python numpy 和 matplotlib 库,它们在数据科学领域非常基础。在本系列的第二部分,我已经用 python 描述了数据结构和。你可以点击下面的链接来看看。
第 2 章:Python 数据结构—数据类型
towardsdatascience.com](/machine-learning-and-data-analysis-inha-university-part-2-3fb599732021)
近期想做一篇关于如何在 anaconda 中创建一个 虚拟环境 的文章。我希望这个视频能够帮助那些 python 和数据科学领域的新手。我会试着继续这个系列,并放一些 GitHub 库以便更好地理解。如果你喜欢这篇文章,你可以看看我的其他文章:
面向对象编程(OOP)是一种基于“对象”的编程范式,它是一种用面向对象的语言来定义事物的方法
towardsdatascience.com](/python-oop-corey-schafer-datacamp-be6b0b3cafc6) [## 降价单元格— Jupyter 笔记本
我不知道如何开始。这将是我第一个与编程相关的故事。今天我将努力缩小…
towardsdatascience.com](/markdown-cells-jupyter-notebook-d3bea8416671)
参考链接:
- 安装 python,anaconda:https://www.youtube.com/watch?v=5mDYijMfSzs&t = 4s
- 安装 py charm:https://www.youtube.com/watch?v=SZUNUB6nz3g
或,https://www.youtube.com/watch?v=56bPIGf4us0&t = 15s - 安装蟒蛇:https://www.youtube.com/watch?v=mIB7IZFCE_k****
机器学习和数据分析—仁荷大学(第二部分)
第 2 章:Python 数据结构—数据类型
欢迎来到基于韩国仁荷大学研究生课程的机器学习和数据分析系列的第二部分。在这一部分,我们将讨论 python 中的数据结构。然而,如果你是第一次看这篇文章,我们鼓励你先看第一部分,在那里我们讨论了基本的 python,像 Anaconda,Pycharm 这样的 ide 的安装,以及一些 python 库,像 Numpy,Matplotlib 等等。
第 1 章:基本 Python 和安装
towardsdatascience.com](/machine-learning-and-data-analysis-inha-university-part-1-be288b619fb5)
数据结构是编程语言在你的计算机上存储数据的不同方式,以便数据可以被容易地访问和有效地工作。它基本上定义了数据和对数据执行的不同操作之间的关系。一般来说,数据结构分为两类:原语和非原语数据结构。整数、浮点、字符串和布尔是基本的数据结构,有时称为数据操作的构建块,包含在原始数据结构中。数组、列表、元组、集合、字典都包含在非原始数据结构中。在本文中,我们将讨论以下数据类型:
- 1。标量(整数、浮点、布尔、无)
- 2。字符串
- 3。字节
- 4。列表
- 5。元组
- 6。字典
- 7。设置
- 8。布尔
1.标量(整数、浮点、布尔、无)
标量是一种可以有单个值的类型,如5
、3.14
或'Arman'
。有时字符串也被认为是一个标量,但在这里我们单独描述它。Python 附带了许多内置的数据类型。基本的内置标量类型有:
int
—带符号的无限精度整数float
—浮点数None
—特殊的奇异空值bool
—true
/false
布尔值
Scalar Data Types
Data types in numeric form
Python 有一个名为None
的特殊空值,用大写字母 n 拼写。None 常用来表示没有值。
2.字符串
字符串是由字母、单词或其他字符组成的字符序列。在 Python 中,可以通过在一对单引号或双引号中包含一系列字符来创建字符串。比如:'Saman'
、"12345"
等。python 中使用了几个转义序列,比如新行的\n
和双引号的\"
等等。点击此链接可以找到更多信息。下图中显示了字符串索引、、、切片、串联、和重复。
String indexing, Slicing, concatenation, repetition
字符串是不可变的,这意味着你不能覆盖不可变的对象的值。但是,您可以再次分配变量,这将创建一个新对象,或者您可以用替换字符串部分,我们可以在下图中观察到。几种串法,包括find()
、replace()
、split()
、upper()
、rstrip()
等。在这里被描述。
Several String methods
String Methods: %, format()
String Methods: %d, %f, separator
3.字节
bytes ()方法返回用给定大小和数据初始化的不可变 bytes 对象。 bytes ()方法返回一个 bytes 对象,它是范围0<=x<256
内的一个不可变(不能修改)的整数序列。
计算机唯一能存储的是“字节”。
- 编码以字节表示音频、图像、文本等。
- 要保存音乐,您必须首先使用 MP3、WAV 等进行编码。
- 要保存图片,你需要用 PNG,JPEG 等编码。
- 要保存文本,首先使用 ASCII、UTF-8 等进行编码。
- MP3、WAV、PNG、JPEG、ASCII 和 UTF-8 都是编码的例子。
Example of Bytes class (\ = crossed W)
4.列表
一个列表是允许你添加、更新或删除元素的元素集合。数组大小可自由扩展,元素是可变的,用逗号分隔,没有元素的空列表表示为。
List indexing, addition, and some methods
List Comprehensions
List Methods
5.元组
一个元组是一系列不可变的 Python 对象。元组是序列,就像列表一样。元组和列表的区别在于,元组不能像列表那样改变,元组使用括号,而列表使用方括号。下面三幅图展示了元组串联、索引、不变性等几种操作,以及、open()
、write()
和read()
等几种元组方法。在文本文件上写东西时,你需要使用close()
关闭它。要运行它,你需要输入cat "Filename.txt"
。对于阅读,你可以遵循第三图所示的几种方法,如从文件中读取文本,逐行阅读等。
Tuples and tuple methods
Tuple: Files, open(), write()
Tuple: read()
6.字典
字典是一组key:value
对,其中key
用于标识条目,而value
保存条目的值。字典中的所有键必须是唯一的(可散列的)。下面三幅图展示了字典是如何形成的,以及字典的可变性和索引方法。
Dictionary
Dictionary: keyword arguments, zipping
7.一组
集合是 唯一 元素的无序集合。集合是可变的、无序的、唯一的对象,这在遍历庞大的数据集时非常有效。集合中的元素必须是可哈希的。下面三幅图概括了 set 的形成、操作和方法。
Creating a set and set operations
Set Operations
Set Methods
8.布尔
这个内置的数据类型可以取值:True
和False
,这通常使它们可以与整数 1 和 0 互换。
Boolean
在本文中,我们总结了 Python 中的数据类型。在本系列的下一部分,我们将讨论控制语句 (if、for、while 等。)在 Python 中。如果有人在这篇文章或以后的文章中为更好的结果提供指导或批评,我们将非常感激。如果你喜欢这篇文章,你可以关注我关于数据科学几个问题的其他文章。
参考链接:
- Python 数据类型 cheat sheet:http://www . cog sci . rpi . edu/~ destem/igd/Python _ cheat _ sheet . pdf
https://clouds . EOS . UBC . ca/~ Phil/courses/eosc 582/pdf files/Python-Data-manipulations . pdf - Python 备忘单:http://datasciencefree.com/python.pdf
- https://www . data camp . com/community/tutorials/data-structures-python
- https://www.programiz.com/python-programming
- https://www.tutorialspoint.com/python/
机器学习和数据分析—仁荷大学(第三部分)
Python 中的控制语句(循环)
这是由大韩民国仁荷大学(T2)提供的机器学习和数据分析系列的第三个教程。在本文中,我们将学习 Python 中的循环控制语句。如果你想了解这个系列,那么你可以看看我们之前关于这个系列的文章。链接如下:
第 1 章:基本 Python 和安装
towardsdatascience.com](/machine-learning-and-data-analysis-inha-university-part-1-be288b619fb5) [## 机器学习和数据分析—仁荷大学(第二部分)
第 2 章:Python 数据结构—数据类型
towardsdatascience.com](/machine-learning-and-data-analysis-inha-university-part-2-3fb599732021)
在本文中,我们将讨论 Python 中的以下循环控制语句:
- 1。if 语句
- 2。while 循环
- 3。for 循环
- 4。断开
- 5。继续
- 6。通过
1.如果语句
if
是最简单的决策语句,用于决定是否执行某个语句或语句块。如果任何语句块为真,那么结果将被执行,否则不会被执行。Python 支持数学中常见的逻辑条件:
Logical operators in Python
控制语句 if: 这些条件可以以多种方式使用,最常见于“if 语句”和循环中。
single if and if-else selection structure flow chart with the operation.
if/elif/else Selection Structure
example of if statement
在上面提到的图中,我们试图展示 if-else 选择结构的操作流程图和一些例子。通常情况下提出条件后。如果条件为真,那么if/elif/else
将执行它下面的语句块,否则不执行。语句本身告诉我们,如果条件为真,它将执行一组语句,如果条件为假,则不会执行。但是如果条件为假,我们想做别的事情呢。else
语句来了。我们可以使用else
语句和if
语句在条件为假时执行一段代码。当条件数量较多时,最好使用if-elif-else
结构,只有当其他条件都不为真时,才会执行 else 语句。elif
是else if
的简称。嵌套的 if
是一个if
语句,它是另一个if
语句的目标。嵌套的if
语句意味着一个if
语句在另一个if
语句内。
#Nested if statement only execute if statement above it is true.
i **=** 52
**if** (i **==** 52):
**if** (i < 60):
**print** ("i is smaller than 60")
**if** (i < 55):
**print**("i is smaller than 55 too")
**else**:
**print**("i is greater than 60").
输出:
i is smaller than 60
i is smaller than 55 too
2.while 循环
while
循环只要测试表达式(条件)为真,就迭代一段代码。如果事先不知道循环将重复多少次,可以使用这种类型的循环(强大的循环类型)。如图所示,只要测试表达式评估为真,while
结构就会执行代码块。
i = 1
**while** i < 6:
**print**(i)
i += 1
请注意,确保代码块包含修改是很重要的:如果我们忘记了上面示例中的行i+=1
,那么while
循环就会变成一个无限循环。嵌套的while
循环允许在另一个while
循环中使用一个while
循环。
3.for 循环
最基本类型的确定循环是for
循环。它用于迭代序列(列表、元组、字符串)或其他可迭代对象。遍历一个序列叫做遍历。使用for
循环,我们可以执行一组语句,对列表、元组、集合等中的每一项执行一次。如下图for
的通用格式所示,for
循环遍历列表对象中目标的所有可能值,每次执行语句。嵌套for
循环的一个例子也在这里说明。
for Loop
**for** var **in** seq:
**for** var **in** seq:
statements(s)
statements(s)
4.破裂
break
语句终止包含它的循环。程序的控制直接流向循环体之后的语句。如果break
语句在嵌套循环内(循环在另一个循环内),break
将终止最里面的循环。break
最常见的用途是当某些外部条件被触发时,需要快速退出循环。如下图所示,break
语句可用于while
和for
循环。
break statement structure flow chart with operation example in for and while loop
for val in "string":
if val == "i":
break
print(val)
print("The end")
输出:
s
t
r
The end
5.及格
Python 中的pass
语句在语法上需要一个语句,但您不想执行任何命令或代码时使用。pass
语句是一个空操作;它执行的时候什么都不会发生。这个pass
在你的代码最终要去但还没有被编写的地方也是有用的。
for letter in 'Arman':
if letter == 'm':
pass
print ('This is pass block')
print ('Current Letter :', letter)
print ("See you!")
输出:
Current Letter : A
Current Letter : r
This is pass block
Current Letter : m
Current Letter : a
Current Letter : n
See you!
当您创建了一个代码块,但不再需要它时,pass
语句很有用。然后,您可以删除该块中的语句,但让该块保留一个pass
语句,这样它就不会干扰代码的其他部分。
6.继续
continue
语句用于仅在当前迭代中跳过循环中的剩余代码。循环不会终止,而是继续进行下一次迭代。continue
语句可以在while
和for
循环中使用。
continue statement structure flow chart with operation example in for and while loop
for val in "Arman":
if val == "m":
continue
print(val)
print("The end")
输出:
A
r
a
n
The end
在下图中,我们试图显示while
循环下的pass
、break
和continue
、语句。希望有助于清晰理解概念。
Example of pass, break and continue statements in while loop.
在本教程中,我们尽最大努力使 Python 中积累的循环控制语句简洁。可以浏览一篇只描述for
/ if-else
/ while
循环的文章。但是我们使它简洁,并试图以兼容的方式描述,使它对 Python 新手有利可图。在本系列的下一部分,我们将描述 Python 中的内置和用户自定义 函数和模块。
感谢您宝贵的时间。任何类型的建议或批评都是值得的,这样我们可以确保在未来的教程中有更好的表现。
参考链接:
- https://www.geeksforgeeks.org/loops-in-python/
- 【https://www.tutorialspoint.com/python/python_loops.htm】
- http://nook . cs . UC Davis . edu/~ koehl/Teaching/ECS 15/lections/Python _ chapter 3 . pdf
- https://www . tutorialspoint . com/python/pdf/python _ loop _ control . pdf
- http://pages . CPSC . u Calgary . ca/~ tamj/2008/217 w/notes/acrobat/loops . pdf
机器学习和数据分析—仁荷大学(第四部分)
Python 函数和模块
现在让我们关注 Python 中的函数。一个函数是一段代码,只在被调用时运行。您可以将数据(称为参数)传递给函数。函数可以返回数据作为结果。它是一组执行特定任务的相关语句。
Syntax of Function
调用函数
要调用一个函数,使用函数名后跟括号:
def **my_function**():
print("Hello from a function")
**my_function()**
输出:
Hello from a function
每当您调用函数my_function
时,您都会得到打印语句作为结果。有两种类型的函数:内置函数和用户自定义函数。内置函数内置到 python 中就像print()
、abs()
、sum()
都是内置函数。用户自定义功能和my_function
功能一样,由用户自己定义。
方法中的参数(自变量)
变量或参数是可以作为参数传递给函数的信息。参数在函数名后面的括号内指定。添加任意数量的参数,用逗号分隔即可。在下面的例子中,我们在sum()
函数的括号内传递a,b
参数,函数将返回两个参数的和。我们还可以提到括号内的参数值,称为默认参数值,然后可以调用该函数,默认参数输出没有参数,或者不同结果有不同的参数值。比如,如果我们像sum(a=4,b=8)
一样定义下面的函数,那么我们可以将 total 定义为sum()
来获得默认参数输出,或者sum(10,12)
来利用不同于默认参数的值。
**def** sum(a, b):
s = a + b
**return** s
total = **sum**(4, 7)
print(total)
输出:
11
列表作为参数:我们可以将参数的任何数据类型发送给函数(字符串、数字、列表、字典等。List 也可以作为函数中的一个参数。在下面的例子中,列表fruits
作为一个参数。
def **my_function**(food):
"""*how lists are used as a parameter in function.*"""
for x in food:
print(x)
fruits = ["apple", "banana", "cherry"]
**my_function**(fruits)
输出:
apple
banana
cherry
有时在函数头后面会提到一个字符串,用来简单解释函数的作用。这个字符串叫做 Docstring 。像上面的例子一样,在my_function(food)
之后的文档串用于描述函数。
全局变量:在 Python 代码主体中创建的变量是全局变量。全局变量可以在任何范围内使用,无论是全局的还是局部的。
局部变量:在函数内部创建的变量属于该函数的局部作用域,只能在该函数内部使用。
非局部变量:非局部变量用于未定义局部范围的嵌套函数中。这意味着变量既不能在局部范围内,也不能在全局范围内。
Example of Local and Global variable and their usage.
你可以在一个函数中调用任何一个全局变量,只有当它像global x
一样被调用时才改变它的值,这里 x 是变量。
Python 中的模块
简单来说, 模块 是指包含 Python 语句和定义的文件。包含 Python 代码的文件,例如: example.py ,称为模块,其模块名就是一个例子。我们使用模块将大型程序分解成易于管理和组织的小文件。此外,模块提供了代码的可重用性。我们可以在一个模块中定义我们最常用的函数并导入,而不是把它们的定义复制到不同的程序中。模块可以是三种类型:内置 模块 ( 数学、平台等。)、添加模块 ( Numpy 、 matplotlib 、 scikit-learn 、 keras 、 scipy 等。),以及用户自定义模块(可以像 module_name.py 一样自己定义)。要定义一个用户定义的模块,你需要使用任何文本编辑器,如 Atom 或 sublime text 来创建一个文本文件,该文件应该保存为.py
,然后在该目录下你可以创建另一个文件,在该文件中你可以调用该模块的任何函数,如下例所示。
Example of Add on, Built-in, and user-defined modules.
我们可以使用dir()
函数找出定义在一个模块内部的名字。
Modules with dir() built-in function
我们可以从一个模块中导入特定的名称,而不用将该模块作为一个整体导入。通过使用 from 关键字,可以选择只从一个模块导入零件。Python 中有几个内置模块,可以随时导入。您可以在导入模块时创建一个别名,通过使用 作为 关键字。
Importing & Renaming modules
本教程到此结束。希望一切都更容易穿透。本系列的嵌套部分“Python 中的面向对象编程 ”已经出版。你可以点击下面的链接阅读这篇文章:
面向对象编程(OOP)是一种基于“对象”的编程范式,它是一种用面向对象的语言来定义事物的方法
towardsdatascience.com](/python-oop-corey-schafer-datacamp-be6b0b3cafc6)
从下一篇文章开始,我们将利用 Scikit-learn 库来关注 Python 中的机器学习,这是一个非常流行的机器学习算法库。感谢您的宝贵时间,非常感谢您的任何建议或批评。
为机器学习处理数据中的歧视性偏差
当数据告诉你是种族主义者时,你会怎么做?
“算法当然是种族主义的。它们是由人制造的。”——斯蒂芬·布什,美国新政治家
机器学习中的伦理
大多数时候,机器学习不会触及特别敏感的社会、道德或伦理问题。有人给了我们一个数据集,并要求我们根据给定的属性预测房价,将图片分为不同的类别,或者教计算机玩 PAC-MAN 的最佳方式——当我们被要求根据反歧视法预测受保护的属性时,我们该怎么办?
我们如何确保我们不会在我们的算法中嵌入种族主义、性别歧视或其他潜在的偏见,无论是明确的还是隐含的?
你可能不会感到惊讶,在美国有几起关于这个主题的重要诉讼,可能最著名的是涉及 Northpointe 有争议的 COMPAS——替代制裁的矫正罪犯管理概况——软件,该软件预测被告再次犯罪的风险。专有算法考虑了 137 项问卷调查的部分答案来预测这种风险。
2013 年 2 月,Eric Loomis 被发现驾驶一辆曾用于枪击的汽车。他被捕了,并承认躲避警察。在量刑时,法官不仅要看他的犯罪记录,还要看一个叫 COMPAS 的工具给出的分数。
COMPAS 是目前在美国使用的几种风险评估算法之一,用于预测暴力犯罪的热点,确定囚犯可能需要的监督类型,或者像 Loomis 的案件一样,提供可能对判决有用的信息。COMPAS 将他列为重新犯罪的高风险,卢米斯被判 6 年。
他对该裁决提出上诉,理由是法官在考虑一种算法的结果时,违反了正当程序,这种算法的内部工作是秘密的,不能被检查。上诉到了威斯康辛州最高法院,最高法院做出了不利于卢米斯的裁决,指出如果没有咨询过 COMPAS,判决将是一样的。然而,他们的裁决呼吁对算法的使用要谨慎和怀疑。
可以理解的是,这个案件在机器学习社区引起了轩然大波——我怀疑任何人都希望被算法评判,毕竟,你不能指责算法不道德,你能吗?
争议愈演愈烈
到目前为止,我们所讨论的是一个据称不公正的人,据称他受到了算法的严厉审判。然而,当我们快进到 2014 年时,这款软件背后的争议变得更加激烈。
在几个更有争议的结果被从算法中剔除并仔细检查后,它再次吸引了公众的目光。然后,美国司法部长埃里克·霍尔德警告说,风险评分可能会给法院带来偏见。他呼吁美国量刑委员会研究它们的使用。“虽然这些措施是出于最良好的意图,但我担心它们会无意中破坏我们确保个性化和平等司法的努力,”他说,并补充说,“它们可能会加剧毫无根据和不公正的差距,这些差距在我们的刑事司法系统和我们的社会中已经太常见了。”
然而,判决委员会并没有开展风险评分的研究。因此 ProPublica 做了,作为对算法在美国生活中强大的、很大程度上隐藏的影响的更大检查的一部分。
ProPublica 的研究得出了一些有趣的结论。该算法不仅荒谬地不准确(只有不到 20%的预测是正确的),而且正如霍尔德所担心的那样,它还显示出明显的种族差异。在预测谁会再次犯罪时,该算法对黑人和白人被告犯错误的比率大致相同,但方式非常不同。
- 这个公式很有可能错误地将黑人被告标记为未来的罪犯,错误地将他们标记为未来罪犯的比率几乎是白人被告的两倍。
- 白人被告比黑人被告更容易被误贴上低风险的标签。
黑人被告仍有 77%的可能性被认定为未来暴力犯罪的高风险,45%的可能性被预测为未来会犯罪。
这听起来可能很糟糕,但这个故事并不像看上去那样简单。根据我们分析这一点的方式,我们可以发现该算法既是种族主义者又不是种族主义者,这取决于我们在我们的模型中定义‘平等’的方式。在本文的剩余部分,我将试图帮助我们理解这个模型实际上是以一种可接受的方式设计的,但是仍然会产生据称是种族主义的结果。
歧视的类型
我们首先需要定义算法中可能存在的歧视类型,以及我们在前面的例子中处理的是哪种歧视。有两种形式的歧视,我们称之为不同的影响和不同的待遇。
不同的待遇— 涉及以不允许的方式对某人进行分类。它涉及歧视的意图,通过明确提及群体成员资格得到证明。
不同的影响— 查看分类/决策对特定群体的影响。不需要意图,表面上是中性的。
不同的影响通常被称为无意的歧视,而不同的待遇是有意的。
最高法院认为,对特定群体产生不相称影响的做法,如果“基于合理的商业考虑”,就不会造成不同的影响。
当考虑以下任何受保护的属性时,可能会导致不同的处理或不同的影响。
所有这些属性都可以在我们的机器学习算法中用作特征,因此我们的算法有可能在这些属性的基础上进行区分。一些常见的例子是面部识别、惯犯(如前所述)和雇佣。我们能做些什么来帮助解决这个问题呢?
反对不同的待遇很容易。明显的歧视性偏见使得分类不太准确,所以没有很好的理由这样做。然而,当歧视被嵌入历史数据中时,情况又如何呢?或者这些属性是过去的社会不公正的结果,至今仍然存在?
培训数据中的歧视性偏见
当分类和决策基于不准确的信息时(例如,认为每个超过 7 英尺的人都是糟糕的保姆),歧视会影响社会公益。这些想法经常被人类的偏见所延续,并嵌入到用于训练算法的数据中。
在这种情况下,机器学习算法不会减轻人类的偏见。事实上,它们在分类中被复制。为什么会这样?由 Northpointe 软件得出的累犯分数是基于以前的逮捕、第一次接触警察的年龄、父母的监禁记录。这些信息是由世界上的偏见(如文化价值观和民族主义)和更普遍的不公正(如种族偏见)形成的。
这种偏见也存在于侧重于文本数据的自然语言处理中。一个很好的例子是一篇题为“男人对于电脑程序员就像女人对于家庭主妇?去偏置词嵌入”,它显示了从软件的向量自动生成的类比,例如男人→计算机程序员,女人→家庭主妇。这些反映了原文中的性别歧视。
更一般地说,这些偏差来源通常来自:
- 过采样和欠采样
- 倾斜样本
- 功能选择/有限功能
- 代理/冗余编码
- 世界上的偏见和不公正
那么我们如何消除这些偏见呢?机器学习算法可以使歧视永久化,因为它们是在有偏见的数据上训练的。解决方案是识别或生成一个无偏的数据集,从中得出准确的概括。
消除偏见
种族、性别和社会经济阶层等特征决定了我们与某些执行任务的结果相关的其他特征。这些都是受保护的属性,但它们仍然与某些性能任务相关——而且这些性能任务是公认的社会商品。例如:
- 白人家庭的平均财富比黑人家庭的平均财富高七倍。
- 财富与你能否偿还贷款有关。
- 财富的差异是由历史和现实的不公平决定的。
机器学习本质上是历史的。为了有效打击歧视,我们需要改变这些模式。然而,机器学习强化了这些模式。因此,机器学习可能是问题的一部分。
“即使历史是一条弯向正义的弧线,机器学习也不会弯曲。”
那么,我们该何去何从呢?我们注定会有种族主义和性别歧视的算法吗?
即使当我们优化准确性时,机器学习算法也可能使歧视永久化,即使我们从一个无偏见的数据集工作,并且有一个考虑到社会公益的性能任务。我们还能做什么?
- 顺序学习
- 更多理论
- 因果建模
- 优化公平性
在所有这些方法中,为公平而优化似乎是最容易也是最好的方法。在下一节,我们将概述如何优化一个模型的公平性。
优化公平性
可以通过 4 种方式构建针对非歧视性进行优化的机器学习算法:
- 正式确定不歧视标准
- 人口均等
- 均等的赔率
- 校准良好的系统
我们将依次讨论这些问题。
非歧视标准的形式化实质上是其他 3 种方法所涉及的内容,它们是旨在将非歧视标准形式化的标准类型。然而,这个列表并不详尽,可能有更好的方法尚未被提出。
人口统计均等提出决策(目标变量)应该独立于受保护的属性——种族、性别等。与决定无关。
对于二元决策 Y 和受保护的属性 A:
P(Y=1 ∣ A=0) = P(Y=1∣A=1)
无论受保护的属性是(A=1)还是(A=0),做出某些决策的概率(Y=1)应该是相同的。然而,人口统计的均等性排除了使用完美的预测值 C=Y,其中 C 是预测值,Y 是目标变量。
为了理解这种异议,请考虑下面的例子。假设我们想预测一个人是否会购买有机洗发水。某些群体的成员是否购买有机洗发水与他们是否属于该群体无关。但是,人口统计学上的均等将排除使用完美预测的可能性。所以也许这不是最好的程序,也许其他的会给我们一个更好的结果?
均衡赔率建议预测值和受保护属性应该是独立的,以结果为条件。对于预测值 R、结果 Y 和受保护的属性 A,其中三者都是二元变量:
P(R=1|A=0,Y=1) = P(R=1|A=1,Y=1)。
属性(无论是(A=1)还是(A=0))不应改变您对某个相关预测值(R=1)符合候选人的可能性的估计(P)。相反,(某些决策的)结果(Y=1)应该是。这种方法的一个优点是它与理想预测值 R=Y 兼容。
考虑下面这个案例,一个学生被耶鲁大学录取,假设他们是高中的毕业生代表。均等赔率假设知道学生是否是同性恋不会改变学生是否是毕业生代表的概率。
预测 R =你是否是高中毕业生代表(1)还是(0)
结果 Y =进耶鲁(1)或不进(0)
属性 A =同性恋(1),异性恋(0)
P(R=1| A=0,Y=1) = P(R=1| A=1,Y=1)。
校准良好的系统认为结果和受保护的属性是独立的,取决于预测器。对于预测值 R、结果 Y 和受保护的属性 A,其中三者都是二元变量:
P(Y=1|A=0,R=1) = P(Y=1|A=1,R=1)
某个结果发生的概率(Y=1)应该不受某个受保护属性的影响(无论是(A=0)还是(A=1)),而是应该取决于相关的预测值(R=1)。这种表述的优势在于它没有群体意识——它让每个人都遵循同样的标准。
与我们之前的例子相比,知道学生是同性恋并不会改变学生是否被耶鲁大学录取的概率。均衡的赔率和校准良好的系统之间的区别是微妙的,但很重要。
事实上,这种差异是我们在开始时讨论的关于 COMPAS 软件的分歧的基础。
那么康帕斯是种族主义者吗?
均等的赔率和良好校准的系统是互不相容的标准。有时,在特定的经验环境下,我们无法让一个系统既能很好地校准,又能均衡胜算。让我们在 ProPublica 和 Northpointe 关于 COMPAS 是否对黑人被告有偏见的辩论的背景下看看这个事实。
Y =被告是否会再次犯罪
A =被告的种族
r = COMPAS 使用的累犯预测值
Northpointe 的辩护: COMPAS 校准良好,即,
P(Y=1|A=0,R=1) = P(Y=1|A=1,R=1)。
COMPAS 系统对被告做出大致相似的再犯预测,不管他们是什么种族。
ProPublica 的反驳: COMPAS 对黑人被告的假阳性率较高,对白人被告的假阴性率较高,即不满足均等赔率:
P(R=1|A=0,Y=1) ≠ P(R=1|A=1,Y=1)
Source: Washington Post
被告的种族对个人是否被列入低风险或中/高风险类别有影响。(A=0)或(A=1)是否对 COMPAS 已经识别出被告的一些累犯风险预测者将持有的概率(P(R=1))有影响,而不仅仅是被告是否会/不会再犯(Y=1)。
为什么会这样?
当某些经验事实成立时,我们拥有一个校准良好的、赔率均衡系统的能力就会崩溃。似乎产生问题的是我们之前讨论过的东西:不公正造成的背景事实。例如,由于更严格的警察审查,再次犯罪的被抓率更高。
很难弄清楚什么时候应该适用某些公平标准。如果某个标准不是以其他标准为代价的,那么当你不确定的时候,你就不会那么担心应用某个标准。但是,由于情况并非如此,我们需要理解未能满足某些标准的影响。
那么我们讨论的标准中哪一个是最好的选择呢?所有这些方法都有很好的特性,但是都有缺点。
那现在怎么办?
我们不能在一个小角落里分割公平,而不努力改变世界上的不公正和机器学习系统之外发生的歧视。这并不意味着我们不能做任何事情!我们必须在某些领域设定一些公平标准,同时努力改变基本利率。
尽管有一些争议和不受欢迎,COMPAS 软件继续使用到今天。开发算法的人不想因为不知不觉地开发了种族主义算法而被指控或监禁,但必须选择一些标准来预测 COMPAS 试图解决的情况。
它可能是一个算法,也可能不完美,但它是一个开始,一个人必须从某个地方开始。
机器学习能帮助减少歧视吗?
机器学习是一个非常强大的工具。随着人类开始从人文主义者的角度向数据主义者的角度转变,这一点变得越来越明显——我们开始相信算法和数据,而不是人或我们自己的想法(有些人开车进入湖泊,因为他们的 GPS 也告诉他们!).这使得我们努力使算法尽可能不偏不倚变得极其重要,这样它们就不会在不知不觉中延续历史数据中蕴含的社会不公正。然而,使用算法来建立一个更加公正和平等的社会也有巨大的潜力。一个很好的例子是在招聘过程中。
假设你正在申请你梦想中的工作,并且正处于面试的最后阶段。招聘经理有权决定你是否被录用。你想要一个公正的算法来决定你是否是这份工作的最佳人选吗?
如果你知道招聘经理是种族主义者,你还会喜欢这样吗?还是性别歧视?
也许招聘经理是一个非常中立的人,纯粹是根据优点来选择工作,然而,每个人都有自己的倾向和潜在的认知偏见,这可能使他们更有可能选择他们最喜欢的候选人,而不是最适合这份工作的人。
如果可以开发出无偏见的算法,招聘过程可能会变得更快、更便宜,他们的数据可能会让招聘人员找到更高技能的人,这些人更适合他们的公司。另一个潜在的结果是:更加多样化的工作场所。该软件依靠数据从各种各样的地方筛选候选人,并将他们的技能与工作要求相匹配,不受人为偏见的影响。
这可能不是完美的解决方案,事实上,当涉及到正义时,很少有完美的答案。然而,历史的弧线似乎倾向于正义,所以也许这将使正义向前迈进一步。
另一个很好的例子是自动贷款承销。与传统的人工承销相比,自动承销更准确地预测某人是否会拖欠贷款,其更高的准确性导致更高的借款人批准率,特别是对于服务不足的申请人。其结果是,有时机器学习算法在进行最准确的分类方面比我们做得更好,有时这可以打击招聘和信贷审批等领域的歧视。
精神食粮
在结束这篇又长又严肃的文章时,我给你留下了谷歌关于机器学习中歧视的一句话供你思考。
“为机会均等而优化只是可以用来改善机器学习系统的众多工具之一——而数学本身不太可能带来最佳解决方案。打击机器学习中的歧视最终需要一种谨慎的多学科方法。”——谷歌
时事通讯
关于新博客文章和额外内容的更新,请注册我的时事通讯。
丰富您的学术之旅,加入一个由科学家,研究人员和行业专业人士组成的社区,以获得…
mailchi.mp](https://mailchi.mp/6304809e49e7/matthew-stewart)
参考文献
[1]奥尼尔,凯茜。数学毁灭武器:大数据如何增加不平等并威胁民主。皇冠,2016。
[2]加维,克莱尔;弗兰克,乔纳森。面部识别软件可能存在种族偏见问题。大西洋,2016。
[3] 托尔加·博卢克巴斯,张凯威,詹姆斯·邹,文卡特什·萨利格拉玛,亚当·卡莱。男人对于电脑程序员就像女人对于家庭主妇一样?去偏置词嵌入。Arxiv,2016。
[4] CS181:机器学习。哈佛大学,2019。
机器学习及其范围——核心工程师,一杯咖啡
机器学习(ML)的字面定义是机器采用的基于信息/数据的学习,以允许在特定任务中做出决策。另一方面,人工智能(AI)是基于信息/数据的智能,由机器“开发”以允许在复杂任务中做出决策。因此,人工智能是一个更广泛的术语,也包括机器学习的概念。
给定这些定义,让我们探索 ML/AI 在处理真实物理、化学或生物系统的核心工程领域中的相关性。机器学习或人工智能在这里如何应用?在当今世界,ML/AI 几乎是机器人、图像识别和自动驾驶汽车等应用的同义词。因此,这些本质上是基于数据的计算方法的相关性在核心行业中没有被清晰地感知。
因此,我的目标是在这里创建一个介绍性的阅读材料,为传统技术领域的专业人士描绘出这个快速发展领域的清晰画面。
Coffee brewing
为了更好地理解上下文,让我们围绕一个实际的小型物理系统来进行讨论,比如说咖啡酿造!咖啡酿造是一个受欢迎的实验系统。给定一种咖啡颗粒,不同的冲泡方式会产生不同的咖啡。例如,用浓缩咖啡机煮的咖啡味道浓郁,还带有一层“克莉玛”层。另一方面,滴滤咖啡口味更广,咖啡因含量更高。这两种冲泡方法在几个方面有所不同——从所用咖啡的研磨尺寸,到水温,提取时间和浸出咖啡所用的力的类型。因此,为了确定由动态调制系统生产的咖啡的质量,理解这些输入变量中的每一个的相关性和影响是重要的。
为了系统地计算这些变量对酿造质量的影响,首先,我们需要评估、量化和汇总最终咖啡的产出概况(基于其质地、咖啡因/酸/油/涩味含量、甜度等)。)输入变量和定义的输出变量之间的关系可以通过应用基本的热量、质量和动量平衡来导出。通过转换所得的微分方程,可以为输出变量生成解析或稳定的数值解。
虽然这看起来很简单,但是从基本原则出发全面定义模型是很有挑战性的。即使做到了这一点,也很难确定模型中各种参数的值,如质量/传热率系数等。
Mass transfer processes involved in coffee brewing
简而言之,生成一个纯粹的“白盒”模型是非常具有挑战性的,并且计算工作通常不能保证得到想要的结果。或者,可以映射输入和输出变量之间的数据驱动关系。
这就把我们带到了应用机器学习来解决同样的问题。假设建立了一组设计良好的实验,以针对各种输入变量组合(即不同的冲泡条件)生成咖啡质量数据。线性回归在捕捉潜在关系方面可能不够有效,导致模型可能存在较大偏差。这意味着它们没有用,并且会在未知/推断的酿造条件下导致不准确的预测。另一方面,机器学习提供了一套可以有效捕捉这些非线性关系的模型。例如,有决策树、随机森林、Adaboost 或梯度推进回归器、支持向量回归器等。
A map of machine learning techniques for different types of datasets
现在,机器学习算法表现更好的原因是,与传统的回归技术不同,数据不是在预定的模型结构(即,线性、多项式、指数等)上训练的。)结果,在确定非线性关系时有更大的自由度。例如,下图描述了决策树回归器如何为我们的咖啡冲泡示例工作。可以看出,咖啡质量是通过从输入变量中生成一个树形结构来回归的,每个输入变量在不同层次上起作用。
Decision tree regression
然而,这些模型通常可能过拟合,这意味着它完美地拟合/解释了训练数据,但不能预测类似容量的未知测试数据集。为了减轻过度拟合,有几种策略可用。例如,在支持向量回归(SVR)模型中,当模型回归输入和输出变量之间的关系时,允许有误差幅度(见下图)。特别地,支持向量回归机采用了一种核技巧,允许将输入特征空间转换到一个更高维的非线性空间,从而以非常少的计算需求实现非线性回归。(参见https://towards data science . com/understanding-the-kernel-trick-e0bc 6112 ef 78)
Support Vector Regression
决策树、SVR 等机器学习算法通常用形容词“经典”来指代,因为与用神经网络构建的一套深度学习模型相比,它们在某种意义上本质上不那么黑箱化。让我们试着理解这一点。首先,神经网络可以被视为强大的数学工具,它可以通过由非线性函数转换的输入特征的线性组合的堆叠来实现分类/预测输出。模型然后学习特定任务的方式是通过损失函数的反向传播(即,真实值和模型生成的预测之间的观察差异的函数)。因此,既没有决策树中的决策规则层次,也没有 SVR 中的预先指定的核。神经网络在其操作中是真正的黑箱。此外,与经典的机器学习算法不同,深度学习模型中几个层的堆叠使得对最终输出的特征影响的洞察最小。考虑到我们的咖啡酿造示例,这意味着尽管实现了出色的预测能力,深度学习的咖啡酿造模型无法精确确定蒸汽压力对最终咖啡甜度的贡献大小——另一方面,决策树或(线性)SVR 为我们提供了这一信息。
Deep neural networks
然而,深度学习模型的范围是巨大的,它的应用一次又一次地在各种领域取得成功。
这种成功超出了人们会立即联想到的机器人领域。例如,深度学习模型适用于石油和天然气以及石化行业,在这些行业中,运营工厂继续定期收集大量数据储备。制药公司或生命科学实验室通常需要处理大量的实验/试验,以获得重要成果,如药物发现。在这种情况下,机器学习为从这些已经生成的数据集转移知识提供了巨大的空间。然而,另一个可以从机器学习中受益匪浅的领域是金融——在这个领域,人们不断有动力从各种数据源中挖掘越来越多的信息。制造业、农业、矿业、替代能源,可以从机器学习中受益的行业不胜枚举。
- 刘,易,等.集成深度核学习及其在工业聚合过程质量预测中的应用化学计量学和智能实验室系统174(2018):15–21。
- 赵、杨、、乐安。"一种用于原油价格预测的深度学习集成方法"能源经济学66(2017):9–16。
- Chong,Eunsuk,Chulwoo Han 和 Frank C. Park。股票市场分析和预测的深度学习网络:方法论、数据表示和案例研究专家系统与应用83(2017):187–205。
- Acharya,U. Rajendra 等.使用 ECG 信号自动检测心肌梗死的深度卷积神经网络应用信息科学415(2017):190–198。
总而言之,任何一种技术专长通常都是通过观察、学习和经验获得的。在许多方面,这类似于 ML/AI 模型从显示给它的数据中获得的学习。因此,在这个先进计算资源的时代,在数据丰富的环境中茁壮成长的专业人士有必要认识到机器学习的潜力,并将其识别为一系列可以帮助他们业务的复杂技术。
正如他们所说,数据是新的石油!如果经过适当的训练,机器学习模型的发展潜力是无限的!
机器学习和心理健康
大数据能否帮助心理健康领域?
Canadian Mental Health Association
“根据美国焦虑和抑郁协会的数据,焦虑症是美国最常见的精神疾病。它们每年影响4000 万成年人,占总人口的 18.1%。此外,焦虑症影响着 25.1%的 13 至 18 岁儿童,使他们面临更高的风险,在学校表现不佳,滥用药物,并错过重要的社会经历。尽管这种疾病是高度可治疗的,只有 36.9%的患者接受治疗,很可能是由于一种可感知的社会污名,男性寻求治疗的可能性远低于女性。
我一生中做的最好的决定之一是在我大学的最后一年决定去看心理健康专家。那是一段充满压力的时光,也是我人生中重大转变的时刻。过渡期和巨大变化的时刻是我们许多人可能会发现自己在应对焦虑和压力的时候。当我看到许多朋友正在经历类似的人生转变时,我鼓励他们也这样做。
话虽如此,我认为重要的是要强调,心理健康维护的整个范围不仅仅是看心理健康专业人士的要求,而是 创造一个自我检查的例行程序正确维护我们的心理状态* 。(但是看心理健康专家仍然是一种有益健康的体验,不需要被诊断出特定的状况。我还是强烈推荐。)*
作为一名对心理健康领域充满热情的数据科学学生,看到这两个领域的交叉让我兴奋不已。改变心理健康领域的一个非常酷的概念是机器学习。
机器学习和心理健康
世界各地的神经科学家和临床医生正在使用机器学习来为患者制定治疗计划 ,并在开始之前识别一些精神健康障碍的关键标志。其中一个好处是,机器学习有助于临床医生预测谁可能面临特定疾病的风险。
有这么多可用的数据,我们现在能够为心理健康专业人员汇编数据,以便他们可以更好地完成工作。让机器学习在今天如此有用的是,在过去,对诊断的理解是基于组平均值和对人口的统计。机器学习让临床医生有机会个性化。
“机器学习确实满足了我们在精神病学中的一种特定需求,这就是个性化的 T2 需求,”他说。“几十年来,我们一直在研究适用于可能患有相同诊断的人群的群体平均值和统计数据,但这些数据并不能很好地应用于个体患者。机器学习让我们能够以一种前所未有的方式进行个体预测。”—大卫·本里莫,医学博士,医学博士,麦吉尔大学的精神病学住院医师
机器学习正在以两种关键方式帮助改变心理健康的面貌:
- 识别生物标志物/制定治疗计划
- 预测危机
识别生物标记和制定治疗计划
今天,当患者被诊断为精神疾病时,有一个试错过程来实现正确的药物剂量和采用正确的治疗方案。这种反复试验的过程是不应该发生的,但事实是,每一个精神健康疾病如抑郁症患者的症状都是不一样的。一个患者的症状会与下一个患者不同。
生物标记的一个例子是作为冠心病生物标记的血液胆固醇。就像人体有身体生物标记一样,它也有行为生物标记对抑郁和焦虑等状况。
机器学习算法可以帮助确定关键的行为生物标记,以帮助心理健康专业人员决定患者是否有患特定心理健康疾病的风险。此外,该算法可以帮助跟踪治疗计划的有效性。
Benrimoh 说:“这些算法可以识别出一些模式,这些模式可以帮助我们在我们目前所做的事情之外,根据标记对患者进行聚类——根据严重程度或特定症状进行聚类。”。通过观察这些不同的模式,以及谁对什么样的治疗有反应,我们可以更好地确定不同疾病的相关亚型,以及哪种治疗方法对它们最有效
归根结底,每个病人对压力和抑郁等情况都有自己的生理、触发因素和反应。精神健康障碍的许多症状是重叠的,尽管精神健康障碍的一些关键指标是已知的,但试错治疗计划是不可接受的。机器学习算法为精神病学家和心理健康专业人士提供了一个成熟的机会,来识别不同疾病的子类型,并制定更适合的治疗计划和药物剂量。
预测危机
让我们暂时把所有的科学和数据收集放在一边。重要的是要明白,患有某些疾病的人更容易出现恐慌症、精神病、躁狂状态、偏头痛等危机。
对于已经被诊断患有精神健康疾病的患者,他们的状况受到监测,以帮助他们过日常生活。但是某些疾病,如精神分裂症和双相情感障碍,发生危机的风险更高。心理健康专家负责将患者的危机风险降至最低。
我们如何帮助心理健康专家预测危机?
机器学习算法可以结合自己提供的数据以及来自智能手机/社交媒体的被动数据,来确定患者是否即将发病。有一些关键的指标可以表明一个事件是否即将发生。如果我们能够发现压力、孤立或暴露于触发因素的模式,这些危机是可以预测的。
事实上,我自己最近也经历了一次偏头痛。我睡得很少,不知道发生了什么。在我意识到之前,我失去了平衡,倒在了地铁站台的地板上,试图喘口气,明白发生了什么。我以前从未患过偏头痛,所以当发作时,我感到困惑和害怕。当我和一位医生谈到这一事件以及我生活中发生的事情时,我清楚地意识到,我最近经历的压力和不健康的模式已经在身体上体现在这一事件中。
这个故事的要点是,有明确的迹象表明,一场危机或事件即将发生。这适用于任何人,无论是否有诊断结果。我们都有特定的诱因和应对机制。危机将不可避免地发生。我们能做些什么来帮助精神卫生领域预防这些危机?我相信分析病人模式的治疗计划,在疾病发作前帮助他们,会非常有效。
人工智能
在我的研究中,我发现人工智能是如何被用来解决美国目前的精神健康危机的。现实是,许多人在与精神病医生或治疗师交谈时感到尴尬和不舒服,因为他们不知道自己的弱点。有一些团队和公司正在致力于开发人工智能,这些人工智能可以为那些可能正在处理成瘾、心理健康状况或生活中任何压力/触发事件的个人提供服务并与之互动。
尽管人工智能正在“取代”心理健康领域的专业人士,这看起来有些不寻常或可怕,但结果是显而易见的。
Woebot
心理健康专家使用的关键技术之一是认知行为疗法,通过几次谈话来改变病人的消极思维模式。2017 年,斯坦福大学的临床心理学家开发了一款名为 Woebot 的聊天机器人,使用与 40 年前治疗师使用的技术相同的数字版本来治疗学生的抑郁和焦虑:认知行为治疗。
在一项针对患有抑郁症的大学生的研究中,根据 PHQ-9 分数——一种常见的抑郁症衡量标准——那些使用 Woebot 的人在短短两周内经历了近 20%的改善。Woebot 在研究小组中取得成功的一个原因是参与者的高度参与。在每月 39 美元的低廉费用下,大多数人几乎每天都与机器人交谈——这种参与程度是面对面咨询所无法达到的。
人工智能被用来直接治疗精神健康状况是一个相对较新的应用,我认为需要更多的研究来确定它的应用范围有多广。
如果你有兴趣更多地了解一些在精神健康领域使用机器学习和人工智能取得进展的公司,这里有一些。单击嵌入链接了解更多信息。
就个人而言
在美国和全球都有心理健康流行病。尽管存在流行病,心理健康仍然是许多社区的禁忌话题。最重要的是,可能由于精神卫生保健的禁忌性质,没有足够的途径获得精神卫生资源。
亨利·j·凯泽家族基金会提供了美国医疗专业人员短缺地区的信息。
近 40%的美国人生活在联邦政府指定的精神健康专业人员短缺的地区;超过 60%的美国县没有一个精神病医生。那些足够幸运地生活在有足够的心理健康服务的地区的人通常负担不起,因为许多治疗师不接受保险。
此外,除了获得精神卫生保健已经存在的困难之外,代表性不足的社区和少数群体社区获得这种服务更加困难。这与经济限制和缺乏关于心理健康重要性的教育有关,也是这个话题最大的禁忌。
数据科学/机器学习是一个很好的工具,可以帮助现有的临床医生、精神病医生和治疗师帮助他们的患者。有人试图通过技术进步来应对这种流行病,这很好。但老实说,这还不够。我们应该像讨论身体健康一样,坦然地谈论心理健康。现在比以往任何时候都更重要的是,我们在使这种讨论正常化方面取得进展。
近五分之一的美国成年人患有某种精神疾病。自杀率创历史新高,每天有 115 人死于阿片类药物滥用,八分之一的 12 岁以上的美国人每天服用抗抑郁药。仅抑郁症一项的经济负担就估计每年至少有 2100 亿美元…
National Alliance on Mental Health
来源
[## 精神健康中的机器学习:方法和应用的范围审查。
背景:本文旨在综合文献的机器学习(ML)和大数据应用的心理…
www.ncbi.nlm.nih.gov](https://www.ncbi.nlm.nih.gov/pubmed/30744717) [## 顶级心理健康科技初创公司——波士顿医疗科技公司
根据美国焦虑和抑郁协会,焦虑症是最常见的精神疾病…
medtechboston.medstro.com](https://medtechboston.medstro.com/blog/2018/05/14/the-top-mental-health-tech-startups/) [## 利用数据科学帮助解决心理健康问题
相对于医学的其他领域,数据科学在精神健康领域的应用是有限的,但是…
www.discoverdatascience.org](https://www.discoverdatascience.org/social-good/mental-health/) [## 精神卫生保健专业人员短缺地区
凯泽家庭基金会网站提供了关于关键健康政策问题的深入信息,包括医疗补助…
www.kff.org](https://www.kff.org/other/state-indicator/mental-health-care-health-professional-shortage-areas-hpsas/?currentTimeframe=0&sortModel={"colId":"Location","sort":"asc"}) [## 人工智能诊断和治疗精神疾病的潜力
美国面临着精神健康流行病。近五分之一的美国成年人患有…
hbr.org](https://hbr.org/2018/10/ais-potential-to-diagnose-and-treat-mental-illness) [## 人工智能在精神健康领域的惊人应用
由于缺乏心理健康专业人员,由于缺乏途径或费用高昂而不寻求治疗的个人…
www.forbes.com](https://www.forbes.com/sites/bernardmarr/2019/05/03/the-incredible-ways-artificial-intelligence-is-now-used-in-mental-health/#5c8bb690d02e)
机器学习和液体中的粒子运动:一个优雅的链接
Image by rony michaud from Pixabay.
作为全局最小化算法的朗之万方程
梯度下降算法是机器学习中最流行的优化技术之一。它有三种风格:批量或“普通”梯度下降(GD)、随机梯度下降(SGD)和小批量梯度下降不同之处在于用于计算每次迭代损失函数梯度的数据量。
本文的目标是描述基于朗之万动力学 (LD)的全局优化器的研究进展,朗之万动力学是一种分子运动的建模方法,它起源于阿尔伯特·爱因斯坦和保罗·朗之万在 20 世纪早期关于统计力学的工作。
我将从理论物理的角度提供一个优雅的解释,解释为什么梯度下降的变体是高效的全局优化器。
奇迹之年
没有迹象表明一场革命即将发生。1904 年,如果阿尔伯特·爱因斯坦放弃了物理学,他的科学家同事们可能都不会注意到。幸运的是,这并没有发生。1905 年,这位年轻的专利办事员发表了四篇革新科学的论文。
Albert Einstein circa 1905, his miracle year (source).
流体中的随机运动
在其中一篇论文中,爱因斯坦推导出了所谓的布朗运动的模型,这是液体中悬浮粒子与更小、快速移动的分子(例如在水中移动的花粉粒)碰撞引起的随机运动。
Brownian motion: dust particle colliding with gas molecules (source).
在这篇论文中,他单枪匹马地证实了原子和分子的存在,从而诞生了一个名为分子动力学的物理学新分支,并创建了一个名为随机微积分的全新应用数学领域。
朗之万动力学
1908 年,在爱因斯坦发表他的里程碑式的论文三年后,法国物理学家保罗·朗之万发表了另一篇开创性的文章,他在文章中推广了爱因斯坦的理论并发展了一个描述布朗运动的新的微分方程,今天被称为朗之万方程
其中 x 是运动粒子的位置, m 是其质量, R 代表与流体中更小的快速运动分子碰撞产生的(随机)力(见上面的动画),而 F 代表任何其他外力。随机力 R 是增量相关平稳高斯过程,其均值和方差如下:
R is a normal process.
术语“增量相关”意味着在两个不同时间的力具有零相关性。LE 是第一个描述热力学不平衡的数学方程。
The French physicist Paul Langevin (source).
如果粒子的质量足够小,我们可以把左边设为零。此外,我们可以将一个(保守)力表示为某个势能的导数。我们获得:
Langevin equation for small masses.
现在,写作
其中 δt 是一个小的时间间隔,移动项,我们得到小质量粒子的离散化的朗之万方程:
Discretized Langevin equation for particles with small inertia.
用这种方式表达,朗之万方程描述了布朗运动中粒子的位移增量。
一小段插曲:布朗运动的 Python 代码
布朗运动的 Python 实现可以在这里找到。为了模拟 2D 离散布朗过程,使用了两个 1D 过程。代码的步骤是:
- 首先,选择时间步长的数量
steps
。 - 坐标
x
和y
是随机跳跃的累积和(函数np.cumsum()
用于计算它们) - 使用
np.interp()
通过插值计算中间点X
和Y
- 然后使用
plot()
功能绘制运动
代码是:
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inlinesteps = 5000
random.seed(42)
x,y = np.cumsum(np.random.randn(steps)), np.cumsum(np.random.randn(steps))points = 10
ip = lambda x, steps, points: np.interp(np.arange(steps*points),
np.arange(steps)*points,
x)
X, Y = ip(x, steps, points), ip(y, steps, points)fig, ax = plt.subplots(1, 1, figsize=(10, 10))
ax.set_title('Brownian Motion')
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.plot(X, Y, color='blue',
marker='o', markersize=1)
Illustration of Brownian motion (source).
朗之万动力学和全局极小值
朗之万动力学的一个重要性质是随机过程【其中x的扩散分布p(x)服从上面给出的朗之万方程
Boltzmann distribution.**
其集中在势能 E ( x )的全局最小值(从其泛函形式中我们不难看出,BD 峰值在势能E(x)的全局最小值上)。更准确地说是、如 Hajek 等所示,如果温度按照离散步骤缓慢降至零:**
然后p(x)会收敛到 n 的大值的玻尔兹曼分布(而 x 会收敛到E(x)的全局最小值)。与时间相关的温度的朗之万方程通常被解释为描述亚稳态物理状态衰变为系统的基态(这是能量的全局最小值)。因此,人们可以使用朗之万动力学来设计算法,这些算法是全局最小化器,甚至是潜在非凸函数。**
该原理是模拟退火技术的基础,用于获得函数的近似全局最优。
Application of simulated annealing to search for maxima (source).
梯度下降算法
我现在将转向机器学习优化算法。
梯度下降是一种简单的迭代优化算法,用于最小化(或最大化)函数。在机器学习的背景下,这些函数是损失函数(或成本函数)。具体来说,考虑一个多元损失函数L(w)定义为围绕某个固定点wp 的所有点。GD 算法基于一个简单的性质,即从任意点 p 开始,函数 L( w )在其负梯度方向上下降最快:
Negative gradient of the loss function.
首先猜测(未知)最小值的初始值,然后计算序列
在迭代过程之后
Gradient descent recursion.
其中 γ 是学习率,允许在每次迭代中改变 n 。如果损失函数 L 及其梯度具有某些特性并且学习率变化是按照某些协议选择的,则局部收敛是有保证的(只有当 L 是凸的时,收敛到全局最小值才是有保证的,因为对于凸函数,任何局部最小值也是全局最小值)。
随机梯度下降(SGD)和小批量梯度下降
与基本 GD 算法不同,基本 GD 算法在每次迭代时扫描整个数据集, SGD 和小批量 GD 只使用训练数据的一个子集。SGD 使用训练数据的单个样本来更新每次迭代中的梯度,即当它扫过训练数据时,它对每个训练示例执行上述的 w 的更新。小批量 GD 使用小批量训练样本执行参数更新。
让我们用数学术语来描述它。对于一般的训练集
Training set with n samples.
损失函数具有一般形式:
General loss function.
在小批量梯度下降的情况下,总和仅超过批量内的训练样本。特别是 SGD,只使用一个样本。与普通 GD 相比,这些过程有两个主要优势:它们更快,可以处理更大的数据集(因为它们使用一个或几个样本)。
定义 G 和 g 如下所示,我们在这种情况下有:
Gradient in the mini-batch algorithm.
在亚历克·拉德福德的精彩动画中,SGD 收敛与其他方法一起展示(本文中没有提到的这些其他方法,是 SGD 最近的改进)。
Great animation below by Alec Radford comparing optimization methods (source).
机器学习和物理学:作为朗之万过程的梯度下降
下一步(也是最后一步)对论证至关重要。我省略了一些更严谨的方面,以便让主要思想能够被理解。
我们可以将小批量梯度写成全梯度和正态分布的 η: 之和
现在将这个表达式代入 GD 迭代表达式,我们得到:
Mini-batch gradient descent iteration step.
一个优雅的链接
将小批量梯度下降迭代的表达式与朗之万方程进行比较,我们可以立即注意到它们的相似性。更准确地说,它们通过以下对应关系变得相同:
在第二个表达式中用 γ 代替 δt 我们发现
因此,SGD 或小批量梯度下降算法在形式上类似于 Langevin 过程,这就解释了为什么如果学习速率按照前面提到的协议变化,它们有很高的概率选择全局最小值。
这个结果并不新鲜。事实上有许多证据表明,在通常的梯度下降递归中加入噪声项会使算法收敛到全局最小值。必须强调的是,正是学习率的“冷却协议”提供了至关重要的“额外”随机化,使得算法能够逃离局部最小值并收敛到全局最小值。
结论
在这篇文章中,我表明,通过将随机或小批量梯度下降视为朗之万随机过程(用损失函数标识能量),并通过学习率包括额外的随机化水平,我们可以理解为什么这些算法可以作为全局优化器工作得如此之好。这是一个优雅的结果,表明从多个角度审视一个问题通常是非常有用的。
感谢阅读!
我的 Github 和我的个人网站 www.marcotavora.me (希望)有一些关于数据科学和物理学的其他有趣的东西。
一如既往,欢迎建设性的批评和反馈!
机器学习和测试驱动的开发
两者都可以被认为是示例编程。
Source: https://www.nascenia.com/tdd-in-net-an-overview-of-red-green-refactor/
当我在 21 世纪初开始使用敏捷的前身极限编程(XP)时,我很快了解到 XP 的核心实践之一是测试驱动开发(TDD)。我想提醒你的是,与人们现在所认为的相反,XP 不是作为对瀑布过程的反应而产生的,而是 Kent Beck 所说的“编码并修复”方法,这与瀑布正好相反,因为它的特点是编写难以维护的代码,修改起来非常困难且昂贵,错过最后期限,缺乏计划以及周末工作。瀑布被视为通过引入大设计先行(BDUF)来解决这一问题的尝试。另一方面,XP 通过引入训练有素的软件开发实践,特别是 TDD 和重构,提出了一种不同的解决软件开发混乱的方法。想法是以一种可以在以后运行的方式编写单元测试,以证明代码仍然在工作。这将允许重构代码,而不用担心它会破坏系统。
忠于它的名字,XP 提出通过一直运行测试套件来将这种实践发挥到极致。但是当 XP 实践者在写代码之前就开始写测试时,这变得更加极端。单元测试被视为可执行的规范,而 TDD——被视为通过实例编程。事实上,您在一系列测试示例中编码新需求,然后编写代码以满足所有示例,然后进行重构,确保所有测试仍然通过。这就是著名的 Reg-Green-Refactor 循环,敏捷实践者对此非常熟悉。
我在听 Cassie Kozyrkov 的采访时想起了这一点,她说机器学习是通过例子编程。事实上,早在 2000 年,我就在想,如果代码是基于我写的测试自动编写的,会不会很酷?所以我意识到机器学习是我梦想的实现。不是我不知道,而是 TDD 和 ML 之间的联系直到那时才变得清晰。
当然,在这一点上,机器学习不能完全取代程序员,因为它不是编写程序,而是学习大量的模型参数,需要多次迭代才能正确。由于例子的数量是有限的,模型很可能会过度适应这些例子(这对人类程序员来说也是一种危险!)但人们可能希望在未来算法变得足够强大,能够完成这一点,并确实基于测试示例生成正确工作的程序。
Spark MLlib Python 示例-大规模机器学习
在其历史的大部分时间里,计算机处理器每年都变得更快。不幸的是,这种硬件趋势在 2005 年左右停止了。由于散热方面的限制,硬件开发人员不再提高单个处理器的时钟频率,而是选择并行 CPU 内核。这对于在台式电脑上玩视频游戏来说很好。然而,当涉及到处理数 Pb 的数据时,我们必须更进一步,将多台计算机的处理能力集中在一起,以便在任何合理的时间内完成任务。对水平扩展的需求催生了 Apache Hadoop 项目。Apache Hadoop 提供了一种方法来分解给定的任务,在一个集群内的多个节点上并发执行该任务,并聚合结果。
Apache Spark 始于 2009 年的加州大学伯克利分校 AMPlab。当时,Hadoop MapReduce 是集群的主流并行编程引擎。AMPlab 创建了 Apache Spark 来解决使用 Apache Hadoop 的一些缺点。Apache Hadoop 最显著的局限性之一是它将中间结果写入磁盘。相比之下,Spark 将所有内容都保存在内存中,因此速度更快。2013 年,该项目得到了广泛应用,有来自加州大学伯克利分校以外 30 多个组织的 100 多名贡献者。AMPlab 为 Apache 软件基金会贡献了 Spark。早期的 AMPlab 团队还成立了一家名为 Databricks 的公司来改进这个项目。
尽管像 scikit-learn 这样的 Python 库对于 Kaggle 竞赛之类的比赛来说很棒,但是它们很少被大规模使用。根据我个人的经验,我遇到过只能加载一部分数据的情况,因为否则它会完全填满我的计算机的内存并使程序崩溃。Spark 有能力通过一个名为 MLlib 的内置库来大规模执行机器学习。MLlib API 虽然不如 scikit-learn 包容,但可以用于分类、回归和聚类问题。在前面的文章中,我们将使用传统的 scikit-learn/pandas 堆栈训练一个机器学习模型,然后使用 Spark 重复这个过程。
Jupyter 笔记本
import pandas as pd
在前面的例子中,我们将尝试根据人口普查数据预测一个成年人的收入是否超过 5 万美元/年。数据可以从 UC Irvine 机器学习库下载。
我们正在处理的数据集包含 14 个要素和 1 个标注。默认情况下,csv 文件中不包含标题,因此,我们必须自己定义列名。
column_names = [
'age',
'workclass',
'fnlwgt',
'education',
'education-num',
'marital-status',
'occupation',
'relationship',
'race',
'sex',
'capital-gain',
'capital-loss',
'hours-per-week',
'native-country',
'salary'
]train_df = pd.read_csv('adult.data', names=column_names)test_df = pd.read_csv('adult.test', names=column_names)
您会注意到每个特性都由逗号和空格分隔。虽然熊猫可以在引擎盖下处理这些,但 Spark 不能。因此,我们删除了空格。此外,我们从我们的训练集中删除了任何一行本国为Holand-Neitherlands
的行,因为在我们的测试集中没有任何实例,这将在我们对分类变量进行编码时引起问题。我们将生成的数据帧保存到一个 csv 文件中,这样我们可以在以后使用它。
train_df = train_df.apply(lambda x: x.str.strip() if x.dtype == 'object' else x)train_df_cp = train_df.copy()train_df_cp = train_df_cp.loc[train_df_cp['native-country'] != 'Holand-Netherlands']train_df_cp.to_csv('train.csv', index=False, header=False)test_df = test_df.apply(lambda x: x.str.strip() if x.dtype == 'object' else x)test_df.to_csv('test.csv', index=False, header=False)
接下来,让我们来看看我们在做什么。训练集包含 3 万多行。
print('Training data shape: ', train_df.shape)
train_df.head()
另一方面,测试集包含 15000 多行。
print('Testing data shape: ', test_df.shape)
test_df.head()
很多时候,我们必须在训练模型之前处理缺失的数据。以下行将返回每个要素的缺失值的数量。幸运的是,数据集是完整的。
train_df.isnull().sum()
分类变量的类型为object
。分类变量必须进行编码,以便由机器学习模型(而不是决策树)进行解释。
train_df.dtypes.value_counts()
以下代码打印每个分类变量的不同类别数。
train_df.select_dtypes('object').apply(pd.Series.nunique, axis=0)
test_df.select_dtypes('object').apply(pd.Series.nunique, axis=0)
我们手动编码 salary,以避免在执行一个热编码时创建两列。在转换我们的数据之后,每个字符串都被替换为一个由1和0组成的数组,其中 1 的位置对应于一个给定的类别。
train_df['salary'] = train_df['salary'].apply(lambda x: 0 if x == ' <=50K' else 1)
test_df['salary'] = test_df['salary'].apply(lambda x: 0 if x == ' <=50K' else 1)train_df = pd.get_dummies(train_df)
test_df = pd.get_dummies(test_df)print('Training Features shape: ', train_df.shape)
print('Testing Features shape: ', test_df.shape)
测试集和训练集中native-country
类别的不同数量之间存在差异(测试集没有一个人的祖国是荷兰)。结果,当我们应用一个热编码时,我们得到了不同数量的特性。在使用逻辑回归之前,我们必须确保训练集和测试集中的特征数量相匹配。我们可以通过执行内部连接来做到这一点。
# Align the training and testing data, keep only columns present in both dataframes
train_df, test_df = train_df.align(test_df, join = 'inner', axis = 1)print('Training Features shape: ', train_df.shape)
print('Testing Features shape: ', test_df.shape)
train_df.head()
接下来,我们将数据帧分解成因变量和自变量。
X_train = train_df.drop('salary', axis=1)
y_train = train_df['salary']X_test = test_df.drop('salary', axis=1)
y_test = test_df['salary']
只要我们在解释系数时牢记单位,我们就不需要为正态逻辑回归调整变量。然而,默认情况下,逻辑回归的 scikit-learn 实现使用 L2 正则化。L2 正则化同等地惩罚所有参数的大值。因此,以米为单位的高度特征将比以毫米为单位的另一个特征受到更多的惩罚。因此,在通过我们的模型发送数据之前,我们对数据进行缩放。
from sklearn.preprocessing import MinMaxScalerscaler = MinMaxScaler(feature_range = (0, 1))scaler.fit(X_train)
X_train = scaler.transform(X_train)
X_test = scaler.transform(X_test)
最后,我们可以训练我们的模型,并在测试集上测量它的性能。
from sklearn.linear_model import LogisticRegressionlr = LogisticRegression()lr.fit(X_train, y_train)lr_pred = lr.predict(X_test)from sklearn.metrics import accuracy_scoreaccuracy_score(y_test, lr_pred)
Pyspark
让我们看看如何使用 Spark 来完成同样的事情。根据您的喜好,您可以用 Java、Scala 或 Python 编写 Spark 代码。鉴于大多数数据科学家习惯于使用 Python,我们将使用它。
前面部分中的所有代码都将在我们的本地机器上运行。然而,如果我们要建立一个具有多个节点的 Spark 集群,这些操作将在集群中的每台计算机上并发运行,而无需对代码进行任何修改。
开始使用 Spark 最简单的方法是使用 Jupyter 提供的 Docker 容器。为了简单起见,我们创建一个包含以下内容的docker-compose.yml
文件。确保修改路径以匹配包含从 UCI 机器学习资源库下载的数据的目录。
version: '2'
services:
spark:
image: jupyter/pyspark-notebook:latest
ports:
- 8888:8888
volumes:
- /home/cory/kaggle/adult:/home/jovyan/work
然后,运行前面的命令。
docker-compose up
要访问 Jupyter 笔记本,请打开浏览器并进入localhost:8888
。
继续导入下列库。
from pyspark import SparkConf, SparkContext
from pyspark.sql import SparkSession
from pyspark.ml.classification import LogisticRegression
from pyspark.ml.feature import OneHotEncoderEstimator, StringIndexer, VectorAssembler
from pyspark.ml import Pipeline
from pyspark.sql.types import StructType, StructField, IntegerType, StringType
在做任何事情之前,我们需要初始化一个 Spark 会话。
spark = SparkSession.builder.appName("Predict Adult Salary").getOrCreate()
就像之前一样,我们定义了在读取数据时要使用的列名。
schema = StructType([
StructField("age", IntegerType(), True),
StructField("workclass", StringType(), True),
StructField("fnlwgt", IntegerType(), True),
StructField("education", StringType(), True),
StructField("education-num", IntegerType(), True),
StructField("marital-status", StringType(), True),
StructField("occupation", StringType(), True),
StructField("relationship", StringType(), True),
StructField("race", StringType(), True),
StructField("sex", StringType(), True),
StructField("capital-gain", IntegerType(), True),
StructField("capital-loss", IntegerType(), True),
StructField("hours-per-week", IntegerType(), True),
StructField("native-country", StringType(), True),
StructField("salary", StringType(), True)
])
像 Pandas 一样,Spark 提供了一个 API,用于将 csv 文件的内容加载到我们的程序中。我们使用开始时创建的文件。
train_df = spark.read.csv('train.csv', header=False, schema=schema)test_df = spark.read.csv('test.csv', header=False, schema=schema)
我们可以运行下面一行来查看前 5 行。
train_df.head(5)
不管出于什么原因,如果你想把 Spark 数据帧转换成 Pandas 数据帧,你可以这样做。就我个人而言,我觉得输出更清晰,更容易阅读。
train_df.limit(5).toPandas()
在继续前进之前,必须了解 Spark 和 Scikit-learn/Pandas 之间的几个重要区别。
- Spark 数据帧是不可变的。因此,每当我们想要应用转换时,我们必须通过创建新的列来实现。
- MLlib 希望所有功能都包含在一列中。
在前面的代码块中,我们对分类变量进行了所有必要的转换。
StringIndexer
类执行标签编码,必须在OneHotEncoderEstimator
执行一次热编码之前应用。VectorAssembler
类接受多个列作为输入,输出一个列,其内容是一个数组,包含所有输入列的值。
categorical_variables = ['workclass', 'education', 'marital-status', 'occupation', 'relationship', 'race', 'sex', 'native-country']indexers = [StringIndexer(inputCol=column, outputCol=column+"-index") for column in categorical_variables]encoder = OneHotEncoderEstimator(
inputCols=[indexer.getOutputCol() for indexer in indexers],
outputCols=["{0}-encoded".format(indexer.getOutputCol()) for indexer in indexers]
)assembler = VectorAssembler(
inputCols=encoder.getOutputCols(),
outputCol="categorical-features"
)pipeline = Pipeline(stages=indexers + [encoder, assembler])train_df = pipeline.fit(train_df).transform(train_df)test_df = pipeline.fit(test_df).transform(test_df)
让我们查看在上一步中创建的所有不同的列。
train_df.printSchema()
在应用转换之后,我们得到了一个包含每个编码分类变量的数组的单个列。
df = train_df.limit(5).toPandas()
df['scaled-categorical-features'][1]
我们将连续变量和分类变量合并成一列。
continuous_variables = ['age', 'fnlwgt', 'education-num', 'capital-gain', 'capital-loss', 'hours-per-week']assembler = VectorAssembler(
inputCols=['categorical-features', *continuous_variables],
outputCol='features'
)train_df = assembler.transform(train_df)test_df = assembler.transform(test_df)
让我们看看最后一列,我们将使用它来训练我们的模型。如您所见,它输出了一个 SparseVector。为了节省空间,稀疏向量不包含来自一个热编码的0。
train_df.limit(5).toPandas()['features'][0]
最后,我们对目标标签进行编码。
indexer = StringIndexer(inputCol='salary', outputCol='label')train_df = indexer.fit(train_df).transform(train_df)test_df = indexer.fit(test_df).transform(test_df)train_df.limit(10).toPandas()['label']
我们适合并训练我们的模型。
lr = LogisticRegression(featuresCol='features', labelCol='label')model = lr.fit(train_df)
transform
方法用于对测试集进行预测。
pred = model.transform(test_df)pred.limit(10).toPandas()[['label', 'prediction']]
最后的想法
Spark 是一个分布式计算平台,可用于在数据帧上执行操作,并大规模训练机器学习模型。
Python 中的 BIRCH 聚类算法示例
https://www.pexels.com/photo/boy-in-beige-hoodie-solving-a-math-problem-6256102/
现有的数据聚类方法不能充分解决用有限数量的资源(即,存储器和 cpu 周期)处理大数据集的问题。因此,随着数据集大小的增加,它们在运行时间和结果质量方面的伸缩性很差。在高层次上,使用层次结构的平衡迭代减少和聚类,或简称为 BIRCH ,通过首先生成一个更紧凑的摘要来处理大型数据集,该摘要保留尽可能多的分布信息,然后对数据摘要而不是原始数据集进行聚类。BIRCH 实际上是对其他聚类算法的补充,因为不同的聚类算法可以应用于 BIRCH 生成的摘要。BIRCH 只能处理度量属性(类似于 KMEANS 可以处理的那种特性)。度量属性的值可以用欧几里得空间中的显式坐标来表示(没有分类变量)。
聚类特征(CF)
BIRCH 试图通过将密集区域中包含的信息汇总为聚类特征(CF)条目来最小化大型数据集的内存需求。
http://www.cs.uvm.edu/~xwu/kdd/BIRCH.pdf
正如我们将要看到的,CFs 有可能由其他 CFs 组成。在这种情况下,子集群等于 CFs 的总和。
http://www.cs.uvm.edu/~xwu/kdd/BIRCH.pdf
CF 树
CF-tree 是数据集的一种非常紧凑的表示,因为叶节点中的每个条目不是单个数据点,而是一个子簇。每个非叶节点最多包含 B 个条目。在这种情况下,单个条目包含指向子节点的指针和由子节点中的 CF 的总和构成的 CF(子集群的子集群)。另一方面,一个叶节点最多包含 L 个条目,每个条目是一个 CF(数据点的子簇)。叶节点中的所有条目必须满足阈值要求。也就是说,每个叶子条目的直径必须小于 阈值 。此外,每个叶节点都有两个指针, prev 和 next ,用于将所有叶节点链接在一起,以便高效扫描。
http://www.cs.uvm.edu/~xwu/kdd/BIRCH.pdf
插入算法
让我们描述一下如何将一个 CF 条目(单个数据点或子集群)插入到 CF-tree 中。
- 识别适当的叶子:从根开始,通过根据所选择的距离度量(即欧几里德距离)选择最近的子节点,递归地下降 DF 树。
- 修改叶子:到达一个叶子节点后,找到最近的条目,测试是否能够吸收CF 条目而不违反阈值条件。如果可以,更新 CF 条目,否则,向叶子添加新的 CF 条目。如果叶子上没有足够的空间来容纳这个新条目,那么我们必须分割叶子节点。通过选择相距最远的两个条目作为种子并基于距离重新分配剩余条目来完成节点分裂。
- 修改到叶子的路径:回忆一下每个非叶子节点本身是如何由它的所有子节点的 CF 组成的 CF。因此,在将一个 CF 条目插入到一个叶子中之后,我们为到叶子的路径上的每个非叶子条目更新 CF 信息。在分裂的情况下,我们必须在父节点中插入一个新的非叶子条目,并让它指向新形成的叶子。如果根据 B ,父节点没有足够的空间,那么我们也必须拆分父节点,以此类推直到根节点。
聚类算法
现在,我们已经介绍了 BIRCH 的一些基本概念,让我们来看看算法是如何工作的。
http://www.cs.uvm.edu/~xwu/kdd/BIRCH.pdf
第一相
该算法从初始阈值开始,扫描数据,并将点插入树中。如果它在扫描完数据之前耗尽了内存,它会增加阈值,并通过将旧 CF 树的叶条目重新插入新 CF 树来重建一个新的更小的 CF 树。在所有旧的叶子条目被重新插入之后,数据的扫描和插入到新的 CF-树中从它被中断的点重新开始。
阈值的良好选择可以大大减少重建次数。然而,如果初始阈值太高,我们将获得比可用存储器可行的更不详细的 CF-树。
http://www.cs.uvm.edu/~xwu/kdd/BIRCH.pdf
可选地,我们可以分配固定数量的磁盘空间来处理异常值。离群值是低密度的叶条目,被判断为相对于整个聚类模式不重要。当我们通过重新插入旧的叶子条目来重建 CF-树时,新的 CF-树的大小以两种方式减小。首先,我们增加阈值,从而允许每个叶子条目吸收更多的点。其次,我们将一些叶条目视为潜在的离群值,并将它们写到磁盘上。如果旧叶条目的数据点远少于平均值,则它被认为是潜在的异常值。响应于新数据的阈值的增加或分布的改变很可能意味着潜在的异常值不再有资格作为异常值。因此,扫描潜在的离群值,以检查它们是否可以被树重新吸收,而不会导致树的大小增长。
第二相
假设当对象的数量在一定范围内时,某些聚类算法表现最佳,我们可以将拥挤的子聚类分组为更大的子聚类,从而产生整体更小的 CF-tree。
第三阶段
几乎任何聚类算法都可以用来对聚类特征而不是数据点进行分类。例如,我们可以使用 KMEANS 对我们的数据进行分类,同时从 BIRCH 中获得好处(即最大限度地减少 I/O 操作)。
第四阶段
到目前为止,尽管树可能已经被重建了多次,但是原始数据只被扫描了一次。阶段 4 涉及对数据的额外传递,以校正由于聚类算法被应用于数据的粗略汇总这一事实而导致的不准确性。阶段 4 还为我们提供了丢弃异常值的选项。
密码
接下来,我们将在 Python 中实现 BIRCH。
import numpy as np
from matplotlib import pyplot as plt
import seaborn as sns
sns.set()
from sklearn.datasets.samples_generator import make_blobs
from sklearn.cluster import Birch
我们使用scikit-learn
来生成具有良好定义的集群的数据。
X, clusters = make_blobs(n_samples=450, centers=6, cluster_std=0.70, random_state=0)
plt.scatter(X[:,0], X[:,1], alpha=0.7, edgecolors='b')
接下来,我们使用以下参数初始化并训练我们的模型:
- 阈值:新样本和最近的子聚类合并得到的子聚类的半径应该小于阈值。
- branch _ factor:每个节点中 CF 子簇的最大数量
- n_clusters: 最终聚类步骤后的聚类数,该步骤将来自叶子的亚聚类视为新样本。如果设置为
None
,则不执行最后的聚类步骤,子聚类按原样返回。
brc = Birch(branching_factor=50, n_clusters=None, threshold=1.5)brc.fit(X)
我们使用predict
方法来获得一系列的点和它们各自的集群。
labels = brc.predict(X)
最后,我们用不同的颜色绘制每个聚类的数据点。
plt.scatter(X[:,0], X[:,1], c=labels, cmap='rainbow', alpha=0.7, edgecolors='b')
最后的想法
BIRCH 为非常大的数据集提供了一种聚类方法。它通过集中在密集占用的区域,并创建一个紧凑的摘要,使一个大的聚类问题看似合理。BIRCH 可以使用任何给定数量的内存,I/O 复杂性比一次数据扫描多一点。其他聚类算法可以应用于 BIRCH 产生的子聚类。
2020 年你应该读的机器学习书籍
现在最好的机器学习书籍是什么
机器学习成为计算机科学最热门的领域之一。每个更大的公司要么应用机器学习,要么考虑尽快这样做,以解决他们的问题,了解他们的数据集。这意味着是时候学习机器学习了,尤其是如果你正在寻找新的计算机科学挑战。一个很好的方法就是读几本书。在这篇文章中,我将回顾 2020 年最好的机器学习书籍。
Machine Learning Books
入门水平
如果你刚刚开始学习机器,一定要读这本书:
Python 机器学习入门是机器学习的温和入门。它没有假设任何关于 Python 的知识,它介绍了机器学习的基本概念和应用,通过例子讨论了各种方法。这是我见过的入门级机器学习工程师的最佳书籍。
中间能级
如果你已经为自己完成了一系列机器学习项目,并习惯了使用机器学习模型,下面这些书将带你走得更远:
Python 机器学习是一本很棒的实用书籍,里面有很多实际的代码示例。它从温和开始,然后进入机器学习和深度学习的最新进展。它非常容易阅读,将吸引任何水平的人,因为第二版甚至涵盖了甘斯。
用 Scikit-Learn 和 TensorFlow 进行机器学习(第二版已经推出!)是中级惊人的参考。它涵盖了所有的基础知识(分类方法、降维),然后进入神经网络和深度学习。
模式识别和机器学习从一个好的统计修正开始,遍历所有的基本算法。它主要关注机器学习的理论方面,是其他更实用书籍的绝佳伴侣。
专家
在专家水平上,阅读科学论文通常比阅读书籍好得多,因为在我们说话的时候,知识正在更新。机器学习真的是活在当下。然而,手里有一堆书籍参考资料来完全进入深度学习也是很棒的:
用 Python 进行深度学习是由 Keras 的一个创建者编写的,Keras 是 Python 中最流行的机器学习库之一。这本书从温和开始,非常实用,给出了你可以马上使用的代码,并且总的来说有许多关于使用深度学习的有用提示。深度学习的必读书目。
深度学习是深度学习算法的惊人参考。它包含的代码不多,但对如何处理机器学习问题有很好的见解:由深度学习的先驱编写。它涵盖了几乎所有目前使用的技术。
如果你更注重数学,那么你会喜欢机器学习:概率视角。这是所有机器学习方法背后的数学杰作。你很可能一下子读不出来,但是作为机器学习研究中的参考非常有用。
Data Science Job
最后,如果你想了解成为一名数据科学家意味着什么,那么看看我的书数据科学工作:如何成为一名数据科学家,它将指导你完成这个过程。
仅此而已!祝你在机器学习的旅途中一切顺利!
如果你正在寻找你的第一份入门级数据科学工作,并且不知道从哪里开始,请在这里 报名参加我的 数据科学工作课程。我解释你应该做什么,并在几周内学会成为一名初级数据科学家或初级机器学习工程师。
如果您正在查找其他书籍列表,请参阅:
请继续关注更多有用的材料](https://creative-producer-9423.ck.page/c3b56f080d)
机器学习案例研究:预测银行电话营销成功的数据驱动方法
给定客户关系数据,预测客户是否会认购定期存款
Photo by Franki Chamaki on Unsplash
当今世界,数据为王。以有效的方式使用它,它可以对你的业务产生巨大的影响,不要利用它,你会很快被这个快节奏的世界抛在后面。组织提高其市场绩效的方法之一是以有效的方式获取和分析客户数据,以改善客户体验。
最近机器学习进步改变最大的行业之一是金融业。无论是预测股票价格,还是在我们的案例中预测客户是否会订阅定期存款,机器学习都是一种非常有用的工具,可以提供更好的盈利能力。有了这个,让我们直接进入我们的案例研究。
关于问题:
我们获得了一家葡萄牙银行机构的直接营销活动(电话)数据。分类的目标是预测客户是否会认购定期存款(目标变量 y)。本案例研究受到了这篇研究论文的启发,研究人员使用了一个非常相似的数据集,我们将在整个案例研究中使用该数据集来确定银行电话营销的成功与否。研究人员在他们的论文中提到,他们得到的最好结果是 AUC 分数为 0.8,ALIFT 为 0.7。因此,作为一个目标,我们将尝试在我们的案例研究中产生类似的结果。
关于数据集:
如上所述,数据集由银行机构的直接营销活动数据组成。数据集选自 UCI 机器学习库,这是一个公开可用数据集的惊人来源。数据集有四个变量,我们从中选择了“bank-additional-full.csv ”,它由 41188 个数据点和 20 个独立变量组成,其中 10 个是数字特征,10 个是分类特征。我们可用的功能列表如下:
银行客户数据:
- 年龄(数字)
- 作业:作业类型(分类:“管理。”、'蓝领'、'企业家'、'女佣'、'管理'、'退休'、'自雇'、'服务'、'学生'、'技术员'、'失业'、'未知')
- 婚姻:婚姻状况(分类:“离婚”、“已婚”、“单身”、“未知”);注意:“离婚”是指离婚或丧偶)
- 教育(分类:'基础. 4y ','基础. 6y ','基础. 9y ','高中','文盲','专业.课程','大学.学位','未知')
- 违约:有信用违约?(分类:“否”、“是”、“未知”)
- 住房:有住房贷款吗?(分类:“否”、“是”、“未知”)
- 贷款:有个人贷款?(分类:“否”、“是”、“未知”)
与当前战役的最后一个联系人相关:
8。联系人:联系人通信类型(分类:“手机”、“电话”)
9.月份:一年中的最后一个联系月份(分类:'一月','二月','三月',…,'十一月','十二月')
10.星期几:一周的最后一个联系日(分类:“星期一”、“星期二”、“星期三”、“星期四”、“星期五”)
11.duration:上次联系持续时间,以秒为单位(数字)。重要注意事项:该属性对输出目标有很大影响(例如,如果 duration=0,则 y='no ')。然而,在执行呼叫之前,持续时间是未知的。还有,结束通话后 y 显然是已知的。因此,该输入应仅用于基准测试目的,如果目的是获得现实的预测模型,则应丢弃。
其他属性:
12。活动:在此活动期间为此客户执行的联系次数(数字,包括最后一次联系)
13.pdays:从上一个活动中最后一次联系客户后经过的天数(数字;999 表示之前没有联系过客户)
14.上一次:在此活动之前为此客户执行的联系次数(数字)
15.poutcome:之前营销活动的结果(分类:“失败”、“不存在”、“成功”)
社会经济背景属性
16。员工变动率:员工变动率-季度指标(数字)
17.cons.price.idx:消费者价格指数—月度指标(数字)
18.cons.conf.idx:消费者信心指数——月度指标(数字)
19.euribor3m: euribor 3 个月利率—每日指标(数字)
20.受雇人数:雇员人数—季度指标(数字)
机器学习问题的类型:
现在您可能已经猜到了,这是一个二元分类问题。我们的两个类别是“是”表示客户订阅了定期存款,“否”表示客户没有订阅。
使用的绩效指标:
本案例研究使用的性能指标是 AUC ROC 得分,也称为AUROC(接收器操作特性下的区域)。
为什么使用 AUC? 我们选择 AUC 而不是准确性的原因是,
正如我们将在探索性数据分析中看到的,我们正在处理的数据集是一个不平衡的数据集,其中类“否”是大多数类。如果我们使用准确性作为我们的度量,任何随机模型都可以给我们一个非常好的准确性。但最终,它将是一个随机模型。AUC 通过调查真阳性率(TPR)和假阳性率(FPR)来解决这个问题。只有当 TPR 和 FPR 都远高于 ROC 曲线中的随机线时,我们才能获得良好的 AUC。准确性并不能保证这一点。
探索性数据分析:
在对问题一无所知的情况下就开始建模并不是一个好主意。因此,作为开始,我们将进行一些 EDA,以更多地了解我们正在处理的是什么类型的数据,以及这些数据是否有任何模式。我们将进行一些单变量分析,以找出哪些特征可以帮助我们完成分类任务,哪些变量并不那么重要。现在,如果我们在这里对所有 20 个特征逐一进行单变量分析,这将是一个非常冗长的博客,我们将只研究这个博客中的一些关键方面。如果你想浏览我的整个案例研究,你可以在这个资源库中找到。
类别变量的分布 :
首先我们将研究类别分布,看看它是否是一个平衡的数据。
Class distribution
从上面的图中我们可以看到,数据集是不平衡的,其中负类的数量接近正类数量的 8 倍。
现在,我们将进行一些单变量分析,即一次获取一个特征,并检查它在两个类别之间的区分程度。例如,我们数据集中的一个特征是客户的“工作”。我们将查看分布情况,以确定是否有任何特定类别的功能比其他类别订阅定期存款更多。
分类变量的单变量分析:
我们将研究每个特性的计数图,找出每个特性的类别分布。首先,让我们定义一个绘制计数图的函数,这将有助于我们继续进行案例研究。
工作:客户的工作类型。让我们调用前面定义的计数图函数来绘制作业特征的计数图。
从上面的图中,我们可以看到,有管理工作的客户认购定期存款的比率最高,但他们不认购的比率也最高。这仅仅是因为我们有比其他职业更多的客户从事管理工作。
让我们看看更多的功能。
婚姻:这只是表示客户的婚姻状况。
大多数顾客都结婚了。其次是单身,离异,不知名。
违约:表示客户是否有信用违约。类别包括是、否和未知。
住房:表示客户是否有住房贷款。三个类别是“否”、“是”、“未知”。
从上面的图中我们可以看出,大多数客户都有住房贷款。
poutcome:该特征表示先前营销活动的结果。
对于大多数客户来说,先前的营销活动结果并不存在。说明大部分客户都是之前没有接触过的新客户。这里还需要注意的一点是,对于那些在之前的活动中取得成功的客户,大多数客户选择了定期存款。因为它的等级分布为正等级 2.2%,负等级 1.2%。由此,我们可以假设,该特征在预测目标变量时可能具有一些价值。特别 poutcome_success 类别。
让我们来看看一些在分析中似乎没有太大帮助的特性。
星期几:该特性表示一周的最后一个联系日(分类:“周一”、“周二”、“周三”、“周四”、“周五”)
从上面的图中我们可以清楚地看到,这两个类的所有天数都有相似的分布。任何一天都有 17-18%的客户拒绝认购定期存款,2.1-2.5%的客户同意认购。由此我们可以推断出,该特征在预测目标变量时不会有很大帮助。
有了这个,让我们看看一些数字特征。
数字特征的单变量分析:
我们将研究箱形图和所有数字特征的分布。
年龄:
从上面的箱线图中,我们知道订购或未订购定期存款的客户的中值年龄约为 38-40 岁。这两个类别的箱线图有很多重叠,这意味着年龄不一定是哪个客户会订阅哪个客户不会订阅的好指标。
持续时间:这个特性在我们的案例研究中非常有趣。它表示最后一次联系的持续时间,以秒为单位。在数据集的来源中提到:
重要提示:该属性对输出目标有很大影响(例如,如果 duration=0,则 y='no ')。然而,在执行呼叫之前,持续时间是未知的。还有,在调用结束后,目标变量 y 显然是已知的。因此,该输入应仅用于基准测试目的,如果目的是获得现实的预测模型,则应丢弃。
所以有了这个我们就知道这个特性会很有意思 xD。我们也知道,我们将无法在最终模型中包含此功能,因为很明显,我们希望创建一个可供业务使用的现实预测模型。但是,我们肯定会实现一个具有持续时间特性的基本模型,来看看这个特性会产生多大的影响。因此,让我们看看这个功能的方框图和 pdf。
从上图可以清楚地看出,客户的持续时间(上次联系持续时间)对于预测目标变量非常有用。这是意料之中的,因为在数据概述中已经提到,该字段高度影响目标变量,并且应该仅用于基准目的。
就业变动率:就业变动率,季度指标。尽管这一特征和其他一些特征(如“先前的”等)是数字特征,但是它们具有有限数量的重复出现的唯一值。这是 emp.var.rate 特性的值计数。
value counts for the feature
euribor3m:
euribor 3 个月利率,每日指标。euribor 表示欧盟银行间市场上银行间借贷的基本利率,也用作设定其他贷款利率的参考。
从上面的图中,我们可以清楚地看到两个类的中位数的差异。这表明该特性对我们的案例研究非常有用。但是我们只能通过应用模型和提取特征重要性来验证这个假设。
数字特征的相关矩阵:
相关矩阵的想法来自这个博客。相关性是一种统计度量,表示两个或更多变量一起波动的程度。正相关性表明这些变量平行增加或减少的程度;负相关表示一个变量增加而另一个变量减少的程度。这是一个非常有用的工具,可以快速检查哪些要素更相关,哪些要素对不相关。
emp.var.rate、cons.price.idx、euribor3m 和 nr.employed 特征具有非常高的相关性。其中 euribor3m 和 nr.employed 的相关性最高,为 0.95!
完成基本的 EDA 之后,让我们进入下一步,即数据预处理。如果你想浏览所有特性的 EDA,你可以查看这个库。
数据预处理:
由于我们的数据集有 10 个分类特征,我们需要将这些特征编码成数字表示,以应用机器学习模型。在本案例研究中,我们将研究两种编码方案,并在案例研究结束时比较两种编码方案的结果。这两种编码方案是:
1。一种热门编码:这是处理分类特征最流行的编码方案之一。对于每个唯一的类别,它创建一个具有二进制值(0 或 1)的单独列。在这些新列的每一列中,如果相应的类别出现在该行中,则值为 1,否则为 0。
2。响应编码:作为该技术的一部分,我们表示数据点属于给定类别的特定类别的概率。因此,对于 K 类分类问题,我们得到 K 个新特征,这些新特征基于分类数据的值嵌入属于每个类的数据点的概率。从数学上来说,我们计算—
P(class = X | category = A)= P(category = A∩class = X)/P(category = A)
但是在对分类特征进行编码之前,让我们首先进行一些基本的检查,看看是否有任何丢失的值或重复的行等,因为它们会影响最终的模型性能。
处理缺失值:
谢天谢地,在我们的数据集中没有丢失值。如果有任何缺失值,我们要么删除行(如果缺失值的数量比我们拥有的数据量少),要么使用插补来处理缺失值。
处理重复值:
There are 12 duplicate rows
正如我们可以看到的,在我们的数据集中有一些重复的行,我们将在继续之前删除重复的行。
删除重复行后,总共有 41176 行。
分离自变量和类变量:
拆分数据:
现在,在应用任何编码方案之前,将数据集分成训练、测试和 CV 数据集是非常重要的。否则我们会有数据泄露的问题。因此,在对分类变量进行编码之前,让我们先对数据进行分割。我们将对训练、cv 和测试数据集分别应用 64%、16%和 20%。
一个热点编码分类变量:
One hot encoding the categorical variables
为了对分类变量进行编码,我们使用 CountVectorizer,它通常用于将文本特征编码到单词包(BoW)表示中。由于测试数据集中丢失维度的问题,我们使用 countVectorizer 而不是任何其他函数进行一次热编码。这是一个问题,你会面临,如果你说使用熊猫获取 _ 假人功能。出现问题的原因是,当您将数据分割为训练时,测试可能会有一些类别的一些特征会在训练中,但不在测试数据集中。如果你使用 pd.get_dummies,你将在训练和测试中得到不同的维度。为了解决这个问题,我们在训练数据集上使用 CountVectorizer 和 fit_transform,并在 cv 和测试数据集上进行转换,正如您在上面的嵌入式代码中看到的那样。
使用 T-SNE 图可视化数据集:
因为我们已经可以对我们的数据集进行编码,所以不在它上面应用 t-sne 来可视化 2D 的高维数据是非常不公平的,不是吗?所以我们就这么做吧。
Tsne on train dataset
Tsne on CV dataset
TSNE on test dataset
正如我们所看到的,尽管数据中似乎有很多重叠,但这两个类别之间似乎有一些区别。
分类变量的响应编码:
现在让我们对分类特征使用响应编码。在我们完成响应编码之后,我们将进入建模部分,在这里我们将比较使用两种编码方案的模型的结果,以查看编码方案是否会产生影响。以下是使用响应编码对分类特征进行编码的伪代码:
*# alpha is for laplace smoothing* *1\. Consider all unique values and the number of occurrences of given feature in train data frame**2\. Build a vector (1*2) [As this is a binary classification problem].**3\. The first element = (number of times it occured in class1 + 10*alpha / number of time it occurred in total data+20*alpha)**4\. Create a dict (say feat_dict) that will store every categorical data as key and store a (1*2) representation of response coded vector as the value*5\. Create a list (say res_fea) that will store the final response coded features*5\. for a value of feature in df:*
*if it is in train data:*
*we add the vector that was stored in 'feat_dict' look up table to 'res_fea'*
*if it is not there in train data:*
*we add [1/2, 1/2] to 'res_fea' to indicate equal probability of both classes.**return 'res_fea'*
预测目标变量:
现在是我们一直在等待的部分,我们将数据应用到机器学习模型来预测目标变量。让我们从这个开始。
应用具有和不具有“持续时间”特征的逻辑回归:
现在正如我所承诺的,在开始创建一个可以使用的真实模型之前,我们将首先看看持续时间特性是如何影响输出的。为此,我们将只应用简单的逻辑回归模型,没有任何超参数调整,有和没有持续时间列,并比较结果。之后,我们将从数据集中一劳永逸地移除该特征,并应用各种模型。
应用逻辑回归:
现在,我们将对 One hot 编码数据集和 Response 编码数据集应用逻辑回归,并比较结果。
对一个热点数据进行编码:
从上面的要点中我们可以看出,我们通过用一种热编码方案对数据集应用逻辑回归得到的最佳 AUC 是 0.798。无论如何,这非常接近研究人员得到的 0.8。让我们看看逻辑回归如何在响应编码数据集上工作。
上应答编码数据:上
对于反应编码,逻辑回归的效果不如热编码,给出的 AUC 为 0.77。
同样,我们将应用一些其他模型,看看哪种算法效果最好,可以让我们的 AUC 达到或超过 0.8。
应用线性 SVM:
对一个热点数据进行编码:
上应答编码数据:上
应用随机林:
关于一个热编码数据:
关于响应编码数据:
在随机森林的情况下,我们可以看到,即使在超参数调整之后,模型仍然过度拟合,训练 AUC 为 0.99,测试 AUC 为 0.77。这并不奇怪,因为随机森林在某些情况下确实有过度适应的趋势。
现在让我们尝试我最喜欢的算法之一,XGBoost,看看它是否能胜过所有其他模型,给我们一个超过 0.8 的测试 AUC 分数!
应用 XGBoost:
关于一个热编码数据:
对应答编码数据:
从上面两个 gists 可以看出,XGBoost 在响应编码数据上给出了 0.803 的测试 AUC 分数。我们还可以在 gists 的末尾看到两种编码方案中每个特性的特性重要性。事实证明,最重要的特征是数字特征:在最后的结论中有更多的内容。
总结:
因此,在应用了所有模型后(我还应用了 KNN 和径向基函数 SVM 核函数,我在这里没有包括它们),这是所有训练和测试 AUC 分数的最终表格。
Final Report
最重要的关键特性:
帮助预测类变量的前 3 个关键特征或属性是:
1。受雇人数
2。euribor3m
3。员工变动率
除了这三个缺点,price.idx 和分类特征 month 和 poutcome 在我们的案例研究中也非常重要
达到 0.803 AUC 的步骤如下:
因此,让我们快速回顾一下我们在本案例研究中所做的工作,以实现我们所期望的性能。
- 本案例研究的目的是,在给定客户数据的情况下,预测客户是否会认购定期存款。
- 有许多分类变量和一些数字变量,它们捕获了有关客户和银行-客户关系的各种信息。
- 首先,我们做了 EDA,发现数据没有空值,并且数据是不平衡的,其中“否”是大多数类。
- 在对进行单变量分析后,我们发现星期几在预测目标变量时帮助不大。但是另一方面,一些数字特征倾向于更好地预测目标变量。
- 使用 T-SNE 进行数据可视化后,很明显,数据在类之间没有很好的分离,因为即使在尝试不同的参数后,两个类也高度重叠。
- 在基本的数据预处理之后,我将分类数据编码成一个热编码方法和一个响应编码方法。
- 在实现了所有的模型之后,我们看到给出最佳性能的模型是 XGBoost with RandomizedSearchCV,并且测试 AUC 是 0.803,这与研究人员在相关研究论文中得到的结果相似。
注意:
如果您想浏览完整的案例研究,您可以查看这个库。
关于我:
嗨,我叫 Sukanta Roy,我是一名软件开发人员和一名有抱负的机器学习工程师,前谷歌 2018 年代码之夏的学生,也是一名巨大的心理学爱好者。如果你对这些感兴趣,你可以通过 medium 和 LinkedIn 与我联系。
面向直接营销的 Python 机器学习分类
你如何提高业务的时间效率、削减成本并提高销售额?这个问题是永恒的,但不是修辞性的。在接下来的几分钟阅读时间里,我将应用一些分类算法来演示数据分析方法的使用如何有助于实现这一目标。我们将一起创建一个预测模型,帮助我们定制交给电话营销团队的客户数据集,以便他们可以首先将资源集中在更有前景的客户上。
在此过程中,我们将对数据集执行一些操作。首先,我们将对数据进行清理、编码、标准化和重新采样。一旦数据准备就绪,我们将在训练子集上尝试四种不同的分类器,进行预测并用混淆矩阵可视化它们,并计算 F1 分数以选出最佳模型。这些步骤已经放在模式中:
Project’s schema
我们将在这里使用的数据集对这个城镇来说并不陌生,您可能以前就遇到过。41,118 条记录的数据样本由一家葡萄牙银行在 2008 年至 2013 年间收集,包含电话营销活动的结果,包括客户对银行提供的存款合同的回应(二元目标变量“y”)。这种反应正是我们要用模型预测的。数据集可从加州大学欧文分校的机器学习仓库获得。所以让我们开始吧!
结果:
数据清理、特征选择、特征转换
“我喜欢把事情一笔勾销”,弗里德里希·尼采说。这是数据清理部分!
使用df.isnull().sum()
查询,我们确保数据集中没有丢失的值(如果有的话,df.dropna(subset = ['feature_name'], inplace=True)
会将它们从相关的列中删除)。
在本例中,我使用 Tableau Prep Builder 数据清理工具来跟踪和删除异常值,以确保数字特征中的值不是字符串,重命名一些列并删除一些不相关的列,例如'contact', 'month', 'day_of_week', 'duration', 'campaign', 'pdays', 'previous' and 'poutcome'
(这些列描述了一个已经发生的电话呼叫,因此不应在我们的预测模型中使用)。
接下来,我们将把分类变量的非数字标签转换成数字标签,并把它们转换成整数。我们这样做:
运行df.dtypes
查询只是为了确保标签已经变成整数,这是有意义的。然后,我们应用sklearn.preprocessing
工具箱中的StandardScaler
来标准化我们期望在模型中使用的其他特征的数值。该方法通过移除平均值并缩放至单位方差来标准化特征:
现在,让我们使用递归特征消除(RFE)方法和随机森林分类器算法作为估计器对数据集的特征进行排序:
输出:
Num Features: 6
Selected Features: [ True True False True False False True False True True]
Feature Ranking: [1 1 3 1 2 5 1 4 1 1]
在稍后的阶段,当我们将建立一个预测模型时,我们将利用这个特性排名。我们将使用该模型,试图找到排名最高的特征的最佳组合,该组合将做出具有令人满意的 F1 分数的预测。展望未来,最佳组合将是:
例如,随着欺诈性信用卡交易或在线活动的结果等分类案例的出现,往往会出现类别失衡的问题。在执行df['y'].value_counts()
查询后,我们看到变量‘y’的两个类在我们的数据集中也没有被平等地表示。数据清理后,目标变量“y”中有 35584 条属于类“0”的记录,只有 4517 条属于类“1”的记录。在将数据分成训练样本和测试样本之前,我们应该考虑对数据进行过采样或欠采样。
为了对数据进行重新采样,让我们从imblearn.over_sampling
工具箱中应用SMOTE
方法进行过采样(对于此步骤,您可能需要先安装带有 Pip 或 Conda 的imblearn
包):
就这么简单。现在,数据与每个类中的 35584 个条目保持平衡:
输出:
[35584] [35584]
构建预测模型
既然数据已经准备好了,我们就可以训练我们的模型并进行预测了。让我们首先将数据分成训练集和测试集:
我们将尝试四种分类算法,即逻辑回归、支持向量机、决策树和随机森林,然后使用用户定义的scorer
函数计算它们的 F1 得分,以选择得分最高的分类器:
输出:
LogisticRegression F1 score = 0.71245481432799659
SVC F1 score = 0.753674137005029
DecisionTreeClassifier F1 score = 0.7013983920155255
RandomForestClassifier F1 score = 0.923286257213907
F1 得分是准确率和召回率的加权平均值。你可以在我的帖子这里阅读如何解读精度和召回分数。
现在,让我们打印一份完整的分类报告,其中包含随机森林算法的精确度和召回率,该算法已经证明了最高的 F1 分数:
输出:
precision recall f1-score support
0 0.91 0.93 0.92 10594
1 0.93 0.91 0.92 10757
micro avg 0.92 0.92 0.92 21351
macro avg 0.92 0.92 0.92 21351
weighted avg 0.92 0.92 0.92 21351
最后,我们可以用混淆矩阵将结果可视化:
结果:
太好了!我们已经清理并转换了数据,选择了最相关的特征,选出了最佳模型,并做出了一个得分不错的预测。现在,我们有了一个模型,可以帮助我们定制交给电话营销团队的客户数据库,这样他们就可以将精力集中在那些更有条件首先对活动做出肯定反应的人身上。
感谢您的阅读!!
使用 ROC 和 CAP 曲线的机器学习分类器评估
Photo by Isaac Smith on Unsplash
虽然有几个度量标准,如准确性和召回率,来衡量机器学习模型的性能,但 ROC 曲线和 CAP 曲线非常适合分类问题。在本文中,我将探讨什么是 ROC 和 CAP,以及我们如何使用 Python 和虚拟数据集来创建这些曲线。
即使在探索了许多关于 CAP Curve 的文章后,我也找不到一篇详细解释如何创建它们的文章,这就是我写这篇文章的原因。
完整的代码被上传到下面的 GitHub 库。
在这个知识库中,我讨论了各种机器学习模型的性能评估指标。…
github.com](https://github.com/kb22/ML-Performance-Evaluation)
资料组
我创建了自己的数据集。有两个特性,age
和experience
。基于这两个特征,输出标签为0.0
表示工资低于 20 万美元,而1.0
表示工资高于或等于 20 万美元。
Complete dataset
GREEN
点数代表超过或等于 20 万美元的薪资,而RED
点数代表低于 20 万美元的薪资。我还确保了这两个类之间有一些重叠,所以数据更真实一些,不容易分离。
分类
首先,我将数据分成两组,70%的训练数据和 30%的测试数据。我用Support Vector Classifier
和linear kernel
对训练数据进行训练,然后在测试数据上测试模型。该模型取得了 95% 的评分。
Classification on Test data
性能赋值
受试者工作特性曲线
接收器操作特性曲线,更好地称为 ROC 曲线,是测量分类模型性能的极好方法。针对分类器预测的概率,将真阳性率(TPR) 与假阳性率(FPR) 作图。然后,计算地块下的面积。
曲线下的面积越大,模型区分类别的能力就越强。
导入文件并创建基线 首先,我从sklearn.metrics
导入roc_curve
和auc
,这样我可以创建 ROC 曲线并计算曲线下的面积。我还将图形大小定义为 20x12,并创建一条从(0,0)
到(1,1)
的基线。
值r--
表示线条颜色为红色,是一条虚线(— — — — — — — — — — — — —
)。
计算概率并确定 TPR 和 FPR 接下来,使用predict_proba
我计算预测的概率并将其存储在probs
中。它由两列组成,第一列包括第一类的概率(薪金< $20 万),第二列包括第二类的概率(薪金≥ $20 万)。所以,我用probs[:, 1]
选择第二类的概率。
roc_curve
生成 roc 曲线并返回fpr
、tpr
和thresholds
。最后,使用fpr
和tpr
作为auc
中的输入,我计算出该模型曲线下的面积,并将其保存在roc_auc
中。roc_auc
现在有了我们的支持向量分类器生成的曲线下的面积。
绘制 ROC 曲线 我使用fpr
作为 x 值和tpr
作为 y 值绘制曲线,颜色为绿色,线宽为 4。这条曲线的标签包括曲线下的区域。x 轴标签设置为False Positive Rate
,y 轴标签设置为True Positive Rate
。标题为Receiver Operating Characteristic
,图例出现在图的右下角。文本大小设置为 16。
ROC Curve
曲线下面积为 0.98,这真是令人惊讶,提供了我们的模型表现良好的信息。
累积精度曲线
CAP 曲线试图分析如何使用最少的尝试次数有效地识别给定类别的所有数据点。在这个数据集中,我试图确定Support Vector Classifier
能够多快地识别出所有工资高于或等于 20 万美元的个人。
计算每个类的计数 首先,我在测试数据(60)中找到总的数据点,并保存在变量total
中。测试标签要么是0.0
要么是1.0
,所以如果我把所有的值加起来,我将得到类1.0
(31)的计数,我可以把它保存在class_1_count
中。从total
中减去这个数将得到class_0_count
(29)。
我还将图形尺寸设置为 20x12,使其比正常尺寸大。
随机模型 首先,我们绘制一个随机模型,该随机模型基于类别1.0
的正确检测将线性增长的事实。
颜色为red
,样式为使用--
定义的dashed
。我已经将标签设置为Random Model
。
Random Model
完美模型
接下来,我绘制完美模型。一个完美的模型将在与类别1.0
数据点相同的尝试次数中检测所有类别1.0
数据点。完美模型需要 31 次尝试来识别 31 类1.0
数据点。
我把这块地涂成灰色。标签设置为Perfect Model
。
Perfect Model
经过训练的模型(支持向量分类器)
最后,我绘制出Support Vector Classifier
的结果。首先,像在 ROC 曲线中一样,我提取变量probs
中类1.0
的概率。
我把probs
和y_test
拉上拉链。然后,我按照概率的逆序对这个 zip 文件进行排序,最大概率排在最前面,然后是较小的概率。我只提取数组中的y_test
值,并将其存储在model_y
中。
np.cumsum()
创建一个值数组,同时将数组中所有以前的值累加到当前值中。例如,如果我们有一个数组[1, 1, 1, 1, 1]
。应用cumsum
将导致[1, 2, 3, 4, 5]
。我用它来计算 y 值。此外,我们需要在数组前面追加0
作为起始点(0,0)
。x 值的范围从0
到total + 1
。我添加一个,因为np.arange()
不包括终点,我希望终点是total
。
然后我用蓝色标出结果,并标上Support Vector Classifier
。我还将另外两个模型包含在情节中。
Support Vector Classifier
使用曲线下面积
的 CAP 分析分析 CAP 曲线的第一种方法是使用曲线下面积。让我们考虑随机模型下的面积为a
。我们使用以下步骤计算准确率:
- 计算完美模型(
aP
)到随机模型(a
)下的面积 - 计算预测模型(
aR
)到随机模型(a
)下的面积 - 计算准确率(
AR
) = aR / aP
准确率越接近 1,模型越好。
使用auc
,我计算了所有面积,然后使用这些值计算了准确率。该比率约为 0.97,非常接近于 1,表明我们的模型非常有效。
使用图进行 CAP 分析 另一种分析 CAP 曲线的方法是读取我们上面生成的图。相同的步骤如下:
- 从 x 轴的 50%处画一条垂直线,直到它穿过
Support Vector Classifier
图。 - 在垂直线与训练模型相交的点上,画一条水平线,使其与 y 轴相交。
- 计算 1 类标签占 1 类标签总数的百分比。
一旦我们知道了百分比,我们就可以用下面的括号来分析它。低于 60%:垃圾型号
2。60% — 70%:差模
3。70% — 80%:好型号
4。80% — 90%:非常好的型号
5。超过 90%:好得难以置信
请注意,如果该值超过 90%,测试过度拟合是一个很好的做法。
首先,我通过计算总测试数据的 50%的 int 值来找到索引。我用它来画一条从这个点到训练好的模型的垂直虚线(— — —
)。接下来,我画出从这个交点到 y 轴的直线。我通过将目前观察到的类1.0
值除以总的类1.0
数据点并乘以 100 来确定百分比。我得到的值为 93.55% 。
CAP Curve Analysis
尽管百分比是 93.55%,大于 90%,但结果是预期的。正如我们在开始时看到的数据集和分类,该模型在拆分数据方面非常有效。虽然我对测试数据使用了 CAP 分析,但我们也可以对训练数据使用同样的方法,并分析我们的模型对训练数据的了解程度。
结论
本文总结了如何用 Python 计算 ROC 曲线和 CAP 曲线,以及如何对它们进行分析。
请随时分享你的想法和想法。与 ROC 和 CAP 一起工作对我来说也是全新的,所以请分享我可能错过的任何信息。感谢阅读!
DBSCAN Python 示例:Epsilon (EPS)的最佳值
https://www.pexels.com/photo/a-boy-holding-a-chalk-5212334/
DBSCAN,即基于密度的带噪声应用空间聚类,是一种无监督的机器学习算法。无监督的机器学习算法用于分类未标记的数据。换句话说,用于训练我们的模型的样本没有预定义的类别。与其他聚类算法相比,DBSCAN 特别适用于需要以下条件的问题:
- 确定输入参数的最少领域知识(即 k-means 中的 K 和层次聚类中的 Dmin
- 发现任意形状的团簇
- 大型数据库的良好效率
如果你对阅读 DBSCAN 感兴趣,可以在这里找到原文。
算法
与大多数机器学习算法一样,模型的行为由几个参数决定。在接下来的文章中,我们将触及三个问题。
- eps :如果两点之间的距离低于阈值ε,则认为这两点是相邻的。
- min_samples :一个给定点为了被分类为核心点而应该拥有的最小邻居数量。需要注意的是,点本身包含在最小样本数中。
- 度量:计算特征数组中实例间距离时使用的度量(即欧几里德距离)。
该算法通过计算每个点和所有其他点之间的距离来工作。然后,我们将这些点分为三类。
核心点:至少有 个 min_samples 个点的点,这些点相对于该点的距离低于由ε定义的阈值。
边界点:至少与 min_samples 点不接近,但与一个或多个核心点足够接近的点。边界点包含在最近核心点的群集中。
噪声点:离核心点不够近的点被认为是边界点。噪声点被忽略。也就是说,它们不属于任何集群。
密码
让我们看看如何用 python 实现 DBSCAN。若要开始,请导入以下库。
import numpy as np
from sklearn.datasets.samples_generator import make_blobs
from sklearn.neighbors import NearestNeighbors
from sklearn.cluster import DBSCAN
from matplotlib import pyplot as plt
import seaborn as sns
sns.set()
与导入数据相反,我们可以使用scikit-learn
来生成定义良好的集群。
X, y = make_blobs(n_samples=300, centers=4, cluster_std=0.60, random_state=0)
plt.scatter(X[:,0], X[:,1])
如前所述,我们必须为ε提供一个值,它定义了两点之间的最大距离。下面的文章描述了一种自动确定 Eps 最佳值的方法。
https://IOP science . IOP . org/article/10.1088/1755-1315/31/1/012012/pdf
通俗地说,我们通过计算每个点到最近的 n 点的距离,对结果进行排序和作图,从而为ε找到一个合适的值。然后我们观察变化最明显的地方(想想你的手臂和前臂之间的角度),并选择它作为ε。
我们可以使用NearestNeighbors
来计算每个点到最近邻点的距离。点本身包含在n_neighbors
中。kneighbors
方法返回两个数组,一个包含到最近的n_neighbors
点的距离,另一个包含这些点的索引。
neigh = NearestNeighbors(n_neighbors=2)nbrs = neigh.fit(X)distances, indices = nbrs.kneighbors(X)
接下来,我们对结果进行排序和绘图。
distances = np.sort(distances, axis=0)distances = distances[:,1]plt.plot(distances)
ε的最佳值将在最大曲率点找到。
我们训练我们的模型,选择0.3
为eps
,设置min_samples
为5.
m = DBSCAN(eps=0.3, min_samples=5)m.fit(X)
labels_
属性包含集群列表和它们各自的点。
clusters = m.labels_
然后,我们将每个单独的聚类映射到一种颜色。
colors = ['royalblue', 'maroon', 'forestgreen', 'mediumorchid', 'tan', 'deeppink', 'olive', 'goldenrod', 'lightcyan', 'navy']vectorizer = np.vectorize(lambda x: colors[x % len(colors)])
该模型对人口密集区进行了分类。正如我们所见,所有深蓝色的点都被归类为噪声。
plt.scatter(X[:,0], X[:,1], c=vectorizer(clusters))
最后的想法
与 k-means 不同,DBSCAN 会计算出聚类数。DBSCAN 的工作原理是确定最小数量的点是否彼此足够接近以被视为单个聚类的一部分。DBSCAN 对比例非常敏感,因为ε是两点之间最大距离的固定值。
机器学习速成班
你现在如何在你的问题中使用机器学习?
机器学习是发展最快的技术领域之一。它能够自动化大量当前流程,这些流程是当今工作的一部分。机器学习有两种主要的一般方法:监督和非监督。两者都可以用来解决许多分类或回归问题。
Machine Learning is great for classifying, predicting and analysing data.
例如,假设我们想要预测“黄邦贤在美国吗”。然后你会使用监督学习。在监督学习中,学习者有一个特征数据集,对于每个标签,都有一组训练实例。关键是选择理想的分类器,使其在给定训练示例的情况下学习数据应该预测什么。
示例:生成准确的未来警察追捕历史
想象一个犯罪侦查系统。我们想比较一个高调犯罪和一个类似的低调犯罪在未来的描述与他们的预期结果。这是监督机器学习的一个例子。这里有一篇信息丰富的博客文章,可以了解更多关于 NLP 和机器学习的知识,并查看用于帮助生成未来搜索历史的代码。
当使用无监督的机器学习时,我们没有任何类似标记数据集的东西(还没有)。相反,我们有一个未标记的“源”数据集。为了预测犯罪,我们需要了解一些犯罪的历史原因。我们使用数据挖掘方法来识别与犯罪密切相关的因素。
但是机器学习也包括从未标记的数据中创建数据集的过程。我们应用一些机器学习方法来创建一组未标记的数据点。这些点作为我们分类任务的标签。这个过程叫做训练。
现在我们有了一个未标记的数据集和一组训练示例,我们可以运行分类任务了。此时,分类器不知道预测的标签是什么(它应该将数据点分配给哪个类)。它只是知道如何预测它。但是一些分类器可能需要运行更多的训练样本以便收敛。这叫学习率。
基于决策树的回归
我们可以使用基于分类器的方法,该方法依赖于一些输入特征和我们的输出标签之间的成对链接结构。决策树就是一个例子。该树只包含一个树形目录,该目录是每个所需特征链接的特征(分类标签)。
例如,我们可能希望预测每个感兴趣类别的帖子中的消息长度。但是用户只是想要标题。因此,对于每个类别,树目录可能只有一个条目。每个条目将描述一类消息,每个树条目将给出一些树链接,这些树链接的左轴和右轴的值之和大于我们选择的一个数字。这些值是从一些随机抽样中计算出来的。
这将适用于某些类别标签。然而,通过额外的训练例子,它变得几乎无用。我们最终会有很多错误类别的树条目,这将导致没有一个条目会收敛。
机器学习和视觉
现在,考虑一个世界,我们生活在一个有 WiFi 的城市。为了检测城市环境中的活动和移动,有大量的数据和许多传递这些数据的方式。例如,我们也许可以使用摄像机,而不仅仅是在电视机上发出警告。图像传感器上的每对标记可以指示该邻域中的活动。使用这些特征,系统可以对活动进行分类,并且可以准确地检测活动。要做到这一点,系统必须学习背景上的活动模式,并预测用户的位置。这将需要大量的例子来收敛。
机器学习和训练
对于每个数据点,可以训练机器学习模型,以便该模型能够预测数据点的“未来类别”。训练可以通过反向传播来完成。通常,回归问题还涉及某种对象检测问题。因此,需要结合物体检测和机器学习。
应用基于分类器的机器学习
在某些情况下,模型学习问题过于复杂,无法用有监督的机器学习技术来解决。在其他情况下,人类的机器学习专家必须实现和实施模型。但是,为了训练模型,我们可以使用一些机器学习算法,如梯度提升、支持向量机、AdaBoost、剩余秩学习和某种程度上的随机森林。
结论
机器学习是一个很好的工具,可以对数据进行分类、预测和生成洞察,不管是有标签的还是无标签的。
作为一名机器学习工程师(或数据科学家,这里没有通用的职称标准),你将基于数据解决现实世界的问题。您的数据可能包括图像、音频文件或文本文档。第一步总是清理你的数据,使它更容易使用和实现机器学习算法。接下来是探索数据和思考你可能想要用来成功的算法的时候了。
Data Science Job
最后,如果你想了解成为一名数据科学家意味着什么,那么看看我的书数据科学工作:如何成为一名数据科学家,它将指导你完成这个过程。
如果你想了解更多关于机器学习和数据科学的内容,可以看看我的其他文章:
机器学习、骑自行车和 300W FTP(第一部分)
寻找更好的体育锻炼方法
Credit: Coen Van Den Broek
我不时地骑自行车。我说的是公路自行车。我不是职业选手,我也不想成为——但是我喜欢竞争,我喜欢比赛,我喜欢挑战。
原来骑自行车是一项与数据纠缠不清的运动。从功率计到心率监测器,追踪这项运动变得很容易。
A Wattbike Trainer
使用我自己的 106 次 Wattbike(室内教练)旋转训练的数据集,这一系列文章的目的是了解我的表现的重要特征。我希望能够利用这些信息来实现我的目标:300 瓦的 FTP。
我会尽可能多的把工作喂给 野兽 (ML)。
所有代码都在 GitHub 上。
F警察?!*
不,不完全是。功能阈值功率(FTP) 代表骑手可以维持一小时的功率,以瓦特为单位,通常计算为 20 分钟全力测试平均功率的 95%。
基于 20 分钟会话的计算似乎是任意的,但这是为了易于复制和方便起见。 FTP 与大多数骑自行车的人相关,是评估你短期和长期努力的基础。
如果你想了解更多,请点击这里查看 BikeRadar 的文章。
从 255 瓦开始
Figure 1: Session Average Distribution of Power over a Revolution
截至 2019 年 8 月 20 日,我记录了一个 255 瓦的 FTP,重 87 公斤。也就是说,我在 Wattbike 上 20 分钟内平均输出 268 瓦(其中 95%是我的 FTP 读数)。鉴于我的体重,我猜这可能是平均水平。
我以为这是关于权力的,你为什么要谈论花生?
你可能想知道如何推动踏板转化为权力。在任何物理系统中,功率都表示为力和速度的乘积。在自行车运动中,这个等式告诉我们:
力量=蹬力 x 腿速
步频,以每分钟转数(rpm)衡量,代表腿部速度,对于单次 360 度腿部旋转,上面的花生状极坐标图显示了在会话中每次旋转平均的每个角度的切向力。
Zwatt 团队和 Wattbike 团队都有关于主题这里和这里的作品(分别)。
好吧,那有什么变化呢?
Figure 2: Polar plots for 4 different 20 Minute Tests
每条线代表完成的 20 分钟最大努力测试,首先在 2017 年,然后在 2019 年再进行三次测试。虽然极坐标图确实显示了变化,但现在,我对 FTP 的变化感兴趣。
1)+2W2017 年 11 月 9 日至 2019 年 3 月 25 日改进。
2)+16W2019 年 3 月 25 日至 2019 年 5 月 28 日改进。
3)+7W2019 . 5 . 28-2019 . 8 . 20 改善。
2019 年 3 月至 8 月是行动的开始。
反思期,没有一个训练目标。然而,我确实试图坚持训练,并且每次都或多或少地使用预定义的 Wattbike 应用程序会话。该应用程序跟踪一系列变量,包括训练过程中的距离、节奏和力量。数据集说明了什么?
2019,低强度训练年
Figure 3: Distribution of Time Spent in Bucketed Power Zones
嗯,今年我确实找到了更多的时间去骑车。
根据图 3 中的分布图,相对于其他类别,我已经在100–150 w类别中花费了更多的时间。尽管骑自行车的时间更多,但与 2018 年相比,今年到目前为止,我花在测试我的功率极限( 300W+ 类别)上的时间更少。我没想到会这样。
Figure 4: Proportion of Ride Duration in each Power Zone.
添加一个日期维度,只观察今年记录的时段,上面的堆积条形图显示了每个动力区类别花费的每次乘坐时间比例。红色大竖条与之前在花生地里进行的 20 分钟 FTP 测试相吻合。
+16W vs+7W——我做了哪些不同的事情?
通过 3 个 FTP 测试分离情节,我们剩下两个时期,创造性地,我将它们称为时期 1 和时期 2 。
第一阶段:9 周内 19 次会议(3 月 25 日-5 月 28 日)。
第二阶段:12 周内 20 次会议(5 月 28 日—8 月 20 日)。
该图说明了在周期 1 中的会话的特点是花费在200-250 w和100-150 w区域中的时间比例较大,并且几乎没有时间测试我的功率极限的上限。
换句话说,黄色的多,深红色的 少。
Figure 5: Absolute Ride Duration split by Power Zone.
在绝对时间而不是相对时间中绘制图 4 揭示了更多好东西。看看上面,有什么让你印象深刻的?
a) 更长的乘坐持续时间在周期 1 中展现。****
b)在周期 1** 中,计时超过 200 w15 分钟的更多会话**。****
c)在100-150 w区域内,大多数周期 1** 时段计时 25 分钟以上。**
持续时间、工作量&节奏
Figure 6: Max Power, Average Power, Session Duration, Workload, Power Standard Dev & Cadence Scatterplots (top left to bottom right, period 1 = blue, period 2 = orange).
在图 6 中,我们绘制了周期之间的六个进一步的指标(周期 1 =蓝色,周期 2 =橙色),并揭示了以下内容:
1)
2) 平均功率 —没有明显差异,但是在周期 2 会话中可能维持稍高的平均功率。
3) 会话持续时间 — 获胜者 —在周期 1 中会话长度的变化更大,更短和更长的会话都是如此。
4) 工作量 — 赢家 —第 1 期利用了更多的工作量变化。我将工作负载定义为平均功率乘以会话持续时间,代表会话的总强度。
5) 功率标准差 —这是为了区分持续努力(低标准 dev)和间歇会话(高标准 dev)。两个时期都显示混合会议。嗯,没有明显的区别。
6) 节奏 — 优胜者 —第一期以更大范围的节奏训练。
对 Wattbike 课程的一些探索性数据分析已经突出显示了(获胜者)一些有趣的途径,可以探索有关训练强度、节奏和持续时间的内容。
要达到 300 瓦的 FTP,我至少要接受多少专业训练?
我们还没喂 野兽 (do ML) 但是回到目标,还是有那么多要回答的。
什么时候训练时间变得无关紧要了?我的饮食是什么样的?睡眠模式如何影响训练?精神状态和压力起什么作用?
还有很多生活方式的因素在起作用——我认识到,我仅凭权力得出的结论是不确定的。
接下来呢?
在把数据扔给 ML 之前,我想深入挖掘一下我的心率和睡眠数据集。如果我能够将这些数据集以菊花链的方式连接在一起,并与我已经拥有的电力数据保持一致,那就更好了。
我不知道他们会透露什么,但我迫不及待地想知道——我将在第 2 部分记录我的发现。请随意提出任何建议或您自己的结果。
问题不在于我训练了多少时间,而在于我在这段时间里做了什么。
这部作品的驱动者是 个性化 。
我们每个人对身体压力的反应不同,需要不同的恢复程度,有自己的伤害,活动水平,饮食和生活方式——所以我们真的应该期待关注甚至不了解我们的网站会有好的结果吗?
个性化结果怎么样?
研究对于分享知识来说是很棒的,但是我不想要一个 100 人的样本的结果,他们不是我的年龄,不是我的种族,不分享我的生活方式,也没有我的伤害。
最初纯粹是一个物理目标,现在变成了一个练习,学习是什么让一个人成功,了解优势和针对弱点。在此过程中利用尽可能多的数据。
更重要的是,这个原理是运动不可知的。对我来说是骑自行车,但对你来说可能是抱石,对他来说可能是减肥,对她来说可能是橄榄球。
欢迎来到自我意识的时代。
导出并可视化代码: github
机器学习数据集
为数据科学项目寻找第一批数据的最佳资源
简介
你读过几篇关于数据分析的文章,然后你跟随了几个教程,看着人们应用基本的机器学习算法。现在您已经准备好自己尝试一些这种技术,但是您从哪里开始呢?您的笔记本电脑上没有数百万行数据等待分析。
在本文中,将向您介绍五种不同的数据源,您可以通过搜索来找到最适合数据科学项目的第一个数据集。
卡格尔
下载数千个项目的开放数据集+在一个平台上共享项目。探索热门话题,如政府…
www.kaggle.com](https://www.kaggle.com/)
Kaggle 可能是最受欢迎的资源,鼓舞人心的或现有的数据科学家可以在这里找到边项目的数据集。目前,这个网站上有近 25000 个公开的数据集,它们涵盖了各种各样的主题。您可以使用关键字搜索数据集,如果其他数据科学家决定通过创建一个公开可用的内核来共享他们的工作,则可以查看他们在数据集上的工作。
此外,该网站举办机器学习竞赛,以防你想与全球其他数据科学家竞争奖项,一旦你学到足够的知识,你还可以搜索他们的工作板以找到与数据科学相关的工作。
驱动数据
DrivenData 致力于数据科学和社会影响交叉领域的项目,如国际…
www.drivendata.org](https://www.drivendata.org/)
DrivenData 是一个类似 Kaggle competition 的网站,因为数据集是以有奖竞赛的形式发布的。他们没有这么大的数据库,但他们的主题是对世界和社会产生影响。因此,许多人发现他们的数据集鼓舞人心,绝对值得研究。
UCI 机器学习知识库
UCI 机器学习知识库 目前已经有近 500 个数据集可供你下载并开始使用。搜索他们的数据集是绝对值得的,因为他们大多是干净的,组织良好的。
美国政府数据
美国海岸警卫队保存着历史船只位置变动的档案,通过全国范围的…
www.data.gov](https://www.data.gov/)
美国 Gov 数据 是另一个拥有大量数据集的地方。你现在可以浏览超过 25 万个不同的政府数据集。分为农业,气候,消费者,生态系统,教育,能源,金融,卫生,地方政府,制造业,海事,海洋
结论
我已经介绍了我最喜欢的寻找机器学习和数据科学数据集的资源。现在是你的时间了,所以在你的 jupyter 笔记本上浏览、下载和加载数据吧。
原发表于 aboutdatablog.com: 机器学习数据集,2019 年 11 月 11 日。
PS:我正在 Medium 和上撰写深入浅出地解释基本数据科学概念的文章。你可以订阅我的* 邮件列表 *每次我写新文章都会收到通知。如果你还不是中等会员,你可以在这里加入。**
下面还有一些你可能喜欢的帖子
** [## python 中的 lambda 函数是什么,为什么你现在就应该开始使用它们
初学者在 python 和 pandas 中开始使用 lambda 函数的快速指南。
towardsdatascience.com](/what-are-lambda-functions-in-python-and-why-you-should-start-using-them-right-now-75ab85655dc6) [## Jupyter 笔记本自动完成
数据科学家的最佳生产力工具,如果您还没有使用它,您应该使用它…
towardsdatascience.com](/jupyter-notebook-autocompletion-f291008c66c) [## 当你开始与图书馆合作时,7 个实用的熊猫提示
解释一些乍一看不那么明显的东西…
towardsdatascience.com](/7-practical-pandas-tips-when-you-start-working-with-the-library-e4a9205eb443)**
机器学习——诊断车队跟踪器的故障
本文提出了一种数据驱动的解决方案来诊断车队跟踪模块的故障。
Figure 1: https://www.shortlandinsurance.com/module_resources/page_management/36/Fotolia_37500680_L.jpg
介绍
许多运输和物流公司使用模块来跟踪他们的车辆,一些模块不能按预期工作并不罕见。例如,可能需要丢弃追踪器,可能会收集到车辆的错误数据,或者可能会将技术支持人员派到很远的地方去分析问题。因此,有必要对这些模块进行远程故障诊断,因为当它们出现故障时,可能会造成经济损失。
由于这些模块不断地向数据库发送数据,本研究的目的是使用这些数据来诊断模块上的故障。有必要开发一种方法来预处理由车辆模块发送的收集数据。在此之后,机器学习技术被应用于创建模型,模型被分析和比较。但是,错在哪里呢?
故障是系统的至少一个属性或特征参数的不允许的偏差[1]。诊断故障有三个步骤,即:
- 故障检测:是故障诊断最基本的任务,用于检查系统中的故障或失效,并确定故障发生的时间;
- 故障隔离:隔离的作用是检测故障的位置或者是哪个部件有缺陷;
- 故障标识:该标识用于确定故障的类型、形式和大小。
通常,故障识别过程只包括故障检测和隔离(FDI)。这并没有否定故障识别的效用。然而,如果不涉及重新配置动作,这个过程可能不是必需的[2]。
发展
首先,要执行任何机器学习解决方案,都需要数据。在本案例研究中,一家巴西物流公司提供了许多追踪器发送的一些数据,因此所有使用的数据都是真实的。
问题描述
安装在车辆中的模块在整个运行期间发送数据。该公司提供了 12586 个注册表。该公司提供了 12586 个注册表。注册表由一个模块在一天内传输的所有数据组成。平均每个模块每天发 1116.67 分。每个点有八个属性:
- 电池电压:车载电池电压的浮动值;
- 经度:车辆经度的浮点值;
- 纬度:车辆纬度的浮点值;
- 点火:表示点火
是否打开的布尔值; - 里程表:车辆里程表的浮点值;
- GPS 信号:表示 GPS 信号
是否有效的布尔值; - 速度:车速的浮点值;
- 内存索引:模块中
点保存的内存位置的整数值。
因为模块根据每个模块以不同的频率定期发送数据,所以每个注册表具有不同的大小。这样,每个注册表的大小就是发送的点数乘以 8(属性的数量)。
目的是识别注册中心可能存在的错误或其是否正常工作。这样,这是一个多类分类问题,这里有八类;一类为无故障的注册表,七种可能的故障,如下所列:
- 故障 1 :脉冲设置错误;
- 故障二:里程表锁定;
- 故障三 : GPS 锁定;
- 故障 4 :点火线释放;
- 故障 5 :加速计故障;
- 故障 6 :模块缓冲有问题;
- 故障 7 : GPS 出现位置跳变;
这些故障中的一些有几次出现得太低。不足 3%的瑕疵都被贴上了“其他”的标签。每个故障的数据量可以在左边看到。
数据预处理
因为特征提取过程是一项大规模的工作,会显著影响最终结果[3]。这种方法使用来自系统的知识来执行数据转换,以显著降低数据维度。
初始属性是时间序列(电池电压、纬度等。),从它们中,我创建了 21 个新属性,如下表所示。此后,数据转换将原始数据从二维转换为一维。这些新属性中的大多数都可以很容易地计算出来,因此没有复杂的公式或算法。
New Attributes description table.
大多数属性都是二进制的,所以不需要规范化。然而,诸如点数、关于电池电压的数据和存储器索引中的跳跃之类的属性可以被标准化。由于没有对异常值进行分析,传统的归一化会导致数据被一些高值所抑制,因此使用 RobustScaler。此缩放器使用第一个和第三个四分位数作为约束,而不是最大值和最小值,因此这种归一化更健壮,并保留了异常值。
由于某些属性可能与其他属性高度相关,因此计算了所有可能的相关性。经度和纬度变化具有 0.996315 的皮尔逊相关性,这在大多数 ML 项目中建议我们应该丢弃这些属性中的一个。然而,由于模型的目标是诊断模块的 GPS 中的故障,尽管相关性很高,但这两个属性都是有用的。
而且,点数和 GPS 无效的点数有很高的相关性,0.962769。这是因为点数是有效 GPS 点数与无效 GPS 点数之和。因此,由于这种线性组合,属性“点数”被丢弃。最后,日期和序列字段也被丢弃,因为它们用于识别车辆和模块,并且不提供关于模块操作的任何信息。
训练 ML 模型
为了运行算法,数据集被分成训练集和测试集。对于每个实验,20%的注册表用于测试,80%用于训练。
我想找出哪种传统算法更适合这种数据,所以我测试了过采样和欠采样的每种算法。
考虑到最大似然技术,所有的随机森林都使用 100 个估计器,所有的最大似然都使用架构(5,10,5),lr = 0:001 和 200 次最大迭代。
获得的指标可以在下表中看到:
通过过采样,随机森林的归一化混淆矩阵如下所示:
除了最大似然技术的评价指标,还计算了模型的训练和评价时间。在最坏的情况下,这个时间是 0.37 ms ,在这个案例研究中,这个时间可以被认为是应用程序
的实时响应。
结论
正如所提出的,这些模型可以检测和识别具有高性能指标的车队跟踪模块上的故障。然而,有广泛的功能工程,可以由 LSTM 或 CNN 自动执行。我也,做了一些 CNN 的模型来做这个故障诊断,也许我会在下一篇文章中详细介绍。
所采用的方法的局限性包括模型不能发现未被映射的故障,因此任何未被学习的故障将被错误地分类为已知故障之一。
和文章中一样,这里没有任何代码,你可以在我的 GitHub 库中随意查看。
故障诊断模型检测和识别车队跟踪模块上的故障。…
github.com](https://github.com/lmeazzini/Tracker-fault-diagnosis)
参考
[1] D. van Schrick,“关于
监督、故障检测和诊断领域术语的说明”,IFAC 会议录
卷,第 30 卷,第 18 期,第 959-964 页,1997 年。
[2] D. Wang 和 W. T. Peter,“基于移动平均磨损退化指数
和一般
顺序蒙特卡罗方法的泥浆泵预测”,机械系统和
信号处理,第 56 卷,第 213–229 页,2015 年。
[3] L. Wen,X. Li,L. Gao,Y. Zhang,“一种新的基于卷积
神经网络的数据驱动故障诊断方法”,
IEEE Transactions on Industrial Electronics,vol. 65,no. 7,
PP . 5990–5998,2018,
机器学习——用 CNN 诊断车辆追踪器故障
Photo by Omer Rana on Unsplash
初步考虑
几周前,我发表了另一篇标题几乎相同的文章:
一种数据驱动的跟踪模块故障诊断方案。
towardsdatascience.com](/machine-learning-diagnosing-faults-on-vehicle-fleet-trackers-56b123d77cf5)
在这个故事中,我使用了跟踪模块操作的一些特定知识来手动提取特征;现在,在这个故事中,我的目标是在没有任何特征提取的情况下,在同一个数据集上诊断故障。对于没有阅读第一篇文章的人来说,介绍和问题描述将是相同的。然而,所有的发展都不会。
介绍
许多运输和物流公司使用模块来跟踪他们的车辆,一些模块不能按预期工作并不罕见。例如,可能需要丢弃追踪器,可能会收集到车辆的错误数据,或者可能会将技术支持人员派到很远的地方去分析问题。因此,有必要对这些模块进行远程故障诊断,因为当它们出现故障时,可能会造成经济损失。
由于这些模块不断地向数据库发送数据,本研究的目的是使用这些数据来诊断模块上的故障。有必要开发一种方法来预处理由车辆模块发送的收集数据。在此之后,机器学习技术被应用于创建模型,模型被分析和比较。但是,错在哪里呢?
故障是系统的至少一个属性或特定参数的不允许的偏差[1]。此外,诊断故障有三个步骤,即:
- 故障检测:是故障诊断最基本的任务,用于检查系统中的故障或失效,并确定故障发生的时间;
- 故障隔离:隔离的作用是检测故障的位置或者哪个是有缺陷的部件;
- 故障标识:该标识用于确定故障的类型、形式和大小。
通常,故障识别过程只包括故障检测和隔离(FDI)。这并没有否定故障识别的效用。然而,如果不涉及重新配置动作,这个过程可能不是必需的[2]。
问题描述
首先,要执行任何机器学习解决方案,都需要数据。在本案例研究中,一家巴西物流公司提供了许多追踪器发送的一些数据,因此所有使用的数据都是真实的。
安装在车辆中的模块在整个运行期间发送数据。该公司提供了 12586 个注册表。该公司提供了 12586 个注册表。注册表由一个模块在一天内传输的所有数据组成。平均每个模块每天发 1116.67 分。每个点有八个属性:
- 电池电压:车载电池电压的浮动值;
- 经度:车辆经度的浮点值;
- 纬度:车辆纬度的浮点值;
- 点火:表示点火
是否开启的布尔值; - 里程表:车辆里程表的浮点值;
- GPS 信号:表示 GPS 信号
是否有效的布尔值; - 速度:车速的浮点值;
- 内存索引:模块中
点保存的内存位置的整数值。
因为模块根据每个模块以不同的频率定期发送数据,所以每个注册表具有不同的大小。这样,每个注册表的大小就是发送的点数乘以 8(属性的数量)。
目的是识别注册中心可能存在的错误或其是否正常工作。这样,这是一个多类分类问题,这里有八类;一类为无故障的注册表,七种可能的故障,如下所列:
- 故障 1 :脉冲设置错误;
- 故障二:里程表锁定;
- 故障三 : GPS 锁定;
- 故障 4 :点火线释放;
- 故障 5 :加速计故障;
- 故障 6 :模块缓冲器有问题;
- 故障 7 : GPS 出现位置跳变;
这些故障中的一些有几次出现得太低。不足 3%的瑕疵都被贴上了“其他”的标签。每次故障的数据量见下表。
发展
我的目标是检测和隔离故障;然而,虽然仅仅检测故障是一个二元问题,但是检测和隔离是一个多类问题。检测故障可能容易得多。从公司方面来看,几乎总是,当一个模块出现故障时,他们需要更换它。所以不管是什么故障,我们都需要更换模块。
我们在这里提出模型,一个用于检测故障,另一个用于检测和隔离故障。
数据预处理
由于我们的目标是在不使用任何关于系统操作的特定知识的情况下对数据集进行微小的更改,因此数据预处理相当简单。
我们选择保留所有数据,不执行任何异常值分析。大多数离群值强烈表明存在错误,如果我们丢弃所有离群值,许多有问题的注册中心将会消失。这样,我们唯一要做的就是使用鲁棒定标器进行归一化。传统的归一化会导致数据被某个高值抑制,因此使用 RobustScaler。此缩放器使用第一个和第三个四分位数作为约束,而不是最大值和最小值,因此这种归一化更健壮,并保留了异常值。
考虑到注册表具有可变长度,不可能用该数据集直接构建 ML 模型。这样,有必要为所有重试设置一个默认大小。已知注册表中存在的最大点数是 6410,点数的平均值是 1116.67,标准偏差是 1155.75,具有较小数据量的注册表以“0”完成,直到它们具有与最大注册表相同的数据量。
可以执行不同的方法来设置注册表的默认大小,例如从高于平均值的注册表中截断数据量,并且用“0”来填充低于平均值的注册表,或者从比较小的注册表具有更多数据的所有注册表中截断数据量。然而,由于 CNN 的分歧,这些方法被测试并被认为是不可行的。
CNN 架构
我根据 VGG 16 号做了一个模型。
使用 4 个卷积块。每个像 Conv->Conv->统筹。然后是两个完全连接的层。
卷积的思想是让过滤器选择和修改属性。为此,我们使用(8,6410,1)形状来处理每个注册表。这样,CNN 就像威胁图像一样威胁数据。要更深入地检查架构,请检查我的 GitHub(链接在介绍和结论中)。
使用的批量大小为 1,学习率为 0.0001,he_uniform 初始化器。batch_size 可以更大。然而,由于硬件限制,三个对我来说更高。
模特培训
训练两个模型,一个用于故障检测,另一个用于故障检测和隔离。因此,定义了同一数据集的两种结构。这些结构描述如下:
- 结构 1 :用于实验检测系统是否有故障。它包含 12586 条记录,其中 7480 条有缺陷,5106 条无缺陷;
- 结构 2 :在实验中用于检测和隔离故障。它包含 5106 条无缺陷记录、2170 条失败 2 记录、1573 条失败 3 记录、1702 条失败 4 记录和 2035 条“其他”失败记录,总共 12586 条记录。
所有模型都是用 Python 3.6 和 Sk-learn 0.20.2 编写的,在 Ubuntu 18.04 上运行,采用英特尔 i7–7700 HQ、16Gb 内存、GTX 1050Ti。
为了运行算法,数据集被分成训练集和测试集。对于每个实验,20%的注册表用于测试,80%用于训练。
模型评估
度量标准需要充分的解释。在所讨论的案例研究中,最大限度地减少误报的数量至关重要,因为这将涉及派遣技术人员执行不必要的维护。而假阳性意味着接收到对某个故障模块的投诉。那么,从财务角度来看,召回的相关性大于精确度。
对于 88.42 的精度和 87.96 的召回,故障检测的混淆矩阵可以如下所示:
对于 54.98 的精度和 52.57 的召回,用于故障检测和隔离的混淆矩阵可以如下所示:
对于这两个模型,都存在高方差和高偏差。如果架构更深入或者改变一些超参数,模型会有更好的结果。或者,甚至执行更广泛的数据预处理。
结论
正如所提出的,这些模型可以检测和隔离车队跟踪模块上的故障。然而,评价性指标不适合使用模型。在我的另一篇文章中,使用来自系统的知识,可以在公司实现更高的指标来远程诊断他们模块上的故障。
所采用的方法的局限性包括模型不能发现未被映射的故障,因此任何未被学习的故障将被错误地分类为已知故障之一。
和文章中一样,这里没有任何代码,你可以在我的 GitHub 库中随意查看。
故障诊断模型检测和隔离车队跟踪模块上的故障。…
github.com](https://github.com/lmeazzini/Tracker-fault-diagnosis)
参考
[1] D. van Schrick,“对
监督、故障检测和诊断领域术语的评论”,IFAC 会议录
卷,第 30 卷,第 18 期,第 959-964 页,1997 年。
[2] D. Wang 和 W. T. Peter,“基于移动平均磨损退化指数和一般
序贯蒙特卡罗方法的
泥浆泵预测”,机械系统和
信号处理,第 56 卷,第 213–229 页,2015 年。
机器学习——不要仅仅依赖你的大学
正式课程和网络课程之间的巨大差异
Photo by Andrew Neel on Unsplash
在大学学习的问题是
将机器学习整合到预测分析中一直是高需求的,这为企业提供了竞争优势。这个热门话题受到了全世界大学生的高度关注。然而,在大学中正式介绍机器学习的概念和技术可能会证明对普通本科生来说极其令人生畏。
在麦吉尔大学的本科冬季交流期间,我报名参加了他们的 应用机器学习 课程。是的,我报名参加研究生水平的课程是愚蠢的!它始于线性回归的引入,因为它是最基本的机器学习算法。导师做了很好的工作,试图解释算法背后的直觉。
但在介绍了算法背后的大量数学之后,最后一击是“哦,顺便说一下,作业 1 已经完成了,10 天后到期,鼓励你用 Python 来完成它,下节课见。”
我怎么可能在 10 天内学会 L2 正则化和用随机梯度下降拟合回归模型的概念!我甚至不知道如何用 Python 编码!
我已经被第二次演讲淹没了,我立即退出。在那门课程中,需要扎实的统计学、微积分、线性代数和编程背景知识。果然,在第一次介绍性讲座中,这四个要素立即被引入。
我是许多学生中的一员,通过寒暑假学习并忘记了大部分的数学概念,这一点也没有帮助。
在线课程的发现
我不允许一点小挫折摧毁我对数据科学的兴趣,我开始在网上搜索对“足够感兴趣”的公众足够友好的教授机器学习的资源。有很多很棒的在线课程,有些是免费的,有些是付费的,有些是正式认证的。我选择付费课程是因为我从提供付费课程的老师那里找到了真正的激情。
我报名参加的在线课程是基里尔·叶列缅科的 机器学习 A-Z:数据科学中的动手 Python&R。
Kirill 在课程中介绍的所有算法中提供了易于理解的直觉,即使是高中生也能理解,这方面做得非常出色。所有介绍的算法都辅以实际操作的编码会话,使用接近真实生活的数据,帮助我可视化并理解其意义。
受到激励,我重新注册了我家乡大学的另一门机器学习课程,并发现随着我直觉基础的建立,这门课程变得容易多了。
在接下来的部分中,我想提供一些我在大学里所学和所学之间的对比。我希望这篇文章能够激励那些正在考虑将他们的学习延伸到大学之外的人,或者在机器学习领域寻求进一步知识的工作专业人员。
免责声明:以下比较仅限于 2 个来源提供的学习资料:我的大学和 Kirill 的机器学习课程。从今以后,我为下面这篇文章中的偏颇观点道歉,这不应该被视为所有正式学习和在线学习中的普遍现象。
那么有什么不同呢?
为了说明正式学习和在线课程之间的区别,让我们看看几个常见的机器学习概念,并看看它在我的大学中是如何解释的,与 Kirill 的课程是如何处理的。以下列表是我在大学时发现很难理解的东西的快照,但在我观看 Kirill 的视频时完全被揭穿了。
线性回归
这就是我的大学试图在他们的演讲幻灯片中解释线性回归的方式:
Throwing in mathematical notations as a general introduction to linear regression makes it difficult to understand (Credits: Pun Chi Seng Patrick)
对有经验的人来说,这是小事一桩。但是对于任何一个刚刚开始学习统计学和微积分的人来说,消化这些信息需要相当长的时间,尤其是在缺乏好的视觉效果的情况下。
另一方面,在线课程通过一步一步的动画解释直接切入业务问题:
Explaining the relationship of working experience and salary makes the intuitive understanding of simple linear regression so much easier (Credits: Kirill Eremenko)
一个简单的 3 分钟视频解释了普通最小二乘法背后的直觉,足以让任何人明白它的意义。
使用 R 平方统计评估线性回归模型
R 平方统计,也称为拟合优度,广泛用于评估线性回归模型。下面红色的句子完美地总结了 R 平方统计的使用:
Explaining the use of R-squared statistics to evaluate generalized linear regression models ((Credits: Pun Chi Seng Patrick)
然而,我发现从 Kirill 的课程中呈现的视觉效果来理解要容易得多:
A visual representation of R-squared statistics presented by Kirill (Credits: Kirill Eremenko)
通俗地说,R 平方统计就是将最佳拟合线与“最差拟合线”进行比较,后者是数据的恒定平均值。残差平方和越低,R 平方值越高。调整后的 R 平方增加了与模型无关的额外预测因子的惩罚,适用于多元线性回归模型。
支持向量最大间隔分类器
在我大学的机器学习课程中,理解支持向量机的概念显然是最难的任务。沉重的数学的轰炸,让我们似乎不可能耐着性子一口气理解概念。请看下面关于最大间隔分类器的摘录信息:
The heavy math behind the computation of a maximal margin classifier (Credits: Pun Chi Seng Patrick)
现在,相比之下,我们看到了基里尔的一个简单插图是如何抓住最大间隔分类器的直觉的妙处:
Credits: Kirill Eremenko
好吧,你明白了,我还可以做很多比较,但是我会让你不无聊的!到现在为止,你可能认为你从网上学习中会比在大学里接受正规教育受益更多。但就个人而言,我觉得完成大学的机器学习课程比仅仅完成 Kirill 的课程更有就业价值。
但是正规学习也没那么差吧?
没有最终项目,机器学习课程是不完整的。Kirill 的课程用 Python 和 R 语言提供了易于理解的直觉和示例代码,供学习和遵循。完成他的教程让我很满意,我可以用一系列机器学习算法进行预测。
但这还不够。
期末专题评分的重要性
正式学习和网上学习的区别在于一个分等级的期末项目。我们的任务是从公开可用的数据集设计一个机器学习问题。下面的流程图强调了处理与真实世界应用非常相似的良好机器学习项目的过程:
我们在公共数据集建模方面的实践经验得到了来自教授和助教的项目咨询和支持的补充,以个性化的方式丰富了我们的学习。在项目期间,我很高兴我有一个来自 Kirill 课程的机器学习脚本集,可以用于数据预处理和建模。
习惯重数学的重要性
从统计推断到超参数调优,高性能模型的神奇之处在于对背后复杂数学的深刻理解。
诸如:“我的 ANN 模型的最佳学习速率和权重衰减是多少?”以及“一个好的随机森林回归模型在不过度拟合的情况下所需的最优树数是多少?“只有具备足够的数学知识才能回答。
简单地
The demand of data scientist to provide business and product intelligence is on the rise (Source: PredictiveAnalyticsWorld)
无论是建立推荐系统,还是在人工智能产品和服务中实现计算机视觉,机器学习算法的实施都在不断增加。有利可图的人工智能行业激起了大学的兴趣,提供数据科学专业学位的大学开始涌现。以我大学的 最近提供的数据科学学位 为例。
随着人们越来越意识到它的需求,他们开始冒险进入未知领域。没有意识到数学和计算机科学完美融合背后的技术细节,普通大学生很自然地会在这门课程中苦苦挣扎。
机器学习技术应用的简单性可以被许多可用的在线课程所揭穿。不幸的是,严酷的事实是,几乎没有雇主在乎你是否有一个勉强被认可的在线课程认证。你的正式资格永远是人力资源主管优先考虑的。尤其是如果人力资源主管没有技术倾向的话。
另一个严峻的事实是,大多数数据科学职位要求高等教育才能被考虑。对许多人来说,完成一门涉及机器学习的本科课程已经被证明是一个挑战。但是我希望这篇文章可以激励读者减少对正规教育的依赖,并知道有大量非常有用的资源可以补充你在数据科学和机器学习方面的学习。
如果你有兴趣了解如何成为一名优秀的数据分析师,我认为大学需要更加重视这一点,你可以看看我在这里写的另一篇文章:
从数据收集、预处理、转换到非技术交流,这些都是非常重要的…
towardsdatascience.com](/4-important-things-universities-need-to-teach-about-data-science-analytics-6ab5988639ca)
感谢您的时间,我希望这篇文章在某种程度上让读者受益,如果您有任何问题,请随时联系我!
机器学习工程师、数据科学家以及他们各自的角色。
在过去的十年里,诸如“数据科学”、“大数据”、“数据湖”、“机器学习”、“人工智能”等术语已经上升到日常词汇的最前沿(有时又回落),用于最广泛的各种行业。然而,不管它们的广泛使用(或者正因为如此!)对于其中许多术语的含义,似乎没有什么共识。我不希望在一致的术语上进行长时间的争论,但是有两个经常使用的术语让我特别感兴趣:“数据科学家”和“机器学习工程师”。
在最广泛的意义上,这两个术语都可以理解为指“构建机器学习解决方案的技术熟练的人”。“数据科学家”是一个术语,多年来,它已经成为一种多面手数学家或统计学家,他们也可以编写一些代码,并知道如何解释和可视化数据。最近,“机器学习工程师”这个术语已经和软件开发人员联系在一起了,他们已经学会了一些数学。
虽然这些解释确实有些道理,但我觉得它们都不是特别有用。因此,冒着增加困惑的风险,我想通过两个勇敢的冒险故事来说明我对这些角色的理解——一个是科学家,另一个是工程师——他们前往一个未知的、可能是无尽的沙漠,寻找石油…
根据他们的任务,工程师和科学家有不同的装备。
这位科学家轻装旅行。他有一个背包、一个指南针、一把铲子和一些简单但精确的测量设备。他对沙漠进行了几次突袭,虽然不是很深入,但是足够深入到可以评估哪个方向看起来最有希望。在进行测量并用铁锹挖了几个洞后的几天内,他想到了可能有石油的地方。
另一方面,工程师带着笨重而精密的机器。目前,他并不关心哪里能找到石油。然而,一旦找到了,他将不得不运输它,所以他花了几天时间设计管道的蓝图。
合作让两个探索者结合他们的优势,变得更有效率。
几天后,探险者们进行了商议,科学家宣布他将在接下来的几天里进行更深入的探索,因为他现在更加确定在哪里可以找到石油。当科学家出发时,工程师启动他的机器,跟随科学家的脚步,开始建造第一段管道。最终他追上了科学家,他发现了一口小井!
他们一起在该位置安装了一个钻机,并将其与管道连接起来。这条管道使科学家的工作更加高效,尽管他们还没有找到真正的主井,但这口小井已经可以带来一些利润,工程师可以用它来测试他的管道。
经过几个月的顺利合作,两位探索者都准备好了第一次重大突破。
为了准备下一阶段的探险,工程师建造了一个轻型石油钻机,并指导科学家如何使用。有了这种专门的钻头,科学家现在可以在没有工程师在场的情况下开井了。有一段时间,科学家继续寻找新井,而工程师继续将它们连接到管道上。
接下来,工程师现在还设计了轻型管道,科学家可以在没有工程师帮助的情况下将其连接到管道上。这使得科学家大大加快了他的探索速度,同时也让工程师有时间重新设计管道的大部件,从而使管道更加稳定和高效,
同样,科学家为工程师设计了一套新的标准化测量方法,并将其嵌入到主轮毂的测量协议中,这样科学家就不再需要前往钻井现场监控其性能。
经过几个月的艰苦工作,他们到达了寻找的大油井。他们一起将油井连接到管道上,并安装复杂的测量设备。到现在为止,例行公事已经很好地解决了。测量,钻孔,连接,泵送,测量。完成了。很快,大油井开始喷涌。
过了一段时间,他们分道扬镳——工程师留在现场,而科学家在场外为项目做贡献。
不久之后,科学家打包回家。现场不再需要他,但他仍然可以分析油井产生的测量结果。
工程师多呆一会儿。他对整个系统运行良好还不满意。一组操作员来了,他们一起解决了所有剩余的问题。然后,工程师将系统交给操作员,然后回家,并承诺如果出现问题会回来。
科学家和工程师的重聚。
我们的两个探险者很快又见面了。他们回忆起他们小小的沙漠冒险,并开始为他们的下一次冒险制定计划——显然,北极可能有石油,他们准备去发现!
数据科学家和机器学习工程师的角色不同。
也许你能够从上面的故事中认识到成功的机器学习项目的一些要素。
我选择了两个探险家的这个小寓言,因为我相信机器学习——尽管它在过去的五到十年里取得了巨大的进步——仍然是一个很大程度上需要探索未知领域的领域。我相信探索精神(快速原型)和五年前一样重要,但是在项目开始时就开始为生产系统(快速扩展)打基础也变得越来越重要。
对于我的两个探索者,我选择了一名(数据)科学家和一名(机器学习)工程师来说明他们合作实现快速有效的价值交付的重要性。
毫无疑问,这两个角色有许多不同的定义,但对我来说,关键的定义特征是,数据科学家会问:“解决这个问题的最佳算法是什么?”并试图通过快速测试各种假设(寻找油井)来回答这个问题。另一方面,机器学习工程师会问:“帮助我们解决问题的最佳系统是什么?”并试图通过构建一个自动化的过程(构建一条输油管道)来回答这个问题,这个过程可以用来加速假设的测试。
尽管数据科学家和机器学习工程师的角色不同,但他们的合作对机器学习项目至关重要。
无论这两个定义是否 100%准确,重要的是当两个有才华的专业人士以这种心态走到一起时,随之而来的合作。在我的例子中,数据科学家寻找新的模型架构来尝试;衡量业绩的新方法;要包括的新数据源等。,而机器学习工程师则在寻找将数据科学家的工作整合到可扩展系统中的方法。随着系统的扩展,数据科学家变得更加高效,因为他有更好的工具可以使用。机器学习工程师变得更加有效,因为他构建的工具被用来交付越来越多有价值的结果。
机器学习工程师写软件,数据科学家写脚本。
这两种职业之间的差异也可以从他们写的代码中看出。当然,两个演员都得是优秀的程序员。不仅仅是机器学习工程师必须能够编写高质量的代码。当然,数据科学家不一定要能够构建复杂的软件系统,但他或她必须能够构建结构清晰、文档完善且易于维护的代码!
也就是说,对于数据科学家来说,重点将是看到快速的结果,而不是构建可持续的软件。因此,数据科学家的首选工具——因为整个事情通常在 Python 世界中进行——将是广泛使用 Jupyter 笔记本,它积极支持探索性的工作方式;这种工作的最终产品通常是原型脚本。
然而,机器学习工程师编写了软件。我怎么强调这一点都不为过。(如果你在机器学习方面非常优秀,并且正在构建结构清晰、文档完善且易于维护的脚本,那么你就是我们在 Alexander Thamm 的项目中能够找到的最好的数据科学家——而不是机器学习工程师!).机器学习工程师专注于构建可以快速扩展的软件。Python 世界中也会出现很多这种情况,这意味着作为首选工具,通常会使用像 PyCharm 这样的 ide。(然而,它确实超越了 Python,因为伸缩还意味着知道如何使用工具来编排用于模型训练的资源,以及将训练好的模型提供给最终用户系统,但这是另一个时间的讨论)。
项目的不同阶段需要机器学习工程师和数据科学家的不同参与。
最后要谈的是项目的阶段和谁在什么时候参与。如果我们考虑一个经历“假设”阶段的项目进展;“概念证明”;“原型”;“生产”——那么很容易说前两个是数据科学家的领域,而后两个是机器学习工程师的领域。我只是部分同意。
科学家和工程师站在沙漠边缘,凝视着远方,想知道那里是否有石油:这是“假设”阶段。科学家在沙漠中跑来跑去,用铁锹挖许多小洞,以观察石油的最初迹象,而工程师则为他的管道绘制蓝图,这就是我所说的“概念证明”。一条成熟的管道正在建设,第一口正在开采的小井就是我所说的“原型”。以及由一个我认为是“生产”的操作员团队维护的大规模、完全精炼和高效的系统。
机器学习工程师和数据科学家在整个项目中至关重要。
因此,也许看待这个问题的正确方式是认识到每个阶段都需要来自两个角色的输入,但是这些输入看起来会发生变化。特别是在开始时,机器学习工程师将非常依赖于数据科学家所做的探索,后来数据科学家将非常依赖于机器学习工程师构建的工具。但是每一个都将始终保持相关性——事实上至关重要。
在最后,两人都将继续下一件事,这可能是又一次探索之旅——这次是去北极?
机器学习可解释性
kaggle.com 微课综述
最近,我在 kaggle.com 上做了微课机器学习可解释性。我强烈推荐这门课程,因为我学到了很多有用的方法来分析一个训练过的 ML 模型。为了对所涉及的主题有一个简要的概述,这篇博文将总结我的学习。
以下段落将解释排列重要性、部分相关图和 SHAP 值等方法。我将使用著名的泰坦尼克号数据集来说明这些方法。
Photo by Maximilian Weisbecker on Unsplash
开始之前
我将要描述的方法可以用于任何模型,并且在模型适合数据集之后应用。以下回答的问题分别涉及上述在线课程中的一个部分。泰坦尼克号数据集可以用来训练一个分类模型,该模型预测泰坦尼克号上的乘客是幸存还是死亡。我在这个任务中使用了一个简单的决策树,没有优化它,也没有平衡数据,等等。它只是为了说明方法而被训练。分析代码可以在这个 GitHub 库上找到。
哪些变量对存活率影响最大?
对于这个问题,本课程建议采用排列重要性法。这种方法只是简单地取一列数据,并改变它的值,而保持其他列不变。利用改变的数据,该方法计算模型的性能。与原始数据相比,性能下降得越多,混洗列中的特征对于模型就越重要。为了找到所有特性的重要性,对所有列逐一进行这种操作。使用 eli5 python 包,我为我们的数据集找出了以下数字。
Importance of each feature for the survival on the Titanic
正如我们所见,泰坦尼克号幸存的最重要特征是性别,其次是年龄和票价。
这些数字只告诉我们哪些特征是重要的,而不是它们如何影响预测,例如,我们不知道是女性还是男性更好。为了找出特征是如何影响结果的,本课程建议使用部分相关图。
这些变量是如何影响存活率的?
找出变量如何影响结果的一个方法是在线课程建议的部分相关图。此方法获取数据集的一行,并重复更改一个要素的值。对不同的行执行多次,然后进行汇总,以找出该特性如何在很大范围内影响目标。python 包 pdpbox 可用于创建一个图表,显示使用不同值时的结果。对于我们的数据集,绘制“年龄”对目标的部分依赖关系如下所示。
Partial dependence plot for age on survival on Titanic
这个情节以一种非常好的方式表明,随着年龄的增长,在泰坦尼克号上幸存的概率会降低。尤其是 20 岁到 30 岁之间,在泰坦尼克号上可不是个好年龄。线周围的蓝色区域是线的置信度。这表明其他因素也对某人是否幸存起着很大的作用。幸运的是 pdpbox 库提供了二维图来显示两个特征对结果的相互作用。让我们看看年龄是如何与乘客乘坐的舱位相互作用的。
Partial dependence plot for age-class interaction on survival on Titanic
交互图显示,具有特定年龄的班级确实会对存活率产生影响,例如,20 至 30 岁之间的三等生的存活率低于 0.3,而拥有一等票的同龄人的存活率约为 0.5。
让我们看看三等舱的那个 30 岁的乘客,看看她的情况如何影响她的生存。为了分析特定的数据样本,本课程建议使用 SHAP 值。
变量如何影响特定乘客的生存?
SHAP 值用于显示单个用户的特征的效果。这里,该方法也采用一个特征并将该值与该特征的基线值进行比较,而不改变其他特征。所有特征都是如此。最后,该方法返回总和为 1 的所有 SHAP 值。有些价值观对结果有正面影响,有些价值观对结果有负面影响。我们特定的 30 岁乘客具有以下 SHAP 值。
Showing parameters of a specific passenger influencing the output
影响最大的有她是女性的事实,票价价格等等。蓝色值显示她乘坐的是三等舱,对结果有负面影响。
概要剧情
为了显示所有乘客的 SHAP 值汇总,我使用了如下所示的汇总图。
Summary plot of features importance towards the survival on the Titanic
该图按颜色显示特征值,红色为最大值,蓝色为最小值。因此,分类特征“性”只有两种颜色。水平位置是对样本结果的特定影响,垂直位置显示特征重要性。可以看出,就生存而言,女性大多具有积极影响,而男性大多具有消极影响。然而,例如,“费用”特征就不太明显。它的大部分值分布在 x 轴上。
依赖贡献图
为了说明在给定乘客性别的情况下,年龄对实际结果的影响,依赖贡献图就派上了用场。下面的图显示了这种贡献。
Interaction of Age and Sex towards contribution to survivals on the Titanic
随着女性乘客年龄的增加,我们看到了一个小的下降趋势(红点)。不过,这些点主要出现在正值 0 以上。如前所述,男性乘客大多低于 0,尤其是 20 到 30 之间的值。
结论
出于多种原因,我真的很喜欢上这门课。然而,对于每个数据分析师和科学家来说,分析数据或模型本身也是非常重要的。特别是,当考虑深度神经网络或其他难以遵循决策的黑盒方法时,引入的方法肯定会增加价值。
12 分钟解释机器学习
在过去的两年里,我接触了许多不同行业的客户,包括医疗保健、政府、金融、制造、电信、非营利等。,我被问到的第一个问题仍然是:我如何开始机器学习和人工智能?
这是我将制作的机器学习基础系列的第一集。不需要技术/数学/统计背景。
视频中提到的一些问题包括:
- 什么是机器学习?
- 为什么机器学习对企业如此重要?
- 机器学习是如何工作的?
- 在机器学习算法的引擎盖下会发生什么?
关于作者
scar D. Lara Yejas 是高级数据科学家,也是 IBM 机器学习中心的创始成员之一。他与世界上一些最大的企业密切合作,将 ML 应用于他们的特定用例,包括医疗保健、金融、制造、政府和零售。他还为 IBM 大数据产品组合做出了贡献,特别是在大规模机器学习领域,是 Apache Spark 和 Apache SystemML 的贡献者。
scar 拥有南佛罗里达大学的计算机科学和工程博士学位。他是《人类活动识别:使用可穿戴传感器和智能手机》一书的作者,并发表了大量关于大数据、机器学习、以人为中心的传感和组合优化的研究/技术论文。
机器学习!= .适合()
像所有初学者一样,当我开始机器学习之旅时,我犯了太多的错误。这是同样的故事。要学的东西很多。大肆宣传。大量的技术术语。涵盖了大量的先决条件等等。
似曾相识?我知道。
Photo by David Paschke on Unsplash
对我来说,当时机器学习只涉及复杂的数学,没有别的。都是关于越来越复杂的模型。我在学习所有的数学细节,并欺骗自己我正在学习,但事实上,情况并非如此。
当时我脑海中有一个事实上的规则,如果你想提高性能或减少误差指标,就切换到更复杂的模型。并且一直做下去,直到性能提升或者损耗降低。
说说结果?挫败感!
事情没有按照我的期望进行。在从线性回归切换到具有 RBF 核的支持向量机回归机之后,我一直在等待性能大幅提升。
但现实世界中事情并不是这样的。
这样做了很多次后,我意识到这里有什么地方出了问题,我需要找出原因。
我了解到:
垃圾进= >机器= >垃圾出
机器学习!= .fit()
不要犯同样的错误。
机器学习还有很多东西。
不仅仅是复杂的模型。不仅仅如此。
以下是机器学习流程中你也应该关注的三个主要步骤:
数据清理
在现实世界的项目中,你不会每次都得到那个干净的.csv
文件。更常见的情况是,您必须从多个来源收集数据,清理它们,然后连接它们,并进一步检查一致性和重复。
数据清理不仅仅涉及填充缺失值。除此之外还有很多事情。下面列出了其中的一些:
- 检查整个数据的一致性
- 选择与您的问题相关的数据子集。
- 异常值处理
剔除离群值不是解决办法。有时,您需要深入挖掘,找出这个记录值行为不同的原因。根据你的问题陈述,在真实案例中可能吗?然后,进行相应的处理。
- 重命名列名以提高可解释性
- 删除重复记录
- 处理缺失值
- 以正确的格式存储抓取的数据
还有更多…
数据分析和可视化
如果你不了解你的数据,你就不能用它做任何事情。当然
询问与业务问题相关的问题,并通过代码了解解决方案。有时,在现实世界中,任务不是建立一个最先进的模型来预测一些事情。而是分析数据,找出隐藏的可以让业务受益的洞察,用简单的语言把洞察呈现出来。
例句:假设你在亚马逊工作,你知道客户在平台上进行的每笔交易的大部分细节。
你可以问的问题:
- 一天中大多数交易发生的高峰时间是什么时候?
- 亚马逊上卖得最多的是什么类型的产品?
- 收视率多少对购买有影响吗?
还有更多…
明白了吗?你的目标是找出可以帮助亚马逊获得更多销售的见解。
你的问题随着你的问题陈述的改变而改变。
即使你的目标是预测某事,如果不知道你的数据,你也不能做得很好。
不仅如此,数据分析和可视化还有助于您进行下一步工作,即特征工程
为什么大家都说:认识你自己,背后是有原因的。
特征工程
它是从原始特征集中提取新特征或转换现有特征集以使其适用于机器学习模型的过程。
为什么选择特色工程?
你需要明白:具有良好特性集的简单模型比具有不良特性集的复杂模型表现更好。
不理解数据和你的问题陈述,你就不能进行特征工程。
领域知识在特征工程中起着非常重要的作用。你需要找出以前在这个空间里做过的工作。阅读文献,然后结合你的发现构建新的特征。如果你有这个闲心,最好和领域专家谈谈。
特征选择:从原始集合中选择重要特征的子集。它也属于特征工程,sklearn 有关于它的大量文档。在这里 看完 。
创建一个简单的基线模型,这样你就可以在加入新特性后比较你的结果,看看它们是否有帮助。记住:这是一个迭代的过程。
投入时间构建新特性远比等待一个复杂的模型开始工作要好。
关键教训:不要爱上复杂的模型,而要爱上数据。各有侧重。都是有联系的。
希望你喜欢这篇文章,并学到一些新东西。将这些知识融入到你的新项目中,并与刚刚起步的人分享这篇文章!
关注我更多这样的文章。和平与力量。
用于异常检测和状态监控的机器学习
从数据导入到模型输出的分步教程
我上一篇关于异常检测和条件监控的文章收到了很多反馈。我收到的许多问题涉及技术方面以及如何建立模型等。由于这个原因,我决定写一篇后续文章,详细介绍所有必要的步骤,从预处理数据到构建模型和可视化结果。
对于异常检测和状态监控的介绍,我建议首先阅读我关于这个主题的原始文章。这为如何利用机器学习和数据驱动分析从传感器数据中提取有价值的信息提供了必要的背景信息。
当前的文章主要集中在技术方面,包括建立基于多元统计分析和自动编码器神经网络的异常检测模型所需的所有代码。
下载数据集:
为了复制原始文章中的结果,首先需要从 NASA 声学和振动数据库下载数据集。有关实验和可用数据的更多信息,请参见下载的 IMS 轴承数据自述文件。
每个数据集由单独的文件组成,这些文件是以特定间隔记录的 1 秒振动信号快照。每个文件由 20.480 个点组成,采样率设置为 20 kHz。文件名表示收集数据的时间。数据文件中的每条记录(行)都是一个数据点。较大的时间戳间隔(显示在文件名中)表示在下一个工作日恢复实验。
导入包和库:
第一步是为分析导入一些有用的包和库:
*# Common imports*
**import** **os**
**import** **pandas** **as** **pd**
**import** **numpy** **as** **np**
**from** **sklearn** **import** preprocessing
**import** **seaborn** **as** **sns**
sns.set(color_codes=**True**)
**import** **matplotlib.pyplot** **as** **plt**
%**matplotlib** inline
**from** **numpy.random** **import** seed
**from** **tensorflow** **import** set_random_seed
**from** **keras.layers** **import** Input, Dropout
**from** **keras.layers.core** **import** Dense
**from** **keras.models** **import** Model, Sequential, load_model
**from** **keras** **import** regularizers
**from** **keras.models** **import** model_from_json
数据加载和预处理:
假设随着时间推移,齿轮逐渐退化,所以在下面的分析中,我们每 10 分钟使用一个数据点。通过使用每个文件中 20.480 个数据点的振动记录的平均绝对值,汇总每个 10 分钟的数据点。然后,我们将所有内容合并到一个数据帧中。
在下面的例子中,我使用了来自第二档齿轮故障测试的数据(参见 readme 文档以获得关于该实验的更多信息)。
data_dir = '2nd_test'
merged_data = pd.DataFrame()
**for** filename **in** os.listdir(data_dir):
print(filename)
dataset=pd.read_csv(os.path.join(data_dir, filename), sep='**\t**')
dataset_mean_abs = np.array(dataset.abs().mean())
dataset_mean_abs = pd.DataFrame(dataset_mean_abs.reshape(1,4))
dataset_mean_abs.index = [filename]
merged_data = merged_data.append(dataset_mean_abs)
merged_data.columns = ['Bearing 1','Bearing 2','Bearing 3','Bearing 4']
加载振动数据后,我们将索引转换为日期时间格式(使用遵循惯例的,然后在将合并的数据集保存为. csv 文件之前,按时间顺序按索引对数据进行排序
merged_data.index = pd.to_datetime(merged_data.index, format='%Y.%m.**%d**.%H.%M.%S')merged_data = merged_data.sort_index()
merged_data.to_csv('merged_dataset_BearingTest_2.csv')
merged_data.head()
Resulting dataframe: “merged_data”
定义训练/测试数据:
在建立模型之前,我们需要定义训练/测试数据。为此,我们执行一个简单的分割,在数据集的第一部分(应该代表正常运行条件)上进行训练,并在导致轴承故障的数据集的其余部分上进行测试。
dataset_train = merged_data['2004-02-12 11:02:39':'2004-02-13 23:52:39']
dataset_test = merged_data['2004-02-13 23:52:39':]dataset_train.plot(figsize = (12,6))
Training data: Normal operating conditions
标准化数据:
然后我使用 Scikit-learn 的预处理工具来缩放模型的输入变量。“最小最大缩放器”只是将数据重新缩放到范围[0,1]内。
scaler = preprocessing.MinMaxScaler()
X_train = pd.DataFrame(scaler.fit_transform(dataset_train),
columns=dataset_train.columns,
index=dataset_train.index)*# Random shuffle training data*
X_train.sample(frac=1)
X_test = pd.DataFrame(scaler.transform(dataset_test),
columns=dataset_test.columns,
index=dataset_test.index)
异常检测的 PCA 型模型;
由于处理高维传感器数据通常具有挑战性,因此有几种技术可以减少变量的数量(降维)。主要技术之一是主成分分析 (PCA)。关于更详细的介绍,我参考了我关于这个主题的原始文章。
作为初步尝试,让我们将传感器读数压缩到两个主要分量。
**from** **sklearn.decomposition** **import** PCApca = PCA(n_components=2, svd_solver= 'full')X_train_PCA = pca.fit_transform(X_train)
X_train_PCA = pd.DataFrame(X_train_PCA)
X_train_PCA.index = X_train.index
X_test_PCA = pca.transform(X_test)
X_test_PCA = pd.DataFrame(X_test_PCA)
X_test_PCA.index = X_test.index
马哈拉诺比斯距离度量:
马氏距离广泛用于聚类分析和分类技术。为了使用 Mahalanobis 距离将测试点分类为属于 N 个类别之一,首先估计每个类别的协方差矩阵,通常基于已知属于每个类别的样本。在我们的例子中,由于我们只对“正常”与“异常”的分类感兴趣,我们使用只包含正常操作条件的训练数据来计算协方差矩阵。然后,给定一个测试样本,我们计算到“正常”类的 Mahalanobis 距离,如果距离超过某个阈值,则将测试点分类为“异常”。
关于这些技术方面的更详细的介绍,你可以看看我以前的文章,它更详细地涵盖了这些主题。
定义 PCA 模型中使用的函数:
计算协方差矩阵:
**def** cov_matrix(data, verbose=**False**):
covariance_matrix = np.cov(data, rowvar=**False**)
**if** is_pos_def(covariance_matrix):
inv_covariance_matrix = np.linalg.inv(covariance_matrix)
**if** is_pos_def(inv_covariance_matrix):
**return** covariance_matrix, inv_covariance_matrix
**else**:
print("Error: Inverse of Covariance Matrix is not positive definite!")
**else**:
print("Error: Covariance Matrix is not positive definite!")
计算马哈拉诺比斯距离:
**def** MahalanobisDist(inv_cov_matrix, mean_distr, data, verbose=**False**):
inv_covariance_matrix = inv_cov_matrix
vars_mean = mean_distr
diff = data - vars_mean
md = []
**for** i **in** range(len(diff)):
md.append(np.sqrt(diff[i].dot(inv_covariance_matrix).dot(diff[i])))
**return** md
检测异常值:
**def** MD_detectOutliers(dist, extreme=**False**, verbose=**False**):
k = 3\. **if** extreme **else** 2.
threshold = np.mean(dist) * k
outliers = []
**for** i **in** range(len(dist)):
**if** dist[i] >= threshold:
outliers.append(i) *# index of the outlier*
**return** np.array(outliers)
计算将数据点分类为异常的阈值:
**def** MD_threshold(dist, extreme=**False**, verbose=**False**):
k = 3\. **if** extreme **else** 2.
threshold = np.mean(dist) * k
**return** threshold
检查矩阵是否正定:
**def** is_pos_def(A):
**if** np.allclose(A, A.T):
**try**:
np.linalg.cholesky(A)
**return** **True**
**except** np.linalg.LinAlgError:
**return** **False**
**else**:
**return** **False**
设置 PCA 模型:
从两个主要部分定义训练/测试集:
data_train = np.array(X_train_PCA.values)
data_test = np.array(X_test_PCA.values)
根据训练集中的数据计算协方差矩阵及其逆矩阵:
cov_matrix, inv_cov_matrix = cov_matrix(data_train)
我们还计算训练集中输入变量的平均值,因为这在以后用于计算测试集中数据点的 Mahalanobis 距离
mean_distr = data_train.mean(axis=0)
使用协方差矩阵及其逆矩阵,我们可以计算定义“正常条件”的训练数据的 Mahalanobis 距离,并找到阈值以将数据点标记为异常。然后可以计算测试集中数据点的 Mahalanobis 距离,并将其与异常阈值进行比较。
dist_test = MahalanobisDist(inv_cov_matrix, mean_distr, data_test, verbose=**False**)
dist_train = MahalanobisDist(inv_cov_matrix, mean_distr, data_train, verbose=**False**)
threshold = MD_threshold(dist_train, extreme = **True**)
标记异常的阈值:
如果满足正态分布输入变量的假设,到分布质心的马氏距离的平方应遵循χ2 分布。这也是上述用于标记异常的“阈值”计算背后的假设。由于这种假设在我们的情况下不一定成立,因此可视化 Mahalanobis 距离的分布以设置标记异常的良好阈值是有益的。再次,我参考我的前一篇文章,获得关于这些技术方面的更详细的介绍。
我们首先想象马哈拉诺比斯距离的平方,它应该理想地遵循χ2 分布。
plt.figure()
sns.distplot(np.square(dist_train),
bins = 10,
kde= **False**);
plt.xlim([0.0,15])
Square of the Mahalanobis distance
然后想象马哈拉诺比斯距离本身:
plt.figure()
sns.distplot(dist_train,
bins = 10,
kde= **True**,
color = 'green');
plt.xlim([0.0,5])
plt.xlabel('Mahalanobis dist')
从上述分布来看,计算出的用于标记异常的阈值 3.8 似乎是合理的(定义为距分布中心的 3 个标准偏差)
然后,我们可以保存 Mahalanobis 距离,以及数据帧中训练和测试数据的阈值和“异常标志”变量:
anomaly_train = pd.DataFrame()
anomaly_train['Mob dist']= dist_train
anomaly_train['Thresh'] = threshold
*# If Mob dist above threshold: Flag as anomaly*
anomaly_train['Anomaly'] = anomaly_train['Mob dist'] > anomaly_train['Thresh']
anomaly_train.index = X_train_PCA.indexanomaly = pd.DataFrame()
anomaly['Mob dist']= dist_test
anomaly['Thresh'] = threshold
*# If Mob dist above threshold: Flag as anomaly*
anomaly['Anomaly'] = anomaly['Mob dist'] > anomaly['Thresh']
anomaly.index = X_test_PCA.index
anomaly.head()
Resulting dataframe for the test data
基于计算的统计数据,任何高于阈值的距离都将被标记为异常。
我们现在可以将数据合并到单个数据帧中,并将其保存为. csv 文件:
anomaly_alldata = pd.concat([anomaly_train, anomaly])
anomaly_alldata.to_csv('Anomaly_distance.csv')
在测试数据上验证 PCA 模型:
我们现在可以绘制计算的异常度量(Mob dist),并检查它何时超过异常阈值(注意对数 y 轴)。
anomaly_alldata.plot(logy=**True**, figsize = (10,6), ylim = [1e-1,1e3], color = ['green','red'])
从上图中,我们看到模型能够在实际轴承故障前大约 3 天检测到异常。
其他方法:用于异常检测的自动编码器模型
这里的基本思想是使用自动编码器神经网络将传感器读数“压缩”为低维表示,这捕捉了各种变量之间的相关性和相互作用。(基本上与 PCA 模型的原理相同,但是这里我们也允许输入变量之间的非线性)。
关于自动编码器的更详细的介绍,你可以看看我以前的文章,它更详细地涵盖了这个主题。
定义自动编码器网络:
我们使用一个 3 层神经网络:第一层有 10 个节点,中间层有 2 个节点,第三层有 10 个节点。我们使用均方误差作为损失函数,并使用“Adam”优化器训练模型。
seed(10)
set_random_seed(10)
act_func = 'elu'
*# Input layer:*
model=Sequential()
*# First hidden layer, connected to input vector X.*
model.add(Dense(10,activation=act_func,
kernel_initializer='glorot_uniform',
kernel_regularizer=regularizers.l2(0.0),
input_shape=(X_train.shape[1],)
)
)
model.add(Dense(2,activation=act_func,
kernel_initializer='glorot_uniform'))
model.add(Dense(10,activation=act_func,
kernel_initializer='glorot_uniform'))
model.add(Dense(X_train.shape[1],
kernel_initializer='glorot_uniform'))
model.compile(loss='mse',optimizer='adam')
*# Train model for 100 epochs, batch size of 10:*
NUM_EPOCHS=100
BATCH_SIZE=10
拟合模型:
为了跟踪训练期间的准确性,我们在每个时期后使用 5%的训练数据进行验证(validation_split = 0.05)
history=model.fit(np.array(X_train),np.array(X_train),
batch_size=BATCH_SIZE,
epochs=NUM_EPOCHS,
validation_split=0.05,
verbose = 1)
Training process
可视化培训/验证损失:
plt.plot(history.history['loss'],
'b',
label='Training loss')
plt.plot(history.history['val_loss'],
'r',
label='Validation loss')
plt.legend(loc='upper right')
plt.xlabel('Epochs')
plt.ylabel('Loss, [mse]')
plt.ylim([0,.1])
plt.show()
Train/validation loss
训练集中损失函数的分布:
通过在训练集中绘制计算损失的分布,可以使用它来识别用于识别异常的合适阈值。在这样做时,可以确保该阈值被设置在“噪声水平”之上,并且任何被标记的异常应该在噪声背景之上具有统计显著性。
X_pred = model.predict(np.array(X_train))
X_pred = pd.DataFrame(X_pred,
columns=X_train.columns)
X_pred.index = X_train.index
scored = pd.DataFrame(index=X_train.index)
scored['Loss_mae'] = np.mean(np.abs(X_pred-X_train), axis = 1)plt.figure()
sns.distplot(scored['Loss_mae'],
bins = 10,
kde= **True**,
color = 'blue');
plt.xlim([0.0,.5])
Loss distribution, training set
根据上面的损失分布,让我们尝试使用阈值 0.3 来标记异常。然后,我们可以计算测试集中的损失,以检查输出何时超过异常阈值。
X_pred = model.predict(np.array(X_test))
X_pred = pd.DataFrame(X_pred,
columns=X_test.columns)
X_pred.index = X_test.index
scored = pd.DataFrame(index=X_test.index)
scored['Loss_mae'] = np.mean(np.abs(X_pred-X_test), axis = 1)
scored['Threshold'] = 0.3
scored['Anomaly'] = scored['Loss_mae'] > scored['Threshold']
scored.head()
然后,我们也为训练集计算相同的指标,并将所有数据合并到单个数据帧中:
X_pred_train = model.predict(np.array(X_train))
X_pred_train = pd.DataFrame(X_pred_train,
columns=X_train.columns)
X_pred_train.index = X_train.index
scored_train = pd.DataFrame(index=X_train.index)
scored_train['Loss_mae'] = np.mean(np.abs(X_pred_train-X_train), axis = 1)
scored_train['Threshold'] = 0.3
scored_train['Anomaly'] = scored_train['Loss_mae'] > scored_train['Threshold']scored = pd.concat([scored_train, scored])
自动编码器模型的结果:
计算了损耗分布和异常阈值后,我们可以将轴承故障前的模型输出可视化:
scored.plot(logy=**True**, figsize = (10,6), ylim = [1e-2,1e2], color = ['blue','red'])
总结:
两种建模方法给出了相似的结果,它们能够在实际故障之前很好地标记即将发生的轴承故障。主要的区别本质上是如何为标记异常定义合适的阈值,以避免在正常操作条件下出现许多假阳性。
我希望这篇教程能给你启发,让你自己尝试这些异常检测模型。一旦你成功地建立了模型,是时候开始试验模型参数了。并在新的数据集上测试同样的方法。如果你遇到一些有趣的用例,请在下面的评论中告诉我。
玩得开心!
如果你有兴趣了解更多与人工智能/机器学习和数据科学相关的主题,你也可以看看我写的其他一些文章。你会发现他们都列在我的中型作者简介,,你可以在这里找到。
而且,如果你想成为一个媒体会员,免费访问平台上的所有资料,你也可以使用下面我的推荐链接。(注意:如果您使用此链接注册,我也会收到一部分会员费)
[## 通过我的推荐链接加入媒体- Vegard Flovik
作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…
medium.com](https://medium.com/@vflovik/membership)
更多来自 Vegard Flovik 媒体:
- 蒙特卡洛方法简介
- 从物理学到数据科学的转变
- 什么是图论,你为什么要关心它?
- 用于图像分类的深度迁移学习
- 建造一个能读懂你思想的人工智能
- 机器学习:从炒作到现实应用
- 人工智能和大数据隐藏的风险
- 如何使用机器学习进行异常检测和状态监控
- 用于供应链管理的人工智能:预测分析和需求预测
- 如何(不)使用机器学习进行时间序列预测:避免陷阱
- 如何利用机器学习进行生产优化:利用数据提高绩效
- 你如何向人工智能系统教授物理学?
- 我们能使用纳米级磁铁建立人工大脑网络吗?
人工智能研讨会——从宣传到现实应用
面向八年级学过数学的人的机器学习
抛开所有的复杂性,剩下的就是一个简单的代数公式
Credit: OstapenkoOlena/iStock/Getty Images Plus
我通常看到以两种方式解释人工智能:通过媒体日益煽情的视角,或者通过充斥着多余语言和特定领域术语的密集科学文献。
初学者的机器学习:神经网络导论
简单解释它们如何工作,以及如何用 Python 从头实现一个。
这里有些东西可能会让你吃惊:神经网络并没有那么复杂!术语“神经网络”经常被用作时髦词汇,但实际上它们往往比人们想象的要简单得多。
这篇文章是为完全的初学者而写的,假设你没有机器学习的知识。我们将理解神经网络是如何工作的,同时用 Python 从头实现一个神经网络。
我们开始吧!
注意:我推荐阅读 victorzhou.com的这篇文章——这篇文章的大部分格式在那里看起来更好。
1.构建模块:神经元
首先,我们必须谈谈神经元,它是神经网络的基本单位。一个神经元接受输入,用它们做一些数学运算,然后产生一个输出。这是一个双输入神经元的样子:
这里发生了三件事。首先,每个输入乘以一个权重:
接下来,所有加权输入与偏差 b 相加:
最后,总和通过一个激活函数传递:
激活函数用于将一个无界的输入转换成一个具有良好的、可预测的形式的输出。一个常用的激活功能是 sigmoid 功能:
sigmoid 函数只输出(0,1)范围内的数字。你可以把它想成是把(∞,+∞)压缩到(0,1)——大负数变成0,大正数变成1。
简单的例子
提醒:这篇文章的大部分格式在 victorzhou.com上的原帖中看起来更好。
假设我们有一个 2 输入神经元,它使用 sigmoid 激活函数并具有以下参数:
w =[0,1]只是向量形式的 w 1 =0, w 2 =1 的一种写法。现在,让我们给神经元一个x=【2,3】的输入。我们将使用点积来更简洁地写东西:
给定输入x=【2,3】,神经元输出 0.999。就是这样!这个向前传递输入以获得输出的过程被称为前馈。
编码一个神经元
是时候实现一个神经元了!我们将使用 NumPy ,一个流行且强大的 Python 计算库,来帮助我们做数学:
认得这些号码吗?这就是我们刚才做的例子!我们得到同样的答案 0.999。
2.将神经元组合成神经网络
神经网络只不过是一堆连接在一起的神经元。下面是一个简单的神经网络可能的样子:
这个网络有两个输入,一个隐层有两个神经元( h 1 和 h 2),一个输出层有一个神经元( o 1)。请注意, 1 的输入是来自 h 1 和 h 2 的输出——这就是网络的构成。
隐藏层是输入(第一个)层和输出(最后一个)层之间的任何层。可以有多个隐藏层!
一个例子:前馈
让我们使用上图所示的网络,并假设所有神经元都具有相同的权重 w =[0,1】,相同的偏差 b =0,以及相同的 sigmoid 激活函数。设 h 1、 h 2、 o 1 表示它们所代表的神经元的输出。
如果我们传入输入 x =[2,3]会发生什么?
输入 x =[2,3]的神经网络输出为 0.7216。很简单,对吧?
一个神经网络可以有任意数量的层,在这些层中有任意数量的神经元。基本思想保持不变:通过网络中的神经元将输入前馈,最终得到输出。为了简单起见,我们将在本文的剩余部分继续使用上图所示的网络。
神经网络编码:前馈
让我们为我们的神经网络实现前馈。这里的网络形象再次供参考:
我们又得了 0.7216!看起来很有效。
3.训练神经网络,第 1 部分
假设我们有以下测量值:
让我们训练我们的网络,根据某人的体重和身高来预测他们的性别:
我们将用 0 表示男性,用 1 表示女性,我们还将移动数据以使其更易于使用:
失败
在我们训练我们的网络之前,我们首先需要一种方法来量化它做得有多“好”,以便它可以尝试做得“更好”。这就是损失的原因。
我们将使用均方误差 (MSE)损失:
让我们来分解一下:
- n 为样本数,为 4(爱丽丝、鲍勃、查理、戴安娜)。
- y 代表被预测的变量,是性别。
- y_true 是变量的 true 值(“正确答案”)。例如,爱丽丝的 y_true 将为 1(女性)。
- y_pred 是变量的预测值。它是我们网络输出的任何东西。
(y _ true-y _ pred)被称为平方误差。我们的损失函数只是取所有平方误差的平均值(因此名字表示平方误差)。我们的预测越准确,我们的损失就越低!
更好的预测=更低的损失。
训练一个网络=尽量减少它的损失。
损失计算示例
假设我们的网络总是输出 00——换句话说,它确信所有人类都是男性🤔。我们会有什么损失?
代码:MSE 损失
下面是一些为我们计算损失的代码:
If you don’t understand why this code works, read the NumPy quickstart on array operations.
很好。向前!
喜欢这个帖子吗?我写了很多初学者友好的 ML 文章。订阅我的简讯让它们进入你的收件箱!
4.训练神经网络,第 2 部分
我们现在有一个明确的目标:最小化神经网络的损失。我们知道我们可以改变网络的权重和偏差来影响它的预测,但是我们怎样才能减少损失呢?
本节使用了一点多变量微积分。如果你对微积分感到不舒服,可以跳过数学部分。
为了简单起见,让我们假设我们的数据集中只有 Alice:
那么均方误差损失就是爱丽丝的平方误差:
另一种思考损失的方式是作为权重和偏差的函数。让我们给网络中的每个权重和偏差贴上标签:
然后,我们可以将损失写成一个多变量函数:
假设我们想要调整 w 1。如果我们改变 w 1,损失 L 会如何变化?这个问题偏导数可以回答。我们怎么算?
这就是数学开始变得更加复杂的地方。不要气馁!我建议带上纸和笔——这会帮助你理解。
如果你读这个有困难:下面的数学格式在 victorzhou.com 的原始帖子里看起来更好。
首先,让我们用∂y _ pred/∂w1 来重写偏导数:
This works because of the Chain Rule.
我们可以计算∂ L/ ∂ y_pred ,因为我们在上面计算了 l =(1-t34)y _ pred:
现在,让我们弄清楚如何处理∂y _ pred/∂w1。就像之前一样,设 h 1、 h 2、 o 1 为它们所代表的神经元的输出。然后
f is the sigmoid activation function, remember?
由于 w 1 只影响 h 1(而不是 h 2),我们可以写
More Chain Rule.
我们为∂做同样的事情:
You guessed it, Chain Rule.
x 1 这里是体重, x 2 是身高。这是我们现在第二次看到f'(x)(sigmoid 函数的导数)了!我们来推导一下:
稍后我们将使用这个漂亮的形式来表示f'(x)。
我们完了!我们已经设法将∂1 分解成我们可以计算的几个部分:
这种通过逆向计算偏导数的系统被称为反向传播,或“反向传播”。
唷。这是一大堆符号——如果你还是有点困惑,没关系。让我们做一个例子来看看这是怎么回事!
示例:计算偏导数
我们将继续假设只有 Alice 在我们的数据集中:
让我们将所有权重初始化为 1,将所有偏差初始化为 0。如果我们通过网络进行前馈,我们得到:
网络输出 y_pred =0.524,不强烈偏向男性(0)或女性(1)。我们来计算一下∂ L/ ∂ w 1:
提醒:我们在前面为我们的乙状结肠激活函数推导了 f'(x)=f(x)∫(1-f(x)。
我们做到了!这告诉我们,如果我们要增加 w 1, L 结果会增加一个t iiny位。
训练:随机梯度下降
我们现在已经拥有了训练神经网络所需的所有工具!我们将使用一种叫做随机梯度下降 (SGD)的优化算法,告诉我们如何改变我们的权重和偏差,以最小化损失。基本上就是这个更新方程式:
η 是一个叫做学习率的常数,它控制着我们训练的速度。我们所做的就是从 w 1 中减去η∂w1/∂l:
- 如果∂ L/ ∂ w 1 为正, w 1 将减少,这使得 L 减少。
- 如果∂ L/ ∂ w 1 为负, w 1 将增加,这使得 L 减少。
如果我们对网络中的每一个权重和偏差都这样做,那么损耗会慢慢减少,我们的网络也会改善。
我们的培训过程将是这样的:
- 从我们的数据集中选择一个样本。这就是随机梯度下降的原因——我们一次只对一个样本进行操作。
- 计算损失相对于权重或偏差的所有偏导数(例如∂ L/ ∂ w 1,∂ L /∂ w 2 等)。
- 使用更新等式来更新每个权重和偏差。
- 回到步骤 1。
让我们看看它的实际效果吧!
代码:一个完整的神经网络
终于到了实现完整神经网络的时刻:
你可以自己运行/玩这个代码。在 Github 上也有。
我们的损失稳步下降,因为网络了解到:
我们现在可以利用网络来预测性别:
现在怎么办?
你成功了!快速回顾一下我们的工作:
- 介绍了神经元,神经网络的构建模块。
- 在我们的神经元中使用了乙状窦激活功能。
- 我发现神经网络只是连接在一起的神经元。
- 创建了一个数据集,将体重和身高作为输入(或特征),将性别作为输出(或标签)。
- 了解了损失函数和均方误差 (MSE)损失。
- 意识到训练一个网络只是最小化它的损失。
- 使用反向传播计算偏导数。
- 使用随机梯度下降 (SGD)来训练我们的网络。
还有很多事情要做:
- 使用适当的机器学习库,如 Tensorflow 、 Keras 和 PyTorch ,尝试更大/更好的神经网络。
- 用 Keras 建立你的第一个神经网络。
- 在你的浏览器中修补神经网络。
- 发现除了 sigmoid 之外的其他激活功能,如 Softmax 。
- 发现除了 SGD 之外的其他优化器。
- 看我的卷积神经网络介绍(CNN)。CNN 彻底改变了计算机视觉的领域,并且非常强大。
- 看我的介绍递归神经网络 (RNNs),经常用于自然语言处理 (NLP)。
我将来可能会写这些话题或类似的话题,所以如果你想得到新帖子的通知,请订阅。
感谢阅读!
原贴于victorzhou.com。
一个或多个变量的线性回归
生物医学数据的机器学习
如何在医学中使用线性回归进行结果预测
简介
线性回归是一种用于机器学习的统计模型,属于“监督学习”类算法,适用于生物医学数据的分析。我们使用它来预测连续值输出,这与逻辑回归不同,逻辑回归用于预测离散值输出(即分类)。
在开始之前,我建议读者先去 Coursera 上学习 Andrew NG 教授的有趣的机器学习课程。本课程对这篇文章中讨论的所有论点提供了一个很好的解释。
让我们从我们的例子开始:我们有一个检查收缩压(SBP)并监测年龄和体重的患者数据集,我们想预测一个新患者的 SBP。我们假设体重和年龄等因素会影响 SBP。对于我们的数据集,我们将从[2]中获取一个表的值
Table 1: Dataset
要说明的变量(SBP)称为 因变量 ,或 响应变量 ,它与我们的 输出 变量或 目标向量 相匹配。而是将解释 输入 (年龄和体重)的变量称为 自变量 或 预测变量 ,或 特征 。如果因变量和自变量是连续的,如 SBP、和体重的情况,那么可以计算出一个相关系数作为它们之间关系强度的度量。[3]
我们说线性回归代表了相关性的进化。两者的区别在于:相关性是指两个或多个变量之间关系的强弱。相反,回归指的是描述两个或多个变量之间关系的统计技术和算法的集合[2]。
线性回归假设一个或多个输入要素与相对目标矢量(输出)之间的关系近似呈线性。[4],它能够识别和表征这种关系。这种假设的结果是,在线性回归模型中,输入特征对目标向量(输出)有“影响”,并且这种影响是恒定的。
“影响”通常被确定为“系数”、“权重”或“参数”,更简单地说,我们说线性回归计算输入特征的加权和,加上一个称为“偏差项”或截距的常数[5]。
为了简化,让我们从应用一个变量的线性回归开始。
一元线性回归
如果我们想彻底理解线性回归是如何工作的,从一个变量开始是一个基本步骤。我们将使用表 1 中的数据集,只外推特征“年龄”并使用“SBP”列作为输出。
本文中的所有代码都是用 Python 2.7 编写的,对于移植到许多其他语言来说,它也是不言自明的。对于实现环境,我建议使用 Jupyter 笔记本。
将主要使用线性代数计算,因为它在尽可能避免“while”和“for”循环方面具有内在优势。为了实现这个目标,我们将使用 NumPy ,这是一个强大的数学函数库,用于使用 Python 进行科学计算。
在开始描述线性回归模型之前,有必要看一下我们的数据,并尝试了解线性回归是否适用于这些数据。目标是基于患者年龄预测例如收缩压值。
第一步:导入 Python 库
首先,我们导入本帖将要讨论的 Python 代码所需的所有包: NumPy 、 Pandas 和 matplot 。这些软件包属于 SciPy.org,这是一个基于 Python 的数学、科学和工程开源软件生态系统。
Numpy 对于线性代数计算是必要的。
Pandas 是一个开源库,为 Python 提供高性能、数据结构和数据分析工具。pandas 数据帧是一个二维大小可变的、潜在异构的表格数据结构。它由三个主要部分组成,数据、行和列,带有标记的轴(行和列)。点击这个链接到 GeeksForGeeks 门户网站,获取关于熊猫数据框架使用的详细信息。
Matplotlib 是创建所有绘图的基础。
Code 1: import Python libraries
第二步:创建数据集
在这一步中,我们将使用我们的值创建一个数据集。带有标题的逗号分隔值格式的示例如下:
年龄体重 SBP
60,58,117
61,90,120
74,96,145
57,72,129
63,62,132
68,79,130
66,69,110
77,96,163
63,96,136
50
复制并粘贴文件中的值,并将其保存为“SBP.csv”
第三步:打开数据集
一旦我们创建了 SBP.csv 数据集,上传它并使用 Pandas pd 对象创建一个 DataFrame。数据集上传的 Python 代码如下:
Code 2: upload data and create a pandas DataFrame
在 Jupyter 单元格中键入“df ”,将显示如下数据帧内容:
Table 2: Visualizing a pandas DataFrame
步骤 4:上传数据集
SBP 数据集由 3 列组成(年龄、体重和 SBP),但我们将上传第一列和最后一列(年龄和 SBP);我们的模型将决定年龄和 SBP 之间关系的强度。Pandas 使访问 DataFrame 变量变得容易,这些变量将被复制到一个包含输入的 X 向量和一个用于输出的 y 向量中。
Code 3: Uploading the dataset
第五步:特征缩放和归一化
在继续之前,此处报告的 SBP 数据集必须进行重新缩放和归一化。在机器学习中,需要缩放和归一化,尤其是当特征和输出之间出现数量级差异时。如简介中所述,我们将在矩阵上使用线性代数,以尽可能避免而和 for 在变量上循环。此外,编程线性代数将导致代码的良好可读性。
为此,在 Python 中,我们可以利用 NumPy。如前所述,NumPy 是一个用于科学计算和线性代数的数学函数库。所有的操作都可以简化,创建一个 NumPy 对象,并使用一些相关的方法。我们之所以要使用 NumPy,是因为尽管矩阵上的许多操作可以使用常规操作符(+、-、*、/)来完成,但 NumPy 保证了对操作的更好控制,尤其是在矩阵很大的情况下。例如,使用 NumPy,我们可以逐元素地乘以参数,如特征矩阵 X 和输出向量 y :
Code 4: Multiply arguments element-wise
关于 NumPy 使用的深入讨论超出了本文的范围。为了实现特性的缩放和规范化,我们需要以下代码:
Code 5: The FeatureScalingNormalization() function.
代码 5 实现了一个名为 FeatureScalingNormalization()的 Python 函数。该函数将特征向量 X 作为参数,返回 3 个参数:1)同一个 X 向量,但经过缩放和归一化( X_norm ),2) mu ,即训练集中 X 的平均值,3) sigma ,即标准差。此外,我们将存储 mu 和 sigma ,因为这些参数在后面会很重要。复制以下代码并将其粘贴到新的 Jupyter 笔记本单元格中:
Code 6: Run the FeatureScalingNormalization function.
在笔记本单元格中键入“X”将显示新的 X 值:
array([-0.73189052, -0.59728997, 1.15251726, -1.13569219, -0.32808885, 0.34491392, 0.07571281, 1.55631892, -0.32808885, -1.53949386, -0.32808885, 1.42171837, -0.73189052, -0.59728997, -0.05888774, 1.82552004])
包含年龄值的 X 向量现在被归一化。
第六步:给 X 向量添加一列 1
现在我们将把一列 1 添加到向量 X 中。
Code 7: Add a column of ones to the X vector.
这是 X 的新结构:
array([[ 1\. , -0.73189052],
[ 1\. , -0.59728997],
[ 1\. , 1.15251726],
[ 1\. , -1.13569219],
[ 1\. , -0.32808885],
[ 1\. , 0.34491392],
[ 1\. , 0.07571281],
[ 1\. , 1.55631892],
[ 1\. , -0.32808885],
[ 1\. , -1.53949386],
[ 1\. , -0.32808885],
[ 1\. , 1.42171837],
[ 1\. , -0.73189052],
[ 1\. , -0.59728997],
[ 1\. , -0.05888774],
[ 1\. , 1.82552004]])
第七步:绘制数据集
当我们想知道数据是如何分布的时候,绘制数据图是一种有用的做法。使用 matplotlib 散点图方法绘制数据:
Code 8: Plot data
Figure 1: Plot Age-SBP
将数据可视化一目了然,我们可以注意到年龄和 SBP 之间增加关系的模式。这是我们所期望的,因为收缩压在生理上与年龄增长有关。
第八步:假设(线性回归模型)
线性回归的基本思想由基于输入特征 X 预测输出 y 的函数来表示。
Equation 1: Linear Regression Model
预测输出是 h = θ * X 项,它等于一个称为“偏差项”或“截距项”或 θ_0 的常数加上输入特征 X 、的加权和,其中 θ_1 代表X的权重。我们将这个函数称为“假设”,我们将使用它从 X (年龄)到 y (SBP)进行“映射”。
由于我们使用线性代数,对于所有计算,我们可以将假设模型写成矢量化形式:
Equation 2: Linear Regression Model in vectorized form
其中θ_0和 θ _ 1 表示为向量θ=【θ_ 0,θ_1】***,假设等于 θX 。*
预测 y 的最佳性能包括找到预测的 y 值和实际的 y 值之间的距离更接近最小值的θ 值。
让我们试试随机选择的两个参数,对于向量θ,例如:θ = [140.0,5.0],看看会发生什么:
Code 9: Plot the Hypothesis with θ = [140.0, 5.0]
Figure 2: θ = [140.0; 5.0]
图 2 中用红线表示的假设模型应该预测y(SBP)。对于θ=【140.0,5.0】的值,它表示我们在预测 y 时的 h=θX 向量。但是这个模型显然不符合我们的数据。正如用红线连接圆点的蓝线所突出显示的,假设“触及”了一些 y 值,但是剩余的 h 向量远不是最小值。所以我们很想猜测当设置不同的值时,哪个 θ 可以预测 y 。我们可以“通过试错法”选择 θ 来最小化假设和y之间的所有距离。为了实现这个目标,我们可以为我们的模型计算 成本函数 。
第九步:计算成本函数
成本函数 可以记录我们离假设模型的最小值有多远,并可以帮助我们找到最佳θ 。描述成本函数的等式如下:
Equation 3: Linear Regression Cost Function
其中 m 是 X 向量的长度(在我们的例子中= 16),而 i 是分配给数据集中每一项的索引。该等式由三部分组成:
- 假设( h=θX )
- 平方误差即= ( h-y ) ^2
- 成本函数 J 计算如下:J = 1/2m * Sum(平方误差)
由于我们使用线性代数,等式 3 的矢量化实现如下:
Equation 4: Linear Regression Cost Function (vectorized form)
直觉一.
为了简化解释,让我们尝试手动计算仅由 SBP 数据集的前 3 个值组成的较小数据集的成本函数,以及θ = [120.0,10.0]的。目前,这些参数是随机选择的,因为我们现在不需要设置最佳的*θ。*我们将分割 X 和 y ,产生数组 X_1 和 y_1 😗*
Code 10: Make a vector X_1 and y_1 with the first 3 values of X, and y.
同样,我们必须设置 m=3 ,因为我们现在有三个样本。让我们将数据和假设绘制如下:
Code 11: Plot data and Hypothesis
Figure 4: Plot of the first 3 values of the dataset; θ = [120.0; 10.0]
SBP 前三个值(蓝点)对应的矢量 y 为:
y = [117.0,120.0,145.0]
由于我们的 θ 为=【120,10.0】, h = θ X_1 的乘积将由以下向量表示,(红线上的点高亮显示):*
h = θX_1 = [112.7,114.0,131.5]*
蓝色虚线突出显示了实际 y_1 值和预测值之间的距离。现在,我们有了所有我们需要的,来计算成本函数 J 。我们将应用解决方案 1 中描述的成本函数:
Solution I: Calculating the Cost Function
…成本函数(J)是= 39.3
Python 中的代价函数。
以下 Python 代码实现了成本函数:
Code 12: The code for calculating the Cost Function
该代码逐步实现等式 4 中描述的成本函数(矢量化)。让我们再重复一遍:
- 假设( h=θX )
- 平方误差即= (h-y) ^2)
- 成本函数 J 即= 1/2m * Sum(平方误差)
既然我们已经理解了成本函数计算的机制,让我们回到完整的 SBP 数据集(16 名患者)。如果我们想计算整个 SBP 数据集的成本函数,使用θ=【140.0;5.0],我们将键入:
Code 13: Running calcCostFunction
该函数将返回 J = 138.04,这是为θ=【140.0】计算的代价函数;5.0] 。这个 J 不是我们能找到的最小 J ,因为我们已经手动设置了 θ,不知道如何最小化它。下面的直觉 II 可以帮助我们更好地理解我们手工方法的局限性。
直觉二。
以下代码随机生成 10 个 θ 向量,并将它们传递给 calcCostFunction ,生成一个相对成本函数表( J ):
Code 14: Try random θ and calculate the Cost Function
产生的输出是:
***[Th0 Th1] J**
[38\. 55.] 5100.4688623710845
[71\. 47.] 2352.6631642080174
[28\. 76.] 7148.466632549135
[73\. 75.] 3579.826857778751
[79\. 47.] 1925.1631642080174
[12\. 42.] 7320.026790356101
[68\. 25.] 1992.2131192595837
[25\. 92.] 8565.015528875269
[51\. 46.] 3667.1483894376343
[13\. 62.] 7992.509785763768*
“带回家的信息”是试图手工最小化 J 不是正确的方法。在随机选择的 θ的上运行 10 次之后, J 的行为是不可预测的。而且,没有办法根据 θ来猜测 J 。那么问题来了:我们如何选择 θ,求最小 J?我们需要一个能为我们最小化 J 的算法,这个算法就是下一步的论证。
步骤 10:梯度下降
我们感兴趣的是使用 【梯度下降】**找到成本函数的最小值,这是一种可以使这种搜索自动化的算法。梯度下降计算代价函数的导数,通过参数 α、更新向量 θ ,即学习率。从现在开始,我们将把 SBP 数据集称为训练集。这种澄清是必要的,因为梯度下降将使用数据集的实际矢量 y 和 h 矢量预测之间的差异来“学习”如何找到最小值 J 。该算法将重复,直到它将收敛。 θ 更新必须同时进行。**
Equation 4: Gradient Descent implementation
由于我们使用线性代数,矢量化实现如下:
Equation 5: Gradient Descent (vectorized form)
注意,这里我们必须转置 X ,因为 X 是一个[16,2]矩阵,而错误是一个[16,1]向量。
梯度下降实现。
以下 Python 代码实现了梯度下降。我们将使用方程 5 的矢量化形式:
Code 15: The Gradient Descent function
要运行梯度下降,我们必须初始化 θ 、迭代、和 α、,它们与 X 和 y 一起是梯度下降函数的参数:
Code 16: Running the Gradient Descent
结果收集在“结果”列表中。该列表由找到的 θ、加上包含 θ 和 J 历史的两个列表组成。经过 2000 次迭代后,梯度下降找到了θ=【128.4,9.9】和 J = 59.7 ,这是 J 的最小值。我们将使用这两个列表来绘制梯度下降活动。以下代码将绘制训练集和 h 。
Code 17: Plot dataset and h for θ = [128.4, 9.9]. J = 59.7 is the minimum
Figure 5: Plot of dataset and h; θ = [128.4; 9.9]; J = 59.7
假设 h 现在符合我们的数据!
我们来绘制一下 θ历史:
Code 18: Plot the θ history
θ 历史曲线如图图 6 所示。红色曲线代表 θ _0,绿色曲线代表 θ _1。2000 次迭代后, θ 为=【128.4;9.9]**
Figure 6: The θ history plot. The red curve represents θ0; the green curve represents θ1
现在我们来绘制一下 J 的历史:
Code 19: Plot the J history
Figure 7: The J history plot
在大约 200 次迭代之后,成本函数下降,在 1500 次迭代之后稳定在 59.7 左右。 J 曲线取决于我们设置为 0.01 的 α、。
第 11 步:预测
现在我们已经找到了最佳的 θ,我们可以预测一个 75 岁老人的收缩压。该查询是一个向量,由两个数字[1,75]组成。第一个数字对应于特征 x_0 。为了运行预测,我们必须使用我们在步骤 5:特征缩放和归一化中计算的μ和σ参数来缩放和归一化查询向量。查询向量将是[1,1.29]。然后,我们要将查询乘以 θ 向量(θ=【128.4,9.95】)。下面的代码实现了预测。
Code 20: Predicting SBP
75 岁老人的 SBP 是:141.2
步骤 12:关于学习常数 α 的直觉
让我们用学习率 α 做一些实验。改变 α 会影响 J 的动态。如果 α 过小,梯度下降会收敛缓慢,我们需要用更多的迭代来训练它,以找到 J 的最小值。相反,如果 α 太大,则梯度下降有永不收敛的风险。有趣的是,对于大约 1.9 的 α 值,梯度下降收敛,但是对于最初的 40 次迭代, θ 的行为是紊乱的,以便连续达到稳定。(图 8)
Figure 8: Experiments with α. Panel A shows h, J and θ, with α = 0.001. If α is too little, 2000 iterations are not sufficient; Gradient Descent will be slow in converging, and it will require ~ 10000 iterations for finding the minimum J (data not shown). Panel B shows the opposite situation. With α = 1.9, Gradient Descent converges, but initially,the searching of θ shows turbulence. After 40 iterations θ reaches stability, and finally, the algorithm converges.
步骤 13:J 和 θ 的等高线图
我们可以创建一个等高线图,它是一个包含许多同心轨迹的图形。对于每条轨道,有多对与恒定值 J 相关联的 θ 。最小值 J 对应的 θ 位于中心(红点)。其他同心线对应 J 的所有不同值。距离中心越远,成本函数值 J 越高。
Code 21: Drawing a Contout Plot of J and θ
代码 20 产生以下图形:
Figure 9: The contour plot of J and theta
注意*θ=【128.4;9.9]* 对应的最小值 J (59.7),就是图形中心的红点。蓝点跟踪梯度下降收敛到最小值的路径。**
步骤 14:如何修改多变量代码
我们已经解释了具有一个变量的线性回归的统计机制:SBP 数据集中的特征年龄。这里提出的代码的主要部分也适用于多个变量。SBP 数据集由两个特征(年龄和体重)和一个输出: SBP 。在这一步中,我们将更新代码,使其能够适应多个变量。唯一需要调整的是:
- 数据集上传
- 特征缩放和归一化功能
- 向向量 X 添加一列“1”的代码
- 预测查询。
数据集上传
必须修改上传数据集的代码,以生成新的 X 向量,其中包含每位患者的年龄和体重:
Code 22: The code for uploading the dataset for multiple variables
用于产生新 X 向量的 numpy 方法是。因为我们现在想要一个具有两组不同特征的 X 向量。
特征缩放和归一化功能
在矢量 mu 和 sigma 中修改关于特征缩放和归一化的代码。现在这两个向量将各接受两个参数。
Code 23: The FeatureScalingNormalization function for Linear Regression with Multiple Variables.
向向量 X 添加一列“1”
向 X 向量添加“1”的行修改如下:
Code 24: Adding a column of “ones” to the vector X.
预测查询
预测的查询和归一化的代码修改如下:
Code 25: The Query in Linear Regression with Multiple Variables
在这种情况下,预测结果是 SBP =143.47
有了这些变化,Python 代码就可以进行多变量线性回归了。每次从训练集中添加新功能时,您都必须更新代码!
希望这篇帖子对你有用!
参考文献
- Andrew NG,机器学习| Coursera。
- 约翰·佩祖罗,假人生物统计学,威利,ISBN-13:9781185585
- 施耐德,A;Hommel,G;Blettner,m .科学出版物评价系列的线性回归分析第 14 部分,Dtsch Arztebl Int 2010107(44): 776–82;DOI: 10.3238
- Chris Albon,《Python 机器学习指南》, O'Really,ISBN-13:978–1491989388。
- Aurélien Géron,使用 Scikit-Learn 和 TensorFlow 进行机器学习:构建智能系统的概念、工具和技术,O'Reilly,ISBN-13:978–1491962299。
用于乳腺癌分类和生物标记识别的机器学习模型比较
以 Python 中的配对图和相关矩阵构造为特色。
这个数据集可供公众研究。鸣谢:帕特里西奥,m .,佩雷拉,j .,克里斯索斯托莫,j .,马塔福梅,p .,戈梅斯,m .,塞萨,r .,&卡拉梅洛,F. (2018)。使用抵抗素、葡萄糖、年龄和身体质量指数预测乳腺癌的存在。BMC 癌症,18(1)。
2019 年,美国估计有 268,600 名女性被诊断患有乳腺癌。尽管女性乳腺癌发病率(在 50 岁及以上的女性中)逐渐下降,存活率也有所上升,但仍需要进行研究以解决乳腺癌问题(https://www . national breast cancer . org/breast-cancer-facts)。存活率增加的主要原因之一是更好的筛查和早期检测做法;这可以包括评估生物标记。生物标记是生物体中可测量的物质,如个体的血糖水平,可以作为疾病或感染存在的指标。
这个项目和这篇文章的目标是尝试使用相对少量的数据开发一个强大的预测模型。我的目的是展示机器学习应用中存在的小样本问题,同时探索预测分析在医疗决策中的实际应用。通过利用探索性分析和机器学习模型,我的目标是识别可以指示患者乳腺癌的具有统计意义的生物标记。这个数据集包含 116 行,每行有 9 个属性,一列表示分类。在分类方面,有 64 名乳腺癌患者和 52 名健康对照。116 行对于执行机器学习技术来说相对较低,但尝试各种预测模型是值得的。小样本量在机器学习任务中提出了相当大的挑战,因为过拟合可能导致对一个类别的高偏差。通过合并交叉验证程序,我将尝试最小化隐含的分类偏差。基于给定的变量(或者甚至是所提供的生物标记的小子集)的强预测模型可以用于测试容易收集的生物标记并指示乳腺癌。以下生物标记是该数据集中的属性:
年龄,身体质量指数,葡萄糖,胰岛素,稳态模型评估(量化胰岛素抵抗和β细胞功能)瘦素(小肠中脂肪细胞产生的一种激素,有助于调节能量平衡)脂联素(参与调节葡萄糖水平和脂肪酸分解的蛋白质激素)抵抗素(脂肪储存细胞、免疫细胞和上皮细胞分泌的肽
我采取的第一步是查看特征的描述性统计数据,然后生成一个相关矩阵。在取平均值和查看分布之前,我将数据集除以目标值,以分别查看健康对照组和乳腺癌患者的描述性统计数据。
健康对照组的描述性统计数据:
Those in the healthy control group show what would be considered ‘normal’ levels for these 8 bio-markers.
乳腺癌患者的描述性统计:
Glucose, Insulin, HOMA, Resistin, and MCP-1 levels in breast cancer patients tend to be higher, based on averages, than those in the control group.
这两个阶层的平均年龄相对接近,身体质量指数、瘦素和脂联素值也是如此。值得注意的是,健康对照人群中的最低年龄是 24 岁,而最年轻的乳腺癌患者是 34 岁,尽管他们的平均年龄相似。在健康对照样品(平均 88.23 mg/dL)和乳腺癌患者(平均 105.56 mg/dL)之间的血糖水平有相当大的差异。在基于决策树的模型中,葡萄糖可以作为良好的预测因子或分裂点来对乳腺癌患者进行分类。胰岛素、抵抗素和 MCP-1 遵循相似的趋势,平均而言,乳腺癌患者显示出比健康对照组更高的值。这些生物标志物可能被证明是比身体质量指数、瘦素和脂联素更好的预测因子,但现在下这样的结论还为时过早。
下面,我使用“seaborn”可视化软件包来制作一个配对图。配对图显示了数据集中所有特征之间的关系,包括每个特征的分布。我对数据进行了过滤,橙色的点是乳腺癌数据,蓝色的点是健康的对照患者。因此,我们不仅可以看到所有的变量关系,还可以在类中寻找模式。
年龄、身体质量指数、MCP-1 似乎呈正态分布。葡萄糖、胰岛素、HOMA、瘦素、脂联素和抵抗素具有右偏分布。如果你观察 HOMA 和胰岛素,你会发现散点图中有很强的正线性关系。也就是说,这两个变量之间的关系可以使用直线回归模型精确建模。胰岛素和 HOMA 也是如此。身体质量指数和葡萄糖似乎有一个坚实的集群分离,我们可以看到这两个类存在于各自的领域。如果用在 KNN 模型中,这两个变量以后会成为强有力的特征。
让我们看看这些生物标记中是否有任何一个与另一个高度相关。如果我们试图使用没有相关性或相关性很小的变量来训练机器学习模型,我们的模型将返回不准确的结果。为了制作相关矩阵热图,我引入了 Python 包“seaborn”它将计算两个变量之间关系的正或负线性强度的相关系数可视化。
Values close to 1.0, like 0.93 and 0.7, show a strong positive linear relationship between the two variables while values close to -1.0 show the inverse, strong but negatively correlated.
- 身体质量指数和瘦素的正相关值为 0.57
- 葡萄糖和 HOMA 具有中等强度的正相关值 0.7
- 葡萄糖和胰岛素具有 0.5 的正相关值
- 胰岛素和 HOMA 具有非常强的正相关值 0.93
- 葡萄糖、胰岛素、HOMA 和抵抗素都在高于 0.2 的水平上与分类变量正相关
- 在某种程度上,所有的变量都是相互关联的
接下来,我将测试 sklearn 包提供的各种分类模型,在确定最佳模型后,我将研究它的架构。我使用 sklearn 包中的 train_test_split 函数来创建训练和测试数据集,并应用缩放。需要注意的是,数值的标度并不完全相同,有些数值以 mg/dL、pg/dL 和 kg/m 为单位,因此在将数据输入 ML 模型之前,应用标度函数是一个关键的预处理步骤。
我根据数据训练的第一个模型是逻辑回归,一种简单的分类方法。最初,它在测试数据上返回 62%的准确率,有 8 个假阴性(错过了 8 个癌症样本)和 3 个假阳性(3 个健康样本被分类为癌症)。该模型为预测健康类返回了 57%的精度值和 33%的召回值。由于样本量小,结果初步偏低。对于分类问题中的低样本量,一个很好的补救方法是改变损失函数。分类问题使用交叉熵损失来训练和优化模型,在样本量较低的情况下,模型在尝试优化其损失值时会偏向一个类别。为了补救,我将权重值添加到与不同类别相对应的损失中,以消除偏差。这很容易通过添加参数 class_weight = 'balanced '来实现,该参数查找类权重并平衡数据比率以消除偏差。我使用平衡类权重参数运行另一个逻辑回归模型。
这在测试集上返回了 69%的准确率,提高了 7%,并且我们还消除了 3 个假阴性。
接下来,我使用平衡和非平衡类权重参数训练了一个线性判别分析模型、一个决策树模型和一个 k-最近邻模型。最好的模型是 KNN,准确率为 79%,只有 3 个假阴性和 3 个假阳性。
我试图通过找到 k 的最佳值来调整 k-nn。虽然我能达到的最大精度是 79%,但没有任何改进。
This visualizes the attempt to find the best value for k based on accuracy. We see that 1, 5, 7 are the best values for k when optimizing for accuracy.
对我来说,这个项目的一个重要部分是识别生物标记。我选择训练一个随机森林分类器,这样我们就可以接收一个可变的重要性输出,并查看哪些生物标记被认为是“最重要的”,从统计角度来说,在确定样本是否患有癌症方面。
一个随机森林是许多单个决策树的集合。它将决策树的多数结果作为最终值。最初的随机森林模型表现糟糕,准确率为 58.6%。我使用交叉验证实现了一个随机搜索,以确定随机森林模型的最佳超参数,希望实现更好的准确性和更透明的机器模型。
这段代码构建了一个随机搜索来识别随机森林进行分类的最佳参数。以下代码使用上面定义的随机网格搜索,运行 100 种不同的模型组合,并确定最佳组合。
这些是最佳参数:
{'n_estimators': 266,' min_samples_split': 5,' min_samples_leaf': 1,' max_features': 'sqrt ',' max_depth': 30,' bootstrap': True}
使用可能的最佳随机森林模型,我们实现了 68.97% 的准确度。这个分数与逻辑回归的结果相当,但比 KNN 差。在我看来,随机森林最有用的输出是特征重要性。它显示了哪些变量,从统计学上来说,在进行分类时最重要。这个输出使得随机森林模型不那么像一个抽象的“黑盒”,并且允许我们看一看它是如何做出某些决定的。
基于上面的可变重要性结果,我选择了两个最重要的特征,并将它们可视化,然后应用目前为止表现最好的模型,KNN。
在上面的代码块中,我将 K 的值设置为我之前确定的获得最佳精度的值之一,在本例中是 K = 5。然后,我将 k-最近邻模型仅适用于两个特征:葡萄糖和身体质量指数。
Red = Healthy Controls. Green = Breast Cancer Patients
这种可视化有助于对我们的预测模型进行推断。在大约 90 (mg/dL)葡萄糖水平处,存在垂直截止,其中来自任一类别的一些样品混合。在 120 (mg/dL)之后,所有样品都是乳腺癌患者。
结论
葡萄糖和身体质量指数一起可能是检测乳腺癌的两个强有力的生物标记。对这两个生物标记进行建模,并添加 HOMA 和抵抗素水平(接下来的两个重要特征),我用 k 最近邻法对乳腺癌样本进行分类时达到了几乎 80%的准确率。因此,这个项目表明,结合这四个重要的生物标志物,乳腺癌可以很容易地分类。如果数据集可以扩展,其他方法可能会更准确,比如随机森林。再增加一百个左右的样本有可能返回比 KNN 分类器 80%的准确率更好的结果。这些模型的运行速度也非常快,因此,如果我们能够否定假阳性/假阴性预测(最有可能是由于低样本量导致的偏差),这些模型对于医疗应用来说是实用的。本文旨在展示小样本量对强大的机器学习方法的影响,以及如何轻松地将这些方法用于医疗诊断。
用于内容审核的机器学习—挑战
使用机器学习系统进行内容审核的挑战
概观
有关内容审核的机器学习主题的介绍,请阅读本系列的简介:
用于在线内容审核的机器学习系统综述
towardsdatascience.com](/machine-learning-for-content-moderation-introduction-4e9353c47ae5)
现在,我们已经对用于自动内容审核的机器学习系统进行了概述,我们可以解决这些系统面临的主要挑战。这些潜在的问题可能导致在评估模型、确定接近的分类器阈值以及公平地使用它而没有无意的偏差方面的困难。由于内容审核系统作用于复杂的社会现象,因此它们面临着在其他机器学习环境中不一定会遇到的问题。
不同的定义
对于内容调节的许多应用,很难提供感兴趣现象的明确定义。这些话题往往是非常复杂的社会现象,其定义是学术界不断争论的话题。例如,网络欺凌在学术文本中有各种各样的定义,因此很难创造一个所有人都同意的包罗万象的定义。由于这个原因,提供给手动内容贴标机的说明可能不够清楚,不能产生非常可靠的标签。
https://indigenousx.com.au/is-the-definition-of-racism-racist/
这就导致了两个问题。
首先,如果用户认为违反规则的一些内容被删除而另一些没有被删除,那么对用户来说,内容审核系统似乎是不一致的。这可能会导致用户不信任内容审核机制,或者认为它不公平地针对某些用户。从用户的角度来看,这些系统是模糊的黑匣子,很难解释为什么会出现这种不一致。
另一个问题是,标记的训练数据可能有矛盾的数据点。如果标注不一致导致两个非常相似的数据点具有相反的标注,那么模型的性能可能会受到影响,因为它要努力学习数据中的正确属性和模式。
数据标签可用性
获取标记数据通常是一个成本高昂的过程。对于许多内容审核任务来说,标记任务相对复杂,并且需要训练标记员。他们必须理解特定社会现象的某种定义。这与简单得多的标记任务形成对比,例如确定图像是否包含特定对象。
此外,与图像分类等任务相比,这些任务的公共数据集非常少,因为它们通常被视为收集数据的公司的财产。公司不太可能想要分享这些数据,因为他们认为这是他们竞争优势的一部分。
由于成本很高,可能很难获得足够大的数据集来轻松训练有监督的机器学习模型。为了解决这个问题,机器学习实践者必须经常求助于半监督或弱监督方法来扩充他们的数据集。通常,他们利用一小组手动标记的数据(“黄金标准”数据)来获取其他未标记的提交内容的标签。通过这种方法,他们能够从最初较小的手动标记的数据点池中创建大型数据集。
虽然这些方法很强大,但它们也有自己的问题。“黄金标准”数据中存在的偏差或误差很可能会传播到整个数据集。
算法偏差
当创建作用于社交内容的机器学习模型时,总是存在引入算法偏差的风险。算法偏差指的是一种算法(机器学习模型)创造了一种与某种种族或社会经济因素相关的不公平情况,例如通过不公平地惩罚某些人群,或者通过将人群从平台的其余部分中分割出来。
创建内容审核模型时,尽最大努力避免算法偏差是很重要的。如果您的模型考虑了用户配置文件特征,如位置或人口统计特征,则必须非常小心,以确保模型不会根据这些特征进行辨别。
例如,在网络欺凌检测模型中,如果模型的输入是性别,则它可以学习在涉及某个性别的情况下增加网络欺凌的概率。然而,由于网络欺凌通常更多地发生在该性别的人群中,该模型只是继承了社会的整体偏见。
在这种情况下,机器学习从业者必须小心谨慎,要么不使用某些人口统计特征,要么验证有用,非歧视性模式正在用它们学习。否则,这种模式可能成为歧视性的,并加剧先前存在的社会不平等。
对抗性
自然,对于那些内容被认为违反规则的人来说,这些系统被认为扼杀了他们在平台上的表达自由。因此,这些人通常会尽最大努力继续发布相同类型的内容,同时规避机器学习系统的标记机制。
这与其他机器学习环境非常不同,在其他机器学习环境中,输入数据通常只是原始的传感器数据或金融数据。一旦你将对手引入其中,学习的任务就会变得更加困难和微妙,因为这些对手会不断改变他们的方法以逃避检测。
一个常见的例子是垃圾邮件和诈骗/网络钓鱼检测。为了避免被发现,犯罪分子会尝试许多技术,例如改变文本的大小写和间距,用同义词替换单词,用数字或类似的非标准字符替换字符,以及将其实际内容嵌入到更大的非犯罪内容中。
这些对手愿意不断研究新方法来逃避检测,这意味着机器学习从业者必须不断重新评估他们的模型,以确保它们仍然有效。有时,这可能需要训练新的模型来处理新类别的规避方法。
用于内容审核的机器学习—简介
用于在线内容审核的机器学习系统综述
https://digital.wf.com/treasuryinsights/portfolio-items/tm13050/
概观
随着互联网的社交平台,如脸书和推特,越来越受欢迎,访问量越来越大,提交给它们的内容也越来越多。虽然这些平台的发展带来了许多好处,使人们能够保持相互联系,并在世界各地集体组织起来,但它也带来了一些问题,如假新闻的传播,以及网络欺凌等在线滥用。随着围绕这些互动空间的法律和社会环境的成熟,这些公司监管其平台的负担越来越重。他们对平台的维护和质量越来越负责。
然而,这些平台上有数十亿用户和数百万条消息和照片,这些公司不可能人工检查每一个。相反,他们通常利用机器学习系统来自动解析上传到他们网站的内容。被标记为违反规则的提交内容随后被提交给人工审查人员,他们将对该内容是否应该被允许出现在网站上做出最终判断。
什么内容得到审核?
首先,了解一些内容审核系统通常针对的内容示例非常重要。内容通常通过以下两种方法中的一种来处理,要么在提交可疑的滥用内容之前先发制人地发出警告,要么在事后删除和/或惩罚。
滥用内容
第一类涉及旨在在线骚扰或虐待某人或一群人的内容。这包括各种类型的行为,如:网络攻击、网络欺凌、仇恨言论和 doxxing。虽然这些社会现象中一些有点难以定义,但是公司仍然努力自动检测它们。在发生了几起不幸导致自残和自杀的网络欺凌事件后,脸书和 Instagram 等公司面临着越来越大的压力,要求它们增加报告选项,并加强监管。大多数滥用内容检测方法混合使用自然语言处理、图像处理和社交网络分析。
虚假/误导性内容
下一类涉及虚假或误导的内容,旨在利用社交网络加速虚假信息的传播,通常以新闻文章的形式出现。最常见的是,我们在带有政治色彩的短语“假新闻”下听到这些内容。检测假新闻是一个开放的研究领域,存在许多挑战,因为不可能手动检查每篇文章。当前的方法使用各种方法,例如结合大的一般/常识知识库、自然语言处理,以及通过社交网络分析和内容的风格元素结合各种基于声誉的因素。
裸露/露骨的内容
下一类涉及裸体和露骨的性内容。这通常通过图像处理方法来检测。不同的平台对此有不同的立场——例如,Instagram 根本不允许,而 Reddit 允许所有(合法)情况下的这种行为。最值得注意的是,Tumblr 最近决定改变他们对露骨内容的政策,并禁止色情和大多数裸体案例。
诈骗/网络钓鱼/黑客攻击
最后,我们有针对平台上用户的诈骗、网络钓鱼或黑客内容。这种类型的内容通常会试图让用户离开平台,使用另一个网站。在这个外部网站上,用户通常会被诱骗提交个人信息,或者向非预期方汇款。这通常是通过模仿原始网站上的 URL(通常通过同形异义攻击)或者通过使用外部网站向用户承诺更好的购买交易来实现的。这种内容通常通过自然语言处理、已知网络钓鱼链接的集合以及通过社交网络分析和账户因素的基于声誉的因素来检测。
https://www.pcmag.com/article/364947/how-to-avoid-phishing-scams
适度是如何发生的?
现在,我们已经了解了常见的审核内容类型,我们可以了解一下大多数自动内容审核系统是如何工作的。这通常发生在两个主要阶段。
自动标记
首先,当然,内容是由用户创建和提交的。
如果基于一些基本检查,该用户被认为是违规者或者内容非常明显地违反了规则,则该用户可能会被屏蔽,并且内容可能会自动隐藏,而他们并不知道。
否则,计算特征以输入到内容审核机器学习模型中。如果这些特征不是内容本身的函数(例如用户特征),则这些特征中的一些可能已经通过预定的批处理系统进行了计算,而如果这些特征是从提交的内容中直接导出的(例如涉及文本或图像的特征),则这些特征中的另一些可能是即时计算的。此外,提交后,如果内容被其他用户手动标记,它可能会被重新处理。
基于这些特征,机器学习模型输出可以被解释为概率的分数。如果这个分数高于某个阈值,该内容就会被标记为人工审查,因为它被怀疑违反了平台的规则。自然,由于这些企业的目标是优化其支出,因此通常会严格选择该阈值,以便优化某种衡量标准,平衡违规成本和人工标记成本。
人类评论
一旦内容被标记,它就会被传递给人工审阅者进行人工检查。他们通常会接受少量培训,以识别违规内容。这些人工审阅者操作非常快,可能只花几秒钟来审阅每一条内容。由于他们每天必须查看的内容类型,这些员工的工作条件被认为是有问题的。
在审查内容之后,审查者然后对内容是否违反任何规则做出最终判断。通常,每份提交的材料将被分配给几个评审员(~5 个),以便有希望消除由标签错误或不同解释引起的不一致的结果。
一旦有了最终的标签,如果内容违反了任何规则,就会被处理。这通常意味着内容被删除。用户的账户也可能被处罚或删除。
最后,这段内容随后被存储在其给定的标签旁边。内容标记机器学习模型的未来迭代将最有可能在其训练集中使用这一新数据。通过这一过程,没有数据被浪费,模型能够不断地被重新训练,并能够适应用户提交的变化模式。
用于客户分析的机器学习— 1
使用逻辑回归预测顾客反应
Photo by Ibrahim Rifath on Unsplash
语境
个人贷款是银行的主要收入来源,所有银行都主动接触潜在客户,为他们的贷款产品进行宣传。这些营销活动大多针对随机的客户数据库,因此最终会变成烦人的电话营销,而不是有效的线索转化手段。
在这篇文章中,我们将看到如何利用机器学习的力量将活动瞄准正确的客户群,从而增加转化倾向。我们将使用已响应和未响应个人贷款活动的客户的人口统计、银行详细信息和交易模式的过去可用数据,作为预测客户是否会响应活动的概率的训练数据。
在机器学习术语中,这是一个分类问题,有几种分类算法可用于构建预测模型,我们将使用逻辑回归。
关于逻辑回归
逻辑回归是一种流行且强大的监督机器学习技术,用于建立将独立预测因子(x 变量)与本质上是分类的响应变量(y)相关联的模型。在已知类的情况下,根据数据集中的预测变量,它可以帮助找到区分不同类中记录的因素。
当结果变量只有两类时(例如:通过/失败;欺诈/非欺诈;默认/无默认)如果我们有两个以上的类别(例如:买入/卖出/持有),则应用二项式逻辑回归和多项式逻辑回归。
逻辑回归是一种统计技术,它根据预测变量的统计显著性以及每个预测变量如何影响 Y 变量类别的概率来提供详细的统计摘要。这些独特的品质使该算法与银行和金融领域高度相关,以提供预测变量的详细和数字解释。
资料组
我们有一个数据集,它提供了一家银行执行的“个人贷款”活动的详细信息。向 20,000 名客户提供 14%利率的个人贷款,其中 2512 名客户积极响应。数据集和数据字典可以从这里下载。
高级方法
下面的流程图描述了我们使用逻辑回归寻找分类问题解决方案的高级方法,从定义问题陈述开始,到计算新客户分类模型的准确性。
High Level Approach
问题定义
我们将使用逻辑回归建立一个模型,预测客户对个人贷款活动的反应倾向(概率)。模型中的概率将用于对结果进行分类,并确定影响反应的变量。目标是建立一个模型,确定在未来的个人贷款活动中最有可能接受贷款的客户。
数据清理和准备
作为第一步,我们设置工作目录并将 csv 格式的数据集读入 R:
## Setting working directory and reading the csv file**setwd("F:/DataScience/BLOG/LogRegproject1")****loanorg <- read.csv("PLXSELL.csv")**
接下来,我们使用 R 中的基本命令查看数据集,以了解列及其数据类型,以及存在的记录数量。
## View the dataset using View, str, names in R**View(loanorg)** *(output not shown here)***dim(loanorg)** [1] 20000 40**names(loanorg)** ## [1] "CUST_ID" "TARGET"
## [3] "AGE" "GENDER"
## [5] "BALANCE" "OCCUPATION"
## [7] "AGE_BKT" "SCR"
## [9] "HOLDING_PERIOD" "ACC_TYPE"
## [11] "ACC_OP_DATE" "LEN_OF_RLTN_IN_MNTH"
## [13] "NO_OF_L_CR_TXNS" "NO_OF_L_DR_TXNS"
## [15] "TOT_NO_OF_L_TXNS" "NO_OF_BR_CSH_WDL_DR_TXNS"
## [17] "NO_OF_ATM_DR_TXNS" "NO_OF_NET_DR_TXNS"
## [19] "NO_OF_MOB_DR_TXNS" "NO_OF_CHQ_DR_TXNS"
## [21] "FLG_HAS_CC" "AMT_ATM_DR"
## [23] "AMT_BR_CSH_WDL_DR" "AMT_CHQ_DR"
## [25] "AMT_NET_DR" "AMT_MOB_DR"
## [27] "AMT_L_DR" "FLG_HAS_ANY_CHGS"
## [29] "AMT_OTH_BK_ATM_USG_CHGS" "AMT_MIN_BAL_NMC_CHGS"
## [31] "NO_OF_IW_CHQ_BNC_TXNS" "NO_OF_OW_CHQ_BNC_TXNS"
## [33] "AVG_AMT_PER_ATM_TXN" "AVG_AMT_PER_CSH_WDL_TXN"
## [35] "AVG_AMT_PER_CHQ_TXN" "AVG_AMT_PER_NET_TXN"
## [37] "AVG_AMT_PER_MOB_TXN" "FLG_HAS_NOMINEE"
## [39] "FLG_HAS_OLD_LOAN" "random"
在查看和研究数据集后,我们推断:
- 有 20,000 个观察值和 40 个变量。
- 我们混合了整数、数字和因子变量。
- 分类响应变量表示客户是否对活动做出响应,该变量称为“目标”。[0 -未回应/ 1 -已回应]
根据数据探索,我们还注意到需要以下操作来准备数据集以供进一步分析:
- 列 CUST_ID 和“随机”不是必需的,因为这些列是用于用一些 ID 表示调查参与者的(它们既不是 x 变量也不是 y 变量)。
##remove unwanted columns CUST_ID and random**loancamp <- loanorg[,-c(1,40)]**
- 有些变量的相同数据由数据集中的其他变量表示。分别是 AGE_BKT(用 AGE 表示)和 ACC_OP_DATE(用' LEN_OF_RLTN_IN_MNTH '表示)。因此,年龄 _BKT 和 ACC_OP_DATE 可以从数据集中删除。
## remove columns AGE_BKT and ACC_OP_DATE**loancamp$AGE_BKT <- NULL
loancamp$ACC_OP_DATE <- NULL**
- 分类变量 TARGET,OLD _ 哈斯 _CC,OLD _ 哈斯 _ANY_CHGS,OLD _ 哈斯 _NOMINEE,OLD _ 哈斯 _OLD_LOAN 表示为整数数据类型。这些在 r 中被转换成范畴类型。
## Convert variables into correct datatypes (FLG_HAS_CC, FLG_HAS_ANY_CHGS, FLG_HAS_NOMINEE, FLG_HAS_OLD_LOAN, TARGET should be categorical)**loancamp$TARGET <- as.factor(loancamp$TARGET)
loancamp$FLG_HAS_CC <- as.factor(loancamp$FLG_HAS_CC)
loancamp$FLG_HAS_ANY_CHGS <- as.factor(loancamp$FLG_HAS_ANY_CHGS)
loancamp$FLG_HAS_NOMINEE <- as.factor(loancamp$FLG_HAS_NOMINEE)
loancamp$FLG_HAS_OLD_LOAN <- as.factor(loancamp$FLG_HAS_OLD_LOAN)****str(loancamp)**
四个不需要的列已被删除,上面列出的五个变量的数据类型已被更正。
让我们检查数据集中是否有缺失的值:
## Check for missing values in any of the columns**colSums(is.na(loancamp))**
数据集中没有缺失值。
既然数据集已准备好进行建模,让我们检查数据集中观察结果的基准客户响应率:
##Calculate baseline conversion rate**respons_rate <- round(prop.table(table(loancamp$TARGET)),2)
respons_rate**0 1
0.87 0.13
我们可以看到数据集明显不平衡—只有 13%的客户记录有响应(类别 1),而其余 87%的记录没有响应(类别 0)。这将对模型性能度量产生影响,我们将在本分析的后面部分详细了解这一点。
探索性数据分析
在本节中,我将使用 r 中的 ggplot2 以数据可视化的形式进一步探索数据集。这将有助于初步了解数值变量的分布以及影响响应变量的重要特征。
单变量分析
重要独立数值变量的直方图
## EDA - histogram plot for important numeric variables**library(ggplot2)
library(cowplot)****ggp1 = ggplot(data = loancamp, aes(x = AGE))+
geom_histogram(fill = "lightblue", binwidth = 5, colour = "black")+
geom_vline(aes(xintercept = median(AGE)), linetype = "dashed")**
Histogram of Numeric Variables
从直方图中我们可以看出
- 年龄的频率分布显示,26-30 岁年龄组的目标客户最多。
- 持有期(在账户中持有资金的能力)和与银行的关系长度或多或少是平均分布的。
- 这些客户的大部分信用交易在 0-15 英镑之间,而借贷交易少于 10 英镑。
重要独立数值变量的箱线图
Box plot of Numeric Variables
从箱线图中,我们可以直观地推断出:
- 箱线图显示了数字变量的以下中值:年龄约为 38 岁,持有期即在账户中持有资金的能力为 15 个月,与银行的关系长度为 125 个月,信贷交易次数为 10,借贷交易次数为 5。
- 对于变量信贷交易数量和借贷交易数量,存在许多异常值。
重要分类变量的柱状图
Bar plot of Categorical Variables
我们可以从柱状图中推断出
- 在贷款活动中,近四分之三的目标客户是男性。
- 工薪阶层和专业阶层构成了大部分目标客户。
- 四分之一的顾客有信用卡
- 数据集中有相同比例的客户有旧贷款或没有贷款。
双变量分析
数值变量与目标( y 变量)的箱线图
#bivariate analysis of AGE, LEN_OF_RLTN_IN_MNTH,HOLDING_PERIOD against TARGET**ggbi1 = ggplot(data = loancamp, aes(x = TARGET, y = AGE, fill = TARGET))+geom_boxplot()
ggbi2 = ggplot(data = loancamp, aes(x = TARGET, y = LEN_OF_RLTN_IN_MNTH, fill = TARGET))+geom_boxplot()
ggbi3 = ggplot(data = loancamp, aes(x = TARGET, y = HOLDING_PERIOD, fill = TARGET))+geom_boxplot()
plot_grid(ggbi1, ggbi2, ggbi3, labels = "AUTO")**
Box plot for numeric variables vs TARGET
当我们根据分类目标变量查看数值变量的双变量分析的数据可视化时,我们获得了以下见解:
年龄与目标(目标:响应贷款活动= 1;未响应贷款活动= 0)
对活动做出回应的客户的年龄中位数略高于未做出回应的客户。尽管这两个阶层在年龄上没有太大区别,我们也从与银行关系的月数与目标阶层的时间长度中得出这一推论。
对个人贷款活动做出响应的客户中,平均持有期(在账户中持有资金的能力)较短,约为 10 个月。
分类 x 变量与目标( y 变量)的堆积条形图
Stacked Bar plot for Categorical x variables vs TARGET
使用堆积条形图对分类 x 变量和目标 y 变量进行双变量分析有助于我们直观地了解以下情况:
- 我们发现,与女性客户相比,更多的男性客户(约 25%)对该活动做出了回应(相比之下,“其他”类别下的客户总数非常少)。
- 与工薪阶层的顾客相比,个体经营的顾客对利用个人贷款更感兴趣。
- 17%在银行有往来账户并被联系贷款的客户表示有兴趣,相比之下,有储蓄账户的客户有 11%表示有兴趣。
- 客户有未决的费用要支付给银行或没有未决的费用,似乎对响应或不响应活动没有任何影响。我们看到在银行有旧贷款的客户也有类似的模式。
- 与没有信用卡的顾客相比,持有信用卡的顾客对贷款更感兴趣。
将数据集分为开发(定型)集和维持(验证或测试)集
接下来,我们将把数据集分成训练数据集和测试数据集。我们将基于训练数据集构建模型,并使用测试数据集测试模型性能。
## split the dataset into training and test samples at 70:30 ratio**library(caTools)****set.seed(123)****split = sample.split(loancamp$TARGET, SplitRatio = 0.7)
devdata = subset(loancamp, split == TRUE)
holddata = subset(loancamp, split == FALSE)**## Check if distribution of partition data is correct for the development dataset**prop.table(table(devdata$TARGET))
prop.table(table(holddata$TARGET))**
上面的 prop.table 输出证实了我们在原始数据集中看到的不平衡数据集特征在开发和保留样本中保持相同的比例。
现在,训练数据集已准备好构建模型。
建立基于逻辑回归的预测模型
逻辑回归的步骤
步骤 1:对训练数据运行逻辑回归
在 R 中使用广义线性模型命令 glm 来使用逻辑回归建立模型。
**library(glmnet)
logreg = glm(TARGET ~., data=devdata, family="binomial")**
步骤 1a:可变膨胀系数检查
让我们根据生成的模型,通过可变通货膨胀系数(VIF)检查来检查 x 变量之间的多重共线性。
**library(car)****vif(logreg)**
VIF 值大于 4 的要素(x)变量表示高度多重共线性。
从下表中,我们注意到以下变量具有大于 4 的 VIF 值:远程登录数量、远程登录数量、远程登录数量、远程登录数量、远程登录数量、远程登录数量、远程登录数量、AVG 远程登录数量、远程登录数量、远程登录数量。
VIF output showing variables with VIF value above 4
我们从训练和测试数据集中删除这些具有高度多重共线性的 x 变量,并重新运行模型。这将有助于确定明显影响响应变量(TARGET-y 变量)的变量,并建立一个可以更准确地对记录进行分类的模型。
重复这个过程,直到我们得到值低于 4 的干净的 VIF 输出。
步骤 2:模型的总体意义
**library(lmtest**) **lrtest(logreg1)**
我们可以看到,低 p 值表明模型非常重要,即客户对活动(目标)做出反应的可能性取决于数据集中的独立 x 变量。
第三步:麦克法登或伪 R 解读
**library(pscl)****pR2(logreg1)**
基于麦克法登 R 的值,我们可以得出结论,仅截距模型的 8.7%的不确定性是由完整模型(当前 x 变量)解释的。该值表示拟合优度低。这可能表明需要添加更多的 x 变量来解释响应(y)变量的变化。
第四步:个别系数的意义和解释
**summary(logreg1)**
从生成的模型的总结中,我们推断有一些 x 变量基于它们的 p 值是显著的。这些是影响客户对活动做出回应的 x 变量,如下表所示。
每个 x 变量的比值比和概率是基于公式计算的,
优势比= exp(系数估计值)
概率=优势比/ (1 +优势比)
Summary of Logistic Regression Model with Odds Ratio and Probability
逻辑回归总结的推论:
- 如果客户是个体户,他回应的几率是不回应的 1.88 倍。换句话说,他响应竞选的概率是 65%。
- 如果他有一张信用卡,那么响应竞选的几率是 1.84。
- 如果客户有旧贷款或属于工薪阶层,那么他们响应活动的概率会下降到 50%以下,即他们不太可能响应。
预测验证数据
使用我们刚刚构建的模型,让我们尝试预测验证样本中记录的倾向和类别。请注意,我们已经知道了这些记录的类,并将使用该输入来比较和发现新模型在分类新记录时有多好。
**holddata1.predict.score=predict(logreg1,newdata = holddata1, type="response")**
该模型具有验证集中各个记录的输出倾向。
为了确定基于概率对记录进行分类的临界值,我们查看预测概率的分布。
如果我们看一下分布,大多数记录的概率值都在 10%以下。因此,我们使用临界值 0.1 来预测记录的类别。
## Assgining 0 / 1 class based on cutoff value of 0.1
**holddata1$Class = ifelse(holddata1.predict.score>0.1,1,0)**
模型已经预测了每条记录的类别(目标值 0 或 1)。让我们创建混淆矩阵,看看模型根据验证集中这些记录的已知目标值对记录进行分类的效果如何。
模型性能—混淆矩阵
混淆矩阵提供了模型准确性的清晰快照。
## Creating the confusion matrix
**tabtest=with(holddata1, table(TARGET,Class))****tabtest**
Confusion Matrix of Test Data
在这里,敏感性比准确性更重要,因为我们更感兴趣的是了解客户会对新活动做出反应的所有记录,而不是客户可能根本不会做出反应的记录。由于模型分类(敏感性)不正确,联系潜在客户(该客户将获得贷款并因此向银行支付利息)的机会成本损失比由于分类不正确(特异性)而收到邮件或电话的潜在无响应客户更为严重。
当我们比较训练数据和测试数据之间的模型性能度量时(见下表),模型对测试数据保持良好,而性能度量没有显著下降。这表明模型中没有过度拟合。
为了使用该模型预测类别,我们有意识地在准确性上做出妥协,以获得更好的敏感性,即不会失去对贷款活动做出反应的潜在客户。
可行的见解
基于上述模型,我们可以向银行提出以下建议:
- 不要给随机的一组客户打电话,而是瞄准具有以下一种或多种特征的客户——男性客户、个体户、持有信用卡、在银行有过或曾经有过一些费用。
- 避免联系已经贷款和/或工薪阶层的客户。
结论
在这里,我们使用了二项式逻辑回归技术,不仅预测了响应贷款活动的客户类别,还获得了影响客户对活动响应的统计显著性独立变量列表。我们还能够根据模型摘要预测客户响应或不响应的概率。这些提供了强有力的见解,将有助于提高客户的回应率,从而转化为银行贷款。
资源
面向数据分析师的机器学习— BigQuery ML
BigQuery 中使用 SQL 的机器学习介绍
数据分析包括分析原始数据,以提取有价值的见解。这些见解经常被用作未来决策的辅助手段。
被分析的数据通常以一种或多种格式存储。这些可以是平面文件或文本文件(逗号分隔,制表符分隔),电子表格(Excel,Google Sheets),数据库和其他格式。
我第一次使用结构化查询语言(SQL)是在 2000 年左右的 MySql 早期版本。当时,我不得不访问该网站下载安装程序(我使用的是 Windows)和文档。正是从那里,我了解了 DML 和 DDL。那时,我必须下载并安装软件,并决定我想要运行什么引擎,如果我想要复制,我必须自己设置它。我不得不关注性能调优,当我的负载增加时进行扩展,并想出如果我的存储空间用完了该怎么办。
多年来,我一直在使用其他数据库,包括来自微软、甲骨文和 IBM 的产品。
虽然许多数据库供应商已经转而提供托管服务,但有一家供应商让我印象深刻。这是谷歌的 BigQuery。Google 云平台是一个很棒的产品,但是现在让我们只关注 BigQuery。
BigQuery 是谷歌提供的无服务器服务。这意味着,您不需要调配或管理它。您不需要指定打算使用多少存储空间,也不需要指定希望将哪种处理器连接到数据库服务器。相反,它会扩展以适应您的工作需求。
它能够存储大量的数据。然而,它是为数据分析工作负载而设计的,这意味着它不希望您存储的数据频繁更改。如果你来自旧数据库的世界,它是为 OLAP 设计的,而不是 OLTP。
BigQuery 将在没有任何准备的情况下存储数千万亿字节的数据。您可以通过实现分区策略来帮助您的情况,这将大大加快您的数据检索。我还需要提一下,数据检索已经很快了,你不用做任何事情。
您可以通过查看它们托管的公开可用的数据集来开始使用 BigQuery。你可以在这里找到那些。
将您自己的数据导入 BigQuery 非常容易。从 BigQuery 控制台,您可以单击项目名称并创建数据集。一旦有了数据集,就可以继续创建表或将数据导入表中。
BigQuery Console
查询要求您指定项目、数据集以及表名。下面是一个查询示例。
#standardSQL
SELECT
weight_pounds,
state,
year,
gestation_weeks
FROM
`bigquery-public-data.samples.natality`
ORDER BY
weight_pounds
DESC
LIMIT 10;
Query Result
按住 Command(或 Windows 中的 CTRL)并单击查询中的表名,将显示表的详细信息。您还可以访问表模式。
在查询编辑器下面的栏中,有一个验证器,它告诉您查询是否有效,以及如果您要执行它,该查询将处理多少数据。
Query Validator
将数据导入 BigQuery 的一种流行方式是将文本文件上传到 Google 云存储桶中。从那里,您可以将 BigQuery 指向该文件,并将其导入到一个表中。
Table Creation
Specifying Details during Table Creation
一旦将数据导入 BigQuery,就可以继续运行查询了。
查询很有趣。它们告诉你已经发生了什么,让你清楚地了解过去。你可以称之为描述性分析。我卖出了多少件商品,订单多长时间来一次,特定商品在一周的哪几天卖得最多?
查询能告诉你未来会发生什么吗?你能根据一天中的时间预测销售额,同时考虑季节性吗?
我们正在进入预测分析的领域,更正式的名称是机器学习。我们需要从我们的数据中提取洞察力,这将让我们对以前看不见的数据做出预测,但首先,我们试图解决的问题需要被框住。机器学习本身分为三类:监督学习、非监督学习和强化学习。本文将关注前两者。
监督学习处理的情况是,你想要预测的内容包含在你已经收集的数据中。考虑这样一种情况,您希望根据一天中的时间和日期来预测供应商可能售出的水瓶数量。这叫做回归。您试图预测的值称为标签或目标,您用来进行预测的信息称为特征。
考虑另一个场景,你试图预测的是电子商务网站的访问者是否会购买。这叫做分类。这仍然是监督学习,因为你需要历史数据来显示你网站的访问者是否进行了购买。
无监督学习处理的是有历史数据但没有标签的情况。例如,您有关于客户交易的数据,并且您希望将这些交易放入聚类中,以便进行营销或新产品开发。
一种训练机器学习模型的方法涉及最小化损失。你可以在这里快速入门。所有这些都涉及到大量的数学和统计,以及行业专用术语,如优化器、梯度下降、学习率、过拟合和欠拟合、偏差-方差权衡、超参数调整,以及许多普通数据分析师可能不想涉及的词汇。还有一个事实是,处理编程语言是强制性的。
谷歌的 BigQuery 团队认为,如果数据分析师可以训练机器学习模型,而不必在只使用 SQL 的情况下处理大部分数学和术语,那就太好了。这就产生了 BigQuery ML 。
BigQuery ML(也称为 BQML)支持线性回归、二元逻辑回归(两个类之间)、多类逻辑回归(属于多个类中的一个)和 k-means 聚类(用于数据分段的无监督学习)。
BigQuery ML 出奇的简单。您需要了解的第一个对象是model
。与表和视图类似,模型存储在数据集中。
创建模型由两部分组成。第一部分指定模型参数,包括数据集和模型的名称以及模型的类型。第二部分指定用于训练的数据,并包括标签。不是标签的每一列都被认为是特征。
考虑下面的查询。
第一行通过指定数据集和名称来定义模型。第二行将模型类型指定为逻辑回归。随后的几行通过从 BigQuery 公共数据集中获取一些数据来提供训练数据,该公共数据集中托管了一些来自电子商务站点的数据。注意,选择有一个名为标签的列,这就是我们试图预测的。另外,请注意,它被设置为 0 或 1,因为计算机喜欢处理数字。查询中的两个新内容是表名如何使用通配符和表后缀范围。以上是 BigQuery 的一些特性,很容易学习。
逻辑回归模型给出了数据归入我们表示为 1 的一类的概率。如果概率低于 50%,则数据属于表示为 0 的替代类。50%是一个阈值,您可以根据自己的需要进行更改。你可以在这里了解更多。
创建模型时要记住的一点是,标签列不能是NULL
。
create model
的语法如下:
{CREATE MODEL | CREATE MODEL IF NOT EXISTS | CREATE OR REPLACE MODEL}
[model_name](https://cloud.google.com/bigquery-ml/docs/reference/standard-sql/bigqueryml-syntax-create#model_name)
[OPTIONS([model_option_list](https://cloud.google.com/bigquery-ml/docs/reference/standard-sql/bigqueryml-syntax-create#model_option_list))]
[AS [query_statement](https://cloud.google.com/bigquery-ml/docs/reference/standard-sql/bigqueryml-syntax-create#query_statement)]
model_type
可以是logistic_reg
、linear_reg
或kmeans
。
如果你对机器学习有所了解的话,不妨具体说明一下:l1_reg
、l2_reg
、max_iteration
、learn_rate_strategy
、learn_rate
、early_stop
、data_split_method
、data_split_col
、ls_init_learning_rate
、warm_start
。这些参数都在这里描述。
当模型完成训练时,您将得到确认,并且该模型将出现在您的数据集中。
Result of model training
您可能对培训选项感兴趣,当您向下滚动描述页面时会看到这些选项。
Model Training Options
您可以单击“培训”按钮打开选项卡,看到类似以下内容:
Training Report
该信息也以表格形式提供。在每次迭代中,您可以看到训练数据和评估数据的损失是如何减少的。您还可以看到用于该训练迭代的学习率。
Training Report
还提供了评估指标。你可以在找到更多关于精确和回忆的信息。你可以在这里找到更多关于 ROC 的信息。混淆矩阵告诉你模型的准确性,即预测正确的百分比。
Evaluation Metrics
模型需要用一种叫做评估数据集的东西来评估。本质上,您并没有使用所有的数据来训练模型。相反,您应该留出 20%到 30%的数据来评估模型的质量。模型评估的语法如下:
ML.EVALUATE(MODEL [model_name](https://cloud.google.com/bigquery-ml/docs/reference/standard-sql/bigqueryml-syntax-evaluate#eval_model_name)
[, {TABLE [table_name](https://cloud.google.com/bigquery-ml/docs/reference/standard-sql/bigqueryml-syntax-evaluate#eval_table_name) | ([query_statement](https://cloud.google.com/bigquery-ml/docs/reference/standard-sql/bigqueryml-syntax-evaluate#eval_query_statement))}]
[, STRUCT(<T> AS [threshold](https://cloud.google.com/bigquery-ml/docs/reference/standard-sql/bigqueryml-syntax-evaluate#eval_threshold))])
为了评估模型,您调用ML.EVALUATE()
函数。型号名称是必需的。如果不想使用 50%,可以选择传入一个评估数据集和一个阈值。下面是我们如何评估上面创建的模型。
模型评估的结果如下所示:
The output from model evaluation
在处理二元分类模型时,您可能会对称为接收器操作特性曲线的东西感兴趣。其语法如下:
ML.ROC_CURVE(MODEL [model_name](https://cloud.google.com/bigquery-ml/docs/reference/standard-sql/bigqueryml-syntax-roc#roc_model_name)
[, {TABLE [table_name](https://cloud.google.com/bigquery-ml/docs/reference/standard-sql/bigqueryml-syntax-roc#roc_table_name) | ([query_statement](https://cloud.google.com/bigquery-ml/docs/reference/standard-sql/bigqueryml-syntax-roc#roc_query_statement))}]
[, GENERATE_ARRAY([thresholds](https://cloud.google.com/bigquery-ml/docs/reference/standard-sql/bigqueryml-syntax-roc#roc_thresholds))])
这就是我们如何为我们的模型生成 ROC 曲线。
运行上述查询的结果类似于以下内容:
ROC Curve
最后,在处理分类模型时,您可能会对混淆矩阵感兴趣。这是一个交叉列表,列出了哪些是正确分类的,哪些不是。例如,使用二进制分类,我们得到四个单元:真阳性、真阴性、假阳性和假阴性。其语法如下:
ML.CONFUSION_MATRIX(MODEL [model_name](https://cloud.google.com/bigquery-ml/docs/reference/standard-sql/bigqueryml-syntax-confusion#eval_model_name)
[, {TABLE [table_name](https://cloud.google.com/bigquery-ml/docs/reference/standard-sql/bigqueryml-syntax-confusion#eval_table_name) | ([query_statement](https://cloud.google.com/bigquery-ml/docs/reference/standard-sql/bigqueryml-syntax-confusion#eval_query_statement))}]
[, STRUCT(<T> AS [threshold](https://cloud.google.com/bigquery-ml/docs/reference/standard-sql/bigqueryml-syntax-confusion#eval_threshold))])
当生成混淆矩阵时,我们的模型的查询看起来是这样的:
混淆矩阵看起来如下所示:
Confusion Matrix
我们终于准备好利用我们的模型通过ML.PREDICT()
进行预测了。你可以在这里找到更多关于这个函数的行为。语法如下:
ML.PREDICT(MODEL [model_name](https://cloud.google.com/bigquery-ml/docs/reference/standard-sql/bigqueryml-syntax-predict#predict_model_name),
{TABLE [table_name](https://cloud.google.com/bigquery-ml/docs/reference/standard-sql/bigqueryml-syntax-predict#predict_table_name) | ([query_statement](https://cloud.google.com/bigquery-ml/docs/reference/standard-sql/bigqueryml-syntax-predict#predict_query_statement))}
[, STRUCT<threshold FLOAT64> settings)])
以下查询显示了我们将如何使用我们的模型进行预测。没有标签的查询被用作预测的输入。
输出将包含一个predicted_label
列,这是模型做出的预测。使用分类模型,您还会得到一个概率列。
Model Prediction
总之,BQML 使得为回归、分类和聚类创建机器学习模型成为可能。虽然这篇文章将带您走上构建模型的道路,但它不会让您擅长于此。你至少需要很好地理解机器学习理论。
你需要知道什么是学习率,梯度下降是如何工作的,偏差-方差权衡,正则化,提前停止,以及其他机制。了解这些东西的一个好地方是谷歌的机器学习速成班,可以在这里找到。
最需要学习的是特征工程。您需要理解数据,以及特征之间的相关性意味着什么。正是特征工程最终导致了好的模型。
通过机器学习清理和统一您的数据
Photo by Mike Kononov on Unsplash
数据科学家今天面临的最大问题是脏数据。当涉及到真实世界的数据时,不准确和不完整的数据是常态而不是例外。问题的根源在于记录的数据不符合标准模式或违反完整性约束的来源。结果是脏数据被传送到下游的系统,如数据集市,在那里很难清理和统一,从而使其不可靠地用于分析。
如今,数据科学家在应用任何分析或机器学习之前,往往会花费 60%的时间清理和统一脏数据。数据清洗本质上是删除错误和异常,或者用数据中的真实值替换观察值,以在分析中获得更多价值的任务。有传统类型的数据清理,如输入缺失数据和数据转换,也有更复杂的数据统一问题,如重复数据删除和修复完整性约束违规。所有这些都是相互关联的,理解它们是什么很重要。
数据清理和统一问题
模式映射查看多个结构化数据,并判断它们是否以相同的方式谈论同一件事情。在下面的例子中,“建筑#”和“建筑代码”都代表建筑编号吗?
Schema Mapping
记录关联是指在数据中多次提到同一个现实世界的实体。每个源的不同格式样式导致记录看起来不同,但实际上都指向同一个实体。在下面的例子中,所有四个表记录都指向同一个医学实验室。
Record Linkage & Deduplication
缺失数据是指数据集中缺失的值。缺失值插补是用替代值替换缺失数据的过程。实际上,问题更复杂,因为丢失的数据不是由空值表示,而是由垃圾表示,如下例所示。
Missing Data
完整性约束确保数据遵循功能依赖性和业务规则,这些规则规定了哪些值可以合法地共存。从数据中推导出约束可能非常困难,尤其是因为大多数数据关系并不明显。在下面的例子中,简·史密斯是医学实验室和管理大楼的大楼经理,这违反了业务规则。根据这条规则,要么简·史密斯不是这两栋楼的管理人员,要么医学实验室实际上是一栋管理大楼,要么管理大楼是一个医学实验室。
Integrity Constraint
上面我们已经看到了一些数据质量挑战。问题是,大多数数据科学家都在使用基于规则的工具和 ETL 脚本,它们孤立地处理每一个数据质量问题。然而事实是,大多数数据(如下图所示)通常都存在数据质量问题,并且它们以复杂的方式相互作用。问题不仅仅是工具不能处理数据质量问题之间的交互。由于高水平的计算,这些解决方案甚至不能在大型数据集上很好地扩展,并且在进行足够的校正之前需要多次通过。
Most datasets contain several data quality issues (source)
用于数据清理和统一的机器学习
考虑到当前解决方案的问题,科学界正在倡导用于数据清理的机器学习解决方案,这些解决方案以整体方式考虑所有类型的数据质量问题,并可扩展到大型数据集。
实体解析是数据统一任务的一个很好的例子,其中机器学习是有用的。实体解析中涉及的三个主要任务是重复数据删除、记录链接和规范化。重复数据消除的核心是消除重复数据的重复拷贝。通过记录链接,我们的目标是识别引用不同来源的相同实体的记录。规范化是指我们将具有多种表示形式的数据转换成标准形式。这些任务可以被描述为“分类”和“聚类”练习,通过足够的训练,我们可以开发模型来将记录对分类为匹配或不匹配,并将记录对聚类成组以选择最佳记录。
下图直观地展示了这一过程。
The deduplication process (source)
python 重复数据删除库是可扩展 ML 解决方案的一个示例,用于跨不同的结构化数据集执行重复数据删除和记录链接。为了有效地工作,重复数据删除依靠领域专家将记录标记为匹配或不匹配。领域专家很重要,因为他们擅长识别哪些字段最有可能唯一地标识记录,并且他们可以判断记录的规范版本应该是什么样子。
记录修复是 ML 在数据清理中的另一个应用,也是统一项目的一个重要组成部分。修复记录主要是预测源数据记录中错误或缺失属性的正确值。关键是建立一个模型,结合完整性约束、外部知识和定量统计等信号,对缺失或错误值进行概率推断。
HoloClean 系统是 ML 解决方案的一个这样的例子,其中用户提供要被清理的数据集和一些高级域特定信息,例如参考数据集、可用的规则和约束以及数据库内类似条目的例子。然后,系统修复从冲突和拼写错误的值到离群值和空条目的错误。在下面的例子中,用户可以指定拒绝约束(捕获领域专业知识的一阶逻辑规则),如城市、州、地址- >邮政编码,以确定行 1 与行 2 和行 3 中的信息冲突。
Repairing Integrity Constrain Violations (source)
提供可扩展的 ML 解决方案
使用传统方法进行数据清理和统一的组织已经构建了许多遗留操作,包括带有业务规则和领域知识文档的 ETL 脚本。忽略所有这些工作是许多新解决方案在改进遗留操作方面不起作用的主要原因。一个大的 ML 挑战是如何从遗留操作中获取信息来指导 ML 解决方案的学习过程。一种选择是使用传统操作来构建训练数据,但是数据有可能是有偏差的和有噪声的。
由于数据清洗和统一通常在数据源执行,ML 解决方案需要能够在大规模数据集上进行推理和预测。采用前面提到的重复数据删除解决方案;分类本质上发生在发现记录对之间的相似性上,并且这是一个计算量大且慢的 n 平方问题。因此,设计使用采样和哈希等技术来降低复杂性的解决方案变得非常重要。
对于任何 ML 解决方案来说,让人们成为流程的一部分是非常重要的。像领域专家和 IT 专家这样的角色在将遗留操作转换为有用的特征和标签以生成用于 ML 解决方案的训练数据、验证 ML 预测对数据质量的结果以及评估 ML 清理和统一对下游分析的影响方面是必不可少的。
总之,在源头进行数据清理和统一对于为下游组织创建值得信赖的分析至关重要。重要的是要认识到,数据质量问题不能孤立地得到妥善解决,提供清理和统一数据的整体方法的机器学习解决方案可能是最佳解决方案。与此同时,我们必须明白,为了开发在组织层面上工作的可扩展的 ML 管道,我们必须确保这些解决方案建立在遗留操作的基础上,并将人带入循环中。
如果你需要帮助或者有更多关于基于 ML 的数据清理解决方案的问题,请通过 LinkedIn 联系我。
日内交易的机器学习
A scene from ‘Pi’
在这篇文章中,我将探索用于时间序列分析的机器学习算法,并解释为什么它们不适用于日内交易。如果你是这个领域的新手,你可能会被作者用惊人的结果愚弄,在这些结果中,测试数据与预测几乎完全匹配。一个常见的技巧是显示一个带有长时间数据预测值的图,这造成了一种滞后不明显或者根本看不到的错觉。滞后是让预测变得无用的原因,稍后我会给你一个例子。还有其他方法让预测看起来合理,其中一些我确信是错误的。但是不要气馁,记住模型可以和你的数据一样好,缺乏模型是你获得可靠结果的主要绊脚石。
日内交易的真相
日内交易是在一天内买卖股票的过程。它可以简单到在早上买入一家公司的股票,然后在一天结束时(准确地说是下午 4 点)卖出。虽然这一行为本身很简单,但它需要大量的经验和手头的信息来购买可能上涨的股票。日内交易风险很大,因为市场的短期行为反映了数十亿快速波动的价值,这些价值是对接近随机游走的不断变化的条件的反应。超过 95%的交易者亏损。
机器能打败人类吗?
Small Trading Setup
交易需要大量的注意力和对市场的敏感性。有经验的交易者依赖多种信息来源,如新闻、历史数据、收益报告和公司内部人士。风险很高,需要考虑许多变量。出于这个原因,一些金融机构完全依赖机器进行交易。这意味着一台高速互联网连接的电脑可以在一天内执行数千次交易,从微小的价格差异中获利。这叫高频交易。没有人能和这些算法竞争,它们非常快而且更准确。
这种方法的缺点是,普通人可能无法获得这种工具,或者它们太贵了。然而,通过 Robinhood 或 TD Ameritrade 等交易平台,任何个人都可以通过电脑或智能手机参与股市交易。而且你甚至不用付经纪费,这对新手来说很有吸引力。
作为一名数据科学学生,我非常热情地尝试了不同的机器学习算法,并回答了这样一个问题:机器学习可以用来预测股市运动吗?
我们开始吧
我最喜欢的获取市场和上市公司信息的地方之一是 finance.yahoo.com。你可以用技术指标查看历史数据,阅读公司财务报表,新闻等。
我从纳斯达克市场挑选了我个人感兴趣的科技公司。对于这个项目,我构建了几个技术指标,方式与你在雅虎财经上看到的类似。让我们看看特斯拉的历史数据,感受一下我们在处理什么。
价格几乎没有离开布林线的空间。这告诉我们价格在两个标准差之间上下波动。我们可以用这个指标作为买卖股票的信号。
移动平均收敛发散(MACD)是一个动量指标,显示了证券价格的两条移动平均线之间的关系。通常,当 MACD(紫色线)超过信号(橙色线)时,意味着股票正在上涨,并将持续上涨一段时间。
相对强度指数(RSI)是另一个动量指标,可以判断股票是超买还是超卖。它的范围从 0 到 100,但一般来说,当指数接近 20 时,我们会注意,这将是买入的信号。如果接近 80,最好快点卖掉。
可视化有助于理解技术指标是如何工作的,以及它们的优缺点。让我们转到机器学习部分,所有的神奇都发生在这里。
为什么 ARIMA 不起作用?
自回归综合移动平均(ARIMA)模型用于预测时间序列数据,它基于数据点彼此相关的假设。如果数据不相关,模型将无法做出预测。自相关函数(ACF)将显示数据点是否有这种关系。我们来看看剧情:
ACF
数据点确实不相关,因此使用 ARIMA 来预测未来值是不合理的。不显示著名的滞后预测将是一种犯罪,所以这里是:
这就是我们在这里需要知道的一切,让我们转向更有前途的神经网络。
深度神经网络
当交易者使用历史数据和技术指标来预测股票走势时,他们会寻找熟悉的模式。一些类型的神经网络在寻找模式方面表现出色,并在图像识别或文本处理方面有多种应用。
首先,我尝试用卷积网络来识别历史数据中的模式。它可以接受任意数量的特征,并同时从中学习。在这个例子中,网络必须从 21 天的序列中学习并预测第二天的股票回报。我说的回报是指一天开始和结束时的价格差异。如果价格上涨,收益为正,下跌,收益为负。
那么它表现如何呢?网络容易过度拟合,这意味着它很好地学习了训练数据中的模式,但未能对测试数据做出任何有意义的预测。准确性和随机猜测一样好。
Overfitting (Accuracy: 80%)
递归网络(LSTM)也擅长从序列数据(即时间序列)中学习。在相同的序列长度和特征数量下,网络无法从数据中学习到任何东西。
让我们来看看预测。该网络采取了一条简单的路线,并决定每天的回报将是负的。它有 50%的正确率。
我已经尝试了数百种网络架构、功能数量、序列长度、超参数调整、预测第二天/周/月的组合。结果和随机猜测一样好。
显然,神经网络在这里也不起作用。
模式匹配
这种技术背后的想法是在测试集中取一个 9 天的序列,在训练集中找到相似的序列,并比较它们的第 10 天的回报。如果某个算法找到了多个序列,它会简单地对结果进行平均。让我们来看看这个过程:
粉色线是来自训练集的 9 天序列。该算法找到了 5 个匹配,其中三个在第 10 天有正回报,两个是负回报。取平均值,我们得到了一个正的预期回报。与测试集的实际回报相同。它工作了。
但是通过整个测试集匹配模式给了我大约 50%的准确率。魔法也没有在这里发生。
有希望
Photo by Kristopher Roller
我的技术都不起作用,但是如果你还想在股票市场上赚钱,有一个替代日交易的方法。使用技术指标的经典方法可以为短期投资提供良好的回报——从几天到大约一个月不等。它是这样工作的:我只用两个指标模拟了一个交易策略:布林线和 MACD。大多数指标都讲述了同样的故事,因为它们使用了同样的历史数据:价格或交易量。因为这个原因,我没有把它们组合在一起,而是分开使用。
我做了一个模拟,假设你在价格接近较低区间时买入股票,反之亦然。2018 年初,该算法有 15000 美元投资特斯拉。到年底,它仅通过 19 笔交易就获得了超过 100%的利润。
布林线对特斯拉很有效,但对其他股票就不那么有效了。例如,亚马逊的回报率为负。因此,它并不完美,但它对我尝试过的大多数股票都有效(总共 19 只)。
另一方面,MACD 的表现要差得多。这让我觉得它可能是布林线或其他指标的一个很好的补充,但它本身不是。
结论
这个项目的一大收获是,股票市场是一个非常复杂的系统,仅用历史数据来解释其行为是不够的。机器学习算法将其视为随机行走或白噪声。基本面分析、twitter 分析、新闻分析、本地/全球经济分析——诸如此类的东西有可能提高预测。
项目仓库住在这里。
感谢您的阅读,
阿瑟尼。
Picture made by Microsoft stock data
营销人员的机器学习
简介
随着电子商务、数字和移动技术的进步,以及消费者人口统计数据的变化,营销职能正在快速发展。Forrester 最近的一项研究【1】表明,到 2022 年,电子商务将占零售总额的 17.0%,高于 2017 年预计的 12.9%。这一趋势表明,越来越多的人开始在网上购物,或者在店内购物时受到数字活动的严重影响。
随着拉美裔和千禧一代等消费群体的增长,美国的人口统计数据正在快速变化,因此充分了解这些客户群体以向受众提供个性化和有针对性的信息至关重要。最近的一项研究【2】表明,将近一半(49%)的西班牙裔和拉丁裔消费者在购物过程中使用社交媒体,相比之下,所有种族的这一比例为 32%。因此,深入了解消费者并拥抱快速发展的技术进步以提供以客户为中心的全渠道体验至关重要。
营销人员的任务是成为首席执行官中客户的代言人,并在为消费者提供深入的个性化体验方面发挥关键作用。营销组织的成长与三件事密切相关
1.数据 2)营销技术栈和 3)人工智能/机器学习(AI-ML)
在本文中,我们将概述人工智能和机器学习(尤其是与客户分析相关的)将如何推动组织的增长。数据和人工智能/人工智能是推动营销人员推动组织创新的关键驱动力。做出高速数据驱动决策的组织将成为强大的营销先锋。
实现愿景的挑战
在我们深入研究 AI-ML 之前,以集成的方式获得高质量的数据以执行分析是至关重要的。许多组织仍在处理 excel 数据湖、孤岛式数据集和陈旧数据(旧数据和非实时数据)。这阻碍了营销团队得出一致且准确的报告指标,因为每个营销分析师使用不同的业务规则并得出不同的数字。因此,无论是在 CRM、CDP(客户数据平台)【3】还是在数据仓库/数据湖中,拥有一个整合的数据平台对任何组织来说都是至关重要的。重要的是不要迷失在这些系统中,而是理解营销用例,以确保正确的技术和基础设施到位。
在本文中,我们假设营销职能已经达到这一成熟水平,因此组织可以超越数据整合,寻求从高级分析中提取价值。整合的实时数据的基础是能够 360 度了解客户。
营销组织的 ML
一旦高质量的数据以可消费的方式可用,下一步就是为组织识别 AI-ML 用例。这里是营销人员可以考虑的最常见的使用案例,以便为客户提供个性化的体验。
1.细分和定位
2.客户流失
3.客户生命周期价值
4.推荐引擎
5.营销组合建模
6.客户归属
Common Machine Learning Use Cases for Marketers
总结
整合分析战略是首席营销官(CMO)刺激创新和增长的关键。大多数组织都会经历这一过程,最终实施高级分析,为客户实现超个性化。
Typical Analytics Journey of Organizations
这一切都从 CRM 数据库中的运营报告开始,然后发展到创建基于指标的报告,最终实现高级数据可视化。Tableau、Power BI 或 QlikView 等可视化工具是可视化类别【4】的领导者。
随着组织转向预测分析和其他高级分析,可以使用各种工具,从开源工具到付费工具。最流行的开源工具是 Python【5】和 R,并且有一个繁荣的社区【6】为这个知识库做出了贡献。
底层数据基础需要支持这些用例,许多组织正在向数据湖【7】转移。最流行的数据湖是由 AWS 提供的,使用了 AWS S3 和亚马逊红移【8】。云数据湖为集成和整合的数据提供了基础架构,使分析和机器学习开发人员能够生成可用于为客户提供个性化体验的见解。
一旦数据基础到位,分析用例得到实施,一个伟大的营销组织应该建立实验来不断测试、迭代和学习,以尽可能避免猜测。从长远来看,拥有复杂的客户分析并与客户进行更多双向互动的公司最有可能胜出。
注意:完整的白皮书和相关的用例可以从这个链接下载——https://www . element solutions . com/machine-learning-for-retail-markets-white-paper
关于作者
Yasim Kolathayil 是 Element Solutions 的数据科学总监。Yasim 对客户分析特别感兴趣,并且长期以来一直是客户分析的热心学生。
[1]https://www . Forrester . com/report/Forrester+数据+线上+零售+预测+2017+至+2022+US/-/E-RES139271
[2]https://www . prnewswire . com/news-releases/Deloitte-digital-study-digital-infected-sales-in-retail-brick-and-mortar-stores-to-reach-22 万亿-by-year-end-300082524.html
[3]https://www . element solutions . com/services/customer-data-platform
[4]https://power bi . Microsoft . com/en-us/blog/Gartner-positions-微软连续十年成为商务智能和分析平台的领导者/
[5]https://www . ka ggle . com/amberthomas/ka ggle-2017-调查-结果
[6]https://stackoverflow.blog/2017/10/10/impressive-growth-r/
[7]https://AWS . Amazon . com/big-data/data lakes-and-analytics/what-a-data-lake/
[8]https://aws.amazon.com/redshift/
当你不是物理学家时,对粒子数据的机器学习
Photo credit: Pixabay
如何通过 Python 使用 H2O 深度学习模型进行监督分类
本文介绍了深度学习与 H2O 、 H2O.ai 的开源机器学习包,并展示了如何使用一个 H2O 深度学习模型来解决监督分类问题,即使用 ATLAS 实验来识别希格斯玻色子。
我们没有粒子物理学的知识,但我们仍然希望应用先进的机器学习方法来看看我们是否可以准确地预测粒子碰撞事件是希格斯玻色子信号还是背景噪声。
请注意,将机器学习方法应用到你不熟悉的领域,并不是说,没有领域专业知识也能成为一名称职的数据科学家。它们是不同的东西。记住这一点,让我们开始吧。
安装 H2O
用 Python 安装 H2O 相当简单。我按照 H2O 官方文件上的说明:下载&安装 H2O 。它就像一个魔咒!
初始化 H2O 并加载数据
数据集可以在这里找到。我们加载 H2O Python 模块。
- 在我的本地机器上启动一个单节点 H2O 云。
- 允许它使用所有 CPU 核心和高达 2GB 的内存。
- 在集群已经运行的情况下进行清理。
- 在 H2OFrame 上使用 CPU 构建深度神经网络模型。
import h2o
h2o.init(max_mem_size = 2)
h2o.remove_all()
%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from h2o.estimators.deeplearning import H2ODeepLearningEstimator
初始化完成后,我们可以将数据集上传到 H2O 集群。数据被导入 H2O 框架,其功能与熊猫数据框架类似。在我们的例子中,集群运行在我们的笔记本电脑上。
higgs = h2o.import_file('higgs_boston_train.csv')
我们可以快速浏览一下数据集。
higgs.describe()
describe()给出了很多信息。
- 数据集中的行数和列数。
- 数据集的汇总统计信息,如数据类型、最小值、平均值、最大值、标准偏差、列中零的数量、列中缺失值的数量以及数据集的前 10 行。
Figure 1
数据预处理
我们将数据分为以下几种方式:
- 60%用于培训
- 20%用于验证(超参数调整)
- 20%用于最终测试,将保留到最后
- 预测值是除“事件 Id”和“标签”之外的所有列。
- 响应列是最后一列“标签”。
train, valid, test = higgs.split_frame([0.6, 0.2], seed = 2019)
higgs_X = higgs.col_names[1: -1]
higgs_y = higgs.col_names[-1]
深度学习模型
模型 1
- 在希格斯玻色子数据集上运行我们的第一个深度学习模型。
- 我们需要预测“标签”列,这是一个具有两个级别的分类特征。
- 深度学习模型的任务将是执行二元分类。
- 深度学习模型使用了数据集除“EventId”之外的所有预测器,而且都是数值型的。
- 第一个深度学习模型将只是一个时代来感受模型的构建。
higgs_model_v1 = H2ODeepLearningEstimator(model_id = 'higgs_v1', epochs = 1, variable_importances = True)
higgs_model_v1.train(higgs_X, higgs_y, training_frame = train, validation_frame = valid)
print(higgs_model_v1)
我们打印出模型以进行更多研究:
Figure 2
有相当多的信息,但我们在过去已经看到了所有这些信息。
- 训练集的误差度量,如对数损失、平均每类误差、AUC、基尼系数、均方误差、RMSE
- 最大 F1 阈值的混淆矩阵
- 不同指标的阈值
- 增益/提升表
验证集也打印出来了:
Figure 3
训练集和验证集的结果非常接近。
因此,使用我们最简单的深度学习模型,我们在验证集上获得了大约 0.994 auc,在训练集上获得了 0.995 auc。并且 log loss 在验证集上是 0.09,在训练集上是 0.085。
变量重要性
在 H2O 构建分类模型时,我们将能够在 Python 中以重要性降序查看变量重要性表,如下所示:
var_df = pd.DataFrame(higgs_model_v1.varimp(), columns = ['Variable', 'Relative Importance', 'Scaled Importance', 'Percentage'])
var_df.head(10)
Figure 4
进球历史
要查看评分历史,我们可以使用 score_history 方法检索作为 pandas 数据框的数据,然后绘制分类错误。
higgs_v1_df = higgs_model_v1.score_history()
plt.plot(higgs_v1_df['training_classification_error'], label="training_classification_error")
plt.plot(higgs_v1_df['validation_classification_error'], label="validation_classification_error")
plt.title("Higgs Deep Learner")
plt.legend();
Figure 5
pred = higgs_model_v1.predict(test[1:-1]).as_data_frame(use_pandas=True)
test_actual = test.as_data_frame(use_pandas=True)['Label']
(test_actual == pred['predict']).mean()
Figure 6
这个简单的深度学习模型我们达到的准确率已经是 0.967 了。
模型 2
来提高成绩。现在,我们运行另一个更小的网络,一旦错误分类率收敛,我们让它自动停止(特别是如果长度为 2 的移动平均值在连续 2 次得分事件中没有提高至少 1%)。我们还将验证集采样为 10,000 行,以加快评分。
higgs_model_v2 = H2ODeepLearningEstimator(model_id = 'higgs_v2', hidden = [32, 32, 32], epochs = 1000000, score_validation_samples = 10000, stopping_rounds = 2, stopping_metric = 'misclassification',
stopping_tolerance = 0.01)
higgs_model_v2.train(higgs_X, higgs_y, training_frame = train, validation_frame = valid)
进球历史
为了查看评分历史,我们绘制了第二个模型的分类误差。
higgs_v2_df = higgs_model_v2.score_history()
plt.plot(higgs_v2_df['training_classification_error'], label="training_classification_error")
plt.plot(higgs_v2_df['validation_classification_error'], label="validation_classification_error")
plt.title("Higgs Deep Learner (Early Stop)")
plt.legend();
Figure 7
好多了。
精度也有所提高。
pred = higgs_model_v2.predict(test[1:-1]).as_data_frame(use_pandas=True)
test_actual = test.as_data_frame(use_pandas=True)['Label']
(test_actual == pred['predict']).mean()
Figure 8
我们将从第二个模型中得到变量重要性图。
higgs_model_v2.varimp_plot();
Figure 9
AutoML:自动机器学习
最后但同样重要的是,让我们试试 H2O 的 AutoM L. H2O 的 AutoML 可以用于自动化机器学习工作流,其中包括自动训练和调整许多模型,然后我们打印出来看看哪些模型将成为 AutoML 排行榜上表现最好的模型。
from h2o.automl import H2OAutoMLaml = H2OAutoML(max_models = 10, max_runtime_secs=100, seed = 1)
aml.train(higgs_X, higgs_y, training_frame = train, validation_frame = valid)
aml.leaderboard
Figure 10
AutoML 已经建立了 5 个模型,包括 GLM(广义线性模型)、DRF(分布式随机森林)和 XRT(极度随机化树)以及两个堆叠集合模型(第二和第三),最好的模型是 XRT。
事实证明,我引以为傲的深度学习模型甚至不在排行榜上。
Jupyter 笔记本可以在 Github 上找到。享受这周剩下的时光。
参考: H2O 深度学习 Doc
面向产品经理的机器学习简介
理解机器学习如何在引擎盖下工作,而不要过于技术化。
想象一个石头剪子布游戏…
而且,你想写代码,这样当你用石头、布或剪刀移动你的手时,计算机会识别它并与你对弈。
想想写代码实现这样一个游戏。你必须从相机中提取图像,查看这些图像的内容,等等。
这对你来说会有很多代码要写。不出所料,给游戏编程最终会变得极其复杂和不可行。
传统编程
在传统编程中——多年来这一直是我们的谋生之道——我们考虑用编程语言来表达规则。
传统编程中,程序员定义的规则一般作用于数据,给我们答案。
例如,在石头剪子布中,数据将是一幅图像,规则将是所有查看该图像中的像素以尝试确定对象的if-then
语句。
传统编程的问题是,它将涵盖所有可预测的基础。但是,如果我们不知道某个规则的存在呢?
机器学习
机器学习扭转了传统编程的局面。它通过设置某些参数来产生期望的输出,从而得出预测。
这是一种复杂的说法,模型从错误中学习,就像我们一样。
参数是函数中的那些值,当模型试图学习如何将这些输入与这些输出相匹配时,这些值将被设置和更改。
把这些函数想象成你生活中的时刻,把这些参数想象成你从这些时刻中学到的东西。你希望永远不要重蹈覆辙,就像你希望你的模特那样。
在机器学习中,我们不是用代码编写和表达规则,而是向提供大量答案,标记这些答案,然后让机器推断出将一个答案映射到另一个答案的规则。
例如,在我们的石头剪刀布游戏中,我们可以说明石头的像素是多少。也就是说,我们告诉电脑,“嘿,这就是石头的样子。”我们可以这样做几千次,以获得不同的手,肤色等。
如果机器能够找出这些之间的模式,我们现在就有了机器学习;我们有一台为我们决定这些事情的计算机!
我如何运行一个看起来像这样的应用程序?
在上面显示的培训阶段,我们已经培训了这方面的模型;这个模型本质上是一个神经网络。
在运行时,我们会传入我们的数据,我们的模型会给出一个叫做预测的东西。
例如,假设您已经在许多石头、纸和剪刀上训练了您的模型。
当你对着摄像头举起拳头时,你的模型会抓取你拳头的数据,并给出我们所说的预测。
我们的预测是,有 80%的可能性这是石头,有 10%的可能性这是剪刀或布。
机器学习中的许多术语与传统编程中的术语略有不同。我们称之为训练,而不是编码和编译;我们称之为推理,从推理中得到预测。
您可以使用 TensorFlow 轻松实现这个模型。下面是创建这种神经网络的一段非常简单的代码:
model = tf.keras.models.Sequential([
tf.keras.layers.Flatten(input_shape=(150, 150, 3)),
tf.keras.layers.Dense(512, activation='relu'),
tf.keras.layers.Dense(3, activation='softmax')
])model.compile(loss='categorical_crossentropy', optimizer='rmsprop')model.fit(..., epochs=100)
潜得更深
以下是我在过去几个月里收集的一些很棒的资源。我希望他们能帮你找到正确的方向。
MOOCs
- 经典:吴恩达的 Coursera 机器学习
- Udacity 机器学习简介
- 谷歌的 Udacity 深度学习
- EdX 对 AI 的介绍
- Fast.ai 的 7 周实用深度学习,老师杰瑞米·霍华德(Kaggle 前任总裁,Enlitic 和 fast.ai 创始人)
教程
- 韦尔奇实验室神经网络简介,几个 4-5 分钟的精彩视频
- 谷歌的 Tensorflow 教程
- 谷歌 3 小时课程学习 TensorFlow 和深度学习,没有博士
- 斯坦福的深度学习教程
讲座和播客
- AI 与深度学习。从机器智能的类型到算法之旅,16z 交易和研究团队负责人 Frank Chen 在这张幻灯片演示中向我们介绍了人工智能和深度学习的基础知识(及其他)。
- a16z 播客:机器学习初创公司中的产品优势。很多机器学习初创公司最初在与大公司竞争时会感到有点“冒名顶替综合症”,因为(论点是这样的),那些公司拥有所有的数据;当然我们不能打败它!然而,初创公司有很多方法可以、也确实成功地与大公司竞争。本播客的嘉宾认为,如果你在此基础上构建了正确的产品,即使只有相对较小的数据集,你也可以在许多领域取得巨大的成果。
- 当人类遇上 AI 。安德森·霍洛维茨杰出的计算机科学客座教授费-李非(以的名义发表文章)是斯坦福大学的副教授,他认为我们需要注入更强的人文主义思维元素来设计和开发能够与人和在社交(包括拥挤的)空间中共处的算法和人工智能。
- “面向智能计算机系统的大规模深度学习”,2016 年 3 月,谷歌科技与杰夫·迪恩在首尔校园的对话。
放射学的机器学习—从哪里开始
磨刀霍霍:了解机器学习工具链,这样你就可以开始学习了。
Image by Eric M. Baumel, MD
您有兴趣开始学习放射学的机器学习吗?新术语的星座可能会让人不知所措:深度学习、TensorFlow、Scikit-Learn、Keras、Pandas、Python 和 Anaconda。在你开始之前,有一大堆令人头晕的新信息需要你掌握。
就我个人而言,我希望能够在我的一些使用苹果 CoreML 框架的 iOS 应用程序中使用机器学习(ML)功能。这意味着在你真正开始工作之前,还有一系列复杂的问题要处理。一旦我们正确配置了工具,工作将会更容易。
机器学习的主导语言是 Python。在你开始学习很多优秀的教程之前,你需要熟悉整个生态系统。
网上有无数的资源和书籍可以帮助你开始(另一篇文章的工作)。让我们看看迈出第一步需要做些什么。
“给我六个小时砍树,我会用前四个小时磨利斧头。”
——亚伯拉罕·林肯(可能从来没说过这话)
我们来谈谈
最常见的 ML 开发语言是 Python。如果你不了解 Python,许多 ML 初学者的参考资料都是从快速的 Python 介绍开始的。
这篇文章不是为了教 Python,而是为了展示一个开发人员如何开始使用庞大的 ML 工具链。
你要做的第一件事就是下载 Python 和机器学习所必需的 Python 工具。
你好,Unix
我们需要使用命令行界面来安装和管理我们的 Python 工具。
足够的狂欢是危险的:
在 Linux 或 Mac 中,我们使用终端。您可以在 Finder >应用程序>实用工具>终端中找到该程序。
在 Windows 中,我们使用命令提示符。你点击 Windows 图标> Windows 系统>命令提示符或者点击 Windows 图标并输入cmd
。
在光标前,您会看到一个文本字符串,它指向:
机器名:目录用户名$
你在美元符号后面打字。
以下是一些常用命令:
列出当前目录中的文件:ls
同时显示隐藏文件:ls -a
导航到新目录:cd <directory_path>
转到主目录:cd ~
或直接键入:cd
向上导航一级:cd ..
转到您所在的上一个文件夹:cd -
显示当前工作目录:pwd
向上箭头重新输入最后一个命令。再次按下向上箭头可以回到之前的命令。
清除窗口:clear
在文本编辑器中打开一个文件,例如:atom <filename>
取消申请(例如 ping) Ctrl-C
巨蟒
Python 是一种解释型语言,所以它是逐行阅读的,而不是编译型语言,在编译型语言中,你必须在使用它之前烤好蛋糕。
目前有两个独立的 Python 版本,Python 2.7 和 Python 3。Python 2.7 将于 2020 年 1 月 1 日寿终正寝,而 Python 3.x 不是向后兼容的。那么,为什么要使用旧版本呢?不幸的是,一些框架只支持 2.7 版本,许多书籍和在线教程都是专门为该版本编写的。我们该如何应对?
幸运的是,您可以在计算机上安装两种版本的 Python,并在硬盘上的不同文件夹中运行不同的虚拟环境,因此您可以在 Python 3.7 中完成大部分 ML 工作,如果您的项目需要一个只能在 2.7 上运行的库,则可以在不同的文件夹中安装 2.7 版本。
使用 virtualenv、Python Environment Wrapper (pew)、venv、pyvenv,有几种方法可以管理不同的 Python 虚拟环境。最简单的是使用 Conda,使用 Anaconda 时随 Python 一起安装。
https://imgs.xkcd.com/comics/python_environment.png
蟒蛇
Anaconda 是一个开源平台,可能是在 Linux、Mac OS X 和 Windows 上开始 Python 机器学习的最简单的方法。它帮助您管理编程环境,并包括数据科学中使用的常见 Python 包。您可以在https://www.anaconda.com/distribution/下载您平台的发行版。
一旦为您的系统安装了合适的 Python 版本,您将需要设置一些环境。
康达
Conda 是 Anaconda 使用的 Python 包管理器和环境管理系统。Conda 会安装您需要的大部分软件包,但不是全部。其余的可以使用pip
通过命令行安装——稍后会详细介绍。
要查看当前环境中的包:
conda list env
您运行的是哪个版本的 Conda:
conda -version
(如果低于 4.1.0,那么您可以用conda update conda
更新 Conda)
您可以使用 Anaconda Navigator 创建一个环境,方法是从左侧菜单中选择 Environments,然后单击 create 按钮。
Creating a new environment “new_env” using Anaconda Navigator
您也可以从命令行创建环境。例如,我们使用 Python 2.7 创建了一个名为“py27”的环境:
conda create -n py27 python=2.7
要激活环境:
conda activate <your_env_name>
要停用当前环境,请执行以下操作:
conda deactivate
要删除环境,请执行以下操作:
conda remove -name <your_env_name> -all
要列出您的所有 Conda 环境:
conda info --envs
List of Conda managed Python environments
带有星号的环境是当前的活动环境。
要查看当前环境中的包:
conda list env
您运行的是哪个版本的 Conda:
conda -version
(如果低于 4.1.0,那么您可以用conda update conda
更新 Conda)
两个主要的机器学习包 TensorFlow 和 Keras 应该使用pip
安装。对于苹果的机器学习框架,你也可以安装 Turi Create 。
科学堆栈
有一组被称为科学堆栈的 Python 包,可用于多个学科。其中包括:
NumPy
Scikit-learnhttps://scikit-learn.org/stable/—机器学习算法库
Jupyterhttps://jupyter.org/—基于网络的笔记本中的交互式 Python shell
Seabornhttps://seaborn.pydata.org/index.html—统计数据可视化
Bokehhttps://bokeh.pydata.org/en/latest/—交互式数据可视化
PyTables
您可以使用 Anaconda 安装这些包及其依赖项。在新创建的环境中,搜索您想要的包。
Search Anaconda Navigator for the packages you want to install
然后,通过选中复选框并单击“应用”,从列表中选择它们。
Adding new packages and dependencies via Anacona Navigator
如前所述,你使用pip
来安装 TensorFlow 和 Keras (以及 Turi Create 用于苹果的 CoreML)。
pip
pip 是 python 的标准包管理器https://pypi.org/project/pip/
pip install — upgrade pip
要使用 pip 安装软件包:
pip install <package_name>
编辑 Python 文件
您可以在 Mac 的终端或 Windows 的控制台中与 python 进行交互。为了编写代码,大多数人使用代码编辑器,比如 Atomhttps://atom.io/或者 Sublime Texthttps://www.sublimetext.com/。有关于代码编辑器的宗教战争,但是生命太短暂了。
我最喜欢的(也是免费的)文本编辑器是 GitHub 的 Atomhttps://atom.io/。Atom 的一个很酷的功能是,你可以用集成终端窗口等功能来扩展应用程序。
安装后,您可以通过进入设置/安装包并搜索platformio-ide-terminal
来添加此功能
运行 Python 文件
在命令提示符处($或>)键入python <filename.py>
要退出 python,使用exit()
或 Ctrl-D(Windows 中的 Ctrl-Z)
要查看您当前使用的 python 版本,请输入:
python --version **or** python -V
要查看您正在使用的 Python 安装的位置,请输入:
which python
环境文件
环境文件是项目根目录中的一个文件,它列出了所有包含的包及其特定于项目环境的版本号。这允许您与其他人共享项目,并在其他项目中重用。
您可以使用以下方式创建文件:
conda env export -file environment.yaml
您可以使用以下命令重新创建 Conda 环境及其包:
conda env create -n <conda-env> -f environment.yaml
在一些项目或教程中,你会看到 requirements.txt ,它被 pip 用作包管理器,而不是 Conda 使用的 environment.yaml。
这些是由冻结环境造成的:
pip freeze > requirements.txt
要重建,请使用:
pip install -r requirements.txt
Jupyter 笔记本
jupyter Notebookhttps://jupyter.org/是一款基于开源网络浏览器的应用。这允许您在一个更加用户友好的环境中直接运行 python 代码,并逐步查看结果。它非常适合教学,因为您可以在标记单元格中的代码单元格之间添加文本和图像。该应用程序是可扩展的,因此您可以添加许多其他有用的功能。
你也可以用 Anaconda Navigator 安装 Jupyter 笔记本:
Install Jupyter Notebook with Anaconda Navigator
在提示符下键入以下内容,在浏览器中创建新的 Jupyter 笔记本应用程序:
jupyter notebook
Create a new notebook with Python 3
要启动特定的笔记本:
jupyter notebook <notebook-name>
顺便说一下,不建议同时运行 Jupyter 笔记本应用程序的多个实例。
Jupyter Notebook helps keep you organized!
要运行单元格,请单击 Jupyter 工具栏中的“运行”按钮或按 Shift + Enter。
关闭笔记本,关闭终端窗口或键入:
jupyter notebook stop
或 按 Ctrl+C
好吧,现在该怎么办?
现在我们的斧子已经磨快了,你如何开始真正的放射信息学呢?
这里有几个链接可以让你注意到:
医学成像的机器学习【https://pubs.rsna.org/doi/10.1148/rg.2017160130T2
深度学习:放射科医生入门https://pubs.rsna.org/doi/10.1148/rg.2017170077
为了更深入的了解,这里有两期专门讨论这个主题的期刊:
March 2018 年 3 月第 15 卷第 3PB 期特刊数据科学:大数据、机器学习和人工智能
June 2018 年 6 月第 31 卷第 3 期特别关注开源软件
如果您现在仍然清醒,这里有一些有用的 GitHub 参考资料:
https://github.com/ImagingInformatics/machine-learning
https://github.com/slowvak/MachineLearningForMedicalImages
我们开始吧!
上面提到的 2018 年 6 月的《数字成像杂志》中有一篇非常精彩的介绍:
Hello World Deep Learning in Medical ImagingJDI(2018)31:283–289 Lakhani、Paras、Gray、Daniel L .、Pett、Carl R .、Nagy、Paul、Shih、George
不是创建一个典型的猫对狗的分类器,而是创建一个胸部对腹部的 x 射线分类器(CXR 对 KUB)!这是开始你的人工智能之旅的好地方。
以上所有内容都很难解释,但我希望这篇介绍能帮助您开始。我不是专家,写这篇文章最初是为了帮助自己记忆。对流程有基本理解的从业者越多越好。
祝你好运!
体育博彩的机器学习:这不是一个基本的分类问题。
我们提出了一种使用自定义损失函数将 bets 损益包含到神经网络分类器中的方法。
Photo by Christin Noelle on Unsplash
体育博彩是机器学习算法,特别是分类神经网络的完美问题之一。大量可用的数据和明确的目标,挑选赢家!尽管如此,经典的分类模型并不太适合赌博策略,人们需要在他的神经网络中使用一个定制损失函数来实现更好的盈利能力。我们在下面解释原因。
英格兰超级联赛的简单赌博策略。
让我们根据博彩交易所的赔率来实施基本的博彩策略。小数赔率是全额支付与赌注的比率。例如,赔率为 2,意味着 1 美元的赌注可以赢得 2 美元(包括你的赌注)。请注意,赔率倒数给出了正确的隐含概率。赔率为 2 意味着有 50%的胜算(1/赔率)。因此,您希望押注于赔率最低的团队,即获胜概率最高的团队。
为了便于说明,我们设计了两个基本策略:
- " 赢 ":赌赔率最低的一方,赢的概率最高。
- " 赢或平 ":赌赔率值最低的队伍,赌平局。
假设伯恩茅斯对切尔西的赔率为 5.5-1.61。切尔西的赔率为 1.61。因此我们赌切尔西的胜利为“ 赢 ”策略,而一场胜利和平局为“ 赢或平局 ”策略。
预测准确性与总体利润。他们不相似。
现在我们来比较一下两种投注策略,“赢vs .”赢或平。
对于数据,我们使用了必发 API 。Betfair 是最大的博彩交易所之一,其 API 包含交易所市场导航、赔率检索和下注操作。
上面的条形图显示了两种下注系统的准确性和利润。准确性是指我们下注正确的次数除以下注总数(在这种情况下是 200)。利润代表每次下注投资 1 英镑可以获得的金额。左边的第一个图表显示“赢”策略的准确率为 61%,而“赢或平”策略的准确率为 80%在这种情况下,“赢或平”似乎更好。然而,第二张图表显示,它产生的利润远低于“赢”策略。1 对 12。
因此,我们不应该以更准确地预测比赛结果为目标,相反,我们应该专注于最大化我们的整体利润。
用于博彩预测的神经网络。
在决定把钱投给哪支球队时,会涉及到很多数据。出于这个原因,赌博是应用最流行的机器学习技术之一的理想主题,神经网络。
特别是,我们可以使用分类神经网络。当应用于有离散结果的问题时,分类神经网络是理想的,或者换句话说,当识别特定观察属于哪个类别时。作为例子,想想有趣的“ 热狗,而不是热狗 ”或情感分析,它们试图将文本分为积极或消极的情感。
应用于体育博彩,我们可以设计一个具有三个简单类别的神经网络。下面是这样一个网络的架构。
然而,从我们之前的两个简单下注策略的例子来看,很明显我们不是在试图预测游戏的结果,而是哪种下注最有利可图。应用于分类神经网络,这将导致以下架构。注意,在这种情况下,我们甚至允许“无赌注”类别。
我们最终会遇到一个多标签分类问题(不要与多类别分类混淆),因为游戏的结果可能会导致一两个预测是正确的。例如,主队获胜将导致两个获胜赌注:“赢得主场”和“赢得主场或平局”。
我们需要整合赌注的潜在利润。
并非所有的赌注都提供相同的回报。赔率为 2 的赌注可以产生 1 的利润,而赔率为 1.1 的赌注可以产生更低的 0.1 的利润。然而,如果不成功,这两个赌注都要承担 1 英镑的损失。因此它们是不平等的;拿 1 去冒险赚 1 和拿 1 去冒险赚 0.1 是不一样的。
为了在我们的神经网络中考虑到这一点,我们需要使用一个定制的损失函数。损失函数(或目标函数)是在给定训练样本和预期输出的情况下,神经网络“有多好”的度量。在标准分类神经网络中,我们使用损失函数,例如分类交叉熵。然而,这种函数会给所有赌注相似的权重,忽略盈利能力的差异。
在我们的例子中,我们希望模型能够最大化策略的整体收益。因此,我们的自定义损失函数的输入必须包含每次下注的潜在利润。
自定义损失功能
我们在 TensorFlow 之上用 Keras 建立了我们的自定义损失函数。
在 Keras 中,损失函数有两个参数:
- y_true :真标签向量(赢主场,赢主场或平局,平局,赢客场,赢客场或平局,不下注)。基于我们的神经网络架构,这采取 1 和 0 的向量的形式。例如,导致主队获胜的游戏具有以下 y_true 向量(1,1,0,0,0,0)。
- y_pred :预测向量。它是我们的神经网络分类器的输出。
由于 Keras 的限制,我们不能在损失函数中传递游戏的赔率,所以我们必须将它们作为 y_true 向量的附加项来传递。
一点点 python 代码
下面是我们用 Python 和 Keras 写的自定义损失函数。
简而言之,它衡量单位股份投入的平均利润/损失。每个观察(每个游戏)的步骤如下:
- 从 y_true 输入中获取赔率
- 使用赔率计算每笔赌注的潜在利润。
- 把赢的赌注和输的赌注连在一起。
- 我们以这个观察的预期 P&L 结束。我们将这个乘以-1,得到一个最小化的“损失”(而不是一个最大化的增益)。
def odds_loss(y_true, y_pred):
"""
The function implements the custom loss function
Inputs
true : a vector of dimension batch_size, 7\. A label encoded version of the output and the backp1_a and backp1_b
pred : a vector of probabilities of dimension batch_size , 5.
Returns
the loss value
"""
win_home_team = y_true[:, 0:1]
win_home_or_draw = y_true[:, 1:2]
win_away = y_true[:, 2:3]
win_away_or_draw = y_true[:, 3:4]
draw = y_true[:, 4:5]
no_bet = y_true[:, 5:6]
odds_a = y_true[:, 6:7]
odds_b = y_true[:, 7:8]
gain_loss_vector = K.concatenate([win_home_team * (odds_a - 1) + (1 - win_home_team) * -1,
win_home_or_draw * (1/(1 -1/odds_b) - 1) + (1 - win_home_or_draw) * -1,
win_away * (odds_b - 1) + (1 - win_away) * -1,
win_away_or_draw * (1/(1 -1/odds_a) - 1) + (1 - win_away_or_draw) * -1,
draw * (1/(1 - 1/odds_a - 1/odds_b) - 1) + (1 - draw) * -1,
K.zeros_like(odds_a)], axis=1)
return -1 * K.mean(K.sum(gain_loss_vector * y_pred, axis=1))
数据。
对于我们的数据,我们从 2018 年 8 月至 12 月的 2018-2019 赛季英超联赛中选取了 200 场比赛。它包含描述性的游戏数据,如球队名称、Betfair 的赔率和情绪得分(表示正面推文占正面和负面推文的百分比)。我的 github 页面上有数据和 Jupyter 笔记本。
从文件中加载数据,并在训练和测试数据中拆分。
我们的数据以 1,2 或 3 的形式包含每场比赛的结果:
- 1:主场获胜
- 2:客场胜利
- 3:画
这需要被转换成代表我们的神经网络的输出层的独热编码向量。另外,我们把每个队的赔率加起来作为这个向量的元素。这正是我们下面要做的。
def get_data():
data = pd.read_csv('extract-betsentiment-com.csv')
X = data.values[:, 5:-5]
y = data.values[:, -1]
y_full = np.zeros((X.shape[0], 8))
for i, y_i in enumerate(y):
if y_i == 1:
y_full[i, 0] = 1.0
y_full[i, 1] = 1.0
if y_i == 2:
y_full[i, 2] = 1.0
y_full[i, 3] = 1.0
if y_i == 3:
y_full[i, 1] = 1.0
y_full[i, 3] = 1.0
y_full[i, 4] = 1.0
y_full[i, 6] = X[i, 1] # ADD ODDS OF HOME TEAM
y_full[i, 7] = X[i, 2] # ADD ODDS OF AWAY TEAM
return X, y_full, yX, y, outcome = get_data()# SPLIT THE DATA IN TRAIN AND TEST DATASET.
train_x, test_x, train_y, test_y, = train_test_split(X, y)
模型的训练
在训练模型之前,我们首先需要定义它。我们使用一个全连接神经网络,有两个隐藏层。我们使用 BatchNormalization 来归一化权重并消除消失梯度问题。
然后,我们使用一组任意参数来训练该模型。
def get_model(input_dim, output_dim, base=1000, multiplier=0.25, p=0.2):
inputs = Input(shape=(input_dim,))
l = BatchNormalization()(inputs)
l = Dropout(p)(l)
n = base
l = Dense(n, activation='relu')(l)
l = BatchNormalization()(l)
l = Dropout(p)(l)
n = int(n * multiplier)
l = Dense(n, activation='relu')(l)
l = BatchNormalization()(l)
l = Dropout(p)(l)
n = int(n * multiplier)
l = Dense(n, activation='relu')(l)
outputs = Dense(output_dim, activation='softmax')(l)
model = Model(inputs=inputs, outputs=outputs)
model.compile(optimizer='Nadam', loss=odds_loss)
return modelmodel = get_model(21, 6, 1000, 0.9, 0.7)
history = model.fit(train_x, train_y, validation_data=(test_x, test_y),
epochs=200, batch_size=5, callbacks=[EarlyStopping(patience=25),ModelCheckpoint('odds_loss.hdf5',save_best_only=True)])
训练完成后,我们使用以下 print 命令查看模型的性能:
print('Training Loss : {}\nValidation Loss : {}'.format(model.evaluate(train_x, train_y), model.evaluate(test_x, test_y)))150/150 [==============================] - 0s 271us/
step 50/50 [==============================] - 0s 318us/
step Training Loss : -0.05027060141166051
Validation Loss : -0.08301501810550689
如我们所见,我们最终的训练损失为-0.05。请记住,我们正在尝试最小化我们的损失函数,这与我们的损益相反。这个数字告诉我们,平均来说,每一次下注将为每 1 英镑的股份产生 0.05 英镑的利润。我们的验证数据集显示,每磅的平均利润为 0.08 英镑。考虑到我们刚刚向神经网络提供了基本数据,这还不错。在 200 多场比赛中,假设我们每场比赛下注 1,我们理论上的 NN 下注策略将产生 10 到 16.6。
结论。
我们提出了一种使用自定义损失函数将赌注 p&l包含到神经网络分类器中的方法。它超越了在设计投注系统时可能误导的准确率。我们相信这对任何希望在体育运动中使用机器学习的人都是有用的。
如需更多信息或问题,请随时与我联系。另外,请注意,如果您对我们的数据感兴趣,我们将很乐意与您分享。
成为中等会员,在平台上支持我!
https://medium.com/@charlesmalafosse/membership
参考和代码。
基于 K-Means 算法的股票聚类机器学习
了解如何使用聚类通过无监督的股票聚类使投资组合更加多样化。
多元化是构建投资组合的关键步骤,但真正的多元化是不可能的,因为投资每家公司都需要大量资本。除此之外,并不是所有的公司都值得投资,这可能是因为它们的流动性非常差。
所以现在你要做的是想出一个有效的策略,只选择那些表现不同的股票。这将有助于降低风险,一种方法是从不同的行业挑选股票,但一种更数据驱动的解决方案是对股票数据应用 K 均值聚类算法,以识别不同的股票聚类。
[参考:https://www . python forfinance . net/2018/02/08/stock-clusters-using-k-means-algorithm-in-python/]
在下面的帖子中,我将给出一个使用 Python 应用 K-Means 算法的例子。
首先,我们需要有组织结构的数据。对于这个任务,我将使用一个符合 Shariah 的股票列表,如这里的所列。名单已经更新,所以我选择的公司可能会有点不同。
下面的代码块从计算机中加载数据,并根据我们的需要构造数据
import pandas as pd
from sklearn.cluster import KMeans
from math import sqrt
import pylab as pl
import numpy as np#Loading the data
data = pd.read_csv("SC Close Prices.csv", index_col = "date")
data.index = pd.to_datetime(data.index)start = "2010-01-01"data = data.loc[start:]#Calculating annual mean returns and variances
returns = data.pct_change().mean() * 252
variance = data.pct_change().std() * sqrt(252)returns.columns = ["Returns"]
variance.columns = ["Variance"]#Concatenating the returns and variances into a single data-frame
ret_var = pd.concat([returns, variance], axis = 1).dropna()
ret_var.columns = ["Returns","Variance"]
ret_var variable after running the code block above
现在,在将模型拟合到我们的数据之前,我们需要决定我们希望将数据分成多少个簇。决定这个数字可能很棘手,因此我们将使用“肘方法”来计算一系列不同集群的 SSE(误差平方和)。然后,我们将在 x 轴上绘制簇的数量,在 y 轴上绘制 SSE。
X = ret_var.values #Converting ret_var into nummpy arraysse = []for k in range(2,15):
kmeans = KMeans(n_clusters = k)
kmeans.fit(X)
sse.append(kmeans.inertia_) #SSE for each n_clusterspl.plot(range(2,15), sse)
pl.title("Elbow Curve")
pl.show()
下图显示了 5 个簇是一个很好的数字,因为我们不希望 n_clusters 太大,并且在 5 个簇之后错误率下降速度变慢,因此,我认为这是一个合理的选择。
因此,现在我们要将 K-Means 模型再次拟合到我们的数据集,n_clusters = 5,并绘制结果。
kmeans = KMeans(n_clusters = 5).fit(X)centroids = kmeans.cluster_centers_pl.scatter(X[:,0],X[:,1], c = kmeans.labels_, cmap ="rainbow")
pl.show()
就像任何其他数据科学问题一样,我们的数据中有一个离群值,我们需要通过确定它是哪家公司来消除它。下面的代码做了同样的事情。
print(returns.idxmax())ret_var.drop("HADC", inplace =True)
移除后,我们现在重新进行拟合模型和绘图的过程。
X = ret_var.values
kmeans =KMeans(n_clusters = 5).fit(X)centroids = kmeans.cluster_centers_pl.scatter(X[:,0],X[:,1], c = kmeans.labels_, cmap ="rainbow")
pl.show()
我们现在要做的就是获取数据集中每家公司的聚类数,这样我们就可以在构建多元化投资组合的同时区分不同的公司。
Company = pd.DataFrame(ret_var.index)
cluster_labels = pd.DataFrame(kmeans.labels_)df = pd.concat([Company, cluster_labels],axis = 1)
我更多关注的是算法在 python 中的实现,而不是解释理论。我希望这篇文章对你有用。如果你有任何问题或发现任何技术错误,请在下面的评论区告诉我。
供应链预测的机器学习
你如何使用机器学习来预测供应链中的需求?
Source: https://www.vpnsrus.com/
下面这篇文章摘自我的《供应链预测的数据科学》一书,这里有。你可以在这里* 找到我的其他出版物 。我也活跃在LinkedIn*。
什么是机器学习?
供应链从业者通常使用老派的统计方法来预测需求。但随着最近机器学习算法的兴起,我们有了新的工具,可以轻松实现典型工业需求数据集预测准确性方面的出色表现。这些模型将能够学习许多关系,这些关系超出了传统统计模型的能力。例如,如何将外部信息(如天气)添加到预测模型。
传统的统计模型使用预定义的模型来根据历史需求进行预测。问题是这些模型不能适应历史需求。如果使用双指数平滑模型来预测季节性产品,它将无法解释季节性模式。另一方面,如果对非季节性需求使用三重指数平滑模型,它可能会过度拟合需求的噪声,并将其解释为季节性。
机器学习是不同的:在这里,算法(即机器)将从训练数据集(即我们的历史需求)中学习关系,然后能够将这些关系应用于新数据。传统的统计模型将使用预定义的关系(模型)来预测需求,而机器学习算法不会假定先验特定的关系(如季节性或线性趋势);它将直接从历史需求中学习这些模式。
对于学习如何进行预测的机器学习算法,我们必须向它显示输入和期望的相应输出。然后它会自动理解这些输入和输出之间的关系。
使用机器学习和指数平滑模型预测我们的需求之间的另一个关键区别是,机器学习算法将从我们所有的数据集学习模式。指数平滑模型将单独处理每个项目,与其他项目无关。机器学习算法将从所有数据集中学习模式,并将最有效的方法应用于每种产品。人们可以通过增加每个时间序列的长度(即,为每个产品提供更多的历史周期)来提高指数平滑模型的准确性。有了机器学习,我们将能够通过提供更多产品来提高我们模型的准确性。
欢迎来到机器学习的世界。
用于需求预测的机器学习
*为了进行预测,我们将向机器学习算法提出以下问题:
基于上 n 个需求周期,下一个周期的需求会是多少?
我们将通过为模型提供特定布局的数据来训练模型:
- n 个连续的需求周期作为输入。
-作为输出的下一个周期的需求。
让我们看一个例子(用季度预测来简化表格)😗
对于我们的预测问题,我们将基本上向我们的机器学习算法显示我们的历史需求数据集的不同提取作为输入,并且每次显示下一次需求观察是什么。在我们上面的例子中,算法将学习上四个季度的需求和下一个季度的需求之间的关系。算法会学习如果我们有 5,15,10 & 7 作为最后四个需求观测值,那么下一个需求观测值就是 6,所以它的预测应该是 6。
大多数人对这个想法会有两种截然不同的想法。要么人们会认为“计算机根本不可能观察需求并做出预测”要么认为“到目前为止,人类无事可做。”两者都不对。
后面我们会看到,机器学习可以产生非常准确的预测。作为控制机器的人,我们仍然必须问自己许多问题:
——向算法提供哪些数据,让它理解正确的关系。
-用哪个机器学习算法(有很多不同的!).
-在我们的模型中使用哪些参数。正如你将看到的,每个机器学习算法都有一些设置,我们可以调整这些设置来提高其准确性。
和往常一样,没有确定的放之四海而皆准的答案。实验将帮助您找到最适合您的数据集的方法。
数据准备
任何机器学习算法项目的第一步都是对数据进行正确的清理和格式化。在我们的例子中,我们需要格式化历史需求数据集,以获得一个类似于上表所示的数据集。
命名约定在我们的数据清理过程中,我们将使用标准的数据科学符号,并将输入称为 X ,将输出称为 Y 。具体来说,数据集X _ train&Y _ train将包含我们将用来训练我们的算法的所有历史需求( X_train 作为输入, Y_train 作为输出)。数据集X _ test&Y _ test将用于测试*我们的模型。*
您可以在下表中看到一个典型的历史需求数据集示例,您应该在预测项目开始时拥有该数据集。
我们现在必须将这个数据集格式化为类似于第一个表的格式。现在让我们假设,我们希望根据某个产品在前四个季度的需求观察来预测该产品在一个季度的需求。我们将通过遍历我们拥有的不同产品来填充数据集X _ train&Y _ train,每次创建一个数据样本,其中连续四个季度为 X_train ,下一个季度为 Y_train 。这样,机器学习算法将学习四分之一的需求和之前四分之一的需求之间的关系。
您可以在下表中看到第一次迭代的图示。为了验证我们的模型,我们将把 Y3Q4 放在一边作为测试集。
这意味着我们的训练集不会持续到 Y3Q4,因为它是为测试集保留的:最后一个循环将被用作最终测试。
我们的 X_train 和 Y_train 数据集将如下表所示:
请记住,我们的算法将学习 X_train 中的关系,以预测 Y_train。所以我们可以写成 X_train -> Y_train。
最终测试将通过这些 X_test 和 Y_test 数据集提供给我们的工具:
这些是我们在 Y3Q4 之前(即 Y2Q4 到 Y3Q3)知道的每种产品的四个最新需求季度。这意味着我们的算法在训练阶段不会看到这些关系,因为它将测试它在这些特定预测练习中达到的准确性。我们将在这个测试集上测量它的准确性,并假设它在预测未来需求时的准确性是相似的。
数据集长度
对于任何机器学习练习来说,关注有多少数据被输入到算法中是很重要的。越多越好。另一方面,我们用来做预测的周期越多(我们称之为 x_len ,我们就越不能遍历数据集。此外,如果我们想要一次预测更多的周期( y_len ),这将花费我们一部分数据集,因为我们需要更多的数据(Y_train 更长)来在我们的数据集中执行一次循环。
通常,如果我们有一个有 n 个周期的数据集,我们将能够使 1+n-x_len-y_len 贯穿它。
loops = 1 + n- x_len- y_len
最佳实践是至少保持足够的运行来循环两年,以便 23 + x_len + y_len ≤ n 。这意味着该算法将有两个完整的季节周期来学习任何可能的关系。如果它只有一个,你将面临过度拟合的高风险。
自己动手
数据收集
数据集的创建和清理是任何数据科学项目必不可少的一部分。为了说明我们将在接下来的章节中创建的所有模型,我们将使用 2007 年 1 月至 2017 年 1 月挪威的历史汽车销售数据作为示例数据集。你可以在这里下载这个数据集:【www.supchains.com/download】T21你会得到一个 csv 文件,名为Norway _ new _ car _ sales _ by _ make . CSV。该数据集包含 65 家汽车制造商在 121 个月内的销售额。平均而言,挪威每年销售 140,000 多辆新车,因此,如果我们假设一辆新车在挪威的平均价格约为 30,000 美元,则市场价值可粗略估计为 40 亿美元。就规模而言,这个数据集是适度的,但它足够大,足以与新模型和想法的实验相关。然而,机器学习模型可能会在其他更大的数据集上显示出更好的结果。
自带数据集在文章的第二部分,我们将讨论如何将机器学习模型应用于这个示例数据集。但是我们真正感兴趣的是你自己的数据集*。不要浪费任何时间,已经开始收集一些历史需求数据,以便您可以在我们讨论不同主题时,根据您自己的历史需求数据来测试以下模型。建议您从拥有至少三年数据(5 年更好)和一百多种不同产品的数据集开始。越大越好。
训练和测试集创建
我们将编写第一个代码,从这个 csv 中提取数据,并将其格式化,以日期为列,以产品为行。*
*# Load the CSV file (should be in the same directory)
data = pd.read_csv(“norway_new_car_sales_by_make.csv”)
# Create a column “Period” with both the Year and the Month
data[“Period”] = data[“Year”].astype(str) + “-” + data[“Month”].astype(str)
# We use the datetime formatting to make sure format is consistent
data[“Period”] = pd.to_datetime(data[“Period”]).dt.strftime(“%Y-%m”)
# Create a pivot of the data to show the periods on columns and the car makers on rows
df = pd.pivot_table(data=data, values=”Quantity”, index=”Make”, columns=”Period”, aggfunc=’sum’, fill_value=0)
# Print data to Excel for reference
df.to_excel(“Clean Demand.xlsx”)*
请注意,我们将结果打印在一个 excel 文件中,供以后参考。直观地检查数据集的外观,以确保代码按预期运行,这始终是一种好的做法。
您还可以定义一个函数来存储这些步骤以备后用。
*def import_data():
data = pd.read_csv(“norway_new_car_sales_by_make.csv”)
data[“Period”] = data[“Year”].astype(str) + “-” + data[“Month”].astype(str)
data[“Period”] = pd.to_datetime(data[“Period”]).dt.strftime(“%Y-%m”)
df = pd.pivot_table(data=data,values=”Quantity”,index=”Make”,columns=”Period”,aggfunc=’sum’,fill_value=0)
return df*
既然我们已经有了格式正确的数据集,我们就可以创建训练集和测试集了。为此,我们将创建一个函数数据集,它接受以下输入:
df 我们最初的历史需求;
x_len 我们将用来进行预测的月数;
y_len 我们要预测的月数;
y_test_len 我们离开的月数作为最终测试;
并返回 X_train,Y_train,X_test & Y_test。
*def datasets(df, x_len=12, y_len=1, y_test_len=12):D = df.values
periods = D.shape[1]
# Training set creation: run through all the possible time windows
loops = periods + 1 — x_len — y_len — y_test_len
train = []
for col in range(loops):
train.append(D[:,col:col+x_len+y_len])
train = np.vstack(train)
X_train, Y_train = np.split(train,[x_len],axis=1)
# Test set creation: unseen “future” data with the demand just before
max_col_test = periods — x_len — y_len + 1
test = []
for col in range(loops,max_col_test):
test.append(D[:,col:col+x_len+y_len])
test = np.vstack(test)
X_test, Y_test = np.split(test,[x_len],axis=1)
# this data formatting is needed if we only predict a single period
if y_len == 1:
Y_train = Y_train.ravel()
Y_test = Y_test.ravel()
return X_train, Y_train, X_test, Y_test*
在我们的函数中,我们必须使用。在 Y_train 和 Y_test 上的 ravel() 如果我们只想一次预测一个周期。
array.ravel() 将 NumPy 数组的维数减少到 1D。我们的函数总是将 Y_train 和 Y_test 创建为 2D 数组(即包含行和列的数组)。如果我们只想一次预测一个周期,那么这些数组将只有一列(和多行)。不幸的是,如果我们只想预测一个周期,我们稍后将使用的函数将需要 1D 数组。
我们现在可以轻松地调用我们的新函数 datasets(df) 以及 import_data() 。
*import numpy as np
import pandas as pd
df = import_data()
X_train, Y_train, X_test, Y_test = datasets(df)*
我们现在获得了为我们的机器学习算法(X_train & Y_train)提供数据所需的数据集,以及测试它所需的数据集(X_test & Y_test)。
注意我们取 y_test_len 为 12 期。这意味着我们将在 12 个不同的预测上测试我们的算法(因为我们一次只预测一个时期)。
一次预测多个期间如果想一次预测多个期间,可以更改 y_len。你需要注意保持y _ test _ len≥y _ len;否则,你就无法检验你算法的所有预测。
回归树
作为第一个机器学习算法,我们将使用一个决策树。决策树是一类机器学习算法,它将创建一个问题地图(实际上是一棵树)来进行预测。如果我们想让这些树预测一个数字,我们称它们为回归树,如果我们想让它们预测一个类别或标签,我们称它们为分类树。
为了做出预测,该树将从其基础开始,首先提出是/否问题;基于这个答案,它将继续问新的是/否问题,直到它得到一个最终的预测。不知何故,你可以看到这些树就像一个大游戏猜猜是谁?(著名的 80 年代游戏):模型会连续问多个问题,直到得到正确答案。
在决策树中,每个问题被称为一个节点。例如,在上图中,'这个人的鼻子大吗?'是一个节点。每个可能的最终答案被称为叶。在上面的例子中,每片叶子只包含一个人。但是这不是强制性的。你可以想象很多人都有一张大嘴和一个大鼻子。在这种情况下,叶将包含多个值。
一棵树用来分割一个节点的不同信息被称为特征。例如,上图中的树可以在三个特征嘴、鼻子、和眼镜上分割一个节点。
它是如何工作的?
为了说明我们的树将如何增长,让我们拿回我们的季度虚拟数据集。
基于这个训练数据集,问自己一个聪明的问题来做一个预测:第一个需求观察>是 7 吗?
这是一个聪明的问题,因为您知道答案(是/否)将提供下一季度需求行为的有趣指示。如果答案是是,我们试图预测的需求很可能相当高(> 8),如果答案是否,那么我们试图预测的需求很可能很低(≤7)。
下面是一个不好的问题的例子。
这没有帮助,因为这个问题没有将我们的数据集分成两个不同的子集(即,每个子集内仍然有很多变化)。如果问题的答案是第三需求观察< 6?是是,我们仍然有从 1 到 11 的需求范围,如果答案是否,范围从 4 到 13。这个问题对预测未来需求毫无帮助。
不必过多地探究树的数学内部工作的细节,生长我们的树的算法将在每个节点选择一个关于可用的特征(即先前的季度)之一的问题(即分裂),这将最小化两个新数据子集的预测误差。
1963 年,Morgan 和 Sonquist 在他们的论文“调查数据分析中的问题和建议”中,首次提出了创建决策树的算法关于如何生长决策树,有许多不同的算法(许多是从 60 年代开始开发的)。它们都遵循这样的目标,即询问关于数据集不同特征的最有意义的问题,以便将数据集分成不同的子集,直到达到某种标准。**
参数这是一个可怕的想法,因为即使你在训练集上有完美的准确性,你也不能在新数据上复制这些结果。我们将基于一些标准来限制我们的树的增长。让我们看看最重要的(我们已经在使用 scikit-learn 命名约定)。
最大深度树可以询问的连续问题(节点)的最大数量。
最小样本分割节点中触发新分割所需的最小样本量。如果将此值设置为 6,则只剩下 5 个观测值的节点将不会被进一步分割。
Min samples leaf 一片叶子中需要的最小观察量。这是一个非常重要的参数。这越接近 0,过度拟合的风险就越高,因为你的树实际上会增长,直到它提出足够多的问题来分别处理每个观察。
标准这是算法将最小化的 KPI(MSE 或 MAE)。
当然,根据您的数据集,您可能希望为这些参数赋予不同的值。我们将在下一章讨论如何选择最佳参数。
自己动手
我们将使用 scikit-learn Python 库(www.scikit-learn.org)来种植我们的第一棵树。这是一个著名的开源库,世界各地的数据科学家都在使用它。它构建在 NumPy 的基础上,因此它可以很容易地与我们代码的其余部分进行交互。
第一步是调用 scikit-learn 并创建一个回归树的实例。一旦完成,我们必须根据 X_train 和 Y_train 数组来训练它。
*from sklearn.tree import DecisionTreeRegressor
# — Instantiate a Decision Tree Regressor
tree = DecisionTreeRegressor(max_depth=5,min_samples_leaf=5)
# — Fit the tree to the training data
tree.fit(X_train,Y_train)*
请注意,我们创建了一个最大深度为 5 的树(即,最多需要五个连续的是/否问题来对一个点进行分类),其中每个树叶至少有 5 个样本。
现在,我们有了一个针对我们特定需求历史的树。我们已经可以在训练数据集上测量它的准确性。
*# Create a prediction based on our model
Y_train_pred = tree.predict(X_train)
# Compute the Mean Absolute Error of the model
import numpy as np
MAE_tree = np.mean(abs(Y_train — Y_train_pred))/np.mean(Y_train)
# Print the results
print(“Tree on train set MAE%:”,round(MAE_tree*100,1))*
你应该获得 15.1%的平均收益率。现在,让我们根据测试集来衡量准确度:
*Y_test_pred = tree.predict(X_test)
MAE_test = np.mean(abs(Y_test — Y_test_pred))/np.mean(Y_test)
print(“Tree on test set MAE%:”,round(MAE_test*100,1))*
我们现在获得大约 21.1%。这意味着我们的回归树过度适应历史需求:与历史数据集相比,我们在测试集中损失了 6 个点的 MAE。
更进一步
有很多方法可以进一步改善这个结果:
-优化树参数。
-使用更高级的模型(如森林、ETR、极端梯度推进)。
-优化输入数据。
-使用外部数据。
所有这些都在供应链预测数据科学一书中有解释(亚马逊上有售)
关于作者
* [## Nicolas vande put——顾问,创始人——供应链| LinkedIn
查看 Nicolas Vandeput 在世界上最大的职业社区 LinkedIn 上的个人资料。尼古拉斯有 7 份工作列在…
www.linkedin.com](https://www.linkedin.com/in/vandeputnicolas/)
icolas Vandeput 是一名供应链数据科学家,擅长需求预测和库存优化。他在 2016 年创立了他的咨询公司 SupChains ,并在 2018 年共同创立了 SKU 科学——一个快速、简单、实惠的需求预测平台。尼古拉斯对教育充满热情,他既是一个狂热的学习者,也喜欢在大学教学:自 2014 年以来,他一直在比利时布鲁塞尔为硕士学生教授预测和库存优化。自 2020 年以来,他还在法国巴黎的 CentraleSupelec 教授这两个科目。他于 2018 年出版了 供应链预测的数据科学(2021 年第 2 版)和 2020 年出版了 库存优化:模型与模拟 。
*
城市规划的机器学习:估算停车容量
哈佛数据科学顶点项目,2019 年秋季
Figure 1. Map of predicted proportion of driveways in Somerville by block
注:本文由 Josh Feldman、Lipika Ramaswamy 和 Anthony Rentsch 共同撰写。
如果一切按计划进行,马萨诸塞州的萨默维尔——波士顿外围的一个城市——将在 2021 年获得一条新的地铁线。虽然这条新线路令人兴奋,但它可能会给现有的全市居民路边停车计划带来问题。如果居民开车到这些新车站,把车停在附近的街道上,住在这些街道上的人会失去停车位吗?还是可以停在他们的车道上?
为了解决像这样的交通规划问题,萨默维尔正在对他们的停车供应进行审计。他们对路内停车容量有很好的估计,但是他们关于路外停车的数据要少得多。他们的问题看似简单:萨默维尔有多少住宅单元有路外停车场?
对于我们哈佛大学数据科学硕士项目的顶点项目,我们与萨默维尔市合作回答了这个问题。我们的第一步是弄清楚计算车道数的确切含义。虽然我们可以为全市范围内的车道数量提供一个具有置信区间的单点估计,但萨默维尔的规划者可能需要在不同的粒度级别上合计车道数。我们希望为他们提供包裹级别的精确概率估计以及这些概率的不确定性。
首先,我们需要标签。萨默维尔市为我们提供了整个城市的光栅格式的航空卫星照片,我们使用 GIS 软件将这些照片分成每个地块的图像。接下来,我们编写了一个脚本来下载每个地块的 Google 街景图像。我们随机抽样了 600 多个地址,并根据我们在卫星和街景照片中看到的内容,手动标记它们是否有车道。我们在评估数据中注意到,还有数百个地块被标记为有车库,因此我们将这些地块添加到标记为有车道的地块中。
Figure 2. Examples of aerial and street view imagery
特色工程
为了预测一个住宅单元是否有车道,我们从各种来源收集和设计特征,以输入到监督学习模型中。我们使用了萨默维尔的税收评估数据库来获取大量关于房屋的信息,从建造年份到屋顶风格。
两个非常有价值的信息来源是包裹和建筑足迹。我们使用这些多边形来测量房屋和地块边缘之间的空间以及房屋在地块上的中心位置。据推测,有车道的房子坐在一边,一侧有足够的空间来容纳一辆汽车。
除了这些几何和空间特征之外,我们还汇总了地块的街道停车许可,假设更多的停车许可将表明一个单元不能在车道或车库中停车。
Figure 3. Visualization of our feature engineering process with building and parcel footprints
建模
生成特征后,我们尝试将各种二元分类器与我们的数据相匹配,结果变量是房子是否有车道。
最初,我们尝试使用卷积神经网络从我们的图像数据中提取特征并进行预测,但我们标记的照片非常少,而且它们的质量太低,无法使用,尽管我们进行了大量尝试来执行数据增强,合并迁移学习,并调整我们的网络架构。
相反,税务评估数据和手工设计的功能与传统的机器学习相结合,被证明比深度学习更有效。
我们将几个分类器用于该数据,包括逻辑回归(有和没有交互)、随机森林、AdaBoost、XGBoost 和前馈神经网络。我们还试验了这些模型的堆叠组合。
我们的问题也有很大的阶级不平衡。在我们手工标记的包裹中,代表了一个随机样本,82%有车道。为了弥补这一点,我们天真地在没有车道的情况下对宗地进行过采样,我们发现这种技术比合成少数过采样技术(SMOTE)和自适应合成采样(ADASYN)等更先进的技术更能提高性能。
逻辑回归和随机森林获得了可比的性能。我们选择随机森林,因为它能更好地捕捉特征和标签之间关系的非线性。这种基于树的模型还通过特征重要性提供了可解释性。
Figure 4. Feature importances from random forest model
后期造型
由于我们的模型将被萨默维尔市用于交通规划,我们希望在宗地级别上进行概率估计。为此,我们需要精确校准的概率,即反映事件真实可能性的概率。
不幸的是,许多机器学习模型,如随机森林,默认情况下不会产生校准良好的概率。此外,我们对少数民族类的上采样将许多原始随机森林得分推向 0.5,尽管我们预计大多数地块都有车道。
为了解决这个问题,我们执行了一个校准步骤来调整我们的模型产生的概率。对于我们预测有 70%机会拥有车道的单元,我们希望这 70%是真的。
我们使用了一种叫做 Platt scaling 的技术,它涉及到对我们未校准的预测概率和标签进行逻辑回归拟合。需要注意的是,我们希望用于校准模型的数据分布反映出我们对萨默维尔市车道总体分布的预期。在拟合这个模型之前,我们重新平衡了我们的校准集,使得车道在这个集中的比例大约为 82%。
这种校准技术使许多概率更接近于 1,反映了我们有根据的信念,即萨默维尔的大多数地块都有车道。
Figure 5. Calibration curves for uncalibrated and calibrated predictions on labelled data
估算
最后,由于我们希望萨默维尔市的分析师能够估算任何聚合级别(如街区或社区)的车道数,因此我们正式提出了一种方法来进行估算。
我们将每个地块中车道的存在 Y 建模为伯努利随机变量,其相应的概率 p 由两步分类器和校准模型估计。我们假设,根据我们的模型 X 中使用的特征,车道的存在以及车道在任何地块上存在的相关概率独立于其他地块。这一假设很重要,因为当我们考虑车道预期数量的变化时,它允许我们忽略任何空间相关性。
Figure 6. Variance derivation
要获得车道的预期数量,我们可以合计所有感兴趣宗地的概率。为了获得方差,我们首先创建了许多训练数据的自举样本,并为每个样本拟合了一个新的随机森林模型。然后,我们为每个地块计算了一组概率,每个自举样本一个。为了获得宗地级别估计的方差,我们计算了每个宗地的 p⋅ (1- p )的均值和 p 的方差,并将它们相加。最后,为了获得感兴趣的聚集级别的方差,我们可以对所有这些宗地级别的方差求和。
使用这种方法模拟车道的存在允许在任何地理水平上的统计上合理的聚集。如果我们添加任何一组地块的预测和方差,我们可以恢复有效的点估计和置信区间。
总体而言,我们估计在该市的 12,069 个住宅区中存在 10,288 条机动车道+/- 74 (2 个标准误差),尽管不同的街区有不同的机动车道比例,这可以在街区级别预测的地图中看到。
最终想法
我们进入这个项目的目的是使用最先进的计算机视觉和深度学习技术从卫星和街道视图图像中提取信息,以确定它们是否有车道。我们发现这个策略对于问题和手头的数据既不合适也不有效。
相反,采取更传统的机器学习方法结合由领域知识和现实不确定性估计启发的智能特征工程是有效的。我们希望我们的工作为萨默维尔市的分析师提供价值,因为他们计划新的地铁站和更多。
有关哈佛数据科学峰会的更多信息,请访问:capstone.iacs.seas.harvard.edu。
机器学习:从炒作到现实应用
如何利用新兴技术推动商业价值?
炒作是真实的。人工智能(AI)机器学习(ML) 遍布媒体,每个人都想参与到技术竞赛中。过去几年的进步绝对是巨大的,你可能听说过诸如“人工智能是新的电力”和“人工智能将彻底改变我们的社会”之类的说法。我不会对这些言论发表评论,但我们都可以有把握地同意的是,肯定有很多人对这些技术感兴趣。然而,所有这些关注回避了一个重要的问题:它真的能不负众望吗?
在某些领域,技术已经赶上,甚至超过了宣传。例如,在图像识别中,识别物体并从图像中提取信息的任务,人工智能现在正在超越人类水平的表现(即,机器在识别物体和图像方面实际上越来越好于人类)。
当在正确的用例中正确应用时,人工智能解决方案可以为您的业务提供巨大的价值。然而,随着围绕 AI 和 ML 的所有关注和炒作,清楚如何和何时应该使用这些技术变得非常重要。
参考上图中的“Gartner 新兴技术炒作周期”,我们看到“AI/深度学习”一直位于炒作周期的顶端。关于这一点的好处是,有很多关于这些技术提供的可能性的关注。但是,与此同时,人们需要意识到,在某些情况下,期望和现实之间可能存在不匹配。这使得超越宣传并展示如何正确应用 AI/ML 和数据分析以解决业务相关案例并提供真正价值变得更加重要。
人工智能革命:为什么是现在?
为什么我们突然有了这种围绕 AI 的炒作?人工智能和人工智能已经存在很长时间了,但有一些关键因素可以解释为什么这些技术在最近几年才真正开始起步。
一个至关重要的因素当然是可用数据的数量。访问大量数据是 ML 如此强大的关键因素之一。无论是记录数据的设备数量,还是它们之间通过物联网(IOT) 的连接性,可用数据量都在呈指数级增长。
当然,访问大量数据是一回事。另一个是能够处理这些数据,以便提取有用的信息。获取廉价而强大的计算资源对于推动人工智能和人工智能的发展至关重要。作为计算能力巨大发展的直观例子,让我们看看上图。在左边,我们有一张大约 15 年前世界上最快的超级计算机 NEC 地球模拟器的(部分)图像。而今天,你可以买一台普通的游戏电脑,并且基本上拥有相同的计算能力。
访问大数据和大规模计算能力的互补因素使得大规模处理数据成为可能,而这在几年前还是不可行的。随着谷歌和脸书等科技巨头开放大部分研究的额外好处,我们现在有了一个很好的起点来解决新的有趣的问题。
跨职能协作打造优质产品
超越宣传,真正构建为您的业务提供真正价值的解决方案,有几个重要因素需要考虑。涉及算法、计算机和数据的技术方面是一回事,但为了构建好的解决方案,你需要跨职能的合作。
领域知识:一方面,你需要对你要解决的问题有领域知识的人。在一个系统中有哪些可能性和局限性,如何在实践中应用该解决方案?
数据科学:你还需要数据科学内部的能力,这涉及到与分析、统计、信号处理、机器学习、人工智能和深度学习相关的一切。本质上,提取和利用数据中的模式和信息的方法和技术
软件工程:软件工程技能对于构建良好的数据驱动解决方案至关重要。这包括建立基础设施,通过适当的管道收集和处理数据,管理对数据的访问,并最终为最终用户建立实用和用户友好的软件工具。
最重要的是,你需要成功地将所有这些因素结合起来,才能制造出好的产品。
什么是机器学习?
机器学习是人工智能的主要分支之一,也是目前在开发新的更好的解决方案方面取得很多进展的领域。不涉及技术细节,ML 本质上就是从数据中提取有价值的信息。在这个上下文中,数据可以是来自文本、视频、图像、声音、传感器数据等的任何东西。典型的人工智能解决方案包括对图像和视频进行分析和分类的模型,通过传感器数据监控复杂工业设备的“健康状态”或者预测您企业的未来销售预测。(我们将在文章末尾回到一些具体的用例示例)
深度学习:从炒作到应用
重要的是要记住,深度学习不是魔法,而是基于处理图像等信息的数学模型(毕竟,图像只是计算机看到的数字集合)。
术语“人工神经网络”来自大脑处理信息的方式。人工神经网络模型并不试图复制人脑,但它们大致受到“神经元”数学模型的启发,神经元是神经信息处理的构建模块之一(因此得名神经网络)。
这些人工神经网络的分层结构(如上图所示)是我们将这种类型的建模称为“深度学习”的原因。模型的较深层(图的左边部分)通常提取关于尖锐边缘和基本形状的信息,而上层(图的右边部分)检测更精细和更详细的结构。
学习这些模型如何正确分类图像是一个耗时且计算量大的过程。我们本质上用正确分类的图像的例子来呈现该模型,然后该模型尝试自己对新图像进行分类。最初,预测只是随机猜测,但通过向模型显示足够多的图像,并在每次做出错误猜测时进行纠正,它最终学会提取相关信息,以便正确分类。
令人惊讶的是,我们不必告诉模型要寻找什么——它通过经验自己学习这些特征(我们称之为“机器学习”的原因)。
近年来,这一领域的进展令人惊讶,这主要是由于可以访问大量数据和廉价的计算能力。许多任务的性能现在已经超过了人类的水平(即,在识别和分类物体和图像方面,机器实际上正在变得比人更好)。当然,这有许多非常有趣和有用的应用,我们很快就会谈到。
人工智能和创造力
我们通常认为“智能”是执行任务的能力,我们通常将它与人类智能联系在一起。一个这样的任务例如可以是产生艺术或音乐的创造性能力。足够有趣的是,即使对于这些类型的创造性“人类”任务,我们现在也看到人工智能表现得惊人地好。
为了说明这一点,我展示了上面的一个例子,其中一个人工智能模型被训练成以挪威著名画家爱德华·蒙克的风格生成图像。给定一个训练有素的模型,我们就可以使用新风景的图片作为“人工智能艺术家”的“灵感”,并以人类艺术家的绘画风格复制它。效果出奇的好,你不觉得吗?
上面的例子也许不是很有用(虽然很有趣)。然而,它很好地说明了底层技术从图像中提取有意义信息的能力,这反过来对其他应用程序也非常有用。
机器学习的现实应用
为了展示我们工作的主题的大跨度,我挑选了几个 ML 如何在现实世界中使用的例子。这些例子从使用数据分析和 ML 进行重型工业设备的状态监控,到使用计算机视觉进行质量保证以及各种图像识别和物体检测任务。你也可以在这里阅读我们其他令人兴奋的项目。
利用传感器数据的质量保证
上述案例是一个典型的生产公司,例如,可能涉及复杂设备的制造或控制加工厂。一般来说,任何最终产品是某种生产单位的东西。
上图所示的简化视图旨在通过传感器数据利用所有可用信息,并揭示测量变量和生产质量之间的关系。变量 x 影响生产质量吗?在当前的操作条件下,我的产品出现缺陷的风险有多大?为了提高产品质量,生产的哪一部分最需要优化?这些是我们可以通过适当利用现有数据来回答的一些问题。
状态监控
作为一个具体的例子,我们可以例如考虑将传感器数据用于压缩机的状态监控。在这种情况下,我们监控传感器数据(温度、压力、振动、++),ML 模型根据积累的经验学习什么是“正常的”。该模型持续寻找记录数据中的异常和即将发生的故障/故障的迹象。如果根据测量的变量,行为看起来可疑,该模型可以生成警报或启动预防措施。
即将发生的故障的早期预警对于基于状态的维护和维修计划等具有重要价值。利用这种解决方案有助于避免由于早期预警导致的突然故障,从而允许采取预防措施并控制关键设备的关闭。如果您有兴趣了解更多关于如何使用 ML 进行状态监控的信息,您可以阅读下面的文章
用于质量保证的图像识别
上图展示了这种技术在质量保证中应用的例子。在这种情况下,模型分析图像,寻找某些确定的特征,如腐蚀、损坏、裂纹、焊接不良等。也许不如创作艺术有趣,但对许多工业应用来说肯定非常有用。
水产养殖中的图像识别
另一个例子是在渔场中应用对象检测来监控鱼的健康。这在今天是一项非常具有挑战性的任务,因为鱼在水下基本上无法直接目视检查。一个新的创新解决方案是利用水下摄像机和人工智能解决方案进行自动图像和视频分析。这允许实时提取关于鱼类健康和幸福的重要信息。这是一个好消息,无论是从动物福利的角度,还是从健康的鱼对养鱼场主来说更有利可图的事实来看。在这里了解更多关于这个项目的信息
从技术到商业价值:主要收获
主要的信息是,一个人应该始终专注于带来商业价值的东西。新兴技术肯定可以成为实现这一目标的推动者,但专注于业务方面对于新计划和项目的成功至关重要。
要打造优秀的产品和创新的解决方案,不同专业领域之间的合作是关键。当领域专家和软件/分析专业知识合作,充分发挥新兴技术的优势时,最佳解决方案就会出现。
如果您对如何超越宣传进入现实生活的应用程序感到好奇,请随时与我们聊聊技术和软件解决方案如何帮助解决您的业务需求。
这篇文章最初出现在axbit.com/blog
你觉得这篇文章有趣吗?如果是这样的话,你可能也会喜欢我的其他一些关于人工智能、机器学习、物理等主题的文章。,你可以在下面的链接和我的中型作者简介中找到:
2018 年夏天我发表第一篇关于“走向数据科学”的文章时,数字背后的统计数据…
medium.com](https://medium.com/@vflovik)
而且,如果你想成为一个媒体会员,免费访问平台上的所有资料,你也可以使用下面我的推荐链接。(注意:如果您使用此链接注册,我也会收到一部分会员费)
[## 通过我的推荐链接加入 Medium—Vegard flo vik
作为一个媒体会员,你的会员费的一部分会给你阅读的作家,你可以完全接触到每一个故事…
medium.com](https://medium.com/@vflovik/membership)
更多来自 Vegard Flovik 媒体:
- 蒙特卡洛方法简介
- 从物理学到数据科学的转变
- 什么是图论,为什么要关心?
- 用于图像分类的深度迁移学习
- 建造一个能读懂你思想的人工智能
- 人工智能和大数据隐藏的风险
- 如何使用机器学习进行异常检测和状态监控
- 如何(不)使用机器学习进行时间序列预测:避免陷阱
- 如何利用机器学习进行生产优化:利用数据提高绩效
- 你是怎么把物理教给 AI 系统的?
- 我们能使用纳米级磁铁构建人工大脑网络吗?
- 供应链管理中的人工智能:利用数据推动运营绩效
研讨会演示—从宣传到实际应用
Conv 网络-影像分类张量流 Keras 示例
Photo by David Sola on Unsplash
Kaggle 是一家公司,其商业模式是让来自世界各地的数据科学家竞争,为给定的问题建立最佳性能模型。换句话说,为了收费,Kaggle 为希望使用众包来解决数据问题的企业举办比赛。
在 Kaggle 比赛中,你会得到一套训练装备和一套测试装备。提供了测试集的功能,但隐藏了标签。目标是训练训练集,并使用它来预测测试集的目标标签。预测结果存储在提交文件中,并上传到 Kaggle 进行评估。参赛者可以看到他们的模型如何与其他竞争者相抗衡,并相应地调整他们的模型。当比赛结束时,第三套,其特征和标签的参赛者从来没有接触过,被用来确定赢家。通常情况下,这将惩罚那些模型倾向于过度拟合(即高方差)的团队。
有一个著名的例子,网飞提供了 100 万美元的奖金,但最终获胜的模型对他们来说太复杂了,无法投入生产。除此之外,Kaggle 的竞赛已经产生了一些好的结果。例如,保险公司好事达(Allstate)发布了一项挑战,在给定驾驶员属性的情况下,该模型近似于车祸的概率。202 名竞争者最终将好事达的模式提高了 271%。
在接下来的文章中,我们将通过一个 kaggle 竞赛来确定一个给定的图像是否包含一个 仙人掌。 比赛可以在这里找到。
密码
在机器学习中,每当你在处理图像时,你应该自动思考卷积神经网络。幸运的是,Keras,一个运行在 Tensorflow 之上的高级 API,抽象出了构建神经网络的大量复杂性。
import cv2
import os
import pandas as pd
import numpy as np
from matplotlib import pyplot as plt
from keras.models import Sequential
from keras.layers import Flatten, Conv2D, MaxPool2D, Activation, Dense, Dropout
from keras.optimizers import Adam
from keras.preprocessing.image import ImageDataGenerator
如果你想继续,继续从 Kaggle 下载训练和测试集,并将它们复制/解压缩到你的工作目录中。
train_directory = 'train'
test_directory = 'test'
此外,我们得到一个文件,其中包含每个图像的 id,以及它是否由仙人掌组成。
df = pd.read_csv('train.csv')
df.head()
让我们看看我们在做什么。
img = cv2.imread('train/0004be2cfeaba1c0361d39e2b000257b.jpg')
plt.imshow(img)
每个图像的高度和宽度分别为 32 像素和 32 像素。第三维度是指色彩。值 1 意味着它是灰度图像,其中每个像素的亮度范围从 0 到 255。值为 3 意味着它是一个 RGB 图像。在 RGB 图像中,每个像素都有红色、绿色和蓝色属性,每个属性的范围从 0 到 255。
img.shape
Keras ImageDataGenerator 对象可用于应用数据扩充。执行数据扩充是正则化的一种形式,使我们的模型能够更好地泛化。在训练阶段,根据提供给 ImageDataGenerator 的参数随机调整每批新数据。
train_datagen = ImageDataGenerator(
rescale=1./255,
validation_split=0.15,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True
)
让我们仔细分析一下这些论点的含义。
- ****重新缩放:重新缩放像素,使其亮度范围从 0 到 1
- validation_split :为验证而留出的图像部分
- shear_range :在固定方向随机移动每个点
- zoom_range :随机放大图片内部。如果你传递一个浮点数,那么
[lower, upper] = [1-zoom_range, 1+zoom_range]
- ****horizontal _ flip:随机水平翻转图像
通常情况下,您将要处理的图像要么放在具有各自类名的文件夹中,要么放在 CSV 或 JSON 文件中的一个文件夹中,该文件将每个图像映射到其标签。例如,在第一个场景中,所有包含仙人掌的图像都放在名为 cactus 的目录中,所有不包含仙人掌的图像都放在名为 no_cactus 的单独目录中。在这种情况下,我们会在图像旁边看到一个 CSV。我们可以使用flow_from_dataframe
方法将每个图像与其标签关联起来。
df['has_cactus'] = df['has_cactus'].astype(str)train_generator = train_datagen.flow_from_dataframe(
df,
directory = train_directory,
subset = 'training',
x_col = 'id',
y_col = 'has_cactus',
target_size = (32,32),
class_mode = 'binary'
)
val_generator = train_datagen.flow_from_dataframe(
df,
directory = train_directory,
subset = 'validation',
x_col = 'id',
y_col = 'has_cactus',
target_size = (32,32),
class_mode = 'binary'
)
接下来,我们可以着手构建我们的模型。我们网络的最后一层只有一个神经元,因为我们正在执行二元分类。在隐藏层中使用卷积和最大池来尝试和学习底层模式(例如,仙人掌看起来像什么)。
model = Sequential()model.add(Conv2D(32, (3,3) ,activation = 'relu', input_shape = (32,32,3)))
model.add(Conv2D(32, (3,3), activation = 'relu'))
model.add(MaxPool2D(2,2))
model.add(Conv2D(64, (3,3), activation='relu'))
model.add(Conv2D(64, (3,3), activation='relu'))
model.add(MaxPool2D(2,2))
model.add(Conv2D(128, (3,3), activation='relu'))
model.add(MaxPool2D(2,2))model.add(Flatten())
model.add(Dense(512, activation = 'relu'))
model.add(Dropout(0.2))
model.add(Dense(1, activation = 'sigmoid'))
我们使用binary_crossentropy
作为我们的损失函数,因为它是一个二进制分类问题,我们基于准确度来测量我们的模型的性能,并且我们使用Adam
来最小化损失函数。
model.compile(
loss = 'binary_crossentropy',
optimizer = Adam(),
metrics = ['accuracy']
)
在机器学习的背景下,每个训练步骤我们都会计算梯度。如果我们使用小批量梯度下降,那么在一个步骤中, x 个例子被处理,其中 x 等于批量大小。例如,如果您有 2,000 个图像,并且批次大小为 10,则一个时期由 2,000 个图像/ (10 个图像/步骤)= 200 个步骤组成。
通常,我们会将批量大小作为参数传递给 fit 函数。然而,由于 Keras 数据发生器意味着无限循环,Keras 无法确定一个时期何时开始,另一个时期何时开始。因此,我们使用steps_per_epoch
和validation_steps
,它们简单地等于ceil(num_samples / batch_size)
。
history = model.fit_generator(
train_generator,
steps_per_epoch = 2000,
epochs = 10,
validation_data = val_generator,
validation_steps = 64
)
我们加载测试样本,确保标准化数据,使每个像素的亮度范围从 0 到 1。然后,我们使用我们的模型来预测图像是否包含仙人掌。
ids = []
X_test = []for image in os.listdir(test_directory):
ids.append(image.split('.')[0])
path = os.path.join(test_directory, image)
X_test.append(cv2.imread(path))
X_test = np.array(X_test)
X_test = X_test.astype('float32') / 255 predictions = model.predict(X_test)
最后,我们创建提交文件。
submission = pd.read_csv('sample_submission.csv')
submission['has_cactus'] = predictions
submission['id'] = idssubmission.head(10)
我们将 index 设置为 false,否则,它将为每一行添加一个索引作为第一列。
submission.to_csv('submission.csv', index = False)
能源领域的机器学习
能源专家指南
在文章结束时,你将能够回答下列问题:
- 什么是机器学习?
- 为什么机器学习现在这么火?
- 什么是驾驶性能?
- 有哪些挑战?
- 今天的机器学习和能源是怎么回事?
- 能源和机器学习的未来会怎样?
词汇表
人工智能=感知环境并采取行动实现目标的机器。
机器学习=人工智能的一个分支,赋予计算机从数据中学习高维模式的能力。
深度学习=一系列机器学习模型,使用多层神经网络来逼近函数。
什么是机器学习?
下一万家创业公司的商业计划书很容易预测:取 X 加 AI —凯文·凯利
机器学习是自科学方法以来,我们在如何做工程方面取得的最大进步——Steve juventson
炒作已经正式见顶——深度学习正处于膨胀的预期的顶峰。
深度学习是现代机器学习炒作的基础。深度学习使用复杂的多层神经网络从大型数据集学习模式。这是机器学习的初级智能——模式识别。
机器学习已经在一系列困难问题上超越了先前的技术水平。它正在影响每个行业——这种能力源于神经网络从我们使用和学习的原始高维数据(如图像或文本)中学习的能力。
那么我们今天在哪里?目前,机器学习在计算机视觉和语言处理方面形成了突破性表现的核心部分。任务对象识别、图像分类、语音识别和语言翻译的最新技术都是由深度学习驱动的。
谷歌、亚马逊和脸书都拥有世界级的人工智能实验室,他们的大部分业务已经被机器学习所改变。机器学习的潜力在数字化程度较低的行业(如医疗保健、能源或教育)中更具潜力。
机器学习对人工智能
到目前为止,机器学习提供了狭义的人工智能(AI)。这些系统的能力通常是超人的,足以证明围绕机器学习的宣传是正确的。典型地,该任务涉及使用高维数据(即图像)的感知。这是机器学习的主要贡献——能够从原始的高维数据中创造商业价值。
这种狭隘的智能与许多人工智能研究人员的目标形成了鲜明对比——通用人工智能,即一台机器可以执行一台机器可以完成的各种任务。虽然几乎可以肯定,机器学习将成为通用人工智能的一部分,但要提供一台可以执行各种任务的智能机器,还需要更多的东西。
机器学习和人工智能不应该互换使用。机器学习只是更广泛的人工智能领域的一个子集。AI 包含多种不同的方法,超出了本文的范围。
机器学习经常与人工智能混淆的一个原因是现代机器学习的表现如何——一些研究人员甚至认为这是我们解决一般智能问题所需的全部。具体需要什么还不清楚,但我们离提供一般情报还有许多突破。狭义的超人类机器智能已经在这里了。
机器学习的三个分支
为了学习这些模式,机器学习利用三种不同的学习信号,这将机器学习分成三个分支。
第一个是监督学习,机器使用带标签的训练数据来学习如何预测看不见的数据的标签。例子包括时间序列预测、计算机视觉和语言翻译。监督学习是为什么脸书可以分辨出你的照片中是你的哪个朋友,或者为什么谷歌可以翻译你智能手机上照片的文本。
ImageNet 上计算机视觉的最新进展基准— 人工智能的恶意使用:预测、预防和缓解
第二个是无监督学习,机器能够在没有标签监督的情况下生成新数据。示例包括艺术风格转换和生成逼真的人脸。
生成对抗网络(GANs)学习使用两个竞争的神经网络来生成逼真的图像。一个网络生成图像(生成器),第二个网络必须决定图像是真是假。这种对抗性学习是可以有效的。
右边的所有图像都是机器生成的— Karras et。al (2019)一种基于风格的生成式对抗网络生成器架构(NVIDIA)
对抗性学习也可以用在我们机器学习的最后一个分支——强化学习。在强化学习中,机器在标量奖励信号的监督下学习选择动作。强化学习适用于各种带有奖励信号的决策问题,如成本或碳排放。
现代强化学习皇冠上的明珠是 2016 年 AlphaGo 战胜 Lee Sedol。围棋是人工智能在棋盘游戏中面临的最后一个巨大挑战——创造一台超人围棋计算机被认为是十年之后的事情。AlphaGo 使用深度神经网络从高维棋盘状态映射到最佳下一步棋。
李·塞多尔最终以 4 比 1 输给了 AlphaGo — AlphaGo 影片
AlphaGo 与 1996 年战胜 Garay Kasparov 解决国际象棋问题的计算机“深蓝”形成鲜明对比。深蓝的所有智能都源自一个程序员和国际象棋大师团队,他们手工将棋步输入机器。这与 AlphaGo 使用的监督形成了对比——通过在围棋比赛中玩自己来学习。
deep mind(alpha go 背后的伦敦实验室)随后推出了 AlphaZero,它以 100 比 0 击败了之前的版本。这个版本从不依赖于人类专家行动的数据集,完全从对抗性的自我游戏中学习。
为什么机器学习现在这么火?
这三个分支中的每一个都正在经历一个巨大的表现期、研究活动期和宣传期。所有这些改进的基础是深度学习——使用多层神经网络作为复杂函数逼近器。
这些人工神经网络的灵感来自于我们大脑中的生物神经网络。机器使用的人工神经网络要简单得多——但它们正在推动现代机器学习的性能。
神经网络就像任何其他功能一样,它接受一些输入并产生一个输出。将高维数据样本降维是机器学习的基本过程。例子包括从卫星图像预测太阳能发电,或从电网数据调度电池。
神经网络是通用的。如果神经网络只适用于计算机视觉,这仍然是一件大事。然而,神经网络正在向多个方向拓展。神经网络的这种普遍性使它们能够在广泛的问题上达到最先进水平,也使机器学习能够应用于广泛的行业。
神经网络的原子单元是感知器——一个简单的模型,它结合来自其他感知器的输入,通过非线性函数(如 sigmoid 或整流器)挤压它,并将输出发送给子感知器。这方面的数学问题超出了本文的范围——关键的要点是,将这些感知机堆叠到许多层中,可以让神经网络从大量数据中学习复杂的功能。
机器学习不仅仅是深度神经网络——像逻辑回归和随机森林这样的算法适用于许多商业问题。经典机器学习的问题是,它没有从海量数据中受益。因为神经网络的容量可以通过增加深度来增加,所以神经网络能够突破经典机器学习模型的限制。
深度神经网络能够从海量数据中学习— 改编自《AI 是新电》(吴恩达)
选择图层是为了利用原始数据中的结构。三个常见层完全连接,卷积和递归。
Deep mind Atari 作品2015中使用的深度卷积神经网络
卷积层受到我们自己的视觉皮层的启发,是现代计算机视觉的动力。它们允许机器看到。它们可以用来对图像内容进行分类,识别人脸并为图像创建标题。
一个展开的递归神经网络— colah 的博客
递归层处理输入并生成序列输出,为现代自然语言处理提供动力。递归网络允许机器理解数据中的时间结构,例如句子中的单词。
看到和理解语言的能力不仅能提高性能,还能让机器学习一般化。视觉和语言理解是低级技能,基本上用于人类生活的每个领域。掌握这些低级技能意味着机器可以在一系列行业中发挥作用。能量也不例外。
是什么驱动了现代机器学习的性能?
现代深度学习的性能是由两个过程的交互作用驱动的——数据可用性的增加和用大量数据训练大型模型的能力。
互联网和生成原始数据(传感器、图像和文本)的设备的兴起导致了对海量数据集的监管。这些海量数据集是深度神经网络的食物——没有数据,模型就无法学习。
训练大型模型的能力依赖于访问云中专门硬件的能力。在 21 世纪初,研究人员重新利用为视频游戏设计的硬件(图形处理器,或 GPU)来训练神经网络。这导致训练时间大幅加快,这很重要——我们对机器学习的所有理解都是经验性的(通过实验学习)。
第二个硬件趋势是云计算。云提供了在完全可变成本基础上进行计算的途径。亚马逊网络服务等平台允许按需访问大量支持 GPU 的计算能力,同时提供廉价的数据存储。这种对计算能力的获取在大型科技公司内部和小型公司中都有效。它使资产负债表受益于将资本支出(建设数据中心)转变为运营支出。
推动现代机器学习的最后一个趋势是获取算法和工具。几乎所有机器学习的相关文献都可以在 arXiv 这样的网站上免费获得。还可以在 GitHub 上访问机器学习工具的高质量实现。这种开放趋势与能源行业的付费墙和授权软件形成了鲜明的对比。
挑战
机器学习面临着广泛的挑战。检查所有这些问题超出了本文的范围——诸如可解释性、工人置换和滥用强大的狭义人工智能等问题是重要的问题,也是许多研究的焦点。将我们今天拥有的强大、狭隘的机器智能扩展为通用的人工智能,还有许多工作要做。相反,我们将专注于使用机器学习解决能源问题的具体挑战。
主要挑战是获取数据。能源行业仍处于数字化过程中——我在能源领域的所有工作都涉及建立基本的数据收集基础设施。我们已经看到了大量数据对机器学习的重要性——缺乏历史数据可能会阻碍许多能源和机器学习项目。
有远见的能源公司知道数据只能收集一次。它不仅仅是一个本地历史学家记录来自现场控制系统的数据。21 世纪能源公司拥有从传感器级数据到会计数据的一切数据,可供全球范围内需要这些数据的员工和机器接近实时地使用。
大型有趣数据集的管理是能源公司可以建立的少数可防御优势之一(另一个是品牌)。这些数据集很有价值,不仅因为我们今天可以如何使用它们,还因为明天可以产生的洞察力。
当考虑将机器学习应用于能源问题时,首先也是最重要的考虑因素是数据集。其实很多机器学习项目的第一步都是一样的——开始收集数据。用于监督机器学习的数据集有两个部分-特征(如图像或原始文本)和目标(您想要预测的内容)。用于强化学习的数据集是一个模拟器——学习算法可以与之交互的东西。
机器学习在能源领域的一些潜在应用包括(但不限于):
- 预测性维护
- 客户细分
- 流失预测和最小化
现在,我们将深入探讨当今机器学习在能源领域的一些应用细节。
时间数列预测法
能源的经济和环境影响取决于使用时间。预测一直是能源领域的一项重要实践——可变风能和太阳能的增加使用使得预测更有价值。DeepMind 声称,通过提前 36 小时预测,能源价值提高了 20 %。更好的预测可以增加可再生能源的价值,减少对备用化石燃料的需求。
特别令人兴奋的是使用卫星图像和深度卷积神经网络预测风力或太阳能的能力——参见杰克·凯利和丹·特拉弗斯在开放气候修复的工作。
控制
复杂能源系统的最优控制是困难的。强化学习是一个决策框架,可以应用于许多能源控制问题,奖励信号的可用性,模拟器
更好地控制我们的能源系统将使我们能够降低成本,减少环境影响和提高安全性。
DeepMind 的数据中心优化是能源和机器学习最著名的例子。该算法使用数千个传感器在五分钟的基础上做出决策。这些传感器将数据输入深度神经网络,该网络预测不同的行动组合将如何影响未来的冷却发电效率。
这听起来像是 DQN 的一种形式——一种强化学习算法,可以预测每个可能行为的未来回报。
神经网络在云上执行计算,在本地控制系统进行安全验证之前,将建议的行动发送回数据中心。
数据中心的性能使用每吨冷却能量输入(kW/tonC)来衡量,并随着数据的增加而提高,在九个月内从最初的 12%提高到 30%。
关键要点
我们刚刚旋风般地介绍了机器学习。关键要点是:
- 机器学习是正在工作的人工智能的子集
- 机器学习有三大分支——监督学习、非监督学习和强化学习
- 深度学习正在推动现代机器学习
- 视觉卷积,序列递归
- 性能由数据、云计算和算法的可用性驱动
更多技术和非技术机器学习资源,请查看 ml-resources 。对于强化学习资源,请查看 rl-resources 。
感谢阅读!
原载于 2019 年 4 月 25 日https://adgefficiency.com。
金融中的机器学习:为什么你不应该用 LSTM 的来预测股市
Photo by Markus Winkler on Unsplash
最近,机器学习有了很大的发展和兴趣,最有希望的成果是语音和图像识别。本文分析了一种深度学习方法——长短期记忆神经网络(LSTM 神经网络)在以标准普尔 500 为代表的美国股票市场上的应用效果。这篇论文表明,虽然这种技术在语音识别等其他领域可能取得了很好的成功,但在应用于金融数据时却表现不佳。事实上,它们的特点是高信噪比,这使得机器学习模型很难找到模式并预测未来的价格。
这篇研究文章的结构如下。第一部分介绍了 LSTM 和为什么他们可能适用于金融时间序列。第二节分析了 LSTM 应用于标准普尔 500 的性能。第三部分总结。
1.什么是 LSTM?
长短期记忆(LSTM)神经网络是一种特殊类型的深度学习模型。特别是,它是一种可以学习数据长期相关性的递归神经网络,因此通常用于时间序列预测。
图 1 显示了 LSTM 层的架构。
Figure 1 Architecture LSTM layer
如图所示,它由一个重复的核心模块组成。这种结构使得 LSTM 能够学习长期依赖性。第一 LSTM 块采用网络的初始状态和序列 X(1)的第一时间步长,并计算第一输出 h(1)和更新的小区状态 c(1)。在时间步长 t,该模块获取网络的当前状态(c(t 1),h(t 1))和序列 X(t)的下一个时间步长,并计算输出 ht 和更新的单元状态 ct。
Figure 2 Architecture LSTM block
图 2 显示了 LSTM 模块的架构,它由 4 个主要组件组成:
- 输入门:控制单元状态更新的级别
- 遗忘门:控制电池状态复位的电平
- 候选单元格:添加单元格状态信息
- 输出门:控制添加到隐藏门的单元状态的级别。
为了学习建模任务的特征并能够预测,需要训练 LSTM。该过程包括通过一些优化算法最小化目标函数(通常为 RMSE)来计算 LSTM 的权重和偏差。一旦模型在初始训练数据集上得到训练,并在验证集上得到验证,它就会在真正的样本外测试中得到测试。这确保了模型确实学习了有用的特征,并且它不会在训练集上过度拟合,对新数据的预测能力较差。下一节分析应用于标准普尔 500 的 LSTM 的性能。
2.绩效 LSTM 应用于美国股票市场
使用的数据集由美国股票市场的每日收盘价格组成,以标准普尔 500 为代表,从 1950 年 1 月 3 日到 2019 年 1 月 4 日,共 17,364 次观察。数据分为 60%用于训练,20%用于验证,20%用于测试。
图 3 显示了用于对数级分析的数据。
Figure 3 S&P 500 close prices (log scale)
在我们的分析中,我们训练了由 1 个隐藏层、20 个神经元和 20 个值的时间序列长度组成的 LSTM 神经网络。我们尝试了神经网络参数和架构的不同组合,发现了类似的结果。
图 4 显示了实际价格与训练有素的 LSTM 预测的第二天价格的比较。
Figure 4 LSTM predicted vs actual price for the S&P 500 (log scale)
从图中可以看出,预测值与实际价格非常接近,因此无法正确看到潜在的实际价格。因此,看起来 LSTM 在预测所考虑的时间序列的下一个值方面做得很好。
表 1 报告了预测第二天价格的 LSTM 准确度的性能统计。
Table 1 LSTM prediction accuracy stats
该数据证实了我们从图 4 中看到的情况。RMSE 中的低值和 R2 中的适当值表明,LSTM 可能擅长预测所考虑的时间序列的下一个值。
图 5 显示了从 2018 年 8 月 13 日到 2019 年 1 月 4 日,100 个实际价格与预测价格相比的样本。
Figure 5 LSTM predicted vs S&P 500 price for 100 days
这个数字让我们得出了不同的结论。总的来说,LSTM 似乎可以有效地预测第二天的值,但实际上,第二天的预测值与前一天的实际值非常接近。这可以从图 6 中进一步看出,该图显示实际价格比预测价格滞后 1 天。
Figure 6 LSTM predicted vs 1-day lagged S&P 500 price for 100 days
如图所示,2 系列几乎相同,证实了我们之前的结论。
这些结果表明,LSTM 无法预测股票市场第二天的价值。事实上,该模型能够做出的最佳猜测是一个与当天价格几乎相同的值。
3.结论
诚然,新的机器学习算法,尤其是深度学习,在不同领域都相当成功,但它们无法预测美国股市。如前面的分析所示,LSTM 只是使用非常接近前一天收盘价的值作为第二天的预测值。这是一个没有预测能力的模型所期望的。
这也突显出,尽管一些机器学习技术可能在金融领域有用,但量化对冲基金必须另辟蹊径,想出能够为客户带来阿尔法的策略。
如果您想了解我们投资产品的更多信息,请发送电子邮件至info@blueskycapitalmanagement.com或填写我们的信息请求表格。
最初发表于 蓝天资本 。
放弃
本文旨在学术和教育目的,而不是投资建议。我们提供的或来自我们网站的信息不应替代投资专业人士的建议。本文讨论的假设模型并不反映测试期间存在的任何实际产品或策略的投资业绩,也不能保证如果存在这种产品或策略,它会表现出类似的业绩特征。投资任何产品或策略的决定不应基于本文包含的信息或结论。这既不是出售要约,也不是购买证券权益的邀约。
JavaScript 中的机器学习
是不是更容易?难?还是单纯的好玩?
Picture on Unsplash by Luca Bravo
如果你以前尝试过机器学习,你可能会认为这篇文章的标题中有一个巨大的错别字,我打算用 Python 或 R 来代替 JavaScript。
如果你是一名 JavaScript 开发人员,你可能知道自从 NodeJS 创建以来,在 JavaScript 中几乎任何事情都是可能的。您可以使用 React 和 Vue 构建用户界面,使用 Node/Express 构建所有“服务器端”内容,使用 D3 构建数据可视化(Python 和 R 主导的另一个领域)。
在这篇文章中,我将向你展示如何用 JavaScript 执行机器学习!我们将从定义什么是机器学习开始,快速介绍 TensorFlow 和 TensorFlow.js,然后使用 React 和 ML5.js 构建一个非常简单的图像分类应用程序!
机器学习?那是什么?
除非你一直生活在一块石头下面,否则你很可能听说过机器学习(ML)和人工智能(AI)之类的词。即使你不是一个非常注重科学的人,你也可能在电视和互联网上看到过那些微软的广告,在那里人们谈论微软正在做的所有令人惊奇的事情。
事实是,几乎每个人在一生中的某个时刻都使用过机器学习和人工智能。划掉那个,每个人在生活中每天都在使用 ML 和 AI。从要求 Siri 和 Alexa 播放一些歌曲到使用手机上的导航应用程序来获得最快的上班路线,这都是 ML 和 AI。
但是我们如何定义这两个术语呢?让我们集中讨论 ML,因为它是本文的主题。用最简单的话说,机器学习就是:
一个研究领域,它允许计算机系统在没有给它任何具体指令的情况下做某事。
作为一名开发人员,你要以一种特殊的方式编写代码。您的客户或经理告诉您他们想要的输出是什么,您尝试编写一些代码来获得该输出。但是在机器学习中,你只知道需要解决的问题!你“教”你的计算机一些东西,然后坐下来,看看你从系统中得到什么惊人的结果!
要回答的问题是:我们如何进行机器学习?Python 程序员使用类似scikit-learn
和谷歌令人惊叹的TensorFlow
这样的包来执行机器学习。但是去年(2018 年),谷歌发布了 JavaScript 版本的 TensorFlow,优雅地叫做TensorFlow.js
!
但是为什么要用 JavaScript 做机器学习呢?首先,Python 的机器学习方式要求开发人员将机器学习代码保存在服务器上,然后使用 JavaScript 允许用户在客户端访问模型。这里我们遇到了一个潜在的问题。如果你的机器学习模型太受欢迎,很多用户都想访问它,那么你的服务器很有可能会崩溃!
但是如果我们使用机器学习,我们不仅为机器学习代码和用户界面代码保留了 JavaScript 环境,模型也将保留在客户端本身!还有,机器学习模型大多被金融公司使用。所以客户端 ML 模型意味着你的数据是私有的。
我们写点代码吧!
现在,您已经对 ML 有了一些基本的了解,并且知道了为什么用 JavaScript 来实现 ML 是一个好主意。但是 ML 是那些你可以通过尝试更好理解的东西之一。如果你想了解更多关于机器学习的内容,可以看看我不久前写的另一篇文章:
围绕着人工智能(AI)这样的话题,人们总是非常兴奋。当有人提到…
medium.com](https://medium.com/@geekyants/deep-learning-with-react-native-65fae456839d)
在本节中,我们将使用 React 构建一个机器学习应用程序,它可以执行一些非常好的图像分类。
侧栏:机器学习过程包括两个步骤:训练和测试。训练包括向模型提供大量数据,然后模型将处理这些数据并识别不同的模式,然后模型将使用这些数据进行未来预测。
由于我们正在构建一个图像分类模型,因此在我们能够做出任何预测之前,我们需要将数以千计的图像发送到该模型进行处理。图像需要以某种方式相互关联,老实说,我没有那么多图片(我是一个害羞的人)。还有,JavaScript 的机器学习对我来说还是新鲜的。所以作为一个捷径,我将使用一个预先训练好的模型。
在我们开始编码之前,请确保您的系统上安装了以下内容:
接下来是构建一个样板 React 应用程序。为此,请打开命令终端并运行以下命令:
$ npx create-react-app ml-in-js
该命令将创建一个名为ml-in-js
的文件夹,并在您的系统中构建一个启动应用程序。接下来,回到命令终端,运行以下命令:
$ cd ml-in-js
$ npm run start
第一个命令非常简单。真正的奇迹发生在第二部。npm run start
命令创建系统的本地开发级别,并在浏览器上自动打开,如下所示:
这个入门应用根本不知道什么是机器学习或者 Tensorflow。要解决这个问题,我们需要安装 Tensorflow.js 包。对于 Python 开发人员来说,您需要在您的系统上执行一次pip install tensorflow
,并且可以在任何地方和项目中自由使用这个包。但是对于 JavaScript,你需要为每个项目运行npm install
命令。
但我们不会在应用程序中安装 Tensorflow.js (TFJS)库,而是安装另一个名为 ML5.js 的库。这个库就像是 TFJS 的一个更好的版本,使我们在客户端进行机器学习变得更加容易。所以让我们像这样安装这个库:
$ npm install --save ml5
如果您想确保库安装成功,请转到src
文件夹中的App.js
文件,并编写以下代码:
import React, {Component} from 'react';
import * as ml5 from 'ml5';export default class App extends Component {
render() {
return (
<div>
<h1>{ml5.version}</h1>
</div>
)
}
}
如果你回到浏览器,你会看到一个大大的 0.4.1 印在屏幕上。根据 ML5.js 的最新版本,这个数字可能会有所不同。只要您看到屏幕上打印的数字,您就可以放心,您的 ML5 库已成功安装。
至此,我们完成了安装部分。现在,我们需要创建一个函数,它可以接收图像,并使用预先训练好的模型对其进行分类。为此,在App
组件中编写以下代码:
classifyImage = async () => {
const classifier = await ml5.imageClassifier('MobileNet')
this.setState({ready: true})
const image = document.getElementById("image")
classifier.predict(image, 1, (err, results) => {
this.setState({
predictionLabel: results[0].label,
predictionConfidence: results[0].confidence,
predicted: true
})
})
}
这里我们有一个名为classifyImage
的异步函数。在这个函数中,我们首先通过加载MobileNet
数据作为训练集来定义我们的图像分类器。一旦这个分类器准备好了,我们将ready
状态设置为true
。然后,我们选择用户插入的image
并将其传递给分类器,运行predict
函数。我们将最高预测的标签和置信度保存在state
对象中。
我们的整个 App.js 文件将如下所示:
测试模型的时间到了。为此,我将给出下面的应用程序图像:
当我按下Classify
按钮时,应用程序运行classifyImage
功能,一段时间后您会得到以下结果:
The app is 63.99456858634949% sure that this is bucket
不是我所期待的。造成这种不正确结果的原因有很多。其中最重要的是,MobileNet 不是对该图像进行分类的合适数据集。
让我们试试其他图像。也许是一种动物:
Pic on Unsplash by Joséphine Menge
再次点击Classify
按钮,我得到🤞:
The app is 90.23570418357849% sure that this is Border collie
哇!90%的信心,图像有边境牧羊犬,这是一种狗!
包扎
如果你一直坚持到现在,那么你已经用 JavaScript 做了一些机器学习!来吧,拍拍自己的背!
但是你和我离成为 ML 专家还有很长的路要走。在本文中,我们做了机器学习的测试部分,并使用了预训练的模型。真正的乐趣始于你获取自己的原始数据,并试图用它来训练你的数据。
这就是我现在要努力去做的。所以祝我好运吧!如果我成功了,我会写下一篇关于它的文章。
一如既往的感谢大家阅读我的长文。JavaScript 的机器学习我还是新手。因此,如果你认为我在这篇文章中犯了什么错误,或者我本可以做些不同的事情,那么请对此发表评论。
你可以在这里查看 React 应用的完整源代码:
[## rajatk16/ml-in-js
这个项目是用 Create React App 引导的。在项目目录中,您可以运行:在…中运行应用程序
github.com](https://github.com/rajatk16/ml-in-js)
制造业中的机器学习
供应链革命的案例研究
机器学习是技术领域的话题,但在大众意识中,它是一个如此广泛而又缺乏理解的概念,以至于它经常被解释为类似于魔法的东西。
source: pixabay.com
人们通常理解机器学习实际上意味着什么,但事实是,它在各个学科的应用实际上如许多人预测的那样广泛。
机器学习可以产生重大影响的一个领域是制造业。
让我们更仔细地看一下。
在现有原则的基础上
当亨利·福特引进装配线时,这是一场彻底改变制造业世界的革命。
它可以被合理地看作是****劳动过程自动化的第一步,并且一直沿用至今。
虽然福特的原则在当今几乎每一个生产过程中都在发挥作用,但它并没有一成不变。
其他公司已经磨练和完善了这项技术,以保持自己的竞争力。
丰田就是这种情况,在 20 世纪 70 年代,他们发现自己在效率方面落后于通用汽车。他们发明了众所周知的丰田制造技术。
虽然其 DNA 直接植根于装配线,但他们通过确定制造过程中最常见的七种浪费并将其作为简化流程的传奇,将精益制造的理念向前推进了几步。
它成为了一种非常有效的模式,以至于几年后,丰田会将这些原则传授给通用汽车,作为交换,通用汽车会帮助他们适应美国市场。
虽然竞争驱动市场,但通常可以确定完成任务的最佳方式,并且最佳公司将相互学习以开发自己的流程。
从最纯粹的意义上来说,制造业的成功是进化的,基于这样一种理念:创造最高效开发流程的公司将会繁荣,落后的公司将会灭亡。
机器学习似乎就是这种情况。
革命性的质量控制
装配线的建立是基于这样一个前提,即一个较大的执行重复性任务的雇员组比一个较小的多学科雇员组能获得更高的效率。
有些任务天生就比其他任务复杂。缺陷被丰田认定为汽车制造过程中的关键浪费之一。
机器学习可以在这方面有所帮助。
通过了解导致缺陷的潜在问题并识别这些缺陷的潜在风险因素,他们可以显著地减少浪费并加快生产进度。
钢铁生产部门的案例研究进一步支持了这种观点。
这并不是说机器学习算法将取代人类,而是说人类在这个过程中需要扮演的角色正在变得不同。
通过创建一个由数据工程师、领域专家和工厂经理组成的紧密核心,这项研究展示了机器学习可以制造更安全、缺陷更少、对消费者风险更低的产品的显著效果。
福布斯发现,机器学习实际上可以将缺陷检测率提高 90%。
长期以来,机器一直被用来识别肉眼无法察觉的风险,比如基于重量或形状的风险。
人类通常更善于识别颜色、裂缝、光泽和其他可能表明质量控制问题的问题。但是机器学习识别这些视觉线索的能力已经开始超过人类所能完成的。
这项研究可能是制造业中关于机器学习的最重要的发现,也是一项可能将行业改变到与丰田制造技术的引入相匹配的水平的研究。
预测性地识别问题
最大限度地减少缺陷的存在会对最大限度地减少未来的维护需求(或防止将客户置于风险之中)产生重大影响,但即使是最好的产品最终也会出故障。
这不仅仅是产品从装配线上下线的情况,也是最初制造它们的机器的情况。
在过去,维护设备是一个非常耗时的过程。设备必须从生产线上取下,由工人或机器仔细评估,以发现问题并紧固。
维护是必要的,值得花时间去做,因为装配线上的设备故障会造成更大的损失。
机器学习可以通过更好地确定设备何时应该退出生产进行维护来减少浪费。
●如果您过早对设备进行维护,您会浪费不必要浪费的宝贵资源。
●如果你执行太晚,你可能会看到装配线流程的全面崩溃。
机器学习可以确定维护设备的理想时间,创造一个更安全、更高效的环境。
工厂之外的机器学习
装配线流程和丰田制造技术都是为了提高生产要素或工厂的效率,但这并不是效率可以带来好处的唯一环节。
存储和交付产品的过程本身造成了低效率,这种低效率对底线的影响不亚于装配线上的问题。
幸运的是,机器学习算法可以有益于库存优化和供应链优化的双重需求。
对于一家从事制造业的公司来说,储存库存是最高的成本之一,占总成本的 20-30%。
库存就是在你需要生产多少之间找到一个平衡:有足够的库存让你的所有客户都能得到他们需要的东西,同时减少花费昂贵的费用储存积压的货物。
但决定需求的数据量太大,人类分析师无法处理。
人工智能可以更准确地解析这些信息,由于机器学习,它可以考虑更复杂的模式,以找到供需之间的完美平衡。
提高整个供应链的效率
机器学习通过以下方式帮助制造商:
●预测他们需要多少** 和什么类型的产品**
●确定何时需要****
●了解将产品运送到目的地的最有效的运输路线
●更准确地预测可能导致供应链放缓的复杂情况
效率不仅适用于生产,也适用于在最短的时间内获得你需要的产品并把你生产的产品送到消费者手中的过程。
有了机器学习,整个供应链改善。
[1] P.Chojecki,人工智能如何改变世界 (2019),走向数据科学
[2] R .金达尔,汽车生产线终极指南 (2018),邦蒂有限责任公司
[3] J.Sutter 丰田如何培训通用 (2019),创新企业有限公司
[4]未知,钢铁制造中的产品质量预测与优化,Rapidminer
[5] L .哥伦布,2018 年机器学习变革制造业的 10 种方式 (2018),福布斯
[6] P. Trujillo,持有库存的实际成本 (2015),Wasp 条形码技术公司
[7] L. Ampil,数据科学产品管理基础:Ml 工作流程 (2019),走向数据科学
用通俗易懂的语言描述机器学习
初学者机器学习的简明介绍。
就像生物一样,机器也可以学习做事。在这种情况下,机器是学生,而世界或另一个存在——无论是自然的还是人工的——是老师。
根据 Tom Mitchell 1997 年的有影响力的书机器学习,机器学习有三个主要部分:
- 需要学习的任务。
- 学习任务的观察。
- 任务进展如何。
要学习的任务包括预测知识或行动。这些任务执行得有多好是由预测知识的准确性和行动产生的奖惩决定的。
根据 Mitchell 的说法,当作为学生的机器通过观察更多的世界而更好地完成任务时,机器学习就会发生。
Artificial Intelligence & AI & Machine Learning by www.vpnsrus.com is licensed under the Attribution 2.0 Generic (CC BY 2.0)
学习类型
学生可以根据观察到的世界预测新知识。这可能包括对事物进行分类或评估,或者理解行动可能产生的好的或坏的结果。
学习预测知识
知识包括对世界当前状态的描述和基于该状态的预测知识。状态可以包括多条信息。例如,在电子邮件上注明包括发件人的电子邮件地址和电子邮件的正文。预测的知识将包括基于状态的电子邮件是否是垃圾邮件。
学生可以根据世界或老师给出的完整例子来预测知识。完整的例子是那些包括前因和后果知识的例子。结果知识跟随先前知识。例如,电子邮件文本的后续知识(先行知识)可能是它被分类为垃圾邮件或不是垃圾邮件。使用这些完整的例子,学生发现模式或一般关系,称为假设,可以用来估计未来的后续知识,只有先行知识。这种学习形式被称为监督学习。
Image via https://pxhere.com/en/photo/1575601 is licensed under the CC0 1.0 Universal (CC0 1.0)
Public Domain Dedication
学生也可以在没有包含结果性知识的例子的情况下预测知识。在这种情况下,学生在观察中发现模式和共性,可以用来估计随后的知识。这叫做无监督学习。例如,学生可以有一组对象照片,并根据照片中的共同特征(或状态)将该组对象分类为不同类型的对象。但是类别事先并不知道。这个例子是一个叫做聚类的无监督学习的例子。
Polaroids by Louise McLaren is licensed under the Attribution 2.0 Generic (CC BY 2.0)
学习行动
学生也可以根据可能得到的奖励或惩罚来采取行动。行动任务是通过所谓的强化学习来学习的。这包括学习状态(可能是目标)的可取性,以及可能导致状态被实现的行动。学生学习一个策略——在某些状态(即情况)下要做的动作。
例如,一个学生可以在迷宫中导航,到达终点的奖励与超时的惩罚。学生通过从一个位置移动到另一个位置来行动——从一个状态到另一个状态。期望的最终目标或状态是走出迷宫并获得奖励。
老师给予奖励或惩罚,他可以是另一个存在,也可以是外部世界本身。众生可以发奖;外部世界会带来惩罚,比如下雨或其他自然灾害。学生们学会寻找奖励,避免惩罚,不管它们来自何方。
The hedge maze at Traquair House by marsroverdriver is licensed under the Creative Commons Attribution-Share Alike 2.0 Generic license.
推理和知识结构
这三种学习形式从具体的例子中建立更多的一般知识——归纳推理的一种形式。概括储存在记忆中,并在新的情况下用于预测新的知识或行动——一种演绎推理的形式。它们包含两部分知识:前件和后件。例如,来自强化学习的策略具有作为当前情况的前因和作为要做什么的后果。
实践中的机器学习:算法
我们可以通过用机器学习算法给它们编程来制造学习机器——一系列接收输入并产生输出的指令。例如,监督学习算法将数据作为输入,并输出前件和后件知识之间的关系。这些算法可以从简单的指令系列到更复杂的甚至模仿大脑的指令系列——这些算法被称为神经网络。
学习是人工智能的一部分
为了有效地发挥作用,学生需要将预测知识和行动结合起来。例如,监督学习可以用于识别国际象棋中的情况——在人工智能中称为状态——如处于“检查”状态。但是强化学习被用来找出在那种状态下最有效的行动来获得奖励——在这种情况下,就是赢得游戏。
已经制造出具有人工智能的机器来处理这些形式的学习,但是还没有一种机器能与人类的能力相匹敌。
三步线性回归
引入梯度下降
Photo by Charlie Foster on Unsplash
动机
我们在本系列的第一部分中的 9 步 中演示了如何使用 Python NumPy 构建神经网络,但是对于初学者来说可能太难理解了。在这种情况下,我们将使用 NumPy 库来实现最简单的机器学习模型之一的线性回归。最好对微积分和 Python 语法有基本的了解(但不是必须的,因为你可以随时学习)。
代码在GitHub上有。最初发布于edenau . github . io。**
1.初始化
第一步。导入 NumPy。说真的。
2.生成数据
我们为标量输入X
及其对应的高斯noise
生成一万个点,这样对于一些固定的斜率w_true=7.6
和截距b_true=-3.3
,我们可以通过下面的线性关系生成y
。w_true
和b_true
的值完全是任意的。
y = w_true * X + b_true + noise
添加零均值高斯噪声使我们的数据更加真实。
Data points (blue) and linear relationship without noise (red)
3.梯度下降
实际上,我们不知道线性函数参数w
和b
的值,这就是梯度下降的由来。我们将误差函数e
定义为某些(w,b)
的实际y
和预测y=wx+b
之间的平方差的和。****
该误差函数惩罚实际值和预测值y
之间的不匹配。使用平方差代替绝对差||.||
,这样我们可以解析地计算 ∂e/∂w 和 ∂e/∂b ,这留给读者作为练习。 这些渐变分别代表了 ***w***
和 ***b***
增加的方向。 因此,如果我们想 减少 的误差e
,我们应该通过去导数的 负方向 来更新参数。这可以表示为
w ← w - learning_rate * ∂e/∂w
b ← b - learning_rate * ∂e/∂b
# The key is the minus signs
Photo by Bernard Hermant on Unsplash
如果我们迭代地进行这些更新,直到(w,b)
收敛,我们将得到一组最佳的参数,可以表示X
和y
之间的线性关系。
外卖
这是在 3 步 中使用 NumPy 库的线性回归算法的最小实现。如果你想测试你对线性回归的理解,以下是你可能想尝试的事情:
- 使用其他库实现线性回归(在 GitHub 和上)
- 训练测试数据集拆分
- 多输入特征
- 非高斯分布噪声
- 不同的误差函数
Photo by Ameen Fahmy on Unsplash
代码可在 Github 上获得。编码快乐!
相关文章
感谢您的阅读!如果您对机器学习或 Python 感兴趣,请查看以下文章:
** [## 我希望我能早点知道的 5 个 Python 特性
超越 lambda、map 和 filter 的 Python 技巧
towardsdatascience.com](/5-python-features-i-wish-i-had-known-earlier-bc16e4a13bf4) [## 使用交互式地图和动画可视化伦敦的自行车移动性
探索 Python 中的数据可视化工具
towardsdatascience.com](/visualizing-bike-mobility-in-london-using-interactive-maps-for-absolute-beginners-3b9f55ccb59) [## Python NumPy 中的机器学习(第 1 部分):9 步神经网络
通过编码理解神经网络
towardsdatascience.com](/machine-learning-in-python-numpy-neural-network-in-9-steps-eafd0db25906)
最初发表于edenau . github . io。**
现实生活中的机器学习
为现实世界的商业案例开发一个模型到底是什么样的
Photo by Ben White on Unsplash
你曾经参加过纸牌游戏比赛吗?如果你正在学习,或者已经学习了机器学习,很有可能在某个时候你会进入其中。这绝对是将你的建模技能付诸实践的好方法,我在学习的时候花了相当多的时间在 Kaggle 上。
如果你以前参加过机器学习竞赛,那么你的工作流程可能看起来有点像我的工作流程:
- 下载一些数据(可能是一个或几个 CSV 文件)。
- 或许做一点清理,或者数据集可能已经足够干净了。
- 执行一些预处理,例如将分类数据转换为数字数据。
- 通过各种合适的模型运行数据,直到找到最佳模型。
- 花很长时间在超参数调整、特征工程和模型选择上,因为一个很小的改进可能意味着你在排行榜上上升几个名次。
- 结束了
然而,如果你正在为一个真实世界的商业应用开发一个机器学习模型,这个过程看起来会非常不同。我第一次在业务场景中部署模型时,这些差异非常令人惊讶,特别是在工作流的某些阶段花费了多少时间。在下面的帖子中,我想描述在商业环境中开发模型的过程,详细讨论这些差异,并解释它们存在的原因。
在商业案例中,工作流将有更多的步骤,可能看起来有点像这样。
- 将业务问题转化为数据问题。
- 考虑机器学习模型如何连接到现有的技术栈。
- 花费大量时间提取、转换和清理数据。
- 花大量时间进行探索性分析、预处理和特征提取。
- 建立模型。
- 选择能够以最少的工程工作量集成到现有技术体系中的最佳模型。
- 考虑到商业价值,优化模型,直到它“足够好”。
- 部署模型。
- 在生产中监控模型。
- 必要时再培训。
- 构建版本 2。
- 继续,直到模型不再有商业用途。
在这篇文章的剩余部分,我将会更详细地介绍每一个步骤。
你需要把一个商业问题转化成一个数据问题
在 Kaggle 竞赛中,要解决的问题将在前面明确定义。例如,在一个名为“ Severstal:钢缺陷检测的最新比赛中,你得到了一些经过策划的数据,问题以数据问题的形式清楚地陈述出来。
如今,谢韦尔钢铁公司使用来自高频摄像机的图像来驱动缺陷检测算法。在这场比赛中,你将通过定位和分类钢板表面缺陷来帮助工程师改进算法。
在真实的业务问题中,不太可能要求您构建特定类型的模型。更有可能是团队或产品经理带着业务问题来找你。这可能看起来像这样,有时问题甚至可能没有被很好地定义。
客户服务团队希望减少企业回复客户电子邮件、实时聊天和电话的时间,以便为客户创造更好的体验并提高客户满意度。
根据这个业务请求,在开始构建实际的模型之前,您需要与团队一起规划和设计这个问题的最佳解决方案。
数据不会是干净的
您处理的数据几乎肯定不是干净的。通常会有丢失的值需要处理。日期格式可能不正确。值中可能有错别字、不正确的数据和异常值。在实际构建模型之前,可能会花费大量时间来删除错误数据、异常值和处理缺失值。
你可能不得不从不同的来源获取数据
同样,您需要的所有数据可能都不是来自一个简单的来源。对于数据科学项目,您可能需要从以下任意组合中获取数据:SQL 查询(有时跨多个数据库)、第三方系统、web 抓取、API 或来自合作伙伴的数据。与数据清理类似,这部分通常是项目中非常耗时的部分。
特征选择非常重要
一般来说,在机器学习比赛中,你有一个给定的数据集,其中包含有限数量的变量,可以在你的模型中使用。特征选择和工程仍然是必要的,但是首先你可以选择的变量数量有限。在处理现实世界的问题时,你很可能会接触到大量的变量。作为一名数据科学家,您必须选择可能会产生解决问题的好模型的数据点。因此,您需要结合使用探索性数据分析、直觉和领域知识来选择构建模型所需的正确数据。
建立模型是这个过程中最小的部分
花了这么多时间来选择、提取和清理数据,相比之下,你实际花在构建模型上的时间将会非常少。特别是对于模型的版本 1,您可能想要使用模型作为基线测试,那么您可能在第一个实例中只花费少量的时间在模型选择和调整上。一旦商业价值被证明,你就可以投入更多的时间来优化模型。
您将花费比您想象的更少的时间来调整模型
在 Kaggle 比赛中,花费数周时间来调整模型以获得模型分数的微小提高并不罕见。因为这个小小的改进可能会让你在排行榜上上升不少。例如,在当前的 Severstal 比赛中,排行榜上位置 1 和位置 2 之间的分数差目前仅为 0.002。花时间稍微提高你的分数肯定是值得的,因为这可能会让你获得最高奖项。
在商业中,你花在调整模型上的时间是一种成本。公司必须根据你完成这项任务的天数或周数支付你的工资。与任何事情一样,这种投资需要有商业价值形式的回报。一个模型的业务用例不太可能提供足够的价值来证明花费几天来提高一个 0.002 增量的模型的准确性是合理的。实际上,您将调整模型,直到它“足够好”而不是“最好”。
你不一定要用最好的模型
这让我想到了我的下一个观点,即你不会总是使用最好的模型或最新的深度学习方法。通常情况下,您将能够通过更简单的模型(如线性回归)交付更多的业务价值。这需要更少的时间(因此构建成本更低)并且更容易解释。
您的模型必须连接到某种端点,比如网站。此端点的现有技术体系将对您将部署的模型类型有很大影响。数据科学家和软件工程师经常会在最小化两端的工程工作上达成妥协。如果您有一个新模型,这将意味着对现有部署流程或大量工程工作的更改,那么您必须有一个非常好的业务案例来部署它。
工作不止于此
一旦投入生产,就需要对模型进行监控,以确保它像在培训和验证期间一样运行良好,并检查模型是否退化。由于多种原因,模型的性能通常会随着时间的推移而降低。这是因为数据会随着时间的推移而变化,例如客户行为的变化,因此您的模型可能会在新数据上表现不佳。出于这个原因,模型也需要定期重新培训,以保持业务绩效。
此外,大多数企业将有一个部署机器学习模型的测试和学习周期。因此,您的第一个模型通常是版本 1,以形成性能基线。之后,您将对模型进行改进,可能会更改特性或调整模型,以部署更好的版本并根据原始模型进行测试。
这两个过程可能会一直持续下去,直到该模型的业务案例不再存在。
结论
这篇文章的部分灵感来自 Chip Huyen 的这条推文。
机器学习角色很难招聘的部分原因是,我在这里讨论的许多在商业中部署机器学习的现实并没有在这些课程中教授。这就是为什么我如此热衷于实践优先的学习方法,也是为什么我认为工业实习、实习和初级数据科学角色如此重要。
然而,随着该领域技术的快速发展,隧道尽头有了光明,这有助于数据清理和模型部署等流程的自动化。然而,我们仍有一段路要走,因此,对于数据科学家来说,除了典型的数据科学家技能组合之外,开发软件工程技能、提高沟通技能以及拥有弹性和坚持不懈的心态仍然至关重要。
感谢阅读!
雪花中的机器学习
更新:截止 2021 年年中,这篇文章现在已经 2.5 岁左右了!在这段时间里,Snowflake 有了很大的发展,包括推出了 Snowpark ,这是将繁重的定制处理移入其引擎的最佳方式。
所以,如果你是从搜索引擎登陆到这里的,那是因为历史受欢迎程度比内容的有用性更高😁
如果你对一个有趣的实验感兴趣,这个实验采用基于集合的方法来研究最大似然算法,请继续读下去,希望你会喜欢这篇文章。
但是如果你正在寻找在生产中在雪花引擎中实际运行机器学习训练算法的最佳方式,有许多官方雪花合作伙伴已经修改了他们的产品,通过 Snowpark 推动处理。
如果你在雪花做机器学习,你需要有一个计划来操作它!自这篇文章以来,另一件事发生了变化,那就是我已经启动了一个名为 Omnata 的初创公司,它允许你 1)将你的 CRM 直接连接到 Snowflake 以获取实时的上下文数据,以及 2)将数据从 Snowflake 推送至你的 SaaS 应用。一定要来看看我们!
雪花目前正在全球掀起波澜,因为它是为云从零开始构建的令人兴奋的新数据仓库。
它已经拥有数量惊人的传统统计类型的聚合和分析函数,但是即将发布的Javascript 存储过程允许您将其高效、灵活的分布式计算引擎用于 SQL 方言之外的更一般的任务。
我认为 ML 工作负载将是路测该特性的一个很好的方式,事实证明它真的很擅长!
我们应该吗?
数据库引擎是训练模型的好地方吗?
在数据库内处理和属于外部世界的计算之间有一条不断变化的界线。
随着 20 世纪 90 年代“数据挖掘”一词的流行,DBMS 供应商在其 SQL 方言中增加了统计建模功能,例如 IBM 推出了“智能挖掘器”,Oracle 推出了“ Oracle 数据挖掘”。
然后按照。随着 com 的繁荣,数据集增长到我们开始称之为“大”的程度,Hadoop 作为一种扩展处理的方式越来越受欢迎,随后是 Spark。数据挖掘工作负载已经转移到传统数据库管理系统之外。
但是就在许多人宣称 SQL 已死的时候,2010 年 Hive 发布了,突然间这些大量的数据又被称为数据仓库。快进到 2019 年,现在所有主要的云供应商都在其对象存储中的结构化和半结构化数据上提供了某种形式的 SQL 接口。
2018 年年中,谷歌宣布了 BigQueryML 的测试版,现在我们又回来使用 SQL 作为机器学习的抽象,尽管是在更大的数据集上,处理能力更强(也更有弹性)。截至 2019 年 2 月,BigQueryML 仍处于测试阶段,它目前相当基础,仅限于线性回归和逻辑回归。
只要算法能够适当地伸缩,就有很多很好的理由将您的数据仓库引擎用于 ML:
- 简单性—无需管理另一个计算平台、在系统间集成以及提取/分析/加载数据
- 安全性—数据保存在安全的地方,无需在外部系统中配置雪花凭据,也无需担心数据拷贝的最终位置
- 性能——一个好的数据仓库引擎将维护大量用于优化查询的元数据,这些元数据可以在 ML 过程中重用,从而使其比通用计算平台更具优势
在雪花中
因此,让我们看看我们是否可以仅使用雪花引擎来实现一个适度、最小但合法的机器学习算法。
决策树可用于通过将数据集分解成越来越小的子集来构建回归或分类模型,这些子集被组织成一棵树。
为了最大限度地减少我需要实现的逻辑量,我将使用 ID3 算法进行一个回归树练习,主要是为了在构建树时可以重用 Snowflake 现有的标准差函数。
雪花并不像 Spark 那样是一个通用的集群计算框架,但是它非常擅长并行分析查询。
出于这个原因,也因为 javascript 是单线程的,我的目标是将尽可能多的计算交给查询引擎,让存储过程执行更多的协调任务。
场景
我选择了华盛顿特区的自行车共享数据集,使用每小时一次的频率。
我们可以把它存储在一个像这样的表中:
create table bikes_hours(instant numeric, dteday date, season numeric, yr numeric, mnth numeric, hr numeric, holiday numeric, weekday numeric, workingday numeric, weathersit numeric, temp numeric, atemp numeric, hum numeric, windspeed numeric, casual numeric, registered numeric, cnt numeric)
并使用 SnowSql 命令行工具上传 csv 文件。
Here’s the example data set in a Snowflake table
培养
首先,我们将创建一个表来存储我们的训练跑步和完成的模型,这只是在我们证明概念时的一些简单的事情:
create or replace sequence ml_model_runs_sequence start = 1 increment = 1;create or replace table ml_model_runs(run_id integer,
table_name varchar(256),
algorithm varchar(100),
training_parameters variant,
start_time timestamp,
end_time timestamp,
model_object variant);
现在在 javascript 存储过程中实现 ID3 决策树算法。数学上,它看起来像这样:
我们在每个分支点应用该公式,以便选择下一个要拆分属性。
我不是一个沉迷于复杂性的人,这只是一种正式的说法,即我们将根据最好地“分组”其子代中的值(即具有最相似的值)的属性进行拆分。为此,我们将比较父母和子女之间的标准偏差(一个群体的成员与平均值的差异程度)。
我们的存储过程将接受四个参数:一个表名、一个目标变量(包含我们要预测的值的列的名称)、在树中用作属性的列的名称以及训练参数。
从树的顶部(根节点)开始,我们将在每个分支点运行两个查询。
第一个查询给了我们:
1)从该节点向下的所有目标值的标准偏差,因为我们将挑选减少该值最多的分支
2)从该节点向下的所有目标值的平均值,因为当我们到达叶子时,最终平均值被用作预测值
3)变异系数,当它变得太小时可以用于停止构建
4)从该节点向下的目标值的数量, 当它变得太小时,可用于停止构建
5)对于下面的每个潜在分支(来自剩余列的列表),中值。 如果选择了该属性,这将用于拆分数据。
在树的顶部,它看起来像这样:
但是随着树变得越来越宽,它开始看起来像这样:
heavily abbreviated
第二个查询有两个部分:
- 一个子查询,用于测量每个子分支下目标的标准偏差(每个子分支乘以其相对于整体的大小)
- 计算标准偏差减少的封闭查询,从最高到最低排序,以便我们可以轻松选择最大值
这两个查询都使用 WHERE 子句向下筛选到它们在树中的位置。
复杂的地方在于,我们不仅将分支选择卸载给雪花,还要求它使用 UNION 语句计算当前深度的每个分支。这使我们不必遍历整个树。
在树的顶部,有一个要计算的树分割和 5 个要评估的可能属性,查询如下所示:
在底部,当它评估每个分支的每个可能的分割时,它看起来像这样:
even more heavily abbreviated
在可用属性的总数(9)中,使用配置参数,我将它限制为一次评估其中的 5 个。
在第一次拆分时,第二个查询的查询计划如下所示(拆分每列所依据的值由第一个查询提供):
当您深入到一定深度时,查询计划开始看起来像这样:
内联发布所有这些的完整代码有点长,这里有一个链接。
在运行之前,我们将选择变量。这不是一个如何进行数据科学的练习,所以我将只挑选一些看起来有用的。
首先,让我们向数据集添加一个分数列:
alter table bikes_hours add column score numeric
然后,使用雪花的样本函数,将源表拆分为 training (90%):
create temporary table bikes_hours_training as
select * from bikes_hours sample (90)
…剩下的 10%用于测试(10%):
create temporary table bikes_hours_testing as
select * from bikes_hours where instant not in (select instant from bikes_hours_training)
现在我们调用 decision_tree_train proc 来预测‘休闲’列(每小时休闲乘客的数量),使用其中的 9 列。
call decision_tree_train('bikes_hours_training', 'CASUAL', 'season,hr,weekday,workingday,temp,atemp,weathersit,hum,holiday');
ml_model_runs 表中的结果模型如下所示:
下面是模型对象的一个片段:
得分
为了生成对数据库记录的预测,我们需要一种方法来使用列中的值向下导航树。
最初我认为一个用户定义的表函数(UDTF)将会是完美的(代码这里,因为它应该利用你从雪花引擎得到的并行性。我构建了一个深入模型(作为一个 javascript 对象)直到到达叶子的模型。实际上,UDF 时间限制(大约一分钟?)似乎堆积在桌子上,我经常撞到它。
然后我发现决策树可以很容易地转换成庞大的 CASE 语句,并作为普通的 SQL 运行。所以我编写了一个存储过程(代码,这里是)来生成 case 语句,并对选择的表执行更新查询,将预测值放入其中一列。
所以我们运行它,传入决策树 json 对象和要放入分数的列的名称:
call decision_tree_score('bikes_hours_testing',(select model_object from ml_model_runs where run_id=1),'SCORE');
评价
评估模型的常用方法是均方根误差。我们可以在雪花中这样做:
select sqrt(sum(square(casual-score))/count(*) ) from bikes_hours_testing
结果是 25.49340847
考虑到值的范围从 0 到 367,这还不算太尴尬。
表演
培养
Snowflake 的一大优点是查询性能反馈内置在产品中。因此,在运行我的训练程序后,我只需切换到历史选项卡来查看个人资料。
我使用了 9 个属性,但是将培训限制为:
- 一次最多比较 5 个属性
- 变异系数下限为 10
这就产生了一棵有 33 片叶子的二叉树。
总的来说,在一个中型集群上训练需要 128 秒。
在根节点处,第一次查询(每个深度处每个节点的摘要)耗时约 200ms,在最终深度 10 处逐渐增加到 10 秒。
第二个查询(评估每个深度的每个节点的分支分裂候选)从 1.3 秒开始,在深度为 7 时逐渐增加到 23.8 秒,然后在最终深度为 10 时缩回到 14.8 秒(这是因为分支终止,所以树不会一直向下散开)。
得分
当然,得分几乎是瞬间的。将 CASE 语句传递给 Snowflake 查询引擎(即使是这么大的引擎)是一个很好的优化。
结论
这是一个有趣的练习,也是测试新存储过程特性的好方法。但最重要的是,它有效!
在这个实验的开始,我不确定它是否会表现得很好,但是到最后,我对结果感到非常兴奋。
接下来呢?
对这个基本实现有许多改进,包括不同的分裂方法(gini,entropy)以及对分类值的更好支持(而不仅仅是在中间值上分裂)。
但更重要的是,决策树构建形成了结构化数据最流行的 ML 算法(random forests,XGBoost)的基础,因此这种方法没有理由不能进一步扩展。
可能让数据科学家完全在雪花内部赢得 Kaggle 竞赛的其他难题是:
特征工程
雪花在这里也应该出类拔萃。用现有的函数库构建像 hot encoding 这样的函数应该很简单,并且已经支持值的分桶。
抽样
对于像构建随机森林这样的任务,数据集的随机采样变得非常重要。雪花似乎有很大的灵活性与内置的采样方法-另一个优点。
航空业的机器学习:下一步
Photo by Ross Parmly on Unsplash
这篇文章谈到了航空公司利用人工智能提高利润的机会
“必要性是创新之母”这句话可以很好地描述航空业的重大变化。在过去的 20 年里,航空公司的运营为世界提供了无数创新的想法,这些想法可以应用于大多数面向消费者的行业。其中一些想法包括动态定价、收入管理系统、优化成本的运营计划。像动态定价这样的概念在 10 到 15 年前是不可想象的。它引入了不同的顾客为同一产品支付不同的价格,而同时所有顾客都能获利的理念。
这种创新背后的必要性是,航空公司是整个旅行和旅游链中最令人苦恼的行业之一。这个行业的参与者的利润率非常低。因此,对他们来说,制定策略来赚取最大利润,同时帮助他们赢得价格战变得非常重要。
根据麦肯锡的一份报告,特别是旅游公司和航空公司,如果他们有强大的数据战略,获得客户的可能性增加 23 倍,保持客户的可能性增加 6 倍,盈利的可能性增加 19 倍。
在这篇文章中,我将讨论一些这样的策略,它们可以利用航空公司收集的大量数据来提高他们的底线。
中断和恢复
航空公司拥有大量关于航班延误的历史数据,可以很容易地从各种其他门户网站获取天气数据。结合这两组数据源可以帮助公司更好地计划即将到来的延误(如果有的话),即飞行中的出发或到达。
得益于此类信息的一个例子是,爱尔兰西部的风暴预计将在一两天内穿过英国,根据其强度,可能会扰乱世界上最繁忙的机场之一伦敦希思罗机场的航班时刻表。航空公司可以提前一两天通知乘客由于风暴即将到来的延误,以便乘客可以根据他们的旅行目的做出必要的安排。主管可能会提前重新安排会议,从而避免失去商业机会,或者游客可能会推迟预订目的地的酒店。结果是顾客非常满意,并因此获得了回头客。
以上是使用天气数据做好准备以防中断的一个例子。这也可以通过结合其他数据源来实现,如旅行目的地的动荡、旅行日期和时间。从而提供增强的客户体验。
Image by Author
重新安排机会
一项研究表明,获得一个新客户的成本是留住一个客户的成本的 7 倍。此外,该行业面临巨大的竞争,每个玩家都在惨淡的利润率上生存。因此,对于航空公司来说,在价格是大多数客户转换服务提供商的最重要参数的市场中,减少客户流失是非常重要的。
目前,对于提前预订航班以节省一些额外费用的客户来说,取消或重新安排航班的费用相当高。提前 30 天预订其航班的用户比预订接近出发日期的用户更有可能在接近旅行日期时重新安排航班。大多数提前预订的用户都希望通过提前预订来利用低成本优势。目前,改期的价格几乎等于用户最初购买机票的价格(参考文献 1)。下图就是一个这样的例子)。这阻碍了用户在行程有任何变化的情况下重新安排航班。
相反,航空公司可以保持较低的重新安排费用,从而抓住机会并在客户服务上获得高分。其工作方式是,重新安排费用而不是一个固定的数额应该是可变的,并与空缺席位被另一个客户填补的概率成比例。这可以通过使用诸如目的地的消费者需求、航班过去的预订趋势、航班中的空位数量、航班的始发地、目的地城市即将发生的事件等参数来容易地预测。
空位被另一个乘客占据的高概率会导致相同的座位被高价卖给新的乘客,因为航班需求高且更接近旅行日期。现有乘客为另一个航班的新座位支付少量费用,因为它更接近旅行日期。该航空公司从这两个客户那里获得收入。在一个票价占运营收入 75%的行业中,额外门票的销售对总收入贡献巨大。此外,它为航空公司和客户带来了双赢的局面。
无障碍程序
客户在机场办理登机手续和退房手续所花费的时间增加了旅行时间,有时可能会超过旅行时间。航空公司可以通过提供平稳过渡和减少在始发地和目的地机场的等待时间来大幅改善客户体验。
例如,使用面部识别的人工智能技术可以通过比较护照上的照片和客户的实际图像来帮助简化登记过程。该数据还可以与托运行李相关联,从而使在目的地机场领取行李变得更加简单。这也消除了顾客在结账时拿错行李的可能性。如果行李中有任何违禁物品,它还可以通过将行李映射到客户来提高机场的安全性。
由于便利是当今世界的王道,由人工智能(AI)驱动的智能礼宾服务已成为增强客户体验的必要条件。目前,只有当传单到达航空公司柜台时,才是追踪该传单登机的时候。在智能系统的帮助下,航空公司甚至可以在乘客到达机场登机之前就成为乘客旅程的一部分。传单可以在登机牌领取柜台或安检柜台收到关于排队的动态更新。如果愿意,客户还可以在最后一刻检查并更改航班。其中的一部分可能是-
托运和购买额外行李限额
在飞机上点一份特别餐
如果到达机场有延误,通知航空公司
正在检查登机门号码
Image by Author
根据个人选择量身定制
对于一家航空公司来说,顾客之旅不应该随着旅客到达目的地而结束。旅行结束后还会继续。根据一项研究,90%的旅行者在一个或另一个社交媒体平台上发布他们的旅行经历。这为航空公司提供了一个分析其品牌忠诚度的好机会。从社交媒体平台收集的数据的情感分析可以帮助航空公司改善他们的整体客户体验。
更进一步,对客户体验的实时分析有助于航空公司即时改进服务。例如,如果客户对其第一段旅程的整体旅行体验不满意,可以通过为其下一次转机航班提供免费的商务舱升级来获得补偿。这种补充将需要实时收集数据,并向传单提供定制的包。
同样,实时行李跟踪服务也很有帮助,可以让乘客知道他们的行李是否放错了地方或延误了。这些数据策略将对航空公司建立客户忠诚度和提高整体品牌价值大有帮助。
云中的机器学习:与 Jupyter、Spark 和 Dask 合作的最简单方法
昨天,我和一个朋友谈论数据科学和机器学习的环境变化有多快。他是一所商学院的院长,教授 MBA 学生数据和分析长达 20 年,见证了所有的起起落落。纵观历史,在经历了许多繁荣和失败之后,我们已经为机器学习度过了许多冬天。在他的职业生涯中,还没有人对他感兴趣。
那么,为什么它现在这么热:首先,计算机的力量——云计算和虚拟机使我们能够在比过去更短的时间内处理任何数据。第二,随着数字革命——互联网进入日常生活——可用于处理的数据量。第三,现在已经足够成熟——不像过去的大肆宣传时代,我们已经看到巨大的发展证明了可行性。
Photo Credit: Unsplash, by @ mimithian
机器学习(Machine learning)专注于开发计算机程序来访问数据并利用数据进行自我学习,它需要大量的计算能力。随着云计算的广泛采用,高性能虚拟机(VM)无需巨额资本成本即可获得,机器学习变得如此强大。
云平台上越来越多的机器学习工具表明,机器学习和云计算是相互依存的。随着新工具进入市场,在数据科学项目(包括代码、可视化和 Jupyter 笔记本)上共享和协作变得更加容易和高效。
像现收现付这样的支付模式以及随需求增长而扩展的可用性,使得启动机器学习工作负载变得如此容易。此外,由于云平台中可用的功能和工具,您不需要总是拥有博士学位或高级技能。当我在从事一个加密项目时,我们使用市场上可用的 Cloudinary 和 Google AI 工具轻松实现了一个欺诈检测算法。
机器学习和 Jupyter 笔记本
作为一名机器学习程序员,人工智能开发人员,或者更广义的数据科学家,Jupyter 笔记本已经成为我们工作中不可或缺的一部分。很容易看出为什么;Jupyter 笔记本允许数据科学家在简洁易用的界面中编写代码并立即执行。
Jupyter 笔记本提供更多。数据分析师发现 Jupyter 笔记本不仅是编写和执行代码的简单工具,也是可视化和解释性文本的简单工具。非典型的 Jupyter 笔记本可以用于“数据清理和转换、数值模拟、统计建模、机器学习等等”
同时,作为数据科学家的优秀原型工具,Jupyter 笔记本也面临一些挑战。
本地机器上的 Jupyter 笔记本
在典型情况下,Jupyter 笔记本将在用户的本地机器上运行,因此依赖于计算机的 CPU(或 GPU)规格。对于基本的数据科学任务,这不是问题,因为电脑可以管理处理需求。然而,如果科学家将执行涉及机器学习的高级操作,则需要更强大的系统,这些系统可随时通过云服务获得。
Photo Credit: Unsplash, by @ clintadair
分享 Jupyter 笔记本的问题
在团队项目中与其他团队成员共享 Jupyter 笔记本是一项同样具有挑战性的任务,尤其是当所有团队成员都不熟悉 GitHub 时 GitHub 是最常见的解决方案。当团队决定通过 GitHub 共享工作时,所有团队成员都需要将他们笔记本的最新版本提交给 GitHub。如果团队成员不熟悉 GitHub,这一要求和其他要求使得他们很难共享 Jupyter 笔记本。此外,GitHub 不允许其他用户使用共享链接查看和编辑 Jupyter 笔记本。这是云计算解决方案的一个可能特性。
在谷歌云平台(GCP)、微软 Azure 和亚马逊网络服务(AWS)等云平台上运行 Jupyter 笔记本成为数据科学家的常用解决方案。它解决了与团队成员共享 Jupyter 笔记本的主要问题,通过将笔记本托管在云上,提供了充足的计算能力选择。然而,与 GitHub 的情况一样,数据科学项目中的所有团队成员都必须熟悉所选择的云平台。这就需要一种解决方案来处理 DevOps,让数据科学家专注于数据科学。
进入土星云,这是一种基于云的服务,允许数据科学家发布代码、笔记本和其他形式的内容,与同事和队友分享。
是什么让 土星云 如此特别?
土星云是数据科学家在云上托管 Jupyter 笔记本并与团队成员共享的绝佳选择。它是首选,原因有三:
首先,在土星云上发布和分享笔记本比在 AWS 和 GCP 这样的普通云服务上更容易,这些云服务不是专门为数据科学家设计的。借助土星云,数据科学家可以在 GCP、Azure 或 EC3 上运行虚拟机(VM ),完成设置这些系统的复杂过程。它去掉了 DevOps,让数据科学家专注于编写代码来分析数据。Saturn cloud 允许数据科学团队指定合适的标准化环境,只需点击一下鼠标即可与 Jupyter、Spark 和 Dask 一起使用。
其次,土星云消除了基础数据科学项目使用 GitHub 共享笔记本的需求。借助基于云的工具,数据科学家可以通过链接与团队成员共享项目。通过该链接,团队成员可以查看和编辑 Jupyter 笔记本或通过该链接共享的代码。
第三,Saturn cloud 有一个自动化版本控制的特性,确保团队成员提交笔记本的最新版本。当使用像 S3 这样的版本化数据存储时,土星云在管理代码版本的同时管理数据版本,因此科学总是可重复的。
此外,土星云允许用户在任何云平台上运行自己的虚拟机(VM ),无论是 CGP、Azure 还是 EC3,从而为用户提供了灵活性和对成本的严格控制。用户可以从一个供应商迁移到另一个供应商。借助特殊的成本控制,如支出警报和支出限制,Saturn Cloud 可帮助您在您为自己和团队指定的云成本限额内运行。
如何在土星云中共享 Jupyter 笔记本?
开始使用 Saturn Cloud 很容易,大约需要 15 分钟来完成设置并运行第一个虚拟机。这本入门指南中详细说明的步骤包括首先注册土星云平台,然后在土星云上旋转你的第一台 Jupyter 笔记本。接下来是对您的笔记本进行设置和优化,当然还有发布笔记本以与团队成员共享。
在这篇文章中,Anne Bonner 生动地描述了如何在 Saturn Cloud 上注册,如何在平台上创建和发布 Jupyter 笔记,并提供了有用的提示和插图。Lukas Frei 还解释了如何在土星云上发布 Jupyter 笔记本。这里是一个 Jupyter 笔记本,他分享了在土星云上看到的纽约老鼠。你会注意到,一个人可以通过链接访问和编辑土星云上的笔记本,而不需要精通 GitHub、CGP、AWS 和其他类似的云平台。
Unity 中的机器学习
你对强化学习或机器学习感兴趣,并对构建定制环境感兴趣?然后,我认为 Unity 的 ML-Agents 框架是适合你的工具。在过去的一年里,它已经成为一个相当稳定和广泛的实验平台。
机器学习很好玩!
Machine Learning is fun!
Unity3D 是什么?
Unity 是一个游戏引擎,试图将 3D 和 2D 游戏开发民主化。这是一个非常强大的工具,它允许你为许多平台(从 PC 到移动到控制台)创建具有尖端图形的复杂游戏。在过去的几年里,引擎的能力不断增长,增长到了难以跟踪的程度。但是现在,你不用担心这个。当使用 ML-Agents 时,我们可以忽略许多这些特性而不会感觉不好。
由于开发定制引擎是一项非常昂贵的工作,难怪许多游戏工作室都在使用 Unity 开发他们的游戏,如 Cuphead、Gwent、Monument Valley 和等等。
为什么要把 Unity 和机器学习结合起来?
在我看来,Unity 在机器学习上投入巨资是一个非常明智的想法。作为一个游戏引擎,它已经提供了你构建环境所需的所有工具。此外,游戏中的人工智能大多使用寻路和决策树等技术,这些技术无法像机器学习那样动态适应玩家的行为。Unity 正在设想一个 NPC 不再被严格硬编码的未来。
想看视频吗?看看这个:
从哪里开始?
如果你认为:“好吧,你得到了我。这听起来很有趣,但我该从哪里开始呢?”。这是我们现在要解决的问题。如前所述,统一是一种野兽,它可以在一开始非常势不可挡。在进入机器学习之前,我建议先学习基础知识。这方面有很多不错的教程系列,像这个一个。
在学习 Unity 的基础知识时,您需要记住以下几个提示:
- 不要为灯光、着色器和图形而烦恼。让你的场景看起来很棒,感觉很真实,对于机器学习来说不是必须的。人工智能不在乎环境是否美丽。
- 关注逻辑和脚本。你将在这里呆很长时间。好消息是:这并不复杂。Unity 为你做了大部分工作。
当你掌握了基础知识,你就可以开始机器学习了。你可以在这里找到 ML-Agents 工具包。如果您仍然对发动机的许多方面感到困惑,请不要担心。这是意料之中的!!
ML 代理——一些提示
首先文档是你最好的朋友。请务必仔细阅读,细节决定成败。本文的目标不是一步一步的分解。但是我想给你一些建议,在开始之前我会很感激的。
- 先看看例子。我的意思是真的检查他们。查看代码,尝试理解每一个细节。您可以在这里找到许多最佳实践,它可以帮助您构建自己的环境。
- 开始尽可能简单。如果你觉得:“哦这个环境太轻松了,真没意思”。完美,只有这样你的环境才足够简单。当你的特工训练成功后,你可以随时增加复杂性。但是它减少了你犯错的机会。强化学习中的小错误会导致灾难。
- 工作认真。在编程中,我们习惯于先按 play,再修复错误。对于机器学习来说,这是一个坏主意,因为迭代时间取决于训练时间。训练时间从几个小时到几天不等。
- 与人工输入一起工作,直到一切正常。通过使用所谓的“玩家大脑”,你可以控制代理。它允许更快的测试和迭代,并且您可以在培训代理之前确保您的环境的基础是稳固的。
- 如果一切正常,切换到独立版本。在使用您的输入测试所有核心功能后,您可以切换到实际培训。首先在编辑器中这样做。如果一切似乎都很好,切换到一个独立的版本。编辑器有很多开销,不必要地减缓了你的训练时间。
- 人类示范是你的朋友。当我开始的时候,我高估了代理人的能力。看似简单的环境可能极具挑战性。记录你的游戏可以极大地加快学习过程。用它!
- 奖励塑形危险,适量使用。很多时候,奖励都是在一个关卡结束才给的。因此,要获得任何奖励都需要一系列复杂的步骤。当你看着代理人努力获得任何奖励时,即使经过几个小时的培训,给予一些中介奖励也是非常诱人的。这很容易导致剥削或者以你可能不喜欢的方式塑造游戏。在你塑造奖励之前,试着利用好奇心或人类示范。
我希望这有所帮助!如果你感兴趣的话,我正在经营一个 youtube 频道,里面有关于强化学习的内容。查看 这里 !
亚马逊 SageMaker 和 Terraform 的机器学习基础设施——欺诈检测案例
Image by krzysztof-m from Pixabay
想到机器学习和它的“深度”孩子,深度学习,人们会立即想象出一个只有通过巨大的计算能力才能解决的复杂网络。大数据的出现,特别是云机器学习平台,极大地简化了更广泛人群对这些计算能力的访问。
一个云机器学习平台提供了一个完全托管的基础设施,它可以自动扩展,与最新的数据技术集成,并配备了许多内置算法。这使得任何开发人员和数据科学家都能够快速构建和部署模型,而无需担心底层复杂的基础设施。
亚马逊 SageMaker 是亚马逊 Web Services (AWS) 提供的云端机器学习平台。
AWS 解决方案构建团队分享了许多基于亚马逊 SageMaker 构建的不同解决方案,涵盖了电信预测分析或预测性列车设备维护等主题。
在这篇文章中,我将以 信用卡欺诈检测解决方案 为例,解释如何使用 Terraform 建立支持基础设施,同时将解决方案分解成更小的块。
这篇文章的目标读者是对学习支持机器学习的云基础设施和快速浏览机器学习工作流程感兴趣的读者。
免责声明 :我不自称任何机器学习方面的专业知识。这篇文章中所有的机器学习工作都来自 AWS 网站。我主要关注云基础设施和开发运维。我确实有数据分析的背景,使用过 R 进行金融预测和风险管理计算,但这不是这里的主要目的。
A.介绍
这个解决方案的目标是预测给定的信用卡交易是否是欺诈性的。
这是一个二元(是/否)分类,通常需要逻辑回归算法,在 Amazon SageMaker 的上下文中,该算法相当于带有二元分类器预测器类型的内置线性学习器算法。
本文的完整项目托管在 Github 上。
B.解决方案概述
该解决方案有 3 个主要部分:
- 基于示例信用卡交易数据集训练模型。
- 将模型存储在可访问的界面中。
- 使用该模型来预测生成的交易是否是欺诈性的。
这些是典型的机器学习过程,看起来像这样:
Source: https://hackernoon.com/a-brief-overview-of-automatic-machine-learning-solutions-automl-2826c7807a2a
C.实施演练
让我们根据以上 3 个部分来实现。
1.基于示例信用卡交易数据集训练模型。
要训练模型,需要以下组件:
我。信用卡交易数据集,其中欺诈交易已经被识别(也称为标记)。
二。存储为 Docker 映像的机器学习算法(对于外行来说相当于 CD-ROM)。
三。一个服务器,带有预加载的机器学习库,供数据科学家准备、可视化和增强训练数据,然后设置算法的参数(通俗地说;机器学习中的超参数说话)。
四世。服务器使用特定算法训练模型,这本质上是机器学习的“学习”部分,也是需要最多计算能力的部分。
亚马逊 SageMaker 提供 ii 、 iii 和 iv 作为托管服务,而 i 取自公共数据源。
1a。基础设施
这是它开始变得技术性的地方。如果对基础设施不感兴趣,可以跳过这个。
就这部分解决方案的基础设施而言,我们只需要设置 iii (称为 notebook 实例),其中包含了所有必要的库和一个Jupyter notebook,基本上就是数据科学家的工具代码(cum 文档)。位于源代码库中source/notebooks/sagemaker_fraud_detection.ipynb
的 Jupyter 笔记本,包括使用 Amazon SageMaker 的库检索 ii (算法)和交付 iv (训练实例)的代码。
在 AWS 世界中,一个实例通常是指一个服务器,它可以是一个虚拟机或一个容器。
如上所述,笔记本实例需要一些支持资源,包括:
- 笔记本实例的 IAM 角色和策略:
Complete code: https://github.com/qtangs/tf-fraud-detection-using-machine-learning/blob/master/terraform/iam_sagemaker.tf
- 用于存放 Jupyter 笔记本的 S3 桶:
Complete code: https://github.com/qtangs/tf-fraud-detection-using-machine-learning/blob/master/terraform/s3_lambda.tf
- 用于存储训练数据以及生成的模型数据的 S3 存储桶:
Complete code: https://github.com/qtangs/tf-fraud-detection-using-machine-learning/blob/master/terraform/s3_sagemaker.tf
- SageMaker 笔记本实例:
Complete code: https://github.com/qtangs/tf-fraud-detection-using-machine-learning/blob/master/terraform/sagemaker.tf
1b。笔记本实例初始化脚本
为了让 notebook 实例获得位于我们源代码中的 Jupyter 笔记本,我们必须添加一个 init 脚本,从上面的AWS _ S3 _ bucket . fraud _ detection _ function _ bucket(我们使用 aws_s3_bucket_object 上传)下载笔记本。这是使用笔记本实例的生命周期配置完成的:
Complete code: https://github.com/qtangs/tf-fraud-detection-using-machine-learning/blob/master/terraform/sagemaker.tf
sagemaker_instance_init.sh
1c。培训用 Jupyter 笔记本逻辑
以下是 Jupyter 笔记本中的主要步骤:
I .下载样本数据并提取特征和标签(欺诈/非欺诈)。
二。将 n 维数组转换为 RecordIO 格式(一种高效的数据格式)。
import sagemaker.amazon.common as smac
buf = io.BytesIO()
smac.write_numpy_to_dense_tensor(buf, features, labels)
三。将记录数据存储到 S3 桶中。
bucket = "fraud-detection-end-to-end-demo"
prefix = 'linear-learner'
key = 'recordio-pb-data'boto3.resource('s3').Bucket(bucket).Object(os.path.join(prefix, 'train', key)).upload_fileobj(buf)
四。为线性学习算法检索 Docker 图像。
container = get_image_uri(boto3.Session().region_name, 'linear-learner')
v 。使用所需的实例类型和实例数量创建一个训练作业,更改算法的(超级)参数,并使用之前上传到 S3 的训练数据开始训练。您可以看到,建立一个服务器集群来训练一个模型是多么简单,并且只需为训练花费的时间付费,这是一个主要的成本节约。
import sagemaker
s3_train_data = 's3://{}/{}/train/{}'.format(bucket, prefix, key)
output_location = 's3://{}/{}/output'.format(bucket, prefix)linear = sagemaker.estimator.Estimator(container,
get_execution_role(),
train_instance_count=1,
train_instance_type='ml.c4.xlarge',
output_path=output_location,
sagemaker_session=session)linear.set_hyperparameters(feature_dim=features.shape[1],
predictor_type='binary_classifier',
mini_batch_size=200)linear.fit({'train': s3_train_data})
2.将模型存储在可访问的界面中。
要存储模型并将其呈现给外部世界以便以后进行预测,需要以下组件:
我。模型数据
二世。其他模型元数据(容器、培训作业等)
三。端点(接口)配置
四。实际端点(按需运行预测的一组服务器)
Amazon Sagemaker 托管 ii 、 iii 和 iv ,而 i (模型数据)存储在 S3,正如我们在前面的代码(output_location
)中看到的。 i 和 ii (型号规格)均在调用linear.fit(...)
结束时创建。
端点配置( iii )和实际端点( iv )由 Jupyter 笔记本的这一部分创建:
linear_predictor = linear.deploy(initial_instance_count=1,
endpoint_name="fraud-detection-endpoint",
instance_type='ml.m4.xlarge')
3.使用该模型来预测生成的交易是否是欺诈性的。
有了创建的端点,我们现在可以在任何生成的事务上使用它。
为了模拟即将进行预测的事务,我们需要:
- 创建一个 CloudWatch 事件,每 1 分钟触发一次 Lambda 函数。
- AWS Lambda 函数是使用代码库中位于
source/fraud_detection/index.py
的代码创建的。它遵循以下步骤:随机选择预定义的欺诈或非欺诈交易,将交易发送到端点以获得欺诈预测,在进行一些小的处理后,将结果发送到 Kinesis Data Firehose。 - 将流式结果存储到 S3 的 Kinesis 数据消防软管。
- 最后,S3 桶。
如上所述,带有蓝色 Terraform 徽标的资源是必需的:
- 云观察事件:
Complete code: https://github.com/qtangs/tf-fraud-detection-using-machine-learning/blob/master/terraform/cloudwatch_event.tf
- Lambda 预测函数的 IAM 角色和策略:
Complete code: https://github.com/qtangs/tf-fraud-detection-using-machine-learning/blob/master/terraform/iam_lambda.tf
- 用于存储函数代码的 S3 存储桶,取自我们代码库中的
source/fraud_detection/index.py
Complete code: https://github.com/qtangs/tf-fraud-detection-using-machine-learning/blob/master/terraform/s3_lambda.tf
- 处理新事务的 Lambda 函数:
Complete code: https://github.com/qtangs/tf-fraud-detection-using-machine-learning/blob/master/terraform/lambda.tf
- 用于 Kinesis 数据消防软管的 IAM 角色和策略:
Complete code: https://github.com/qtangs/tf-fraud-detection-using-machine-learning/blob/master/terraform/iam_kinesis.tf
- 存储来自 Kinesis 数据消防软管的已处理事务的 S3 存储桶:
Complete code: https://github.com/qtangs/tf-fraud-detection-using-machine-learning/blob/master/terraform/s3_kinesis.tf
- 最后,Kinesis 数据消防软管:
Complete code: https://github.com/qtangs/tf-fraud-detection-using-machine-learning/blob/master/terraform/kinesis.tf
D.部署
Terraform 代码位于terraform
文件夹中(原始云信息可在cloudformation
中找到)。
在运行terraform apply
之前,需要进行一些设置:
我。将terraform_backend.tf.template
复制到terraform_backend.tf
并相应修改数值。您需要手动创建一个 S3 存储桶或使用现有的存储桶来存储 Terraform 状态文件。
terraform_backend.tf.template
对 Terraform 状态使用远程后端是一个很好的实践。即使像这样简单的场景也应该这样做。
二。将terraform.tfvars.template
复制到terraform.tfvars
,并相应修改数值。您不需要创建此处指定的任何存储桶;它们是由terraform apply
创造的。
terraform.tfvars.template
iii 。一旦创建了以上文件,只需运行以下 terraform 命令。记住确保所有命令返回 ok,并在应用前查看地形图。
# Set default AWS profile,
# use 'set' instead of 'export' for Windows.
export AWS_PROFILE=<your desired profile>terraform init
terraform validate
terraform plan -out=tfplan
terraform apply --auto-approve tfplan
Terraform 平面图的输出应该如下所示:
而terraform apply
的结果:
最终手动步骤
一旦所有的 Terraform 资源都设置好了,你需要按照 AWS 站点记录的这些手动步骤:
运行笔记本
- 导航到亚马逊 SageMaker 控制台。
- 在导航窗格中,选择笔记本实例。
- 选择frauddetectionnotebook instance。
- 笔记本实例应该已经在运行。
- 选择打开 Jupyter 。
- 在 Jupyter 笔记本界面,打开
sagemaker_fraud_detection.ipynb
文件。 - 在单元格下拉菜单中,选择运行全部运行文件。
启用云观察事件规则
- 导航到 AWS Lambda 控制台。
- 在导航窗格中,选择功能。
- 选择
fraud_detection_event_processor
λ功能。 - 在设计器选项卡的图中,选择 CloudWatch 事件。
- 在 CloudWatch 事件选项卡中,选择
*<stackname>*-ScheduleRule-*<id>*
。 - 选择动作动作>动作启用。
- 选择启用。
验证 Lambda 函数正在处理事务
- 导航到AWSλ控制台。
- 在导航窗格中,选择功能。
- 选择
fraud_detection_event_processor
λ功能。 - 选择监控并验证调用图显示活动。
- 几分钟后,检查已处理事务的结果亚马逊 S3 桶。
E.清除
完成实验后,只需执行以下操作即可删除所有资源并节省成本。再次提醒,记得在应用之前检查地形图。
terraform plan -destroy -out=tfplan
terraform apply tfplan
您应该能够看到如下输出:
F.摘要
亚马逊 SageMaker 是一个强大的平台,我们刚刚触及它的表面。
感谢 AWS Solution Builders 团队,我们有许多关于如何利用 Amazon SageMaker 的精彩例子。
与此同时,Terraform 简化了企业的基础设施设置,开发运维及持续交付变得越来越重要。
在未来的帖子中,我将研究 AWS 团队提供的更复杂的示例,并探索如何设计 Terraform 基础设施,以适应机器学习设置中的 CI/CD 管道。
感谢您的阅读。请在下面评论分享你的想法。
本文的完整项目托管在 Github 上。
黑盒与白盒模型
大多数机器学习系统需要能够向利益相关者解释为什么做出某些预测。在选择合适的机器学习模型时,我们通常会在准确性和可解释性之间进行权衡:
- 精确和“黑箱”:
神经网络、梯度推进模型或复杂集成等黑箱模型通常可以提供很高的精确度。这些模型的内部工作更难理解,它们不能提供对模型预测中每个特征的重要性的估计,也不容易理解不同特征如何相互作用。 - 较弱的“白盒”:
另一方面,线性回归和决策树等较简单的模型提供的预测能力较低,并且不总是能够模拟数据集的内在复杂性(即特征相互作用)。然而,它们更容易解释和诠释。
Image from Applied.AI
准确性与可解释性的权衡基于一个重要的假设,即‘可解释性是模型的固有属性’。然而,我坚信,通过正确的“可解释性技术”,任何机器学习模型都可以变得更具可解释性,尽管有些模型的复杂性和成本要高于其他模型。**
在这篇博文中,我将讨论一些可用于解释机器学习模型的不同技术。这篇博文的结构和内容高度基于 H20.ai 关于机器学习可解释性的小册子。如果你想了解更多,我强烈推荐大家阅读帕特里克·霍尔的 H20.ai 小册子或其他材料!
模型属性
模型的可解释程度通常与响应函数的两个属性有关。模型的响应函数 f(x) 定义了模型的输入(特征 x )和输出(目标 f(x) )之间的输入输出关系。根据机器学习模型,该函数具有以下特征:
- 线性:在线性响应函数中,特征和目标之间的关联表现为线性。如果一个特性线性变化,我们也期望目标以相似的速率线性变化。
- 单调性:在单调响应函数中,特征和目标之间的关系在特征上总是在一个方向上(增加或减少)。更重要的是,这种关系适用于整个特征域,并且独立于其他特征变量。
An example of a simple linear and monotic response function (1 input variable x, 1 response variable y)
线性和单调函数的例子是例如线性回归模型,而例如随机森林和神经网络是展示高度非线性和非单调响应函数的模型的例子。
由 Patrick Hall 制作的下一张幻灯片说明了为什么在需要清晰简单的模型解释时,白盒模型(具有线性和单调函数)通常是首选。顶部的图显示,随着年龄的增长,购买次数也在增加。响应函数在全局水平上具有线性和单调的关系,容易被所有利益相关者解释。
然而,由于白盒模型的线性和单调约束,错过了趋势的很大一部分。通过探索更复杂的机器学习模型,有可能更好地拟合观察到的数据,尽管响应函数在局部水平上只是线性和单调的。为了解释模型的行为,有必要在本地级别研究模型。
模型可解释性的范围,即在全球或地方一级,与模型的复杂性有内在联系。线性模型在整个特征空间表现出相同的行为(如顶部图所示),因此它们是全局可解释的。输入和输出之间的关系通常受限于复杂性和局部解释(即,为什么一个模型在某个数据点做出某个预测?)默认为全局解释。
对于更复杂的模型,模型的全局行为更难定义,需要对响应函数的小区域进行局部解释。这些小区域更有可能表现为线性和单调的,从而实现更准确的解释。
ML libraries (e.g. sk-learn) allow quick comparisons between different classifiers. When the dataset is limited in size and dimensionality, it is possible to interpret the results. In most real-life problems this is not the case anymore.
在这篇博文的剩余部分,我将关注两个模型无关的技术,它们提供了全局和局部的解释。这些技术可以应用于任何机器学习算法,并且它们通过分析机器学习模型的响应函数来实现可解释性。
可解释性技术
代理模型
代理模型是(通常更简单的)模型,用于解释更复杂的模型。线性模型和决策树模型由于其简单的解释而经常被使用。创建代理模型是为了表示复杂模型(响应函数)的决策过程,并且是基于输入和模型预测而不是输入和目标训练的模型。代理模型在非线性和非单调模型之上提供了一层全局可解释性,但不应完全依赖它们。代理模型不能完美地表示潜在的响应函数,也不能捕捉复杂的特征关系。它们主要作为一个模型的“全局总结”。以下步骤说明了如何为任何黑盒模型构建代理模型。
- 训练一个黑盒模型。
- 评估数据集上的黑盒模型。
- 选择一个可解释的代理模型(通常是线性模型或决策树)。
- 对数据集及其预测训练可解释的模型。
- 确定代理模型误差度量并解释代理模型。
石灰
LIME 背后的一般思想与代理模型相同。然而,LIME 并不构建代表整个数据集的全局代理模型,而仅构建解释局部区域预测的局部代理模型(线性模型)。关于 LIME 更深入的解释可以在这篇关于 LIME 的博文中找到。
LIME 提供了一种直观的方式来解释给定数据点的模型预测。
以下步骤说明了如何为任何黑盒模型构建 LIME 模型。
- 训练一个黑盒模型。
- 感兴趣的局部区域的样本点。可以从数据集中检索点,也可以生成人工点。
- 根据新样本与感兴趣区域的接近程度对其进行加权。将加权的、可解释的(替代)模型拟合到有变化的数据集上。
- 解释本地代理模型。
结论
有几种不同的技术可以用来提高机器学习模型的可解释性。尽管随着该领域的发展,这些技术变得越来越强大,但始终比较不同的技术是很重要的。我没有讨论的一个技巧是 Shapley 值。看看 Christoph Molnar 关于“可解释机器学习”的书,了解更多关于这方面(以及其他)的技术!
如果你对机器学习的可解释性有任何问题,我很乐意在评论中阅读。如果你想收到我博客上的更新,请在 Medium 或 Twitter 上关注我!
机器学习:介绍、巨大的失败和希望
Photo by Ahmed Hasan on Unsplash
什么是机器学习?
维基百科告诉我们,机器学习是“计算机科学的一个领域,它赋予计算机无需明确编程就能学习的能力”它接着说,“机器学习探索研究和构建可以从数据中学习并对数据进行预测的算法——这种算法通过进行数据驱动的预测或决策,通过从样本输入建立模型,克服了严格静态的程序指令。”
从输入中学习
在没有明确编程的情况下从输入中学习意味着什么?让我们考虑一个经典的机器学习问题:垃圾邮件过滤。
想象一下,我们对机器学习一无所知,但我们的任务是确定一封电子邮件是否包含垃圾邮件。我们如何做到这一点?以下是我的一些想法:
- 分析 IP 地址。根据 IP 地址,我们通常可以确定发件人的位置,垃圾邮件可能更多地来自离收件人不近的位置。
- 看邮件的正文。有提到尼日利亚王子的吗?
- 寻找不常见的电子邮件地址模式。例如,电子邮件地址的末尾是否有大量的数字?
这些只是一些想法,但希望你还能想到更多。
现在想象我们有一个黑匣子,如果给它大量垃圾邮件和非垃圾邮件的例子,它可以从这些例子中学习垃圾邮件的样子。我们将称之为黑盒机器学习。通常我们提供给它的数据被称为特性。
想要一个更直观的从输入中学习的例子吗?看看这个程序使用机器学习来学习如何玩 Flappy Bird。
为什么是机器学习?
看完上面的垃圾邮件例子后,你可能会想:为什么我们需要机器学习来检测垃圾邮件?似乎人类或基于规则的程序可以很好地完成这项任务。以下是一些好处:
- 刻度。与人类相比,扩展机器学习算法要容易得多。一台机器可以在一分钟内分析数千封(如果不是更多)邮件中的垃圾邮件。
- 成本。虽然开发机器学习的前期成本较高,但如果你成功开发了一种有效的算法,则终生成本会显著降低。
- 健壮。机器学习的好处之一是它可以更容易地适应新趋势。如果您开发了数千行规则来检测垃圾邮件,然后发布了一种新的垃圾邮件(可能是一封说您中了彩票的电子邮件),则很难在不违反先前规则的情况下更新您的规则。使用机器学习算法,你需要的只是新趋势的数据,然后重新训练你的算法——它会根据趋势进行调整。
- 聪明。人类和基于规则的程序经常会努力开发方法来检测具有挑战性的案例。例如,为垃圾邮件中可能存在的所有基于文本的模式编写规则是很困难的。随着更复杂的模型(如深度学习)的出现,通常模型可以更好地捕捉模式。
机器学习问题的类型
现在我们已经有了什么是机器学习以及为什么它会有价值的基础,让我们看看机器学习可以解决的一些类型的问题。
有监督的机器学习问题是那些你已经标注了数据的问题。带标签的数据意味着你用数据给算法解,这些解叫做标签。例如,对于垃圾邮件分类,标签可能是“垃圾邮件”或“非垃圾邮件”线性回归被认为是解决监督问题的算法。
无监督机器学习则相反。它没有任何标签。这些算法通常没有标签那么强大,但当获取标签数据非常昂贵或不可能时,它们会非常有价值。一个例子是聚类。
回归问题是一类你试图预测一个实数的问题。例如,线性回归输出一个实数,可以用来预测房价。
分类问题是你要预测其类别标签的问题。例如,垃圾邮件预测是一个分类问题,因为您想知道您的输入是属于两类之一:“垃圾邮件”还是“非垃圾邮件”。逻辑回归是一种用于分类的算法。
排名问题在电子商务中非常普遍。这些模型试图根据项目对用户的价值进行排序。比如网飞的电影推荐。一个示例模型是协同过滤。
强化学习是指在一个环境中,有一个代理人开始执行行动并获得行动奖励。这里的模型学习采取最佳行动以获得最大回报。flappy bird 视频就是强化学习的一个例子。一个示例模型是深度 Q 网络。
Photo by Nathan Dumlao on Unsplash
未能交付
也许我最喜欢维基百科页面上关于机器学习的部分是,“截至 2016 年,机器学习是一个时髦词,根据 Gartner 2016 年的炒作周期,处于膨胀预期的顶峰。有效的机器学习是困难的,因为发现模式是困难的,并且通常没有足够的训练数据可用;因此,机器学习程序经常无法交付。
以下是我对机器学习问题为何无法传递价值的一些思考。
没有明确的问题需要解决。
该公司的一名高管听说机器学习是下一件大事,所以他们聘请了一个数据科学团队。不幸的是,对于要解决什么问题没有一个清晰的想法,所以团队纠结了一年。
标记数据对于构建机器学习模型可能极其重要,但也可能极其昂贵。
首先,你经常需要大量的数据。 Google 发现,对于表示学习,性能会根据训练数据量以对数方式增长:
其次,您需要获得代表您试图解决的问题的完整分布的数据。例如,对于我们的垃圾邮件分类问题,我们可能想要收集哪些类型的电子邮件?如果我们只有来自美国 IP 地址的邮件会怎么样?
最后,光是标记数据就很费时,而且要花很多钱。如果你还没有垃圾邮件分类的数据,谁来给数百万封邮件贴上垃圾邮件或者不是垃圾邮件的标签呢?
数据可能会很乱
现实世界中的数据通常有错误、异常值、缺失数据和噪声。如何处理这些会极大地影响模型的结果,并且需要时间和经验来做好。
特色工程
一旦有了数据和标注,决定如何在模型中表示数据可能会非常具有挑战性。例如,对于垃圾邮件分类,你会给它输入原始文本吗?IP 地址的来源呢?时间戳呢?从数据中创建的特征通常比选择的算法更重要。
你的模型可能无法概括
在所有这些之后,您可能仍然会得到一个过于简单而无效(欠拟合)或者过于复杂而不能很好地概括(过拟合)的模型。你必须开发一个恰到好处的模型。😃
评价非同小可
假设我们开发了一个垃圾邮件分类的机器学习模型。我们如何评价?我们更关心精度还是召回?我们如何将科学指标与业务指标联系起来?大多数新数据科学家习惯于处理评估指标已经确定的问题。在行业中,确定您想要优化什么,以及设计一个算法来适当地最大化(或最小化)该指标,可能是非常具有挑战性的。
投入生产可能会很困难
您有一个内置 Python 的漂亮模型,却发现您不知道如何将它投入生产。后端是 Java,模型必须在 5 毫秒内运行。你没有 Java 经验,不确定如何加速你的模型。通常,公司试图通过让工程师将科学家的代码转化为产品来解决这个问题,但这种移交方法可能会由于过程中的信息丢失而导致严重的延迟甚至错误。
Photo by bruce mars on Unsplash
希望
虽然许多机器学习计划确实失败了,但也有许多获得了成功,并经营着一些世界上最有价值的公司。像谷歌、脸书、亚马逊、Airbnb 和网飞这样的公司都已经找到了利用机器学习的成功方法,并获得了巨大的回报。
谷歌首席执行官桑德尔·皮帅最近甚至说“从移动优先的世界到人工智能优先的世界有一个重要的转变”
马克·库班对说,“人工智能、深度学习、机器学习——不管你在做什么,如果你不懂,就去学。因为否则你会在三年内变成恐龙。”
最后,哈佛商业评论发现
在使用数据驱动的决策方面,行业排名前三分之一的公司比其竞争对手的生产率和利润平均高出 5%和 6%
我希望这篇文章已经很好地向您介绍了机器学习的世界、一些挑战以及它为什么如此有价值。现在取决于你在你的公司执行机器学习并释放潜在价值。如果你正在寻找一些关于如何开始的想法,看看我的另一篇文章:
为了你的创业
towardsdatascience.com](/delivering-on-the-promise-of-artificial-intelligence-f6424a75d61c)
这篇文章也可以在这里找到。
初学者机器学习入门
“追求数据科学的简单性。真正的创造力不会让事情变得更复杂。相反,它会简化它们。”
― 达米安·杜菲语重心长
我们想通过广告来提高产品的销量。所以,让我们看看我们的广告渠道:电视、广播、社交媒体、报纸等。
因此,广告预算(Y)被称为因变量或反应,电视(X1)、广播(X2)、社交媒体(X3)、报纸(X4)被称为自变量或预测因素。
预言;预测;预告
关系:- Y = f (X) + e 是我们真实的观测值。 f 是将输入变量(X)最佳映射到输出变量(Y)的目标函数。
我们对 Y 的预测将取决于 y(y
=f(X))、*** 的精度,而后者又取决于另外两个量:**可约误差**和**不可约误差**。一般来说, ***f
想成为f 的完美估计量,但可约误差以不精确的形式存在。这个误差是可以减少的,因为我们可以通过使用最合适的统计学习方法来提高 f*** 的精度。然而,即使有可能为 ***f、*** 形成完美的估计量,使得 ***y
=f(X) ,我们的预测仍然会有一些误差,称为不可约误差。这个误差的存在是因为 y 也是 e、 的一个函数,它不能由 X 预测。我们不测量它们,因此, f 不能用它们进行预测。
我们的主要焦点应该是如何减少可约误差。预测问题就像:给定这个人的特征,你会把他归入哪一类?这个问题是关于当你已经给定了输入变量 X 时,如何预测 Y。
推理
当我们想了解反应(Y)和预测因素(X)之间的关系时,就称为推论。我们不能把 f` 当作一个黑盒,因为我们想知道它的确切形式。我们希望了解预测因素和反应之间存在的关系,无论是正相关还是负相关。
这将回答诸如“哪种媒体对销售贡献最大?”等等。这些问题的要点是单个输入变量(X)对输出变量(Y) 的影响有多大。
线性模型将帮助我们进行简单和可解释的推断,但可能不会像其他一些统计方法那样产生准确的预测。
参数模型
它是一个分布族,可以很容易地用有限数量的参数来定义。在这种模型中,您知道哪个模型适合您的数据。
举例:- yi=β0+β1xi+ei 是线性回归。
它与您“假设”的数据遵循的特定概率分布相关联。这种方法将估计 f 的问题减少到几组参数。
参数模型示例:-线性回归、逻辑回归和 SVM。
唯一的缺点就是我们选择的模型可能和 f 的真未知形式不匹配。如果选择的模型离真实的 f、 太远,那么我们从那个模型得到的估计就会很差。
为了解决这个问题,我们可以为 f. 选择一些可以适应多种不同功能形式的灵活模型
非参数模型
它基于无分布或者具有指定的分布,但是分布的参数未指定。这些数据会告诉你‘回归’应该是什么样子。
**Y =f(X)+e,*** 其中 f() 可以是任意函数。
数据会告诉你函数会是什么样子。在训练模型 之前,我们不推测任何关于我们试图学习的 f 的函数形式的假设。 模型将由数据决定。参数模型的示例:- KNN、决策树和 RBF 核 SVM。
唯一的缺点是,我们需要非常大量的观测数据来获得对真 f. 的准确估计,这导致模型的复杂性和灵活性增加。*
限制性与灵活性方法
如果我们主要对推理感兴趣,那么我们应该选择限制性模型。这是因为它的简单性和可解释性。
举例:线性回归有助于我们理解 Y 和 X1,X2 的关系,..Xp。 假设,我们没有选择一个更简单、限制性更强的模型,而是选择了一个像 KNN 那样复杂、灵活的模型。我们将无法理解个体预测因子是如何与反应变量相关联的。当我们只对预测感兴趣而对可解释性不感兴趣时,我们应该使用灵活的模型。
例子:预测股票价格。
此外,由于在高度灵活的方法中过度拟合,有时我们可能使用不太灵活的方法获得更准确的预测。
监督与非监督学习
如果给定了响应( Y )变量,则采用监督学习方法。在学习中,我们使用标注有正确答案的数据来训练机器。
监督学习分为两部分:回归或分类。有定量反应的问题称为回归问题,有定性反应的问题称为分类问题。定量反应意味着真实值,如身高、价格等。定性意味着绝对。
例子:-线性回归、逻辑回归、KNN 等。
如果没有给出响应( Y )变量,则采用无监督学习方法。我们希望了解数据的底层结构,而不需要提供任何明确的标签。
它有聚类,帮助我们进行细分。
均方误差
它是使用训练数据 ie 计算的。用于拟合模型。我们应该不是真的对 f(xi) = Yi*** 感兴趣;相反我们想知道 ***f
(x0) 是否约等于y0;* 其中 (x0,y0) 是一个看不见的测试观测。
随着模型灵活性的增加,模型可能会产生较小的训练 MSE,但由于过度拟合,可能会导致较大的测试 MSE。这是因为我们的统计学习方法过于努力地在训练数据中寻找模式,这导致它拾取随机噪声,而不是未知函数 f 的真实属性。*
偏差-方差权衡
这个期望测试 MSE 是f ( x0)****f
( x0)的方差和误差的方差 (e)之和。****
这个等式告诉我们要降低偏差和方差。
方差指的是 f*** 变化的量,如果我们使用一个看不见的训练数据集来估计的话。这是一种通过拟合高度灵活的模型来学习随机事物的趋势,这些模型过于接近地学习数据中的误差/噪声。导致**过拟合。**由于训练数据符合统计学习方法,不同的训练数据集会产生不同的 ***f
。f*** 应该变化不大,理想情况下。但是具有高方差的方法将随着训练数据的改变而保持改变 ***f
。一般来说,灵活的方法更倾向于较高的方差。
偏差是该方法由于没有考虑数据中的所有信息而不断学习错误的东西的倾向。它很少关注训练数据,并且过于简化模型。这导致装配不足。如果我们用一个非常简单的模型来近似一个非常复杂的问题,会导致偏差。
参数或线性机器学习算法往往偏高但方差低,非参数算法偏低但方差高。
理想的拟合应该是捕捉数据集中的规律性,足以能够推广到来自同一来源的看不见的数据点。不幸的是,在实践中,同时做到这两点几乎是不可能的。因此,我们在游戏中有一个权衡。
感谢阅读! 这里也可以给支持:https😕/buymeacoffee.com/divadugar
机器学习是零和游戏!
ML 不同于工业化、电力和 IT
我预测,10 年后,只有今天投资机器学习的公司才会存在。那些观望的人会被他们的竞争对手吃掉。
机器学习(ML)革命不同于以往的任何革命;工业革命,电力或信息技术革命。
我们称之为工业化的时代,围绕着从手工生产方式向机械自动化的转变而发展。第二次工业革命发生在大约一百年后,当时我们开始通过大坝发电获得更可靠的能源。第三次大革命是通过从 20 世纪 90 年代一直到今天的 IT 繁荣形式的自动化。
在前三次革命中,不适应工业化、电力或 IT 的公司最终会消亡。但是那些成功的公司并没有获得无限的竞争优势。革命性的步骤是巨大的,但它们并没有带来永久的竞争优势。每个人都从中受益,每个人都可以从零开始,很快赶上来。举例来说,你今天可以开一家制鞋厂,而老厂商不会有竞争优势,因为它们已经用了一百年的电了。
ML 中的先行者获得了不公平的优势
机器学习不同于以往的革命,因为它非常依赖你收集的历史数据。
拥有最多数据的公司将能够创造不公平的竞争优势!想象一下,例如,一家制造公司可以更好地采购 5%的原材料,减少 2%的损耗,提高 10%的能源效率,减少 7%的人为错误,等等。企业的利润越薄,在该行业进行 ML 的可能性就越大。他们根据历史数据优化得越多,失败者就越难赶上。
那些更早开始收集数据并利用这些数据进一步改进其 ML 模型的公司将获得永久的不公平优势。不可能用更少的数据竞争,也不可能迎头赶上或从头开始。数据不是新的黄金,数据是你的克星——它会让你的竞争对手无法接近你。
这在 B2B 中尤其如此,在 B2B 中,客户数据依赖于与其他企业的协议。这一小小的竞争优势将帮助你赢得客户,帮助你增加数据并进一步改进你的 ML 模型。
企业是有优势的,但前提是要觉醒
世界上的企业巨头拥有先发优势,因为他们已经掌握了关于客户的最多数据。当一个商业垂直领域的第一个巨头意识到 ML 的可能性时,其余的巨头将会被迅速吃掉,而且比过去 20 年中的速度要快得多。沉睡的企业不会有第二次机会。
该醒醒了。你和我的大部分工作最终将被取代,政府有可能因此而监管数据,但政府行动缓慢,现在采取行动的政府将比其他政府至少拥有 20 多年的优势。这是一个零和游戏:你想成为 0 还是 1?
这篇文章的灵感来自 Andreessen Horowitz 播客上的一次讨论。对于原始来源和整个讨论,请在苹果播客收听。
最初发表于T5【https://blog.valohai.com】。
SparkML 与 AWS SageMaker 中的机器学习(kmeans 聚类)——我的两分钱
机器学习,即从数据中学习的能力,一直是大数据最成功和最具颠覆性的用例之一。在数据和分析领域,人们可以使用无数的工具集来承担不同性质和复杂性的机器学习任务。
然而,当一个人在大规模数据上操作时,R 和 Python 等常用语言中的传统机器学习库(如 pandas、scikit-learn)通常会有所不足,因为这些库原本在单个机器上运行,其中要分析的数据应该在内存中(虽然有一些方法,如核外学习,可用于绕过这一点,但它有自己的一套警告)。因此,对于真正的大规模机器学习来说,分布式训练和推理管道变得至关重要。这本身不是一个简单的任务,但是框架和库的可用性极大地促进了这个过程。像 Mahout(运行在旧的 MapReduce 上)和 SparkMLLIB (Spark 基于 RDD 的机器学习库)这样的库是这一类别中的第一批玩家,从那以后我们看到了许多其他类似的出现。这一趋势有如下几个方面:
1.Spark 的机器学习库(SparkML)已经成熟,现在支持通用的数据框架/数据集 API,并覆盖了许多算法和功能工程转换
2。与 Spark 无缝协作的库的可用性,例如 Sparkling Water、DeepLearning4J、XgBoost4J、Stanford Core NLP Wrapper for Spark,因为 Spark 是领先的分布式计算框架
3。深度学习库如 TensorFlow 与其他分布式计算框架如 Apache Beam 的集成和兼容性(如 TensorFlow Transform,在 Google 云平台中得到很好的支持)
4 .云本机机器学习框架和库的可用性,例如 AWS 的 SageMaker
在所有这些趋势中,核心驱动力一直是支持和普及可扩展的机器学习,以便组织可以更加专注于实际工作,而不是陷入如何在引擎盖下运行的底层复杂性。
在 SparkML 和 SageMaker 上使用 kmeans
最近,我有机会在一个无监督的机器学习任务环境中使用 SparkML 和 AWS SageMaker,其核心目标是分析海量数据以执行聚类。鉴于机器学习问题的性质,kmeans(一种广泛使用的基于划分的聚类算法)被认为是合适的。
kmeans in action (source: https://commons.wikimedia.org/wiki/File:K-means_convergence.gif)
SparkML 和 SageMaker 都提供了 kmeans 算法,使用这两种算法的体验有很大的不同,有很多注意事项,因此这篇文章重点关注这一点。如果您打算使用 kmeans 算法(或者其他算法),并且您需要在 SparkML 和 AWS SageMaker 之间做出设计决策,这篇文章也可能在这方面对您有所帮助。
距质心的距离度量:
假设聚类主要是一种无监督的机器学习活动,其中训练实例的真实标签事先不可用,应用聚类算法得到的主要见解是聚类标签与训练实例的关联,即训练实例被分组为聚类,其中启发是聚类中的实例彼此相似,而不是不同聚类中的实例。SparkML 和 SageMaker kmeans 都在运行 kmeans 算法时提供聚类标签。然而,一个显著的区别是离质心的距离,即特定实例离聚类中心有多远。这种洞察力对于检测内聚性和潜在的离群值非常有用。
在这种情况下,除了聚类标签之外,SageMaker 还方便地为每个训练实例提供距质心的距离。
An example of how distance from centroid insight is made available against each training instance in SageMaker
这大大减少了将输出与输入相关联的预处理步骤。
然而,在 SparkML 的情况下,它不是作为输出提供给每个训练实例的。相反,它是作为模型的一个属性提供的。例如,对于虹膜数据,如果使用 4 个特征执行聚类,并且 k=3,则作为训练模型的属性可访问的聚类中心(或质心)将是大小为 3 的数组(相当于聚类的数量),其中每个元素将是 4 个浮点数的数组(对应于 4 维特征空间中的 4 个坐标)。
这就需要额外的预处理步骤来将输出与输入相关联。
确定最佳聚类数:
k 均值要求在运行算法之前提供聚类数(指定为 k)。虽然手头问题的领域知识通常有助于构思聚类的数量,但是我们数据科学家采用数据驱动的方法来确定 k 的正确值。在这种情况下使用肘形曲线和剪影方法等方法。我们采用肘曲线法来确定 k 的最佳数量,这涉及使用不同的 k 值在数据集上多次运行 kmeans 算法,并基于评估度量来确定拟合优度。Spark ML 在设定的误差平方和(WSSSE)内使用。对于 k 的每个值,使用该度量,然后绘制成图。基于此,曲线上发生弯曲的点(从统计角度来说,梯度变小的地方)通常是正确的 k 值。直观地说,这意味着进一步增加 k 值不会导致度量的显著降低。
An example of Elbow curve plotted using matplotlib after running kmeans algorithm for a range of k values (on x-axis) and distortion/cost (on y-axis)
在 SparkML 中使用肘曲线方法非常简单,因为需要指定范围,只需在这些值上训练模型。运行 Spark 的同一个集群用来运行 kmeans 的不同 k 值的多次运行,并且不需要额外的开销。我们使用一个 r 5.12 x 大型实例和大约 35 万个实例以及不同数量的特性(从 4 到 100)进行了测试,每次运行大约需要一分钟。
from pyspark.ml.clustering import KMeans
import numpy as np
cost = np.zeros(50)for k in range(3,50):
kmeans = KMeans().setK(k).setSeed(1).setFeaturesCol("scaled_features")
model = kmeans.fit(spark_dataframe)
cost[k] = model.computeCost(spark_dataframe)
如果使用 Python,可以通过 matplotlib 绘制它。
然而,在 SageMaker 中做同样的事情有它自己的一套注意事项。SageMaker 中的机器学习管道可以形象地表示如下:
Machine Learning workflow using SageMaker (source: https://docs.aws.amazon.com/sagemaker/latest/dg/how-it-works-hosting.html)
在 SageMaker 的情况下,为每个训练或推理作业启动实例,也就是说,如果您想要运行一个具有一组特定超参数(如 k=10)的模型(如 kmeans ),那么您将需要运行一个训练作业来启动一个实例(或多个实例,如果您指定了多个实例)。该训练实例将生成一个名为“模型”的工件,该工件将被存储在一个 S3 存储桶位置(可配置)。仅仅通过运行训练作业并不能得到推论,即集群标签。相反,培训工作的输出是一个模型工件。
为了通过 SageMaker 获得实际的推理,需要运行两种形式的推理作业:
部署一个端点— 推理是通过以 API 调用的形式将测试数据(或无监督算法情况下的训练数据)发送到端点来获得的。SageMaker SDK 对这一点进行了重要的抽象。此外,相同的端点可用于从 SageMaker 生态系统中获取推理,如果有下游应用程序希望以接近实时的方式获取推理,该端点尤其有用
批量转换作业— 如果没有这样的要求来提供一个端点以便于生成如上所述的洞察,那么用户可以使用批量转换作业功能来启动一个实例,下载位于 S3 上的训练数据(这里可以有两种模式,即文件或管道。当使用文件模式时,数据在训练实例上下载,而当使用管道模式时,如果算法支持,则数据是“流”的),生成推理,然后存储回 S3(格式可以是 CSV、JSON 或 recordIO,具体取决于所使用的算法)。
因此,简而言之,使用肘曲线这样的方法将需要相当于你想要的“k”范围的训练实例。由于成本与每次实例启动相关联,因此这是需要小心的事情。此外,每个实例类型都有一个启动时间(可以从 1 分钟到 7 分钟不等,甚至更长),因此仅运行肘形曲线在这方面也会花费大量时间。
Kmeans 参数的默认值:
SparkML 和 SageMaker 中 kmeans 的默认值大不相同。虽然一个好习惯是彻底检查默认值是什么,并根据要求设置它们,但我已经看到人们只是依赖默认值并运行算法。特别是在 SparkML kmeans 的情况下,默认值为:
距离度量:欧几里德
init 方法:kmeans||(这是 kmeans++的增强形式,解决了初始质心初始化的方式)
Init 步骤:2
而在 SageMaker 中:
距离度量:msd(均方距离)
初始化方法:随机
历元(相当于 SparkML 中的初始化步骤):1
在这些差异中,init 方法参数尤其重要,因为与随机方法相比,使用 kmeans++已经证明可以提供更好的结果。
此外,根据我们的分析,通过 SparkML 或 SageMaker 运行 kmeans 时获得的集群的组成有很大不同。因此,如果您在管道中使用这些技术堆栈,这是需要考虑的事情。
简而言之,如果想要加速大规模执行分布式机器学习,这两种方法都是强有力的选择。SageMaker 是一个完整的生态系统,提供了许多其他功能,如笔记本、模型注册等,大大简化了端到端的流程;如果使用 SparkML,这将需要定制的实现。有趣的是,像 Databricks 这样的供应商推出了提供类似功能的 MLFlow 框架,这是社区对这一领域的强烈关注的另一个标志。
如果你有兴趣提升自己在这些技术方面的技能,一定要看看我的关于 Spark 的最畅销课程和我的关于大数据分析的书
机器学习:从企业中吸取的教训
Photo by IBM
训练机器学习(ML)模型的纯学术练习与构建真实企业问题的端到端数据科学解决方案之间存在巨大差异。这篇文章总结了我们的团队在与来自不同行业的数十家企业客户打交道的两年中所学到的经验,这些行业包括制造、金融服务、零售、娱乐和医疗保健等。企业面临的最常见的 ML 问题是什么?训练一个 ML 模型之外还有什么?如何解决数据准备?如何扩展到大型数据集?为什么特征工程如此重要?如何在生产中从一个模型变成一个完全有能力的系统?如果每个数据科学工具都是开源的,我还需要一个数据科学平台吗?这些是将要解决的一些问题,通过具体的行业示例揭示了一些挑战、陷阱和最佳实践。
0。ML 不仅仅是训练模特
我意识到这是一个普遍的误解。当我采访有抱负的数据科学家时,我通常会问:
“假设给你一个具有某些特征的数据集,目标是预测某个变量,你会怎么做?”
令我沮丧的是,他们的回答通常是这样的:
“我会将数据集分成训练/测试,运行逻辑回归、随机森林、SVM、深度学习、XGBoost……(以及其他一些闻所未闻的算法),然后计算精度、召回率、F1 分数……(以及其他一些闻所未闻的指标),最终选择最佳模型”。
但是,我问他们:
“你看过数据了吗?如果你有缺失值怎么办?如果你有错误的值/坏的数据怎么办?你如何映射你的分类变量?你是怎么做特征工程的?”
在这篇文章中,我回顾了成功创建端到端机器学习系统所需的七个步骤,包括数据收集、数据监管、数据探索、特征提取、模型训练、评估、和部署。
1。给我一些数据!
作为数据科学家,数据显然是我们的主要资源。但有时,即使是获取数据也很困难,数据科学团队可能需要几周甚至几个月的时间才能获得正确的数据资产。一些挑战包括:
- 访问:大多数企业数据都非常敏感,尤其是在涉及政府、医疗保健和金融行业时。就共享数据资产而言,保密协议(NDA)是标准程序。
- 数据分散:数据分散在组织内的不同单位,需要得到不同方面的批准,这种情况并不少见。
- 专业知识:访问数据通常是不够的,因为可能有太多的来源,只有的主题专家 (SME)知道如何浏览数据湖,并为数据科学团队提供正确的数据资产。中小型企业也可能成为数据科学项目的瓶颈,因为他们通常忙于核心企业运营。
- 隐私: 混淆和匿名已经成为它们自己的研究领域,并且在处理敏感数据时必不可少。
- 标签:拥有基础事实或标签通常是有帮助的,因为它允许应用广泛的监督学习算法。然而,在某些情况下,标记数据可能过于昂贵,或者由于法律限制,标签可能不可用。像聚类这样的无监督方法在这些情况下很有用。
- 数据生成器:当数据或标签不可用时,另一种方法是模拟它们。在实现数据生成器时,了解一些关于数据模式、数字变量的概率分布和名义变量的类别分布的信息是很有用的。如果数据是非结构化的, Tumblr 是标签图片的绝佳来源,而 Twitter 可能是自由文本的绝佳来源。Kaggle 还提供许多领域和行业的各种数据集和解决方案。
2。大数据往往没那么大
这是一个有争议的问题,尤其是在过去十年大数据供应商大肆宣传,强调可扩展性和性能的必要性之后。尽管如此,我们需要区分原始数据(即所有可能与手头问题相关或不相关的部分)和特征集(即 ML 算法的输入矩阵)。从原始数据到特性集的过程称为数据准备,通常包括:
- 丢弃无效/不完整/脏的数据,根据我们的经验,这些数据可能多达记录的一半。
- 聚合一个或多个数据集,包括连接和组聚合器等操作。
- 特征选择/提取,例如,移除可能不相关的特征,如唯一 ID,并应用其他维度缩减技术,如主成分分析 (PCA)。
- 使用稀疏数据表示或特征散列来减少具有许多零值的数据集的内存占用。
在所有的数据准备步骤完成后,不难意识到最终的特征集——将是机器学习模型的输入——将会小得多;而且,内存框架如 R 或 scikit-learn 足以训练模型的情况并不少见。在特征集非常庞大的情况下,像 Apache Spark 这样的大数据工具会派上用场,但它们可能只有有限的算法集可用。
3.你这肮脏的数据!
Data are often dirty
是的,我最好告诉你一些你不知道的事情,但是我怎么强调都不为过。数据是脏的。在我们的大多数项目中,客户都自豪而兴奋地谈论他们的数据湖,他们的数据湖有多美,以及他们迫不及待地想从中获得多少见解。所以,作为数据科学家,这变成了我们的大脑图像:
尽管如此,当他们真正分享他们的数据时,它实际上看起来更像这样:
这就是像 Apache Spark 这样的可扩展框架至关重要的地方,因为所有的数据监管转换都需要在整个原始数据上执行。一些典型的策展任务是:
- 异常值检测:负年龄、浮点邮政编码或信用评分为零只是无效数据的几个例子。不更正这些值可能会在训练模型时引入高偏差。
- 缺失/不正确的值插补:解决不正确/缺失值的明显方法是简单地丢弃它们。另一种方法是插补,即用相应属性的平均值、中值或模式替换缺失/错误值。另一种选择是插值,即建立一个模型来预测缺失值的属性。最后,领域知识也可以用于插补。假设我们正在处理患者的数据,并且有一个属性表明患者是否患有癌症。如果缺少这样的信息,可以查看预约数据集,并找出患者是否与肿瘤学家有任何预约。
- 虚拟编码和特征散列:这有助于将分类数据转化为数字,尤其是对于基于系数的算法。假设有一个属性 state 表示美国的州(例如 FL , CA , AZ )。映射 FL 到 1, CA 到 2, AZ 到 3 引入了一个感测顺序和幅度,意味着 AZ 将大于 FL ,CA 将是 FL 的两倍。一次性编码— 也称为虚拟编码— 通过将一个分类列映射到多个二进制列来解决这个问题,每个二进制列对应一个类别值。
- 缩放:当特征处于不同的缩放比例时,基于系数的算法会出现偏差。比方说年龄在【0,100】以内以年为单位,而薪水在【0,100,000】以内以美元为单位。优化算法可以向薪金、分配更多的权重,因为它具有更高的绝对幅度。因此,标准化通常是可取的,常见的方法包括 z 评分或标准化(当数据正常时)和最小-最大特征缩放。
- 宁滨:将一个实值列映射到不同的类别会很有用,例如,将一个回归问题转化为一个分类问题。假设您对预测以分钟为单位的航班到达延迟感兴趣。另一种方法是预测航班是提前、准时还是晚点,为每个类别定义范围。
4.这都是关于特征工程的
简而言之,特征是 ML 算法将要学习的特征。正如预期的那样,噪声或不相关的特征会影响模型的质量,因此拥有良好的特征至关重要。特征工程的一些策略是:
- 定义你想预测什么。每个实例代表什么?一个顾客?一笔交易?一个病人?一张票?确保功能集的每一行都对应于一个实例。
- 避免唯一的 id。它们不仅在大多数情况下不相关,而且会导致严重的过拟合,尤其是在应用 XGBoost 等算法时。
- 利用领域知识衍生出有助于衡量成功/失败的新特性。医院就诊的号可能是患者风险的一个指标;过去个月的对外交易的总额可能是欺诈的指标;要求贷款金额与年收入的比例可能是信用风险的一个指标。**
- 使用自然语言处理技术从非结构化自由文本中获取特征。例如 LDA、TF-IDF、 word2vec 和 doc2vec 。
- 如果有非常多的特征,使用降维,例如 PCA 和 t 分布随机邻居嵌入 (t-SNE)。
5.异常检测无处不在
Photo by feature.fm.
如果我要在企业中挑选一个最常见的 ML 用例,那就是异常检测。无论我们指的是欺诈检测、生产测试、客户流失、患者风险、客户违约、系统崩溃预测、等。,问题永远是:我们能大海捞针吗?这引出了我们的下一个话题,与不平衡数据集有关。
一些常见的异常检测算法有:
- 自动编码器
- 单类分类算法,如单类 SVM 。
- 置信区间
- 聚类
- 分类使用过采样和欠采样。
6.数据经常是不平衡的
Unbalanced data
假设您有一个带有标签的信用卡交易的数据集。其中 0.1%的交易被证明是欺诈性的,而 99.9%的交易是正常的。如果我们创造一个模型,说没有欺诈,猜猜会发生什么?该模型将在 99.9%的情况下给出正确答案,因此其准确性将为 99.9%!这种常见的精度谬误可以通过考虑精度和召回等不同的度量来避免。这些是根据真阳性* (TP) 、真阴性 (TN) 、假阳性 (FP) 、和假阴性 (FN)来定义的:*
TP =正确预测为阳性的实例总数**
TN =正确预测为阴性的实例总数
FP =被错误地预测为阳性的实例总数
FN =被错误预测为负的实例总数****
在一个典型的异常检测场景中,我们的目标是最大限度地减少假阴性——例如,忽略欺诈性交易,没有识别出有缺陷的芯片,或者将生病的病人诊断为健康的——同时不招致大量的假阳性。
精度= TP/(TP+FP)
召回= TP/(TP+FN)
注意精确惩罚 FP,而回忆惩罚 FN。从不预测欺诈的模型将具有零召回率和未定义的精确度。相反,总是预测欺诈的模型将具有 100%的召回率,但精确度非常低,这是由于大量的假阳性。
我强烈反对在异常检测中使用接收器工作特性 (ROC)曲线。这是因为 ROC 曲线所依赖的假阳性率 (FPR)严重偏向于数据集中的阴性实例数量(即 FP+TN),导致即使存在大量 FP,FPR 也可能很小。
FPR = FP/(FP + TN)
相反,错误发现率 (FDR)有助于更好地理解 FP 在异常检测模型中的影响:
FDR = 1 -精度= FP/(TP+FP)
7。不要预测。告诉我为什么!
我遇到过几个项目,它们的目标不是创建一个实时预测的模型,而是解释一个假设或分析哪些因素解释了某种行为——鉴于大多数机器学习算法是基于相关性而不是因果关系,这一点要持保留态度。一些例子是:
- 哪些因素使病人陷入高风险?
- 哪种药物对验血结果的影响最大?
- 哪些保险计划参数值使利润最大化?
- 客户的哪些特征使他更容易拖欠?
- 搅拌者的特征是什么?
解决这些问题的一种方法是计算特征重要性,特征重要性由算法给出,如随机森林、决策树和 XGBoost。此外,诸如莱姆或 SHAP 等算法有助于解释模型和预测,即使它们来自神经网络或其他“黑箱”模型。
8.调整你的超参数
机器学习算法既有参数又有超参数。它们的不同之处在于,前者是由算法直接估计的——例如,回归的系数或神经网络的权重——而后者不是并且需要由用户设置——例如,随机森林中的树的数量,神经网络中的正则化方法,或者支持向量机(SVM)分类器的核函数。
为您的 ML 模型设置正确的超参数值可以产生巨大的差异。例如,SVM 的线性核无法对不可线性分离的数据进行分类。如果最大深度或分割数量设置得太高,基于树的分类器可能会过拟合,或者如果最大特征数量设置得太低,基于树的分类器可能会欠拟合。
寻找超参数的最佳值是一个非常复杂的优化问题。一些提示是:
- 了解超参数的优先级。在随机森林中,树的数量和最大深度可能是最相关的,而对于深度学习,学习速率和层数可能是优先的。
- 使用一种搜索策略: 网格搜索 或 随机搜索 。后者优先。
- 使用 交叉验证 :设置一个单独的测试集,将剩余的数据分成 k 个折叠,迭代 k 次,每个折叠用于验证(即调整超参数),剩余的用于训练。最后,计算所有折叠的平均质量度量。
9.深度学习:灵丹妙药?
在过去几年中,深度学习已经成为研究和行业发展的巨大焦点。诸如 TensorFlow 、 Keras 和 Caffe 等框架现在能够通过高级 API 快速实现复杂的神经网络。应用不计其数,包括计算机视觉、聊天机器人、自动驾驶汽车、机器翻译,甚至游戏——击败了世界上最顶尖的围棋人类棋手和最顶尖的国际象棋计算机!
深度学习背后的一个主要前提是它能够随着数据量的增加而持续学习,这在大数据时代尤其有用(见下图)。这与硬件(即 GPU)的最新发展相结合,允许执行大型深度学习作业,这在过去由于资源限制而被禁止。
Picture by machinelearningmastery.com
那么……这是否意味着 DL 永远是解决任何机器学习问题的方法?不完全是。原因如下:
简单
神经网络模型的结果非常依赖于网络的结构和超参数。在大多数情况下,您需要一些网络架构方面的专业知识来正确地调整模型。在这方面也有一个重要的试错成分。
可解释性
正如我们前面看到的,许多用例不仅需要预测,还需要解释预测背后的原因:为什么贷款被拒绝?或为什么保险价格会上涨?虽然基于树和基于系数的算法直接考虑到了可解释性,但神经网络并非如此。在这篇文章中,介绍了一些解释深度学习模型的技术。
质量
根据我们的经验,对于大多数结构化数据集,神经网络模型的质量不一定比随机森林和 XGBoost 好。当涉及到非结构化数据时,即图像、文本或音频时,DL 实际上表现出色。底线:不要用猎枪打死一只苍蝇。像 Random Forest 和 XGBoost 这样的 ML 算法对于大多数结构化的监督问题来说已经足够了,并且更容易调整、运行和解释。让 DL 在非结构化数据问题或者强化学习中自己说话。
10。不要让数据泄露
在做一个预测航班到达延误的项目时,我意识到当我使用数据集中所有可用的特征时,我的模型突然达到了 99%的准确率。我悲哀地意识到我在用出发延迟作为到达延迟的预测器。这是一个典型的数据泄漏的例子,当用于创建模型的任何特征在预测时不可用或未知时,就会发生这种情况。小心,伙计们!
Photo by the Kini group.
11.开源给了我一切。为什么我需要一个平台?
构建机器学习模型从未如此简单。几行 R 或 Python 代码就足够了,网上有很多资源和教程甚至可以训练一个复杂的神经网络。现在,对于数据准备,Apache Spark 非常有用,甚至可以扩展到大型数据集。最后,像 docker 和 plumbr 这样的工具通过 HTTP 请求简化了机器学习模型的部署。因此,看起来人们可以完全使用开源栈来构建一个端到端的 ML 系统。对吗?
嗯,对于构建概念证明来说,这可能是真的。一个正在写论文的研究生肯定会受到开源软件的保护。然而,对于企业来说,情况有所不同。
不要误解我。我本人是开源的忠实粉丝,有许多奇妙的工具,但同时,也有相当多的差距。以下是企业选择数据科学平台的一些原因:
****a .开源集成:几分钟启动运行,支持多种环境,透明版本更新。
****b .协作:轻松共享数据集、数据连接、代码、模型、环境、部署。
****c .治理和安全:不仅针对数据,还针对所有分析资产。
d .模型管理、部署和再培训。
****f .模型偏差:检测并纠正因性别或年龄而产生偏差的模型。
****e .辅助数据管理:解决数据科学中最棘手任务的可视化工具。
****g . GPU:深度学习框架(如 TensorFlow)的最佳性能的即时供应和配置。
****h .无代码建模:针对统计人员、主题专家,甚至不编码但想可视化建模的高管。
寻找数据科学平台?考虑免费试用沃森工作室!
关于作者
scar D. Lara Yejas 是高级数据科学家,也是 IBM 机器学习中心的创始成员之一。他与世界上一些最大的企业密切合作,将 ML 应用于他们的特定用例,包括医疗保健、金融、制造、政府和零售。他还为 IBM 大数据产品组合做出了贡献,特别是在大规模机器学习领域,是 Apache Spark 和 Apache SystemML 的贡献者。
scar 拥有南佛罗里达大学的计算机科学和工程博士学位。他是《人类活动识别:使用可穿戴传感器和智能手机》一书的作者,并发表了大量关于大数据、机器学习、以人为中心的传感和组合优化的研究/技术论文。
机器学习:林肯领先于他的时代
Photo by Jp Valery on Unsplash
在第 45 届总统任期内,有很多关于什么是总统语言的讨论。但它并不总是“假新闻、“憎恨者和失败者、“科菲”美国有着悠久的总统语言遗产,机器学习可以帮助我们获得对这个非常具有历史意义的话题的新见解。
在过去的一个月左右的时间里,我一直在做一个项目,目的是利用数据科学来学习总统语言。在我到目前为止的探索中,我比较并跟踪了单词的用法,创建了总统的聚类,按总统对演讲摘录进行了分类,并根据上下文生成了缺失的单词。在这篇文章中,我想分享我根据单词选择对总统进行分类的发现。
我的完整数据集包括所有 44 位美国总统的所有官方演讲。总的来说,在 223 年的 945 次演讲中有将近 350 万个单词。(数据来源于弗吉尼亚大学米勒中心语法实验室的总统演讲语料库和总统演讲网站。)
我组织了一个数据框架,其中有 44 行,每行包含一个字符串,包含了每位总统所有演讲中的所有单词。由于聚类是一种无监督的学习方法,所以我剥离了标签的数据。从这一点出发,我对数据应用 CountVectorizer,对其进行缩放,然后将其输入 k-means 聚类模型。对于聚类模型,我选择 k=5 个聚类,这产生了最好的轮廓分数。
结果令人兴奋!该模型按时间顺序将总统分组。这一发现非同寻常,因为该模型的唯一输入是每位总统演讲中使用的词汇,而不是任何关于日期的信息。
在分类时间线中,每个分类都由单词选择最相关的总统组成,用不同的颜色表示。在左边,紫色集群包含开国元勋,在右边,蓝色集群包含现代总统。绿色聚类大致从一战到二战,橙色聚类包含从二战到几十年前的总统。红色星团的时间跨度最长,超过 100 年。
随着时间的推移,集群几乎完全不间断地运行——只有一个主要的例外:林肯。当他的绿色方块在红色的海洋中脱颖而出时,聚类模型断言林肯的用词选择使他从他那个时代的其他总统中脱颖而出。
林肯发表了一些美国最令人难忘的演讲,甚至机器学习也同意林肯走在了他的时代的前面!
要了解更多关于机器学习和总统语言的见解,请访问我的 GitHub 页面:
机器学习和总统语言:(1)用可视化和假设得出关于单词使用的结论…
github.com](https://github.com/ebpalmer17/capstone-presidential-language)
机器学习:让二进制注释不那么无聊
概观
对于一个大学项目,我正在开发一个基于 Spotify API 的音乐推荐分类器。广大的想法是根据用户个人喜欢或不喜欢的歌曲,根据歌曲的音乐成分(速度、调性、工具性等等),向用户推荐新的音乐。
数据集的准备通常是任何机器学习项目中最耗时的部分。这通常包括收集数据、清理数据、可选地标记数据、特征提取、将数据分成测试和训练数据。在本帖中,我们将讨论标签部分。
什么是标注(注解)?
标记或注释是评估单个数据点并为机器学习模型学习提供基础事实的行为。它主要用于监督机器学习应用。如果你有一个动物图片的数据集,你想让你的模型学会识别猫。然后你必须给所有的图片贴上相应的动物标签。如果只有两个可用的类,它被称为二元分类。例如,如果您有一个垃圾邮件过滤器模型,并且您想要决定它是垃圾邮件(1)还是垃圾邮件(0)。
永远不要低估正确标注数据集的重要性。如果你为你的机器学习算法提供的基本事实是错误的,你不能指望该算法胜过人类注释者。因此,您在注释过程早期犯的错误将会在以后的模型评估中被发现。
Annotation of a email dataset, weather it’s spam or not (ham)
Image labeling of a cute cat 😄
在我的例子中,我必须给我的数据集贴上标签,决定我是喜欢这首歌(1)还是不喜欢这首歌(0)。因此,我的数据集将由不同的特征(能量、可跳舞性等)组成。)和我手动赋给数据集的标签 (liked={True,False}) 。
The first 5 rows of my dataset containing the different features
应用程序
现在,为了让这个无聊的任务变得有趣一点,我开发了一个用于二进制分类的 android 应用程序。原因是我无法激励自己坐下来给最近听的歌曲贴上标签。有了这个应用程序,当我有一些空闲时间可以消磨的时候,比如我在排队,或者在公共交通工具上,我就可以给一些歌曲贴上标签。这不仅让它变得更有趣,而且效率更高,我能够在更短的时间内标记更大的数据集。
偷窃
那么它是如何工作的呢?首先,你必须用你的 Spotify 账户登录,然后应用程序会调出你最近听过的 30 首歌曲,并以卡片形式显示出来。从这一点来看,它与 Tinder非常相似如果你向左刷卡,你不喜欢这首歌,如果你向右刷卡,你喜欢它。如果你按下该卡,它将在你的手机上启动 Spotify 并播放歌曲(仅在安装了 Spotify 的情况下有效)。我提供这个功能是因为我总是忘记这首歌听起来是什么样的,所以我可以很快地检查一下。
此外,您还有一个概览,在这里您可以看到您滑动的歌曲,并通过点击相应的歌曲来更改歌曲的当前状态(喜欢或不喜欢)。
Swipe screen (LEFT) and the overview screen (RIGHT)
还有一个屏幕,你可以选择你的 Spotify 播放列表。向左滑动的歌曲将自动添加到您的播放列表中。我删除了这个功能,因为我不确定我是否想在应用程序中使用这个功能。现在它真正关注的是标签。
Spotify API
我使用 Spotify API,因为我认为他们对不同歌曲的音频分析非常准确,还因为我每天都使用 Spotify,觉得用它来玩真的很有趣。稍后在我的机器学习项目中,我将使用另一个名为 MusicBrainz 的音乐数据库。但是我会在另一篇文章中讨论这个问题。
要使用我的应用程序,你需要一个 Spotify 账户来登录,因为我们不能对 API 进行未授权的调用。此外,如果我们不能从你的帐户中取出你最后听的歌曲来滑动,这就没有意义了。
我认为这个 API 使用起来非常简单有趣。你真的可以摆弄数据库和音乐。
为了试验一下,我在我的应用程序中添加了一些额外的特性。如果您向右或向左推送,您可以自动将它们添加到播放列表(左)或资料库中您喜欢的歌曲(右)。因此,该应用程序还可以用来快速将歌曲添加到播放列表中,甚至通过概览屏幕删除它们。你可以在下面找到关于 Spotify API 的更多信息
音乐,遇见代码。简单和高级应用程序的强大 API、SDK 和小部件。
developer.spotify.com](https://developer.spotify.com/)
作为后端的 Firebase
现在,如果你刷一首歌,数据去了哪里?我使用 firebase 作为应用程序的后端,因为它非常简单,并且不需要很多时间来建立数据库。
A snippet of the firebase database structure I’m using
如果你不知道 Firebase 实时数据库,它基本上是一个 NoSQL 云数据库。数据存储为 JSON,并实时同步到每个连接的客户端。目前,我只保存最相关的数据,即 Spotify 曲目 ID、我是否喜欢它、我滑动歌曲的时间以及一些附加信息,如名称和在应用程序中显示的图像。否则,我不得不再次调用 Spotify API,我认为这样做会更有办法。
摘要
对我来说,这是一个有趣的小项目,让我更熟悉 Spotify API,我后来在我的机器学习项目中使用了它。
该应用程序可以进一步开发,使通用标签或二进制分类成为可能。目前,用例非常具体和狭窄。
此外,该应用程序可以开发成类似于 Spotify 播放列表添加应用程序的东西,在那里您可以操作您的播放列表,并快速将最近收听的歌曲添加到播放列表中。
这篇文章介绍了我在 Spotify API 上的标签应用。在下一篇博文中,我们将讨论技术问题,我将向您详细展示我是如何开发该应用程序的,以及应该避免的陷阱。
我没有在 Appstore 或其他地方发布应用程序,因为我认为对公众来说,用例太窄了。如果你有任何可以让更多人从中受益的用例的想法,我会考虑发表它。所以,如果你有任何想法让我知道。
此外,如果你愿意通过提供你自己的标记数据集来帮助我改进我的机器学习模型,并在应用程序完成后尽快获得个性化推荐。请与我联系,我很乐意向你发送申请,这样你就可以开始刷卡!
如果你想创建自己的分类应用,我的项目在我的 Github 上是公开的。放心用吧!
[## hyferion/SpotifyRecLabelingAndroid
这个应用程序是基于机器学习的应用程序的一部分,用于歌曲的分类和制作…
github.com](https://github.com/Hyferion/SpotifyRecLabelingAndroid)
机器学习营销——发展业务的 10 个应用
Photo by Franki Chamaki on Unsplash
机器学习和营销之间的关系在过去几年里蓬勃发展,催生了一系列优化这一过程的新策略和工具。现代营销人员别无选择,只能紧跟潮流,以保持竞争力,并在行业中保持理想的技能组合。
另一方面,我们都一直在寻求这种革命性的营销方式。“客户是业务的核心”是如此熟悉的一句话,现在我们终于可以通过利用机器学习来实现它。正如 Altimeter 首席分析师兼未来学家 Brian Solis 所说:
“人工智能和机器学习将对 2018 年的营销产生最深远的影响,因为它将从根本上让‘营销’更加人性化……这本身就很讽刺”。
通过跟踪和分析数据以推动客户参与,机器学习在市场营销中有许多应用。
1.预测客户终身价值
获得一个新客户的成本远远高于保持现有客户的满意度。如果营销人员想要在成本和结果之间取得平衡,明智的预算和努力分配是他们必须的。
使用 RFM(近期、频率和货币)分析,我们可以预测客户的终身价值,并关注那些将在未来带来最多收入的客户。
2.预测客户流失
客户流失预测与客户终身价值相关。预测分析使用关于客户行为的数据来预测客户是否会离开企业。这些信息对营销人员非常有用,因为他们可以在早期发现风险,并及时采取行动防止风险发生。
假设一个客户连续 6 个月每周访问你的网站,但是下个月他只访问一次,这可能导致他不再回来。如果你预料到了这一点,你可以向前迈出一步,提出一项新的交易,或者给他提供一些有价值的东西,如折扣或免费送货。
这为营销人员建立了一种积极的心态,帮助双方建立一种忠诚、值得信赖的关系。
3.改善客户旅程
过去,顾客体验是留给销售公司产品的人的。互动是一对一进行的。在数字时代,这种情况不再存在,也不可能满足每个对你的产品感兴趣的人的独特体验。
但是技术进步已经开始解决这个问题。我敢说,在理解客户需求并轻松引导他们完成购买之旅方面,机器学习算法甚至比人类做得更好。
由于自然语言处理,客户支持也有所改善。客户可以陈述他们的问题,机器学习技术将破译其含义,进一步向客户支持团队提供标准化的消息内容。快速有效地解决投诉是满足行业和客户需求的关键。
从所有接触点的无缝个性化导航到快速高效的客户支持,我们可以提高客户保留率并建立持久的忠诚度
4.线索评分
机器学习可以生成倾向模型,使用数据根据潜在客户的购买概率对其进行评分。这在处理许多销售线索时很方便,因为它节省了时间并提高了效率,使销售团队能够执行其他重要任务。
销售线索评分还有助于定义理想的买家角色。通过查看购买量最大的客户的个人资料,营销人员可以识别出未来需要关注的共同特征。
5.个性化
机器学习营销的主要目的是提供一个个性化的客户旅程,这是专门定制的,以在正确的时间满足个人需求。现场个性化,以及电子邮件和广告个性化,可以帮助你实现目标。
“没有个性化,我们就失去了相关性和速度”Marvin Chow——谷歌营销副总裁
通过机器学习支持的个性化,您可以预见客户在购买过程中的位置,并为他提供合适的内容。如果客户是你网站的常客,当你可以向他提供折扣或免费送货来建立忠诚度时,发送多余的内容是没有意义的。
6.产品推荐
向上销售和交叉销售可以通过使用机器学习来加速和优化产品推荐流程,从而提高参与度。通过预测需求和分析过去的客户行为,营销人员可以有针对性地提供更好的转换机会。
适当的产品推荐也有助于保持新鲜感,避免冗余。如果客户已经有一张信用卡,你为什么还要给他提供信用卡交易呢?因为他刚刚买了梦想中的房子,你可以为他提供房屋保险。
7.动态定价
打折还是不打折?这是许多营销人员迫切需要解决的问题。销售有时可能是王牌,但不断降价比完全不打折对公司利润的损害更大。
机器学习算法可以识别不需要打折就可以购买产品的人,以及那些可以利用这种推动最终进行购买的人。
使用动态定价可以最大限度地提高销售额,保持企业盈利。但是这种策略应该根据你的行业和客户来谨慎使用。
8.广告定位
对于营销人员来说,寻求广告优化是永无止境的。A/B 测试是顺利开展活动的基础,但它永远无法超越机器学习。通过不断学习和调整融合的数据分析是在购买生命周期中的正确时间接触正确受众的防弹策略。
9.营销自动化
自动化使营销人员能够建立工作流程并进行频繁的实验来优化流程。然而,这个过程需要大量的试验和错误,而没有真正解释形成结果的模式。
有了机器学习,你可以抛弃那个乏味的过程,让它基于对客户习惯的深刻洞察来运行测试。营销自动化通过这种方式变得更加强大。
10.理解和预测投资回报率
当客户体验和数据驱动的销售技巧成为你战略的一部分时,难怪营销投资回报率会增加。我们有许多公司以机器学习作为他们的强项来领导他们的行业的例子。
理解和预测投资回报率有助于你在公司内部建立一种数据驱动的文化,这从长远来看更有价值。
现在怎么办?
我们不能对机器学习在市场营销中的所有应用和好处视而不见。更高的准确性,更多的时间专注于创造性任务,更多的数据需要利用。
统计数据摆在那里,人们对此深信不疑,世界各地的公司都在为一流的客户体验和飞速增长的销售额做准备。
机器学习是拼图中缺失的一块。现在是时候退一步,放眼全局,开始为成功制定战略了。
利用机器学习识别陨石中的矿物
上周末,美国自然历史博物馆(AMNH)举办了第五届年度黑客马拉松。今年的主题是“黑掉太阳系”我的团队致力于一个项目,以确定和绘制陨石的矿物成分。
了解陨石的矿物成分可以让我们了解太阳系。当它们来自行星际天体(如小行星)时,我们可以了解 45 亿年前太阳系是如何形成的。陨石甚至可以来自其他星球,这给了我们一种从几百万公里外研究它们的方法。
化学 101
原子是构成物质的微小物体。原子由中心的质子和中子组成,周围是电子。原子核中质子的数量决定了那个原子是什么 T2 元素。比如最轻的元素氢,有 1 个质子;氧有 8 个,铁有 26 个。
分子由多个原子结合在一起组成。例如,一个水分子由两个氢原子和一个氧原子组成。这可以写成 H₂O.的化学式
矿物是一组固体分子,如钻石、石英或黄玉。原子可以以无数种方式聚集在一起,形成非常不同的矿物。已知的元素只有 118 种,但它们合在一起构成了 3800 种矿物。
有些矿物配方可能相当复杂,例如黄玉:al₂sio₄(oh,f)₂——2 个铝、1 个硅、4 个氧和 2 个氧+氢或 2 个氟。而其他人的公式可能非常简单。钻石的分子式是 C——仅仅是碳。但是,原子的结构也很重要。钻石和石墨(你铅笔里的东西)都是由碳组成的,但它们如此不同是因为碳原子以不同的方式结合。
The chemical structure of diamonds vs graphite. (http://www.jidonline.com/viewimage.asp?img=JInterdiscipDentistry_2011_1_2_93_85026_f3.jpg)
陨石是如何被研究的
科学家使用电子微探针(EMP)扫描陨石。电磁脉冲向陨石发射一束电子。当电子束与陨石中的原子碰撞时,原子会发出 x 射线。每个元件具有不同的特征频率。
A graph of characteristic frequencies of different elements. (https://commons.wikimedia.org/wiki/File:XRFScan.jpg)
在开始扫描之前,科学家们设置电磁脉冲来检测一组特定的元素。当所需元素的特征 x 射线发射时,探测器记录强度。EMP 产生一系列灰度图像,每个元素一个,其中每个像素代表该元素在该位置的比例。
The 10 images produced by the EMP when scanning a meteorite for 10 different elements. Brighter means that more of that element is present at that location. The 10 elements are: Aluminum (Al), Calcium (Ca), Chromium (Cr), Iron (Fe), Magnesium (Mg), Nickel (Ni), Phosphorus (P), Silicon (Si), Sulfur (S) and Titanium (Ti).
这可以告诉我们存在什么元素。但是我们如何确定矿物质呢?
来自不同元素的 x 射线的相对强度对应于该元素在不同矿物中的相对比例。一种元素存在的越多,撞击该元素原子的电子就越多,从而发射出特有的 x 射线。例如,矿物硫铁矿大约 2/3 是铁,1/3 是硫,这意味着我们预计发射的 x 射线的 2/3 是铁的 x 射线特征,1/3 是硫的特征。
但是有几个问题使这变得困难。首先,结果可能非常嘈杂,这意味着 EMP 很少会给出与矿物中理论元素比例相匹配的结果。第二,每个元件的传感器的比例不同。例如,铁读数 400 可能意味着 50%的铁,而硫读数 200 可能意味着 100%的硫。
为了控制这些,陨石和“标准”一起被扫描。标准是已知的矿物,被扫描以了解电磁脉冲的行为。我们有 8 种标准矿物,排列成 4x2 网格,如下图所示。每个方块都标有放在那里的已知矿物。顶部是铁(Fe)扫描的图像,中间是硫(S)扫描的图像,底部是镍(Ni)扫描的图像。
Scans from 3 of the 10 elements for the known standard minerals. Each square is the labeled with the known mineral that was placed there. The top is the image from the iron (Fe) scan, the middle is from the sulfur (S) scan and the bottom from the nickle (Ni) scan. *SCOlv stands for San Carlos Olivine, which doesn’t have one distinct chemical formula.
这应该给你一种感觉,我们如何从矿物的组成元素中找出矿物。例如,只有铁的正方形在铁扫描中是亮的,而在其余时间是暗的,这表明那里只存在铁。Fe₃O4 和 FeS 在 Fe 扫描中看起来都很相似,但是 FeS 在 s 扫描中也会变亮。同样,FeS 和 NiS 在 S 扫描中看起来相似,但是 Ni 扫描可以帮助区分它们。还要注意图像中的所有斑点。即使我们正在扫描已知的矿物,他们也不会给出完全一致的读数。当我们试图识别陨石中的未知矿物时,我们必须记住这一点。
机器学习
现在我们有了尝试解决这个问题所需的所有要素。概括地说,我们的最终目标是识别陨石内部的矿物。为了做到这一点,我们在电子探针中扫描陨石,这可以告诉我们陨石中每个位置的元素的相对比例。与此同时,我们扫描了一组称为标准的已知矿物,这样我们就可以正确地解释电磁脉冲的结果。
我的目标是为我们的陨石中的不明矿物创建一个分类器,但是到目前为止,我们只有标记为的数据作为标准。我们不能直接从标准中建立一个分类器,因为如果陨石含有标准中没有的矿物,我们就不能对它进行正确的分类。但是,如果我们猜测陨石中可能有什么矿物,我们可以模拟这些矿物(目标矿物),并在此基础上建立一个分类器。这些标准可以帮助我们进行模拟。
第一步是使用标准来找到将元素的重量比例转换成 EMP 强度的系数。我们期望重量比例和强度之间的线性关系。例如,如果一种矿物含有 50%的铁,我们预计其强度是含有 25%铁的矿物的两倍。这意味着我们可以使用线性回归来找到系数。
下面显示了每个元素的回归结果。每个蓝色斑点来自不同的标准。理论上,每个蓝色斑点应该是一个点,但由于读数中的噪声,它们被拉长了。即使有噪声,你也可以看到一个相当清晰的线性关系。但是,在预期比例接近的情况下,例如在 Fe 图中,事情可能是不明确的。
The linear regression results for each element. The x-axis is the intensity from the EMP results and the y-axis is the theoretical weight-proportion of that element in the mineral.
我可以用这些结果来模拟我们要找的目标矿物。为了模拟一种矿物,我们计算每种矿物元素的理论重量比例,使用回归结果将它们转换为预期强度,并根据我们在标准中发现的噪声添加随机噪声。
我对每种目标矿物模拟了 10,000 次,并将样本分成 80%的训练集/20%的测试集。我在训练集上训练了一个随机森林分类器,得到的模型在测试集上达到了 96.8%的准确率。
结果
将该模型应用于陨石扫描,结果如下:
The predicted mineral composition of a meteorite. Each color represents a different mineral.
在第二颗陨石中:
The predicted mineral composition of a meteorite. Each color represents a different mineral.
我们没有这些陨石的地面真相,所以我们不知道它有多准确。但是和我们一起工作的科学家说最初的结果是有希望的!
结论和后续步骤
这种方法的一个大问题是,它要求科学家提前知道他们在寻找什么矿物。因此,它在识别已知-未知方面似乎很有前途,但会对未知-未知给出错误的分类。
我的团队采用的另一种识别矿物的方法是用 DBSCAN 进行无监督聚类。它不会告诉你具体是什么矿物,但它可以告诉你陨石中有类似元素成分的矿物,可能代表一种独特的矿物。我们认为可能有一种方法可以将这些方法结合起来,两全其美。
我们正在继续这项工作,并希望它不仅仅是一个有趣的黑客马拉松项目,并且成为科学家工具箱中有用的一部分。
我们所有的代码都可以在github上找到。我们仍在努力,所以事情可能会有所改变。
本页更详细的描述了原挑战:https://github . com/amnh/HackTheSolarSystem/wiki/陨石-矿物-测绘
团队的其他成员包括:凯蒂·艾伯特、梅雷特·戈特舍、彼得·康、、塞西娜·巴比奇·莫罗和约翰·安德伍德。塞缪尔·阿尔珀特和玛丽娜·杰玛给了我们建议。感谢 Abigail Pope-Brooks 编辑这篇文章。
Cecina 还写了一篇关于周末的 博文 。
用 C++部署机器学习模型
最近,我着迷于构建一个数学化的应用程序,并在没有任何模型大小、平台或 api 调用需求限制的情况下大规模部署它,这将是多么有趣。我知道 Python 有足够的库来处理机器学习项目的原型,但是没有多少人在谈论扩展这个项目,尤其是当你不想通过 web api 来做这件事的时候。
我相信真正的智能不应该仅仅依赖于对 api 的调用来实现模型的规模化。这种魅力让我开始研究如何将 C++用于机器学习和一般智能。
我坚信 Matlab 和 Python 的数学优势都是基于底层的 c/c++代码。因此,从根本上扩展技术以处理机器学习中涉及的数学计算,并考虑一个极快的场景,可能需要您能够深入研究低级编程,尤其是 c/c++。
此外,我想知道为什么大多数计算机科学学校确保他们的课程中有 c/c++课程。这强调了将 c/c++用于可伸缩技术的理由。
在使用 Udemy 动手课程学习 c++之后,现在的挑战是在 android 中集成一个简单的人脸识别应用程序。
这篇文章将包括构建 c++项目和在 android 或任何其他操作系统环境中部署所需的一些初步方法。
组件:
- 用 opencv 建立一个机器学习的 c++项目。
- 学习主成分分析生成特征脸
- 为多平台部署设置. so 推理库
- 为推理库开发 jni 包装器。
- 使用 Android 或任何 java 代码中的库。
第一部分将是用 OpenCV 学习一个机器学习算法。在这种情况下,我们将探索最基本的人脸识别算法,使用主成分分析的特征脸。机器学习社区非常熟悉 python 中的这一点,特别是使用 sci-kit learn 等工具,但是当生产,尤其是离线/设备上生产出现在脑海中时,从不同的维度进行这一工作的需求是有利的。
OpenCV 提供了一个非常好的学习主成分分析的 api,一旦设置好数据,学习起来非常简单。
以下是步骤:
使用 OpenCV 建立一个 cmake 项目 c++。
您的 CMakeFile.txt 的关键部分是确保 0 项目中有一个 OpenCV 库,并且可供您的库编译。理想情况下,在请求 Cmake 为您查找 OpenCV 之前,在您的机器上安装 OpenCV 库是很重要的。
find_package(OpenCV REQUIRED)include_directories(${OpenCV_INCLUDE_DIRS})set(LIBS ${OpenCV_LIBS})target_link_libraries(featureCalculation ${LIBS})
PS:为了训练和推断,我不得不设置不同的 cmake。我将分享这两个
学习主成分分析。
既然 OpenCV 已经可用,学习 PCA 就相当简单了。逻辑是这样的:
读取所有图像数据作为数组。 使用 OpenCV 中的 cv::glob ,所有文件名都以 结尾。jpg,。png 或/和。用 cv::imread 可以读取 jpeg ,可以进行图像数据的数据预处理。
农作物面孔。 这很重要,因为PCA 对人脸图像比对整幅图像做得好得多。我发现多任务级联卷积网络(MTCNN) 是最可靠、最简单、最小的人脸检测和裁剪模型。在 C++中有一个使用 OpenCV 中的 Caffe 网络的原始模型的实现。
将裁剪后的面转换成灰度。 这部分挺直截了当的。使用cv::CVT COLOR(originalimagemat,grayscaleimagematcontainer,cv::COLOR_BGR2GRAY) 我们可以在 OpenCV 中将原始的 BGR 图像转换成灰度。
其他预处理 —另一个预处理是确保数据类型正确。这非常重要,因为 C++非常注重数据类型的精度。在这一点上很容易引入错误,因此要小心确保数据类型是正确的。除此之外,这是一个好主意,规范化您的图像数据和调整所有图像到一个一致的形状。只有当数据在同一维度时,PCA 才起作用。在 OpenCV 中,我们可以使用以下函数来处理预处理:
CV::resize(original image,containermatofnewimage,size) 用于调整图像大小original mat::convertTo(newmatnormalize,CV_32FC3,1/255.0) 用于归一化图像的像素值。
将所有图像转换成数据表 —数据表有点像单个数据表,其中每个元素都表示为一行,有趣的是,我们可以将数据表中的每一行都视为扁平格式的独立图像。PCA 的本质是将图像值投影到具有该图像的独特表示的几列。因此,数据表将具有等于训练数据集中图像数量的行,而列将是每个图像的归一化灰度值。
为了创建数据表, std::vector 可用于保存所有图像(希望它们适合内存),然后将其复制到数据矩阵的每一行。这是一个帮助器函数,它从一个矢量图像 mat 中完成这个任务。
**cv::Mat** **createdatamatrix**(std::vector<cv::Mat> imageArray) {
cv::Mat datamatrix(static_cast<int>(imageArray.size()), imageArray[0].rows * imageArray[0].cols, CV_32F);
unsigned int i;
*for*(i=0; i < imageArray.size(); i++) {
cv::Mat imageRow = imageArray[i].clone().reshape(1, 1);
cv::Mat rowIData = datamatrix.row(i);
imageRow.copyTo(rowIData);
}
***return*** datamatrix;
}
cv::reshape() 帮助将 mat 数组变换成不同的形状,用 (1,1) 字面意思是我们希望数据存在一行中。
学习实际主成分分析算法。 现在我们已经用预处理的人脸图像创建了数据表,学习 PCA 模型通常是顺利的。就像把数据表传递给一个 OpenCV pca 实例一样流畅,带有你期望的最大组件像这样cv::PCA PCA PCA(datatable,cv::Mat(),cv::PCA::DATA_AS_ROW,number_of_components) 。这样,我们就有了一个用 C++编写的学习过的 PCA,可以用于生产了。
为了将该模型转移到任何环境中使用,open cv 有一个 文件存储 对象,允许您按原样保存垫子。因此,我可以保存这个文件,并通过 jni for OpenCV 传递其文件名,以重新创建用于推理的模型实例。为模特服务就是这么简单。
为了结束本文的推理部分,我将简单地展示如何使用 OpenCV 编写 mat 对象。最终,保存的模型中的值会以 YAML 文件或 XML 的形式输出,这取决于用户最喜欢的选择。
保存 pca 模型对象,用于生产环境上的推理。 pca 对象中确切需要保存的是经过训练的 PCA 的均值和特征向量,有时也保存特征值可能是个好主意,以防您想要构造自己的特征脸投影,但是 OpenCV 已经实现了一个 pca- >项目 实例,它有助于推理和特征脸生成。在任何情况下,以下是如何保存您的模型:
**void Facepca::savemodel**(cv::PCA pcaModel, const std::stringfilename)
{
cv::FileStorage fs(filename,cv::FileStorage::WRITE);
fs << “mean” << pcaModel.mean;
fs << “e_vectors” << pcaModel.eigenvectors;
fs << “e_values” << pcaModel.eigenvalues;
fs.release();
}
推理层
保存模型后,推理层将包括加载保存的模型,该模型的值也通过 OpenCV 存储在 yml 文件中,并被开发以形成具有必要数据预处理模块的推理引擎,该推理引擎最终被捆绑为用于在基于 linux 的环境上部署的. so 文件。对于其他平台,cpp 代码可以被编译为分别用于 windows 和 mac 的 dll 或 dylib 。
因为我们更关心在 android 应用程序上部署模型,所以重点将是构建 。所以 文件推理机从我们保存的模型中。
建筑。so 推理库
加载 PCA 模型 为了推理,我们让 OpenCV 从保存的 中加载已有的模型文件。yml 文件,之后我们将特征值、特征向量和均值输入到一个新的 PCA 对象中,然后我们可以调用一个 pca- >项目 来创建一个新图像的投影。
下面是加载保存的 OpenCV 文件存储模型的示例代码。
cv::PCA **newPcaModel**;
cv::PCA **loadmodel**(cv::PCA newPcaModel, const std::string filename){
cv::FileStorage fs(filename,cv::FileStorage::READ);
fs[“mean”] >> newPcaModel.mean ;
fs[“e_vectors”] >> newPcaModel.eigenvectors ;
fs[“e_values”] >> newPcaModel.eigenvalues ;
fs.release();
***return*** newPcaModel;
}
**loadmodel**(newPcaModel, “path-to-saved-yml-file”);
一旦模型被加载, newPcaModel 对象现在包含从现有训练参数保存的模型,即 pca 特征值、特征向量和均值。因此,当完成面部投影时,可以保证返回的数据与训练数据集相关。
创建新的图像预处理和预测阶段。 在机器学习模型的推断过程中,重要的是输入图像也要经过与训练数据集相同的预处理。
可以使用几种方法将图像传递给推理引擎,可能是从磁盘加载图像,也可能是将图像作为 base64 字符串传递。
在我们的例子中,可能的方法是使用 base64 字符串,因为我们也考虑了两个因素,一个是 jni 将被暴露,另一个是我们的最终库是用于 android 应用程序的。
记住这一点,然后我们需要确保库能够从 base64 字符串中检索图像并将其发送到 OpenCV。
在 c++中解码一个 base64 字符串是非常重要的,然而,读者可以参考这个链接中的代码片段。
一旦 base64 图像字符串被解码,我们就将该字符串转换成一个由 无符号字符(uchar) 组成的向量,它可以被认为是图像值。
OpenCV 可以使用函数调用cv::im decode(vectorUchar,flag) 将 uchar 的矢量解码成图像。这个过程返回一个 Mat 图像,用它可以做进一步的预处理。
然后,图像可以通过以下预处理阶段:
- 人脸提取
- 将裁剪面转换为灰度。
- 图像大小调整
- 图像标准化
- 创建数据矩阵
正如本文上面的培训部分所述。
对新图像进行推理的最后一步是使用加载的 pca 对象在新图像中创建人脸的投影。
这样做的代码片段将如下所示:
newPcaModel->project(datamatrix.row(0));
当你用一个加载的 pca 对象在两个面上投影,并使用距离度量(如欧几里德距离或余弦相似度)比较投影(特征面)时,识别或验证部分发生。
为推理库开发 jni 包装器
用一个暴露的 jni 打包这个库。 这一部分非常简单,一旦推理代码被适当地结构化,很可能是在一个类中,那么 jni 主体就可以直接调用暴露的函数来进行模型加载、预处理和预测。
然而,要创建一个 jni,理解 java 中的链接是如何发生的是很重要的。
第一种方法是创建一个 java 类和您希望在 Java 类中使用的带有输入参数的函数。
这将是 jni 在创建 cpp 代码时使用的函数名。Java 中方法的类路径名与 cpp 中的类路径名之间的一致性非常重要。
让我们假设我们将用于 pca 特征匹配的方法被命名为matchpcafeatures(),然后我们的 java 类可以看起来像这样。
package org.example.codeclass MatchFeatures {static float matchpcafeatures(modelfilename: String, image: String, projectionToCompare: Array[Float])}
有了上面的 java 类和方法,我们的 jni 头文件看起来会像这样。
*#include* <jni.h>*/* Header for class com_example_code_MatchFeatures */
#ifndef* _Included_com_example_code_MatchFeatures
*#define* _Included_com_example_code_MatchFeatures*#ifdef* __cplusplus
extern “C” {
*#endif*JNIEXPORT jfloat JNICALL Java_com_example_code_MatchFeatures_matchpcafeatures
(JNIEnv *, jobject, jstring, jstring, jfloatArray);*#ifdef* __cplusplus
}
*#endif
#endif*
你还不需要担心 extern C 的细节,重点是 jni 头文件中方法的名称。
接下来,我们将看看如何使用上面的 java 代码进行推理。让我们首先为这个方法开发 jni 桥。
jni 头的最后 3 个参数与 java 方法中的参数完全相同,位置也完全相同。
因此,我们将对这些参数进行处理,因为它们是客户对我们的 c++推理引擎的关键要求。
下面展示了如何连接这些输入参数并返回一个值,java 代码可以接受这个值并继续它的其他进程。
*/**
* Match features of pca
* */*JNIEXPORT jfloat JNICALL Java_com_seamfix_qrcode_FaceFeatures_matchpcafeatures
(JNIEnv * env, jobject obj, jstring pcafilename, jstring imagestring, jfloatArray projectionToCompare){ const char *pcastring_char;
pcastring_char = env->GetStringUTFChars(pcafilename, 0);
*if*(pcastring_char == NULL) {
*return* 0.0f;
} const char *imagestring_char;
imagestring_char = env->GetStringUTFChars(imagestring, 0);
*if*(imagestring_char == NULL) {
*return* 0.0f;
} *//Get file name string as a string for cpp* std::string stdfilename(pcastring_char);
cv::PCA pca; *//Class InferencPca holds the preprocesing and inference methods* InferencePca ef;
std::vector<cv::Mat> imagevec; *//Get image as base64* cv::Mat image = ef.readBase64Image(imagestring_char);
ef.loadmodel(pca, stdfilename);
imagevec.push_back(image); cv::Mat datamatrix = ef.createdatamatrix(imagevec);
cv::Mat projection = ef.project(datamatrix.row(0)); *//Load the existing vector.* std::vector<float> initialProjectionPoints; *//Load existing features -- needed to do comparison of faces* jsize intArrayLen = env->GetArrayLength(existingfeatures);
jfloat *pointvecBody =
env->GetFloatArrayElements(existingfeatures, 0); *for* (int i =0; i < intArrayLen; i++) {
initialProjectionPoints.push_back(pointvecBody[i]);
} std::vector<float> newProjectionpoints =
ef.matToVector(projection);
float comparisonScores =
ef.compareProjections(newProjectionpoints,
initialProjectionPoints); env->ReleaseFloatArrayElements(existingfeatures, pointvecBody, 0);
env->ReleaseStringUTFChars(pcafilename, pcastring_char);***return*** comparisonScores;}
有了这个,我们就着手打造我们的 。于是库和库成功地释放给 java 代码使用。cmakelists . txt中说明了构建库的协议。
它看起来像下面这样:
find_package(JNI REQUIRED)*#Include jni directories* include_directories(${JNI_INCLUDE_DIRS})
file (GLOB_RECURSE SOURCE_FILE src/*.h src/*.cpp)set(LIBS ${JNI_LIBRARIES})
add_library(matchprojection SHARED ${SOURCE_FILE})target_link_libraries(matchprojection ${LIBS})
构建项目应该生成一个lib-match projection . so文件,该文件可以添加到您的 java 项目中。
然而,对于 android 来说,这有点棘手,因为构建工具不同于官方的 cmake 构建工具链,Android 有自己的本地 cpp 代码构建工具。这叫做【NDK】【原生开发套件】。这将用于为生成的 构建 c++原生代码。所以 要兼容安卓。
建筑。所以使用 NDK 的安卓系统的 将会是一个完整的教程,所以我现在跳过它。
但是一般来说,一旦使用 NDK 完成构建,您将拥有相同的lib-match projection . so可以在您的 android 应用程序中使用。
使用。Android 应用程序中的库。
在 Android 应用程序中使用生成的库就像在任何 java 应用程序中使用它一样。
其思想是加载本地库,然后用所需的参数调用最初创建的类中对应于本地 jni 方法的方法。
要在包括 android 在内的任何 java 程序中加载该库,请确保 。所以 库是在你的程序的类路径中,有的会把它放在一个名为 lib 或者 jniLibs 的文件夹下。这样我就可以使用函数调用来加载库,如下所示:
System.loads(“native-lib”)
最后,我可以用必要的参数调用前面创建的方法,然后本机代码可以为我执行。
MatchFeatures mf = *new* MatchFeatures();float matchscores = mf.matchpcafeatures(storedpacfilepath, imagebase64string, anotherimageprojectionarray);
如果您仔细观察,就会发现该方法被声明为 native,并且该方法没有主体,这是因为程序知道有一个用该类路径名定义的 native cpp 方法。
结论:
这种方法是在 java 环境中构建和部署包含本机代码的项目的基本方法。此外,最复杂的算法问题,包括机器学习和核心计算机视觉项目,可以很容易地在 cpp most 中推理,因为它很快,而且有现成的库。
甚至 TensorFlow 也有一个在 c++中加载深度学习模型以及在 c++中使用其 tflite 模型的 api。
因此,我认为这种使用本机代码构建推理引擎的方法是一种构建强大的生产就绪型引擎的方法,这种引擎将利用高精度数学,尤其是将机器学习模型部署到各种环境,尤其是离线环境中的 android 环境。
我在 Seamfix Nigeria Ltd .担任数据科学家和机器学习工程师,我的工作重点是确保数据科学功能最终应用于生产。
Docker 中作为微服务的机器学习模型
机器学习开发中最大的被低估的挑战之一是在生产中以可扩展的方式部署训练好的模型。我读过的一个关于它的笑话是“如今机器学习最常见的部署方式是 powerpoint 幻灯片:)”。
为什么是 Docker?
Docker 是一个容器化平台,它将一个应用程序&及其所有依赖项打包到一个容器中。
激活该容器导致应用程序被激活。
当你有一大堆以隔离方式工作的服务,并作为 web 应用程序的数据提供者时,就使用 Docker。根据负载情况,可以根据设置的规则按需剥离实例。
为什么要用 Docker 做机器学习模型?
常规软件应用程序的生产部署非常困难。如果那个软件是机器学习管道,那就更糟糕了!在今天的情况下,你无法摆脱机器学习,因为这是你在业务中可以获得的最大竞争优势。在生产中,一个机器学习驱动的应用程序可能会出于多种目的使用多个模型。可以通过 docker 处理的机器学习模型部署中的一些主要实际挑战有:
- 不同型号的环境不一致。
有些情况下,对于一个模型,您需要将 LANG_LEVEL 设置为“c ”,而对于另一个模型,LANG_LEVEL 应该为“en_us”。UTF 8 英尺高。将不同的模型放入不同的容器中,以便获得不同模型的隔离环境。
2。模型间不一致的库需求。
您已经使用 tensorflow 1.10 开发了一个文本摘要器。现在我们想用 tensorflow2.0 支持的迁移学习进行情感分析(假设)。将它们放在不同的容器中不会破坏应用程序。
另一个主要的用例是,你用 python 开发 ML 模型。但是你想用 Go 语言做的应用(为了一些技术优势),那么通过 docker 把 ml 模型暴露给 app 就解决了。
3。不同型号的资源需求不一致。
你有一个非常复杂的对象检测模型,需要 GPU,你有 5 个不同的神经网络,用于其他目的,适合在 CPU 上运行。然后在容器中部署模型时,您可以根据需求灵活地分配资源。
4。跨模型的不一致流量。
假设您有一个问题标识符模型和答案生成模式,前者调用频繁,而后者调用不频繁。那么你需要比答案生成器更多的问题标识符实例。这可以由 docker 轻松处理。
另一个场景是,上午 10 点你的模型有 10000 个请求,而晚上 8 点只有 100 个。因此,您需要根据您的需求剥离更多的服务实例,这在 docker 中更容易。
5。模型级缩放
假设你有一个每秒处理 100000 个请求的统计模型,而一个每秒能够处理 100 个请求的深度学习模型。那么对于 10000 个请求,你只需要纵向扩展深度学习模型。这可以由 docker 来完成。
现在让我们看看如何创建深度学习模型的容器。在这里,我建立的模型是在 http://cogcomp.org/Data/QA/QC/的可用的问题分类器数据集上的问题主题标识符。Google 的通用句子编码器用于单词嵌入。
为模型创建容器时,通常必须遵循的工作流程是:
- 建立和训练模型。
- 创建模型的 API。(这里我们把它放在一个 flask API 中)。
- 创建包含所有必需库的需求文件。
- 使用必要的环境设置和启动操作创建 docker 文件。
- 建立 docker 形象。
- 现在运行容器,并在完成后跳舞:)
[## sambit 9238/QuestionTopicAnalysis
发现问题主题在各种用例中起着重要的作用,从问答系统到回答…
github.com](https://github.com/sambit9238/QuestionTopicAnalysis)
建立并训练模型。
为了建立和训练模型,基本的工作流程是获取数据,对数据进行清理和处理,然后将数据提供给模型架构,以获得训练好的模型。
例如,我在 http://cogcomp.org/Data/QA/QC/的 TREC 数据集上建立了一个问题意图分类器模型。训练数据有 6 个意图,每个意图的实例数如下:
Counter({'DESC': 1162,
'ENTY': 1250,
'ABBR': 86,
'HUM': 1223,
'NUM': 896,
'LOC': 835})
可以在https://github . com/sambit 9238/QuestionTopicAnalysis/blob/master/question _ topic . ipynb查看模型创建
这里遵循的处理步骤是:
- 处理宫缩就像我会,我已经等。
- 处理超链接、邮件地址等。
- 处理数字和身份证。
- 处理标点符号。
对于嵌入,使用了来自 tensorflow-hub 的 Google 通用句子编码器。
遵循的模型结构是具有两个隐藏层的神经网络,每个隐藏层具有 256 个神经元。为了避免过度拟合,使用 L2 正则化。
Layer (type) Output Shape Param #
=================================================================
input_1 (InputLayer) (None, 1) 0
_________________________________________________________________
lambda_1 (Lambda) (None, 512) 0
_________________________________________________________________
dense_1 (Dense) (None, 256) 131328
_________________________________________________________________
dense_2 (Dense) (None, 256) 65792
_________________________________________________________________
dense_3 (Dense) (None, 6) 1542
=================================================================
Total params: 198,662
Trainable params: 198,662
Non-trainable params: 0
_________________________________
该模型存储在. h5 文件中以供重用。标签编码器存储在 pickle 文件中以供重用。
创建模型的 API。(这里我们把它放在一个 flask API 中)。
存储的模型放在 Flask api 中,以便可以在生产中使用(https://github . com/sambit 9238/QuestionTopicAnalysis/blob/master/docker _ question _ topic/app . py)。)
API 需要一个文本列表,因为在实时使用时会出现多个句子。它经过清洗和处理后被送入预测系统。预测结果被缩放以表示每个意图的置信度百分比。然后,缩放后的结果以 JSON 格式发送。
举个例子,
输入:【“你工资多少?”]
输出:{'ABBR': 0.0012655753,' DESC': 0.0079659065,' ENTY': 0.011016952,'哼':0.028764706,' LOC': 0.013653239,' NUM': 0.93733364}
这意味着模型有 93%的把握认为这个问题的答案应该是一个数字。
创建包含所有所需库的需求文件。
为了创建 Docker 映像来服务我们的 API,我们需要创建一个需求文件,其中包含所有使用过的库及其版本。
创建具有必要环境设置和启动操作的 Dockerfile 文件。
一个 Dockerfile 是一个文本文档,它包含用户可以在命令行上调用的所有命令来组合一个图像。
对于我们的示例,预构建的 python-3.6 映像被用作基础映像。然后,已经下载了预先训练的通用语句编码器模型文件,随后安装了所需的库。docker 的 5000 端口是公开的,这是 flask app 在默认配置下运行的端口。
打造 docker 形象。并运行容器
现在我们在一个目录中有了 Dockerfile、flask API 和经过训练的模型文件。因此,我们需要从中创建 docker 图像。该命令可以是:
docker build -t question_topic .
#the last option is location of the directory. Since I am in the directory so '.' is put, which represents current directory in unix.
现在 docker 映像已经创建,我们需要在容器docker run -p 8888:5000 --name question_topic question_topic
中运行该映像
它将使创建的 docker 映像运行。docker 中的端口 5000 映射到主机的 8888 端口。因此,API 将在端口 8888 接收和响应请求。如果您想在后台运行 docker 并将其从命令提示符中分离出来(这将是实时的情况),请使用'-d '选项运行它。
为了检查 docker 的输出,让我们使用 curl 发送一个 post 请求。
输入:
为了提供输入,curl—request POST
—URLhttp://0 . 0 . 0 . 0:8888/predict _ topic
—header ' content-type:application/JSON '
—data ' { " raw text _ list ":["您现在在哪里工作?",“你的工资是多少?”]}'
输出:
{
" input": "['你现在在哪里工作?',‘你的工资是多少?’]",
“output”:“[{ ' ABBR ':0.0033528977,' DESC': 0.0013749895,' ENTY': 0.0068545835,'哼':0.7283039,' LOC': 0.25804028,' NUM': 0.0020733867},
{'ABBR': 0.0012655753,' DESC': 0.0079659065,' ENTY': 0.011016952,'哼':0.028764706,' LOC': 0.013653239,' NUM': 0.93733364} ]"
}
看来 docker 运行良好:)
备注:
提到的例子还没有准备好投入生产。但是,通过以下几个步骤,它就可以投入生产了:
- 在模型级别,可以进行更多的处理和模型超参数调整,以使模型更好。
- 在 API 级别,不需要在每次请求时初始化会话和变量。通过大幅缩短 API 的响应时间,可以在应用启动时完成一次。
- 在 docker 级别,Docker 文件没有优化,因此 Docker 映像在大小上可能比要求的要大。
深度学习—模型优化和压缩:简化
看看最先进的机器学习模型的压缩、修剪和量化领域
这是什么?
我们周围的世界充满了神经网络和深度学习模型,它们在创造奇迹!!但是这些模型既计算量大又耗能。如此昂贵,以至于人们已经开始要求 AI/ML 对他们的碳排放负责,数字 不好看!!
[## 训练一个人工智能模型在它们的一生中可以排放相当于五辆汽车的碳
人工智能行业经常被比作石油行业:一旦被开采和提炼,数据就像石油一样,可以…
更多研究人员转向模型压缩的另一个主要原因是在硬件资源有限的系统上部署这些模型的困难。虽然这些模型已经成功地成为头条新闻并实现了非凡的性能,但它们需要昂贵的高速 GPU 的支持才能工作,这限制了它们的应用。
能够压缩这些高度复杂的模型,将它们传输到硬件设备,并结束它们对巨大计算资源的依赖,是该领域的主要目标之一。这些进步可以帮助我们将人工智能融入到我们周围的每个小型嵌入式系统中。
为什么不直接用 GPU 服务器?
是的当然!!随着像谷歌和亚马逊这样的互联网巨头提供在线计算服务,人们确实想知道进行远程计算是否是一条出路。虽然人们已经开始像使用拐杖一样使用这些云服务进行繁重的计算,但它也带来了自己的一系列问题。
云计算的一个主要问题是网络连接。该系统需要一直在线才能顺利工作。但是这并不总是能够保证的,因此在本地进行计算对于不能承受任何网络延迟的系统来说是极其重要的。
使用这些云服务的另一个问题是牺牲“空气间隙”。“空气间隙”是一个技术术语,用来表示没有连接到互联网的系统,因此无法被远程攻破。访问这些配置中的数据需要通过物理方式完成,不可能完成的任务风格!!😛
对于极度保护隐私和安全的系统来说,放弃这种“空气间隙”是不理想的,因此他们更喜欢本地计算而不是云服务。
但这些都不会影响到我!!
这是大多数 ML 社区相信的,但不是真的!!如果您是 ML 的初学者,希望开发最先进的模型,并且不受处理能力的限制,那么您可能会认为高度复杂和深度的模型总是最佳选择。
但这是一个巨大的误解。高度复杂和深度的模型不能保证性能。更不用说,这些模型可能需要几个小时甚至几天的训练时间(即使是在 GPU 上)。对修剪和量化的研究表明,模型中真正重要的连接只占整个蜘蛛网的一小部分!!
例如,像 AlexNet 和 VGG-16 这样的著名 ImageNet 模型已经被压缩到其原始大小的 40-50 倍,而准确性没有任何损失(实际上略有增加)。这极大地提高了他们的推理速度,以及他们适应各种设备的便利性。
有足够的说服力,让我们谈谈所涉及的技术!!
模型压缩可以分为两大类,
修剪:移除架构中存在的冗余连接。剪枝包括切除不重要的权重(通常定义为绝对值小的权重)。
显然,所形成的新模型将具有较低的准确性,因为该模型实际上是为原始连接而训练的。这就是为什么模型在修剪后被微调以重新获得准确性。值得注意的是,全连接层和 CNN 通常可以达到 90%的稀疏度,而不会损失任何精度。
量化:量化包括通过聚类或四舍五入将权重捆绑在一起,这样相同数量的连接可以用更少的内存来表示。
通过聚类/捆绑进行量化,从而使用较少数量的不同浮点值来表示更多数量的特征,这是最常用的技术之一。形成许多量化方法框架的另一种常见技术是通过舍入将浮点权重转换为定点表示。
同样,正如修剪一样,我们需要在量化后对模型进行微调。这里重要的一点是,量化时赋予权重的属性也应该通过微调来保持。这就是为什么要使用特定的微调方式来匹配量化方法。
请看上图,这是一个通过聚类进行量化的例子。相同颜色的权重聚集在一起,用它们的质心来表示。这减少了表示这些权重所需的数据量。早期需要 32 位16 = 512 位来表示它们。现在只需要 32 位 4+2 位*16 = 160 位来表示它们。在微调期间,属于同一颜色的所有权重的梯度被相加,然后从质心中减去。这确保了在量化期间进行的聚类通过微调得以保持。
下一步是什么?
深度学习模型剪枝和量化是相对较新的领域。虽然在这一领域取得了重大成功,但仍有很长的路要走。该领域的下一个重点应该是创建开源和易于访问的管道,用于将常见的深度学习模型转移到 FPGAs 等嵌入式系统。
这个博客是为机器学习领域创建简化介绍的努力的一部分。点击此处的完整系列
在你一头扎进去之前就知道了
towardsdatascience.com](/machine-learning-simplified-1fe22fec0fac)
或者干脆阅读系列的下一篇博客
让我们来看看高频交易这个竞争激烈的世界,以及人工智能是如何成为其中一部分的。
towardsdatascience.com](/high-frequency-trading-hft-with-ai-simplified-a24c00da72e0)
参考
[1]韩、宋、、毛和威廉·j·戴利。"深度压缩:压缩深度神经网络与剪枝,训练量化和霍夫曼编码."arXiv 预印本 arXiv:1510.00149 (2015)。
[2]贾,海鹏,等.“模型压缩中的丢弃问题”arXiv 预印本 arXiv:1812.02035 (2018)。
[3]王、硕等,“C-lstm:在 fpgas 上使用结构化压缩技术实现高效 lstm。”2018 年 ACM/SIGDA 现场可编程门阵列国际研讨会论文集。ACM,2018。
分类变量上的机器学习
如何正确运行和评估模型
乍一看,分类变量和数字变量没什么不同。但是,一旦你开始深入挖掘,并在代码中实现你的机器学习(和预处理)思想,你就会每分钟都停下来问一些问题,比如“我在训练集和测试集上都做特征工程吗?”或者“我听说了一些关于基数的事情——那是什么,我应该用谷歌搜索更多相关信息吗?”
让我们看看我们是否可以通过一个行动计划来澄清这一点,即如何处理具有许多分类变量的数据集并训练几个模型。
Kaggle 将作为我们的数据源:它有一个优秀的房价数据集。准备花些时间浏览提供的数据字典。您可以在单独的浏览器窗口中打开它。我们还会将其加载到 Jupyter 笔记本中。在本练习中,我们将根据房屋的各种参数预测列 SalePrice 中的值。
和往常一样,所有代码都可以在 GitHub 上获得(你需要工作簿Features _ for _ mlops . ipynb)。它还有一些额外的图表,我们在这里没有涉及,但对于更好地理解这个过程是有用的。
让我们加载依赖项和数据:
# Loading necessary packages
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import scipy.stats as st
import seaborn as sns
import pandas_profiling
import requests
%matplotlib inlinetrain = pd.read_csv(r'train.csv')
test = pd.read_csv(r'test.csv')
如果您想在 GUI 中有一个数据字典:
response = requests.get('[https://storage.googleapis.com/kaggle-competitions-data/kaggle/5407/205873/data_description.txt?GoogleAccessId=web-data@kaggle-161607.iam.gserviceaccount.com&Expires=1564407075&Signature=Iduf4UDvx2Cei5S9B7A%2B%2Fz3u%2Ff8GG0RxvpfMu5IHRtJOFBsjq806B2sSr6zucZBwJeBNSOuIpOssfa4i%2BYS8ybrJgaHnA%2Fqkcox6ZsD8BLIl3yTHjwmfkie2ohGSI0bdZLiXblBWps8xJ8sGZPnmTegLYLhFgrA7O0BEF5dIXrFVYufTcndkOeOyYm3fopGjTablaxWOUyhmd43WfOxADJInaMqUk37SBzVD4jD1bj%2F%2B%2FJkK7OeTvUIBJOR3EXij97rhVqcZNdxTttF91t0W3HFcqJrRhrw5%2BKvZmHNzsT5AO164QSjlFqT5kU3dZWoZqxdDOxImVvr%2Fw2m4IRZGCw%3D%3D'](https://storage.googleapis.com/kaggle-competitions-data/kaggle/5407/205873/data_description.txt?GoogleAccessId=web-data@kaggle-161607.iam.gserviceaccount.com&Expires=1564407075&Signature=Iduf4UDvx2Cei5S9B7A%2B%2Fz3u%2Ff8GG0RxvpfMu5IHRtJOFBsjq806B2sSr6zucZBwJeBNSOuIpOssfa4i%2BYS8ybrJgaHnA%2Fqkcox6ZsD8BLIl3yTHjwmfkie2ohGSI0bdZLiXblBWps8xJ8sGZPnmTegLYLhFgrA7O0BEF5dIXrFVYufTcndkOeOyYm3fopGjTablaxWOUyhmd43WfOxADJInaMqUk37SBzVD4jD1bj%2F%2B%2FJkK7OeTvUIBJOR3EXij97rhVqcZNdxTttF91t0W3HFcqJrRhrw5%2BKvZmHNzsT5AO164QSjlFqT5kU3dZWoZqxdDOxImVvr%2Fw2m4IRZGCw%3D%3D'))
dict = response.text
print(dict)
我们现在可以进行快速数据分析:
train.describe().T
test.describe().T
和往常一样,我推荐熊猫简介包。
pandas_profiling.ProfileReport(train)
有很多缺失的值。除了逐一检查每个特性并决定如何处理它们之外,没有什么灵丹妙药可以解决这个问题。我们用以下方式清洁它们:
dr = ['Alley','Fence','FireplaceQu','MiscFeature','PoolQC']
train.drop(labels = dr, axis = 1, inplace = True)
test.drop(labels = dr, axis = 1, inplace = True)train['LotFrontage'].fillna(train['LotFrontage'].mean(), inplace = True)
train['GarageQual'].fillna('NA', inplace = True)
train['GarageFinish'].fillna('NA', inplace = True)
train['GarageCond'].fillna('NA', inplace = True)
train['GarageYrBlt'].fillna(train['GarageYrBlt'].mean(), inplace = True)
train['GarageType'].fillna('NA', inplace = True)
train['MasVnrType'].fillna('None', inplace = True)
train['MasVnrArea'].fillna(train['MasVnrArea'].mean(), inplace = True)
train['BsmtQual'].fillna('NA', inplace = True)
train['BsmtCond'].fillna('NA', inplace = True)
train['BsmtExposure'].fillna('NA', inplace = True)
train['BsmtFinType1'].fillna('NA', inplace = True)
train['BsmtFinType2'].fillna('NA', inplace = True)
train['Electrical'].fillna('SBrkr', inplace = True) # substituting with the majority class# and for the test settest['LotFrontage'].fillna(train['LotFrontage'].mean(), inplace = True)
test['GarageQual'].fillna('NA', inplace = True)
test['GarageFinish'].fillna('NA', inplace = True)
test['GarageCond'].fillna('NA', inplace = True)
test['GarageYrBlt'].fillna(train['GarageYrBlt'].mean(), inplace = True)
test['GarageType'].fillna('NA', inplace = True)
test['MasVnrType'].fillna('None', inplace = True)
test['MasVnrArea'].fillna(train['MasVnrArea'].mean(), inplace = True)
test['BsmtQual'].fillna('NA', inplace = True)
test['BsmtCond'].fillna('NA', inplace = True)
test['BsmtExposure'].fillna('NA', inplace = True)
test['BsmtFinType1'].fillna('NA', inplace = True)
test['BsmtFinType2'].fillna('NA', inplace = True)
test['Electrical'].fillna('SBrkr', inplace = True) # substituting with the majority class
有趣的是,测试集有缺失值,而训练集没有。这意味着我们需要做额外的清洁工作:
test['MSZoning'].fillna('RL', inplace = True)
test['Utilities'].dropna(inplace = True)
test['Exterior1st'].dropna(inplace = True)
test['Exterior2nd'].dropna(inplace = True)
test['BsmtFinSF1'].fillna(test['BsmtFinSF1'].mean(), inplace = True)
test['BsmtFinSF2'].fillna(test['BsmtFinSF2'].mean(), inplace = True)
test['BsmtUnfSF'].fillna(test['BsmtUnfSF'].mean(), inplace = True)
test['TotalBsmtSF'].fillna(test['TotalBsmtSF'].mean(), inplace = True)
test['BsmtFullBath'].fillna(test['BsmtFullBath'].mean(), inplace = True)
test['BsmtHalfBath'].fillna(test['BsmtHalfBath'].mean(), inplace = True)
test['KitchenQual'].dropna(inplace = True)
test['Functional'].dropna(inplace = True)
test['GarageCars'].fillna(round(float(test['GarageCars'].mean()),1), inplace = True)
test['GarageArea'].fillna(test['GarageArea'].mean(), inplace = True)
test['SaleType'].dropna(inplace = True)test.drop(test.index[[95,45,485,756,1013,1029]], inplace = True)
test.drop(test.index[[455,691]], inplace = True)
test.drop(test.loc[test['Id']==1916].index, inplace = True)
test.drop(test.loc[test['Id']==2152].index, inplace = True)
在这个过程之后,没有 nan 留下:
train.columns[train.isna().any()].tolist()
It’s an empty list that would have had columns with NaNs if there were any
test[test.isna().any(axis=1)]
The Test set is also good to go
分类变量的未来工程
这就是你在这里的原因。这是我们将遵循的清单:
- 确保分类变量被如此对待。这同样适用于数字变量
- 检查分类要素的基数
- 查看“可疑”列如何与目标变量交互
- 查看是否有任何高度相关的要素可以删除
- 看看有没有可以组合的功能
- 考虑基数,对分类变量进行一次性编码或频率编码
分类变量的类型为“类别”
如果您查看一些列,如 MSSubClass ,您会意识到,虽然它们包含数值(在本例中为 20、30 等。),它们实际上是分类变量。从数据字典中可以清楚地看出:
Numbers don’t always mean numbers
我们怀疑这样的柱子不止一根。我们来确认一下:
[col for col in train.columns.tolist() if train[col].dtype not in ['object']]
它返回非对象列的列表。在阅读了对它们每一个的描述后,我们决定进行以下转换:
train['Id'] = train['Id'].astype('category')
train['MSSubClass'] = train['MSSubClass'].astype('category')
# train['YearBuilt'] = train['YearBuilt'].astype('category')
# train['YrSold'] = train['YrSold'].astype('category')
# train['YearRemodAdd'] = train['YearRemodAdd'].astype('category')
train['GarageYrBlt'] = train['GarageYrBlt'].astype('category')
train['Fence'] = train['Fence'].astype('category')
train['MiscFeature'] = train['MiscFeature'].astype('category')
train['MiscVal'] = train['MiscVal'].astype('category')
您将很快看到为什么三个与年份相关的列还没有被转换。
基数
如果您有显示高基数的分类要素,您可能会面临某些问题。最有可能的情况是,您将使用一键编码器,您的数据集可能会突然变得非常宽和稀疏。这不利于计算(尤其是当列数接近观察数时),不利于任何基于树的方法(很可能,树会向一个方向生长),并且可能导致过度拟合和数据泄漏。
你可以从概念上或者技术上来解决这个问题。****
概念方法:检查每一个变量,对它们进行 value_counts() 运算,决定是否可以牺牲一些不常用的值,将它们放在“其他”项下。
top = test['GarageType'].isin(test['GarageType'].value_counts().index[:5])
test.loc[~top, 'GarageType'] = "other"
我们刚刚在这里做的: index() 返回给定元素在列表中的位置。在我们的例子中,该列中所有不在频率前五位的值现在都在“其他”中。理想情况下,您希望对每一列都这样做。之后,你做一个热编码。然而,如果你对自己的时间很吝啬,你可能会用一种纯粹的技术方法。最有可能的是,你的计算机将能够处理一个非常广泛的数据集,并相对快速地处理它。所以只要调用 get_dummies()就可以了,希望一切顺利。你可能需要忘记基于森林的或者降维方法,但是,在大多数情况下,你可以忍受它。Sklearn 的 OneHotEncoder() 在这里提供了一些额外的功能可能会有用。它有一个参数 n_values() ,您可以用它来指定每一列可以保留的值的最大数量。
在这个特定的数据集中,我们首先调查了训练列和测试列是否具有不同的基数:
for col in train.columns:
if train[col].dtype == "object":
print("For column {} cardinality in Train minus cardinality in Test equals: {}".format(col, train[col].nunique()-test[col].nunique()))
然后决定通过研究条形图来研究这些信息:
# Gathering columns for which cardinality isn't the same into a list in order to make charts
cols_list = []
for col in train.columns:
if train[col].dtype == "object" and (train[col].nunique()-test[col].nunique()) != 0:
cols_list.append(col)
# looking at values in these columns
for l in cols_list:
sns.catplot(x=l, hue='Status', kind='count', data=combo)
plt.xticks(rotation=45)
Example of a variable’s values in the train and test datasets
幸运的是,一般来说,没有一个列有很多不同的分类值,测试集和训练集也没有表现出很高的基数。正因为如此,我们能够继续进行一个普通的独热编码。
“可疑”栏
正如我们上面所说的,高基数的情况没有那么糟糕,只适用于相应列中的较小值。因此,我们将保持原样。不过,我们仍然可以检查它们是如何影响销售价格的。
我们将构建盒子图(可能需要一些时间来渲染):
# list w/ categorical variables
cater_cols = train.select_dtypes(include='category').columns.to_list()for cols in cater_cols:
plt.figure()
sns.boxplot(x = cols, y = 'SalePrice', data = train)
一个好主意是在以下情况后关闭图表:
plt.clf()
plt.close()
无法检测到任何可见的异常值。
相关
我们将把数字特征与销售价格联系起来,希望了解哪些可以删除,哪些可以合并。查看每个特性可能不是一个好主意,所以让我们关注前 15 个(但是您可以在下面的代码中将这个数字更改为任何其他值)最相关的变量:
corrmat = train.corr()
plt.figure(figsize=(20,10))
k = 15 #number of variables for heatmap
cols = corrmat.nlargest(k, 'SalePrice')['SalePrice'].index
cm = np.corrcoef(train[cols].values.T)
sns.set(font_scale=1.25)
hm = sns.heatmap(cm, cbar=True, annot=True, square=True, fmt='.2f', annot_kws={'size': 10}, yticklabels=cols.values, xticklabels=cols.values)
plt.show()
Top categories affecting SalePrice
同样,你需要运用一些常识。例如, GarageCars 和 GarageArea 都在讲述一个关于你停放车辆的地方有多大的故事。关于平方英尺的信息分布在不同的列中,并且可能被汇总。平方英尺的浴池可以跟随诉讼。一个时代的房子和他们何时被改造也应该齐头并进。让我们来实现它:
train['Remodeled Y/N'] = np.where(train['YearRemodAdd'] ==train['YearBuilt'], 'No', 'Yes')
train['Age when Sold'] = train['YrSold'] - train['YearRemodAdd']
train['Remodeled Y/N'] = train['Remodeled Y/N'].astype('category')train['totSqFt'] = train['TotalBsmtSF'] + train['GrLivArea'] + train['1stFlrSF'] + train['2ndFlrSF']train['totBath'] = train['FullBath'] + 0.5*train['HalfBath'] + train['BsmtFullBath'] + 0.5*train['BsmtHalfBath']
我们刚刚创建了一个新列, totSqFt ,它合并了三个现有的值。我们可以检查它是否可以作为一个正确的近似:
fig = plt.figure(figsize=(20,10))
ax1 = fig.add_subplot(121)
ax2 = fig.add_subplot(122)ax1.scatter(train['totSqFt'],train['SalePrice'], color = 'crimson', label = 'totSqFt')ax2.scatter(train['GrLivArea'],train['SalePrice'], color = 'teal', alpha = 0.3, label ='GrLivArea')
ax2.scatter(train['TotalBsmtSF'],train['SalePrice'], color = 'midnightblue', label = 'TotalBsmtSF')
ax2.scatter(train['1stFlrSF'],train['SalePrice'], color = 'coral', alpha = 0.4, label = '1stFlrSF')ax1.legend()
ax2.legend()
plt.show()
看起来很准确:
Sum of three columns on the left; original features on the right
完成后,我们可以删除进入新变量的列:
# Remove variables that were used to create new features
cols_2_remove = ['GrLivArea','TotalBsmtSF','1stFlrSF','YearRemodAdd','YearBuilt','YrSold','Id','2ndFlrSF',
'FullBath','HalfBath','BsmtFullBath','BsmtHalfBath','GarageYrBlt']
train_rem = train.copy()
train_rem.drop(cols_2_remove, axis = 1, inplace = True)
我们有独立变量,情况很好,但是让我们再看看销售价格。
# Building normality plots
from statsmodels.graphics.gofplots import qqplot
from matplotlib import pyplot
Normality plot for SalePrice
这张 q-q 图显示,非常便宜和非常昂贵的房子并不真正遵循正态分布。对 totSqFt 的额外检查证实了这一点:
q-q plot for totSqFt
你可以探索这些又大又贵(或者又小又便宜)的房子:
train_rem[train_rem['totSqFt']>10000]
train_rem[train_rem['SalePrice']>700000]
它们没有什么特别的,所以我们应该对从集合中移除它们感到相对安全:
train_rem.drop(train_rem[train_rem.totSqFt>10000].index, inplace = True)
train_rem.drop(train_rem[train_rem.SalePrice>700000].index, inplace = True)
之后,q-q 图看起来更正常。
这是有效处理具有大量分类特征的数据集的方法。我们已经做了大量的数据探索和预处理,这将在 ML 阶段有所帮助。
现在这里最重要的部分:你必须对合并的数据集进行任何编码!为什么?假设您有一个列“颜色”,它在训练集中的值为“蓝色”、“绿色”和“黑色”。同时测试也有“黄色”和“红色”您的编码器必须看到所有可能的值,才能充分利用它们。
操作的顺序是:
- 在新列状态中分别标记训练集和测试集
- 组合列车和测试装置,从列车部分移除销售价格
- 对分类特征进行一次性编码(但不包括状态
- 使用状态将接头组拆分回列车并测试
没有理由保留分类列的对象类型。让我们把它们变成 类别 。
# turning object columns into category columns
for i in train.select_dtypes(include='object').columns.to_list():
train[i] = train[i].astype('category')
和主要部分:
# list w/ categorical variables
cater_cols = train.select_dtypes(include='category').columns.to_list()#Add new column Status to both sets to differentiate between the two
train_1 = train_rem.copy()
train_1.drop(labels = 'SalePrice', axis = 1, inplace = True)
train_1['Status'] = 'Train Set' # adding a column Status to differentiate between Train and Test in the combined set
test_1 = test_rem.copy()
test_1['Status'] = 'Test Set'
combo = train_1.copy()
combo = combo.append(test_1)
确保每件事都做对的一个好方法是不断检查你的数据帧的形状:
train_1.shape
test_1.shape
combo.shape
这里我们单独保存了状态并从 X:
X = combo.copy()
St = X['Status']
X.drop('Status', axis = 1, inplace = True)
以及编码:
X_cat = X.select_dtypes(include=['category'])
X_num = X.select_dtypes(exclude=['category'])
X_encoded = pd.get_dummies(X_cat)
现在我们有三块: X_encoded (编码后的分类变量) X_num (没变的数值变量) St (就一列,状态)。
检查它们的大小是否匹配:
print("X_encoded = {}\nX_num = {}\nSt = {}".format(X_encoded.shape,X_num.shape, St.shape))
将它们组合在一起(并进行最终尺寸检查):
frames = [X_encoded, X_num, St]
combo_enc = pd.concat(frames, axis = 1)print('Combined set is {}'.format(combo_enc.shape))
现在,我们可以将组合集分为训练集和测试集,并继续机器学习:
train_enc = combo_enc.loc[combo_enc['Status']=='Train Set']
test_enc = combo_enc.loc[combo_enc['Status']=='Test Set']print('Encoded Train set is {}\nEncoded Test set is {}'.format(train_enc.shape,test_enc.shape))
这种事实上的方法是透明的,在各种文章和书籍中都有描述。然而,让我们避免使我们的数据集太宽。怎么会?通过频率编码。
频率编码
X_cat_freq = X_cat.copy()for c in X_cat_freq.columns.to_list():
X_cat_freq[c] = X_cat_freq.groupby(c).transform('count')/len(X_cat_freq[c])
频率编码并不难理解或实现。我们计算一列中不同值的数量,然后除以该列的总长度。结果,我们得到了每一个值的“份额”,这些值在任何 ML 算法中都能很好地发挥作用。
下面的代码看起来应该很熟悉:我们需要区分训练集和测试集,然后将它们合并在一起,
frames_freq = [X_cat_freq, X_num, St]
combo_enc_freq = pd.concat(frames_freq, axis = 1)combo_enc_freq.shape
# All features and Status are together#cut combo_enc_freq by Train and Test. Add SalePrice back to the Train portion
train_freq = combo_enc_freq.loc[combo_enc_freq['Status']=='Train Set']
test_freq = combo_enc_freq.loc[combo_enc_freq['Status']=='Test Set']# adding SalePrice to Encoded Train set
fr = [train_freq, sp]
train_freq = pd.concat(fr, axis = 1)# Checking sizes
print("Respective sizes of the train set: {}\nOf the test set: {}\nOf the prices array:{}".format(train_freq.shape,
test_freq.shape,
sp.shape))
为了便于您比较哪种编码类型会产生更好的结果,我们创建了使用频率和一键编码方法编码的数据帧:
features_freq = train_freq.drop(['SalePrice','Status'], axis = 1)
result_freq = np.exp(train_freq['SalePrice'])X_train_freq, X_test_freq, y_train_freq, y_test_freq = train_test_split(features_freq, result_freq, test_size = 0.2, random_state = 12)features = train_enc.drop(['SalePrice','Status'], axis = 1)
result = train_enc['SalePrice']X_train, X_test, y_train, y_test = train_test_split(features, result, test_size = 0.2, random_state = 12)
机器学习
这一部分在其他资料中有详细解释;此外,GitHub 上的工作簿包含了几个不同模型的实现:从使用 one-hot 编码数据集的回归到 Lasso 和 XGBoost。下面我们将探讨线性回归和 XGBoost,我们在经过频率编码的集合上运行。
import xgboost as xgb
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import StratifiedKFold
import math
加载完依赖项后,我们可以开始建模了。
regr_freq = LinearRegression()
regr_freq.fit(X_train_freq, y_train_freq)print("RMSE is: {:.2f}\nR_squared is {:.2f}%".format(math.sqrt(np.mean((regr_freq.predict(X_test_freq) - y_test_freq) ** 2)),
regr_freq.score(X_test_freq,y_test_freq)*100))
回归给了我们:
Not bad for the simplest method possible
和 XGBoost:
xgb_freq = xgb.XGBRegressor(n_estimators=100, learning_rate=0.08, gamma=0, subsample=0.75,
colsample_bytree=1, max_depth=7)xgb_freq.fit(X_train_freq,y_train_freq)
predictions_xgb_freq = xgb_freq.predict(X_test_freq)
print(explained_variance_score(predictions_xgb_freq,y_test_freq))
现成的结果几乎与回归结果一致:
如果我们优化参数,会有帮助吗?运行以下代码需要几分钟时间:
# TAKES TIME
n_estimators = [80, 100, 120, 140, 160]
max_depth = [4, 5, 6, 7, 8, 9, 10]
learning_rate = [0.0001, 0.001, 0.005, 0.01, 0.1, 0.2, 0.3, 0.04]
param_grid = dict(max_depth = max_depth, n_estimators = n_estimators, learning_rate=learning_rate)
kfold = StratifiedKFold(n_splits = 10, shuffle = True, random_state = 10)
grid_search_xg_freq = GridSearchCV(xgb_freq, param_grid, scoring = 'r2', n_jobs = -1, cv=kfold, verbose = 1)
result_gcv_xgb_freq = grid_search_xg_freq.fit(X_train_freq, y_train_freq.astype(int))print("Best score: %f using %s" % (result_gcv_xgb_freq.best_score_, result_gcv_xgb_freq.best_params_))
means = result_gcv_xgb_freq.cv_results_['mean_test_score']
stds = result_gcv_xgb_freq.cv_results_['std_test_score']
params = result_gcv_xgb_freq.cv_results_['params']
让我们使用最佳参数:
Results of GridSearchCV
# Rebuilding using the best parameters:
xgb_freq = xgb.XGBRegressor(n_estimators=110, learning_rate=0.1, gamma=0, subsample=0.75,
colsample_bytree=1, max_depth=5)xgb_freq.fit(X_train_freq,y_train_freq)
predictions_xgb_freq = xgb_freq.predict(X_test_freq)
print("R squared is {}".format(explained_variance_score(predictions_xgb_freq,y_test_freq)))
我们可以进一步调整模型,但这不是主要的学习成果。主要的一点是,通过以明智和准确的方式对待分类特征,我们可以在没有非常花哨的机器学习方法或过度计算能力的情况下获得体面的结果。
机器学习,第 1 部分:基本概念
Image by the author
机器学习基础
系列介绍
当我第一次学习机器学习的时候,我发现了很多对孤立概念的很好的解释:一个算法,一个子领域,一个概念,等等。随着时间的推移,这些孤立的解释开始汇集成一个更大的、相互关联的视野。作为一个倾向于系统思考的人,我希望我能早点接触到提供这种更大视角的东西。
这一系列的文章就是一个尝试。这些帖子应该都适合没有机器学习经验的人,每个部分都提供足够的信息来真正理解特定问题的要点。也就是说,我不会像课程或教科书那样,对每个问题的数学或算法进行详细的描述。相反,重点是提供上下文和机器学习最常见的子问题之间的联系。对于那些喜欢系统思考的人来说,这应该为更深入地研究特定算法和问题提供了一个极好的切入点。
这篇文章的第一部分涵盖了所有机器学习形式的基本概念。它主要谈论数据、数据集以及我们如何使用它们。第 2 部分涵盖监督学习,第 3 部分涵盖非监督学习,第 4 部分涵盖强化学习。如果你甚至不确定什么是机器学习,或者为什么需要它,那么它可能值得一读我的广泛介绍文章。如果你对机器学习/数据科学领域的各种术语感到困惑,我也有一篇关于这个的文章。
有人监督与无人监督
机器学习的一般定义是,我们使用数据来训练一个试图学习复杂决策逻辑的模型。通常,决策是如此复杂,以至于程序员要么自己不知道正确的逻辑,要么不知道如何将该逻辑翻译成计算机友好的格式,或者两者兼而有之。如果逻辑简单,程序员知道,他们可以直接编程。学习复杂决策的逻辑通常是通过使用数据集来完成的。根据我们收到的数据类型,我们有两种不同的方法来学习我们的决策逻辑。
在监督学习中,我们有一个训练观察数据集,它被标记。带标签的数据意味着“正确”的答案提供给了我们。用更专业的术语来说,我们知道特定输入的预期输出。有标签很重要,原因有二:首先,假设我们生成一个逻辑,给它输入,然后生成输出(预测)。因为我们有标签,我们可以将我们的逻辑预测与预期输出(标签)进行比较,看看我们的预测是否准确。
训练数据的准确性是有用的,因为我们假设训练数据非常类似于我们最终想要对其使用该逻辑的未标记的真实世界数据。训练数据的良好准确性通常也转化为现实世界的良好准确性。如果训练数据不不像真实世界,那么基本上不可能产生好的预测。这通常用短语“垃圾进,垃圾出”来描述
如果我们发现我们的逻辑是而不是输出好的预测,那么我们可以将标签用于它们的第二个目的:指导我们逻辑的改进。事实上,这正是“监督”一词的来源:像这样的算法通常有一个学习器元素,它是问题的模型/逻辑。他们还有一个教师元素,监督学习者并使用标签提供对预测的反馈。
让我们看一个简单的例子。假设你希望能够准确预测汽车的耗油量,你该如何去做呢?你可以很容易地做的一件事就是指着路上的汽车说:“我想那辆车每加仑跑 X 英里。”然而,如果没有任何形式的反馈,那就不太可能提高你的猜测。你不仅不知道你的猜测是否接近,你也不知道它们是如何错的;它们是太高还是太低?他们是在球场上还是在远处?
如果没有反馈,流程会停止,但我们可以通过收集更多数据来停止。那么,假设你去了一个汽车展,那里有数百辆汽车的橱窗上贴着(字面上的)标签,上面列出了油耗等信息。现在你可以看着一辆车,做一个预测,然后将这个预测与窗口中列出的实际油耗进行比较。假设一开始你猜轿车 100mpg 左右,SUV 更好 120mpg 左右。接触甚至两三个不同的标签示例就足以让你意识到这两个猜测都太高了,事实上 SUV 比轿车(总的来说)的油耗更低。
你得到的反馈越多,你就越能认识到一些趋势,比如大型汽车的油耗越低,大型发动机的油耗越低,新车的油耗比旧车高。从长远来看,所有这些模式都有助于做出更好的整体预测。不仅如此,当你预测未标记的数据时,它们会给你一个很好的错误概念。如果你预测的平均误差是 5mpg,那么当你做一个新的预测时,你应该确信它接近真实值。如果你的平均误差是 20 英里/加仑,那么用现有的数据做出准确的预测是不可能的。在这两种情况下,监管为我们的预测模型提供了至关重要的信息。
无监督学习是……嗯,没有监督。基本上“无监督的”变成了一个包罗万象的术语,指任何不遵循教师/学习者模式,没有监督元素的事物。事实上,根据某些定义,无监督学习甚至根本不是机器学习,因为没有“教师”元素,同样也没有“学习者”元素。根据这一论点,无监督学习只是统计分析。
然而,根据大多数定义,无监督学习仍然算作机器学习,我们在这里涵盖它。很难像上面我们对监督学习所做的那样解释无监督学习,因为每种无监督方法都倾向于解决不同的问题,并做出不同的假设。我能想到的解释它的最好方式是说,在监督学习中,我们在数据中寻找模式,这样我们就可以将这些模式与标签联系起来,希望这种方式能让我们准确地预测标签。
在无监督学习中,我们仍然在寻找模式,但是我们没有标签来关联这些模式。所以无监督的方法倾向于寻找特定类型的模式,基于这些模式通常重要的假设。例如,找到相似点的聚类,通常意味着这些点有一些共同点,即使我们不知道那是什么。找到对其余数据极端异常的点通常意味着这些点与其余数据相比具有非常独特的特征。如果没有进一步的调查,我们通常不会知道这个独特的特征是什么,但是识别异常点是这个过程中必要的第一步。
描述数据集
鉴于数据对机器学习的重要性,拥有一个描述数据的词汇最终是必不可少的。不幸的是,在数据科学中,许多概念有许多不同的等价术语。一线希望:这里的概念比看起来要容易理解得多。
在绝大多数机器学习应用中,数据集可以被认为类似于电子表格或表格。列被称为特征或变量。每个行都是一个实例、观察或实例。示例通常也被称为数据点或仅仅是点,因为在数学上它们代表了一个 n 维空间中的一个点,其中 n 是特征的数量。
在监督学习中,特征有其他名称,这取决于该特征是否是期望的输出(也称为标签),或者它是否是我们用来预测该标签的特征。我们用来预测输出的特征称为输入变量/输入、预测器或独立变量。期望输出被称为输出变量/输出、响应变量或因变量。这些通常是成对的:如果你看到术语“自变量”用于输入,你会期望“因变量”用于输出。在代码和方程中,预测值通常标记为X
,而标签使用y
。
为什么同样的东西有这么多术语?机器学习背后的理论被许多领域使用并得到发展。经济学家一般使用“独立/因变量”,统计学家一般使用“预测器/响应”,计算机科学家更可能使用“输入/输出”。大多数情况下,我会使用“预测/反应”,因为我觉得它们是最直观的术语,也最容易记住哪个是哪个。“输入/输出”也很好,但它们在计算机科学中太常见了,含义略有不同,所以我宁愿避免使用它们。
最后,特性是一个特例,它可以描述任何列,但它最常用于我们不关心该列是预测还是响应的时候。因此,在无监督学习(没有预测器/响应)中,我们使用“特征”来描述一切。
噪音
所有数据都包含信息,但是该信息被分成两部分:信号和噪声。信号是我们想要的,它是数据中有价值和有用的部分。噪声可能来自许多来源,但其效果总是会给数据带来我们不想要且无法解释的变化。
让我们考虑一个例子:我们为一个学区工作,我们听说了一项研究,在学校增加更多的植物可以提高考试成绩。我们想尝试这种方法,但由于预算原因,该地区不想要真的植物,他们只想买一堆假植物,希望效果是一样的。他们决定先在一所学校尝试,然后在整个学区推广这个项目。
令许多人惊讶的是,在增加了塑料植物后,这所学校的考试成绩直线上升。负责人自然很激动,但是有没有可能这里发生了别的事情?
事实上是有的。在添加植物前一个月左右,学校与当地一所大学合作,让大学生来学校为高中生提供一对一的辅导。我们的分析没有考虑或控制这一点——这不是数据集的一部分——但辅导项目可能比假工厂对考试增加的贡献更大是有道理的。
现在让我们通过信号和噪声的框架来考虑这个问题。在这种情况下,“信号”是任何关于假植物特别是效果的数据。我们只想测量植物对考试分数的影响。然而,噪音已经以我们做了而不是测量的事情的形式悄悄进来,这些事情仍然影响着结果——特别是辅导项目。
不可测量的变量是一个极其常见的噪声源,还有其他的。当数据来自传感器时,另一个常见的噪声源是电磁干扰。干扰是(电话公司)最先广泛研究的噪音形式之一,因为当通过扬声器收听时,它会产生持续的静态嗡嗡声,所以它也是术语“噪音”的来源。
我们如何处理噪音?在大多数情况下,我们不知道,它只是我们数据集的固有部分。有时可以通过添加新特征(测量不可测量的量)、控制缺失变量和/或通过更先进的噪声消除技术来消除噪声。大多数噪声去除取决于噪声的类型及其来源,并且它们通常不能完全去除噪声。
幸运的是,机器学习算法在面对噪声时仍然有效,它们将根据给定的数据生成最佳模型。很多时候这就足够了,有无数有用的 ML 模型已经在嘈杂的数据集上进行了训练。然而,有时我们收到的数据并不能产生一个真正有效的模型。发生这种情况时,噪音通常是罪魁祸首。
展望未来,我不会过多地谈论噪声,除非算法有其他人没有的噪声问题。然而,这是应该永远记住的事情,因为它是数据科学的基础部分。
下一个
上面的概念对所有类型的机器学习都是通用的,所以在前进的过程中有一些熟悉是有帮助的。接下来,我们进入监督学习。
Python 中的主成分分析示例
Photo by Markus Spiske on Unsplash
主成分分析或 PCA 用于在不损失太多信息的情况下减少特征的数量。拥有过多维度的问题在于,它使得数据难以可视化,并且使得训练模型在计算上更加昂贵。
为了让我们对 PCA 有一个直观的理解,假设我们想要建立一个预测房价的模型。我们将从收集该地区房屋的数据开始。假设我们收集了数以千计的样本,每个样本都包含了一个给定房屋的属性信息。这些属性包括卧室数量、浴室数量和面积。常识会让我们相信,卧室的数量、浴室的数量和房子的面积之间存在某种关系。换句话说,我们怀疑房子的面积越大,包含的卧室和浴室就越多。如果变量高度相关,我们真的有必要为同一基本特征(即大小)设置三个独立的变量吗?主成分分析用于确定哪个变量(即浴室数量或平方英尺)占房价的最大差异,并将它们结合起来。
假设我们绘制了一个任意变量的三个样本。
平均值等于所有数据点的总和除以样本总数。
单个数据点的方差就是它与平均值的距离。
整个数据集的方差是所有这些距离的平方和除以样本总数。我们最终将这些值平方,因为在坐标系中,平均值左侧的距离将为负,并且会与平均值右侧的距离抵消。
在二维空间中,为了计算其中一个变量的方差,我们将数据点投影到它的轴上,然后遵循与前面相同的过程。一个特征(即薪水)的均值和方差是相同的,不管它所绘制的其他特征是什么。
可惜的是,x 和y 方差本身并没有包含足够的信息。
尽管两个图有明显的差异,但它们导致相同的 x 和y 方差。
因此,我们利用另一个叫做协方差的性质。计算协方差时,我们将 x 和 y 坐标相乘,而不是取平均值的距离的平方。
协方差和相关性是不同的概念。然而,它们都描述了两个变量之间的关系。更具体地说,两个变量之间的相关性实际上是协方差除以第一个变量的方差的平方根乘以第二个变量的方差。因此,当相关或协方差为负时,x 的增加导致 y 的减少,当相关或协方差为正时,x 的增加导致 y 的增加。
两个变量的协方差矩阵由左上角第一个变量的方差、右下角第二个变量的方差和对角线上剩余两个位置的协方差组成。
作为 PCA 算法的一部分,协方差矩阵用于计算特征值和特征向量。
假设我们画出了两个不同变量之间的关系。
首先,我们将数据居中。
接下来,我们在特征向量的方向上画两个向量,它们的大小与特征值相等。
然后我们选择方差最大的一个,因为当我们删除另一个维度时,它会导致最少的信息损失。
然后,数据点被投影到直线上。
后者用作新特征的一维图。
密码
让我们看看如何用 python 实现主成分分析。首先,导入所有必需的库。
import pandas as pd
import numpy as np
from matplotlib import pyplot as plt
from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler
from sklearn.datasets import load_iris
在本例中,我们将使用 iris 数据集,该数据集可以通过 sklearn API 轻松导入。
iris = load_iris()X = pd.DataFrame(iris.data, columns=iris.feature_names)
y = pd.Categorical.from_codes(iris.target, iris.target_names)
正如你所见,有 4 个特点。凭直觉,我们可以预测萼片长度和萼片宽度之间有很强的相关性,花瓣长度和花瓣宽度之间也有很强的相关性。因此,我们应该能够将维数从 4 减少到 2。
X.head()
正如我们前面看到的,方差是通过从平均值中取距离的平方和来计算的。因此,如果一个要素的尺度比另一个要素大得多,那么即使相对离差可能较小,它的方差也会大得多。因此,我们必须扩展数据。在缩放数据时,平均值设置为 0,标准偏差设置为 1。
scaler = StandardScaler()
X = scaler.fit_transform(X)
接下来,我们将使用 PCA 将维数从 4 减少到 2。
pca = PCA(n_components=2)principal_components = pca.fit_transform(X)new_X = pd.DataFrame(data = principal_components, columns = ['PC1', 'PC2'])
让我们来看看这两个新特性。
new_X.head()
最后,我们可以使用一个 scree 图来可视化每个主成分解释的方差的百分比。
per_var = np.round(pca.explained_variance_ratio_ * 100, decimals=1)labels = ['PC' + str(x) for x in range(1, len(per_var) + 1)]plt.bar(x=range(1, len(per_var)+1), height=per_var, tick_label=labels)
plt.ylabel('percentange of explained variance')
plt.xlabel('principal component')
plt.title('scree plot')
plt.show()
最后的想法
总而言之,我们采用一个多维数据集并绘制它(虽然我们不能可视化任何大于 3 维的东西,但数学仍然会解决)。然后我们计算协方差矩阵和特征向量/特征值。后者将告诉我们哪些特征是高度相关的,并且可以在没有太大信息损失的情况下被压缩。产生的特征可用于训练我们的模型。
朴素贝叶斯分类器
Photo by Green Chameleon on Unsplash
与其他通过多次迭代来收敛到某个解决方案的机器学习算法相比,朴素贝叶斯仅基于条件概率对数据进行分类。朴素贝叶斯有以下优点:
- 训练和预测速度极快
- 可解释的
- 不需要超参数调整
在决定是否使用朴素贝叶斯时,您应该考虑朴素假设是否实际成立(在实践中非常罕见),以及您正在处理的数据是否具有很高的维数。
贝叶斯定理
很多时候,我们想知道某个事件发生的概率,假设另一个事件已经发生。这可以象征性地表示为 P(E|F)。如果两个事件不是独立的,那么这两个事件发生的概率由下面的公式表示。
例如,假设您从一副标准的 52 张牌中抽取两张牌。这副牌中一半是红色的,一半是黑色的。这些事件不是独立的,因为第二次抽签的概率取决于第一次抽签的结果。
P(E) = P(第一次抽黑牌)= 25/52 = 0.5
P(F|E) = P(第二次抽黑牌|第一次抽黑牌)= 25/51 = 0.49
利用这些信息,我们可以计算连续抽两张黑牌的概率,如下所示:
Baye 定理是条件概率最常见的应用之一。例如,baye 定理被用来计算一个在特定疾病筛查测试中呈阳性的人实际患有该疾病的概率。贝叶斯定理可以表示为:
如果你已经知道 P(A),P(B)和 P(B|A ),但想知道 P(A|B ),你可以使用这个公式。例如,假设我们正在测试一种罕见的疾病,这种疾病会感染 1%的人口。医学专家已经开发了一种高度敏感和特异的测试,但还不十分完善。
- 99%的病人测试呈阳性
- 99%的健康患者测试呈阴性
贝叶斯定理告诉我们:
假设我们有 10,000 人,100 人生病,9,900 人健康。此外,在对所有人进行测试后,我们会让 99 名病人进行测试,但也让 99 名健康人进行测试。因此,我们会以下面的概率结束。
p(生病)= 0.01
p(没病)= 1 - 0.01 = 0.99
p(+|有病)= 0.99
p(+|未患病)= 0.01
针对单个单词的垃圾邮件过滤器
朴素贝叶斯通常用于构建垃圾邮件过滤器,将电子邮件分类为垃圾邮件或 ham(非垃圾邮件)。例如,我们可能会开发一个垃圾邮件过滤器,根据某个单词的出现将一封电子邮件归类为垃圾邮件。例如,如果一封电子邮件包含单词 【伟哥】 ,我们将其归类为垃圾邮件。另一方面,如果一封电子邮件包含单词 money,那么它有 80%的可能是垃圾邮件。
根据贝叶斯定理,给定包含“单词”的邮件是垃圾邮件的概率。
虽然我们不知道分母的值,但可以用下面的公式计算出来。简单地说,找到该单词的概率是在垃圾邮件中找到该单词的概率乘以电子邮件是垃圾邮件的概率,加上在垃圾邮件中找到该单词的概率乘以电子邮件是垃圾邮件的概率。
因此,公式变为:
训练集包含足够的信息量来计算等式的右边。
p(垃圾邮件)
被归类为垃圾邮件的电子邮件数量
火腿
被归类为垃圾邮件(非垃圾邮件)的电子邮件数量
p(word|spam)
包含“单词的垃圾邮件数量
p(单词|火腿)
包含“单词”的垃圾邮件数量
结合单词的垃圾邮件过滤器
实际上,仅仅根据一个单词的出现来进行分类是不够的。有些词本身是无害的。当它们与特定的其他单词结合使用时,我们更应该将其归类为垃圾邮件。例如,根据包含单词“ 女孩 ”的事实来过滤电子邮件,最终会将与您女儿的足球队相关的电子邮件放入您的垃圾邮件文件夹中。理想情况下,我们能够针对特定的句子,如“ 你所在地区的漂亮女孩 ”。
天真的假设
通常,在我们的训练集中,我们不会有带有适当标签的准确句子。换句话说,如果我们试图确定一封包含“ 你所在地区的漂亮女孩 ”的电子邮件是否应该被归类为垃圾邮件,我们会查看我们的训练数据,看看是否有任何包含该句子的电子邮件已经被归类为垃圾邮件。如果没有,我们有两个选择,要么获取更多的数据,要么通过查看句子中的每个单词来计算给定的概率。
为了使数学更简单,我们做了简单的假设,文本中的单词是相互独立的**。换句话说,文本中包含某些单词的事实对在文本中找到给定单词的概率没有影响。然而在现实中,某些词往往会被组合在一起使用。例如,如果你在一篇关于机器学习的文章中找到单词,很可能你也会找到单词*和 训练 。*****
假定一封电子邮件同时包含单词“有吸引力的”和“女孩”,则该电子邮件包含垃圾邮件的概率可以写为:
密码
我们将从导入所需的库开始。
**from sklearn.datasets import fetch_20newsgroups
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.naive_bayes import MultinomialNB
from sklearn import metrics**
在前面的例子中,我们将使用新闻文章的语料库。幸运的是,sklearn 提供了一个简单的 API 来导入数据。
**newsgroups = fetch_20newsgroups()**
顾名思义,新闻文章分为 20 类。
**print(newsgroups.target_names)**
语料库包含超过 11,000 个文档。
**print(newsgroups.filenames.shape)**
为了了解我们在做什么,让我们打印第一个文档。
**print(newsgroups.data[0])**
为了简单起见,我们将使用类别的子集。
**categories = ['alt.atheism', 'talk.religion.misc', 'comp.graphics', 'sci.space']train_newsgroups = fetch_20newsgroups(subset='train', categories=categories)
train_X = train_newsgroups.data
train_y = train_newsgroups.targettest_newsgroups = fetch_20newsgroups(subset='test', categories=categories)
test_X = test_newsgroups.data
test_y = test_newsgroups.target**
接下来,我们使用 TfidfVectorizer 类来解析每个文档中包含的单词,并根据相关性对它们进行排序。如果你想了解更多关于 TF-IDF 是如何工作的,我会在后续文章中详细介绍。
**** [## 自然语言处理:使用 TF-IDF 的特征工程
自然语言处理(NLP)是人工智能的一个子领域,处理理解和处理…
medium.com](https://medium.com/@corymaklin/natural-language-processing-feature-engineering-using-tf-idf-e8b9d00e7e76)
vectorizer = TfidfVectorizer()
train_vectors = vectorizer.fit_transform(train_X)
test_vectors = vectorizer.transform(test_X)
我们使用多维朴素贝叶斯,因为我们试图将数据分为多个类别。与其他机器学习算法相比,朴素贝叶斯的训练过程几乎是瞬时的。
classifier = MultinomialNB()
classifier.fit(train_vectors, train_y)
我们使用 f1 分数来衡量我们模型的性能。
predictions = classifier.predict(test_vectors)score = metrics.f1_score(test_y, predictions, average='macro')
另外,我们可以写一个函数来预测一个句子属于哪一类。
def predict_category(sentence):
sentence_vector = vectorizer.transform([sentence])
prediction = classifier.predict(sentence_vector)
return train_newsgroups.target_names[prediction[0]]
正如你所看到的,这个模型正确地将这个句子归类到了计算机图形学中。
predict_category('determining the screen resolution')
最后的想法
朴素贝叶斯特别适合对具有大量特征的数据进行分类。与其他机器学习模型不同,朴素贝叶斯几乎不需要训练。当试图做出一个包含多个特征的预测时,我们通过做出天真的假设这些特征是独立的来简化数学。****
Python 中的 AdaBoost 分类器示例
Photo by Franki Chamaki on Unsplash
boosting 方法背后的一般思想是顺序训练预测器,每个预测器都试图纠正其前任。两种最常用的增强算法是 AdaBoost 和梯度增强。在接下来的文章中,我们将介绍 AdaBoost。在高层次上,AdaBoost 类似于随机森林,因为它们都汇总了森林中每个决策树所做的预测,以决定最终的分类。然而,还是有一些细微的差别。例如,在 AdaBoost 中,决策树的深度为 1(即 2 个叶子)。此外,每个决策树做出的预测对模型做出的最终预测有不同的影响。
算法
在前面的例子中,我们将使用一个数据集,该数据集根据某些特征对人进行分类。
步骤 1:初始化样品重量
在 AdaBoost 的第一步中,每个样本都与一个权重相关联,该权重指示它对于分类的重要性。最初,所有样本都具有相同的权重(1 除以样本总数)。
第二步:用每个特征建立一个决策树,对数据进行分类并评估结果
接下来,对于每个特性,我们构建一个深度为 1 的决策树。然后,我们使用每一个决策树对数据进行分类。然后,我们将每棵树的预测与训练集中的实际标签进行比较。在分类训练样本方面做得最好的特征和对应的树成为森林中的下一棵树。
例如,假设我们建立了一棵树,将聪明的人归类为有吸引力的,不聪明的人归类为没有吸引力的。
决策树错误地将一个人归类为有吸引力的人,因为他们很聪明。我们对所有的树重复这个过程,并选择错误预测最少的树。
步骤 3:计算树在最终分类中的重要性
一旦我们决定了决策树。我们用前面的公式来计算在最后的分类中它的数量。
其中总误差是错误分类样本的权重之和。
回到我们的例子,总误差等于如下。
通过将误差代入我们的公式,我们得到:
正如我们将在后面看到的,这个数字用于确定整个森林所做的预测。
步骤 4:更新样本权重,以便下一个决策树将考虑前一个决策树产生的错误
我们查看当前树分类不正确的样本,并使用以下公式增加它们的相关权重。
这里没什么特别的。我们将 e 提升到上一步中计算的显著性的幂,因为我们希望新的样本权重呈指数增长。
然后,我们查看树正确分类的样本,并使用以下公式减少它们的关联权重。
这个等式和之前的一样,只是这次我们把 e 提升到负指数的幂。
这里的要点是,先前残肢错误分类的样本应该与较大的样本权重相关联,而正确分类的样本应该与较小的样本权重相关联。
请注意,如果我们将所有样本的权重相加,我们会得到一个小于 1 的数字。因此,我们对新的样本权重进行归一化,使它们加起来等于 1。
步骤 5:形成新的数据集
我们首先创建一个与原始数据集大小相同的新的空数据集。然后,想象一个轮盘赌台,其中每个口袋对应一个样品重量。我们随机选择 0 到 1 之间的数字。每个数字所在的位置决定了我们将哪个样本放入新数据集中。
因为被错误分类的样本相对于其他样本具有更高的权重,所以随机数落入它们的分布部分的可能性更大。因此,新数据集将倾向于包含被之前的树错误分类的样本的多个副本。因此,当我们返回到评估每个决策树所做预测的步骤时,得分最高的决策树将会正确地对前一个决策树误分类的样本进行分类。
步骤 6:重复步骤 2 到 5,直到迭代次数等于超参数指定的次数(即估计数)
步骤 7:使用决策树森林对训练集之外的数据进行预测
AdaBoost 模型通过让森林中的每棵树对样本进行分类来进行预测。然后,我们根据他们的决定把树分成组。对于每个组,我们把组内每棵树的重要性加起来。森林作为一个整体所做的最终分类是由具有最大总和的组确定的。
密码
让我们看看如何在 Python 中实现 AdaBoost。首先,我们导入以下库。
from sklearn.ensemble import AdaBoostClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.datasets import load_breast_cancer
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.metrics import confusion_matrix
from sklearn.preprocessing import LabelEncoder
在这个例子中,我们将使用 AdaBoost 将肿瘤分类为恶性或良性。我们使用 scikit-learn API 将数据集导入我们的程序。
breast_cancer = load_breast_cancer()X = pd.DataFrame(breast_cancer.data, columns=breast_cancer.feature_names)
y = pd.Categorical.from_codes(breast_cancer.target, breast_cancer.target_names)
每当我们处理分类特征时,我们必须把它编码成数字。对于这个问题,我们将恶性设为 1,良性设为 0。
encoder = LabelEncoder()
binary_encoded_y = pd.Series(encoder.fit_transform(y))
我们将数据分为训练集和测试集,以评估模型的性能。
train_X, test_X, train_y, test_y = train_test_split(X, binary_encoded_y, random_state=1)
接下来,我们构建模型并使其适合训练集。max_depth=1
用于告诉我们的模型,我们希望我们的森林由具有单个决策节点和两片叶子的树组成。n_estimators
用于指定森林中的树木总数。
classifier = AdaBoostClassifier(
DecisionTreeClassifier(max_depth=1),
n_estimators=200
)classifier.fit(train_X, train_y)
我们使用我们的模型来预测肿瘤是恶性的还是良性的。
predictions = classifier.predict(test_X)
最后,我们使用混淆矩阵评估模型。该模型以 2 个假阳性和 3 个假阴性结束。
confusion_matrix(test_y, predictions)
最后的想法
像随机森林一样,AdaBoost 通过对每个样本应用多个决策树并结合各个树的预测来进行预测。然而,在 AdaBoost 算法中,每个决策树对最终预测的贡献是不同的,而不是取森林中每个决策树所做预测的平均值(或分类情况下的大多数)。
梯度推进决策树算法讲解
Photo by NeONBRAND on Unsplash
在接下来的文章中,我们将看看如何在 Python 中实现渐变增强。梯度增强类似于 AdaBoost,因为它们都使用决策树的集合来预测目标标签。然而,与 AdaBoost 不同,梯度增强树的深度大于 1。在实践中,您通常会看到梯度增强的最大叶子数在 8 到 32 之间。
算法
在我们深入研究代码之前,重要的是我们要理解梯度增强算法是如何实现的。假设,我们试图根据房子的年龄、面积和位置来预测房子的价格。
步骤 1:计算目标标签的平均值
当处理回归问题时,我们从一片叶子开始,它是我们想要预测的变量的平均值。在接下来的步骤中,这一页将用作接近正确解决方案的基线。
第二步:计算残差
对于每个样本,我们用下面的公式计算残差。
残差=实际值-预测值
在我们的示例中,预测值等于上一步中计算的平均值,实际值可以在每个样本的 price 列中找到。计算残差后,我们得到下表。
步骤 3:构建决策树
接下来,我们构建一棵树,目标是预测残差。换句话说,每片叶子将包含一个关于残差值的预测(不是期望的标签)。
如果残差比叶子多,一些残差将在同一个叶子中结束。当这种情况发生时,我们计算它们的平均值,并将其放入叶子中。
这样,树就变成了:
步骤 4:使用集合中的所有树预测目标标签
每个样本通过新形成的树的决策节点,直到它到达给定的线索。所述叶中的残差用于预测房价。
通过实验表明,朝着解决方案采取小的增量步骤可以实现具有较低总体方差的可比偏差(较低的方差导致训练数据之外的样本具有更好的准确性)。因此,为了防止过度拟合,我们引入了一个叫做学习率的超参数。当我们做一个预测时,每个残差都要乘以学习率。这迫使我们使用更多的决策树,每一棵都向最终解决方案迈出一小步。
步骤 5:计算新的残差
我们通过从上一步的预测中减去实际房价来计算一组新的残差。如步骤 3 所述,残差将用于下一个决策树的叶子。
步骤 6:重复步骤 3 到 5,直到迭代次数与超参数指定的次数(即估计数)相匹配
步骤 7:一旦训练完毕,使用集合中的所有树对目标变量的值进行最终预测
最终预测将等于我们在第一步中计算的平均值,加上组成森林的树木预测的所有残差乘以学习率。
密码
在本教程中,我们将使用来自 scikit-learn 库中的GradientBoostingRegressor类。
from sklearn.ensemble import GradientBoostingRegressor
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error
from sklearn.datasets import load_boston
from sklearn.metrics import mean_absolute_error
对于前面的示例,我们将使用波士顿房价数据集。
boston = load_boston()
X = pd.DataFrame(boston.data, columns=boston.feature_names)
y = pd.Series(boston.target)
为了评估我们模型的性能,我们将数据分为训练集和测试集。
X_train, X_test, y_train, y_test = train_test_split(X, y)
接下来,我们构建并拟合我们的模型。max_depth
是指每棵树的叶子数量(即 4 片),而n_estimators
是指集合中树的总数。如前所述,learning_rate
超参数缩放每棵树的贡献。如果将其设置为较低的值,集合中将需要更多的树来适应训练集,但总体方差会更低。
regressor = GradientBoostingRegressor(
max_depth=2,
n_estimators=3,
learning_rate=1.0
)
regressor.fit(X_train, y_train)
staged_predict()
方法测量每个训练阶段的验证误差(即一棵树、两棵树……),以找到最佳的树数。
errors = [mean_squared_error(y_test, y_pred) for y_pred in regressor.staged_predict(X_test)]best_n_estimators = np.argmin(errors)
现在,我们可以使用最佳数量的树来构建和拟合我们的模型。
best_regressor = GradientBoostingRegressor(
max_depth=2,
n_estimators=best_n_estimators,
learning_rate=1.0
)
best_regressor.fit(X_train, y_train)
Sklearn 提供了许多指标来评估我们的机器学习模型的性能。我发现特别有用的是,他们根据适用的问题领域对每个指标进行分类。例如,精度只在分类的上下文中有意义。
https://scikit-learn.org/stable/modules/model_evaluation.html
我们使用平均绝对误差,它可以解释为预测值和实际值之间的平均距离。
y_pred = best_regressor.predict(X_test)mean_absolute_error(y_test, y_pred)
ARIMA 模型 Python 示例-时间序列预测
https://www.pexels.com/photo/white-printer-paper-590011/
基于历史观察做出预测的能力创造了竞争优势。例如,如果一个组织有能力更好地预测一种产品的销售量,它将在优化库存水平方面处于更有利的地位。这可以增加组织现金储备的流动性,减少营运资本,并通过减少积压订单来提高客户满意度。
在机器学习领域,有一组特定的方法和技术特别适合于根据时间预测因变量的值。在接下来的文章中,我们将讨论自回归综合移动平均(ARIMA)。
我们将按时间顺序索引(或绘制)的一系列数据点称为时间序列。时间序列可以分解成 3 个部分。
- 趋势:向上&数据在很长一段时间内随时间的向下移动(即房屋升值)
- 季节性:季节性差异(即夏季对冰淇淋的需求增加)
- 噪声:尖峰信号&随机间隔的低谷信号
https://commons.wikimedia.org/wiki/File:Mae.timeseries_decomposition.commonswiki.svg
在对时间序列应用任何统计模型之前,我们希望确保它是平稳的。
数据是静止的意味着什么?
序列的平均值不应该是时间的函数。下面的红色图表不是静止的,因为平均值会随着时间的推移而增加。
序列的方差不应该是时间的函数。这种性质称为同质性。请注意红色图表中数据随时间变化的分布。
最后,第(i+m)项的第 I 项的协方差不应该是时间的函数。在下图中,你会注意到随着时间的增加,传播变得越来越近。因此,对于红色系列,协方差随时间不是常数。
如果一个时间序列是平稳的,并且在给定的时间间隔内具有特定的行为,那么可以有把握地假设它在以后的某个时间点将具有相同的行为。大多数统计建模方法假设或要求时间序列是平稳的。
密码
statsmodels
库提供了一套处理时间序列数据的函数。
import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
from statsmodels.tsa.stattools import adfuller
from statsmodels.tsa.seasonal import seasonal_decompose
from statsmodels.tsa.arima_model import ARIMA
from pandas.plotting import register_matplotlib_converters
register_matplotlib_converters()
我们将使用一个包含某一天飞机乘客数量的数据集。
df = pd.read_csv('air_passengers.csv', parse_dates = ['Month'], index_col = ['Month'])df.head()plt.xlabel('Date')
plt.ylabel('Number of air passengers')
plt.plot(df)
如前所述,在我们建立模型之前,我们必须确保时间序列是平稳的。有两种主要方法来确定给定时间序列是否是平稳的。
- 滚动 统计:绘制滚动平均值和滚动标准差。如果时间序列随时间保持不变,则时间序列是静止的(用肉眼观察这些线是否是直的并且平行于 x 轴)。
- 扩展的 Dickey-Fuller 检验:如果 p 值较低(根据零假设),并且 1%、5%、10%置信区间的临界值尽可能接近 ADF 统计值,则认为时间序列是平稳的
对于那些不理解平均价格和滚动平均价格之间区别的人来说,10 天的滚动平均价格是作为第一个数据点的前 10 天的收盘价的平均值。下一个数据点将删除最早的价格,添加第 11 天的价格并取平均值,依此类推,如下所示。
rolling_mean = df.rolling(window = 12).mean()
rolling_std = df.rolling(window = 12).std()plt.plot(df, color = 'blue', label = 'Original')
plt.plot(rolling_mean, color = 'red', label = 'Rolling Mean')
plt.plot(rolling_std, color = 'black', label = 'Rolling Std')
plt.legend(loc = 'best')
plt.title('Rolling Mean & Rolling Standard Deviation')
plt.show()
如您所见,滚动平均值和滚动标准差随着时间的推移而增加。因此,我们可以得出结论,时间序列不是平稳的。
result = adfuller(df['Passengers'])print('ADF Statistic: {}'.format(result[0]))
print('p-value: {}'.format(result[1]))
print('Critical Values:')
for key, value in result[4].items():
print('\t{}: {}'.format(key, value))
ADF 统计值远离临界值,p 值大于阈值(0.05)。因此,我们可以得出结论,时间序列不是平稳的。
取因变量的对数是降低滚动平均值增长率的简单方法。
df_log = np.log(df)
plt.plot(df_log)
让我们创建一个函数来运行这两个测试,以确定给定的时间序列是否是平稳的。
def get_stationarity(timeseries):
# rolling statistics
rolling_mean = timeseries.rolling(window=12).mean()
rolling_std = timeseries.rolling(window=12).std()
# rolling statistics plot
original = plt.plot(timeseries, color='blue', label='Original')
mean = plt.plot(rolling_mean, color='red', label='Rolling Mean')
std = plt.plot(rolling_std, color='black', label='Rolling Std')
plt.legend(loc='best')
plt.title('Rolling Mean & Standard Deviation')
plt.show(block=False)
# Dickey–Fuller test:
result = adfuller(timeseries['Passengers'])
print('ADF Statistic: {}'.format(result[0]))
print('p-value: {}'.format(result[1]))
print('Critical Values:')
for key, value in result[4].items():
print('\t{}: {}'.format(key, value))
我们可以对时间序列进行多种变换,使其保持平稳。例如,我们减去滚动平均值。
rolling_mean = df_log.rolling(window=12).mean()
df_log_minus_mean = df_log - rolling_mean
df_log_minus_mean.dropna(inplace=True)get_stationarity(df_log_minus_mean)
我们可以看到,减去均值后,滚动均值和标准差是近似水平的。p 值低于阈值 0.05,ADF 统计值接近临界值。因此,时间序列是平稳的。
应用指数衰减是另一种转换时间序列使其稳定的方法。
rolling_mean_exp_decay = df_log.ewm(halflife=12, min_periods=0, adjust=True).mean()
df_log_exp_decay = df_log - rolling_mean_exp_decay
df_log_exp_decay.dropna(inplace=True)get_stationarity(df_log_exp_decay)
指数衰减比减去滚动平均值表现更差。然而,它仍然比原来更稳定。
让我们再尝试一种方法来确定是否存在更好的解决方案。当应用时移时,我们用前一个点减去每个点。
空、(x1 x0)、(x2 x1)、(x3 x2)、(x4 x3)、……、(xn xn 1)
df_log_shift = df_log - df_log.shift()
df_log_shift.dropna(inplace=True)get_stationarity(df_log_shift)
时间偏移的效果不如减去滚动平均值。然而,它仍然比原来更稳定。
自回归模型
自回归模型在过去的值对当前值有影响的前提下运行。AR 模型通常用于分析自然、经济和其他时变过程。只要假设成立,我们就可以建立一个线性回归模型,根据前几天的值,尝试预测因变量今天的值。
AR 模型的阶数对应于公式中包含的天数。
移动平均模型
假设当天因变量的值取决于前一天的误差项。该公式可以表示为:
你还会遇到这样的等式:
其中μ是级数的平均值, θ 1、…、 θq 是模型的参数, εt 、εt—1、…、εt—q 是白噪声误差项。 q 的值称为 MA 模型的阶数。
自回归移动平均
ARMA 模型是 AR 和 MA 模型的简单组合。
自回归综合移动平均模型(ARIMA)
ARIMA(又名 Box-Jenkins)模型增加了 ARMA 模型的差异。差分从以前的值中减去当前值,可用于将时间序列转换为静态时间序列。例如,一阶差分处理线性趋势,并采用转换zi = yi — yi-1
。二阶差分处理二次趋势,并采用一阶差分的一阶差分,即zi = (yi — yi-1) — (yi-1 — yi-2)
,等等。
三个整数(p,d,q)通常用于参数化 ARIMA 模型。
- p:自回归项数(AR 顺序)**
- d:非季节性差异数(差异顺序)**
- 问:移动平均线数量(MA 顺序)**
自相关函数
当前时间点的观测值与所有先前时间点的的观测值之间的相关性。我们可以使用 ACF 来确定 MA 项的最佳数量。术语的数量决定了模型的顺序。
部分自相关函数(PACF)
顾名思义,PACF 是 ACF 的一个子集。PACF 表示在两个时间点进行的观察之间的相关性,同时考虑来自其他数据点的任何影响。我们可以使用 PACF 来确定在 AR 模型中使用的最佳项数。术语的数量决定了模型的顺序。
让我们看一个例子。回想一下,PACF 可以用来计算 AR 模型的最佳阶数。水平蓝色虚线代表显著性阈值。垂直线代表在时间点的 ACF 和 PACF 值。只有超过水平线的垂直线被认为是显著的。
因此,我们将在自回归方程中使用前两天。
回想一下,ACF 可以用来计算 MA 模型的最佳阶数。
因此,我们在移动平均方程式中只使用昨天。
回到我们的例子,我们可以用 2 阶 AR、1 阶差分和 2 阶 MA 来创建和拟合 ARIMA 模型。
decomposition = seasonal_decompose(df_log)
model = ARIMA(df_log, order=(2,1,2))
results = model.fit(disp=-1)
plt.plot(df_log_shift)
plt.plot(results.fittedvalues, color='red')
然后,我们可以看到该模型如何与原始时间序列进行比较。
predictions_ARIMA_diff = pd.Series(results.fittedvalues, copy=True)
predictions_ARIMA_diff_cumsum = predictions_ARIMA_diff.cumsum()
predictions_ARIMA_log = pd.Series(df_log['Passengers'].iloc[0], index=df_log.index)
predictions_ARIMA_log = predictions_ARIMA_log.add(predictions_ARIMA_diff_cumsum, fill_value=0)
predictions_ARIMA = np.exp(predictions_ARIMA_log)
plt.plot(df)
plt.plot(predictions_ARIMA)
假设我们有过去 12 年每个月的数据,并希望预测未来 10 年的乘客数量,我们使用(12 x12)+ (12 x 10) = 264。
results.plot_predict(1,264)
最后的想法
在机器学习的领域中,有一套操作和解释依赖于时间的变量的技术。其中包括 ARIMA,它可以删除趋势成分,以准确预测未来值。
机器学习,第 2 部分:监督学习
Image by the author
机器学习基础
介绍
我们在第一部分讨论了基本的、通用的机器学习概念。现在我们转向机器学习问题,这里我们有一个带标签的数据集的好处——我们知道所有输入示例的期望输出值。有两个主要的监督问题:分类和回归。
监督分类法
监督分类可能是最常用的机器学习技术。顾名思义,它是“受监督的”:它利用已标记的训练集来建立逻辑,然后最终将该逻辑用于未标记的数据。
它解决的问题是分类。分类是将每个训练样本分配到不同的类别。一个类本质上是一个个体例子的特征(就像一个动物的种类),有一些特殊的条件。具体来说,类的数量是有限的,并且我们知道并且拥有我们期望分类的所有类的例子。如果我们有一个没有训练例子的班级,我们就不知道在分类的时候要找什么。每个例子只属于一个类。我们不能说一个例子属于不属于类,同样,我们也不能把它归为多于一类。
给定一个这样的问题,我们如何找到一个逻辑来将项目分类?我们通常寻找符合两个标准的预测值:1)同一类中的所有示例都具有与该类中的其他示例相似的属性值。2)同一类中的所有示例都具有与不同类中的示例不同的属性值。
监督分类算法对数据使用统计方法,并寻找其值与特定类别不同的特征(或特征组合)。独特的值实现了上述两个目标:它们将一个类的项目分组,并将其他类的项目分开。
例子
假设我们在一个园艺中心工作,在那里我们种植两种植物,百日菊和矮牵牛。该中心的所有者刚刚购买了一台机器,它可以测量三样东西:植物的height
和color
,以及土壤的ph
水平。他们聘请我们编写一个程序,根据这些测量值自动区分这两种植物。
由于这是一个监督问题,我们得到了一个包含这三个预测值的数据集,所有的例子都标有species
。不要深入任何特定算法的细节,让我们只考虑如果要求手动操作,我们将如何解决这个问题。
或许我们可以从一些统计数据开始。具体来说,我们将数据分为百日菊和矮牵牛,并查看每组的汇总统计数据。希望在这些汇总统计数据中,我们能找到以下值:1)同类花之间的相似值,2)牵牛花和百日菊之间的不同值,以及 3)足够不同的值,我们可以用它们来区分两者。
在此过程中,我们发现了一些值得注意的事情。首先,土壤ph
似乎和species
没有任何关系,最好忽略掉。这并不是说ph
完全没用。如果我们试图回答一个不同的问题,如植物的健康,这样的数据点可能是有用的,但对于我们分离物种的问题来说,它是没有用的。
其他功能更好。就目前而言,百日菊几乎总是超过 12 英寸高,牵牛花几乎总是低于 12 英寸。也许最有用的是,牵牛花总是红色、紫色或白色,而百日菊总是红色、橙色或黄色。
有了这些信息,我们可以设计一个简单的分类器。如果一朵花是白色或紫色的,那它就是矮牵牛花。橙色或黄色的花是百日菊。对于红色的花来说,如果 T9 大于 12”,它可能是百日菊,如果它小于 12”,它可能是矮牵牛。我们不能完全有把握地区分红花,但这种方法在大多数情况下是正确的。使用这套简单的规则,我们只用最少量的信息就能得到非常准确的分类器。
每种机器学习分类算法的方法都不同,但其中一些算法执行的步骤几乎与我们刚刚做的完全相同。决策树算法寻找将数据分成比前一组更“纯净”的组的方法。即使不理解它背后的确切术语或数学,这也是我们已经做的:我们发现使用color
允许我们生成几个完全纯的组。最后一组,红色的花,不能使用任何属性完全纯,但height
得到最接近完美的分离。
从这个例子中需要记住的一件重要事情是,标签对我们的过程至关重要。如果没有标签,我们可能会意识到有高的和矮的花,甚至可以认识到黄色的花通常是高的。然而,如果没有标签,我们无法确切地说出那群高大的黄色花朵意味着什么。
监督回归
在监督回归中,就像在监督分类中一样,我们有一个可用于改进模型的标注数据集。分类和回归的不同之处在于输出的类型,或者说“响应”在回归分析中,答案是一个数字,这个区别比可能立即显现的差异更大。首先,让我们来谈谈如何识别回归问题,作为一个数字的回答是一个很大的线索,但是有可能有一个数字的回答是而不是回归问题。**
在回归中,响应是一个数字,可以像数字一样对待。我们可以用它来做数学运算,较大的值和较小的值相比意味着什么。此时你可能会问“什么样的数字不能像数字一样处理?”这种情况最常见的例子是当数字被用作 id 或类标签时。**
例如,以邮政编码 80123 和 60652 为例。80123 变大意味着什么吗?一点也不,它只是科罗拉多州一个地方的数字代码,而 60652 是伊利诺伊州。同样,如果我们减去这两个,我们将得到 19471。巧合的是,这是宾夕法尼亚州的一个邮政编码,但它没有任何实际意义。没有公式或说明来计算邮政编码。
除此之外,你看到的大多数数字都像数字一样。如果我们看两栋价格分别为 40 万美元和 20 万美元的房子:40 万美元越大,意味着房子越值钱,具体来说,我们可以用 40 万美元/20 万美元(即:用它们做数学计算)找到 2 倍多的房子。我们也可以通过取$400K-$200K = $200K
来找出价格的差异。乘法$400K*$200K
呢?这实际上并没有给我们一个有意义的输出,但没关系,不是每个操作者都必须给出有意义的输出。
所以回归反应首先是一个数字。我们稍后会谈到为什么这很重要。回归问题的第二个要求是响应是连续的 T2。在实际意义上,这意味着三件事:有无限多的响应,任何一组输入都应该导致有效的输出,类似地,任何有效的输出都有一组输入会导致有效的输出。连续输出使得这个问题与分类如此不同。
回想一下,在分类中,我们说过类是有限的,并且每个类都有一个例子。在回归中,可能的响应数量可以是无限个,自然,我们不会有这些输出的例子。
如何使用有限数量的训练样本来预测潜在的无限数量的输出?如果我们继续使用监督分类中的假设,这是不可能的,因为在分类中,我们需要总结单个输出的所有示例,以寻找共同因素。
那么,我们需要的是一套新的关于问题如何工作的假设,允许处理无限数量的可能输出。在回归中,核心假设是被解决的问题包含趋势并且预测器和响应具有函数关系。换句话说,趋势可以用一个数学函数来描述,利用这个函数,我们可以预测任何输入的任何输出值,而不仅仅是我们之前已经看到的组合。如果我们可以在训练数据的帮助下近似这个函数,那么我们已经使用了有限的数据来总结无限数量的输出。
例子
这很容易通过例子看出。考虑下面的数据,它描述了相对于房子大小的价格:
A simple regression dataset
一栋 2000 平方英尺的房子价格是多少?…
如果你说 200,000 美元,那么恭喜你,你已经为一个我们没有数据的输入值预测了一个我们从未见过的输出值。尽管这一壮举令人印象深刻,但它可能并不觉得很难。人类可能不像我们一样擅长识别趋势和关系,但对我们来说仍然相当直观,在这个例子中,趋势非常明显。
至于你是如何做出评估的,你可能是通过两种方式中的一种来完成的。第一,你意识到价格只是平方英尺乘以 100 美元,然后算了一下。第二,你注意到 2000 平方英尺介于 1500 和 2500 之间,于是你选择了介于这两个价格之间的价格,即 20 万美元。
这两种方法都可行,而且实际上都得到了相同的基本概念——我们的预测可以通过在由下式定义的直线上找到一个点来生成:
price = sqft * 100
此外,一旦我们有了这个等式,我们就可以为sqft
的任意值生成一个预测。回归就是要找到这些方程,或者更具体地说,是要找到与预测值相关的一组系数。系数可以解释为将预测值增加 1 的效果。这里我们只有一个预测器,sqft
,它的系数是100
。因此,如果我们将sqft
值增加 1,我们预计价格会上涨$100
。
让我们看一个更复杂的例子。这可以用纸和笔来解决,但显然比上一个要困难得多。
A more complex regression dataset
你可以试着自己解决这个问题。看看两栋房子之间只有一点不同的例子会特别有帮助。
系数的正确值为:
- 每平方英尺 75 美元
- 每间卧室 1 万美元
- 每个浴室 5000 美元
- 所有房屋的固定费用为 50,000 美元
您可能会认为这些系数的值本身就很有趣。你不会是第一个;这一观察导致了回归分析领域的出现,在该领域,关注的重点不是生成最准确的预测,而是找到最准确的系数。
你有没有看到过这样的广告或新闻:“获得这个学位可以为你的工资每年增加 10,000 美元!”?这个数字(希望)是通过回归分析计算出来的,用包括degree_earned
在内的多个预测因子预测yearly_income
,发现该学位的系数值大约为 10,000 美元。换句话说,如果两个人之间的唯一区别是一个人有学位,而另一个人没有,那么模型预测有学位的人会多挣大约 1 万美元。
回归分析本身是一个深入而广泛的领域。生成良好的系数估计需要很多东西,我们没有时间在这里讨论,但我想提到它,因为它是一种非常有用和广泛使用的方法,值得进一步研究。
到目前为止,明显缺少的是对计算机如何找到这些系数值的解释。原因是,答案远不如监督分类那么直接,并且涉及大量的高等数学,我不想在介绍性的帖子中深入讨论。
然而,简单的版本是我们定义一个叫做成本函数的函数,它告诉我们我们的预测有多远。在成本函数中,值越低越好,因此目标是找到成本函数的最低可能值。在有噪声的数据集中,该值将而不是为零,因为不是所有的点都可以完美拟合。
在此之后,主要有两种方法。使用线性代数可以(当数据集不太大时)直接使用正规方程找到最小化成本函数的系数值。不然可以用渐变下降更直观一点。
本质上,梯度下降是利用微积分寻找成本更低的方向。换句话说,我们是否需要提高或降低一个给定的系数来制作一个更好的模型?通过找到这些“梯度”,并在每一步将系数在这些方向上移动一小段,我们逐渐将模型移动得越来越接近最佳系数。经过(通常)数千次迭代,我们的模型“收敛”在最优值上。
更简单地说,梯度下降的诀窍是,虽然我们不知道最佳系数,但我们知道如何建立一个比我们当前模型略好的模型。通过一遍又一遍地重复这个小的改进,我们最终得到了一个我们无法改进的模型,我们知道我们已经达到了最佳状态。**
结论
监督分类和回归涵盖了大量的机器学习问题。监督分类本身可能是最常见的最大似然问题,如果监督回归排在第二位,我也不会感到惊讶。特别是分类,有一系列令人眼花缭乱的算法可以用来实现这一点,虽然我们没有在这里涵盖其中的绝大多数,但它们都遵循相同的基本逻辑,即在数据和标签中寻找模式之间的联系。接下来我们讨论无监督学习,我们仍然在寻找模式,但我们不再有标签来帮助指导我们对这些模式的解释。
Keras 中的神经网络脱层解释
https://www.pexels.com/photo/colleagues-looking-at-survey-sheet-3183153/
机器学习最终用于在给定一组特征的情况下预测结果。因此,我们可以做的任何概括模型性能的事情都被视为净收益。放弃是一种用于防止模型过度拟合的技术。Dropout 的工作原理是在训练阶段的每次更新时,将隐藏单元(组成隐藏层的神经元)的输出边缘随机设置为 0。如果你看一下 Keras 关于辍学层的文档,你会看到一个由 Geoffrey Hinton 和 friends 撰写的白皮书的链接,该白皮书探讨了辍学背后的理论。
密码
在前面的例子中,我们将使用 Keras 构建一个神经网络,目标是识别手写数字。
from keras.datasets import mnist
from matplotlib import pyplot as plt
plt.style.use('dark_background')
from keras.models import Sequential
from keras.layers import Dense, Flatten, Activation, Dropout
from keras.utils import normalize, to_categorical
我们使用 Keras 将数据导入我们的程序。数据已经分为训练集和测试集。
(X_train, y_train), (X_test, y_test) = mnist.load_data()
让我们看看我们在做什么。
plt.imshow(x_train[0], cmap = plt.cm.binary)
plt.show()
在我们完成模型的训练后,它应该能够识别前面的图像为 5。
我们必须事先进行一点预处理。我们将像素(特征)归一化,使它们的范围从 0 到 1。这将使模型更快地收敛到一个解。接下来,我们将给定样本的每个目标标签转换为 1 和 0 的数组,其中数字 1 的索引表示图像代表的数字。我们这样做是因为,否则我们的模型会将数字 9 解释为比数字 3 具有更高的优先级。
X_train = normalize(X_train, axis=1)
X_test = normalize(X_test, axis=1)
y_train = to_categorical(y_train)
y_test = to_categorical(y_test)
没有辍学
在将二维矩阵输入神经网络之前,我们使用一个展平层,通过将每个后续行附加到其前面的行,将其转换为一维数组。我们将使用两个由 128 个神经元组成的隐藏层和一个由 10 个神经元组成的输出层,每个神经元代表 10 个可能的数字中的一个。softmax 激活函数将返回样本代表给定数字的概率。
model = Sequential()
model.add(Flatten(input_shape=(28, 28)))
model.add(Dense(128))
model.add(Activation('relu'))
model.add(Dense(128))
model.add(Activation('relu'))
model.add(Dense(10))
model.add(Activation('softmax'))model.summary()
因为我们试图预测类别,所以我们使用分类交叉熵作为损失函数。我们将使用准确性来衡量模型的性能。
model.compile(
loss='categorical_crossentropy',
optimizer='adam',
metrics=['accuracy']
)
我们留出 10%的数据进行验证。我们将用它来比较一个模型在有和没有辍学的情况下过度适应的趋势。批量大小为 32 意味着在通过神经网络传递 32 个样本后,我们将计算梯度并在梯度方向上迈出一步,其幅度等于学习速率。我们总共这样做 10 次,具体次数由历元数决定。
history = model.fit(
X_train,
y_train,
epochs=10,
batch_size=32,
validation_split=0.1,
verbose = 1,
shuffle=True
)
我们可以通过使用由 fit 函数返回的历史变量来绘制每个时期的训练和验证精度。
loss = history.history['loss']
val_loss = history.history['val_loss']
epochs = range(1, len(loss) + 1)
plt.plot(epochs, loss, 'y', label='Training loss')
plt.plot(epochs, val_loss, 'r', label='Validation loss')
plt.title('Training and validation loss')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend()
plt.show()
正如你所看到的,在没有丢失的情况下,验证损耗在第三个时期后停止下降。
acc = history.history['acc']
val_acc = history.history['val_acc']
plt.plot(epochs, acc, 'y', label='Training acc')
plt.plot(epochs, val_acc, 'r', label='Validation acc')
plt.title('Training and validation accuracy')
plt.xlabel('Epochs')
plt.ylabel('Accuracy')
plt.legend()
plt.show()
如您所见,在没有丢失的情况下,验证精度往往在第三个历元左右趋于平稳。
使用这个简单的模型,我们仍然能够获得超过 97%的准确率。
test_loss, test_acc = model.evaluate(X_test, y_test)
test_acc
拒绝传统社会的人
关于 dropout 应该放在 activation 函数之前还是之后还有一些争论。根据经验,对于除之外的所有激活功能,将 dropout 放在 activate 功能之后。在传递 0.5 时,每个隐藏单元(神经元)以 0.5 的概率被设置为 0。换句话说,有 50%的变化,给定神经元的输出将被强制为 0。
*model_dropout = Sequential()
model_dropout.add(Flatten(input_shape=(28, 28)))
model_dropout.add(Dense(128))
model_dropout.add(Dropout(0.5))
model_dropout.add(Activation('relu'))
model_dropout.add(Dense(128))
model_dropout.add(Dropout(0.5))
model_dropout.add(Activation('relu'))
model_dropout.add(Dense(10))
model_dropout.add(Activation('softmax'))model_dropout.summary()*
同样,由于我们试图预测类别,我们使用分类交叉熵作为损失函数。
*model_dropout.compile(
loss='categorical_crossentropy',
optimizer='adam',
metrics=['accuracy']
)*
通过提供验证分割参数,模型将分离训练数据的一部分,并将在每个时期结束时评估该数据的损失和任何模型度量。如果 dropout 背后的前提成立,那么我们应该会看到与以前的模型相比,验证准确性有显著的不同。洗牌参数将在每个时期之前洗牌训练数据。
*history_dropout = model_dropout.fit(
X_train,
y_train,
epochs=10,
batch_size=32,
validation_split=0.1,
verbose = 1,
shuffle=True
)*
如您所见,验证损失明显低于使用常规模型获得的损失。
*loss = history_dropout.history['loss']
val_loss = history_dropout.history['val_loss']
epochs = range(1, len(loss) + 1)
plt.plot(epochs, loss, 'y', label='Training loss')
plt.plot(epochs, val_loss, 'r', label='Validation loss')
plt.title('Training and validation loss')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend()
plt.show()*
正如您所看到的,该模型收敛得更快,并在验证集上获得了接近 98%的准确性,而之前的模型在第三个时期左右达到稳定。
*acc = history_dropout.history['acc']
val_acc = history_dropout.history['val_acc']
plt.plot(epochs, acc, 'y', label='Training acc')
plt.plot(epochs, val_acc, 'r', label='Validation acc')
plt.title('Training and validation accuracy')
plt.xlabel('Epochs')
plt.ylabel('Accuracy')
plt.legend()
plt.show()*
在测试集上获得的准确性与从没有丢失的模型中获得的准确性没有太大的不同。这很可能是由于样本数量有限。
*test_loss, test_acc = model_dropout.evaluate(X_test, y_test)
test_acc*
最后的想法
Dropout 可以通过将给定神经元的输出随机设置为 0 来帮助模型泛化。在将输出设置为 0 时,成本函数对改变反向传播过程中权重更新方式的相邻神经元变得更加敏感。
机器学习,第 3 部分:无监督学习
Image by the author
机器学习基础
介绍
在无监督学习中,我们被给予一个未标记的数据集来分析。就像在监督学习中,我们在这些数据中发现模式,但是没有标签,我们不一定能解释这些模式。相反,无监督学习利用了关于数据模式的假设:像聚类、相关性和异常值这样的东西都代表了一些重要的东西,即使我们并不立即知道那是什么。我们将在这里讨论两个最常见的无监督问题:聚类和离群点分析。
使聚集
聚类有时被称为“无监督分类”,我对这个术语有一种复杂的感觉,原因我将很快介绍,但它对这个问题提供了足够好的解释,值得介绍。
首先,问题是无监督的——我们不会有一个带标签的数据集来指导我们的逻辑。其次,我们希望根据预测因素将项目分成类(从技术上讲,它们不是预测因素,它们在这里是“特征”,因为没有响应)。不同之处在于,在监督分类中,类结构是已知的并被标记,而在聚类中,我们仅从特征值发明类结构。
如何处理这个问题?在监督分类中,我们使用标签来挑选出一个类,并寻找具有两种品质的预测值:1)它们对于该类的每个示例都具有相当共同的值,2)它们将该类与其他类分开。
在集群中,我们基本上反过来执行这个过程。我们正在寻找基于特征值的点组,这些点 1)彼此相似,2)与其余数据不同。在足够简单的数据集中,像这样的组显示为点的簇,因此得名。
基本的想法是,如果我们能够识别这些彼此相似而与其他点不相似的点群,那么我们就可能识别出了数据中的一些潜在结构。换句话说,即使没有标签,我们仍然希望识别数据中的类结构。
例子
在关于监督分类的文章中,我们考虑了花的数据。在那个数据集中,我们有zinnia
朵花,它们通常高于 12 英寸,可能是红色、橙色或黄色。我们还有一般比 12 英寸短的花,可以是紫色、白色或红色。
想象一下在没有任何species
标签的情况下将这些数据可视化。从数据上看还是很明显的,有一簇矮的例子,也有一簇高的例子。我们可以合理地假设这两个集群代表不同的类。在这种情况下,我们知道假设是正确的。
从人类的角度来看,我们可能会直观地解决简单的聚类问题(3 维或更少的数据)——实际上是在我们的数据中寻找点的聚类。计算机做不到这一点,那么我们如何用计算机可以处理的方式来处理这个问题呢?IE:我们如何用数学方法解决这个问题?
所有聚类算法都利用了一个叫做距离函数或距离度量的概念,它测量两点之间的距离。一个常见而简单的距离度量是曼哈顿距离,它只是两个观察值(每个特征)之间差异的绝对值之和。例如,假设我们有:
A
和B
之间的距离是:
abs(16-6) + abs(12 -6) = 16
而A
和C
之间的距离为 2。从这些距离可以明显看出A
比B
更像C
。即使没有数学,光看表格就能直观地看出这一点。聚类算法都使用这样的距离度量来寻找相似的点。从这里开始,就要决定如何将相似的点分成不同的簇。不同的算法以不同的方式处理这一步,我们没有时间去深入研究它们,但是我们可以涵盖流行的 k-means 算法。
在 k-means 中,数据科学家必须首先选择一些聚类。然后,我们将那个数量的质心插入到数据中,以表示每个聚类的中心。形心只是一个代表群集精确中心的点。放置质心可以完全随机进行,也可以使用随机元素。从这里开始,我们循环如下:
- 对于每个点,测量到所有质心的距离,并将该点指定给最近的质心。一个聚类由分配给该质心的所有点定义。
- 在分配点之后,质心可能不再位于簇中所有点的实际中心。因此,我们取聚类中所有点的平均值,并将质心移动到该位置,这就是聚类的实际中心。
- 因为我们已经移动了质心,所以一些点可能更靠近不同的质心,而不是它们最初被指定的质心。换句话说,一些点可能已经移动到不同的集群。在这种情况下,我们将所有的点重新分配到最近的质心,并跟踪有多少点改变了聚类。
- 如果任何点在步骤 3 中改变了聚类,那么质心不会都在它们各自聚类的精确中心,所以我们循环回到步骤 2 并继续该过程。如果没有点改变聚类,那么从现在开始什么都不会改变,并且算法已经完成。
K-means 是一种在数据中创建聚类的简单而直观的方法。它确实有两个缺点:首先,被要求选择集群的数量使它容易出错。事实上,我们使用集群意味着我们不知道有多少类,所以这是一个非常试错的过程。
第二,质心的随机放置会导致最终出现一组不同的簇。专业术语是算法是非确定性 — 它可以对同一个问题给出不同的答案。这又一次增加了试错的因素,使得聚类算法的最终输出不如数据科学家理想的精确。
“聚类”与“无监督分类”
前面我说过我不喜欢用“无监督分类”这个术语来描述聚类,让我们来解释一下为什么。聚类背后的逻辑基本上是“如果它看起来像一个类,它可能是一个类”,但有大量的情况下,聚类版本的“类”和监督分类版本的“类”是非常不同的。
在监督分类中,我们知道有一个潜在的类结构,我们知道那些类是什么,我们有每一个类的例子。在集群中,我们只怀疑有一个底层的类结构,我们通常不知道它是如何构造的。毕竟,如果我们确切地知道类是什么,我们就可以标记数据集并使用监督分类来代替。
在我们上面的花的例子中,很明显我们有两组花,由高度分开。然而,当我们考虑花的颜色时,事情就变得更棘手了。我们是不是应该把所有的短白花都分到它们自己的簇里?那些高高的橙色的怎么样?红色的花可以是高的和矮的,那么哪一个更重要,是花的颜色相同还是它们的高度相似?在我们介绍的 k-means 算法中,我们必须选择要创建的聚类数。在 flower 示例中,k=2
和k=6
都工作得很好,但是像k=3
这样的东西会导致非常奇怪的输出。在实际问题中,不像在我们的花的例子中,我们不知道潜在的模式是什么,所以选择k
变得不那么明显。
所以很多聚类归结于对数据的底层和未知结构的有根据的猜测。仅仅因为我们生成了一组集群,难道不就意味着它们代表了底层的类结构,在某些情况下,它们可能根本没有任何意义。这就是为什么我更喜欢使用术语“聚类”,因为我们总是获得一组聚类,而我们可能并不总是获得有效的类。
这并不是说输出没有用。上面的批评指出,聚类不一定会在我们已经知道类结构的数据集中找到底层的类结构。然而,如果我们使用集群,这通常意味着我们对底层的类结构一无所知。
因此,另一种选择并不是真正的“聚类与分类”,而是“聚类与无”,即:将整个数据集视为单个类。自然,提供任何一种有效的结构都会改善我们的结果。在花的例子中,即使我们错误地根据颜色将数据分成五个不同的种类,我们仍然得到四个捕获单一种类的花的类,和一个错误地将它们组合在一起的类(红色的花)。总的来说,对于未标记的数据来说,这是一个不错的结果。
另一个例子:假设我们试图将杂货店的顾客分成相似的群体,这样我们就可以有针对性地投放广告。可能存在一个理想的基础结构,如果我们知道它,它会比所有其他结构表现得更好。但实际上,任何聚类都比仅仅将客户视为一个大型同质群体表现得更好。聚类取得了如此大的成功,因为在许多情况下,监督学习是不可能的,但任何基于数据的结构,即使是不完美的结构,都比没有结构要好。
最后,我应该指出,因为聚类依赖于距离,所以它会受到数据中噪声的严重影响。噪声会导致聚类散开,变得无法识别,它会导致两个独立的聚类看起来像一个聚类,通常它会使我们想要找到的趋势更难识别。这是不可能完全避免的,但是有一系列的调整和工具可以使聚类算法在有噪声的情况下表现得更好。集群的大部分是一个尝试不同的东西,看看什么最有效的过程,处理噪音也不例外。
异常检测/异常值分析
在异常检测中,我们试图发现异常。一个异常是一个罕见的、已知的兴趣点。自然,这可能意味着很多事情,但在实践中,异常通常是不好的——欺诈性的信用卡交易、服务器崩溃、机器故障等。异常检测的目标是在正常数据的海洋中找到这些不经常出现的点,这些点就是任何非异常点。对于我们列出的例子,目标通常是在异常导致问题之前识别出异常——例如识别欺诈交易并在交易进行之前取消交易。
我们可以想象异常可能表现出的许多不同的模式,其中只有一些是可检测的。在一个极端,异常可能是完全随机的,没有共同点。我们不能指望能够探测到这些点。在另一个极端,我们可能有大量的已知异常,这些异常彼此之间有很多共同点,并且与正常数据明显分离。如果我们确信所有可能的异常都与这个已知的组相似,那么我们甚至可以将这个问题视为监督分类。
然而,最常见的是,异常很少且分散;他们有共同的特征,但只是一小部分。像这样的异常最常见的特征之一是,它们是正常数据其余部分的异常值。异常值的特征值远远超出正常范围。
例如,假设一个银行客户通常在加利福尼亚发布信用卡交易,平均每笔交易 30 美元,通常在上午 8 点到晚上 10 点之间。现在假设我们在凌晨 4 点从中国得到一笔 5000 美元的交易。即使不对这个新数据点应用任何数学或算法,也很容易看出它是可疑的。异常值分析就是利用这种“极端和/或异常值可疑”的直觉,并以数学方式将其应用于数据集。因此,许多异常检测问题可以通过离群点分析来解决,尽管它们不一定是同一个问题。
值得一提的是,即使我们可以使用这种方法识别异常值,如果没有某种后续措施,我们通常也不会知道它们是否真的是异常。因此异常值分析实际上是关于识别潜在的异常。这方面的一般策略是“标记和跟进”如果你在进行了一笔大额购买或者在另一个城市进行了一次购买之后,接到了银行的电话,那么你的交易就会被标记出来并被跟踪。
与监督分类的比较
异常检测的一个独特之处是,我们正在处理一个部分标记为的数据集。对于已知异常的点,我们有标签,但是对于其余的点,我们没有标签。一般来说,我们假设几乎所有这些都是代表非异常的“正常”数据点。这导致许多人在遇到这个问题时会问同一个问题:“我们可以只将未标记的点标记为‘正常’并使用监督分类吗?”
简而言之,答案是否定的。长的答案很长,也很专业,所以我不会在这里详细讨论。中间版本是,尽管它们之间有表面上的相似性,监督分类是一个与异常检测非常不同的问题,我们将在这里讨论其中的一些原因。
在监督分类中,我们希望以最大化分类准确性的方式在不同的类之间划出严格的界限。这是有道理的,因为在之前的帖子中,我们提到大多数监督问题在每个类中涉及大致相等数量的数据点。假设我们有三个类,A、B 和 C,每个类占全部例子的 33%。如果我们的分类器达到 99%的准确率,那么我们知道我们在所有三个类别上都做得很好。如果我们完全不能对 C 类进行分类,那么我们只能达到大约 67%的准确率。高水平的准确性要求我们做好每一个级的。
然而,在异常检测中,通常 99%以上的数据都是非异常的,只有非常少的已知异常点。我们可以完全忽略异常点,仍然获得 99%以上的准确率,这正是许多监督算法所做的。因为异常检测的全部目的是识别少量的异常点,所以这完全失败了。
一个相关但不相同的问题是,监督分类倾向于将所有点视为相等。如果我们将一些东西从 A 类中误分类,这与将一些东西从 b 类中误分类没有什么不同。这允许监督算法在类之间设置静态的、不可改变的决策边界。在异常检测中,将异常错误分类为正常点的成本(假阴性)高于将正常点错误分类为异常的成本(假阳性),和这些成本因问题而异。因此,我们需要一种算法,允许我们改变边界,并适应不同的成本和假阳性与假阴性之间的权衡。
最后,监督分类做出了一个隐含的假设,即我们用来训练模型的数据是它将永远接收到的所有数据的本质上准确的视图。在我们的监督分类示例中,我们正在对花卉进行分类。在那些数据中,白花总是矮牵牛花,矮牵牛花总是矮的。因此,如果我们看到一朵白色的花,我们会自动将其归类为矮牵牛,我们可以推断它也很短。
如果我们收到一个真正不寻常的数据点,这可能会在现实世界中遇到问题。假设我们有一朵 60 英寸高的白色花朵。我们的监督分类算法会毫不犹豫地把它归类为矮牵牛花。然而,任何人类观察者都不会认为这是一个糟糕的决定。要么数据点只是错误的(也许身高实际上是 6.0”并且输入不正确),要么我们正在看到一朵我们从未见过的花。不管怎样,我们都不应该把它当成矮牵牛。
换句话说,当我们输入的数据不同于我们以前见过的任何数据时,监督分类并不总是符合逻辑的。异常值分析旨在标记任何不寻常的点,即使我们以前从未见过这样的例子。
方法
所以,让我们回顾一下上一节:我们想要识别的异常通常是正常数据的异常值。至于识别异常值,我们需要一个算法来做三件事:
- 即使异常点数量很少,也不会忽略它们。
- 允许数据科学家定义正常点和我们标记为异常的点之间的阈值。
- 将任何异常值识别为潜在异常值,即使我们以前从未见过这样的异常值。
那么我们如何解决这个问题呢?事实证明,统计学中最成功和最广泛使用的技术之一,假设检验,本身就是一种异常值分析的形式,并且适用于我们的问题。假设检验的基本问题是这样的:假设我们得到一组我们知道都来自同一个来源的数据观察。接下来,我们得到一个新的观察结果,而我们不知道这个观察结果来自哪里。我们能决定新的观察结果是否来自同一个来源吗?
这适用于异常检测,因为我们可以检测到的异常通常来自不同于正常数据的数据源。在上面的信用卡示例中,正常数据的来源是持卡人,而异常数据来自欺诈者。
假设检验背后的数学和概念太复杂了,无法在这里完全解释,但它们对统计学和机器学习来说都是非常基础的,所以我强烈建议更深入地了解它们。下面是两个不同的资源。
简短的版本是这样的:我们在数据科学中观察到的许多值都有钟形概率分布(也称为“钟形曲线”)。这也称为高斯或正态分布数据。对于像这样的数据,大多数观察值将相当接近于集合的平均值,并且当我们远离平均值时,观察值会更少。这使得概率分布呈现独特的钟形,如下所示:
Courtesy of Dan Kernler and Wikipedia
我们对数据分布的了解允许我们提出另一个问题:假设我们被给定一个新值,并需要回答这个问题:“这个新值属于那组正态分布的数据吗?”我们的答案在很大程度上取决于与平均值的距离。离平均值越远,我们越不确定该数据点属于该数据集。
根据标准偏差测量与平均值的距离,标准偏差是所有点与平均值的平均距离。在正态分布中,我们预计所有样本中有 68%是平均值的+/- 1 标准偏差,95%在 2 以内,99.7%在 3 以内。有了这些知识,让我们考虑一个使用这种方法发现异常值的例子。
例子
假设我们被一个古怪的亿万富翁雇佣,他建造了一个大型的、先进的鸟舍,专门用来饲养蓝鸟。这个鸟舍很先进,因为它有电子门,当鸟儿落在旁边的传感器上时,可以让它们进出。
不幸的是,对我们古怪的雇主来说,讨厌的鸟已经进来了。他们希望我们开发一个软件补丁,只允许蓝鸟使用这个门,禁止其他鸟类进入。为了实现这一点,我们可以使用来自传感器的重量输入来知道试图使用门的鸟的质量。我们有大量关于蓝鸟体重的信息,但只有几个“异常”鸟类的例子。我们能用这样一个稀疏的、倾斜的数据集来实现我们的目标吗?
我们将从简单地构建一个异常模型开始。我们通过测量得知,成年蓝鸟的体重呈正态分布,有mean = 80g
和std = 10g
。幼鸟呆在鸟舍里,所以我们只需要担心成年鸟。有了这些数字,我们可以根据与平均值的距离来选择阈值。让我们首先将阈值设置在三个标准差的范围内。这给了我们一个80 +/- 3 * 10
的范围,给了我们低端的50g
和高端的110g
值。
接下来,我们必须根据预期的假阳性和假阴性的数量来评估该模型。假阳性是当我们不应该让一只异常的鸟进来时,假阴性是当我们应该让一只蓝松鸦进来时。
对于假阴性,我们只考虑我们期望包含的分布的百分比。在三个标准差下,我们得到了 99.7%的蓝鸟。假设鸟舍能容纳 2000 只鸟,那就相当于排除了三只最小的和三只最大的鸟(总共 6 只),这还不算太糟糕。
至于假阳性我们需要查看我们的异常数据。我们只有 12 点:
[23g, 25g, 33g, 38g, 48g, 52g, 64g, 80g, 96g, 120g, 148g, 322g]
这些点中的四个在范围50g-110g
内,因此我们将错过示例异常点的 1/3。正如我们上面所说的,这是“好”还是“坏”真的取决于问题,以及我们分配给假阳性/假阴性的成本。在这种情况下,让我们假设错误种类的鸟进入鸟舍比排除更多的蓝鸟成本更高,所以让我们尝试一个更严格的门槛。
把它改成两个标准差,我们就得到一个范围60g-100g
。这只排除了一个我们之前没有排除的异常,我们现在会从 2000 只鸟中排除大约 100 只。这是否是一个好的权衡是值得讨论的。同样值得注意的是,因为一个异常正好位于平均值处,所以不管我们选择什么样的阈值,都不能用这种方法排除它。在异常检测中,点与正常数据非常相似以至于无法排除是很常见的。
更复杂的模型
我们已经介绍了在只有一个特征的问题中用于异常检测的最常见的算法,但是事实上,当使用更多的特征时,它不会变得非常复杂。通常,我们为每个特征单独构建异常值模型,并根据特征值在同一分布中的可能性生成一个介于 0 和 1.0 之间的数字(分数越高越好)。然后我们把所有的特征值相乘。由于任何单个要素的值的范围在 0.0 到 1.0 之间,这种相乘的过程永远不会使该数字大于其最小值,因此作为单个要素的异常值仍然会导致较低的分数。
当然,这种方法并不适合每一个问题,对于更复杂的问题有许多更复杂的方法,但是它们背后的大概念都符合我们上面讨论的内容。它们都必须处理相同的问题,如类别不平衡、重叠以及误报和漏报的不同成本。
结论
虽然无监督学习的方法与有监督学习有很大的不同,但是潜在思想的相似之处在这里是显而易见的。所有这些方法都依赖于相关观察的数据集,并进一步假设这些相关观察中存在有意义的模式,可以解释数据集中不存在的东西(如观察的类)。
主要的区别是我们处理问题的方向:在监督学习中,我们从正确的答案开始,并寻找解释它们的模式。在无监督学习中,我们寻找模式,然后试图辨别它们的含义以及它们解释了什么样的事情。这两种方法都有价值。
接下来,我们将讨论强化学习,这在很多方面与我们已经讨论过的内容有很大的不同。
机器学习,第 4 部分:强化学习
Image by the author
机器学习基础
强化学习在机器学习问题的世界中占有一个有趣的位置。一方面,它使用了一个反馈和改进系统,看起来类似于梯度下降的监督学习。另一方面,我们通常在解决强化学习问题时使用数据集。鉴于我们之前的所有方法都完全依赖于数据集,这种新问题如何联系起来似乎令人困惑。
强化学习和我们之前所做的当然有区别;在很多方面,强化学习本身更类似于更广泛的人工智能领域的问题。然而,在一天结束时,仍然有教师和学习者的因素,我们仍然通过反馈来学习我们问题的逻辑。强化学习是一个很好的例子,说明了整体“学习”方法可以有多广泛。
问题是
想象一下,你坐在桌边玩 21 点。你从来没有玩过 21 点,你不知道任何规则,也不允许任何人告诉你(奇怪,我知道)。庄家告诉你“你的总数是硬 19,庄家的上牌是 10,你可以站着或打。”即使你不知道那是什么意思,你还是选择了“打”,庄家告诉你你输了,并拿走你的钱。
你从中学到了什么?很可能下一次当你面对同样的手牌和选择击打或站立时,你会选择站立,而不是上次失败的那个选项。不是很多,但比你之前知道的要多。从根本上来说,这是强化学习,在这里我们学习根据类似情况下先前行动的结果选择正确的行动。
强化学习在我们事先不知道一个特定行为是“好”还是“坏”的情况下很有效,但是我们可以测量该行为的结果,并在事后弄清楚。这类问题出奇的普遍,计算机非常适合学习这类模式。强化学习仍然是一种学习算法,但它与我们之前讨论的有许多不同之处,这需要定义一些新的术语。
强化学习术语
第一任是代理。“代理”一词可以粗略地定义为“作用于自身环境的能力”在之前的例子中,我们的模型只是被动地对呈现给它们的数据做出反应,但在强化学习中,我们正在训练能够主动影响它们环境的算法。换句话说,我们用代理,也就是“代理”,来训练算法
代理通过选择一个影响他们周围环境的动作来完成这个任务。他们通过检查状态来决定这个动作,状态是与他们相关的“环境状态”。状态通过例子更容易理解(我们稍后会讲到),但是现在假设状态包含了选择一个动作所需的所有信息。
我们将使用 choice 来指代在该特定状态下从所有选项中选择的动作,我们的代理做出的所有选择的组合定义了它的行为。我们最终试图学习最佳行为。
在强化学习中,这是通过教师元素完成的,它为每个动作提供一个分数和。积极的分数表示一个好的选择,而消极的分数表示一个坏的选择。可以有多个好的选择,也可以有多个坏的选择。在给定的状态下,也可以有零个好的或坏的选择。最终目标是从这些选项中找到最佳选择。分数是帮助我们找到它的反馈。
将这些术语放在上面例子的上下文中。你是代理人,因为你在做决定。你的手牌总数(19)和庄家的升牌(10)组成了状态。您可用的动作是“击中”或“站立”,在本例中,您的选择是“击中”那个选择的分数是输掉你下注的所有钱。如果你玩了数百手牌,你所有选择的组合将定义你在玩 21 点时的行为。
关注结果,而不是选择
我们之前提到了一些我们应该扩展的东西:当我们在强化学习中得分时,我们想要判断选择的结果,而不是选择本身。判断结果而不是行动有三个主要原因:
首先,我们对结果的了解比我们对每个行动的价值的了解要多得多。事实上,行动的价值是我们正在努力学习的,我们不知道它们的事实是隐含的。如果我们确实知道每个状态下每个动作的价值,那就根本没有强化学习的理由了。
第二,即使状态保持不变,一些动作的值也可以改变;通常这是随机的结果。这不会影响我们的栅栏绘画示例,但会影响像 21 点这样的游戏。在 21 点游戏中,在总共15
上选择hit
有时会赢,有时不会。稍后我们会看到更多。
最后,试图奖励的具体行动而不是结果会导致怪异的行为。想象一下,我们正在训练一个机器人去画栅栏:每次机器人选择“画”作为它的动作时,我们似乎应该奖励它。对一个人来说,这是有意义的,因为我们理解问题的背景:我们希望整个围栏都被油漆。
然而,机器所看到的是,它因为绘画而得到奖励,所以它可能会无休止地绘画栅栏的同一部分,直到它关闭。这看起来可能很奇怪,因为机器人是而不是因为移动而得到奖励,这实际上是我们评分系统的最优策略。
如果我们改变奖励,使其基于状态——换句话说,我们奖励结果而不是行动——那么我们就会得到正确的行为。从国家的角度来看,呆在一个地方画画什么也做不了,因为栅栏和以前画的一样。然而,移动和绘制一个新的部分更接近目标(并导致更高的分数)。通过正确地构建问题,我们得到了我们想要的行为。
与监督分类的比较
当我们看强化学习的核心循环时,我们有:做出决定(行动),获得反馈(评分),使用反馈来改进逻辑。与监督学习相比,我们有:作出决定(预测),获得反馈(误差度量),使用反馈来改善逻辑。
他们看起来非常相似,因为就他们的学习过程而言,他们是。他们都使用来自知识丰富的来源的反馈来改进他们的逻辑。然而,除此之外,他们两人之间的情况就不同了。主要的区别是他们为了学习如何接收和处理数据。
在监督学习中,我们有一个示例数据集,用正确的输出进行标记。该模型使用这些示例和标签来查找可用于预测响应值的趋势和模式。监督学习模型“知道”的一切都来自这个训练数据集。训练也是完全被动的:没有概念模型需要做任何事情来生成或访问新的训练数据。
在强化学习中,情况并非如此。使用强化学习而不是标记的训练数据,我们得到的(通常)是一组规则。我们有规则来确定某些动作何时有效,例如“当机器人靠近栅栏时,paint
是一个有效的动作。”我们还有其他规则来规定状态如何响应动作而改变。例如“如果栅栏在当前状态下是unpainted
,并且代理选择paint
作为动作,那么栅栏现在是painted
我们给每个动作打分的方式本身通常是一套规则。从unpainted
到painted
的栅栏可能值+10
,但是从painted
到painted
的栅栏一文不值。
此外,我们无法访问列出所有可能的状态、动作和结果组合的整个数据集。相反,这些需要通过选择一个动作并使用规则集转换状态来发现。这意味着代理必须通过选择动作、转换状态和接收反馈来探索。换句话说,学习过程需要智能体积极地做事情,不像我们迄今为止看到的任何其他学习算法。
你可能想知道为什么我们不能创建一个包含所有可能的状态、动作和反馈的数据集,并以这种方式学习呢?我们可以,如果有可能列出每种组合的话。然而,大多数时候,枚举每一个可能的状态是而不是不可能的,因为它们的数量巨大,可能是无限的。我们最终会得到一个包含数万亿(或更多)例子的数据集。也可能是这样的情况,如果不选择一些起点并采取行动来观察会出现什么样的新状态,我们甚至不会真正知道哪些状态是可能的。
无论哪种方式,结果都是一样的:我们需要一个代理通过探索来学习状态、动作和反馈。它必须选择随机行动,看看会发生什么。这里值得强调的是,许多状态只能通过执行某些动作来达到,代理只能通过首先到达这些状态来了解这些状态:例如,如果围栏油漆机器人想要了解油漆围栏所导致的动作,但整个围栏开始未油漆,那么它需要选择首先油漆一部分。事实上,有些状态只能通过特定的动作组合才能达到,这使得学习所有正确的动作变得更加困难。
这与我们以前见过的任何东西都非常不同,需要更多的术语来描述它。这种状态和动作的互联网络的概念被称为状态空间。术语“空间”表明了一个事实,即代理需要通过动作从一个状态“移动”到下一个状态。围绕状态空间本身移动的行为被称为遍历。
新挑战
可以想象,这种问题会带来一系列全新的挑战。最大的问题之一就是状态空间本身的大小。许多强化学习问题的状态空间包含数十亿、数万亿甚至无限数量的状态。这些巨大的状态空间通常是因为 1)具有大量变量的非常复杂的状态,2)涉及随机性的状态,因此单个动作可能导致许多不同的结果,或者两者都有。
更专业的术语是组合爆炸。有时这真的无法处理,其他时候我们可以通过忽略不会影响行为的事情来减少状态空间的大小。我们有时也可以避免探索可能不属于任何最优行为的状态,因此我们可能永远不会在实践中达到它们。我们将在后面的示例中更多地讨论这两者。
这就引出了探索与开发的相关概念。当一个代理第一次开始学习时,它将看到状态,在大多数时间里它几乎没有数据。然后尝试随机行动,看看会发生什么/会导致什么结果,这是有意义的。这被称为探索,它帮助代理建立问题知识。
一旦代理获得了这些早期状态的一些知识,就值得只关注那些看起来是最佳的状态和动作。在这种情况下,代理需要在每个状态下做出“正确”的选择。这个过程被称为利用,因为代理正在利用它对问题的了解来做出选择。利用使我们能够改进对最佳选择的估计,并遍历一系列我们认为是最佳的状态,但可能对其了解不够。最优选择本身在这里被称为【贪婪】选择,因为它是当时的最佳选择,忽略了未来的任何后果。
有些选择并不贪婪,它们让我们想到了最后一个我们不会多谈的因素。不是因为它不重要,而是因为它太复杂,无法在这里深入讨论。在一个特定的问题中,最优行为可能包括做出非贪婪的选择,仅仅是为了达到一种状态,这种状态下的行动会有很大的回报。
换句话说,我们需要提前计划,以达到一种有巨大回报的状态,这种回报可以补偿达到这种状态所需的次优选择。这些问题被称为规划问题,需要一种方法来说明未来的回报以及当前的回报。正如我所说的,这本身就是一个复杂的问题,有一整个领域的不同方法,所以我们不会深入研究这个问题,但知道它的存在是很好的。
这在短时间内提供了很多信息,但这里的基本思想是,在强化学习中,我们有一个状态空间,代理只能通过遍历状态空间并从与其选择相关的反馈中学习来改进。这与我们迄今为止讨论过的任何内容都有很大不同,但幸运的是,如果你理解了这个概念,你就已经攻克了强化学习中最令人困惑的部分。学习过程本身非常简单:代理获得关于其动作的即时反馈,只需记住状态/动作/反馈的组合。
方法
讨论了强化学习的不同方面后,我们现在可以考虑一种方法。我们需要解决几个问题:
- 状态表示:我们需要以一种方式来表示状态,这种方式包括我们需要的所有信息,排除我们不需要的信息,并且如果可能的话,我们应该减少状态空间的大小。
- 列举选择:无论如何,我们可以做出的选择可能都是一样的。然而,在一些问题中,选择会根据状态而改变,所以当我们向代理呈现状态及其动作选择时,我们需要一种方法来确定哪些选择是有效的。
- 评分:我们需要一种方法来给代理的动作评分。在某些情况下,这可能是显而易见的——例如,在赌博游戏中,我们可以使用赢/输的钱数——在其他情况下,我们需要自己构建分数。正如我们在上面提到的画栅栏机器人的例子,我们如何给动作打分对算法的成功极其重要。
- 探索:我们需要算法探索状态空间的方法。至少,这很简单。如果我们已经实现了上面的所有东西,我们可以通过简单地从呈现给我们的动作中选择一个随机动作来探索。
- 剥削:剥削有点难。我们需要能够存储我们之前选择的行为的值。这包括记录行动的选择和我们选择行动时的状态。如果行动的价值永远不变,那么我们只需要经历一次每个选择。如果动作的值可以改变,那么我们需要反复尝试每一个动作,并且我们需要存储我们选择的所有时间的平均值。选择贪婪行为的实际行为仅仅包括查找在该状态下可用的每个行为的值,并选择具有最高期望分数的一个。如果我们需要实施计划,而不是总是选择贪婪的行动,这需要改变,但像以前一样,我们不会在这里深入讨论。
列表中的问题 1、2 和 3 取决于具体的问题,因此没有处理它们的通用方法。然而,解决探索-开发权衡确实有一些通用的方法,其中最流行的是ε-贪婪算法。
在 epsilon-greedy 中,我们将 epsilon 设置为 0.0 到 1.0 之间的值,并选择以概率 epsilon 进行探索。所以如果我们 90%的时间都在探索。随着时间的推移,我们降低了ε的值,因此我们越来越经常地做出贪婪的选择。在需要一长串正确动作的问题中,较低的ε值意味着我们更有可能沿着有用的动作路径前进,而不是像我们随机探索那样完全忽略探索。这对于大型复杂的状态空间自然是最有用的。
例子
在这篇文章的介绍中,我谈到了只用强化学习来学习 21 点。让我们更具体地证明可以真正做到。我们将使用一个简化版的游戏,去掉了分裂、翻倍、投降和保险。如果你不知道这些术语的意思,不要担心,因为我们不会用到它们。对于那些想要快速复习剩余规则的人,您可以在这里找到。
国家代表权
让我们仔细研究一下上面列出的问题。首先,我们需要代表国家,顺便提一下,这可能是这个具体问题中最困难的部分。如上所述,带有随机元素的问题——就像这个——可能有大量的状态。四张卡的初始交易有 6,497,400 个可能的状态,所以我们希望尽可能减少。
我们还提到,如果我们能够将状态简化为必要的状态,那么组合爆炸问题将会得到解决。这是我们可以在这里做的事情。首先,代理人在做决定时不会知道经销商的“向下牌”(面朝下的牌)的值,所以从代理人的角度来看,我们可以忽略它。我们现在只有 132,600 个州,州的表示如下:
{
Agent: [5 of Diamonds, 10 of Clubs],
Dealer: [Jack of Spades]
}
这里有几件事值得一提。在 21 点中,一张牌的花色并不重要,许多牌值 10,所以我们应该只使用牌值,而不是其他任何值。卡片的顺序同样不重要:一手[5, 10]
牌和一手[10, 5]
牌是一样的,所以我们应该确保代理意识到这一点。
我们可以通过将状态更改为仅从玩家的角度显示一手牌的总价值来实现这一点,甚至更多。这要求我们确保自动处理 a,可以是 1 或 11,但这并不难做到(在大多数赌场中,庄家会选择对玩家更好的值)。这让我们看起来像是:
{ Agent: 15, Dealer:10 }
现在像[10, 5]
和[5, 10]
这样的手是一样的。这也使得像[8, 7]
这样的手相当于[11, 4]
,因为它们都是总计15
。我们也忽略了经销商的降牌——尽管不同的降牌在技术上是不同的州——因为我们无论如何也不会知道。请记住,我们希望代理学习玩家的行为,所以我们需要状态来准确地表示只有玩家会知道什么。
通过这些改变,庄家的单卡可以是从2
到11
的任何值(9 个可能值),而玩家的手牌可以是从4
到21
的任何值(18 个可能值)。这给了我们9 * 18 = 162
个可能状态的总数。考虑到我们从超过 600 万个初始状态开始,这是一个巨大的进步。
列举选择
现在我们继续列举动作,这可能是这个问题最简单的部分。在任何时候,我们都可以选择hit
或stand
,不多也不少(回想一下,我们删除了允许更多操作的规则)。所以列举动作很容易。
得分
对于计分系统,我们只考虑这手牌是赢、输还是平(21 点术语中的“推”)。换句话说,我们对待代理人就好像它每手都下相同的赌注。这简化了评分,足以使用:
Winning a hand = +1
Losing a hand = -1
Tie (Push) = 0
这里实际上有一个问题。我们需要对我们的代理人做出的每一个选择给予反馈,但是这个评分系统只考虑已经完成的手牌。在我们打了牌但没有打爆的牌上,我们有一个不能用这个系统来判断的状态。如何解决这个问题?规划是一个显而易见的答案,我们可以等待这手牌结束,并将这手牌的最终价值分配给导致这手牌的每一个选择。
这是可行的,但是有两个原因使得它在这里看起来不理想。首先,这可能导致对某些选择的不合逻辑的反馈。假设开始手牌是 10,代理选择hit
。这在客观上是正确的选择,因为当总数为 10 时,没有办法破产。点击后,我们的总数是 20,代理再次选择hit
。毫不奇怪,这是半身像,手是一个损失。即使第一个选择hit
是个好选择,我们还是要把损失分配给两个选择吗?
从长远来看,即使我们这样做了,它也可能会成功,但我想大多数人都会同意这个分数没有多大意义。第二个独立的问题是,将计划添加到这样一个简单的方法中会增加很多额外的复杂性。如果我们能避免,我们应该避免。
我们可以做到这一点,只要考虑到任何时候我们在不破坏的情况下增加总量通常都是一件好事。不如赢一手,但还是聊胜于无;我们将这个结果称为Hit/increase
。为了处理最后一个边缘情况,我们需要考虑当我们击中并且减少我们的总数时会发生什么,这可能发生在软牌值变硬的情况下(这手牌包含被计为 11 的 a,但是在击中后变为 1);我们称之为Hit/decrease
。自然,这比Hit/increase
差,也比失败好,所以我们应该在-1
和0.5
之间选择一个值。很难说达到和减少总数是好的、坏的还是中性的,但我将继续给它赋值-0.2
。这给了我们最后的分数:
Winning a hand = +1
Losing a hand = -1
Tie (Push) = 0
Hit/increase = +0.5
Hit/decrease = -0.2
这些值可能不太准确,可能需要进一步测试,以找到产生最佳策略的值。不管怎样,这确实让我们可以在任何一手牌上得分,而不需要等着看最后的结果。我们通过增加得分来避免额外的计划复杂性。
勘探和开发
最后,我们到了问题的探索/开发部分。探索很容易,我们可以通过简单的抛硬币机制在hit
和stand
之间随机选择。剥削更加复杂,但也不复杂多少。我们只需要一个结构(比如 hashmap/dictionary ),它可以记录状态和动作的每种组合,并平均出我们在执行时看到的结果的值。选择贪婪的选择只是挑选估计分数最高的选择。
最终算法
我们现在有了一个可以学习 21 点的代理。我们可以遵循 epsilon-greedy 方法,随着时间的推移减少探索的数量,但在这种情况下,相对较少的总状态数和我们不需要担心规划的事实意味着,如果我们通过足够多的手牌随机探索,我们会获得同样好的策略(为此,我们可以轻松地模拟数百万手牌)。尽管对规则一无所知,也不需要任何复杂的规划或战略编程,这种简单的方法可以在几秒钟内找到一种几乎最佳的纸牌游戏方法。就效率而言,这种方法可能会击败除了最勤奋的人类玩家之外的所有人。
结论
强化学习介绍了两件事,我认为这对任何机器学习从业者都是有用的。首先,它显示了反馈和改进机制在生成逻辑时是多么灵活,因为这个问题以一种与我们以前见过的完全不同的方式出现。
其次,它引入了通过搜索状态空间来解决问题的概念。事实证明,AI 中的很多问题都可以用同样的方式概念化。这甚至可以应用于我们已经讨论过的其他形式的机器学习。比方说,我们为监督学习模型生成的参数只是所有可能参数的状态空间中的一组参数。通过在每一步对参数进行微小改变的方法(如梯度下降)找到它们,非常类似于在状态空间中搜索。
这不是一个需要理解的必要联系,但有时意识到这些不同的算法很有趣,其中大多数看起来非常独特和不同,很大程度上只是处理同一基础抽象问题的不同方式。
系列结论
我真诚地感谢所有阅读了本系列部分或全部内容的人。我希望它对机器学习中正在发生的事情提供了一个很好的高层次的观点,并有助于揭开这个有时感觉像魔法的领域的神秘面纱。如果对未来的帖子有任何要求或建议,请在评论中留下。
机器学习——完美总是从错误开始
有抱负的数据科学家需要知道什么来避免常见的 ML 错误
Photo by chuttersnap on Unsplash
有很多文章解释新数据科学家犯的常见错误,主要集中在实践上,而不是机器学习(ML) 过程本身。
这篇文章将涵盖这一点:
数据科学家在 ML 管道中会犯什么样的错误,以及解决这些错误的几种方法…
修订本
在我们开始之前,请确保您了解 ML 管道的步骤:
你能和你的老板进行一次对话,简单解释一下机器学习的基础知识吗?现在你可以…
towardsdatascience.com](/not-yet-another-article-on-machine-learning-e67f8812ba86)
特别要记住 ML 管道图,因为我们将引用各个步骤:
ML Pipeline
错误的影响
ML 过程中的大多数错误很难识别和解决,因为它们不会直接抛出错误或异常,但它们会影响我们项目的最终结果,从而影响我们的洞察力。
ML 管道本质上是迭代的,但是简单的错误会导致额外的修改和来回的修改。限制它们可以提高我们过程的效率和洞察的质量,因为我们可以专注于真正的任务而不是故障排除。
不要误解我的意思:每个人都会犯错误,如果把它们作为学习经历的一部分,它们将是无价的!随着我们作为数据科学家的成长,我们将建立在这种经验的基础上,并能够避免它们或尽早识别和补救它们。
错误类型
ML 管道中最常见的错误类型与以下一个或多个方面有关:
数据准备—数据清理
不言而喻,“脏数据”是数据科学家面临的最大障碍之一,数据清理是 ML 项目中最耗时的部分,占总时间的 60%,其次是 20%的数据摄取——在项目的初始阶段总共花费了 80%!
有个笑话声称:
80%的机器学习在清理数据,20%在抱怨清理数据😃
处理缺失值是数据清理最重要的任务之一,因此可能会导致错误。我们需要检查缺少值的列,并查看它们如何与数据集的其余部分相关,尤其是目标值。一种常见的技术是使用现有值的平均值/中值/众数,但也有可能这不是正确的指标,我们需要想出其他的方法。
此外,当涉及分类时,我们需要考虑数据集的类别结构,因为我们可以引入新的“未定义的类别,或者另一种可能性是使用 ML 算法来预测缺失值。
最后,我们可以记下这些空值,并选择一个能够满足需求的算法。
这里的任何错误都可能会在以后扭曲最终结果,因此建议将该过程拆分为单独的步骤,并可能在我们的代码中引入策略或工厂设计模式的组合,以便我们可以在所有这些填充方法之间互换。
数据准备—特征工程
特征工程是特征提取、构造和选择的超集。在这里,数据科学家使用业务经验和数据驱动的洞察力来识别哪些列与目标相关。
可以通过分配分数然后对它们进行排序来导出特征重要性:可以选择那些具有最高分数的特征来包含在训练数据集中,而其余的可以忽略。我们也可以使用这些信息来构建新的特征,或者降低它们的维数。
选择正确的功能非常关键,因为拥有更好的功能意味着:
- 更灵活地选择不太复杂的型号
- 更灵活地选择次优模型参数
- 更好的结果
尽管这可能简单或复杂,但记住特征选择直接影响模型选择是很重要的,因为我们不希望无意中将偏差引入我们的模型,这会导致过度拟合。这个阶段的任何错误都会直接影响模型的精度。
在这里,明智的做法是保留一份我们所做的所有假设的记录,这样如果遇到错误,我们可以回去重新审视它们。拥有大量的文档将有助于整个项目,尤其是在模型的验证和部署方面。
数据分离—取样
这方面的主要误差与使用单一或有限数量的样本有关,这会在模型的训练和测试中引入可测量的偏差。
另一种错误是没有从数据集中选择具有代表性的样本,因此没有获得特征/特性的比例。例如,如果人口中有 35%的黑人和 65%的白人,那么我们的样本应该反映这个百分比。
候选模型评估
在这个流水线步骤中,一个常见的错误是数据科学家没有花足够的时间来评估模型,而是直接使用它。模型评估对于确保不存在偏见非常重要。这一步与取样步骤密切相关:验证程序需要重复多次才能产生更好的结果。
最后但同样重要的是:选择正确的模型
为 ML 项目选择正确的模型是一个需要特别关注的过程,因为有无数的模型可以处理我们的数据,但这并不一定意味着它们对我们试图解决的问题是合适的。与型号选择流程相关的主要错误有:
选择型号是因为:
- 它在数据科学社区中的受欢迎程度
- 其精度(作为唯一标准)
- 其返回结果的速度(作为唯一标准)
- 与其他选项相比,易于使用
结局
Forget the Mistake — Remember the Lesson!
错误是学习过程中不可或缺的一部分——我们应该接受它们,因为它们是驱动我们不断前进的引擎。我们对 ML 管道越小心,我们就越不容易犯可能危及整个项目的错误。
我们还可以通过彻底研究一个 ML 案例来加强我们的学习,观察它如何处理管道的各个步骤,更不用说:
熟能生巧!!!
感谢阅读!
我定期在 媒体 上撰写关于技术&的数据——如果你想阅读我未来的帖子,只需“关注”我!
机器学习管道:特征工程编号
任何机器学习模型真正重要的一部分是数据,尤其是使用的特征。在本文中,我们将讨论特征工程在机器学习管道中的位置,以及如何使用宁滨、变换和归一化对数字进行一些特征工程。特征工程的真正好处是能够改进模型的预测,而不会使模型变得更加复杂。在本文中,我们将使用我在 Kaggle.com[1]发现的来自 Goodreads.com 的数据进行一些动手编码。
本文使用的数据是关于书籍评级的,数据可以在这里下载:https://www.kaggle.com/jealousleopard/goodreadsbooks
机器学习管道的高级概述
一般的机器学习流水线由 5 个步骤组成:
- 询问 —企业或客户想要做什么(例如,预测下一季度的销售额,检测癌症等。)
- 数据——数字形式的现实。比如一个季度的销售数量。
- 特性 —用数字转换的数据,以便模型可以理解。你们中的一些人可能会说,“嘿,我的模型接受红色或绿色作为特征!”在您的模型中,代码实际上将红色或绿色转换为 0 或 1,这通常是通过一次热编码完成的。
- 模型选择 —模型是您用来弥合数据和预测之间差距的工具。对于那些熟悉数学的人来说,把它想象成一个函数。你的数据是输入,模型是函数,你的预测是输出。
- 预测 —解决“提问”请求的答案与上面 ask 中的示例相关,第一季度(Q1)销售了 10,000 台,或者患者 XYZ 患有癌症。
下图显示了构建机器学习管道的类似过程,取自微软【2】:
对于下面显示的其余特征工程技术(如宁滨、对数变换、特征缩放),它们只是您操纵数据以便有望做出更好预测的额外工具。
扔掉
当你有一个数据集需要聚集成组时,宁滨是很棒的。创建这些组或箱有助于模型提高预测准确性。例如,你有一个收入范围来预测信用违约。应用宁滨的一种方法是对不同的收入水平进行分组。现在,我们将开始使用宁滨直方图对图书计数评级。
#Load Packages
import numpy as npimport pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn import linear_model
from sklearn.model_selection import cross_val_score
import sklearn.preprocessing as pp#load data into dataframe
books_file = pd.read_csv('books.csv', error_bad_lines=False)
将“error_bad_lines”代码放在 pd.read_csv 函数中,因为有一些不干净的行。不然 Python 会吼我们的。
#Taking a look at the data
books_file.head()
现在,我们将开始绘制直方图。
#Plotting a histogram - no feature engineering
sns.set_style('whitegrid') #Picking a background color
fig, ax =plt.subplots()
books_file['ratings_count'].hist(ax=ax, bins=10) #State how many bins you want
ax.tick_params(labelsize=10)
ax.set_xlabel('Ratings Count')
ax.set_ylabel('Event') #How many times the specific numbers of ratings count happened
这里怎么了?看起来大多数计数的权重都较低。有道理,因为有很多书只得到几个评级。如果我们想在我们的图表中捕捉更多的受欢迎的书评呢?答案是:对数标度。
对数变换
#Plotting a histogram - log scale
sns.set_style('whitegrid') #Picking a background color
fig, ax =plt.subplots()
books_file['ratings_count'].hist(ax=ax, bins=10) #State how many bins you want
ax.set_yscale('log') #Recaling to log, since large numbers can mess up the weightings for some models
ax.tick_params(labelsize=10)
ax.set_xlabel('Ratings Count')
ax.set_ylabel('Event') #How many times the specific numbers of ratings count happened
现在,我们将根据额定值的正常值和对数转换值进行额定值预测。
对于下面的代码,我们添加+1,因为 0 的日志是未定义的,这将导致我们的计算机爆炸(开玩笑,有点)。
books_file['log_ratings_count'] = np.log10(books_file['ratings_count']+1)#Using ratings count to predict average rating. Cross Validation (CV) is normally 5 or 10.
base_model = linear_model.LinearRegression()
base_scores = cross_val_score(base_model, books_file[['ratings_count']],
books_file['average_rating'], cv=10)
log_model = linear_model.LinearRegression()
log_scores = cross_val_score(log_model, books_file[['log_ratings_count']],
books_file['average_rating'], cv=10)#Display the R^2 values. STD*2 for 95% confidence level
print("R^2 of base data: %0.4f (+/- %0.4f)" % (base_scores.mean(), base_scores.std()*2))
print("R^2 of log data: %0.4f (+/- %0.4f)" % (log_scores.mean(), log_scores.std()*2))
基础数据的 r:-0.0024(+/-0.0125)
日志数据的 r:0.0107(+/-0.0365)
这两个模型都相当糟糕,这从仅使用一个特征来看并不太令人惊讶。从标准统计学 101 的角度来看,我觉得看到负的 R 平方有点可笑。在我们的例子中,负的 R 平方意味着一条直线,假设一个特征实际上预测更差(也就是不遵循直线/线性回归的趋势)。
特征缩放
我们将讨论三种特征缩放方法:最小最大缩放、标准化和 L2 归一化。
#Min-max scaling
books_file['minmax'] = pp.minmax_scale(books_file[['ratings_count']])
#Standarization
books_file['standardized'] = pp.StandardScaler().fit_transform(books_file[['ratings_count']])
#L2 Normalization
books_file['l2_normalization'] = pp.normalize(books_file[['ratings_count']], axis=0) #Needs axis=0 for graphing
#Plotting histograms of scaled features
fig, (ax1, ax2, ax3, ax4) = plt.subplots(4,1, figsize=(8, 7))
fig.tight_layout(h_pad=2.0)#Normal rating counts
books_file['ratings_count'].hist(ax=ax1, bins=100)
ax1.tick_params(labelsize=10)
ax1.set_xlabel('Review ratings count', fontsize=10)#Min max scaling
books_file['minmax'].hist(ax=ax2, bins=100)
ax2.tick_params(labelsize=10)
ax2.set_xlabel('Min max scaled ratings count', fontsize=10)#Standardization
books_file['standardized'].hist(ax=ax3, bins=100)
ax3.tick_params(labelsize=10)
ax3.set_xlabel('Standardized ratings_count count', fontsize=10)#L2 Normalization
books_file['l2_normalization'].hist(ax=ax4, bins=100)
ax4.tick_params(labelsize=10)
ax4.set_xlabel('Normalized ratings count count', fontsize=10)
The graph above shows a histogram of the normal data, min max scaled transformation, standardized transformation, and normalization transformation. Overall, the transformations are pretty similar, but you would want to pick one over the other dependent upon other features in your dataset.
现在,我们将从 3 个特征比例数据中进行预测。
#Using ratings count to predict average rating. Cross Validation (CV) is normally 5 or 10.
base_model = linear_model.LinearRegression()
base_scores = cross_val_score(base_model, books_file[['ratings_count']],
books_file['average_rating'], cv=10)
minmax_model = linear_model.LinearRegression()
minmax_scores = cross_val_score(log_model, books_file[['minmax']],
books_file['average_rating'], cv=10)
standardized_model = linear_model.LinearRegression()
standardized_scores = cross_val_score(base_model, books_file[['standardized']],
books_file['average_rating'], cv=10)
l2_normalization_model = linear_model.LinearRegression()
l2_normalization_scores = cross_val_score(log_model, books_file[['l2_normalization']],
books_file['average_rating'], cv=10)#Display R^2 values. STD*2 for 95% confidence level
print("R^2 of base data: %0.4f (+/- %0.4f)" % (base_scores.mean(), base_scores.std()*2))
print("R^2 of minmax scaled data: %0.4f (+/- %0.4f)" % (minmax_scores.mean(), minmax_scores.std()*2))
print("R^2 of standardized data: %0.4f (+/- %0.4f)" % (standardized_scores.mean(), standardized_scores.std()*2))
print("R^2 of L2 normalized data: %0.4f (+/- %0.4f)" % (l2_normalization_scores.mean(), l2_normalization_scores.std()*2))
基础数据的 r:-0.0024(+/-0.0125)
最小最大比例数据的 r:0.0244(+/-0.0298)
标准化数据的 r:0.0244(+/-0.0298)
L2 标准化数据的相对误差:0.0244 (+/- 0.0298)
对日志转换稍有改进。由于大多数缩放类型在图形上产生相同的形状,所以它们给出相同的 R 平方值也就不足为奇了。每种缩放方法都有一些需要注意的地方。最小最大值有利于使所有特征值介于 0 到 1 之间。标准化有利于缩放特征的方差,因此使均值= 0,方差= 1(也称为正态分布风格)。L2 归一化的工作原理是将要素缩放到欧几里德或 XY 平面范数。重要说明:要素缩放不会改变要素的形状,因为在遮光罩下它会除以一个常数。
结论
太棒了,我们讨论了机器学习管道的简要概述以及特征工程的适用范围。然后我们讨论了宁滨、对数变换和各种形式的特征缩放。一路上,我们还通过书评观察了特征工程如何影响线性回归模型预测。
就个人而言,我发现在处理其他数据集中大多数其他要素的概率分布时,最小最大值工作得很好。类似地,标准化和 L2 归一化用于将数字从非常大的数字缩小到与所选分析数据集相关的相似特征。
免责声明:本文陈述的所有内容均为我个人观点,不代表任何雇主。
[1] Kaggle,Goodreads-books (2019),https://www.kaggle.com/jealousleopard/goodreadsbooks
【2】微软,什么是机器学习管道?(2019),https://docs . Microsoft . com/en-us/azure/machine-learning/service/concept-ml-pipelines