建立您的第一个图形神经网络模型来预测 20 分钟内的交通速度
实践教程
循序渐进的编码实践
图形神经网络(GNN)是深度学习的一个活跃前沿,有很多应用,例如交通速度/时间预测和推荐系统。在这篇博客中,我们将建立第一个 GNN 模型来预测旅行速度。我们将使用来自 dgl 库的示例代码运行时空 GNN 模型。
图片由 Caleb Oquendo 从 Pexels
时空 GNN 模型
我们将训练一个在 IJCAI’18 发表的论文中提出的 GNN 模型:
时空图卷积网络:流量预测的深度学习框架 。
本文的总体思想是使用历史速度数据来预测未来时间步长的速度。
图来源:参考文献[1]
参见图 1。每个节点代表一个记录交通速度的传感器站。连接两个节点的边意味着这两个传感器站连接在道路上。代表一个地区交通速度的地理图随时间而变化。我们的任务是使用历史数据,例如从 v_{t-M+1} 到 v_{t} ,来预测未来时间步的速度,例如 v_{t+H} 。这里的 M 是指之前的 M 交通观测值( v_{t-M+1},…,v_{t} ),而 H 是指下一个 H 时间步,例如,在接下来的 30 分钟内。
图来源:参考文献[1]
该模型由一组圣 Conv 块和一个输出层组成。每个圣 Conv 区块由两个时间门控 conv 图层和位于两者之间的空间图形 conv 图层组成。输出图层由 conv、诺姆、conv 和一个完整的 conv 图层组成。
准备洛杉矶 METR 数据集
我们先准备数据集,接下来我会解释。
mkdir <your working directory>
cd <your working directory>
# clone dgl source code
git clone [git@github.com](mailto:git@github.com):dmlc/dgl.git
# clone DCRNN_PyTorch repo, because we need the data folder from it
git clone [git@github.com](mailto:git@github.com):chnsh/DCRNN_PyTorch.git
# copy the data folder from DCRNN_PyTorch repo to dgl repo
cp -r DCRNN_PyTorch/data dgl/examples/pytorch/stgcn_wave/
# go to the stgcn_wave folder
cd dgl/examples/pytorch/stgcn_wave/
然后从这个 Google drive 下载 metr-la.h5 文件,放在 data 的文件夹里。最后,您的目录结构应该是这样的:
.
├── data
│ ├── metr-la.h5
│ └── sensor_graph
│ ├── distances_la_2012.csv
│ ├── graph_sensor_ids.txt
├── load_data.py
├── main.py
├── model.py
├── README.md
├── sensors2graph.py
└── utils.py
请注意,在数据文件夹中,我们只需要 metr-la.h5、graph_sensor_ids.txt 和 distances_la_2012.csv 文件。数据文件夹中的其他文件无关紧要。
METR-拉交通数据集广泛用于交通速度预测。它包含从洛杉矶县高速公路的环形检测器收集的交通信息。选择了 207 个传感器,数据集包含从 2012 年 3 月 1 日到 2012 年 6 月 30 日收集的 4 个月的数据。
文件 graph_sensor_ids.txt 包含传感器的 id。文件 distances_la_2012.csv 包含传感器之间的距离。这两个文件用于创建一个邻接矩阵,然后使用 dgl 库创建一个图。
METR-洛杉矶数据集的传感器分布(图来源:参考文献[2])
文件 metr-la.h5 包含一个形状为[34272,207]的数组,其中 34272 是时间步长的总数,207 是传感器的数量。该数组仅包含速度数据,这意味着 GNN 模型使用历史速度来预测未来速度。不涉及其他特征(道路类型、天气、节假日)。用传感器每 5 分钟记录一次速度。207 个传感器分布在区域内的道路上。分布见上图。每 5 分钟收集一次速度。所以一天应该有 24*(60/5)=288 条记录。因此,一天的数据只是一个形状数组[288,207],其中 288 是总时间步长,207 是传感器的数量。由于数据是在 4 个月内收集的,在可选的数据清理之后,总共有 34272 个时间步长。下面是前 5 行。标题是传感器的 id,内容的值是速度。
文件 metr-la.h5 的标题和前 5 行
为了使数据适应机器学习,我们需要准备特征 X 和目标 Y 。对于每个样本(时间步长 t ),特征 X 是其从 t-144 到 t-1 (12 小时)的过去 144 个时间步长的速度历史。假设我们有 N 个样本,那么 X 的形状就是 N,144,207 。目标 Y 是未来时间步的速度,比如说 t+4 ,那么 Y 的形状就是 N,1,207 。现在我们有了( X,Y )对,我们可以把它们馈送给 ML。
培训、验证和测试
现在我们已经准备好训练、验证和测试了。
首先,创建一个虚拟环境并安装软件包。你需要访问这个链接来选择你合适的 dgl 包。
conda create -n stgcn_wave python=3.6
conda activate stgcn_wave
pip install dgl-cu102 -f [https://data.dgl.ai/wheels/repo.html](https://data.dgl.ai/wheels/repo.html)
pip install torch
pip install pandas
pip install sklearn
pip install tables
然后我们可以通过以下方式运行 main.py
# maybe you need to adapt your batch size to suit your GPU memory
python main.py --batch_size 10
main.py 一次性完成训练、验证和测试。它使用 pytorch 作为 ML 框架。总的来说,使用 NVIDIA GeForce GTX 1080 显卡需要将近一天的时间。
作为评估行驶速度预测模型的常用方法,脚本中使用了平均绝对误差(MAE)、平均绝对百分比误差(MAPE)和均方根误差(RMSE)。下面是我日志的结尾:
我的日志截图
MAE (6.68)接近于 dgl 库的自述文件中声称的版本(~5.76)。如果我能够使用默认的批处理大小(50)运行,我可能会得到更接近的结果。
参考文献:
[1]冰雨,郝腾银,朱占兴,时空图卷积网络:一个用于流量预测的深度学习框架,2018,IJCAI。
[2],Rose Yu,Cyrus Shahabi,,扩散卷积递归神经网络:数据驱动的交通预测,2018,ICLR。
用卷积神经网络(CNN)构建您的第一个图像分类器
CNN tensor flow 初学者指南
图片由皮克斯拜的 Gerd Altmann 提供
卷积神经网络(CNN)是一种深度神经网络,主要用于图像分类和计算机视觉应用。本文将通过使用 Python 中的 TensorFlow 包实现 CNN,引导您创建自己的图像分类模型。
一个简单的神经网络有一个输入层、一个隐藏层和一个输出层。深度神经网络可以有两个或多个隐藏层。卷积神经网络具有卷积层,其后是完全连接的神经网络。层的类型及其功能将在后续章节中解释。
简单的神经网络或完全连接的层
简单的神经网络(图片由作者提供)
上图中突出显示的部分显示了一个神经元。神经元是神经网络的基本元素。神经元接受输入,对其应用权重来预测输出。隐藏层中的每个节点都是前一层(在本例中为输入层)输出的函数。用于获得隐藏层输出的函数被称为激活函数。最后,输出 y 通过将权重应用于隐藏层的每个节点并通过应用适当的激活函数将它们组合而获得。
CNN 的架构
基本 CNN 的架构(图片由作者提供)
卷积层从图像(输入)中提取特征。一个小的过滤器或内核扫描整个图像并提取特征,例如,一条垂直线或一条水平线,并创建一个特征图。卷积层之后的层是池层。汇集图层实质上是对卷积图层提取的要素地图进行缩减采样。由卷积图层提取的要素地图包含要素的准确位置。这可能会导致过度拟合。池图层在整个要素地图中运行过滤器。它只从该筛选器中获取特定信息,根据所选的池化方法,可以是筛选器下的平均值,也可以是最大值。这减小了要素地图的空间大小,并将要素的精确空间信息转换为粗略信息。这有助于防止过度拟合。根据输入数据集的复杂程度,任何卷积和池化图层都可以堆叠在一起。最终的池层随后被展平并转换为一维数组,然后被提供给预测输出的完全连接的层。这是卷积神经网络架构的总结。在接下来的步骤中,我们将使用该算法实现它来构建我们的第一个图像分类器。
履行
我们将使用 Keras 的 MNIST 数据库来训练该模型,以对手写数字进行分类。MNIST 数据库由大小为 28x28 的手写数字的黑白图像组成。让我们从导入和可视化数据集开始。此外,我们还通过将整个数据集除以 255 来标准化数据。这是因为数据集中的值范围是从 0 到 255。进行归一化是为了使整个数据集达到共同的比例。
下面是存储在数据库中的图像示例。
存储在 MNIST 数据集中的手写数字图像(作者提供的图像)
现在我们已经完成了数据集的导入和规范化,让我们继续构建模型。下面是我们将要建立的模型的示意图。
我们的模型将包含三组卷积和池层以及两个完全连接的层。上一节解释了每种类型层的功能。上面的示意图可以用 python 实现,如下所示。
“过滤器”参数定义卷积层的深度:叠加在一起形成一个卷积层的特征地图的数量。我们使用的内核大小为 3x3,除了最后一层,所有层的激活函数都被设置为 relu,简称为整流线性 **激活函数。**我对最后一个密集层使用的是 softmax 激活,基本上给出了每一类的概率分布,根据其概率可以预测出正确的类。点击 链接 可以了解更多关于激活函数的信息请注意,只有第一层需要“input_shape”参数。这必须是输入的大小。在这种情况下,input_shape 参数是(28,28,1),这是输入图像的大小。密集层中的“单位”参数是节点的数量。最后一层中单元的数量必须基本上等于输出类的数量。在我们的例子中,输出类的数量是 10 (0 到 9)。
我们已经定义了一个函数来构建模型。下一步将是优化模型,调整权重以最小化损失。我们将定义一个函数来编译带有优化器和损失函数的模型,以获得最佳权重。你可以从这里 了解更多关于优化器的知识
好了,我们已经定义了一个函数来建立模型并编译模型。我们唯一剩下的就是用我们的数据集来训练模型。在下一步中,我们将定义一个函数来训练模型。在下面的代码片段中,“epochs”是算法遍历整个数据集的次数。“x”和“y”是训练数据集和相应的标签。
让我们通过使用合适的参数调用每个相应的函数来总结所有三个部分(构建、编译和训练)。在将数据集输入模型之前,我们必须执行一些小的数据预处理。MNIST 的输入数据是 28x28 的形状。然而,灰度图像是 28×28×1 的形状。因此,我们必须将训练和测试数据调整为 28x28x1。此外,存储在 train_y 和 val_y 变量中的数字的标签是数字的。这些数字必须被视为绝对的,因为我们有 10 个不同的类别(0 到 9)。因此,我们将把标签编码成二进制;例如,0 将编码为[0,0,0,0,0,0,0,0,0],1 将编码为[1,0,0,0,0,0,0,0],2 将编码为[0,1,0,0,0,0,0,0,0]等等。
唷…在没有强大 GPU 的情况下,花了一段时间来训练模型(我没有使用 google collab 这样的云服务)。在上面的代码片段中,“model.save”命令将训练好的模型保存在根文件夹中,稍后可以加载该模型来预测输入,而无需再次重新训练整个模型。所以,我们的模型被建立和训练。让我们来看看它的性能。
该模型经过训练,上面的图显示它表现得相当好。任务完成了吗?还没有。在我们知道如何使用模型来解决问题之前,模型是没有用的。在下一节中,我简要介绍了如何使用之前训练过的模型对手写数字进行分类。为了实际测试该模型,我在一张纸上草草写了一个数字,使用 OpenCV 处理图像,使其与我们用来训练模型的图像一致,并将其传递给模型。可以看到原始图像和处理后的图像。我承认我本可以在图像处理方面做得更好😬。但目的是测试模型,我相当有信心 CNN 将能够对处理后的图像进行分类(相信我,神经网络相当强大)。
输入图像的处理和图像类别的预测
瞧啊。现在你知道用卷积神经网络建立一个图像分类器。您可以随意选择层数和相关参数、时期数等。,并决定什么是最好的。类似的方法可以应用于更复杂类型的图像。一旦你习惯了对手写数字进行分类,你就可以将这种方法应用到来自“https://keras.io/api/datasets/fashion_mnist/”的 MNIST 时装数据集中。
我希望这篇文章对你有用。从https://www.linkedin.com/in/vipul-kumar-03241b102/通过 LinkedIn 与我联系,分享和讨论更多与数据科学相关的技能。
使用 Streamlit 构建您的首个交互式数据科学 Web 应用
突出一些最常见的特征
Web 应用程序是展示您的数据科学工作的最便捷的方式之一。对于许多没有任何 web 开发经验的数据科学家来说,构建 web 应用程序可能会令人望而生畏。然而,有了 streamlit 框架,web 应用程序对数据科学家来说不再困难——如果你了解 Python,你可以用 streamlit 构建交互式 web 应用程序——这个令人敬畏的框架为我们在幕后制作和布局 web 元素做了艰苦的工作。我们将只关注数据部分。
要安装 streamlit 框架,请使用 pip 工具。
pip install streamlit
一旦安装完毕,你就可以检查它的版本。
streamlit --version
如果您已经正确安装了 streamlit,您可以通过运行以下命令来运行演示应用程序。在应用程序中,您将有机会看到使用 streamlit 框架可以实现的各种可能性。
streamlit hello
在演示应用程序中,你会发现 streamlit 框架支持这么多很酷的功能,而这些功能是数据科学家通常需要的。在这篇文章中,我想提供一个简短的教程来开始使用这个令人敬畏的 web 框架。我敢打赌,如果你了解 Python,你只需要几个小时就能对这个工具有一个合理的理解。
如果你想跟随这个教程,你可以在 GitHub 页面这里找到这个脚本。出于本教程的目的,我们将使用 Titanic 数据集来展示一些常见的 streamlit 技术,重点是交互式小部件。
在适用的地方,我还会集成一些可选的小部件,这样您就可以在这个过程中了解更多。
项目设置
每个 streamlit web 应用的核心都是一个 Python 脚本。在文件的顶部,我们导入必要的依赖项。在这种情况下,我们将使用多个模块,如下所示。
import pandas as pd
import time
import streamlit as st
import plotly.express as px
在数据集方面,我们将使用泰坦尼克号数据集,我们将从互联网上下载。
加载数据
一个值得注意的特性是装饰器st.cache
的使用,这将提高 web 响应能力,因为缓存了之前获取的数据。在这种情况下,titanic 数据集将只被获取一次,并且随着网页的刷新,它将不会被再次获取。与此相关,应该注意的是,一旦代码中有任何更改,脚本将再次运行,因此利用缓存功能对于改善用户体验至关重要。
要查看数据,我们可以简单地运行st.dataframe(titanic_data)
,您将看到如下所示的内容。
数据概述
1.组织元素(如标题)
在 streamlit 中,有几种方法可以给你的网页添加标题。要给页面添加标题,可以运行:st.title(“My First Streamlit App”)
。
要在两个不同的级别添加额外的标题,您可以使用st.header()
和st.subheader()
。
或者,你可以利用减价功能,你可以添加像st.markdown(“#Just like a header”)
和st.markdown(“#Just like a subheader”)
这样的标题。
除了标题之外,streamlit 中一个重要的组织元素是侧边栏,您可以在其中添加配置元素来修改主页上显示的元素。要添加侧边栏,只需在脚本中添加st.sidebar
。值得注意的是,您可能会在侧边栏中添加更多的元素。因此,与其使用st.sidebar
来引用侧边栏,不如创建一个对侧边栏的引用,类似于sidebar = st.sidebar
。
2.多选择小工具
为了收集用户的反馈,我们有几个选项来创建多选择小部件。第一个小部件是单选按钮。
单选按钮代码
您将看到如下所示的内容。请注意,所选选项将是所显示选项的实际值,而不是所选的数字索引。在这种情况下,它将是文本。
用单选按钮选择选项
第二个小部件是**selectbox**
,它提供了一个下拉列表,您可以从中进行选择。代码会是这样的。
selected_sex = st.selectbox("Select Sex", titanic_data['sex'].unique())
st.write(f"Selected Option: {selected_sex!r}")
交互将如下所示。
用选择框选择选项
当您要求用户输入多选时,您应该使用**multiselect**
小部件,如下所示。
selected_decks = st.multiselect("Select Decks", titanic_data['deck'].unique())
st.write("Selected Decks:", selected_decks)
对于这个小部件,您将看到类似下面的内容。
多选小工具
3.与数字相关的部件
当您需要收集数字作为输入时,我们可以使用**number_input**
小部件。和往常一样,您可以命名小部件并为其设置一个值。
数字输入码
在代码中,我还在 streamlit 中包含了一个“通知”特性。当你想显示一条错误消息时,你使用st.error()
,而要显示一条成功消息,你使用st.success()
。另一个包含的特性是使用列(st.beta_columns),这在您拥有彼此密切相关的并行小部件时非常有用。在这种情况下,将收集最小和最大年龄的两个小部件组合在一起是合理的。
使用上面的代码,我们将看到一个如下所示的小部件。
数字输入
除了这个小部件之外,streamlit 还提供了一个 slider 小部件,允许用户在不键入任何内容的情况下指定数字输入。这是代码。
滑块
使用slider
小部件,您可以指定小部件的名称。同时,设置最小值和最大值。除了 slider 小部件,上面的代码还包含了另一个叫做 expander 的特性(st.beta_expander
)。当您想要隐藏一些可选的小部件时,这个特性非常有用。您可以指定是否希望扩展器默认扩展。
下图向您展示了这样一个交互式滑块小部件。
滑块和扩展器
4.文本相关的小部件
为了收集文本数据,我们可以使用**text_input**
和**text_area**
小部件。主要区别在于,text_input
小部件适合收集简短的文本字符串,而如果您想要收集大量的文本数据,则首选text_area
小部件。
文本输入部件
上面的代码向您展示了如何显示这些小部件。我还包括了两个额外的特性。一个是代码显示小部件(st.echo
),除了小部件之外,它还将显示包含在with
语句中的代码。另一个特色是一个复活节彩蛋,就是发射一堆气球(st.balloons
)。这样的功能见下图。
文本输入部件
5.一些其他功能的亮点
进度条代码如下所示。
进度条—代码
这是进度条在应用程序中的样子。
应用程序中的进度条
MarkdownStreamlit 支持 Markdown 条目,为我们创造了很多可能性。要使用这个特性,您只需使用st.markdown
。要了解更多关于 markdown 语法的信息,你可以去 GitHub 。
下面是一些常用的例子。
降价示例
Plots 这里有一个列表,摘自其官方文档。
write(mpl_fig): Displays a Matplotlib figure.
write(altair): Displays an Altair chart.
write(graphviz): Displays a Graphviz graph.
write(plotly_fig): Displays a Plotly figure.
write(bokeh_fig): Displays a Bokeh figure.
下图是用 Plotly 制作的一个图形。
Plotly 制作的直方图
结论
在本文中,我们回顾了一些有用的特性,您应该将它们包含在您的交互式 web 应用程序中。正如您所看到的,streamlit 提供了各种功能,允许您收集数字、文本、多项选择选项,并显示代码、降价和数字。有了 streamlit,您几乎不用担心 web 元素。你只需要专注于构建网络应用的内容。
用 Python 在 7 分钟内构建您的第一个机器学习模型
使用熊猫、NumPy 和 Scikit-学习
马塞尔·埃伯勒在 Unsplash 上的照片
当我刚开始学习数据科学时,机器学习听起来像是一门极其困难的学科。我正在阅读一些有着奇特名字的算法,比如支持向量机、梯度推进决策树、逻辑回归等等。
我很快就意识到,所有这些算法本质上都是在捕捉变量之间的关系或数据中的底层结构。
有些关系非常清楚。例如,我们都知道,在其他条件相同的情况下,汽车的价格会随着车龄的增长而下降(经典款除外)。然而,有些关系并不那么直观,不容易被我们注意到。
想简单点,先学基本面。
在本文中,我们将创建一个简单的机器学习算法来预测客户流失。我也会解释一些你需要额外注意的基本要点。因此,我们不仅要练习,还要学习一些理论。
我们将使用 Python 库。更具体地说,Pandas 和 NumPy 用于数据争论,Scikit-learn 用于预处理和机器学习任务。
数据集可以在 Kaggle 上以无版权的知识共享许可获得。让我们从读取数据集开始。
import numpy as np
import pandas as pddf = pd.read_csv("/content/Churn_Modelling.csv")print(df.shape)
(10000, 14)df.columns
Index(['RowNumber', 'CustomerId', 'Surname', 'CreditScore', 'Geography', 'Gender', 'Age', 'Tenure', 'Balance', 'NumOfProducts', 'HasCrCard','IsActiveMember', 'EstimatedSalary', 'Exited'],
dtype='object')
数据集包含 10000 行和 14 列。我们应该使用其他 13 列来预测客户流失(即退出= 1)。退出的列称为目标变量或独立变量。其他列称为特征或因变量。
行号、姓氏和客户 id 是多余的特性,所以我们可以删除它们。客户的 id 或他们的姓氏对客户流失没有影响。
df.drop(["RowNumber","CustomerId","Surname"], axis=1, inplace=True)df.head()
df(作者图片)
编码分类变量
典型的数据集包含分类变量和数值变量。很大一部分机器学习算法只接受数字变量。因此,对分类变量进行编码是一项常见的预处理任务。
我们的数据集包含两个分类变量,即地理和性别。让我们检查这些列中的不同值。
df.Geography.unique()
array(['France', 'Spain', 'Germany'], dtype=object)df.Gender.unique()
array(['Female', 'Male'], dtype=object)
将这些值转换成数字的一种方法是给每个值分配一个整数。例如,法国是 0,西班牙是 1,德国是 2。这个过程称为标签编码。
这种方法的问题在于,算法可能会将这些数字视为一种层级关系。德国被认为比法国有更高的优先权。
为了克服这个问题,我们可以使用一种叫做一键编码的方法。每个不同的值都表示为一个二进制列。如果“地理”列中的值是“法国”,则只有“法国”列的值为 1。其他的变成零。
熊猫的 get_dummies 函数可以用来完成这个任务。
geography = pd.get_dummies(df.Geography)gender = pd.get_dummies(df.Gender)df = pd.concat([df, geography, gender], axis=1)df[["Geography","Gender","France","Germany","Spain","Female","Male"]].head()
一键编码(图片由作者提供)
探索性数据分析
在设计和实现模型之前,探索性数据分析是至关重要的一步。目标是全面了解手头的数据。
我们将通过一些控制来完成这一步。随着经验的积累,您将花费越来越多的时间来探索数据。
探索性数据分析的典型任务是检查数值变量的分布。您还可以用这种方法检测异常值(即极值)。
直方图对于检查变量的分布非常有用。您可以使用 Seaborn 或 Matplotlib 等数据可视化库。我更喜欢用熊猫,因为制作基本情节很简单。
让我们从平衡栏开始。
df.Balance.plot(kind="hist", figsize=(10,6))
余额列的直方图(作者提供的图片)
好像很多顾客都是零余额。将该列转换为二进制可能更好,0 表示无余额,1 表示正余额。
我们可以使用 NumPy 的 where 函数来完成这项任务,如下所示:
df.Balance = np.where(df.Balance==0, 0, 1)df.Balance.value_counts()
1 6383
0 3617
Name: Balance, dtype: int64
三分之一的客户余额为 0。
我们也来画年龄栏的直方图。
df.Age.plot(kind="hist", figsize=(10,6))
年龄列的直方图(按作者分类的图像)
它接近正态分布。高于 80 的值可能会被视为异常值,但我们现在不会关注检测异常值。
随意探索其他数字变量的分布,如任期、产品数量和估计工资。
缩放数值变量
您可能注意到,数值变量的取值范围非常不同。年龄值小于 100,而估计工资超过 1 万。
如果我们按原样使用这些特性,模型可能会赋予具有较高值的列更多的重要性。因此,最好将它们缩放到相同的范围。
一种常见的方法是最小-最大缩放。最高值和最低值分别缩放为 1 和 0。介于两者之间的部分会相应地缩放。
还有更高级的扩展选项。例如,对于具有极值的列,mix-max 缩放不是最佳选择。然而,我们现在将坚持简单的情况。这里的重点是强调特征缩放的重要性。
在引入另一个非常重要的主题后,我们将执行特征缩放。
列车测试分离
机器学习模型通过训练来学习。我们向模型输入数据,它学习变量之间的关系或数据中的结构。
一个模型训练好之后,就要进行测试。但是,用模型训练的数据来测试模型是不可接受的。这类似于作弊。一个模型可能只是记住数据中的一切,并给你 100%的准确性。
因此,在训练模型之前,通常的做法是留出一部分数据用于测试。应该使用测试数据来评估模型性能。
这里重要的是,一个模型不应该有任何关于测试数据的信息。因此,我们在上一步中讨论的特征缩放应该在分割训练集和测试集之后进行。
我们可以手动或使用 Scikit-learn 的 train_test_split 函数来完成此操作。
from sklearn.model_selection import train_test_splitX = df.drop(["Exited","Geography","Gender"], axis=1)y = df["Exited"]X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=42)
X 包含特性,y 包含目标变量。默认情况下,整个数据的 25%被留出用于测试。您可以使用 test_size 或 train_size 参数来更改此比率。
X_train.shape
(7500, 13)X_test.shape
(2500, 13)
我们现在可以进行特征缩放。Scikit-learn 的 MinMaxScaler 函数可用于此任务。我们将创建一个 Scaler 对象,并用 X_train 训练它。
然后,我们将使用经过训练的缩放器来变换(或缩放)X_train 和 X_test。因此,模型不会得到任何关于测试集的提示或信息。
from sklearn.preprocessing import MinMaxScalerscaler = MinMaxScaler()scaler.fit(X_train)X_train_transformed = scaler.transform(X_train)X_test_transformed = scaler.transform(X_test)
模特培训
这部分其实包括两个步骤。第一个是选择算法。有几种机器学习算法。它们都有一些优点和缺点。
我们无法在一篇文章中涵盖所有算法。所以我们会选一个继续。逻辑回归算法是二元分类任务的常用算法。
Scikit-learn 的这一过程如下:
- 创建一个逻辑回归对象,这是我们的模型
- 用训练集训练模型
- 基于特定的度量在训练集和测试集上评估其性能
以下代码将执行所有这些步骤:
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score# Create a model and train it
model = LogisticRegression()
model.fit(X_train, y_train)# Make predictions
y_train_pred = model.predict(X_train)
y_test_pred = model.predict(X_test)# Evaluate model performance
print(accuracy_score(y_train, y_train_pred))
0.78print(accuracy_score(y_test, y_test_pred))
0.80
我们的模型在训练集和测试集上分别达到了 78%和 80%的准确率。肯定是可以改进的。
提高模型性能的一些方法有:
- 收集更多数据
- 尝试不同的算法
- 超参数调谐
在本文中,我们将不讨论模型改进。我认为最有效的方法是收集更多的数据。其他两种方法的潜在改进是有限的。
结论
我们已经介绍了创建机器学习模型的基本工作流程。在真实案例中,每一步都更加详细和深入研究。我们只是触及了表面。
一旦你熟悉了基本的工作流程,你就可以专注于改进每一步了。
建立一个像样的机器学习模型是一个迭代的过程。性能评估后,您可能需要多次修改模型或特征。
你如何评价一个分类模型也是非常关键的。在许多情况下,我们不能只使用一个简单的准确性指标。我之前写过一篇关于如何最好地评估分类模型的文章。
感谢您的阅读。如果您有任何反馈,请告诉我。
零配置构建您的第一个机器学习模型——探索 Google Colab
开始你的机器学习之旅就是这么简单。
机器学习(ML)是一种趋势,每个公司都希望利用 ML 来帮助他们改善产品或服务。因此,我们一直在观察对 ML 工程师不断增长的需求,这种需求已经吸引了许多人的注意。然而,对于许多人来说,ML 可能听起来令人生畏,尤其是对于那些几乎没有编码或数据相关工作经验的人。
一个可能的原因是设置计算机需要大量的努力,允许他们开发任何 ML 模型。在本文中,我想介绍 Google Colab,这是一个用于学习和构建 ML 模型的免费工具(尽管有付费升级选项)。更重要的是,你会发现,它对你来说是零配置——现在就可以使用——唯一的要求是你有一个谷歌账户。如果你还没有,请注册,这样你就可以跟随教程。
我假设你不太了解 ML,但是非常热衷于学习 ML。你懂多少 Python 其实并不重要。我会尽可能用外行人的语言解释主要步骤。
事不宜迟,让我们开始吧。如果你想看源代码,你可以使用链接访问笔记本。
第一步。在 Colab 中创建笔记本
在 Colab 中,您使用笔记本(。ipynb),就像你处理文档(。docx)在微软 Word 中。所以,使用 Colab 的第一步是创建一个新的笔记本,方法是转到:https://colab.research.google.com/。
Colab 中的新笔记本(图片由作者提供)
点击“新建笔记本”按钮后,您会看到 Colab 创建了一个新的笔记本,默认名称为Untitled1.ipynb
。为了现在的教程,姑且称之为first_ml_model.ipynb
。
从现在开始,我们将在这个笔记本上工作。
第二步。导入依赖关系
当我们构建模型时,我们需要经验丰富的 ML 开发人员开发的代码库。本质上,这些库通过提供用于处理数据和构建模型的预定义功能来充当工具集。在本教程中,我们将主要使用以下库。
- scikit-learn :一个 ML 库,由各种数据处理函数和 ML 算法(例如回归、分类和聚类)组成。这个库也称为 sklearn,我们将使用 sklearn 作为参考。
- pandas :一个数据科学库,主要用于在构建 ML 模型之前预处理类似电子表格的数据。
在 Google Colab 的笔记本中,每个工作单元被称为一个细胞,我们使用一系列细胞来完成我们的 ML 工作。在每个细胞中,我们通常做一个特定的任务。要添加单元格,只需点击顶部的+ Code
,如下所示。您可以点击+ Text
添加自己的代码注释。
添加代码单元格(图片由作者提供)
使用创建的代码,通过运行下面的单元,您可以导入本教程所需的库。
导入依赖项(按作者排序的图像)
顺便提一下,如果您试图为 ML 配置一台计算机,您需要在配置 Python 的基础上安装所有这些依赖项。
第三步。工作数据集
在当前教程中,我们将使用红酒质量数据集。你可以在kaggle.com找到关于这个数据集的更多信息,这是一个流行的数据科学和 ML 网站,以一系列比赛为特色。您还可以在领先的 ML 数据存储库 UCI 上找到数据集的信息。
wine 数据集经常被用作展示 ML 模型的例子,因此,在 sklearn 中可以方便地获得它。请注意,sklearn 中的数据集已被修改,以更好地作为 ML 训练和学习的玩具数据集。数据如下所示。
葡萄酒数据框架(图片由作者提供)
上面的截图向您展示了数据的特征。在 ML 中,我们使用特征来研究哪些因素对于正确的预测可能是重要的。正如你所看到的,有 12 种特性可供选择,它们对红酒的质量有潜在的重要性,比如酒精和苹果酸。
一个特定的 ML 与分类有关。每个数据记录都有一个显示其类别的标签,所有记录的类别都被称为数据集的“目标”。在红酒数据集中,标签有三类,我们可以检查标签,如下所示:
红酒数据集—目标(图片由作者提供)
请注意,在典型的管道中,我们通常需要花费大量时间来准备数据集。一些常见的准备工作包括异常值识别和移除/重新编码、缺失数据处理、一键重新编码(某些模型需要)、降维、特征选择、缩放等。因为数据集在 sklearn 中已经被清理为玩具数据集,所以我们不需要担心这些准备工作。
第四步。训练模型
下一步是训练 ML 模型。你可能想知道训练一个 ML 模型有什么意义。嗯,对于不同的用例,有不同的用途。但总的来说,训练一个 ML 模型的目的或多或少是为了对他们从未见过的东西做出预测。这个模型是关于如何做出好的预测。创建模型的方法称为训练,即使用现有数据来确定进行预测的适当方法。
有许多不同的方法来建立一个模型,如 K-最近邻、SVC、随机森林和梯度推进,仅举几例。为了让本教程向您展示如何使用 Google Colab 构建 ML 模型,我们只使用 sklearn 中现成的模型——随机森林分类器。
需要注意的一点是,因为我们只有一个数据集。为了测试模型的性能,我们将数据集分成两部分,一部分用于训练,另一部分用于测试。我们可以简单地使用train_test_split
方法,如下所示。训练数据集有 142 条记录,而测试数据集有 36 条记录,比例大约为 4:1(请注意,test_size=0.2
表示原始数据集的 20%(如果需要,可以取整)用于测试)。
分割数据集(按作者分类的图像)
sklearn 的好处是,它通过预先配置许多分类器来为我们做大量繁重的工作,这样我们只需几行代码就可以使用它们。在下面的截图中,我们首先创建一个随机森林分类器。本质上,它为我们建立了一个框架,我们可以将数据放入其中来构建模型。
创建随机森林分类器
使用 classifier.fit,我们正在训练该模型以生成该模型的参数,以便该模型可用于未来预测。
第五步。做出预测
通过 sklearn 的训练模型,我们可以在我们之前创建的测试数据集上测试模型的性能。如下所示,我们实现了 97.2%的预测准确率。请注意,在玩具数据集中达到这样的高水平并不罕见,但在实际项目中被认为是非常高的。
预测准确度(图片由作者提供)
如果您想更仔细地查看我们模型的预测,您可以运行下面的代码,这样我们就有了一个更完整的预测模型性能报告。
分类报告(图片由作者提供)
您可能会注意到,有几个术语您可能不熟悉,比如精度和召回。您可能会发现关于这些术语和分类模型的相关讨论。
结论
在本文中,我使用 Google Colab 作为代码编辑器,向您展示如何构建 ML 模型来对玩具数据集进行预测。它甚至可能没有触及所有重要的 ML 概念的表面。然而,它确实向您展示了 Google Colab 是一个易于使用的工具,只需要最低限度的配置就可以开始您的 ML 学习之旅。
当您熟悉 Google Colab、Python 和 ML 相关的术语和概念时。您可以探索其他 Python IDEs,如 PyCharm,以获得更高级的 ML 工作和更好的编码体验。
感谢阅读这篇文章。通过注册我的简讯保持联系。还不是中等会员?通过使用我的会员链接支持我的写作(对你没有额外的费用,但是你的一部分会费作为奖励由 Medium 重新分配给我)。
用 Python 构建你的第一个基于情绪的音乐推荐系统
实践教程
使用 Spotify API 从头开始基于音频的推荐
照片由阿莱娜·达梅尔拍摄
为什么要建立基于情绪的推荐系统?
虽然音乐流派在建立和展示社会身份方面发挥着巨大的作用,但在音乐偏好领域,歌曲的情感表达以及更重要的是,它对听众的情感印象往往被低估。
流派是不够的
仅仅几十年前,按流派和/或艺术家选择音乐是唯一的选择。想听现场音乐?好吧,选择一个艺术家或者一个典型的基于流派的节日。想买音乐?好吧,看看我们按流派分类的 CD 架,挑一张你喜欢的艺术家的专辑。随着数字音乐平台上定制或预先策划的播放列表和个人推荐的出现,这种情况发生了巨大变化。
因此,如果你的目标是建立一个音乐推荐系统,你将需要找到一种超越流派标签的思维方式,并且——更困难的是——找到量化的方法来将你的想法实现为一个真正有用的推荐工具。推荐方法有两个主要分支:
协同过滤:
在这里,我们对用户行为进行建模,以预测在特定情况下特定用户在统计上可能喜欢什么。这包括“其他人也买了 X”以及考虑到整体受欢迎程度。最后,一个随机的用户很可能比活结更喜欢德雷克。尤其是如果我们已经知道他喜欢其他说唱艺人。
基于内容的过滤
另一种方法是从音乐对象本身检索数据。这可以是元数据,如发行日期、指定的流派或歌曲发行时使用的标签。另一方面,我们也可以从音频本身检索出或多或少的抽象音乐特征。这包括明显的方面,如音调或速度,但也包括高度抽象的数学特征,如 MFCCs,在某种程度上,它是对音乐音色的测量(GER:“Klangfarbe”,EN:“声音的颜色”)。
在这篇文章中,我将向你展示一种无需任何机器学习就能构建有效推荐系统的简单方法。嗯……至少你那边没有。
从哪里获取音频数据?
使用现有算法或机器学习模型从 MIR ( 音乐信息检索)研究中提取音频数据,对于该领域的初学者来说是一件困难的事情。幸运的是,一些聪明人构建了 API 来与我们分享他们的数据,这样我们就可以用它来构建创新技术。
图 1: 节选 Spotify Web API 关于可用音频功能的文档。
Spotify Web API 是一个很好的起点。它可以免费使用,正如你在图 1 中看到的,它提供了多种情绪特征,这些特征是从它们内部的机器学习模型中提取出来的。但是,我们究竟如何用“可跳舞性”、“效价”、“能量”和“节奏”(后者很难被视为情绪特征)来模拟情绪的复杂性呢?实际上,我们只需要其中的两个。
心理学:效价唤醒平面
图 2: 价唤醒平面和其上几种情绪/心境的位置(改编自 Russel,1980)
情绪的因素结构(即情绪存在多少个独立维度)的一个占主导地位的心理学模型是**价-唤醒平面(图 2)。**这是一个二维模型,将每一种现有的情绪或心情还原为其唤醒成分(这种感觉是高能还是低能?)及其化合价成分(感觉好还是不好?).尽管这种模式并非没有问题(例如,恐惧和愤怒在这里会被放在一起),但它被广泛采用,因为它在复杂性和预测能力之间取得了巨大的平衡。
这里令人惊讶的是,我们可以很好地采用价-唤醒平面模型,使用 Spotify API 的“价”和“能量”功能。在本文的其余部分,我将介绍如何从 API 抓取数据,以及如何用它实现一个简单有效的推荐系统。
如何使用 Spotify API 创建数据集
授权(烦人的部分)
让我们从最无趣的部分开始:要访问 Spotify API,你需要按照本指南注册一个应用程序。或者,看看这篇中型文章,其中很好地说明了这个过程。我知道你只是想开始,但不幸的是,你必须先通过认证。一旦您有了自己的客户 ID 和客户机密 ID,我将为您提供创建推荐数据集所需的所有代码。这听起来像交易吗?
代码准备
为了建立一个推荐系统,我们需要一个曲目数据库,从中我们可以挑选出最适合给定曲目的曲目。为此,您只需要 Python 包 tekore ( < pip 在您的终端中安装 tekore >)、您的 Spotify 客户端 ID 和 Secret ID,以及我将向您提供的代码。
首先,请在项目目录中创建一个名为“authorization.py”的新 python 脚本,并用以下代码填充它:
import tekore as tkdef authorize():
CLIENT_ID = “ENTER YOUR CLIENT ID HERE”
CLIENT_SECRET = “ENTER YOUR CLIENT SECRET HERE”
app_token = tk.request_client_token(CLIENT_ID, CLIENT_SECRET)
return tk.Spotify(app_token)
只需输入您的客户 ID 和客户密码 ID,代码中会这么说。这个脚本只做一件事:它授权您访问 Spotify API,并返回一个允许您访问 API 的对象。该脚本充当我们的主程序的助手脚本。然而,主要的是,它确保你的客户 ID 和秘密 ID 对主程序的读者/用户是隐藏的。只有这样我才能和你分享我的全部代码。
获取 Spotify 数据集
当然,有很多方法可以收集数据集。我们将使用一种方法,从超过 120 个流派中抽取 100 首曲目,从而产生一个包含各种风格音乐的约 12000 首曲目的曲目数据库。
如果你还没有安装软件包熊猫和 tqdm 的话,你需要通过< pip install【软件包名称】>来安装它们。从那里,只需复制并运行下面的代码和/或按照我的代码快速概述。
如果您只想复制代码,请跳过这一步
算法是这样工作的:我们使用助手脚本来授权我们的 API 访问。然后,我们使用<sp.recommendation_genre_seeds>获取 Spotify 的所有 120 个流派标签,并将每个流派的推荐数量设置为 100(这是可能的最大数量)。下一步,我们建立一个字典,它可以保存我们想要抓取的所有数据。接下来,我们循环播放每个流派,然后播放该流派的每首曲目。对于这些音轨,我们抓取元数据和音频信息,并将它们存储在我们之前创建的<data_dict>中。然后,我们将字典转换成 pandas 数据帧,删除重复的 id,最后将数据帧导出到我们的工作目录。</data_dict></sp.recommendation_genre_seeds>
**惊艳!**你知道你的工作目录中有一个名为“valence _ 唤醒 _ 数据集. csv”的数据集。接下来,我们将使用这个数据集来构建我们的推荐系统。
如何使用效价和唤醒度进行推荐
基本思想:向量距离
图 3: 应用于一些知名歌曲的价唤醒平面上的距离(仅估计位置)
如果你看一下图 3 ,我们的相似性度量就很容易理解。在那里,我估计了几首著名歌曲在效价唤醒平面上的位置。在这个平面上,每个向量(一条轨迹,其坐标为“价”和“唤醒”),在这个例子中是托托的“罗莎娜”,可以通过一条线与其他轨迹相连。从视觉上看,很明显,迈克尔·杰克逊的“颤栗”的情感轮廓更类似于“罗珊娜”,而不是平面上更远的所有其他曲目。
数学上,连接每条轨道的线也是向量,我们可以测量它们的长度。2D 向量(a,b)的长度或“范数”被定义为 sqrt(a +b ) 。假设一个轨道有 0.5 个“价”和 1 个“能”,因此坐标是(0.5,1)。那么,它的长度,也就是它到坐标系原点(点(0,0))的距离,等于 sqrt((0.5) + 1 ,大约是 1.12。因此,我们所需要的是找到连接一个给定轨迹和所有其他轨迹的所有向量(箭头),应用公式并取具有最低范数/长度的箭头。
从点 p1 到点 p2 的这个“箭头向量”由 *p2-p1 给出。*因此,轨迹 T1 和轨迹 t2 之间基于情绪的“距离”等于 norm(t2-t1)。换句话说,从 t2 中减去 t1,然后使用上面的公式计算得到的向量的范数。在 Python 代码中,这很容易实现:
def distance(p1, p2):
distance_x = p2[0]-p1[0]
distance_y = p2[1]-p1[1]
distance_vec = [distance_x, distance_y]
norm = (distance_vec[0]**2 + distance_vec[1]**2)**(1/2)
return norm
在我的代码中,我使用 numpy.linalg.norm(p2-p1),它做同样的事情。
一些统计问题
在我们进入推荐系统的实际实现之前,我想向您指出我们的系统将要面临的两个统计问题。如果你真的不在乎,就跳过这一部分,或者以后再来。
图 4: “化合价”和“能量”特征的分布。
正如您在图 4 中看到的,这两个特性的分布完全不同。虽然“化合价”似乎遵循某种近似非常平坦的正态分布,但“能量”却严重左倾。这对于我们的模型来说有一个主要的缺点:在不涉及太多统计细节的情况下,这意味着:“化合价”0.2 的“跳跃”并不总是与“能量”0.2 的跳跃是一回事。然而,我们的模型假设向量(0.5,0.5)与(0.7,0.5)一样接近。如果你想解决这个冲突,应用一个 z 变换 会有所帮助。出于本文的目的,我们将忽略这个问题。
图 5: “化合价”与“能量”的相关性与线性回归线。
另一个问题如图 5 所示。在心理学理论中,效价和唤醒被认为是情绪的两个统计上独立的维度。然而,如果我们将数据集中的所有 12,000 首曲目绘制成“能量-价”平面,我们会看到随着“价”的增加,“能量”也会增加。事实上,发现回归斜率为 0.250,这表明两个特征之间存在不可忽略的相关性。不幸的是,这个问题没有解决方案,因为这个错误(至少对我们来说)是内置在 Spotify API 中的。
最终推荐算法
从这一点开始,构建最终的推荐算法就很简单了。我将指导您完成本部分的最后几个步骤。你也可以跟着一起看这个笔记本。
首先,我们导入一些模块:
import pandas as pd
import random
import authorization # this is the script we created earlier
import numpy as np
from numpy.linalg import norm
接下来,我们读入大约 12000 个磁道的数据帧:
df = pd.read_csv("valence_arousal_dataset.csv")
现在,我们将“价”和“能量”列组合起来,形成每个音轨的单个向量“情绪 _vec ”:
df["mood_vec"] = df[["valence", "energy"]].values.tolist()
我们实施推荐算法之前的最后一步是授权您的 Spotify API 访问,就像我们之前做的那样:
sp = authorization.authorize()
最后,是时候实现我们的基于向量距离的推荐算法了。该算法采取的步骤是:
- 从 Spotify API 抓取输入音轨的“价”和“能量”值
- 计算输入轨迹和参考数据集中所有其他轨迹之间的距离。
- 从最低到最高距离对参考轨迹进行排序。
- 返回 n 条最近的轨迹。
代码是:
测试推荐算法
剩下要做的就是测试我们的算法是否产生有意义的结果!每个 Spotify 曲目作为一个 ID,您可以像这样简单地从 web 浏览器中提取:
这就给你带来了 https://open.spotify.com/track/3JOVTQ5h8HGFnDdp4VT3MP?的si=96f7844315434b0a “其中” 3JOVTQ5h8HGFnDdp4VT3MP "为曲目 ID。
加里·朱尔斯的《疯狂的世界》
那么我们把加里·朱尔斯的《疯狂的世界》(“化合价” = 0.30,“能量” = 0.06)扔到我们的推荐者里怎么样?
Spotify 嵌入加里·朱尔斯的《疯狂世界》。
mad_world = "3JOVTQ5h8HGFnDdp4VT3MP"
recommend(track_id = mad_world, ref_df = df, sp = sp, n_recs = 5)
“化合价”= 0.31,“能量”= 0.05 的最佳推荐是亨瑞·贝拉方特的《荣耀经理》。
Spotify 嵌入亨瑞·贝拉方特的《光荣的马槽》。
还不错!虽然“荣耀经理”来自完全不同的流派,但我们的算法已经匹配了这些歌曲,因为它们都具有相似的“价”和“能量”水平。
托托的《罗珊娜》
让我们再举一个例子!托托的《罗珊娜》“化合价”为 0.739,“能量”为 0.513。
Toto 的《罗珊娜》的 Spotify 嵌入。
最受欢迎的推荐是由 Duelo 创作的“Sentimientos De Chartón ”,其“化合价”为 0.740,“能量”为 0.504。
Spotify 嵌入 Duelo 的“Sentimientos De Chartón”。
再一次,音乐类型非常不同,更像是“拉丁”而不是“流行摇滚”。然而,《Sentimientos De Cartón》捕捉到了这种“浪漫渴望”的感觉,同时仍传达出一种运动感和最佳状态,就像《罗珊娜》一样。
结论和最终想法
**恭喜你!**如果你一直关注这篇文章,那么你要么已经建立了你的第一个基于情绪的推荐系统,要么至少已经了解了一点如何编写这样一个系统。然而,仍有一些事情值得简要地思考或讨论。
我们取得了什么成就?
我们一起建立了音乐推荐系统的基础,该系统使用“价-唤醒平面”的适应以及向量距离测量来匹配传达相似类型情感/情绪的曲目。这种方法从根本上不同于协作过滤方法(“其他用户也购买了[…]”),因为它试图提取歌曲的内在品质,而不依赖于用户数据。这对于你们(像我一样)没有运营大型音乐平台,拥有数十亿相关用户数据点的人来说,尤其有帮助。另一个好处是,这种方法的实现是快速和免费的,从收集数据到实现实际的推荐算法。最后,跨流派类别推荐音乐是任何现实世界推荐系统的期望品质,因为这支持用户参与新类型的音乐并发展他们的个人音乐品味。
我该如何改进这个推荐系统?
正如在统计一节中提到的,**对“价”和“能量”特征进行“z 变换”**将使您的距离测量更准确,从而使您的推荐更准确。
Spotify API 提供了更多功能,如“可跳舞性”、“声音”和“速度”。试着想出合理的方法来**扩展“价-唤醒平面”**或者从零开始开发你自己的变量集。
将基于情绪的方法与协作过滤方法结合起来也是一种有趣的探索。怎么样,在我们使用“价”和“能量”计算出前 10 个推荐之后,我们**按照“流行度”**对推荐重新排序(这也是 Spotify API 中的一个功能)。
你可以让用户决定一组所有推荐都必须是的类型,或者一组不应该出现在推荐中的类型。
最后,你可以通过探索 Spotify API 的可能性和分析越来越多的歌曲来扩展你的参考数据集。较大的数据库更有可能为每个输入轨迹准备一个近乎完美的匹配。
非常感谢你阅读这篇文章!如果您有任何问题或意见,或者有任何不正常的地方,请告诉我。我目前正在探索创造性的方法,使用自建的机器学习模型来扩展这里显示的推荐系统。如果你想看的话,请继续关注!
用 Python 构建你的语言过滤器
这是一个关于如何用 python 构建语言过滤器的指南,用于审查污言秽语和其他不合适的内容
玛利亚·克里萨诺娃在 Unsplash 上的照片
语言过滤器是一个你可以去除不必要的脏话的过滤器。某种过滤对于维护网站或所提供服务的真实性是必要的。
这种必要的审查对于各种自然语言处理项目也是有帮助的。为了儿童使用的安全,你可以使用语言过滤,在聊天机器人中使用来阻止亵渎的词语,以及审查被认为对工作不安全的污言秽语。
**注意:**在这篇文章中,我将删除任何被认为冒犯公众的词语。但是,当您在您的设备上尝试这种方法时,建议使用完整的单词来测试它们,并检查它是否如您所愿完美地工作。
在这篇文章中,我们将讨论两个这样的简单方法,我们可以利用有效的语言过滤。一种方法是使用预构建的 python 库模块,它可以有效地执行这项任务,另一种方法是构建自己的定制语言过滤。
有关如何使用深度学习从头开始构建聊天机器人的更多信息,请查看下面的文章。我们今天看到的脏话过滤器对这类应用也很有用,你可以选择过滤掉可能被你的聊天机器人认为是不适当的回复的文本。
在本文的这一部分中,我们将探索几种方法来实现过滤掉特定语言中任何不合适的俚语的过程。我们将讨论完成以下任务的两个过程。在第一种方法中,我们将利用亵渎过滤器库来完成项目。在第二种方法中,我们将构建自己的自定义代码来执行这样的操作。
1.脏话过滤方法:
其中一种方法是使用 python 中的脏话过滤器库模块。这是一个通用的检测和过滤脏话的库。包括对英语和俄语的支持。它有助于检测两种语言范围内的脏话,并可以相应地审查它们。
该模块的安装过程非常简单,可以使用以下 pip 命令成功完成:
pip install profanity-filter
但是,在执行您安装的以下库模块时,您可能会遇到一些小问题。在运行本节后面提供的代码时,您可能会遇到的错误之一如下。
**ProfanityFilterError**: Couldn't load Spacy model for any of languages: 'en'
以下错误表明您的 Spacy 模型中没有可用的英语。Spacy 是处理自然语言处理相关数据的最佳工具之一。它建立在高端研究的基础上,旨在支持复杂的任务。如果您还没有安装这个库,我强烈建议您用下面的命令安装它。
pip install spacy
现在你已经安装了 spacy 库,你可以同时在这个模块中安装英语,这样脏话过滤库就可以利用它来过滤不合适的内容。下面提供的以下命令应该可以成功地在您的设备上为 Spacy 型号安装英语。
python -m spacy download en
让我们看一些关于如何有效利用这个库的代码。一旦我们浏览了代码,我们将理解这个库的一些特性,然后在本文的下一节中继续开发我们自己的过滤系统。
代码:
使用脏话过滤器库的代码块非常简单。我们可以导入下面的库和空间模块。我们可以访问需要执行审查操作的特定语言,并将返回值存储在所需的变量中。这个变量现在可以用来有效地过滤掉任何不必要的俚语。下面的代码片段及其输出显示了一个完美的用例示例。
from profanity_filter import ProfanityFilter
import spacyspacy.load('en')pf = ProfanityFilter(languages = ['en'])
pf.censor("That's bullshit!")
输出:
"That's ********!"
亵渎过滤器支持该库中包含的多种语言。目前,两个最突出的语言支持是英语和俄语。本节的特点来自官方来源之后的。让我们看看脏话过滤模块能够实现的一些惊人的功能。
特点:
- 全文或单个单词审查。
- 多语言支持,包括在混合语言编写的文本亵渎过滤。
- 深度分析。该库不仅使用 Levenshtein 自动机检测精确的亵渎单词匹配,还检测衍生和扭曲的亵渎单词,忽略字典单词,包含亵渎单词作为一部分。
- 将库用作管道一部分的空间组件。
- 决策说明(属性
original_profane_word
)。 - 部分文字审查。
- 扩展性支持。可以通过提供词典来增加新的语言。
- RESTful web 服务。
该模块的唯一限制是它是上下文无关的。该图书馆无法检测使用由体面的话组成的亵渎性短语。反之亦然,图书馆不能检测一个亵渎的词的适当用法。这意味着过滤器不能理解一个单词的真实语义。因此,有可能在数据库没有意识到的讽刺语句或俚语中出现失误。
2.如何在不使用该库的情况下构建自己的过滤器系统:
在本节中,我们将了解如何在这个自定义代码块中为特定语言(如英语)构建我们自己的自定义语言过滤器。这种执行的代码很简单,我们可以构建自己的函数来执行这种任务。
第一步是为你的特定项目列出你希望保留审查的所有单词。下面是一个例子代码块的一些话,我们可能希望被审查。用户也可以随意添加和探索任何其他类型的单词。
Banned_List = ["idiot", "stupid", "donkey"]
下一步,我们将定义一个包含三个禁用单词中的两个的随机句子。下面是我们将在变量中声明的句子。
sentence = "You are not only stupid , but also an idiot ."
最后,我们将定义我们的审查自定义函数,该函数将执行审查特定句子中不适当语言的操作。在这个函数中,我们将把想要的句子作为一个参数,并相应地计算下面的内容。我们将用空格将句子分开,这样我们就有了需要的单词。然后,我们将继续检查以下单词是否是禁用列表的一部分。如果是,那么我们将用星号代替这个词。如果没有,我们将继续按照最初的解释打印句子。下面是解释这个函数的代码片段。
def censor(sentence = ""):
new_sentence = ""
for word in sentence.split():
# print(word)
if word in Banned_List:
new_sentence += '* '
else:
new_sentence += word + ' '
return new_sentence
最后,让我们调用函数并查看下面句子的相应输出。
censor(sentence)
输出:
'You are not only * , but also an * . '
还有一些额外的改进,观众可以选择进行,例如为每个单词加入正确数量的星号空格,并确保阅读单词时标点符号不会干扰。这两项任务都很容易完成,我建议有兴趣的人试一试!
结论:
在本文中,我们讨论了两种简单的方法,通过这两种方法,我们可以针对任何特定的任务有效地使用语言过滤方法。然而,这些过滤系统的一个主要问题是缺乏对所用语言的语义理解。因此,它无法找出什么合适的短语或特定的巧妙方法来绕过它的方法。
尽管如此,他们在从网站设计到使用深度学习方法创建的聊天机器人的广泛应用中,出色地完成了与大多数常见做法的对抗。您可以找到更好的方法来使用这些函数产生更有效的结果。
如果你想在我的文章发表后第一时间得到通知,请点击下面的链接订阅邮件推荐。如果你希望支持其他作者和我,请订阅下面的链接。
https://bharath-k1297.medium.com/membership
看看我的其他一些文章,你可能会喜欢读!
</6-reasons-why-your-ai-and-data-science-projects-fail-2a1ecb77743b>
谢谢你们坚持到最后。我希望你们喜欢阅读这篇文章。我希望你们都有美好的一天!
用 Keras 以三种方式建立你的神经网络
如何、为什么以及何时使用每种方法
如何使用 Keras API[图片由作者提供]
我仍然清晰而痛苦地记得我第一次面对神经网络及其实现的情景。好像我的困惑还不够大,试图让我的思想围绕着神经网络的内部工作方式,如何使用 Keras API 的不同方式使混乱更加彻底。所以我坐下来,拼命寻找这个问题的最终答案:实现神经网络的最佳方式是什么?
在接下来的几节中,我们将解开这些乱七八糟的东西。避免不同语法带来的不必要的麻烦,因此我们可以专注于更重要的问题,如使用哪种架构或如何提高模型的性能。
Keras 或者更具体地说是模型 API 可以分为三个部分,因此可以通过多种方式创建模型。接下来,我们将学习如何以及何时利用 API 的哪一部分。
我们将使用良好的 MNIST 数据集,以三种不同的方式构建相同的全连接神经网络。
顺序模型
使用Sequential Model
非常简单。我们既可以通过向构造函数传递一个层列表来构建模型,也可以通过多次调用add()
方法来逐步构建模型。
顺序模型的作用类似于一个线性或普通 层的堆叠,其中每一层恰好有一个输入张量和一个输出张量。这使得我们一方面很容易使用和调试,而另一方面,我们失去了很多灵活性。
层叠[图片由作者提供]
因此,当我们的模型或我们的一个层具有多个输入或输出时,顺序模型是不合适的,我们需要进行层共享,或者我们想要使用非线性拓扑,例如剩余或跳过连接。
我们现在可以编译、训练并获得我们模型的摘要。
>> Total params: 119,306
>> Trainable params: 118,794
>> Non-trainable params: 512
功能 API
functional API
为我们提供了一种建立模型的方法,比顺序模型更加灵活。它使我们能够创建非线性拓扑、共享层,甚至多个输入或输出。作为功能 API 的基础,主要思想是构建一个层图。
我们可以通过用输入维度(28x28 像素)定义一个输入节点来构建一个图层图。
接下来,我们定义更多的节点来重新创建之前的模型。然后,通过将前一个节点作为输入传递给下一个节点来连接这些节点。这些连接为我们提供了构建非线性拓扑所需的灵活性,例如通过连接非相邻节点和创建跳过连接。
我们还可以编译、训练并获得我们的模型的摘要,它与序列模型具有相同的结构。
>> Total params: 119,306
>> Trainable params: 118,794
>> Non-trainable params: 512
模型子类化
用子类化创建模型为我们提供了最大的灵活性。然而,这种灵活性的代价是复杂性和冗长性的增加。
Layer Class
是 Keras 中的核心抽象之一。一个层保存状态(层的权重)和从输入到输出的转换(来自调用的前向传递)。当模型的复杂性增加时,创建定制层特别有用,它为我们提供了在模型架构中创建可重用“块”的方法。
在我们的模型中,我们可以使用一个定制层来创建一个在我们的架构中多次出现的基本构建块。下面的类继承自 layer 类,初始化两层:Dense 和 BatchNormalization。然后,这两层都在正向传递中被简单地调用。
接下来,我们利用上面的自定义层创建我们的模型。我们的类继承自Keras Model Class
,因此得名子类化。我们基于hidden_layer = [128,128]
初始化我们的自定义图层,以及另外两个图层:展平和我们的最终输出图层。然后,在模型的正向传递中,所有的层都被简单地调用。
然后,我们可以再次编译、训练并获得模型的摘要,这应该与之前相同。
>> Total params: 119,306
>> Trainable params: 118,794
>> Non-trainable params: 512
结论
在 Keras 中有三种创建模型的方法。根据我们要解决的问题和我们需要构建的模型,一种方法可能比另一种更适合,但一般来说没有绝对最好或正确的方法。
简单、线性和直观的模型可以而且可能应该用顺序 API 或函数 API 来构建。然而,更复杂、非线性和高度定制的模型将从子类化中受益匪浅。
总之,一个人应该知道并尝试以上所有的方法,扩大他们的工具箱,以便有效地解决问题。
喜欢这篇文章吗?成为 中等会员 继续无限学习。如果你使用下面的链接,我会收到你的一部分会员费,不需要你额外付费。
https://medium.com/@marvinlanhenke/membership
构建您自己的 arcpy 助手包
告别剪切粘贴 Python
沃洛季米尔·赫里先科在 Unsplash 上的照片
Esri 的 arcpy package for Python 是最全面的地理信息管理、分析和可视化工具包。
这种详尽的功能集是以代码的简洁性为代价的。看似简单的操作实现起来可能会很复杂,Esri 的 ArcGIS 软件可能会增加学习曲线。
Pythonic 的格言应该有一个……显而易见的方法去做并不一定适用。
由于技术需求和个人偏好的混合,每个组织都将以自己的方式组装和配置脚本。结果可能是大量重复的代码,以及复制和粘贴的强烈诱惑。更糟糕的是,在一个部门内,同样的行为可能以不同的方式实施。
轮子:不要重新发明它。乔恩·卡塔赫纳在 Unsplash 上的照片
软件工程的一个关键原则是不要重复你自己(干)。 Python 的模块框架是为帮助我们实现这一目标而量身定制的。然而,从地理学家-GIS 分析师(像我一样)的角度来看,当您第一次面对一项复杂的任务时,将 arcpy 与模块开发结合起来可能会感觉像以毒攻毒。这当然是一个我推迟了几年的问题!
事实上,抽象掉重复的逻辑有很多好处。它确保了一致性,有助于维护,并增加了脚本的可读性。您可以进行渐进的改进,并立即看到它们在所有项目中的应用!短期的痛苦伴随着明确的长期收益。
下面是你需要知道的开始。我假设您已经安装了 ArcGIS Pro,并且可以从命令行运行 python 和 pip。你可以在这里找到下面所有代码的模板。
结构
我认为 90%以上的 arcpy 项目都是由单独的脚本组成的。
当我们刚刚找到一种方法来做我们一直试图做的事情时,我们不倾向于用额外的复杂性把它弄乱。
没有必要每次想要自动化某件事情时都创建一个成熟的 Python 项目。然而,当我们包装所有最重要的代码时,我们应该尝试遵循最佳实践。
假设我们有以下 c:\files\parent_folder 文件夹结构
parent_folder module_name tests
我用一个很基本的例子。假设我们想要调用 arcpy。每次我们调用 AddMessage()时都以一种特殊的方式。我们将调用我们的包 archelpy,并创建一个 messages.py 模块。
archelpy archelpy __init__.py
messages.py tests
这个基本的 messages.py 示例在脚本工具界面中将时间戳应用于 arcpy 消息。这有助于确定漫长流程中哪个部分最耗时。
消息. py
您可以决定创建相应的模块来管理属性域、索引、切片缓存或任何数量的其他技术问题,
archelpy archelpy __init__.py
caching.py
domains.py
indexes.py
messages.py tests
测试
单元测试是另一个经常被归为“太难”的话题。
对于许多工作流来说,编写测试可能是多余的。另一方面,它们可能非常有益。
据说可测试代码是高质量的代码。测试鼓励深思熟虑的设计,不鼓励过于复杂或混乱的代码。测试还以其他开发人员能够理解的方式记录了工具的目的和预期行为。随着项目的发展,他们通过验证行为和确保质量来提供安心。
Python 内置的 unittest 框架允许我们检查我们的逻辑是否以我们期望的方式调用了 arcpy(或其他第三方模块)。
archelpy
__init__.py archelpy __init__.py
messages.py tests __init__.py
test_messages.py
测试消息. py
注意测试 _。命名约定很重要。*
从父目录中运行下面的命令将通过在整个项目中搜索测试文件来执行我们的测试套件,
cd c:\files\archelpypython -m unittest discover -v
在这种情况下,我们应该看到这样的结果,
testAddMessageParameters (tests.test_messages.HelpyMessagesTestCase)Uses assert_called_with() to make sure that our code passes ... ok----------------------------------------------------------------------Ran 1 test in 0.003sOK
在实践中,您将创建更多的测试,并将它们组织到不同的文件和目录中。这时,unittest 中的 discover 特性变得特别有用。
打造
我们已经准备好分发包裹了。如果你想大方一点,你可以开源它并把它添加到 PyPi 中。对于专有工作,您更愿意将安装资源保存在安全的地方。
cd c:\<path>\archelpy
ArcGIS Pro 的 Python 安装附带了 setuptools 和 wheels,它们会创建一个名为 wheel 文件的 pip 兼容安装程序。whl)。
我们在名为 setup.py 的文件的顶层目录中定义我们的包属性,
archelpysetup.py
setup.py 模板
运行以下命令,
python setup.py bdist_wheel
这将在项目中生成许多工件,包括一个. whl 文件,您可以用它来安装您的模块!
archelpy dist archelpy-0.1.0-py3-none-any.whl
安装
使用 pip 来安装使用新创建的 wheel 文件的模块,
pip install c:\files\archelpy\archelpy-0.1.0-py3-none-any.whl
您应该会看到以下结果,
Processing c:\files\archelpy\archelpy-0.1.0-py3-none-any.whl
Installing collected packages: archelpy
Successfully installed archelpy-0.1.0
使用!
像这样在脚本工具中导入 archelpy,
from archelpy import messagesmessages.time_message("Hello!", arcpy)
你已经准备好了!当您对软件包进行改进时,使用以下命令重新构建 wheel 文件并更新安装,
pip install <wheel file> --upgrade
快乐脚本!
由 uomo libero 在 Unsplash 上拍摄的照片
感谢
参见起亚 Eisinga 的这篇文章,对包装进行了更深入的讨论。
参见来自帕特里克·肯尼迪的这篇文章,以及来自 Ian Firkin 的这篇文章,分别了解关于测试 Python 和 arcpy 的更多细节。
构建您自己的自动差异化程序
实践教程
对于那些完全不知道如何使用图形计算导数的人,或者只想知道张量流在基本层面上是如何工作的人,这是你的指南。
照片由在 Unsplash 上拍摄
深度学习如今如此流行,如此广泛,人们很容易问这样一个问题,“为什么人们花了这么长时间才弄明白这个问题?”原因有很多,进入深度学习的历史真的不是这篇文章的重点(参考文献[1]的介绍做得很好),但使这场革命滚动的关键进步之一是自动微分(AutoDiff) 。
如果您想直接了解技术细节,请跳到“构建自动挖掘”一节,如果您只想了解代码,请跳到“用 Python 实现自动挖掘”一节
关于本文所用代码的配套 Jupyter 笔记本,请参见以下链接:https://github.com/Jmkernes/Automatic-Differentiation
你问自动微分有什么了不起的?假设你正在研究一个函数,你很想知道它的导数。如果这是一个相对简单的函数,你大概可以很快给出答案。如果 *f(x)=x,*那么我们可以很快得出 df/dx=3x 。如果它更复杂,而你不仅仅知道答案呢?好吧,你没有太多的选择。
选项 1:如果你想要数值答案,你可以回到基础,直接计算有限差分,使用公式如下
以及他们更复杂、更精确的表亲。但这并不令人满意。也许我们想要象征性的答案,用 x和 y之类的东西来表示,在这种情况下,一个数字答案是不够的。或者,也许我们的微分变量 x 实际上是一个大的多维张量,为那个东西的每个条目逐个计算数值差将是非常低效和耗时的。
选项二:求导求导。这应该是元的。求导是什么意思?我们之前是怎么知道 df/dx=3x 的答案的?事实证明,只有两种方法可以算出导数。如果这是一个全新的函数,你只需要通过上面显示的极限表达式来得到答案。然而在现实中,大多数函数都不是新的,它们实际上只是其他函数的组合。在这种情况下,我们可以通过链式法则算出新的衍生品:
但是,比如,什么是功能?
我从事的第一个物理项目涉及到一些特殊函数的使用,叫做广义超几何函数。如果你不知道那些是什么,不要担心,这才是重点。像每一个特殊函数一样,它们很难处理,并且包含足够多的身份和特殊情况,足以填满一本哈利波特魔法书。所以,心灰意冷的我去找我的导师,直接问他,“嘿,这到底是什么东西?”
他的回答非常简单——“这只是我们知道的一些功能。”这似乎是一个无用的答案,但它实际上很有深度。然后他问我“你知道余弦是什么,对吗?”对此我尖刻地回应道:“是的,当然,我知道余弦是什么。”他毫不犹豫地回击道,“但是你怎么知道余弦是什么?知道什么是超几何函数和知道什么是余弦有什么不同?最后,你知道余弦是什么,因为你能说出一些恒等式,你能画出一个漂亮的图。就是这样。”
此时,我被难住了。我正面临一场数学生存危机,并重新评估我所学的一切。“我知道余弦是什么,因为我知道它的导数是 -sin(x) !”,我想。“而且,我知道正弦是什么!因为它的导数是 cosi… ",哦不,一个无限循环。
从我的生存危机中恢复过来后,我开始意识到世界上有两种类型的功能:我们熟悉的东西,如 x 或 *x+5,*和我们不熟悉的东西,但可以由熟悉的东西组成——如 (x+5) 。自动微分以后一个概念为中心。我们可以把它的使命描述为:
给定一组初等函数,比如 e^x 、 cos(x) 、或 x 、,然后使用微积分规则,就有可能确定由这些初等函数的组成的的任何函数的导数。
因为我们可以用各种方式表示函数,比如幂级数、傅立叶级数等等。这是一个非常有力的声明。这一切都是通过链式法则起作用的。自学的奇妙之处在于,它在数学上相当于零计划地环游世界。您可以随心所欲地不断组合和堆叠函数,越来越深入,始终确保 AutoDiff 能够跟踪面包屑并为您计算导数。
在这篇文章的其余部分,我们将假设我们想要求导的每一个函数都可以分解成初等函数(如果你想要第二类修正贝塞尔函数的导数,你将不得不去别处寻找
建立我们的自动挖掘系统
在这篇文章结束时,你将能够生成如下图:
来源:现作者。一个非常简单的计算图
但是你喜欢多复杂就有多复杂。我们来分解一下这个图的意思。假设我们被赋予了这个函数
我们想计算 f 对其变量 x,y,和 z 的偏导数。我们可以将这个函数分解成一组非常基本的函数,即函数 add(x,y)=x+y 接受两个数并将它们相加,函数 **multiply(x,y)=xy* 接受两个数并将它们相乘。基本的,对吧?在这种新形式中,我们有
这是一个更罗嗦的表述,但是…这并没有错。
资料来源:knowyourmeme.com。我们冗长陈述的理由。
这种形式很有用,因为我们立即知道了的导数加上和乘以。此外,我们将它重写为两个初等函数的组合,因此我们可以应用链式法则。我们获得
利用基础微积分,我们得到 1*y=y,这显然是正确答案。虽然你可能没有注意到,但是每当你计算导数的时候,你都会隐式地执行上面的操作。现在,让我们让计算机来做这件事。
计算图
为了说明这个过程,我们需要做两件事:1)告诉计算机什么是基本构件 2)告诉它如何把这些构件放在一起计算导数。
让我们先集中讨论第一部分。有四种基本类型的块,我们用图论的语言称之为节点 T21。这些包括
- 变量 —我们想要知道其梯度的可变对象(张量)。
- 常量 —不可变对象(张量),其值一旦指定就不会改变。
- 占位符 —这些基本上是空的容器,一旦我们决定了未来变量或常数的值应该是什么,它们就指定了未来变量或常数的位置。
- 操作符——这些是概念上最难描绘的,但也是最重要的。
前三个应该相对简单。需要一段时间来适应的计算图有一点令人困惑,那就是图中的节点实际上是操作符,而不是变量、常数或占位符。直觉上,我们喜欢认为函数是由它们的值组成的。我们写 f(x,y,z) 的时候用的是 x,y,z. 没有写 f( 加,乘) 。然而,这正是我们的计算机要寻找的。通常,操作符节点接受输入并返回输出。我们假设节点只发出一个输出;虽然张量包含许多项,但它可以被认为是一个单一的输出
来源:现作者。操作符节点的特写。
我们现在可以理解本节开头的图表了。我们只使用了数字,但是这些数字也可以被认为是标量张量。因此,图表显示了张量是如何在计算中流动的。明白了吗?张量…流…张量流。现在让我们考虑相反的方向,计算梯度。
为了计算输出 f(x,y,z) 的实际值,我们沿着箭头的方向向前运行图形,从变量 *x,y,z,*开始,流经操作符。现在让我们用图形来思考这个方程。我们将添加一个额外的、琐碎的计算
这将帮助我们初始化反向传播程序。检查我们的方程对 f 的偏导数,需要注意的一点是*导数也是一个函数!*这意味着链式法则导数也是函数的组合。记住,函数的组合=图形。这是规矩。真正好的是,我们的图形结构是相同的,但反向运行。你可以看到下面的结构:
来源:现作者。红线表示梯度的流动。
红色箭头表示从最终输出到开始的导数流是一个反向计算图。它可以用完全相同的方式计算,其中我们使用平凡的恒等式 df/df=1,为第一个节点提供 1 的导数。我们的目标现在应该很明确了:
- 指定图表中的所有变量、占位符和常量
- 使用运算符将它们组合在一起,形成最终的标量输出
- 计算一个前向传递,它输入值并流经运算符以获得输出。将每个节点的输出值存储在该节点中。
- 计算一个反向传递来计算梯度,从最后一个节点(输出)的梯度 1 开始。
实现这一点是本文剩余部分的目标。
在 Python 中实现自动搜索
我们想预先警告读者这涉及到全局变量。全局变量是禁忌,但是我们使用它们的原因有望随着我们的深入而变得清晰。图是我们的全局对象(好吧,不是一个全局变量,实际上是一个全局对象,很抱歉我说谎了),我们将向其中添加节点。据我所知,没有一种简单的方法可以明确地确定对象的范围,我相信 TensorFlow,至少在 V1,也使用了全局图形变量。如果有人有避免全局变量的解决方案,请在评论中发表!
好了,先不说警告,我们开始吧。我们首先需要定义默认的图形类。这将是一个基本的结构,只跟踪当前的节点和它们的类型。
一些事情:所有在 init 方法之后的事情你都可以忘掉。它不影响代码,只是试图使创建本地化的图形变得稍微容易一些。您也可以删除它,并确保运行Graph()
来初始化全局默认图,运行del _g
来在定义一组节点之前和之后删除它。此外,我们并不真的需要 numpy,它是为了帮助我们以后做矩阵乘法。
太好了,我们有工作图了。现在让我们来定义我们之前讨论的四个类。它们或多或少都是一样的,每个都包含一些独特的功能
Operator 类需要一个输入属性,Constant 类需要保护它的值,其余的类似。我们使用了一些默认的名字,比如 Var1,Var2,…这是描述性的最低水平。name 字段对于以后从图中检索节点很重要,因为我们没有任何其他方法来标识它们
此外,跟踪占位符的名称也很重要,否则我们真的无法在计算图中找到它们。
我们放入了一些其他东西,比如 repr 函数,以类似“Operator: name:mul/2,value:3.875”的格式自动将节点显示为字符串。这应该能帮助我们马上知道我们正在处理的是哪个节点。
现在,为了让我们的图做点什么,我们需要给它一些真正的操作符。这些正是我们一直在谈论的基本操作。像加减乘除之类的东西。我们将定义其中的一些,为了使事情更容易编码,我们将重载所有这些操作符(注意:我想不出更好的方法来做到这一点,既不重复大量的代码,也不需要以奇怪的方式向基本节点类添加方法。接受更好的建议)。一个棘手的运算符是 neg。记住 x - > -x 实际上是一个乘法运算符,所以图形需要知道这一点。
现在,我们所有的基础设施都已就绪。我们只需定义变量、常量或占位符,并执行常规计算,就可以轻松构建图表。操作员将负责向图中添加节点和其他一切。我们可以创建一个图g
并通过下面的语法添加一些操作
with Graph() as g:
x = Variable(1.3)
y = Variable(0.9)
z = x*y+5g.variables # Will output {Variable: name:Var/0, value:1.3, Variable: name:Var/1, value:0.9}g.operators # Will output {Operator: name:add/0, Operator: name:mul/0}g.constants # Will output {Constant: name:Const/0, value:5}
如您所见,该图正确地创建了一个常数,并且还记录了两个操作,x*y 乘法以及常数 5 的加法。如果我们再次运行with Graph() as g
,它应该会删除当前的默认图形,并开始重新构建。酷,一切正常。现在,我们必须使用一点算法知识来计算我们的向前和向后传球。
目前,我们的默认图表只跟踪当前节点。它没有结构。最终,我们想要向前运行我们的图形,这意味着我们给它输入所有的变量、常量和占位符,然后这些通过操作符流到我们的输出。我们这样做的顺序是一个经典的算法问题。我们需要执行一个拓扑排序(CLRS 的书【3】总是好的,或者只是使用维基百科)。我们的图是一个有向无环图,意味着每个节点都有一个起点和终点。没有循环。拓扑排序保证了如果我们按顺序运行每个节点,我们将永远不会缺少计算节点的信息。就像点了课前提;您将时间表调整为在 Calc III 之前学习 Calc I。
经过拓扑排序,我们的图真正成为了一个图。它终于有了一些坚实的结构!即使这个结构只是有序节点的数组。为了完成我们的程序,我们执行通行证。向前传球真的很简单;只需按顺序计算每个节点的值,并将其值存储在该节点中,以便将来的节点可以在需要时访问它。
向后传球稍微难一点,但也不算太难。用值 1 初始化根节点(回想一下使用 df/df=1 的讨论)。然后,只通过它的操作符遍历图形。换句话说,计算当前操作符的所有输入的梯度,然后递归地对那些也是操作符的输入做同样的事情。代码如下:
就是这样!我们已经完成了程序的主要部分。剩下的就是摆弄它,并对它进行一点分析。这里有一个例子,说明如何计算一个简单函数的梯度
它取决于两个变量和一个常数。我们可以很容易地手工计算它的导数,并检查我们的代码是否正确。首先向前传球:
val1, val2, val3 = 0.9, 0.4, 1.3with Graph() as g: x = Variable(val1, name='x')
y = Variable(val2, name='y')
c = Constant(val3, name='c')
z = (x*y+c)*c + x order = topological_sort(z)
res = forward_pass(order)
grads = backward_pass(order) print("Node ordering:")
for node in order:
print(node) print('-'*10)
print(f"Forward pass expected: {(val1*val2+val3)*val3+val1}")
print(f"Forward pass computed: {res}")
---------------------------------------------------""" Output:
Node ordering:
Variable: name:x, value:0.9
Variable: name:y, value:0.4
Operator: name:mul/6
Constant: name:c, value:1.3
Operator: name:add/6
Operator: name:mul/7
Operator: name:add/7
----------
Forward pass expected: 3.0580000000000003
Forward pass computed: 3.0580000000000003
"""
对于向后传球:
dzdx_node = [a for a in order if a.name=='x'][0]
dzdy_node = [a for a in order if a.name=='y'][0]
dzdc_node = [a for a in order if a.name=='c'][0]print(f"dz/dx expected = {val3*val2+1}")
print(f"dz/dx computed = {dzdx_node.gradient}")print(f"dz/dy expected = {val1*val3}")
print(f"dz/dy computed = {dzdy_node.gradient}")print(f"dz/dc expected = {val1*val2+2*val3}")
print(f"dz/dc computed = {dzdc_node.gradient}")---------------------------------------------------""" Output:
dz/dx expected = 1.52
dz/dx computed = 1.52
dz/dy expected = 1.1700000000000002
dz/dy computed = 1.1700000000000002
dz/dc expected = 2.96
dz/dc computed = 2.96
"""
测绘
好吧,所以我答应你在这结束之前你会拍出漂亮的照片。这是我信守的承诺。我们将使用 python 库 Graphviz 。你可能不得不pip install graphviz
这就是为什么我把这个留到最后。要构建图,我们只需为图中的每个节点创建一个节点,然后使用运算符绘制边。操作符决定了图的流向,所以就像我们做 backward_pass 时一样,我们只需要操作符的边。通过使用下面的代码
我们可以制作如下漂亮的图片
它代表了我们之前运行的测试代码的图表。
结论
如果你已经做到了这一步,感谢你的阅读!总而言之,我们已经展示了自动微分是建立在两个理念之上的
- 我们通常对计算导数感兴趣的所有函数都可以表示为初等函数的组合
- 这些初等函数很简单,或者至少有已知的导数,我们可以用它们来提供我们的自动探索程序
从那里,我们可以创建一个图形,拓扑排序,然后运行一个向前向后传递来获得梯度。我希望这是有用的,也是对像 TensorFlow 这样的自动挖掘系统如何工作的很好的介绍。有时候,如果你只是稍微努力思考一些你已经非常了解的东西,你可能会发现一些有趣的东西!
参考
[1] Goodfellow,Ian 等深度学习。第一卷。№2.剑桥:麻省理工学院出版社,2016 年。
[2]https://en.wikipedia.org/wiki/Five-point_stencil
[3]科尔曼、托马斯·h 等著算法导论。麻省理工学院出版社,2009 年。
使用 Python 和深度学习构建自己的不和谐调节机器人
建立一个自主机器人,删除所有有毒信息。
在 Unsplash 上由 Clément Falize 拍摄的照片
介绍
鉴于互联网用户生成的文本规模,内容审核可能很困难。简化这一过程的一个解决方案是使用机器学习来自动化它。一个 ML 模型训练了版主不想看到的例子,如有毒内容、侮辱或种族主义评论,然后可以用来自动过滤掉这些消息。
在这个项目中,我们将使用 Jigsaw 毒性评论数据集训练这样的模型:https://www . ka ggle . com/c/Jigsaw-Toxic-Comment-class ification-challenge/Data
然后,我们将使这个模型可以从一个 Discord bot 中调用,该 bot 将删除该模型标记为有毒的所有消息。
数据
Jigsaw 毒性数据包括 159,000 个样本,每个样本都可以贴上多个类别的标签,如“有毒”、“侮辱”…
数据集格式-按作者分类的图像
为简单起见,我们使用所有这些类别来创建一个二进制目标,如下所示:
data["label"] = (
data[
["toxic", "severe_toxic", "obscene", "threat", "insult", "identity_hate"]
].sum(axis=1, skipna=True)
> 0.5
).astype(int)
机器学习步骤
机器学习步骤-作者图片
标记器
我用 huggingface 的库训练了我自己的 BPE 分词器,你可以用我的 Github 库中的脚本做同样的事情:
python bleach_bot/ml/train_tokenizer.py --files YOUR_TEXT_FILES
这个记号赋予器将句子分解成小记号,然后将每个记号映射成整数:
标记器—按作者分类的图像
分类者
我们使用变压器网络作为分类器:
变压器网络—图片由作者提供
通过使用 torch.nn.TransformerEncoderlayer 和 torch . nn . transformer encoder 类,实现变得很容易。
class TextBinaryClassifier(pl.LightningModule):
def __init__(
self,
vocab_size,
channels=256,
dropout=0.4,
lr=1e-4,
):
super().__init__()
self.lr = lr
self.dropout = dropout
self.vocab_size = vocab_size
self.embeddings = torch.nn.Embedding(self.vocab_size, embedding_dim=channels)
self.pos_embedding = torch.nn.Embedding(1024, embedding_dim=channels)
encoder_layer = nn.TransformerEncoderLayer(
d_model=channels, nhead=4, dropout=self.dropout, dim_feedforward=1024
)
self.encoder = torch.nn.TransformerEncoder(encoder_layer, num_layers=8)
self.linear = Linear(channels, 1)
self.do = nn.Dropout(p=self.dropout)
self.loss = torch.nn.BCEWithLogitsLoss()
def forward(self, x):
batch_size, sequence_len = x.size(0), x.size(1)
embedded = self.embeddings(x)
pos_x = (
torch.arange(0, sequence_len, device=x.device)
.unsqueeze(0)
.repeat(batch_size, 1)
)
pos_x = self.pos_embedding(pos_x)
embedded += pos_x
embedded = self.do(embedded)
embedded = embedded.permute(1, 0, 2)
transformed = self.encoder(embedded)
transformed = transformed.permute(1, 0, 2)
out = self.linear(transformed[:, 0])
return out
预言者
火炬至 onnx
出于实际原因,我们将模型从 torch 转换。ckpt 格式到. onnx.
我们还使用 onnxruntime 库在我们的预测中使用这个模型。
为此,我们运行:
torch.onnx.export(
model, # model being run
ids, # model input (or a tuple for multiple inputs)
filepath, # where to save the model (can be a file or file-like object)
export_params=True, # store the trained parameter weights inside the model file
opset_version=10, # the ONNX version to export the model to
do_constant_folding=True, # whether to execute constant folding for optimization
input_names=["input"], # the model's input names
output_names=["output"], # the model's output names
dynamic_axes={
"input": {0: "batch_size", 1: "sequence_len"}, # variable length axes
"output": {0: "batch_size"},
},
)
执行此过程可以将模型的大小减少 66%,并将 CPU 上的预测速度提高 68%(从 2.63 毫秒到 0.85 毫秒,以生成一个小句的预测)。
预测服务器
我们使用一个带有 RabbitMQ 和 pika 的排队系统来处理来自机器人的预测查询。
预测架构—作者图片
这种架构允许将机器人逻辑与机器学习/NLP 逻辑隔离开来,并且如果需要的话,可以更容易地横向扩展到多个预测器。
您可以使用我的存储库中的 docker-compose 文件来运行整个架构:
首先,按照本教程获取您的 bot 令牌:
[https://www.freecodecamp.org/news/create-a-discord-bot-with-python/](https://www.freecodecamp.org/news/create-a-discord-bot-with-python/)
然后,下载模型和标记器:
wget https://github.com/CVxTz/bleach_bot/releases/download/v1/toxicity_model.onnx -P ./data/wget https://github.com/CVxTz/bleach_bot/releases/download/v1/tokenizer.json -P ./data/
最后,运行 docker-compose
docker-compose up --build
机器人演示
该机器人删除分类模型给出的分数大于 0.8 的所有邮件。
接下来是演示。我使用 docker-compose 在我的机器上运行这个机器人。我们可以看到,机器人删除了所有令人讨厌的负面消息,保留了常规消息。不要眨眼,因为它真的很快😉
结论
这个项目详细介绍了使用深度学习构建一个仲裁机器人所需的第一步。该机器人经过训练,可以检测有毒或侮辱性信息,并自动删除它们。下一步将是进一步改进机器人的机器学习部分,以减少误报的数量,并致力于其部署。
来源
[1] [https://www.freecodecamp.org/news/create-a-discord-bot-with-python/](https://www.freecodecamp.org/news/create-a-discord-bot-with-python/)
密码
https://github.com/CVxTz/bleach_bot
用 Python 构建自己的语法
Python 中的拼写和语法纠正工具
良好的语法和正确拼写的单词有助于你清楚地写作和交流,并得到你想要的东西。无论你是在写一篇文章、短文还是电子邮件,用清晰正确的语言表达你的想法会给你的读者留下好印象。在打电子邮件、短文、文章等的时候,人们经常会犯很多语法和拼写错误。
Grammarly 是一家总部位于美国的技术公司,提供基于人工智能和自然语言处理的数字写作评估工具。它提供了许多免费和付费的工具,包括语法检查、拼写检查、写作辅助等。在本文中,我们将使用一个开源包**gingerit**
来实现一个可以纠正文本中拼写和语法错误的模型。
GingerIt:
GingerIt 是一个开源的 Python 包,它是 gingersoftware.com API 的包装器。Ginger 是人工智能支持的写作辅助工具,可以根据完整句子的上下文来纠正文本中的拼写和语法错误。
使用此软件包,您可以:
- 消除语法错误
- 纠正拼写错误
- 纠正标点错误
- 提高你的写作水平
这个包并不完全是 Grammarly 的克隆,但可以被看作是它的基础版本,因为它提供了一些通用的特性。目前,gingerit 只支持英语。
拼写检查和语法检查算法是如何工作的?
拼写检查器运行各种算法来纠正错别字。该算法如下:
- 首先,它扫描文本以标记出单个或一对单词。
- 它涉及字典中单词列表的标记/单词。
- 如果这些单词与任何单词都不匹配,那么它会运行编辑距离算法来建议最接近的单词或单词列表。
与拼写检查算法类似,语法检查算法也从文本中提取一个句子,并对照句子检查每个单词,根据句子中的位置查看诸如词性之类的信息。同样依赖于几个规则,该算法检测时态一致、数字、词序等方面的错误。
安装:
可以使用以下命令从 PyPl 安装 Gingerit:
**pip install gingerit**
用法:
- 在安装和导入 gingerit 包之后,它可以用来纠正给定输入文本的语法和拼写错误。
- 将文本传递给 gingerit 包中的 parse()函数,它返回一个输出字典,关键字为:“更正”、“文本”、“结果”。
**Value of the corresponding keys:****Corrections:** List of mistakes in dictionary format as starting index, mistaken text, corrected text, the definition of the corrected text.
**Text:** Original Text
**Result:** Corrected text free from grammatical and spelling mistakes
(作者代码)
从上面的代码片段可以看出,使用 gingerit 包纠正了一个不正确的语句。
(图片由作者提供),输入输出文本
结论:
在本文中,我们使用开源 Python 包实现了一个基本版本的语法和拼写检查器。gingerit 软件包的结果没有达到标准,因为它可以纠正拼写错误和轻微的语法错误。Gingerit 是一个围绕gingersoftware.comAPI 的包装器,这是一个付费版本,在纠正语法错误方面可能会有很好的效果。
language_tool 是另一个开源包,工作方式与 gingerit 包非常相似。
感谢您的阅读
建立你自己的关于人工智能道德和安全的模块化音频课程
人工智能研究前沿问题和利害关系的精选“倾听清单”
菲利普·伯恩特在 Unsplash 上的照片
人工智能和机器学习的最新进展有助于创造新的工具和产品,并推动科学知识向前发展。它们也带来了我们尚未完全理解的风险和复杂性——这些风险和复杂性从超本地化(例如,公司在人工智能驱动的招聘流程中延续偏见)到存在性(如我们所知,一般人工智能正在消灭生活😱).
很难跟上该领域的发展,更不用说理解新研究的深层含义了。但我们是来帮忙的:由 Jeremie Harris 主持的 TDS 播客第二季,聚焦于这些围绕人工智能、安全和伦理的新兴问题。我们鼓励你探索整个赛季(现在有超过 24 集,还在增加!),下面我们汇集了一个八集的节略课程,涵盖了这次对话中一些最基本的要素。
你可以按顺序进行选择,也可以根据自己的需要进行混搭。无论你是在沙滩上、做饭时还是在办公桌前听,我们希望这些讨论能激励你不断学习和思考这个及时而紧迫的话题。
布莱恩·克里斯蒂安谈校准问题
全面介绍了围绕构建安全人工智能(与我们的价值观一致的人工智能)的重大问题,以及如何找到非常清楚和正确地量化我们希望我们的人工智能做什么的方法。
海伦·托勒谈人工智能的战略和安全含义
随着人工智能技术的不断发展和变得更加强大,我们将不得不更加担心安全和保障。但竞争压力有可能鼓励公司和国家专注于能力研究,而不是负责任的人工智能开发。
大卫·罗德曼谈经济史和通往奇点的道路
现在是我们探索变革性人工智能如何、甚至何时可能从根本上改变当代经济的时候了。
爱德华·哈里斯谈机器学习中出现的问题以及如何让人工智能变得“好”
一个数据科学家可以设计出一种算法,在部署后的几分钟内,它将立即影响数百万甚至数十亿人的生活。尚不清楚我们是否已经变得足够聪明来运用这种力量。
Margot Gerritsen 谈人工智能是否必须是可理解的才是道德的
非故意的坏人工智能可能会导致各种偏见,使算法对一些人来说比其他人表现得更好,或者更普遍地说,使系统对我们实际上长期不想要的东西进行优化。
罗布·迈尔斯上为什么我们要关心 AI 的安全
在部署先进的人工智能系统之前,我们是应该努力确保它们绝对安全,还是可以在它们出现时修复它们?随着系统变得越来越强大——随着它们的部署伴随着人类不可避免且不可逆转地失去对世界的控制——似乎有可能在前期需要更多的谨慎。
西尔维亚·米兰诺谈推荐系统的伦理挑战
推荐系统是非常有价值的技术,但它们也有一些严重的道德失败模式——其中许多是因为公司倾向于建立反映用户反馈的推荐器,而没有考虑这些系统对社会和人类文明的更广泛影响。
安迪·琼斯谈人工智能安全和扩展假说
正如 GPT-3 所显示的,当人工智能系统变得更大时,它们不仅在特定的任务上表现得更好,而且在全新的、更一般的任务上也表现得更好。
有关 TDS 播客的最新剧集,请访问此页面。
使用 BERT4Rec 构建您自己的电影推荐系统
PyTorch 中基于变压器的推荐系统的分步实现
在 Unsplash 上由 Myke Simon 拍摄的照片
推荐算法是我们每天使用的许多服务的核心部分,从 YouTube 上的视频推荐到亚马逊上的购物项目,不要忘记网飞。
在这篇文章中,我们将实现一个简单而强大的推荐系统,名为 BERT4Rec:来自 Transformer 的双向
编码器表示的顺序推荐。
我们将在约 60,000 部电影的数据库上,将该模型应用于电影推荐。
任务
我们的目标是向用户推荐他们过去看过的电影。该推荐直接从数据中学习,并且针对每个用户进行个性化。
作者图片
数据
我们将使用 MovieLens-25m 数据集(https://grouplens.org/datasets/movielens/25m/)。这是一个记录 162541 个用户和 62423 部电影之间互动的数据集。
我们可以为每个用户构建他们互动的电影的时间排序序列。我们将使用这些序列来训练我们的推荐系统。
模型
BERT4Rec 很像 NLP 的常规 BERT。这是一个变形金刚网络,它被训练来从用户的历史中预测“屏蔽”的电影。
第一步是以按时间排序的电影列表的形式构建用户的历史记录。
作者图片
其中一些电影被一个符号[面具]所取代。
作者图片
然后对 BERT4Rec 模型的任务进行训练,以尝试预测[MASK]项的正确值。通过这样做,模型将学习每部电影的有用表示,以及电影之间存在的重要模式。
作者图片
然后为了进行推断,我们可以在用户序列的末尾添加一个[MASK]来预测他们将来最有可能想要的电影。
作者图片
BERT4Rec 是一种常规的转换器架构,类似于 NLP 中使用的架构:
变压器层
序列中的每个电影都被映射到一个嵌入向量。
src_items = self.item_embeddings(src_items)
然后,自我关注是允许这种架构对输入序列的元素之间的长期依赖性进行建模的原因。
顺序通过位置嵌入来建模,其中我们在每个时间步学习一个“位置向量”。
batch_size, in_sequence_len = src_items.size(0), src_items.size(1)
pos_encoder = (
torch.arange(0, in_sequence_len, device=src_items.device)
.unsqueeze(0)
.repeat(batch_size, 1)
)
pos_encoder = self.input_pos_embedding(pos_encoder)
src_items += pos_encoder
最后,在每个时间步,模型从 62423 部电影中输出每个可能选项的预测分数。我们使用这些分数来优化分类交叉熵损失。
培训日志
模型使用示例
现在,我们将使用经过训练的模型,根据三种情况提出建议:
场景 1:冒险/幻想
用户历史–>
- 《哈利·波特与魔法石》(又名《哈利·波特与魔法石》)(2001 年)
- 哈利·波特与密室(2002)
- 哈利·波特与阿兹卡班的囚徒(2004)
- 哈利·波特与火焰杯(2005)
车型推荐->
['**Ice Age (2002)**',
"**Pirates of the Caribbean: Dead Man's Chest (2006)**",
'**Avatar (2009)**',
'Star Wars: Episode III - Revenge of the Sith (2005)',
'Shrek 2 (2004)',
'Ratatouille (2007)',
'Bruce Almighty (2003)',
'I, Robot (2004)',
'Last Samurai, The (2003)',
'Up (2009)',
'Matrix Revolutions, The (2003)',
'Men in Black II (a.k.a. MIIB) (a.k.a. MIB 2) (2002)',
'Iron Man (2008)',
'**Spirited Away (Sen to Chihiro no kamikakushi) (2001)**',
'300 (2007)',
'Big Fish (2003)',
"Bridget Jones's Diary (2001)",
'My Big Fat Greek Wedding (2002)',
'Pianist, The (2002)',
'Interstellar (2014)',
'Shaun of the Dead (2004)',
'Moulin Rouge (2001)',
'Juno (2007)',
'WALL·E (2008)',
'Casino Royale (2006)',
'School of Rock (2003)',
'40-Year-Old Virgin, The (2005)',
'**Harry Potter and the Order of the Phoenix (2007)**',
'Bourne Supremacy, The (2004)',
'Miss Congeniality (2000)']
我们可以看到,该模型在冒险/幻想流派中提出了一些有趣的建议。请注意,该模型无法访问电影的类型。
场景 2:动作/冒险
用户历史–>
- 黑豹(2017 年)
- 复仇者联盟(2012)
- 复仇者联盟 3:无限战争—第一部分(2018 年)
- 洛根(2017)
- 蜘蛛侠(2002)
- 蜘蛛侠 3 (2007)
- 《蜘蛛侠:远离家乡》(2019)
车型推荐->
['**Avengers: Infinity War - Part II (2019)**',
'**Deadpool 2 (2018)**',
'**Thor: Ragnarok (2017)**',
'**Spider-Man: Into the Spider-Verse (2018)**',
'**Captain Marvel (2018)**',
'Incredibles 2 (2018)',
'**Untitled Spider-Man Reboot (2017)**',
'Ant-Man and the Wasp (2018)',
'Guardians of the Galaxy 2 (2017)',
'Iron Man 2 (2010)',
'Thor (2011)',
'Guardians of the Galaxy (2014)',
'Captain America: The First Avenger (2011)',
'X-Men Origins: Wolverine (2009)',
"Ocean's 8 (2018)",
'Wonder Woman (2017)',
'Iron Man 3 (2013)',
'Pirates of the Caribbean: The Curse of the Black Pearl (2003)',
'Amazing Spider-Man, The (2012)',
'Aquaman (2018)',
'Dark Knight, The (2008)',
'Mission: Impossible - Fallout (2018)',
'Avengers: Age of Ultron (2015)',
'Jurassic World: Fallen Kingdom (2018)',
'Iron Man (2008)',
'Coco (2017)',
'Lord of the Rings: The Two Towers, The (2002)',
'Rogue One: A Star Wars Story (2016)',
'X-Men: The Last Stand (2006)',
'Venom (2018)']
这些建议完全正确!大部分来自漫威宇宙,就像用户的历史一样。
场景 3:喜剧
用户历史–>
- 疯狂动物城(2016)
- 玩具总动员 3 (2010)
- 玩具总动员 4 (2019)
- 海底总动员(2003)
- 《料理鼠王》(2007)
- 乐高电影(2014)
- 捉鬼敢死队(又名捉鬼敢死队)(1984)
- 艾斯·文图拉:当自然召唤(1995)
车型推荐->
['**Home Alone (1990)**',
"**Bug's Life, A (1998)**",
'**Toy Story 2 (1999)**',
'Nightmare Before Christmas, The (1993)',
'Babe (1995)',
'**Inside Out (2015)**',
'**Mask, The (1994)**',
'**Toy Story (1995)**',
'Back to the Future (1985)',
'Back to the Future Part II (1989)',
'Simpsons Movie, The (2007)',
'Forrest Gump (1994)',
'Austin Powers: International Man of Mystery (1997)',
'Monty Python and the Holy Grail (1975)',
'Cars (2006)',
'Kung Fu Panda (2008)',
'Groundhog Day (1993)',
'American Pie (1999)',
'Men in Black (a.k.a. MIB) (1997)',
'Dumb & Dumber (Dumb and Dumber) (1994)',
'Back to the Future Part III (1990)',
'Big Hero 6 (2014)',
'Mrs. Doubtfire (1993)',
'Clueless (1995)',
'Bruce Almighty (2003)',
'Corpse Bride (2005)',
'Deadpool (2016)',
'Up (2009)',
"Ferris Bueller's Day Off (1986)"]
在这种情况下,该模型能够推荐一些很棒的电影,如《玩具总动员 1》或《独自回家》,这些电影符合用户历史的主题。
结论
在这个项目中,我们构建了一个强大的电影推荐系统,名为 BERT4Rec。这是一个基于 transformer 层的模型,使用与 BERT 非常相似的方案进行训练,其中我们屏蔽了用户电影历史序列的一些元素,然后尝试预测这些项目的真实值。
你看看下面代码中的实现细节–>
代号:https://github.com/CVxTz/recommender_transformer/
构建您自己的 Salesforce 数据加载器
使您的用户能够使用 Salesforce Dataloader 的强大功能,但具有可定制的用户体验
作为全球领先的客户关系管理(CRM)平台,Salesforce 是一款能够存储大量数据的出色工具。因此,管理这些数据是平台管理员的日常工作。其中一种方法是通过 数据加载器 *,*一个能够提取、插入、更新和删除 Salesforce 记录的客户端应用程序。
当我在 2018 年夏季实习期间第一次开始与 Salesforce 合作并使用 Dataloader 时,我记得我很害怕不小心做错事情。一打开它,所有我能接触到的物品就出现在我面前,即使我一开始并不知道它们的存在或对它们感兴趣。虽然可以限制哪些用户可以使用该工具,但我感兴趣的是能够在其中定制用户体验,并创建一个更可控和优化的环境。这样,我可以选择只向销售团队显示业务机会、销售线索和客户,或者向开发团队显示自定义元数据类型和自定义设置,而不是显示组织内的所有对象。选项是无限的,在本文中,我将介绍一个尝试完整模拟 Salesforce 数据加载器的应用程序,它可以作为构建更多定制体验的垫脚石。它的一些限制是,它在一个作业中最多只能插入、更新和删除 10k 条记录,输入 Excel/Csv 文件中的列名必须与您尝试写入的字段的“API 名称”完全匹配,并且登录需要从您在 Salesforce 中的个人设置中获得的安全令牌。该解决方案使用 simple_salesforce 和 salesforce_bulk Python 包来处理数据,并使用 Tkinter 来构建用户界面。
应用程序
我只在文章正文中包含了部分代码。要检查整个事情,导航到https://github.com/soravassi/FauxSFDCDataloader
登录窗口
当用户第一次打开应用程序时,他们会发现一个简单的 Tkinter 窗口,必须在其中插入用户名、密码和安全令牌。按下“登录”后,将调用 Login()函数并构建主菜单。
炙单
认证后,将出现操作选项。
query 按钮调用查询操作特有的顶层 Tkinter 窗口,因为它的用户体验与其他操作稍有不同。插入、更新和删除按钮都调用同一个窗口模板,通过函数“open_secondary(operation)”上的关键字参数指定动作
动作窗口
该应用程序有两个主要的操作窗口模板:一个用于查询,另一个用于写操作(插入、更新、删除):
查询窗口
查询页面利用两个 Tkinter 列表框来帮助用户构建他们的 SOQL 查询。第一个列表框是 SOQL 查询的结果,它包含 Salesforce 中所有对象的名称,而第二个列表框是 SOQL 查询的结果,它包含第一个列表框中所选对象内的所有字段名称。在这里,用户可以按“创建查询”,这将根据他们的列表框选择编译查询,或者直接在文本框中编写查询,然后单击“提取”以生成包含所需数据的 Excel 文件。
用于编译“open_query()”函数中的对象名的代码段,该函数打开查询顶层窗口
分别按下“显示字段”、“创建查询”和“提取”时运行的功能
更新/插入/删除窗口:
此窗口的行为类似于查询窗口,因为在打开它时,列表框将显示您可以在其中执行所需操作的对象。主要区别在于,对于写操作,应用程序利用 salesforce_bulk 包而不是 simple_salesforce,并且用户必须输入从中选择字段的 CSV/Excel 文件,而不是在第二个列表框中选择受影响的字段。
提示用户选择输入文件,并将其保存在数据帧上
“动作(操作)”功能的一部分,启动批量数据作业并编译结果。
将这一切结合在一起
使用 Tkinter 构建这样一个应用程序的好处在于,您可以快速推出它的不同版本。例如,您可以使应用程序的某些方面(如他们可以访问的对象列表)以用户的配置文件为条件。
其他选项可能只显示查询按钮,或者隐藏删除按钮。根据我自己的个人经验,我创建了该应用程序的多个版本,帮助产品所有者提取选项列表值及其依赖关系,并帮助质量保证用户更改他们自己的配置文件,以便从业务用户的角度测试新功能,而无需授予他们“管理用户”权限或“登录身份”功能。正如我说过的,天空是无限的,具体的应用将因 Salesforce 的实施而异。希望这有助于帮助用户以更加定制化和定制化的体验处理数据。
威廉·冈克尔在 Unsplash 上拍摄的照片
感谢您的阅读!这是我尝试分享一些代码和我试图解决的一个问题的解决方案的第一篇文章。我很感激你所有的建设性反馈,从文章的结构到代码本身。
更多项目,我邀请您参观andrecarmo.com
构建更好的数据文化:采访 ThoughtSpot 首席数据战略官辛迪·豪森
数据停机访谈
与辛迪·豪森就如何实现大规模数据民主化展开对话。
我们与领先的搜索和人工智能驱动的分析平台thought spot的首席数据战略官 辛迪·豪森 进行了广泛的交谈,讨论了她的日常工作、组织在数据民主化道路上面临的共同挑战以及数据科学的多样性。
在过去的几十年里,数据分析领域经历了从孤岛式实体到跨职能机构的转变。现在,在 2021 年,在这个数据十年中,又一次巨变的时机已经成熟,这次是以数据民主化和可访问性的形式。
ThoughtSpot 为这一走向可操作和精确分析的新运动铺平了道路,首席数据战略官 Cindi Howson 负责该公司的客户支持计划。
刚刚获得雪花对 ThoughtSpot 的 2000 万美元投资,辛迪一直很忙。从帮助组织更智能地利用他们的数据到代表 STEM 中的女性进行宣传,Cindi 是数据分析领域最杰出的声音之一。而且理由很充分。
在加入 ThoughtSpot 之前,Cindi 曾在 Gartner 担任副总裁,并担任分析和商业智能魔力象限的主要作者。她还创建了 BI 记分卡,这是评估商业智能解决方案的第一个行业框架。现在,在 ThoughtSpot,她正围绕在整个企业中构建(和扩展)数据战略的意义展开对话。
我们与 Cindi 进行了交谈,以了解她在数据分析方面的更多信息,ThoughtSpot 的首要目标是什么,以及行业如何使 STEM 更具包容性:
在您的职业生涯中,您评估了各种 BI 和分析解决方案,以帮助您的客户更好地了解这种情况。有没有让你惊讶的行业趋势?
对我来说最大的惊喜之一是,我们仍然不擅长如何评估新技术,这听起来很疯狂。
如果你想想 iPhone 刚出来的时候,人们会说,“等等。我的键盘呢?”他们把它和黑莓进行了比较。甚至当 iPad 出来的时候,你会说,“等等,那个 u 盘在哪里?”我们一直想把东西放回旧的评估框架中。作为一个技术行业,我们必须意识到旧框架的局限性,以及它们移动的速度有多慢。
我们关心的一件事是让每个人都能轻松地进行分析——采用消费级易用性的概念,如 Spotify 或 iTunes,并将这种易用性应用于数据和分析。如果以前没有人考虑过这个问题,它甚至可能不会出现在你的评估列表中。令我惊讶的是,作为一个行业,我们仍然没有想出如何做得更好。
作为首席数据战略官,您能更详细地介绍一下您现在的角色吗?听起来人们经常错误地认为你可能负责在内部塑造自己公司的数据文化,但事实并非如此。
所以实际上,我的角色有三个方面。一个是与我们的顶级客户合作,指导他们克服障碍。许多障碍不是技术,而是文化。是人们改变管理和数据流畅性,所以我帮助他们驾驭这些东西。它还可能会考虑什么样的工具适合合适的用户,以及管理他们的 BI 工具组合的用例。
但是,当我与我们的客户一起工作时,他们也会给我反馈,告诉我我们需要将我们的产品带到哪里,以继续保持市场上的最佳和领先优势。因此,我与我们的产品团队合作,要么解决差距,要么规划下一波颠覆和创新。
然后第三部分实际上是这样的事情,巴尔——成为一个思想领袖,并与像你这样的人会面。因此,去年,我的目标之一是推出数据首席播客,我可以与团队一起完成这项工作,并参与整个行业的活动。
我见过这种数据囤积的现象,组织每天吸收、转换和处理如此多的数据,但实际上这些信息中只有很小一部分得到了利用。您认为数据组织如何才能消除噪音并从分析中获得更多价值?
我不知道我们囤积了这么多,因为技术落后了。获取数据的能力超过了我们获得洞察力的能力。
这就是我认为云改变了游戏的地方。从历史上看,由于计算和桌面分析产品有限,因此出于性能原因,许多分析必须进行汇总和简化。在云中运行分析,您不再需要这样做。我认为这是为什么我们会陷入捕捉多于实际分析的陷阱的部分原因。
传统公司的数据团队如何开始迁移到云并推动数字化转型的旅程?如果有的话,你见过哪些效果最好的?
首先,我们不能称他们为传统公司,因为他们没有死。但也许我们会称他们为落后者,我想这是《哈佛商业评论》的术语。
我认为疫情向我们展示了你过去认为不可能的事情,比如将客户数据放在云中,甚至共享医疗保健或其他私人数据——实际上,这是非常可能的。当您的业务成果一致时,很有可能更快地完成工作。如果你走老派路线,你可能会让恐惧和对改变的抗拒拖慢你的脚步,阻碍你前进。这就是这些组织将成为传统组织的时候。
我想到了 Clayton Christensen,以及他关于颠覆性创新和创造性破坏的观点:仅仅因为你今天运作良好并不意味着你明天就会成为领导者。我听过 Instacart 的一位领导说过一句话,我很喜欢,他说“你的下一个竞争对手可能是两个在大学宿舍里的女人,她们想出了最酷的创业公司。”云和开源技术降低了众多领域的准入门槛
这无疑是数据民主化趋势的一部分,这一运动旨在让每个人都可以访问数据。在你看来,真正的数据民主化是什么样子的?
我脑海中经常浮现出老派电话接线员或总机接线员的形象。这就是所发生的事情,因为 BI 工具最初很难使用,并且需要专业培训。这种模式无法扩展,也无助于业务发展。
了解该领域的人,知道他们想问的问题,应该能够获得真知灼见。有太多的窃窃私语偏离了方向。我的客户会谈到仪表板积压。供给和需求是不平衡的,因为对新数据、更及时的见解和更复杂的问题的需求超过了能够回答这些问题的分析师的供给。
您之前提到过,与业务成果挂钩有助于迁移或推动转型。负责这些重要计划的数据领导者如何将他们与业务成果联系起来?
作为 ThoughtSpot 的首席数据战略官,辛迪·豪森(Cindi Howson)通过更易于访问的人工智能驱动的分析,帮助客户运营他们的数据。
我经常告诉 CDO 和分析主管,从他们最大的痛点或最高价值的机会开始。你不想从你的超级乱七八糟的数据开始,因为人们会失去兴趣和信心。
说客户忠诚度是你生意中的头等大事。我们通过 NPS 分数来衡量这一点,但还有其他指标,如响应服务请求的时间或与客户忠诚度相关的准时交付。
通过了解这些数字并确定 NPS 得分或响应时间最低的服务代表,您可以深入了解这些数据点背后的原因。他们 NPS 分数最低是因为训练吗?也许是因为他们的耳机电话并没有那么好?我们可以修好那些东西。因此,数据大众化实际上是执行这些业务成果的一个推动者。
我认为很多人是从下往上开始的,因为变化不是从上往下的。那些数据专业人员或技术专业人员可能是知道可能性艺术的人。因此,他们可能会做一个概念或技术的证明,说,好吧,我们有这些数据,我们认为这是一个没有人关注的价值。让我快速向你展示可能的艺术。
对我来说,技术创新和数字化转型的区别在于,在你证明了这个概念之后,你必须找到一个拥护者来说,“是的,这将有助于提高我们的业务绩效。”
我经常看到的另一个挑战是,无论你的数据分析解决方案有多好,如果你不信任你的数据,就很难获得有意义的见解。您见过客户如何处理数据质量和数据可靠性?
信任是一个大问题。这确实与数据素养,或者我们喜欢说的数据流畅性有很大关系。
我确实认为,数据技能将继续成为全体员工的必备技能。我们已经看到小学和初中越来越多地教授这种课程。甚至 SAT 现在实际上也包括了解决某人数据素养的问题。但是现在,大多数员工都不懂得数据。不幸的是,有了 COVID,你真的可以看到人们不明白数据从何而来,意味着什么。
当人们明白数据来自哪里,当他们明白即使是高质量的数据也不会完全干净时,您就建立了信任。我喜欢我们的一位数据分析领导者谈论“数据在方向上准确吗——准确到足以做出决策吗?”
现在有些事情必须做到完美。举例来说,你必须确定你的血型。但是,如果我着眼于活动分析和客户体验趋势,我们可以利用足够准确的数据做出决策。
几年前,你写了一篇名为 的伟大文章,我们可以把男人送上月球,但我们不能把女人留在科技领域 。我喜欢这个标题,它是关于技术多样性的商业案例,以及是什么阻止了我们实现更公平的劳动力。对于许多数据驱动的公司来说,增加 STEM 中表示的多样性是一个巨大的优先事项,但显然,许多公司都做不到。事实上,根据 BCG 统计,如今的数据科学家中只有 15%是女性。在你看来,为了创造一个更具包容性的行业,我们需要做哪些完全不同的事情?
我想说,嗯,自从我一年前写了那个博客,事情已经变得更好了。但不幸的是,在疫情,情况变得更糟了。部分原因与虚拟学校教育有关,女性在家工作时必须在家教学,然后可能还要照顾生病的父母或兄弟姐妹。这很难。
如果有一线希望,我会说,2020 年发生在乔治·弗洛伊德和布里奥纳·泰勒身上的种族不公正提高了对话的水平。人们现在说,我们不能一直谈论这个。我们确实需要将它与行动结合起来。因此,我很高兴地看到,组织实际上正在更多地衡量这些事情,并主动制定计划来解决这个问题。例如,星巴克现在将高管薪酬与实现各种多元化目标的高管挂钩。纳斯达克提议将多元化指标作为在纳斯达克上市的一项要求。
现在我确实有一种担心——希望它是错误的或者没有根据的——但是担心这会适得其反,因为没有人愿意被雇佣去打勾。他们希望被雇用,因为他们是这项工作的最佳人选。他们只是不想让这些无意识的偏见或系统性的偏见妨碍他们打针。
让我们以一些有趣的问题来结束。2020 年你最喜欢的书是什么?
在小说方面,我喜欢星星的给予者,它基于一个关于肯塔基州的驮马图书馆员的真实故事。然后从商业和分析方面来说,我真的很喜欢约翰·汤姆逊的建立分析团队和艾琳·迈耶的文化地图。
播客或时事通讯呢?你今年学到了什么最喜欢的东西吗?
我确实听过雪花的数据云的兴起。如果允许我说,我喜欢那些如此乐意分享他们对数据主管的灵感的客人。所以我实际上是在录音后听的。当然,我会听布伦·布朗的歌。
至于时事通讯,我刚刚订阅了《原子习惯》的作者詹姆斯·克利尔的一篇,它真的很不错。
有兴趣在ThoughtSpot了解更多关于辛迪的作品?关注她上 推特 或者LinkedIn***!***
阅读更多来自蒙特卡洛数据停机采访系列的内容:
- 将可靠的数据和人工智能带到云端:A Q&A with Data bricks ’ Matei Zaharia
- 关于数据治理:SAP 企业数据战略和转型主管 Maria Villar
- 用数据对抗流失:卡尔·戈尔德访谈
构建生物医学知识图谱
使用公开可用的数据集对复杂的生物医学数据进行分析推理
听取 Vaticle 社区讲座的汇报—主讲人是罗氏系统生物学科学家 Konrad myliwiec。这个演讲是四月份在轨道 2021 上虚拟发表的。
像许多 TypeDB 社区成员一样,Konrad 来自不同的工程背景。自从为 GSK 开发企业知识图以来,知识图一直是他工作范围的一部分。他加入 TypeDB 社区已经大约 3 年了。虽然他的大部分职业生涯都在生物医药行业度过,但他也花时间研究商业智能应用程序,开发移动应用程序,目前是罗氏制药公司 RGITSC(罗氏全球 IT 解决方案中心)的数据科学工程师。
去年,康拉德开始注意到网上的一种趋势,无论是 LinkedIn 上的文章还是他的生物医学网络;知识图表到处都是。鉴于世界正处于与新冠肺炎·疫情的斗争中,他想知道知识图谱是否能帮助他的生物同龄人的努力。
在开发 BioGrakn Covid 的过程中,他试图将这两个主题结合在一起,以提供一种更容易理解和有用的方法来支持疫情期间的研究和生物医学斗争。在这个演讲中,他描述了他和一组 TypeDB 社区成员如何处理一些技术开发领域。
外卖:
- biog rakn Covid——它是什么,项目的目标是什么
- 公开可用的数据源和本体——什么数据被加载到 BioGrakn Covid 中
- 知识提取—处理非结构化数据
- 分析推理——如何在知识图上进行一些分析
建筑 BioGrakn Covid
BioGrakn Covid 是由 Konrad、Vaticle 的 Tomás Sabat 和 GSK 的 Kim Wager 共同发起的开源项目。这是一个以新冠肺炎为中心的数据库。
用图表表示生物医学数据
一旦我们认识到生物医学数据的自然表示倾向于类似图形,将生物医学数据建模为图形就成了显而易见的选择。图形数据库传统上将数据表示为二进制节点和边。想想标签属性图,其中两个节点通过有向边连接。康拉德和他的同事很快意识到,用超图来表示生物医学数据变得更简单,最终也更自然,就像在 TypeDB 中发现的那样。
图表与超图模型—经许可使用的幻灯片
超图通过放宽边的定义来概括图的一般概念。图中的边只是一对顶点。相反,超图中的超边是一组顶点。这种顶点集可以进一步结构化,遵循超图的不同可能定义中涉及的一些附加限制。
在 TypeDB 中,模型使用矩形来表示实体(节点),菱形表示关系或超关系(一个关系中有 n 个角色)。
TypeDB 图表示例—经许可使用的幻灯片
使用的数据源
目前,在 BioGrakn Covid 中有相当多的公开数据集。简而言之,以下是数据库中包含的一些数据集和映射:
BioGrakn Covidslides 中使用的数据集经许可使用
- https://www.uniprot.org/—实体(转录本、基因、蛋白质),关系(翻译、转录、基因-蛋白质编码)
- 人类蛋白质图谱 —实体(组织)、关系(表达)
- https://reactome.org/—实体(通路),关系(通路——参与)****
- DGldb —实体(药物),关系(药物-基因-相互作用)
- https://www.disgenet.org/—实体(疾病),关系(基因-疾病关联)
- 冠状病毒 —实体(病毒)、关系(生物体-病毒宿主、基因-病毒关联、蛋白质-病毒关联)
- ClinicalTrials.gov—实体(临床-试验,组织),关系(临床-试验-协作,临床-试验-药物-关联)
保持数据质量 我们很多人都知道,从上述来源获取数据并将其加载到数据库中并不简单。首先需要考虑数据质量。正如 Konrad 在他的演讲中指出的,保持数据质量是这项工作的一个重要方面。
你不希望有任何数据差异,你不希望有几个节点代表相同的实体,因为这将影响和偏见你的分析在未来。
他们解决数据质量问题的方法是使用像 UMLS(统一医疗语言系统)这样的数据源。UMLS 提供了一些有助于维护数据质量的结构和上下文。在演讲中,康拉德关注了 UMLS 的两个子集。第一个,UMLS 的“Metathesaurus ”,包含了各种类型不同层次的生物医学实体,如蛋白质、基因、疾病、药物以及它们之间的关系。
作为可用的例子,我们有两种蛋白质:protein-1
和protein-2
,它们通过interact-with
边缘连接。
将 UMLS 映射到 TypeDB 架构—经许可使用的幻灯片
第二个子集是语义网络数据。这集中在分类法上。每个概念都在一个分类法中给出,例如,我们有一个概念compound
,而protein
是compound
的一个子类型。这个子集的好处将在以后变得更加明显。
使用 UML 作为初始或基线本体给了我们信心,我们可以在没有数据质量问题的情况下前进——显然,这不是解决数据质量挑战的唯一方法。尽管如此,UML 在生物医学领域仍然是有效的。
定义 TypeDB 架构
TypeDB 中的 Schema 为我们的数据提供了结构和模型,并且知道所有被接收到数据库中的数据都将遵守这个模式,这是安全的。
在 Konrad 的案例中,他们正在创建一个具有实体的生物医学模式:protein
、transcript
、gene
、pathway
、virus
、tissue
、drug
、disease
;以及它们之间的关系。应该注意的是,这些决策中的大部分都可以从您使用的数据源中推导出来。
以下是该模式的摘录:
**define
gene sub fully-formed-anatomical-structure,
owns gene-symbol,
owns gene-name,
plays gene-disease-association:associated-gene;
disease sub pathological-function,
owns disease-name,
owns disease-id,
owns disease-type,
plays gene-disease-association:associated-disease;
protein sub chemical,
owns uniprot-id,
owns uniprot-entry-name,
owns uniprot-symbol,
owns uniprot-name,
owns ensembl-protein-stable-id,
owns function-description,
plays protein-disease-association:associated-protein;
protein-disease-association sub relation,
relates associated-protein,
relates associated-disease;
gene-disease-association sub relation,
owns disgenet-score,
relates associated-gene,
relates associated-disease;**
现在我们有了模式,可以开始加载数据了。
摄取结构化数据
在讲座中,Konrad 演示了如何从 UniProt 加载数据,其中也包含来自 Ensembl 的数据。首先要做的是识别相关的列,然后根据我们的模式,识别要用数据填充的相关实体。从这里开始,为每个概念添加属性就相当简单了。
将 UniProt 映射到 TypeDB 模式—经许可使用的幻灯片
加载数据很简单——使用 Python、Java 或 Node.js 中的客户端 API。Konrad 为 UniProt 数据构建了这个迁移器——可通过 BioGrakn Covid repo 获得。
那些积极使用这些类型的公开可用数据集的人知道,它们不会像我们希望的那样频繁更新。其中一些是每年更新的,所以我们需要用相关的当前数据来补充这些数据源。这里的问题是,这些数据通常来自论文、文章和非结构化文本。要使用这些数据,需要一个子域模型。这使我们能够更有表现力地处理文本,并最终将其与我们的生物医学模型联系起来。这两种型号如下所示:
在 TypeDB 模式中一起使用两个域模型—经许可使用的幻灯片
知识抽取
随着模式集和发布的确定,需要解决一些挑战。Konrad 强调了其中的两个:从文本中提取生物医学实体,并在一个中心知识图中链接不同的本体。
从文本中提取生物医学实体
在应对这一挑战时,Konrad 提醒我们不要重新发明轮子,而是要利用现有的命名实体识别语料库。在这个项目中,康拉德公司使用了 NER 科德公司和 SemMed 公司。
命名实体识别是在文本中识别命名实体的自然语言处理算法。
软线 NER
绳索 NER 是预先计算的命名实体识别输出的数据源。CORD NER 的优点是 NLP 工作的输出,来自文本的实体,被映射到 UML 中的概念。这有助于在知识图中提供一致性和数据质量。有了概念及其类型,我们现在可以映射到 TypeQL 中的模式。
经许可使用的幻灯片
SemMed
SemMed 包含从 PubMed 中可用的出版物派生的实体,这些实体存储在语义三元组中。CORD NER 的问题是它不包含命名实体之间的任何链接,而 SemMed 确实提供了这些链接。这些语义三元组由主语、谓语和宾语组成。所有这些都与 UMLS 元霸王龙相对应,这再次帮助我们在知识图谱中保持一致的命名惯例。
下面你可以看到一个例子,说明 Konrad 如何处理 SemMed 中的数据。这是两个表的简单连接,我们看到主语、谓语和宾语:NDUFS8
是基因组,NDUFS7
也是基因或基因组,interacts-with
是它们之间的谓语或关系。SemMed 自然地从文本中导出这些联系,并且当涉及到将这些实体映射到定义的模型时,这为我们提供了所需的大部分内容。事实上,Konrad 注意到大约有 18 种不同的谓词可以映射到模式中的关系。
经许可使用的幻灯片
经许可使用的幻灯片
使用 SciSpacy 进行文本处理
很多时候,我们需要自己从论文中的非结构化文本中提取结构化数据。对于 Konrad 来说,这里的挑战是处理临床试验数据,这些数据通常以 XML 数据的形式出现。
问题在于有时输出并不直接。它可以提供一种以上的药物、化合物或化学品以及其他信息。为了对这些数据进行 NER,康拉德推荐使用科学软件。SciSpacy 是一个 Python 库,构建于 Spacy 之上,它使用一个在公开出版物上训练过的 transformer 模型来执行 NER。用它来对照上面的例子,它可以识别两个命名实体,更好的是,它提供了 UMLS 的映射。
生物数据中的 ID 解析
另一种可能出现的情况是当本体中的 ID 不存在于您正在处理的数据中时。为了解决这个问题,我们可以使用实体的规范名称,并使用类似于 RxNorm 的 API 来获取一个 RxNorm ID,然后可以用它来查找丢失的 ID。
经许可使用的幻灯片
转换图表
一旦加载了数据,我们如何开始遍历图表以生成一些见解和/或新信息?在下面的截图中,Konrad 浏览了一个查询的可视化结果。
TypeDB studio 查询可视化—经许可使用的幻灯片
更高层次的问题是:
找出在与 SARs 病毒的关系中起 *host*
作用的、受另一个基因刺激的任何基因;以及与刺激基因相互作用的药物;最后,提到基因之间关系的出版物。
在 TypeQL 中,该查询如下所示:
**match
$gene isa gene;
$virus isa virus, has name "SARs";
$r(host: $gene, virus: $virus) isa gene-virus-host;
$gene2 isa gene;
$r2(stimulating: $gene2, stimulated: $gene) isa gene-gene-interaction;
$r3(mentioned: $r2, publication: $pub) isa a mentioning;
get $gene, $gene2, $pub;
$drug isa drug;
$r4 (interacted: $gene2, interacting: $drug) isa gene-drug-interaction;**
这个问题在 TypeDB 中变得非常容易查询,并且代表了在限制探索空间的同时遍历图是多么简单。
其他查询可以帮助我们从临床试验数据中了解更多信息。我们能够识别临床试验的潜在目标、赞助组织的标识符,并将这些信息与我们对药物、药物-基因关系和药物-疾病关系的了解联系起来。
其他查询示例可在 Github 上的 BioGrakn Covid repo 中找到。
图的分析推理
因为 BioGrakn Covid 是一个开源数据库,任何人都可以自己使用它;如果不提及获取价值的其他方式,那将是我们的失职。
众所周知,给定网络中的社区——尤其是生物医学网络中的社区——倾向于聚集在一起,在特定网络或整个系统中创建共享功能的社区。给定网络中节点的这个函数可以从它们的 n 跳 egonet 或邻居中导出。例如,在蛋白质-蛋白质相互作用网络中,蛋白质倾向于与共享类似功能(如代谢过程或免疫信息)的其他节点聚集在一起。
PPI 网络—经许可使用的幻灯片
我们可能有一个关系的假设,但我们需要确认这个关系是否应该存在于数据库中。我们可以使用图形神经网络来实现
为了创建或识别这些类型的集群,我们可以执行一些任务:节点分类、链路预测和图形分类。Konrad 选择将本次演讲的重点放在链接预测上,因为他觉得这是继续探索 BioGrakn Covid 的最令人兴奋的途径。
链接预测
在 BioGrakn Covid 中,我们已经实例化了现有的关系,但是,Konrad 想要识别隐含的、未发现的关系。这是由于生物医学知识图表是出了名的不完整。找到自动完成它们的方法是非常令人兴奋的。这样做之后,可以直接从图表中得出新的见解。
经许可使用的幻灯片
他使用的方法是假设关系存在,并使用图形神经网络(ML 中的一个新的热门话题)来确认这一点。
接近
使用图邻接矩阵的特征向量加上图的结构特征作为特征,Konrad 能够训练平面图卷积神经网络。要预测的新关系是现有节点之间的假设的“疾病-基因”和“疾病-药物”关系,并且通过从所有可能和不可能的关系类型中进行负采样来获得负样本。
在机器学习中,术语负采样描述了从不存在的数据中抽取随机样本作为负样本的行为。在不完整的图中,负样本可能确实是正的,但根据经验,Konrad 发现这种方法效果很好。
结果
Konrad 使用模型上的最终 Softmax 层来生成关系存在的概率。
他发现,随着阈值的变化,精确度和回忆的行为如下图所示。他对 85%的回忆值感兴趣,这在两条曲线上都标有一个红点。令人高兴的是,我们可以看到,在这个性能点附近,我们看到了精确度和召回率的平衡。
经许可使用的幻灯片
从另一个角度来看结果,我们可以看到固定召回率为 85%时的混淆矩阵。在这一点上,他给出了 91.16%的精确度。我们还可以注意到矩阵是相当平衡的。我们看到有 50,160 个假阴性,略多于 31,007 个假阳性。作为比较,我们看到 303,393 个真阴性和 264,240 个真阳性。
经许可使用的幻灯片
基因关系预测
Konrad 对所做的基因关系预测进行了特别分析,他对是否所有这些预测都能被正确分类表示怀疑。为了进一步研究,Konrad 对靶向另一个节点(化合物或另一个基因)的基因的前 5 个关系预测进行了抽查。他发现这些预测的关系中有 3 个已经在文献中的一篇或多篇论文中进行了研究。
药物关系预测
对网络预测的前 5 种药物-疾病相互作用进行抽样检查,他在文献中发现其中 2 种已经确定存在。
经许可使用的幻灯片
经许可使用的幻灯片
康拉德自然对他使用这些方法所取得的成就感到非常兴奋,并对如何扩大该方法的范围和准确性有很多想法,正如他在演讲视频中概述的那样。
6 月 30 日,我们将举办一场关于加速药物发现和在 TypeDB 中建立生物医学数据模型的网络研讨会。你可以通过变焦加入。
你能提供什么帮助
这是一个正在进行的项目,我们需要你的帮助!如果您想做出贡献,您可以帮助我们,包括:
- 迁移更多数据源(如临床试验、药物库、Excelra)
- 通过添加相关规则来扩展模式
- 创建网站
- 撰写教程和文章,供研究人员入门
如果您希望取得联系,请通过#biograkn 频道联系我们的 Discord ( 链接此处)。
特别感谢康拉德的辛勤工作、热情、灵感和透彻的解释。
你可以在 Vaticle YouTube 频道点击找到完整的演示文稿。