TowardsDataScience-博客中文翻译-2016-2018-二-

龙哥盟 / 2024-10-13 / 原文

TowardsDataScience 博客中文翻译 2016~2018(二)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

张量流入门(第 1 部分)

原文:https://towardsdatascience.com/a-beginner-introduction-to-tensorflow-part-1-6d139e038278?source=collection_archive---------0-----------------------

Tensorflow 是广泛用于实现机器学习和其他涉及大量数学运算的算法的库之一。Tensorflow 由 Google 开发,是 GitHub 上最受欢迎的机器学习库之一。Google 使用 Tensorflow 在几乎所有应用程序中实现机器学习。例如,如果你正在使用谷歌照片或谷歌语音搜索,那么你正在间接使用张量流模型,它们在谷歌硬件的大型集群上工作,在感知任务中非常强大。

这篇文章的主要目的是向初学者友好地介绍 TensorFlow,我假设你已经了解一点 python。TensorFlow 的核心组件是计算图和通过边在所有节点间遍历的张量。下面我们就来简单介绍一下其中的每一个。

张量:

数学上,张量是一个 N 维向量,这意味着张量可以用来表示 N 维数据集。上图很难理解。我们将看看它的简化版本

上图显示了一些具有最小维数的简化张量。随着维度的不断增加,数据表示变得越来越复杂。例如,如果我们取一个(3x3)形式的张量,那么我可以简单地称它为 3 行 3 列的矩阵。如果我选择另一个形式的张量(1000x3x3),我可以称它为一个向量或 1000 个 3x3 矩阵的集合。这里我们称(1000x3x3)为结果张量的形状或维度。张量可以是常数,也可以是变量。

计算图表(流程):

现在我们理解了张量的真正含义,是时候理解流动了。这个流程指的是计算图或简单的图,图不可能是循环的,图中的每个节点代表一个操作,如加、减等。并且每个操作导致新张量的形成。

上图显示了一个简单的计算图表。计算图形具有以下属性:

上图的表达式:

e = (a+b)x(b+1)

  • 叶顶点或开始顶点总是张量。也就是说,一个操作永远不会出现在图的开始,因此我们可以推断图中的每个操作应该接受一个张量并产生一个新的张量。同样,张量不能作为非叶节点出现,这意味着它们应该始终作为操作/节点的输入。
  • 计算图总是以层次顺序表示复杂的操作。上述表达式可以用分层的方式组织,将 a+b 表示为 c,b+1 表示为 d。因此,我们可以将 e 写成:

e = (c)x(d)其中 c = a+b,d = b+1。

  • 以相反的顺序遍历图导致子表达式的形成,这些子表达式被组合以形成最终表达式。
  • 当我们向前遍历时,我们遇到的顶点总是成为下一个顶点的依赖,例如没有 a 和 b 就不能得到 c,同样地,没有 c 和 d 的解就不能得到 e。
  • 同级节点中的操作相互独立。这是计算图的重要性质之一,当我们以图中所示的方式构造一个图时,很自然地,同一层中的节点(例如 c 和 d)是相互独立的,这意味着在计算 d 之前不需要知道 c,因此它们可以并行执行。

计算图形中的并行性;

上面提到的最后一个属性当然是最重要的属性之一,它清楚地表明同一级别的节点是独立的,这意味着在 c 求值之前没有必要闲置,当 c 仍在求值时,您可以并行计算 d。Tensorflow 很好地利用了这一特性。

分布式执行:

Tensorflow 允许用户利用并行计算设备更快地执行操作。计算的节点或操作被自动调度用于并行计算。这一切都发生在内部,例如在上面的图中,操作 c 可以在 CPU 上调度,而操作 d 可以在 GPU 上调度。下图显示了分布式执行的两种前景:

第一种是单系统分布式执行,其中单个 Tensorflow 会话(将在后面解释)创建单个工作进程,该工作进程负责在各种设备上调度任务;第二种情况下,有多个工作进程,它们可以在同一台机器上或不同的机器上,每个工作进程在其自己的上下文中运行,在上图中,工作进程 1 在单独的机器上运行,并在所有可用的设备上调度操作。

计算子图:

子图是主图的一部分,本质上是计算图。例如,在上图中,我们可以获得许多子图,其中一个如下所示

上图是主图的一部分,从性质 2 我们可以说一个子图总是代表一个子表达式,因为 c 是 e 的子表达式。子图也满足最后一个性质。同一层的子图也是相互独立的,可以并行执行。因此,可以在单个设备上调度整个子图。

上图解释了子图的并行执行。这里有两个矩阵乘法运算,因为它们都在同一级,它们相互独立,这适用于最后一个属性。这些节点被调度在不同的设备 gpu_0 和 gpu_1 上,这是因为它们具有独立性。

工人之间交换数据:

现在我们知道 Tensorflow 将其所有操作分布在由工人管理的不同设备上。更常见的是,在工作者之间交换张量形式的数据,例如在 e =(c)*(d)的图中,一旦计算出 c,就希望将其进一步传递给过程 e,因此张量从节点向上流到节点。这种移动如图所示:

这里,来自设备 A 的张量被传递到设备 b,这导致了分布式系统中的一些性能延迟。延迟取决于一个重要的性质,即张量的大小。设备 B 处于理想模式,直到它从设备 a 接收到输入。

压缩需求:

很明显,在计算图形中,张量在节点之间流动。在流到达可以处理它的节点之前,减少由流引起的延迟是很重要的。减小尺寸的一个这样的想法是通过使用有损压缩。

张量的数据类型起着重要作用,让我们来理解为什么,很明显,我们在机器学习操作中追求更高的精度,例如,如果我们使用 float32 作为张量的数据类型,那么每个值都使用 32 位浮点数表示,因此每个值占用 32 位的大小,这同样适用于 64 位。假设一个形状为(1000,440,440,3)的张量,可以包含在该张量中的值的数量将是 1000440440*3。如果数据类型是 32 位,那么它是这个大数字的 32 倍,它在内存中占据了相当大的空间,因此造成了流的延迟。可以使用压缩技术来减小大小。

有损压缩:

有损压缩处理压缩数据的大小,并不关心它的值,这意味着它的值可能会在压缩过程中损坏或不准确。但是,如果我们有一个 32 位浮点数,如 1.01010e-12,那么最低有效位的重要性就会降低。更改或删除这些值不会对我们的计算产生太大影响。因此,Tensorflow 通过忽略所有可忽略的数字,自动将 32 位浮点数转换为 16 位表示,这将大小减少近一半,如果是 64 位数字,压缩到 16 位将导致大小减少近 75%。因此张量占据的空间可以最小化。

一旦张量到达节点,16 位表示就可以通过添加 0 恢复到原始形式。因此,32 或 64 位表示在到达节点进行处理后被买回。

张量流介绍的第 1 部分到此结束,编程和构造简单的子图将在下一部分解释。

谢谢☺

RNN 情感分析初学者指南

原文:https://towardsdatascience.com/a-beginners-guide-on-sentiment-analysis-with-rnn-9e100627c02e?source=collection_archive---------4-----------------------

Photo Credit: Unsplash

情感分析大概是自然语言处理中最常见的应用之一。客户服务工具情绪分析变得有多重要,我就不用强调了。所以在这里,我们将使用递归神经网络在 IMDB 数据集中训练一个分类器电影评论。如果你想深入深度学习进行情感分析,这是一篇很好的论文。

数据

我们将使用递归神经网络,特别是lstm,在 Keras 中执行情感分析。方便的是,Keras 有一个内置的 IMDb 电影评论数据集,我们可以使用。

from keras.datasets import imdb

设置训练和测试数据中的词汇大小和负载。

vocabulary_size = 5000(X_train, y_train), (X_test, y_test) = imdb.load_data(num_words = vocabulary_size)
print('Loaded dataset with {} training samples, {} test samples'.format(len(X_train), len(X_test)))

加载了 25000 个训练样本的数据集,25000 个测试样本

检查样本评论及其标签。

print('---review---')
print(X_train[6])
print('---label---')
print(y_train[6])

Figure 1

注意,评论被存储为一个整数序列。这些是预先分配给单个单词的单词 id,标签是一个整数(0 表示负,1 表示正)。

我们可以用imdb.get_word_index()返回的字典把复习映射回原来的单词。

word2id = imdb.get_word_index()
id2word = {i: word for word, i in word2id.items()}
print('---review with words---')
print([id2word.get(i, ' ') for i in X_train[6]])
print('---label---')
print(y_train[6])

Figure 2

最大评论长度和最小评论长度。

print('Maximum review length: {}'.format(
len(max((X_train + X_test), key=len))))

最大评论长度:2697

print('Minimum review length: {}'.format(
len(min((X_test + X_test), key=len))))

最小审核长度:14

焊盘序列

为了将这些数据输入到我们的 RNN 中,所有输入文档必须具有相同的长度。我们将通过截断较长的评论并用空值(0)填充较短的评论,将最大评论长度限制为 max_words。我们可以使用 Keras 中的 pad_sequences()函数来实现这一点。现在,将 max_words 设置为 500。

from keras.preprocessing import sequencemax_words = 500
X_train = sequence.pad_sequences(X_train, maxlen=max_words)
X_test = sequence.pad_sequences(X_test, maxlen=max_words)

设计一个用于情感分析的 RNN 模型

我们开始在下面的代码单元中构建我们的模型架构。我们从 Keras 中导入了一些你可能需要的层,但是你可以随意使用任何你喜欢的层/转换。

记住我们的输入是最大长度= max_words 的单词序列(技术上是整数单词 id),我们的输出是二元情感标签(0 或 1)。

from keras import Sequential
from keras.layers import Embedding, LSTM, Dense, Dropoutembedding_size=32
model=Sequential()
model.add(Embedding(vocabulary_size, embedding_size, input_length=max_words))
model.add(LSTM(100))
model.add(Dense(1, activation='sigmoid'))print(model.summary())

Figure 3

总之,我们的模型是一个简单的 RNN 模型,具有 1 个嵌入层、1 个 LSTM 层和 1 个致密层。总共需要训练 213,301 个参数。

训练和评估我们的模型

我们首先需要通过指定我们在训练时想要使用的损失函数和优化器,以及我们想要测量的任何评估指标来编译我们的模型。指定适当的参数,包括至少一个度量“准确性”。

model.compile(loss='binary_crossentropy', 
             optimizer='adam', 
             metrics=['accuracy'])

一旦编译完成,我们就可以开始培训过程了。我们必须指定两个重要的训练参数——批量大小和训练时期的数量,它们与我们的模型架构一起决定了总的训练时间。

训练可能需要一段时间,所以喝杯咖啡,或者去跑步更好!

batch_size = 64
num_epochs = 3X_valid, y_valid = X_train[:batch_size], y_train[:batch_size]
X_train2, y_train2 = X_train[batch_size:], y_train[batch_size:]model.fit(X_train2, y_train2, validation_data=(X_valid, y_valid), batch_size=batch_size, epochs=num_epochs)

Figure 4

一旦我们训练了我们的模型,就该看看它在看不见的测试数据上表现如何了。

如果我们通过度量=['accuracy'],scores[1]将对应于准确性

scores = model.evaluate(X_test, y_test, verbose=0)
print('Test accuracy:', scores[1])

测试精度:0.86964

摘要

有几种方法可以用来建立我们的模型。我们可以通过试验不同的架构、层和参数来继续尝试和提高我们模型的准确性。如果不花太多时间训练,我们能有多好?我们如何防止过度拟合?

源代码可以在 Github 找到。期待听到反馈或问题。

参考: Udacity — NLP

脑机接口和卷积神经网络初学者指南

原文:https://towardsdatascience.com/a-beginners-guide-to-brain-computer-interface-and-convolutional-neural-networks-9f35bd4af948?source=collection_archive---------0-----------------------

简单并附有定义。

Futurist / Humanist Gerd Leonhard

路标

Part 1: 脑机接口与 AI +研究论文大图

第 2 部分:
深入解释与 BCI 一起使用的神经网络

大脑能否通过脑机接口(BCI)技术直接与人工智能、机器人和其他大脑连接,以超越我们人类的局限性?

对一些人来说,这是我们生存的必需品。事实上,我们需要成为电子人才能在人工智能时代发挥作用。

定义

脑-机接口(BCI): 仅通过大脑活动使用户能够与计算机交互的设备,这种活动通常通过脑电图(EEG)来测量。

脑电图(EEG): 通过放置在头皮表面的电极记录大脑产生的电活动的首选生理方法。

功能磁共振成像(fMRI): 通过检测与血流相关的变化来测量大脑活动。

功能性近红外光谱 ( fNIRS ):使用近红外光谱(NIRS)进行功能性神经成像。使用 fNIRS,通过与神经元行为相关的血液动力学反应来测量大脑活动。

卷积神经网络(CNN): 一种用于图像识别和处理的人工神经网络,专门用于处理像素数据。

视觉皮层:大脑皮层的一部分,接收和处理来自眼睛的感觉神经冲动

历史

《卫报》记者莎拉·马希说:“脑机接口(BCI)并不是一个新想法。已经有各种形式的 BCI,从放在你头顶上测量大脑信号的设备到植入你大脑组织的设备。”(来源)

大多数脑机接口最初是为医疗应用开发的。Tellart 的首席设计师 Zaza Zuilhof 表示,“大约 22 万名听力受损者已经从耳蜗植入中受益,耳蜗植入可以将音频信号转化为电脉冲,直接发送到他们的大脑。”(来源)

这篇文章名为《脑机接口简史》给我们提供了许多与 BCI 历史有关的信息。事实上,文章说“在 20 世纪 70 年代,对脑机接口的研究在加州大学开始,这导致了大脑-计算机接口这一表达的出现。BCI 研发的重点仍然是神经假体的应用,这有助于恢复受损的视觉、听觉和运动。20 世纪 90 年代中期,标志着人类第一个神经假体装置的出现。BCI 并不准确地解读思想,但当你以某种方式思考时,它能探测到大脑辐射能量的最小变化。BCI 识别大脑中特定的能量/频率模式。

【2004 年 6 月【Matthew Nagle 成为第一个植入 cyber kinetics BrainGate BCI 的人,标志着该领域的一项重大发展。

2004 年 12 月,Jonathan Wolpaw 和纽约州卫生部沃兹沃斯中心的研究人员提交了一份研究报告,展示了使用 BCI 控制电脑的能力。在这项研究中,患者被要求戴上一顶包含电极的帽子,以捕捉来自运动皮层的脑电图信号,运动皮层是大脑控制运动的一部分。

BCI 在控制应用方面有着悠久的历史:光标、瘫痪的身体部位、机械臂、电话拨号等。

最近,埃隆·马斯克(Elon Musk)进入了这个行业,宣布向 Neuralink 投资 2700 万美元,这是一家旨在开发一种 BCI 的风险投资公司,该公司根据人工智能改善人类沟通。Regina Dugan 介绍了脸书的计划,该计划将改变 BCI 技术的游戏规则,提高数字通信的效率。"

根据约翰·托马斯、托马兹·马斯奇克、尼尚特·辛哈、蒂尔曼·克鲁格、贾斯汀·道韦尔斯“一个 BCI 系统有四个主要组成部分:信号采集、信号预处理、特征提取和分类。”(来源)

这有什么关系?

埃塞克斯大学脑机接口博士后研究员 Davide Valeriani 说:“人类和技术的结合可能比人工智能更强大。例如,当我们基于感知和推理的结合来做决定时,神经技术可以用来改善我们的感知。这有助于我们应对一些情况,比如从安全摄像头看到非常模糊的图像,不得不决定是否干预。”(来源

这些脑机接口实际上能做什么?

对于 Zaza Zuilhof 来说,这取决于你问谁,以及你是否愿意接受手术。“为了这个思想实验的目的,让我们假设健康的人只会使用不需要手术的非侵入性脑机接口。既然如此,目前主要有两种技术,fMRI 和 EEG。第一种需要一个巨大的机器,但第二种,通过像 Emotiv 和 Neurosky 这样的消费耳机,实际上已经可以为更普通的观众所用。”(来源)

Source

然而,BCI 也可以成为健康人的一种有前途的交互工具,在多媒体、虚拟现实或视频游戏领域以及许多其他潜在应用中有几个潜在的应用。

Davide Valeriani 说,“脑电图硬件对用户来说是完全安全的,但记录的信号非常嘈杂。此外,到目前为止,研究实验室主要集中在使用它来了解大脑和提出创新应用,而没有任何商业产品的后续行动……但这将会改变。(来源)

马斯克的公司是最新的。其“神经花边”技术包括在大脑中植入电极来测量信号。这将允许获得比脑电图质量更好的神经信号——但这需要手术。最近,他表示,需要脑机接口来确认人类对人工智能的优势。"(来源)

这个技术还是很危险的!事实上,我们制造了计算机,并且确切地知道它们如何工作以及如何“修改”它们。然而,我们并没有制造大脑,我们仍然不知道它们是如何工作的。更不用说如何安全成功地“入侵”它们了。我们已经取得了很大的进步,但还不够。

你的大脑现在是如何工作的,以及未来会发生什么

简单来说,你的大脑分为两个主要部分:

  • 边缘系统
  • 新大脑皮层。

边缘系统负责我们的原始欲望,以及那些与生存有关的欲望,如进食和繁殖。我们的新大脑皮层是最高级的区域,它负责逻辑功能,使我们擅长语言、技术、商业和哲学。

人类大脑包含大约 86 个称为神经元的胆神经细胞,每个细胞都通过称为轴突和树突的连接器与其他神经元相连。每当我们思考、移动或感觉时,神经元都在工作。事实上,大脑产生大量的神经活动。基本上,从一个神经元到另一个神经元的微小电信号在起作用。

有许多信号可以用于 BCI。这些信号可以分为两类:
-尖峰信号
-场电位

我们可以检测这些信号,解释它们,并使用它们与设备进行交互。

Cortext 的机器学习顾问鲍里斯·鲁德林克(Boris Reuderink)表示,“脑机接口的一个更大的问题是,大脑信号很弱,非常多变。这就是为什么很难训练一个分类器,并在第二天使用它,更不用说在不同的主题上使用它了。”(来源)

为了插入神经带,一根包含卷起来的网状物的微小的针被放置在颅骨内。该网状物然后被注射并在注射时被揭开,包围大脑。

人工智能或机器学习已经受到极大关注,用于开发 BCI 应用来解决几个领域中的困难问题,特别是医疗和机器人领域。AI/ML 已经成为 BCI 系统最有效的工具。( 来源 )

下面让我们试着详细阐述一下这些方面。这些方面都有各自的研究领域。

信号产生
产生这些大脑信号有两种方式:

****据Sjoerd LagardeQuintiq 的软件工程师“主动产生信号的好处是信号检测更容易,因为你对刺激有控制权;比如当他们出现的时候。如果你只是在读取受试者的脑电波,这就更难了。”

信号检测
检测大脑信号有不同的方法。最著名的是脑电图和功能磁共振成像,但也有其他的。脑电图测量大脑的电活动,功能磁共振成像测量大脑中的血流。这些方法各有其优缺点。一些具有更好的时间分辨率(它们可以在大脑活动发生时检测到),而另一些具有更好的空间分辨率(它们可以精确定位活动的位置)。

这个想法对于其他类型的测量技术来说基本上是一样的。

****信号处理例如,当使用脑电图时,像磨牙这样的事情会显示在数据中,还有眼球运动。这种噪音需要过滤掉。

该数据现在可用于检测实际信号。当受试者主动产生信号时,我们通常会意识到我们想要检测的信号类型。一个例子是 P300 波,这是一种所谓的事件相关电位,当出现不频繁的任务相关刺激时就会出现。这种波动将在您的数据中显示为一个大的峰值,您可能会尝试机器学习的不同技术来检测这样的峰值。

信号转导
当你在数据中检测到了感兴趣的信号,你想以某种对某人有帮助的方式使用它们。例如,受试者可以使用 BCI 通过想象的运动来控制鼠标。这里你会遇到的一个问题是,你需要尽可能有效地使用你从受试者那里得到的数据,同时你必须记住,BCI 氏症可能会出错。目前的 BCI 相对较慢,偶尔会出错(例如,计算机认为你想象的是左手运动,而实际上你想象的是右手运动)。"(来源)

在神经带的例子中,它将自己与人脑整合在一起。它在人和机器之间创造了完美的共生关系。

这两个部分相互共生。一个人工智能层或第三界面可以位于它们之上,将我们插入一个非常新的先进的世界,并使我们能够与我们的人工智能机器人朋友保持一致。

这种连接可以让我们获得更多的记忆存储,惊人的机器学习能力,是的,不需要说话就可以与他人进行心灵感应式的交流。

“你有一个你自己的机器延伸,以你的电话、电脑和所有应用程序的形式存在。。。迄今为止,你比 30 年前的美国总统拥有更多权力和能力,”埃隆·马斯克说

BCI 的种类

《富有同情心的人工智能》的作者阿米特·雷(Amit Ray)表示:“最复杂的脑机接口是“双向”脑机接口,它既可以记录神经系统,也可以刺激神经系统。
脑机接口可分为三大类:

在侵入性技术中,必须使用特殊的设备来捕获数据(脑信号),这些设备通过关键的手术直接插入人脑。在半侵入式中,设备被插入到人类大脑顶部的头骨中。一般来说,非侵入性被认为是最安全和低成本的设备类型。然而,由于头骨的阻碍,这些设备只能捕捉到“较弱”的人脑信号。大脑信号的检测是通过放置在头皮上的电极实现的。

有几种方法可以开发无创的脑机接口,如 EEG(脑电图)、MEG(脑磁图)或 MRT(磁共振断层成像)。基于脑电图的脑机接口是研究 BCI 最受欢迎的类型。EEG 信号在控制信号中被处理和解码,这是计算机或机器人设备容易感知的。处理和解码操作是构建高质量 BCI 的最复杂的阶段之一。特别是,这项任务非常困难,以至于科学机构和各种软件公司不时地组织竞赛来为 BCI 创建 EEG 信号分类。

卷积神经网络和 BCI

CNN 是一种基于视觉皮层的人工智能神经网络。它能够通过前向和后向传播优化每个滤波器的权重参数,从输入数据中自动学习适当的特征,以最小化分类错误。

人类的听觉皮层是以分层组织的方式排列的,类似于视觉皮层。在层级系统中,当感觉信息流经系统时,一系列的大脑区域对感觉信息执行不同类型的计算。早期区域或“初级视觉皮层”对颜色或方向等简单特征做出反应。后期阶段实现更复杂的任务,如对象识别。

使用深度学习技术的一个优点是它需要最少的预处理,因为最佳设置是自动学习的。关于 CNN,特征提取和分类被集成到单个结构中并被自动优化。此外,人类受试者的 fNIRS 时间序列数据被输入到 CNN。由于卷积以滑动显示方式进行,CNN 的特征提取过程保留了 fNIRS 获得的时间序列数据的时间信息。

Source

然而,BCI 研究中最大的问题之一是大脑信号的非平稳性。这个问题使得分类器很难在信号中找到可靠的模式,导致不良的分类性能。"(来源)

你如何从零开始了解 BCI?

航空航天工程博士生 Hosea Siu 表示,“对于直接的‘大脑’接口,你需要一组脑电图电极,对于周围神经系统接口,你需要肌电图电极。

一旦你能把数据输入电脑,你就需要做一些信号调节。比如过滤你要寻找的信号频率,过滤掉环境噪音(在美国,电线产生的 60 赫兹噪音很常见……)。

之后,你需要考虑你实际上想要让系统做什么。当你想到蓝色时,你需要它来检测你的脑电图模式的特殊变化吗?或者当你移动手指时,你需要它来检测你的肌电图的变化吗?电脑呢?它应该运行一个程序吗?键入一些文本?

想想你将如何标记你的数据。计算机最初如何知道一个特定的信号是有意义的?

这是监督学习。选择您喜欢的分类方法,获取大量标记数据,并训练您的系统。您可以使用交叉验证等方法来检查您训练的模型是否在做您认为它们应该做的事情。

做完这些,你可能会有一个看起来像脑机接口的东西。"(来源)

在哪里可以找到脑机接口上机器学习的数据集?

您可以在以下网站找到几个公开的脑电图数据集:

  • 免费脑电图数据库免费 ERP 数据公开可用
  • 柏林脑机接口

人工智能和强化学习与神经接口技术的最新进展以及各种信号处理方法的应用,使我们能够更好地理解并利用大脑活动与计算机和其他设备进行交互。

了解更多信息

  • https://www . the guardian . com/technology/2018/Jan/01/elon-musk-neuro technology-human-enhancement-brain-computer-interfaces
  • https://www . core 77 . com/posts/72957/When-Brain-Computer-Interfaces-Go-Mainstream-Will-Dystopian-Sci-Fi-Be-Our-Only-Guidance
  • http://www . brain vision . co . uk/blog/2014/04/the-brief-history-of-brain-computer-interfaces/
  • https://ieeexplore.ieee.org/document/8122608
  • https://observer . com/2017/04/elon-musk-wants-to-merge-man-and-machine-artificial-intelligence-EEG-neuro technology/
  • https://medium . com/dx lab-design/how-will-brain-computer-interfaces-change-your-life-aa 89 b 17 c 3325
  • https://team.inria.fr/potioc/bci-2/
  • https://pdfs . semantic scholar . org/5088/ab 0900 ef7d 06023796 f 651 f 4 ee 5 fa 0 FB 36 a 0 . pdf
  • https://www . quora . com/What-a-good-machine-learning-project-containing-brain-computer-interfaces
  • https://www . quora . com/How-do-current-brain-computer-interfaces-work
  • https://amitray . com/brain-computer-interface-体恤-ai/
  • https://www . quora . com/How-can-I-start-learning-about-brain-computer-interface-from scratch

决策树分类初学者指南

原文:https://towardsdatascience.com/a-beginners-guide-to-decision-tree-classification-6d3209353ea?source=collection_archive---------3-----------------------

决策树是最流行的机器学习算法之一,但也是最强大的。本文将从非技术角度解释它们是如何工作的。

它们如此强大的原因之一是因为它们很容易被可视化,因此人类可以理解正在发生的事情。想象一个流程图,其中每一层都是一个带有是或否答案的问题。最终一个答案会给你一个最初问题的解决方案。那是一棵决策树。每个人都下意识地使用决策树来完成最琐碎的任务。机器学习中的决策树利用这种能力,并将其放大,以便能够人工执行复杂的决策任务。

很多时候,很难理解机器学习算法是如何做出决定的,这使得它们无法用于许多场景。对于可能需要对决策提出异议的情况,尤其如此,例如在刑事司法系统、卫生行业和战略性商业决策中。对于面向客户的机器学习算法来说,这甚至是一个更重要的因素,因为根据 GDPR,客户有“权利获得解释。决策树的人类理解能力是一个主要的优势。

决策树分析数据集,以构建一组规则或问题,用于预测类别。让我们考虑一个由许多不同动物和它们的一些特征组成的数据集。这些特征可以用来预测他们的阶级。如果我们拿一只鹰和一头大象来说,一个能把这两种动物分开的问题会是‘这种动物有两条腿吗?’或者可能是“这只动物体重在 500 公斤以下吗?”。对这两个问题中的任何一个回答“否”都会导致大象的分类,而“是”会导致鹰的分类。

可以建立这些规则来创建一个可以对复杂情况进行分类的模型。为了扩展动物分类的例子,考虑需要将选择的动物分类为哺乳动物、鸟类、鱼类的场景。查看可视化决策树,了解如何使用两个简单的问题来拆分数据。

这些简单的问题一个接一个地分层,允许对各种各样的动物进行分类。这就是决策树的力量。现在,如果我们给训练好的决策树一个新的动物,比如一只狗,它会对它进行分类。狗会呼吸空气吗?是的。狗会下蛋吗?不。因此模型会将其归类为哺乳动物,正确答案!

当一个人构建决策树时,问题和答案是基于他们的逻辑和知识的。在数据科学中,这些规则的创建通常由算法控制,该算法通过分析整个数据集来学习要问哪些问题。为了将这放入上下文中,我们将回到动物的例子,算法将查看所有的动物,以找出所有不呼吸空气的动物,并注意到它们都是鱼。这在数学上将数据集按其类别进行分割。这创造了强大的算法,可以以任何人都可以理解的方式将新数据分类。

决策树在作为整体使用时会变得更加强大。集成是结合决策树创建更强大模型的聪明方法。这些集成创造了最先进的机器学习算法,在某些情况下可以胜过神经网络。两种最流行的集成技术是随机森林和梯度推进。

感谢您的阅读。请查看我的下一篇文章深度学习初学者指南。或者,如果你对数据科学初学者指南或人工智能应用于商业的更多文章感兴趣,请访问 Miminal 。

自然语言处理初学者指南

原文:https://towardsdatascience.com/a-beginners-guide-to-natural-language-processing-e21e3e016f84?source=collection_archive---------0-----------------------

当我开始作为一名数据科学家的旅程时,最吸引人的是寻求理解单词的意义和影响的自然语言处理(NLP)。

NLP 最伟大的方面之一是它跨越了计算研究的多个领域,从人工智能到计算语言学,都在研究计算机和人类语言之间的交互。它主要关注编程计算机准确快速地处理大量的自然语言语料库。什么是自然语言语料库?它是对现实世界语言所表达的语言的研究。它是一种理解文本中一组抽象规则以及语言与另一种语言之间关系的综合方法。

虽然 NLP 在现代计算机工业革命中变得更加重要,但它实际上是令人惊叹的艾伦·图灵的大脑产物,他在帮助破解德国 Enigma 编码机器的同时,还写了一篇题为“计算机器和智能”的文章,该文章首次提出了将人类语言与计算机联系起来的严肃用途。随着技术在我们日常生活中的无处不在,我们已经看到了自然语言处理通过革命性的工具如谷歌翻译、IBM 沃森、语音识别和生成以及情感分析对我们日常生活的影响。

然而,像所有的事情一样,NLP 也有一些问题和缺点。当一个人说话时,它努力产生自然流动的语言,就像你读一部糟糕的电影剧本时一样,听起来像是计算机在说话。虽然有一些方法可以尝试理解语调的变化,但 NLP 仍然难以理解讽刺和幽默。然而,这是一个需要深入研究的领域,我期待着“讽刺突破”出现的那一天。不为别的,就是为了更好地理解朋友偶尔发来的短信或即时消息。

目前可用的一些最有用的计算机/数据科学工具有:

计数向量化、哈希向量化、词频-逆文档频率(TF-IDF)、词汇化、词干分析、解析和情感分析。

CounterVectorization 是一个 SciKitLearn 库工具,它获取任意数量的文本,并将每个唯一的单词作为一个特征返回,并计算该单词出现的次数。虽然这可以生成许多特性,但这些特性是一些非常有用的参数,有助于避免这种情况,包括停用词、n_grams 和 max_features。停用字词会生成一个不会作为特征包括在内的字词列表。它的主要用途是在“英语”词典中删除无关紧要的单词,如“is,The,a,it,as ”,这些单词可能会频繁出现,但对我们的最终目标几乎没有影响。Ngram_range 选择如何将单词组合在一起。不是让 NLP 分别返回每个单词,而是如果它等于 2,您可以得到类似“Hello again”或“See you later”的结果,如果它等于 3。Max_features 是您选择创建的要素数量。如果你选择它等于无,这意味着你会得到所有的单词作为特征,但如果你设置它等于 50,你只会得到 50 个最常用的单词。

哈希矢量器使用“哈希技巧”将文本转换为出现矩阵,每个单词映射到一个特征,使用哈希函数将其转换为哈希。如果该单词在文本主体中再次出现,则它被转换成相同的特征,这允许我们在相同的特征中对其进行计数,而无需在存储器中保留字典。

TF-IDF 揭示了在不同的文本主体中,哪些词最有区别。如果您试图看到在一个文档中多次出现但在其他文档中没有出现的单词之间的差异,这将特别有帮助,从而使您可以解释该文档的一些特殊之处。它取决于术语频率、一个单词出现的频率以及逆文档频率,即它在所有文档中是唯一的还是共有的。

词汇化是将单词的屈折形式组合在一起作为单个方面进行分析的过程。它是一种利用一个词的预期意义来确定“引理”的方法。这在很大程度上取决于在一个句子、段落或更大的文档中正确地找到“预期的词类”和一个词的真正含义。例如,“run”是“running”或“ran”等词的基本形式,或者“better”和“good”在同一个词条中,因此它们被认为是相同的。

词干与词汇归类非常相似,它将单词组合在一起,但与词汇归类不同的是,它将一个单词引用回它的基本形式或词根形式。事实上,在我遇到的描述它的最好的例子中,涉及到词干回溯到它的基本形式。“词干”、“词干化”、“词干化”、“词干化”都是基于单个词“词干”。

解析一般用途是分析一串单词以形成语法规则。对于 NLP 来说,它是对一串单词的分析,产生一个解析树,揭示单词之间的句法关系,它可以包含语义。然而,解析的一个缺点是,何时解析和解析什么完全取决于用户,因为任何段落都可以以他们选择的任何方式解析,从单个字符到整个句子等等。

情感分析最简单的定义是从一个文档或一组文档中提取单词的解释或主观含义,以确定特定单词或一组单词的“态度”。它最大的用途之一是在脸书、推特和其他社交媒体上识别公众意见的趋势,一个词在特定音调环境中出现的频率,以及解释一组词的音调。

在做任何和所有这些分析之前,我强烈建议您过滤和清理您正在处理的任何文档。我遇到的最好的函数之一是由我的一位老师 Mark Mummert 创建的。虽然它的重点是通过使用漂亮的汤清理 html 文件,但它可以很容易地适用于其他 NLP 清理。

def review_to_words(raw_review):
      #Remove html
      review_text=BeautifulSoup(raw_review).get_text()
      #Remove non-letters - Utilized Regex Library
      letters_only = re.sub("[^a-zA-Z]", " ", review_text)
      #Conver to lowercase and split into individual words
      words = letters_only.lower().split()
      #Convert Stop-Words to a set and remove them
      stops = set(stopwords.words("english"))
      meaningful_words = [w **for** w **in** words **if** **not** w **in**    stops]
      #Join the Words back into one string seperated by a  space and return the result.
      **return**( " ".join( meaningful_words ))

NLP 的世界是巨大而复杂的,并且仍然是一个需要大量研究的领域。有许多有用的工具,所有这些工具在解释和利用文字世界方面都有极其有益的用途。

对于 python 用户来说,我相信你对 NLP 最有用的资源是 Sci-Kit Learn 库和 NLTK 库。

神经网络初学者指南:第一部分

原文:https://towardsdatascience.com/a-beginners-guide-to-neural-networks-b6be0d442fa4?source=collection_archive---------1-----------------------

神经网络背后的动机,以及最基本的网络背后的架构:感知器。

人类是难以置信的模式识别机器。我们的大脑处理来自世界的“输入”,对它们进行分类(那是一只蜘蛛;那是冰淇淋),然后生成一个‘输出’(逃离蜘蛛;品尝冰淇淋)。我们自动地、快速地做到这一点,不费吹灰之力。这和感觉到有人在生我们的气,或者在我们加速经过时不由自主地读出停车标志是同一个系统。心理学家将这种思维模式称为“系统 1”(由 Keith Stanovich 和 Richard West 创造),它包括我们与其他动物共有的先天技能,如感知和恐惧。(还有一个“系统 2”,如果你想了解更多这方面的内容,可以看看丹尼尔·卡内曼的 思考,快与慢)。

那么这和神经网络有什么关系呢?我马上就到。

你毫不费力地认出了上面的数字,对吗?你刚刚知道第一个数字是 5;你不必真的去想它。当然,你的大脑不会说,“啊,那看起来像两条正交的线连接着一个旋转的,没有根据的半圆,所以那是一个 5。”设计识别手写数字的规则是不必要的复杂,这就是为什么历史上计算机程序很难识别它们。

Oh, Apple Newton. (Source: Gary Trudeau for Doonesbury)

神经网络粗略地模拟了我们大脑解决问题的方式:接受输入,处理它们并生成输出。像我们一样,他们学习识别模式,但他们是通过在标记数据集上训练来做到这一点的。在我们进入学习部分之前,让我们看看最基本的人工神经元:感知机,以及它如何处理输入和产生输出。

感知器

感知器是由科学家弗兰克·罗森布拉特在 20 世纪 50-60 年代开发的,他受到了沃伦·麦卡洛克和沃尔特·皮茨早期工作的启发。虽然今天我们使用人工神经元的其他模型,但它们遵循感知机设定的一般原则。

那它们到底是什么?感知器接受几个二进制输入: x1,x2,…,并产生一个二进制输出:

Perceptron with 3 inputs. (Source: Michael Nielsen)

让我们用一个例子来更好地理解这一点。假设你骑自行车去上班。你有两个因素来做出你去上班的决定:天气一定不能坏,而且一定是工作日。天气没什么大不了的,但是周末工作是一个大禁忌。输入必须是二进制的,所以让我们把条件提议为是或否的问题。天气很好?1 代表是,0 代表否。今天是工作日吗?1 是,0 否。

记住,我不能告诉神经网络这些条件;它必须自己去学习。它如何知道哪些信息对决策最重要?它与叫做的权重有关。记得我说过天气没什么大不了的,但周末才是?权重只是这些偏好的数字表示。较高的权重意味着神经网络认为该输入比其他输入更重要。

对于我们的示例,让我们特意为天气设置合适的权重 2,为工作日设置合适的权重 6。现在我们如何计算产量?我们简单地将输入与其各自的权重相乘,并对所有输入的所有值求和。例如,如果是一个晴朗的工作日,我们将进行如下计算:

这种计算被称为线性组合。8 是什么意思?我们首先需要定义阈值。如果线性组合的值大于阈值,则确定神经网络的输出,0 或 1(呆在家里或去工作)。假设阈值是 5,这意味着如果计算得出的数字小于 5,你可以呆在家里,但如果它等于或大于 5,那么你就得去工作。

您已经看到了重量是如何影响产量的。在本例中,我将权重设置为特定的数字,以使示例正常工作,但实际上,我们将权重设置为随机值,然后网络根据使用之前的权重产生的输出误差来调整这些权重。这叫做训练神经网络。

(Source: Panagiotis Peikidis. Based on XKCD comic ‘Compiling’)

回到手写数字识别问题,一个简单的单节点网络(如上图所示)无法做出如此复杂的决定。为了实现这一点,我们需要更复杂的网络,有更多的节点和隐藏层,使用诸如 sigmoid 激活函数之类的技术来做出决策,并使用反向传播来学习。第二部中的一切!

接下来:

[## 神经网络初学者指南:第二部分

#2.偏置、激活函数、隐藏层以及构建更高级的前馈神经网络架构。

medium.com](https://medium.com/@nehaludyavar/a-beginners-guide-to-neural-networks-part-two-bd503514c71a)

资源

  1. 利用神经网络识别手写数字 迈克尔尼尔森(Michael Nielsen)著(同级更详细解释)。
  2. 深度学习书籍 作者伊恩·古德菲勒、约舒阿·本吉奥和亚伦·库维尔(更高级的&技术,假设本科水平的数学知识)。
  3. Udacity 深度学习纳米学位基础 (17 周项目化课程;难度在 1 的中间。第二。)
  4. TensorFlow 神经网络游乐场 (有趣、互动的可视化神经网络在行动)

神经网络初学者指南(深度学习)

原文:https://towardsdatascience.com/a-beginners-guide-to-neural-networks-deep-learning-c17273a24409?source=collection_archive---------11-----------------------

神经网络是一项突破性的技术,从未停止让我惊讶。就像一般的机器学习一样,它们正越来越多地融入我们的生活,而我们许多人却没有意识到。它们可能非常复杂,很难理解它们是如何做出决定的。顾名思义,他们设计背后的灵感来自于我们每天都拥有和使用的东西;大脑。

神经元是大脑的组成部分,当单独研究时,它们并不复杂。两个神经元通过突触连接,电脉冲通过突触从一个神经元传递到另一个神经元。如果电脉冲达到一定的强度,突触就会激活,将电脉冲传递给下一个神经元。

Perceptron

人工神经网络以非常相似的方式工作。左边的图像显示了最简单的神经网络,一个单层神经网络,称为感知器。它显示了一个节点(y ),输入(x1,x2,x3)进入该节点。每个输入都有一个权重(w1,w2,w3)。节点 y 获取每个输入,并将其值乘以权重。这种加权产生了神经网络最强大的功能之一,通过使用不同的强度权重来评估不同级别的输入。让我们用一个例子来更清楚地理解这一点。假设神经网络将预测我和一个朋友今晚是否会打网球。节点的输入可以是:

  1. 我的朋友有空吗?是或否
  2. 天气预报说今晚是晴天吗?是或否
  3. 法院有空吗?是或否

如果这三个问题的答案都是肯定的,那么结果将是“是的,让我们打网球吧!”每个输入都根据其重要性被赋予一个权重。在这个例子中,很明显,朋友和球场是非常重要的输入,如果这两个答案中的任何一个是否定的,我和我的朋友将不打网球,那么这些权重将非常高。天气预报是晴天不太重要,因为如果是阴天甚至是毛毛雨,我们仍然可以打网球。

神经网络需要数学形式的“是”和“否”,因此神经网络的输入为“是”, 1 表示“是”, 0 表示“否”。每个输入通过将其值乘以其权重传递给节点 y。然后,节点将所有值相加。如果总数高于某个阈值,则返回 yes。如果总数低于,那么它将返回一个否。这是它的决定!

在提供输入和结果的许多不同的例子上训练一个神经网络。这允许网络学习其权重,以提供具有最佳可能精度的整体模型。例如,如果我对这三个问题的答案训练一个神经网络,如果我和我的朋友在过去的一年里每天都打网球,它将学会预测我们是否会打得很准确。这是一个非常基本的例子,神经网络还有很多我没有讨论的特性,比如隐藏层和反向传播。请继续关注更多深入神经网络工作的文章。

如果您对神经网络以及如何将它们应用于业务流程感兴趣,请访问 Miminal 。Miminal 为希望利用人工智能的力量但缺乏内部能力或专业知识的公司提供定制的数据科学解决方案。

神经网络初学者指南:第二部分

原文:https://towardsdatascience.com/a-beginners-guide-to-neural-networks-part-two-bd503514c71a?source=collection_archive---------0-----------------------

偏置、激活函数、隐藏层以及构建更高级的前馈神经网络架构。

在 第一部分,我解释了感知器如何接受输入,应用线性组合,如果线性组合大于或小于某个阈值,则分别产生 1 或 0 的输出。在数学语言中,它看起来像这样:

在上面的公式中,希腊字母适马∑用于表示求和,下标 i 用于迭代输入( x) 和权重( w) 配对。

为了让后面的训练简单一点,我们对上面的公式做一个小的调整。让我们将阈值移动到不等式的另一边,并用神经元的偏差来代替它。现在我们可以将等式改写为:

有效,偏差= —阈值。你可以把偏置想象成让神经元输出 1 有多容易——如果偏置非常大,神经元输出 1 就很容易,但如果偏置非常负,那就很难了。

Source: SMBC Comics

在定义中做这个小改动有几个原因(稍后还会有一些改动;很高兴看到做出这些改变背后的直觉)。正如我在第一部分中提到的,我们随机分配权重数字(我们事先不知道正确的数字),随着神经网络训练,它对这些权重进行增量更改,以产生更准确的输出。类似地,我们不知道正确的阈值,并且像权重一样,网络将需要改变阈值以产生更精确的输出。现在有了偏差,我们只需要对等式的左边进行修改,而右边可以保持不变为零,很快,你就会明白为什么这是有用的。

为输出神经元的决策转换值或陈述条件的函数被称为激活函数。上面的数学公式只是深度学习中使用的几个激活函数之一(也是最简单的),它被称为 Heaviside 阶跃函数。

General formula (h being the condition) and graph of the Heaviside step function. The solid circle is the y-value you take (1.0 for x=0 in this case) , not the hollow circle. The line the hollow and solid circles are on is the ‘step’. (Source: Udacity)

其他激活功能包括 sigmoidtanhsoftmax 功能,它们各有其用途。(在这篇文章中,我将只解释 sigmoid 函数,但我会在其他函数出现时进行解释)。

Sigmoid 函数

即使在处理绝对数(1 和 0;yes 和 nos),让输出给出一个中间值是有益的。这有点像在被问到一个你不知道的是或否的问题时回答“也许”,而不是猜测。这实质上是 sigmoid 函数优于 Heaviside 函数的地方。

The graph and formula of the sigmoid function. Source: Udacity

像亥维赛阶梯函数一样,sigmoid 的值在 0 和 1 之间。但是这一次,没有;它已经被平滑,以创建一个连续线。因此,输出可以被认为是成功的概率(1),或者是肯定的。在日常生活中,0.5 的输出意味着网络不知道它是肯定的还是否定的,而 0.8 的输出意味着网络“非常肯定”它是肯定的。

拥有这一特性对于网络的学习能力尤为重要,我们将在以后的文章中看到这一点。现在,只要把它想象成更容易教会一个网络逐步走向正确答案,而不是直接从 0 跳到 1(反之亦然)。

隐藏层

到目前为止,我们已经探索了感知器(最简单的神经网络模型)的架构,并看到了两个激活函数:Heaviside 阶跃函数和 sigmoid 函数。(要了解感知机如何用于计算逻辑功能,如 AND、OR 和 NAND,请查看迈克尔·尼尔森在线书籍中的第 1 章)。

现在让我们使我们的网络稍微复杂一点。在这里,以及所有的神经网络图中,最左边的层是输入层(即你馈入的数据),最右边的层是输出层(网络的预测/答案)。这两层之间的任意数量的层被称为隐藏层。层数越多,决策能得到的细致入微就越多。

(Source: Stanford CS231n)

网络通常有不同的名称:深度前馈网络、前馈神经网络、多层感知器(MLP)。(为了使事情不那么混乱,我将坚持使用前馈神经网络)。它们被称为前馈网络,因为信息在一个总的(正向)方向上流动,在每个阶段都应用了数学函数。事实上,它们之所以被称为“网络”是因为这个功能链的(第一层功能的输出是第二层的输入,第三层的输出也是第三层的输入,依此类推)。那条链的长度给出了模型的深度,这实际上就是深度学习中的术语“deep”的来源!

Not quite the same ‘hidden’. (Source: Bill Watterson)

添加隐藏层可以让神经网络做出更复杂的决定,但更多的是,以及神经网络如何通过第三部分(即将推出)中的反向传播、过程进行学习!

资源

  1. 利用神经网络识别手写数字 迈克尔尼尔森。
  2. 神经网络第一部分:搭建架构,斯坦福 CS231n。
  3. 深度学习书籍 伊恩·古德菲勒、约舒阿·本吉奥和亚伦·库维尔。

绘制“五个三十八”可视化效果的初学者指南

原文:https://towardsdatascience.com/a-beginners-guide-to-plotting-fivethrityeight-like-visualizations-5b63d3f3ddd0?source=collection_archive---------9-----------------------

在这里,我将向你展示我是如何从 FiveThirtyEight 的文章 中重现乔恩·斯图尔特在《每日秀》 中的每一位嘉宾的形象的。

Source: FiveThirtyEight’s article “Who Got to Be On ‘The Daily Show’?”

您可能已经使用 Matplotlib 和 Seaborn 进行了可视化,但是您可能希望提高绘图的美观性。你可以在这里从 FiveThirtyEight 的 Github 获得数据集的 csv 文件。

那么,让我们开始吧……

首先,进入你喜欢的编码环境。我更喜欢使用 Jupyter 笔记本(以防你不知道它或者想要帮助下载它,这里有一个我找到的教程)。另外,另一个不错的选择是谷歌合作实验室。

一旦您的环境准备好了,加载适当的库,读取文件并显示前五行。

First five rows of dataset

现在让我们重命名“YEAR”和“Raw_Guest_List ”,以减少我们的输入,因为我们很快就会用到它们。

现在我们需要将“组”列中所有客人的职业浓缩为三类。这将有助于在图表中绘制我们的三条线。为此,我们定义了一个循环遍历“Group”列并创建一个新的“Occupations”列的函数。

See added ‘Occupation’ column combining occupations into three categories

接下来,根据每年的职业创建一个客人百分比表。为此,我们将使用 Pandas 的交叉表函数,这将帮助我们简化计算。

Table with percentage of guests by occupation each year

默认情况下,上面的交叉表函数会计算每年每个类别的客人数量。但是请注意包含的“正常化”参数。这将调整我们的计算,给出一个比例。此外,将 normalize 设置为*“index”会将此规范化应用于每一行,而不是每一列。然后我们可以乘以 100 ( 100 )把这些比例变成百分比。

接下来,如果我们想要清理我们的表,我们也可以删除“Other”列,它不会在我们的图中使用。

Same table without ‘Other’ column

为了方便绘图,我们将在表格中列出所有年份。

是时候做我们一直以来真正想做的事情了!

这里有一个代码要点,它将为我们提供粗略的草稿。自定义线条颜色和线条粗细,以匹配文章中的图表…

Here’s our initial plot

沿 y 轴增加网格线的长度,并在图的基线处添加一条水平线。

Grid line along y-axis increased and horizontal line at baseline added

调整显示的 x 和 y 标签,再次调整字体颜色和大小。

Reduced number of grid lines and changed x & y axis labels

设置图形标题和副标题(不使用传统的 plt.title()* ,因为它限制了文本放置)。请注意,下面的 x 和 y 参数根据 x 和 y 坐标确定文本的位置。*

Title & subtitle aligned with ‘100%’ label on plot

使用自定义字体大小和颜色为绘图中的每一行添加文本标签。

Adding labels here takes a lot of playing with x & y coordinates

我们的最后一点是,在我们图表的底部有一个自定义的签名框。这里你必须在文本中获得正确的间距(见参数中的文本),以使其适合图表的宽度。

Voila!… Our finalized ‘FiveThirtyEight like’ visualization

就是这样。

自己制作出像这样好看又干净的知识性剧情,感觉不是很好吗?不得不承认我感觉很好:)

现在,您可以利用 FiveThirtyEight 提供的数据了。走吧。是时候让你看看一些有趣的文章,尝试自己去重现其他的情节了。

数据科学管道初学者指南

原文:https://towardsdatascience.com/a-beginners-guide-to-the-data-science-pipeline-a4904b2d8ad3?source=collection_archive---------0-----------------------

“信不信由你,你和数据没什么区别。设身处地为 Data 想想,你就会明白为什么了。”

从前有一个叫数据的男孩。在他的一生中,他总是试图理解他的目的是什么。我有什么价值观? 我能对这个世界产生什么影响? 数据从哪里来?看到你和数据有什么相似之处吗?这些问题总是在他的脑海中,幸运的是,通过纯粹的运气,数据最终找到了解决方案,并经历了巨大的转变。

这一切都是从数据沿着行移动时开始的,当时他遇到了一个奇怪但有趣的管道。一端是一根有入口的管子,另一端是出口。管子上还标有五个不同的字母:“ O.S.E.M.N. ”。尽管他很好奇,但数据决定进入管道。长话短说… 进来的是数据,出来的是洞察力。

提醒:本文将简要概述典型数据科学管道中的预期内容。从构建您的业务问题到创造可行的见解。不要担心,这很容易读懂!

数据科学是一门学问

你真棒。我很棒。数据科学是 OSEMN 。你可能会问,为什么数据科学“很棒”?嗯,作为一名有抱负的数据科学家,你有机会磨练你作为一名巫师和一名侦探的能力。我说的巫师是指拥有自动预测事物的能力!通过侦探,它有能力在你的数据中发现未知的模式和趋势!

理解数据科学管道如何工作的典型工作流程是理解业务和解决问题的关键一步。如果你对数据科学管道的工作方式感到害怕,那就不要再说了。这篇文章送给你!我从希拉里·梅森和克里斯·维金斯那里找到了一个非常简单的缩写词,你可以在你的数据科学管道中使用。那就是o s e m n

OSEMN 管道

  • O — 获取我们的数据
  • S —擦洗/清理我们的数据
  • E — 探索/可视化我们的数据将使我们能够发现模式和趋势
  • M — 对我们的数据进行建模将赋予我们作为向导的预测能力
  • N — 解读我们的数据

商业问题

因此,在我们甚至开始 OSEMN 管道之前,我们必须考虑的最关键和最重要的一步是理解我们试图解决的问题我们再说一遍。在我们开始用“数据科学”做任何事情之前,我们必须首先考虑我们试图解决什么问题。如果你有一个想要解决的小问题,那么你最多只能得到一个小的解决方案。如果你有一个问题要解决,那么你就有一个解决方案的可能性。

扪心自问:

  • 我们如何将数据转化为美元
  • 我想用这些数据产生什么影响?
  • 我们的模式带来了什么商业价值?
  • 什么能为我们节省很多钱?
  • 怎样做才能让我们的业务更有效率?

“把钱给我看看!”

了解这一基本概念将带你走得更远,并引领你朝着成为一名“数据科学家”迈出更大的成功步伐(从我所相信的来看…抱歉我不是一名数据科学家!)但尽管如此,这仍然是你必须做的非常重要的一步!无论你的模型预测得有多好,无论你获得了多少数据,无论你的渠道有多广,你的解决方案或可操作的洞察力只会和你为自己设定的问题一样好。

“好的数据科学更多的是关于你对数据提出的问题,而不是数据管理和分析。”——赖利·纽曼

获取您的数据

作为一名数据科学家,如果没有任何数据,你什么也做不了。作为一条经验法则,在获取数据时,有些事情你必须考虑。你必须识别你所有可用的数据集(可以来自互联网或外部/内部数据库)。你必须将数据提取成可用的格式。csv、json、xml 等..)

所需技能:

  • 数据库管理:MySQL,PostgresSQL,MongoDB
  • 查询关系数据库
  • 检索非结构化数据:文本、视频、音频文件、文档
  • 分布式存储 : Hadoops,Apache Spark/Flink

擦除/清理您的数据

清理第五列!管道的这个阶段应该需要最多的时间和精力。因为你的机器学习模型的结果和输出只和你投入进去的东西一样好。基本上,垃圾进垃圾出。

目标:

  • 检查数据:理解你正在处理的每一个特性,识别错误、丢失的值和损坏的记录
  • 清除数据:丢弃、替换和/或填充缺失值/错误

所需技能:

  • 脚本语言 : Python,R,SAS
  • 数据角力工具 : Python 熊猫,R
  • 分布式处理 : Hadoop、Map Reduce / Spark

“有准备的人已经成功了一半。”——米格尔·德·塞万提斯

探索(探索性数据分析)

现在,在探索阶段,我们试图理解我们的数据具有什么样的模式和价值。我们将使用不同类型的可视化统计测试来支持我们的发现。在这里,我们将能够通过各种图表和分析得出数据背后隐藏的含义。出去探索吧!

"停泊在港口的船只是安全的——但这不是建造船只的目的。"约翰·谢德。

目标:

  • 通过可视化和图表在数据中寻找模式
  • 通过使用统计数据识别和测试重要变量来提取特征

所需技能:

  • Python : Numpy,Matplotlib,Pandas,Scipy
  • R : GGplot2,Dplyr
  • 推断统计
  • 实验设计
  • 数据可视化

提示:做分析时有你的【蜘蛛感官】刺痛。有意识地发现奇怪的模式或趋势。时刻关注有趣的发现!

设计考虑:大多数时候,人们会直接想到视觉上的“让我们完成它”。这都是关于最终用户谁将解释它。关注你的听众。

建模(机器学习)

现在有趣的部分来了。模型是统计学意义上的一般规则。把机器学习模型想象成你工具箱里的工具。你将有机会接触到许多算法,并用它们来完成不同的业务目标。您使用的功能越好,您的预测能力就越强。在清理你的数据并找到什么特征是最重要的之后,使用你的模型作为预测工具只会增强你的商业决策。

预测分析正在成为游戏规则的改变者。而不是回头分析“发生了什么?”预测分析帮助高管回答“下一步是什么?”以及“我们应该做些什么?”(《福布斯》杂志,2010 年 4 月 1 日)

预测能力的例子:沃尔玛的供应链就是一个很好的例子。沃尔玛能够预测他们将在飓风季节在他们的一个商店销售所有的草莓馅饼。通过数据挖掘,他们的历史数据显示,飓风发生前最受欢迎的商品是果馅饼。虽然听起来很疯狂,但这是一个真实的故事,并提出了不要低估预测分析能力的观点。

目标:

  • 深入分析:创建预测模型/算法
  • 评估并细化模型

所需技能:

  • 机器学习:监督/非监督算法
  • 评估方法
  • 机器学习库:Python(Sci-kit Learn)/R(CARET)
  • 线性代数&多元微积分

“模型是嵌入在数学中的观点”——凯西·奥尼尔

解释(数据叙事)

故事时间到了!这个过程中最重要的一步是理解并学会如何通过交流来解释你的发现。讲故事是关键,不要小看它。这是关于和人们联系,说服他们,帮助他们。理解你的受众并与他们联系的艺术是数据故事最好的部分之一。

“我相信讲故事的力量。故事打开了我们的心扉,打开了我们的思想,这往往会导致行动”——梅林达·盖茨

情绪在数据讲故事中起着很大的作用。人们不会神奇地理解你的发现。产生影响的最好方法是通过情感讲述你的故事。作为人类,我们自然会受到情绪的影响。如果你能挖掘你的观众的情绪,那么你,我的朋友,就在控制之中。当你展示数据时,请记住心理学的力量。理解你的受众并与他们联系的艺术是数据故事最好的部分之一。

最佳实践:我强烈建议,增强您的数据叙述能力的一个好实践是反复排练。如果你是父母,那对你来说是个好消息。不要在睡前给孩子读典型的苏斯博士的书,试着用你的数据分析结果哄他们入睡!因为如果一个孩子能理解你的解释,那么任何人都可以,尤其是你的老板!

"如果你不能向一个六岁的孩子解释,那你自己也不明白。"——阿尔伯特·爱因斯坦

目标:

  • 识别业务洞察力:回到业务问题
  • 相应地想象你的发现:保持简单和优先驱动
  • 讲述一个清晰可行的故事:有效地与非技术观众沟通

所需技能:

  • 商业领域知识
  • 数据可视化工具 : Tablaeu,D3。JS,Matplotlib,GGplot,Seaborn
  • 沟通:陈述/发言&汇报/写作

更新您的模型

别担心,你的故事不会就此结束。由于您的模型正在生产中,因此根据您接收新数据的频率,定期更新您的模型非常重要。您收到的数据越多,更新就越频繁。假设你是 亚马逊,你为顾客推出了一个购买“鞋类特色”的新功能。您的旧型号没有此功能,现在您必须更新包括此功能的型号。如果不是这样,你的模型将会随着时间的推移而退化,表现不佳,让你的业务也退化。新功能的引入将通过不同的变化或可能与其他功能的相关性来改变模型性能。

结论

综上所述,

  • 形成你的业务问题
  • 获取你的数据

获取您的数据,清理您的数据,用可视化方式探索您的数据,用不同的机器学习算法对您的数据建模,通过评估解释您的数据,更新您的模型。

记住,我们和数据没什么不同。我们都有价值观、目标和存在于这个世界的理由。

事实上,你将面临的大多数问题都是工程问题。即使有一个伟大的机器学习大神的所有资源,大部分影响也会来自伟大的功能,而不是伟大的机器学习算法。所以,基本的方法是:

  1. 确保您的管道端到端是稳固的
  2. 从一个合理的目标开始
  3. 直观地理解您的数据
  4. 确保你的管道保持稳固

这种方法有望赚很多钱和/或让很多人长期快乐。

所以……下次有人问你什么是数据科学的时候。告诉他们:

“数据科学是一门学问”

我希望你们今天学到了一些东西!如果你们对这篇文章有什么想补充的,请随时留言,不要犹豫!非常感谢任何形式的反馈。不要害怕分享这个!谢谢!

商务化人际关系网

在 LinkedIn 上联系我:https://www.linkedin.com/in/randylaosat

想要更多免费资源?

访问我的网站: ClaoudML 。com

图像分类的锦囊妙计

原文:https://towardsdatascience.com/a-big-of-tricks-for-image-classification-fec41eb28e01?source=collection_archive---------8-----------------------

来拿你的深度学习好东西吧

想获得灵感?快来加入我的 超级行情快讯 。😎

你上次在深度学习中看到理论 100% 匹配实践是什么时候?这很少发生!研究论文说了一件事,但现实世界中的结果往往大相径庭。

这不完全是这项研究的错。科学研究的很大一部分是实验——基于这些特定的环境,通过这个数据集,我们得到了这些结果。一旦你真正尝试并应用这些模型,处理嘈杂和无序数据的挑战就出现了。该理论并不总是与现实世界中实际发生的事情一致,但它确实提供了一个不错的基线。

那么造成这种理论与实践差距的原因是什么呢?它不完全来自新的数据!这种差异很大程度上来自深度学习专家用来给他们的模型提供额外推动的“技巧”。这些是隐藏的交易技巧,你只能通过大量的模型实验,或者只是从有经验的人那里学习。亚马逊研究小组最近的研究对此进行了量化,表明这些技巧可以让你在相同的模型上获得高达 4%的准确性提升

在这篇文章中,你将了解这项研究,以及专家们用来给他们的深度学习模型提供额外推动的最重要的诀窍。我会给你一些实用的观点,旨在实际应用这些技巧。

(1)大批量

理论上,更大的小批量应该有助于网络收敛到更好的最小值,从而获得更好的最终精度。人们通常会因为 GPU 内存而陷入困境,因为人们可以购买的最大消费级 GPU 在云上只能达到 12GB(对于 Titan X)和 16GB(对于 V100)。有两种方法可以解决这个问题:

(1) 分布式训练:将你的训练拆分到多个 GPU 上。在每个训练步骤中,您的批次将在可用的 GPU 之间进行拆分。例如,如果您的批处理大小为 8 和 8 个 GPU,那么每个 GPU 将处理一个图像。然后你将在最后合并所有的渐变和输出。您确实会受到 GPU 之间数据传输的小影响,但仍然可以从并行处理中获得很大的速度提升。许多深度学习库中都支持这一功能,包括 Keras 。

(2)在训练期间改变批次和图像大小:许多研究论文能够报告使用如此大的批次大小的部分原因是许多标准研究数据集具有不是很大的图像。例如,当在 ImageNet 上训练网络时,大多数最先进的网络使用 200 到 350 之间的作物;当然,他们可以有这么小的图像尺寸大批量!在实践中,由于目前的相机技术,大多数时候我们都在处理 1080p 的图像,或者至少不会太远。

为了避开这个小障碍,您可以从较小的图像和较大的批量开始训练。通过对训练图像进行缩减采样来实现这一点。然后你就可以把更多的放入一批中。有了大批量+小图片,你应该已经能够得到一些不错的结果。要完成网络的训练,请使用较小的学习速率和较小批量的大图像进行微调。这将使网络重新适应更高的分辨率,并且较低的学习速率防止网络从从大批量中找到的好的最小值跳开。因此,您的网络能够从大批量训练中获得良好的最小值,并通过微调在高分辨率图像上工作良好。

The effects of large mini-batch training on object detectors, from the MegDet paper

(2)迷你模型调整

研究论文并不总是告诉你完整的故事。作者通常会在论文中链接到他们的官方代码,这可能是比论文本身更好的学习算法的资源!当您阅读代码时,您可能会发现他们忽略了几个小的模型细节,而这些细节实际上造成了很大的准确性差异。

我鼓励大家看看研究论文的官方代码,这样你就可以看到研究人员用来获得他们的结果的确切代码。这样做还会给你一个很好的模板,这样你就可以很快做出自己的小调整和修改,看看它们是否能改进模型。探索模型的一些公共重新实现也是有帮助的,因为这些可能有其他人已经试验过的代码,最终改进了原始模型。查看下面的 ResNet 架构和在一些公共代码中发现的 3 处改动。它们看起来很小,但每一个都在运行时间几乎没有变化的情况下提供了不可忽略的精度提升;ResNet-D 在 Top-1 精度方面提升了整整 1%。

The original ResNet-50 architecture; from the Bag of Tricks paper

Altered and improved versions of the ResNet-50 architecture; from the Bag of Tricks paper

(3)精细化训练方法

如何训练一个深度网络通常根据手边的应用和实际设置训练的研究团队而变化!知道如何正确训练你的网络可以让你的准确率提高 3-4 %!这是一种从深层网络知识和简单的实践中获得的技能。不幸的是,大多数人不太重视培训,并期望网络能神奇地给他们带来巨大的成果!

尽量注意最新研究中使用的具体训练策略。你会经常看到,他们中的大多数人不会使用 Adam 或 RMSProp 这样的自适应方法来默认单一的学习速率。他们使用诸如热身训练、速率衰减和优化方法的组合来获得他们可能挤出的最高精确度。

这是我个人最喜欢的。

亚当优化器超级容易使用,并且倾向于自己设定一个好的学习速度。另一方面,SGD 通常比 Adam 高出 1-2 %,但是很难调整。所以,从亚当开始:只要设定一个不太高的学习率,通常默认为 0.0001,你通常会得到一些非常好的结果。然后,一旦你的模型开始被 Adam 饱和,以较小的学习速率微调 SGD,以获得最后一点精度!

(4)迁移学习

除非你正在做前沿研究,并试图打破基本的艺术状态,迁移学习应该是默认的实践方法。根据新数据从头开始训练网络具有挑战性,非常耗时,有时需要一些额外的领域专业知识才能真正做到正确。

迁移学习提供了一种既能加快训练速度又能提高准确性的简单方法。有大量的研究和实践证据表明,迁移学习使模型更容易训练,并且比从头开始训练更准确。这将完全简化事情,让你更容易得到一些像样的基线结果。

一般来说,精确度更高的模型(相对于同一数据集上的其他模型)更适合迁移学习,并能获得更好的最终结果。另一件需要注意的事情是,根据你的目标任务选择你的预训练网络进行迁移学习。例如,在医学成像数据集上使用为自动驾驶汽车预先训练的网络就不是一个好主意;这是领域之间的巨大差距,因为数据本身非常不同。你最好从零开始训练,不要带着对与医学成像完全不同的数据的偏见开始你的网络!

The main idea behind Transfer Learning (original)

(5)奇特的数据增强

数据增强是另一大准确性助推器。大多数人坚持经典的旋转和翻转,这很好。如果你有时间等待这些额外图像的训练,它们可能会给你几个百分点的额外精度提升,而且几乎是免费的!

但是最先进的技术不止于此。

一旦你开始更深入地阅读这项研究,你会发现更先进的数据增强,为深度网络提供最后的推动力。缩放,即增加图像像素的颜色或亮度值,将使网络暴露于比原始数据集更多样化的训练图像。它有助于说明这种变化,特别是,例如,基于房间或天气的不同照明条件,这在现实世界中变化相当频繁。

另一个现在在最新的 ImageNet 模型上普遍使用的技术是。尽管名为 cutout,但它实际上可以被看作是增加数据以处理遮挡的一种形式。遮挡是现实世界应用中极其常见的挑战,尤其是在机器人和自动驾驶汽车的热门计算机视觉领域。通过对训练数据应用某种形式的遮挡,我们有效地调整了我们的网络,使其更加健壮。

Cutout regularisation / augmentation

喜欢学习?

在推特上关注我,我会在那里发布所有最新最棒的人工智能、技术和科学!

有点超越梯度下降:小批量,势头,和一些纨绔子弟命名为尤里内斯特罗夫

原文:https://towardsdatascience.com/a-bit-beyond-gradient-descent-mini-batch-momentum-and-some-dude-named-yuri-nesterov-a3640f9e496b?source=collection_archive---------4-----------------------

上一次,我讨论了梯度下降如何在线性回归模型上工作,用十行 python 代码编写了它。这样做是为了展示梯度下降的原则,当涉及到自我实现时,它将给予读者洞察力和实际知识。有大量的库可以通过简单的即插即用为我们完成这项工作。然而,我相信学习这些方法如何在内部工作对于研究人员和实践数据科学家同样重要。

为了让读者更顺利地过渡到深度学习,我努力讨论了梯度下降。当研究深度学习时,理解如何对成本函数求导并使用它来更新权重和偏差是很重要的,因为它会重复显示自己(参见反向传播)。花时间去学习这些东西。

我们将再次探索我们的基本线性回归模型与我们的均方误差成本函数,通过优化技术超越梯度下降导航。在继续阅读之前,你自己想想,梯度下降会给我们带来什么潜在的问题?

最后,回想一下,我们的成本函数是下面给出的均方误差:

Average of all real values minus predicted values squared.

解开上述线性回归方程,我们得到:

m is the slope and b is the bias term

查看我的GitHub repo包含完整算法。我对我们将要讨论的所有方法进行了基准测试。

小批量梯度下降

当我们使用普通梯度下降(我们的普通老伙伴梯度下降的另一个术语)时,我们面临的一个问题是内存问题。我们的计算机只能处理这么多,那么如果我们要处理数百万,甚至更常见的数十亿的数据呢?幸运的是,顾名思义,小批量梯度下降使用与普通梯度下降相同的方法,但规模更小。我们根据训练数据创建批次,并在较小的批次上训练我们的模型,同时更新我们的斜率和偏差项。它看起来会像这样:

for epoch in range(number_of_epochs):
     for j in range(0, length_of_input_array, batch_size):
          batch_train_X = train_X[j:j+batch_size]
          batch_train_y = train_y[j:j+batch_size]
          ...
          m = m - learning_rate * m_gradient
          b = b - learning_rate * b_gradient

对于每个时期,我们每批训练我们的模型。这将导致我们创建一个嵌套的 for 循环。在我看来,这是必要的牺牲,而不是完全满足庞大的数据集。小批量梯度下降的一个问题是,高方差参数更新数量的增加会导致成本函数的波动。有时,这将导致我们的梯度由于过冲而跳到较低的局部最小值,这使它优于普通梯度下降,因为小批量梯度下降只是不停留在局部最小值的区域内,它可以超越该区域找到其他较低的局部最小值。其他时候,我们可能达不到更低的局部最小值,因为的过冲。

我们可以做得更好。我们借用一下物理学。

动力

还记得物理学中的动量吗?动量方程是 p =m v ,其中 p 是动量,m 是质量,而 v 是速度——pv 都是矢量。对动量的直观理解,可以用一个滚下山坡的球来画。它的质量一路不变,但是因为引力的作用,它的速度( v )随着时间增加,使得动量( p )增加。同样的概念也可以应用于成本最小化!当前一个时间步长的梯度“指向”与我们当前时间步长相同的方向时,当我们“下山”时,我们增加“速度”

在改善小批量梯度下降方面,这允许我们在某个方向上增加我们的“速度”。当方向改变时,我们会稍微慢一点,因为我们的动量“中断了”当我们的球滚下山时,它不断增加动量,但当另一个球击中它(或任何真正击中它的东西)时,它会减速,然后试图恢复动量。物理学允许我们进行直观的类比!

我们将不得不做一些改变。参考下面的等式:

This is our new parameter update.

这里只是我们相对于时间的“速度”。那个看起来像“y”的符号就叫做动量项,通常取值为 0.9。看起来像字母“n”的符号是我们的学习率,乘以成本函数的导数。我们仍然采用与普通梯度下降法和小批量梯度下降法相似的导数,如下所示:

你计算出 v 并从我们之前的参数中减去它,瞧,这就是你的参数更新!

在代码中,它看起来像这样:

for epoch in range(number_of_epochs):
     for j in range(0, length_of_input_array, batch_size):
          batch_train_X = train_X[j:j+batch_size]
          batch_train_y = train_y[j:j+batch_size] if epoch == 0:
               v_m = 0
               v_b = 0 m_gradient = -(2/N) * sum(X[j:j+batch_size] * (y[j:j+batch_size] - y_current))
          b_gradient = -(2/N) * sum(y[j:j+batch_size] - y_current) v_m = mu * v_m + learning_rate * m_gradient
          v_b = mu * v_b + learning_rate * b_gradient m_current = m_current - v_m
          b_current = b_current - v_b

再次,参考我的 GitHub repo 了解完整的实现细节。

内斯特罗夫加速梯度

只有动量的问题是它不够动态。当然,它会放大速度,以便更快地达到收敛,但一位名叫尤里·内斯特罗夫的研究人员观察到,当梯度达到局部最小值时,动量的值仍然很高。

当我们到达局部最小值时,上面的方法没有办法让我们减慢我们的参数更新。超调的问题再次出现。想象我们的球又滚下山了。在我们的动量法中,球在下落的时候肯定滚得更快,但是它不知道它要去哪里,所以它知道什么时候减速,并在下一个上坡之前最终稳定下来。我们需要一个更聪明的球。

内斯特罗夫加速梯度(NAG)是一个预先更新,防止我们走得“太快”,当我们不应该已经。参考下面的等式,看看你是否注意到了一个与动量相比发生了变化的东西。提示:检查成本函数。

在成本函数中,我们从权重/斜率中减去了一个新项!这是预先的行动。通过从上一个时间步取梯度,我们预测我们可能去的地方,而你最终加入的项是我们所做的修正。这使得 NAG 更具动态性,因为我们的更新会根据误差函数的斜率进行调整。

Source: http://cs231n.github.io/assets/nn3/nesterov.jpeg

我们新的斜率和偏置梯度看起来会有所不同。对于 NAG,你所要做的就是将新项插入到成本函数中,然后像我们之前所做的那样进行求导。对于我们的具有均方误差成本函数的线性回归示例,它看起来如下所示:

Derivative of the cost function with respect to the slope term

Derivative of the cost function with respect to the bias term

我们需要对之前的代码做一些调整。再次,检查我的 GitHub repo 了解完整的实现细节。它看起来像下面这样:

for epoch in range(number_of_epochs):
     for j in range(0, length_of_input_array, batch_size):
          batch_train_X = train_X[j:j+batch_size]
          batch_train_y = train_y[j:j+batch_size] if epoch == 0:
               v_m = 0
               v_b = 0 y_nesterov_m = (m_current - mu * v_m) * X[j:j+batch_size] + b_current
          y_nesterov_b = (b_current - mu * v_b) * X[j:j+batch_size] + b_current m_gradient = -(2/N) * sum(X[j:j+batch_size] * (y[j:j+batch_size] - y_nesterov_m))
          b_gradient = -(2/N) * sum(y[j:j+batch_size] - y_nesterov_b) v_m = mu * v_m + learning_rate * m_gradient
          v_b = mu * v_b + learning_rate * b_gradient m_current = m_current - v_m
          b_current = b_current - v_b

还有吗?

当然有!到目前为止,我们已经讨论了:1)使我们的计算机更容易进行计算;以及 2)基于误差函数的斜率实现自适应梯度步骤。我们可以更进一步。为什么不让所有其他的东西都适应呢?比如说,适应性学习率?如果我们使这些自适应学习率的更新类似于我们用 NAG 进行更新的方式,会怎么样呢?

有很多资源讨论这些问题。一个简单的谷歌搜索将带你到一个等待被学习的信息宝库。下次我会试着简单地解释给你听。到时候见!

一个关于午餐和数据科学的博客——为什么没有免费的午餐

原文:https://towardsdatascience.com/a-blog-about-lunch-and-data-science-how-there-is-no-such-a-thing-as-free-lunch-e46fd57c7f27?source=collection_archive---------25-----------------------

如果你已经开始阅读关于食物的文章,你会失望地发现这篇文章实际上是关于古老的数学。对于一个真正好的午餐创意美食博客,我强烈推荐food52.com;然而,如果你对免费食物和数据科学如何携手共进感兴趣,我会给你一个没有免费午餐定理的概述,以及它如何应用于数据科学的世界。

“天下没有免费的午餐”这句话传达了这样一种思想,即你不能不劳而获,即使有些东西看起来是免费的,也总是有代价的。这个短语起源于 19 世纪,当时酒吧试图用免费食物吸引更多的顾客,条件是这些顾客会点饮料和他们的食物一起吃;然而,工薪阶层的消费者通常不会喝醉,而且他们的钱还在口袋里。

虽然人们可以将这句话视为生活的智慧,但它也适用于数据科学领域。没有免费的午餐定理(NFLT),意味着一个算法,创造了最好的解决方案,并不普遍优于任何其他算法。

正如 David Wolpert 和 William G. Macready 所说,“如果一个算法在某类问题上比随机搜索表现得更好,那么它在其余问题上的表现一定比随机搜索差。”对我来说,这意味着如果一个算法特别擅长解决一类问题,那么这个算法就适合于识别这个特殊问题的模式。Al 算法适用于特定的数据集,因为它对该数据集的独特质量做出响应,但是,另一个数据集可能有其他独特的挑战,这些挑战无法用相同的算法解决。

the trade-off between performance and problem type for a general-purpose algorithm and a specialized algorithm

现在,知道了 NFLT 如何适应我的生活和流程,下面的公式证明了两种学习算法的性能,一种不比另一种好。

该公式显示了从函数 f 上的算法arunm次获得给定成本值序列的条件概率的两个部分。对于下面等式中的一对算法 a1a2 ,该定理证明了给定算法在一个类问题上的收益,它同样被其在其余问题上的性能所抵消。

For any algorithms a1 and a2, at iteration step m

本质上,这意味着当所有函数 f 都有相同的可能性时,在搜索过程中观察到任意序列的 m 值的概率不依赖于搜索算法。NFLT 也适用于搜索优化,你可以在这里阅读更多关于它的。

关于 NFLT 值得一提的是,该定理假设人们试图解决的问题是正态分布和随机的。这意味着没有一种类型的问题会取代另一种类型的问题,这种关系同样可以用分类和回归问题来解释。

此外,在优化器迭代的搜索空间将是有限的,并且可能的成本值的空间也将是有限的条件下,NFLT 是真实的。请放心,优化器在计算机上运行时会自动满足这些条件。因为空间的大小是有限的,这意味着所有可能的问题的集合的大小是有限的。

作为一名数据科学家,我一直在采用“全部尝试”的方法,因为没有一个适用于所有问题的主算法。实际上,考虑到时间和资源的现实限制,退一步考虑手头的任务和我可用的数据是最佳策略。计算是昂贵的,所以在运行任何算法之前,重要的是考虑我的目标是什么。

在科学数据的真实世界中,我们关注的是解决我们试图解决的问题的工程特性和解决方案。因此,NFLT 给我们的直觉是,为了找到最好的学习算法,我们应该专注于手头的特定问题和我们可用的数据。算法的表现如何取决于机器和我们的问题之间的一致性。

正如 Wolpert 和 Macready 所阐明的,对于给定的成本函数,一个好的解决方案是确定它的某些显著特征,然后构造一个搜索算法,a,专门定制来匹配这些特征。“人脑是一个无限的空间,可以处理各种不同的问题,并根据一些输入做出决定,但是,学习算法只能接受有限的输入,以便做出最适合这些输入的决定。学习是一种非常人性化的行为,所以让一个复杂的数学公式像人脑一样做同样的事情有点牵强。

模型本质上是基于假设和偏见的现实的简化,因此,没有一个模型在所有情况下都是最好的。最终,随机选择一个算法而不对问题做任何结构性假设就像大海捞针一样。考虑问题和数据,设计最适合任务的解决方案是值得的。

资源:

[## 没有免费的午餐——维基百科

“天下没有免费的午餐”(或者,“天下没有免费的午餐”或其他…

en.wikipedia.org](https://en.wikipedia.org/wiki/There_ain't_no_such_thing_as_a_free_lunch)

为股票交易制作一个深刻的演员-评论家机器人的浮躁指南

原文:https://towardsdatascience.com/a-blundering-guide-to-making-a-deep-actor-critic-bot-for-stock-trading-c3591f7e29c2?source=collection_archive---------3-----------------------

技术分析就像一厢情愿的想法和复杂的数学一样。如果数字中有一个真实的趋势,不管特定股票的基本面如何,那么给定一个足够的函数逼近器(…就像一个深度神经网络),强化学习应该能够找出它。

这里有一个有趣的,也许是有利可图的项目,我试图这样做。我与 RL 合作不到六个月,仍然在搞清楚事情,但在为几个基本游戏制作人工智能学习器后,时间序列股票市场数据是我脑海中的首要问题。

这并不容易,这篇文章记录了我的过程和一路上犯的错误,而不是写一篇文章把我自己作为一个解决问题的专家。有很多。

Reinforcement learning is The Good Place

请注意,如果你对 RL 完全陌生,你可能会从阅读我之前关于深度 Q 学习的文章中受益。这个有点不一样,但也是从更高的层次出发,有更多的隐性知识。

如果你只是想跳到代码/笔记本,这里是,但是记住:过去的表现并不能保证未来的结果。

设置问题

我从 RL 中学到的一件事是,框定问题对成功非常重要。我决定让我的机器人:

  • 会得到一笔启动资金
  • 将学会在给定的时间间隔结束时最大化其投资组合(股票和现金)的价值
  • 在每个时间点,可以买卖股票,也可以什么都不做
  • 如果它买的比它现有的钱多,挤兑就结束了;如果它卖出的比它拥有的多,这一轮就结束了。它必须学会游戏规则,以及如何玩好游戏。

为了让事情易于管理,我决定只投资一对可能有点相关的股票:AAPL 和 MSFT。最初,我希望机器人能够选择在每个时间步购买或出售多少股票,这使我陷入了“连续行动空间”强化学习的兔子洞。在一个离散的空间中,给定一个当前状态,机器人可以知道它的每个离散动作的值。空间越复杂,训练越辛苦;在一个连续的空间中,动作的范围呈指数增长。为了简单起见,我暂时降低了我的目标,这样人工智能在每个时间步长只能买卖一只股票。

像往常一样,我们有一个机器人的神经网络和一个对机器人的行动做出反应的环境,根据机器人的行动有多好,每一步都返回一个奖励。

在继续下一步之前,这里有一个队长明显的专业提示:单元测试一切随你去!尝试同时调试一个环境和一个人工智能(“或者我只需要训练它更长时间或者调整超参数?!")可能有点像噩梦。

准备数据

Quandl ,一个数据平台,让获取股票数据变得真正容易;如果您超出了免费限额,您也可以快速注册一个免费的 API 密钥:

msf = quandl.get('WIKI/MSFT', start_date="2014-01-01", end_date="2018-08-20")

It returns a nice Pandas dataframe

我不会讲述所有繁琐的数据准备步骤,您可以在我的笔记本中跟随。但我确实想指出至少不跳过粗略的 EDA(探索性数据分析)的价值——我起初没有发现我选择的日期范围对 AAPL 来说有很大的不连续性。

我发现,在 2014 年 6 月 9 日,苹果股票以 1:7 的比例被分割。因此,我简单地将该日期之前的所有数据除以 7,以保持一致。

另一件重要的事情是从数据中去除趋势。起初,我没有这样做,我的人工智能只是学会了通过在早期购买股票并持有直到游戏结束来最大化其回报,因为有一个普遍的上升趋势。没意思!此外,AAPL 和 MSFT 有非常不同的手段和 stddev 的,所以这就像要求人工智能学习交易苹果(双关语!)和橘子。

显然,有几种不同的方法可以消除这种趋势;我用的是 SciPy 的信号处理模块。它用线性逼近器拟合数据,然后从实际数据中减去估计数据。例如,MSFT 是从:

收件人:

你可以看到在转换之后,有一些负的股票价值是没有意义的(比免费的好!).我处理这个问题的方法是,给所有输入数据加上一个常量,使其变为正值。

最后要注意的是,我把两个股票价格都当作一个连续的数组。在上面的图表中,您可以看到 100“天”的数据,但是由于周末和节假日的原因,实际的时间段会更长。为了简单起见,我在这个项目中完全忽略了时间的现实,但在现实世界中,我相信它们是重要的。

让我们暂时抛开训练/测试分离的问题;等我回头再来说,你就明白为什么了。

演员兼评论家 RL

我从 Q-learning 转向 trader bot 的实现,有两个原因:

  • 大家都说演员-评论家更好;和
  • 这实际上更直观。忘记贝尔曼方程,只是使用另一个神经网络来计算状态值,并优化它,就像你优化主要的行动选择(又名策略,又名演员)神经网络一样。

事实上,政策网络和价值网络可以作为两个不同的线性层,位于一个主要的“理解世界”神经网络之上。

代码非常简单,用伪代码表示如下:

For 1..n episodes:
  Until environment says "done":
    Run the current state through the network
    That yields:
      a set of "probabilities" for each action
      a value for how good the state is Sample from those probabilities to pick an action Act upon the environment with that action
    Save the state, action, reward from environment to a buffer Adjust each saved reward by the value of the terminal state
  discounted by gamma each timestep Loss for the episode is the sum over all steps of:
    The log probability of the action we took * its reward
    The value of that action compared to what was expected Propagate the loss back and adjust network parameters

你可以看到 A-C 并没有试图优化行动的选择——我们从来不知道客观上正确的行动会是什么——而是:

  • 每个行动的确定程度,给定其产生的回报
  • 给定状态下,对每个奖励的惊讶程度

随着网络对给定动作越来越确定( p - > 1 ),损耗减少( ln(p) - > 0 ),并且它学习得更慢。另一方面,被取样的不太可能的行为意外地带来了巨大的回报,却产生了更大的损失。这在反推/梯度下降中导致优化器增加将来不太可能的动作的概率。

在我的 A-C 实现中,基于官方 PyTorch 代码,该策略没有ε贪婪的方面(“随着概率的降低,采取随机行动而不是你的最佳猜测,以鼓励探索行动空间”)。相反,我们根据概率从政策网络的输出中取样,所以总有很小的几率会选择一些不太可能的行动。

此外,奖励信号在馈入梯度下降之前会受到轻微扰动,因此反向传播不仅会完美地追踪局部最小值,还会导致一些轻微错误的权重更新,从而在输出端放大,导致选择意外的操作。我认为这也是一种正规化。在我的实现中,我让扰动是一个随机的小量,它在每个训练步骤上都不同;从经验上看,这比每次只添加相同的小常数更有效。将来,随着网络开始融合,我可能会随着时间的推移调整数量。

我最终选定的网络并不复杂,只是我使用递归层可能是个错误,原因我们将会谈到:

环境代码和大部分训练循环代码不是很有趣的样板文件;有兴趣的话,在 Github 上的笔记本里。

国家,和一些失误

我最终选择的状态是一个向量,由以下部分组成:

[AAPL holdings, 
MSFT holdings, 
cash, 
current timestep's AAPL opening price, 
current timestep's MSFT opening price, 
current portfolio value, 
past 5 day average AAPL opening price, 
past 5 day average MSFT opening price]

这当然不是我尝试的第一件事!起初,我手工设计了一些功能:许多不同的移动平均线,最高价和最低价,等等。后来,我放弃了这种想法,认为递归层能够自己找出这些特性。

“Look away, look away … these RL methods will wreck your evening, your whole life and your day” — fellow blunderer Count Olaf from A Series Of Unfortunate Events. Actor Neil Patrick Harris has no critics!

你看,我想让人工智能学习买入信号和卖出信号的基本原理,而不仅仅是学习反刍时间序列。因此,每次重置环境时,我都将其设置为从不同的随机时间步长开始,并使用不同的随机步幅遍历数据,并将“完成”定义为未来不同的随机步数。

虽然我认为这是正确的方法,但不幸的是,这使得 RNN 基本上不可能学到任何有用的东西,因为它每次都不知道自己在系列中的位置。所以我放弃了不同的起点、步幅和序列长度,在所有的训练中保持不变。

将来我一定会保留手工制作的特色;虽然从理论上讲,RNN 可能能够解决这些问题,但训练时间可能会非常长。

结果

大多数时候,机器人学会了不欺骗自己或让自己破产,并且能够获得可观的利润:这里你可以看到 36%的回报(根据它训练的数据)。

(Here, 0.36 means 36% profit)

(初始投资组合价值平均约为 3000 英镑,因此 4000 英镑的奖励代表着 36%的涨幅。)这个机器人也学会了规则:除了一次,它没有让自己破产,也没有试图出售更多股份。这是它在一段训练数据上的样子:

Red: BUY, Green: SELL, Yellow Cross: do nothing

修补以获得更好的结果

我学到的一件重要的事情是,如果不同的状态产生相同的回报,它会使训练变得复杂,并减缓收敛。这里有一个有用的窍门:

在奖励中加入时间因素。随着时间的推移,不杀死游戏的行动越来越有价值;或者说,代理在其环境中持续的时间越长,它得到的回报就越多。

我对代理人的行动给予了一点积极的奖励,对他什么也没做给予了一点消极的奖励。因此,像“购买 AAPL”这样的行为在序列中的任何时候都可能产生+0.1 的回报。但我们最终希望机器人继续前进,直到序列结束,而不会破产,我通过混合时间元素来鼓励这一点,即从奖励中减去剩余的步骤数。“购买 AAPL”还有 50 步,可能产生-49.9 的回报;有 49 步的奖励将是-48.9(更好),以此类推。

虽然这有助于它学会生存更长时间,但我感到困惑的是,为什么我的机器人似乎只会学会生存、收益最大化,却很难学会两者兼而有之。原来设计奖励是相当困难的!步进奖励需要平衡机器人存活的时间和它获得的收益。我用的确切公式是笔记本里的。

一些其他的经验发现:

  • 与所有的负面奖励相比,通过增加好的奖励来弥补好的奖励的稀少。
  • 计算奖励时,没有必要从最终价值中减去投资组合的起始价值。你可以免费得到这个,因为机器人总是试图优化更高。
  • 一旦机器人达到最大值,它就开始振荡;此时,你最好停止训练。
  • 训练的理想地点似乎是在一半时间到达终点状态和一半时间未能到达终点状态之间的“边缘”。

训练/测试分割

此时,一切看起来都很好,您希望在不同时间范围的股票数据上测试该模型,以确保它具有良好的泛化能力。毕竟,我们希望将来能够在我们的 Robinhood 交易账户上部署这一功能,并赚很多钱。

接下来我做的是把时间更早的回溯到 2012 年,抓取从那时到现在的股票数据;然后,我将它分成大约 2/3 的列车,并保留最后 1/3 用于测试。

不幸的是,在考虑趋势后,这两只股票在 2012-2016/17 年期间都经历了下滑,如果你还记得,当时市场被认为是相当波动的。这使得机器人很难学会如何盈利。(根据我使用的 2014 年至 2018 年的原始数据,简单地购买一只股票并持有它是一个非常好的策略)。

为了帮助机器人,我将步幅设置为 1,将序列长度设置为训练数据的长度,这样它就有尽可能多的序列数据进行训练。现在,有足够多的动作奖励对被处理,在 CPU 上继续处理太慢了,所以通过添加 5 个.cuda()语句,我能够将大部分工作转移到 GPU 上。

现在,你可以想象机器人为了获得有意义的奖励而走到大约 1000 步序列末尾的机会。从随机开始,它必须按照它甚至还不知道的规则来玩,并且不要走错一步。即使它这么做了,对我们来说也没什么用,除非它在那段时间里做了一些交易并获利。几个小时的训练时间的浪费证实了这不是一个可行的方法。

为了让它真正发挥作用,我必须发现并应用我认为是一个廉价的技巧:

放松对代理人学习规则的要求;让它在一个非常容易的环境中训练,在那里它不会死,并在连续的训练期间增加难度。

就我在这里创造的金融环境而言,这并不太难。我只需要用大量 AAPL 和 MSFT 的股票和一大笔现金来启动这个代理。训练它一段时间,然后降低起始股份/现金,再训练一次,以此类推。最终它学会了尊重规则。

机器人没有训练过的测试数据的结果不是很好。我认为,如果是这样的话,每个人都已经这样做了,我们将不再有一个正常运作的市场。

It has, however, learned to follow the rules

这是它的“交易策略”之一,用图表表示。红色代表买入,绿色代表卖出,左边是 AAPL,右边是 MSFT。黄色十字是机器人选择不采取行动的时间点。

这是一个更长期的数据,显示了原始的、未转换的股价背景下的买入和卖出。如你所见,相当混乱。

我对 RL 作为通用优化器的潜力很感兴趣,它可以学会自己运行,但事实上它很难很好地工作——特别是在像交易这样的高熵环境中。

至此,我的悲哀和错误的故事结束了。我们没有变得富有,但我们确实找到了最先进的人工智能技术,而且这两件事肯定会随着时间的推移而被证明是相关的!

使用 Tableau 的数据可视化简介:UNICEF 数据

原文:https://towardsdatascience.com/a-brief-introduction-to-data-visualization-using-tableau-9917fc1244f?source=collection_archive---------7-----------------------

我们人类是视觉生物。当有人说大象时,我们的大脑想到的是大象的图片,而不是单词
T5“E L E P H A N T”的字母。

这就是为什么以视觉美感的方式呈现任何信息是最重要的,这样每个人都可以很容易地理解甚至非常复杂的信息。

数据可视化在数据科学项目中的重要性

在每一个数据科学/机器学习项目中, 探索性数据分析(EDA) 是理解手中数据的至关重要的一步。项目的这一阶段处于早期阶段,就在获得数据之后。在设计统计模型之前,使用图形和绘图将数据可视化,以便更好地理解数据并创建一些假设。
同样,当你需要向非数据科学人士展示你所获得的见解时,可视化展示要比展示复杂的数据表好得多。

手中的数据

[## 儿童死亡率数据-儿童基金会数据

儿童基金会数据:监测儿童和妇女的状况

data.unicef.org](https://data.unicef.org/resources/dataset/child-mortality/)

UNICEF DataSet Page

儿童基金会的数据是公开的,它们是真实世界的数据集。我们从上面的链接中得到了数据。我们用的是最后一个文件,名为“死因-2017”
直接下载链接:https://data . UNICEF . org/WP-content/uploads/2017/10/Cause-of-Death-2017 . xlsx

数据预览

该数据集包含 195 个国家和儿童死亡率的列表(<5 years) in them according to causes of death, for two census years — 2000 & 2016. The excel file looks like this.

Tableau : A brilliant tool for creating beautiful Dashboards

Tableau is an extremely powerful tool for visualizing massive sets of data very easily. It has an easy to use drag and drop interface. You can build beautiful visualizations easily and in a short amount of time.

Importing data into Tableau

Tableau supports a wide array of data sources. Here we have used an excel file.

Before importing, it is necessary to format the data in a manner that Tableau can understand. After data preparation our data set looks like this.

Preview of Data Imported into Tableau

Designing Worksheets

I have designed 三个工作表使用我们的数据集,最后将它们组合在一起创建了一个 交互式仪表盘 )。

第一个工作表:按死亡原因和人口普查年份筛选的所有国家数据

1。死亡原因:早产和常年

Cause of Death : Preterm and for All Years

2。死亡原因:艾滋病和常年

Cause of Death : Aids and for All Years

3。按年份过滤:2000T3

FILTERED BY YEAR : 2000

4。按年份过滤:2016

FILTERED BY YEAR : 2016

第二个工作表:按每个国家筛选的所有死亡原因

你可以从第一张工作表中看到,在博茨瓦纳,很大比例的儿童死于艾滋病。可以使用此工作表以特定于国家/地区的方式进行进一步调查。

博茨瓦纳

BOTSWANA

这里有一个维基百科参考,证明我们的发现是正确的,博茨瓦纳确实受到艾滋病的严重影响

印度

INDIA

美利坚合众国

USA

第三张工作表:世界地图

Tableau 可以通过简单的拖放操作创建我们数据集中所有国家的地图。在这里。

World Map built using Tableau

控制板:合并所有工作表

最终的结果是一个漂亮的交互式仪表板,它将所有工作表的功能集中到一个地方。

  • 通过点击地图可以选择任何国家,相关图表显示在我们的国家特定工作表中
  • 普查年过滤器适用于仪表板中的所有工作表。
  • 死亡原因过滤器、人口普查年份过滤器和国家过滤器一起工作,使我们能够轻松理解数据,hep us 正在直观地分析手头的数据。

我通过给出仪表板的快照来结束这篇博客。

国家—俄罗斯,脑膜炎,全年

Country — Russia , COD- Meningitis, Year — ALL

国家—巴西,鳕鱼腹泻,2016 年

Country — Brazil , COD- Diarrhoea, Year —2016

查看现场仪表盘:https://public.tableau.com/profile/sourav.kajuri#!/viz home/causesofchildresses/Dashboard

[## Tableau 公共

编辑描述

public.tableau.com](https://public.tableau.com/profile/sourav.kajuri#!/vizhome/CausesofChildDeaths/Dashboard)

致所有读者

谢谢你浏览我的博客。希望我合理地利用了你的时间。我相信,当我的知识对他人有用时,它真的会激励我

获得知识是走向智慧的第一步,分享知识是走向人性的第一步

神经风格迁移简介

原文:https://towardsdatascience.com/a-brief-introduction-to-neural-style-transfer-d05d0403901d?source=collection_archive---------2-----------------------

2015 年 8 月,一篇名为《艺术风格的神经算法》的论文问世。当时,我刚刚开始深度学习,我试图阅读这篇论文。我不能理解它。所以我放弃了。几个月后,一款名为 Prisma 的应用程序发布了,人们为之疯狂。如果你不知道 Prisma 是什么,它基本上是一个允许你将著名画家的绘画风格应用到自己的照片上的应用程序,并且结果在视觉上相当令人满意。它不同于 Instagram 滤镜,insta gram 滤镜只在色彩空间中对图片进行某种变换。它要复杂得多,结果也更加有趣。这是我在网上找到的一张有趣的照片。

现在,一年后,我学到了很多关于深度学习的知识,我决定再读一遍这篇论文。这次我理解了整篇论文。如果你熟悉深度学习的方法,这实际上是很容易读懂的。在这篇博文中,我主要介绍了我对这篇论文的看法,并试图用更简单的术语向与我一年前处境相同的人(即深度学习领域的初学者)解释神经类型转移。我确信,一旦你看到神经类型转移的结果并理解它是如何工作的,你会对未来的前景和深度神经网络的力量更加兴奋。

基本上,在神经风格转移中,我们有两个图像-风格和内容。我们需要从样式图像中复制样式,并将其应用于内容图像。所谓风格,我们基本上是指图案、笔触等。

为此,我们使用预训练的 VGG-16 网。最初的论文使用 VGG-19 网,但我无法为 TensorFlow 找到 VGG-19 权重,所以我用 VGG-16。实际上,这(使用 VGG-16 而不是 VGG-19)对最终结果没有太大影响。产生的图像是相同的。

那么直观地说,这是如何工作的呢?

为了理解这一点,我将向您介绍一下 ConvNets 是如何工作的。

ConvNets 基于卷积的基本原理工作。比方说,我们有一个图像和一个过滤器。我们在图像上滑动滤波器,将滤波器覆盖的输入的加权和作为输出,通过 sigmoid 或 ReLU 或 tanh 等非线性变换。每个滤波器都有自己的一组权重,在卷积运算期间不会改变。这在下面的 GIF 中有很好的描述

这里,蓝色网格是输入。您可以看到滤波器覆盖的 3x3 区域滑过输入(深蓝色区域)。这种卷积的结果称为特征图,由绿色网格表示。

这是 ReLU 和 tanh 激活函数的图表

ReLU activation function

Tanh activation function

因此,在 ConvNet 中,输入图像与几个滤波器进行卷积,并生成滤波器映射。这些滤波器图然后与一些更多的滤波器卷积,并且产生一些更多的特征图。这一点通过下图得到了很好的说明。

在上图中,您还可以看到术语“最大池”。maxpoollayer 主要用于降维。在最大池操作中,我们简单地在图像上滑动一个大小为 2x2 的窗口,并将窗口覆盖的最大值作为输出。这里有一个例子-

现在这里有一些很酷的东西。仔细观察下图,检查不同图层的特征地图。

你一定注意到了——较低层的贴图寻找低层次的特征,如线条或斑点(gabor 过滤器)。随着我们向更高层发展,我们的功能变得越来越复杂。直观地说,我们可以这样想——较低的层捕捉低层次的特征,如线和斑点,上面的层建立在这些低层次的特征上,并计算稍微复杂的特征,等等…

因此,我们可以得出结论,ConvNets 开发了特征的层次表示。

这个属性是风格转移的基础。

现在记住——在进行风格转换时,我们不是在训练一个神经网络。相反,我们正在做的是——我们从一个由随机像素值组成的空白图像开始,通过改变图像的像素值来优化成本函数。简单地说,我们从空白画布和成本函数开始。然后,我们迭代地修改每个像素,以便最小化我们的成本函数。换句话说,在训练神经网络时,我们更新我们的权重和偏差,但在风格转移中,我们保持权重和偏差不变,而是更新我们的图像。

为了做到这一点,我们的成本函数正确地表示问题是很重要的。成本函数有两项——风格损失项和内容损失项,下面将对这两项进行解释。

内容丢失

这是基于具有相似内容的图像将在网络的较高层中具有相似表示的直觉。

P^l 是原始图像的表示, F^l 是在层 l 的特征图中生成的图像的表示。

风格丧失

这里, A^l 是原始图像的表示, G^l 是层 l 中生成的图像的表示。 Nl 是特征地图的数量 Ml 是图层 l 中展平后的特征地图的大小。 wl 是赋予层 l 风格损失的权重。

所谓风格,我们基本上是指捕捉笔触和模式。因此,我们主要使用较低层,它捕捉低级特征。这里还要注意 gram 矩阵的使用。一个向量的克矩阵XX . X _ 转置。使用 gram matrix 背后的直觉是,我们试图捕捉较低层的统计数据。
不过,你不一定非要使用 Gram 矩阵。一些其他的统计方法(比如均值)已经被尝试过了,而且效果也很好。****

总损失

其中αβ分别是内容和风格的权重。它们可以被调整以改变我们的最终结果。

所以我们的总损失函数基本上代表了我们的问题——我们需要最终图像的内容与内容图像的内容相似,最终图像的风格也应该与风格图像的风格相似。

现在我们要做的就是把这个损失降到最低。我们通过改变网络本身的输入来最小化这种损失。我们基本上从一个空白的灰色画布开始,并开始改变像素值,以尽量减少损失。任何优化器都可以用来最小化这种损失。这里,为了简单起见,我使用了简单的梯度下降。但是人们已经利用亚当和 L-BFGS 在这个任务上取得了相当好的结果。

这个过程在下面的 GIF 中可以看得很清楚。

这是我的一些实验结果。我对这些图像(512x512px)进行了 1000 次迭代,这个过程在我装有 2GB 英伟达 GTX 940MX 的笔记本电脑上花费了大约 25 分钟。如果你在 CPU 上运行它,时间会长得多,但如果你有一个更好的 GPU,时间会短得多。我听说在 GTX 泰坦上 1000 次迭代只需要 2.5 分钟。

如果你希望获得一些关于卷积神经网络的深入知识,请查看斯坦福 CS231n 课程。

这就是你自己的神经类型转移。去吧,实施吧,玩得开心!!
下次见!

如果你想了解更多关于神经类型转移及其用例的信息,可以看看 Fritz AI 关于神经类型转移的优秀博文。该博客还包含额外的资源和教程,以帮助您开始您的第一个神经风格转移项目。

PySpark 简介

原文:https://towardsdatascience.com/a-brief-introduction-to-pyspark-ff4284701873?source=collection_archive---------0-----------------------

Source: Wikimedia (Vienna Technical Museum)

面向数据科学的 PySpark 入门

PySpark 是一种很好的语言,可以进行大规模的探索性数据分析,构建机器学习管道,为数据平台创建 ETL。如果您已经熟悉 Python 和 Pandas 之类的库,那么为了创建更具可伸缩性的分析和管道,PySpark 是一种很好的学习语言。这篇文章的目标是展示如何使用 PySpark 并执行常见任务。

[## NHL 游戏数据

游戏、团队、玩家和游戏信息,包括 x、y 坐标

www.kaggle.com](https://www.kaggle.com/martinellis/nhl-game-data)

我们将为 Spark 环境使用 Databricks,并将 Kaggle 的 NHL 数据集作为分析的数据源。这篇文章展示了如何在 Spark 数据帧中读写数据,创建这些帧的转换和聚合,可视化结果,以及执行线性回归。我还将展示如何使用 Pandas UDFs 以可伸缩的方式将常规 Python 代码与 PySpark 混合。为了简单起见,我们将把重点放在批处理上,避免流数据管道带来的一些复杂性。

这篇文章的完整笔记本可以在 github 上找到。

环境

使用 Spark 有许多不同的选项:

  • 自托管:你可以使用裸机或虚拟机自己建立一个集群。Apache Ambari 是这个选项的一个有用的项目,但是它不是我推荐的快速启动和运行的方法。
  • 云提供商:大多数云提供商都提供 Spark 集群:AWS 有 EMR,GCP 有 DataProc。我曾经在博客上写过关于 DataProc 的文章,你可以比自托管更快地进入交互式环境。
  • 供应商解决方案:包括 Databricks 和 Cloudera 在内的公司提供 Spark 解决方案,使 Spark 的启动和运行变得非常容易。

要使用的解决方案因安全性、成本和现有基础架构而异。如果你正在尝试建立一个学习环境,那么我建议你使用 Databricks 社区版。

Creating a PySpark cluster in Databricks Community Edition.

在这种环境下,很容易启动并运行 Spark 集群和笔记本电脑环境。对于本教程,我用 Spark 2.4 运行时和 Python 3.0 创建了一个集群。要运行本文中的代码,您至少需要 Spark 版的 Pandas UDFs 功能。

火花数据帧

PySpark 中使用的关键数据类型是 Spark 数据帧。这个对象可以被认为是一个分布在集群中的表,其功能类似于 R 和 Pandas 中的数据帧。如果您想使用 PySpark 进行分布式计算,那么您需要对 Spark 数据帧执行操作,而不是其他 python 数据类型。

在使用 Spark 时,也可以使用 Pandas 数据帧,方法是在 Spark 数据帧上调用 toPandas() ,这将返回一个 Pandas 对象。但是,除非使用小数据帧,否则通常应避免使用此函数,因为它会将整个对象拉入单个节点的内存中。

Pandas 和 Spark 数据帧之间的一个关键区别是急切执行和懒惰执行。在 PySpark 中,操作被延迟,直到管道中实际需要一个结果。例如,您可以指定从 S3 加载数据集的操作,并将一些转换应用到数据帧,但是这些操作不会立即应用。相反,转换的图形被记录下来,一旦实际需要数据,例如当将结果写回 S3 时,转换就作为单个流水线操作被应用。这种方法用于避免将完整的数据帧放入内存,并在机器集群中实现更有效的处理。有了 Pandas dataframes,所有东西都被放入内存,每个 Pandas 操作都被立即应用。

一般来说,如果可能的话,最好避免在 Spark 中进行急切的操作,因为这限制了可以有效分布的管道数量。

读取数据

使用 Spark 时,要学习的第一步是将数据集加载到数据帧中。一旦数据被加载到 dataframe 中,您就可以应用转换、执行分析和建模、创建可视化以及持久化结果。在 Python 中,您可以使用 Pandas 直接从本地文件系统加载文件:

import pandas as pd
pd.read_csv("dataset.csv")

在 PySpark 中,加载 CSV 文件稍微复杂一些。在分布式环境中,没有本地存储,因此需要使用分布式文件系统(如 HDFS、数据块文件存储(DBFS)或 S3)来指定文件的路径。

一般来说,使用 PySpark 时,我在 S3 处理数据。许多数据库都提供了卸载到 S3 的功能,也可以使用 AWS 控制台将文件从本地机器移动到 S3。在这篇文章中,我将使用 Databricks 文件系统(DBFS),它以 /FileStore 的形式提供路径。第一步是上传您想要处理的 CSV 文件。

Uploading a file to the Databricks file store.

下一步是将 CSV 文件读入 Spark 数据帧,如下所示。这段代码片段指定了 CSV 文件的路径,并将一些参数传递给 read 函数来处理文件。最后一步显示加载的数据帧的子集,类似于 Pandas 中的df.head()

file_location = "/FileStore/tables/game_skater_stats.csv"df = spark.read.format("csv").option("inferSchema", 
           True).option("header", True).load(file_location)display(df)

在使用 Spark 时,我更喜欢使用 parquet 格式,因为这是一种包含关于列数据类型的元数据的文件格式,提供文件压缩,并且是一种专为使用 Spark 而设计的文件格式。AVRO 是另一种适合 Spark 的格式。下面的代码片段显示了如何从过去的代码片段中提取数据帧,并将其保存为 DBFS 上的拼花文件,然后从保存的拼花文件中重新加载数据帧。

df.write.save('/FileStore/parquet/game_skater_stats',  
               format='parquet')df = spark.read.load("/FileStore/parquet/game_skater_stats")
display(df)

这一步的结果是一样的,但是执行流程有显著的不同。当将 CSV 文件读入数据帧时,Spark 以急切模式执行操作,这意味着在下一步开始执行之前,所有数据都被加载到内存中,而当读取 parquet 格式的文件时,则使用惰性方法。通常,在使用 Spark 时,您希望避免急切的操作,如果我需要处理大型 CSV 文件,我会在执行管道的其余部分之前,首先将数据集转换为 parquet 格式。

通常,您需要处理大量文件,比如位于 DBFS 某个路径或目录下的数百个 parquet 文件。使用 Spark,您可以在路径中包含通配符来处理文件集合。例如,您可以从 S3 载入一批拼花文件,如下所示:

df = spark.read .load("s3a://my_bucket/game_skater_stats/*.parquet")

如果您每天有一个单独的拼花文件,或者如果您的管道中有一个输出数百个拼花文件的在先步骤,那么这种方法非常有用。

如果您想从数据库中读取数据,比如 Redshift,那么在用 Spark 处理数据之前,最好先将数据卸载到 S3。在 Redshift 中, unload 命令可用于将数据导出到 S3 进行处理:

unload ('select * from data_to_process') 
to 's3://my_bucket/game_data'  
iam_role 'arn:aws:iam::123:role/RedshiftExport';

还有数据库库,如火花红移,使这个过程更容易执行。

写入数据

类似于用 Spark 读取数据,使用 PySpark 时不建议将数据写入本地存储。相反,你应该使用分布式文件系统,如 S3 或 HDFS。如果要用 Spark 处理结果,那么 parquet 是保存数据帧的好格式。下面的代码片段显示了如何将数据帧保存到 DBFS 和 S3 作为拼花。

**# DBFS (Parquet)** df.write.save('/FileStore/parquet/game_stats',format='parquet')**# S3 (Parquet)** df.write.parquet("s3a://my_bucket/game_stats", mode="overwrite")

以拼花格式保存数据帧时,通常会将它分成多个文件,如下图所示。

The parquet files generated when saving the dataframe to DBFS.

如果您需要 CSV 文件中的结果,那么需要一个稍微不同的输出步骤。这种方法的一个主要区别是,在输出到 CSV 之前,所有数据都将被拉至单个节点。当您需要保存一个小的数据帧并在 Spark 之外的系统中处理它时,推荐使用这种方法。以下代码片段显示了如何在 DBFS 和 S3 上将数据帧保存为单个 CSV 文件。

**# DBFS (CSV)** df.write.save('/FileStore/parquet/game_stats.csv', format='csv')**# S3 (CSV)** df.coalesce(1).write.format("com.databricks.spark.csv")
   .option("header", "true").save("s3a://my_bucket/game_sstats.csv")

Spark 脚本的另一个常见输出是 NoSQL 数据库,如 Cassandra、DynamoDB 或 Couchbase。这超出了本文的范围,但我过去见过的一种方法是向 S3 写一个数据帧,然后启动一个加载过程,告诉 NoSQL 系统从 S3 上的指定路径加载数据。

我还省略了写入流输出源,如 Kafka 或 Kinesis。当使用火花流时,这些系统更有用。

转换数据

可以在 Spark 数据帧上执行许多不同类型的操作,就像可以在 Pandas 数据帧上应用的各种操作一样。对 Spark 数据帧执行操作的一种方式是通过 Spark SQL,这使得数据帧可以像表一样被查询。下面的片段显示了如何在数据集中找到得分最高的球员。

df.createOrReplaceTempView("stats")display(spark.sql("""
  select player_id, sum(1) as games, sum(goals) as goals
  from stats
  group by 1
  order by 3 desc
  limit 5
"""))

结果是球员 id、出场次数和在这些比赛中的总进球数的列表。如果我们想显示球员的名字,那么我们需要加载一个额外的文件,使它作为一个临时视图可用,然后使用 Spark SQL 连接它。

Top scoring players in the data set.

在上面的代码片段中,我使用了 display 命令来输出数据集的样本,但是也可以将结果分配给另一个 dataframe,这可以在管道的后续步骤中使用。下面的代码显示了如何执行这些步骤,其中第一个查询结果被分配给一个新的 dataframe,然后该 data frame 被分配给一个临时视图,并与一组球员姓名连接。

top_players = spark.sql("""
  select player_id, sum(1) as games, sum(goals) as goals
  from stats
  group by 1
  order by 3 desc
  limit 5
""")top_players.createOrReplaceTempView("top_players")
names.createOrReplaceTempView("names")display(spark.sql("""
  select p.player_id, goals, _c1 as First, _c2 as Last
  from top_players p
  join names n
    on p.player_id = n._c0
  order by 2 desc  
"""))

这一过程的结果如下所示,根据 Kaggle 数据集,确定 Alex Ovechkin 为 NHL 的顶级得分球员。

The output of the process joining dataframes using Spark SQL.

Spark dataframe 操作适用于常见任务,例如添加新列、删除列、执行连接以及计算聚合和分析统计数据,但是在开始使用 Spark SQL 时,执行这些操作可能会更容易。此外,如果您已经在使用诸如 PandaSQL 或 framequery 之类的库来使用 SQL 操作 Pandas 数据帧,那么将代码从 Python 移植到 PySpark 会更容易。

像 Spark 数据帧上的大多数操作一样,Spark SQL 操作是以延迟执行模式执行的,这意味着 SQL 步骤在需要结果之前不会被评估。Spark SQL 提供了一种深入研究 PySpark 的好方法,而无需首先学习一个新的数据帧库。

如果您正在使用数据块,您也可以直接在笔记本中创建可视化,而无需显式使用可视化库。例如,我们可以使用下面的 Spark SQL 代码绘制每场比赛的平均进球数。

display(spark.sql("""
  select cast(substring(game_id, 1, 4) || '-' 
    || substring(game_id, 5, 2) || '-01' as Date) as month
    , sum(goals)/count(distinct game_id) as goals_per_goal
  from stats
  group by 1
  order by 1
"""))

Databricks 笔记本中显示的初始输出是一个结果表,但是我们可以使用绘图功能将输出转换为不同的可视化形式,例如下面显示的条形图。这种方法并不支持数据科学家可能需要的每一种可视化,但它确实使在 Spark 中执行探索性数据分析变得更加容易。如果需要,我们可以使用 toPandas() 函数在驱动程序节点上创建一个 Pandas 数据帧,这意味着任何 Python 绘图库都可以用于可视化结果。但是,这种方法应该只用于小数据帧,因为所有数据都被急切地提取到驱动程序节点的内存中。

Average goals per game during February and March.

我也看了平均每杆进球数,至少有 5 个进球的球员。

display(spark.sql("""
  select cast(goals/shots * 50 as int)/50.0 as Goals_per_shot
      ,sum(1) as Players 
  from (
    select player_id, sum(shots) as shots, sum(goals) as goals
    from stats
    group by 1
    having goals >= 5
  )  
  group by 1
  order by 1
"""))

这种转换的结果如下图所示。大多数至少有 5 个进球的球员完成投篮的概率大约是 4%到 12%。

Goals per shot for players in the Kaggle data set.

MLlib

对于数据科学家来说,Python 的一个常见用例是构建预测模型。虽然 scikit-learn 在处理 pandas 时很棒,但它不能扩展到分布式环境中的大型数据集(尽管有办法用 Spark 对它进行并行化)。当使用 PySpark 和海量数据集构建预测模型时, MLlib 是首选库,因为它本来就在 Spark 数据帧上操作。并不是 scikit-learn 中的每个算法都可以在 MLlib 中使用,但是有各种各样的选项涵盖了许多用例。

为了使用 MLib 中的一种监督算法,您需要使用一个要素矢量和一个标量标注来设置数据帧。一旦做好准备,您就可以使用拟合功能来训练模型。下面的代码片段展示了如何使用一个 VectorAssembler 将 dataframe 中的几个列组合成一个单独的 features vector。我们使用生成的数据帧来调用 fit 函数,然后为模型生成汇总统计数据。

**# MLlib imports** from pyspark.ml.feature import VectorAssembler
from pyspark.ml.regression import LinearRegression**# Create a vector representation for features** assembler = VectorAssembler(inputCols=['shots', 'hits', 'assists', 
    'penaltyMinutes','timeOnIce','takeaways'],outputCol="features")
train_df = assembler.transform(df)**# Fit a linear regression model** lr = LinearRegression(featuresCol = 'features', labelCol='goals')
lr_model = lr.fit(train_df)**# Output statistics** trainingSummary = lr_model.summary
print("Coefficients: " + str(lr_model.coefficients))
print("RMSE: %f" % trainingSummary.rootMeanSquaredError)
print("R2: %f" % trainingSummary.r2)

该模型根据射门次数、比赛时间和其他因素来预测球员的进球数量。然而,该模型的性能很差,其结果是均方根误差(RMSE)为 0.375,R 平方值为 0.125。具有最大值的系数是发射列,但是这并没有提供足够的信号使模型精确。

使用 PySpark 构建 ML 管道时,需要考虑许多额外的步骤,包括训练和测试数据集、超参数调整和模型存储。上面的代码片段只是开始使用 MLlib 的一个起点。

熊猫 UDF

Spark 中我最近一直在使用的一个特性是 Pandas 用户定义函数(UDF ),它使您能够在 Spark 环境中使用 Pandas 数据帧执行分布式计算。这些 UDF 的一般工作方式是,首先使用 groupby 语句对 Spark 数据帧进行分区,然后每个分区被发送到一个 worker 节点,并被转换成 Pandas 数据帧,该数据帧被传递给 UDF。然后,UDF 返回转换后的 Pandas 数据帧,该数据帧与所有其他分区组合,然后转换回 Spark 数据帧。最终结果是非常有用的,你可以使用需要 Pandas 的 Python 库,但是现在可以扩展到大规模数据集,只要你有一个好的方法来划分你的数据帧。熊猫 UDF 是在 Spark 2.3 中引入的,我将在 Spark Summit 2019 期间谈论我们如何在 Zynga 使用这一功能。

曲线拟合是我作为数据科学家执行的一项常见任务。下面的代码片段显示了如何执行曲线拟合来描述玩家在游戏过程中记录的射门次数和命中次数之间的关系。该代码片段显示了我们如何通过对过滤到单个玩家的数据集调用 toPandas() 来为单个玩家执行这个任务。这一步的输出是两个参数(线性回归系数),试图描述这些变量之间的关系。

**# Sample data for a player** sample_pd = spark.sql("""
  select * from stats
  where player_id = 8471214
""").toPandas()**# Import python libraries** from scipy.optimize import leastsq
import numpy as np**# Define a function to fit** def fit(params, x, y):
    return (y - (params[0] + x * params[1] ))**# Fit the curve and show the results** 
result = leastsq(fit, [1, 0], 
                 args=(sample_pd.shots, sample_pd.hits))
print(result)

如果我们想为每个玩家计算这条曲线,并且有一个庞大的数据集,那么 toPandas() 调用将会由于内存不足异常而失败。我们可以通过在 player_id 上调用 groupby() ,然后应用如下所示的熊猫 UDF,将这个操作扩展到整个数据集。该函数将描述单个玩家游戏统计数据的 Pandas 数据帧作为输入,并返回一个包括 player_id 和拟合系数的汇总数据帧。然后,每个 summary Pandas 数据帧被组合成一个 Spark 数据帧,显示在代码片段的末尾。使用 Pandas UDFs 的另一项设置是为生成的数据帧定义模式,其中模式描述了从应用步骤生成的 Spark 数据帧的格式。

**# Load necessary libraries** from pyspark.sql.functions import pandas_udf, PandasUDFType
from pyspark.sql.types import *
import pandas as pd**# Create the schema for the resulting data frame** schema = StructType([StructField('ID', LongType(), True),
                     StructField('p0', DoubleType(), True),
                     StructField('p1', DoubleType(), True)])**# Define the UDF, input and outputs are Pandas DFs** [@pandas_udf](http://twitter.com/pandas_udf)(schema, PandasUDFType.GROUPED_MAP)
def analyze_player(sample_pd): **# return empty params in not enough data**    if (len(sample_pd.shots) <= 1):
        return pd.DataFrame({'ID': [sample_pd.player_id[0]], 
                                   'p0': [ 0 ], 'p1': [ 0 ]})

 **# Perform curve fitting**    result = leastsq(fit, [1, 0], args=(sample_pd.shots, 
                                  sample_pd.hits)) **# Return the parameters as a Pandas DF**    return pd.DataFrame({'ID': [sample_pd.player_id[0]], 
                       'p0': [result[0][0]], 'p1': [result[0][1]]})**# perform the UDF and show the results** player_df = df.groupby('player_id').apply(analyze_player)
display(player_df)

这个过程的输出如下所示。我们现在有了一个数据框架,总结了每个球员的曲线拟合,并可以在一个巨大的数据集上运行这个操作。当处理大型数据集时,选择或生成分区键以在数据分区的数量和大小之间取得良好的平衡是很重要的。

Output from the Pandas UDF, showing curve fits per player.

最佳实践

我已经介绍了使用 PySpark 的一些常见任务,但是还想提供一些建议,以便更容易地从 Python 过渡到 PySpark。以下是我根据在这些环境之间移植一些项目的经验收集的一些最佳实践:

  • 避免使用字典,使用数据框架:使用字典等 Python 数据类型意味着代码可能无法在分布式模式下执行。不要使用键来索引字典中的值,可以考虑向 dataframe 中添加另一列来用作过滤器。
  • 少用toPandas:调用 toPandas() 会导致所有数据被加载到驱动节点的内存中,并阻止操作以分布式方式执行。当数据已经聚合并且您想要使用熟悉的 Python 绘图工具时,使用此函数是很好的,但是它不应该用于大型数据帧。
  • 避免 for 循环:如果可能,最好使用 groupby-apply 模式重写 for 循环逻辑,以支持并行代码执行。我注意到,专注于在 Python 中使用这种模式也导致了更容易翻译成 PySpark 的代码的清理。
  • 尽量减少急切操作:为了让您的管道尽可能地可伸缩,最好避免将完整数据帧拉入内存的急切操作。我注意到在 CSV 中读取是一个急切的操作,我的工作是将数据帧保存为 parquet,然后从 parquet 重新加载它,以构建更具可伸缩性的管道。
  • 使用 framequery/pandasql 使移植更容易:如果您正在使用其他人的 Python 代码,那么破译一些 Pandas 操作正在实现的功能可能会很棘手。如果您计划将代码从 Python 移植到 PySpark,那么使用 Pandas 的 SQL 库可以使这种转换更容易。

我发现花时间在 PySpark 上写代码也因 Python 编码技巧而有所提高。

结论

PySpark 是数据科学家学习的一门好语言,因为它支持可扩展的分析和 ML 管道。如果您已经熟悉 Python 和 Pandas,那么您的许多知识都可以应用于 Spark。我已经展示了如何用 PySpark 执行一些常见的操作来引导学习过程。我还展示了 Pandas UDFs 的一些最新 Spark 功能,这些功能使 Python 代码能够以分布式模式执行。有很好的环境使 Spark 集群很容易启动和运行,现在是学习 PySpark 的好时机!

本·韦伯是 Zynga 的首席数据科学家。我们正在招聘!

强化学习与价值函数简介

原文:https://towardsdatascience.com/a-brief-introduction-to-reinforcement-learning-and-value-functions-8aa0919fc02e?source=collection_archive---------8-----------------------

在我之前的帖子中,我已经讨论了 n 臂土匪问题,我希望我已经给了你关于强化学习的基本直觉。在这篇文章中,我计划深入研究并正式定义强化学习问题。但是首先,有几个更重要的概念要介绍…

价值函数

在之前的帖子中,我解释了拉动老丨虎丨机的 n 个臂的每一个被认为是不同的动作,并且每个动作都有我们不知道的值。我们所能观察到的只是吃角子老丨虎丨机在我们执行一个动作(拉手臂)后给我们的奖励。

我们的主要目标是最大化回报。如果我们知道每个动作的值,这就很容易做到,因为我们总是可以用最大值来执行动作。

但问题是——我们永远无法找到一个行为的实际价值,但我们可以很精确地估计它。

那么我们如何评估一个行为的价值呢?

在 n 个武装匪徒的问题中,有一种方法可以做到这一点,那就是不断执行动作,并保存一份我们得到的所有奖励的列表,然后对每个动作的奖励进行平均。这将会给我们一个行动价值的估计,但是我们估计的好坏取决于我们执行行动的次数。我们执行一个动作的次数越多,我们对它的价值的估计就越准确。

这在数学上可以写成-

其中, Qt(a) 是在第 t 次播放时动作‘a’的估计值。 r1,r2,… 是获得的奖励。 ka 是动作 a 已经执行的次数。

很简单,对吧?

但是用这种方法发现行动的价值需要我们维护一个行动和回报的列表,并且随着我们不断地执行行动,这个列表会无限制地增长。这是一个严重的问题,因为这样的列表会占用太多的内存。

下面的等式解决了这个问题,因为它只需要我们跟踪两个变量- Qk 和 k。

到目前为止一切顺利。我们有一个 n 臂强盗,每个臂都有不同的值(平均奖励),我们可以拉任何一个臂。直到现在,土匪的手臂的价值是不变的,也就是说,我们正在处理一个稳定的问题。但是如果手臂的值随着时间慢慢变化,而我们不知道如何变化呢?在这种情况下,我们会怎么做?

价值函数随时间变化的这类问题称为非平稳问题。在这种情况下,与旧的奖励相比,我们更重视最近的奖励是有意义的。这可以使用下面的等式来完成

其中,α是步长参数。它是一个介于 0 和 1 之间的常数。你可能会注意到,上面的等式与前面的等式非常相似。这两个方程的唯一区别是,在前一个方程中,步长随 k 变化,而在后一个方程中,步长是常数。

现在,如果我们插入 Qk 的值,我们得到

你可以在上面的等式中看到,Qk+1 取决于(1-α)^(k-i).由于(1-α)<1,Ri 的权重随着 I 的增加而降低。这意味着我们对较老的奖励给予较少的权重。

请记住,上述方法只适用于价值函数变化缓慢的非平稳问题。

乐观的初始值

这种方法就像一个小黑客,鼓励代理在开始时探索。

Q0 的值可以设置为某个较高的正值,例如 30。现在,由于最高奖励只有 10,我们的值 Q0 是非常乐观的。无论代理选择哪一个行动,它都会得到比价值估计值少的奖励,因此,它会继续探索其他行动。

请注意,这种黑客攻击的效果只是暂时的,在开始时大多可以注意到。

这就完成了强化学习的第二章:简介。干杯。✌ ️😁

慢速特征分析快速介绍

原文:https://towardsdatascience.com/a-brief-introduction-to-slow-feature-analysis-18c901bc2a58?source=collection_archive---------0-----------------------

Photograph by Jürgen Schoner / CC BY-SA 3.0

使用 python 和数学的面向应用的 SFA 介绍

我最近开始在波鸿鲁尔大学攻读机器学习的博士学位。我加入的小组的一个主要研究课题叫做慢特征分析(SFA)。为了了解一个新的话题,在让自己沉浸在数学的严谨中之前,如果可能的话,我喜欢看例子和直观的解释。我写这篇博文是为了那些喜欢以类似方式研究主题的人,因为我相信 SFA 是非常强大和有趣的。

在这篇文章中,我将以一个应用 SFA 的代码示例开始,来帮助激发这种方法。然后,我将更详细地介绍该方法背后的数学原理,最后提供该材料中其他优秀资源的链接。

1.确定平滑潜变量

SFA 是一种无监督学习方法,从时间序列中提取最平滑(最慢)的底层函数或特征。这可以用于降维、回归和分类。例如,我们可以有一个高度不稳定的序列,它是由一个行为更好的潜在变量决定的。

让我们从生成时间序列 DS: 开始

这就是所谓的逻辑地图。通过绘制系列 S ,我们可以考察它的混沌本质。驱动上述曲线行为的基本时间序列 D 要简单得多:

我们如何从不稳定的时间序列中确定简单的潜在驱动力?

我们可以用 SFA 来确定一个函数变化最慢的特征。在我们的例子中,我们将从像 S 这样的数据开始,以 D 结束,而不必事先知道 S 是如何生成的。

SFA 的实现旨在找到输入的特征,这些特征是线性的。但是从我们的例子可以看出,驱动力 D 是高度非线性的!这可以通过首先对时间序列 S 进行非线性扩展来弥补,然后找到扩展数据的线性特征。通过这样做,我们发现了原始数据的非线性特征。

让我们通过堆叠 S 的时间延迟副本来创建一个新的多元时间序列:

接下来,我们对数据进行立方扩展,并提取 SFA 特征。三次展开将一个四维向量[ abcd]ᵀ]变成 34 个元素向量,其中元素 t 、t v、tvu、t 、tv、t 为不同的 t、u、v ∈{a、b、c、d}。

请记住,添加时间延迟副本的最佳数量因问题而异。或者,如果原始数据维数过高,则需要进行降维,例如使用主成分分析。

因此,考虑以下是该方法的超参数:维度扩展(缩减)的方法、扩展(缩减)后的输出维度以及待发现的慢特征的数量。

现在,添加时间延迟副本后,时间序列的长度从 300 变为 297。因此,慢特征时间序列的相应长度也是 297。为了更好的可视化,我们将第一个值添加到它前面,并将最后一个值添加两次,从而将它的长度变为 300。SFA 发现的特征具有零均值和单位方差,因此在可视化结果之前,我们也对 D 进行归一化。

即使只考虑 300 个数据点,SFA 特性也能几乎完全恢复底层源代码——这令人印象深刻!

2.引擎盖下到底发生了什么?

理论上,SFA 算法接受一个(多变量)时间序列 X 和一个整数 m 作为输入,该整数表示要从该序列中提取的特征的数量,其中 m 小于时间序列的维数。该算法确定了 m 个函数

使得每个 yᵢ 的两个连续时间点的时间导数的平方的平均值最小化。直觉上,我们希望最大化这些特性的缓慢性:

其中点表示时间导数,在离散情况下:

目标函数(1)测量特征的慢度。零均值约束(2)使得特征的二阶矩和方差相等,并简化了符号。单位方差约束(3)丢弃常数解。

最后的约束(4)使我们的特征去相关,并导致它们的慢度排序。这意味着我们首先找到最慢的特征,然后我们找到下一个最慢的特征,它与前一个特征正交,依此类推。对特征进行去相关可以确保我们捕捉到最多的信息。

在接下来的内容中,我浏览了重要的细节并跳过了一些步骤,但是为了完整起见,我想把它包括进来。我建议也看看下面的链接,以获得更全面的解释。

让我们只考虑线性特征:

时间序列 X 可以是“原始数据”或其非线性扩展,见上例。请记住,即使这些是扩展数据的线性特征,它们也可能是原始数据的非线性特征。

假设零均值,通过求解广义特征值问题AW=bwλ找到线性特征。我们确定 m 个特征值-特征向量元组( λᵢWᵢ )使得awᵢ=λᵢb我们有**

标量 λᵢ 表示特征的慢度,即 λᵢ 越小,相应的 yᵢ 变化越慢。如果你熟悉广义特征值问题,注意这里的特征值是增加的——而不是减少的。最后,特征向量 Wᵢ 是定义我们学习特征的变换向量。

3.进一步阅读

原文:https://www.ini.rub.de/PEOPLE/wiskott/Reprints/WiskottSejnowski-2002-NeurComp-LearningInvariances.pdf

SFA 在分类中的应用:http://cogprints.org/4104/1/Berkes2005a-preprint.pdf

以上例子改编自:http://MDP-toolkit . SourceForge . net/examples/log map/log map . html


在推特上关注我

支持向量机简介

原文:https://towardsdatascience.com/a-brief-introduction-to-support-vector-machine-adf0f103a80f?source=collection_archive---------14-----------------------

支持向量机(SVM)是最流行的机器学习分类器之一。它属于监督学习算法的范畴,并使用边缘的概念在类之间进行分类。它给出了比 KNN,决策树和朴素贝叶斯分类器更好的准确性,因此非常有用。

谁应该阅读这篇文章

任何对机器学习概念有所了解并对学习 SVM 感兴趣的人。如果你是这个领域的初学者,先浏览一下这篇文章。

读完这篇文章,你会知道:

  1. SVM 到底是什么
  2. 如何使用 Sklearn (Python)的 SVM 分类器
  3. 调整其参数以获得更好的结果

所以让我们开始吧!

什么是 SVM?

如前所述,SVM 属于用于分类的监督算法类别。让我们从两个类的例子开始:

给定类 X1 和 X2,我们想要找到最好地分离这两个类的判定边界,即具有最小误差。

SVM 用一个 【超平面】 做到了这一点。这个超平面在二维数据的情况下可以是一条直线,在三维数据的情况下可以是一个平面。

不用深入幕后的数学,让我们了解一些基本的功能。

支持向量机使用了‘支持向量的概念,支持向量是离超平面最近的点。

在上面的例子中,红线表示分隔两个类(蓝色星形和红色圆形)的决策边界,连字符线表示我们的'' Margin ',即我们想要的两个类的支持向量之间的差距。

界限很重要

边缘是在支持向量的帮助下定义的(因此得名)。在我们的示例中,黄色的星星和黄色的圆圈是定义边距的支持向量。间隙越大,分类器工作得越好。因此,支持向量在开发分类器中起着重要的作用。

测试数据中的每一个新数据点都将根据这个余量进行分类。如果它位于它的右侧,它将被归类为红色圆圈,否则被归类为蓝色星星。

最棒的是,SVM 还可以对非线性数据进行分类。

在非线性数据的情况下,事情变得有点棘手。这里 SVM 使用了Kernel-trick,它使用一个核函数将非线性数据映射到更高维度,这样它就变成线性的,并在那里找到决策边界。

无论是线性数据还是非线性数据,SVM 总是使用核函数,但当数据以其当前形式不可分时,它的主要功能就会发挥作用。这里,核函数为分类问题增加了维度。

现在让我们看一些代码。

使用支持向量机

在 Sklearn 的帮助下,您只需几行代码就可以利用 SVM 分类器的强大功能。

from sklearn import svm #Our linear classifier
clf = svm.SVC(kernel='linear') ''' 
X_train is your training data y_train are the corresponding labels y_pred are the predicted samples of the test data X_test 
'''#Training our classifier on training set with labels
clf.fit(X_train, y_train)#Predicting output on the Test set 
y_pred = clf.predict(X_test) #Finding the Accuracy 
print("Accuracy:",metrics.accuracy_score(y_test, y_pred))

在这种情况下,我们使用的是线性内核,如你所见。根据问题的不同,您可以使用不同类型的内核函数:

  • 线性的
  • 多项式
  • 径向基函数
  • 高斯的
  • 拉普拉斯(侯爵)

…以及更多。选择正确的核函数对于构建分类器非常重要。在下一节中,我们将调整超参数,使我们的分类器更好。

你可以在这里访问完整的代码。

如果你觉得无聊,这里有一只可爱的猫!

调谐参数

内核:我们已经讨论过内核函数有多重要。根据问题的性质,必须选择正确的核函数,因为核函数定义了为问题选择的超平面。这里的是最常用的内核函数列表。

正规化:听说过过度拟合这个词吗?如果你没有,我认为你应该从这里的学习一些基础知识。在 SVM,为了避免过度拟合,我们选择软边界,而不是硬边界,即我们故意让一些数据点进入我们的边界(但我们仍然惩罚它),这样我们的分类器就不会过度拟合我们的训练样本。这里有一个重要的参数γ(γ),它控制 SVM 的过拟合。伽玛越高,超平面尝试匹配训练数据的程度越高。因此,选择最佳伽马值以避免过拟合和欠拟合是关键。

误差罚分:参数 C 代表对 SVM 错误分类的误差罚分。它保持了更平滑的超平面和错误分类之间的折衷。如前所述,为了避免分类器过拟合,我们允许一些错误分类。

这些是用于调整 SVM 分类器的最重要的参数。

总的来说,SVM 具有许多优点,因为它提供高精度,具有低复杂性,并且对于非线性数据也非常有效。缺点是,与朴素贝叶斯等其他算法相比,它需要更多的训练时间。

这就是支持向量机!如果你有任何问题,请在评论中告诉我。

恭喜你坚持到帖子的最后!

这是给你的饼干

如果你喜欢这篇文章,别忘了加上掌声

原载于 2018 年 11 月 2 日【adityarohilla.com】

两种数据处理架构简介— Lambda 和 Kappa 用于大数据

原文:https://towardsdatascience.com/a-brief-introduction-to-two-data-processing-architectures-lambda-and-kappa-for-big-data-4f35c28005bb?source=collection_archive---------2-----------------------

B ig 数据、物联网(IoT)、机器学习模型和其他各种现代系统正在成为今天不可避免的现实。各行各业的人们已经开始将与数据存储和服务器的交互作为他们日常生活的一部分。因此,我们可以说,以最佳方式处理大数据正成为企业、科学家和个人的主要兴趣领域。例如,为实现某些业务目标而启动的应用程序,如果能够有效地处理客户提出的查询并很好地服务于他们的目的,将会更加成功。这种应用程序需要与数据存储进行交互,在本文中,我们将尝试探索两种重要的数据处理架构,它们是各种企业应用程序(称为 Lambda 和 Kappa)的主干。

社交媒体应用程序、基于云的系统、物联网和无休止的创新热潮的快速增长,使得开发人员或数据科学家在启动、升级企业应用程序或对其进行故障排除时做出精心计算的决策变得非常重要。尽管使用模块化方法来构建应用程序具有多种优势和长期益处,这一点已经被广泛接受和理解,但是对选择正确的数据处理架构的追求仍然在许多与现有和即将出现的企业软件相关的提议前面打上问号。尽管目前全球有各种各样的数据处理架构,但让我们详细研究一下 Lambda 和 Kappa 架构,并找出它们的独特之处,以及在什么情况下应该优先选择哪一种。

λ架构

Lambda 架构是一种数据处理技术,能够以高效的方式处理大量数据。这种体系结构的效率以增加吞吐量、减少延迟和忽略错误的形式变得显而易见。当我们提到数据处理时,我们基本上使用这个术语来表示高吞吐量、低延迟和以接近实时的应用为目标。这也将允许开发者在基于事件的数据处理模型中以代码逻辑或自然语言处理(NLP)的形式定义增量规则,以实现稳健性、自动化和效率,并提高数据质量。此外,数据状态的任何变化对系统来说都是一个事件,事实上,作为对运行中的事件的响应,可以发出命令、查询或期望执行增量过程。

事件源是使用事件进行预测以及实时存储系统中的变化的概念。系统状态的变化、数据库中的更新或事件可以理解为变化。例如,如果有人与网页或社交网络个人资料进行交互,则页面查看、喜欢或添加为好友请求等事件会触发可以处理或丰富的事件,并将数据存储在数据库中。

数据处理处理事件流,大多数遵循领域驱动设计的企业软件使用流处理方法来预测基本模型的更新,并存储不同的事件,作为实时数据系统中预测的来源。为了处理系统中发生的大量事件或增量处理,Lambda 架构通过引入三个不同的层来实现数据处理。Lambda 架构由批处理层、速度层(也称为流层)和服务层组成。

1.批量层

新数据源源不断地输入数据系统。在任何情况下,它都被同时输送到配料层和速度层。任何到达数据系统批处理层的新数据流都是在数据湖之上进行计算和处理的。当数据存储在数据湖中时,使用数据库,如内存数据库或长期持久数据库,如基于 NoSQL 的存储 batch layer 使用它来处理数据,使用 MapReduce 或利用机器学习(ML)来预测即将到来的批处理视图。

2.速度层(流层)

速度层使用在批处理层完成的事件源的成果。在批处理层中处理的数据流导致更新 delta 过程或 MapReduce 或机器学习模型,流层进一步使用这些模型来处理馈送给它的新数据。速度层提供基础丰富过程的输出,并支持服务层减少响应查询的延迟。顾名思义,速度层具有较低的延迟,因为它只处理实时数据,计算量较小。

3.服务层

来自批处理层的批处理视图形式的输出和来自速度层的近实时视图形式的输出被转发到服务层,服务层使用这些数据来满足临时的未决查询。

下面是 Lambda 架构模型的基本示意图:

Lambda Architecture

让我们将其转化为一个函数方程,它定义了大数据领域中的任何查询。这个等式中使用的符号称为 Lambda,Lambda 架构的名称也是从同一个等式中产生的。对于熟悉大数据分析花絮的人来说,这个功能广为人知。

Query = λ (Complete data) = λ (live streaming data) * λ (Stored data)

该等式意味着,通过在速度层的帮助下以批处理和实时流的形式组合来自历史存储的结果,可以在 Lambda 架构中满足所有与数据相关的查询。

Lambda 架构的应用

Lambda 架构可以部署在以下数据处理企业模型中:

  • 用户查询需要使用不可变的数据存储在特定的基础上提供服务。
  • 需要快速响应,系统应该能够处理新数据流形式的各种更新。
  • 不应删除任何存储的记录,并且应允许向数据库添加更新和新数据。

Lambda 架构可以被认为是接近实时的数据处理架构。如上所述,它可以承受故障,并允许可伸缩性。它使用批处理层和流层的功能,并不断向主存储器添加新数据,同时确保现有数据保持不变。Twitter、网飞和雅虎等公司正在使用这种架构来满足服务质量标准。

Lambda 架构的利弊

赞成的意见

  • Lambda 架构的批处理层通过容错分布式存储管理历史数据,即使系统崩溃也能确保低错误率。
  • 这是速度和可靠性的良好平衡。
  • 容错和可扩展的数据处理体系结构。

骗局

  • 由于涉及全面的处理,它会导致编码开销。
  • 重新处理每个批处理周期,这在某些情况下是无益的。
  • 用 Lambda 架构建模的数据很难移植或重组。

卡帕建筑

在 2014 年,Jay Kreps 发起了一场讨论,他指出了 Lambda 架构的一些差异,这些差异进一步将大数据世界引向了另一种替代架构,这种架构使用较少的代码资源,并且能够在某些使用多层 Lambda 架构似乎有些奢侈的企业场景中运行良好。

Kappa 架构不能作为 Lambda 架构的替代品,相反,它应被视为在批处理层的主动性能不需要满足标准服务质量的情况下使用的替代方案。这种体系结构在不同事件的实时处理中有其应用。这是 Kappa 架构的基本示意图,显示了该数据处理架构的两层操作系统。

Kappa Architecture

让我们将 kappa 架构的操作顺序转化为一个函数等式,该等式定义了大数据领域中的任何查询。

Query = K (New Data) = K (Live streaming data)

这个等式意味着所有的查询都可以通过在速度层对实时数据流应用 kappa 函数来满足。它还表示流处理发生在 kappa 架构中的速度层。

卡帕架构的应用

社交网络应用的一些变体、连接到基于云的监控系统的设备、物联网(IoT)使用优化版本的 Lambda 架构,该架构主要使用速度层与流层相结合的服务来处理数据湖中的数据。

Kappa 架构可以部署在以下数据处理企业模型中:

  • 多个数据事件或查询被记录在一个队列中,以迎合分布式文件系统存储或历史。
  • 事件和查询的顺序不是预先确定的。流处理平台可以随时与数据库交互。
  • 它具有弹性和高可用性,因为系统的每个节点都需要处理数 TB 的存储来支持复制。

上面提到的数据场景是通过耗尽 Apache Kafka 来处理的,Apache Kafka 速度极快,具有容错性和水平可伸缩性。它允许一个更好的机制来管理数据流。对流处理器和数据库的平衡控制使得应用程序能够按照预期执行。Kafka 将有序数据保留更长时间,并通过将它们链接到保留日志的适当位置来满足类似的查询。LinkedIn 和其他一些应用程序使用这种风格的大数据处理,并获得保留大量数据的好处,以满足那些仅仅是彼此副本的查询。

卡帕建筑的利与弊

优点

  • Kappa 架构可用于开发在线学习者的数据系统,因此不需要批处理层。
  • 只有当代码改变时才需要重新处理。
  • 它可以使用固定内存进行部署。
  • 它可以用于水平可伸缩的系统。
  • 由于机器学习是在实时基础上进行的,因此需要的资源更少。

缺点

缺少批处理层可能会导致数据处理过程中或更新数据库时出错,这需要使用异常管理器来重新处理数据或进行协调。

结论

简而言之,在 Lambda 和 Kappa 架构之间的选择似乎是一种权衡。如果您寻求一种在更新数据湖方面更可靠,以及在设计机器学习模型以稳健的方式预测即将发生的事件方面更有效的架构,您应该使用 Lambda 架构,因为它获得了批处理层和速度层的优势,以确保更少的错误和速度。另一方面,如果您希望通过使用较便宜的硬件来部署大数据架构,并要求它有效地处理运行时发生的独特事件,则选择 Kappa 架构来满足您的实时数据处理需求。

FlowNet 简介

原文:https://towardsdatascience.com/a-brief-review-of-flownet-dca6bd574de0?source=collection_archive---------1-----------------------

最近,细胞神经网络已经成功地用于估计光流。与传统方法相比,这些方法在质量上有了很大的提高。在此,我们将对以下论文进行简要回顾。

概观

卷积神经网络(CNN)在各种计算机视觉任务中做出了巨大贡献。最近,细胞神经网络已经成功地用于估计光流。与传统方法相比,这些方法在质量上有了很大的提高。在此,我们将对以下论文进行简要回顾。

FlowNet1.0 和 FlowNet2.0 都是端到端架构。FlowNet2.0 由 FlowNetCorr 和 FlowNet 堆叠而成,比 FlowNetCorr 和 flownet 都有好得多的结果。FlowNetS 简单地将两个顺序相邻的图像堆叠起来作为输入,而在 FlowNetCorr 中,两个图像被分别卷积,并通过一个相关层组合在一起。在空间金字塔网络中,作者为每一层独立训练一个深度网络来计算流量更新。SPyNet 和 FlowNet2.0 都以由粗到细的方式估计大的运动。FlowNet2.0 在这些架构中性能最好,SPyNet 的模型参数最少。

FlowNet:用卷积网络学习光流

在 FlowNet1.0 中,本文提出并比较了两种架构:FlowNetSimple 和 FlowNetCorr。这两种架构都是端到端的学习方法。在 FlowNetSimple 中,如图 1 所示,作者简单地将两个顺序相邻的输入图像堆叠在一起,并通过网络传送它们。与 FlowNetSimple 相比,FlowNetCorr(图 2)首先分别产生两幅图像的表示,然后在“相关层”将它们结合在一起,一起学习更高的表示。这两种架构都有用于上采样分辨率的改进。

相关层用于在两个特征图之间执行乘法面片比较。更具体地,给定两个多通道特征图 f1、f2,其中 w、h 和 c 是它们的宽度、高度和通道数量。以第一个图中的 x1 和第二个图中的 x2 为中心的两个补片的“相关性”定义为:

其中 x1 和 x2 分别是第一地图和第二地图的中心,并且大小为 K = 2k+1 的正方形空间面片。此外,出于计算原因,作者限制了最大位移。具体来说,对于每个位置 x1,作者通过计算大小为 D = 2d+1 的邻域中的相关性来限制 x2 的范围,D 是给定的最大位移。输出的大小是(whD)。然后,作者将使用卷积层从 f1 提取的特征图与输出连接。

然而,在一系列卷积层和汇集层之后,分辨率已经降低。因此,作者通过“向上进化”层改进了粗略的池化表示,包括取消池化和向上进化。对特征图进行上变换后,作者将其与相应的特征图和上采样的粗流量预测连接起来。如图 3 所示

实际上,作者在 Github 上提供的模型与上图略有不同。图 3 的第二个框不仅包括来自 deconv5 和 con5_1 的特征图,还包括由以下流生成的流 6。

con V6—-(conv)—> con V6 _ 1—(conv)→predict _ flow 6—-(conv)—> flow 6

表 1。显示不同数据集上不同方法的平均终点误差(以像素为单位)。

FlowNet 2.0:深度网络光流估计的发展

简介和贡献

FlowNet2.0 比 FlowNet1.0 好得多,与 FlowNet1.0 相比,FlowNet2.0 在质量和速度上都有很大的提高。主要架构如图 7 所示。本文有四个主要贡献:

1.呈现数据的时间表在培训进度中很重要
2。提出了堆叠架构
3。介绍了一个专门研究小动作的子网络
4。提出了融合架构

数据测试计划

在实验中,不仅训练数据的种类对性能很重要,而且它在训练期间呈现的顺序也很重要。作者分别在椅子和 Things3D 上测试了 FlowNetS 和 FlowNetCorr。图 5 显示了使用不同学习速率表的两个数据集样本的等量混合。S_short、S_long 和 S_fine 是不同的学习速率表,如图 6 所示。图 5 中的数字表示 Sintel 数据集的终点误差。从图 5 中,我们可以知道最好的结果是先在椅子上训练,然后在 Things3D 上微调。

堆叠网络

为了计算光流的大位移,作者叠加了流网和流网校正,如图 7 所示。表 3 显示了叠加流网的效果,其中应用了图 5 中的最佳流网。第一流网获取图像 I1 和 I2 作为输入,第二流网获取图像 I1、由第一流网计算的流 wi、由流 wi 扭曲的图像 I2 以及由流 wi 扭曲的图像 I1 和图像 I2 之间的亮度差误差。

在训练栈结构中有两种方法:固定第一网络的权重,或者与第二网络一起更新它们。结果如表 3 所示,从中我们可以看出,当固定 Net1 并用 warping 训练 Net2 时,在 Sintel 上获得了最好的结果。

此外,作者确实对堆叠多个不同的网络进行了实验,他们发现多次堆叠具有相同权重的网络,并对这种循环的过去进行微调不会改善结果。因此,他们添加了不同权重的网络,每个新网络首先在椅子上进行训练,并在 Things3D 上进行微调。最后,他们通过平衡网络精度和运行时间来实施 FlowNet2-CSS。FlowNetCorr 是 FlowNet2-CSS 的第一个网络,后面是两个 FlowNet,如图 7 所示的第一个流

小位移网络与融合

但是,对于小排量,FlowNet2-CSS 并不可靠。因此,作者创建了一个具有小位移的小数据集,并在该数据集中训练 FlowNetSD。FlowNetSD 与 FlowNetS 略有不同。他们用多个 33 内核替换了开头的 77 和 5*5 内核,去掉了第一层的 stride 2。最后,作者引入了一个小而简单的深度网络(Fusion)来融合 FlowNet2-CSS 和 FlowNet2-SD 的输出,如图 7 所示。

表演

表 4 显示了不同基准测试的性能。AEE:平均终点误差;Fl-all:流量估计误差为 3 个像素和 5%的像素比率。在 Sintel、Sintel final 和 Middlebury 中,FlowNet2 在准确率上超越了所有其他参考方法,在其他准确率相对较高的数据集上也表现良好。

使用空间金字塔网络的光流估计

介绍

将经典的空间金字塔模型与深度学习相结合,提出了一种新的光流方法。这是一种由粗到细的方法。在空间金字塔的每一层,作者训练一个深度神经网络来估计流量,而不是只训练一个深度网络。这种方法对于任意大的运动是有益的,因为每个网络要做的工作较少,并且每个网络上的运动变得较小。与 FlowNet 相比,SPyNet 要简单得多,在模型参数方面要小 96%。此外,对于一些标准基准,SPyNet 比 FlowNet1.0 更准确。

体系结构

图 8 显示了一个三级金字塔网络:

  • d()是将 mn 图像 I 减小到 m/2n/2 的下采样函数
  • u()是重采样光流场的重采样函数
  • w(I,V)用于根据光流场 V 扭曲图像 I
  • { G0,…,GK }是一组经过训练的卷积神经网络
  • v_k 是由 convnet Gk 在第 k 个金字塔级计算的剩余流量

在第 k 个金字塔等级,剩余流量 v_k 由 G_k 使用 I_k1(来自前一个金字塔的上采样流量)和 I_k2 计算,I _ k2 由上采样流量补偿。那么,流量 V_k 可以表示为

修道院{ G0,…GK }被独立地训练以计算残差流 v_k。此外,地面真实残差流 V^_k 是通过减去下采样地面真实流 v^_k 和 u(V_k-1)获得的。如图 6 所示,作者通过最小化剩余流 v_k 上的平均端点误差(EPE)损失来训练网络

表演

个人观点

与 Flownet 1.0 相比,Flownet 2.0 的精度更高的原因是,通过使用堆叠结构和融合网络,网络模型更大。对于堆叠结构,它通过用中间光流扭曲每一层的第二图像,以由粗到细的方式估计大的运动,并计算流更新。因此,这种方法降低了每一级学习任务的难度,为大位移做出了贡献。对于融合网络,作者引入了 FlowNet2-CSS 和 FlowNet2-SD 来分别估计大位移和小位移。然后,融合网络旨在更好地融合从上述两个网络学习到的两种光流,期望提高最终预测光流的整体质量。

从我的角度来看,重复使用特征映射对 FlowNet1.0 和 FlowNet2.0 的良好性能产生了影响。作者将估计流量和输入连接在一起,这些流量和输入在当前层中被上采样为特征映射,从与当前层的上采样输入相同分辨率的前层获得,作为下一个去卷积层的输入,因此这些特征映射可以重复使用,在设计概念上与 DenseNet 有点类似。

SPyNet 也是一个堆叠网络。它也适合通过使用由粗到细的方法来处理大位移,类似于 FlowNet2.0。flownet 2.0 和 SPyNet 的区别在于,SPyNet 比 flownet 2.0 小得多,SPyNet 的每一层都是独立训练的深度网络。SPyNet 的模型参数比 FlowNet 少很多,因为它是直接使用 warping 函数,女修道院不需要学习。

总的来说,FlowNet2.0 的性能最好,而 SPyNet 要轻量得多,参数更少,速度更快,可以在移动终端上使用。

FlowNet:用卷积网络学习光流链接:
https://arxiv.org/pdf/1504.06852 FlowNet 2.0 论文链接:
https://lmb . informatik . uni-freiburg . de/Publications/2017/imk db 17/Paper-FlowNet _ 2 _ 0 _ _ cvpr . pdf
利用空间金字塔网络的光流估计链接:
https://arxiv.org/pdf/1611.00850.pdf

作者:李子云| 编辑:杨| 由 Synced 全球团队本地化:陈翔

一堆训练深度神经网络的技巧和窍门

原文:https://towardsdatascience.com/a-bunch-of-tips-and-tricks-for-training-deep-neural-networks-3ca24c31ddc8?source=collection_archive---------3-----------------------

I took this nice photo in GüvenPark

训练深度神经网络是困难的。它需要知识和经验,以便正确地训练和获得最佳模型。在这篇文章中,我想分享我在训练深度神经网络中所学到的东西。以下提示和技巧可能对您的研究有益,可以帮助您加快网络架构或参数搜索的速度。

哦,让我们开始吧…

①。在开始构建您的网络架构之前,您需要做的第一件事是验证您输入到网络中的数据是否与标签(y)相对应。在密集预测的情况下,请确保地面实况标签(y)被正确编码为标签索引(或一次性编码)。如果没有,培训就没有效果。

2)。决定是使用预先训练好的模型还是从头开始训练你的网络?

  • 如果您的问题域中的数据集与 ImageNet 数据集相似,请对该数据集使用预训练模型。使用最广泛的预训练模型有 VGG 网、雷斯网、丹森网或例外等。有许多层结构,例如,VGG (19 和 16 层),雷斯网(152,101,50 层或更少),DenseNet (201,169 和 121 层)。注意:不要尝试使用更多的层网络来搜索超参数(例如VGG-19、ResNet-152 或 DenseNet-201 层网络,因为其计算成本很高),而是使用更少的层网络(例如 VGG-16、ResNet-50 或 DenseNet-121 层)。选择一个预训练的模型,您认为它可以提供您的超参数的最佳性能(比如 ResNet-50 层)。获得最佳超参数后,只需选择相同但更多的层网(如 ResNet-101 或 ResNet-152 层)来提高精度。
  • 微调几个层或只训练分类器,如果你有一个小数据集,你也可以尝试在你要微调的卷积层后插入 Dropout 层,因为它可以帮助对抗网络中的过度拟合。
  • 如果您的数据集与 ImageNet 数据集不相似,您可以考虑从头开始构建和训练您的网络。

③。在您的网络中始终使用标准化图层。如果你用一个大的批量(比如 10 或更多)来训练网络,使用批量标准化层。否则,如果你用一个小的批量(比方说 1)训练,用实例规范化层代替。请注意,主要作者发现,如果增加批处理大小,批处理标准化会提高性能,而当批处理大小小时,它会降低性能。然而,如果他们使用小的批处理大小,实例规范化会稍微提高性能。或者你也可以尝试分组规范化。

4)。如果你有两个或更多的卷积层(比如李)在同一个输入(比如 F )上操作,那么在一个特征拼接之后使用空间删除。由于这些卷积层对相同的输入进行操作,因此输出特征很可能是相关的。因此,空间丢失会移除那些相关的特征,并防止网络中的过度拟合。:多用于低层而非高层。

SpatialDropout use-case

5)。为了确定你的网络能力,试着用一小部分训练样本来充实你的网络。如果它没有超载,增加你的网络容量。过度拟合后,使用正则化技术,如 L1 、 L2 、辍学或其他技术来对抗过度拟合。

6)。另一个正则化技术是约束或限制你的网络权重。这也有助于防止网络中的梯度爆炸问题,因为权重总是有界的。与在损失函数中惩罚高权重的 L2 正则化相反,该约束直接正则化您的权重。可以在 Keras 中轻松设置权重约束:

7)。从数据中平均减法有时会给出非常差的性能,尤其是从灰度图像中减法(我个人在前景分割领域面临这个问题)。

⑧。总是打乱你的训练数据,训练前的和训练中的,以防你没有从时间数据中获益。这可能有助于提高网络性能。

9)。如果您的问题域与密集预测相关(例如语义分割,我建议您使用扩张残差网络作为预训练模型,因为它针对密集预测进行了优化。

10) 。要捕获对象周围的上下文信息,请使用多尺度要素池模块。这可以进一步帮助提高准确性,这一思想已成功用于语义分割或前景分割。

11)。从损失或准确性计算中剔除无效标签(或模糊区域)(如果有)。这可以帮助你的网络在预测时更加自信。

12)。如果您有高度不平衡数据问题,请在训练期间应用类别权重。换句话说,给稀有类更多的权重,给主要类更少的权重。使用 sklearn 可以轻松计算类别权重。或者尝试使用过采样和欠采样技术对训练集进行重新采样。这也有助于提高你预测的准确性。

13)。选择合适的优化器。有许多流行的自适应优化器,如亚当、阿达格拉德、阿达德尔塔或 RMSprop 等。 SGD+momentum 广泛应用于各种问题域。有两件事需要考虑:F 首先,如果你关心快速收敛,使用 Adam 之类的自适应优化器,但它可能会以某种方式陷入局部最小值,并提供较差的泛化能力(如下图)。第二个*, SGD+momentum 可以实现找到一个全局最小值,但是它依赖于健壮的初始化,并且可能比其他自适应优化器需要更长的时间来收敛(下图)。我推荐你使用 SGD+momentum ,因为它会达到更好的效果。*

This image borrowed from https://arxiv.org/abs/1705.08292

14)。有三个学习率起点(即 1e-1、1e-3 和 1e-6)。如果对预训练模型进行微调,可以考虑小于 1e-3 的低学习率(说 1e-4* )。如果你从头开始训练你的网络,考虑学习率大于或等于 1e-3。你可以试试这些起点,调整一下,看看哪个效果最好,挑那个。还有一件事,你可以考虑通过使用学习率调度器来降低学习率。这也有助于提高网络性能。*

15)。除了随着时间降低学习率的学习率计划表之外,还有另一种方法,如果验证损失在某些时期(说 5* )停止改善,并且如果验证损失在某些时期(说 10 )停止改善,我们可以通过某些因素降低学习率(说 10 )。这可以通过在 Keras 中使用减速板和提前停止轻松完成。*

16)。如果您在密集预测领域工作,如前景分割或语义分割,您应该使用跳过连接,因为最大池操作或步长卷积会丢失对象边界或有用信息。这也可以帮助你的网络容易地学习从特征空间到图像空间的特征映射,并且可以帮助缓解网络中的消失梯度问题。

17)。更多的数据胜过巧妙的算法!总是使用数据增强,如水平翻转,旋转,缩放裁剪等。这有助于大幅提高精确度。

18)。你必须有一个用于训练的高速图形处理器,但这有点昂贵。如果你希望使用免费的云 GPU,我推荐使用 Google Colab 。如果你不知道从哪里开始,可以看看我的上一篇或者尝试各种云 GPU 平台,比如 Floydhub 或者 Paperspace 等等。

19)。在 ReLU 之前使用 Max-pooling 以节省一些计算。因为 ReLU 阈值为零:f(x)=max(0,x)和最大池仅最大激活:f(x)=max(x1,x2,...,xi),所以使用Conv > MaxPool > ReLU而不是Conv > ReLU > MaxPool

例如假设我们有两个来自Conv的激活(即 0.5 和-0.5):

  • 所以MaxPool > ReLU = max(0, max(0.5,-0.5)) = 0.5
  • ReLU > MaxPool = max(max(0,0.5), max(0,-0.5)) = 0.5

看到了吗?这两个操作的输出仍然是0.5。在这种情况下,使用MaxPool > ReLU可以为我们省去一个max操作。

20)。考虑使用深度方向可分离卷积运算,与普通卷积运算相比,该运算速度快,并大大减少了参数数量。

21)。最后但同样重要的是,不要放弃💪。相信自己,你能行!如果你仍然没有达到你所期望的高精度,调整你的超参数、网络架构或训练数据,直到你达到你所期望的精度👏。

最后的话…

如果你喜欢这个帖子,请随意鼓掌或分享给全世界。如果你有任何问题,请在下面留言。你可以在 LinkedIn 上联系我,或者在 Twitter 上关注我。过得愉快🎊。

与艾伦·唐尼关于数据科学的坦诚对话

原文:https://towardsdatascience.com/a-candid-conversation-about-data-science-with-allen-downey-a147d39bc38c?source=collection_archive---------1-----------------------

我们在这里讨论 1)对非技术受众的态度如何影响数据科学家的工作,以及 2)如何定义算法偏差,以及在解决这些问题时需要注意数据科学管道的哪些部分。

Listen to my podcast conversation with Allen Downey, CS professor at Olin College and author of open source textbooks like Think Stats, Think Bayes, Think Complexity, and Think Python.

欢迎来到坦诚的机器学习对话。我是 Ryan Louie,我采访了机器学习从业者,了解他们职业背后的思考。

本周,我和艾伦·唐尼聊天,他是奥林学院的计算机科学教授。他教授贝叶斯统计、数据科学、建模与仿真、复杂性科学和软件系统的本科课程。在课堂之外,他是一名作家和博客作者。他的开源教材系列“Think X”被奥林大学和其他学校的许多班级使用。“Think X”系列试图通过采用计算方法来使科学或工程主题更容易理解,这种方法更倾向于用代码来演示概念,而不是编写数学。他还通过他关于统计学的博客“可能想多了”展示了数据探索,并解释了可能不会写进他的书里的概念

有趣的视角

与艾伦的交谈让我对自己的几个问题有了新的认识。

1.数据科学家如何与非技术受众进行互动?共情在一个数据科学家的工作中是如何发挥作用的?

我读了艾伦写的关于 2016 年选举概率预测的问题陈述的博文。在写这篇评论时,艾伦小心翼翼地避免了他所谓的“统计唠叨”

“我认为统计学作为一个领域受到……这种几乎对立的关系的困扰。“每个人都是白痴,我们知道如何做好事情,但没有人会听我们的,他们不断犯同样的愚蠢错误,我们的工作就是大声斥责他们,”—艾伦·唐尼

受到批评的选举预测是 FiveThirtyEight 和《纽约时报》发布的“结果”,这两家网站使用选举日之前几个月的民意调查统计分析来预测谁将赢得总统大选。

(Image Source) The numbers presented by FiveThirtyEight here represent the probability that a simulation would result in a Hillary or Trump win. Problem #1: People better understand the results if rephrased as “Trump has little less than 1 in 3 chance of winning” if the frequency hypothesis is true. Problem #2: reporting probabilities of victory can be confused with proportions of the vote. Problem #3: presenting numbers with 3 significant digits might be misinterpreted as a false sense of precision.

(Image Source) There’s a convention of showing predictive maps with swing states colored light blue, “Leaning Democrat,” and pink “Leaning Republican”. Problem #4: The results don’t look like the predictions because in the results all the states are either dark red or dark blue. There is no pink in the electoral college. This visual mismatch between forecasts and actual results is a reason for readers to be unhappy.

艾伦的博客帖子没有统计学家素以唠叨著称的语气,他提出的在选举季期间发布不同选举预测模拟的解决方案是有充分理由的,同时也不是对抗性的。他指出了现状可视化遭受的原则性问题,然后解释了为什么选举模型的替代呈现通过避免这些陷阱使预测更容易理解。

“我试图首先表现出同情。我没有说这是因为人们是白痴而出错,它也没有因为提出预测的人犯了严重的错误而出错。它之所以出错,是因为很难(让数据呈现清晰易懂),我们可以做一些事情来帮助解决这个问题。”—艾伦·唐尼

我很欣赏 Allen 意识到在从事统计、设计、工程或数据科学时,傲慢会成为一个问题。从 Allen 的观点来看,这种对待外行人的不良态度的“经典工程师错误”对摆在分析消费者或软件产品用户面前的创作有不利影响。

“同样,我们设计用户界面,利用我们擅长的东西,避免踩上我们不擅长的地雷——数据可视化也是如此,呈现概率也是如此——利用我们的优势,比如我们的视觉系统,它非常擅长快速吸收大量信息,但避免呈现小概率,因为人们无法使用它们。”—艾伦·唐尼

Allen 从用户界面设计方法和实现有效数据可视化所需的思考之间的类比中得到了一些深刻的东西。

  • 对于面向大量观众的可视化来说,测试可视化将如何被解释是非常重要的。用户界面设计的类似物是纸上原型或交互式模型。
  • 用户将试图根据他们的直觉与创作互动。艾伦指出,“我们无法修复人们的直觉。”如果浏览者的直觉导致他们在数据分析中得出错误的结论,这应该是分析的创造者的错误。如果用户的直觉导致他们在软件上按了错误的按钮,设计者有责任让它更容易使用。

我与 Allen 的谈话加深了我对数据科学家对非技术受众的态度如何影响他们工作的理解。他对选举预测读者的态度是宽容的。他把理解概率预测的困难归结为数据消费者可以理解的经历的许多问题。艾伦提出的呈现选举预测模型的解决方案将这些问题作为用户洞察,并将其转化为贯穿其设计的需求。

当然,包容的态度表明,作为数据科学家,我们渴望与任何有兴趣倾听的人分享见解。我希望,如果更多的从业者采取这种态度,数据科学作为一个领域可以向前迈进,打破它和受实践影响的每个人之间的墙。

2.偏见是一个被过度使用的术语,用来描述数据科学家必须小心的许多问题

我用来获取 Allen 对某个主题的意见的一种方法是阅读一段我与其他数据科学从业者交谈时引用的话。一句话警告说,根据有偏差的数据训练的预测模型将模仿我们当前世界中存在的同样的偏差。

“有一种危险是,机器学习模型可能会增加另一层……惰性。因为如果你有一个根据历史训练数据训练的模型,你用这个模型来做关于未来的决策,它会做出与它看到的历史数据一致的决策。因此,如果在训练集中输入歧视的例子,它可能会强化现有的偏见或歧视的例子。如果我们有机器学习模型来做这些决定,这可能会让社会变革变得更加困难。”—麦迪逊·梅

艾伦同意这个非常真实的警告:“当你把一个预测模型放入一个系统时,它会改变这个系统,你需要考虑这会产生什么影响。”在深入研究他是如何将这个想法与自己的工作联系起来之前,他试图通过使用这个词来消除他所看到的多重含义

  1. 输入中的偏差:训练数据的样本不能代表总体——这是总体中有偏差的样本。
  2. 结果偏差 ( “差异影响” ) :预测系统中的错误会对一个非常可识别的群体产生不良后果。

“你输入的统计偏差会在世界上造成不同的影响”——艾伦·唐尼

在我的探索过程中,我发现学术工作在调查抽样偏差和差异影响如何与社交媒体平台上农村和城市用户的案例研究相关联。作者研究了应用于 Twitter 等社交媒体数据的地理位置推断算法中存在的算法偏差。推断社交媒体用户的地理位置很重要,因为大量使用 Twitter 数据的研究和应用需要地理数据;然而,只有大约 2%的 Twitter 数据被明确地理标记,剩下的 98%有待推断。

社交媒体用户中的人口偏见可能会影响地理定位算法的工作效果。更多城市用户相对于农村用户的倾斜导致代表不足的农村阶层的地理位置预测较差。这一结果符合这样一种观点,即输入中的偏差会对可识别的人群产生不同的影响。

事实上,研究的问题是“算法偏差存在吗?”在本案例研究中得到证实。该算法的输入数据显示了明显的人口偏差:与基于美国人口普查的真实人口数字相比,210%的城市用户代表过多,45%的农村用户代表不足。基于文本的地理定位算法通过从“文本(在推文中找到的)中找到某个区域的词汇特征和概念”(例如,运动队、地区方言、城镇名称)中找到模式来工作

(Image Source) The status quo of how geolocation models trained on population-biased input data reveal differential impacts for rural social media users. The authors’ description of the figure: “Text-based geolocation baseline precision by county (percentage of tweets originating from each county correctly geolocated to within 100km of each tweet’s true location).”

两个阶层之间的不平衡——在这个案例研究中是农村和城市——是机器学习实践中经常出现的问题。通常提供的答案是对类进行过采样,以应对输入中的总体偏差。如果农村用户一直被预测为比城市用户更差的程度,你最好收集更多关于农村用户的数据。

论文中提出的其他研究问题— “是由于人口偏差导致的观察偏差”“我们可以通过过采样来修正偏差吗”试图通过调整输入训练数据中城市和农村用户的分布来对抗不公平的预测。他们的发现对我作为数据科学家从业者被告知的建议提出了质疑。通过修正农村人口偏差以与美国人口普查保持一致,该算法的差异影响并未得到解决。用城市和农村用户数量相等的输入数据对算法进行重新训练,并没有产生公平的预测。

老实说,我仍在思考如何理解这一切,以及如何努力防止算法偏差。描绘出导致算法偏差的组成部分很有启发性,我已经在用艾伦对算法偏差的重新表述作为差异影响来更清楚地说明我强调的问题。

阅读算法偏差文献的论文帮助我认识到,我没有意识到识别和纠正有偏差算法的不同影响的细微差别。我接触过的网上资源(此处和此处)确实对数据不平衡的问题做了深入的技术解释;然而,他们很少迫使我批判性地思考阶级失衡如何与伦理问题和数据科学中不同影响的其他原因相关联。

我渴望成为一名工程师,认识到与公平和我的算法的不同影响相关的问题。这些问题往往在团队的待办事项列表中被推到较低的位置,以利于其他任务,如快速部署和增加模型的整体准确性。然而,我认为,通过更多地了解对抗差异影响的各种方法,解决这些重要问题就变得不那么像一门艺术,而更像一门科学。通过更好地理解过采样等方法在修复输入数据中的总体偏差时的优劣,我可以在我的团队中更有效地发表意见,通过系统的工程流程来确定优先级和解决差异影响。

与麦迪逊·梅关于机器学习的坦诚对话

原文:https://towardsdatascience.com/a-candid-conversation-about-machine-learning-with-madison-may-fdfd1dd60b22?source=collection_archive---------5-----------------------

欢迎来到坦诚的机器学习对话。我是 Ryan Louie,我采访了机器学习从业者,了解他们职业背后的思考。

My full conversation with Madison May, a machine learning practitioner and CTO of text/image machine learning startup indico

自 2014 年秋季以来,麦迪逊·梅一直是总部位于波士顿的机器学习初创公司 indico 的首席技术官。在 Madison 在 indico (是的,那是小写的“I”)工作之前,他是一名本科计算机科学学生,就读于奥林学院。对于不熟悉奥林学院社区的读者来说, indico 是学院最成功的创业故事之一。麦迪逊描述他如何与 indico 扯上关系的方式是对他是什么样的人的坦率看法。

Please listen as Madison describes how he got to where he is today — as CTO of machine learning startup indico.

我有幸在 2015 年夏天在 indico 实习,因此我对 indico 作为一家公司以及 Madison 作为 CTO 在其中的角色非常熟悉。我们没有花太多时间就开始进行有意义的讨论,讨论在部署机器学习模型供世界使用时需要的深思熟虑。

现在,我将讨论我们谈话中出现的一些亮点。

1。你如何衡量一个 ML 模型的成功?您如何知道何时部署“足够好”呢?

当我问麦迪逊 indico 如何衡量他们的模型的成功时,他承认这个问题实际上是一个具有挑战性的问题。

“理想情况下,作为一名数据科学家,你希望将事情转化为一种格式,在这种格式中,你有一个可以优化的误差指标或损失。但有时,你得不到训练集,得不到真正的标签,得不到足够多的数据来准确衡量你的表现。”—麦迪逊·梅

“什么?没有真正的验证数据来报告数字吗?”有人可能会惊呼。麦迪逊说,这种情况似乎足以不容忽视。最常见的选择是“吸收并标记更多数据”——该团队已经建立了内部工具来更有效地完成标记图像和文本数据的任务。

但是在现实中,另一种方法是随机引入一个不熟悉项目的团队成员,向他们展示两个模型的输出,并让他们提供一个关于哪个更好的定性评估。这种比较评估是衡量进展的另一种方式。

他说这话的时候我有点喘不过气来。

我认为有几种标准的方法来评估模型的性能。这些是误差度量(或准确度分数,误差的重新表述)和损失。它们来自 Kaggle 主办的数据科学竞赛对不同模型的普遍比较,以及 ML 研究论文中的表格,这些表格详细说明了如何为一些基准数据集设置新的最先进的方法,并与一系列替代方法进行比较。使用定性比较来评估哪个模型表现更好并不是这种常见做法的一部分。

I took this screenshot from an active data science competition hosted on Kaggle.com. The competition is an image classification task for different species of fish — and every competitor is being accessed by the Multiclass Loss of the training dataset. See, now there’s a quantitative measure by which to rank competitors.

然而,当我开始思考这个问题时,我意识到在某些情况下,定性评估是必要的,或者作为一种呈现结果的方式可能更自然。作为一个例子,我在 indico 的 frontpage 上找到了一个服装相似性应用程序的演示用例,它依赖于 indico 的图像特征产品。

In this clothing similarity example, a machine learning model finds which photos in a clothing dataset looks most similar to a query image, highlighted by the purple box. (Screenshot taken from the “Clothing Similarity” example on https://indico.io)

一个定性的演示告诉我很多关于图像功能产品背后的力量。相似的颜色、剪裁和图案都是产品似乎要捕捉的维度。作为一个用户,看到例子的多样性有助于我判断在寻找相似性的过程中幕后发生了什么。

我可以想象用一种更严格、更量化的方式来建立服装相似性。将时尚相似性功能与业务指标联系起来——如果发布服装相似性功能有助于客户发现他们在其他情况下不会发现的相似风格的服装,并且购买量增加,这是应该部署该产品的良好量化证据。我认为这是许多网站在推出新功能时会做的事情——他们会使用 A/B 测试功能的方法,衡量包含该功能的效果,并评估这一新功能是否有利于更多用户参与或购买。

但我不得不再次提出,进入 A/B 测试新算法产品的阶段需要一些初步验证——该算法实际上完成了寻找服装视觉相似性的基本任务。我认为,可视化的、定性的演示对于传达可视化匹配是否如预期的那样工作是必要的。我们可以为每一件商品(如印花、深色、过膝连衣裙)创建手工标签,并计算在相似性搜索中检索到多少课堂内外的例子。虽然我认为这是一种明确的方式,但我不知道这比让几个熟悉时尚的同事评估模型是否做出足够合理的预测来部署更有价值。

不管怎样,Madison 分享了一个令人惊讶的轶事,帮助我理解了定性模型评估的一些局限性。最近的一个“机器学习出错”的故事警告数据科学家,在你通过机器学习算法解决任务之前,要评估一项任务是否是人类可以解决的。

Listen to Madison talk about his humorous story of machine learning gone wrong. Thankfully, the mistake was caught and the model prevented from deploying!

在这项任务中,麦迪逊和他的团队试图从一段文字中预测性格类型。只有几个标记的示例将文本映射到 16 种 Myer-Brigg 的人格类型,通过正常的错误度量进行评估本来就很困难(即,对于特定个人创作的更多作品,经过训练的模型是否预测了相同的 Myer-Brigg 的人格类型?)

当 Madison 求助于“引入一名团队成员,向他们展示两种模型的输出,并让他们提供一个关于哪一种更好的定性评估时,他发现人类对这项任务的定性反馈并不是成功的可靠衡量标准。

当显示两个模型之间的比较时,

  1. 一个复杂的自然语言处理模型,在数据集上将段落映射到 Myer-Brigg 的性格类型
  2. 随机输出 16 种迈尔-布里格性格类型之一的模型

该团队成员对随机模型竖起了“大拇指”,表示该产品已经可以交付给客户了!如果随机输出对于人类来说是不可区分的,那么人类的评估肯定不能被用来决定一个模型是否成功。

2。你认为你的机器学习研发会出什么问题?

“indico 很久以前就表明了立场(当时我们正在讨论我们现在和未来可以建设什么)。我们放弃了根据文字预测人口统计信息的想法,比如年龄、性别和种族背景。这种类型的信息通常用于定向广告,因此即使没有提供直接的标签,我们也有社交媒体领域的人对这些信息感兴趣。我们……决定这不是我们想要跨越的一条线——我们不想产生一种可能导致歧视的算法。”—麦迪逊·梅

如果我只是想听听麦迪逊作为一名实践数据科学家是如何表现出深思熟虑的,那么这句话就能满足我的需求。在很多层面上,它都是令人放松、鼓舞和美妙的。但我将进一步解释为什么这个故事支持了我的信念,即 indico 团队具有伟大的道德。

算法可能具有歧视性,并对他人产生完全不同的影响。

我认为首先要说的是,indico 的工程师承认算法可能具有歧视性,并将其视为一个问题。

并非每个人都持有反对算法偏见的坚定立场。反驳这一点的讨论点往往会落入这些可预测的模式中,正如算法公平博文《种族主义算法》和习得性无助所强调的。

  • 算法不可能有偏见或种族主义,因为它们从根本上是中立的,它们不知道什么是种族主义。
  • 算法只在历史上的歧视性数据上训练,它们从我们固有的种族主义世界的数据中学习。

有很多保护算法的无助位置,其目的是不要成为种族主义者。然而,人们并没有充分关注这样一个事实,即无论歧视的意图来自哪里,算法应用所产生的“不同影响”(一个实际的法律术语与艾伦·唐尼用来描述算法偏差的影响非常接近)才是问题所在。最后一层问题是“放大”效应,当一种算法被部署在广泛触及如此多类型的人的系统上时,就会出现这种效应。

“即使‘一个算法所做的一切’是反映和传递社会固有的偏见,它也在比你友好的邻居种族主义者更大的范围内放大和延续这些偏见。这是更大的问题。”— Suresh Venkat ,算法公平的作者

使用人口统计学作为预测特征的系统坐在一个道德滑坡上。

对于创建自动决策系统的数据科学家来说,使用人口统计信息作为预测特征可能是一个潜在的问题。我对艾伦·唐尼的采访实际上深入探讨了这个话题。

“当你做预测时,很多时候,出于道德原因,有些因素你不应该包括在内,尽管它们可能会使预测更好。如果你试图做出好的预测——关于人——你几乎总是会发现,如果你包括种族、宗教、年龄、性别……它们几乎总是会让你的预测更好……你的准确率会上升。但在很多情况下,比如刑事司法,我们会故意决定排除相关信息,因为使用这些信息是不道德的……作为一个社会,我们已经决定不包括这些信息。”—艾伦·唐尼

I cut to the conversation with Allen Downey where we discuss factors that should not be included, for ethical reasons, in a model. When making predictions about people, these factors include race, religion, gender, age — all sorts of demographic information.

我很欣赏 indico——尽管他们的位置离使用人口统计信息进行预测的过程只有一步之遥——很清楚他们的预测 API 可以发现自己是更大管道的一部分,而确实使用 人口统计信息进行预测。

设计师、工程师、数据科学家——你们是技术关键持有者,可以决定技术的使用和误用

有了一个可以从用户的社交媒体档案或文本中推断人口统计信息的工具,广告商就可以利用这些特征来驱动他们的模型。不开发这个工具将会把人口统计学排除在广告商使用的算法之外。

我在 indico 决定不开发人口统计文本预测 API 和消息服务 Whatsapp 决定加密所有消息之间看到了哲学上的相似之处,结果是任何有兴趣窃听对话的政府都不可能这样做。

I draw a parallel, in response to indico’s refusal to build an inherently discriminatory algorithm based on demographic information, with how messaging service Whatsapp uses their development powers to express their view that all users deserve privacy.

“我们是技术关键持有者,我们想明确地说,‘我们不想公开那些特性。我们不想让它们被滥用。(这是我们的)决定,不要建造可能被用于那种用途的东西。”—瑞安·路易

我想请挑剔的读者想出更多的例子,即使是在数据科学领域之外,在这个领域中,由工程师的道德来决定世界上应该建立什么和不应该建立什么。对于不仅仅是数据科学家的设计师和工程师来说,在决定什么是道德的方面有着丰富的智慧。下面是一个链接,从伦理的角度讲述了值得努力的事情。

[## 道德和支付租金

不可避免的是,当我提起设计师职业道德的话题时,有人会带着“那是……

deardesignstudent.com](https://deardesignstudent.com/ethics-and-paying-rent-86e972ce9015)

阿姆斯特丹住宅的地图探索

原文:https://towardsdatascience.com/a-cartographic-exploration-of-housing-in-amsterdam-aa2573be41eb?source=collection_archive---------14-----------------------

上周,我花了一些时间研究我从网上获得的房价数据,并在这个系列的第一篇文章中得到了一些非常好的反馈。我收到的最常见的请求之一是给这些数字中的故事添加一些背景。如果用我们都熟悉的术语来表述,就更容易理解了,所以在地图上标出我的发现似乎是合理的下一步。

制作地图

这就是阿姆斯特丹市的样子,如果你把除了邮政编码之间的界限之外的一切都剥开的话:

市政府做得非常好,为各种各样的用例提供了这样的公开数据。如果你好奇,我强烈推荐去看看他们能提供什么。将你在他们网站上找到的数据与一些更熟悉的谷歌地图结合起来,会产生一幅更清晰的画面:

地理编码

有一些免费的方法可以将地址转换成纬度和经度。我的首选方法是使用 R 和 Google Maps API,它们免费提供给像我这样的爱好者。你每天只能编码 2500 个地址,否则就要付出代价了。幸运的是,我们的数据只有 1800 行——没问题。这就是我们的房子在地图上的样子。

它看起来并不特别令人兴奋,所以让我们通过询问价格来着色,作为简单的第一步:

这并没有告诉我们太多,因为整个城市的房子都很贵。我们可以看到,在冯德尔公园附近的市中心可能会有一些非常昂贵的房子,但除此之外,我们真的没有看到任何重大的主题出现。如果我们看看每个人最喜欢的指标— 价格/平方米— 看看是否有更清晰的画面出现,会发生什么?

有趣的是,同样一群非常昂贵的房子再次出现,但这次我们看到市中心的大片区域也变得更加明亮。这些住宅大多位于老城区的中环,以及离冯德尔公园最近的地方。这是有道理的,因为城市中更令人向往和更有历史意义的部分,无论大小,购买起来都会更贵。

但是这种每平方米价格的差异能解释我们的亮点和镇上其他地方的差异吗?也许另一个原因是这些房子的面积更大?我们通过标绘每处房产的房间数量来找出答案。我们再次看到了同一个亮点,就在冯德尔公园的南边:

从这三幅图中我们可以得出结论,城市的昂贵部分也是我们发现最大的房屋(按房间数)和每平方米最高标价的地方。它还强调了为什么我们选择使用房间的大小和数量来预测我们模型中的价格。太棒了。

系数

我们关心系数,因为它们告诉我们预测者和价格之间的关系。我们已经知道价格随地理位置而变化,所以让我们在我们的模型中画出地理位置的变化。混合效应模型为我们提供了每个邮政编码的不同估计值,因此我们可以对邻近地区进行相互比较。对于每一个,我们得到固定效应和随机效应的混合,得到我们的模型系数(b1、b2 和截距)如下:

价格= b1 *平方米+B2 *房间+截距

首先,让我们看看每平方米价格的系数(b1):

与我们之前看到的点状图一致,看起来 1075 和 1071 邮政编码是阿姆斯特丹最贵的地区。镇上这一带的房子令人印象深刻,而且非常昂贵。同样,约旦和哈勒默布尔特的面积每平方米也很贵。这是明信片照片拍摄的地方,弯曲的老房子排列在运河两岸。城镇的郊区描绘了一幅不同的画面,最低的价格出现在 zuidoost 和 noord 地区。镇上的这些地方比较新,游客较少,因此价格也更实惠。

然而,在考察额外房间(b2)的价值时,我们看到了一个有趣的模式:

房间数量的增加会导致房屋成本的增加,但这只是在某些地方。我们之前看到的同样昂贵的邮政编码实际上对于房间变量有一个负(绿色)系数。在其他条件不变的情况下,一个额外的房间似乎会降低这些地区的房屋价值

为什么会这样?一种可能的解释是,城市的昂贵地段被高档人士占据,而这些高档人士更喜欢在他们的家中拥有更大、更高档的房间。想象两个相同的 200 平方米的房产,一个有 7 个房间,一个有 8 个房间。根据定义,有 8 个房间的酒店必须有较小的房间。对这些地区来说,越大似乎越好。

另一方面,市中心亮起了黄橙色的灯光,在这里,给一栋 100 平方米的房子增加一个额外的房间可能会使其挂牌价格增加多达 4 万欧元。这可能有很多原因,但我认为这可能是由于旅游业。城市的这一部分是每个游客都想去的地方,而找到安置这些人的地方是很昂贵的。也许能在一个小空间里容纳很多人是件好事?

在考虑房间数量和增加的平方米空间的价值后,截距就是我们加到最后得到的总标价。当它是正数时,我们可以假设任何大小的房子对一个潜在的买家来说都是有价值的。相反,负截距意味着价格/平方米和房间必须抵消足以弥补它。在这种情况下,我们看到城市的边缘都有大约 10 万欧元或以上的截距。这弥补了模型估计的每平方米价值要低得多的事实。

另一方面,城市的昂贵部分有负截距。为了克服这一点,房子必须更大,并有更高的平方米系数。这与我们之前绘制房屋图时看到的一致。

关于模型性能的说明:

在上一篇文章中,我们建立了不同变量之间的关系,并开始对阿姆斯特丹的住房状况有了更全面的了解。

我们已经可以说明不同的社区如何可以获得非常不同的价格,并表明它是房子的大小和地理位置的函数。这个项目中使用的混合效果模型非常有用,因为它们允许我们的模型在接近现实的方式上具有灵活性。凭借他们的设计,我们可以在每个邮政编码中获得量身定制的估计,同时仍然可以建立一个模型来解释我们在整个城市中的信息。

为了说明这一点,我生成了一些图表,根据它们在预测中产生的误差量进行了颜色编码。回想一下,普通最小二乘法 (OLS)模型没有考虑任何关于住宅位置(邮政编码)的信息,并且假设大小和房间的重要性在整个城市是一致的。我们知道这是一个天真的假设,我们可以看到模型的表现有多差。平均绝对百分比误差(MAPE)到处都是,从大约 10%到超过 130%不等。

Gray areas indicate zip codes where MAPE exceeds 50%

很明显,该模型已经学会将其预测建立在它所看到的大部分房屋的基础上,这些房屋大多位于市中心。这最终真的损害了它对城镇边缘房屋的预测的可靠性。没有阴影的区域不在我们的数据中,所以我们不能估计它们的误差。

然而,如果我们假设每一个邻域都是不同的,并允许模型有一点弹性,它会对自己的预测更有信心。当我们以与之前相同的方式绘制误差时,模型的改进是显而易见的:

值得一提的是,这些模型都不是为了预测目的,也没有针对维持集进行验证。因此,它们更适合分析系数,而不是进行预测或预报。任何对建立这样一个模型感兴趣的人都应该根据地面事实对其进行适当的交叉验证。然而,我认为这是这种方法的灵活性和可解释性的一个有趣的例子。

展望未来:

我不太确定接下来该何去何从。我肯定会继续在阿姆斯特丹寻找一个家。我爱这座城市,也爱住在这里的人们。挑战仍然是找到这里房产的实际销售价格。在此之前,我可能会继续向模型中添加一些其他公开可用的数据,以尝试提高性能。_(ツ)_/

目前,我已经将我的 scraper 代码的大部分放在了一个 github 库中,供任何好奇的人自己尝试。很丑,但是很管用。这篇文章还涉及了相当多的 r 处理和绘图工作。如果我有时间让这些脚本更易读的话,我会试着把它们也放在那里。

学者成为数据科学家的案例

原文:https://towardsdatascience.com/a-case-for-academics-becoming-data-scientists-821e83ea1284?source=collection_archive---------14-----------------------

今年早些时候,我离开了学术界,仅仅过了一个周末,我就从终身助理教授变成了一名数据科学家。不,那不是因为我讨厌学术界。我喜欢它,并在那种环境中茁壮成长。我职业的改变是由于在两个国家之间的移动。像几个已经完成或想要完成这一转变的人一样,我也有疑问。我很担心。Medium 和 LinkedIn 福音书宣称“学者还没有为行业做好准备”或“我不会为数据科学职位雇用学者,原因如下”这让我既愤怒又害怕(相信我,有几篇这样的帖子!).

然而,在成为软件行业的数据科学家几个月后,我实际上得出了一个不同的结论。

I think academics actually fit well in the industry!

是的,我说的是学术界人士(即在学术界工作的人。不是学生)正好可以“融入”行业工作。由于有太多对学者及其技能的曲解(通常来自从未做过学者的人),我想我应该提出一些观点,说明为什么我认为学者很容易适合行业数据科学职位。这篇文章就是关于这个的。

在我开始之前,有三个免责声明:

  • 我的观察是专门针对来自科学和工程背景的学者的,他们精通计算机编程,通常要么刚刚完成博士学位,要么在他们的博士后职业生涯中(博士后、助理教授及以上)希望转向软件/技术行业的数据科学工作。
  • 我说的是一种可能性——所以,我并不是在宣扬所有的学者都应该被雇佣,因为他们自动适合。
  • 我写的不是一份经过充分研究的报告。我正在写下星期五晚上我的想法。

让我从陈述显而易见的事情开始。学术界和工业界是有区别的我将选择与我的帖子最相关的两个:

  • 工业界所做的研究专注于开发一个可以被其他人部署和使用的解决方案,然后数据科学家继续解决下一个问题。在学术界,我们通常会花几个月甚至几年的时间来逐步优化同一个问题,并创造出越来越多新颖的解决方案。也就是说,关注点和激励结构是不同的——这并不意味着那些做增量优化的人不能为未来的产品做快速的原型开发或者为整个项目生命周期做贡献。
  • 良好的工程实践、编写干净的代码、林挺代码、版本控制等在学术环境中并不被重视。然而,这也取决于教授/研究小组负责人,我认为这正在发生变化(至少在我密切关注的研究领域——NLP、机器学习等)。例如,看看 Allen NLP 团队关于如何按照良好实践编写研究代码的这个演示。此外,我认为如果一个人在其他方面技术上适合某个角色,这些是很容易获得的。

(好吧,还有很多其他的差异,比如钱。但我必须在某个地方停下来)。

在我看来,这些都不是不可逾越的分歧。他们存在只是因为他们是两种不同的职业。这不像从外科医生变成房地产顾问。这就像在 It 工作的不同领域之间移动(举个极端的例子,从银行业到消费电子)。人类是地球上适应性最强的生物。如果我们愿意在人工智能(AGI)上下赌注,而不愿意面试一位自己申请了一个行业职位的学者——那我们的大脑肯定有线路功能障碍。在简历筛选或面试后,你可能会认为学术简历不合适,但我们看到的 90%的非学术简历也是如此!如果 100 个人申请一份工作,其中可能有 10 个学者。假设我们最终做了一个 15 人的电话筛选(仍然很多)。这意味着,有太多的非学术简历不符合了!

我认为学术界非常适合这个行业的三个原因:

  • 快速学习新的概念/想法并适应它:学术研究(不管是好是坏)只奖励站在前沿的人。如果一个新的想法出现了,在下一次大型会议/杂志上就会有 100 个跟进的想法出现。这就是他们的运作方式。因此,如果你是一名学者,你必须在很少或没有监督的情况下快速学习和开展工作。本质上,你被训练快速学习新东西。这在进行快速原型制作、从一个问题转移到另一个问题、比较和评估技术状态以及开发满足需求的解决方案的行业中非常方便。
  • 组织和时间管理:博士主要是一项孤独的练习。获得博士学位后,在学术工作中,你通常会在多个项目之间周旋,而且很多时候,会有多项教学任务。你在工作中可以做许多不同类型的活动(见 Philip Guo 关于这个话题的精彩文章)。这会让你在时间管理上变得有条理和有效率。因此,即使你从未听说过 trello 或敏捷或 scrum 或其他什么,你也可能需要 1-2 个小时来理解并转向这些东西!
  • 领导力:通常情况下,如果你是博士后,你将不得不自己做很多事情,同时,你可能会被要求指导年轻的学生,教学,寻求资金等。如果你是一名助理教授,你可以做所有这些事情,但是可能会有更多的自主权。作为一名独立的学术研究者(在美国,我就是其中之一)就像维持一个小规模的创业公司。你应该寻找资金,完成工作,雇佣研究助理,指导学生,建立团队等等。如果你还在读博后的前 5 年,研究管理和行政职责不会完全吞噬你。所以,你还是要做很多实际工作。当你开始在这个行业工作时,所有这些基本上使你已经是一个有经验的工人了。所有这些领导技能也会转移。如果所有这些工作描述对你来说听起来不可思议,那么请看这篇关于教授工作生活的文章,以及他的关于成为教授的经济学的文章,作者是菲利普·郭。因此,一名被聘为数据科学家的学者甚至在加入之前就已经超越了“初级”角色!

福音书作者认为学术不适合的典型原因(以及为什么我认为这只是自信的无知):

  • 声明:他们不知道现实世界在发生什么(我的评论:学者如果不跟随外界,真的无法在学术界生存!)
  • 声称:他们没有任何实践经验(我的评论:正如我之前提到的,大多数博士后学者在日常生活中做大量的实践工作+其他“高级”工作,如指导、管理、规划等。所以,正如我之前提到的,如果你雇佣了一个学者,你实际上得到了一个奖金!)
  • 声称:他们不知道如何遵循良好的软件工程实践(我的评论:这不是火箭科学!如果他们还不知道,他们将在工作中获得知识!)
  • 声明:他们倾向于花数年时间解决同一个问题(我的评论:这是他们的工作性质,不是他们的天性!!)
  • 声称:聪明人就是进不了学术界。他们“工作”。(我的评论:嗯,实际上我认为转行后我找到了更好的工作生活平衡)。

所以,我认为有很多错误的信息在传播——一个相当聪明、勤奋、有组织、努力工作的学者没什么好担心的,只要他们不失去自信并愿意适应。我相信这是数据科学工作的好时机,尽管有这些反对者,但学者可以成为软件工程团队中优秀的数据科学家。

当然,该说的都说了,该做的都做了——我说的只有在以下情况下才成立:

  • 这位学者以一种潜在的面试官能很快理解的方式展示自己
  • 这位学者确实符合这项工作的要求
  • 他们愿意随着工作的性质而改变
  • 他们一般都有成功的欲望。

在过去的几个月里,我喜欢我正在做的工作,以及工作环境。我试图让自己融入当地的数据科学家和研究人员社区,并开始为更多初级数据科学家提供指导。我确实怀念教学、学术研究的乐趣以及从事跨学科项目的工作。但到目前为止,我喜欢做一名数据科学家。

更新:我没有提到另一个重要因素——一个好的雇主和他们提供的工作环境。我不应该错过它——但是,正如 LinkedIn 评论中正确指出的那样,它在我迅速适应行业和对成为数据科学家的总体积极感觉中发挥了重要作用!

由于这篇文章已经很长了,我不想触及我认为学者在申请数据科学家职位和准备面试时需要做的工作(想起来了,任何人!不仅仅是学术!),有哪些属于“数据科学家”头衔的工作等等。我会试着写一篇关于这个的文章。感谢你能活到现在!

LightGBM 的案例

原文:https://towardsdatascience.com/a-case-for-lightgbm-2d05a53c589c?source=collection_archive---------2-----------------------

Microsoft’s Distributed Machine Learning Toolkit

正如任何活跃的 Kaggler 所知,梯度推进算法,特别是 XGBoost,主导着竞赛排行榜。然而,在 2016 年 10 月,微软的 DMTK 团队开源了它的 LightGBM 算法(附带 Python 和 R 库),它肯定会占据优势。因此,社区已经开始比较鲜为人知的 LightGBM 和 XGBoost 的性能。

在这篇文章中,我认为提及我使用 LightGBM 而不是 XGBoost 的情况以及我在它们之间经历的一些权衡是有价值的。

使用

我对这两种算法的使用都是通过它们的 Python、Scikit-Learn 包装器。我通常选择使用算法的 Scikit-Learn 包装器,因为它创建了一个在相同数据上实现和评估各种算法的标准。它还允许通过 Scikit 创建预处理管道,然后可以通过多种算法轻松应用该管道。

除了每个平台的特定超参数之外,这两种算法的实现几乎完全相同。但是,任何熟悉典型 SKLearn 流程的人都可以使用 LightGBM。

装置

安装 LightGBM 的 CPU 版本轻而易举,可以通过 pip 安装。我希望我可以说,GPU 版本是轻而易举的,但可悲的是,还有更多额外的步骤要采取。您必须安装 Cuda、Boost、CMake、MS Build 或 Visual Studio 和 MinGW。在路径中添加了一些东西之后,我很幸运能够通过运行以下命令来安装 GPU 实现:

pip 安装灯 GBM-install-option =-GPU

速度

对我来说,这是 LightGBM 真正闪耀的地方。使用默认参数,我发现我的 XGBoost 基线通常会超过 LightGBM,但是 LightGBM 运行的速度非常快。它已经针对最大并行化运行进行了优化,这意味着它在 CPU 和 GPU 上都可以真正运行。

在优化模型时,这种加速允许更快的超参数搜索。对我来说,这就是 LightGBM 如此强大的原因。它允许开发人员在更短的时间内随机/网格搜索参数范围,与在相同时间段内使用 XGBoost 相比,允许测试更多可能的组合。这种速度还允许添加交叉验证测试,以获得更准确的模型泛化度量。我相信,快速优化的能力在很大程度上超过了默认性能的权衡。

如果你对阅读更多关于 LightGBM 的性能感兴趣, Laurae 有一篇很棒的深度文章将它与 XGBoost 进行了比较。

分类特征支持

使用 LightGBM 的另一个好处是它通过指定列而不是使用一键编码(OHE)来支持分类特性。OHE 可能很重,因为它可以显著增加数据集的维度,这取决于类别+选项的数量。在微软的结果中,他们看到了高达 8 倍的训练速度提升。这个特性使它更适合 GPU 训练,因为它利用了更有效的方法来处理分类数据。这种支持最酷的部分可能是它有一个自动模式来检测 Pandas 数据帧中指定的分类列,大大减少了转换数据所需的预处理量。

包装东西

随着梯度推进算法越来越受欢迎(由 Kaggle 社区提供),我认为与鲜为人知的库分享一些见解是有价值的。我相信在某些情况下,它对开发人员来说比其他库有着巨大的潜力,并建议每个数据科学家下次开始 ML 项目时都尝试一下。

p 值的问题是

原文:https://towardsdatascience.com/a-case-study-of-the-p-value-f0d708861334?source=collection_archive---------3-----------------------

http://1.bp.blogspot.com/-m1ucuiGYiw0/UNaULkQ0IYI/AAAAAAAAARk/OTDIBDI7Ydo/s1600/photo+(2).JPG

像大多数人一样,我曾经认为统计学是我应该尽量避免的一种瘟疫。然而,我作为一名医学研究人员的时间改变了我的观点,因为我意识到准确的统计数据在做出可靠和可重复的结论时是多么重要。幸运的是,我接触了一位教授,他改变了我对 p 值的看法。他这样做是向我展示了它是如何误导人的,我希望与你分享。

让我们考虑一下学生的 t 检验,这是一个决定两组数据是否不同的程序。例如,一家公司可能想知道他们的产品是男性还是女性购买的多,一位医生想知道他们的病人在接受治疗后是否改善了症状,或者一群朋友正在计划他们的下一次度假,并想知道纽约市或旧金山的酒店价格是否更高。

让我们考虑一下最后一个例子。我们的假设酒店价格和我们去的城市有关系。我们的无效假设是酒店的价格和它所在的城市没有关系。假设该数据遵循正态分布,让我们模拟一些数据。我们假设四个最好的朋友统计了旧金山 100 家酒店的每晚价格,发现平均价格为 100 美元,变动幅度为+/-25 美元(n=100,u=100,sd=25)。

这四个朋友在直方图中绘制了结果分布,并覆盖了密度图。请注意,每位朋友都观察到了不同的酒店价格分布,这取决于他们查看的酒店。也许朋友 2 的品味更昂贵,而朋友 4 更节俭。然而,当我们比较两个分布时,考虑这对 p 值意味着什么是很重要的?

假设这四个最好的朋友对纽约市的酒店重复了这一过程,并试图通过完成 t 检验来确定哪个城市的酒店更贵。有两种情况会发生。案例 1:两个城市的酒店价格不同或者案例 2:没有区别。

对于案例 1,假设朋友们收集了纽约 100 家酒店的数据,发现他们平均每晚花费 80 美元,标准差为 25 美元。完成学生的 t 检验并计算 p 值,朋友们比较他们的发现。

考虑到他们极小的 p 值,四个朋友都认为纽约 酒店比旧金山便宜。重要的是,所有四个朋友根据他们收集的数据得到了不同的 p 值。假设这些朋友真的很受欢迎,并且有 500 个额外的朋友计划加入他们的旅行。

如果他们都完成了这个分析并记录了他们的 p 值,我们可以预期在左边看到的 p 值分布。尽管我们通常会得到低于 0.05 阈值的 p 值,但也有朋友得到高于 0.05 的 p 值的时候。在这种情况下,这位朋友会得出结论,酒店价格之间没有差异,即使有差异。令人震惊!

更令人担忧的是,让我们来看看案例 2 ,数据显示纽约和旧金山的酒店价格没有差别

在这里,四个朋友中有三个会认为酒店价格没有差别。然而,第四个朋友得到的 p 值低于 0.05,他会认为有差别,尽管实际上没有差别。谁知道呢?也许这会引起一场大的争吵,他们也不会再是朋友了…这真让人难过。

在这三个朋友与第四个朋友解除好友关系之前,他们决定咨询另外 500 个朋友,比较他们的 p 值。

他们震惊地发现,当酒店价格没有差异时, p 值实际上是随机的!虽然大多数朋友会得出相同的结论,但有一组人会得出结论认为存在差异……尽管实际上并没有差异。

回想一下,p 值的正确解释是

假设空值为真,p 值量化了在当前观察点或超出当前观察点看到数据点的概率

基本上,您可以计算出您预期数据位置的 95%置信区间。如果您观察到一个超出这些界限的值,这是意料之外的,因为它在数据的最大 5%之内,并且支持您的零假设。如果您希望对变化更加宽容,您可以计算 97.5%的置信区间,并且只允许 p 值为 0.025 的观察值不同意您的假设。对抗变化无常的 p 值的最好方法是增加你重复的次数,看看你的 p 值是上下波动还是一直保持在低位。这里我编写了一个交互式可视化程序,允许您更改两个分布的参数,并查看最终的 p 值分布。如果你想阅读更多,我推荐这篇论文。重新生成它的代码可以在这个库中找到。

https://pixabay.com/en/crowd-lego-staff-choice-selector-1699137/

基于人口普查的贫困指数

原文:https://towardsdatascience.com/a-census-based-deprivation-index-using-r-7aa738da697c?source=collection_archive---------9-----------------------

Area deprivation scores at the county-level. Brighter colors represent higher deprivation relative to all counties in the U.S.

你住在哪里对你的健康有重大影响;更具体地说,生活在贫困地区的人健康状况更差。因此,剥夺指数经常用于健康研究。为了估计邻里层面的剥夺,大多数研究人员依赖于人口普查数据,但是,收集和清理这样的数据需要相当多的时间和精力。在这里,我展示了一个 R 函数,它收集数据并不费吹灰之力就创建了一个标准化的贫困指数。

要运行这个功能,你需要tidysensus和 psych 软件包。所有代码都发布在 GitHub 中。

工作原理

该指数是基于刀子乐队和他的同事们的方法论。简而言之,他们发现从八个特定变量中提取的主成分最能代表邻里层面的剥夺。按照他们的方法,普查区一级需要以下变量:

不到 HS 学位的百分比(25 岁及以上)

低于贫困线的百分比

有 18 岁以下子女的女户主家庭百分比

%从事管理、科学和艺术职业

拥挤家庭中的百分比(每个房间超过 1 人)

%有公共援助或食品券

失业百分比(16-64 岁劳动力)

家庭年收入低于 3 万英镑的百分比

该功能收集普查估计值,转换变量,然后执行主成分分析(PCA)。对于给定的县,在区域级别收集估计值。由于该指数已在以前的研究中得到验证,PCA 仅提取一个成分。

使用函数:countyND()

该函数通过输入参数 StateCounty 来工作。输出变量“PC1”是分析中每个相应人口普查区(ct)的剥夺指数得分。较高的指数分数代表较高的剥夺感。这些分数可以单独使用,也可以导出用于统计模型。

例题

这是纽约州奥农达加县人口普查区的贫困分布情况。

NDI <-countyND("NY","Onondaga")
ggplot(NDI, aes(PC1)) + geom_histogram() + theme_classic()

我通过分类进一步探索剥夺分数的分布。通过根据锡拉丘兹市内外的地理位置对人口普查区进行分类,可以清楚地看出,大多数城区的邻里贫困程度高于县城。

NDI$type[as.numeric(NDI$GEOID) < 36067006104] <- "City Tract"
NDI$type[as.numeric(NDI$GEOID) >= 36067006104] <- "County Tract"

ggplot(NDI, aes(reorder(Tract, -PC1), PC1)) + geom_col(aes(fill = type)) + coord_flip() +
  theme(axis.text.x = element_text(size = 8, color = "black"), 
        axis.text.y = element_text(size = 4, color = "black")) +
  scale_fill_viridis_d(option = "cividis") + 
  labs(fill = "", x = "Tract", y = "Deprivation Index")

专题制图

该指数可通过其空间分布进行进一步研究。绘制剥夺分数图显示,高度剥夺集中在锡拉丘兹市。

然而,仅绘制锡拉丘兹市的剥夺分数,一些变化仍然是显而易见的。

此外,通过省略参数,该函数将返回给定州中所有县的贫困指数。

NYND <- countyND("NY")ggplot(NYND, aes(PC1, color = County)) + geom_density() + 
  theme_classic() +  guides(colour=FALSE) + 
  scale_color_viridis_d() +
  labs(x = "Deprivation Index for all Counties in NYS")

纽约贫困的空间分布:

Neighborhood-level deprivation across New York

所有的代码和更多的例子可以在 GitHub 上找到。我为自己的分析编写了这个函数;但是,也许其他人也会发现它很有用。

单词云的一个世纪

原文:https://towardsdatascience.com/a-century-in-wordclouds-72be5f5ca391?source=collection_archive---------10-----------------------

由于缺乏作为可视化工具的精确性,云受到了 T2 的批评。但是它们看起来很有趣。

接下来是一系列的单词云,分别代表 20 世纪的每一个十年。每个十年的词云中的每个词都在那个十年的某个时候出现在《韦氏词典》或《牛津英语词典》中。

不过,不要让我知道具体是哪一年,因为两本词典在增加单词的时间上有所不同(因为一本反映了美国英语,另一本反映了英国英语)。每个人都可能在一个词进入流通领域后很久才加上这个词。有些词可能在某个特定的十年中出现,不是因为新造的,而是因为获得了新的含义。

我想你会同意,虽然这些词中的大多数以某种方式结合,抓住了特定十年的要点。他们抓住了它的俚语(是的, mook 听起来像 30 年代的 slam),它的重大事件(两次世界大战分别发生在十几岁和四十多岁的年轻人身上),以及它的技术进步(计算机术语甚至在 20 世纪 50 年代就开始出现,并且每十年变得更加流行)。

你还会注意到,很多看起来很现代的词出现的时间比你想象的要早得多(例如,迅猛龙,早在 20 年代就首次出现了)。

滚动愉快。。。

1900

1910

20 世纪 20 年代

20 世纪 30 年代

二十世纪四十年代

制作单词云的注意事项

我想把这些整合到一个 D3.js 可视化中——看着单词从一个 wordcloud 到下一个 word cloud 以 SVG 的形式动态显示会很酷——但是我找不到一个简单的方法来做屏蔽(不用写很多代码)。

我选择使用这个 Python repo ,它很棒,支持遮罩和自定义颜色。(遗憾的是,你不能让它输出 SVG,我可以将 SVG 加载到 D3.js 中,然后嵌入动画等。)

这篇博客文章有助于选择十年看起来合适的颜色(尽管我在这里和那里调整了她的调色板,以使每个十年都不同)。

来自未来的聊天机器人:用 Rasa 构建端到端的对话助手

原文:https://towardsdatascience.com/a-chatbot-from-future-building-an-end-to-end-conversational-assistant-with-rasa-ai-51a1c93dabf2?source=collection_archive---------4-----------------------

Figure1: A Chatbot from future! by rawpixel on Unsplash

Y 你可能已经在我的上一篇文章中看到,我一直在使用 Rasa 构建聊天机器人。你会在 Rasa 上找到很多使用 Rasa APIs 构建聊天机器人的教程。但是我没有发现任何关于这些 API 的细节,不同的 API 参数是什么,这些参数是什么意思等等。在这篇文章中,我不仅会分享如何使用 Rasa 构建聊天机器人,还会讨论使用的 API 以及如何使用 Rasa 模型作为服务从 NodeJS 应用程序进行通信。

什么是 Rasa

Rasa 是一个开源的对话式人工智能框架。我喜欢 Rasa 的一点是,你不必拘泥于预先构建的模型或用例(Dialogflow 等)。).因此,您可以根据您的使用情形对其进行定制,这可以成为一项市场优势。Rasa 不是一个基于规则的框架(如僵尸工具),你不需要像 Dialogflow、Microsoft LUIS 或 Amazon Lex 那样担心将你的数据放在别人的云中。

Rasa 有两个主要组件— Rasa NLU 和 Rasa 核心。

NLU 是自然语言理解者。假设用户说“I want to order a book”。NLU 的工作就是接受这个输入,理解用户的意图并在输入中找到实体。例如,在上面的句子中,意图是订购,实体是图书。Rasa NLU 内部使用Bag-of-Word (BoW)算法寻找意图,使用Conditional Random Field (CRF)寻找实体。尽管您可以使用其他算法通过 Rasa 来查找意图和实体。为此,您必须创建一个自定义管道。关于定制管道的细节超出了本文的范围。如果你有兴趣,可以查看这个链接。

Rasa 核心的工作主要是为聊天机器人生成回复消息。它采用 Rasa NLU ( 意图实体)的输出,并应用机器学习模型来生成回复。我们将在稍后的 API 讨论中讨论更多可能的机器学习模型。

Figure2: Basic steps of Rasa app internally works to reply a message. Reference here.

如上图所示,输入消息由一个Interpreter解释以提取intententity。然后,它被传递给跟踪对话当前状态的TrackerPolicy应用机器学习算法来确定什么应该是回复,并相应地选择ActionAction更新Tracker以反映当前状态。

打造聊天机器人

假设我们正在构建一个客户服务聊天机器人。创建一个名为customer_bot的目录,并在其中创建一个名为data的目录。还要创建一个名为config_spacy.yml的配置文件

$mkdir customer_bot
$cd customer_bot
$mkdir data
$vi config_spacy.yml

将中的config_spacy.yml文件内容复制到此处。在配置文件中,我们指定了用于构建各种模型的管道类型。在这种情况下,我们使用SpacyScikit-learn来构建管道,并且仅支持如下配置中指定的English语言:

language: "en" 
pipeline: "spacy_sklearn"

您可以使用 Rasa 支持的其它管线类型,也可以创建自定义模型管线并在配置中指定它。

建立 NLU 模型

首先,我们需要建立 NLU 模型。拉莎·NLU 使用监督学习模型工作。因此,您需要训练数据来训练 NLU 模型。在训练数据中,我们需要指定该数据的intententity是什么。例如,如果机器人的输入文本是' hi ,您可以将意图定义为' greet '。在这种情况下没有实体。因此,训练数据集如下所示

{        
 "text": "hi",        
 "intent": "greet",        
 "entities": []     
}

你可以使用我的 github 复制粘贴整个训练数据用于代码中。将其命名为data.json并放入data文件夹中。

手动创建这些 trining 数据非常耗时。因此,相反,你可以使用这个网络用户界面来创建数据来训练拉沙 NLU。

现在使用data.jsonconfig_spacy.yml,我们需要训练一个 NLU 模型。创建nlu_model.py并放在customer_bot文件夹下。NLU 模特培训代码如下:

我们可以像下面这样调用上面的train_nlu方法:

if __name__ == '__main__': 
    model_directory = train_nlu('./data/data.json', 'config_spacy.yml', './models/nlu')

让我们看看这是怎么回事。我们正在使用load_data加载训练数据。load_data函数读取训练数据并返回一个TrainingData对象。然后我们使用通过config_spacy.yml传递的配置创建一个Trainer对象。现在使用那个trainer对象,我们实际上可以训练数据来创建一个机器学习模型——在这种情况下,Rasa NLU 模型如图trainer.train(training_data)所示。一旦模型被训练,我们需要将模型保存在一个目录中。我们通过调用Trainer类的persist方法来实现。正如您在上面看到的,在trainer.persist中,我们指定了保存模型的目录,并为我们的模型指定了一个名称— customernlu

既然我们已经训练并保存了模型,我们可以像下面这样运行 NLU 模型:

def run_nlu(model_directory): 
      interpreter = Interpreter.load(model_directory)

建立对话管理模式

对话管理是 Rasa 核心的工作。在构建对话模型之前,我们需要定义我们希望对话如何流动。实质上,我们正在为对话模型创建一组训练示例。我们将创建一个文件stories.md并将其放在data文件夹中。让我们来看看stories.md的一组样本数据。

使用 stories.md 训练对话模型

## story_001
* greet
   - utter_greet
* order_product
   - utter_ask_product_name
* order_product[router=829]
   - slot{"router": "829"}
   - action_order_product
* goodbye
   - utter_goodbye

假设我们想要一个当用户说Hi时开始的对话。我们可以将意图定义为greet。当机器人发现一个greet意图时,它会回复utter_greetutter_greet的内容将在后面的domain文件中定义。

插槽和动作

我们再举一个例子。假设用户说“I want to order an 829 router”。机器人明白这是一个order_product意图,实体是router。实体的值是 829,这意味着有不同产品 ID 的路由器,但是用户只对 829 感兴趣。因此路由器及其值 829 在这里被定义为时隙的一部分slot{“router”: “829”}。插槽本质上是你的机器人的内存,被定义为一个键值对。更多关于插槽的信息可以在这里找到。有时,来自机器人的回复消息不是静态消息。相反,机器人可能需要调用一些服务或执行一些其他计算来创建回复消息的内容。如上文action_order_product所示,这些通过action定义。在action_order_product中实际发生的事情将在actions.py中定义。

这个项目的stories.md文件可以在这里找到。

关于stories数据格式的详细说明是这里的。

定义域

我们将为名为customer_domain.yml的域创建一个yml文件,并将其放在customer_bot目录中。域文件指定了slotsintententitiesactionstemplates(例如在utter_greet对不同话语的示例回复)。这个项目的域文件可以在这里找到。

actions.py

如果您的 bot 的回复消息都是静态消息,您不需要任何操作。但最有可能的情况并非如此。任何真实的机器人应用程序都会与一些其他服务进行通信,或者至少为它的一些回复进行实时计算。在我们的项目中,一旦产品被订购,机器人应该回复一个确认号。对于不同的用户/产品,此确认号码会有所不同。因此,产品订购流程将成为行动的一部分。为了简单起见,在我们当前的代码中,我们显示了一个硬编码的确认号,假设产品订单是成功的。

How to write an action in Rasa

你可以在这里找到这个项目的actions.py文件。

训练对话模型

为了训练对话模型,我们将编写一个函数train_dialogue。该函数需要 3 个参数——域文件、故事文件和训练后保存对话模型的路径。在 Rasa 中,我们使用代理类来训练对话模型。您通过传递domain文件并指定一个policy来创建一个agent对象。政策本质上是模型。例如KerasPolicy内部使用 LSTM 网络。在你的训练数据中记忆对话。根据您使用的 Rasa 核心版本,您可能有不同类型的可用策略。更多关于政策这里。

我们必须使用agent对象的train方法来训练使用stories.md文件。如上图所示,您可以指定epochsbatch_sizevalidation_split。我们将使用agent.persist保存模型。

要运行对话模型,我们需要一个如run_customer_bot方法所示的interpreter对象。解释器做它所说的——解释输入给机器人的文本。凭直觉,您可能会理解,您需要之前创建的NLU model来创建一个interpreter对象。因为 NLU 的工作是解释传入的文本——理解intententity。然后您需要创建一个agent对象,它接受interpreter对象和您刚刚通过train_dialogue方法创建的dialogue model。一旦有了代理对象,就可以使用agent.handle_channel()来运行将进行对话的机器人。在这种情况下,我们使用 Mac 终端作为输入/输出网关,因此我们将ConsoleInputChannel()作为agent.handle_channel的参数传递。Rasa 核心支持一些其他的输入通道或者你可以创建你自己的自定义通道。更多关于interpreter的信息可以在这里找到。

你们中的一些人可能已经注意到dialogue_management_model.py不是图 2 的 100%反映。例如,dialogue_management_model.py中没有使用Tracker对象。这是因为图 2 反映了内部发生的事情,而不一定是您用代码编写的内容。您仍然可以使用tracker功能来了解对话的当前状态。关于追踪器更多的是这里。

怎么跑

本教程是在 MacBook 上完成的。按照 Rasa 文件安装 Rasa NLU 和 Rasa 核心。对于本教程,我使用了 NLU 版本0.12.3和核心版本0.9.0a6

从我的 github 下载完整代码。

创建 NLU 模式

$python nlu_model.py

创建对话模型。注释__main__里面的run_customer_bot()方法。然后运行下面的命令。

$python dialogue_management_model.py

现在取消__main__run_customer_bot()方法的注释,注释掉train_dialogue()方法的。然后再往下面跑。

$python dialogue_management_model.py

现在,您应该已经在终端中运行了 bot。

将模型作为服务使用

一旦您准备好了 NLU 和对话模型,您就可以将 Rasa 核心作为服务器运行,并从服务器应用程序与它通信

$cd customer_bot
$python -m rasa_core.server -d models/dialogue -u models/nlu/default/customernlu/ --debug -o out.log --cors *

Rasa 核心服务器默认运行在端口5005上。假设用户说hello。这个用户输入来自 NodeJS 服务器中的前端到后端。NodeJS 服务器希望与运行在端口5005上的 Rasa 核心服务器通信,并希望从 Rasa bot 获得回复。下面的示例 NodeJS 代码可以做到这一点。

var messageToRasa = 'hello'
request.post(
      '[http://localhost:5005/conversations/default/respond'](http://localhost:5005/conversations/default/respond'),
      { json: { 'query': messageToRasa} },
      function (error, response, body) {
          if (!error && response.statusCode == 200) { //body[0].text is the reply from Rasa
              console.log(body[0].text)
              }
          else{
            console.log(`Error: \n${error}`);
          }
      }
  );

参考:

  1. Justina 关于如何使用 Rasa 构建一个简单聊天机器人的优秀教程
  2. 使用 Rasa 时的一些有趣的提示。
  3. 揭开拉莎·NLU 的神秘面纱。
  4. 条件随机场简介。
  5. 自然语言处理从业者指南这里。
  6. 带插图的 LSTM 指南。
  7. 更多关于 Rasa 核心政策的信息。

处理复杂 ML 问题的清单

原文:https://towardsdatascience.com/a-checklist-for-working-with-complex-ml-problems-3ea729362db0?source=collection_archive---------15-----------------------

很多时候,我们会遇到复杂的机器学习问题,这些问题很难分解为简单的子问题。那些在创业公司工作的人会想到这样一个事实,当我们试图解决如此复杂的用例时,我们经常有从一个实验跳到另一个实验的习惯。

在小队,我们的机器学习团队遇到了类似的挑战。尽管做了初步研究,我们有时会忘记我们的实验和方法。我们认识到,为了避免频繁的错误并在处理复杂的业务问题时保持清晰,我们必须有一个标准的清单。清单应该确保我们在解决任何复杂问题时不会遗漏关键要素。

在这篇博文中,我们将分享一个 三阶段清单 ,它可以用来处理复杂的 ML 问题。每个阶段都有一些检查点,可以帮助系统地解决问题。

第一阶段:问题发现和需求收集

检查点 1:了解业务问题

  1. 了解问题的相关背景。
  2. 第一原理思维技巧 把一个复杂的问题分解成单元问题。
  3. 需要解决什么?
  4. 为什么需要这样做?

检查点 2:探索性数据分析

  1. 将数据转换成有用的格式,以进行过滤、合并和其他数据操作。
  2. 对几个项目进行抽样以了解数据的变化。
  3. 积累所有可能的统计数据,了解数据的特性,例如,数据集中不同类别之间的类别分布重叠、数据偏斜度、名义变量。
  4. 进行数据清理和分析,以消除任何异常值。创建相关的可视化。
  5. 找到一个好的在这里读上EDA

检查点 3:定义目标

  1. 准确定义每个单元问题的目标。
  2. 准备相应的假设、约束和边缘案例。
  3. 列出并确定可接受的指标,如给定问题的错误率/准确度/精确度/召回数。

关卡 4:澄清疑点

  1. 消除相关团队/客户的所有疑虑。
  2. 验证目标、约束、边缘情况、假设和前提。

检查点 5:详尽的文献列表/过去的研究

  1. 阅读博客/文章,熟悉类似的问题和最新发展
  2. 查找在线发表的研究论文和调查论文。
  3. 探索类似问题的 Github 库。

检查点 6:选择有前途的文献

  1. 浏览每一篇文献,仔细阅读引言、建议的工作、图表。
  2. 尝试从高层次理解事物。
  3. 检查研究的目的是否与用例或相关阻碍因素相匹配。
  4. 核实文章是否介绍了现代研究,而不是历史工作。
  5. 直观地验证,如果提出的算法和提到的数据集似乎很好地解决了你的问题。

关卡 7:文学深潜

  1. 深入研究承诺的文献/可用的实现。
  2. 从文献中收集见解:寻找预处理步骤、特征、提议的管道和算法/架构、数据集、超参数、评估标准、其他细微差异、挑战、所用技术的利弊。
  3. 在开始执行之前,阅读 4-5 篇文献,也许可以从 2 篇或更多的文献中为你的实验寻找灵感。
  4. 我们在文学深度挖掘班遵循的一种格式是

Format used for Literature Summary while doing an exercise on literature deep-dive.

检查点 8:设计实验和流水线/算法

  1. 基于各种预处理、特征、分类层和从文献深度挖掘中获得的其他见解的组合,创建潜在方法的列表。
  2. 根据上面的列表为你的目标设计相关的实验。
  3. 过滤掉直觉上没有意义的实验。
  4. 根据 a)简单、直观且易于构建的 常识基线 对其余实验进行排序,b)根据数据集要求、实施和执行时间对实验的投资回报进行排序。

检查点 9:数据集估计和采集

  1. 基于文献调查,我们可以收集相关的公共数据集或要求内部数据集。
  2. 对不同实验所需的训练、验证和测试数据集的估计。
  3. 考虑到数据中的错误/异常值,可能会要求比你需要的多 20-25%的数据。
  4. 为数据集准备所需的模板(如果要由其他部门/客户共享)
  5. 遵循此处的数据验证核对表以避免差距:
  • 注释模板(id、标签、时间等。)
  • 每个类别的训练集的样本数
  • 每个类别验证集的样本数
  • 每个类别测试集的样本数
  • 整个训练/验证和测试集的最小和最大样本,考虑异常值。

6.准备两套:

  • 一个 虚拟集 ,用于在流水线实现过程中快速验证代码片段。
  • 一个 最终设定 为最终实验岗位流水线实现。

第二阶段:实施和实验

检查点 10:执行代码

  1. 为预处理、特征、特征提取器、提取特征的后处理、最终特征向量形状、模型系列、架构、评估方法和度量标准定义不同的步骤。
  2. 为数据集和结果设计输入和输出格式。
  3. 基于 EDA 创建培训、验证和测试集。使用各种采样程序,如平衡集、分层集和其他采样技术。
  4. 设计和评估您的管道,同时考虑所有的边缘情况和限制。
  5. 为再现性和调试在每个步骤实现记录器。
  6. 使用虚拟数据集进行模拟运行,以验证管道的每个部分。捕捉 bug,修复,重新迭代。
  7. 从功能和代码两个角度进行验证。
  8. 一旦一切就绪,就开始实施。
  9. 配置您的系统,以便您可以轻松快速地重复实验。

检查点 11:数据准备

  1. 清理数据并移除异常值。验证此步骤后留下的数据是否足以用于训练和测试。
  2. 了解是否需要平衡数据或不平衡数据。
  3. 为所有父类和子类随机选择数据点。
  4. 形成最终的数据集,好好洗牌。
  5. 拆分数据并创建培训、验证和测试文件。
  6. 如果可能,保存上述文件,可能有助于以后重复实验。
  7. 训练集和验证集应该是测试集的近似副本,并且应该有足够的变化以有助于泛化。
  8. 如果测试集与生产过程中预期的不同,尝试消除选择偏差。
  9. 始终在管道中使用数据 id,即使在提供原始文件的不同排列时,也可以使用数据 id 将数据点特征映射回原始数据点。
  10. 如果使用扩充数据集,请确保验证集和训练集不包含同一数据点基本样本的不同扩充样本,因为这可能会提高验证准确性。

检查点 12:超参数优化

  1. 列出在选定的算法/管道上进行实验时可以改变的参数。
  2. 从博客、文献综述中找到上述参数的最佳值。
  3. 使用参数的默认值运行第一个实验,然后根据结果开始微调,以确定最佳值。
  4. 如果模型经过训练,则分析验证数据的性能。
  5. 如果有巨大的偏差,对超参数进行网格搜索。网格搜索可能会持续一段时间。拿杯咖啡!
  6. 如果你得到了一个相关的模型,进行 K-fold-cross-validation 以确保模型不会过度拟合。
  7. 来自 Andrew NG 在他的 DL 专业化课程 中的一些提示,a)总是在试图平衡训练和验证准确性之前过度拟合模型。b)让训练精度首先膨胀,在第一次迭代中去除漏失/ L2 正则化或任何其他过拟合减少方法。c)在训练任何深度学习模型时,使用模型检查点学习速率衰减提前停止
  8. 此外,找到一个关于从深度学习专业化课程中学到的经验教训的博客。

检查点 13:定量和定性分析

  1. 我们应该分配足够的时间来分析实验。
  2. 检查在测试集上获得的模型的定性和定量结果。
  3. 如果在测试集上表现不好,就找原因。a)可能测试数据与预期完全不同。b)可能测试数据中存在噪声。c)可能需要处理测试集。d)可能评价方法存在根本性错误。e)可能模型有问题。
  4. 如果在先前实验的结果之后需要迭代,那么对实验失败的可能原因进行批判性分析。
  5. 在这里从各方面获得感悟,尝试打破自己的设计,找到漏洞。
  6. 检查预处理数据:预处理算法可能给出不正确的输出,这意味着我们的模型正在错误的数据上进行训练。
  7. 特征形状:检查生成的特征和特征向量形状。
  8. 混洗数据:在发送给模型进行训练之前,确保标签和数据点被混洗。
  9. 使用偏移裁剪特征值:如果我们知道特征处理过程中的某些特定操作可能会使任何特征的任何字段的值为无穷大,那么我们应该考虑使用偏移。
  10. 根据上述步骤决定可能的后续步骤,以获得好的和坏的结果。
  11. 基于分析,重复或移动到下一组实验。

检查点 14:管理实验

  1. 一个人可以按照电子表格来管理实验的一切,这样在后期就很容易比较了。
  2. 每个实验应记录的细节,a)实验标识符/名称,b)管道标识符,c)数据集标识符,d)管道组件和超参数(可以分开用于预处理、特征、分类),e)训练日志/模型日志,f)状态(成功、失败),g)失败/成功的原因,h)跟进问题。
  3. 根本原因分析 对于你的实验来说,哪些管用,哪些没用。记录失败和成功的原因。
  4. 在这里找到关于计划和运行实验的参考。

第三阶段:准备生产和后续步骤

检查点 15:整合

  1. 弄清楚如何整合模型。为生产环境准备实施管道。
  2. 让同行评审
  3. 在生产环境中使用虚拟数据集测试模型。
  4. 用最终设置测试模型,以检查生产结果与实验结果之间的任何差异。

检查点 16:采样

  1. 根据误差率估计抽样规模。您可以使用 SurveyMonkey 计算器获得具有统计显著性的样本量。
  2. 为您的模型进行必要的采样。

检查点 17:优化

  1. 现在是时候进一步优化流水线的速度、自动化、精度/召回率和可扩展性了。
  2. 选择下一个最佳渠道,重复或继续下一个业务问题:)

最后但同样重要的是,一旦你完成了你的研究/实验,做一个回顾。回顾和反思总是好的

  1. 什么进展顺利?
  2. 哪里出了问题?
  3. 重要经验!

尽管数据科学问题本质上几乎是循环的,上面的检查点没有固定的顺序。我们希望上述清单可以帮助您更全面地解决下一个数据科学问题。

班里的 ML 团队一直在使用上面的检查表来解决各种问题。感谢 Vedvasu Sharma 、 Aniket Bhatnagar 、 Medha Katehar a、 Pragya Jaiswal 为清单的清晰化所做的贡献。

闭环 NLP 查询预处理器和响应合成器

原文:https://medium.com/innovation-machine/a-closed-loop-nlp-query-pre-processor-and-response-synthesizer-16a72eb186d2?source=collection_archive---------12-----------------------

一项关于合成准确、引人入胜、上下文相关和个性化查询响应的专利申请

闭环自然语言查询预处理器和响应合成器架构接受自然语言查询并动态合成查询结果。查询结果可以是数据故事的形式。

该架构识别、选择候选响应元素,并将其组合成一致且有意义的查询结果。该体系结构还实现了可适应的传递机制,该机制响应连接带宽、查询源偏好、查询源特征和其他因素。来自多个来源的反馈调整了处理后续查询的架构

该体系结构实现了对自动生成有意义的查询响应领域中的许多困难技术问题的技术解决方案,假定手动搜索潜在相关信息的数据存储广泛且不可能。下面总结了一些技术解决方案的例子。该架构提供了用于回答问题的个性化机制,例如,响应于:提问者的角色和视角;时机考虑;语境;会话历史,包括先前的查询和响应,来自与查询实体具有相似特征的其他人的查询和响应历史,例如其他企业工程师或经理;和其他因素。该架构还可以标识输入查询中显式和隐式引用的实体,并在其搜索候选响应元素时使用所标识的实体。

该体系结构还实现查询预测,以在给定起始输入查询或输入查询序列和上下文的情况下,预先确定可能的后续查询。

该架构理解哪些度量、关键性能指标(KPI)和其他数据与输入查询的实质相关,响应于可配置的本体和其他模型,其内容为输入查询的实质提供预定义的上下文。例如,上下文可以描述一个特定的企业、它的市场、它的产品、工作流、度量以及它的企业活动。

该体系结构还识别输入查询中提出的问题类型,并将输入查询和候选响应元素与企业活动、目标、计划和其他目标相关联。该架构中的技术解决方案进一步标识输入查询中的时间参考框架、其在例如企业或竞争企业的预定义财政年度内的定位以及其他定时数据。该体系结构响应企业结构数据,例如组织结构和企业动态,以区分查询响应。

该体系结构的技术实现还实现了推荐引擎,用于在输入查询和查询结果的会话之后建议智能动作。推荐引擎提供了进一步的好处,即通过任何给定的查询和响应之后的建议、问题和数据故事来鼓励额外的交互会话。

专利申请

仔细看看三种流行的人工智能技术以及它们是如何使用的

原文:https://towardsdatascience.com/a-closer-look-at-three-popular-artificial-intelligence-technologies-and-how-theyre-used-548408402ca?source=collection_archive---------6-----------------------

Photo by Roman Bozhko on Unsplash

从机器人流程自动化到机器学习算法,当今许多最具影响力的公司都在部署人工智能(AI)技术来推动业务成果。虽然大多数决策者都意识到新兴技术所带来的商业机会,但许多人却没有做好准备,仅仅是因为他们没有理解这些机会。

人工智能包括各种各样的技术和工具,有些已经存在了很长时间,有些则相对较新。尽管如此,有一点是明确的:企业正在更加努力地思考如何在 2018 年优先考虑人工智能。

根据国际数据公司(IDC)的数据,人工智能的广泛采用将从 2016 年的 80 亿美元跃升至 2020 年的 470 亿美元。下面让我们仔细看看三种流行的人工智能技术,以及创新公司是如何使用它们的。

机器学习

当公司谈论使用人工智能技术时,大多数指的是机器学习(ML)。作为人工智能计算最受欢迎的分支,ML 涉及通过从历史数据而不是人类命令中学习来训练算法执行任务。换句话说,计算机在没有显式编程的情况下学习。小型初创企业和主要品牌都使用 ML 来以更有效和结果驱动的方式访问、组织和决策数据。

在 SAP,机器学习是内容营销策略的重要组成部分。这家企业软件公司使用 ML 来分析内容,以便为他们的客户提供更加定制的体验。ML 算法通过主题映射发布的文章,帮助 SAP 通过内容个性化客户参与。

目标是帮助读者根据他们独特的行为和搜索历史找到更多相关的文章。对于 SAP 来说,ML-powered 技术使他们能够超越标准的推荐引擎,提供有针对性的见解和内容,在正确的时间以正确的创意体验吸引正确的客户。

计算机视觉

计算机视觉是人工智能的一个分支,研究计算机如何模仿人类的视觉以及人类查看和解释数字图像的能力。通过模式识别和图像处理,计算机视觉理解图片的内容,并对我们如何体验周围的世界产生了深远的影响。

Photo by Octavian Rosca on Unsplash

亚马逊使用计算机视觉技术,通过其亚马逊 Go 体验来改善顾客的实体购物。没有排队和结账,顾客只需使用 Amazon Go 应用程序进入商店,选择他们想要的商品,然后离开。怎么会?照相机拍下顾客购物时的照片。使用机器视觉、深度学习和传感器融合,亚马逊跟踪虚拟购物车中的商品,适当地向正确的亚马逊账户收费。

视觉引导的零售只是开始,因为计算机视觉也可能为智能城市打开大门,先进的视觉技术可能有助于减少道路上的碰撞和伤害。

机器人流程自动化

人工智能驱动的软件,如机器人流程自动化(RPA),已经成为世界各地公司的竞争优势。RPA 等数字技术提高了效率,减少了错误,甚至扰乱了公司打造客户体验的方式。

南非最大的银行标准银行通过 RPA 、ML 和认知自动化将传统流程数字化,提高了运营和后台工作的效率。结果,他们将客户入职时间从 20 天缩短到了 5 分钟!

RPA 软件为标准银行提供了应对金融服务挑战的灵活性和能力,同时与其他行业保持同步。RPA 技术减少了错误,将平凡的工作变成了有趣的事情,同时为客户提供了更丰富的体验。

总之

今天的客户期望数字的、无摩擦的体验。人工智能技术消除了对公司现有的海量数据进行解释和处理的负担。如上所述,聪明的企业使用这些工具来优化内容营销,提高运营效率,并提供屡获殊荣的客户体验。

GCP 特殊化张量流的无代码指南

原文:https://towardsdatascience.com/a-codeless-guide-to-tensorflow-with-the-gcp-specialization-bca5215c606b?source=collection_archive---------4-----------------------

边做边学。

我写这篇文章是为了让你理解 tensorflow 的细微差别,它是无代码的,通过这篇文章,你会对 tensorflow 实际上是如何工作的以及它的不同组件有一个概念。到目前为止,Google 的专长是检查实际代码和编码,以便你学得更好。这里提到的课程是 coursera 上 Google cloud 的“Tensorflow 简介”,包括向您介绍 tensor flow——Google 最著名的开源项目之一,也是 ML 行业的事实标准。学习 tensorflow 不仅可以帮助您创建模型,还可以理解和欣赏基于它构建的其他框架(如 keras 和 pytorch)的细微差别。这是一门信息量很大的课程,在三个模块中有很多东西要学。

Tensorflow,用于数值计算而不仅仅是机器学习的开源平台。写出用有向无环图表示的复杂数学函数。你可以借助 python 这样的高级编程语言来编写。名字从何而来?一维数列称为数组,而二维数组称为矩阵。现在三维数组被称为张量。张量是数据的 n 维数组(通常是 3 维或更多维)。Tensorflow 使用图是因为语言和硬件的可移植性(cpu 或 gpu)。这些图形计算模型是跨平台的,你可以用一种语言编写它们,但是使用计算模型,然后用不同的语言执行它们以提高速度。关于这一点最有趣的事实是在强大的机器上训练高度密集的模型,如云,然后使用训练好的模型,并将其部署在较小的硬件上,如手机,树莓派等。

有一个 tensorflow api 层次结构。它从用 c++编写自定义代码和制作自己的模块开始,这是非常低级的,涉及很多技术细节。tensorflow 的 python 级别为您提供了添加、子代理、创建张量等功能。tf.layers 的下一个级别,tf.losses 和 tf.metrics 帮助您进行更高的抽象,这是为了构建定制的神经网络模型而创建的。tf.estimator 的最高级别是 tf.estimator。用这种方式很容易理解层次结构。最后,google 云引擎使用 cmle 来运行 Tensorflow,而不管您使用的是什么抽象级别。

Tensorflow API Hierarchy

Tensorflow 的 python 级抽象让您可以构建我们之前讨论过的 DAG。要理解的最基本的事情是,最终在构建任何 DAG 之后,它只是一个模型。你可以把它想象成一个函数,函数运行于自身之中吗?他们没有我们需要打电话给他们。因此,在我们的例子中,我们首先需要创建一个会话来运行我们的模型,之后我们就像输入函数值一样输入模型值。所以本质上有两个步骤,创建图(DAG ),然后在会话中运行图。这被称为懒惰评估。

图表是你试图建立的计算模型。这些都是在 python api 的帮助下构建的。节点代表数学计算,而边代表节点之间传递的数据。最终,由于图表就像一个模型,它需要在会话的帮助下运行。所有需要的值都由 feed-dict 提供。张量是向量的推广,它们是数据的 n 维数组。简单地说,一个向量可以被认为是一系列的数字。当向量是二维的(即有行和列)时,它们被称为矩阵,三维或三维以上的向量通常被称为张量。这些是非常强大的数字仪器。在各种函数的帮助下,张量可以被制作、切片或整形。最后,我们在 tensorflow 中有变量,大多数变量是可训练的,神经网络的权重向量是可训练的变量,创建变量的最重要部分是考虑如何初始化它们。最后,如果你不想要变量,而只想有一个形式参数,并在运行时给它们输入值,那该怎么办?这是通过占位符解决的,占位符只是定义的变量,需要借助 tf.run()中的 feed-dict 参数进行初始化。

由于懒惰的评估,调试是棘手的。在调试的第一部分,您需要查找堆栈跟踪,然后是实际的错误消息。这通常非常简单,但是您可能会被错误消息的大小所困扰。然后用一些数据调用这个方法,检查哪里可能出错,然后改正。一些常见的问题是形状和数据类型问题。使用 tf.print、tfdbg 或 tensorboard 调试完整的程序。

估算器用于以简单的方式创建生产就绪模型。它们内嵌了许多样板代码,因此您不必再编写相同的代码。估算器是高级 tensorflow api 的一部分。估计器允许快速建模、检查点、内存不足的数据集、分布式训练等等。tf.estimator 具有所有这些功能。有许多预制的估算器,因为有一个通用的基础 api,你可以很快地把它换成其他预制的估算器,从而实现快速原型制作。

What Estimator API helps with

您可以按如下方式运行估算器,要素列类似于 api 的输入,您需要将数据集中的所有列插入到这些要素列中,例如,在房价预测的情况下,您的列可能是平方英尺和房屋类型,还可能有其他列,如带家具或不带家具等,有许多不同的数据类型来适应这些要素/属性..之后,通过使用预先制作的估计量(在这种情况下是线性回归量)来创建模型。train_input_fn 用于将训练数据集输入到模型中。predict_input_fn 用于将测试数据输入到模型中。

Using the estimator api

检查点就像游戏中的保存点,它们是成功运行后保存在某个位置的重量和其他参数。如果你认为一个模型没有达到标准,那么训练就从这个检查点开始,它们被内置在估计器中。estimator api 还具有从 numpy 数组或 pandas 数据帧馈送数据的功能。estimator api 还可以在 tf.dataset 的帮助下帮助您处理大型数据集。关于数据集,您需要了解的一件事是,ML 模型通常是通过批处理来训练的,每个批处理都有一个有限的大小,这表明无论整个数据集大小有多大,它最终都会被分解成多个批处理。这是由张量流促成的。随着并行而不是单机计算思想的进步,我们正在走向并行。数据并行性是当今训练 ML 模型的核心,Tensorflow 通过 train_and_evaluate 函数使这一点变得更容易,您需要使用该函数来提及训练和评估规范。为了评估你的训练,通常使用 tensorboard。

Cloud ML 引擎与您之前看到的整个 tensorflow 堆栈是正交的,它可以与堆栈中的任何抽象层进行交互并使用它。为什么是 CMLE?用于在多台机器上分配培训。向外扩展而不是向上扩展是关键。ML 算法计划收集比现有数据多 10 倍的数据,并将其整合到他们的系统中,这就是为什么他们比简单的数据系统好得多。另一件需要考虑的事情是,可以从分析原始数据中发现许多见解,并将这些见解作为特征进行整合会有很大帮助。

The Processing Cycle

你如何使用 CMLE?您需要使用 Tensorflow 创建您的计算图,然后打包您的 trainer 应用程序,最后配置并启动 CMLE 作业。在使用 CMLE 之前,您需要保留一个包结构,您可以使用 gcloud 命令来检查正确的包结构。最后,您可以通过获取作业的当前状态来监控作业,这可以通过 gcp web 控制台来完成。

CMLE 模块为本课程画上了一个句号,即 GCP 特殊化的 Tensorflow 简介。为了熟悉本文中谈到的 tensorflow 的各种组件,您可以查看可在此处找到的实验材料。完成本实验的最佳方式是通过查看 tensorflow 文档,同时尝试理解这些函数的细微差别。

多光谱激光雷达数据聚类的 K-Means 和 EM 方法比较

原文:https://towardsdatascience.com/a-comparison-between-k-means-clustering-and-expectation-maximization-estimation-for-clustering-8c75a1193eb7?source=collection_archive---------2-----------------------

多年来,已经开发了几种类型的聚类算法。这些算法通常分为 4 个子类别(分割算法、分层算法、密度算法和基于模型的算法)。分割算法是最常用的算法,因为它们简单而直观。分区算法将数据分成几个分区,并根据某种标准对它们进行评估。相比之下,基于模型的算法为数据集中的每个分类假设一个统计模型,条件是假设的模型最适合该分类。作为对激光雷达数据进行分类的研究项目的一部分,我研究了用于树种分类的分区算法和基于模型的聚类算法之间的异同。我使用 K-means 和期望最大化估计作为上面两个类别的样本算法。这篇博文将会用一些很酷的视觉效果总结我的发现,但是如果你对更多的技术细节感兴趣,你可以在这里找到完整的调查。

k 均值

K-means 聚类可能是大多数人在开始机器学习课程时遇到的第一个无监督学习算法之一。它易于使用和直观。然而,如果我们沉迷于 K-means 背后的概率理论,很明显,该算法对数据的分布做出了非常一般的假设。K-means 算法试图在聚类间方差之和最小化的优化标准下检测数据集中的聚类。因此,K-均值聚类算法产生数据中已识别聚类状态的最小方差估计(MVE)。

该算法背后的直觉在于,平均而言,从聚类质心(𝜇𝑘)到聚类内的元素的距离在所有识别的聚类中应该是均匀的(这是我们稍后将看到的缺点)。尽管该方法在检测同质聚类时工作良好,但是由于其优化函数中固有的关于聚类的球形性质的简单假设(即,它假设所有聚类具有相等的协方差矩阵),该方法不可避免地存在缺点。

期望最大化估计

期望最大化(EM)是另一种流行的聚类算法,尽管有点复杂,它依赖于最大化可能性来找到数据集中底层子群体的统计参数。我不会深入 EM 背后的概率理论。如果你有兴趣,你可以在这里阅读更多。但是简单总结一下,EM 算法在两个步骤(E 步骤和 M 步骤)之间交替。在 E 步骤中,该算法试图使用统计参数的当前估计来找到原始似然性的下限函数。在 M 步骤中,该算法通过最大化下限函数(即确定统计参数的 MLE)来寻找这些统计参数的新估计。因为在每一步我们最大化下界函数,所以该算法总是产生比前一次迭代更高可能性的估计,并最终收敛到最大值。

那么是什么让 EM 比 K-means 更特别呢?与 K-means 不同,在 EM 中,聚类不限于球形。在 EM 中,我们可以约束算法以提供不同的协方差矩阵(球形、对角线和通用)。这些不同的协方差矩阵反过来允许我们控制聚类的形状,因此我们可以检测数据中具有不同特征的子群体。

Cluster Analysis: Original Data (left), k-means (middle), EM (right) (Illustration by Chire)

您可能已经注意到,在上图中,数据包含异常值,显示为黄色点。这两种算法都没有检测异常值的能力,因此我们必须对数据进行预处理,以减轻检测到的聚类中的异常值的影响。尤其是 EM,由于对协方差矩阵没有约束,因此它往往对异常值的存在很敏感。

泰坦激光雷达数据集

现在我们对 EM 的工作有了一些基本的了解,我们可以谈谈一些结果了。我从 Optech 的 Titan 传感器获得了一个多光谱激光雷达数据集,它有 3 个通道(532 纳米,1064 纳米和 1550 纳米)。该数据集是在多伦多斯卡伯勒上空收集的,飞行高度为 1500 米。为了对树种进行分类,我使用阈值技术对数据进行了预处理,去除了所有非树木覆盖类型。

LiDAR scan (Right Image) Titan multispectral LiDAR intensity data plotted in the spectral domain (Top Left: 1550 nm spectral band on the Vertical-Axis vs. 532 nm spectral band on the Horizontal-Axis, Top Right: 1550 nm spectral band on the Vertical-Axis vs. 1064 nm spectral band on the Horizontal-Axis, Bottom: 1064 nm spectral band on the Vertical-Axis vs. 532 nm spectral band on the Horizontal-Axis).

数据集还包含异常值,这些异常值在预处理阶段被删除。因为我已经实现了 K-means,所以我使用离群点去除聚类(ORC)方法从数据集中过滤离群点。

集群

使用上述 3 个光谱特征中的数据,我初步确定了数据集中的最佳聚类数。分区和基于模型的算法有一个主要缺点,即数据集内的聚类数需要由用户提供(基于密度的算法没有这个问题,但是需要指定其他阈值)。为了确定最佳的集群数量,我对一系列集群运行了 k-means 算法,并记录了每个分区的误差平方和(SSE)

Inter Cluster Variance for different number of clusters determined using k-means clustering. The red circle indicates the optimal number of clusters for the dataset.

然后,我使用图的渐近性质来挑选数据集中的最佳聚类数(这是基于我的主观解释,但是我发现 SSE 在 3 个聚类之后表现得相当渐近)。

我运行了 k-means 和 EM 算法的不同变体来获得以下聚类。对于 EM 算法,我主要关注协方差矩阵的三种配置(球形、对角线和完全填充(或通用))。

K-means (Left) vs EM with Spherical Covariance Matrix (Right)

EM with Generic Covariance Matrix (Left) vs EM with Diagonal Covariance Matrix (Right)

我发现 k-means 的结果最接近 EM 算法的球形变体,这正是我们所期望的。EM 的对角线变体允许每个聚类具有不同的大小,而通用协方差矩阵另外给予每个聚类在特征空间中不同的方向。

虽然通用协方差矩阵允许在检测数据中的不同亚群体时有更大的灵活性,但它肯定不是没有问题。在我疯狂编程期间,我在使用完全填充的协方差矩阵时遇到了一些收敛问题。我发现,由于协方差较大,解有时很容易发散。当我测试更高维度的数据集(即超光谱图像)时,情况尤其如此。具有全协方差模型的 EM 的收敛性问题并不新鲜;由于需要估计大量的参数,收敛到一个正确的解决方案也可能非常缓慢。

总之,EM 算法为流行的 k-means 提供了一个强大的替代方法,对聚类的特征有更好的控制。然而,EM 算法,像 k-means 一样,也产生次优解。换句话说,不能保证算法将产生最适合底层子群体的模型(即聚类)。

Python 中完整的机器学习演练:第二部分

原文:https://towardsdatascience.com/a-complete-machine-learning-project-walk-through-in-python-part-two-300f1f8147e2?source=collection_archive---------3-----------------------

模型选择、超参数调整和评估

组装解决问题所需的所有机器学习部件可能是一项艰巨的任务。在这一系列文章中,我们将使用真实世界的数据集来实现机器学习工作流,以了解各种技术是如何结合在一起的。

在第一篇文章中,我们清理并结构化了数据,进行了探索性的数据分析,开发了一组在我们的模型中使用的特性,并建立了一个我们可以用来衡量性能的基线。在本文中,我们将了解如何在 Python 中实现和比较几个机器学习模型,执行超参数调整以优化最佳模型,并在测试集上评估最终模型。

这个项目的完整代码是 GitHub 上的,与本文对应的第二本笔记本在这里。您可以随意使用、共享和修改代码!

模型评估和选择

提醒一下,我们正在进行一项监督回归任务:使用纽约市建筑能源数据,我们希望开发一个模型,可以预测建筑的能源之星得分。我们的重点是预测的准确性和模型的可解释性。

有吨的机器学习模型可供选择,决定从哪里开始可能是令人生畏的。虽然有一些图表试图告诉你使用哪种算法,但我更喜欢尝试几种,看看哪种效果最好!机器学习仍然是一个主要由经验(实验)而不是理论结果驱动的领域,并且几乎不可能提前知道哪个模型会做得最好。

一般来说,从简单、可解释的模型(如线性回归)开始是一个好主意,如果性能不够好,就转向更复杂但通常更精确的方法。下图显示了准确性与可解释性权衡的(极不科学的)版本:

Interpretability vs. Accuracy (Source)

我们将评估涵盖复杂性范围的五种不同模型:

  • 线性回归
  • K-最近邻回归
  • 随机森林回归
  • 梯度推进回归
  • 支持向量机回归

在这篇文章中,我们将着重于实现这些方法,而不是它们背后的理论。对于任何对学习背景感兴趣的人,我强烈推荐统计学习入门(网上免费提供)或使用 Scikit-Learn 和 TensorFlow 进行机器学习。这两本教科书都很好地解释了理论,并分别展示了如何有效地使用 R 和 Python 中的方法。

输入缺失值

虽然我们在清理数据时删除了丢失值超过 50%的列,但仍然有相当多的观察值丢失。机器学习模型无法处理任何缺失的值,所以我们必须填充它们,这是一个被称为插补的过程。

首先,我们将读入所有数据,并提醒自己它看起来像什么:

import pandas as pd
import numpy as np# Read in data into dataframes 
train_features = pd.read_csv('data/training_features.csv')
test_features = pd.read_csv('data/testing_features.csv')
train_labels = pd.read_csv('data/training_labels.csv')
test_labels = pd.read_csv('data/testing_labels.csv')**Training Feature Size:  (6622, 64)
Testing Feature Size:   (2839, 64)
Training Labels Size:   (6622, 1)
Testing Labels Size:    (2839, 1)**

每个值NaN代表一个缺失的观察值。虽然有多种方法来填充缺失数据,但我们将使用一种相对简单的方法,即中位数插补。这会用列的中值替换列中所有缺失的值。

在下面的代码中,我们创建了一个策略设置为 median 的 Scikit-Learn Imputer对象。然后我们在训练数据上训练这个对象(使用imputer.fit,并用它来填充训练和测试数据中缺失的值(使用imputer.transform)。这意味着用来自训练数据的相应中值来填充测试数据中的缺失值。

(我们必须以这种方式进行插补,而不是对所有数据进行训练,以避免测试数据泄漏的问题,即来自测试数据集的信息溢出到训练数据中。)

# Create an imputer object with a median filling strategy
imputer = Imputer(strategy='median')# Train on the training features
imputer.fit(train_features)# Transform both training data and testing data
X = imputer.transform(train_features)
X_test = imputer.transform(test_features)**Missing values in training features:  0
Missing values in testing features:   0**

所有的特征现在都有真实的有限值,没有遗漏的例子。

特征缩放

缩放是指改变特征范围的一般过程。这是必要的,因为特征以不同的单位测量,因此涵盖不同的范围。诸如支持向量机和 K-最近邻之类的方法考虑了观测值之间的距离度量,这些方法受到特征范围的显著影响,并且缩放允许它们学习。虽然像线性回归和随机森林这样的方法实际上并不需要特性缩放,但是当我们比较多个算法时,采取这一步骤仍然是最佳实践。

我们将通过将每个特征放在 0 到 1 的范围内来缩放特征。这是通过取特性的每个值,减去特性的最小值,然后除以最大值减去最小值(范围)来完成的。这种特定版本的缩放通常被称为标准化,另一个主要版本被称为标准化。

虽然这个过程很容易手工实现,但是我们可以使用 Scikit-Learn 中的MinMaxScaler对象来实现。这种方法的代码与插补的代码相同,只是用了一个定标器而不是插补器!同样,我们确保仅使用训练数据进行训练,然后转换所有数据。

# Create the scaler object with a range of 0-1
scaler = MinMaxScaler(feature_range=(0, 1))# Fit on the training data
scaler.fit(X)# Transform both the training and testing data
X = scaler.transform(X)
X_test = scaler.transform(X_test)

现在,每个要素的最小值为 0,最大值为 1。缺失值插补和特征缩放是几乎任何机器学习管道中都需要的两个步骤,因此了解它们是如何工作的是一个好主意!

在 Scikit-Learn 中实现机器学习模型

在我们清理和格式化数据的所有工作之后,实际上用模型创建、训练和预测是相对简单的。我们将使用 Python 中的 Scikit-Learn 库,它有很好的文档和一致的模型构建语法。一旦您知道如何在 Scikit-Learn 中制作一个模型,您就可以快速实现各种算法。

我们可以用梯度推进回归器来说明模型创建、训练(使用.fit)和测试(使用.predict)的一个例子:

**Gradient Boosted Performance on the test set: MAE = 10.0132**

模型创建、训练和测试都是一行!为了构建其他模型,我们使用相同的语法,只是改变了算法的名称。结果如下所示:

为了客观地看待这些数字,使用目标的中值计算的原始基线是 24.5。显然,机器学习适用于我们的问题,因为在基线上有显著的改进!

梯度提升回归量 (MAE = 10.013)略胜随机森林(10.014 MAE)。这些结果并不完全公平,因为我们主要使用超参数的默认值。特别是在支持向量机等模型中,性能高度依赖于这些设置。尽管如此,我们将从这些结果中选择梯度推进回归变量进行模型优化。

用于模型优化的超参数调整

在机器学习中,在我们选择了一个模型之后,我们可以通过调整模型超参数来优化它。

首先,什么是超参数,它们与参数有何不同?

  • 模型超参数最好被认为是数据科学家在训练前设置的机器学习算法的设置。例如随机森林中的树木数量或 K-最近邻算法中使用的邻居数量。
  • 模型参数是模型在训练期间学习的内容,例如线性回归中的权重。

控制超参数通过改变模型中欠拟合和过拟合之间的平衡来影响模型性能。欠拟合是指我们的模型不够复杂(它没有足够的自由度)来学习从特征到目标的映射。一个欠拟合模型有高偏差,我们可以通过使我们的模型更复杂来纠正它。

过度拟合是指我们的模型基本上记住了训练数据。过度拟合模型具有高方差,我们可以通过正则化来限制模型的复杂度,从而对其进行校正。欠拟合和过拟合模型都不能很好地概括测试数据。

选择正确的超参数的问题是,对于每个机器学习问题,最佳集合都是不同的!因此,找到最佳设置的唯一方法是在每个新数据集上尝试多种设置。幸运的是,Scikit-Learn 有许多方法可以让我们有效地评估超参数。此外,像 TPOT 上位实验室这样的项目正在尝试使用遗传编程这样的方法来优化超参数搜索。在这个项目中,我们将坚持用 Scikit-Learn 来做这件事,但是请继续关注 auto-ML 场景的更多工作!

交叉验证随机搜索

我们将实施的特定超参数调整方法称为交叉验证随机搜索:

  • 随机搜索 指的是我们将用来选择超参数的技术。我们定义一个网格,然后随机抽样不同的组合,而不是网格搜索,我们穷尽地尝试每一个组合。(令人惊讶的是,随机搜索的表现几乎和网格搜索一样好,运行时间大幅减少。)
  • 交叉验证 是我们用来评估超参数选定组合的技术。我们使用 K-Fold 交叉验证,而不是将训练集分成单独的训练集和验证集,这减少了我们可以使用的训练数据量。这包括将训练数据分成 K 个折叠,然后经历一个迭代过程,其中我们首先在 K-1 个折叠上训练,然后在第 K 个折叠上评估性能。我们重复这个过程 K 次,在 K 重交叉验证结束时,我们取 K 次迭代中每一次的平均误差作为最终的性能测量。

K = 5 的 K 倍交叉验证的思想如下所示:

K-Fold Cross Validation with K = 5 (Source)

使用交叉验证执行随机搜索的整个过程是:

  1. 建立一个超参数网格来评估
  2. 随机抽样超参数组合
  3. 使用所选组合创建模型
  4. 使用 K-fold 交叉验证评估模型
  5. 确定哪些超参数效果最好

当然,我们实际上并不手动完成这项工作,而是让 Scikit-Learn 的RandomizedSearchCV来处理所有的工作!

轻微分流:梯度升压法

由于我们将使用梯度推进回归模型,我至少应该给一点背景知识!该模型是一种集成方法,这意味着它是由许多弱学习者构建而成的,在这种情况下是个体决策树。一种 bagging 算法,如随机森林并行训练弱学习者,并让他们投票做出预测,而一种增强方法如梯度增强,依次训练学习者,每个学习者“专注于”前一个学习者所犯的错误。

助推方法近年来变得流行,并经常赢得机器学习比赛。梯度提升方法是一种特殊的实现方式,它使用梯度下降,通过在先前学习者的残差上顺序训练学习者来最小化成本函数。梯度增强的 Scikit-Learn 实现通常被认为不如其他库(如 XGBoost )有效,但它对于我们的小数据集来说足够好,并且相当准确。

返回超参数调谐

在梯度增强回归器中有许多超参数需要调整,您可以查看 Scikit-Learn 文档了解详情。我们将优化以下超参数:

  • loss:最小化损失函数
  • n_estimators:要使用的弱学习器(决策树)的数量
  • max_depth:每个决策树的最大深度
  • min_samples_leaf:决策树的一个叶节点所需的最小样本数
  • min_samples_split:拆分决策树节点所需的最小样本数
  • max_features:用于分割节点的最大特征数

我不确定是否有人真正理解所有这些是如何相互作用的,找到最佳组合的唯一方法是尝试它们!

在下面的代码中,我们构建了一个超参数网格,创建了一个RandomizedSearchCV对象,并对 25 个不同的超参数组合使用 4 重交叉验证来执行超参数搜索:

执行搜索后,我们可以检查RandomizedSearchCV对象以找到最佳模型:

# Find the best combination of settings
random_cv.best_estimator_**GradientBoostingRegressor(loss='lad', max_depth=5,
                          max_features=None,
                          min_samples_leaf=6,
                          min_samples_split=6,
                          n_estimators=500)**

然后,我们可以使用这些结果,通过为网格选择接近这些最佳值的参数来执行网格搜索。然而,进一步的调整不太可能显著改进我们的模型。一般来说,适当的特征工程对模型性能的影响要比最广泛的超参数调整大得多。这是应用于机器学习的收益递减定律:特征工程让你走了大部分路,而超参数调整通常只提供很小的好处。

我们可以尝试的一个实验是改变估计器(决策树)的数量,同时保持其余的超参数不变。这直接让我们观察这个特定设置的效果。参见笔记本了解的实现,但以下是结果:

随着模型使用的树的数量增加,训练和测试误差都减小。然而,训练误差比测试误差下降得更快,我们可以看到我们的模型过度拟合:它在训练数据上表现非常好,但在测试集上不能达到同样的性能。

我们总是预计测试集的性能至少会有所下降(毕竟,模型可以看到训练集的真实答案),但是显著的差距表明过度拟合。我们可以通过获取更多的训练数据来解决过度拟合问题,或者通过 hyerparameters 来降低我们模型的复杂性。在这种情况下,我们将把超参数留在原处,但我鼓励任何人尝试减少过度拟合。

对于最终的模型,我们将使用 800 个估计量,因为这在交叉验证中产生了最低的误差。现在,是时候测试这个模型了!

对测试集进行评估

作为负责任的机器学习工程师,我们确保不让我们的模型在任何训练点看到测试集。因此,我们可以使用测试集性能作为我们的模型在现实世界中部署时的性能指标。

对测试集进行预测并计算性能相对简单。这里,我们将默认梯度推进回归器的性能与调整后的模型进行比较:

# Make predictions on the test set using default and final model
default_pred = default_model.predict(X_test)
final_pred = final_model.predict(X_test)**Default model performance on the test set: MAE = 10.0118.
Final model performance on the test set:   MAE = 9.0446.**

超参数调整将模型的精度提高了约 10%。根据不同的用例,10%可能是一个巨大的改进,但这需要大量的时间投入!

我们还可以使用 Jupyter 笔记本中的%timeit magic 命令来计时训练这两个模型需要多长时间。首先是默认模型:

%%timeit -n 1 -r 5
default_model.fit(X, y)**1.09 s ± 153 ms per loop (mean ± std. dev. of 5 runs, 1 loop each)**

1 秒训练似乎很合理。最终调优的模型没有这么快:

%%timeit -n 1 -r 5
final_model.fit(X, y)**12.1 s ± 1.33 s per loop (mean ± std. dev. of 5 runs, 1 loop each)**

这展示了机器学习的一个基本方面:它总是一个权衡取舍的游戏。我们必须不断地平衡准确性和可解释性,偏差和方差,准确性和运行时间,等等。正确的混合最终取决于问题。在我们的例子中,相对而言,运行时间增加 12 倍是很大的,但从绝对意义上来说,并不显著。

一旦我们有了最终的预测,我们就可以研究它们,看看它们是否表现出任何明显的偏差。左侧是预测值和实际值的密度图,右侧是残差直方图:

Density Plot of Predicted and Actual Values (left) and Histogram of Residuals (right)

模型预测似乎遵循实际值的分布,尽管密度峰值更接近于训练集的中值(66),而不是真正的密度峰值(接近 100)。残差接近正态分布,尽管我们看到一些大的负值,其中模型预测远低于真实值。在下一篇文章中,我们将更深入地解读这个模型的结果。

结论

在本文中,我们介绍了机器学习工作流程中的几个步骤:

  • 缺失值的插补和特征的缩放
  • 几种机器学习模型的评估和比较
  • 使用随机网格搜索和交叉验证的超参数调谐
  • 评估测试集上的最佳模型

这项工作的结果表明,机器学习适用于使用可用数据预测建筑物能源之星得分的任务。使用梯度增强回归器,我们能够预测测试集上的分数在真实值的 9.1 分之内。此外,我们看到超参数调优可以提高模型的性能,但在时间投入方面要付出很大的代价。这是我们在开发机器学习解决方案时必须考虑的众多权衡之一。

在第三篇文章中(此处),我们将深入观察我们创造的黑箱,并试图理解我们的模型是如何做出预测的。我们还将确定影响能源之星评分的最大因素。虽然我们知道我们的模型是准确的,但我们想知道为什么会做出这样的预测,这告诉了我们什么问题!

一如既往,我欢迎反馈和建设性的批评,可以通过 Twitter @koehrsen_will 联系。

Python 中完整的机器学习项目演练:第一部分

原文:https://towardsdatascience.com/a-complete-machine-learning-walk-through-in-python-part-one-c62152f39420?source=collection_archive---------0-----------------------

Photo by Ross Sneddon on Unsplash

把机器学习的碎片放在一起

通读一本数据科学书籍或参加一门课程,感觉就像你掌握了各个部分,但不太知道如何将它们组合在一起。采取下一步措施并解决一个完整的机器学习问题可能会令人生畏,但保留并完成第一个项目将让你有信心解决任何数据科学问题。这一系列文章将通过一个真实世界的数据集来介绍一个完整的机器学习解决方案,让您了解所有这些部分是如何组合在一起的。

我们将逐步遵循一般的机器学习工作流程:

  1. 数据清理和格式化
  2. 探索性数据分析
  3. 特征工程和选择
  4. 在性能指标上比较几种机器学习模型
  5. 对最佳模型执行超参数调整
  6. 评估测试集上的最佳模型
  7. 解释模型结果
  8. 得出结论并记录工作

在这个过程中,我们将看到每个步骤如何流入下一个步骤,以及如何用 Python 具体实现每个部分。完整的项目可以在 GitHub 上找到,这里有的第一个笔记本。第一篇文章将涵盖第 1-3 步,其余部分将在后续文章中讨论。

(注意,这个问题最初是在一家初创公司的工作筛选中作为“任务”交给我的。完成工作后,我得到了这份工作,但后来公司的首席技术官辞职了,他们无法再招聘新员工。我猜这就是创业现场的情况吧!)

问题定义

在我们开始编码之前,第一步是理解我们试图解决的问题和可用的数据。在这个项目中,我们将使用来自纽约市的公开建筑能源数据。

目标是使用能源数据建立一个模型,该模型可以预测建筑物的能源之星得分,并解释结果以找到影响得分的因素。

这些数据包括能源之星得分,这使得这成为一个受监督的回归机器学习任务:

  • 监督:我们可以访问特征和目标,我们的目标是训练一个模型,它可以学习两者之间的映射
  • 回归:能源之星得分是一个连续变量

我们希望开发一个既准确——它可以预测接近真实值的能源之星分数——又可解释 —我们可以理解模型预测的模型。一旦我们知道了目标,我们就可以在挖掘数据和构建模型时用它来指导我们的决策。

数据清理

与大多数数据科学课程让你相信的相反,并不是每个数据集都是一组完美的观察值,没有缺失值或异常(看看你的 mtcars 和 iris 数据集)。现实世界的数据是杂乱的,这意味着我们需要在开始分析之前将数据清理并转换成可接受的格式。数据清理是大多数实际数据科学问题中不光彩但必要的一部分。

首先,我们可以像熊猫DataFrame一样加载数据,然后看一看:

import pandas as pd
import numpy as np# Read in data into a dataframe 
data = pd.read_csv('data/Energy_and_Water_Data_Disclosure_for_Local_Law_84_2017__Data_for_Calendar_Year_2016_.csv')# Display top of dataframe
data.head()

What Actual Data Looks Like!

这是包含 60 列的完整数据的子集。我们已经可以看到一些问题:首先,我们知道我们想要预测ENERGY STAR Score,但是我们不知道任何列是什么意思。虽然这不一定是一个问题——我们经常可以在没有任何变量知识的情况下建立准确的模型——但我们希望关注可解释性,并且至少理解一些列可能是重要的。

当我最初从初创公司获得任务时,我不想问所有列名的含义,所以我查看了文件的名称,

并决定搜索“土法 84”。这让我看到了这个页面,它解释说这是纽约市的一项法律,要求所有一定规模的建筑报告它们的能源使用情况。更多的搜索把我带到了所有列的定义。也许查看文件名是一个显而易见的开始,但对我来说,这是一个提醒,要慢慢来,这样你就不会错过任何重要的东西!

我们不需要研究所有的栏目,但我们至少应该了解能源之星评分,它被描述为:

基于报告年份自我报告的能源使用情况的 1 到 100%的排名。能源之星评分是用于比较建筑物能源效率的相对指标。

这解决了第一个问题,但是第二个问题是丢失的值被编码为“不可用”。这是 Python 中的一个字符串,这意味着即使包含数字的列也将被存储为object数据类型,因为 Pandas 将包含任何字符串的列转换为包含所有字符串的列。我们可以使用dataframe.info()方法查看列的数据类型:

# See the column data types and non-missing values
data.info()

果然,一些明显包含数字的列(如 ft)被存储为对象。我们不能对字符串进行数值分析,所以这些必须被转换成数字(特别是float)数据类型!

下面是一小段 Python 代码,它将所有“不可用”的条目替换为非数字(np.nan),这可以解释为数字,然后将相关列转换为float数据类型:

一旦正确的列是数字,我们就可以开始研究数据了。

缺失数据和异常值

除了不正确的数据类型之外,处理真实世界数据时的另一个常见问题是缺少值。这些可能由于许多原因而出现,并且必须在我们训练机器学习模型之前填充或移除。首先,让我们大致了解一下每一列中有多少缺失值(代码见笔记本)。

(为了创建这个表,我使用了这个堆栈溢出论坛中的一个函数)。

虽然我们总是希望小心地删除信息,但是如果一个列有很高百分比的缺失值,那么它可能对我们的模型没有用。移除列的阈值应该取决于问题(这里有一个讨论),对于这个项目,我们将移除任何缺失值超过 50%的列。

在这一点上,我们可能还想删除离群值。这些可能是由于数据输入中的打字错误、单位错误,或者它们可能是合法但极端的值。对于这个项目,我们将根据极端异常值的定义移除异常值:

  • 低于第一个四分位数 3÷四分位数间距
  • 高于第三个四分位数+3÷四分位数间距

(有关删除列和异常的代码,请参见笔记本)。在数据清理和异常移除过程结束时,我们留下了超过 11,000 个建筑物和 49 个特征。

探索性数据分析

既然繁琐但必要的数据清理步骤已经完成,我们可以继续探索我们的数据了!探索性数据分析 (EDA)是一个开放式的过程,我们通过计算统计数据并制作图表来发现数据中的趋势、异常、模式或关系。

简而言之,EDA 的目标是学习我们的数据能告诉我们什么。它通常从高层次的概述开始,然后随着我们发现数据中感兴趣的部分,缩小到特定的领域。这些发现本身可能是有趣的,或者它们可以用于通知我们的建模选择,例如通过帮助我们决定使用哪些功能。

单变量图

我们的目标是预测能源之星得分(在我们的数据中被重命名为score),因此一个合理的起点是检查这个变量的分布。直方图是可视化单个变量分布的一种简单而有效的方法,使用matplotlib很容易制作。

import matplotlib.pyplot as plt# Histogram of the Energy Star Score
plt.style.use('fivethirtyeight')
plt.hist(data['score'].dropna(), bins = 100, edgecolor = 'k');
plt.xlabel('Score'); plt.ylabel('Number of Buildings'); 
plt.title('Energy Star Score Distribution');

这个看起来挺可疑的!能源之星得分是一个百分位数排名,这意味着我们希望看到一个统一的分布,每个分数分配给相同数量的建筑。然而,大量的建筑要么得分最高(100 分),要么得分最低(1 分)(能源之星得分越高越好)。

如果我们回到分数的定义,我们会看到它是基于“自我报告的能源使用情况”,这可能解释了非常高的分数。要求建筑业主报告他们自己的能源使用情况就像要求学生报告他们自己的考试成绩一样!因此,这可能不是衡量建筑能效的最客观的标准。

如果我们有无限的时间,我们可能想要调查为什么这么多的建筑有非常高和非常低的分数,我们可以通过选择这些建筑并查看它们的共同点。然而,我们的目标只是预测分数,而不是设计一个更好的建筑评分方法!我们可以在报告中注明分数的分布是可疑的,但我们主要关注的是预测分数。

寻找关系

EDA 的主要部分是搜索特征和目标之间的关系。与目标相关的变量对模型是有用的,因为它们可用于预测目标。检查分类变量(仅取有限的一组值)对目标的影响的一种方法是通过使用seaborn库的密度图。

一个密度图可以被认为是一个平滑的直方图,因为它显示了单个变量的分布。我们可以按类别给密度图着色,看看分类变量如何改变分布。以下代码根据建筑类型(仅限于超过 100 个数据点的建筑类型)绘制了能源之星得分的密度图:

我们可以看到,建筑类型对能源之星得分有显著影响。办公楼往往得分较高,而酒店得分较低。这告诉我们,我们应该在建模中包括建筑类型,因为它确实对目标有影响。作为分类变量,我们必须对建筑类型进行一次性编码。

类似的图表可用于显示各区的能源之星得分:

行政区对得分的影响似乎没有建筑类型大。尽管如此,我们可能希望将它包含在我们的模型中,因为各行政区之间存在细微的差异。

为了量化变量之间的关系,我们可以使用皮尔逊相关系数。这是对两个变量之间线性关系的强度和方向的度量。得分+1 是完美的线性正关系,得分-1 是完美的负线性关系。相关系数的几个值如下所示:

Values of the Pearson Correlation Coefficient (Source)

虽然相关系数不能捕捉非线性关系,但它是开始弄清楚变量如何相关的好方法。在 Pandas 中,我们可以很容易地计算数据帧中任何列之间的相关性:

# Find all correlations with the score and sort 
correlations_data = data.corr()['score'].sort_values()

与目标的最负(左)和正(右)相关性:

在特征和目标之间有几个很强的负相关,最负的是不同类别的 EUI(这些度量在它们的计算方式上略有不同)。EUI——能源使用强度 —是一栋建筑使用的能源量除以建筑的平方英尺。它旨在衡量建筑的效率,分数越低越好。直观地说,这些相关性是有意义的:随着 EUI 的增加,能源之星得分往往会降低。

双变量图

为了可视化两个连续变量之间的关系,我们使用散点图。我们可以在点的颜色中包含附加信息,例如分类变量。例如,下图显示了能源之星得分与按建筑类型着色的站点 EUI 的关系:

这个图让我们想象相关系数为-0.7 是什么样子。随着现场 EUI 降低,能源之星得分增加,这种关系在各种建筑类型中保持稳定。

我们将制作的最后一个探索图被称为 Pairs 图。这是一个伟大的探索工具,因为它让我们看到多对变量之间的关系以及单个变量的分布。这里我们使用 seaborn 可视化库和PairGrid函数创建一个 Pairs 图,上面的三角形是散点图,对角线是直方图,下面的三角形是 2D 核密度图和相关系数。

为了看到变量之间的相互作用,我们寻找行和列的交叉点。例如,要查看Weather Norm EUIscore的相关性,我们查看Weather Norm EUI行和score列,看到相关系数为-0.67。除了看起来很酷之外,这样的图可以帮助我们决定在建模中包含哪些变量。

特征工程和选择

特征工程和选择通常为机器学习问题提供最大的时间回报。首先,我们来定义一下这两个任务是什么:

  • 特征工程:获取原始数据并提取或创建新特征的过程。这可能意味着对变量进行转换,例如自然对数和平方根,或者对分类变量进行一次性编码,以便它们可以在模型中使用。一般来说,我认为特征工程就是从原始数据中创建额外的特征。
  • 特征选择:在数据中选择最相关特征的过程。在特征选择中,我们移除特征以帮助模型更好地概括新数据并创建更易解释的模型。一般来说,我认为特征选择就是减去特征,所以我们只剩下那些最重要的。

机器学习模型只能从我们提供的数据中学习,因此确保数据包含我们任务的所有相关信息至关重要。如果我们不给一个模型输入正确的数据,那么我们就是在让它失败,我们不应该期望它学习!

对于本项目,我们将采取以下特征工程步骤:

  • 一键编码分类变量(区和物业使用类型)
  • 加入数值变量的自然对数变换

一键编码是在模型中包含分类变量所必需的。机器学习算法无法理解“办公室”的建筑类型,所以如果建筑是办公室,我们必须将其记录为 1,否则记录为 0。

添加变换后的要素可以帮助我们的模型了解数据中的非线性关系。采用平方根、自然对数或各种幂的特征是数据科学中的常见做法,可以基于领域知识或实践中最有效的方法。这里我们将包括所有数字特征的自然对数。

以下代码选择数字特征,对这些特征进行对数变换,选择两个分类特征,对这些特征进行一次性编码,并将这两个集合连接在一起。这看起来工作量很大,但在熊猫中却相对简单!

在这个过程之后,我们有超过 11,000 个观察值(建筑物)和 110 个列(特征)。并非所有这些特征都可能对预测能源之星得分有用,因此现在我们将转向特征选择以移除一些变量。

特征选择

我们数据中的 110 个特征中有许多是多余的,因为它们彼此高度相关。例如,这是一个站点 EUI 与天气标准化站点 EUI 的关系图,其相关系数为 0.997。

彼此高度相关的特征被称为共线,移除这些特征对中的一个变量通常可以帮助机器学习模型进行概括,并更具可解释性。(我应该指出,我们讨论的是功能与其他功能的相关性,而不是与目标的相关性,这有助于我们的模型!)

有多种方法可以计算要素之间的共线性,其中最常用的一种方法是方差膨胀因子。在这个项目中,我们将使用相关系数来识别和移除共线特征。如果一对特征之间的相关系数大于 0.6,我们将丢弃其中一个特征。对于实现,看一下笔记本(和这个栈溢出答案)

虽然这个值看起来有些武断,但我尝试了几种不同的阈值,这个选择产生了最佳模型。机器学习是一个经验领域,通常是关于实验和发现什么表现最好!在特征选择之后,我们剩下总共 64 个特征和 1 个目标。

# Remove any columns with all na values
features  = features.dropna(axis=1, how = 'all')
print(features.shape)**(11319, 65)**

建立基线

我们现在已经完成了数据清理、探索性数据分析和功能工程。开始建模前的最后一步是建立一个简单的基线。这基本上是一个猜测,我们可以根据它来比较我们的结果。如果机器学习模型没有击败这个猜测,那么我们可能不得不得出结论,机器学习对于这项任务来说是不可接受的,或者我们可能需要尝试一种不同的方法。

对于回归问题,合理的原始基线是猜测测试集中所有示例的训练集目标的中值。这为任何车型设定了相对较低的超越门槛。

我们将使用的指标是 平均绝对误差 (mae) ,它测量预测的平均绝对误差。回归有许多度量标准,但我喜欢吴恩达的建议选择一个单一的度量标准,然后在评估模型时坚持使用它。平均绝对误差易于计算和解释。

在计算基线之前,我们需要将数据分为训练集和测试集:

  1. 特征的训练集是我们在训练期间连同答案一起提供给我们的模型的。目标是让模型学习特征和目标之间的映射。
  2. 特征的测试集用于评估训练好的模型。模型不允许看到测试集的答案,并且必须仅使用特征进行预测。我们知道测试集的答案,因此我们可以将测试预测与答案进行比较。

我们将使用 70%的数据进行培训,30%的数据进行测试:

# Split into 70% training and 30% testing set
X, X_test, y, y_test = train_test_split(features, targets, 
                                        test_size = 0.3, 
                                        random_state = 42)

现在我们可以计算原始基线性能:

**The baseline guess is a score of 66.00
Baseline Performance on the test set: MAE = 24.5164**

在测试集上,天真的估计大约有 25 点的误差。分数范围从 1 到 100,所以这代表了 25%的误差,这是一个很低的超越标准!

结论

在本文中,我们走过了机器学习问题的前三个步骤。定义问题后,我们:

  1. 清理并格式化原始数据
  2. 执行探索性数据分析以了解数据集
  3. 开发了一套将用于我们的模型的功能

最后,我们还完成了建立基线的关键步骤,我们可以根据基线来判断我们的机器学习算法。

第二篇文章(此处可用)将展示如何使用 Scikit-Learn 评估机器学习模型,选择最佳模型,并执行超参数调整以优化模型。第三个岗位,处理模型解释和报告结果,在这里。

一如既往,我欢迎反馈和建设性的批评,可以通过 Twitter @koehrsen_will 联系。

Python 中完整的机器学习演练:第三部分

原文:https://towardsdatascience.com/a-complete-machine-learning-walk-through-in-python-part-three-388834e8804b?source=collection_archive---------3-----------------------

解释机器学习模型并呈现结果

机器学习模型经常被批评为黑箱:我们把数据放在一边,得到答案——通常是非常准确的答案——另一边没有解释。在展示完整的机器学习解决方案的本系列的第三部分中,我们将深入研究我们开发的模型,以尝试并理解它如何进行预测,以及它可以教给我们关于该问题的什么。我们将通过讨论机器学习项目中最重要的部分来结束:记录我们的工作并展示结果。

本系列的第一部分涵盖了数据清理、探索性数据分析、特性工程和特性选择。第二部分涵盖了输入缺失值、实现和比较机器学习模型、使用交叉验证的随机搜索进行超参数调整,以及评估模型。

这个项目的所有代码都在 GitHub 上。第三本 Jupyter 笔记本,对应本帖,在此。我鼓励任何人分享、使用和构建这些代码!

提醒一下,我们正在解决一个监督回归机器学习问题。使用纽约市建筑能源数据,我们开发了一个可以预测建筑能源之星得分的模型。我们构建的最终模型是一个梯度推进回归器,它能够将测试数据的能源之星得分预测到 9.1 分以内(1-100 分)。

模型解释

梯度推进回归变量位于模型可解释性的尺度的中间:整个模型很复杂,但它是由数百个决策树组成的,它们本身是很容易理解的。我们将从三个方面来理解我们的模型是如何进行预测的:

  1. 特征重要性
  2. 可视化单个决策树
  3. LIME:局部可解释的模型不可知解释

前两种方法专门针对树的集合,而第三种方法——正如你可能从名称中猜到的那样——可以应用于任何机器学习模型。LIME 是一个相对较新的包,代表了正在进行的解释机器学习预测的努力中令人兴奋的一步。

特征重要性

特征重要性试图显示每个特征与预测目标任务的相关性。特征重要性的技术细节很复杂(它们测量平均杂质减少量,或因包含特征而减少的误差),但我们可以使用相对值来比较哪些特征最相关。在 Scikit-Learn 中,我们可以从任何基于树的学习者集合中提取特征重要性。

使用model作为我们的训练模型,我们可以使用model.feature_importances_ 找到特征重要性。然后,我们可以将它们放入熊猫数据框架中,并显示或绘制前十个最重要的:

Site EUI ( )能源使用强度)和Weather Normalized Site Electricity Intensity是最重要的特征,占总重要性的 66%以上。在前两个特征之后,重要性显著下降,这表明我们可能不需要保留数据中的所有 64 个特征来实现高性能。(在Jupyter 笔记本中,我看了一下仅使用前 10 个功能的情况,发现该模型并不十分准确。)

基于这些结果,我们终于可以回答我们最初的一个问题:建筑物能源之星得分的最重要指标是站点 EUI 和天气标准化站点电力强度。虽然我们确实希望小心不要过度解读特征重要性,但它们是开始理解模型如何做出预测的有用方式。

可视化单个决策树

虽然整个梯度推进回归可能难以理解,但任何一个单独的决策树都是非常直观的。我们可以使用 Scikit-Learn 函数 [export_graphviz](http://scikit-learn.org/stable/modules/generated/sklearn.tree.export_graphviz.html)来想象森林中的任何一棵树。我们首先从系综中提取一棵树,然后将其保存为点文件:

使用 Graphviz 可视化软件我们可以从命令行将点文件转换成 png 文件:

dot -Tpng images/tree.dot -o images/tree.png

结果是一个完整的决策树:

Full Decision Tree in the Model

这有点让人不知所措!尽管这棵树的深度只有 6(层数),但还是很难理解。我们可以修改对export_graphviz的调用,并将我们的树限制在更合理的深度 2:

Decision Tree Limited to a Depth of 2

树中的每个节点(框)有四条信息:

  1. 这个问题问的是数据点的一个特性的值:这决定了我们是向右还是向左离开节点
  2. mse是节点误差的度量
  3. samples是节点中实例(数据点)的数量
  4. value是节点中所有样本的目标估计值

Individual Node in Decision Tree

(叶节点只有 2 个。–4.因为它们代表最终估计值,并且没有任何子代)。

决策树通过从称为根的顶部节点开始,沿着树向下工作来预测数据点。在每一个节点,数据点会被问一个是或否的问题。例如,上面节点的问题是:建筑物的场地 EUI 是否小于或等于 68.95?如果答案是肯定的,那么该建筑被放置在右边的子节点中,如果答案是否定的,那么该建筑被放置在左边的子节点中。

在树的每一层重复该过程,直到数据点被放置在树的底部的叶节点中(叶节点从小树图像中被裁剪)。对叶节点中所有数据点的预测是value。如果在一个叶节点中有多个数据点(samples),它们都得到相同的预测。随着树的深度增加,训练集上的误差将减少,因为有更多的叶节点,并且示例可以被更精细地划分。然而,太深的树将过度适应训练数据,并且将不能推广到新的测试数据。

在第二篇文章的中,我们调整了许多模型超参数,它们控制着每棵树的各个方面,比如树的最大深度和一个叶节点所需的最小样本数。这两者对欠拟合和过拟合的平衡都有重大影响,可视化单个决策树允许我们看到这些设置如何工作。

虽然我们不能检查模型中的每一棵树,但是查看一棵树可以让我们了解每个学习者如何做出预测。这种基于流程图的方法看起来很像人类做决策的方式,一次回答一个关于单个值的问题。基于决策树的集成将许多单个决策树的预测结合起来,以创建一个更准确、方差更小的模型。树的集合往往非常准确,并且解释起来也很直观。

局部可解释的模型不可知解释(LIME)

我们将探索的试图理解我们的模型如何“思考”的最后一个工具是模型解释领域的一个新入口。 LIME 旨在通过使用线性回归等简单模型在数据点附近局部创建模型的近似来解释来自任何机器学习模型的单个预测。完整细节可在论文中找到。

在这里,我们将使用 LIME 来检查模型完全错误的预测,以了解它可能会告诉我们关于模型为什么会出错的信息。

首先,我们需要找到我们的模型最容易出错的观察结果。我们通过使用模型进行训练和预测,并提取模型误差最大的示例来实现这一点:

**Prediction: 12.8615
Actual Value: 100.0000**

接下来,我们创建 LIME explainer 对象,向它传递我们的训练数据、模式、训练标签和数据中的特性名称。最后,我们要求解释者对象解释错误的预测,传递给它观察和预测函数。

解释这一预测的图表如下:

以下是解释该图的方法:y 轴上的每个条目表示一个变量的一个值,红色和绿色条显示该值对预测的影响。例如,顶部条目显示站点 EUI 大于 95.90,这从预测中减去了大约 40 个点。第二个条目说天气标准化的站点电力强度小于 3.80,这为预测增加了大约 10 分。最终预测是截距项加上这些单独贡献的总和。

我们可以通过调用 explainer .show_in_notebook()方法来查看相同的信息:

# Show the explanation in the Jupyter Notebook
exp.show_in_notebook()

Output from LIME Explainer Object

这通过显示每个变量对预测的贡献,在左侧显示了模型的推理过程。右边的表格显示了数据点变量的实际值。

对于本例,模型预测值约为 12,而实际值为 100!虽然最初这一预测可能令人费解,但通过查看解释,我们可以看到这不是一个极端的猜测,而是给定数据点值的合理估计。该站点 EUI 相对较高,我们预计能源之星得分较低(因为 EUI 与得分高度负相关),这是我们的模型得出的结论。在这种情况下,逻辑是错误的,因为该建筑的满分是 100 分。

当一个模型是错误的时候,它可能是令人沮丧的,但是诸如此类的解释帮助我们理解为什么模型是不正确的。此外,基于这一解释,我们可能想要调查为什么该建筑尽管有如此高的场地 EUI 却得到了满分。也许我们可以了解到一些新的问题,如果不研究这个模型,我们可能会忽略这些问题。诸如此类的工具并不完美,但它们对帮助我们理解模型大有帮助,这反过来可以让我们做出更好的决策。

记录工作和报告结果

任何技术项目中经常被忽视的部分是文档和报告。我们可以做世界上最好的分析,但是如果我们不与清楚地交流结果,那么他们将不会有任何影响!

当我们记录一个数据科学项目时,我们会将所有版本的数据和代码打包,以便其他数据科学家可以复制或构建我们的项目。重要的是要记住,代码被阅读的次数比它被编写的次数要多,我们要确保我们的工作是可以理解的对他人和我们自己如果我们几个月后再回来看的话。这意味着在代码中加入有用的注释,并解释你的推理。我发现 Jupyter 笔记本是一个很好的文档工具,因为它们允许一个接一个的解释和编码。

Jupyter 笔记本也是一个很好的与他人交流发现的平台。使用笔记本扩展,我们可以在我们的最终报告中隐藏代码,因为虽然这很难相信,但并不是每个人都想在一个文档中看到一堆 Python 代码!

就我个人而言,我很难简明扼要地总结我的工作,因为我喜欢浏览所有的细节。然而,重要的是在你演讲的时候理解你的听众并且相应地调整信息。考虑到这一点,以下是我对这个项目的 30 秒总结:

  1. 使用纽约市的能源数据,可以建立一个模型,将建筑物的能源之星得分预测到 9.1 分以内。
  2. 站点 EUI 和天气标准化电力强度是预测能源之星得分的最相关因素。

最初,我被一家初创公司作为筛选工作的“任务”给了这个项目。为了期末报告,他们想看我的工作和结论,所以我做了一个 Jupyter 笔记本上交。然而,我没有在 Jupyter 中直接转换为 PDF,而是将其转换为一个 Latex .tex文件,然后在 texStudio 中编辑,然后渲染为用于最终版本的 PDF。Jupyter 的默认 PDF 输出有一个体面的外观,但它可以通过几分钟的编辑得到显著改善。此外,Latex 是一个强大的文档准备系统,了解基础知识很有好处。

一天结束时,我们的工作的价值取决于它所促成的决策,而能够展示结果是一项至关重要的技能。此外,通过正确记录工作,我们允许其他人复制我们的结果,给我们反馈,以便我们可以成为更好的数据科学家,并为未来建立我们的工作。

结论

在这一系列的帖子中,我们已经走过了一个完整的端到端机器学习项目。我们从清理数据开始,进入模型构建,最后看如何解释机器学习模型。提醒一下,机器学习项目的一般结构如下:

  1. 数据清理和格式化
  2. 探索性数据分析
  3. 特征工程和选择
  4. 在性能指标上比较几种机器学习模型
  5. 对最佳模型执行超参数调整
  6. 评估测试集上的最佳模型
  7. 尽可能解释模型结果
  8. 得出结论,写一份证据充分的报告

虽然具体步骤因项目而异,并且机器学习通常是一个迭代而不是线性过程,但本指南应该在您处理未来的机器学习项目时很好地为您服务。我希望这个系列已经给了你信心,让你能够实现你自己的机器学习解决方案,但是记住,我们没有一个人自己做到这一点!如果你需要任何帮助,有许多令人难以置信的支持社区,你可以在那里寻求建议。

在我的学习过程中,我发现了一些有用的资源:

  • 用 Scikit-Learn 和 Tensorflow 进行动手机器学习 ( 这本书的 Jupyter 笔记本在线免费提供)!
  • 统计学习入门
  • Kaggle:数据科学和机器学习之家
  • Datacamp :练习数据科学编码的入门教程
  • Coursera :许多学科的免费和付费课程
  • Udacity :付费编程和数据科学课程

一如既往,我欢迎反馈和讨论,可以通过 Twitter @koehrsen_will 联系。

关于如何在 Google Colab(免费 GPU)上使用 Keras 微调深度神经网络的全面指南

原文:https://towardsdatascience.com/a-comprehensive-guide-on-how-to-fine-tune-deep-neural-networks-using-keras-on-google-colab-free-daaaa0aced8f?source=collection_archive---------7-----------------------

I like sweet oranges.

在 CPU 上训练深度神经网络比较困难。本教程将指导你如何使用谷歌协作实验室上的 Keras 对 VGG-16 网络进行微调,谷歌协作实验室是一个免费的 GPU 云平台。如果你是谷歌实验室的新手,这是一个适合你的地方,你会学到:

  • 如何在 Colab 上创建您的第一个 Jupyter 笔记本,并使用免费的 GPU。
  • 如何在 Colab 上上传和使用您的自定义数据集。
  • 如何在前景分割领域对 Keras 预训练模型(VGG-16)进行微调。

现在,让我们开始吧…

1.创建您的第一个 Jupyter 笔记本

假设您已经登录了您的 Google 帐户。请遵循以下步骤:

一)。导航至http://drive.google.com。
b)。您将在左侧窗格中看到我的驱动器选项卡。现在,在里面创建一个文件夹,比如说 Colab 笔记本
c)。在已创建的文件夹内的右窗格的其他地方单击右键,选择更多 > 协同实验室。另一个窗口会弹出来,你可以给你的笔记本起个别的名字,比如说 myNotebook.ipynb 。加油!!!您已经在 Colab 上创建了您的第一个笔记本😄

2.为笔记本电脑设置 GPU 加速器

在笔记本中,选择运行时 > 改变运行时类型。将弹出一个窗口。然后,选择您的运行时类型,从硬件加速器下拉菜单中选择 GPU 并保存您的设置(如下图)。

3.将您的自定义数据集上传到 Colab

您已经完成了在 GPU 上运行笔记本的设置。现在,让我们把你的数据集上传到 Colab。在本教程中,我们工作在前景分割,从背景中提取前景物体(下图)。

images are taken from changedetection.net

将数据集上传到 Colab 有几个选项,但是,在本教程中我们考虑两个选项;首先,我们上传到 GitHub 并从它克隆到 Colab,其次,我们上传到 Google Drive 并直接在我们的笔记本上使用。你可以选择任何一个选项。或 b)。下图:

a)。从 GitHub 克隆

让我们将上述数据集克隆到创建的笔记本中。在你笔记本的单元格中,运行!git clone [https://github.com/lim-eren/CDnet2014.git](https://github.com/lim-eren/CDnet2014.git).你会看到这样的东西:

搞定了。让我们列出训练集,看看它是否有效:

开始了。训练集包含 25 个输入帧和 25 个真实帧。跳过部分 b)。并跳转到第 4 节。如果你做到了这一步。

b)。从 Google Drive 下载

另一个选择是将你的数据集上传到 Google Drive,然后从中克隆。假设你已经压缩了上面的训练集,比如说 CDnet2014.zip ,上传到 Google Drive 和 myNotebook.ipynb 在同一个目录下。现在,右键点击cdnet 2014 net . zip>获取可共享链接。复制文件的 id 并将其存储在某个地方(我们稍后会用到)。

然后,通过运行以下代码验证 Colab 以访问 Google Drive。按照链接获取验证码并粘贴到下面的文本框中,然后按 Enter 键。

然后,让我们将 CDnet2014net.zip 文件内容下载到我们的 Jupyter 笔记本中(用上一步获得的 id 替换YOUR_FILE_ID),并通过运行以下代码将其解压缩:

搞定了。您已经将数据集从 Google Drive 下载到 Colab。让我们继续第 4 节使用这个数据集建立一个简单的神经网络。

4.微调你的神经网络

在您的数据集下载到 Colab 后,现在让我们在前景分割域中微调 Keras 预训练模型。请遵循以下步骤:

一)。首先,将该代码片段添加到您的笔记本上,以获得跨机器的可再现结果(请在您笔记本的单元格中运行该代码片段):

b)。创建一个从 Colab 加载数据的函数。该函数返回输入图像(X)和相应的基本事实(Y):

c)。初始一个普通的编码器-解码器模型。我们采用 VGG-16 预训练模型作为编码器,其中所有全连接层都被移除,只有最后一个卷积层(block5_conv3)被微调,其余层被冻结。我们使用转置卷积层来恢复解码器部分的特征分辨率。

因为这是一个二元分类问题,所以使用了binary_crossentropy,网络的输出将是 0 和 1 之间的概率值。这些概率值需要被阈值化,以便获得二进制标签 0 或 1,其中标签 0 表示背景,标签 1 表示前景。

维。我们设定学习率为 5e-4,batch_size 为 1,validation_split 为 0.2,max-epochs 为 100,当验证损失在 5 个时期内停止改善时,将学习率降低 10 倍,当验证损失在 10 个时期内停止改善时,提前停止训练。现在,让我们训练模型。

Training with GPU

一个纪元大约需要 1 秒,太快了!!!在验证集上,最高准确率达到 98%以上。不错吧?现在,让我们暂停一下。我们来对比一下训练有 GPU** 和没有 GPU的速度吧(如果你愿意可以跳过这个对比直接跳到测试部分)。要在没有 GPU 的情况下进行训练,请将硬件加速器设置为无**(参见第 2 节。以上)。这是训练日志。在没有 GPU 的情况下,一个历元需要大约 30 秒,而使用 GPU 训练时只需要 1 秒(大约快 30 倍👏).

Training without GPU

现在,让我们用 Colab GPU 在测试集上测试训练好的模型(你可以运行 *!ls */test/** 来查看带有相应地面实况的测试帧)。

加油!!!对于一个普通的网络,我们只需要使用 25 个training+validation例子就可以达到 98.94% 的测试精度😄。注意,由于训练样本的随机性,你可能会得到和我相似的结果(不完全相同但只有很小的精度差异)。

注意一个问题:我们的模型过度拟合训练数据,解决这个问题是你的工作。提示:使用正规化技术,如辍学、 L2 、批量正规化。

e)。让我们通过运行以下代码来绘制分段掩码:

开始了。分割结果一点都不差!大多数对象边界被错误分类,这个问题主要是由于在训练期间的损失计算中考虑了空标签(对象边界周围的模糊像素)的情况。我们可以通过在损耗中省略这些 void 标签来进一步提高性能。你可以参考这里的或者这里的关于如何做。

test result on CDnet2014 dataset (changedetection.net)

本教程的完整源代码可在 GitHub 中获得。

摘要

在本教程中,您已经学习了如何使用 Google Colab GPU,并以快速的方式训练了网络。您还学习了如何在前景分割领域中微调 Keras 预训练模型,您可能会在未来的研究中发现这一点。

如果你喜欢这个帖子,请随意分享或鼓掌。请过得愉快!🎊😁

卷积神经网络综合指南 ELI5 方法

原文:https://towardsdatascience.com/a-comprehensive-guide-to-convolutional-neural-networks-the-eli5-way-3bd2b1164a53?source=collection_archive---------0-----------------------

人工智能见证了在弥合人类和机器能力之间的差距方面的巨大发展。研究人员和爱好者一样,致力于该领域的许多方面,使惊人的事情发生。许多这样的领域之一是计算机视觉领域。

该领域的目标是使机器能够像人类一样看待世界,以类似的方式感知世界,甚至将这些知识用于多种任务,如图像和视频识别、图像分析和分类、媒体娱乐、推荐系统、自然语言处理等。具有深度学习的计算机视觉的进步已经随着时间的推移而构建和完善,主要是在一种特定的算法上——一种卷积神经网络

准备好尝试自己的卷积神经网络了吗?查看土星云免费计算(包括免费 GPU)。

介绍

A CNN sequence to classify handwritten digits

卷积神经网络(ConvNet/CNN) 是一种深度学习算法,可以接受输入图像,为图像中的各个方面/对象分配重要性(可学习的权重和偏差),并能够区分彼此。与其他分类算法相比,ConvNet 中所需的预处理要低得多。在原始方法中,滤波器是手工设计的,经过足够的训练,ConvNets 有能力学习这些滤波器/特性。

ConvNet 的架构类似于人脑中神经元的连接模式,其灵感来自视觉皮层的组织。单个神经元只在视野中被称为感受野的有限区域内对刺激做出反应。这些区域的集合重叠覆盖了整个可视区域。

为什么 ConvNets 优于前馈神经网络?

Flattening of a 3x3 image matrix into a 9x1 vector

图像不过是像素值的矩阵,对吗?那么,为什么不干脆将图像扁平化(例如,将 3×3 的图像矩阵转化为 9×1 的向量)并将其输入到多级感知器中进行分类呢?哦..不完全是。

在极其基本的二进制图像的情况下,该方法在执行类别预测时可能显示平均精度分数,但是当涉及到整体上具有像素依赖性的复杂图像时,该方法将几乎没有精度。

通过应用相关过滤器,ConvNet 能够成功捕捉图像中的空间和时间相关性。由于所涉及的参数数量的减少和权重的可重用性,该架构对图像数据集执行更好的拟合。换句话说,可以训练网络更好地理解图像的复杂程度。

输入图像

4x4x3 RGB Image

在图中,我们有一个 RGB 图像,它由三个颜色平面(红色、绿色和蓝色)分开。图像存在于许多这样的色彩空间中——灰度、RGB、HSV、CMYK 等。

你可以想象一旦图像达到 8K (7680×4320)的尺寸,计算量会有多大。ConvNet 的作用是将图像简化为一种更容易处理的形式,而不会丢失对获得良好预测至关重要的特征。当我们要设计一个不仅擅长学习特征,而且可扩展到大规模数据集的架构时,这一点很重要。

卷积层—内核

Convoluting a 5x5x1 image with a 3x3x1 kernel to get a 3x3x1 convolved feature

图像尺寸= 5(高)x 5(宽)x 1(通道数,如 RGB)

在上面的演示中,绿色部分类似于我们的 5x5x1 输入图像,I 。卷积层第一部分的卷积运算中涉及的元素称为内核/滤波器,K ,用黄色表示。我们选择了 K 作为一个 3x3x1 的矩阵。

Kernel/Filter, K = 1  0  1
0  1  0
1  0  1

由于步长= 1(非步长),内核移位 9 次,每次在 K 和内核所悬停的图像部分 P 之间执行逐元素 乘法运算( 哈达玛乘积 )。

Movement of the Kernel

过滤器以一定的步幅值向右移动,直到解析完整的宽度。继续前进,它向下跳到具有相同步幅值的图像的开头(左侧),并重复该过程,直到遍历整个图像。

Convolution operation on a MxNx3 image matrix with a 3x3x3 Kernel

在具有多个通道(例如 RGB)的图像的情况下,内核具有与输入图像相同的深度。在 Kn 和 In 栈之间进行矩阵乘法([K1,I1];[K2,I2];[K3,I3]),所有结果与偏差相加,得到一个压缩的单深度通道卷积特征输出。

Convolution Operation with Stride Length = 2

卷积操作的目的是从输入图像中提取高级特征,如边缘。ConvNets 不必仅限于一个卷积层。按照惯例,第一个 ConvLayer 负责捕获边缘、颜色、渐变方向等低级特征。随着图层的增加,该架构也适应了高级功能,为我们提供了一个对数据集中的图像有全面了解的网络,就像我们会做的那样。

该操作有两种类型的结果-一种是与输入相比,卷积特征的维数减少,另一种是维数增加或保持不变。这是通过在前一种情况下应用有效填充,或者在后一种情况下应用相同填充来完成的。

SAME padding: 5x5x1 image is padded with 0s to create a 6x6x1 image

当我们将 5x5x1 图像放大为 6x6x1 图像,然后对其应用 3x3x1 内核时,我们发现卷积矩阵的维数为 5x5x1。因此得名——同垫

另一方面,如果我们在没有填充的情况下执行相同的操作,我们会看到一个矩阵,它具有内核(3x3x1)本身的维度— 有效填充

下面的存储库包含了许多这样的 gif,它们将帮助你更好地理解垫高和步幅长度是如何协同工作以达到我们需要的结果的。

[## vdumoulin/conv 算术

深度学习背景下的卷积算法技术报告——VDU moulin/conv 算法

github.com](https://github.com/vdumoulin/conv_arithmetic)

汇集层

3x3 pooling over 5x5 convolved feature

与卷积层类似,汇集层负责减小卷积要素的空间大小。这是为了通过降维来降低处理数据所需的计算能力。此外,它对于提取旋转和位置不变的主导特征是有用的,从而保持有效训练模型的过程。

有两种类型的池:最大池和平均池。最大池从内核覆盖的图像部分返回最大值。另一方面,平均池返回内核覆盖的图像部分的所有值的平均值。

最大池也表现为噪音抑制。它完全丢弃有噪声的激活,并且在降维的同时执行去噪。另一方面,平均池只是作为一种噪声抑制机制来执行降维。因此,我们可以说最大池比平均池性能好得多。

Types of Pooling

卷积层和汇集层一起形成卷积神经网络的第 I 层。根据图像的复杂性,这种层的数量可以增加,以捕捉更低层次的细节,但代价是更多的计算能力。

在经历了上述过程之后,我们已经成功地使模型理解了特征。接下来,我们将使最终输出变平,并将其输入常规神经网络进行分类。

分类—全连接层(FC 层)

添加全连接层是学习由卷积层的输出表示的高级特征的非线性组合的(通常)廉价方式。全连接层正在学习该空间中可能的非线性函数。

既然我们已经将输入图像转换成适合多层感知器的形式,我们应该将图像展平成一个列向量。平坦化的输出被馈送到前馈神经网络,并且反向传播被应用于训练的每次迭代。在一系列时期内,该模型能够区分图像中的主要特征和某些低级特征,并使用 Softmax 分类技术对其进行分类。

有各种可用的 CNN 架构,它们是构建算法的关键,在可预见的未来,这些算法将作为一个整体为 AI 提供动力。其中一些列举如下:

  1. LeNet
  2. AlexNet
  3. VGGNet
  4. 谷歌网
  5. 雷斯内特
  6. ZFNet

GitHub 笔记本——使用 TensorFlow 的 MNIST 数据集识别手写数字

[## ss-is-master-chief/MNIST 数字。识别器-CNN

CNN 识别运行 10 个时期的手写数字(MNIST)的实现。准确率:98.99% …

github.com](https://github.com/ss-is-master-chief/MNIST-Digit.Recognizer-CNNs)

准备好尝试自己的卷积神经网络了吗?查看土星云免费计算(包括免费 GPU)。

多维数据有效可视化的图形语法综合指南

原文:https://towardsdatascience.com/a-comprehensive-guide-to-the-grammar-of-graphics-for-effective-visualization-of-multi-dimensional-1f92b4ed4149?source=collection_archive---------3-----------------------

了解利用图形框架的分层语法实现有效数据可视化的有效策略

介绍

可视化多维数据是一门艺术,也是一门科学。由于我们的二维(2-D)渲染设备的限制,随着维度数量的增加,在两个以上的数据维度(属性或特征)上构建有效的可视化变得具有挑战性。在我之前的一篇文章 【多维数据有效可视化的艺术】 中,我们已经广泛地介绍了有效的多维数据可视化的一些策略,并提供了实际操作的例子。在本文中,我们将介绍我们用来构建这些可视化的分层框架,称为‘图形的语法’。我们还将探索图形框架分层语法背后的基本概念,并讨论我们如何使用每个特定的分层组件在多维数据上构建有效的可视化。示例将用 Python 展示,但是,如果您感兴趣,您可以轻松地用 R 复制相同的内容。

动机

数据可视化和讲故事一直是任何数据科学管道中最重要的阶段之一,涉及到从数据中提取有意义的见解,不管数据或项目有多复杂。举个简单的例子 【十几只雷龙】——下图描绘了十二个不同的数据集。

你能猜出这些看起来非常不同的数据集之间的共同点吗?

The Datasaurus Dozen — What is common among these diverse datasets?

答:所有数据集的汇总统计数据完全相同!

这是著名的安斯科姆四重奏的有趣变体,你们很多人可能都很熟悉,如下图所示。

Anscombe’s quartet — Different datasets with same summary statistics

这些演示的关键要点是,“不要盲目相信你的数据,开始根据你的数据建模”。汇总统计数据总是具有欺骗性。在继续进行特征工程和构建统计、机器学习和深度学习模型之前,请始终可视化和理解您的数据属性。

另一个非常重要的动机来源,特别是对于有效的数据可视化,可以从几个世纪前的一些优秀案例研究中获得,当时我们甚至没有计算机,更不用说 Python 或 R!第一幅是约翰·斯诺著名的可视化作品,描绘了 1854 年英国伦敦爆发的宽街霍乱!

Visualizing the Broad Street Cholera outbreak which helped find the root cause of the disease outbreak!

你可以看到一个简单的手绘可视化是如何帮助找到 19 世纪 50 年代宽街霍乱爆发的根本原因的。另一个有趣的可视化是由现代护理实践之母佛罗伦萨南丁格尔建立的,她对护理和统计有着根深蒂固的兴趣。

Causes of Mortality in the Army of the East — Florence Nightingale

上图描绘了一个极区图,描述了 19 世纪 50 年代军队中的死亡原因。我们可以看到,这一可视化绝对不是简单化的,但它传达了正确的见解——清楚地显示了士兵死于可预防疾病的比例,这些疾病基于伤口或其他原因。这应该为有效的数据可视化提供足够的动力!

理解图形的语法

为了理解图形的语法,我们需要理解语法是什么意思。下图简要总结了这两个方面。

基本上,图形语法是一个框架,它遵循分层的方法,以结构化的方式描述和构建可视化或图形。涉及多维数据的可视化通常有多个组件或方面,利用这种分层的图形语法有助于我们描述和理解可视化中涉及的每个组件——在数据、美学、比例、对象等方面。

图形框架的原始语法是由 Leland Wilkinson 提出的,它详细地涵盖了与有效数据可视化相关的所有主要方面。我肯定会推荐感兴趣的读者去看看这本书,只要他们有机会!

[## 图形的语法|利兰·威尔金森|斯普林格

第一版序言在 1980 年代为 SYSTAT 编写图形之前,我首先讲授了一个关于…

www.springer.com](https://www.springer.com/in/book/9780387245447)

然而,我们将使用它的一个变体——称为图形框架的分层语法,它是由著名的数据科学家 Hadley Wickham 提出的,他也是著名的 R visualization 软件包[**ggplot2**](https://ggplot2.tidyverse.org/)的创建者。读者应该看看他的论文,标题是 【图形的分层语法】 ,其中详细介绍了他提出的图形分层语法,还谈到了他为 R 编程语言构建的开源实现框架**ggplot2**

[## 图形的分层语法

图形语法是一种工具,它使我们能够简明地描述图形的组成部分。这样的语法…

vita.had.co.nz](http://vita.had.co.nz/papers/layered-grammar.html)

哈德利的图形分层语法使用几个分层组件来描述任何图形或可视化。最值得注意的是,它与威尔金森提出的原始图形语法有一些不同,如下图所示。

Mapping between components of Wilkinson’s grammar (left) and the layered grammar (right)

你可以看到语法中有各种各样的成分,可以用来建立和描述可视化。我已经确定了 七个 这样的主要组件,它们通常帮助我在多维数据上建立有效的可视化。下图显示了语法中每个特定组件的一些细节。

Major components of the Grammar of Graphics

我们用一个金字塔架构来展示组件的内在分层结构。通常,为了用一个或多个维度构建或描述任何可视化,我们可以使用如下组件。

  1. 数据:始终从数据开始,确定你想要可视化的维度。
  2. 美观:根据数据尺寸,图中各数据点的位置确定轴。还要检查是否需要任何形式的编码,包括大小、形状、颜色等等,这些对于绘制多个数据维度都很有用。
  3. 标度:我们是否需要对潜在值进行标度,用一个特定的标度来表示多个值或一个范围?
  4. 几何对象:这些通常被称为“几何对象”。这将涵盖我们在可视化上描绘数据点的方式。应该是点,条,线之类的?
  5. 统计:我们是否需要在可视化中显示一些统计度量,如集中趋势、扩散、置信区间的度量?
  6. Facets: 我们需要根据特定的数据维度创建支线剧情吗?
  7. 坐标系:可视化应该基于哪种坐标系——是笛卡尔坐标系还是极坐标坐标系?

现在,我们将通过一些实际操作的例子来看看如何利用这个分层框架来为多维数据构建有效的数据可视化。

动作图形的语法

现在,我们将把我们在上一节中学到的概念应用到一些实际数据上。我们将使用 Python 来构建我们所有的可视化,但是我也推荐人们查看 R 中的**ggplot2** 包,这是迄今为止最鼓舞人心的框架之一,用于构建漂亮和干净的出版物质量的可视化。我们确实有一个用 Python 编写的[**ggplot**](http://ggplot.yhathq.com) 框架,它是由 Yhat,Inc. 构建的。但是,如果你检查一下存储库,在过去的两年里没有提交或更新,不幸的是,这导致了一些错误,特别是由于与**pandas**的新版本的向后不兼容问题。因此,为了模拟 Python 中图形语法的真正分层语法,我们将使用另一个有趣的框架[**plotnine**](https://plotnine.readthedocs.io/en/stable/)

[## Python - plotnine 0.4.0 文档的图形语法

plotnine 是 Python 中图形语法的一个实现,它基于 ggplot2。该语法允许用户…

plotnine.readthedocs.io](https://plotnine.readthedocs.io/en/stable/)

Plotnine 是基于**ggplot2**的图形框架分层语法的开源 Python 实现。因此,使用这个分层语法中先前指定的组件,我们可以构建有效的可视化。

从数据开始

我们总是从加载并查看我们想要分析和可视化的数据集开始。我们将使用著名的[**mtcar**](https://stat.ethz.ch/R-manual/R-devel/library/datasets/html/mtcars.html)**s** 数据集作为**plotnine**中预加载的数据集之一。

mtcars 数据集由从 1974 年美国杂志《汽车趋势中提取的数据组成,描述了 32 款汽车(1973-74 款)的油耗和汽车设计及性能的 10 个其他属性。上图中描述了每个属性的详细信息。让我们现在建立一些可视化。

可视化二维(2d)

我们现在可以使用图形框架的分层语法中的一些组件(包括数据、比例、美学和几何图形)来可视化高达二维的数据。在这种情况下,我们为几何对象选择一个点或散点图来表示每个数据点。

从上面的可视化中我们可以清楚的看到**mpg** 和猫**wt**是负相关的。

三维可视化

为了从我们的数据集中可视化三维,我们可以利用颜色作为我们的美学组件之一,来可视化除了其他两个维度之外的一个额外的维度,如下例所示。

在上面的可视化中,我们使用颜色美学以及其他两个数据维度(变量)将具有不同数量档位的汽车描述为单独的类别。很明显,平均而言,**gears** 数较少的汽车往往**wt** 较高,而**mpg**较低。

可视化四维(四维)

为了从我们的数据集中可视化四维,除了包括几何图形、数据和比例在内的其他常规组件之外,我们还可以利用颜色和大小作为我们的两个美学要素。

可视化向我们展示了美学在帮助我们在单个绘图中可视化多个数据维度方面有多么强大。很明显,**cyl**(气缸)数量较高的汽车的**gears**数量较低,反过来,它们的**wt**较高而**mpg**较低。

或者,我们也可以使用颜色和刻面来描述四维数据,而不是大小,如下例所示。

刻面无疑是构建有效数据可视化的最强大的组件之一,如上面的可视化所示,我们可以清楚地看到具有较高**cyl**计数的汽车具有较低的**gear**计数,并且趋势与之前的颜色和尺寸可视化相似。

可视化数据维度和统计数据

为了可视化数据维度和一些相关的统计数据(比如拟合线性模型),我们可以在分层语法中利用统计数据和其他组件。

这使我们能够看到基于**wt****mpg**的线性模型趋势。

可视化五维空间

要在五维空间中可视化数据,您现在已经知道该如何操作了!我们将利用美学的力量,包括颜色、尺寸和小平面。

这里我们用**am**作为刻面,其中 0 表示自动挡的车,1 表示手动挡的车。该图显示,与自动变速器的汽车相比,手动变速器的汽车具有更高的档位数量。此外,大多数气缸数量较多的汽车(**cyl**)都配有自动变速器。其他见解与我们在前面的情节中观察到的相似。

可视化六维(6-D)

为了在六个维度上可视化数据,我们可以在 y 轴上添加一个额外的面,在 x 轴上添加一个面,并添加颜色和大小作为美观。

我们将变速器(**am**)表示为 0(自动)和 1(手动),作为在 y 轴上的一个小平面,将化油器数量(**carb**)表示为在 x 轴上的一个小平面,此外,使用与我们之前的绘图类似的其他美学来表示其他尺寸。从上面的图像中可以看出一个有趣的现象,档位较多的汽车有手动变速器(**am**)和较多的化油器(**carb**)。你注意到其他有趣的见解了吗?

我们能再高点吗?

紧迫的问题是,我们能超越六维吗?当然,突破二维渲染设备的限制来可视化更多的数据维度肯定会变得越来越困难。

一种方法是使用更多的面和支线剧情。除此之外,如果数据集具有时间方面,也可以使用时间的概念,如下例所示。

Hans Rosling’s famous visualization of global population, health and economic indicators

这描绘了 汉斯·罗斯林的 著名的描绘全球各国人口、健康和各种经济指标的可视化作品。这也在 官方 ted 大会 上展示过,如果大家还没做过,我推荐大家去看看!

这将为您提供一个很好的视角,让您了解如何利用图形的分层语法来可视化多维数据。

结论

正如我一再提到的,数据可视化既是一门科学,也是一门艺术。本文将为您提供足够的动力和示例,让您开始理解和利用图形框架的分层语法,在多维数据上构建自己的有效可视化。

本文中使用的所有代码都可以作为 Jupyter 笔记本 以及其他内容和幻灯片在 my GitHub 资源库 中获得。

[## 数据可视化艺术

多维数据的有效可视化艺术

github.com](https://github.com/dipanjanS/art_of_data_visualization)

我确实讲述了如何在稍微复杂一些的数据上使用 Python 中最先进的数据可视化框架(如**seaborn****matplotlib**)来可视化多维数据。如果你有兴趣,下面的文章 中的 应该可以帮你入门。

[## 多维数据的有效可视化艺术

有效数据可视化的策略

towardsdatascience.com](/the-art-of-effective-visualization-of-multi-dimensional-data-6c7202990c57)

我最近在 2018 年 ODSC的一次会议上谈到了这些文章的主要部分。你可以在这里查看 完整的演讲议程和幻灯片 。一旦发布,我会在 YouTube 上发布这次会议的演讲!

[## 多维数据的有效可视化艺术-实践方法- ODSC 印度…

描述性分析是与数据科学项目或…相关的任何分析生命周期的核心组成部分之一

confengine.com](https://confengine.com/odsc-india-2018/proposal/6846/the-art-of-effective-visualization-of-multi-dimensional-data-a-hands-on-approach)

有反馈给我吗?或者有兴趣与我一起从事研究、数据科学、人工智能,甚至发表一篇关于 TDS 的文章?可以在LinkedIn上联系我。

[## Dipanjan Sarkar -数据科学家-英特尔公司| LinkedIn

查看 Dipanjan Sarkar 在世界最大的职业社区 LinkedIn 上的个人资料。Dipanjan 有 6 份工作列在…

www.linkedin.com](https://www.linkedin.com/in/dipanzan/)

感谢 杜巴 编辑本文。

在深度学习中通过真实世界的应用转移学习的综合实践指南

原文:https://towardsdatascience.com/a-comprehensive-hands-on-guide-to-transfer-learning-with-real-world-applications-in-deep-learning-212bf3b2f27a?source=collection_archive---------0-----------------------

用知识转移的力量进行深度学习!

Source: Pixabay

介绍

人类有跨任务传递知识的天生能力。我们在学习一项任务时获得的知识,我们以同样的方式用来解决相关的任务。任务越相关,我们就越容易转移或交叉利用我们的知识。一些简单的例子是,

  • 知道如何骑摩托车⮫学习如何骑汽车
  • 知道如何演奏古典钢琴⮫学习如何演奏爵士钢琴
  • 了解数学和统计⮫学习机器学习

在上述每个场景中,当我们试图学习新的方面或主题时,我们不会从头开始学习一切。我们从过去学到的知识中转移和利用我们的知识!

到目前为止,传统的机器学习和深度学习算法一直被设计为孤立工作。这些算法被训练来解决特定的任务。一旦特征空间分布发生变化,就必须从头开始重建模型。迁移学习是克服孤立的学习范式,利用从一项任务中获得的知识来解决相关任务的思想。在本文中,我们将全面介绍迁移学习的概念、范围和实际应用,甚至展示一些实际例子。更具体地说,我们将涉及以下内容。

  • 迁移学习的动机
  • 理解迁移学习
  • 迁移学习策略
  • 深度学习的迁移学习
  • 深度迁移学习策略
  • 深度迁移学习的类型
  • 迁移学习的应用
  • 案例研究 1:具有数据可用性约束的图像分类
  • 案例研究 2:具有大量类别和较少数据可用性的多类别细粒度图像分类
  • 转移学习优势
  • 转移学习挑战
  • 结论&未来范围

我们将把迁移学习视为一个通用的高级概念,它始于机器学习和统计建模的时代,然而,在本文中,我们将更专注于深度学习。

注意:所有案例研究将逐步涵盖代码和输出的细节。这里描述的案例研究及其结果完全基于我们在编写本书时实施和测试这些模型时进行的实际实验: 用 Python 进行迁移学习 (细节在本文末尾)。

鉴于网络上的信息过载,本文旨在尝试涵盖理论概念,并在一个地方展示深度学习应用的实际动手示例。所有的例子都将包含在 Python 中,使用 keras 和 tensorflow 后端,这是老手或刚开始深度学习的人的完美匹配!对 PyTorch 感兴趣?请随意转换这些例子并联系我,我会在这里和 GitHub 上展示你的作品!

迁移学习的动机

我们已经简单地讨论过,人类不会从头开始学习所有的东西,也不会利用和转移他们以前学习领域的知识到新的领域和任务中。鉴于对 真正的人工智能 的狂热,数据科学家和研究人员认为迁移学习可以进一步推动我们朝着的方向前进。事实上, 吴恩达 ,知名教授和数据科学家,一直与谷歌大脑、百度、斯坦福和 Coursera 有联系,最近在 NIPS 2016 上给出了一个惊人的教程,名为‘使用深度学习构建 AI 应用的基本要素’,他提到**

监督学习之后——迁移学习将是 ML 商业成功的下一个驱动力

推荐有兴趣的乡亲们去看看 NIPS 2016 的 他的有趣教程

事实上,迁移学习并不是 21 世纪 10 年代才出现的概念。神经信息处理系统(NIPS) 1995 年研讨会学会学习:归纳系统中的知识巩固和转移被认为为该领域的研究提供了最初的动力。从那以后,学会学习知识巩固归纳迁移等术语就和迁移学习互换使用了。不变的是,不同的研究人员和学术文本从不同的背景下提供定义。Goodfellow 等人在他们的名著深度学习中提到了泛化背景下的迁移学习。它们的定义如下:

在一种情况下学到的东西被用来在另一种情况下提高概括能力。

因此,关键的动机,尤其是考虑到深度学习的背景,是这样一个事实,即解决复杂问题的大多数模型需要大量的数据,考虑到标记数据点所花费的时间和精力,为监督模型获取大量的标记数据可能非常困难。一个简单的例子是 ImageNet 数据集 ,它拥有数百万张属于不同类别的图像,这要归功于从斯坦福开始的多年努力!

The popular ImageNet Challenge based on the ImageNet Database

然而,为每个领域获取这样的数据集是困难的。此外,大多数深度学习模型都非常专门针对特定领域甚至特定任务。虽然这些可能是最先进的模型,具有非常高的准确性,并超越了所有基准,但它只会在非常特定的数据集上使用,当用于新任务时,性能最终会大幅下降,而新任务可能仍然与它接受训练的任务相似。这形成了迁移学习的动机,它超越了特定的任务和领域,并试图了解如何利用来自预训练模型的知识,并使用它来解决新问题!

理解迁移学习

这里要记住的第一件事是,迁移学习并不是一个新的概念,它对于深度学习来说是非常具体的。建立和训练机器学习模型的传统方法与使用遵循迁移学习原则的方法之间存在明显的差异。

Traditional Learning vs Transfer Learning

传统的学习是孤立的,纯粹基于特定的任务、数据集和在其上训练单独的孤立模型而发生。没有保留可以从一个模型转移到另一个模型的知识。在迁移学习中,您可以利用以前训练的模型中的知识(特征、权重等)来训练新的模型,甚至解决新任务中数据较少的问题!

让我们借助一个例子来理解前面的解释。假设我们的任务是在一家餐馆的限定区域内识别图像中的物体。让我们将这个任务在其定义的范围内标记为。给定此任务的数据集,我们训练一个模型并对其进行调整,使其在来自同一域(餐馆)的看不见的数据点上表现良好(一般化)。当我们没有足够的训练样本来完成特定领域的任务时,传统的监督 ML 算法就会失效。假设,我们现在必须从公园或咖啡馆的图像中检测物体(比方说,任务 T2 )。理想情况下,我们应该能够应用为 T1 训练的模型,但在现实中,我们面临着性能下降和不能很好概括的模型。这种情况的发生有多种原因,我们可以将其统称为模型对训练数据和领域的偏好。

迁移学习应该使我们能够利用以前学习的任务中的知识,并将它们应用到更新的相关任务中。如果我们对于任务有明显更多的数据,我们可以利用它的学习,并且对于任务(其具有明显更少的数据)概括这种知识(特征、权重)。在计算机视觉领域中的问题的情况下,某些低级特征,例如边缘、形状、拐角和强度,可以在任务之间共享,从而实现任务之间的知识转移!此外,正如我们在前面的图中所描述的,当学习新的目标任务时,来自现有任务的知识作为额外的输入。**

形式定义

现在让我们来看看迁移学习的正式定义,然后利用它来理解不同的策略。在他们的论文、、中,潘和杨用领域、任务和边际概率提出了一个理解迁移学习的框架。该框架定义如下:

一个域, D ,定义为由特征空间、【ꭕ】和边际概率、p(χ)组成的二元元组,其中χ为样本数据点。因此,我们可以在数学上把定义域表示为 D = {ꭕ,p(χ)}****

这里的表示如上所述的特定向量。另一方面,一个任务, T 可以定义为标签空间的二元元组, γ ,以及目标函数,【η。从概率的角度,目标函数也可以表示为P(γ|χ)。****

因此,有了这些定义和表述,我们可以如下定义迁移学习,这要感谢 Sebastian Ruder 的一篇优秀文章。

情节

基于我们之前的定义,现在让我们来看看涉及迁移学习的典型场景。

为了更清楚地说明术语 领域任务 之间的区别,下图试图用一些例子来解释它们。

关键要点

正如我们到目前为止所看到的,迁移学习就是在目标任务中利用源学习者的现有知识的能力。在迁移学习过程中,必须回答以下三个重要问题:

  • ****转什么:这是整个流程的第一步,也是最重要的一步。为了提高目标任务的绩效,我们试图寻找关于哪部分知识可以从源转移到目标的答案。当试图回答这个问题时,我们试图确定知识的哪一部分是源特定的,以及源和目标之间的共同点。
  • ****何时转移:有些情况下,为了转移知识而转移知识可能会比改善任何事情都更糟糕(也称为负迁移)。我们应该致力于利用迁移学习来提高目标任务的绩效/结果,而不是降低它们。我们需要小心什么时候转移,什么时候不转移。
  • 如何转移:**一旦回答了什么何时,我们就可以继续确定跨领域/任务实际转移知识的方法。这涉及到对现有算法和不同技术的更改,我们将在本文后面的部分中讨论。此外,为了更好地理解如何转移,最后列出了具体的案例研究。**

这应该有助于我们定义迁移学习可以应用的各种场景和可能的技术,我们将在下一节讨论。

迁移学习策略

有不同的迁移学习策略和技术,可以根据领域、手头的任务和数据的可用性来应用。我非常喜欢我们之前提到的关于迁移学习的论文中的下图, 迁移学习调查

Transfer Learning Strategies

因此,根据上图,迁移学习方法可以根据所涉及的传统 ML 算法的类型进行分类,例如:

  • ****归纳迁移学习:在这个场景中,源域和目标域是相同的,但是源任务和目标任务是不同的。这些算法试图利用源域的归纳偏差来帮助改进目标任务。根据源域是否包含标记数据,这可以进一步分为两个子类别,分别类似于多任务学习和自学学习。
  • ****无监督迁移学习:这种设置类似于归纳迁移本身,重点是目标领域的无监督任务。源域和目标域相似,但任务不同。在这种情况下,标记的数据在任一域中都不可用。
  • ****直推式迁移学习:在这种情景中,源任务和目标任务有相似之处,但对应的域不同。在此设置中,源域有许多标记数据,而目标域没有。这可以进一步分类为子类别,指的是特征空间不同或边际概率不同的设置。

我们可以在下表中总结上述每种技术的不同设置和场景。

Types of Transfer Learning Strategies and their Settings

上一节讨论的三个迁移类别概述了迁移学习可以应用的不同环境,并对其进行了详细研究。要回答在这些类别之间传递什么的问题,可以采用以下一些方法:

  • ****实例转移:将知识从源领域重用到目标任务通常是一个理想的场景。在大多数情况下,源域数据不能直接重用。相反,源域中的某些实例可以与目标数据一起重用,以改善结果。在归纳迁移的情况下,如戴和他们的合作者的 AdaBoost 等修改有助于利用来自源域的训练实例来改进目标任务。
  • ****特征表示转移:这种方法旨在通过识别可以从源域利用到目标域的良好特征表示,来最小化域差异并降低错误率。根据标注数据的可用性,可对基于要素制图表达的传输应用监督或非监督方法。
  • ****参数转移:这种方法基于相关任务的模型共享一些参数或超参数的先验分布的假设。与同时学习源任务和目标任务的多任务学习不同,对于迁移学习,我们可以对目标域的损失应用额外的权重来提高整体表现。
  • ****关系型知识转移:与前面三种方法不同,关系型知识转移试图处理非 IID 数据,比如非独立同分布的数据。换句话说,数据,其中每个数据点都与其他数据点有关系;例如,社交网络数据利用关系知识转移技术。

下表清楚地总结了不同迁移学习策略之间的关系以及要迁移什么。

Transfer Learning Strategies and Types of Transferable Components

现在让我们利用这种理解,了解迁移学习如何应用于深度学习的环境中。

面向深度学习的迁移学习

我们在上一节中讨论的策略是可以应用于机器学习技术的一般方法,这使我们产生了一个问题,迁移学习真的可以应用于深度学习的环境中吗?

深度学习模型是又被称为 归纳学习 的代表。归纳学习算法的目标是从一组训练样本中推断出一个映射。例如,在分类的情况下,模型学习输入要素和类标签之间的映射。为了让这样的学习器能够很好地对看不见的数据进行归纳,它的算法使用了一组与训练数据的分布相关的假设。这几组假设被称为 感应偏置 。归纳偏差或假设可以由多个因素来表征,例如它所限制的假设空间和通过假设空间的搜索过程。因此,这些偏差会影响模型在给定任务和领域中学习的方式和内容。

Ideas for deep transfer learning

归纳迁移技术 利用源任务的归纳偏差来辅助目标任务。这可以通过不同的方式来实现,例如通过限制模型空间来调整目标任务的归纳偏差,缩小假设空间,或者在来自源任务的知识的帮助下对搜索过程本身进行调整。下图直观地描述了这一过程。

Inductive transfer (Source: Transfer learning, Lisa Torrey and Jude Shavlik)

除了归纳迁移,归纳学习算法还利用贝叶斯和分层迁移技术来帮助改进学习和目标任务的执行。

深度迁移学习策略

深度学习近年来取得了长足的进步。这使我们能够解决复杂的问题并取得惊人的成果。然而,这种深度学习系统所需的训练时间和数据量要比传统的 ML 系统多得多。有各种各样的深度学习网络,它们具有最先进的性能(有时与人类的性能一样好,甚至更好),已经在计算机视觉和自然语言处理(NLP)等领域进行了开发和测试。在大多数情况下,团队/人员共享这些网络的详细信息,供他人使用。这些预先训练的网络/模型形成了深度学习背景下迁移学习的基础,或者我喜欢称之为 【深度迁移学习】 。让我们看看深度迁移学习的两个最流行的策略。

现成的预训练模型作为特征提取器

深度学习系统和模型是分层的架构,在不同的层学习不同的特征(分层特征的分层表示)。然后,这些层最终连接到最后一层(在监督学习的情况下,通常是完全连接的层),以获得最终输出。这种分层架构允许我们利用预训练的网络(如 Inception V3 或 VGG ),而无需其最终层作为其他任务的固定特征提取器。

Transfer Learning with Pre-trained Deep Learning Models as Feature Extractors

这里的关键思想是仅利用预训练模型的加权层来提取特征,而不是在为新任务训练新数据的过程中更新模型层的权重。

例如,如果我们在没有最终分类层的情况下使用 AlexNet,它将帮助我们根据隐藏状态将新领域任务中的图像转换为 4096 维向量,从而使我们能够利用来自源领域任务的知识从新领域任务中提取特征。这是使用深度神经网络执行迁移学习的最广泛使用的方法之一。

现在可能会出现一个问题,这些预先训练好的现成功能在不同任务中的实际效果如何?

在现实世界的任务中,它看起来确实工作得很好,如果上表中的图表不是很清楚,下面的图应该会使事情更加清楚,关于他们在不同的基于计算机视觉的任务中的表现!

Performance of off-the-shelf pre-trained models vs. specialized task-focused deep learning models

根据上图中的红色和粉红色条,您可以清楚地看到,预训练模型的功能始终优于非常专业的以任务为重点的深度学习模型。

微调现成的预培训模型

这是一个更复杂的技术,我们不仅替换最后一层(用于分类/回归),而且我们还选择性地重新训练一些先前的层。深度神经网络是具有各种超参数的高度可配置的架构。正如前面所讨论的,最初的层被认为是捕捉一般的特征,而后来的层更关注手边的特定任务。下图描述了一个人脸识别问题的例子,网络的初始低层学习非常一般的特征,而高层学习非常特定的任务特征。

利用这种洞察力,我们可以在重新训练时冻结(固定权重)某些层,或者微调其余层以满足我们的需要。在这种情况下,我们利用网络整体架构方面的知识,并使用其状态作为我们再训练步骤的起点。这反过来帮助我们用更少的培训时间获得更好的表现。

冻结还是微调?

这就给我们带来了一个问题,我们应该冻结网络中的图层以将其用作特征提取器,还是也应该在此过程中微调图层?

这应该给我们一个很好的视角,让我们了解这些策略是什么,以及何时应该使用它们!

预训练模型

迁移学习的一个基本要求是要有在源任务中表现良好的模型。幸运的是,深度学习世界相信分享。他们各自的团队已经公开分享了许多最先进的深度学习架构。这些跨越了不同的领域,例如计算机视觉和 NLP,这是深度学习应用中最受欢迎的两个领域。预训练模型通常以模型在被训练到稳定状态时获得的数百万个参数/权重的形式被共享。每个人都可以通过不同的方式使用预先训练好的模型。著名的深度学习 Python 库 keras 提供了下载一些流行模型的接口。你也可以从网上获得预先训练好的模型,因为大多数模型都是开源的。

对于计算机视觉 ,可以利用一些流行的模型包括,

  • VGG-16
  • VGG-19
  • 盗梦空间 V3
  • 异常
  • ResNet-50

对于自然语言处理 任务,由于 NLP 任务的多变性质,事情变得更加困难。您可以利用单词嵌入模型,包括:

  • Word2Vec
  • 手套
  • 快速文本

但是等等,还没完呢!最近,在自然语言处理的迁移学习方面有了一些很好的进展。最值得注意的是,

  • 谷歌通用句子编码器
  • 谷歌的变压器(BERT)双向编码器表示法

它们肯定很有前途,我相信它们很快会被广泛应用于现实世界。

深度迁移学习的类型

关于迁移学习的文献已经经历了多次反复,正如本章开始时提到的,与迁移学习相关的术语一直被不严格地使用,而且经常互换。因此,有时很难区分迁移学习领域适应多任务学习。放心,这些都是有关联的,并试图解决类似的问题。总的来说,你应该总是把迁移学习看作一个一般的概念或原则,在这里我们将尝试使用源任务领域的知识来解决一个目标任务。

领域适应

领域自适应通常指源领域和目标领域之间的边际概率不同的场景,例如【p(xₛ】≠p(xₜ)。源域和目标域的数据分布存在固有的偏移或漂移,需要调整以转移学习。例如,标记为正面或负面的电影评论的语料库将不同于产品评论情感的语料库。如果用于对产品评论进行分类,根据电影评论情感训练的分类器将看到不同的分布。因此,在这些场景中,领域适应技术被用于迁移学习。

领域混淆

我们学习了不同的迁移学习策略,甚至讨论了从源到目标迁移知识的内容、时间和方式这三个问题。特别是,我们讨论了特征表征转移是如何有用的。值得重复的是,深度学习网络中的不同层捕获不同的特征集。我们可以利用这个事实来学习领域不变特征,并提高它们跨领域的可移植性。我们不允许模型学习任何表示,而是推动两个领域的表示尽可能地相似。这可以通过将某些预处理步骤直接应用于表示本身来实现。其中一些已经由孙、贾士丰和 Kate Saenko 在他们的论文【】【易域改编的回归】 中讨论过。Ganin 等人也提出了这种对表示相似性的推动。艾尔。在他们的论文中, 【神经网络的领域对抗训练】 。这种技术背后的基本思想是向源模型添加另一个目标,通过混淆领域本身来鼓励相似性,因此产生了领域混淆。**

多任务学习

多任务学习与迁移学习略有不同。在多任务学习的情况下,几个任务被同时学习,而不区分源和目标。在这种情况下,学习者一次接收关于多个任务的信息,与学习者最初不知道目标任务的迁移学习相比。下图对此进行了描述。

Multitask learning: Learner receives information from all tasks simultaneously

一次性学习

深度学习系统天生就需要数据,因此它们需要许多训练样本来学习权重。这是深度神经网络的一个限制因素,尽管人类学习并非如此。例如,一旦给孩子看了苹果的样子,他们可以很容易地识别不同种类的苹果(用一个或几个训练例子);而 ML 和深度学习算法却不是这样。一次性学习是迁移学习的一种变体,我们试图根据一个或几个训练例子来推断所需的输出。这在现实世界中很有帮助,在现实世界中,不可能为每个可能的类都标记数据(如果这是一个分类任务),在现实世界中,可以经常添加新的类。飞飞和他们的合著者的里程碑式的论文 【一次学习的对象类别】 ,被认为是创造了一次学习这个术语和这个子领域的研究。提出了一种基于贝叶斯框架的物体分类表示学习方法。这种方法后来得到了改进,并使用深度学习系统进行了应用。

零射击学习

零射击学习是迁移学习的另一个极端变体,它依赖于没有标记的例子来学习一项任务。这听起来可能难以置信,尤其是当使用例子学习是大多数监督学习算法的内容时。零数据学习或零短期学习方法,在训练阶段本身进行巧妙的调整,以利用额外的信息来理解看不见的数据。在他们关于深度学习的书中,Goodfellow 和他们的合著者将零射击学习呈现为学习三个变量的场景,例如传统的输入变量 x ,传统的输出变量 y ,以及描述任务的附加随机变量 T 。从而训练模型学习 P(y | x,T) 的条件概率分布。零镜头学习在机器翻译等场景中很方便,在这些场景中,我们甚至可能没有目标语言的标签。

迁移学习的应用

深度学习无疑是已经被用来非常成功地收获迁移学习的好处的算法的特定类别之一。以下是几个例子:

  • ****NLP 的迁移学习:当涉及到 ML 和深度学习时,文本数据呈现出各种各样的挑战。这些通常使用不同的技术进行转换或矢量化。已经使用不同的训练数据集准备了嵌入,例如 Word2vec 和 FastText。通过转移来自源任务的知识,它们被用在不同的任务中,例如情感分析和文档分类。除此之外,像通用句子编码器和 BERT 这样的新模型无疑为未来提供了无数的可能性。
  • ****音频/语音的迁移学习:类似于 NLP 和计算机视觉等领域,深度学习已经成功用于基于音频数据的任务。例如,为英语开发的自动语音识别(ASR)模型已经成功地用于提高其他语言(如德语)的语音识别性能。此外,自动说话人识别是迁移学习有很大帮助的另一个例子。
  • ****用于计算机视觉的迁移学习:深度学习已经非常成功地用于各种计算机视觉任务,例如使用不同 CNN 架构的对象识别和标识。在他们的论文中,Yosinski 和他们的合著者(https://arxiv.org/abs/1411.1792)介绍了他们的发现,即较低层如何充当传统的计算机视觉特征提取器,如边缘检测器,而最后几层则致力于特定任务的特征。

因此,这些发现有助于利用现有的最先进的模型,如 VGG,AlexNet 和 Inceptions,来完成目标任务,如风格转换和人脸检测,这些目标任务与这些模型最初训练的目标不同。现在让我们探索一些真实世界的案例研究,并建立一些深度迁移学习模型!

案例研究 1:具有数据可用性约束的图像分类

在这个简单的案例研究中,将研究一个图像分类问题,其约束条件是每个类别的训练样本数量非常少。我们问题的数据集可以在 Kaggle 上获得,并且是最受欢迎的基于计算机视觉的数据集之一。

主要目标

我们将使用的数据集来自非常流行的 狗对猫挑战赛 ,我们的主要目标是建立一个深度学习模型,可以成功地识别图像并将其分类为

Source: becominghuman.ai

用 ML 来说,这是一个基于图像的二元分类问题。在开始之前,我要感谢 Francois Chollet 不仅创建了令人惊叹的深度学习框架**keras**,还在他的著作【Python 深度学习】 中谈到了迁移学习在现实世界中有效的问题。我以此为灵感,在本章中描绘了迁移学习的真正力量,所有结果都基于在我自己的基于 GPU 的云设置(AWS p2.x)中构建和运行每个模型

构建数据集

首先,从数据集页面下载**train.zip**文件,并将其存储在您的本地系统中。下载完成后,将其解压缩到一个文件夹中。这个文件夹将包含 25,000 张狗和猫的图片;也就是说,每个类别有 12,500 个图像。虽然我们可以使用所有 25,000 张图片,并在它们的基础上建立一些不错的模型,但如果你还记得的话,我们的问题目标包括每个类别有少量图片的额外约束。为此,让我们构建自己的数据集。

****import** **glob**
**import** **numpy** **as** **np**
**import** **os**
**import** **shutil****np.random.seed(42)****

现在,让我们加载原始训练数据文件夹中的所有图像,如下所示:

****(12500, 12500)****

我们可以用前面的输出验证每个类别有 12,500 张图片。现在让我们构建更小的数据集,这样我们就有 3,000 张图像用于训练,1,000 张图像用于验证,1,000 张图像用于我们的测试数据集(两种动物类别具有相等的代表性)。

****Cat datasets: (1500,) (500,) (500,)
Dog datasets: (1500,) (500,) (500,)****

现在我们的数据集已经创建好了,让我们将它们分别写到磁盘的不同文件夹中,这样我们就可以在将来的任何时候访问它们,而不用担心它们是否存在于我们的主内存中。

由于这是一个图像分类问题,我们将利用 CNN 模型或 ConvNets 来尝试解决这个问题。我们将从头开始构建简单的 CNN 模型,然后尝试使用正则化和图像增强等技术进行改进。然后,我们将尝试并利用预先训练的模型来释放迁移学习的真正力量!

准备数据集

在我们开始建模之前,让我们加载并准备数据集。首先,我们加载一些基本的依赖项。

****import** **glob**
**import** **numpy** **as** **np**
**import** **matplotlib.pyplot** **as** **plt**
**from** **keras.preprocessing.image** **import** **ImageDataGenerator, load_img, img_to_array, array_to_img****%matplotlib inline****

现在让我们使用下面的代码片段加载数据集。

****Train dataset shape: (3000, 150, 150, 3) 	
Validation dataset shape: (1000, 150, 150, 3)****

我们可以清楚地看到,我们有 3000 个训练图像和 1000 个验证图像。每幅图像的大小为**150 x 150**,有三个通道用于红色、绿色和蓝色(RGB ),因此赋予每幅图像**(150, 150, 3)**的尺寸。我们现在将缩放每张像素值在**(0, 255)****(0, 1)**之间的图像,因为深度学习模型在小输入值的情况下工作得非常好。

前面的输出显示了我们训练数据集中的一个样本图像。现在让我们设置一些基本的配置参数,并将我们的文本类标签编码成数值(否则,Keras 将抛出一个错误)。

****['cat', 'cat', 'cat', 'cat', 'cat', 'dog', 'dog', 'dog', 'dog', 'dog'] [0 0 0 0 0 1 1 1 1 1]****

我们可以看到,我们的编码方案将数字**0**分配给**cat**标签,将**1**分配给**dog**标签。我们现在准备建立我们的第一个基于 CNN 的深度学习模型。

从零开始的简单 CNN 模型

我们将首先建立一个具有三个卷积层的基本 CNN 模型,结合最大池技术从我们的图像中自动提取特征,并对输出卷积特征图进行下采样。

A Typical CNN (Source: Wikipedia)

我们假设你对 CNN 有足够的了解,因此不会涉及理论细节。请随意参考我的书或网上任何解释卷积神经网络的资源!现在让我们利用 Keras 来构建我们的 CNN 模型架构。

前面的输出显示了我们的基本 CNN 模型摘要。正如我们之前提到的,我们使用三个卷积层进行特征提取。展平层用于展平第三个卷积层输出的**17 x 17**特征图的**128**。这被馈送到我们的密集层,以获得图像应该是一只【1】还是一只 猫(0) 的最终预测。所有这些都是模型训练过程的一部分,所以让我们使用下面利用**fit(…)**函数的代码片段来训练我们的模型。

以下术语对于训练我们的模型非常重要:

  • **batch_size**表示每次迭代传递给模型的图像总数。
  • 每次迭代后,更新层中单元的权重。
  • 总迭代次数总是等于训练样本总数除以**batch_size**
  • 一个历元是指完整的数据集已经通过网络一次,即所有的迭代都是基于数据批次完成的。

我们使用 30 的**batch_size**,我们的训练数据总共有 3000 个样本,这表明每个时期总共有 100 次迭代。我们针对总共 30 个时期训练该模型,并因此在我们的 1,000 幅图像的验证集上验证它。

****Train on 3000 samples, validate on 1000 samples
Epoch 1/30
3000/3000 - 10s - loss: 0.7583 - acc: 0.5627 - val_loss: 0.7182 - val_acc: 0.5520
Epoch 2/30
3000/3000 - 8s - loss: 0.6343 - acc: 0.6533 - val_loss: 0.5891 - val_acc: 0.7190
...
...
Epoch 29/30
3000/3000 - 8s - loss: 0.0314 - acc: 0.9950 - val_loss: 2.7014 - val_acc: 0.7140
Epoch 30/30
3000/3000 - 8s - loss: 0.0147 - acc: 0.9967 - val_loss: 2.4963 - val_acc: 0.7220****

基于训练和验证准确性值,看起来我们的模型有点过度拟合。我们可以使用下面的代码片段来绘制模型的准确性和误差,以获得更好的视角。

Vanilla CNN Model Performance

您可以清楚地看到,经过 2-3 个时期后,模型开始过度拟合训练数据。在我们的验证集中,我们得到的平均准确率大约是 72% ,这是一个不错的开始!我们能改进这个模型吗?

正则化 CNN 模型

让我们改进我们的基本 CNN 模型,增加一个卷积层,另一个密集的隐藏层。除此之外,我们将在每个隐藏的密集层后添加**0.3**的 dropout 以实现正则化。基本上,退出是深度神经网络中一种强大的正则化方法。它可以分别应用于输入图层和隐藏图层。Dropout 通过将层中一小部分单元的输出设置为零来随机屏蔽这些单元的输出(在我们的示例中,是密集层中 30%的单元)。

****Train on 3000 samples, validate on 1000 samples
Epoch 1/30
3000/3000 - 7s - loss: 0.6945 - acc: 0.5487 - val_loss: 0.7341 - val_acc: 0.5210
Epoch 2/30
3000/3000 - 7s - loss: 0.6601 - acc: 0.6047 - val_loss: 0.6308 - val_acc: 0.6480
...
...
Epoch 29/30
3000/3000 - 7s - loss: 0.0927 - acc: 0.9797 - val_loss: 1.1696 - val_acc: 0.7380
Epoch 30/30
3000/3000 - 7s - loss: 0.0975 - acc: 0.9803 - val_loss: 1.6790 - val_acc: 0.7840****

Vanilla CNN Model with Regularization Performance

您可以从前面的输出中清楚地看到,我们仍然以过度拟合模型而告终,尽管这花费的时间稍长,并且我们还获得了大约 78% 的稍好的验证准确性,这是不错的,但并不惊人。模型过度拟合的原因是因为我们的训练数据少得多,并且模型在每个时期都看到相同的实例。解决这个问题的一种方法是利用图像增强策略,用现有图像的微小变化来增强我们现有的训练数据。我们将在下一节详细介绍这一点。让我们暂时保存这个模型,这样我们可以在以后使用它来评估它在测试数据上的性能。

****model.save(‘cats_dogs_basic_cnn.h5’)****

图像增强的 CNN 模型

让我们通过使用适当的图像增强策略添加更多数据来改进我们的正则化 CNN 模型。由于我们以前的模型每次都是在相同的小样本数据点上训练的,它不能很好地概括,并在几个时期后结束了过度拟合。图像增强背后的思想是,我们遵循一个设定的过程,从我们的训练数据集中获取现有图像,并对它们应用一些图像变换操作,如旋转、剪切、平移、缩放等,以产生现有图像的新的、改变的版本。由于这些随机转换,我们每次得到的图像并不相同,我们将利用 Python 生成器在训练期间将这些新图像输入到我们的模型中。

Keras 框架有一个出色的实用程序**ImageDataGenerator**,可以帮助我们完成前面的所有操作。让我们为我们的训练和验证数据集初始化两个数据生成器。

**ImageDataGenerator**中有很多选项可用,我们只是利用了其中的一些。请随意查看 文档 以获得更详细的观点。在我们的训练数据生成器中,我们接收原始图像,然后对它们执行一些转换来生成新图像。其中包括以下内容。

  • 使用**zoom_range**参数以**0.3**的系数随机缩放图像。
  • 使用**rotation_range** 参数将图像随机旋转**50**度。
  • 使用**width_shift_range****height_shift_range**参数,按照图像宽度或高度的**0.2**因子,随机水平或垂直平移图像。
  • 使用**shear_range** 参数随机应用基于剪切的变换。
  • 使用**horizontal_flip** 参数随机水平翻转一半图像。
  • 在我们应用任何前面的操作(尤其是旋转或平移)之后,利用**fill_mode**参数为图像填充新的像素。在这种情况下,我们只是用最近的周围像素值填充新像素。

让我们看看这些生成的图像可能是什么样子,以便您可以更好地理解它们。我们将从我们的训练数据集中选取两个样本图像来说明这一点。第一个图像是一只猫的图像。

Image Augmentation on a Cat Image

您可以在之前的输出中清楚地看到,我们每次都生成新版本的训练图像(带有平移、旋转和缩放),并且我们还为它分配了一个 cat 标签,以便模型可以从这些图像中提取相关特征,并记住这些是猫。现在让我们看看图像增强是如何在一个样本狗图像上工作的。

Image Augmentation on a Dog Image

这向我们展示了图像增强如何有助于创建新图像,以及如何在这些图像上训练模型来帮助克服过度拟合。请记住,对于我们的验证生成器,我们只需要将验证图像(原始图像)发送给模型进行评估;因此,我们只缩放图像像素(在 0-1 之间),不应用任何变换。我们只对训练图像应用图像增强变换。现在,让我们使用我们创建的图像增强数据生成器来训练一个具有正则化的 CNN 模型。我们将使用与之前相同的模型架构。

我们在这里将默认学习速率降低了 10 倍,以防止模型陷入局部最小值或过度拟合,因为我们将发送大量带有随机变换的图像。为了训练模型,我们现在需要稍微修改我们的方法,因为我们正在使用数据生成器。我们将利用 Keras 的**fit_generator(…)** 函数来训练这个模型。**train_generator**每次生成 30 幅图像,因此我们将使用**steps_per_epoch**参数并将其设置为 100,以根据每个时期的训练数据在 3000 幅随机生成的图像上训练模型。我们的**val_generator**每次生成 20 幅图像,因此我们将**validation_steps**参数设置为 50,以在所有 1,000 幅验证图像上验证我们的模型准确性(记住,我们不是在扩充我们的验证数据集)。

****Epoch 1/100
100/100 - 12s - loss: 0.6924 - acc: 0.5113 - val_loss: 0.6943 - val_acc: 0.5000
Epoch 2/100
100/100 - 11s - loss: 0.6855 - acc: 0.5490 - val_loss: 0.6711 - val_acc: 0.5780
Epoch 3/100
100/100 - 11s - loss: 0.6691 - acc: 0.5920 - val_loss: 0.6642 - val_acc: 0.5950
...
...
Epoch 99/100
100/100 - 11s - loss: 0.3735 - acc: 0.8367 - val_loss: 0.4425 - val_acc: 0.8340
Epoch 100/100
100/100 - 11s - loss: 0.3733 - acc: 0.8257 - val_loss: 0.4046 - val_acc: 0.8200****

我们得到了大约 82% 的验证准确度,这比我们以前的模型几乎好了4–5%。此外,我们的训练精度与验证精度非常相似,表明我们的模型不再过度拟合。下面描述了每个历元的模型精度和损失。

Vanilla CNN Model with Image Augmentation Performance

虽然在验证准确性和损失方面存在一些尖峰,但总体而言,我们看到它更接近于训练准确性,损失表明我们获得了一个比我们以前的模型概括得更好的模型。让我们现在保存这个模型,这样我们就可以稍后在我们的测试数据集上评估它。

****model.save(‘cats_dogs_cnn_img_aug.h5’)****

我们现在将尝试利用迁移学习的力量,看看我们是否能建立一个更好的模型!

利用预先训练的 CNN 模型进行迁移学习

当构建新模型或重用它们时,预训练模型以以下两种流行的方式使用:

  • 使用预先训练的模型作为特征提取器
  • 微调预训练模型

我们将在本节中详细讨论这两个问题。我们将在本章中使用的预训练模型是流行的 VGG-16 模型,由牛津大学的 视觉几何小组 创建,该小组专门为大规模视觉识别构建非常深的卷积网络。

像 VGG-16 这样的预训练模型是在具有许多不同图像类别的巨大数据集(ImageNet)上已经预训练的模型。考虑到这一事实,该模型应该已经学习了特征的健壮层次,这些特征相对于由 CNN 模型学习的特征是空间、旋转和平移不变的。因此,该模型已经学习了属于 1,000 个不同类别的超过一百万个图像的特征的良好表示,可以充当适用于计算机视觉问题的新图像的良好特征提取器。这些新图像可能永远不会存在于 ImageNet 数据集中,或者可能属于完全不同的类别,但是模型应该仍然能够从这些图像中提取相关的特征。

这使我们能够利用预先训练的模型作为新图像的有效特征提取器,来解决各种复杂的计算机视觉任务,例如用较少的图像解决我们的猫和狗的分类器,甚至建立狗的品种分类器、面部表情分类器等等!在针对我们的问题释放迁移学习的力量之前,让我们简要讨论一下 VGG-16 模型架构。

了解 VGG-16 模型

VGG-16 模型是建立在 ImageNet 数据库上的 16 层(卷积和全连接)网络,该数据库是为了图像识别和分类的目的而建立的。这个模型是由卡伦·西蒙扬和安德鲁·齐泽曼建立的,并在他们题为‘用于大规模图像识别的超深度卷积网络’的论文中提到。我推荐所有感兴趣的读者去阅读这篇文章中的优秀文献。下图描述了 VGG-16 模型的架构。

VGG-16 Model Architecture

您可以清楚地看到,我们共有使用**3 x 3**卷积滤镜的**13**卷积层,以及用于缩减采样的 max pooling 层,并且共有两个完全连接的隐藏层,每个层中有**4096**个单元,后面是一个密集的**1000**个单元层,其中每个单元代表 ImageNet 数据库中的一个图像类别。我们不需要最后三层,因为我们将使用我们自己的完全连接的密集层来预测图像是一只狗还是一只猫。我们更关心前五个模块,这样我们可以利用 VGG 模型作为有效的特征提取器。

对于其中一个模型,我们将通过冻结所有五个卷积块来将其用作简单的特征提取器,以确保它们的权重不会在每个时期后更新。对于最后一个模型,我们将对 VGG 模型进行微调,其中我们将解冻最后两个块(块 4 和块 5),以便在我们训练自己的模型时,它们的权重在每个时期(每批数据)得到更新。在下面的框图中,我们展示了前面的架构,以及我们将使用的两种变体(基本特征提取器和微调),这样您可以获得更好的视觉效果。

Block Diagram showing Transfer Learning Strategies on the VGG-16 Model

因此,我们最关心的是利用 VGG-16 模型的卷积块,然后展平最终输出(来自特征图),以便我们可以将它馈送到我们自己的分类器的密集层中。

作为特征提取器的预训练 CNN 模型

让我们利用 Keras,加载 VGG-16 模型,并冻结卷积块,以便我们可以将其用作图像特征提取器。

从前面的输出可以清楚地看到,VGG-16 模型的所有层都被冻结了,这很好,因为我们不希望它们的权重在模型训练期间发生变化。VGG-16 模型中的最后一个激活特征图(来自**block5_pool**的输出)为我们提供了瓶颈特征,然后可以将其展平并馈入完全连接的深度神经网络分类器。下面的代码片段显示了来自我们训练数据的样本图像的瓶颈特征。

****bottleneck_feature_example = vgg.predict(train_imgs_scaled[0:1])
print(bottleneck_feature_example.shape)
plt.imshow(bottleneck_feature_example[0][:,:,0])****

Sample Bottleneck Features

我们展平 vgg_model 对象中的瓶颈特征,使它们准备好被提供给我们的全连接分类器。在模型训练中节省时间的一种方法是使用该模型,从我们的训练和验证数据集中提取出所有特征,然后将它们作为输入提供给我们的分类器。现在让我们从我们的训练和验证集中提取出瓶颈特性。

****Train Bottleneck Features: (3000, 8192) 	
Validation Bottleneck Features: (1000, 8192)****

前面的输出告诉我们,我们已经为 3,000 幅训练图像和 1,000 幅验证图像成功提取了维度为**1 x 8192**的平坦瓶颈特征。现在让我们构建我们的深度神经网络分类器的架构,它将这些特征作为输入。

正如我们之前提到的,大小为 8192 的瓶颈特征向量充当我们的分类模型的输入。在密集层方面,我们使用与之前模型相同的架构。现在来训练这个模型。

****Train on 3000 samples, validate on 1000 samples
Epoch 1/30
3000/3000 - 1s 373us/step - loss: 0.4325 - acc: 0.7897 - val_loss: 0.2958 - val_acc: 0.8730
Epoch 2/30
3000/3000 - 1s 286us/step - loss: 0.2857 - acc: 0.8783 - val_loss: 0.3294 - val_acc: 0.8530
Epoch 3/30
3000/3000 - 1s 289us/step - loss: 0.2353 - acc: 0.9043 - val_loss: 0.2708 - val_acc: 0.8700
...
...
Epoch 29/30
3000/3000 - 1s 287us/step - loss: 0.0121 - acc: 0.9943 - val_loss: 0.7760 - val_acc: 0.8930
Epoch 30/30
3000/3000 - 1s 287us/step - loss: 0.0102 - acc: 0.9987 - val_loss: 0.8344 - val_acc: 0.8720****

Pre-trained CNN (feature extractor) Performance

我们得到了一个验证准确率接近 88%的模型,几乎比我们的基本 CNN 图像增强模型提高了 5-6%,这是非常好的。不过,这个模型似乎有些过度拟合了。在第五个时期之后,模型训练和验证准确性之间存在相当大的差距,这在某种程度上表明模型在那之后对训练数据过度拟合。但总的来说,这似乎是目前为止最好的模式。让我们尝试在这个模型上使用我们的图像增强策略。在此之前,我们使用下面的代码将这个模型保存到磁盘。

****model.save('cats_dogs_tlearn_basic_cnn.h5')****

预训练 CNN 模型作为图像增强的特征提取器

我们将利用以前使用的相同的数据生成器来训练和验证数据集。为了便于理解,构建它们的代码描述如下。

让我们现在建立我们的深度学习模型并训练它。我们不会像上次一样提取瓶颈特性,因为我们将在数据生成器上进行培训;因此,我们将把**vgg_model**对象作为输入传递给我们自己的模型。我们将学习率稍微降低,因为我们将训练 100 个纪元,并且不希望对我们的模型层进行任何突然的权重调整。请记住,VGG-16 模型的层仍然被冻结在这里,我们仍然使用它作为一个基本的特征提取器而已。

****Epoch 1/100
100/100 - 45s 449ms/step - loss: 0.6511 - acc: 0.6153 - val_loss: 0.5147 - val_acc: 0.7840
Epoch 2/100
100/100 - 41s 414ms/step - loss: 0.5651 - acc: 0.7110 - val_loss: 0.4249 - val_acc: 0.8180
Epoch 3/100
100/100 - 41s 415ms/step - loss: 0.5069 - acc: 0.7527 - val_loss: 0.3790 - val_acc: 0.8260
...
...
Epoch 99/100
100/100 - 42s 417ms/step - loss: 0.2656 - acc: 0.8907 - val_loss: 0.2757 - val_acc: 0.9050
Epoch 100/100
100/100 - 42s 418ms/step - loss: 0.2876 - acc: 0.8833 - val_loss: 0.2665 - val_acc: 0.9000****

Pre-trained CNN (feature extractor) with Image Augmentation Performance

我们可以看到,我们的模型的整体验证精度为 90% ,比我们之前的模型略有提高,而且训练和验证精度也相当接近,表明模型没有过拟合。现在让我们将这个模型保存在磁盘上,以便将来对测试数据进行评估。

****model.save(‘cats_dogs_tlearn_img_aug_cnn.h5’)****

我们现在将微调 VGG-16 模型以构建我们的最后一个分类器,其中我们将解冻块 4 和 5,正如我们在前面的框图中所描述的那样。

带有微调和图像增强的预训练 CNN 模型

我们现在将利用存储在**vgg_model**变量中的 VGG-16 模型对象,解冻卷积块 4 和 5,同时保持前三个块冻结。下面的代码帮助我们实现了这一点。

从前面的输出中可以清楚地看到,属于块 4 和块 5 的卷积和池层现在是可训练的。这意味着当我们传递每批数据时,这些层的权重也将随着每个历元中的反向传播而更新。我们将使用与先前模型相同的数据生成器和模型架构,并训练我们的模型。我们稍微降低了学习速率,因为我们不想陷入任何局部最小值,我们也不想突然更新可训练的 VGG-16 模型层的权重一个可能对模型产生不利影响的大因子。

****Epoch 1/100
100/100 - 64s 642ms/step - loss: 0.6070 - acc: 0.6547 - val_loss: 0.4029 - val_acc: 0.8250
Epoch 2/100
100/100 - 63s 630ms/step - loss: 0.3976 - acc: 0.8103 - val_loss: 0.2273 - val_acc: 0.9030
Epoch 3/100
100/100 - 63s 631ms/step - loss: 0.3440 - acc: 0.8530 - val_loss: 0.2221 - val_acc: 0.9150
...
...
Epoch 99/100
100/100 - 63s 629ms/step - loss: 0.0243 - acc: 0.9913 - val_loss: 0.2861 - val_acc: 0.9620
Epoch 100/100
100/100 - 63s 629ms/step - loss: 0.0226 - acc: 0.9930 - val_loss: 0.3002 - val_acc: 0.9610****

Pre-trained CNN (fine-tuning) with Image Augmentation Performance

从前面的输出中我们可以看到,我们的模型获得了大约 96% 的验证精度,这比我们之前的模型提高了 6% 。总体而言,该模型在验证准确性方面比我们的第一个基本 CNN 模型提高了 24% 。这真的说明了迁移学习是多么有用。我们可以看到,这里的精度值非常好,尽管模型看起来可能有点过度拟合训练数据,但我们仍然获得了很高的验证精度。现在让我们使用下面的代码将这个模型保存到磁盘上。

****model.save('cats_dogs_tlearn_finetune_img_aug_cnn.h5')****

现在让我们通过在我们的测试数据集上实际评估它们的性能来测试我们所有的模型。

在测试数据上评估我们的深度学习模型

我们现在将评估我们到目前为止构建的五个不同的模型,首先在我们的测试数据集上测试它们,因为仅仅验证是不够的!我们还构建了一个叫做**model_evaluation_utils**的漂亮的实用模块,我们将使用它来评估我们的深度学习模型的性能。在开始之前,让我们加载必要的依赖项和我们保存的模型。

现在是最后测试的时候了,我们通过在测试数据集上进行预测来测试我们的模型的性能。在我们尝试进行预测之前,让我们先加载并准备我们的测试数据集。

****Test dataset shape: (1000, 150, 150, 3)
['dog', 'dog', 'dog', 'dog', 'dog'] [1, 1, 1, 1, 1]****

现在我们已经准备好了缩放数据集,让我们通过对所有测试图像进行预测来评估每个模型,然后通过检查预测的准确性来评估模型性能。

模型 1:基本 CNN 性能

模型 2:具有图像增强性能的基本 CNN

模型 3:迁移学习——预训练 CNN 作为特征提取器的性能

模型 4:迁移学习——预训练的 CNN 作为具有图像增强性能的特征提取器

模型 5:迁移学习——具有微调和图像增强性能的预训练 CNN

我们可以看到,我们肯定有一些有趣的结果。每个后续模型都比前一个模型表现得更好,这是意料之中的,因为我们对每个新模型都尝试了更先进的技术。

我们最差的模型是我们的基本 CNN 模型,模型精度和 F1 分数约为 78% ,我们最好的模型是我们经过迁移学习和图像增强的微调模型,这使我们的模型精度和 F1 分数为 96% ,考虑到我们是从 3000 个图像训练数据集训练我们的模型,这真是令人惊讶。现在让我们画出最坏和最好模型的 ROC 曲线。

ROC curve of our worst vs. best model

这应该让你很好地了解预训练模型和迁移学习可以产生多大的影响,特别是在处理复杂问题时,我们有像更少的数据这样的限制。我们鼓励您用自己的数据尝试类似的策略!

案例研究 2:具有大量类别和较少数据可用性的多类别细粒度影像分类

现在,在这个案例研究中,让我们升级游戏,让图像分类的任务更加激动人心。在之前的案例研究中,我们构建了一个简单的二进制分类模型(尽管我们使用了一些复杂的技术来解决小数据约束问题!).在这个案例研究中,我们将专注于细粒度图像分类的任务。与通常的图像分类任务不同,细粒度图像分类是指识别更高级别类别中不同子类的任务。

主要目标

为了帮助更好地理解这项任务,我们将围绕 斯坦福狗 数据集进行讨论。顾名思义,这个数据集包含了不同犬种的图像。在这种情况下,任务是识别这些狗的品种。因此,高层次的概念是狗本身,而任务是正确地分类不同的子概念或子类——在这种情况下,是品种。

我们将利用通过 Kaggle 可用这里可用的数据集。我们将只使用训练数据集,因为它已经标记了数据。该数据集包含大约 10,000 张 120 种不同犬种的标记图像。因此,我们的任务是建立一个细粒度的 120 类分类模型,对 120 种不同的犬种进行分类。绝对有挑战性!

加载和浏览数据集

让我们通过加载数据和查看一批图像样本来看看数据集的样子。

Sample dog breed images and labels

从前面的网格中,我们可以看到在分辨率、照明、缩放级别等方面有很多变化,同时图像不仅仅包含一只狗,还包含其他狗和周围的项目。这将是一个挑战!

构建数据集

让我们先看看数据集标签是什么样子的,以便了解我们正在处理什么。

****data_labels = pd.read_csv('labels/labels.csv')
target_labels = data_labels['breed']****print(len(set(target_labels)))
data_labels.head()****------------------
120****

我们接下来要做的是使用下面的代码为磁盘中的每个图像添加精确的图像路径。这将有助于我们在模型训练期间轻松定位和加载图像。

现在是准备我们训练、测试和验证数据集的时候了。我们将利用以下代码来帮助我们构建这些数据集!

****Initial Dataset Size: (10222, 299, 299, 3)****Initial Train and Test Datasets Size: (7155, 299, 299, 3) (3067, 299, 299, 3)****Train and Validation Datasets Size: (6081, 299, 299, 3) (1074, 299, 299, 3)****Train, Test and Validation Datasets Size: (6081, 299, 299, 3) (3067, 299, 299, 3) (1074, 299, 299, 3)****

我们还需要将文本类标签转换为一次性编码标签,否则我们的模型将无法运行。

****((6081, 120), (3067, 120), (1074, 120))****

一切看起来都井然有序。现在,如果您还记得之前的案例研究,图像增强是处理每类数据较少的一种好方法。在这种情况下,我们总共有 10222 个样本和 120 个类。这意味着,平均每堂课只有 85 张图片!我们使用来自**keras.****ImageDataGenerator**实用程序来完成这项工作

现在我们已经准备好了数据,下一步就是实际构建我们的深度学习模型!

使用 Google 的 Inception V3 模型进行迁移学习

现在我们的数据集已经准备好了,让我们开始建模过程。我们已经知道如何从头开始构建深度卷积网络。我们也了解实现良好性能所需的微调量。在这项任务中,我们将利用迁移学习的概念。预训练模型是开始迁移学习任务所需的基本要素。

在这个案例研究中,我们将集中利用一个预先训练的模型作为特征提取器。我们知道,深度学习模型基本上是神经元互连层的堆叠,最后一层充当分类器。这种架构使深度神经网络能够捕捉网络中不同级别的不同特征。因此,我们可以利用这一特性将它们用作特征提取器。这可以通过移除最后一层或使用倒数第二层的输出来实现。倒数第二层的这个输出然后被馈送到另外一组层中,接着是分类层。我们将使用谷歌的 Inception V3 模型 作为我们的预训练模型。

基于前面的输出,您可以清楚地看到,Inception V3 模型非常庞大,有很多层和参数。让我们现在开始训练我们的模型。我们使用**fit_generator(...)**方法训练模型,以利用上一步中准备的数据扩充。我们将批量大小设置为**32**,并训练 15 个时期的模型。

****Epoch 1/15
190/190 - 155s 816ms/step - loss: 4.1095 - acc: 0.2216 - val_loss: 2.6067 - val_acc: 0.5748
Epoch 2/15
190/190 - 159s 836ms/step - loss: 2.1797 - acc: 0.5719 - val_loss: 1.0696 - val_acc: 0.7377
Epoch 3/15
190/190 - 155s 815ms/step - loss: 1.3583 - acc: 0.6814 - val_loss: 0.7742 - val_acc: 0.7888
...
...
Epoch 14/15
190/190 - 156s 823ms/step - loss: 0.6686 - acc: 0.8030 - val_loss: 0.6745 - val_acc: 0.7955
Epoch 15/15
190/190 - 161s 850ms/step - loss: 0.6276 - acc: 0.8194 - val_loss: 0.6579 - val_acc: 0.8144****

Performance of our Inception V3 Model (feature extractor) on the Dog Breed Dataset

该模型在仅仅 15 个时期内在训练集和验证集上实现了超过 80%的准确性,这是值得称赞的性能。右边的图显示了损失下降并收敛到大约**0.5**的速度。这是一个清晰的例子,说明迁移学习是多么强大而简单。

在测试数据上评估我们的深度学习模型

训练和验证性能相当好,但是在看不见的数据上性能如何呢?因为我们已经将原始数据集分成了三个独立的部分。这里要记住的重要一点是,测试数据集必须经历与训练数据集相似的预处理。考虑到这一点,在将测试数据集输入函数之前,我们也要对其进行缩放。

****Accuracy: 0.864
Precision: 0.8783
Recall: 0.864
F1 Score: 0.8591****

该模型实现了惊人的 86% 准确率以及测试数据集上的 F1 分。考虑到我们刚刚用我们这边最少的输入训练了 15 个纪元,迁移学习帮助我们实现了一个相当不错的分类器。我们还可以使用下面的代码来检查每个类的分类指标。

我们还可以使用下面的代码以一种视觉上吸引人的方式可视化模型预测。

Model predictions on test data for dog breeds!

上图展示了模型性能的直观证明。正如我们所看到的,在大多数情况下,该模型不仅预测正确的狗品种,而且有很高的可信度。

转移学习优势

在前面的章节中,我们已经以这样或那样的方式介绍了迁移学习的一些优点。通常,迁移学习使我们能够建立更强大的模型,这些模型可以执行各种各样的任务。

  • 有助于解决具有多种约束的复杂现实问题
  • 解决诸如很少或几乎没有标注数据可用性的问题
  • 基于领域和任务,将知识从一个模型转移到另一个模型的容易程度
  • 提供了一条在未来某一天实现人工智能的道路!

转移学习挑战

迁移学习具有巨大的潜力,是现有学习算法普遍需要的改进。然而,有一些与迁移学习相关的问题需要更多的研究和探索。除了难以回答转移什么、何时转移和如何转移的问题之外,负转移和转移界限也提出了重大挑战。

  • ****负迁移:到目前为止,我们讨论的案例都是基于源任务的知识迁移来讨论目标任务的改进。迁移学习有时会导致成绩下降。负迁移是指知识从源到目标的迁移并没有带来任何改善,反而导致目标任务的整体绩效下降。负迁移可能有多种原因,例如源任务与目标任务没有足够的相关性,或者迁移方法不能很好地利用源任务和目标任务之间的关系。避免负迁移非常重要,需要仔细研究。在他们的工作中,Rosenstien 和他们的合作者根据经验展示了当源和目标太不相似时,蛮力转移如何降低目标任务的性能。Bakker 和他们的合著者的贝叶斯方法,以及其他探索基于聚类的解决方案以识别相关性的技术,正在被研究以避免负迁移。
  • ****迁移界限:迁移学习中量化迁移也很重要,它影响迁移的质量及其可行性。为了测量迁移的数量,Hassan Mahmud 和他们的合作者使用 Kolmogorov 复杂性来证明某些理论界限,以分析迁移学习和测量任务之间的相关性。伊顿和他们的合著者提出了一种新颖的基于图表的方法来衡量知识转移。对这些技术的详细讨论超出了本文的范围。鼓励读者使用本节中概述的出版物来探索这些主题的更多内容!

结论和未来范围

这可能是我最长的一篇文章了,它全面地介绍了迁移学习的概念、策略、深度迁移学习的重点、挑战和优势。我们还介绍了两个实际案例研究,让您很好地了解如何实现这些技术。如果你正在阅读这一部分,通读这篇相当长的文章值得称赞!

迁移学习肯定会成为机器学习和深度学习在行业主流采用中取得成功的关键驱动因素之一。我绝对希望看到更多的预训练模型和创新的案例研究,它们利用了这一概念和方法。对于我未来的一些文章,你肯定可以期待下面的一些。

  • 自然语言处理的迁移学习
  • 音频数据的迁移学习
  • 面向生成性深度学习的迁移学习
  • 更复杂的计算机视觉问题,如图像字幕

让我们期待更多关于迁移学习和深度学习的成功故事,使我们能够建立更多智能系统,让世界变得更美好,并推动我们自己的个人目标!

以上所有内容都以某种形式摘自我最近的一本书,,这本书可以在 Packt 网站以及 Amazon 上找到。****

*** [## 用 Python 实践迁移学习:实现高级深度学习和神经网络模型…

深度学习通过监督、非监督和强化学习简化到下一个级别,使用…

www.amazon.com](https://www.amazon.com/Hands-Transfer-Learning-Python-TensorFlow-ebook/dp/B07CB455BF/ref=zg_bsnr_16977170011_71?_encoding=UTF8&psc=1&refRID=3VS8TYPZGN776BFEZJVG)

没有时间通读这本书或者现在没有时间?别担心,您仍然可以访问我们在 GitHub 库 上实现的所有精彩示例和案例研究!

[## dipanjanS/用 python 实践迁移学习

通过使用 Python 深度学习生态系统转移先前的学习来简化深度学习…

github.com](https://github.com/dipanjanS/hands-on-transfer-learning-with-python)

非常感谢我的合著者Raghav&Tamoghna与我一起为这本书铺平了道路!

感谢 Francois Chollet 和他令人惊叹的书 【用 Python 进行深度学习】 为本文中使用的一些示例提供了很多动机和灵感。

[## 使用 Python 进行深度学习

我所见过的关于深度学习的最清晰的解释…阅读是一种享受。

www.manning.com](https://www.manning.com/books/deep-learning-with-python)

有反馈给我吗?或者有兴趣与我一起从事研究、数据科学、人工智能甚至发表一篇关于TDS的文章?可以在LinkedIn上联系我。

[## Dipanjan Sarkar —数据科学家—英特尔公司| LinkedIn

查看 Dipanjan Sarkar 在世界最大的职业社区 LinkedIn 上的个人资料。Dipanjan 有 6 份工作列在…

www.linkedin.com](https://www.linkedin.com/in/dipanzan/)

感谢 Durba 编辑本文。***

一个全面的机器学习工作流程,使用 R

原文:https://towardsdatascience.com/a-comprehensive-machine-learning-workflow-with-multiple-modelling-using-caret-and-caretensemble-in-fcbf6d80b5f2?source=collection_archive---------6-----------------------

介绍

我将使用一个非常有趣的数据集,该数据集出现在布雷特·兰茨(Brett Lantz)写的《带 R 的机器学习》(RPackt Publishing)一书中。我的意图是通过执行一个完全监督的机器学习工作流来扩展对这个数据集的分析,这个工作流我已经设计了一段时间,以便帮助我用一种系统的、有条不紊的方法来解决任何类似的问题。

如果你认为这不是什么新鲜事,那么你绝对是对的!我在这里没有提出任何新的东西,只是确保我有所有必要的工具来遵循一个完整的过程,而不会留下任何大的细节。希望你们中的一些人也会发现它很有用,并确信你们会从我的部分和/或你们会以不同方式做的事情中发现一些判断错误。欢迎给我留言,帮助我改进!

让我们向前一跳,开始了解我们将处理哪些信息:

混凝土强度建模

从书中:

“在工程领域,准确估计建筑材料的性能至关重要。为了制定建筑、桥梁和道路施工中所用材料的安全指南,需要进行这些评估。
估算混凝土的强度是一项特别有趣的挑战。尽管混凝土几乎用于每一个建筑项目,但由于各种成分以复杂的方式相互作用,混凝土的性能差异很大。因此,很难准确预测最终产品的强度。给定输入材料的成分列表,可以可靠地预测混凝土强度的模型可以产生更安全的施工实践。

为了进行这一分析,我们将利用由叶一诚捐赠给 UCI 机器学习数据仓库( 、http://archive.ics.uci.edu/ml)的混凝土抗压强度数据。

根据该网站,混凝土数据集包含 1030 个混凝土实例,具有描述混合物中使用的成分的八个特征。这些特征被认为与最终抗压强度有关,它们包括产品中使用的水泥、矿渣、灰、水、超塑化剂、粗骨料和细骨料的量(以千克/立方米计)以及老化时间(以天计)。”

机器学习工作流程

我发现将工作流程分成 6 个阶段最适合我。在这个意义上,我将把这个实例描述为:
1)设置
2)探索性数据分析
3)特征工程
4)数据准备
5)建模
6)结论

在实践中,我从一个跳到另一个,很多时候不考虑顺序,而且经常是循环的。因此,请将此视为一个初始结构,更像是一份清单,而不是一步一步的指南。

这份清单相当全面,涵盖了你在监督学习 分类回归 问题中要遵循的大部分内容。在实践中,你很可能会跳过列表中的一些要点,因为有些事情是你为分类问题所做的,而不是为回归问题所做的,反之亦然。甚至有些有时候还有点多余(虽然在我看来双重检查总是有用的)。我相信随着更多的实践和经验,这个列表会得到调整,我希望我也能在未来再次分享。

我将把自己限制在简短直接的回答上,并在必要时扩展。否则我担心我会让任何人逗留太久!

你会看到,即使我包括了完整的清单,在许多情况下,我们并不一定要做什么。这是因为这个数据集非常简单。这感觉有点像作弊,但是,我会确保提到为什么我们不必做任何事情,以及检查点背后的想法。

我想提到的最后一件事是,当我到达建模阶段时,我将改变我的方法,展示一些有用的建模工具,包括 R 包 caretcaretEnsemble 。因此,我不是一步一步地尝试一些基线模型,然后尝试一些更高级的模型,通过超参数调整和正则化来减少过度拟合,而是一次训练一堆模型,因为这使我能够使最后一个阶段更加简洁明了,便于解释。还因为建模阶段是一个人喜欢做自己的事情并通过使用不同的方法获得创造力的阶段。在我看来,这个清单对于阶段 1 至 4 非常重要,但从阶段 5 开始,它可能会变得不那么严格。

说够了,我们开始吧:

在这里找到工作文件和代码:https://github.com/gabrielpierobon/ML-workflow-caret

1)设置

1.1)我们试图预测什么?

我们需要为工程领域准确地估计建筑材料的性能。

1.2)这是什么类型的问题?监督学习还是非监督学习?分类还是回归?二元还是多类?单变量还是多变量?

这是一个多元监督机器学习问题,我们必须预测数字结果,因此我们将使用回归技术。

1.3)我们有什么类型的数据?

我们的数据是“csv”格式。它显示了带有列名的标题行。它似乎只包含数字信息。

1.4)导入数据集

我们可以简单地用下面的代码加载它:

*concrete <- read.csv(“/Users/Gabriel Pierobon/Desktop/Datasets para cargar/concrete.csv”)#use your own directory!*

这是我们数据集的大小:

*dim(concrete)
[1] 1030    9*

1,030 行 9 列,其中一列是我们的响应/目标变量。

我们可以看到它是作为数据框导入的,这是我们处理这些数据所需的格式:

*class(concrete)
[1] "data.frame"*

我们还可以检查我们的列名是否被正确导入。

*names(concrete)*

从该列表中,我们将strength确定为我们的响应/目标变量

我们可以得出结论,我们的数据被正确地导入,从而结束我们的 ssetting阶段。

在此之前,我想要求我们所有的图书馆。为了提高这本书的可读性,在乞讨的时候一次完成是很有用的:

*library(dplyr)
library(ggplot2)
library(PerformanceAnalytics)
library(ggthemes)
library(corrplot)
library(car)
library(psych)
library(caret)
library(caretEnsemble)
library(doParallel)*

考虑到这一点,让我们继续探索性的数据分析:

2) 探索性数据分析 (EDA)

2.1)查看数据(str 或 dplyr 的一瞥)。第一眼。有什么奇怪的吗?

我们想要再次检查我们在设置阶段所做的事情的第一个方法是快速查看我们的完整数据集。我们这样做:

*View(concrete)*

这将显示一个包含数据集的窗口。我喜欢从上到下、从左到右快速查看,以确保数据加载正确。这也是一种快速而肮脏的方式来检测一眼就能发现的问题。对于非常大的数据集,您不希望这样做。

接下来,我们将对我们的数据进行浏览并观察数据帧的前几行:

*glimpse(concrete)*

*head(concrete)*

2.2)它是一个“整洁”的数据集吗?需要“聚集”还是“分散”呢?它是以一种我们可以合作的方式呈现的吗?

我们需要我们的数据以行的形式呈现,以列的形式呈现特征。幸运的是,这是数据集的情况,所以我们不必转换它。否则,我们将不得不使用某种功能来旋转数据框以适应我们的需要(参考该网站了解更多关于那个)

2.3)行名和列名可以吗?我们应该改变他们吗?

我们已经检查过这些是如何装载的。我们需要更新/改变什么来更清楚地了解我们的变量吗?我觉得不是这样的,我们可以继续。这里的想法是确保我们舒适地使用我们的特性名称,避免不必要的长名称或任何其他令人困惑的情况。

2.4)检查数据类型。他们还好吗?如果没有,转换

正如我们所看到的,我们所有的变量都是双类型,除了变量age是整数。好在我们什么都不用换算!为了避免加载数据时出现某种类型的错误,我们检查这一点非常重要。有时数字列中的单个字符会导致整个列作为字符被加载。

2.5)我们的响应/目标变量是什么?阶层失衡?研究一下

我们的响应变量是strength。让我们来看看一些有用的统计数据:

*summary(concrete$strength)*

我们可以看到它从 2.3 到 82.6 不等。中值平均值非常接近,但是由于中值实际上更小,这导致变量分布的稍微向右倾斜。

我们可以观察到,使用 ggplot2 的绘图:

**

正如我们所看到的,strength变量的分布并不完全符合正态分布,但是我们还是要继续下去。这应该不成问题,因为很近。QQ 图也有助于常态的视觉分析(我把这个留给你)

最后,由于这是一个回归问题,我们不必担心阶级不平衡。在分类中,你希望在你的响应变量中有平衡的类(这里有一个关于类不平衡的好帖子)

2.6)其余功能。汇总统计数据。了解您的数据

这里,我们将统计分析扩展到我们的其他变量/特征。我们希望关注最小和最大(这是对潜在异常值的第一次检查)。同样,意味着的中位数的差异是值得关注的。我们希望所有变量尽可能遵循正态分布。

*summary(concrete)*

我们可以根据我们的分析绘制相关图。这将为我们提供一个图表,显示所有变量之间的相关性。这也让我们第一次思考,我们是否需要模型中的所有变量。我们不希望我们的特征变量之间呈现高相关性。我们稍后会处理这件事。

*corrplot(cor(concrete), method = “square”)*

另一种看待所有这些的好方法是用这个相关图:

*chart.Correlation(concrete)*

在其中一条对角线上,我们可以看到每个特征的分布。并不是所有的都类似于常态,所以我们将在后面处理这个问题。

在这一点上,我的第一个结论是,变量ash与我们的响应变量strength具有低相关性,而与八个其他特征中的四个具有高相关性。因此,它是一个很有可能被删除的对象,我们稍后也会谈到这一点。

2.7)分类数据/因素:创建计数表以了解不同的类别。全部检查一下。

在这种情况下,我们不使用分类特征。你要确保你理解你的类别,有时拼写错误会给因子变量带来问题。

我们可以继续前进。

2.8)不必要的列?我们可以很快理解我们不需要的列。放下它们

这里我们想寻找完全无用的列。数据集中出现的任何信息都是毫无意义的,我们可以决定是否应该删除。附加索引列、无信息字符串列等。对于该数据集,情况并非如此。只要导入数据集,就可以很好地做到这一点,此时不需要特别做。

2.9)检查是否有缺失值。多少?在哪里?删除它们?归咎于他们?

让我们首先对 NAs 做一个全面的检查:

*anyNA(concrete)
[1] FALSE*

精彩!整个集合中没有缺失值!让我向您展示一种方法,我们可以为每一列检测到这一点:

*sapply(concrete, {function(x) any(is.na(x))})*

(一些处理缺失值的工具

2.10)检查异常值和其他不一致的数据点。箱线图。用于异常值检测的 DBSCAN?

在我看来,离群点检测更像是一门手艺。我真的很喜欢使用 DBSCAN 聚类进行异常值检测的方法,但我不打算继续这样做,所以我不会过度扩展这个分析。DBSCAN 是一种聚类算法,可以检测数据中的噪声点,并且不会将它们分配给任何聚类。我发现异常值检测非常有吸引力(更多关于 DBSCAN 的信息,请点击

相反,我将继续绘制一个箱线图,并尝试处理我认为与视觉相关的点:

*boxplot(concrete[-9], col = “orange”, main = “Features Boxplot”)*

我们看到有几个潜在的异常值,但是我认为age特性可能是最有问题的。让我们孤立地来看:

*boxplot(concrete$age, col = “red”)*

这仅仅是 4 个异常值吗?如果是这样,我们可以摆脱他们。还是不应该?我们来看看这些值是什么,有多少个。

*age_outliers <- which(concrete$age > 100)
concrete[age_outliers, “age”]*

我的天啊。所以他们有 62 个,而不是只有 4 个!显然,这只是因为相同的数字重复了几次。这让我觉得这个age点其实是有关联的,我们不想去掉。我们的 1,030 个数据集中的 62 个数据点似乎太高,不能简单地删除(我们会丢失大量信息)。

2.11)检查数字数据中的多重共线性。差异通货膨胀系数(VIF)

我们已经在之前展示的相关图中看到,某些特征之间似乎存在显著的相关性。我们希望确保多重共线性不会成为阻碍我们前进的问题。为此,我们将计算一个名为方差膨胀因子(VIF) 的分数,该分数测量回归系数的方差因模型中的多重共线性而膨胀的程度。如果 VIF 得分大于 10,则强烈建议使用多重共线性,我们应该尝试去除导致多重共线性的要素。

首先,我们为我们的目标变量生成一个简单的线性回归模型,用相互特征来解释。之后,我们在模型对象上调用函数vif(),并查看命名列表输出:

*simple_lm <- lm(strength ~ ., data = concrete)
vif(simple_lm)*

尽管有许多变量得分为 5 或更高,但没有一个变量超过阈值10,因此我们认为多重共线性不是一个大问题。然而,有些人会争辩说,拥有这么多分数为 7 的特性确实是个问题。我们现在不会担心这个。**

至此,我们认为探索性数据分析(EDA)* 阶段已经结束,我们继续进行特性工程。你可以不同意这件事结束了!我相信还有很多探索要做。*

3)特征工程

对于数据科学家来说,特征工程也被认为是一项非常重要的技能。它包括从数据集中的现有要素生成新要素。这可以简单到从字符串列中提取一些日期信息,或者产生 交互术语 。此外,它肯定需要一定程度的主题专业知识和领域知识,因为提出新的信息特征是数据和整个应用领域的本质所固有的。

在这里,我们将超快,因为我们的数据似乎已经非常翔实和完整(工程师可能不同意!).

我想说的是,设计新要素很可能需要我们重复之前已经完成的一些分析,因为我们不想引入给数据集增加噪声的新要素。所以请记住,我们必须总是回头再看一遍我们的清单,并确定我们是否需要再分析一次。

3 .1)创建新的有用特征。互动术语。基础数学和统计学。使用 if-else 结构创建类别

因为我不是工程领域的主题专家,所以我不会从交互术语中创建新特性。我只限于验证是否有任何变量需要任何类型的转换。

我想做的第一件事是检查两个变量,它们似乎有不寻常的分布。就是agesuperplastic的情况。让我们绘制它们的原始形式,并在下面记录(红色)。

*par(mfrow = c(2,2))hist(concrete$age)
hist(concrete$superplastic)
hist(log(concrete$age), col = “red”)
hist(log(concrete$superplastic), col = “red”)*

虽然我觉得将age转换成对数形式很舒服,但是在superplastic,的观察值为 0 的情况下,当取 0 的对数时,我会有一些问题,所以我会取对数,然后手动将它们设置为 0。

下面是转换这两种功能的代码:

*concrete$age <- log(concrete$age)concrete$superplastic <- log(concrete$superplastic)
concrete$superplastic <- ifelse(concrete$superplastic == -Inf, 0,  
                                concrete$superplastic)head(concrete)*

注:我花了相当多的时间在这一点上试图创建一个新的宁滨的superplastic功能,原来的superplastic功能分为 3 个数字类别。然而,就解释目标变量的重要性而言,我没有取得多大成功。我不会展示这些尝试,但只知道我确实尝试了一段时间,但没有成功。失败也是学习的一部分!

3.2)为分类特征创建虚拟模型。优选地使用一位热编码

我们目前不使用分类特征,因此将跳过这一部分。然而,如果你看到了一些因子列,你必须确保你的算法能够处理它们,否则就对它们进行一次热编码。

3.3)我们可以使用正则表达式从字符串列中提取一些重要的文本吗?

我们目前不处理 sting 数据,因此将跳过这一部分。这应该是一个非常有用的工具,当你有一些字符类型的相关信息,你可以从中创建新的有用的类别。

谢天谢地,我们不必经历这一切!但是,如果我们要处理这类信息,最后三个部分是必须的。我将确保分析一个数据集,在其中我可以展示一些内容。

让我们进入数据准备阶段:

4)数据准备

4.1)手动特征选择。移除有噪声、无信息、高度相关或重复的要素。

这是我们在此工作流中第二次花时间查看我们的要素,并检测是否有任何要素信息不够丰富,或者由于引入了多重共线性等问题而应被删除。

正如我已经决定的那样,我将首先放弃ash功能(在尝试了一些基线模型后,你可能想要放弃它并删除它,如果它对性能没有帮助,我已经这样做了,所以我现在将放弃它,正如我最初的评估一样)

*concrete$ash <- NULLhead(concrete)*

除此之外,其他的我就不拆了。

4.2)如果需要,转换数据。如果需要,缩放或规格化。

我们将使用的大多数算法要求我们的数字特征被缩放或归一化(原因如下

我们不会在这个精确的部分这样做,但留待以后,因为脱字符允许我们在它的训练功能内做一些预处理。这特别有用,因为当向我们展示预测和结果时,该算法会自动转换回其原始比例。如果我在这里手动归一化数据集,那么我必须手动转换回预测。

4.3)自动特征提取。降维(主成分分析,NMF,t-SNE)

如果手动移除特征不够简单,但我们仍然认为数据集包含太多特征或太多相关特征,我们可以应用维度缩减技术。主成分分析就是其中的一种技术,这种技术非常有用,既可以简化我们的数据集,也可以永久消除多重共线性的问题。

非负矩阵分解(NMF) 和 t-SNE 是另外两种有用的降维技术。

我们的数据集中只有 8 个特征,1 个已经被手动删除,我不认为我们需要进一步降低维数。

4.4)我们的数据集是随机的吗?

我们不确定它是随机的,所以我们将随机播放以防万一:

*set.seed(123)
concrete_rand <- concrete[sample(1:nrow(concrete)), ]
dim(concrete_rand)*

4.5)定义评估方案:我们有多少样本?坚持方法。需要交叉验证吗?

我们有 1030 个样本,所以这绝对是一个小数据集。我们将数据集分为训练集和测试集,并确保在训练模型时使用交叉验证。通过这种方式,我们可以确保尽可能好地利用我们的少量观察数据。

4.6)将数据集分成训练和测试集(为可复制性设置种子)

我们首先创建一组预测值和一组目标变量

*X = concrete_rand[, -8]
y = concrete_rand[, 8]*

我们检查一切正常:

*str(X)*

*str(y)*

然后,我们继续将新的X(预测值)和y(目标值)集分成训练集和测试集。

注意:您不必将集合分开,并且可以使用公式方法完美地进行。我只是更喜欢这样做,因为这样我确信我的过程与我如何使用 Python 的 scikit-learn 是一致的。

我们将使用 caretcreateDataPartition()函数,它为我们生成分区索引,我们将使用它们来执行分割:

*set.seed(123)part.index <- createDataPartition(concrete_rand$strength, 
                                  p = 0.75,                         
                                  list = FALSE)X_train <- X[part.index, ]
X_test <- X[-part.index, ]
y_train <- y[part.index]
y_test <- y[-part.index]*

所以现在我们有 4 套。两个预测器集合拆分为序列测试,两个目标集合也拆分为序列测试。它们都使用相同的索引进行分区。

再一次,让我们检查一切工作正常:

*str(X_train)
str(X_test)
str(y_train)
str(y_test)*

好吧!我们可以走了!现在到建模阶段!

5)建模

正如我在导言中提到的那样,在这一阶段,我将改变我的方法,不再一一列举要做的事情,而是总结我们将如何进行。

  • 我们将使用包以便同时训练一系列模型
  • 由于 caret 的功能,这将允许我们对每个模型使用相同的 5 折交叉验证
  • 我们将允许并行处理来提高速度
  • 我们不会关注算法的本质。我们只是使用它们并对结果进行评论
  • 我们将使用一个线性模型,一个具有径向核的支持向量机,一个随机森林,一个梯度推进基于树的模型和一个梯度推进基于线性的模型
  • 我们不会进行手动超参数调整,相反,我们将允许插入符号在每个模型中进行一些默认调整
  • 我们将通过训练集和测试集来比较性能,重点关注作为我们度量标准的 RMSE (均方根误差)
  • 我们将使用来自 caretEnsemble 包的一个非常酷的功能,将集合模型列表,然后将它们堆叠起来,以尝试产生模型的最终组合,希望能进一步提高性能

所以我们继续吧。

我们首先在trainControl()中设置并行处理和交叉验证

**registerDoParallel(4)
getDoParWorkers()set.seed(123)my_control <- trainControl(method = “cv”, *# for “cross-validation”*
                           number = 5, *# number of k-folds*
                           savePredictions = “final”,
                           allowParallel = TRUE)**

然后,我们通过调用我们的X_trainy_train集合,使用caretList()函数训练我们的模型列表。我们用上面创建的trainControl对象指定trControl,并将methodList设置为算法列表(检查脱字符包信息以了解哪些模型可用以及如何使用它们)。

**set.seed(222)model_list <- caretList(X_train,
                        y_train,
                        trControl = my_control,
                        methodList = c(“lm”, “svmRadial”, “rf”, 
                                       “xgbTree”, “xgbLinear”),
                        tuneList = NULL,
                        continue_on_fail = FALSE, 
                        preProcess = c(“center”,”scale”))**
  • 我用的是X_trainy_train,但是你完全可以用y ~ x1 + x2 + … + xn公式来代替
  • my_control指定 5 重交叉验证并激活平行处理
  • tuneList为假,因为我们没有指定手动超参数调整
  • continue_on_fail设置为 FALSE,因此如果出现问题,它将停止
  • preProcessing中是我们缩放数据集的地方。我们选择“中心和“刻度

现在我们的caretList已经训练好了,我们可以看看结果了。我们可以访问每个单独的模型。这是 SVM 的结果:

**model_list$svmRadial**

请注意,caret 尝试对模型的可用参数进行一些自动调整,并使用 RMSE 作为性能度量来选择最佳模型。

这对于我们的型号列表中的其他型号都是一样的。我们不会逐一介绍。那是给你检查的!

让我们直接进入我们的目标,即找到具有最低 RMSE 的模型。我们首先对训练数据进行评估。

**options(digits = 3)model_results <- data.frame(
 LM = min(model_list$lm$results$RMSE),
 SVM = min(model_list$svmRadial$results$RMSE),
 RF = min(model_list$rf$results$RMSE),
 XGBT = min(model_list$xgbTree$results$RMSE),
 XGBL = min(model_list$xgbLinear$results$RMSE)
 )print(model_results)**

就 RMSE 而言, xgbTree 模型提供了最好的结果,得分为 4.36(记住平均强度为 35.8)。

caretEnsemble 提供了对该模型列表的性能进行重新采样并绘制的功能:

**resamples <- resamples(model_list)dotplot(resamples, metric = “RMSE”)**

我们还可以看到,xgbTree与其他型号相比,差异也更小。

接下来,我们将尝试通过组合我们的model_list来创建一个新模型,以便找到可能的最佳模型,希望这是一个采用我们已经训练的 5 个模型中的最佳模型并优化性能的模型。

理想情况下,我们将集成彼此相关性较低的模型。在这种情况下,我们将看到存在一些高度相关性,但我们将选择继续,只是为了展示这一特征:

**modelCor(resamples)**

首先,我们使用caretEnsemble()训练我们的模型集合,这将与所有模型执行线性组合。

**set.seed(222)
ensemble_1 <- caretEnsemble(model_list, 
                            metric = “RMSE”, 
                            trControl = my_control)
summary(ensemble_1)**

****

如我们所见,我们设法将训练集的 RMSE 减少到 4.156

这是我们合奏的一张图表

**plot(ensemble_1)**

红色虚线是该乐团的 RMSE 演出。

接下来,我们可以更具体地尝试使用其他算法与caretStack()进行集成。

注:我尝试了一些型号,但无法提高性能。我将展示其中一个在训练数据上产生相同性能的例子。无论如何,我们都将使用这两个集合,以便检查哪一个在处理看不见的数据时做得更好。

**set.seed(222)ensemble_2 <- caretStack(model_list, 
                         method = “glmnet”, 
                         metric = “RMSE”, 
                         trControl = my_control)print(ensemble_2)**

注意使用 glmnet 的最佳模型的 RMSE 是 4.15,与我们的第一个集合相同。

最后,是时候评估我们的模型在看不见的数据上的性能了,这些数据在我们的测试集中。

我们首先预测每个模型的测试集,然后计算 RMSE:

**# PREDICTIONS
pred_lm <- predict.train(model_list$lm, newdata = X_test)
pred_svm <- predict.train(model_list$svmRadial, newdata = X_test)
pred_rf <- predict.train(model_list$rf, newdata = X_test)
pred_xgbT <- predict.train(model_list$xgbTree, newdata = X_test)
pred_xgbL <- predict.train(model_list$xgbLinear, newdata = X_test)
predict_ens1 <- predict(ensemble_1, newdata = X_test)
predict_ens2 <- predict(ensemble_2, newdata = X_test)# RMSE
pred_RMSE <- data.frame(ensemble_1 = RMSE(predict_ens1, y_test),
                        ensemble_2 = RMSE(predict_ens2, y_test),
                        LM = RMSE(pred_lm, y_test),
                        SVM = RMSE(pred_svm, y_test),
                        RF = RMSE(pred_rf, y_test),
                        XGBT = RMSE(pred_xgbT, y_test),
                        XGBL = RMSE(pred_xgbL, y_test))print(pred_RMSE)**

令人惊讶的是,xgbLinear模型在测试集上的表现优于所有其他模型,包括我们的ensemble_1和匹配ensemble_2的性能

我们还观察到,一般来说,与训练集相比,在性能上存在差异。这是可以预料的。我们仍然可以尝试手动调整超参数,以减少一些过度拟合,但在这一点上,我相信我们已经在看不见的数据上实现了非常强大的性能,我将在未来的出版物中进一步优化。

我想展示的最后一件事是可变重要性。为了做到这一点,我将单独计算我们的xgbLinear模型,表明我想保留变量重要性,然后绘制它:

**set.seed(123)xgbTree_model <- train(X_train,
                       y_train,
                       trControl = my_control,
                       method = “xgbLinear”,
                       metric = “RMSE”,
                       preProcess = c(“center”,”scale”),
                       **importance = TRUE)**plot(varImp(xgbTree_model))**

这里我们可以看到变量agecement对混凝土的strength预测的高度重要性。这是意料之中的,因为我们已经在最初的相关图中观察到它们之间的高度相关性。

使用age的日志也让我们提高了可预测性(单独验证)。

注意图表中出现的一些“不重要”的特征。我们应该放弃他们吗?我们能否在不影响性能的情况下简化模型?如果我们出于任何原因需要一个更简单的模型,我们当然可以继续努力。

6)结论

这是一段不寻常的旅程!我们进行了大多数必要的步骤,以便执行一个完整而仔细的机器学习工作流程。尽管我们不必对从 csv 导入的原始数据进行大量的更改和转换,但我们确保理解了为什么以及我们应该做些什么。

此外,我能够展示一个人可以用 caretcaretEnsemble 做的有趣的工作,在做多种建模方面,快速和肮脏,并且能够快速比较模型性能。更高级的数据科学家和机器学习爱好者可能会将此作为第一稿,然后继续进行更高级的算法和精细的超参数调整,以获得额外的性能。为了这部作品,即使是基本配置,它也被证明是非常强大的。

在介绍中提到的书中,作者计算了预测值(使用具有 5 个隐含层的神经网络)和真实值之间的相关性,得到了 0.924 的分数。它还提到,与原始出版物(他的工作所基于的出版物)相比,这是一个重大的改进(原始出版物使用类似的神经网络获得了 0.885)

那么,我们是如何计算出与该书作者相同的相关分数的呢?

**pred_cor <- data.frame(ensemble_1 = cor(predict_ens1, y_test),
                       ensemble_2 = cor(predict_ens2, y_test),
                       LM = cor(pred_lm, y_test),
                       SVM = cor(pred_svm, y_test),
                       RF = cor(pred_rf, y_test),
                       XGBT = cor(pred_xgbT, y_test),
                       XGBL = cor(pred_xgbL, y_test))print(pred_cor)**

相当强劲的表现!

机器学习的贝叶斯超参数优化的概念解释

原文:https://towardsdatascience.com/a-conceptual-explanation-of-bayesian-model-based-hyperparameter-optimization-for-machine-learning-b8172278050f?source=collection_archive---------0-----------------------

使用贝叶斯优化的高效超参数调整背后的概念

以下是机器学习超参数优化的四种常用方法,按效率递增的顺序排列:

  1. 手动
  2. 网格搜索
  3. 随机搜索
  4. 基于贝叶斯模型的优化

(也有其他方法如进化和基于梯度的。)

我很自豪我最近从手工搜索上升到了随机搜索,直到我在 Bergstra 等人的论文中发现了这张图片:

Validation Errors comparing random search and a model based approach on LFW (left) and PubFig83 (right)

这些图比较了图像分类神经网络的超参数优化的验证误差,灰色为随机搜索,绿色为贝叶斯优化(使用 Tree Parzen 估计器或 TPE)。越低越好:验证集误差越小通常意味着测试集性能越好,试验次数越少意味着投入的时间越少。显然,贝叶斯方法有显著的优势,这些图表,以及其他令人印象深刻的结果,让我相信是时候采取下一步,学习基于模型的超参数优化了。

贝叶斯超参数优化的一句话总结就是:建立目标函数的概率模型,用它来选择真实目标函数中最有希望评估的超参数。

如果你喜欢在很高的层次上操作,那么这句话可能就是你需要的全部。然而,如果你想了解细节,这篇文章是我试图概述贝叶斯优化背后的概念,特别是基于序列模型的优化(SMBO)与树 Parzen 估计(TPE)。抱着这样一种心态,你不知道一个概念,除非你能向别人解释它,我查阅了几篇学术论文 论文,并将尝试以一种(相对)容易理解的格式交流结果。

虽然我们经常可以在不了解机器学习方法如何工作的情况下实现它们,但我喜欢尝试并了解正在发生的事情,这样我就可以尽可能有效地使用这项技术。在后面的文章中,我将通过使用诸如 Hyperopt 之类的库在 Python 中使用这些方法,因此本文将为即将到来的实现奠定概念基础!

更新:这是一个简短的 Jupyter 笔记本,展示了在 Hyperopt Python 库中使用基于贝叶斯模型的优化的基础。

超参数优化

机器学习中超参数优化的目的是找到给定机器学习算法的超参数,这些超参数返回在验证集上测量的最佳性能。(与模型参数相反,超参数是由机器学习工程师在训练之前设置的。随机森林中的树的数量是超参数,而神经网络中的权重是在训练期间学习的模型参数。我喜欢把超参数看作是要调整的模型设置。)

超参数优化以等式形式表示为:

这里 f(x)表示在验证集上评估的要最小化的客观分数,例如 RMSE 或错误率;x*是产生最低分值的超参数集,x 可以取域 x 中的任何值。简单地说,我们希望找到在验证集指标上产生最佳分值的模型超参数。

超参数优化的问题在于,评估目标函数以找到分数是极其昂贵的。每次我们尝试不同的超参数时,我们都必须根据训练数据训练一个模型,根据验证数据进行预测,然后计算验证度量。由于大量的超参数和复杂的模型,如需要数天时间训练的集成或深度神经网络,这一过程很快就变得难以手动完成!

网格搜索和随机搜索比手动调整略好,因为我们建立了模型超参数网格,并在循环中自动运行训练-预测-评估循环,同时我们做更有成效的事情(如特征工程)。然而,即使这些方法也是相对低效的,因为它们不基于先前的结果选择下一个超参数来评估。网格和随机搜索完全不了解过去的评估,因此,经常花费大量时间评估“坏的”超参数。

例如,如果我们有下面的图表,分数越低越好,那么我们应该在哪里集中搜索呢?如果你说低于 200 个估计量,那么你已经有了贝叶斯优化的想法!我们希望关注最有希望的超参数,如果我们有评估记录,那么使用这些信息进行下一步选择是有意义的。

随机和网格搜索根本不关注过去的结果,而是在估计量的整个范围内继续搜索,即使很明显最优答案(可能)在一个小区域内!

贝叶斯优化

贝叶斯方法,与随机或网格搜索相反,跟踪过去的评估结果,它们使用这些结果来形成概率模型,将超参数映射到目标函数得分的概率:

在文献中,这个模型被称为目标函数的“代理”,用 p(y | x)表示。替代函数比目标函数更容易优化,贝叶斯方法通过选择在替代函数上表现最佳的超参数来寻找下一组超参数以在实际目标函数上进行评估。换句话说:

  1. 建立目标函数的代理概率模型
  2. 找到在代理上表现最好的超参数
  3. 将这些超参数应用于真正的目标函数
  4. 更新包含新结果的代理模型
  5. 重复步骤 2-4,直到达到最大迭代次数或时间

贝叶斯推理的目标是用更多的数据“减少错误”,这些方法通过在每次评估目标函数后不断更新替代概率模型来做到这一点。

在高层次上,贝叶斯优化方法是有效的,因为它们以知情的方式 选择下一个超参数。基本思路是:多花一点时间选择下一个超参数,以便少调用目标函数。实际上,选择下一个超参数所花费的时间与目标函数所花费的时间相比是无关紧要的。通过评估从过去的结果看起来更有希望的超参数,贝叶斯方法可以在更少的迭代中找到比随机搜索更好的模型设置。

如果从这篇文章中有什么可以借鉴的话,那就是基于贝叶斯模型的方法可以在更短的时间内找到更好的超参数,因为它们可以根据过去的试验推理出要评估的最佳超参数集。

作为对贝叶斯优化中发生的事情的一个很好的可视化描述,请看下面的图片(来源)。第一幅图显示了两次评估后对代理模型的初步估计——黑色表示相关的不确定性,灰色表示。显然,代理模型是对红色实际目标函数的一个很差的近似:

下图显示了 8 次评估后的代理函数。现在代理几乎完全匹配真正的函数。因此,如果算法选择最大化代理的超参数,它们将可能在真实评估函数上产生非常好的结果。

贝叶斯方法对我来说总是有意义的,因为它们的运作方式与我们非常相似:我们形成对世界的初始看法(称为先验),然后我们根据新的经验更新我们的模型(更新后的模型称为后验)。贝叶斯超参数优化采用该框架,并将其应用于寻找模型设置的最佳值!

基于序列模型的优化

基于序列模型的优化(SMBO)方法(SMBO) 是贝叶斯优化的形式化。序列是指一个接一个地运行试验,每次都通过应用贝叶斯推理和更新概率模型(替代)来尝试更好的超参数。

基于模型的超参数优化有五个方面:

  1. 要搜索的超参数域
  2. 一个目标函数,接受超参数并输出我们想要最小化(或最大化)的分数
  3. 目标函数的代理模型
  4. 称为选择函数的标准,用于评估接下来从替代模型中选择哪个超参数
  5. 由算法用来更新代理模型的(分数,超参数)对组成的历史

SMBO 方法有几种变体,在步骤 3-4 中与有所不同,即它们如何构建目标函数的替代函数以及用于选择下一个超参数的标准。替代模型的几种常见选择是高斯过程、随机森林回归和 Tree Parzen 估计量(TPE),而第 4 步最常见的选择是预期改进。在本帖中,我们将重点关注 TPE 和预期的改进。

领域

在随机搜索和网格搜索的情况下,我们搜索的超参数的域是一个网格。随机森林的示例如下所示:

对于基于模型的方法,域由概率分布组成。与网格一样,这使我们能够通过在我们认为真正的最佳超参数所在的区域放置更大的概率来将领域知识编码到搜索过程中。如果我们想将上面的网格表示为概率分布,它可能看起来像这样:

这里我们有一个均匀的,对数正态的,正态分布。这些由先前的实践/知识提供(例如学习率域通常是几个数量级的对数正态分布)。

目标函数

目标函数接受超参数并输出我们想要最小化(或最大化)的单个实值分数。作为示例,让我们考虑为回归问题构建随机森林的情况。我们想要优化的超参数显示在上面的超参数网格中,最小化的分数是均方根误差。我们的目标函数看起来会像(用 Python 写的):

虽然目标函数看起来很简单,但是计算起来非常昂贵!如果可以快速计算目标函数,那么我们可以尝试每一个可能的超参数组合(就像网格搜索一样)。如果我们使用一个简单的模型,一个小的超参数网格和一个小的数据集,那么这可能是最好的方法。然而,在目标函数可能需要几个小时甚至几天来评估的情况下,我们希望限制对它的调用。

基于贝叶斯模型的优化的整个概念是通过基于对评估函数的先前调用仅选择最有希望的一组超参数进行评估来减少目标函数需要运行的次数。基于称为代理的目标函数的模型选择下一组超参数。

代理函数(概率模型)

代理函数也称为响应面,是使用以前的评估构建的目标函数的概率表示。这有时被称为响应面,因为它是超参数到目标函数得分概率的高维映射。下面是一个只有两个超参数的简单示例:

Response surface for AdaBoost algorithm (Source)

有几种不同形式的替代函数,包括高斯过程和随机森林回归。然而,在本帖中,我们将重点关注树形结构的 Parzen 估计量,如 Bergstra 等人在论文“超参数优化算法”中提出的。这些方法的不同之处在于它们如何构造代理函数,我们稍后会解释。首先我们需要谈谈选择函数。

选择功能

选择函数是从替代函数中选择下一组超参数的标准。最常见的标准选择是预期改进:

这里,y*是目标函数的阈值,x 是建议的超参数集,y 是使用超参数 x 的目标函数的实际值,p (y | x)是表示给定 x 时 y 的概率的代理概率模型。如果这都有点多,简单地说,目标是最大化相对于 x 的预期改进。这意味着在代理函数 p(y | x)下找到最佳超参数。

如果 p (y | x)处处为零,则 y < y*, then the hyperparameters x are not expected to yield any improvement. If the integral is positive, then it means that the hyperparameters x are expected to yield a better result than the threshold value.

树形结构 Parzen 估计器(TPE)

现在让我们回到代理函数。SMBO 的方法不同之处在于它们如何构造代理模型 p(y | x)。树形结构的 Parzen 估计器通过应用 Bayes 规则建立模型。它不是直接表示 p( y | x ),而是使用:

Bayes Rule in Action!

p (x | y)是给定目标函数分数的超参数的概率,其依次被表示为:

其中 y < y* represents a lower value of the objective function than the threshold. The explanation of this equation is that we make 超参数的两种不同分布:一种是目标函数值小于阈值l(x),另一种是目标函数值大于阈值 g(x)

让我们更新我们的随机森林图,以包括一个阈值:

现在我们为估计量的数量构造两个概率分布,一个使用产生低于阈值的值的估计量,另一个使用产生高于阈值的值的估计量。

直觉上,我们似乎想从 l(x) 而不是从 g(x) 中得出 x 的值,因为这种分布仅基于产生低于阈值的分数的 x 的值。事实证明,这正是数学上所说的!通过贝叶斯法则和一些替换,期望改善方程(我们试图最大化)变成:

最右边的术语是最重要的部分。这意味着预期改善与比率 l(x) / g(x) 成比例,因此,为了最大化预期改善,我们应该最大化该比率。我们的直觉是正确的:我们应该画出在 l(x) 下比在 g(x) 下更可能出现的超参数值!

树形结构的 Parzen 估计器的工作原理是从 l(x) 中抽取样本超参数,根据 l(x) / g(x) 对它们进行评估,并返回在 l(x) / g(x) 下产生最高值的集合,该集合对应于最大的预期改进然后根据目标函数评估这些超参数。如果代理函数是正确的,那么这些超参数应该在评估时产生更好的值!

预期改进标准允许模型平衡勘探和开采。 l(x) 是一个分布,而不是一个单一的值,这意味着绘制的超参数可能很接近,但不完全是预期改善的最大值。此外,因为代理只是目标函数的估计,所以当评估时,所选择的超参数可能实际上不会产生改进,并且代理模型将必须被更新。这种更新是基于当前代理模型和目标函数评估的历史来完成的。

历史

每当该算法提出一组新的候选超参数时,它用实际的目标函数对它们进行评估,并将结果记录在一对(得分、超参数)中。这些记录构成了的历史。该算法使用历史来构建 l(x)g(x) 以得出随着每次迭代而改进的目标函数的概率模型。

这是贝叶斯法则在起作用:我们对目标函数的代理有一个初始估计,当我们收集到更多的证据时,我们会更新这个估计。最终,通过对目标函数进行足够的评估,我们希望我们的模型准确地反映目标函数,并且产生最大预期改进的超参数对应于最大化目标函数的超参数。

综合考虑

基于序列模型的方法如何帮助我们更有效地搜索超参数空间?因为该算法提出了用于评估的更好的候选超参数,所以目标函数的分数比随机或网格搜索提高得更快,从而导致目标函数的整体评估更少。

即使该算法通过最大化期望的改进花费更多的时间来选择下一个超参数,这在计算成本方面比评估目标函数便宜得多。在一篇关于使用 SMBO 和 TPE 的论文中,作者报告了寻找下一组候选超参数需要几秒钟,而评估实际目标函数需要几个小时。

如果我们使用更明智的方法来选择下一个超参数,这意味着我们可以花更少的时间来评估糟糕的超参数选择。此外,使用树形结构 Parzen 估计器的基于序列模型的优化能够在相同次数的试验中找到比随机搜索更好的超参数。换句话说,我们得到

  • 减少超参数调整的运行时间
  • 测试集上更好的分数

希望这能让你相信基于贝叶斯模型的优化是一项值得尝试的技术!

履行

幸运的是,现在有很多库可以用 Python 来做 SMBO。 Spearmint 和 MOE 使用高斯过程作为替代,hyperpt使用树形结构 Parzen 估计器, SMAC 使用随机森林回归。这些库都使用预期改进标准从代理模型中选择下一个超参数。在后面的文章中,我们将看看如何在 Python 中使用 Hyperopt,已经有几篇好的文章和代码示例供学习。

结论

基于贝叶斯模型的优化方法构建目标函数的概率模型,为下一组待评估的超参数提出更明智的选择。SMBO 是贝叶斯优化的形式化,它在为机器学习模型寻找最佳超参数方面比随机或网格搜索更有效。

基于序列模型的优化方法在构建代理方面有所不同,但它们都依赖于来自先前试验的信息来为下一次评估提出更好的超参数。Tree Parzen 估计器是一种使用贝叶斯推理来构建代理模型的算法,并且可以使用预期改进来选择下一个超参数。

Python 中有许多实现 SMBO 的库,我们将在后续文章中探讨。这些概念一开始有点难,但是理解它们将允许我们更有效地使用基于它们构建的工具。我想说的是,我仍在努力解决细节问题,如果我犯了错误,请让我知道(礼貌地)!

要了解更多详细信息,以下文章非常有用:

  1. 超参数优化算法[ 链接
  2. 创建模型搜索的科学:视觉架构的数百维超参数优化[ 链接
  3. 贝叶斯优化初级读本[ 链接
  4. 把人带出循环:贝叶斯优化的回顾[ 链接

一如既往,我欢迎反馈和建设性的批评。可以在推特上找到我

神经网络简史

原文:https://towardsdatascience.com/a-concise-history-of-neural-networks-2070655d3fec?source=collection_archive---------0-----------------------

“从我们个人设备内部贫瘠的土地上,传来了那些有朝一日将成为我们霸主的数字仆人偷偷哼唱的颂歌”

人工智能冬季

毫不奇怪,神经网络的想法最初是作为大脑中神经元如何运作的模型出现的,被称为“连接主义”,并使用连接电路来模拟智能行为。1943 年,神经生理学家沃伦·麦卡洛克和数学家沃尔特·皮茨用一个简单的电路描绘了它。唐纳德·赫布(Donald Hebb)在他的著作《行为的组织》(The Organization of Behaviour,1949)中进一步发展了这一观点,提出神经通路在每次连续使用后都会加强,尤其是在倾向于同时放电的神经元之间,从而开始了量化大脑复杂过程的漫长旅程。

作为神经网络前身的两个主要概念是

  • “阈值逻辑”——将连续输入转换为离散输出
  • “赫比学习”(hebbian Learning)——一种基于神经可塑性的学习模式,由唐纳德·赫比(Donald Hebb)在其著作《行为的组织》(The Organization of Behaviour)中提出,通常用一句话来概括:“一起放电的细胞,连接在一起。”

两者都是在 20 世纪 40 年代提出的。在 20 世纪 50 年代,当研究人员开始尝试将这些网络转换到计算系统上时,第一个 Hebbian 网络于 1954 年在麻省理工学院成功实现。

大约在这个时候,康奈尔大学的心理学家弗兰克·罗森布拉特(Frank Rosenblatt)正致力于理解苍蝇眼中相对简单的决策系统,这些系统是苍蝇逃跑反应的基础和决定因素。为了试图理解和量化这一过程,他在 1958 年提出了感知机的概念,称之为 Mark I 感知机。这是一个具有简单输入输出关系的系统,以麦卡洛克-皮茨神经元为模型,由神经科学家沃伦·s·麦卡洛克和逻辑学家沃尔特·皮茨在 1943 年提出,以使用线性阈值门来解释大脑中复杂的决策过程。麦卡洛克-皮茨神经元接受输入,进行加权求和,如果结果低于阈值,则返回“0”,否则返回“1”。

A McCulloch-Pitts neuron

Mark I 感知器的优点在于,它的权重可以通过连续传递的输入来“学习”,同时最小化期望输出和实际输出之间的差异。

First known implementation of a Mark I Perceptron. The machine was connected to a camera that used 20×20 cadmium sulfide photocells to produce a 400-pixel image. The main visible feature is a patchboard that allowed experimentation with different combinations of input features. To the right of that are arrays of potentiometers that implemented the adaptive weights.[wiki]

一个主要的缺点?这种感知器只能学习分离线性可分的类,使得简单但非线性的异或电路成为不可逾越的障碍。

尽管使用机器学习来量化除大脑之外的决策系统出现了混乱和有些令人不满意的情况,但今天的人工神经网络只不过是这些感知机的几层。

大约在这个时候,神经网络开始迅速发展。1959 年,伯纳德·维德罗和马尔西安·霍夫在斯坦福开发了第一个成功应用于现实世界问题的神经网络。这些系统因使用了多种自适应线性元件而被命名为 ADALINE 和 MADALINE,后者是专门为消除电话线中的噪声而设计的,至今仍在使用(!).然而,这些人工神经元与感知器的不同之处在于它们返回的输出,在这种情况下是加权输入。

正如历史上人工智能技术的每一次小进步一样,这些早期的成功导致了对神经网络能力和潜力的越来越多的炒作,而研究人员却遇到了一个又一个的路障。在围绕这些“思维机器”的宣传达到高潮时,纽约时报发表了这篇关于神经网络潜力的文章,而这段视频也在大约同一时间发布。

就像之前的几次“千钧一发”一样,我们仍然没有像我们一直喜欢相信的那样(或者恐惧,取决于你如何看待它)接近喷出有意识的人造生命。出现的问题之一是运行这些网络所需的不切实际的长运行时间,因为这是 60 年代,除了它不能学习简单的布尔异或电路。

1969 年,随着麻省理工学院人工智能实验室创始人马文·明斯基和实验室主任西蒙·派珀特合著的《感知机》一书的出版,这一切都告一段落。这本书最终认为,罗森布拉特对神经网络的单一感知方法不能有效地转化为多层神经网络。基于最终输出来评估跨层分布的神经元的权重的正确相对值将花费若干次(如果不是无限次的话)迭代,并且将花费非常长的时间来计算。

明斯基在他的文章中阐述了神经网络的这些和其他问题,并有效地引导了更大的科学界,最重要的是资助机构得出结论,在这个方向上的进一步研究是没有结果的。这篇文章的影响是巨大的,在接下来的 10-12 年里,没有人在当时最大的研究机构中,也没有人在较小的研究机构中,承担任何以注定失败的神经网络为前提的项目。现在被称为“人工智能冬天”的时代开始了。

这十年漫长冬天的解冻始于 1982 年,当时 Jon Hopfield 在美国国家科学院提交了他的论文,该论文后来被称为 Hopfield Net 同年,在美日合作/竞争神经网络会议上,日本宣布打算开始其第五代神经网络研究。这使得资金从一个害怕被抛在后面的国家的金库中重新开始流动。不久,美国物理研究所于 1985 年建立了“计算中的神经网络”年会,随后由电气和电子工程师协会(IEEE)于 1987 年召开了第一次神经网络国际会议。

然而,这是对自 60 年代以来就存在的概念的重大重新发现,帮助神经网络走出了它过早的坟墓。反向传播,一种自 60 年代以来由研究人员设计并持续发展到人工智能冬天的方法,是一种基于直觉的方法,随着人们在事件链中走得更远,它将每个事件的重要性降低。第一个看到它们在神经网络方面的潜力并解决如何将其转化为 MLP 氏症的问题的人是保罗·沃博斯,他部分受到了神经网络在人类思维中的应用以及弗洛伊德关于学分分配逆向流动的工作的启发,写了一篇博士论文阐述了它们的重要性。然而,直到 1985 年帕克在麻省理工学院发表了一份关于他的工作的报告,这项工作才被社区中的任何人注意到。只是在被 Rumelhart、Hinton 和 Williams 重新发现并在一个清晰而详细的框架中重新发表后,这项技术才在社区中引起了轰动。这些作者还在后来的文本中提到了明斯基在 1969 年的出版物中列出的具体缺点。

反向传播和梯度下降形成了神经网络的主干和动力。虽然梯度下降不断更新权重和偏差并将其移向成本函数的最小值,但反向传播通过权重和偏差来评估成本的梯度,梯度下降使用其大小和方向来评估权重和偏差参数的校正大小和方向。

A simple visual description of the movement towards the minima of a 2d function. The step-size of jump is determined by the value of the gradient at each point.

因此,到了 20 世纪 90 年代,神经网络肯定又回来了,这一次真正抓住了世界的想象力,并最终达到了它的期望,如果不是超越的话。然而,我们再次向人工智能提出同样的问题,并把我们所有人的恐惧投射到它身上,然而,我们再次比我们想象的更远离向我们的数字霸主低头。

如果你喜欢阅读这样的故事,并想支持我的写作,请考虑注册成为一名灵媒会员。每月 5 美元,你可以无限制地阅读媒体上的所有报道。如果你使用 我的链接 注册,我会收到一点佣金。

拓扑数据分析的一个具体应用

原文:https://towardsdatascience.com/a-concrete-application-of-topological-data-analysis-86b89aa27586?source=collection_archive---------5-----------------------

今天,我将介绍一个机器学习应用拓扑数据分析 (TDA),这是一个快速发展的数据科学领域,它利用拓扑来改进数据分析。这很大程度上是从我的一个项目中的得到的灵感。

太好了!等等……TDA 是什么?

我将首先简要回顾一下 TDA 的基本情况。感兴趣的读者可能还想看看的其他 故事(以及其中的所有参考文献)了解更多细节。

TDA 是一种基于数学的理论,旨在使用数据的拓扑来表征数据,而是通过计算拓扑性质的特征来完成的。最常见的是持久性图,它采用对角线上方平面中一组点的形式。

Example of persistence diagram computed with the library Gudhi. Source: http://gudhi.gforge.inria.fr/python/latest/persistence_graphical_tools_user.html

每个这样的点代表数据的一个拓扑特征(如一个连接的组件、一个孔或一个空腔)。此外,点到对角线的距离作为相应特征的重要性的指示,通常的解释是靠近对角线的点可能是由于噪声。

这样的图的计算需要一个过滤,也就是一个增长空间的序列:序列中的每个空间都包含在下一个中。例如,给定一个点云,一个可能的过滤是计算以半径递增的点为中心的球的联合。

Example of union of balls filtration.

这个想法是,对于序列中的每个空间,记录一个拓扑特征是在那个空间中被创建还是被破坏。例如,如果我们考虑球过滤的联合,可能发生的情况是,对于某些半径,球联合包含一个孔,该孔持续一段时间,直到当球具有足够大的半径时最终被填满,这正是上面显示的过滤中发生的情况。然后,这些半径可用作坐标,在平面上创建一个代表该孔的点。

听起来不错,但是…我想要一份申请!

持久性图在数据分析的各个领域都有很多应用。在这篇笔记中,我将介绍几何处理中的一个可视化应用,即 3D 形状分割

3D 形状通常在计算机中存储为一组点、边和三角形。分割的目标是为每个形状的每个点提供标签。例如,如果给你一堆代表人类的 3D 形状,分割的目标是成功地为每个点分配它所属的身体部位(“躯干”、“手臂”、“腿”…)。

Segmented 3D human shapes. The different colors correspond to the different labels or parts. Source: https://people.cs.umass.edu/~kalo/papers/LabelMeshes/

这个问题的难点在于,只给你点坐标,这是很差的特征。事实上,用一个点的坐标来描述它是不可能的,因为它们依赖于 3D 形状的嵌入或姿态。例如,想象两个人形,其中一个举起右手,另一个没有;人类是相同的,只是他们的姿势不同。然后,这两个形状的右手点会有很大的不同,即使它们共享相同的标签。

TDA 来救援了!

这就是持久性图发挥作用的地方。由于它们的拓扑性质,持久性图是固有的,这意味着它们不依赖于 3D 形状的嵌入或姿态。因此,它们是点要素的良好候选对象。为此,我们需要定义一个内在过滤。

这可以通过测地线距离来实现。3D 形状上两点之间的测地线距离是该形状上两点之间最短路径的长度。你可以把它想成一只蚂蚁从第一个点到第二个点所走的路径长度。这个距离显然是固有的,因为蚂蚁行走的路径与 3D 形状的姿态无关。

Example of geodesic distances computed for various pair of points on a 3D camel shape. Source: http://www.numerical-tours.com/matlab/shapes_2_bendinginv_3d/

测地线距离可以用来定义测地线球。半径为r0 且以点 x 为中心的测地线球,就是到 x 的测地线距离小于或等于 r 的形状的点集。同样,通过使 r 从 0 增加到无穷大,我们使测地线球从单个的 {x} 增长到整个形状本身,这给了我们一个内在的过滤。现在,为了计算相应的持续图,我们记录球中发生拓扑事件的半径,并将它们用作坐标。在 3D 形状的情况下,拓扑事件是非常有限的:由于 3D 形状是连接的表面,所以它们的固有维度是 2(实际上,3D 形状局部看起来像平面),唯一可能发生的拓扑事件是球中出现或填充孔。例如,看看下面 3D 手形上显示的过滤。

Example of geodesic ball filtration computed for a point located on the palm of a 3D hand shape.

增长的测地线球显示为红色,而形状的其余部分显示为蓝色。对于前三个半径,测地线球没有有趣的拓扑结构:它看起来就像一个圆盘。然而,对于第四个半径,五个手指中的每一个都在测地线球中创建了一个洞:出现了五个拓扑事件。它们持续到第五个半径,最终在第六个半径被填满。相应的持久性图,如下图所示,包含五个点。

Each point of the persistence diagram corresponds to a specific finger of the shape.

更有趣的是,如果我对位于形状另一部分的点应用相同的过程,那么图表将会不同。例如,让我们考虑位于中指上的点:

Geodesic ball filtration computed for a point located on the middle finger.

所有手指将再次在测地线球中创建孔,但半径不同。例如,对应于中指的孔出现并被填充的时间比第一次过滤早得多。在余辉图中,相应的点离其他点较远。

The point corresponding to the middle finger (pink) is far from the others.

一般来说,根据 3D 形状点(用于计算图)所属的位置或部分,持久性图点具有不同的配置。这说明了这样一个事实,持久化图是分段的精确描述符。我实现了计算这种图的代码:如果你想试试的话,请看我的 Github。

该学习了!

终于!既然我们已经有了点的一个好的特征或描述符,我们就可以开始机器学习(ML)了。

还是我们?

持久性图的一个大问题是它们的非结构化形式:持久性图是可能包含不同数量的点的集合。它们不像传统的欧几里得向量那样容易处理,传统的欧几里得向量是 ML 算法的常见食物。这就是为什么目前 TDA 社区正致力于寻找在 ML 中处理持久性图的方法。到目前为止,两种主要的方法要么是从图中计算矢量(比如持久图像或风景),要么是在图上定义内核并使用内核化的 ML 算法(比如 PCA 或 SVM)。详见这个故事。

我在一个兼容 scikit-learn 的 python 包中实现了大部分方法。我再次向感兴趣的读者推荐我的 Github 。多亏了这个软件包,所有的方法都可以在一个大的交叉验证过程中进行比较和使用。在我的笔记本中,我用它来分割一堆代表不同大小和形状的飞机的 3D 表面(见下面的代码样本)。最终准确率可以达到 90%,考虑到任务的难度,这已经相当不错了!

**import** **sklearn_tda** **as** **tda**
**from** **sklearn.pipeline**        **import** Pipeline
**from** **sklearn.svm**             **import** SVC
**from** **sklearn.ensemble**        **import** RandomForestClassifier
**from** **sklearn.neighbors**       **import** KNeighborsClassifier

*# Definition of pipeline*
pipe = Pipeline([("Separator", tda.DiagramSelector(limit=np.inf, point_type="finite")),
                 ("Rotator",   tda.DiagramPreprocessor(scalers=[([0,1], tda.BirthPersistenceTransform())])),
                 ("TDA",       tda.PersistenceImage()),
                 ("Estimator", SVC())])

*# Parameters of pipeline. This is the place where you specify the methods you want to use to handle diagrams*
param =    [{"Rotator__use":        [**False**],
             "TDA":                 [tda.SlicedWassersteinKernel()], 
             "TDA__bandwidth":      [0.1, 1.0],
             "TDA__num_directions": [20],
             "Estimator":           [SVC(kernel="precomputed")]},

            {"Rotator__use":        [**False**],
             "TDA":                 [tda.PersistenceWeightedGaussianKernel()], 
             "TDA__bandwidth":      [0.1, 1.0],
             "TDA__weight":         [**lambda** x: np.arctan(x[1]-x[0])], 
             "Estimator":           [SVC(kernel="precomputed")]},

            {"Rotator__use":        [**True**],
             "TDA":                 [tda.PersistenceImage()], 
             "TDA__resolution":     [ [5,5], [6,6] ],
             "TDA__bandwidth":      [0.01, 0.1, 1.0, 10.0],
             "Estimator":           [SVC()]},

            {"Rotator__use":        [**False**],
             "TDA":                 [tda.Landscape()], 
             "TDA__resolution":     [100],
             "Estimator":           [RandomForestClassifier()]},

            {"Rotator__use":        [**False**],
             "TDA":                 [tda.BottleneckDistance()], 
             "TDA__wasserstein":    [1],
             "TDA__delta":          [0.1], 
             "Estimator":           [KNeighborsClassifier(metric="precomputed")]}
           ]

最后一句话…

几何处理只是 TDA 众多可能应用中的一种。这个领域非常活跃,因为它连接了从代数拓扑到计算机科学的不同数学领域,越来越多的人正在成为 TDA 爱好者。不要错过火车!;-)

语言与代码的融合

原文:https://towardsdatascience.com/a-convergence-of-language-with-code-a3965d8953e3?source=collection_archive---------9-----------------------

你好,我叫托马斯,我叫托马斯,名字是(x):返回托马斯。在我的生活中,我学习了多种语言,每种语言都有自己的软木塞、语法和实用性,并且每种语言都有不同的学习风格。在伦敦的高中学习法语三年,师从老师,互动语言实验室,以及在法国南部/中部的暑期沉浸式项目。在南非美丽的 Matlerekeng 和 Enable 村,我在和平队服务期间,通过现场互动和与讲母语的人在小组中进行长达一小时的交谈,学会了 Sepedi,也被称为 Northern Sotho。现在,面对一种新的语言和新的方法,我开始学习数据科学的语言(如 Python、SQL 和统计学等)。)在为期 12 周的训练营。这些经历中的每一种都是用不同的语言教给我的,带来了新的学习方法和新的问题,每一种都提出了自己的挑战和不断增长的知识,但随着我的技能不断扩展,它们之间的相似之处都出现了。

如果让你选择学习法语、Sepedi 和一门计算机语言,一开始你可能会认为你必须用不同的方式来学习。然而,我的经验告诉我,虽然个人的教学风格可能不同,但效果最好的整体方法几乎是一致的。它们都是从教你较小的细节开始的,这样当你接近较大的短语时,你就知道在引擎盖下发生了什么。在口语中,这可以是知道我、我、她、他、我们之间的区别,而 python 代码可以学习 import x as、统计数学以及==、=、or!=.事实上,理解这三种语言中发生的事情的最基本的方法是能够翻译成你的母语。对于编码来说,就是在你的代码中留下尽可能多的易于阅读的注释,以便其他人理解你的目标和方法。对于像法语和西班牙语这样的语言来说,那就是知道如何说“我不理解”。“这是英国的还是法国的传统?”(我不明白。用英语或传统法语怎么说?或者“Aowa,ga re kwisisa。ke sekgowa ke __ ke English ne?”(我不明白。用英语翻译是什么?).所有这些都为学习者提供了一种将新语言与母语联系起来的方法。在学习了基本的日常用语后,下一步的学习是沉浸在语言中,无论是在教室里说法语,和只说西班牙语或支离破碎的英语的家庭一起生活,还是从周一到周五朝九晚五地被代码包围。这种沉浸感不仅迫使你为了生存而学习,有时是字面上的,而且让你学会一门语言的真正本质。我所说的语言的“真正本质”是指,当一种语言被教授时,大部分时间是在教科书/上层阶级的术语中完成的,这通常意味着当从教室带到现实世界时,术语会发生变化。当你完全沉浸其中时,你就学会了事物的速记,学会了语气和语境是如何改变一个词的整个含义,并把你和你周围的文化联系起来。沉浸的最终结果是,单词或代码成为第二天性,即使你远离它们多年,当再次被扔进文化中时,你的大脑总会有一部分记得。

在口语中,单词的变化取决于性别、连接词和时态。例如,在法语 to 中,当从 I 到 we 时,它从 Je 到 Nous,在 Sepedi 中,它从 Rena re 到 Nna ke。虽然计算机代码不会像语言那样改变,但它会根据相似的变量改变,只是名字不同而已。对于编码来说,它是列表类型、For 或 while 循环、if-else 语句和一系列计算机软件包,每个软件包在解释手头的情况时都有其特定的作用,就像口语动词表一样。

虽然罗曼语、班图语和计算机语言初看起来就像相隔千里的苹果和橙子一样亲密,并且创造了几个世纪,但这三种语言有几个重叠的特征。也许最常见的字符串是它们在直接翻译成简单英语时的字面意思。一个简单的例子就是说“天气很热。都 85 度了!”必须用每种语言一步一步清晰地拼写/说出。

法语:这是真理。这是四分之一夜!

天气很热。它是四十五度

塞佩迪:莱霍诺加油,加油,加油!

今天是个大热天。已经 85 度了!

对于 Python:

temperature=85
if temperature >= 85:
    return "It is hot. It is " +str(tempeture) + "degrees!"
else if temperature <85:
    return "It is not so hot. It is" +str(tempeture) + "degrees."
Output[] It is hot. It is 85 degrees!

在一个充斥着来自不同大洲和不同终端的数千种语言的世界里,人们常常忘记这些语言是如何容易和流畅地连接在一起的。他们可能没有相同的单词或起源,但当你了解他们每个人时,你可以看到他们在措辞、情景变化以及他们想要理解对方单词方面的相似之处。最后,虽然从表面上看,我们所有的交流可能看起来不同,但他们都试图与他人联系,帮助他人了解彼此的世界正在发生什么。

关于深度学习的对话

原文:https://towardsdatascience.com/a-conversation-about-deep-learning-9a915983107?source=collection_archive---------11-----------------------

有人无意中听到两个人谈论深度学习,让我知道每一个小细节。其中一个完全反对深度学习,另一个不仅是该领域的捍卫者,而且真的知道这个主题。

为了保密,我称第一个人为 A 先生(“憎恨者”)和 B 女士(“专家”)。

这是 A 先生:

嗨!

这位是 B 女士:

嗨!

甲先生:你好乙!你好吗

B 女士:棒极了 A!很高兴见到你。我没想到会在深度学习会议上见到你。

A 先生:是的,我来看看这些疯子在说些什么,我是对的。深度学习烂透了。这只是我在大学学习的关于神经网络的老东西,现在你添加更多的层,就是这样!没什么有趣的东西可看。

女士 B:哇,这是一个大的声明,我很抱歉你看到这样的事情。实际上,深度学习只是人工智能世界中正在发生的事情的一个品牌。你可以称之为“炒作”,但那里有非常重要的发展。你想来我的电脑吗?我带你去看。

我不知道重点,但是我现在没有别的地方可去,我们走吧。

B 女士:那么,让我们从基础开始,你对深度学习了解多少?

答:我读到过,它们是一些模拟我们大脑工作方式的算法,这就是“神经网络”这个名称的来源,我们的大脑。他们找到了一种方法将其抽象成数学、微积分和代码。然后,有了它,系统可以像我们一样学习,或者他们这么说,使用这些老式的神经网络来解决系统遇到的一些问题。哦,顺便说一下,他们不知道如何解释他们的模型,只是另一个黑盒。

B 女士:好的。我想你可能在读一些关于深度学习的奇怪的东西。我从基础开始。在机器学习的上下文中,“学习”一词描述了一个自动搜索过程,以更好地表示您正在分析和研究的数据。看看我在网上找到的这个例子:

假设我告诉你,我想让你画一条线,将这个图的蓝色圆圈和绿色三角形分开:

你会怎么做?

A 先生:再问一下线的定义是什么?

女士 B:让我们说是直的一维图形,没有厚度,在两个方向上无限延伸。

A:好的,如果是那样的话,这是一个不可能完成的任务。我不能在那里放一条线。

B 女士:如果我现在展示这张照片,并请你也这样做,你会说什么?

A:哦,那很简单,中间有一条线就行了。但这是欺骗,这是一个不同的数据集。这一行应该是这样的:

B 女士:很好,但这实际上是我之前介绍过的同一个数据集。

A 先生:什么?不,另一个是圆形的,这不一样。

B 女士:我给你解释一下。在这种情况下,我做了一个坐标转换,所以我们可以用一种我们可以画这条线的方式来绘制或表示这些数据。数据是相同的,但是表示是不同的。碰巧的是,在新的表示中,画这条线是一项简单的任务。

A 先生:好的,我明白你的意思。但是这和深度学习有什么关系呢?还是机器学习?

B 女士:深度学习是机器学习的一个子集。而是表征学习中一个非常特殊的子集。深度学习使我们能够创建一个系统,一个程序,它可以搜索不同的表示(在这种情况下是坐标变化),然后找到一种方法来计算类别被正确分类的百分比,当我们这样做时,我们正在进行深度学习,当然还有机器学习。

A 先生:听起来很棒。但是我们几十年前看到的老式神经网络呢?为什么现在有这么重要?以及它们在深度学习中的作用是什么?

B 女士:这是一个非常好的问题。我们可以将深度学习定义为使用不同类型的神经网络的表示学习,并优化网络的超参数,以获得(学习)我们数据的最佳表示。但是为什么是神经网络呢?它们非常灵活,让我们找到高度非线性数据的有用表示,就像我之前给你展示的那样。这个概念并不新鲜,但我们现在用来构建它们的工具与过去非常不同。他们拥有人工智能和机器学习领域的所有重大进步。

A 先生:它们是相同的神经网络,但唯一不同的是工具?比如编程语言?

B 女士:在某种程度上这是真的。但是还有更多。直到 2000 年代末,我们仍然缺少一种可靠的方法来训练非常深度的神经网络。我们多年来一直在研究这一理论,但现在,随着几项重要的理论和算法改进的发展,硬件的进步,以及数据的指数级生成和积累,深度学习自然而然地适应了这一缺失,从而改变了我们进行机器学习的方式。现代语言允许我们对这些理论部分进行编程,借助分布式计算和大数据的力量,我们成功创造了这场革命。

A 先生:听起来很有趣。你提到的这些理论上的进步和改进是什么?

B 女士:它们来自全世界多年的调查。有些来自大型大学或公司,但也有来自开源世界的巨大贡献。没有这些花里胡哨的补助金什么的。实际上我找到了一个时间线可以帮我解释给你听。看一看:

你是对的,这是一个古老的理论。但这并不意味着它不再相关。从那里我可以说反向传播的思想,网络参数的更好初始化,更好的激活函数,辍学的概念,以及一些类型的网络,如卷积神经网络,残差网络,区域基 CNN,递归神经网络和生成对抗网络,是我们在深度学习领域取得的最重要的进展之一。我希望我能有时间向你们解释所有的问题,但遗憾的是,我必须赶去参加下一个会议!

答:好的,现在我想我更明白“深度学习”是怎么回事了。你从没告诉我深度学习这几个字的意思。

B 女士:你说的对!深度学习中的深度并不是指通过这种方法实现的任何一种更深入的理解;更确切地说,它代表了连续层表示的思想。像这样:

学习就是我之前告诉你的,它是一个自动搜索过程,以更好地表示我们拥有的数据,目标是理解模式,做出预测,并对我们周围的世界进行建模。

甲先生:谢谢乙!在离开我之前,你能推荐一些关于这个主题的好读物吗?

B 女士:当然可以!我会有一份文件,让我找一下…在这里!请写下它们,并在你离开后锁上门。很高兴见到你!回头再聊!

[## 如何训练你的深度神经网络

为了有效地训练深度神经系统,深度学习中有一些特定的实践是非常值得推荐的。

rishy.github.io](http://rishy.github.io/ml/2017/01/05/how-to-train-your-dnn/) [## 用于视觉识别的 CS231n 卷积神经网络

斯坦福 CS231n 课程材料和笔记:视觉识别的卷积神经网络。

cs231n.github.io](http://cs231n.github.io/neural-networks-2/#init) [## 理解神经网络中的激活函数

最近,我的一个同事问了我几个类似“为什么我们有这么多激活功能?”,“为什么是…

medium.com](https://medium.com/the-theory-of-everything/understanding-activation-functions-in-neural-networks-9491262884e0) [## 激活函数:神经网络

Sigmoid,tanh,Softmax,ReLU,Leaky ReLU 解释!!!

towardsdatascience.com](/activation-functions-neural-networks-1cbd9f8d91d6) [## 为了学得更好而学得更少——在(深度)机器学习中辍学

在这篇文章中,我将主要讨论神经网络中的辍学概念,特别是深度网络,然后是…

medium.com](https://medium.com/@amarbudhiraja/https-medium-com-amarbudhiraja-learning-less-to-learn-better-dropout-in-deep-machine-learning-74334da4bfc5) [## 使用 Python 进行深度学习

我见过的对深度学习最清晰的解释...阅读是一种乐趣。

www.manning.com](https://www.manning.com/books/deep-learning-with-python) [## 深度学习基础

关于这门课,上一堂速成课,学习内容是什么,以及如何学习更多。深度学习…

cognitiveclass.ai](https://cognitiveclass.ai/courses/introduction-deep-learning/) [## Python 中的深度学习| DataCamp

深度学习是机器人等不同领域中最令人兴奋的能力背后的机器学习技术…

www.datacamp.com](https://www.datacamp.com/courses/deep-learning-in-python) [## 深度学习的“怪异”介绍

有关于深度学习的惊人介绍、课程和博文。但这是一种不同的介绍…

towardsdatascience.com](/a-weird-introduction-to-deep-learning-7828803693b0) [## 主页

我们想邀请您在 3 月 26 日至 29 日的 GPU 技术大会上加入 Deep Cognition 的团队,展位号为 1035…

deepcognition.ai](http://deepcognition.ai/) [## 使用 Apache Spark 进行深度学习—第 1 部分

第一部分全面讨论了如何使用 Apache Spark 进行分布式深度学习。这一部分:什么是火花…

towardsdatascience.com](/deep-learning-with-apache-spark-part-1-6d397c16abd) [## 使用 Apache Spark 进行深度学习—第 2 部分

第二部分全面讨论了如何使用 Apache Spark 进行分布式深度学习。我将完全专注于…

towardsdatascience.com](/deep-learning-with-apache-spark-part-2-2a2938a36d35) [## deeplearning.ai

探索 AI 前沿。

www.deeplearning.ai](https://www.deeplearning.ai) [## 西拉伊·拉瓦尔

我是西拉杰。我正在为激励和教育开发人员构建人工智能而奋斗。游戏、音乐、聊天机器人…

www.youtube.com](https://www.youtube.com/channel/UCWN3xxRkmTPmbKwht9FuE5A) [## 深度认知让深度学习变得简单

在过去的一个月里,我有幸见到了 DeepCognition.ai 的创始人

becominghuman.ai](https://becominghuman.ai/deep-learning-made-easy-with-deep-cognition-403fbe445351) [## 想知道深度学习是如何工作的?下面给大家一个快速指南。

人工智能(AI)和机器学习(ML)是目前最热门的话题。

medium.freecodecamp.org](https://medium.freecodecamp.org/want-to-know-how-deep-learning-works-heres-a-quick-guide-for-everyone-1aedeca88076)

感谢你阅读这篇文章。希望你在这里发现了一些有趣的东西:)

如果您想联系我,请务必在 twitter 上关注我:

[## 法维奥·巴斯克斯(@法维奥·巴斯克斯)|推特

Favio Vázquez 的最新推文(@FavioVaz)。数据科学家。物理学家和计算工程师。我有一个…

twitter.com](https://twitter.com/faviovaz)

和 LinkedIn:

[## Favio Vázquez -首席数据科学家- OXXO | LinkedIn

查看 Favio Vázquez 在世界上最大的职业社区 LinkedIn 上的个人资料。Favio 有 17 个工作列在他们的…

linkedin.com](http://linkedin.com/in/faviovazquez/)

在一轮受欢迎的饮酒游戏之前,我应该期待什么?

原文:https://towardsdatascience.com/a-data-analysis-of-riding-the-bus-d2d60fd114e4?source=collection_archive---------10-----------------------

乘坐公交车的数据分析

Recommended equipment for Ride The Bus

大学。这是探索你的个性、发现你的价值观和结交终生朋友的时候。这些都很好,但大学也是喝酒游戏的时候!白天有足够的时间去实现更崇高的目标,但是晚上需要新的方式去喝啤酒或者啜饮杜松子酒和滋补品。有很多娱乐性的饮酒游戏,但乘坐公共汽车尤其提出了一些有趣的数据问题。

喝酒游戏通常包括给别人喝饮料作为奖励,不得不拿饮料作为“惩罚”,然后是一大堆运气让事情变得有趣。乘坐公共汽车将所有这些方面整合到一个三阶段的纸牌游戏中,其中臭名昭著的第三阶段甚至可以测试经验丰富的大学生的决心。

有些回合你只需喝一两杯就能脱身。其他时候,你会感觉每隔几秒钟就要喝一杯。那么一个人在一场比赛中到底应该喝什么呢?数据分析和数百万次模拟都有答案。

注意:这个游戏有许多不同的版本,但我会在每一节之前简要说明我正在使用的版本。

第一阶段:获得卡片

工作原理:

一个庄家在给每个玩家发牌的时候会问他们四个问题。如果玩家答对了,他们会给一杯饮料。如果玩家答错了,他们就喝一杯。

  1. “红的还是黑的?”猜猜你第一张牌的颜色。
  2. “高还是低?”你的第二张牌会比第一张高还是低?
  3. “里面还是外面?”你的第三张牌在前两张之间还是之外?
  4. “什么西装?”猜猜你第四张牌的花色。

如果一张牌在边缘,那么一个人加注饮料赌注,然后给另一张牌。例如,如果你的第一张牌是 8,你说更高,而你的第二张牌是 8,那么你简单地再次猜测高或低,以获得更高的风险。

玩家最终会有 4 张或更多的牌。

数据:

平均来说,你将不得不喝 1.8 杯饮料,但在这一轮中,你要送出 2.4 杯饮料。这个阶段是一个轻松的介绍,提倡给予多于索取。除了分发卡片,还增加了一点乐趣。

下面是一张热图,显示了在第一阶段,人们可以预期给予或接受的饮料数量。很少有人能喝超过 3 杯的酒。

第二阶段:金字塔

工作原理:

这一阶段的目标是摆脱你的卡。正面朝下的卡片金字塔有四排。最下面一排有四张牌,而每高一排少一张。

庄家将从底部开始向上翻牌。如果你有一张翻过来的卡片,你可以把那张卡片放在金字塔上,然后分发一杯饮料。如果卡片在第一排,给一杯饮料,第二排,两杯饮料,依此类推。

手里剩余牌最多的玩家必须在第三阶段“乘坐公共汽车”。

数据:

在这个阶段,饮酒的赌注上升了。平均而言,在这一轮中,人们预计会送出 3.9 杯饮料。如果每个人都在随机分发饮料,那么你也可能会喝那么多,但你总有可能被挑出来喝更多。

下面是金字塔阶段你可以分发的饮料数量的直方图。分发的肉大约是 0-7 杯,但是分发 10 杯或更多杯的可能性是非常真实的。

在这一轮分发饮料很有趣,但关键的方面是找出谁必须在下一轮乘坐公共汽车。玩家越多,乘坐公共汽车的可能性就越小。下图显示了基于游戏中有多少玩家,你不得不乘坐公共汽车的概率。

呀!因为最大牌数中的平手几率,乘坐大巴的几率明显大于 1/(玩家人数)。即使是 10 个人,你也有 1/5 的机会坐公交。特别是在小团体中,不得不乘坐公共汽车是非常可能的。

第三阶段:乘坐公交车

工作原理:

只有在第二阶段中被选中乘坐公共汽车的玩家才参与这个最后阶段。庄家将七张面朝下的牌排成一行。一个庄家会翻一张牌,问玩家,“高还是低?”然后,发牌者在有问题的牌上面展示另一张牌。

如果玩家是正确的,他们翻转下一张牌。如果玩家错了,就从头再来。玩家必须猜对七次才能下车并赢得游戏。

这个游戏最令人生畏的部分,乘坐巴士是一个高度随机的事件,当失败时会感到紧张,但一旦结束就会很兴奋。

数据:

与这一阶段的声誉相反,平均而言,你可以预计在下车前只需喝 4.9 杯饮料。当然不是一个低数字,但有时会觉得平均是 20 或 30 杯,这取决于有时下车需要多长时间。

下图显示了乘坐公共汽车时,每次饮酒量的概率。

最典型的结果是在不喝任何饮料的情况下,将七张牌全部答对!这个图表几乎完全类似于一种叫做指数分布的分布。指数分布的重要方面是“无记忆”特性。

这意味着,无论你在乘车时已经喝了多少酒,你都应该准备在下车前再喝 4.9 杯。即使你已经喝了 100 杯了(不太可能),你也应该在下车前预计还会有 4.9 次失败。下次感觉公共汽车永远不会停下来的时候,请记住这一点!

下图是与上面相同的信息,但显示的是累积概率。例如,不得不喝 12 杯或 12 杯以上的概率约为 10%。

又来了!大量饮酒的负面风险很大。只有在喝了 16 杯左右的时候,才不太可能在没有获胜的情况下坚持那么久。

结论

在一个六人游戏中,假设饮料是随机分发的,那么一个人可能总共要喝 9.5 杯饮料。尽管如此,还是有很大的风险,那就是你必须乘两倍或更多的时间,这取决于你是否必须乘公共汽车,以及需要多长时间。

我希望我没有破坏数字游戏的乐趣!保持干渴,我的朋友,继续乘坐公共汽车。

代号:https://github.com/DastonArman

关于选择同行的数据驱动指南

原文:https://towardsdatascience.com/a-data-driven-guide-on-choosing-who-to-fly-with-c2c4a67708bb?source=collection_archive---------13-----------------------

继上一篇关于按国家划分的航空公司偏好的文章之后,今天我将查看 Skytrax 上 30 家最受关注的航空公司的详细评级。

哪些航空公司处于类似的等级?

给定 7 个子类别的详细评级,包括座位舒适度、客舱工作人员、食品和饮料、机上娱乐、地面服务、wifi 连接和性价比,我们可以对航空公司进行分层聚类,结果看起来相当合理。

我们观察到以下集群:

  • 廉价航空公司(瑞安航空、捷星航空、易捷航空)
  • 排名较低的北美航空公司(联合航空、美国航空、加拿大航空)
  • 评价稍好的欧洲航空公司(维珍航空、法航)
  • 亚洲和中东地区获得良好评价的航空公司(国泰航空、新加坡航空、卡塔尔航空、阿联酋航空)

一个附带说明是,如果还有其他因素对乘客很重要,但没有被属性捕捉到,如安全,详细评级可能不会捕捉到航空公司的整体评级。

航空公司集群之间有什么不同?

为了进一步了解每家航空公司的利弊,我们检查了详细的评级。

我们可以看到这些集群的属性:

  • 法航和维珍航空在 wifi 连接方面的评级较低
  • 廉价航空公司在 wifi 和机上娱乐方面得分较低,但在性价比方面得分较高。为什么这里会有这样的期望?
  • 像达美航空和英国航空这样的航空公司得分相当不错,同样,wifi 和地面服务相对较低
  • 汤姆森和托马斯·库克这两家英国区域性航空公司在无线网络上的评级相当不错
  • 像联合航空这样的北美航空公司在各方面都被评为平均水平
  • 亚洲/中东航空公司,如阿联酋航空公司和新加坡航空公司相对得分最高(鉴于没有人真正得到 5 分)

Detailed rating in same color as the previous clusters

这意味着你可以根据你在飞机上最关心的事情来选择航班,无论是 wifi 还是座位舒适度。航空公司也可以评估他们与类似评级的竞争对手的价格竞争力。

哪个属性对总体评分最重要?

检查每个属性与总体评分之间的相关性,我们可以看到价格的价值最重要,其次是来自机组人员和地勤人员的服务,接下来是座位舒适度食物电影wifi 其实没那么重要。

我今天学到的是 r 中的雷达图。雷达图在显示太多等级相差很大的类别时会有点棘手,在这种情况下,类别的排序可能会扭曲故事。在这里,因为大多数评级在 3-4 之间,所以这是了解每个类别评级的一个不错的选择。

library(fmsb)#need to add two rows on max and min range of each category
df=rbind(rep(5,7), rep(0,7), df)#plug in the numerical columns
radarchart(df[,2:8])

这是我关于数据科学和视觉故事的# 100 日项目的第 47 天。我的 github 上的全部代码。感谢阅读。欢迎新主题的建议和反馈。

成为持续的亿万富翁的数据驱动指南

原文:https://towardsdatascience.com/a-data-driven-guide-to-becoming-a-consistent-billionaire-7fe222971dbe?source=collection_archive---------4-----------------------

你真的认为所有的亿万富翁都一样吗?

最近,我对那百分之一的亿万富翁有点着迷了。当我偶然发现一些文章告诉我们谁是真正的亿万富翁时,我很感兴趣。文章说的是这样的事情:大多数企业家没有学位,亿万富翁在开始创业之前一般都是 30 多岁。我觉得这有点笼统,我会解释的。让我们来看看比尔·盖茨和世嘉公司的首席执行官 Hajime Satomi。两人都是亿万富翁,但他们真的一样吗?在过去的十年中,比尔·盖茨每年都是亿万富翁,而哈吉已经三次从福布斯的名单中跌出。当没有人想成为一个朝觐者时,把这两个人放在同一个盒子里,发布漂亮的文章,给出漂亮的统计数据,这公平吗?我认为不会——尤其是在这十年里,像 Hajime 这样反复无常的亿万富翁占到了亿万富翁总数的 50%以上。解决亿万富翁之间的差异是这篇文章的主题。我们将强调关于持续的亿万富翁的有趣事实,并最终找出持续的亿万富翁与其他人的区别。

我所说的持续的亿万富翁是什么意思?这就是我们来这里的目的。🙂

对于像我这样的书呆子来说,我是这样做的

  • 数据来源:大部分数据都是从 3000 份《福布斯》个人资料中刮来的。从一篇研究论文中收集了两个额外的变量: 亿万富翁特征数据库 。涵盖的亿万富翁是 2007 年至 2017 年 6 月期间是或曾经是亿万富翁的人。
  • 数据收集:我使用亿万富翁的名字创建了他们的福布斯个人资料网址,并使用 RSeleniumrvest 收集了我需要的数据。我坦白说。一点也不性感。我做了大量的 Excel VLOOKUPS,手工检查和字符串操作,以获得一个可行的数据集。
  • 数据清理:我使用 stringr 从字符串创建了列。

代码可以在这里找到。

亿万富翁有多少种类型?

这是我想到的:

  • 如其名,这些人年复一年都是亿万富翁。它还包括最多一年没有上榜的亿万富翁(如 2008 年的马克·扎克伯格)。他们在 2015 年之前应该已经是亿万富翁了。
  • 鬼魂:这些是离开榜单的亿万富翁,他们在过去四年里没有回来过。他们也应该在 2015 年前首次亮相。
  • 皮条客:这一类别包括所有其他在 2015 年前首次亮相的亿万富翁。即
  • 那些不止一次离开的人,每次都卷土重来。
  • 那些虽然回到了名单上,但却离开了一年多的人。
  • 那些还没有回来,但没有花了长达 4 年的名单。
  • 新手:这些是在 2015 年至 2017 年间首次亮相的亿万富翁。他们自成一组,因为我认为把他们放在其他任何地方都是不公平的,因为没有足够的数据将他们归入任何其他类别。尽管如此,我认为看看他们在做什么会很有趣。

所以,让我们开始吧!

你知道吗?

一贯的亿万富翁都受过良好教育。

接近 55%的亿万富翁至少有一个学位。

事实上,拥有学士、博士、硕士和几乎所有其他学位的人最多。

亿万富翁创业的平均年龄比普通鬼魂大 7 岁。

这适用于白手起家创业的亿万富翁。亿万富翁平均在 30 多岁开始创业,这与文章中关于 30 多岁成功创业的观点一致。

这位比其他人至少早两年创业的幽灵亿万富翁是否说明了年轻企业家不太可能维持他们的财富?大概吧。然而,如果你看看这些新手,他们大多也是在年轻时开始的。问题是:一般的新手最终会变成幽灵吗?或者说,在过去的几年里,竞争环境发生了变化吗?我们可以在几年后回答这个问题。🙂

持续产生亿万富翁比例最高的前三个行业是电信、时尚和多元化投资组合。

看起来极其主流吧?但是时尚?真的吗?

注:这里的时尚和零售不是指零售。这意味着商业零售时尚商品,如 Zara,H & M 等。

非洲亿万富翁最有可能成为持续的亿万富翁

接近 70%的非洲亿万富翁是稳定的——比世界上任何其他地区都多。最接近的地区是北美,占 53%。

然而,在新手时代,亚洲似乎主宰着所有其他地区,这一数字主要是由中国推动的。事实上,超过 50%的中国亿万富翁是在这一时期上榜的。

另一方面,中东的亿万富翁最有可能是鬼。我知道你在想什么。油价吧?大概吧。然而,大多数中东亿万富翁拥有多样化的投资组合。

拥有博士学位的亿万富翁比辍学者还多。

这是我最喜欢的。

这适用于所有其他学位,如工商管理硕士,理学硕士等。只有法律或医学等专业学位的亿万富翁比辍学者少。然而,在新手和骗子类别中,拥有专业学位的人甚至比辍学的人还要多。

11%的亿万富翁是女性。

唯一一个男女比例更令人鼓舞的类别是新人类别,约占 16%。然而,鉴于全球男女比例为 50:50,新人类别仍然短缺 34%。好消息是情况正在好转。自 2015 年以来,女性成为亿万富翁的可能性是此前的近两倍。

64%的亿万富翁都是白手起家。

唯一百分比较低的类别是幽灵。好消息(或坏消息——取决于你希望你的财富来自哪里)是,新亿万富翁的比例比这高。这意味着在最近一段时间,更多的“新”财富正在产生。此外,白手起家似乎并不奇怪,因为每个类别都有超过 60%的亿万富翁是白手起家。

酷,现在怎么办?

我们都知道和喜爱的亿万富翁都受过良好的教育,坦率地说,一般都很无聊。

"如果你想成为持续的亿万富翁,这有多重要?"

为了回答这个问题,我们将做一些机器学习(在这里请原谅,这可能有点技术性)。使用 h2o.ai 机器学习包(我爱!),我们会训练模型来预测一个亿万富翁会属于哪一类。除了新手,我们会对所有类别的人都这样做,因为和其他人不同,区分这个群体的是他们加入名单的时间,而不是他们在名单上的表现。我们还将使用真正的独立变量来训练我们的模型。例如,用于创建类别的变量,如他们离开列表的次数,将不会被使用。如果我们使用这样的变量,就像知道答案并逆向工作一样,对吗?然后,我们将检查哪些变量是预测亿万富翁类别的最佳变量,以回答我们的问题。在上面分享的同一个脚本中也有代码。

我会首先使用 purrr 和 h2o 包在梯度推进机器、随机森林和深度学习之间找到最佳算法。

看起来 GBM 算法在测试集上的准确性击败了其他机器学习算法。

让我们来看看 GBM 认为哪些变量在预测亿万富翁的类别时最重要。

在 50%的相对重要性之上,我们看到了三个变量:国家、行业和为他们带来财富的公司的成立年份。

这告诉我们什么是持续的亿万富翁?首先,它说,虽然一致性可能受过良好的教育,这肯定不是他们有什么。国家和行业是重要的变量,这并不令人吃惊,但“创建年份”却很有趣。这可能意味着建立一个可持续发展的企业变得越来越容易或越来越难。

还是那句话,非常直白和无聊。在正确的时间进入一个对你所在的行业有利的环境,然后蓬勃发展!你创造了可持续的财富。在这一点上,我觉得我有义务说,84%的技术亿万富翁在北美和亚洲。目前没有一个来自非洲(见上面关于你所在行业有利环境的句子),但话说回来,你可以成为先锋,所以接受我的建议吧。祝你好运!

要记住的事情

数据来自福布斯。这意味着我天生被他们的方法、估计和误差所约束。例如,数据显示只有一位亿万富翁来自政界。我非常怀疑那是真的。

  • 一天结束的时候,我有超过 30 个变量,我不能在一篇文章中谈论所有的变量,所以这里有一些可视化供你玩,自己发现如何成为一个持续的亿万富翁。😉
  • 想知道谁是一贯的亿万富翁吗?点击,使用完整数据集了解详情。
  • 在我的下一篇文章中,我将讨论哪些行业、国家和成立年代是成为持续的亿万富翁的最佳时机;
  • 我有一个小小的惊喜。🙂

原载于 2017 年 10 月 7 日theartandscienceofdata.wordpress.com

超过 1.5 TB 的标记音频数据集

原文:https://towardsdatascience.com/a-data-lakes-worth-of-audio-datasets-b45b88cd4ad?source=collection_archive---------5-----------------------

我在音频研究中使用的 25 个大型音频数据集列表

在 Wonder Technologies,我们花了大量时间来构建通过音频理解世界的深度学习系统。从基于深度学习的语音提取到教计算机如何读取我们的情绪,我们需要使用大量数据来提供即使在最疯狂的声音环境中也能工作的 API。这里有一个数据集列表,我发现它对我们的研究非常有用,我个人用它来使我的音频相关模型在现实环境中表现得更好。

尝试构建自定义数据集?不确定从哪里开始?和我一起进行 30 分钟的一对一谈话,谈谈你的项目。 报名时间段

音乐数据集

免费音乐存档

FMA 是一个用于音乐分析的数据集。数据集由全长和 HQ 音频、预先计算的特征以及音轨和用户级元数据组成。它是为评估音乐信息检索(MIR) 中的几项任务而创建的开放数据集。

这个很大,差不多有 1000 GB。

百万首歌曲数据集

百万歌曲数据集是一百万首当代流行音乐曲目的音频特征和元数据的免费收集。数据集的核心是一百万首歌曲的特征分析和元数据。数据集不包含任何音频,仅包含派生要素。使用哥伦比亚大学提供的代码,可以从 7digital 等服务中获取样本音频。这个数据集的大小大约是 280 GB。

6 大小抄新手机器学习工程师需要

语音数据集

自由口语数字数据集

这个是为了解决在音频样本中识别语音数字的任务而创建的。这是一个开放的数据集,因此希望随着人们不断贡献更多的样本,它将继续增长。目前,它包含以下特征:1) 3 个扬声器 2) 1,500 个录音(每个扬声器每个数字 50 个)3)英语发音。这是一个非常小的集合-大约 10 MB 大小。

LibriSpeech

这个数据集是大约 1000 个小时的英语演讲的大规模语料库。数据来源于 LibriVox 项目的有声书籍,大小为 60 GB。

沃克斯勒博

VoxCeleb 是一个大规模的说话人识别数据集。它包含了从 You Tube 视频中提取的 1251 位名人的约 10 万句话语。数据基本上是性别平衡的(男性占 55%)。这些名人的口音、职业和年龄各不相同。开发和测试集之间没有重叠。这是一个有趣的用例,用于隔离和识别声音属于哪个超级巨星。

这套是 150 兆字节的大小,有大约 2000 小时的讲话。

口语维基百科全集

这是一个英语、德语和荷兰语维基百科的口语文章语料库。数百小时的对齐音频和注释可以映射回原始 HTML。整套大约 38 GB 大小,有音频和无音频两种格式。

Flickr 音频字幕语料库

8,000 幅自然图像的 40,000 个语音字幕,大小为 4.2 GB。这个语料库是在 2015 年收集的,用于研究无监督语音模式发现的多模态学习方案。

泰德-刘姆

TED 演讲的音频转录。1495 年,TED 演讲录音以及这些录音的全文转录,由缅因州大学信息实验室(LIUM)创建。

语音命令数据集

数据集(1.4 GB)有 65,000 个一秒钟长的 30 个短词的话语,由成千上万不同的人通过 AIY 网站由公众贡献。它是在 Creative Commons-BY 4.0 许可下发布的,随着收到更多的贡献,它将在未来的版本中继续增长。该数据集旨在让您为应用程序构建基本但有用的语音界面,包括“是”、“否”等常用词、数字和方向。用于创建数据的基础设施也是开源的,我们希望看到它被更广泛的社区用来创建他们自己的版本,特别是覆盖服务不足的语言和应用程序。

常见语音

Common Voice(大小为 12 GB)是用户在 Common Voice 网站上阅读的语音数据的语料库,并且基于来自大量公共领域来源的文本,如用户提交的博客帖子、旧书、电影和其他公共语音语料库。它的主要目的是实现自动语音识别(ASR)系统的训练和测试。

波斯语辅音元音组合(PCVC)语音数据集

波斯语辅音元音组合(PCVC)语音数据集是用于语音识别和说话人识别的现代波斯语语音语料库。该数据集包含来自不同说话者的现代波斯语元音和辅音音素组合的声音样本。每个声音样本只包含一个辅音和一个元音,所以它以某种方式被标记在音素级别。该数据集包含 23 个波斯语辅音和 6 个元音。声音样本是元音和辅音的所有可能组合(每个说话者 138 个样本),长度为 30000 个数据样本。

如果要使用这个数据集,请参考本文:

Saber MalekzadeH,Mohammad Hossein Gholizadeh,Seyed Naser Razavi“在 PCVC 语音数据集上使用 MFCC 和安进行完整的波斯语元音识别”第五届电子工程、计算机科学和信息技术国际会议,伊朗,德黑兰,2018 年。 ( PDF )

VoxForge

口音英语的干净语音数据集。对于您期望对不同口音或语调具有鲁棒性的情况非常有用。

钟声

这是一个嘈杂的语音识别挑战数据集(约 4GB 大小)。该数据集包含真实的模拟和干净的语音记录。真实是在 4 个有噪声的位置上的近 9000 个记录中的 4 个说话者的实际记录,模拟是通过结合语音话语的多个环境和干净的无噪声记录而生成的。

您可以从这里的下载数据集。

2000 HUB5 英语

百度深度语音论文中最近使用的纯英文语音数据。

具有多种类型录音数据集的帕金森语音数据集

训练数据属于 20 名帕金森病(PD)患者和 20 名健康受试者。对于这个 20 MB 的集合,从所有对象中获取多种类型的录音(26)。

零资源演讲挑战

零资源语音挑战的最终目标是构建一个系统,该系统仅使用语言学习婴儿可用的信息,从零开始学习未知语言的端到端口语对话(SD)系统。“零资源”指的是零语言专门知识(例如,拼写/语言转录),而不是除了音频之外的零信息(视觉、有限的人类反馈等)。4 岁的孩子在没有语言专家监督的情况下自发学习语言的事实表明,这个目标在理论上是可以达到的。

等值线数据集

这个 38.7 GB 的数据集有助于预测说出了哪个字母名称——这是一个简单的分类任务。

阿拉伯语语音语料库

阿拉伯语语音语料库(1.5 GB)是用于语音合成的现代标准阿拉伯语(MSA)语音语料库。该语料库包含超过 3.7 小时的 MSA 语音的语音和拼写转录,与音素级别上的记录语音一致。注释包括单个音素上的单词重音标记。这个语料库是南安普顿大学的 Nawar Halabiat 博士工作的一部分。该语料库是使用专业工作室用南黎凡特阿拉伯语(大马士革口音)录制的。使用该语料库作为输出的合成语音产生了高质量、自然的声音。

TIMIT 文集

TIMIT read 语音语料库(440 MB)旨在为声学-语音研究以及自动语音识别系统的开发和评估提供语音数据。TIMIT 包含了美国英语八种主要方言的 630 名使用者的宽带录音,每个人朗读十个语音丰富的句子。它包括时间对齐的正字法、语音和单词转写,以及每个话语的 16 位、16 kHz 语音波形文件。

多模态情感线数据集(MELD)

通过增强和扩展情感线数据集,建立了多模态情感线数据集。MELD 包含与 EmotionLines 中相同的对话实例,但它还包含音频和视频模态以及文本。MELD 有超过 1400 段对话和 13000 句来自老友记电视剧的话语。对话中的每一个话语都被贴上了标签——愤怒、厌恶、悲伤、喜悦、中立、惊讶和恐惧。下载此处

为你的算法获取更多的数据是提高准确性的一种方式。在 深度学习表现小抄 中多探索几个秘籍

声音/自然

音频设备

632 个音频事件类的扩展本体和从 YouTube 视频中提取的 2,084,320 个人类标记的 10 秒声音剪辑的集合。要下载这套,点击这个 GitHub 链接。

Mivia 音频事件数据集

监控应用的 6000 个事件,即玻璃破碎、枪声和尖叫声。事件分为由 4,200 个事件组成的训练集和由 1,800 个事件组成的测试集。

要下载该数据集,您必须在 Mivia 网站上注册。

环境音频数据集

该网页试图维护一个适合环境音频研究的数据集列表。除了免费提供的数据集之外,为了完整起见,这里还列出了专有和商业数据集。除了数据集之外,一些在线声音服务也列在了页面的末尾。这些服务可用于为特殊研究需求形成新的数据集。

数据集分为两个表:

  • 声音事件表包含适用于自动声音事件检测和自动声音标记领域研究的数据集。
  • 声学场景表包含适合于涉及基于音频的上下文识别和声学场景分类的研究的数据集。

FSD:日常声音的数据集 ( Freesound )

AudioSet 本体是 600 多个声音类别的分层集合,我们用来自 Freesound 的 297,159 个音频样本填充了它们。该过程生成了 678,511 个候选注释,这些注释表达了音频剪辑中声源的潜在存在。FSD 包括各种各样的日常声音,从人类和动物的声音,到音乐和由事物发出的声音,所有这些都在知识共享许可下。通过创建这个数据集,我们寻求促进研究,使机器能够像人类一样听到和解释声音。

Freesound 是一个基于 Freesound 内容、由人类标记的音频集合的协作创建平台。

城市声音分类

数据集(6 GB)被称为 UrbanSound,包含 8732 个标记的声音摘录(<=4s) of urban sounds from 10 classes namely: Air Conditioner, Car Horn, Children Playing, Dog bark, Drilling Engine, Idling, Gun Shot, Jackhammer, Siren and Street Music The attributes of data are as follows: ID — Unique ID of sound excerpt Class — type of sound.

城市声音数据集

这个数据集包含 1302 个带标签的录音。每个录音都标有 10 类声音事件的开始和结束时间:空调、汽车喇叭、儿童玩耍、狗叫、钻孔、发动机空转、枪击、手提钻、警笛和街头音乐。每个录音可能包含多个声音事件,但对于每个文件,只有来自单个类的事件被标记。这些类别来自城市声音分类法。

鸟类音频探测挑战

在与 IEEE 信号处理协会的合作中,引入了一项研究数据挑战,以创建一种鲁棒且可扩展的鸟类检测算法。这项挑战包括在真实的生物声学监测项目中收集的新数据集(5.4 GB),以及一个客观、标准化的评估框架。

感谢阅读:)如果你喜欢它,尽可能多的点击下面的按钮!这对我意义重大,鼓励我写更多这样的故事

咱们也连线上 推特 或者 LinkedIn

现代数据忍者的工具包

原文:https://towardsdatascience.com/a-data-ninjas-toolkit-abfe11d38fe8?source=collection_archive---------4-----------------------

做数据分析既有趣又有益。这是我在空闲时间经常做的事情。但是,如果没有合适的工具,这可能会令人沮丧,而且非常耗时。我将处理数据的过程分为 4 个步骤。

  1. 数据收集:找到并获取您感兴趣的数据集
  2. 数据清理:将数据转换成正确的格式
  3. 数据探索:发现趋势和有趣的模式
  4. 数据可视化:将你发现的惊人趋势可视化

数据采集

在过去的 5 到 10 年里,收集数据的过程已经有了明显的改善。现在可以在网上找到大量的数据集。

卡格尔

Kaggle 在 2016 年推出了一个新的数据集功能,它很快成为我最喜欢的浏览和探索数据集的地方。它允许你上传自己的数据集,也可以自由访问他人的数据集。许多人创建了他们自己的“内核”,这是讲述某个数据集的故事/分析的小脚本。这个来源的警告是,它对所有人都是免费的,一些数据集没有得到很好的记录,数据的来源也不清楚。

A visualization of a Pokemon dataset found on Kaggle. Don’t ask me to interpret it.

谷歌大查询

另一个在过去几年里真正开花结果的大玩家是 Google BigQuery。他们拥有大量的公共数据集。此外,通过 SQL 浏览数据很容易,通常只需要几分钱。

Data.gov

Data.gov是开始搜索政府相关数据的好地方。我发现这个网站有些断断续续,经常把我链接到一些不可行的政府网站。尽管美国政府越来越重视开放数据,但我确信这将是一个会随着时间而改进的工具。

政府领域开放数据的另一个参与者是 Socrata。寻找大城市政府经常托管他们的数据。一些例子包括纽约开放数据和芝加哥数据门户。

Reddit

/r/datasets 经常可以有一些非常新颖、漂亮的数据集。你也可以发布一条信息或数据集的请求,偶尔你会得到回应。

我偶尔使用的另一个技巧是浏览 /r/dataisbeautiful 。所有 OC(原创内容)帖子都需要包含一个评论,说明他们的数据集是从哪里来的。

令人惊叹的公共数据集

github 存储库[awesome-public-datasets](https://github.com/caesar0301/awesome-public-datasets)链接到许多类型的数据集,按类别聚集。

Scrapy

有时候,最好的数据不是通过下载按钮或容易访问的 API 获得的。我尝试了多种 web scrapers,一次又一次,我回到了 Scrapy 。如果你有编程技能或者不怕钻研一点 python,Scrapy 是一个非常容易上手的 web 抓取工具,它运行良好,并且有很好的文档和工具。

我最喜欢的特性是scrapy shell <url>,它会抓取一个网页并为您打开一个 REPL 来运行 python 命令,直到您确定了获取感兴趣的数据所需的命令集。

谷歌

这个显而易见,但还是值得一提。网上有大量的其他资源。谷歌一下你想找的东西,加上“数据集”这个词,是一个很好的起点。

信息自由法(FOIA)

最后但同样重要的是,如果你真的想得到一些数据,你可以提交一个 FOIA 请求。这项法律允许你向任何联邦机构索取数据,他们必须交出数据,除非它属于豁免范围。

数据清理

处理数据最乏味的部分,也是许多数据黑客可以证明的最耗时的部分。幸运的是,有一些工具可以让这个过程变得更容易。

Trifacta

如果您依赖 Excel 进行数据转换,您需要立即获取 Trifacta。Trifacta 是数据清理(坦率地说,是数据探索)的一个不可思议的工具,原因有很多。

处理任意大小的数据

Trifacta 处理数据的子集,然后生成一个脚本在原始数据集上运行。这是一个惊人的特性,因为它允许您快速操作大量数据集。如果你曾经试图用 Excel 打开超过 100k 行的文件,你就会知道应用宏是多么痛苦。

更好的数据处理

Trifacta 引入了一种不同的数据操作范式,称为 recipes。菜谱中的每一步都是对数据集的原子性改变。这很好,因为它允许您非常容易地恢复更改。Trifacta 也有非常灵活的语言来操作数据。

对您的数据进行分析

最后,Trifacta 在你操作数据时提供了关于你的数据的有见地的统计数据。它会告诉您列中有多少空值、值的分布、不同值的数量等。这种信息对于进行适当的数据清理是必不可少的。

Example analytics on a column in Trifacta

我怎么强调 Trifacta 改变游戏规则都不为过。尤其是对于那些不习惯命令行工具的人。

OpenRefine

数据清理的老国王。 OpenRefine 在 Trifacta 推出之前曾经是我的 goto 工具。OpenRefine 仍然有一些真正强大的功能,你在许多其他数据清理工具中找不到这些功能。我最喜欢的一个是它的文本聚类能力。这允许您对文本值进行聚类,然后合并它们。这在您收集城市和州名等数据时非常有用,您的数据条目如下所示:

Chicago, IL
chicago il
Chicago Illinois
...

这在现实世界的数据收集中经常发生。OpenRefine 对值进行聚类,并允许您通过单击按钮将它们合并为一个值。

命令行工具

我强烈建议您熟悉终端,因为许多强大的工具只作为命令行界面存在。这里有一些我最常用的。

csvkit

这个工具包非常适合快速处理 CSV 数据。这篇博客文章详细介绍了如何使用它。

jq

这个工具第一次使用时可能有点吓人,但是一旦你习惯了它,使用 JSON 就变得轻而易举了。我建议浏览一下教程,它会让你很快熟悉基础知识。

JSON 2 CSV

我经常发现自己将数据集从 json 转换成 csv。我发现 json2csv 非常有用。

数据探索

探索数据很可能是整个漏斗中我最喜欢的部分。是你偶然发现迷人发现的时候。这也是容易被忽略的领域之一。找到明显的趋势并不令人兴奋。获取数据集并找出细微差别需要时间。

Tableau 公共

Tableau Public 是一个免费的应用程序,可以让你快速绘制巨大的数据集。它可以让您轻松地加入数据集,甚至为您提供可视化建议。它有一个中等大小的学习曲线,有时会令人沮丧地得到你所寻找的图表,但最终很容易获得数据趋势的快速感觉。

除非我在绘制地图,否则我通常坚持使用 Tableau Public 作为我的主要工具。上面提到的其他工具也可以帮助探索过程,例如 Trifacta。

Python 库

如果你准备写一些 python,你可以做比 Tableau 更深入的分析。

  • Pandas:这个库非常适合操作数据,并且与 numpy 配合得很好。这使得在数据集中排序和查找统计分布变得很容易。
  • Matlibplot :用 python 生成一些快速绘图的强大工具。
  • NLTK :如果你正在处理任何类型的非结构化数据,我经常会启动 NLTK(自然语言工具包)工具包,在基于文本的数据中寻找见解。

数据可视化

漏斗的这一部分挤满了工具,让人应接不暇。很奇怪,因为我经常认为这部分工作最容易。由于工具种类繁多,我将列出我在数据博客中使用的工具,然后是我过去使用过或听说过的一些其他工具。

我经常使用的工具

D3.js

在所有的可视化库中,这可能是学习曲线最高的,并且需要编程技能,但无疑是最灵活的。你可以做任何你能想到的事情。如果你在做简单的可视化,比如线形图或条形图,我会提醒你远离 D3。我发现这不值得努力。

An excellent visualization done by the NYTimes using D3.js. Back in the days when Obama was president…

沙特克

与 D3 相比,这个库使用起来非常简单,并使绘制基本图表变得轻而易举。您不必担心工具提示或标签,因为这些都是为您处理的。可以用 Google 图表或者 High 图表做后盾。

对我来说,就是这样。我当然会使用表格和图像,并不时地使用其他适合工作的工具,但 D3 产生高质量的定制图表的能力通常消除了这种需要。

我有时使用或听说过的工具

  • 排行榜
  • Google Sheets:是的,他们有非常漂亮的可视化工具,而且不需要编程。
  • 对于非编码人员来说,这是一个很好的选择
  • C3.js
  • NVD3.js
  • fleet . js
  • 地图框
  • 谷歌图表
  • TileMill
  • CartoDB
  • Seaborn

有几个,但外面有几十个。去探索吧!

FYK 和赫比·汉考的数据追溯

原文:https://towardsdatascience.com/a-data-retro-on-fyk-and-herbie-hancock-93d92cc41e11?source=collection_archive---------12-----------------------

我的全职工作是一名数据工程师(我有关于的想法),但我也是一名活跃的音乐家。在过去的两年里,我作为嘻哈歌手,发行了 10 首歌曲。当我开始为我的下一个音乐项目集思广益时,我想知道:我的音乐是否有某些音质在 Spotify 上表现得更好?我是应该少说唱,多唱歌,还是根本不唱?我应该让我的音乐更有趣还是更情绪化?让我们看看通过 Spotify 的 API 和 Spotify for Artists 提供的数据能告诉我们什么。

FYK

我的曲目中有很多数据可以直接从 Spotify for Artists 数据门户下载。首先,让我们来看看我所有时间流的热门曲目。

我基本上是昙花一现。我的歌,三重大调有将近 140K 的流,而我的中值曲目有~300 的流。

虽然我很想说 Triple Major 如此成功的原因是因为它是一个直截了当的 BANGER(确实如此),但它做得好的真正原因是因为 Kpop。我被 taste makerChristina Choi选中,她把这首歌放到了她的播放列表中,该列表拥有> 24 万粉丝(旁注:我实际上不是韩国人,但谁会去计算呢??).在下图中,你可以看到由于这种放置和新粉丝的后续流而产生的大峰值。

这种消费实际上直接进入了《发现周刊》,而我有一段时间在这方面游刃有余。现在热度已经下降了一点,重复这一成功是一个挑战。播放列表的力量是真实的。

储蓄比率

因为我的信息流是多么的不均衡,我不能仅仅依靠信息流来衡量我的成功。相反,让我们看看每首曲目的保存比率(总保存数除以总唯一听众数)。这个概念更接近我作为一个艺术家想要最大化的东西:让人们对一首歌做出如此积极的反应,以至于他们保存了它。

Sunrise (Remix) ,一首有 rap 桥段的 r & b/pop 歌曲,保存率最高,也恰好是我最喜欢的一束歌。第二个是 Sposed To Do ,这是一首罂粟原声歌曲,在我最后一次演出时,我惊讶地发现人们居然知道歌词。有趣的是,这看起来还不错。

音频功能与存储比率

下一个合乎逻辑的问题是,“这首歌有什么特别的品质使它更有可能被保存下来?”

我们可以通过 python spotipy 库直接从 Spotify API 获取“音频功能”。音频特征用 0 到 1 的分数来表示一首歌曲的“可跳舞”或“活力”程度。

对于我的每一首曲目,我们来看看它们的音频特征,看看和保存率有没有关系。

每个点是一个轨迹,每个图表示给定音频特征(例如可跳舞性)和保存率之间的关系。这里唯一有点意思的关系是价,Spotify 的文档将其描述为:

从 0.0 到 1.0 的测量值,描述轨道所传达的音乐积极性。高价曲目听起来更积极(例如,快乐、愉快、欣快),而低价曲目听起来更消极(例如,悲伤、沮丧、愤怒)。

我的音乐在效价和保存率之间有一个负的关系,这意味着我应该用更低的效价制作更多的音乐,即更悲伤的歌曲。我一直认为我是一个积极的歌手/说唱歌手,但也许是时候改变一下了。我是说,你更喜欢德雷克还是威尔·史密斯?

赫比·汉考

老实说,鉴于我的曲目很少,听的人也很少,很难从我自己的数据中得出任何真正的结论:(。让我们把这个框架应用到一个拥有令人难以置信的目录的艺术家身上:美国爵士钢琴家,赫比·汉考

赫比的音乐生涯跨越了 50 多年,我认为他是所有活着的音乐家中最好的。虽然他可以说最出名的是他在爵士乐方面的创新,如《猎头》 (1973),但其他人可能会提到他在米勒·戴维斯第二大五重奏(1964-68),嘻哈经典 Rockit (1984),或他 2007 年凭借 River: The Joni Letters 获得格莱美年度专辑奖。时至今日,这位音乐变色龙已年近 80,但仍然活力十足。他的下一张专辑将主打当代嘻哈音乐,如肯德里克·拉马尔、雷猫和卡马西·华盛顿。

我强烈推荐阅读他的传记《可能性》。这个人以如此谦逊的方式讲述了惊人的故事,这在人类层面上和在音乐家层面上都激励了我。

让我们看看 Spotify 的 API 能告诉我们赫比惊人的职业生涯。

目录

赫比·汉考在 Spotify 上有多达 54 张专辑(包括录音室专辑和编辑/重新发行的专辑)。在他 50 多年的音乐生涯中,平均每年大约发行一张专辑。

从这张图表中我们可以看出,赫比在 70 年代是最多产的。特别是,他仅在 1979 年就发行了 5 张专辑。

大约在那个时候,我们也知道赫比·汉考开始更多地尝试他的电子爵士乐,其中包括一些我最喜欢的唱片,如 Head Hunters,Thrust 和 sunshine。也许我们可以使用之前介绍的音频特性来可视化这种效果。

如果我们看看赫比音乐的舞蹈性,我们可以看到它在 80 年代真正开始上升,因为他开始更倾向于迪斯科/电音。1986 年的大衰退是因为他在《午夜圆》电影原声带上的工作,但他在 1988 年用《完美机器》做了最后一张“可跳舞的”专辑,然后回归到一种更声学的声音。

势不可挡,对吧?如果你刚开始听 Herbie,也许他在 Spotify 上最受欢迎的 5 张专辑是很好的聆听灵感:

《九天之岛》( 1964 年)

猎头(1973)

处女航(1965 年)

哈密瓜岛(1994)

起飞(1962)

我很惊讶看到九天岛打败了猎头!虽然有些人可能会说这是因为 Spotify 的听众喜欢模态爵士乐而不是爵士放克(jazz-funk),但这很可能是因为 Empyrean Isles 包含了哈密瓜岛的首张录音,可以说是赫比最著名的爵士乐作品,也是最值得播放的(是的,这是一个词)。受欢迎程度是最近流式传输的函数,因此受播放列表的影响很大。

音频特性与流行度

虽然有 Herbie 所有曲目的保存率是很好的,但这个数据是不公开的,所以我们必须坚持流行度。类似于我们对 FYK 所做的,让我们看看音频特征和流行度之间是否有任何明显的相关性:

对于更适合跳舞、更有活力、更高价的赫比音乐来说,似乎存在温和的正相关关系。这并不奇怪,因为流行音乐通常更有活力。

工具性与流行度呈轻度负相关。说来有趣,我好像发现大部分人都不喜欢纯器乐。这种效果似乎也适用于赫比。

这对赫比·汉考意味着什么?我认为这对他的下一个项目是个好兆头,该项目将由嘻哈音乐超级制作人 Terrace Martin 制作,并将邀请当代爵士乐/嘻哈音乐皇室成员如 Kendrick Lamar、Thundercat 和 Snoop Dogg。一张以歌手为特色的高能专辑听起来很符合他过去在 Spotify 上的表现。赫比实际上有工程背景,并在他的书中谈了很多关于拥有分析头脑的内容,所以我不会否认他已经完成了完全相同的分析…

说真的,基于数据的艺术家发展?

我认为流媒体时代的一大好处是发现新人才变得非常容易。我们正处于音乐推荐的黄金时代,每周都会发现一个新的最喜欢的艺术家,这并不罕见。

发现天才很容易,但将这种天才培养成职业艺术家却很难。这就是我认为有很多机会使用数据来了解历史上哪些创造性决策可行,哪些不可行的地方。最棒的是,这些信息对任何人都是公开的。即使你是一名独立艺术家,你也能接触到比你想象的更多的信息。虽然拥有一些数据会有所帮助,但我不认为这需要一个科学家用批判的眼光来处理你的音乐创作过程。我已经看到艺术家经理开始扩展他们的数据技能,但我认为我们艺术家也是时候进步了。

查看 Jupyter 笔记本详细描述了这一分析,还有 FYK:

一个数据科学练习:根据就职演说,特朗普与其他总统有多相似?

原文:https://towardsdatascience.com/a-data-science-exercise-how-similar-is-trump-to-other-presidents-based-on-inaugural-speeches-8fa7f534a5fb?source=collection_archive---------4-----------------------

Darker is more similar

这是基于运行一些由谷歌团队编写的 NLP(自然语言处理) Doc2Vec 算法的结果。(浅层,两层神经网络)。轴中的名称格式为<年> _ <总统> _ <党> _ <簇>。现在,我们使用了不同的方法来对结果进行聚类,我们将回到这一点。首先,让我们更深入地挖掘相似之处。以下是最相似的演讲:

[('1993_Clinton_D_1', 0.9777867794036865),
 ('1977_Carter_D_5', 0.9765924215316772),
 ('1969_Nixon_R_5', 0.975844144821167),
 ('1989_Bush_R_5', 0.974454939365387),
 ('2001_Bush_R_1', 0.9733594655990601),
 ('1961_Kennedy_D_5', 0.973156213760376),
 ('1913_Wilson_D_3', 0.9689352512359619),
 ('1981_Reagan_R_5', 0.9668718576431274),
 ('1945_Roosevelt_D_4', 0.9627108573913574),
 ('1953_Eisenhower_R_5', 0.9612894654273987)]

如果你将这些演讲与同一个政党的演讲相比较,最常见的演讲是、尼克松、老布什和里根。Doc2Vec/Word to Vec 使用一种叫做单词嵌入的复杂方法来进行比较。以下是所有演讲与其他演讲的对比:

几个有趣的观察可以立即在一个非常高的水平。例如,较暗的下角表示最近几年的演讲都在谈论类似的东西。word2vec 的问题虽然它很好地显示了语义和句法关系的整体保留,但由于向量的性质,更简单的单词关联丢失了或难以可视化。

LDA(一种较老的技术)对于文档的分组(聚类)更加透明。我们将上面找到的文档聚集在一起,发现了一些有趣的关系。

Trump is in Cluster 8

像克林顿和老布什这样的总统使用了一些相同的语言,比如:挑战、一代、勇气、承诺和变革。而最不同的总统像早期民主党人和假发党(6 和 2 集群)谈论的事情像:联盟,国会,外国,联合,党。或许可以天真地说,总统们谈论的更多的是:A)改变或者 B)保持话语权。同样的,群集不止不跟随时代而不是总统。公平地说,总统们通常在同一时期谈论同样的事情。

将所有三个指标(政党、文档向量和聚类)放在一起,我们发现特朗普的演讲最像里根,支持他最相似的说法(参考 4 位具有特朗普般特质的美国总统)。然而,波尔克的就职演说与特朗普大相径庭。补充说明:由于威廉·亨利·哈里森去世、加菲尔德和肯尼迪遇刺、尼克松被弹劾,我们没有泰勒、亚瑟、约翰逊或福特的正式就职演说。

感谢和更多阅读:

  • 作为 Jupyter 笔记本的此分析的源代码
  • 由 Data Dot World 主办的这次演习的数据
  • 使用的工具:Python,Jupyter,Word2vec,sklearn,pandas,matplotlib
  • http://brandonrose.org/clustering、https://medium . com/@ Mishra . the depak/doc 2 vec-in-a-simple-way-fa 80 bfe 81104Mishra“探索自然语言工具包(NLTK)”by Abhinav Raihttps://medium . com/@ theflyingmanis/Exploring-Natural-Language-Toolkit-NLTK-e 3009 de 61576

相似的分析有不同的结果:

  • 关于特朗普所说的更多 NLP
  • “就职演说有什么内容?一个通过 Empath 的词法分析”作者@ unignoranthttps://hacker noon . com/whats-in-an-就职演说-词法分析-via-empath-bf9a5eb90b76
  • 《死亡与重生:解读特朗普就职演说的字里行间》作者@ ascotthineshttps://medium . com/@ ascotthines/Death-and-重生-解读特朗普就职演说的字里行间-speech-329fdd4ef632

Python 中的“好的数据科学”机器学习项目演练:第一部分

原文:https://towardsdatascience.com/a-data-science-for-good-machine-learning-project-walk-through-in-python-part-one-1977dd701dbc?source=collection_archive---------1-----------------------

(Source)

为社会利益解决一个完整的机器学习问题

在我们这个数据驱动的世界里,数据科学是一个非常强大的工具。你可以说我是理想主义者,但是我相信这个工具不应该仅仅用于让人们点击广告或者花更多的时间在社交媒体上。

在本文和续集中,我们将通过一个完整的机器学习项目来研究一个“数据科学促进发展的问题:预测哥斯达黎加的家庭贫困。我们不仅能够以最有效的方式提高我们的数据科学技能——通过对真实世界数据的实践——而且我们还获得了解决一个具有社会效益的问题的回报。

事实证明,公司用来最大化广告浏览量的技巧也可以用来帮助减轻人类的痛苦。

完整的代码在 Kaggle (可以在浏览器中运行,不需要下载)和 GitHub 上都可以作为 Jupyter 笔记本使用。这是一个活跃的 Kaggle 竞赛,也是一个开始机器学习或学习一些新技能的伟大项目。

问题和方法

哥斯达黎加家庭贫困水平预测挑战赛是目前正在 Kaggle 上进行的良好机器学习数据科学竞赛。目标是使用个人和家庭社会经济指标来预测家庭的贫困状况。美洲开发银行开发了这个问题,并提供了数据,目的是改进识别需要帮助的家庭的传统方法。

The Costa Rican Poverty Prediction contest is currently running on Kaggle.

贫困标签分为四个等级,这使得这成为一个监督多类分类问题:

  • 监督:给定训练数据的标签
  • 多类分类:标签是离散的,有两个以上的值

解决机器学习问题的一般方法是:

  1. 了解问题和数据描述
  2. 数据清理/探索性数据分析
  3. 特征工程/特征选择
  4. 车型对比
  5. 模型优化
  6. 结果解释

虽然这些步骤似乎呈现出一种僵化的结构,但机器学习过程是非线性的,随着我们对数据越来越熟悉,一些部分会重复多次,看看什么是有效的。有一个大纲来提供一个总的指导是很好的,但是如果事情不顺利或者当我们对问题了解得更多时,我们经常会回到过程的早期部分。

在本文中,我们将大致介绍前四个步骤,看看一些例子,笔记本中提供了全部细节。这个问题对于初学者来说是一个很好的解决问题——因为数据集的大小是可管理的——对于那些已经有坚实基础的人来说也是如此,因为 Kaggle 提供了一个试验新技术的理想环境。

最后两个步骤,加上一个实验部分,可以在第二部分中找到。

理解问题和数据

在理想情况下,我们都是问题主题的专家,拥有多年的经验来指导我们的机器学习。实际上,我们经常处理来自新领域的数据,并且必须快速获取数据所代表的内容以及如何收集数据的知识。

幸运的是,在 Kaggle 上,我们可以使用其他数据科学家分享的工作来相对快速地达到速度。此外,Kaggle 还提供了一个讨论平台,你可以在这里向比赛组织者提问。虽然与在实际工作中与客户互动不完全相同,但这给了我们一个机会来弄清楚数据字段代表什么,以及在我们遇到问题时应该记住的任何考虑事项。

此时可以问的一些好问题是:

  • 根据领域专家的观点,对于这个问题,是否有某些变量被认为是最重要的?
  • 数据是否存在已知问题?需要注意的某些价值/异常?
  • 数据是如何收集的?如果有异常值,它们可能是人为错误或极端但仍然有效的数据的结果吗?

例如,在与组织者进行讨论后,社区发现文本字符串“yes”实际上映射到值 1.0,并且其中一列的最大值应该是 5,这可用于纠正异常值。如果没有了解数据收集过程的人,我们很难找到这些信息!

数据理解的一部分也意味着挖掘数据定义。最有效的方法是一次浏览一列,阅读描述并确保您知道数据代表什么。我觉得这有点枯燥,所以我喜欢将这个过程与数据探索结合起来,阅读专栏描述,然后用统计数据和数字探索专栏。

比如我们可以读到meaneduc是家庭的平均教育量,然后我们可以用标签的值来绘制它的分布,看看它在贫困水平之间是否有任何明显的差异。

Average schooling in family by target (poverty level).

这表明贫困风险最小的家庭——非弱势家庭——往往比风险最大的家庭有更高的平均教育水平。稍后在特征工程中,我们可以通过从教育中构建特征来使用此信息,因为它似乎显示了目标标签之间的不同。

总共有 143 个专栏(特性),虽然对于一个实际的应用程序,您希望与专家一起浏览每个专栏,但是我并没有在笔记本中详尽地探究所有这些。相反,我阅读了数据定义,并查看了其他数据科学家的工作,以理解大多数列。

从问题和数据理解阶段建立的另一点是我们想要如何构造我们的训练数据。在这个问题中,我们给出了一个数据表,其中每行代表一个个体,列代表特征。如果我们阅读问题定义,我们被告知要对每个家庭进行预测,这意味着我们最终的训练数据框架(以及测试)应该对每个家庭有一行。这一点贯穿了我们的整个流程,因此从一开始就把握住这一点至关重要。

A snapshot of the data where each row is one individual.

确定度量标准

最后,我们要确保我们理解了问题的标签和度量。标签是我们想要预测的,度量是我们如何评估这些预测。对于这个问题,标签是一个整数,从 1 到 4,代表一个家庭的贫困程度。该指标是宏 F1 得分,这是一个介于 0 和 1 之间的度量值,值越高表示模型越好。F1 分数是二进制分类任务的常用度量,而“宏”是多类问题的平均选项之一。

一旦你知道了度量标准,弄清楚如何用你正在使用的工具来计算它。对于 Scikit-Learn 和宏 F1 分数,代码为:

from sklearn.metrics import f1_score# Code to compute metric on predictions
score = f1_score(y_true, y_prediction, average = 'macro')

知道了度量标准,我们就可以在交叉验证中评估我们的预测,并使用坚持测试集,这样我们就知道我们的选择对性能有什么影响,如果有的话。在这个竞赛中,我们得到了要使用的度量标准,但是在现实世界中,我们必须自己选择一个合适的度量标准。

数据探索和数据清理

数据探索,也称为探索性数据分析(EDA) ,是一个开放式的过程,在这个过程中,我们要弄清楚我们的数据能告诉我们什么。当我们发现可以用于特性工程或发现异常的有趣的趋势/模式时,我们开始广泛并逐渐在我们的分析中磨练。 数据清理 与探索密切相关,因为我们需要在建模之前解决我们发现的缺失值或异常。

对于数据探索的简单的第一步,我们可以可视化训练数据的标签分布(没有给我们测试标签)。

Distribution of training labels.

这马上告诉我们,我们有一个不平衡的分类问题,这可能使机器学习模型难以学习代表性不足的类别。许多算法都有尝试和处理这一问题的方法,例如在 Scikit-Learn 随机森林分类器中设置class_weight = "balanced",尽管它们并不完美。当我们遇到不平衡的分类问题时,我们还希望确保使用 分层抽样 进行交叉验证,以在每个折叠中获得相同的标签平衡。

为了熟悉数据,浏览代表不同数据统计类型的不同列数据类型是有帮助的:

  • float:这些通常是连续的数字变量
  • int:通常要么是布尔型的,要么是序数型的(有顺序的离散型)
  • objectcategory:通常是在机器学习之前必须以某种方式转换的字符串或混合数据类型

我使用统计类型来表示数据代表什么——例如只能是 1 或 0 的布尔值——使用数据类型来表示值在 Python 中的实际存储方式,例如整数或浮点数。统计类型告知我们如何处理特征工程的列。

(我为每个数据类型/统计类型配对指定了通常是,因为您可能会发现统计类型被保存为错误的数据类型。)

如果我们看一下这个问题的整数列,我们可以看到它们中的大多数表示布尔值,因为只有两个可能的值:

Integer columns in data.

浏览对象列,我们遇到了一个难题:2 列是 Id 变量(存储为字符串),但是 3 列看起来是数值。

# Train is pandas dataframe of training data
train.select_dtypes('object').head()

Object columns in original data.

这就是我们早先的数据理解发挥作用的地方。对于这三列,一些条目是“是”,一些是“否”,而其余的是浮动。我们做了背景调查,因此知道“是”意味着 1,“否”意味着 0。使用这些信息,我们可以校正这些值,然后可视化由标签着色的变量分布。

Distribution of corrected variables by the target label.

这是数据探索和清理齐头并进的一个很好的例子。我们发现数据中的错误,修正它,然后研究数据以确保我们的修正是适当的。

缺少值

此数据的一个关键数据清理操作是处理缺失值。在熊猫中,计算缺失值的总数和百分比很简单:

Missing values in data.

在某些情况下,缺失值是有原因的:v2a1列代表月租金,许多缺失值是因为家庭拥有房屋。为了弄清楚这一点,我们可以将数据划分为房屋缺少租金支付,然后绘制显示房屋所有权的tipo_变量(我不确定这些列名来自哪里)。

Home ownership status for those households with no rent payments.

根据该图,解决方案是为拥有自己房屋的家庭填写缺失的租金付款,并让其他家庭进行估算。我们还添加了一个 boolean 列,指示租金付款是否丢失。

列中其他缺失的值以同样的方式处理:使用来自其他列或关于问题的知识来填充值,或者让它们被估算。添加一个布尔列来指示丢失的值也是有用的,因为有时值丢失了的信息很重要。需要注意的另一个关键点是,对于缺失值,我们通常希望考虑使用其他列中的信息来填充缺失值,就像我们对租金付款所做的那样。

一旦我们处理了缺失值、异常和不正确的数据类型,我们就可以继续进行特性工程。我通常将数据探索视为一个正在进行的过程,而不是一个固定的块。例如,当我们进入特征工程时,我们可能想要探索我们创建的新变量。

数据科学过程是非线性的:虽然我们有一个大致的轮廓,但随着我们对问题的深入,我们经常回过头来重复前面的步骤。

特征工程

如果你关注我的工作,你会知道我确信自动化特征工程——具有领域专业知识——将取代传统的手工特征工程。对于这个问题,我采用了两种方法,在主笔记本中完成大部分手工工作,然后用自动化特征工程编写另一个笔记本。毫不奇怪,自动化的特征工程花费了十分之一的时间,并获得了更好的性能!这里我将展示手动版本,但是请记住自动化特征工程(带有 Featuretools) 是一个很好的学习工具。

在这个问题中,我们特征工程的主要目标是在家庭级别聚集所有个人级别的数据。这意味着将一所房子里的个人分组,然后计算统计数据,如最大年龄、平均教育水平或家庭拥有的手机总数。

幸运的是,一旦我们将单个数据分离出来(放入ind数据帧中),在 Pandas 中做这些聚合就是字面上的一行(使用idhogar家庭标识符用于分组):

# Aggregate individual data for each household
ind_agg = ind.groupby('idhogar').agg(['min', 'max', 'mean', 'sum'])

重命名列后,我们有了许多类似于以下的功能:

Features produced by aggregation of individual data.

这种方法的好处是可以快速创建许多特征。其中一个缺点是,这些特征中的许多可能没有用或者高度相关(称为共线),这就是为什么我们需要使用特征选择。

聚合的另一种方法是基于哪些特征可能对预测贫困有用,使用领域知识一次计算一个特征。例如,在家庭数据中,我们创建了一个名为warning的特征,它增加了许多家庭“警告信号”(house是家庭变量的数据框架):

# No toilet, no electricity, no floor, no water service, no ceiling
house['warning'] = 1 * (house['sanitario1'] + 
                         (house['elec'] == 0) + 
                         house['pisonotiene'] + 
                         house['abastaguano'] + 
                         (house['cielorazo'] == 0))

Violinplot of Target by Warning Value.

我们还可以通过将一个值除以另一个值来计算“人均”特征(tamviv是家庭成员的数量):

# Per capita features for household data
house['phones-per-capita'] = house['qmobilephone'] / house['tamviv']
house['tablets-per-capita'] = house['v18q1'] / house['tamviv']
house['rooms-per-capita'] = house['rooms'] / house['tamviv']
house['rent-per-capita'] = house['v2a1'] / house['tamviv']

当谈到手工与自动化特征工程时,我认为最佳答案是两者的混合。作为人类,我们在构建功能时受到创造力和时间的限制,创造力是我们能想到的功能是有限的,时间是我们编写代码的有限时间。我们可以手工制作一些类似上面的有见识的特性,但是自动化特性工程擅长的是在其他特性之上自动构建聚合。

最好的方法是花一些时间使用领域知识手工创建一些特性,然后将这个过程交给自动化的特性工程来生成成百上千个特性。

( Featuretools 是最先进的自动化特征工程开源 Python 库。这里有一篇文章可以让你在 10 分钟内开始。)

特征选择

一旦我们耗尽了时间或耐心来制作特性,我们就应用特性选择来删除一些特性,试图只保留那些对问题有用的特性。“有用”没有固定的定义,但是我们可以使用一些启发法(经验法则)来选择特性。

一种方法是通过确定特征之间的相关性。彼此高度相关的两个变量称为共线变量。这是机器学习中的一个问题,因为它们会降低训练速度,创建更难解释的模型,并且会通过对训练数据进行过度拟合来降低模型性能。

移除相关特征的棘手部分是确定相关阈值,以表明两个变量过于相关。我通常尽量保持保守,使用 0.95 或以上的相关系数。一旦我们决定了一个阈值,我们就使用下面的代码从每一对相关性高于该值的变量中删除一个:

我们只移除那些相互关联的特性。我们想要与目标相关的特征(尽管与标签的相关性大于 0.95 会好得令人难以置信)!

特征选择有很多种方法(我们会在接近文章结尾的实验部分看到另一种)。这些可以是单变量——对照目标一次测量一个变量——或多变量——评估多个特征的影响。我也倾向于使用基于模型的特征重要性进行特征选择,比如那些来自随机森林的特征。

在特征选择之后,我们可以对我们的最终变量集进行一些探索,包括制作一个关联热图和一个对图。

****

Correlation heatmap (left) and pairsplot colored by the value of the label (right).

我们从探索中得到的一点是教育与贫困之间的关系:随着一个家庭教育水平的提高(平均和最大),贫困的严重程度趋于降低(1 为最严重):

Max schooling of the house by target value.

另一方面,随着拥挤程度——每个房间的人数——的增加,贫困的严重程度也在增加:

Household overcrowding by value of the target.

这是来自这场比赛的两个可行的见解,甚至在我们进入机器学习之前:教育水平较高的家庭往往贫困程度较低,每个房间有更多人的家庭往往贫困程度较高。除了技术方面,我喜欢思考数据科学项目的分支和更大的图景。我们很容易被细节淹没,然后忘记了解决这个问题的整体原因。

这个项目的最终目标是找出如何预测贫困,以便最有效地帮助那些需要帮助的人。

模型比较

下图是我最喜欢的机器学习结果之一:它显示了机器学习模型在许多数据集上的性能,百分比显示了特定方法击败任何其他方法的次数。(摘自 Randal Olson 的一篇可读性很强的论文。)

Comparison of many algorithms on 165 datasets.

这表明在一些问题上即使是简单的逻辑回归也会胜过随机森林或梯度推进机。虽然渐变树增强模型一般来说效果最好,但也不能保证它会胜出。因此,当我们处理一个新问题时,最佳实践是尝试几种不同的算法,而不是总是依赖同一个算法。我以前也曾被同一个模型(随机森林)困住,但是请记住没有一个模型永远是最好的。

幸运的是,有了 Scikit-Learn ,使用相同的语法评估许多机器学习模型变得很容易。虽然我们不会对每个模型进行超参数调整,但我们可以将模型与默认超参数进行比较,以便选择最有希望进行优化的模型。

在笔记本中,我们尝试了六种模型,涵盖了从简单的高斯朴素贝叶斯到复杂的随机森林和梯度推进机器的复杂范围。尽管 Scikit-Learn 确实有一个 GBM 实现,但是它相当慢,更好的选择是使用一个专用的库,比如 XGBoost 或 LightGBM。对于这款笔记本电脑,我使用了 Light GBM ,并根据过去的良好表现选择了超参数。

为了比较模型,我们在 5 或 10 倍的训练数据上计算交叉验证性能。我们想要使用训练数据,因为测试数据只打算用一次来评估我们最终模型在新数据上的性能。下图显示了模型比较。条形的高度是模型记录的折叠的平均宏 F1 分数,黑色条形是标准偏差:

Model cross validation comparison results.

(要查看名称的解释,请参阅笔记本。RF 代表随机森林,GBM 是梯度提升机器,SEL 代表特征选择后的特征集)。虽然这不完全是水平比较——我没有使用梯度推进机器的默认超参数——但总体结果是:GBM 是最好的模型,遥遥领先。这反映了大多数其他数据科学家的发现。

请注意,我们在特性选择前后交叉验证了数据,以查看其对性能的影响。机器学习在很大程度上仍然是一个经验领域,知道一种方法是否有效的唯一方法是尝试它,然后衡量性能。为管道中的步骤测试不同的选择很重要——例如特征选择的相关性阈值——以确定它们是否有帮助。请记住,我们还希望避免将过多的权重放在交叉验证结果上,因为即使有许多折叠,我们仍然可能过度适应训练数据。最后,尽管 GBM 最适合这个数据集,但情况并不总是这样!

基于这些结果,我们可以选择梯度推进机作为我们的模型(记住这是一个我们可以回头修改的决定!).一旦我们决定了一个模型,下一步就是充分利用它,这个过程被称为模型超参数优化。

认识到不是每个人都有时间一口气写 30 分钟的文章(即使是关于数据科学的),我把这篇文章分成两部分。第二部分包括模型优化、解释和实验部分。

Decision tree visualization from part two.

结论

至此,我们可以看到机器学习的所有不同部分是如何走到一起形成解决方案的:我们首先必须理解问题,然后我们挖掘数据,根据需要清理数据,然后我们为机器学习模型制作特征,最后我们评估了几个不同的模型。

我们已经涵盖了许多技术,并有一个像样的模型(虽然 F1 分数相对较低,但它在提交给比赛的前 50 名模型中占有一席之地)。尽管如此,我们仍然有几个步骤:通过优化,我们可以改进我们的模型,然后我们必须解释我们的结果,因为直到我们已经交流了我们的工作,分析才是完整的。

下一步,看第二部分,查看笔记本(也在 GitHub 上),或者开始为自己解决问题。

和往常一样,我欢迎反馈、建设性的批评以及倾听您的数据科学项目。可以在 Twitter @koehrsen_will 上找到我。

Python 中的“好的数据科学”机器学习项目演练:第二部分

原文:https://towardsdatascience.com/a-data-science-for-good-machine-learning-project-walk-through-in-python-part-two-2773bd52daf0?source=collection_archive---------8-----------------------

(Source)

最大限度地利用我们的模型,弄清楚它意味着什么,并尝试新的技术

机器学习是一个强大的框架,从外面看起来可能很复杂,令人生畏。然而,一旦我们将一个问题分解成它的组成步骤,我们就会看到机器学习实际上只是一系列可理解的过程,每个过程本身都很简单。

在本系列的前半部分,我们看到了我们如何实现一个“为好的数据科学”机器学习问题的解决方案,在我们选择了梯度推进机器作为我们的选择模型之后,我们就停止了。

Model evaluation results from part one.

在本文中,我们将继续预测哥斯达黎加的贫困状况,执行模型优化,解释模型,并尝试一些实验技术。

完整的代码可以在 Kaggle (可以在浏览器中运行,不需要下载)和 GitHub 上的 Jupyter 笔记本中获得。这是一个活跃的 Kaggle 竞赛,也是一个开始机器学习或学习一些新技能的伟大项目。

模型优化

模型优化意味着为给定数据集搜索产生最佳性能的模型超参数(通过交叉验证测量)。因为最佳超参数随数据而变化,所以我们必须优化我们数据的模型,也称为调整模型。我喜欢把调优看作是为机器学习模型寻找最佳设置。

有 4 种主要的调优方法,从最低效率(手动)到最高效率(自动)排列。

  1. 手动调优:凭直觉/经验或通过猜测选择超参数,用这些值训练模型,找到验证分数,重复直到你失去耐心或对结果满意。
  2. 网格搜索:设置一个超参数网格,对于每一个数值组合,训练一个模型,找到验证分数。超参数的最佳集合是得分最高的那些。
  3. 随机搜索:设置超参数网格,选择随机数值组合,训练模型,找到验证分数。搜索迭代受到时间/资源的限制
  4. 自动调整:使用方法(梯度下降、贝叶斯优化、进化算法)引导搜索最佳超参数。这些是使用过去信息的知情方法

自然,我们将跳过前三种方法,直接进入最有效的方法:自动超参数调优。对于这个实现,我们可以使用 Hyperopt 库,它使用带有树 Parzen 估计器的贝叶斯优化版本进行优化。你不需要理解这些术语来使用模型,尽管我在这里写了一个概念性的解释。(我还在这里写了一篇关于使用 Hyperopt 进行模型调优的文章。)

细节有点冗长(见笔记本),但是我们需要 4 个部分来实现 Hyperopt 中的贝叶斯优化

  1. 目标函数:我们想要最大化(或最小化)什么
  2. 域空间:要搜索的区域
  3. 用于选择下一个超参数的算法:使用过去的结果来建议要评估的下一个值
  4. 结果历史:保存过去的结果

贝叶斯优化 (BO)的基本思想是,算法从过去的结果中推理——之前的超参数的得分如何——然后选择它认为最好的下一个值组合。网格或随机搜索是不使用过去结果的方法,其思想是通过推理,BO 可以在更少的搜索迭代中找到更好的值。

完整的实现见笔记本,但下面是 100 次搜索迭代后的优化分数。

Model optimization scores versus iteration.

与分数随时间随机变化的随机搜索不同,在贝叶斯优化中,随着算法学习最佳超参数的概率模型,分数往往会随着时间的推移而改善。贝叶斯优化的想法是,我们可以通过将搜索集中在有希望的设置上来更快地优化我们的模型(或任何函数)。一旦优化运行完成,我们可以使用最佳超参数来交叉验证模型。

优化模型并不总能提高我们的测试分数,因为我们是在为训练数据进行优化。然而,与默认的超参数相比,有时它可以带来很大的好处。在这种情况下,最终的交叉验证结果以数据框架的形式显示如下:

Cross validation results. Models without 10Fold in name were validated with 5 folds. SEL is selected features.

优化的模型(用 OPT 表示,并在选择后使用 10 个交叉验证折叠的特征)正好位于梯度增强机器的非优化变体的中间(它使用我发现对以前的问题工作良好的超参数)。)这表明我们还没有找到最佳的超参数,或者可能有多组表现大致相同的超参数。

我们可以继续优化,尝试找到更好的超参数,但通常超参数调整的回报远小于特征工程的回报。在这一点上,我们有一个相对高性能的模型,我们可以使用这个模型对测试数据进行预测。然后,由于这是一个 Kaggle 比赛,我们可以将预测提交给排行榜。这样做让我们进入了前 50 名(目前),这是对我们所有努力的一个很好的证明!

至此,我们已经实现了这个机器学习问题的完整解决方案。我们的模型可以对哥斯达黎加家庭的贫困做出相当准确的预测(F1 得分相对较低,但这是一个困难的问题)。现在,我们可以继续解释我们的预测,看看我们的模型是否能告诉我们关于这个问题的任何东西。即使我们有解决方案,我们也不想忽视为什么我们的解决方案很重要

关于 Kaggle 竞赛的注记

机器学习竞赛的本质可能会鼓励不良做法,例如以牺牲所有其他考虑因素为代价来优化排行榜分数的错误。一般来说,这导致使用更复杂的模型来弥补微小的性能增益。

在现实世界中,超过某个阈值——这取决于应用程序——准确性变得次要于可解释性,如果更简单的话,您最好使用性能稍差的模型。

投入使用的简单模型比永远无法部署的复杂模型要好。此外,那些在排行榜顶端的人可能过度适应测试数据,并且没有一个健壮的模型。

最大限度地利用 Kaggle 的一个好策略是努力解决一个问题,直到你有一个合理的好解决方案——比方说 90%的排行榜得分——然后不要为达到最高分而感到压力。竞争是有趣的,但学习是承担这些项目最有价值的方面。

解释模型结果

在编写所有机器学习代码的过程中,很容易忽略一些重要的问题:我们制作这个模型是为了什么?我们的预测会有什么影响?幸运的是,我们这次的答案不是“增加广告收入”,而是有效地预测哥斯达黎加哪些家庭最容易陷入贫困,以便他们能够获得所需的帮助。

为了尝试了解我们的模型的输出,我们可以根据测试数据以家庭为单位来检查贫困水平的预测。对于测试数据,我们不知道真实的答案,但我们可以将每个预测类的相对频率与训练标签中的相对频率进行比较。下图左侧显示了贫困的训练分布,右侧显示了测试数据的预测分布:

Training label distribution (left) and predicted test distribution (right). Both histograms are normalized.

有趣的是,尽管“不脆弱”的标签在训练数据中最常见,但在预测的相对基础上,它的出现频率较低。我们的模型预测其他 3 个阶层的比例更高,这意味着它认为在测试数据中有更严重的贫困。如果我们把这些分数转换成数字,我们有 3929 个家庭属于“非脆弱”类别,771 个家庭属于“极端”类别。

另一种看待预测的方式是通过模型的可信度。对于测试数据上的每一个预测,我们不仅可以看到标签,还可以看到模型赋予它的概率。让我们看看箱线图中标签值的置信度。

Boxplot of probability assigned to each label on testing data.

这些结果相当直观——我们的模型对最极端的预测最有信心——对温和的预测信心较低。理论上,最极端的标签之间应该有更多的分离,而中间的目标应该更难区分。

从这个图表中得出的另一点是,总的来说,我们的模型对预测并不十分确定。一个没有数据的猜测会将 0.25 的概率放在每一类上,我们可以看到,即使对于最不极端的贫困,我们的模型也很少有超过 40%的置信度。这告诉我们这是一个棘手的问题——在可用的数据中没有太多的分类。

理想情况下,这些预测,或者那些来自竞赛中获胜模型的预测,将被用来确定哪些家庭最有可能需要帮助。然而,仅仅是预测本身并不能告诉我们什么会导致贫困,或者我们的模型是如何“思考”的。虽然我们还不能完全解决这个问题,但我们可以尝试窥视机器学习的黑箱。

在基于树的模型中——如梯度推进机——特征重要度表示特征上节点分裂的和基尼系数杂质减少总量。我从来没有发现绝对值很有帮助,而是将这些数字归一化,并在相对的基础上看待它们。例如,下面是优化的 GBM 模型的 10 个最重要的特性。

Most important features from optimized gradient boosting machine.

在这里,我们可以看到家庭成员的教育和年龄构成了最重要的特征。进一步看重要性,我们也看到了家庭的大小。这与贫困研究人员的发现相呼应:家庭规模与更极端的贫困相关,而教育水平与贫困成反比。在这两种情况下,我们不一定知道哪一个导致了哪一个,但是我们可以使用这些信息来突出哪些因素应该被进一步研究。希望这一数据能够被用来进一步减少贫困(在过去的 25 年中贫困一直在稳步减少)。

It’s true: the world is better now than ever and still improving (source).

除了潜在地帮助研究人员之外,我们可以通过尝试在这些基础上构建更多的特性来使用特性重要性进行进一步的特性工程。使用上述结果的一个例子是用meaneduc除以dependency来创建一个新特征。虽然这可能不太直观,但很难提前知道什么对模型有效。

使用测试数据检查我们的模型的另一种方法是将训练数据分成较小的训练集和验证集。因为我们有所有定型数据的标签,所以我们可以将我们对维持验证数据的预测与真实值进行比较。例如,使用 1000 个观察值进行验证,我们得到下面的混淆矩阵:

Confusion matrix on validation data.

对角线上的值是模型正确预测的值,因为预测标签与真实标签相同。任何偏离对角线的模型预测错误。我们可以看到,我们的模型在识别非弱势家庭方面是最好的,但在识别其他标签方面不是很好。

例如,我们的模型错误地将 18 户家庭归类为非弱势群体,而这些家庭实际上处于极端贫困之中。像这些的预测具有现实世界的后果,因为这些家庭可能会因为这种模式而得不到帮助。(更多关于错误算法的后果,见 数学毁灭的武器 )。)

总的来说,这种平庸的表现——模型精度约为 60%,比随机猜测好得多,但并不例外——表明这个问题可能很困难。可能是没有足够的信息来在可用数据中分离类别。

主办机构美洲开发银行的一个建议是,我们需要更多的数据来更好地解决这个问题。这可能表现为更多的特征——因此调查中有更多的问题——或者更多的观察——更多的家庭被调查。这两者都需要付出巨大的努力,但投资于数据科学项目的最佳时间回报通常是通过收集更多的高质量标记数据。

我们可以使用其他方法来理解模型,例如本地可解释的模型不可知解释器(LIME) ,它使用一个更简单的线性模型来近似预测周围的模型。我们还可以查看森林中的单个决策树,这些决策树通常很容易解析,因为它们本质上模拟了人类的决策过程。

Individual Decision Tree in Random Forest.

总体而言,机器学习仍然存在可解释性差距,这阻碍了它的适用性:人们不仅想要准确的预测,还想要了解这些预测是如何产生的。

探索技术

我们已经用标准工具箱解决了机器学习问题,那么为什么还要进一步探索技术呢?嗯,如果你像我一样,那么你喜欢仅仅为了学习而学习新的东西。此外,今天的探索技术将成为明天的标准工具。

对于这个项目,我决定尝试两项新技术:

  • 递归特征消除进行特征选择
  • 均匀流形近似和投影用于降维和可视化

递归特征消除

递归特征消除是一种用于特征选择的方法,它使用模型的特征重要性(该应用程序的随机森林)来选择特征。这个过程是一个重复的方法:在每次迭代中,最不重要的特性被删除。通过对训练数据进行交叉验证来确定要保留的最佳特征数量。

递归特征消除与 Scikit-Learn 的 RFECV 方法一起使用很简单。这种方法建立在一个评估器(一个模型)上,然后像任何其他 Scikit-Learn 方法一样fitscorer部分是必需的,以便使用宏 F1 得分制作自定义得分指标。

Recursive Feature Elimination code.

虽然我以前使用过特征重要性进行选择,但我从未实现过递归的特征消除方法,并且像往常一样,惊喜地发现在 Python 中做到这一点是多么容易。RFECV 方法根据交叉验证分数从大约 190 个特征中选择了 58 个:

Recursive Feature Elimination Scores.

然后对所选的特征集进行试验,以将交叉验证性能与原始特征集进行比较。(最终结果将在下一部分之后呈现)。鉴于这种方法的易用性,我认为它是您建模技能中的一个好工具。像任何其他 Scikit-Learn 操作一样,它可以适合一个 [Pipeline](http://scikit-learn.org/stable/modules/generated/sklearn.pipeline.Pipeline.html),允许您快速执行一系列完整的预处理和建模操作。

可视化降维

机器学习中有多种无监督方法用于降维。这些分为两大类:

  • 矩阵分解算法: PCA 和 ICA
  • 将数据映射到低维流形上的嵌入技术: IsoMap , t-SNE

通常,PCA(主成分分析)和 ICA(独立成分分析)用于可视化和作为机器学习的预处理步骤,而像t-SNE(t-分布式随机邻居嵌入)这样的多种方法仅用于可视化,因为它们高度依赖于超参数,并且不保留数据内的距离。(在 Scikit-Learn 中,t-SNE 实现没有transform方法,这意味着我们不能用它来建模)。

降维场景中的一个新条目是 UMAP:一致流形近似和投影。它旨在将数据映射到一个低维流形,因此这是一种嵌入技术,同时保留数据的全局结构。虽然背后的数学是严谨的,但它可以像 Scikit-Learn 方法一样使用[fit](https://github.com/lmcinnes/umap)``[transform](https://github.com/lmcinnes/umap)调用。

我想尝试这些方法,既可以减少可视化的维度,又可以将减少的组件作为附加特性添加进来。虽然这个用例可能不是典型的,但是尝试一下没有坏处!下面显示了使用 UMAP 创建训练和测试数据嵌入的代码。

Uniform Manifold Approximation and Embedding Code.

其他三种方法的应用完全相同(除了 TSNE 不能用于transform测试数据)。在完成变换之后,我们可以在 3 维中可视化减少的训练特征,用目标的值给点着色:

Dimension Reduction Visualizations

没有一种方法能根据标签清晰地分离数据,这些标签遵循其他数据科学家的发现。正如我们之前发现的,考虑到我们可以访问的数据,这个问题可能很难解决。虽然这些图表不能用来说明我们是否能解决一个问题,但是如果有一个清晰的分离,那么它表明在数据中有某种的东西可以让一个模型很容易地辨别每一类。

最后一步,我们可以在应用特征选择后将缩减的特征添加到特征集中,以查看它们是否对建模有用。(通常应用降维,然后仅在降维后的维度上训练模型)。每个型号的性能如下所示:

FInal model comparison results.

使用降维特征的模型具有后缀 DR,而 GBM 之后的折叠数是指交叉验证折叠数。总的来说,我们可以看到选择的特征集(SEL)做得稍微好一点,添加降维特征损害了模型性能!鉴于较大的标准偏差,很难从这些结果中得出太多结论,但我们可以说梯度增强机器明显优于所有其他模型,并且特征选择过程提高了交叉验证性能。

这个笔记本的实验部分可能是我最享受的部分。始终学习保持在数据科学领域的领先地位不仅重要,而且对于学习新东西来说也是一种享受。

不断改进和获取新知识的动力是数据科学家的一项关键技能。

后续步骤

尽管对机器学习工具进行了详尽的报道,我们还没有找到解决这个问题的方法!

我们可以采取的一些额外步骤是:

  1. 自动化特征工程:详见本笔记本
  2. 过采样少数类:一种通过生成合成数据点来解决不平衡类的方法
  3. 进一步的特征选择:特别是在自动化特征工程之后,我们有了可能对模型性能产生负面影响的特征
  4. 集合或堆叠模型:有时将较弱的——性能较低的——模型与较强的模型结合起来可以提高性能

关于 Kaggle 竞赛的伟大之处在于,你可以在其他数据科学家的笔记本中读到许多这些尖端技术。此外,这些比赛在非关键任务环境中为我们提供了真实的数据集,这是一个完美的实验环境。

最好的竞赛可以通过鼓励友好的竞争、开放的工作分享和奖励创新方法来带来新的进步。

作为更好的机器学习方法竞争能力的一个例子, ImageNet 大规模视觉识别挑战导致了卷积神经网络的重大改进。

Imagenet Competitions have led to state-of-the-art convolutional neural networks.

结论

数据科学和机器学习不是不可理解的方法:相反,它们是组合成强大解决方案的一系列简单步骤。通过一步一步地解决问题,我们可以学习如何构建整个框架。我们如何使用这个框架最终取决于我们自己。我们不必奉献一生去帮助他人,但是接受一个更有意义的挑战是值得的。

在本文中,我们看到了如何将完整的机器学习解决方案应用于数据科学中的好问题,即构建一个机器学习模型来预测哥斯达黎加的贫困水平。

我们的方法遵循一系列流程(1-4 在第一部分中):

  1. 理解问题和数据
  2. 在探索性数据分析的同时执行数据清理
  3. 自动和手动设计相关特征
  4. 比较机器学习模型
  5. 优化最佳性能模型
  6. 解释模型结果并探索它是如何做出预测的

最后,如果在所有这些之后,您仍然没有完全理解数据科学,您可以继续探索技术并学习新的东西!

和任何过程一样,你只会在练习中进步。竞争是有价值的,因为它为我们提供了运用和发展技能的机会。此外,他们鼓励讨论、创新和协作,从而培养出更有能力的个人数据科学家和更好的社区。通过这个数据科学项目,我们不仅提高了我们的技能,还努力改善我们人类同胞的成果。

和往常一样,我欢迎反馈、建设性的批评以及倾听您的数据科学项目。我可以通过推特 @koehrsen_will 联系到。

数据科学工作流

原文:https://towardsdatascience.com/a-data-science-workflow-26c3f05a010e?source=collection_archive---------0-----------------------

Photo by Kevin Ku from Pexels https://www.pexels.com/photo/coding-computer-data-depth-of-field-577585/

Jupyter 笔记本可以在这里找到。

没有解决数据科学问题的模板。路线图会随着每个新数据集和新问题而变化。但是我们确实在许多不同的项目中看到类似的步骤。我想创建一个干净的工作流程,作为有抱负的数据科学家的榜样。我还想给与数据科学家一起工作的人一个易于理解的数据科学指南。

这是一个高层次的概述,概述中的每一步(以及几乎每一句话)都可以单独解决。许多书籍,如哈斯蒂和蒂布希拉尼的《T2 统计学习导论》和许多课程,如吴恩达在斯坦福大学的机器学习课程,更详细地探讨了这些主题。数据科学社区有大量的文献和资源。一定要深入任何你感兴趣的话题。

概述:

  1. 目标
  2. 导入数据
  3. 数据探索和数据清理
  4. 基线建模
  5. 二次建模
  6. 交流结果
  7. 结论
  8. 资源

最后,我想说这个过程不是完全线性的。随着你对数据了解的越来越多,你会跳来跳去,并发现新的问题需要解决。

我们开始吧!

1)目标

你想解决的问题是什么?从等式中删除建模、评估指标和数据科学。你的公司面临的问题是什么?你想进一步了解什么?清楚地陈述你的问题是解决问题的第一步,没有一个清楚的问题,你会发现自己陷入了数据科学的兔子洞。

对于此工作流,我们将分析 IMDB.com 排名最高的电影。我想建立一个模型来预测 IMDB 电影评级的基础上,如预算,运行时间和网站上的投票功能。

2)导入数据

数据可以来自各种来源。您可以从本地计算机导入 CSV 文件,查询 SQL 服务器,或者使用 web scraper 从 Internet 上提取数据。我喜欢用 Python 库,**熊猫* *,导入数据。Pandas 是一个非常棒的开源数据分析库。我们还将在这个工作流程的数据清理步骤中使用 Pandas。

对于本例,我们将从本地机器导入数据。我将使用 Kaggle.com 用户 Sai Pranav 的数据集。该数据集的标题是“这十年排名靠前的英语电影”,它是在一个 CSV 文件中。

[## 这十年排名最高的英语电影。

理解高收视率电影的成功。

www.kaggle.com](https://www.kaggle.com/saipranava/top-ranked-enlglish-movies-of-this-decade/data)

import pandas as pd 
df = pd.read_csv(‘/Users/aakashtandel/Downloads/IMDB.csv’, index_col=0, encoding=’latin-1')

我想马上说,这个数据集非常小。观察次数相对较少。但是因为这只是一个示例问题,所以我可以继续。在工业界,你肯定会想要一个更大的数据集。

3)数据探索

现在我们已经将数据导入到 Pandas 中,我们可以检查数据帧的前几行。

df.head()

我喜欢一开始就做三个区分。这是监督学习还是非监督学习?这是分类问题还是回归问题?这是预测问题还是推理问题?

监督或无监督学习:有了监督学习,我们已经明确标注了因变量和自变量。因变量(我们的目标)是已知的。如果我们在看线性回归,我们的 y 变量是显而易见的。如果我们确实有一个明确标记的 y 变量,我们正在执行监督学习,因为计算机正在从我们明确标记的数据集学习。它正在学习我们的 x 变量和我们的 y 变量之间的关系。监督学习可以分解为回归和分类问题。无监督学习,我们没有一个明确的因变量。我们有一个 x 变量的特征矩阵,没有 y 变量。无监督学习问题可能涉及聚类和创建关联。在这篇概述中,我不会涉及集群,但是这是一个很好的学习技巧。此外,从数据探索的角度来看,无监督学习可能是有益的。

分类或回归:现在我们知道我们有一个监督学习问题,我们可以决定它是分类问题还是回归问题。我查看 y 变量,并确定该变量是连续变量还是离散变量。分类 y 变量属于分类设置,而连续数量变量属于回归设置。分类问题的一个例子是确定信用卡交易是否是欺诈性的。这是一个二元分类问题,因为每笔交易要么是欺诈性的,要么不是欺诈性的。回归问题的经典例子是根据平方英尺、卧室数量和地块大小等特征来确定房子的价格。

预测或推断:在预测设置中,我们希望我们的模型估计一个 y 值,给定各种特征。从上面的回归示例中,我们希望为我们的模型提供一栋 1500 平方英尺、两间卧室和一块 0.50 英亩土地的房子。然后我们的模型会预测房子价值 20 万美元。在推理设置中,我们想知道一个特征( x 变量)如何影响输出( y 变量)。我们可以看到当你给房子增加一个额外的卧室时,房子的价格是如何增加的。

在解决您的数据科学问题时,这三组问题可以提供很多指导。

在我们的示例中,我们将使用回归(监督学习)从元批评评级、预算、运行时间和投票中预测 IMDB 评级。

回到编码部分!让我们确定哪个变量是我们的目标,哪些特征是我们认为重要的。

我们的目标是标题为 Rating 的列,我们的功能是标题如下的列:MetaCritic、Budget、Runtime、VotesUS、VotesnUS 和 TotalVotes。我将删除本次分析不需要的所有列。

df = df[['Title', 'Rating', 'TotalVotes', 'MetaCritic', 'Budget', 'Runtime', 'VotesUS', 'VotesnUS']]

Pandas 和 Matplotlib(一个流行的 Python 绘图库)将帮助我们进行大部分的探索。探索性数据分析(EDA) 让数据科学家有机会真正了解他或她正在处理的数据。许多数据科学家发现自己后来又回到了 EDA 以及他或她在 EDA 中发现的发现。

在整个 EDA 过程中,我清理数据。来自真实世界的数据非常杂乱。但是,当我在 EDA 过程中工作并学习数据时,我会记下需要修改的地方,以便进行分析。数据清洗对我来说和 EDA 齐头并进。我在这两个阶段之间工作了相当长的时间,我经常发现自己又回到了这两个阶段。

我首先检查的是数据类型。以正确的格式获取所有值非常重要。这可能涉及到从字符串中剥离字符、将整数转换成浮点数或许多其他事情。

df.dtypesdf.TotalVotes = df.TotalVotes.str.replace(',', '')
df.TotalVotes = df.TotalVotes.astype(int)
# Total Votes column is ready.df = df[(df.Budget.str.contains("Opening") == False) & (df.Budget.str.contains("Pathé") == False)]
df.Budget = df.Budget.str.replace('[^\x00-\x7F]','')
df.Budget = df.Budget.str.replace(',', '')
df.Budget = df.Budget.str.replace('$', '')
df.Budget = df.Budget.astype(int)
# Budget column is ready.df.Runtime = df.Runtime.str.extract('(\d+)', expand=False)
# Runtime column is now ready.

缺失值和空值很常见。有时你有很大的矩阵,但里面的信息很少。这些被称为稀疏矩阵。处理缺失值和空值本身就是一个完整的主题。这个话题被称为缺失数据插补,我不能在这里深入探讨。一定要查找更多关于这个主题的信息,尤其是当你遇到稀疏矩阵的时候。出于我们的目的,我将简单地删除具有空值的电影。这并不总是最好的主意,但是在这个分析中我选择了这样做。

df = df.dropna()df.Runtime = df.Runtime.astype(int)
df.VotesnUS = df.VotesnUS.astype(float)
df.VotesUS = df.VotesUS.astype(float)

有许多不同的方法可以对你的数据进行 EDA。检查缺失值、检查数据类型和格式化数据只是冰山一角。寻找唯一值的数量。使用 Pandas describe 方法获得列的汇总统计信息。在数据分析过程的这个阶段,Pandas 是一个非常有用的工具,熟悉 Pandas 的数据清理对于任何数据科学家来说都是一个必不可少的工具。

EDA 的最后一部分是绘图。绘图非常重要,因为它允许你直观地检查你的数据。直方图、散点图和箱线图都可以用来提供对数据问题的另一层洞察。对于这个例子,我们将使用熊猫来创建一个散布矩阵。

import matplotlib.pyplot as plt
pd.plotting.scatter_matrix(df, figsize=(20,20))
plt.show()

在数据探索和清理阶段,我还执行特征工程。特征工程是从旧特征中构造新特征。特征工程的一些基本类型是从两个特征中创建交互变量或为时间序列分析创建滞后变量。特征工程是我将在这个工作流程中讨论的另一个主题,但它不应该被遗忘。

4)基线建模

作为一名数据科学家,你会建立很多模型。您将使用各种算法来执行各种各样的任务。你需要用直觉和经验来决定什么时候某些模型是合适的。作为一名职业经济学家,我更喜欢用线性回归来解决我的回归问题,用逻辑回归来解决我的分类问题。(我也倾向于使用 kNN 用于基线分类模型,使用 K-Means 作为我在无监督学习中的第一个聚类算法。)这些模型会给你一个可以改进的基线。

在 Kaggle 竞赛中,许多获胜者使用先进的神经网络XGBoost随机森林来解决数据科学问题。所有这些都将随后出现,应该会比线性回归和逻辑回归给我们带来更准确的预测。

Scikit-Learn 是一个 Python 的机器学习包,可以用于各种任务。我们可以使用 Scikit-Learn 进行建模(分类、回归和聚类)。它还可以用于降维(主成分分析)、模型选择(网格搜索、评估度量)和数据预处理。当您在 Scikit-Learn 中工作时,不同算法的建模基础是相似的。

在模型预处理期间,我们将从因变量中分离出我们的特征,全面扩展数据,并使用训练-测试-分割来防止我们的模型过度拟合。过度拟合是指当我们的模型过于紧密地跟踪我们的训练数据,并且当它被输入新数据时,它的表现不好。这意味着该模型不能很好地推广到新问题。该模型会拾取训练数据中的所有噪声,并记忆下来。创建训练-测试-分割有助于对抗过度拟合。此外,我们可以使用交叉验证来防止过度拟合。一定要自己查找更多关于交叉验证的信息。

y = df.Rating
X = df[['TotalVotes', 'MetaCritic', 'Budget', 'Runtime', 'VotesUS', 'VotesnUS']]
# We need to separate our feature matrix from our y variable for Sklearn.from sklearn.preprocessing import MinMaxScaler
cor_X = MinMaxScaler().fit_transform(X)from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(cor_X, y, test_size=0.2)
print (X_train.shape, y_train.shape)
print (X_test.shape, y_test.shape)

现在我们准备使用我们的模型。我们将根据训练数据拟合我们的模型。然后,我们将通过让预测我们的 X_test 数据的 y 值来测试我们的模型。然后,我们可以通过查看预测的 y 值与实际的 y 值相差多远来评估我们的模型表现得有多好。

from sklearn import linear_model
lm = linear_model.LinearRegression()
model = lm.fit(X_train, y_train)
predictions = lm.predict(X_test)plt.scatter(y_test, predictions)
plt.xlabel('True y')
plt.ylabel('Predicted y')
plt.show()
# Graph print ('Score:', model.score(X_test, y_test))  # R-squared is the default metric used by Sklearn.

我们的模型表现得相当好。它能够达到 0.96 的 R 平方。这个评估指标 R 平方是一个拟合优度指标。它是我们的模型解释的我们的 y 变量的变化百分比。对于这个回归问题,我们也可以用均方根误差和调整的 R 平方来评估我们的模型。

模型评估指标很多。对于分类问题,常用的评价指标是准确率ROC-AUC 得分。评估您的模型是非常重要的,了解更多关于评估指标是明智的。

总的来说,我会谨慎对待这些结果。我们选择的特征很可能共线。基本上,共线性是指当你有非常相似的特征或者给我们关于因变量的相同信息时。共线性(完美共线性)的典型示例是一个以摄氏度为单位给出温度,另一个以华氏度为单位给出温度的要素。这些变量中有一个是多余的。VotesUS 和 VotesnUS(非美国投票)的特征可能非常相关。这可能是我们有如此高的 R 平方值的原因。幸运的是,我们将在第 5 部分使用非参数算法。

有几种方法可以对抗共线性,其中最基本的方法是删除一个投票变量。还有其他方法,比如代理变量,我们可以用来解决这个共线性问题。但是我们不会在这里讨论这些(我似乎经常这么说)。

lm.coef_

在讨论其他模型之前,我想先讨论一下线性模型的β系数。我们看到,美国以外的投票对 IMDB 评级产生了最大的积极影响。这种形式的推断可能不是一个好主意,因为我们不知道这些系数是否有统计学意义。如果你试图解决一个回归推理问题,我会推荐使用 Python 库 Statsmodels 。Statsmodels 的输出是一个 ANOVA 表加上系数及其相关的 p 值。

5)二次建模

你可以建立数百个模型,我有朋友花了大量的时间进行模型建立和模型调整。我将使用 Kaggle 最喜欢的一种方法,随机森林,而不是在这个场景中使用的每一个回归模型。随机森林模型是一个集合模型,它使用许多决策树来分类或回归。训练算法使用 bagging,这是引导和聚集的组合。随机森林算法还具有非参数化的优势。因为这不是一个模型教程(制作起来可能会很有趣),所以我不打算深入这个算法的细节。让我们看看如何在 Scikit-Learn 中使用它。

from sklearn.ensemble import RandomForestRegressor
rf = RandomForestRegressor()
model = rf.fit(X_train, y_train)
predictions = rf.predict(X_test)print ('Score:', model.score(X_test, y_test))  # R-square is still the default for Sklearn.model.feature_importances_

哇哦。我们的随机森林模型比我们的线性回归模型表现更差。这是一个令人惊讶的结果。这向我们展示了像线性回归这样简单易懂的模型的力量。如果我们看看特征的重要性,我们可以看到这个随机森林模型与我们的线性回归模型一致,即美国以外的投票在预测 IMDB 评级方面非常重要。我们的数据集非常小,所以这个奇怪的结果可能是小数据集的产物。

或者,我们已经提到,我们的线性回归可能遭受高度共线性。在这种情况下,由于共线性问题,我会相信随机森林模型的结果,而不是线性回归的结果。

现在有一个完整的参数调整的兔子洞我们可以下去了。每个算法都有一组你可以优化的参数。对于我们的随机森林模型,我经常试验最大深度和学习率。但是正如您所知,这些参数是特定于您的建模算法的,所以我不会在这里深入讨论。我将提到网格搜索。网格搜索允许您改变模型中的参数(从而创建多个模型),训练这些模型,并使用交叉验证来评估每个模型。Scikit-Learn 对此有一个 GridSearchCV。当您决定一次调优多个参数时,使用网格搜索可能会有好处。

现在怎么办?

Photo by energepic.com from Pexels https://www.pexels.com/photo/architect-composition-data-demonstration-313691/

6)交流结果

在我看来,你的数据科学项目可以有两个方向:数据科学产品和数据科学报告。

首先,你可以创建一个数据科学产品。让您的模型投入生产,这本身又是一个话题。首先,您需要将代码从 Jupyter 笔记本转移到脚本中。在大多数公司中,数据科学家将与软件工程团队一起编写代码。首先需要对模型进行酸洗,这可以通过 Scikit-Learn 的 Joblib 来完成。然后我们可以使用 Flask 和 Heroku 为您的模型创建一个应用程序。在本教程中,我选择放弃这种方法。开发数据科学产品是一项非常有用的技能,我本人正在深入研究这些过程。我鼓励你也这样做!

除了数据产品,您还可以创建一份数据科学报告。你可以用演示文稿向公司展示你的成果,并对整个过程进行技术概述。记住要记住你的听众。如果你要向一屋子的数据科学家展示结果,请详细说明。如果你在给销售团队提建议,在解释你的结果之前,不要花 45 分钟谈论通用逼近定理。对我来说,数据科学报告有点像迷你论文。你正在提交一篇论文,你的同事(和老板)会仔细审查,你需要为这篇论文辩护。

如果你的公司允许你发表结果,我会建议你把你的报告带到数据科学会议上。对于数据科学社区来说,关于您的项目的反馈总是一次很好的学习经历。如果你想看一些精彩的演示,可以看看 YouTube 上的 PyData 视频。此外,写一篇博客文章并将您的代码推送到 GitHub ,这样数据科学社区就可以从您的成功中学习。交流你的结果是科学过程的一部分,所以不要隐藏你的发现!

7)结论

我希望这个工作流程和迷你项目对有抱负的数据科学家和与数据科学家一起工作的人有所帮助。就像我提到的一百万次,有很多细节,我在这里掩饰。如果您有任何问题或意见,请告诉我!

8)资源

工作流程的想法来自威廉·沃尔夫(Platzi.com)和凯茜·奥尼尔和瑞秋·舒特的《做数据科学》。

统计学习的要素统计学习介绍是很好的文本,可以提供我忽略的许多主题的更多细节。

电汇给布里斯·沃尔夫冈编辑。

Aakash Tandel

aakashtandel.com

[## 阿克什·坦德尔(阿克什·坦德尔)

aakashtandel 有 12 个可用的存储库。在 GitHub 上关注他们的代码。

github.com](https://github.com/aakashtandel)

高效项目生命周期的数据科学家指南

原文:https://towardsdatascience.com/a-data-scientists-guide-to-an-efficient-project-lifecycle-c4f44ef41df7?source=collection_archive---------7-----------------------

最近,我发现自己处于一个项目的末尾,这个项目花费的时间可能是它应该花费的 3 倍。与预期的 6-8 周不同,我的团队花了 5 个多月的时间来应对不断变化的目标、收集和验证数据的低效方法,以及探索各种解决方案。

回过头来看,这些都是反复出现的问题,本可以通过更有纪律的决策来缓解。简而言之,有三个主要原则可以在不牺牲结果质量的情况下大幅缩短项目长度:

  1. 快速失败
  2. 40/70 法则
  3. 费米估算

在回顾这些原则的作用之前,我应该提到定义总体目标的重要性。正如我在之前的帖子中所说:

您定义问题和目标的方式对于确定使用哪些绩效指标以及在何处设置标准至关重要。定期停下来,以确保您的问题、目标、指标和数据仍然一致。

假设我们的任务是建立一个识别狗图片的模型。我们可以找到地球上所有动物的数据集,训练一个模型单独挑出每种动物,然后然后选择只有狗的照片。然而,我们也可以只选择有狗和没有狗的照片,用更少、更有效的数据训练更有效的分类器。方法的不同可能意味着数月的数据收集、验证和复杂的评估指标。花在案例驱动目标上的每一个单位的时间都将为你的团队节省数十个到达终点线的时间。

快速失败

快速判断解决问题的方法是否可行是很重要的。快速失败是一种方法论,用于在初步测试后判断一个想法是否值得追求。

设定一个初始目标并尝试 A 方法可以很快告诉你是否在大概范围内。如果没有,在回到 A 方法进行微调之前,你可能值得花时间去寻找其他途径。

举个例子:我想把情感分析放在我的产品里,我收集了一些真相数据。我可以尝试使用一种简单的方法,通过识别一系列表示积极和消极情绪的单词,并计算出现的次数。然而,如果当我仔细地为我的产品设置一个 70%准确率的标准时,这个方法达到了 25%的准确率,当我可以尝试另一个方法时,修改这个方法可能没有用。

四七法则

通常情况下,人们在做决定前会尽量等待,直到掌握尽可能多的信息。虽然这有助于我们感觉更好,但从长远来看,这并不一定会带来更好的结果,尤其是当许多决定需要快速做出的时候。

前国务卿科林·鲍威尔(Colin Powell)认为,领导者应该掌握不低于 40%也不高于 70%的信息来做决定。任何低于这个门槛的都被认为是不成熟的,任何高于这个门槛的都意味着你已经等了太久。

问问你自己完美的信息是什么样的,然后反过来找出门槛在哪里。这不是一个硬性规定,因为 35%到 45%的信息之间的界限太难尝试和客观区分。相反,关键在于找到知情及时决策之间的平衡。

例如:如果我有 10 个类问题,我需要弄清楚我的真实数据有多可靠,也许我可以使用众包来验证 4 个类,并进行推断以减少成本和时间。如果数据被错误标注,那么使用它就没有什么意义了。我已经决定尝试一种新的方法,而不是花费时间和金钱来检查每一寸数据,因为我已经有了做出及时而明智的决定所需的所有信息。

费米估计

费米估计是使用近似值来获得一个复杂问题的“足够好”的答案,而不需要花费大量的时间和金钱。要获得更详细的解释,请阅读本文,或者略读引言以获得其要点。

我发现费米估算在估算项目长度时非常有用。通过分解项目的不同部分,我们可以快速乘以各种任务的预期长度,以找到一项任务将花费多长时间的粗略估计。在项目开始的时候,知道某件事需要一天、一周还是两周是非常有用的。有一个大概的估计可以帮助数据科学家更有效地设置期望值和规划他们的工作流程。

费米估算本质上是不精确的,并且估算总是可以被更新,以获得关于项目长度的预期的越来越精确的视图。

简单>花哨(加分)

这一原则的核心是机会成本。过度设计解决方案会浪费时间追求不必要的复杂解决方案,没有真正的附加价值。例如,当我们可以通过 scikit-learn 的逻辑回归模型获得足够好的分数时,为什么要用 tensorflow 精心设计复杂的神经网络呢?绝招问题——没有理由这样做。

然而,并不是所有的例子都如此明显。让我们考虑一下我们的情感示例:如果我设定一个 70%准确率的目标来发布一个用于生产的情感分析模型,我可以尝试朴素的单词字典方法,并计算正面和负面单词的出现次数。

如果这种方法让我达到 67%的准确率,我应该重新考虑成功的标准,并在尝试使用更复杂的东西之前确保我们的简单模型 T2 确实不够好。

有时候,简单的解决方案已经足够好了,你最好把时间花在新的问题上,而不是对现有的解决方案进行不必要的微调。机会成本是关键。

结论

数据科学问题很复杂,在没有完美信息的情况下做出决策会让感到错误。通过一些启发和保持更大的视野,我们可以克服寻找完美信息和设计完美解决方案的自然倾向。感谢您的阅读,希望您能在这些提示中找到价值!

数据科学家的数据结构和算法指南,第 1 部分

原文:https://towardsdatascience.com/a-data-scientists-guide-to-data-structures-algorithms-1176395015a0?source=collection_archive---------2-----------------------

注意:这是 2 部分系列的第 1 部分。后续帖子见 此处

在数据科学中,计算机科学和统计学融合在一起。作为数据科学家,我们使用统计原理来编写代码,以便我们可以有效地探索手头的问题。

这至少需要对数据结构、算法和时空复杂性有一个基本的了解,这样我们才能更有效地编程并理解我们使用的工具。对于较大的数据集,这变得尤为重要。我们编写代码的方式会影响我们分析数据的速度,从而得出相应的结论。在这篇文章中,我将描述大 O 符号作为一种描述时空复杂性的方法,并简要回顾一些与时间复杂性相关的算法。在以后的文章中,我将讨论与空间复杂性相关的算法。

大 O 批注

在编程中,算法是为了实现特定目标而遵循的一个过程或一组规则。一个算法的特征是它的运行时间(运行时间),无论是空间还是时间。作为数据科学家,我们对最有效的算法感兴趣,这样我们就可以优化我们的工作流程。

在计算机科学中,大 O 符号用于描述一个算法增长有多“快”,通过比较算法内的运算次数。这将在后面进一步详细解释,但现在,让我们理解所有的正式符号。

形式符号

  • 大ω:最好的情况。算法的大ω描述了算法在最佳情况下运行的速度。
  • 大 O:最坏的情况。通常,我们最关心的是大 O 时间,因为我们感兴趣的是一个给定的算法在最坏的情况下会运行多慢。我们如何从本质上让“最坏的情况”不那么糟糕?
  • 大θ:这只能用来描述一个算法的运行时间,如果大ω和大 O 相同的话。也就是说,算法的运行时间在最好和最坏的情况下都是相同的。

因为我们最关心的是一个算法的大 O,所以这篇文章的其余部分将只关注大 O。

我们如何用大 O 来描述一个算法?假设你想在电话簿中搜索某人的名字。

Phone books: before Google was a thing

找到这个人最直接的方法是什么?你可以查遍电话簿上的每个名字直到找到你的目标。这就是所谓的简单搜索。

如果电话簿很小,只有 10 个名字,这是一个相当快的过程。但是如果电话簿里有 1000 个名字呢?

在最好的情况下,你的目标的名字在列表的前面,你只需要检查第一项。在最坏的情况下,你的目标的名字在电话簿的最后,你需要搜索所有 1000 个名字。随着“数据集”(或电话簿)大小的增加,运行简单搜索所需的最长时间也呈线性增加。

在这种情况下,我们的算法是一个简单的搜索。大 O 符号允许我们描述最坏的情况是什么。最坏的情况是,我们将不得不搜索电话簿中的所有元素( n )。我们可以将运行时间描述为:

O(n) where n: number of operations

因为操作的最大数量等于我们的电话簿中元素的最大数量(您可能需要搜索所有元素来找到您的目标的名字),所以我们说简单搜索的大 O 是 O( n )。一个简单的搜索绝对不会比 O( n )时间慢。

不同的大 O 运行时间

不同的算法有不同的运行时间。也就是算法增长速度不同。从最快到最慢,最常见的大 O 运行时间是:

  • O(log n ):又名日志时间
  • O( n ):又名线性时间
  • O( n 日志 n )
  • O( n )
  • O( n !)

大 O cheatsheet 对于不同运行时间的快速图形表示以及它们之间的相互比较也非常有用。

A graphical representation of common Big O run times (credit: http://bigocheatsheet.com/)

在这篇文章及其后续文章中,我将描述由这些不同的运行时描述的常见算法。

笔记

在讨论一些常用算法之前,有一些重要的原则需要理解。

递归:递归是指函数调用自己。也许递归的典型例子是阶乘函数的实现:

def factorial(n):
    if n < 1:        #base case
        return 1
    else:             #recursive case
        return n * factorial(n-1)

该函数在函数自身内被调用,并且将继续调用自身,直到到达基本情况(在本例中,当 n 为 1 时)。

分而治之(D & C): 一种解决问题的递归方法,D & C (1)确定问题的最简单情况(也称为基本情况)和(2)减少问题,直到它现在是基本情况。

General overview of divide & conquer technique (credit: http://bigdata.ices.utexas.edu/project/divide-conquer-methods-for-big-data-analytics/)

也就是说,一个复杂的问题被分解成更简单的子问题。这些子问题被解决,然后它们的解决方案被组合以解决原始的、更大的问题。

常见算法

搜索和排序算法可能是首先要理解的最重要的算法。

搜索

简单搜索 这在前面的电话簿示例中已经描述过了,最糟糕的情况是需要搜索电话簿中的所有名字,然后才能找到感兴趣的名字。一般来说,简单搜索的时间为 O( n )。所需的最大时间与列表中元素的数量成线性关系。

二分搜索法
让我们继续以电话簿为例。我们仍然对在电话簿中查找某人的名字感兴趣,只是这一次我们将尝试更有效地查找。我们将从电话簿的中间开始,从那里开始,而不是单调乏味地浏览电话簿中的每一个名字。

假设我们的目标名字以一个 P. 开头,我们打开到大约在字母表中间的 M s。我们知道在字母表中 MP 早,所以我们可以删除从 AM 的部分。现在我们可以查看电话簿的后半部分( NZ ),从中间分割该部分(到 Ts ,并与我们的目标进行比较。在字母表中,T 比 P 靠后。我们然后知道要剔除后半部分( TZ )。我们现在专注于 NS ,把这个分成两半等等,直到找到我们感兴趣的名字。

一般来说,在二分搜索法,你把你的排序后的(这很重要)数据,找到中点。每一次,你都将你的目标与中间值进行比较。如果目标值与中间值相同,那么您的工作就完成了。否则,根据比较,你就知道应该消除列表中的哪一半。继续分割,直到找到目标或数据集无法再被分割。

Diagram of binary search with a list of numbers

因为二分搜索法涉及到数据集的减半,所以大 O 时间是 O(log n )。因此,它比简单搜索更快,尤其是当数据集增长时(该算法的增长不是线性的,而是对数的,因此相对于 O( n ))的线性运行时间,它增长得更慢)。

顺便说一句,二分搜索法可以递归编写,但不认为是 D&C 算法。尽管较大的输入确实被分解成子集,但是如果这些子集不包含感兴趣的值,它们将被忽略。没有为这些子集产生解决方案,因此它们可以被组合以解决更大的输入。

分类

选择排序 很像简单的搜索搜索算法,选择排序可能是最直接的,对你的数据进行排序的‘蛮力’方式。本质上,您遍历列表中的每个元素,并按照所需的顺序将每个元素添加到一个新列表中。例如,如果您对从最大到最小的数字列表排序感兴趣,您可以:

  1. 在列表中搜索以找到最大的数字
  2. 将该号码添加到新列表中
  3. 转到原始列表,再次搜索以找到下一个最大的数字
  4. 将该号码添加到新列表中,以此类推…

对于选择排序,您必须遍历列表中的每一项(这需要花费 n 次,就像简单搜索一样),并且您必须这样做 n 次(不仅仅是一次,因为您必须不断返回到原始列表以找到您想要添加到新列表中的下一项)。因此,这需要 O( n 时间。

快速排序与选择排序有什么不同?如果我们像以前一样处理一系列数字:

  1. 从列表中选择一个元素,称为轴心。枢纽的选择对于确定快速排序算法的运行速度非常重要。现在,我们可以每次选择最后一个元素作为轴心。(关于 pivot 选择的更多信息,我推荐斯坦福 Coursera 算法课程。)
  2. 对列表进行分区,使所有小于主元的数字都在它的左边,所有大于主元的数字都在它的右边。
  3. 对于列表的每一半,你可以把它当作一个有新支点的新列表,重新排列每一半,直到它被排序。

Diagram of quicksort with a list of numbers

快速排序是 D&C 算法的一个例子,因为它将原始列表分成越来越小的有序列表。然后将这些较小的有序列表组合起来,得到一个较大的有序列表。

快速排序是独一无二的,因为它的速度取决于枢轴选择。在最坏的情况下,它可能需要 O( n )的时间,这与选择排序一样慢。但是,如果 pivot 总是列表中的某个随机元素,则 quicksort 平均运行时间为 O( n log n )次。

假设我们仍然在处理我们的数字列表。对于合并排序算法,列表将被分解成单个元素。然后从这些元素创建有序对(较小的数字在左边)。然后,这些有序对被分组为四个有序组,这一过程一直持续到最终的合并排序列表被创建。

Animated overview of mergesort algorithm (credit: By Swfung8 — Own work, CC BY-SA 3.0, https://commons.wikimedia.org/w/index.php?curid=14961648)

与 quicksort 一样,mergesort 是一种 D&C 算法,因为输入列表在被组合以产生更大的原始列表的有序版本之前被分解和排序。

Mergesort 运行 O( n log n )次,因为整个列表被减半(O(log n )),并且这是针对 n 个项目完成的。

算法和数据结构的知识对数据科学家很有用,因为我们的解决方案不可避免地是用代码编写的。因此,理解我们的数据结构以及如何从算法的角度思考是很重要的。在我的下一篇文章中,我将描述常见的数据结构、空间复杂性和常见的相关算法。

其他有用资源:

  • Aditya Y. Bhargava 的 搜索算法
  • 破解编码访谈 作者格利·拉克曼·麦克道尔
  • 斯坦福大学 Coursera 算法专业化
  • 大 O 小抄

数据科学家的数据结构和算法指南,第 2 部分

原文:https://towardsdatascience.com/a-data-scientists-guide-to-data-structures-algorithms-part-2-6bc27066f3fe?source=collection_archive---------4-----------------------

在我的上一篇文章中,我描述了大 O 符号,为什么它很重要,以及常见的搜索和排序算法及其时间复杂度(本质上,一个给定的算法在数据大小变化时的运行速度)。现在,有了基础知识,我们可以开始讨论数据结构、空间复杂性和更复杂的绘图算法。

空间

以前,我使用大 O 符号来描述一些常见的搜索和排序算法的时间复杂度。大 O 也是用来形容空间复杂度的。毕竟,时间不是我们可支配的唯一有限资源。任何计算机都只有这么多的空间(也称为内存),任何给定的算法也可以用它需要的工作存储量来表征。可以想象,随着我们感兴趣的数据集的增长,空间变得更加令人担忧。

当处理数据时,选择正确的数据结构允许我们优化时间和空间,这样我们的管道运行得足够平稳,允许我们得出结论

数据结构

数据可以以不同的方式存储;存储的方式确实是依赖于上下文的。

让我们从由它们的排序行为定义的更抽象的数据结构开始。这些数据结构被称为堆栈和队列,在许多语言中可能没有正式的实现,尽管它们可以并且经常是手动实现的。

它们的重要性主要在于解释管理数据和访问内存的不同方式。随着数据量的增加,数据结构的选择变得越来越重要;与各种操作相关的大 O 时间取决于数据结构。栈和队列,作为概念,告知基本数据结构(如列表和数组)是如何组织的。实际上,堆栈和队列也经常被合并到许多算法中,并且是这些算法如何工作的组成部分。

后进先出(LIFO)排序。添加到堆栈中的最后一个项目总是第一个被移除。为了理解堆叠是如何工作的,想象一个假设的盘子堆叠。

你总是把一个新盘子放在盘子堆的顶部(或末端)。当你想要一个盘子时,你可以从盘子堆里拿最上面的(或者最近添加的)盘子。添加(“推入”)到堆叠中的最后一个板首先被移除(“弹出”)。

您可能在处理列表时认识到了这个“推送”和“弹出”术语(实际上,在本文的后面,我们将把列表(或数组)称为数据结构)。

visual representation of a stack

队列

先进先出(FIFO)。添加到队列中的第一个项目将总是第一个被删除。这最好用一个实际的排队人群来说明。

第一个进入队列的人也将是第一个接受所需服务的人,对吗?这正是队列作为数据结构的工作方式。最新的项目仍然被推到队列的末尾,但是第一个项目首先被弹出。

既然我们理解了堆栈和队列,我们就可以描述我们通常会遇到的具体的数据结构实现。

具体数据结构

我们如何将这些抽象结构(栈和队列)与我们经常遇到的数据结构协调起来呢?

数组一个数组由一个线性的项目集合(称为元素)组成,连续存储在内存中。任何给定的元素都可以使用数字索引来访问,该索引指向元素在数组中的位置。在 Python native 中,这是用 list 类型实现的。

哈希表 在哈希表中,唯一键映射到值。在 Python 原生语言中,字典是哈希表的实现。

图表

作为一种抽象数据结构,图由节点和边组成,以模拟连接。想想一个人如何建立一个社交网络模型:

How are Bob, Sue, and Joe connected?

对于任何给定的节点,它的邻居构成了它所连接的所有节点。需要注意的是,上图是一个有向图的例子(节点是箭头,表示连接的单向方向)。因为苏和乔有联系(联系从苏到乔),所以乔是苏的邻居。然而,苏不是鲍勃的邻居。这种关系是单向的。

对于无向图,边不是箭头,关系是双向的。

在这样的无向图中,乔和鲍勃都是苏的邻居。


熟悉决策树的人应该已经知道树的一般结构。

every tree has a single root node from which all other nodes stem. each ‘child’ node will only have one parent node.

每棵树都有一个根节点,它实质上是所有其他节点的“起点”。任何两个节点之间都只有一条路径(而对于常规图,两个节点之间可以有多条边)。

由于决定它们各自结构的特征,通常用图来模拟网络,用树来模拟层次结构。图和树之间还有许多其他的差异,但这是最重要的一点。

然而,相同的算法对图和树都起作用(尽管由于结构的不同,实现方式不同)。因为图和树用于通过节点和边来建模关系,所以这种算法旨在沿着这些边“搜索”以表征任何给定节点之间的距离(和连接程度)。

(更高级的树有:二分搜索法树和红黑树)。

图形/树遍历

有不同的方法来遍历(搜索)这些结构,以便我们可以从起始节点找到感兴趣的节点。

这为什么有用?实际上,你可以做这样的事情:

  • 找到去教室的最快路线
  • 找到赢得象棋的最短路径
  • 在“迷宫”中找到通向出口的路径
  • 在你的 LinkedIn 网络中找到最近的 X 公司关系

从这些例子中可以明显看出,我们可以将许多问题建模为图,然后使用图搜索算法来解决这些问题。我们使用这些算法来评估(1)感兴趣的节点之间是否存在路径和/或(2)这些节点之间的最短路径。

这些算法最容易用树来解释(由于它的层次性)。然而,这也适用于图形。

广度优先搜索(BFS) BFS 从根节点(或图形的某个随机节点)开始,在移动到下一个深度之前,它检查第一个“级别”或深度的所有节点。BFS 通常用于评估任意两个给定节点之间是否存在路径,以及这两个节点之间的最短路径。

numbers correspond with the search order

实现是如何工作的?让我们考虑一下 BFS 要求的行为:第一个项目(根)也是第一个被搜索的项目(一旦被检查,就被删除)。这是先进先出(FIFO) 行为,因此将使用队列来顺序检查节点,直到找到目标。

这可能会令人困惑,所以让我们用更高级的术语来描述它。

我们使用图(或树)结构来描述关系。因为图是抽象数据结构,所以必须使用具体的数据结构(将每个节点映射到其相邻节点)在代码中手动实现。现在我们需要在图上实现我们感兴趣的算法(BFS)。因为 BFS 的特点是 FIFO 行为,我们使用队列结构来手动实现 BFS。

抽象地说,我们可以说树结构是用来描述关系的。堆栈和队列结构用于描述行为。

BFS 在日常生活中有什么用处?

你对 X 公司感兴趣,你想在你的关系网中找到在 X 公司工作的人。你更喜欢找一个和你“更亲近”的人;一级连接比四级连接更可取。这对 BFS 来说再好不过了。你先搜索你的一级人脉(先加的),再搜索你的二级人脉(他们的朋友)等等。

深度优先搜索(DFS) DFS 从根节点(或图的某个随机节点)开始,在回溯之前沿着单个分支一路向下搜索。

numbers correspond with the search order

与涉及队列实现的 BFS 不同,DFS 涉及堆栈的实现。总是首先检查根节点(在 BFS 和 DFS 中)。如果它不是感兴趣的节点,它的后续子节点将被添加到堆栈的顶部:

  • 节点 8、7 和 2 按此顺序添加到堆栈中。此时,节点 2 位于堆栈的顶部
  • 栈顶(节点 2)被检查。如果它不是感兴趣的节点,它的子节点,即节点 6 和 3,将按此顺序添加到堆栈的顶部。此时,节点 3 位于堆栈的顶部。
  • 栈顶(节点 3)被检查。如果它不是感兴趣的节点,它的子节点,即节点 5 和 4,将按此顺序添加到堆栈的顶部。此时,节点 4 位于堆栈的顶部。
  • 节点 4 已选中。它没有孩子。如果不是感兴趣的节点,则检查下一个节点(节点 5)。

诸如此类…

DFS 通常用于更复杂的算法中。

与树不同,图可能是循环的(每个节点可以有一个以上的连接,因此,存在返回到同一个节点的风险)。当与图形结构一起使用时,这些算法变得更加复杂。我推荐斯坦福算法课程了解更多信息。

BFS 与外勤支助部

BFS 和 DFS(以及相关的运行时间)的使用确实因数据和图/树结构而异。

两种算法的时间复杂度相同。在 BFS 和 DFS 中,每个节点只被访问一次。big-O 时间是 O(n)(对于树中的每个节点)。

然而,这些算法的空间复杂度各不相同。

对于 BFS,它遍历树中给定深度的所有节点,并使用队列实现,树的宽度很重要。BFS 的空间复杂度是 O(w ),其中 w 是树的最大宽度。

对于 DFS,它沿着一个“分支”一直向下,并使用堆栈实现,树的高度很重要。DFS 的空间复杂度是 O(h ),其中 h 是树的最大高度。

Dijkstra 算法

对于 BFS,我们假设所有的树都没有加权。最短路径简单地定义为具有最少边的路径。

像 BFS 一样, Dijkstra 的算法也试图找到节点间的最短路径,但它是在加权图(有向无环图)上操作的;这些边具有不同的权重或一些成本(如时间或距离)。

因为边将具有不同的权重,所以任意两个给定节点之间的最短路径不一定是具有最少线段的路径。Dijkstra 的算法识别总权重最小的路径。

流程1。从起始节点,找到并访问“最便宜”的节点

assume cost is in minutes. from start, go to node A (has the lowest cost, 3 versus 10)

到节点 A 的时间:3
到节点 B 的时间:10
到结束的时间:无穷大(未知)

2.在这个新节点上,更新其相邻节点的成本(对于任何给定的邻居,可以通过计算从起始节点到那里的成本来完成)。

2a。如果先前访问的任何相邻节点的成本发生变化(您必须访问图中的每个节点,因此成本可能会发生变化),您必须更新任何成本。

time to node B is updated from 10 to 7 minutes (fastest path is through node A)

到节点 A 的时间:3
到节点 B 的时间:7
到结束的时间:8

3.对图中的每个节点重复上述步骤。

focus on node B now

不需要更新权重。

到节点 A 的时间:3
到节点 B 的时间:7
到结束的时间:8

4.计算最终的最低成本路径。

最短路径仍然是通过节点 a。

数据结构的大时代

对于任何给定的数据结构,访问、搜索、插入和删除都有不同的运行时间。

例如,对于一个数组,如果删除了任何给定的元素,所有后续的元素都必须相应地移动。访问数组非常快(O(1)),因为元素在内存中是连续排列的,并且可以通过索引来访问。但是连续排列使得与删除相关的 big-O 时间变得更糟。

source: http://bigocheatsheet.com/

随着数据结构基础的下降,我认为简要讨论两个在讨论算法时经常使用的主题可能会有所帮助。

贪婪算法

贪婪算法是一种快速找到最大值或最小值的方法。它用于描述常见的算法,如决策树分析(根据熵减少的多少在每一步做出决策)。

背包问题是描述贪婪算法如何工作的一种常见方式。

假设你有一个背包,一个只能装 20 磅的背包。你面前有几样东西,每样都有不同的重量和价值。你想最大化你放入背包的物品的总价值,而不超过背包所能承载的最大重量。(假设尺寸不是问题。)

  • 笔记本电脑:2200 美元(3 磅)
  • 显示器:2500 美元(18 磅)
  • 扬声器:1500 美元(15 磅)

第一步,你伸手去拿价值最高的东西,显示器。在第二步,你会拿到下一个最高价值的物品,笔记本电脑。然而,背包只能容纳 20 磅,所以现在没有更多的空间放笔记本电脑或任何其他物品。你有价值 2500 美元的物品。

最佳解决方案实际上是带上笔记本电脑和扬声器。你不会超过 20 磅的最大重量,并且会有价值 3700 美元的物品。

背包问题说明了贪婪算法的过程及其缺陷。它并不完美,当然,贪婪算法也不能保证你得到最优解。但它离工作地点很近,有时,这就是你所需要的。最终,你的包里仍有价值 2500 美元的物品。

动态规划

与贪婪算法相反,d 动态规划是一种详尽的问题解决方法,它涉及将一个大问题分解成子问题并解决这些子问题。保证能找到最优解。在每一步之后,基于先前的决策做出决策,并且可以重新考虑先前的步骤(参见上面的 Dijkstra 算法中的动态规划示例)。

它不同于也涉及子问题的分治(D&C)方法。D&C 涉及递归解决子问题,然后组合这些解决方案来解决更大的问题。动态规划解决重叠子问题(考虑与到达任何给定节点相关的成本如何取决于先前访问的节点)。每个子问题只需要解决一次,因为每个子问题的解决方案都存储在一个表中,如数组或哈希表(称为记忆)以供将来参考。

我希望大家清楚为什么理解数据结构和算法对于数据科学的成功工作如此重要。当然,除了我的博客帖子所涵盖的内容之外,还有更多的内容,我鼓励你寻找更多的资源来真正丰富你对这个主题的理解。下面是我推荐的一些资源(也列在我之前的博文中):

  • 搜寻算法Aditya y . Bhargava 著
  • 破解编码访谈 作者格利·拉克曼·麦克道尔
  • 斯坦福大学 Coursera 算法专业化
  • 大 O 小抄

TensorFlow 路演的一天

原文:https://towardsdatascience.com/a-day-in-tensorflow-roadshow-dae64b470fe7?source=collection_archive---------5-----------------------

TensorFlow Roadshow Bangalore

TensorFlow 最初是由谷歌大脑团队的研究人员开发的内部项目,现在已经成为 2018 年最受欢迎的软件库( Stack Overflow 的 2018 年调查)。谷歌在 2015 年将 TensorFlow 开源,从那以后,它一直在不断发展,在社区方面也在增长。这是一个令人鼓舞的因素,不仅让谷歌变得更好,让更多的研究人员可以访问,也让机器学习社区尝试这个库,并用它来建立模型,从而解决了许多关键问题。关注社区的反馈确实对 TensorFlow 有所帮助,TensorFlow 团队一直在以多种方式与社区互动。昨天,TensorFlow 团队在班加罗尔为机器学习社区组织了一次路演,并进行了精彩的会议。

此次路演出席人数众多,谷歌开发人员关系主管 Karthik Padmanabhan 对开发人员社区表示欢迎并致辞。在过去的几年里,机器学习,更具体地说是深度学习,改变了许多关于技术如何影响人类生活的事情。深度学习的进展导致了计算机视觉和 NLP 相关任务的快速发展。在所有这些进步的帮助下,ML 使许多以前想都不敢想的事情成为可能。TensorFlow 作为一个帮助构建机器学习解决方案的库,正在通过让研究人员将他们解决问题的想法转化为现实来推动机器学习向前发展。Dushyantsinh Jadeja 开始了当天的第一场会议,强调了 ML 在我们生活中的不可避免性,以及 TensorFlow 如何帮助构建了一些改变生活的解决方案。

Pic Credit

TensorFlow 用于解决许多问题,如在天文学中检测新的太阳系和行星,通过使用传感器进行实时检测来避免砍伐森林,并自动警告任何非法活动,评估谷物质量,更好地帮助农民和农业,最积极的是,在医学领域帮助医生做出更好更快的决定。作为一个有潜力解决这类问题的库,TensorFlow 成为 ML 使用最多的库之一并不奇怪。

TensorFlow 的项目经理 Sandeep Gupta 在当天的第一次演讲中简要介绍了一些主要的和最常用的 TensorFlow 模块和功能。TensorFlow 提供高级 API,如 Estimators、tf.data 和非常受欢迎的 Keras API,使构建机器学习模型变得简单快捷。保存的 TensorFlow 机器学习模型可以使用 TFLite 转换并部署到移动设备上。TF.js 使 JavaScript 开发人员能够在浏览器本身利用机器学习。Tensor2Tensor 是一个独立的库,提供现成的数据集和模型。当天晚些时候,我们进行了非常有用的讨论,深入了解了一些有用的工具和库的细节。虽然 TensorFlow 到目前为止有超过 1600 名贡献者,但他们中的大多数人都来自谷歌之外!

Using TensorFlow to Prototype and train models

建立机器学习模型来解决问题包括几个步骤,从数据收集开始,直到保存和部署训练好的模型。Amit Patankar 使用一个心脏病数据集来快速带领我们完成建立机器学习模型的不同步骤。在这样做的同时,他还展示了评估者如何通过提供可以尝试和评估的不同模型来使这一过程变得更容易和更好。这时是沃尔夫·多布森上台的时候了。为了在 TensorFlow 中编码和运行任何东西,首先需要创建一个包含所有必要组件的图,然后从一个会话中运行该图。虽然这种执行模式有其自身的优点,如更好的优化、简化的分布式培训和部署等,但这种方法可能会有点乏味,而且对初学者不太友好。与此相反的是急切执行模式,在这种模式下,执行会立即发生,不需要会话。对于初学者和研究人员来说,这听起来要好得多,可以对他们的模型进行原型化和编码。但是这里的权衡正在失去前一种方法带来的优势。如果我们能获得两种方法的优点,那不是很好吗?这就是亲笔签名的作用!

AutoGraph — Credit

AutoGraph 以 eager 模式获取代码,并将其转换为等价的图形。上面的图片是一个例子,它展示了代码在两种模式下是多么的不同,以及 AutoGraph 是多么的有用!通过使用 AutoGraph,可以在 eager 模式下构建原型,在 Graph 模式下部署。Wolff Dobson 还谈到了将于明年发布的 TensorFlow 2.0 正在进行的工作,并要求社区通过 RFCs(征求意见)流程参与设计决策。

接下来的两个演讲是关于使用分布式计算和加速器的 TensorFlow。Priya Gupta 谈到了分布式张量流。根据使用的数据集、选择的架构和其他一些因素,训练机器学习模型可能需要几分钟到几天或几周的时间。与非分布式模式相比,分布式培训有助于大幅减少培训时间。在这种模式下,集群(一组工作器/处理器)用于图形执行,而不是单个处理单元。这不仅导致更少的训练时间,而且导致更好的性能,这可以通过最小的代码改变来实现。TPU 是张量处理单元,具有强大的计算能力。TPUs 与分布式 TensorFlow 一起为构建深度学习模型提供了很好的结果。在他的演讲中,Sourabh Bajaj 解释了快速发展的深度学习方法的计算需求如何导致 TPU 的设计和开发。

Distributed TensorFlow

在建立机器学习模型时,除了代码之外,还有许多事情需要考虑和担心。收集数据,为模型训练做准备是一个耗时的过程。由于模型的性能和准确性高度依赖于用于训练的数据,因此数据验证和转换非常重要。在高层次上,机器学习模型获取数据并从中学习,以输出可用于推理的训练模型,将此用于生产涉及许多约束和要求。TensorFlow 不仅专注于构建和部署模型,还在增加对机器学习管道其他部分的支持,TensorFlow Extended (TFX)正是这样做的。Kenny Song 通过一系列幻灯片解释了 TFX 是什么以及它的作用。TFX 是一个端到端的 ML 平台,它提供库来验证和分析训练和服务的不同阶段的数据,分析不同数据切片的训练模型等。他还谈到了 TF Hub,这是一个可重用机器学习模块的存储库。模块包含 TF 图及其为某些特定任务训练的学习权重。这些模块可以按原样用于相同的任务,也可以通过一些修改来重用,以解决类似的其他任务。

TFX

仅在几年前,没有多少人会想到在浏览器中训练和运行机器学习模型。但这现在已经成为现实,这要归功于 TensorFlow.js. Sandeep Gupta 就此发表了另一篇演讲,他分享了 TensorFlow Playground 如何为 TensorFlow.js 铺平了道路。Playground 是一种交互式神经网络可视化工具,旨在从浏览器运行。开发这个工具的团队必须做大量的工作,因为移植这个机器学习工具以从浏览器运行涉及一些障碍和限制。在这样做的同时,他们意识到了将机器学习引入浏览器的潜力。从浏览器运行 ML 模型有很多好处——不需要安装驱动程序,它是交互式的,与传感器连接良好,数据与用户在一起。所有这些导致了 TensorFlow.js,它是一个用于在浏览器中构建和部署 ML 模型的 JavaScript 库。对于一些可以在你的浏览器上运行的很酷的 ML 项目,请看博客末尾的链接。

Edge TPU — Credit

如果模型能在高端设备上高效运行,这还不够。随着手机成为最常用的设备,让 ML 模型尽可能高效地在低端设备上运行的探索也取得了一些成果。软件工程师 Andrew Selle 是 TensorFlow 团队的一员,他带我们了解了 TensorFlow Lite,该软件使移动和嵌入式设备能够运行 ML 模型。直接从设备运行 ML 模型有很多优点。由于不需要联系任何服务器来进行推断,移动 ML 导致了更低的延迟,并且不依赖于数据连接。在这种情况下,数据完全不在设备上,因此避免了任何隐私问题。但这是一项具有挑战性的任务,因为手机和嵌入式设备内存紧张,能耗低,计算能力差。TFLite 使这成为可能,并且已经被许多应用程序用于生产。边缘 TPU 是 TPU 的变体,开发用于为移动通信的边缘设备供电。

TensorFlow for art and music

随着 ML 在几乎每个领域都找到了自己的位置,艺术家们也投身其中。使用 ML 来提出某种艺术形式已经成为一种日益增长的兴趣。ML 被用来创作自己的绘画、作品、音乐等。Magenta 是一个 TensorFlow 项目,用于使用机器学习生成艺术和音乐。沃尔夫·多布森再次登上了舞台,最后一次讲述了这神奇的一天。他向我们展示了使用 TensorFlow 构建的一些播放音乐和游戏的应用程序的演示。

成为技术的一部分是一个激动人心的时刻。像这样的会议可以提供很多东西,通过参加这样的社区活动,人们可以了解和学习到很多东西,这是令人惊讶的。除了非常有用的谈话,见到 TensorFlow 团队和其他 ML 研究人员真的很高兴。感谢整个谷歌印度团队为社区组织了许多这样的精彩活动!

谷歌为任何对 ML 感兴趣的人免费提供许多资源,从初级速成课程到研究级博客。我写了一个博客,上面有很多这样有用的资源,你可以在这里找到——谷歌知道如何教。

你觉得这篇文章有用吗?欢迎留下任何反馈/意见。感谢阅读!!

连接:LinkedInTwitter和我的 博客

有用链接:

[## AutoGraph 将 Python 转换为张量流图

亚历克斯·维尔奇科,丹·摩尔多瓦,沃尔夫·多布森

medium.com](https://medium.com/tensorflow/autograph-converts-python-into-tensorflow-graphs-b2a871f87ec7) [## 可教机器

可教机器:探索机器学习,活在你的浏览器里。

teachablemachine.withgoogle.com](https://teachablemachine.withgoogle.com/) [## Metacar:浏览器中自动驾驶汽车的强化学习环境。

算法:Q-用表学习在这个例子中,目标是演示一个简单的 a…

www.metacar-project.com](https://www.metacar-project.com/) [## 用神经网络绘制在一起

更新(2018 . 8 . 2):sketch-rnn 已经移植到 Magenta.js 项目下的 TensorFlow.js!看一看…

magenta.tensorflow.org](https://magenta.tensorflow.org/sketch-rnn-demo) [## MusicVAE:使用机器学习创建乐谱调色板。

当一个画家创作一件艺术品时,她首先在艺术家的调色板上混合和探索颜色选项,然后…

magenta.tensorflow.org](https://magenta.tensorflow.org/music-vae) [## 谷歌知道如何教学

“够了够了!我受够了!”我脑袋里面的声音就是这样磨了几个小时才向我吼的…

towardsdatascience.com](/google-knows-how-to-teach-45e531ab3ada) [## 通过 Magenta.js 连接音乐

编者按:在过去的几个月里,我们注意到许多由 creative.ai 的 Tero Parviainen 开发的令人印象深刻的应用程序…

magenta.tensorflow.org](https://magenta.tensorflow.org/blog/2018/05/03/connecting-with-magenta-js/)

tensor flow Hub—https://tfhub.dev/

https://dl.acm.org/citation.cfm?id=3098021 TFX 纸—

TensorFlow.js 图库—https://github.com/tensorflow/tfjs/blob/master/GALLERY.md

营销分析专家的一天

原文:https://towardsdatascience.com/a-day-in-the-life-of-a-marketing-analytics-professional-83dd45f2e702?source=collection_archive---------3-----------------------

营销分析是一个多方面的,但往往被误解的做法。这里有一个例子来突出这个角色的多样性。

营销分析通常是任何世界级营销计划的基础。但是会议、采访和会谈让我明白,很少有人了解营销分析的世界。

一些人错误地将营销分析仅仅描述为数字分析——跟踪访问、点击和转化。是的,我们是这样做的,但这不是我们所做的全部。我听说有人把营销分析和市场调查混为一谈。我和我的市场研究同事密切合作,但我通常不做研究。有一次,有人愤怒地告诉我,我要为他们在 Spotify 上的广告负责。我从未在 Spotify 工作过。

我热爱我的工作的原因是,我的一天可以从简单的 SQL 编码到成熟的机器学习算法。我的角色是多样的,有影响力;我的分析推动数百万美元的决策。我有机会与每个人见面,从首席财务官到精力充沛的实习生。我观察整个生态系统的数据。我回顾每个产品领域的数据,深入研究产品行为、人口统计信息和文化趋势之间的关系。我将这项工作描述为应用计算社会科学。

为了提升这个价值,并揭示营销分析专业,我总结了“营销分析专业人员的一天”。项目和任务被压缩为 45 分钟的间隔,以确保我能够提供我经常处理的项目的代表性概述。

欢迎来到我作为营销分析从业者的一天。

上午 7.30—运行资源密集型 SQL 查询。

我喜欢早到。早餐,咖啡和 SQL 代码。数据库在早上运行最快,因为运行查询和消耗计算资源的分析师较少。我启动了一些需要大量计算能力的大型查询。快跑,你这个甜数据库,你。

上午 8.15——电子邮件和管理。

我的收件箱在嘲讽我。我支持全球各地的营销人员,所以我尽量早点查看收件箱,回答问题,尤其是来自 EMEA 同事的问题,他们刚刚结束一天的工作。

上午 9 点—聚类分析。

聚类时间。我拉起 R(统计软件)开始编码。我正在为基于教育的营销活动寻找产品的低于平均水平的用户。聚类是一种 ML(机器学习)技术,帮助我找到用户的“自然”分组。在这种情况下,我使用 ML 来确定“低于平均水平”的自然定义。我的 ML 工具根据特定的指标给出了从高到低的用户群。我接受低于平均水平的用户定义,这就是我的受众。

Cluster example; Source: CSSA

上午 9 点 45 分——咨询营销同事。

我与营销团队成员会面,帮助他们为即将到来的营销活动制定战略和方法。我们讨论潜在受众、关键绩效指标(KPI)、战略和预算。很有趣。我喜欢创意和头脑风暴。

上午 10:30——查看仪表盘和趋势。

回到我的办公桌,现在是“仪表板审查和电子邮件”时间。我为营销团队维护总共四个自动化仪表板。这些仪表板涵盖人口统计、营销绩效、区域数据细分和营销基准。我的目标是每两周发送一封简短的电子邮件,介绍仪表盘上的趋势。今天,我正在查看并通过电子邮件发送关于区域数据趋势仪表板的更新,查看特定国家的趋势,以帮助国内营销团队。

Tableau example; Source: Analytics Vidya

上午 11.15 分—活动结果分析。

结果时间。法国为期两个月的营销活动刚刚结束,团队正在寻找结果。我调出媒体印象文件开始分析。我们几乎所有的营销都是用测试和控制的形式来衡量的——测试受众接受营销,而类似的控制受众没有接受营销。我使用 SQL 和 R 来比较测试组和控制组的行为。我的目标是看看在产品行为指标上,各组之间是否有统计学上的显著差异。结果和学习进入总结报告卡文档以及我们的基准数据库。

中午 12 点——与产品分析师会面。

午餐会议。我会见了产品数据科学家,他们提供了他们看到的最新趋势和他们建立的新数据表。产品分析师负责理解特定产品领域的深层趋势和细微差别。他们还为自己的产品领域建立和维护关键数据表。作为一名营销分析师,我负责观察所有产品领域的相关性和相互作用。所以我依赖产品分析师的深入见解,并使用他们的各种数据表来衡量营销对用户行为的影响。我们谈论蜂巢表和趋势。 #BigData

下午 12.45——构建机器学习工具的工作会议。

我会见了我团队中的数据工程师。我们正在建立一个机器学习工具,它将自动化我们营销活动的各个部分,以帮助我们进行大规模测试和学习。这是一个令人兴奋的项目。我们花时间讨论算法,将我的 R 代码翻译成 Python,并计算出我们需要建立的数据库。科技爱好者团结起来。

下午 1 点 30 分——预测投资回报率。

回到我的办公桌。我的下一个项目专注于预测一个计划好的营销活动的投资回报率。目标是弄清楚这个活动是否值得投资。如果我开了绿灯,数百万美元将被投入,三个不同的团队将在这个项目上工作——所以我确保我仔细检查了我的数字。我会查看潜在覆盖范围、估计点击率和近似 CPAs(每次收购成本)等指标。我正在平衡快速回复和准确回复的需求。这种玩杂耍的行为是现代营销分析师的通病。我使用基准和多元回归来进行预测。

下午 2 点 15 分——活动的地理测绘。

位置,位置,位置。我将注意力转移到地理和制图上。一些队友已经获准在英国各地的城市创建一个“弹出式”活动计划。我已经在我们的规划和战略会议中预先选择了城市。现在,他们需要明确知道他们应该在城市的什么地方举办活动。他们询问午餐时间人流量大的地点。我使用 R 中带有映射功能的位置数据(我喜欢使用传单映射 API)来创建按位置划分的步行交通热图。我找出前三个地点,发给营销团队。我喜欢这个项目,我是一个喜欢热图的书呆子。

Heat map example; Source: Stack Overflow

3pm——撰写测量计划。

接下来,我需要写营销活动的测量计划部分。所有营销活动计划都必须包括一个衡量部分,概述 KPI、二级指标、目标、目标受众、地理位置和衡量方法。如果有意识或情绪研究的成分,我的研究同事也会添加到这一部分。我们的组织拥有强大的测试和学习文化,因此分析和研究(如果适用)部门会签署所有营销计划。

下午 3.45 分——第二轮邮件。

一天快结束了。我会花点时间查看邮件,回答当天的问题,或者前几天的未决问题。我每天都会收到很多问题,随着时间的推移,我学会了在回答问题时要简洁直接。我尽可能地使用主动的声音。这几天我已经把邮件里的垃圾都删除了,因为时间不够了。我把闲聊留到面对面交谈和咖啡聚会时。

下午 4:30—回顾日本的数据趋势。

我今天的最后一次会议——我正在和我们的日本市场经理讨论行为趋势。他是一个充满激情、风趣的人,喜欢钻研数字。我试着每两个月会见一次国家营销经理,向他们汇报我在仪表盘上看到的最新情况。这也是一个很好的机会听取他们对重要问题、我可以提供额外见解的领域以及他们的推广计划的意见。我打开为日本制作的交互式仪表盘,我们聊起了数据。Tableau 是我处理小型数据集的“首选”,但它无法处理我使用的数据表,所以我还使用了一个内部仪表板工具,可以处理大型(阅读:新标准)数据集。

下午 5.15——设置 SQL 查询通宵运行。

我的一天就要结束了。我的最后一个任务是设置一些 SQL 查询在夜间运行,为明天的分析创建数据表。我通宵运行它们,因为人们回家后有更多的服务器资源可用。当您处理具有数十亿和数万亿数据行的表时,您需要所有您能争取到的服务器资源。

如你所见,营销分析专业远远不止点击和转化。这是仪表板、算法、编码和内部咨询的大杂烩。这种多样性是我喜欢这个职业的原因。星期很少是相同的。

希望这篇文章已经强调了营销分析中提供的一些多样性。哦……如果你正在考虑一个结合数据、多样性和影响力的职业,营销分析将是值得考虑的。

深入了解物联网

原文:https://towardsdatascience.com/a-deep-dive-into-the-internet-of-things-2c8d813e9653?source=collection_archive---------6-----------------------

读安德鲁·明特尔 的《物联网分析》

本周,我一直在阅读 Packt 出版社最近出版的一本名为《物联网分析》的书。这是一本很棒的读物,我绝对可以把它推荐给任何想更多了解这个迷人领域的人。

有很多关于物联网的书,但这本书最吸引我。广告的文字“突破宣传,了解如何从海量的物联网数据中提取可操作的情报”特别吸引我——物联网是一个随处可见的术语,甚至在你最意想不到的地方。此外,它仅在一个月前(2017 年 7 月)出版,因此至少这意味着内容将是最新的,这是一个优势,因为该领域正在快速发展。

我不仅有兴趣了解物联网应用,还有它背后的技术,以及硬件和软件的结合,最后还有一个开发者的视角。这本书的作者是 Andrew Minteer,他目前是一家领先的全球零售公司的数据科学和研究高级总监。他是物联网领域的专家,拥有统计学、软件开发、数据库设计、云架构方面的背景,领导分析团队超过 10 年。从这本书来看,他也是一位伟大的作家。

“物联网分析”面向各种读者群体。在 Packt Publishing books 的序言中,有一个名为“这本书是给谁的”的部分描述了目标读者。最重要的是,这本书面向的是“目前正在努力利用物联网数据创造价值,或者正在考虑在不久的将来建立这种能力的专业人士。”这些人可能是"开发人员、分析从业人员、数据科学家和普通物联网爱好者。"就成本与收益而言,价值创造的确是一个突出的主题,但同样重要的是物联网数据流的不同组成部分:设备和传感器、网络协议以及数据收集技术。最后,读者将获得数据存储和处理选项及策略的概述,所有这些都以使用物联网大数据集实现商业价值最大化为基本主题。Python、R 以及 Tableau 中都有代码示例。

我喜欢这本书的一点是,作者从零开始,向你解释了人们对“物联网”、“物联网数据”的理解,以及为什么物联网数据不同于其他数据。作者用日常用语来阐述他的观点。例如,他在物联网分析中的第一条规则如下:“永远不要相信你不知道的数据。像陌生人给你糖果一样对待它。”另一个伟大的想法是以一个虚构的场景开始每一章,该场景是一名数据科学家与他的首席执行官进行对话,每次应用新的物联网数据分析场景时,都会接到新的任务,从而带来新的挑战。这些成为每一个新章节的主题,并赋予这本书一定的逻辑。它们读起来也很有趣,给了文本一点空气,因为大多数章节都很复杂。

事情很早就变得复杂了,例如在第 2 章中讨论了物联网设备和网络协议。下一章涵盖了面向云的物联网分析,描述了来自云基础设施市场领导者亚马逊的亚马逊网络服务。AWS 的服务列表长度令人印象深刻,作者在后面的章节中详细介绍了本书的一些相关服务,例如 AWS Lambda 和 AWS IoT 平台。正如作者解释的那样,这种云基础设施是来自各地设备的大量数据的最佳选择——云是处理和分析物联网数据的首选。

下一步是定义收集物联网数据的策略,以便进行分析。在这里,我们进入了大数据技术领域,因此期待来自 AWS、Microsoft Azure 和 Hadoop 生态系统等存储大数据技术的大量关于物联网特定服务的信息。我发现这一章是书中最强的一章,因为它详细解释了多个生态系统的许多不同组件,同时揭开了大数据分析的复杂性。干得好。

本书的后半部分更加实用:您将学习如何使用 Tableau 来探索和可视化数据,使用 R 语言来增强可视化工具,并了解一些特定于行业的示例。外部数据集可以增加现有数据集的价值,并且可能更容易访问,因为有许多免费的在线数据集可用。Tableau 再次用于可视化物联网数据分析的结果,这在准备仪表板时提供了一些很好的建议。

关于将地理空间分析应用于物联网数据的单独一章有点令人失望,因为它相当短,因此不完整。它没有提到最近的物联网和大数据分析工具,如 Esri 的 ArcGIS GeoAnalytics 和 ArcGIS GeoEvent Server。虽然这不是本书的重要部分,但它很容易成为一本书的主题。另一方面,作者解释得很好的是 GIS 中使用的不同文件格式,以及几个开放和封闭源数据库如何处理空间数据。

在关于物联网分析的数据科学的一章中介绍了机器学习概念,以及深度学习和预测。特别关注如何将这些方法用于物联网数据。每一个的核心概念都通过 r 中的例子进行了回顾,同样,如果你是这些主题的新手,这本书是一个很好的资源来解释它们和一些示例代码。由于作者是这些领域的专家,这是一个非常复杂和详细的章节,因此是核心章节,第三章是关于云的物联网分析。最后两章最后关注经济学(预算)和组织数据进行分析的策略。这两者是相互关联的:更多的数据意味着更多的云基础设施成本。如果没有明确的维护策略,数据湖可能会变成数据沼泽。

关于 Python 和 R 的使用,最后说一句:这两种语言在整本书中都有使用,但作者承认 Python 是大型数据集的更好选择,这通常(如果不总是)是物联网数据分析的情况。但是 R 比 Python 更容易实现数据分析,这也是事实(有时)。这也可能是作者的偏好问题,因为他在本书中多次选择 R 而不是 Python。我从这本书中获得的另一个深刻见解是 Linux 在大数据计算集群中的作用。正如作者在第 130 页所写的那样,“……你需要知道如何与 Linux 操作系统进行交互,以进行物联网分析。这是不可避免的,一旦你习惯了,也没那么糟糕。你不需要成为专家,但你需要知道如何找到自己的路,运行程序,并做一些基本的脚本。”这本书提供了许多这样的建议。这是与物联网相关的所有内容的绝佳资源,强烈推荐。

深入探究嵌入——一种语言学方法

原文:https://towardsdatascience.com/a-deeper-look-into-embeddings-a-linguistic-approach-89cc428a29e7?source=collection_archive---------3-----------------------

所以你可能知道 Word2vec 或者 Glove 甚至 Elmo,甚至可能知道它背后的算法(Skipgram 等)。但是,它们之间的区别是什么,为什么一个比另一个好?这个博客是关于单词嵌入及其解决的语言学问题的,利用了一篇非常棒的关于 ACL 的论文来帮助解释一些语言学概念。

那么首先,什么是嵌入?

它们可以被认为是一个学习查找表,其中输入是一个单词(一位热编码),输出是一个 n 维向量。

Picture from Adrian Colyer

这个博客不是为单词嵌入初学者准备的。如果你是这样的人,请访问 Adrian Colyer 的惊人的帖子,以获得对嵌入、连续单词包和 Skipgram 的良好概述。

所以——让我们从头开始,带着 NLP 的前辈们必须解决的问题:建模语言的问题。我们如何预测哪些单词序列有意义,哪些没有意义?更具体地说,给定一个长度为 t 的句子,其中有单词 w_1,w_2,…,w_t,那么 p(w_1,w_2,…,w_t)是多少,或者一个单词以那个特定顺序一个接一个出现的概率是多少?这将需要准确地表示单词的含义

那么,建模的真正含义是什么呢?

You in the future when others don’t understand what the big deal is about using the ELMO word embedding over Word2Vec.

一点语言形态学背景

首先,我们需要确保那些只是彼此版本的单词被映射到一个向量上。作为人类,我们知道“吃”,和“吃”有相同的意义,但形态结构不同。单词有一个词干,或引理,在吃和被吃的情况下会是“吃”正如这篇论文所言,“一个词的所有可能的词形都代表了这个词的词素”。

其次,有些词可能看起来很相似,但意思不同。以“蝙蝠”为例蝙蝠可能意味着恐怖电影中的动物,或者是美国最受欢迎的运动之一的击球动作。这两个,或者说 bat 的意思,被分配到各个词汇单位。

所有这些可能看起来只是一堆术语,所以论文中的这张图表很好地总结了这一点。

单词嵌入的神经网络方法使用直觉

“相似的单词也会被相似的上下文所包围”

从数学上来说,上面可以写成下面的目标函数

其中 x*和 x_t 是在句子中频繁出现在彼此 2N 个单词内的两个单词。

这意味着给定一个焦点词 x_t,Skipgram 将最大化该焦点词周围的相似词 x*的对数概率。通常,神经网络 Skipgram 训练模型的最终隐藏层将被用作单词嵌入。

虽然这一切都做得很好,但基于 Skipgram 的 approach post(在这里解释得很好)基于精确的字符匹配为每个单词分配一个表示。这意味着“bat”只获得一个平均 bat 的各种含义的向量,并将“bat”可能使用的各种上下文编码到一个向量中——这意味着对于该词的每个上下文,表示都将过于一般化(这是一个万事通,无所不能的情况)。然而,Skipgram 将“吃”、“吃”和“吃”映射到不同的单词表示,因为“吃”!=“吃”!=“吃了”,虽然都是同一个词干,来自同一个词汇单位。那样的话,Word2Vec 就太具体了,没有很好地处理多义词,所谓的多义词词。

Yep that’s probably what our NLP forefathers probably felt like

那我们该怎么办?

我们可以通过明确标注词类及其词汇形式来帮助半监督这种方法,从而增加一个额外的步骤。例如,您可以用词类显式地标记语料库中的单词,和/或将其转换为词条。例如,您可以将所有动词“going”替换为“going”。v”(表示词性)和 lemma(“go”),这将允许模型为多义词的各种意义区分和分配不同的向量。

现在,一切都解决了吧?

那么,单词嵌入模型没有见过的单词呢?多次被训练成单词级模型(至少在 Word2Vec 中)的 Skipgram 不能很好地处理这些情况。

其次,不同于诸如去除标点符号的更机械的预处理步骤,必须为每个目标函数和每个 NLP 问题训练单词嵌入。例如,虽然“快乐”和“悲伤”在大多数上下文中可能使用相似,并且都是情绪,但在情感分析的上下文中,这些词的使用非常不同。因此,使用预先训练的模型可能不会很好地工作。

ELMO 来了

今年早些时候推出的 ELMO 使用语言模型方法来解决缺乏可训练性和看不见的单词。

与其他嵌入不同,ELMO 使用基于字符的模型,这意味着不是给它一个单词的热编码,而是给它一个字符的热编码。这意味着它能够处理没有出现在其训练语料库中的单词的表示,从而通过编码其词根和前缀的语义来处理拼写错误的单词或未见过的单词(类似于 GRE 或 SAT 的方式!).如果你有兴趣了解更多关于 ELMO 的信息,请看这篇文章。

ELMO 由多双向 LSTM (biLM)组成,它还在每一层(而不仅仅是最后一层)暴露其输出和隐藏状态,从而允许科学家了解特定 NLP 问题所需的 LSTM 每一层的权重。例如,与更抽象的理解有关的问题,如句子摘要,可能会受益于比第一层嵌入更多地加权 ELMO 的最后几层。

所以,下次你听到有人说,“哦,我就用 Word2Vec 吧,”让他们想想 ELMO、Sense2Vec 和其他单词嵌入方法,以找出哪种方法最适合你的问题和数据集,并针对你自己的特定数据进一步训练嵌入。

如果你对这篇文章有任何编辑或评论,请通过 yp913@nyu.edu 联系我。爱说话:)

参考资料:

Sense2Vec 论文

介绍性单词嵌入博客

更多关于语言学+多义词的资源

加深对网络英语的理解(上)——CNN

原文:https://towardsdatascience.com/a-deeper-understanding-of-nnets-part-1-cnns-263a6e3ac61?source=collection_archive---------0-----------------------

介绍

深度学习和人工智能是 2016 年的热门词汇;到了 2017 年底,它们变得更加频繁,也更加混乱。所以让我们试着一次理解一件事。我们将研究深度学习的核心,即神经网络(NNets)。Nets 的大多数变体很难理解,底层架构组件使它们听起来(理论上)和看起来(图形上)都一样。

感谢阿西莫夫研究所的 Fjodor van Veen,我们有了最流行的 NNet 架构变体的公平代表。请参考他的博客。为了提高我们对网络的理解,我们将每周学习和实现一个架构。以下是我们将在未来几周讨论的架构。

第一周

本周的架构是卷积神经网络或 CNN 。但是在开始 CNN 之前,我们将首先对感知器进行一次小小的深入探究。NNet 是称为感知器的几个单元/单元的集合,感知器是二元线性分类器。让我们快速看一下,以了解相同的内容。

输入x1x2乘以各自的权重 w1 和 w2,并使用函数f求和,因此得到f = x1*w1 + x2*w2 + b(偏置项,可选添加)。这个函数f可以是任何其他的运算,但是对于感知器来说,它通常是求和。该功能f随后通过允许所需分类的激活进行评估。Sigmoid 函数是用于二元分类的最常见的激活函数。关于感知机的更多细节,我推荐这篇文章。

现在,如果我们堆叠多个输入,并使用函数f将它们与堆叠在另一层中的多个单元连接,这形成了多个完全连接的感知机,来自这些单元(隐藏层)的输出成为最终单元的输入,最终单元再次使用函数f和激活来导出最终分类。如下图所示,这是最简单的神经网络。

由于被称为“通用近似函数的 nnet 的独特能力,nnet 的拓扑或架构变体是多样的。这本身就是一个巨大的话题,最好由迈克尔·尼尔森在这里讲述。读完这篇文章后,我们可以相信这样一个事实:无论多么复杂,NNet 都可以表现为任何函数。上述网络也被称为前馈神经网络或 FFNN,因为信息流是单向的而不是循环的。现在我们知道了感知器和 FFNN 的基础知识,我们可以想象数百个输入连接到几个这样的隐藏层,会形成一个复杂的网络,流行称为深度神经网络或深度前馈网络。

深度神经网络和 CNN 到底有什么不同?让我们找出答案。

CNN 通过像 ImageNet 这样的竞赛而变得流行,最近它们也被用于自然语言处理和语音识别。要记住的一个关键点是,许多其他变体,如 RNN、LSTM、GRU 等,都是基于与 CNN 相似的架构,但在架构上有所不同。我们将在后面详细讨论这些差异。

使用 3 种类型的层来形成 CNN,即“卷积”、“汇集”和“密集或完全连接”。我们之前的网络是“密集”层网络的典型示例,因为所有层都是完全连接的。要了解更多关于需要切换到卷积和池层的信息,请阅读 Andrej Karpathy 的精彩讲解这里。继续我们对层的讨论,让我们看看卷积层。

(对于下面的讨论,我们将使用图像分类作为理解 CNN 的任务,稍后转移到 NLP 和视频任务)

卷积层:考虑一个 5X5 像素的图像,有1 as whiteo as black,这个图像被识别为一个 5X5 尺寸的单色图像。现在想象一个具有随机1s and 0s的 3×3 矩阵,这个矩阵被允许与图像子集进行矩阵乘法,这个乘法被记录在一个新的矩阵中,因为我们的 3×3 矩阵在每次迭代中移动一个像素。下面是这一过程的视觉效果。

上面考虑的 3X3 矩阵被称为“滤波器,它的任务是从图像中提取特征,它通过使用“优化算法来决定 3X3 矩阵中的特定1s and 0s。我们允许几个这样的过滤器在一个神经网络的卷积层中提取几个特征。3×3 矩阵的单个步骤被称为“步距**

下面提供了使用两个 3 通道滤波器产生两个卷积输出的 3 通道(RGB)图像的详细视图。感谢安德烈·卡帕西!

这些滤波器W0 and W1是“卷积”,output是提取的特征,由所有这些滤波器组成的层是卷积层。

池层:该层用于使用不同的函数降低输入的维度。一般来说,卷积层之后经常使用" MAX Pooling "层。池化使用 2X2 矩阵,并以与卷积层相同的方式对图像进行操作,但这一次它缩小了图像本身。以下是使用“最大池化或“平均池化”来池化图像的两种方法

密集层:该层是激活层和前一层之间的完全连接层。这类似于我们之前讨论的简单的“神经网络”。

注意:归一化层也用在 CNN 架构中,但它们将单独讨论。此外,池层不是首选,因为它会导致信息丢失。通常的做法是在卷积层中使用更大的步幅。

ILSVRC 2014 年的亚军 VGGNet ,是一个受欢迎的 CNN,它通过使用 16 层网络而不是 ILSVRC 2012 年获奖者 AlexNet 的 8 层网络,帮助世界了解网络深度的重要性。一个即插即用模型“VGG-16”可在 keras 中使用,我们将使用相同的来查看一个获奖的 CNN 架构。

Keras 中加载模型后,我们可以看到每一层的输出形状以了解张量维度,以及 Param # 以查看如何计算参数以获得卷积特征。" Param # "是所有特征的每个回旋特征的总权重更新。

现在,我们已经熟悉了 CNN 的架构,了解了它的层次和工作原理,我们可以进一步了解它在 NLP 和视频处理中的应用。这将在下周的文章中讨论,同时介绍 RNNs 以及 CNN 和 RNNs 之间的主要区别。同时,免费阅读自 2012 年以来赢得 ImageNet 竞赛的所有 CNN 模特,此处,感谢 Adit Deshpande!

未来的工作

  • 一旦我们讨论了所有的架构,我们将遵循相同的顺序,并使用 jupyter 笔记本来实现它们。一旦我们完成实施,所有的代码链接都将可用。

更新者上的类似帖子

  • 合成成分
  • 阿达德尔塔
  • 阿达格拉德
  • 亚当
  • 涅斯特罗夫
  • RMSPROP
  • 签名于
  • 共轭梯度
  • 黑森自由报
  • LBFGS
  • 线梯度下降

类似开机自检激活功能

  • ELU
  • 硬乙状结肠
  • 哈尔坦
  • 身份
  • LEAKYRELU
  • 理性坦
  • RELU
  • RRELU
  • 乙状结肠的
  • SOFTMAX
  • SOFTPLUS
  • 软设计
  • 双曲正切

感谢您的阅读,希望有所帮助

数据科学入门指南

原文:https://towardsdatascience.com/a-definitive-guide-to-the-world-within-data-science-90300bf6330?source=collection_archive---------3-----------------------

目标

这篇文章旨在探讨构成数据科学的主要概念和重点。对于每一个概念,我希望有效地传达一个的一般定义,以及对其在该领域所扮演角色的充分的解释。以下列表反映了我将涉及的相关子主题:

  • 统计数据
  • 线性代数
  • 编程
  • 机器学习
  • 数据挖掘
  • 数据可视化

统计数字

什么事?

《商业词典》将统计学定义为“数学的一个分支,涉及对数字事实的收集、分类、分析和解释,以便根据其可量化的可能性进行推断”。或者更简单的说,统计学就是收集数字,看数字,从数字中得出结论。

数据科学中的意义

统计学在数据科学实践中有多种发挥作用的方式。这些实践对于解释数据和产生有趣的结果非常有帮助。

实验设计:如果你有一个问题,并且想要得到答案,不管你是否知道,你很可能会进行某种实验来寻找答案。这包括建立实验,处理样本大小,控制组,等等。

频繁统计:使用统计实践,如置信区间和假设检验,可以让你确定一个结果或数据点有多重要。能够从数据中计算重要性和其他重要信息将使你成为更强的数据科学家。

建模:回归和聚类等技术经常在数据科学中用于建模工作。无论你是想预测什么,在数据中找到更大的图景,还是理解数据背后的推理;有可能你最终会使用某种预测模型。

有多重要?

这是事情变得有点模糊和意见开始变化的地方。为了更准确地回答这个问题,我建议我们将统计数据分成两组:新的和旧的

回归和假设检验等旧的统计方法本质上是简单化的。虽然它们很有用,但许多杰出的数据科学家预测它们会越来越少被使用。说明随着我们的前进和统计技术的发展,这些概念可能会变得不那么重要。另一方面,像决策树和预测能力这样的新统计数据非常有用,并且经常被数据科学家使用。

话虽如此,我仍然建议有抱负的数据科学家通过一般的统计理论和实践来工作。即使你不会在日常工作中使用它们,它们仍然非常有助于帮助你进步到更高级的概念,你将在训练分析思维时经常使用它们。

资源

数据科学和统计学有什么区别? : 关于这两个领域区别的精彩解释。

数据科学与统计 : 又一篇关于类似问题的伟大文章。

数据科学家使用统计数据的 7 种方式 : 更详细地介绍了实施目的。

线性代数

什么事?

我个人觉得维基百科的定义是最有帮助的:线性代数是关于向量空间和这种空间之间的线性映射的数学分支。这是一个很好的开始,但是我相信我们可以简化这个定义,让它不那么像教科书。

简单来说,线性代数就是处理空间中直线东西的数学。

数据科学中的意义

以下是当今数据科学中线性代数的一些比较突出的用例:

机器学习:大量的机器学习策略与线性代数的各个方面联系在一起。仅举几个例子,有主成分分析、特征值和回归。当您开始处理高维数据时尤其如此,因为它们往往会包含矩阵。

建模:如果你想以任何方式对行为进行建模,你可能会发现自己在这样做之前需要使用一个矩阵来将样本分成子组,以便建立准确的结果。这个法案要求你使用一般的矩阵数学,包括求逆、求导等等。

优化:了解各种版本的最小二乘法对任何数据科学家都非常有用。可用于降维、聚类等。所有这些都在优化网络或投影中发挥作用。

你们中的一些人可能已经意识到矩阵和矩阵这两个词的重复,这不是巧合。矩阵是一般线性代数理论的一大部分。矩阵上使用的这些概念在表和数据框上同样有效,这是数据科学中使用的两种基本结构。

资源

线性代数维基百科页面 : 适合所有教科书式的东西。

线性代数有什么意义?:Quora 上的大线程,特别注意山姆·利希滕斯坦和丹·皮波尼的前两个回答。

一个好的数据科学家应该掌握线性代数的哪些概念? : 另一个优质 Quora 线程,姜黎黎的第一个回答特别有见地。

面向数据科学家的线性代数: 如果你正在寻找一个可以快速浏览基础知识的地方。

编程;编排

有多重要?

如果你计划从事数据科学的职业,你将需要学习如何编码,并且很好地编码。这就是为什么这么多数据科学家有计算机科学背景的原因;这是个很大的优势。然而,如果你不够幸运,没有一些编程经验,那么不要担心,像生活中的大多数事情一样,它可以自学

什么时候最重要?

我们已经确定,无论你在哪个领域,编程能力都是数据科学家的一项基本技能。尽管如此,通用脚本或命令并不是数据科学中编程真正繁荣的地方。通过编写自动化任务的程序,你不仅节省了以后的宝贵时间,还使你的代码更容易调试、理解和维护。

一般来说,如果你不得不做一件事两次以上,你应该写一个脚本或程序来自动化它。

我应该知道些什么?

让我们转到数据科学中与编程相关的一些关键技能。请记住,下面的列表更侧重于实践技能而不是具体实践(例如,时间管理技能,而不是右外连接)。

开发:如今,许多数据科学家被称为“软件开发人员”,尽管他们执行的任务与数据科学中的任务非常相似。当从事大型商业项目时,熟悉软件开发实践的数据科学家通常比学者更自在。

数据库:数据科学家在不断地使用数据库。为了有效地工作,你需要有这方面的经验。随着面向 NoSQL 和云的数据库的增长,传统的 SQL 数据库急剧下降。然而,雇主仍然希望你对 SQL 命令和数据库设计实践有基本的了解。

协作:协作是软件的关键。毫无疑问,你对这句古老的谚语很熟悉,“一个团队的好坏取决于它最薄弱的环节”。尽管这是老生常谈,但这也适用于任何数据科学团队。你的大部分工作将在小组中完成,因此你需要在与你的团队沟通以及维护关系方面得到提升,以最大限度地提高生产率。

重要实践

如果你问任何软件开发人员或数据科学家,在工作场所编程最重要的方面是什么,他们肯定会用一个词,三个音节的答案来回答:维护。在工作场所,简单、可维护的代码几乎总是胜过复杂的 genius 代码。如果其他程序员不能理解你的代码是否足够好来扩展和维护它,那么你的代码最终是无关紧要的。有几种方法可以轻松提高代码的可维护性。它们如下所示…

不要在代码中使用“硬”值:使用变量和输入,它们本质上是动态的,会随着时间的推移而变化,而不是输入任何静态值。代码中的这个小变化将使您的工作更加轻松。

坚持不懈地记录和注释你的代码:让你的代码更容易理解的最有效的方法就是疯狂地注释。通过用简洁和信息丰富的轶事进行评论,你将会省去向你的同事解释你自己的无尽转换。

重构你的代码:记住,一旦你提交了一段代码,它不会就此结束。不断回顾你过去的工作,寻找优化它的方法,让它更有效率。

资源

数据科学家的软件开发技能 : 这是对编程实践的重要软技能的极好概述。

所谓数据科学家的 5 个维度 : 有趣的是,数据科学家可以扮演不同的角色。密切关注“编程专家”和“数据库专家”。

成为一名数据科学家所需的 9 项必备技能 : 这篇短文的“技术技能”部分提供了很好的信息。

机器学习

什么事?

首先,机器学习是更广阔的人工智能领域的一部分。人工智能是约翰·麦卡锡在 1956 年创造的一个术语,最初定义为“制造智能机器的科学和工程”。在这个领域中,随着时间的推移,机器学习变得越来越重要。

机器学习允许我们教会计算机如何给自己编程,这样我们就不必为某些任务编写明确的指令。

两种类型

机器学习可以分解成两种学习形式:有监督的和无监督的

监督学习:今天大多数实用的机器学习都是使用监督学习来完成的。监督学习是算法从数据中学习的过程,产生预期的结果,然后由用户进行纠正,以便算法在下次运行时提高准确性。因此,通俗地说,把计算机算法想象成学生,把你想象成老师,在需要的时候纠正它,并把它引向正确的方向。

无监督学习:虽然这种类型的机器学习目前还没有多少实际用途,但它可以说是更有趣的分支。无监督学习是让算法自己去发现和识别数据中的潜在结构。

数据科学中的意义

机器学习无疑是当今科技领域的一件大事。托尼·泰瑟和约翰·汉尼斯已经分别称之为。比尔·盖茨在这个话题上也被引用过,他说“机器学习上的一个突破抵得上十个微软”。

随着自动驾驶汽车、图像分类和语音识别等著名应用的出现,人们可以很容易地看出所有关于机器学习的宣传是什么。这个领域正在迅速发展,所以现在就跟上潮流吧,否则就会被甩在后面。

资源

什么是机器学习?:Quora 上的好帖子,有几个略有不同的答案,旨在定义机器学习。

机器学习简史 : 再深入一点看看机器学习的历史。

有监督和无监督的机器学习算法 : 对机器学习算法类型的清晰、简明的解释。

机器学习的可视化 : 轻松搞定我最喜欢的资源这件事。出色的可视化,带你了解机器学习是如何使用的。

数据挖掘

是什么?

如果你已经仔细阅读了大量的在线数据科学资源,那么你可能已经见过“数据挖掘”这个术语了。但是这种做法到底是由什么组成的呢?看了各种资料后,我觉得最好这样描述:

数据挖掘是探索数据以提取重要信息的过程。

词汇表

根据我的经验,我遇到了数据挖掘中的许多其他主题,我认为了解这些主题会有所帮助。下面你会发现一个快速简单的数据挖掘俚语定义列表。请记住,区分它们可能会很棘手,因为它们都非常相似。

数据争论:这是将数据从原始形式转换成更有用形式的行为。它通常由几个重要步骤组成,包括清理和解析成预定义的结构。

数据争吵:与上面显示的“数据争吵”完全一样。为什么我们需要两个术语来描述这个过程,我可能永远也不知道…

数据清洗:这是一个关键的步骤,包括从数据集中检测并纠正(或删除)损坏的、不准确的或缺失的值。

数据抓取:一种计算机程序读入来自另一个程序或网站(如 Twitter )的数据的技术。

数据科学中的意义

每个人都想做出令人敬畏的预测模型,并把令人瞠目结舌的可视化。然而,人们经常忽略的是,在你完成“看门人”的工作之前,这些事情都不会发生。纽约时报最近的一篇文章(将发布在参考资料中)发现数据科学家花费大约 50%-80%的时间来收集和准备数据。

这一严酷的现实需要传达给未来的数据科学家。在丰厚的基本工资和 21 世纪最性感工作的头衔之间,年轻的专业人士在不了解职业现实的情况下盯上了数据科学家的工作。

资源

什么是数据挖掘?:Quora 上一个关于数据挖掘各种定义的好线程。

什么是数据角力? : 简短阐述一下数据角力到底是由什么组成的。

“看门人的工作”是洞察的关键障碍 : 这篇有趣的文章详细介绍了数据挖掘实践在数据科学领域的重要性。

数据可视化

什么事?

数据可视化似乎比其他主题更容易理解。然而,我想你会意识到数据可视化并不像看上去那么简单。让我们从定义我们的主题开始,尽管这看起来有些多余。

数据可视化是通过某种图片或图表传达数据或结果的行为。

一个常见的误解是,视觉化最重要的部分是它看起来有多吸引人。虽然这非常重要,但这不是我们想要表达的意思。最终,我们的目标是以大脑最容易理解的方式交流你在数据中发现的见解。根据 NeoMam Studios 的报道,研究人员发现,彩色视觉效果可以增加读者 80%的阅读意愿

常见类型

现在让我们来看看一些常见的可视化类型。请记住,这绝不是一份详尽的清单。相反,它只是我个人在有生之年遇到的一些最常见的二维可视化。所以给你:

多维:这些是处理多个变量的图形和图表。这是你将会看到的最常见的视觉化形式。一些例子包括:饼图、直方图和散点图。

时间驱动:所有这些可视化都使用时间作为有效交流数据的基线。这些都是在一段时间内传达变革的有力工具。一些例子包括:时间序列、甘特图和弧形图。

地理空间:正如人们可能猜测的那样,地理空间可视化都与位置有关。这些通常用于传达对特定领域或地区的见解。一些例子包括:点分布图、比例符号图和等高线图。

关键要素

所有伟大的数据可视化都有一些共同的关键元素。下面你会发现一个我认为最重要的清单。

信息:这涉及到拥有准确一致的信息。如果数据不可靠,你的最终产品是什么并不重要。

你的视觉化应该有意义。它应该是以这样或那样的方式与一个项目或社会相关的东西。如果没人愿意看,制作一个视频还有什么意义呢?

功能:无论你在传达的信息多么详尽,你的工作就是让它简洁易懂。将您的数据转换成对不一定是技术背景的人有用的形式的能力将被证明是非常重要的。在职场上尤其如此。

吸引力:最后,你的形象需要总体上好看。它应该吸引人,并且赏心悦目。为了做到这一点,你将不得不考虑诸如平衡、颜色、稠度和尺寸等诸多因素。

数据科学中的重要性

无论你想专注于哪个领域,数据可视化技能对数据科学家来说都非常有用。能够通过图像而不是文字有效地传达你的数据,会让你的信息更容易理解,反过来,会让你有更大的机会影响你的工作。

资源

什么是好的数据可视化 : 优秀的维恩图解释了优秀的数据可视化的组成部分。上面提到了一些,但是我仍然强烈建议你看一看。

杜克可视化简介 : 贯穿杜克大学图书馆所见的所有数据可视化类型。

数据可视化 Quora 线程 : 关于数据可视化通用话题的一些好问题供进一步阅读。

把它包起来

现在你可能已经意识到了,数据科学是一个复杂的领域,由各种独特的子主题组成。对于一名有抱负的数据科学家来说,更清楚地理解这些子主题是朝着正确方向迈出的重要一步。

感谢阅读!如果你喜欢这篇文章,请继续向鼓掌按钮展示你的爱。对更多的帖子感兴趣吗?请务必关注我并订阅下面的我的简讯以接收任何新内容。想了解更多关于我和我在做什么,请查看我的网站。

一种不同的(深度)学习:第 1 部分

原文:https://towardsdatascience.com/a-different-kind-of-deep-learning-part-1-90fe6c52f1ab?source=collection_archive---------6-----------------------

自我监督学习导论

深度学习真正重新洗牌了机器学习领域的东西,特别是在图像识别任务中。2012 年,Alex-net 发起了一场解决(或至少显著改善)计算机视觉任务的竞赛(仍远未结束)。虽然主要思想相当稳定(对所有事情都使用深度神经网络),但研究人员采取了非常不同的途径:

  • 尝试优化模型架构
  • 尝试优化训练计划,例如优化者自己。
  • 尝试优化数据,例如它的顺序、大小、多样性等等。

这些研究路径中的每一条都提高了训练质量(速度、准确性,有时还有泛化能力),但似乎做更多同样的事情可能会导致一些逐渐的改进,但不会有重大突破。

另一方面,深度学习领域越来越多的工作表明,当前的方法存在重大缺陷,特别是在泛化方面,例如最近的这个对象旋转时的泛化失败:

因此,似乎有必要进行更积极的改进。或者把研究范围扩大到更冒险的想法。

除了上述方法,还有一些方向试图改变学习范式。可能是:

  • 镜头学习
  • 半监督学习
  • 领域适应
  • 自我监督学习

这些方法采用一些不同的训练范式,试图更具创造性,或者模仿一些类似人类的模式。虽然我们还没有从上述方法(和其他方法)中获得重大突破的证据,但它们确实取得了一些不平凡的结果,也教会了我们许多关于训练过程的知识。

在这篇和接下来的文章中,我将尝试讨论一些最有趣的方法,并将这个系列命名为“不同种类的(深度)学习”。我绝不试图预测深度学习的未来发展,而仅仅是描述最近的有趣作品,这些作品可能不会受到关注。这可以为读者提供几个目的:

  • 你可能有兴趣了解你不知道的作品。
  • 你可能会对自己的工作有新的想法。
  • 你可能会在深度学习中了解到你没有意识到逻辑部分和任务之间的关系。

这个系列的第一部分将是关于自我监督学习,这是我写这个系列的主要动力之一。

自我监督学习

想象一下,你有一个搜索网络的代理,它可以从遇到的每张图片中无缝学习。这个想法非常有趣,因为如果它将被实现,深度学习的最大障碍,即注释数据,将(部分)被移除。

但是怎么做呢?嗯,它首先在 text 中提出:文本由人类很好地组织,因此有许多概念可以在没有任何注释的情况下从中学习。预测下一个/前一个单词是一个突出的例子,如在 单词嵌入语言模型任务中所做的。

视觉中,做这样的技巧有点复杂,因为视觉数据(图像和视频)不是人类明确创建的(嗯,一些摄影师可能在他的摄影中投入了一定的思想),但不是每个视频,并且肯定不是每个图像都有任何类型的逻辑结构可以用来提取信号。

不就是另一种形式的无监督学习吗?的确,但是它有一个特殊的微妙之处:因为任务是被监督的(例如分类),但是没有主动的注释发生。这个话题是我的最爱之一,也迅速成为了本文的主要话题。我不能保证这种特定的范式会给深度学习带来最好的成就,但它肯定已经带来了一些伟大的创造性想法。

如上所述,这种任务的名称是自我监督学习。与“弱注释”不同,弱注释意味着图像具有不同的标签、标题或说明,自监督任务被认为除了图像本身没有注释。如果你问从一张没有标注的图片中能学到什么,敬请期待。

着彩色

也许图像中最直观的信号是它的颜色。当大多数计算机化颜色表示中有 3 个通道时,1 或 2 可以无缝地用作注释。

由于给旧图像着色是一项有趣的任务,因此有许多作品致力于此。然而,如果我们考虑全自动着色(这是自我监督的资格),数量减少到相当少。

这种情况下的着色任务形成为“交叉通道编码器”,这意味着图像中的一个(或一些)通道用于编码其他通道。这个概念将在以后的文章中进一步讨论。

最引人注目的彩色纸是张曦轲和阿列克谢·埃夫罗斯的这张。

解决着色任务的常见方法不是使用标准的 RGB 编码,而是使用 Lab 色彩空间。在 Lab 色彩空间中, L 代表亮度(B & W 强度),用于预测 ab 通道(a —绿色到红色,b —蓝色到黄色)。

Colorization with Lab encoding, from [1]

正如我们将在我们讨论的所有任务中看到的,自我监督学习不像我们在深度学习中习惯的那样简单。有一些工件打断了模型实现它的设计目标。此外,有时如果训练没有被仔细检查,模型会制造出“捷径”,这将阻碍它推广到其他任务。

以下是着色任务的一些挑战:

1。彩色化中固有的模糊性:很明显,对于一些图像来说,有不止一种似乎合理的彩色化。这个问题会在培训和评估中引起多种问题:

在下面的唐纳德·特朗普图片中,窗帘的颜色可能是红色或蓝色(以及许多其他颜色)。唐纳德的领带可以搭配(也可以不搭配)。给定数据集中领带和窗帘的不同示例,模型将倾向于对它们进行平均,将这些项目用灰色着色。

:在张的文章中,研究者将彩色化处理为一个分类问题,而不是回归问题。除了使用特殊的损失函数,他们的模型还预测了一个概率分布层,而不是图像的实际颜色,然后将这些概率转换为颜色-从 Lab space 的 313 种可用颜色中选择:

2。偏向:实验室不是一个均匀分布的空间。由于云、路面等的高频率,大多数解决方案倾向于较低的值。

解决方案:对损失函数进行重新加权来解决这个问题。

3。评估问题:既然模型可以预测不同的正确答案,例如,如果地面实况是蓝色,模型将选择红色,那么在标准评估中它将被认为是错误的。

解决方案:使用不同的评估方法,其中包括:人类后 hok 分类—“彩色化图灵测试”,要求人们区分真实图像和机器彩色图像。此外,将图像输入图像分类器,将结果与真实图像进行比较。

该模型在彩色化图灵测试中获得了 35%的分数,这……还不算太差。

in this image the machine-colored dog looks more real than the original one

在另一篇最近的论文中,Larson 等人与 Zhang 和 Efros(两篇论文都提到对方)同时工作,并使用了空间定位的多层切片(超柱)和回归损失。他们试图通过预测颜色直方图并从中采样来克服模糊问题:

除了使用 LAB 空间之外,这项工作还试图预测色调/色度属性,这与“HSV”颜色空间有关。

语境

除了颜色预测,下一个最明显的(但也是创造性的)任务是从图像结构中学习东西。更准确地说,试图预测一些关于图像裁剪的事情。

这个任务的灵感直接来自于 word2vec ,或许我们可以称之为图像的“跳过克”。

然而,在文本中,字数受限于词汇量的大小,很可能不会超过一百万。而一个像素接一个像素地完成图像补片占用了大得多的空间。你可能会说 GANs 正是这么做的,但是:

  1. 确实有大量的正确解,因此很难一概而论
  2. 我们将在下一部分讨论 gan。

在这种范式中,实际任务不会自然出现:研究人员必须想出模型要解决的“游戏”。会举一些突出的例子:

拼图背景

从图像中提取上下文最简单的方法是使用类似拼图的任务。第一个是由 Doersch 和 Efros 完成的工作:从图像中裁剪小块,并训练模型对它们的关系进行分类。一个例子可以很好地解释这一点:

和着色一样,任务并不简单。具体来说,model 正在寻找“快捷方式”:它可能会学习某些低级特征,如边缘和光照关系,而不是实际学习高级特征及其关系。这倾向于暗示图像部分。

为了解决这个问题,研究人员在补丁上应用了一些抖动(如图所示)

研究人员遇到的另一个问题是通过一些照明伪像预测斑块位置的模型—。这意味着在一些相机中,图像不同部分的颜色分布是不同的。解决方案:这部分是通过一些颜色转换处理的,特别是将绿色和品红色向灰色转移。

下一个突出的成果是诺鲁齐和法瓦罗的这篇论文,它一路走来,使用了一个更难的问题,解决了完整的 9 部分拼图,但作为回报,它获得了更强的性能:

研究人员验证了片的良好混排和每幅图像多于 1 个混排样本。

上下文编码器

如前所述,text 中的 word2vec 会填充缺失的单词。在视觉上有没有尝试这样做?事实上,有。在这篇文章中,Pathak 等人(当然还有 Efros)尝试了一些自动编码器模型来填充图像上的裁剪空间。

结果表明,这实际上是可能的,特别是增加了对抗性损失,这成功地避免了处理多模式(如前所述),从而防止模糊,“平均”的结果。

旋转

在我们跳到下一个级别之前,我想提一下这个花絮:旋转预测。这篇论文采用了预测图像旋转的创造性方法。

旋转预测除了具有创造性之外,还相对较快,并且不需要像我们之前看到的其他任务那样进行任何预处理,以克服对琐碎特征的学习。

论文还探讨了一些“注意力地图”,显示出他们的网络聚焦于图像的重要部分:头部、眼睛等。

虽然将迁移学习的最新成果报告给了 imageNet 分类(大多数其他作品都与 pascal 相关),但评论者在论文中发现了一些缺陷,因此不得不持保留态度。

一般化

那么在所有这些工作之后,我们从中获得了什么呢?当然,给 B&W 图像着色很好,解决拼图可能是一个有趣的演示应用程序,但更大的目标是在主要任务中取得更好的结果——特别是分类检测分割

当使用 imagenet 预训练时,最常见的基准是 VOC Pascal 数据集,具有当前的技术水平:

目前的结果是:

Detection results, from rotation article

嗯,看来我们还没到那一步。虽然自我监督的数据实际上是无限的,但还没有一项工作挑战“经典的”基于 Imagenet 的迁移学习结果。然而,在具体任务上有一些好的结果,我们将在后面的帖子中讨论。

除了对上述任务的标准概括,研究人员还利用这组任务的具体特征来尝试和概括其他一些任务,如图像聚类(最近邻、可视化数据挖掘等)

包裹

下一个大的进步会来自于自我监督学习吗?也许是,也许不是,但我相信探索这样不同的方法会显著改善深度学习领域,并可能间接积极影响真正的突破。在下一篇文章中,我们将了解更多的想法和方法,这些想法和方法会带来一些有趣和新奇的结果。

如果您希望进一步阅读,请继续关注(并跟随我)本系列的下一部分。此外,以下是一些对我研究和学习这些主题有很大帮助的资源:

  1. 阿列克谢·埃夫罗斯发表的演讲,他是该领域的杰出研究人员之一(也是这里讨论的大多数论文的合著者)。他在这里谈的非常值得推荐。
  2. 一个伟大的甲板总结了在这一领域所做的工作。

系列链接:

  • 自我监督学习介绍(这篇文章)
  • 自我监督学习:生成方法

一种不同的(深度)学习:第 2 部分

原文:https://towardsdatascience.com/a-different-kind-of-deep-learning-part-2-b447ff469255?source=collection_archive---------20-----------------------

自我监督学习:生成方法

介绍

在之前的帖子中,我们已经讨论了一些自我监督学习文章,以及一些朝着“圣杯”努力的尝试:利用几乎无限数量的无注释图像,以推广到其他任务。希望能更接近目前未达到的基准 ImageNet 预培训。

令人惊讶的是,或者也许不那么令人惊讶的是,我们从阎乐存那里获得了一些额外的支持,他在他的 NeurIPS 演讲(“迈向人工智能的下一步”)中花了几分钟时间讨论自我监督学习。他将自我监督学习描述为“蛋糕的主体”当浇头是监督学习,樱桃是强化学习(因为 RL 中奖励的稀疏性)。Lecun 还从我们最喜欢的自我监督研究员 Aloysha Efros 那里拿了一些幻灯片,所以我很高兴我们有共同的兴趣。

此外,一些读者指出,也有突出的自我监督机构处理视频,这是显而易见的。然而,视频将在稍后的帖子中讨论,因为我们有另一个主题,即生成模型

生成模型和自我监督有什么关系

在他关于自我监督的谈话中,Efros(是的,他也将在这篇文章中占主导地位)经常讨论为自我监督的任务找到正确的损失函数的困难。

在前一篇文章中,我们检查了用于着色任务的特殊分类损失,并强调了为它们找到正确损失函数的难度。

在的演讲中, Efros 描述了一种寻找这种损失函数的方法。他称之为:“研究生血统”。换句话说,为这些模型找到一个好的损失函数需要大量的反复试验。那么我们能有更好的,更通用的方法来找到它们吗?

colorization, super resolution, etc: is there a universal self supervised loss function?

此外,还有彩色图灵测试的事情:为了评估结果,研究人员使用机械土耳其人来区分真假照片。因此,我们希望有某种机制来区分这两种类型的图像。

如果您在 2014 年就热衷于深度学习,您可能还记得,当伊恩·古德费勒(Ian Goodfellow)首次展示他开创性的作品《T0》、《T1》、《T2》、《T3》时,社区对这种有希望的代际能力非常兴奋,但许多研究人员对这项工作的目的持怀疑态度。对他们来说,这只是一个玩具,至少在取得重大进展之前是这样。

自我监督的研究人员有一些不同的想法:在他们看来,GAN 可能是自我监督任务的一种定制丢失功能

This is how Generative Adversarial network works

让我们想一想:在着色工作中,我们使用了标准的深度学习范式来预测每个像素的颜色。我们可以将 GAN 鉴频器的能力用作定制损耗吗?如果是这样,就需要用不同的方式来构造问题。

我们知道,氮化镓本质上是从一个完全随机的分布产生图像。如果我们可以让它给定一个黑白图像,生成一个彩色图像,使用鉴别器来评估结果呢?

这需要范式上的一些改变:从不同的东西生成图像,然后通过条件 GAN 完成完全随机的分布:向生成器添加一个特征,使其生成目标空间的一些子集。例如,来自 Mnist 数据集的特定数字。但是如果我们可以使用标量(数字)作为“条件”,我们也可以使用向量。如果我们可以用一个向量,我们也可以用一个张量。图像只是一个张量,不是吗?

因此,我们的想法是:训练一个类似条件 GAN 的网络,其中条件(以及生成器的输入)是黑白图像,这将限制输出为彩色图像。

Pix2pix

菲利普·伊索拉(Phillip Isola)是 Efros 的学生,也参与了之前讨论的彩色化工作,他在论文“中承担了这项任务,论文名为 Pix2pix 。这需要对 GAN 架构进行重大调整:首先为生成器使用编码器-解码器架构。第二,鉴别器不能只从数据集和生成器中获得随机配对的图像。它应该有严格的图像对,一个是原始的 RGB,另一个是由黑白图像生成的。鉴别器架构和训练时间表也不同于标准。你可以在这个帖子中读到关于它的很好的解释。很明显,这份文件投入了大量的辛勤工作。

The pairing strategy of pix2pix. Here with edges=>photo instead of B&W=>RGB

但伊索拉更进一步:他可能对自己说:好吧,如果我成功地建立了一个彩色化-GAN,它从成对的图像中学习,为什么我不能将其应用于不同的图像对?关于:

  • 谷歌地图和谷歌地球图像对
  • 建筑抄本和实际建筑立面
  • 边缘和对象

诸如此类。一切都成功了。

这成为了过去几年中最有趣的深度学习作品之一(这意味着有史以来),它引发了 Efros 所谓的东西:“ Twitter 驱动的研究”。由于这篇论文的代码在 GitHub 上很容易获得,许多人在各种图像配对上训练它,并得出一些高度 创造性的结果。这些也是:

你也可以通过在 twitter 上寻找 #pix2pix 找到更多。埃夫罗斯说,这些项目让他感到惊讶,带来了许多新的想法,并使他们的研究前进了许多步。

好吧,我们有点忘乎所以了——所有这些令人兴奋的事情带来了各种新的选择。然而,在通往创新的道路上,一个小细节被忽略了:自我监督的范式,它旨在使用自我监督的模型进行迁移学习,在这个过程中被忽略了,甚至在本文中也没有提到。也许发生器的结构太不一样,无法尝试,或者也许生成结果的重要性掩盖了又一次部分成功的自我监督尝试的潜力。

甘比

嗯,pix2pix 作品是第一篇文章中着色背景作品的“自然继承者”。但还有另一项工作确实尝试在 GAN 网络上应用迁移学习:双向 GAN—

甘比提出了一个新概念(当时,2016 年):除了标准的 GAN 架构,一个编码器被添加到该架构中(见下文)。出于不同的目的,该编码器用于学习发生器的逆过程。

这项工作采用了一种非常有趣的方法:采用标准的 GAN 架构,而不是为鉴频器提供 x (真实图像)和 G(z) (生成的图像,当 z 是发生器的随机输入时)鉴频器馈入 2 对: (x,E(x))、( G(z)、z) ,这意味着随机输入 z 有趣的是,生成器和编码器之间没有共享知识。

这有点难以理解,所以您可以在文章中阅读更多的细节——关于编码器和生成器的正式(和直观的)解释必须学会相互反转以欺骗鉴别器。

虽然这里没有条件元素— z 不是标签,但是编码器可以通过迁移学习用于分类(以及因此的检测和分割,在切换一些层之后)。结果可以说是“合理的”。

如果你觉得类似的想法出现在甘比和 Pix2Pix 作品中(我应该提到甘比更早出现)这不是偶然的。pix2pix 的后续论文 CycleGAN 是两者的结合,允许在没有“成对”训练图像的情况下训练这样的网络,并显著扩展了可转移的对象,创造了著名的斑马到马(和背)的转移。

some results from CycleGAN

交叉通道编码器

因此,我们已经看到 GANs 在自我监督学习中有巨大的潜力(不知何故还有待实现)。但是他们更老的、目前不太受欢迎的同类产品自动编码器怎么样呢?

事实上,自动编码器在某些任务上已经取得了很好的结果,但是它们总是遭受通过它们的层的信息丢失。

在自我监督学习中,他们也取得了一些成功。

在我们之前的文章中关于彩色化的讨论中,我们提到了彩色化实际上是一个跨通道编码器。意思是,用一些渠道去预测其他的。如果我们给真正的自动编码器一个机会,用不同的方式定义通道,会怎么样?

更具体地说,通过试图用另一半来重建图像的一半。接下来的工作,名为“裂脑”正是这么做的。它定义的任务是对角地将图像一分为二,并使用自动编码器预测一半,使用另一半。

更进一步,每个图像可以使用两次,每一半用于预测另一半。

看到这种方法对对角线平分法相当有效,研究人员又回到了颜色,来回预测:B&W 预测 RBG,反之亦然,颜色预测黑白(特别使用实验室空间)

总结和评估

根据之前的帖子,我有一些关于自我监督模型的实际迁移学习结果的问题。如那里所说,重要的特征是对不同任务的概括,例如检测和分割。有意地,我没有把太多的重点放在这些结果上,因为它们相当脆弱,并且总是保持与它们的目标 10%的相当稳定的差异:ImageNet 预训练。

上面的表格摘自轮换的作品,这可能是令人惊讶的自我监督迁移学习的当前“艺术状态”。大多数其他讨论过的论文也在那里。然而,这应该有所保留,因为:

  • 审稿人对轮换论文的评价不高
  • 这些论文中有一些数据展示技巧,使它们在发表时看起来领先,但在现实生活中并不真正有用。

因此,再一次,它似乎有很大的潜力,特别是在客户损失函数的想法,但结果还没有“在那里”。然而,我们仍然有一些理由保持乐观:幸运的是,视觉信号不仅限于图像,也存在于…视频中。视频增加了重要的时间维度,这反过来又增加了大量新的可能的任务、范例和选项,最终,一些真实的结果(!).这一点和更多将在下一篇文章中讨论,敬请关注。

一如既往,我欢迎反馈和建设性的批评。可以通过 Twitter @shgidi 联系到我

系列链接:

  • 自我监督学习简介
  • 自我监督学习:生成方法(本帖)
  • 通过视频进行自我监督学习(未来帖子)

识别季节性客户的时间序列的不同用法

原文:https://towardsdatascience.com/a-different-use-of-time-series-to-identify-seasonal-customers-8806f2a626b?source=collection_archive---------12-----------------------

我以前写过关于创造性地利用你的数据,使用细分来了解客户群。文章此处。在文章中,我提到了利用任何可能相关的数据。尝试识别具有季节性使用模式的客户是我提到的听起来很有趣的变量之一。由于我准备做另一个聚类分析,我决定解决这个问题。

这些是我最喜欢的数据科学问题类型。设计解决方案需要你跳出框框思考。基本上,我希望能够标记每个客户,无论他们是否表现出季节性模式,这将是第一步。稍后,我可能会进一步扩展这一点,以确定每个客户的“淡季”的开始。这将使我们能够更好地培养这些客户关系,并提供更加个性化的体验。

我是 Constant Contact 的数据科学家,我们为小型企业提供电子邮件营销解决方案。由于这是一个订阅产品,客户有不同的使用模式,我可以使用这些模式进行分析。

起初,我的假设是这些顾客中有很大一部分可能生活在一个有四个季节的地区。你知道,新英格兰的冰淇淋店冬天关门。经过进一步思考,如果我在寻找季节性的使用模式,这也将包括那些不一定受天气影响的季节性商业模式的人。在教育领域有账户的人会在暑假休假,这是季节性的。零售业全年都有相当稳定的使用量,但在圣诞节增加使用量的企业也呈现出季节性模式。因此,模型将确定哪些人是季节性的,这不仅仅是基于天气,也可能是基于业务类型。(或者可能有些人足够幸运,在年中无缘无故地随意休长假,我想确保我也能找到这些人,如果他们存在的话)。

为了进行这项分析,我按客户、按月汇总了每个客户至少两年的电子邮件发送模式。每个客户都有自己的时间序列。然而,有几个复杂的问题。有一个细节特别值得注意,客户可能会停止使用一两个月(或更长时间)。所以首先我必须写一些代码来填充这几个月的零。我不能指定我正在寻找一个每年的模式,但是在模型中只给出每年 8 个月的数据,我需要这些零。我使用 Python 找到了这些丢失的零,然后决定我想使用 R 来表示时间序列/确定是否存在季节性模式。我第一次使用 Python 中的 rpy2 包。从我想尝试的新包列表中检查一下。

我为 r 中的每个客户拟合了一个 TBATS 模型。这可能是多余的,因为 TBATS 旨在处理非常复杂(并且可能是多个)的季节性模式。然而,询问模型是否有每年的季节成分真的很简单。另外,TBATS 比其他方法对平稳性更具鲁棒性。

这是一个被模型确定为季节性的客户的图片,右边是一个明显不是季节性的客户,模型也同意这一点。

在我得到我的模型的输出后,我回去对这些客户的样子做了一个全面的分析。他们在东北部指数过高,而在西部和南部指数较低。

季节性用户也更有可能自我报告处于如下行业:

  • 零售
  • 体育和娱乐
  • 非营利组织

非季节性用户也更有可能自我报告处于这样的行业:

  • 汽车服务
  • 财务咨询机构
  • 医疗服务
  • 保险

任期只有 2-3 年的客户比任期更长的客户更不可能是季节性的。这可能是由于几个不同的因素。也许只是还没有足够的数据来检测它们,也许他们在真正达到他们的大步之前需要一段时间来熟悉这个工具(涉及不同的使用模式),或者也许他们真的不是季节性的。有更多的见解,但这是公司的数据😉

这是东北部季节性客户过度指数化的地图。利益相关者通常喜欢看到漂亮的地图。注:季节性和非季节性的比例不是 50/50。

目前,我们正在考虑在即将到来的细分中我们可能能够利用哪些数据(其中这个季节性变量将是一个候选变量。这可能包括来自 BigData 环境的信息或关系数据库中的任何信息。我们也在权衡获得一个特定变量的难度与我们从收集数据中可能获得的附加值。

我感到非常幸运,能够参与帮助我们了解客户的项目,这样当我们向他们传达信息时,我们可以更有针对性。没有什么比收到一个完全不了解你的公司的信息更糟糕的了。我发现这种工作令人兴奋,它让我有创造力,这对我很重要。

我希望你觉得这篇文章很有趣,也许有几个人会发现这也适用于他们自己的工作。我希望你有很多有趣的项目,让你感到鼓舞🙂

如果你想订阅我未来的文章,你可以在这里订阅。

原载于 2018 年 7 月 3 日【datamovesme.com

生物信息学入门

原文:https://towardsdatascience.com/a-dummies-intro-to-bioinformatics-e8212ed7c09b?source=collection_archive---------0-----------------------

Bioinformatics and related fields

单词 生物信息学 在当今的科学世界中正在发生巨大的转变。这个词似乎由两部分组成,这两部分涉及两个不同的领域,生物学计算机科学。大约一、二十年前,人们认为生物学和计算机科学是两个完全不同的领域。一个人将学习生物及其功能,而另一个人将学习计算机和基础理论。

让我们把详细的谈话留到以后。如果你对这个新兴领域毫无头绪,那你来对地方了。在这篇文章中,我将尽可能简单地解释这个领域,不会深入到生物学或计算机科学。

什么是生物信息学?

生物+信息学=生物信息学

根据维基百科,

生物信息学是一个跨学科领域,开发理解生物数据的方法和软件工具。作为一个跨学科的科学领域,生物信息学结合了计算机科学、统计学、数学和工程学来分析和解释生物数据。

随着生物分析中新概念、新理论和新技术的出现,科学家们在进行各种实验后收集了大量的数据。尽管数据量呈指数级增长,但手动分析它们变得不切实际。这是计算机科学技术与统计学、数学和工程学相结合的地方。计算技术被用来更准确和有效地分析这些大量的数据。因此,生物信息学可以被认为是解决生物学问题的数据科学领域。

过去和现在的实验

在生物信息学出现之前,生物实验只有两种方式。

  1. 在一个活的有机体内部( 在体内, 意为 在活的 在拉丁文中)
  2. 在人工环境中( 试管内 ,拉丁文中的意思是 玻璃内 )

In vitro and in vivo experiments (Image Source: http://www.invivotransfection.com)

生物信息学领域在 silico 上被认为是(在 silicon 上的意思是**在拉丁文中的意思是),我们在一个硅片上,或者更准确地说是在一个微处理器上进行生物实验。计算机模拟方法的一个主要优点是,你可以在不使用任何动物或试剂的情况下进行模拟和实验。这将是动物权利活动家的好书。😊**

为什么要学生物信息学?

生物信息学已经成为生命科学和生物医学科学的重要交叉学科。如果你是一名生物学家,你会发现拥有生物信息学的知识可以让你的实验和研究受益匪浅。

目前的就业行业充满了具有生物信息学技能的人的空缺。科学杂志称,主要的制药、生物技术和软件公司正在寻求招聘具有生物信息学经验的专业人员,他们将在这些领域处理大量的生物和医疗保健信息。去 Indeed.com 的看看生物信息学领域的几个工作机会。

除了工作和职业要求,如果你热爱生物和计算机科学,那么这个领域很适合你。作为一个热爱生物学,目前正在学习生物信息学的计算机科学本科生,相信我这样说,你一定会热爱这个领域。

生物信息学会学到什么?

首先,你必须学习一点生物学知识;具体来说就是遗传学和基因组学。这将包括研究基因、DNA、RNA、蛋白质结构等。

然后你将不得不学习生物序列(例如,在 DNA、RNA 和蛋白质中发现的序列)以及发现和分析其中各种模式的技术。你会遇到不同技术使用的各种算法。

因为您将处理大量的数据,所以很好地理解统计是至关重要的,因为您必须根据特定的需求来分析数据。因此,你也会学到很多关于统计学的知识。

当然,你会需要编程技能。r、Python 和 Bash 是最有用、最常用的编程语言。决定从哪个开始取决于你的目标。我选择了 Python。🐍您也可以使用其他语言,如 C/C++和 Java。

在对基本概念有了基本了解之后,你可以继续学习其他领域,如结构生物信息学、** 系统生物学生物网络。**

生物信息学的应用

据科学日报报道,生物信息学正被用于许多不同的方面,包括 DNA 序列基因蛋白质进化建模。我们不会深入讨论这些细节。

生物信息学的一个众所周知的应用是在精准医学预防医学领域。在精准医疗中,针对个体患者的医疗保健技术正在相应地定制,包括治疗和实践。精准医疗不是治疗或治愈疾病,而是开发预防疾病的措施。这些领域的一些重点领域是流感癌症心脏病和糖尿病。人们已经开展了研究来识别病人身上的基因变化,这使得科学家们能够提出更好的治疗方法,甚至可能的预防措施。你可以从这篇由国家癌症研究所撰写的文章中了解更多关于生物信息学在癌症治疗中的作用。

Disease Identification

生物信息学的另一个重要应用是创造药物。我们可以使用计算工具来了解疾病,确定疾病的原因,并相应地使用合适的药物进行治疗,而不仅仅是治疗症状。

这是生物信息学的一些应用。使用生物信息学知识的情况更多,包括微生物学、基因技术和农业。

最后的想法

我开始学习生物信息学已经有几个星期了,我对它非常感兴趣。我读了一些书,想推荐以下几本书。

  1. 假人生物信息学 作者 Cedric Notredame 和 Jean-Michel Claverie
  2. 初学者生物信息学:基因、基因组、分子进化、数据库和分析工具 作者 Supratim Choudhuri
  3. Python 中的生物信息学编程:初学者实用教程 作者鲁迪格-马库斯·弗莱格
  4. 利用 Python 进行生物信息学编程 采用米切尔 l .模型

我认为这些书对初学者来说非常好。读完这些之后,你会对基本概念有一个很好的基础和理解,并且开始编程。

因为我对这个领域还很陌生,所以我想听听你的建议。😇

我希望你对生物信息学有一个基本的了解。

感谢阅读…!😃

Python 中用于机器学习的特征选择工具

原文:https://towardsdatascience.com/a-feature-selection-tool-for-machine-learning-in-python-b64dd23710f0?source=collection_archive---------0-----------------------

使用 FeatureSelector 实现高效的机器学习工作流

特征选择,即在数据集中寻找和选择最有用的特征的过程,是机器学习管道的关键步骤。不必要的特征降低了训练速度,降低了模型的可解释性,最重要的是,降低了测试集的泛化性能。

我发现自己在机器学习问题上一遍又一遍地应用特别的特征选择方法,这让我感到沮丧,于是我用 Python 编写了一个特征选择类,可以在 GitHub 上找到。FeatureSelector包括一些最常见的特征选择方法:

  1. 缺失值百分比高的特征
  2. 共线(高度相关)特征
  3. 在基于树的模型中具有零重要性的特征
  4. 重要性低的特征
  5. 具有单一唯一值的特征

在本文中,我们将在一个示例机器学习数据集上使用FeatureSelector。我们将看到它如何允许我们快速实现这些方法,从而实现更高效的工作流。

完整的代码可以在 GitHub 上获得,我鼓励任何贡献。功能选择器是一项正在进行的工作,并将根据社区需求继续改进!

示例数据集

对于这个例子,我们将使用 Kaggle 上的家庭信用违约风险机器学习竞赛的数据样本。(参赛入门,见本文)。整个数据集可以从下载,这里我们将使用一个示例来说明。

Example data. TARGET is the label for classification

竞争是一个监督分类问题,这是一个很好的数据集,因为它有许多缺失值、许多高度相关(共线)的要素和许多对机器学习模型没有帮助的不相关要素。

创建实例

为了创建一个FeatureSelector类的实例,我们需要传递一个行中有观察值、列中有特性的结构化数据集。我们可以使用一些只有特征的方法,但是基于重要性的方法也需要训练标签。由于我们有一个监督分类任务,我们将使用一组特征和一组标签。

(确保在与feature_selector.py相同的目录下运行此程序)

from feature_selector import FeatureSelector# Features are in train and labels are in train_labels
fs = FeatureSelector(data = train, labels = train_labels)

方法

要素选择器有五种方法来查找要移除的要素。我们可以访问任何已识别的特征,并手动将其从数据中删除,或使用特征选择器中的remove功能。

在这里,我们将介绍每种识别方法,并展示如何同时运行所有 5 种方法。FeatureSelector另外还有几个绘图功能,因为视觉检查数据是机器学习的一个重要组成部分。

缺少值

查找要移除的要素的第一种方法很简单:查找缺失值比例高于指定阈值的要素。下面的调用识别缺失值超过 60%的特征(输出粗体)。

fs.identify_missing(missing_threshold = 0.6)**17 features with greater than 0.60 missing values.**

我们可以看到数据帧中每一列缺失值的比例:

fs.missing_stats.head()

为了查看被识别为要删除的特性,我们访问了FeatureSelectorops属性,这是一个 Python 字典,特性在值中作为列表。

missing_features = fs.ops['missing']
missing_features[:5]**['OWN_CAR_AGE',
 'YEARS_BUILD_AVG',
 'COMMONAREA_AVG',
 'FLOORSMIN_AVG',
 'LIVINGAPARTMENTS_AVG']**

最后,我们绘制了所有特征中缺失值的分布图:

fs.plot_missing()

共线特征

共线特征是彼此高度相关的特征。在机器学习中,由于高方差和较低的模型可解释性,这些会导致测试集上的泛化性能下降。

identify_collinear方法基于指定的相关系数值寻找共线特征。对于每对相关的特征,它识别要移除的特征之一(因为我们只需要移除一个):

fs.identify_collinear(correlation_threshold = 0.98)**21 features with a correlation magnitude greater than 0.98.**

我们可以用相关性做一个简洁的可视化,这就是热图。这将显示至少有一个相关性高于阈值的所有要素:

fs.plot_collinear()

和以前一样,我们可以访问将被移除的相关要素的完整列表,或者在数据帧中查看高度相关的要素对。

# list of collinear features to remove
collinear_features = fs.ops['collinear']# dataframe of collinear features
fs.record_collinear.head()

如果我们想要研究我们的数据集,我们也可以通过向调用传递plot_all = True来绘制数据中所有相关性的图表:

零重要性特征

前两种方法可以应用于任何结构化数据集,并且是确定性的 —对于给定的阈值,每次结果都是相同的。下一种方法仅设计用于监督机器学习问题,其中我们有用于训练模型的标签,并且是不确定的。identify_zero_importance 函数根据梯度推进机器(GBM)学习模型查找重要性为零的特征。

利用基于树的机器学习模型,比如 boosting 集成,我们可以发现特征的重要性。重要性的绝对值不如相对值重要,相对值可用于确定任务的最相关特征。我们还可以通过移除零重要性特征来使用特征重要性进行特征选择。在基于树的模型中,重要性为零的特征不用于分割任何节点,因此我们可以在不影响模型性能的情况下移除它们。

FeatureSelector使用梯度推进机器从 LightGBM 库中找到特征重要性。为了减少方差,在 GBM 的 10 次训练运行中对特征重要性进行平均。此外,使用验证集的早期停止来训练模型(有一个选项可以关闭它),以防止过度拟合训练数据。

下面的代码调用方法并提取零重要性特征:

# Pass in the appropriate parameters
fs.identify_zero_importance(task = 'classification', 
                            eval_metric = 'auc', 
                            n_iterations = 10, 
                             early_stopping = True)# list of zero importance features
zero_importance_features = fs.ops['zero_importance']**63 features with zero importance after one-hot encoding.**

我们传入的参数如下:

  • task:对应我们问题的“分类”或“回归”
  • eval_metric:用于提前停止的度量(如果提前停止被禁用,则不需要)
  • n_iterations:平均特征重要性的训练运行次数
  • early_stopping:是否使用提前停止来训练模型

这次我们用plot_feature_importances得到两个图:

# plot the feature importances
fs.plot_feature_importances(threshold = 0.99, plot_n = 12)**124 features required for 0.99 of cumulative importance**

左边是plot_n个最重要的特征(根据归一化重要性绘制,总和为 1)。右边是累积重要性与特征数量的关系。垂直线画在累积重要性的threshold处,在本例中为 99%。

对于基于重要性的方法,需要记住两点:

  • 训练梯度推进机器是随机的,这意味着特征的重要性将在每次模型运行时发生变化

这应该不会有很大的影响(最重要的特性不会突然变得最不重要),但是会改变一些特性的顺序。它还会影响所识别的零重要性特征的数量。如果特性的重要性每次都发生变化,不要感到惊讶!

  • 为了训练机器学习模型,首先对特征进行一键编码。这意味着某些被标识为重要性为 0 的要素可能是在建模过程中添加的一次性编码要素。

当我们到达特征移除阶段时,有一个选项来移除任何添加的独热编码特征。然而,如果我们在特征选择之后进行机器学习,我们无论如何都要对特征进行一次性编码!

低重要性特征

下一种方法建立在零重要性函数的基础上,使用模型中的特征重要性进行进一步选择。函数identify_low_importance查找对指定的总重要性没有贡献的最低重要性特征。

例如,下面的调用查找实现 99%的总重要性不需要的最不重要的功能:

fs.identify_low_importance(cumulative_importance = 0.99)**123 features required for cumulative importance of 0.99 after one hot encoding.
116 features do not contribute to cumulative importance of 0.99.**

基于累积重要性的图和该信息,梯度推进机器认为许多特征与学习无关。同样,这种方法的结果会在每次训练中发生变化。

要查看数据框架中所有特征的重要性:

fs.feature_importances.head(10)

low_importance方法借鉴了的一种方法,使用主成分分析(PCA) ,其中通常只保留需要保留一定百分比方差(如 95%)的 PC。占总重要性的百分比是基于同样的想法。

基于特征重要性的方法实际上仅在我们要使用基于树的模型进行预测时才适用。除了随机性之外,基于重要性的方法是一种黑盒方法,因为我们并不真正知道为什么模型认为特征是不相关的。如果使用这些方法,运行几次,看看结果如何变化,也许可以创建多个带有不同参数的数据集进行测试!

单一独特价值特征

最后一个方法相当简单:查找任何具有唯一值的列。只有一个唯一值的特征不能用于机器学习,因为这个特征的方差为零。例如,基于树的模型永远不能对只有一个值的特征进行分割(因为没有组来划分观察值)。

与其他方法不同,这里没有可供选择的参数:

fs.identify_single_unique()**4 features with a single unique value.**

我们可以绘制每个类别中唯一值数量的直方图:

fs.plot_unique()

需要记住的一点是,默认情况下,NaNs在计算 Pandas 中的唯一值之前被删除。

移除功能

一旦我们确定了要丢弃的特性,我们有两个移除它们的选项。所有要删除的特征都存储在FeatureSelectorops字典中,我们可以使用列表手动删除特征。另一种选择是使用remove内置函数。

对于这个方法,我们传入methods来用来移除特性。如果我们想使用所有实现的方法,我们只需传入methods = 'all'

# Remove the features from all methods (returns a df)
train_removed = fs.remove(methods = 'all')**['missing', 'single_unique', 'collinear', 'zero_importance', 'low_importance'] methods have been run

Removed 140 features.**

该方法返回一个移除了特征的数据帧。要移除在机器学习过程中创建的一次性编码特征:

train_removed_all = fs.remove(methods = 'all', keep_one_hot=False)**Removed 187 features including one-hot features.**

在继续操作之前检查将要删除的功能可能是个好主意!原始数据集存储在FeatureSelectordata属性中作为备份!

同时运行所有方法

我们可以通过identify_all使用所有的方法,而不是单独使用这些方法。这需要每个方法的参数字典:

fs.identify_all(selection_params = {'missing_threshold': 0.6,    
                                    'correlation_threshold': 0.98, 
                                    'task': 'classification',    
                                    'eval_metric': 'auc', 
                                    'cumulative_importance': 0.99})**151 total features out of 255 identified for removal after one-hot encoding.**

请注意,由于我们重新运行了模型,总特征的数量将会发生变化。然后可以调用remove函数来丢弃这些特征。

结论

特征选择器类实现了几个常见的操作,用于在训练机器学习模型之前移除特征。它提供了用于识别要移除的特征以及可视化的功能。方法可以单独运行,也可以同时运行,以实现高效的工作流程。

missingcollinearsingle_unique方法是确定性的,而基于特征重要性的方法会随着每次运行而改变。特征选择,很像机器学习的领域,很大程度上是经验性的,需要测试多个组合来找到最佳答案。最佳实践是在管道中尝试几种配置,特性选择器提供了一种快速评估特性选择参数的方法。

一如既往,我欢迎反馈和建设性的批评。我想强调的是,我正在寻求关于FeatureSelector的帮助。任何人都可以在 GitHub 上做出贡献,我感谢那些刚刚使用这个工具的人的建议!也可以通过 Twitter @koehrsen_will 联系到我。

Pytorch 1.0 初探

原文:https://towardsdatascience.com/a-first-look-at-pytorch-1-0-8d3cce20b3ee?source=collection_archive---------10-----------------------

Image by Facebook

今年 10 月 2 日,我有幸参加了第一届 Pytorch 开发者大会。这是一次很棒的经历!Pytorch 已经迅速成为深度学习框架中的一等公民,两年前刚刚起步。在这次活动中,我遇到了许多熟悉的面孔。我将讲述 Pytorch 1.0 上午会议中与软件开发人员最相关的部分。会议包括脸书副总裁 Jerome Pesenti 和 Pytorch 核心开发团队成员的演讲,旨在向社区介绍 Pytorch 1.0。

Pytorch 主要由 Facebooks 的人工智能研究团队开发。目标是使人工智能开放和协作,以便越来越多的人可以利用它。这个团队成立于大约 5 年前,从那时起,他们为脸书的大部分产品提供核心支持。脸书广泛使用人工智能来增强他们产品的功能。一些广泛的领域是(a)提供推荐(新闻源/你可能喜欢的文章),(b)机器翻译(这样世界各地的每个人都可以相互理解),以及(c)创建机器人和消息助手。脸书研究公司在工业界和学术界有很多合作伙伴。

Pytorch 用于新模型和系统的研究和原型制作。这个框架是灵活和必要的,因此易于使用。接下来,必须使用 ONNX(开放式神经网络交换)将 Pytorch 模型移植为更适合生产的形式。ONNX 是深度学习模型的一种格式,能够跨不同的开源 AI 框架移植它们。正在讨论的生产系统是 Caffe2。在脸书,Caffe2 是大多数人工智能应用的主力,并在数据中心大规模部署。Caffe2 框架是健壮的、稳定的,每天能进行 300 万亿次预测。Pytorch 1.0 的目标是将所有这 3 个框架的伟大特性结合成一个单一的框架,以便提供从研究到生产的无缝路径。

T5【py torch 1.0 之路】T6

在之前的升级中,这一次非常重要(因此从 0.4 跳到了 1.0)。每个 Pytorch 版本之前都解决了 Pytorch 框架中的一个核心增强/改进,如图所示。Pytorch 1.0 的重点是引入了高级编译器 torch.jit 。torch.jit 的引入是出于解决两个主要问题的需要:

将模型与代码分离:在 1.0 之前,AI 模型用 Pytorch 编写的代码,为了运行它,需要一个 python VM/环境。对于定制计算环境、移动系统、多线程服务器等,这不是最佳解决方案。Pytorch 1.0 通过在 torch.jit 中提供函数和类注释,允许您将模式与 python 代码分开。这些函数/类可以被编译成可检查、可导出并保存在磁盘上的高级表示。

针对定制硬件的高效模型优化:py torch 模型可以在服务器、TPU 的 GPU、移动设备等上运行Python 代码的纯命令式执行会错过很多优化机会。 Torch.jit 模型可以提前检查,以在不同的粒度级别执行整体程序优化、节点融合等。

Pytorch 1.0 预览版被认为是相当稳定和成熟的,据称 90%的特性已经存在。在脸书,这个系统已经在生产中使用,团队不希望开发人员暴露在严重的错误中。预计 1.0 的稳定版本将于 2018 年 NIPS 前后发布。

深入研究 torch.jit

急切执行模式是研究的绝佳选择。我们可以在代码中使用任意的 python 库,并使用我们选择的调试工具快速构建原型。一旦我们有了一小组想要投入生产的模型,事情看起来就变得更加麻烦了。python 解释器的要求使得移动环境或多线程环境下的服务器设置变得不舒服。即使使用 python 解释器,代码的优化和并行化程度也是有限的。

脚本模式代码可以在没有 python 解释器的情况下执行。这是一个使用 Python 子集编写的模型,可以优化并转换成中间格式。脚本模式拥有构建 AI 模型所需的所有基本构件,但它限制了 python 语言的其他动态行为。

理想的过渡看起来会像上面这样。正如我们所知,大多数人会以渴望模式开始编写程序,这是常规的 Pytorch 代码。当您想要将一个特定的模型转移到生产中时,可以使用 pytorch.jit 工具来注释代码,以将其从渴望模式转移到脚本模式。这可以逐步完成,从您最有信心的模型部分开始,同时仍然保留可调试性,并用其余代码进行测试。为了实际完成从一种形式到另一种形式的转换, torch.jit 提供了两种方法:

Torch.jit.trace — T his 适用于现有的 eager python 模型,这些模型是没有控制流的“直线型”(vision CNN 模型)。跟踪器使用提供的输入运行模块,记录它遇到的张量运算。

例如,可以在常规 python 函数 foo 上运行 torch.jit.trace ,也传入预期的输入。跟踪器基础结构记录发生了什么操作,并将其存储在对象 traced_foo 中。traced_foo 是一个独立的包,可以独立于 python 运行,保存到磁盘和加载等等。

Torch.jit.script — 这对于控制流很重要的模型很有用,比如自定义 RNN。这里我们直接用 Torch 脚本编写代码,这是 Python 的一个子集,可以进行优化。我们使用类和方法注释( @torch.jit.script,@torch.jit.script_method )来表示 python 代码的 torch 脚本部分。循环、打印语句和控制流被保留下来,因为我们只是在 python 代码上使用注释。要使用标准 python 工具调试这部分代码,或者切换到急切执行模式,我们只需要移除注释。

在任何一种情况下(跟踪模式或脚本模式),基本部分仍然是用 python 编写的,而不是用任何中间元编程范式编写的。一个模型可以包含脚本和跟踪代码的混合。保存模型并将其加载到另一个环境中,比如说 C++非常简单,如下图所示。

Pytorch 1.0 和 C++,Pytorch C++前端

首先,Pytorch 1.0 使得将现有的 C++函数集成到您的 Python 环境中变得很容易。例如,您希望使用一些 OpenCV 库功能,并将其引入 Python 代码中。Pytorch 已经有了像 ATEN 这样的库,可以让你用 C++编程,它还有 Autograd,引入了梯度和微分。在 eager 和 script 模式场景中支持 C++似乎很容易:(a)对于 eager 模式,您可以将 C++程序代码转换成一个 Python 模块进行实验(b)对于 script 模式,在 script 模式中使用 C++代码本身

第二,对于特殊的环境,有一个 C++前端,你甚至可以用它来运行训练循环,而不仅仅是推理。这对于具有低延迟、裸机、多线程需求的应用程序来说可能是有意义的。C++前端支持现有的 Pytorch 特性,如 torch::nn、torch::optim、序列化等。

参考资料:

Pytorch 开发者大会活动。视觉效果取自活动期间展示的幻灯片。Pytorch 核心发展演讲者是 Soumith Chintala、Dmytro Dzhulgakov、Zack DeVito、Peter Goldsborough 和李腾

为 scikit-learn 模型提供服务的 Flask API

原文:https://towardsdatascience.com/a-flask-api-for-serving-scikit-learn-models-c8bcdaa41daa?source=collection_archive---------0-----------------------

Scikit-learn 是一个直观而强大的 Python 机器学习库,使得训练和验证许多模型变得相当容易。Scikit-learn 模型可以被持久化(腌)以避免每次使用时重新训练模型。您可以使用 Flask 来创建一个 API,该 API 可以使用一个 pickled 模型基于一组输入变量提供预测。

在我们进入 Flask 之前,重要的是要指出 scikit-learn 不处理分类变量和缺失值。分类变量需要用编码为数值。通常分类变量使用 OneHotEncoder (OHE)或 LabelEncoder 进行转换。LabelEncoder 为每个分类值分配一个整数,并将原始变量转换为一个新变量,并用相应的整数替换分类变量。这种方法的问题在于,名义变量被有效地转换成顺序变量,这可能会欺骗模型,使其认为顺序是有意义的。另一方面,OHE 没有这个问题,但是它倾向于增加变换变量的数量,因为对于分类变量的每个值都会产生一个新的变量。

关于 LabelEncoder 需要知道的一件事是,转换将根据变量中分类值的数量而变化。假设您有一个值为“黄金”和“白金”的“订阅”变量。LabelEncoder 会将这些分别映射到 0 和 1。现在,如果您将值“free”添加到组合中,分配就会改变(free 编码为 0,gold 编码为 1,platinum 编码为 2)。因此,在预测时保留原始的 LabelEncoder 以备转换非常重要。

对于这个例子,我将使用泰坦尼克号数据集。为了进一步简化,我将只使用四个变量:年龄、性别、上船和幸存。

import pandas as pd
df = pd.read_csv('titanic.csv')
include = ['Age', 'Sex', 'Embarked', 'Survived']
df_ = df[include]  # only using 4 variables

性别和从事是分类变量,需要转换。“年龄”有缺失值,通常是估算值,这意味着它被汇总统计数据(如中值或平均值)所替代。缺失值可能非常有意义,值得研究它们在现实应用程序中代表什么。这里我简单的用 0 代替 NaNs。

categoricals = []for col, col_type in df_.dtypes.iteritems():
     if col_type == 'O':
          categoricals.append(col)
     else:
          df_[col].fillna(0, inplace=True)

上面的代码片段将遍历 df_ 中的所有列,并将分类变量(数据类型为“O”)追加到 categoricals 列表中。对于非分类变量(整数和浮点数),在本例中只有年龄,我用零代替 NaNs。用单个值填充 nan 可能会产生意想不到的后果,尤其是当您用来替换 nan 的值在数值变量的观察范围内时。因为零不是一个可观察到的合法的年龄值,所以我不会引入偏见,如果我用 40,我会的!

现在我们准备好 OHE 我们的分类变量。Pandas 提供了一个简单的方法 get_dummies 为给定的数据帧创建 OHE 变量。

df_ohe = pd.get_dummies(df, columns=categoricals, dummy_na=True)

OHE 的好处在于它是决定性的。按照下面的 column_value 格式,为每个列/值组合创建一个新列。例如,对于“已装船”变量,我们将得到“已装船 _C”、“已装船 _Q”、“已装船 _S”和“已装船 _nan”。

既然我们已经成功地转换了数据集,我们就可以开始训练我们的模型了。

# using a random forest classifier (can be any classifier)
from sklearn.ensemble import RandomForestClassifier as rfdependent_variable = 'Survived'
x = df_ohe[df_ohe.columns.difference([dependent_variable])
y = df_ohe[dependent_variable]clf = rf()
clf.fit(x, y)

训练好的模特准备好被腌制了。我准备用 sklearn 的 joblib。

from sklearn.externals import joblib
joblib.dump(clf, 'model.pkl')

就是这样!我们坚持了我们的模式。我们可以用一行代码将这个模型加载到内存中。

clf = joblib.load('model.pkl')

我们现在准备使用 Flask 来服务我们的持久模型。

烧瓶非常简约。下面是启动一个裸机 Flask 应用程序所需的内容(在本例中是在端口 8080 上)。

from flask import Flaskapp = Flask(__name__)if __name__ == '__main__':
     app.run(port=8080)

我们必须做两件事:(1)当应用程序启动时,将我们的持久模型加载到内存中,以及(2)创建一个端点,该端点接受输入变量,将它们转换成适当的格式,并返回预测。

from flask import Flask, jsonify
from sklearn.externals import joblib
import pandas as pdapp = Flask(__name__)@app.route('/predict', methods=['POST'])
def predict():
     json_ = request.json
     query_df = pd.DataFrame(json_)
     query = pd.get_dummies(query_df)
     prediction = clf.predict(query)
     return jsonify({'prediction': list(prediction)})if __name__ == '__main__':
     clf = joblib.load('model.pkl')
     app.run(port=8080)

这只在理想情况下有效,在这种情况下,传入的请求包含分类变量的所有可能值。如果不是这样,get_dummies 将生成一个数据帧,其列数少于分类器的列数,这将导致运行时错误。此外,需要使用我们训练模型时使用的相同方法来替换数值变量。

列数少于预期的一个解决方案是保存来自培训的列列表。记住 Python 对象(包括列表和字典)是可以被腌泡的。要做到这一点,我将使用 joblib,就像我以前做的那样,将列的列表转储到一个 pkl 文件中。

model_columns = list(x.columns)
joblib.dumps(model_columns, 'model_columns.pkl')

因为我们有这个持久化的列表,所以我们可以在预测的时候用零替换丢失的值。我们还必须在应用程序启动时加载模型列。

@app.route('/predict', methods=['POST'])
def predict():
     json_ = request.json
     query_df = pd.DataFrame(json_)
     query = pd.get_dummies(query_df) for col in model_columns:
          if col not in query.columns:
               query[col] = 0 prediction = clf.predict(query)
     return jsonify({'prediction': list(prediction)})if __name__ == '__main__':
     clf = joblib.load('model.pkl')
     model_columns = joblib.load('model_columns.pkl')
     app.run(port=8080)

这个解决方案仍然不是万无一失的。如果您碰巧发送了不属于训练集的值,get_dummies 将产生额外的列,您将遇到错误。为了使这个解决方案有效,我们需要从查询数据帧中删除不属于 model_columns 的额外列。

GitHub 上有一个可用的解决方案。

利用以太坊收盘价进行时间序列预测的尝试

原文:https://towardsdatascience.com/a-foray-into-time-series-forecasting-using-ethereum-closing-prices-5ca69dbbd76a?source=collection_archive---------6-----------------------

Photo by Executium on Unsplash

围绕加密货币的狂热炒作不同于我在这个星球上 25 年来所目睹的任何事情(也许除了狂骨的崛起,这在我上小学的时候是身份的象征)。每天,似乎都有各种密码达到“历史新高”的新报告,经济学家预言众所周知的密码泡沫破裂,新玩家(我正看着你,涟漪)震撼市场。伴随着所有的讨论,我开始思考——这个市场有什么逻辑吗?昨天(甚至最后一小时)的市场动态可以用来预测未来的表现吗?带着这些问题,我开始寻找噪音中是否有信号。

在本帖中,我将使用几种不同的算法,看看是否有可能仅使用“传统”加密货币市场数据(开盘价/收盘价、高/低价、成交量)对每小时的加密货币价格进行可靠的预测。由于许多不同的因素驱动着市场(供给/需求、媒体炒作和/或公众认知、硬币效用等。),这可能看起来像是一个西西弗式的努力,但正如我们将看到的,即使使用节省计算费用的模型,也可以生成相当不错的预测。(此外,这个项目给了我一个深入时间序列分析/预测的借口,我在这里的一组笔记中详细介绍了这一点。)

事不宜迟,我们开始吧!

数据源

对于这项工作,我通过 crypto compare API(https://www.cryptocompare.com/api/)获取每小时的加密货币数据。我发现使用他们的 API/文档非常简单,事实上他们集成了 75 个以上不同的交换,这对我来说是一个一站式商店。然而,唯一的缺点是,当使用免费帐户的 API 时,只能访问 2000 年最近的时间点(大约 3 个月的每小时数据)。

Cryptocurrency closing prices (standardized for visualization).

在这个脚本中,我从五个最大的交易所(比特币基地、波洛涅克斯、北海巨妖、Bitstamp、Bitfinex)提取了五种流行的加密货币(比特币、以太币、莱特币、Dash 和 Monero)的数据。一旦我有了所有的数据,我就执行必要的聚合(平均)以将来自每个交换的特征组合成一个,尽管人们可以想象将它们都保存起来并观察这如何改变事情。

您可能会从脚本中注意到,我还添加了一些额外的功能。除收盘价外,我还包括:

  • 成交量:总成交量(交易所平均;一个总数会更自然,但是我丢失了一些交换的数据)

  • 波动:波动性的度量;定义为小时最高价和最低价与开盘价之差(交易所的平均值)

  • relative_hl_close :波动率的附加度量;使用高/低价(交易所的平均值)对收盘价进行最小-最大缩放。值为 1 表示收盘价与所有交易所在该小时的最高价相同,而值为 0 表示所有交易所的收盘价都是最低价。

在博客的其余部分,我将通过时间序列分析/预测,使用 ARIMA随机森林和长短期记忆( LSTM )网络来预测收盘价,详细描述我的冒险经历。我选择使用比特币的亲戚以太坊,它正日益流行。在我修补各种模型/算法的时间里,以太坊市场增长如此之快,以至于我可能会在我这里添加更多的最新数据(我的数据集只持续到 2017 年 12 月的一周左右),但现在,我们将使用我手头的数据。

预赛

在深入研究结果之前,我想花点时间讨论一下贯穿本文其余部分的几个总体统计概念— 平稳性、时间序列验证、先行一步预测。

Ethereum closing prices (blue) and differenced closing prices (red), standardized for the sake of visualization. The Augmented Dickey-Fuller Test was used to assess stationarity.

平稳过程的维基百科定义是“一个随机过程,它的无条件联合概率分布在时间移位时不变”。对于那些讲统计的人来说,这是一个非常好的一行程序(因此被引用),但是如果它让你抓耳挠腮,不要害怕!本质上,平稳性意味着生成时间序列数据的基本过程与时间无关——如果存在时间相关性,我们如何能够以有意义的方式进行预测?平稳性是一些经典预测技术的核心(例如, ARMA ),即使在它不是必要条件的情况下(树,神经网络),它也是准备数据时要考虑的因素。

时间序列验证是一个相当任性的企业。在一个普通的机器学习问题中,您将获得手头的所有数据,将其随机划分为训练集/测试集(其中一些训练集被保留用于验证),根据训练集拟合模型,根据训练模型为测试集生成预测,并使用所述预测来评估模型的性能。然而,当您有时间依赖性时,这种方法可能不可行,这取决于您选择的算法——随机分割您的时间序列可能会对可以利用的任何类型的自相关造成严重破坏,并且在实践中,您可能会对选择尊重数据的时间依赖性的分割感兴趣(即,使用滚动窗口)。即使找到了合适的验证方案,您也必须决定如何生成预测(一次一个/多个步骤,使用实际/预测值等)。).

Train-test split (time ordering preserved) for Ethereum closing prices.

在这篇文章中,我用以下方式来解决这些问题:

  • 对于随机森林,我在超参数调整期间使用了滚动窗口(时间序列分割)。对于 LSTM,为了节省计算时间,我没有加入任何花哨的验证方案。(不过,我确实添加了一些剔除层,有望解决过度拟合的问题)。
  • 我保留最近一周左右的数据作为测试集,并生成提前一步的预测,其中实际观察值在需要时成为滞后协变量。我之前提到过,我将在本文的剩余部分使用以太坊,这样做的部分原因与测试集和训练集末尾的收盘价动态之间的偶然相似性有关。如果我们在测试集中有以前没有观察到的不可靠的行为,评估模型性能将是一个徒劳的练习——在这里,这不应该构成太大的问题。

ARIMA

首先,我决定看看我是否能在以太坊的收盘价上安装一个 ARIMA 。如果我在数据中发现了某种 AR(p)或 MA(q)特征,那么我将尝试引入一组额外的外生变量(ARIMAX ),看看我是否可以改进 ARIMA 的拟合/预测。然而,我很快发现,在这种情况下,单靠 ARIMA 是不可行的,这可能是因为推动加密货币市场的许多不同因素(对自回归/误差项进行线性拟合是不够的)。

我和 ARIMA 的工作进展如下:

  • 在 ARIMA, I 代表“整合的”——在实践中,它指的是使所考虑的时间序列平稳所需的差分(d)阶。对于以太坊收盘价,一阶差分(d=1)是我们使时间序列平稳所需要的。
  • AR (p)和 MA (q)分别指我们模型的自回归和移动平均部分。说白了,AR 项是感兴趣的量的滞后值(我们保留其中的 p ),而 MA 项说明过去时间点的回归误差(我们保留其中的 q )。传统上,参数 p 和 q 是从差分(平稳)序列的部分自相关和自相关函数(PACF/ACF)中手动确定的,尽管它们也可以通过模型选择经由AIC/BIC(auto . ARIMA用于 R 用户)来选择。
  • 自相关(在滞后 n 时)就是一个时间序列和移动了 n 个周期的同一序列之间的线性相关。另一方面,部分自相关是一个时间序列和偏移了 n 个周期的相同序列之间的线性相关性的度量,调整来自滞后 n 之前的所有滞后的相关性。后者消除了中间(少于 n )滞后阶数之间可能存在的任何相关性,允许对任何给定滞后阶数的相关性进行独立评估。

Autocorrelation (ACF) and partial autocorrelation (PACF) functions for differenced closing prices.

  • 本质上,我们在寻找 AR 模型的 PACF/ACF 在滞后零之后稳定/急剧下降的某种模式,以及 MA 签名的相反情况(ACF/PACF)(有关更详细的概述,请查看这些注释)。为了可视化的目的,我已经将上面显示的 ACF/PACF 缩短到只有 50 个滞后,但是最终,没有结构指示 ARMA 过程。

回想起来,我们在这里运气不佳可能并不奇怪。正如我前面提到的,加密货币市场的兴衰是由不确定的潜在因素驱动的,这使得自回归/误差项的线性拟合充其量是可疑的。

随机森林

尽管在 ARIMA 没有取得成功,我还是想探索一些流行的 ML 方法会有怎样的表现。另一个简单(但流行/强大)的预测时间序列的方法是通过回归树,所以我决定尝试一下随机森林 (RF)!

当使用 RF 进行时间序列分析/预测时,人们通常会使用时间序列的滞后值和任何其他被认为在您的问题环境中具有某种效用的附加特征来构建特征矩阵。在这里,我包括了以太坊收盘价的八个滞后值,我前面提到的衍生功能,以及 Monero (XMR)的相同功能集,因为在早期我将完整的功能集(八个滞后加上所有五种加密货币的附加功能)输入 RF 时,这两者之间似乎有某种联系。(旁注:为了更严格地做到这一点,可以用 Boruta 来代替)。

Snapshot of feature matrix (target variable in red box, predictors contained in blue box).

在对一些 RF 参数(n_estimators、max_features、min_samples_leaf)执行了(一点点)网格搜索交叉验证之后,在检查结果之前,我查看了特征的重要性,试图了解 RF 正在做什么:

Feature importances for ETH_USD.

正如人们可能预料的那样,我们看到收盘价的最后几个滞后值支配了所有其他特征(我加入的额外值也完全无关紧要)。由于 ARIMA 只包含目标变量滞后值(和误差项)的线性回归,这将表明,在所有之后,可以从滞后值中收集到一些东西(非线性的)。

此外,Monero (XMR_USD)的一些滞后收盘价中包含一小部分信息。由于我对加密没有深入的投资,我不确定这是否是伪造的,但我认为即使没有适当的解释,我也会保留这些特性。

现在,看看结果:

Actual/predicted ETH_USD closing prices for training set (RF).

Actual/predicted ETH_USD closing prices for test set (RF).

还不错!尽管我们有时会与实际收盘价不同步,但我们从未偏离它们太远。凭借更具识别性的功能,RF 可能会表现得足够好,让加密投资者用他们的钱包做出合理的金融决策——目前,它可能只适合那些喜欢在生活中加点料的人。

LSTM

如果模型的可解释性不是问题,为什么不试着把数据塞进神经网络呢?这里,我们将使用一个长短期记忆网络。(关于 LSTMs 的更多背景,请看这里,这里这里,这里这里。如果你想了解与 crypto 类似的努力,只需看看这里的和这里的。

在将我们的数据输入 LSTM 之前,我们将标准化我们所有的输入特性——为了保持一致,我将包括与 RF 相同的特性。在将其分成适当的训练/测试集之后,我们将把我们的数据分块输入到 LSTM 中——我已经决定以 12 小时为间隔进行此操作——并尝试预测紧接在每个 12 小时窗口之后的一个小时的(标准化)收盘价。对于测试集,我们将使用前面详述的方案进行预测。提前一步预测会对我们的预测提出一个过于乐观的观点(立即预测更长的时间段或使用拟合值会做得更差),但它应该足以用于演示目的。

我们的 LSTM 的总体框架如下:

  • 在内部,我们将有一个两层,堆叠的 LSTM。我在每个隐藏层中任意选择了 20 个隐藏节点,但是在实践中,人们可以通过反复试验来确定最佳数量。
  • 为了使正规化,我在每次 LSTM 后加入两层退图层。我为每个下降层提供的参数(0.2)也是任意选择的,但也可以调整。
  • 出于计算方面的考虑(我正在笔记本电脑上运行这个程序),我将时期的数量限制为五个。通过增加这个数字,你不会烧掉房子,但是损失看起来稳定了,即使是很少的时期。

随着这些细节的公开,以下是我们的 LSTM 的表现:

Actual/predicted ETH_USD closing prices for training set (LSTM)

Actual/predicted ETH_USD closing prices for test set (LSTM).

汪汪。虽然我们看到 LSTM 在 11 月底之前的训练中表现相似,但我们在测试中表现不尽如人意。然而,值得注意的是,我们似乎能够捕捉到该系列的总体形状(上涨时上涨,下跌时下跌,等等。),但我们永远无法到达最高点和最低点。如果我是一个打赌的人,我会把这种行为归因于缺乏参数调整,或者我们的 LSTM 学习到的大多数“长期”行为可能来自 9 月到 11 月初,在 11 月底/12 月更不稳定的行为之前。这反过来又说明了 LSTMs 的一个局限性——要使它真正发挥优势,我们需要许多样本,这些样本包含像这样的时间序列的所有细微行为,以馈入我们的网络。

总结(TL;博士)

在这篇博文中,我介绍了在加密货币收盘价的背景下用于时间序列分析/预测的三种流行方法的比较。虽然我们确实观察到了不错的结果,但加密货币市场的善变性质阻止了我们提升到吉姆·坎托雷级别的预测者,并且从理论上来说,纳入从诸如外汇市场和 T10 在线论坛 T11(或 Twitter/Google)构建的其他协变量可能会带来更好的时机。

参考

Jupyter 笔记本:各种剧情、 ARIMA 、随机森林、 LSTM

评估数据科学家能力的框架

原文:https://towardsdatascience.com/a-framework-for-evaluating-data-scientist-competency-89b5f275a6bf?source=collection_archive---------1-----------------------

不乏建议 讲解 如何 如何 聘请 一个 数据 科学家。我以前写过这个话题。大多数建议假设一个理想的数据科学家应该具备的技能或素质列表,并专注于如何对求职者拥有这些技能感到自信。我想更仔细地看看这份基本技能清单。标签是有问题的。例如,“统计学”通常被认为是数据科学家技能集的一个重要方面,但你会发现数据科学家更多地来自计算机科学背景,而不是统计学背景。因此,我们可能会创建一个“机器学习”维度来适应这种背景。因此,我们要么专注于两种实际上有很多重叠的不同技能,要么将它们归为“统计和机器学习”技能,这正好避免了这个问题。换句话说,数据科学家需要什么技能的问题是一个降维问题。

大多数降维的一个关键特征是关注正交性,我认为这也是大多数讨论所缺少的。数据科学家技能框架应该采用庞大、杂乱的数据科学家-数据科学家-技能矩阵,并尝试将其缩减为几个重叠最小的信息维度。这可能需要一些文字上的修饰,以避免使用已经加载的术语,但这在概念上是值得的。例如,我认为“编码能力”不属于技能框架,更不用说像 R 或 Python 这样的特定语言了。在设计良好的主题中展示所有技能的数据科学家应该理所当然地展示编码技能,因为公司有技术堆栈,数据科学家需要与技术堆栈集成的技能,以确保他们的工作是可重复和可扩展的。像编码这样的东西是一种手段,而不是目的,因此我认为它们不应该成为直接的目标。

我还应该提前声明,我坚信“数据科学家”的角色应该与“工程师”和“分析师”的角色分开。这就是我目前工作的角色,但我知道在许多其他组织中情况并非如此,包括我以前工作过的那些组织。我认为我现在的雇主说得对。即使在财务或其他业务考虑要求一个人担任两个或更多角色的情况下,我认为这也应该被视为一个人身兼数职,而不是数据科学家的帽子大到足以包含其他两个角色的标志。

我开始认为“好的数据科学”是在个人层面上不存在的东西:虽然单个团队成员都非常擅长某些技能,但建立强大的数据科学能力是任何一个人都无法完成的事情。我看到的大多数关于数据科学技能的讨论都没有明确承认这一点。我们所有人的技能都有差距,但只要团队没有任何差距,那就没问题:它确保我们能够共同完成我们需要做的事情,并且仍然给我们所有人留下许多成长的机会。我通常在这样的讨论中看到的是某种免责声明,大意是不是每个人都需要检查每个框。如果这是我们作为数据科学专业人员的想法(我认为大部分是这样),那么它应该明确地纳入我们的框架。

框架

个人技能

让我们来看一下每一项技能,并讨论当我们看到它们时如何识别它们。

设计分析。属于该能力的技能与将业务需求转化为技术分析计划有关。数据科学家使用这些技能做出的决策部分取决于可用数据的结构、类型和数量,但也取决于存在的业务需求,而不管数据看起来如何。该能力范围内的所有技能都可以归入“知道如何处理不明确的需求”的大标题下

  • 明确地计划分析。这包括里程碑的范围界定、排序和证明。分析很少会有一个自然的停止点——几乎所有的分析都可以被无休止地改进。在业务应用程序中,需要对分析进行范围划分和划分:需要设定里程碑,需要为每个里程碑确定停止规则,并且需要以保持概念完整性的方式将所有部分总结为一个整体。
  • 预见并解决相互矛盾的解释。这可能包括实验设计、抽样策略或敏感性分析。任何分析都做出断言:预测足够准确,有商业价值,变量 x 和 y 是重要的预测指标,增加变量 z 并没有增加足够的价值,值得等等。所有这些主张都容易受到对立解释的影响:抽样有偏差,数据集不平衡,变量定义不当,等等。预测这些漏洞是一种技能。特定的方法可能会减轻问题,但通常关键是将假设检查纳入分析的设计中。
  • 确定评估结果的最佳方式。这可能包括诊断指标、基准或 KPI 开发,以监控产品质量。分析很少产生具有明确解释价值的结果。通常,问题不是“结果好吗?”,而是“结果是否比我们以前获得的结果对业务更有价值?”评估分析结果需要了解分析方法的输出,以及结果将部署到的业务环境。

进行分析。当人们谈论数据科学时,属于这种能力的技能通常会受到大量关注。数据科学家利用这些技能做出的决策几乎完全取决于数据本身的细节。

  • 适当地探索数据。这包括分布、汇总指标、可视化和功能选择/工程。这些技能可以简单到知道如何表征分布或集中趋势的度量,也可以复杂到设计全新的功能。这项技能的重点是了解在数据集中寻找什么类型的“陷阱”,以便可以转换、省略、适应或减轻这些特质。
  • 建立或应用适当的算法。这包括回归、分类、降维、聚类和参数调整。分类数据有时会对分析施加不同于连续数据的约束。稀疏与密集数据、有监督与无监督学习问题等也是如此。不同的问题需要不同的技术方案,知道如何选择合适的技术方案是一项有价值的技能。
  • 明确记录调查结果。这通常包括数据可视化和技术交流。记录分析结论的摘要有助于其他人从一个数据科学家停止的地方继续分析,但也可以作为对数据科学家结论的健全性检查。如果分析结果不能清楚地记录下来,那么很有可能分析不够连贯,不可信。

将分析纳入管道。数据在用于分析之前和之后会发生很多变化。数据科学家的部分职责是确保这些移交顺利进行。这是数据科学家的技能组合与工程师的技能组合最一致的地方。当工程师能够按照数据科学家需要的方式清理、构建和定位数据时,这总是有用的,但这应该是提高效率的一种方式,而不是能够完成工作的先决条件。

  • 从任何格式和位置读取/写入数据。这包括数据库查询、合并不同的文件类型、API 和文件管理。数据科学家不能奢望让别人来组织他们的数据集。需要从数据所在的任何格式和位置提取用于分析的数据,并输出到那些将使用结果的人所需的任何格式和位置。
  • 合并复杂匹配和过滤。进行布尔匹配或过滤,将字符串或数字作为整体进行比较,是一项相对简单的任务。然而,许多数据科学需要更复杂的操作,定义匹配字符串子集的模式或使用复杂的数据类型,如时间戳、shapefiles、图形。
  • 使工作与工程堆栈兼容。这包括版本控制、编码风格和软件工程最佳实践。如果不能整合到业务的其他技术系统中,或者不能扩展(如果业务需要的话),那么世界上最好的分析也是没有用的。

将管道纳入业务。该能力中的所有三项技能都属于“沟通技能”的范畴。这个标签通常不够精确,没有用。如果一个数据科学家可以在任何情况下都与每个人很好地沟通,那就太好了。任何人能做到这一点都很好。数据科学家必须能够在三种特定环境下进行交流。

  • 发现业务的需求。这包括前期技术要求和对更广泛行业背景的理解。这项技能主要是为了让数据科学家理解非技术主题。数据科学家通常充当技术和非技术利益相关者之间的桥梁,因此应该能够理解业务的非技术方面。
  • 浏览企业的组织结构。这包括建立关系和利益相关者管理,有时被总结为“软技能”。任何组织都有需要驾驭的人际关系,以实现业务成果。这当然包括不做混蛋的人际技巧,但也包括,例如,识别项目的非官方看门人并在计划更广泛的听证会之前获得此人的认可的更微妙的技巧。
  • 为不同的受众打包技术工作。这包括非技术交流,包括视觉效果和信息。这是“发现业务需求”技能的另一面。无论是出于营销目的还是为了确保利益相关者能够明智地使用数据科学产品,数据科学家都需要能够让非技术人员了解技术主题。

建立职业。这个能力领域可能看起来更像是一个“值得拥有的东西”,但我认为这大大低估了超越一个人的工作进入更大的职业领域的价值。数据科学作为一种职业变化太快,如果数据科学团队不持续地重新评估什么是数据科学,他们就无法真正跟上技术的发展。与更大范围的职业接触标志着一个个人贡献者,他做出有意义贡献的能力已经被审查。

  • 尽力做出贡献。聚会、黑客马拉松、开源代码库、博客和其他公共贡献让数据科学家与更广泛的社区保持联系。公共捐款会引起公众的评论和批评,这反过来会改进实践。
  • 领导团队。参与工作小组、担任团队初级成员或实习生的导师是团队中最常见的非正式领导职位。在某些方面,非官方领导是公开贡献的缩小版:它让数据科学家的实践接受审查,从而改进实践。
  • 起草政策和程序。这可能包括创建候选人面试协议、会议出席政策或社交媒体政策。对更广泛的数据科学社区的贡献不一定要公开。如何最好地组织和管理数据科学团队仍然是一个悬而未决的问题。政策和程序是可传播的人工制品——能够改善的不仅仅是创建它们的组织。

能力水平

确定正交的能力领域是定义数据科学技能标准的一半挑战。挑战的另一半是决定如何评估能力程度。我发现意识能力学习模式是思考技能水平的一种便捷方式:

无意识的不称职意味着数据科学家不熟练,但在很大程度上没有意识到这一点——事实上,甚至没有意识到拥有技能的重要性。例如,从事技术职业的人通常被刻板地认为在软技能领域无意识地无能——他们不擅长与人互动,没有意识到自己不擅长,有时甚至否认擅长这种事情的重要性。无意识无能的人对某项技能的直觉很差:他们得出错误的结论,因为他们甚至不知道问题出在哪里。

有意识的无能意味着数据科学家知道问题是什么,但不知道如何解决。这一阶段的学习是艰难的——数据科学家可能会将错误视为对他们作为员工的价值的控诉,或许在请求导师指出更微妙的方法之前,模仿公认的最佳实践的时间超过了明智的时间。

自觉能力意味着数据科学家知道问题和答案。这仍然是学习的高速增长阶段,但数据科学家将错误视为新信息的宝贵来源。困惑或无能的感觉被认为是一种积极培养能力的信号。

无意识能力是一种技能已经成为“第二天性”的阶段——以至于展示这种技能几乎不需要有意识的思考。

使用标题

传统上,一个标题提供了一个清单:评估者为每一行项目选择一个最能体现被评估者技能水平的选项。由于数据科学家非常清楚报告集中趋势而非分布测量的危险,因此该标题是为更细微的用法而设计的。例如,我在目前的职位上只呆了几个月,下面是我如何为自己填写的:

因为一个数据科学家可以有几十甚至几百种方式来举例说明一项特定的技能,我已经描绘了我认为我在每项技能中的最低()表现在哪里。下面是我决定用这种方式填写表格时的想法的简要解释。

  • 明确规划分析。我在社会科学领域的背景,以及我在各种行业和部门工作的十年,让我或多或少地习惯于将一个模糊的目标分解成几个可衡量的子目标,并为我的计划提供理由。也就是说,我阅读关于设计原则的文章和书籍,仍然经常发现我不知道的最佳实践。
  • 预测并解决不同的解释。定义我在分析中做出的假设,并对这些假设进行测试,这是我的第二天性。我对实施大多数采样策略或提出自己的策略完全满意。我对实验的形式设计原则只是略知一二,如果没有进一步的学习,我不会觉得自己有能力实施这些原则。
  • 确定评估结果的最佳方式。我认为我在这方面一般比较可靠。这不是第二天性,但我已经有一段时间没有遇到任何完全陌生的领域了。
  • 适当发掘数据。在探索性可视化方面,我会给自己打高分到非常高的分,但在统计分布方面,我会稍微低一点(我不是统计学出身,所以在那个领域有很多我不知道的东西)。我也意识到有许多我只是名义上熟悉的工程特征的方法。
  • 建立或应用适当的算法。我觉得我在这方面总体上是有能力的,但是我很少有机会使用深度学习方法。这是我技能组合中的一个明显的缺口。
  • 清楚地记录调查结果。我对这项技能的感觉类似于我对“明确计划分析”技能的感觉。我的背景训练我这样做,我的经验给了我很多实践。我很少需要考虑如何去做。
  • 从任何格式和位置读取/写入数据。在这项技能上,我从第二天性(CSV、Postgres)到一般胜任(SQL、Spark、AWS EC2 和 S3 的大多数其他版本),到不胜任但知道它(其他 Hadoop 技术、其他 AWS 服务、其他像 Google Bigtable 这样的云系统,等等)。)
  • 合并复杂的匹配和过滤。文本模式匹配(正则表达式等。)是我的第二天性,大多数日期时间数据管理也是如此。我最近对形状数据和图形非常熟悉,但我知道在这些领域我还有很多东西要学。
  • 使工作与工程堆栈兼容。在很大程度上,我觉得自己在这方面总体上是称职的,这主要是因为我过去组建并管理过一个数据科学和工程团队。然而,对于顺利移交给需要大规模运营的工程团队,我仍在学习许多东西。
  • 发现业务需求。总的来说,我在利益相关者管理、需求开发、业务流程映射等方面有很多经验。然而,我转到了现在的工作岗位,却没有那份工作的行业经验。我很大程度上对这个行业一无所知,并满足于在机会到来时学习,而不是明确地优先考虑这个领域的增长。
  • 浏览企业的组织结构。总的来说,我在这方面很擅长,但是我在一个新的组织中工作,这个组织的结构和政策正在发生很大的变化。说到具体的,我不知道我不知道的。
  • 为不同的受众打包技术工作。我通常很擅长这个。我作为人类学家的背景使我能够相对容易地理解他人的观点,几年的教学经验使我能够相对容易地对甚至难以理解的话题进行陈述。
  • 对外投稿。我写博客已经很多年了。我曾经在 Github 上发布过很多我的作品,但是已经有几年没有这么做了,因为我的大部分作品都是专有的。我仍然在业余时间想办法做志愿者或咨询,我积极参加招聘活动。
  • 带队。我领导一个外部拓展和协作工作组,并指导团队中的初级成员。
  • 政策和程序草案。除此之外,在我从事的所有工作中,我倾向于关注政策。有时候这是我的主要工作职责之一。

我个人更喜欢在前瞻性对话中使用技能标准,而不是在回顾性对话中。例如,绩效评估不一定是谈论数据科学家在任何特定技能集方面的一般能力的合适时间和地点。然而,这是一个合适的时间和地点来谈论数据科学家如何花几个月的时间,比如说,创建一个优雅的统计解决方案,不能大规模部署。审查时的问题不是缺乏技能;这是缺乏价值的传递。然后,这可以为一个单独的前瞻性对话奠定基础,在这种情况下,建立一个人的软件工程约束和最佳实践的知识。绩效评估作为一种现实检查,然后这个标题作为一种工具来构建一个增长计划。在我为自己填写标题时,我决定在一些领域发展,按优先顺序排列如下:

  1. 更好地了解业务需求。我觉得与我们客户的实际需求有些距离。我的大部分创新想法来自我自己,而不是来自实际使用我们产品的人。我希望感觉自己有一个了解客户痛点和愿望清单的既定渠道。
  2. 提高我的分析规划/设计技能。当时我正在阅读弗雷德·布鲁克斯的设计的设计,我很喜欢它,但我觉得我没有保留足够的东西来真正地将它融入我的实践中——我想要更多的经验来明确地设计整个数据支持的项目,而不仅仅是设计单个的分析。
  3. 练习使用流式数据。我使用的大部分数据可以来自流,但它总是一段时间内的快照或摘要。我想在使用 Kafka、Spark Streaming contexts 等方面获得更多的经验。
  4. 网络分析。通过我最近的一些工作,我对网络分析变得更加熟悉,但是在这个领域还有大量的领域需要探索,我发现我真的很喜欢它。
  5. 学习 Scala。我使用 PySpark,但是我遇到过几种情况,如果我使用 Scala 的话,工作效率可能会更高。当我看到 Scala 代码时,我知道的足够理解它,但我不会写它。
  6. 开源我的一些作品。我对创建自己的图书馆不感兴趣,虽然我很想为已经建立的图书馆做些贡献,但我不确定我能在哪里增加价值。与此同时,我开发了几个方便的函数来处理杂乱的形状数据,还开发了一些函数通过 Spark 从邻接表中获取连接的组件。我想优先记录这些事情,并获得我的雇主的许可,公开分享这些信息。
  7. 扩展我在功能工程方面的经验。有很多方法。我使用的相对较少,并且熟悉许多其他的,但是我觉得那只是我技术专长的一小部分。
  8. 熟悉深度学习。它现在很流行,而且在它成功的领域确实产生了一些很好的结果,所以我认为在这方面胜任对我有好处。

为什么重要?

我想说,质疑我们为什么需要如此具体地定义数据科学技能集是公平的,但我真的不认为质疑这一点是公平的。当我们有如此多的招聘广告规定数据科学家必须拥有 STEM 领域的高等学位,或者必须通过一系列玩具编码挑战,或者必须在一系列不可思议的技术工具中拥有在职经验时,就不会这样了。任何在就业市场上寻找数据科学职位的人都看到,大多数潜在雇主对他们在寻找什么或如何识别能力知之甚少。技能框架为对话建立了共同的基础,即使这些对话是在观点大相径庭的人们之间进行的。这个规则迫使你和其他人对评估都要明确。一个好的框架不能保证对话会有成效,但是一个糟糕的框架几乎可以保证对话不会有成效。很多人想雇佣一名数据科学家。许多潜在的数据科学家希望被雇佣。如果我们能够更加清楚和准确地了解数据科学家需要能够做什么,我们就可以让这两个群体都比现在更高兴。

一个免费的谷歌数据工作室是一个好的开始,但是在民主化分析方面我们还有很长的路要走

原文:https://towardsdatascience.com/a-free-google-data-studio-is-a-good-start-but-we-still-have-a-long-way-to-go-in-democratizing-f22f461444e?source=collection_archive---------1-----------------------

Google Data Studio 向分析民主化迈进了一步,但却未能向最需要的人提供数据分析的 3 个原因。

谷歌最近在其谷歌数据工作室中启用了无限报告。在这样做的时候,他们实际上让他们的旗舰数据分析工具免费供每个人使用。

从高层次来看,Google Data Studio 提供了一套全面的分析功能,包括:

  • 集成来自多个数据源的数据,包括 SQL 数据库、Google Analytics 和 Google Sheets。
  • 格式化和清理集成数据集,为分析做准备。
  • 基于清理后的数据集生成和共享数据可视化和仪表板。

传统上,这些功能只在 Chartio 和 Quill 等付费工具中提供。因此,推出免费的谷歌数据工作室是向数据分析普及迈出的一大步。

首先,我想首先为谷歌这一前瞻性的决定鼓掌。免费的数据可视化和集成工具是走向分析民主化的关键一步。

然而,我也相信,就像谷歌分析一样,让谷歌数据工作室免费只是让数据分析变得简单、有趣、对所有企业都有价值的过程中的第一步。

虽然谷歌数据工作室(GDS)提供了许多有用的功能,但它在帮助中小企业理解和提取数据价值方面存在不足,因为:

  1. 尽管 GDS 拥有强大的数据清理和整合能力,但它并不指导一个组织的整体数据战略,也不帮助它决定首先收集和分析哪些数据集。
  2. 虽然它的可视化和仪表板功能可以快速测试业务假设,以找到“已知”业务问题的答案, GDS 不能帮助组织发现令人惊讶的见解,或“未知的未知”。
  3. 虽然 GDS 可以帮助企业监控和跟踪指标,它没有告诉你如何首先识别和选择好的指标来跟踪。

我来详细说明一下。

GDS 并不指导一个组织的整体数据战略

数据分析本身从来都不是目的。它总是实现某些商业目标的一种手段。

因此,在开始一个分析项目之前,你需要非常清楚它如何为你的业务增加价值——是增加收入、削减成本还是获得更多客户。

如果没有明确的战略,您甚至不知道首先要在您的组织中收集哪些数据集,您的分析也不会为您带来任何即时的业务洞察力。

Google Data Studio 使在您的组织中收集和清理数据集比以往任何时候都更容易,但它并不能帮助您首先提出数据收集的策略。

然而,制定良好的数据战略并理解数据的直接价值是阻碍中小型企业在其组织中采用分析的最大挑战。

作为 Humanlytics 客户开发流程的一部分,我的团队采访了 70 多家中小型企业(SMB)。在所有接受采访的企业中,我们发现的两个最大的难点与数据策略有关,而不是分析项目本身:

  • 采用:“我们不理解在我们公司实施数据分析的商业价值。”
  • 解读:“我们缺乏人才和资源来理解我们拥有的数据,并从数据中提取可操作的见解。”

尽管许多公司也抱怨集成、清理和可视化方面的痛点,但实际上是数据采用和解释首先阻止了中小型企业使用任何分析。

Google Data Studio 根本没有解决这两个挑战,因为您仍然需要有经验的分析师或顾问来协助中小型企业,并帮助他们了解如何在他们的组织中使用数据,而数据人才通常对这些企业来说非常昂贵。

GDS 不会帮助组织发现令人惊讶的洞察力,或者“未知的未知”

在分析过程中,您可以向数据提出三种类型的问题:

  • “已知的已知”:什么是我们已经知道的,我们想要验证或定期跟踪的洞察力?
  • “已知的未知”:有哪些我们知道自己不知道的因素,需要我们去调查?
  • “未知的未知”:有哪些我们尚未意识到的隐藏见解可能会提供机会?

虽然发现“已知的已知”和“已知的未知”的能力在帮助公司建立数据驱动的行动和调查流程方面至关重要,但发现未知的未知的能力被认为是分析可以提供的最有价值的见解。

这是因为发现“未知的未知”的能力可以为您的公司提供超越竞争对手的分析优势,并为您提供竞争对手不知道的独特信息和模式。

Google Data Studio 的可视化和仪表板功能使组织能够回答“已知已知”级别(通过仪表板和主动监控)和“已知未知”级别(通过提供数据可视化工具)的问题。然而,它不能提供发现“未知的未知”洞察力的能力。

本质上,需要丰富的数据分析经验和时间来发现“未知的未知”分析师不仅需要使用多个维度快速分割数据,还需要有统计敏锐度来识别数据中的异常。

此外,随着更多的维度被添加到分析中,所需的分析工作量也呈指数级增长。

例如,如果您想要通过流量来源确定跳出率,您可能只需要进行 3 次分析,但如果您想要通过流量来源和地理来源确定跳出率,您将需要 5*5 = 25 次分析,并且随着您添加更多维度,复杂性只会呈指数级增加。

渐渐地,从人力和经济上来说,进行分析来揭示所有相关的“未知的未知”变得不可能,而 Google Data Studio 并没有充分缓解这种分析压力,使其在经济上可行。

3.尽管 GDS 可以帮助企业监控和跟踪指标,它并没有告诉你如何首先识别和选择好的指标来跟踪

Google Data Studio 的交互式仪表盘和数据可视化功能使用户能够几乎实时地跟踪重要指标,并将这些分析结果传达给整个团队。

这种度量跟踪和监控功能对于许多企业来说非常重要,因为它可以为他们的业务活动提供实时反馈,并使他们能够快速迭代和调整他们的策略。

然而,虽然跟踪指标很重要,但我们采访的许多中小型企业都很难首先提出这些指标。

这是因为提出好的指标非常困难,需要丰富的行业经验和良好的分析能力。

通常,好的指标需要具有可比性、可理解性、相关性和可操作性。它们还需要足够精细以捕捉真实信息,并且足够简洁以避免因分析而瘫痪(我在本文的中谈到了选择好的度量标准)。

除了这些标准之外,企业还需要在度量选择过程中避免“度量陷阱”,如“虚荣度量”(没有上下文的度量)和“错误度量”(没有反映业务目标的度量)。

此外,因为只建议企业一次跟踪大约 10 个指标,所以即使一个错误的指标也会严重损害公司的决策过程。这反过来会侵蚀数据驱动的决策文化中的信任。

对于没有经验丰富的分析人才的中小型企业来说,通常很难在第一时间选择好的指标供 Google Data Studio 跟踪。因此,在这一领域,GDS 工具在帮助这些公司采用分析方面再次表现不佳。

在本文中,我们研究了 Google Analytics 无法帮助企业解决的一些重要商业问题。

然而,本文的目的绝不是批评谷歌数据工作室,而是指出一个事实,即它不应该被视为商业中所有分析问题的“万灵药”。

在我看来,Google Data Studio 并没有让中小型企业的分析变得更容易,而是让营销分析师和分析机构的数据分析和可视化变得更容易。

事实上,我们唯一一次与对 Google Data Studio 非常感兴趣的受访者交谈的是那些喜欢将自己的发现传达给客户的顾问。

这里的问题是,数据顾问通常为大型企业提供良好的服务,这就是为什么他们不断与大型企业签订合同。但我们不要忘记中小企业,它们提供了我们国家 55%的工作岗位,是我们经济的支柱。他们通常没有钱或资源来雇佣数据科学家或顾问团队。

在中小型企业能够理解他们可以通过跟踪已知信息、测试已知未知信息和发现未知未知信息从数据中提取的可操作的业务洞察力之前,我们还有很长的路要走…

在 Humanlytics,我们希望为中小型企业打造一款工具,不仅能帮助他们回答业务问题和实时跟踪指标,还能告诉他们应该问什么问题,并教他们如何实施解决方案。

如果你对更多类似的内容感兴趣,请关注数据科学。请在 媒体上关注我们 ,或者在 推特*【脸书 上关注我们。如果你对这篇文章有任何问题,请随时给我发电子邮件,地址是 bill@humanlytics.co。*

GAMEBOY 超级电脑

原文:https://towardsdatascience.com/a-gameboy-supercomputer-33a6955a79a4?source=collection_archive---------6-----------------------

每秒超过 10 亿帧的总速度可以说是世界上最快的 8 位游戏主机集群。

Distributed Tetris (1989)

1 of 48 boards of IBM Neural Computer which was used for experiments

怎么建一个?

食谱

拿一把硅,倒强化学习知识、超算经验和计算机架构激情,然后加上汗水和泪水,最后搅拌大约 1000 小时,直到沸腾瞧吧……

为什么会有人想要一个呢?

简答:向强人工智能迈进。

这是更长的版本:

现在是 2016 年。深度学习无处不在。图像识别可以被认为是由卷积神经网络解决的,我的研究兴趣被吸引到具有记忆和强化学习的神经网络。

具体来说,在 Google Deepmind 展示的一篇论文中,已经表明使用一种叫做 Deep Q-Neural Network 的简单强化学习算法,在各种 Atari 2600(1977 年发布的家用游戏机)游戏上实现人类甚至超人级别的性能是可能的。所有这些都是通过观察游戏来完成的。这引起了我的注意。

[## 通过深度强化学习实现人类水平的控制

一个人工智能体被开发出来,它可以直接从电脑上学习玩各种经典的 Atari 2600 电脑游戏

www.nature.com](https://www.nature.com/articles/nature14236)

One of the Atari 2600 games, Breakout. Trained using a simple RL algorithm. After millions of iterations, the computer agent plays at a super-human level.

我开始在雅达利 2600 游戏上运行实验。虽然令人印象深刻,但《T21》并不是一个复杂的游戏。人们可以通过将你的行动(操纵杆)与结果(得分)联系起来的难度来定义复杂性。当人们需要等待很长时间才能观察到效果时,问题就出现了。

An illustration of the problem with more complex games. LEFT: Breakout (ATARI 2600) is very reactive, we get feedback very quickly; RIGHT: Mario Land (NINTENDO GAMEBOY) does not provide immediate information about consequences of an action, there can be stretches of irrelevant observations between important events

为了让学习更有效率,你可以想象尝试从简单的游戏中转移一些知识。这是目前尚未解决的问题,也是一个热门的研究课题。OpenAI 最近发布的一项挑战试图测量这一点:

[## OpenAI 复古大赛

OpenAI 是一家非营利性的人工智能研究公司,旨在发现和制定通往安全人工智能的道路。

contest.openai.com](https://contest.openai.com/2018-1/)

拥有迁移学习能力不仅会使训练更快,而且我甚至认为,除非有一些先验知识,否则有些问题是无法解决的。你需要的是数据效率。让我们来看看波斯王子:

A short clip from Prince of Persia

  • 没有明显的分数
  • 如果不执行任何操作,需要 60 分钟才能结束游戏(动画中还剩 58 分钟)。

Random actions

你能尝试和 Atari 2600 论文中完全一样的方法吗?如果你想一想,你随机按键到达终点的可能性有多大?

这激励我通过解决这个问题来为社区做贡献。所以,从本质上说,这是一个先有鸡还是先有蛋的问题——你需要一个更好的算法来传递知识,但这需要很长时间的研究和实验,因为我们没有更有效的算法。

Transfer learning example: Imagine first learning a very simple game, such as the one on the lefthand side, then you preserve concepts such as ‘race’, ‘car’, ‘track’, ‘win’, and learn colors or 3D models. We say that the common concepts are ‘transferrable’ between those games. One could define similarity by the amount of transferrable knowledge between two problems. I.e. Tetris and F1 racing will not be similar.

我决定退而求其次,通过让环境变得更快来避免最初的减速。我的目标是:

  • 更快的环境(想象你可以用 1/100 的时间完成波斯王子)同时运行 100,000 个游戏
  • 更好的研究环境(关注问题,但不做预处理,有各种游戏)

最初,我认为性能瓶颈可能在某种程度上与模拟器代码的复杂性有关(例如 Stella 的代码库相当大,而且它依赖于 C++抽象,这对于模拟器来说不是最佳选择)。

控制台

Arcade Space Invaders

总的来说,我在几个平台上工作过,从可能是有史以来最早的游戏之一(和 Pong 一起)——街机“太空入侵者”、Atari 2600、NES 和 Gameboy 开始。所有用 c 写的。

我能观察到的最大帧速率大约是 2000-3000 FPS。为了开始看到实验结果,我们需要数百万或数十亿帧,所以差距是巨大的。

My Space Invaders running inside an FPGA — low speed debug mode, the counter in the FPGA shows clock cycles elapsed

我想——如果我们可以对这些环境进行硬件加速会怎么样。例如,最初的太空入侵者运行在 1MHz 的 8080 CPU 上。我能够在 3GHz Xeon 上模拟 40MHz 8080 CPU。还不错,但作为概念验证,一旦放入 FPGA,它就能达到 400 MHz。这意味着单个实例可以达到 24000 FPS,相当于 30GHz 的至强 CPU!我有没有提到一个可以在中间层 FPGA 中安装大约 100 个 8080 CPU 的处理器?也就是 2.4M FPS。

Hardware-accelerated Space Invaders, 100MHz, 1/4 of the full speed

Over one hundred tiny cores inside one Xilinx Kintex 7045 FPGA (bright colors, the blue patch in the middle is shared logic for display)

Irregular Execution Path

此时,你可能会问,GPU 呢?简而言之,你需要 MIMD 式的平行,而不是 SIMD 式的。在学生时代,我花了一些时间在 GPU 上实现蒙特卡罗树搜索(AlphaGo 中使用了 MCTS)。

http://olab . is . s . u-Tokyo . AC . jp/~ kamil . rocki/rocki _ IP dps 11 . pdf

当时我花了无数个小时试图让 GPU 和其他种类的 SIMD 硬件(IBM Cell、Xeon Phi、AVX CPU)高效运行这类代码,但都失败了。几年前,我开始相信,如果我能设计出自己的硬件,来解决类似的问题,那就太好了。

Multiple Instruction Multiple Data (MIMD) Parallellism

雅达利 2600,NES 还是 GAMEBOY?

总之,我用《太空入侵者》、《NES》、《2600》和《游戏男孩》实现了 8080。这里有一些事实和他们各自的优势。

NES Pacman

太空入侵者只是一个热身。我们让它工作,但它只是一个游戏,所以它不是很有用。

Atari 2600 是强化学习研究的事实标准。CPU (MOS 6507)是著名的 6502 的简化版本,它的设计更优雅,比 8080 更高效。我没有选择 2600,只是因为我认为它在游戏和图像方面有一定的局限性。

我实现了 NES(任天堂娱乐系统)以及,它与 2600 共享 CPU。游戏比 2600 上的好多了。NES 和 2600 都受到过于复杂的图形处理管道和许多需要支持的墨盒格式的困扰。

与此同时,我重新发现了任天堂 Gameboy。这就是我一直在寻找的东西。

game boy 为什么这么牛逼?

1049 Classic games + 576 for Gameboy Color

  • 总共超过 1000 个游戏(经典+彩色),范围非常广,都是高质量的,其中一些非常具有挑战性(王子),游戏可以进行某种程度的分组,并为迁移学习和课程学习的研究分配难度(例如,有俄罗斯方块、赛车游戏、Marios 的变体)。试图解决波斯王子可能需要从其他类似的游戏中转移知识,这些游戏有明确的分数(王子没有!)

Nintendo Gameboy is my transfer learning research platform of choice. In this chart I tried to group the games and plot them according to their difficulty (subjective judgement) and their similarity (concepts such as racing, jumping, shooting, variety of Tetris games; Has anyone ever played HATRIS?).

  • Gameboy classic 有一个非常简单的屏幕(160×144 2 位颜色),这使得预处理更简单,我们可以专注于重要的事情。在 2600 的情况下,即使是简单的游戏也有各种颜色。除此之外,Gameboy 有更好的显示物体的方式,所以不需要闪烁或最多连续几帧。

IBM Boot ROM + Super Marioland

  • 没有像 NES 或 2600 案件中那样疯狂的记忆地图绘制者。你可以用总共 2-3 个地图绘制者来完成大部分游戏工作。
  • 它被证明是非常紧凑的,总的来说,我能够用不到 700 行代码完成 C 仿真器,用大约 500 行代码完成我的 Verilog 实现。
  • 它带有与街机版相同的简单版《太空入侵者》

Gameboy version of Space Invaders — Basically no preprocessing needed!

这就是我 1989 年的点阵游戏机,以及在 4K 屏幕上通过 HDMI 运行的 FPGA 版本。

这是我以前的游戏机做不到的:

Hardware accelerated Tetris, this is a realtime screen recording at 1/4 the max speed.

实际有用吗?

是的,它是。到目前为止,我已经在一个简单的环境中测试过了,那里有一个外部策略网络,它与 Gameboy 的工作人员进行交互。更具体地说,我使用了分布式 A3C(优势行动者评论家)算法,我将在另一篇文章中描述这一部分。我的一个同事也将它连接到 FPGA convnet,它工作得相当好。更多将在即将到来的职位。

FPGA-NN communication

Distributed A3C setup

Mario land: Initial State. Pressing buttons at random does not get us far. Top right corner shows remaining time. If we get lucky and Goomba, we finish quickly as we touch Goomba. If not, it takes 400 seconds to ‘lose’.

Mario land: after less than 1 hour of gameplay, Mario has learned to run, jump and even discovers a secret room by going into a pipe.

Pac Man: after about one hour of training it can even finish the entire game once (eats all dots), then the games starts all over again.

结论

我喜欢将未来十年视为 HPC 和 AI 最终走到一起的时期。我希望硬件有一定程度的定制允许,这取决于人工智能算法的选择。

The Next Decade

这里的国标 C 码【https://github.com/krocki/gb

奖金 A —调试

这一部分可能值得单独写一篇文章,但是现在,我太累了。

经常有人问我:最难的部分是什么?一切……都很痛苦。一开始就没有 gameboy 的规范。我们所知道的一切都是逆向工程的结果,我的意思是:运行一些代理任务,如游戏或任何其他片段,并观察它是否执行。这与标准的软件调试非常不同,因为在这里执行代码的硬件被调试。我必须想出一些方法来完成这个过程。我有没有提到当它运行在 100MHz 时很难看到一些东西?哦,没有指纹。

One approach to implementing the CPU is to group instructions into some clusters which do more or less the same thing. This is much easier with 6502. LR35092 has much more random stuff and many edge cases. Here is the chart which I used while I worked on the Gameboy CPU. I adopted a greedy strategy of taking the largest chunk of instructions, implementing it and then crossing it out, then repeat. In this case 1/4 of the instructions are ALU, 1/4 are register loads which can be implemented relatively quickly. On the other side of the spectrum, there are some outliers such as load from HL to SP, signed which need to be handled separately

Debugging: you run a piece of code on the hardware you are debugging, record a log for your implementation and some other reference implementation (here I compared Verilog code, left vs my C emulator, right). Then you run diff on the logs to identify discrepancies (blue). One reason for using some automated way is that in many cases I found problems after millions of cycles of execution, where a single CPU flag caused a snowball effect. I tried many approaches and this seemed to be one of the most effective ones.

You need coffee! Lots of it.

These books are 40 years old — It’s incredible to go through them and see the world of computers through the eyes of the users then. I felt like a visitor from the future.

奖金 B——开放式研究申请

最初我想从内存的角度来看游戏,就像 OpenAI 在这篇文章中描述的那样。

[## 研究请求

关注的序列对序列模型取得了巨大的成功。他们使得神经网络成为可能…

openai.com](https://openai.com/requests-for-research/#q-learning-on-the-ram-variant-of-atari)

令人惊讶的是,当输入为 RAM 状态时,让 Q-learning 正常工作具有意想不到的挑战性。

该项目可能无法解决。如果事实证明 Q-learning 在 Atari 的 RAM 变体上永远不会成功,那将是令人惊讶的,但它有一些机会将被证明是具有挑战性的。

鉴于 Atari 游戏只使用 128B 的内存,处理这些 128B 的内存而不是整个屏幕帧是非常有吸引力的。我得到了不同的结果,所以我开始深入调查。

虽然我不能证明直接从记忆中学习是不可能的,但我可以证明,记忆捕捉游戏的整个状态的假设是错误的。Atari 2600 CPU (6507)使用 128B 的 RAM,但它也可以访问独立电路中的额外寄存器(电视接口适配器,类似于 GPU)。这些寄存器用于存储和处理关于物体的信息(桨、导弹、球、碰撞)。换句话说,当只考虑 RAM 时,这将不可用。同样,NES 和 Gameboy 有额外的寄存器用于屏幕操作和滚动。RAM 本身并不能反映游戏的完整状态。

只有 8080 以直接方式将数据存储到 VRAM 中,这将允许检索整个状态。在其他情况下,“GPU”寄存器插在 CPU 和屏幕缓冲区之间,在 RAM 之外。

琐事:如果你正在研究 GPU 的历史,这可能是第一个“图形加速器”——8080 有一个外部移位寄存器,使用单个命令移动入侵者,卸载 CPU。

参考

[## 我做了一个 NES 模拟器。以下是我对最初的任天堂的了解。

关于 NES 有趣的技术花絮…

medium.com](https://medium.com/@fogleman/i-made-an-nes-emulator-here-s-what-i-learned-about-the-original-nintendo-2e078c9b28fe) [## 为什么我花了 1.5 个月的时间创建一个 Gameboy 模拟器?托梅克的博客

后来我意识到这并不完全正确——创建一个工作程序是一个相当大的挑战。同时…

博客. rekawek.eu](https://blog.rekawek.eu/2017/02/09/coffee-gb/) [## 深度强化学习:来自像素的 Pong

一位计算机科学家的思考。

karpathy.github.io](http://karpathy.github.io/2016/05/31/rl/)

还有更多…

Gameboy 和 NES 是任天堂的注册商标。

文件结束

一种利用 2D 目标检测进行人脸识别的通用方法

原文:https://towardsdatascience.com/a-general-approach-for-using-2d-object-detection-for-facial-id-b5dc816a970?source=collection_archive---------12-----------------------

有几种技术可以利用计算机视觉进行面部识别。在这个场景中,我们演示了一种通过面部识别来识别感兴趣的人的方法。有多种方法可以实现积极的身份识别。深度学习可用于映射和识别人脸的三维平面。或者,也可以应用聚焦在人脸上的 2D 对象检测技术。前者需要大规模扫描的 3D 人脸,这是非常昂贵的,需要目前正在研究和开发的技术,并达到远低于 80%的精度水平。用这种方法看到成功将是困难的、不确定的和昂贵的。我们认为这种方法不太实际。后者(2D 物体探测技术)需要高分辨率的照片作为数据集,这可以通过高质量的相机来实现。2D 深度学习技术,卷积神经网络(CNN)今天被应用于各种类型的识别。利用 2D 面部识别技术来识别感兴趣的人是可行的,可以实现高度的准确性(80%以上),并且减少了总的技术债务。我们建议开发一个 2D 面部识别模型原型,作为一个实用的方法,积极的面部识别感兴趣的人。

一般方法:

数据是关键。最初,您需要评估和绘制数据采集过程和数据结构(例如,使用什么相机,照明如何,照片中通常出现多少人)。基于以上所述,您应该收集速度和准确性要求,建立什么被认为是“可接受的”。然后,评估并记录硬件限制。

一旦正确的评估完成,开始并建立使用系统的 UI/UX 流程,并定义 API 端点。建立视频/照片和标签的数据收集系统。然后将数据集解析成训练、验证和测试桶。需要开发适当的数据预处理管道来减少图像和视频数据中的模糊和噪声。

构建深度学习算法(CNN)或将迁移学习应用于现有模型;接受过特定人脸检测、嵌入和分类模型的培训。在开发了核心人脸检测和识别模型之后,您将需要开发一个跟踪模型来跟踪整个视频中的多个对象。

最后,集成和服务于模型的数据库和后端将被开发。需要定义和实现一个人在回路中的过程来持续改进模型。

型号选择/开发:

我们建议从人脸检测、关键点提取、对齐和嵌入的开源解决方案开始。这允许对感兴趣的应用的现有技术进行快速评估,并通知我们集中改进建模技术或数据采集的方向。然后,收集带标签的图像或视频,并标注人脸边界框和身份。

通过进一步的特征工程和超参数调整来调整所选模型。然后,测试系统并找出系统故障所在。一旦选择了模型,您将需要为重新培训、测试、部署和监控计划创建一个计划。

技术推荐:

对于人脸检测和识别模型,我们建议使用卷积神经网络(例如 ResNet)作为主干。对于人脸检测损失函数,我们推荐使用 SSD 损失(交叉熵和回归损失)。人脸嵌入模型的损失函数有多种选择:

  • 交叉熵损失
  • 三重损失
  • 中心损失

对于关键点提取,我们建议使用回归损失。

当然,你需要训练数据。这可能是一个挑战。为了达到高水平的准确性,您将需要标记的训练数据(1 到 1000 万张脸)。

人脸检测

给定一幅图像,我们需要检测人脸所在的像素区域。下面是一个例子,我们的工作中,面部检测显示。

输入:图像

输出 : 1)包含正面或稍微侧面的面的边界框(上、左、下、右);2)对应于眼睛、鼻子和嘴的面部上的关键点

采用多路最先进的卷积神经网络进行计算。

面部对齐

使用面部关键点对图像执行 2D 变换,使眼睛和月份处于大致正常的位置。

输入:检测到人脸的裁剪图像块

输出:面部对齐的图像补片

人脸嵌入(描述符)

输入:裁剪后的人脸图像补丁

输出:描述人脸的向量

人脸嵌入模型将是一个卷积神经网络。它可以基于预先训练的模型(例如:最初用于分类 1000 个对象类别-例如猫和狗)。执行迁移学习,并使用交叉熵损失或三重损失(在最近的文献中提出了新的损失)在我们的面部匹配数据集上微调模型。

图上的人脸聚类

嵌入的面部描述符存在于向量空间中。在这个向量空间中两个面的距离表明它们是多么不同。在由面部向量之间的这些成对距离指定的面部图上执行聚类算法。每个聚类包括很可能是同一个人的面部。

输入:人脸描述符

输出:人脸聚类,每个人脸聚类是一组很可能属于同一个人的人脸。

项目流程图:

预处理和标准化

需要带标签的训练数据来提供照片、人脸的带标签的边界框以及每个边界框的身份(人名或 ID)。标签需要组织成一种易于使用的格式,比如 PASCAL VOC 格式。对于原型的范围,我们将假设数据可用性和结构。

部署后改进系统

构建一个人在回路中的组件,该组件审核生产中的模型,并标注边界框和人员身份的正确标签。这包括开发一个批量训练过程,不断吸收新的训练数据。

这个人在回路组件的目的是扩大已知人脸和嵌入向量的数据库。他们会尝试在照片中加入不同的光线,不同的角度,不同的玻璃等等。提高在新照片中认出那个人的回忆率。

准确性取决于 1:N 人脸比较的干扰物比率(每个查询人脸的干扰物数量)。在 mega face(N = 100 万)上,最精确的系统可以达到大约 30%的精度。在 1:1 人脸比对上,可以达到 99%+的准确率。

潜在挑战:

用于培训和验证的图像质量将阻碍项目的成功:

  • 光线太弱或太强。
  • 低分辨率。
  • 运动模糊。
  • 鱼眼相机。

复杂的场景提供了额外的噪声,影响了准确识别面部的能力。例如,拥挤的场景和来自其他对象的遮挡必须被隔离。

此外,数据大小可能会成为技术基础架构和资源的负担。数千万张照片产生了海量数据。这对于有限的计算资源是有问题的,并且会产生长的训练周期。这导致了缓慢的迭代。

硬件提供了约束。如果模型部署在“边缘”(例如,在 Raspberry Pi 或移动电话上)而不是云实例上,则只能使用模型的一小部分。大量使用可能会有问题。如果许多相机数据流同时消耗 API,那么对面部识别 API 的请求会淹没计算能力。

会有速度限制。如果需要模型来生成实时预测,这就限制了可以使用的模型的大小和类型。

克服挑战:

图像质量

使用高质量和高分辨率的相机;安装摄像机的方式应能获得最佳的角度、距离和照明。

复杂场景

对模型的局限性设定期望。关注确定最高价值目标的更窄的用例。

数据大小

可能需要更多计算资源。我们将开发一个更好的分布式模型训练算法来减轻资源的负担。

高用量

在模型部署期间提供足够的机器资源。

培训流程:

首先,需要将数据收集到对象存储中的一个桶中(例如 AWS S3)。使用 TensorFlow/PyTorch/Caffe 框架开发培训管道。则需要供应 GPU 资源。一旦模型被训练,模型工件和度量就被持久化到对象存储中。

在模型训练期间,我们建议执行连续的超参数调整。我们调整的 nob 包括但不限于:

  • 主干架构:VGG,雷斯网,DenseNet,MobileNet,NASNet。
  • 学习率调度。
  • 批量大小。

可能需要分布式培训。如果图像数量超过数百万,通常需要在多个 GPU 实例上进行分布式训练。我们推荐 Horovod(来自优步)。

虽然 3D 面部识别是一个可行的解决方案,但它并非没有挑战。它的计算成本很高,当前的精度基准对许多应用来说可能太低。人脸识别的 2D 对象检测应该足以处理大多数用例。以上提供了许多方法中的一种。我们鼓励其他人分享他们的!

功夫。AI 是一家人工智能咨询公司,帮助公司建立他们的战略,运营和部署人工智能解决方案。请点击 查看 www.kungfu.ai

R 中整洁统计的简明指南(第 1 部分)

原文:https://towardsdatascience.com/a-gentle-guide-to-statistics-in-r-a1da223e08b7?source=collection_archive---------3-----------------------

While data analysis in R can seem intimidating, we will explore how to use it effectively and clearly!

介绍

Jesse Maegan 在 Twitter 上提出了以下问题,并在 R 频谱的所有点上与#RStats 用户展开了一场大讨论。

许多人加入进来,提出了缺少详细插图的包、使用其他编程语言的社会团体的影响、难以找到与你相关的例子、需要更多关于大学编程与统计的指导,以及许多其他主题。

两条推文给我留下了深刻的印象,与我在 r 中的第一个需求非常相似。关于您感兴趣的主题的多元和描述性统计!对于我们许多从事科学研究的人来说,通过 ANOVAs 和线性回归/相关性以及简单的总结(描述性统计)进行的均值测试将解决我们的许多问题。

然后,David 带来了一个很好的观点和视角,他是一个需要指导学生/同事的人,这些学生/同事表达了使用 R 的需求,但在数据科学的背景下没有 R 的需求或愿望。对于局外人来说,R 的编码本质可能是令人生畏的,让你看起来好像是在“矩阵”中执行数据分析

我肯定去过那里,还没有找到一个坚实的例子走过多变量 ANOVAs,后 hocs,绘图,和描述性统计。基本上是一个完整的 R 语言数据分析的例子,但用于学术用途。

所以我告诉大卫我会写一篇博客,我们开始吧!

如果你觉得打开和使用 R Studio 很舒服,请随意跳到第二部分!里面有所有的统计数据和图表!

We’ll get here eventually I promise!

R/R 工作室

我将大量借用切斯特·伊斯梅和艾伯特·金的精彩电子书《T4 现代潜水》。如果你对如何使用 R 感兴趣,他们的电子书是最好的之一,而且还是免费的!

如果你需要安装 R,请参见他们关于下载和安装 R and R 工作室的章节。

现在开始使用 R Studio!打个电话的比方,R 是运行你手机的电脑,而 R Studio 是主屏幕。R Studio 提供了交互的接口,告诉 R 做什么。R 分为 4 个主要部分,左边是 R 脚本(在这里输入代码)和 R 控制台,而右边是环境和文件/图/包部分。

Source: Grolemund & Wickham — R for Data Science

继续进行电话类比,我还想介绍一下。软件包类似于手机上的应用程序。虽然你的手机/R 可以做很多开箱即用的事情,但应用程序/软件包增加了功能!要在 R 中安装这些“应用”,我们需要先明确告诉 R 安装包!

要开始用 R 编写代码,首先同时输入“ctrl + shift + N”。这将打开一个新的 R 脚本,基本上是一个文件,您可以在其中保存键入的 R 代码和您对正在做的事情的评论。或者,您可以单击左上角的绿色“+”并从下拉菜单中选择 R Script。

在那里,您可以安装我们进行这些分析所需的一个包。首先在新的 R 脚本中键入以下代码,然后在光标停留在同一行的同时单击 ctrl + enter。不管包的名字是什么,我们都需要用" "

install.packages("tidyverse")

这将首次将感兴趣的软件包安装到您的计算机上。您不需要再次安装它,除非您希望在将来下载更新的软件包。

每当你启动 R Studio 时,你也需要加载这个包。这就相当于在手机上打开一个 app!它将加载额外的功能,并允许您通过键入代码来调用它们。

library("tidyverse")

在您的脚本/分析的顶部加载包是一个好主意,因此很清楚需要什么包!我们还可以在笔记上添加注释,记录我们正在做的事情以及我们为什么要这么做!R 中的注释可以在你的注释前加一个#形成。这个#告诉 R 不要“读取”同一行上的任何内容,防止它在试图读取您的精彩评论时向您抛出错误!

# Adding the hashtag/pound sign tells R to not evaluate this line

不涉及太多细节,tidyverse包为我们提供了一个优雅的描述性统计、漂亮的出版级图表的选项,并使我们的代码更具可读性!

我想介绍的下一个概念是赋值操作符

<-

这告诉 R 你正在把右边的所有东西分配给左边的对象。让我们将变量x赋值为 5,y赋值为 6,然后做一些基本的数学运算。

x <- 5
y <- 6
x * y# output
>[1] 30

您可以在 R 中做同样的事情,一旦您运行了x * y代码,您将看到 30 在输出控制台中弹出!恭喜你写出了你的第一个代码!

我们将跳过前面的部分,直接进入分析的开始部分。如果你想了解更多关于 R 的基础知识,我再次建议你去看看Modern Dive——R 的统计介绍。此外,www.datacamp.com有很多与 R 相关的免费内容,而且经常打折!

继续第二部分!

R 中整洁统计的简明指南(第 2 部分)

原文:https://towardsdatascience.com/a-gentle-guide-to-statistics-in-r-ccb91cc1177e?source=collection_archive---------1-----------------------

While data analysis in R can seem intimidating, we will explore how to use it effectively and clearly!

第 1 部分让您踏上用 R 代码运行统计数据的旅程。

介绍

在 Jesse Maegan ( @kiersi )在 Twitter 上发起了一场大讨论之后,我决定发布一些(伪造的)实验治疗数据。这些数据与一种名为 AD-x37 的新(假)研究药物相对应,AD-x37 是一种理论药物,已被证明对阿尔茨海默病小鼠模型的认知衰退具有有益的结果。在目前的实验中,我们将对药物在减少痴呆患者的认知障碍方面是否有效进行统计测试。此处见数据。

我们将使用 MMSE(简易精神状态测验)分数来评估认知障碍的程度。在真正的临床试验中,会记录许多其他变量,但为了一个简单但多变量的例子,我们将只关注 MMSE。

Source: Folstein et al, 1975 — J Psychiatr Res 12:189–198

我们将通过tidyverse加载、绘制、分析和保存我们的分析输出,这是一个为数据分析而设计的“R 包的自以为是的集合”。我们将把依赖性限制在两个包中:tidyversebroom,而对其余的包使用基数 R。在我看来,这两个包极大地改进了数据分析工作流程。虽然其他侧重于统计的包提供了额外的统计测试,但 base R 有相当好的能力来执行开箱即用的统计分析。我将使用knitr::kable为 markdown 文档生成一些 html 表格,但是对于工作流来说这不是必需的。

此外,我将上传本例中使用的 excel 表,以便您可以自己重新创建工作流程。您可以简单地复制粘贴此处看到的代码,它将在 R 中运行。如果您希望在 R-Markdown 文档中看到整个工作流,请参见此处的。R Markdown 是在 R 内部创建的一个文档,它允许您编写代码、内联执行代码,并在编写过程中编写注释/笔记。你可以把它想象成能够在一个基本的 Word 文档中编写 R 代码(但是它能做的远不止这些!).

虽然您可能对我提供的数据集不感兴趣,但这有望为您提供一个清晰的工作流程,让您可以交换感兴趣的数据并完成基本分析!

装载扫把、扫帚和编织机

使用库函数,我们将加载tidyverse。如果您以前从未安装过它,您也可以使用install.packages("tidyverse")调用来首次安装它。这个包包括ggplot2(图形)、dplyr / tidyr(汇总统计、数据操作)、和readxl(读取 excel 文件)以及管道%>%,这将使我们的代码更具可读性!我们还将加载broom包来整理我们的一些统计输出。最后,我们将通过knitr::kable,加载knitr来制作漂亮的 html 表格,但不需要简单地将输出保存到 Excel。

# Load libraries
library(tidyverse)
library(broom)
library(knitr)
library(readxl)

这将输出一些关于正在加载的包和任何函数调用冲突的消息。

加载数据

当我呼叫readxl::read_xlsx时,您也可以简单地使用read_xlsx, ,但是为了透明起见,我将使用完整的呼叫开始。使用::调用函数的概念很重要,因为一些包在函数上有冲突,例如多个包包括函数selectsummarize。这样,我们可以明确我们希望 R 从哪个包中调用我们的函数,所以package::function!要了解更多关于调用函数时“名称空间”的概念,请查看这里。

readxl 很不幸是一个有趣的例子,因为安装tidyverse 会安装readxl,但是通过library 调用加载tidyversereadxl 不会被加载。因此,我们必须像加载任何其他包一样加载readxl ,或者像readxl::read_xlsx. readxl 中允许我们读取的那样调用包和名称。xls,。或者,您可以将您的 Excel 表转换为。csv,可以通过read_csv()读取。通过使用来自dplyrglimpse函数,我们可以看到变量是如何导入的,以及前几行。

# Read excel file
raw_df <- readxl::read_xlsx("ad_treatment.xlsx")
dplyr::glimpse(raw_df)# this is the output from glimpse(raw_df)
Observations: 600
Variables: 5
$ age            <dbl> 80, 85, 82, 80, 83, 79, 82, 79, 80, 79, ...
$ sex            <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, ...
$ health_status  <chr> "Healthy", "Healthy", "Healthy", ...
$ drug_treatment <chr> "Placebo", "Placebo", "Placebo", ...
$ mmse           <dbl> 24.78988, 24.88192, 25.10903, 23.38...

我们现在可以收集一些关于数据集的信息。也就是说,我们有 3 个分类/因素变量:性别、健康状况和药物治疗以及 1 个因变量(DV): mmse。我们也有年龄,但重要的是它被记录为一个离散的数字,而不是一个因素(如 85 岁,而不是老)。因此,我们可以考虑年龄,但我们不会把它作为方差分析的一个因素。

检查数据分布

我们将使用第一个ggplot2调用来创建一个显示年龄分布的图表。为了分解我们正在做的事情,我们需要调用 ggplot,告诉它使用什么数据,并使用aes 或“美学”调用来分配 x 坐标。然后我们添加一个+ ,告诉 ggplot 包含下一行代码。geom_density告诉 R 我们想要创建一个密度分布层,我们想要fill用蓝色!关于ggplot2的更多信息,请点击此处或此处。

ggplot(data = raw_df, aes(x = age)) + 
 geom_density(fill = "blue")

图表显示,年龄实际上只在 79-85 岁之间,而且实际上不存在年龄过高或过低的情况。我们可以通过一个dplyrsummary 调用或通过调用 base R 中的range来确认年龄范围 s。顺便提一下,我们现在可以讨论使用管道或%>%.管道将结果或数据从它的左边传递到右边。有关该管道的更多信息,请参见这里。

我们可以把下面的代码理解为取raw_df,然后通过取age变量的minmaxsummarize它。现在,因为我们从raw_df开始,R 知道我们想要从这个数据帧中取出列age

raw_df %>% summarize(
 min = min(age), 
 max = max(age))# A tibble: 1 x 2
    min   max
  <dbl> <dbl>
1  79.0  85.0

或者,我们可以使用 base R range函数,这需要使用$。美元符号表示 R 应该使用来自raw_dfage列。这两个函数给我们的结果是一样的,最小数和最大数。

range(raw_df$age)[1] 79 85

有关使用这两种语法的更多信息,请点击这里或者查看备忘单这里。

实验变量水平如何?

现在,虽然我非常清楚这个数据框架中的变量,但你可能不会不探索它!为了快速确定drug_treatment组、health_status组以及它们如何交互,我们可以做一个table调用。通过在drug_treatmenthealth_status上调用它,我们得到了一个很好的表格,它分解了每个变量组中有多少行。

table(raw_df$drug_treatment, raw_df$health_status)#output below Alzheimer's Healthy
  High Dose         100     100
  Low dose          100     100
  Placebo           100     100

或者,我们可以用下面的代码在dplyr中做同样的事情。

raw_df %>% 
  group_by(drug_treatment, health_status) %>% 
  count()

现在我们知道了我们感兴趣的变量的水平,并且每个整体治疗组有 100 名患者!

因变量的数据探索

在运行我们的汇总统计数据之前,我们可以通过一个geom_boxplot调用来可视化范围、集中趋势和四分位数。

ggplot(data = raw_df, # add the data
       aes(x = drug_treatment, y = mmse, # set x, y coordinates
           color = drug_treatment)) +    # color by treatment
  geom_boxplot() +
  facet_grid(~health_status) # create panes base on health status

我们将健康和阿尔茨海默病患者的数据分成单独的图形面(或窗格),并按药物治疗分成每个面内的组。这个图表告诉我们一些有趣的事情。看起来我们的(假的)神奇药物确实有效果了!让我们用描述性统计来探讨这个问题。

虽然这是一个探索性的图表,我们不一定要将其“调整”到完美,但我们可以注意到,我们的药物治疗应该是安慰剂< Low dose < High Dose and we should have Healthy patients presented first, and Alzheimer’s patients second. This is something we can fix in our next section!

汇总统计

我们希望生成 mmse 分数的平均值和标准误差,这对于测量集中趋势和创建我们的最终出版图表是有用的。我们有性别、药物治疗和健康状况的分类变量。然而,回到我们之前的glimpse调用,我们可以看到数据没有被正确“编码”。即性是一个dbl(数字),没有描述性名称,health_status / drug_treatmentchr(人物)!这些都需要换算成因子!

Observations: 600
Variables: 5
$ age            <dbl> 80, 85, 82, 80, 83, 79, 82, 79, 80, 79, ...
$ sex            <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1...
$ health_status  <chr> "Healthy", "Healthy", "Healthy", ...
$ drug_treatment <chr> "Placebo", "Placebo", "Placebo", ...
$ mmse           <dbl> 24.78988, 24.88192, 25.10903, 23.38...

我们可以使用dplyr::mutate函数告诉 R 我们想要改变(突变)感兴趣的变量中的行。因此,我们将获取sexdrug_treatmenthealth_status 列中的数据,并将它们从数字或字符转换成因子变量!dplyr::mutate还可以表演数学,以及许多其他有趣的事情。更多信息,请参见此处。

我们将使用mutate 函数和基数 R factor函数将我们的变量转换成适当的因子,并给它们加上标签(表示性别)或重新排列因子的级别。

我们需要非常小心地准确键入列中显示的标签,否则它会用 NA 替换那些拼写错误的标签。例如,您是否注意到High Dose有一个大写的“D ”,而Low dose有一个小写的“D ”?

sum_df <- raw_df %>% 
            mutate(
              sex = factor(sex, 
                  labels = c("Male", "Females")),
              drug_treatment =  factor(drug_treatment, 
                  levels = c("Placebo", "Low dose", "High Dose")),
              health_status = factor(health_status, 
                  levels = c("Healthy", "Alzheimer's"))
              )

尽管 R 非常强大,但它需要明确而准确的代码输入来完成最终目标。因此,如果我们键入“High d ose ”,它会给出安娜,而“High D ose”会正确输出。我们现在将agemmse 视为dbl (数字),将sexhealth_statusdrug_treatment 视为因子。

Observations: 600
Variables: 5
$ age            <dbl> 80, 85, 82, 80, 83, 79, 82, 79, 80, 79,...
$ sex            <fct> Male, Male, Male, Male, Male, Females, Mal...
$ health_status  <fct> Healthy, Healthy, Healthy, Healthy, Health...
$ drug_treatment <fct> Placebo, Placebo, Placebo, Placebo, Placeb...
$ mmse           <dbl> 24.78988, 24.88192, 25.10903, 24.92636,...

现在一切都已正确编码,我们可以计算我们的平均值和标准误差(se =标准偏差/样本数的平方根)!我们将使用group_by来告诉 R 我们想要…分组的因素!然后,我们将通过首先调用summarize然后用mmse_meanmmse_se以及样本数量n()指定我们想要的汇总来创建命名汇总。最后,我们将ungroup,从数据帧中删除group_by代码。

sum_df <- sum_df %>%   
  group_by(sex, health_status, drug_treatment) %>%  
  summarize(mmse_mean = mean(mmse),   
            mmse_se = sd(mmse)/sqrt(n()),
            n_samples = n()) %>%
  ungroup() # ungrouping variable is a good habit to prevent errors

现在我们有了一个格式良好的数据框架,可以保存到 Excel 中,或用于绘图。我们需要指出我们正在写什么数据(sum_df)以及我们希望结果文件被命名为什么(“adx37_sum_stats.csv”)。

# code to save the table into a .csv Excel file
write.csv(sum_df, "adx37_sum_stats.csv")

总结图

通过调用 ggplot 函数,我们可以生成一个初步的摘要图。

ggplot(data = sum_df, # add the data
       aes(x = drug_treatment,  #set x, y coordinates
           y = mmse_mean,
           group = drug_treatment,  # group by treatment
           color = drug_treatment)) +    # color by treatment
  geom_point(size = 3) + # set size of the dots
  facet_grid(sex~health_status) # create facets by sex and status

我们现在可以看到,该图按照药物治疗和健康状况进行了适当的分类。我们在最终的图表上还有一些工作要做,但是让我们先来看看 ANOVAs!

方差分析终于出来了!

我们将准备一个数据框架,通过方差分析进行分析。我们需要再次确保通过mutate将我们的因素作为因素,并且顺序正确。这是 ANOVA/事后检验工作所必需的,并使事后 hoc 和 ANOVA 输出更容易读取。

stats_df <- raw_df %>% # start with data
   mutate(drug_treatment = factor(drug_treatment, 
             levels = c("Placebo", "Low dose", "High Dose")),
         sex = factor(sex, 
             labels = c("Male", "Female")),
         health_status = factor(health_status, 
             levels = c("Healthy", "Alzheimer's")))glimpse(stats_df)#output belowObservations: 600
Variables: 5
$ age            <dbl> 80, 85, 82, 80, 83, 79, 82, 79, 80, 79...
$ sex            <fct> Male, Male, Male, Male, Male, Male, ...
$ health_status  <fct> Healthy, Healthy, Healthy, Healthy...
$ drug_treatment <fct> Placebo, Placebo, Placebo, Placebo,...
$ mmse           <dbl> 24.78988, 24.88192, 25.10903...

这使我们的数据框架进入工作状态!

通过aov功能调用 ANOVA。基本语法通过下面的伪代码显示。我们首先放入因变量(在我们的例子中是 mmse ),然后是一个~,然后是我们想要测试的自变量。最后,我们指定使用什么数据。

aov(dependent_variable ~ independent variable, data = data_df)

我们可以通过下面的代码添加真实的数据集:

# this gives main effects AND interactions
ad_aov <- aov(mmse ~ sex * drug_treatment * health_status, 
        data = stats_df)# this would give ONLY main effects
ad_aov <- aov(mmse ~ sex + drug_treatment + health_status, data = stats_df)

因为我们有 3 个独立变量,所以我们要做出选择。我们可以简单地通过在每个变量之间添加一个+来寻找主效应,或者我们可以通过在每个变量之间添加一个*来寻找主效应和交互作用。确保不要用逗号替换+*,因为这会导致错误!

# this throws an error because we shouldn't use commas in between!
ad_aov <- aov(mmse ~ sex, drug_treatment, health_status, data = stats_df)

通过将 ANOVA 分配给ad_aov对象,我们可以调用它的summary 来查看 ANOVA 的结果。

# look at effects and interactions
summary(ad_aov) Df  Sum Sq Mean Sq  F value Pr(>F)    
sex                                1      0       0    0.047  0.828    
drug_treatment                     2   3601    1801  909.213 **<2e-16** 
health_status                      1  10789   10789 5447.953 **<2e-16** 
sex:drug_treatment                 2      8       4    2.070  0.127    
sex:health_status                  1      5       5    2.448  0.118    
drug_treatment:health_status       2   2842    1421  717.584 **<2e-16** 
sex:drug_treatment:health_status   2      5       2    1.213  0.298    
Residuals                        588   1164       2                    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

总结给出了自由度、平方和、均方、F 值和 p 值。我在<2e -16, these p values are so small that R switches to scientific notation. So we see significant main effects of drug treatment, health status, and an interaction of drug treatment by health status. We can interpret that Alzheimer’s patients had different cognitive scores than healthy, and that drug treatment had an effect on cognitive scores. Importantly, sex was not a significant factor, as p = 0.828. Variables being scored as significant or non-significant can both be important!

We can also use 【 to clean up the results of the ANOVA and put them into a dataframe. This is useful for storage, or for automation of some analysis for future ANOVAs.

# this extracts ANOVA output into a nice tidy dataframe
tidy_ad_aov <- tidy(ad_aov)# which we can save to Excel
write.csv(tidy_ad_aov, "ad_aov.csv")

However, we don’t know the direction of changes, or where the changes occurred. Was it just the high dose? Low dose? Both? We need follow-up post hoc tests to determine these answers!

后 hocs >博士后(学术界笑话<爸爸笑话)上加了一个醒目的强调

我们有多种方式来看待后 hocs。我将在这一部分展示两个。

对于成对的,我们需要使用$从每个数据帧中选择列,并通过:查看交互。我们的第一个两两比较没有对多重比较进行校正,与无保护的 Fisher's-LSD post-hoc 相当。这一点也不严格,考虑到我们所做的大量比较,建议要么继续进行 p.adjusting Bonferonni 校正(将p.adj = “none”改为p.adj = “bonf”)要么进行 Tukey 事后测试,如下例所示。您可以看到,由于dataset$column方法和每次交互之间对:的需要,这个方法读起来有点混乱。我们可以这样理解,我们需要对sexdrug_treatmenthealth_status的相互作用进行成对 t.test,它给出了这些因素相对于其他因素的每一次迭代。

# call and save the pair.t.test
ad_pairwise <- pairwise.t.test(stats_df$mmse,    stats_df$sex**:**stats_df$drug_treatment**:**stats_df$health_status, 
p.adj = "none")

此外,我们需要提取 p 值矩阵并保存到 Excel 文件中以备将来使用。

我们通过简单地用broom::tidy包装我们的ad_last posthoc 来做到这一点。

# tidy the post hoc
tidy_ad_pairwise <- broom::tidy(ad_pairwise)# save to excel
write.csv(tidy_ad_pairwise, "tidy_ad_pairwise.csv")

Tukey post-hoc 比未调整的成对 t-test 更容易调用。请注意,我们已经将 Tukey 结果封装在broom::tidy中,以保存为一个整洁的数据帧!TukeyHSD 调用合并了 ANOVA 调用的结果,并且优于前面的方法。

下面的代码可以被阅读,因为我们想要对我们的ad_aov ANOVA 的结果进行 Tukey 事后测试,该 ANOVA 跨越drug_treatment by health_statussex 的交互。注意每个变量之间的‘sex:drug_treatment:health_status’:的引号。这些是告诉 R 我们希望 Tukey 如何运行所必需的!一旦完成,R 就对它运行 tidy,使它成为一个好的数据帧,类似于我们之前的成对测试。然后我们可以将结果保存到 Excel 中!

# call and tidy the tukey posthoc
tidy_ad_tukey <- tidy(TukeyHSD(ad_aov, which =             'sex:drug_treatment:health_status'))# save to excel
write.csv(tidy_tukey_ad, "tukey_ad.csv")

出版图

现在,我们已经生成了 ANOVAs 和 post-hoc,并将其保存到 Excel 中进行存储,我们可以开始制作出版物级别的图表了!

图表允许极端的定制,我在图表上添加的一些内容是个人的选择,因此我建议与你所在领域的导师或有经验的成员讨论。条形图在我的领域中无处不在,虽然我认为绘制成箱线图可以告诉我们更多的数据,但我首先会从条形图开始。

我们的目标是绘制平均值、标准误差,并指出其发生的意义。我将使用tribble 函数手工制作一个定制的数据帧,而不是依赖一个包来标记重要性。除了这样做还有其他选择,但是我可以很容易地控制使用这种方法会发生什么,而且数据帧包含的内容非常明显。下面的例子显示了三层结构的基本原理。我们用~指定列,然后显式地写出我们在列的每一行中想要的内容。

[tribble](https://rdrr.io/cran/tibble/man/tribble.html)(
  ~colA, ~colB,
  "a",   1,
  "b",   2,
  "c",   3
)# Output below
*# A tibble: 3 x 2*
   colA  colB
  <chr> <dbl>
1     a     1
2     b     2
3     [c](https://rdrr.io/r/base/c.html)     3

这是我们制作自定义数据帧的实际代码。

# make the dataframe with specific points of interest to add *
sig_df <- tribble(
  ~drug_treatment, ~ health_status, ~sex, ~mmse_mean,
  "Low dose", "Alzheimer's", "Male", 17,
  "High Dose", "Alzheimer's", "Male", 25,
  "Low dose", "Alzheimer's", "Female", 18, 
  "High Dose", "Alzheimer's", "Female", 24
  )# convert the variables to factors again :)
sig_df <- sig_df %>% 
  mutate(drug_treatment = factor(drug_treatment, 
               levels = c("Placebo", "Low dose", "High Dose")),
         sex = factor(sex, 
               levels = c("Male", "Female")),
         health_status = factor(health_status, 
               levels = c("Healthy", "Alzheimer's")))# Output below
# A tibble: 4 x 4
  drug_treatment health_status sex    mmse_mean
  <fctr>         <fctr>        <fctr>     <dbl>
1 Low dose       Alzheimer's   Male        17.0
2 High Dose      Alzheimer's   Male        25.0
3 Low dose       Alzheimer's   Female      18.0
4 High Dose      Alzheimer's   Female      24.0

现在我们有了这个数据框,我们可以在一个geom_text调用中使用它,用重要性标签来标记我们的条,如*所示。

下面是最终发布图在ggplot2代码中的样子。你会注意到我把它赋给了g1,而不是直接调用它。这意味着我将不得不调用g1 来查看图表,但我现在可以保存它!为了理解我们正在做的事情,我像以前一样调用初始的ggplot 调用,但是添加了一个误差条层、一个条形图层、分为性别和健康状态的窗格、切换到另一个外观(theme_bw)、手动设置颜色、通过主题进行微小调整、添加* 以指示重要性,最后在添加图形标题的同时更改轴标签。

g1 <- ggplot(data = sum_df, 
       aes(x = drug_treatment, y = mmse_mean, fill = drug_treatment,  
           group = drug_treatment)) +
  geom_errorbar(aes(ymin = mmse_mean - mmse_se, 
                    ymax = mmse_mean + mmse_se), width = 0.5) +
  geom_bar(color = "black", stat = "identity", width = 0.7) +

  facet_grid(sex~health_status) +
  theme_bw() +
  scale_fill_manual(values = c("white", "grey", "black")) +
  theme(legend.position = "NULL",
        legend.title = element_blank(),
        axis.title = element_text(size = 20),
        legend.background = element_blank(),
        panel.grid.major = element_blank(), 
        panel.grid.minor = element_blank(),
        axis.text = element_text(size = 12)) +
  geom_text(data = sig_df, label = "*", size = 8) +
  labs(x = "\nDrug Treatment", 
       y = "Cognitive Function (MMSE)\n",
       caption = "\nFigure 1\. Effect of novel drug treatment AD-x37 on cognitive function in healthy and demented elderly adults. \nn = 100/treatment group (total n = 600), * indicates significance at p < 0.001")g1# save the graph!
ggsave("ad_publication_graph.png", g1, height = 7, width = 8, units = "in")

保存是通过ggsave 函数完成的,在这里我们需要用" ",告诉 R 我们想要哪个 ggplot 对象(g1),并通过高度、宽度和单位指示大小。

还有最后的图!

我认为说你可以通过简单地重现我的例子来学习ggplot是一种伤害。因此,我想为您指出数据科学教科书的 R 方向,以及现代潜水电子书。这些免费的电子书有大量的信息,可能超出你今天需要完成的,但会在你未来的努力中为你服务。他们关于数据可视化的章节对 R 绘图入门非常有帮助!

谢谢

如果你已经做到了这一步,对你有好处!我希望这有所帮助,如果你有任何问题,我建议你通过#rstats 标签联系 twitter,或者你可以在 Twitter 上找到我@thomas_mock。

此外, Jesse Maegan 有一个 R for Data Science Slack 频道,你可以在那里学习和提问。r 工作室(潮汐看护者)在 https://community.rstudio.com/举办他们自己的论坛。

购物篮分析——关联规则简介

原文:https://towardsdatascience.com/a-gentle-introduction-on-market-basket-analysis-association-rules-fa4b986a40ce?source=collection_archive---------0-----------------------

Source: UofT

介绍

购物篮分析是大型零售商用来发现商品之间关联的关键技术之一。它通过寻找在交易中频繁出现的项目组合来工作。换句话说,它允许零售商识别人们购买的商品之间的关系。

关联规则被广泛用于分析零售购物篮或交易数据,并且旨在基于强规则的概念,使用感兴趣的度量来识别在交易数据中发现的强规则。

关联规则的一个例子

  • 假设有 100 个客户
  • 其中 10 人买了牛奶,8 人买了黄油,6 人两样都买了。
  • 买了牛奶= >买了黄油
  • 支持= P(牛奶和黄油)= 6/100 = 0.06
  • 信心=支持度/P(黄油)= 0.06/0.08 = 0.75
  • lift =置信度/P(牛奶)= 0.75/0.10 = 7.5

注意:这个例子非常小。在实践中,一个规则需要数百个事务的支持,才能被认为具有统计意义,数据集通常包含数千或数百万个事务。

好了,理论到此为止,让我们来看看代码。

我们今天使用的数据集来自 UCI 机器学习库。该数据集被称为“在线零售”,可以在这里找到。它包含一家总部位于英国的注册在线零售商在 2010 年 1 月 12 日至 2011 年 9 月 12 日之间发生的所有交易。

装载包裹

library(tidyverse)
library(readxl)
library(knitr)
library(ggplot2)
library(lubridate)
library(arules)
library(arulesViz)
library(plyr)

数据预处理和探索

retail <- read_excel('Online_retail.xlsx')
retail <- retail[complete.cases(retail), ]
retail <- retail %>% mutate(Description = as.factor(Description))
retail <- retail %>% mutate(Country = as.factor(Country))
retail$Date <- as.Date(retail$InvoiceDate)
retail$Time <- format(retail$InvoiceDate,"%H:%M:%S")
retail$InvoiceNo <- as.numeric(as.character(retail$InvoiceNo))glimpse(retail)

经过预处理后,数据集包括 406,829 条记录和 10 个字段:发票号、库存代码、描述、数量、发票日期、单价、客户 ID、国家、日期、时间。

人们通常在什么时候上网购物?

为了找到这个问题的答案,我们需要从时间列中提取“小时”。

retail$Time <- as.factor(retail$Time)
a <- hms(as.character(retail$Time))
retail$Time = hour(a)retail %>% 
  ggplot(aes(x=Time)) + 
  geom_histogram(stat="count",fill="indianred")

Figure 1. Shopping time distribution

一天中的小时和订单量之间有明显的偏差。大多数订单发生在 10:00-15:00 之间。

每位顾客购买多少件商品?

detach("package:plyr", unload=TRUE)retail %>% 
  group_by(InvoiceNo) %>% 
  summarize(n_items = mean(Quantity)) %>%
  ggplot(aes(x=n_items))+
  geom_histogram(fill="indianred", bins = 100000) + 
  geom_rug()+
  coord_cartesian(xlim=c(0,80))

Figure 2. Number of items per invoice distribution

大多数人购买的商品少于 10 件(每张发票少于 10 件)。

十大畅销书

tmp <- retail %>% 
  group_by(StockCode, Description) %>% 
  summarize(count = n()) %>% 
  arrange(desc(count))
tmp <- head(tmp, n=10)
tmptmp %>% 
  ggplot(aes(x=reorder(Description,count), y=count))+
  geom_bar(stat="identity",fill="indian red")+
  coord_flip()

Figure 3. Top 10 best sellers

在线零售商的关联规则

在使用任何规则挖掘算法之前,我们需要将数据从数据帧格式转换为事务,这样我们就可以将所有购买的商品放在一行中。例如,这是我们需要的格式:

Source: Microsoft

retail_sorted <- retail[order(retail$CustomerID),]
library(plyr)
itemList <- ddply(retail,c("CustomerID","Date"), 
                       function(df1)paste(df1$Description, 
                       collapse = ","))

函数 ddply()接受一个数据帧,根据一个或多个因素将其分割成多个部分,对这些部分进行计算,然后将结果作为数据帧返回。我们用“,”来分隔不同的项目。

我们只需要项目交易,所以删除 customerID 和 Date 列。

itemList$CustomerID <- NULL
itemList$Date <- NULL
colnames(itemList) <- c("items")

将数据帧写入 csv 文件,并检查我们的事务格式是否正确。

write.csv(itemList,"market_basket.csv", quote = FALSE, row.names = TRUE)

完美!现在我们有了交易数据集,它显示了一起购买的商品的矩阵。我们实际上看不到他们多久一起买一次,也看不到规则。但是我们会找到答案的。

让我们仔细看看我们有多少事务,它们是什么。

tr <- read.transactions('market_basket.csv', format = 'basket', sep=',')
tr
summary(tr)

我们看到 19,296 个事务,这也是行数。有 7,881 个项目—记住项目是我们原始数据集中的产品描述。这里的事务是这 7,881 个项目的集合或子集。

总结给了我们一些有用的信息:

  • 密度:稀疏矩阵中非空单元的百分比。换句话说,购买的商品总数除以矩阵中可能的商品总数。我们可以这样使用密度来计算购买了多少物品:19296 X 7881 X 0.0022
  • 最常见的项目应该与图 3 中的结果相同。
  • 看看交易的规模:2247 笔交易仅针对 1 件商品,1147 笔交易针对 2 件商品,一直到最大的交易:1 笔交易针对 420 件商品。这表明大多数顾客在每次交易中只购买少量商品。

  • 数据的分布是右偏的。

让我们看一下项目频率图,它应该与图 3 一致。

itemFrequencyPlot(tr, topN=20, type='absolute')

Figure 4. A bar plot of the support of the 20 most frequent items bought.

创建一些规则

  • 我们使用 Arules 库中的 Apriori 算法来挖掘频繁项集和关联规则。该算法对频繁项集采用逐级搜索。
  • 我们通过 supp=0.001 和 conf=0.8 来返回支持度至少为 0.1%、置信度至少为 80%的所有规则。
  • 我们按照置信度递减的方式对规则进行排序。
  • 看一下规则的总结。
rules <- apriori(tr, parameter = list(supp=0.001, conf=0.8))
rules <- sort(rules, by='confidence', decreasing = TRUE)
summary(rules)

这些规则的总结给了我们一些非常有趣的信息:

  • 规则数:89697。
  • 按长度分布规则:长度为 6 项的规则最多。
  • 质量度量的概要:支持、信心和提升的范围。
  • 关于数据挖掘的信息:挖掘的数据总量,以及我们之前设置的最小参数。

我们有 89697 条规则。我不想把它们都印出来,所以我们来检查一下前 10 名。

inspect(rules[1:10])

解释相当直接:

  • 100%买了“晃晃悠悠的鸡”的顾客也买了“装修”。
  • 买了“红茶”的顾客 100%也买了“糖罐”。

并列出这 10 条最重要的规则。

topRules <- rules[1:10]
plot(topRules)

plot(topRules, method="graph")

plot(topRules, method = "grouped")

摘要

在这篇文章中,我们学习了如何在 R 中执行购物篮分析,以及如何解释结果。如果你想用 Python 实现它们, Mlxtend 是一个 Python 库,它实现了这类应用程序的 Apriori 算法。这里可以找到介绍教程。

如果你想用 R Markdown 文件来制作这篇博文,你可以在这里找到。

参考: R 和数据挖掘

用 Go 对遗传算法的简单介绍

原文:https://towardsdatascience.com/a-gentle-introduction-to-genetic-algorithms-c5bc15827e2d?source=collection_archive---------5-----------------------

通过进化蒙娜丽莎引入遗传算法

乍一看可能不太明显,但计算机科学算法经常受到自然和生物过程的启发。这些算法包括神经网络、粒子群优化、人工蜂群、蚁群优化、进化算法等等。事实上,你可以把生物过程看作是大自然想出的解决问题的简单算法。从这个角度来看,很容易理解为什么这些算法是优化试探法和元试探法。毕竟,大自然为了生存而优化。

试探法,如果你不熟悉这个术语,是通过做一些假设来试图更快解决问题的算法。因此,试探法通常不是最佳的,但在获得最佳结果需要很长时间的情况下更有用。元启发式把这带到下一个层次——它们是一种产生或发现启发式的启发式方法。

遗传算法

遗传算法是基于自然选择过程的元启发式算法。遗传算法是一种进化算法。

自然选择,作为一种更新,是进化中的一个关键机制。这是一个自然过程,随着时间的推移,导致(生物)种群适应它们的环境。这些群体在特征上有所不同。具有更合适特征的个体生物在环境中生存的机会更高。从这些幸存下来的生物体中繁殖的下一代将继承它们的特征,最终产生具有这些更合适特征的种群。

然而,如果整个种群都有相同的特征,而环境改变了,种群就会灭绝。幸运的是,偶尔发生的突变会导致性状的变异,这使得具有更适合变化的环境的性状的生物体得以生存并成为主导。

一个普遍使用的例子是英国胡椒蛾的颜色变化。在 19 世纪早期之前,英格兰的胡椒蛾大多是白色的,它的颜色有助于它躲避食肉鸟类,因为它与浅色的地衣和英国树木很好地融合在一起。然而,在工业革命期间,浅色的地衣因污染而死亡,许多飞蛾栖息的树木被煤烟熏黑。这使得深色的蛾子在躲避捕食者时具有优势,而浅色的蛾子很容易被发现。到了 19 世纪中期,深色蛾子的数量增加了,到了 19 世纪末,几乎所有的胡椒蛾都是深色品种。1956 年《清洁空气法案》的影响打破了这种平衡,深色的蛾子又变得罕见了。

Peppered moth (credits: https://commons.wikimedia.org/wiki/File:Lichte_en_zwarte_versie_berkenspanner_crop.jpg)

这就是自然选择。遗传算法是如何出现的?遗传算法是启发式的,使用与自然选择相同的机制——DNA、种群、变异、适应度、选择、繁殖、遗传和突变。

  • DNA——定义拥有一个或多个 DNA 的生物体
  • 种群——从 DNA 基因(值)不同的生物体初始种群开始
  • 适合度 —确定每种生物对其环境的适合度
  • 选择——选择最适合的生物,给它们更高的繁殖机会
  • 繁殖 —从选择的最适合的生物体中创造下一代种群
  • 遗传 —人口的下一代必须继承基因的值
  • 突变——每一代人的基因值都有微小的变化

猴子、打字机和莎士比亚

无限猴子定理说的是,无限数量的猴子坐在无限数量的打字机前随机敲击键盘,只要给足够的时间,最终会重现莎士比亚的全集。假设我们只想让一只猴子复制这句话:“生存还是毁灭”。你觉得猴子随机锤出这个要多长时间?

Monkeying around with Shakespeare (credits: https://commons.wikimedia.org/wiki/File:Chimpanzee_seated_at_typewriter.jpg)

报价有 18 个字符(包括空格)。猴子打出【t】(姑且说全是小盘也可以)的概率是 26 分之一。因此,键入确切序列“生存还是毁灭”的概率是 26 的 18 次方分之一,或者是大约 29,479,510,200,013,920,000,000,000 的 1 分之一。假设猴子每秒钟打一封信,那么在 934,789,136,225,707,600 年中,它只有 1 次机会打出这句话。这是 934 万亿年的 1 倍。

显然,这种野蛮的方式不会让我们有任何进展。如果我们尝试“改进”报价会怎么样?让我们看看如何使用遗传算法来做到这一点。下面是用于解决该问题的遗传算法的步骤:

定义由一个或多个 DNA 组成的有机体

我们的莎士比亚-喷算法中的一个生物体由单个 DNA 组成,它是一个字节数组和一个代表生物体适应度的数字。

type Organism struct {
	DNA    []byte
	Fitness float64
}

从最初的生物群体开始

我们需要为我们的初始种群创建有机体,所以这里有一个函数来做这件事。

func createOrganism(target []byte) (organism Organism) {
	ba := make([]byte, len(target))
	for i := 0; i < len(target); i++ {
		ba[i] = byte(rand.Intn(95) + 32)
	}
	organism = Organism{
		DNA:    ba,
		Fitness: 0,
	}
	organism.calcFitness(target)
	return
}

target是我们想要实现的,在这种情况下,它是字符串“生存还是毁灭”的字节数组表示。在这个函数中,我们随机创建一个与目标长度相同的字节数组,并将其设置为新创建的生物体中基因的值。

既然我们可以创造生物体,我们需要创造一个生物体群体。

func createPopulation(target []byte) (population []Organism) {
	population = make([]Organism, PopSize)
	for i := 0; i < PopSize; i++ {
		population[i] = createOrganism(target)
	}
	return
}

population是一组生物体,而PopSize是一个定义种群规模的全局变量。

找到生物体的适合度

我们需要计算我们种群中生物体的适合度。这在我们创造有机体时被称为早期,但在我们交叉有机体时也会被称为晚期。

func (d *Organism) calcFitness(target []byte) {
	score := 0
	for i := 0; i < len(d.DNA); i++ {
		if d.DNA[i] == target[i] {
			score++
		}
	}
	d.Fitness = float64(score) / float64(len(d.DNA))
	return
}

这个健身功能比较简单。我们简单地计算基因中的字节与目标匹配的次数。分数除以目标中的总字节数,以使适合度为一个百分比,即 0.0 到 1.0 之间的数字。这意味着如果适应度是 1.0,我们将进化生物体的基因以匹配“生存还是毁灭”的引用。

选择最适合的生物,给它们更高的繁殖机会

现在我们有了一个种群,我们可以找出哪些生物最适合,我们想挑选最适合的生物,让它们繁殖来创造种群的下一代。有许多不同的方法可以做到这一点,但在这种情况下,我们使用的是一种“繁殖池”机制。

func createPool(population []Organism, target []byte, maxFitness float64) (pool []Organism) {
	pool = make([]Organism, 0)
	// create a pool for next generation
	for i := 0; i < len(population); i++ {
		population[i].calcFitness(target)
		num := int((population[i].Fitness / maxFitness) * 100)
		for n := 0; n < num; n++ {
			pool = append(pool, population[i])
		}
	}
	return
}

我们所做的是创造一种繁殖池,在这里我根据生物的适合度将相同生物的多个副本放入池中。有机体的适应度越高,池中就有越多的有机体副本。

从所选择的最适合的生物体中创建种群的下一代

之后,我们从繁殖池中随机挑选 2 个生物体,用它们作为亲本,为种群创造下一代生物体。

func naturalSelection(pool []Organism, population []Organism, target []byte) []Organism {
	next := make([]Organism, len(population)) for i := 0; i < len(population); i++ {
		r1, r2 := rand.Intn(len(pool)), rand.Intn(len(pool))
		a := pool[r1]
		b := pool[r2] child := crossover(a, b)
		child.mutate()
		child.calcFitness(target) next[i] = child
	}
	return next
}

人口的下一代必须继承基因的价值

然后,下一代的child由两个随机挑选的生物体杂交而成,继承了两个生物体的DNA。

func crossover(d1 Organism, d2 Organism) Organism {
	child := Organism{
		DNA:    make([]byte, len(d1.DNA)),
		Fitness: 0,
	}
	mid := rand.Intn(len(d1.DNA))
	for i := 0; i < len(d1.DNA); i++ {
		if i > mid {
			child.DNA[i] = d1.DNA[i]
		} else {
			child.DNA[i] = d2.DNA[i]
		} }
	return child
}

对于交叉,我简单地选择了一个中点mid,并使用第一个生物体的第一个mid字节和第二个生物体的剩余字节。

随机变异每一代

在一个新的子有机体从两个亲代有机体中复制出来后,我们观察子有机体是否发生了突变。

func (d *Organism) mutate() {
	for i := 0; i < len(d.DNA); i++ {
		if rand.Float64() < MutationRate {
			d.DNA[i] = byte(rand.Intn(95) + 32)
		}
	}
}

这里的突变仅仅意味着确定一个随机生成的数是否低于MutationRate。为什么我们需要突变子生物体?如果突变从未发生,群体中的 DNA 将始终保持与原始群体相同。这意味着如果原始种群没有所需的特定基因(值),将永远无法获得最佳结果。就像在这个例子中,如果字母t在初始种群中根本找不到,那么无论我们经历多少代,我们都无法得出这个引用。换句话说,没有突变,自然选择就不起作用。

更专业地说,突变让我们摆脱局部最大值,以找到全局最大值。如果我们将遗传算法视为一种寻找最优解的机制,如果我们没有突变,一旦找到局部最大值,该机制将简单地停留在这一点上,而不会继续寻找全局最大值。突变可以使群体跳出局部最大值,因此为算法提供了继续寻找全局最大值的机会。

一旦我们检查了突变,我们就计算出子生物体的适应度,并将其插入到下一代种群中。

这就是遗传算法的全部内容!现在让我们把它们放在main函数中。

func main() {
	start := time.Now()
	rand.Seed(time.Now().UTC().UnixNano()) target := []byte("To be or not to be")
	population := createPopulation(target) found := false
	generation := 0
	for !found {
		generation++
		bestOrganism := getBest(population)
		fmt.Printf("\r generation: %d | %s | fitness: %2f", generation, string(bestOrganism.DNA), bestOrganism.Fitness) if bytes.Compare(bestOrganism.DNA, target) == 0 {
			found = true
		} else {
			maxFitness := bestOrganism.Fitness
			pool := createPool(population, target, maxFitness)
			population = naturalSelection(pool, population, target)
		} }
	elapsed := time.Since(start)
	fmt.Printf("\nTime taken: %s\n", elapsed)
}

在主函数中,我们经历了几代,每一代我们都试图找到最适合的有机体。如果最适合的生物体的基因与目标相同,我们就会找到答案。

现在运行软件程序!你花了多长时间?

因为初始群体是随机生成的,所以每次您都会得到不同的答案,但大多数情况下,我们可以在不到一秒钟的时间内完成报价!如果我们不得不强行计算的话,这与 934 万亿年有很大的不同。

进化中的蒙娜丽莎

进化莎士比亚似乎很简单。毕竟只是一串。来点不同的怎么样,比如说一个图像?还是有史以来最著名的画作,达芬奇的《蒙娜丽莎》?我们能进化吗?

Mona Lisa (public domain)

让我们给它同样的待遇。我们将从定义生物体来代表蒙娜丽莎的照片开始。

定义由一个或多个 DNA 组成的有机体

我们的 DNA 不再是字节数组,而是来自image标准库的结构。

type Organism struct {
	DNA     *image.RGBA
	Fitness int64
}

从最初的生物群体开始

像以前一样,让我们先看看如何创造一个有机体。

func createOrganism(target *image.RGBA) (organism Organism) {
	organism = Organism{
		DNA:     createRandomImageFrom(target),
		Fitness: 0,
	}
	organism.calcFitness(target)
	return
}

我们不创建随机字节数组,而是调用另一个函数来创建随机图像。

func createRandomImageFrom(img *image.RGBA) (created *image.RGBA) {
	pix := make([]uint8, len(img.Pix))
	rand.Read(pix)
	created = &image.RGBA{
		Pix:    pix,
		Stride: img.Stride,
		Rect:   img.Rect,
	}
	return
}

一个image.RGBA struct 由一个字节数组Pix ( byteuint8是一回事)、一个Stride和一个Rect组成。对我们来说重要的是Pix,我们使用相同的StrideRect作为目标图像(这是蒙娜丽莎的图像)。幸运的是,math/rand标准库有一个名为Read的方法,可以用随机字节很好地填充一个字节数组。

你可能会好奇,那么我们在这里讨论的字节数组有多大呢?Pix无非是用 4 个字节代表一个像素的字节数组(R,G,B,A 各用一个字节表示)。对于一个 800 x 600 的图像,我们谈论的是每个图像中有 192 万字节!为了保持程序相对较快的速度,我们将使用一个 67 x 100 大小的较小图像,它给出了一个 26,800 字节的数组。如果你到现在还没有意识到,这和我们在上一个程序中使用的 18 字节相差甚远。

此外,你可能会意识到,因为每个像素现在是随机着色的,我们最终会得到一个彩色的静态雪花图案。

Randomly generate image

我们继续吧。

找到生物体的适合度

有机体的适合度是两个图像之间的差异。

// calculate the fitness of an organism
func (o *Organism) calcFitness(target *image.RGBA) {
	difference := diff(o.DNA, target)
	if difference == 0 {
		o.Fitness = 1
	}
	o.Fitness = difference}// find the difference between 2 images
func diff(a, b *image.RGBA) (d int64) {
	d = 0
	for i := 0; i < len(a.Pix); i++ {
		d += int64(squareDifference(a.Pix[i], b.Pix[i]))
	}
	return int64(math.Sqrt(float64(d)))
}// square the difference between 2 uint8s
func squareDifference(x, y uint8) uint64 {
	d := uint64(x) - uint64(y)
	return d * d
}

为了找到区别,我们可以回到勾股定理。如果你记得,我们可以找到两点之间的距离,如果我们平方xy值的差,将它们相加,然后平方根结果。

Pythagorean theorem

给 2 个点a (x1,y1)和b (x2,y2),ab之间的距离d为:

那是在二维空间。在三维空间中,我们简单地做两次勾股定理,在四维空间中,我们做三次。一个像素的 RGBA 值本质上是 4 维空间中的一个点,因此为了找出两个像素之间的差异,我们对两个像素的rgba值之间的差异求平方,将它们相加,然后对结果求平方根。

这就是 2 个像素的区别。为了找出所有像素之间的差异,我们只需将所有结果加在一起,就可以得到最终的差异。因为Pix本质上是一个包含连续 RGBA 值的长字节数组,所以我们可以使用一个简单的快捷方式。我们简单地平方图像和目标中每个对应字节之间的差异,然后将它们全部相加,并对最终数字求平方根,以找到两个图像之间的差异。

作为参考,如果两个图像完全相同,差异将为 0,如果两个图像完全相反,差异将为 26,800。换句话说,最适合的生物体应该具有 0 的适合度,并且数字越高,生物体越不适合。

选择最适合的生物,给它们更高的繁殖机会

我们仍然使用繁殖池机制,但有所不同。首先,我们将人群从最佳健康状态到最差健康状态进行排序。然后我们把最好的生物放入繁殖池。我们使用一个参数PoolSize来表示我们希望池中有多少最适合的生物体。

为了计算出应该把什么放入繁殖池,我们减去每一个最好的生物体,最不适合的生物体在最上面。这在最好的生物体之间产生了不同的等级,并且根据该不同的等级,我们将该生物体的相应数量的拷贝放入繁殖池中。例如,如果最适合的生物体和最不适合的生物体之间的差异是 20,我们将 20 个生物体放入育种池。

如果最适合的生物之间没有差异,这意味着种群是稳定的,我们不能真正创造一个合适的繁殖池。为了克服这一点,如果差值为 0,我们将池设置为整个群体。

func createPool(population []Organism, target *image.RGBA) (pool []Organism) {
	pool = make([]Organism, 0)
	// get top best fitting organisms
	sort.SliceStable(population, func(i, j int) bool {
		return population[i].Fitness < population[j].Fitness
	})
	top := population[0 : PoolSize+1]
	// if there is no difference between the top  organisms, the population is stable
	// and we can't get generate a proper breeding pool so we make the pool equal to the
	// population and reproduce the next generation
	if top[len(top)-1].Fitness-top[0].Fitness == 0 {
		pool = population
		return
	}
	// create a pool for next generation
	for i := 0; i < len(top)-1; i++ {
		num := (top[PoolSize].Fitness - top[i].Fitness)
		for n := int64(0); n < num; n++ {
			pool = append(pool, top[i])
		}
	}
	return
}

从所选择的最适合的生物体中创建种群的下一代

有了游泳池之后,我们需要创造下一代。这里自然选择的代码和前面的程序没有什么不同,所以我们在这里就不展示了。

人口的下一代必须继承基因的价值

crossover函数略有不同,因为孩子的 DNA 不是字节数组,而是 image.RGBA。实际的交叉机制在Pix上工作,而是像素的字节数组。

func crossover(d1 Organism, d2 Organism) Organism {
	pix := make([]uint8, len(d1.DNA.Pix))
	child := Organism{
		DNA: &image.RGBA{
			Pix:    pix,
			Stride: d1.DNA.Stride,
			Rect:   d1.DNA.Rect,
		},
		Fitness: 0,
	}
	mid := rand.Intn(len(d1.DNA.Pix))
	for i := 0; i < len(d1.DNA.Pix); i++ {
		if i > mid {
			child.DNA.Pix[i] = d1.DNA.Pix[i]
		} else {
			child.DNA.Pix[i] = d2.DNA.Pix[i]
		} }
	return child
}

随机变异每一代

mutate功能也相应不同。

func (o *Organism) mutate() {
	for i := 0; i < len(o.DNA.Pix); i++ {
		if rand.Float64() < MutationRate {
			o.DNA.Pix[i] = uint8(rand.Intn(255))
		}
	}
}

现在我们已经有了所有的东西,我们把它们放在main函数中。

func main() {
	start := time.Now()
	rand.Seed(time.Now().UTC().UnixNano())
	target := load("./ml.png")
	printImage(target.SubImage(target.Rect))
	population := createPopulation(target) found := false
	generation := 0
	for !found {
		generation++
		bestOrganism := getBest(population)
		if bestOrganism.Fitness < FitnessLimit {
			found = true
		} else {
			pool := createPool(population, target)
			population = naturalSelection(pool, population, target)
			if generation%100 == 0 {
				sofar := time.Since(start)
				fmt.Printf("\nTime taken so far: %s | generation: %d | fitness: %d | pool size: %d", 
				sofar, generation, bestOrganism.Fitness, len(pool))
				save("./evolved.png", bestOrganism.DNA)
				fmt.Println()
				printImage(bestOrganism.DNA.SubImage(bestOrganism.DNA.Rect))
			}
		}
	}
	elapsed := time.Since(start)
	fmt.Printf("\nTotal time taken: %s\n", elapsed)
}

现在运行它看看。你得到了什么?

Start evolving Mona Lisa

按照我设置的参数,当我运行它时,我通常会以 19,000 左右的健身值开始。平均来说,我需要 20 多分钟才能达到低于 7500 的体能。

After about 20 minutes

这是一系列随着时间推移而产生的图像:

Evolving Mona Lisa

用圆形和三角形进化蒙娜丽莎

我通过在一张图片上画圆圈和三角形来玩《蒙娜丽莎》的演变。结果没有那么快,图像也没有那么明显,但它显示了实际发生的一瞥。你可以从资源库中找到剩下的代码,自己调整参数,看看是否能得到更好的图片,但这里有一些我得到的图片。

蒙娜丽莎三角形

蒙娜丽莎的圆圈

玩得开心!

在终端上显示图像

你可能在我的截图中注意到了,我实际上在终端上显示了图像。我本来可以创建一个 web 应用程序来展示这一点,但是我想让事情简单得多,所以我想直接在终端上显示图像。虽然终端控制台不是您通常期望显示图像的地方,但实际上有几种方法可以做到这一点。

我选了一个最简单的。我正好用了优秀的 iTerm2 ,这是 MacOS 中默认终端应用的替代品,iTerm2 中有一个有趣的 hack,可以显示图像。

诀窍是这样的——如果你可以用 Base64 编码你的图像,你可以用一个特殊的命令把图像打印到终端上。下面是实现这一点的 Go 代码,但是您也可以用任何其他语言实现这一点。上面的文档中有几个脚本展示了如何使用简单的 shell 脚本来实现这一点。

func printImage(img image.Image) {
	var buf bytes.Buffer
	png.Encode(&buf, img)
	imgBase64Str := base64.StdEncoding.EncodeToString(buf.Bytes())
	fmt.Printf("\x1b]1337;File=inline=1:%s\a\n", imgBase64Str)
}

不幸的是,这意味着如果你在 iTerm2 之外的任何地方运行这段代码,你将看不到图像的变化。但是,您可以随时调整输出,以便每隔几代就捕获一次输出。

密码

这篇文章中的所有代码和图片都可以在这里找到:https://github.com/sausheong/ga

参考

示例代码受到了以下工作的启发:

  • 丹尼尔·席夫曼的优秀著作代码的本质【http://natureofcode.com】T2——这是一本很棒且容易理解的读物!我还用 Java 编写了一些丹尼尔的代码,并将其转换成莎士比亚引用算法
  • 罗杰·约翰逊在《遗传编程:蒙娜丽莎的进化》一文中的出色工作https://rogerjohansson . blog/2008/12/07/Genetic-Programming-evolution-of-Mona-Lisa/——尽管我最终使用了一种完全不同的方式来完成遗传算法,但他的原创工作给了我灵感,让我使用蒙娜丽莎,并尝试用三角形和圆形来完成它

最大似然估计简介

原文:https://towardsdatascience.com/a-gentle-introduction-to-maximum-likelihood-estimation-9fbff27ea12f?source=collection_archive---------0-----------------------

我第一次听到有人使用术语最大似然估计时,我去了谷歌,并找出了它的意思。然后我去维基百科了解它真正的意思。我得到了这个:

在统计学中,最大似然估计 ( MLE )是一种估计统计模型给定观测值的参数的方法,通过寻找使给定参数下进行观测的似然最大化的参数值。MLE 可以被视为最大后验概率估计 (MAP)的特殊情况,其假设参数的均匀 先验分布,或者被视为忽略先验分布的 MAP 的变体,因此其不规则。

好吗??

为了避免你为理解 MLE 并将其融入你的数据科学工作流程、理念和项目而绞尽脑汁,我编辑了这个指南。下面,我们将:

  • 将概率上下文设置为 MLE
  • 钻研所需的数学
  • 看看 MLE 在 Python 中是如何工作的
  • 利用 MLE 探索数据科学的最佳实践

不过先来点 xkcd :

常客 vs .贝叶斯

这很有趣(如果你遵循这个奇怪的幽默领域),而且这两个阵营之间的差异基本上是正确的。不要介意我们的太阳进入新星并不是一个真正可重复的实验——抱歉,常客们!—我们可以概括为,对于真实的观察和研究,两个阵营通常会得出类似的结论,但当研究设计或数据开始变得棘手时,就会有很大的不同。

简而言之,MLE 帮助我们回答了这个问题:

哪些参数/系数最适合我的模型?

有趣的是,你可以用这两种观点中的任何一种来解释 MLE 为什么有效!因为,虽然最大似然估计给出了一个现场估计——这在 frequentist 输出中很常见——但它可以被视为最大后验概率 (MAP)估计的一个特例,在这里我们使用了一个天真的先验知识,并且从不费心去更新它。

设置我们的问题

今天为了接近 MLE,让我们从贝叶斯的角度出发,使用贝叶斯定理将我们的问题框定如下:

P(β∣y) = P(y∣β) x P(β) / P(y)

或者,用英语说:

posterior = likelihood x prior / evidence

我们可以有效地忽略priorevidence,因为——给定均匀先验分布的 Wiki 定义——所有系数值都是同等可能的。而且所有数据值的概率(假设连续)都是相等的,而且基本上为零。

所以,在实际的英语中:给定一些特定系数的概率,我看到一些结果,涉及到以完全相反的方式提出问题。这很有帮助,因为这个问题更容易解决。

概率和可能性

从今以后,我们将在代码中引入可能性的概念,或L。为了理解其中的区别,我将从 Randy Gallistel 的精彩文章中摘录:

概率和可能性之间的区别是非常重要的:概率与可能的结果相联系;可能性附属于假设。

可能的结果是互斥的和穷尽的。假设我们让一个受试者预测 10 次投掷硬币的结果。只有 11 个可能的结果(0 到 10 个正确的预测)。实际的结果总是一个又一个可能的结果。因此,可能结果的概率总和必须为 1。

与结果不同,假设既不是互斥的,也不是穷尽的。假设我们测试的第一个对象正确预测了 10 个结果中的 7 个。我可能会假设受试者只是猜测,你可能会假设受试者可能有某种千里眼,你的意思是受试者可能被期望以稍高于概率的长期正确预测结果。这些是不同的假设,但并不互相排斥,因为你说“可能是”的时候就对冲了。你因此允许你的假设包括我的。用专业术语来说,我的假设嵌套在你的假设中。其他人可能会假设受试者有很强的透视能力,观察到的结果低估了她下一次预测正确的可能性。另一个人可以假设一些完全不同的东西。人们可以接受的假设是无限的。

我们赋予可能性的一系列假设受到我们虚构它们的能力的限制。实际上,我们很少能确信我们已经设想了所有可能的假设。我们关心的是估计实验结果在多大程度上影响我们和其他人目前所接受的假设的相对可能性。因为我们通常不考虑所有的替代假设,而且因为一些假设嵌套在其他假设中,我们附加到假设上的可能性本身没有任何意义;只有相对可能性——也就是两个可能性的比率——才有意义。

太神奇了!谢谢你兰迪。

MLE 是频率主义者,但可以从贝叶斯的角度出发:

  • 常客可以声称 MLE,因为它是一个逐点估计(不是一个分布),并且它假设没有先验分布(技术上,不知情或一致)。
  • 此外,MLE 没有给出真实参数值的 95%概率区域。
  • 然而,最大似然法是一种特殊形式的映射,并且使用了似然的概念,这是贝叶斯哲学的核心。

当心天真或一致的先验假设!!您可能会将数据错误地归因于一个极不可能的模型。你可能会成为辛普森悖论的受害者,如下图。你很容易被小样本欺骗。

Simpson’s Paradox

以上都是常客和数据科学家必须处理或意识到的问题,所以 MLE 没有什么本质上更糟糕的。

回到我们的问题

所以如果p(y|*β*)相当于 L(*β*|y),那么p(y_1,y_2,...,y_n|*β*)相当于L(*β*|y_1,y_2,...,y_n)。另外,请记住,我们可以将独立概率相乘,就像这样:

p(A,B) = p(A)p(B)

我们越来越近了!这是我们当前的设置:

L(*β*|y1,y2,…,yn) = p(y1|*β*)p(y2|*β*),…,p(yn|*β*) = ∏p(yi|*β*)

右边的部分看起来像是我们可以最大化的东西:

Initial Cost Function

但是我们可以做得更好!用自然对数把我们的积函数变成和函数怎么样?日志是单调变换,所以我们将简化我们的计算,但保持我们的最佳结果。

Halfway there!

我们最终的成本函数如下所示:

Ready to roll!

为了简单起见,让我们假设我们有一个回归问题,所以我们的结果是连续的。最大似然法对于离散结果的分类问题非常有效,但是我们必须使用不同的分布函数,这取决于我们有多少个类,等等。

现在,记住普通最小二乘法(OLS)等模型的一个中心假设是残差正态分布在均值零附近,我们拟合的 OLS 模型实际上成为了最大期望值y的体现。而我们的概率分布是… 正态!

y is normally distributed around our ŷ

因为计算机在计算概率方面比我们好得多,所以我们将从这里转向 Python!

Python 中的 MLE

在您的数据科学建模管道中实现 MLE 可能非常简单,有多种方法。下面是一个你可以偷着开始的方法。

设置

如果导入正确的包,MLE 很容易:

# import libraries
import numpy as np, pandas as pd
from matplotlib import pyplot as plt
import seaborn as sns
from scipy.optimize import minimize
import scipy.stats as statsimport pymc3 as pm3
import numdifftools as ndt
import statsmodels.api as sm
from statsmodels.base.model import GenericLikelihoodModel
%matplotlib inline

在此基础上,我们将生成遵循围绕基本事实函数的正态分布误差的数据:

# generate data
N = 100
x = np.linspace(0,20,N)
ϵ = np.random.normal(loc = 0.0, scale = 5.0, size = N)
y = 3*x + ϵdf = pd.DataFrame({‘y’:y, ‘x’:x})
df[‘constant’] = 1

最后,让我们使用 Seaborn 的 regplot 进行可视化:

# plot
sns.regplot(df.x, df.y);

我得到了下面的,你应该看到类似的东西。但是,请记住这里有随机性,我们没有使用种子:

Scatter plot with OLS line and confidence intervals

使用 Statsmodels 为 OLS 建模

由于我们创建了类似回归的连续数据,我们将使用sm.OLS来计算最佳系数和对数似然(ll)作为基准。

# split features and target
X = df[[‘constant’, ‘x’]]# fit model and summarize
sm.OLS(y,X).fit().summary()

我得到这个,并将记录拟合模型的系数:

注意constant接近于零,对于我们使用的地面真实发生器,特征xbeta接近于 3。

最大化 LL 以求解最佳系数

从这里开始,我们将使用软件包和自定义函数的组合,看看我们是否可以使用 MLE 方法计算相同的 OLS 结果。

因为scipy.optimize只有一个minimize方法,我们将最小化对数似然的负值。这甚至是他们推荐的!数学欺骗通常比重新发明轮子更快更容易!

我们可以构建一个简单的函数,一次完成回归输出的所有工作:

# define likelihood function
def MLERegression(params):
 intercept, beta, sd = params[0], params[1], params[2] # inputs are guesses at our parameters
 yhat = intercept + beta*x # predictions# next, we flip the Bayesian question
# compute PDF of observed values normally distributed around mean (yhat)
# with a standard deviation of sd
 negLL = -np.sum( stats.norm.logpdf(y, loc=yhat, scale=sd) )# return negative LL
 return(negLL)

现在我们有了一个成本函数,让我们初始化并最小化它:

# let’s start with some random coefficient guesses and optimize
guess = np.array([5,5,2])results = minimize(MLERegression, guess, method = ‘Nelder-Mead’, 
 options={‘disp’: True})--------------------------------------------------------------------
Optimization terminated successfully.
         Current function value: 311.060386
         Iterations: 111
         Function evaluations: 195

让我们来看看结果:

results # this gives us verbosity around our minimization
# notice our final key and associated values…--------------------------------------------------------------------
final_simplex: (array([[0.45115297, 3.03667376, 4.86925122],
       [0.45123459, 3.03666955, 4.86924261],
       [0.45116379, 3.03667852, 4.86921688],
       [0.45119056, 3.03666796, 4.8692127 ]]), array([300.18758478, 300.18758478, 300.18758478, 300.18758479]))
           fun: 300.18758477994425
       message: 'Optimization terminated successfully.'
          nfev: 148
           nit: 80
        status: 0
       success: True
             x: array([0.45115297, 3.03667376, 4.86925122])

我们可以进一步清理:

# drop results into df and round to match statsmodels
resultsdf = pd.DataFrame({'coef':results['x']})
resultsdf.index=['constant','x','sigma']   
np.round(resultsdf.head(2), 4)# do our numbers match the OLS model?
--------------------------------------------------------------------

你会注意到 OLS 和我很相配!你的结果会有所不同,因为我们没有使用随机种子。

MLE 的最佳实践

在我们更进一步之前,这可能是一个加强我们对 MLE 信任的好时机。作为我们的回归基线,我们知道,根据定义,普通最小二乘法是具有正态分布残差并满足线性回归的其他假设的连续结果的最佳线性无偏估计量。使用最大似然法来寻找我们的系数是否稳健?

是的!

  • MLE 与 OLS 一致。
  • 对于无限的数据,它将估计最佳的 β,并很好地近似它用于小而健壮的数据集。
  • MLE 是高效的;没有一致的估计量具有比 MLE 更低的渐近均方误差。

所以看起来它完全复制了 OLS 的做法。那么…为什么用 MLE 而不是 OLS?

因为!

  • MLE 对于回归和分类是可推广的!
  • MLE 是高效的;如果你使用正确的分布,没有一致的估计比 MLE 有更低的渐近误差。

我们可以将 MLE 视为通过优化概率成本函数来拟合模型的模块化方式!

应用 MLE 的四个主要步骤:

  1. 定义可能性,确保您对回归或分类问题使用正确的分布。
  2. 取自然对数,将乘积函数简化为和函数。
  3. 最大化——或最小化目标函数的负值。
  4. 验证制服前科是一个安全的假设!否则,你可以将数据归因于一个生成函数或世界模型,它不符合简约法则。

在最大似然估计空间中有更多的东西,包括分类分布,使用贝叶斯统计软件包如PyMC3等。但是今天我们就讲到这里。

您如何在数据科学工作流程中使用 MLE?在下面评论,或者在 LinkedIn 或者 Twitter 上联系我!

特别感谢 查德·谢勒 的优秀同行点评。

神经网络简介

原文:https://towardsdatascience.com/a-gentle-introduction-to-neural-networks-14e5c02bafe?source=collection_archive---------16-----------------------

神经网络系列

神经网络系列—第 0 章

序言注释

这个故事是我正在创作的关于神经网络的新系列的第一部分。作为一名前研究人员,我喜欢让自己跟上研究领域的最新发展,我也喜欢写作。我最近一直在努力做到这一点,直到我想到了一个主意:如果我强迫自己通过写作来强迫自己阅读和调查更多的东西,会怎么样?所以我想出了这个从零开始的想法,深入研究神经网络领域的历史,从基础直到今天应用的复杂的神经网络架构。这个系列对我个人来说有两个挑战:填补知识上的空白(我很确定我不是什么都知道),以及确保我可以开始一个想法并坚持到底而不放弃。

我决定将这一章命名为第 0 章,因为在这篇文章中,我将只解释该领域的最初历史步骤,为什么神经网络存在,它们用于什么,以及神经生物学和计算机科学之间的桥梁是什么。

神经网络

神经网络是一种人工智能连接主义方法,能够学习如何执行模式识别或过程控制任务,而无需显式编程。神经网络应用的一些例子可以是(1) 控制房间的温度,(2) 识别图片/视频中的人脸,(3) 生成文本序列。它们受到我们大脑工作方式的启发,通过连接和引起多个基本实体之间的交互来实现最终目标。这些实体被称为神经元(根据这些算法和我们大脑工作方式之间的整体相似性)。神经元可以与其他神经元相互作用,这取决于它们相互连接的方式以及它们的连接有多强。

这个过程是如何从生物学转化到计算机科学的?

从生物学上讲,神经元由 3 个主要部分组成:树突、核/细胞体和轴突。其完整结构如图 1 所示。

Figure 1: Structure of a neuron. Image taken from this lifehacker article

树突以电脉冲的形式接收来自其他神经元的信息。细胞体是接收和处理来自树突的信息的地方。这种处理的结果然后通过轴突传导,直到它到达末端(突触)。然后,信息通过一个称为突触过程的化学过程传递给另一个树突神经元。在整个人类生活中,许多神经元被创建和死亡,神经元之间的许多连接被创建,而其他连接则不复存在(这是一种过于简化的说法,但它让你了解了我们大脑的动态)。

根据赫布边理论,当它们之间的突触过程重复发生时,这些连接的强度会更大。换句话说,两个神经元一起放电越多,它们之间的联系就越强。另一方面,如果两个神经元从未一起被激发,它们的连接就会变弱。这条规则被称为赫布规则

一些人认为赫布法则是经典条件作用的一种形式(也称为巴甫洛夫学习)。经典条件反射是一种应用于刺激的联想学习形式。这个想法是将两种刺激联系在一起,这样它们就可以共享相同的反应。在巴甫洛夫的实验中,以他的名字命名这个概念的人,他训练他的狗,给它们食物,同时按铃。因为一旦给了狗食物,狗就会开始分泌唾液,在重复这个食物-铃的联系相当多的次数后,他的狗一听到铃响就开始分泌唾液。赫比学习也是如此:如果代表'获取食物'的最终神经元与流涎反应相关,并且如果'听觉铃'神经元和'获取食物'神经元之间的连接受到刺激,从而变得更强,那么在某个点激发'听觉铃'神经元就足以引起相同的流涎反应。

1943 年,麦卡洛克和皮茨提出了一个数学模型,能够捕捉神经元的这些生物特征。图 2 描述了神经元的这种数学模型的模式。这个被称为麦卡洛克-皮茨神经元

Figure 2: Schema of the McCulloch-Pitts neuron

麦卡洛克-皮茨神经元有三个组成部分:

  • 一组加权输入(xw )。它们分别代表输入和连接强度。赫布规则是关于刺激或减弱神经元之间的连接,取决于它对两个神经元一起放电的重要性。 w 的角色就是这个意思:描述关系的优势。它们被称为权重,因为它们量化了连接的权重。 x 映射到从突触中一个神经元的轴突末端传递到其他神经元的树突的输入。
  • 一个加法器(即 z )。这代表负责将所有输入信号整理和聚集成统一电脉冲的核/细胞体,该电脉冲稍后将沿着轴突传输。用数学术语来说,麦卡洛克和皮茨将这种聚合转化为输入( x )和权重( w )之间的点积。但这意味着什么呢?让我们使用图 2 中的例子。向量 xx₀x₁x ₂组成,而向量 w 具有元素 w₀w₁w那么 x 和 w 的点积就是:x₀×w₀x₁×w₁x×w₂.让我们用数学符号将这个逻辑形式化。

  • 一个激活功能(f(z)块)。激活功能的作用是决定整理后的信号的输出,并基于整理后的信号检查神经元是否应该触发。神经元的这一部分是一个数学函数,它抓取 z 并基于该函数计算输出 y 。麦卡洛克和皮茨提出的方法是阈值函数。基本上定义一个阈值电平𝜃,如果 z 大于𝜃,输出将是 1 ,否则输出将是 0

让我们尝试一个端到端的例子。想象你有一个神经元,它有输入: x₀﹦2x₁﹦-0.75x ₂﹦ 2 ,还有权重 w₀﹦-1w₁﹦-1w ₂﹦ 1 。所以,要做的第一件事就是计算 z。根据之前定义的方程,z2×(-1)﹢(-0.75)×(-1)2×10.75。最后一步是计算激活函数 f(z) 。例如,让我们假设一个𝜃﹦为 0 的阈值函数。因为 0.75 > 0 我们的输出会是 1

我已经解释了最基本的神经网络是如何工作的。但真的是全部吗?你现在已经理解了网络如何基于外部输入或来自环境的传感器来计算其输出/预测/结果,但是在这个解释中描述的学习过程在哪里呢?答案是:无处!神经网络学习的方式是通过找到向量 w 的正确值,这些值将增加网络根据提供的输入正确猜测答案的次数。向量 w 在很大程度上是神经网络中的“内部”,因此尝试不同的值是我们可以用来训练网络的。那么这些权重 w 如何修改才能提高网络质量呢?我将在我的下一章:感知机网络中谈论这个。敬请期待!

感谢阅读!你喜欢这篇文章吗?非常感谢你的反馈,🗣。你可以随时在 TwitterLinkedIn 上联系我,或者如果你对下一章的最新消息感兴趣,就在 Medium 上关注我😀。

一些相关阅读:

  • 【1】神经网络简介、优势及应用作者Jahnavi Mahanta;
  • 【2】神经网络简介作者约翰·奥拉芬瓦;
  • [3] 对神经网络的可视化介绍作者shik har Sharma;
  • [4] 人工神经网络——简介作者 Tharani Gnanasegaram 。
  • 【5】麦卡洛克-皮茨神经元——人类第一个生物神经元的数学模型作者阿克谢·钱德拉·拉甘杜拉

神经网络系列简介—第 1 部分

原文:https://towardsdatascience.com/a-gentle-introduction-to-neural-networks-series-part-1-2b90b87795bc?source=collection_archive---------1-----------------------

神经网络系列简介(GINNS)。

介绍

神经网络和深度学习是计算机科学和技术行业的重要话题,它们目前为图像识别、语音识别和自然语言处理中的许多问题提供了最佳解决方案。最近,许多论文发表了人工智能,它可以学习绘画,建立 3D 模型,创建用户界面(pix2code),有些可以根据一个句子创建图像,还有许多令人难以置信的事情正在使用神经网络进行日常工作。

我正在撰写这一系列关于神经网络和深度学习的帖子,我将指导您学习人工神经网络(ANN)的基本概念,向您展示从简单网络模拟与门到使用卷积神经网络(CNN)、递归神经网络(RNN)等解决图像识别任务的示例。代码将始终用 python 编写,有时会借助 Tensorflow(我不期望您是使用 Tensorflow 的专家,因为我将尝试详细解释代码)。

议程

  • 神经网络导论(本帖)
  • 与门神经网络(感知器)和异或门前馈神经网络(2 层)。
  • 使用 CNN 进行首次数字识别
  • 用 RNN 识别第一位数字

神经网络

神经网络,更确切地说是“人工”神经网络(ANN)的定义是由第一台神经计算机的发明者 Robert Hecht-Nielsen 博士提出的。他将神经网络定义为:

"...由许多简单、高度互联的处理元件组成的计算系统,这些元件通过对外部输入的动态响应来处理信息

或者,你也可以将人工神经网络视为计算模型,它是受人脑中生物神经网络处理信息的方式的启发。

生物动机和联系

大脑的基本计算单元是一个神经元。在人类神经系统中可以找到大约 860 亿个神经元,它们与大约 10 个⁴-10 个⁵ 突触相连。下图显示了一个生物神经元(左)和一个常见数学模型(右)的卡通图。

biological neuron (left) and a common mathematical model (right)

神经网络中的基本计算单元是神经元,通常称为节点或单元。它接收来自其他节点或外部源的输入,并计算输出。每个输入都有一个相关的
权重(w ),该权重根据其对其他输入的相对重要性进行分配。该节点对其输入的加权和应用一个函数。

这个想法是,突触强度(权重 w )是可以学习的,并控制影响的强度和方向:一个神经元对另一个神经元的兴奋性(正权重)或抑制性(负权重)。在基本模型中,树突将信号传递到细胞体,并在那里进行汇总。如果最终总和高于某个阈值,神经元就会触发,沿着其轴突发出一个尖峰信号。在计算模型中,我们假设尖峰脉冲的精确时间并不重要,只有放电的频率才能传递信息。我们用一个激活函数 (e.x sigmoid function) 来模拟神经元的放电频率,它代表了沿着轴突的尖峰的频率。

神经网络体系结构

从上面的解释中,我们可以得出结论,神经网络由神经元组成,从生物学上讲,神经元通过突触连接,信息在突触中流动(计算模型的权重),当我们训练神经网络时,我们希望神经元在从数据中学习到特定模式时触发,我们使用激活函数对触发率进行建模。

但这并不是一切……

  • 输入节点(输入层):这一层内不做任何计算,它们只是把信息传递给下一层(大部分时间是隐藏层)。节点块也被称为
  • 隐藏节点(Hidden layer):中的隐藏层是进行中间处理或计算的地方,它们执行计算,然后将权重(信号或信息)从输入层传递到下一层(另一个隐藏层或输出层)。有一个没有隐藏层的神经网络是可能的,我稍后会解释这一点。
  • ****输出节点(输出层):这里我们最后使用一个激活函数,它映射到所需的输出格式(例如用于分类的 softmax)。
  • 连接和权重:网络由连接组成,每个连接将神经元 I 的输出传输到神经元 j 的输入。从这个意义上来说, ij 的前任,而 ji 的继任者,每个连接都被赋予一个权重 Wij。**
  • 激活函数:给定一个输入或一组输入,节点的激活函数**定义该节点的输出。一个标准的计算机芯片电路可以被看作是一个激活功能的数字网络,激活功能可以是“开”(1)或“关”(0),这取决于输入。这类似于神经网络中线性感知器的行为。然而,正是非线性激活函数允许这样的网络仅使用少量节点来计算非平凡的问题。在人工神经网络中,这个函数也称为传递函数。
  • 学习规则:学习规则是修改神经网络参数的规则或算法,目的是使网络的给定输入产生有利的输出。这个学习过程通常相当于修改权重和阈值。**

神经网络的类型

神经网络有许多类别,这些类别也有子类,这里我将列出最常用的类别,并使学习神经网络的过程变得简单。

1.前馈神经网络

前馈神经网络是一种人工神经网络,其中单元之间的连接不也不形成循环。在这个网络中,信息只在一个方向上移动,即从输入节点向前,通过隐藏节点(如果有的话)到达输出节点。网络中没有循环或环路。

我们可以区分两种类型的前馈神经网络:

1.1。单层感知器

这是最简单的前馈神经网络,不包含任何隐藏层,这意味着它只由单层输出节点组成。之所以说这是单一的,是因为当我们计算层数时,我们不包括输入层,原因是因为在输入层不进行任何计算,输入通过一系列权重直接馈入输出。

Simple Perceptron

1.2.多层感知器(MLP)

这类网络由多层计算单元组成,通常以前馈方式互连。一层中的每个神经元都与下一层的神经元有直接连接。在许多应用中,这些网络的单元应用 sigmoid 函数作为激活函数。MLP 非常有用,一个很好的原因是,它们能够学习非线性表示(大多数情况下,呈现给我们的数据不是线性可分的),我们将在下一篇文章中展示的示例中回来分析这一点。

MLP

1.3.卷积神经网络(CNN)

卷积神经网络与普通神经网络非常相似,它们由具有可学习权重和偏差的神经元组成。在卷积神经网络(CNN 或 ConvNet 或移位不变量或空间不变量)中,单元连接模式受到视觉皮层组织的启发,单元在称为感受野的受限空间区域中对刺激做出反应。感受野部分重叠,覆盖整个视野。单位响应可以通过卷积运算进行数学近似。它们是使用最少预处理的多层感知器的变体。它们广泛应用于图像和视频识别、推荐系统和自然语言处理。CNN 需要大量数据进行训练。

CNN for image classification

2.递归神经网络

在递归神经网络(RNN)中,单元之间的连接形成了一个有向循环(它们向前传播数据,但也向后传播数据,从后面的处理阶段到前面的阶段)。这允许它展示动态的时间行为。与前馈神经网络不同,rnn 可以使用其内部存储器来处理任意输入序列。这使得它们适用于诸如未分段的、连接的手写识别、语音识别和其他通用序列处理器的任务。

常用的激活功能

每个激活函数(或非线性)取一个数字,并对其执行某个固定的数学运算。以下是一些您在实践中经常会发现的激活功能:

  • 乙状结肠
  • ReLU
  • 泄漏的 ReLU

有关更多详细信息,请遵循此激活功能帖子以及此cs 231n(CNN)课程笔记。

人工神经网络和大脑

人工神经网络不像我们的大脑那样工作,人工神经网络只是简单粗糙的比较,生物网络之间的连接比那些由人工神经网络架构实现的要复杂得多,记住,我们的大脑要复杂得多,我们需要从中学习更多。关于我们的大脑,有许多事情我们不知道,这也使得我们很难知道我们应该如何在人类层面上模拟一个人工大脑来进行推理。每当我们训练一个神经网络时,我们希望我们的模型学习最佳权重(w ),该权重在给定输入信号或信息(x)的情况下最好地预测期望的结果(y)。

接下来是什么?

在下一篇文章中,我将带来一些代码示例,并解释我们如何训练神经网络。敬请期待!

参考资料:

  • 神经网络和深度学习
  • http://cs231n.github.io/neural-networks-1/

如果你喜欢这些作品,请留下你的掌声👏推荐这篇文章,让其他人也能看到。**

OCR 简介

原文:https://towardsdatascience.com/a-gentle-introduction-to-ocr-ee1469a201aa?source=collection_archive---------2-----------------------

想了解更多?参观www.Shibumi-ai.com

在这里阅读这个帖子的重访版本

介绍

光学字符识别(OCR)是最早解决的计算机视觉任务之一,因为在某些方面它不需要深度学习。因此,在 2012 年深度学习热潮之前就有不同的 OCR 实现,有些甚至可以追溯到 1914 年(!).

这让很多人以为 OCR 挑战是“解决了”,就不再有挑战性了。另一个来自类似来源的信念是,OCR 不需要深度学习,或者换句话说,使用深度学习进行 OCR 是一种矫枉过正。

任何实践计算机视觉或一般意义上的机器学习的人都知道,没有所谓的已解决的任务,这个案例也不例外。相反,OCR 仅在非常具体的用例上产生非常好的结果,但是一般来说,它仍然被认为是具有挑战性的。

此外,对于某些不需要深度学习的 OCR 任务,确实有很好的解决方案。然而,要真正迈向更好、更通用的解决方案,深度学习将是强制性的。

我为什么要写 OCR?

像我的许多作品/文章一样,这也是作为客户的项目开始的。我被要求解决一个特定的 OCR 任务。

在从事这项工作期间和之后,我得出了一些值得分享的结论和见解。此外,在集中精力完成一项任务后,很难停下来扔掉它,所以我继续我的研究,并希望获得一个更好、更通用的解决方案。

你会在这里找到什么

在这篇文章中,我将探索一些用于解决不同 OCR 任务的策略方法逻辑,并分享一些有用的方法。在最后一部分,我们将用代码解决一个现实世界的问题。这不应该被认为是一个详尽的评论(不幸的是),因为这种方法的深度、历史和广度对于这种博客文章来说太广了。

然而,和往常一样,我不会放过你参考文章、数据集、知识库和其他相关的博客文章。

OCR 的类型

如前所述,OCR 有不止一种含义。从最普遍的意义上来说,它指的是从每一个可能的图像中提取文本,无论是一本书的标准印刷页,还是一张随机的带有涂鸦的图像( in the wild )。在这之间,你可能会发现许多其他任务,比如阅读车牌,无人机器人验证码街道标志等。

尽管这些选项中的每一个都有自己的困难,但显然“在野外”的任务是最难的。

Left: Printed text. Right: text in the wild

从这些例子中,我们可以得出 OCR 任务的一些属性:

  • 文字密度:在打印/书写的页面上,文字密度大。然而,给定一个只有一个街道标志的街道图像,文本是稀疏的。
  • 文本的结构:页面上的文本是结构化的,大部分是严格的行,而野生的文本可能会以不同的旋转方式散落在各处。
  • 字体:印刷字体更容易,因为它们比嘈杂的手写字符更有结构。
  • 字符类型:文本可能以不同的语言出现,这些语言可能彼此非常不同。此外,文本的结构可能不同于数字,例如门牌号等。
  • 伪像:很明显,室外照片比舒适的扫描仪要嘈杂得多。
  • 位置:一些任务包括裁剪/居中的文本,而在其他情况下,文本可能位于图像中的随机位置。

数据集/任务

SVHN

一个很好的起点是街景门牌号数据集。顾名思义,这是从谷歌街景中提取的一组门牌号数据。任务难度中等。数字以各种形状和书写风格出现,然而,每个门牌号位于图像的中间,因此不需要检测。这些图像的分辨率不是很高,它们的排列可能有点奇特。

车牌

另一个常见的挑战是车牌识别,这在实践中不是很难,也不是很有用。这个任务和大多数 OCR 任务一样,需要检测车牌,然后识别它的字符。由于车牌的形状相对恒定,一些方法在实际识别数字之前使用简单的整形方法。以下是一些来自网络的例子:

OpenALPR example. with car type a s abonus

  1. OpenALPR 是一个非常强大的工具,不需要深度学习,可以识别不同国家的车牌
  2. 这个 repo 提供了 CRNN 模型的实现(将进一步讨论)来识别韩国车牌。
  3. 监督. ly,一家数据应用公司,写了关于使用他们的工具生成的人工数据来训练一个车牌识别器(人工数据也将被进一步讨论)

验证码

由于互联网上到处都是机器人,区分它们和真正人类的常见做法是视觉任务,特别是文本阅读,又名验证码。这些文本中的许多是随机的和扭曲的,这应该使计算机更难阅读。我不确定开发验证码的人是否预测到了计算机视觉的进步,但是今天大多数文本验证码并不难解决,尤其是如果我们不试图一次解决所有的验证码。

Facebook knows how to make challenging CAPTCHAs

亚当·盖特基提供了一个不错的教程,用深度学习解决一些验证码,其中包括再次合成人工数据。

PDF OCR

OCR 最常见的情况是印刷/pdf OCR。打印文档的结构化特性使得解析它们变得更加容易。大多数 OCR 工具(例如 Tesseract )主要是为了解决这个任务,并获得良好的结果。因此,我不会在这篇文章中对这个任务做过多的阐述。

野外的 OCR

这是最具挑战性的 OCR 任务,因为它将所有一般的计算机视觉挑战(如噪声、光照和伪像)引入 OCR。此任务的一些相关数据集是 coco-text 和 SVT 数据集,它们再次使用街景图像来提取文本。

COCO text example

合成文本

SynthText 不是一个数据集,甚至可能不是一个任务,但提高训练效率的一个好主意是人工数据生成。由于文本的扁平性质,在图像上随意添加字符或单词看起来比其他任何物体都要自然。

我们之前已经看到了一些为简单任务生成的数据,比如验证码和车牌。在野外生成文本稍微复杂一点。该任务包括考虑图像的深度信息。幸运的是,SynthText 是一个很好的作品,它接收带有上述注释的图像,并智能地散布文字(来自新闻组数据集)。

SynthText process illustration: top right is the segmentation of an image, bottom right is the depth data. Bottom left is a surface analyses of the image, which according to text is sprinkled on the image.

为了使“分散”的文本看起来真实而有用,SynthText 库为每幅图像设置了两个遮罩,一个是深度遮罩,另一个是分段遮罩。如果您喜欢使用自己的图像,也应该添加这些数据

  • 建议查看 repo ,自己生成一些图像。你应该注意,回购使用了 opencv 和 maptlotlib 的一些过时版本,所以一些修改可能是必要的。

Mnist

虽然这并不是一个真正的 OCR 任务,但是要写 OCR 而不包括 Mnist 例子是不可能的。最广为人知的计算机视觉挑战实际上并不是一项经过深思熟虑的 OCR 任务,因为它一次只包含一个字符(数字),而且只有 10 个数字。然而,它可能暗示了为什么 OCR 被认为是容易的。此外,在一些方法中,每个字母将被单独检测,然后 Mnist like(分类)模型变成 relevantץ

战略

正如我们已经看到和暗示的,文本识别主要是一个两步任务。首先,您希望检测图像中的文本外观,可能是密集的(如在打印的文档中)或稀疏的(如在野外的文本)。

在检测行/字级别之后,我们可以再次从一大组解决方案中进行选择,这些解决方案通常来自三种主要方法:

  1. 经典的计算机视觉技术。
  2. 专业化的深度学习。
  3. 标准深度学习方法(检测)。

让我们逐一检查一下:

1.经典的计算机视觉技术

如前所述,计算机视觉解决各种文字识别问题由来已久。你可以在网上找到很多例子:

  • 伟大的阿德里安·罗斯布鲁克在他的网站上有大量的教程,像这个一个,这个一个和更多的。
  • 堆栈溢出也有一些像这个一样的宝石。

经典 CV 方法通常声称:

  1. 应用滤镜让人物从背景中凸显出来。
  2. 应用轮廓检测逐个识别字符。
  3. 应用图像分类识别字符

显然,如果第二部分做得好,第三部分很容易,无论是模式匹配还是机器学习(例如 Mnist)。

然而,轮廓检测对于概括来说是相当具有挑战性的。它需要大量的手动微调,因此在大多数问题中变得不可行。例如,让我们将一个简单的计算机视觉脚本从应用到来自 SVHN 数据集的一些图像上。第一次尝试我们可能会取得很好的结果:

但是当角色之间的距离越来越近时,事情就开始变得不可收拾了:

我艰难地发现,当你开始摆弄参数时,你可能会减少这样的错误,但不幸的是会引起其他错误。换句话说,如果你的任务不简单,这些方法就不合适。

2.专门的深度学习方法

大多数成功的深度学习方法都在通用性方面表现出色。然而,考虑到上述属性,专用网络可能非常有用。

我将在这里检查一些著名方法的非详尽示例,并对介绍它们的文章做一个快速总结。与往常一样,每篇文章都以“任务 X(文本识别)最近获得关注”为开头,并继续详细描述他们的方法。仔细阅读这些文章会发现,这些方法是从以前的深度学习/文本识别工作中收集的。

结果也描述得很透彻,但是由于设计上的许多差异(包括数据集的微小差异),实际比较是不可能的。真正了解这些方法在您的任务中的性能的唯一方法,是获取它们的代码(最好到最坏:找到官方的回购,找到非官方但评价很高的回购,自己实现)并在您的数据上尝试。

因此,我们总是更喜欢附有好的回购的文章,如果可能的话,甚至是演示。

EAST (高效准确的场景文本检测器)是一种简单而强大的文本检测方法。使用专门的网络。

与我们将要讨论的其他方法不同,只限于文本检测(不是实际的识别),但是它的健壮性值得一提。
另一个优势是它也被添加到 open-CV 库(从版本 4 开始)所以你可以很容易地使用它(见教程这里)。这个网络实际上是众所周知的 U 形网的一个版本,它可以很好地检测大小不同的特征。这个网络的底层前馈“stem”(如文中杜撰,见下图)可能非常— 文中使用 PVANet ,然而 opencv 实现使用 Resnet 。显然,它也可以被预先训练(例如使用 imagenet)。与 U-Net 一样,特征是从网络的不同层次提取的。

最后,网络允许两种类型的输出旋转边界框:带有旋转角度(2X2+1 个参数)的标准边界框或“四边形”,它只是带有所有顶点坐标的旋转边界框。

如果现实生活的结果就像上面的图片一样,那么识别这些文字并不需要太多的努力。然而,现实生活的结果并不完美。

CRNN

卷积回归神经网络是 2015 年的一篇文章,其中提出了一种混合(或三混合?)端到端架构,旨在以三步方法捕获单词。

其思想如下:第一层是标准的全卷积网络。网络的最后一层被定义为特征层,并划分为“特征列”。在下图中可以看到,每个这样的特征列是如何表示文本中的某一部分的。

然后,特征列被输入到深度双向 LSTM 中,后者输出一个序列,用于查找字符之间的关系。

最后,第三部分是转录层。它的目标是获取杂乱的字符序列,其中一些字符是冗余的,而另一些是空白的,并使用概率方法来统一和解释它。

这种方法叫做 CTC 丢失,在这里可以读到。该层可以与/或不与预定义的词典一起使用,这可以促进单词的预测。

本文在固定文本词典的情况下达到了高准确率(> 95%),在没有固定文本词典的情况下达到了不同的成功率。

STN-net/参见

参见 —半监督的端到端场景文本识别,是 Christian Bartzi 的作品。他和他的同事应用真正的端到端策略来检测和识别文本。他们使用非常弱的监督(他们称之为半监督,与通常意义不同)。因为他们训练网络只使用文本注释(没有边界框)。这允许他们使用更多的数据,但使他们的训练过程非常具有挑战性,他们讨论了不同的技巧来使其工作,例如,不要在超过两行文本的图像上训练(至少在训练的第一阶段)。

这份文件有一个更早的版本,叫做 STN OCR 。在最后的论文中,研究人员改进了他们的方法和陈述,此外,由于结果的高质量,他们更加强调他们方法的通用性。

SEE strategy

STN-OCR 的名字暗示了使用空间转换器的策略。

他们在中训练两个级联网络,其中第一个网络,即变换器,学习对图像的变换,以输出更容易解释的子图像。

然后,另一个 LSTM 在前的前馈网络(嗯…好像我们以前见过)识别文本。

研究人员在这里强调了使用 resnet 的重要性(他们使用了两次),因为它提供了到早期层的“强”传播。然而,这种做法如今已被广泛接受。

不管怎样,这都是一个有趣的尝试。

3.标准深度学习方法

正如标题所暗示的,在检测到“单词”后,我们可以应用标准的深度学习检测方法,如 SSD、YOLO 和 Mask RCNN。因为网上有太多的信息,所以我不打算详细说明这些方法。

我必须说这是我目前最喜欢的方法,因为我喜欢深度学习的“端到端”哲学,在这种哲学中,你可以应用一个强大的模型,通过一些调整可以解决几乎所有问题。在这篇文章的下一部分,我们将看到它实际上是如何工作的。

然而,当涉及到密集、相似的类时,SSD 和其他检测模型会受到挑战,如这里的所述。我觉得这有点讽刺,因为事实上,深度学习模型发现识别数字和字母比识别更具挑战性和复杂的物体(如狗、猫或人)要困难得多。它们往往达不到预期的精度,因此,专门的方法蓬勃发展。

实际例子

所以说了这么多之后,是时候动手了,试着自己做些模特。我们将尝试解决 SVHN 任务。SVHN 数据包含三个不同的数据集:训练测试额外。差异不是 100%清楚,但是最大的额外的数据集(约 50 万样本)包括更容易识别的图像。因此,为了这次拍摄,我们将使用它。

要准备该任务,请执行以下操作:

  • 你需要一台 Tensorflow≥1.4、Keras≥2 的基本 GPU 机器
  • 从这里克隆 SSD_Keras 项目。
  • 从这里下载 coco 数据集上预先训练好的 SSD300 模型。
  • 在此从克隆项目的回购..
  • 下载extra.tar.gz文件,其中包含 SVHN 数据集的额外图像。
  • 更新此项目报告中 json_config.json 中的所有相关路径。

为了有效地遵循流程,您应该阅读以下说明,并从项目的 repo 中运行 ssd_OCR.ipynb 笔记本。

而且…你已经准备好开始了!

步骤 1:解析数据

不管你喜不喜欢,但是在探测任务中没有“黄金”格式的数据表示。一些众所周知的格式有:coco、via、pascal、xml。还有更多。例如,SVHN 数据集用晦涩的进行了注释。mat 格式。幸运的是,这个要点提供了一个巧妙的 read_process_h5 脚本来转换。mat 文件转换为标准 json,您应该更进一步,将其进一步转换为 pascal 格式,如下所示:

def json_to_pascal(json, filename): #filename is the .mat file
    # convert json to pascal and save as csv
    pascal_list = []
    for i in json:
        for j in range(len(i['labels'])):
            pascal_list.append({'fname': i['filename'] 
            ,'xmin': int(i['left'][j]), 'xmax': int(i['left'][j]+i['width'][j])
            ,'ymin': int(i['top'][j]),  'ymax': int(i['top'][j]+i['height'][j])
            ,'class_id': int(i['labels'][j])})
    df_pascal = pd.DataFrame(pascal_list,dtype='str')
    df_pascal.to_csv(filename,index=False)*p = read_process_h5(file_path)*json_to_pascal(p, data_folder+'pascal.csv')

现在我们应该有一个更加标准的 pascal.csv 文件,它将允许我们继续前进。如果转换太慢,你应该注意到我们不需要所有的数据样本。~10K 就够了。

第二步:看数据

在开始建模过程之前,您最好对数据进行一些探索。我只为健全性测试提供了一个快速功能,但是我建议您做一些进一步的分析:

def viz_random_image(df):
    file = np.random.choice(df.fname)
    im = skimage.io.imread(data_folder+file)
    annots =  df[df.fname==file].iterrows() plt.figure(figsize=(6,6))
    plt.imshow(im) current_axis = plt.gca() for box in annots:
        label = box[1]['class_id']
        current_axis.add_patch(plt.Rectangle(
            (box[1]['xmin'], box[1]['ymin']), box[1]['xmax']-box[1]['xmin'],
            box[1]['ymax']-box[1]['ymin'], color='blue', fill=False, linewidth=2))  
        current_axis.text(box[1]['xmin'], box[1]['ymin'], label, size='x-large', color='white', bbox={'facecolor':'blue', 'alpha':1.0})
        plt.show() viz_random_image(df)

A representative sample form SVHN dataset

对于接下来的步骤,我在 repo 中提供了一个 utils_ssd.py ,以方便训练、负重等。部分代码取自 SSD_Keras repo,也是广泛使用的。

第三步:选择策略

如前所述,对于这个问题,我们有许多可能的方法。在本教程中,我将采用标准的深度学习检测方法,并将使用 SSD 检测模型。我们将从这里的使用 SSD keras 实现。这是 PierreLuigi 很好的实现。虽然它的 GitHub 明星比 rykov8 的实现少,但它看起来更新了,也更容易集成。当你选择使用哪个项目时,这是一件非常重要的事情。其他好的选择将是 YOLO 模型和掩模 RCNN。

步骤 4:加载并训练 SSD 模型

一些定义

要使用 repo,您需要验证您有 SSD_keras repo,并填写 json_config.json 文件中的路径,以允许笔记本找到这些路径。

从导入开始:

**import** **os**
**import** **sys**
**import** **skimage.io**
**import** **scipy**
**import** **json****with** open('json_config.json') **as** f:     json_conf = json.load(f)ROOT_DIR = os.path.abspath(json_conf['ssd_folder']) *# add here mask RCNN path*
sys.path.append(ROOT_DIR)

**import** **cv2**
**from** **utils_ssd** **import** *
**import** **pandas** **as** **pd**
**from** **PIL** **import** Image

**from** **matplotlib** **import** pyplot **as** plt

%matplotlib inline
%load_ext autoreload
% autoreload 2

以及更多的定义:

task = 'svhn'labels_path = f'{data_folder}pascal.csv'input_format = ['class_id','image_name','xmax','xmin','ymax','ymin' ]

df = pd.read_csv(labels_path)

车型配置:

**class** **SVHN_Config**(Config):
    batch_size = 8

    dataset_folder = data_folder
    task = task

    labels_path = labels_path

    input_format = input_format

conf=SVHN_Config()

resize = Resize(height=conf.img_height, width=conf.img_width)
trans = [resize]

定义型号,装载重量

与大多数深度学习案例一样,我们不会从头开始训练,但我们会加载预训练的权重。在这种情况下,我们将加载 SSD 模型的权重,在 COCO 数据集上训练,该数据集有 80 个类。很明显,我们的任务只有 10 个类,因此在加载权重后,我们将重建顶层以获得正确数量的输出。我们在 init_weights 函数中完成。补充说明:在这种情况下,正确的输出数量是 44:每个类 4 个(边界框坐标),另外 4 个用于背景/无类。

learner = SSD_finetune(conf)
learner.get_data(create_subset=**True**)

weights_destination_path=learner.init_weights()

learner.get_model(mode='training', weights_path = weights_destination_path)
model = learner.model
learner.get_input_encoder()
ssd_input_encoder = learner.ssd_input_encoder

*# Training schedule definitions*
adam = Adam(lr=0.0002, beta_1=0.9, beta_2=0.999, epsilon=1e-08, decay=0.0) 
ssd_loss = SSDLoss(neg_pos_ratio=3, n_neg_min=0, alpha=1.0)
model.compile(optimizer=adam, loss=ssd_loss.compute_loss)

定义数据加载器

train_annotation_file=f'**{conf.dataset_folder}**train_pascal.csv'
val_annotation_file=f'**{conf.dataset_folder}**val_pascal.csv'
subset_annotation_file=f'**{conf.dataset_folder}**small_pascal.csv'batch_size=4
ret_5_elements={'original_images','processed_images','processed_labels','filenames','inverse_transform'}train_generator = learner.get_generator(batch_size, trans=trans, anot_file=train_annotation_file,
                  encoder=ssd_input_encoder)val_generator = learner.get_generator(batch_size,trans=trans, anot_file=val_annotation_file,
                 returns={'processed_images','encoded_labels'}, encoder=ssd_input_encoder,val=True)

5.训练模型

现在模型准备好了,我们将设置一些与上次训练相关的定义,并开始训练

learner.init_training()history = learner.train(train_generator, val_generator, steps=100,epochs=80)

作为奖励,我在训练脚本中包含了 training_plot 回调,以在每个时期后可视化一个随机图像。例如,下面是第六个纪元后的预测快照:

SSD_Keras repo 在几乎每个时期后处理保存模型,因此您可以稍后加载模型,只需更改 weights_destination_path 行使其等于路径

weights_destination_path = <path>

如果你按照我的指示做,你应该能训练出这个模型。ssd_keras 提供了更多的特性,例如数据扩充、不同的加载器和评估器。经过短暂的训练,我已经达到了> 80 地图。

你达到了多高?

Training for 4X100X60 samples, from tensorboard

摘要

在这篇文章中,我们讨论了 OCR 领域的不同挑战和方法。正如深度学习/计算机视觉中的许多问题一样,它比乍看起来要复杂得多。我们已经看到了它的许多子任务,以及解决它的一些不同的方法,目前没有一个是银弹。另一方面,我们已经看到,没有太多的争论,达成初步结果并不困难。

希望你喜欢!

对强化学习或当你不知道该做什么时该做什么的温和介绍

原文:https://towardsdatascience.com/a-gentle-introduction-to-reinforcement-learning-or-what-to-do-when-you-dont-know-what-to-do-31faf5acd60b?source=collection_archive---------8-----------------------

今天我们要看一组有趣的学习算法,它不需要你在学习的时候知道真相。因此,这是无监督学习和有监督学习的混合。受监督的部分来自于这样一个事实,即你在采取行动后看着后视镜,然后根据你做得有多好来调整自己。这是惊人的强大,因为它可以学习知识表示允许它学习的任何东西。不过有一点需要注意的是,它慢得令人难以忍受。这自然源于没有正确解决方案的概念。无论是在你做决定的时候,还是在你评估决定的时候。你只能说“嘿,考虑到我之前的尝试,这还不算太糟”,但你不能说这是最好的选择。这降低了学习速度。好处是,只要我们能观察到我们在所处环境中行动的后果,我们就能了解任何事情。

如上所述,强化学习可以被认为是一个代理人在一个环境中行动,并作为这些行动的结果接收奖励。原则上,这是一个马尔可夫决策过程(MDP ),它基本上捕捉了你可能想在一个环境中学习的任何东西。从形式上看,MDP 包括

  • 一组状态
  • 一系列动作
  • 一套奖励
  • 一组转移概率

这看起来惊人的简单,但实际上是我们所需要的。任务是学习最佳转移概率,使预期的未来总回报最大化。因此,为了继续,我们需要引入一点数学符号。首先,我们需要一个奖励函数 R( sa ),它给我们奖励 r ,这来自于在时间 t 在状态 s 采取行动 a 。我们还需要一个转换函数 S( sa ),它将给出下一个状态S’。动作由代理按照一个或多个策略生成。因此,政策函数 P( s )生成一个动作 a ,据其所知,该动作将在未来给出最大回报。

我们要解决的问题——车杆

我们将利用 OpenAI 体育馆中的一个环境,叫做手推车杆子问题。这项任务基本上是学习如何通过控制手推车来平衡杆子。每次我们在环境中行动时,环境都会给我们一个新的状态。这种状态由对应于位置和运动的四个可观测量组成。这个问题之前已经由亚瑟·朱利安尼用张量流说明过。在向您展示实现之前,我们先来看看一个训练有素的代理是如何执行的。

正如你所看到的,它表现得很好,实际上通过实时控制手推车来平衡杆子。你可能会想,嘿,这听起来很容易,我只是生成随机动作,它应该会抵消。嗯,放心吧。下面你可以看到这种方法失败的例子。

所以对于眼前的问题。我们如何对此建模?我们需要制造一个智能体来学习一个能最大化未来回报的策略,对吗?对,所以在任何给定的时间,我们的政策可以选择两个可能的行动之一,即

  1. 向左移动
  2. 向右移动

如果你以前做过任何建模工作,这听起来应该很熟悉。这基本上是一个伯努利模型,其中概率分布看起来像这样 P(yp)=p**y**(1-**p**){1-y)。一旦我们知道了这一点,接下来的任务就是将 p 建模为当前状态 s 的函数。这可以通过做一个由 s 形包裹的线性模型来实现。更多数学细节请看看我的原帖。

履行

由于人工智能健身房大部分是用 Python 编写的,我们选择了用那种语言。这绝不是我对数据科学的首选语言,我可以给你 10 个有力的论据来说明为什么它不应该是你的,但因为这篇文章是关于机器学习而不是数据科学的,所以我不会扩展我的想法。无论如何,Python 对于机器学习来说是很棒的,这就是我们今天所看到的。所以让我们继续导入 Python3 中我们将需要的库。

import numpy as np
import math
import gym

在此之后,让我们看看初始化我们的环境,并设置一些变量和占位符,我们将需要。

env = gym.make('CartPole-v0')
# Configuration
state = env.reset()
max_episodes = 2000
batch_size = 5
learning_rate = 1
episodes = 0
reward_sum = 0
params = np.random.normal([0,0,0,0], [1,1,1,1])
render = False
# Define place holders for the problem
p, action, reward, dreward = 0, 0, 0, 0 ys, ps, actions, rewards, drewards, gradients = [],[],[],[],[],[]
states = state

除此之外,我们将使用一些需要定义的函数。我确信多种机器学习框架已经实现了它,但是它很容易做到,也很有指导性,所以为什么不去做呢。;)

您将需要的 python 函数

因为我们是在 Python3 中实现的,而 Python3 和 Python2 并不总是简单明了的,所以我与你分享我创建的函数定义,因为它们确实与 Python3 库兼容。尤其是 Numpy,它是 Python 中计算不可或缺的一部分。这些功能大部分都很容易实现和理解。确保你通读了它们并掌握了它们的全部内容。

def discount_rewards(r, gamma=1-0.99):
  df = np.zeros_like(r)
  for t in range(len(r)):
    df[t] = np.npv(gamma, r[t:len(r)])
    return df
def sigmoid(x):
  return 1.0/(1.0+np.exp(-x))
def dsigmoid(x): 
  a=sigmoid(x) return a*(1-a)
def decide(b, x):
  return sigmoid(np.vdot(b, x))
def loglikelihood(y, p):
  return y*np.log(p)+(1-y)*np.log(1-p)
def weighted_loglikelihood(y, p, dr):
  return (y*np.log(p)+(1-y)*np.log(1-p))*dr
def loss(y, p, dr):
  return -weighted_loglikelihood(y, p, dr)
def dloss(y, p, dr, x):
  return np.reshape(dr*( (1-np.array(y))*p - y*(1-np.array(p))),[len(y),1])*x

有了这些功能,我们就可以开始主要的学习循环,这是代理和培训的逻辑发生的地方。这将是最难的部分,所以要慢慢来。

学习循环

while episodes < max_episodes:
  if reward_sum > 190 or render==True: 
    env.render()
    render = True
  p = decide(params, state)
  action = 1 if p > np.random.uniform() else 0
  state, reward, done, _ = env.step(action) reward_sum += reward
  # Add to place holders
  ps.append(p)
  actions.append(action)
  ys.append(action)
  rewards.append(reward)
  # Check if the episode is over and calculate gradients
  if done:
    episodes += 1
    drewards = discount_rewards(rewards)
    drewards -= np.mean(drewards)
    drewards /= np.std(drewards)
    if len(gradients)==0:
      gradients = dloss(ys, ps, drewards, states).mean(axis=0)
    else:
      gradients = np.vstack((gradients, dloss(ys, ps, drewards, states).mean(axis=0)))
    if episodes % batch_size == 0:
      params = params - learning_rate*gradients.mean(axis=0)
      gradients = []
      print("Average reward for episode", reward_sum/batch_size)
      if reward_sum/batch_size >= 200:
        print("Problem solved!")
      reward_sum = 0
    # Reset all
    state = env.reset()
    y, p, action, reward, dreward, g = 0, 0, 0, 0, 0, 0
    ys, ps, actions, rewards, drewards = [],[],[],[],[]
    states = state
  else: 
    states=np.vstack((states, state))env.close()

唷!就在那里,还不算太糟,是吧?我们现在有一个完全工作的强化学习代理,它通过策略梯度学习来学习横竿问题。现在,对于那些了解我的人来说,你知道我总是宣扬考虑所有可能的解决方案,并且与你的数据一致。所以,也许横翻筋斗的问题有不止一种解决方法?确实有。下一节将向您展示这些解决方案在四个参数中的分布。

多重解决方案

因此,我们已经使用我们的学习代理解决了 CartPole 问题,如果您运行它多次,您将看到它收敛到不同的解决方案。我们可以在所有这些不同的解决方案上创建一个分布,这将告知我们由我们的参数化所支持的所有可能模型的解决方案空间。下面给出了曲线图,其中 x 轴是参数值,y 轴是概率密度。

你可以看到 X0 和 X1 应该在 0 左右,而 X2 和 X3 应该在 1 左右。但是如图所示,存在几种其他的解决方案。因此,学习代理自然会考虑到参数应该是什么的不确定性。

结论

我们实现了一个强化学习代理,它在一个以最大化未来回报为目的的环境中工作。我们还在代码中贴现了未来的回报,但在数学中没有包括它。尽管这很简单。能够从自己的错误中学习的概念是非常酷的,它代表了一种学习范式,这种范式既不是有人监督的,也不是无人监督的,而是两者的结合。这种方法的另一个吸引人的地方是,它非常类似于生物从与环境的互动中学习的方式。今天我们解决了翻筋斗,但是这种方法可以用来解决更有趣的问题。

我希望你在阅读这篇文章的时候觉得有趣,并且学到了一些东西。

推理快乐!

原载于doktormike . github . io

算法公平性讨论的温和介绍

原文:https://towardsdatascience.com/a-gentle-introduction-to-the-discussion-on-algorithmic-fairness-740bbb469b6?source=collection_archive---------1-----------------------

近年来,机器学习算法已经兴起:在打破了几乎所有可以想象的计算机视觉相关任务的基准之后,机器学习算法现在一直在我们的家里和口袋里。一个不太为人知的事实是,它们最近开始在一些更敏感的领域取代人类决策者,如刑事司法系统和医学测试领域。

当机器学习算法应用于人类时,一个直接的观察结果是,这些算法并不总是表现得“公平”。事实证明,以标准效用最大化目标(例如,最大化训练数据的预测准确性)训练机器学习算法有时会导致算法的行为方式让人类观察者认为不公平,尤其是对某个少数群体。

这种行为有许多潜在的原因。一个自然的怀疑是训练数据本身:机器学习算法本质上是大型计算机器,经过训练可以识别和利用数据中的统计模式。如果作为“基本事实”提供给它们的数据包含一些偏见或历史歧视,机器将会发现这种偏见,并将其纳入未来预测。一个很好的例子是[1]中的工作,其中作者证明了著名的单词嵌入模型 word2vec 实际上包含了隐含的性别偏见。我发现这很麻烦,因为许多应用程序现在使用经过训练的 word2vec 嵌入作为其机器学习管道中的第一个预处理阶段;这意味着这种偏见每天都在传播。

[1] gives a quantitative demonstration that word-embeddings contain gender biases in their geometry

克服这个问题的一种方法是,在假设历史偏差处于自我纠正过程的情况下,不断用“新鲜”数据重新训练机器学习模型。我不知道这是否是完美的解决办法,但有理由抱有希望。我喜欢的一个最近的例子是通过考虑 Getty Image 的库存摄影库中搜索词“女人”的最畅销图像在过去十年中的变化:2007 年最受欢迎的图像是一个躺在床上的裸体女人,而 2017 年最受欢迎的图像是一个独自在岩石小道上徒步旅行的女人。见[7]的整个演变和其他一些很酷的例子。如果你认为库存照片——出现在广告、广告牌、杂志和博客等地方的普通图片——反映了我们社会的任何事情,那么我们显然走在一条积极的道路上。

然而,一个不太令人期待的结果是,即使有完美标记的训练数据,偏见和歧视也可能以多种方式出现。[6]是一篇很棒的博文,讲述了机器学习算法即使有完全无偏的训练数据也可能不公平的各种原因。

最近一个著名的例子是谷歌照片错误地将两个黑人标记为“大猩猩”。显然,这并不是说谷歌用于这项任务的训练数据包含了被标记为“大猩猩”的黑人的例子。但是机器学习算法仍然会出错,在这种情况下,这是一个代价高昂且不公平的错误,因为它只发生在黑人身上,而不是白人。

研究分类中的公平性意味着不仅从准确性的角度,而且从公平性的角度来研究机器学习算法。听起来很简单,对吧?令人惊讶的是,大部分的困难实际上都围绕着如何定义公平的含义。在过去的几年里,许多研究人员定义了不同的算法公平概念。在许多情况下,这些定义在准确性方面有所取舍(也就是说,实现它们意味着必然要在模型的准确性方面付出代价),但更意想不到的是,这些定义中有许多本身也有取舍。

在本帖中,我们将围绕一个具体的例子来逐步引入不同的算法公平概念:为科技行业过滤简历。具体来说,我们将认为我们的特征空间 X 是一些可以从一个人的简历中计算出来的观察到的特征(例如:姓名、出生年份、地址、性别、编程语言、大学学位和学分等),如果这个人应该被带去面试,那么输出将是 Y=1,否则是 Y=0。出于这个例子的目的,我们的受保护属性(我们希望保证公平的属性)是性别,我们假设它是可观察的并且是二进制的。

第一站:过程的公平与结果的公平

我们介绍的第一个区别是“有意识的”和“无意识的”方法。“aware”算法将在学习过程中使用关于受保护属性的信息;“无意识”算法不会。

无意识方法背后的动机是,对于受保护的属性来说,公平本质上意味着不考虑它。在简历示例中,这意味着同等对待男性和女性的最佳方式就是不要让算法访问这些信息。

第一个观察结果是,仅仅删除受保护的属性通常是不够的。在大多数实际情况下,受保护的属性实际上被冗余地编码在其余的观察到的特征中;大多数最大似然算法都是复杂的计算机器,能够利用这一事实。例如,我们可能会删除性别特征,却发现我们的分类器非常重视一个人的军龄。为什么?在以色列,女性通常服刑两年,男性服刑三年。这意味着“服役年限”的特征几乎与性别完全相关;使用这个特性的分类器本质上不符合无意识方法。

实践中经常使用的一种快速修复方法是,也删除与受保护属性高度相关(例如,高于某个阈值)的所有其他属性。一个更严谨的方法(本身也是一个非常有趣的工作)是“学习公平表征”(Zemel et al,2013 [2])。它使用机器学习来代替手动设计不传达关于受保护属性的信息的特征列表的过程。

让我们假设我们成功了。完全无视性别的学习方式是我们真正想要的吗?受保护属性所定义的种群之间可能存在固有的差异,这实际上将使这成为不期望的。

在我们的例子中,假设高中主修物理高度预示着申请人未来在科技行业的成功,即使这并不是所需的实际物理知识。因此,这将是我们的分类器在简历中寻找的一个特征。然而,可以说,由于社会学的原因,以色列的年轻女孩比同龄的男孩更不愿意学习物理。这将意味着,通过完全无视性别信息,一种有利于具有物理学背景的申请人的算法给了男性申请人看似不公平的优势。这种现象通常被称为恢复“多数解”(这里的解是指理想候选人的原型),它自然会伤害少数。在我们的例子中,一名女性候选人可能同样合格,但被算法“遗漏”。

另一方面,“aware”方法——确实使用了性别信息——可以克服这一点,因为它实际上发现了这样一个事实,即学习物理对于男性未来的成功来说是一个比女性更强的信号。

另一种看待意识到和没有意识到的问题的方式是区分过程的公平性结果的公平性。无意识方法确保了过程的公平性:它强调了这样一个事实,即在学习阶段,算法不会以任何方式根据受保护的属性对个体进行不同的处理。然而,这样做的最终结果,几乎是矛盾的,实际上对受保护和不受保护的子群体不太公平。另一方面,aware 方法使用一个不公平的过程(明确使用性别信息,并为人口中不同部分的人学习不同的分类规则),但实际上可以达到对少数群体更公平的结果。

第二站:统计平价

为算法公平提出定义的一个自然方法是看看在计算机科学社区之外公平是如何被定义的,并把这些想法公式化为数学定义,我们的算法将遵循这些标准。

美国法律 理论使用了“不同影响”原则:如果一种行为对受保护群体的成员产生了“不成比例的不利”影响,那么这种行为就被认为是非法歧视。“不成比例的不利”通常使用 80%规则来定义。

用于二进制分类任务的不同影响原理的最极端版本(不允许对保护组的成员产生不利影响)的数学等价是统计奇偶校验条件:它本质上均衡了保护组和非保护组的结果。

Statistical Parity: equalize outcomes across the protected and non-protected groups

对统计均等概念及其变体的主要批评(例如允许两个群体之间的某种均等,例如高达 20%)是非常自然的:我们真的想让受保护群体和不受保护群体之间的结果均等吗?

在我们的简历示例中,这将迫使我们接受相同数量的女性和男性。鉴于一名计算机工程师因暗示女性不太适合科技和领导领域的某些角色而被谷歌解雇,最近关于这个问题有了非常公开的辩论。在不深入我对这一具体主张的想法的情况下,很明显,在许多其他任务中,实施统计均等没有什么意义。例如,考虑任何分类任务,其中受保护的属性和输出变量之间存在明确的因果关系,例如:预测某个人在未来十年内是否会生育。自然,在这里实施统计上的平等是可笑的。

步骤 3:扩展到跨组校准的其他概念

我们仍然希望在受保护群体和不受保护群体之间实现某种程度的平等。我们可以均衡算法性能的一些统计数据,而不是均衡结果本身:例如,均衡各组之间的错误率。在这种观点看来,筛选简历的公平算法是让男性求职者和女性求职者犯同样多的错误。

一个有用的分析工具是混淆矩阵:

一个混淆矩阵,也被称为误差矩阵,是一个特定的表格布局,允许可视化监督学习算法的性能

Confusion Table: A cross-tabulation of the actual outcome by the predicted outcome

这就是公平文献可能有点可怕的地方,因为许多定义之间有非常微妙的差异,很容易忘记它们的共同点。[5]做了大量工作,给出了详细的例子,说明如何通过比较受保护和不受保护的矩阵来定义公平性。一些例子:

  • 处理平等通过一个分类器实现,该分类器产生两个保护组类别相同的假阴性和假阳性比率(在表中,c/b 或 b/c)。
  • 当以已知结果为条件时,实现了条件程序准确性相等,分类器在保护组类别中同样准确。这相当于男女的假阴性率和假阳性率是一样的。

关于混淆矩阵的不可否认的数学事实是,细胞计数之间存在关系——例如,它们必须与观察的总数相加。这意味着不同种类的公平性——所有共享混淆矩阵中的细胞计数——也是相关的。事实上,已经表明有许多权衡。

顾名思义,权衡意味着没有单一的赢家:这是一个零和游戏。治疗平等性的一个小改进和条件使用准确性平等性的一个小改进哪个更好?[5]声称,虽然科学家有责任提出关于权衡的讨论,并可能设计算法,其中权衡被明确表示,并可作为易于调整的转向参数,但最终还是要由利益相关者来确定权衡。

参考

  1. 男人对于电脑程序员就像女人对于家庭主妇一样?去偏置单词嵌入
  2. 学习公平陈述

3.谷歌员工因多元化争议被解雇考虑采取法律行动

4.通过意识实现公平

5.刑事司法风险评估中的公平性:最新水平

6.大数据有多不公平

7.从性对象到坚韧不拔的女人:库存照片中女人的演变

从线性回归到神经网络的温和旅程

原文:https://towardsdatascience.com/a-gentle-journey-from-linear-regression-to-neural-networks-68881590760e?source=collection_archive---------0-----------------------

一些机器学习和深度学习概念的软介绍。

Credit: Pexels on Pixabay

介绍

深度学习是一个非常时髦的术语。主要原因是,相关技术最近显示出令人难以置信的能力,即使不是最先进的,也能在各种问题上产生非常好的结果,从图像识别到文本翻译。面对这种不断发展的技术,由于数据和计算机能力的增加而成为可能,对于没有入门的人来说,有时很难真正知道“幕后发生了什么”。什么是深度学习?神经网络是如何工作的?

我们希望通过这篇文章,帮助消除与主题相关的大部分困惑或疑问,并为正确的(即使是非常基本的)理解和一些有洞察力的直觉创造空间。

为此,我们将尝试给出一些简单的答案来理解什么是深度学习,尤其是神经网络是如何工作的。我们将利用例子、说明、类比和任何能使理解尽可能容易的东西。我们在这里的目标更多的是让主要的指导方针尽可能的清晰,而不是用一些技术细节来阻碍读者的理解(尽管这可能非常有趣)。特别是,我们将从简单的问题到更困难的问题,以展示神经网络如何自然地(至少在精神上)扩展一些众所周知的技术。显然,在我们的过程中,我们将不得不进行一些简化或省略一些细节。如果在某些方面,它会让更高级的读者感到沮丧,我们提前道歉。

由于本文的目的主要是给读者一个简单的概述和一些直觉,以符合机器学习、深度学习和神经网络的主要思想,因此后面的大部分内容不需要高级的数学背景。

概述

在第一部分,我们给出了机器学习的定义,并用线性回归这个非常基本的例子说明了机器学习技术是如何从数据中提取知识的。

然后,在第二部分中,我们表明问题通常比真正简单的线性回归更难,并且需要一些更高级的机器学习技术。我们介绍了这样一个事实,即具有更好预测能力的更先进的模型,通常是以模型的优化或可解释性的更高难度为代价的,然后简要讨论了这两个问题。

最后,在最后一节中,我们看到对于一些真正复杂的问题,我们可以选择放弃(部分或全部)可解释性来设计具有更好预测能力的模型。我们介绍深度学习,尤其是神经网络。我们展示了在何种意义上神经网络可以被视为我们的初始线性回归例子的自然延伸,并讨论了反向传播算法。

基础机器学习

什么是机器学习?

计算机游戏和人工智能领域的先驱亚瑟·塞缪尔(Arthur Samuel)将机器学习(ML)定义为在没有明确编程的情况下赋予计算机学习能力的研究领域。换句话说,无论我们算法的目的是什么,实现这一目标的规则都不是显式编程的,而是由计算机根据一些有用的数据“学习”(稍后我们将回到这个词)。这是与经典算法的最大区别。

在经典算法中,规则被明确地给予计算机来执行任务。在机器学习算法中,定义一系列可能规则的模型(参数化或未参数化)与一大堆数据和基于这些数据在可能规则中寻找更好规则的策略一起提供给计算机(优化)。在下一段中,我们将在现有的最基本的机器学习模型之一中明确所有这些元素:线性回归。

简单线性回归

线性回归是我们能想到的最简单的机器学习算法的例子之一。让我们看看它完全符合我们上面给出的描述。假设你有一堆关于房子两个属性的数据:面积(用 s 表示)和价格(用 p 表示)。现在,假设您想要一个程序,它以房子的大小作为参数,并返回一个价格,即该房子的估计价格。第一种选择是对规则进行显式编程。在这种情况下,这意味着我们必须明确定义函数 f 使得 p = f(s)。 换句话说,我们必须明确给出价格,作为尺寸的明确函数。然而我们可能不知道这个函数是什么,或者我们可能只有一个模糊的概念。如果是这样的话,我们可以依靠数据以 ML 的方式建立我们的规则。然后,我们首先定义一组(一族)规则:在这个例子中,我们假设一个线性规则表达了价格和大小之间的联系。因此,我们现在已经知道 f 具有形式 f(s)=as+b ,具有 ab 未指定的参数(自由度),这些参数需要基于可用数据并遵循给定策略来定义。传统上,对于线性回归,这种策略非常简单,包括选择b 以最小化真实输出和预测输出之间的误差平方和。这可以在线性回归的情况下分析完成(我们可以找到一个封闭形式的解决方案)。但是我们会看到事情并不总是那么容易。然而,我们可以注意到,在这个例子中,我们有三个提到的部分:一个(参数化的)模型,一些数据和一个优化策略(一种找到最佳参数的方法)。我们将在本文讨论的更高级的方法中再次遇到这个三联体(模型/数据/优化)。

非参数化模型

前面的线性回归的例子是参数化模型的例子,其中b 是参数。在本文中,我们将主要讨论这类模型,因为我们想展示向(高度)参数化的神经网络的过渡。然而,人们应该记住,也存在非参数化模型。然而,三联画保持不变。该模型仍然定义了一组可能的函数,并且在该组函数中的选择是基于遵循给定优化策略(大多数情况下是误差最小化)的可用数据进行的。**

高级机器学习

问题往往会变得更难

当然,问题不能总是用线性回归这样简单的方法来解决,在大多数情况下,我们将不得不建立更复杂的模型。有些问题甚至不符合线性回归所建议的具体框架(即:取一些真实的输入,返回一个真实的输出)。然而,无论我们选择哪种方法,我们总能恢复我们潜在的三联模型/数据/优化。

例如,假设您有一些关于客户使用您的某项服务的数据,并且您想要一个工具来根据这些数据预测客户是否会流失。在本例中,要预测的输出不是一个实数值,而是一个二进制值(两类问题),因此,我们面对的是分类问题,而不是回归问题。然后,输出预测应该是 0 和 1 之间的变动概率,并且具有无界输出的线性回归应该例如通过在线性输出之上应用专用非线性函数而转变成逻辑回归。

另一个例子是考虑一个客户细分问题。假设您有一些关于客户的数据,并且希望展示这些数据中的聚类,以便获得客户细分。这里的问题不再是一个监督的问题。事实上,我们不想学习一些输入和给定输出(监督)之间的映射,而是在未标记的数据(非监督)中寻找一些结构。

即使我们不打算给出每一种机器学习算法的细节,我们也可以给出以下大图:更高级的模型旨在表达数据中更复杂的结构,但这可能是以优化或解释模型的一些困难为代价的。让我们以后讨论这两点。

最佳化

一旦定义了模型,就必须对其进行优化,使其“刚好足以”拟合数据,以捕捉数据中的相关总体结构,同时忽略不相关的特定“噪声”(我们将在后面讨论“过度拟合”的概念)。事实上,正如前面提到的,一个模型定义了一个空间(这个模型的可能“实例”),我们需要在这个空间中找到关于一个选择的度量的最佳点(一种评估空间中每个点的质量的方法)。该指标通常由误差项定义,惩罚与数据不匹配的模型实例,有时还加入正则化项,惩罚过于复杂和过于接近数据的模型实例。然后,我们可以把我们得到的最优化问题主要分为三类。

首先,对于非常简单的方法,我们可以面对一个二次型优化问题。这里我们指的是有可能找到我们问题的封闭形式解的情况(我们知道如何用数学方法表达问题的解)。线性回归显然就是这样一种方法。事实上,我们可以获得一个封闭形式的解决方案是非常有吸引力的,但也反映了简单,因此无法捕捉数据中的复杂结构,由模型定义的空间。

Quadratic minimisation with linear derivative. Finding the minimum is straightforward in an analytical way : we just need to find the 0 of a linear function.

那么,优化问题可以是非二次的,而是凸的。非二次优化问题通常不能用解析方法解决,大多数时候需要迭代方法。这些迭代方法背后的主要思想是从空间的给定点开始——由我们的模型描述的空间,其中一个点是模型的一个实例,例如具有特定参数——并通过在每次迭代中选择在我们的空间中的最佳可能方向上迈出一小步(取决于我们如何定义“最佳”的概念)来尝试改进这个解决方案迭代。这些迭代方法可以采取不同的形式,如各种梯度下降变量、EM 算法等,但最终的基本思想是相同的:我们无法找到直接的解决方案,所以我们从给定点开始,一步一步地前进,在每次迭代中朝着改进当前解决方案的方向迈出一小步。关于梯度下降的图示,请参见下图。对于这种迭代方法,空间的凸性是一个非常重要的性质,它确保无论选择什么样的起点,我们都将达到全局最优(我们将获得的模型实例将是关于定义的优化问题的最佳可能实例)。

Convex minimisation. Finding the minimum is not straightforward and require iterative approach (as the derivative is no longer linear). Here, we used gradient descent. However, convexity ensure that iterative approach will reach the global minimum.

最后,由模型定义的空间可以是非凸的,然后我们面临一个非凸优化问题。在这种情况下,非线性将再次影响迭代方法的使用。然而,非凸性使得我们不再确定迭代过程将在整个空间上达到最佳可能点。换句话说,我们获得的最优(模型的实例)高度依赖于我们选择的起点。这显然是我们所能面对的最优化问题的最坏情况,也是一些更先进的模型在表达数据内部复杂结构方面的高能力的一个明显缺陷。

Non-convex minimisation. Finding the minimum require iterative approach (here, gradient descent) but the non-convexity make it possible to reach local minima instead of the global minimum depending on the starting point.

小心过度拟合

一般来说,在机器学习中,当处理优化过程时,我们需要非常小心过度拟合。当模型不仅学习了我们想要的有趣的一般特征,而且还学习了一些特定的不想要的噪声时,我们说模型过度拟合了数据。换句话说,过度拟合是指优化过程导致模型实例过于接近训练数据,因此不能很好地推广到新的未知数据。下图很好地说明了过度拟合现象。

From left to right : underfitting, fitting and overfitting. Over the same set of data we fit polynomial functions of various degrees. We can see that 1 degree polynomial function has not enough freedom while 20 degrees polynomial function has too much.

模型的参数数量和可用于训练的数据数量之间的比率对过度拟合风险有影响。如果与参数的数量相比没有足够的数据,在某种意义上,就有学习不希望的噪声的空间。但是,如果数据的数量足够大,它将具有正则化效果,并将迫使参数仅学习一般特征(见下图)。当拟合神经网络时,参数的数量可能非常多,因此存在过度拟合的风险。

From left to right : fitting of a 5 degrees polynomial function with 10, 30 and 100 points. We can see that more points have a regularisation effect : with 100 points, the fitted curve looks like a 2 degrees polynomial function.

我们应该注意到,正则化参数/约束参数以关注一般特征的另一种方式是引入显式正则化器。我们不会在本文中给出任何细节,但这是机器学习中一个非常重要的概念:误差函数(我们希望优化)通常包含正则化器,以加强对主要期望特征的关注,并减少噪声的潜在影响。

模型可解释性

模型的可解释性是一个不容忽视的大问题,有时是决定选择一个模型而不是另一个模型的决定性因素。

我们所说的模型的“可解释性”是指一旦模型被优化,理解为什么一些输入给出一些输出的能力。让我们以上一节的线性回归为例( p=f(s)=as+b ,以 s 一套房子的大小和 p 其价格)。一旦我们优化了参数 ab ,基于这些数据,我们可以完全解释我们所获得的结果。事实上,我们可以说,为了猜测新房子的价格,我们有一个基础价格 b 货币单位,我们为房子的每个尺寸单位加上 a 货币单位。同样,线性回归的完全可解释性来自于它的过于简单以及建模方面的一些限制。相反,一些模型非常强大,但可解释性差得多(如果有的话)。然而,在模型的性能和它的可解释性之间没有必然的直接联系。例如,已知支持向量机在许多问题上表现良好,并且它们的可解释性也很好。

可解释性的重要性

请注意,随着机器学习在我们的日常生活中占据越来越重要的位置,可解释性问题变得越来越重要,并且在未来会越来越重要。机器学习模型将帮助人类完成一些(可能是重要的)任务(在健康、金融、驾驶等方面),我们有时希望能够理解模型返回的结果是如何获得的。例如,一个智能键盘在输入信息时会提示下一个最有可能的单词,这个键盘不一定要让人理解:我们只是希望它有效率。然而,预测患者是否存在疾病的模型最好在准确的基础上是可解释的:在这种情况下,我们不仅对结果感兴趣,而且希望理解其背后的“逻辑”,以便让人类确认或不确认诊断。

因此,可解释性是一个非常吸引人的模型特征。然而,有时有必要通过建立一些非常复杂的模型来牺牲一些(如果不是全部)可解释性以获得更大的预测能力:这正是下一节中讨论的神经网络的情况。

深度学习

我们在说什么?

在谷歌上快速搜索会给我们提供以下“深度学习”的定义:“深度学习方法的集合是更广泛的机器学习方法家族的一部分,旨在用高度抽象的数据建模”。在这里,我们应该理解深度学习在于建立非常复杂的模型,用可解释性的容易程度换取预测能力。

神经网络属于深度学习方法。从大的方面来看,它们是高度参数化的复杂函数,我们试图优化(我们寻找最佳参数)以适应我们的数据。如果我们想在极端情况下进行模式化,我们可以说神经网络是线性回归的非常复杂的“进化”,旨在能够对数据中的复杂结构进行建模。

例如,让我们考虑一个回归或分类问题。在这两种情况下,我们都有一些输入,用 (i1,i2,…,in) 表示,我们希望找到这些输入的一个函数,它很好地解释了观察到的相应输出,用 (o1,o2,…,om) 表示。换句话说,就像在我们的线性回归示例中一样,我们正在寻找一个函数 f ,使得 (o1,o2,…,om) 很好地近似为 f(i1,i2,…,in) 。神经网络建模背后的想法是忘记建立主要由人类“塑造”并由机器调整(通过这几个参数,如在我们的线性回归示例中)的轻度参数化函数的想法,而是建立非常灵活的高度参数化函数,该函数对人类来说没有太多先验意义,但将在学习阶段方便地塑造。让我们试着用一个简单的神经网络来说明这一点。

基本前向神经网络

在这一小节中,我们将看看基本的前向神经网络。这将使我们有机会介绍一些关于神经网络的基本术语,并清楚地看到它们如何被视为线性回归的自然延伸。

然后,让我们再次考虑我们的房屋定价示例,但是这一次有 2 个输入可用(让我们将这些输入表示为 i1i2 ),并且没有关于这些输入和我们想要预测的价格之间的关系的特殊知识(表示为 o1 ),除了这种关系是先验的、相当复杂的和非线性的。

所以我们要学习函数 f 使得 f(i1,i2)o1 的一个很好的估计量。然后,我们可以建议以下第一种模式:

其中 w11w12 只是权重/系数(暂时不关心指数)。在继续之前,我们应该注意到,在这里,模型中没有常数项。但是,我们可以通过设置 f1(i1,i2) = w11 * i1 + w12 * i2 + c 来引入此术语。为了简化一些符号,我们不会在下面写这样的常数项,但读者应该记住,它们总是可以添加的(而且大多数情况下都是这样)。
这种模型是多输入的线性回归模型(也称为多线性回归),可表示如下。

“Network” graphical representation of the multilinear regression (model f1)

在这种情况下,模型很容易理解和拟合,但有一个很大的缺点:没有非线性!这显然不尊重我们的非线性假设。为了引入非线性,让我们对前面的模型做一点修改,提出下面的模型。

其中 a(。) 是一个被称为“激活函数”的非线性函数。然后,我们可以注意到w11 * i1+w12 * I2仍然是线性的,但是当我们让这个值通过一个非线性函数时,整体结果不再是线性的,因此,这个模型比之前的模型更接近我们的假设。这个模型可以表示如下。

“Network” graphical representation of the f2 model. If the activation function a is the logistic function, it defines the well known logistic regression model.

请注意,如果我们选择所谓的“逻辑函数”作为激活函数,我们以这种方式定义了一个称为“逻辑回归”的模型,该模型可以适合例如一些二元分类问题(实际上,逻辑函数输出 0 和 1 之间的数字,该数字可以被视为属于两个类别之一的概率)。

然而,即使比多线性模型更好,这种模型仍然过于简单,不能处理输入和输出之间关系的假设的潜在复杂性。我们可以更进一步,通过以下方式丰富模型。首先,我们可以认为数量 a( w11 * i1 + w12 * i2 ) 不再是最终输出,而是我们函数的一个新的中间特征,称为 l1 。第二,我们可以考虑以相同的方式构建几个(在我们的例子中是 3 个)这样的特征,但是可能具有不同的权重和不同的激活函数:L1 = a11(w11 * i1+w12 * I2)L2 = a12(w21 * i1+w22 * I2)L3 = a13(w31 * i1+W32 * I2),其中最后,我们可以考虑我们的最终输出是基于这些中间特征用相同的“模板”构建的:a2(v1 * L1+v2 * L2+v3 * L3)。如果我们把所有的部分加起来,我们就会得到:**

这里我们应该主要记住的是,是非线性激活函数,而 wv 是权重。在下一张图中,我们以与之前相同的方式给出了该模型的网络图形表示。

“Network” graphical representation of the f3 model. Here we have a neural network with 2 entries, 1 hidden layer with 3 hidden nodes/neurones and 1 output.

最后一个模型是一个基本的前馈神经网络,具有 2 个条目( i1i2 ),1 个具有 3 个隐藏神经元的隐藏层(其输出为 l1l2l3 ),以及 1 个最终输出。我们可以决定在 l 和最终输出之间添加另一个中间“隐藏”层,就像我们在输入和输出之间添加这些 l 一样:这样我们就有了一个具有两个隐藏层的神经网络。或者,我们可以选择保持 1 个隐藏层,但有更多的神经元(例如,5 个而不是 3 个)。因此,我们有不同的方法来丰富/复杂化模型,这将使权重的数量增加。隐藏层的数量、每层神经元的数量(如权重值)和激活函数的性质定义了神经网络,因此也定义了该网络所描述的函数的“模板”。

最后,让我们注意几件重要的事情。首先,在对这些网络进行数学描述的过程中,我们可以(而且我们总是这样做!)用矩阵符号写出前面所有的方程:对于大的架构来说,这使得所有这些更容易阅读。然而,在这里,我们的例子足够小,可以不使用矩阵符号,因此,我们可以避免使用它们,因为读者可能不习惯这些符号。第二,所有的神经网络都不符合上面描述的模板:有不同种类的架构(我们将在下一段中对此说几句),但前馈神经网络确实是首先要了解的基本架构。第三,一旦定义,模型仍然需要拟合(权重应该根据数据进行调整,以最小化一些误差函数,就像线性回归的情况一样),这是一个真正难以完成的优化任务。

不同的需求,不同的架构

正如我们在上一段中看到的,神经网络是高度可调的函数模板,通过其参数,需要优化以适应数据。但是根据问题的性质和建模的数据,我们可能需要使用不同种类的模板。这些不同种类的模板被称为不同的“架构”。例如,上面讨论的基本前向神经网络(也称为多层感知器)是第一种基本架构。然而,还有其他几个。在众所周知的架构中,我们可以提到递归神经网络(RNN)——其代表一些序列数据的递归函数,其中在时间 t 的输出取决于在该时间 t 的输入以及在时间 t-1 的先前输出——以及卷积神经网络(CNN)——其代表对输入的数学卷积运算,并且例如在诸如图像识别的一些基于图像的问题中显示出良好的特性。
在所有正在进行的研究工作中,总是会根据要建模的问题设想出更多的架构。显然,我们无法描述所有这些类型的架构(这完全超出了本文的范围),但这里要记住的最重要的事情是,神经网络的架构应该始终被视为一个可能函数的空间,其中优化网络的参数等同于在这个空间中找到最佳函数(基于优化标准)。因此,选择正确的架构当然很重要,因为如果选择不当,我们将定义一个空间,在这个空间中,即使最好的功能也可能与我们的预期相差甚远。

为什么这是个好主意?

在使神经网络如此有效和受欢迎的原因中,我们可以提到以下三个。首先,许多领域中可用的数据量不断增加,这使得使用这种高度参数化的模型变得合理。请注意,模型的参数也称为“自由度”(该术语不专用于机器学习领域,表示模型中“可调值”或“动作杠杆”的概念),并且模型中的许多自由度需要大量数据来调整/校准该模型。本着同样的精神,你不能在一个线性方程组中有比方程更多的未知数,你需要在你的网络中有比参数更多的数据(事实上,更多更好)。第二,计算能力总是更强,再加上智能优化技术,使得在具有如此多参数的超大规模模型上进行训练成为可能。在大型模型中,可能有数百万个参数需要优化,而在合理的时间内实现优化过程只需要最低的计算能力。最后,正如我们刚才所说的,优化过程是一项艰巨的任务,毫无疑问,简单而聪明的优化技术,如非常适合基于计算机的优化框架的众所周知的“反向传播”,是神经网络取得成功的主要原因之一。

神经网络很难优化

那么,什么是反向传播呢?在回答这个问题之前,让我们简单讨论一下在处理神经网络时我们需要面对的优化问题。我们在选择的“架构”所描述的函数空间中寻找最佳函数(最小化一些预定义误差度量的参数)。由于构成这种“架构”的非线性激活函数以及由模型定义的参数化函数的整体复杂性,我们面临的最小化问题是非线性和非凸的。

优化问题的非线性需要使用一些如前所述的迭代方法。因此,想法如下:随机设置网络的初始权重(给定一些精心选择的分布),然后对所有这些参数应用梯度下降方法,以迭代地改善(减少)误差度量。换句话说,这意味着:使用您的数据在网络中向前传递,观察结果,将模型输出结果与实际预期结果进行比较,然后稍微改变网络中的权重,使结果稍微接近真实值(通过梯度下降方法),并重复此过程,只要我们可以对权重进行“小移动”以改善结果。

让我们举个例子来说明一下。考虑前面介绍的简单前向神经网络(具有 2 个输入、1 个具有 3 个隐藏神经元的隐藏层和 1 个输出)。假设该神经网络的权重在给定时间处于某种状态(见下图)。然后,我们可以为数据集中的每个输入计算当前权重的预测输出。

At the beginning of a step, the neural network has its weights set at some values. We can then compute a forward path for all inputs (i1, i2).

现在,为了进行梯度下降的一步,我们应该独立地问我们自己网络中的每个权重:什么样的行为会降低增加和减少这个权重之间的误差。

让我们强调“独立”的概念:这意味着,对于每一个权重,我们必须定义,假设所有其他权重固定,我们是否需要降低或增加这个权重以减少误差。

这样做,我们在某种意义上给每个权重*赋予了一点“+w”(增加)或“-【𝜶_】w(减少),其中𝜶_ w 为正,与该权重增加(或减少)多少有关(见下图)前面的量显然是关于每个权重的导数,直到一个符号(导数将指示如何增加误差)。*

Once the forward computations achieved, the error related to each input can be computed. The total error is the sum of the individual errors for each input data. For each weight, we can assign (between parenthesis on the graphic) the opposite sign of the derivative of the total error with respect to this weight. Roughly speaking, for each weight, these values answer the question : if we suppose all the other weights fixed, should we increase or decrease this weight to lower the total error ?

一旦对每个权重都完成了,我们就可以应用梯度下降步骤,并且更新所有标有“+𝜶_w的权重,使得www+𝜶_w 步长* ,而更新所有标有“ -𝜶_ w 的权重,使得注意 step_size 定义了在每次迭代中改变多少权重,并且可以随着训练时间的推移而演变。一旦达到这一步,我们可以重新开始一个新的迭代,直到权重不能再提高了。****

Finally, we can apply the gradient descent step. We considered in this example a step size of 0.1. The weights are then updated (two examples are detailed in the graphic) and we can then start again, until weights can not be improved anymore.

即使我们不会给出关于它的任何更多细节,我们应该提到,对于大多数迭代优化过程,没有什么可以确保我们以比初始状态更好的网络状态(就误差而言)结束迭代(特别是因为步长可能太大,或者因为我们在假设所有其他权重固定的情况下计算每个权重的更新值,但是我们同时更新所有权重)。

作为“逐层”梯度下降的反向传播

我们刚刚描述了神经网络上的梯度下降过程。然而,为了能够进行这些权重的“微小移动”,我们仍然需要计算误差项相对于网络中每个权重的导数(我们需要知道每个权重是应该增加还是减少一点)。它需要计算由网络表示的函数相对于每个权重的导数。这是一个真正的大任务,除非我们利用网络的分层结构来帮助我们。事实上,正如我们前面提到的,网络通常是分层构建的,这意味着我们面对的是(高度)复合的功能。反向传播算法在于使用这种特定的分层结构来有效地计算导数。为此,我们依赖于这样一个事实,即对于给定层的权重的导数可以表示为两个事物的函数:第一,对于下一层的权重的导数,以及第二,在向前传递期间取神经元的值。网络中导数的这种特殊表达直接来自于合成函数的数学导数()f(g(x))' = f '(g(x)) g '(x)*)。然后,如下进行有效的导数计算。我们从计算正向传递开始(我们提供输入,并运行计算直到输出)。然后,我们以相反的方向返回,首先计算误差相对于最后一层的权重的导数。基于这些计算,我们可以计算相对于前一层的导数,以此类推,回到第一层。换句话说,我们在网络中“反向传播”导数计算。这种算法技术使得优化过程更加容易处理。

局部最小值和过拟合风险

最后,假设通过神经网络的优化过程获得的解的质量在很大程度上受到潜在优化问题的非凸性以及由于模型中大量参数而导致的过拟合风险的影响。

由于优化问题的高度复杂性,迭代方法几乎不可能达到全局最优。所面临的优化问题的非凸性带来了在迭代过程中陷入局部最小值的巨大风险。由于这个原因(也是为了解决计算约束),也可以使用随机梯度下降(SGD)。SGD 在于不使用整个训练数据集来进行权重更新(通过梯度下降),而是连续使用不同批次的该数据,以便使优化过程有一点噪声,并且由于这种噪声,有机会克服局部最优。这里我们不再进一步讨论随机梯度下降的概念。

此外,在拟合/训练神经网络时,我们必须特别小心过度拟合的风险。为了避免过度拟合,我们可以减少网络参数的数量,获得更多的数据或使用显式正则化器(在损失函数中或通过本文中不讨论的退出过程)。

外卖食品

在这篇谦虚的文章中,我们试图给读者一些关于神经网络是什么的直觉。为此,我们从机器学习的概念及其简单模型转向更具体的深度学习概念,即神经网络。一路上,我们遇到了与机器学习相关的各种概念,如迭代优化、过度拟合风险等。正如我们在导言中提到的,这里的目的根本不是深入探讨问题的每一个部分,而是给出“为什么”、“什么”和“如何”的总体情况。

主要要点如下:

  • 机器学习是在没有明确编程的情况下赋予计算机学习能力的研究领域。
  • 机器学习依赖于三联模型/数据/优化。
  • 在建立更复杂的模型时,主要有两点需要注意:如何优化和如何解释?
  • 粗略地说,当使用深度学习和神经网络时,我们通过建立非常复杂的模型来放弃可解释性,以获得更大的预测能力。
  • 神经网络所取得的成功主要来自于不断增长的可用数据量和计算能力,以及非常有效的反向传播思想,这种思想使得优化过程更加容易处理。

总之,让我们说神经网络是非常强大的工具。他们已经证明了他们在许多现代问题上表现出色的能力。然而,它们不是能够解决任何问题的神奇工具。这项工作真正聪明的部分仍然在人类手中,他们知道在哪里以及如何以正确的方式使用这些模型。如果因为许多人在该领域引入的解决越来越复杂问题的所有聪明想法而将神经网络简化为“曲线拟合”是令人不快的,那么将它们描述为“神奇工具”也是不准确的,因为这些模型目前覆盖的问题范围明显有限。作为一个正确的平衡,让我们享受伟大的(巨大的!)这些工具在许多领域带来了进步,同时牢记它们目前的局限性……并且不会被可怕的机器人杀手所吓倒。暂时如此。

感谢阅读!

感谢 Baptiste Rocca 和 Benjamin Blanc 阅读草案并提出有益的修改和改进。

欢迎对本文的任何反馈!

与巴蒂斯特·罗卡一起写的其他文章:

** [## 机器学习中不平衡数据集的处理

面对不平衡的班级问题,应该做什么,不应该做什么?

towardsdatascience.com](/handling-imbalanced-datasets-in-machine-learning-7a0e84220f28) [## 理解生成敌对网络(GANs)

一步一步地建立导致 GANs 的推理。

towardsdatascience.com](/understanding-generative-adversarial-networks-gans-cd6e4651a29)**

神经网络里有鬼?

原文:https://towardsdatascience.com/a-ghost-in-the-neural-network-b2fa4ce6f219?source=collection_archive---------6-----------------------

An image emerges from images: http://artwerker.tripod.com/digital-mosaic.html

吉尔伯特·赖尔(Gilbert Ryle)创造了一个著名的比喻,即“机器中的幽灵”,以反驳人类大脑或其相关智能有任何“怪异”之处的观点。他认为笛卡尔的身心二元论是一个简单的分类错误——忽略了精神和心理活动是如何基于大脑的物理工作的——因此,精神的属性可以通过研究大脑来研究。自从赖尔写作以来,神经网络已经成为机器学习的支柱,并在从图像识别到视频游戏的复杂任务中展现出巨大的能力。但是,对于所有的进步,问题仍然是神经网络是否是人脑工作的足够准确的复制,正如人们经常暗示或声称的那样,具有“机器中的幽灵”的外观。由于缺乏简单性,未能理解人类智能的真正复杂程度,整个人工智能领域在过去遭受了巨大的停滞。最近关于人工智能进步的说法有根据吗?或者我们会期待人工智能发展的又一次停滞吗?在这里,我向人工智能领域的行业领导者(Google) DeepMind 寻求帮助,并询问开创性的 AlphaGo 机器背后的算法是否能够提供一条通向普通或类人智能的道路。

哲学家吉尔伯特·赖尔强烈反对笛卡尔的身心二元论。根据 20 世纪早期的科学唯物主义,赖尔认为,假设大脑“不能被分解,它所遵循的规律不是普通工程师所知道的规律”是荒谬的(1949 年,第 21 页)。他指责笛卡尔的二元论是一个简单的“类别错误”,在概念上框定“心灵”的属性是混乱的,好像它们独立于“身体/大脑”的属性。听起来很合理,对吧?

虽然赖尔在他的论点中非常小心,但博学的亚瑟·库斯勒警告说,从笛卡尔的二元论到任何形式的一元论的匆忙。危险在于,头脑可能被认为仅仅是“大脑工作”的隐喻。这种“除此之外什么都没有”的观点否认了鬼魂是需要解释的东西这一隐喻。科斯勒诙谐地说:“当知识精英、思想家和领袖们认为人类只不过是一只发育过度的老鼠时,那么就该感到震惊了”(1967,第 353 页)。

作为两种观点的适度平衡,许多科学家都倾向于“突现唯物主义”。显然,思维根植于大脑的机制中,但是正如哲学家大卫·查默斯所说,想象一个没有思维的大脑是可能的。事实上,是否将思维归因于动物和其他生物一直是实验心理学和动物行为学的一个主要问题,这个问题仍然有些神秘。尽管如此,赖尔的洞察力是广为接受的,头脑被广泛认为是从一些大脑过程的特殊活动中产生的。明确地说,头脑实质上是大脑不可约化的,但却依赖于某种大脑过程。

突现唯物主义的危险在于,许多科学家认为这一解决方案合乎逻辑且令人满意,但它实际上并没有解释任何事情。正如心理学家理查德·格雷戈里(Richard Gregory)所指出的,任何基于某种涌现的理论都必须被视为不完整的:“好理论的作用是消除涌现的表象”(1981,第 87 页)。格雷戈里认为,只有当解释性叙述被混淆时,涌现才会出现。特别是,突现唯物主义混淆了功能性和机械性的解释:“对于理解功能来说,机器是如何组装的,或者如何方便地将其拆开,都是无关紧要的。机器零件和功能单元之间的混淆会产生神秘的幽灵般的出现(1981 年,第 87 页)。

格雷戈里承认精神和大脑/身体之间的功能差异,但要求一种涌现机制。他甚至提出了一条前进的道路:“我认为我们可以通过这样的说法来消除机器和化学中幽灵般的出现:当部分被组合成更复杂的……结构时,这些结构彼此之间以及与它们的局部环境有不同的界面,因此当组合时,它们显示出与孤立部分不同的属性,以及与以不同方式组合的部分不同的属性(1981,第 87 页)。在澄清中,格雷戈里并没有把他的协同作用原理作为一种解释本身提出来,而是作为一种方法来帮助在特定系统中发展真正的解释。

目前,对于从大脑/身体中产生精神背后的机制还没有被广泛接受的理论,但是,总的来说,格雷戈里对涌现的批判被用作一个描述性的术语(而不是解释性的术语)仍然非常正确。许多跨科学的系统以数学方式描述,依赖于突现:整体传导性,人群运动,经济市场等等。所有这些系统都有一个经常被忽视的共同点:这些“部分”按照自身利益行事,但却带来一种集体行为,就好像这个群体也有自身利益一样。在经济学中,这种现象被描述为由一只“看不见的手”引导。(看这里伟大的解释和背景;而这里换个角度怀疑经济学中看不见的手的存在——集体现象的不出现。有趣的是,你可以怀疑集体现象的存在,这加强了看不见的手的解释的无形性的想法。)再说一遍,给它起个名字并不意味着问题解决了,因为通常情况下,引导个体走向集体财产的机制仍然难以捉摸,但也许在未来格雷戈里的挑战会得到解答。(其实作为一个不要脸的塞,这也是我博士希望贡献的一部分。)

所以,我们认为心灵是基于大脑的一些物理机制,但我们也迫切需要一个清晰而具体的解释,来解释一些物理行为是如何导致心灵从大脑/身体中出现的。

最近,我一直在思考人工神经网络是否能够“幽灵般出现”,拥有我们与思维相关的开放式创造力(第一部分;第二部分回应。一个主要的问题是,大脑不是“设计”来容纳思想的,而是可以在特殊情况下容纳思想,这种特殊情况通常被描述为仅限于人类。当前的动物行为学认为,非人类动物的大脑是“反射共和国”,充满了“指导性”过程,详细说明了动物应该如何对环境做出反应。因此,动物行为在很大程度上是一个由基因决定的本能、可塑性和特定底物学习的故事。然而,人类心理学似乎更具创造性,通常被认为具有“选择性”属性,使大脑成为一种新的遗传信息的宿主——迷因。选择被广泛认为是进化理论中创造力起源的唯一已知机制,而普遍达尔文主义(或进化认识论)认为它的逻辑属性延伸到所有形式的问题解决,包括大脑/思维的问题解决。但是在这种区别之下,指导和选择并不代表一种明确的二分法,因为两种系统都可以用来描述另一种系统:指导可以产生于选择,而选择可以产生于指导。因此,仅从程序的方法来看很难确定计算机是否符合一种解决问题的机制,因此也很难确定一台机器是否能够进行开放式的创造性学习,这是普通或人类智能所需要的。

在缺乏人工智能的明确理论基础的情况下,我被吸引去挖掘并仔细研究机器学习中正在使用的精确方法。在近年来报道的最大成功中,(Google) DeepMind 在深度学习与无监督强化技术的结合方面吸引了最大的关注和兴趣。特别是,在这里,我将快速浏览一下 AlphaGo 的内幕——这台机器现在主宰着古代围棋。正如 DeepMind 在他们的谷歌博客:上发布的那样,AlphaGo 的关键是将巨大的搜索空间缩小到更易于管理的程度。为此,它将最先进的树搜索与两个深度神经网络相结合,每个深度神经网络都包含许多层,这些层具有数百万个类似神经元的连接。一个名为“策略网络”的神经网络预测下一步棋,用于缩小搜索范围,只考虑最有可能获胜的棋。然后,另一个神经网络“价值网络”被用来降低搜索树的深度——估计每个位置的获胜者,以取代一直搜索到游戏结束。

从这个对架构的简单描述中,让我们问一问,AlphaGo 的机制有多聪明?DeepMind 已经证明,类似的计算架构在一系列性质不同的游戏中具有有效的性能,从射击游戏到赛车游戏。我认为很容易批评这种架构“不太像大脑”,因为它是不同类型的网络和树搜索算法的模块化组合,但如果仿生是 AlphaGo 架构的目标,这只是一种批评。虽然 DeepMind 像其他最近的人工智能初创公司一样,依靠人工智能炒作和生物类比建立起来(例如这里的),但我不认为复制人脑( sensu Searle 1980 )真的在他们的议程上。我曾在别处论证过,人类类型的智力依赖于感觉,这似乎不是超人能力的目标或要求。在这方面,我认为将人类类型的智能和 AlphaGo 这样的机器可以获得的一般智能的概念分开是合适的。

但是,即使将一般智力作为一个单独的问题来关注,为特定问题定制一个像 AlphaGo ( 见)这样的机器学习“黑匣子”所需的人类专业知识的数量往往被大大低估。有一整套常数定义了网络架构中的修改规则,估计合适的这些常数可能非常棘手。例如,通常有一个折扣因子来衡量未来奖励对当前奖励的重要性,当前奖励需要根据所讨论的特定游戏进行校准,以反映游戏特定的策略要求。有一些渐进神经网络的例子似乎具有一般属性,但这些算法对它们的效用进行实质性评估还为时过早。特别是,还不清楚同一台机器是否可以应用于非常不同种类的游戏。

无论如何,尽管机器学习技术可以说是使机器能够自己学习,但即使是进步的神经网络也不能说是有能力自己“学习如何学习”。这个概念听起来有点拗口,但是这经常被报道为人类教育系统的主要目标,在这种教育系统中,随着学生知识面的扩大,学习的责任逐渐增加,直到他们成为一个有能力的自学成人。这不是一项容易的任务,通常掌握的程度或多或少,并且个体之间的特异性(相对于普遍性)不同。但这种学习需要高度的自我意识,以意识到什么时候某个特定的学习策略值得修改或放弃,以支持另一种选择。没有知觉,我无法想象一台机器如何能达到这种类似人类的一般智能。

也就是说,几乎肯定有方法可以令人满意地复制“学会如何学习”的过程。我的感觉是,这将需要给一个计算机代理附加更多的网络。为了避免策略和价值网络中的进程之间的干扰,A lphaGo 通过在系统架构中将每个网络创建为单独的模块,将这两个网络视为解决不同的问题(还要注意,动作不是由神经网络选择的,而是由树搜索选择的)。如果机器学习的人类艺术可以简化为一组原则,那么很可能将“学习如何学习模块”附加到系统架构中,该架构可以管理如何更新控制学习规则的常数。即使这种艺术不能以一种有意识的方式被还原,神经网络仍然能够以“黑盒”的形式复制这一过程。

但是,同样,随着计算架构变得更加复杂,与生物智能的直接类比将变得越来越弱。作为一名生物学家,我认为智能来自大脑功能完全不同且经常被重新设定用途的机制的结果,而不管代理人是否有知觉 ( 参见)。从这个意义上来说,人工智能的行为导向方法似乎与盲目且不完美的自然选择过程没有根本区别,后者只根据设计的能力来评估设计。从这个意义上来说,我完全相信,对于没有知觉的机器来说,普遍智能是一种真正的可能性。我所说的“一般”是指非特定的任务能力(不是通常定义的类似人类的智能)——就像在渐进神经网络中开始展示的那种智能。当然,一个系统架构对于不同任务的通用性是由程度(而不是种类)决定的,有些架构比其他架构有更广泛的权限。但是,我看不出有什么理由,通过扩展模块化架构来增加跨游戏类型的灵活性,非常通用的能力/智力形式不能成为现实的可能性。

为了捍卫这一立场,我经常遇到关于自然智能和人工智能之间不可逾越的差异的说法,这种差异往往基于以人类为中心的假设(参见我以前关于这一主题的帖子,例如 1 和 2 )。最常见的是,人们从训练数据的规模中听说自然智能和人工智能之间的区别。因为我们人类,事实上还有其他一些动物,能够从低质量和低数量的数据中学习。我认为,这是一个被误解的因素,因为代理人快速学习的能力是在大量非特定背景数据的背景下设定的。虽然机器是在完全无知的情况下接受任务训练的,但生物制剂不会在大脑一片空白的情况下解决问题。年幼的动物通常是天真的,表现出低水平的直觉行为,事实上,人类可能要用一生的时间来获得、发展和磨练他们在特定知识领域的直觉。也许随着进步神经网络的发展,这种普遍智能的壮举可以被复制(因为,毕竟,非人类动物通常被认为是没有知觉的,或者至少具有非常有限的自我意识)。

那么,这给我们留下了什么?正如我在其他地方论证过的,我怀疑随着人工智能体环境的复杂性和与环境的相互作用的增加,基于(必然是渐进式的)基于神经网络的技术的智能体出现一般智能机器的可能性会更大。我认为像感觉这样的生物智能特征似乎不太可能。就我而言,目前对感知(或意识)的生物学基础了解得太少,以至于无法明确感知的精确设计要求(尽管像每个人一样,我也有自己喜欢的理论)。有许多基于感觉的想法,但没有一个达成任何重大共识。因此,类似人类的智能很快出现的可能性似乎很小,因为这将是一个盲目猜测的结果(超出了目前的非决定性证据)。另一方面,似乎很有可能出现(无意识的)“普通”智能。我的意思是,同一台机器同时获得多种任务能力的可能性几乎是确定的。普遍性的程度还有待观察,但人工和自然代理人的能力之间没有质的区别。因此,我可以很好地想象一些非常通用的解决问题的人工智能确实是非常可能的——尽管我不想猜测时间框架(!)因为现在还为时尚早。

考虑到这一点,对当前技术被扩展以产生通用人工智能是否有乐观的空间?还是我们将面临另一个人工智能的冬天?我认为有合理的乐观空间。围绕像(谷歌)DeepMind 和其他公司的成就的炒作在某种程度上是当之无愧的,因为他们收集了一些令人惊叹的奖杯成就。此外,未来的研究似乎有一些明确的方向,特别是在进步的神经网络中,这增加了当前的兴奋可能会持续到不久的将来,并有更多成功的强烈承诺的想法。但是,我认为,对类人智能的类比可能(也应该!)以避免混乱,并专注于可解决的问题,从而取得可控制的进展。因此,尽管有乐观的空间,但那些将取得巨大进步的领域/方向并不是那些经常向公众报道的领域/方向。这使得公众对人工智能的理解对研究人员来说是一个真正的挑战,并产生了对清晰展示工作的真正需求,而不是用错误的类比来“降低水平”。我对这一点深信不疑,因为人们对人工智能的发展充满了恐惧;如果这些想法能够被公平地交流,那么关于“机器人伦理”的蓬勃发展的猜测将被证明与阿西莫夫的故事一样远离现实。正如(deep mind 的)戴密斯·哈萨比斯所说:“我们离我们担心的事情还远着呢……这更多的是让每个人都跟上速度”。我们应该庆祝一般人工智能的进步,而不是警告或谴责研究人员。而且,如果对监管的呼声被忽视,像渐进式神经网络这样的技术被给予喘息的空间,谁知道也许一些幸运的研究人员甚至会发现潜伏在他们机器中的精神品质的‘幽灵般出现’!

感谢阅读!

今天和明天之间人工智能潜力一瞥(上)

原文:https://towardsdatascience.com/a-glimpse-into-ai-potential-between-today-and-tomorrow-part-1-e73e28f394ce?source=collection_archive---------9-----------------------

4 月 23 日,我很荣幸被 GDG 莫纳斯提尔 (突尼斯)邀请作为演讲人参加 Google Next 2017 扩展活动。我的演讲是关于人工智能的,以下是我想要传达的想法的书面版本。

我敢打赌,当你想到/听到人工智能的时候,你的脑海中会浮现出许多想法!大数据,IBM Watson,Alexa,谷歌自动驾驶汽车,NAO,图灵,谷歌云,但什么是人工智能?是能胜过人类大脑的大脑吗?人工智能如何影响我们的日常生活?AI 背后有哪些技术?

AI 是什么?

回到 1950 年,当计算机科学先驱艾伦·图灵开始思考“如果机器学习会怎样?”。为了制造智能机器,他发明了图灵测试。这项测试改编自一个叫做模仿游戏的维多利亚风格的比赛。当时,艾伦指出了一个许多人不相信或从未想象过的人工智能的可能前景。

仅仅 5 年后,在达特茅斯会议上,约翰·麦卡锡创造了“人工智能”一词,定义为“制造智能机器的科学和工程”。

智能机器,人工智能..在深入挖掘之前,让我们先定义一下智力。

What Intelligence consists of [1]

正如我们所见,智力包括:

  1. 处理数据的能力
  2. 解决特殊用途和通用领域的复杂问题
  3. 根据情况进行推理和推断的能力。

这些机器都有这些能力吗?你们中的一些人会说“我想是的!”其他人会反对..而我在这里建议的是,通过查人工智能现在在哪里,一起发现答案!因为没有比真实的事实更有说服力的论据了!

AI 有什么影响?

人工智能在不同的行业都有影响:汽车、电子商务、市场营销、机器人、移动设备等等。毫无疑问,健康是人类最重要的支柱之一。如果一个人的健康状况不佳,他就不可能在技术上取得任何进步。因此,对包括 IBM 和谷歌在内的许多公司来说,在医疗领域投资人工智能是一件大事。

人工智能正在帮助医生更好地探索人体,并处理其复杂性。2017 年 4 月,英国诺丁汉大学的一个团队进行的一项研究证明,医生在使用人工智能时,可以更好地预测病人的心脏病发作风险。这每年可以拯救成千上万的人。

事实是,每年有 1500 万到 2000 万人成为心血管疾病的受害者,包括心脏病发作、中风和动脉阻塞。医生使用一种称为 ACC/AHA 的方法,根据年龄、胆固醇水平和血压等指南来预测心脏病发作的风险。实际上,该方法显示出不是非常有效。人体的复杂性还隐藏着一些不为人知的生物学准则。

幸运的是,正如诺丁汉大学的流行病学家斯蒂芬·翁告诉《科学》杂志的那样。"计算机科学让我们能够探索这些联系."在这个问题上尝试一些机器学习算法,如逻辑回归和神经网络,得到了更好的预测!该算法比 ACC/AHA 方法多 7.6%,导致假阳性减少 1.6%。这意味着,在大约 83,000 份病历的样本量中, 355 条额外的生命本可以被挽救。[2]

人工智能在医学领域的成就不止于此:

  1. IBM Watson for oncology 致力于癌症诊断,
  2. 谷歌 DeepMind 失明检测:英国有 200 万人患有失明,其中约 36 万人注册为盲人或部分失明。[3]这个研究项目是调查技术如何帮助更好地分析扫描结果,让医生更好地了解眼病。研究团队开发了一种人工智能算法,可以自动识别糖尿病视网膜病变,这是成年人失明的主要原因。“我们能够把谷歌的一些核心东西——对猫、狗和面孔进行分类——应用到另一类问题上,”在谷歌负责该项目的医生和生物医学工程师 Lily Peng 说。
  3. 像软银公司开发的用于老年人辅助的罗密欧一样,作为手术和病人助手的机器人。

虽然为了真正帮助开发医疗服务和患者援助,确实还有许多工作要做,但人工智能的影响已经存在,医生们相信与人工智能的合作将是有益的,“我不能强调它的重要性,”加利福尼亚州帕洛阿尔托斯坦福大学的血管外科医生埃尔西·罗斯告诉《科学》,“我真的非常希望医生们开始接受使用人工智能来帮助我们护理患者。”

让我们继续关注与人工智能一起成长的第一个领域:游戏
这个故事始于计算机通过简单地计算棋盘上所有可能的走法或死记硬背,在国际象棋或危险边缘等游戏中击败人类。

今天,计算机甚至可能具有超前思考和推理的能力!在谷歌的阿尔法围棋赢得 T4 之前,研究人员没有考虑到这些可能性!

2016 年 3 月,世界顶级围棋选手之一李世石(Lee Se-dol)在与 AlphaGo 程序的比赛中只赢了一场。该游戏被认为比国际象棋复杂得多,因为它有更多的移动可能性(> 10170 个合法位置)。因此,它通常需要一种特殊的人类技能:直觉和创造力。DeepMind 的研究人员表示,这种计算能力在游戏之外还有现实世界的前景,特别是在医疗保健和科学领域。

DeepMind 的研究人员表示,这种计算能力在游戏之外还有现实世界的前景,特别是在医疗保健和科学领域。

健康,游戏,还有什么?

Google self-driving car

嗯,人们现在都在谈论不仅能运送我们,还能替我们思考的交通工具!

“谷歌在 2012 年开始测试一辆自动驾驶汽车,从那时起,美国交通部 发布了不同自动化水平的定义 ,谷歌的汽车被列为全自动化的第一级。其他交通方式有 更接近全自动化 ,比如公交车和火车。

人工智能在交通领域的应用领域非常广泛。由于模式识别、系统识别、分类和许多其他人工智能子集,交通运输多年来发生了巨大的演变!

交通状态跟踪、高级驾驶员辅助系统(ADAS) 、驾驶员警报系统(例如睡意检测)已经存在,为驾驶员提供更好的驾驶体验。谷歌、特斯拉、沃尔沃以及许多其他公司都专注于提供道路安全,其方式是“人工智能可以改变我们的情感以及我们与汽车的实际关系”。

好吧,你可能会告诉我:这听起来不错,但我身边没有这些人工智能的应用!“我在美国不是为了看自动驾驶汽车”,“我不是为了在工作中尝试人工智能辅助的医生”,“我不玩游戏!”我不确定 AI 对我生活的影响!

你已经在用 AI 了!又不是科幻!是真的。也许,你只是没有意识到!不管你愿不愿意,人工智能正在影响你日常生活的方方面面。

在网上冲浪时,你正在试验用户行为跟踪。像谷歌、亚马逊、脸书等许多公司都在利用你的偏好、历史、搜索和购买,以便预测你的兴趣,并根据情况锁定你(脸书新闻提要,网站页面右侧/左侧的广告,购买书籍的建议..).所以,通过谷歌搜索,脸书,网飞的电影推荐,亚马逊商店,你会遇到人工智能的方方面面。

人工智能也在你的手机里!Siri、Google Now、Cortana 都是使用人工智能技术的智能助手,旨在帮助你获得问题的答案,或通过语音控制执行操作。例如,你可以说:“今天天气怎么样?”助手会搜索这些信息并把它与你联系起来。

不仅如此,AI 还用于在线客户支持。不是你访问的每个网站都有真人和你交流。在许多情况下,你在和一个初级的人工智能(聊天机器人)交谈。

你看到了吗?AI 无处不在!你的智能手机,你的汽车,你的银行和你的房子也可能!

在这一点上,这个故事开始像一部恐怖电影:谈论所有这些人工智能的影响提出了一些问题..好像有争议吧?直觉,创造力,协助,保存你的数据,可能会拿你的隐私冒险,使用数据训练机器,帮助医生,分心的司机识别,人形机器人,下一步是什么?人工智能是否拥有真正的“智能”(我们在开始时定义的智能)?人工智能会取代我们的工作吗?

未完待续……

原创文章发表在我的网站。

资源:

[1] 人工智能定义,德勤。

[2] 机器学习能否利用常规临床数据提高心血管风险预测?

[3] 谷歌健康领域的 DeepMind 研究。

芝加哥西尼罗河病毒

原文:https://towardsdatascience.com/a-go-at-kaggle-723447f8d95f?source=collection_archive---------3-----------------------

我刚刚学到了一些令人沮丧的教训——作为对卡格尔西尼罗河病毒竞赛的敬意。https://www.kaggle.com/c/predict-west-nile-virus。这不是我们有过的最大或最棘手的项目,但它让我很困惑。我的方法过于草率,陷入了竞争的心态,这让我陷入了许多兔子洞,所有这些都是可以避免的。这些都是糟糕的流程和代码混乱的症状。我很高兴我得到了教训,因为我不会让它再次发生!至少这是希望..有了这些经验教训。

  • 不要混淆你的笔记本进度没有什么比从头开始运行单元并失败更糟糕的了,因为一部分 EDA 是在未来的数据帧上执行的
  • 制作函数并使其动态化这不仅允许添加功能,也允许省略功能;允许您操作数据以快速迭代,通常是朝着更好的先前数据集进行多次迭代。
  • 保存表现良好的提交数据/模型。 这个数据集仍然是小规模的,可以在几秒钟内重新运行,但没有理由忘记哪些功能让你获得了 0.73 的 Kaggle 分数!
  • 确认训练/测试集具有相同的列。 您对测试数据的预测最终取决于它提供的列/值——当然您也可以对其进行特征工程——但是确保您可以将测试集传递到您的训练数据转换函数中是关键。

有了这个数据集,对数据有个概念是相当容易的。我们正在查看芝加哥的一些捕蚊器,以及一些关于它们的位置、捕捉的蚊子类型、日期和一些其他琐碎特征的数据。训练集约为 12k 行;测试约 112k。Kaggle 对提交的内容进行评分的标准是 AUC。更多内容请见下文。

因为我们在看一个分类问题,EDA 之后的第一步实际上是获得基线分数:就准确性而言,最简单的预测会给你多少分。在这种情况下,目标变量是 WnvPresent,由于西尼罗病毒的罕见性质,如果我们猜测一只蚊子没有西尼罗病毒,我们 94.8%的时间都是正确的!这是一个简单但** 关键** 的概念。

我的下一步是向 Kaggle 发送一个示例提交,这样我就可以确认格式。你知道,登上排行榜。有了这个剪刀,我就在那里。

从这里开始,最初的 jupyter 笔记本是这样的。调查分类数据预测西尼罗河的可能性。看看这些数字,找出它们之间的关系。假设。重复一遍。它很乱,我忽略了让它容易重复。第二天我非常后悔。

很明显,很多陷阱都是惯犯。此外,NumMosquitos 特性似乎会使预测变得容易。记住,任何高于 0.0525 的预测西尼罗河的机会都是值得研究的。这是我们的基线谈话。所以这些落在 0.09 以上的陷阱看起来是很好的预测。

捕获的蚊子越多,蚊子数量就越多。

因此,我创建了一个快速而肮脏的虚拟变量函数,将陷阱和块数据放入一些数字中,删除了其他大部分列,然后将我的测试集放入模型中,然后嘎然而止。在我对它进行变换后,会有更多的列。为什么?该死。没想到会这样。你看,我们的课程往往有非常干净的数据。嗯,并不是说这很混乱,但它与我的假设 test.columns = train.columns 不同。测试集中也有新的数据。看不见的陷阱。和一个新物种。这就是大多数额外栏目的来源。

所以,我不完全确定在这种情况下什么是正确的决定。大多数其他学生都在用相反的方法运行,即找出几个最有可能感染西尼罗河病毒的关键特征,然后用它们运行他们的模型。我喜欢快速迭代替代方案,这意味着我需要弄清楚如何手动修复大约 200 个特性列而不是。我能想到的最好的办法是从一开始就连接测试和训练,并重复虚拟预处理。我想,这将确保它们具有相同数量的列,并且我可以将它们从 Id 列中分离出来,Id 列是测试集的数字,NaN 是火车的数字。

这意味着测试集中的新列与可预测性无关。尽管他们不会,除非我们能以某种方式概括他们。比如把陷阱按 10 个一组分组之类的。我也不确定是否使用了年份数据——因为我添加了虚拟值,但是从测试到训练的年份不同。我决定下次再考虑这个问题。

经过一两个小时的忙碌,我提交了下一套,很高兴地发现在 Kaggle 上获得了 70 AUC。AUC 指标在这里也很重要,但要理解它,我们首先需要理解什么是混淆矩阵。

在像西尼罗河病毒这样的二元分类中,有 4 种可能的结果:

  • TP —真阳性:WNV 出现,WNV 被预测。
  • FP —误报:(第一类错误) WNV 不存在而 WNV 却被预测到了。
  • TN——真正的否定:WNV 不在,WNV 没有被预测到。
  • FN —假阴性:(第二类错误) WNV 是存在的,但 WNV 却没有被预测到。

这些是我们判断分类器的依据。混淆矩阵有许多最常用的评估指标:

  • 准确度= (TP + TN) / (TP + FP + TN + FN)
  • 精度= TP / (TP + FP)
  • 召回率(TPR)= TP/(TP+FN)-正确预测的阳性数据点占全部阳性数据点的比例。
  • 脱落(FPR)= FP/(FP+TN)-被错误预测的负数据点占负数据点总数的比例。

AUROC 或通常称为 AUC,是真阳性率和假阳性率之比的曲线下面积。理想的分类器是 AUC 为 1 的分类器;其中 TPR = 1,而 FPR = 0。AUC 讲述了在我们可以选择的阈值范围内,我们的分类器的 TPR 如何与其 FPR 相关的整体情况。在下面的例子中,TPR 在大约 0.6 FPR 时达到最大值。意思是要正确分类所有的正面事例,我们会错误地把 6/10 的负面事例分类为正面。

The AUROC commonly referred to as the AUC is the ratio of the TPR over the FPR

很好地解释了这一切是如何运作的:https://www.youtube.com/watch?v=OAl6eAyP-yo&t = 6s

我能够添加的一些最好的功能是基于位置和天气的。两者都是在数据中发现更高概率的 WNV 聚类的例子。在地理位置方面,我在奥黑尔机场附近找到了 WVN 的一个热点。通过将距离< 3 英里归类为 1,我能够创建一个二进制列,使样本中存在 WNV 的几率为 0 . 1。

另一种是使用湿球值作为高于某一阈值的二元指标。

最后,我太沉迷于添加和删除功能以及重新训练我的模型,以至于失去了我最初的最好成绩。在我对自己感到相当沮丧之后,我重新构建了许多代码,并且有条不紊地修改了我的解决方案。结果是能够获得更高的分数,并且能够在不失去我的位置的情况下快速迭代。

这个故事的寓意是,获得最快最好的结果不应该以不可复制的数据为代价。你的流程越有条理,你在函数中构建的自由度越大,你就越有能力改变你的数据和模型。

毕业生的观点:解决实际问题

原文:https://towardsdatascience.com/a-grads-view-solving-real-problems-939f15360348?source=collection_archive---------11-----------------------

这是我为 MassMutal 博客写的一篇文章的报告:https://blog . mass mutual . com/post/a-grads-view-solving-real-problems

就在今年 5 月,我从佛蒙特大学和计算故事实验室研究小组毕业,作为一名高级数据科学家在 MassMutual 工作。虽然终身学生(读博生)和在工业界工作有很多不同之处,但重叠部分是巨大的,我已经能够在 MassMutual 安顿下来。

差异

最大的区别是什么定义了价值。机器学习研究的价值在于新的算法和分类精度的边际改进。但是,在商业中,我们的数据科学成果和机器学习算法通过改善客户体验来提供价值。

虽然花费几个月的努力来开发一种改进的算法,并将准确率从 90%提高到 92%会在学术期刊上受到欢迎,但将过程从 50%提高到 90%才是所有收益所在。(相关 : 数据科学与万通)

重叠

事情如此相似的一个最大原因是,MassMutual 的数据科学团队采纳并应用了许多在大学行之有效的实践。我发现,在每周的实验室会议上,在拥有导师结构的同行学习文化中,在类似于期刊论文的项目报告的间隔评审过程中(没有任何粗鲁的评审员),我很容易感到自在。

再加上计算故事实验室使用机器学习和计算作为工具来研究有趣的问题,这是匹配的。

哪些大学可以学

另一方面,我在 MassMutual 工作的几个月所学到的东西可能对改进研究大有帮助。

我们有一个数据工程团队来支持计算和数据平台(从第一天开始就令人兴奋),以有助于保持项目进展的方式跟踪我们的工作,在整个团队中遵循一致的编码风格,并确保我们的模型是可复制的。后一部分,用一致的项目结构构建可复制的模型,是我和另一个团队成员 Paul Shearer 最近致力于并实现的工作。

最后,虽然我们的重点是解决业务问题,但这并不是说没有任何科学在进行。我们预测寿命的模型利用了新的方法,我还没有完全理解。我们针对棘手的问题调整实践状态的方法,并使用实验来跟踪我们的模型的结果并改进它们。

我们正在将应用机器学习带到整个公司的各个领域,这是一个令人兴奋的地方!

更多来自 MassMutual…

MassMutual 的研究生项目:如何运作

MassMutual 的数据科学发展计划

生活互助:教训和故事

媒体标签图

原文:https://towardsdatascience.com/a-graph-of-mediums-tags-8e3cf6cad1d9?source=collection_archive---------5-----------------------

热门帖子涵盖的 5 大主题

正如在之前的一篇文章中所描述的,我收集了 1000 个媒体最受欢迎的故事的数据。这是他们最常见的标签的可视化。我冒昧地将同义标签映射到它们的规范名称。比如“Tech”→“Tech”,还有“Trump”→“Donald Trump”。

节点的大小与标签的使用次数成正比。技术是媒体的宠儿。

连接两个标签的灰线表示它们都在同一个帖子中使用。一对标签之间的线条越粗,它们并排出现的频率就越高。

彩色聚类是一组标签,这些标签内部有密集的连接,而它们之间的连接则比较稀疏。这五个集群总结了流行媒体帖子的主要主题。

  • 设计:设计,UX,网页开发,软件开发,苹果,营销,谷歌,数据科学,灵感,产品设计,网页设计
  • 个人发展:生产力、人生经验、自我提升、创业、商业、教育、书籍、心理学、个人发展、创造力、健康、爱情、生活、创业、人际关系、养育、心理健康、领导力、工作、写作、艺术、文化
  • 编程: JavaScript,编程,科学,人工智能,社交媒体,技术,机器学习,React
  • 政治:女权主义,政治,榜单,女性,新闻,幽默,唐纳德·特朗普,旅游,种族主义,黑人问题,历史,新闻,媒体
  • 加密货币:区块链、比特币、以太坊、加密货币、风险投资、经济学

用 R 绘制图形出奇的容易。我创建了一个文档术语矩阵,其中行是文章,列是标签,值为 0 或 1,表示文章是否有标签。它的叉积给出了一个邻接矩阵,这是一个所有帖子中标签共现计数的对称矩阵。r 的 igraph 软件包绘制了这样的邻接矩阵。通过调用 tkplot,可以在 GUI 中交互式地调整节点的布局。

g = graph.adjacency(adjMatrix, mode="upper", weighted=T, diag=F)plot(cluster_leading_eigen(g), g, edge.width=E(g)$weight*.1, 
layout=l, vertex.size=25*counts[-removed]/max(counts[-removed]), vertex.label.family="Arial", edge.color=NULL, vertex.label.color="black", edge.curved=.5)

生活的图示

原文:https://towardsdatascience.com/a-graphical-representation-of-life-f2dd6a7f9c8b?source=collection_archive---------10-----------------------

Graphs Plotted with Processing

对我来说,生活由一系列的起起落落、好时光和坏时光,或者快乐和悲伤组成,保持着周期性。除了周期性的波峰和波谷,还有一丝混乱和不确定性。

解释图表

一个周期波或信号本质上是那些每当一个恒定的时间过去时循环回到一个相似的模式的波或信号,该“时间”正式地被称为信号的“周期”。余弦波是一种常见的周期信号,让我们从它开始。

A Cosine Wave

看着余弦波,一个非常普遍的生活模型出现了——线上的驼峰代表生活中的好时光,而下面的驼峰代表不好的时光。

现在,这种模式还有改进的空间。基本上,一个“快乐”的时间框架仍然会有微小的起伏。“悲伤”的时间框架也是如此。这就是生活不可预测性的来源。这可以通过在余弦图上添加一点噪声来实现。

A Cosine with noise added

最后,我们中的一些人往往会在生活的“好”和“坏”部分之间经历快速的转变或变化。

Rapid transitions

而另一些则倾向于具有较慢的过渡。

Slower Transitions

无论一个人对生活的描述是什么,这里要记住的关键一点是,坏时光结束了,好时光几乎马上就来了。暴风雨总是会放晴,为晴朗的天空腾出空间。

本文中的所有图表都是使用 处理 编程语言绘制的。向丹尼尔·希夫曼喊出他关于柏林噪声和图形绘制的精彩教程

一个很大的陷阱:忽视验证

原文:https://towardsdatascience.com/a-great-pitfall-neglecting-validation-9b8621dc5a87?source=collection_archive---------16-----------------------

Photo by Paul on Unsplash

它出现在你的书的第一章,出现在你参加的第一次讲座,或者出现在你看的第一个教程中。这似乎很简单:你不能根据你对用于训练的数据所做的预测来衡量你的预测者的表现。然而,随着管理层不断施加更大的压力,或者您的堆栈需要更长的时间来运行,您开始牺牲验证。整个故事是关于一个非常基本的事情:确认。

什么是验证?

如果你已经知道答案,你可以跳过这一节。如果你不确定,我来大致解释一下。让我们说,你想有一个预测器,在一个特定的任务执行预测。得到预测器后,你会想知道它的表现如何?它是表现很差以至于没用,还是表现很优秀以至于你可以宣布问题解决了?为了测量性能,您需要验证。

为了执行验证,您需要数据。更具体地说,您需要包含您想要预测的信息的数据。我们称这些信息为地面真相。根据维基百科,地面真理被定义为:“直接观察提供的信息” *** 。地面实况通常由人类提供。在我们的过程中,我们相信基础事实是我们想要为我们的数据预测的实际值。

一旦你有了你的预测者和真实的数据,验证的冒险就开始了。如果在你的开发过程中没有真实的数据,这很容易。你只需将预测与实际情况进行比较。但是,这种情况很少见。你很少锁定你的全部数据,不到最后也不会深入研究。在开发预测器时,经常会用到这些数据。您使用一些数据进行训练,检查数据以调整阈值,或者深入数据以了解如何实现良好的预测。在这种情况下,你需要思考如何建立一个稳固有效的验证机制。

我们为什么要进行验证?

这似乎很简单:我们正在进行验证,因为我们想衡量我们的预测性能。但是,我们不要被这种现成的定义所迷惑。我们不只是想衡量业绩。我们想知道我们的预测器在现实生活中是否会做得很好。

让我们建立一个预测任务示例。在这个例子中,我们想知道一个图像中是否有一只猫。在这个任务中,你向预测器提供一幅图像,它会告诉你图像中是否有一只猫。所以根据定义,这是一个二元分类问题。

对于此任务,您可以找到一个数据集或准备自己的数据集。在那之后,你就可以开始开发你的预测器了。但是人们不应该忘记你为什么要开发一个预测器。您不想在数据集中检测猫。你想要一个预测器,当你拿起相机在当地公园给猫拍照时,它能检测到猫。为了验证,你硬盘上的数据集是为了帮助你,这样你就不用一直在你当地的公园里追猫了。但是有了这种安慰,我们经常会忘记真正的目标,而去追求奖励价格:更高的 KPI(关键绩效指标)值!

我们正在进行验证,以便让我们很好地了解我们的预测器在现实生活中的作用。你的 KPI 只是帮你,并不是你的实际目标。在开发预测工具时,我们需要记住这一点。

当你忘记验证的时候

如果您忘记或未能建立有效的验证机制,会发生什么情况?让我给你描述一下这个场景的可能结果。

你在做你的项目。你专注于让你的 KPI 越来越好。你在它上面努力工作。你得到更多的数据,你用不同的方法进行研究,你进行大量的实验。最后,你会得到一个看起来很棒的表演。任务完成!您现在已经准备好展示您的工作并部署它了。

在这一点上,每个人都很高兴。你把它展示给你的团队、管理层或你的同事。如果你幸运的话,有人会发现你犯的错误。如果你幸运的话,有人会告诉你,你没有建立一个有效的验证机制。这还不是最坏的情况。你还是没有部署你的预测器。尽管如此,没有人受到这个错误的影响。你只需要回到草图板,引入一个有效的验证机制。但是如果你运气不好,你会陷入一个糟糕的境地。

在最糟糕的情况下,你部署了你的预测器,它就启动了。过了一段时间,人们开始意识到你开发的预测器表现不好。用户会开始抱怨。每个人都变得困惑。KPI 表明预测器表现非常好。但是为什么用户对性能不满意呢?过了一段时间,你确信有问题。你回到画板,试着调试你的模型。最后,你意识到你的 KPI 显示的是不对的。你的验证机制被破坏了。你太专注于提高 KPI,牺牲了验证。现在你的声誉受损,你需要在混乱开始前迅速想出一个新的模式。

为什么我们会放弃或忘记验证

我们牺牲验证或者忘记完全建立验证有很多原因。我相信这个清单很长。我下面的列表并不完整,但这些是我经常遇到的。

管理层施压

这个问题不是数据科学或验证所特有的。管理层或业务方总是希望快速有结果。他们给团队施加压力,让他们尽快想出一个预测器。随着压力的增加,你开始放弃你的方法的某些方面。你选择放弃的一个方面可能是验证。你知道验证并不好玩。正因为如此,你需要有一个不同的工作流程。除此之外,还需要更长的时间。因为这些,它可能看起来像一个修剪的好地方。

你认为你不需要验证

我相信这是因为忘记了我们为什么要进行验证。不管原因是什么,你可能认为你不需要验证。让我列举几个我遇到的原因:

因为你不使用机器学习。

验证的需要并不是机器学习所特有的。模型的复杂性并不决定验证的必要性。即使你的方法是一个单一的 if 语句,或者一个复杂的机器学习模型,也没关系。你需要被认可。

因为你认为你的方法并不过分。

即使你使用复杂的正则化方法,也不意味着它能完美地工作。过度配合预防措施并不完美。意味着你不能依赖他们,也不能在训练集上衡量他们的表现。

因为你的方法与验证无关。

也许你认为你不需要验证,因为你没有在训练中使用任何数据。然而,你确定你自己没有在你的方法中引入任何偏见吗?这是兔子洞更深的部分。即使你在训练过程中没有使用任何数据,你作为一个人可能已经发展出一种偏向于你所使用的数据的方法。让我使用猫检测示例来阐明这一点:如果您的数据集仅包含深色猫,并且您在开发算法时使用了此信息,则它在您的数据集上的表现将优于在真实生活环境中的表现,在真实生活环境中有不同颜色的猫。

您的跑步/实验花费了很长时间

通常机器学习操作需要很长时间,这不是秘密。即使一次运行没有,你也会因为各种原因想要很多次,比如尝试不同的超参数、方法等。当你的耐心开始消退,云服务器账单开始堆积,最后期限临近;你试着砍掉一些操作。在这一点上,你倾向于切断验证。您可能会开始使用较少的折叠,切换到二次采样,或者更糟:取消验证。

没有借口。您需要验证

不管是什么原因,不管上面是否列出,你都不能没有一个有效的验证机制。验证是预测工作的基础。你可以从不同的方法中选择一种(如交叉验证、二次抽样等。)但是你必须有一个。这是最好的从非常早期的阶段。它可能会随着项目的进行而发展,但是即使在您的第一次运行中,您也必须使用验证。没有有效的验证机制会在项目的后期导致更大的问题。

兔子洞更深:有效验证

当我们再次思考为什么我们需要验证时,情况比仅仅使用现成的验证方法如 K-fold 交叉验证更深入。如果我们想确保在现实生活中获得类似的表现,我们需要更深入地考虑验证。

这个话题超出了这个故事的范围,但是这里有一些值得思考的东西:

  • 您的数据是否以一种不明确的方式泄露了实例的标签?
  • 数据集是否包含一系列变化?
  • 数据是在合成(实验室)环境中收集的,还是真实收集的?
  • 你是否通过你自己在你的方法中引入了偏见?

构建卷积神经网络指南

原文:https://towardsdatascience.com/a-guide-for-building-convolutional-neural-networks-e4eefd17f4fd?source=collection_archive---------5-----------------------

为计算机视觉构建深度网络

想获得灵感?快来加入我的 超级行情快讯 。😎

计算机视觉处于人工智能(AI)进步的最前沿。每天都有新的研究出来,这让我们可以做以前用计算机和人工智能做不到的真正令人惊叹的事情。下图显示了 Mask-RCNN 的结果,这是有史以来为计算机视觉设计的最灵活、最强大的深度网络之一。它能够产生你在下面看到的惊人的分段。

From Mask-RCNN, a state-of-the-art Instance Segmentation network

卷积神经网络(CNN)是我们今天看到的计算机视觉研究中每一个进步背后的驱动力。大多数人从一般意义上知道他们是如何工作的。只需将一堆卷积的东西堆叠成许多层,也许加入一些池,在最后加上一个 softmax,瞧,这就是计算机视觉!

对于一些人来说,有了这种高层次的理解就足以了解正在发生的事情。但是如果你真的想为现实世界的计算机视觉设计一个 CNN,你将需要更多。

你使用哪种预先训练好的网络?你如何修改它来满足你的需求?你的网络应该有 20 层还是 100 层?哪些是最快的?最准确?这些都是在尝试为您的计算机视觉任务选择最佳 CNN 时出现的问题。

让我们来看看你可以用来构建 CNN 的所有构件,不同的权衡,以及如何实际应用它们!

盘旋

卷积运算是 CNN 的核心,如何使用它将是网络性能的一个重要决定因素。在你的 CNN 中使用任何大于 3x3 大小的东西都没有多大意义,例如,避免在你的网络中使用 5x5、7x7 等。已经可重复地表明,最显著的是利用 VGGNet 和 ResNet ,顺序堆叠 3×3 卷积将有效地实现与更大尺寸卷积相同的感受域,同时计算效率更高。

Illustration of how stacking two 3x3 Convolutions will get you a receptive field of 5x5 with 18 parameters (3x3 + 3x3 = 18), while a regular 5x5 Convolution would require 25 parameters to achieve the same thing

1x1 卷积也可用于网络中的某些点,以在用 3x3 进行处理之前降低特征图的维数。ResNets 用下图所示的瓶颈块实现了这一点。我们首先将所有信息压缩到 64 个特征地图中,而不是处理一个巨大的 256 深度的特征地图。一旦它被压缩,我们应用我们的 3×3 卷积;当应用于 64 个要素地图而不是 256 个要素地图时,它的速度要快得多,并且这种处理已经被证明可以获得与常规的 3x3 堆栈相同或更好的结果。最后,在最后,我们使用另一个 1x1 映射回我们原来的 256 大小。

A ResNet bottleneck layer, utilising 1x1 convolutions to reduce feature map dimensionality

至于激活,通常与代码中的卷积相关,一个很好的经验法则是从 ReLU 开始。使用 ReLU 通常会立即得到一些好的结果,而不需要像 eLU、PReLU 或 LeakyReLU 那样进行繁琐的调整。关于哪种激活是最好的,研究界仍有很多争论。但是在实际操作中,差别往往很小,除非你真的需要那额外的 1%,否则用它们做很多实验是不值得的。一旦您确定您的设计与 ReLU 配合得很好,那么如果需要的话,您可以与其他人一起玩,调整他们的参数,尝试并提高最后一点精度。

吸取的教训

  • 对于大量的处理,使用 3x3 的堆栈
  • 使用 1x1s 来压缩和扩展特征地图,以降低计算成本

联营

CNN 中的池用于特征汇总,而当我们深入网络时进行下采样。当我们到达每个“阶段”的末尾并希望进行下采样时,我们保留空间信息的能力将由于下采样而降低。因此,为了保留我们的信息,我们进行了一些汇总来总结我们所拥有的。最常见的两种池类型是最大值和平均值。

关于最大池还是平均池更好,在研究界仍有很多争论。坦率地说,根据我的经验,这种差别可以忽略不计。也就是说,一个常用的范例是在整个网络中使用最大池来保留最佳要素,并在最后使用平均池来在最后一个密集图层之前获得要素的最终矢量表示,然后将数据传递给 softmax。

An illustration of max pooling

经验教训

  • 作为默认选项,在整个网络中使用最大池,在密集层+ softmax 之前的最末端使用全局平均池
  • 您可以尝试其他配置/风格,尽管在大多数情况下收益可能很小。

网络深度和结构

网络深度、准确性和速度之间的权衡相当简单。图层越多,总体精度越高,但由于计算量增加,网络运行速度会越慢。总的来说,你可以尝试一下深度,找到最适合你的最佳点。经过一点练习,你可能也能做出一个不错的猜测。需要注意的是,精确度和速度之间的权衡是由收益递减规律决定的,也就是说,我们增加的层数越多,每层给我们的精确度增加的就越少。

至于网络结构,像 ImageNet 这样的标准基准和上面两个漂亮的可视化让我们的工作变得容易多了!对于速度, MobileNet-v2 和深度可分离卷积块应该是默认选项。MobileNets 还有一个额外的优势,那就是它们设计得很好,可以在 CPU 上运行,在某些情况下甚至可以达到实时性!其他网络在 GPU 上的性能看起来与 MobileNets 相似,但在 CPU 上却远远不够。这是一个很大的优势,因为 CPU 计算比 GPU 便宜得多($)。

世界上最精确网络的头衔是不分胜负的: SENet 和 NASNet 在精确度上相差百分之几。如果你只是想进行迁移学习,那就用 NASNet,因为它有一些深度学习库的内置实现,比如 Keras。然而,当从头开始构建时,SENet 和挤压激励模块在实践中更容易编码。对于快速原型,或者在速度和准确性之间取得平衡的东西,一个常规的 ResNet 和剩余块就足够了。

你可能想玩的最后一件事是图像分辨率。越小越快。越大通常以内存消耗和运行时间的平方增加为代价获得更高的精度。

经验教训

  • MobileNet-v2 /深度方向可分离卷积和低速度分辨率
  • SENet / Squeeze-Excitation 或 NASNet 和高精度分辨率
  • 余额的常规 ResNet / Residual 块

数据预处理和扩充

一个经常被遗忘但需要考虑的关键问题是数据准备、预处理和扩充。你并不总是去做这件事。在对数据进行任何处理之前,您应该首先评估您的应用程序是否会从中受益。

例如,在图像分类中,标准协议是基于训练数据的平均值对图像进行均值归一化。研究文献已经多次证明,均值归一化是一种很好的默认做法。

另一方面,如果你正在进行图像增强,均值归一化实际上会对网络和结果造成相当大的伤害。任何真正与纹理、颜色或外观等非常细微的差异有关的任务,而不是高层次的形状和语义差异,可能会从而不是做任何均值归一化中受益。

另一方面,数据扩充已经被强有力地证明能够持续地提高网络性能,无论是在绝对准确性还是普遍性方面。它在从高级分类到低级增强的所有任务范围内都是如此。

话虽如此,你还是应该考虑应用哪些增强的。例如,如果您正在为自动驾驶汽车进行图像分割,您并不真的希望汽车颠倒行驶!因此,您可以应用水平翻转,但避免垂直翻转。当您实际训练您的最终网络,或者只是快速查看增强有多大帮助时,使用数据增强是最合适的。在此之前,你只是在试验和原型制作,所以没有必要通过更多的数据来延长你的训练时间。

经验教训

  • 仅在需要时进行预处理,基于您的任务,并使用经过验证的研究作为指导
  • 增强几乎总是增加准确性,只要确保您在反射中使用它,并且数据是您实际期望在应用程序中看到的

规范化

当你觉得你过度适应你的训练数据而在测试中表现不佳时,可以使用正则化。当您看到您的训练和测试精度之间的差异非常大时,您可以知道您是否过度拟合,因为您的训练精度比测试精度好得多。

有几个选项可供选择:失落,空间失落,剪切,L1,L2,添加高斯噪声…在研究论文的海洋中还有更多!实际上,dropout 是最容易使用的,因为你通常只需要把它放在几个地方,并调整一个参数。您可以将它放在网络中最后几个密集层之前。如果你觉得自己仍然过度适应,你可以在网络中更早地添加更多,或者调整退出概率。这将缩小你的训练和测试准确性之间的差距。

如果常规辍学失败,你可以和其他人一起玩。像 L1 和 L2,你有更多的调谐选择,所以也许可以校准他们,做一个比辍学更好的正规化工作。在绝大多数情况下,你不需要结合一个以上的正则化技术,即在你的整个网络中只使用一个。

吸取的教训

  • 出于实用性和易用性的考虑,默认使用 dropout
  • 如果辍学失败,探索一些其他可以定制的课程,如 L1 / L2
  • 如果所有的技术都失败了,你的训练和测试数据可能会不匹配

培养

当你最终想要训练你的网络时,有几种优化算法可供选择。许多人说 SGD 在准确性方面给你带来了最好的结果,这在我的经验中是真实的。然而,调整学习率时间表和参数可能是具有挑战性和乏味的。另一方面,使用 Adam、Adagrad 或 Adadelta 之类的自适应学习速率既快速又简单,但您可能无法获得 SGD 的最佳精度。

这里要做的最好的事情是遵循与激活函数相同的“风格”:首先从简单的开始,看看你的设计是否工作良好,然后使用更复杂的东西进行调整和优化。我建议从 Adam 开始,因为根据我的经验,它非常容易使用:只需设置一个不太高的学习率,通常默认为 0.0001,你通常会得到一些非常好的结果!以后你可以从头开始使用 SGD,甚至从 Adam 开始,然后用 SGD 进行微调。事实上,本文发现,从 Adam 切换到 SGD 中训,以最简单的方式达到了最好的准确率!看看报纸上的下图:

至于你的数据,越多越好。唯一要考虑的是你从哪里开始得到收益递减。例如,如果您已经达到 95%的准确率,并且您估计如果您将训练数据翻倍,您可以达到 96%,那么可能是时候真正考虑您是否真的需要这 1%,因为达到这一水平所需的努力和资源相当高。当然,要确保您收集的数据反映了您将在实际应用中看到的情况。否则,无论你使用什么算法,选择不当的数据都不能解决问题。

喜欢学习?

在推特上关注我,我会在那里发布所有最新最棒的人工智能、技术和科学!也在 LinkedIn 上和我联系吧!

建立神经网络结构的有效方法指南——第一部分:用 Hyperas 对密集网络进行超参数选择和调整——MNIST

原文:https://towardsdatascience.com/a-guide-to-an-efficient-way-to-build-neural-network-architectures-part-i-hyper-parameter-8129009f131b?source=collection_archive---------1-----------------------

介绍

“如果你听从你的直觉,你将永远知道什么是最适合你的”

这是人们在讲授生活时所说的,对生活来说可能是真的,但对训练神经网络来说,这是我所相信的

“相信你的直觉,但也要相信你的逻辑,不要为了弥补一个而忽略另一个”

这源于这样一个事实,即我遇到的许多人在被问到为什么在他们的神经网络架构中选择某些值时,他们通常回答说“嗯,只是直觉和一点点尝试”,这似乎不太合适,因为这不能帮助我们知道我们的模型实际上有多有效,以及是否有任何架构组合可以帮助我们实现更好的概括结果。

因此,通过这个博客,我想分享我在修补深度学习模型时学到的一些旅行和技巧,以及我遵循的一条铺设好的道路,以帮助我实现最佳架构,获得最佳结果

这里显示的所有结果都是我在 appliedaicourse.com 大学 ML/AI 课程中对时尚 MNIST 数据进行的一个案例研究的结果。感谢 AppliedAICourse 团队在撰写本博客时提供的宝贵建议。

更多的数据可以从https://www.kaggle.com/zalando-research/fashionmnist、https://github.com/zalandoresearch/fashion-mnist了解。帮助我们开始工作的数据的重要细节如下

-包含 28x28 件衣服的图像
-包含训练集的 60,000 幅图像和测试集的 10,000 幅图像
-我们的任务是将图像分为 10 个不同的类别,如 t 恤/上衣、裤子、套头衫、连衣裙等。

必要的函数库或软件包有:-
-tensor flow
-Keras
-Numpy
-Hyperas,Hyperopt

  • Matplotlib

您将需要一个 IPython 笔记本来在您的项目中尝试这一点或跟随它。

博客中遵循的程序是从一个基本的基线模型开始,找出我们可以调整的超参数,以及它们对提高我们的架构效率的影响,最后是如何调整超参数,以获得最佳架构,从而实现架构的最佳可能结果。

本文讨论密集网络中的超参数调整,并奠定基础。第二部分进一步学习了这篇文章,并给出了如何训练 CNN 的技巧。请务必在完成这篇文章时也阅读下面的链接。

[## 建立神经网络结构的有效方法指南-第二部分:超参数…

介绍

medium.com](https://medium.com/@shashank.ramesh2396/a-guide-to-an-efficient-way-to-build-neural-network-architectures-part-ii-hyper-parameter-42efca01e5d7)

超参数是一个可配置的值,在学习过程开始前设置。这些超参数值决定了训练算法的行为以及它如何从数据中学习参数。

选择正确的指标

在我们开始之前,我们需要清楚地了解我们手头的问题,然后选择一个指标来衡量我们的模型和损失函数的性能,我们打算对其进行优化。我们的问题是一个一般的图像分类任务,我们选择精度作为度量,分类交叉熵作为我们的损失函数

稀疏分类交叉熵和分类交叉熵之间的区别在于,当输出不是一次性编码(1,2,3 等)时,使用稀疏分类交叉熵。)和分类交叉熵(当输出是一位热编码时([1,0,0]或[0,1,0])。稀疏分类交叉熵和分类交叉熵可以被认为是对数损失的多类变体。

Distribution of data-points among all classes

从图中可以推断出,数据集是平衡的,因为我们在每个类中都有几乎相同数量的数据点。这种检查对于选择准确性作为度量是必要的。其他选择可以是 F1-score。选择 Log-loss 是因为最小化它不仅有助于最小化不正确的分类,而且确保我们以高概率预测正确的类别。

预处理数据

我们从 keras.datasets 加载数据

from keras.datasets import fashion_mnist
(X_train, y_train), (X_test, y_test) = fashion_mnist.load_data()

我们只提供了一个训练和测试集,因为我们还需要一个验证集。我们使用 scikit-learn 的训练-测试拆分将获得的训练数据拆分为 80%训练和 20%验证

from sklearn.model_selection import train_test_split
X_train, X_val, y_train, y_val = train_test_split(X_train, y_train, test_size=0.2, random_state=12345)

训练集是模型学习/训练的数据点集,验证集用于比较模型和测试集,以查看我们的模型对未知输入(我们没有训练过的输入)的概括程度

由于我们将首先使用密集的神经网络,因此在将数据输入网络之前,我们需要对数据进行一些预处理。这包括:-

-将列车验证和测试数据的形状从 28x28 格式更改为 784 个值的列表
-标准化我们的输入,使输入值的范围从 0 到 1,而不是从 0 到 255,标准化也可以完成

标准化/规范化输入可以使训练更快,并减少陷入局部最优的机会,因此强烈建议在将数据输入网络进行训练之前进行

X_train = X_train.reshape(48000, 784)
X_val = X_val.reshape(12000, 784)
X_test = X_test.reshape(10000, 784)
X_train = X_train.astype(‘float32’)
X_val = X_val.astype(‘float32’)
X_test = X_test.astype(‘float32’)
X_train /= 255
X_val /= 255
X_test/= 255

此外,由于我们已经使用了分类交叉熵,我们需要将我们的输出转换为独热编码形式,这可以很容易地做到如下

# np is numpy
nb_classes = 10 
Y_train = np_utils.to_categorical(y_train, nb_classes)
Y_val = np_utils.to_categorical(y_val, nb_classes)
Y_test= np_utils.to_categorical(y_test, nb_classes) 

基础模型

首先从一个基本模型开始,然后在每一步中不断尝试改进它,这是一个很好的做法。我们的基线模型将是一个 softmax 分类器,它将像素值列表作为输入,并将输出 class-label

model = Sequential([
 Dense(10,input_shape=(784,),activation=’softmax’)
])
model.compile(optimizer=keras.optimizers.SGD(lr=0.1),
 loss=’categorical_crossentropy’,
 metrics=[‘accuracy’])

对于上述模型,损失和精度值如下所示

Train loss: 0.4080537739445766
Train accuracy: 0.8587291666666667
-------------------------------
Validation loss: 0.4190353289047877
Validation accuracy: 0.8551666666666666
-------------------------------
Test loss: 0.4566255069732666
Test accuracy: 0.8375

为了进一步改进模型,我们需要知道在我们的密集网络中哪些是我们可以调整的超参数,接下来的部分将向您简要介绍超参数以及它们如何影响学习,但在此之前,让我们了解为什么我们需要超参数调整。

需要超参数调整

  1. 在偏差和方差之间找到正确的平衡:-在使用密集神经网络训练我们的数据时,很容易实现非常高的精度,但是这些可能不能很好地推广到我们的验证和测试集。此外,如果我们尝试并抑制自己使用深度/复杂的架构,则我们的数据集总是有可能具有低精度,因此我们需要找到推广良好且具有高精度的最佳点。每个超参数都会影响偏差方差。
  2. 为了防止我们自己陷入消失/爆炸梯度问题:-反向传播步骤可能涉及许多梯度值的相乘,并且如果梯度值很小(<1) we may suffer from the vanishing gradient problem and if they are large(> 1),我们可能遭受爆炸梯度问题。我们可以通过在学习率、激活函数和层数的超参数调整时进行必要的调整来避免这一点
  3. 遇到鞍点和局部最优:-一些模型可能会陷入梯度接近零的鞍点和局部最小值,因此我们需要调整学习率等超参数,并将优化器更改为 Adam 或 RMSProp,以避免陷入困境并停止进一步学习。

Optimizers on encountering saddle points

4.没有收敛:-众所周知,较大的学习速率可以防止收敛到最小值,如下所示,但同时,如果学习速率太慢,我们可能无法收敛到最小值,因为我们向它迈出了非常小的步伐。为了克服这个问题,我们可以选择 Adam 这样的自适应学习率优化器,或者在优化器中使用 decay。

Effect of learning rate

5.Sigmoid 和 tanh 激活函数问题:-sigmoid 和 tanh 函数在其末端是弯曲的,导致这些点处的梯度非常低,因为即使当应用 sigmoid 激活之前的值显著增加时,应用之后的值也不会增加,因此即使梯度也不会增加很多,从而影响学习。但是 Sigmoid 和 tanh 可能是浅层网络(最多 2 层)的好选择。

6.为了加速学习:-通过获得正确的超参数集,与更复杂且需要更多时间训练的模型相比,我们可以获得更好的结果。

7.所有超参数的无数组合:-超参数的数量和它们可以取的值在深度学习中相当高,因为它们在计算可能的组合时共存,我们可以很容易地达到一个非常大而令人生畏的数字。因此,本文将尝试使用我在训练深度神经架构方面的经验,向您提供一些应对这一问题的提示和技巧。

8.事半功倍:-更多元件和复杂架构并不总是降低损耗、提高精度的最佳选择,相反,要确保充分利用现有架构,并在需要时慢慢增加复杂度和元件。

超参数:密集网络

  1. 层数:-必须明智地选择层数,因为很高的层数可能会引入过拟合、消失和爆炸梯度问题等问题,而较低的层数可能会导致模型具有高偏差和低潜力模型。在很大程度上取决于用于训练的数据量
  2. 每层隐藏单元的数量:-这些也必须合理选择,以便在高偏差和方差之间找到一个最佳点。再次取决于用于训练的数据大小
  3. 激活函数:-这方面的流行选择是 ReLU、Sigmoid & Tanh(仅适用于浅层网络)和 LeakyReLU。一般来说,选择 ReLU/LeakyReLU 做得同样好。Sigmoid/Tanh 可能适用于浅层网络。同一性在回归问题中有帮助。
  4. 优化器:-它是模型使用的算法,用于在每次迭代后更新每一层的权重。比较受欢迎的选择是 SGD,RMSProp 和 Adam。SGD 适用于浅层网络,但无法避开鞍点和局部最小值。在这种情况下,RMSProp 可能是更好的选择,AdaDelta/AdaGrad 适用于稀疏数据,而 Adam 是最受欢迎的方法,可用于实现更快的收敛。进一步参考https://towardsdatascience . com/types-of-optimization-algorithms-used-in-neural-networks-and-ways-to-optimization-gradient-95 ae5d 39529 f
  5. 学习率:-它负责核心学习特性,并且必须以这样的方式选择,即它不能太高而不能收敛到最小值,也不能太低而不能加速学习过程。建议以 10 的幂尝试,具体为 0.001,0.01,0.1,1。学习率的值在很大程度上取决于所使用的优化器。对于 SGD - 0.1 通常工作良好,而对于 Adam - 0.001/0.01,但建议总是尝试上述范围内的所有值。你也可以使用衰减参数,以减少你的学习与迭代次数,以达到收敛。一般来说,使用 Adam 这样的自适应学习率算法比使用衰减学习率要好。
  6. 初始化:-没有发挥很大的作用,因为默认值工作得很好,但仍然首选使用 He-normal/uniform 初始化,同时为 Sigmoid 使用 ReLUs 和 Glorot-normal/uniform(默认为 Glorot-uniform)以获得更好的结果。必须避免使用零或任何恒定值(所有单位相同)的重量初始化
  7. 批量大小:-它表示在更新权重矩阵之前向网络显示的模式数量。如果批量较小,模式的重复性会降低,因此权重会到处都是,收敛会变得困难。如果批量很大,学习将变得很慢,因为只有在多次迭代之后批量才会改变。建议根据数据大小以 2 的幂尝试批量大小(以便更好地优化内存)。
  8. 时期数:-时期数是整个训练数据显示给模型的次数。它在模型与训练数据的拟合程度上起着重要的作用。大量的历元可能会过度拟合数据,并可能在测试和验证集上产生泛化问题,还可能导致消失和爆发梯度问题。较少的历元数可能会限制模型的潜力。根据您拥有的时间和计算资源尝试不同的值。
  9. 漏失:-漏失层的保持概率可以被认为是超参数,其可以作为正则化器来帮助我们找到最佳偏差变化点。这是通过在每次迭代中移除某些连接来实现的,因此隐藏的单元不会太依赖于任何特定的特征。它可以取 0-1 之间的任何值,完全取决于模型过度拟合的程度。
  10. L1/L2 正则化:-充当另一个正则化器,其中非常高的权重值被抑制,使得模型不依赖于单个特征。这通常会以增加偏差(即降低精度)为代价来降低方差。当模型继续过度拟合时,甚至在大幅增加压差值后也应使用

简介 Hyperas

现在,我们已经了解了超参数调整的必要性,并了解了在调整我们的密集网络时要考虑的超参数,我们现在继续讨论如何进行调整。

我们有两种选择,一种是 scikit-learn GridSearchCV 方法,可以通过 Keras 中的 scikit-learn API 包装器来使用,这种方法不利用 GPU 加速,因此即使在并行化后也无法实现很高的速度,我们将在这里讨论的另一种方法是 Hyperas,它使我们能够利用 GPU 加速,使您训练模型的速度至少提高 10 倍,也是一种接近超参数调整的简单方法。如果你没有 GPU,选择任何一个选项都会给你几乎相同的速度。

这里使用的 Hyperas 模块是指位于https://github.com/maxpumperla/hyperas的模块。要使用 Hyperas,您首先需要使用 pip 安装包

pip install hyperas

然后,在您的项目中,您将需要添加以下导入语句

from hyperopt import Trials, STATUS_OK, tpe
from hyperas import optim
from hyperas.distributions import choice, uniform

如果遇到任何错误,请参考位于https://github.com/maxpumperla/hyperas的常见问题部分

使用 Hyperas:密集网络

一旦你完成了上面的工作,要进行超参数优化,你需要 3 个代码片段

  1. 数据功能

您需要创建一个从源直接加载训练和验证数据的函数,或者如果您已经进行了任何预处理,建议将预处理后的数据存储在 pickle/numpy/hdf5/csv 文件中,并在数据函数中编写代码以从该文件中访问数据。

以这种方式加载数据是必要的,因为 Hyperas 将数据加载函数缓存到 pycache 上,该 py cache 与您的项目位于同一文件夹中,并且它不能访问您在程序中使用的全局变量,因此有了上面的解决方法。

在我的例子中,我直接从数据源加载数据,并重复所有的预处理步骤,如下所示。我还可以在预处理后将训练和验证数据存储到一个 hdf5 文件中,并在数据函数中从那里检索它,无论如何它都会工作,除非我不希望在我的程序中访问任何全局变量的值。

该函数返回 X_train、Y_train、X_val、Y_val,它们是保存训练数据及其对应的类标签以及验证数据及其对应的类标签的变量

def data():
    (X_train, y_train), (X_test, y_test) = fashion_mnist.load_data()
    X_train, X_val, y_train, y_val = train_test_split(X_train,    y_train, test_size=0.2, random_state=12345)
    X_train = X_train.reshape(48000, 784)
    X_val = X_val.reshape(12000, 784)
    X_train = X_train.astype('float32')
    X_val = X_val.astype('float32')
    X_train /= 255
    X_val /= 255
    nb_classes = 10
    Y_train = np_utils.to_categorical(y_train, nb_classes)
    Y_val = np_utils.to_categorical(y_val, nb_classes)
    return X_train, Y_train, X_val, Y_val

调试提示:-如果您遇到任何与数据函数相关的错误,请尝试在函数的开头再次添加函数或数据函数中使用的包的导入语句

2.模型函数

这是我们定义我们的架构价值的一般框架和我们想要调整的超参数的地方。模型函数包含我们的模型的 Keras 体系结构,用{ { choice([])} }或{ { uniform()} }代替我们希望调整的超参数值。用于优化时尚 MNIST 架构的模型函数示例如下所示

def model(X_train, Y_train, X_val, Y_val):

    model = Sequential()
    model.add(Dense({{choice([128, 256, 512, 1024])}}, input_shape=(784,)))
    model.add(Activation({{choice(['relu', 'sigmoid'])}}))
    model.add(Dropout({{uniform(0, 1)}}))
    model.add(Dense({{choice([128, 256, 512, 1024])}}))
    model.add(Activation({{choice(['relu', 'sigmoid'])}}))
    model.add(Dropout({{uniform(0, 1)}}))

    if conditional({{choice(['two', 'three'])}}) == 'three':
        model.add(Dense({{choice([128, 256, 512, 1024])}}))
        model.add(Activation({{choice(['relu', 'sigmoid'])}}))
        model.add(Dropout({{uniform(0, 1)}}))
            model.add(Dense(10))
    model.add(Activation('softmax')) adam = keras.optimizers.Adam(lr={{choice([10**-3, 10**-2, 10**-1])}})
    rmsprop = keras.optimizers.RMSprop(lr={{choice([10**-3, 10**-2, 10**-1])}})
    sgd = keras.optimizers.SGD(lr={{choice([10**-3, 10**-2, 10**-1])}})

    choiceval = {{choice(['adam', 'sgd', 'rmsprop'])}}
    if choiceval == 'adam':
        optim = adam
    elif choiceval == 'rmsprop':
        optim = rmsprop
    else:
        optim = sgd

    model.compile(loss='categorical_crossentropy', metrics=['accuracy'],optimizer=optim) model.fit(X_train, Y_train,
              batch_size={{choice([128,256,512])}},
              nb_epoch=20,
              verbose=2,
              validation_data=(X_val, Y_val))
    score, acc = model.evaluate(X_val, Y_val, verbose=0)
    print('Test accuracy:', acc)
    return {'loss': -acc, 'status': STATUS_OK, 'model': model}

以上说明了我们如何制作一个我们希望我们的模型是什么样子的一般框架,以及我们希望调整的超参数是什么。

model . add(Dense({ { choice([128,256,512,1024])} })-此行用于传达我们希望调整层中隐藏单元的数量,并在 128、256、512 和 1024 中找到最佳匹配。

model . add(Activation({ { choice([' relu ',' sigmoid ')} })-该行用于传达我们希望调整激活函数参数并在 ReLU 和 Sigmoid 之间找到最佳匹配的事实

model . add(Dropout({ { uniform(0,1)} })-这一行用于传达这样一个事实,即我们希望调整保持丢失概率的值,并在 0 和 1 之间的实数范围内找到最佳匹配。

“选择”中包含的值是我们希望用来调整超参数的值,“统一”中包含的范围是我们期望超参数的最佳值所在的实数范围

Hyperas 模块运行许多不同的模型,每次从每个值池中取一个值,通过我们希望调整的所有超参数值的“选择”和“统一”给出。最后,它给出了在验证集上运行时获得最低损失值的值的组合。可以认为是在做类似于 sklearn 中的 RandomSearchCV 的事情。

if conditional({{choice(['two', 'three'])}}) == 'three':
        model.add(Dense({{choice([128, 256, 512, 1024])}}))
        model.add(Activation({{choice(['relu', 'sigmoid'])}}))
        model.add(Dropout({{uniform(0, 1)}}))

上面的代码片段用于调整层数,以了解两层或三层密集网络架构是否是一个好的选择。这里,在迭代期间,从{{choice(['two ',' three'])}}中选择一个值。

if conditional({{choice(['two', 'three'])}}) == 'three':

如果值为“2 ”,则不满足 If 条件中的条件,因此不执行 if 块中的代码,只给我们留下两层架构,或者如果选择的值为“3 ”,则条件满足,并且执行 if 块,给我们一个三层架构来测试当前迭代。

 adam = keras.optimizers.Adam(lr={{choice([10**-3, 10**-2,  10**-1])}})
    rmsprop = keras.optimizers.RMSprop(lr={{choice([10**-3, 10**-2, 10**-1])}})
    sgd = keras.optimizers.SGD(lr={{choice([10**-3, 10**-2, 10**-1])}})

    choiceval = {{choice(['adam', 'sgd', 'rmsprop'])}}
    if choiceval == 'adam':
        optim = adam
    elif choiceval == 'rmsprop':
        optim = rmsprop
    else:
        optim = sgd

上面的代码片段用于调优优化器和学习率。在迭代上述部分时,从每个优化器的学习率的值池中选择一个值,随后从 {{choice(['adam ',' sgd ',' rmsprop'])}} 中选择一个值。如果选择的值是“adam”,则对于当前迭代,Adam 优化器连同从Adam = keras . optimizer . Adam(lr = { { choice([10 * *-3,10-2,10 * *-1])})**中的值池中选择的学习率被用作模型的优化器,这是下面的 If 块中传达的内容

 if choiceval == 'adam':
        optim = adam
    elif choiceval == 'rmsprop':
        optim = rmsprop
    else:
        optim = sgd

3.执行

X_train, Y_train, X_val, Y_val = data()best_run, best_model = optim.minimize(model=model,
                                      data=data,
                                      algo=tpe.suggest,
                                      max_evals=30,
                                      trials=Trials(),
                                      notebook_name='Fashion_MNIST')

该代码片段将使用数据函数中给出的训练和验证数据,开始对模型函数中给出的框架进行超参数优化。

optim . minimize 函数中的所有值必须保持相同,除了 notebook_name 参数、max_evals 参数之外,Notebook _ name 参数用于输入您的 IPython 笔记本的名称,而max _ evals 参数用于输入在为您的架构选择正确的超参数集之前您希望训练的模型的最大数量。该值取决于您拥有的资源和时间,一般来说,30-50 之间的值就足够了。

上述代码片段必须在数据和模型函数之后编写,并将开始执行 Hyperas 模块,该模块将返回 best_model 变量中的最佳模型配置和 best_run 中的最佳超参数集。

可以使用print(best _ model . evaluate(X _ test,Y_test)) 使用测试集中的最佳模型进行预测或者 print(best_run) 了解最佳模型中有哪些参数选择。在执行print(best _ run)时,您将得到如下所示的输出

{'Activation': 0, 'Activation_1': 0, 'Activation_2': 0, 'Dense': 3, 'Dense_1': 3, 'Dense_2': 1, 'Dropout': 0.6346993188487943, 'Dropout_1': 0.3471522714859784, 'Dropout_2': 0.42208889978571484, 'batch_size': 1, 'choiceval': 0, 'conditional': 1, 'lr': 0, 'lr_1': 1, 'lr_2': 1}

为了解释上述内容,您需要查看包含运行代码的执行部分时的输出的部分,如下所示。

Output of the execution section and print(best run)

model = Sequential()
model.add(Dense(space['Dense'], input_shape=(784,)))
model.add(Activation(space['Activation']))
model.add(Dropout(space['Dropout']))
model.add(Dense(space['Dense_1']))
model.add(Activation(space['Activation_1']))
model.add(Dropout(space['Dropout_1']))

if conditional(space['conditional']) == 'three':
    model.add(Dense(space['Dense_2']))
    model.add(Activation(space['Activation_2']))
    model.add(Dropout(space['Dropout_2']))model.add(Dense(10))
model.add(Activation('softmax'))
adam = keras.optimizers.Adam(lr=space['lr'])
rmsprop = keras.optimizers.RMSprop(lr=space['lr_1'])
sgd = keras.optimizers.SGD(lr=space['lr_2'])
choiceval = space['choiceval']
if choiceval == 'adam':
     optim = adam
elif choiceval == 'rmsprop':
     optim = rmsprop
else:
     optim = sgd
model.compile(loss='categorical_crossentropy', metrics=['accuracy'],
                 optimizer=optim)
model.fit(X_train, Y_train,batch_size=space['batch_size'], nb_epoch=20, verbose=2, validation_data=(X_val, Y_val))

如图所示,输出包含模型框架,每个空间/值池的名称作为模型函数中的输入给出。要了解所选的确切值,我们可以参考我们在模型函数中任何空间变量位置处提供的空间/值池。

'密集':3 表示对于第一层中隐藏单元的数量,最佳模型使用列表中索引 3 处的值 1024。请注意:-使用的索引值从 0 开始。

' Activation_1':0 表示对于第二层,最佳模型具有 ReLU 作为它的激活函数。

' conditional': 1 表示最佳模型由 3 层组成。

' choiceval':0 表示最佳模型使用 Adam 作为优化器,学习率为 0.001(由 lr:0 给出)。

Dropout_2':0.42…表示隐藏单元的第三层使用 0.42 的 keep-prob 后的丢弃层。

如上所示解码所有参数值后的最佳模型的最终模型配置为

model = Sequential([
    Dense(1024, input_shape=(784,), activation='relu'),
    Dropout(0.63),
    Dense(1024, activation='relu'),
    Dropout(0.35),
    Dense(256, activation='relu'),
    Dropout(0.42),
    Dense(10, activation='softmax')
])

运行 40 个时期的该模型给出以下结果

Train loss: 0.23121074857314428
Train accuracy: 0.9159583333333333
-------------------------------
Validation loss: 0.28158413629730544
Validation accuracy: 0.9024166666666666
-------------------------------
Test loss: 0.3213586136817932
Test accuracy: 0.8871

我们已经实现了 88%的测试准确度,而之前在基线模型中为 83%。这是一个好的开始,但我们将在下一部分使用卷积神经网络继续这一探索。

提示和技巧

1.不要用测试数据代替验证集。始终将手头的数据集分为 3 组:训练、验证和测试。使用 train 来学习数据中的各种模式,使用 validation 来学习超参数的值,并测试模型是否概括良好。

2.确保您在优化时仅针对最重要的超参数进行训练,即,始终尝试减少超参数的数量及其值,我们使用文章中所述的经验法则进行调整。这是因为超参数和它们的值越多,需要训练的模型的数量就越多,以便在优化时实现公正。

例如,在上述情况下,在激活函数的值中,我们没有使用 LeakyReLU,这是因为 LeakyReLU 的性能总是等于或略好于 ReLU。类似地,我没有优化初始化超参数,因为我们知道,如果是重新激活,我们需要使用 He-normal 和 glrot-normal if Sigmoid 作为经验法则。时段数尚未优化,因为我们不希望我们的模型通过设置较大的时段数值来花费很长时间来查找超参数。我们还希望模型能够快速学习,因此时段数设置为 20。在模型选择之后,我们可以运行模型更多的时期。

正如您可能已经观察到的,我们只优化那些对学习有很大影响的组合,如层数、隐藏单元、学习速率等。

3.调试提示:-当您必须在上次执行后更改模型函数时,建议总是删除 pycache 文件夹,因为即使您更改了模型函数,模块也可能使用 pycache 中的旧版本进行优化。如果您仍然面临更新模型函数的问题,请在删除 pycache 后重启您的内核。

pycache 文件夹位于项目运行所在的笔记本所在的文件夹中。

希望这篇文章能帮助你为你的密集网络找到合适的架构,并且你能做出更多的超参数优化模型而不是直觉模型。感谢您的阅读!

参考文献

  1. https://towards data science . com/what-is-hyperparameters-and-how-to-tune-the-hyperparameters-in-a-deep-neural-network-d 0604917584 a
  2. 【https://github.com/maxpumperla/hyperas
  3. https://medium . com/machine-learning-world/neural-networks-for-algorithm-trading-hyperparameters-optimization-CB 2 B4 a 29 b 8 ee
  4. https://medium . com/@ jrod thoughts/knowledge-tuning-hyperparameters-in-machine-learning-algorithms-part-I-67a 31 B1 f 7 c 88
  5. https://www.appliedaicourse.com/

建立神经网络体系结构的有效方法指南——第二部分:用 Hyperas 对卷积神经网络进行超参数选择和调整——时尚 MNIST

原文:https://towardsdatascience.com/a-guide-to-an-efficient-way-to-build-neural-network-architectures-part-ii-hyper-parameter-42efca01e5d7?source=collection_archive---------0-----------------------

介绍

本文是下面链接的文章的延续,该文章涉及超参数优化的需要以及如何使用 Hyperas 对密集神经网络(多层感知器)进行超参数选择和优化

[## 建立神经网络结构的有效方法指南-第一部分:超参数…

介绍

medium.com](https://medium.com/@shashank.ramesh2396/a-guide-to-an-efficient-way-to-build-neural-network-architectures-part-i-hyper-parameter-8129009f131b)

在当前的文章中,我们将从第一部分停止的地方继续,并尝试解决相同的问题,即使用卷积神经网络(CNN)的时尚 MNIST 数据集的图像分类任务。

为什么是 CNN?

CNN 有几个不同的滤波器/内核,由可训练的参数组成,这些参数可以在给定的图像上进行空间卷积,以检测像边缘和形状这样的特征。这些高数量的滤波器本质上学习通过反向传播基于所学习的权重从图像中捕捉空间特征,并且滤波器的堆叠层可用于从每个后续级别的空间特征中检测复杂的空间形状。因此,他们可以成功地将一个给定的图像浓缩成一个高度抽象的、易于预测的表示。

在密集网络中,我们试图在作为输入给出的像素值中找到模式,例如,如果像素号 25 和 26 大于某个值,则它可能属于某个类以及该类的一些复杂变体。如果我们在图像中的任何地方都可以有对象,而不一定像在 MNIST 或在某种程度上在时尚 MNIST 数据中那样居中,这可能很容易失败。

另一方面,rnn 在数据中寻找序列,并且边缘或形状也可以被认为是像素值的序列,但是问题在于它们只有一个单一的权重矩阵,该矩阵被所有的循环单元使用,这无助于寻找许多空间特征和形状。而 CNN 可以在一层中具有多个内核/过滤器,使它们能够找到许多特征,并在此基础上形成每个后续层的形状。RNNs 将需要很多层和大量的时间来模拟,因为它们只能在一层找到很少的序列。

因此,让我们继续研究卷积网络,看看更深层次的超参数优化版本能有多好,但在此之前,让我们看看卷积神经网络中的额外超参数。

超级参数:CNN

这里我们将讨论 CNN 中的附加参数,请参考第一部分(开头的链接)了解密集层中的超参数,因为它们也是 CNN 架构的一部分。

  1. 内核/过滤器大小:过滤器是一个权重矩阵,我们用它对输入进行卷积。卷积上的过滤器可用于测量输入面片与要素的相似程度。特征可以是垂直边缘或拱形,或者任何形状。滤波器矩阵中的权重是在训练数据时导出的。较小的过滤器收集尽可能多的局部信息,较大的过滤器代表更多的全局、高级和代表性信息。如果你认为大量的像素对于网络识别物体是必要的,你将使用大的过滤器(如 11x11 或 9x9)。如果你认为区分物体的是一些小的和局部的特征,你应该使用小的过滤器(3x3 或 5x5)。注意,通常我们使用奇数尺寸的过滤器。
  2. 填充:填充通常用于添加零的列和行,以在卷积后保持空间大小不变,这样做可能会提高性能,因为它保留了边界处的信息。Keras 中填充函数的参数为 Same -通过左右均匀填充,输出大小与输入大小相同,但如果要添加的列数为奇数,它会将额外的列添加到右侧。 有效 -输出大小缩小到 ceil((n+f-1)/s),其中“n”是输入尺寸,“f”是滤波器大小,“s”是步长。ceil 将小数四舍五入为最接近的整数,不进行填充。
  3. 跨距:通常是在输入权重与过滤器中的权重按元素相乘后,卷积期间水平和垂直遍历输入时希望跳过的像素数。它用于显著减小输入图像尺寸,因为卷积运算后尺寸缩小到 ceil((n+f-1)/s),其中“n”是输入尺寸,“f”是滤波器尺寸,“s”是步长。ceil 将小数四舍五入为最接近的整数。
  4. 通道数:它等于输入的颜色通道数,但在后面的阶段等于我们用于卷积运算的滤波器数。通道数量越多,使用的过滤器数量越多,学习的特征就越多,过拟合的机会就越多,反之亦然。
  5. 汇集层参数:汇集层也具有与卷积层相同的参数。最大池通常在所有池选项中使用。目标是对输入表示(图像、隐藏层输出矩阵等)进行下采样。),通过保持子区域中的最大值(激活的特征)入库来减少其维数。

引入批量标准化:- 通常,在深度神经网络架构中,标准化输入在经过中间层的各种调整后变得过大或过小,同时到达较远的层,这导致影响学习的内部同变量偏移问题。为了解决这一问题,我们添加了批量标准化层,以标准化(均值居中和方差缩放)给予后面层的输入。这一层通常必须在通过包含激活功能的层之后、在脱落层(如果有)之前放置在架构中。sigmoid 激活函数是一个例外,其中您需要在激活前放置批处理规范化图层,以确保在应用函数前值位于 sigmoid 的线性区域内。

构建 CNN 架构的原则/惯例

构建卷积神经网络所遵循的基本原则是在网络的初始阶段保持特征空间的宽和浅,并在接近结束时使其变得更窄和更深

谨记上述原则,我们制定了一些在构建 CNN 架构时需要遵循的惯例来指导您

1.总是从使用更小的过滤器开始是为了收集尽可能多的局部信息,然后逐渐增加过滤器宽度以减少生成的特征空间宽度来表示更全局、更高级和更有代表性的信息

2.遵循该原则,通道的数量在开始时应该是低的,以便它检测低级别特征,这些低级别特征被组合以形成许多复杂的形状(通过增加通道的数量),这有助于在类别之间进行区分。

增加过滤器的数量以增加特征空间的深度,从而帮助学习更多层次的全局抽象结构。使特征空间变得更深更窄的另一个用途是缩小输入到密集网络的特征空间。

按照惯例,当我们在卷积神经网络架构中逐层前进时,通道数量通常会增加或保持不变

3.对于中等或小尺寸图像的卷积层,使用的一般滤波器大小为 3×3、5×5 和 7×7,对于最大池参数,我们使用步长为 2 的 2×2 或 3×3 滤波器大小。较大的过滤器尺寸和跨度可用于将大图像缩小到中等尺寸,然后进一步遵循所述的惯例。

4.当您觉得图像的边界可能很重要或只是为了帮助延长您的网络架构时,请尝试使用 padding = same,因为即使在卷积操作之后,padding 也会保持尺寸不变,因此您可以执行更多的卷积而不会缩小尺寸。

5.不断添加层,直到你超适合。一旦我们在验证集中达到相当高的准确度,我们就可以使用正则化组件,如 l1/l2 正则化、剔除、批量规范、数据扩充等。为了减少过度拟合

5.始终使用经典网络,如 LeNet、AlexNet、VGG-16、VGG-19 等。作为构建模型架构的灵感。我所说的灵感是指遵循架构中使用的趋势,例如 conv-池-conv-池或 conv-conv-池-conv-conv-池层中的趋势,或通道数量 32–64–128 或 32–32–64–64 的趋势,或过滤器尺寸、最大池参数等的趋势。

构建 CNN 架构

由于上述惯例,CNN 的超参数调谐比密集网络的调谐稍微困难一些。这是因为 Hyperas 使用随机搜索来寻找可能的最佳模型,这反过来可能导致违反一些惯例,为了防止这种情况发生 我们需要设计 CNN 架构,然后在 Hyperas 中微调超参数,以获得我们的最佳模型。

在调谐密集网络时与 Hyperas 一起使用的方法,其中我们为所有超参数给出一个集合 a 值,并让模块决定哪一个是最佳的,对于调谐 CNN 不起作用。这是因为在每一层,由于卷积和最大池化等操作,输入维度减少,因此,如果我们给定步幅、滤波器大小等超参数的值范围。Hyperas 总是有可能选择一个以负维异常结束并在完成前停止的模块。

那么如何构建你问的架构呢?我们开始吧。但在此之前,我想回顾一下,在使用卷积或池层时,我们将输入图像的维数 N 降低到(N-f+1)/s,其中“f”是滤波器大小,“s”是步长,这在处理过程中对我们非常有帮助。

关于如何构建 CNN 架构的第一个示例如下所示,该示例从 LeNet-5 架构中获得灵感

第一步是制作一张包含建筑尺寸、激活形状和大小的表格,如下所示

更多参考请参考 AndrewNg 的视频-【https://www.youtube.com/watch?v=w2sRcGha9nM】T4&t = 485s

这里,我们计算每个卷积或池化操作之后的激活形状为 (ceil(N+f-1)/s,ceil(N+f-1)/s,滤波器的数量),其中填充值为“有效”并且维度为(N,N,滤波器的数量),其中使用的填充为“相同”,这里“N”是输入维度,“f”是滤波器大小,“s”是步长。激活值通过将激活形状的维度中的所有值相乘来计算。

对于第二阶段,N=28,f=3,s=1,滤波器数量=8,填充有效,因此我们得到激活形状为(28,28,8)。激活值= 28x28x8=6272

对于第三阶段最大池层,我们得到 ceil((28–2+1)/2)= ceil(13.5)= 14,因此维度为(14,14,8)。最后一个维度在使用池层时不会改变。激活值= 14x14x8=1568

对于第四级,N=14,f=5,s=1,滤波器数量=8,填充有效,因此我们得到激活形状为((14–5+1)/2,(14–5+1)/2,16)= (10,10,16)

Flatten 使输入成为一维列表,以便输入到密集层,因此激活形状是(400,1)。激活值= 400x1=400

密集激活形状(64,1)表示在密集层中使用了 64 个隐藏单元。激活值= 64x1=64

这一计算告诉我们,在构建 CNN 架构时,我们是否选择了正确的参数,因为架构绝不能因过度使用高值的步长和滤波器尺寸而以负维度结束

确保您选择的值在激活值中有一个总体下降趋势,并且在激活值中没有任何非常突然的变化,这一点非常重要

接下来,我们将模型架构转换成 keras 代码。

cnn1 = Sequential([
    Conv2D(8, kernel_size=(3, 3), activation='relu',padding='same',input_shape=input_shape),
    MaxPooling2D(pool_size=(2, 2),strides=2),
    Conv2D(16, kernel_size=(5, 5), activation='relu'),
    MaxPooling2D(pool_size=(2, 2),strides=2),
    Flatten(),
    Dense(120, activation='relu'),
    Dense(84, activation='relu'),
    Dense(10, activation='softmax')
])

转换成 keras 代码后,检查转换是否正确,尺寸是否符合您的要求,您可以使用。摘要“输出形状”列为您提供了输出尺寸

使用学习率为 0.001 的 Adam 优化器通常可以很好地处理 CNN,因此我们使用它来训练架构,以获得如下所示的精度值

Train loss: 0.18204240553701917
Train accuracy: 0.932125
-------------------------------
Validation loss: 0.24995902764300507
Validation accuracy: 0.9090833333333334
-------------------------------

我们对更多的 CNN 架构重复相同的过程

接下来,我们使用 Conv 池-Conv 池式架构,每一级的滤波器数量增加一倍。该架构如下所示

转换为 Keras

cnn1 = Sequential([
    Conv2D(32, kernel_size=(3, 3), activation='relu',input_shape=input_shape),
    MaxPooling2D(pool_size=(2, 2),strides=2),
    Conv2D(64, kernel_size=(3, 3), activation='relu'),
    MaxPooling2D(pool_size=(2, 2),strides=2),
    Conv2D(128, kernel_size=(3, 3), activation='relu'),
    MaxPooling2D(pool_size=(2, 2),strides=2),
    Flatten(),
    Dense(64, activation='relu'),
    Dense(10, activation='softmax')
])

使用学习率为 0.001 的 Adam 优化器,我们训练该架构以获得如下所示的精度值

Train loss: 0.18507329044366877
Train accuracy: 0.9320625
-------------------------------
Validation loss: 0.287726696540912
Validation accuracy: 0.8989166666666667
-------------------------------

最后,我们还训练了一个类似 vgg 的模型,其趋势为 conv-conv-普尔-conv-conv-普尔

转换为 keras

cnn1 = Sequential([
    Conv2D(16, kernel_size=(3, 3), activation='relu',padding='same',input_shape=input_shape),
    Conv2D(16, kernel_size=(3, 3), activation='relu',padding='same'),
    MaxPooling2D(pool_size=(2, 2),strides=2),
    Conv2D(32, kernel_size=(3, 3), activation='relu'),
    Conv2D(32, kernel_size=(3, 3), activation='relu'),
    MaxPooling2D(pool_size=(2, 2),strides=2),
    Flatten(),
    Dense(512, activation='relu'),
    Dense(10, activation='softmax')
])

获取精度值

Train loss: 0.05137992699308476
Train accuracy: 0.9810625
-------------------------------
Validation loss: 0.30437974256711703
Validation accuracy: 0.923
-------------------------------

步骤 2-选择您希望进行超参数优化的架构

在所有模型中,找出具有最高验证集分数的模型,将其用作基础架构

在我们的模型中,vgg 类模型在验证集上具有最高的准确性值,因此我们选择如下所示的基础架构

cnn1 = Sequential([
    Conv2D(16, kernel_size=(3, 3), activation='relu',padding='same',input_shape=input_shape),
    Conv2D(16, kernel_size=(3, 3), activation='relu',padding='same'),
    MaxPooling2D(pool_size=(2, 2),strides=2),
    Conv2D(32, kernel_size=(3, 3), activation='relu'),
    Conv2D(32, kernel_size=(3, 3), activation='relu'),
    MaxPooling2D(pool_size=(2, 2),strides=2),
    Flatten(),
    Dense(512, activation='relu'),
    Dense(10, activation='softmax')
])

步骤 3-超参数优化

与验证集损失相比,模型中的训练损失非常低,这告诉我们模型过度拟合。因此,我们需要调整超参数,使我们获得低损耗,但不会过度适应这一点,我们将使用 Hyperas。

使用 Hyperas: CNN

我们现在使用 Hyperas 优化超参数,类似于我们在第一部分中所做的。更多详情请参考第一部分

为了优化,我们需要 3 个代码块

  1. 数据功能

直接从源加载训练和验证数据的函数,或者如果进行了预处理,建议将预处理后的数据存储在 pickle/numpy/hdf5/csv 文件中,并在数据函数中编写代码以从该文件中访问数据。

def data():
    (X_train, y_train), (X_test, y_test) = fashion_mnist.load_data()
    X_train, X_val, y_train, y_val = train_test_split(X_train, y_train, test_size=0.2, random_state=12345)
    X_train = X_train.astype('float32')
    X_val = X_val.astype('float32')
    X_train /= 255
    X_val /= 255
    nb_classes = 10
    Y_train = np_utils.to_categorical(y_train, nb_classes)
    Y_val = np_utils.to_categorical(y_val, nb_classes)
    return X_train, Y_train, X_val, Y_val

调试提示:-如果您遇到任何与数据函数相关的错误,请尝试重新运行代码块,或者在函数的开头再次添加函数或数据函数中使用的包的导入语句

2.模型函数

***def model(X_train, Y_train, X_val, Y_val):***

    model = Sequential()
    ***model_choice = {{choice(['one', 'two'])}}
    if model_choice == 'one':***
        model.add(Conv2D(16, kernel_size=3, activation='relu',padding='same', input_shape=(1,28,28), data_format='channels_first'))
        model.add(Conv2D(16, kernel_size=3, activation='relu',padding='same'))
        model.add(MaxPooling2D(pool_size=2,strides=2))
        model.add(Dropout({{uniform(0, 1)}})) model.add(Conv2D(32, kernel_size=3, activation='relu'))
        model.add(Conv2D(32, kernel_size=3, activation='relu'))
        model.add(BatchNormalization())
        model.add(MaxPooling2D(pool_size=2,strides=2))
        model.add(Dropout({{uniform(0, 1)}}))
    ***elif model_choice == 'two':***
        model.add(Conv2D(32, kernel_size=3, activation='relu',padding='same', input_shape=(1,28,28), data_format='channels_first'))
        model.add(Conv2D(32, kernel_size=3, activation='relu',padding='same'))
        model.add(MaxPooling2D(pool_size=2,strides=2))
        model.add(Dropout({{uniform(0, 1)}})) model.add(Conv2D(64, kernel_size=3, activation='relu'))
        model.add(Conv2D(64, kernel_size=3, activation='relu'))
        model.add(BatchNormalization())
        model.add(MaxPooling2D(pool_size=2,strides=2))
        model.add(Dropout({{uniform(0, 1)}}))

    model.add(Flatten())
    model.add(Dense({{choice([256, 512,1024])}}, activation='relu'))
    model.add(BatchNormalization())
    model.add(Dropout({{uniform(0, 1)}}))
    choiceval = {{choice(['one', 'two'])}}
    if choiceval == 'two':
        model.add(Dense({{choice([256, 512,1024])}}, activation='relu'))
        model.add(BatchNormalization())
        model.add(Dropout({{uniform(0, 1)}}))

    model.add(Dense(10, activation='softmax'))

    adam = keras.optimizers.Adam(lr=0.001)

    model.compile(loss='categorical_crossentropy', metrics=['accuracy'],
                  optimizer=adam) model.fit(X_train, Y_train,
              batch_size=256,
              nb_epoch=15,
              verbose=2,
              validation_data=(X_val, Y_val))
    score, acc = model.evaluate(X_val, Y_val, verbose=0)
    print('Val accuracy:', acc)
    return {'loss': -acc, 'status': STATUS_OK, 'model': model}

注意 Dropout 层的位置,它位于 Max-Pool 层之后。以这种方式完成布局,支持在学习时消除对小特征集的高度依赖的丢失定义。如果放置在 Max-Pool 图层之前,则由 Dropout 移除的值可能不会影响 Max-Pool 图层的输出,因为它会从一组值中选取最大值,因此只有在移除最大值后,才能考虑移除要素依赖关系。如上所述的批量标准化层被放置在激活功能被应用之后。

在模型函数中,我们可以选择需要优化的超参数。在上面的代码块中,我们针对

  1. 密集网络的隐藏单元数和层数(一层或两层)
 model.add(Dense({{choice([256, 512,1024])}}, activation='relu'))
    model.add(BatchNormalization())
    model.add(Dropout({{uniform(0, 1)}}))
    ***choiceval = {{choice(['one', 'two'])}}
    if choiceval == 'two':***
        model.add(Dense({{choice([256, 512,1024])}}, activation='relu'))
        model.add(BatchNormalization())
        model.add(Dropout({{uniform(0, 1)}}))

“choiceval”的值决定了我们使用双层密集网络还是单层

2.辍学值

model.add(Dropout({{uniform(0, 1)}}))

3.架构中的通道数量

***if model_choice == 'one':***
        model.add(**Conv2D(16**, kernel_size=3, activation='relu',padding='same', input_shape=(1,28,28), data_format='channels_first'))
        model.add(**Conv2D(16**, kernel_size=3, activation='relu',padding='same'))
        model.add(MaxPooling2D(pool_size=2,strides=2))
        model.add(Dropout({{uniform(0, 1)}}))
        model.add(**Conv2D(32**, kernel_size=3, activation='relu'))
        model.add(**Conv2D(32**, kernel_size=3, activation='relu'))
        model.add(BatchNormalization())
        model.add(MaxPooling2D(pool_size=2,strides=2))
        model.add(Dropout({{uniform(0, 1)}}))

***elif model_choice == 'two':***
        model.add(**Conv2D(32**, kernel_size=3, activation='relu',padding='same', input_shape=(1,28,28), data_format='channels_first'))
        model.add(**Conv2D(32**, kernel_size=3, activation='relu',padding='same'))
        model.add(MaxPooling2D(pool_size=2,strides=2))
        model.add(Dropout({{uniform(0, 1)}}))
        model.add(**Conv2D(64**, kernel_size=3, activation='relu'))
        model.add(**Conv2D(64**, kernel_size=3, activation='relu'))
        model.add(BatchNormalization())
        model.add(MaxPooling2D(pool_size=2,strides=2))
        model.add(Dropout({{uniform(0, 1)}}))

model _ choice的值决定了我们选择初始层为 conv(16)-conv(16)-Pool-conv(32)-conv(32)-Pool 还是 conv(32)-conv(32)-Pool-Conv(64)-Conv(64)-Pool 的架构。(括号中的数字代表该层中过滤器的数量。)

3.执行和解释

我们使用上述数据和模型函数开始优化

X_train, Y_train, X_val, Y_val = data()best_run, best_model = optim.minimize(model=model,
                                      data=data,
                                      algo=tpe.suggest,
                                      max_evals=30,
                                      trials=Trials(),
                                      notebook_name='Fashion_MNIST')

在执行上面的代码片段时,我们在输出中得到下面的框架。我们用这个来匹配调整的超参数值。

model = Sequential()
model_choice = space[***'model_choice'***]
if model_choice == 'one'**:**
   model.add(Conv2D(16, kernel_size=3, activation='relu',padding='same', input_shape=(1,28,28), data_format='channels_first'))
   model.add(Conv2D(16, kernel_size=3, activation='relu',padding='same'))
   model.add(MaxPooling2D(pool_size=2,strides=2))
   model.add(Dropout(space[***'Dropout'***]))
   model.add(Conv2D(32, kernel_size=3, activation='relu'))
   model.add(Conv2D(32, kernel_size=3, activation='relu'))
   model.add(BatchNormalization())
   model.add(MaxPooling2D(pool_size=2,strides=2))
   model.add(Dropout(space[***'Dropout_1'***]))
elif model_choice == 'two'**:**
   model.add(Conv2D(32, kernel_size=3, activation='relu',padding='same', input_shape=(1,28,28), data_format='channels_first'))
   model.add(Conv2D(32, kernel_size=3, activation='relu',padding='same'))
   model.add(MaxPooling2D(pool_size=2,strides=2))
   model.add(Dropout(space[***'Dropout_2'***]))
   model.add(Conv2D(64, kernel_size=3, activation='relu'))
   model.add(Conv2D(64, kernel_size=3, activation='relu'))
   model.add(BatchNormalization())
   model.add(MaxPooling2D(pool_size=2,strides=2))
   model.add(Dropout(space[**'Dropout_3'**]))

 model.add(Flatten())
 model.add(Dense(space[***'Dense'***], activation='relu'))
 model.add(BatchNormalization())
 model.add(Dropout(space[***'Dropout_4'***]))
 choiceval = space[**'model_choice_1'**]
 if choiceval == 'two':
   model.add(Dense(space[***'Dense_1'***], activation='relu'))
   model.add(BatchNormalization())
   model.add(Dropout(space[***'Dropout_5'***]))
   model.add(Dense(10, activation='softmax'))
adam = keras.optimizers.Adam(lr=0.001)

现在我们需要从 print(best_run)输出中的参数索引中获取我们的值

{'Dense': 1, 'Dense_1': 2, 'Dropout': 0.2799579955710103, 'Dropout_1': 0.8593089514091055, 'Dropout_2': 0.17434082481320767, 'Dropout_3': 0.2839296185815494, 'Dropout_4': 0.7087321230411557, 'Dropout_5': 0.3273210014856124, 'model_choice': 1, 'model_choice_1': 0}

通过将价值与它们在框架中的位置相匹配来解释上述内容,我们得到了最佳的架构

cnn1 = Sequential([
    Conv2D(32, kernel_size=(3, 3), activation='relu',padding='same',input_shape=input_shape),
    Conv2D(32, kernel_size=(3, 3), activation='relu',padding='same'),
    MaxPooling2D(pool_size=(2, 2),strides=2),
    Dropout(0.2),
    Conv2D(64, kernel_size=(3, 3), activation='relu'),
    Conv2D(64, kernel_size=(3, 3), activation='relu'),
    BatchNormalization(),
    MaxPooling2D(pool_size=(2, 2),strides=2),
    Dropout(0.3),
    Flatten(),
    Dense(256, activation='relu'),
    BatchNormalization(),
    Dropout(0.7),
    Dense(10, activation='softmax')
])

上述架构的精度和损耗值为

Train loss: 0.14321659112690638
Train accuracy: 0.9463333333333334
-------------------------------
Validation loss: 0.17808779059847196
Validation accuracy: 0.93525
-------------------------------
Test loss: 0.20868439328074456
Test accuracy: 0.9227

因此,我们最终在测试集上获得了 92.27%的准确率,这优于我们优化的密集网络架构,后者在测试集上获得了 88%的准确率。但最重要的是,我们的模型不是过拟合的,因此将很好地推广到看不见的点,不像其他架构可以实现更高的精度,但对训练集过拟合。

我们可以通过使用数据增强技术来进一步提高这种准确性,但我将把它留给您进行实验。

希望这篇文章对您有所帮助,并且您通过这篇文章学会了如何构建一个高效的 CNN 架构。

更多信息请查看 https://neptune.ai/blog/optuna-vs-hyperopt 的博客文章

感谢您的阅读!

Connect with the Raven team on Telegram

机器学习和数据科学决策树指南

原文:https://towardsdatascience.com/a-guide-to-decision-trees-for-machine-learning-and-data-science-fe2607241956?source=collection_archive---------0-----------------------

想获得灵感?快来加入我的 超级行情快讯 。😎

决策树是一类非常强大的机器学习模型,能够在许多任务中实现高准确性,同时具有高度的可解释性。决策树在 ML 模型领域中的特殊之处在于它们清晰的信息表示。决策树通过训练学习到的“知识”被直接公式化为层次结构。这种结构以一种即使非专家也能容易理解的方式保存和显示知识。

现实生活中的决策树

你可能在自己的生活中使用过决策树来做决定。以关于你这个周末应该做什么活动的决定为例。这可能取决于你是否想和你的朋友出去或者独自度过周末;在这两种情况下,你的决定也取决于天气。如果天气晴朗,你的朋友有空,你可能想踢足球。如果最后下雨,你就去看电影。如果你的朋友根本不出现,那么无论天气如何,你都喜欢玩电子游戏!

这是一个现实生活中决策树的明显例子。我们已经建立了一个树来模拟一组顺序的、 层次的 决策,这些决策最终导致一些最终结果。请注意,我们还选择了相当“高层次”的决策,以保持树小。例如,如果我们为天气设置了许多可能的选项,比如 25 度晴天、25 度雨天、26 度晴天、26 度雨天、27 度晴天…等等,我们的树会很大!确切的温度真的不太相关,我们只是想知道在室外是否可以。

这个概念对于机器学习中的决策树也是一样的。我们希望构建一个包含一组分层决策的树,这些决策最终会给我们一个最终结果,即我们的分类或回归预测。将选择决策,使得树尽可能小,同时以高分类/回归准确度为目标。

机器学习中的决策树

决策树模型是使用 2 个步骤创建的:归纳和修剪。归纳是我们实际构建树的地方,即根据我们的数据设置所有的层次决策界限。由于训练决策树的性质,它们很容易过度拟合。修剪是从决策树中删除不必要的结构的过程,有效地降低了复杂性,以防止过度拟合,并使其更容易解释。

感应

从高层次来看,决策树归纳通过 4 个主要步骤来构建树:

  1. 从训练数据集开始,它应该有一些特征变量和分类或回归输出。
  2. 确定数据集中分割数据的“最佳特征”;稍后将详细介绍我们如何定义“最佳特性”
  3. 将数据分割成包含此最佳特征的可能值的子集。这种分割基本上定义了树上的一个节点,即每个节点都是基于我们数据的某个特征的分割点。
  4. 使用步骤 3 中创建的数据子集递归生成新的树节点。我们不断分裂,直到我们达到某一点,在这一点上,我们通过某种措施优化了最大精度,同时最小化了分裂/节点的数量。

第 1 步很简单,只需获取您的数据集!

对于步骤 2,通常使用贪婪算法来选择使用哪个特征和具体的分割,以最小化成本函数。如果我们想一想,在构建决策树时执行分裂相当于划分特征空间。我们将反复尝试不同的拆分点,然后最终选择成本最低的一个。当然,我们可以做一些聪明的事情,比如只在数据集中的值范围内进行拆分。这将使我们避免浪费计算来测试非常差的分割点。

对于回归树,我们可以使用简单的平方误差作为成本函数:

其中 Y 是我们的基本事实,Y-hat 是我们的预测值;我们对数据集中的所有样本求和,以获得总误差。对于分类,我们使用基尼指数函数:

其中 pk 是特定预测节点中类别 k 的训练实例的比例。一个节点应该理想情况下有一个零错误值,这意味着每次分割都 100%输出一个类。这正是我们想要的,因为这样我们就知道,一旦我们到达那个特定的决策节点,无论我们是在决策边界的一边还是另一边,我们的输出到底是什么。

在我们的数据集中每次分割一个类的概念被称为信息增益。看看下面的例子。

如果我们选择一个拆分,其中每个输出都有一个取决于输入数据的混合类,那么我们真的没有得到任何信息;我们不知道某个特定的节点(即特征)是否对我们的数据分类有任何影响!另一方面,如果我们的分割对于每个输出有很高的百分比,那么我们获得了信息,即在特定的特征变量上以特定的方式分割给了我们特定的输出!

现在我们当然可以继续分裂,分裂,分裂,直到我们的树有成千上万的分支…..但是这真的不是一个好主意!我们的决策树会很大,很慢,并且过度适应我们的训练数据集。因此,我们将设置一些预定义的停止标准来停止树的构建。

最常见的停止方法是对分配给每个叶节点的训练样本数量使用最小计数。如果计数小于某个最小值,则分割不被接受,并且该节点被作为最终叶节点。如果我们所有的叶子节点都变成最终节点,训练就停止了。较小的最小计数将为您提供更精细的分割和潜在的更多信息,但也容易使您的训练数据过度拟合。分钟数太大,你可能会过早停下来。因此,最小值通常是基于数据集设置的,取决于每个类中预期有多少个示例。

修剪

由于训练决策树的性质,它们很容易过度拟合。为每个节点的最小实例数设置正确的值是一项挑战。大多数时候,我们可能只是进行一个安全的打赌,并使最小值非常小,导致有许多分裂和一个非常大,复杂的树。关键是,这些分割中的许多将是多余的,对增加我们模型的准确性是不必要的。

树修剪是一种利用分裂冗余来移除的技术,即修剪我们树中不必要的分裂。从高层次来看,修剪将树的一部分从严格和僵化的决策边界压缩到更平滑和更一般化的边界,有效地降低了树的复杂性。决策树的复杂度被定义为树中分裂的数量。

一种简单而高效的剪枝方法是遍历树中的每个节点,并评估删除它对成本函数的影响。如果变化不大,那就修剪掉!

Scikit Learn 中的一个示例

用于分类和回归的决策树在 Scikit Learn 中非常容易使用,内置了一个类!我们将首先加载我们的数据集,并初始化我们的决策树进行分类。跑步训练是一个简单的小程序!

Scikit Learn 还允许我们使用 graphviz 库可视化我们的树。它附带了一些选项,将有助于可视化模型学习到的决策节点和分割,这对理解它是如何工作的非常有用!下面我们将根据特性名称给节点着色,并显示每个节点的类别和特性信息。

您也可以在 Scikit Learn 中为您的决策树模型设置几个参数。以下是一些更有趣的方法,可以尝试使用,并获得更好的结果:

  • max_depth: 树的最大深度,在这里我们将停止分割节点。这类似于控制深度神经网络中的最大层数。较低会使你的模型更快,但不准确;更高可以给你准确性,但风险过度拟合,可能会很慢。
  • min_samples_split: 分割一个节点所需的最小样本数。我们在上面讨论了决策树的这一方面,以及将其设置为更高的值将如何有助于减轻过度拟合。
  • max_features: 寻找最佳分割时要考虑的特征数量。更高意味着潜在的更好的结果,代价是训练时间更长。
  • min _ infinity _ split:树生长提前停止的阈值。如果节点的杂质高于阈值,则节点将分裂。这可用于权衡防止过度拟合(高值,小树)与高精度(低值,大树)。
  • 预排序:是否对数据进行预排序,以加快拟合中最佳分割的发现。如果我们事先对每个特征的数据进行分类,我们的训练算法将更容易找到好的值进行分割。

实际应用决策树的技巧

这里有一些决策树的优点和缺点,可以帮助您决定它是否是您的问题的正确模型,以及如何有效应用它们的一些提示:

赞成的意见

  • 容易理解和解释的。在每一个节点上,我们都能够看到确切地说我们的模型正在做出什么决定。在实践中,我们将能够充分了解我们的精度和误差来自哪里,模型适合什么类型的数据,以及输出如何受要素值的影响。Scikit learn 的可视化工具是可视化和理解决策树的绝佳选择。
  • 需要很少的数据准备。许多 ML 模型可能需要大量的数据预处理,例如标准化,并且可能需要复杂的正则化方案。另一方面,在调整了一些参数之后,决策树在开箱即用的情况下工作得相当好。
  • 使用树进行推理的成本是用于训练树的数据点数量的对数。这是一个巨大的优势,因为这意味着拥有更多的数据并不一定会大大降低我们的推理速度。

缺点

  • 由于决策树训练的性质,过度拟合在决策树中很常见。人们经常建议进行某种类型的降维,比如 PCA ,这样树就不必学习这么多特征的分裂
  • 出于与过度拟合类似的原因,决策树也容易偏向于在数据集中占多数的类。做一些种类的类平衡总是一个好主意,比如类权重、采样或者专门的损失函数。

喜欢学习?

在 twitter 上关注我,我会在这里发布所有最新最棒的人工智能、技术和科学!也在 LinkedIn 上与我联系!

熊猫和 Matplotlib 数据探索指南

原文:https://towardsdatascience.com/a-guide-to-pandas-and-matplotlib-for-data-exploration-56fad95f951c?source=collection_archive---------0-----------------------

Photo by Clint McKoy on Unsplash

在最近使用 Pandas 和 Matplotlib 为我正在写的这篇文章制作图表/分析之后。我决定将这本实用指南放在一起,希望它足以让您使用 Pandas 和 MPL 开始并运行自己的数据探索!

本文分为以下几个部分:

基本要求

  • 从 CSV 读取数据
  • 格式化、清理和过滤数据框
  • 分组依据和合并

可视化您的数据

  • 绘图功能基础
  • Seaborn 小提琴和 lm-plots
  • 配对图和热图

身材美学

  • 多轴绘图
  • 让你的图表看起来不那么科学

基本要求

读取 CSV/Matplotlib 和 Pandas 所需的导入

import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
%matplotlib inlinecar_data = pd.read_csv('inbox/CarData-E-class-Tue Jul 03 2018.csv')

Inline 表示将图形显示为单元格输出, read_csv 返回一个数据帧,文件路径相对于您笔记本的文件路径。

格式化、清理和过滤数据帧

通常在处理大量特性时,使用 columns 属性和 head(nRows) 函数查看第一行或所有列的名称会更好。但是,如果我们对分类的值的类型感兴趣,例如模型线,我们可以使用方括号语法访问该列,并使用。unique() 检查选项。

print(car_data.columns)
car_data.head(2)

car_data['modelLine'].unique()

很明显,在“特殊设备”的不同变体下输入了同一型号系列的多个版本,因此我们将使用正则表达式将任何包含 se 的内容替换为特殊设备。同样,有些列带有 Nans(不是数字),所以我们将只删除这些带有dropna(subset =[' model line '])的列。

car_data = car_data.dropna(subset=['modelLine'])
car_data['modelLine'] = car_data['modelLine'].replace(to_replace={'.*SE.*': 'Standard equipment'}, regex=True)

我们还可以通过将模型线的行与一些布尔问题进行比较来过滤掉不需要的值,如“未定义”,这将返回一个与 DataFrame 行具有相同维数的布尔数组,可以再次使用方括号语法进行过滤。

car_data = car_data[(car_data['modelLine'] != 'undefined')]car_data['modelLine'].unique()

This is looking much better!

请注意,pandas 从不改变任何现有数据,因此当我们执行任何改变/过滤时,我们必须手动覆盖我们的旧数据。虽然这看起来有些多余,但这是减少代码中不必要的副作用和错误的非常有效的方法。

接下来,我们还需要更改 firstRegistration 字段(通常应该将其视为 python 日期格式),但是为了方便在以后的文章中对数据执行回归,我们将把它视为数值字段。

考虑到该数据与汽车注册相关,年份确实是我们需要保留的重要组成部分。因此,将它视为数值字段意味着我们可以应用数值舍入、乘法/除法来创建如下所示的注册年份特征列。

car_data['firstRegistration'].head(5)car_data[‘firstRegistrationYear’] = round((car_data[‘firstRegistration’] / 10000),0)
car_data[‘firstRegistrationYear’] .head(5)

Looks like the output we were looking for.

使用分组和合并

分组依据可用于根据数据集中的特定要素构建行组,例如“模型线”分类列。然后,我们可以对各个组执行均值、最小值、最大值、标准差等操作,以帮助描述样本数据。

group_by_modelLine = car_data.groupby(by=['modelLine'])
car_data_avg = group_by_modelLine.mean()
car_data_count = group_by_modelLine.count()

Averages Data

Count Data: Note that this is simply a count of the records for each model Line

如您所见,已经为每条模型线计算了每个数字特征的平均值。Group by 非常通用,也接受 lambda 函数用于更复杂的行/组标记。

接下来,我们将组装一个仅包含相关特征的数据框架,以绘制可用性(或车辆数量)和每辆车平均设备的图表。这个数据框架可以通过传入一个键字典来创建,这些键表示来自现有数据的单列或系列的列和值。这在这里是可行的,因为两个数据框具有相同的行数。或者,我们可以通过索引(模型线)合并两个数据框,并适当地重命名重复列的后缀。

然后,我们将把这两个变量按设备和可用性分类绘制成一个水平条形图。

# Since all the columns in car_data_count are the same, we will use just the first column as the rest yield the same result. iloc allows us to take all the rows and the zeroth column.car_data_count_series = car_data_count.iloc[:,0]features_of_interest = pd.DataFrame({'equipment': car_data_avg['equipment'], 'availability': car_data_count_series})alternative_method = car_data_avg.merge(car_data_count, left_index=True, right_index=True, suffixes=['_avg','_count'])alternative_method[['equipment_avg', 'firstRegistration_count']].sort_values(by=['equipment_avg', 'firstRegistration_count'], ascending=True).plot(kind='barh')

可视化您的数据

熊猫情节功能

熊猫有一个内置的。plot()函数作为 DataFrame 类的一部分。它有几个关键参数:

种类—‘条形’,‘barh’,‘馅饼’,‘散点’,‘kde’等,可以在文档中找到。
颜色 —接受与每个数据系列/列顺序对应的十六进制码数组。
line style—‘实线’,‘虚线’,‘虚线’(仅适用于线图)
xlim,ylim —指定将要绘制图形的元组(下限,上限)
legend —显示或隐藏 legend
标签的布尔值 —对应于数据帧中列数的列表,此处可为 legend
提供描述性名称

这些很容易使用,我们将使用。plot()在文章的后面。

eaborn lmplots

Seaborn 构建在 matplotlib 之上,以提供更丰富的开箱即用环境。它包括一个简洁的 lmplot 绘图功能,用于快速探索多个变量。使用我们的汽车数据示例,我们希望了解汽车的装备套件和销售价格之间的关联。显然,我们也希望这些数据按模型线进行分段,以便进行同类比较。

import seaborn as sns

传入设备和价格的列标签(x 和 y 轴),后跟实际的数据帧源。使用 col 关键字为每条模型线生成一个单独的地块,并设置 col_wrap 2 以生成一个漂亮的网格。

filtered_class = car_data[car_data['modelLine'] != 'AVANTGARDE']sns.lmplot("equipment", "price", data=filtered_class, hue="gears", fit_reg=False, col='modelLine', col_wrap=2)

正如你所看到的,在图表上添加一个颜色来表示齿轮的数量是非常有意义的,因为这些类型的车往往没有更好的装备,但是更贵。如您所见,我们可以用 3 行代码对数据集进行重要的探索。

Seaborn 小提琴情节

这些图非常适合处理大型连续数据集,同样可以通过索引进行分割。使用我们的汽车数据集,我们可以更好地了解二手车的价格分布。由于车龄会显著影响价格,我们将把第一个登记年份作为 x 轴变量,价格作为 y 轴变量,然后我们可以设置色调来区分不同的车型变量。

from matplotlib.ticker import AutoMinorLocatorfig = plt.figure(figsize=(18,6))LOOKBACK_YEARS = 3
REGISTRATION_YEAR = 2017filtered_years = car_data[car_data['firstRegistrationYear'] > REGISTRATION_YEAR - LOOKBACK_YEARS]ax1 = sns.violinplot('firstRegistrationYear', "price", data=filtered_years, hue='modelLine')ax1.minorticks_on()
ax1.xaxis.set_minor_locator(AutoMinorLocator(2))
ax1.grid(which='minor', axis='x', linewidth=1)

请注意,violin plot 函数返回显示绘图的轴。这允许我们编辑轴的属性。在本例中,我们设置了次要刻度,并使用 AutoMinorLocator 在每个主要间隔之间放置 1 个次要刻度。然后,我用线宽 1 使小网格可见。这是一个巧妙的方法,在每个注册年度都加上一个框。

配对图和关联热图

在具有少量要素(10-15 个)的数据集中,Seaborn Pairplots 可以快速实现对变量之间任何关系的可视化检查。沿着左对角线的图形表示每个特征的分布,而在非对角线上的图形显示变量之间的关系。

sns.pairplot(car_data.loc[:,car_data.dtypes == 'float64'])

(This is only a section, I couldn’t fit all the variables in, but you get the concept.)

同样,我们可以利用 pandas Corr()找到矩阵中每个变量之间的相关性,并使用 Seaborn 的热图函数绘制,指定标签和热图颜色范围。

corr = car_data.loc[:,car_data.dtypes == 'float64'].corr()sns.heatmap(corr, xticklabels=corr.columns, yticklabels=corr.columns, cmap=sns.diverging_palette(220, 10, as_cmap=True))

这两个工具结合起来对于快速识别模型的重要特征非常有用。例如,使用热图,我们可以从顶行看到,档位数量和首次注册与价格正相关,而与此同时,milage 可能与价格负相关。到目前为止,这是一个完美的分析工具,但在基础层面上很有用。

图形美学

多轴绘图

以下是我之前关于中国房地产泡沫的文章中的一些数据。我想显示所有城市的建设数据,然后在一个图中按城市层级提供后续细分。

让我们来分解如何创建这样一个数字:

首先,我们定义图形的大小,以提供足够的绘图空间。当用多轴绘图时,我们定义一个网格,轴可以放置在网格上。然后,我们使用 subplot2grid 函数返回位于所需位置(从左上角指定)的轴,该轴具有正确的行/列跨度。

fig = plt.figure(figsize = (15,12))
grid_size = (3,2)
hosts_to_fmt = []# Place A Title On The Figurefig.text(x=0.8, y=0.95, s='Sources: China National Bureau of Statistics',fontproperties=subtitle_font, horizontalalignment='left',color='#524939')# Overlay multiple plots onto the same axis, which spans 1 entire column of the figurelarge_left_ax = plt.subplot2grid(grid_size, (0,0), colspan=1, rowspan=3)

然后,我们可以通过指定绘图函数的 ax 属性,在这个轴上绘图。请注意,尽管绘制到特定的轴上,但使用 secondary_y 参数意味着将创建一个新的轴实例。这对于以后存储格式非常重要。

# Aggregating to series into single data frame for ease of plottingconstruction_statistics = pd.DataFrame({
    'Constructed Floorspace (sq.m, City Avg)':
     china_constructed_units_total,
    'Purchased Units (sq.m, City Avg)':     
     china_under_construction_units_total,
})construction_statistics.plot(ax=large_left_ax,
    legend=True, color=['b', 'r'], title='All Tiers')# Second graph overlayed on the secondary y axislarge_left_ax_secondary = china_years_to_construct_existing_pipeline.plot(
    ax=large_left_ax, label='Years of Backlog', linestyle='dotted',
    legend=True, secondary_y=True, color='g')# Adds the axis for formatting laterhosts_to_fmt.extend([large_left_ax, large_left_ax_secondary])

为了生成城市层级的细分数据,我们再次使用了 subplot2grid,但这一次改变了每个循环的指数,这样三个层级的图表一个在另一个之下。

# For each City Tier overlay a series of graphs on an axis on the right hand column
# Its row position determined by its indexfor index, tier in enumerate(draw_tiers[0:3]):
    tier_axis = plt.subplot2grid(grid_size, (index,1))

    china_constructed_units_tiered[tier].plot(ax=tier_axis,     
     title=tier, color='b', legend=False)

    ax1 = china_under_construction_units_tiered[tier].plot(
     ax=tier_axis,linestyle='dashed', label='Purchased Units 
     (sq.m,City Avg)', title=tier, legend=True, color='r')  

    ax2 =china_property_price_sqmetre_cities_tiered[tier].plot(
     ax=tier_axis, linestyle='dotted', label='Yuan / sq.m', 
     secondary_y=True, legend=True, color='black')

    ax2.set_ylim(0,30000)hosts_to_fmt.extend([ax1,ax2])

好了,现在我们已经生成了正确的布局和绘图数据:

让你的图表看起来不那么科学

在上图的例子中,我选择了类似 ft.com 的造型。首先,我们需要通过 Matplotlib 字体管理器导入字体,并为每个类别创建一个字体属性对象。

import matplotlib.font_manager as fm# Font Importsheading_font = fm.FontProperties(fname='/Users/hugo/Desktop/Playfair_Display/PlayfairDisplay-Regular.ttf', size=22)subtitle_font = fm.FontProperties(
fname='/Users/hugo/Library/Fonts/Roboto-Regular.ttf', size=12)# Color Themescolor_bg = '#FEF1E5'
lighter_highlight = '#FAE6E1'
darker_highlight = '#FBEADC'

接下来,我们将定义一个函数,它将:

  • 设置图形背景(使用 set_facecolor)
  • 使用指定的标题字体将标题应用于插图。
  • 调用紧凑布局功能,更紧凑地利用绘图空间。

接下来,我们将遍历图中的每个轴,并调用一个函数来:

  • 禁用除底部脊椎(轴边界)之外的所有脊椎
  • 将轴的背景颜色设置得稍暗一些。
  • 如果图例存在,禁用图例周围的白色框。
  • 将每个轴的标题设置为使用副标题字体。

最后,我们只需要调用我们创建的格式化函数,并传入我们之前收集的图形和轴。

结论

感谢您阅读本教程,希望这有助于您开始使用 Pandas 和 Matplotlib。

一位 HCI 研究员对 AAAI 2018 大会的总结!

原文:https://towardsdatascience.com/a-hci-researchers-summary-on-aaai-2018-conference-6496d6328aa4?source=collection_archive---------8-----------------------

AAAI18 的演讲摘要,涵盖了计算机视觉、机器学习/深度学习(灾难性遗忘)、学习表示、知识图和应用人工智能等主题。

这篇帖子包含我在刚刚结束的人工智能大会( AAAI 2018,路易斯安那州新奥尔良)上参加的会议的笔记。演讲的选择是基于我对人机交互和应用人工智能的兴趣。这些包括人工智能的人类方面,视觉,机器学习/深度学习(灾难性遗忘),学习表示,知识图和一般的应用人工智能。欢迎反馈,指正(错别字!)和讨论——请联系( @vykthur )) 。对于那些对 AAAI 有兴趣的人来说, David Abel 也写了一份 AAAI 2018 的详细摘要,涵盖了一些我没有参加的会议。
TLDR——我的一些笔记可能缺乏细节。

2 月 3 日星期六

教程—从网络语料库构建知识图—马扬克·凯杰里瓦尔、克雷格·克诺布洛克、佩德罗·策克利[ 幻灯片

本教程概述了使用从网站上搜集的数据创建知识图表的过程,由南加州大学信息科学研究所的研究人员演示。

动机

  • 为什么是领域特定知识图(DSKG)?
    人类行为表明我们已经执行了特定领域搜索(DSS。例如,人们去亚马逊上的部分搜索商品,或者去 YouTube 上搜索视频,而不是执行一般的谷歌搜索。
  • DSKGs 在回答特定领域的问题方面做得更好。
  • DSS >关键字搜索;它编纂了许多文档中的领域知识。
  • 人们对国防高级研究计划局赞助的项目越来越感兴趣

知识图构建

  • 知识图是一组三元组( H ead, R elationship, T ail)。巴拉克·奥巴马出生在夏威夷。
  • 从网站抓取的数据生成知识图可能会很复杂。解决这一问题的手动方法是不可扩展的,因此需要自动化这一过程的系统。从表格图形、地块图像甚至 excel 文件中提取数据和实体可能会面临特定的挑战。
  • 大多数自动化方法包括语法归纳方法,其中系统试图学习爬行数据中的底层结构。这些算法的例子包括 RoadRunner、Disjoint Regex 等。

知识图构建的示例工具
本教程的最后一部分展示了作者在实验室开发的一些知识图生成工具——Karma 和 DIG 。他们还展示了一个有趣的用例,其中他们构建了一个知识图表来帮助追踪人口贩运。

我的想法:这个教程有助于理解抓取网站的流程。它比我预期的有更多的手动方面(提取的实体需要手动标记,结果可能非常嘈杂)。我还想了解更多关于问答的知识,这在这次演讲中并没有涉及太多。

2 月 4 日星期日

[总统演讲]人类感知人工智能系统的挑战[ 视频,幻灯片

该演讲由 AAAI 主席(Subbarao Kambhampati)主讲,提供了一些关于人类感知人工智能(HAAI)的观点——动机、研究挑战和开放问题。

动机

  • 今天的艾对人类有一种奇怪的矛盾心理。
  • 但是人工智能可以应用的许多领域都需要人类。智能辅导系统、社交机器人、助手(个人、医疗)以及人机团队。
  • 我们应该追求人类感知的人工智能,因为它拓宽了人工智能的范围和前景。

研究挑战和问题

  • 人机合作需要对人类建模:让机器人/人工智能代理维护与其交互的人类的精确模型是一个挑战。该模型的准确性对于创建对机器人和人类都优化的计划是必要的。对人-人团队的研究可以为这个问题的解决方案提供信息。
  • 机器人/人工智能代理可以通过牺牲它们的最佳模型来满足人类或者提供/请求有助于解决差异的信息(可解释性)来从这些不准确性中恢复。[更多参考见幻灯片。来自代理的可解释性是产生信任的必要条件
  • 伦理挑战——如果/当人工智能代理能够正确地模拟人类,它可能会给他们“说谎”的能力。

我的想法:我发现这个演讲很有趣,因为它有助于提供人工智能规划领域正在进行的工作的概述,以改善人与机器人的互动——努力模拟人类,制定可解释的计划和权衡的观点。

【技术谈】多连体嵌入学习的极低分辨率活动识别。【 论文

Example videos of the HMDB and DogCentric datasets. The upper rows show the original HR videos and the lower rows show the 16x12 extreme low resolution videos used in the paper experiments. The first two videos are from HMDB and the other two videos are from DogCentric. Source

这个演讲(由印第安纳大学的 Michael S. Ryo 主持)介绍了一种神经网络方法来识别低分辨率图像中的活动——低至 16 * 12 像素!!

动机

  • 低分辨率处理帮助我们理解远处的活动(远场识别)。例如,视频片段中的背景中正在发生什么(人行走、挥手等)。
  • 低分辨率识别提供了隐私(脸很小,变得无法识别)节省电池的好处。

贡献

  • 这项工作贡献了一个新的双流多连体卷积神经网络。在低分辨率 (LR)视频中,源自完全相同场景的两幅图像通常具有完全不同的像素值,这取决于它们的 LR 变换。
  • 该方法学习将具有相同内容的 LR 视频映射到相同位置的共享嵌入空间,而不管它们的变换。
  • 当在 LR 视频上进行活动识别时,这种映射被用于改进推断。

我的想法:这篇文章提供了一些关于处理低分辨率图像的有趣见解——常规 CNN 需要 200 * 200 的图像!!他们讨论了从多个 LR 到 HR 图像变换学习映射的技术,并利用该知识来提高推理的准确性。我发现这很有趣,因为像这样的方法可以通知在边缘执行人工智能的努力(允许我们使用更小的图像,提高推理速度和电池寿命)。报告的准确性不是很高(37.70%),他们在运行 Tensorflow 的 Jetson TX2 上实现了 50fps。

【技术演讲】深度神经网络领域扩展的少遗忘学习[ 论文

Source

这篇论文提供了一种方法来处理神经网络中灾难性遗忘的扩展(他们称之为域扩展)。

动机。
域扩展问题,即创建一个在旧域和新域上都工作良好的网络的问题,即使是在仅使用来自新域的数据而不访问来自旧域的数据的监督方式下对其进行训练之后。他们指出了域名扩张面临的两大挑战。

  • 首先,即使学习了新域数据而没有看到旧域的数据,旧域上的网络性能也不应降低。
  • 第二,DNN 应该能够很好地工作,而不需要事先知道输入数据来自哪个域。

灾难性遗忘的方法

  • 微调 Softmax :冻结下层并微调最终的 Softmax 分类器层。该方法将下层作为特征提取器,更新线性分类器以适应新的领域数据。换句话说,特征提取器在新旧领域之间共享,并且该方法似乎保留了旧的领域信息。
  • 权重约束方法:在学习新数据时,使用 l2 正则化获得新旧网络之间相似的权重参数。
  • 论文提出的模型:使用旧网络的训练权值作为新网络的初始权值,同时最小化两个损失函数。

我的想法:我希望了解更多关于灾难性遗忘的知识,这个演讲(以及相关参考资料)对于了解这个主题的研究状况非常有用。我注意到,这里的评估(以及大多数其他论文中的评估)通常使用小型数据集(例如 CIFAR 10)来评估他们的解决方案在新领域中经过培训后的表现。尚不清楚这是否能很好地适应更大的数据集。灾难性遗忘仍然是一个重要的、公开的和 T21 难题。

【用于人体姿态估计的具有注意力调制特征融合的初始网络的级联初始技术】论文

Results of our the paper on the MPII datasets. It is shown that the method is able to handle non-standard poses and resolve ambiguities when body parts are occluded. Source.

动机

  • 姿势估计——需要对身体部位的关键点进行精确定位,以分析图像和视频中的行为。它需要多样化的特性:高层次的上下文依赖和低层次的关节细化。
  • 定位人体关节很难。由于人体的变形、外观的变化和遮挡,存在一些挑战。
  • 现有方法在保留低级特征、自适应地调整不同级别特征的重要性以及模拟人类感知过程方面存在局限性。

贡献。

本文提出了三个新的技术,逐步有效地利用不同层次的特征,以改善人体姿态估计。

  • 首先,《盗梦空间》( IOI)模块的设计是为了强调低级功能
  • 其次,提出了一种注意机制来根据上下文调整个体层次的重要性。
  • 第三,提出了一个级联网络来顺序定位关节,以加强从独立部分(如头部和躯干)的关节到远程关节(如手腕或脚踝)的消息传递

我的想法:本文提供了关于调整网络以解决特定问题的方法的见解(在这种情况下,对由遮挡和变形引起的姿态估计误差具有鲁棒性)。

【技术讲座】人员再识别的图形对应传递纸

(a) shows misalignment among local patches caused by viewpoint changes. The proposed GCT model can capture the correct semantic matching among patches using patchwise graph matching, as shown in image (b). Source

动机

  • 人物再识别(ReID)是将不同的非重叠摄像机视图中具有相同身份的图像关联起来。视频分析、监控等领域的大量应用。
  • ReID 很难,因为不同摄像机视图中的外观变化很大,身体遮挡严重,探针组中的许多其他图像相似。空间未对准,其中补丁在不同的视图/帧中具有不同的外观。

贡献

提出了一种用于身份识别的图对应转移(GCT)方法。

  • 与现有方法不同,GCT 模型将人物再识别归结为一个 离线 图匹配和 在线 对应转移问题。
  • 在训练期间,GCT 模型旨在离线学习,即通过逐块图匹配从具有各种姿态对配置的正训练对中学习一组对应模板。
  • 在测试过程中,对于每一对测试样本,他们选择几个具有最相似姿态对配置的训练对作为参考,并将这些参考的对应关系传递给测试对用于特征距离计算。匹配分数是通过合计来自不同参考的距离而得到的。对于每个探测图像,具有最高匹配分数的图库图像是重新识别结果。与现有算法相比,GCT 可以处理由于视角和人类姿态的巨大变化引起的空间错位,这是由于逐片图形匹配的好处。

我的想法:在任务中利用离线知识的有趣方式。他们为具有特定姿态对的图像学习正确的面片对应,并在测试时在具有相似姿态对配置的图像中重用该知识!

【技术讲座】端到端联合视频去雾(EVD)和检测[ 论文

Comparisons of detection results on real-world hazy video sample frames. Note that for the third, fourth and fifth columns, the results are visualized on top of the (intermediate) dehazing results. Source

微软中国研究院的研究人员在创建一个端到端模型方面做了一些工作,该模型既可以去雾,也可以进行下游操作,如对象检测。

动机

  • 由于在户外视频监控、交通监控和自动驾驶等领域具有深远的应用价值,去除野外获取的视觉数据中的雾霾一直吸引着人们极大的研究兴趣。
  • CNN 已经应用于具有 SOTA 结果的去雾图像(去雾网,AOD 网)。
  • 传统统计方法或 CNN 在探索视频去雾方面的努力有限

贡献

  • 端到端模型(李等 2017aWang et al. 2016),直接从模糊输入中回归出清晰图像,无需任何中间步骤。该模型优于多级流水线
  • 通过明确考虑在恢复当前帧时如何嵌入相邻视频帧之间的时间一致性,接受视频设置。
  • 作者表明,用于视频去雾和视频对象检测的联合优化的流水线比在已经独立去雾的视频流上运行检测的性能更好。除了去雾部分,检测部分还必须考虑时间相干性,以减少闪烁检测结果。

我的想法:研究人员确定了一种联合优化管道,有助于提高模糊图像的对象检测精度。这项工作有助于阐明联合优化和端到端模型的效用。

2 月 5 日星期一

【特邀演讲】交互式机器学习【查尔斯·伊斯贝尔和迈克尔·利特曼】

这次演讲由佐治亚理工学院的查尔斯·伊斯贝尔和布朗大学的迈克尔·利特曼主持。这是一个有趣的,引人入胜的(有时很机智)和互动的演示。它以 Charles 关于强化学习(RL)的讨论开始,用户在 RL 中扮演的角色,然后是生动的来回辩论式互动,Michael 向我们介绍了他的研究,该研究告知如何在 RL 中使用人类反馈。以下是一些注意事项:

强化学习(查尔斯·伊斯贝尔)

  • 强化学习:假设有一个代理可以与环境交互,并得到一些可以用来修改未来交互的响应。建模为序列马尔可夫模型。允许我们从小数据集中学习。
  • 交互式强化学习:利用并从人类身上提取好的数据。
  • 我们为什么要信任用户?人民是最终的仲裁者;他们最清楚目标。
  • 人类有时是愚蠢的:有时忽略人类的输入(或避免对其进行字面解释)以获得最佳结果是很重要的。考虑一个模拟,其中一个代理可以在一个包含辐射区域的领域中拯救人类。一个简单的“去人类,避免辐射”会导致更少的人类被拯救。此外,人类在某个时间点后会停止提供反馈,之后他们只会提供反馈。例如,成年人不会因为学骑自行车而得到补偿,但孩子会。

交互式机器学习(迈克尔·利特曼)

  • 有时候,特工会学错东西。例如,模拟中的一只狗会走进一个花园,这样它就可以因为从花园出来而获得积极的奖励。这表明我们应该重新审视我们使用奖励的方式。
  • 反馈应该是一个梯度信号,作为对代理人政策/行为的评论。我们没有把反馈插入代理的奖励系统,而是把它作为一个等式的输入,这个等式模拟代理的行为/政策(优势函数)。这种方法更好地支持收益递减、差异反馈和政策制定。
  • 人类并不愚蠢:我们只需要更好地解释人类的输入,以及如何使用它来更新代理参数。我们不能外包我们对人类的理解。人类是一个循环,人工智能研究人员应该更多地与人类行为研究人员合作

【特邀演讲】【人类人工智能协作】走向人工智能思维理论..Devi Parikh [ 纸张

(a) These montages an agent’s quirks. For a given question, it has the same response to each image in a montage. (b) Human subjects predict the success or failure and output responses of a VQA agent (called Vicki). Source

乔治亚理工学院的 Devi Parikh 做了一个有趣的演讲,她主张进行更多的研究来量化用户对人工智能局限性的理解。

  • 我们越来越多地与能够接收图像并理解物体、活动、场景、对话、描述物体等的人工智能代理合作。参见 cloudcv 上的演示( visualChatbo t, VisualQA )。
  • 自然语言很重要,因为人类是机器推理的消费者。
  • 人类人工智能团队是未来。代理应该有一个很好的人类需求、意图、信念等模型,对用户的想法有一个理论。人类还必须对机器的能力、极限、信念等有所了解——人工智能的思维理论
  • 人类如何理解 AI?人类如何逼近神经网络?可解释性努力在多大程度上帮助人类理解 AI 极限?
  • 特工都很古怪。
    大多数代理不会计数、推理、一致性,也不会查阅外部知识库。不知道 3 离 4 有多近。他们视野有限,语言能力有限,不会推理,看不到世界上的先验知识(例如,香蕉主要是黄色的),从有偏见的数据集学习,并试图回答所有的问题。
  • 特工的古怪是可以预见的。我们要量化这个。她与一名接受过 VQA 训练的代理进行了一项实验(参见视觉问题回答的分层问题-图像共同关注)。给定一幅图像,参与者被要求估计代理是否会正确回答问题。
    — 60%的人正确预测了代理人的表现。
    —解释模态增加预测…显著图和其他模态导致预测增加。
  • 她建议使用监督学习来训练代理,并使用强化学习来微调它们。
  • 下一步和一些重要的论文:合作游戏,人类描述一个图像,代理人试图猜测图像。两人分享正确猜测的奖励。关于这项工作的一些论文。-https://visualdialog.org/
    -【HCOMP 2017】通过人机合作游戏评估视觉对话智能体。
    -【ICCV 2017】学习合作视觉对话具有深度强化学习的智能体
    -【CVPR 2017】视觉对话。

作为一名人机交互研究员,我发现 Devi 的演讲是会议上最有趣的演讲之一。我特别欣赏为开发推进 SOTA 的系统所做的努力(例如 VQA 在她的工作中)以及探索与这些系统相互作用的人为因素的实验。我的感觉是,Devi 的工作为成功结合人工智能和人机交互的研究提供了一个很好的例子。

2 月 6 日星期二

[邀请谈话]公平的问题,辛西娅·德沃克

辛西娅提供了她在差分隐私、算法公平和偏见方面丰富工作的想法。

  • 偏见会影响算法的公平性
    数据、算法和系统都有偏见,反映了设计者的显性和隐性选择、历史偏见和社会优先考虑。它们不折不扣地形成了价值观的法典化。算法的不公平——从广告到累犯预测——最近在大众媒体上引起了相当大的关注。(德沃克、哈特、皮塔西、莱因戈尔德和泽梅尔,2012 年)。
  • 分类中的公平概念
    —统计均等:那些接受正(或负)分类的人口统计数据与整个人口的人口统计数据相同的性质
    —相似地对待相似的个体:任何两个在特定任务方面相似的个体都应该被相似地分类
    —组成对个体和群体公平的影响。

辛西娅最后做了一些笔记

  • 教育有两种用途…扶老携幼和传授知识的主要任务。教育越进步,补偿越少。
  • 如果人工智能使现有问题复杂化,它的负面影响将变得更加深远。例如,增加面临风险的母亲(她们最需要经济支持)的保险费
  • 需要描述数据集“公平性”的指标。

【技术谈】终身学习的选择性经验回放。

来自宾夕法尼亚大学 Grasp 实验室的 David Isele 和 Akansel Cosgun 的演讲。

动机

  • 我们通常希望在一个受控的环境中训练一个模型,并希望它在野外有优雅的表现(适应新环境的能力)。
  • 在许多情况下,所学习的模型可能不是立即适合的,但是可以代表极好的初始化点。然后,我们可以基于这种初始化来启动某种形式的学习。
  • 然而,当我们尝试这种“在线”学习时,灾难性遗忘带来了复杂性。需要支持在线学习而不会遗忘的方法。

贡献

  • 这项工作采用了来自生物学的灵感和类比,并建议选择性体验回放。为了对连续学习者有用,经验重放必须被修改以允许适应变化的环境,同时保持过去的经验仍然相关。深度强化神经网络和经验回放见 Mnih 等 2015 。
  • 经验回放利用长期和短期记忆。然而,我们不能把所有的经历都保存在记忆中,我们需要策略来选择保存哪一段记忆。
  • 这项工作评估了经验选择策略(包括他们的)以及它们如何影响终身学习绩效——惊喜、奖励、最大化覆盖和匹配分布。

****我的想法:本文讨论了在终身学习的背景下解决灾难性遗忘的另一种方法。这是一个更有趣的用例(与“离线”模型相比,后者可能不需要在约束条件下频繁“学习”新信息)。期待着在报纸出版时阅读它。

用于跨领域情感分类的分层注意力转移网络

有趣的应用人工智能论文,探索跨领域情感分类的问题。

动机

  • 当训练集和测试集存在差异(分布)时,我们通常会观察到准确性的降低。例如,如果我们训练一个模型来检测书籍/小说文本中的情感,如果我们将该模型应用于不同的领域,例如餐馆评论文本,我们会观察到较低的分类性能。考虑一下例子【小说正文】《一个令人清醒的故事》【餐厅评论正文】“饭后我感到清醒”。 清醒 这个词可能会有不同的情绪(和含义)。
  • 显然,我们需要可扩展的、端到端可训练的方法来改进跨领域分类并解决上面举例说明的问题。

贡献

  • 这项工作利用文本的语言特征,识别两种类型的词——中枢和非中枢。支点是传达情感但不随领域变化的词。在大多数领域,厌恶这个词可能是负面的。非中枢:与中枢共现的特定领域词汇。
  • 了解中枢和非中枢之间的比对以及它们与分类的关系,然后将这种比对跨多个域进行转移。为了学习这种排列,他们提出了两个层次化的注意力转移网络(HATNs),它们学习中枢(P-Net)和非中枢(NP-Net)。
  • 作者在 5 个不同的领域测试了他们的方法,并显示了从基线开始的准确性的提高。

****我的想法:有趣实用的应用 AI 演示。这项工作也是深入领域的专业知识(在这种情况下是语言学)可以为神经网络架构的设计提供信息的方式的一个例子。有趣的是,随着独立学习正确架构的网络取得更多进展(例如谷歌与 AutoML 合作),看看他们如何与基于深层领域专业知识的解决方案进行比较将是有趣的。

【技术讲座】从人群中深度学习[ 论文 ]

: Bottleneck structure for a CNN for classification with 4 classes and R annotators. Source

动机

  • 深度学习使 SOTA 在各个领域取得了成果,并从标记的数据集中受益。但是对于许多问题,这种数据是不可用的。
  • 为了解决这个问题,我们使用了群体,有时我们需要专家群体(例如医学诊断)。虽然这种方法可行,但通常需要从多个具有不同专业水平的嘈杂贡献者那里收集标签。
  • 几种可能的聚合策略:
    ——多数投票(天真地假设所有注释者都是同等可靠的)。
    -使用期望最大化(EM)式算法,将公证人及其答案的未知偏差联合建模为一些潜在事实的嘈杂版本

投稿

  • 作者提出了一种新颖的人群层,这使他们能够直接从多个标注者的嘈杂标签中训练端到端的神经网络,仅使用反向传播。****
  • 这种变通的方法不仅避免了 EM 的额外计算开销,而且导致了一个通用的框架,该框架除了分类问题之外还可以进行一般性的推广。
  • 从经验上看,所提出的人群层能够自动区分好的和不可靠的注释者,并捕捉他们的个体偏见,从而在来自 Amazon Mechanical Turk 的真实数据中实现新的最先进的结果,用于图像分类、文本回归和命名实体识别

****我的想法:异常简单(概念和实现)但有效且有见地的问题解决方案。这些结果也可能对可以被公式化为聚合或投票问题的用例的一般集合有影响。

【技术谈】测量神经网络中的灾难性遗忘 论文

As a network is incrementally trained (solid lines), ideally its performance would match that of a model trained offline with all of the data upfront (dashed line). Experiments show that even methods designed to prevent catastrophic forgetting perform significantly worse than an offline model. Incremental learning is key to many real-world applications because it allows the model to adapt after being deployed. Source

动机

  • 一旦网络被训练来完成特定的任务,例如鸟类分类,它就不能容易地被训练来完成新的任务,例如递增地学习识别额外的鸟类或学习完全不同的任务,例如花的识别。当增加新任务时,典型的深度神经网络容易灾难性地忘记以前的任务。
  • 然而,增量学习很重要。希望有一种网络能够适应测试中的各种扰动。
    —略有变化的已知数据(例如天气、驾驶中的振动等)
    —新的数据类型(图像和音频)
    —新的对象类别(例如 MNIST 的新数字)
  • 能够逐渐吸收新信息的网络,就像人类如何随着时间的推移形成新的记忆一样,将比每次需要学习新任务时从头开始重新训练模型更有效。
  • 已经多次尝试开发减轻灾难性遗忘的方案,但是这些方法没有被直接比较,用于评估它们的测试变化很大,并且这些方法仅在小规模问题上被评估。

贡献

  • 作者引入了新的度量基准来直接比较五种不同的机制,这些机制旨在减轻神经网络中的灾难性遗忘:正则化、集合、预演、双记忆和稀疏编码。
  • 指标
    稳定性…它对基础知识的记忆有多好
    可塑性…它还在学习新材料吗?总体表现…稳定塑性比。
  • 对真实世界图像和声音的实验表明,对最佳性能至关重要的机制因增量训练范式和所用数据类型而异,但它们都表明灾难性遗忘问题尚未解决
  • 下一步:作者提出了他们解决灾难性遗忘问题的方法。

我的想法:我非常喜欢这个演示,觉得它很有教育意义,并且相信它们提供的度量、实验和见解有助于我们理解灾难性遗忘问题。该论文还强调了当前灾难性遗忘方法的一些难以处理的性质(例如,稀疏方法导致了40 倍的内存开销)以及为什么它们可能无法用于现实世界的部署。他们还表明,许多这些方法的性能不能很好地推广到更大的数据集。****

2 月 7 日星期三

【特邀演讲】我们如何评价斯坦福不良贷款集团 AI — Percy Liang)

Screenshot from Percy’s slide on future directions in crafting test sets.

在这个演讲中,Percy 主张改进我们评估 ML 算法的方式,以确保它们编码有意义的信息(没有廉价的技巧)并且很好地外推到新的发行版。

需要更好的指标

  • ML 已经成功了。然而,最大似然算法容易受到(敌对的)干扰,并且会犯人类不会犯的错误
    —阅读理解也容易受到对抗性攻击(小队数据集)。遭受同样的问题。移动互联网。
    ——这些问题表明我们正在做错事。我们如何缩小人类和机器之间的差距?
    —解决方案… 杰夫·辛顿—胶囊网络?….Yosua bengi 的意识先验?概率编程( Kolter and Wong 2017 )?Hector levesque 2103 …除了小抄,我们还需要更难的 ML/AI 系统测试。
    — Winograd 模式。考虑“狗追猫上树”这个例子。 在底部等待”。一个算法是否理解我们所说的 it
    —插值不充分
    —外推更难…测试域不同于训练域。我们需要跨领域推断的算法。

关于更难的测试和对立的例子

  • 【阅读理解的对抗性例子— EMNLP 2017 】在对抗性的设定下,十六个已发表模型的准确率从平均 75%的 F1 分下降到 36%;当对手被允许添加不合语法的单词序列时,四个模型的平均准确率进一步下降到 7%
  • 对对立例子的易感性(例如,对人类来说看起来正常的停车标志,但可以欺骗网络进入错误的分类)可能表明网络在表示停车标志时学到了错误的东西
  • 另一个更好的测试基准的例子:更深入理解常识性故事的语料库和评估框架,ACL 2016 。
    该语料库在两个方面是独特的:(1)它捕获了日常事件之间的一组丰富的因果和时间常识关系,以及(2)它是日常生活故事的高质量集合,也可用于故事生成。实验评估表明,许多基于浅层语言理解的基线和最先进的模型都难以在故事完形填空中获得高分。
  • Codalab — Percy 的团队创建了 Codalab,作为管理模型和促进可复制计算研究的工具。这有助于他们进行一些基准测试和评估实验。

关于防御对抗性攻击
Percy 提供了一种方法— 针对数据中毒攻击的认证防御

  • 为了防止攻击,我们可以尝试创建一个模型性能的上限保证。这是防御方在一系列攻击中最糟糕的防御损失的概念,防御方首先执行异常值删除,然后执行经验风险最小化。
  • 创建一个捕捉这个界限的证书,如果我们将它添加到训练目标函数中,它允许更好的防御。

学习评价

  • 模特能把负面评价转化成正面评价吗?这可能意味着它已经学到了一些对文本有意义的东西。
  • 经验评估仍然是一个好方法。与图灵测试和 Winograd 模式的传统保持一致。
  • 如果训练集和测试集具有相同的分布,我们就不能确切地确定我们的网络已经学到了深刻的东西。
  • 当一项措施成为目标时,它就不再是一项好的措施。古德哈特定律。

[技术演讲]使用递归神经网络的句子排序和连贯性建模[ 论文

Model Overview: The input set of sentences are represented as vectors using a sentence encoder. At each time step of the model, attention weights are computed for the sentence embeddings based on the current hidden state. The encoder uses the attention probabilities to compute the input for the next time-step and the decoder uses them for prediction. Source

动机

  • 如何才能以连贯的方式排列文本?连贯指的是让读者理解和吸收信息的文本属性。他们的缺席限制了理解。**
  • 连贯建模:区分连贯和不连贯文本的任务。如果我们能模拟连贯性,那么我们就能完成句子排序这项有价值的任务。
  • 案例示例:在多文档摘要中,我们想知道如何从每个不同文档中组合提取的文本来生成连贯的摘要。

贡献

  • 作者提出了基于 set-to-sequence 框架的端到端无监督深度学习方法。
  • 可视化所学习的句子表示表明,该模型捕捉段落中的高级逻辑结构。

我的想法:提供一些关于一致性建模方法的有趣想法。在学习生成连贯故事、对话或闲聊的 GAN 时,这可能有作为自动鉴别器的应用。

【技术谈】意象如何激发诗歌:用记忆网络从意象中生成中国古典诗歌

动机

  • 中国古典诗歌结构简洁,节奏优美,内容丰富。中国诗歌最常见的体裁是绝句(四行诗)。
  • 目标:给定一幅图像,我们如何生成一首既遵循四行诗的规则,又能描述图像的四行诗。
  • 现有的工作有几个局限性——它们表现出主题漂移(系统生成与电子邮件无关的材料),无法覆盖图像,以及覆盖关键字。

贡献

  • 作者提供了一个管道,首先提取关键字和特征(语义),逐行生成诗歌,整合语义关键字,忽略不重要的信息。
  • 注意力层允许模型关注图像的重要部分和前面几行的内容。支持无限数量的关键字。
  • 他们开发了一些有趣的评估实验来验证他们的工作。

【技术谈】一个基于知识的神经对话模型 论文

Knowledge-grounded model architecture and evaluation metrics. Source

动机

  • 神经网络模型能够生成极其自然的声音对话交互。然而,这些模型还没有证明它们能够以事实信息或基于实体的观点的形式整合内容,这将使它们能够服务于更面向任务的对话应用。如果用户提到一个不在数据集中的实体,就没有办法正确处理它。****
  • 目标:一个端到端的可训练管道,完全由数据驱动,学习使用数据集中的基础信息进行对话。

贡献

  • 提出了一种新颖的、完全数据驱动的、基于知识的神经对话模型,旨在产生更有内容的响应,而无需填充缝隙。
  • 将广泛使用的序列对序列(Seq2Seq)方法一般化,根据对话历史和外部“事实”来调节响应,使模型在开放领域设置中通用和适用。将非对话数据注入对话。
  • 该方法相对于竞争性 Seq2Seq 基线有显著改善。人类法官发现,模型输出的信息量要大得多。
  • 实验:数据收集自 Foursquare,23M 通用域 twitter 会话。基础:与 foursquare 实体的 100 万次 twitter 对话。
  • 多任务学习和参数共享解决泛化问题。

【特邀演讲】从朴素物理学到内涵:用语言学习和推理世界——叶筋·崔

这是一个比较有趣的演讲,叶筋从丰富的角度介绍了她在自然语言处理方面的工作。她从她的团队赢得亚马逊 Alexa Alexa 奖开始——创造了一个社交机器人,在 10 分钟内进行自然对话。

入选 Alexa 奖的团队在创造社交机器人方面展开竞争,这些机器人可以就一系列时事和热门话题(如娱乐、体育、政治、技术和时尚)与人类进行连贯而生动的对话。

为了感受一场精心设计的社交机器人对话有多令人满意,我建议看看关于 2017 年 Alexa 奖 结果的 视频。这些机器人可以被中断,在多个域上生成对话,似乎保持上下文等。

上面的幻灯片是叶筋在 AAAI 演讲的浓缩版。

我们的解决方案优于 SOTA!

一件有趣的事情是,在所有的技术讲座中,每一个演讲者都用这句台词来宣告他们的胜利

“我们的解决方案超越了最先进的技术(SOTA)”。(附有这方面的表格)

人工智能的研究进展非常非常快,我想研究人员展示进展的一种客观方式是展示他们报告的性能分数超过之前 SOTA 基准的指标(有时是 0.1 或 0.2)。一些人已经观察到这些比较是如何被操纵的,并在发布过程中产生瑕疵。

另一个有趣的术语是“端到端可训练的”——指的是使用单/联合损失函数训练所有模型的 ML 管道。拥有这样一个端对端可训练的模型,当然胜过 SOTA ,这是既令人向往又时髦的!**

结论

AAAI 2018 是一次组织得非常好的会议,很棒的场地(纽奥良被点亮了),我学到了很多!更重要的是,它帮助我确定了人工智能中我需要投入更多时间理解的领域和概念。与同事一起展示我在一个用于分析和可视化系外行星数据的认知助手上的工作也很棒。这个项目的视频描述可以在这里找到。

感谢阅读(原来是一篇冗长的帖子!).你可以随时联系 Twitter、Github 或 Linkedin。

差分隐私的高级介绍

原文:https://towardsdatascience.com/a-high-level-introduction-to-differential-privacy-edd20e6adc3b?source=collection_archive---------8-----------------------

在隐私和实用性之间取得平衡

Photo by ev on Unsplash

在一个数据科学家眼里,你生命中的每一刻都是一个数据点。从你的牙膏品牌到你挥手的次数,我们经常认为理所当然的细节是可以用来推断我们行为和意图的关键因素。这些由跨国组织挖掘的见解可以用来使我们集体生活的各个方面更加方便和有趣,但代价是我们的私人信息被暴露甚至被利用。

以美国第二大百货零售商 Target 为例,该公司在 2012 年决定实施一种看似直观的方法,根据客户的特定需求定制他们的购物体验。目标是找出哪些客户最有可能怀孕,然后根据计算出的可能性向这些客户发送与怀孕相关的广告。我们可以将 Target 的想法解释为双管齐下的方法:1 .存储或合并数据以分析怀孕买家的趋势。2.应用技术或算法将新客户的数据点与以前客户的购买模式相关联,以确定一个人想要孩子的可能性。当 Target 在一名少女的家人知道她怀孕之前向她发送了与孕产相关的广告(混合了来自不同部门的广告)时,Target 的倡议成为了隐私和机器学习算法交汇处的许多讨论的中心(来源:福布斯关于的文章“Target 如何在她的父亲之前发现一名少女怀孕了”)。这些隐私问题不仅适用于出于营销目的的数据收集和存储,也适用于从人口普查数据到社交媒体的各种应用。

因此,大数据、机器学习和数据科学的出现使得重新考虑隐私成为必要,这是有道理的。

差分隐私被认为是可以帮助我们实现这一目标的最先进的概念之一,并且已经被苹果、优步、美国人口普查局和其他组织所使用。

在这篇文章中,我将概括介绍什么是差分隐私,为什么它是相关的,它是如何实现的,以及如何使用它。

什么是差分隐私?

差分隐私(DP)的主要前提包括确保数据主体不受其进入或参与数据库的影响(例如,不受伤害),同时最大化查询的效用/数据准确性(与随机/空输出相对)。

DP 保证:

  • 原始数据不会被查看(也不需要修改)。
  • 维护受试者的隐私将比从数据中挖掘重要的洞察力更有价值。
  • 对后处理的弹性;对差分私有算法的输出进行后处理不会影响算法的差分私有性。换句话说,对数据库没有额外知识的数据分析师不能简单地通过考虑 DP 算法的输出来增加隐私损失(来源:【differential 隐私的算法基础】 )。

基于概述的保证,这意味着如果数据分析师/对手依赖于仅相差一个数据条目的数据库,最终结果改变的概率将不会受到该数据条目的存在/不存在/修改的影响(结果最多改变一个倍数)。换句话说,当使用 DP 时,分析师或对手不能根据查询的输出来区分数据库。

Taken from Ian Goodfellow and Nicholas Papernot’s blog post “Privacy and machine learning: two unexpected allies”

然而,与他/她对从数据中挖掘出的结论的感知相关的个人的伤害或收益不受 DP 概念的保护。DP 的正式(数学)定义如下:

Taken from Differential Privacy: A Survey of Results

Cynthia Dwork 在论文 “差分隐私的承诺算法技术教程” 中用一个简单的例子演示了 DP:

正在为一项研究向个人收集数据(玛丽是一名吸烟者,是研究参与者之一)。这项研究得出的结论是,吸烟极有可能致癌。差异隐私保证:

  • 分析趋势的数据科学家或数据库经理不能直接访问原始数据。
  • 诸如 Mary 的保险费之类的服务不会基于她在数据集中的参与而改变。

然而,这项研究的结论性分析(“吸烟可能导致癌症”)对伤害/好处的效用留给了玛丽的感知;玛丽可以选择相信“基于这项研究的发现,我可以通过戒烟来预防潜在的癌症”,与这种说法完全相反,或者别的什么。

为什么这很重要?

“数据是信息时代的污染问题,保护隐私是环境挑战。”— 布鲁斯·施奈尔

确保隐私对于许多应用至关重要,包括维护敏感信息的完整性,消除对手根据个人身份信息跟踪用户的机会(PII)等。DP 对各种应用都有吸引力,因为它保证了以下隐私“需求”:

DP 消除了数据分析师可能不得不使用的任何潜在方法来区分特定个人与其他参与者,或将特定行为与之前识别的个人相关联,以便相应地定制内容/服务;因此,DP 确保与参与研究相关的隐私风险不会显著增加( 【辛西娅·德沃克的“差分隐私” ) )。

这是因为无法直接访问原始数据,并且使用个人独有的发现来专门针对或影响特定个人违反了个人在数据集中的存在不应影响其接受服务的机会的规则。此外,使用 DP 不需要成为隐私或 DP 专家(即深入了解 DP 的内部机制),而且如上所述,DP 对后处理具有弹性。DP 还延伸到群体隐私,尽管增加群体的规模会削弱 DP 界限( “差异隐私:结果调查”作者 Cynthia Dwork )。

我们现在可以看到,上面呈现的 Target 从购买行为中预测母性的例子可能是对差分隐私概念的违反。在预测一名少女怀孕的案例中(如这里的所述,Target 应该将个人的购买趋势与其他期待孩子的客户的其他模式相关联,并开始根据她在数据集中的参与情况专门为她量身定制广告。如果她被从数据集中删除,Target 将不会向她发送与生育相关的广告,这违反了差异隐私的概念。

作为一个题外话,重要的是要注意到思考这样的道德场景并不是这么简单。销售的目标是通过说服顾客他/她需要某件商品来激励顾客购买该商品。Target 向购买了与其他顾客相似的商品的个人提供有针对性的广告,这可能侵犯了差分隐私,因为 Target 使用从组织收集的数据来帮助顾客了解公司可能提供的潜在好处,并根据他们的个人需求定制购物体验。

此外,也有反对我提到的立场的论点。一种观点强调,如果目标确实使用了该算法,它也不会是完全准确的(没有算法是完全准确的),因此会犯许多错误(即误报)。另一个角度(在《金融时报》的文章《大数据:我们正在犯一个大错误吗?》中解释))声明 Target 邮件列表上的每个人都会收到与孕产相关的广告和其他类型的广告。不仅仅是期待的顾客。

这是如何工作的?

虽然 DP 本身不是一个算法,但将 DP 的应用程序想象成位于数据分析师和数据库之间的一个软件会有助于理解它是如何工作的:

Taken from Microsoft’s “Differential Privacy for Everyone”, page 4

查询是由用户传递给 DP 警卫的输入;一个示例查询可能是“计算数据库中的行数”。差分隐私有许多变体——本节讨论ε-差分隐私,它不同于(ε,δ)-差分隐私和 DP 的其他(较弱)版本(如果您想了解 DP 的其他版本,请参见“我们的数据,我们自己:通过分布式噪声生成的隐私”)。

DP 的主要目标之一是在隐私损失(由ε测量,为此需要选择一个值,例如 0.01)和效用最大化(可以通过数据精度等许多参数测量)之间进行平衡。ε = 0 的值导致完全的私密性,但缺乏实用性,而较高的ε值导致私密性缺乏,但具有良好的实用性。(摘自 《差分隐私的承诺:算法技术教程》 )。

如微软白皮书“每个人的差分隐私”中所述,DP 技术将原始数据作为输入,从原始输入数据中找到答案,然后基于各种因素(例如,数据库的大小、查询的类型等)引入失真。)

在查询函数 f 上,隐私机制 k 用 f(X)+(lap(δf/ε))^k 以分布 lap(δf/ε)添加噪声)独立地响应 f(x)的 k 个分量中的每一个。

——摘自辛西娅·德沃克的《Differential 隐私:调查结果》

换句话说,DP“守卫”的作用是为查询(定义为函数 f )的真实答案(定义为f(x)】+(lap(δf/ε))^k)中的每个 k 输出项添加噪声;DP 防护的输出或最终结果称为响应。**

让我们把它分解一下。

噪声是通过拉普拉斯分布(在上式中表示为 Lap )添加的,这类似于正态分布/钟形曲线——正态分布和拉普拉斯分布都是单一模型(具有一个峰值)和对称的概率分布类型(分布的左侧和右侧同等平衡)。然而,主要的区别是拉普拉斯分布有一个更尖锐的峰值,正如 Statistics How To 在他们的文章中解释的那样。

A picture of the Laplace Distribution from Frank McSherry’s blog post “Differential Privacy for Dummies”

值得注意的是,也可以使用其他机制来代替拉普拉斯分布。例如,虽然拉普拉斯机制对于任何具有实数作为输出的函数都有效,但是指数机制可以用于相反的情况(没有实数作为输出的函数)并且是添加噪声不实际的情况;类似于的指数机制函数给定一个数据集,使用测量输出质量的效用函数产生一个输出/对象(来源:摘自“differential 隐私:结果调查”“野外差分隐私当前实践和公开挑战教程” )。

使用 DP 时,我们需要计算查询的敏感度(敏感度表示为δf,*查询表示为函数 f*

Taken from Differential Privacy: A Survey of Results

查询的敏感性有助于我们了解个人数据对计算的影响程度,从而了解需要添加的噪声量。 f 的灵敏度通常较小,因此,在大多数情况下,DP 算法不需要添加太多噪声;当ε(隐私损失)的值固定时,较大的敏感度用作需要添加更多噪声来掩盖数据的警告(来源: “隐私的构建块:差分隐私机制” ,作者:Graham Cormode)。

需要注意的重要一点是,随着更多的问题被问及,DP 的隐私保证会减弱。这将我们带到顺序和并行合成的正式定义:

“顺序合成:如果你执行两个(或更多)差分隐私计算,它们共同提供差分隐私,其参数由你使用的参数的总和限定” ( 《差分隐私:图解入门》 )。

根据顺序合成的定义,如果您有两个差分私有计算,这意味着结果将是ε1 + ε2 差分私有(摘自 Graham Cormode 的“隐私的构建块:差分私有机制”)。并行组合涉及“释放每个具有ε-差分隐私的单元”,而不是顺序组合提出的总和(如 Graham Cormode 的“隐私的构建块:差分私有机制”中所述)。如“ 差分隐私:结果调查 中所述,“通过在每个查询上运行具有拉普拉斯噪声分布的差分隐私算法,可以为任何查询序列确保差分隐私。另外要补充的一点是调查中提到的,敏感性和隐私损失(这是添加噪声所需的参数)与数据库的大小和数据库本身无关;较大的数据库导致对普通查询的差分私有算法具有较高的准确性。除了关于如何最大化 DP 在不敏感查询上的潜力的细节以及产生差分隐私的数学证明/定理之外,关于这一点的进一步讨论可以在调查中找到。

这一节可以用这个定理来概括:

Taken from Differential Privacy: A Survey of Results

这是如何使用的?

  • 美国人口普查局在 2008 年的 OnTheMap 应用程序中实现了 DP,以确保居住人口数据的隐私性。阅读这篇文章中的更多细节:" 保护美国统计数据的保密性:在人口普查局采用现代披露避免方法 " 由约翰·m·阿伯德博士撰写。
  • 苹果在苹果机器学习杂志的文章 “大规模隐私学习” 中描述了利用 DP 的三种用例:发现流行的表情符号,识别使用 Safari 访问的资源密集型网站,以及发现新词的使用。苹果实现的一个新颖方面是他们使用了三种不同的私有算法——私有计数均值草图算法、私有哈达玛计数均值草图和私有序列片段拼图。

Taken from the article “Learning with Privacy at Scale” from Apple’s Machine Learning Journal

  • 微软应用 DP 来掩盖个人在其地理位置数据库中的位置;这种方法包括随机删除、添加和打乱单个数据点。其实现的一个新颖方面是创建了 PrivTree ,在给定原始数据和一些其他参数(要使用的拉普拉斯噪声的比例、用于决定是否应该发生节点分裂的阈值等)的情况下。),可以实现差分私有算法,并为几乎任何种类的位置数据输出噪声数据。

**

Pictures taken from Microsoft’s blog post “Project PrivTree: Blurring your “where” for location privacy”

  • 优步将差分隐私作为其数据分析管道和其他开发工作流程的一部分。他们的实现的一个新颖方面是使用弹性敏感度,这种技术允许您计算查询的敏感度,并满足优步苛刻的性能和可伸缩性要求。

Taken from Uber Security’s Medium article “Uber Releases Open Source Project for Differential Privacy”

  • 谷歌实施了 DP 作为其随机可聚合隐私保护顺序响应(RAPPOR)技术的一部分,该技术允许数据分析师研究客户的数据,而无需查看单个数据点。他们实现的一个新颖方面是,DP 的实现是为了在 RAPPOR 执行的两个重要步骤中保证客户端隐私:永久随机响应确保隐私不受生成的噪声的影响,而瞬时随机响应防止攻击者使用永久随机响应。

Taken from the paper “RAPPOR: Randomized Aggregatable Privacy-Preserving Ordinal Response” by Úlfar Erlingsson, Vasyl Pihur, and Aleksandra Korolova

额外资源

这篇文章仅仅触及了不同隐私的表面。如果你想进一步探索动态规划的内部机制和应用,有很多很好的资源;其中一些包括:

  • 在微软的研究网站这里可以找到关于 DP 的出版物概要。
  • Georgian Impact 的媒介文章《差分隐私简介》除了对拉普拉斯噪声计数机制的模拟。
  • 《差分隐私小教程》Borja Balle 著。
  • 《科学美国人》文章“数字隐私:保护数据的新方法”
  • Frank McSherry 关于差分隐私的博客帖子(其中一些包含用于演示目的的代码),比如这篇帖子。
  • 宾夕法尼亚州立大学课程 的课堂讲稿和课程材料数据隐私中的算法挑战
  • 演讲幻灯片:“野外的不同隐私:当前实践和公开挑战指南”。
  • 如果你想了解我们如何将 DP 应用于机器学习,我推荐你阅读尼古拉斯·帕伯诺特和伊恩·古德菲勒的博客文章“隐私和机器学习:两个意想不到的盟友?”和马丁·阿巴迪及其同事的论文“具有差异隐私的深度学习”。
  • 如果你对机器学习和隐私之间的交集感兴趣,请查看 NeurIPS 2018 " 隐私保护机器学习研讨会。

感谢您的阅读!

原载于 2018 年 11 月 20 日demystifymachinelearning.wordpress.com

基于后见之明的数据科学博士学位方法

原文:https://towardsdatascience.com/a-hindsight-based-approach-to-a-phd-in-data-science-9a272cf65394?source=collection_archive---------7-----------------------

最近刚完成计算机科学(更具体地说是数据科学)的博士学位,事后回想起来,我发现有些事情我会采取不同的做法。我的目标是这篇文章对那些刚刚开始或考虑攻读数据科学博士学位的人有用。

Photo by Glen Noble on Unsplash

r 与 Python

我博士的开始日期是 2014 年 9 月,我最初在 KNIME (一个基于可视化节点的数据挖掘工具)中做了一些初步的研究。然而,我发现用 KNIME 编写任何相当复杂的东西都需要创建一个定制的 KNIME 节点。节点创建需要大量样板代码,通常会导致 Eclipse 出现问题(在我看来,Eclipse 是一个糟糕的编辑器——希望事情已经发生了变化,因为我自 2014 年以来就没有接触过它)。

有人可能会问,“你为什么首先使用 KNIME?”这是一个合理的问题。答案是,我的主管参与的以前的研究有一个为它开发的自定义 KNIME 插件,所以从这个开始似乎是个好主意。

因为我要停止使用 KNIME,所以我需要用一个新的工具来替换它,这个选择我缩小到了 R 或 Python。当时,在 2014 年,R 和 Python 似乎在可用的机器学习库中拥有平等的地位。出于几个原因,我最终选择了 R:

  1. Python 的缩进:我真的不喜欢 Python 的强制缩进。我目前的看法是,我仍然不喜欢它,我只是咬紧牙关,遵守它的规则。
  2. 统计计算:R 是为统计和分析而设计的语言,而 Python 是为通用计算而设计的。我的想法是,R 将允许更容易地调查数据,因为语言本身就是为这项任务设计的。

至于为什么我希望选择 Python: Python 是迄今为止最受欢迎的编程语言,根据 2018 年 8 月 TIOBE 指数 Python 排名第 4,R 排名第 18。2014 年9 月,Python 是#8,R 是#21。也许我当时就应该看看这个榜单,看到这两种语言流行的趋势。

此时,Python 已经开发了大量的库和资源。另一个问题是 R 的古怪之处,dplyr 试图通过使代码看起来更合理来解决它——我希望我在开始时就知道这一点,而不是在结束时发现这一点。

在我的研究过程中,我确实为 R 写了一个包,我认为如果这个包是为 Python 开发的,它实际上可能不仅仅是我一个人在使用。事实上,一名硕士生正在开发我研究的未来工作部分。我最后一次和他交谈时,他告诉我他将从事 Python 的工作,而我的回答是“我希望我已经那样做了”。我相信他可能要做的第一件事是用 Python 重写 R 包的许多功能,因为这些功能非常常见——几乎是基本的——来操作我在博士学位期间分析的数据。

制作更多互动作品

这一点不是为了研究方面的事情,我可以说这是可选的,因为它不会影响最终结果,也不会提高生产率。在我读博士期间,我根据我正在分析的数据制作了几个互动项目:

  • 允许用户输入特征的用户界面和经过训练的分类器将做出预测。
  • 用过滤器列表更改下拉列表,图形将根据下拉列表中的项目更新—数据将应用不同的过滤器。

这些都是非常基本的东西,但是对于向我的主管解释概念有很大的帮助,而且交互性远比静态图表更令人愉快。我希望我能开发出更多这样的东西。这也可以包括动画图表——这很容易用 D3.js 来完成,并且可以为演示制作一些引人注目的幻灯片。

第一个项目使用了gWidgetstcltk——一个交互式 GUI 生成器——它就像这个包的名字一样有趣。第二个项目使用了闪亮的——一个交互式网络应用构建器——实际上使用起来很有趣,尤其是与 gWidgetstcltk 相比。

减少脚本依赖性

我绝大多数的工作都是由原型组成的,这些原型从未产生任何有意义的结果。其中一些原型是独立的,但随着我继续攻读博士学位,这些原型变得越来越相互依赖:

每个脚本的结构如下:

  • 导入库
  • 函数定义
  • 执行函数的耗时代码

当脚本#2 需要使用脚本#1 中定义的函数时,就会产生脚本依赖性,因此它会运行整个脚本#1 来将定义的函数加载到 R 工作空间中。

每当运行脚本#2 时,运行脚本#1 的第一个问题是,这会导致每次都运行耗时的代码。为了解决这个问题,我不得不返回到脚本#1 并编写一些额外的代码,这样耗时的代码只有在脚本#1 直接运行时才会被执行(而不是从另一个脚本)。

第二个问题是这变成了一团乱麻。一种解决方案是将函数定义与执行代码完全分离,将它们放在各自的文件中。

第三个问题是,脚本#1 中的重构函数会对每个使用重构函数的依赖脚本产生连锁反应。这个问题的潜在解决方案让我想到:

(非常小的)持续集成

一个持续的集成环境,它只是运行所有的脚本(或子集)来检查它们是否还在工作。

数据的版本控制

随着我收集和处理的数据越来越多,我在博士期间使用的数据量也在增加。我最终通过将数据复制并粘贴到存储每个原型的文件夹中来复制每个项目的数据,所以在某种程度上,这是对数据版本化的一种粗略尝试。数据量不是很大,所以在这方面这不是很大的问题。但是将它放在一个包含最终原型的代码库中(在那里已经分析了结果),并链接到提交,会是一个简单得多的解决方案。

结论

我不认为我会再去读一个博士,但希望这对潜在的博士生或刚开始读博士的人有用。很明显,这不是一份详尽的清单,而是一份我应该做却没有做的清单。

免责声明:我提到的软件/技术在我读博士时可能已经改变,我的观点是基于我使用它们时的状态

RTS 人工智能研究的历史

原文:https://towardsdatascience.com/a-history-of-rts-ai-research-72339bcaa3ee?source=collection_archive---------1-----------------------

RTS 游戏中的 AI 研究有着丰富的历史。十多年来,研究人员一直致力于构建能够击败最佳人类选手的机器人,但仍有很长的路要走。在 BlizzCon 2016 上,DeepMind 和暴雪宣布了一项合作,这导致了星际争霸 2 人工智能研究的开放 API。

这篇文章的目标是涵盖 RTS 游戏和人工智能研究的一些发展,这些发展可能有助于这一结果。要更全面地了解 RTS 游戏的研究,请查看由翁塔诺等人和罗伯逊和沃森撰写的调查文章

StarCraft II, Blizzard Entertainment

在过去的十年里,研究人员已经从孤立地研究 RTS 游戏中的不同人工智能技术,过渡到在更复杂的游戏中合作和竞争,在这些游戏中,不同的技术面对面地进行匹配。为了使这项工作取得成功,下列条件是必要的:

  • 开放 API 供研究人员构建和评估机器人
  • 竞赛让研究人员能够比较不同的技术
  • 回放学习算法用于训练
  • 人类对手评估机器人的性能

随着 2009 年 Brood War API 的发布,这些条件中的大部分都得到了满足,但该平台的封闭性使得研究人员难以自动化训练 AI 系统的过程。随着开放的星际争霸 2 环境的宣布,研究人员将有很大的机会开发能够在 RTS 游戏中实现专家级性能的系统。以下是我认为对实现这一目标具有重要意义的一些事件。如果有我应该包括的其他重要事件,请在评论区留言。

1998 年

《星际争霸 1》发行
原版《星际争霸》于 1998 年 3 月发行,资料片《育雏战争》于同年 11 月发行。《星际争霸》风靡全球,并在韩国引发了一场职业游戏热潮。

在有星际争霸之前,有 1995 年发行的魔兽争霸 2。魔兽争霸 2 的一个克隆版本在 1998 年以 Freecraft 的名字首次发布,后来被重新命名为 Wargus。这个克隆体是建立在 Stratagus 游戏引擎上的。Freecraft 是 RTS AI 研究的一个重要项目,因为最初的大部分工作都是使用 Wargus 作为测试平台。

2001 年

对游戏人工智能的学术兴趣一篇关于游戏人工智能的开创性文章是约翰·莱尔德和迈克尔·范·伦特的文章,发表在 2001 年的《人工智能杂志》上。这是一篇意义重大的文章,因为它是 AAAI 最早承认实时游戏是人工智能研究的优秀环境的出版物之一。它还帮助改变了学术研究人员的心态,从试图将现有的方法应用于游戏,转而考虑为游戏建立新的和专门的方法。

2002 年

魔兽争霸 III 发布
魔兽争霸 III 附带的一个很棒的特性是一个高度可扩展的地图编辑器,它被用来创建像 DOTA 初始版本一样的独特内容。地图编辑器也有一些脚本功能,可以用来创作自定义的人工智能。然而,以这种方式创作的 AI 仅限于单个地图,并且脚本语言仅向作者提供命令的子集。一些研究人员能够在这个框架内实现他们的人工智能技术,但不可能测试不同的机器人。

2003 年

RTS 游戏被提议作为人工智能试验台
Michael Buro 和 Timothy Furtak 在 2003 年发表了一篇文章声称 RTS 游戏提出了许多需要解决的新问题,以便构建人类级别的人工智能。他们还提议开发一个开源的 RTS 游戏引擎,供人工智能研究社区使用。

State Estimation in StarCraft

2004 年

第二年,Michael Buro 发布了第一个开源 RTS 引擎版本, ORTS 。该游戏能够在图形和非图形模式下运行,这使得机器人能够在数千个游戏会话中快速训练。使用 ORTS 的一个主要挑战是,虽然有人类玩家的界面,但没有专家玩家可以评估机器人。

ORTS Game Engine

第一个沃格斯研究
Freecraft 更名为沃格斯,使用了 Stratagus 游戏引擎。Wargus 的主要优势之一是它是开源的,这为研究人员使用他们想探索的任何技术开放了平台。Wargus 面临的一些挑战是缺乏用于分析的回放,缺乏活跃的玩家基础,以及用于测试机器人相互之间的网络代码有限。马克·庞森是第一批发表关于使用沃格斯作为人工智能测试平台的文章的研究人员之一。

TIELT 提出
2004 年提出的 AI 项目之一是 TIELT 系统,这是一个为多个游戏标题提供一致 API 的 AI 框架。该系统的目标之一是使研究人员能够为一个游戏构建人工智能,并将学到的知识转移到新的游戏中。例如,在 Wargus 中学到的领域知识可能适用于其他 RTS 游戏。我将 TIELT 包括在这个讨论中,因为 DeepMind 和暴雪合作的成果之一将是一个 API 和潜在的示例数据集。对于这个 API 来说,重要的是不要对人工智能如何运行做出假设。TIELT 的挑战之一是它不提供对游戏状态的直接访问,这限制了可以利用它的人工智能技术的数量。这个系统的许多目标现在在脸书的 ELF 平台上实现了。

TIELT Architecture [Aha and Molineaux, 2004]

2005 年

沃格斯的强化学习
沃格斯很快成为研究人员构建 RTS AI 的环境。2005 年,研究人员开始探索诸如强化学习的技术,这是 AlphaGo 使用的策略之一。Wargus 的工作最终开始停滞不前,因为不同的研究人员无法相互评估工作,而是依赖于性能而不是硬编码脚本的小集合。

2006 年

第一届 ORTS 竞赛
2005 年,第一届 ORTS AI 竞赛公布,赛事在斯坦福的 AIIDE 2006 大会上举行。第一届比赛有 4 个参赛项目,比赛规模逐年增长,直到 2009 年结束。

2007 年

ICCup 推出
国际赛博杯是星际争霸的第三方托管天梯服务器。这个服务器对人工智能研究很重要,因为你可以在这个服务器上运行机器人,但不能在官方的暴雪服务器上运行。这个服务器的另一个好处是,它为玩家提供了一个字母分数,他们可以使用它来轻松地交流他们的技能。比如我 2010 年认真打球的时候顶多是个 D+玩家。

2008 年

首次星际争霸人工智能研究
虽然之前有关于星际争霸的出版物,但我所知道的第一篇专注于星际争霸人工智能构建的文章发表于 2008 年。谢和孙建立了一个模型,通过挖掘成千上万的录像来预测玩家正在制造哪些建筑和单位。

Build-Order prediction in StarCraft

2009 年

育雏战争 API 发布
2009 年,我发现了一个名为 BWAPI(育雏战争 API)的 Google 代码项目,它提供了对星际争霸的编程访问。该库通过使用第三方 DDL 工具将 API 注入星际争霸运行时来工作,并暴露了一组用于调用游戏内函数的钩子。从那以后,这个项目的贡献者规模不断扩大,并被移植到多种语言。它现在托管在 GitHub 上,有一个 Java 版本。

2010 年

星际争霸 2 发售
2010 年,星际争霸 2 自由之翼发售,竞技育雏大战场面持续活跃了几年。资料片《虫群之心》发布于 2013 年,《虚空的遗产》发布于 2015 年。

首届星际争霸赛
首届星际争霸赛 AI 赛在 AIIDE 2010 举行。主赛事由伯克利 Overmind 团队赢得。比赛还包括一场人机表演赛,人类选手轻松击败了人工智能对手。

UC Berkeley Overmind Team

2011 年

第二届 AIIDE 星际争霸赛
阿尔伯塔大学的 Dave Churchill 接手了第二届以及随后几届的 AIIDE 星际争霸赛。他编写了一个自动运行锦标赛的锦标赛框架,并改变了一些规则以促进合作,例如要求提交的内容是开源的。

学生星际 AI 锦标赛
第二届星际 AI 锦标赛开始了,重点是学生提交。该锦标赛与年度会议无关,每年举办几次锦标赛。

https://sscaitournament.com/

2013 年

星际争霸 BroodWar 机器人天梯
Krasi0 为星际争霸机器人开发了一个天梯系统,现在 24/7 运行。这为研究人员评估不同的人工智能方法提供了一个环境。

2014 年

星际争霸 2 自动化玩家
Matt web corner演示了可以通过拦截 DirectX 命令来构建星际争霸 2 机器人,以便推断游戏状态。这种方法的一个主要限制是机器人只能访问当前显示在屏幕上的游戏状态。

2016

AlphaGo 击败 Lee Sedol
2016 年 3 月,DeepMind 的 AlphaGo 系统击败围棋世界冠军 Lee Sedol。胜利之后,很多人预计《星际争霸》将是 DeepMind 尝试的下一个挑战。

脸书加入
2016 年,来自脸书的人工智能研究人员开始使用《星际争霸》作为强化学习试验台。他们发表了一篇关于星际争霸中微观管理的文章。该机器人参加了 AIIDE 2017 竞赛,但它的学习方法被更关注脚本的机器人胜过。

在 BlizzCon 2016 上,DeepMind 宣布他们正在与暴雪合作开发一个开放的人工智能框架。随着谷歌和脸书竞相打造一个能够胜任职业星际争霸游戏的机器人,竞争开始升温。

2017

星际争霸 2 API 发布 暴雪在 8 月 9 日发布了用于编写 bot 的星际争霸 2 API。还宣布了一个用于编写机器人的研讨会。

触发人工神经元的历史

原文:https://towardsdatascience.com/a-history-of-triggering-artificial-neuron-d1d9853d9fdc?source=collection_archive---------14-----------------------

这一切都是从四年前我了解到深度信念网开始的。当时,人们说“这是由生物神经网络启发的”,我只是接受了这一点。在我深入研究之后,我的脑海中涌现出许多问题,尤其是当我看到 乙状结肠函数 时。起初,这对我来说似乎很荒谬,因为这个 sigmoid 函数只是将任何给定的数字映射到范围-1 到 1。那么,我们为什么需要这个?。我的第一个猜测是,也许它只是使输出正常化,所以在某些时候它不会爆炸。这个问题一直留在我的脑海角落里,静静地坐着,等待着有一天被回忆起来。

几年过去了,我一直在质疑很多其他的东西。直到几周前,我才接触到一本关于计算神经科学的书。我读了这本书,我在那本书的第三章找到了答案。它描述了神经元如何表现的几种计算模型,我发现了人们最近使用的深度学习模型的联系,以及人们更喜欢使用当前模型的原因。在本文中,我将总结我所知道的人们用来模拟神经元的一些神经元模型,并试图将计算神经科学与应用人工智能联系起来。由于我既不是计算神经科学家也不是生物学家,可能会有一些不准确的信息,如果有的话,我会很乐意纠正它们。

计算神经科学和人工智能

在我看来,这两个主题虽然关注的方向不同,但仍然紧密相关。我称之为习得智力的因果关系。这篇文章是从两个角度写的。

The causality of learned intelligence

在模拟模型时,计算神经科学的重点是了解大脑如何工作,以及如何才能接近真实的大脑。反过来,人工智能试图基于提出的理论、观察结果和近似模型来构建智能系统。

基本人工神经元结构

神经元是一种细胞。与我们身体中的其他细胞相同(如红细胞)。它的主要任务是传输和处理信息(编码为电脉冲)。据我所知,对于所有不同的人工神经元模型,人工神经元的结构是相同的。它有许多输入(x)和一个输出(y)。就发送电脉冲(信息)而言,一个神经元与其他所有神经元之间的连接能力可以不同,这种能力称为连接强度

Basic structure of artificial neuron

计算神经科学中的神经元模型

漏整合和发射神经元(1907)

这个模型通常缩写为 IF-model。它来源于当两个连接神经元在两个膜中都有电势差时产生的尖峰(由化学反应、转移的离子等引起)。正如基尔霍夫定律所说,两个端点之间的电位差导致电流从一端流向另一端。

该模型对每个输入的电流进行积分(求和),并改变神经元膜中的电位值。如果神经元膜上的电位值达到一定的电位阈值,神经元就会发出一个尖峰信号。出现尖峰后,神经元膜将其值重置为静息电位。然而,在膜中存在渗漏(阻力因子),并且该渗漏因子将在膜复位后重新启动(抵消)静息电位。

在这种模式下,有两种产生尖峰的独特情况:

  1. 当输入电流恒定并且低于膜的电位阈值,并且它们的总和仍然低于膜的电位阈值(非激发尖峰)时
  2. 当输入电流恒定且低于膜的电位阈值,并且它们的总和高于膜的电位阈值(激发尖峰)时

这两种情况都被称为亚阈值,在亚阈值中,神经元表现为线性。在第一种情况下,不会产生尖峰。在后者中,由于神经元膜的电容性行为,它产生周期性的尖峰。

但是,这种模式有一些限制:

  • 该模型的亚阈值条件没有给出实际发生在真实神经元中的各种产生的尖峰。
  • 真正的大脑由大量相互连接的神经元组成。如果将该模型集成到大规模网络中,它将变得不容易处理。

麦卡洛克-皮茨神经元(1943 年)

麦卡洛克-皮茨神经元模型没有考虑神经元如何工作的所有细节,而是忽略了所有细节,例如微分方程、重置膜电位等,并且仅考虑神经元模型的主要特征。甚至使其离散。

The McCulloch-Pitts Neuron model, o for output, h for threshold

这个想法是,给定一些输入值,如果输入值的总和超过阈值,神经元将输出 1,否则神经元将输出 0。这种神经元模型适用于较大的网络。

伊兹基科维奇神经元(2003)

与 IF-neuron 相比,该模型的计算效率相对更高,并且产生尖峰的可能性更大。该模型引入了两个微分方程,一个用于更新膜电位,另一个用于更新“恢复变量”。它还引入了简单的复位条件。

神经元如何学习?

如果我们再看一下上一节中的基本人工神经元结构,我们可以得出结论,最影响神经元输出的是神经元之间的连接强度。我们可以简单地说,当我们学到一些东西时,连接强度会根据我们学到的东西以某种方式形成。我们获得了一个新的信息(如图像、新闻、歌曲等),我们是通过感官从体外环境中获得的。信息会从输出神经元到输入神经元反向传播到网络,并影响神经元之间的连接强度。比如我们现在的知识是“树上的叶子都是绿的”。但是,当我们看到一片棕色的叶子时,新的信息“有一片棕色的叶子”将与我们当前的知识进行比较,并且我们当前的知识将被更新为“不是树上所有的叶子都是绿色的”。以前存储信息“树中的所有叶子都是绿色的”的连接强度,现在存储“树中的所有叶子都不是绿色的”。

人工智能中的桥接神经元模型和人工神经元——激活函数

在计算神经科学中,神经科学家尽可能接近真实的神经元,并或多或少地考虑神经元的细节。为了使模型在大型网络中可计算,需要一个可计算但有代表性的模型,并且在计算和精度之间总是有一个折衷。

从之前描述的所有模型中,有一个主要的相似特征在神经元模型中非常重要,即触发的尖峰。简而言之,神经元的基本任务是在给定一些输入的情况下产生一个尖峰。这个主要特性可以用数学的方式表示为一个函数,称之为 激活函数

人工智能中的人工神经元

模拟真实神经网络的人工神经元网络是人工神经网络。对于每个人工神经元,都有一个数学函数。人工神经网络应该具有学习新信息的能力。神经元模型中的连接强度在人工神经网络中称为参数。为了形成参数,我们需要像大脑那样通过将新信息从输出传播到输入来训练神经网络。它被称为反向传播。在反向传播过程中,可以使用微分计算比较当前知识和新知识。从数学的角度来看,并不是所有的函数都是可微的。因此,找到一个既可微分又具有良好性能(近似真实神经元)的激活函数有点棘手。

除此之外,一个好的模型是更一般化的模型。想象一个孩子正在学习动物的名字。老师教他“狗、马、鸡”是动物。如果在那之后,孩子可以知道老师以前从未教过他的动物种类,例如“一头牛,一只山羊”也是动物,因为它们与马有相似的解剖结构,即使有时孩子说“一只鸡”不是动物,这是错误的,这意味着他可以概括他所学的东西。

但如果孩子只知道“狗、马、鸡”是动物,其他的不是动物,即使他回答得很完美,也不是一个概括的问题。这就是所谓的过度拟合。下面是几种激活功能。它们都有自己的优点和局限性。人们可以根据需要使用任何激活功能。

乙状结肠功能

Sigmoid 函数具有与 logistic 函数相似的曲线(“S”形曲线)。如果输入是相对较大的负值,则输出为零,如果输入是相对较大的正值,则输出为一,否则输出值介于 0 和 1 之间。

Sigmoid function

优势:

  • 因为输出在 0 到 1 的范围内,如果我们想表示某件事情发生的概率,这个激活函数是有用的。

校正线性单位(ReLU) (2010)

如果输入小于零,ReLU 使输出为 0。如果输入大于 0,则输出与输入相同的值。

ReLU function

优势:

  • 与具有指数常数的 sigmoid 函数不同,计算导数(梯度/微分)ReLU 在训练中相对更快。如果输入小于 0,消除(产生零)输出会使整个网络更加稀疏。
  • 产生与输入值相同的输出值(恒等式)使得导数更容易计算(相同值的导数将总是 1),因此网络不会遭受 消失梯度 的问题。

还有 ReLU 的其他变体,、漏 ReLUs (LReLUs) 、参数化 ReLUs (PReLUs) 。

指数线性单位(ELU) (2016)

ELU 的功能与瑞路相似。而不是在输入小于零时产生输出 0。如果输入小于零,它用特定的函数计算,否则它输出与输入相同的值。因此,如果输入小于零,输出将为负。

优势:

  • 尽管仍然像 ReLU 一样解决消失梯度问题,但如果输入小于零,eLU 通过使用负输出使平均激活值(类似于将数据集归一化为平均零)趋向于零。这使得学习速度更快。

高斯误差线性单位(GELU) (2016)

这个激活单元根据输入比其他输入大多少来随机缩放输入。高斯的累积分布函数用于确定比例因子。该单元具有与自适应退出类似的功能。

优势:

  • 一个非凸的非线性函数使它比 ELU 和 ReLU 具有更大的灵活性。它还具有更好的通用性,有助于获得更高的精度。

综上

这篇文章只是我对发生的事情和我之前发现的事情的看法,对一些人来说可能非常肤浅。另外,我刚才描述的话题只是神经元的一小部分,一个 激活功能 ,一件小事却影响巨大。

无论如何,知道人类能在多大程度上推动自己去了解自己真的很令人兴奋。计算、推断和建立智能系统的新方法的发明一直在迅速增加。计算神经科学家和人工智能科学家都在尽最大努力改善目前的状况。每个月都有新的方法、理论、模型被发明出来。我打算把这篇文章写得尽可能简单,让每个有兴趣的人都能理解。所以,如果有一点复杂的语言或术语,或者无法解释的词,请原谅我。

python NumPy 数组的搭便车指南

原文:https://towardsdatascience.com/a-hitchhiker-guide-to-python-numpy-arrays-9358de570121?source=collection_archive---------1-----------------------

A hitchhiker guide to python NumPy Arrays

如果您正在使用 python 进行数据科学研究,那么您要么使用过 NumPy,要么肯定听说过它。大多数需要将数据存储在内存中的统计分析都使用 Numpy。

有人可能会问为什么是 NumPy?难道 python 列表或其他数据结构不能做同样的事情吗?

嗯,是也不是,在 NumPy 中没有什么是不能通过 python 列表或使用其他数据结构来完成的,但是,NumPy 提供了一个有效的存储和更好的方式来处理使用简单 API 的数学运算的数据,其好处远远超过了编写自己的代码。

NumPy 为数学运算提供了高效的存储和更好的数据处理方式

为什么使用 NumPy 数组?

NumPy 用于创建 同构 n 维数组(n = 1..n)。与 Python 列表不同,NumPy 数组的所有元素都应该是同一类型。因此,如果提供了数据类型,下面的代码无效

numpy_arr = np.array([1,2,"Hello",3,"World"], dtype=np.int32)  # Error

然而,对于 python 列表,这是一个有效的代码

py_arr = [1,2,"Hello",3,"World"]  # Valid Code

考虑到可以在 NumPy 数组上执行的数学运算,NumPy 数组被创建为同构数组。对于异构数据集,这是不可能的。

让我们看看 NumPy 为我们提供了什么额外的好处,以及它如何简化我们的编程生活,尤其是处理数学计算的编程。

1.NumPy 使用更少的内存来存储数据

与 python 列表相比,NumPy数组占用的内存要少得多。它还提供了指定内容的数据类型的机制,这允许进一步优化代码。

作为一个例子,我们可以使用 python list 和使用numpy.array(...)创建一个简单的 6 个元素的数组,它所占用的内存量的差异是相当惊人的。参见下面的例子

如果这种差异看起来令人生畏,那就准备好接受更多。如果我们知道我们计划拥有的单个数据的最大数量,就有可能对 NumPy 数组做进一步的优化。

在上面的例子中,NumPy 默认认为这些整数是8 Bytes整数,但是,如果我们知道数据的最大范围,我们可以用 NumPy 数组提供数据类型。例如,我们可以使用1 Byte整数存储到255的数字,使用2 Bytes整数存储到65535的数字

优化的内存分配不仅限于存储数字,它还扩展到存储字符串。但是,由于 NumPy 数组主要用于数学计算,string 将很少被存储和使用。然而,知道需求是否出现是很好的

类似地,NumPy 数组在存储浮点值方面提供了相当大的节省。

现在我们知道了 NumPy 的内存优势,让我们继续了解它如何允许我们创建多维数组

2.使用 NumPy 创建 n 维数组

n 维数组通常用于创建矩阵或张量,也主要用于数学计算目的。与基于 python 列表的 n 维数组相比,NumPy 不仅节省了内存使用,还提供了大量额外的好处,使数学计算变得容易

这是我们可以用 NumPy n 维数组做的一系列事情,否则很难做到。

只要多重因子产生相同数量的元素,数组的维数就可以在运行时改变。例如,2 * 5 的矩阵可以转换为 5 * 2,1 * 4 可以转换为 2 * 2。这可以通过调用数组上的 NumPy *.reshape(...)* 函数来完成

NumPy 也可以为一个数组生成一组预定义的数。使用 *numpy.arange(...)* 功能可以生成一组预定义的数字(包括小数步长)。这个函数的输出总是一维的数字集合。但是,我们可以对这个输出使用 reshape 来生成我们选择的维度。

NumPy 提供了使用预先填充的 1 和 0 创建 n 维数组的 API,其中矩阵的所有成员不是 0 就是 1。最有可能的用途之一是为机器学习创建一个稀疏或密集的矩阵。

默认情况下,NumPy 使用浮点 *float64* 数据类型来创建 1 和 0,但是可以使用 *dtype* 选项将数据类型更改为整数,如下图

正如 *.reshape(x,y)* 可以将一个数组转换成多维数组,同样,使用 *.ravel()*函数可以从任意多维数组创建一个一维数组

3.n 维数组的数学运算

如前所述,NumPy 不仅可以有效地存储数据,还可以非常容易地对数据进行数学运算。对 n 维数组的任何操作都与数学运算非常相似。

NumPy n 维数组使得对其执行数学运算变得极其容易

这是 NumPy 的主要 USP,因为它被广泛用于数据分析社区。python 列表离它能做的还差得很远。例如,考虑将 python 列表乘以 2。这是我们将得到的

py_arr = [1,2,3] * 2
# Generates [1,2,3,1,2,3]

而 numpy 数组产生输出,每个数组元素乘以 2

np_arr = np.array([1,2,3]) * 2
# Generates [2,4,6]

类似地,我们也可以对 numpy 数组进行其他数学运算,如加、减和除

np_arr = np.array([1,2,3]) + 2
# Generates [3,4,5]

一个多维矩阵的运算就像我们使用两个数一样简单

np_arr1 = np.array([[1,2,3],[4,5,6]])
np_arr2 = np.array([[1,2,3],[4,5,6]])np_arr3 = np_arr1 * np_arr2
#Generates
# [[ 1  4  9]
# [16 25 36]]np_arr3 = np_arr1 + np_arr2
#Generates
# [[ 2  4  6]
# [ 8 10 12]]

NumPy 内置的数学函数还允许我们执行复杂的数学运算,如 sqrt、mean 和 median。

np.sqrt(np_arr1)
#generates
# [1\.         1.41421356 1.73205081]
# [2\.         2.23606798 2.44948974]]np.mean(np_arr1) #generates 3.5
np.median(np_arr1) #generates 3.5

还有额外的内置成员函数来获取数组的更多细节,包括 sum、min 和 max

np_arr1.sum()  # 21
np_arr1.min()  # 1
np_arr1.max()  # 6

4.在 NumPy 数组中查找元素

在处理数据集时,有时我们需要从可用的数据集中找到特定的数据。虽然 NumPy 为相同的功能提供了多种功能,但其中三种功能会比其他功能使用得更频繁。他们是where, nonzerocount_nonzero

Wherenonzero函数返回与 True 语句相关的索引。例如

np_arr = np.array([1,2,0,4,5])
find = np.where(np_arr > 2)
#returns [3,4]

np_arr = np.array([1,2,0,4,5])
find = np.nonzero(np_arr)
# return [0,1,3,4]

最后可以通过使用count_nonzero(...)函数来计算 numpy 数组中非零元素的个数

n_arr = np.array([1,2,3,0,3,0,2,0,0,2])
np.count_nonzero(n_arr) 
# returns 6

这些方法在计算矩阵的稀疏度或密度时非常有用。

在机器学习中有其自身用途的最后一种方法是找到 NumPy 数组的形状。这是使用.shape完成的。例如

n_arr = np.array([1,2,3,0,3,0,2,0,0,2])
n_arr.shape
# Generates => (10,)
n_arr = np.array([[1,2],[3,0]])
# Generates => (2,2)

5.最后的想法

上面提供的例子仅仅描述了 NumPy 功能的最小集合。虽然不全面,但是应该对什么是 NumPy 以及我们为什么要学习和使用它有足够的了解。

这就是这篇文章的全部内容。将在另一篇文章中提出另一组有趣的 NumPy 功能

感谢阅读…!!!

达克什

人工智能科…不要!

原文:https://towardsdatascience.com/a-i-coe-no-33f7e0f85880?source=collection_archive---------8-----------------------

我如饥似渴地阅读了 HBR 的文章——机器学习改善公司工作流程的 8 种方式。虽然这篇文章包含了一些非常好的观点,但我完全不同意创建人工智能卓越中心的建议。值得称赞的是,两位作者确实对彼此脱节的创新孤岛提出了警告。

我更大的问题是机器学习太重要了,不能被隔离在创新实验室里!Frank Chen 提供了机器学习将如何嵌入产品的最佳类比。根据陈的说法,机器学习类似于关系数据库,从电子商务到猫视频,关系数据库一直是当前所有数字产品和体验的核心。关系数据库在存储和排序数据方面非常出色。

机器学习应用同样将是未来体验的基础。不同的是,ML 的度量单位是预测。回到这篇文章,人工智能 COE 和关系数据库 COE 一样荒谬。

相反,我建议采用 ML 优先的方法。那么——这在实践中应该如何运作呢?

创新的类型

基本上有三种类型的创新:

  1. 渐进式创新——这是持续调整和改进的改善方法。
  2. 破坏性渐进主义——这是间隙空间中的创新,导致“曲棍球棒”的结果。想想看——苹果应用商店的推出。
  3. 突破性创新——这在商业中极为罕见,在自然界几乎从未出现过。思考——优步的创造和共享经济的兴起。

对于这类创新的精彩分析,请看谷歌前首席信息官 Doug Merrill 的这篇 Google Talk 。这是相当过时,但仍然非常相关。

虽然机器学习将创造一些激进的创新,但我认为更有趣的机会是创造具有破坏性影响的增量变化。

你如何发现颠覆性渐进主义的机会?良好的开端是从您的客户(外部或内部)开始,并遵循以下步骤:

  • 规划顾客的旅程
  • 确定旅程中的空白区域,在那里顾客正在离开或者没有以某种关键的方式得到服务
  • 你在收集有效数据吗?例如,您是否正在收集客户的人口统计数据、当前表达的意向信号、这些信号对公司的价值等
  • 有没有办法建立一个模型来传递一个独特的信息,提高客户转化的机会?

以上所有的步骤都是渐进的变化,但是总的来说(并且是大规模的),它们可以带来不成比例的巨大成果。对我来说,这是机器学习的更大机会——不是藏在某个 COE 里,而是在取悦你的客户的前线。

人工智能玩疯狂图书馆,结果是可怕的

原文:https://towardsdatascience.com/a-i-plays-mad-libs-and-the-results-are-terrifying-78fa44e7f04e?source=collection_archive---------10-----------------------

这是 1982 年。迈克尔·杰克逊的《T2》惊悚片《T3》是世界上最畅销的专辑。外科医生最近植入了世界上第一颗人造心脏。时代杂志刚刚选择了“计算机”作为年度风云人物。但是现在这些都不重要了,因为你已经在 8 小时的家庭汽车旅行中呆了 30 分钟,你已经厌倦了。

你会在 iPhone XS 上打开 Instagram 自娱自乐吗?没有,苹果还在为大家翘首以待的 Apple IIe 的发布做准备。你有没有看最新的哈利波特书?没那么快,J. K .罗琳才高中毕业。取而代之的是,你拿起新削好的 2 号铅笔,画出这个:

疯狂图书馆?你指的是那种简单而巧妙的游戏吗?一个玩家向另一个玩家要一系列单词,然后用这些单词填充一个故事模板,接着就是欢乐。是的,那个疯 Libs。

回到我们的故事…你和你的弟弟设法通过 30 分钟玩游戏。最终,你的兄弟厌倦了这个游戏,出于你新的厌倦,你开始自己玩。因为你没有耐心,你就直接跳到故事,然后开始以你认为合适的方式填写空白。这是我们在本文中关注的 Mad Libs 的退化单机版。

自 1982 年以来,世界发生了巨大的变化。首先,伯特被释放了。伯特?“你问吧。"你是指最近达到最新技术水平的BI directionEn coderR代表从 T 变压器 是的,那个伯特。你可能会问,伯特和疯狂图书馆有什么关系?嗯,就像 X 一代一样,从某种意义上说,伯特是在疯狂图书馆长大的。请允许我澄清…

BERT 是一种语言表示模型——一种将人类语言翻译成计算机可以理解的数学形式的模型,实现了从自动问答到情感分析的各种应用。但是为了表现语言,伯特首先得理解它。那么伯特是如何学习人类语言的呢?正如论文所解释的:

为了训练深度双向表示,我们采用了一种简单的方法,即随机屏蔽一定比例的输入标记,然后只预测那些被屏蔽的标记

BERT learned by reading 11,000 books and all of English Wikipedia

换句话说,伯特通过猜测文本中缺失的单词(“记号”)来学习语言。本质上,伯特玩的是疯狂图书馆,或者至少是前面描述的单人游戏,骗子版本。然而,BERT 也有一个答案(被删除的单词),因此它可以学习预测“正确”的答案。BERT 非常擅长这个练习,因为它重复了数百万次,涵盖了英语维基百科中的所有文本以及 11,000 本书。通过这样做,伯特学会了语言的基本结构,然后可以应用于更有用的任务。

实验

我用一些真实的疯狂库测试了伯特,从神奇的计算机开始,这是一首歌颂大约 1982 年个人计算机最新进展的颂歌:

From Mad Libs #11 (1982)

为了运行 BERT,我们求助于来自 HuggingFace 的优秀的 Python 实现,它构建在深度学习框架 PyTorch 之上。这个库使得我们完成填空任务变得非常容易:

注意,我们严格专注于填空,以及诸如复数名词身体的一部分等标签。被忽略。

结果

伯特令人惊讶且有些令人不安的解决方案如下所示:

BERT’s solution

看起来 BERT 已经利用了它所有的关于现代计算机的知识:移动设备,亚马逊购物门户,人类替代品,甚至更糟。(注意,用于训练伯特的文本包括 786 部科幻小说,这可能解释了反乌托邦倾向)。

这里有一个更好的例子,表明 BERT 也可以给出更可预测的结果,尽管有时有些夸张:

BERT has strong feelings about sneakers

免责声明:预测一个句子中缺失的单词并不是 BERT 的最终目标;这是伯特利用现有数据学习语言的第一步。通常情况下,BERT 随后会针对特定任务进行微调,例如自动问答。BERT 已经在许多这些最终任务上取得了最先进的成果,所以不要根据它疯狂的库实力来判断 BERT:)

在这里 了解更多关于我的可视化和可解释性工作 。你可以在 Twitter 上找到我@Jesse _ vig

Apache Spark 大数据之旅:第 1 部分

原文:https://towardsdatascience.com/a-journey-into-big-data-with-apache-spark-part-1-5dfcc2bccdd2?source=collection_archive---------3-----------------------

关于了解 Apache Spark 用于大数据处理的系列文章的第一篇。

我的大数据之旅始于 2018 年 5 月。十多年来,我一直是一名软件工程师,参与并领导了一些 Sky Betting & Gaming 最大的产品和服务的开发。在此期间,我学到了很多关于如何构建和操作可扩展应用程序的知识——从对日志和指标的需求,到性能优化和可维护性。当我被要求成为我们数据部落的工程经理时,我既兴奋又极度紧张——我以前领导过小团队,但对大数据一无所知。所以我决定学!

“你从哪里开始做这样的事情?”这是我经常问自己的问题。大数据生态系统非常庞大。所以我问我团队中的一位首席工程师他们会推荐什么,Apache Spark 是他们的首选。

什么是火花?

从 Apache Spark 网站:

Apache Spark是用于大规模数据处理的统一分析引擎。

用人类的话来说,Spark 是一个分布式计算框架,当查询内存数据集时,它有一个跨多种语言的通用接口,用于 SQL 和 MapReduce 之类的东西。由于是分布式的,Spark 可以在一个机器集群上处理非常大的数据集。

为什么是火花?

从工程角度来看,Spark 有多种语言版本:Scala、Java、Python 和 r。这看起来是一个相当大的胜利,因为它没有限制我们可以租用特定语言的内容。Spark 有自己的 DSL ( 领域特定语言),这在所有实现中都是相同的,这意味着尽管选择了不同的实现语言,但还是有一种通用语言。我们的数据科学团队使用 PySpark 和 Spark 的组合,更广泛的团队使用 Scala——我们让团队(大部分)选择他们自己的工具。

Spark 对数据框架的使用非常适合通常的软件工程和应用程序设计原则,例如单元测试、数据建模、单一责任原则等等。又一次大获全胜。我可以像以前一样继续构建应用程序(我是12 因子原则的忠实粉丝)。

Spark 还附带了一个 SQL 接口,对于大多数曾经需要在某个地方存储和查询数据的程序员/工程师来说,这通常是很熟悉的。

如果你感兴趣的话,Spark 甚至有一个流媒体库。虽然我不会马上这么做(虽然我是 Apache Kafka 的超级粉丝),但它对未来的学习(我想也是商业用例)很有吸引力。

我们开始吧

Apache Spark 似乎令人望而生畏(就像任何新事物一样),我发现自己又在问“我从哪里开始?”我坚信从头开始理解事物会让你成为更好的工程师。这一点,加上在某个地方实际练习使用 Spark 的需要,引导我构建一个小型本地 Spark 独立集群。

注:我是 Docker 的忠实粉丝。它为你提供了一种打包方式,并以一种非常便携的方式分发。我需要在自己的机器上安装的惟一依赖项是 Docker 本身。我将在我所有的例子中使用 Docker,所以你可能想从这里的中得到它。我还在运行 OSX,它对 Docker 有一些小的限制,但我们可以解决它们。

我们的首要任务是找到一个合适的包含 Java 版本的 Docker 映像。作为开源软件的粉丝,我选择了使用 OpenJDK。我不是一个膨胀的粉丝,并决定 Alpine Linux 是正确的选择。幸运的是,我们可以使用已经可用的图片。让我们开始创建我们的docker 文件。**

在一个名为 Dockerfile 的空目录下创建一个新文件。在顶部添加以下一行:

*FROM openjdk:8-alpine*

现在我们可以构建我们的映像,它使用 OpenJDK 映像作为基础。通过运行以下命令构建映像:

*docker build .*

这将提取基础图像并创建我们自己的图像版本。您将看到类似于以下输出的内容:

*Successfully built 68ddc890acca*

我们不再在每次构建图像时记录输出散列,这一次我们将标记图像,给它命名以便更容易使用(当然,用您自己的名字替换$MYNAME)。这是对上面的构建命令的一个小小的调整:

*docker build -t $MYNAME/spark:latest .*

现在,我们可以使用我们给它的标签来引用它,而不是使用生成的散列来引用构建的映像。通过使用标签名运行容器进行测试,如下所示:

*docker run -it --rm $MYNAME/spark:latest /bin/sh*

这个图像还没有多大用处,因为它只包含 Java。让我们安装一些实用程序,我们将需要下载和安装 Spark。我们将需要wget来下载包含 Spark 的归档文件,并需要tar来从该归档文件中提取文件。我们还需要bash来管理一些事情。在 Dockerfile 中的新行上,添加以下内容(我们需要包含--update,这样 Alpine 就有了一个新的存储库列表,可以从中下载二进制文件):

*RUN apk --update add wget tar bash*

现在重建图像并观察wgettarbash的安装。

我们现在可以下载并安装 Spark。我们将使用基于 Scala 2.11 和 Hadoop 2.7 的 Spark (2.4.0)的最新版本(不要担心 Hadoop,我们对此不感兴趣…还没有)。将以下内容添加到您的docker 文件中的新行,并进行编译:

*RUN wget [http://apache.mirror.anlx.net/spark/spark-2.4.0/spark-2.4.0-bin-hadoop2.7.tgz](http://apache.mirror.anlx.net/spark/spark-${SPARK_VERSION}/spark-${SPARK_VERSION}-bin-hadoop2.7.tgz)*

Docker 非常聪明,它将重用我们之前构建的,所以现在它所要做的就是下载 Spark 归档文件。一旦构建完成,映像将包含 Spark 归档文件,供我们安装。安装就是简单地从档案中提取 Spark 并把它放在一个合适的地方。将另一行添加到 Dockerfile 中,这样做(为了可读性,我将命令分成多行。rm是简单地清理下载的归档文件)然后构建:

*RUN tar -xzf spark-2.4.0-bin-hadoop2.7.tgz && \
    mv spark-2.4.0-bin-hadoop2.7 /spark && \
    rm spark-2.4.0-bin-hadoop2.7.tgz*

恭喜你!现在,您已经在 Docker 映像上下载并安装了 Spark。是时候测试一下了!让我们开始一个容器,并得到一个外壳。注意构建图像结束时的 ID 输出,因为我们现在将使用它。在您的 shell 中运行以下命令:

*docker run --rm -it $MYNAME/spark:latest /bin/sh*

然后我们将在容器内部运行的外壳中结束,用它来启动 Spark Master 。当开始成功启动时,Spark 需要几个选项。这些是主服务器监听的端口、WebUI 的端口和主服务器的主机名:

*/spark/bin/spark-class org.apache.spark.deploy.master.Master --ip `hostname` --port 7077 --webui-port 8080*

希望您应该看到一堆日志输出!如果有,恭喜你!您已经成功开始运行 Spark Master。

下一步是将一些 Worker 添加到集群中,但是首先,我们需要在 Master 上设置一些配置,以便 Worker 可以与它对话。为了使事情变得简单,我们将为 Master 提供一个合适的名称,并公开 Master 端口(最后一个命令中的--port选项),同时使 WebUI 对我们可用。通过使用 CTRL+C 和 CTRL+D 停止主 shell 并退出容器。现在您应该在本地 shell 中了。只需调整docker run命令,添加--name--hostname-p选项,如下所示,然后运行:

*docker run --rm -it --name spark-master --hostname spark-master \
    -p 7077:7077 -p 8080:8080 $MYNAME/spark:latest /bin/sh*

运行docker ps,您应该看到容器运行时的输出如下(我已经删除了一些输出,以使其适合代码块):

*CONTAINER ID  PORTS                                NAMES
3dfc3a95f7f4  ..:7077->7077/tcp, ..:8080->8080/tcp spark-master*

在容器中,重新运行命令来启动 Spark Master,一旦启动,您应该能够浏览到 http://localhost:8080 并看到集群的 WebUi,如下图所示。

Spark Master WebUI

添加工作节点

正如我提到的,我正在使用 Docker for Mac,这使得 DNS 很麻烦,并且如果不运行本地 VPN 服务器或其他东西来解决这个问题,通过 IP 访问容器几乎是不可能的——这超出了本文的范围。幸运的是,Docker 有自己的网络功能(具体细节也不在本文讨论范围之内),我们将用它来为本地集群创建一个网络。创建网络非常简单,只需运行以下命令:

*docker network create spark_network*

我们不需要指定任何特定的选项,因为默认选项对我们的用例来说已经很好了。现在,我们需要重新创建我们的主服务器,以将其连接到新网络。运行docker stop spark-masterdocker rm spark-master删除当前运行主机的实例。要在新网络上重新创建主服务器,我们可以简单地将--network选项添加到docker run,如下所示:

*docker run --rm -it --name spark-master --hostname spark-master \
    -p 7077:7077 -p 8080:8080 --network spark_network \
    $MYNAME/spark:latest /bin/sh*

这与我们第一次运行 Spark Master 时没有什么不同,只是它使用了一个新定义的网络,我们可以使用这个网络来连接工作人员,以使集群工作👍。现在主节点已经启动并运行,让我们向它添加一个 Worker 节点。这就是 Docker 的魔力真正闪耀的地方。要创建一个 Worker 并将其添加到集群中,我们只需启动同一个 docker 映像的新实例并运行命令来启动 Worker。我们需要给这个工作者一个新的名字,但是除了这个命令之外,其他的基本保持不变:

*docker run --rm -it --name spark-worker --hostname spark-worker \
    --network spark_network \
    $MYNAME/spark:latest /bin/sh*

要在容器上启动 Spark Worker,我们只需运行:

*/spark/bin/spark-class org.apache.spark.deploy.worker.Worker \
    --webui-port 8080 spark://spark-master:7077*

当它启动并连接到主机时,您应该看到输出的最后一行:

*INFO  Worker:54 - Successfully registered with master spark://spark-master:7077*

主服务器将输出以下行:

*INFO  Master:54 - Registering worker 172.21.0.2:37013 with 4 cores, 1024.0 MB RAM*

恭喜你!您已经使用 Docker 设置了一个 Spark 集群

但是这有用吗?

为了检查它是否工作,我们可以加载主 WebUI,我们应该看到 Worker 节点列在“Workers”部分下,但这实际上只是确认了将 Worker 连接到主 WebUI 的日志输出。

Spark Master WebUI with Worker

为了进行真正的测试,我们需要在集群中实际运行一些 Spark 代码。让我们运行 docker 映像的一个新实例,这样我们就可以运行安装 Spark 时提供的一个示例。同样,我们可以重用现有的 docker 映像,并简单地启动一个新的实例,用作驱动程序(向集群提交应用程序的东西)。这个不需要--hostname--name-p选项:**

**docker run --rm -it --network spark_network \
    $MYNAME/spark:latest /bin/sh**

在容器中,我们可以通过运行以下命令向集群提交应用程序:

**/spark/bin/spark-submit --master spark://spark-master:7077 --class \
    org.apache.spark.examples.SparkPi \
    /spark/examples/jars/spark-examples_2.11-2.4.0.jar 1000**

提供的示例计算出哪个 Pi 正在使用集群。

当应用程序运行时,您应该能够在 Spark Master WebUI 中看到:

Spark Master WebUI — Running Application

完成后,您将在日志中看到 Pi 输出的值:

**Pi is roughly 3.1414459514144597**

您还会在 WebUI 中看到完整的应用程序报告:

Spark Master WebUI — Completed Application

用 Docker Compose 把它钩在一起

Docker Compose 是 Docker 提供的一个简洁的工具,我们可以将其用作编排工具,这样我们就不必自己在许多终端窗口中运行命令了。我们本质上是将各种命令缝合在一起,并将一些东西参数化,这意味着我们可以简单地运行docker-compose up,集群就开始运行了。

为了实现这一点,我们可以创建一些脚本来复制到映像并在容器启动时运行。我们将创建的第一个是设置 Spark Master。创建一个名为start-master.sh的新文件,并添加以下命令:

**#!/bin/sh/spark/bin/spark-class org.apache.spark.deploy.master.Master \
    --ip $SPARK_LOCAL_IP \
    --port $SPARK_MASTER_PORT \
    --webui-port $SPARK_MASTER_WEBUI_PORT**

我们没有在脚本中直接指定 IP、Master 和 WebUI 端口,而是将它们参数化,这意味着我们可以将它们作为环境变量提供。从而在主设备监听的配置(端口)方面提供了更大的灵活性。要将脚本放到图像上,我们需要复制它。然而,在此之前,我们需要确保脚本是可执行的。只要运行chmod +x start-worker.sh就可以了。现在将脚本添加到图像中,在最后一个RUN命令下面的 Dockerfile 中,添加以下内容:

**COPY start-master.sh /start-master.sh**

在我们重新构建映像之前,我们也将为 Worker 创建一个类似的脚本。创建一个名为start-worker.sh的新文件,并添加以下命令:

**#!/bin/sh/spark/bin/spark-class org.apache.spark.deploy.worker.Worker \
    --webui-port $SPARK_WORKER_WEBUI_PORT \
    $SPARK_MASTER**

同样,我们已经对配置进行了参数化,以提供更大的灵活性。使新脚本可执行(chmod +x start-worker.sh),并在 Dockerfile 中添加另一个COPY行,以将脚本添加到图像中:

**COPY start-worker.sh /start-worker.sh**

重建并运行。如果一切顺利,您将进入容器中的一个 shell,该容器中的脚本位于文件系统的根目录中:

**bash-4.4# pwd
/
bash-4.4# ls -l
total 72
...
-rwxr-xr-x    1 root   root   357 Dec 6 11:56 start-master.sh
-rwxr-xr-x    1 root   root   284 Dec 6 17:10 start-worker.sh
...**

回来后,我们将使用docker-compose来编排集群。

创建一个名为docker-compose.yml的新文件,并输入以下内容:

**version: "3.3"
services:
  spark-master:
    image: $MYNAME/spark:latest
    container_name: spark-master
    hostname: spark-master
    ports:
      - "8080:8080"
      - "7077:7077"
    networks:
      - spark-network
    environment:
      - "SPARK_LOCAL_IP=spark-master"
      - "SPARK_MASTER_PORT=7077"
      - "SPARK_MASTER_WEBUI_PORT=8080"
    command: "/start-master.sh"
  spark-worker:
    image: $MYNAME/spark:latest
    depends_on:
      - spark-master
    ports:
      - 8080
    networks:
      - spark-network
    environment:
      - "SPARK_MASTER=spark://spark-master:7077"
      - "SPARK_WORKER_WEBUI_PORT=8080"
    command: "/start-worker.sh"
networks:
  spark-network:
    driver: bridge
    ipam:
      driver: default**

我们在这里所做的就是指定要使用的映像名,设置主机名和容器名,显示正确的端口并连接到我们在底部创建的网络,设置一些环境配置和启动时要运行的命令。我们还将 Worker 设置为依赖于正在运行的主服务器。

要启动集群,我们只需运行docker-compose up。Docker Compose 的一个优点是,我们可以通过简单地在 Compose 命令中添加一个--scale选项来扩展 Workers。假设我们需要 3 个工作节点,我们运行:

**docker-compose up --scale spark-worker=3**

就这样。我们完了。下次我们开始学习在 Scala 中构建我们自己的应用程序时,请继续收听。

监督机器学习之旅

原文:https://towardsdatascience.com/a-journey-into-supervised-machine-learning-f26f238b0477?source=collection_archive---------22-----------------------

关于监督式 ML 的一些实例、提示和想法

今年早些时候,通过我在康乃尔理工的 MBA 项目,我和一位了不起的教授卢茨·芬格一起上了一堂很棒的机器学习入门课。Lutz 的课程激励我更深入地挖掘 ML 和 AI,所以我最近在 Udacity 上开始了一个动手操作的机器学习课程,我觉得这会很好地增加我的背景。到目前为止,我已经完成了关于监督学习的部分,并希望分享我的初学者对我所学到的东西的看法,并思考这项技术的潜在影响。

你可以在这里 的课程/项目中找到我的 python 文件。相关文件夹choose_your_own, decision_tree, naive_bayes, and svm

监督学习概述

监督学习是机器学习任务,它学习基于示例输入-输出对将输入映射到输出的函数(Stuart J. Russell,Peter Norvig (2010) 人工智能:一种现代方法 )

我觉得这个定义相当直观;该算法从“监督”历史动作/数据点中学习以产生输出。在监督机器学习中,有几十种不同的方法,但我最近的研究集中在朴素贝叶斯、支持向量机(SVM)、决策树和随机森林,然后进一步讨论如何在 Python/ scikit-learn 中使用这些算法。

我不会在这里重复每种方法的细节,但是如果你想要一个概述,我建议你参加这个课程或者浏览 Google 了解细节。但是,我确实想指出一些重要的经验,以及我如何看待这些经验对我未来发展的影响。

监督/课程外卖

与任何数据驱动方法一样,数据质量和结构对受监督模型输出的有用性有着巨大的影响。这并不令人惊讶,但令人惊讶的是,为了改进模型或性能,可以修改传入数据的方式有多种。虽然我没有太深入地研究功能选择/工程,但简单地处理数据量以及测试与训练数据的比例对准确性、性能和潜在的过度拟合有着巨大的影响。

至少从我初学者的角度来看,Scikit-learn (sklearn)非常容易使用。对于每种算法(不包括导入),只需 4 行代码即可训练、预测和计算模型的精度。这显然也忽略了之前发生的所有数据准备工作以及在初次运行之后发生的调整工作,但是通过这种简单的方式,在同一数据集上运行许多不同的模型是很快的。这使您有机会对同一数据尝试许多不同的模型,帮助您找到解决问题的正确方法。当我把我的工作从 PyCharm 转移到 Jupyter 笔记本电脑时,对同一数据运行许多不同的模型变得更加容易。

通过在同一数据集上创建和运行多个模型的练习,可以很容易地用各种各样的参数调整模型。幸运的是,Sklearn 和 Juypter 的结合使得这个游戏非常容易玩。我也没有使用大量的数据集,所以迭代相当快。正是在这一步,我开始看到经营这些模型的艺术方面。要在准确性、速度和可推广性之间取得适当的平衡,需要调整各种模型和数据方面。就过度拟合数据集的倾向而言,我所研究的每一个模型都有不同的弱点,但每一个都有独特的属性来防止这种情况。例如,使用 SVM,您可以调整 C 和 Gamma 级别以直接平衡分类边界,从而提高准确性和泛化能力。

分析文本识别数据

我想在野外发现的数据集上测试我所学的东西,所以我从加州大学欧文分校下载了字母识别数据集以供使用。数据集包含在一个文本文件中,其中包含 16 个代表扫描信件图像的标准化数字特征。然后,它会提供相应的标签。数据集相当简单,试图将这些数据点分类成不同的字母似乎是数据的一个很好的用例。

从这个分析代码中可以发现 在这里

我首先将数据读入 Pandas 数据帧,研究一些数据点,然后将它们作为 NumPy 数组分成要素和标签。除了非常容易从数据帧中分离出数组之外,我还发现了另一个非常酷的 Sklearn 模块preprocessing,它允许我在一行中缩放特性的值。我后来发现,由于我的数据集相当小(~20k 行),预处理最终只为我节省了几秒钟的训练和预测时间,但在处理更大的数据集时,这似乎是一个有用的步骤。最后,我使用 Sklearn 的train_test_split来创建我的训练和测试数据集,分别利用默认的 75%-25%分割。

我的下一步是根据我的问题/数据考虑我想尝试的模型类型。我知道我需要擅长分类的东西,可以在相当多的维度上分离数据,不需要超快,并且有参数来控制拟合。对我来说,SMV 和 Random Forest 符合这里的要求,所以我继续测试它们。

支持向量机

我在 SVM 的第一次测试获得了 94.6%的准确率,训练和预测总共只花了 4.5 秒。我认为这已经很不错了,但我继续调整一些参数,看看是否能提高精度。用kernelC参数做实验,我能够得到超过 97%的准确率。将 C 值提高到 1000 似乎给了我最大的准确性提升,而内核似乎没有太多积极的影响(这是我需要进一步研究的)。内核的另一个奇特之处是,其中一些内核,如 sigmoid 内核,将精确度降低到了 43.44%。我不太精通如何应用“内核技巧”,所以这对于我来说可能比那些了解内核的人更有意思。

Training time: 2.0 s
Prediction time: 1.484 s
Accuracy 0.9718

对于其他数据集,我发现 SVM 非常慢,但由于这个数据集较小且没有时间限制,SVM 证明是一个很好的选择。随着时间的推移,我想做更多的验证,以确保我的模型不会过度拟合,并看看我是否可以通过调整伽马来提高准确性。

随机森林

我想尝试的另一个模型是随机森林。我过去曾使用决策树将数据分类成组,因此一个健壮的随机森林似乎是迎接这一挑战的一大进步。默认的射频分类器返回了 93.36%的准确率,但只用了 0.197 秒,明显快于 SVM。我首先尝试将min_samples_split修改为 25,然而这只会降低我的精确度。不知道为什么,我转向了n_estimators值,我首先将其更新为 200。这使我的准确率提高到了 96.4%,但总的训练/预测时间增加到了 3.5 秒,仍然比 SVM 快。最后,我试着将n_estimators提高到 1000,精度提高了 0.2%,但时间增加了 11 秒。为了改进 RF,我希望花时间调整或加权特征,并研究样本分割如何改进模型。

Training time: 2.998 s
Prediction time: 0.275 s
Accuracy 0.9692

按照我的标准,这两个模型似乎都表现得很好,但每次运行都会引发不同的问题。这些意想不到的结果使得 ML 成为一个有趣的话题,激发了许多人对这个主题的好奇心!

如果可以,应该吗?

在一个以技术为重点的大学校园里,我每天都会听到很多次“我们使用机器学习来做 x ”,通常我认为这是一件好事,但在应用这些工具之前,我们需要更加批判性地思考。我之前提到过 Sklearn“非常容易”使用,在某种程度上,我确实认为“预测”一个结果就像它这么容易有点儿可怕。人们抓住了使用 ML 的想法和它在某些情况下的强大力量,但是他们忘记了考虑正在做出的决策的含义或答案的有效性。仅仅因为我们做到,我们就需要停下来想想我们是否应该做到。

感谢阅读!

生产力例行程序之旅

原文:https://towardsdatascience.com/a-journey-of-productivity-routines-towards-data-science-59a8ccc53690?source=collection_archive---------13-----------------------

这一切都是从我搬到马德里开始的。

“Downtown”, Puebla, Mex. Image credit: Sheila Montes

零点

我从小就渴望知识。学习我感兴趣的东西给了我一种完整的感觉。然而,碰到我对一个主题的理解的极限是许多深刻的内部反思的原因。

我决定攻读“大数据和商业智能”硕士学位,因为我来自一个完全不同的非技术领域。这是一个巨大的挑战。

我心中只有一个明确的目标: 强势完成我的程序。我 几乎感觉自己像一匹眼睛被半遮着的赛马;刚好能看清前面是什么。因为当你下定决心要冲过终点线的时候,其他事情都不重要。

一些灵感

就像重力一样。拥有一个包罗万象的动机变得显而易见,最终,就像重力一样,对像你一样的人有一种明显的吸引力。在那里,我与一位巴拉圭软件工程师合作,他的友谊我至今仍珍视。

黄金法则:找到和你一样的人..或者有引力或者

第一次常规尝试。

拼命学习,爱上田野。

新的国家,新的习惯,新的人,新的旅程开始了。

随着日子一天天过去,你会开始有时间感;日常活动、周末、天气、你什么时候做饭、你什么时候买杂货、锻炼或者给家人打电话。这个清单可以一直列下去,所以我的第一课是:

试错:好的套路是在几次尝试之后出现的

我有一份兼职工作,所以时间优化是关键。

冬天的时候,我在早上 8 点左右醒来,刚好够早喝上一杯咖啡。我可以带着我的 iPad 在上班的路上学习。幸运的是,我的工作是在商学院关注学生的需求,并为即将到来的学术课程提案做研究。第二部分很美好,我可以研究我的笔记,阅读与我的领域相关的论文和文章。

午餐结束后,我返回火车去上课,在那 40 分钟的旅途中,更多的是同样的事情;Ipad 和 10 多张幻灯片。多亏了至少 3 杯咖啡,有时还有红牛,还有溅在我脸上的冷水,我总能在 7 个小时的讲座中保持专注。我在课堂上喝饮料,这样当休息时间开始时,我可以学习,和我的教授交谈,或者和我的同事讨论课程。

夜幕降临时,他们得到了应得的休息。我只是在回家的路上欣赏我的音乐,健身,为第二天做饭,给家人打电话。

环境决定一切

My temple of study in my 4x4 room

第二次常规尝试。

实习,SQL 和绘图。

夏天敲响了我们的门,人们向南方迁移,去西班牙最美丽的地中海海滩。我也在打包行李,但我的目的地是北方,比利牛斯山附近的一个小城市,在那里我在一家小型科技咨询公司实习了 4 个月。

我早上 6 点左右醒来,天气非常适合跑步,城市空无一人。一顿丰盛的早餐,洗个冷水澡,然后去上班。

这些是我学到的最有价值的经验:

  1. 。通常会有很多工作要做,因此保持高效率很有价值
  2. 时间管理至关重要。 我看到项目经理在开 3 分钟的会!
  3. 宁静高于一切 有一天,我陪着首席运营官去拜访一个客户。总经理和其他 4 名高级员工开始对该项目提出许多抱怨和质疑。他认真听取了每个人的意见,然后开始以更健康、更有成效的方式引导会议。每个人都微笑着离开了房间
  4. SQL,你只要学会就行了。 你懂 SQL?我被问到的第一个问题。然后我意识到它可以成为你完成第一课的最好的朋友。

当我到家的时候,已经快 8 点了,仍然是晴朗无云的天空,正准备进行另一次跑步。我在工作中投入了很多精力,但我想做得更多,所以我重拾了童年时擅长的一个老习惯,画画。我买了一个全新的笔记本和木炭,开始在我的工作室画画。周末的时候,我会去公园阅读佩德罗·多明戈斯的《大师算法》。这本书给了我继续学习的力量。佩德罗采用故事的方式来谈论机器学习,指出它的历史、未来以及它如何影响我们的生活。

Image source: Pixabay

第三次常规尝试

课本、MOOCS、播客、Python、SAS 和我缺乏编程技能。

这是 2017 年初,回到马德里,另一场冒险即将开始。这个叫做风险管理。

是的,我在银行工作。

事实证明,这是我经历过的最长的通勤时间,每天坐地铁两个小时甚至更多。

是时候想想如何以富有成效的方式度过这 10 个小时了!

我早上 6:30 左右醒来,去喝咖啡吃早餐。我不得不在 7:45 离开家,这样我可以在 9:00 到达。在我上班的路上,我混合阅读和播客,主要是中型和 KDnuggets 文章。在播客中找到大量与数据科学相关的内容真是太棒了。奇怪的是,除了音乐之外,我从来没有消费过音频内容,所以坐上地铁开始听确实非常令人兴奋,我最喜欢的播客是:

  1. 我和克里斯和维迪亚一起笑得很开心。学习机器学习给我留下了印象,除了被介绍到一个精选的学习机器学习的书籍列表。我认同克里斯的个人经历。
  2. 机器学习指南ML 算法的一些严肃音频学习
  3. O'Reilly 数据显示与像 Paco Nathan 这样的高级嘉宾进行超级有趣的谈话。

SAS 是我在工作中第一次真正接触编程。了解 SQL 的基础知识对我帮助很大。我不想撒谎,每次我在 SAS 编辑器里写东西的时候,我都觉得自己是个坏蛋。我主要做的是编写脚本来自动化报告、风险研究的数据挖掘,以及其他一些很酷的事情,比如试图解决金融世界中的数学悖论。

为什么

我编程的所有这些分析。它们是干什么用的?他们给公司带来价值了吗?可视化足够简单来解释数据吗?

在我进入银行的早期,我的老板找到我,告诉我要阅读大量的文档,主要是为了理解风险管理背后的艺术以及我们做事的原因。他告诉我“为什么”比“如何”重要得多,换句话说,首先要了解业务逻辑,编程可以在过程中学习。

黄金教训:从那以后,我在工作时总是问自己同样的问题。

经过几个月的锻炼和每天的学习后,只剩下非常有限的时间来做基础训练;洗衣服,打扫卫生,吃饭,准备第二天的饭菜。所以我决定减少一点日常活动的强度,一周锻炼两三天,其余时间直接回家学习。

有几天,我呆在办公室里,预订了一间会议室,主要是学习认知课程,阅读福斯特教务长汤姆·福西特的《T2 商业数据科学:你需要了解的数据挖掘和数据分析思维》。

当我深入 DS 时。我意识到 Python 在社区中是多么强大。自从我在硕士时学习 R,我就决定一直学习 Python。

Image credit: Emlie Perron

我从 Udemy 的课程和教材开始,这些帮助我理解了基本原理。虽然我对 Python 代码的美丽感到高兴,但它变得难以理解,可能是因为我的注意力集中在机器学习上。我认为,如果我想掌握 ML 代码,我首先必须真正精通 Python。我猜这只是我太固执了,但是一旦我学会了最基本的,我就直接去买了塞巴斯蒂安·拉什卡的 Python 机器学习。

一本成为我生命中真正宝藏的书。感谢塞巴斯蒂安。

“Python 机器学习”在这篇文章中值得一提。这是一本写得很好的漂亮的书,指导你通过机器学习工作流程的每个方面。方程令人惊讶地解释到最后的细节,所以你可以欣赏数学和代码之间的共生关系。在比你想象的更短的时间内,你将对复杂的算法有深刻的理解

机器学习的夏天。

这是我从克里斯·阿尔邦那里得到的一个想法。关于我的学习,这基本上是我给自己提出的一系列目标。除此之外,我还建立了一些不同的目标,比如 80 小时的游泳和跑步,以更健康的方式改善我的生活。

我有一个很酷的学习组合;阅读“Python 机器学习”和 Coursera 吴恩达课程。这种方法给了我宝贵的见解。我终于开始学习 Python 中的 ML 代码,并将其与 Andrew 完美的教学方式相结合。而且,因为我对数学充满了冒险精神,所以我抓住了统计学习的要素。如果我不理解代码的逻辑,我会回到那些 Udemy 课程和 Python 教科书。

2017 年夏天,我就在那里。在 Google Drive 电子表格中记录我的进展,并记下这样的笔记:

2017 年 6 月 26 日与吴恩达一起复习线性代数。抽认卡很有帮助!**

2017 年 12 月 7 日 “开始领悟感知机背后的数学。对向量和矩阵感到舒适”**

2017 年 7 月 23 日。“周末休息。跟我姑娘吃印度菜!”

2017 年 7 月 31 日。“决策树和随机森林。40 分钟游泳,需要改善身材!”

2017 年 8 月 3 日。“神经网络,迄今为止最复杂的算法。旧笔记学习;EDA、二维分析、正态性检验和假设对比”

2017 年 12 月 8 日。“去巴塞罗那!”

我现在在哪里?

我是一家大型电信公司的全职数据分析师。

一路上,我生活中的事情发生了变化,有更多的时间做这个,更少的时间做那个。

我的学习永远不会停止。

我正在做我自己的数据科学作品集。

“Python 机器学习”依然是我每次有项目的左右手。

总是阅读数据科学

现在我是一个新播客的忠实粉丝;数据框

我最近偶然发现了罗伯特·张和他的博客。太棒了!

我总是知道这些人要说些什么:塞巴斯蒂安·拉什卡、克里斯·阿尔邦、弗朗索瓦·乔莱、法维奥·瓦斯奎兹、西拉杰·对手、克里斯·奥拉赫、吴恩达、艾伦·唐尼、李飞飞、伊恩·古德菲勒

我仍然尽可能参加每一个数据科学聚会

现在,我开始写作了。希望一切顺利。

我想感谢 Amy Kelly 审阅我的帖子并给我反馈

外行人的算法丛林指南

原文:https://towardsdatascience.com/a-lay-persons-guide-to-the-algorithm-jungle-2bc77dc30faf?source=collection_archive---------16-----------------------

这是一系列文章中的第三篇,旨在使机器学习对那些没有受过技术培训的人来说更容易理解。以前的文章介绍了机器学习的概念,并讨论了学习过程的一般工作方式。你可以在这里开始系列。

这一期描述了许多常用的机器学习算法家族。这个列表并不详尽,主要集中在两类分类算法上(我最熟悉的)。描述旨在简洁而直观,面向不熟练或没有经验的读者。提供了每个算法家族的简要描述和说明,以及每个家族的一些算法示例。为这些算法的更详细的数学处理和发现更多,提供了进一步的阅读清单。

朴素贝叶斯分类器

朴素贝叶斯分类器是基于相当简单的原理的分类算法家族。这些算法学习哪些输入属性具有与感兴趣的类相关联的高概率和低概率,然后基于这些属性概率计算实例是否属于某个类。例如,如果机动车辆有两个轮子,长度在 1900 毫米和 2500 毫米之间,宽度在 700 毫米和 1000 毫米之间,则可以归类为摩托车。

朴素贝叶斯分类器之所以被称为朴素贝叶斯分类器,是因为统计假设每个变量相互独立,尽管在实践中很少出现这种情况,例如车轮的数量通常与宽度相关。

通常,这些算法需要相对少量的数据来估计参数,这被认为是一个优点。然而,由于底层数学模型的简单性,这些算法通常优于其他算法。

这类算法最早也是最常见的用途之一是文本过滤。在垃圾邮件过滤中,可以基于在电子邮件中发现的某个单词、单词组合或随机文本串将电子邮件分类为垃圾邮件。以类似的方式,这些算法可以用于将文档分类到不同的主题类别中。

有许多替代算法试图克服朴素贝叶斯分类器的独立性假设。最有力的例子之一是平均一相依估计量(AODE),它通常可以产生比朴素贝叶斯更低的误差水平,而只需要适度的额外计算能力。

决策树算法

这是一个使用决策树原理运行的大算法家族,并且已知在许多情况下非常成功。这些算法根据基于实例属性做出的一系列决策(分支)将实例分类到某个类(叶)中。

例如,下图是一个简单的决策树算法,用于根据三个输入(性别、年龄和船上兄弟姐妹和配偶的数量)确定泰坦尼克号上的乘客发生了什么。每片叶子下面的数字代表存活的概率和属于该类的实例的百分比:

Example decision tree for survival of Titanic passengers

决策树算法使用自上而下的归纳学习,通常被称为贪婪算法(因为它总是决定获取最大份额)。从每个类(叶)开始,根据输入数据是否与该类相关联,将输入数据分成子集。然后,在称为递归划分的过程中,在每个子集(或决策节点)上重复这一过程。当算法到达对分割数据没有进一步价值的决策节点时,学习停止。在我们的泰坦尼克号的例子中,算法将在男性和女性之间分割数据,然后它将确定分割女性数据没有进一步的价值。然后,它将确定首先根据年龄,然后根据 sibsp,拆分男性数据是有价值的。

决策树算法是健壮的,易于解释,并且可以很好地处理大型数据集。然而,有许多问题它们无法解决,因为底层数据太复杂了。这些算法还可能倾向于从训练数据中创建过于复杂的树,这些树不能很好地概括,最终会过度拟合数据。在某些情况下,可以回过头来简化树。这就是所谓的修剪

基于决策树方法的算法示例包括装袋树随机森林提升树

支持向量机

支持向量机是基于多维线性代数原理的非概率算法。这些算法非常适合将样本分为两类的二元问题,并且在输入数据的结构有限时特别有用。

SVM 算法获取数据集中实例的属性,并将这些属性转换成 n 维空间中的向量,其形式为 X = (x1,x2,x3,…,xn)

然后,该算法将尝试计算 n 维空间中的超平面或“线”,该超平面或“线”以可能的最大距离分隔两个类别。

下面是一个简单的二维例子。在本例中,位于虚线边缘的向量称为支持向量,用于计算最大分离线,用实线标记。

现代 SVM 算法能够通过挖掘文本串并识别可用于对样本进行分类的文本子集和家族来确定维度和属性的数量。维度,也就是向量长度,可以是数百甚至数千。对这种数据执行计算的复杂性可以非常容易且快速地超越可用计算能力的极限。然而,现代 SVM 算法利用了一个核函数,可以大大降低问题的复杂性。

当训练集不容易线性分离(即,不可能识别分离的超平面)时,线性 SVM 的多种发展已经导致了许多可选方案。例如,软边界可用于某些数据可能被错误分类的情况。最近也有一些算法发展了 SVM 原理,使其适用于两个以上的类,以及非线性和回归问题。

感知器

与 SVM 类似,感知器算法通过将输入属性转换成形式为 X = (x1,x2,x3,…,xn) 的向量来运行。对于训练集中的每个实例,该算法计算权重向量 W = (w1,w2,w3,…,wn) 以形成线性预测函数 W.X,该函数正确预测所有先前的训练集实例。

与大多数其他算法不同,感知器执行在线学习,这意味着它逐个分析每个训练实例,并在处理每个实例后更新权重向量 W,而不是必须先处理所有实例。与其他算法相比,这可以更加高效和精简。

然而,如果训练集是线性可分的,感知器算法将仅收敛于权重向量 W。如果不存在将训练数据中的正样本与负样本分开的超平面,则该算法将不能收敛到将正确分类所有训练集样本的 W 上。

感知器的变体可以用来处理多类问题,甚至非线性问题。袖珍算法是一个潜在有用的变体,它处理非线性可分离的训练数据。在处理每个训练实例时,该算法会将迄今为止看到的最佳解决方案保存在“口袋”中。在每个实例中,算法返回“口袋”解,而不是最后一个解,这允许它迭代到训练集上误差最小的解。

神经网络

神经网络算法是目前使用的最复杂的算法之一。它们模仿大脑中神经元的结构,并且它们被设计成以与大脑相似的方式学习。它们通常没有预先设定任何规则,而是通过处理示例来学习。

图像识别是经常使用神经网络的一个常见例子。例如,可以向网络提供狗的图像集合,并告知每只狗的品种。然后,它可以学习狗图像的特征,这允许它预测给它的新图像的品种。

Hey computer — here’s some nice doggy pictures!

人们很自然会问计算机如何模拟神经元网络。实际上,“神经元”之间的信号通常是某种形式的数字,而“神经元”本身是某种数学函数,它处理它接收的信号并吐出新的数字——所以实际上这些算法在数学上模拟了神经元网络的信号到节点的行为。

进一步阅读

我在这里仅仅触及了表面,但是我已经涵盖了你可能听说过的分类算法的主要类别。如果你想真正进入令人愉快的算法世界,比如 BLASTnautySaucyMersenne Twister (是的,它们都是算法名称),这里有几个地方你可以看看。请自担风险,尤其是如果你不是数学家、统计学家或计算机科学家。

  1. **机器学习介绍,Ethem Alpaydin,ISBN 0262028182。这是一本非常好的关于机器学习的宽泛的文本,涵盖了广泛的主题。它是大学课程中非常常见的教材。
  2. **机器学习:使数据有意义的算法的艺术和科学,彼得·弗拉克,ISBN 1107422221。这是一个非常实际的话题,用具体的例子来说明算法是如何运作的。
  3. **机器学习基础,Mehryar Mohri 等人,ISBN 026201825X。这本书理论性很强,重点是关键概念的证明。它还涵盖了几种常见的 ML 算法的数学基础。
  4. **机器学习,概率视角,凯文·P·墨菲,ISBN 0262018020。这本书很好地融合了理论(尤其是概率和统计)和实践,有算法代码的例子和大量插图。
  5. **信息论、推理和学习算法,大卫·麦凯,ISBN 0521642981。这本书的重点是科学和工程目的的编码。然而,在填字游戏和生物进化的算法上有一些有趣的消遣。
  6. **统计学习、数据挖掘、推理和预测的要素,特雷弗·哈斯蒂,ISBN 0387848576。一个学术文本,侧重于将与机器学习相关的各种概念结合到一个统计框架中。
  7. **信息检索简介,克里斯托弗·D·曼宁等,ISBN 0521865719。这本书集中在与文本分类和聚类相关的应用。

下一篇文章将关注如何衡量预测算法的有效性。这里读一下*。***

最初我是一名纯粹的数学家,后来我成为了一名心理计量学家和数据科学家。我热衷于将所有这些学科的严谨性应用到复杂的人的问题上。我也是一个编码极客和日本 RPG 的超级粉丝。在LinkedInTwitter上找我。

计算机视觉外行指南

原文:https://towardsdatascience.com/a-laymans-guide-to-computer-vision-39b9291e5278?source=collection_archive---------2-----------------------

我今天刚刚在 arXiv 上发现了这个新发表的研究,我认为它非常酷。这是对机器学习未来的迷人一瞥,虽然我已经期待了一段时间,但最终看到一些坚实的研究是惊人的!它基本上是使用遗传算法进化出一串卷积神经网络来创建一个用于图像分类的最优网络。解释我到底在说什么,继续读!

A bunch of animals.

假设我们收集了各种动物的照片,我们想知道每张照片里都有什么。借助我们自己的眼睛、大脑和记忆,我们能做的最基本的事情就是看一张照片,看到它是一只狗的照片,并把它贴上“狗”的标签。对于一台电脑来说,完成同样的任务是一个非常棘手的过程。

几十年前,计算机科学家试图通过构建一个配方来检测个体特征,并将它们放在一起预测照片所描绘的内容,从而以编程方式识别图像。例如,狗有毛皮,长鼻子,大眼睛,长舌头,长尾巴,等等。猫的皮毛较少,脸较圆,眼睛较小,鼻子较平。如果你在照片中找到这些特征,那一定是猫/狗/袋鼠。正如您可能想象的那样,这种技术几乎不起作用。如果照片是从另一个角度拍摄的,这个食谱就没有意义了。每只动物都需要自己特定的食谱来检测,不同的品种或蓬头垢面的宠物将无法识别,它的规模也不太好。这项技术开发费用昂贵,而且在实践中也没有用。

A car hiding in a tree

快进十年左右,科学家们试图将这个过程概括一下。他们将检测圆形,而不是检测鼻子。他们将检测线条或特定图案,而不是皮毛。然后,这些特征的组合将被用于更具预测性。这种方法效果更好,但它仍然需要手动编程来检测特定的形状和特征。它也不总是成功的,有时会令人印象深刻地失败。

然后在 1998 年,一种叫做卷积神经网络(CNN)的全新技术问世了,它试图模仿我们的大脑处理图像的方式。取代手动选择要检测的特征,这些特征将由计算机通过输入大量图像和正确的标签来自动“学习”。然后计算机程序会计算出哪些特征是最重要的,并用它们对照片进行分类。这些特征基本上是简单的数学滤波器,图像通过这些滤波器将其结构简化为关键部分。通过使用多层特征,可以检测更复杂的对象。下面,你可以看到这样一个程序是如何工作的。在第一层中,检测基本形状。在第二种情况下,这些形状被组合起来构建更复杂的形状,比如眼睛和鼻子。最后,在第三层,这些被组合成更高层次的物体,如人脸!

Feature map in a modern CNN

虽然 1998 年开发的 CNN 非常成功,特别是在诸如手写识别等任务方面,但它确实需要巨大的处理能力和大量的训练数据,这两项要求在 1999 年无法轻易满足。因此,在十多年的时间里,当人们继续手动定义特性时,这项技术实际上被搁置了。

最终在 2012 年,大学的研究人员。创建了 AlexNet 。它使用了与原始 CNN 相同的技术,做了一些改动,但是使用了更多的图片。AlexNet 不是几千幅,而是在 1500 万幅图像上进行训练。它不只是几个过滤器,而是计算出数百个。它一发布就把竞争对手扫地出门了。所有程序员现在要做的就是设计网络的基本流程,选择构建模块,神经网络会解决剩下的问题。

在 30 年的时间里,计算机视觉技术进步缓慢,但 AlexNet 改变了这一切。在 2012 年之前,每 4 张图像中就有 1 张被错误识别。AlexNet 将这一比例降低到每 7 天 1 次。从那以后,每 25 张图片中就有 1 张是错误的(例如在谷歌的 Inception 网络中)。那精准度其实比绝大多数人类都强!这就引出了这篇论文。

Google’s Inception V3 network. State-of-the-art in image classification, for now.

过去五年的所有改进都归结于对神经网络的轻微调整,要么通过添加新的数学函数,改变滤波器的顺序和组合,要么增加滤波器捕捉的细节水平。这些“宏参数”可以不断调整以获得最佳结果,但它们需要一点直觉才能正确。本文中的研究人员决定将最后一步自动化。

Relevant XKCD (CC-by-SA-NC Randall Munroe)

他们没有繁琐地设计一个新网络,手动组合不同的功能和过滤器,而是简单地给遗传机器学习算法一个任务——最小化识别误差——并给它提供积木。然后他们让它在一台高速电脑上运行几周。它继续,建立一个基本的神经网络,并计算其图像识别的误差。然后,它进行一些更改,并计算一个新的错误。如果误差较低,则采用该设计,以此类推。事实上,它的改进很像生物进化,通过突变、繁殖和生存。

如果你真的一直读到这篇很长的帖子的结尾,那么感谢你的阅读!毫无疑问,你仍然会奇怪为什么我觉得这很酷。原因是这篇论文不仅揭示了我们(嗯……聪明的男人和女人)在人工智能方面已经走了多远,而且揭示了我们的世界在未来将如何被它塑造。我们正处于这样一个时刻,像我这样的笨猴子可以玩弄困扰数千研究人员几十年的技术。一个拥有 1000 英镑并且事先没有人工智能知识的人可以实现过去花费数百万研究小时的事情。我们所需要的只是一个数据集和一个聪明的想法,我们可以让人工智能做艰苦的工作!我认为这既令人印象深刻又相当可怕!我们还没有到那一步,但总有一天人工智能会取代创造它们的计算机科学家,所以现在就开始为未来做计划是明智的。

在不太遥远的未来,我可以想象一个场景,任何想要制作自己电影的人都可以简单地编写一个带有一些线索和风格元素的电影剧本,将其传递给人工智能,然后人工智能自动创建配乐,合成语音,指导一系列 3d 生成的模型,添加一些特殊效果,并呈现一部完整的照片级逼真的电影。如果有些地方不太对劲,你可以进去调整一下。当胶片相机在 19 世纪 80 年代被发明时,人们没有预测到它会变得如此普遍。当电吉他被发明出来的时候,工程师们尽了最大的努力去消除它所造成的失真,然而今天的摇滚乐就是建立在这样的基础上的。关于人工智能的未来,我很可能是错的,但我迫不及待地想看看会发生什么!希望不是天网

This film was written by an LSTM neural network

延伸阅读,如果你感兴趣:

  • 安德烈·卡帕西的精彩演讲我的大部分素材都是从那里获得的。
  • 费的 TED 演讲,他建立了 ImageNet 数据库
  • 人工智能实验 由谷歌
  • Siraj Raval 的过顶 Youtube 频道
  • 两分钟论文 ,里面展示了一些最酷的人工智能东西!
  • 克里斯·奥拉的博客 关于神经网络

动物照片:

  • 猫鼬: CC-0 迈克·贾斯敏·范登博加尔德
  • 狗和马: CC-0 希拉里·哈利维尔
  • 豹子: CC-0
  • 鹅: CC-0
  • 猕猴:公共领域
  • 鸭子: CC-0 马丁·迪金森
  • 蜘蛛: CC-by-SA 托马斯·沙汉
  • 捷豹: CC-by-SA-ND 瓦莱丽
  • 狗: CC-0 Pixabay
  • 捷豹: CC-0 突击者摄影

随意分享&在 知识共享许可 下修改这篇文章,如果有需要修改的地方,请告诉我!

使用 TensorFlow 进行线性回归的逐行外行指南

原文:https://towardsdatascience.com/a-line-by-line-laymans-guide-to-linear-regression-using-tensorflow-3c0392aa9e1f?source=collection_archive---------2-----------------------

本文是使用 TensorFlow 进行线性回归的逐行外行指南。如果你读这篇文章有困难,考虑在这里订阅中级会员!

线性回归是机器学习之旅的一个良好开端,因为它是一个非常简单的问题,可以通过流行的模块来解决,如 scikit-learn 包。在本文中,我们将讨论使用 TensorFlow 实现线性回归的逐行方法。

linear regression equation

查看上面的线性回归方程,我们首先构建一个图形,通过多次迭代学习斜率( W )和偏差( b )的梯度。在每次迭代中,我们的目标是通过比较输入 y 和预测的y来缩小差距(损失)。也就是说,我们想要修改 Wb ,这样 x 的输入就会给我们想要的 y 。求解线性回归也称为寻找最佳拟合线或趋势线。

生成数据集

[第 1、2、3 行]

import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt

在本文中,我们将使用一些流行的模块,如 numpy 、 tensorflow 和 matplotlib.pyplot 。让我们导入它们。

[第 6、7 行]

x_batch = [np.linspace](https://docs.scipy.org/doc/numpy-1.15.0/reference/generated/numpy.linspace.html)(0, 2, 100)
y_batch = 1.5 * x_batch + np.random.randn(*x_batch.shape) * 0.2 + 0.5

首先,我们从生成数据集开始,即 xy 。你可以把 xy 中的每个值想象成图上的点。在第 6 行中,我们希望 numpy 生成 100 个值在 0 和 2 之间的点,均匀分布。结果是一个存储在x_batch中的 numpy 数组。类似地,我们还想随机生成 y ,这样它的梯度为 1.5 ( W )并且使用np.random.randn()具有某种形式的随机性。为了让事情变得有趣,我们将 y 轴截距 b 设置为 0.5。

【第八行】return x_batch, y_batch

我们返回 numpy 数组x_batchy_batch

plt.scatter(x_batch, y_batch) — this is our starting point

这就是generate_dataset()的剧情样子。请注意,从视觉上看,这些点形成了一条从左下方到右上方的趋势线,但没有穿过原点(0,0)。

构建图表

[第 2 行和第 3 行]

x = tf.placeholder(tf.float32, shape=(None, ), name='x')  
y = tf.placeholder(tf.float32, shape=(None, ), name='y')

接下来,我们构建张量流图,帮助我们计算 Wb 。这在函数linear_regression()中完成。在我们的公式y = Wx + b中, xy 是表示为 TensorFlow 的占位符的节点。将 xy 声明为占位符意味着我们需要在以后传入值——我们将在下一节重新讨论这个问题。请注意,我们现在仅仅是构建图形,而不是运行它(TensorFlow 有惰性评估)。

tf.placeholder的第一个参数中,我们将数据类型定义为 float 32——占位符中常见的数据类型。第二个参数是设置为None的占位符的形状,因为我们希望它在训练期间确定。第三个参数让我们设置占位符的名称。

占位符仅仅是一个变量,我们将在以后的某一天把数据赋给它。它允许我们创建我们的操作和构建我们的计算图,而不需要数据。在 TensorFlow 术语中,我们通过这些占位符将数据输入图表。

参考:https://learningtensorflow.com/lesson4/

【第 5 行】with tf.variable_scope(‘lreg’) as scope:

这一行为第 6 行和第 7 行中的变量定义了变量范围。简而言之,变量作用域允许以层次方式命名变量,以避免名称冲突。详细地说,它是 TensorFlow 中的一种机制,允许在图形的不同部分共享变量,而无需四处传递对变量的引用。请注意,尽管我们在这里没有重用变量,但是恰当地命名它们是一个很好的做法。

with tf.name_scope("foo"):
    with tf.variable_scope("var_scope"):
        v = tf.get_variable("**var**", [1])
with tf.name_scope("bar"):
    with tf.variable_scope("var_scope", reuse=True):
        v1 = tf.get_variable("**var**", [1])
assert v1 == v
**print(v.name)   # var_scope/var:0
print(v1.name)  # var_scope/var:0**

在上面的代码中,我们看到变量(" var ")被重用并被断言为真。要使用同一个变量,只需调用[tf.get_variable](https://www.tensorflow.org/api_docs/python/tf/variable_scope)(“var”, [1])

【第六行】w = tf.Variable(np.random.normal(), name=’W’)

与占位符不同, W 被定义为一个[tf.Variable](https://www.tensorflow.org/api_docs/python/tf/Variable),其值随着我们训练模型而变化,每次都以较低的损失结束。在第 10 行,我们将解释“损失”是什么意思。现在,我们使用[np.random.normal()](https://docs.scipy.org/doc/numpy-1.15.0/reference/generated/numpy.random.normal.html)设置变量,以便它从正态(高斯)分布中抽取一个样本。

tf。变量—一个变量在调用*run()*时维护图中的状态。您通过构造类*Variable*的实例向图中添加一个变量。

*Variable()*构造函数需要变量的初始值,可以是任何类型和形状的*Tensor*。初始值定义了变量的类型和形状。构造后,变量的类型和形状是固定的。可以使用赋值方法之一来更改该值。

参考:https://www.tensorflow.org/api_docs/python/tf/Variable

请注意,即使现在定义了变量,也必须在使用该值运行操作之前显式初始化它。这是惰性求值的一个特性,我们将在后面进行实际的初始化。

这里 W 真正做的是找到我们最佳拟合线的梯度。之前,我们使用 1.5 的梯度生成数据集,因此我们应该期望经过训练的 W 接近这个数字。为 W 选择起始数字有些重要——想象一下,如果我们可以“随机”选择 1.5,工作就完成了,不是吗?差不多吧…

因为我们的主题是寻找线性回归中的最佳梯度,我需要指出的是,无论我们在哪里初始化 W ,我们的损失函数将总是产生一个最小损失值。这是由于我们的损失函数, Wb 的凸性,当我们在这样的图表中绘制它们时。换句话说,这个碗形图形让我们可以确定最低点,不管我们从哪里开始。

One global minimum

然而,对于更复杂的问题,情况并非如此,在这些问题中存在多个局部最小值,如下所示。选择一个不好的数字来初始化你的变量会导致你的梯度搜索陷入局部极小值。这阻止了你达到具有较低损失的全局最小值。

Multiple local minima with one global minimum

研究人员想出了替代的初始化方法,例如 Xavier 初始化,试图避免这个问题。如果您想使用它,请随意使用:

tf.get_variable(…, initializer=[tf.contrib.layers.xavier_initializer()](https://www.tensorflow.org/api_docs/python/tf/contrib/layers/xavier_initializer))

【第 7 行】b = tf.Variable(np.random.normal(), name=’b’)

除了 W 之外,我们还要训练我们的 bias b 。如果没有 b ,我们的最佳拟合线将总是穿过原点,而不会学习 y 轴截距。还记得 0.5 吗?我们也需要了解这一点。

【第九行】y_pred = tf.add(tf.multiply(w, x), b)

在分别定义了 xyW****、之后,我们现在准备将它们放在一起。为了实现公式y = Wx + b,我们首先使用[tf.multipl](https://www.tensorflow.org/api_docs/python/tf/multiply)ywx相乘,然后使用[tf.add](https://www.tensorflow.org/api_docs/python/tf/math/add)将变量b相加。这将执行逐元素的乘法和加法,从而产生张量y_predy_pred代表预测的 y 值,正如您可能会怀疑的那样,预测的 y 一开始会很糟糕,并且与生成的 y相差甚远,类似于占位符或变量,您可以随意为其命名。

【第 11 行】loss = tf.reduce_mean(tf.square(y_pred — y))

Mean Squared Error (MSE)

计算完y_pred,我们想知道预测的 y 与我们生成的 y 有多远。为此,我们需要设计一种方法来计算“差距”。这种设计被称为损失函数。这里,我们选择了均方误差(MSE) 又名 L2 损失函数作为我们的“评分机制”。还有其他流行的损失函数,但我们不包括它们。

为了理解我们的 MSE 实现,我们首先使用y_pred — y找到y_predy的 100 个点之间的差异。接下来,我们通过对它们求平方([tf.square](https://www.tensorflow.org/api_docs/python/tf/square))来放大它们的差异,从而使差异变大(很多)。哎哟!😝

向量大小为 100,我们现在有一个问题—我们如何知道这 100 个值是否代表一个好的分数?通常分数是决定你表现如何的一个数字(就像你的考试一样)。因此,为了得到一个单一的值,我们利用[tf.reduce_mean](https://www.tensorflow.org/api_docs/python/tf/reduce_mean)找到所有 100 个值的平均值,并将其设置为我们的loss

【第 13 行】return x, y, y_pred, loss

最后但同样重要的是,我们在构造它们之后返回所有的 4 个值。

计算图表

有了generate_dataset()linear_regression(),我们现在准备运行程序,并开始寻找我们的最佳梯度 W 和偏差 b

[第 2、3 行]

x_batch, y_batch = generate_dataset()
x, y, y_pred, loss = linear_regression()

在这个run()函数中,我们首先调用generate_dataset()linear_regression()来得到x_batchy_batchxyy_predloss。向上滚动查看这两个功能的解释。

[第 5、6 行]

optimizer = tf.train.GradientDescentOptimizer(0.1)
train_op = optimizer.minimize(loss)

然后,我们定义优化器并要求它最小化图中的损失。有几个优化器可供选择,我们方便地选择了梯度下降算法并将学习率设置为 0.1。

我们不会深入优化算法的世界,但简而言之,优化者的工作是最小化(或最大化)你的损失(目标)函数。它通过在每次运行时向最优解的方向更新可训练变量( Wb )来实现这一点。

调用最小化函数计算梯度并将它们应用于变量——这是默认行为,您可以使用参数var_list随意更改。

【第八行】with tf.Session() as session:

在我们构建图形的前面部分,我们说过张量流使用惰性求值。这实际上意味着只有在会话开始时才计算图形。这里,我们将会话对象命名为session

【第 9 行】session.run([tf.global_variables_initializer()](https://www.tensorflow.org/api_docs/python/tf/initializers/global_variables))

然后我们通过初始化我们要求变量保存的所有值来启动我们的第一个会话。由于惰性求值,在第一次构建图形时,变量如 W ( w = tf.Variable(np.random.normal(), name=’W’))没有初始化,直到我们运行这一行。更多解释见本。

【第 10 行】feed_dict = {x: x_batch, y: y_batch}

接下来,我们需要提出 feed_dict ,它本质上是session.run()的一个参数。feed_dict是一个字典,其关键字为tf.Tensortf.placeholdertf.SparseTensorfeed_dict参数允许调用者覆盖图中张量(标量、字符串、列表、numpy 数组或 tf.placeholder,例如 xy )的值。

在这一行中, xy 是占位符, x_batchy_batch 是生成的值,准备在session.run()期间填充占位符。

【第 12 行】for i in range(30):

在初始化变量并使用feed_dict为占位符准备值之后,我们现在进入脚本的核心,定义我们想要“调整”/“训练”权重( W )和偏差( b )的次数。我们在一个完整周期中遍历训练数据的次数( xy )也称为时期/训练步骤。一个完整的循环也被定义为一个前馈和一个反向传播。

前馈时,我们传入 xwb 的值,得到预测的 y 。这将计算用数字表示的损失。由于该图的目标是最小化损耗,优化器将执行反向传播以“调整”可训练变量( Wb ),以便下一次我们执行前馈(在另一个时期)时,损耗将会降低。

我们这样向前向后循环 30 次。请注意,30 是一个超参数,您可以自由更改它。还要注意,更多的纪元=更长的训练时间。

[第 13 行]

session.run(train_op, feed_dict)

现在,我们准备通过调用获取的session.run()feed_dict来运行我们的第一个纪元。在这里,session.run()评估提取的每个张量(train_op)并用feed_dict中的值替换相应的输入值。

**fetches**:单个图形元素、图形元素列表或其值为图形元素或图形元素列表的字典(参见run的文档)。

session对象调用run()方法时,在幕后发生的事情是,您的代码将运行图的必要部分(节点),以计算提取中的每个张量。由于train_op指的是optimizer调用方法minimize(loss),那么将通过调用损失函数来计算loss,损失函数又触发y_predyWxb进行计算。

下面是来自 TensorFlow 文档的代码。你可以看到提取可以是单例、列表、元组、命名元组或字典。在我们的例子中,我们使用 feed_dict 作为 dictionary 类型的参数。

fetches in session.run()

print(i, “loss:”, loss.eval(feed_dict))

【第 14 行】print(i, “loss:”, loss.eval(feed_dict))

这一行打印出每个时期的损失。在左侧,您可以看到每个时期的损失值都在减少。

使用loss.eval()feed_dict作为参数计算损失值。

[第 16、17 行]

print('Predicting')
y_pred_batch = session.run(y_pred, {x : x_batch})

30 个纪元后,我们现在有一个训练有素的 Wb 供我们执行推理。与训练类似,可以使用session.run()对相同的图进行推理,但这一次,获取将是 y_pred 而不是 train_op ,我们只需要输入 x 。我们这样做是因为 Wb 已经被训练过,并且预测的 y 可以仅用 x 来计算。注意在tf.add(tf.multiply(w, x), b)中,没有 y

到目前为止,我们已经声明了 3 个session.run(),所以让我们回顾一下它们的用法,因为session.run()是我们运行操作和评估图中凸榫的命令。第一次我们做的是初始化我们的变量,第二次在训练期间传递我们的 feed_dict,第三次运行预测。

[第 19–23 行]

plt.scatter(x_batch, y_batch)
plt.plot(x_batch, y_pred_batch, color='red')
plt.xlim(0, 2)
plt.ylim(0, 2)
plt.savefig('plot.png')

我们用生成的x_batchy_batch以及我们预测的线(用x_batchy_pred_batch)绘制图表。最后,我们有我们的预测线很好地画在下面。花点时间回顾一下我们的第一个神经网络如何计算出梯度和 y 截距,并欣赏机器学习的魔力!

plt.plot(x_batch, y_pred_batch) — we drew the line of best fit

[第 25、56 行]

if __name__ == "__main__":
 run()

不需要解释——你可以做得更好。😉

最后

投身机器学习并不容易。有人从理论开始,有人从代码开始。我写这篇文章是为了让自己理解基本概念,并帮助那些正在接触机器学习或 TensorFlow 的人入门。

你可以在这里找到最终代码。如果您发现任何错误,并希望提出建议或改进,请随时发表评论或发 tweet me 。🙏

特别感谢莱米、任杰和羽心阅读本文初稿。你是最棒的!💪

一个长期的数据科学路线图不会帮助你在几个月内成为专家

原文:https://towardsdatascience.com/a-long-term-data-science-roadmap-which-wont-help-you-become-an-expert-in-only-several-months-4436733e63ff?source=collection_archive---------0-----------------------

成为数据科学家的几点思考?这既不容易也不快速,需要很多努力,但如果你对数据科学感兴趣,这是值得的。

不时有人问我:如何成为一名数据科学家?有哪些课程是必须的?需要多长时间?你是怎么成为 DS 的?我已经回答过这个问题几次了,所以在我看来,写一篇文章可能是一个帮助有抱负的数据科学家的好主意。

关于我

我在 MSU 经济学院获得了硕士学位,并在 ERP 系统实施领域做了大约 4 年的分析师/顾问。它包括与客户交谈,讨论他们的需求并使之形式化,编写文档,向程序员解释任务,测试结果,组织项目和许多其他事情。

但这是一份压力很大的工作,有很多问题。更重要的是,我并不真的喜欢它。尽管我喜欢和数据打交道,但大多数事情并不鼓舞人心。因此,在 2016 春夏,我开始寻找其他东西。我在精益六适马拿到了绿带,但是附近没有机会。有一天我发现了大数据。经过几周的谷歌搜索和阅读大量文章,我意识到这可能是我梦想的职业。

我辞职了,8 个月后,我在一家银行获得了第一份数据科学家的工作。从那以后,我在几家公司工作过,但我对数据科学的热情仍然很高。我已经完成了 ML 和 DL 的几门课程,做了几个项目(如一个聊天机器人或一个数字识别 app ),参加了许多 ML 比赛和活动,在 Kaggle 上获得了三枚银牌等等。因此,我有一些学习数据科学和作为数据科学家工作的经验。当然,我还有很多东西要学,还有很多技能要掌握。

放弃

这篇文章包含了我的观点。有些人可能不同意他们的观点,我想指出,我不想冒犯任何人。我认为任何希望成为数据科学家的人都必须投入大量的时间和精力,否则他们会失败。声称你可以在几周或几个月内成为 ML/DL/DS 专家的课程或 MOOCs 并不完全真实。你可以在几周/几个月内获得一些知识和技能。但是如果没有大量的练习(这不是大多数课程的一部分),你就不会成功。

你确实需要内在的动力,但是,更重要的是,你需要自律,这样你才能在动力消失后继续工作。

让我再重复一遍——你需要自己做事情。如果你问最基本的问题,甚至没有尝试使用 Google/StackOverflow 或思考几分钟,你将永远无法赶上专业人士。

在我参加的大多数课程中,只有大约 10-20%的人完成了课程。大多数辍学者没有奉献精神或耐心。

谁是数据科学家?

有很多图片展示了数据科学家的核心技能。就本文的目的而言,它们都是好的,所以让我们看看这一个。这表明你需要数学和统计,编程和开发,领域知识和软技能。

太多了!怎么可能知道这一切?嗯,真的要花很多时间。但是这里有一个好消息:没有必要什么都知道。

2018 年 10 月 21 日在 Yandex 有一场有趣的讲座。据说有许多类型的专家,他们拥有上述技能的不同组合。

数据科学家应该在中间,但事实上他们可以在三角形的任何部分,在三个领域中的任何一个都有不同的层次。

在本文中,我将谈论通常被认为的数据科学家,即那些能够与客户交流、执行分析、构建模型并交付模型的人。

转行?这意味着你已经有了!

有人说转行很难。虽然这是真的,有一个职业可以转换,意味着你已经知道一些东西。也许你有编程和开发的经验,也许你在数学/统计领域工作过,或者你每天都在磨练你的软技能。最起码你在你的领域有专业知识。所以总是试着利用你的优势。

来自 Reddit 的路线图

事实上将会有两个路线图:)

第一个来自 Reddit,来自这个话题:

首先,读他妈的哈斯提,提白拉尼,还有谁。第 1-4 章和第 7-8 章。如果你不明白,继续读,直到你明白。

如果你愿意,你可以读这本书的其余部分。你可能应该知道,但我会假设你都知道。

以吴恩达的 Coursera 为例。用 python 和 r 做所有的练习,确保所有的答案都是一样的。

现在忘掉这些,去读深度学习的书吧。将 tensorflow 和 pytorch 放在一个 Linux 盒子上,运行示例,直到得到它。做 CNN 和 rnn 的事情,只是前馈神经网络。

一旦你完成了所有这些,就可以上 arXiv,阅读最新的有用文章。文献每隔几个月就有变化,所以要跟上。

那里。现在你可能在大多数地方都能被雇佣。如果你需要简历填充,那么一些 Kaggle 比赛。如果有调试问题,请使用 StackOverflow。有数学题,多读。如果你有人生问题,我不知道。

从其中一条评论来看:

直到不够为止。。想出一个没有训练数据的新问题,并想出如何收集一些数据。学会写一个刮刀,然后做一些标注和特征提取。在 EC2 上安装所有东西并自动化它。编写代码,随着新数据的出现,在生产中不断地重新训练和重新部署您的模型。

虽然简短、苛刻且非常困难,但这份指南非常棒,它会让你达到一个可雇佣的水平。

当然,数据科学还有许多其他方法,所以我将提供我的方法。它并不完美,但它是基于我的经验。

我的路线图

有一项技能会让你走得很远。如果你还没有,我敦促你开发它。这个技能是…形成思想,搜索信息,找到它并理解它。说真的!有些人无法表达思想,有些人无法找到最基本问题的解决方案,有些人不知道如何正确创建谷歌查询。这是一个基本的、必须的技能,你必须完善它!

  1. 选择一门编程语言,学习它。通常会是 Python 或者 r,我强烈推荐选择 Python。我不会列出原因,因为已经有很多关于 R/Python 的争论,我个人认为 Python 更加通用和有用。花 2-4 周时间学习语言,这样你就可以做一些基本的事情。对所使用的库有一个大致的了解,比如 pandas/matplotlib 或者 tydiverse/ggplot2。
  2. 通过安德鲁·吴的 ML 课程。它是旧的,但它给了一个伟大的基础。在 Python/R 中完成任务可能是有用的,但不是必需的。
  3. 现在再选一门好的 ML 课程(或几门)。对于 R 用户我推荐 Analytics Edge ,对于 Python 用户— mlcourse.ai 。如果你懂俄语,Coursera 上的这个课程也很棒。在我看来 mlcourse.ai 是这三个里面最好的。为什么?它提供了很好的理论和一些艰难的任务,这可能已经足够了。然而,它也教人们参加 Kaggle 比赛,并制作独立的项目。这对于练习来说非常有用。
  4. 学习 SQL。在大多数公司中,数据都保存在关系数据库中,所以你需要能够得到它。让自己习惯使用选择,分组,CTE,连接和其他东西。
  5. 尝试处理原始数据,以获得处理脏数据集的经验。
  6. 虽然前一点可能不是必要的,这一点是强制性的:完成至少 1 或 2 个完整的项目。例如,对某些数据集进行详细的分析和建模,或者创建一个应用程序。要学习的主要内容是如何创造一个想法,计划其实施,获得数据,使用它并完成项目。
  7. 去 Kaggle,学习内核,参加比赛。
  8. 加入一个好的社区。我加入了 ods.ai —一个由 15k+活跃的俄罗斯数据科学家组成的社区(顺便说一下,这个社区对任何国家的数据科学家开放),它给了我很大的帮助。

研究深度学习是一个完全不同的话题。

这仅仅是开始。遵循这个路线图(或做类似的事情)将帮助你开始成为数据科学家的旅程。剩下的就看你自己了!

现在你也可以在我的网站这里阅读这篇博文。

看看梯度下降和 RMSprop 优化器

原文:https://towardsdatascience.com/a-look-at-gradient-descent-and-rmsprop-optimizers-f77d483ef08b?source=collection_archive---------2-----------------------

简短的解释

1.介绍

有无数的超参数,你可以调整,以提高你的神经网络的性能。但是,并不是所有这些都会显著影响网络的性能。您选择的优化器是决定您的算法是收敛还是爆炸的一个参数。有相当多的优化器可供选择,让我们来看看最广泛使用的两个。

2.梯度下降优化器

梯度下降可能是所有优化器中最流行和使用最广泛的。这是一种寻找神经网络最优值的简单而有效的方法。所有优化器的目标是达到全局最小值,其中成本函数达到最小可能值。如果你尝试在三维空间中形象化成本函数,它将类似下图。

Convex cost function

Stochastic Gradient Descent - AlgorithmFor each example in the data
    - find the value predicted by the neural network 
    - calculate the loss from the loss function 
    - find partial derivatives of the loss function, these partial derivatives produce gradients
    - use the gradients to update the values of weights and biases

每当我们找到梯度并更新权重和偏差的值时,我们就向最佳值靠近了一步。在我们开始训练我们的神经网络之前,我们的成本会很高,这由上图中的 A 点表示。通过训练神经网络的每一次迭代(寻找梯度并更新权重和偏差),成本降低并向全局最小值移动,该最小值由上图中的点 B 表示。下面的模拟将提供一个更好的直观理解,当我们迭代训练我们的模型时,我们如何达到全局最小值。

我们的成本函数并不总是像上面图片中描绘的那样平滑。很多时候,这些成本函数是非凸的。非凸函数的问题是,你有可能陷入局部极小值,你的损失可能永远不会收敛到全局最小值。看看下面的图片。

Non-Convex cost function

从上图可以看出,图中有两个最小值,两个中只有一个是全局最小值。我们的神经网络很有可能会错过全局最小值而收敛到局部最小值。有一些方法可以限制网络收敛,例如:我们可以改变学习速率或使用动量等。

2.1 学习率

Different learning rate

学习率可能是梯度下降和其他优化器最重要的方面。让我用一个类比来更好地解释学习率。把成本函数想象成一个坑,你将从顶部开始,你的目标是到达坑的底部。你可以把学习率想象成你要到达坑底(全局最小值)的那一步。如果你选择一个大的值作为学习率,你将会对权重和偏差值做出剧烈的改变,也就是说,你将会经历巨大的跳跃来达到底部。还有一个巨大的概率,你会越过全局极小值(底部),最终在坑的另一边,而不是底部。学习率大,你永远无法收敛到全局极小值,永远在全局极小值附近徘徊。如果你选择一个小的值作为学习率,你会失去超过最小值的风险,但是你的算法会有更长的时间收敛,也就是说,你采取更短的步骤,但是你必须采取更多的步骤。因此,你必须训练更长的时间。此外,如果成本函数是非凸的,您的算法可能很容易陷入局部最小值,它将无法摆脱和收敛到全局最小值。学习率没有通用的正确值。这归结于实验和直觉。

2.2 带动量的梯度下降

几乎总是,带动量的梯度下降比标准梯度下降算法收敛得更快。在标准的梯度下降算法中,你会在一个方向上迈出较大的步伐,而在另一个方向上迈出较小的步伐,这会降低算法的速度。在下图中,您可以看到标准梯度下降在 y 方向上的步长较大,在 x 方向上的步长较小。如果我们的算法能够减少在 y 方向上采取的步骤,并将步骤的方向集中在 x 方向上,我们的算法将收敛得更快。这就是动量所做的,它限制了一个方向的振荡,这样我们的算法可以收敛得更快。此外,由于 y 方向的步数受到限制,我们可以设置更高的学习率。

Standard gradient descent

3.RMSprop 优化器

RMSprop 优化器类似于带有动量的梯度下降算法。RMSprop 优化器限制垂直方向的振荡。因此,我们可以提高我们的学习率,我们的算法可以在水平方向上采取更大的步骤,收敛得更快。RMSprop 和梯度下降之间的区别在于梯度是如何计算的。以下等式显示了如何计算 RMSprop 的梯度和带动量的梯度下降。动量的值用β表示,通常设置为 0.9。如果你对优化器背后的数学不感兴趣,你可以跳过下面的等式。

Gradient descent with momenttum

RMSprop optimizer

有时 v_dw 的值可能非常接近 0。然后,我们体重的价值可能会膨胀。为了防止梯度爆炸,我们在分母中包括一个参数ε,它被设置为一个小值。

4.结论

优化器是神经网络的重要组成部分,了解它们的工作方式将有助于您选择哪一个用于您的应用程序。我希望这篇文章有助于做出这个决定:)

机器人技术一览

原文:https://towardsdatascience.com/a-look-at-robotics-b58271013509?source=collection_archive---------4-----------------------

通过初创公司 Clearpath Robotics 简要介绍机器人行业及其竞争格局。

这是我对一家投资组合公司案例研究的精简版。与 Clearpath Robotics 或其团队没有任何关系。(最初发布于 2017 年 3 月 20 日)

关于 Clearpath:

Clearpath Robotics 自其创始人——4 名雄心勃勃的滑铁卢学生——发现他们“为了更大的利益而制造机器人”的热情以来,已经走过了漫长的道路

自 2009 年以来,Clearpath Robotics 引领了一场实施智能机器人的运动,这些机器人可以执行危险的任务,以减轻人类的危险。Clearpath 的自动驾驶汽车是一项无与伦比的自动化技术,其潜力超出了农业和采矿等工业目的。目前,Clearpath 的机器人解决方案及其硬件、软件和服务已经整合到 500 多个全球品牌的日常流程中。

“Clearpath 的最终目标是将人类从履行中心完全移除。从长远来看,我们的目标是建立一个制造或履行设施,在那里,你可以真正地关灯,因为一切都是自动化的。”

- 西蒙·德雷克斯勒 Clearpath 的工业系统总监

概述 Clearpath 的 3 个不同支柱:人工智能进步,机器人自主和工业自动化,它们将在稍后进行审查。

Culminated based on my findings

机器人行业:

机器人领域是一个具有高增长潜力的蓬勃发展的市场。机器人是一个独立的数十亿美元的全球市场,能够转移到工业环境之外的新行业,在这些行业中,他们的现代技术仍然高度适用和有需求。

根据当前趋势,到 2020 年,机器人的市场价值预计将达到 410 亿美元,其中 15 亿美元将用于机器人扩展到 B2C 模式。这与像 Clearpath 这样的初创公司的可能性相一致,它们只将企业作为唯一的客户群。

下面是 12 年期间(2002 年至 2014 年)数据的可视化,代表了该行业在购买数量方面的巨大增长。

Based on source

此外,机器人的未来市场将由两个主要部门驱动:工业和服务。很明显,机器人产业只会继续快速扩张,在全球范围内扩大规模。最值得注意的是,在未来几年,服务行业将有更大的市场进入机会,让公司将机器人应用于受过高等教育的角色,如客户服务。

Based on source and source

全球市场:

目前,亚洲是机器人领域支出最多的地区,占全球市场总额的 65%以上。此外,据预测,到 2019 年,他们的支出将翻一番,这表明了令人难以置信的增长,但也为 Clearpath 等公司提供了巨大的市场机会,让他们在不久的将来探索扩张方案。

众所周知,中国生产了全世界几乎一半的商品。事实上,中国的进口仅占其出口的 35%[,而出口最近在 2013 年增加到 43.1%](http://www.economist.com/news/leaders/21646204-asias-dominance-manufacturing-will-endure-will- make-development-harder-others-made)。随着中国工资上涨,许多大公司选择将生产外包给菲律宾等成本更低的国家。随着中国作为制造业世界工厂的有希望的主导地位,其减少劳动力的需求,以及其强大的机器人市场机会,中国似乎是 Clearpath 的 Otto 等产品的下一个成功扩张地点。

从不同的角度来看,与其他大型国际机器人公司相比,Clearpath 仍然被认为是一家规模小得多的初创公司。由于他们的团队和库存更小,新的业务环境可能弊大于利,因为它将带来大量的新费用和硬件需求的突然增加,而 Clearpath 无法满足这些需求。鉴于他们目前的公司状况,他们目前留在加拿大境内可能更容易。

编辑 : Geek+ ,一家成立 1.5 年的中国北京公司,正在为仓库建造机器人(类似于亚马逊的 Kiva 机器人),本周在 A 轮中筹集了 1400 万美元。

Clearpath 的竞争对手:

为了分析 Clearpath 的独特地位和研究强大的市场参与者,我们必须重新审视前面提到的 3 个支柱。哪些主要竞争对手正在同一个领域进行创新,并专注于创造一系列自主、智能和高效的士兵?

值得注意的竞争对手包括Fetch Robotics:一家最近在硅谷成立的初创公司,旨在通过其旗舰产品 Freight、Seegrid Corp:一家 3D 视觉导航的创新者,希望通过自主机器人解决方案来提高生产率,并希望改造下一代视觉和自动导向车辆。

Positioning map

尽管 Clearpath 面临着挑战和不断增加的竞争对手,但这家初创公司有一个整体的价值主张,无法被其他人轻易超越。Clearpath 的基础设施不仅允许轻松的企业集成、即时实施和无缝的整体体验,而且 Clearpath 致力于卓越的客户服务,这在很大程度上帮助他们在社区中扬名立万。

Clearpath 的未来展望:

检查伙伴关系

1。地理扩张

正如之前提出的潜在扩张战略,Clearpath 在进入全球市场时并不具备规模优势。然而,机器人行业内的一些强大的参与者有,未来的合作伙伴关系可以帮助 Clearpath 支撑这一弱点。

Grenzebach 是一家德国公司,几十年来一直以家族企业的方式运营。专注于工业自动化,他们的移动设备 Carry 被编程为处理材料运输任务。随着品牌在欧洲和亚洲广泛使用他们的技术,Grenzebach 仍然远远没有统治北美,因为他们只进入了一个国家(美国)。Grenzebach 在德国、美国和亚洲拥有 3000 家工厂和设施,未来与 Clearpath 的合作对双方都有利。通过与 Grenzebach 合作,Clearpath 有能力轻松地扩展到我们的邻国,各州,以及亚洲市场,因为 Grenzebach 的物理设施。对于 Grenzebach 来说,Clearpath 是加拿大领先的机器人初创公司,拥有一个有前途的研究团队,他们的创新速度比典型的大公司更快。此外,在 Clearpath 的帮助下,Grenzebach 最终可以通过进入加拿大市场来覆盖北美的所有地区。

2。产业扩张

考察潜在合作伙伴的另一种方式是考察行业扩张机会。根据麦肯锡&公司的预测,到 2025 年,医疗保健、服务和制造等行业的先进机器人市场预计将产生高达 4.5 万亿美元的经济影响。

“对于私人控股的 Clearpath 来说,即使是一小块蛋糕,也意味着数十亿美元。自 2010 年以来,clear path 的合作伙伴关系推动其收入同比增长了 200%。”

有鉴于此,Clearpath 可以探索与领先的医疗机构合作的选择,这些机构规模庞大,但不一定有人力或时间自己发明先进的机器人技术。医院将通过整合 Clearpath 受益,因为许多程序将变得更加高效。同样,这将是 Clearpath 的理想合作伙伴,因为他们可以将其产品扩展到医疗保健领域,收集有价值的第一手数据以进行改进,如果医疗机构是国际机构,还可能进行跨境合作。

Unsplash/Alex Knight

检查收购

1。大型公司收购

2012 年,一家致力于为航运中心制造自动化机器人的机器人公司被亚马逊以 7 . 75 亿美元的巨额交易收购,该交易给了他们所有研发的独家权利。 Kiva Systems,现在被称为亚马逊机器人,只在亚马逊自己的工厂内使用。

大公司刚刚开始赶上贝佐斯的步伐,因为他们最近注意到机器人和制造业之间的正相关和巨大增长。[像 IBM 和微软这样的大公司对机器人初创公司进行了无数次新投资。](http://www.geekwire.com/2016/sarcos-robotics-raises-10-5m-microsoft-caterpillar-ge-heavy-duty-ro botics-technology/)

2015 年, GE Ventures 公开了其作为 Clearpath Robotics 战略长期投资者的角色。

“我们相信机器人技术将极大地改善通用电气服务的行业,”

通用电气风险投资公司的董事总经理拉尔夫·泰勒-史密斯。

这反映了 GE 未来的发展方向。由于通用电气对自动机器人非常感兴趣,Clearpath 提供了他们希望在自己的服务中实现的创新,这使得阿格成为 Clearpath 的潜在收购者,交易类似于亚马逊的交易。

2。扩展采集

参照 Clearpath 目前较小的规模,他们可能更容易受到不断变化的市场的影响,对新的竞争准备不足。尤其是在文化层面和工厂程序上的差异。Clearpath 可以通过大型外国机器人公司的收购自动放弃这种担忧。此外,一个更大的公司会非常有兴趣追求 Clearpath 的独特和先进的创新,将其引入他们的外国(也许是未开发的)市场。

ABB 集团 是一家总部位于瑞士的自动化公司,通过自动化和机器人技术解决公用事业、交通和工业领域的问题。米语,ABB 两年前创造的双臂机器人是世界上第一个鼓励人机互动的协作机器人。这不仅与 Clearpath 的目标一致,而且从向新行业和新国家扩张的角度来看,被收购将大有裨益。

结论:

总之,Clearpath 正在人工智能、全自动机器人和工业自动化的支柱下创造令人难以置信的发明,同时通过其现代应用来完成培养前瞻性思维、高效和安全的工作环境的使命。根据我对 Clearpath 当前竞争格局的简要分析,他们最大的优势是:提供全面的基础设施系统以及全球机器人市场需求巨大的高度先进的技术创新。Clearpath Robotics 是一家快速增长的初创公司,有可能在 Grenzebach 等合作伙伴的帮助下,或被 GE 等更大的公司收购后,扩大地理范围,进入新的行业。

随着人工智能发展研究的深入,我们继续努力复制人类智能或更高的智能,机器人行业是一个即将到来的巨人,我们必须感到兴奋,但同时保持警惕。

感谢阅读!在此之前和之后,我从未深入研究过机器人技术,我可能会再次成为一名软件狂热者。

这是我上个月的一篇文章:

[## 关于微信的想法,以及它对北美数字应用市场的意义

注意:这是我的第一篇媒体文章,也是我第一篇试图分析一个应用程序和一个行业的文章

medium.com](https://medium.com/@diane.huang/thoughts-on-wechat-and-what-it-means-for-north-americas-digital-app-market-641e5063f1ac)

我们连线吧!😃

对酒精消费的调查

原文:https://towardsdatascience.com/a-look-into-alcohol-consumption-around-the-world-87109d060271?source=collection_archive---------1-----------------------

从人们的饮酒习惯,你能说出他们来自哪里吗?

根据世界卫生组织提供的一组国家级人均酒精消费量的数据,我很想知道各个地区的酒精偏好。

幸运的是,R 库(countrycode)可以很容易地将国家名称转换成 ISO3 代码、地区和大陆。然后我们可以使用 library(rworldmap)将其可视化。

我们可以使用 plot.ly 查看国家级别的消耗量。气泡大小是指总消耗量,单位为升。

我们对地区饮料偏好进行了观察:

  • 加勒比人和亚洲人倾向于消费更多的烈酒和少量的葡萄酒
  • 除此之外,世界各地的啤酒消费量最高

如果在地图上画出每个国家的消费量,除了明显知道伊斯兰国家消费很少的酒以外,我们可以看到:

  • 整个美洲(北部、中部和南部)都喝很多啤酒
  • 欧洲人似乎对葡萄酒比对烈酒更感兴趣

这是我的# 100 days 项目的第 3 天。完整的代码可以在 github 这里找到。

二分搜索法树一瞥

原文:https://towardsdatascience.com/a-look-into-binary-search-trees-ee2d69e9d0ef?source=collection_archive---------10-----------------------

本周我一直在学习算法和数据结构,所以我想我们应该深入研究一下技术面试中常见的数据结构,二分搜索法树。对我来说,学习一个新主题的最好方法是看它如何应用于现实世界的问题,所以我将从解决特定问题的角度来介绍这个主题。

让我们假设你在一家软件工程公司工作,一个客户向你提出了一个问题。他们为一个只有一条跑道的小机场工作。他们要求您开发一个预订系统,该系统将跟踪着陆的飞机,以便没有重叠。他们希望能够为您的申请提供一个时间T,该时间代表两次航班着陆之间的最短时间,以分钟为单位。最后,他们希望应用程序在 O(log n)中运行。

让我们首先考虑什么样的数据结构最适合这个问题。第一个想到的是一个Unsorted list / Array结构,但是几乎所有你想用数组做的事情都将以线性时间运行(O(N))。插入以恒定的时间运行,然而,搜索是线性的,当一架新飞机请求着陆时间时,我们将需要搜索一个可用的时隙。

下一个逻辑步骤是Sorted Array,这允许我们使用二分搜索法在O(log N)中找到请求的时间,并且我们可以通过将它与它之前和之后的下一个相邻时间进行比较来验证恒定时间(O(1))中的槽。当我们试图插入新的预订时,问题出现了。要将一个新元素插入到一个排序的数组中,我们必须将插入点之前的所有其他元素向前移动 1,这是在线性时间内完成的,这违反了我们的最后一个要求。

考虑到这一点,我们继续进行Sorted Linked Lists。这种结构允许在恒定的时间内插入,但是剥夺了我们应用二分搜索法的能力,这将我们的搜索时间复杂度降低到线性时间。

现在我们已经讨论了各种可能性,最符合我们需要的数据结构是排序数组,那么我们如何解决它的插入问题呢?这就是二叉查找树发挥作用的地方。二叉查找树(BST),也称为有序二叉树,是一种基于节点的数据结构,其中每个节点不超过两个子节点。每个子节点必须是另一个二叉查找树的叶节点或根节点。左侧子树仅包含键小于父节点的节点;右边的子树只包含键大于父节点的节点。

二叉查找树为我们提供了一些有趣的时间复杂性。为了搜索,我们必须遍历所有元素。因此,在二叉查找树中搜索的最坏情况复杂度为 O(n)。对于插入元素,它必须作为一片叶子插入到正确的位置,以保持二叉查找树不变量为真。因此,我们需要遍历所需的元素来找到它的正确位置,其最坏情况的复杂度为 O(n)。最后,对于删除,我们必须遍历所有元素来找到要删除的目标。因此,二叉树中的删除具有 O(n)的最坏情况复杂度。通常,这些操作的时间复杂度是O(H),其中H是 BST 的高度。树的高度被定义为从节点到叶子的最长路径。这不应该被混淆

所以现在,我想象你对着你的电脑屏幕大喊“O(H)的复杂性不符合客户给我们的O(log N)的要求!”。放轻松,老虎,我们会成功的。让我们讨论树的高度的最好和最坏的情况。

Worst Case Scenario

在最坏的情况下,每次我们添加一个叶子,它都会被添加到相同的路径中。如果将一系列递增的数字添加到树中,就会出现这种情况,因为每个数字都比上一个数字大,它总是会选择正确的路径。这导致树的高度为N,因此如果我们的目标是这棵树的叶子,那么无论何时我们都必须遍历它,我们将不得不查看每一个元素。该树的时间复杂度为O(N)

Best Case Scenario

在最好的情况下,我们所有的节点均匀地分布在整个树中。没有一条路比另一条路更长。这被称为平衡树,它为我们在其上执行的操作提供了最佳的运行时间。每次你选择一个分支往下走,你实际上是把你必须搜索的节点数减半,就像一个。是的…你猜对了,二分搜索法算法。平衡二叉树的高度将是log N,因此其基本操作的时间复杂度也将是O(log N)

现在唯一需要回答的问题是如何保持我们的树木平衡。有许多不同的算法来平衡一棵树,我们将使用 AVL 树(以发明者命名)作为这个例子,因为它是第一个被发明的这样的数据结构。在 AVL 树中,任何节点的两个子树的高度最多相差 1;如果在任何时候它们相差一个以上,就要进行重新平衡以恢复该属性。这保证了在一般和最坏的情况下,查找、插入和删除都需要花费O(log N)时间。

为了保持 AVL 树的平衡,我们必须记录两个孩子的身高差。差额由abs(Height(RightSubtree) — Height(LeftSubtree))计算。只要结果小于 1,我们就知道我们的树符合 AVL 定义。请注意,这个公式永远不会产生大于 2 的值,因为我们一次只会向已经平衡的树中添加一个节点。当一棵 AVL 树变得不平衡时,我们必须对它的子树进行旋转以重新平衡结构。

Blatantly stolen image from Wikipedia.

α, β and γ表示的三角形代表N大小的子树。当在树上执行旋转时,它的顺序遍历是不变的,这允许我们的树保持它的排序性质。

最简单的解决模式是我喜欢称之为线模式。在这种情况下,节点沿直线向右或向左延伸。在这种情况下,旋转中间节点(在这个例子中是B)将平衡我们的树。

在大多数情况下,右旋转或左旋转将平衡树。然而,有一个实例,其中插入创建了之字形图案,其中单次旋转不会改变树的最终平衡。在左边的例子中,我们在B上执行向左旋转。在这种情况下,旋转只是移动节点,因此树现在是右偏而不是左偏。

Double Rotation

对此的解决方案是首先在底部节点上执行旋转,使其符合线型。然后,您可以像在线型中一样旋转中间节点,并平衡您的树。这就是所谓的双旋转。

让我们回到我们的问题上来。当插入一个节点时,我们必须遍历树,一旦我们找到它的插入点,我们就可以检查它的父节点和子节点是否离它至少有K远。如果满足所有验证,我们的函数将返回一个true,否则返回一个false。在 AVL 树中插入一个新节点可以在O(log N)时间内完成,搜索可以以相同的复杂度完成。

我希望这有助于照亮二分搜索法树和他们的力量。作为临别礼物,我留给你一张来自维基百科的 gif,它很好地概述了 AVL 树中的插入和旋转。

AVL Tree Insertion and Rotation

*一如既往,如果您喜欢此内容或有任何反馈,请在下面留下评论 *

《权力的游戏》回顾

原文:https://towardsdatascience.com/a-look-over-game-of-thrones-fdcb887e0631?source=collection_archive---------5-----------------------

《权力的游戏》被公认为是这十年来最好的惊险、动作、战略、奇幻电视剧。该片于 2011 年上映,在很短的时间内就获得了认可,全球平均收视率达到 2570 万。这部剧是根据乔治·R·R·马丁写的系列丛书【冰与火之歌】改编的。

如果你还没看这部剧或读过这本书,下一部分会有剧透提醒

关于这个节目—

该剧展示了整个系列中的许多“家族”,但主要集中在其中的四个——坦格利安、史塔克、兰尼斯特和拜拉席恩。它讲述了四大家族如何不择手段地试图获得铁王座。

“字面上任何可能的意思”

故事从劳勃·拜拉席恩坐在铁王座上开始,奈德·史塔克是国王之手,瑟曦·兰尼斯特是他的妻子,丹妮莉丝·坦格利安和她的哥哥流亡海外。在这一系列的某个时候,劳勃去世,他的儿子乔佛里成为下一任国王。他的第一个命令是砍掉内德的头,他实际上是罗伯特的好朋友和助手。与此同时,丹的哥哥也被多斯拉克人杀死,她成了多斯拉克人卓戈·卡奥的妻子。在展览的后期,一系列事件发生了(按顺序)

  1. 内德的儿子罗柏·史塔克试图为父亲报仇,在一次晚宴上被他认为是自己忠诚的人杀死。
  2. 乔佛里在他叔叔提利昂的婚礼上喝啤酒时中毒身亡。
  3. 提利昂得知他最爱的女人实际上是被他雇佣并逃跑后,杀死了他的父亲泰温。
  4. 琼恩·雪诺死了,并再次由梅丽珊卓转世。(他什么都不知道)。
  5. 坦格利安家族的丹妮莉丝,她名字中的第一个,未燃烧者,安达尔人、洛依纳人和先民的女王,弥林的女王,大草海的卡丽熙,王国的守护者,七大王国的女统治者,锁链的破坏者和龙之母。
  6. 琼恩·雪诺现在是北境之王,瑟曦是铁王座和七大王国的女王,丹妮莉丝现在在维斯特洛的龙石岛。白鬼要来维斯特洛了,而且
  7. 冬天来了…

关于数据集—

Kaggle 基于书籍中的信息提供了来自三个数据源的数据集。

  • 首先是 battles.csv 包含克里斯·阿尔邦的《五王之战》数据集,可以在这里找到:https://github.com/chrisalbon/war_of_the_five_kings_dataset。这是一个伟大的系列中所有战斗的集合。
  • 其次,我们有来自艾琳·皮尔斯和本·卡勒的角色-死亡。这个数据集是作为他们的贝叶斯生存分析的一部分创建的,可以在这里找到:http://allendowney . blogspot . com/2015/03/Bayesian-Survival-Analysis-for-game-of . html
  • 最后,我们有了一个更全面的人物数据集和人物预测。这来自冰与数据之歌的团队,他们是从http://awoiaf.westeros.org/刮来的。还包括他们对哪个角色会死的预测,其方法论可以在这里找到:https://got . show/machine-learning-algorithm-predicts-death-game-of-thrones

在这些数据中,你能找到哪些关于这个奇幻世界复杂政治格局的洞见?

接近—

正如前面提到的,我们需要在数据集内部找到洞察力,基本上我们需要对它进行 EDA。关于这篇文章,我们将分析 battles.csv 数据集,在后续文章中,我们将尝试获得尽可能多的见解(以及其他数据集)。

我在这里问的问题是——哪一个国王赢得了最多的战斗,用了多少人?

我们将首先尝试绘制一些当前特征的图表,然后尝试查看它们是否显示任何有用的信息。

笔记本—

要获得带有适当解释、输出和数据集文件的完整代码,请参考我的 GitHub 帐户—

[## saahil 1292/权力的游戏

在 GitHub 上创建帐户,为《权力的游戏》的开发做出贡献。

github.com](https://github.com/saahil1292/Game-Of-Thrones)

参考文献—

  • http://quizfactory.com/simple/got2/desktop/top.jpg
  • https://www . quora . com/How-much-people-watch-Game-of-Thrones/answer/Tini-Bancroft?srid=MrHW
  • https://www . quora . com/What-the-full-title-of-daene rys-Targa ryen/answer/Mahesh-Shrestha-23?srid=MrHW

机器学习方法——构建酒店推荐引擎

原文:https://towardsdatascience.com/a-machine-learning-approach-building-a-hotel-recommendation-engine-6812bfd53f50?source=collection_archive---------3-----------------------

source: Expedia

人工智能驱动的个性化,旅游推荐

所有在线旅行社都在争先恐后地满足亚马逊和网飞设定的人工智能驱动的个性化标准。此外,在线旅游世界已经成为一个竞争激烈的空间,品牌试图通过推荐、比较、匹配和分享来吸引我们的注意力(和钱包)。

在本帖中,我们的目标是为 Expedia 的用户创建最佳酒店推荐,这些用户正在搜索要预订的酒店。我们将把这个问题建模为一个多类分类问题,并使用集成方法建立 SVM 和决策树,以预测用户在给定他(或她)的搜索细节的情况下可能预订哪个“酒店群”。

数据

数据是匿名的,几乎所有的字段都是数字格式。数据集可以在 Kaggle 找到,我们将使用 train.csv 和 destinations.csv,前者捕获用户行为的日志,后者包含与用户对酒店的评论相关的信息。

下面的图 1 提供了 train.csv 的模式:

Figure 1

下面的图 2 提供了 destinations.csv 的模式:

Figure 2

import datetime
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inlinefrom sklearn.model_selection import cross_val_score
from sklearn.ensemble import RandomForestClassifier
from sklearn.pipeline import make_pipeline
from sklearn import preprocessing
from sklearn.preprocessing import StandardScaler
from sklearn import svm

为了能够在本地处理,我们随机抽取 1%的记录。之后我们还有大量的记录在 241179。

df = pd.read_csv('train.csv.gz', sep=',').dropna()
dest = pd.read_csv('destinations.csv.gz')
df = df.sample(frac=0.01, random_state=99)
df.shape

(241179,24)

电子设计自动化(Electronic Design Automation)

目标是根据用户搜索中的信息,预测用户将预订哪个酒店。总共有 100 个集群。换句话说,我们正在处理一个 100 级的分类问题。

plt.figure(figsize=(12, 6))
sns.distplot(df['hotel_cluster'])

Figure 3

数据分布在所有 100 个集群中,并且数据中存在偏斜。

特征工程

日期时间、入住日期和退房日期列不能直接使用,我们将从中提取年和月。首先,我们定义了几个函数来实现这一点,我们还定义了一个函数来与 destination.csv 合并。

from datetime import datetime
def get_year(x):
    if x is not None and type(x) is not float:
        try:
            return datetime.strptime(x, '%Y-%m-%d').year
        except ValueError:
            return datetime.strptime(x, '%Y-%m-%d %H:%M:%S').year
    else:
        return 2013
    passdef get_month(x):
    if x is not None and type(x) is not float:
        try:
            return datetime.strptime(x, '%Y-%m-%d').month
        except:
            return datetime.strptime(x, '%Y-%m-%d %H:%M:%S').month
    else:
        return 1
    pass

def left_merge_dataset(left_dframe, right_dframe, merge_column):
    return pd.merge(left_dframe, right_dframe, on=merge_column, how='left')

处理日期时间列:

df['date_time_year'] = pd.Series(df.date_time, index = df.index)
df['date_time_month'] = pd.Series(df.date_time, index = df.index)from datetime import datetime
df.date_time_year = df.date_time_year.apply(lambda x: get_year(x))
df.date_time_month = df.date_time_month.apply(lambda x: get_month(x))del df['date_time']

处理 srch_ci 列:

df['srch_ci_year'] = pd.Series(df.srch_ci, index=df.index)
df['srch_ci_month'] = pd.Series(df.srch_ci, index=df.index)# convert year & months to int
df.srch_ci_year = df.srch_ci_year.apply(lambda x: get_year(x))
df.srch_ci_month = df.srch_ci_month.apply(lambda x: get_month(x))# remove the srch_ci column
del df['srch_ci']

处理 srch_co 列:

df['srch_co_year'] = pd.Series(df.srch_co, index=df.index)
df['srch_co_month'] = pd.Series(df.srch_co, index=df.index)# convert year & months to int
df.srch_co_year = df.srch_co_year.apply(lambda x: get_year(x))
df.srch_co_month = df.srch_co_month.apply(lambda x: get_month(x))# remove the srch_co column
del df['srch_co']

初步分析

在创建新特性并删除无用的特性后,我们想知道是否有任何东西与 hotel_cluster 有很好的关联。这将告诉我们是否应该更加关注任何特定的功能。

df.corr()["hotel_cluster"].sort_values()

Figure 4

没有与 hotel_cluster 线性相关的列,这意味着对特征之间的线性关系建模的方法可能不适合该问题。

战略

快速谷歌搜索后,不难发现,对于搜索目的地、酒店国家、酒店市场的已知组合,肯定有助于找到酒店集群。就这么办吧。

pieces = [df.groupby(['srch_destination_id','hotel_country','hotel_market','hotel_cluster'])['is_booking'].agg(['sum','count'])]
agg = pd.concat(pieces).groupby(level=[0,1,2,3]).sum()
agg.dropna(inplace=True)
agg.head()

Figure 5

agg['sum_and_cnt'] = 0.85*agg['sum'] + 0.15*agg['count']
agg = agg.groupby(level=[0,1,2]).apply(lambda x: x.astype(float)/x.sum())
agg.reset_index(inplace=True)
agg.head()

Figure 6

agg_pivot = agg.pivot_table(index=['srch_destination_id','hotel_country','hotel_market'], columns='hotel_cluster', values='sum_and_cnt').reset_index()
agg_pivot.head()

Figure 7

与目标表和我们新创建的聚合数据透视表合并。

df = pd.merge(df, dest, how='left', on='srch_destination_id')
df = pd.merge(df, agg_pivot, how='left', on=['srch_destination_id','hotel_country','hotel_market'])
df.fillna(0, inplace=True)
df.shape

(241179,276)

实现算法

我们只对预订活动感兴趣。

df = df.loc[df['is_booking'] == 1]

获取要素和标签。

X = df.drop(['user_id', 'hotel_cluster', 'is_booking'], axis=1)
y = df.hotel_cluster

朴素贝叶斯

from sklearn.naive_bayes import GaussianNBclf = make_pipeline(preprocessing.StandardScaler(), GaussianNB(priors=None))
np.mean(cross_val_score(clf, X, y, cv=10))

0.10347912437041926

k 近邻分类器

from sklearn.neighbors import KNeighborsClassifierclf = make_pipeline(preprocessing.StandardScaler(), KNeighborsClassifier(n_neighbors=5))
np.mean(cross_val_score(clf, X, y, cv=10, scoring='accuracy'))

T5 0.25631461834732266

随机森林分类器

我们通过k-折叠交叉验证来报告性能测量,并且流水线使得构建评估器更加容易。

clf = make_pipeline(preprocessing.StandardScaler(), RandomForestClassifier(n_estimators=273,max_depth=10,random_state=0))
np.mean(cross_val_score(clf, X, y, cv=10))

0.24865023372782996

多类逻辑回归

from sklearn.linear_model import LogisticRegressionclf = make_pipeline(preprocessing.StandardScaler(), LogisticRegression(multi_class='ovr'))
np.mean(cross_val_score(clf, X, y, cv=10))

0.3045543572367767

SVM 分类器

SVM 非常耗时。然而,我们取得了更好的结果。

from sklearn import svmclf = make_pipeline(preprocessing.StandardScaler(), svm.SVC(decision_function_shape='ovo'))
np.mean(cross_val_score(clf, X, y, cv=10))

0.3228727137315005

似乎我们需要做更多的特征工程来改善结果。敬请期待进一步的改进!

源代码可以在 Github 上找到。祝你一周愉快!

机器学习入门:几乎没有数学——第 1 部分

原文:https://towardsdatascience.com/a-machine-learning-primer-almost-without-the-math-part-1-19ed04e352c0?source=collection_archive---------21-----------------------

机器学习课程的介绍总是以大量数学内容开始,这往往会吓倒初学者,并使他们远离它。在这里,我会试着复习机器学习的一些重要概念,除了数学,差不多。我还将尝试为每个术语附上一些简单的例子。这里涉及的大多数概念都与监督学习和预测建模有关。

这里讨论的所有解释都是实际概念的淡化版本。如果你对这些感兴趣,我强烈推荐回到数学上来获得更多的见解!

(机器)学习

如果由 P 测量的计算机程序在 T 中的任务的性能随着经验 E 而提高,则称该计算机程序从关于某类任务 T 和性能测量 P 的经验 E 中学习。—汤姆·米切尔

机器学习模型

机器学习模型可以被视为机器学习系统的数学(有时是架构)表示,包括但不限于输入和输出数据的表示、学习中涉及的算法、定义学习过程的参数和模型的架构。

人口

与所考虑的实验相关的所有可能的例子的集合。这是机器学习模型试图预测的,目标人群的分布。

特征空间(输入)

特征空间是模型的输入空间,变量(除了我们想要预测的目标变量)存在于此。特征可以是数字的,也可以是分类的。例如,汽车的重量和速度是数字特征。这辆车是雪佛兰还是特斯拉是一个明确的特征。

如果您使用颜色、速度、品牌和型号来描述一组汽车,那么这些属性的所有可能值构成了特征空间。

特征向量 X

特征空间中的每个条目被称为 n 维特征向量,其中 n 是定义特定数据点的特征的数量。

如果您要使用汽车的某些特征来定义汽车,特征列表将形成特征向量。例如:[橙色,280 英里/小时,2800 磅]是一个三维特征向量,具有 3 个特征,颜色,速度和重量。

标签空间(输出)

与每个特征向量相关联的标签或目标变量的集合构成了标签空间。

可以有各种车野马 GT,跑车,卡玛洛等。所有这些都是定义它们的功能集的标签。

真实标签 y

这是与一个特定数据点相关联的实际标签。

示例

一个例子是包括特征和标签的数据点。手头数据集中可用的示例可能不会完全穷尽数据分布。

Roadster[橙色,280 英里/小时,2800 磅]就是数据集中的一个例子。如果我们有一个只属于一家公司的 100 辆汽车的数据集,这并不意味着我们可以预测其他公司的汽车,因为它们可能有完全不同的数据分布。根据特斯拉汽车公司的数据,很难对福特汽车做出预测。

预测标签 y^

它是机器学习模型为给定特征向量预测的标签。它可能正确,也可能不正确。

vector【橙色,280 英里/小时,2800 磅】可以预测为跑车或橙色沙滩车。

训练集

用于训练机器学习模型的一组示例。

验证集

这是用于在训练过程中检查模型当前状态的训练集的子集(有时与训练集分开)。这并不直接有助于模型的训练。验证集可用于训练模型的参数或为模型提供评估度量。

测试设备

除非经过训练,否则模型无法访问的数据点集。它用于测试模型的训练状态。

Different data splits

分类

分类模型是将数据分类或归类为 2 个(二元分类器)或更多个(多类分类器)类的模型。

我们将尝试理解模型如何使用小数据集进行学习:

让我们绘制这个数据集,每个轴代表一个特性值:

现在我们将在这些点上标记给定的标签:

如果我们试图用直线来区分这两类,理论上可能会有无限可能的直线:

如果我们添加另一个点,可能的行数会减少:

添加更多点..

更多..

现在,如果我们从相同的数据分布中得到一个新点,我们知道根据我们的蓝线将该点分类到哪里。这条蓝线是从训练好的模型中获得的假设。

我们仍然不能确定我们的蓝线是否是原始人口分界线的实际代表。考虑下面这条线,它也将两类点分开。

如果我们得到更多的点,这条线实际上可能会改变它的位置。这就是为什么你可能总是听说,机器学习中更多的数据通常会产生更好的结果。

回归

简单线性回归是一种对标量标注和一个或多个解释性要素之间的关系进行建模的线性方法。通常,回归模型用于预测连续值,如温度、重量、利率等。

考虑另一个绘制在图表上的玩具数据集:

蓝线描述了分布点的大致位置。

现在,如果我们将数据分布中的更多点添加到训练集中,线条会完全改变:

我们从同一数据分布中添加的任何新点都将位于这条蓝色曲线上。给定两个特征之一的值,我们可以根据它在曲线上的位置预测另一个特征的值。前任。如果给定 x1 = 3,那么根据曲线,x2 = 1

培养

随着模型不断看到新的点,线的位置也在不断移动。这是学习的过程(在监督学习的情况下)。我们得到的点越多,学习过程就越好,模型的准确性就越好。

假设

它是我们认为尽可能接近描述数据的真实函数(或模型)的函数(或模型)。在我们的分类示例中,我们获得的蓝线是一个这样的假设,它描述了这样的数据,即该线一侧的所有点都属于相似的类。

假设空间

假设空间是可以用 n 个特征表示的所有可能的模型或函数的集合,不一定描述数据。必须从这个假设空间中选择目标函数。给定 2 个变量,在 2 维中可能有无限多条曲线。

探索的

它可以被认为是一个简单的假设空间或决策,直观地帮助我们最终选择正确的模型或函数。例如,在我们的分类示例中,我们凭直觉决定选择不同形式的直线,而不是圆或正方形,因为很明显,一条线就足以分隔这些点。这是我们的启发。我们可以选择一些圆来包含这两个类,但是这将会把测试空间限制在那些从训练数据中获得的圆上。如果我们选择了其他形状,可能需要更多的尝试才能到达最终的线条。正确选择启发式算法有助于更快地达到目标函数。

指标函数

目标函数是实际代表原始数据分布的函数。如果我们可以访问所有可能的数据点,我们就可以训练一个模型来学习目标函数。

参数

模型参数是内部变量,其值可以从数据中确定。在训练期间,模型参数值得到更新。

选择机器学习模型

现在我们知道了一些相关的基本术语,让我们来看看如何选择机器学习模型:

  1. 定义问题陈述。是分类问题还是回归问题?
  2. 获取所需数据。
  3. 基于初始数据分析选择一种启发式方法。
  4. 根据启发和手头的任务选择机器学习模型。

既然我们已经介绍了基础知识,我们将在下一篇文章中尝试看到一个感知器模型。同样,这里涵盖的概念是淡化的版本。我将推荐吴恩达在 Coursera 上的机器学习课程,对这些主题进行深入的数学展望。

经理的日常工作不是在屏幕前…

原文:https://towardsdatascience.com/a-managers-day-job-isn-t-in-front-of-a-screen-e9af6c216f24?source=collection_archive---------4-----------------------

但是是和同事和顾客一起。

在每天钻研数据之前,我们最好从办公桌前退一步,回顾一下我们的组织试图解决的问题的性质。数据的无处不在并没有让我们的客户、团队或市场份额的管理变得更容易,因为每个数据源都构成了日益复杂的业务难题中的又一部分。要解开这个谜,需要弄清楚数据是如何反映人性、你的业务和你的市场的更大图景的。我们试图解决什么类型的问题,这些问题与过去管理者面临的问题有本质的不同吗,分析在今天能发挥什么作用?

如果这些数据告诉了我们什么,那就是泰勒的“一个最佳方式”的观点早已过时。因为业务本质上是“混乱的”,运营管理主要是解决没有按计划运行的流程、政策和决策。出现这些挑战的部分原因是,如今消费者对价值的认知更多地基于他们的体验,而不是公司产品或服务的特性。这种复杂性还源于这样一个事实,即基于每个利益相关者的精神状态、认知偏差和背景,对这些经历的评估是不同的。这也是信息经济发展的结果:数据的数量、速度和多样性影响了我们所掌握的数据的准确性和可见性。【我】

大卫·斯诺登和玛丽·布恩提醒我们,这些年来,我们今天面临的问题的性质已经发生了很大的变化。【ii】他们谈到了复杂程度,这决定了管理者如何评估他们的业务环境,以及他们在哪里寻找数据。他们认为,第一级问题涉及线性事件链,其中过程优化提供了相关的和可复制的解决方案。第二层业务挑战是由流程故障引起的,其答案可以从管理层以前的经验中推断出来。第三级挑战要求重新表述问题,因为无论是过程还是先前的经验都没有提供足够的数据来处理问题。斯诺登和布恩认为,多年来,市场和组织已经在很大程度上解决了第一和第二层次的问题,今天留给我们的是第三层次的挑战,即客户满意度、员工参与度和组织效率,这些挑战错综复杂地交织在我们设想的工作方式中。

应对业务挑战与手头数据的数量关系不大,而与我们利用数据来激发集体行动的能力关系更大。好的、更好的和伟大的决策取决于我们所处的决策环境。【iii】在确定性决策环境中,好的决策是可能的,在这种环境中,答案可以从手头的数据中确定。不幸的是,大多数业务决策都是在随机环境中做出的,在这种环境中,无法从可用数据中找到正确的决策,但在减少不确定性的原因方面,更好的决策是可能的。最后,伟大的决策是那些背景、挑战和解决方案允许我们重新审视决策过程本身的本质的决策。在查看数据之前,首先关注问题出现的背景,这是决策科学的主要收获之一。

如果测量是为了减少不确定性,那么管理就是为了阐明复杂性。【iv】我们的业务挑战源自我们对结构良好的组织和有序市场的幻想,并以对业务“应该”如何运营的理想简化为基础。今天的组织和市场是相互依赖的开放和相互依赖的,消费者和商业逻辑往往是自生的。“涌现”描述了违背经过时间考验的业务实践的结果行为,并提出了预测性和规范性分析的困难。如果数据科学的作用是降低风险、不确定性和模糊性,那么我们必须在衡量消费者、员工和管理层的动机、目标和行动之前,仔细研究他们是如何理解这些问题的。底线是,在回到工作之前,和你屏幕后面的数据,好好看看你周围的世界。

希望提高您的数据科学技能?在巴约纳的暑期学校,以及在欧洲的大师班,我们让分析为您和您的组织服务。该研究所专注于管理者数据科学的五个应用:数字经济学、数据驱动的决策、机器学习、社区管理和视觉通信。改善管理决策会对你未来的工作和职业生涯产生影响。

Lee Schlenker 是 Pau 商学院的教授,也是 http://baieurope.com 商业分析研究所的负责人。他的 LinkedIn 个人资料可以在 www.linkedin.com/in/leeschlenker.查看你可以在 https://twitter.com/DSign4Analytics的 Twitter 上关注我们

【I】Marr,B. (2014),大数据:每个人都应该知道的 5v,LinkedIn

【I】d . snow don 和 m . Boone(2007),一个领导者的决策框架,HBR

【ii】sch lenker,L. (2017),衡量你的决策质量而不仅仅是你的数据,中

【iii】r .施特劳布(2013),为什么管理者还没有拥抱复杂性,HBR

MapReduce 概述

原文:https://towardsdatascience.com/a-mapreduce-overview-6f2d64d8d0e6?source=collection_archive---------2-----------------------

针对高级编码人员的介绍说明,试图应对您可能也遇到过的任何劝阻。

当我第一次开始阅读 MapReduce 时,几乎每个教程都有 Java 或 C++先决条件的提示。然而,在科技界还有一种过时(而且越来越少)的思维模式,即成为程序员需要 CS 学位。我发现这是非常令人惊讶的,有多少教程有这种前兆,只是让他们通过完全可复制的进出反正。

说到而不是重新发明轮子,抽象就是一切。我们发现自己越少需要记住每个算法的二进制执行,我们就越接近实现它。开发的目的是让 进化 ,如果我们不使用这种技术,我们还不如回到勒德派时代,在工会组织的恐龙牧场用套索套住迅猛龙,只为了赚一些诚实的郁金香球茎。

“跳进来”的想法听起来很忌讳,但不要误解。这并不是说应该忽视整体的理解。了解你的方法的功能和相关的依赖关系对于避免不可逆转的错误是至关重要的。但是要达到这个目标并不需要回到学校或者学习一门新的语言。

也就是说,我将引用这篇文章,来自《并行编程和 MapReduce 入门》课程。现在让我们开始

历史

回到计算的初期,程序是串行的,即由一系列指令组成,每个指令被一个接一个地执行,就像一个人乘坐爱情船的队列。

开发并行化是为了提高性能和效率。它将进程原子化,并同时执行它们。这些碎片化的指令在不同的 CPU 上同时运行,要么来自一台机器,要么来自clouuddd中的。**

除了加速这个过程,它还创造了一个解决方案,当你在本地资源上受到限制时,可以处理大量的数据集。然而,一个实际的先决条件是您拥有对所有数据的同一个存储系统的块级(物理层)访问权,即

集群文件系统

一个共享磁盘文件系统。最常见的 CFS 类型使用一个存储区域网络 (SAN)来允许多台计算机在块级别获得直接的磁盘访问。这由您的数据库管理系统(DBMS)进一步提取。或者,分布式文件系统不这样做,而是使用网络发送数据。

操作它的系统增加了并发控制和串行化的机制,将数据结构编译成可存储的格式,用于网络传输、内存缓冲等。

此外,CFS 使用隔离,在级联故障的预防性情况下隔离集群中的单个节点(稍后将更详细地讨论)。

一旦确定了这一点,您就可以继续

考虑到你的计划

创建并行程序的第一步是确定一组可以并发运行的任务和/或数据分区。

有时,一个进程根本不能同时运行,就像在斐波那契函数中一样:

Fk = Fk-2 + Fk-1

这不能并行化,因为每个计算值都依赖于它前面的值。

更常见的情况是,您将处理大量一致的数据,这些数据必须进行处理,但也可以进行分区。考虑一个字符串数组:

['暴躁','傀儡','蜡笔']

可以分成大小相等的子阵列:

['暴躁'] ['傀儡'] ['蜡笔']

如果每个子阵列都没有计算依赖性,没有互通需求,并且可以遵循相同的迭代过程,那么它就是并行计算的理想候选!有一种常见的实现技术叫做master/worker:

主人:

—初始化数组,并根据可用的工作线程将其拆分

—给每个工人发送他们的子阵列

—接收来自每个工作者的响应

工人:

—从主机接收子阵列

—对子阵列执行处理

—将结果返回给主机

如果我们使用以前的子阵列,工人们将完成同样多的工作。该模型将实现静态负载平衡

负载平衡指的是在并行系统中的处理器之间分配任务的技术,以避免一些工作人员重复排队,而其他工作人员则处于空闲状态。为了激起一些想象,把它想象成共产主义的理想实现。

虽然静态平衡器允许更少的开销,但它们没有考虑当前的网络负载。

相反,dynamicbalancer 在考虑网络的同时,提供了更灵活、但计算成本更高的分配。

主/工人示例:

让我们以勾股定理为例来实现

这说明斜边(直角的对边)的平方等于其他两条边的平方之和,

a + b = c

虽然这本身是一个非常简单的算法,但它还可以进一步分解:

a_sq = a ^ 2

b_sq = b^ 2

sum_ab =a_sq + b_sq

c = sqrt(sum_ab)

这可以用 Python 重写:

cool cool. so at this point you are probably wondering

什么是 MapReduce rly

在查看了一些并行编程示例之后,我们可以对 MapReduce 的实际功能有更多的了解。

MapReduce 是从像 Lisp 这样的函数式语言的 mapreduce 组合子中派生出来的。

在 Lisp 中,映射函数值序列的形式接受输入。然后,它迭代地将该函数应用于序列中的每个值。

一个归约使用一个二元运算组合一个序列的所有元素。例如,它可以使用“+”将一个序列中的所有元素相加。

谷歌利用这一基础作为灵感,因此恰当的标题。与此一起使用的预期数据集非常庞大,通常需要存储在多台服务器上。因此,假定了并行化的必要性。

MapReduce 为 Google 工程师提供了一个抽象概念来执行基本计算,同时隐藏并行化、负载平衡和容错的细节。

MAP: 由 MapReduce 库的用户编写,接受输入对并生成一组中间键/值对。MapReduce 库将与同一个中间键 I 相关联的所有中间值组合在一起,并将它们传递给 Reduce 函数。

化简:也由用户编写,接受中间密钥 I 和以及该密钥的一组值。它将这些值合并在一起,形成一个可能更小的值集。

例如,考虑对大量文档中每个单词的出现次数进行计数的问题:

map 函数发出每个单词以及相关出现次数的计数。然后 reduce 函数将特定单词发出的所有计数加在一起。

MapReduce 执行概述

通过将输入数据自动划分为一组 M 分割或碎片,映射调用被分布在多台机器上,这些将在多台机器上被处理。

Reduce 调用是通过使用用户指定的分区函数将中间密钥空间划分为 R 个片段来分发的。

下图描述了 MapReduce 操作的整个流程序列:

  1. 用户程序中的 MapReduce 库首先将输入文件分成 M 段,通常为 16MB-64MB/段。然后,它在一组机器上启动程序的许多副本。
  2. 该程序的副本之一是特殊的:主程序。其余的是由主人分配工作的工人。有 M 个映射任务和 R 个归约任务要分配。主设备挑选空闲的工人,给每个工人分配 M 或 R 任务。
  3. 被分配了地图任务的工作者读取相应输入碎片的内容。它从输入数据中解析出键/值对,并将每一对传递给用户定义的映射函数。产生的中间 K/V 对在存储器中缓冲。
  4. 周期性地,缓冲对被写入本地磁盘,由分区函数划分成 R 个区域。这些缓冲对在本地磁盘上的位置被传递回 master,master 负责将这些位置转发给 reduce workers。
  5. 当 reduce worker 从 master 获得位置时,它使用远程调用从磁盘读取缓冲的数据。当 reduce worker 读取了所有中间数据后,它会按照中间键对数据进行排序,这样所有相同的事件就会被分组在一起。(注意:如果中间数据量太大而不适合内存,则使用外部排序)
  6. reduce 工作器遍历排序后的中间数据,对于遇到的每个唯一的中间键,它会将该键和相应的一组中间值传递给用户的 Reduce 函数。reduce 函数的输出被附加到这个 Reduce 分区的最终输出文件中。
  7. 当所有的 map 任务和 reduce 任务完成后,主机唤醒用户程序。此时,用户程序中的 MapReduce 调用返回到用户代码。

执行注意事项:

  • 成功完成后,MapReduce 执行的输出可以在 R 输出文件中获得。
  • 为了检测故障,主服务器会定期 pings 每个工作线程。如果在某个点之后没有工作者响应,则该工作者被标记为“失败”,并且该工作者的所有先前任务工作被重置,以变得有资格在其他工作者上重新调度。
  • 发生故障时,会重新执行已完成的映射任务,因为它们的输出存储在故障机器的本地磁盘上,因此无法访问。完成的 reduce 任务不需要重新执行,因为它们的输出存储在全局文件系统中。

MapReduce 示例

我将用几个程序示例来结束本文,这些程序可以很容易地表示为 MapReduce 计算,并有助于描绘 M/R worker 进程的画面:

Distributed Grep — 如果匹配到一个模式,Map 函数会发出一条线。reduce 函数是一个恒等函数,它只是将提供的中间数据复制到输出中。

URL 访问频率统计—map 函数处理网页请求日志,输出 < URL,1 > 。reduce 函数将同一 URL 的所有值加在一起,并发出一个 < URL,total count > 对。

反向网络链接图— 映射函数为每个链接输出 <目标、源> 对,这些链接指向在名为“源”的页面中找到的目标 URL。reduce 函数连接与给定目标 URL 相关联的所有源 URL 的列表,并发出一对: < target,list(source) >

每台主机的术语向量— 术语向量将文档中出现的最重要的单词概括为一列 <单词、频率> 对。map 函数为每个输入文档发出一个 <主机名,术语向量> 对(其中主机名是从文档的 URL 中提取的)。reduce 函数被传递给给定主机的所有每个文档的术语向量。它将这些术语向量加在一起,丢弃不常用的术语,并发出最终的 <主机名、术语向量> 对。

倒排索引—map 函数解析每个文档,发出一个序列的 < word,document ID > 对。reduce 函数接受给定单词的所有对,对相应的文档 ID 进行排序,并发出一个 <单词,列表(文档 ID > 对。所有输出对的集合形成了一个简单的倒排索引。也很容易增加这个计算来跟踪单词的位置

冶金学家预测 NBA 球队成功的方法

原文:https://towardsdatascience.com/a-metallurgical-scientists-approach-to-predicting-nba-team-success-4bfa7b2bd6a7?source=collection_archive---------5-----------------------

彼得·蔡博士

由于我是博客社区的新手,请允许我介绍一下我自己。我是一名训练有素的冶金科学家,很难认为自己是一名专业的体育分析师。然而,在我内心的书呆子成长为完全成熟之前,我已经是一个忠实的篮球爱好者(包括打球和观看),并且作为一个技术领域的积极研究者,我通常倾向于通过创造性思维和定量分析从可用数据中发现新的见解。因此,下面的故事详细介绍了几个月的随机研究结果,试图回答我脑海中一个简单但反复出现的问题:篮球队的胜率在多大程度上反映了其球员的表现统计数据和比赛风格?

冶金研究界的一个普遍观点是,合金的性能与其化学组成或成分密切相关。例如,两种合金可能包含完全相同的类型的原子种类,但是由于它们的化学成分的平衡不同,它们的测量属性有很大不同。打个篮球的比方,我的假设的基本假设是,所有活跃在 NBA 的球员都可以根据他们在场上活动的共同相似性被分成有限数量的不同类别。如果大体上是真的,那么每支球队的名单就可以根据组成球队的球员类型来明确地描述。就像工程合金的化学成分决定了它的结构属性一样,我假设一个团队的球员构成应该反映它的获胜成功率。

眼前的挑战是找出如何具体定义这些“所谓的”玩家类别。最明显的分组就是篮球中的五个位置: PGSGSFPFC 。通常,一个球队的质量是通过一个球员名单的“深度”来评估的,这个“深度”是指占据每个位置的球员数量。不幸的是,传统的位置缺乏特异性,因为它们不能充分描述现代游戏中球员的进攻风格,在现代游戏中,角色可能有很大的重叠。例如,勒布朗詹姆斯正式成为一名小前锋,但像一名控球后卫一样,比传统的中锋更好地控制局面。另一方面,凯里·欧文是得分后卫,但打得更像得分后卫。最近几年,我们也引进了所谓的“延伸 5”,像布鲁克·洛佩斯这样的中锋,他们可以在内线投球,也可以游走到外线,以意想不到的效率投篮。让我们不要忘记凯文·杜兰特,一个 7 英尺高的小前锋,但拥有令人印象深刻的后卫般的技能。

对比赛风格更准确的描述是累积击球图表,这是一个赛季中在球场上尝试击球的所有位置的 x-y 图。利用各种 Python 库中的工具,我能够从网上抓取 2010 年至 2016 年间所有 NBA 球员的投篮数据。虽然数据的原始来源是 stats.nba.com,但因为包含拍摄图表信息的 API 最近变得无法访问,所以我从可靠的第三方网站www.nbasavant.com 间接获得了相关数据。为了说明投篮图表中包含的其他见解,请参见下面提供的勒布朗·詹姆斯和扎克·兰多夫过去一个赛季的图表。

显然,勒布朗·詹姆斯似乎更喜欢从篮筐的左侧(从球员的角度来看)投篮,而扎克·兰多夫更喜欢从另一侧投篮。这个观察相当有趣,因为伦道夫是左撇子,而詹姆斯是右撇子,这使得他们的倾向有些反常。由于球员之间的射门量不同,为了根据相似的射门图表模式有效地比较球员,我通过将数据的二维直方图与尝试的投篮总数归一化,将每个射门图表转换为热图。请看下面的例子,在过去的一个赛季中,联盟中几位杰出球员的 25 x 47 热图。

接下来是机器学习的魔力。我首先将每个玩家的 25 x 47 热图展开成 1 x 1175 个特征向量,然后将它们堆叠起来,创建一个数据矩阵,每行数据代表一个特定的玩家。平均每场比赛投篮不到一次的球员被排除在外,因为他们的累积投篮量不足以产生一个准确描绘他们投篮倾向的地图。然后,我继续应用一种经过试验但真正无监督的学习算法,K-means 聚类,将数据矩阵中相似的行/玩家分组在一起。使用“肘技术”,决定了球员可以根据他们的拍摄模式分为 7 类。7 个组的代表性质心是通过平均属于一个组的所有球员的击球图表创建的,如下所示。

看着这些图片,可以说有些群体并没有太大的不同。例如,组 2、组 3 和组 7 都由主要在内线活动的玩家组成,属于组 2 的玩家是否真正不同于组 3 的玩家是值得怀疑的。作为健全性检查,我根据组标签重新组织了累积数据矩阵中的所有行,并可视化了它的图像表示,如下所示。为了视觉上的清晰,超出半场线的不必要的数据被剪掉,因为“空白”背景对所有球员来说几乎是一样的。

盯着数据矩阵足够长的时间,你可以说服自己,聚类算法识别的 7 组球员实际上是彼此不同的。在成功地对球员进行分类之后,每支球队的组成可以通过 7 维“组成”向量来具体描述,属于一个组的球员人数作为向量的相应特征。例如,勇士队的组成向量为[4,3,1,1,3,2,0],这意味着其 2016-2017 年的球员名单由 4 名属于第 1 组的球员,3 名属于第 2 组的球员,1 名属于第 3 组的球员组成,…你明白了。再次提醒,平均每场比赛投篮次数少于一次的球员被排除在分析之外,所以名册的实际大小可能略大于组合向量的总和。然后,通过将 30 支球队中的每支球队的组合向量一个接一个地堆叠起来,来编译 30×7 的球队组合训练集,并且使用简单的线性回归模型来评估每一类球员相对于其对球队胜率的贡献所承担的“权重”:

通常,将一组训练示例(在我们的例子中是团队组成向量)分成训练集、交叉验证集和测试集被认为是一种良好的做法,以便确保模型的泛化,防止过度拟合,并避免潜在离群值的不良影响。由于团队组成数据集相对较小,仅包含 30 个训练示例,因此我使用了不同的方法来优化模型。对 24 个小组的随机子集进行线性回归,记录得到的拟合系数,包括截距值。这个过程重复了很多次,直到所有试验的平均拟合系数收敛到“最佳”值。

奇怪的是,简单的回归分析表明,第 2 组和第 6 组(最大的正系数)的球员对球队的成功贡献最大,而第 4 组和第 7 组(负系数)的球员对球队获胜的机会没有任何帮助。下面是回归模型的预测胜率图,通过团队组成矩阵和拟合系数之间的内积计算得出,与所有 30 个团队的实际胜率相比。

红线表示完美的可预测性,点的显著分散表明模型远非理想。然而,预测胜率和实际胜率之间的 R 平方值 0.49 并不是微不足道的,这证实了射击模式至少是团队成功的一个重要因素。

也许上述预测模型最明显的不足是完全没有考虑到玩家的表现指标。毕竟,获胜只需要一支球队比他们的对手得分更多,不需要火箭科学家告诉你,最好的球队也会有最好的得分手和防守者。类似于上面描述的分析方法,我再次应用 K-means 算法来识别独特的球员群体,这一次是基于从 stats.nba.com 获得的 16 类传统球员统计数据而不是射门图。这些包括比赛次数、上场时间、得分、投篮次数、投篮次数、三分球次数、三分球次数、罚球次数、罚球次数、进攻篮板、防守篮板、助攻、失误、抢断、盖帽和个人犯规。该算法成功识别了 8 个不同的玩家组,下面显示的是 jet 配色方案中 16 x 486 累积数据矩阵的彩色表示,根据组标签排序。深蓝色表示统计类别中的最低值,深红色表示最高值。

从图像中可以立即注意到几个有趣的细节。第二组包括大量几乎在每个统计类别都很低的玩家;这些多是被贬到替补席的“默默无闻”的球员,希望能被插入轮换阵容。与之形成鲜明对比的是,第 5 组的球员代表了目前超级巨星的上层梯队:拉塞尔·维斯特布鲁克、詹姆斯·哈登、伊塞亚·托马斯、德玛尔·德罗赞、达米恩·利拉德、德马库斯·考辛斯、勒布朗·詹姆斯、科怀·伦纳德、斯蒂芬·库里、凯文·杜兰特、吉米·巴特勒、约翰·沃尔、凯尔·洛瑞、埃里克·布莱索。有趣的是,这一组包括了过去一个赛季所有提议的和官方的 MVP 候选人,证明了该算法客观地识别联盟最佳球员的能力,其中一些球员,如埃里克·布莱索,由于球队表现不佳或赛季结束受伤而被忽视。第七组包括联盟中著名的大个子:安东尼·戴维斯、卡尔-安东尼·唐斯、扬尼斯·阿德托昆博、乔尔·恩比德、克里斯塔普斯·波尔津吉斯、拉马库斯·阿尔德里奇、哈桑·怀特塞德、尼古拉·约基奇、尼古拉·武切维奇、迈尔斯·特纳、鲁迪·戈贝尔、安德烈·德拉蒙德、德怀特·霍华德和迪安卓·乔丹。同样,有趣的是,根据流行的看法,名单中的一些球员并不被认为是全明星级别的,即使他们的表现数据表明并非如此。

像以前一样,我继续对基于统计的团队组成矩阵的随机子集应用迭代线性回归。不出所料,拟合系数的值显示,上一段中讨论的第 5 组和第 7 组对团队的成功贡献最大。下面显示的是预测胜率与实际胜率的散点图,预测值由基于统计的回归模型的拟合系数计算得出。

关于这些结果没有太多可说的,只是第二个回归模型的可预测性与第一个模型不相上下。为了改进模型,我尝试了一个“愚蠢”的简单方法,将第一个合成矩阵与第二个合成矩阵合并成一个 30×15 的矩阵;简单的理由是,由于投篮命中率和表现统计都是球队成功的重要因素,也许结合两者的回归模型会导致预测准确性的提高。

事实上,混合回归模型的预测胜率之间的相关性明显好于前两个模型,其 R 平方值为 0.71,RMSE 误差为 0.07。

进一步改进该模型的一个可能的方法是通过合并说明一个组中每个玩家的独特性的信息。回想一下,在团队组成向量的创建中,特定组中的玩家被认为是彼此无法区分的;勒布朗·詹姆斯对一支球队的价值被认为和德马库斯·考辛斯一样。换句话说,即使在一个给定的组中的玩家之间有轻微的差异,这些差异也被分析方法忽略了。

我得出的解决方案是用一个给定玩家到群体质心的相对“距离”来评估这个玩家对所有群体的贡献。也就是说,如果将组形心想象成不同的颜色,每个玩家将被表征为所有颜色的部分混合,而不是采用最近形心的绝对颜色。玩家的数据表示越像特定的质心,它对该组的贡献就越大;相反,远离质心的玩家对相应组的贡献很小。由此可见,玩家到质心的距离 d 的倒数可以作为接近度的定量度量,并且玩家对组 i 的分数贡献可以由以下表达式给出:**

使用该策略,构建了新的 30×15 团队组成矩阵,并再次应用线性回归来计算模型的新拟合系数。令人惊讶的是,新模型的预测结果乍一看并没有显示出明显的改善(R 平方= 0.71,RMSE 误差为 0.07),即使每个队的组成向量现在更准确地描述了其组成球员的个性。为了比较,下面是两个混合回归模型的“预测与实际”图。

尽管为两个模型计算的 R 平方值几乎相同,但对图的进一步观察表明,新模型中绘制的数据点的分布更加结构化。例如,右边图中的淡蓝色线是“完美可预测性”趋势线的变化版本。注意它们与数据点的重叠程度;本质上,这表明了超额预测的胜率都偏离了实际胜率几乎相同的量(~ +0.10),对于预测不足的胜率团队也是如此(~ -0.07)。对这些观察结果的合理解释是,也许所有被高估或低估的球队都有不可忽视的相似之处(例如,球员受伤、赛季中期名单变化、教练、团队化学等)。)是新模型没有考虑到的。然而,确认是否如此需要进一步的分析,这超出了本初步研究的范围。

因为本研究中的回归模型是建立在团队组成决定成功的基本概念之上的,所以它有可能被用作建立成功 NBA 球队的指导工具。假设一名球员的表现统计数据和特征投篮图表可以从一个球队转移到另一个球队,该模型可以提供一个相当不错的潜在收购对球队获胜机会的直接影响的定量估计。据我所知,我可能是错的,整个联盟管理层的团队重组决策仍然主要植根于人类的直觉和传统智慧。我并不是建议球探和人类的直觉应该被计算模型所取代,但我个人认为,NBA 的名册建设工作肯定可以受益于比现在更受数据驱动。

一个没有时间的头脑:对向阿尔茨海默病转化的分类

原文:https://towardsdatascience.com/a-mind-without-time-classifying-the-conversion-to-alzheimers-disease-1a5c6079bb91?source=collection_archive---------12-----------------------

这是我在跳板数据科学职业生涯的第一个顶点项目的总结。

由于我的背景是脑科学,我想从事与我的专业领域相关的机器学习工程。令人欣慰的是,许多伟大的科学家和医生已经投入了大量的工作,使大量关于阿尔茨海默病(AD)的数据公开和可访问。我在这个项目中使用的数据集来自阿尔茨海默病神经成像倡议(ADNI),主要由南加州大学神经成像实验室(LONI)管理。这不是唯一一个公开的关于 AD 的数据集,但它似乎包含了我认为与识别有患 AD 风险的人相关的最多样化的变量集。

我从 ADNI 检索到的数据集包括已知在某些方面与 AD 相关的变量。其中包括:

  • 年龄和性别等人口统计信息
  • 相关认知评估的分数
  • 大脑区域体积和皮质厚度的估计
  • 脑功能活动的测量
  • APOE4 等位基因的存在

研究的基本原理

我查阅了已发表的关于 AD 分类的文献,发现大多数研究都专注于使用特定的数据类型,无论是认知评估还是基于 MRI 的测量。很好,最近对这些研究的综述是 多变量数据分析和阿尔茨海默病的机器学习,重点是结构磁共振成像

虽然确切的指标和评分标准因研究而异,但使用 MRI 特征的方法通常以 68-75%的准确度将转换器与非转换器进行分类。使用多模态特征集的性能更好,以 68–82%的准确度分数将转化者与非转化者进行分类,我观察到的最高准确度分数是 91.5% 在专门对转化为 AD 的 MCI 患者进行分类时。考虑到一些基准,我接下来概述了我的研究用例。

目标受众和使用案例

这项研究的主要目标受众是医疗保健提供者。结构和静息态功能磁共振成像是最简单和最快的大脑成像方法之一。使用它们对处于危险中或患有 AD 的人进行分类将有助于提供早期干预和针对性治疗。重要的是,能够准确地对有转化为阿尔茨海默病风险的人进行分类也将允许医院在资源稀缺时优先考虑用于预防的资源。

作为科学家,另一个目标受众是学术界。这是我写这些论文和博客的很大一部分原因。正如牛顿的名言

如果说我看得更远,那是因为我站在巨人的肩膀上

我能在这么短的时间内,只用我的笔记本电脑完成这项研究的原因是因为研究社区的存在,他们推动数据和数据分析向所有人开放和开放。如果没有 ADNI 或 Sci-Kit Learn 的开发人员,将会有一个人无法合理完成的大量工作。我坚信科学最好是在开放的环境中进行,方法、代码和数据都可以向其他人公开。在我看来,这大大加快了集体知识和对世界以及我们在其中的位置的理解的速度。

在接下来的部分中,我将概述我在这项研究中采取的具体步骤,如果您想自己运行它(我强烈建议这样做),可以链接到代码和数据。如果你只对研究结果感兴趣,直接进入第三步。

第一步:数据争论

无论好坏,数据争论是数据科学的核心,通常需要大量的时间投入。当数据集对您来说很陌生时尤其如此,因为您需要了解您正在处理的变量、它们之间的潜在关系、它们与您正在解决的特定问题的关系,以及需要对它们做些什么才能使模型构建成为可能。

我采取的所有数据争论步骤都包含在这个 Jupyter 笔记本中。注意,所有的编码都是用 Python 完成的。简而言之,我采取的步骤是:

  • 重命名列,使它们更容易理解和理解
  • 从主数据帧中提取感兴趣的列
  • 将主数据框与包含 fMRI 测量的数据框合并
  • 记录缺失值
  • 删除或估算缺失值
  • 将时间序列列减少到具有感兴趣的测量的患者就诊
  • 处理诊断变更栏中的缺失值
  • 识别并清除诊断更改列中的重复条目

清理后的数据帧在这里可用。

步骤 2:探索性数据分析

像数据争论一样,一个好的 EDA 是数据科学工作流程的重要组成部分。这是你开始理解其中的数据和模式的机会,也是你开始讲述背后的故事的机会。我们通常带着特定的假设/问题来处理数据集,一个有洞察力的 EDA 将显示为什么该假设是重要的,但也可能揭示与假设/问题相关的有趣方面,这些方面可能无法从我们的直觉和领域专业知识中获得。

这方面的一个例子是我在 EDA 期间做的一些功能工程。当观察不同诊断组(即 AD、认知正常、早期轻度认知障碍、晚期轻度认知障碍、显著记忆问题)的认知评估得分之间的关系时,我注意到两种易于使用的认知评估之间的相关性随着认知障碍的严重程度而变化。

Correlation matrices showing the relationship between scores on different cognitive assessments broken down by diagnosis type

这些图中有两个要点需要注意。首先,如果我们只看整个组内的关系,数据中有趣的模式会被掩盖。第二,测试分数之间的相关性随着诊断类型的不同而变化。在 AD 患者中,CDRSB 和 ADAS13,以及 MMSE 和 MOCA 之间存在高度正相关。这些相关性在晚期 MCI 患者中有些明显,在 CDRSB/ADAS13 相关的情况下,在认知正常的人群中呈负相关。为了进一步研究这一点,我创建了一个新的特征向量,它采用了 CDRSB 和 ADAS13 之间的得分差异。这只是特征工程捕捉这方面数据的一种方法,但正如我们稍后将看到的,这是将转化为 AD 的患者与未转化为 AD 的患者进行分类的一个重要特征。

完整的 EDA 在这个 Jupyter 笔记本中可用,用于建模的最终数据帧是这里的。请注意,我使用这个 EDA 作为学习伟大的 plotly 可视化库的机会。虽然我没有在离线模式下编码所有的情节,所以笔记本没有渲染所有的情节。你可以下载相关的eda.html文件,看看他们辉煌的剧情。

老年痴呆症患者的画像

虽然没有大量的人口统计信息,但观察典型的 AD 患者是什么样子还是很有趣的。

Demographic information for patients with Alzheimer’s Disease at baseline

正如我们在图中看到的,基线时 AD 患者的平均年龄大于其他诊断组,男性,受教育程度较低且已婚。

皈依者与非皈依者

虽然注意到典型的 ad 患者是什么样子是很有趣的,但我的目标是对有转化为 AD 风险的人进行分类,而不是对那些在基线访问时患有 AD 的人进行分类。下图显示了在研究的某个时间点转化为 AD 的患者的人口统计学信息。

Demographic information for patients that convert to Alzheimer's Disease during the study

不足为奇的是,典型的转化者被诊断为晚期轻度认知障碍而进入研究。这是因为轻度认知障碍,尤其是晚期轻度认知障碍,被认为是功能正常的人和被诊断为 AD 的人之间的中间步骤。此外,他们通常是男性,平均年龄较大,有大学学位,已婚,不是西班牙裔/拉丁裔。

EDA 包含大量信息,因为数据集非常大,并且包含许多不同的要素和要素类别。我通过它们找出了认知正常、轻度认知障碍和 AD 之间的区别。这是通过将数据中的趋势可视化,以及主要使用事后检验的 ANOVAs 进行一些统计推断来完成的。

步骤 3:模型评估和优化

在 EDA 之后,我决定在训练模型时使用一组精简的特征,以便最大化训练/测试集中的数据点。显示诊断类型之间差异并记录大多数患者就诊的主要特征类别是人口统计学信息、认知评估得分(不包括 MOCA)、海马和内嗅皮层的体积估计以及 APOE 突变的存在。其他特征记录得更少,将它们包含在训练集中意味着要处理大量缺失数据或丢弃大量观察值。参见下一步的最后一节,了解我打算如何处理这里没有包括的特性。

用于模型评估和优化的 Jupyter 笔记本可在这里获得。请注意,笔记本中有两个主要功能,您可以在自己的工作流程中复制和使用。这些功能允许您训练、优化和评估不同的分类器。

我的基本管道是这样的:

  1. 提取特征值和目标标签
  2. 将数据集分为训练集(75%)和测试集(25%)。请注意,这是一个分层的分离,以保持训练/测试集中转换者与非转换者的比例。这在这样的情况下是很重要的,因为这里有不止一个目标类(这里是非皈依者)。
  3. 缩放非二进制数据
  4. 使用网格搜索交叉验证优化超参数
  5. 评估模型

为了评估这个模型,我考察了三个指标。

  1. 测试集的准确度分数
  2. ROC 曲线下面积
  3. 平均精度

我还绘制了 ROC 和 precision-recall 曲线,以便更好地了解性能。

笔记本显示了四个模型的结果:逻辑回归、随机森林、XGBoost 和支持向量机。我建议把它们都记下来,看看它们的表现有什么不同。现在,我将关注 XGBoost 模型,因为它在三个评估指标中表现最好。

Performance of XGBoost model on classifying coverts from non-converts

如果你以前看过这些图,你会发现这个模型在对转化为 AD 的人进行分类方面做得非常好。ROC 曲线绘制了真阳性率(被归类为转化为 AD 的患者,他们在研究期间确实转化为 AD)与假阳性率(被归类为转化为 AD 的患者,他们实际上并未转化为 AD)的对比图。精确回忆曲线的工作原理略有不同。精度是真阳性率除以真阳性率加上假阳性率。这告诉你分类器在标记真正皈依者时有多精确。召回率是真阳性率除以真阳性率加上假阴性率,假阴性率表示被归类为非皈依者的患者实际上皈依了。这是这项研究的一个重要指标,因为分类器的用例是帮助识别应该接受早期干预和预防性护理的患者。在这个用例中,向不太可能转化的人提供这些资源(误报)比不向可能转化的人提供这些资源(误报)要好。

总的来说,模型表现得非常好。请记住,它所做的是将一个人分类为在未来某个时间转换为 AD 或不转换。评估指标包括:

  • 测试数据的准确率为 92.1%
  • 测试数据的 ROC 曲线下面积:0.975
  • 平均精度:0.787

准确性分数比我在《将皈依者与非皈依者进行分类》中看到的有了很大的提高,并且在将 AD 患者与认知正常的个体进行分类的更简单的任务上也有相似的准确性分数。但是,该模型也过度拟合了训练数据,准确率为 100%。

为了了解不同的特性是如何对模型产生影响的,我根据它们的重要性分别绘制了图表。

Feature importance in final model

虽然这只是评估特征如何影响分类模型的一种方式,但它提供了模型如何区分转换者和非转换者的初步观察。主要特征是年龄,ADAS13 和 CDRSB,海马和内嗅皮层的体积估计,以及 APOE4 等位基因。有趣的是,基线诊断并不重要。

后续步骤

首先,我只评估了一组精简的特性。数据集中有更多的可用数据,但这是以丢失数据增加为代价的。合乎逻辑的下一步将是训练包括其他特征类别的新模型,并观察它们与基线模型相比如何。

第二,为了处理过度拟合,我正在考虑做一些功能工程,以包括更多的功能(一个例子是在基线模型中包括功能之间的交互),并调整交叉验证用于优化模型的得分度量。

第三,该模型目前表明一个人是否在某个时候有转化为 AD 的风险。预测转换的时间框架是可能的。这不会影响评估和转化为 AD 之间的时间,但会提示对资源有限的医院或护理人员有用的预防性治疗的紧迫性。

还有其他潜在的下一步,虽然这些对我来说是唾手可得的。我希望你喜欢这个概述,并学到了一些新的东西。如果您对研究有任何疑问,请联系我。

德鲁·康威数据科学维恩图的一个修正

原文:https://towardsdatascience.com/a-modification-of-drew-conways-data-science-venn-diagram-d5ba93037e1a?source=collection_archive---------5-----------------------

在大会上我们的数据科学沉浸式项目的第一周,我们的一位讲师马特·布雷姆斯展示了德鲁·康威著名的维恩图。

Drew Conway’s Data Science Venn Diagram

Brems 解释了每个圆圈以及交叉点,并强调了危险区域。以下是他对那个十字路口的人的体验:

我亲眼看到人们处于“危险地带”。“这些人对他们应用数据科学的现实世界问题有着非常扎实的理解,并且拥有出色的编程技能——甚至使用涉及统计的库或函数。因为这些人所拥有的技能,他们知道一种特定的建模技术可能被设计来解决现实世界的问题,并且可以利用他们的 Python(或 R,等等)。)实现它的技巧。但是,不会弹出错误消息警告用户建模技术的假设不合理或者数据没有正确缩放。在许多情况下,所发生的是正在建立的模型类型依赖于不满足的假设。因此,这些模型可能无法准确反映真实发生的情况,因此使用这些模型来更好地了解世界或解释一些现实世界的现象可能是不合适的。虽然分析通常是出于好意,但是仅仅因为 Python 能够给你一个结果并不意味着它是有意义的。当有人对一个可能误导的结果采取行动时……嗯,这就是为什么“危险区”——不理解建模背后的统计数据——会如此危险。”

康威对处于危险地带的人也有类似的看法,但他也认为恶意可能是这个十字路口的一些人的动机:

“在这个领域,完全有能力提取和构建数据的人,可能与他们相当了解的领域有关,甚至可能知道足够的 R 来运行线性回归并报告系数;但是他们对这些系数的含义缺乏理解。“谎言、该死的谎言和统计数据”这句话就是从图表的这一部分发出的,因为不管是出于无知还是恶意,这种技能的重叠让人们有能力做出看似合理的分析,而不知道他们是如何做到这一点的,也不知道他们创造了什么。”

我理解 Brems 和 Conway 的想法,但是危险区域不应该成为那些拥有编程技能和领域知识但缺乏数学技能的人的默认标签。是的——这个地区的人们有可能遇到危险,但前提是他们在没有适当的数学或统计学知识的情况下试图做出统计推断。然而,处于危险区域的人可以为分析/数据科学团队做出巨大贡献。我这样说是因为这是我过去几年工作的领域。

数据项目管理

我以前的工作是管理劳联-产联的会员数据。AFL-CIO 是一个工会联合会,每个工会都有一份成员名单。我们的分析团队需要一份准确的成员名单,以便他们可以创建各种模型,并根据该名单进行投票。

这项任务要求我作为项目经理与客户组织的 IT 部门合作,以确保他们及时提交成员文件。美国劳联-产联有数百万成员,我不仅需要了解数据应该是什么样子,还需要有黑客技能,能够对数据进行适当的探索性分析。

这是至关重要的,因为如果客户联盟在他们的数据上犯了一个错误,例如丢失了三分之一的文件,丢失了一个字段,或者交换了名字和姓氏等字段,这可能会对我们的程序产生负面影响。尽管这些错误不一定是我的错,但我要对它们负责——责任在我。我需要保持警觉,准备好抓住这些错误,并为客户提出解决方案。

尽可能提高这一过程的效率也很重要。许多客户希望在文件从他们的数据库中出来时就交付文件。我必须指导许多客户以标准格式提交数据,以简化流程,这需要与这些 it 部门建立关系。

他们说数据科学 80%是清洗数据,只有 20%是分析。向我们的分析团队交付我们的会员文件是我热衷的事情,因为这使他们能够进行他们拥有技能的更高层次的分析。

描述性分析

除了每个客户的 IT 部门,我还与每个组织的政治主管建立了关系。劳联-产联提供的一项关键服务是为劳工运动共享政治资源,这就是为什么政治指导者是重要的利益相关者。

尽管一些政治指导者可能对进入模型构建的杂草感兴趣,但许多人想要他们的数据的肉和土豆。我管理的成员更新过程的一部分是向他们的成员添加政治数据字段。

我开发了可复制的报告,这些报告将在会员更新周期结束时为每个会员生成,这些报告将告诉政治主管他们的工会成员中有多少人是注册选民,他们注册了哪个政党,他们在哪些选举中投票,等等。

这些报告对数学的要求都不比计算或生成百分比的能力更高。然而,这些报告得到了广泛的赞赏,因为我用我的领域知识和黑客技能创造了一个这些关键利益相关者想要的产品。

我并不是说我们的分析团队不能做同样的工作,但这项工作会有机会成本。由于我负责数据采集、增强和向附属机构报告关于其会员资格的描述性统计数据,我们的分析团队可以更加专注于分析会员和投票者数据,以帮助推动我们组织的战略。

数据支持:黑客和领域知识的交集

事实是,任何一个极端的十字路口都可能是危险地带。处于领域知识和数学技能的交叉点,但不会编程的人将总是被 Excel 电子表格提供的百万记录限制所限制。如果有人处于黑客技术和数学技能的交叉点,但不具备他们行业的领域知识,他们可能会提出一个理论上很好的建议,但由于他们行业的现实,这个建议是站不住脚的。

Data Support: The Intersection of Hacking Skills and Substantive Expertise

尽管我不是我们分析团队的成员,但以上是我为支持他们的工作所做贡献的例子。这种关系之所以有效,是因为我没有试图扮演数据科学家。我没有尝试运行回归、神经网络或决策树,并以某种方式、形状或形式使用它来影响我们组织的战略。然而,我总是钦佩他们的工作,因此我现在在大会上提高我的数学技能。

分析和数据科学团队应该寻找符合这些技能的人。站在这些人的肩膀上,他们可以专注于分析,以帮助他们的组织取得成功。

一种求解聚类问题的改进人工蜂群算法

原文:https://towardsdatascience.com/a-modified-artificial-bee-colony-algorithm-to-solve-clustering-problems-fc0b69bd0788?source=collection_archive---------6-----------------------

Python 中的分步实现。

Image credit: https://www.wikipedia.org/

在我的上一篇文章中,我已经介绍了我们如何通过实现一个叫做人工蜂群(ABC)群体智能(SI) 算法来解决现实世界的优化问题。

现在是我们接触一些真实数据并解释如何使用 ABC 算法的 Python 实现来执行聚类任务的时候了。但在此之前,让我们更深入地了解一下集群问题

聚类问题

聚类问题是一个非明确定义的 NP-hard 问题,其基本思想是在我们的数据中发现隐藏的模式。对于什么是集群并没有正式的定义,但是它与以这样一种方式对元素进行分组的想法相关联,即我们可以区分不同组中的元素。

有不同系列的算法以不同的方式定义聚类问题。在文献中经常看到的定义聚类问题的经典方法是将其简化为一个数学问题,称为寻找原始数据的 k 划分

寻找集合 Sk-划分 ,被定义为寻找 Sk 子集,它遵循两条规则:

  • 这些子集的任何不同子集的交集等于空集。
  • 所有 k 子集的并集等于 S.

基本上,在这个划分聚类过程的最后,我们希望找到原始数据集的不同子集,这样,没有一个实例属于一个以上的组。下图说明了这一点:

On the left the original data, on the right the partitioned data with k=2.

An example of how centroids can be used to perform a data partition with k=2.

我们如何分割数据来执行上图所示的分区?嗯,聚类过程的输出是一组质心。质心基本上是每个组的代表实体,所以如果我们想要我们的数据的一个,那么我们将有 k 质心。

质心也是由我们的数据定义的搜索空间上的点,由于每个质心定义一个组,每个数据点将被分配到离它最近的质心。

修改人工蜂群进行聚类

好了,现在我们知道什么是聚类问题,我们如何修改原始的 ABC 算法来执行这样的任务?你猜怎么着,我们没有!是的,这就是你刚刚读到的,我们根本不需要修改我们的 ABC 实现。我们唯一要做的就是关注集群问题,并将其转化为优化任务!但是我们怎么做呢?

正如我们在上一篇文章中看到的,一个定义良好的优化问题需要一个搜索空间,一组 d 维输入决策变量和一个**目标函数。如果我们将人工蜂群中的每只蜜蜂视为聚类问题的整体解决方案,那么每只蜜蜂可以代表一组完整的候选质心!如果我们在一个 d 维空间上工作,并且我们想要在我们的数据集上执行一个 k 分区,那么每只蜜蜂将是一个kd 维向量!****

厉害!既然我们已经定义了如何表示我们的输入决策变量,我们只需要弄清楚如何定义我们的搜索空间的边界以及什么将是我们的目标函数。

我们的搜索空间的边界很容易,我们可以用[0,1]区间归一化我们的整个数据集,并将我们的目标函数定义为具有从 0 到 1 的边界。搞定,就这样。现在让我们进入更复杂的部分:如何定义我们的目标函数?

划分聚类方法中,我们希望最大化两个不同组之间的距离,最小化一个组内的内部距离。文献中使用了几个目标函数,但最广为人知和使用的是【SSE】**。**

Formula for the Sum of Squared Errors. Don’t be afraid, is not that scary.

这个公式是什么意思?嗯, 误差平方和(SSE) 是一个聚类度量,背后的思想很简单。它基本上是一个数值,计算数据中每个实例到其最近质心的平方距离。我们优化任务的目标是最小化这个函数。

我们可以使用我们之前的目标函数框架来实现如下的 误差平方和 :

用真实的数据动手

是时候用一些真实的数据来测试我们的 ABC 聚类算法的性能了。对于这个研究案例,我们将使用众所周知的 虹膜数据集

这是一个原始的 4 维数据集,包括三种植物的特征。出于可视化的目的,我们将只使用这个数据集的两个维度。让我们检查该数据集的第二维度和第四维度之间的关系:

上面代码的输出如下所示:

The original data distribution.

由于我们将使用该数据作为基准测试,我们已经知道它的最优分割是什么,以及它由三种类型的花的原始分布给出。我们可以用下面的 Python 代码来可视化 虹膜数据集 的原始最优分区:

其中绘制了以下分布:

The original groups within our dataset

既然我们已经知道了这个样本数据的原始最优分区是什么,那么是时候看看我们的 ABC 算法是否能够找到这个问题的非常接近的解决方案了。我们将使用我们的 误差平方和 目标函数,并将分区数量设置为三。

由于初始化是随机的,很可能生成的质心的顺序与类的顺序不匹配。因此,当绘制 ABC 算法的输出时,各组的颜色可能不匹配。这并不重要,我们真正要看的是对应的分区组看起来有多好。

我们的 Python 代码的输出如下所示:

The partition of our dataset found by the ABC algorithm.

哇,太棒了!如果我们看一下原始分区和由我们的 ABC 算法生成的分区,我们可以看到它能够找到一个真正接近最优的分区。这证明了“改进的”ABC 聚类算法是多么强大。我们还可以通过查看 ABC 算法的optimality _ tracking属性来了解优化过程是如何进行的:

正如所料,ABC 算法在最小化 SSE 目标函数方面非常有效。我们可以看到群体智能拥有一些解决优化问题的强大机器,将这些算法用于解决现实世界的问题只是我们如何将这些问题转化为优化任务的问题。

参考

  • 一种新颖的聚类方法:人工蜂群算法——德尔维斯·卡拉博加,塞拉尔·厄兹图尔克
  • 一种采用协同人工蜂群算法的聚类方法 —邹文平、、陈汉宁、
  • 人工蜂群算法及其在数据聚类中的应用综述 — Ajit Kumar,Dharmender Kumar,S. K. Jarial
  • 一种用于聚类的两步人工蜂群算法 — Yugal Kumar,G. Sahoo

下一步是什么?

我们已经通过实现人工蜂群算法简单介绍了群体智能,以及如何用它来解决一些有趣的问题比如优化实函数,如何“修改”ABC 算法来解决聚类问题。

这些算法有大量的应用,如图像分割、人工神经网络的训练、数字图像处理和模式识别、蛋白质结构预测等等。还有一些其他强大的群体智能(SI) 算法,如粒子群优化(PSO)鱼群搜索(FSS) ,它们也是非常众所周知的技术,并有一些有趣的应用。

敬请期待下一章!

一种新的深度神经网络

原文:https://towardsdatascience.com/a-new-kind-of-deep-neural-networks-749bcde19108?source=collection_archive---------2-----------------------

作者阿尔弗雷多·坎齐阿尼、阿比舍克·乔拉西亚和尤金尼奥·库勒西略

又有新一波深度神经网络来了。它们是前馈模型的演变,我们之前详细分析过。

这种新型神经网络是最初的前馈模型lenet 5/Alex net及其衍生模型的进化,包括比ResNet/Inception更复杂的旁路方案。这些前馈神经网络也被称为编码器、,因为它们将图像压缩和编码成更小的表示向量。

新一波神经网络有两个重要的新特征:

  • 生成分支:也称为解码器,因为它们将一个表示向量投射回输入空间
  • 重现层:将先前时间步的表示与当前时间步的输入和表示相结合

太好了!但是这种增加的复杂性能为我们做什么呢?

原来传统的前馈神经网络有很多局限性:

1- 无法精确定位:由于较高层中的下采样和空间分辨率损失,特征/对象/类别的定位受损

2- 无法对场景进行推理:因为他们将图像压缩成一个简短的表示代码,他们丢失了关于图像如何构成以及图像或场景的部分如何在空间上排列的信息

2-具有时间不稳定性:由于他们是在静止图像上接受训练的,他们没有学会物体在空间中运动的平滑时空变换。它们可以识别某些图像中的物体类别,但不能识别其他图像,并且对敌对噪声和扰动非常敏感

3- 无法预测:由于不使用时间信息,前馈神经网络仅基于当前输入在每一帧提供新的表示代码,但无法预测接下来几帧会发生什么(注意:除了例外,未在视频上训练)

为了超越这些限制,我们需要一种新的网络,它可以将学习到的表达投射回输入图像空间,并且可以对时间上连贯的图像序列进行训练:我们需要对视频进行训练

这是这些新网络可以提供的高级功能列表:

  • 无监督学习:它们可以在视频上进行预训练,以预测未来的帧或表示,从而需要少得多的标记数据(在视频上很昂贵!)来训练执行一些任务
  • 分割 : 分割图像中的不同对象
  • 场景解析:如果数据集具有逐像素对象标签,则遵循分割,用于自动驾驶和增强现实
  • 定位:遵循分割和完美的对象边界,所有的场景解析和分割网络都可以做到这一点!
  • 时空表示:使用视频进行训练,而不仅仅是静止图像,了解时间概念和时间关系
  • 视频预测:一些网络被设计成预测视频中未来帧
  • 表示预测:某网络可以预测视频中未来帧的表示
  • 通过监控预测和实际未来帧或表示之间的误差信号来执行在线学习的能力

现在让我们检查这些新网络的细节和实现,如下所示。

生成梯形网络

这些模型使用编码器和解码器对来将图像分割成部分和对象。例子有: ENet , SegNet , Unet , DenseNets ,梯形网络等等。

下面是一个典型的三层模型:

D 模块是标准的前馈层。 G 模块是生成模块,类似于标准前馈层,但具有去卷积和上采样功能。它们还使用类似残差的连接“RES”将每个编码器层的表示连接到其中一个解码器层。这迫使生成层的表示由前馈表示来调制,从而具有更强的将场景定位和解析为对象和部分的能力。【x】是输入图像,【y】是输出分割的同时步。

这些网络可以执行分割、场景解析和精确定位,但是不在时间域中操作,并且没有过去帧的记忆。

最近,每层的编码器到解码器旁路帮助这些网络实现了最先进的性能。

递归和生成梯形网络

最新的深度神经网络架构之一将递归添加到生成梯形网络中。这些是递归和生成式梯形网络(REGEL,我们称之为 CortexNet 模型),它们是迄今为止最复杂的深度神经网络模型之一,至少对于图像分析来说是如此。

这是我们目前使用的一个网络的三层模型:

DG 模块实际上与上述生成梯形网络中的模块相同。这些网络增加了从每个 G 模块到同一层中相应的 D 模块的循环路径“t-1”

这些网络将视频中的一系列帧作为输入 x[t] ,并在每个时间步预测视频中的下一帧 y[t+1] ,如果预测准确的话,该帧接近 x[t+1]

由于该网络可以测量预测和实际下一帧之间的误差,它知道何时能够预测输入或不能够预测输入。如果没有,它可以激活增量学习,这是前馈网络所不能做到的。因此,它能够执行固有的在线学习

我们认为这是机器学习的一个非常重要的特征,是预测神经网络的特权。没有这个特征,网络就不能提供真正的预测置信度信号,也不能进行有效的增量学习。

这些网络仍在研究中。我们的建议是:保持警惕!

预测编码网络—第 1 部分

递归生成网络是一种可能的预测模型。或者,预测编码计算神经科学模型可以提供预测能力,并被安排为分层深度神经网络。

下面是一个两层模型的示例:

Rao 和 Ballard 模型和 Friston 实现计算“A”模块(类似于梯形网络上的 D 模块)和R/Ay】模块(类似于梯形网络上的 G 模块)之间每一层的误差“e”。这个误差“e”表示在每一层,网络预测表示的能力。错误“e”然后作为输入被转发到下一层。“R”是卷积 RNN/LST 模块,“Ay”类似于“A”模块。【R】【Ay】也可以组合成一个单独的循环模块。在第一层 "x" 是输入帧。

这个模型的问题是,这个网络与标准的前馈神经网络非常不同。它不在创建较低层特征组合的较高层创建分层表示,而是这些预测网络计算先前层的残差的表示。

因此,它们有点让人想起残差前馈网络,但在实践中,迫使这些网络转发错误并不会导致它们在更高层学习有效的分层表示。因此,它们不能有效地执行基于上层表示的其他任务,例如分类、分割、动作识别。需要更多的实验来证明这些局限性。

这个模型已经由 Bill Lotter 和 David Cox 在 PredNet 中实现。类似的型号也来自大脑公司。

预测编码网络—第二部分

Spratling 预测编码模型将表示 y 投射到上层,而不是误差“e”,如在上面的 Friston 模型中所执行的。这使得该网络模型与分层前馈深度神经网络更兼容,并避免了上层中的学习误差时刻。

下面是一个两层模型的示例:

这个模型可以基本上重写并简化为我们上面看到的递归生成阶梯模型。这是因为“R”“Ay”可以组合成一个单独的循环模块。

与生成性对抗网络的关系

生成对抗网络(GAN)是一种非常流行的模型,它能够学习从数据分布中生成样本。这里介绍的新网络模型优于 GAN,因为:

  • 他们不是在一个极大极小游戏中被训练,而是直接为一个有用的任务被训练,所以鉴别器和生成器都是直接有用的
  • 他们学习创建有用的输入表示,同时也能够生成新的输入
  • 他们可以学习根据输入生成目标数据
  • 发生器和鉴别器网络连接在一起,消除了收敛问题
  • 与 GAN 提供的难看的结果相比,该生成器提供了近乎完美的照片级真实样本(见下文)

Example of CortexNet predictive capabilities — Left: current frame, Center: next frame ground truth, Right: predicted next frame

其他型号的注意事项

像 CortexNet 这样的模型让人联想到像素递归网络及其各种实现( PixelCNN 、 Pixel CNN++ 、 WaveNet 、等)。这些模型旨在对输入数据的分布进行建模:(“我们的目标是估计自然图像上的分布,该分布可用于计算[数据]的可能性并生成新的数据。”).他们只专注于生成新的现实数据样本,但没有显示出学习现实生活任务的表示。这些模型的推理速度也非常慢。

结论

关于这个话题的一篇论文是这里。CortexNet 仍在研究和评估中。例如,最近的 PredNet 论文对预测编码和梯形网络进行了比较,PredNet 在某些任务上胜出。PredNet 用于执行方向不变的人脸分类,使用较高层表示。它还可以预测数据集中的转向角,但主要是使用网络第一层的简单运动滤波器。这项任务不需要对特征进行层次分解。

关于作者

我在硬件和软件方面都有将近 20 年的神经网络经验(一个罕见的组合)。在这里看关于我:媒介、网页、学者、 LinkedIn 等等…

Matplotlib 的新情节主题——牛虻

原文:https://towardsdatascience.com/a-new-plot-theme-for-matplotlib-gadfly-2cffc745ff84?source=collection_archive---------6-----------------------

Sample plots from the new plotting theme inspired by the Gadfly plotting package for the Julia programming language

介绍

我为 Matplotlib 制作了一个绘图主题,灵感来自于牛虻中为 Julia 编程语言使用的默认绘图主题。通常我会用 Julia 写代码,这也是我在以前的博客文章中所做的。然而,自从升级到朱莉娅 1.0 版,我已经无法导入牛虻,这意味着没有更多漂亮的牛虻情节。所以我对自己说“ Jonny,是时候自己创造主题了”。我做到了!

(如果您想了解如何使用该主题,请跳到最后一节)

更多(漂亮的)情节

KDE 地块

Left: Two 1-dimensional kernel density estimate (KDE) plots. Right: A 2D KDE plot.

线形图

All the lines. Code to generate the data shamelessly stolen from Jake VanderPlas’s article on how to create Simple line plots in Python.

散点图

Scatter plot. Code to generate the plot shamelessly stolen from this article on how to create scatter plots in Python.

与 Seaborn 一起策划

当使用 Seaborn 绘图时,默认的美学会有一点改变。我还没有想出如何改变这一点,但我不会对此大惊小怪。例如,箱线图非常不同(见下文)

Code for creating the boxplots below

Left: Standard matplotlib boxplot function. Right: Boxplot using Seaborn

使用sns.lmplot绘图时,图例绘制在轴外,没有边框(如下)。默认情况下,它还会绘制左侧和底部的脊线。

Scatter plot made with maplotlib’s scatterplot function

Scatter plot made with seaborn’s lmplot function

如何获得主题

这个主题没有安装在 matplotlib 附带的主题集中。因此,如果你想使用这个主题,你有几个选择。我将在这里列出几个选项,但是你可以通过阅读 matplotlib 文档中的使用样式表和 rcParams 定制 Matplotlib 来了解所有的方法。

选项 1

复制这篇博文末尾的 matplotlibrc 样式表内容,并将其保存在与您想要绘制的脚本相同的目录中。用matplotlibrc这个名字保存。那应该就行了。

选项 2

同样,在这篇博文的末尾复制 matplotlibrc 样式表的内容,但是这次在mpl_configdir/stylelib中另存为<style-name>.mplstyle。你可以用matplotlib.get_configdir()找到mpl_configdir在哪里。我必须创建stylelib目录,因为它还不在mpl_configdir目录中。

一旦你把文件保存在正确的目录下,你就可以用

import matplotlib.pyplot as plt
plt.style.use(<style-name>)

所以我把文件保存为gadfly.mplstyle,我可以用plt.style.use('gadfly')设置主题

牛虻主题 matplotlibrc 文件

深度学习和新的编程范式

原文:https://towardsdatascience.com/a-new-programming-paradigm-for-deep-learning-8ce53b5b6345?source=collection_archive---------8-----------------------

An engraving of the Turk from Karl Gottlieb von Windisch’s 1784 book Inanimate Reason (wiki)

在我之前的帖子中,当讨论 DSL 在 ML 和 AI 中的重要性时,我们提到了软件 2.0 的想法,由安德烈·卡帕西提出:

软件 2.0 是用神经网络权重写的。没有人参与编写这段代码,因为有很多权重(典型的网络可能有几百万),直接用权重编码有点困难(我试过)。相反,我们对期望的程序的行为指定一些约束(例如,示例的输入输出对的数据集),并使用由我们支配的计算资源在程序空间中搜索满足约束的程序。在神经网络的情况下,我们将搜索限制在程序空间的一个连续子集,在这个子集上,搜索过程可以通过反向传播和随机梯度下降【19】变得(有点令人惊讶地)高效

**深度学习就是吃软件【13】。在本帖中,我们将对此进行更深入的探讨。

自动微分

什么是自动微分(AD)?网上有无数关于这个主题的资源。

Ryan Adams, You Should Be Using Automatic Differentiation, 2016

简而言之:

  1. 向前模式计算方向导数,也称为切线。无需明确计算雅可比矩阵【4】即可计算方向导数。换句话说,前向模式的一次扫描可以计算雅可比矩阵的一个列向量, Jẋ ,其中 是种子的一个列向量【7】
  2. 反向模式计算方向梯度,即反向模式的一次扫描可以计算雅可比矩阵的一个行向量, ŷJ ,其中 ŷ 是种子【7】的一个行向量
  3. 一次向前或向后扫描的计算成本大致相当,但反向模式需要访问中间变量,需要更多内存。
  4. 倒车模式 AD 最适合F: R^n -> R,前进模式 AD 最适合G: R -> R^m。对于使用n > 1m > 1的其他情况,选择是很重要的。
  5. 反向传播仅仅是自动微分的一个特殊版本 [ 2 ]:反向传播有时也被称为反向模式自动微分。查看[ 3 了解一些历史背景。

实现自动微分

自动微分的实现是一个有趣的软件工程课题。【15】确定了实现自动微分的两种主要方法:

  1. 运算符重载[…]可以用包含额外导数信息的新类型替换浮点变量的类型,并重载该新类型的算术运算,以便沿传播该导数信息
  2. 程序转换人们可以决定显式地构建一个计算导数的新源代码。这非常类似于编译器,除了它产生源代码。这种方法比操作符重载更需要开发,这也是为什么操作符重载 AD 工具出现得更早、数量更多的原因之一。【15】

亲笔签名的可能是最常用的自动分化文库之一:

*[## 臀部/亲笔签名

自动签名-有效地计算 numpy 代码的衍生物。

github.com](https://github.com/HIPS/autograd)*

亲笔签名是开始学习如何实现自动差异化的好地方:

要计算梯度,Autograd 首先必须记录应用于输入的每个变换,因为它被转换为函数的输出。为此,自动签名包装函数(使用函数*primitive* ) ,以便当它们被调用时,它们将自己添加到执行的操作列表中。Autograd 的核心有一个表,将这些包装的图元映射到它们相应的梯度函数(或者更准确地说,它们的向量雅可比乘积函数)。为了标记我们要获取梯度的变量,我们使用Box类包装它们。您不应该考虑 Box 类,但是您可能会在打印调试信息时注意到它。

在函数求值之后,Autograd 有一个图形,指定对我们想要区分的输入执行的所有操作。这是函数求值的计算图。为了计算导数,我们简单地将微分规则应用于图中的每个节点。【亲笔签名】

这种“装箱”是操作符重载的好味道。另一个基于 F#的选择是 DiffSharp:

* [## DiffSharp:可微分函数编程

DiffSharp 是一个自动微分(AD)库,由 atlm günebaydin 和 Barak 用 F#语言实现…

diffsharp.github.io](http://diffsharp.github.io/DiffSharp/)

DiffSharp 展示了如何用合适的类型构建 AD。其他资源,对于熟悉 Haskell 的人来说,包括【24】和【25】。我觉得重载在函数静态类型的设置中大放异彩:

An Haskell implementation of AD [24]

未决问题:控制流、就地操作和别名

注意到自动区分适用于包含控制流(分支,循环,..).拥有控制流的可能性是具有动态计算图的深度学习框架的关键卖点(例如:PyTorch、Chainer)——这种能力也被称为“定义并运行”【18】:

[## 皮托赫/皮托赫

Python 中 pytorch - Tensors 和动态神经网络的 GPU 加速能力

github.com](https://github.com/pytorch/pytorch) [## 链条链/链条链

chainer——一种用于深度学习的灵活神经网络框架

github.com](https://github.com/chainer/chainer)

然而,控制流可能导致代码只能分段可微,这是一个巨大的复杂性开销【4】。

如果机器学习模型变得更像程序,那么它们将基本上不再是可微分的——当然,这些程序仍将利用连续的几何层作为子例程,这将是可微分的,但模型作为一个整体将不是可微分的。因此,在固定、硬编码的网络中使用反向传播来调整权重值,不可能是未来训练模型的选择方法——至少不可能是全部。【21】

我们需要找出有效训练不可微系统的方法。目前的方法包括遗传算法,“进化策略”,某些强化学习方法,和 ADMM(交替方向乘数法)。自然,梯度下降不会有任何进展——梯度信息对于优化可微参数函数总是有用的。但我们的模型肯定会变得越来越雄心勃勃,而不仅仅是可微的参数函数,因此它们的自动开发(“机器学习”中的“学习”)需要的不仅仅是反向传播。【21】

注意:有趣的是,正如我们将看到的,处理控制流的问题与一个机会密切相关:解耦深度学习模块的想法(与端到端深度学习整体相反)。

就地操作

就地操作是算法设计中不可避免的弊端,但也带来了额外的危险:

就地操作会对自动区分造成危害,因为就地操作会使区分阶段所需的数据无效。此外,它们需要执行重要的磁带转换。【16】**

【16】直观地展示了 PyTorch 如何处理就地操作:失效。

变量的每一个底层存储都与一个版本计数器相关联,该计数器跟踪已经对该存储应用了多少就地操作。当一个变量被保存时,我们记录当时的版本计数器。当试图使用保存的变量时,如果保存的值与当前值不匹配,就会引发错误。16】

错认假频伪信号

让我们看看 PyTorch 如何看待混叠:

x 的原地加法也导致 y 的一些元素被更新;因此,y 的计算历史也发生了变化。支持这种情况相当不容易,所以 PyTorch 拒绝了这个程序,在版本计数器中使用一个额外的字段(参见无效段)来确定数据是共享的【16】

可微分规划

一种看待深度学习系统的方式是“可微分函数式编程”【8】。深度学习有一个功能解释:

  1. 同一个神经元(如 ConvNets 和 RNNs)的权重绑定或多个应用类似于功能抽象【8】
  2. 构图的结构模式类似于高阶功能(例如,地图、折叠、展开、压缩)【8】【12】;

探索作为深度学习网络训练的功能结构的最自然的操场将是一种可以直接在功能程序上运行反向传播的新语言。【14】

更高层次抽象的好处之一是可以更容易地设计基础设施,调整模型参数和模型【10】的超参数,利用超梯度:

超梯度的可用性允许您对基于梯度的优化进行基于梯度的优化,这意味着您可以优化学习率和动量计划、权重初始化参数或哈密顿蒙特卡罗模型中的步长和质量矩阵。【11】**

获得超参数的梯度打开了一个快乐的花园。我们可以拥抱它们,并丰富地超参数化我们的模型,而不是努力从我们的模型中消除超参数。正如高维基本参数化提供了灵活的模型一样,高维超参数化提供了模型类、正则化和训练方法的灵活性。【10】

然而,还有更深层的含义:

这感觉就像一种全新的编程,一种可微分的函数式编程。一个人用这些灵活的、可学习的片段编写一个非常粗糙的函数式程序,并用大量数据定义程序的正确行为。然后应用梯度下降或其他优化算法。结果是一个程序能够做一些我们不知道如何直接创建的非凡的事情,比如生成描述图像的标题。【9】

我喜欢这种思路:函数式编程意味着函数的可组合性。

我们今天通常发现的端到端训练的整体深度学习网络本质上非常复杂,以至于我们无法解释它的推理或行为。最近的研究表明,增量训练方法是可行的。通过用较小的单元进行训练,然后将它们组合起来执行更复杂的行为,网络已经被证明工作得很好。【20】**

解耦深度学习模块是一个令人兴奋的研究领域:使用合成梯度的解耦神经接口已经显示出,例如,非常有前景的结果【22】**

我们面前的路

我不确定可微规划这个术语是否还会存在。与差动动态编程混淆的风险很高。

另一方面,这个想法很有趣。非常有意思,我很高兴看到像tensor lang【17】这样的项目越来越受欢迎。

《连线》杂志认为,很快我们就不会给计算机编程了。我们会像训练狗一样训练他们。T10【23】。让我们看看会发生什么。

资源

[0]格里万克、安德烈亚斯和安德里亚·瓦尔特。“评估衍生物:算法微分的原理和技术”。第 105 卷。暹罗,2008 年。

[1]乌烈芝、卡伦、爱德华·密德斯和马克斯·韦林。"用于神经网络压缩的软加权共享."arXiv 预印本 arXiv:1702.04008 (2017)

[2] Dominic,Steinitz,反向传播只是自动微分的最速下降,链接

[3]罗杰·格罗斯,《神经网络和机器学习导论讲义》,链接

【4】什么是自动微分?环

[5]梯度和方向导数,链接

[6]阿列克谢·拉杜尔,《自动微分导论》,链接

[7]哈佛·伯兰,自动微分,链接

[8]atlm gne Baydin,可微分编程,链接

[9] Christopher Olah,神经网络,类型和函数式编程,链接

[10]马克劳林、杜格尔、戴维·杜文瑙德和瑞恩·亚当斯。"通过可逆学习的基于梯度的超参数优化."机器学习国际会议。2015.

[11]炒作:组合机器学习和超参数优化,链接

[12] Christopher Olah,神经网络,类型和函数式编程,链接

[13]皮特·沃登,深度学习就是吃软件,链接

[14]大卫·达尔林普尔,可微分编程,链接

[15] Hascoet、Laurent 和 Valérie Pascual。“Tapenade 自动区分工具:原则、模型和规范。”美国计算机学会数学软件汇刊(TOMS) 39.3 (2013): 20

[16] Paszke,Adam,et al .“py torch 中的自动微分”2017 年

[17] Max Bendick,为深度学习设计一种可区分的语言,链接

[18] Carlos Perez,PyTorch,动态计算图和模块化深度学习,链接

[19]安德烈·卡帕西,软件 2.0,链接

[20]卡洛斯·佩雷斯,《深度教学:未来最性感的工作》,链接

[21]弗朗索瓦·乔莱,深度学习的未来,链接

[22] Jaderberg,Max,et al. “使用合成梯度的去耦神经接口” arXiv 预印本 arXiv:1608.05343 (2016)。

[23]杰森·坦兹,《代码的终结》,连线杂志,2016 年,链接

[24] Conal Elliott,什么是自动微分,它为什么起作用?,链接

[25]丹尼尔·布里斯,自动微分在哈斯克尔中是微不足道的,链接*

Word2Vec 的非自然语言处理应用

原文:https://towardsdatascience.com/a-non-nlp-application-of-word2vec-c637e35d3668?source=collection_archive---------1-----------------------

当使用机器学习解决问题时,拥有正确的数据至关重要。不幸的是,原始数据通常是“不干净的”和非结构化的。自然语言处理 ( NLP ) 从业者对这个问题很熟悉,因为他们所有的数据都是文本的。因为大多数机器学习算法不能接受原始的字符串作为输入,所以在将数据馈送给学习算法之前,使用单词嵌入方法来转换数据。但这并不是文本数据出现的唯一场景,它还可以在标准的非 NLP 任务中以分类特征的形式出现。事实上,我们中的许多人都在努力处理这些类型的特征,那么在这种情况下,单词嵌入有任何用处吗?

本文旨在展示我们如何能够使用 Word2Vec ( 2013,Mikolov et al. ),一种单词嵌入技术,将具有大量模态分类特征转换为更小的一组更易于使用的数字特征。这些功能不仅更容易使用,而且成功地学习了几种模态之间的关系,类似于经典的单词嵌入对语言的影响。

Word2Vec

你可以通过一个人所交往的公司来了解这个人所说的话

以上正是 Word2Vec 试图做的事情:它试图通过分析一个单词的相邻单词来确定该单词的含义(也称为上下文)。该算法有两种版本 CBOWSkip-Gram 。给定一组句子(也称为语料库),该模型循环每个句子的单词,并试图使用当前单词来预测其邻居(其上下文),在这种情况下,该方法被称为“Skip-Gram”,或者它使用这些上下文中的每一个来预测当前单词,在这种情况下,该方法被称为“连续单词包”(CBOW)。每个上下文中的字数限制由一个名为“窗口大小的参数决定。

Both Word2Vec architectures. The current word is w(t) and w(t-2)..w(t+2) are context words. (Mikolov et al. 2013)

因此,如果我们选择例如 Skip-Gram 方法,Word2Vec 则包括使用浅层神经网络,即只有一个隐藏层的神经网络,来学习单词嵌入。网络首先随机初始化其权重,然后在训练过程中反复调整这些权重,以最小化使用单词预测其上下文时产生的错误。在一次有希望成功的训练之后,通过将网络的权重矩阵乘以单词的独热向量来获得每个单词的单词嵌入。

注意:除了允许文本数据的数字表示之外,由此产生的嵌入还学习单词之间有趣的***关系,并可用于回答如下问题:国王对王后就像父亲对…?*****

关于 Word2Vec 的更多细节,你可以看看这个斯坦福讲座或者这个tensor flow 的教程。

应用

我们提供在线数学练习。老师给学生布置家庭作业,每次做完一个练习,一些数据就会被储存起来。然后,我们使用收集到的数据评估学生的水平,并给他们量身定制的复习练习,帮助他们进步。对于每个回答的练习,我们存储一个标识符列表,帮助我们判断:回答的练习是什么?学生是谁?,是哪一章? …除此之外,我们还存储了一个分数值,该值根据学生的成绩为(0)或(1)。为了评估学生的水平,我们只需预测这个分值,并从我们的分类器中获得成功概率。********

如你所见,我们的许多特征都是绝对的。通常,当模态的数量足够小时,可以简单地将具有(n)个模态的分类特征转换成(n-1)个虚拟变量,然后将其用于训练。但是当模态的数量成千上万时——就像我们的一些特征的情况一样——依赖虚拟变量变得低效和不切实际。

为了解决这个问题,我们的想法是使用 Word2Vec 来将分类特征转换成相对少量的可用的连续特征。为了说明这一点,让我们考虑“exercise_id”,这是一个分类特征,它告诉我们哪个练习得到了回答。为了能够使用 Word2Vec,我们必须提供一个语料库,一组输入算法的句子。但是原始特征——id 列表——本身并不是一个文集:顺序完全是随机的并且较近的 id 不携带任何关于它们邻居的信息我们的技巧包括把老师给的每一个作业都看作一个“句子”,一个连贯的练习 id 列表。因此,id 是按级别、章节自然地收集的,Word2Vec 可以直接在上面嵌入学习练习。**

事实上,多亏了这些人造句子,我们才能够使用 Word2Vec 并获得漂亮的结果:

Exercise embedding (3 main components of PCA) colored by level. 6e, 5e, 4e, 3e, 2e, 1e and tm are the french equivalents of the 6th, 7th, 8th, 9th, 10th, 11th and 12th grades in the US.

正如我们所看到的,最终的嵌入有一个结构。事实上,3d 投影的练习云是螺旋形的,更高级别的练习直接跟随前一级别的练习。这意味着嵌入成功学会了区分不同学校级别的练习,并将相似的练习重新组合在一起。但这还不是全部,使用一种 非线性降维 技术,我们能够将整个嵌入减少到具有相同特征的单个实值变量中。换句话说,我们获得了一个练习复杂性特征,其对于 6 年级练习是最小的,并且随着练习的增加而增加,并且变得更加复杂,直到其对于 12 年级练习是最大的。

此外,嵌入还学习了练习之间的关系,就像米科洛夫学习英语单词一样:

上图显示了我们的嵌入能够学习的一些关系的例子。那么如果我们问这个问题“一个 数字加法的练习 是为了一个 数字减法的练习 作为一个 时间加法的练习 是为了…?”嵌入给了我们答案“一个 时间减法 ”。具体来说,这意味着如果我们采用差值嵌入[subtract(Numbers)]-嵌入[Add(Numbers)]并将其添加到要求学生添加时间值(小时、分钟……)的练习的嵌入中,那么最接近的嵌入是由减去时间值组成的练习之一。****

结论

总之,单词嵌入技术有助于将文本数据转换成实值向量,然后可以轻松地插入到机器学习算法中。尽管这些技术主要用于自然语言处理应用,如机器翻译,我们通过给出我们在 Kwyk 使用的一个特定特征的例子,展示了这些技术在分类特征处理中的地位。但是,为了能够应用 Word2Vec 这样的技术,人们必须建立一个语料库——即一组句子,其中的标签被排列,以便隐式地创建上下文。在我们的例子中,我们使用网站上的家庭作业来创建练习的“句子”并学习练习嵌入。因此,我们能够获得新的数字特征,这些数字特征成功地学习了练习之间的关系,并且比它们所源自的一堆标签更有用。

Kwyk 的一名开发人员 Christophe Gabard 提出了用 Word2Vec 处理分类特征的想法,这应该归功于他。

**作者:

每天用四个小时学习数据科学的非革命性技术

原文:https://towardsdatascience.com/a-non-revolutionary-technique-for-learning-data-science-in-four-hours-per-day-68da3199fd64?source=collection_archive---------9-----------------------

(或者其他什么……)

Man sitting at computer desk whilst looking intently at a monitor— @mrdbourke on Instagram

大学里临时抱佛脚应付考试对我来说从来都不起作用。我记得考试那天,我走进校园,直奔食堂。

请来两杯红牛。

然后,我的膝盖会在接下来的两个小时里不停地敲打,但我的大脑却无法将这些点联系起来。当我 4 个小时前读到的东西没有出现在页面上时,我会感到不安。

三年制的学位五年后,我毕业了。但是我从大学带走的最有价值的东西不是那张纸。它是学习如何学习。

我没有在考试前几天死记硬背,而是把整个学期的工作量分成 25 分钟的小块。没有任何革命性的东西。但对我来说是。

现在我也一样。

当我想学东西的时候,我试着每天做一点。

如果你想学点什么,最好的方法就是和做任何事情一样,一点一点来。

对于数据科学和编程,我的大脑在大约四个小时的集中注意力时达到极限。之后,工作开始遵循收益递减规律。

作为一名机器学习工程师,我花了很多时间在马克斯·凯尔森(Max Kelsen)清理数据,在互联网上研究解决问题的新方法,并编写数据科学和机器学习管道的代码,以投入生产。

所以当我完成工作时,我不可能有效地学习新的东西。我不再死记硬背更多的信息,而是用运动、创造和休息来填满时间。让潜意识做它该做的事。

在我不在 MK 的日子里,如果我想提高我的技能,我会使用番茄工作法。还记得之前的 25 分钟吗?

还是那句话,没什么革命性的。但我是那种对什么都兴奋的人。因此,如果像设置计时器这样简单的事情能让我集中注意力,我完全赞同。

在重要的日子里,我会瞄准 10 个。

其他日子我会瞄准 8。有时更少。

很简单。你设定了一个 25 分钟的计时器,在这 25 分钟里,除了你在一天开始时为自己设定的单一任务之外,什么也不做。你想重复多少次就重复多少次。

假设你做了 10 次,你的一天可能是这样的:

早上 7 点 45 分

抽屉里有电话。

上午 8 点

打开关注 Mac 并设置定时器。或者你可以使用任何其他计时设备(除了你的手机,太多分散注意力的东西)。

番茄 1 号

5 分钟休息

番茄 2 号

5 分钟休息

番茄 3 号

5 分钟休息

番茄 4 号

30 分钟休息

上午 10 点 25 分

番茄 5 号

5 分钟休息

番茄 6 号

5 分钟休息

番茄 7 号

5 分钟休息

番茄 8 号

60 分钟休息

下午 1 点 20 分

番茄 9 号

5 分钟休息

番茄 10 号

5 分钟休息

下午 2 点 20 分

现在还不到下午 2:30,如果你做对了,你已经完成了一些不可思议的工作。你现在可以检查你的手机了。

你可以用下午剩下的时间补上那些你需要补上的东西。

你不认为 10 次 25 分钟(4 小时多一点)的时间足够做你需要做的事情吗?

试试看。你会惊讶于你在 4 小时的专注工作中所能完成的事情。

上面的时间表类似于我在找到工作之前花了九个月时间攻读我自己的人工智能硕士学位。

前几天也是一样。除了我在中午的时候挤出一点时间去训练和小睡。

我在 Coursera 上学习密歇根大学的 Python 应用数据科学专业。

前几课都是关于操作数据的不同方法。我发现这是解决机器学习问题时最重要的步骤之一。课程项目与我在 Max Kelsen 做机器学习工程师时的日常工作非常接近。

因此,如果你想提高你的数据科学技能,特别是预处理步骤,我建议试试免费的 7 天试用期,看看专业化是否适合你。

如果你不能在一天之内完成 10 件值得专注的工作。从 1 开始。然后 2。然后 3。有时你甚至会决定超过 25 分钟。最终,你会想知道你是如何以其他方式工作的。

PS 你不用把手机放在抽屉里。如果你白天需要它,你需要它。

本文首发于【mrdbourke.com】(每天还有更)。

关于发现异常的一个注记

原文:https://towardsdatascience.com/a-note-about-finding-anomalies-f9cedee38f0b?source=collection_archive---------0-----------------------

序言

这篇文章的灵感来自于在大学期间所做的研究。本文的目标是提醒人们发现异常并不是一项简单的任务(目前)。

介绍

异常检测是指发现不符合正常预期行为的观察结果的任务。在不同的应用领域中,这些观察结果可以被命名为异常、离群、新奇、例外、惊喜。文献中最常见的术语是异常值和异常值。异常检测是各种领域中的实际问题,例如:

  • 入侵检测
  • 欺诈检测
  • 工业损伤检测
  • 医疗和公共卫生
  • 图像处理
  • 文本数据中的异常检测
  • 传感器网络和其他领域

什么是异常

不幸的是,异常没有明确的定义,这就是为什么我选择了下面这个——异常是数据中不符合正常行为的明确定义的模式[1]。我们可以用一个简单的二维空间来说明异常(图 1)。

Figure 1. Illustration of simple anomalies in two-dimensional space

N₁和 N₂是有正常数据的地区,因为大多数观测值都在这些地区。远离正常区域的点,如 O₁点、O₂点和 O₃地区点是异常点。数据中的异常可能由于不同的原因而出现。恶意活动、信用卡欺诈、入侵、系统故障等。这些异常对数据分析师很有吸引力。因此,异常检测是一个重要的过程,并被认为是各种决策系统的优势。

异常类型

异常可分为以下三类:

  • 点异常。如果一个对象可以相对于其他对象被观察为异常,则它是点异常。这是最简单的异常类别,许多研究都包括它们。考虑图 1 所示的例子,O₁和 O₂是异常点
  • 语境异常。如果对象在某个定义的上下文中是异常的。只有在这种情况下才是语境异常(也称条件异常[2])。在图 2 中可以看到周期性的背景。在这种情况下,点 O₁是异常的,因为它不同于周期性的背景
  • 集体异常。如果一些链接的对象可以相对于其他对象被观察为异常。在这种情况下,单个物体不可能是异常的,只有物体的集合才是异常的。

Figure 2. Contextual anomaly example

我们需要明白,这些异常是有联系的。如果我们对它应用上下文,点异常可以变成上下文。或者点异常可以变成集体异常,如果我们把多个点异常连接在一起。

在抽象层面上,异常检测似乎是一项简单的任务。但是这项任务非常具有挑战性。以下是一些挑战:

  • 定义正常区域是非常困难的。在许多情况下,异常数据和正常数据之间的界限并不精确。在这种情况下,正常的观察可以被认为是异常,反之亦然
  • 如果行为是恶意的,如欺诈,它被认为是异常的。攻击者经常试图使他们的行为适应正常行为。同样,在这种情况下,识别异常任务并不简单
  • 今天被认为是正常的,将来可能就不正常了。在各种因素的影响下,大多数业务系统都会及时发生变化
  • 一个领域中的异常检测方法通常不能用于另一个领域。它们在大多数情况下是无效的
  • 模型训练的训练和验证数据可用性是一个大问题

让我们来玩吧!

下面我将给出一些数据集的例子。你的目标是慢慢滚动(一个例子接一个例子)并尝试用眼睛确定异常。

Figure 3. Little game

正如您所看到的,在某些情况下“通过眼睛”来确定异常并不简单。即使你会应用一些统计技术,它仍然不是微不足道的。那么,去哪里找,做什么呢?

异常检测方法概述

可用于发现异常的方法分为以下几类[4]:

监督异常检测。在训练和测试数据集中标记数据的设置;当简单的分类器可以被训练和应用时。这种情况类似于传统的模式识别,只是类别在大多数情况下非常不平衡。并非所有的分类方法都适合这项任务。例如,某些类型的决策树不能很好地处理不平衡的数据。支持向量机【SVM】或者人工神经网络应该表现更好。然而,这种设置是不相关的,因为我们需要知道所有的异常并正确标记数据。在许多情况下,异常是事先不知道的,或者可能在测试阶段以新奇的方式出现。

Figure 4. Supervised anomaly detection

半监督异常检测。最初当我们没有任何知识时,我们从训练结果中收集。该设置还使用训练和测试数据集,其中只有训练数据由没有任何异常的正常数据组成。其思想是,正常类的模型已经被教导,并且异常可以通过偏离学习的模型来检测。这种方法也被称为“一类”分类。众所周知的方法是一类支持向量机和自动编码器。一般来说,任何密度估计方法都可以用于建模正态类的概率密度函数,例如高斯混合方法或核密度估计。

Figure 5. Semi-Supervised anomaly detection

无监督异常检测。一种设置,当我们不知道数据中哪些是正常的,哪些是不正常的。这是最灵活的配置,不需要任何标签。训练数据集和测试数据集之间也没有区别。其概念是无监督异常检测方法仅基于数据集的自然特征对数据进行评分。通常,距离或密度用于评估什么是正常的,什么是异常值。可视化表示可以在图 6 中找到。

Figure 6. Unsupervised anomaly detection

大多数方法作为输出会给出分数或标签。评分和贴标签的区别在于灵活性。使用评分技术,分析师可以选择更适合问题领域的值。之后,他可以使用阈值来选择异常或只选择顶部的异常。标签是一种分类。如果不对领域和特征提取进行研究,到目前为止还没有一种方法可以在所有领域都获得同样的成功。大多数无监督的异常检测方法如图 7 所示。

Figure 7. Unsupervised anomaly detection approaches classification diagram

现实生活是动态的

如果定义的环境中的可观察对象的行为随时间改变,则该环境可以被认为是动态环境。

动态环境,如生产过程、通信网络、公路交通等。,可能包含大量随时间变化的信息,这对于理解环境的一般行为、发现环境中当前发生的规律和异常、控制进化过程以及智能建模或管理环境来说是宝贵的资源[3]。

例如:一个正在成长的网上商店。交通和交易量的变化。以前正常的事情现在不会了,这种转变只能被认为是一种异常。这是之前确定的挑战之一。另一个例子是分析客户行为的系统。最初可以对客户进行分类。但是顾客也可以因为某种原因及时从一个等级转移到另一个等级。随着软件的更新或行为的改变,系统会随着时间而发展。首先,为了有效地检测异常,需要持续学习的系统。其次,要在早期阶段检测异常,不能等到指标明显超出界限。早期检测需要能够检测到模式中不明显的细微变化。此外,由于异常本质上是不可预料的,有效的检测系统应该能够确定异常事件是否是新的,而不依赖于预编程的阈值。

检测动态环境中的异常似乎是一项艰巨的任务。可以面临的最大问题是,在大多数公司里,不会有可供学习的数据。在这种情况下使用的大多数方法应该是无人监管的。

可能的解决方案

目前进步并给人希望的解决方案包括神经网络(NN),其中一些与统计方法相结合。

现在用于时间序列的流行神经网络是长短期记忆(LSTM)——它在深度学习领域受到欢迎,因为它们有可能记住长期运行的依赖关系。

另一种有趣的网络是新的,没有提到很多,是分层时间记忆(HTM)——这是一种基于神经科学研究的神经网络,它也有能力学习和记忆长期运行的依赖关系。会告诉你更多。

分级时间记忆(HTM)

HTM 是由 Numenta 公司的 Jeff Hawkins 和 Dileep George 开发的一种无监督到半监督的在线机器学习方法,它是一种旨在捕捉新大脑皮层的结构和算法属性的技术。HTM 是新大脑皮层的理论,几乎没有类似的大脑结构。新大脑皮层约占人脑体积的 75%,它是我们所认为的大部分智力的核心。HTM 是一个生物理论,这意味着它来自神经解剖学和神经生理学,并解释了生物新皮层如何工作。他们说,HTM 理论是“生物约束的”,与机器学习中使用的术语“生物激励的”相反。

HTM 学习方法设计用于动态环境,如传感器和电机数据。传感器输入可以根据来自服务器的不同障碍而改变。相反,输入数据可能会发生变化,因为传感器的移动与人眼观看静态图像的移动相同。

HTM 系统在线学习。当输入数据有任何变化时,HTM 系统的存储器被更新。有一种标准的机器学习方法,如在测试和训练数据集中拆分数据,并学习网络以达到定义的准确性水平。问题来了:“如果没有标签,它怎么知道,它工作正常?它如何纠正自己的行为?”。在每一个时间点,HTM 都会预测下一步会发生什么。换句话说,HTM 建立了一个预测世界的模型。然后,将预测与发生的事情进行比较,这个结果是学习的基础。作为一种经典的机器学习方法,它试图最小化预测的误差。HTM 不断学习。这是生物有机体生存的基本素质。HTM 是围绕这一理念建立的,即智能系统需要像生物有机体一样不断学习。将会有系统不需要在线学习的应用,但是这些不是标准,而是例外。HTM 假装是一种通用的学习方法,适用于任何具有时间行为的任务。更多细节可以在他们的网站上找到,参考以下来源[4]。

发明了新方法!如何证明有效?

好吧,你发明了新方法来解决这个问题。如何证明你的方法有效并且比别人更好?

许多研究人员在研究无监督异常检测方法时遇到了一个问题——没有一个定义好的框架来评估它们的性能。许多科学家只做理论上的假设。目前,出现了一些创建这种框架的尝试。

Markus Goldstein 和 Seiichi Uchida 在他们的工作[5]中提出了如何对异常检测方法进行评估。但是他们的评估方法是基于处理表格数据的方法。

在 2015 年第 14 届机器学习和应用国际会议(IEEE ICMLA)上,Alexander Lavin 和 Subutai Ahmad 提出了他们的实时异常检测程序评估方法 Numenta 异常基准(NAB)[6]。

抓捕

这是时间序列中异常检测程序的第一个基准。 NAB 是一个开源框架,旨在通过可控和可重复的环境来评估实时异常检测程序。NAB 数据语料库由 58 个真实数据集组成,其中异常窗口被标记。每个文件包含 2,000 到 22,000 个时间戳,数据以 5 分钟为间隔聚合。它的总分是 365,551 分。这些数据集是合成的和真实的:

  • IT 指标
  • 社交媒体聊天
  • 工业机器传感器

评分机制定义了异常检测窗口来衡量早期检测。它奖励算法:

  • 检测所有存在的异常
  • 尽快发现他们
  • 触发很少的误报
  • 处理实时数据
  • 在所有数据集中都是自动的

它使用应用程序配置文件来衡量不同场景的性能。“开始吧”一节中的所有数据集示例都来自该基准测试。

结论

许多主要产品是某种数据库的公司会在会议上提出这个话题,并向你展示如何用他们的工具发现异常。但问题是,所示方法仅适用于特定数据集和用例。永远记住这一点。

请记住,发现异常需要分析师给出适当的定义。有不同类型的异常。有不同的方法可以找到特定类型的异常。总是试图缩小你的问题。并针对您的问题使用可用的基准或一些数据集(如果可用)来测试您的方法。

要阅读更多关于这个主题的内容,你可以参考下面的不同文章。

愿原力与你同在。

参考文献

[1]chan dola v .,Banerjee,a .和 Kumar v .,2009 年。异常检测:综述。美国计算机学会计算调查,7 月。41(3).

[2]宋,谢,吴,米&杰梅因,2007 .条件异常检测。IEEE 知识与数据工程汇刊,3 月 26 日,19(5),第 631–645 页。

[3]川野,h,西尾,s,韩,j 和长谷川,t,1994。知识发现如何与主动数据库技术合作控制动态环境?。希腊雅典,柏林海德堡施普林格出版社。

[4]霍金斯,j .,艾哈迈德,s .和拉文,a .,2016 年。生物和机器智能。地点:【http://bit.ly/2qJzvjO

[5] Goldstein,m .和 Uchida,s .,2016 年。多元数据无监督异常检测算法的比较评估。PLoS ONE,11(4),第 31 页。

[6]拉文和艾哈迈德,2015 年。评估实时异常检测算法 Numenta 异常基准。迈阿密 IEEE。

置信区间:参数和非参数重采样

原文:https://towardsdatascience.com/a-note-on-parametric-and-non-parametric-bootstrap-resampling-72069b2be228?source=collection_archive---------14-----------------------

Image by Author

机器学习工程师一生中很重要的一部分时间都花在制作一个好的模型上。泪水和汗水被投入到这个艰苦的过程中。但是,一旦基于防弹理论(当然)的模型存在,一个狡猾的问题就潜伏在其中:“它能告诉我们什么?”。

置信区间

置信区间的概念通常用对称高斯分布来解释。然而,它们不一定是对称的,并且根据具体情况,推导起来可能非常繁琐。总的想法基于下面的公式:

其中【⍬】为固定且未知的参数真值,【⍬】【hat】**为其“最大似然估计( MLE) 来自数据(为随机变量) deltas 为置信区间的界限,其在术语中取决于与常见的误解相反,置信区间并不给出预测的置信度,而是给出参数的真实值属于由边界定义的范围的概率。类似地,它可以被解释为误差概率,即参数的真实值超出界限的概率。**

如果再次运行该路径,我会看到什么结果?

这个问题是频率主义者分析的核心。模型依赖于数据,数据越大、越清晰、越通用,就能获得更好的参数估计。在给定数据的情况下,可以使用参数的置信区间并通过提出以下问题来估计模型的良好性:“如果略有不同,参数和预测将会是什么,但仍然使用看似合理的数据来生成它们。”获取置信区间的步骤如下:

  1. 写出一个概率模型。
  2. 在给定数据的情况下,用最大似然估计替换任何参数。用重采样版本替换任何随机变量。
  3. 使用蒙特卡罗方法来估计第 2 步中的概率。

步骤 2 中的重采样版本可以通过多种方式获得,即参数化和非参数化。

非参数重采样

如果假设我们可能看到的所有数据都来自与手头数据相同的分布是安全的,那么,我们能做的最好的事情就是从数据集本身进行替换采样(以保持概率密度函数)。

参数重采样

然而,在某些情况下,从数据集进行采样并不是一个很好的主意,例如当数据稀缺时。然后,我们可以直接从最佳拟合( MLE)、中生成新样本,并对噪声进行一些假设。

把所有的放在一起

考虑两种情况:当数据充足时和当数据有限时。在这两种情况下,数据的基本分布都被假定为未知。

******

Image by Author.**

检查散点图(图 1)后,假设最能描述数据的模型是三次多项式。

此外,假设数据中的噪声是具有零均值和未知标准差的高斯噪声是安全的。

这两个过程都遵循上一节中的步骤。对于参数重采样,样本从具有附加高斯噪声的模型中生成,该噪声具有从 MLE 拟合的残差中获得的方差。对于非参数重采样,样本从数据的原始分布中生成。

要获得响应的置信区间:首先,对于每个预测值,从所有 bootstrap 运行中对模型的预测进行排序,然后找出 MLE 和期望区间的界限之间的差异(在这种情况下为 95%)。上限和下限之间的差异是置信区间的上限和下限的增量。

******

95% confidence intervals for response, non-parametric (left), parametric (Right), 10 points. Image by Author.** ******

95% confidence intervals for response, non-parametric (left), parametric (Right), 100 points. Image by Author.**

类似于预测的置信区间,我们保存来自 bootstrap 的所有拟合模型。

******

95% confidence intervals for coefficients, non-parametric (left), parametric (Right), 10 points. Image by Author.** ******

95% confidence intervals for coefficients, non-parametric (left), parametric (Right), 100 points. Image by Author.**

何时使用

何时需要使用参数和非参数重采样?两者都有论据支持。使用非参数重采样,我们无法生成超出经验分布的样本,而使用参数重采样,可以生成超出我们目前所见的数据。但是,如果对模型没有太大的信心,或者数据丰富,那么非参数重采样是更可取的。如果数据不足,那么从参数模型中取样可以使其平滑(从图中可以看出)。

进一步阅读和链接

有很多方法可以获得置信区间,例如估计后验分布(贝叶斯主义),应用中心极限定理(在正态假设下),使用威尔克斯定理,或者如果使用高斯随机变量,使用海森的逆作为协方差矩阵等。

我推荐阅读这篇关于置信区间的文章,它从实践的角度给出了一个概述。另外,这篇论文对基于 bootstrap 的置信区间方法进行了很好的概述。

本文的 jupyter 笔记本可从这里获得。

喜欢作者?保持联系!

我错过了什么吗?请不要犹豫,直接在 LinkedIn 或 Twitter 上给我留言、评论或发消息吧!

** [## 你能做得更好吗?抽样策略,重点是吉布斯抽样,实践和代码

提供了通用采样策略的概述,重点是 Gibbs 采样、示例和 python 代码。

towardsdatascience.com](/can-you-do-better-sampling-strategies-with-an-emphasis-on-gibbs-sampling-practicals-and-code-c97730d54ebc) [## 贝叶斯优化的超参数调整或者我如何用木头雕刻船

超参数调整通常是不可避免的。对于一个参数,网格搜索可能就足够了,但如何处理…

towardsdatascience.com](/bayesian-optimization-or-how-i-carved-boats-from-wood-examples-and-code-78b9c79b31e5) [## 成对比较的主动采样

如何配对玩家,以便在尽可能少的游戏中知道排名,同时游戏体验质量…

towardsdatascience.com](/active-sampling-for-pairwise-comparisons-476c2dc18231)**