Python 中的单变量异常检测
从数据集中检测异常值的五种方法
威尔·梅尔斯在 Unsplash 上拍照
异常值检测通常是任何探索性数据分析的重要部分。这是因为在现实世界中,数据通常是杂乱的,许多不同的事情都会影响底层数据。因此,能够从底层数据中识别不同的方法是非常重要的。
那么,首先要问的是“什么是离群值?”离群值可以被归类为不符合模式、数据结构或不在我们对现有数据的预期的正常范围内的一个或几个数据点。这是一个非常主观的定义,因为异常值在很大程度上取决于您检查数据点是否为异常值的环境。
这种异常值可能是许多不同问题的结果:
- 人为误差
- 仪器误差
- 试验误差
- 有意创造
- 数据处理错误
- 抽样误差
- 自然离群值
当然,能够识别该异常值的目的也可以不同。这可能是因为异常值表明产生数据的操作发生了变化,这些数据在以下情况下很有用:
- 欺诈检测
- 入侵检测
- 故障诊断
- 时间序列监控
- 健康监控
异常值表示流程中可能出现了问题,或者生成数据的流程的性质发生了变化。因此,这将需要根据基本的公认正常数据来确定异常值。
在其他情况下,能够从现有数据中移除异常值以确保模型工作是有用的。例如:
- 推荐引擎
- 时间数列预测法
- 科学实验
- 模型结构
其中现有数据中的异常值会影响模型实现,例如线性回归或分类任务。因此,在我们还不确定什么是正常行为的情况下,从现有数据中识别异常值是很重要的。
因此,这两个任务可以分开,第一个任务涉及新生成数据中的新颖性检测,而第二个任务涉及基础数据中的异常检测。我们主要关注第二个领域,尽管下面概述的方法也可以应用于第一种情况。
我为此使用的数据集是前七代神奇宝贝的数据集,总共包含 801 个神奇宝贝。具体来说,我将重点分析这个数据集中 HP 属性的分布,以便能够检测任何潜在的异常。当然,通过这些方法检测到的数据集中的任何异常可能实际上不是异常,但是我们可以根据结果做出选择。
分布图
第一种方法是通过分布图检查基础数据集的分布。这可以使用以下代码实现:
#create the displot
sns.displot(pokemon["hp"],
kde = True)#label the axis
plt.xlabel("HP", fontsize = 15)
plt.ylabel("Count", fontsize = 15)
plt.title("Pokemon HP distribution", fontsize = 15)plt.show()
作者图片
由此我们可以看到,该分布呈现正偏态,有几个点位于该分布的最右端。根据视觉检查,我们可以说,血量大于 200 的神奇宝贝可能是该数据集中的异常值。这可以通过以下方式从数据集中提取:
pokemon_above_150_HP = pokemon[pokemon["HP"] > 150]
pokemon_above_150_HP
作者图片
我们可以看到,这导致了 8 个潜在的异常值,但这只是基于纯粹的视觉检查。
Z 值
我们可以看到 HP 属性的分布大致是正态的,尽管有一定程度的倾斜。因此,我们可以通过使用 Z 分数来补充视觉检查。这基于以下公式:
其中,𝜇是数据的平均值,𝜎是标准偏差。这样做的目的是查看数据点距离数据集平均值有多少标准差。数据点越远,Z 值越高,我们就越有可能认为该数据点是异常值。这可以在 Python 中实现为:
#calculate the Z score
pokemon["HP_z"] = (pokemon["hp"] - pokemon["hp"].mean())/pokemon["hp"].std()
在此基础上,我们可以使用 Z 分数来检查大于平均值 2、2.5、3 或 3.5 倍标准差的数据。选择哪个 Z 值作为临界值将取决于基础数据,但这里选择临界值 3 将提取以下神奇宝贝:
作者图片
这里的主要区别是,这包括那些与 150 或以上的 HP,而不仅仅是大于 150。因此,这表明,就该数据集而言,最初的目测检查和截断点的选择是相对准确的。
箱线图
另一个好方法是箱线图。这又是另一种可视化方法,可用于识别数据集中的任何异常值。这样做的依据是,任何小于下四分位数减去四分位数间距的 1.5 倍或者大于上四分位数加上四分位数间距的 1.5 倍的值都可以被视为异常值。在图上,这显示为超出箱线图本身的最小值和最大值的单独点。这可以使用 Seaborn 库来实现,如下所示:
#create the boxplot
ax = sns.boxplot(x = pokemon["HP"])#add labels to the plot
ax.set_xlabel("HP", fontsize = 15)
ax.set_ylabel("Variable", fontsize = 15)
ax.set_title("pokemon HP boxplot", fontsize =20, pad = 20)plt.show()
作者图片
与分布图相比,这个箱形图更清楚地表明了哪些数据点可以归类为异常值,我们可以看到,这表明不仅在分布的高端有异常值,而且在分布的低端也有异常值。
Tukey fences
可以使用四分位距的值提取这些点,如下所示:
#extract the upper and lower quantiles
pokemon_HP_lq = pokemon["HP"].quantile(0.25)
pokemon_HP_uq = pokemon["HP"].quantile(0.75)
#extract the inter quartile range
pokemon_HP_iqr = pokemon_HP_uq - pokemon_HP_lq#get the upper and lower bounds
lower_bound = pokemon_HP_lq - 1.5*pokemon_HP_iqr
upper_bound = pokemon_HP_uq + 1.5*pokemon_HP_iqr#extract values outside these bounds
Pokemon_IQR_outliers = pokemon[(pokemon.HP <= lower_bound) | (pokemon.HP >= upper_bound)]
Pokemon_IQR_outliers
作者图片
这表明比以前的检查有更多的异常值。事实上,这表明一个神奇宝贝的血量低于下限,而 23 个神奇宝贝的血量高于上限。
考虑到大量的潜在异常值,这种方法的替代方法是使用替代值乘以四分位间距。为了从中获得极端的异常值,而不是只乘以 1.5,我们可以乘以 3。这样做,我们得到:
作者图片
这表明在分布的上端只有六个异常值。您选择哪一个将取决于您想要识别的异常值的类型。
集群
最后一种可能使用的方法是聚类。聚类的目的是能够从数据集中识别组,其中潜在的离群值可能适合极端组或它们自己的组,这取决于它们的特征与基础数据集的不同程度。对于单变量分析来说,这可能会限制其明确识别不同组的能力,但是可视化结果可能会比仅仅检查下面的分布更清楚地识别异常值。因此,使用 K 均值聚类,这可以实现为:
#convert the HP values to a float to be able to use numpy
HP_raw = pokemon["hp"].values.astype("float")
#use the kmeans function from scipy
centroids, avg_distance = kmeans(HP_raw, 4)
#extract the groups from the data
groups, cdit = vq(HP_raw, centroids)#plot the results
#assign groups back to the dataframe
pokemon["HP_groups"] = groups#plot the scatter plot
fig = px.scatter(pokemon, x = "hp", y = pokemon.index,
color = "HP_groups",
hover_name = "name")
#add a title
fig.update_layout(title = "K-Means outlier detection",
title_x = 0.5)
#show the plot
fig.show()
作者图片
从中我们更有可能识别出分布的低端和高端的异常值。
这些方法表明不同的潜在异常值都来自同一数据集的事实表明,异常值检测不是一门精确的科学,必须做出判断。其中的一个重要部分是决定需要对这些异常值做什么,以及它们从数据集中移除的意义,输入值以覆盖这些异常值,或承认它们的存在但继续按原样进行分析。
这当然将取决于识别异常值的目的、基础数据集和未来将执行的分析。虽然试图从整个数据集的单个变量中找出异常值的实际应用可能会受到限制,但这些方法可用于补充多元异常值检测算法,如隔离森林、局部异常值因子或椭圆包络线,其中可分析异常值得分以确定污染值。
可用代码:【https://github.com/PhilipDW183/Outlier_detection
可用数据集:https://www.kaggle.com/rounakbanik/pokemon?select=pokemon.csv
https://philip-wilkinson.medium.com/membership [## scikit-learn 决策树分类器简介
towardsdatascience.com](/introduction-to-decision-tree-classifiers-from-scikit-learn-32cd5d23f4d)
单变量与多变量预测
生命科学的数理统计和机器学习
DESeq2 与 LASSO 对基因表达的预测能力
作者图片
这是我的专栏 生命科学的数理统计和机器学习 中的第二十一篇文章,我试图以简单的方式解释生物信息学和计算生物学中使用的一些神秘的分析技术。在我之前的文章为组学集成选择特征中,我给出了多变量特征选择的例子,并提到了它相对于单变量特征选择的优势,但没有实际演示。在本帖中,我们将比较多变量模型如 【套索】PLS随机森林 与单变量模型的预测能力,如著名的差异基因表达工具 DESeq2 以及传统的 曼-惠特尼 U 检验 和 斯皮尔曼使用骨骼肌 RNAseq 基因表达数据集,我们将展示使用多变量模型构建的预测得分,以优于来自单价特征选择模型的预测得分。
骨骼肌 RNAseq 基因表达数据
这里,我们将量化几种特征选择方法的预测能力:a)单变量(逐个)特征选择,b) 多变量(全部)特征选择。出于演示目的,我们将使用来自 GTEX 人类组织基因表达联盟 的骨骼肌 RNAseq 基因表达数据集(为简单起见,随机取样 1000 个基因)。
版本 6 GTEX 骨骼肌数据集包括 157 个样本。在这里,我们加载基因表达矩阵 X,并删除低表达基因。为了与后选择组学整合特征保持一致,我们将使用性别作为我们将要预测的响应变量 Y。让我们快速观察一下降维后的样本,如 PCA。
作者图片
正如我们所看到的,PCA 图并没有显示基于骨骼肌基因表达数据的雄性和雌性之间的明显区别。我们可以假设仅来自性染色体(X 和 Y) 的基因可以在雄性和雌性之间提供完美的分离,但是我们在这里没有观察到,因为:1)大多数基因来自常染色体,2)随机采样了 1000 个基因,所以我们可能没有从 X 和 Y 染色体上采样很多基因。在下一部分中,我们将把数据集分成训练和测试子集,然后在训练集上实现单变量和多变量特征选择(训练)模型,并且使用平衡假阳性(FPR)和真阳性(TPR)率的 ROC 曲线 技术在测试集上评估模型。
性别预测:套索法与单变量法
为了评估单变量和多变量模型的预测能力,我们需要对独立的数据集进行训练和评估。为此,让我们将数据集分成训练(80%的样本)和测试(20%的样本)子集。为了确保我们的评估不是基于特定的“幸运”数据分割,我们将多次随机分割成训练和测试子集,计算每次 ROC 曲线,并对多个 ROC 曲线进行平均。这样,我们将一举两得:为每个模型的 ROC 曲线建立置信区间,并使 ROC 曲线平滑且美观,否则它们会显得“尖锐”,除非你在测试子集中有大量样本,而我们这里肯定没有。
在之前的文章中,我展示了如何使用 LASSO 进行多变量特征选择,以及使用 Spearman 相关性进行单变量特征选择。为了进行比较,我将再添加一种单变量特征选择方法,即 Mann-Whitney U 检验,它应该在很大程度上与 Spearman 相关性相当,因为两者都是非参数和基于等级的单变量方法,不假设数据的特定分布。为了将通过单变量方法单独选择的基因组合成预测分数,我们将通过其表达和性别之间的个体关联的 p 值来使用它们的排序,用 Bonferroni 程序(或不太保守的 Benjamini & Hochberg FDR 程序)校正多重测试。这通常导致在多次测试调整后,在训练数据集上出现一些差异表达的基因。此外,显著差异表达的(雄性和雌性之间)基因可以通过计算它们对训练数据集的影响/权重(雄性和雌性之间基因表达的 Spearman rho 和倍变化的对数)和它们对来自测试数据集的样品的基因表达值的乘积而被压缩成预测分数。让我们对其进行编码,并比较模型之间的 ROC 曲线。
作者图片
这里我们可以得出结论,LASSO 比两种单变量特征选择方法具有更大的预测能力。为了更好地了解这三种方法的 ROC 曲线下面积(AUC ROC)的差异,并能够进行统计测试来说明 ROC 曲线之间的差异有多显著,让我们根据 LASSO、单变量 Spearman 相关和 Mann-Whitney U 检验制作一个 AUC ROC 的箱线图。
作者图片
我们可以看到,Spearman 相关性和 Mann-Whitney U test 单变量特征选择模型具有可比的 AUC ROC 指标(尽管 Mann-Whitney U test 更好),并且与 multivarite LASSO 相比,两者都具有明显更低的AUC ROC,即预测能力。
然而,这种比较可能会有偏差。在谈到单变量模型(Spearman 和 Mann-Whitney U 检验)时,我们提到在Benjamini&hoch Berg FDR校正多重检验后,只有少数基因是显著的。因此,我们在构建单变量模型的预测分数时只使用了几个基因,而 LASSO 选择了更多的基因,大约 30 个,请参见我的 github 上的完整代码。如果 LASSO 更好的预测能力仅仅是因为更多的特征被用于其预测得分,会怎么样?为了检验这一假设,在下一节中,我们将暂时忽略 Benjamini & Hochberg FDR 校正,并单独使用 p 值排序,通过 Spearman 相关和 Mann-Whitney U 检验确定约 30 个最具预测性的基因。换句话说,我们将使用与用于构建预测分数的多变量套索相同数量的基因。通过所选基因的数量模拟 LASSO 的相应单变量模型将被称为 Spearman(与约 30 个差异表达基因的 Spearman 相关性)和 MWU30(与约 30 个差异表达基因的 Mann-Whitney U 检验)。
性别预测:DESeq2 与多元方法
在本节中,除了将 LASSO 与 Spearman(约 30 个差异表达基因的 Spearman 相关性)和 MWU30(约 30 个差异表达基因的 Mann-Whitney U 检验)模型进行比较,我们还将添加一些其他流行的单变量和多变量模型。
首先,当一个人做差异基因表达分析时, DESeq2 软件是使用的金标准。这个工具名声很好,在 RNAseq 社区中非常受欢迎。这是一个单变量工具,也就是说,它假设基因表达计数的负二项分布,执行逐个基因的测试。此外,它应用了方差稳定程序,其中高表达基因帮助低表达基因被正确测试。将 DESeq2 的预测能力与 Mann-Whitney U 检验和 Spearman 相关性进行比较是很有趣的,它们基本上利用了相同的单变量概念,但都进行非参数类型的检验,与 DESeq2 相反,deseq 2 假定基因表达的负生物学分布,因此进行参数检验。同时,我们将计算一个 DESEQ2_30 模型,该模型使用与 LASSO 选择的相同数量的基因(按其与性别关联的 p 值排序)来构建预测得分。这类似于 SPEAR30 和 MWU30 型号。
其次,我们将添加两个多变量特征选择模型,以与 LASSO 和单变量模型进行比较。这两个是偏最小二乘判别分析( PLS-DA )和随机森林,它们都是常见的多元模型。其中一个(PLS-DA)和 LASSO 一样是线性的,另一个(随机森林)是非线性的。这里,我们不仅旨在比较单变量特征选择模型和多变量特征选择模型,还想看看非线性随机森林与线性 LASSO 和 PLS-DA 相比是否能提高预测。
与上一节一样,我们将通过将数据集分成多次训练和测试来围绕 ROC 曲线建立置信区间。它涉及到很多编码,我在这里不展示代码,但是欢迎你在我的 github 上查看。下面我只给出了在多次训练测试分割后每个模型的平均 ROC 曲线以及 AUC 的箱线图。
作者图片
作者图片
我们在这里观察到一些有趣的事情。首先,与所有多变量模型相比,所有单变量模型的预测能力似乎更差。即使是最差的多变量模型,这里似乎是随机森林(RF),也比最好的单变量模型(这里似乎是曼-惠特尼 U 检验(MWU))具有显著更高的 AUC ROC。
第二,与 LASSO 选择的基因数量相同的所有单变量模型(DESeq230、SPEAR30 和 MWU30)未能与所有其他单变量或多变量模型竞争,这意味着单变量模型具有较差预测能力的原因不是由于选择的特征/基因数量不同,而是由于对构建预测分数的基因的不同排序和权重。
第三,对于这个特定的 RNAseq 基因表达问题,与线性多元 LASSO 和 PLS-DA 模型相比,非线性多元随机森林似乎没有改善预测。然而,根据我的经验,这是许多生命科学问题的常见情况,在开始非线性分类之前,检查简单的线性模型通常是值得的。
第四,也是最有趣的,DESeq2 单变量参数预测得分似乎不仅比多变量模型(LASSO、PLS-DA、Random Forest)表现更差,而且比单变量非参数模型(如 Spearman correlation 和 Mann-Whitney U 检验)表现更差。考虑到提到的非参数测试是如此简单,以及 DESeq2 的杰出声誉,这是非常出乎意料的。然而,事实证明,至少对于这个特定的数据集,简单的 Spearman 和 Mann-Whitney 非参数检验在预测能力方面优于 DESeq2 。
加分:套索 vs 山脊 vs 弹力网
另外,在本节中,我们将比较 LASSO (L1 规范)、Ridge (L2 规范)和 Elastic Net(L1 和 L2 规范的组合)预测得分的预测能力。惩罚线性模型族的这三个成员之间的差别通常并不明显。不涉及细节(有许多文献解释了这种差异),我们只强调 LASSO 是最保守的方法,因此由于生命科学数据的高噪声水平,在生命科学中通常是首选方法。弹性网在脊的凸优化优势和套索的严格性之间提供了很好的平衡,在癌症研究中很受欢迎。下面,我们再次展示了在 RNAseq 基因表达数据集的 100 次训练测试分割后,套索、脊和弹性网的平均 ROC 曲线,以及 AUC ROC 度量的箱线图。
作者图片
作者图片
我们可以看到,LASSO 和 Elastic Net 给出了几乎相同的 ROC 曲线,并且优于已知最宽松的 Ridge 模型,这显然不利于模型泛化,因此也不利于预测目的,因此 Ridge 可能不是处理有噪声的生命科学数据时的首选。
摘要
在本文中,我们了解到,与单变量模型相比,多变量统计模型似乎具有更强的预测能力。至少对于本文研究的 GTEX 骨骼肌 RNAseq 基因表达数据,单变量差异基因表达工具 DESeq2 不仅与 LASSO、PLS-DA 和 Random Forest 等多变量模型相比,而且与 Spearman correlation 和 Mann-Whitney U test 等简单的非参数单变量模型相比,都表现出了较差的预测。
像往常一样,请在下面的评论中告诉我生命科学和计算生物学中的哪些话题对你来说特别神秘,我将在本专栏中尝试回答这些问题。在我的 github 上查看完整的笔记本。在 Medium 关注我,在 Twitter @NikolayOskolkov 关注我,在 Linkedin 关注我。下次我们将讨论如何在 UMAP 空间聚集,敬请关注。
普遍的对抗性扰动可能会对自动驾驶汽车构成威胁
人工智能校准和安全
论文综述:自主车辆物体类别检测对普遍敌对干扰的弹性
在这篇文章中,我将讨论我作为合著者撰写我的第一篇同行评审出版物的旅程:自主车辆物体类别检测对普遍敌对扰动的弹性 , 最近被授予2021IEEE iem tronics(国际 IOT,电子和机电一体化会议)最佳口头陈述。
自动驾驶汽车这些天越来越受关注。为了让自动驾驶车辆识别人、交通灯和其他车辆以做出关键任务决策,物体检测是自动驾驶系统中的关键任务之一。然而,众所周知,基于深度学习的算法容易受到被称为对抗性干扰的精心制作的噪音的影响。
因此,我们必须评估我们在自动驾驶汽车中使用的物体检测算法是否对这些扰动具有鲁棒性,以确保它可以安全地部署在现实世界中。如果不这样做,可能会发生严重的后果,例如,检测到街道上的停车标志,因为不同的物体会使汽车忽略该标志,并撞上另一辆汽车或人。
当我意识到这个问题的动机时,我搜索了关于对抗目标检测攻击的著作,一篇关于“对抗目标检测的普遍对抗扰动”**【1】的论文引起了我的注意。这是第一个从经验上证明物体探测任务中普遍对抗性干扰存在的工作。我想到,对手也可以利用这种针对自动驾驶汽车的对抗性攻击。
为什么目前对对抗性鲁棒性的研究相当普遍,而不涉及自动驾驶汽车等任务关键型应用?难道我们不应该在应用程序级别研究对抗性攻击和防御吗?
这个问题让我和我的顾问专注于一个流行的数据集 COCO2017 中与自动驾驶汽车相关的最重要的类别。在研究领域,理解敌对扰动对与自动驾驶汽车相关的特定类别的影响似乎探索得较少。虽然[1]已经探索了针对对象检测的对抗性攻击,但不是在自动驾驶汽车的背景下。
这种差异导致我制定了三个研究问题 :
- 与[1]中使用的 PASCAL VOC 相比,这种普遍扰动的存在会扩展到更大的真实世界背景数据集 COCO 吗?
- 我们是否完全将普遍扰动的影响从其他因素中分离出来,例如包括没有扰动就已经被错误分类的图像?
- 通用扰动对 COCO 子集(仅包括与自动驾驶相关的类别)的影响有多大?
介绍
本文介绍了与自主车辆相关的五个类别中普遍扰动对物体检测的影响:人、停车标志、汽车、卡车和交通灯。我们从经验上证明,对包含这些类别的图像训练集计算普遍扰动并将那些发现的扰动添加到那些图像中会使对象检测器在大多数图像上检测不到那些类别。
论文的主要贡献包括:
- 在目标探测中建立类别级的脆弱性等级以对抗普遍的敌对扰动
- 通过管理数据集以仅包括其中检测器正确预测了至少一个指定类别的那些图像,完全隔离对抗扰动对检测结果的影响
数据集管理
[1]使用 PASCAL VOC 作为他们实验的主要数据集,这是一个规模相对较小的对象检测数据集,更重要的是,它没有捕捉到真实视觉世界的复杂性。我们在这个实验中使用了 COCO2017 训练集,因为它是用于具有更真实上下文环境的对象检测的事实上的标准大规模数据集。
此外,我们声称,我们需要对目前用于对抗性攻击实验的数据集进行更精细的管理。策展分两个方向进行: (1)班级*(2)影像。***
班级
从自动驾驶的背景来看,我们不需要数据集中的所有 80 个类。这可能会妨碍评估普遍扰动的影响,特别是在自动驾驶汽车最常遇到的街道环境中。因此,我们只使用我们的数据集的一个子集,只策展我们感兴趣的图像类别。
*为了对自动驾驶汽车最相关的类进行实验,我们选择了 **5 个类(人、汽车、卡车、交通灯、停车标志)。*我们可以使用 COCO API 轻松搜索我们感兴趣的特定类别的图像。
形象
为了完全隔离敌对扰动对检测性能的影响,我们过滤了特定于类的数据集,以仅包括其中检测器正确预测了至少一个目标类的图像。我们这次实验的主要对象检测模型是来自 Detectron2 库的更快 RCNN /特征金字塔网络(FPN) / Resnet50 基网络(在 COCO2017 训练集上预训练)。
为了滤除图像,我们使用了更快的 RCNN 对阈值为 0.5 IoU 的图像进行检测。只要对象检测器能够检测到我们的对象类别的至少一个实例,我们就会将该图像保留在我们的数据集中。如果检测器错过了图像中的所有对象实例,则该图像将不再被使用,因为该图像不需要被攻击,因为它已经发生故障。
由于时间和资源有限,我们精选了特定于类别的数据集,包括 500 幅人物、汽车和卡车图像、344 个交通灯和 313 个停车标志。特定于类的数据集意味着所有图像至少有一个该目标类的实例,因此这些数据集之间可能有重叠,因为许多图像可能有多个我们选择的类。现在,我们准备计算每个特定于类的数据集的通用扰动。
针对目标检测的通用对抗性扰动
通用对抗性扰动 [2]的想法很有趣,因为与需要为每个图像创建的图像特定扰动相反,图像不可知扰动在某种意义上更危险,因为一旦你发现了一个可以很好地推广到不同数据集、图像和模型的扰动,它就可以广泛地用于攻击各种对象检测系统。
我们建立在由[1]提出的方法上,因为他们第一次证明了在物体探测任务中普遍扰动的存在。[1]引入了 通用密集对象抑制(U-DOS) 算法来计算通用扰动,该算法将使对象检测器看不见,以在图像集 I 的大多数图像中找到对象,同时保持人眼不可察觉。如果你看完这个帖子还不清楚这个算法,请阅读[1]。
图一。U-DOS 算法[1]。
给定对象检测器 D、图像集 I、扰动的最大 inf_norm 约束和历元数,UDOS 计算并返回通用扰动 v 。
对于每个时期,它在图像集 I 中的每个图像上迭代,以首先检查将当前通用扰动添加到该特定图像是否导致遮蔽检测器。如果是,跳到下一张图片。否则,通过优化目标函数(2)来计算 v_i(与我们修改的原始算法 1 略有不同)。v_i 是攻击第 I 个图像并将其添加到我们的通用扰动 v 的扰动。在更新之后,它总是验证更新的扰动的 inf 范数被约束在 Xi 内,该超参数是我们设置的以确保人类的准感知性。
图二。U-DOS 算法的原始目标函数[1]。
我们对[1]提出的算法 1 中的目标函数(第 6 行)进行了如下修改:
1.目标函数中的第一项:取决于对象检测器及其实现,从检测器的输出中访问背景类概率可能是棘手的,因此我们移除了背景类项,并且仅关心对象类的输出的总和。修正后的 F(I_i,v,v_i)如下:
图 3。U-DOS 算法目标函数中第一项的修正。[1]
2.等式中的第二项:曾经是||的 L-inf 范数。||,所以在运行一些时期后,它停留在最大约束(Xi),因此比较超过某个时期的扰动幅度是没有意义的。因此,我们使用平均 L1 范数——L1 范数除以像素数来比较扰动范数如何平均增加。
基于这些变化,我们希望最小化第 I 个扰动图像上的扰动范数和目标检测概率:I_i + v + v_i (I_i:原始图像,v:通用扰动,v_i:第 I 个图像的附加扰动)。需要最小化的函数如下:
图 4。U-DOS 算法的改进目标函数。
为了优化(2),我们使用梯度下降来为每个第 I 个图像找到 v_i。α是我们乘以目标函数相对于 v_i 的梯度的步长,v _ I 是我们为了更新普适扰动而添加的扰动。
图 5。梯度下降以更新增加的扰动。[1]
这种攻击非常简单,因为我们使用其输出相对于输入扰动的梯度,这意味着我们可以攻击图像中任意数量的类。
实验和结果
超参数
对于这个实验,我们需要调整四个主要的超参数:
- n_epochs:时期的数量
- 阿尔法:学习率
- xi:扰动的最大范数约束
- score_threshold:对象检测器将其视为最终预测
在一系列试点实验之后,我们确定了以下参数值:n_epoch=250,Xi=10,α= 20,score_threshold=0.7。
韵律学
在我们的实验中,我们评估了通用扰动对数据集的影响,因为我们通过迭代使用两个指标找到了更强的扰动:实例级和图像级盲度。我们为每个类别运行实验,以在类别级别比较易受干扰的程度。
***图像级盲度:*物体检测器 D 能够以高于阈值的置信度找到至少一个物体的图像与图像总数 N. (4)的比率
这里要提到的重要一点是,在策展过程中,我们需要确保在添加通用扰动之前,数据集的图像级盲度始终为 1.0。这是因为我们应该只包括至少有一个物体的置信度高于阈值的图像。
图 6。图像级盲度度量[1]。
***实例级盲度:*检测器 D 在每幅图像中找到的置信度超过给定阈值的平均实例数。此度量显示在实例级别有把握地检测到多少目标类的对象。(5)
图 7。实例级盲度度量[1]。
结果
下面的第一张图显示了随着标准的增加,扰动对每个类别的影响。为了绘制这个图,我们跟踪实例级和图像级的盲度,因为我们为五个类别中的每一个改变扰动范数。在进行了一系列的实验后,我们发现所有 5 个类别的图像和实例级盲度随着我们发现具有更强范数的普遍扰动而降低。很明显人在图像级和实例级失明程度中是最有弹性的类别,其次是汽车、交通灯、卡车和停车标志增加了干扰标准。进一步调查和分析为什么某些类别更能抵御这种攻击将是一个有趣的方向。
图 8。图像级盲度与 5 个类别上的扰动范数[3]。
图 9。实例级盲度与 5 个类别上的扰动范数[3]。
基于我们上面的实验结果,我们已经在图像和实例级盲度中建立了一个类别排名,随着时期和规范的增加,对每个类别对普遍扰动的弹性进行排名。随着扰动范数和迭代次数(历元)的增加,我们通过比较图像和实例级盲度的下降率来设置排序。因为这两个指标密切相关,所以这两个指标的排名遵循相似的模式是有意义的。
表 1。对普遍扰动的复原力的分类等级。从最高到最低[3]。
为了形象化,我挑选了一些样本图像,它们清楚地表明,添加在数据集上计算的发现的通用扰动成功地使 Faster-RCNN 在检测我们指定攻击的目标类时失败。前两幅图像显示,在将计算出的攻击停车标志的扰动添加到图像后,原始图像中的 2 个停车标志检测消失。接下来的两幅图像显示,在添加计算出的扰动以攻击交通灯后,原始图像中的 4 个交通灯检测被移除。除此之外,有趣的是,添加扰动也会影响对非目标类别的检测,例如汽车。
图 10。停止对原始图像[3]的标志检测。
图 11。在受干扰的图像[3]上检测停车标志失败。
图 12。对原始图像进行交通灯检测[3]。
图 13。扰动图像上的交通灯检测失败[3]。
结论
从使用不同的精选数据集评估原始工作的有效性开始,我了解到准可感知的普遍扰动会对与自动驾驶相关的数据集安全的核心造成真正的伤害。此外,发现哪一类特别容易受到普遍扰动的影响,将对我们应该如何设计自动驾驶系统产生重要影响,以优先考虑我们应该重点防御的类别,而不仅仅是建立一个防御系统来抵御整体的敌对攻击。
完成这个实验后,我意识到我可以直接在大规模的驾驶特定数据集上进行实验,例如,Waymo 或 Berkeley DeepDrive,以研究自动驾驶汽车领域的对抗性攻击的影响。
我们未来的工作将是对这些数据集进行不同的对抗性攻击实验,以研究更多攻击状态的影响,或开发针对自动驾驶汽车的新型攻击,并提出可以提高自动驾驶系统鲁棒性的防御措施。
如果有人想使用这个,请引用我们的论文并指出引用,我已经分享了我的代码库。如有任何问题,请随时联系 nayeem@umd.edu 或 aspiringtechsavvy@gmail.com。任何建设性的批评或反馈都会受到欢迎。感谢阅读。
参考
[1]李,张俊杰,黄,王(2020).针对目标探测的通用对抗性扰动。模式识别, 110 ,107584。
[2] Moosavi-Dezfooli,S. M .,Fawzi,a .,Fawzi,o .,& Frossard,P. (2017 年)。普遍的对抗性干扰。IEEE 计算机视觉和模式识别会议论文集(第 1765-1773 页)。
[3] Mohammad Nayeem Teli 和 Seungwon Oh。“自主车辆物体类别检测对普遍扰动的弹性”,被认可出现在 IEEE 国际 IOT、电子学和机械电子学(IEMTRONICS '21)中。
普适近似定理:软件 2.0 的代码重构?
思想实验
约书亚·阿拉贡在 Unsplash 上拍摄的照片
什么是 UAT?
普适逼近定理到底是什么?通俗地说,UAT 的意思就是给一个隐层神经网络足够多的神经元。它可以逼近(或近似模拟)给定输入范围内的任何连续函数。这意味着一个隐层神经网络是一个终极的柔性函数逼近器。可能有点太灵活了。
吸取的教训
**由于普适逼近定理的灵活性,过去常常推动 AI 研究人员将注意力大多放在浅层神经网络上,从而在某种程度上阻碍了深度学习的发展进程。**这个有意思。想想看,一个“浅而宽”的神经网络倾向于“记住”所有特征来逼近目标函数。然而,更深层次的网络往往在特征提取方面更加抽象,并找出可以应用于数据集许多部分的模式。他们显然概括得更好。并且用更少的计算能力获得更好的结果。
更深入
如果你是一名软件开发人员,你觉得这听起来怎么样?‘代码重构’! 开发人员重构他们的代码,将重复的代码片段放到函数中,尽可能地重用它们。干净的代码通常是更好的代码。深度神经网络在某种程度上做了同样的事情。通过拥有更多的层,它使网络能够更好地“重构”自己,并学习更多的通用模式,从而更有效地实现相同的目标。这导致了更好的(在性能和效率方面)模型。
软件 1.0 与软件 2.0
还有哪些软件开发技术我们可以应用到机器学习上?更准确地说,我们从‘软件 1.0’中学到的东西可以应用到‘软件 2.0’上吗?(如果你不熟悉“软件 2.0”的概念,我强烈推荐你观看下面来自 Andrej Karpathy 的视频,它并不完全适用于所有情况,但绝对值得注意,并得到了特斯拉成功的支持!)
根据 Karpathy 的说法,我们目前在软件工程中所做的事情,即有才华的人编写代码来完成任务和解决问题,是“软件 1.0”,人类通过直接告诉计算机如何做每一步来为这个过程做出贡献。在“软件 2.0”的新范式中,机器学习和深度学习被广泛采用,人类通过以数据集的形式提供大量人们做某事的例子来做出贡献,计算机和模型将自动计算出如何做到这一点。事实上,特斯拉的自动驾驶系统有相当一部分是由深度学习模型驱动的。
一些人仍然怀疑“软件 2.0”方法是否会有光明的未来。我们从 1.0 到 2.0 的道路仍有待讨论。对于机器学习研究者和实践者来说,重新应用传统软件工程的智慧可能仍然是一个很好的探索方向。欢乐时光!
如果你想了解更多关于万有逼近定理的知识,可以参考我下面的文章:
从乐高乐园到神经网络:通俗易懂的通用逼近定理|作者李立伟| 2020 年 12 月|走向数据科学
大学学位 vs 暑期学校 vs 自学:数据科学和数据分析
瓦西里·科洛达在 Unsplash 上的照片
据招聘网站称,受大数据和人工智能的推动,对数据分析和数据科学技能的需求正呈指数级增长。随着公司寻找利用大数据力量的方法,急需精通数据分析和数据科学的技术专业人员。然而,高技能申请人的供应增长速度较慢,这使得这类工作非常适合转行者。
在这篇博客文章中,我将假设你不是高中毕业,而是已经拥有大学学位(不是计算机科学或统计学)和/或已经工作了几年,现在正在考虑如何成为一名合格的数据分析师或科学家。当然,在决定如何提高你目前的技能时,有许多因素需要考虑,比如以前的经验、财力以及你想在这方面投入多少时间,我的意图是概述最常见的提高技能方式的利弊:大学学位、速成课程(比如暑期学校)以及各种类型的在线课程。
我目前是伦敦大学学院计算机科学系的助教,过去曾在一所数据科学暑期学校任教,并且因为我的学士学位是法律,所以我做了大量的自学,所以我相信我可以很好地概述以上所有方面的利弊。
数据科学、机器学习或数据分析硕士学位
显然,大学学位(在英国)的主要缺点是费用。如果你正在考虑全日制学习,你不仅需要支付学费,还需要支付一整年的生活费用。第二个问题是,它是基于申请的,你可能不会被你感兴趣的项目录取。要想做数据科学或者机器学习的硕士,需要有一个量化学科的学士学位。所以,除非你学过数学、工程学、经济学或金融学,否则你没有资格申请这样的硕士课程,你必须先修一门转换课程(计算机科学硕士)。对于没有计算机科学背景,但有财力和时间的人来说,我可以强烈建议在完成法学学士学位后,参加一个转换课程,就像我在 2015 年做的那样。但是目前这已经超出了本文的范围。
另一个不利之处是,在学位结束时,你可能不一定有不同项目的投资组合可以展示给潜在的雇主。课程作业通常不能反映真实的商业问题,你的硕士论文可能更偏重于学术研究。
如果你有必要的定量背景和财务资源(或获得学生贷款),那么攻读数据科学、机器学习、数据分析或金融计算等更专业的硕士学位肯定有其好处:作为结构化课程的一部分,你将有机会接触各种模块,会见该领域的领先学者,结识有趣的人,结交新朋友,并(希望在后新冠肺炎时代)体验学生生活。
暑期学校/数据科学/机器分析短期强化课程
**优点:**对于以前很少或没有数据分析和数据科学经验的人来说,速成课程(2-4 周)提供了学习 Python 或 R、复习统计和假设检验、学习如何处理(数字)数据以及学习机器学习的基本概念的绝佳机会。像这样的课程有助于了解你是否真的想走这条职业道路,并有助于决定下一步该怎么走(例如,大学学位或其他更深入的课程)。
这种课程的费用和时间投入都很低,因此每个人都可以参加。
**缺点:**此类短期课程只是介绍性的,并不能为您提供成为数据科学家或数据分析师所需的所有知识和工具。许多概念都以黑盒的方式涵盖,没有深入数学。您可能会从 scikit-learn 中学习如何预处理数据并将其输入到逻辑回归分类器中,但不会学习逻辑回归的实际工作原理。
自学
所谓自学,我指的是一种你可以按照自己的进度进行的结构化在线课程,需要几个月才能完成,包括评估,最好还有某种辅导计划。
缺点:很难找到一个物有所值的合适课程。在我为这篇文章所做的研究中,我发现许多课程(并不便宜!)大纲不在线,需要请求,之后你就被垃圾邮件了。
许多被宣传为“数据科学”课程的课程实际上是数据分析课程,因为它们不涉及任何数学,而是数据库(SQL)和数据可视化方法。因此,如果你正在从事数据分析方面的职业,这些课程将涵盖你需要的一切。它们是否涵盖了一个数据科学家应该知道的一切,这是值得怀疑的。我没有找到一门涵盖线性代数和微积分的英语课程。有趣的是,当我搜索一门确实涵盖必要数学的课程时,我能找到的唯一一门课程是用俄语教授的——与关于数据科学和数据分析的课程是同一种语言,这些课程的教学大纲最吸引我,我过去曾向朋友和家人推荐过这些课程(他们都对它们非常满意)。
鉴于你可以按照自己的进度完成这些课程,你需要有必要的时间管理技巧和动力来完成它们,因为你通常不像在大学那样有严格的截止日期或考试
优点:你可以按照自己的进度学习这些课程,这当然也是一个优点。你不必放下工作,在晚上或周末做这些事情。
这些课程中的许多价格非常合理,因此每个人都可以参加(我会远离价格在 5 位数范围内的课程)。
最后,你更有可能有一个基于行业的项目组合,你可以向雇主展示。其中一些项目甚至与行业合作伙伴密切合作,并可能将你与潜在雇主联系起来。
下面我列出了一些在线课程,我觉得它们的教学大纲很吸引人,价格也很合理:
- 用 Python 进行机器学习:从线性模型到深度学习(注:以下为完整课程)
- 统计与数据科学
- IBM 数据科学专业证书(注:数据分析多于数据科学)
我希望这篇文章能帮助你决定什么样的技能提升方法最适合你,以及在选择学位或寻找在线课程时需要注意什么。
未知知识、贝叶斯推理和结构化高斯过程
思想和理论
为什么领域科学家知道的 ML 比他们想象的要多
马克西姆·兹亚迪诺夫&谢尔盖·加里宁
美国田纳西州橡树岭橡树岭国家实验室纳米材料科学和计算科学与工程中心
大约 20 年前,前国防部长唐纳德·拉姆斯菲尔德在提到情报情况时说了一句著名的话,“…有已知的已知;有些事情我们知道我们知道。我们也知道有已知的未知;也就是说,我们知道有些事情我们不知道。但也有未知的未知——那些我们不知道我们不知道的。”。尽管来自不同的背景,这句话深刻地描述了科学家的工作。我们建立自己的世界观,并基于我们所知道的、可以在教科书中读到的、或在整个职业生涯中从经验、与同事的讨论或在实验室中度过的无数个小时中学到的东西来建立基本的探索。这些是已知的知识。我们也经常知道我们不知道的事情——通常,这些已知的未知是我们研究的直接目标。也就是说,对于每个科学实验来说,未知的未知是至关重要的——我们关注范围之外的因素会极大地影响我们的测量、分析和结论。
显然,拉姆斯菲尔德非常简洁的陈述并不是第一次注意到把世界分成已知和未知的类型。据作者所知,这方面的第一份书面陈述可以追溯到纳赛尔·奥德·丁·图西(1201-1274),他说
Har kas ke bedanad va bedanad ke bedanad
阿斯布-埃凯拉德阿兹贡巴德-埃加敦贝贾汉纳德
Har kas ke nadana d va bedanad ke nadana d
甘兰·卡拉克-凯什贝·曼泽尔·贝雷萨纳德
达尔贾赫勒-莫拉卡巴德奥德-达尔贝马纳德
或者,从波斯语翻译过来:
任何知道的人,以及知道他知道的人
让智慧的骏马飞跃苍穹
任何不知道,但知道自己不知道的人
尽管如此,他还是能把他那只跛脚的小毛驴带到目的地
任何不知道的人,以及不知道自己不知道的人
永远陷在双重无知中
很有可能历史参考可以更早,但我们无法找到它们。也就是说,尽管从阿拔斯和倭马亚时代开始,科学探究工具取得了重大进步,但已知和未知因素在科学发现中的作用依然存在。
例如,在他的科学生涯中,第二作者与电化学应变显微镜(ESM)进行了广泛的合作,该技术允许通过测量由离子运动引起的材料的微小(小于氢原子的半径)膨胀和收缩来探测纳米水平的电化学反应[1,2]。ESM 中测得的信号是局部磁滞回线,代表材料对偏压的电化学响应。对于诸如二氧化铈 CeO₂的经典材料,这些磁滞回线在样品表面的不同位置之间是非常可重复的。这表明它们描述了扫描探针显微镜针尖-表面接合处的反应,并且不受材料成分(我们并没有期望太多)或表面粗糙度(这在 SPM 中总是一个问题)的可能变化的影响。然而,当在受控气体环境和真空中进行测量时,磁滞回线的形状完全改变。这反过来表明,大气环境是测量响应的一个重要因素。如果我们没有在几个大气中进行测量(这需要对显微镜进行非标准的修改),并试图在不考虑大气水的作用的情况下描述机制,这将是未知的未知的典型例子。可以说,它变成了一个已知的未知——这刺激了另一个十年的理论和实验研究,并导致铁电性和表面电化学之间不寻常的耦合的发现[3],以及其他发展。
也就是说,这三个已知/未知的范畴就是全部了吗?我们提出,当积极地将机器学习方法融入领域科学时,我们经常会发现未知的知识——这意味着先验知识的全部范围,从概括(物理定律)和特定领域的数据,一直到难以量化的直觉。因此,现在的问题是,我们如何将先前的知识,未知的知识,整合到科学发现过程中,并以一种有原则的和可量化的方式这样做。
贝叶斯公式奠定了这方面的一般框架。有许多优秀的书籍描述了贝叶斯方法,也有一些中型文章。对于第二作者来说,进入贝叶斯的首选切入点是 Martin [4]和 Lambert [5]的书,Kruschke [6]给出了贝叶斯和频率主义方法之间的系统比较。第一作者认为,关于贝叶斯分析的最好的(对于领域科学家来说)书是 Richard McElreath 的“统计再思考”。
下面,我们从领域科学家的角度给出经典贝叶斯公式。在这里,科学实验的目的是从新获得的实验数据中获得新的知识,也就是理论的概率。
**图一。**领域科学家视角下的贝叶斯公式。作者图。
这里,给定理论的数据的概率,或贝叶斯语言中的可能性,使用正演模拟直接访问。使用计算方法直接评估数据或证据的概率,无论是马尔可夫链蒙特卡罗还是变分推断。但是第三部分——理论的概率,或者先验——通常会引发最多的问题。事实上,经常针对贝叶斯模型的批评是它们需要先验知识,而这些先验知识很难被一致地建立。事实上,他们是——如果一个人完全停留在统计学领域。对于领域专家来说,先验知识是绝对必要的,它实际上定义了领域专长。然而,它是未知的已知,并且通常这种知识不容易量化或以可追踪算法形式的先验分布的形式建立。也许更重要的是,现在还不清楚如何将先前的知识整合到实验发现的主动学习流程中。让我们逐一考虑。
一旦实验数据可用,贝叶斯推理方法允许进行直接分析。例如,最近,我们利用高分辨率电子显微镜探索了铁电畴壁的结构[7]。这里,畴壁结构由自由能的特定函数形式决定,自由能产生描述畴壁轮廓的解析解。简单的函数拟合,如前所述[8,9],给出了参数的数值估计,但不允许超出这些。相比之下,贝叶斯方法允许以相对常数的先验分布的形式结合材料物理学的先验知识,这反过来可以从大量的公开数据、宏观测量等中获得。例如, Materials Project 等大型材料信息学项目的价值之一就是将来自多个独立来源的数据整合成易于访问的形式。
同样,贝叶斯框架允许回答一些重要的问题,如材料物理学的先验知识是否影响我们从实验中学到的东西(相当令人惊讶的是,我们知道的越多,我们学到的越多),材料行为的特定模型是否可以基于观察到的数据进行区分(在这种情况下不是),以及区分不同模型需要什么样的显微镜分辨率或信息限制。类似地,贝叶斯方法允许以概率方式定义许多“绝对”量——例如,对称性或结构单元等描述符[10]。
然而,下一个问题变成了我们是否可以使用贝叶斯方法进行主动学习和属性优化?原则上,可以使用上面详述的经典贝叶斯方法。这里,我们将先验假设定义为一个结构化的概率模型。给定实验数据,我们改进我们模型的参数,然后在参数空间上探索后验预测概率。与我们之前的帖子中描述的经典贝叶斯优化/主动学习(BO/AL)非常相似,期望值和/或相关的不确定性可用于指导测量(即选择下一个测量点)。
然而,在实践中,基于预期系统行为的结构化概率模型的 BO/AL 在模型仅部分正确时不能很好地工作。与此同时,这正是我们通常在实验中必须处理的问题,在实验中,即使最复杂的理论也只能在一定程度上描述现实,而且可能存在几种竞争模型,更不用说所有与测量相关的非理想性了。当然,另一种选择是用高度灵活的高斯过程(GP)来代替刚性的结构化概率模型。然而,后者通常不允许结合先前的领域知识,并且可能偏向于平凡的插值解决方案。
因此,我们引入了结构化高斯过程(sGP),其中经典的高斯过程被预期系统行为的结构化概率模型所增强[11]。这种方法允许我们平衡非参数 GP 方法的灵活性和编码到参数模型中的先验(物理)知识的刚性结构。后者的贝叶斯处理通过选择模型参数的先验,即结合过去的知识,对 BO/AL 提供了额外的控制。
更正式地说,给定输入参数 x 和目标属性 y ,经典 GP 被定义为 y ~ 多变量 ( m ( x ), K ( x , x `)),其中 m 是通常设置为 0 和的均值函数后者可以使用哈密尔顿蒙特卡罗(HMC)抽样技术来推断。然后,对新的/未测量的输入集的预测由下式给出
其中 θⁱ 是具有核超参数的单 HMC 后验样本。注意,通常假设的观察噪声被吸收到核函数的计算中。(我们用*下标表示新的输入和相关的预测——不幸的是,在撰写本文时,介质还没有对这个下标和其他下标的内嵌支持)。
在我们的 s GP 方法中,我们用一个结构化的概率模型代替上述等式中的常数均值函数 m ,该模型的参数通过 HMC 与核参数一起推断。然后,等式(1b)变成:
其中 ϕⁱ 是具有学习模型参数的单个 HMC 后验样本。该概率模型反映了我们关于系统的先验知识,但它不必是精确的,也就是说,该模型可以具有不同的函数形式,只要它捕捉数据中的一般或部分趋势。
使用结构化 GP 的贝叶斯优化
我们将通过具体的例子来说明 s GP 方法的优势。首先,我们将使用一个稍加修改的福雷斯特函数、f(x)=(5x-2)sin(12x-4),它通常用于评估优化算法。除了全局最小值之外,它还有两个局部最小值。我们的目标是仅使用少量的步骤(测量)来收敛到全局最小值。首先,我们将 BO 与 vanilla GP 一起使用。我们从种子点的“良好”初始化开始(在运行 BO 之前执行的“预热”测量),并使用置信上限 (UCB)采集函数和 k = -0.5,在每一步选择下一个测量点。不出所料,GP-BO 很快收敛到真正的最小值。
**图二。**使用普通 GP-BO 的黑盒函数优化:“良好”初始化的情况。作者图。
现在,让我们从一个“坏的”初始化开始,其中初始化的点落入一个局部最小值周围的区域。由于这种糟糕的初始化,GP-BO 陷入局部最小值,无法收敛到真正的最小值。我们注意到,在真实的实验中,人们通常没有使用不同的初始化来重新开始测量的奢侈,因此必须准备好处理不好的初始化。
**图三。**使用普通 GP-BO 的黑盒函数优化:“坏”初始化的情况。
看待上面的例子的一种方式是,我们陷入局部最小值,因为我们的算法不“知道”不同最小值的潜在存在。但是如果我们确实知道可能有更多的极小值(其中一个可能是真实的/全局的极小值),那么这个先验知识可以合并到 s GP 模型中。
具体来说,让我们将结构化概率模型定义为
其中 y ₀ ~ 均匀 (-10,10)aₙ~对数正态 (0,1)wₙ*半正态*(0.1)*x*ₙ⁰均匀 (0,1)为模型参数的先验。这个模型简单地告诉我们,在我们的数据中有两个极小值,但并不假设对它们的相对深度和宽度有任何了解,也不包含它们相距多远的信息。然后,我们用等式(3)中定义的概率模型替换 GP 中的常数先验均值函数 m ,并以与之前相同的方式运行“坏”初始化的 BO。
图 4。在初始化“不良”的情况下,使用 s GP-BO 进行优化。由于关于系统的部分先验知识(其具有不止一个最小值),优化算法能够将其自身从局部最小值中拉出,并收敛于真实/全局最小值。作者图。
我们可以看到,配备了预期系统行为的一些知识的优化算法能够将自己从局部最小值拉出来并收敛到全局最小值。我们已经在 GP-BO 和 s GP-BO 之间进行了系统的比较,针对种子点的几十种不同的随机初始化,并且在存在噪声的情况下,发现 s GP-BO 在几乎所有情况下都有更好的性能【11】。
为了理解 sGP-BO 的优越性能,我们可以比较 GP-BO 和 s GP-BO 在不同优化步骤的采集函数。
**图 5。**第 1、3、5、7 和第 9 步中普通 GP-BO(顶行)和 s GP-BO(底行)的采集功能。作者图。
显然,普通 GP-BO 很快锁定在局部最小值,其获取函数基本保持不变(图 5 中的顶行),因为算法“假设”它已经找到了真实/全局最小值。另一方面, s GP-BO(图 5 中的底行)中的采集函数在早期显示了一个具有多个最小值的结构,这有助于算法在过程的后期爬出局部最小值并收敛到真正的最小值,即使初始化非常糟糕。图 5 的底行中的采集函数的演变在某种意义上确实是显著的,因为该算法正在寻找第二个最小值,好像是由直觉驱动的。从某种意义上来说,我们在等式(3)中以 GP 均值函数的形式纳入的先验知识假设在某处存在第二个最小值,而采集函数突出显示了第二个最小值最有可能出现的位置。
但是如果这个“先验知识”只是部分正确呢?如前所述,与独立的概率模型相比, s GP-BO 的优势在于 GP 内核的灵活性允许我们使用不精确的,有时甚至是“不正确的”函数形式的模型。我们使用形式为m=aeᵃˣsin(bx)的结构化概率模型来说明这一点,BO 作为独立模型和作为 s GP 的一部分。我们注意到,虽然这显然不是描述 Forrester 函数的正确模型,但它确实捕捉到了数据中的一些趋势,例如存在一个全局最小值和多个局部最小值。
**图 6。**使用独立概率模型的 BO 结果(左)和使用完全相同的模型增强的 sGP-BO 结果(右)。作者图。
具有独立概率模型的业务对象(图 6,左侧)无法收敛到全局最小值。如果现实不适合所选择的模型框架,那么推论本身就太死板并且会失败。它也不能产生目标函数的令人满意的重建,即使在测量点周围,并且它的不确定性估计似乎不是特别有意义。另一方面, s GP-BO 使用相同的概率模型作为 GP 的一部分,轻松识别出真正的最小值(图 6,右)。它还对测量区域周围的基础函数进行了良好的重建,并提供了这些区域之外的有意义的不确定性估计,这可用于选择下一个测量点以完全恢复目标函数(如有必要)。
主动学习不连续函数的结构化 GP
作为我们的第二个例子,我们展示了如何使用 s GP 从稀疏和有噪声的观测中重建不连续的函数。我们注意到,不连续性的存在在相变物理学中是常见的,在相变物理学中,人们通常希望重建靠近相变点的感兴趣的性质的行为,以及在相变之前和之后的两个阶段中的行为。同时,标准 GP 不具备处理这种不连续性的能力。
图 7。 (a)不连续函数的噪声观测,(b)基础分段函数的基于普通 GP 的重构,© s 基于 GP 的重构,具有系统行为的“正确”模型,(d)基于 sGP 的重构,具有部分正确的模型。重构中的不确定性由采样预测中的离散度定义。作者图。
图 7a 示出了由形式的分段函数产生的观察值
我们的目标是从这些有噪声的数据点重建基础函数。首先,我们尝试普通 GP(图 7b)。它表现不佳,这并不奇怪,因为标准 GP 不具备处理不连续性的能力。直观上,它可以通过不连续性给核函数带来的矛盾需求来理解——具有大长度尺度的核不能描述不连续性,而小长度尺度需要多次测量来发现各处的函数行为。请注意,简单 GP 在测量区间之外的外推也很差(尽管在这种情况下,可以使用多种策略来解决这个问题)。
接下来,我们尝试用两种不同的概率模型增强的 s GP。第一个 s GP 由分段概率函数扩充,该函数具有一般幂律形式:对于xaxᵇxₜ和 cxᵈ 对于 x ≥ xₜ ,具有关于 xₜ 的均匀先验和关于其他参数的对数正态先验。它显示了一个良好的整体重建(图 7c),除了过渡区,我们没有足够的观察。然而,该区域也具有非常大的不确定性(采样预测的变化),表明人们可能想要在该区域进行额外的测量。在这种情况下,检查采样预测的行为也是值得注意的-本质上,它们在切换点位置的估计上是不同的。同样,这符合科学家的决策逻辑——如果我们预期相变,并且对相变前后测量响应的功能行为有信心,那么剩下的唯一不确定性就是相变点!
第二个 s GP 由一个分段概率函数扩充,对于 x < xₜ 等于 ax 并且对于 x ≥ xₜ 等于 bx ,在 xₜ 上具有均匀先验并且在 a 和 b 上具有对数正态先验。请注意,这个模型只是部分正确:它有一个转变点,但在转变前后呈现线性(而不是幂律)行为。因此,重建质量(图 7d)较低,尽管它仍然比普通 GP 好一些。请注意,在这种情况下,最大的不确定性与转换前的行为相关(我们不期望幂律行为)。
模型预测中的不确定性可用于指导测量,以获得基础函数的更精确的重建。该过程与贝叶斯优化中的过程相同,除了我们使用模型的不确定性而不是采集函数来预测下一个测量点。
**图 8。**主动学习的结果,其中(a)普通 GP,(b) s GP 由预期系统行为的“正确”模型增强,© s GP 由预期系统行为的部分正确模型增强。作者图。
我们可以看到,两个的 GP 模型在探索参数“空间”的其他部分之前,很快集中在过渡区域(图 8b,c)。因此,我们能够显著提高重建质量。另一方面,使用 vanilla GP 的不确定性导向勘探仍然无法重建过渡区(图 8a)。因此,我们再次看到,即使的 GP 对预期系统的行为有部分正确的模型,也能胜过标准的 GP 方法。
总之,用预期系统行为的(完全贝叶斯)概率模型增强高斯过程,允许更有效的优化和系统属性的主动学习。请注意,即使对于不正确或部分正确的模型,主动学习算法最终也会得出正确的答案——但代价是大量的实验步骤。查看我们的预印本了解更多细节,包括这个概念在物理模型中的应用[11]。也请查看我们的 gpax 软件包,将此工具和其他 GP 工具应用于科学数据分析。如果你想了解更多关于扫描探针显微镜的知识,欢迎来到 M*N 频道:显微镜,机器学习,材料。
最后,在科学界,我们感谢我们的研究赞助商。这项工作在橡树岭国家实验室纳米材料科学中心(CNMS)进行并得到支持,该中心是美国能源部科学用户设施办公室。您可以使用此链接进行虚拟漫游,如果您想了解更多信息,请告诉我们。
可执行的 Google Colab 笔记本在这里有。
参考文献:
1.巴尔克,新泽西州;杰西;莫罗佐夫斯卡;叶利舍耶夫,e;钟德伟;金,y;阿达姆奇克湖;加西亚河;新泽西州杜德尼;锂离子电池阴极中离子扩散的纳米级绘图。 Nat。纳米技术。 2010, 5 (10),749–754。
2.库马尔,a。丘奇,女;莫罗佐夫斯卡;加里宁公司;Jesse,s,《在纳米尺度上测量氧还原/析出反应》。 Nat。化学。 2011, 3 (9),707–713。
3.杨,S. M 莫罗佐夫斯卡;库马尔河;叶利舍耶夫,英国;曹;马泽特湖;巴尔克,新泽西州;杰西;瓦苏德万;杜布尔迪厄,c;纳米级铁电体中的混合电化学-铁电态。自然物理 2017, 13 (8),812–818。
4.Martin,o .,使用 Python 的贝叶斯分析:使用 PyMC3 和 ArviZ 的统计建模和概率编程介绍,第二版。Packt 出版:2018。
5.Lambert,贝叶斯统计学生指南。塞奇出版有限公司;1 版:2018。
6.Kruschke,j .,做贝叶斯数据分析:与 R,JAGS 和斯坦的教程。学术出版社;2 版:2014 年。
7.C. T .纳尔逊;瓦苏德万;张;齐亚特迪诺夫,m;叶利舍耶夫,英国;竹内岛;莫罗佐夫斯卡;通过原子解析 STEM 数据的贝叶斯分析探索铁电畴壁的物理学。 Nat。Commun。 2020、 11 (1)、12。
8.鲍里塞维奇;莫罗佐夫斯卡;金耀明;伦纳德博士;奥克斯利议员;医学博士 Biegalski 叶利舍耶夫,英国;通过拓扑缺陷的原子尺度观测探索空位有序系统的介观物理。物理学家列特。 2012 年, 109 (6)。
9.李,q;C. T .纳尔逊;许淑玲;达摩达兰;李;亚达夫,又名;麦卡特尔,m;马丁;拉梅什河;Kalinin,S. V,《使用机器学习和相场建模对 PbTiO3/SrTiO3 超晶格极涡中的挠曲电进行量化》。 NatCommun。 2017, 8 。
10.加里宁公司;奥克斯利议员;瓦莱蒂,m;张;赫尔曼,注册会计师;郑;张;Eres,g;瓦苏德万;深度贝叶斯局部结晶学。 npj 计算资料 2021、 7 (1)、181。
11.文学硕士齐亚特迪诺夫;戈什,a。物理学有所不同:贝叶斯优化和通过增广高斯过程的主动学习。arXiv:2108.102802021。
释放 Databricks CLI 的威力
从您的控制台舒适地管理您的 Databricks 工作区!
照片由在 Unsplash 上的Launde Morel 拍摄
如果我告诉您,您可以从一个命令行控制台控制所有数据块资产,会怎么样?
Databricks 已经是数据工程师武库中一个非常强大的工具。它在分析方面的成就令人印象深刻,有些人甚至可以说是革命性的。
一个数据块工作空间本质上是一个管理所有数据块资产的环境。工作区允许您组织笔记本、表格、群集,并帮助管理作业。
虽然界面非常光滑和用户友好,但像导出/导入笔记本、启动集群、尝试将每个笔记本链接到您的 git repo 这样的事情感觉更像是痛苦的体力劳动。
这变得令人毛骨悚然,尤其是如果你必须在你的平台上管理多个工作区,并且很难跟踪你的浏览器中打开的所有小标签。
要是有办法从一个地方管理您所有的工作空间就好了。值得庆幸的是有,并且像所有的好东西一样,这个是以 python 包的形式出现的。
如何配置 Databricks CLI
Databricks-CLI 是一个开源库,可以使用 pip 命令安装。
使用适合您的 python 版本的 pip 版本运行pip install databricks-cli
。
一旦你安装了库,你可以使用databricks -- version
列出版本
要开始编写 CLI 命令,您必须首先设置要管理的 Databricks 工作区的身份验证。这必须只做一次。
我将以 Azure Databricks 为例展示以下步骤,但这些步骤在任何托管 Databricks 服务上都非常相似。
可以使用 Databricks 个人访问令牌设置身份验证。这个令牌可以直接从工作区生成。
- 点击工作区中的用户资料图标,并选择用户设置
- 您将看到一个选项生成新令牌
- 设置生存期并生成令牌。记得复制令牌。
- 从浏览器中获取工作区的 URL,格式为
https://<instance-name>.cloud.databricks.com
现在,您可以通过在 cmd 行上运行databricks configure --token
在本地机器上配置认证。系统会提示您输入Databricks Host
粘贴工作区的 URL。接下来,系统会提示您输入Token
,粘贴您生成的令牌。
要快速检查认证是否有效,运行命令databricks workspace list
,如果一切正常,您必须能够在控制台上列出您的数据块工作区中的所有目录。
但是,如果您希望管理属于不同环境的多个工作区,或者您为多个客户端工作,并且每个客户端都有自己的专用工作区,那么这将使您只能管理单个工作区。
您可以通过设置连接配置文件在控制台上进行配置。要添加连接配置文件,请设置唯一的名称来标识特定的工作区。例如开发或 UAT 工作区。
- 运行
databricks configure --token --profile <<profile_name>>
这就像为你的每个工作区创建一个别名,这样 CLI 就能记住哪个是哪个。 - 像之前一样输入主机名和令牌。
- 要使用此连接配置文件,您只需用
--profile <<profile_name>>
来补充您想要运行的每个 CLI 命令 - 要确认只需运行
databricks workspace list --profile <<profile_name>>
- 要切换到另一个工作空间,只需更改配置文件
这是它在游戏机上的样子。
如何配置 Databricks CLI(图片由作者提供)
只需对所有工作区重复相同的配置步骤,并记住给每个工作区取一个唯一的名称,以便于识别。
**提示:**CLI 将此配置作为.databrickscfg
存储在您机器中的一个文件中。如果您想通过控制台为每个工作区配置身份验证,只需手动编辑这个文件。文件看起来像这样。
的内容。databrickscfg 文件(图片由作者提供)
如何使用 CLI 管理笔记本电脑
CLI 命令组合在一起,代表您可以管理的不同资产。您可以使用databricks <<group>> --help
列出特定组的子命令。组可以是fs
、clusters
、workspaces
等等。要列出文件系统的子命令,只需运行databricks fs --help
数据块文件系统子命令(图片由作者提供)
您最想做的一件事是列出您工作区中的所有笔记本,并可能将它们导出到您的本地机器中,然后您可以轻松地将其与 git 存储库集成。
- 使用
databricks workspace list --profile <<profile_name>>
列出你工作区中的所有文件夹 - 使用
databricks workspace export_dir /<<directory_in_databricks>> <<Target_path>> --profile <<profile_name>>
递归导出工作区目录中的所有笔记本这会将所选目录中的所有笔记本导出到您机器上的目标路径中。
同样,您可以导出单个笔记本,也可以轻松地将笔记本或目录导入工作区。这里有一个与工作空间相关的命令的详尽列表,您可以尝试一下。
如何使用 CLI 管理集群
数据工程师通常会花大量时间管理集群,通常一天中,我必须在许多不同的工作区启动集群,它们需要时间预热。过了一会儿,事情变得如此混乱,以至于你不记得你最初打算做什么。
Databricks CLI 允许您从控制台管理所有集群,而不必访问每个工作区。这无疑为你节省了大量宝贵的时间,并清理了你的浏览器标签。
- 您可以做的最简单的事情就是使用
databricks clusters list --profile <<profile_name>>
列出工作区中的所有集群。它列出了工作区中的所有集群及其唯一的集群 id 和当前状态。 - 一旦您有了集群 id 并知道了您的集群的状态,您就可以使用
databricks clusters start --cluster-id <<id>> --profile <<profile_name>>
轻松地启动这些集群中的任何一个几分钟后,您的集群将全部预热完毕。
在 CLI 中管理集群(图片由作者提供)
使用集群组命令,您可以做许多更有趣的事情,这里是与集群相关的 CLI 命令的详尽列表。
外卖食品
Databricks CLI 是一种将一些乐趣引入管理 Databricks 的好方法,也是一种帮助我节省宝贵时间的工具,我可以将这些时间花在喝咖啡休息上。
我的收获:
- 您可以在舒适的控制台上控制所有数据块资产。
- 您可以随时关注您的集群。
- 您可以使用简单的命令创建、删除、启动集群并调整其大小,而无需导航到工作区。
这篇博客中列出的命令只是日常任务中微不足道的几个。您可以深入研究 Databricks 文档,尝试一些新的东西,或者用它构建一个完整的应用程序。
如果您是一名数据工程师,请将 Databricks CLI 添加到您已经令人印象深刻且详尽的工具列表中,我保证您不会后悔。
请随意问我关于这篇文章的任何问题,我很想知道你对 Databricks CLI 的看法。
释放 Scikit-learn 管道的力量
scikit-learn 管道中级指南
克里斯托夫·迪翁在 Unsplash 上拍摄的照片
在我的上一篇文章中,我写了一篇介绍 scikit-learn 管道的文章。如果您尚未阅读,可以通过下面的链接访问:
在这篇文章中,我想扩展以前的帖子,展示一些很酷的功能,以创建更强大的管道,在帖子的最后,我将向您展示如何微调这些管道,以提高准确性。
正如我们在上一篇文章中看到的,管道可能非常有用,但是我们在介绍中仅仅抓住了表面。
如果我们想做一些考虑到特征类型的特征转换呢?
假设我们有一个包含数字和分类特征的熊猫数据帧,我们希望以不同的方式处理这两种类型的特征。在这种情况下,我们可以使用 scikit-learn pipeline 中的 ColumnTransformer 组件。我们开始吧!
出于教育目的,我们将使用 Kaggle 的成人人口普查收入数据集:
https://www.kaggle.com/uciml/adult-census-income
该数据集包含 6 个数字特征和 9 个分类特征,因此它似乎适合我们想要构建的管道。jupyter 笔记本将在我的 github 中提供,您可以通过以下链接下载:
在实现管道之前,我们必须对数据集做一点转换,因为所有未知的值都保存为“?”而不是 NaN,收入(目标列)是一个字符串,我们想把它编码成实数。
一旦我们完成了这些转换,我们就可以开始实现我们的管道了。为此,我们将使用 scikit-learn 的 ColumnTransformer 组件,并以不同的方式选择和处理分类和数字特征:
Make_column_selector 将帮助我们按类型选择列。在我们的例子中,这些类型对于数字特性是 int 和 float,对于分类特性是 object。如果我们仔细观察,ColumnTransformer 组件也使用了两个变量,称为 numerical _ pipe 和 categorical _ pipe。这些管道的定义如下:
一旦我们定义了 ColumnTransformer 的组件及其所有元素,我们将使用该组件来创建我们的主管道:
就是这样!我们的管道完工了!让我们用它来训练,并测量它的准确性:
我们使用 33%的数据作为测试集的准确率是 83.2%。那一点也不差!
如何才能提高这条流水线的精度?
为了改善这个管道的结果,我们可以对每个组件执行微调技术。Scikit-learn 使使用 GridSearchCV 进行微调变得容易。该组件将进行广泛的微调,在我们定义的范围内尝试所有可能的超参数组合。这里我们必须小心,因为如果我们尝试太多的组合,与此过程相关的计算复杂性可能会呈指数级增长:
如果我们仔细观察代码,我们已经为管道定义了一些超参数,然后在定义了我们想要优化的指标之后,我们已经开始了拟合所有可能组合的过程。经过这一过程,我们将准确度提高了 0.9%,总准确度达到 84.1%。这听起来不多,但这是一个非常简单的优化,它可以进一步改善定义一个更大的超参数空间,尝试更强大的模型,进行一些贝叶斯或遗传优化,而不是网格搜索优化,等等。
结论
当我们一起使用管道和超参数微调时,它们工作得非常好。这篇文章展示了管道不可思议的潜力,以及它们如何在数据科学家的日常工作中非常有用。虽然这个管道比我第一篇文章中的管道更复杂,但是这些管道可以更复杂。例如,我们可以创建自定义转换,并在管道中使用它们。然而,这超出了这篇文章的范围,但是如果你想要一篇关于定制变形金刚的文章,请告诉我。
参考
https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.GridSearchCV.html https://scikit-learn.org/stable/modules/generated/sklearn.metrics.make_scorer.html https://scikit-learn.org/stable/modules/generated/sklearn.compose.ColumnTransformer.html https://scikit-learn.org/stable/modules/generated/sklearn.pipeline.Pipeline.html
熊猫无限的灵活性
几乎总是有不止一个解决方案
埃里克·普劳泽特在 Unsplash 上拍摄的照片
Pandas 是一个非常流行的 Python 数据分析和操作库。它是数据科学教育中引入的首批工具之一。Pandas 为更有效的数据分析提供了丰富的功能和方法。
我最喜欢熊猫的一点是,完成一个给定的任务几乎总是有多种方式。一种方法可能在时间和复杂性方面胜过其他方法。然而,拥有多种选择会让你跳出框框思考。这也有助于改善你解决复杂任务的方法。
练习用不同的方法来解决问题的另一个好处是,它会大大提高你对熊猫的了解。
在本文中,我们将查看一些示例,展示完成相同任务的不同方法。Kaggle 上可用的医疗费用数据集用于示例。
让我们从导入库和将数据集读入数据帧开始。
import numpy as np
import pandas as pddf = pd.read_csv("/content/insurance.csv")
df.head()
(图片由作者提供)
该数据集包含一些个人信息和保险费用。
第一组示例是基于列中的值过滤行。例如,我们可能想要过滤年龄大于 40 的行。
完成这项任务的更常见的方法如下。
df[df.age > 45]
另一种方法是使用 query 方法,并将过滤条件指定为字符串。
df.query('age > 45')
我将展示的第三种方式通常不被使用,但对展示熊猫的灵活性很重要。
df.where(df.age > 45).dropna(axis=0, how='all')
我们首先应用 where 函数,该函数只接受符合指定条件的行,并将其他行标记为 NaN。然后,我们删除充满 NaN 值的行。
第二个任务是创建一个新列。假设我们需要添加一个包含客户 id 号的新列。
下面是第一种方法。
cust_id = np.arange(1,1339)df['cust_id'] = cust_iddf.head()
(图片由作者提供)
如果我们将客户 id 列作为第一列,可能会更好。熊猫的插入功能就是在那种情况下使用的。
df.drop('cust_id', axis=1, inplace=True)cust_id = np.arange(1,1339)df.insert(0, 'cust_id', cust_id)df.head()
(图片由作者提供)
我们首先删除上一步中添加的列,然后插入客户 id 列作为第一行。insert 函数的参数是要插入的位置、列名和值。
下一个例子涉及到熊猫的功能分组。我们可以用它来计算性别和吸烟者列中每个类别的平均费用。
df[['sex','smoker','charges']].groupby(['sex','smoker']).mean()
(图片由作者提供)
假设我们希望将性别和吸烟者作为数据帧中的列,而不是索引级别。
一种方法是使用 reset_index 函数。
df[['sex','smoker','charges']].groupby(['sex','smoker']).mean()\
.reset_index()
我们还可以使用 group by 函数的 as_index 参数。
df[['sex','smoker','charges']].groupby(['sex','smoker'], as_index=False).mean()
两者都会产生以下数据帧:
(图片由作者提供)
下一个例子简单而实用。我们可能希望看到一列中唯一值的数量。一种方法是隐式使用 value_counts 函数。
value_counts 函数返回列中的唯一值以及出现的次数。如果我们应用带有 value_counts 的 len 函数,我们将得到唯一值的数量。
一个更简单的方法是使用一个专用的函数来完成这个任务,这个函数就是 nunique。顾名思义,它返回一列中唯一值的数量。
len(df.age.value_counts()) == df.age.nunique()
True
正如我们所看到的,两者返回相同的值。
假设我们有以下数据帧:
(图片由作者提供)
索引包含 id 号。我们希望将它们作为名为“id”的列,而不是索引。
一种方法是使用 reset_index 函数,该函数使用索引创建一个新列。但是,该列的名称将是“index ”,因此我们需要使用 rename 函数来更改它。
df.reset_index().rename(columns={'index':'id'})
(图片由作者提供)
另一种方法是首先重命名索引,然后重置索引。
df.rename_axis('id').reset_index()
(图片由作者提供)
结论
我们已经看到了一些例子,说明用不同的方法用熊猫来完成同样的任务是可能的。
在某些情况下,由于时间和复杂性的考虑,一种方法比其他方法更受欢迎。然而,知道多种方法总是更好的。练习和实施不同的方法也会提高你的熊猫技能。
感谢您的阅读。如果您有任何反馈,请告诉我。
Kubernetes 中无限的科学图书馆和应用程序,即刻!
建立一个包和应用程序的共享库,可以动态地加载到您的 Kubernetes 数据科学环境中。
迈克尔·D·贝克与在 Unsplash 上的合影
TL;DR:
在 Kubernetes 上提供 Jupyter-as-a-Service 在规模上是很棘手的,当你需要提供许多不同版本的不同库或应用程序来满足每个用户的需求时。
而不是创建超重的容器图像,或者必须管理(并从中选择!)数百个,或者让人们每次打开笔记本时从头重新安装所有东西,您可以建立一个共享的库和应用程序库,并让用户动态和即时地加载它们。
为开放数据中心提供的完整代码和部署说明!
(作者截图)
*免责声明:*我在 Red Hat 工作,帮助组织开发数据科学/数据工程平台和解决方案。因此,这里描述的实现使用不同的 Red Hat 产品,如 Red Hat OpenShift (我们的 Kubernetes 企业发行版),或[Red Hat open shift Data Foundation](http://Red Hat OpenShift Data Foundation)(我们基于 Ceph 的 open shift-原生存储解决方案)。然而,整体架构和方法可以适用于其他平台。
现在,让我们开始长篇大论吧!
第一章:麻烦是如何开始的
Kubernetes 是数据科学和数据工程平台的流行选择。敏捷性、多功能性、资源可扩展性……使其成为这些工作负载类型的首选平台。尤其是在拥有共享环境的大型组织中:将您的应用程序、库和依赖项打包到轻量级容器映像中,使它们可复制、一致且安全,这似乎是解决您所有问题的完美答案!
您最近读到的这些内容让您激动不已,您以这种方式打包了一个 Jupyter 容器图像:
(作者图文)
因为你很聪明,想要预测需求(翻译:你不想一次又一次地回到这个话题),所以你甚至创造了一些不同的“味道”来涵盖你能想到的不同用例:仅带 Scipy 的基本笔记本,一个带 Tensorflow 的,一个带 Pytorch 的,……完美,那些容器图像都可以使用。
因此,您在 Kubernetes 环境中设置了 JupyterHub 或 Kubeflow,并为所有用户创建了一个 Jupyter 即服务环境!任务完成了,问题解决了,你就可以回去做其他(总是)迫切的事情了。
几个星期过去了…
然后是 Alice、Bob 和数据科学家团队的其他成员。他们甚至带来了一些 BI 人员,以通过该组织正在经历的数字化转型来展示他们的善意,还带来了一些数据工程师(谁也不知道,可能会有数据管道的漏洞需要修复)。但是没有统计学家,你们都知道为什么…
(图片作者来自 imgflip.com)
爱丽丝开始说,“听着,Jupyter 即服务这个东西太棒了!过去几周我们一直在玩它,我们看到它如何取代我们的个人环境:在我们的笔记本电脑上不再需要安装和管理任何东西,因为笔记本电脑缺乏处理能力和内存。任何地方都可以访问任何东西!”。
“是的,这绝对是一个巨大的进步。”,鲍勃继续说道。“我们现在能够轻松地交换我们的笔记本电脑,因为它们都基于相同的容器映像,并使用中央数据湖。这个库或这个应用程序不会再丢失了!”
有些困惑,因为这以前从未发生过,你问,“好吧,那么,完美。但你为什么在这里,不仅仅是为了感谢我吗?”
“哦,几乎没有什么,对你来说,这很容易!”查理大声说道。“你知道,你为我们创造的不同风格的环境非常棒。它只是缺少这个我经常使用的库,你知道我的 avLib 吗?当然是在 3.2.4 或更高版本,因为在 3.2.3 之前有一些坏的东西。但不是来自新的 4.x 分支,我真的不喜欢他们用它做的事情。”
“是的,如果你还能加上巴丽、LibB 和 LibC,那就太好了。哦,顺便说一下,对于 LibC,我需要最近的 3 个版本,以便能够比较一些东西”,Debbie 补充道。
鲍勃以他一贯的方式插话道,“既然我们在讨论这个问题……当然,所有旧版本的图像和库总是可用的,对吗?因为这是我们审计流程的一部分,可以在任何时候重新计算,你知道,为了负债的目的。因此,当然必须总是使用完全相同的工具。另外,我也不想为了适应新版本而修改代码。”
看到你的脸有点腐烂,爱丽丝打断了它,“好吧,我猜你已经明白了,所以我们会离开你,再次感谢!”
由于你是一个经验丰富的专业人士,你设法隐藏恐慌上升,并迅速切换到解决方案模式…
第二章:几个选择,没有真正的解决方案…
几天后,你会思考你绞尽脑汁的结果…
选项 A :臃肿的形象。
好了,让我们把他们问的所有东西放到同一个容器图像里!这很简单:只需在 requirements.txt 中添加几行,或者在 docker 文件、docker build 中添加一些东西,就完成了!现在让我们把图像上传到回购。什么,预计到达时间 2:34:12?!哦…这个图像是 38.2GB…肯定是不可管理或不可行的:“起始容器。拉图,请明天再来……”。无论如何,我不能适应同一个库的多个版本。
选项 B :永无止境的图像流。
嗯,在现有图像的基础上,我总是可以创建定制的图像来满足各种需求。但是让我们看看,……只有 15 个库,每个库有 2 个可能的版本,理论上有 2 个⁵组合,32 768 个!即使他们只要求百分之一,仍然有 300 多个容器图像可供选择。我很确定哪个图像的下拉选择器不会允许这么多。无论如何,即使用户因为没有选择而应付,从长远来看,整个事情将是不可收拾的。
选项 C :让他们自己处理。
毕竟,做一个 pip 安装并没有那么难!如果有 requirements.txt,我甚至可以通过一些巧妙的机制让一个进程查看笔记本的文件夹,并安装后台列出的所有内容。当然,每次笔记本启动时都会出现这种情况,这会导致延迟和投诉…而且无论如何,它不会解决使用不同集/版本的基础库来维护许多图像的问题。除非我希望用户每次都从头开始重新安装整个堆栈…
这种方法也不能解决无法使用 pip 或 conda 安装应用程序的问题。而且在一个安全的企业环境中,容器不作为 root 运行(这是一个最佳实践),所以人们无论如何也不能安装任何东西。
那么该怎么办呢…?
你不太好的选择…(作者提供图片)
第三章:绝望的深渊
作者注:本章已被自愿过滤为 1)没有必要让每个人都过这种生活,即使是通过代理。2)它与 It 或数据科学没有任何联系。
第四章:这就是方法
在过去,我有机会了解加拿大计算机公司(Compute Canada)和 HPC 世界的许多人,至少是学术界的人,特别是神奇的 T2 easy build(T3)社区,正在做什么来解决这个相同的问题:如何在一个共享的环境中以有效和可重复的方式为您的用户带来应用程序和库,使数据科学家轻松地完成他们的工作,而不是笨拙地安装、打包或编译…?
他们的答案是使用环境模块来动态“加载”预打包的库或应用程序。将其简化到极致,假设您可以访问安装在文件系统中某处的一些共享文件夹,模块引擎将简单地修改您的 P A T H 、 PATH、 PATH、PYTHONPATH 或类似的其他环境变量,以使这些文件夹在您的环境中“可见”。不再有 Python 抱怨当你做“导入 pytorch”时找不到库,因为现在它知道在哪里可以找到它!
当然,所有这些都更加精确,因为它可以跟踪依赖性,加载或不加载什么,卸载什么,以及在交叉依赖性的情况下何时卸载…
但基本上,我们问题的解决方案包括两件事:
- 提供对“模块”库的访问,这些模块可以是 Python 库、Linux 库或成熟的应用程序。这个库可以在繁殖时挂载到您的环境中。
2.有办法在环境中轻松加载这些模块。
Kubernetes 中的实现概念(图片由作者提供)
所以这是我在开放数据中心(开放数据中心,ODH,是一个基于 Kubeflow 的开源项目,提供开源 AI 工具,用于在 OpenShift 容器平台上运行大型分布式 AI 工作负载)内实现的概念验证解决方案:
- 共享库安装在 OpenShift Data Foundation 提供的 RWX 卷上(后台有 CephFS)。
- ODH 正在提供 Jypyter-as-a-Service 环境,在这种情况下,它有一个稍微定制的镜像,可以加载模块,还有一个 JupyterLab 扩展,可以轻松地完成加载/卸载部分。
- 当产生 Jupyter 时,共享库以只读方式安装在 pod 中。
- 然后,您只需在需要时加载您需要的内容!
这是它看起来的样子:
环境快速演示(作者截图)
这是在这个快速概述中发生的事情:
- 我启动了一个基本的笔记本示例,它使用 Torchvision 从一张图片中推断出一只狗的品种(不是任何一只狗,我的!).
- 当我尝试运行笔记本时,出现了 ModuleNotFound 错误,因为我的环境中没有可用的 torchvision 库。
- 所以在左边的面板上,在我的软件的扩展菜单中,我通过输入几个字母来查找这个包,然后我只需点击 Load。
- 由于笔记本已经启动,我必须快速重启我的内核以使更改生效。我可以运行整个笔记本。
在这一点上,你可能会说:“这很有趣,但你可以只做一个 pip 安装”。
当然,特别是这个基本的例子,这也是我们习惯做的,特别是在本地环境中(相对于共享环境)。但是这种替代方法带来了有趣的功能,所有这些功能都不需要创建特定的容器映像:
- 提供人们无法安装的应用程序,因为它们可能没有 Conda 或 Pip 包。在这种共享环境中,人们不应该能够 yum/apt-get 安装任何东西,因为他们不应该有 root 访问权限。我希望您的环境也是如此…
- 测试不同版本的包/应用程序变得非常容易。只需加载/卸载相关的模块,不需要做长时间或复杂的安装/卸载或玩弄依赖关系。
- 您可以提供许多不同版本的包或应用程序,用户可以根据自己的需要选择他们想要的。即使几年后,这些模块仍然可用,不需要删除它们,因为环境已经升级。相反,您可以提供最先进的模块 alpha 版本,而不会将整个环境置于危险之中。
- 用户的环境保持整洁,不会因为安装的库而变得杂乱。此外,他们不必在每次想要运行特定笔记本电脑时都进行所有这些安装。模块加载/卸载速度更快,因为事实上所有内容都已经装载到 pod 中。
- 对于系统管理员来说,生活变得简单多了。只有一个容器映像需要管理。这就是为什么这个项目被称为开放数据中心-汉兰达,“只能有一个!”。
但是等等,还有更多!
在第一个基本示例中,我加载了一个 Python 包。但正如我之前所说,它也可以是一个完整的应用程序,甚至是一个拥有自己的 Web UI 的应用程序,如 RStudio-Server。为了实现这一点,我将使用 jupyter-server-proxy 和一些特殊的配置,使它在模块加载时出现在启动器中。
加载模块:
加载模块(作者截图)
RStudio 会出现一个新的单幅图块:
新 RStudio 磁贴(作者截图)
当你点击磁贴时,浏览器会打开一个新标签,RStudio 会在几秒钟内启动。
RStudio(作者截图)
这是与以前相同的容器环境,这意味着您可以访问相同的文件、相同的工具……这在您想要混合使用 R 和 Python 脚本时非常有用,反之亦然!
更多关于如何使用它的细节
在下面的报告中,您将找到完整的部署说明和代码,包括一个预编译的模块库,该库易于在您的开放式数据中心环境中部署:https://github.com/guimou/odh-highlander
一旦部署好一切,您就可以这样做了…
在您的 JupyterLab 实例中,您可以访问一个新的扩展“软件”。可用模块列表分为两部分。“特色”模块和完整列表(这只是我在这个演示环境中选择提供的模块):
模块列表(作者截图)
您可以使用过滤器框来搜索特定的模块(只需输入几个字母)。过滤同时发生在两个列表上:
过滤列表(作者截图)
如果你点击一个模块名,一个弹出窗口会给你更多的信息:描述,依赖关系,…
模块信息(作者截图)
要加载模块,请将鼠标悬停在模块上,然后单击“加载”按钮:
模块加载(作者截图)
模块及其所有依赖项被自动加载(本例中为 torchvision):
模块已加载(作者截图)
要卸载模块,请将鼠标悬停在“已加载”列表上,然后单击“卸载”:
卸载模块(作者截图)
模块及其依赖项将被自动卸载。
注意 : Lmod ,模块管理器引擎,跟踪每个模块加载的依赖关系。如果两个不同的模块共享依赖关系,一个模块卸载不会影响另一个模块,它的依赖关系仍然存在。只有当模块不再需要它们时,它们才会被卸载!
高级功能
收集
如果您想要创建一个特定的环境,其中包含一组您想要使用的不同模块,那么不需要每次都从 scracth 重新创建它!您可以简单地加载这些模块,然后创建一个“集合”。下一次,只需双击即可恢复此收藏。
要创建一个集合,请加载您想要的模块,单击图标并为集合命名。
创建收藏(作者截图)
命名并保存收藏(作者截图)
当您想要恢复这个环境时,只需单击恢复图标,然后选择并加载您的集合。
还原收藏(作者截图)
还原收藏(作者截图)
进口
您也可以直接从笔记本和脚本加载您需要的模块。要知道要用到哪些模块,可以直接导出相关的 Python 代码!
点击“生成 Python 代码”图标:
生成代码(作者截图)
然后,您可以将完整的代码复制粘贴到您的第一个笔记本单元格或脚本中:
Python 代码(作者截图)
注意:当然,为了在您的笔记本或脚本中工作,您正在使用的容器映像或环境必须是“支持 lmod 的”,并且具有相关模块的库必须可访问/安装到该环境中。
下一步是什么?
如前所述,您将在此回购中找到部署此解决方案的所有资源和说明。在接下来的文章中,我将详细介绍技术实现,尤其是:
- 如何创建一个环境来创建你自己的模块。
- 关于如何使用 EasyBuild 创建模块的说明和示例。
- 如何创建一个 Lmod 增强的 JupyerLab 容器映像来使用模块库。
- 如何创建特定于硬件的模块(比如支持 cuda,需要 GPU),并使它们只在相关的基础设施上可用。
多谢
我必须感谢许多人和组织,因为我在这里没有发明任何东西。我只是把一些项目组合起来,把一些解决方案从一个世界移植到另一个世界,瞧!
- Open Data Hub 团队,感谢他们创建了这个奇妙的数据科学环境,它非常容易在 OpenShift 上部署。
- EasyBuild 社区当然感谢他们创造的伟大工具,但也感谢他们的热烈欢迎(感谢 Kenneth!),以及愿意回答我的 dum 新手问题(谢谢马克西姆!).
- Compute Canada ,是谁让我发现了这种解决方案。他们的设置是病态的,尤其是他们在整个组织中分配模块的方式,真了不起!
- CMD-NTRF 、费利克斯-安托万·福廷,出色的 Jupyter-Lmod 扩展,通过 Jupyter 中流畅的用户界面将解决方案提升到另一个层次。
参考和链接
- 回购与指令:https://github.com/guimou/odh-highlander
- 启用 Lmod 的 JupyterLab:https://github.com/guimou/s2i-lmod-notebook
- 各种 EasyConfigs(如果你想看看哪些模块已经可用):https://github.com/easybuilders/easybuild-easyconfigs
- 各种定制简易配置:https://github.com/guimou/odh-easyconfigs
- 开放数据中心文档:【http://opendatahub.io/docs.html
- EasyBuild 文档:【https://docs.easybuild.io/en/latest/
- 加拿大计算机展上的 EasyBuild 展示:https://www.youtube.com/watch?v=eQ1_iWSnJaI
利用机器学习和行为心理学开启电子商务增长
对 100,000 名在线购物者进行细分和评分预测,以及这对企业意味着什么
rupixen.com在 Unsplash 上拍照
问题是
营销人员和研究人员长期以来一直使用人口统计学和心理统计学来进行客户细分。不可否认,这些信息对于满足客户需求至关重要。然而,随着 insights 实践的发展,我们现在知道基于购买行为的细分更加有效,因为它会带来更好的广告支出回报和更高的转化率。
还有一个心理学基础解释了为什么行为细分可能会带来更好的洞察力——诺贝尔经济学奖得主丹尼尔·卡内曼发现,购物者倾向于使用“系统 1”思维(快速&直觉)而不是“系统 2”(缓慢&深思熟虑)。
在阅读了最近频率货币(RFM)分割之后,我想在一个大型数据集上试验这种方法,并探索它能揭示什么样的洞察力。
简单地说,这是我的发现——
- K-means 聚类有助于根据行为确定购物者细分,从而揭示业务的直接机会。
- 最高价值客户的评价最差,通常位于马拉尼昂,在 Q2 购物最多。相比之下,价值最低的顾客会留下最好的评价,他们往往位于圣保罗,在 Q1 购物最多。
- 我能够以 93%的准确率预测客户群,以 94%的准确率评估得分。
数据
Olist 是巴西最大的电子商务网站。它把全国各地的小零售商联系起来,直接卖给顾客。从 2016 年到 2018 年,该公司在其网站上慷慨地分享了一个包含 11 万份订单的大型数据集。
SQL 风格的关系数据库包括站点中的客户及其订单,其中包含大约 10 万个不同的订单和 73 个类别。它还包括与订单相关的商品价格、时间戳、评论和地理位置。这是真实的匿名商业数据。
方法论
RFM 是一种用于分析客户行为的数据建模方法。它代表—
最近度衡量客户最近一次订购到今天的时间(以天为单位)。
频率衡量客户的订单总数。
货币是他们在这些订单上花费的平均金额。
通过这三个镜头对客户进行细分,我们可以精确定位以特定方式行事的客户群,并创建人物角色,这反过来会带来更好的营销效果。RFM 分析可以帮助企业找出挑战和机遇,关注哪里,做什么。
我使用 K-means 聚类(无监督机器学习)来确定 RFM 聚类,然后给每个客户分配一个总体分数——将他们分为高价值、中价值和低价值。
#creates a generic user dataframe to keep CustomerID and new segmentation scores
df_user = pd.DataFrame(df['customer_unique_id'])
df_user.columns = ['customer_unique_id']#gets the max purchase date for each customer and create a dataframe with it
df_max_purchase = df.groupby('customer_unique_id').order_purchase_timestamp.max().reset_index()
df_max_purchase.columns = ['customer_unique_id', 'MaxPurchaseDate']#we take our observation point as the max purchase date in our dataset
df_max_purchase['Recency'] = (df_max_purchase['MaxPurchaseDate'].max() - df_max_purchase['MaxPurchaseDate']).dt.days#merge this dataframe to our new user dataframe
df_user = pd.merge(df_user, df_max_purchase[['customer_unique_id','Recency']], on='customer_unique_id')df_user.head()
作者图片
为了验证聚类的数量,我使用了 K 均值聚类的“肘方法”。
这种方法估计 K 的最佳值。使用下面的可视化,“肘部”计算失真下降的点,或者换句话说,如果图形看起来像一只手臂,肘部就是前臂开始的地方。
[作者图片]使用肘方法,我们可以确定最近有 5 个理想的集群
在我将同样的方法应用于频率和货币之后,我根据客户的总体聚类分数对他们进行了细分。分数低于 3 分为“低值”,介于 3-6 分为“中值”,高于 6 分为“高值”。
另一种方法是分配权重或进一步分割线段,但我决定在这个分析中保持简单。
#assigning value labels to segments
df_user['Segment'] = 'Low-Value'
df_user.loc[df_user['OverallScore']>3,'Segment'] = 'Mid-Value'
df_user.loc[df_user['OverallScore']>6,'Segment'] = 'High-Value'
[图片由作者提供]虽然只有 10%的客户群,但是高价值客户占了营收的 50%!
从机器学习的角度来看,这是一个多类分类问题。价值段的预测模型结果相当准确,随机森林模型的 F1 得分达到 93%。
[图片由作者提供]最终模型:随机森林| F1 评分:93%
洞察力
探索这 3 个部分被证明是非常有用的,并且差异是明显的。每个细分市场都有不同的购买模式、地点和主要产品类别。这些信息可以告知营销团队如何为这些客户制定最佳策略。
[作者图片]高价值客户有明确的品类偏好,例如推动 2 月份电脑配件销售
[图片由作者提供]3 个细分市场的宏观人物角色
也许最有趣的区别是 3 个部分如何离开评论。最高价值的客户负责最差的评论,这对公司来说是一个巨大的危险信号。对于任何电子商务生态系统来说,评论对于培养买卖关系至关重要。因此,预测客户评论分数并了解是什么推动了积极的评论是合乎逻辑的下一步。
[图片由作者提供]高价值客户留下的平均评论分数仅为 3.2
这让我掉进了预测顾客评论的兔子洞。评论被二进制化为 0 表示负面(1-3),1 表示正面(超过 4)。总体分布似乎更偏向积极阶层。
作者图片
在尝试了几个不同的机器学习模型后,我用 94%的 F1 分数预测了客户满意度,并找到了两个决定正面或负面评价的关键因素-
[图片由作者提供]最终模型:XGBoost | F1 评分:94%
满意度的最大预测因素是实际交付日期和预计交付日期之间的差异。从本质上讲,如果订单比预期提前到达,客户会更满意,如果订单比预期晚到达,客户会不高兴。从认知心理学的角度来看,这可以通过锚定启发式来解决——例如,Olist 可以为预期的交付时间建立一个缓冲窗口,从而导致更高的机会以比预期更早的交付来取悦购物者。
产品描述的长度是第二大预测因素——这意味着描述越长的产品往往会获得更多正面评价。这意味着管理购物者的期望有助于推动正面评价。我们可以再次利用行为偏差来“推动”购物者的行为——这是应用框架效应的绝佳机会。例如,Olist 可以与卖家合作,帮助提供更好(更长)的描述,这可能会带来更好的客户评论。
警告
虽然这是一个迷人的项目,具有明显的商业含义,但我可以想到一些进一步改进的方法—
- 数据仅限于样本。10 万订单只是 Olist 实际业务量的一小部分。如果所有的数据都是可用的,那将会更有洞察力(也更费计算)。
- 人口统计信息(年龄、性别等)的附加层将允许对客户细分进行更深入的分析。
最后的想法
如果你想看的话,可以在我的 GitHub 上找到完整的项目(在那里,我还使用寿命库和 beta geo fitter/负二项式分布模型研究了客户流失和客户终身价值,并创建了一个产品推荐引擎)。
我还发表了一个关于场景故事的宏观观点。
用多语言开启包容性的可能性-NER
思想和理论
海量多语言命名实体识别基础
通过 Unsplash 由 Nick Fewings 拍摄的图像
简介
近年来,命名实体识别(NER)技术发展迅猛,新的模型不断出现。这是一个激动人心的地方,值得观看,也是其中的一部分。就在最近,我的同事 Sybren Jansen 和 Stéphan Tulkens 探索了生物医学命名实体识别(BioNER)的优势和局限性,作为一个例子。
然而,在利用 NER 能力构建值得信赖的人工智能时,仍然存在一个重大挑战:如何适应世界上的多样化语言。绝大多数 NER 模型、训练集、数据、开源代码等等都是英文的。然而,在全球近 80 亿人口中,只有 3.75 亿人的母语是英语。NER 盛行的英语偏见实际上是将世界上相当一部分地区排除在这一重要的技术进步之外。
多语言 NER 模型提供了语言之间的桥梁的可能性。
在这第一篇博文中,我将进一步探讨多语言模型的重要性,并更详细地探讨特定的多语言模型。在后续的文章中,我将更深入地研究测试和结果。
输入:多语
据估计,世界上有 7000 种活跃的语言。[1] NLP 专家通常将语言分为所谓的低、中和高资源语言。高资源语言是这样一种语言,其中有许多不同体裁的在线标记和未标记文本,如英语。低资源语言是一种数据非常少的语言;例如,约鲁巴语。中等资源语言介于这两种类型之间。
在 NLP 中,大多数研究是在英语和其他高级资源语言上完成的。因此,从语言技术中获益是不对称的。[2]
有两个常用术语用来描述可用于不同语言的模型:多语言和多语种。在这一领域,专家们也使用“跨语言学习”这个短语,这是将一种语言的知识应用到另一种语言的过程。这种技术用于训练多语言模型,可以用来在资源较少的语言上表现得更好。
命名实体识别(NER)
我们将通过 NER 的子任务探索多语言模型。在这项任务中,模型必须检测文本中哪些标记引用了命名实体(NE)。NE 的定义因域而异,但 NE 最简单的定义是一个令牌或一组令牌,它指的是现实世界中的特定事物。然而,这并不完全准确,因为“哈利·波特”这个角色也是一个 NE,但在现实世界中并不存在。
没有必要对 NE 有严格的定义,因为哪个令牌属于 NE 将因域和数据集而异。例如,在医学领域中,像肺炎这样的特定情况可以被认为是 NE,但是在商业领域中,它不会被认为是 NE。
当处理多种语言时,NER 任务变得更加困难,因为不同的语言对于如何指示 NE 有不同的约定。例如,在英语中,句子中间以大写字母开头的单词很可能是 NE。在德语中,这不太可靠,因为所有名词都以大写字母开头,但不是每个名词都是 NE。此外,有许多语言不使用拉丁字母,也不区分大写字母和小写字母。语言中表示 NE 的这些不同约定对于多语言领域来说是额外的挑战。
应用 NER:匿名化
能够识别 100 种不同语言的命名实体不同于用 100 种不同语言进行对话。然而,这仍然是一项有用且令人印象深刻的技能。匿名化领域可以通过使用 NER 模型获得显著的价值。随着开放数据趋势的增加[3],匿名化扮演了一个关键角色,因为文档在发布前通常需要匿名化。此外,公众对透明政府的要求越来越高,政府官员提出了对隐私的关切。透明度和隐私之间的权衡是一个合理的考虑。通过 NER 的匿名化,可以帮助消除交易的负面影响。
还有几个其他的用例可以从 NER 文档匿名化中受益。欧盟(EU)对法院和医疗文件的匿名化表示了兴趣,并资助了 MAPA 项目 [4]。该项目旨在创建一个工具,对欧盟所有 24 种官方语言的医学和法律文本进行匿名化处理。这个项目仍处于开发阶段。
当前可用的型号
今天有几种型号可供使用。首先,已在 LENER-BR 数据集上训练了由 Luz 等人[5] 建立的单语巴西葡萄牙语模型。这个数据集是为了训练这个模型而专门开发的。LENER 代表合法命名实体认可,BR 表示该名称在巴西葡萄牙语中。LENER-BR 数据集由 66 份法律文件组成,这些文件是用特定法律实体手动注释的。这些实体不同于标准命名实体,如个人、组织和位置。虽然这些类型的实体也包括在内,但数据集包括对特定法律实体和判例的注释,总共有 6 个类别。基于这些数据训练的模型是基于 LSTM 的 CRF,并使用单词嵌入作为输入。在他们的论文中,他们报告了 6 个班级的平均 92.5 分。
此外,还提供了一种由connaau 等人命名为 XLM-R 的多语种模型供使用。[6] XLM-R 是基于 Transformer [7]的模型,是 XLM [https://arxiv.org/pdf/1901.07291.pdf 8]和罗伯塔[9]的组合。XLM-R 使用掩蔽语言建模方法接受了 100 种语言的培训。下图显示了所包含的语言和每种语言的数据量。
表 1:XLM-R 模型训练数据,取自原论文[6]
XLM-R 模型已经在四个任务上进行了评估,其中之一是 NER。虽然 XLM-R 模型是在 100 种语言上训练出来的,但原始的论文只报告了四种语言的 NER 分数:英语、荷兰语、德语和西班牙语。这些结果已在 2003 年 CONLL NER 数据集上报告。[10]这令人失望,因为在其他任务中,该模型表现良好,即使在资源较少的语言中也是如此。看到 NER 在更多语言上的表现会很有趣。
表 2:XLM-R 在 NER 的性能与其他模型的比较取自原 XLM-R 论文[9]
在上表中,我们看到了原始 XLM-R 文件中关于 NER 的结果报告。多语 BERT (M-BERT) [11]是最成熟的多语种模型之一。M-BERT 用于比较 XLM-R 在原始论文中的表现。前两个模型被用作基线,都是单语模型。对于这四种语言,我们可以看到 XLM-R 模型在所有语言上都优于 M-BERT,在 4 种语言中的 2 种语言上优于单语基线。
幸运的是,我们可以超越这四种语言,因为 Plu [12]采用了 XLM-R,并在 40 种语言上进行微调,并在所有语言上进行 NER 实验。它可用于拥抱脸。[12]该模型在 PAN-X 数据集[13]上进行了微调,该数据集也称为 Wiki-Ann 数据集,它利用了维基百科的数据。在维基百科上,有超过 295 种不同语言的文章。手工标记所有这些页面将是一项非常耗费资源的任务。手工标签被认为是黄金标准。潘等人[13]通过利用维基百科页面标记,使用维基百科页面创建了所谓的银标准命名实体语料库,命名实体通常链接到其他页面。根据语言的不同,性能会有很大的差异,但总体而言,该模型表现良好:对于许多语言,F 值接近 0.9。令人印象深刻的是,这 40 种语言来自非常不同的语系。
让 XLM-R 更进一步的实验
我们已经看到了来自 XLM-R 的令人兴奋的结果。但是有两种方法可以将这种模式进一步发展,以获得更大的收益来执行 NER:
- 领域变更:XLM-R 模型只在三个 NE 类上训练:人员、组织、位置。虽然 XLM-R 已经表明自己能够处理不同的语言,但我们还不知道它是否能够处理不同的领域。当我们在没有任何额外改变的情况下切换域时,看看结果会是什么将会是有趣的。这可能是因为该模型非常强大,可以开箱即用地跨领域应用。这将使它非常容易接近。
- 匿名化:在这篇文章的开始,我们介绍了匿名化任务及其重要性。好消息是,我们可以通过将任务转换为二元任务,将 3 类模型应用于 6 类数据集。也就是预测某个东西是不是 NE。
如果您想匿名化一个文档,您想编校文档中的每一个 NE。然而,在某些情况下,控制哪种类型的实体需要匿名,哪种类型的实体需要保留并进行实验可能是好的;对于被认为是 NE 的一部分的令牌,预测 1,对于不是 NE 的一部分的令牌,预测 0。通过这种方式,我们可以将 XLM-R 模型应用于这个数据集。
在这样的实验中,有两件事需要测试:二值化的效果和 XLM-R 模型是否也可以在跨域设置中工作。为了将单语模型与二进制化的 XLM-R 进行比较,单语模型也应该以二进制方式进行转换。
总结和下一步行动
我们现在已经奠定了多语言 NER 的基础,作为构建更具包容性的自然语言处理的关键技术。在下一篇博文中,我们将看到二进制域转换实验的结果。你认为结果会是什么?你还希望看到什么样的实验?我很想收到你的来信!
如果你想了解更多关于更苗条的人工智能和我们人工智能创新团队的最新研究,请看:【https://medium.com/slimmerai/innovation/home】T2。
参考文献
[1]世界上有多少种语言?(2021 年 2 月 23 日)。从 https://www.ethnologue.com/guides/how-many-languages取回
[2]p . Joshi,s . Santy,a . Budhiraja,k . Bali 和 m . Choudhury(2020 年)。NLP 世界中语言多样性和包容性的状态和命运。arXiv,2004.09095。从 https://arxiv.org/abs/2004.09095v3取回
[3]欧洲联盟出版物处。,凯捷发明。,&欧洲数据门户。(2020).开放数据和隐私。出版办公室。https://doi.org/10.2830/532195
[4]Mapa——公共管理的多语种匿名化。(2021 年 6 月 03 日)。检索自https://mapa-project . eu
[5] Luz de Araujo,P. H .,de Campos,T. E .,de Oliveira,R. R. R .,Stauffer,m .,Couto,s .,& Bermejo,P. (2018 年)。LeNER-Br:巴西法律文本中命名实体识别的数据集。葡萄牙语的计算处理。斯普林格。doi:10.1007/978–3–319–99722–3 _ 32
[6] Conneau,a .,Khandelwal,k .,Goyal,n .,Chaudhary,v .,Wenzek,g .,Guzmán,f .,…Stoyanov,V. (2019)。大规模无监督跨语言表征学习。arXiv,1911.02116。从 https://arxiv.org/abs/1911.02116v2取回
[7] Vaswani,a .,Shazeer,n .,Parmar,n .,Uszkoreit,j .,Jones,l .,Gomez,A. N .,…Polosukhin,I. (2017)。你需要的只是关注。arXiv,1706.03762。从 https://arxiv.org/abs/1706.03762v5取回
[8]兰普尔,g .,&康瑙,A. (2019 年)。跨语言语言模型预训练。arXiv,1901.07291。从 https://arxiv.org/abs/1901.07291v1取回
[9]刘,y .,奥特,m .,戈亚尔,n .,杜,j .,乔希,m .,陈,d,…斯托扬诺夫,V. (2019)。RoBERTa:稳健优化的 BERT 预训练方法。arXiv,1907.11692。从 https://arxiv.org/abs/1907.11692v1 取回
[10]桑,E. T. K .,& De Meulder,F. (2003 年)。CoNLL-2003 共享任务简介:独立于语言的命名实体识别。ACL 选集,142–147。从https://www.aclweb.org/anthology/W03-0419取回
[11] Devlin,j .,Chang,m-w .,Lee,k .,& Toutanova,K. (2018 年)。BERT:用于语言理解的深度双向转换器的预训练。arXiv,1810.04805。从 https://arxiv.org/abs/1810.04805v2取回
[12]jplu/TF-xlm-r-ner-40-郎抱脸。(2021 年 6 月 22 日)。从 https://huggingface.co/jplu/tf-xlm-r-ner-40-lang取回
[13]潘,x .,张,b .,梅,j .,诺斯曼,j .,奈特,k .,&纪,H. (2017)。282 种语言的跨语言姓名标记和链接。ACL 选集,1946-1958。doi:10.18653/v1/P17–117
用数据释放风能的潜力
调查加利福尼亚风能的案例研究
全球变暖严重威胁着子孙后代的福祉以及他们与这个星球互动的能力。虽然有许多行业需要改变协议来帮助应对气候变化,但其中最关键的是能源部门。电力让我们开发出令人难以置信的技术,并将我们与全球联系起来。然而,它也是温室气体排放的主要来源。
“根据美国环保署 2018 年进行的一项研究,电力生产产生了美国温室气体总量的 26.9%。”[1]
可再生能源在减少这一数字方面有很大作用。
可再生能源有很多种,其中一种是风力。风力是通过使用大型涡轮机来利用风的动能而产生的。风力使连接在发电机上的大型涡轮机旋转并发电。这些涡轮机可能非常大,高达 80 多米。一般来说,这些涡轮机建在风力发电场中,这些风力发电场包含大量相互靠近的涡轮机。
在本帖中,我们将关注北加州大风项目的风力发电,该项目是我在斯坦福大学天气和风暴课程项目的一部分。这篇文章的目的是给出相关数据的一般概念,以及如何用它来估算风力。我还想展示一些数据的大致数量,比如一个典型风力发电厂的发电量。让我们了解一下加州风力发电的现状:
2018 年,加州风能项目发电量为 15,078 千兆瓦时,占总发电量的 7.2%。[2]
W帽子是风?你知道实际上有不同类型的风吗?在课堂上,我们学习了四种主要类型:地转、梯度、沿直线等压线的表面和沿曲线等压线的表面。每种风的驱动力组合都不同。例如,沿圆形等压线作用的地面风有科里奥利力、压力梯度、摩擦力和视在离心力的作用。
沿圆形安索帕[3]的地面风力
一个地区的地形对该地区产生的风力也有影响。在北加州,特别是旧金山湾区,地形多山,靠近海边。在海边,当陆地在白天变暖时,你可以感受到陆风,风从陆地吹向海洋。相反,在晚上,当陆地更冷时,你可以得到海湾微风,风从海湾吹到陆地上。压力和温度对大气中的风的形成起着很大的作用。
T 这里的是两种主要类型的风力发电机:垂直轴和水平轴。垂直轴风力涡轮机的轴垂直于气流,而水平轴风力涡轮机的轴平行于气流。一般来说,生产中的大多数风力涡轮机是水平轴的。
仔细观察水平轴涡轮机发电的机械结构,这些结构通过大型螺旋桨状叶片利用风能。通常有三个钢制叶片安装在一个大的塔上。叶片安装在高处,以利用更高海拔处更快的风速。吹过涡轮机的风在叶片的一侧产生低压,从而产生使叶片旋转的升力。由于螺旋桨叶片的惯性质量较大,轴的转速通常为 5-20 转/分。为了产生交流电,螺旋桨叶片的轴连接到齿轮箱,齿轮箱将转速提高到 1800 rpm。
由 El-Ahmar 等人进行的一项研究。al (2017)调查了风力发电的最关键因素,并设计了以下列表:风速、空气密度、转子扫掠面积和塔架高度[4]。这些部件中的每一个都对功率输出产生不同的影响。如你所料,发电量与风速直接相关(即风速越大,发电量越大)。事实上,下面的等式通常用于测量涡轮机的潜在功率输出。我们将利用这一进展来计算功率。
D 如前所述,High Winds 项目选自 USGS 风力涡轮机数据库进行分析,并收集了 2018 年的数据,时间范围为 2018 年 1 月 1 日至 2018 年 12 月 31 日[5]。该项目始于 2003 年,位于费尔菲尔德市东南的海湾东北部。该项目包含总共 90 台额定功率为 1.8 兆瓦的 Vestas V80–1.8 涡轮机,总容量为 162 兆瓦。每台涡轮机高 60 米,转子直径 80 米。下图突出显示了 90 台涡轮机的位置。
加州北部的大风项目[5]
除了单个涡轮机信息之外,还从加州能源委员会收集了功率输出汇总信息[6]。
气候信息是从美国国家海洋和大气管理局(NOAA)的全球预报系统(GFS)大气模型中收集的。地球观测卫星系统覆盖全球,分辨率为 28 公里。在此分析中,考虑了以下变量:时间、地表温度(K)、2m 处的温度(K)、向东风速(m/s)、向北风速(m/s)、2m 处的相对湿度(%)和海平面气压(Pa)。再次收集 2018 年的数据,中心坐标约为(38,-122)。
我找到了什么?根据这一分析,该农场将在 2018 年开工不足。该分析中有一些假设,例如使用简化的风力模型,这可以解释比风力涡轮机通常发现的运行能力略低的原因。在基于风速的预期输出和总容量之间进行了比较。输出和容量用于单台涡轮机。在下图中,红线代表容量,蓝线代表当天风速下的功率输出。从图中可以看出,大多数日子都远远低于容量。
相对于容量的涡轮机输出
创建实际容量百分比分布有助于正确看待之前的数字。从下图可以清楚地看到,2018 年的涡轮机在远低于容量的情况下运行。大部分日子都在 10%或以下。
容量百分比分布图
除了运行容量,还计算了风向趋势。下图总结了 2018 年的风向。360 度罗盘被分成 45 度的相等部分,并且在该范围内的任何数据点被分配相应的罗盘方向。从结果中我们可以看出,风主要来自北/东方向。一个可能的解释是地形,这解释了暗黑风现象。在海湾的东北部,山脉之间有一个缺口,这可以让山风发展并吹向旧金山。
2018 年风向直方图
除了风向之外,速度(绿色)、温度(黄色)、压力(紫色)、相对湿度(蓝色)和功率(红色)都标在了一起。下图显示了 2018 年全年绘制的这些变量。
2018 年气候变量时间序列
要全面了解这种方法,请查看本文底部 github 上的最终报告和 jupyter 笔记本
R可再生能源每年都在增长,如果我们要达到抑制全球变暖的排放目标,就需要继续增长。风能已经并将继续成为解决方案的重要组成部分。
我希望这能让我们更好地了解预测风力发电场发电量的复杂性。虽然这种分析的简单性有些随意,但它显示了使用天气变量预测风能产量可以获得多少洞察力。
为了获得更好的结果,可以使用更复杂的风模型来获得每个涡轮机位置的速度和方向。可以在更长的时间内收集数据,以更好地了解历史趋势并预测产量何时会高或低。随着机器学习的进步,预测这些变量变得更加精确,这可以在需求规划中发挥作用。
Github 完整报告和代码:
https://github.com/jackseagrist/Wind_Available_for_Energy_Production
参考资料:
[1]—[https://www . EPA . gov/GHG emissions/sources-green house-gas-emissions #:~:text = Electricity %20 production % 20(26.9% 20 percent % 20)of,主要是% 20 煤炭% 20 和% 20 天然气% 20。](https://www.epa.gov/ghgemissions/sources-greenhouse-gas-emissions#:~:text=Electricity%20production%20(26.9%20percent%20of,mostly%20coal%20and%20natural%20gas.)
[2] —加州能源委员会,能源年鉴,全系统发电(2018)。(见https://www . energy . ca . gov/data-reports/energy-almanac/California-electricity-data/2018-total-system-electric-generation。))
[3] —丹尼尔·a·瓦列罗,5 —大气物理学,编者:丹尼尔·a·瓦列罗,《空气污染基础》(第四版),学术出版社,2008 年,第 123–153 页,ISBN 9780123736154,【https://doi.org/10.1016/B978-012373615-4/50006-6】T4。(http://www . science direct . com/science/article/pii/b 9780123736154500066)
[4] — M. H. El-Ahmar,A. M. El-Sayed 和 A. M. Hemeida,“影响风力发电机组输出功率的因素评估”, 2017 年第十九届国际中东电力系统会议(MEPCON) ,开罗,2017 年,第 1471–1476 页,doi:10.11109/MEPCON . 2013105
[5]—https://eerscmap.usgs.gov/uswtdb/
[6]—https://WW2 . energy . ca . gov/almanac/renewables _ data/wind/index _ CMS . PHP
利用 ModelOps 释放人工智能在商业应用中的价值
图片来自 Canva
人工智能正迅速成为商业和 IT 应用和运营的关键。
多年来,各组织一直在投资人工智能能力以保持竞争力,正在雇用最好的数据科学家团队,并在人工智能和机器学习系统上投入了越来越多的资金。然而,实现 AI / ML 模型并不容易,失败的风险就在眼前。需要一种可靠的方法来降低这种风险并使公司取得成功。
什么是 ModelOps,它能解决什么问题
人工智能高管多年来一直致力于在商业中获得更多模型。第一个障碍是雇佣数据科学家和快速创建模型的工具。那个问题已经解决了。下一个障碍是及时、合规地将这些模型投入生产。公司积压了大量闲置和退化的模型,对业务没有任何价值/收入贡献。我们称之为模型债务。或者他们正在努力将他们的第一个人工智能模型投入生产,并发现它比他们预期的要复杂得多,花费的时间也长得多。最重要的是,他们意识到模型,尤其是 ML 模型本质上给整个组织带来了很多风险。董事会明白,如果他们想大规模使用人工智能,他们必须有一些流程标准化和自动化,以及强有力的治理。
作者精心制作的信息图
来自运营部门,并参与了许多数字化转型项目,难怪 ModelOps 是每个人工智能项目的基石。在实验室和生产中,团队之间的思维模式/需求/协作有着巨大的差异。这在企业世界中并不是第一次:软件也发生过类似的事情:软件开发人员的代码不能及时有效地投入生产。DevOps 通过软件帮助我们改善了跨 IT 团队的协作,加快了部署周期,并通过现代软件开发方法提供了更好的体验。以类似的方式,ModelOps 正在帮助企业运营模型(人工智能、机器学习、传统模型)。由于模型会随着时间的推移而漂移,并在企业间带来巨大的董事会级风险,这就更加复杂了。数据科学家使用多种工具和语言构建模型,然后在大多数情况下,模型永远不会在生产中出现,或者即使出现也需要很长时间——有时太多,模型在那个时候就不再有用了。如果将模型投入生产,通常模型在没有适当的监控、控制和整体治理的情况下运行,因此它们并不总是能够发挥应有的作用,并且可能会使整个公司面临多种风险:法规遵从性、声誉等。…这是企业级的风险。
也就是说,我们可以将 ModelOps 定义为文化、政策、实践和工具的组合,这是组织大规模运营 AI、ML 和分析模型的能力的关键,以比现有/自主开发的方法更快的速度发展和改善模型治理和性能。这种速度使组织能够采用人工智能决策来更好地服务他们的客户,保护他们的业务,并在他们的市场上更有效地竞争。
影子人工智能:未来几年组织将不得不应对的关键问题
在早期阶段经常被低估的一个重要方面是,ModelOp 和 MLOps 是截然不同的,彼此是分开的。MLOps 面向数据科学家,而 ModelOps 主要面向首席信息官。事实上,生产中的模型必须 24x7 全天候监控和治理,法规即将出台,而且不仅限于金融服务行业。这是应该由首席信息官组织处理的事情。风险是出现另一种情况,就像我们在影子 IT 中遇到的情况一样——我们可以称之为影子 AI:每个 BU 都在没有标准化的情况下将模型投入生产,我们有一个模型的狂野西部。即使是简单的问题:“有多少生产中的模型?”变得很难回答,更不用说了解生产中每个模型的状态和状况,更不用说与法规遵从性和风险管理相关的问题了。
如果我们想到影子 IT,它不一定是坏的,因为它刺激了创新。当然,首席信息官组织必须控制它,而不是真正消除它。我们已经看到了很多问题,我在最近的文章中提到了这个问题,即组织仍然将模型视为业务部门级别的一些资产,即使在生产中也属于业务部门和数据科学家,而不是像 it 组织管理的许多其他共享服务一样,作为应该集中管理的企业资产。这是一个需要的重大思维转变。起点是理解 ModelOps 必然与数据科学分离开来。实验室和生产应该像教会和国家。不应要求数据科学家兼任运营资源,因为他们既没有带宽,也没有技能,也没有兴趣管理确保正常运营的 24x7 复杂模型生命周期。
首席信息官应在首席风险官的帮助下加快步伐,实施模型操作。
没有合适的模型操作能力的公司面临的潜在风险
在最近的一份报告中,Forrester 宣称“如果没有 ModelOps ,你的人工智能转型注定要失败”。ModelOps 当然是企业部署、监控和治理 AI/ML 模型所需的核心能力。不决定采用 ModelOps 的公司可能很难跟上竞争,当然也不会超越或领先。
良好的治理绝对需要严格的政策、实践和工具来实施控制,并跟踪可审计性、风险管理和法规遵从性的步骤和变化。做不好模型操作的风险是不可靠的业务决策(影响收入)、监管和合规处罚以及导致巨额财务和品牌成本的潜在违规。
这不仅适用于金融服务等高度监管的行业。根据《福布斯》上 Stu Bailey 的文章,人工智能正被用于在广泛的业务和行业中实现自动化决策,新的或许不太明显的漏洞正在出现。考虑这些场景:
- 一家使用人工智能驱动产品设计决策的制造商发现,一个机器学习模型出现了错误,导致了严重的客户安全问题。为了抵御责任,该公司被要求证明其人工智能模型得到了适当的开发和维护。
- 一家大型零售商的人力资源部门使用第三方软件工具来评估员工,并做出薪酬和职业发展决策。该工具整合了一些功能,允许公民数据科学家(在这种情况下,是一名没有数据科学或风险管理背景的人力资源经理)创建和部署人工智能模型,以评估员工并确定工资、奖金和晋升。该模型的部署和运行没有任何风险管理或合规团队的参与。一名没有获得晋升的员工声称,人工智能模型存在偏见,就不公平的劳动做法提起诉讼,并要求公司证明该模型是公平的”。
此外,贝利认为,“随着人工智能越来越广泛和常规化,这些只是任何类型的公司都可能很快面临的一些现实挑战。据 Gartner 预测, 到 2024 年,50%的 AI 用例 将接受风险评估,到 2022 年,15%的应用领导者将面临 AI 故障的董事会级调查。显然,是时候关注 AI 合规性了”。
组织应该如何开始做模型操作
对分析和数据科学团队:尽早让您的 IT 部门和风险部门参与进来,因为他们会帮您解决运营方面的问题,这将节省成本,并避免整个公司面临不必要的风险。
利用 ModelOps 平台自动化和标准化生产模型的模型生命周期设计流程。他们中的大多数都有乐高积木,可以缩短生产时间,例如开箱即用的工作流程、控制、监控和补救预设计流程。
选择 ModelOps 平台的另一个重要方面是尊重数据科学家和业务用户的需求:ds 平均使用 3 种模型创建工具/语言,这个数字只会增加,工具会不断地分阶段使用和淘汰。模型在内部、云中运行,并为多个分散的应用程序提供服务。这种“多对多”的情况需要一个不可知的 ModelOps 平台。
最后的想法
模型操作是大规模操作人工智能的必备能力。它包括工具、技术和实践,使组织能够在生产应用程序中部署、监控和治理 AI/ML 模型和其他分析模型。模型运算不仅仅是移动比特。部署模型并不仅仅是提供基础设施和复制代码。机器学习模型是独一无二的,因为它们必须在生产过程中不断受到监控,并定期进行再培训,这需要从数据科学家到运营专家等众多利益相关者的协作。
组织应该开始理解为什么模型操作是重要的,他们需要的能力,以及如何开发或获得它们。
关注我的每日技术和创新更新
参考
ModelOp,“2021 年 ModelOps 状态”报告。2021 年 4 月 15 日
Forrester,“引入人工智能的模型运算”,Kjell Carlsson 博士和 Mike Gualtieri,2020 年 8 月 13 日。
人工智能信任、风险和安全管理市场指南。2021 年 9 月,阿维瓦·谭力,法尔汉·乔杜里,杰瑞米·德霍因
用 Spray 将 ERDDAP 数据解组到 Akka/Scala 中
实践教程
科学数据唾手可得。有一种方法可以将它吸收到你的 Akka/Scala 项目中。
ERDDAP 是 NOAA 开发的工具,以可扩展的格式提供科学数据集,供公众广泛使用。如果您以前曾经处理过科学数据,您就会知道处理这些数据极具挑战性,因为这些数据格式是为非常特定的科学用途而构建的,具有复杂的要求,例如在多维数组中工作,并且通常是使用 Fortran 之类的计算机编程语言构建的,这些语言在科学世界之外很少使用。由于像美国宇航局或欧洲核子研究中心这样的长期组织不太可能在一夜之间改变他们的做法,所以 ERDDAP 是对公众的一种令人惊叹的服务,即使它在美学方面有一点缺乏。它吸收各种常见科学数据格式的数据,并以各种有用的格式提供易于访问的 API,以便于使用。许多组织使用 ERDDAP 来处理和分发他们的数据,以实现开放访问(和其他)的目的。
基于 ERDDAP 的数据服务中的大多数链接都指向 ERDDAP 表单,这本身就有点吓人。
ERDAP 表单——有点难看,但是考虑到您可以从 ERDAP 服务器提取的数据量,这种难看是可以原谅的。
默认的提交屏幕将为您提供一个 html 表格。我认为您可以尝试解析它,但是使用原始的 JSON 数据更有意义。您还可以使用许多其他格式,包括 MATLAB 二进制文件和 netcdfs。要访问 json 数据,只需更改文件类型。
获取一些好的旧 json 数据!
我们现在将使用普通的 JSON,但是我们也将查看。jsonlKVP(键值对流)。如果运行 submit,ERDDAP 会将 json 下载到您的计算机上——但是如果您想从服务器或以编程方式访问数据呢?为此,您可以使用“只生成 URL”服务。或者,您可以学习erd DAP 如何生成 URL 并完全跳过表单过程。
也许根本没有必要使用这个表单。
为了这项工作,我决定从加拿大渔业和海洋部收集数据——这是一个位于加拿大新斯科舍省普尔湾的水温和压力计。的。json 输出如下所示:
{
"table": {
"columnNames": ["station_name", "time", "water_pressure", "water_temperature", "battery_voltage", "latitude", "longitude"],
"columnTypes": ["String", "String", "float", "float", "float", "double", "double"],
"columnUnits": [null, "UTC", "mbar", "degree_C", "V", "degrees_north", "degrees_east"],
"rows": [
["POOLC_20200929", "2020-09-29T15:18:51Z", null, null, 0, 47.679933, -55.43001667],
["POOLC_20200929", "2020-09-29T15:18:51Z", null, null, 0, 47.679933, -55.43001667],
["POOLC_20200929", "2020-09-29T15:18:51Z", null, null, 0, 47.679933, -55.43001667], [...] ["POOLC_20200929", "2020-09-29T16:08:51Z", 83.5167, 14.4, 12.73, 47.679933, -55.42001667] [...]
}
如果你了解 Scala,你可能已经心脏病发作了。你看,与更流行的 Python 不同,Scala 非常关心进出程序的数据类型。作为一种强类型语言,它希望确切地知道正在使用什么数据类型。作为一种面向对象的语言,它希望使用类将数据放入对象中。最后,作为一种相当新的基于 Java 的语言,它会希望尽可能避免空值。
好消息是 Spray 被设计成将所有这些数据类型放入漂亮、干净的类 java 对象中。Spray 的另一个优点是它得到了 Akka 框架的支持。虽然我不会在这里过多地讨论 Akka 的内部工作方式,但主要的要点是,使用 Akka,您可以构建并发操作的流管道,而不会阻塞分布式系统。因此,如果你想获得所有这些可爱的 ERDDAP 数据,并通过一个巨大的消防水管快速可靠地发射出去,Akka 是一个很好的工作方式。Akka 也有一个名为 Alpakka 的姐妹库,它将允许你将这些流与其他服务挂钩,例如与 Apache Kafka 或 Amazon Kinesis 流挂钩,与 Cassandra 或 MongoDB 挂钩,通过像 Lambda 这样的无服务器应用程序,与像 Parquet 这样最新最棒的大数据格式挂钩(这是额尔达普人可能会做的事情)
但是足够证明 Akka,让我们进入编码的过程。我们首先需要一个对象来存储我们所有的类。这需要一些导入。
import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport
import spray.json._
import DefaultJsonProtocol._
第一次导入允许我们在 Akka 代码中使用 Spray。二是喷 json 库本身。最后,spray 中的 DefaultJsonProtocol 库包含了 Json 中可以出现的所有基本数据类型如字符串、数组、对象、整型、浮点型等等。
接下来,我们构建对象并创建一些 case 类来存储数据。
object erddapConstants extends SprayJsonSupport {
//(implicit val will go here eventually)
final case class Root(table: Table) // the root class
final case class Table(
columnNames: List[String],
columnTypes: List[String],
columnUnits: List[Option[String]],
rows: ???) abstract class ErddapDataFormat {} final case class **P**oolCoveSensorRow(
station_name: String,
time: String,
water_pressure: Option[Float],
water_temperature: Option[Float],
battery_voltage: Float,
latitude: Double,
longitude: Double) extendsErddapDataFormat}
该对象扩展了“SprayJsonSupport ”,以确保我们可以将所有可爱的 json 工具翻译成基于 Akka 的命令。我们有一个承载所有数据的根类,然后有一个对应于其余可用数据的表类。幸运的是,我们不必创建对象来处理列表特性,因为 Spray 的 DefaultJsonProtocol 已经为我们做了这些。我们还通过要求 Spray 在遇到空数据时创建一个Option[T]
来解决我们的null
问题。再一次,DefaultJsonProtocol
为我们做了繁重的工作。最后,有一个 PoolCoveSensorRow case 类来处理行数据本身。
然而,我们在弄清楚如何管理这些行时遇到了一个大问题。Spray 不支持构建一个值为Any
类型的List
。此外,spray 将无法将列表直接封送到 PoolCoveSensorRow 类中,因为没有可供 Spray 用来将行值与 case 类匹配的键值对。我们将在后面讨论这个问题。
首先,我们必须看看 spray 如何自动获取 json,并根据我们的需要将其放入我们的 case 类中。答案是通过包含隐式值来处理数据。同样,Spray 为我们提供了一些 jsonFormat 函数,帮助我们将 json 与 case 类相互转换。我们只需要知道我们的 case 类有多少个参数。
implicit val poolcSensorRowJsonFormat: JsonFormat[**P**oolCoveSensorRow] = jsonFormat7(PoolCoveSensorRow)
implicit val rootFormat: RootJsonFormat[Root] = jsonFormat1(Root)
implicit val tableFormat: JsonFormat[Table] = jsonFormat4(Table)
现在是最后一部分。我们如何处理这些行?我的第一次尝试尝试使用 Spray 的自定义格式化代码。为此,您用一个write
和一个read
方法构建一个隐式对象。大概是这样的:
implicit object PoolCoveSensorRowFormat extends RootJsonFormat[PoolCoveSensorRow] {
// writing is not so important here as you can simply
// create a JsObject out of the case class.
// How you want to handle it is up to you. def write(item: PoolCoveSensorRow) = {} // do nothing def read(json: JsValue) = {
val jsObject = json.asJsObject
jsObject.getFields("rows") match {
case List[List[***???***] if (some test) => ***(put List items into PoolCoveSensorRow object)***
case _ => ***(handle error)***}
在尝试了许多可能的格式选项后,我决定采用更简单的方法。我们可以将数据整理成 spray 的 JsValue 类型,然后根据需要进行修改,而不是搞乱数据格式。这涉及到更改表 case 类。
final case class Table (columnNames: List[String],
columnTypes: List[String],
columnUnits: List[Option[String]]
rows: List[List[JsValue]) { def poolCoveSensorTest: Boolean = rows(0).length == 7 && rows(0)(0).convertTo[String] == "POOLC_20200929" def convertedRows[T <: ErddapDataFormat]: List[T] = rows match {
case x if poolCoveSensorTest => rows.map({row: List[JsValue] =>
PoolCoveSensorRow(
row(0).convertTo[String],
row(1).convertTo[String],
row(2).convertTo[Float],
(etc)
)
case _ => throw new Exception("Rows did not match any known ErrdapDataSet")})
}
}
}
这种方法的一个好处是,您也可以为其他类型的数据创建测试,然后将测试用例包含在 convertedRows 定义中以进行数据处理。
最后,您只需将这个对象导入到另一个类中进行数据摄取。
**import** akka.NotUsed
**import** akka.actor.ActorSystem
**import** akka.http.scaladsl.Http
**import** akka.stream.scaladsl.{Sink, Source}
**import** akka.http.scaladsl.model.{DateTime, HttpRequest, HttpResponse}
**import** java.util.concurrent.ExecutorService
**import** scala.concurrent.{ExecutionContext, ExecutionContextExecutorService}class ProcessErddapData () {
implicit val system: ActorSystem = ActorSystem()
val execution: ExecutorService = java.util.concurrent.Executors.newSingleThreadExecutor()
implicit val ec: ExecutionContextExecutorService = ExecutionContext.fromExecutorService(execution) import erddapConstants._ // Get source from url
val poolCoveUrl: String = // the url def jsonDataSource(url: String): Future[HttpResponse] = {
val http = Http(system)
http.singleRequest(HttpRequest(uri = url)
} val poolCoveData: Source[PoolCoveSensorRow, NotUsed] = {
val data = jsonDataSource(poolCoveUrl)
.flatMap(resp => Unmarshal(resp.entity).to[Root])
.map(_.table.convertedRows[PoolCoveSensorRow])
Source.future(data).flatMapConcat(iter => Source(iter)) }}
现在,您可以使用poolCoveData
值作为流源,以泵入 Kafka producer,映射,与其他数据源合并,过滤,并最终运行 Akka streams 接收器进行输出。
现在有另一种方法可以用来构建流媒体源。除了在 Erddap 中使用 json 格式,还可以使用 Jsonl 格式,它只是一组由换行符分隔的键值对。看起来是这样的:
{"station_name":"POOLC_20200929", "time":"2020-09-29T15:18:51Z", "water_pressure":null, "water_temperature":null, "battery_voltage":0, "latitude":47.679933, "longitude":-55.43001667}{"station_name":"POOLC_20200929", "time":"2020-09-29T15:38:51Z", "water_pressure":null, "water_temperature":null, "battery_voltage":0, "latitude":47.679933, "longitude":-55.43001667}{"station_name":"POOLC_20200929", "time":"2020-09-29T16:18:51Z", "water_pressure":83.5167, "water_temperature":null, "battery_voltage":12.73, "latitude":47.679933, "longitude":-55.43001667}[...] and so on...
为什么我一直不用这个?活到老学到老!
不用说,使用 Akka 和 spray 收集 jsonl 数据要简单得多,几乎不值得运行教程。当然,缺点是您无权访问列数据类型和单位,并且必须自己决定转换。主要的挑战是,您需要告诉 Akka 数据是如何构造的——\n
定界的(如本例所示)或类似 json list 的其他东西。
class ProcessErddapStreamData () {
// This part is the same as before. Set up your actor system,
// and the context for your concurrent operations (single thread
// in this case). implicit val system: ActorSystem = ActorSystem()
val execution: ExecutorService = java.util.concurrent.Executors.newSingleThreadExecutor()
implicit val ec: ExecutionContextExecutorService = ExecutionContext.fromExecutorService(execution) import erddapConstants._// Add a Flow to handle the framing of your Json with max size
val jsonStream: Flow[ByteString, ByteString, NotUsed] = JsonFraming.objectScanner(1000) val poolCoveUrl = // the url ending with '.jsonlKVP' def jsonDataSource(url: String) = {
// You need to fully run the Http request before
// processing the streams. If you do not, Akka will throw an
// error to avoid having an http request open too long. Http()
.singleRequest(HttpRequest(uri=url)
.flatMap(resp => resp.entity.dataBytes.runReduce(_++_))} val poolCoveData = Source.future(jsonDataSource(poolCoveUrl))
.via(jsonStream)
.map(_.utf8String.parseJson.convertTo[PoolCoveSensorRow])}
使用 JsonFraming 类 objectScanner 方法,既可以标识要使用的分隔值,又可以为数据流设置最大值。因为这里的数据是新行分隔的,并且默认情况下在 JsonFraming 类中处理,所以除了简单地创建一个流来处理流之外,没有太多事情要做。接下来,您可以使用 Spray 的.convertTo[Class]
方法,轻松地将 json 对象转换成适当的PoolCoveSensorRow
类。
清理数据从来都不容易,处理不熟悉的数据会带来许多挑战。和往常一样,随着您越来越了解数据源内部的情况以及您的用户希望如何与数据源进行交互,找到一个可行的解决方案并随着时间的推移对其进行改进是没有坏处的。
为学习更多关于数据的知识并找到使用数据的新方法干杯!
数据科学家应该开博客的非正统理由
这些都不是你应该开博客的常用理由
Ioana Tabarcea 在 Unsplash 上拍摄的照片
每隔几周左右,我就会看到一篇关于数据科学家为什么应该开博客的新文章。
此时,互联网上充斥着这些文章,它们都在重复同样众所周知的原因,即为什么数据科学家昨天就应该开始写作。
“数据科学家应该开一个博客,这样他们就可以练习交流,这样他们就可以提高对数据科学概念的理解,这样他们就可以增加他们的专业投资组合……”
你很清楚我在说什么。
不要误会,这些文章没有错。然而,现在是时候分享一些新的观点,并提到一些不同的理由,说明为什么数据科学家应该出去写作。
因此,如果你是一名数据科学家,而那些文章并没有完全说服你应该开一个博客,那就继续读下去。
你的工作是有报酬的。
如果我说错了,请纠正我,但是开博客的最好理由之一就是每个月有一点额外的零花钱。谁不想有一些额外的被动收入呢?此外,额外的收入真的可以用来偿还学生贷款、购买食品杂货、支付汽车贷款、投资或增加你的储蓄账户。
当我开始写关于数据科学和编程的文章时,我开始每月从我在 Medium 上发表的文章中额外赚几百美元。这份额外的收入是我继续写作的一个明确的动力,它的一个奇妙的副产品是开始探索我有经验的学科以及我不太熟悉的技术领域。
有时候,除了处理数字和编写代码,做点别的事情对你的大脑有好处。
我们有时都需要休息,你的大脑也不例外。
数据科学家的工作充其量是繁重的,这使得休息一下去做一些完全不同的事情变得更加必要。写作可以是创造力和尝试新事物的一个很好的出口,否则你将无法在常规工作中获得。
我发现成功人士有趣的一点是,他们通常总是有一个与他们的工作没有任何相似或相关的爱好。爱好是充电的好方法,成功人士利用这一点来避免疲惫和放松。例如,杰克·多西徒步旅行,梅丽尔·斯特里普编织,桑德尔·皮帅打板球,史蒂夫·沃兹尼亚克打赛格威马球(是的,那确实是赛格威上的马球)。
因此,也许你不需要做像打赛格威马球这样疯狂的事情,但你可以写作,作为放松、充电和放松的一种方式。
你有机会了解你想成为什么样的数据科学家。
与普遍的看法相反,成为数据科学家的方式不止一种。
数据科学家可以根据他们的工作类型分为不同的类别,或者“原型”。例如,数据科学家可能更倾向于工程方面,他们编写代码来确定事情是如何工作的。或者,他们可能对事物的数学方面更感兴趣,并对发现事物工作的原因感兴趣。最后,他们可以更多地关注事情的商业方面,关注什么是有效的。或者,坦率地说,数据科学家可能是这三种类型的混合体。这在的这篇文章中有更好的解释。
关键是,通过创建博客和发现数据科学的不同领域,你可能会发现你真正感兴趣的数据科学领域和你真正不关心的领域。
你可以探索数据科学的不同领域,否则你将无法涉足。
根据你所从事的行业,数据科学职位可能会受到你要做的工作类型的限制。无论是你工作描述中的工作类型,还是你将要承担的项目类型,你工作的行业通常会预先决定这些事情。
虽然这绝不是一件坏事,但扩展您的视野并探索数据科学的其他领域并无大碍。
写关于数据科学的文章可以让你发现你不一定习惯的机器学习、深度学习、人工智能、数学和编程领域。此外,您将看到不同行业如何使用数据科学来解决他们的业务问题。
写作可以是一种释放压力的好方式。
或者写作是一种缓解压力的好方法——取决于你问的是谁。
在漫长的一天工作后,每个人都有自己释放压力的方式,无论是健身、遛狗、烹饪、听音乐还是阅读。写作是一种非常规的消遣方式,也能缓解压力。
写作是进入心流状态的一种极好的方式,它不需要与工作相关。通过学习写作进入心流状态,你可以鼓励你的身体在工作之外的时间进入心流状态。
为什么进入心流状态对释放压力很重要?一种心流状态鼓励注意力集中,没有来自你肆无忌惮的想法的额外噪音,给人一种清晰的感觉,良好的感觉被推到你头脑的最前沿,在达到心流状态后你甚至会变得更快乐。此外,当你专注于释放压力的事情时,压力、担忧和自我怀疑就会变得遥远。
最后的想法。
希望你带走了一些你应该开博客的不同理由。除了学习如何沟通、更深入地理解数据科学概念以及增加您的专业投资组合之外,很少触及其他原因。博客并不像听起来那样无聊和重复。
相反,把写博客看作是一种赚钱的方式,减轻一些压力,开始一个富有成效的爱好,并发现不同的领域,否则你不会有。
解除熊猫数据框的透视
如何将熊猫的数据框按摩成你需要的形状
托德·夸肯布什在 Unsplash 上拍摄的照片
介绍
上一篇文章我们分享了一个尴尬的时刻,这鼓励我们学习和使用熊猫来旋转数据帧。今天我们来看看熊猫内置的.melt()
函数来反转我们的旋转数据。当您需要改变数据帧的形状或取消数据帧的透视时,.melt()
函数就派上了用场。
入门指南
在开始之前,如果你还没有阅读Pivoting a Pandas data frame或者之前没有接触过 Python Pandas,我们建议首先从 Pandas 系列& DataFrame Explained 或者 Python Pandas 迭代 DataFrame 开始。这两篇文章都将为您提供安装说明和今天文章的背景知识。
我们离开的地方
为了让你快速了解,我们在下面加入了一段 Python 代码,摘自旋转熊猫数据框架。这个代码片段一旦执行,将会创建一个透视数据帧。
上面的 Python 代码片段将创建一个包含虚拟数据的 Pandas 数据框架。
上面的截图是执行上面的 Python 片段的结果。
既然我们的透视数据框架已经创建好了,我们将学习熊猫.melt()
函数的语法,然后再将其应用到我们的数据框架中。
熊猫。melt()语法
上面是显示熊猫融化函数语法的 Python 片段。
因素
id_vars
:您可以在这里输入一列或多列,Pandas 将使用这些列作为每条记录的标识符。value_vars
:您可以使用该参数设置您希望取消透视的列。如果您没有设置该参数,Pandas 将使用除了在id_vars
中指定的列之外的所有剩余列。var_name
:这将为变量列设置一个带标签的列名。您可以为包含已取消透视的组的列传入所需的标签。value_name
:您可以在这里设置值栏的名称。values 列表示对应于原始透视列类别的值。col_level
:如果列是多索引的,您可以使用它来设置熔化发生的级别。ignore_index
:接受一个布尔值,True
将保留原来的索引,False
将删除它。
我们的解决方案
上面的 Python 片段演示了熊猫融化函数。
上面的截图显示了熊猫融化被调用后的数据帧。
为了取消原始数据帧,我们需要将staff_no
和name
传递给id_vars
。这样做将告诉 Pandas,我们将使用员工编号和员工姓名作为每个分组的标识符。然后,我们使用var_name
和value_name
为变量和值列设置标记为列的数据帧。通过不引用原始数据帧中的 year 列作为id_vars
,Pandas 知道这些是我们想要取消透视的列。
如果您在运行上面的 melt 片段时遇到问题,您可以在这里找到一个完整的脚本。
摘要
在旋转熊猫数据框和这篇文章之间,我们为你提供了两种非常强大的方法来重塑数据框。能够应用.pivot()
和.melt()
将允许您以灵活的心态处理数据,因为您知道您可以将数据框调整到您想要的形状。
感谢您花时间阅读我们的故事,我们希望您已经发现它的价值。
不受欢迎的观点:我们将放弃机器学习作为主要的人工智能范式
人工智能
这一时刻将会到来,就像它发生在象征性人工智能身上一样。
巴林顿·拉特里夫在 Unsplash 上拍摄的照片
机器学习和深度学习将慢慢失去它们的地位,直到它们被归入它们真正的样子;奇特的统计技术。
至少二十年来,人工智能一直由连接主义人工智能(基于神经网络的人工智能)主导。从识别手写数字到掌握语言,突破一个接一个地出现。人工智能发展得如此之快,世界已经跟不上了。尽管该领域很受欢迎,但神经网络革命的主要先驱之一,人工智能的教父杰弗里·辛顿(Geoffrey Hinton)认为,我们应该从头开始重新思考一切:“我的观点是扔掉所有东西,重新开始。”
机器学习(ML)和深度学习(DL)是目前领先的人工智能范式,迄今为止已经做了出色的工作。一个很好的例子是最近基于 transformer 的语言模型的繁荣——像 GPT-3。但是,前面还有一些障碍似乎是今天的方法无法触及的。有新生的框架将在未来几年接管人工智能。这里有两个原因可以解释为什么我们会放弃将连接主义人工智能作为推动该领域前进的主导力量。
1.以目前的模式,我们无法达到人工智能的目标
人工智能可以从两个非常不同的角度来看。
首先,人工智能的实际应用方面。我们正在用深度学习方法解决问题,而就在几年前,我们还认为这是不可能的。人类水平、创造性系统、对话机器人或语言大师的对象/语音检测和识别。从这个角度来看,AI 看起来不错。
但是还有另一个角度:看着我们前进的方向。而且看起来也没那么好。在这个领域有一个持续的争论。没有人知道哪条路是通向人工智能的正确道路(AGI)。基于深度学习的解决方案是好的,但最终目标——假设可以解决一切——是,而且一直是,AGI。专家们对最新技术的认同程度不亚于他们对下一步该怎么做的分歧。
有人说我们正朝着更大、更强大的语言模型的正确方向前进——考虑到 GPT-3 及其后继者的成功,这是公平的。其他人说我们必须在这里和那里做一些曲折——想想完全自我监督的模型、强化学习、、混合模型。其他人认为我们必须添加尚不存在的新东西——比如系统 2 推理、因果关系,或者直观物理学。
我们是我们所知的唯一高智商的例子。可以合理地假设,人工智能至少在某种程度上会与某些特征相似。这就是为什么越来越多的研究人员捍卫“具体化人工智能”的观点:没有一个与世界互动的身体,智力是无法获得的。阿尔瓦·诺伊在他的《感知中的行动》一书中认为,“感知不是大脑中的一个过程,而是身体作为一个整体的一种熟练活动。”我们的智慧来自于我们在这个世界上成长、生活和互动的方式。
发展机器人学的子领域旨在以物理机器人的形式建造人工智能机器,可以像人类儿童一样成长。但是这并不是一个新的想法;图灵本人认为“与其试图制作一个模拟成人思维的程序,不如试着制作一个模拟儿童思维的程序。”然后,我们可以将问题分成两个更明确的部分:构建孩子的大脑——在图灵的假设中很容易编程——然后教育它。
这种解决方案对于今天的 ML/DL 来说完全是遥不可及的。虚拟人工智能可以解决一些问题,但不是全部。因为基于 ML 和 DL 的人工智能并不生活在现实世界中,它们无法像我们这样与现实世界互动。因此他们永远不会变得像我们一样聪明。
2.我们正在通过在黑暗中射击接近 AGI
但是让我们假定 ML 和 DL 是无辜的,假设我们可以通过继续这条道路来建设 AGI。
自从 2012 年对 DL 的兴趣飙升以来,我们一直在建立更大的模型,在更大的计算机上用更多的数据进行训练。这种“越大越好”的想法已经在自然语言处理和计算机视觉等子领域取得了重大成功。只要我们能够开发更大的模型,这种方法可能会不断给我们带来更好的结果。希望在未来的某个时候,这些模型中的一个变得如此智能,以至于达到 AGI 的地位——我们现在甚至还没有接近。
GPT 3 号是这种态度的一个很好的例子。它成为有史以来最大的神经网络,拥有 1750 亿个参数——比它的前身 GPT-2 大 100 倍。它展示了自己,在许多不同的语言任务中表现出色,甚至解决了以前留给我们的问题,如写诗或音乐,将英语转换成代码,或思考生命的意义。
GPT-3 比其他模型强大得多,以至于我们很快发现自己无法评估它的局限性:作者没有考虑人们发现的许多用例。人们不断试图找到它的弱点,一次又一次撞上了自己局限的墙。GPT 3 号的能量超出了我们测量工具的极限。无论它的智力水平如何,我们所测量的都低于这个水平。
另一个例子是一个月前发布的 Wu Dao 2.0,它现在保持着有史以来最大的神经网络的记录,它很快就会失去这个记录。这个 1.75 万亿参数的怪物比 GPT-3 大 10 倍。我们无法充分衡量 GPT 3 号的智能水平——尽管人们普遍认为它没有 AGI 的水平——我们一直在建造越来越大的模型。
为什么我们这样接近 AGI?这将把我们引向何方?
我们在黑暗中拍摄。经济利益是一个诱人的追求目标,这也正是这些模式背后的大多数公司和机构所追求的。如果我们继续构建我们无法评估的更大的智能模型,会发生什么?
通过做出我在本节开始时描述的假设,我们得出结论,我们最终将使用当前的技术构建一个 AGI 级别的系统。我们会寻找它,我们会找到它。但是我们不会知道,因为我们用来定义现实的工具会告诉我们另一个故事。而且,因为我们关灯向前走,我们甚至不会停下来怀疑这是否发生了。
这种情况有多危险?我们试图建立有史以来最强大的实体。我们在黑暗中进行。我们在盲目地做这件事。我们这样做是因为金钱和权力。如果最终,ML 和 DL 可以创造 AGI,我们最好找到一种方法来避免这种情况。我们应该改变我们的心态和范式——让其他人更容易理解,更负责任。
最后的想法
ML 和 DL 是今天 AI 的同义词。在过去的 15-20 年里,该领域的每一个重大突破都是由于这些方法的不合理的有效性。他们在解决一些问题上创造奇迹,但他们不是万灵药;他们不会解决 AI 的终极问题。
我们要么用其他更适合的范式取代这些范式,这些范式确实能够不断推动该领域向前发展,越过连接主义人工智能的障碍。或者我们最好让他们不再是主力前锋,除非我们想在不知道的情况下撞上 AGI,并潜在地发现我们自己处于 AI 推翻和否决我们的可怕场景中。
让我们去浪漫化机器学习和深度学习。让我们试着不要要求他们超出他们所能给予的。它们是非常有用的范例,但是历史一次又一次地向我们表明,即使是看起来像最终解决方案的东西也往往不是。
跟我一起去未来旅行了解更多关于人工智能、哲学和认知科学的内容!此外,欢迎在评论中提问或在 LinkedIn 或 Twitter 上联系!😃
推荐阅读
[## GPT 三号吓到你了?遇见武道 2.0:1.75 万亿参数的怪兽
towardsdatascience.com](/gpt-3-scared-you-meet-wu-dao-2-0-a-monster-of-1-75-trillion-parameters-832cd83db484)
Python 中的无监督异常检测
初学者指南
什么是异常检测?
异常检测也称为离群点检测,是在数据集中寻找与其他数据点不同的数据点的过程。异常检测的常见应用包括金融交易中的欺诈检测、故障检测和预测性维护。
广义地说,异常检测可以分为监督和非监督领域。监督异常检测需要带标签的数据集来指示记录是“正常”还是“异常”。无监督异常检测涉及未标记的数据集。它假设未标记数据集中的大多数数据点是“正常”的,并且它寻找不同于“正常”数据点的数据点。
在本文中,我们将使用 Pycaret 来检测异常。Pycaret 是一个自动机器学习(AutoML)工具,可用于监督和非监督学习。
无监督异常检测
让我们从安装 PyCaret 开始。
pip install pycaret==2.3.5
pip install scipy==1.4.1
导入必要的模块
from pycaret.anomaly import *
from sklearn.datasets import load_breast_cancer
加载数据集
我们将使用来自 UCI 机器学习库[2]的威斯康星州乳腺癌(诊断)数据集[1],该数据集包含乳腺肿块细针抽吸的特征计算数字化图像以及肿块是良性(B)还是恶性(M)的诊断。该数据集通常用于演示受监督的机器学习,其中模型被训练来预测诊断。出于演示无监督异常检测的目的,我们将忽略诊断。
我们将数据分成训练集,保留一小部分“看不见的”数据用于评分。
df = load_breast_cancer(as_frame=True)['data']
df_train = df.iloc[:-10]
df_unseen = df.tail(10)
设置 Pycaret
anom = setup(data = df_train,
silent = True)
当执行setup
时,将silent
参数设置为True
会自动确认数据类型的输入。如果silent
设置为False,
,Pycaret 要求用户手动确认输入数据类型,如下图所示。
作者图片
如果没有显式定义,Pycaret 将推断数据类型。我们还可以使用categorical_features
、numeric_features
、ordinal_features
参数定义哪些列包含分类、数字、序数和日期特性。定义不同的数据类型将影响列的预处理方式。例如,categorical_imputation
参数决定了如何处理缺失的分类值。可用选项有constant
和mode
。类似地,对于数字特征,numeric_imputation
参数决定了如何处理丢失的数值。可用选项有mean
、median
或zero
。
还有各种其他预处理选项,如归一化、降维甚至自定义转换。查看文档了解更多详情。
查看可用车型
让我们看看 Pycaret 中有哪些异常检测模型。
models()
reference 列指示模型是从哪个源包构建的。PyOD (Python 离群点检测)是一个提供各种离群点检测模型的包。
作者图片
训练异常检测模型
anom_model = create_model(model = 'iforest', fraction = 0.05)
我们通过定义模型的 ID 来训练异常检测模型。fraction
参数指示数据集中存在的异常值的数量。默认值是0.05
,表示数据集有 5%的异常值。
对数据集评分
results = assign_model(anom_model)
assign_model
使用训练好的模型对训练数据集进行评分,并返回模型的预测,与训练数据连接在一起。Anomaly
列为二进制,其中1
表示记录异常,0
表示记录正常。Anomaly_Score
列给出了记录的原始分数,负值表示记录正常。
作者图片
剧情模式
plot_model
功能有助于使用 TSNE 或 UMAP 可视化高维数据。
plot_model(anom_model, plot = 'tsne')
作者 Gif
plot_model(anom_model, plot = 'umap')
作者图片
保存模型
save_model
将转换管道和训练好的模型保存为 pickle 文件。pickle 文件包含一个 scikit-learn 管道对象。
save_model(model = anom_model, model_name = 'iforest_model')
加载模型
load_model
加载保存的转换管道和训练模型作为 scikit-learn 管道对象。
loaded_model = load_model('iforest_model')type(loaded_model)
>> sklearn.pipeline.Pipeline
看不见的数据得分
predict
方法将得到1
或0
的二进制输出,其中1
代表异常记录而0
代表正常记录。
loaded_model.predict(df_unseen)>> array([0, 0, 0, 0, 0, 1, 0, 0, 1, 0])
predict_proba
方法将得到记录被分类为0
或1
的概率。
loaded_model.predict_proba(df_unseen)>> array([[0.81527091, 0.18472909],
[0.88219213, 0.11780787],
[0.4789605 , 0.5210395 ],
[0.46277058, 0.53722942],
[0.47638085, 0.52361915],
[0.4421625 , 0.5578375 ],
[0.68153289, 0.31846711],
[0.75207438, 0.24792562],
[0.27120702, 0.72879298],
[0.54821746, 0.45178254]])
decision_function
方法将返回异常值
loaded_model.decision_function(df_unseen)>> array([-0.11826784, -0.14024322, -0.00783128, -0.00251488, -0.00698418,
0.00425233, -0.07435137, -0.09751556, 0.06039016, -0.03057366])
结论
在本文中,我们探讨了如何使用 Pycaret 快速训练无监督异常检测模型,使用 TSNE 或 UMAP 可视化高维特征,并使用训练好的模型预测未知数据。
加入 Medium 阅读更多这样的故事。
参考
[1] 乳腺癌威斯康星州(诊断)数据集
创作者:
1.威廉·h·沃尔伯格医生,普通外科部
威斯康辛大学,临床科学中心
麦迪逊,WI 53792
沃尔伯格**’ @ '**eagle.surgery.wisc.edu
2.威斯康星大学计算机科学系 w . Nick Street
,威斯康辛州麦迪逊市西代顿街 1210 号,邮编:53706
Street**’ @ '**cs.wisc.edu 608–262–6619
3.Olvi L. Mangasarian,计算机科学系
威斯康星大学,威斯康辛州麦迪逊市西代顿街 1210 号,邮编:53706
olvi**’ @ '**cs.wisc.edu
捐赠者:尼克街
许可证:CC BY 4.0
[2]Dua d .和 Graff c .(2019 年)。UCI 机器学习知识库[http://archive . ics . UCI . edu/ml]。加州欧文:加州大学信息与计算机科学学院。
使用 Python-K Means ++和剪影分数进行聚类的无监督学习技术
K 入门指南意味着使用 Python 进行集群
丽贝卡·坎贝尔在 Unsplash 上拍摄
没人监督我!
对于那些想知道什么是无监督学习技术的人,想象一下你在克莱顿经营一家体育用品店。你计划为你的高价值客户推出促销优惠,以示感谢。每天都有成百上千的顾客来拜访你。您应该将此报价发送给谁?艰难的选择!嗯,也许是高价值的?但是那些经常购买但花费不多的人呢?这是一个很大的困境。幸运的是,您的积分卡计划可以捕获您的客户信息,而您的 oracle 数据库包含所有交易详情。您可以使用这些数据,形成一组具有相似属性的客户,而无需预先定义谁属于哪里。简而言之,没有预定义的结果变量(在这种情况下是你的客户细分)但在研究客户属性后形成一个结果变量的学习技术被定义为无监督学习技术。
遭受维度的诅咒
从理论上讲,你对你的客户了解得越多,你就能更好地对他们进行分组。难道不是吗?然而,在现实生活中,比你想象的要复杂一点。实际上,太多的信息(特征)会导致你的客户分组不佳。但是为什么呢?
- 特征可能高度相关,年龄越高,花费越低
- 太多的特征会引入大量的噪声,使得算法很难对数据执行良好的操作——Sam,您的邻居客户几乎每天都来打招呼并购买价值一美元的蛋白质棒。他是一个非常受重视的客户?
- 训练任何无监督模型所需的数据点数量会随着维度(特征)呈指数增长。太多的信息意味着需要更多的数据来训练模型
为了克服这些问题,不同的降维技术,如主成分分析,因子分析等。可以使用。我们引入了维数灾难的概念,为围绕无监督学习技术的假设铺平了道路。
算法
无监督学习技术的一些常见算法包括:
- k 表示聚类
- 分层聚类
- k 模式聚类
- DBScan 聚类-基于密度的空间聚类
- 主成分分析
- 要素分析
我们今天讨论什么?
人们通常认为现实是一系列非黑即白的事件。这是一个具有挑战性的问题,因为那些受这种思维方式折磨的人可能永远不会觉得现实足够好。今天,我们试图解决简单和抑郁的问题,同时确定因抑郁症住院的精神病患者中更高水平的黑白思维和更高水平的自我报告抑郁之间的关系。
数据源
用于此分析的数据来自 Ginzberg 数据框架,该数据框架基于因抑郁症住院的精神病患者。数据收集自《应用回归分析和广义线性模型》一书,第二版,作者 Fox,J. (2008)。该数据集包括三个变量——简单性(非黑即白的思维)、宿命论和抑郁症及其调整后的分数。
算法— K 表示聚类
分解一下,K 表示组数,Means 表示平均值。本质上,我们有基于平均距离计算的 K 个组。我猜不清楚!对于任何要工作的 K 均值聚类算法,我们需要有以下参数。
- K —我们想要多少组。注意——该算法不具备决定或得出 k 值的预测能力。这是由肘图和轮廓分数等少数技术指导的用户调用
- 数据点——在这种情况下,简单、宿命论和抑郁得分,即你的输入数据
- K 个质心 —把它想象成 K 个组中每一组的锚点/中心值。大多由算法随机选择。质心的选择影响最终集群/组的形成方式。此外,如果您熟悉使用 O(n)表示的任何算法的时间复杂度,已经观察到次优的质心分配使得时间复杂度为多项式,即算法运行和收敛的时间更长。因此,David Arthur 和 Sergei Vassilvitskii 提出了一种更智能的方法(也称为 K 表示++的意思),它执行以下操作:
-从输入数据点(比如 X)
中随机选择一个中心 C1-对于尚未选择的每个数据点 X∈**X,计算 D(x),即 X 和已经选择的最近质心之间的距离
-对于所有 x* ∈选择一个新的中心 Ci,选择 x* ∈ X,使其概率为 D(x) / Sum(对于所有 x ∈ X D(x) )
-重复步骤 2 和 3,直到 k 个中心被选择 - 距离度量 —主要是欧几里德距离,作为多个患者之间相似性的度量。例如,当我们谈论足球或众所周知的足球时,我们经常使用总得分来对优秀球员进行分组。说 c 罗,梅西,沃纳,普基分别进了 35,32,10,8 个球。你将如何衡量类似球员的质量?大概是 c 罗和梅西(各 35、32 球)和沃纳和普基(各 10、8 球)。请注意,我们研究了进球得分的差异。如果我添加“助攻”作为另一个指标,我们需要使用不同的衡量标准。比如助攻分别是 10,8,2,1。所以 c 罗和梅西之间的新距离变成了的平方根((35–32)+(10–8))。注意——其他距离度量,如曼哈顿、城市街区、雅可比距离等。也被其他一些算法所采用。
K-如何意味着工作?
图一。K 均值聚类算法的工作可视化。图片来源:图片来源——Wikimedia.com GIF
图二。说明了 K 均值算法的逐步分解。图片来源——由作者使用 PowerPoint 开发。
重要术语和公式
注:所有图片均由作者使用 latex 复制。
- 质心
1. Ci - ith Centroid where i ∈ K (or K Groups of Cluster)
2\. Si - Group of Data points that belong to Cluster K with Ci as its centroid; j represents attributes of a point Xi
3\. ||Si|| - Number of data points from Si
- 欧几里德距离
1\. Dx is the distance of of a point Xi from it's centroid Ck
- 收敛准则 K 意味着是一个迭代过程。一旦所有数据点都被分配给质心(基于最短的欧几里德距离),质心被重新计算,并且该过程继续,直到质心停止重新移动,即新的和先前的质心编号没有显著变化
- 类内和类间距离
类内距离是同一类中的点之间的总距离,类间距离是不同类中的两点之间的距离
假设
- k 表示如果数据包含异常值,算法性能很差
- k 表示算法不能处理缺失值
- 聚类变量之间不应该高度相关
- 所有聚类变量都应标准化,因为变量的大小会影响距离计算
还在想怎么决定 K?让我们深入挖掘
# Numerical libraries
import numpy as npfrom sklearn.model_selection import train_test_splitfrom sklearn.cluster import KMeans# to handle data in form of rows and columns
import pandas as pd# importing ploting libraries
from matplotlib import pyplot as plt
%matplotlib inline#importing seaborn for statistical plots
import seaborn as snsfrom sklearn import metricsimport pandas as pd# reading the CSV file into pandas dataframe
mydata = pd.read_csv(“Depression.csv”)mydata.drop('id', axis=1, inplace=True)
检查相关性
# — — — — — — — — — — — — — — — -Heat map to identify highly correlated variables — — — — — — — — — — — — -
#-------------------------------Heat map to identify highly correlated variables-------------------------
plt.figure(figsize=(10,8))
sns.heatmap(mydata.corr(),
annot=True,
linewidths=.5,
center=0,
cbar=False,
cmap="YlGnBu")
plt.show()
图 3。展示了关联矩阵的热图。注意——所有变量都与其调整后的分数高度相关。这是一个关于是保留原来的分数还是继续调整分数的个人问题。这无法得到任何统计假设的支持。图片来源——作者使用 Jupyter Notebook 开发。
异常检测和处理
mydata.drop(columns = {‘simplicity’, ‘fatalism’,’depression’}, inplace=True)#--Checking Outliers
plt.figure(figsize=(15,10))
pos = 1
for i in mydata.columns:
plt.subplot(3, 3, pos)
sns.boxplot(mydata[i])
pos += 1
图 4。聚类变量的箱线图摘要。图片来源——作者使用 Jupyter Notebook 开发。
col_names=list(mydata.columns)
display(col_names)for i in col_names:
q1, q2, q3 = mydata[i].quantile([0.25,0.5,0.75])
IQR = q3 — q1
lower_cap=q1–1.5*IQR
upper_cap=q3+1.5*IQR
mydata[i]=mydata[i].apply(lambda x: upper_cap if x>(upper_cap) else (lower_cap if x<(lower_cap) else x))
标准化属性/聚类变量
##Scale the data
from scipy.stats import zscoremydata_z = mydata.apply(zscore)mydata_z.head()
K 表示使用 Sklearn 进行聚类
# List to store cluster and intra cluster distanceclusters = []
inertia_vals = []# Since creating one cluster is similar to observing the data as a whole, multiple values of K are utilized to come up with the optimum cluster value
#Note: Cluster number and intra cluster distance is appended for plotting the elbow curve
for k in range(1, 10, 1):
# train clustering with the specified K
model = KMeans(n_clusters=k, random_state=7, n_jobs=10)
model.fit(mydata_z)# append model to cluster list
clusters.append(model)
inertia_vals.append(model.inertia_)
参数
- n_clusters —要形成的簇的数量;也等同于要生成的质心的数量
- init 指定初始质心初始化的方法(默认 K-means++)
- n_init —使用不同质心种子运行 k-means 算法的次数
- max _ ITER—k-means 算法单次运行的最大迭代次数。满足收敛标准时停止,使用 tol(公差选项)定义
- random_state —协助质心初始化的随机数生成。导入以确保可重现的结果
什么是惯性 _?
惯性被定义为数据点到它们最近的聚类中心(质心)的平方距离之和。距离越小,聚类的紧密度越好。但是,随着 k 值的不断增加,惯性会不断降低。具有两个聚类的算法将始终比具有四个聚类的算法具有更高的惯性分数,依此类推。这就是我们结合肘部绘图和轮廓分数来决定 k 的最佳值。
肘击剧情
这里的想法是为不同的 K 值绘制总惯性分数,并确定 K,超过 K 惯性变化不大。惯性的公式如下。
1\. I = Inertial = Sum of the squared distance of data points to their closest cluster
2\. n = Total number of records in the dataset
3\. D()= Sum of squared distance
4\. Xi = Record i in the data (i.e. in this case record of a given patient)
5\. Ck = Cluster to which record Xi is assigned
图 5。说明了肘图。X 轴表示聚类的数量(K ), Y 轴表示惯性值。图片来源——作者使用 Jupyter Notebook 开发。
# plot the inertia vs K values
plt.plot(range(1,10,1),inertia_vals,marker='*')
plt.show()
研究上图可以发现,4、5 或 6 是 k 的最佳值。请注意,从 6 到 7,曲线趋于平缓,而斜率在 4 个聚类后没有观察到显著变化。
比我们想象的要难!让剪影配乐成为救世主
轮廓分数用于测量聚类之间的分离程度。在上面的公式中,bi 表示一个点到 I 不属于的任何其他聚类中所有点之间的最短平均距离,而 ai 是 I 和来自同一聚类的所有数据点的平均距离。从逻辑上来说,如果 bi > ai,那么一个点与它的相邻聚类分离得很好,而它更接近它所属的聚类中的所有点。
from sklearn.metrics import silhouette_scorefor i in range(1,9,1):
print("---------------------------------------")
print(clusters[i])
print("Silhouette score:",silhouette_score(mydata_z, clusters[i].predict(mydata_z)))
输出
KMeans(n_clusters=2, n_jobs=10, random_state=7)
Silhouette score: 0.40099183297222984
---------------------------------------
KMeans(n_clusters=3, n_jobs=10, random_state=7)
Silhouette score: 0.3191854112351335
---------------------------------------
KMeans(n_clusters=4, n_jobs=10, random_state=7)
Silhouette score: 0.281779515317617
---------------------------------------
KMeans(n_clusters=5, n_jobs=10, random_state=7)
Silhouette score: 0.2742499085300452
---------------------------------------
KMeans(n_clusters=6, n_jobs=10, random_state=7)
Silhouette score: 0.2790023172083168
---------------------------------------
KMeans(n_clusters=7, n_jobs=10, random_state=7)
Silhouette score: 0.2761554255999077
---------------------------------------
KMeans(n_jobs=10, random_state=7)
Silhouette score: 0.2666698045792603
---------------------------------------
KMeans(n_clusters=9, n_jobs=10, random_state=7)
Silhouette score: 0.27378613906697535
观察局部最大值的轮廓分数用于确定与肘图一起的聚类的最佳数量。因此,在本例中,我们可以将 6 作为最佳群集数量。
关于作者:高级分析专家和管理顾问,帮助公司通过对组织数据的商业、技术和数学的组合找到各种问题的解决方案。一个数据科学爱好者,在这里分享、学习、贡献;你可以和我在 上联系 和 上推特;