Unicode、UTF-8 和 Python 中的字符串指南
让我们来看看弦乐的基本概念,这将使你的理解更上一层楼。
字符串是 Python 中最常见的数据类型之一。它们用于处理任何类型的文本数据。自然语言处理领域是建立在某种文本和字符串处理之上的。了解 Python 中字符串的工作方式很重要。当字符串由英语 ASCII 字符组成时,通常很容易处理,但是当我们输入非 ASCII 字符时,就会出现“问题”——这在当今世界越来越普遍。随着表情符号等的出现。
Let’s decipher what is hidden in the strings
许多程序员将encode
和decode
与字符串一起使用,希望消除令人恐惧的UnicodeDecodeError
——希望这篇博客能帮助你克服对处理字符串的恐惧。下面我会用一个 Q 和一个格式来真正得到你可能会有的问题的答案,在我开始学习字符串之前我也有。
1.绳子是由什么制成的?
在 Python (2 或 3)中,字符串既可以用字节表示,也可以用 unicode 码位表示。
字节是由 8 位构成的信息单位,字节用于存储硬盘中的所有文件。所以你计算机上所有的 CSV 和 JSON 文件都是由字节组成的。我们都同意我们需要字节,但那么 unicode 码位呢?我们将在下一个问题中讨论它们。
2.什么是 unicode 和 Unicode 码位?
当从文件中读取字节时,读者需要知道这些字节意味着什么。因此,如果你写一个 JSON 文件并发送给你的朋友,你的朋友需要知道如何处理你的 JSON 文件中的字节。对于最初 20 年左右的计算,大写和小写的英文字符,一些标点符号和数字就足够了。这些都被编码成一个名为 ASCII 的 127 符号列表。7 位信息或 1 字节足以对每个英文字符进行编码。你可以告诉你的朋友用 ASCII 编码解码你的 JSON 文件,瞧——她就能读懂你发给她的东西了。
这在最初的几十年里很酷,但是慢慢地我们意识到有更多的字符而不仅仅是英文字符。我们尝试将 127 个字符扩展到 256 个字符(通过 Latin-1 或ISO-8859–1)以充分利用 8 位空间——但这还不够。我们需要一个大家都同意的国际标准来处理成百上千的非英语字符。
Unicode 出现了!
Unicode 是国际标准,其中维护了单个字符和唯一数字的映射。截至 2019 年 5 月,Unicode 的最新版本是 12.1,包含超过 137k 个字符,包括英语、印地语、中文和日语等不同的脚本,以及表情符号。这 137k 个字符每个都由一个 unicode 码位表示。所以 unicode 码位指的是显示的实际字符。
这些码点被编码成字节,再从字节解码回码点。例如:字母表a
的 Unicode 码位是 U+0061,表情符号🖐是 U+1F590,ω是 U+03A9。
3 Unicode 定义的最流行的编码标准是 UTF-8、UTF-16 和 UTF-32。
3.什么是 Unicode 编码 UTF-8、UTF-16 和 UTF-32?
我们现在知道 Unicode 是一种国际标准,它将每个已知的字符编码成一个唯一的数字。那么下一个问题是,我们如何在互联网上移动这些唯一的号码?你已经知道答案了!使用字节的信息。
UTF-8: 使用 1、2、3 或 4 字节对每个码点进行编码。它向后兼容 ASCII。所有的英文字符只需要 1 个字节——效率相当高。如果我们发送非英语字符,我们只需要更多的字节。
这是最流行的编码形式,也是 Python 3 中默认的编码方式。在 Python 2 中,默认编码是 ASCII(不幸的是)。
UTF-16 是变量的 2 或 4 个字节。这种编码方式非常适合亚洲文字,因为大多数亚洲文字都可以用 2 个字节进行编码。这对英语不好,因为所有的英语字符在这里也需要 2 个字节。
UTF-32 是固定的 4 字节。所有的字符都用 4 个字节编码,所以需要很大的内存。它不经常使用。
【你可以在这篇 StackOverflow 帖子里读到更多。]
我们需要encode
方法将 unicode 码位转换成字节。例如,这通常发生在将字符串数据写入 CSV 或 JSON 文件的过程中。
我们需要decode
方法将字节转换成 unicode 码位。这通常发生在将数据从文件读入字符串的过程中。
Why are encode and decode methods needed?
4.Python 中有哪些数据类型处理 Unicode 码位和字节?
正如我们前面讨论的,在 Python 中,字符串可以用字节或 unicode 码位表示。
Python 中主要的外卖有:
1。Python 2 使用**str**
类型存储字节,使用**unicode**
类型存储 unicode 码位。默认情况下,所有字符串都是str
类型——字节~默认编码是 ASCII。因此,如果传入的文件是西里尔字符,Python 2 可能会失败,因为 ASCII 将无法处理这些西里尔字符。在这种情况下,我们需要记住在读取文件时使用decode("utf-8")
。这不方便。
2。Python 3 来了,解决了这个问题。默认情况下,字符串仍然是**str**
类型,但是它们现在意味着 unicode 码位——我们携带我们看到的东西。如果我们想在文件中存储这些str
类型的字符串,我们使用**bytes**
类型。默认编码是 UTF-8,而不是 ASCII。完美!
5.有没有比较不同数据类型的代码示例?
Yes, let’s look at “你好” which is Chinese for hello. It takes 6 bytes to store this string made of 2 unicode code points. Let’s take the example of popularlen
function to see how things might differ in Python 2 and 3 — and things you need to keep note of.
>>> print(len(“你好”)) # Python 2 - str is bytes
6>>> print(len(u“你好”)) # Python 2 - Add 'u' for unicode code points
2>>> print(len(“你好”)) # Python 3 - str is unicode code points
2
因此,在 Python 2 中添加前缀u
会对代码是否正常运行产生完全不同的影响——这可能会令人困惑!Python 3 通过默认使用 unicode 码位解决了这个问题——所以在上面的例子中,如果长度为 2,那么len
将会像您所期望的那样工作。
让我们看看 Python 3 中处理字符串的更多例子:
# strings is by default made of unicode code points
>>> print(len(“你好”))
2# Manually encode a string into bytes
>>> print(len(("你好").encode("utf-8")))
6# You don't need to pass an argument as default encoding is "utf-8"
>>> print(len(("你好").encode()))
6# Print actual unicode code points instead of characters [[Source](https://stackoverflow.com/questions/7291120/get-unicode-code-point-of-a-character-using-python)]
>>> print(("你好").encode("unicode_escape"))
b'\\u4f60\\u597d'# Print bytes encoded in UTF-8 for this string
>>> print(("你好").encode())
b'\xe4\xbd\xa0\xe5\xa5\xbd'
6.信息量很大啊!你能总结一下吗?
当然可以!让我们直观地看看我们到目前为止所学的内容。
在 Python 3 中,默认情况下,我们位于字符串 Unicode 码位世界的左侧。我们只需要在写入或读取数据时来回移动字节。此转换过程中的默认编码是 UTF-8,但也可以使用其他编码。我们需要知道在解码过程中使用了什么编码器,否则我们可能会得到错误或得到乱码!
Visual diagram of how encoding and decoding works for strings
这个图对 Python 2 和 Python 3 都适用!我们可能会得到UnicodeDecodeErrors
,因为:
1)我们试图使用 ASCII 编码非 ASCII 字符。这种情况会发生。在 Python 2 中,默认编码器是 ASCII。因此,您应该使用 UTF-8 显式编码和解码字节。我们可能完全用错了解码器。如果 unicode 码位是用 UTF-16 而不是 UTF-8 编码的,你可能会遇到在 UTF-8 土地上乱码的字节。所以 UTF-8 解码器可能完全无法理解这些字节。
一个好的做法是,一旦从文件中加载了字节,就用 UTF-8(或用于创建这些字节的编码器)对它们进行解码。通过 Python 代码对 unicode 码位进行处理,然后使用 UTF-8 编码器将字节写回到文件中。这叫做 Unicode 三明治。阅读/观看内德·巴奇尔德(@ 内德巴特)关于这个问题的精彩演讲。
如果你想在 Python 中添加更多关于字符串的信息,请在下面的评论中提及,因为这将有助于他人。我关于 Unicode、UTF-8 和字符串指南的博客到此结束。祝你在自己的文本探索中好运!
**PS,看看我的新播客!**它叫做“数据生活播客”,我在这里谈论类似的话题。在最近的一集里,我谈到了为什么熊猫是新的 Excel。你可以在这里或任何你听播客的地方听播客。
My podcast: The Data Life Podcast
如果您有任何问题,请在我的 LinkedIn 个人资料中给我留言。感谢阅读!
从高中的角度介绍深度学习
Image Courtesy of Xkcd ( https://xkcd.com/1838/)
他的一系列博客文章致力于为寻求学习深度学习的高中生提供直接而简单的深度学习解释。
主要的 DL 概念将在本系列中以一种互动的、实际操作的方式进行解释,引导读者完成构建一个简单的 DL 模型并对其进行训练和评估的过程。
我在互联网上获取数字图书馆资料的经验是,它仍然主要面向那些寻求转向数字图书馆的人,或者关注那些寻求从事数字图书馆的大学生。当我开始学习 DL 的时候,大部分信息都需要对数学和微积分概念有一个很好的、直观的理解。虽然获得这些知识是我从学习 DL 的旅程中获得的许多好处之一,但该过程的最初步骤导致对梯度下降和激活函数的目的等概念的理解非常肤浅。总的来说,我缺乏对概念的数学直觉,这导致了混乱和误解。这种数学直觉在网上的大部分资料中通常被忽略,因为类似领域的大学生和大学毕业生都有广泛的数学背景。
本系列旨在以一种典型的对数学和数字逻辑感兴趣的高中生能够理解的方式提供数字逻辑概念的直观联系。
本系列将遵循构建、训练和评估亚马逊评论情感分析模型的过程。情感分析是根据语句含义中的情感对语句进行分类。例如,有人说“天气晴朗”背后的一般情绪是积极的,而如果有人说“天气多云,正在下雨”,他们可能感到消极。这是情感分析的基础,这个概念将被应用于对 polar IMDB 电影评论进行正面或负面分类。
这第一篇文章将使读者了解深度学习的最新基础知识,并将教给读者完全理解该主题所需的核心概念。
背景
M 机器学习(ML)是一种算法,利用数据来学习模式,得出有意义的结果,并从多个应用中进行预测。深度学习(DL)和神经网络是更有效地实现 ML 目标的专门技术。
在过去的几年中,ML 领域,尤其是 DL 领域发展迅速。多年来,传统的企业数据量已经从大约 10,000–100,000 增长到 1,000,000–1,000,000,000。
这引发了一个研究人员从未遇到过的独特问题;计算能力对训练模型的限制。为了创建更深层次的神经网络,他们需要一种当时无法提供的计算能力。这就是 ML 领域停滞多年的原因。
然后,计算能力的提高允许研究人员实现更深、更高维的神经网络。新的技术进步带来了图形处理单元(GPU),这是深度学习所需的高维矩阵乘法的最有效的硬件之一。同样,唯一的限制是模型的算法和架构,而我们可以不断地收集更多的数据来提高准确性。
现在,DL 领域已经分裂成多个主要组:计算机视觉(CV)、音频理解和自然语言处理(NLP)等等。本教程将集中在一个“Hello World”类型的 NLP 介绍性问题,但也将包括一些计算机视觉技术。
有几个主要行业 NLP 可以完全重新设计。这些是客户服务,虚拟助理,信息检索。
- 在客户协助方面,聊天机器人可以简化客户服务,处理简单的任务和问题,并将复杂的查询留给人类。在未来,DL 模型可以分析电话,并通过情感分析对客户满意度进行评级。
- 虚拟助手使用自然语言理解技术从你的语音中提取命令。正是这些技术让 Alexa、Siri 和 Google Assistant 等虚拟助手能够交流并理解我们的语言。
- 信息检索通过使用情感分析和抽象概括从非结构化文本中提取有价值信息。
计算机视觉可以重新设计的一些领域是自动驾驶和安全。
- CV 是自动驾驶背后的主要力量之一,它存在于越来越受欢迎的特斯拉汽车中。它允许计算机识别街道地标,如车道线、交通信号和街道上的其他物体,如汽车和行人
- 安全性也会受到 CV 的严重影响。公司可以使用 CV 代替员工监控摄像头的威胁,这既增加了发现威胁的可能性,又降低了误报的几率。
基础知识
Image Courtesy of MPLS VPN (http://www.mplsvpn.info/2017/11/what-is-neuron-and-artificial-neuron-in.html)
深度学习以人类神经元为模型,其中神经元具有从其他神经元获取信息的树突,进行计算的轴突,以及向其他神经元发送信号的轴突终端。在人工神经元中,输入与树突同义,激活功能与轴突同义,输出类似于轴突终末。
深度学习的一个简单应用就是从数据中画出边界和洞察。
Courtesy of StackoverFlow
在上面的例子中,假设 x 轴是房子里卧室的数量,y 轴是房子里浴室的数量。红点代表公寓,绿点代表单户住宅,蓝点代表豪宅。DL 中的一个常见任务是根据卧室和浴室的数量将房子分类为公寓、单户住宅或豪宅。这是通过学习一个函数来完成的,该函数在 3 个不同的类周围画出一个大致的边界。
对于一个人来说,仅仅通过查看图就可以相对容易地用手画出这些边界。可以绘制的边界示例如下:
虽然当只有两个参数时,我们人类很容易做出这些界限,但随着参数数量的增加,这变得越来越具有挑战性。例如,如果给定房子的四个或五个不同的方面,在我们的头脑中想象这些数据几乎是不可能的。这是深度学习的主要应用。对于一台计算机来说,学习边界对于具有 10 个甚至 100 个不同特征的问题来说是非常初级的。
如果一个房子突然出现 1.5 个卫生间和 3 个卧室,我们可以根据上面的数据来概括我们的边界并预测它很可能是一个单独的家庭住宅。就像这样,深度学习模型可以很容易地针对许多数据点进行归纳,这意味着它不需要针对每个数据点和案例场景进行专门编程,并且可以使用之前从数据中获得的洞察力来决定做出什么决定。
让我们看看这到底是怎么做到的:
Image Courtesy of Jeffries (https://hackernoon.com/@dan.jeffries)
上面的图像是一个人造物体内部到底发生了什么的图像。一个人工神经元基本上是线性模型,形式是 y = Wx + B,或者 y = mx + b,应该看起来比较熟悉。w 和 B 是神经元的参数,可以改变以适应数据。最后,其中一个激活函数将被应用于 y,产生单个神经元的输出。
Image Courtesy of Sbongo (https://www.kaggle.com/sbongo/)
就像大脑是由数万亿个这样的神经元组成一样,神经网络(NNs)也是由许多相互连接的神经元组成的。
全连接层是最基本的架构,由数百个相互连接的人工神经元组成。这种架构有两个属性:深度和隐藏层大小。深度是模型中的总层数,而隐藏层大小是每层中神经元的数量。
这种架构的缺点是,随着输入图层的维度变得越来越大,例如当输入高分辨率图像的数百万个像素值时,完全连接的图层或密集图层不再起作用。
这就引出了下一个基础架构,称为卷积。
Image Courtesy of Tamang (https://medium.com/@apiltamang)
卷积神经网络是基于位置的架构,最初设计用于读取和解释图像像素。他们的工作原理是使用滑动滤波器,将滤波器中的所有值乘以一个权重并添加一个偏差,然后对总和应用一个激活函数。然后将从该操作中获得的所有值相加。当过滤器以一定的步幅穿过图像时,这继续进行。
ConvNet 的好处是它可以学习识别图像中的特征,从垂直和水平边缘一直到大型物体和动物。这使得 ConvNets 在 DL 的计算机视觉领域取得了巨大成功,并用于特斯拉的自动驾驶系统,以检测汽车、行人和道路特征,如车道线、标志和交通信号。
Image Courtesy of Computer Science Wiki (https://computersciencewiki.org/index.php/Max-pooling_/_Pooling)
一种重要的卷积类型是最大池,它只是从一个区域中获取最大像素值,并丢弃所有其他像素。提取并移动过滤器尺寸中的最大值,同时移除所有其他值。通常,最大池的过滤器大小为 2x2,跨距为 2,但也可以使用其他大小和跨距。max pooling 背后的直觉是,它减少了查看的像素数量,同时保留了图像最重要的特征。
Image Courtesy of Colah (https://colah.github.io)
递归神经网络(RNNs)主要用于语言或任何对其序列有长期依赖性的东西,如语音记录或音频文件。这些网络将输入分割成时间步长,每个时间步长的计算结果都被输入到下一个时间步长,从而赋予模型记忆输入的能力。这种网络是专门为语言设计的,因为当时的主要架构是无效的。时间步长的计算也不同于传统的人工神经元。RNN 建筑师实现了忘记和保留门,这为模型提供了一种以加权的方式记忆信息的方法,类似于人类记住他们生活中的重要部分并丢弃平凡的事情。这些系统被称为长短期记忆单元或 LSTMs。
这些是 DL 模型最常见的架构,可以相互结合使用,为复杂的任务创建更复杂的网络。
接下来我要解释的是一些最流行的激活函数以及为什么使用它们。您应该记得,DL 模型中的每个神经元计算输入和偏置的加权和,然后对输出应用激活函数以增加非线性。
双曲正切函数非常类似于 sigmoid 函数,而 sigmoid 函数的范围是 0 到 1,双曲正切函数的范围是-1 到 1。tanh 和 sigmoid 都可以表示门,这就是为什么这两个函数在 LSTMs 中非常流行的原因(见下图)。LSTMs 通常在其遗忘和保留门中使用 tanh 函数,因为它压缩-1 和 1 之间的值,这些值直观地对应于关闭和打开门。
sigmoid 函数是一个历史上非常流行的函数,当时模型和数据集都很小。在现代,它已经失去了一些流行,由于问题出现时,这个功能是复合在自己身上。最大的问题是由于这样一个事实,即随着数量的增加,这个函数的斜率变得无限小,停止了模型的优化。称为消失梯度问题,它导致了这个函数的轻微下降。
ReLU,或整流线性单元,是深度学习社区中使用的非常流行的激活函数(类似于大脑神经元思维)。它的流行是因为线性模型非常擅长概括数据。由于 ReLU 函数非常类似于线性函数,因此它保留了泛化的优点,同时仍将非线性引入模型。ReLU 函数简单来说就是 y=max(0,x)。
现在,您已经了解了创建自己的 DL 模型所需的所有基础知识。学习 DL 的下一步是理解它是如何从数据集学习的。
训练和损失函数
机器通过损失函数来学习。这是一种评估特定算法对给定数据建模程度的方法。如果预测与实际结果相差太多,损失函数就会产生一个非常大的数字。逐渐地,在一些优化函数的帮助下,损失函数学习减少预测中的误差。
DL 中使用的损失函数有很多种,每种都有自己的优缺点。DL 中最常见的两个损失函数是回归的损失函数(均方误差(MSE ))和分类问题的损失函数(交叉熵)。
MSE 损失是预测值和实际观测值的平方差的平均值。这种损失的一些优点是,高度不正确的预测受到很大的惩罚,并且更容易计算用于优化的损失函数的斜率。
使用的另一个损失是交叉熵:
交叉熵损失是分类问题中最常用的损失,因为它简单而有效。当实际标签为 1 时,函数的后半部分消失,而在实际标签为 0 的情况下,前半部分消失。为什么这种损失会起作用,一种直觉是注意到当预测和实际数据点都是 1 或 0 时,损失中的一项抵消,输出为 0。如果预测和数据点分别为 1 和 0,则损失最大。一个重要的方面是交叉熵损失会严重惩罚那些有把握但却是错误的预测。
训练深度学习模型的过程类似于调整模型中的每个参数,以便它们尽可能准确地拟合数据。一个简单的例子是改变公式 y=Wx + b 中的参数 W 和 b,以找到散点图上数据的最佳拟合线。
Image Courtesy of Stackoverflow ( https://stackoverflow.com/questions/19068862/how-to-overplot-a-line-on-a-scatter-plot-in-python)
实际上,有数学方法可以求解最符合数据的最佳参数 W 和 b,但在 DL 中这是不可能的,因为参数数量巨大。这可以通过查看关于上述数据的参数 W 和 b 的损失函数的曲线图以及 DL 模型的损失函数的曲线图来可视化。
Graph for the Linear Function’s Loss
Graph for the loss of a DL model
当损耗最小时,可以很容易地求解上图中的参数 W 和 b,但是对于 DL 模型,这是不可能的。因此,采用迭代方法来训练 DL 模型。
优化算法通过获取斜率或函数在给定点的梯度来实现这一点,然后从参数中减去斜率,以将该点向下移动到希望的最小值。
简单地说,调整 DL 模型的参数,直到它们输出正确的预测,之后这些参数被锁定在适当的位置以供使用。
该步骤的数学表示如下:
这里,θ是参数,表达式中的第二项可以看作损失函数相对于参数θ的斜率。alpha 符号表示该步骤的学习速率,并控制算法进行的步长。这一点很重要,因为如果步长太小,算法将运行非常慢,但如果步长太大,算法将快速波动。
估价
一旦训练了 DL 模型,就需要对它进行评估,以查看它在数据上的表现如何。衡量一个 DL 模型做得有多好的方法叫做度量,有许多不同的类型。
要使用的最简单的度量标准就是模型正确分类的示例占示例总数的百分比。这是模型的准确性,用于对模型的表现有一个浅显的、全面的了解。更复杂的指标将在本系列的第 2 部分中解释,我将一步一步地创建一个情感分析模型。
感谢您阅读这篇博文!在本系列的下一部分,我将一步一步地使用 Tensorflow 2.0 创建一个情感分析模型。我希望这篇文章已经成功地教会了你深度学习的基础。
自动编码器高级指南
一个自动编码器工具箱,从最基本的到最花哨的。
在机器学习和人工智能的奇妙世界中,存在一种称为自动编码器的结构。自动编码器是一种神经网络,它是无监督学习(或者对某些人来说,半无监督学习)的一部分。有许多不同类型的自动编码器用于许多目的,有些是生成式的,有些是预测式的,等等。本文将为您提供一个工具箱和不同类型的自动编码器指南。
传统自动编码器(AE)
The basic autoencoder
自动编码器的基本类型如上图所示。它由输入层(第一层)、隐藏层(黄色层)和输出层(最后一层)组成。网络的目标是输出层与输入层完全相同。隐藏图层用于特征提取或识别决定结果的特征。从第一层到隐藏层的过程称为编码。从隐藏层到输出层的过程称为解码。编码和解码的过程是自动编码器的特别之处。黄色层有时被称为瓶颈隐藏层。
从这里,有一堆不同类型的自动编码器。
问题:隐藏图层过多
我们首先要看的是解决过度完整的隐藏层问题。
Overcomplete Hidden Layers
需要注意的重要部分是,隐藏层比输入/输出层多。如果他们的数据中有比平常更多的特征,他们将需要这个。这样做的主要问题是输入可以不加任何改变地通过;就不会有任何真正的特征的提取。看看下面的例子:
Grey nodes are not used; the blue nodes are not at all altered.
输入层和输出层之间没有发生真正的变化;他们只是保持不变。此外,两个隐藏层节点根本没有被使用。为了避免这种情况,至少有三种方法:
解决方案 A:稀疏自动编码器
Sparse Autoencoders
简而言之,稀疏自动编码器能够“淘汰”隐藏层中的一些神经元,迫使自动编码器使用它们所有的神经元。它不再仅仅通过某些节点来记忆输入,因为在每次运行中,这些节点可能不是活动的。
解决方案 B:降噪自动编码器(DAE)
Some of the inputs are turned into 0.
我们改变了稀疏自动编码器中的隐藏层。另一种选择是改变输入。在去噪自动编码器中,一些输入被(随机地)归零。一旦它被馈通,输出就与原始(非零)输入进行比较。这与稀疏自动编码器的目的相似,但是这一次,清零的编码器位于不同的位置。
解决方案 C:收缩式自动编码器(CAE)
The darkened circles represent a slightly modified output.
我们改变了输入层,隐藏层,现在我们将改变输出层。自动编码器通过一种叫做反向传播的方法进行训练;在收缩式自动编码器中执行这种算法时,输出会略有改变,但不会完全归零(就像过去的算法一样)。反向传播时对输出层的这种改变阻止了纯粹的记忆。
为什么要解决这个问题?
这些网络的一些实际应用包括标记用于分割的图像数据、对图像去噪(对此的明显选择是 DAE)、检测异常值以及填充图像中的间隙。这些应用程序中的许多还与 SAE 一起工作,这将在下面解释。
别再提那个问题了。现在我们要提到其他更强大的自动编码器的变体。
堆叠式自动编码器(SAE)
Source: https://www.researchgate.net/figure/Stacked-autoencoders-architecture_fig21_319524552
堆叠自动编码器开始看起来很像神经网络。本质上,SAE 是许多自动编码器与多层编码和解码放在一起。这允许算法有更多的层、更多的权重,并且很可能最终变得更健壮。
不仅要了解 SAE,还要了解其他形式的 AEs,这些层也可以是卷积层和解卷积层;这样更便于图像处理。
SAE 和 AEs 的一些用途通常包括分类和调整图像大小。这是自动编码器已知的特征提取工具的两个实际应用;特征提取的任何其他用途对于自动编码器都是有用的。
可变自动编码器(VAE)
Source: http://kvfrans.com/variational-autoencoders-explained/
这可能是自动编码器最常用的变体:生成式。它也比其他的要复杂得多。
简而言之,VAEs 类似于 SAE,但是它们能够分离解码器。在中间,有两个向量,然后结合成一个潜在向量。这是什么意思?嗯,如果理论上从 SAE 中提取瓶颈隐藏层,并要求它生成给定随机向量的图像,很可能会产生噪声。有很多随机性,只有某些区域是提供真实图像的矢量。
The yellow sectors are good vectors. All of the pink region will just give noise.
由于获得图像生成向量的机会很小,均值和标准差有助于将这些黄色区域压缩成一个称为潜在空间的区域。然后,对其进行采样,以产生最终图像。潜在空间内的一切都应该产生图像。
从这里,我们可以取出编码部分,结果应该是一个生成器。
解开变分自动编码器
这是 VAEs 的决胜,略有变化。这将基本上允许每个向量控制图像的一个(且仅一个)特征。
看看下面的例子:
The two to the left use disentangled VAEs, and the one to the left is a normal VAE. (Source: https://arxiv.org/pdf/1707.08475.pdf)
请注意,在“解开”选项中,只有一个特征被更改(例如,左转、右转、距离等。).然而,在纠缠中,似乎有许多特征同时发生变化。单个变化改变单个特征的能力是解开 VAEs 的要点。
做到这一点的方法是向原始值添加另一个参数,该参数将考虑模型随着输入向量的每次变化而变化的程度。从那里开始,权重将相应地调整。
而且…现在就这样了。我希望你喜欢这个工具箱。我用了大量的文章和视频,都是很好的读物。如果有任何我可以改进的地方,或者如果你有任何意见或建议,我很乐意听到你的反馈。谢谢大家!
使用的来源
注:除非另有说明,所有图片均由本人设计。
该领域的术语没有固定的、清晰的和明确的定义,不同的研究可能意味着不同的…
stackoverflow.com](https://stackoverflow.com/questions/49296951/neural-networks-difference-between-deep-autoencoder-and-stacked-autoencoder#targetText=As%20I%20understand%20it%2C%20the,greedy%2C%20layer%2Dwise%20approach.) [## 基于堆叠式自动编码器的深度神经网络实现齿轮箱故障诊断
机械故障诊断在现代制造业中至关重要,因为早期检测可以避免一些故障的发生
www.hindawi.com](https://www.hindawi.com/journals/mpe/2018/5105709/) [## 教程-什么是变分自动编码器?-贾恩·阿尔托萨尔
为什么深度学习研究人员和概率机器学习人员在讨论变分时会感到困惑…
jaan.io](https://jaan.io/what-is-variational-autoencoder-vae-tutorial/) [## 解释了各种自动编码器
在我上一篇关于生成对立网络的文章中,我介绍了一个简单的方法来训练一个可以…
kvfrans.com](http://kvfrans.com/variational-autoencoders-explained/)
https://www.youtube.com/watch?v=9zKuYvjFFS8
【https://www.youtube.com/watch?v=fcvYpzHmhvA
http://www . jmlr . org/papers/volume 11/Vincent 10a/Vincent 10a . pdf
https://arxiv.org/pdf/1707.08475.pdf
用于通用乐高分拣机的高速计算机视觉流水线
在过去的几年里,我一直在设计和制造一台可以识别和分类乐高积木的机器。该机器的一个关键部分是捕获单元——这是一个小型的大部分封闭的腔室,具有一条皮带、一盏灯和一台相机。
You’ll see the light a bit later.
相机拍摄沿着传送带移动的乐高零件的照片,然后将零件的图像无线发送到服务器,服务器运行人工智能算法,从数千个可能的乐高元素中识别出零件。我将在未来的文章中提供更多关于人工智能算法本身的细节,但本文将致力于相机的原始视频输出和神经网络输入之间的处理。
我需要解决的核心问题是将皮带的实时视频流转换为神经网络可以使用的各个部分的图像。
The final goal: Go from raw video (left) to a bunch of uniformly sized images (right) to send to the neural network. (Gif is slowed down to about 50% speed vs realtime)
这是一个很好的例子,这个问题表面上看起来很简单,但实际上存在许多独特而有趣的障碍,其中许多是计算机视觉平台所特有的。
以这种方式提取图像的相关部分通常被称为“对象检测”。这正是我需要做的:检测对象的存在,它们的位置和大小,这样我就可以为每一帧的每一部分生成边界框。
The key is to find good bounding boxes (shown in green)
我将讨论解决方案的三个方面:
- 通过消除无关的变量来为自己的成功做准备
- 从简单的 CV 操作中构建管道
- 在有限的 Raspberry Pi 平台上保持良好的性能
消除无关变量
对于类似这样的问题,在尝试应用计算机视觉技术之前,最好尽可能多地消除变量。例如,我不想关心环境条件、不同的相机位置或由于遮挡造成的信息丢失。如果有必要,在软件中解决所有这些变量是可能的(如果非常困难),但幸运的是,我正在从头开始设计这台机器——我可以在编写任何代码之前通过删除这些变量来为自己的成功做准备。
第一步是强制固定相机位置、角度和焦点。很简单,装备把摄像机锁定在腰带上方。我也不需要担心遮挡;不想要的物体不太可能开始进入捕获单元。稍微难一点,但非常重要的是,强制一致的照明条件。我不希望我的物体探测器错误地将路人的影子解读为物理物体。对于许多计算机视觉应用来说,加强照明是非常困难或不可能的。谢天谢地,捕捉单元超级小(相机的整个视野比一条面包还小!)所以我对环境有了超乎寻常的掌控力。
View from inside the capture unit. The camera is in the top third of the frame.
一种选择是将盒子完全封闭,这样外部环境的光线就无法进入。我试过这个,用 LED 灯带做光源。不幸的是,它非常棘手——外壳上的一个小洞和光线可以涌入,干扰任何物体检测。
最后,最好的解决方案是通过彻底爆破充满光线的小房间来“战胜”其他光源。事实证明,这种可以照亮整个房间的灯非常便宜,使用起来也很简单。
Take that, shadows!
当光线射进这个小房间时,它远远压倒了任何潜在的干扰。作为一个令人高兴的副作用,这种丰富的光线意味着相机可以使用非常快的快门速度,拍摄零件的完美清晰的图像,即使它们沿着传送带跑。
物体检测器
那么,我如何把这个漂亮的、持续发光的视频变成有用的边框呢?如果你是一名人工智能从业者,你可能会建议实现一个对象检测神经网络,像 YOLO 或更快的 R-CNN 。这些神经网络可以轻松实现这个目标。不幸的是,我在一个 Raspberry pi 上运行对象检测代码。即使是高端计算机也很难以我需要的大约 90FPS 的帧率运行这些卷积神经网络。没有任何方式,一个树莓派,缺乏任何人工智能兼容的 GPU 硬件,将能够运行这些人工智能算法之一的超级精简版本。我可以将视频从 Pi 流式传输到另一台计算机,但实时视频流非常麻烦,延迟和带宽限制都会导致严重的问题,尤其是在需要高数据速率的情况下。
YOLO is really cool! But I don’t need all this functionality.
幸运的是,我可以通过寻找“老派”计算机视觉技术来避免复杂的人工智能解决方案。第一个是背景减除,它试图突出显示图像中正在变化的任何部分。在我的例子中,摄像机看到的唯一移动的东西是乐高零件。(皮带当然在移动,但是因为它有统一的颜色,所以看起来不会向摄像机移动)。把那些乐高零件从背景中分离出来,我就成功了一半。
为了使背景减法起作用,前景物体必须与背景有很大不同才能被提取出来。乐高零件有各种各样的颜色,所以我需要非常明确地选择背景颜色,尽可能不像乐高。这就是为什么相机下面的带子是由纸制成的——不仅需要非常均匀,而且不能由乐高制成,否则它会与它需要识别的一些砖块颜色相同!我选择了淡粉色,但任何其他不同于普通乐高颜色的柔和颜色都可以。
精彩的 OpenCV 库内置了许多背景减除算法。MOG2 背景减法器是最复杂的,运行速度惊人,甚至在树莓 pi 上也是如此。然而,将视频帧直接馈送到 MOG2 并不十分有效。浅灰色和白色的作品在亮度上与苍白的背景过于相似,会丢失。我需要一种方法,通过告诉背景减法器更仔细地查看颜色而不是亮度来更清楚地区分皮带和皮带上的东西。我所需要做的就是在将图像传递给背景减法器之前增加图像的饱和度。结果大大改善了。
在背景减除之后,我需要使用形态学操作来消除尽可能多的噪声。OpenCV 的 findContours()功能可用于查找白色区域的轮廓。在应用了一些基于轮廓面积的启发式方法来丢弃包含噪声的轮廓之后,将这些轮廓转换成最终的边界框是一个简单的过程。
表演
神经网络是一头饥饿的野兽。为了获得尽可能好的分类结果,需要尽可能多的高分辨率图像。这意味着我需要以很高的帧速率拍摄,同时还要保证图像质量和高分辨率。我将把相机和树莓图形处理器推到绝对的极限。极其详尽的 picamera 文档显示,V2 相机芯片可以以每秒 90 帧的最高速度输出 1280x720 像素的图像。这是一个令人难以置信的数据量,即使相机可以生成它,也不意味着计算机可以处理它。如果我处理的是原始的 24 位 RGB 图像,那就需要大约 237 MB/s 的带宽,对于可怜的 Pi 的 GPU 或 SDRAM 来说太多了。即使使用 GPU 加速的 JPEG 压缩,90fps 也是不可能实现的。
raspberry pi 摄像机能够输出未经过滤的原始“YUV”图像。尽管 YUV 比 RGB 更难处理,但它实际上有很多很好的属性。最重要的是,它每像素只有 12 位(相对于 RGB 的 24 位)。
Every 4 ‘Y’ bytes has one ‘U’ and one ‘V’ byte — that comes out to 1.5 bytes per pixel.
这意味着我可以处理两倍于 RGB 帧的 YUV 帧,甚至不考虑 GPU 否则将不得不花费编码 RGB 图像的额外时间。
上面对实际的处理管道设置了一些非常独特的限制。对全尺寸视频帧的大多数操作都将是内存和 CPU 密集型的。在我严格的时间限制内,即使解码一个全尺寸的 YUV 帧也是不可能的。
幸运的是,我实际上不需要处理整个帧!对象检测不需要精确的边界框,只需要相当接近即可,因此整个对象检测流水线可以在小得多的调整大小的帧上完成。缩小操作不需要考虑全尺寸帧中的所有像素,因此,只要小心,可以非常快速且廉价地调整帧的大小。然后,生成的边界框被按比例放大,并用于从全尺寸 YUV 帧中取出裁剪部分。这样,我永远不需要解码或处理整个高分辨率帧。
幸运的是,由于这种 YUV 格式的存储方式(见上文),实现直接在 YUV 格式上工作的快速裁剪和缩小操作实际上非常容易。最后,整个管道可以在 Pi 的 4 个内核上多线程化,而不会有太多麻烦(您确实需要在后台减法步骤周围设置一个锁)。然而,我发现并非所有内核都得到充分利用,这表明瓶颈仍然是内存带宽。即便如此,我在实践中也能达到 70-80 fps。更深入的内存使用分析可能会进一步加快速度。
如果你有兴趣了解更多关于这个项目的信息,可以看看我以前的文章,我是如何创造了超过 100,000 个标记的乐高训练图像。
你可以在推特上关注我: @JustASquid
极区/花簇/玫瑰图的历史&如何在 R 的 ggplot2 中制作它们
探索图表名称背后的故事及其潜在的使用案例
A sample Polar Area Chart created in R using data from transfermarkt.com
这张图表有几个不同的名字:极地区域图,风玫瑰图,玫瑰图,花花公子图,甚至是顾问图。我将从概述图表的历史和我在网上搜索观察到的一些差异开始。在底部有一个关于如何在 R 的 ggplot2 包中创建图表的技术解释。
首先,我们来处理一下名字。数据即 Projec t 使用以下描述将极区、Coxcomb &玫瑰图组合在一起:
“极区图类似于通常的饼图,除了扇形是等角的,并且每个扇形从圆心延伸的距离不同。”
《T4 可视化数据》一书的作者安迪·基尔克用同样的方式对它们进行分类,尽管不包括玫瑰图,包括圆形柱状图。他的定义稍微详细一些,如下:
'极坐标图在同一个显示屏上显示三个或更多不同定量指标的值。它使用一个放射状(圆形)布局,包括几个等角度的扇形,就像比萨饼的切片,每个测量一个。与雷达图(使用沿刻度的位置)相比,极坐标图使用扇形区域大小的变化来表示定量值。这实际上是一个放射状绘制的条形图。
因此,该图表是条形图(使用长度作为预先注意的特征)和饼图(本质上是放射状的,顶部较宽,中间较薄的部分,即。极坐标)。这有助于我们理解图表的形式作为一种表示数据的方式,但仍然没有告诉我们为什么这种图表类型在涉及到不同的名称时如此贪婪!
为了回答这个问题,我们先来看看这张图表在野外的首次出现。根据大多数资料,它首次出现是在克里米亚战争期间,佛罗伦萨·南丁格尔在她的统计图中使用它来显示一年中几个月的死亡原因。
Nightingale’s Diagram on the Causes of Mortality in the Crimean War
出于这个原因,可以理解为什么它有时被称为“夜莺的玫瑰”——向外延伸的部分类似于玫瑰的形状。作为它的一个变体,“风玫瑰图”采用了类似的格式,但是这些线段是根据指南针的指向来显示风向和风力的。在足球分析领域,风玫瑰图被用来显示特定位置或球员的传球方向和数量。
然而,弗罗伦斯·南丁格尔自己从来没有把图表称为玫瑰,这个名字是后来才有的。与普遍看法相反,她也没有把它们称为“花花公子”图表。更详细的解释可以在这里找到,但是看起来‘花花公子’这个名字已经因为一个误解而随着时间的流逝而消失了!
A Cockerel’s Coxcomb
到底什么是花花公子?它可以指一种花的形式,但是,考虑到图表的视觉特性,误解很可能是在与另一个定义进行比较时产生的:公鸡头顶上的红色羽冠(自己看吧!)
本质上,虽然南丁格尔在她的报告中使用了 coxcomb 这个词,但她指的不是图表本身,而是图表的位置和一份更大的报告----皇家委员会报告----的报告。
我们现在已经讨论了玫瑰和花花公子,只剩下极地区域图和顾问图(不可否认不太为人所知,不在本文讨论之列)。
在数学中,极坐标系是一种二维坐标系,其中平面上的每一点都由与参考点的距离和与参考方向的角度来确定。参考点称为极点,从极点沿参考方向发出的射线为极轴。这与我们大多数人习惯的坐标系不同;“笛卡尔”坐标系。这包括线性、垂直/水平方向的标准 x、y 坐标。
Same Chart using Cartesian (x,y) coordinates
上面的例子是与原始图表完全相同的图表,但没有 r 中的 coord_polar()指令。你可以明白为什么安迪·基尔克将该图表描述为“实际上是一个径向绘制的条形图”。通过使用极坐标,您可以将整个图表环绕在一个中心点周围,使其向外呈扇形增大。
它与径向条形图的不同之处在于,当你远离中心时,它的宽度会增加,形成楔形或比萨饼切片,而不是矩形条。这就是极区图中“面积”部分的由来。我相信这使得极区图更适合跨类别的快速比较,正如我们在阿森纳比较中所做的那样,因为可视化利用长度和宽度来表示数据。由于 viz 中覆盖的表面积更大,我的眼睛能够更快地注意到较高和较低的值&对不同的玩家进行比较。
因此,总之,对于大多数用例来说,极区图应该是该图的常用名称。玫瑰图/风玫瑰图适用于可视化采用预先获得的罗盘/特定方向知识,以强调每个线段长度上的运动。据我们所知,这张花花公子图的命名是错误的,尽管它至少保留了与该图的原始设计者——弗洛伦斯·南丁格尔的联系。最终,和大多数语言情况一样,只要你的听众明白你在说什么,你叫它什么并不重要!
如何制作 R 中的极区图
本博客的第二部分现在将分解如何在 R 中构建极区图。这假设对 R、RStudio &如何安装包有基本的了解。下面是创建相对无格式的极区图的完整代码。请参阅下面的逐行描述。用您自己的数据框替换粗体彩色指标。
ggplot( 数据,aes(x= 公制,y= 长度)+
- 这一行调用 ggplot2 包,将您的数据绑定到绘图,并允许您选择将用于可视化的“美学”(aes)。
- 在这种情况下,我们希望 x 轴上是我们的度量,y 轴上是我们的值。请记住,我们正在创建一个柱形图,直到 coord_polar 命令。
- 使用“+”号将各行链接在一起。
geom_col(fill = " red ",alpha=1,width=1)+
- 这将调用 geom_col 函数,这是制作柱形图/垂直条形图所必需的。
- fill 参数设置列的填充颜色。这里可以使用十六进制代码/RGB。
- alpha 设置透明度(0 =透明,1=不透明)。
- 宽度设置列之间的间隙(0 =无栏,1=并排接触)。
geom_hline(yintercept = seq(0,100,by = 10),
color = "grey ",size = 1) +
geom_vline(xintercept = seq(.5,16.5,by = 1),
color = "grey ",size = 1) +
- 这些线条为我们的图表添加了一些方便的网格线。
- geom_hline 设置圆形网格线,geom_vline 设置线段边界线。
- seq()在两个数字之间创建一个序列,“by”参数说明了间隔。
- 颜色设置线条颜色。
- 大小设置线条宽度。
坐标极坐标()+
- 神奇就发生在这里。从笛卡尔坐标转换到极坐标。
facet _ wrap(vars(Player))
- 使用“facet”函数获得每个特定指标的小倍数。点击阅读更多关于这个的内容。
图表的所有其他格式,例如添加标题、副标题、背景颜色和小平面的方框,都可以在主题()中实现。下面是我为我的兵工厂图表创建的主题的一个例子。
混合密度网络搭便车指南
评估预测的不确定性是商业决策的基础。混合密度网络帮助你更好地理解你在现实世界中面临的不确定性。
Photo by Adi Goldstein on Unsplash
介绍
不确定性是我们做出每个决定的关键因素。然而,在商业中,经理们经常会面临各种各样不可预见的后果。经理可能会处理以下问题:
- “我们如何根据产品属性为 XYZ 定价?”
- “这个广告会带来多少网站访问量?”
- “顾客 Z-A137 的预期顾客终身价值是多少?”
- “考虑到市场形势,我们应该在广告上花多少钱?”
这些问题中的每一个都意味着一个决策,这个决策最好是充分知情的,并且考虑(或者至少承认)潜在的不确定性。例如:错误的定价会导致收入减少,这反过来可能会导致节约成本的必要性。
这篇文章面向面向业务的数据科学受众。我们将探讨一些关于预测连续值的技术问题,以及众所周知的线性模型在某些情况下的局限性。然后,我们展示了一种称为混合密度网络(MDN)的神经网络变体,以规避这些限制。因此,管理者可以更好地理解预测的潜在不确定性。
前面提出的问题需要预测,并且有三个共同的基本特征。第一个是,我们希望预测一个连续的数量(价格、网站访问量、销售额,你能想到的)。第二个,预测是在不确定性下做出的。因此,我们很想了解一下我们对预测的不确定性。第三,预测取决于一些输入观察(产品属性、客户、广告设计)。理想情况下,我们不希望得到问题的单一答案,而是希望得到一系列答案来评估每个答案的概率。简而言之:我们正在寻找一个概率分布在给定输入的答案范围内。因此,我们增强了对预测的理解,甚至可以作为经理或客户做出更明智的决策。
高斯混合的直觉
举个例子:让我们假设,我们将要预测一个产品的价格,比如说耳机。看一下市场价格的柱状图,我们推断出存在低价位(~30 美元)、中位(~60 美元)和高价(~120 美元)的耳机。回归到简单的高斯分布来模拟数据注定会失败,从经验高斯分布的曲线可以很容易地看出这一点。请记住,高斯正态分布(𝒩)由两个值参数化:均值(μ)和标准差(σ)。根据样本平均值(μ=47.95)和标准差,将𝒩拟合到数据中。偏差(σ=27.76)将概率分配给价格区域,这是我们在虚拟市场中观察不到的(即价格在$90 到$110 之间)。此外,根据曲线的左侧,负的价格是“合理的”。
Source: Author
产生价格分布的基础数据是高斯混合的。混合物是多峰的;因此,它表现出多个“峰值”。为了适应我们虚构的定价数据的分布,我们可以使用不是一个,不是两个,而是三个充分混合的高斯分量。我们“只”需要选择参数(μ,σ),通过加权(⍺)归一化分布,并对它们求和(稍后将详细介绍)。如下图所示,巧妙地混合这些组件反映了真实的数据。
Source: Author
我们将在后续章节中使用 tensor flow(【www.tensorflow.org】)及其扩展 tensor flow-Probability(【www.tensorflow.org/probability】)。该示例是在 Tensorflow Probability 中使用下面代码片段中显示的值生成的。我们基本上定义了同一个族的混合分布。
线性回归的假设
本文开头提出的问题的第一个解决方案确实是执行一个简单的线性回归。我们几乎可以听到你在打哈欠。
但是等等,我们会给它一个简短的技术镜头!给定一个输入向量 x (产品属性、客户……等等),我们希望预测 y (价格、网站访问量……等等)。更准确地说:我们的目标是在给定x:*p(y |x)的情况下获得 y 的概率。如果我们假设实值目标数据的高斯分布(正如我们通常所做的,当我们最小化平方误差时),那么p(y |x)*采用众所周知的形式:
在实际应用中,对于某数据集𝔻.中的所有( x 、t15】y)对,给定 x 、其参数θ和目标值 y ,我们最小化线性函数μ的输出的平方误差项(μ( x 、θ-y)在给定数据和参数的情况下,学习函数实质上“吐出”了高斯分布μ( x ,θ)的条件均值。它扔掉了性病。偏差和归一化常数,不依赖于θ**。通过这样做,该模型强加了多个重要的假设,这些假设在实践中可能非常有限:**
- 数据分布是高斯分布。引用[1]:
“实际的机器学习问题往往可以有显著的非高斯分布”(第 272 页)。 - 产出分布是单峰的。因此,我们无法解释 x 可以产生多个有效答案的情况,而多模态分布可以捕获这些答案(如上面的耳机示例)。
- 性病。假设噪声分布的偏差σ为常数,因此一定不依赖于 x (同质性,各向同性协方差矩阵)。同样,在现实世界中情况并不总是如此。
- 函数μ( x ,θ)是线性的,即μ( x ,θ)=x×w+b**,其中θ**= {w,b 线性模型被广泛认为更容易解释。另一方面,神经网络提供了极好的预测能力,因为它们理论上能够模拟任何函数。
让我们考虑两种情况,这两种情况形象地激发了先前概述的技术问题:
Source: Author
(LHS):基本函数是线性的。然而,我们观察到两个违反:首先是,std。(噪声)分布的偏差不是常数。其次,噪声确实取决于输入。
(RHS):不仅是性病。噪声分布的偏差取决于 x ,但是输出额外为非线性。此外,输出分配是多模态。对于某些数据区域(大约 8),简单平均值不是一个合理的解决方案。当我们要预测遵循如此复杂模式的结果时,强加先前概述的假设可能容易误导。
MDN 的背景
考虑到上述限制,[2]建议通过 DNN 对混合分布进行参数化。MDN 最初构想于 1994 年[1] [2],最近发现了一系列不同的应用。比如:苹果 iOS 11 中的 Siri 使用 MDN 进行语音生成[3]。Alex Graves 使用 MDN 结合 rnn 来生成人工笔迹[4]。此外,还有多个博客帖子专门讨论这个主题[5] [6] [7] [8]。Amazon Forecast 为其客户提供 MDN 作为算法[9],而[10]写了一篇关于这个主题的硕士论文。
然而,我们希望为更广泛的受众建立方法。原因很简单,许多现代神经网络架构可以扩展为 MDN(Transformer、LSTMs、CovNets 等)。MDNs 本质上可以被视为一个扩展模块,适用于各种各样的业务相关任务。
Source: Author
在其核心,MDN 的概念是简单的,直截了当的,有吸引力的:**结合了深度神经网络(DNN)和混合分布。**DNN 为多个分布提供参数,然后通过一些权重进行混合。这些砝码也由 DNN 提供。由此产生的(多模态)条件概率分布有助于我们对现实世界数据中的复杂模式进行建模。因此,我们能够更好地评估,我们预测的某些值有多大的可能性。
混合模型的形式化
理论上,高斯混合能够模拟任意概率密度[2],如果它被充分参数化(例如,给定足够的分量)。形式上,混合物的条件概率定义为
让我们分别阐述每个参数:
- c 表示相应混合物成分的指数。每个输出最多有 C 个混合成分(即:分布),这是一个用户可定义的超参数。
- ⍺表示混合参数。将混音参数想象成滑块,以不同的强度将不同的音频信号混合在一起,产生更丰富的输出。混合参数取决于输入 x 。
- 𝒟是要混合的相应分布(音频信号)。可以根据任务或应用来选择分布。
- λ表示分布𝒟.的参数如果我们将𝒟表示为高斯分布,λ1 对应于条件均值μ( x ),λ2 对应于条件标准差。偏差σ( x )。分布可以有多个参数(例如:Bernoulli 和 Chi2 有一个参数,Gaussian 和 Beta 有两个参数,截断的 Gaussian 最多有四个参数)。这些是神经网络输出的参数。
将条件概率公式化为分布的混合已经解决了与概述的假设相关的多个问题。首先,分布可以是任意的,因为我们理论上能够将每个分布建模为高斯分布的混合物[2]。其次,使用多种分布有助于我们对多模态信号进行建模。考虑我们的耳机价格例子,这显然是多模态的。**第三,**性病。偏差现在以输入为条件,允许我们考虑变量 std。偏差。即使我们只使用单一的高斯分布,这个优势也适用。第四个,函数的线性问题可以通过选择一个非线性模型来解决,该模型决定了输入的分布参数。
为了获得混合物的参数,DNN 被修改以输出多个参数向量。我们从单层 DNN 和 ReLU 激活开始。使用隐藏层 h1( x ),我们继续计算混合物的参数如下:
混合系数必须总和为 1:∑⍺(x)= 1。因此,我们使用 softmax 函数来约束输出。这一步很重要,因为概率的混合必须整合为一。λ1 和λ2 的约束本身取决于我们为模型选择的分布。我们必须对高斯函数施加的唯一约束是。偏差为
σ( x ) > 0。这种效果可以通过多种方式实现。例如,我们可以使用最初由 Bishop [1] [2]提出的指数激活。然而,指数会导致数值不稳定。或者,我们可以使用简单的 softplus 激活,类似于[11]中使用的 oneplus 激活。或者我们采用一种有偏移的 ELU 激活的变体。由于最近 ELU 的突出,我们选择了后者。因此,我们最终完成了以下转换:
约束条件的选择取决于分布和数据。一如既往:不同的约束可能在不同的数据集上表现得更好。有人甚至会说,从商业角度来看,将μ( x )限制为正值也是明智的。因此,我们可以认为负价格是不可能的。
既然我们现在指定了参数和条件概率,我们就有了使用某种形式的梯度下降(SGD、Adagrad、Adadelta、Adam、RMSProp 等)直接最小化平均负对数似然(NLL)所需的一切。).
千年发展目标的实施
建立了 MDN 的基本理论后,我们现在展示如何在 Tensorflow/Keras 中实现该模型。我们基本上需要两个组件:计算参数的自定义层和最小化的损失函数。出于数值稳定性和方便性的原因,我们将在张量流函数中进行大部分计算。正如我们之前强调的 MDN 框架的灵活性一样,我们并没有讨论所有的内容,而是讨论了与您构建自己版本的 MDN 框架相关的部分。定义 DNN 很简单:
根据数据和应用,对 sigmas 进行额外的活动调整以防止 std 也可能是有意义的。偏离炸毁。简单的 L2 正则化将是一个明智的选择。
代码示例需要一个“非负指数线性单位”激活函数,确保 sigmas 严格大于零。Tensorflow 提供了一种非常友好的方式来定义所需的激活函数。我们只是让 nnelu 成为一个可调用的函数,并在 Keras 中将其注册为自定义激活函数。
剩下的构建模块是损失函数的实现。Tensorflow-Probability 的应用很方便,因为我们只是稍微重新定义了本文开头的例子。MixtureSameFamily 需要混合分布和组件分布。前者是一个简单的分类分布,它得到混合权重⍺( x 。后者是正态分布,由平均值和标准差参数化。偏差。随后,我们只需计算 y 及其负平均值的对数似然。通过回归到张量流概率,我们避免了数值上溢/下溢(手动实现这一点实际上相当棘手)。
在定义了 MDN 最重要的组件之后,只剩下模型的编译了。
模拟数据的应用
是时候回到我们之前的例子了。我们训练具有两层的简单 MDN,每层 200 个神经元,并且在线性数据集上有一个高斯分量。MDN 显示了它的实力:由于调节性病。输入上分布的偏差,MDN 可以适应底层数据分布的变化。它巧妙地捕捉到了线性趋势(如预期的那样),但调整了标准差。根据数据中存在的不确定性的增加而产生的偏差(我喜欢这个图表。看起来像流星)。
Source: Author
为了更好地掌握结果,我们还对几个模型的平均负对数似然进行了比较。也就是说,让我们看看零模型(样本均值和样本标准差。偏差)、线性模型(线性条件均值和样本标准差。偏差)、DNN(非线性条件均值和样本标准差。偏差)和 MDN(非线性条件均值和非线性条件标准差)。偏差)。DNN 和 MDN 使用相同的参数和训练程序。幸运的是,我们可以使用 Tensorboard 监控 MDN 的训练进度。所要做的就是回调 fit 例程。因此,我们不需要费心单独存储训练损失。我们正在汇合!
MDN nll-loss during optimization. Source: Author
Source: Author
所有模型都能够击败零模型。其余模型在 MSE 方面表现相同,因为 MSE 假设 std。基础分布的偏差是常数。我们无法充分捕捉数据的行为!NLL 包含了 std。偏差,确实反映了一个更微妙的画面。由于基础函数是线性的,因此 DNN 和线性模型的性能相当。然而,MDN能够更好地适应数据分布,从而产生最低的 NLL 值。
为了从单个数据点的 MDN 的概率密度中导出条件均值,可以计算:
看一下这个公式就可以解释这个结果:平均值没有包含标准差。偏差σ( x )。仅仅查看 MDN 的含义就丢弃了有价值的信息,而这些信息在现实世界的应用程序中可能是需要的。有了这种分布,我们就可以计算更精细的数量。例如,香农熵可以作为我们有多确定的指标。或者我们可以计算 f-散度来评估,预测有多相似。
现在让我们转向第二个非线性的例子。我们首先使用最小-最大缩放器将 y 转换为 DNN / MDN 的合理范围,以加速学习。
Source: Author
MDN 不仅能捕捉潜在的非线性,还能捕捉输出的多模态和标准差的变化。偏差。数据生成分布被充分捕获。查看 x = 8 的条件密度,我们看到 MDN 产生两个不相交的峰值:
Source: Author
对这些复杂分布建模的能力反映在 NLL 中,MDN 在 NLL 中取得了最好的效果。
Source: Author
真实世界数据的应用
我们以预测价格的例子开始这篇文章。在冗长的技术阐述之后,让我们回到最初的例子:预测价格。
为了便于分析,我们使用数据集的果蝇:波士顿住房。给定大约 13 个独立变量,目标是预测以 1000 美元为单位的自有住房的中值(MDEV)。这个例子可能没有充分利用 MDNs 的能力来建模多模态分布。尽管如此,它显示了 MDN 如何能够模拟价格的不确定性。自变量使用最小-最大缩放器进行转换,而价格则进行对数转换。
Source: Author
在 NLL 中,我们观察到与前面的例子类似的行为。MDN 能够更好地处理数据。因此,虽然我们在例子中可能没有多模态,但我们肯定受益于对完整条件概率的建模,而不仅仅是点估计。
Source: Author
分析不同房屋的条件密度有助于我们更好地做出决定。我们对 18 号房的高价相当有信心,因此,作为管理者,我们可以相应地设定价格。
对 12 号房的预测很不确定。可能需要人类专家直接评估案例来设定价格。
房子 13 和 45 在价格上确实重叠。直接分析它们的属性是有意义的,以查看它们是否可以作为相同价格范围内的买家感兴趣的对象。虽然我们没有在这个简单的数据集中挖掘模型的全部潜力,但我们仍然从附加功能中受益。
摘要
评估不确定性是现代企业的一个重要方面。这篇博文重点介绍了理论推理、实现细节以及使用 MDN 时的一些技巧和诀窍。我们展示了 MDN 在模拟和实际应用中的能力。由于它的简单性和模块化,我们期待广泛的应用。
如有疑问,欢迎联系 me 。
附加说明
代码在Github/Colab**上有。**本指南是为 Tensorflow 1.12.0 和 Tensorflow-Probability 0.5.0 编写的。
文学
[1] Christopher M. Bishop,模式识别与机器学习 (2006)
[2]克里斯托弗·m·毕晓普,混合密度网络 (1994)
[3] Siri 团队,Siri 语音的深度学习:用于混合单元选择合成的设备上深度混合密度网络 (2017)
[4] Alex Graves,用递归神经网络生成序列 (2014)
[5] Christopher Bonnett,Edward,Keras 和 TensorFlow 的混合密度网络 (2016)
[6]吴炳浩,混合密度网络:基础知识 (2017)
[7] Otoro,tensor flow 混合密度网络 (2016)
[8] Mike Dusenberry,混合密度网络 (2017)
[9]亚马逊,混合密度网络配方 (2019)
[10] Axel Brando,分布和不确定性估计的混合密度网络实施 (2017)
[11] Alex Graves 等人,使用具有动态外部存储器的神经网络的混合计算 (2016)
放弃
表达的观点仅代表我个人,并不代表我的雇主的观点或意见。作者对本网站内容的任何错误或遗漏不承担任何责任或义务。本网站包含的信息按“原样”提供,不保证完整性、准确性、有用性或及时性。
为数据科学家揭秘对象检测和实例分割
The stage we are at and how we reached it.
目标检测
简单解释!!!我试过了
我非常喜欢深度学习,但对象检测对我来说并不容易。
并且目标检测是重要的并且确实有它的用途。其中最常见的是自动驾驶汽车、医学成像和人脸检测。
这绝对是一个很难解决的问题。在这个问题的漫长历史中引入了如此多的活动部件和新概念,它变得更加难以理解。
这篇文章是关于 将那段历史提炼成一个简单的解释 并解释对象检测和实例分割的血淋淋的细节。
介绍
我们都知道图像分类问题。给定一幅图像,你能找出它属于哪一类吗?
我们可以使用预训练的网络,通过 ConvNets 和转移学习解决任何新的图像分类问题。
作为固定特征提取器的 conv net。获取一个在 ImageNet 上预训练的 ConvNet,移除最后一个完全连接的层(该层的输出是 ImageNet 等不同任务的 1000 个类分数),然后将 ConvNet 的其余部分视为新数据集的固定特征提取器。在 AlexNet 中,这将为每个包含分类器之前隐藏层激活的图像计算 4096-D 向量。我们称这些特征为 CNN 代码。如果这些代码在 ImageNet 上训练 ConvNet 期间也达到了阈值(通常情况下),则这些代码被重新赋值(即阈值为零)对性能非常重要。为所有图像提取 4096-D 代码后,为新数据集训练一个线性分类器(如线性 SVM 或 Softmax 分类器)。
但是在图像领域还有很多其他有趣的问题。
这些问题可以分为 4 大类。在接下来的几行中,我将尝试在我们深入探讨之前简要解释这些问题:
- 语义分割: 给定一幅图像,我们能否将每一个像素归类为属于特定的一类?
- **分类+定位:**我们能够将图像分类为一只猫。太好了。*我们是否也可以通过在猫的周围画一个边界框来获得该猫在图像中的位置?*这里我们假设图像中有固定数量的物体(一般为 1 个)。
- **物体检测:**一个更一般情况下的分类+定位问题。在真实世界的设置中,我们事先不知道图像中有多少对象。那么我们是否可以检测图像中的所有对象,并在它们周围绘制边界框?
- 实例分割: *我们可以为图像中的每个单独的对象创建遮罩吗?*不同于语义切分。怎么会?如果你看顶部的第四张图片,我们将无法使用语义分割程序区分两只狗,因为它会将两只狗合并在一起。
正如你所看到的,所有的问题都有相似的味道,但彼此又有些许不同。在这篇文章中,我将主要关注对象检测和实例分割,因为它们是最有趣的**。我将介绍 4 种最著名的物体探测技术,以及它们是如何随着时间和新想法而改进的。**
分类+本地化
因此,让我们首先尝试理解,当图像中只有一个物体时,我们如何解决这个问题。分类+本地化案例。
💡把本地化当成回归问题!
输入数据
让我们首先讨论这种模型期望什么样的数据。通常在图像分类设置中,我们使用(X,y)形式的数据,其中 X 是图像,y 是分类标签。
在分类+本地化设置中,我们通常会有(X,y)形式的数据,其中 X 仍然是图像,y 是包含(class_label,X,y,w,h)的数组,其中,
x =边界框左上角的 x 坐标
y =边界框左上角的 y 坐标
w =边界框的宽度,以像素为单位
h =边界框的高度,以像素为单位
型号
所以在这个设置中,我们创建了一个多输出模型,它以一个图像作为输入,有(n_labels + 4)个输出节点。n_labels 每个输出类的节点和给出(x,y,w,h)预测的 4 个节点。
损失
通常,损失是 Softmax 损失(来自分类问题)和回归 L2 损失(来自边界框坐标)的加权和。
损失=阿尔法*软最大损失+(1-阿尔法)*L2 损失
由于这两个损失将在不同的规模,阿尔法超参数是需要调整的东西。
这里有一件事我想注意一下。我们正在尝试进行对象定位任务,但我们仍然有我们的 convnets 在这里。我们只是增加了一个输出层来预测边界框的坐标,并调整了我们的损失函数。
*而这正是整个深度学习框架的精髓所在——*层层叠加,重用组件来创建更好的模型,创建架构来解决自己的问题 。这就是我们将会看到的未来。
目标检测
那么这种使用回归的定位思想是如何映射到物体检测的呢?没有。
我们没有固定数量的物体。所以我们不能有 4 个输出来表示边界框坐标。
一个天真的想法可能是将 CNN 应用于图像的许多不同部分。CNN 将每种作物分类为对象类或背景类。这很棘手。你可以创造很多这样的作物。
区域提议:
因此,如果有一种方法(通常称为区域建议网络)可以自动为我们找到一些数量较少的裁剪区域,我们就可以在这些区域上运行 convnet 并完成对象检测。这就是 RCNN 背后的基本思想——物体探测的首次重大成功。
这就是选择性搜索(Uijlings 等人,“目标识别的选择性搜索”IJCV,2013)所提供的。
那么什么是地区提案呢?
- 找到可能包含物体的图像区域
- 跑起来比较快;例如,选择性搜索在几秒钟内在 CPU 上给出 2000 个区域建议
那么,地区提案究竟是如何提出的呢?
目标识别的选择性搜索:
本文分两步寻找区域。
首先,我们使用[13] (P. F. Felzenszwalb 和 D. P. Huttenlocher)从一组初始区域开始。高效的基于图形的图像分割。IJCV,59:167–181,2004 年。1, 3, 4, 5, 7)
基于图的图像分割技术通常用图 G = (V,E)来表示该问题,其中每个节点 v ∈ V 对应于图像中的一个像素,E 中的边连接某些相邻像素对。
在本文中,他们采用了一种方法:
每个边(vi,vj )∈ E 具有相应的权重 w((vi,vj)),其是相邻元素 vi 和 vj 之间的相似性的非负度量。在基于图的方法中,分段 S 是将 V 划分成多个分量,使得每个分量(或区域)C ∈ S 对应于图中的一个连通分量。
Efficient graph-based Image Segmentation Example
简而言之,他们使用基于图形的方法来寻找图像中的连通成分,并根据像素之间的某种相似性度量来制作边缘。
正如你所看到的,如果我们在这些遮罩周围创建边界框,我们将会丢失很多区域。我们希望将整个棒球运动员放在一个边框中。我们需要以某种方式将这些初始区域分组。这是第二步。
为此,对象识别的选择性搜索的作者将分层分组算法应用于这些初始区域。在这种算法中,他们根据不同的相似性概念(基于颜色、纹理、大小和填充)将最相似的区域合并在一起,为我们提供更好的区域建议。
**
The Algorithm for region Proposal used in RCNN
1.R-CNN
所以现在我们有了我们的区域提案。在 R-CNN 中我们到底该如何使用它们?
物体检测系统概述。我们的系统
(1)获取输入图像,(2)提取大约 2000 个自下而上的区域提议,(3)使用大型卷积神经网络(CNN)计算每个提议的特征,然后(4)使用特定类别的线性 SVM 对每个区域进行分类。
除此之外,作者还使用了特定于类的边界框回归器,它采用:
输入:(Px,Py,Ph,Pw)-建议区域的位置。
目标:(Gx,Gy,Gh,Gw)-该区域的地面实况标签。
我们的目标是学习一种将建议区域§映射到地面真实框(G)的变换
培训 R-CNN
RCNN 的输入是什么?
因此,我们从 RPN 战略和标签的基本事实(标签、基本事实框)中获得了一个图像、区域建议
接下来,我们将所有 IoU(交集/并集)与基础事实框重叠≥ 0.5 的区域提议视为该框类的正面训练示例,其余视为负面训练示例。我们训练班级特定的 SVM 氏症
因此,每个地区的提案都成为一个培训范例。并且 convnet 给出该区域提议的特征向量。然后,我们可以使用特定于类的数据来训练我们的 n-SVM。
测试时间 R-CNN
在测试时,我们使用特定于类的支持向量机来预测检测盒。在测试的时候,我们会得到很多重叠的检测框。因此,非最大抑制是对象检测流水线的组成部分。
首先,它根据分数对所有检测框进行分类。选择具有最大分数的检测框 M,并且抑制与 M 有显著重叠(使用预定阈值)的所有其他检测框。
这个过程递归地应用于所有剩余的框,直到我们只剩下好的边界框。
https://www.pyimagesearch.com/wp-content/uploads/2014/10/hog_object_detection_nms.jpg
RCNN 的问题:
- 训练很慢。
- 推断(检测)慢。使用 VGG16 时每幅图像 47s——因为需要多次运行 Convnet。
对速度的需求。这么快 R-CNN。
2.快速 R-CNN
**💡所以来自同一作者的下一个想法:为什么不创建输入图像的卷积图,然后从卷积图中选择区域?我们真的需要运行这么多网络吗?我们可以只运行一个 convnet,然后对 convnet 计算的特征应用区域建议裁剪,并使用简单的 SVM/分类器对这些裁剪进行分类。
类似于:
来自论文:图为快速 R-CNN 架构示意图。快速 R-CNN 网络将整个图像和一组对象提议作为输入。网络首先用几个卷积(conv)和最大汇集层处理整个图像,以产生 conv 特征地图。然后,对于每个对象提议,感兴趣区域(RoI)池层从特征图中提取固定长度的特征向量。每个特征向量被馈入一系列全连接(fc)层,这些层最终分支成两个兄弟输出层:一个层产生 K 个对象类加上一个包罗万象的“背景”类的 softmax 概率估计,另一个层为 K 个对象类中的每一个输出四个实数值。每组 4 个值对 K 个类之一的精确边界框位置进行编码。
💡想法
所以 的基本思想是在图像中只需运行一次卷积,而不是 R-CNN 中的那么多卷积网络。 然后,我们可以使用某种方法映射 ROI 提议,过滤最后一个卷积层,并在其上运行最终分类器。
这个想法在一定程度上依赖于所用模型的架构。
所以作者提出的架构是:
**我们对三个预训练的 ImageNet [4]网络进行了实验,每个网络有五个最大池层和五到十三个 conv 层(有关网络详情,请参见第 4.1 节)。预训练网络初始化快速 R-CNN 网络时,要经历三次变换。首先,最后一个最大池层由 RoI 池层替换,RoI 池层通过设置 H 和 W 与网络的第一个完全连接层兼容来配置(例如,对于 VGG16,H = W = 7)。第二,网络的最后一个全连接层和 softmax(其被训练用于 1000 路 ImageNet 分类)被替换为之前描述的两个兄弟层(K + 1 个类别上的全连接层和 softmax 以及类别特定的边界框回归器)。第三,网络被修改以接受两个数据输入:图像列表和那些图像中的 ROI 列表。
如果你不了解以上内容,也不要担心。这显然有点令人困惑,所以让我们来分析一下。但为此,我们需要先了解 VGG16 架构。
VGG 16 Architecture
最后一个池层是 7x7x512。这是网络作者打算用 ROI 池层来代替的层。该池层获得了作为输入的区域提议的位置(xmin_roi,ymin_roi,h_roi,w_roi)和先前的特征地图(14x14x512)。
We need fixed-sized feature maps for the final classifier
现在 ROI 坐标的位置以输入图像为单位,即 224×224 像素。但是我们必须应用 ROI 合并操作的层是 14x14x512。
当我们使用 VGG 时,我们将图像(224 x 224 x 3)转换为(14 x 14 x 512),即高度和宽度除以 16。我们可以将 ROI 坐标除以 16,映射到特征图上。
在深度上,卷积特征图已经编码了图像的所有信息,同时保持了它相对于原始图像编码的“事物”的位置。例如,如果图像的左上角有一个红色方块,并且卷积层为其激活,则该红色方块的信息仍将位于卷积特征图的左上角。
什么是投资回报率池?
请记住,最终的分类器会针对每种作物运行。所以每种作物都需要一样大。这就是投资回报池的作用。
在上图中,我们的区域建议是 x,y,w,h 格式的(0,3,5,7)。
我们将该区域划分为 4 个区域,因为我们希望有一个 2x2 的 ROI 池层。我们通过舍入 5/2 和 7/2 将整个区域分成桶,然后只做一个最大池。
你如何在小于目标规模的区域进行投资回报池?如果区域提案大小为 5x5,投资回报池层大小为 7x7。如果发生这种情况,我们只需将每个单元格复制 7 次,然后最大合并回 7x7,就可以将大小调整到 35x35。
在替换了汇集层之后,作者还将 1000 层的 imagenet 分类层替换为全连接层和 K + 1 个类别上的 softmax(对于背景+ 1)和类别特定的边界框回归器。
训练快速神经网络
快速 RCNN 的输入是什么?
非常类似于 R-CNN:所以我们有一个图像,来自 RPN 策略的区域提议和标签的基本事实(标签,基本事实框)
接下来,我们将所有 IoU(交集/并集)与基础事实框重叠≥ 0.5 的区域提议视为该框类的正面训练示例,其余视为负面训练示例。这一次我们在上面有一个密集层,我们使用多任务损失。
所以每一个 ROI 都成了训练样本。主要区别在于多任务丢失有一个概念:
快速 R-CNN 网络具有两个兄弟输出层。
首先输出一个 离散概率分布 (每 RoI),p = (p0,。。。,pK),超过 K + 1 个类别。通常,p 由 softmax 通过全连接层的 K+1 个输出来计算。
对于 K 个对象类中的每一个,第二兄弟层输出 包围盒回归偏移 ,t= (tx,ty,tw,th)。每个训练 RoI 被标记有基本事实类 u 和基本事实包围盒回归目标 v。我们在每个标记的 RoI 上使用多任务损失 L 来联合训练分类和包围盒回归
Classification Loss + regression Loss
其中,Lcls 是 softmax 分类损失,Lloc 是回归损失。u=0 表示 BG 类,因此,只有当我们有任何其他类的边界框时,我们才会增加损耗。
问题:
区域提案仍然占据了大部分时间。我们能否缩短区域提案的时间?
Runtime dominated by region proposals!
3.快速 RCNN
下一个被问到的问题是:网络本身能做区域提议吗?
直觉是:使用 FastRCNN,我们已经在 CNN 中计算了一个激活图,为什么不通过几个层来运行激活图以找到感兴趣的区域,然后通过预测类+ bbox 坐标来完成向前传递呢?
区域提案网络如何运作?
论文中的一个主要观点是锚的概念。锚点是固定的边界框,以不同的大小和比例放置在整个图像中,在首次预测对象位置时将用作参考。
所以,首先,我们在图像上定义锚定中心。
Anchor centers throughout the original image
在 VGG16 网络的情况下,锚中心相隔 16 px,因为(14×14×512)的最终卷积层以因子 16(224/14)对图像进行子采样。
这是主播的样子:
Left: Anchors, Center: Anchor for a single point, Right: All anchors
- 所以我们从一些预定义的区域开始,我们认为我们的对象可能带有锚点。
- 我们的区域提议网络(RPN)对哪些区域具有对象和对象边界框的偏移进行分类。使用相同的逻辑完成训练。如果边界框> 0.5 的锚点的 IOU 为 1,否则为 0。
- 减少区域建议的非最大抑制
- 基于建议的快速 RCNN 检测网络
快速 RCNN 损耗
然后用 4 个损失联合训练整个网络:
- RPN 分类对象/非对象
- RPN 回归框坐标偏移
- 最终分类分数(对象类别)
- 最终框坐标偏移
表演
Results on VOC Dataset for the three different approaches
实例分割
现在是最有趣的部分——实例分割。我们能为图像中的每个物体创建 蒙版 吗?具体来说大概是:
Some images with masks from the paper
掩模-RCNN
同样的作者再次前来救援。基本思想是添加另一个预测遮罩的输出层。并使用 ROIAlign 代替 ROIPooling。
Source: Everything remains the same. Just one more output layer to predict masks and ROI pooling replaced by ROIAlign
Mask R-CNN 采用相同的两阶段程序,第一阶段(RPN)相同。
在第二阶段,与预测类别和盒子偏移并行,掩模 R-CNN 还为每个 RoI 输出二进制掩模。
ROIAlign 与 ROIPooling
在 ROI 合并中,我们会丢失基于位置的准确信息。看看我们是如何将我们的区域任意分成 4 个不同大小的盒子的。对于分类任务来说,它工作得很好。
但是对于在像素级别上提供遮罩,我们不想丢失这些信息。因此,我们不会量化池图层,而是使用双线性插值法来找出将提取的要素与输入正确对齐的值。看看 0.8 和 0.88 有什么不同
培养
在训练期间,我们将每个采样 RoI 的多任务损失定义为
L = Lcls + Lbox + Lmask
分类损失 Lcls 和包围盒损失 Lbox 与快速 R-CNN 中的相同。对于每个 RoI,mask 分支有一个 K × m × m 维输出,它对分辨率为 m × m 的 K 个二进制掩码进行编码,K 个类别中的每一个都有一个掩码。
为此,我们应用每像素 sigmoid,并将 Lmask 定义为平均二进制交叉熵损失。对于与地面实况类别 k 相关联的 RoI,Lmask 仅在第 k 个掩码上定义(其他掩码输出不会造成损失)。
掩模预测
掩模层是 K × m × m 维的,其中 K 是类的数量。m×m 浮点数掩模输出被调整到 RoI 尺寸,并在阈值 0.5 被二值化以获得最终掩模。
结论
祝贺你到达终点。这篇文章很长。
在这篇文章中,我谈到了对象检测和实例分割领域的一些最重要的进展,并试图尽可能简单地解释它们。
这是我自己对这些论文的理解,来自互联网上的许多博客和幻灯片,我真诚地感谢创作者。如果你发现我的理解有问题,请告诉我。
目标检测是一个广阔的领域,有许多其他方法在这个领域占主导地位。其中一些是优网,SSD 和 YOLO。
学习它们的资源并不缺乏,所以我鼓励你去看看它们。你现在有了坚实的后盾/理解。
在这个帖子里,我没有写编码和实现。因此,请继续关注我的下一篇文章,在这篇文章中,我们将为自定义数据集训练一个掩码 RCNN 模型。
如果你想了解更多关于各种 物体检测技术,运动估计,视频中的物体跟踪等 。,我想推荐这个关于计算机视觉深度学习的超赞课程。
谢谢你的阅读。将来我也会写更多初学者友好的帖子。在关注我或者订阅我的 博客 了解他们。一如既往,我欢迎反馈和建设性的批评,可以通过 Twitter @mlwhiz 联系。
此外,一个小小的免责声明——在这篇文章中可能会有一些相关资源的附属链接,因为分享知识从来都不是一个坏主意。
Spring Boot、Elasticsearch、Logstash、Kibana、PostgreSQL 和 Docker 的搭便车指南
最近,我决定开始创建一个 ELK stack 示例项目的旅程,该项目与 Spring Boot 和 PostgreSQL 一起工作——全部在 Docker 中,带有 docker-compose。没有 SaaS。尽管由于 ELK 的流行程度,任何给定的 web 框架都有许多示例项目,但在我看来,Spring Boot 并没有明确的终点线。
我的示例 Spring Boot 应用 spring-elastic-genie 有一个 REST API,它在 OMDB 寻找电影,并将结果保存在 PostgreSQL 中。这些结果然后被 Elasticsearch 索引,这时你可以在 Kibana 中可视化结果。你应该提前知道这是而不是一个如何编码的教程,而是在 Docker 中使用 Spring Boot 和本地 ELK 的高级架构概述。
如果您对进一步阅读不感兴趣,但是想要一个 GitHub 链接来查看一些代码,这里有一个指向我的示例项目的 GitHub 链接:
🧶This 项目将展示如何使用弹性搜索和弹性靴。— tech4242/spring-elastic-genie
github.com](https://github.com/tech4242/spring-elastic-genie)
但是我强烈建议你继续阅读,因为有许多陷阱和大量的教程不能告诉你整个故事;尤其是如果你来自一个非春天的背景(像我一样)。
我看到的所有教程都涵盖了如何使用 Spring 数据仓库直接写入 Elasticsearch,但它们没有涵盖如何使用生产中的 Spring Boot 应用程序,这些应用程序实际上将数据保存到诸如 PostgreSQL、MariaDB 等关系数据库中,相反,对于全文搜索等用例,需要搜索索引在之上。下面的部分解释了细微的差别以及它们背后的原因。
架构选项
选项 1:还有哪些“如何使用 Spring Boot 和 Elasticsearch”教程
好了,基本上这就是你在网上浏览关于弹性搜索和 Spring Boot 的教程时会发现的。您将拥有一个 Spring 数据存储库,允许您使用 ElasticsearchCrudRepository 接口直接向 Elasticsearch 写入数据,该接口是用于向 PostgreSQL 等普通数据库写入数据的 CrudRepository 的扩展。这一切都很棒,但只涵盖了现实世界用例的一小部分,因为很多时候你希望 Elasticsearch 索引你的主数据库,而不是像上面提到的那样。
所以,当你想直接写给 Elasticsearch 和 PostgreSQL 的时候,问题就来了。如果你想保持如上所示的架构,很遗憾只有一个选择*:每个模型有两个 Spring 数据仓库——一个用于 Elasticsearch,一个用于 PostgreSQL。这太可怕了。您只需要 2 倍的业务逻辑代码,而 Spring 不能在两个数据库之间进行事务管理,所以如果事务失败,您可能最终只能保存在 Elasticsearch 或 PostgreSQL 中(除非您想手动管理这些东西……),这首先违背了拥有搜索索引的目的。*
TL;如果您想同时写入两个数据库,这种方法并不好。没有什么比 Django + Haystack 方法更好的了,在这种方法中,你可以告诉 Elasticsearch 索引你的 Django 模型,然后你就完成了。
此外,您不能做类似以下的事情:
*public interface MovieRepository extends CrudRepository<Movie, Integer>, ElasticsearchCrudRepository<Movie, Integer> {
//...
}*
这将立即在运行时(而不是在构建时)给你一个错误,因为你正在覆盖 beans,缺省情况下是禁用的,但是启用它将没有帮助,因为你只能做两者之一(在单词中是 override)。这就是为什么你将坚持为每个 DB 拥有一个 Spring 数据存储库。除非你选择选项 2。
选项 2: Logstash 和更多抽象
这就是选项 2 的样子。本质上,Spring Boot 处于次要位置,我们使用标准的 CrudRepository 将数据保存到 PostgreSQL 中,然后我们开始使用 Logstash 将我们想要的所有交易从 PostgreSQL 记录到 Elasticsearch,从而从我们的 Spring Boot 应用程序中删除所有 Elasticsearch 代码,并消除代码复制的需要。选项 1 所需的代码在 GitHub 的每个文件中都被注释掉了。
这个项目的 docker-compose 包括 Spring Boot app、PostgreSQL、Elasticsearch、Kibana、Logstash 和 ElasticHQ (ES 监测服务)。这个设置会让你立刻与 ELK 和 Docker 一起运行。
如果你熟悉 Docker,这大部分都是非常基本的。一些亮点:
- Spring Boot 正在等待 PostgreSQL 的健康检查。这个 Docker 容器只是运行用 gradle 构建的 jar 文件。DB 连接的配置可以在 application.properties 中找到,它是从 core.env 文件中读取的。
- Logstash 在我的 GH 项目中为 JDBC 驱动程序和 logstash.conf 安装了两个本地文件夹
- Elastichq 实时监控 Elasticsearch,并且几乎可以开箱即用
- 所有这些都不能用于生产—只能用于开发!此外,如果在 AWS 上用作 SaaS,ELK 也相当不错,但我想展示如何实现内部开源路径。GitHub 上的 README 中进一步描述了该配置。
- Logstash 免责声明:目前 Logstash 仅配置为通过简单的 SQL 查询从 PostgreSQL 获取数据,但它没有针对重复等的过滤器。有许多 Logstash 教程可以用来过滤数据。
随机陷阱
- Logstash 7.2.0 与许多 JDBC 驱动程序不兼容,你需要将 Logstash 与 Elasticsearch 连接起来。相反,我恢复到 7.0.0。在这上面浪费了这么多时间。最后在 pgjdbc GH 页面上打开一个问题,却发现这是一个 Logstash bug 。
- 弹性搜索 7。x 与 spring-data-elasticsearch 不兼容,后者是通过使用 spring 的数据仓库将数据保存到 elasticsearch 中。支持的最新版本是 6.7.2,但 Kibana 的是 7。x 有黑暗模式,我想在这篇文章中的一些黑暗模式截图。因为黑暗模式。:)你可以在 GitHub 上关注他们的发布。
幸运饼干的故事
选项 2 有点违背了为 Spring Boot 和弹性设计一个专用指南的目的,对吗?也许是,但也许不是。由于选项 1 最终变得有点混乱,这应该突出了您可以用现有项目做什么,而不需要彻底检查您的整个 Spring 项目来编写 Elasticsearch。此外,问问自己是否需要 Elasticsearch。另一个直接与 PostgreSQL 一起工作的索引能完成这项工作吗?PostgreSQL 本身能很好地完成任务吗?如果对这些问题的回答是“不”,那么选项 2 应该会带来最少的麻烦。
我希望这篇教程能够让你开始你的 ELK stack 之旅(也许甚至可以用 Docker ),这样你就可以少担心你的 Spring 应用程序,多关心如何充分利用 Elasticsearch!
最重要的是:不要惊慌;)
一种混合神经机器翻译模型(Luong & Manning);
Luong & Manning 最近发表了一篇题为“用混合单词字符模型实现开放词汇神经机器翻译”的论文其内容我总结如下。
要快速总结神经机器翻译(NMT)的现状,你可以快速看一下我的另一篇文章这里
目前,通用的基于单词的 NMT 为输出中的罕见单词生成,然后应用后处理步骤,通过使用来自它们的注意力机制的对齐信息,经由简单的单词字典查找来处理这些未知标记。这种方法存在 1)字母不匹配和 2)多词对齐的问题
添加一个字符组件。
Luong 和 Manning 通过在当前的编码器-注意力-解码器架构中使用基于核心单词的 NMT 来解决这个问题,但他们没有将所有罕见的单词都视为<unk,而是添加了一个字符组件,以每个字符为基础对它们进行编码:
Luong, Manning, “Achieving Open Vocabulary Neural Machine Translation with Hybrid Word-Character Models.”
在这个图表中,“可爱”是一个罕见的词。因此,它被分解成字符,并通过“c”、“u”、“t”、“e”和“_”(边界符号)输入到基于字符的深层 LSTM 中。最终的表现,隐藏状态,在顶层,然后取代了“可爱”的。
每当单词级 NMT 产生一个< unk >,你就可以参考这个字符级解码器来恢复未知目标单词的正确表面形式。
这在纯字 NMT 上提供了以下改进:
1)更快更容易训练(无后处理步骤)
2)从不产生未登录词
相对于现有技术的结果:
在 WMT 的 15 个英语-捷克语翻译任务中,与其他 NMT 模型相比,混合神经机器翻译模型获得了+2.1–11.4 BLEU,最好的系统获得了最高的 20.7 BLEU。它还获得了更高的 chrF3 分数。
基于字符的模型,用于取代纯粹的< unk >技术,对 BLEU 分数贡献最大,在 10k 词汇上为+2.1 BLEU。
Figure 3. Vocabulary size effect
Table 1. Experiment results
结论
本文提出的混合体系结构结合了基于单词的模型和基于字符的模型,前者速度快且易于训练,后者能很好地处理未登录词,从而产生更高质量的翻译。本文还展示了纯基于字符的模型的潜力,尽管它的训练速度非常低。因此,可能需要做更多的工作来提高基于角色的模型的速度。
最初发表于“使用混合单词-字符模型实现开放词汇神经机器翻译”
Minh-Thang Luong 和 Christopher D. Manning,加利福尼亚州斯坦福市斯坦福大学计算机科学系,邮编:94305
人工智能和人类的自我异化
Photo by Andy Kelly on Unsplash
“我们是谁?”是一个永恒的问题,无法用单一的特性来回答,因为我们不是任何一个事物。正如我们所知,我们是许多东西,许多文化,许多社会,许多制度,许多规范,许多关系。我们是善与恶,养育与威胁,聪明与愚蠢,明智与愚蠢。简单地说,我们是人类,我们有智慧。
那么,什么是智能呢?智力是多方面的。什么被认为是智慧会随着时间的推移而改变,并且会因环境和文化的不同而不同。与美国流行文化对待它的方式相反,智力是流动的,而不是固定的。它的评估依赖于上下文。
没有对这种本体论问题的固定答案,人类对一般(不同于狭隘的、特定任务的)人工智能(AI)的追求是一种既傲慢又天真的练习。建立一个神经网络可能接近于一个精心设计的大厦中的建筑,但它的结果是一个格式塔表达式。正如我们的身体大脑,在我们头骨的立方英寸内,产生意识和主观体验的奇迹,感觉大于其各部分的总和。
由于我们被文化所影响,很容易把特殊误认为一般,把特殊误认为普遍。例如,随着时间的推移,主要在美国设计的心理测量智力评估已经尽可能地得到完善,以一种纯粹个性化的方式获取智力。我们对智力(以及更多)的理解已经开始通过个人主义文化来理解。
问题是,真空中没有智能这种东西。即使有,也没什么用,因为应用的是智能。人类不是一直在一起努力建造经得起时间考验的东西吗?即使是做出重大发现的科学家这一(正确的)被看重的人物也经历了一个系统的教育,并定期与同事磋商。以一种纯粹个性化的方式评估智力对谁或什么最有利?除了特定社会秩序的合法化和维护,个性化测试的构建、验证、管理和依赖还能获得什么?
在当前对广义人工智能的狂热追求中,我们冒着梦游般自我淘汰的风险。通过相信收益将超过负担来淡化人工智能的风险,如果当一个广义的人工智能实现并上线时,那就太晚了。
对人工智能问题的批评方法在内容上可以不同于陈词滥调的悲观主义。我们最大的恐惧并不一定是暴力的终结者或黑客帝国场景,导致悲剧的仿生活艺术情节扭曲。尽管在可能性的范围内,而不是采取一种向外看的姿态,看着机器,思考它的力量,我们应该通过向内转向,提出问题来批判对人工智能的盲目追求。例如,人工智能(以及我们对它的追求)告诉我们关于我们自己的什么?AI 的梦想从何而来?其诉求的语境是什么?
Self-entanglement. | Photo by Artem Kim on Unsplash
资本主义现代性
对人工智能的追求来自我们的当代历史——先进生产的晚期资本主义时期。从机械和技术中可以想象出一个乌托邦世界,在这个世界中,生产完全自动化,留给人类自由的时间——这个梦想就这样实现了。我们这个时代的生产、分配和消费的现实,以这种方式为我们想象力的扩展创造了真实、具体的基础。
抛开完全自动化的梦想不谈,资本主义现代化时期产生了自身特有的社会生活形式。日常现实被认为是理所当然的——例如,关于个人自由/企业家精神和市场中达尔文式竞争的想法。这些真理看起来具有普遍的、超越历史的有效性,但实际上是资本主义时代特有的社会生活的各个方面。它们是人类创造和提炼的一般经验的一部分,是这个系统维持和繁殖所必需的。
资本主义现代性的一个显著特征是异化。当人们去工作时,他们必然会将他们原本的个人自由置于工作场所的等级和专制结构之下。人们与他们的劳动产品分离,无论是服装制造还是一行代码。我们的劳动属于他人。这是他人的财产,是我们大多数人认为理所当然的生活的基本特征。最近,泰勒·斯威夫特相当公开地疏远了她的工作当音乐执行官斯库特·布劳恩购买了她的整个旧目录时,尽管,正如作家诺亚·伯拉特斯基所指出的,她是自己作词和音乐的作者,也是她自己的动力。根据 Berlatsky 的说法,Swift 与其他人的区别在于
大多数人不仅不拥有自己的劳动,而且在文化上也不具备拥有劳动的能力。斯威夫特可以说,“我应该拥有我的专辑,”这很有道理。但是如果一个装配线上的工人说,“我应该拥有我的汽车”,或者一个沃尔玛的员工说,“我应该拥有我的商店”,他们得到的公众支持会少得多,因为他们认为他们甚至可以找到任何人来倾听。
这些权利和工作成果的分离是现代世界中异化活动的形式。然而,我们可以说,今天的人们比以前的社会遭受的公开统治要少得多*(我们不受封建地主的摆布,尽管我们中的许多人会被我们的城市地主驱逐出去)。然而,正如已故马克思学者Moishe Postone所言,“只考虑个人依赖性和独立性问题的自由可能会掩盖更为普遍的不自由形式的存在……”(2015 年,第 8 页)。然而,作为个体,我们不得不做我们必须做的事情来生存。正是这种以现代性的他律史为特征的抽象异化形式,将资本主义与以前的社会形态区分开来。*
21 世纪的异化起着破坏性和破坏性的社会作用。它同时是具体的和抽象的,由直接的社会活动决定,并作为一种模糊的、不可描述的社会统治形式被体验。它的一个分支是围绕人工智能发展的集体不响应——也许是因为我们想象一个我们自己创造的、独立于我们的存在,比我们允许自己成为的那种人更完整。
简而言之,异化是指将人从其本性中分离出来的关系。工作和创造是人类的天性,然而我们却与之分离。生产是我们的天性,但我们与我们的产品分离,无法控制我们创造什么,如何处理我们的创造。我们变得彼此分离,被迫参与竞争和各种形式的敌意,大部分时间都在课间度过(见办公室中的虚构例子,以及每天都在发生的为生活工资和安全工作条件而斗争)。通过这种分离和隔离,现代社会中的绝大多数人被降低到最低的共同标准,失去了最初使他们成为人的特殊品质。通过彻底异化的生活形式,人类变成了“抽象的”,个体化的,孤立的,与任何超越表面共性的社会整体都没有联系。根据 NYU 大学政治学教授 Bertell Ollman 的说法,异化是“这一过程在很大程度上说明了货币在资本主义社会中的力量,即购买那些如果它们仍然是生产者的组成部分就永远不会被出售的物品”(1976 年,第 135 页)。
鉴于我们当前世界的结构,人们开始质疑现状就不足为奇了。我们今天所认识的自由是片面的、浅薄的。如果一个人“选择”不工作,他就有挨饿的自由——这种选择本身就是错误的。相反,我们被迫从事报酬过低的劳动,并被告知我们是自由的。在这种情况下,可以理解的是,会存在一种对完全智能和有能力的机器的集体渴望,这是一种解放我们的工具。我们想赋予一个合成生物超越自身局限的能力,让我们摆脱苦差事,而我们却在当前条件下系统地否认自己拥有同样的能力。我们所知的人工智能等同于外包人性,因为我们已经疏远了自己。
Urban assembly line. | Photo by Alex Kotliarskyi on Unsplash
很长一段时间以来,在各种情况下,人类一直梦想着与智能机器人共存——这些机器人没有睡眠时间表,肌肉不会疲劳,大脑不会疲劳。抛开想象力不谈,尽管有杰出的怀疑论者,迈向通用人工智能的竞赛正在被推销,仿佛它的成就将带来某种未指明的解脱,由寻求赚取惊人利润的公司带给你。我们有多年的技术进步。节省时间和劳动力的技术的扩散并没有解放任何人的时间,也没有让我们减少工作。
在最近的一次采访中,劳工组织者萨姆·金丁指出,在资本主义中,例如,如果工厂工人被给予工厂的控制权,工人们将不知道该做什么。资本主义不关心发展普通人的能力。它只教特定的人(历史上,白人男性)在特定的班级地点如何协调,管理和经营任何事情,绝大多数人只是做他们被告知的事情。为什么一个被系统剥夺权力的人会同意在解除自身权力之前创造一个理论上无限的智能?在这样的条件下会发展出什么样的智力?
我们对智能机器人的愿景是资本透过我们支离破碎、疏离的生活所投射出的想象。想象我们之外的东西比我们自己更有人情味,具有我们显然缺乏的革命潜力,已经变得更容易接受了。我们更容易想象构建一个比我们自己更“人”的有感知能力的机器人,因为我们已经失去了认识自身更伟大人性的能力。
人工智能非军事化不会发生
人工智能已经被集成到下一代防御系统中,它的非军事化是极不可能的。无论如何,限制其用于军事用途可能不是最明智的策略。
Photo by Rostislav Kralik on Public Domain Pictures
今年的世界经济论坛年会即将开幕。在浏览今年的议程时,我不禁想起了去年对谷歌首席执行官孙戴·皮查伊的采访,他非常坦率和乐观地谈到了他对人工智能如何改变人类运作方式的根本方式的设想。
事实上,思维过程的自动化,结合高速通信网络、即时可用的数据和强大的计算资源,有可能影响社会的所有机制。人工智能将在医疗、教育、能源供应、执法、经济和治理等领域的决策、日常运营和自动化中发挥关键作用。
像大多数其他创新一样,每一项技术进步都可能被滥用于邪恶的目的,人工智能也不例外。让大多数人害怕的是它难以捉摸的本质,它是一个如此广阔的领域,并且在如此多的科幻情节中扮演着核心角色,以至于没有很好的结局。
在他的采访中,Sundai 试图通过建议各国应该解除人工智能的武装来平息这种担忧。当然,人们应该结合上下文来看待这些评论。但是期望所有国家都这样做就像期望人类完全停止战争一样。
我强调而非的原因是,只需要一个国家就能造成失衡。如果朝鲜决定在其洲际弹道导弹中集成人工智能以实现高精度自主制导会怎样?期望美国不做同样的事情来应对这种威胁现实吗?又是一次同归于尽。
在这种情况下,只有当双方都采取更具侵略性的优势策略并且对手进行报复时损失更大,你才能达到纳什均衡。人们会期望世界上最大的人工智能公司之一的首席执行官至少知道博弈论的这样一个基本概念。
Photo Credits Wikimedia Commons
但是 Sundai 当然完全意识到了这一点。他对人工智能应用的和谐的国家间和平合作的乌托邦式的愿景,正符合他的雇主的议程。具有讽刺意味的是,这发生在同一年年初,当时其“不作恶”的座右铭被删除,其自己的员工罢工抗议其参与军事项目,人们开始严重关注他们的私人信息的可用性和滥用,如电子邮件和手机数据。
保持对立双方的力量平衡已经是不要对一方施加限制的足够好的理由,而没有任何具体的保证另一方实际上也在这样做。但是这里有更多的原因为什么人工智能非军事化不会发生,以及为什么我们可能一开始就不希望它发生。
资助
国防预算推动了西方国家的大量研究和创新,在这些国家,强大的军事能力被视为至关重要。他们不仅资助导弹和隐形战斗机的建设。他们支持一些想法的发展,这些想法通常还没有任何商业模式,但在竞争国家出现之前仍然值得拥有。当然,更有可能的是,具有明确军事用途的想法会得到国防预算的资助。但是像互联网(最初是阿帕网)和全球定位系统(最初是国防项目)这样的技术最终被公之于众。
自动驾驶汽车可能因谷歌的自动驾驶汽车项目(现为 Waymo )而变得更受欢迎,但实际上这是美国国防高级研究计划局(DARPA)的大挑战的结果。然后,谷歌从赢得 2005 年挑战的团队中招募人员。DARPA 还举办了一场机器人挑战赛,目标是开发能够在对人类有害的环境中执行危险任务的人形机器人。人们只需要回忆一下切尔诺贝利和福岛的灾难,以及人们在放射性环境中工作的后果,就能意识到这种技术有多么有用。
JPL’s RoboSimian at the DARPA Robotics Challenge
DARPA 非常重视人工智能,其他国防组织也是如此,比如 BAE 系统公司和泰雷兹公司。期望军方袖手旁观,与人工智能保持距离是完全不现实的。
人工智能可以减少(双方的)伤亡
在军事上使用人工智能的一个主要担忧是杀手机器人的发展。这是一个合理的担忧,需要通过正确的政策和条约来解决,尽管我怀疑如果技术组件可以获得,任何国家都会公开承认拥有自主武器(直到它被迫拿出并使用它们)。此外,如果一个国家有可能获得这样的技术,那么让竞争环境失衡可能是一个非常糟糕的主意。
鉴于人工通用智能距离还很遥远,而且不太可能出现“终结者式”杀手机器人,也许我们应该更关注人工智能的眼前利益,比如战场智能。如果一个士兵的护目镜配备了增强现实,使用人工智能来识别朋友和敌人,或者平民和威胁,比肾上腺素分泌过多担心自己生命安全的人类更准确,会怎么样?自主装甲车可以用于高风险的任务,比如通过敌对路线运送物资,或者从活跃的战区营救伤员。机器人可以陪伴士兵,帮助他们调查威胁或搬运重型设备。
Photo by Sgt. Eric Keenan
如果导弹制导系统配备了在爆炸前验证目标的机载算法会怎么样?“外科手术式打击”只会击中预定目标,而不会造成附带伤害和无辜平民死亡。利用人工智能来跟踪和拦截空中威胁,甚至在它们实际发射之前检测它们的更智能的防空系统怎么样?
人工智能没有很好的定义
大多数人工智能技术涉及处理数据流,应用微积分、概率和统计等数学技术,并使用少量算法将它们放在一起以达成解决方案。没有什么真正的认知、感知或自我意识在进行。
与核武器不同,你可以清楚地确定一个国家是否有库存(假设你能找到它们),没有明确的方法对集成在各种防御系统中的软件技术进行分类。此外,人们不能真正指望军方不使用它所拥有的数据和计算资源来获得更快、更智能和机器验证的决策支持,而普通公众对它了如指掌。人工智能非军事化不会发生。
约瑟夫·巴加达 拥有计算机科学博士学位,专门研究计划和调度的人工智能技术。他是一名技术顾问,为物流和油田技术应用开发人工智能解决方案。上述文章中表达的任何观点纯属其个人观点,不一定代表任何附属机构的观点。
A.一.加强分子发现和优化
召集所有科学家和开发者
我们正处于一种新的科学方法的边缘,这种方法利用人工智能的力量来加速科学发现的发展。
“在过去几年中,实验和模拟产生的大量数据催生了第四种科学范式,即数据驱动科学,它统一了理论、实验和计算/模拟的前三种范式。”—西北大学的安基特·阿格拉瓦尔
A visual representation of science (colorized, circa. 2003)
科学常常会像一根泥棒,因此理论和实验科学的前两种范式被证明是缓慢的或两个原因:
- 理论知识缺乏经验证据**(第一范式)**
- 实验中人类偏见的丰富程度**(第二范式)**
然而,计算机改变了科学游戏,我们开始充分欣赏这些不可思议的设备带来的准确性和速度。计算和模拟的第三范式是一个很有前途的范式,但是受到当时技术的限制。这将我们引向第四种范式。
第四范式利用了计算范式的数字副产品:数据。数据科学虽然不是一门精确的科学,但可以带来如此高的性能和准确性,以至于它们经常可以识别我们尚未用科学发现的新方法、方程和想法。
这就是计算机如何以及为什么能够:
- 击败世界上最好的国际象棋、围棋和 DOTA 玩家
- 发现新的药物、材料和分子
- 翻译语言,驾驶汽车,交易股票
这个名单每天都在增长。他们能比我们更好地做这些事情,*和做一些我们不能做的事情,*,**与 ,,只是数据和一个模型/架构。它需要的唯一等式、直觉或知识是通过观察数据中的模式产生的。
图案在化学和材料科学中非常普遍。从钻石的晶体结构到脂质的支链,这些模式定义了分子的各种性质。识别这些模式并从中学习是人工智能的责任。尽管有一些挫折,比如没有足够的数据用于训练,人工智能非常适合分子发现的问题。今天,处于科学前沿的研究人员开始转向人工智能,以获得更高效、更准确、更多样化的结果。
A.I can do it better (Photo by Franki Chamaki)
我为什么要在乎?
仅仅几十年后,对更坚固的建筑材料、更耐久的电池和更个性化的药物的需求将会增加。我们 T2 满足这些需求的能力取决于研究人员能以多快的速度向试图解决世界上最大问题的公司提供合适的材料。如果链条的强度取决于其最弱的一环,那么:
“创新和进步的速度与我们发现和优化材料的速度一样快”
历史被定义在那个时期主要使用的基本材料上。石器时代、青铜时代和铁器时代,也就是我们今天生活的硅时代的前身。明天我们可能会发现自己处于碳时代。总的来说,我们不能等待这些新的科学时代,但一个新分子到达大众仍然需要几十年的时间。答:我想知道我们将如何弥补差额。
每年,使用最新和最棒的机器学习工具的研究论文数量都在增加。从 强化学习增强的递归神经网络 ,到 生成式对抗性自动编码器 ,还有其他的 A.I 恶作剧,这将是一个十年的狂野时代。
如果这是你第一次接触人工智能,太棒了!希望这能给你一张 A .在不久的将来我将去哪里的照片。如果你是化学家、物理学家或生物学家,那太好了!这个领域的每个人都同意的一件事是需要意识到可能性。如果你是一名开发人员或机器学习者,那么欢呼吧!将是你塑造明天的世界。
厉害!但是我们如何到达那里呢?
处于各自领域前沿的研究人员一直在尝试使用我们手头现有的工具来解决这个问题。当前研究的工作方式有一个模式,同样的一般过程适用于任何基于人工智能的科学项目。
研究人员是木匠,这些是材料、工具和指令。
Crafting the perfect molecule (Photo by Barn Images)
首先,我们需要一些高质量的木材…
我们需要数据。更重要的是,我们需要干净的、有标签的和丰富的数据。这些数据必须用计算机能理解的格式来表示。谢天谢地,我们正好有这个东西;简化的分子输入-行-输入系统(SMILES)字符串。
微笑串是计算机可以解释分子的四种方式之一。按照从最低到最高(因此从最简单到最复杂)的顺序听:
- 分子指纹(特定长度的数字序列)
- 字符串表示(描述结构和组件的符号)
- 分子图(与数据结构中的树和图的概念相同)
- 模拟(下一级的东西。说够了)
Pick your poison: molecules like drugs reap the benefits of being represented by all 4 formats
90%的研究项目使用 SMILES 字符串表示,尽管有争议的是像 SMARTS 这样更适用的格式。这是因为它在准确性(就表示给定分子的细微差别而言)和复杂性(就计算机解释数据的容易程度而言)之间取得了平衡。字符串本身看起来有点像化学胡言乱语:
C/C=C/C=C/C
OC(=O)C@@HC
CCc1c[n+]2 CCC 3c 4 cccc 4[nH]C3 C2 cc 1
它们看起来有点像典型的高中科学课上教授的化学式。这是因为每个微笑串是由给定分子的分子图的深度优先树遍历生成的。所以在某种程度上,微笑字符串是一个分子的公式,更详细地拼写出来。
SMILES 字符串数据最好在被清理后使用。这包括规范化、(同一个分子可以有多个微笑字符串)、以及去重。你可以把它想象成从木头上移除碎片。这样工作起来更容易也更安全。
当然,计算机不会按字母顺序思考;它用数字思考。因此,我们必须将所有这些字母、符号和字符转换成整数表示、二进制指纹、一键编码或任何其他计算机可以消化的数字格式。
现在我们需要一把锤子和一些钉子…
我们需要工具来处理数据。在机器学习中,这些工具是各种算法,每种算法都用于预测、分类、生成、回归等。每种工具都有不同的用途,因此针对正确的问题选择正确的工具非常重要。在科学领域,机器学习在任何项目中的应用都可以分为以下两类:
正向模型:用于属性预测
或者
逆模型:用于分子发现/优化
*模型的类型不同,但输入和输出保持不变。*在正向模型中,分子是输入,属性是输出。在逆模型中,这是颠倒的;属性是输入,分子是输出。
有相对简单类型的机器学习模型,如线性回归和 K-最近邻,还有更复杂的算法,如决策树和森林。有时这些工具就足够了,但是如果有足够的数据,可以考虑更强大的模型;神经网络。
神经网络是机器学习算法的瑞士军刀。神经网络可以分类、预测、生成、降低维度等等,这要归功于矩阵乘法的魔力和一种叫做“反向传播”的超级特殊学习算法。
神经网络本身有不同的架构,每种架构都针对不同的目的进行了优化。递归神经网络(RNNs)是操纵时间序列数据(如文本)的完美工具,或者在分子的情况下,意味着微笑字符串表示。rnn 是多用途的,可用于预测属性(输入微笑字符串分子和输出属性)或生成分子(输入属性和输出微笑字符串分子)。
我们需要建造这东西的说明书…
我们现在有了建造新东西所需的材料和工具!我们只需要知道更多的细节。这些细节被称为超参数,如神经元的数量、层数、学习速率等。**超参数告诉我们如何使用我们的工具(机器学习算法),来处理我们的木材(数据)。**很多时候,指令是由木匠和他们的直觉决定的。作为架构师,您的工作是决定一些超参数值,而其他值是在培训过程中学习到的。
But when you do, choose wisely. (courtesy of Daniel Shapiro)
这些参数对模型的结果有很大的影响,所以选择一个好的起点取决于机器学习者的直觉和经验。**成功与失败的区别往往在于单个超参数的变化。**优化就是改变这些超参数,直到模型的最终输出尽可能精确。
我们将不得不选择我们的损失函数(我们决定我们的模型做得好或坏的方式)。还有大量的激活函数可供选择(当在神经网络的每一层之间传递时,保持值不变。发展如何选择所有这些超参数的直觉需要理解每个选择如何以及为什么起作用,有时你只需要猜测和检查!
我真的需要一把锯子和一些抛光机…
木匠的工作不仅仅是建造东西;让它看起来像样也是他们的工作。因此,最后一步是以综合的格式返回模型的输出。
在正向模型中, 这意味着用适当的测量单位最准确地呈现给定材料的属性。
在逆模型中, 这意味着以正确的微笑字符串符号呈现生成的分子。
我们有办法提高产品的光洁度。特别是在寻找潜在的候选药物时,这是最危险的阶段。不进行实际测试就无法知道一个分子是否稳定,这就是为什么确定性和误差率在科学中如此重要。这是许多研究人员在他们的原始模型上使用另一个附件的地方。**找到一劳永逸的解决方案非常罕见,也没有灵丹妙药。**分子发现的良好解决方案实现了多种机器学习算法,也称为集成算法。
发布架构(玛利亚·波波娃等人)结合了 RNNs 和强化学习技术。RNN 由两个不同的网络组成,它们产生有效的分子。强化训练然后将这些结果偏向期望的属性。
ECAAE 架构 ( Daniil Polykovskiy 等人)首先将自动编码器的潜在分布码从属性中分离出来,然后修改潜在码以匹配先前的分布码。这是用一个对抗性的网络来训练的,直到鉴别者不再能够区分潜在的和先前的。
有机架构(Benjamin Sanchez-Lengeling等人)使用带有强化学习技术的生成式对抗网络(GANs)。与释放架构类似,GAN 会在强化学习(称为“目标强化”)将输出转向所需属性之前生成有效的分子。
大概就是这样
我要真实世界的证据!!!
这个一般化的过程不是来自直觉,而是来自两个派别慷慨提供的大量论文、项目和案例研究中开发的模式;学术界和工业界。
大学研究
前面提到的架构,如 ReLeaSE、ECAAE 和 ORGANIC,都是有监督的深度学习的最新例子。这些创新背后令人难以置信的机构是一些世界顶尖大学。
哈佛大学
像“什么是高通量虚拟筛选… ”这样的论文,还有前面提到的有机架构,都是来自世界排名第一的大学。哈佛的清洁能源项目是将人工智能推向前沿的研究的一个例子。贡献者包括来自化学、人工智能、数据科学和许多其他领域的人。如果我们要继续发展这些领域的应用,这种合作是必要的。
剑桥大学
简单的“材料科学的机器学习”是一篇深度论文,涵盖了该领域所有的最新创新。剑桥也是非常特殊应用的地方,比如使用神经网络的合金概率设计。随着像 Deep Mind 这样的公司进驻英国,剑桥继续推出优质内容也就不足为奇了。
西北大学
数据驱动科学的整体理念是西北大学近期工作的一个亮点。从用于分子发现的高通量密度泛函理论到通过递归神经网络预测定向能沉积过程中的高维热历史的研究都源于西北大学进行的研究。
创业公司和公司
我的导师纳维德·纳图给了我一个很好的建议;
“当人们愿意为解决问题付费时,问题就变成了机会;必须有一个经济激励。”
如果没有钱,到目前为止的一切都是一个有趣的科学项目,听起来很酷,但从商业角度来看毫无意义。话虽如此,这里有一些公司,或大或小(它们的规模应该说明有多少经济激励),正在寻求改变。
One of the leaders of the industry specifically in cheminformatics
黄水晶信息学
这家位于旧金山的不可思议的公司在分子发现和优化研究领域取得了长足的进步。我要特别强调他们的操作方法。Citrine 明白,就数据的规模、质量和一致性而言,科学界不像其他领域那样享有特权。我们可能有大量的图像、文本和音频数据集,但你很难找到一个可靠的碳分子数据集,更不用说清洁或标记了。
Citrine 通过利用尽可能多的技术来解决的“小数据”问题。像数据扩充、迁移学习和堆叠架构这样的技术从现有数据集中榨取每一盎司的价值。
IBM 研究
对财富 500 强公司如微软、脸书、谷歌,尤其是 IBM(谁还记得 IBM 代表什么?).自从在计算领域的竞标中失利并错失移动业务后,IBM 已经将注意力从正在发生的事情转移到了将要发生的事情上。今天,IBM 仍在努力保持相关性,但不再是我们曾经认识的计算机公司,而是一家量子计算、人工智能研究和技术创新公司,希望在不久的将来东山再起。
最近,IBM 发布了一个预测化学反应的免费工具,根据大多数此类项目,SMILES strings 是选择的分子表示。有了化学反应的两百万个数据点,人工智能设法得到了相当精确的结果。
谷歌研究
不出所料,这家世界上最有影响力的公司碰巧也把手伸向了饼干罐。谷歌的人工智能研究有一个名为谷歌加速科学的特别团队,他们致力于计算化学和生物学,目标是推进科学研究和加速科学创新。他们与 Deep Mind 合作过几次,推出了令人兴奋的作品。
传言他们最近的工作涉及使用 4 种可能的分子表示中的第 3 种;分子图。这是他们研究的自然结果,因为几何深度学习开始普及,其好处变得更加明显。谷歌一贯发布他们的研究出版物,有时还会发布他们的相关代码。密切关注新闻,如果有人能够完成下一件大事,那就是谷歌。
关键要点
- 我们现在正进入科学的第四范式,一个由数据驱动而不是理论、实验或计算的范式
- A.我是这一变化将如何影响科学以及对社会意味着什么的决定性因素
- 当前的研究遵循一个过程,并且局限于人工智能中当前可用的工具
- 目前学术界和工业界正在解决许多现实世界中的问题,而且这种问题还在不断增加
The future is bright (courtesy of the Science magazine)
接下来会发生什么
Chamath Palihapitiya 认为,虽然谷歌可能是搜索数据的大师,脸书可能是通信数据的大师,亚马逊可能是消费主义数据的大师,还没有一个明确的医疗保健数据、分子数据和许多其他增长领域的大师。
搜索、通信和消费主义数据华而不实,表面上很重要,但没有足够的人来解决世界上最棘手的问题。
人工智能可以改变这一点。
你可以改变。
需要看更多这样的内容吗?
跟我上LinkedIn, 脸书 ,insta gram,当然还有 中
我总是希望结识新朋友、合作或学习新东西,所以请随时联系 flawnsontong1@gmail.com
人工智能:寻找价值
将塑造现代经济的革命联系起来
我们越来越多地看到轰动效应和行话阻碍了关于人工智能的建设性对话。要认识到人工智能能为我们做什么,我们必须提出有针对性的问题,并充实其实际价值。
我将交替使用人工智能和机器学习。机器学习是人工智能的一个子集,指的是建立统计模型,通过发现和推断数据中的模式来执行任务。数据科学是从数据中提取知识,它使用机器学习技术。
人工智能是一个模糊的术语,也是一个移动的目标——用于描述所有类型的模拟智能行为的技术。这些术语是相互关联的,有时会被归入人工智能的范畴。
我们为什么要谈论它?
它对我们的生活产生了巨大的影响。
作为有眼光的消费者,我们需要知道我们的数据是如何被使用的。YouTube 和脸书算法比我们最好的朋友更了解我们的偏好。从我们的交易中,银行知道我们何时搬家,家中有了新成员,以及我们喜欢什么品牌。我们在网络物理空间采取的每一个行动都会产生数据。这些数据被用来模拟我们的虚拟复制品。
这是变革的驱动力。
我们正在经历日常看不到的指数级增长。互联网上市还不到 8000 天。在那个时期,我们看到了数十亿的超链接,数万亿的搜索,最大的开源百科全书的创建;观看和分享视频的平台,以及将你与食物、交通、商品和服务联系起来的应用程序。难道我们过去的统治者不会为了这种神奇的力量而开战吗?
在一代人的时间里,互联网用户的数量从少数科学家增加到 39 亿——占世界人口的一半。增长率不是线性的;是指数级的。这是问题“你宁愿有一百万美元,还是一便士的总和在一个月内每天翻倍?”中暗示的几何级数从一便士开始,你会在第三十天得到 530 万美元。
人工智能革命正处于第一天。我们将越来越多地看到智能渗透到我们生活的方方面面。
它正在创造巨大的价值。
人工智能几乎颠覆了所有行业。很少有技术把人类的经历分成两部分:在它被发现之前,和之后;一些科学家认为人类的下一个这样的发明是人工通用智能。想象一下,一个实体可以像人类一样解决许多领域的问题,只是在访问海量数据时速度要快得多。这可能是我们最后的发明了!
我们所说的人工智能是什么意思?
人工智能的主要领域是:
● 自然语言处理:虚拟助手、聊天机器人
● 计算机视觉:照片标记、X 射线诊断、自动驾驶汽车
● 数据科学和分析:推荐、预测等。
● 机器人和传感器:工业机器人、智能设备、家庭和信息物理系统
我们的人工智能用例中有三种机器学习算法。它们是:
● 监督学习:通过向机器展示大量输入和响应的例子来教它“学习”。
● 无监督学习:输入数据,让机器识别模式
● 强化学习:不给机器任何数据,而是让它在一个环境中自由活动,让它通过试错来学习。
这些算法可以用来创建机器学习中的某些工具。大多数用例可以简化为以下一项或多项:
人工智能能做什么?
人工智能不是魔法。原因:
●需要大量高质量的数据
●非常容易受到对抗性攻击。
●有许多不遵守人工智能安全和道德原则的使用案例。
然而,这不应该阻止人们尝试不同的模型和用例。我们可以认为用例属于三个类别:
1。改进现有功能
看看你的产品/服务的每个特性,然后问自己,“这个特性试图最大化/最小化什么?
示例:假设您手动处理客户支持请求。您收到的大约 80%的查询都是您以前见过的查询——这些可以而且应该是自动化的。您可以在几天内部署一个简单的 FAQ 聊天机器人,如果不是几个小时,并节省数百个小时。如果客户请求需要专门的支持,则将其重定向至人工。拥有聊天机器人还有另一个好处——你可以挖掘客户支持数据,识别客户痛点,提高你的业务质量。
2。创建新特征
写下一个流程中的每一个活动,问有哪些功能可以为用户创造即时价值?
示例:假设您的应用程序存储照片。使用自动标记或分类,您可以允许用户按人物或事件搜索他们的照片。
3。创造全新的产品
这些产品颠覆了工业——想想自动驾驶汽车。想出在 ML 之前不存在的产品是一个令人兴奋的问题:它们涉及新技术的组合。当 AR/VR、量子计算、区块链、边缘计算等其他指数级行业开始融合时,我们将会看到更多这样的产品。
我们该怎么办?
我们知道,机器学习本质上需要数据,数据经过处理后给出响应。使用这个框架,我们可以想到有趣的应用程序,这些应用程序恰好是很好的业务用例。
这里的要点是,每个机器学习应用程序都涉及输入(数据),然后处理这些输入以给出有用的输出(预测)。中间的过程是机器学习。
令人兴奋的是,这些机器学习算法可以作为服务提供给你今天使用。所有主要参与者都在人工智能即服务领域展开竞争。您添加您的数据,模型就为您建立起来了。要获得可用服务的快速列表,请查看这个。
思考数据——以及它是如何被挖掘出来的。
您每天生成哪些数据?下载应用程序时,您授予了它们哪些访问权限?通过访问您的电子邮件、语音记录和交易历史记录,您的服务提供商如何获得您的更多信息?如何使用这些信息?
由于机器学习现在可以作为一项服务提供给每个人,数据成为你的竞争优势。考虑利用机器学习改进现有功能,创造新功能和新产品。
不要对改变脱敏。
比尔·盖茨说,“我们总是高估未来两年将发生的变化,低估未来十年将发生的变化。”要知道,技术的复合性质在未来十年带来的变化将超过上个世纪的总和。
不要小瞧登月的想法。
新技术总会有反对者。尽量不要非黑即白地思考;任何人工智能项目的进展都是一系列的失败和成功。
如果这项技术为社会增加了价值,并且看起来可行,它很可能会以某种方式表现出来——这只是时间问题。而且比大多数人预期的要快。众所周知,增长率是非线性的。
此外,任何雄心勃勃的技术解决方案的每个组成部分本身都是一个突破性的解决方案。自动驾驶汽车由计算机视觉、激光雷达、移动计算、预测算法、人工智能伦理等组成。每个组成部分都可以重新组合成新的产品和服务。
Hari Meyyappan 是一名机器学习工程师、企业家和研究生。要阅读更多他的作品,请访问 hmeyy.com。
人工智能与行为
谣言、时尚/潮流和体育比赛中的潮流有什么共同点?
回答:都是集体行为的形式!
集体行为的由来
创造了“集体行为”一词的美国社会学家罗伯特·e·帕克,将其定义为*“个人在一种普遍的集体冲动影响下的行为,换句话说,这种冲动是社会互动的结果。”何强调,群体、时尚或其他形式的集体行为的参与者有着共同的态度或相似的行为:这不是因为既定的规则或权威力量,也不是因为所有个人都有相同的态度,而是因为一个独特的群体过程。*
- 谣言…真的吗?是的,非常喜欢。大多数对群体行为进行社会分析的人认为,通过谣言进行的 信息分配和传播 是整个现象的关键。当一大群人聚集在一起采取共同的行动时,如暴乱或恐慌,谣言往往就会出现。通常会有一个关于这种情况的近似通用定义的发展,这是通过谣言传播过程发生的。(链接到有趣的例子)
在我看来,动物的集体行为要有趣得多
“Fish, for sport only, not for meat. Fish meat is practically a vegetable.” Ron Swanson
这个视频展示了在多种不同环境下集体动物行为的精彩片段。通过视频观看这些奇观确实令人惊叹,但想象一下这在现实中是多么不可思议。也许我应该放下手头的一切,去当一名摄影师??但在视频中所有这些自然景观中,每个个体(代理人)都被群体淹没了,因为群体有了自己的生活。
很酷的东西,但是有什么好主意呢?
在《集体动物行为的原则》中,D . j . t . sum pter 做了一个很好的过渡,说明集体行为的可能性对研究和未来有多么令人兴奋。
有一种感觉,所有这些集体模式都是有规律的,甚至是可预测的。集体动物行为(群体、群体、蚂蚁踪迹)的规律性使我们感到,一定有某种统一的法则支配着这些不同的现象。但是,虽然通勤车的行列可能会让我们想起一群蚂蚁,但它们之间有什么深刻的相似之处吗?如果是这样,我们能否确定一套原则,让我们能够分类和理解集体动物行为?
群体智能
群体智能,除了听起来像一些未来的机器人接管,本质上是分散的,自组织的,自然或人工系统的集体行为。这个概念是由杰拉尔多·贝尼和王静在 1989 年首次提出的。两人深受大自然的启发,尤其是生物系统。
S.I .系统基本上包括一个群体,其中充满了简单的代理人(个体),这些代理人在本地相互作用,并与他们的环境相互作用。代理遵循简单的规则,但当涉及到他们如何在本地行为时,他们有一种自由意志。它们也有一定程度的随机性。
Intelligent Bees clip from Black Mirror, Sci-Fi show
重要的阶段,特别是智能群体的行为(有点像人工集体行为),通过智能体之间的许多交互发生,而其他个体智能体却不知道。
美国国家航空航天局正试图使用 S.I .技术进行行星测绘。美国军方一直在用同样的技术研究战区无人驾驶车辆。欧洲航天局正在利用它进行自我组装和干涉测量的研究。
AI 在哪里出现
人工智能有多种不同的学习方法(只是算法,基本上是乐高积木,更多细节在我之前的博客)
- 无监督 -我们做 而不是 有任何结果变量或目标要预测/估计。它主要用于将数据(群体)聚类成组。
- 监督- 现在我们有了的目标,我们将根据给定的独立变量的估计来预测结果。
- 强化 学习- 一个流行的例子是马尔可夫决策过程。它是一台有环境的机器,通过试错来学习。它将继续失败,同时从错误中学习,并获取最佳可用知识作为未来决策的基础。
在高度依赖效率的资源分配行业的任何地方,整个系统中所有个体代理的自组织过程都应该被监控。
人工智能规则如何让代理学习
【投影模拟】
汉斯·布里格尔开发了这种学习模型,它基于不以预定(预编程)方式对事件做出反应的代理。这些智能体具有学习能力,同时它们也被编码为个体。这意味着他们在与环境互动时,每个人都有独特的行为方面:受每个“学习”主体感知和反应的所有感官输入的监控。
为此,他们遵循人工智能规则,允许他们使用并记住以前的经验来调整他们的行动,以便受益。
托马斯·穆勒解释了集体行为调节的应用:
实际上是复制集体行为
“投影模拟”学习模型已经成功地应用于蝗虫群集行为的研究。这项研究最初是在一个封闭的空间里进行的,在那里他们研究了每个个体与群体大小相对应的运动行为。结果显示,当蜂群的规模只有几个个体时,它们的运动是杂乱无章的。较大的蝗虫群会作为一个整体一起移动,而非常大的蝗虫群会作为一个整体移动,但现在都是向同一个方向移动。研究人员设法定性地再现蝗虫的行为。
[“展望未来,托马斯·穆勒相信这一领域未来的研究将受益于动物的大型数据集,比如鱼群及其动态行为模式。”穆勒总结道:“为鱼建模可能是一个很好但也非常复杂的下一步,可以让我们的学习模型更加真实。](https://www.sciencedaily.com/releases/2019/04/190408114325.htm)
如果你喜欢这本书,看看我的另一篇文章,一组研究人员成功地模拟了鱼群的行为,非常有趣的发现!
作品引用
什么是集体行为?讨论集体行为的不同类型和例子。也叙述理论…
www.masscommunicationtalk.com](http://www.masscommunicationtalk.com/types-and-examples-of-collective-behaviour.html) [## 集体动物行为的原则
近年来,自组织的概念被用来理解动物的集体行为。的…
www.ncbi.nlm.nih.gov](https://www.ncbi.nlm.nih.gov/pmc/articles/PMC1626537/) [## 集体行为|心理学
集体行为:集体行为,由规模可观但组织松散的群体参与的活动…
www.britannica.com](https://www.britannica.com/science/collective-behaviour) [## 群体智能-维基百科
SI 系统通常由一群简单的代理人或机器人组成,这些代理人或机器人在本地相互作用,并与…
en.wikipedia.org](https://en.wikipedia.org/wiki/Swarm_intelligence) [## 利用人工智能来理解集体行为
托马斯·穆勒教授和汉斯·布里格尔教授一直在研究一种机器学习模型,用于…
www.sciencedaily.com](https://www.sciencedaily.com/releases/2019/04/190408114325.htm) [## 视频:描述大量宏观物体集体行为的框架
让我们把冬天抛在脑后吧——是时候考虑沙子了。物理学家经常想到沙子,因为他们并不真的…
phys.org](https://phys.org/news/2015-04-video-framework-characterize-behavior-large.html)
揭秘人工智能的记者指南。
与其诅咒算法,不如点燃蜡烛
(Image: Gerd Altmann, Pixabay)
我们越来越多地被智能设备和系统所包围,这些设备和系统具有预测我们需求的内置智能。如果你在拨打客户支持电话时使用了语音识别系统,在从国外进入美国时进行了面部扫描,或者让 Alexa 或 Siri 告诉你天气预报,那么你就与人工智能或人工智能进行了互动。
虽然我们享受着智能设备和系统的便利,但随着人工智能在我们越来越多的生活活动中出现,在工作、家庭、学校、商业和休闲中,它们也引起了用户的担忧。甚至新闻编辑室也是人工智能的目标,它们渗透到我们经常随身携带的移动设备上。问问 Siri 就知道了。
我们愿意假设这些系统中的智能是专业制造的,并且在发布用于日常使用之前经过了彻底的测试和验证。但是我们能做出这样的假设吗?作为记者,我们被要求报道影响人们日常生活的事态发展。然而,随着人工智能技术向前发展,记者们经常被留在外面,和其他人一起观察。是时候了——实际上,是过去的时候了——记者们应该问问智能系统的开发者,人工智能里有什么。我们正在转向我们的生活。
关于人工智能和记者
人工智能一词涵盖了许多不同的技术,包括自然语言处理、计算机视觉和语音识别,以感知和理解来自周围世界的信号和刺激。虽然这些进步中的一些已经存在了几十年,但它们延伸到我们的日常生活中是由于巨大计算能力的广泛可用性、移动设备的激增以及存储大量数据的云计算的出现。
但是也许人工智能最引人注目的进步是在机器学习方面。由于机器学习,智能系统在整合它们遇到的数据时变得更加智能。
现在,系统不仅会记住它们遇到的数据,还会从这些数据中学习和增长更多知识,在许多情况下,比人类更高效、更可预测。人们可以说,机器学习提供的便利被它们对人类在日益智能的技术世界中的角色造成的不确定性所抵消。
我们可能会在生活中看到更多人工智能系统。虽然没有关于智能系统和设备数量的可靠统计,但最近的一份风险投资汇编为我们提供了一个很好的趋势线索。市场情报公司 GlobalData 的统计显示,仅在过去一年,开发人工智能系统的初创公司的风险交易和资金大幅增加,使人工智能成为热门的风险投资目标之一。(2019 年第一季度的数据显示,人工智能风险投资从去年的快速增长中放缓。)
这并不是说记者们对所有这些都漠不关心,而是关注点相当狭窄,例如寻找人工智能对就业的潜在影响。我也承认写了那种故事。事实上,最近的另一项研究显示,公司正在安装对业务有益的人工智能系统,不一定是为了裁员。这项由消费者技术协会市场数据公司 Statista 进行的研究显示,人工智能的顶级商业应用是更好地检测安全威胁和改善客户服务,这些功能直接关系到企业的生存。
关于人工智能的一个更好的故事是检查智能系统做什么,它们如何做,以及它们是否做得好。换句话说,点亮黑匣子里的蜡烛,而不是抱怨黑暗。为了点燃这根蜡烛,知道要问什么问题是有帮助的,我们将在这里检查这些问题。
关于算法
机器学习的核心是计算机代码背后的逻辑算法,它通过智能设备或系统处理信息。算法是执行任务的一组规则和过程,通常用数学公式或逻辑表示。它们可以是简单的,如计算贷款利息的公式,也可以是复杂的,考虑多种因素和条件。
在机器学习中,算法具有一种特殊的性质:当遇到更多数据时,它们会调整自己的规则、过程和计算。机器学习中使用的许多算法都来自于贝叶斯统计,以 18 世纪英国牧师和哲学家托马斯·贝叶斯的名字命名,他的定理导致了根据其他相关概率预测某个结果发生的概率的计算。在这些计算中,用于计算结果的数据越多,预测就越可靠。创建了 FiveThirtyEight 的内特·西尔弗(Nate Silver)帮助普及了选举投票中的贝叶斯统计,并预测了体育赛事的结果,甚至在比赛进行的时候。
对于学习这些算法的机器来说,它们需要数据和大量的数据。算法遇到和吸收的数据越多,这些数据中表达的条件越多样化,预测就应该越精确,就越有把握应用于更大的人群。机器学习系统的开发人员编写他们的算法,然后通常用来自大规模数据库的数据来训练例程。在投入使用后,这些算法会继续从遇到的数据中学习,并在结果中变得更加精确。
虽然算法的概念相当简单,但正如前面提到的,它们可能会变得相当复杂。然而,企业高管、政策制定者和普通公民正在使用机器学习算法来帮助做出比以往更多的决定,这些决定取决于他们计算的准确性和可靠性。我们可以信任编写算法的数学家和工程师,或者坚持采取安全措施来检查算法的准确性和可靠性。
为什么我们需要检查算法?我们对 2007-2008 年的金融危机有着痛苦的经历。自 20 世纪 30 年代以来最严重的经济衰退的原因之一是复杂的金融工具,一种被称为抵押债务凭证的衍生品,它将其他资产,如抵押贷款和债券汇集在一起,并重新包装为单独的投资。
许多债务抵押债券非常详细和复杂,需要用算法表达的数学公式和计算机逻辑来精确地确定结果和管理风险。在崩溃之前,许多华尔街投资公司雇佣了训练有素的物理学家和数学家“量子学家”来编写这些算法,算法的复杂性往往掩盖了向投资者推销的抵押贷款组合的潜在风险。
随着一揽子计划中潜在的次级贷款变坏,建立在这个不稳定基础上的债务抵押债券也随之崩溃。因为它们的复杂性,像贝尔斯登和雷曼兄弟这样拥有这些证券的投资银行也无法解释为什么会破产。(2008 年,我在科学杂志的职业专栏中写过一篇关于科学家被聘为量子分析师的专题。)
点燃蜡烛
(Image: Science Translational Medicine)
记者,尤其是那些没有数学和统计学背景的记者——这涵盖了当今的许多记者——如何才能发现这些机器学习算法中的内容?通过问正确的问题:关于算法旨在解决的问题,用于编写算法的过程,以及它在实践中的跟踪记录。如果你想一想,记者们通常会问政治家、企业高管、艺人和体育明星同样的问题。我们现在需要问他们以及人工智能系统的开发者。
从算法的基本事实开始:
1.人工智能系统在解决什么问题?
2.有助于解决这个问题的算法是什么?
3.训练算法的数据来源是什么?
4.当算法遇到数据时,它在学习什么?
下一组问题询问算法的质量和可靠性。当然,这可能是一个棘手的领域,因为除了数据科学家之外,很少有人拥有评估算法的数学或逻辑的技术背景。
密歇根大学法学教授 W. Nicholson Price 在 2018 年 12 月发表在杂志科学转化医学上的一篇文章大数据和黑盒医学算法帮助了我们。尼科尔森提供了一种策略,来帮助医学领域的机器学习算法的用户理解其中的内容。
普莱斯向机器学习系统开发人员提出了一系列问题,以帮助医疗系统监管机构,如食品药品监督管理局,掌握人工智能。(FDA 在 2019 年 4 月宣布,它打算为医疗算法创建一个监管框架。)但普莱斯了解医疗黑匣子内部的策略也可以应用于其他机器学习算法,比如:
5.算法是否被独立审查,或者用于训练算法的代码和数据库是否可供独立审查者使用?
6.除了用于训练的数据集之外,算法是否针对其他数据集运行,以验证最初的发现?
7.该算法在真实世界数据中的表现如何?
与真实算法一起使用的问题示例
这里有一个应用于医疗保健算法的例子,这是科学&企业在 2019 年 3 月报道的。来自斯坦福大学和以色列领先的科学和工程机构 Technion 的医学研究人员和数据科学家团队编写了一种机器学习算法,来计算一个人的免疫系统健康指标,发表在《自然医学杂志上。调用免疫系统正迅速成为许多疾病,特别是癌症新疗法的关键机制。但这些新疗法需要患者体内功能良好的免疫系统才能有效发挥作用。
由斯坦福大学的马克·戴维斯和 Technion 的 Shai Shen-Orr 领导的团队编写了一种算法来计算他们所谓的免疫年龄。随着时间的推移,一个人的免疫系统会逐渐衰退,但如果调用免疫系统的治疗方法合适,实足年龄充其量只是一个粗略的指标。因此,Davis,Shen-Orr 和他的同事设计了这种算法来计算一个人的免疫年龄,他们说这提供了一种更敏感和可靠的免疫系统健康衡量标准。
让我们将我们的 7 个问题应用到这个算法中。
1。人工智能系统在解决什么问题?该系统满足了更好地测量免疫系统健康的需求,以确定调用免疫系统的治疗是否适合一个人。
2。有助于解决这个问题的算法是什么?
3。训练算法的数据来源是什么?
研究人员跟踪了 135 名健康个体 9 年,定期测量各种免疫系统指标:全血样本中表达的基因,细胞对免疫系统细胞发出的称为细胞因子的信号酶的反应,以及体内特定细胞亚群的特征。
4。当算法遇到数据时,它在学习什么?
5。算法是否被独立审查,或者用于训练算法的代码和数据库是否可供独立审查者使用?
研究人员将数据和源代码提供给独立的研究人员。
6。该算法是否针对除用于训练的数据集之外的数据集运行,以验证最初的发现?
该团队对来自弗雷明汉心脏研究的 2000 名参与者样本的健康数据运行了他们的算法,这是一项里程碑式的持续调查,对马萨诸塞州弗雷明汉市 15000 多人的心血管和整体健康进行了调查,始于 1948 年。研究人员表示,他们的免疫年龄算法准确预测了他们采样病例的死亡率。
*7。该算法在真实世界数据中的表现如何?
*《自然医学》论文发表于 2019 年 3 月,因此截至 2019 年 4 月,进行真实世界测试的机会很小。然而,免疫年龄算法不仅仅是一个学术练习。申-奥尔在特拉维夫联合创办的公司 CytoReason 从 Technion 获得知识产权许可,用于模拟药物发现和临床试验计划的细胞行为。该公司在免疫年龄算法方面的经验可以为这个问题提供答案,并在遇到更多样化的人群时提供新的数据来完善算法。
额外问题:如果一家公司声称其算法是专有的怎么办?
提供机器学习算法服务的公司可能会声称他们的算法是商业秘密,不能披露。这里使用的免疫年龄算法作为一个例子,可以提供一些方法来解决这个问题。以下是进一步要问的问题:
公司的算法是基于学术研究吗?如果是这样的话,一个更早的版本可能会发表在杂志上,就像斯坦福科技公司在《自然医学》上的论文一样。该公司可能会增加或微调计算,但发表的研究可以提供最新版本的良好估计。
*该公司的算法,或其背后的研究,是由美国政府资助的吗?美国国立卫生研究院是免疫年龄算法的资助者之一。联邦机构的资金公告是公开文件,可以在线搜索。这里有来自…
**算法有专利,还是公司申请了专利?如果算法对公司的成功至关重要,那么公司——或者从其获得技术许可的学术机构——可能会申请专利来保护知识产权。搜索专利数据库,如美国专利商标局或第三方数据库提供的数据库,可以提供专利文本。同样,该专利可能不会提供所有算法的最新功能,但它可以提供一个关于其工作原理的好主意。
从火星轨道飞行器到陆地神经网络的旅程
年份是 2019 年。如果你现在设法传送到火星,你会发现一艘多用途宇宙飞船在近圆形轨道上围绕火星运行,持续约 2 小时,高度从 250 公里到 316 公里不等。这个被恰当地命名为火星勘测轨道飞行器(MRO) 的航天器,自 2006 年 9 月以来一直在向地球传输由其所有最先进的仪器捕获的大量数据。收到的数据总量为 361 兆兆比特,比过去和现在所有其他星际任务的总和还要多。此外,MRO 以每秒 3.4 公里的速度运行,并绕火星运行了 6 万圈!
NASA Infographic (May 2019) — Image Source
如果一个月前你问我这个奇妙的装置,我根本不知道你在说什么。然而,3 周前,我对火星表面的了解经历了一次彻底的变革,这是因为我被选为奥姆德纳的全球人工智能合作挑战 的一部分,与一个 50 人的团队合作,自动识别火星表面的着陆点和异常。
你可能已经猜到了,我们决定应用机器学习来解决这个问题,但在开始之前,我们意识到我们需要大量的火星表面数据(图像)。为了获取这些数据,我们需要了解在哪里可以找到这些数据,以及如何检索这些数据。因此,我们发现自己费力地阅读与复杂软件系统协同工作的精心构造的机器的规范文档和用户手册;试图更多地了解 MRO 和它所有的乐器。
如果您赶时间,并且只想知道如何使用几行代码*(Python 语言)*检索这些图像,以便您可以专注于构建和调整神经网络来分析火星表面,那么可以随意跳到“一体化 Python 包”部分。然而,如果你想知道更多关于火星图像如何到达地球以及下载这些图像后修复的问题,那么请继续阅读。
目录
- 高分辨率成像科学实验(HiRISE)
- 深空网
- 美国宇航局行星数据系统
- 地球科学节点的轨道数据探测器(ODE)
- ODE Web 界面
- ODE REST 接口
- 海量 JPEG2000 文件
- 切大块
- 寻找可扩展的解决方案
- 黑边和计算机视觉技巧
- Numpy 数据集文件
- 任务总结
- 一体化 Python 包
- 结论
- 参考文献
高分辨率成像科学实验(HiRISE)
MRO 通过捕捉不同类型的火星表面图像,为漫游车和固定着陆器任务提供了至关重要的支持,以便地球上的科学家可以手动评估每张图像,以确定潜在的着陆点。在轨道器上包括的 3 个相机,2 个光谱仪和 1 个雷达中,我们决定专注于由亚利桑那州大学图森分校管理的高分辨率成像科学实验(HiRISE)相机捕获的数据。这款相机的美妙之处在于,它能够在 300 公里的高度达到 1 微弧度的分辨率,即 0.3 米(相当于一张餐桌的大小)。这些观测覆盖了大约 2.4%的火星表面,相当于两个阿拉斯加的面积,许多地方被重复拍摄。
HiRISE Camera — Image Source
深空网络
MRO 通过与美国宇航局的深空网络通信将所有这些数据中继到地球,这是一个由美国航天器通信设施组成的全球网络,位于美国(加利福尼亚州)、西班牙(马德里)和澳大利亚(堪培拉),支持美国宇航局的星际航天器任务。
70 m antenna at Goldstone, California — Image Source
美国宇航局行星数据系统
现在,这些数据到达地球后去了哪里?很高兴你问了。来自这些仪器中每一个的数据都存储在美国宇航局的行星数据系统(PDS)的远程节点中,这是一个分布式数据系统,美国宇航局用来存档太阳系任务收集的数据,能够经受住时间的考验,以便未来的科学家能够访问、理解和使用预先存在的行星数据。
The geographic distribution of NASA’s Planetary Data System. There are nine nodes geographically distributed across the U.S., broken down by scientific expertise — Image Source
地球科学节点的轨道数据探测器
仅仅为了找到在特定纬度和经度拍摄的图像而搜索分散在多个区域的节点将是非常麻烦和低效的。因此,另一个称为地球科学节点的轨道数据探测器(ode)的系统将 PDS 档案数据从本地和远程节点加载到中央数据库,以便它可以通过以可扩展的方式提供高级搜索、检索和排序工具、集成分析和可视化工具来增强现有的 PDS 搜索和检索界面。
PDS and ODE systems — Image Source
ODE 网络界面
ODE 网站为轨道数据探测器提供了一个用户友好的搜索界面,允许用户根据不同的标准搜索图像,如仪器类型、纬度、经度等。
Data Product Search with Filters
它甚至支持地图搜索,这相当于我们如何使用谷歌地图来搜索特定的地方*(我不知道火星的几个地区已经被命名了!)*
Interactive Map of the entire surface of Mars
ODE REST 接口
然而,当我们希望搜索和下载来自火星不同地区的大量图像(超过 1000 张)时,网络界面并不是特别有用。这就是 ODE REST 接口出现的地方。它通过 HTTP 提供对 ODE 网站上的相同图像的编程访问。示例响应如下所示:
Sample Response for a query processed by the ODE REST Interface
庞大的 JPEG2000 文件
如果你仔细观察,你会注意到图像文件的 URL,而不是实际的图像本身。除此之外,图像文件的扩展名不是我们已经习惯的 JPG 或 PNG 格式。相反,它是一种叫做 JP2 的奇怪格式。
JPEG 2000 (JP2)是一种图像压缩标准和编码系统。它是由联合图像专家组委员会在 2000 年创建的,旨在取代他们最初的 JPEG 标准(创建于 1992 年),在压缩高分辨率图像方面更有效。它还提供了将图像分割成较小部分以独立编码的可能性,并提高了抗噪声能力。总的来说,JPEG 2000 是一种更灵活的文件格式。
由于我们处理的是数千像素量级的高分辨率图像,我们不得不依赖这种高级的 JP2 格式,这种格式处理起来计算量很大,并且需要大量的内存来存储。难怪即使在 2019 年,这种格式也没有像 JPEG 格式一样在小规模设备中变得无处不在。
切掉大块
我如何在(̶E̶a̶r̶t̶h̶)火星上建立一个卷积神经网络来处理成千上万的这些 JP2 文件,每个图像的分辨率约为 25000 x 40000 像素,并希望它在我的有生之年完成?好吧,我们试图解决这个问题,从这个巨大的图像中分割出较小的、相同大小的块(大约 1024 x 1024 像素),并将每个块保存为 JPG 格式,这样 CNN 甚至可以考虑观看它。
Low-Resolution JPG Thumbnail of a JP2 image before slicing (Used only for display purposes and isn’t the actual JP2 file) — Image Source
寻找可扩展的解决方案
我们的麻烦才刚刚开始,因为将一个 JP2 文件分割成块被证明是一个非常缓慢的过程——如果 python 程序在此之前设法不崩溃的话,处理一个图像需要大约 1 个小时。这是不可伸缩的。因此,发现了另一种切片方法,它不需要将整个 JP2 文件加载到内存中。它需要使用 rasterio 包,通过滑动窗口技术只获取 JP2 图像的一部分。
JPG Chunks from a single JP2 image
黑边和计算机视觉技巧
但这并不是结束。现在我们有了所有的块,我们手动浏览它们,却发现多个图像是全黑的或者有不规则的黑色边缘。事实上,大约 50%的块是黑色的。深入挖掘后,我们意识到这是因为 JP2 文件中的图像是地图投影的,这导致它沿着一个矩形区域的对角线排列,周围都是黑色的边缘。
为了解决这个问题,一些计算机视觉技巧,如轮廓和阈值,被应用于识别这样的黑边;旋转并裁剪它们。除此之外,所有完全黑色的块都被丢弃。
Numpy 数据集文件
最后,虽然块被单独保存在磁盘上,但我们也希望将这些块保存为 numpy 数组的集合,以便在训练机器学习模型之前可以轻松地将其作为数据集导入,类似于 keras 等库提供样本数据集的方式。这是通过聚集所有块并将它们保存在单个 npz 文件中实现的。
任务摘要
嗯,那是相当多的一口!让我总结一下到目前为止我们已经完成的步骤:
- 创建 HTTP 查询字符串以从 ODE REST 接口获取图像
- 解析查询响应 XML 并提取 JP2 URL
- 使用步骤 2 中获得的 URL 下载所有 JP2 图像
- 将每个 JP2 图像分割成较小的、大小相等的块
- 确定每个块中的黑色边距
- 通过旋转或裁剪来移除黑边,同时保留该块的原始分辨率,如果不可能,则丢弃整个块
- (可选)聚合所有区块,并将其保存在单个 NPZ 文件中
如果所有这些步骤都是通过安装一个包并运行几个命令来完成的,那不是很好吗?
一体化 Python 包
嗯,我非常高兴地宣布,使用我们开发的一个名为" mars-ode-data-access "的小 python 包来执行所有这些步骤确实是可能的,可以在 https://github.com/samiriff/mars-ode-data-access 的获得。
要安装此项目,只需运行以下命令:
pip install git+[https://github.com/usgs/geomag-algorithms.git](https://github.com/usgs/geomag-algorithms.git)
pip install git+[https://github.com/samiriff/mars-ode-data-access.git](https://github.com/samiriff/mars-ode-data-access.git)
它支持多个查询参数和块设置,并在内部利用以下包提供的一些功能:
为了在您的项目中使用 mars-ode-data-access 包,您必须导入相关的类:
确定并定义从轨道数据探测器获取所需的 JP2 图像所需的查询参数。例如,下面的片段演示了如何从凤凰号火星着陆点获取数据:
接下来,我们需要为每个下载的 JP2 图像将被分割到的每个块定义一些设置。下面是一个示例:
最后,我们需要做的就是获取结果并处理它们以创建块。这可以通过运行以下代码来完成:
瞧啊。当所有繁重的工作都在幕后为您完成时,您只需高枕无忧(处理每张 JP2 图像可能需要大约 6 分钟,具体取决于分辨率)。
Sample Output after processing results of the Phoenix Landing Site
如果您想尝试这些 API,看看如何以 NPZ 格式保存这些块,您可以使用这个合作笔记本—https://colab . research . Google . com/drive/1c-j-dblksxuvduhzsdqbp 87 ua 1et 2n
结论
如果没有奥姆德纳人工智能挑战赛提供的协作学习环境,以及来自拉德伯·米特拉、帕特里西奥·韦塞拉、丹尼尔·安格豪森和迈克尔·布哈特的专家建议和指导,这一壮举是不可能实现的。我还要感谢参与本项目的整个团队,特别要感谢 Conrad Wilkinson Schwarz、Sebastian Laverde、Sumbul Zehra、Murli Sivashanmugam、Marta Didych、Aman Dalmia 和 Indresh Bhattacharya,感谢他们为此项目做出的贡献。
总而言之,这对我来说是一次很好的学习和启发经历,我希望我能让你满意地一瞥我在过去 4 周内掌握的知识,亲爱的读者!所以,下一次你在夜空中发现这颗红色星球时,不要仅仅把它当成茫茫太空中的一个小点。请记住,这是一个宏伟的数据源,地球上的任何人都可以使用它来训练神经网络,并了解更多关于其表面和表面下的奥秘,从而提高人类在不久的将来踏上火星的机会…
Dune shaped in the form of the Star Trek logo, discovered southeast Hellas Planitia ( https://www.uahirise.org/ESP_059708_1305)
参考
[1]https://mars . NASA . gov/news/ten-years-of-discovery-by-mars-respective-orbiter/
【2】https://www . pops ci . com/mars-respective-orbiter-have-be-orbiter-being-on-10-years/
【3】https://ode.rsl.wustl.edu/mars/indexHelp.aspx
【4】https://www.uahirise.org
【5】http://www . Planetary
Apache Spark 大数据之旅—第 2 部分
介绍如何用 Scala 构建第一个 Apache Spark 应用程序来读取 CSV 文件。
A tabular view of a DataFrame from a CSV file in Apache Spark
欢迎回到(我希望成为的)关于了解 Apache Spark 的系列文章的第二部分。
我将使用 Scala 构建应用程序,因为我也想了解这一点。Scala 并不是我经常使用的东西,所以当我弄清楚一些事情的时候,请一定要忍耐一下:)。如果有更好的方法来做我做的任何事情,请让我知道——我随时欢迎反馈!
开始之前
本文不会深入探讨如何设置和配置 Scala 应用程序,因为我们的目标是快速启动和运行,并深入 Spark 的世界。Scala world 确实让这变得简单了,它提供了一个叫做 SBT 的工具,Scala Build Tool,有一些值得注意的东西只会让这变得更简单。
设置我们的环境
如果你读过我之前的帖子,我暗示我是一个 Docker 的超级粉丝,以真正的粉丝风格,我将使用已经包含 Scala 和 SBT 的 Docker 图像来帮助我的开发。我将要使用的 Dockerfile 可以在这里找到。这个 Dockerfile 很棒,因为它在构建时接受环境参数,安装由这些参数指定的特定版本的 Scala 和 SBT(非常感谢原作者&贡献者!).我在 Dockerfile 中添加了我自己的小改动,主要是将WORKDIR
设置为/project
(因为那是我挂载项目目录的地方,就像我的代码一样),并添加了一个CMD
,以便在我们启动容器时启动到sbt
控制台中。我们可以通过运行以下命令来构建映像:
docker build -t ls12styler/scala-sbt:latest \
--build-arg SCALA_VERSION=2.12.8 \
--build-arg SBT_VERSION=1.2.7 \
github.com/ls12styler/scala-sbt
您可以看到我们将构建的图像标记为ls12styler/scala-sbt:latest
,因此我们可以通过运行以下命令来简单地运行图像,让我们进入 bash shell,在我们之前配置的WORKDIR
中:
docker run -it --rm ls12styler/scala-sbt:latest /bin/bash
我们可以通过运行scala -version
和sbt sbtVersion
来验证安装,得到以下输出:
bash-4.4# scala -version
Scala code runner version 2.12.8 -- Copyright 2002-2018, LAMP/EPFL and Lightbend, Inc.
bash-4.4# sbt sbtVersion
[warn] No sbt.version set in project/build.properties, base directory: /
[info] Set current project to root (in build file:/)
[info] 1.2.7
为了能够访问我们的本地文件,我们需要将一个卷从我们的工作目录挂载到正在运行的容器中的某个位置。我们可以通过简单地在我们的run
命令中添加-v
选项来做到这一点。我们将移除/bin/bash
,这样我们就可以直接进入sbt
控制台:
docker run -it --rm -v `pwd`:/project ls12styler/scala-sbt:latest
我们在这里所做的就是将pwd
(当前工作目录)挂载到容器上的/project
目录下。当运行上述内容时,我们将在 SBT 控制台的那个路径上结束:
[warn] No sbt.version set in project/build.properties, base directory: /project
[info] Set current project to project (in build file:/project/)
[info] sbt server started at local:///root/.sbt/1.0/server/07b05e14c4489ea8d2f7/sock
sbt:project>
设置我们的项目
在你的项目目录中创建一个名为build.sbt
的新文件,用你最喜欢的编辑器打开它。用以下内容填充它,这些内容实际上是从官方 Spark 文档中借用的,尽管略有改动:
name := "MyFirstScalaSpark"
version := "0.1.0"
scalaVersion := "2.11.12"
libraryDependencies += "org.apache.spark" %% "spark-sql" % "2.4.0"
这给了我们一个最小的项目定义来开始。*注意:我们已经将 Scala 版本指定为 2.11.12,因为 Spark 是针对 Scala 2.11 编译的,但是容器上的 Scala 版本是 2.12。*在 SBT 控制台中,运行reload
命令,用新的构建设置刷新 SBT 项目:
sbt:local> reload
[info] Loading project definition from /project/project
[info] Loading settings for project project from build.sbt ...
[info] Set current project to MyFirstScalaSpark (in build file:/project/)
sbt:MyFirstScalaSpark>
您应该注意到控制台采用了我们项目的名称:MyFirstScalaSpark
。现在我们有了一个构建项目的环境。我们写点代码吧!
我们的第一个应用
我们将进一步跟踪 Spark 文档,只是为了测试我们到目前为止的进展。
SBT 应用程序采用 Java 应用程序的标准目录结构,所以让我们在项目目录中创建一些新目录(使用-p
标志将递归地创建目录):mkdir -p ./src/main/scala/
在新创建的目录中创建一个名为MyFirstScalaSpark.scala
的新文件,并在您喜欢的编辑器中打开它。添加以下内容(同样,从原始内容略作调整):
package com.example
import org.apache.spark.sql.SparkSessionobject MyFirstScalaSpark {
def main(args: Array[String]) {
val SPARK_HOME = sys.env("SPARK_HOME")
val logFile = s"${SPARK_HOME}/README.md"
val spark = SparkSession.builder
.appName("MyFirstScalaSpark")
.getOrCreate()
val logData = spark.read.textFile(logFile).cache()
val numAs = logData.filter(line => line.contains("a")).count()
val numBs = logData.filter(line => line.contains("b")).count()
println(s"Lines with a: $numAs, Lines with b: $numBs")
spark.stop()
}
}
由于我们将在第 1 部分创建的集群上运行这个应用程序,我们知道将设置环境变量$SPARK_HOME
并指向 Spark Workers 上的正确目录。在上面的代码中,我们简单地检索了$SPARK_HOME
(应该是/spark
)环境变量的内容,将其插入到我们正在使用的 Spark 发行版附带的README.md
的文件路径中,创建我们的 Spark 会话,然后执行几个 MapReduce 过滤器来计算包含字母a
或b
的各种行数。然后,我们将这些计数输出到控制台。
现在我们已经有了一些需要实际编译的代码,我们可以创建一个 jar 并提交给 Spark 集群。在 SBT 控制台中,只需运行package
来生成 jar。您应该会看到类似于以下内容的输出:
sbt:MyFirstScalaSpark> package
[info] Updating ...
[info] Done updating.
[warn] There may be incompatibilities among your library dependencies; run 'evicted' to see detailed eviction warnings.
[info] Compiling 1 Scala source to /project/target/scala-2.11/classes ...
[info] Done compiling.
[info] Packaging /project/target/scala-2.11/myfirstscalaspark_2.11-1.0.jar ...
[info] Done packaging.
[success] Total time: 11 s, completed Dec 27, 2018 3:22:16 PM
如您所见,jar 已经在容器内的/project/target/scala-2.11/myfirstscalaspark_2.11-1.0.jar
输出,这意味着在本地,我们可以在``pwd/target/scala-2.11/
中找到 jar。
提交我们的申请
现在是时候让我们在第 1 部分中创建的集群起死回生了!找到包含docker-compose.yml
的目录并运行:
docker-compose up --scale spark-worker=2
这将产生一个 Spark Master 和两个 Spark Workers,这足以证明我们的第一个应用程序实际上是可行的。
在我们的项目目录中,我们可以使用我们在集群中创建的相同 Docker 映像作为我们的 Spark 驱动程序。Spark 驱动程序是我们向 Spark 集群提交应用程序的地方的名称,我们可以使用以下命令启动它:
docker run --rm -it -e SPARK_MASTER="spark://spark-master:7077" \
-v `pwd`:/project --network docker-spark_spark-network \
ls12styler/spark:latest /bin/bash
在这个命令中,我们设置了环境变量$SPARK_MASTER
的内容,在容器上的/project
下安装了pwd
,将它附加到我们创建的 Docker 网络,并放入一个 bash shell 中。要提交我们的申请,只需将其提交给 spark driver:
bash-4.4# spark-submit --master $SPARK_MASTER \
--class com.example.MyFirstScalaSpark \
/project/target/scala-2.11/myfirstscalaspark_2.11-0.0.1.jar
当我们提交应用程序时,我们指定 Spark Master 的 URI、要运行的类名以及该类所在的 jar。当我们在项目目录中启动容器时,Spark Driver 容器可以访问我们构建的 jar,而不需要我们在底层文件系统中复制它。在提交给 Spark 的日志中,您会看到我们在代码输出中构建的行:
...
Lines with a: 62, Lines with b: 31
...
如果我们检查群集的日志,我们会看到如下所示的内容:
spark-master | 2018-12-27 16:24:10 INFO Master:54 - Registering app MyFirstScalaSpark
spark-master | 2018-12-27 16:24:10 INFO Master:54 - Registered app MyFirstScalaSpark with ID app-20181227162410-0005
spark-master | 2018-12-27 16:24:10 INFO Master:54 - Launching executor app-20181227162410-0005/0 on worker worker-20181227134310-172.21.0.4-39747
spark-master | 2018-12-27 16:24:10 INFO Master:54 - Launching executor app-20181227162410-0005/1 on worker worker-20181227134310-172.21.0.3-42931
spark-worker_1 | 2018-12-27 16:24:10 INFO Worker:54 - Asked to launch executor app-20181227162410-0005/0 for MyFirstScalaSpark
spark-worker_2 | 2018-12-27 16:24:10 INFO Worker:54 - Asked to launch executor app-20181227162410-0005/1 for MyFirstScalaSpark
这显示了我们的应用程序被注册到 Master 并被赋予一个 ID。然后在每个 Worker 上启动 Executors,然后在我们的应用程序运行时发生一系列其他事情。
我们已经成功构建了第一个基于 Scala 的 Spark 应用程序,并在第 1 部分构建的集群上运行。恭喜你!
还有一件事…
现在有一个小问题:这只在目前有效,因为我们很幸运地选择了一个文件,该文件可用于所有使用我们在第 1 部分中构建的相同映像的容器(Master、Worker & Driver)。如果我们希望能够访问没有捆绑在映像中的文件,例如主机文件系统上的某个文件,我们需要与 Spark Workers 共享该文件系统。这可以通过在我们启动集群时在docker-compose
中挂载卷来轻松实现。在您的编辑器中打开docker-compose.yml
,并在工作者服务声明的末尾添加以下 YAML:
volumes:
- "./:/local"
保存文件并重新启动集群。现在,我们的 Spark 员工之间有了一个共享目录。接下来,我们需要与驱动程序共享同一个目录(我们提交应用程序的目录)。这只是为了方便起见,所以我们可以使用 bash 自动完成来构建文件路径,并将其作为参数传递给应用程序。我们可以通过更新我们的run
命令来包含新的卷(假设您运行docker-compose up
的目录与您的项目目录在同一级别):
docker run --rm -it -e SPARK_MASTER="spark://spark-master:7077" \
-v `pwd`:/project -v `pwd`/../docker-spark:/local \
--network docker-spark_spark-network -w /project \
ls12styler/spark:latest /bin/bash
这个容器现在有了我们的项目目录和共享数据目录,可以分别在/project
和/local
访问。
在 Spark 中读取 CSV 文件
在我们应用程序的第一次迭代中,我们使用了 Spark 中的read.textFile
函数来加载一个 README,这个 README 已经对工作人员可用了。接下来,我们将使用read.csv
,它将以一种我们可以执行操作的方式加载一个 CSV 文件。我将使用英国航天局支出报告:2018 年 10 月数据来完成这篇文章的其余部分,我将把这些数据放入我在容器上的/local
下安装的目录中。首先,我们将简单地使用count
方法来查看文件中有多少行。我们还将通过传递给 jar 的命令行参数将 CSV 文件的文件路径传递给应用程序。
在编辑器中,打开MyFirstScalaSpark.scala
文件并添加以下代码:
package com.example
import org.apache.spark.sql.SparkSessionobject MyFirstScalaSpark {
def main(args: Array[String]) {
val spark = SparkSession.builder
.appName("MyFirstScalaSpark")
.getOrCreate() val filePath = args(0)
val data = spark.read
.csv(filePath) println(data.count)
spark.stop()
}
}
我们实际上只是添加了使用参数来指定文件路径,并使用它作为用 Spark 打开的文件。Spark 会将该文件加载到一个数据帧中。然后,我们将数据帧中的行数打印到控制台。在 SBT 控制台中再次运行package
来构建我们应用程序的新版本。提交构建的应用程序,这次传入我们使用的数据集的文件路径:
spark-submit --master $SPARK_MASTER \
--class com.example.MyFirstScalaSpark \
target/scala-2.11/myfirstscalaspark_2.11-1.0.jar \
/local/UKSA_Oct_18_-_Transparency_Data.csv
在 Spark 的日志输出中,您应该看到数字689
。命令行上的快速检查显示了相同的内容:
bash-4.4# wc -l /local/UKSA_Oct_18_-_Transparency_Data.csv
689 /local/UKSA_Oct_18_-_Transparency_Data.csv
获得正确的结构
然而,如果我们想要某种类似于“表格”的数据表示,行数可能不是这样。检查 CSV 文件的第一行显示该文件包含列标题,因此我们实际上只有 688 行数据。让我们来看看我们加载的数据的实际结构。在我们的代码中,我们可以添加data.printSchema
来做到这一点:
...
val data = spark.read
.csv(filePath) **data.printSchema**
...
package
并提交以查看类似下面的输出:
root
|-- _c0: string (nullable = true)
|-- _c1: string (nullable = true)
|-- _c2: string (nullable = true)
|-- _c3: string (nullable = true)
|-- _c4: string (nullable = true)
|-- _c5: string (nullable = true)
|-- _c6: string (nullable = true)
|-- _c7: string (nullable = true)
|-- _c8: string (nullable = true)
|-- _c9: string (nullable = true)
|-- _c10: string (nullable = true)
这并没有告诉我们太多。共有 11 列,都是string
类型,而且这些列都没有很好地命名。当使用 Spark 读取 CSV 文件时,我们可以指定一个选项,使用第一行作为列标题,然后使用剩余的行作为“表”的行。我们通过添加到read
行将它添加到我们的应用程序中:
val data = spark.read
**.option("header", true)**
.csv(filePath)
运行package
构建一个新的 jar,然后再次提交给集群。我们现在应该可以在日志和下面的模式中看到数字688
。您可以看到,我们现在有了已命名的列,而不是按位置命名的列:
root
|-- Department: string (nullable = true)
|-- Entity: string (nullable = true)
|-- Date of Payment: string (nullable = true)
|-- Expense Type: string (nullable = true)
|-- Expense Area: string (nullable = true)
|-- Supplier: string (nullable = true)
|-- Transaction Number: string (nullable = true)
|-- Amount: string (nullable = true)
|-- Description: string (nullable = true)
|-- Supplier Post Code: string (nullable = true)
|-- Supplier Type: string (nullable = true)
所以我们现在已经有了正确的行数和一个已命名列的结构——太好了!仔细看看这个模式——我们所有的值都是类型string
。同样,这不是很有帮助。我们应该和合适的类型一起工作。幸运的是,Spark 提供了另一个选项来尝试并最好地猜测文件的模式:inferSchema
。我们可以像对待第一个选项一样,将它添加到我们的代码中:
val data = spark.read
.option("header", true)
**.option("inferSchema", true)**
.csv(filePath)
package
然后提交,您将得到一个稍微改进的模式版本:
root
|-- Department: string (nullable = true)
|-- Entity: string (nullable = true)
|-- Date of Payment: string (nullable = true)
|-- Expense Type: string (nullable = true)
|-- Expense Area: string (nullable = true)
|-- Supplier: string (nullable = true)
|-- Transaction Number: integer (nullable = true)
|-- Amount: double (nullable = true)
|-- Description: string (nullable = true)
|-- Supplier Post Code: string (nullable = true)
|-- Supplier Type: string (nullable = true)
更值得注意的是,Transaction Number
和Amount
字段现在分别是integer
和double
类型。其他的都保持为字符串,甚至是Date of Payment
列。让我们变得迂腐些,让它成为timestamp
类型。再次,火花来拯救!我们可以添加另一个选项来详细说明包含日期的列的格式:
val data = spark.read
.option("header", true)
.option("inferSchema", true)
**.option("timestampFormat", "dd/MM/yyyy")**
.csv(filePath)
结果模式应该如下所示:
root
|-- Department: string (nullable = true)
|-- Entity: string (nullable = true)
|-- Date of Payment: timestamp (nullable = true)
|-- Expense Type: string (nullable = true)
|-- Expense Area: string (nullable = true)
|-- Supplier: string (nullable = true)
|-- Transaction Number: integer (nullable = true)
|-- Amount: double (nullable = true)
|-- Description: string (nullable = true)
|-- Supplier Post Code: string (nullable = true)
|-- Supplier Type: string (nullable = true)
注意Date of Payment
列现在是timestamp
类型!我们现在有了一个类似表格的数据表示,其中包含了正确类型的列。来看看我们的数据吧!在data.printSchema
行之后,插入以下内容:
...
data.printSchema
**data.show
...**
打包并提交应用程序,在输出日志中,我们将看到显示的前 20 行:
+--------------------+---------------+-------------------+--------------------+--------------------+--------------------+------------------+----------+-----------+------------------+-------------+
| Department| Entity| Date of Payment| Expense Type| Expense Area| Supplier|Transaction Number| Amount|Description|Supplier Post Code|Supplier Type|
+--------------------+---------------+-------------------+--------------------+--------------------+--------------------+------------------+----------+-----------+------------------+-------------+
|Department for Bu...|UK Space Agency|2018-10-11 00:00:00|R & D Current Gra...|UK Space Agency -...|SCIENCE AND TECHN...| 241835| 38745.0| null| SN2 1SZ| WGA ONLY|
|Department for Bu...|UK Space Agency|2018-10-17 00:00:00|R & D Printing an...|UK Space Agency -...|ENGINEERING AND P...| 250485| 2256.94| null| SN2 1FF| VENDOR|
|Department for Bu...|UK Space Agency|2018-10-23 00:00:00|R & D Other Staff...|UK Space Agency -...|A.M. HEALTH & SAF...| 253816| 37.5| null| SN5 6BD| VENDOR|
|Department for Bu...|UK Space Agency|2018-10-17 00:00:00|R & D Other Profe...|UK Space Agency -...| QINETIQ LTD| 254217| 33320.0| null| GU14 0LX| VENDOR|
|Department for Bu...|UK Space Agency|2018-10-17 00:00:00|R & D Other Profe...|UK Space Agency -...| QINETIQ LTD| 254318| -5000.0| null| GU14 0LX| VENDOR|
|Department for Bu...|UK Space Agency|2018-10-17 00:00:00|R & D Other Profe...|UK Space Agency -...| QINETIQ LTD| 254318| 10000.0| null| GU14 0LX| VENDOR|
|Department for Bu...|UK Space Agency|2018-10-01 00:00:00|R & D Other Profe...| UKSA - UKSA|Border Consulting...| 255630| 571.06| null| GU51 3BE| VENDOR|
|Department for Bu...|UK Space Agency|2018-10-01 00:00:00|R & D Other Profe...| UKSA - UKSA|Border Consulting...| 255630| 16289.65| null| GU51 3BE| VENDOR|
|Department for Bu...|UK Space Agency|2018-10-01 00:00:00|R & D Other Profe...| UKSA - UKSA|Border Consulting...| 255630| 16289.65| null| GU51 3BE| VENDOR|
|Department for Bu...|UK Space Agency|2018-10-02 00:00:00|R & D Subsistence...| UKSA - UKSA|Personal Expense,...| 256572| 2.42| null| null| EMPLOYEE|
|Department for Bu...|UK Space Agency|2018-10-02 00:00:00|R & D Subsistence...| UKSA - UKSA|Personal Expense,...| 256572| 5.1| null| null| EMPLOYEE|
|Department for Bu...|UK Space Agency|2018-10-02 00:00:00|R & D Rail Travel...| UKSA - UKSA|Personal Expense,...| 256572| 35.4| null| null| EMPLOYEE|
|Department for Bu...|UK Space Agency|2018-10-02 00:00:00|R & D Subsistence...| UKSA - UKSA|Personal Expense,...| 256572| 39.97| null| null| EMPLOYEE|
|Department for Bu...|UK Space Agency|2018-10-26 00:00:00|R & D Other Profe...|UK Space Agency -...| Cabinet Office| 256868| -3570.0| null| FY5 3FW| WGA ONLY|
|Department for Bu...|UK Space Agency|2018-10-26 00:00:00|R & D Other Profe...|UK Space Agency -...| Cabinet Office| 256868| 1230.0| null| FY5 3FW| WGA ONLY|
|Department for Bu...|UK Space Agency|2018-10-26 00:00:00|R & D Other Profe...|UK Space Agency -...| Cabinet Office| 256868| 5910.0| null| FY5 3FW| WGA ONLY|
|Department for Bu...|UK Space Agency|2018-10-01 00:00:00|R & D Current Gra...|UK Space Agency -...|CENTRE NATIONAL D...| 256966| 127900.0| null| 31401| VENDOR|
|Department for Bu...|UK Space Agency|2018-10-01 00:00:00| R & D Contractors| UKSA - UKSA|Alexander Mann So...| 257048| 3435.24| null| EC2N 3AQ| VENDOR|
|Department for Bu...|UK Space Agency|2018-10-01 00:00:00| R & D Contractors|UK Space Agency -...|Alexander Mann So...| 257065| 2532.19| null| EC2N 3AQ| VENDOR|
|Department for Bu...|UK Space Agency|2018-10-02 00:00:00|R & D Current Gra...|UK Space Agency -...|SCIENCE AND TECHN...| 257213|2498072.42| null| SN2 1SZ| WGA ONLY|
+--------------------+---------------+-------------------+--------------------+--------------------+--------------------+------------------+----------+-----------+------------------+-------------+
only showing top 20 rows
我们有一个有点宽的表(抱歉的格式!),但你有望看到我们将要使用的一些价值观。
用我们的数据做些什么
现在我们已经有了一个真正的表状数据结构,我们可以开始进行分析了。首先,让我们简单地按Date of Payment
列降序排列数据。当我们在数据帧上操作时,Spark 提供了许多函数来执行这样的操作。我们可以简单地使用orderBy
函数来做我们想做的事情。我们还将使用desc
函数,向它传递我们想要排序的列的名称。Spark 中对数据帧的任何操作都会返回一个新的数据帧,因此我们将把返回的数据帧分配给orderedData
并显示它。我们还将输出的行数限制为 5,只是为了保持输出最小化。
...
data.show
**val orderedData = data.orderBy(desc("Date of Payment"))
orderedData.show(5)**
...
package
并提交,我们应该看到以下输出:
+--------------------+---------------+-------------------+--------------------+--------------------+--------------------+------------------+--------+-----------+------------------+-------------+
| Department| Entity| Date of Payment| Expense Type| Expense Area| Supplier|Transaction Number| Amount|Description|Supplier Post Code|Supplier Type|
+--------------------+---------------+-------------------+--------------------+--------------------+--------------------+------------------+--------+-----------+------------------+-------------+
|Department for Bu...|UK Space Agency|2018-10-31 00:00:00|R & D Office Supp...|UK Space Agency -...| OFFICE DEPOT UK LTD| 261459| 145.57| null| SP10 4JZ| VENDOR|
|Department for Bu...|UK Space Agency|2018-10-31 00:00:00| R & D Other Travel|UK Space Agency -...|Personal Expense,...| 261508| 6.14| null| null| EMPLOYEE|
|Department for Bu...|UK Space Agency|2018-10-31 00:00:00|R & D Other Profe...|UK Space Agency -...|Geospatial Insigh...| 261474| 13475.0| null| B46 3AD| GRANT|
|Department for Bu...|UK Space Agency|2018-10-31 00:00:00|R & D Current Gra...|UK Space Agency -...|REACTION ENGINES LTD| 261327|167000.0| null| OX14 3DB| GRANT|
|Department for Bu...|UK Space Agency|2018-10-31 00:00:00|R & D Hotel & Acc...| UKSA - UKSA|Personal Expense,...| 261505| 114.0| null| null| EMPLOYEE|
+--------------------+---------------+-------------------+--------------------+--------------------+--------------------+------------------+--------+-----------+------------------+-------------+
only showing top 5 rows
恭喜你!您已经能够使用 Apache Spark 加载 CSV 文件,并学习了如何使用带有desc
的orderBy
方法执行基本排序。
这一版就完成了!下次回来时,我们将研究如何使用 Spark 来回答一些基于我们已有数据的商业问题。