Python 中二进制数据的用户相似性
为二进制数据选择相似性度量时需要考虑什么
作者图片。
用户聚类和相似性计算在当今的行业中越来越重要。顾客被要求对特定的 f. e .产品进行评分,然后与其他顾客的评分进行比较,以找出它们之间的相似之处。
大多数用户聚类应用程序使用分级评级,例如 0-5 颗星,或者像 IMDB 上的评级等级 1-10。在这些情况下,我们可以很容易地应用像欧几里德距离或余弦相似度这样的度量来发现用户的选择有多相似/不同。如果我们没有这样的收视率,我们在处理 二进制数据怎么办?
在本文中,我将向您展示在二进制数据上使用欧几里德距离度量时为什么要小心,使用什么度量来计算用户相似性,以及如何创建这些用户的排名。我将使用 Python 3 和 Scipy 和熊猫 T21。
import scipy.spatial
import pandas as pd
1 |计算适当的相似性度量
假设我们有三个用户:A、B 和 c。这些用户都填写了关于他们最喜欢的水果的多项选择调查。
表 1:用户对喜爱水果的选择。图片作者。
用户的选择可以被解释为独热编码向量,而✔️被替换为 1,❌被替换为 0。
user_choices = [[1, 1, 0, 0],
[1, 1, 1, 0],
[1, 0, 0, 0]]df_choices = pd.DataFrame(user_choices, columns=['Apples',
'Bananas', 'Pineapples', 'Kiwis'],
index=(["User A", "User B", "User C"]))
为什么欧氏距离或余弦相似性等度量不适用于此数据集?
首先看一下表 1,我们会建议用户 A 和用户 B 有更相似的口味,因为他们都选择了“苹果”和“香蕉”作为他们最喜欢的水果。
但是,计算用户之间的欧几里德距离会得到如下结果,如表 2 所示:
euclidean = scipy.spatial.distance.cdist(df_choices, df_choices,
metric='euclidean')user_distance = pd.DataFrame(euclidean,
columns=df_choices.index.values,
index=df_choices.index.values)
表 2:用户之间的欧几里德距离。图片作者。
尽管我们看到用户 A 和用户 B 都选择了更多相同的水果,但欧几里德距离为用户 B 和用户 c 返回了相同的距离值 1.00。为什么会这样呢?
欧几里德距离考虑了联合缺席(即两个用户在相同的位置上具有 0)。因此,它也认为用户 A 和用户 C 是相似的,因为他们都没有选择“菠萝”。同样的原理也适用于余弦相似性。对于某些用例,欧几里德距离可能仍然是二进制数据的合适度量,但是对于我们的用例,它给出了错误的结果。
我们不希望根据用户没有做出的选择来假设用户是相似的。
为了我们的目的,我们应该转向一种叫做雅克卡距离的度量。
图 1: Jaccard 距离方程。作者图片。
TT (True True)是两个用户选择相同水果的次数(即两个用户在相同的位置都有 1)。TF (True False)和 FT (False True)是只有一个用户选择水果的次数(即一个用户选择 1,另一个用户在相同位置选择 0)。我们不考虑两个用户都不选择水果的情况。
现在让我们看看 Jaccard 距离如何对我们用户的相似性进行评级:
jaccard = scipy.spatial.distance.cdist(df_choices, df_choices,
metric='jaccard')user_distance = pd.DataFrame(jaccard, columns=data.index.values,
index=data.index.values)
表 3:用户之间的 Jaccard 距离。图片作者。
从上表中我们可以看到,实际上,与用户 C 到用户 A 的距离值相比,Jaccard 距离值认为用户 B 与用户 A 更相似,因为它的距离值更低。这是我们希望我们的用例达到的结果。
2 |根据用户选择的相似性对用户进行排名
为了完成我们的任务,让我们根据用户的相似性对他们进行排序,并将他们导出为 Python 字典。
# prepare a dictionary
user_rankings = {}# iterate over the columns in the dataframe
for user in user_distance.columns: # extract the distances of the column ranked by smallest
distance = user_distance[user].nsmallest(len(user_distance))
# for each user, create a key in the dictionary and assign a
# list that contains a ranking of its most similar users
data = {user : [i for i in distance.index if i!=user]}
user_rankings.update(data)
输出字典将如下所示:
{'User A': ['User B', 'User C'],
'User B': ['User A', 'User C'],
'User C': ['User A', 'User B']}
用户 A 对喜爱的水果的选择更类似于用户 B,而不是用户 C。
用户 B 对喜爱的水果的选择更类似于用户 A,而不是用户 C。
本文演示了 Jaccard 距离如何成为计算二进制向量之间相似性的合适度量。
尽管如此,始终确保根据数据集类型和您试图实现的目标明智地选择相似性/距离度量**。**
参考资料:
[1] A. S. Shirkhorshidi,S. Aghabozorgi S,T. Y. Wah,连续数据聚类中相似度和相异度的比较研究 (2015),PLoS ONE 10(12): e0144059。
[https://www.ibm.com/support/knowledgecenter/SSLVMB_sub/statistics_mainhelp_ddita/spss/base/cmd_proximities_sim_measure_binary.html 2] IBM,二进制数据的距离相似性度量 (2021)
通过简单的例子解释用户对用户和项目对项目的协同过滤(第 1 部分)
简单解释了协同过滤背后的魔力。
Samuel Regan-Asante 在 Unsplash 上拍摄的照片
如果你是一名数据科学家,想要建立一个项目组合来推荐书籍/电影/产品,或者你只是想了解协同过滤是如何工作的,这篇文章将会帮助你。
概括地说,有两种主要类型的推荐系统。基于内容的协同过滤。顾名思义,第一种基于内容的类型通过推荐与你喜欢的内容相似的产品来工作。一种常见的方法是推荐具有相似描述的产品(即内容)作为您最喜欢的产品。在这篇文章中,我们将关注第二种类型,即协同过滤方法,这种方法根据用户评级推荐产品,在行业中被广泛采用。
让我们用电影推荐来说明这个概念。如果我们使用用户对用户的方法,我们会发现用户之间的相似性,而推荐给用户的电影将基于与他们最相似的另一个用户喜欢的电影。
另一方面,如果我们使用项目到项目的方法,我们会发现电影之间的相似性。然后如果一个用户喜欢一部电影,我们会推荐和那部最相似的电影。
用户到用户和项目到项目之间的区别可能会令人困惑,帮助我区分它们的概念是我们是否使用用户或项目作为绘制的轴。如果我们使用用户作为轴,那么这意味着我们在使用项目到项目的方法。反之亦然,如果我们用电影作为轴心,这意味着我们在做用户对用户的方法。我们来举例说明。
用户对用户的方法
这里有一个例子,其中 3 个用户(u1、u2、u3)对 2 部电影(m1、m2)进行了评级。
3 电影用户评分 1 & 2
然后,我们可以通过将电影 1 的收视率作为 x 轴,将电影 2 的收视率作为 y 轴来绘制这些用户。
用户对用户的方法
如你所见,用户 1 和用户 3 非常相似。如果我们有一些电影 X,用户 1 确实喜欢,而用户 3 没有看过,我们将只把电影 X 推荐给用户 3。
逐项方法
现在让我们假设只有 2 个用户(u1,u2)对 3 部电影(m1,m2,m3)进行了评级。
用户 1 & 2 评价的 3 部电影
我们不会试图寻找用户之间的相似性,而是将重点放在以每个用户评级为轴绘制电影上。
逐项方法
通过查看图表,我们可以看到电影 1 和 3 更接近,因此更相似。起初,这可能看起来有点像魔术,但肯定是有效的,因为喜欢动作片的用户可能会对其他类型的评分很低,从而导致这些相似性聚类的出现。但是我们如何量化这种相似性呢?
确定相似性的两种流行方法是余弦距离和皮尔逊相关性,余弦距离本质上是两个向量之间的角度投影,皮尔逊相关性计算向量之间的成对相关性。
余弦相似度
确定两个向量 A 和 b 之间余弦相似性的公式。分子表示两个向量的点积,分母表示它们的大小相乘。
让我们用 python 计算余弦距离。
from sklearn.metrics.pairwise import cosine_similaritycosine_similarity(df)
或将余弦相似性数组放入数据帧中
余弦相似矩阵
我们做了什么,这意味着什么?
通过做余弦相似度(df),我们已经计算了每部电影之间的 cos(Theta)。因此,第一行向我们展示了电影 1 与其自身完全相关/相似,与电影 2 相关性差,与电影 3 相关性非常强。相关性越强,电影越相似;这使得我们能够向一个用户推荐他过去可能喜欢的类似电影。
标准化评级
将用户相对于其他用户的“审阅者难度”标准化的常用方法是通过减去平均值并将评级除以范围来标准化他们的评级。
如果我们将评级标准化,然后取余弦相似度,我们会得到
归一化余弦相似矩阵
现在你可以看到相关性更容易解释,但得出的结论与我们之前的分析相同。
皮尔森相关性
就拿电影之间的皮尔逊相关性来说吧。提醒一下,这是我们的逐项评级数据框架(df)
我们仍然在做项目到项目的方法,但是为了计算电影之间的相似性,我们必须对这个矩阵进行转置,使每部电影成为一列。原因是 Pearson correlation 将每一列视为一个向量,并将计算它们之间的成对相关性。
项目间的皮尔逊相关矩阵
正如你所看到的,对角线上的词都是 1,因为每部电影都有完美的相关性/完美的相似性。但是为了解释其含义,从第一行我们可以看到,电影 1 与电影 2 的相关性非常差,而与电影 3 的相关性非常强,这也与我们使用归一化余弦相似性方法得到的结果一致。
最后的话
如果用户告诉我们他们最喜欢的电影,我们如何扩展这种方法并创建一个函数或后端 API 来向用户推荐电影?
例如,一个简单的策略是,如果他们告诉我们他们喜欢电影 1;我们将获得 m1 的相似性行,按照降序排列相似性值,并选取与电影 1 最相似的前 10 或 50 个项目,并将它们推荐给用户。
我将在下一篇文章“**如何使用开源 MovieLens 数据集构建电影推荐引擎后端 Flask API(第 2 部分)**中进一步探讨这个问题。
参考文献
- https://medium . com/code-heroku/how-to-turn-your-machine-learning-scripts-into-projects-you-can-demo-CBC 5611 ca 442
- https://real python . com/build-re commendation-engine-collaborative-filtering/
在拥抱脸中使用数据加载器
PyTorch 版本
每一个深入 DL 世界的人都可能听说,相信,或者是被试图说服的目标,这是一个 变形金刚 的时代。自从第一次出现,变形金刚就成了几个方向大量研究的对象:
- 研究人员寻找建筑的改进。
- 人们研究管理这个领域的理论。
- 搜索可能使用此方法的应用程序。
那些旨在深入研究变形金刚的读者可能会找到大量详细讨论变形金刚的资源。简而言之,转换器通常用于为 NLP 问题开发语言模型。这些模型用于构建句子、Q & A 和翻译等任务。在一个非常高级的描述中,转换器可以被认为是复杂的自动编码器,它接收键、值和查询(单词)三元组作为输入,并研究一个语言模型,其中每个单词都有一个依赖于其语义上下文的特定表示。
伯特&拥抱脸
BERT ( 来自变压器的双向编码器表示)在此引入。随着变形金刚的出现, BERT 的想法是采用变形金刚预先训练好的模型,并根据特定任务对这些模型的权重进行微调(下游任务)。这种方法产生了一类新的 NLP 问题,可以通过最初使用转换器来解决,例如分类问题(例如情感分析)。这是通过将网络的上层修改成集群的结构或不同类型的序列来实现的。因此,我们有许多伯特模型。这样一个伟大的“模特银行”就是抱脸。该框架提供了一个包含三个基本组件的包:
- 各种预先训练的模型和工具
- 令牌化引擎
- 框架灵活性(例如 Torch、Keras)
这个软件包可以处理大量的 NLP 任务。
那我为什么要写帖子呢?
当我开始使用拥抱脸时,我对它提供的优秀的“端到端”管道以及它提供的数据结构的便利性印象深刻。然而,我觉得他们的教程中有一部分没有很好地涵盖。在我自己设法找到解决方案后,我觉得作为一个“激进的开源”我必须分享它。
为了说明这个问题,我将简要描述拥抱脸提供的特征提取机制。我们给出的数据很简单:文档和标签。
最基本的函数是记号赋予器:
**from** transformers **import** AutoTokenizer
tokens = tokenizer.batch_encode_plus(documents )
这个过程将文档映射成变形金刚的标准表示,因此可以直接用于拥抱脸的模型。这里我们提出一个通用的特征提取过程:
**def** regular_procedure(tokenizer, documents , labels ):
tokens = tokenizer.batch_encode_plus(documents )
features=[InputFeatures(label=labels[j], **{key: tokens[key][j]
**for** key **in** tokens.keys()}) **for** j **in** range(len(documents ))]
**return** features
该方法的输出列表:特性是一个可以用于训练和评估过程的列表。我发现的一个障碍是缺乏使用 Dataloader 的教程。
在所有教程中,假设我们使用训练/评估期间可用的数据。这个假设对于新兵训练营的需求来说是明确的,但是对于现实世界的任务来说是错误的。我们正在处理大数据:
在大数据中,代码指向数据,而不是数据指向代码
我开始尝试。我的目标是创建一个能够用 PyTorch **数据加载器访问的特性文件夹。**我的第一次尝试如下:
**def** generate_files_no_tensor(tokenizer, documents, labels ):
tokens = tokenizer.batch_encode_plus(documents )
file_pref =**"my_file_"
for** j **in** range(len(documents) ):
inputs = {k: tokens[k][j] **for** k **in** tokens}
feature = InputFeatures(label=labels[j], **inputs)
file_name = file_pref +**"_"**+str(j)+**".npy"** np.save(file_name, np.array(feature))
**return**
这段代码运行得很好,但不是最佳的。它的主要缺点是节省了 numpy 个对象,而抱紧的模型需要个张量。这意味着我的 getitem 函数将有额外的任务,但上传文件:
**def** __getitemnumpy__(self, idx):
aa = np.load(self.list_of_files[idx], allow_pickle=**True**)
cc = aa.data.obj.tolist()
c1 = cc.input_ids
c2 = cc.attention_mask
c3 = cc.label
**return** torch.tensor(c1), torch.tensor(c2), c3
在训练过程中,我们需要将数量级的对象转换成张量。
我决定以一种不同的方式工作:我开发了我的 getitem 并强迫数据“承认它的规则”。
**def** __getitem__(self, idx):
aa = torch.load(self.list_of_files[idx])
**return** aa[0], aa[1], aa[2]
现在让我们面对挑战。让我们试试这个:
**def** generate_files_no_tensor(tokenizer, documents, labels ):
tokens = tokenizer.batch_encode_plus(documents )
file_pref =**"my_file_"
for** j **in** range(len(documents) ):
inputs = {k: tokens[k][j] **for** k **in** tokens}
feature = InputFeatures(label=labels[j], **inputs)
file_name = file_pref +**"_"**+str(j)+**".pt"** torch.save(file_name, feature)
**return**
有用!我们甚至可以直接接触到张量。但是这个循环非常慢。当我观察这些数据时,我看到了两个“现象”:
- 所有文件都有相同的大小
- 文件很大!!
我花了一段时间才意识到所有的文件都保存了整个张量(它们可能保存了一个指向它的位置的点)。因此,我们必须将它切片。
**def** generate_files_with_tensor(tokenizer, documents, labels ):
tokens = tokenizer.batch_encode_plus(doc0, return_tensors=**'pt'**)
file_pref =**"my_file_"
for** j **in** range(len(documents) ):
file_name = file_pref +**"_"**+str(j)+**".pt"** input_t = torch.squeeze(torch.index_select(tokens[**"input_ids"**],dim=0,
index=torch.tensor(j)))
input_m = torch.squeeze(torch.index_select(tokens[**"attention_mask"**],dim=0,
index=torch.tensor(j)))
torch.save([input_t, input_m, labels[j]], file_name)
**return**
index_select 函数对张量进行切片,挤压允许移除尺寸为 1 的尺寸。它达到了要求。现在我有一个快速的 getitem 除了上传数据什么也不做。
具有数据结构和数据加载器的代码示例存在于这里。
希望你会觉得有用。
使用人工智能模拟 TS-9 吉他踏板
装有 TS-9 的踏板(图片由作者提供)
开源,使用机器学习实时数字克隆 TS-9 吉他踏板(带视频演示)
A nalog 是吉他效果领域的王者,但数字建模已经走过了漫长的道路来复制它。详细的电路分析和数学方程可以重现许多这类设备的声音,从电子管放大器到过驱电路再到弹簧混响。通常需要电子和物理建模领域的专业知识。
但是,如果我们能跳过所有的数学和物理,直接去做我们真正想要的东西,美妙的声音,会怎么样呢?如果你可以说,我不在乎那些金属盒子里发生了什么,我只想要声音!这种方法被称为黑盒 建模,公开可用的人工智能框架使任何人都有可能做到。
作为一名工程师,我的一部分想大喊,“*嘿,那是作弊!”*你真的能跳过分析电路、建立元件模型和令人头疼的数学运算,直接把数据扔给计算机替你解决吗?答案是既肯定又否定。
人工智能采用传统的问题解决方式,并彻底改变了它。你仍然需要了解如何设置你的问题,但它的解决方式不同。找出最佳的模型架构和训练参数本身就是一门科学(或艺术),这一切都取决于良好的数据。在 TS-9 吉他踏板的情况下,数据以音频记录的形式出现。
通过记录踏板的输入和踏板的输出,你把它当作一个黑匣子。输入和输出是已知的,但我们不需要了解它是如何工作的。根据音频数据训练神经网络,使其表现与真实踏板相同。你甚至可以在你的吉他上实时运行这个模型,方法是围绕它构建一个高性能的音频应用程序,本质上是制作一个数字克隆。
注:你可以在这里 阅读更多关于我的数据收集方法 。
这对于在特定设置下采集踏板声音非常有用。在 TS-9 踏板的情况下,这可能看起来像 100%的驱动,50%的音调和 50%的水平。但是我们如何在一个模型中复制所有可能的旋钮位置呢?更多数据!
TS-9 踏板上的控件(图片由作者提供)
参数调节允许我们创建一个模型,它可以像真正的踏板一样调整。通过在每个旋钮的离散步骤中记录踏板的音频,您可以训练一个条件模型,该模型对旋钮或旋钮组的整个范围进行插值。
对于 TS-9,驱动和音调控制被选为条件参数。水平旋钮可以被包括在内,但它可以近似为实时音频插件中的一个简单的音量旋钮。这也会给培训增加更多的数据和复杂性。
对于训练数据,在 0%、25%、50%、75%和 100%旋钮位置进行 2 分钟采样。对于两个旋钮,这产生 5 * 5 = 25 种不同的组合,用于 25 个单独的 2 分钟录音加上基线输入音频文件。一旦录制了音频,每个音轨都被导出为 32 位浮点单声道 WAV 文件。音频数据的总大小约为 520MB。
自动化吉他弹模项目的吉他弹模叉用于训练。此分叉包含用于条件模型音频处理的额外代码。该项目用 python 编写,使用 Pytorch ,包含几个机器学习模型,用于模拟效果建模。LSTM(长短期记忆)模型用于 TS-9 踏板。
注意:处理后的输入 WAV 文件包含三个通道,一个用于音频,一个用于驱动旋钮参数(范围 0.0 到 1.0),一个用于色调旋钮参数(范围 0.0 到 1.0),作为 LSTM 模型的输入。输出 WAV 文件包含一个通道,即输出音频。
实时插件(作者图片)
JUCE 框架用于构建实时应用程序,命名为“TS-M1N3”(这是一个不好的双关语)。Windows/Mac 安装程序可以从 Github 和源代码下载,有 VST3 / AU / Standalone 格式。 RTNeural 用于 LSTM 模型的神经网络推理,并显著提高了速度。
注:关于使用 LSTM 神经网络创建实时音频应用程序的更多细节,请查看这些 文章 。
下面是一个视频演示,比较了不同设置下原始 TS-9 踏板和插件克隆:
(作者视频)
特别感谢 UAH(位于亨茨维尔的阿拉巴马大学)MLAMSK 高级设计团队,他们的研究和辛勤工作直接影响了本文呈现的结果。
我希望你喜欢这篇文章,感谢阅读!
使用 Python 后端
从零开始逐个任务地进行数据科学
用于 NLP 的 Python Flask 和 Vue.js
我正在写一个关于创建 NLP 应用程序来帮助人们改进简历的迷你系列文章。我在的第一篇文章中介绍了核心思想,在的最后一篇文章中,我展示了如何将标记应用于特定的关键词。在这篇文章中,我将向您展示如何连接 Python 后端,并为我在上一篇文章中使用的用户界面提供服务。我希望如果我能把这些任务分解成简短的帖子,我就能成功地解释我的过程。截至撰写本文时,我已经做了许多这样的应用,如 概念证明 。你准备好进入后端世界了吗?我们开始吧!
Python 后端
虽然有时我可能看起来是一个死忠的 Python 爱好者,但事实是 Python 只是我工具箱中的一个工具。我经常使用 Express with Node,这实际上涉及到安全性和各种外部服务的可用 SDK,如 Okta 。因为我只对 概念证明 感兴趣,所以我的生活没有那些不得不 **保证数据隐私、安全、性能和弹性的人复杂。**为什么我们选择 Python 作为后端语言归结起来,对于我来说,到 机器学习生态系统 。我从来不喜欢姜戈,但我知道它非常受欢迎。Flask 一直是我的首选,我从未遇到过性能问题。自然,你需要用 Nginx 和 Gunicorn 之类的用 Supervisor 来部署。
照片由 Hitesh Choudhary 在 Unsplash 上拍摄
用 Python 挂接一个单页面前端 UI 有几个步骤。首先,我们需要 Python 后端作业,然后我们需要对 Vue.js 应用程序进行一些更改。好了,我们编码吧!我现在用的是视觉代码!
瓶
让我们讨论一下 Flask 服务器端的工作
我的开发方法一直是极度敏捷的过程。我的重点是在每次迭代中运行软件。一次迭代可以是几分钟,也可以是几小时,但一般来说,有一个大约 3 小时的 时间框。 虽然可能不明显,我的 专业更侧重于的产品管理,而我更喜欢把专业人员留给真正的产品开发。
web.py 文件中的第 1 行到第 3 行处理库的导入。请注意,我们已经将 Gensim 纳入范围。第 5 行是这个脚本中最重要的一行。 Flask 期望一个静态文件夹 ,但是 Vue 和 NPM 构建时设置了一个 Dist 文件夹。 我们需要把这两个人撮合起来。
第 13 行为主页创建了一个路由,在这个早期阶段,它只为 index.HTML 服务,是从 NPM 的 build 命令生成的。第 19 行运行应用程序, 但是请不要在面向 web 的上下文中这样做! 留意图 1 所示的警示井。
图 1:带有警告可视代码中的终端视图。从未在生产中使用过
既然开发 web 服务器已经启动并运行,让我们把注意力转向调整 Vue 前端接口。
某视频剪辑软件
如果你只是在中场休息时才收看比赛,你可以通过阅读前一篇文章来赶上比赛,那会告诉你我们是如何来到这里的!如果你允许类比团队 数据科学原型 在这个区间都涨了 2!
康斯坦丁·希莫年科在 Unsplash 上拍摄的照片
回顾是敏捷的一个重要组成部分,它是一个很有意义的仪式!一般我们都是坐着而不是站着!你记得吗?我告诉过你 Flask 需要一个静态文件夹,但是 NPM build 设置了一个 Dist 文件夹。我们需要将这两者结合起来,我们通过为 Vue 引入一个配置文件来做到这一点。
第 2 行 vue.config.js 定义了构建输出文件夹。第 5 行创建了 Flask 需要的静态文件夹。这是一个关键的步骤,如果忽略,我们将给出 404 错误。
现在你需要记住,我们正在处理两种不同的技术。
- Python 是运行时解释的。
- NPM 需要使用 transpilers、webpack 和 voodoo 来构建,这很无聊,但很有必要。网络浏览器的兼容性比永恒恶臭的沼泽还要糟糕。
所以底线是
- Git 添加。(展示变化)
- Git commit -m(在变更对象中包装变更)
- Git push(更新对 repo 的更改)
- NPM 跑搭( 跑巫毒和闻泥塘 )
- Python backend.py ( 执行服务端 )
必须是你的过程,当然也是我的过程。所以现在我们准备好执行连接的流程。
运行它
对于这一部分,剩下的工作就是运行 Python 脚本。我已经完成了构建并检查了输出。图 2 显示了结果。
图 2:导航到端口 5006,我们得到显示的应用程序。图片作者。
除了我们在端口 5006 而不是图 3 所示的 Vue 开发服务器的 8080 端口之外,真的没有什么新的东西可看。
图 3: npm run serve 在端口 8080 上创建一个服务。图片由作者提供。
但是,我现在已经向您展示了如何创建前端应用程序和后端服务器端作业。Gensim 已经包括在内,我有自己的 NLP 代码从最初的职位。在下一篇文章中,我们将继续这一旅程。
- 给前端添加一个更好的用户界面。
- 添加一些前端 API 调用来处理简历和职位描述。
- 添加一些服务器端 API 端点。
现在我们开始有趣的事情。如果你在问自己这与数据科学有什么关系,你应该接受用 Python 构建 NLP 模型是不够的。你需要一个用户界面,你需要资金,你需要说服其他人投资他们的现金和他们的家庭时间在你的项目上。最后,如果您是项目经理、产品经理或产品所有者,您需要构建 backlog 并交付项目。您需要了解将 NLP 解决方案带给消费者的所有步骤。与其说这是科学,不如说这是编码、营销、设计、隐私、安全和大量艰苦工作的现实生活。
回来获取下一期,我会添加那些新特性!同时,如果你对开发过程感兴趣,想看我演示如何从零开始制作产品的视频,你可能会喜欢我的 YouTube 系列。构建 web 服务、API 调用、用户界面都有详细的讨论。**
在神经网络中使用激活函数
机器学习|神经网络|激活函数|
常见的激活函数及其使用
激活函数是将输入信号转换成输出信号的神经元的内部状态。
基本上,神经元计算其输入的加权和,加上偏差,然后将值输入到激活函数,该函数决定它是否应该吐出输出。激活函数为神经网络提供非线性属性。如果没有激活函数,神经元的输出值可以在(-无穷大)到(+无穷大)之间变化。
我们都知道特性缩放以及为什么要这样做。特征缩放是在数据预处理期间执行的,并且是为了归一化/标准化独立特征。在标准化过程中,我们在 0 到 1 的范围内重新调整特征值。激活函数也在做类似的事情。它将输出值带到特定的范围。
在这里阅读更多关于特征缩放的内容:https://becoming human . ai/feature-scaling-in-machine-learning-20 DD 93 bb 1 BCB
让我们用一个小例子来理解激活函数。
一群 4 个朋友决定去度假。他们已将选择范围缩小到三个国家。泰国、牙买加和迪拜。为了选择最终的目的地,他们每个人都决定在-10 到 10 的范围内为这些国家投票。-10 表示最不感兴趣,10 表示最感兴趣。0 可以认为是中性的。
从下表中,你可以注意到,例如,Bkon 对泰国最感兴趣,对访问牙买加最不感兴趣。
作者创建的虚构数据
让我们给每个变量分配初始随机权重。为了简化计算,我们将保持偏差值= 0.01 或简单地为 0。
观察下图:神经元计算其输入的加权和,并提供输出值。这里的神经元在没有激活功能的情况下将为泰国、牙买加和迪拜各提供 1 个值。即泰国= -2,牙买加= 5,迪拜= 8。由于这不是一个回归问题,这些值将很难解释。
作者创建的图像
不同的激活功能及其输出:
阶跃函数 —该激活函数可用于二元分类。它产生二进制输出 0 或 1。任何低于 0 的值都自动被赋予值 0,任何高于 0 的值都被赋予值 1。
Sigmoid/逻辑函数 —该激活函数可用于二元和多标签分类,我们将输出预测为概率。这个团队去迪拜的可能性有多大?该函数将任何实数值作为输入,并输出 0 到 1 范围内的值。输入越正,输出值就越接近 1,反之,如果输入越负,输出就越接近 0。
Softmax 函数 —当我们将输出预测为概率并希望得到明确答案时,该激活函数可用于多类分类。在 softmax 中,所有概率相加为 1,选择概率最高的类。在我们的例子中,迪拜将是明显的赢家。
在 Sigmoid 函数中,输出的概率值加起来不是 1,而在 Softmax 函数中,概率加起来是 1,因此给出了最终的赢家。
双曲正切函数 —该激活函数类似于 sigmoid 函数。然而,如果两个事件略有不同,它们都将被赋予高概率。该函数将任何实数值作为输入,并输出-1 到 1 范围内的值。输入越正,输出值就越接近 1,反之,如果输入越负,输出就越接近-1。这主要用于递归神经网络(RNNs)。
ReLU 函数 —该激活函数主要用于多层感知器(MLPs)和卷积神经网络(CNN)。任何低于 0 的输入值都被赋予 0 值,任何高于 0 的值都是值本身。因此,它的范围可以从 0 到无穷大。
当不确定为你的神经网络使用哪种激活函数时,最好尝试几种并比较结果。
感谢您的阅读。如果您有更多问题,请通过链接联系我们
使用人工智能生成复杂的和声
在巴赫合唱数据集上训练
范二·阿夫沙里在 Unsplash 上的照片
照片由 Lorenzo Spoleti 在 Unsplash 上拍摄
创造性内容是计算机复制的最复杂的东西:非常低的损失将意味着网络的输出不是原创的,而非常高的损失将意味着网络的输出与源材料没有任何相似之处。因此,需要大量的超参数调整来获得有效的结果。
概念:
巴赫合唱数据集是一个广泛的数据集,包含了巴赫合唱的 381 个音符值。每首赞美诗都被分解成一个 CSV 文件,有 4 列。每列包含合唱中 4 种声部(女高音、女低音、男高音和男低音)的音符值。
你可以在这里找到数据集。
我的目标是将这些数据转换成空间数据,使网络能够链接过去的笔记,为下一个笔记做出决定。我最初的印象是将文件转换成图像,因为图像适用于许多不同类型的网络。
网络将得到损坏的数据(具有丢失信息的数据),并试图填补空白。
数据收集:
该脚本导入运行程序所需的所有库。Numpy 用于矩阵操作,PIL 用于图像,pickle 用于在本地文件中存储列表值,以便将来节省时间。Array2img 是一个特殊的函数,用于将巴赫合唱团数组转换为图像。它采用空白图像(全黑),如果有注释,则添加白色像素。
这个脚本查看一个目录中的所有文件。使用 os.chdir()移动到存储所有数据的目录。这些值被拆分成 106 乘 106 的数组。这是因为 midi 文件中的音符范围是 106,正方形图像比矩形图像更容易处理。这是因为在卷积网络中更容易根据内核大小来处理。这些数据将被保存起来以备将来使用。
这个脚本将 csv 文件转换成一个数组,然后该数组可以转换成一个图像。再加上另一个将图像文件转换成 midi 文件的脚本,这应该可以完美地工作了,对吗?
问题 1:转型
我对将创建的图像转换为 img2midi 函数的输入感到非常困惑。
最终,经过几个小时的测试,我发现将图像逆时针旋转 90 度可以得到最好的结果。
这是一个巴赫合唱曲的形象例子:
由作者创建
问题 2:音高
即使在完成项目后,我也不确定是什么导致了这个问题。函数输出的音符都是错的。当打印计算机使用的值时,它与 csv 文件中的值不匹配。
我不得不重新编写 img2midi 脚本,以便可以将 csv 中的值直接输入到函数中。
这个脚本的原始代码不是我的。这里可以找到。
我将 csv 中的注释直接输入到图像中。笔记是一个名为“notesy”的列表。
通过直接输入值而不是使用图像,它防止了错误音高的发生。
使用另一个 midi2img,我将 midi 转换回图像,然后比较这两个图像。
我观察到了不同之处,并对 array2img 代码做了一些调整。
在经历了许多图像和 midi 文件的困难之后,我决定只使用 midi 音符本身作为网络的输入和输出。从长远来看,这是可行的,因为图像包含大量冗余值。4 声道输入也将导致网络输出一个 4 部分的和声,这正是我在寻找的。
数据综合:
随机损坏:
想到的第一个想法是随机移除某些音符。这个 scr
损坏系数用于计算将从合唱中随机移除的值的数量。这是用合唱中的音符数乘以系数计算出来的。
经过一点点测试后,这种方法的效果并不太好,因为数据集中定义的时间步长非常短,所以脚本只是将笔记分成更多的片段。这对于模型来说太容易外推,因此是无用的数据。
以下是该算法生成的数据示例:
作者创建的两个图像(左:原始,右:损坏)
逐块:
这个脚本使用不同的策略来实现这一点。它创建定义大小的块,并垂直清除合唱。这意味着合唱团的所有 4 个声部的音符在合唱团的一小段中被移除。
不是知道损坏纸币的确切数量,而是使用概率来确定图像损坏的程度。
左边的要点还提供了一个脚本来生成一个具有定义数量的数据点的数据集。
以下是该算法造成的损坏:
作者创建的两个图像(左:原始,右:损坏)
逐行:
此脚本删除了合唱中除低音线以外的所有声部。要保留的这条线可以用 line_n 变量来确定。因为 python 使用基于 0 的索引,所以 0 表示高音,3 表示低音。
以下是使用该算法生成的图像示例:
作者创建的两个图像(左:原始,右:损坏)
经过一些测试后,我认为定义数据的最佳方式是将其表示为大小为(106,4)的数组。每个声部将有 4 个通道,合唱部分将被分割成 106 个时间步长的片段。
模型
假设您已经在当前工作目录中保存了所有的 pickled 文件,左边的代码将准备所有基于块的数据。
它还有另外两个有趣的功能:
填写区块:
填充块接收网络的输出,并移除模型输出的所有重叠,以创建完整的模型输出。这可以通过原始输出获得更多信息。
数组 2 图像分析:
Array2img 分析允许将 array2img 与像素颜色一起转换。这样就很容易分辨出哪些笔记是电脑生成的。
这个基线模型只使用密集模型和 relu 激活函数。它只使用密集层的事实使得它很难学习更多的空间模式。虽然这通常会导致收敛速度变慢,但在这种情况下,几乎没有学习。
以下是结果示例:
作者的所有图片(左:已填充,中:真实,右:未过滤)
该模型类似于基线模型,但增加了漏失层。我认为基线模型产生的大多数平线是由于最佳预测是相同的 4 个音符。因此,这意味着漏失层将导致更大数量的变化,从而获得更好的结果。
辍学可以得到更多的控制,但这仅仅是一个概念的证明。
这是我最初打算使用的第一个包含一维卷积层的模型。
这是一个基本的卷积网络,有一些基本的超参数调整。kernel_size 经过了很好的优化:4 非常适合通道数,并且比其他值收敛得更快。
在研究最佳模型架构时,我发现 GANs 的想法是另一种有效的模型架构。
这个项目最理想的 GAN 是 Pix2Pix GAN。问题是这将需要很长时间来编码,我决定我不想在这个项目上花太多时间,并决定放弃这个想法。
然而,我设法创建了一个类似于 Pix2Pix GAN 中发生器的编码器-解码器设置。
编码器减小输入的维度,直到它具有相同图像的较小表示。然后,解码器将图像放大,填补这个过程中的漏洞。
此外,编码器-解码器模块之间存在跳跃连接,允许信息从不同的处理级别传递。
以下是结果示例:
作者的所有图片(左:已填充,中:真实,右:未过滤)
结论:
我认为这个项目基本上是成功的。然而,在这个项目中使用 Pix2Pix GAN 会非常有趣:
Pix2Pix GAN 将能够产生更多原创和有趣的结果,因为发电机损耗不仅仅是地面真实值和发电机输出之间的 MSE。从理论上讲,这将产生真正原创的结果。
我希望在不久的将来为这个项目使用 Pix2Pix GAN。
我的链接:
如果你想看更多我的内容,点击这个 链接 。
用 AI?你可能希望开始进行人权影响评估(HRIA)
公平和偏见
欧洲人工智能监管目标之争的教训
在最近的一篇文章中,我提供了一些关于拜登政府将如何改变人工智能领域的预测。主要的收获是,人工智能监管的到来比你想象的要快,你最好从实施内部人工智能治理开始准备。如果你在北美开展业务,这将有助于你超越监管机构和竞争对手。如果你在欧洲做生意,你需要遵守欧洲法律。
算法影响评估 (AIAs)和像人工智能注册这样的工具是开始记录你的人工智能的简单方法。然而,鉴于最近的发展,你可能需要在你的人工智能治理工具箱中添加另一个工具:人权影响评估(HRIA)。为什么?让我们看看欧洲围绕人工智能监管的激烈辩论,看看我们可以从中吸取什么教训。其中一些可能很快就会适用于我们,因为美国的方法与欧洲正在采取的方法有相似之处。
这两种方法都倾向于有选择的、有针对性的监管,关注特定的行业,而不是“一刀切”。两人都认为技术应用的目的、背景和范围很重要。例如,NIST 信息技术实验室主任 Elham Tabassi 说,高度争议的面部识别如果用于解锁汽车,可能不会有高风险。这真的取决于用例。
AI 监管:基于风险还是基于价值观?
欧洲委员会关于人工智能的白皮书引发了欧洲的辩论。该文件于 2020 年 2 月进入公众咨询,通常被理解为即将到来的欧洲人工智能立法提案的基础。(该提案有望在 Q1 2021 年提出)。这份文件得到了很多回应,包括来自 60 多个民间社会组织的一封高度批评的公开信 。
争论的核心是人工智能监管应该基于风险还是基于权利的问题,以及鉴于迄今为止记录的许多侵权行为,基于风险的方法是否足以保护人权。
委员会认为,基于风险的方法将确保监管干预是相称的、平衡的和有重点的。这种方法将保护公民和消费者,而不会给部署人工智能/人工智能的组织带来不必要的负担,也不会扼杀这一领域的创新。这种方法也将有助于立法者和监督机构关注最有可能发生危害的领域。(这可能会帮助他们更好地管理资源。)
上周,该委员会人工智能和数字产业主管 Lucilla Sioli 重申了该委员会的意图。她指出,委员会希望建立一个“繁荣的人工智能市场”。她在活动上发言“公正的人工智能转变:机会和威胁在哪里?”,由专门研究欧盟政策的独立泛欧媒体网络 EURACTIV 举办。
委员会的白皮书提出了两个标准来确定人工智能系统是否是高风险的:
1)如果它“被用于预计会发生[…]重大风险的部门[…],例如保健部门;运输;能源和部分公共部门。”
2)“此外,有关部门人工智能应用的使用方式可能会产生重大风险。”
委员会还指出,一些应用程序可能被认为是高风险的,即使它们不符合上述标准。例如,在招聘中使用人工智能是合格的,还有“远程生物识别和其他侵入性监控技术”。你可能会问,这种方法有什么问题?
(人工智能)法则的目的是什么?
第一个争论点是围绕人工智能/人工智能的法律的目的:它是建立标准,维持秩序,解决争端,保护自由和权利,还是促进人工智能的吸收“同时解决与这种新技术的某些使用相关的风险”?委员会的白皮书指出,它有两个目标——委员会“致力于实现科学突破,保持欧盟的技术领先地位,并确保新技术为所有欧洲人服务——改善他们的生活,同时尊重他们的权利。”
作为回应,Access Now 写道“任何技术的采用,尤其是在公共部门,都不应该是一个独立的目标,它本身没有价值”。 Access Now 是一家专注于捍卫数字权利的非营利组织,也是上述公开信的签名者之一。在接下来的文章中,Access Now 写道,“人工智能并不是所有情况下的正确解决方案,也不应被视为灵丹妙药”。
这也是我向 InfoTech 的许多客户提供的建议:并非所有的商业挑战都可以或应该用人工智能来解决。人工智能只是你商业工具包中的一个工具,它不应该取代其他方法(包括一些低技术含量的方法)。
Access Now 表示,欧洲监管机构和立法者不应该强调人工智能的采用,而是应该“通过降低风险来确保技术值得信赖”。[……]欧盟应该通过将保护基本权利置于对人工智能全球竞争力的担忧之前,赢得人们对其人工智能举措的信任。首要目标应该是避免对个人和社会的伤害,而不是减轻伤害。”(同上)
这就引出了下一个争论点。
人工智能监管应该是被动的还是主动的?
除了现有的立法,该委员会还概述了几项要求,希望为高风险的人工智能应用开发这些要求。(这些要求可以作为标准进一步充实。)它们的范围包括确保 AI/ML 系统中使用的训练数据符合欧盟安全规则,披露系统的能力和限制,以及通过人类监督保护人类自主权。
该提案的批评者说,所有这些都是好的,非常需要,但还不够。基于风险的方法会给解释和公司法律操作留下太多空间。与此同时,自动化决策系统已经在伤害人民、社区和环境,而且它们也在侵犯基本人权。然而,这些权利是不可谈判的,无论与外部因素相关的风险水平如何,它们都必须得到尊重。 (原强调)
上面的公开信敦促委员会建立“明确的监管红线,以防止侵犯基本权利的人工智能的使用”。信中指出“即将出台的监管提案在法律中明确限制人工智能的合法使用,这一点至关重要”(原文强调)。换句话说,某些人工智能用例应该被完全禁止,或者因为与民主社会不相容而受到法律限制。具体来说:
生物特征监控
预测性警务
刑事司法中的人工智能,例如风险评估工具
移民和边境管制
人工智能用于社会评分和决定获得社会权利和福利(如福利、教育和就业)的系统。
公开信还呼吁委员会“明确处理”人工智能的使用:
加剧现有的结构性歧视;
限制获得医疗保健、社会保障和其他基本服务;
允许监视工人并侵犯他们的权利;
促进对公众舆论和人类行为的大规模操纵(例如,“轻推”、深度造假)以及“对人类尊严、机构和集体民主的相关威胁。”
图片:联合国大会,维基百科
人权快速复习
根据联合国人权事务高级专员办公室的说法,“人权是我们作为人类而拥有的权利——它们不是任何国家赋予的。这些普世权利是我们所有人固有的权利,不分国籍、性别、民族或种族、肤色、宗教、语言或任何其他身份。这些权利从最基本的权利——生命权——到使生命值得活下去的权利,如食物权、教育权、工作权、健康权和自由权。”换言之,人权是普遍的、不可剥夺的、不可分割的和相互依存的:
普遍性:它们适用于每一个人;我们都平等地享有我们的所有人权。
不可剥夺的:任何人都不能剥夺个人的人权,“除非在特定情况下并根据正当程序”——例如,“如果一个人被法院判定有罪”。
不可分割和相互依存:所有人权地位平等;“一套权利离开另一套就无法充分享受”;侵犯一项权利可能会对其他权利产生负面影响。
人权被编入 1948 年联合国大会一致通过的《世界人权宣言》( UDHR ),以及随后的文件中,这些文件共同构成了《国际人权法案》。
人权和 AI 有什么关系?
如果你没有关注关于人工智能和自动决策系统造成的许多滥用和伤害的新闻,这封公开信和 Access Now 的两篇文章(上文引用)是一个很好的起点。
或者你可以看看大赦国际2019 年的报告《监控巨头:谷歌和脸书的商业模式如何威胁人权》。这份报告简明扼要地解释了谷歌和脸书无孔不入的监控机器是如何侵犯核心人权的,比如尊严权、自主权和隐私权;控制自己信息的权利;以及拥有自由表达自我的空间的权利。
如果你想长时间阅读,我推荐以下几本书:
凯茜·奥尼尔的《摧毁数学的武器》
弗吉尼亚·尤班克斯的《自动化不平等》
卡罗琳·克里亚多·佩雷斯的《隐形女人》
詹妮弗·埃伯哈特的《偏见》
弗兰克·帕斯奎尔的《黑箱社会》
《监视资本主义的时代》作者肖莎娜·祖博夫
还有很多视频。一个是凯特·克劳福德的 NIPS 2017 主题演讲“偏见的麻烦”。另一个是 YouTube 上这个搞笑的 3 分钟喜剧小品“苏格兰语音识别电梯——11 点!”,这说明了有偏见的语音识别系统是如何惩罚甚至是母语人士的。
图片:Getty
人工智能技术并不是第一个引发伦理担忧的技术
我想重温一下 Access 的断言“我们的权利是不可谈判的,无论风险有多大,都必须得到尊重”。除了人工智能的军事应用(这是一个值得拥有自己空间的话题),我们需要确保我们正在建设造福全人类的系统。这个目标需要小心地处理一些技术和用例,甚至可能禁止它们。例如,克隆人类在 70 个国家被禁止,理由很充分。尽管如此,克隆其他物种是允许的——包括宠物和家畜的商业克隆。克隆濒危物种实际上可能会确保它们的生存。
我们可能还需要为人工智能时代增加新的人权,例如:
知情权:了解个人数据的使用方式、技术的发展方式及其对个人、社区、社会和环境的影响;
选择退出的权利:可以选择使用低技术途径(在可能的情况下)或与人类互动,但仍然能够有意义地参与经济和社会;
与自动决策系统打交道时的补救权;
数据代理权;
· …
这些问题对您的组织意味着什么?
立即获取组织认为“希望开发或部署人工智能系统的实体[应该]承担举证责任,通过强制性人权影响评估证明其没有侵犯人权(HRIA)。这一要求将适用于所有领域的所有应用,作为更广泛的尽职调查框架的一部分,它应适用于公共和私营部门。”
监管机构是否同意这一提议仍有待观察。无论如何,我支持 Access Now 和签署公开信的 60 个组织——人权影响评估是构建道德、安全和负责任的人工智能的基础。此外,根据您业务的性质和您经营的地区,您可能已经在进行这样的评估。将它们扩展到你的 AI/ML 项目应该是很自然的下一步。
不知道如何开始使用人权影响评估?—参考丹麦人权研究所的这份优秀指南。这里是雀巢公司评估其商业活动中人权影响的经验。
人权影响评估将帮助你让你的人工智能和你的组织免受牢狱之灾(转述詹姆斯·泰勒在预测分析世界 2020 大会上的专家小组)。所以你晚上可能会睡得更好。他们还将帮助您的组织建立竞争优势,促进信任,这是企业和社会的基础。
在 F#中使用 ActiveX 控件
F#和 COM
我想在我的 F#中添加一个对遗留 ActiveX 控件的引用。NET Framework)项目。问题是,当它添加引用时,它是以一种非常基本且无益的方式添加的。我在 StackOverflow 上发帖,看看是否有人有解决方案,但建议的东西都不起作用:
https://stackoverflow.com/questions/67933379/how-to-access-com-variant-properties-with-f
最后,我自己解决了这个问题,这篇文章是关于我是如何解决的。花了不少功夫,但是键用的是 Visual Studio 2017(完全支持 F#。NET Framework)并利用 C#作为临时过渡。我写这篇文章是为了防止其他人发现自己处于同样的情况,并想知道如何解决它。对我来说也是个参考:)
F#控制台应用程序
创建一个 F#控制台应用程序。NET Framework)在 Visual Studio 2017:
F#控制台应用程序(。NET 框架)
添加一个 C#类库(。NET Framework)添加到解决方案中,并将其命名为 DummyLib :
C#类库(。NET 框架)
右键单击 DummyLib 的引用,并选择添加一个引用。然后选择一个 COM 引用。您应该会看到一个包含 ActiveX 控件的 COM 对象列表。为了演示起见,请选择微软的 ActiveMovie 控件(在现实世界中,您可以添加您想要的 ActiveX 控件):
添加对 Microsoft ActiveMovie 控件的引用
一旦你点击“确定”按钮,它将添加 COM 引用,并且它将被列在“引用”树下。如果您现在双击引用中的一个视图,这将打开对象浏览器窗口。展开互操作。AMovie 对象,您将看到 AMovie 名称空间。展开它,您会看到 ActiveMovieClass。如果选择,您将看到所有方法、属性和事件:
对象浏览器中的 ActiveMovieClass
如果您现在右键单击 DummyLib 项目并选择卸载该项目,那么您可以再次右键单击它并编辑它:
编辑 DummLib.csproj 文件
向下滚动到定义 COMReference 的 ItemGroup 元素,并将其复制到安全的地方:
COMReference 部分
现在需要卸载 AxLegacy 控制台应用程序,然后以同样的方式编辑 FSPROJ 文件。向下滚动到文件底部,将复制的部分插入到最后一条注释的正上方:
AxLegacy.fsproj 中插入的部分
右键单击两个项目文件并重新加载它们。我们快到了!
构建解决方案
如果你现在查看 AxLegacy 项目的 Obj 输出文件夹,你会看到 tlbimp 工具已经创建了引用 COM 库的Interop.AMovie.dll文件。我们需要确保将它复制到我们的输出文件夹中,我们确保这一点的方法是将其添加为后期构建步骤:
构建后副本
那一行写着:
xcopy /Y /F $(ProjectDir)obj\*.dll $(TargetDir)
这应该适用于以这种方式包含的任何 COM 对象。
现在可以安全地从解决方案中移除 DummyLib 了,请继续操作。
测试
为了查看我们是否可以正确地访问我们的 COM 对象,我们将在控制台应用程序中执行如下操作:
结论
在 Visual Studio 2019 中,做一些本应开箱即用的事情需要做很多工作!我希望当我们得到 Visual Studio 2022 时,它也能支持 F#。NET 框架应用程序。
资源
您可以从我的 GitHub 下载我在这里创建的示例应用程序:
https://github.com/ianormy/AXLegacy
2021 年用 iPad 做数据科学!
图片由装有 Juno 应用程序的 iPad 的作者拍摄
查看一些应用程序,以支持您在 iPad 上学习数据科学
一、爱情。我的 iPad。自从它在 2010 年推出以来,我不得不有一个。那时,我还是一个贫穷的大学生,所以我不得不省下一大笔钱来买我的第一个。我不后悔得到它,即使你真的不能做太多。
在我看来,iPad 无疑是最好的消费机器。无论是在网飞看你最喜欢的节目还是浏览网页,iPad 都是最好的个人大屏幕体验,而不是一台成熟的笔记本电脑。但不可否认的是,iPad 一直缺乏让它成为真正好的生产机器的东西。
随着时间的推移,苹果慢慢增加了越来越多的功能,使 iPad 越来越像一台生产机器。从增加键盘支持到允许用 Apple Pencil 进行非常好的图形设计体验,iPad 已经越来越接近真正的笔记本电脑替代品。事实上,在我 2018 年成为数据科学学生之前,有一段时间我完全抛弃了我的笔记本电脑,只使用 iPad。当然,我很快不得不在 2019 年初给自己买了一台新的笔记本电脑,因为很明显,我将需要它来进行数据科学。
但现在是 2021 年 1 月,苹果公司继续大步前进,让 iPad 更像一台生产机器。随着 iOS 14 突破性地支持在最新的 iPad 键盘上使用光标在触控板上烘焙,我现在很好奇 iPad 作为数据科学机器的可行性如何。在这篇文章的剩余部分,我们将看到我们如何在数据科学领域利用 iPad,并对这种体验的有用性做出最终判断。
事不宜迟,我们开始吧!
(哦,还有一件事……我 100%知道,如果你使用 AWS 或 GCP 这样的云服务,你肯定可以把 iPad 当作生产机器来使用,但这感觉像是作弊。这篇文章将涵盖 iPad 的硬件、软件和应用程序,以获得不依赖云计算的体验。)
硬件
作者拍摄的图像
我认为可以有把握地说,过去两年发布的任何 iPad 都有足够强的性能,可以与大多数普通笔记本电脑相媲美。我们将在我们的应用程序中进一步探讨这一点,但使用应用程序从 CSV 加载数据集并使用 Pandas 探索它们是一种非常爽快的体验。我个人是一名 16 英寸的 MacBook Pro,用于我作为机器学习工程师的日常工作,对于用 Python 工作,我要说我的 iPad Pro 和全 MacBook Pro 一样快。
但是我们不能忽视巨大的缺点:iPad 本身就是一个大触摸屏。使用虚拟键盘和使用手指作为光标是一种非常笨拙的体验。(更不用说虚拟键盘占用了一吨宝贵的屏幕空间。)iPad 增加对物理键盘的支持已经有一段时间了,这非常有帮助。2020 年夏天,苹果在 iOS 14 中正式添加了光标支持,以使用支持蓝牙的鼠标等。同样,这是将 iPad 用作生产机器的又一次巨大飞跃,但是这些额外的东西并不便宜。
如果你有一个普通的 iPad,并且没有兴趣购买这些额外的配件,那么你将很难在你的 iPad 上进行数据科学活动。可能吗?从技术上来说,是的,但是这种体验太糟糕了,我宁愿用低端笔记本电脑来工作。
软件
由 Medium、Pythonista 和 PIP 视频的作者拍摄的截图
尽管苹果在让 iOS 对生产客户更具吸引力方面取得了长足进步(甚至最近将 iPad 上的 iOS 重新命名为 iPadOS),但它仍然是 iOS 的核心。它最终限制了我在普通笔记本电脑上做的一些事情,不幸的是,我永远无法真正用 iPad 取代我的工作笔记本电脑。也就是说,我不能使用命令行和命令行工具、构建 Docker 映像等等。
但这并不意味着我们完全不知所措。我们仍然可以做很多很酷的事情,我们将在应用程序部分介绍,但停留在 iOS 的基础水平,有一些事情值得注意。首先是 iOS 文件系统。这与我们对传统笔记本电脑的预期完全不同,但至少苹果在短短几年前就加入了他们自己的变体。这很棒,因为许多应用程序现在可以在所有应用程序中使用相同的文件,就像你在传统计算机上使用任何文件一样。此外,苹果的 iCloud Drive 使您在所有苹果设备之间同步文件变得轻而易举。(当然,如果您处理的是非常大的文件,那么最后一个会有所增加。)而且我也有责任提一下并行应用的非常好的用户界面!
苹果做出的这些重大改进值得称赞,但归根结底,如果没有好的应用,这些改进没有多大意义。让我们探索一下截至 2021 年初,这些应用包括哪些内容。
应用程序
作者捕获的屏幕截图
整个 iOS 生态系统的面包和黄油在于它的应用程序商店,幸运的是,一些伟大的人已经推出了一些伟大的应用程序,以帮助整个代码开发和数据科学过程。我们甚至会谈到这些应用程序是如何协同工作的,甚至会谈到你在 GitHub 上的工作,但我必须做到 100%透明:这不是一个简单的过程。你最终会像我一样习惯它,但它肯定不会像使用传统电脑那样无缝。
让我们进入我发现对数据科学有很大价值的应用程序。
iOS 版 Juno
《iOS 版朱诺》作者截图
(价格:$14.99,App Store 链接 )
不用说,使用 Jupyter 进行探索性数据分析和数据可视化是一项巨大的资产,而 Juno 带来的正是这一点。Juno 是一个允许你运行 Jupyter 笔记本界面的应用程序,它可以与 Python 内核甚至一些包如 Pandas 和 Scikit-Learn 一起工作。如前所述,Juno 等应用程序现在可以直接与 iOS 文件系统交互,因此您可以轻松地从 Kaggle 等网站下载数据集,并直接在 Juno 中使用它。不错!
不幸的是,Juno 并非没有缺点。它建立在 iOS 之上,不能运行传统的 shell 命令。此外,虽然您可以从 PyPi 安装一些额外的包,但它们必须完全用 Python 编写。如果它们不是纯用 Python 编写的,那么它们就不能下载到 Juno。(例如,对于模型透明度,我可以下载石灰,但不能下载 SHAP。去想想。)Juno 在导航文件系统时也可能有点笨拙,但最终,我认为 Juno 是一个令人惊叹的应用程序,并期待着看到它如何随着时间的推移继续发展。
腐霉 3 号
Pythonista 3 作者截图
(价格:$9.99,App Store)链接
在 Jupyter 中工作是很棒的,但是当涉及到形式化你的训练和推理代码时,我们真的需要走出 Jupyter 的世界。幸运的是,Pythonista 是一个优秀的基于 Python 的 iPad IDE,它正好满足了我们的要求。像 Juno 一样,它也可以与 iOS 文件系统无缝同步,这样您就可以在同一个地方使用 Juno 的 Jupyter 笔记本和 Python 的 Python 脚本。Pythonista 还提供了一些非常酷的例子,展示了您可以在应用程序中实际完成的事情,因此,请查看这些例子,了解一些您可以在下一次数据科学工作中考虑的巧妙想法。
工作副本
工作副本的作者捕获的屏幕截图
(价格:基本功能免费,高级功能 19.99 美元,App Store 中的 链接)
还记得我说过你可以把你的作品存回 GitHub 吗?这就是这个应用程序的全部内容。就像 Juno 和 Pythonista 一样,工作副本可以直接进入 iOS 文件系统,以创建可以同步回 GitHub 的 Git repo。(或者 Filelocker 或者 GitLab 或者更多!)这是一个简单的应用程序,但对于在 iPad 上工作来说,它是一个超级好的补充。在这三个应用程序和 iOS 文件系统之间,你现在可以在 iPad 上的一个地方共同工作,这个地方可以很容易地同步到源代码库中。不错!!
当然,我不得不提到一个小缺点:用户界面。你可以说我疯了,但实际上我喜欢使用命令行,由于 iPad 对 iOS 的依赖,这显然是不存在的。工作副本确实有一个 UI 来执行这些传统的 Git 命令,但是…它可能需要一些工作。好消息是,核心功能已经存在,所以如果这款应用的开发者能够真正优化他们的用户界面,我认为这款应用可能会比现在更加出色。但不管 UI 如何,它仍然足够好,我仍然在自己的工作中使用它。
荣誉奖
上面提到的三个应用程序是在 iPad 上执行数据科学的“必备”,但我认为还有其他应用程序可能值得一试。我确信我可能遗漏了一些你想添加到这个列表中的内容,所以请在评论中说出你想在这里看到的内容。
【text astic(价格:9.99 美元) : Textastic 是 App Store 上最受欢迎的编码应用,因为它在语法高亮显示方面做得非常好,并且适用于许多不同的语言。但是因为我大部分时间都在使用 Python,所以我不太需要在 Juno 或 Pythonista 上使用这个应用程序。不过,把它放在诸如 markdown 文件编辑之类的地方还是不错的。
【GitHub(价格:免费) :这款应用最近才问世,支持流行的源代码库。我喜欢用 GitHub 展示我所有的个人作品,但 iPad 应用程序在我的书中并不是“必须的”。我个人不在 GitHub 上进行任何多人协作,但它在这些场景中确实显得更有用。因为它是免费的,为什么不下载呢?
【Carnets Jupyter(价格:免费) :这是我在 Jupyter 笔记本中用于交互的应用程序,但后来我换成了 Juno,老实说我不记得为什么了。它一点也不差,当然,它是免费的,没人能否认。
你能抛弃你的传统笔记本电脑吗?
因此,我们终于来到了我们一直在等待的问题,那就是,我们最终可以单独使用 iPad 进行数据科学工作吗?不幸的是,答案最终是否定的。因为 iOS 不是传统的操作系统,由于我依赖命令行工具、Docker 映像等等,所以有很多事情我做不了。我很有兴趣看看苹果是否能够克服这些障碍,但不幸的是,它们在 2021 年 1 月仍然存在。
但这并不意味着数据科学在 iPad 上完全死亡。我发现,如果有合适的硬件(例如,物理键盘和鼠标/触控板),iPad 是一个令人惊叹的学习和概念验证工具。如果你正在编写一些基本的代码,想要做一些简单的探索性数据分析,或者测试你刚刚学到的一些新技能,iPad 最终能够胜任所有这些事情。在一天结束的时候,我肯定不会扔掉我的笔记本电脑,但很高兴知道如果我真的想的话,我可以用我的 iPad 度过难关。
使用 Apache Airflow DockerOperator 和 Docker Compose
围绕[DockerOperator](https://airflow.apache.org/docs/apache-airflow-providers-docker/stable/_api/airflow/providers/docker/operators/docker/index.html)
的互联网上的大多数教程都很棒,但是它们有一个缺失的环节,我今天想在这里介绍一下,它们都没有假设你正在用 Docker Compose 运行 Apache Airflow。
这里的所有代码和进一步的说明都在 repofclesio/air flow-docker-operator-with-compose中。
游戏攻略
a)首先,使用 webservice 创建一个容器,并创建airflow
用户,如官方文档中所述:
结果应该大致类似于下图:
b)完成初始设置后,通过docker-compose
启动网络服务和其他组件:
当您运行下面的语句时,您可以使用docker container ps
来检查 docker 容器。结果应该大致如下所示:
c)所有容器都已启动并运行,让我们使用airflow
作为登录和密码进入气流 UI:
d)在 Airflow UI 中,您会发现一个与 Docker 操作符相关的 DAG:
e)取消暂停 DAG:
f)单击 DAG 并进入图形模式:
您将看到正在执行的两个任务。这是下面的 DAG 代码:
如我们所见,我们正在执行一条sleep
语句和另一条带有echo
语句的语句。[N1]
在执行过程中,这将是docker container ps
语句的结果:
在这幅图中,我们可以看到每个任务都有自己的容器。我使用任务中的container_name
属性来命名这些任务。我强烈建议你总是在每个任务的容器中输入名字,因为如果你有一些容器在做一些意想不到的事情(例如无限循环,花费很长时间等等),调试一些未命名的容器将会非常困难。
g)我在 DAG 中做了一个小的改动,我加入了两个echo
语句来显示这些信息将如何返回到气流日志中。只需将以下代码复制并粘贴到您的 DAG 中:
我们将向负责该任务的每个容器发送两条echo
语句。一个带有hello
,另一个带有world
:
h)刷新并触发 DAG:
I)使用图形视图检查 DAG 中的执行情况:
在我的机器上执行相当快,但是我们可以通过查看日志来检查每个任务的结果。
如果我们点击docker_command_hello
任务并选择logs
选项,我们将看到command
的输出
我们在docker_command_world
任务中也会得到相同的结果:
j)在实验结束时,运行docker-compose down
并停止所有容器。
一些实际的用法
- 独立于语言的任务编排(例如,我目前正在一个完全用 Ruby 编写的数据管道中工作);
- 提交第三方平台的作业(例如 AWS Sage Maker、Spark jobs、Databricks、Azure 等);
- 在隔离环境中运行 dbt 模型;
- ETL/ELT 任务的容器化;
- 用 soda.sql 进行一些 ETL/ELT 测试;
- 包括一个额外的步骤数据剖析、验证和测试,并对其寄予厚望,没有环境问题。
使用的小技巧
- 正如 Marc Lamberti 所描述的如果您的 docker 映像不是在相同的本地环境中构建的(例如在 worker 中),这意味着它需要被下载,这将增加 SLA
- docker 容器用户(在这个例子中是用户
[airflow](https://github.com/fclesio/airflow-docker-operator-with-compose/blob/main/dags/docker_job/Dockerfile)
) 需要在 docker 守护进程中有权限(一个简单的chmod
给气流用户权限就可以解决[N2】); - 一个单独的
[dockerfile](https://github.com/fclesio/airflow-docker-operator-with-compose/blob/main/dags/docker_job/Dockerfile)
可以被转换成一个图像,供每个 DAG 使用。有一个" god docker image "包含所有的依赖项和包,可以运行 ELT 管道中的所有任务,这很有吸引力。请不要这样做。图像会变得不必要的臃肿,构建会花费很长时间(这将反映在 SLA 中); - 由于 DockerOperator 实现中的一个问题,选项
[AIRFLOW__CORE__ENABLE__XCOM_PICKLING](https://github.com/fclesio/airflow-docker-operator-with-compose/blob/11e67d9248d0639c9786313643190028b27659f0/docker-compose.yaml#L54)
应该设置为[true](https://github.com/fclesio/airflow-docker-operator-with-compose/blob/11e67d9248d0639c9786313643190028b27659f0/docker-compose.yaml#L54)
; - 我们需要将运行 docker 守护进程的主机的 URL 链接作为一个卷传递给以允许 web 服务器容器启动 Docker 映像;
- 不要忘记在
[DockerOperator](https://github.com/fclesio/airflow-docker-operator-with-compose/blob/11e67d9248d0639c9786313643190028b27659f0/dags/docker_job/docker-job.py#L36)
中建立[container_name](https://github.com/fclesio/airflow-docker-operator-with-compose/blob/11e67d9248d0639c9786313643190028b27659f0/dags/docker_job/docker-job.py#L36)
属性。这一点非常重要,因为如果您忘记建立不同的名称,您可能会遇到容器名称冲突,DAG 将会失败(长话短说:出于某种原因,我发现 Airflow 正在尝试重新连接一些上游启动的容器;而这引起了一些冲突); - 默认情况下,
[image](https://github.com/fclesio/airflow-docker-operator-with-compose/blob/11e67d9248d0639c9786313643190028b27659f0/dags/docker_job/docker-job.py#L35)
属性将总是拍摄最新的图像。根据经验,我强烈建议使用最近的Dockerfile
构建所有图像。如果您希望 100%确保作业将始终使用(事实)最新的映像,请考虑为您的映像包含一个以前的构建任务。类似docker build -f path/to/Dockerfile -t yourname/image_name .
的东西。 - 据我查看 Docker 实现的源代码,Airflow 在 Docker 套接字中使用了一种绑定安装来启动容器。我不是 100%确定,但这意味着气流没有做对接可能会导致其他一些过多的问题。
结束语
我个人认为 Airflow + Docker 是一个很好的组合,可以为 ELT/ETL 任务提供灵活、可扩展和无麻烦的环境。不幸的是,在互联网上,大多数使用 Docker Compose 的 Airflow 实现都没有考虑到使用 DockerOperator 作为灵活的任务编排环境的可行替代方案。
就 ELT/ETL 架构而言,这种使用 Docker Compose + DockerOperator 的气流组合认为是一个很好的替代方案,与以下相比:(I)由于我们不需要处理工作人员供应,(ii)由于其固有的复杂性,(iii)使用 Docker Swarm 管理这些任务,但其在供应和故障恢复能力方面存在局限性。
参考
有用的链接,我在这个过程中使用的重要性排序。
- 对接器中的运行气流
- 我已经在 Docker 中运行 Airflow,如何在 Airflow 中使用 DockerOperator?
- 在您的 CI 或测试环境中使用 Docker-in-Docker?三思而后行。
- 如何在 Apache Airflow 中使用 docker operator
- 如何使用气流而不头疼
- 码头工人灭霸(小心使用)
- DockerOperator 无法将 XCom 值序列化到 JSON 中
- 从 docker 内部运行 docker 可以吗?
- 停靠栏中的 chmod 无法正常工作
- air flow docker operator:connect sock . connect(self . UNIX _ socket)file not found error:[Errno 2]没有这样的文件或目录
- 如何使用正确的组将 docker 插座作为卷安装到 docker 容器中
- 关于通过 Apache Airflow 在 Python 子进程中运行 docker 命令的权限问题
- 如何在 Docker 容器中运行 Docker
笔记
[N1] —我在任务名称和命令语句中犯了一点小错误。
【N2】—在 Reddit 的这个帖子中,一个用户通过chmod 777 /var/run/docker.sock
为主机 Docker 守护进程中的权限做了一个激进的解决方案。我个人不推荐。
使用人工智能来预测野火的蔓延,用 Python
Benjamin Lizardo 在 Unsplash 上的照片
这是一个关于如何使用数据分析和机器学习来预测野火蔓延的分步指南
在过去的几天里,可怕的野火已经蔓延到撒丁岛、意大利和全世界。图像和视频令人心碎。当夏季开始时,这些事件往往会更频繁地出现,最终结果是灾难性的。
我决定学习人工智能(AI)的原因之一是能够直接帮助人们和解决现实世界问题的想法。我想这是其中之一。
在这篇文章中,我将指导你一步一步地使用人工智能来预测野火的蔓延。
让我们开始吧。
1图书馆:
您要做的第一件事是导入 Python 库。使用了很多不同的工具, Pycaret 用于开发机器学习部分, Pandas 和 Numpy 用于数据分析, geopy 用于获取距离等信息…
注意:这是一个通用的设置,我为这个笔记本做了一点改动。如果有什么东西在代码部分不会用到,我很抱歉。另外,我使用 plt.rcParams 来设置我最喜欢的绘图参数。你可以放心地跳过这一步。
2数据集
这是我用来下载数据集的源。这是一个加州野火的集合。让我们来看看。
可以看出,纬度和经度列不太可靠(例如 Ventura 是(0,0))。我们将在这方面努力。然后我们有了市 ( 县列)和野火发生的日期,即**开始。**名为 AcresBurned 的一栏是被野火烧毁的英亩数。
3数据可视化
让我们使用 geopy 通过使用县列来定位城市。让我们修复一些错误(例如,圣克鲁斯位于墨西哥,因此我们必须将其从数据集中删除)并绘制结果:
这是数据集的世界地图:
对于我们的分析,我们想要预测最终野火的城市在数据集中出现一定次数是很重要的。我们来策划一下吧!
随着洛杉矶出现足够高的次数,这个城市将被使用和研究。
我们需要的另一条信息是城市之间的距离。
让我们用这段代码得到它们,并绘制热图。
最后一步是绘制数据集的 4 个城市野火直方图:
4数据预处理
好了,现在我们对数据有了一个大致的概念,我们必须很好地定义我们需要什么。
我们想回答这些问题:
“鉴于野火 X 发生在名为 Z 的城市的第 Y 天,从这里到 3 天,洛杉矶市会发生野火吗?3 天到 7 天会有野火吗?7 天到 10 天会不会有野火?”
为了做到这一点,我们希望有一个包含如下行的数据集:
A .野火发生的日期
B .野火的距离
C .野火烧毁的英亩数
D .这场野火与洛杉矶另一场野火之间的天数
特别是,d .列必须包含以下 4 个类中的一个:
D.1 一到三天
D.2 三到七天
D.3 七到十天
D.4 十多天(这意味着没有相关的野火)
这种数据集是通过使用以下代码行获得的:
- 划分 4 个等级
2。将它们全部归入单个数据集
3。创建最终数据集
为分类准备的数据集如下:
5机器学习
你可能听说过,很多时候,机器学习部分是最快的一个。尤其是在 2k21 中用 **PyCaret 这样的工具。**已经测试了各种各样的机器学习模型。最好的一个在测试集上给了我们 87+%的准确率。
这是混淆矩阵,向我们展示了非常好的结果。
最终考虑
我们谈论的是人的生命,所以我们不能给虚假的希望。这篇文章只是野火预测挑战中一条看似有希望的道路的一个例子。必须使用大量研究和资源来验证这种方法。此外,各种不同的方法(例如,检查温度、湿度等)可以用来预测野火,当我写这篇文章时,研究人员正在开发新的方法。
如果你喜欢这篇文章,你想知道更多关于机器学习的知识,或者你只是想问我一些你可以问的问题:
A.在 Linkedin 上关注我,在那里我发布我所有的故事
B .订阅我的 简讯 。这会让你了解新的故事,并给你机会发短信给我,让我收到你所有的更正或疑问。
C .成为 推荐会员 ,这样你就不会有任何“本月最大数量的故事”,你可以阅读我(以及成千上万其他机器学习和数据科学顶级作家)写的任何关于最新可用技术的文章。
使用 Azure Functions 核心工具获取本地开发的应用程序设置
使用 Azure Function Core 工具,我们可以从函数中检索设置,以简化我们的本地开发和调试工作!
在部署我们的 Azure 功能之前,最好在本地调试我们的功能,以确保它按预期工作。本地运行我们的函数需要一个 local.settings.json 文件来存储我们的应用程序设置。
当我们第一次在 Visual Studio 中创建函数时,会为我们生成一个 local.settings.json 文件。但是,如果我们从一个库克隆一个功能 app,这个文件就不会被克隆了!(希望它不会被克隆。最好不要把这个文件提交给你的回购,因为它有应用程序的秘密!).
幸运的是,我们可以使用 Azure Function Core Tools 创建一个 local.settings.json 文件,并将我们的函数设置导入到该文件中,这样我们就可以在本地运行我们的函数,就像我们在那个环境中运行它一样!
我们为什么要这么做?
比方说,如果我们有多个环境(开发、测试、UAT 等),我们希望使用这些环境设置在本地调试一个功能,我们可以使用 Azure Function Core 工具来简化这些设置的检索。尤其是对于有很多设置的函数。我们不想浪费时间复制和粘贴所有这些设置!
开始之前
你需要确保你的机器上已经安装了 Azure 功能核心工具。Azure Functions 核心工具包括一个支持 Azure Functions 运行时的相同运行时版本,我们可以在我们的机器上运行它。
虽然我们将只关注获取我们的应用程序设置,但函数核心工具附带了允许我们创建函数、部署函数等命令!
如果您还没有安装这些工具,请查看本文档开始安装。
我们开始吧
对于本教程,我从 GitHub 克隆了一个现有项目。我已经把这个功能部署到 Azure 和我的。gitignore 文件排除了我创建项目时生成的 local.settings.json 文件。
为了帮助我进行本地调试,我将使用 Function Core 工具来帮助从 Azure 获取我的应用程序设置。为了验证本地设置文件不在我的项目目录中,这里有一个屏幕截图:
图片作者:Will Velida
我们需要创建一个 JSON 文件来写入我们的应用程序设置。为此,右键单击 Functions 项目并创建一个新文件。创建一个 JavaScript JSON 配置文件,命名为 local.settings.json
步骤 1:设置我们的 Azure 订阅
如果你使用多个 Azure 订阅,我们需要使用 AZ CLI 来设置它,以确保当我们运行我们的功能核心工具时,它在正确的位置。
在您的计算机上打开命令行或 PowerShell,并通过运行以下命令登录到您的 Azure 帐户:
az login
登录后,您应该会看到您有权访问的订阅列表。要设置托管您的函数的订阅,请运行以下命令:
az account set -s "<subscription-name-or-id>"
-s 是订阅的简写参数。
步骤 2:获取我们的应用程序设置
现在,我们可以从 Azure 的功能应用程序中获取应用程序设置。确保您位于项目的目录中,并在终端中运行以下命令:
func azure functionapp fetch-app-settings '<function-name>' --output-file local.settings.json
您应该会在终端中看到类似如下的输出:
图片作者:Will Velida
回到 Visual Studio 中的项目,并签出您的 local.settings.json 文件。我们可以看到,我们的函数设置已经被检索并写入我们的本地设置文件!
然而,只有一个问题…
图片作者:Will Velida
我们的设置被加密了!当在本地运行我们的函数时,这对我们没有帮助!函数应用程序设置在存储时是加密的,只有在启动时被注入函数的进程内存之前才会被解密。
要了解 Azure Functions 中应用程序设置的更多信息,请查看这篇文章。
第三步:解密我们的设置。
谢天谢地,我们可以使用 Azure Function Core 工具解密我们的设置!在您的终端中,运行以下命令:
func settings decrypt
回到 Visual Studio,您将看到您的设置已经被解密,并准备好用于您的本地调试需要!
(*当然我不会给你那个的截图!这是秘密!*😂😉).
我们现在可以在本地启动我们的功能,就像我们在 Azure 环境中运行它一样!
这里要注意一点!如果您在 Key Vault 中存储了一些应用程序设置(您应该这样做!),则当您检索该设置时,您可能只能获得存储该机密的密钥库 URL。要使用实际值,您需要从密钥库中检索它。
包扎
正如你所看到的,使用 Azure Function Core 工具可以帮助我们快速检索功能应用设置,从而加快我们的开发过程。
如果您想了解更多信息,请查看以下资源:
如果您有任何问题,请随时在 Twitter 上联系我或在评论中提问!
编码快乐!👨💻👩💻💻
使用 Azure 日志分析工作区从虚拟机收集自定义日志
不,我们不是在谈论带有预定义指标的 Azure Monitor。
马丁·范·登·霍维尔在 Unsplash 上的照片
动机:
我们都已经在虚拟机页面上看到了“Monitoring”选项卡的关键指标。是的,通过 CPU 指标来查看 CPU 是否一直在运行,以指标来检查虚拟机何时通过网络从外部世界获取数据,以及虚拟机是否正在使用磁盘操作/秒指标进行任何类型的写操作,这都很有用,但对于我们在虚拟机上构建的定制服务来说,这并不有效。因此,在这篇博客中,我将向您展示如何基于客户服务创建您自己的日志,使用其默认代理将它带到Azure Log Analytics Workspace**,并根据我们的需要查询它,甚至更好地在其上创建警报。**
先决条件:
- 蓝色账户
- Azure 虚拟机服务
- Azure 日志分析工作区服务
- Azure 警报服务
Azure 虚拟机:
让我们从虚拟机本身开始。您已经在虚拟机上运行了服务,但是不知道如何将这些日志放入门户,甚至不知道如何为您的服务创建日志。因此,让我们假设您还没有为您的服务创建日志。因此,在这篇博客中,我将以一个简单的 flask 应用程序作为我的服务示例。要启动并运行它,我们必须从 pip 下载 flask 库,然后创建一个 flask 应用程序,如下所示:
苏拉布什雷斯塔。使用 Azure 日志分析工作区从 VM 1 收集自定义日志。2021.JPEG 文件。
没什么,只是一个运行在默认端口 5000 上的简单的 flask 应用程序。让我们通过下面的命令来运行它:
python app.py
该服务必须正在运行。现在完成了,让我们移动到日志部分。我们将要使用的技巧都取决于 grep。由于 grep 命令将帮助我们找到正在运行的服务,我们将利用它来了解 app 服务是否正在工作。因此,我创建了这个 bash 脚本来了解应用服务是否正在运行。如果它正在运行,我会给它一个 200 成功代码,如果它没有运行,那么它会得到 500 错误代码。
苏拉布什雷斯塔。使用 Azure 日志分析工作区从您的虚拟机 2 收集自定义日志。2021.JPEG 文件。
一直到现在都很简单。现在尝试运行脚本,它会根据您的服务状态显示 200 或 500。但是我们不能永远手动操作。所以为了自动化,我使用 crontab 每分钟为我运行一次脚本。通过“crontab -e”打开 crontab,然后输入以下命令
苏拉布什雷斯塔。使用 Azure 日志分析工作区从您的虚拟机 3 收集自定义日志。2021.JPEG 文件。
为了解释它,第一部分处理 bash 脚本所在的位置,第二部分处理您希望将生成的日志文件放在哪里。我建议你创建这个文件和文件夹,并在把它放到 crontab 之前给它适当的权限’ chmod '。现在,让我们等待 5 分钟,检查日志是否已写入。
苏拉布什雷斯塔。使用 Azure 日志分析工作区从您的虚拟机 4 收集自定义日志。2021.JPEG 文件。
看起来它像预期的那样工作,因为我在 crontab 上运行它之前已经关闭了我的服务。复制其中 5 条消息,并将其保存在一个新文件中,我们需要向日志分析工作区提交一个样本。现在,让我们转到 Azure 门户。
Azure 日志分析工作区:
转到您的虚拟机,然后选择“日志”并单击“启用”按钮。系统将提示您创建新的工作空间。
苏拉布什雷斯塔。使用 Azure 日志分析工作区从您的虚拟机 5 收集自定义日志。2021.JPEG 文件。
工作区需要 5-10 分钟,请耐心等待。创建工作空间后,转到 Insights 选项卡
我们现在正在做的是通过点击我们的按钮来安装 Azure Log Analytics 工作空间。我们也可以使用 CLI 创建,但我更喜欢门户方式。当且仅当门户不起作用时,我才会选择 CLI 方式。现在让我们配置我们的机器来获取定制日志。转到您创建的日志分析工作区,单击“高级设置”,这将提示您进入新页面。
苏拉布什雷斯塔。使用 Azure 日志分析工作区从 VM 6 收集自定义日志。2021.JPEG 文件。
点击“数据”和“自定义日志”。你会看到一个“添加+”按钮。点击它,你会得到一个新标签的提示。
苏拉布什雷斯塔。使用 Azure 日志分析工作区从您的 VM 7 收集自定义日志。2021.JPEG 文件。
上传您在上面保存示例日志,然后单击“下一步”。您将看到“新行”和“时间戳”选项。选择“新行”并点击“下一步”
苏拉布什雷斯塔。使用 Azure 日志分析工作区从您的 VM 8 收集自定义日志。2021.JPEG 文件。
给出 crontab 上的路径,然后点击“下一步”
苏拉布什雷斯塔。使用 Azure 日志分析工作区从您的 VM 9 收集自定义日志。2021.JPEG 文件。
给出适当的名称,因为如果需要,我们将在查询中使用该名称。
苏拉布什雷斯塔。使用 Azure 日志分析工作区从您的 VM 10 收集自定义日志。2021.JPEG 文件。
不要忘记选择“将以下配置应用于我的 Linux 机器”。现在让我们看看日志是否到达。Azure 文档说日志可能需要 1 小时到达,但是在我的例子中,它在 20 分钟内到达。所以请按照步骤做好,等待日志到达。现在,点击“日志”,会出现一个窗口提示您输入一些类似 SQL 的命令。它实际上是 Kusto 查询语言,类似于 SQL,所以我们可以使用 Azure 提供的引用来使用它。我还将在下面的参考资料部分链接该指南。
苏拉布什雷斯塔。使用 Azure 日志分析工作区从您的 VM 11 收集自定义日志。2021.JPEG 文件。
如你所见,它成功了。如果你已经做到了这一步,那么恭喜你,因为你已经很好地将你的自定义日志引入了 Azure 门户。现在您可以使用它,查询它,分析它,等等。在下一部分中,我将基于自定义日志创建一个警报。
Azure 提醒:
到目前为止,我们将自定义日志引入 Azure 门户,这已经是一项相当大的工作,但我们还想做得更多。因此,让我们基于自定义日志创建一个警报。正如你已经意识到的,自定义日志是混乱的,所以我们要做的是首先使用 Kusto 查询语言(KQL)清理它。
苏拉布什雷斯塔。使用 Azure 日志分析工作区从您的 VM 12 收集自定义日志。2021.JPEG 文件。
我们在这里所做的只是从我们的自定义日志中提取状态代码。我应该说非常整洁。现在,我们要做的是根据状态代码创建一个警报。如果服务不运行,我们将得到一个 500 错误代码,因此,如果服务不工作,我们将使用 500 错误代码创建一个警报。单击“新建警报规则”,这将提示您进入新页面。
苏拉布什雷斯塔。使用 Azure 日志分析工作区从您的 VM 13 收集自定义日志。2021.JPEG 文件。
输入我所做的选择。我们使用聚合类型作为最大值,因为我们只有两个状态代码,并且警报逻辑本身是描述性的。点击“下一步”和“创建行动组”,输入您的电话号码或电子邮件。
苏拉布什雷斯塔。使用 Azure 日志分析工作区从您的 VM 14 收集自定义日志。2021.JPEG 文件。
创建行动组后,返回,您将看到您新创建的行动组。给出您的提醒名称和“查看+创建”。现在让我们等待 5 分钟,看看是否会弹出一封电子邮件。
苏拉布什雷斯塔。使用 Azure 日志分析工作区从您的 VM 15 收集自定义日志。2021.JPEG 文件。
耶,警报被触发了,我们收到了一封邮件。祝贺你,如果你已经做到了这一步,因为这不是一个简单的任务。
结论:
我们创建了一个服务,每分钟生成一个日志,将它带到 Azure 门户,并基于它创建一个警报。如果您想要在为机器学习任务训练模型时创建 GPU 的日志以了解其状态,则可以将相同的逻辑应用于 GPU 指标。它还可以应用于不同的 web 服务,以了解它们的状态等等。可能性是无限的,选择是无限的,你想做什么取决于你自己。如果你遇到任何问题或难以遵循这些步骤,请在下面评论这篇文章或在 tsulabh4@gmail.com 给我发消息。你也可以在 Linkedin 和 GitHub 上和我联系。
资源:
[1]:KQL-1:https://docs . Microsoft . com/en-us/azure/data-explorer/kusto/query/extract function
[2]KQL-2:https://docs . Microsoft . com/en-us/azure/data-explorer/kusto/query/re2
[4]KQL-4:https://docs . Microsoft . com/en-us/azure/data-explorer/kusto/query/SQL cheat sheet
[5] Azure 日志分析工作区:https://docs . Microsoft . com/en-us/Azure/Azure-monitor/agents/data-sources-custom-logs
利用 PyMC3 中的贝叶斯分层模型推断新冠肺炎的疾病参数
在本帖中,我们来看看如何使用 PyMC3 来推断新冠肺炎的疾病参数。PyMC3 是一个流行的概率编程框架,用于贝叶斯建模。实现这一点的两种流行方法是马尔可夫链蒙特卡罗( MCMC )和变分推断方法。这里的工作着眼于使用美国感染病例的当前可用数据作为时间序列,并试图使用分室概率模型对此建模。我们想尝试推断疾病参数,并最终使用 MCMC 采样估计 R0 。然后,我们将探索如何使用贝叶斯分层模型来做同样的事情,以及与池化或非池化模型相比的好处。我们总结了这个模型的局限性,并概述了改进推理过程的步骤。
这里介绍的工作仅用于说明目的,现实生活中的贝叶斯建模需要比这里显示的复杂得多的工具。这里作出了关于种群动态的各种假设,这些假设可能不适用于大型非同质种群。此外,这里不考虑社会距离和疫苗接种等干预措施。
本帖将涵盖以下内容:
- 流行病的分室模型
- 数据从何而来,如何获取
- 疾病动力学 SIR/SIRS 模型
- PyMC3 常微分方程的贝叶斯推理
- 使用层次模型扩展工作
- 概率编程的指南和调试技巧
我还在 Coursera 上推出了一系列课程,涵盖贝叶斯建模和推理的主题,课程 2 和 3 与本文特别相关。请到https://www.coursera.org/specializations/compstats查看。
流行病的分室模型
关于房室模型及其行为的概述,请参考朱莉亚—https://github.com/sjster/Epidemic.的笔记
房室模型是封闭种群的一组常微分方程(ODEs ),这意味着种群没有进出该房室的运动。这些旨在模拟同质人群中的疾病传播。可以想象,这些假设在大人群中可能不成立。这里还必须指出的是,人口出生和死亡人数等生命统计数据可能不包括在这个模型中。下面的列表提到了一些分室模型以及疾病传播的各个分室,然而,这决不是一个详尽的列表。
- 易感感染(SI)
- 易感感染者康复(SIR)
- 易受感染的
- 易感感染恢复易感(SIRS)
- 易感感染者康复死亡(SIRD)
- 易感暴露感染康复(SEIR)
- 易感暴露感染恢复易感(SEIRS)
- 易感暴露感染康复死亡
- 母源性免疫易感传染病痊愈(MSIR)
- 西达尔特(https://www.nature.com/articles/s41591-020-0883-7)
上面列出的最后一个是最近的,专门针对新冠肺炎的,可能值得感兴趣的人读一读。现实世界的疾病建模通常不仅仅涉及疾病阶段的时间演变,因为许多与分室相关的假设都被违反了。为了了解疾病是如何传播的,我们需要观察疾病在人群中的空间离散化和演变。GLEAM 是模拟这种时空演变的框架的一个例子(图 1)。
图 1-真实世界流行病建模(时空动态)。
GLEAM 等工具使用人口普查数据和流动模式来了解人们如何在地理上流动。GLEAM 将地球划分为大约 25 公里 x25 公里的空间网格。大致有两种类型的移动:全球或远程移动和本地或短程移动。长期流动性主要涉及航空旅行,因此机场被认为是疾病传播的中心。海上旅行也是另一个重要因素,因此军港是另一种进入点。与上面列出的数学模型一起,这提供了一个随机框架,可用于进行数百万次模拟,以推断参数并进行预测。
新冠肺炎数据
此处使用的数据来自约翰·霍普金斯 CSSE Github 页面,该页面中的病例数会定期更新:
这些数据以 CSV 文件的形式提供,可以通过 Python pandas 读取。
SIR 和 SIRS 模型
SIR 模型
SIR 模型由下面所示的三个常微分方程组(ODEs)给出。这个模型有三个部分。
这里的‘S’、‘I’和‘R’指大小为‘N’的人群中的易感、感染和康复部分,因此
这里的假设是,一旦你从疾病中康复,个人将获得终身免疫。许多疾病的情况并非如此,因此可能不是一个有效的模型。
λ是感染率,μ是从疾病中康复的速度。从感染中康复的人的比例由“f”给出,但是为了这项工作的目的,“f”在这里被设置为 1。我们以我们的常微分方程组的初值问题(IVP)结束,其中 I(0)被假设为从疫情开始的情况计数中已知,并且 S(0)可以被估计为 N-I(0)。这里我们假设整个人口都是易感的。我们的目标是实现以下目标:
- 使用贝叶斯推理对λ和μ进行估计
- 使用上述参数估算任何时间“t”的 I(t)
- 计算 R0
正如已经指出的,λ是疾病传播系数。这取决于在单位时间内与有传染性的人互动的次数。这又取决于人群中的感染人数。
在任何时间‘t’的感染力或风险被定义为:
另外,μ是单位时间内发生的恢复的分数。因此,μ的倒数就是平均恢复时间。“基本再生数” R0 是由单个主要案例产生的次要案例的平均数(例如https://www.ncbi.nlm.nih.gov/pmc/articles/PMC6002118/)。 R0 也被定义为λ和μ的比值,由下式给出
以上假设 S0 接近 1。当 R0 > 1 时,我们有了疾病的扩散,我们有了疫情。随着最近对脆弱人群进行疫苗接种的努力,这一点变得更加需要理解。如果我们给人口中的一小部分“p”接种疫苗以获得*(1p)R0<1*,我们就能阻止疾病的传播。
SIRS 模型
如下图所示,SIRS 模型并没有假设感染者一旦康复后会终身免疫。因此,从恢复区室到易感区室。因此,对于新冠肺炎来说,这可能是一个更好的低保真度基线模型,因为它表明获得性免疫是短期的。这里唯一的附加参数是γ,它指的是免疫力丧失和受感染个体从恢复池移动到易感池的速率。
对于这项工作,只实现了 SIR 模型,SIRS 模型及其变体留待将来的工作。
使用 PyMC3 推断疾病参数
我们可以使用一阶或二阶时间差分方案对 SIR 模型进行离散化,然后将其传递给 PyMC3,pymc 3 将使用这些离散化方程及时推进求解。然后可以使用蒙特卡罗采样程序拟合参数λ和μ。
一阶方案
二阶方案
PyMC3 中的微分方程方法
虽然我们可以选择高阶离散化方案来手动提供离散化,但这很快就会变得繁琐且容易出错,更不用说在 Python 这样的语言中计算效率低下了。幸运的是,PyMC3 有一个 ODE 模块来完成这个任务。我们可以使用 ODE 模块中的微分方程方法,该方法将一个函数作为输入,该函数以向量的形式返回一组 ODE 的值、需要求解的时间步长、对应于方程数量的状态数量以及我们想要求解的变量数量。尽管这仍然比手工离散化要快,但是这种方法对于问题的规模来说扩展性很差。推荐的最佳实践是使用 PyMC3 中的“sunode”模块(见下文)。例如,对于 100 个样本、100 个调整样本和 20 个时间点,相同的问题使用微分方程需要 5.4 分钟,而使用 sunode 需要 16 秒。
self.sir_model_non_normalized = DifferentialEquation(
func = self.SIR_non_normalized,
times = self.time_range1:],
n_states = 2,
n_theta = 2,
t0 = 0)def SIR_non_normalized(self, y, t, p):
ds = -p[0] * y[0] * y[1] / self.covid_data.N,
di = p[0] * y[0] * y[1] / self.covid_data.N — p[1] * y[1]
return[ds, di]
使用 sunode 模块的语法如下所示。虽然有一些句法上的差异,但总体结构与微分方程是相同的。
import sunode
import sunode.wrappers.as_theanodef SIR_sunode(t, y, p):
return { ‘S’: -p.lam * y.S * y.I,
‘I’: p.lam * y.S * y.I — p.mu * y.I}……sir_curves, _, problem, solver, _, _ =
sunode.wrappers.as_theano.solve_ivp(
y0={ # Initial conditions of the ODE
‘S’: (S_init, ()),
‘I’: (I_init, ()),},
params={
# Parameters of the ODE, specify shape
‘lam’: (lam, ()),
‘mu’: (mu, ()),
‘_dummy’: (np.array(1.), ())} # currently, sunode throws an error, without this # RHS of the ODE
rhs=SIR_sunode,
# Time points of th solution
tvals=times,
t0=times[0],)
SIR 模型的推理过程
为了对我们寻求的参数进行推断,我们首先为疾病参数选择合理的先验。基于我们对疾病现象行为的理解,对数正态分布是疾病参数的合理先验。理想情况下,我们希望这个对数正态分布的平均参数在我们期望的参数附近。对于良好的融合和解决方案,数据似然性是适当的(领域专业知识!).通常选择以下之一作为可能性。
- 正态分布
- 对数正态分布
- 学生的 t 分布
我们从 ODE 求解器获得易感(S(t))和传染(I(t))数,然后对λ和μ的值进行采样,如下所示。
with pm.Model() as model4: sigma = pm.HalfCauchy(‘sigma’, self.likelihood[‘sigma’], shape=1) lam = pm.Lognormal(‘lambda’, self.prior[‘lam’], self.prior[‘lambda_std’]) # 1.5, 1.5 mu = pm.Lognormal(‘mu’, self.prior[‘mu’], self.prior[‘mu_std’]) res, _, problem, solver, _, _ = sunode.wrappers.as_theano.solve_ivp(
y0={‘S’: (self.S_init, ()), ‘I’: (self.I_init, ()),},
params={‘lam’: (lam, ()), ‘mu’: (mu, ()), ‘_dummy’: (np.array(1.), ())},
rhs=self.SIR_sunode,
tvals=self.time_range,
t0=self.time_range[0]) # likelihood distribution mean, these are the predictions from the SIR model ODE solver if(likelihood[‘distribution’] == ‘lognormal’): I = pm.Lognormal(‘I’, mu=res[‘I’], sigma=sigma, observed=self.cases_obs_scaled) elif(likelihood[‘distribution’] == ‘normal’): I = pm.Normal(‘I’, mu=res[‘I’], sigma=sigma, observed=self.cases_obs_scaled) elif(likelihood[‘distribution’] == ‘students-t’): I = pm.StudentT( “I”, nu=likelihood[‘nu’], \
mu=res[‘I’],
sigma=sigma,
observed=self.cases_obs_scaled) R0 = pm.Deterministic(‘R0’,lam/mu) trace = pm.sample(self.n_samples, tune=self.n_tune, chains=4, cores=4) data = az.from_pymc3(trace=trace)
PyMC3 的推理流程
因为开发这样一个模型,使用贝叶斯推理来估计疾病参数,是一个迭代过程,我们希望尽可能自动化。用各种参数实例化一类模型对象并自动运行可能是个好主意。为每次运行保存跟踪信息、推理度量(如 R̂ (R-hat ))以及其他元数据信息也是一个好主意。诸如 NetCDF 之类的文件格式可以用于此,尽管它可以像使用 Python 内置数据库模块“shelve”一样简单。这里没有显示用于数据提取的类,但是显示了它们的调用,以便您对这里使用的数据和模型参数有所了解。
covid_obj = COVID_data(‘US’, Population=328.2e6)covid_obj.get_dates(data_begin=’10/1/20', data_end=’10/28/20')sir_model = SIR_model_sunode(covid_obj)likelihood = {‘distribution’: ‘normal’, ‘sigma’: 2}prior = {‘lam’: 1.5,‘mu’: 1.5, ‘lambda_std’: 1.5, ‘mu_std’: 1.5 }sir_model.run_SIR_model(n_samples=500, n_tune=500, likelihood=likelihood, prior=prior)
这些结果纯粹是为了说明的目的,需要进行大量的实验才能从模拟中得到有意义的结果。美国 1 月至 10 月的病例数如下所示(图 2)。
图 2 -美国新冠肺炎病例数可视化示例
图 3 示出了推理运行的结果,其中显示了λ、μ和 R0 的后验分布。执行贝叶斯推断的一个优点是,分布显示了平均值估计以及用于量化不确定性的最高密度区间(HDI)。检查跟踪是一个好主意(至少!)以确保正确采样。
图 3 -使用 PyMC3 显示最高密度区间(HDI)的推理运行结果示例。
池化、非池化和分层模型
假设您有关于美国各州感染人数的信息。使用该数据来推断新冠肺炎的疾病参数(例如 R0) 的一种方式是将其全部相加以估计单个参数。这被称为集合模型。然而,这种方法的问题是可能包含在这些单独的状态或组中的细粒度信息丢失了。另一个极端是估计每个状态的单个参数 R0 。这种方法产生了一个非池模型。然而,考虑到我们正在尝试估计对应于同一病毒的参数,必须有一种方法来集体执行此操作,这将我们带到了层次模型。当在某些州没有足够的信息来创建准确的估计时,这特别有用。分层模型允许我们使用共享的“超优先级”来共享来自其他状态的信息。让我们以下面的例子来更详细地看看这个公式:
对于混合模型,我们可以从具有固定参数λ_μ,λ_σ的单个分布中提取
对于未规划的模型,我们可以从具有固定参数λ_μᵢ、λ_σᵢ
对于分层模型,我们有一个先验,它由来自其他分布的非常数参数来参数化。这里,我们为每个状态画一个λ值,但是它们通过共享的超优分布(具有常数参数)连接,如下所示。
查看课程 3 贝叶斯建模和推理的 PyMC3 介绍(【https://www.coursera.org/learn/introduction-to-pymc3?】T2)specialization=compstats )来了解更多关于层次模型的细节。
分层模型的新冠肺炎数据
这里我们绘制并使用了美国和巴西这两个国家每天的感染病例数。然而,在层级模型中可以使用的国家的选择或数量没有限制。以下案例发生于 2020 年 3 月 1 日至 2021 年 1 月 1 日。这些图表似乎遵循相似的轨迹,尽管这些国家在 y 轴上的比例不同。考虑到这些病例来自同一个新冠肺炎病毒,这是合理的。然而,在现实场景中,需要考虑差异,例如不同的变量、不同的地理结构和社会距离规则、医疗保健基础设施等等。
图 4 -两个国家的新冠肺炎病例数量图
参数推断
对于分层模型,下面给出了执行疾病参数推断的代码片段。
with pm.Model() as model4: # narrow std is roughly equivalent to a constant prior parameter, if there are issues with sampling from the prior distribution
# make the variance of the mean smaller. Variance of the distribution of the variance parameter seems less relevant in this regard. nsamples = 8000 ntune = 4000 Hyperprior = {“Lambda mean”: 0.75, “Lambda std”: 2, “Mu mean”: 0.75, “Mu std”: 2} Prior = {“Lambda std”: 1.0, “Mu std”: 1.0} Likelihood = {“Name”: “Normal”, “Parameters”: {“std”: 0.01}} prior_lam = pm.Lognormal(‘prior_lam’, Hyperprior[‘Lambda mean’], Hyperprior[‘Lambda std’]) prior_mu = pm.Lognormal(‘prior_mu’, Hyperprior[‘Mu mean’], Hyperprior[‘Mu std’]) prior_lam_std = pm.HalfNormal(‘prior_lam_std’, Prior[‘Lambda std’]) prior_mu_std = pm.HalfNormal(‘prior_mu_std’, Prior[‘Mu std’]) lam = pm.Lognormal(‘lambda’, prior_lam , prior_lam_std, shape=2) mu = pm.Lognormal(‘mu’, prior_mu , prior_mu_std, shape=2) # — — — — — — — — — — ODE model — — — — — — — — # res, _, problem, solver, _, _ = sunode.wrappers.as_theano.solve_ivp(
y0={ ‘S’: (S_init, (2,)), ‘I’: (I_init, (2,)),},
params={‘lam’: (lam, (2,)), ‘mu’: (mu, (2,)), ‘_dummy’: (np.array(1.), ())},
rhs=SIR_sunode,
tvals=time_range[1:],
t0=time_range[0]) I = pm.Normal(‘I’, mu=res[‘I’], sigma=Likelihood[‘Parameters’][‘std’], observed=cases_obs_scaled[1:]) R0 = pm.Deterministic(‘R0’,lam/mu) # if you increase the variance and the distributions looks choppy, increase the tuning sample size to sample the space more effectively
# also, increase the total number of samples trace = pm.sample(nsamples, tune=ntune, chains=8, cores=8) data = az.from_pymc3(trace=trace)
样本后验分布及其 94%的最高密度区间(HDI)如下所示。
图 5 -采样后验分布及其 94%的最高密度区间(HDI)。
我们还可以检查轨迹图的收敛性,它显示了所有变量的良好混合——这是采样器很好地探索了空间的好迹象。所有的痕迹之间有很好的一致性。这种现象可以从上图中相当窄的 HDI 区间得到证实。
图 6-R0 和其他变量的轨迹图和密度图
下表总结了各种推断变量和参数的分布,以及抽样统计。虽然对变量的估计是必不可少的,但此表对于告知我们采样器的质量和效率特别有用。例如,R-hat 都接近或等于 1.0,表明所有链之间的一致性良好。有效样本量是另一个关键指标。如果这与样本总数相比很小,这肯定是取样器有问题的迹象。即使 R-hat 值看起来不错,也一定要检查有效样本量!
图 7 -推断变量分布表以及抽样统计
注意事项和指南
建模和推理的一些一般准则:
- 使用至少 5000 个样本和 1000 个样本进行调整。
- 对于上面显示的结果,我使用了:均值:λ= 1.5,= 1.5,两个参数的标准差:2.0。领域专家和他的知识在设置这些参数时是非常宝贵的。
- 至少从 3 条链上取样。
- 将 target_accept 设置为> 0.85(取决于采样算法)。
- 如果可能,用核心=n 并行采样,其中‘n’是可用核心的数量。
- 检查轨迹是否收敛。
- 有限的时间样本会影响推断的准确性,拥有更多高质量的数据总是更好的。
- 规范化您的数据,大值通常不利于收敛
调试您的模型
- 因为 PyMC3 的后端是 theano,所以 Python print 语句不能用于检查变量值。使用**the no . printing . print(DESCRIPTIVE _ STRING)(VAR)**来完成这个。
- 通过传递“testval”来初始化随机变量。这非常有助于检查那些讨厌的“坏能量”错误,这些错误通常是由于对可能性或先验的错误选择。使用 Model.check_test_point() 来验证这一点。
- 使用步骤= pm。Metropolis() 对于快速调试来说,这运行得更快,但结果却更粗糙。
- 如果采样很慢,检查你的先验分布和似然分布。
- 先验分布的窄西格玛值可用于模拟常数先验,并有助于调试从先验分布采样的问题。
- 如果增加方差导致不连续的后验分布,则增加调整样本大小和样本数量,以便更有效地对空间进行采样。
未来的工作
虽然这为我们的参数产生了令人满意的估计,但我们经常遇到采样器不能有效地执行的问题。对于未来的工作,有几种方法可以诊断和改进建模过程。下面按难度递增的顺序列出了这些问题:
- 增加调整大小和抽取的样本数。
- 减小采样器的 target_accept 参数,以减少样本间的自相关。使用自相关图来证实这一点。
- 向观测数据中添加更多样本,即增加采样频率。
- 为参数使用更好的先验和超先验。
- 使用模型的替代参数化。
- 将社交距离测量等变化纳入模型。
了解更多信息
你可以在我的 Coursera specialization(https://www.coursera.org/specializations/compstats)了解更多关于这些主题的信息,该课程包括以下课程:
- 贝叶斯统计导论(https://www.coursera.org/learn/compstatsintro?专门化=compstats
- 贝叶斯推理与 MCMC(【https://www.coursera.org/learn/mcmc? 专门化=compstats
- 用于贝叶斯建模和推理的 PyMC3 简介(【https://www.coursera.org/learn/introduction-to-pymc3?】T4)专业化=compstats
参考
- Priesemann 小组的工作
https://github.com/Priesemann-Group/covid_bayesian_mcmc
2.Demetri Pananos 在 PyMC3 网站上的工作
3.太阳之歌
https://github.com/aseyboldt/sunode
4.闪光
利用大转移预测疟疾
使用迁移学习将血液涂片分类为未感染或感染了引起疟疾的寄生虫
Pixabay 在像素上拍摄的照片
迁移学习是利用在一项任务中获得的知识来解决另一项任务的过程。先前训练的模型被用作基础,在其上添加一个层来微调模型以解决新的任务。
本博客的主要目的是让读者了解什么是大转移,以及如何以最小的努力将它微调并应用于与预训练模型完全不同的领域中的问题。
在的论文“医学成像规模的监督转移学习”中,来自谷歌的研究人员证明,使用大转移( BiT ),可以提高各种医疗任务的准确性,如乳房 x 线摄影癌症识别、胸部 x 射线解释和皮肤状况分类。该论文还发现,使用 BiT 模型,他们仅使用 30%-60%的训练数据就能够实现基线性能。
在此之前,研究人员不清楚对一组自然图像的迁移学习如何适用于医学图像,因为图像大小的差异、域的差异以及使用医学图像中纹理的局部变化来检测感兴趣的病理。
我看到了 Mark Rober 的视频,讲述了斯坦福大学的一个团队如何开发了一台显微镜( Foldscope )和一台纸离心机( Paperfuge ),总共花费 68 美分,可以由一名训练有素的专业人员用来查看幻灯片和检测疟疾等疾病。虽然我没有设法得到从 Foldscope 收集的幻灯片图像数据集,但我发现了另一个数据集,其中幻灯片图像是由连接到传统光学显微镜的智能手机收集的。这一点很重要,因为在最需要这些检测的贫困社区,缺乏设备和资源是这些检测不容易获得的主要原因。
数据集的未感染(左)和寄生(右)载玻片示例
将所有这些放在一起,以及我对测试在医学图像数据集上微调 BiT 有多容易的兴趣,我决定在这个疟疾数据集上尝试大转移。
本博客将让您了解使用位超规则(BiT-HyperRule)对特定任务的位模型进行微调是多么容易,位超规则是一种启发式方法,用于确定所有用于微调的超参数,并获得很好的结果。比特超规则是一个很好的起点,这也是我将在本教程中经历的。我假设读者具备深度学习的基础知识。你可以在这里查看这个教程的 Jupyter 笔记本。
大传输(位)
BiT 的主要特点是使用 ImageNet-21k 和 JFT-300M 等大型数据集进行预训练。本教程中使用的模型是 BiT-M,它已经在 ImageNet 21k 上进行了预训练,ImageNet 21k 是一个数据集,包含 21,843 个不同类别的 1,400 万张图像,并基于 ResNet-50x1 架构。还有其他变化的钻头可用,这里列出了。
BiT 的优点是:
- 适用于各种各样的任务,甚至是那些领域不匹配的任务,如医学成像
- 使用位超规则,可以获得很好的结果,并且可以通过进一步调整超参数来改善这一点(下面将详细介绍)
- 模型的快速收敛。
记住这一点,让我们开始吧。
我建议在阅读本教程之前,先浏览一下在这里找到的的比特文件。
数据预处理:
该数据集包含 27558 个图像,未感染和寄生的载玻片图像之间平分。然后,我们将数据集分成 3 个不同的子集:训练集、验证集和测试集。训练集用于训练模型,然后基于验证集的结果,选择最佳模型。通常,模型的超参数将使用验证集进行调整,但是因为我们使用位超规则,所以我们将只使用验证集来选择最佳模型。最后,测试集用于评估模型的最终性能。请注意,测试集应该是独立的,永远不要用于调整模型。
在这种情况下,训练集包含 90%的图像,验证集包含 9%的图像,最后测试集包含 1%的图像。
train_size = int(0.90 * num_examples)
val_size = int(0.09* num_examples)
test_size = int(0.01 * num_examples)full_dataset = ds.shuffle(reshuffle_each_iteration=False, buffer_size=len(ds))
train_dataset = full_dataset.take(train_size)
test_val_dataset = full_dataset.skip(train_size)
val_dataset = test_val_dataset.take(val_size)
test_dataset = test_val_dataset.skip(val_size)
数据扩充和标准化;
收集和标记数据是一个昂贵的过程。数据扩充是用现有数据毫不费力地创建更多数据的方法。通过修改现有图像,如旋转、翻转,可以从现有图像生成新图像。其他数据扩充方法包括裁剪等技术,但在这种情况下不使用,因为它可能会导致图像的主要特征被删除。
features['image'] = tf.image.random_flip_left_right(features['image'])
features['image'] = tf.image.random_flip_up_down(features['image'])
我们还对图像数据进行了归一化处理,使该值介于 0-1 之间。这有助于确保数据具有相似的分布,从而有助于模型更快地收敛。这也有助于提高模型的稳定性。
features['image'] = tf.cast(features['image'], tf.float32) / 255.0
添加输出图层:
因为我们将使用的位模型是一个特征提取器,所以我们需要添加一个输出层,神经元的数量等于类的数量(本例中为 2)。然后,我们将该层的权重初始化为 0。
class MyBiTModel(tf.keras.Model):
"""BiT with a new head."""def __init__(self, num_classes, module):
super().__init__() self.num_classes = num_classes
**self.head = tf.keras.layers.Dense(num_classes, kernel_initializer='zeros')**
self.bit_model = module
使用位超规则设置超参数:
- 批量:512 个
- 学习率:0.003
- 计划长度:500
- 计划界限= 720,1440,2160
比特超规则规定,对于具有小于 20 k 的标记示例的数据集,调度长度应该是 500 步,而那些具有小于 500 k 的标记示例的数据集应该是 10 k 步。因为这个问题中的标记示例数是 27558,刚好超过 20 k 标记示例边界,所以我决定坚持 500 步。
初始学习率是 0.003,并且在步骤 720、1440、2160 中衰减 10 倍。这些步骤分别占整个训练步骤的 30%、60%和 90%
提前停止回调以防止过拟合:
为了防止过度拟合,使用了早期停止,这是一种在被监视的度量没有按预期表现时停止训练的方法。在这种情况下,如果验证损失连续 10 个时期没有减少,则停止训练,并且恢复来自具有最小验证损失的时期的模型权重。
es = EarlyStopping(monitor='val_loss', mode='min', verbose=1, patience=10,restore_best_weights=True)
优化器和损失函数:
使用带动量的随机梯度下降优化器。选择的损失函数是稀疏分类损失函数。当标签的数量为 2 或更多时,使用该损失函数,并且它期望类别标签是整数。
optimizer = tf.keras.optimizers.SGD(learning_rate=lr_schedule, momentum=0.9)
loss_fn = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True)
训练模型:
现在是激动人心的部分,按回车键+回车,让模型训练!完成这一步后,去给自己做一杯热饮吧,这是你应得的!
model.compile(optimizer=optimizer,loss=loss_fn,metrics=['accuracy'])
在这种情况下,验证损失在时段 31 之后没有减少,因此从时段 31 开始恢复并使用。
列车运行前检查:
在花费时间和资源在 x 时代上训练模型之前,重要的是执行某些健全性检查以确保模型按预期执行。
最重要的是检查输出值是否有意义。在分类模型的情况下,概率的总和值应该是 1。
test_logits = model(test_image) #running the model on a test image
**sum_proba = (np.sum(tf.nn.softmax(test_logits).numpy()[0]))** #summimg the probabilities
#sum_proba should be 1\.
列车运行后检查:
重要的是,对于特定的图像,当图像稍微改变时,例如旋转或翻转,模型输出不会改变。这被称为不变性检查。为了测试这一点,我们增加了测试集中的图像,并检查模型的预测在单个图像的所有不同变化中是否一致。
Pseudocode for post-train check:
1\. Classify image with the trained model
2\. Augment the image (rotate/ flip) and then classify it again
if result from 1 == result from 2:
Model passes post-train check
else:
Retrain model such that it is invariant to augmentations which does not change the main features of the image.
用于不变性检查的旋转图像
评估模型:
一旦训练完成,我们确保用来自最佳时期的权重来拟合模型。在这种情况下,这是验证损失最小的模型。
model.load_weights('best_model')
然后,我们可以通过查看以下指标来继续分析该模型:
- 测试集上的准确性:使用 274 幅图像的整个测试集,我们测试它的准确性。我们发现准确率高达 97.46%
2.混乱矩阵:
混淆矩阵允许我们以 NxN 矩阵的形式评估模型,其中 N 是类的数量。它让我们很好地了解模型的性能以及真阳性、真阴性、假阳性和假阴性的数量。该数据还可以用于重新训练模型,以改进特定类别的结果。例如,在医疗保健环境中,假阴性(当患者实际上患有疾病时,他/她被确定为健康)比假阳性(当他/她实际上没有疾病时,患者被检测为患有疾病)成本更高。
这里,错误分类的例子的数量是 7,其中 5 个被错误地预测为寄生。其他两个图像被预测为未感染,而它们实际上是寄生图像。
3。ROC-AUC:
受试者工作特征(ROC)曲线下的面积是衡量模型性能的一个非常重要的指标。以下摘录来自对 ROC-AUC 曲线的简单解释此处:
“AUC-ROC 曲线是在各种阈值设置下对分类问题的性能测量。ROC 是概率曲线,AUC 代表可分性的程度或度量。它告诉我们这个模型在多大程度上能够区分不同的类。AUC 越高,模型预测 0 为 0 和 1 为 1 的能力越强。以此类推,AUC 越高,模型在区分患病和未患病患者方面就越好”
结论:
使用 BiT-HyperRule 得到的模型在验证集上的准确率为 96.81%,在测试集上的准确率为 97.46%,ROC-AUC 为 0.99。这表明 BiT 在对医疗数据集进行分类时表现出色,即使它所训练的图像在性质上非常不同。
一个有趣的观察是,在开始稳定之前,验证损失和准确性在最初的几个时期急剧下降。
验证损失与纪元图
这可能是由于学习率和批量大小。当用不同的超参数进行试验时,即通过将批量减少到 64(而不是 512)并将学习率从 0.003 降低到 0.0001,发现验证损失遵循递减趋势,并且不像上图那样波动。但是,在得出任何结论之前,还需要进行进一步的实验。
人工智能有助于让这些疾病的诊断变得更便宜、更容易,当大规模应用时,这将产生巨大的影响。我很乐观,并且真的相信人工智能可以真正彻底改变医疗保健的状况,特别是在发展中国家和不发达国家,那里最需要廉价和容易获得的医疗保健,而且疟疾等致命疾病仍然存在。
感谢谷歌的研究人员,他们研究了比特技术,也感谢谷歌实验室笔记本的作者展示了如何使用比特技术。
“医学成像规模的监督迁移学习”的作者指出,模型可以通过超参数优化进一步改进。在下一篇博客中,我将尝试通过使用定制的超参数来提高模型的性能。所以请继续关注第 2 部分!
感谢阅读。如果你有任何问题,请在下面评论。当这个博客的第二部分出来的时候,请跟随我在 Medium 上阅读它。我在LinkedIn和Twitter上也有空。希望你有美好的一天🙂
使用 BigQuery 数组分析我的网飞观看历史
如何在 SQL 中进行高级数据清理
介绍
当我听说你可以从网飞那里获得你所有的个人资料时,我很兴奋地想看看我能找到什么。最后,我不仅对自己有了更多的了解——比如我最常看《老友记》的哪一季(第六季)——而且这也是一个检验 BigQuery 分析能力的绝佳机会。本文介绍了我如何在 BigQuery 中完成最复杂的转换,但是您可以在这里找到完整的项目:
https://count.co/n/0erWed0YsMF
为什么是 BigQuery?
也许显而易见的问题是,为什么我选择在 BigQuery 中进行这种分析,而在 Python 中却可以轻松完成。嗯,我有几个原因:
BigQuery 很快
尤其是大数据。现在,这些数据并不大,但是如果大的话,用 Python 进行这种类型的转换将需要很长时间。因此,为了迎接不可避免地需要对大数据进行大量字符串和数组操作的那一天,我想我应该准备好我的 BigQuery 技能。
并且缺乏实际例子
在做这个分析时,我意识到在 BigQuery 中进行复杂转换和分析的实际例子远没有 Python 中的多。然而,我和许多仍然依赖并喜欢使用 SQL 进行数据分析的人交谈过。我认为分享我的经验是值得的,这样下一个人就不必像我过去几天那样盯着 BigQuery 的数组文档看很久了。
使用笔记本使 BigQuery 成为这项任务的理想选择
使用 SQL IDE 进行这种类型的分析将是一场噩梦——疯狂的嵌套查询,几十个临时表会让我在不到一天的时间里回到 Jupyter 的怀抱。但是为了这个分析,我使用了一个 SQL 笔记本,这样我就可以一个单元一个单元地分解每个步骤。一切都变了。
声明:我为 Count 工作,所以我是一个粉丝,但也有其他笔记本替代品!
第一部分:准备
当我下载并把数据加载到我的笔记本上时,我注意到网飞并没有帮我把这些数据变得易于分析。
查看历史预览
特别是,他们将所有有趣的信息都放在一个字段中: Title 。
乍一看,我们似乎可以通过“:”来拆分标题,以获得标题 : 第四季(如果可用):第五集(如果可用)。
唉,这并不适用于以下情况:
- 片名中带有“:”的电影如 《星球大战:第七集:原力觉醒》
- 标题中带有“:”的显示:如 《虎王:谋杀、伤害与疯狂:限量系列:废黜(第七集)》
- 多集如 【办公室(美国)】:第六季:尼亚加拉:第一集(第四集)
只要稍微复杂一点,我们就能大幅提高精确度。具体来说,我们可以做到以下几点:
- 将每个标题归类到节目的类型:电视节目、限量系列或电影和特别节目
- 对于电影,我们将保持标题不变——不拆分。
- 对于电视节目和限量系列,我们将按“:”进行分割,
- 找到标题与季节相关的地方(即系列、系列等。)并称之为季,
- 将赛季前的串联成标题,
- 并把第季之后的一切串联成集。
当然还有其他方法,但这是对我来说最有意义的方法。该方法需要对 BigQuery 中的字符串和数组函数有很好的了解。
让我们用几个例子来看看它的实际应用:
例子
1.将我们的标题拆分成多个元素
2.查找包含季节信息的元素:
使用 REGEXP_CONTAINS 和合并
3.提取我们的标题,季节,和插曲
第二部分:分析
清理完数据后,我就可以开始探索了!事实上,去年我看《T4》和《网飞》的时间比前几年要少,但我的口味并没有太大变化——我仍然主要看电视节目。
然而,我在 2020 年暴饮暴食的次数(在 7 天或更少的时间里观看一季 7 集以上)比以往任何时候都多。
最后,我不得不看看我到底看了多少朋友。答案是:很多,尤其是和我其他的顶级电视剧相比。
我们都知道会这样。
由于我在网飞看的电视节目比其他任何东西都多,我决定建立一个互动报告来比较我在不同时间观看不同节目的习惯。这里有一个预览:
您可以在此查看整个项目,从清洁、探索到互动报告:
https://count.co/n/0erWed0YsMF
结论
除了了解我个人的查看习惯和偏好之外,这次练习也是我了解 BigQuery 强大功能的一个很好的方式。我真的对自己能够如此轻松地复制我在 Python 中应用的相同类型的逻辑印象深刻。
有用的资源:
如果您想进一步了解笔记本电脑如何改变您和您的团队处理数据的方式?伸出手去 [我](mailto: taylor@count.co) 还有剩下的 算一算 团队了解更多!
利用脑-机接口和脑电信号对情绪进行分类
我们能从脑电波中学到什么?
Unsplash.com 的乔希·里默尔图片
神经科学和脑电信号
脑电图是由电极测量的大脑活动的记录。汉斯·伯杰在 1924 年首次记录了脑电图信号,这是一个令人难以置信的发现,它导致了一个至今仍在进行大量研究的研究领域,其中有许多未知因素。脑电信号的采集是非侵入性的,电极用凝胶或浆糊放在头皮上。出于医学原因,EEG 信号最常见的用途包括癫痫研究和睡眠研究。它们也被用于发现脑损伤、脑部炎症和中风。
DEAP 数据集
该数据集由伦敦玛丽女王大学创建,可在 https://www.eecs.qmul.ac.uk/mmv/datasets/deap/index.html访问。数据集对公众开放使用,并要求签署发布表格。
数据集包括:
32 名参与者
40 个通道(前 32 个通道为脑电)
40 个一分钟视频
标签:效价、唤醒、支配、喜欢、熟悉、顺序
脑电通道名称- 'Fp1 ‘、’ AF3 ‘、’ F3 ‘、’ F7 ‘、’ FC5 ‘、’ FC1 ‘、’ C3 ‘、’ T7 ‘、’ CP5 ‘、’ CP1 ‘、’ P3 ‘、’ P7 ‘、’ PO3 ‘、’ O1 ‘、’ Oz ‘、’ Pz ‘、’ Fp2 ‘、’ AF4 ‘、’ F4 ‘、’ F8 ‘、’ FC6 ‘、’ FC2 ‘、’ Cz ‘、’ C4 ‘、’ T8 ‘、’ CP6 ‘、’
项目动机
虽然 EEG 信号通常用于医疗实践,但这项研究的重点是 EEG 信号是否以及如何用于更主观的方法,如人类的情感和情绪。通过整理参与者关于音乐视频(主观)和脑电图数据(客观)的调查,我们可以开始了解是否有可能从脑电图信号中预测情绪。
可视化和信号处理 Python 库
这项研究中主要使用的 python 库是 MNE-Python,这是一个开源的 Python 包,用于分析人类神经生理数据,包括脑磁图、脑电图和其他信号。
传感器位置
电极是小金属盘,根据 10/20 放置规则有策略地放置在头皮上。根据受试者头部的固定位置测量这些电极的位置。下面,我们可以看到该数据集实验中使用的 Biosemi 系统的传感器位置。
Biosemi32 系统头部的传感器位置(图片由作者提供)
本实验中的 Biosemi 系统是一个 32 通道系统,用于研究环境,不用于医疗用途。
偶数指头部右侧,奇数指左侧。传感器的命名惯例取决于传感器的位置:
原始的、未经处理的脑电图信号(图片由作者提供)
F —额叶
T —颞叶
C —中央叶
P —顶叶
O —枕叶
处理脑电信号
信号预处理的目的是提高信噪比和检测实验效果。这是通过带通滤波来实现的(它通过一定范围内的频率,而拒绝该范围之外的频率)。此外,在预处理期间,死通道被丢弃,伪像被去除。
标记不良频道
重要的是标记坏的信道,即故障的、未使用的或不显示任何信号的信道,以便将它们从信号分析中排除。我们可以在下面的第一个图中看到,至少有一个坏通道。错误消息告诉我们通道是 GSR2。我们会将此标记为坏通道,并重新绘制图形,看看是否可以更好地看到其他通道。我们还从原始数据集描述中了解到,通道“Erg1”和“Erg2”也不是使用过的通道,因此我们也将它们标记为坏通道。我们可以在下面的第三个图中看到,未使用的通道不再包括在内。
(图片由作者提供)
我们还知道数据集中还有其他非 EEG 通道(例如皮肤电反应),因此我们也将这些通道排除在外,因为我们不会在模型中使用它们。现在,我们已经确定了所有未使用的和非脑电图通道,我们可以设置蒙太奇。这将给出传感器的位置,并将它们转到收集数据的系统(Biosemi32)。在上面的最后一张图中,我们只能看到 EEG 通道,这些通道用颜色将信号与其传感器位置关联起来。
功率谱密度图(图片由作者提供)
通过期望的通带过滤数据
脑电波中最有用的信息存在于 30hz 以下。我们可以在这张功率谱密度图中看到,频率在 30-40hz 之间下降,因此出于研究目的,我们将截止 30hz。
检测伪影并用 ICA 消除
在决定选择哪种方法来修复工件之前,可视化并观察数据中的工件是很重要的。有三种类型的伪像会干扰 EEG 数据。其中包括环境(电线、摔门、电梯噪音、手机、空调等)仪器仪表(头皮连接不良、电磁干扰)生物假象(心跳、眨眼、吞咽)。
(图片由作者提供)
首先,我们将从数据中移除 SSP(信号空间投影)投影仪。这是一个矩阵乘法,通过将数据投影到一个更低维度的子空间来降低数据的秩。
重要的是检测伪影(视觉和心跳),以便确定它们是否足够重要而需要修复,并且还确定使用哪个工具来修复它们。我们将使用独立分量分析(ICA ),它试图将多元信号分解成独立的非高斯信号。
眨眼伪影出现在不同的通道上(图片由作者提供)
寻找事件和时期
一旦信号被处理,我们就能够识别信号中的事件。事件由刺激通道标记。对于这个数据集,刺激通道被称为“状态”。状态通道有 7 个事件标记。这些标记事件如实验开始、音乐开始、出现注视屏幕、实验结束等。这些事件标记可以对 EEG 信号进行切片以创建历元,这些历元是从连续 EEG 信号中提取的特定时间窗口。下面的第一个图像显示了这个数据样本中的所有事件标记。第二个图像是一个小的时间窗口,事件标记覆盖在信号的顶部。
一个数据样本中的标绘事件(图片由作者提供)
脑电图数据覆盖的标绘事件(图片由作者提供)
被拒绝的纪元
当我们搜索事件时,我们能够执行另一种拒绝数据的方式,这意味着眨眼(我们记得这是一种假象)。下图非常有趣,因为我们可以看到额叶中的传感器拒绝的数据比例最大。这符合常识,即额叶最靠近眨眼发生的眼睛,因此产生最强的伪像。
被拒绝的纪元的百分比(按作者分类的图像)
机器学习——监督
在数据集上测试了几种分类模型,包括 KNN、决策树分类器、随机森林分类器和袋装树。还执行了 GridsearchCV 来超调参数。
目标标签:参与者对视频的熟悉程度(图片由作者提供)
结论和前进
不幸的是,EEG 信号有一些缺点。EEG 信号具有较差的空间分辨率(距离头皮约 10cm2 ),导致需要进行密集的解释,以了解特定响应激活了大脑的哪些区域。从这项研究中我们也可以看出,脑电信号也很难处理。因此,向前推进,改进该研究结果的一种方法是进一步处理和测试信号。此外,我们可以在我们的机器学习模型中看到,我们只对“熟悉度”进行了实验,但可以做一个回归问题来解决效价、唤醒和支配。
此外,KNN 模型最初在所有模型中表现最好,但由于数据集(1 个参与者样本)较小,没有一个模型表现得令人难以置信地好。因为这项研究有 32 名参与者,所以将所有的 EEG 信号解释到一个更大的机器学习模型中会很有趣。
参考文献
- A.Gramfort,M. Luessi,E. Larson,D. Engemann,D. Strohmeier,C. Brodbeck,R. Goj,M. Jas,T. Brooks,L. Parkkonen,m . hml inen,使用 MNE-Python 进行脑磁图和脑电图数据分析,神经科学前沿,第 7 卷,2013 年,ISSN 1662–453 x,【DOI】
- 哈斯,L . F .(2003 年)。“汉斯·伯杰(1873–1941),理查德·卡顿(1842–1926),以及脑电图”。神经病学杂志&神经外科杂志。 74 (1): 9。doi:10.1136/jnnp . 74 . 1 . 9。PMC1738204。PMID 12486257 。
- 舍雷尔,“什么是情绪?以及如何衡量它们”,社会科学信息,第 44 卷,第 4 期,第 695-729 页,2005 年。
- 南 Koelstra,C. Muehl,M. Soleymani,J.-S. Lee,A. Yazdani,t .易卜拉希米,T. Pun,A. Nijholt,I .帕特雷,“DEAP:使用生理信号进行情感分析的数据库”, IEEE 情感计算汇刊,系统构建和评估的自然情感资源特刊,正在出版
使用 Codex 将 Keras 翻译成 fastai
作者图片
Codex 能成为深度学习框架的中间人吗?
OpenAI 的 Codex 提供了一组特定于计算机语言的操作,可以用来从英语语言描述中生成代码,自动记录代码,并在编码语言之间进行翻译。在过去的几个月里,我一直在探索 Codex 的能力,包括它从英语提示中生成 web 应用程序的能力和从 COBOL 中生成现代代码的能力。我很好奇 Codex 将如何处理两个不同深度学习框架之间的翻译。
挑战
我有幸写了两本书,一本是关于使用结构化数据的深度学习的,其中展示了用 Keras(tensor flow 的高级深度学习框架)编写的深度学习示例,另一本是关于使用 fastai 的[深度学习的,fastai 是基于 PyTorch 构建的高级框架。在写第二本书的过程中,我需要创建一个现有 Keras 应用程序的 fastai 实现。当我写这本书的时候,我通过反复试验“手工”创建了 fastai 应用程序,直到我得到大致相当于 Keras 代码的工作代码。如果我在写书的时候能够接触到 Codex,我会利用它从 Keras 自动生成 fastai 吗?在这篇文章中,我将描述一个实验来回答这个问题。](https://www.amazon.com/Deep-Learning-fastai-Cookbook-easy/dp/1800208103/ref=sr_1_1?crid=3SYARIO8M3ZU3&dchild=1&keywords=%22deep+learning+with+fastai+cookbook%22&qid=1635994009&qsid=130-4637480-5001025&s=books&sprefix=deep+learning+with+fastai+cookbook+%2Cstripbooks-intl-ship%2C90&sr=1-1&sres=B0971LB85Z&srpt=ABIS_BOOK)
MNIST——深度学习的“你好世界”
你可以解决的最简单的深度学习问题是使用手写数字的 MNIST 数据集来训练一个模型,该模型可以预测手写数字图像中描绘的数字。
来自 MNIST 的示例图像
你可以说,为 MNIST 创建一个模型是深度学习的“你好世界”。
我关于 fastai 的书包含了 MNIST 模型的 Keras 和 fastai 实现的并排比较。这个比较说明了这两个框架之间的差异,并为熟悉 Keras 的开发人员探索 fastai 奠定了基础。
实验
为了锻炼 Codex 从 Keras 翻译到 fastai 的能力,我决定采用我为我的书手工转换成 fastai 的相同的 Keras MNIST 实现,看看 Codex 是否可以正确地完成翻译。
以下是 Keras MNIST 实现的起点,改编自https://github . com/tensor flow/docs/blob/master/site/en/tutorials/quick start/beginner . ipynb:
克拉斯 MNIST 模型
为了让 Codex 将它翻译成 fastai,我使用了以下提示模式:
// Rewrite this as a fastai model[ Keras code goes here ]// fastai version:
食品法典委员会得出的结果看起来像 fastai 一样合理:
fastai 输出从 Keras 输入产生 Codex
我把这段代码复制到了 Colab 笔记本上,但是它不能正常工作。为了让它在 Colab 中正确运行,我需要做两处修改:
- 用笔记本的 include 语句替换 include 语句:
#import fastai
#from fastai.vision.all import *
!pip install -Uqq fastbook
from fastbook import *
from fastai.vision.all import *
- 注释掉编译语句:
#hello_world_model.compile(optimizer=optim.Adam,
# loss_func=nn.CrossEntropyLoss(),
# metrics=[accuracy])
通过这些改变,我能够在 Colab 中成功运行 fastai 代码,并获得一个有效的 MNIST 深度学习模型:
由 Codex 训练 MNIST 模型生成的 fastai 代码
虽然 Codex 生成的 fastai 代码进行了一些小的修改,但它并不完全等同于 Keras 输入代码。特别是,输入的 Keras 代码包括显示测试数据集的模型损失和准确性的语句:
test_scores = hello_world_model.evaluate(x_test, y_test, verbose=2)
print('Loss for test dataset:', test_scores[0])
print('Accuracy for test dataset:', test_scores[1])
Codex 生成的 fastai 代码包括以下语句,用于在测试集上训练模型,但它并不像原始 Keras 代码那样显示聚合结果:
test_dl = dls.test_dl(get_image_files(path/'testing'))preds,_ = learn.get_preds(dl=test_dl)
结论
给定 MNIST 深度学习模型的 Keras 代码作为输入,Codex 能够产生 fastai 代码作为输出(经过几次小的修改),成功训练了 MNIST 深度学习模型。以下是我的主要观察结果:
- 一方面,这令人印象深刻。使用 Keras 框架的代码与使用 fastai 的代码有很大不同,作为一个人,我花了几次尝试,以 Keras 代码为起点,为 MNIST 开发 fastai 代码。Codex 第一次尝试就产生了(几乎)正常工作的 fastai 代码。我不必摆弄提示或对输入的 Keras 代码做任何更改。
- 另一方面,我不得不怀疑 Codex 是否简单地“记住”了作为 github 语料库一部分的 Keras 和 fastai MNIST 实现。例如,我用 fastai 书编写的[深度学习的代码(包括](https://www.amazon.com/Deep-Learning-fastai-Cookbook-easy/dp/1800208103/ref=sr_1_1?crid=3SYARIO8M3ZU3&dchild=1&keywords=%22deep+learning+with+fastai+cookbook%22&qid=1635994009&qsid=130-4637480-5001025&s=books&sprefix=deep+learning+with+fastai+cookbook+%2Cstripbooks-intl-ship%2C90&sr=1-1&sres=B0971LB85Z&srpt=ABIS_BOOK)这个手写的 fastai MNIST 应用和它的同伴 Keras MNIST 应用)自 2021 年年中以来一直在 github 中,所以 Codex 的训练集可能包括了我书中的例子,而 Codex 所做的只是从它在训练集中看到的手写的 MNIST 应用中“查找”fastai 语句。
总的来说,我不得不说,我对 Codex 能够从 Keras 代码中生成(几乎)有效的 fastai 代码印象深刻。甚至将“hello world”从一个框架自动翻译到另一个框架也是一种成就。我期待着用更具挑战性的 Keras 到 fastai 翻译来测试 Codex。
与本文主题相同的视频:https://youtu.be/xUMBiMP4xNw
利用认知科学和教育科学来改善你交流结果的方式
办公时间
提高演讲技巧的八个技巧
由 Austin Distel 在 Unsplash 上拍摄
你们中有多少人在找工作时,在“必备技能”部分看到了“强大的沟通技能”?如果不是特别明确,肯定会有“人际交往技能”或“表达技能”之类的东西。这些在每个行业都很常见,所以最好问一句,你见过不具备上述条件的招聘信息吗?
好消息是,就像其他技能一样,我们可以通过练习和对要点的理解变得更好。在本文中,我们将重点应用认知科学和教育科学中的一些基于证据的结论,以改善我们作为数据科学家和分析师交流结果的方式,尽管这些观点可以推广到任何你发现自己在公开演讲的应用中。如果你想查看原始资料,你可以通读这些 学术 论文。
回到数据科学家;让我们面对现实吧,我们这些花时间埋头于数字的人并不总是最擅长用一种令人信服和易于理解的方式来解释它们。但这有点傻,对吧?无论我们发现模式和做出推论的能力有多好,如果我们不能让团队成员相信这些模式,我们的结果将没有任何影响。作为一个能够应对交流结果这一挑战的人,一个需要对好的演示中隐含的技巧进行一些阐述的人,我发现以下技巧很有帮助。当你浏览这个列表时,我鼓励你思考一下最近的演示如何通过应用来改进。所以,事不宜迟:
1.细致的调查
精心调查“……促使学习者对明确陈述的事实做出解释。”通过提问,我们在社交上吸引了我们的听众(稍后会有更多介绍),并鼓励听众处理正在呈现的信息,增加注意力。作为数据科学家,我们可以通过要求团队成员回忆以前幻灯片或会议的相关结论,或者利用每个人都可能拥有的一些领域知识,来进行精心的调查。精心调查和其他通过提问参与的方法之间的一个重要区别是听者能够回答问题;通过这种技巧,我们有意让听众将相关信息带入他们的头脑中。
2.实践测试
本节的标题不完全具有代表性;我们可能更喜欢在头脑中使用的术语可能是修辞或引导提问。我们不想测试我们听众的知识,因为这会让他们感觉如何,尤其是在一个问题的情况下,我们,演示者,将是唯一知道答案的人,这通常是在演示结果时的情况。然而,标题可能对读者有类似的影响,这导致了这种技术是有益的:
图片来自 knowyourmeme.com
回想一下学校里的考试公告,或者更糟的,可怕的突击测验。它们可能会让你觉得自己很像皮卡丘,感到惊讶并希望你知道更多。学习时的压力显著地促进了记忆的形成,然而,对于记忆回忆来说,情况正好相反。因此,我们对测试同事不感兴趣;事实上,当在演示过程中提问时,我们通常根本不期望他们回答。作为数据科学家,我们将利用这种压力反应以及由此带来的记忆回忆和大脑参与的改善,通过问一些修辞性或引导性的问题。一个有效的实现可以是展示初步数据,并简单地问一些类似这样的问题,“现在,从我们目前所看到的,我们可以推断出什么?”重要的是,在你的问题之后要有一个短暂的停顿,但要足够长,让听众考虑自己的解释和趋势,或者至少足够长,让他们思考,“嗯,我不确定。”然后,转到下一张幻灯片,用你来之不易的洞察力打击他们,在他们的大脑已经准备好接受它之后,他们更有可能记住和理解。
3.心理意象
继续我们的心理参与方法,我们可以使用意象来提高听众处理新信息的能力。毕竟,我们的眼睛是我们感官信息的主要来源。除了你为阐明而创造的美丽的形象化之外,有许多好的资源可以用来制作,要求听众在转述结论时富有想象力也是有帮助的。人类处理图像的速度比文本快 6 万倍,我们的大脑天生就能处理视觉数据。例如,假设你和一群房地产经纪人坐在一个房间里,并解释说,在房子的其他一切保持不变的情况下,我们的模型表明额外的卧室会使房子的售价下降。这可能感觉违反直觉(房地产经纪人也可能像皮卡丘一样看着你),但如果我们让我们的房地产经纪人朋友想象自己站在他们最近出售的房子里,那么建议他们进一步想象,在总面积、浴室数量等没有增加的情况下。,再加一间卧室……嗯,放在哪里合适?为了打造另一个适合居住的卧室,我们必须重新利用现有房间的空间,让它们变得更加拥挤,更多的人最终会共用相同数量的浴室,等等。通过创造心理图像,我们可以用一种相关的、容易理解的方式传达结果,甚至那些一开始可能没有意义的结果。
XKCD 漫画
4.重复和突出显示
虽然教育研究表明这两种方法实际上都不是很好的学习技巧,不管它们有多受欢迎,但我们可以从它们糟糕的原因中获得价值。研究人员认为,突出显示尤其无效,因为你必须已经知道哪些信息是有价值的,才能突出显示正确的信息。幸运的是,我们确实知道什么信息是重要的,可以为我们的观众做重点介绍。这可以通过突出可视化的重要特征来实现,也可以通过将我们的幻灯片文本限制为简洁地捕捉主要思想的几个要点来实现,不过,如果你像我一样,实际的讨论将会冗长得多。最后,虽然我们将在下面进行有效的总结,但我们可以通过在每张幻灯片的结尾收集我们的想法,并通过陈述“继续,但这张幻灯片的主要内容是 _____,稍后您会看到为什么这很重要”来进行简短的总结,从而将重复作为一种突出的类比
5.社会和代理包容
离开时对团队环境感觉积极的听众更有可能关注我们的结果,因为他们更有可能将注意力放在我们身上,并对我们作为同事充满信心。社会包容可以包括指名道姓地提及个人或团队,并在演讲前后到场进行交谈或回答问题(我们都知道我们需要提前到场,以确保我们的演示文稿和演示准备就绪并正常工作!).如果我们碰巧在一天的早些时候看到同事的评论,我们也可以给他们留言,比如,“你会很兴奋地看到我今天下午演示的一些结果!”代理包容,“代理”指的是一个人对其环境施加影响的能力,激励听众在结果中感受到自己的存在,或感受到自己是引导演示流程的一部分。一定要承认其他团队和个人的努力,因为嘿,我们都在一起;创造数据洞察力是我们应该做的。允许观众提问,同时注意尊重时间限制,不要轻视或允许偏离我们精心制作的故事。建议稍后进行进一步的对话,以确保团队不偏离正轨,这是完全可以接受的。提出一个答案是“谢谢你,丽莎,很高兴你问了”的问题,这种感觉总是很棒。看到这种模式,我也想知道……”然后点击下一张幻灯片,上面有漂亮的可视化效果和谈话要点,正是为了满足这种好奇心而准备的。即使他们没有问这个问题,这也是我们真正追求的数据驱动的逻辑流程。
6.为不同的认知风格做好准备
我们需要了解我们的观众。我们是否在与数据团队的其他成员交流?软件部门的朋友,编码背景好但不一定懂数据?或者是销售部门的人,我们依赖他们面对客户的专业知识,或者是你向其解释项目的面试官,他们可能根本没有技术背景?是混合团吗?确保准备演示时考虑到目标受众。此外,在每个小组中,认识到存在不同的认知风格;有些人视觉学得更好,而有些人听觉学得更好。有许多原因,甚至在相似的个体中,为什么一个人的理解力会受到挑战。让我们尽最大努力为回答问题做好准备,记录下我们一路上遇到的困难,同时也考虑到由于我们独特的背景和经历,我们认为理所当然的信息可能会让其他人感到困惑。最后,如果经常向同一群人演示,注意他们问的问题类型和证明有用的可视化。我们可以做很多事情来改善我们的结果沟通,认识到重复的问题或同一类型的多个问题通常意味着我们未能以某种方式在我们的报告中包含必要的信息。
7.让您的结果令人难忘
为了让演示产生持久的影响,帮助提高我们的知名度,并让同事们期待我们未来的成果,我们应该在我们系统的工作环境中设定结果。我们刚刚花时间详细介绍了一个具体的结果;让我们不要忘记提醒每个人为什么我们首先对这个结果感兴趣。如果结果产生进一步的问题,解释未来的探索路径,并在必要时请求其他个人和团队的支持。如果提出问题的解决方案,说明对日常操作程序的影响。然而,作为数据科学家,我们可能不负责有关方向的决策,但我们可以利用这一点来增加我们的演示的普遍性。我们可以问一些问题,比如调查结果会如何影响我们的团队和邻近的团队,或者引发一场关于下一次调查应该关注什么的讨论,此外,我们还可以问一些其他问题,这些问题会让听众离开,通过我们的结论对下一步产生广泛的疑问。以“好吧,让我们在接下来的几天里都考虑一下,然后在我们的下一次会议上再回来”来结束一次会议可能会很好。吸引演示空间之外的同事的注意力,阐明结果的影响,通过增加其他人对其价值的感知,并给他们一个对下一部分好奇的理由,增加他们关注的欲望,使我们的演示更好。
8.摘要
在一次彻底的演讲后,听众会得到很多新的信息。对于回忆和持久的理解来说,重要的是确定想法之间的联系,以及哪些想法和结果是最重要的。花时间做总结,不要从最后一张幻灯片上读出一系列要点。虽然视觉上表现这些点是好的,但我们的口头表达应该以连贯的方式连接这些点,从头到尾总结这个故事。
图片来自 memegenerator.net
在这里,我将尽我所能写一份有效的总结。虽然我们已经介绍了很多技巧,但是所有的技巧都是通过引起听众的注意和让听众参与到信息处理中来实现的。我们通过提问、鼓励对旧问题的反思以及引导他们接受新问题来吸引他们。我们通过包容让他们参与进来;在社交方面,通过创造积极的工作环境;在代理方面,通过形象地回答问题,以个人为基础,并认可他人的贡献。最后,我们让他们参与进来,确保通过有效使用可视化和以重复信息的形式创建“点”作为小摘要来突出重要信息,然后在最终的连贯图片中“连接这些点”。通过这种方式,我们的观众会在离开时感受到我们的结果的价值,以及它在我们整个工作环境中的位置。
如果你已经走了这么远,谢谢你!现在你已经读了这篇文章并且理解了这些技巧…我在写作中使用了它们中的哪一个?我是否遗漏了什么,我的陈述如何才能更好?有没有我做过的有效但没有列在清单上的事情?你有没有最喜欢的老师和演讲者,他们有没有使用这里没有提到的技巧?请在评论中告诉我你的想法!
利用复杂网络改进机器学习方法
使用高级数据分类算法来利用数据的拓扑特征
艾莉娜·格鲁布尼亚克在 Unsplash 上的照片
数据科学为数据科学家工具箱提供了许多不同的范例,如监督学习、非监督学习、时间序列、强化学习等等。要精通所有这些范例是不可能的,但是,对每一个范例都有一个基本的和可行的知识可以帮助我们更好地解决问题。
最近一个为数据科学家提供有洞察力的工具的领域是复杂网络,这是一个专注于研究基于实体之间关系的复杂现象的领域。
在这篇文章中,我将告诉你一些关于复杂网络的知识,以及如何将它们与机器学习算法结合使用,以提高使用 sknet 库进行预测的性能。
复杂网络
让我们从定义什么是复杂网络开始:一个被称为节点的实体的集合,这些节点通过表示某种关系的边相互连接。
如果你在想:这是一个图表!嗯,你是对的,大多数复杂的网络可以被认为是一个图。然而,复杂网络通常会扩展到数千或数百万个节点和边,这使得它们很难用标准的图算法进行分析。
复杂网络和数据科学领域之间有很多协同作用,因为我们有工具来尝试和理解网络是如何构建的,以及我们可以从整个系统中预期什么行为。因此,如果您可以将数据建模为一个复杂的网络,您就有了一套新的工具来应用它。
事实上,有许多机器学习算法可以应用于复杂的网络,也有一些算法可以利用网络信息进行预测。尽管这个交叉点相对较新,但我们已经可以对它进行一些尝试。
因此,为了开始我们连接这两个领域的旅程,现在让我们看看如何将一些表格数据转换成复杂的网络,以及如何对其进行分类。
将数据转化为复杂的网络
从表格数据构建复杂网络的方法有很多。在这里,我将描述一种 KNN 构造方法,该方法使用每个数据点的最近邻来构造网络。
给定一个表格数据集,算法基本如下:
- 选择一个 K 值
- 数据集的每一行都是空间中的一个点,因此将成为一个节点
- 获取空间中的每个点,并计算到其他点的距离
- 从正在评估的节点中选择 K 个最近的节点,并在它们之间绘制一条边
这个想法是连接最近的点。请注意,这种方法不会产生单个节点(没有连接的节点),因为每个节点到另一个节点都有距离。
附注:当用类转换数据时,可能需要每个类都在一个单独的组件上。这是一些算法的要求。
这种方法的脆弱性发生在你有密集的区域,有许多节点彼此靠近。可以想象一个密集的区域也应该是密集连接的,但是 KNN 构造器只会为每个节点创建 K 条边。
还有其他算法试图解决这个问题。一个例子是 Epsilon Radius 构造函数,它在密集区域工作得很好,但是在稀疏区域会产生单值,这就不好了。然后可以结合这两种方法,使用ε半径 KNN 构造函数。所有这些算法都可以在 sknet 库中找到。
高级数据分类
既然我们可以将数据转换成复杂的网络,那么我们该如何利用它呢?嗯,我们可以做很多事情,但在这里,我将侧重于一个特定的算法:高级数据分类。
高级数据分类算法试图将来自传统机器学习算法(如支持向量机和随机森林)的发现与通过分析复杂网络的度量而促进的结构模式识别相结合。
它基本上由两部分组成:
- 一个低级分类器,是我们使用的传统机器学习算法的一个有趣的名字,如支持向量机或 Boosting 算法
- 高级分类器,一种复杂的基于网络的分类机制
然后,该模型将两种结果结合起来生成预测。这里的想法是,复杂网络机制能够识别数据的拓扑方面,而低级分类器将不能容易地识别这些方面。
但是这种复杂的网络机制是如何工作的呢?基本上,对于每个预测点,我们将它添加到网络的每个类组件,并验证该组件的一些度量如何变化。如果变化很小,那么我们确信该点没有改变组件的结构,并且可能从那里开始。然而,如果度量发生了很大的变化,那么这个点就改变了组件的结构,并且可能不属于那里。
人们可以通过设置一个称为 p 的参数来控制高级分类对最终预测的影响程度,该参数是一个介于 0 和 1 之间的值,用于定义高级影响。
关于高级数据分类如何工作的更多细节可以在[1]中找到。
编码
让我们看看如何使用 sknet 库将我们的表格数据转换为复杂的网络,然后利用结构模式识别来尝试和改进我们的标准机器学习算法。
在开始任何编码之前,第一步是使用 pip 安装 sknet 库:
pip install scikit-net
现在,让我们看一下代码:
from sklearn.datasets import load_wine
from sklearn.metrics import accuracy_score
from sknet.network_construction import KNNConstructor
from sknet.supervised import HighLevelClassifierX, y = load_wine(return_X_y = True)
X_train, X_test, y_train, y_test = train_test_split(X, y,
test_size=0.2)
knn_c = KNNConstructor(k=5)
classifier = HighLevelClassifier()
classifier.fit(X_train, y_train, constructor=knn_c)pred = classifier.predict(X_test)
print(accuracy_score(y_test, pred))
如您所见,代码相当简单,但让我们看看每一部分,了解发生了什么:
X, y = load_wine(return_X_y = True)
X_train, X_test, y_train, y_test = train_test_split(X, y,
test_size=0.2)
在这里,我们只是使用 sklearn 库来导入 Wine 数据集,然后将它分成一个包含 20%数据的维持测试集。
knn_c = KNNConstructor(k=5)
classifier = HighLevelClassifier()
classifier.fit(X_train, y_train, constructor=knn_c)
在第一行中,我们将创建一个 KNN 构造函数,它将负责将葡萄酒数据集转换成一个复杂的网络。在下一行,我们正在实例化高级分类器类,就像我们对来自 sklearn 的分类器所做的一样。
最后,我们在训练数据上拟合分类器。注意,我们将构造函数传递给 fit 函数,这样它就知道如何在 fit 期间转换数据。这是库中每个算法的标准方法。
pred = classifier.predict(X_test)
print(accuracy_score(y_test, pred))
最后,我们只是使用拟合的分类器来预测测试集的标签,并将其与真实标签进行比较。
注意这里我没有参数化分类器。为了简单起见,我使用了默认参数,但是,我们能够控制我们将使用哪个低级分类器,我们应该对高级预测赋予多少权重,我们应该对高级分类使用哪些指标,等等。每个参数的列表可以在这里找到。
关于 sknet 库的更多信息
sknet 库的开发旨在弥补在复杂网络上实现机器学习算法的现有差距。它已经提供了将表格数据转换成复杂网络的工具,正如你在这篇文章中看到的,而且还提供了将时间序列转换成网络的工具。它还实现了监督、非监督和半监督算法,可用于从复杂网络中学习或改进现有方法。
希望你喜欢它并测试 lib!
[1] Silva,T.C .,赵,L .基于网络的高层数据分类(2012),IEEE Trans .神经网络。学习。系统。23(6)