深度学习滴滴:破解验证码
在浏览了一些网站后,我发现了这样一个验证码:
作为一个人工智能爱好者,我总是想到计算机模仿人类。所以一些自然的问题出现在我的脑海里:“这似乎是一个容易破解的验证码。为什么他们在这个网站使用它?”“我能用我所知道的机器学习破解这个验证码吗?”,“这要花多长时间?”。
一周后,我在 Tensorflow 中创建了一个模型,可以以 96%的准确率解决这种验证码。我只用了一台普通的电脑就做到了,成本很低。我写这篇文章的动机并不是声称简单的验证码是可以解决的(这并不奇怪),而是我想强调一下现在做这个是多么容易。
仔细看看
这种验证码的低效始于它缺乏方差。这是另一个例子:
我们总是有一个 6 个字母并排的灰度图像,背景中有一些随机噪声。模式是如此固定,以至于我们可以很容易地将图像分解成 6 个不同的较小图像序列:
每个图像显示一个字符。但是等一下,字符识别是我们在深度学习中学到的最基础的东西!如果我们将这些小图片中的每一个都视为与来自 MNIST 数据集的图片相似的图片,我们就将验证码问题转化为模式识别问题。作为输入,我们有一个 50x28 的图像,作为输出,我们有像“A”、“g”、“5”等标签。
现在的问题是如何建立数据集。在过去,我必须花一些时间来标记一堆图像,以产生一个合理大小的数据集,或者在最好的情况下,我可以召集一个朋友任务组来帮助我。但每个人都有更重要的事情要做(我也是)。所以我决定稍微作弊一下。我使用了一些承诺低价破解验证码的付费网站。花了一些钱后,我得到了大约 6 万个验证码。
剩下的就是机器学习程序了。我将数据分为训练、验证和测试,并训练了一个卷积神经网络。我写了一个超参数调整的脚本,并让它在一个周末在一台计算机上运行(仅 CPU)。
其中一个结果是,我并不需要我认为的那么多数据:
当我使用一组 50k 验证码时,获得了最好的结果,但是如果,例如,我们将其与 5k 图像的样本进行比较,改进并不巨大。
就是这样。验证码解决了。如果我想,我可以破解那个网站 96.68%的验证码。
最后
当然,我不会透露这些验证码来自哪个网站。但是你不需要走很远就能碰到类似的情况。互联网上有很多例子:
不用说,像这样的验证码是完全没有效率的。这样做既不需要强大的计算机能力,也不需要惊人的黑客技能。在只有 3k 个例子的数据集上,我得到了非常好的结果,为了得到这么多的验证码,我只需要花 3 美元!
现在有了机器学习工具,破解这样的验证码只需要 3 美元和一台普通电脑。网站创建者认为机器人能做的和机器人真正能做的似乎不匹配。
因此,如果这里有一个教训是,如果你担心你的网站上的机器人,你不应该使用这种验证码。谷歌的 reCAPTCHA 是一个更好的选择。
看到这些结果,我认为任何关于创建新验证码的讨论都应该从卷积神经网络的能力和局限性开始*。*
初学者的深度学习
Python 和 Keras 实用指南
这篇文章将展示如何使用 Keras 对数字识别的示例进行编码,以向读者提供使用这个 Python 库进行深度学习的第一次实际接触,该示例在之前的文章(我强烈建议之前阅读它)中给出。
环境设置
为什么是 Keras?
Keras 是推荐给初学者的库,因为与其他库相比,它的学习曲线非常平滑,目前它是实现神经网络的流行中间件之一。Keras 是一个 Python 库,它以一种简单的方式,使用 TensorFlow、Theano 或 CNTK 等其他库作为后端,提供了广泛的深度学习模型的创建。它由来自谷歌的工程师弗朗索瓦·乔莱开发和维护,他的代码已经在麻省理工学院的许可下发布。还有一点很重要,Keras 作为 API 包含在 TensorFlow 中。虽然 Keras 目前包含在 Tensorflow 包中,但是也可以作为 Python 库使用。首先,我认为第二个选择是最合适的。
这篇文章中的代码可以在 GitHub 中以 Jupyter 笔记本的形式获得(https://GitHub . com/JordiTorresBCN/DEEP-LEARNING-practical-introduction-with-Keras),尽管如果读者愿意,这可以作为 Python 中的正常程序运行。
合作环境
在本帖中,我们将使用 Google 提供的 合作实验室 。
这是谷歌的一个研究项目,旨在帮助传播机器学习教育和研究。这是一个 Jupyter 笔记本环境,不需要任何配置,完全在云中运行,允许使用 Keras、TensorFlow 和 PyTorch。Colab 区别于其他免费云服务的最重要的特点是;Colab 提供 GPU,完全免费。关于该服务的详细信息可以在常见问题页面上找到。
笔记本存储在 Google Drive 中,可以像使用 Google Docs 一样共享。这个环境是免费使用的,只需要一个谷歌账户。此外,该环境允许免费使用 NVIDIA K80 GPU。
第一次进入时,您会看到如下所示的窗口。在此窗口中,您应该选择 GITHUB 选项卡,并在 URL 字段中填写“JordiTorresBCN”,在存储库字段中填写“JordiTorresBCN/DEEP-LEARNING-practical-introduction-with-Keras”。
要加载笔记本,请单击出现在他们右侧的按钮(在新选项卡中打开笔记本):
默认情况下,Colab 笔记本运行在 CPU 上。你可以切换你的笔记本运行 GPU。为了访问一个 GPU,我们需要选择选项卡 Runtime ,然后选择“Change runtime type ”,如下图所示:
当弹出窗口出现时,选择 GPU。确保“硬件加速器”设置为 GPU(默认为 CPU)。
可能会出现一条警告,指出该代码不是由 Google 创建的。我希望您相信我的代码,并运行它!;-)
然后,确保您已连接到运行时(在菜单功能区中“已连接”旁边有一个绿色复选标记):
现在你可以在 Google Colab 中运行 GitHub repo 了。尽情享受吧!
输入神经网络的数据
用于培训、验证和测试的数据集
在展示前一个例子的 Keras 实现之前,让我们回顾一下我们应该如何分配可用的数据,以便正确地配置和评估模型。
对于机器学习中模型的配置和评估,因此深度学习,可用数据通常分为三组:训练数据、验证数据和测试数据。训练数据是那些用于学习算法的数据,以通过我们已经提到的迭代方法获得模型的参数。
如果模型不完全适应输入数据(例如,如果它出现过度拟合),在这种情况下,我们将修改某些超参数的值,并在使用训练数据再次训练它之后,我们将使用验证数据再次评估它。我们可以在验证数据的指导下对超参数进行这些调整,直到获得我们认为正确的验证结果。如果我们遵循了这个过程,我们必须意识到,事实上,验证数据已经影响了模型,所以它也符合验证数据。由于这个原因,我们总是保留一组测试数据用于模型的最终评估,这些数据只会在整个过程结束时使用,此时我们认为模型已经过微调,我们将不再修改它的任何超参数。
考虑到这篇文章的介绍性质,我们不会深入到超参数调优的细节,在示例中,我们将忽略验证数据,只使用训练和测试数据。
Keras 中预加载的数据
在 Keras 中,MNIST 数据集以四个 Numpy 数组的形式预加载,可通过以下代码获得:
import kerasfrom keras.datasets import mnist
(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train 和 y_train 包含训练集,而 x_test 和 y_test 包含测试数据。图像被编码为 Numpy 数组,它们对应的标签从 0 到 9。按照 post 的策略,逐步引入主题的概念,正如我们已经指出的,我们还不会看到如何分离一部分训练数据来使用它们作为验证数据。我们将只考虑训练和测试数据。
如果我们想检查我们加载了哪些值,我们可以选择 MNIST 集的任何图像,例如图像 8,并使用以下 Python 代码:
import matplotlib.pyplot as plt
plt.imshow(x_train[8], cmap=plt.cm.binary)
我们得到了下面的图像:
如果我们想看到它对应的标签,我们可以通过:
print(y_train[8])1
正如我们所看到的,它返回的值为“1 ”,这是意料之中的。
Keras 中的数据表示
正如我们所见,Keras 使用 Numpy 的多维数组作为基本数据结构,称这种数据结构为张量。简而言之,我们可以说张量有三个主要属性:
- 轴数 ( 秩):一个包含单个数的张量将被称为标量(或 0 维张量,或张量 0D)。我们称之为矢量或张量 1D 的一组数字。一组向量将是一个矩阵,或 2D 张量。如果我们把这个矩阵打包成一个新的数组,我们就得到一个 3D 张量,我们可以形象地把它解释为一个数字的立方体。通过将 3D 张力器打包成阵列,我们可以创建 4D 张力器,等等。在 Python Numpy 库中,这被称为张量的 ndim 。
- 形状:它是一个整数元组,描述张量沿每个轴有多少维。在 Numpy 库中,这个属性被称为形状。
- D 数据类型 : 该属性表示包含张量的数据类型,例如可以是 uint8 、 float32 、 float64 等。在 Numpy 库中,这个属性被称为 dtype 。
我建议我们从前面的例子中获得张量 train_images 的轴数和维数:
print(x_train.ndim)3print(x_train.shape)(60000, 28, 28)
如果我们想知道它包含什么类型的数据:
print(x_train.dtype)uint8
Keras 中的数据规范化
这些 28×28 像素的 MNIST 图像表示为一个数值数组,其值的范围为 uint8 类型的[0,255]。但是通常将神经网络的输入值调整到一定的范围。在这篇文章的例子中,输入值应该在区间[0,1]内换算成 float32 类型的值。我们可以通过下面几行代码实现这种转换:
x_train = x_train.astype(‘float32’)
x_test = x_test.astype(‘float32’)x_train /= 255
x_test /= 255
另一方面,为了便于将数据输入到我们的神经网络中(我们将看到在卷积中这是不必要的),我们必须将张量(图像)从二维(2D)转换为一维(1D)的向量。也就是说,28×28 个数字的矩阵可以由 784 个数字(逐行连接)的向量(数组)表示,这种格式接受密集连接的神经网络作为输入,就像我们将在本文中看到的那样。在 Python 中,将 MNIST 数据集的每幅影像转换为包含 784 个分量的矢量可通过以下方式完成:
x_train = x_train.reshape(60000, 784)
x_test = x_test.reshape(10000, 784)
在执行这些 Python 指令后,我们可以验证 x_train.shape 采用(60000,784)的形式,而 x_test.shape 采用(10000,784)的形式,其中第一维索引图像,第二维索引每个图像中的像素(现在像素的亮度是 0 到 1 之间的值):
print(x_train.shape)(60000, 784)print(x_test.shape)(10000, 784)
除此之外,我们还有每个输入数据的标签(记住,在我们的例子中,它们是 0 到 9 之间的数字,表示哪个数字代表图像,也就是与哪个类相关联)。在这个例子中,正如我们已经提到的,我们将用 10 个位置的向量来表示这个标签,其中对应于表示图像的数字的位置包含 1,向量的剩余位置包含值 0。
在这个例子中,我们将使用所谓的一键编码,我们已经提到过,它包括将标签转换成与不同标签的数量一样多的零向量,并在对应于标签值的索引中包含值 1。Keras 提供了许多支持函数,包括to _ categorial来精确地执行这种转换,我们可以从 keras.utils 导入这些函数:
from keras.utils import to_categorical
为了查看转换的效果,我们可以看到将应用到 _ categorial之前和之后的值:
print(y_test[0])7print(y_train[0])5print(y_train.shape)(60000,)print(x_test.shape)(10000, 784)y_train = to_categorical(y_train, num_classes=10)
y_test = to_categorical(y_test, num_classes=10)print(y_test[0])[0\. 0\. 0\. 0\. 0\. 0\. 0\. 1\. 0\. 0.]print(y_train[0])[0\. 0\. 0\. 0\. 0\. 1\. 0\. 0\. 0\. 0.]print(y_train.shape)(60000, 10)print(y_test.shape)(10000, 10)
现在,我们已经准备好了用于简单模型示例的数据,我们将在下一节中用 Keras 对其进行编程。
喀拉斯的密集连接网络
在本节中,我们将介绍如何在 Keras 中指定我们在前面几节中定义的模型。
Keras 中的顺序类
Keras 中的主要数据结构是顺序类,它允许创建一个基本的神经网络。Keras 还提供了一个 API ,允许以图形的形式实现更复杂的模型,可以有多个输入、多个输出,以及它们之间的任意连接,但这超出了本文的范围。
Keras 库的 序列类是 Keras 提供的序列神经网络模型的包装器,可以通过以下方式创建:
from keras.models import Sequential
model = Sequential()
在这种情况下,Keras 中的模型被视为一系列层,每一层都逐渐“提取”输入数据以获得所需的输出。在 Keras 中,我们可以找到所有需要的层类型,通过 add() 方法可以很容易地添加到模型中。
定义模型
我们识别数字图像的模型在 Keras 中的结构如下:
from keras.models import Sequential
from keras.layers.core import Dense, Activationmodel = Sequential()
model.add(Dense(10, activation=’sigmoid’, input_shape=(784,)))
model.add(Dense(10, activation=’softmax’))
在这里,神经网络已经被定义为密集连接(或完全连接)的两层序列,意味着每层中的所有神经元都连接到下一层中的所有神经元。视觉上,我们可以用以下方式表示它:
在前面的代码中,我们在第一层的 input_shape 参数中明确表达了输入数据是什么样的:一个张量,表明我们有模型的 784 个特征(事实上,被定义的张量是 (None,784,),我们将在前面看到更多)。
Keras 库的一个非常有趣的特点是,它会在第一个张量之后自动推导出层间张量的形状。这意味着程序员只需要为其中的第一个建立这些信息。此外,对于每一层,我们指出它所具有的节点数量以及我们将在其中应用的激活函数(在本例中, sigmoid )。
本例中的第二层是由 10 个神经元组成的 softmax 层,这意味着它将返回代表 10 个可能数字的 10 个概率值的矩阵(通常,分类网络的输出层将具有与类一样多的神经元,除了在二元分类中,只需要一个神经元)。每个值将是当前数字的图像属于它们中的每一个的概率。
Keras 提供的一个非常有用的检查模型架构的方法是 summary() :
model.summary()_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
dense_1 (Dense) (None, 10) 7850
_________________________________________________________________
dense_2 (Dense) (None, 10) 110
=================================================================
Total params: 7,960
Trainable params: 7,960
Non-trainable params: 0
稍后,我们将更详细地介绍返回 summary() 方法的信息,因为当我们开始构建非常大的网络模型时,神经网络所拥有的参数和数据大小的计算是非常有价值的。对于我们的简单示例,我们看到它指示需要 7960 个参数(列 Param # ),这对应于第一层的 7850 个参数和第二层的 110 个参数。
在第一层中,对于每个神经元 i (在 0 和 9 之间),我们需要 784 个参数用于权重 wij ,因此需要 10×784 个参数来存储 10 个神经元的权重。此外还有 10 个附加参数,用于 10 个 bj 偏置,与它们中的每一个相对应。在第二层中,作为 softmax 函数,需要将所有 10 个神经元与前一层的 10 个神经元连接。因此,需要 10 个 x10 wi 参数,另外还需要 10 个 bj 偏置,对应于每个节点。
我们可以为 密集层指出的参数细节可以在 Keras 手册中找到。在我们的例子中,最相关的出现了。第一个参数表示层中神经元的数量;下面是我们将在其中使用的激活函数。在下一篇文章中(很快:-),我们将更详细地讨论除了这里介绍的两个激活函数之外的其他可能的激活函数:sigmoid 和 softmax。
权重的初始化也经常被表示为密集层的自变量。初始值必须足以使优化问题尽可能快地收敛。各种初始化选项也可以在 Keras 手册中找到。
在 Keras 中实现神经网络的基本步骤
接下来,我们将简要描述实现一个基本神经网络所必须执行的步骤,在接下来的文章中(很快),我们将逐步介绍每个步骤的更多细节。
学习过程的配置
从顺序模型中,我们可以用 add() 方法以一种简单的方式定义这些层,正如我们在上一节中提到的。一旦我们定义了我们的模型,我们就可以用 compile() 方法配置它的学习过程,用它我们可以通过方法参数指定一些属性。
第一个参数是损失函数,我们将使用它来评估训练数据的计算输出和期望输出之间的误差程度。另一方面,我们指定了一个优化器,正如我们将看到的,这是我们指定优化算法的方式,允许神经网络根据输入数据和定义的损失函数计算参数的权重。损失函数和优化器的确切目的的更多细节将在下一篇文章(不久)中呈现。
最后,我们必须指出我们将用来监控我们的神经网络的学习过程(和测试)的度量。在第一个例子中,我们将只考虑准确度(被正确分类的图像的比例)。例如,在我们的例子中我们可以在 compile() 方法中指定以下参数来在我们的计算机上测试它:
model.compile(loss=”categorical_crossentropy”,
optimizer=”sgd”,
metrics = [‘accuracy’])
在这个例子中,我们指定损失函数是分类 _ 交叉熵,使用的优化器是随机梯度下降(sgd) ,度量是准确度,我们将使用它来评估正确猜测的百分比。
模特培训
一旦我们的模型被定义,学习方法被配置,它就可以被训练了。为此,我们可以通过调用模型的 fit() 方法,将模型训练或“调整”为可用的训练数据:
model.fit(x_train, y_train, batch_size=100, epochs=5)
在前两个参数中,我们已经以 Numpy 数组的形式指出了用于训练模型的数据。 batch_size 参数表示我们将在每次更新模型参数时使用的数据数量,而时期则表示我们将在学习过程中使用所有数据的次数。这最后两个论点将会在下一篇文章中详细解释。
这种方法通过我们提到的迭代训练算法找到网络参数的值,我们将在下一篇文章(很快)中更详细地介绍。大致来说,在该算法的每次迭代中,该算法从 x_train 中获取训练数据,将它们通过神经网络(带有它们的参数在该时刻的值),将获得的结果与期望的结果(在 y_train 中表示)进行比较,并计算损失来指导模型参数的调整过程。 其直观地包括应用上面在 compile() 方法中指定的优化器来计算每次迭代中每个模型参数(权重和偏差)的新值,从而减少损失。
正如我们将看到的,这种方法可能需要更长的时间,Keras 允许我们使用冗长的参数(默认情况下等于 1)来查看其进度,此外还指示每个时期花费的估计时间:
Epoch 1/5
60000/60000 [========] — 1s 15us/step — loss: 2.1822 — acc: 0.2916
Epoch 2/5
60000/60000 [========] — 1s 12us/step — loss: 1.9180 — acc: 0.5283
Epoch 3/5
60000/60000 [========] — 1s 13us/step — loss: 1.6978 — acc: 0.5937
Epoch 4/5
60000/60000 [========] — 1s 14us/step — loss: 1.5102 — acc: 0.6537
Epoch 5/5
60000/60000 [========] — 1s 13us/step — loss: 1.3526 — acc: 0.7034
10000/10000 [========] — 0s 22us/step
这是一个简单的例子,因此读者在文章结束时已经能够编写他们的第一个神经网络,但是,正如我们将看到的, fit() 方法允许更多的参数,这些参数对学习结果有非常重要的影响。此外,这个方法返回一个历史对象,我们在这个例子中忽略了它。其 History.history 属性是连续时期中训练数据和其他度量的损失值的记录,以及验证数据的其他度量(如果它们已经被指定的话)。
模型评估
此时,神经网络已经训练完毕,现在可以使用 evaluation() 方法评估其在新测试数据下的行为。此方法返回两个值:
test_loss, test_acc = model.evaluate(x_test, y_test)
这些值表明我们的模型在处理从未见过的新数据时表现得如何。当我们执行 mnist.load_data() 时,这些数据已经存储在 x_test 和 y_test 中,并将它们作为参数传递给方法。在本帖的范围内,我们将只关注其中之一,准确性:
print(‘Test accuracy:’, test_acc)Test accuracy: 0.9018
准确性告诉我们,我们在这篇文章中创建的模型,应用于该模型从未见过的数据,正确分类了 90%。
读者应该注意到,在本例中,为了评估模型,我们只关注其准确性,即模型做出的正确预测与总预测之间的比率,而不管它是什么类别。然而,虽然在这种情况下这就足够了,但有时有必要再深入一点,并考虑模型在其每个类别中做出的正确和不正确预测的类型。
在机器学习中,评估模型的一个非常有用的工具是混淆矩阵,这是一个包含行和列的表格,用于将预测值与实际值进行比较。我们使用这个表来更好地理解模型的行为,当一个类与另一个类混淆时,明确地显示出来是非常有用的。类似于上一篇文章中解释的二元分类器的混淆矩阵具有这样的结构:
真阳性(TP)、真阴性(TN)、假阳性(FP)和假阴性(FN),是对具有类“1”(“正”)和“0”(“负”)的两类情况的单个预测的四种不同的可能结果。
假阳性是指结果被错误地归类为阳性,而实际上却是阴性。假阴性是指当结果实际上是阳性时却被错误地归类为阴性。真阳性和真阴性显然是正确的分类。
利用这个混淆矩阵,可以通过将对角线的值相加并除以总和来计算精度:
精度 = (TP + TN) / (TP + FP + FN + TN)
尽管如此,就模型的质量而言,准确性可能是误导性的,因为当对具体模型进行测量时,我们不区分假阳性和假阴性类型的错误,好像两者具有相同的重要性。例如,想象一个预测蘑菇是否有毒的模型。在这种情况下,假阴性(即食用毒蘑菇)的代价可能是巨大的。相反,假阳性的代价非常不同。
出于这个原因,我们有另一个称为敏感度(或回忆)的指标,它告诉我们该模型如何避免假阴性:
灵敏度 = TP / (TP + FN)
换句话说,从正面观察(毒蘑菇)的总数中,模型检测到多少。
从混淆矩阵中,可以获得几个指标来关注其他案例,如此链接所示,但更详细地讨论这个主题超出了本文的范围。使用一种度量或另一种度量的便利性将取决于每个特定情况,特别是与模型的每个分类错误相关的“成本”。
但是读者会想知道这个混淆矩阵在我们的分类器中是怎么回事,这里有 10 个类而不是 2 个。在这种情况下,我建议使用 Scikit-learn 包通过计算混淆矩阵来评估模型的质量,如下图所示:
在这种情况下,对角线的元素表示模型预测的标签与标签的实际值相符的点数,而其他值则表示模型分类不正确的情况。因此,对角线的值越高,预测就越好。在本例中,如果读者计算对角线值除以矩阵总值的和,他或她将看到它与 evaluate() 方法返回的精度相匹配。
在帖子的 GitHub 中,读者可以找到用来计算这个混淆矩阵的代码。
生成预测
最后,读者需要知道我们如何使用上一节中训练的模型进行预测。在我们的例子中,它包括预测哪个数字代表一幅图像。为了做到这一点,Keras 提供了 predict() 方法。
为了测试这种方法,我们可以选择任何元素。为了方便起见,让我们从测试数据集 x_test 中选取一个。例如,让我们选择这个数据集的元素 11x _ test。
在看到预测之前,让我们看看图像,以便能够检查我们自己模型是否做出了正确的预测(在进行之前的整形之前):
plt.imshow(x_test[11], cmap=plt.cm.binary)
我想读者会同意,在这种情况下,它对应于数字 6。
现在让我们看看模型的 predict() 方法,执行下面的代码,正确地预测了我们刚刚估计它应该预测的值。
predictions = model.predict(x_test)
predict()方法返回一个向量,其中包含对整个数据集元素的预测。通过 Numpy 的 argmax 函数,我们可以知道哪个类给出的归属概率最大,该函数返回包含向量最高值的位置的索引。具体而言,对于项目 11:
np.argmax(predictions[11])6
我们可以通过打印方法返回的向量来检查它:
print(predictions[11])[0.06 0.01 0.17 0.01 0.05 0.04 0.54 0\. 0.11 0.02]
我们看到向量中的最高值在位置 6。我们还可以验证预测的结果是一个向量,它的所有分量之和等于 1,正如所预期的那样。为此,我们可以使用:
np.sum(predictions[11])1.0
到目前为止,读者已经能够在 Keras 中创建他们的第一个模型,该模型在 90%的情况下正确地对 MNIST 数字进行分类。在下一篇文章中(很快),我们将介绍学习过程是如何工作的,以及我们可以在神经网络中使用的几个超参数来改善这些结果。
在以后的文章中,我们将会看到如何使用卷积神经网络来改进这些分类结果。
人工神经网络是如何学习的?[更新版本]
towardsdatascience.com](/learning-process-of-a-deep-neural-network-5a9768d7a651)
日本古典文学的深度学习
论文摘要
Fig 1. Toons Discussing about converting Kuzushiji-Kanji to Modern Kanji
这是一篇论文的论文摘要: 对日本古典文学的深度学习 由 塔林·克兰瓦特、 米克尔·波贝尔-伊里扎尔、浅野武·北本、亚历克斯·兰姆、山本和树、大卫·哈。
论文:
概观
本文介绍了 3 个新的机器学习基准数据集,即:
-Kuzushiji-MNIST-替代 MNIST 数据集(28x 28)-
-Kuzushiji-49-一个更大但不平衡的数据集,包含 48 个平假名字符和 1 个平假名迭代标记(28x 28)-
-Kuzushiji-Kanji-(64x64)
Fig 2. An example of a Kuzushiji script
由于在这个时代日本语言的现代化,Kuzushiji 文字不再在正常的学校课程中教授。尽管日本人已经使用了 1000 多年,但今天大多数日本人都不会读或写 150 多年前写的书!
Fig 3. Difference between text printed in 1772 and 1900
在国家图书总目录中有超过 170 万册注册图书,超过 300 万册未注册图书和超过 100 万份 1B 历史文献,除了其中一些被数字化外,只有了解《藏书世纪》的人才能阅读这些文献。
本文介绍了一个专门为 ML 研究建立的数据集,并向日本文学界介绍了 ML 社区。
该论文使用最近的模型发布了 Kuzushiji-MNIST 和 Kuzushiji-日本汉字数据集的基准。库祖什基-MNIST 可用作正常 MNIST 数据集的替代品。
本文还将生成模型应用于未知汉字到现代汉字的领域转换任务。
Fig 4. Domain Transfer Experiment between Kuzushiji Kanji and Modern Kanji
数据集
Kuzushiji 数据集由NIJL 国立日本文学研究所创建,由人文科学开放数据中心(CODH)* 管理。
Kuzushiji 全数据集于 2016 年 11 月发布,现在数据集包含 3999 个字符类型,403242 个字符。*
本文作者对从 18 世纪印刷的 35 本古典书籍中扫描的字符进行预处理,并将它们分成 3 个数据集:
-Kuzushiji-MNIST-MNIST 数据集(28x 28)
-Kuzushiji-49-一个更大但不平衡的数据集,包含 48 个平假名字符和 1 个平假名迭代标记(28x 28)
-Kuzushiji-Kanji(64x64)
Fig 5. 10 Classes of Kuzushiji-MNIST
One characteristic of Classical Japanese which is very different from Modern Japanese is Hentaigana(変体仮名).
汉字是一种平假名字符,它有一种以上的书写形式,因为它们来自不同的汉字。
因此,Kuzushiji-MNIST 和 Kuzushiji-49 的一个平假名类可能映射了许多字符(如上图所示)。这使得 Kuzushiji 数据集比 MNIST 数据集更具挑战性。
Fig 6. Few examples from Kuzushiji-Kanji
Kuzushiji-49 和 Kuzushiji-Kanji 中的高类别不平衡是由于真实教科书中的出现频率,并且保持这种方式以表示真实的数据分布。
- Kuzushiji-49 —有 49 个类别,共有 266,407 张图像 (28x28)
- kuzushiji-Kanji-有 3832 个类,总共有 140,426 个图像,从 1,766 个示例到每个类只有一个示例。 (64x64)
Kuzushiji-MNIST 是平衡的。Kuzushiji-Kanji 是为更多的实验任务而创建的,而不仅仅是分类和识别基准。
Fig 7. Kuzushiji-49 Classes
实验
库祖什基-MNIST 和库祖什基-49 的分类基线
Fig 8. Classification baselines for Kuzushiji-MNIST and Kuzushiji-49
从日本汉字到现代汉字的域名转移
Kuzushiji-Kanji 数据集用于从像素图像到矢量图像的域转移(与以前的此类方法相反,以前的方法侧重于从像素图像到像素图像的域转移)
所提出的模型旨在以基于像素和笔画的格式生成给定汉字输入的现代汉字版本。
Fig 9. Kuzushiji Kanji to Modern Kanji
下图展示了整体方法。
Fig 10. Kuzushiji-Kanji to Modern Kanji Approach
他们训练两个独立的卷积变分自动编码器,一个在 Kuzushiji-Kanji 数据集上,另一个在 KanjiVG 数据集的像素版本上,渲染为 64x64 像素以保持一致性。VAE 的建筑与【3】相同。* 并且两个数据集都被压缩到各自的 64 维潜空间中, z_old 和 z_new 。KL 损失项在低于某个阈值时没有被优化。*
然后,训练具有 2 个隐藏层的混合密度网络(MDN)来模拟近似为混合高斯分布的密度函数 P(z_new | z_old) 。
然后,给定从 Kuzushiji-Kanji 编码的潜在向量 z_old,我们可以采样潜在向量 z_new 。
该论文称,与端到端地训练单个模型相比,在每个数据集上训练两个独立的 VAE 模型要高效得多,并且取得了更好的结果。
在最后一步中,草图-RNN 解码器模型被训练以基于 z_new 生成现代汉字。
Fig 11. The algorithm for domain transfer from Kuzushiji-Kanji to KanjiVG
两个数据集之间有 3600 个重叠字符。
-对于不在重叠空间中的那些,我们从编码在 KanjiVG 数据上的 z_new 调节 sktech-RNN 模型,以同样从 KanjiVG 生成笔画数据[ 参见图 10
中的(1).-对于存在于重叠数据集中的那些,我们使用从以 z_old 为条件的 MDN 采样的 z_new,以同样从 KanjiVG 生成笔画数据[ 参见图 10 中的(2)
这有助于 sketch-RNN 微调 VAE 潜在空间的各个方面,当只在像素上训练时,这些方面可能无法很好地捕捉现代汉字的数据分布。
参考
****【1】**y . le Cun。MNIST 手写数字数据库,1998 年。http://yann.lecun.com/exdb/mnist/
**c .对于人文学科的开放数据。Kuzushiji 数据集,2016。http://codh.rois.ac.jp/char-shape/
***【3】*d .哈和 j .施密德胡伯。循环世界模型促进政策演变. arXiv 预印本 arXiv:1809.01999,2018。https://worldmodels.github.io/
所以,简而言之,这就是论文的全部内容! 如果我发现一些有趣的见解需要补充,会更新这个故事! 一定要走纸!
感谢阅读!
图像识别的深度学习:为什么它具有挑战性,我们已经走过的路,以及下一步
想获得灵感?快来加入我的 超级行情快讯 。😎
在过去几年里,深度学习绝对统治了计算机视觉,在许多任务及其相关竞赛中取得了最高分。这些计算机视觉竞赛中最受欢迎和最知名的是 ImageNet 。ImageNet 竞赛要求研究人员创建一个模型,最准确地对数据集中的给定图像进行分类。
在过去的几年里,深度学习技术使这项比赛取得了快速进展,甚至超过了人类的表现。今天,我们将回顾这一进展,以深入了解这些进步是如何伴随深度学习而来的,我们可以从中学习到什么,以及我们可以从这里走向何方。
ImageNet 的挑战
那么 ImageNet 挑战赛有什么难的呢?让我们先看一下数据。ImageNet 分类任务的数据是从 Flickr 和其他搜索引擎收集的,由人工标记,每张图像属于 1000 个对象类别中的一个。下表显示了数据集的分布情况。
ImageNet Dataset
到 2012 年,ImageNet 拥有近130 万张训练图片。如此大规模的图像分类任务的主要挑战是图像的多样性。这里我们可以看几个例子。
看看下面的图片。在左边,我们看到一些来自另一个图像分类挑战的示例图像: PASCAL 。在帕斯卡挑战中,只有大约 20,000 幅训练图像和 20 个对象类别。这个挑战有非常通用的类别,如“鸟”、“狗”和“猫”,如下所示。转移到 ImageNet 挑战,这是一个全新的游戏。ImageNet 没有一个包含所有种类狗的名为“dog”的通用类,而是为每种狗都提供了类。事实上,不同于帕斯卡的“狗”类别,ImageNet 有 120 个不同品种的狗的类别!因此,我们用于这项任务的任何模型/算法必须能够处理这些非常细粒度的和特定的 类,即使它们看起来非常相似并且难以区分。
用更专业的术语来说,我们希望最大化**类间可变性。**这意味着我们希望两张包含不同种类鸟类的图像在我们的模型中看起来非常不同,因为尽管它们都是鸟类,但在我们的数据集中它们属于不同的类别。看看下面的插图。
Inter-class Variability
ImageNet 的另一个具有挑战性的特性是:同一类的对象看起来会有很大的不同。让我们看看下面的图片。左边的两个都来自“橘子”班,右边的两个都来自“台球桌”班。然而,每一对图像看起来非常不同!作为人类,我们可以看到一个橙子被切开,而另一个没有;我们还可以看到,台球桌的一张照片被放大了,另一张没有。这叫做类内变异性。我们希望最小化这种可变性,因为我们希望同一类的两幅图像看起来非常类似于我们的深度学习模型,也就是说,在数量上。
Intra-class Variability
知道了这些图像分类挑战,让我们回顾一下深度学习是如何在这项任务上取得巨大进展的。
图像分类深度学习的快速进展
自 2012 年以来,几乎每年都让我们在为图像分类任务开发深度学习模型方面取得重大突破。由于其大规模和具有挑战性的数据,ImageNet 挑战已成为衡量进展的主要基准。在这里,我们将看看深度学习在这项任务上的进展,以及使这一进展成为可能的一些主要架构。
开始这一切的人:AlexNet
AlexNet Architecture
**早在 2012 年,多伦多大学的一篇论文发表在 NIPS 上,这真是令人震惊。那篇论文是 ImageNet 用深度卷积网络分类 。它在 ImageNet 挑战赛中实现了近 50%的错误率降低,这在当时是前所未有的进步,随后成为该领域最具影响力的 论文之一。论文中 AlexNet 的神经网络架构如上所示。
本文提出使用深度卷积神经网络(CNN)来完成图像分类的任务。与现在使用的相比,它相对简单。这篇论文的主要贡献是:
- 第一个成功地使用 deep 进行大规模图像分类。这之所以成为可能,是因为来自 ImageNet 的标记为 的的大量 数据,以及使用两个 GPU 上的并行计算来训练模型。****
- 他们将 ReLU 用于非 - 线性 激活 功能,发现它们相对于 tanh 功能表现更好,并减少了训练时间。ReLU 非线性现在倾向于成为深度网络的默认激活功能。
- 他们使用数据 增强技术,包括图像平移、水平反射和均值减法。如今,这些技术被广泛用于许多计算机视觉任务。
- 为了解决超过 - 拟合训练数据的问题,他们使用了剔除层。
- 他们提出的风格是让连续 卷积和汇集 层,然后是完全 - 连接最后的层,这仍然是今天许多先进网络的基础。
基本上,AlexNet 设置了标杆,提供了使用 CNN 完成计算机视觉任务的基线和默认技术!
让我们更深入:VGGNet
VGGNet Architecture
VGGNet 论文“用于大规模图像识别的极深度卷积神经网络”于 2014 年问世,进一步扩展了使用具有许多卷积和 ReLUs 的深度网络的思想。论文中 VGGNet 的神经网络架构如上所示。他们的主要想法是,你真的不需要任何花哨的技巧来获得高精度。只要一个有很多 3×3 小卷积和非线性的深度网络就可以了!上图中相同大小的重复块的堆叠是使用 3x3s 堆叠的直接结果!VGGNets 的主要贡献是:
- 仅使用3x 3 大小的过滤器,而不是 AlextNet 中使用的 11x11。他们表明,两个连续的 3×3 卷积具有等同于单个 5×5 卷积的接收** 场或“视野”(即它看到的像素);同样,三个连续的 3×3 卷积相当于一个 7×7 卷积。这样做的好处是,它模拟了一个更大的滤波器,同时保留了较小滤波器的优点。较小滤波器的第一个好处是减少了参数数量。第二个是能够在每个卷积之间使用 ReLU 函数,这将更多的非 - 线性引入网络,这使得决策 函数更具辨别能力。**
- 随着每一层的输入体积的空间大小减小(作为汇集层的结果),体积的深度增加。这背后的想法是,随着空间信息的减少(从通过最大池的向下采样),它应该被编码为更具区分度的 特征,以用于精确和高区分度的分类。因此,特征图的数量随着深度而增加,以便能够捕捉这些特征用于分类。
- 它引入了一种新的数据扩充方式:标度抖动。
- 用 Caffe 工具箱建立模型。在这一点上,深度学习库变得越来越受欢迎。
更深入:GoogLeNet 和 Inception 模块
Inception Module from GoogLeNet
GoogLeNet 架构是第一个真正解决计算 资源以及多 - 规模 处理的问题的,在论文“用卷积走得更深”。随着我们不断地让我们的分类网络越来越深,我们到达了一个耗尽大量内存的点。此外,过去已经提出了不同的计算滤波器大小:从 1x1 到 11x11 你如何决定哪一个?inception 模块和 GoogLeNet 通过以下贡献解决了所有这些问题:
- 通过在每个 3x3 和 5x5 之前使用 1x1 卷积,初始模块减少了通过每层的特征 映射的数量,从而减少了计算和内存消耗!
- 初始模块有 1x1、3x3 和 5x5 个卷积,都在并行中。这背后的想法是让网络通过训练来决定学习和使用什么信息。它还允许多 - 尺度 处理:该模型既可以通过较小的卷积恢复局部 特征,也可以通过较大的卷积恢复高 抽象 特征。厉害!
- GoogLeNet 是第一个引入 CNN 层不必总是按顺序堆叠的想法的模型之一。这篇论文的作者表明,你还可以增加网络宽度以获得更好的性能,而不仅仅是深度。
使用快捷方式跳过:ResNet
Residual block from ResNet
自从 2015 年首次发表论文“图像识别的深度剩余学习”以来,ResNets 已经在许多计算机视觉任务的准确性方面取得了重大进步。ResNet 架构是第一个在 ImageNet 上通过人类水平性能的架构,他们对残差 学习的主要贡献通常默认用于当今许多最先进的网络:
- 显示出一个幼稚的 层层叠加让网络变得很深并不总是有帮助,实际上还会让事情变得更糟。
- 为了解决上述问题,他们引入了跳过连接的剩余学习。其思想是通过使用附加的跳过 连接作为快捷方式,深层具有从先前层直接访问 到 特征。允许功能信息更容易地通过网络传播。这也有助于训练,因为梯度也可以更有效地反向传播。
- 第一个“超 深”网络,通常使用超过 100-200 层。
走极端的捷径:DenseNet
DenseNet visualization
随着论文“密集连接的卷积网络”中 DenseNets 的引入,快捷连接被发挥到了极致。DenseNets 扩展了快捷连接的概念,但具有比 ResNet 更密集的连接:
- DenseNets 以前馈方式将每一层与每一层连接起来。这允许每个层使用在 层之前的所有 的所有特征图作为输入,并且它自己的特征图被用作所有后续层的输入。
- 这是通过连接完成的,而不是在 ResNets 中使用的加法,这样原始特征直接通过层。
- 显示出执行 比 ResNets更好。DenseNets 有助于缓解消失梯度问题,加强特征传播,鼓励特征重用,并大大减少参数的数量。
这些是在过去几年中形成图像分类进展的主干的主要体系结构。已经取得了很大的进展,这是令人兴奋的,因为它允许使用这种新技术来解决许多现实世界的问题。只剩下一个问题……
我们将何去何从
正如我们刚刚回顾的,针对图像分类的深度学习研究一直在蓬勃发展!我们已经在改进这项任务的方法上迈出了巨大的步伐,甚至超越了人类水平的表现。深度神经网络现在广泛用于许多企业对图像进行分类,甚至是许多新启动技术的基础。
很高兴看到所有这些进步,但我们必须一直努力改进。深度学习模型在图像分类方面仍然存在许多挑战。如果我们想要前进,这些挑战是必须解决的。在这里,我将回顾其中一些我认为重要的、研究人员正在积极尝试解决的问题:
从监督学习到非监督学习
An example of Supervised vs Unsupervised learning
目前,大多数应用于计算机视觉任务的深度学习方法都是由监督的。这意味着我们需要大量的标记的训练数据。获取这些数据既繁琐又昂贵。想想看:ImageNet 挑战赛有130 万个训练样本,而这仅仅是针对 1000 个不同的类别!一个人需要得到所有的数据,浏览每一幅图像,并给它贴上标签;好多手动工作!
大多数情况下,当企业想要为自己的特定应用应用图像分类网络时,他们必须使用迁移学习来微调预先训练的 ImageNet 网络。为了进行这种微调,他们仍然需要收集大量自己的数据并对其进行标记;繁琐和昂贵退一步说。
研究人员正在积极努力解决这个问题并取得进展。像快速和有效 转移 学习****半 - 监督 学习和一次 - 射击 学习这样的事情越来越多。我们可能不会直接跳到无监督学习,但这些方法的研究是朝着正确方向迈出的有力一步
抵御我们的敌人
Adversarial images can cause major problems
使用生成 对抗 网络 (GANs)的日益流行,揭示了图像分类的新挑战:对抗 图像。简而言之,敌对图像的类别对人类来说显而易见,但在深层网络中会导致大量 故障。看看上面的图片。仅仅有一点点扭曲(看起来),一个深层网络的图像分类就从熊猫变成了长臂猿!
对我们人类来说,很明显这个图像仍然是一只熊猫,但出于某种原因,它导致深层网络无法完成任务。这在真实 - 世界 应用中可能是非常危险的:如果你的自动驾驶汽车没有认出一个行人,而是从他们身上碾过去怎么办?部分问题可能源于这样一种想法,即我们并不完全了解我们的网络内部发生了什么。无论如何,研究人员正在积极研究这个具有挑战性的问题。
加快进程
MobileNets benchmarking
深度学习的许多进展都是由硬件的改进推动的,特别是 GPU。GPU 允许高速处理可以并行完成的计算。由于矩阵运算运算,深度网络需要大量的乘加运算;GPU 擅长执行这些操作。这是一个了不起的进步,但是我们并不是到处都有 GPU!
许多最先进的网络,包括上面讨论过的网络,只能在高端 GPU 上以合理的速度运行。移动 设备是一个巨大的市场,采取措施为该市场服务非常重要。此外,随着网络越来越深,它们往往需要更多的内存,从而限制更多的设备运行网络!
这一领域的研究最近实际上有了很大进展。 MobileNets 是一个体系结构家族,已经流行于直接在移动设备上运行深度网络。他们使用不同风格的卷积来减少内存消耗和推理时间。
把一切都包起来
这是一个总结!我们看到了对图像进行分类有多么困难,并回顾了使用深度学习在该领域取得的惊人进展。我们也看到了未来的一些挑战。但是用新的科学和工程来应对这些挑战是技术令人兴奋的地方。
喜欢学习?
在推特上关注我,我会在那里发布所有最新最棒的人工智能、技术和科学!也在 LinkedIn 上与我联系!
机器共情的深度学习:机器人和人类的互动——第一部分
当我们思考下一次数字革命迫在眉睫的发展时,人类将面临前所未有的自动化浪潮。越来越多的智能和互联设备将与我们共存。这场革命已经在发生,从手机到自动驾驶汽车,甚至我们的冰箱。有一点是肯定的,机器人已经出现了,而且会一直存在下去。
问题不是我们是否同意,而是我们将如何与这些新租户互动。除了传统的设计原则,如实用性和风格,一个新的标准将获得相关性:机器同理心。随着越来越多的公司认识到人机交互(HMI)是安全技术采用的关键,这种趋势将变得更加强烈。
但是,我们能做些什么来改善人机交互呢?我们能至少软化我们的共存吗?
融入社会的关键是掌握理解他人感受和想法的能力,并做出相应的反应。直到现在,这种能力只保留给(一些)人类。这种被称为同理心的美德促进了社会化,而人类天生善于交际。
因此,答案可能是让机器有能力理解我们的感受、我们的需求和我们的目标。这样他们就能做出相应的反应,最大限度地提高我们的舒适度。这也包括给他们正确的形式。这种新一代机器人会是类人机器人吗?温和的自动机像无害的 Roomba ?或者可能是可怕的黑镜的金属头机器人“狗”和他们现实生活中来自波士顿动力的远亲。这是讨论 HMI 时整体的一部分。
许多研究人员已经在这个领域开展工作,特别是麻省理工学院的人形机器人小组。他们开发了社交机器人 Kismet。Kismet 对观众表现出的情绪做出友好的反应,让人们参与自然而富有表现力的面对面互动。初步结果显示,人类与这些机器之间的互动有了很大的改善。
Kismet, MIT’s social robot.
很明显,这一新的自动化浪潮的成功将在很大程度上取决于机器人的同情心和个性。想象一下,一辆汽车检测到你感到悲伤,并自动播放你喜欢的歌曲让你感觉更好,或者一个机器人医疗助理识别你的需求并做出反应,给你最大限度的关注和安慰。通过添加强大的自动语音识别和自然语言处理(由亚马逊 Alexa 和其他公司广泛开发),可能性是无限的。
这样一个系统可以从外部信息源获取信息,并根据经验不断发展。您的设备将不断向您学习。这种超个性化将产生一个直接的结果:独特性。独特性是依恋、的燃料,而依恋在本质上是人类的。
Real Steel robot Atom (2011)
在科幻电影《铁钢》(2011)中,拳击手机器人 Atom 在战斗中多次遭受严重损伤。突然,情绪开始出现,作为一个明显的标志,我们不想失去原子;它是独一无二的。我们知道是什么让 Atom 与其他机器人相比如此特别,它表现出感情;很有同情心。
不过不用担心,那时候云存储和电信技术会那么发达,你的机器人失去个性的可能性很小。
尚不清楚这将如何改变科技行业并影响消费者习惯。你会像以前一样频繁地换车吗?您会觉得您的设备独一无二吗?你能和它建立联系吗?
现实是,我们仍然没有这些问题的答案。这场革命正在开始,其潜在后果尚未被完全理解。那么这个话题将成为未来几年公开讨论的一部分。
深度学习和情感识别
情感识别是拥有真正的“移情”机器之旅的第一步。这种系统已经使用深度学习架构,特别是卷积神经网络(CNN)成功构建。
这一成功背后的秘密是 CNN 能够自动学习识别输入图像的相关低级和高级特征。该网络生成越来越明确的图像表示,学习将低级和高级特征结合起来,最终关心实际内容,而不是单个像素信息。这个最终的表示用于将情绪分类成几个类别,例如,悲伤、快乐、愤怒、恐惧、惊讶和中立。关于这一点的非常详细的解释可以在臭名昭著的论文’A Neural Algorithm to Transfer Style’中找到。
以下视频是一周沉浸在使用深度卷积神经网络的实时情感识别中的结果。为了测试这个解决方案,我们选择了著名的《悲伤的本·阿弗莱克》采访。初步结果如下所示(更多改进即将推出):
Sad Affleck inteview meets AI
在下一篇文章中,我们将直接讨论基于深度学习的机器人基本(和功能)移情模块的实现。我们将深入研究计算机视觉技术,从经典的快速人脸检测算法到用于情感识别和迁移学习的深度神经网络。
问题
我希望你和我一样喜欢这篇文章。我很乐意阅读你对这个话题的看法。不要犹豫留下你的评论,掌声也欢迎。请关注我,让您了解本文的下一部分。如果你想了解更多关于 Axionable、项目和职业的信息,请访问我们的网站并在 Twitter 上关注我们。
参考书目
Breazeal,C. (2000),“社交机器:人类和机器人之间的表达性社会交换”。麻省理工学院电子工程和计算机科学系博士论文。
洛杉矶 Gatys 公司、埃克公司和 m . Beth ge 公司(2015 年)。艺术风格的神经算法。 CoRR,abs/1508.06576 。
命名实体识别的深度学习#2:为 CoNLL 2003 实现最先进的双向 LSTM + CNN 模型
基于 Chiu 和 Nichols (2016),该实现在 2003 年 CoNLL 新闻数据上取得了 90%以上的 F1 分数。
CoNLL 2003 是对 NER 有用的许多公开可用的数据集之一。在这篇文章中,我们将使用 Keras 和 Tensorflow 在 Python 中实现 Chiu 和 Nichols (2016) ( 此处)的当前 SOTA 算法。该实现的核心是双向 LSTM (BLSTM ),同时还使用卷积神经网络(CNN)来识别字符级模式。
假设读者熟悉 CNN(如果不熟悉,请阅读 Denny Britz 的摘要这里,但不太熟悉 BLSTMs,让我们快速描述一下为什么 BLSTMs 特别适合 NER。
双向 LSTMs
长短期记忆(LSTM)细胞是递归神经网络(RNNs)的构建模块。虽然前馈神经网络中的普通 LSTM 细胞像人类一样处理文本(从左到右),但 BLSTMs 也考虑相反的方向。随着输入信息量的增加,这使得模型能够发现更多的模式。换句话说,该模型不仅考虑感兴趣的记号之后的记号序列,还考虑感兴趣的记号之前的*。*
下图更正式地表达了这一观点。请注意, x 代表输入序列, h 代表向前或向后运行的输出序列(分别由指向右边或左边的箭头定义), y 代表串接的输出序列,其中∑串接向前和向后输出元素。
Unfolded BLSTM architecture with 3 consecutive steps. From Cui et al. (2017) (here).
维基百科的文章(此处)包含了更多的细节,包括到舒斯特和帕利瓦尔(1997)的原始论文的链接(此处)。
Keras 实施
我使用 Keras 和 Tensorflow 后端。这通常是最有效的设置,尤其是在 GPU 上运行时。
[## MX hofer/命名实体识别双向 TM-CNN-CoNLL
命名实体识别双向 TM-CNN-CoNLL - Keras 实现 Chiu 和 Nichols (2016)
github.com](https://github.com/mxhofer/Named-Entity-Recognition-BidirectionalLSTM-CNN-CoNLL)
以下是主要步骤。
嵌入
加载训练、开发和测试数据文件后, embed 函数创建单词和字符级嵌入。这意味着单词和字符被映射到神经网络可以处理的实数。更具体地说,标签(例如 B-ORG、I-ORG、B-LOC 等。)、记号大小写(例如,小写、大写或数字记号)和字符使用字典数据结构被映射到实数。此外,所有唯一的单词被映射到手套嵌入向量。
模型架构
BLSTM 层构成网络的核心,具有以下三个输入:
- 字符级模式由卷积神经网络识别
- 来自手套嵌入的单词级输入
- 大小写输入(无论单词是小写、大写等。)
下图显示了所有层的模型架构。一个 softmax 激活层生成最终输出。
Model architecture, Chiu and Nichols (2016).
因素
推荐参数与论文略有不同。这可能是因为我们不知道 Chiu 和 Nichols (2016)在不使用额外的基于规则的方法的情况下会取得什么样的 F1 分数。仅考虑他们的机器学习模型组件,这些参数达到 90%+的 F1 分数:
- 80 个时代
- 0.68 辍学
- 200 个 LSTM 州大小
- 3 卷积宽度
- 那达慕乐观主义者
在您的本地机器上运行代码时,您只需 30 个历元和大约 1 个小时的训练,就可以获得大约 86%的 F1 分数,其中包括上述的下降、LSTM 状态大小、卷积宽度和优化器参数(见下图)。
Learning curve with 30 epochs.
总之,双向 LSTMs 是用于命名实体识别的非常强大和灵活的神经网络类型。提示:尝试在 CoNLL 格式的不同数据上重用模型。表现如何?
我希望这为 CoNLL 2003 数据的当前 SOTA 模型提供了一个有用的概述和实现。让我知道你用不同的参数和其他调整得到的结果!👋
命名实体识别的深度学习#3:在临床文本数据上重用双向 LSTM + CNN
这篇文章描述了 BLSTM + CNN 网络如何在 i2b2 临床文本中重复使用,以提取药物名称、剂量、频率和处方原因等。重用该模型可使 F1 得分达到 85.65%,与 i2b2 2009 挑战赛的获胜团队不相上下。
在本系列的 post #2 中,我们在 CoNLL 2003 新闻数据上验证了最先进的模型,一个 BLSTM + CNN 模型,实现了 90%+的 F1 分数。下面是使用 Python 和 Keras 实现的这个网络:
[## MX hofer/命名实体识别双向 TM-CNN-CoNLL
命名实体识别双向 TM-CNN-CoNLL - Keras 实现 Chiu 和 Nichols (2016)
github.com](https://github.com/mxhofer/Named-Entity-Recognition-BidirectionalLSTM-CNN-CoNLL)
该模型在我的 arxiv 论文“【https://arxiv.org/abs/1811.05468】”[]中用于医学文本中命名实体识别的少镜头学习。
i2b2 2009 临床文本数据
i2b2 基金会在 2009 年 NLP 挑战赛后发布了文本数据(由参赛团队标注)。总共有 261 份出院小结注明了药物名称(m)、剂量(do)、给药方式(mo)、给药频率(f)、持续时间(du)和给药原因®。以下是训练集、验证集和测试集中每个类别的计数:
Medication annotations: 9318
Dosage annotations: 4666
Mode annotations: 3513
Frequency annotations: 4229
Duration annotations: 571
Reason annotations: 1694
下载和预处理
m = " Caltrate plus d " 5:1 5:3 | | do = " one " 5:4 5:4
…表示名为“caltrate plus d”的药物包含在名为“1234”(无文件扩展名)的文本文件中,第 5 行,偏移量 1 至 3(含)。类似地,剂量“一”直接跟随在第 5 行偏移 4 处的药物之后。
您必须对文件名进行一些预处理,去掉文件名中任何不必要的文本。我发现最简单的方法是创建一个名为“数据”的文件夹,其中包含两个子文件夹“注释”和“条目”。将相应的文件添加到子文件夹中。目标是从注释到文本条目有一个 1:1 的映射,这些条目可以连接起来创建完整的数据集。对于 id 为“1234”的出院小结,注释和条目均应命名为“1234”。i2b2 2009 数据中的文件以文档 id 开始,因此这个代码片段可以帮助您去掉剩余的文本:
将 i2b2 解析为 CoNLL 格式
注释和条目文件名匹配后,我们现在可以将数据从 i2b2 解析为 CoNLL 格式。这涉及到几行代码,下面简要介绍一下。这是 iPython 笔记本:
[## mxhofer/i2b2_2009-to-CoNLL
在 GitHub 上创建一个帐户,为 i2b2_2009-to-CoNLL 开发做出贡献。
github.com](https://github.com/mxhofer/i2b2_2009-to-CoNLL)
首先,解析器为注释和条目建立语料库。注释语料库用于建立注释数据框,包含文档 id、NER 标签(使用 BIO 方案)、注释的行和偏移。条目语料库用于建立条目数据框架,包含文档 id、行、偏移量和相应的单词。它还包含空行关键字(-EMPTYLINE)和新文档的开始关键字(-DOCSTART)。
其次,注释和条目数据框在文档 id、行和偏移列上连接。然后用来自 nltk.pos_tag 函数的 POS 标签对结果数据帧进行标记。
最后,在将数据集分成大约 70%的训练数据、15%的验证数据和 15%的测试数据之前,添加名词和动词短语的组块标签。该脚本的输出是一组。txt 文件,即 train.txt、valid.txt 和 test.txt。
请注意解析器的这些限制:
- 不考虑跨换行符的注释(总共 23,991 个注释中丢失了大约 71 个)。
- Chunk tagger 只标记名词短语(NP)和动词短语(VP)。
- 生物注释方案通过在 XXX 类型的每个序列的开始处的标签“B-XXX”来实现(而不仅仅是为了区分 XXX 类型的连续标签)。
重复使用模型的性能— F1 为 85.65%
如果我们的神经网络模型在新数据上表现不好,那么所有的解析又有什么价值呢?这就是机器学习的魅力所在。尽管针对路透社的新闻数据进行了优化,但该模型仍与 i2b2 2009 挑战赛的最佳提交数据持平,F1 得分为 85.65%。这是一个了不起的结果!
在我的实验中,这些参数运行良好:
- 50 个时代
- 0.5%辍学
- 200 个 LSTM 州大小
- 3 卷积宽度
- 那达慕乐观主义者
调整这些参数,看看你能否打破 2009 年的最先进的分数。
结论
最后,我们从下载 i2b2 2009 数据集开始,继续将 i2b2 数据解析为 CoNLL 格式,以便重用 BLSTM + CNN 模型。在这个过程中,我们了解到神经网络(在某种程度上)不知道底层数据来自哪个领域。虽然 i2b2 2009 挑战赛中的大多数系统都使用了由临床医生硬编码的手工制作的功能和规则,但没有临床知识(像我一样)但有一些机器学习知识的人可以构建一个强大的命名实体识别工具。
您想将此模型用于哪些文本数据?
奖金-计算每个注释类别的 F1 分数
如果您想深入了解,请计算每个注释类别的 F1 分数。您应该会发现,该模型在提取药物名称(m)方面表现良好,但在管理原因®方面表现不佳。这是有道理的:实施治疗的原因比药物名称要模糊得多。此外,可用于培训的药物名称数量超过 5 倍。
希望代码对您来说很好。如果没有,请在下面的评论中留言,我很乐意帮忙。👋
命名实体识别的深度学习#1:公共数据集和标注方法
欢迎来到我的“命名实体识别的深度学习”系列的第一篇文章——让我们从访问高质量数据集开始!🚀
Need for data: Deep Learning for NER requires thousands of training points to achieve reasonable accuracy.
在撰写关于使用深度学习进行命名实体识别(NER)的硕士论文时,我将在一系列帖子中分享我的学习成果。主题包括如何以及在哪里找到有用的数据集(本帖!),最先进的实现以及今年晚些时候一系列深度学习模型的利弊。
公共数据集
与任何深度学习模型一样,你需要大量数据。高质量的数据集是任何深度学习项目的基础。幸运的是,有几个带注释的、公开的、大部分免费的数据集。
CoNLL 2003
这个数据集包括 1393 篇英语和 909 篇德语新闻文章。英语语料库是免费的,但不幸的是,德语语料库要 75 美元。这是本帖中唯一有价值的语料库。为了建立英语语料库,你需要 RCV1 路透社语料库。您将在提交组织和个人协议几天后免费获得访问权限。
实体标注有 LOC (位置) ORG (组织) PER (人员)和 MISC (其他)。这是一个例句,每行由[单词][词性标签][组块标签] [NER 标签]组成:
联合国 NNP I-NP I-ORG
官方 NN I-NP O
埃克乌斯 NNP I-NP I-PER
首脑 VBZ I-VP O
为 I-PP O
巴格达 NNP I-NP I-LOC
。。哦哦
这里有一个POS 标签代表什么的综合列表。这是官方的 2003 年 CoNLL 介绍文件和 GitHub wiki 的 SOTA 排名。
onto notes 5.0/2012 年
OntoNotes 版由 1,745,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,0000 个阿拉伯文本数据组成,这些数据来自一系列来源:电话交谈,新闻专线,广播新闻,广播,广播,广播对话和网络博客。实体标注有人、组织、地点等类别(此处 18 个类别的完整列表,第 21 页)。通过你的大学/系获得访问权是最容易的——当你在这里注册时检查。
i2b2 挑战
整合生物学和床边信息学(i2b2)中心发布了大量 NER 的临床数据集。特别是 2009 年(提取药物),2012 年(提取问题,治疗等。)和 2014 年(提取疾病、危险因素、用药等。)挑战是非常相关的,包括记录良好的最先进的实施。获得访问权是免费的——它需要签署一份协议,声明你基本上是以体谅的态度对待数据的。i2b2 回复很快!
更多数据
我没有详细查看其他数据集,但它们可能对您的应用程序仍然有用: NLPBA 2004 标记有蛋白质/DNA/RNA/细胞系/细胞类型(2,404 MEDLINE 摘要)和 Enron 电子邮件标记有姓名/日期/时间(大约 500 K 条消息)。
注释方法
了解不同的注释模式需要一些时间。有许多框架,从标记方法(类似 HTML)到键值对。
标记(例如 OntoNotes 5.0)
这种注释方法使用带有尖括号的标记标签来定义命名实体,例如组织:
迪士尼是一个全球品牌。
IOB(如 CoNLL 2003)
IOB(或 BIO)代表 B 内, I 内, O 外。用 O 标记的单词在命名实体之外,而 I-XXX 标记用于类型为 XXX 的命名实体内的单词。每当两个类型为 XXX 的实体彼此紧邻时,第二个实体的第一个单词将被标记为 B-XXX 以突出显示它开始另一个实体。下面是一个例句,每行由[单词][词性标签] [NER 标签]组成:
我们PRP B-NP
看见了 VBD O
那个 DT B-NP
黄 JJ I-NP
狗 NN I-NP
北京生物工程学院
一种更复杂的注释方法区分命名实体和单个实体的结尾。这种方法被称为内侧、**B、**n、 **O、**n、 **E、**d、 **S、**S。上述数据集都没有使用现成的 BIOES,但它显示出比 BIO 有相当大的性能改进(例如 Chiu 和 Nichols,2016 )。
更多方法和细节
这里有一篇很棒的博文关于进一步的注释方法及其复杂性。
第一篇帖子到此结束。理解可用的数据以及如何对其进行注释,为您以后构建可靠的统计模型提供了良好的基础。让我知道你是否找到了其他有用的数据来源!👋
用于物体检测的深度学习:综述
随着自动驾驶汽车、智能视频监控、面部检测和各种人数统计应用的兴起,对快速准确的物体检测系统的需求不断增加。这些系统不仅包括识别和分类图像中的每个对象,还包括通过在每个对象周围绘制适当的边界框来定位每个对象。这使得物体检测比其传统的计算机视觉前身图像分类困难得多。
然而,幸运的是,目前最成功的对象检测方法是图像分类模型的扩展。几个月前,谷歌为 Tensorflow 发布了一个新的对象检测 API 。随着这一版本的发布,为少数特定型号提供了预构建的架构和重量:
- 带 MobileNets 的单次多箱探测器 (SSD)
- 带盗梦空间 V2 的固态硬盘
- 基于区域的全卷积网络 (R-FCN)带 Resnet 101
- 使用 Resnet 101 实现更快的 RCNN
- 更快的 RCNN 与 Inception Resnet v2
在我的上一篇博文中,我介绍了上面列出的三种基础网络架构背后的直觉:MobileNets、Inception 和 ResNet。这一次,我想对 Tensorflow 的对象检测模型做同样的事情:更快的 R-CNN、R-FCN 和 SSD。到这篇文章结束时,我们将有望了解深度学习如何应用于对象检测,以及这些对象检测模型如何相互启发和分歧。
更快的 R-CNN
更快的 R-CNN 现在是基于深度学习的对象检测的规范模型。它帮助启发了许多后来的检测和分割模型,包括我们今天要研究的另外两个模型。不幸的是,如果不了解它的前身 R-CNN 和 Fast R-CNN,我们就无法真正开始了解更快的 R-CNN,所以让我们快速了解一下它的祖先。
R-CNN
有线电视新闻网是更快的有线电视新闻网的始祖。换句话说,R-CNN 真的开球了。
R-CNN,或称 R 基于地区的Con 可选 N eural N 网络,由 3 个简单的步骤组成:
- 使用一种称为选择性搜索的算法扫描输入图像中的可能对象,生成大约 2000 个区域提议
- 在这些区域建议的基础上运行卷积神经网络( CNN )
- 获取每个 CNN 的输出,并将其输入 a)SVM 以对区域进行分类,以及 b)线性回归以收紧对象的边界框,如果这样的对象存在的话。
这三个步骤如下图所示:
换句话说,我们首先提出区域,然后提取特征,然后根据特征对这些区域进行分类。本质上,我们已经将目标检测转化为图像分类问题。R-CNN 非常直观,但是非常慢。
快速 R-CNN
R-CNN 的直系后裔是 Fast-R-CNN。快速 R-CNN 在许多方面与原来的相似,但通过两个主要增强功能提高了检测速度:
- 在提出区域之前,对图像执行特征提取,从而在整个图像上仅运行一个 CNN,而不是 2000 个 CNN 的 2000 多个重叠区域
- 用 softmax 图层替换 SVM,从而扩展用于预测的神经网络,而不是创建新模型
新模型看起来像这样:
正如我们从图像中看到的,我们现在基于网络的最后一个特征图而不是原始图像本身来生成区域建议。因此,我们可以为整个图像只训练一个 CNN。
此外,有一个 softmax 图层直接输出分类概率,而不是训练许多不同的 SVM 来对每个对象类进行分类。现在,我们只有一个神经网络来训练,而不是一个神经网络和许多 SVM 氏症。
快速 R-CNN 在速度方面表现得好得多。只剩下一个大瓶颈:生成区域提议的选择性搜索算法。
更快的 R-CNN
在这一点上,我们回到了我们最初的目标:更快的 R-CNN。快速 R-CNN 的主要观点是用快速神经网络取代缓慢的选择性搜索算法。具体来说,它介绍了区域提案网络 (RPN)。
RPN 是这样工作的:
- 在初始 CNN 的最后一层,3×3 的滑动窗口在特征图上移动,并将其映射到更低的维度(例如 256-d)
- 对于每个滑动窗口位置,它基于 k 固定比率锚框(默认边界框)生成多个可能区域
- 每个区域提议包括 a)该区域的“客观性”分数,以及 b)表示该区域的边界框的 4 个坐标
换句话说,我们查看上一个特征地图中的每个位置,并考虑以它为中心的不同盒子:高盒子、宽盒子、大盒子等等。对于这些盒子中的每一个,我们输出我们是否认为它包含一个对象,以及这个盒子的坐标是什么。这是在一个滑动窗口位置的外观:
2 个 k 个分数表示每个 k 个边界框位于“对象”上的最大软概率请注意,尽管 RPN 输出边界框坐标,但它并不试图对任何潜在的对象进行分类:它唯一的工作仍然是提出对象区域。如果锚定框的“客观性”分数高于某个阈值,则该框的坐标将作为区域建议向前传递。
一旦我们有了地区提案,我们就把它们直接输入到一个快速的 R-CNN 中。我们添加一个池层,一些完全连接的层,最后是一个 softmax 分类层和边界框回归。从某种意义上来说,快 R-CNN = RPN +快 R-CNN。
总之,更快的 R-CNN 实现了更好的速度和最先进的准确性。值得注意的是,虽然未来的模型做了很多工作来提高检测速度,但很少有模型能够远远超过更快的 R-CNN。换句话说,更快的 R-CNN 可能不是最简单或最快的对象检测方法,但它仍然是性能最好的方法之一。举个例子,Tensorflow 更快的 R-CNN 和 Inception ResNet 是他们最慢但最精确的模型。
说到底,更快的 R-CNN 可能看起来很复杂,但它的核心设计与最初的 R-CNN 是一样的:假设对象区域,然后对它们进行分类。这是现在许多物体检测模型的主要管道,包括我们的下一个。
R-FCN
还记得 R-CNN 通过在所有区域提案中共享一个 CNN 计算来提高原始的检测速度有多快吗?这种想法也是 R-FCN 背后的动机:通过最大化共享计算来提高速度。
R-FCN,或者说基于区域的 RFfullyCon 可选的 N et,在每一个输出上共享 100%的计算。由于是完全卷积的,它在模型设计中遇到了一个独特的问题。
一方面,在对一个物体进行分类时,我们要学习一个模型中的位置不变性:不管猫出现在图像的什么地方,我们都要把它归类为猫。另一方面,当执行对象的检测时,我们想要学习位置方差:如果猫在左上角,我们想要在左上角画一个方框。因此,如果我们试图在 100%的网络上共享卷积计算,我们如何在位置不变性和位置方差之间折衷?
R-FCN 的解决方案:位置敏感得分图。
每个位置敏感得分图代表一个对象类的一个相对位置。例如,一个分数图可能会在检测到猫的右上角时激活。当看到汽车左下方的时,另一个得分图可能会激活。你明白了。本质上,这些分数图是卷积特征图,已经被训练来识别每个对象的某些部分。
现在,R-FCN 的工作方式如下:
- 对输入图像运行 CNN(在本例中是 ResNet)
- 添加一个完全卷积层,以生成前述“位置敏感得分图”的得分库应该有 k (C+1)个分数图,其中 k 表示划分对象的相对位置的数量(例如,3×3 网格为 3),C+1 表示类别加上背景的数量。
- 运行完全卷积区域建议网络(RPN)以生成感兴趣区域(RoI)
- 对于每个 RoI,将其划分为与分数图相同的 k 个“箱”或子区域
- 对于每个媒体夹,检查乐谱库以查看该媒体夹是否与某个对象的相应位置相匹配。例如,如果我在“左上角”框上,我将抓取对应于对象“左上角”的得分图,并对 RoI 区域中的这些值进行平均。这一过程对每个班级都重复进行。
- 一旦 k 个箱中的每一个都具有每个类的“对象匹配”值,则对箱进行平均以获得每个类的单个分数。
- 在剩余的 C+1 维向量上用 softmax 对 RoI 进行分类
总的来说,R-FCN 看起来像这样,一个 RPN 生成 RoI:
即使有了解释和图像,您可能仍然会对这个模型的工作原理感到有点困惑。老实说,当你能想象它在做什么时,R-FCN 就更容易理解了。这是一个 R-FCN 在实践中检测婴儿的例子:
简单地说,R-FCN 考虑每个区域提议,将其划分为子区域,并在子区域上迭代,询问:“这看起来像婴儿的左上方吗?”,“这看起来像婴儿的顶部中心吗?”“这看起来像婴儿的右上方吗?”等。它对所有可能的类重复这一过程。如果足够多的子区域说“是的,我与婴儿的那部分匹配!”,RoI 在所有类的 softmax 之后被分类为婴儿。
通过这种设置,R-FCN 能够通过建议不同的对象区域来同时解决位置变化,并且通过使每个区域建议引用回相同的分数地图库来解决位置不变性。这些评分图要学会把一只猫归为一只猫,不管这只猫出现在哪里。最重要的是,它是完全卷积的,这意味着所有的计算在整个网络中共享。
因此,R-FCN 比更快的 R-CNN 快几倍,并达到相当的准确性。
(同 solid-statedisk)固态(磁)盘
我们最后的型号是 SSD,代表Ssingle-ShotDetector。像 R-FCN 一样,它提供了比更快的 R-CNN 更大的速度增益,但是以一种明显不同的方式。
我们的前两个模型在两个独立的步骤中执行区域提议和区域分类。首先,他们使用区域提议网络来生成感兴趣的区域;接下来,他们使用全连接层或位置敏感卷积层对这些区域进行分类。SSD 在“单次拍摄”中完成这两项工作,在处理图像时同时预测边界框和类。
具体来说,给定一个输入图像和一组基本事实标签,SSD 执行以下操作:
- 将图像通过一系列卷积层,产生几组不同比例的特征图(例如 10x10、6x6、3x3 等。)
- 对于这些特征图的每个中的每个位置,使用 3×3 卷积过滤器来评估一小组默认边界框。这些默认的边界框本质上相当于更快的 R-CNN 的锚框。
- 对于每个框,同时预测 a)边界框偏移和 b)类别概率
- 在训练期间,根据 IoU 将地面实况框与这些预测框匹配。最佳预测框将被标记为“正”,以及所有其他具有真值为 0.5 的 IoU 的框。
SSD 听起来很简单,但是培训它有一个独特的挑战。使用前面的两个模型,区域建议网络确保我们试图分类的所有东西都有成为“对象”的最小概率。然而,对于 SSD,我们跳过了过滤步骤。我们从图像的每一个位置开始分类并绘制边界框,使用多个不同的形状*,在几个不同的比例。结果,我们生成了比其他模型多得多的包围盒,而且几乎所有的包围盒都是反例。*
为了修复这种不平衡,SSD 做了两件事。首先,它使用非最大抑制将高度重叠的框组合成一个框。换句话说,如果四个形状、大小等相似的盒子。包含同一只狗,NMS 会保留最有信心的一只,丢弃其余的。其次,该模型使用了一种叫做硬负挖掘的技术来平衡训练期间的类。在硬负挖掘中,在每次迭代训练时,仅使用具有最高训练损失(即,假阳性)的负样本的子集。固态硬盘保持 3:1 的正负比例。
它的架构是这样的:
正如我上面提到的,在最后有“额外的特征层”,尺寸缩小。这些不同尺寸的特征地图有助于捕捉不同尺寸的物体。例如,下面是固态硬盘的应用:
在较小的特征地图(例如 4x4)中,每个单元覆盖图像的较大区域,使它们能够检测较大的对象。区域提议和分类是同时执行的:给定 p 个对象类别,每个边界框与一个(4+ p )维向量相关联,该向量输出 4 个框偏移坐标和 p 个类别概率。在最后一步中,再次使用 softmax 对对象进行分类。
最终,SSD 与前两种型号没有太大区别。它简单地跳过了“区域提议”步骤,而是在分类的同时考虑图像的每个位置中的每个单个边界框。因为 SSD 一次搞定一切,所以是三款中最快的,表现还是相当不俗的。
结论
更快的 R-CNN、R-FCN 和 SSD 是目前最好和最广泛使用的三种对象检测模型。其他流行的模式往往与这三个相当相似,都依赖于深度 CNN 的(阅读:ResNet,Inception 等。)来完成最初的繁重工作,并在很大程度上遵循相同的提议/分类流程。
此时,将这些模型投入使用只需要了解 Tensorflow 的 API。Tensorflow 有一个使用这些模型的入门教程在这里。试试吧,祝你黑客生涯愉快!
用于从非结构化文本中抽取特定信息的深度学习
这是与我们的 iki 项目工作相关的系列技术帖子的第一篇,涵盖了机器学习和深度学习技术用于解决各种自然语言处理和理解问题的一些应用案例。
在这篇文章中,我们将解决从非结构化文本中提取某些特定信息的问题。我们需要从用户的简历中提取他们的技能,即使他们是以任意的方式写的,比如“在生产服务器上部署量化交易算法”。
本帖有一个 演示页面 ,在你的简历上查看我们模特的表现。
语言模型
现代语言模型( ULMfit , ELMo )使用无监督学习技术,例如在大型文本语料库上创建 RNNs 嵌入,以在更具体的监督训练步骤之前获得语言结构的一些原始“知识”。相反,在某些情况下,你需要一个在非常具体的小数据集上训练的模型。这些模型对一般的语言结构几乎一无所知,并且只能处理特殊的文本特征。一个经典的例子是用于电影评论或新闻数据集的幼稚情感分析工具——最简单的工作模型只能在“好”或“坏”形容词同义词和一些强调词存在的情况下运行。在我们的研究中,我们利用了两种方法的优点。
一般来说,当分析某个文本语料库时,我们会查看每个文本的全部词汇。文本矢量化的流行方法,例如 tfidf、 word2vec 或GloVe模型使用整个文档的词汇来创建其向量,除了停用词(例如冠词、代词和在这种统计平均过程中带来很少语义意义的其他相当通用的语言元素)。如果有一个更具体的任务,你有一些关于文本语料库的额外信息,你可能会说一些信息比另一些更有价值。例如,要对烹饪食谱语料库进行分析,从文本中提取配料或菜名类别是很重要的。另一个例子是从简历的语料库中提取专业技能。例如,如果我们可以通过将简历与提取的技能向量相关联来对每份简历进行矢量化,这将让我们更成功地进行行业职位聚类。
示例:
简历: 数据科学家,在机器学习、大数据、开发、统计和分析方面有动手能力。我的数据科学家团队实施了 Python 机器学习模型集成、堆叠和特征工程,展示了预测分析的高准确率。使用 Doc2Vec 单词嵌入和神经网络创建了一个推荐系统。
提取专业技能: 机器学习、大数据、开发、统计、分析、Python 机器学习模型集成、堆栈、特征工程、预测分析、Doc2Vec、单词嵌入、神经网络。
步骤 1:词性标注
实体抽取的任务是文本挖掘类问题的一部分——从非结构化的文本中抽取一些结构化的信息。让我们仔细看看建议的实体提取方法。至于主要存在于所谓的名词短语中的技能,我们提取过程的第一步将是由 NLTK 库内置方法执行的实体识别(从文本中提取信息的检验, NLTK book,part 7 )。词性标注方法提取名词短语,并建立代表名词短语和句子其他部分之间关系的树。NLTK 库有许多工具可以执行这样的短语分解。
NLTK book, chapter 7, pic 2.2: An example of a simple regular expression based NP Chunker.
我们可以将模型定义为给出句子分解的正则表达式(例如,我们可以将一个短语定义为多个形容词加一个名词),或者我们可以在 NLTK 中带有提取的名词短语示例的标记数量的文本上教授模型。这一步导致接收许多实体,其中一些是目标技能,一些不是——除了技能 CV 可以包含一些其他实体,如地点、人员、对象、组织等等。
步骤 2:用于候选分类的深度学习架构
下一步是实体分类。这里的目标很简单——区分技能和“非技能”。用于训练的特征集是根据候选短语的结构和上下文构成的。显然,为了训练一个模型,我们必须创建一个带标签的训练集,我们手动为 1500 个提取的实体做了这件事,这些实体中有技能和“非技能”。
我们从来没有试图让我们的模型适合一些有限的硬编码技能,该模型背后的核心思想是学习英语简历中技能的语义,并使用该模型提取看不见的技能。
每个单词的向量由二进制特征组成,如数字或其他特殊字符的出现(技能通常包含数字和符号:C#、Python3)、首字母大写或整个单词大写(SQL)。我们还检查一个单词是否出现在英语词汇和一些主题列表中,如名称、地名等。使用所列特征的最终模型在实体测试集上显示了 74.4%的正确结果。使用另一个二元特征来描述候选中流行的英语前缀和后缀的存在,将模型的性能提高到测试集上 77.3%的正确结果。在模型的特征集中加入编码词性的独热向量后,我们的结果提高到了 84.6%。
可靠的语义单词嵌入模型不能在 CV 数据集上训练,它太小并且太窄,为了减轻这个问题,你应该使用在其他一些非常大的数据集上训练的单词嵌入。我们使用 50 维的手套模型向量,在测试集上将我们的模型性能提高到 89.1%的正确结果。您可以通过上传您简历中的文本,在我们的 演示 中玩最终模型。
流行的词性标注者( NLTK POS tagger , Stanford POS tagger )经常在简历的短语标注任务中出错。原因是,为了突出经验并赋予其一定的结构(人们以谓语而不是主语开始句子,有时短语缺少适当的语法结构),简历文本经常忽略语法,许多单词是特定的术语或名称。我们必须编写自己的 postager 来解决上述问题。
分类是用 Keras 神经网络执行的,该网络具有三个输入层,每个输入层被设计成接受特殊类别的数据。第一输入层采用由候选短语的上述特征组成的可变长度向量,该候选短语可以具有任意数量的单词。这个特征向量用 LSTM 层处理。
第二个可变长度向量带来上下文结构信息。对于给定的窗口大小 n,我们取候选短语右侧的 n 个相邻单词和左侧的 n 个单词,这些单词的矢量表示被连接成可变长度矢量并被传递到 LSTM 层。我们发现最优的 n=3。
第三输入层具有固定的长度,并利用关于候选短语及其上下文的一般信息来处理向量——短语及其上下文中的单词向量的坐标最大值和最小值,这些信息以及其他信息表示整个短语中许多二元特征的存在或不存在。
我们称这个建筑技能为“拖拉机”,这就是。
Skills Extractor network architecture
它的 Keras 实现如下所示:
在学习率降低到 0.0001 的情况下,用 Adam 优化器实现了模型训练的最佳结果。我们选择 binary_crossentropy 作为损失函数,因为该模型被设计成分类成两类。
为了方便使用,我们加入拟合方法,利用交叉验证和预测函数进行神经网络的训练和自动停止,形成候选短语特征向量的预测。
pad_sequences 函数将特征序列列表转换为一个 2d 数组,其宽度等于列表中最长的序列。这是为了将进入 LSTM 层的可变长度数据转换成模型训练所需的格式。
onehot_transformfunction 将目标值 0 和 1 转换为 one-hot 向量[1,0]和[0,1]
只要实体及其上下文中的字数是任意的,使用稀疏固定长度向量看起来就不合理。因此,处理任意长度向量的递归神经网络在这里成为一种方便且非常自然的解决方案。我们的测试证明,使用密集层来处理固定长度向量,使用 LSTM 层来处理可变长度向量的架构是最佳的。
已经用密集层与 LSTM 层的不同组合测试了几种架构。最终的架构配置(层的大小和数量)显示了交叉验证测试的最佳结果,这对应于训练数据的最佳使用。可以通过增加训练数据集的大小以及适当地缩放层的大小和数量来执行进一步的模型调整,使用相同的数据集进行后期调整会导致模型过度拟合。
结果
Examples of extracted skills
所有用于模型训练的简历都来自 IT 行业。我们很高兴地看到,我们的模型在属于其他行业(如设计和金融)的简历数据集上也显示出相当合理的性能。显然,处理结构和风格完全不同的 cv 会导致模型性能降低。我们还想提一下,我们对“技能”概念的理解可能与其他人不同。对于我们的模型来说,一个困难的情况是分辨新公司名称中的技能,因为技能通常等同于软件框架,有时你无法分辨这是提到的初创公司名称,还是新的 JS 框架或 Python 库。然而,在大多数情况下,我们的模型可以成为自动 CV 分析的有用工具,并且与一些统计方法一起可以解决任意 CV 语料库上的广泛的数据科学任务。
面向大众的深度学习(…和语义层)
深度学习现在无处不在,在你的手表里,在你的电视机里,在你的手机里,在某种程度上,在你阅读这篇文章的平台上。在这里我将谈论如何以一种非常简单的方式开始使用深度学习来改变你的业务。但是首先,你需要了解语义层。
深度学习简介
本文的范围不是介绍深度学习,我已经在其他文章中介绍过了,您可以在这里找到:
有关于深度学习的惊人介绍、课程和博文。但这是一种不同的介绍…
towardsdatascience.com](/a-weird-introduction-to-deep-learning-7828803693b0) [## 我的深度学习之旅
在这篇文章中,我将分享我如何研究深度学习并使用它来解决数据科学问题。这是一个…
towardsdatascience.com](/my-journey-into-deep-learning-c66e6ef2a317) [## 关于深度学习的对话
有人无意中听到两个人谈论深度学习,让我知道每一个小细节。其中一个完全…
towardsdatascience.com](/a-conversation-about-deep-learning-9a915983107)
但是如果你想从这里体验一下,我可以告诉你:
…深度学习是使用不同种类的神经网络(深度神经网络)和优化网络的超参数来获得(学习)我们数据的最佳表示的表示学习。
如果你想知道这是从哪里来的,请阅读上面的文章。
深度学习没那么难
This is harder
目前,组织的深度学习并不难。我并不是说深度学习整体上很容易,该领域的研究需要大量的数学、微积分、统计学、机器学习、计算等知识。你可以从我不久前创建的时间线中看到深度学习的来源:
从那里我可以说反向传播的思想,网络参数的更好初始化,更好的激活函数,辍学的概念,以及一些类型的网络,如卷积神经网络,残差网络,区域基 CNN,递归神经网络和生成对抗网络,是我们在深度学习领域取得的最重要的进展之一。
但是你现在如何使用深度学习呢?
hehe
数据第一
Oh, you’d want to be them. Right?. Or maybe not, IDK.
你想知道秘密吗?大型科技公司使用的秘方?不仅仅是深度学习(可能根本不是深度学习)
这里不做完整的演讲,一切从数据说起。正如您可以想象的那样,数据现在是公司的重要资产(可能是最重要的资产)。所以在你可以应用机器学习或深度学习之前,你需要拥有它,知道你拥有什么,理解它,治理它,清理它,分析它,标准化它(也许更多),然后你才能想到使用它。
摘自 Brian Godsey 的惊艳文章:
无论哪种形式,数据现在无处不在,而不仅仅是分析师用来得出结论的工具,它已经成为自己的目的。公司现在似乎将收集数据作为一种目的,而不是一种手段,尽管他们中的许多人声称计划在未来使用这些数据。独立于信息时代的其他定义特征,数据获得了自己的角色、自己的组织和自己的价值。
因此,您可以看到,它不仅将最新的算法应用于您的数据,还能够以良好的格式保存数据,理解数据,然后使用数据。
语义层
These layers mean something. Ok but this is not the semantic layer. Keep reading.
从我这里听到这种事情很不寻常,但是我已经做了很多调查,并且与几家公司合作,他们似乎都有同样的问题。他们的数据。
数据可用性、数据质量、数据接收、数据集成等是常见问题,不仅会影响数据科学实践,还会影响整个组织。
有多种方法可以清理您的数据并为机器学习做准备,并且有很好的工具和方法,您可以在这里阅读更多信息:
[## 宣布 Optimus v2 —简化敏捷数据科学工作流程
作为一名数据科学家,您是否正在寻找一个库来提升您的工作效率?看看这个。
towardsdatascience.com](/announcing-optimus-v2-agile-data-science-workflows-made-easy-c127a12d9e13)
但这意味着你有一个吸收和整合数据的过程。现在有很多很好的工具可以用于 AutoML,我之前已经谈到过:
[## Auto-Keras,或者说如何用 4 行代码创建深度学习模型
自动化机器学习是这个城市的新生事物,它会一直存在下去。它帮助我们创造越来越好的产品…
www.kdnuggets.com](https://www.kdnuggets.com/2018/08/auto-keras-create-deep-learning-model-4-lines-code.html)
以及其他商业工具,如 DataRobot:
DataRobot 的自动化机器学习平台使构建和部署准确的预测模型变得快速而简单…
www.datarobot.com](https://www.datarobot.com/)
但是自动摄取和集成呢?
这是语义层令人惊奇的好处之一。但是语义层到底是什么呢?
语义这个词本身就意味着意义或理解。因此,语义层与数据有关,涉及数据的含义而不是数据的结构。
理解这是一个非常重要的过程,我之前已经讲过了:
在这篇文章中,我将展示数据科学如何让我们通过人工智能创造智能。
towardsdatascience.com](/creating-intelligence-with-data-science-2fb9f697fc79)
这里我提到(来自 Lex Fridman )的是:
理解是将 复杂的 信息转化为 简单的 ,有用的 信息的能力。
当我们理解时,我们正在解码组成这个复杂事物的各个部分,并把我们一开始得到的原始数据转化成有用的、简单易懂的东西。我们通过建模来做到这一点。你可以想象我们需要这样的模型来理解数据的意义。
关联数据和知识图
我们需要做的第一件事是链接数据。链接数据的目标是以一种易于使用和与其他链接数据组合的方式发布结构化数据。
链接数据是 Web 上数据发布和互操作性的新的事实上的标准,并且也正在进入企业。像谷歌、脸书、亚马逊和微软这样的大公司已经采纳了它背后的一些原则。
链接数据的过程是知识图的开始。知识图是一种高级的方法,可以映射某个特定主题的所有知识,填补数据之间的空白,或者数据库内部的虫洞。
知识图由数据和信息的集成集合组成,其中还包含不同数据之间的大量链接。
这里的关键是,在这个新模型下,我们不是在寻找可能的答案,而是在寻找答案。我们想要事实——这些事实从何而来并不重要。
这里的数据可以代表概念、物体、事物、人,实际上是你脑海中的任何东西。图表填充了概念之间的关系和联系。
以下是谷歌 6 年前(是的,6 年前)对知识图谱的精彩介绍:
知识图谱对你和你的公司意味着什么?
按照传统的方式,数据仓库中的数据模型虽然是一项了不起的成就,但却无法吸收向我们袭来的海量数据。创建关系数据模型的过程就是跟不上。此外,用于支持数据发现的数据提取量也太小。
因此,基于 Hadoop 或云存储的数据湖已经激增为数据沼泽,而没有所需的管理和治理能力。
https://timoelliott.com/blog/2014/12/from-data-lakes-to-data-swamps.html
您是否问过您的数据工程师和科学家,他们是否了解您组织拥有的所有数据?动手吧。
分析你所有的数据也非常困难。并了解其背后的关系。
因为是图,知识图更直观。人们不会用表格来思考,但他们会立刻理解图表。当你在白板上画出一个知识图表的结构时,它对大多数人的意义是显而易见的。
知识图表还允许您为图表中的关系创建结构。你可以讲一个图,父母有孩子,父母可以是孩子,孩子可以是兄弟姐妹,这些都是人。提供这样的描述性信息允许从图中推断出新的信息,例如如果两个人有相同的父母,他们一定是兄弟姐妹。
为您的组织扩展语义层
当我在寻找可以帮助我和你实现端到端平台以在企业级交付真正的语义层时,我发现了一个很棒的平台:由一家名为Cambridge Semantics的公司创建的 Anzo。
I’m going to edit this. Keep reading!!
你可以用 Anzo 建立一个叫做“企业知识图”的东西。
图中的节点和边灵活地捕捉了每个数据源的高分辨率孪生数据—结构化的或非结构化的。该图表可以帮助用户快速、交互式地回答任何问题,允许用户与数据进行对话以揭示见解。
除了使每天的大数据分析问题变得简单之外,graph 还开启了 graph 特别适合的新的可能性。基于开放标准的图表是一个持续改进的平台。在图表中,使用业务规则、文本分析甚至机器学习(这将很快变得重要)来快速链接和协调来源。
我也喜欢数据结构的想法。然后我意识到其他人也在用同样的概念。这让我想起了时空结构。我继续定义了数据结构(不知道作者是什么意思,也没有阅读其他定义)。
物理学中时空结构的概念是为了解释空间和时间的连续性而创建的,它由四个维度(或者 11 个或者 26 个,取决于你的理论)组成。在这个结构中,重力是扭曲时空结构的一种表现。
From Ethan Siegel: You can talk about space as a fabric, but if you do, be aware that what you’re doing is implicitly reducing your perspective down to a two-dimensional analogy. Space in our Universe is three dimensional, and when you combine it with time, you get a four dimensional quantity.
那么什么是数据结构呢?如果我们想到物理学中的定义,我们可以说对于一个组织来说:
数据结构是支持公司所有数据的平台。它是如何被管理、描述、组合和普遍访问的。该平台由企业知识图构成,以创建统一的数据环境。
有了 Anzo,这是可能的。这就是使用 Anzo 的数据结构的样子(看起来有点像时空结构,太棒了!):
数据结构之上的是数据层。这些数据层可以添加数据清理、转换、链接和访问控制等内容,以迭代的方式动态增强内存中的图形。
这种堆叠方式的数据层非常灵活,这意味着您可以轻松地打开或关闭层,并根据需要移除、复制和创建层。
有了 Anzo,你可以自动生成查询(是的,这是一个东西),并使用它们来处理复杂的图形,使提取特征变得容易,并最终完全自动化!
通过 Anzo 的几个组件,用户可以真正地与他们的数据进行对话——快速而轻松地根据问题的答案以新的方向进行分析,而无需专业的查询知识,他们甚至可以遍历最复杂的多维数据,以构建探索性的图表、过滤器、表格甚至网络视图。
通过 Spark、Featuretools 和 Optimus 等开源技术的连接,您可以充分准备您的数据,并最终为机器和深度学习做好准备。
我将在未来写更多关于这方面的内容,但现在,让我们认为我们已经有了我们的数据结构和一切,我们想做机器和深度学习。
适合你的深度学习
好的,深度学习。你想用它。它的主要应用是什么?
在这里你可以看到其中的一些:
https://www.slideshare.net/NVIDIA/deep-learning-workflows-training-and-inference
在深度学习成为人工智能世界之王的几年里,它取得了巨大的成就,Franç ois Chollet 列出了深度学习的以下突破:
- 接近人类水平的图像分类。
- 接近人类水平的语音识别。
- 接近人类水平的手写转录。
- 改进的机器翻译。
- 改进的文本到语音转换。
- Google Now 或亚马逊 Alexa 等数字助手。
- 接近人类水平的自动驾驶。
- 谷歌、百度和必应使用的改进的广告定位。
- 改进的网络搜索结果。
- 回答自然语言问题。
所以你可以用它做很多事情。现在,你怎么做呢?
可悲的是,人工智能专业知识(严重)短缺,这给准备采用人工智能的组织造成了重大障碍。通常我们做深度学习编程,学习新的 API,有些比其他的更难,有些真的很容易,比如 Keras。
现在,你可以使用一种更具表现力的方式来创建深度学习模型。那就是利用深度认知。我以前讲过:
在过去的一个月里,我有幸见到了 DeepCognition.ai 的创始人
becominghuman.ai](https://becominghuman.ai/deep-learning-made-easy-with-deep-cognition-403fbe445351)
他们的平台 Deep Learning Studio 有云解决方案、桌面解决方案(【http://deepcognition.ai/desktop/】)可供选择,软件将在您的机器或企业解决方案(私有云或内部解决方案)上运行。
您可以使用预先训练的模型以及内置的辅助功能来简化和加速模型开发过程。您还可以导入模型代码,并使用可视化界面编辑模型。
当您迭代和调整超参数以提高性能时,平台会自动保存每个模型版本。您可以比较不同版本的性能,以找到您的最佳设计。
这个系统建立的前提是让人工智能对每个人来说都很容易,当创建这个复杂的模型时,你不必成为专家,但我的建议是,你对自己正在做的事情有一个想法,阅读一些 TensorFlow 或 Keras 文档,观看一些视频并获得信息是很好的。如果你是这方面的专家,那太好了!这将使你的生活更容易,你仍然可以在构建模型时应用你的专业知识。
你实际上可以下载产生预测的代码,正如你将看到的,它是用 Keras 编写的。然后,您可以上传代码,并使用系统提供的笔记本进行测试,或者在您的笔记本电脑或其他平台上使用它。
语义层和深度学习
因此,通过语义层与 Anzo 等平台和 Deep Learning Studio 等深度学习系统的连接,您可以加速数据和人工智能在您公司的使用。我认为这是一条几乎适用于所有组织的道路:
I went ahead and modified the original picture. I think this is with a touch of Python, Spark and stuff like that can be the future of data science and data technologies.
我认为这与敏捷商业科学问题框架(ABSPF)这样的方法一起,从端到端的角度来看,确实可以为组织带来价值。有关 ABSPF 的更多信息:
数据科学是一个令人惊叹的研究领域,学术界和工业界都在积极发展…
www .商业科学. io](https://www.business-science.io/business/2018/08/21/agile-business-science-problem-framework.html)
我认为我们可以让世界变得更好,改善我们的生活,改善我们工作、思考和解决问题的方式,如果我们现在就调动我们所有的资源,让这些知识领域为更大的利益而共同努力,我们就可以对世界和我们的生活产生巨大的积极影响。
这是我想和你开始的一个更长对话的开始。我希望它能帮助你在这个神奇的领域开始,或者只是发现一些新的东西。
如果这篇文章对你有帮助,请分享给你的朋友!
如果您有任何问题,请在 Twitter 上关注我:
Favio Vázquez 的最新推文(@FavioVaz)。数据科学家。物理学家和计算工程师。我有一个…
twitter.com](https://twitter.com/faviovaz)
和 LinkedIn:
[## favio vázquez——science ia y Datos | LinkedIn 创始人
查看 Favio Vázquez 在世界上最大的职业社区 LinkedIn 上的个人资料。Favio 有 16 个工作列在他们的…
www.linkedin.com](https://www.linkedin.com/in/faviovazquez/)
那里见:)
深度学习框架 Power Scores 2018
谁在使用、兴趣和受欢迎程度上领先?
深度学习仍然是数据科学中最热门的事情。深度学习框架正在快速变化。就在五年前,除了首席执行官之外,其他领导人都不在。
我想找到哪些框架值得关注的证据,所以我开发了这个权力排名。我使用了 7 个不同类别的 11 个数据源来衡量框架的使用、兴趣和受欢迎程度。然后我对这个 Kaggle 内核中的数据进行加权合并。
2018 年 9 月 20 日更新:由于普遍的需求,我扩展了评估的框架,包括 Caffe,Deeplearning4J,Caffe2 和 Chainer。现在所有在 KDNuggets 使用调查中报告使用率超过 1%的深度学习框架都包括在内。
2018 年 9 月 21 日更新:我在几个指标上做了一些方法上的改进。
事不宜迟,下面是深度学习框架的能力得分:
虽然 TensorFlow 是明显的赢家,但也有一些令人惊讶的发现。让我们开始吧!
竞争者
所有这些框架都是开源的。除了一个人之外,其他人都可以使用 Python,还有一些可以使用 R 或其他语言。
TensorFlow 是无可争议的重量级冠军。它拥有最多的 GitHub 活动,谷歌搜索,中型文章,亚马逊上的书籍和 ArXiv 文章。它还拥有大多数开发人员使用它,并被列在大多数在线职位描述中。TensorFlow 由谷歌提供支持。
Keras 有一个“为人类设计的 API,而不是为机器设计的”这是几乎所有评估领域中第二受欢迎的框架。 Keras 位于 TensorFlow、Theano 或 CNTK 之上。如果你是深度学习的新手,可以从 Keras 开始。
PyTorch 是第三大流行的整体框架,也是第二大流行的独立框架。它比 TensorFlow 年轻,受欢迎程度增长迅速。它允许 TensorFlow 不允许的定制。它得到了脸书的支持。
Caffe 是第四大流行的框架。已经有将近五年了。雇主对它的需求相对较大,学术文章中也经常提到,但最近很少报道它的使用。
Theano 于 2007 年在蒙特利尔大学开发,是最古老的重要 Python 深度学习框架。它已经失去了很多人气,它的领导者声明主要版本已经不在路线图上了。但是,更新仍在继续。Theano 仍然是得分第五高的框架。
MXNET 由 Apache 孵化,亚马逊使用。它是第六大最受欢迎的深度学习库。
CNTK 是微软的认知工具包。它让我想起了微软的许多其他产品,因为它试图与谷歌和脸书的产品竞争,但并没有赢得广泛的采用。
Deeplearning4J ,也叫 DL4J,配合 Java 语言使用。这是 Python 中唯一不可用的半流行框架。但是,您可以将使用 Keras 编写的模型导入 DL4J。这是唯一一个两个不同的搜索词偶尔会有不同结果的框架。我对每个指标都使用了较高的数字。由于该框架得分很低,这并没有造成实质性的差异。
Caffe2 是另一个脸书开源产品。它构建于 Caffe 之上,现在存放在 PyTorch GitHub 库中。因为它不再有自己的存储库,所以我使用了旧存储库中的 GitHub 数据。
Chainer 是由日本公司 Preferred Networks 开发的一个框架。它有一小群追随者。
FastAI 建立在 PyTorch 上。它的 API 受 Keras 的启发,只需要更少的代码就能得到很好的结果。截至 2018 年 9 月中旬,FastAI 处于领先地位。它正在为定于 2018 年 10 月发布的 1.0 版本进行重写。杰瑞米·霍华德,FastAI 背后的力量一直是一个顶级卡格勒和卡格勒的总裁。他在这里讨论了为什么 FastAI 从 Keras 转到制作他们自己的框架。
FastAI 还没有被职业需求,也没有被广泛使用。然而,它通过广受欢迎的免费在线课程拥有庞大的用户渠道。它功能强大且易于使用。它的采用可能会显著增加。
标准
我选择了以下类别,以提供对深度学习框架的流行度和兴趣的全面看法。
评估类别包括:
- 在线工作列表
- KDnuggets 使用调查
- 谷歌搜索量
- 中等物品
- 亚马逊图书
- ArXiv 文章
- GitHub 活动
搜索于 2018 年 9 月 16 日至 9 月 21 日进行。源数据在这张谷歌表中。
我使用了 plotly 数据可视化库和 Python 的 pandas 库来探索流行性。对于交互式 plotly 图表,请参见我的 Kaggle 内核这里。
在线工作列表
如今的就业市场需要哪些深度学习库?我在 LinkedIn 上搜索了工作列表,事实上,简单雇佣,怪物和天使列表。
当谈到工作列表中提到的框架时,TensorFlow 显然是赢家。如果你想找一份做深度学习的工作,就去学吧。
我使用术语机器学习后跟库名进行搜索。于是用机器学习 TensorFlow 对 TensorFlow 进行了评测。我测试了几种搜索方法,这一种给出了最相关的结果。
需要一个额外的关键字来区分框架和不相关的术语,因为 Caffe 可能有多种含义。
使用
流行的数据科学网站 KDnuggets 对世界各地的数据科学家进行了调查,询问他们使用的软件。他们问:
在过去 12 个月中,您在实际项目中使用了哪些分析、大数据、数据科学、机器学习软件?
以下是这一类别框架的结果。
Keras 显示了惊人的使用量——几乎与 TensorFlow 一样多。有趣的是,美国雇主压倒性地寻求张量流技能,而 Keras 至少在国际上几乎同样频繁地被使用。
这一类别是唯一包含国际数据的类别,因为包含其他类别的国际数据会很麻烦。
KDnuggets 报告了几年的数据。虽然我在这次分析中只使用了 2018 年的数据,但我应该注意到,Caffe,Theano,MXNET 和 CNTK 的使用量自 2017 年以来有所下降。
谷歌搜索活动
在最大的搜索引擎上进行网络搜索是衡量受欢迎程度的一个很好的标准。我查看了过去一年谷歌趋势的搜索历史。谷歌不提供绝对搜索数字,但提供相对数字。
我在 2018 年 9 月 21 日更新了这篇文章,因此这些分数将包括截至 2018 年 9 月 15 日的一周内在机器学习和人工智能类别中的全球搜索。感谢 Franç ois Chollet 提出改进这一搜索指标的建议。
Keras 离 TensorFlow 不远。PyTorch 排名第三,其他框架的相对搜索量得分在 4 分或以下。这些分数用于功效分数计算。
让我们简单看看搜索量是如何随着时间的推移而变化的,以提供更多的历史背景。谷歌下面的图表显示了过去两年的搜索量。
TensorFlow = red, Keras = yellow, PyTorch = blue, Caffe = green
对张量流的搜索在过去的一年里并没有增长,但是 Keras 和 PyTorch 看到了增长。Google Trends 只允许同时比较五个术语,所以其他图书馆是在单独的图表上进行比较的。除了对 TensorFlow 的搜索兴趣很小之外,其他任何库都没有显示任何其他内容。
出版物
我在 power score 中包括了几种出版物类型。先看中等文章。
中等物品
Medium 是流行数据科学文章和指南的地方。而你现在在这里**——**太棒了!
终于有了新的赢家。在媒体文章提及方面,Keras 在 TensorFlow 之前破了带子。FastAI 的表现优于其通常的表现。
我假设这些结果可能已经发生,因为 Keras 和 FastAI 是初学者友好的。他们对新的深度学习从业者有相当多的兴趣,Medium 通常是教程的论坛。
在过去的 12 个月里,我用谷歌网站搜索了 Medium.com,搜索的关键词是框架名和“学习”。这种方法对于防止“咖啡”一词的错误结果是必要的。在几个搜索选项中,它的文章减少幅度最小。
现在让我们看看哪些框架在亚马逊上有关于它们的书籍。
亚马逊图书
我在书籍 - > 计算机&技术下搜索了 Amazon.com 上的各个深度学习框架。
张量流再次获胜。MXNET 的书比预期的多,而 Theano 的书比预期的少。PyTorch 的书相对较少,但这可能是因为这个框架还很年轻。由于出版一本书需要时间,这种方法偏向于老图书馆。
ArXiv 文章
ArXiv 是大多数学术机器学习文章发表的在线仓库。在过去的 12 个月里,我使用 Google 站点搜索结果在 arXiv 上搜索了每个框架。
更多相同的学术文章来自 TensorFlow。注意 Keras 在 Medium 和 Amazon 上比在学术文章上更受欢迎。Pytorch 在这一类别中排名第二,显示了它在实现新想法方面的灵活性。Caffe 的表现也相对不错。
GitHub 活动
GitHub 上的活动是框架受欢迎程度的另一个指标。我在下面的图表中列出了星星、叉子、观察者和贡献者,因为它们分开比组合起来更有意义。
TensorFlow 显然是 GitHub 上最受欢迎的框架,拥有大量的用户。考虑到 FastAI 还不到一岁,它已经有了相当多的追随者。有趣的是,所有框架的贡献者级别都比其他三个指标更接近。
收集和分析数据后,是时候将其整合到一个指标中了。
动力评分程序
以下是我如何创建能力分数的:
- 在 0 和 1 之间缩放所有特征。
- 聚合的工作搜索列表和 GitHub 活动子类别。
- 根据下面的权重对类别进行加权。
如上图所示,在线工作列表和 KDnuggets 使用情况调查占总得分的一半,而网络搜索、出版物和 GitHub 关注占另一半。这种划分似乎是各种类别之间最恰当的平衡。
4.可理解性的加权分数乘以 100。
5.将每个框架的类别得分相加,得到一个单项得分。
数据如下:
这是加权和汇总子类别后的分数。
这张漂亮的图表再次显示了最终的能力得分。
100 分是可能的最高分,表示每个类别的第一名。TensorFlow 几乎获得了 100 分,这并不奇怪,因为它在每个类别中都名列前茅。Keras 显然是第二名。
要互动地玩图表或分叉 Jupyter 笔记本,请前往这个 Kaggle 内核。
将来的
目前,TensorFlow 稳稳占据榜首。在短期内,它似乎有可能继续占据主导地位。然而,鉴于深度学习世界的发展速度,这种情况可能会改变。
时间会证明 PyTorch 是否超过 TensorFlow,因为 React 超过 Angular。这些框架可能是类似的。PyTorch 和 React 都是脸书支持的灵活框架,通常被认为比谷歌支持的竞争对手更容易使用。
FastAI 会在课程之外获得用户吗?它有大量的学生,是一个比 Keras 更容易上手的 API。
你认为未来会怎样?
2019 年 4 月 1 日更新:未来在这里!至少有一部分。😄我用这篇文章发表后的六个月的增长分数评估了领先的框架。点击此处查看新文章:
TensorFlow 与 PyTorch
towardsdatascience.com](/which-deep-learning-framework-is-growing-fastest-3f77f14aa318)
给学习者的建议
如果你正在考虑学习这些框架中的一个,并且拥有 Python、numpy、pandas、sklearn 和 matplotlib 技能,我建议你从 Keras 开始。它拥有庞大的用户群,雇主对它有需求,在媒体上有很多文章,并且有一个易于使用的 API。
如果你已经知道了 Keras ,,决定下一个要学习的框架可能会很棘手。我建议你选 TensorFlow 或者 PyTorch,好好学学,这样就能做出很棒的深度学习模型。
如果你想掌握什么是需求,TensorFlow 显然是学习的框架。但是 PyTorch 的易用性和灵活性使其受到研究人员的欢迎。下面是 Quora 对这两个框架的讨论。
一旦你掌握了这些框架,我建议你继续关注 FastAI。如果你想学习基础和高级深度学习技能,请查看其免费在线课程。FastAI 1.0 承诺让你轻松实现最新的深度学习策略,快速迭代。
无论你选择哪种框架,我希望你现在对哪种深度学习框架需求最大、使用最多、写得最多有了更好的了解。
如果你觉得这很有趣或有帮助,请通过分享和鼓掌来帮助其他人找到它。
快乐深度学习!
从名字-LSTM 递归神经网络深度学习性别
Python - All *。py 脚本
github.com](https://github.com/prdeepakbabu/Python/tree/master/Deep%20learning%20gender)
深度学习神经网络已经在与视觉、语音和文本相关的问题上显示出有希望的结果,并取得了不同程度的成功。我在这里试着看一个文本问题,我们试着从人名中预测性别。rnn 非常适合这种情况,因为它涉及到从序列(在这种情况下是字符序列)中学习。由于梯度消失,传统的 rnn 存在学习问题。最近的进展表明,RNN 的两种变体可以帮助解决这个问题
(i) LSTM 或长短期记忆-使用记忆/遗忘门来保留或传递顺序学习的模式,用于预测目标变量。我们将在我们的模型中使用它。(推荐 colah 的博客以深入了解 LSTM 背后的理论)
㈡GRU 或门控循环单元
为了正式陈述这个问题,我们感兴趣的是预测给定的名字是男是女。在过去,已经有尝试基于在 NLTK 中看到的关于姓名的简单规则来预测性别,例如,依赖于姓名中的最后一个字符来分类性别,这由于高度概括而遭受低准确性。
我们将使用组成名字的字符序列作为 X 变量,Y 变量作为 m/f 来表示性别。我们使用一个堆叠的 LSTM 模型和一个带有 softmax 激活的最终密集层(多对一设置)。分类交叉熵损失与 adam 优化器一起使用。添加 20%的丢弃层用于正则化,以避免过拟合。示意图显示了模型设置。
LSTM RNN Architecture.
关于数据集
我们使用在 mbejda github 账户中可用的印度名字数据集,该账户具有从公共记录中收集的男性和女性印度名字数据库的集合。基本的预处理是删除重复的特殊字符。男/女班的最终分配比例为 55%:45%。值得注意的是,我们在这里使用全名。一些名字有两个以上的单词,这取决于姓氏、家族名字等。
使用 keras 实施
完整的数据集、代码和 python 笔记本可在我的 github repo 中获得。完整的实现是使用 keras 和 tensorflow 后端完成的。输入表示&参数在下面突出显示
(i) 词汇:我们有一组 39 个字符,包括 a-z、0-9、空格、点号和一个特殊的结束标记。
(二)最大序列长度:选择为 30 ie。超过 30 个字符的字符将被截断。如果名称少于 30 个字符,则填充“END”标记。
(iii) one hot encoding :对每个字符进行 one-hot 编码,表示为[1 X 39]维数组。
(iv) 批量:一批 1000 个样本
(v) 时期 : 50 个时期或 50 次我们迭代整个数据集(见一次)
(vi) Y 标签:表示为[1 X 2]的数组,第一列表示男性,第二列表示女性。例:[1 0]代表男性。
Loss & Accuracy charts as a function of epochs. As seen from loss charts, after 40 epochs the validation loss saturates while training loss keep reducing indicating over-fitting problems.
这个模型在我的中等高端笔记本电脑(基于 CPU)上运行了大约 2 个小时。在验证数据集上,最终的分类准确率为 86% 。更多关于精确度、召回率和混淆矩阵的统计数据如下所示。
模型显示识别男性(88%)比识别女性(84%)的精确度更高。在总共 3,028 个验证样本中,411 个样本被错误地预测,导致 86.43%的准确度和 13.5%的误差
解读模型(模型学到了什么?)
查看在验证集上做出的预测,模型似乎已经在序列中学习了以下模式。例如,出现的“先生”暗示可能是男性名字,而出现的“smt”和“mrs”则表示女性名字。深度学习的魅力在于端到端的学习能力,而不需要传统学习中所需的显式特征工程步骤。此外,女性的名字往往以元音 a,I,o 结尾,这似乎是模特们选择的。有更复杂的模式被模型拾取,不容易通过检查看到。
下一步
提高模型精度的一些想法是
(I)使用预先训练的字符嵌入,而不是一键编码(像这个)。记住这句话同样适用于角色
从一个人交的朋友,你就可以知道这个人说的话
(二)更好的抽样
a .限于名和姓。
b .按 1:1 的比例对男性班级和女性班级进行子抽样。从词汇表中删除所有非字符。
(三)超参数整定
a .序列的最大长度
b .堆叠层数。LSTM·盖茨
我很乐意听到你对这篇文章的评论/问题/建议,如果你觉得有趣,请分享。
深度学习 II L9:生成模型
fast.ai 的深度学习课程中的第九课继续从制作艺术的角度深入到生成对抗网络(GANs)中。这主要涉及(截至编写时)课程库中的神经风格和神经-sr Jupyter 笔记本。注:这篇帖子比较长。从简单开始,不断深入。
在第 8 课中,我们学习了获取一幅图像,将它放入由风格损失和内容损失组成的损失函数中,输出损失和梯度,并使用这些梯度来更新图像并在下一次迭代中减少损失——冲洗并重复。像这样:
copyright: my notebook …
根据杰瑞米·霍华德在讲座中的说法,这是对许多不同的风格和图像进行风格转换的最好方法,比如在 web 应用程序中。然而,如果你想应用一个单一的风格到任何图像:这是我们可以改变事情做得更好的地方。原因是你不需要做上面的优化循环来产生一些东西。相反,你可以只训练 CNN 来学习如何以特定的风格输出图像(并且通过 CNN 向前传递是非常快的——权衡是 CNN 被训练成特定的风格)。
这一次我们开始像以前一样将多个图像输入到同一个损失函数中(样式+内容)。在这个例子中,对于风格损失,我们使用梵高的虹膜,对于内容损失,我们使用当前输入到函数中的图像。这里最大的不同是,我们将在输入图像和损失函数之间放置一个 CNN。CNN 将学习输出一个图像,这样当它进入损失函数时,它将输出一个小的损失值。在英语中,这意味着 CNN 已经学会制作内容与原始输入图像相似、风格与所选风格相似的图像。
这里有一些注释。有了 CNN,你可以选择任何你喜欢的损失函数(你的里程可能会有所不同)。深度学习 I & II 到目前为止已经使用了相当简单的,比如 MSE 和交叉熵。不过,这里我们将使用样式+内容损失,就像上面的第一个例子一样。注意:因为样式+内容损失函数是由神经网络生成的:它是可微的;并且可以优化任何可微的损失函数。
现在,如果我们采用相对于 CNN 权重的输出梯度,我们可以使用它们来更新这些权重,这样 CNN 就可以更好地将图像转变为与风格相匹配的图像。
something like this
这一点的强大之处在于,没有优化步骤来减缓推理——或者模型的“预测”操作。通过 CNN 的单次向前传递几乎是瞬时的。
你还能做更多。
the future is here. ENHANCE.
事实证明,深度学习神经网络可以用来放大图像和推断细节。
we have the technology
我们从在传说和雇佣图像之间放一个 CNN 开始。CNN 将 LoRes 图像作为输入,并将其输出发送到仅计算内容损失的损失函数中。内容损失是通过将其从 CNN 的输入与从 HiRes 图像的激活进行比较来计算的。换句话说,损失函数是检查 CNN 是否从原始知识中创建了一个更大的图像,该图像与雇佣图像具有相同的激活。
这场讨论引发了我在课堂上听到的最好的问题之一:
我们能不能在任何两个事物之间放一个 CNN,它就能知道它们之间的关系?
是的,绝对的。
这就涉及到了我们与 CNN 之前不同的做法。一篇 2016 论文详细介绍了 CNN 使用不同的损失函数来做超分辨率。在此之前, MSE 通常用于升级网络像素输出和 HiRes 图像之间。问题是:模糊图像在 MSE 下仍然表现良好,但这对于图像任务来说有点不可接受。另一方面:
…如果你拿下 VGG 的第二或第三个 conv 街区,那么它需要知道这是一个眼球,否则它不会好看。
教训:使用内容损失而不是像素损失。(题外话:从在像素上使用MSE到内容丢失,显然花了 1 年时间。回顾过去,发现直观事物所花费的时间是很有趣的。)
论文列出了这种方法的一些有用应用——将它们框定为图像变换任务:
- 图像处理:去噪、超分辨率、彩色化
- 计算机视觉:语义分割,深度估计
(这里的另一个题外话是,使用生成模型,你可以通过添加噪声或使彩色图像灰度化等方式产生尽可能多的标签数据。)
high-level view of Content (Perceptual) Loss for Super Resolution or Style Transfer
2。现在进入代码。如果您想继续学习,请参见 neural-style.ipynb (注意:课程的未来更新可能会完全更改代码或笔记本)。
the final network — “The Upsampling Network”
上面的代码首先接收一批低分辨率图像,作为一个维度为arr_lr.shape[1:]
(这里是:(72, 72, 3)
)的张量。在笔记本中,arr_lr
和arr_hr
是 NumPy 数组。
inp = Input(arr_lr.shape[1:])
该输入然后被放入具有 64 个大小为 9 的滤波器和单位步幅(即输入大小没有变化)。
x = conv_block(inp, 64, 9, (1,1))
这是一个大的过滤器尺寸,因为我们想要一个大的初始感受野。显然,拥有 64 个滤波器可以确保没有信息丢失(来自 3 个颜色通道),但我不知道输入滤波器与滤波器的信息丢失曲线是什么样的。但显然这也变得越来越普遍。
接下来是大部分计算将要完成的地方。这是 GAN 必须弄清楚的部分,例如,那个黑点是眼球,然后一个更高分辨率的眼球看起来会是什么样子。
for i in range(4): x = res_block(x)
# res_block()
是在别处定义的 ResNet 块。
在创成式模型中,我们希望以低分辨率完成这个主要的计算步骤。低分辨率意味着工作量更少,因此计算速度更快,但最重要的是:我们将有一个更大的感受域。为什么这很重要?你可以很容易地想象出一张放大版的某人脸部照片是什么样子,因为你知道脸是什么样子的。你知道那个黑色的东西是一只眼睛,而那个黑色的区域是它们下颚投下的阴影。你一开始就知道这些,因为你能一眼看到整张照片,并认出它是一张脸,而不是餐盘或抽象艺术作品。GAN 必须做同样的事情。
决定感受域的有几个因素:卷积层深度、滤波器大小和下采样(非单位步长、最大池等)。
hopefully this makes some amount of sense
回到代码。ResNet 块是这样定义的:
ip: input; nf: num. filters
这个块接受一个输入,用它来构建两个卷积块(通过 Keras 的函数式 API ),然后将这些 Conv 块的结果添加回原始输入:return merge([x, ip], mode='sum')
最后的 Conv 块没有激活(act=False
),因为最近的一篇论文(不确定是哪一篇)发现没有 ResNet 块通常会执行得更好。
1st conv_block has ReLU activation; 2nd block no activ. ip is input. merge using sum operation.
从我目前对深度残差网络的理解来看,ResNet 的优势在于它给了网络的每一层一些关于原始输入的上下文。在讲座中,杰瑞米·霍华德说,一堆 ResNet 块可以磨练他们需要做什么来完成一项任务(这里:放大图像)。
y = f(x) + x;
→ f(x) = y — x;
其中y — x = the residual
那么,如果函数是输出 y 和输入 x 之差,即残差,这就给出了一些关于如何最小化损失函数的上下文信息?我将不得不及时了解更多关于那件事。
conv_block
相当标准:
a convolution, then batch-normalization, and optionally an activation
在这一点上,我们实际上需要改变图像的尺寸。最初的讲座使用了反卷积模块,执行反卷积/转置/分数阶卷积来重建图像的外观,如果它的当前版本(输入)是卷积的结果。简而言之:它是对(零)填充输入的卷积。如果你想深入了解,这是讲座中提到的链接。在课程的 github 存储库中,课程笔记本的当前版本、 neural-style.ipynb 以及 neural-sr.ipynb 都使用一个定义为:
如果我理解正确的话,这是课程代码的一点逻辑发展。转置/分形步长/去卷积的一个问题是棋盘:根据步长,卷积滤波器重叠的地方会出现棋盘图案的假象。谷歌大脑和蒙特利尔大学的一些研究人员写了一篇关于这个问题的很棒的论文。
Figure from Odena, et al., “Deconvolution and Checkerboard Artifacts”, Distill, 2016. http://doi.org/10.23915/distill.00003
简而言之:步长为 2 — stride=(2,2)
—意味着过滤器在扫描输入时以 2 个像素或单元为步长移动,size=3
意味着过滤器是一个3x3
正方形。看一下上图,问题就很明显了。纠正这个问题的一个方法是确保你的过滤器大小是你步幅的倍数。另一种方法是根本不使用去卷积。
相反,该论文建议首先进行上采样,这本质上与最大池操作相反:例如,每个像素都成为同一像素的2x2
网格。在常规卷积之后进行上采样不会产生棋盘效应。这看起来就像杰瑞米·霍华德在新版代码中所做的一样。酷毙了。
让我们再深入一点:原始代码使用了两个去卷积模块来放大低分辨率图像,从72x72
→ 144x144
→ 288x288
。较新的代码通过两个上采样模块来实现这一点,每个模块执行一个Upsampling2D()
操作,然后进行卷积和批量归一化。UpSampling2D()
的 Keras 文档显示:
keras.layers.convolutional.UpSampling2D(size=(2,2), data_format=None)
对我们来说重要的是size
参数:
size : int,或者 2 个整数的元组。行和列的上采样因子。
所以默认的行为是将图像的大小增加一倍,这就是为什么对UpSampling2D()
的两次空调用实现了预期的效果。
Just a reminder for what’s going on: the super-resolution network we’re building. inp is the original LoRes input tensor. outp is the HiRes output tensor. The Upsampling Network.
在放大之后,我们有一个最终的9x9
卷积层,以便回到 3 个颜色通道。讲座中的解释是,在图像输出从 64 个过滤器或通道减少到 3 个时,我们希望大量的上下文(因此是9x9
)能够做到这一点。因此,将前面的(288, 288, 64)
张量通过最后的卷积层输出一个(288, 288, 3)
张量:一个图像。最后一条outp = Lambda(lambda x: (x+1) * 127.5)(x)
线需要将每个像素从之前的 tanh 激活中恢复到正确的0,255
颜色强度等级。Tanh 在范围0±1
我觉得,所以→ ([-1:+1] + 1) * 127.5 = [0:255]
。Lambda(..)
是一个 Keras 包装器,它将内部的所有东西都视为自定义层。注意:感知损失论文的作者之一在 reddit 上提到,他们在没有 tanh 激活和没有最终 Lambda 处理层的情况下运行网络,并获得了同样好或更好的结果(无链接)。
现在可以训练网络,但是我们仍然需要定义我们的损失函数。Ie:网络自我评估的标准是什么?我们首先将我们的上采样网络连接到 VGG。VGG 将仅被用作内容损失的损失函数。在将上采样网络的输出张量输入 VGG 之前,需要对其进行预处理(VGG 模型中使用的归一化)。我们通过定义一个定制的 Keras 预处理层,并定义一个新的输出张量outp_λ
作为预处理层运行outp
的结果,来实现这一点:
vgg_λ = Lambda(preproc)
outp_λ = vgg_λ(outp)
# I just discovered code blocks in Medium :D (```)
接下来,我们创建一个 VGG16 网络,并将其所有层设置为不可训练。这…有点重要。因为这个网络是我们的损失函数——我们的测量棒——它必须是静态的。想象一下如果千克或米改变了。如果你想看现场混乱,只要看看外汇市场。
shp = arr_hr.shape[1:]vgg_inp = Input(shp)
vgg = VGG16(include_top=False, input_tensor=vgg_λ(vgg_inp))
for λ in vgg.layers: λ.trainable=False
VGG 网络的输入张量形状shp
是 HiRes 图像维度。于是:shp = arr_hr.shape[1:]
和vgg_inp = Input(shp)
。arr_hr
是从磁盘上的 bcolz 压缩数组创建的 NumPy 数组,其维数(形状)为:(num-elements,dim1,dim2,dim3,…)。在我们的例子中是:(图像数量,高度,宽度,颜色通道)。所以取arr_hr.shape[1:]
会返回一个形状张量:(288, 288 , 3)
。VGG16(..)
的include_top=False
将省略网络末端的全连接分类块。这是 VGG16 w/ Average-Pooling &批处理规范化的 fast.ai 实现,位于: vgg16_avg.py (如果课程目录结构发生变化,链接可能会断开)。
为了获得我们想要的 VGG 网络的部分内容损失,有几个实现。最初的课堂讲授通过选择提取特征的单个块(特别是块 2 中的 conv 第 2 层)来创建单个模型。在课程存储库中,这已经发展成为从多个块中检索特征的功能。
讲座的实施:
vgg_content = Model(vgg_inp, vgg.get_layer('block2_conv2').output)
vgg1 = vgg_content(vgg_inp)
vgg2 = vgg_content(outp_λ)
更新的课程 repo 在 neural-sr.ipynb 中的实现:
note how similar the 1 & l look. Wait, in this font which is an I and which is an l? → Making my case for the λ. =) vgg_content here is a Multi-Output model (covered in Deep Learning I)
在这两种情况下,我们都使用模型中相对较早的激活。在 L8 中,我们发现我们完全可以使用早期层激活来重建图像。然后我们使用 Keras 的功能 API 创建 VGG 输出的两个版本。这个 Keras API 的一个伟大之处在于,任何层(模型被视为层)都可以被视为一个函数。然后,我们可以将任何我们喜欢的张量传递到这个“函数”中,Keras 将创建一个新的模型,将这两个部分连接在一起。因此vgg2
是outp
,底部是上采样网络,顶部是vgg_content
,VGG16 中我们希望用作损失函数的部分。
旁白:你可能会有点困惑。我不应该说outp_λ
而不是outp
吗?在讲座的代码中,它是outp_λ
:这是经过预处理λ层后的输出张量。然而,在更新的课程代码中,该步骤包含在 VGG16 模型的初始化调用中。新的号召是:
vgg = VGG16(include_top=False, input_tensor=Lambda(preproc)(vgg_inp))
因此,现在我们有两个版本的 VGG 图层输出。vgg1
基于雇佣输入,而vgg2
基于升级网络的输出(接受了知识输入)。我们将比较招聘目标图像和招聘汇总结果,因此两个张量都具有高分辨率形状(288,288,3)。需要明确的是:vgg1
是雇佣内容/感知激活,vgg2
是知识增采样内容/感知激活。
注意:对于损失函数和最终模型的定义,原始讲座和更新的存储库代码之间存在显著差异。我将先浏览一下讲座版本,然后浏览一下新内容。
接下来我们计算它们之间的均方误差。在 Keras 中,任何时候你想把某个东西放到一个网络中,你都需要把它变成一个层,而这是通过把它扔进一个Lambda(..)
来完成的:
loss = Lambda(lambda x: K.sqrt(K.mean((x[0]-x[1])**2, (1,2))))([vgg1, vgg2])
最终模型将采用 LoRes 输入和 HiRes 输入作为其两个输入,并返回刚刚定义为其输出的损失函数:
m_final = Model([inp, vgg_inp], loss)
此外,当您试图在 Keras 中适应事物时,它会假设您试图获取一些输出并使其接近目标。这里的损失是我们想要的实际损失函数;没有目标,我们只是希望它越小越好。由于我们的损失函数使用的是 MSE ,我们可以说我们的目标是零。然而,Keras 中的目标是标签,所以每行(每个输入)都必须有一个标签,所以我们需要一个零数组:
targ = np.zeros((arr_hr.shape[0], 128))
为什么每个图像有 128 个零?讲座回答:Lambda 层,loss
,对应目标数组有 128 个滤镜。128,因为该层包含了vgg1
和vgg2
,两者都有 64 个过滤器。
接下来,我们使用 Adam 优化器和 MSE 损失编译模型,并对其进行拟合:
m_final.compile('adam', 'mse')
m_final.fit([arr_lr, arr_hr], targ, 8, 2, **pars)
注意: pars
包含一对这样定义的参数变量:pars = {'verbose': 0, 'callbacks': [TQDMNotebookCallback(leave_inner=True)]}
—这关闭了冗长性,并使用 TQDM 进行状态报告。
在第一轮训练后,学习率有所降低(称为“学习率退火”):
K.set_value(m_final.optimizer.lr, 1e-4)
m_final.fit([arr_lr, arr_hr], targ, 16, 2, **pars)
训练之后,我们对模型中的上行采样网络感兴趣。一旦我们完成训练&试图最小化损失函数,我们不再关心损失:我们关心的是来自上采样网络的输出图像。所以现在我们定义了一个模型,它接受知识输入inp
并返回雇佣输出outp
:
top_model = Model(inp, outp)
当我第一次为它做任务时,这让我有点困惑:outp
在我们上面的训练步骤中已经被训练过了。事实上,如果你记得:inp
和outp
只是我们的上采样网络的输入层和输出激活。我们基本上建立了一台机器来对图像进行上采样,使用现有的模块(VGG16)来训练这台机器,方法是将它放在上面,然后在完成后断开该模块,现在我们有了一台经过训练的机器来对图像进行上采样。
现在,我做这件事的方式与课程库中的方式有些不同。定义vgg1
和vgg2
后,训练前的部分如下:
def mean_sqr_b(diff):
dims = list(range(1, K.ndim(diff)))
return K.expand_dims(K.sqrt(K.mean(diff**2, dims)), 0)w = [0.1, 0.8, 0.1]def content_fn(x):
res = 0; n=len(w)
for i in range(n): res += mean_sqr_b(x[i]-x[i+n]) * w[i]
return resm_sr = Model([inp, vgg_inp], Lambda(content_fn)(vgg1+vgg2)
m_sr.compile('adam', 'mae')
还记得在 VGG16 中,新代码是如何使用多输出模型在不同的块上进行激活的吗?我们将对每个块对损失函数的相对影响进行加权:w = [0.1, 0.8, 0.1]
表示block1_conv2
的权重为 10%,block_2_conv2
的权重为 80%,&等等。
我们的损失函数本身就是函数中的函数。content_fn(x)
取张量x
,输出标量损失值res
。对于w
中的每个权重,content_fn(.)
根据x
的第 I 个元素和x
的第 I+n 个元素之差调用mean_sqr_b(.)
(其中 n =在w
中权重的数量),将结果乘以w
中的第 I 个权重,并将该值加到res
。
如果你认为进入content_fn(.)
的x
是我们的雇佣张量和我们的 LoRes 上采样张量的连接,如果这两个张量都是多输出模型(3 个不同的 conv 块激活)的结果,那么content_fn(.)
所做的只是两个张量的相应加权块激活的 MSE 。
如果这仍然有点难以理解,试试这个:
yes I see it too.
我要在这里暂停一会儿,希望我没有让它变得更糟。
Terek
没错。这就是损失函数。
最终的模型,这次称为m_sr
的超分辨率模型,将一组张量作为输入:LoRes 和 HiRes originals,并输出应用于vgg1
+ vgg2
的损失函数content_fn
的结果。
m_sr = Model([inp, vgg_inp], Lambda(content_fn)(vgg1+vgg2)
想象这是一个温和的噩梦:想象多重计算图形的不同之处仅在于它们将 VGG 的哪个块作为输出,它们的输出是如何被编织到损失函数中的;这还没有考虑每个上采样网络内部发生了什么,或者反向传播实际上是如何更新网络的。这可以被抽象成几行代码,这很酷。我想过画一个巨大的图表…过了某个点,它是光明会遇到矩阵,你在比赛找出情节。
尽管使用了平均绝对误差而不是 MSE : m_sr.compile('adam', 'mae')
,但编译还是很简单的。另一个区别是训练。加载大约 40k 的图像刚好刚好适合我工作站的内存,有时。如果你想要更多呢?这就是 bcolz 库的用武之地。你把数据保存在磁盘上,然后分批加载。代码是这样的:
bs
是批量大小。它必须是压缩时定义的 bcolz carray 的块长度的倍数。bcolz 数组有一个问题,它的块长度是 64,而我的工作站只能处理 6 的批量大小;8 如果行星排成一行。我通过创建新数组并显式设置参数chunklen
解决了这个问题。这可能是或可能不是犹太人。
niter
是迭代次数。targ
和之前一样是目标向量,但是这次是一个 0 的数组,一个 0 代表批处理中的一个元素。bc
是一个迭代器,它在每次调用next(bc)
时返回下一批arr_hr
和arr_lr
。我真的很喜欢这个,因为我在一个深度学习任务中遇到了系统内存限制的问题,我拼凑了一堆类似的函数来批量从磁盘中提取数据,并正确处理最后的剩余部分。代码更先进一些,把它拆开看看它是如何工作的会很有趣。它使用了线程和with
语句,这些我还没有用过。
对于niter
迭代,train(..)
加载下一批雇佣和知识图像,然后调用m_sr.train_on_batch([lr[:bs], hr[:bs]], targ)
。为什么当lr
是长度bs
时,确切地说是lr[:bs]
而不仅仅是lr
呢,反正我不确定——也许不是?在最后一批中,我遇到了输入和目标数组长度不匹配的问题。如果您有 16,007 个图像,批处理大小为 8,那么您的目标数组大小被设置为批处理大小→您会得到一个减一的错误。我通过将目标指定为targ[:len(hr)]
来解决这个问题,这样最终的输入和目标数组长度相同。至于niter
,我将其设置为:niter = len(arr_hr)//6 + 1
以说明余数,尽管回想起来,只有在余数存在时才添加1
会更好。
毕竟,结束是容易的。训练几个纪元,降低学习速度,然后再训练几个纪元。然后获得您训练有素的工作模型:
top_model = Model(inp, outp)
并开始向上采样。我得到了这个(注:这里的数据一次全部加载到内存中,模型通过model.fit(..)
进行训练):
it enhanced the mashed potatoes
虽然正如课程笔记本暗示的那样,这种良好的表现可能部分是由于过度拟合。以下是木星照片的结果:
LoRes — SuperRes — HiRes
LoRes — SuperRes — HiRes (used batch-loading method)
这并不奇怪。首先,我肯定忘记了至少一个实现中的学习率退火部分——我更感兴趣的是让它工作起来:大量的资源耗尽错误和 bcolz 迭代器的故障排除——而我正在处理的数据集只有 19,439 幅图像。也许这已经足够了,但是如果In: len(arr_hr)//16; Out: 62277
有任何线索的话,课程中的模型至少训练了 996,432 张图像,尽管那可能是在讲座被录制之后。不管是哪种情况,你都应该在 ImageNet 上进行训练,而不是一个小的子集,如果你有发言权的话。理想情况下,你也应该正确地进行训练。顺便说一下,我的两次成功尝试总共花费了大约 12 个小时的计算时间。所以 20k 就可以了。
关于木星和过度拟合的一个注意事项:在所有图片中,似乎确实存在对比度增加和褪色的问题,但据我所知,ImageNet 中也没有行星类别。所以那里可能发生了什么。
3。快速风格转移。我们可以使用来自超分辨率的相同基本思想,利用感知(内容)损失进行快速风格转换。这次我们拍摄一张照片,通过 CNN,然后通过一个损失函数对一张固定风格的图片进行风格和内容损失。关于这个话题有一篇论文和补充材料。
论文在输入上使用反射填充而不是零填充——也就是说:反射边界周围的图像而不是只有黑色像素。杰瑞米·霍华德用一个定制层实现了这个,在 Keras 中这个定制层是作为一个 Python 类来实现的。
第一部分是构造函数。此后,在定义自定义 Keras 层时需要做两件事:您需要定义get_output_shape_for(self, input)
,它接受输入张量的形状,并返回输出张量的形状——在这种情况下,它与s
( s[0]
)具有相同的批处理大小,相同的通道数(s[3]
),以及两倍的行和列填充量(s[1] + 2 * self.padding[0], s[2] + 2 * self.padding[1],
)。当你把东西放在一起时,Keras“神奇地”知道中间层的输入/输出有多大,因为每一层都包含这种信息。第二个要定义的是call(self, x, mask=None)
。call(..)
获取你的层数据x
,并返回你的层所做的一切。 Keras 的文件规定:
这是层的逻辑所在。
我们希望这一层添加反射填充。TensorFlow 有一个名为tf.pad(..)
的内置函数。
该图层现在可用于网络定义:
inp = Input((288, 288, 3))
ref_model = Model(inp, ReflectionPadding2D((40, 2))(inp)
ref_model.compile('adam', 'mse')p = ref_model.predict(arr_hr[10:11]) # run model on 10th img
论文作者使用40x40
像素对图像进行反射填充。因为它们在它们的 ResNet 块中使用“有效”卷积,所以图像通过层被逐渐裁剪,所以反射填充的存在是为了保留图像。
From: Perceptual Loss Supplementary Material
其实作者的架构和我们的很像。一般模式是:通过卷积对输入进行下采样,并增加通道和感受野的数量,从而创建更复杂的数据表示(第 3-5 行),对这些表示进行计算(剩余层),然后对其进行上采样(最后 3 行)。1/2 步是去卷积:它与分数步卷积相同。
没有进入太多的细节,实现这一点(主要遵循更新的课程笔记本)我采取了这种风格的形象:
artist: Alena Aenami
并把它应用到这幅 Waynakh 中世纪塔的图片上:
image: Ahmed Osmiev
两幅图像都被调整到500x500
。回头看看代码,我看到了一些愚蠢的错误:样式图像被裁剪为288x288
以适应样式张量…因此丢弃了 33%的样式图像。在将塔的内容图片调整到333x333
…那不适合,所以我只是裁剪它以适合输入张量。尽管如此,在用学习速率退火(2p @ default→2p @ 0.0001)在 4 个时期中训练快速风格转移模型大约 6 小时之后,该模型在大约 1 秒或更短时间内完成了其风格转移,并产生了以下结果:
resized in Apple Pages to (kind of) match original proportions
有点像角色扮演游戏的卡片。闹鬼的城堡什么的。显然,如果我使用原始内容和风格图像的全分辨率会好得多,但我还没有研究它。由于这种模型首先进行训练,而不是像以前的风格转移模型那样在运行时进行训练……感觉要让它在计算资源有限的情况下处理大型图像会很困难。你可以尝试简单的极端情况,重新压缩 bcolz 数组,使其块长度为 1,这样你就可以使用批量大小为 1 的数组,以低得多的学习速率开始,只需接受更长的训练时间,然后就可以了……但是这种解决方案感觉太简单了。在给定固定资源的情况下,应该有一种方法可以缩放到任何图像大小,并且只在计算时间上付出代价。嗯…
你可以试着把图像分成一个网格马赛克,在每一块上运行,然后把它们拼接起来。但现在你要付出一个定性的代价:如果这是一张雇佣照片,那么有一些重要信息你的社交网络不会知道,因为它实际上会被放大到只见树木不见森林。
等等,有没有一种方法可以使用288x288x3
张量作为视野,并扫描更大的图像,将视野中的内容加载到内存中,并将其余内容保存在磁盘上,也许可以使用 bcolz?嗯…
4。 设计:深度视觉语义嵌入模型。第九课的最后一部分,也是这篇博文的开始。Andrea Frome 在一篇论文中描述了这一点。),DeVISE 试图通过用单词嵌入取代一键编码来更接近我们在图像识别方面所做的事情。
作为一个(非常)粗略的概述:在你传统的一键编码模型中,鲨鱼和鱼之间几乎没有相似之处,或者“鲨鱼”的概念是所有类型鲨鱼的超集。当然,这不是我们在现实生活中感知事物的方式。在一个不同的领域,自然语言处理,有一种方法可以捕捉到类别之间的相互关系,叫做单词嵌入。它基本上是一个矩阵,每行(每列??)由映射一个单词与所有其他单词的相关性的向量组成。我们在深度学习 I 中使用它来创建一种类似尼采的机器人,也用于电影推荐(嵌入可以将电影映射到类别,而不仅仅是单词到单词)。
因此,对于图像,pug 的向量不是 1000 个元素,pug 类别的索引是 1,其他地方都是 0,而是用 pug 的密集单词向量来替换它(向量长度取决于我们使用的嵌入)。我们将使用一个 Softmax 层来进行一键编码(答案是1
其他都是0
),但是现在我们将使用线性层。
棘手的是要通过 ImageNet。150 万张左右的图片已经很多了。这就是 bcolz 和数组迭代器(在前面使用过)的用武之地。
这里有一个来自杰瑞米·霍华德的提示:他定义了两条数据路径——一条用于高速固态硬盘/非易失性存储器上的数据,另一条用于大型硬盘。他使用 RAID 1 SSD 来快速访问调整大小的图像和功能阵列,以及用于批量数据的 HDD 路径。好主意。
使用的单词嵌入是 word2vec。
words, vectors = zip(*wordvec_iterator)
将所有的单词放入words
,所有对应的向量放入vectors
。
所以在这个讲座的例子中,如果wordvec_iterator
包含"fox:", array01, "wolf", array02, ...
,那么当你压缩wordvec_iterator
时,这与把这些内容放入zip(.)
是一样的,就像这样:
zip("fox", array01, "wolf", array02)
那么测试一下这个:
>>> words = ["fox:","wolf:"]; vecs = [[1,2,3],[4,5,6]];
>>> zipped = zip(words, vecs)
>>> list(zipped)Out: [('fox:', [1,2,3]), ('wolf', [4,5,6])]>>> w, v = zip(*zip(words, vecs)) # or: zip(*zipped) ## for fresh `zipped`
>>> words == list(w) and vecs == list(v)Out: True>>> w, vOut: (('fox:', 'wolf:'), ([1,2,3], [4,5,6]))
或者说得迂腐一点:
>>> word, vecsOut: (['fox:', 'wolf:'], [[1, 2, 3], [4, 5, 6]])>>> list(w), list(v)Out: (['fox:', 'wolf:'], [[1, 2, 3], [4, 5, 6]])
所以我今天学到了一些新东西。基本经验:如果你想把一个元组列表转换成一个列表元组,使用 zip-star (Python)。
杰瑞米·霍华德做了更多设置笔记本的工作,将文字嵌入应用到 ImageNet 图片。我不会在这里详述,因为这篇文章遭受了它自己的任务爬行形式——而且我还没有为一个完全解压缩的 ImageNet 腾出 TB 左右的自由空间。Howard 对单词列表做了一些处理,对它们进行了重新排序,这样更常见的单词就会排在前面——并且还将所有单词都变成了小写,因为大写在这里并不重要。他通过使用np.corrcoef(..)
来查看他的名字的大写和小写版本与他的名字和不相关的对象之间的相关系数,从而进行了几次健全性检查。
然后,他创建了两个单词向量映射(Python 字典),分别映射到 1,000 个 Imagenet 类别和 WordNet 中的 82,000 个名词——目标是创建一个可以超越 ImageNet 的 1,000 个类别的系统。
最后,他创建了一个在 WordNet 中找不到的 ImageNet 类别列表,并将这些图像文件夹移出目录。
另一个有用的提示:Howard 保存所有花费大量时间的输出。获取一百万张图像的文件名需要一段时间,尤其是当它们在旋转的磁盘上时。
他还利用了我在计算/数值线性代数课上看到的三种技术:内存局部性、SIMD/向量化和并行处理。【讲座环节】。我觉得关于 SIMD 的那段很有趣。
到目前为止,对我来说,这是这门课最长的一课。有很多事情要做,但我喜欢从大规模架构的角度来看代码的想法。在黑暗的森林中很容易迷路,并且忘记你的模型的一部分来自哪里。人们也很容易害怕做出任何改变,因为害怕再也无法完全理解。但是如果你有一个连续的主题“我通过 CNN 输入图像,CNN 的输出通过一个损失函数与我想要它产生的相比较”,记住你实际上在做什么就变得容易多了。这就差不多结束了!
关于符号的几个注意事项:我将经常大写某些术语,如卷积或生成等。我发现,在阅读新的技术主题时,将一些关键术语强调得恰到好处,就像路径标记一样,会有所帮助,可以避免只是通读像散文这样的文本墙而迷失方向。
此外,每当代码中有一个单独的l
时,我会用λ
替换它。除了λ
漂亮之外,在许多字体中1 I l
看起来完全相同或者非常接近,足以让人迷惑;所以它有一个额外的用途——保持理智。
金融领域的深度学习
我写这篇文章是为了跟进新加坡再工作深度学习峰会上的同名讲座。在演讲中,我试图详细说明金融模型失败的原因,以及深度学习如何弥合这一差距。接下来,我继续介绍了金融领域深度学习的三个用例,以及这些模型优越性的证据。
虽然金融是计算最密集的领域,但金融中广泛使用的模型——监督和非监督模型、基于状态的模型、计量经济学模型甚至随机模型——都存在过度拟合、启发式和样本外结果差的问题。这是因为,金融领域非常复杂,并且是非线性的,有太多的因素相互影响。
为了解决这个问题,如果我们看看在图像识别、语音识别或情感分析等成熟领域的深度学习中所做的研究,我们会发现这些模型能够从大规模未标记数据中学习,形成非线性关系,形成递归结构,并且可以轻松调整以避免过度拟合。
如果这些模型能在金融领域得到应用,那么它们的应用将会非常广泛。这些模型可用于定价、投资组合构建、风险管理甚至高频交易等领域。因此,让我们来解决其中的一些问题。
回报预测
以预测每日黄金价格的样本问题为例,我们首先来看看传统的方法。
使用自回归综合移动平均模型,试图预测一个平稳的时间序列,保持季节性因素不变,我们得到一个结果
如果我们将相关的预测变量添加到我们的自回归模型,并转移到向量自回归模型,我们会得到以下结果—
深度回归
使用相同的输入,如果我对数据拟合一个简单的深度回归模型,我会得到好得多的结果,
修改我的架构以使用卷积神经网络来解决相同的问题,我的结果是
这些结果要好得多。但是接下来是最好的结果。
这就对了。使用这些变化的递归神经网络,我的结果是:
所以总的来说,均方差的趋势是一个启示!
投资组合构建
我们将尝试使用深度学习解决的第二个金融问题是投资组合的构建。深度学习在这个问题上的应用有一个漂亮的结构。我的研究受到了 T4 一篇名为《深度投资组合》的论文的启发。
这篇论文的作者试图做的是构建自动编码器来将一个时间序列映射到它自身。使用这些自动编码器的预测误差成为股票 beta(与市场的相关性)的代理,自动编码器是市场的模型!
基于上述自动编码器误差选择不同的股票集合,我们可以使用另一个深度神经网络来构建深度指数,并且结果相当好。
这里的深度神经网络已经成为一种使用股票复制指数的指数构建方法。
但这只是开始!如果我们应用智能指数,我从指数中删除极端下降的时期,并在智能指数上训练我的指数映射深度神经网络,我就能够以激烈的方式超越指数!
这项技术在投资组合构建领域有着巨大的潜力!
结论
金融行业的当前趋势正在引领更复杂、更合理的模型进入市场。对于所有银行来说,技术是一个巨大的压力领域,有大量数据科学家进入该领域。像 RelTec 和 Worldquant 这样的对冲基金已经在交易中使用这种技术。这些复杂的模型在其他领域表现出了卓越的结果,而金融建模领域存在巨大的差距,这就产生了一系列引人注目的创新!
更好地解决我们在金融和贸易领域的关键问题将提高效率,增加透明度,加强风险管理和创新。
PS:以上所有分析使用的代码可以在我的 github repo 上找到
我正在计划我的下一篇关于投资组合管理的文章,请继续关注!
欢迎任何好的建议。
请访问我的网站http://www . Wright research . in/了解更多我管理的投资策略!
[## 返工
RE*WORK 活动将企业家精神、技术和科学结合起来,利用……
videos.re-work.co](http://videos.re-work.co/videos/410-how-machine-learning-is-transforming-finance)
实践中的深度学习
当你的结果看起来太好或太差时该怎么办
从业者知道深度学习方法非常强大和灵活,但在真实世界的数据集上“在野外”应用它们,与在 CIFAR-10/100 或 ImageNet 等知名数据集上重新运行最新的 SOTA(最先进的)模型是非常不同的。数据缺失、数值错误、打字错误、标签错误等。,使事情变得更加复杂,因此有时我们不确定是否可以相信我们的结果。让我们来看看一些实用的技巧,当你得到的结果看起来*“好得不像真的”或“坏得没用”*时,该检查些什么。
好得令人难以置信的结果
结果会“好得难以置信”吗?例如,你可能正在使用迁移学习:你没有时间从头开始构建和训练一个复杂的架构,所以你得到一个预训练的模型(比方说,在 ImageNet 上训练的 ResNet101)并将其输入你的数据集。您希望在不花费长时间学习的情况下获得良好的准确性,但是您并不期望获得优异的结果,除非您的数据集与最初训练模型的数据集极其相似。
或者,在训练一个复杂且耗时的架构之前,您可能想先尝试一个简单的模型。更简单的神经网络将作为基线,以测量使用 bigger/badder 模型获得的优势。你不会期望一个简单的模型得到 SOTA 结果。
最后,您可能正在处理一个简单的模型,因为它的用例(例如,一个移动应用程序,或一个内部部署的应用程序)阻止您走得太远,尤其是如果您计划执行在线培训的话。
那么,如果你第一次测试就获得了 99.3%的准确率,你会怎么想?你不应该马上断定这个问题很简单,你不需要一个很深的关系网来解决它。相反,这里有一些实用的提示,可以帮助你评估你是否幸运,问题是否简单,或者你犯了一些明显的错误。其中一些技巧只对分类器有意义,而另一些则可以应用于各种深度学习模型。
在下文中,我们将假设您已经遵循了最佳实践以避免过度拟合,即,您使用了 k 折叠交叉验证(CV)或训练/验证/测试集分割来估计您的模型的泛化误差,并且您发现了一个可疑的低值。
检查数据泄漏
首先,检查所有数据转换(或估计量,在 Tensorflow 行话中)是否适合训练集,并应用于测试集, k 的每个折叠的*——折叠 CV。例如,如果放弃“无用”的特征是你的模型的一部分,你不能在完整的训练集中选择“有用”的特征,然后每次折叠都使用相同的特征。相反,您必须为每个折叠重复特征选择操作,这意味着在每个折叠中您可能使用不同的特征来进行预测。如果使用训练/验证/测试集分割而不是kfold CV,等效的方法是仅使用验证集来选择有用的特征,而不需要查看测试集。
如果您使用 Python 编码,确保对每个折叠重复相同的精确操作的一个简单方法是使用“Pipeline”类(在“scikit-learn”中)或“Estimator”类(在 Tensorflow 中),并确保对数据的所有操作都在 pipeline/estimator 内部执行。*
您使用的度量标准正确吗?
如果构建分类器,请验证您使用了正确的分类度量。例如,如果群体中的各种类别达到合理的平衡,准确性作为分类度量只有才有意义。但是在一个医学数据集上,人群中疾病的发病率是 0.1%,你可以在一个代表性的数据集上获得 99.9%的准确性,只需将每个点分类到多数类。在这种情况下,99.9%的准确性没有什么好惊讶的,因为准确性不是这里使用的正确度量。
问题真的简单吗?
同样,在分类的情况下,检查问题是否过于简单。例如,您可以拥有完全可分离的数据。换句话说,在输入空间中存在一个流形(或多个流形的交集),它完美地分离了各种类别(无噪声)。在两类线性可分问题的情况下,输入空间中有一个超平面完美地将两类分开。这很容易诊断,因为超平面的所有低维投影都是超平面。因此,例如在所有特征对的 2D 散点图中,两个类别可以由一条线完美地分开:
当然,由于深度学习经常应用于具有数千或数万数量级的 K (特征的数量)(例如,图像像素)的问题,因此甚至可能无法可视化所有 (K+1)K/2 散点图的一小部分。这不是一个问题,因为线性可分数据将被更简单的机器学习工具完美地(或接近完美地)分类,例如线性判别分析、线性支持向量机(SVM)或正则化逻辑回归(非正则化逻辑回归拟合 MLE 对于线性可分问题是不稳定的)。因此,如果可视化是不可能的,拟合这些模型将给出相同的信息,尽管以一种不太直接的方式。
非线性完全可分离的数据在没有可视化的情况下更难检测:
然而,机器学习工具,如内核支持向量机(或更好的,无标签 VAE),或先进的可视化方法,如 t-SNE,可能有助于识别这种情况。
绘制决策区域,例如使用“scikit-learn”的“mlxtend”助手包中的“plot_decision_regions”函数,是快速识别非线性完全可分数据的另一种方法。然而,在你有大量特征的深度学习问题中,这样的可视化可能是不可能或不切实际的。
在这两种情况下(线性和非线性可分离数据),关键是类之间有一个“硬”分离边界(即没有噪声),因此有可能获得完美的分类。可以说,很少有现实世界的问题属于这些类别:在大多数情况下,对于从群体中提取的所有训练集,没有一个“硬”边界可以完美地将这两个类别分开。尽管如此,做这个检查还是值得的。
在随机标签上训练
一个经常具有启发性的测试是在混洗(置换)标签上重新安装 DNN。在这种情况下,特征和类别标签之间没有关系,因此神经网络只有一种方法来获得良好的训练集误差:记住整个训练集。这通常会表现在更长的训练时间。此外,它没有办法获得良好的测试集误差。如果您在测试集上仍然获得了出色的性能,那么要么是您的代码有严重的问题(考虑增加您的单元测试的覆盖率,以找到问题所在),要么是您使用的框架有问题。在后一种情况下,您应该考虑在此时打开一个 GitHub 问题。
在小数据集上训练
走向极端的反面:在单个(或非常少的)数据点上训练。在这种情况下,你应该很快在训练集上获得 100%的准确率(极短的训练时间),当然在测试集上获得极低的准确率。同样,如果您不这样做,这表明您的代码或您正在使用的框架中存在一些严重的问题。
上次检查:获取新数据
最后,您可以尝试获得一些新的测试点,代表 DNN 的真实用例,这是您之前从未见过的(更不用说在培训中使用了)。如果你仍然得到优秀的准确性,那么恭喜你,你的模型太棒了!
“坏得没用”的结果
“人们担心计算机会变得太聪明并接管世界,但真正的问题是它们太笨了,它们已经接管了世界。”
― 佩德罗·多明戈斯
我们已经看到了当我们在第一次尝试中获得优秀的结果时应该做什么,特别是如何验证我们没有被愚蠢的错误愚弄,例如将测试集泄露给训练集。在这一部分中,我们将看到如何处理神经网络预测不够准确这一更常见的问题。注意:已经有很多次的经验表明,足够深度的神经网络可以记住巨大数据集上的随机标签(例如参见理解深度学习需要重新思考泛化)。因此,原则上,有了足够大的 NN,我们应该总是能够将训练误差减少到极小的值,也就是说,减少过度适应训练集,不管学习任务是多么的无意义。对于泛化错误,情况完全不同。一般来说,不能保证对于每个学习问题,都存在一个可学习的神经网络模型,它可以产生尽可能低的泛化误差。然而,有一些技巧可以帮助你设定现实的目标,并最大化你达到目标的机会。
1.确认你的目标是现实的
在一个问题(数据集+学习任务)上找到一个能达到我们需要的精确度的有信誉的参考,这个问题与我们正在研究的问题足够相似,这将是非常好的。这并不总是可能的,但是保持各种任务的最新技术状态,例如物体检测或命名实体识别,有助于正确设置我们的期望。主题专业知识也可以指导我们选择现实的精度目标。
2.确保你的训练程序中没有错误
当然,如果我们的神经网络训练不正确,我们就不能指望它能很好地推广新数据。以下检查有助于我们验证培训流程:
- 编写**单元测试,**可能使用 Chase Robert 的机器学习库进行单元测试
- 数据集检查:查看训练集和测试集的一些随机输入/标签样本,并检查标签是否正确;检查输入图像的宽度和大小;打乱训练/测试集中的样本,看看它是否会影响结果;等等。
- 过度拟合测试 : 1)将训练集减少到几个样本(两到三个)。训练误差现在应该很快达到 0(NN 立即过拟合如此小的训练集),但是测试集应该增长很多(数据如此之少,NN 不能概括)。2)关闭所有正则化,验证 NN 能够过拟合全部训练集。这并不总是可能的,因为一些架构本质上是不稳定的,如果没有某种形式的调整,训练是不可能的。然而,当测试工作时,它表明 NN 相对于我们的训练集具有过剩的能力,因此,给定适当的正则化,它应该获得低测试误差,只要训练集是测试集的代表,并且特征足以预测标签(如果标签是随机的,再多的训练也不会使 NN 学习:参见下一个要点)。
- 随机化测试:随机洗牌训练标签。现在,训练误差应该减少(尽管慢得多),但是测试集误差不应该低于随机分类误差(即,如果我们将每个类别分配给多数类,则所犯的误差等于 1-f_m ,其中 f_m 是多数类的频率)。
- 标准化您的预处理和包版本。使用 Docker 容器来构建您的模型是确保您的模型无论在哪里部署都以相同的方式运行的最佳方式,而不必担心库安装、环境配置、破坏旧功能的库更新等等。
- 保存详细的数值实验日志
3.尽可能以超收敛为目标
在某些情况下,大学习率与 Leslie N. Smith 的循环学习率方法的结合起到了正则化的作用,使收敛速度加快了一个数量级,并减少了大量正则化的需要。参见超收敛:使用大学习率快速训练神经网络。
4.针对你的问题使用正确的规范化形式
正则化倾向于增加训练时间和训练误差,但同时倾向于减少测试误差。然而,过于一般化实际上会增加这两种错误(欠拟合)。出于这个原因,如果您成功地在没有正则化(过度拟合测试)的情况下使训练集过度拟合,那么一次引入一种正则化技术通常会更好。原因是正则化本身并不一定意味着你的泛化误差会变小:模型必须有足够大的容量来实现良好的泛化特性。一个深度足以过拟合训练集的神经网络,在没有正则化的情况下,一旦正则化开始起作用,应该能够实现低测试误差。
最著名的调整方法是早期停止和体重下降。其他常用工具有:
- 小批量培训:较小的批量通常与较小的概括误差相关,所以这是一种尝试。然而,请注意,一些研究人员对迷你电池的有效性提出了质疑。迷你批处理与批处理规范化不兼容(见下文),所以在使用这两种方法时要格外小心。
- 尝试使用 SGD 来代替 Adam 等自适应优化器:论文通过从 Adam 切换到 SGD 来提高泛化性能表明,对于某些任务,SGD 优化器虽然速度较慢,但能够找到对应于较低测试集误差的最小值。
- 使用下降:如果使用 LSTMs,只对 LSTM 层的输入和输出单元使用标准下降。对于循环单元(门),使用循环辍学,这是 Yarin Gal 在他的博士论文中首次提出的。如果您使用 CNN,当应用于具有更多单元的层(即全连接层)时,dropout 会更有效,除非您使用的是 FCN(全卷积网络),它没有全连接层。然而,对于 CNN 辍学生来说,最近已经失宠了。
- 批量标准化:最新的 CNN 架构避免了丢弃,支持批量标准化。这可能是由于明显的丢失和批量正常化不能很好地配合(通过方差转移理解丢失和批量正常化之间的不协调)。因为当你有大量数据集时,批处理规范比丢弃更有效,这可能是丢弃不再受 CNN 架构青睐的原因。如果使用批量归一化,请验证各图层的权重和偏差分布看起来近似标准正态。对于 RNNs 来说,实现批处理规范是复杂的:权重归一化(一种简单的重新参数化,以加速深度神经网络的训练)是一种可行的替代方案。
5.超参数/架构搜索
如果上述步骤没有足够减少测试误差,您将不得不测试多个不同的超参数设置(贝叶斯优化在这里可能有所帮助)或多个不同的架构变化(例如使用高效神经架构搜索)。确保在有序的日志中记录这些漫长而复杂的实验结果。
6.魔术袋
最后,AWS 最近的一篇论文包含了一个有用的提高测试准确性的技巧包。这篇论文只限于一个任务(图像分类)和一个架构(CNN),尽管它是目前该任务的最佳架构。总之,这篇论文很有趣,充满了有用的见解。
7.摘要
即使最近在深度学习方面取得了所有的进展,建立和训练一个泛化能力很好的神经网络模型仍然是一门艺术,也是一门科学。然而,应用这篇文章中描述的技巧,重用成功的架构并进行仔细的数值实验,将允许您提高模型的泛化能力。
结论
我们描述了一些关于如何验证深度学习模型结果的可靠性的有用提示,以及当它们不令人满意时如何改进它们。如果你知道其他的建议,欢迎在评论中提出来!
浏览器中的深度学习:简明指南
使用网络摄像头和 Tensorflow.js 实时检测物体。
Tensorflow.js 是一个新的深度学习库,可以在你的浏览器中运行。作为一名机器学习和 Javascript 爱好者,我在 Tensorflow.js 发布后立即开始使用它进行对象检测库的工作。
在这里,我将走过我是如何开始的,并分解 tfjs-yolo-tiny 的不同点。你可以点击这里查看现场演示。
我们将涉及提取原始的微型 YOLO 暗网模型,将其转换为 Keras,将其转换为 Tensorflow.js,进行一些预测,在 Tensorflow.js 中编写时捕获数据,以及轻松使用网络摄像头/图像进行预测。
更好、更快、更强
是的那是认真的原论文题目。我们将使用微型 YOLO ,一种可以以 200 FPS 运行的快速对象检测模型。我们将使用小 YOLO 而不是完整的 YOLOv2。为什么?首先,YOLOv2 在一个强大的桌面上“只能”以 40 fps 的速度运行,大多数用户都无法访问。该模型文件也比微型 YOLO 大 5 倍左右,从网上下载要花很长时间。最后,YOLOv2 有一个 reorg 层,它还不支持作为原生 Tensorflow.js 层。我们将在下一步中获取微小 YOLO 的网络配置(神经网络结构)和权重(幻数)。
YAD2K:又一个 Darknet 2 Keras(转换器)
你可能已经注意到 YOLO 是用暗网写的,暗网听起来不像张量流。所以我们的第一站是将我们的 YOLO 模型转换成更张量流的东西,在我们的例子中,就是 Keras !Keras 是一个更高级的深度学习框架。这是将您的权重转换为 Tensorflow.js 格式的推荐格式。
我们将使用 YAD2K 将暗网模型转换为 Keras。继续按照这里的说明安装 YAD2K,我等着。
好吧,你也可以假装是你做的,并使用我已经发布的最终重量文件,但这不会那么有趣!
现在,我们必须修复 YAD2K 中的一个错误,以正确加载微小的 YOLO。
在您最喜欢的文本编辑器中打开 yad2k.py ,在第 83 行,将buffer=weights_file.read(16)
改为buffer=weights_file.read(20)
。为什么?不知道。
现在在您的终端中运行以下命令。它将下载微小的 YOLO 重量和配置,以及输出转换后的模型文件到model_data/yolov2-tiny.h5
wget [https://pjreddie.com/media/files/yolov2-tiny.weights](https://pjreddie.com/media/files/yolov2-tiny.weights)
wget [https://raw.githubusercontent.com/pjreddie/darknet/master/cfg/yolov2-tiny.cfg](https://raw.githubusercontent.com/pjreddie/darknet/master/cfg/yolov2-tiny.cfg)./yad2k.py yolov2-tiny.cfg yolov2-tiny.weights model_data/yolov2-tiny.h5
接下来,我们要确保我们的新模型实际可行!有趣的事实:我忘记这样做了,我花了一整天的时间想知道 Tensorflow.js 为什么是 b0rk。
./test_yolo.py model_data/yolov2-tiny.h5
该模型应该输出一些预测。如果没有,欢迎在下面评论我!
Tensorflow.js 转换器:我们最后的重量转换
这一步更简单,我保证!看官方指南这里。同样,如果这看起来太多了,我已经完成了所有困难的工作,所以你可以直接跳过:)
我们需要安装官方的转换工具。在你的终端中运行pip install tensorflowjs
来安装转换器。
现在再次使用终端来转换我们的模型!
tensorflowjs_converter --input_format keras \
model_data/yolov2-tiny.h5 \
tfjs_model_data
现在我们终于在tfjs_model_data
有了我们所有的模型文件!注意,该文件夹包含一个model.json
以及一堆其他碎片文件。model.json
告诉 Tensorflow.js 神经网络的结构是什么,哪些碎片文件对应什么权重。碎片文件包含模型的权重。确保碎片文件位于model.json
的同一个目录中,否则您的模型将无法正确加载。
Tensorflow.js 时间
现在,有趣的部分。(每一部分都是好玩的部分。)ML 和 JS 代码同时!
我们将从导入一些 Tensorflow 并加载模型开始。
import * as tf from ‘@tensorflow/tfjs’;const model = await tf.loadModel(url);
等等,什么是“网址”?您可以在这里使用托管模型文件或者提供您转换的文件的路径。在这里了解更多!
太棒了,现在我们可以做一些真正的深度学习:
function yolo (input) {
return model.predict(input);
}
哼。这似乎很平常。哦等等。我们忘记了将输出转换成边界框、类标签和概率!
The numbers Mason, what do they mean?? Original Image
把数字变成盒子和数字
我不打算深入探讨这个问题,因为 YOLO 的后期处理可以是他们自己的几篇博文。相反,我将强调我在将 Python 版本转换为 Javascript 时所面临的挑战。
某些张量运算不可用
Tensorflow.js 还很年轻,因此有些东西还不可用,如布尔遮罩或 NMS 。您也可能遇到这个问题,但幸运的是,您可以通过使用
const expected_shape = tensor.shape;
const data = await tensor.data(); // Async transfer from GPU to CPU
// Note: data is a flattened TypedArray of the original tensor
//... data manipulation in JS on CPU
tf.tensor1d(data).reshape(expected_shape); // Shape it back into where we were before
注意:这样做可能会成为应用程序的瓶颈,但是有时候这是不可避免的。
不能像 Python 一样使用-1 索引
在 python 中,你可以使用-1 作为“最后一个元素”。不幸的是,在 Tensorflow.js 中,如果你在tf.slice
上尝试这样做,它会无声地失败。相反,你必须明确地指定尺寸。
不能用 5d 张量
当心 Tensorflow.js 的 WebGL 后端不支持 5d 张量。如果我连 5 维都想象不出来,为什么还要用它们?在 YOLO,我们将产出重塑为[batch_size, xy, wh, box_confidence, box_class_pred]
。这明明是 5d。幸运的是,为了避免这样的痛苦和折磨,我简单地删除了 batch_size 维度。一种替代方法是不整形为 5d 张量。需要警惕的事情。
除此之外,我的经历是流动的。我只需要在 CPU(传统 JS)中重新实现 Tensorflow 通常开箱即用的两个 算法。
NPM 装置
让我们把我们的深度学习放到一个应用程序中吧!
幸运的是,一个可怜的家伙已经写好了代码,所以只需在你的终端上运行一个 NPM 安装程序:
npm i tfjs-yolo-tiny
现在我们将挥舞一下我们的 Javascript 魔杖
import yolo, { downloadModel } from ‘tfjs-yolo-tiny’;const model = await downloadModel();
const inputImage = webcam.capture();const boxes = await yolo(inputImage, model);
哇哇,你说的这个webcam.capture()
是什么?
Original Traffic Image: https://pxhere.com/en/photo/423261
也许比 NPM 装置多一点…
你可能已经注意到,我们还没有触及我们的 YOLO 到底在喂什么。而这是 Tensorflow.js 最酷的部分之一。
我们可以从文档(DOM)中取出一个视频或图像,并将其转换为张量!
我们可以用 JavaScript 写这样的东西:
/* Pretend we had the following element in index.html. Always use alt tags for accessibility!
<img id=”image” src=”/test_input.jpg” alt=”YOLO Model Test Image”>
*/const image = document.getElementById(‘image’);
const input = tf.fromPixels(image);
嘭!输入现在有图像作为张量!要从图像切换到网络摄像头,你只需将它指向正确的元素。这对我来说是相当✨的魔法。
在这之后,我们必须做一些预处理。在这种情况下,将其裁剪为正方形,大小调整为 416x416,然后除以 255 以获得范围从 0 到 1 的像素值。为什么?因为老板是这么说的(我们就是这样训练 YOLO 的)。
最后的想法
我们已经演练了如何将模型转换为 Tensorflow.js 格式。我们可以加载一个模型并用它来预测。然后我们探索了在 Tensorflow.js 中编写后处理代码的一些痛点,但是我们占了上风。我们现在还知道如何通过静态图像或网络摄像头获取数据。现在我们可以将大多数 ML 模型从 Python 转换为 Tensorflow.js,并在您的浏览器中运行它们。
想看看所有的行动吗?查看现场演示。想在您的应用程序中轻松使用它吗?检查一下 NPM 包。查看 Github repo 的演示来看看所有这些代码的运行以及如何使用 NPM 包。
欢迎加入 ModelDepot 的讨论,或者在 Gitter Chat 上找到我们!或者甚至为您的项目浏览下一个机器学习模型!
特别感谢 HS、KZ、VP 和 JS 润色我的字母汤