TowardsDataScience 博客中文翻译 2019(四十八)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

使用人工智能(AI)进行药物发现的初创公司的交互式视觉地图

原文:https://towardsdatascience.com/an-interactive-visual-map-of-startups-that-use-artificial-intelligence-ai-for-drug-discovery-e27213298c21?source=collection_archive---------21-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

find link in map section for interactive map

用于药物发现的人工智能

简介:

上次我制作了一个可视地图,显示了美国所有制药公司的位置。在地图中,它显示了一些使用人工智能(AI)的传统制药公司。有许多初创公司也在利用人工智能进行药物研发。因此,我想创建一个类似的地图,展示世界各地使用人工智能进行药物发现的初创公司是如何增长的。

数据:

我发现这篇文章的标题是“141 家创业公司在药物发现中使用人工智能”。我开始刮公司名字和网站链接。现在我有了所有的网站链接,我需要从网站上收集所有的地址。

下面是抓取姓名和地址的代码。

在调查了几个网站之后,在我看来,所有的网站都彼此大相径庭。所以我不能使用 selenium 或 beautifulsoup 从联系信息中删除完整地址。由于名单不太大,我不想放弃。我只需要 2-3 个小时来收集所有的物理地址。

我手动收集了所有的数据。我在 startup 网站上找到的大部分物理地址。对于其余的物理地址,我搜索了谷歌并收集了它们。在 141 个地址中,我设法收集了 138 个。但是很少有创业公司,我只找到了他们所在的城市,而不是完整的地址。

地图:

然后我用‘Google geocoder’python 库找到了经纬度。

最后,我使用叶库创建了地图。

这里是互动地图链接

或者,您可以在浏览器中复制并粘贴以下链接

【https://bit.ly/2KExnXC

如果你点击图标,它会显示创业公司的名称和网站。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这张地图清楚地显示,美国大多数初创企业位于东西海岸。美国以外也有创业公司。

所有的代码和数据都可以在我的 github 上找到

感谢阅读。请不要犹豫,在文章下面评论。

参考资料:

史密斯,S. (2017)。141 家创业公司在药物发现中使用人工智能。检索自https://blog . bench sci . com/startups-using-artificial-intelligence-in-drug-discovery

我的 linkedin

[## Yousuf Ali -研究生研究助理-德州理工大学健康科学中心| LinkedIn

孟加拉国达卡 Narayangonj ACI 有限公司产品开发官员。

www.linkedin.com](https://www.linkedin.com/in/yousuf–ali/)

有趣且直观的 AUC 和 ROC 曲线视图

原文:https://towardsdatascience.com/an-interesting-and-intuitive-view-of-auc-5f6498d87328?source=collection_archive---------15-----------------------

在学习 AUC 之前,你不需要学习 TPR,FPR 和一堆其他的东西。

AUC,或 ROC 曲线下面积,是一种广泛用于评估模型性能的指标。

网上有一堆关于 AUC 的资源。他们通常从向读者解释真阳性、敏感性、I 型、II 型错误和 FPR 等开始。他们中的许多人都很好,他们详细解释了概念,但一些概念可能会让一些没有分析背景的人感到困惑。我想在这里指出的是,一个人实际上可以在不知道所有这些专业术语的情况下学好 AUC

让我用一个简单的例子来说明如何做。

假设一家信用卡公司建立了一个风险评分模型来评估客户是否能够按时支付账单。他们拥有的数据被标记,1 表示客户不能按时付款(有风险),0 表示那些按时付款的客户。这是 20 条记录的样本的结果(假设没有重复的分数):

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

让我们看看如何从这 20 条记录中画出 ROC 曲线。我们先画一个正方形,左下角为(0,0),右上角为(1,1):

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

然后,在这 20 个记录中,我们有 5 个 1 和 15 个 0,所以我们将 y 轴除以 5,x 轴除以 15:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

然后,从高分到低分,对应的标签是 1,1,0,1,0,0,…,我们把 1 换成’上’,把 0 换成’右’,就会得到一个新的序列:上,上,右,上,右…然后从(0,0)开始,根据这些’上’和’右’画出你的曲线。一上(或右),一招。这是 ROC 曲线。它下面的区域是 AUC。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

让我们用一个完美的模型来比较一下。在一个完美的模型中,任何“1”都将比任何“0”有更高的分数。因此,从高分到低分,相应的标签将是 1,1,1,1,0,0,0,0,…并且 ROC 将是

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

AUC 是 1。一些观察结果:

  • 为了提高 AUC,你需要在“正确”之前出现更多的“向上”。
  • 这意味着,“1”需要在“0”之前。
  • 这意味着,模型给予目标(标签为 1 的记录)更高的分数,因此模型更好。
  • AUC 介于 0 和 1 之间。
  • AUC 是一个排名指标(重要的是得分顺序,而不是得分值本身)。

在深入研究 ROC 的其他属性之前,我想展示几个特例。

更多示例

1.得分相等。让我们稍微改变一下前面的例子,得到相同的分数。在这一组(得分 70),我们有三个 0 和一个 1。我们要做的修改是将三个“右”和一个“上”合并成一个动作。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

新的 ROC 是

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

因此,如果所有分数相等,ROC 将正好是 x=y (AUC = 0.5)线。

2.随机猜测。当记录以随机顺序分配时,ROC 曲线将在 x=y 附近波动,AUC 在 0.5 左右。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

3.逆转比分。如果我们颠倒分数顺序和最开始的例子,我们将得到一条关于点(0.5,0.5)对称于原始 ROC 曲线的新 ROC 曲线[关于线 x=y 不对称!].新的 AUC 是 1 减去原始 AUC。这就是为什么人们说当我们有一个 AUC <0.5 的模型时,我们可以执行这个分数反转技巧来获得一个更好的模型。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

现在让我们看看我们还能从 ROC 曲线中提取什么信息。

性能

  1. 割线斜率越高,标记率越高(1 的数量与一个组中记录的总数之比)。在下面的示例中,选择了两个分数组,分数高的组具有较高的标记率,因此割线斜率也较高。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

2.凹度。通常,由好的 ML 算法生成的结果的 ROC 曲线在整个域中是向下凹的。但是,如果不幸的是,您有一条在子区间上向上凹的曲线,您可以在该特定区间反转分数以提高性能(并且建议您还检查建模数据)。

3.高分区域/低分区域。下面的绿色方框包含高分记录的信息,橙色方框包含低分记录的信息。在绿色区域,我们希望割线斜率较大;在橙色区域,斜率越小越好。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

AUC 不是我们衡量排名模型表现的唯一方式。有时,我们只关注模型在高分区域是否表现良好。

AUC 低的模型仍然有价值。例如,下面 ROC 曲线的 AUC 只有~0.64,但是它在高分记录上有很好的表现。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

4.模特合奏。当我们在同一个数据集上有多个模型,并且 roc 的形状不同(有些在高分区域很好,有些在低分区域很好)时,我们通常可以通过组合模型(打包或堆叠)来找到值。

为讨厌数学和不会编码的人介绍人工智能

原文:https://towardsdatascience.com/an-intro-to-ai-for-people-that-hate-math-and-cant-code-140aa42c9f3f?source=collection_archive---------30-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这是一个关于人工智能的高级速成班,面向经理、企业主和其他非技术角色,他们希望掌握人工智能,并开始使用它来推动他们组织的价值。这不是为计算机科学家和数学家设计的。

这分为 3 个简短的部分:

  1. 为什么人工智能对商业很重要
  2. 不同类型的人工智能及其含义
  3. 机器学习究竟是如何“学习”的

让我们开始吧。

人工智能对商业意味着什么

我们将进一步了解技术,但首先你需要理解为什么你应该关心人工智能的三大原因。

1。人工智能能看到你看不到的图案

对您的车队进行维护的最佳时间是什么时候?哪些销售线索具有最高的潜在价值?公司财务中的哪些模式可能表明欺诈?

如果你给一个人工智能程序足够多的正确数据,它会告诉你。

2。AI 不像人一样思考

人工智能可以在复杂的棋盘和视频游戏中胜过人类,做出更好的投资决策(有时),甚至可以在评估法律文件质量方面击败律师。它通过比我们更理性的思考来做到这一点,并看到我们看不到的模式。

AI 一顿丰盛的午餐也不累,没有根深蒂固的偏见,也不在乎办公室政治

人工智能驱动的建议会让你对工作的任何方面都有不同的看法。

3.AI 比你想象的更容易实现

人工智能极其复杂,该领域的突破是由在计算机科学、数学和神经科学领域拥有丰富经验的团队以及大量资金推动的。

但是,他们的大部分工作已经被合成到高级库中,比如 Python 的 Keras。你(或你团队中的人)不需要成为专家,也可以通过一些教程,编写一个基本的模式识别程序来分析数据。

这需要时间来调整它,学习如何对程序输出采取行动,并适当地组织你的数据,但你不需要为此回到大学。而且,结果将远远超过投入的时间。

好吧。如果你还在这里,你可能已经意识到了人工智能的重要性,并想了解更多。是时候让变得稍微技术性一些了。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

I don’t have image rights for any of the cool sci-fi renderings of AI so we’ll just go with this photo of light bulbs. Symbolism, right?

人工智能、机器学习和深度学习

有许多人工智能的子集和机器学习的变体,但这些是你可能见过使用的一些更常见的术语。

人工智能

  • 人工智能是金字塔的基础。这是一个广义的概念,机器通过某种算法来解决问题或完成任务。
  • 这听起来可能并不特别;毕竟,每个程序不都是按照某种规则运行的吗?你说得对,但让我们所知的人工智能变得“智能”的是机器能够自己创造这些算法,并在机器学习时更新这些算法,让做出更好的决策。
  • 这就是机器学习的用武之地

机器学习

  • ML 是 AI 的子集。ML 是机器用来学习 的实际 过程,所以 AI 可以做决策。
  • 在 ML 中,我们给机器大量的数据来处理和一个目标。
  • 我们通过 ML 程序运行大量数据,它确定数据中哪些特征是重要的,而无需我们告诉它做什么。

深度学习

  • DL 是 ML 的复子集。它可以将数据分成不同的类别,而无需被告知数据代表什么
  • DL 使用多层人工神经元来尝试和复制人脑的复杂性。从技术上讲,当一个网络有三层以上时,它就是“深”的(我们将在下面讨论)。
  • DL 馈入 ML,ML 馈入总体 AI

深度学习示例:

我们想要一个程序,它能告诉我们一张照片是否包含一只猫。我们会给程序提供大量的照片,并给每张照片贴上“猫”或“不是猫”的标签。

这台机器一开始会非常不准确,基本上是猜测图片中是否包含一只猫。但随着时间的推移,它会在每张标记为“猫”的照片中挑出关键特征,并将其与“非猫”照片中的特征进行比较。

在英语中,机器通过思考来“学习”,“照片中有一个白色的斑点,在它的脸中间有一个粉红色的斑点(猫的鼻子)。标有“不是猫”的照片没有那个粉红色的斑点。我要开始寻找粉红色的斑点。”

这是程序添加到算法中的一个“特征”的例子。

有了足够的照片和训练时间,它会挑出越来越多的特征。该程序将使用这些特征来确定一只猫的样子,并相当准确地决定一张照片是否包含一只猫。

AI 是如何学习的?

最后,我们将讨论机器实际上是如何学习的。我在上面提到了它,但我将在这里得到更多的颗粒。

当你创建一个机器学习程序时,你建立了一个神经网络,它应该粗略地模仿人脑中放电神经元的结构。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Source: Chrislb, Wikimedia Commons

输入是您的数据点,隐藏层是进行计算的地方,输出是最终结果:根据编程的方式,这可能是分类、建议或概率。

每个圆称为一个节点,每个垂直堆叠的节点称为一个层。这是一个浅层网络,因为它只有 3 层。但通过增加更多的隐藏层(输入和输出之间的层),网络变得“更深”,更复杂,理想情况下更准确。

上面没有显示的是每个节点的权重。节点的权重告诉网络该节点有多“重要”。每个节点被分配一个 0 到 1 之间的数字(层中节点的权重加起来为 1)。

通过对每个节点进行加权,程序决定寻找什么来做出最佳决策。在前面的例子中,它可以为“粉色斑点”分配一个高权重,以决定某个物体是否是猫。它会给“棕色头发”分配一个较低的权重,因为人类和猫可以有棕色头发。

节点的输出乘以权重,结果用于做出决策。对机器来说,低重量=低重要性。

当程序开始运行时,这些权重完全是随机的,系统很可能会非常不准确。随着你运行程序的次数越来越多,信息的流向就会发生逆转。如果你有任何错误(错过的预测),程序将改变每个节点的权重,从而改变某些特征的“重要性”。

它会一直这样做,直到程序能够达到某个较高的精确度。

包扎

你成功了!希望你现在可以离开,理解人工智能如何做决定,以及为什么它对你的业务很重要。如果您想开始实现它,请开始搜索代码示例!很有可能有人已经发布了满足您需求的开源代码。

如果这对你有帮助,并且你认为其他人也能从中获益,请快速分享。

Tensorflow 中的高级 Keras API 简介

原文:https://towardsdatascience.com/an-intro-to-high-level-keras-api-in-tensorflow-c50f6f5272de?source=collection_archive---------15-----------------------

Tensorflow 是深度学习模型生产中使用的最著名的库。它有一个非常大的令人敬畏的社区,并且在操作上有很大的灵活性。然而,Tensorflow 并不是那么用户友好,并且具有更陡峭的学习曲线。为了解决这个问题,Tensorflow 的高级 Keras API 提供了构建模块,可以更轻松地创建和训练深度学习模型。此外,Keras 模型是通过将可配置的构建模块连接在一起而形成的,几乎没有限制。这使得它更加模块化和可组合。你可以在他们的官方网站上探索。

分类

要使用高级 Keras API 进行简单分类,需要遵循的一些步骤如下:

  1. 导入所需的模块。
  2. 为 API 准备合适的数据格式。
  3. 使用 TF . Keras(tensor flow-Keras)API 构建神经网络模型并编译它。
  4. 用准备好的数据训练模型,同时尝试解决欠拟合和过拟合情况。
  5. 评估模型。
  6. 保存和恢复模型,以便在生产中使用。

导入所需的模块。

首先,需要进口 numpy 和 pandas,因为数据处理和准备需要它们。必须导入 Tensorflow API 和高层 Keras API 进行底层操作和建模。必须导入 Matplotlib 进行性能和精度等的图形分析。

*# TensorFlow and tf.keras*
**import** **tensorflow** **as** **tf**
**from** **tensorflow** **import keras**
**import** **numpy** **as** **np
import pandas as pd
import** **matplotlib.pyplot** **as** **plt
%matplotlib inline** ''' 
%matplotlib inline means with this backend, the output of plotting commands is displayed inline within frontends like the Jupyter notebook, directly below the code cell that produced it. The resulting plots will then also be stored in the notebook document.
'''

数据准备

数据准备阶段获取原始数据,使其看起来结构化,从中去除噪声,并更改数据格式和形状以适合您正在设计的模型。数据可以是不同的格式,如图像数据不同于文本数据,两者都需要不同的处理和预处理。例如,如果我们使用 mnist_fashion 数据来制作一个分类器来对服装进行分类,数据准备可以如下进行:

MNIST 时尚数据集包含 10 个类别的 70,000 幅灰度图像。这些图像以低分辨率(28×28 像素)显示了单件衣服。链接:【https://github.com/zalandoresearch/fashion-mnist

我们将使用 60,000 张图像来训练网络,并使用 10,000 张图像来评估网络学习分类图像的准确性。

加载这些数据的 Tensorflow API 显示了一些 gzip 错误。这里遵循的方法是,从 https://github.com/zalandoresearch/fashion-mnist 的下载原始数据集,然后按照https://pjreddie.com/projects/mnist-in-csv/将数据集转换成 CSV 格式。

**class_names = ['T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat', 
               'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot']****import pandas as pd
train_df = pd.read_csv('data/fashion-mnist_train.csv',sep=',')
test_df = pd.read_csv('data/fashion-mnist_test.csv', sep = ',')
train_df.head()** ''' 
we need to convert the dataframes into numpy arrays of float32 type which is the acceptable form for tensorflow and keras. 
'''
**train_data = np.array(train_df, dtype = 'float32')
test_data = np.array(test_df, dtype = 'float32')** '''
We scale the pixel values to a range of 0 to 1 before feeding to the neural network model. (presently they are from 0-255)
'''
**x_train = train_data[:,1:]/255****y_train = train_data[:,0]****x_test= test_data[:,1:]/255****y_test=test_data[:,0]**

建立神经网络模型

神经网络的基本构造块是层。图层从提供给它们的数据中提取表示。例如:

**model = keras.Sequential([
    keras.layers.Flatten(input_shape=(784,)),
    keras.layers.Dense(128, activation=tf.nn.relu),
    keras.layers.Dense(10, activation=tf.nn.softmax)
])**

该网络由一系列两层致密层组成。这些是密集连接,或完全连接的神经层。

第一密集层有 128 个节点(或神经元)。

第二层(也是最后一层)是一个 10 节点的 softmax 层,它返回一个由 10 个概率得分组成的数组,这些得分的总和为 1。每个节点包含一个分数,该分数指示当前图像属于 10 个类别之一的概率。

在模型为训练做好准备之前,它还需要一些设置。这些是在模型的编译步骤中添加的:

损失函数:衡量模型在训练过程中的精确程度。我们希望最小化这个函数,以便将模型“导向”正确的方向。

优化器:这就是模型如何根据它看到的数据和它的损失函数进行更新。

指标:用于监控培训和测试步骤。下面的例子使用了准确度,即图像被正确分类的比例。

**'''** When doing multi-class classification, categorical cross entropy loss and sparse categorical cross entropy is used a lot**.** To compare them both read [https://jovianlin.io/cat-crossentropy-vs-sparse-cat-crossentropy/](https://jovianlin.io/cat-crossentropy-vs-sparse-cat-crossentropy/)
**'''
model.compile(optimizer=tf.train.AdamOptimizer(), 
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])**

训练模型

训练神经网络模型需要以下步骤:

  1. 将训练数据提供给模型,在本例中是 train_images 和 train_labels 数组。
  2. 模型学习将图像和标签联系起来。
  3. 我们要求模型对测试集进行预测。在本例中,是 test_images 数组。我们验证预测是否与 test_labels 数组中的标签相匹配。
**model.fit(x_train, y_train, epochs=10)
test_loss, test_acc = model.evaluate(x_test, y_test)****print('Test accuracy:', test_acc)
print('Test loss:', test_loss)****10000/10000 [==============================] - 1s 52us/step
Test accuracy: 0.8963
Test loss: 0.3374745888918638**

训练模型时的一个主要问题是过度拟合和欠拟合。通过充分的训练可以避免不合身。为了避免过度拟合,两种解决方案可以是"添加权重正则化""添加丢弃"。

添加权重调整

减轻过度拟合的一种常见方法是通过强制网络权重仅取小值来限制网络的复杂性,这使得权重值的分布更加“规则”。这被称为“权重正则化”,这是通过向网络的损失函数添加与具有大权重相关联的成本来实现的。这种成本有两种形式:

L1 正则化,其中增加的成本与权重系数的绝对值成比例(即,与所谓的权重的“L1 范数”成比例)。

L2 正则化,其中增加的成本与权重系数的值的平方成比例(即,与所谓的权重的“L2 范数”成比例)。在神经网络的上下文中,L2 正则化也称为权重衰减。不要让不同的名称迷惑你:权重衰减在数学上与 L2 正则化完全相同。

唯一需要改变的是模型架构:

**l2_model = keras.models.Sequential([
    keras.layers.Dense(16, kernel_regularizer=keras.regularizers.l2(0.001),
                       activation=tf.nn.relu, input_shape=(NUM_WORDS,)),
    keras.layers.Dense(16, kernel_regularizer=keras.regularizers.l2(0.001),
                       activation=tf.nn.relu),
    keras.layers.Dense(1, activation=tf.nn.sigmoid)
])**

添加辍学

Dropout 是神经网络最有效和最常用的正则化技术之一,由 Hinton 和他在多伦多大学的学生开发。

应用于一个层的丢弃包括在训练期间随机“丢弃”(即设置为零)该层的一些输出特征。假设在训练期间,给定的层通常会返回给定输入样本的向量[0.2,0.5,1.3,0.8,1.1];在应用丢弃后,该向量将具有随机分布的几个零条目,例如[0,0.5,1.3,0,1.1]。

“丢失率”是被归零的特征的分数;通常设置在 0.2 到 0.5 之间。在测试时,没有单元被丢弃,相反,层的输出值会按与丢弃率相等的因子按比例缩小,以平衡比训练时更多的单元处于活动状态这一事实。

这里,唯一需要改变的是模型架构。

**dpt_model = keras.models.Sequential([
    keras.layers.Dense(16, activation=tf.nn.relu, input_shape=(NUM_WORDS,)),
    keras.layers.Dropout(0.5),
    keras.layers.Dense(16, activation=tf.nn.relu),
    keras.layers.Dropout(0.5),
    keras.layers.Dense(1, activation=tf.nn.sigmoid)
])**

模型评估

有许多度量来评估分类、回归、聚类等。这里我们将用准确度来衡量分类。(精度、召回率、F-measure 和准确度是分类器性能测量的主要使用指标)。

**test_loss, test_acc = model.evaluate(x_test, y_test)****print('Test accuracy:', test_acc)
print('Test loss:', test_loss)****10000/10000 [==============================] - 1s 52us/step
Test accuracy: 0.8963
Test loss: 0.3374745888918638**

我们还可以看到当模型被训练时,指标是如何变化的。为此,需要保存模型历史,并绘制图表来显示训练进行的趋势。

**history = model.fit(train_data, train_labels,
                    epochs=50,
                    batch_size=512,
                    validation_split=0.2)****acc = history.history['acc']
val_acc = history.history['val_acc']
loss = history.history['loss']
val_loss = history.history['val_loss']****epochs = range(1, len(acc) + 1)****plt.plot(epochs, acc, 'bo', label='Training Acc')
plt.plot(epochs, val_acc, 'b', label='Validation Acc')
plt.title('Training and validation Acc')
plt.xlabel('Epochs')
plt.ylabel('Acc')
plt.legend()****plt.show()**

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

模型保存和恢复

可以使用 tf.keras.Model API 在 Tensorflow 中保存和恢复模型。

**model.compile(optimizer=tf.train.AdamOptimizer(), 
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])** # Save weights to a TensorFlow Checkpoint file
**model.save_weights('./weights/my_model')**
# Restore the model's state,
# this requires a model with the same architecture.
**model.load_weights('./weights/my_model')**'''It also can be saved in keras HDF5 format'''
# Save weights to a HDF5 file
**model.save_weights('my_model.h5', save_format='h5')**# Restore the model's state
**model.load_weights('my_model.h5')****#The model arch can also be saved to a json file**# Serialize a model to JSON format
**json_string = model.to_json()
json_string** #Then it can be restored like below
**latest_model = tf.keras.models.model_from_json(json_string)**

还可以为动态模型保存创建检查点,以便操作不会因训练时的一些中间错误而丢失。

您可以在我的 git hub repo 上了解更多信息。

[## sambit9238/Tensorflow_Guide

通过在 GitHub 上创建帐户,为 sambit9238/Tensorflow_Guide 开发做出贡献。

github.com](https://github.com/sambit9238/Tensorflow_Guide)

内核介绍

原文:https://towardsdatascience.com/an-intro-to-kernels-9ff6c6a6a8dc?source=collection_archive---------9-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Mathematical tricks

内核是神奇的。

不完全是,但是他们看起来很喜欢。它们是一种数学“技巧”,允许我们不需要对数据进行技术转换就可以更快地进行某些计算。在机器学习中,它们在分类模型中用于将我们的数据分成组。对相似数据进行分组的最简单的方法是用直线,但这并不总是可行的。有时,我们的数据是以这样一种方式组织的,用一条直线将它们分开是不可能的。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

那么当我们有不可线性分离的数据时,我们能做什么呢?一个解决方案是投影我们的数据。这可以通过为我们的数据创建一个新的维度(或特征)来实现,这样我们的数据可以变得更加独立。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

将我们的数据映射到一个更高维的空间是通过一个我们称之为 phi (𝜙).)的函数来完成的

将数据映射到更高维度空间的问题在于,它在计算上可能是昂贵的。映射函数𝜙必须应用于每个数据点,然后我们仍然必须使用包含的新功能对数据进行计算。当处理大量数据和添加许多新功能时,计算成本会呈指数级增长。

对我们来说幸运的是,内核的出现扭转了局面。由于我们只需要数据点的内积来计算支持向量机的决策障碍,这是一种常见的分类模型,因此内核允许我们跳过将数据映射到更高维空间的过程,直接计算内积。数学上,核函数的定义是:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Definition of a kernel

其中 xy 是独立的数据点,𝜙是将我们的数据映射到更高维空间的东西,两端的尖括号意味着你取整个语句的内积。

为了被认为是内核,函数必须满足一些要求。

  • 函数需要是连续的,这意味着在其定义域中不能有任何缺失点
  • 它必须是对称的,这意味着 K(x,y) = K(y,x)
  • 它具有正半定性。这意味着核是具有非负特征值的对称矩阵。

有几十种核用于各种不同的问题,所以让我们来看看机器学习中最常见的三种核,线性核、多项式核和径向基函数核。

线性核

也称为“非内核”,线性内核是所有内核中最简单的。从技术上讲,当使用这个内核时,数据不会被投影到更高的维度上,所以它只是带有可选常数项 cxy 的内积。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Linear kernel equation

线性核的好处是它非常简单,只有常数项 c 作为参数。线性核通常用于具有大量特征的数据集,因为增加这些数据集的维度并不一定提高可分性。文本分类就是这类数据集的典型例子。

多项式核

与线性核不同,多项式核确实涉及到从更高维度空间取内积。多项式核可以表示为

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Polynomial kernel equation

其中三个参数是𝛼、 cd 。最常用的度数( d )是 2,因为更大的度数会导致过度拟合。多项式核通常用于自然语言处理问题。

让我们看一个例子。让我们设定𝛼=1, c =1/2, *d=2,*使这个例子成为二次型。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

正如我们所见,这个内核相当于𝜙*(x)**【𝜙】*(y)的内积,其中𝜙函数的每个元素都表示变量的不同幂。如果我们使用𝜙函数,我们将需要评估六个特征( x,x,1/2,y,y,1/2 )。内核省去了我们创建四个新特性的麻烦,只留给我们评估 xy.

径向基函数核

径向基函数(RBF)核是支持向量机中最常用的核。它被定义为

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Radial basis function kernel equation

其中,𝛾是一个自由参数,用于衡量两点之间的相互影响程度。与着眼于额外维度的多项式核不同,RBF 扩展到无限多个维度。这是由于指数的膨胀。为了使人信服,让我们设定𝛾 = 1/2 并扩展指数。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

从这里, exp(x,y) 可以使用泰勒级数近似展开成无限维。这看起来像

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这意味着两个向量的点积可以表示为

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

所以我们可以看到,一个 RBF 核等价于两个数据点的内积,这两个数据点有无限多个维度。我们现在可以明白为什么 RBF 如此受欢迎了。

我希望这篇博客能帮助你更好地理解内核。如果你还有问题,我推荐这篇论文和以下来源:

* [## 核方法

在机器学习中,核方法是一类用于模式分析的算法,其最著名的成员是核方法

en.wikipedia.org](https://en.wikipedia.org/wiki/Kernel_method)*

Apache、PySpark 和 Dataframe 转换简介

原文:https://towardsdatascience.com/an-introduction-to-apache-pyspark-and-dataframe-transformations-2a6d4229f0e3?source=collection_archive---------5-----------------------

掌握大数据分析的全面指南

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Picture from Unsplash

简介:大数据问题

Apache 是作为数据分析的新引擎和编程模型出现的。它的起源可以追溯到 2009 年,它在最近几年变得如此重要的主要原因是由于经济因素的变化,这些因素强调了计算机应用程序和硬件。

从历史上看,计算机的能力只会随着时间的推移而增长。每年,新的处理器都能够更快地执行操作,运行在其上的应用程序也自动变得更快。

所有这一切在 2005 年发生了变化,当时散热的限制导致从提高单个处理器的速度转向探索 CPU 内核的并行化。这意味着应用程序和运行它们的代码也必须改变。所有这些都为 Apache Spark 等新模型奠定了基础。

此外,传感器和存储单元的成本仅在过去几年有所下降。如今收集和储存大量信息是完全不可能的。

有如此多的数据可用,处理和分析数据的方式也必须彻底改变,通过在计算机集群上进行大规模并行计算。这些集群能够同时协同组合这些计算机的能力,并使处理数据处理等昂贵的计算任务变得更加容易。

这就是 Apache Spark 发挥作用的地方。

什么是 Apache Spark

如伟大的著作《火花——权威指南》所述:

“Apache Spark 是一个统一的计算引擎和一组用于在计算机集群上进行并行数据处理的库”

如今,Apache Spark 是最流行的大数据处理开源引擎。主要原因是:

  • 它支持广泛使用的编程语言,如:Python、Scala、Java 和 r。
  • 它支持 SQL 任务。
  • 它支持数据流。
  • 它有机器学习和深度学习的库。
  • 它可以在单台机器上运行,也可以在一群计算机上运行。

下面是一个示意图,展示了 Spark 生态系统中可用的不同库。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure by the Author

如何设置和运行 Apache Spark

在这一系列文章中,我们将重点关注 Apache Spark Python 的库 PySpark。如前所述,Spark 既可以在本地运行,也可以在计算机集群中运行。有几种方法可以配置我们的机器在本地运行 Spark,但是不在本文的讨论范围之内。

使用 PsyPark 并释放其 inmense 处理能力的最简单、最快速的方法之一是使用免费网站 Databricks,具体来说就是使用它的社区版。

要开始,我们只需访问:

[## 尝试数据块

无限集群,可扩展至任何规模的作业调度程序,为生产管道执行作业完全交互式…

databricks.com](https://databricks.com/try-databricks)

并选择其社区版:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

然后,我们必须创造和说明。

运行临时集群

一旦我们创建了一个帐户,为了能够开始工作,我们应该创建一个临时集群。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

由于是免费版本,这些集群的默认内存为 6 Gb,每个集群可以运行 6 个小时。为了开发工业项目或使用数据管道,建议使用 premiun 平台。

但是对于这些教程来说,社区版已经足够了。

添加数据

为了添加要使用的数据:

  • 单击数据选项卡
  • 然后添加数据

您可以使用其他用户上传的可用数据,也可以使用从您的计算机上传的数据。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

完成后,我们可以在笔记本中创建一个表格,这样我们就都设置好了!

Pyspark 应用和分区

为了理解 Apache Spark 如何工作,我们应该讨论 Spark 应用程序的核心组件:驱动程序、执行器和集群管理器。

下面是一个 Spark 应用程序架构的示意图:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure by the Author

驾驶员

该驱动程序位于计算机集群的一个节点中,并执行三个主要任务:

  1. 保存关于 Spark 应用程序的信息
  2. 响应输入,例如用户的程序
  3. 分析、分配和安排执行者要完成的任务。

实施者

执行者是实际执行驱动程序分配的工作的人。他们做两件事:

  1. 执行分配给他们的代码。
  2. 向驱动程序报告计算的状态。

集群管理器

集群管理器负责:

  1. 控制物理计算机
  2. 将资源分配给 Spark 应用

可以有几个 Spark 应用程序同时在同一个集群上运行,所有这些应用程序都将由集群管理器管理。

PySpark 数据帧

Apache Spark 使用几个数据抽象,每个抽象都有一个特定的接口。最常见的抽象是:

  • 数据集
  • 数据帧
  • SQL 表
  • 弹性分布式数据集

在本系列中,我们将重点关注在 Apache Spark 中表示和存储数据的最常见的单元 Dataframes。

数据帧是具有行和列的数据表,理解它们最接近的类比是具有带标签的列的电子表格。

数据帧的一个重要特征是它们的模式。数据帧的模式是一个列表,其中包含列名和每列存储的数据类型。

数据帧的其他相关属性是它们不位于一台简单的计算机中,事实上它们可以被分割到数百台机器中。这是因为优化了信息处理,并且当数据太大而不适合单台机器时。

Apache 分区

如前所述,执行器执行驱动程序分配的工作,并且它们以并行方式执行,为了能够做到这一点,将数据火花分割到不同的分区。

这些分区是位于群集内单台计算机中的行的集合。当我们谈论 Dataframe 的分区时,我们谈论的是数据如何分布在我们集群上的所有机器上。

大多数情况下,我们不会明确指定如何在集群中进行分区,但通过我们的代码,我们将传输数据的高级转换,Spark 将自行意识到哪种方式是执行这些分区的最佳方式。总是寻求获得最大的处理效率。

执行这些操作的低级 API 超出了本系列的范围。

数据框架转换

首先,我们必须明白,转换是我们指定对数据帧进行的修改。

这些转换是以一种高级的方式指定的,并且直到我们明确地调用一个动作时才会被执行。

这种工作方式叫懒评,目的是提高效率。当我们要求进行转换时,Spark 会设计一个计划来优化执行这些任务,直到最后一分钟我们要求一个动作(如。显示()或。收集())

苹果股价

现在,我们将探讨一些最常见的操作和转换。我们将从 2010 年到 2016 年研究苹果股价的数据。我们将执行一些探索性的数据分析、数据转换、处理缺失值并执行分组和聚合。

导入数据框架

要初始化和显示数据帧,代码如下:

**# File location and type**
file_location = "/FileStore/tables/appl_stock.csv"
file_type = "csv"# CSV options
infer_schema = "true"
first_row_is_header = "true"
delimiter = ","**# The applied options are for CSV files. For other file types, these will be ignored.**
df = spark.read.format(file_type) \
  .option("inferSchema", infer_schema) \
  .option("header", first_row_is_header) \
  .option("sep", delimiter) \
  .load(file_location)**# Display Dataframe**
display(df)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

获取数据框架的模式

数据帧的模式是数据结构的描述,它是 StructField 对象的集合,并提供关于数据帧中数据类型的信息。

显示数据帧的模式非常简单:

**# Display Dataframe's Schema** df.printSchema()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

执行过滤和转换

为了过滤我们的数据,只获取那些收盘价低于$500 的行,我们可以运行下面一行代码:

**# Filter data usign pyspark**
df.filter(" Close < 500").show())

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们还可以过滤以仅获取某些列:

**# Filter data by columns**
df.filter("Close < 500").select(['Open', 'Close']).show()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

要按一列过滤并显示另一列,我们将使用。选择()方法。

**# Filter by one column and show other**
df.filter(df['Close'] < 500).select('Volume').show()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

要按多个条件过滤:

**# Filter by multiple conditions: closing price < $200 and opening price > $200**
df.filter( (df['Close'] < 200) & (df['Open'] > 200) ).show()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

获取数据的统计汇总

与 Pandas 等其他库类似,我们可以通过简单地运行。describe()方法。

**# Display Statistic Summary**
df.describe().show()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

添加和重命名列

要向 dataframe 添加新列,我们将使用。withColumn()方法如下。

**# Display Dataframe with new column**
df.withColumn('Doubled Adj Close', df['Adj Close']*2).select('Adj Close', 'Doubled Adj Close').show()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

要重命名现有的列,我们将使用。withColumnRenamed()方法。

**# Display Dataframe with renamed column**
df.withColumnRenamed('Adj Close', 'Adjusted Close Price').show()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

分组和聚合数据

现在,我们将对我们的数据进行一些整理和汇总,以获得有意义的见解。但是首先,我们应该导入一些库

**# Import relevant libraries**
from pyspark.sql.functions import dayofmonth,hour,dayofyear,weekofyear,month,year,format_number,date_format,mean, date_format, datediff, to_date, lit

现在,让我们创建一个新列,每行包含年份:

**# To know th average closing price per year**
new_df = df.withColumn('Year', year(df['Date']))
new_df.show()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

现在,让我们按最近创建的“年度”列进行分组,并按每年的最高、最低和平均价格进行聚合,以获得对价格状态和演变的有意义的见解。

**# Group and aggregate data**
new_df.groupBy('Year').agg(f.max('Close').alias('Max Close'), f.min('Close').alias('Min Close'), f.mean('Close').alias('Average Close')).orderBy('Year').show()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们已经实现了我们的目标!然而,我们仍然有一些非常难读的数据。事实上,我们有比我们需要的更多的小数。

考虑到我们正在处理数百美元的价格,超过两位小数并不能为我们提供相关信息。

因此,让我们利用这一优势,学习如何格式化结果,以显示我们想要的小数位数。

格式化我们的数据

为了格式化我们的数据,我们将使用 format_number()函数,如下所示:

**# Import relevant functions**
from pyspark.sql.functions import forman_number, col**# Select the appropiate columns to format** cols **=** ['Max Close', 'Min Close', 'Average Close']**# Format the columns** formatted_df = new_df.select('Year', *[format_number(col(col_name), 2).name(col_name) for col_name in cols])

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

用户定义的函数

现在让我们学习如何将我们定义的函数应用到我们的数据帧中。我们将在本例中使用它来获取一个列,其中记录了每行的月份。

**# Import relevant functions**
from pyspark.sql.functions import date_format, datediff, to_date, lit, UserDefinedFunction, month
from pyspark.sql.types import StringType
from pyspark.sql import functions as F**# Create month list** month_lst = ['January', 'Feburary', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']**# Define the function** udf = UserDefinedFunction(lambda x: month_lst[int(x%12) - 1], StringType())**# Add column to df with the number of the month of the year** df = df.withColumn('moy_number', month(df.Date))**# Apply function and generate a column with the name of the month of the year** df = df.withColumn('moy_name', udf("moy_number"))

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

成功!

结论

在本文中,我们讨论了:

  • Apache Spark 的基础
  • 我们对它的重要性和运作方式有了直觉
  • 使用 PySpark 和 Dataframes 执行分析操作

在接下来的文章中,我们将学习如何在 PySpark 中应用机器学习,并将这些知识应用到一些项目中。敬请期待!

最后的话

如果你喜欢这篇文章,那么你可以看看我关于数据科学和机器学习的其他文章 这里

如果你想了解更多关于机器学习、数据科学和人工智能的知识 请在 Medium 上关注我,敬请关注我的下一篇帖子!

注意力入门

原文:https://towardsdatascience.com/an-introduction-to-attention-transformers-and-bert-part-1-da0e838c7cda?source=collection_archive---------1-----------------------

为什么和什么

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们最大的困惑来源是七足动物的“书写”它看起来根本不像是在写作;它看起来更像是一堆复杂的图形设计。这些语标没有排成一排,或者一个螺旋,或者任何线性的样式。相反,Flapper 或 Raspberry 会根据需要将尽可能多的徽标粘在一起,形成一个巨大的聚合体,从而写出一个句子。

姜峯楠的中篇小说《你生命的故事》中的这几行也许能很好地说明基于注意力的架构与普通 RNNs 的顺序性质有何不同。

让我们快速地看一下普通的 RNNs 和用于任务排序的编码器-解码器变体,了解这些设计有什么缺点,并看看注意力机制如何解决它们。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Fig 1: Vanilla RNN example

一个普通 RNN 的基本前提是一个接一个地解析输入序列中的每一项,并在每一步中不断更新它的“隐藏状态”向量,如图 1图 1 所示。每一步末尾的这个隐藏向量被理解为表示所有先前输入的上下文。换句话说,最后一个隐藏状态表示整个序列的上下文。

在序列到序列的翻译任务中,这个代表上下文的产生隐藏状态的 RNN 被认为是一个编码器,最终的隐藏状态向量,在图 2 的中被称为“上下文”,被馈入另一个称为解码器的序列产生 RNN。

但是,这种连续的处理本质是重要的还是让我们处于劣势?有些语言的词序并不重要,比如波兰语和匈牙利语。或者甚至在英语中,我们可以根据我们想要强调的内容改变词序。有时甚至在实际应用中,比如在诊断预测模型中处理患者的病史时,事件间的关系甚至比实际事件序列本身更重要。

直观地说,这种严格的处理顺序可能类似于平面二维图像,即从矩阵转换为矢量,并使用普通的前馈网络来处理它。与在矩阵表示中保持自然空间关系的 CNN 架构相比,它的效率要低得多(当然,与在图像中不同,我们不知道是否存在正确的顺序或者该顺序是什么。原来如此!).这种严格的顺序性处理也许是 的第一个缺点

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Fig 2: RNNs in Seq to Seq Encoder Decoder model

这就是 LSTMs 和 GRUs 通过各种细胞水平的创新(如遗忘门、重置门、更新门等)提供仅携带相关信息从一个步骤到下一个步骤的方法的巨大帮助。双向 RNNs 提供了一种机制,不仅可以查看先前的输入,还可以查看随后的输入,然后在某个时间步长生成输出。这样的发展解决了“严格顺序”的问题,但是并没有完全解决下一个挑战。

输入序列长度(即 NLP 中的句子长度)越长,隐藏向量捕获上下文就越困难(由 Cho 等人在此提出的解释性假设,可以在 Koehn 和 Knowles 在此的论文中找到性能下降的实验证明)。这个缺点直觉上是有道理的;对同一向量进行的更新越多,早期输入和更新丢失的可能性就越大(如图 3 所示)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Fig 3: Context becomes weak with longer sentences

我们如何解决这个问题?也许如果我们不再使用最后一个隐藏状态作为整个句子的代理,而是建立一个消耗所有隐藏状态的架构,那么我们就不必处理弱化的上下文。这就是“注意力”机制的作用。Bahdanau 等人在这篇论文中介绍了这一点。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Fig 4: Using all hidden states, not just the last one

在提出的模型中,每个生成的输出字不仅仅是最终隐藏状态的函数,而是所有隐藏状态的函数。而且,这不仅仅是一个简单的合并所有隐藏状态的操作——如果是的话,那么我们仍然给每个输出步骤相同的上下文,所以它必须是不同的!它不是简单的连接或点积,而是“注意”操作,对于每个解码器输出步骤,产生代表所有编码器隐藏状态的不同向量,但是对不同的编码器隐藏状态给予不同的权重。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Fig 5: From paper by Bahdanau et al.

输出步骤的不同上下文向量是注意力权重和所有输入隐藏状态的和积。每个单一输出的注意力权重将是不同的,因此加权隐藏向量的总和对于每个输出步骤是不同的。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Fig 6: Based on paper by Bahdanau et al.

请记住,“关注”的精神更多的是关注每个输出步骤的各种输入的能力,而不是关注其他方面,如使用的对齐函数、所涉及的 RNN 的性质等。因此,您可能会遇到上述内容的其他变体。

就这一点而言,虽然这种解决方案似乎解决了单个上下文向量的问题,但它使模型变得非常大。当您试图为每个输出步骤准备一个单独的上下文向量时,会涉及到大量的计算。

此外,还有另外一个问题,这个问题的计算复杂度没有被这个解决方案引入,但是甚至在基本的 RNN 中也存在。给定操作的顺序性质,如果输入序列的长度为“n”,则需要“n”个顺序操作来达到最终的隐藏状态(即计算 h1、h2 等,直到 hn)。我们不能并行执行这些操作,因为 h1 是计算 h2 的先决条件。序列中并行性的缺乏也不能通过在训练批次中添加更多样本来弥补,因为加载和优化不同样本的权重会增加内存需求,这将限制批次中可以使用的样本数量。**

解决其中一些问题需要我们看看注意力的一些其他变体,随后它将引导我们探索变压器模型。我打算在另一篇文章中写这些,希望很快。

自动驾驶汽车介绍

原文:https://towardsdatascience.com/an-introduction-to-autonomous-vehicles-91d61ff81a40?source=collection_archive---------9-----------------------

对自动驾驶汽车的大致了解。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Lyft’s self-driving car [Source]

每年,T2 大约有 125 万人死于交通事故。这相当于每天 3287 人死亡!作为一个刚刚学会开车的青少年,这是一个萦绕在我脑海深处的可怕事实。除此之外,我们还不得不忍受数量惊人的交通,这对大多数人来说只是制造了不必要的挫折。

这让我开始思考……有没有另一种方法可以复制人类的驾驶,但要比人类好 20 倍?

这是我发现自动驾驶汽车的地方。

自动驾驶汽车是如何工作的?

对于自动驾驶汽车(SDC),目标是能够像人类司机一样驾驶汽车。唯一的问题是座位后面没有司机。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Caption this on a highway with no driver! [Source]

听起来很吓人,对吧?

你可能想知道,在做如此复杂的事情时,计算机(或者在这种情况下,汽车)是如何接近人类智能的?要回答这个问题,我们需要了解构成 SDC 的五个组成部分:

  1. 计算机视觉
  2. 传感器融合
  3. 本地化
  4. 路径规划
  5. 控制

如果你不懂那些术语,不要担心!目前,解决这个问题的一个好方法是把 SDC 想象成人类。

计算机视觉

像人类司机一样,我们需要能够看到我们周围的环境,无论是看前方的交通还是阅读路标,视觉都是🔑。

同样,计算机视觉是汽车如何看到它的环境

在 SDC 的计算机视觉中,目标是能够识别汽车附近的物体。我们通过使用一种叫做(卷积神经网络)的图像分类网络来做到这一点。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

SDC being able to identify cars in front of them. [Source]

传感器融合

让我们回过头来想想一个人类司机。

假设司机被困在拥挤的交通中。司机通过分析环境知道这一点。

这相当于传感器融合的思想:能够以详细的方式理解环境。因为一辆 SDC 上装备了一堆传感器,我们可以获取所有必要的数据并融合它们来为我们的汽车提供更丰富的图表,因此得名传感器融合

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Generating a detailed environment using LiDAR [Source]

本地化

酷酷。这就是我们目前对 SDC 的了解:

  • 它能看见
  • 它知道它的环境

但是,难道你不认为确切知道你在哪里也很重要吗?就像如果你知道 Chick-fil-a 就在街区附近,那不是很有用吗?在 SDC,我们希望能够找出我们的车在现实世界中的位置,这样我们就可以更好地决定如何从 A 点到达 b 点

这就是事情变得复杂的地方,需要复杂的数学算法。现在,只要把定位想象成你手机上的 GPS。

路径规划

很好,现在我们更新后的列表如下所示:

  • 它能看见
  • 它知道它的环境
  • 它知道自己的位置

下一步是计划旅程。以我们的人类司机为例。在整个乘车过程中,司机可能在考虑要避开的特定街道和预计到达时间。这也正是 SDC 人所做的。

它不断地问,“我怎样才能以可能的最佳方式从 A 点到达 B 点?”。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

控制

一旦我们找到了路径,汽车所要做的就是能够操控方向盘。唯一的挑战是以类似人类的方式驾驶汽车(例如只是不是自动的),这需要大量的练习。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

[Source]

当前应用

有很多公司像 Waymo(谷歌公司)、优步和 Lyft 都在 SDC 大肆宣传,但距离我们达到第五级自动驾驶(无人驾驶,接近 100%准确)还有很长的路要走。

目前,最接近的公司是 Waymo,它的 SDC 行驶了超过 1000 万英里。那大概是 10 辈子的驾驶!

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

No driver! [Source]

然而,SDC 的未来仍然是一个讨论的话题,最终将取决于人们是否决定在 SDC 变得广泛可用时信任他。

TL;博士

在谷歌和优步等公司的引领下,自动驾驶汽车为下一代交通工具带来了光明的未来。无人驾驶汽车背后的主要组件如下:

  • 计算机视觉(汽车如何看到)
  • 传感器融合(汽车如何理解其环境)
  • 定位(汽车如何知道其位置)
  • 路径规划(汽车如何思考关于最优路线)
  • 控制(汽车如何操纵车轮)

资源

  • 优步了解更多关于 SDC 的信息
  • 了解更多关于激光雷达(在 SDCs 中非常重要)

如果你喜欢我的文章或者学到了新的东西,请务必:

  • 通过 LinkedIn 与我联系
  • 发送一些反馈(我总是乐于接受建议!)

贝叶斯推理导论

原文:https://towardsdatascience.com/an-introduction-to-bayesian-inference-e6186cfc87bc?source=collection_archive---------11-----------------------

和马尔可夫链蒙特卡罗

前言:下面的帖子旨在介绍一些数学知识。它假设您对统计学有一定的了解。虽然包括数学,但我绝不是专家。我努力学习概率编程的基础知识,希望这能帮助其他人理解这个世界。如果您发现任何错误,请留下评论并帮助我们学习。干杯!

在数据科学中,我们通常对理解数据是如何产生的感兴趣,主要是因为它允许我们回答关于新的和/或不完整的观察的问题。更具体地说,我们希望对观察数据中的输入影响输出数据的过程和程度进行建模。但是对于任何给定的数据集,有无限多种可能的模型结构可以合理地解释数据集是如何生成的。但是并不是所有的模型结构都是一样的——也就是说,基于我们对世界如何运作的假设,某些模型结构比其他模型结构更现实。由建模者选择最能描述他们所观察的世界的一个。

**目标:**找到最能解释数据集 D 如何生成的模型 M

即使我们已经选择了我们对世界的影响的假设(即模型结构),模型结构本身到目前为止还是抽象的。例如,我们可能认为预测我吃冰淇淋概率的模型是合适的,如果我们设置它,使日期和我的位置影响温度,从而影响我狼吞虎咽黑巧克力冰淇淋(最好的一种)的机会。但这只是给出了模型结构。理想情况下,我们希望有一个函数,可以为给定日期和地点的任何可能的冰淇淋结果分配概率。为了做到这一点,我们还需要知道每一个输入对模型的每一层有多大的影响——这些是由模型参数 θ捕获的。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

I love gelato.

**修改后的目标:**对于包含我们对世界结构的假设的给定模型结构 M (即我们认为数据是通过其产生的影响过程),如果观察到的数据 D 是在这个选择的模型下产生的,那么模型的参数 θ 的值是多少?

换句话说,我们可能感兴趣的是找到 θ 的值,这些值最大化了在给定 X s 的情况下观察到 y s 的可能性(换句话说:最大化了观察到的数据 D 的可能性)。这被称为最大似然估计。

回到意式冰淇淋:想象你记录了我每天在哪里,我是否吃意式冰淇淋(奇怪,但也许我的医生担心我吃了太多的意式冰淇淋)。最大似然估计器将输出使似然函数最大化的θs*。似然函数是我们观察到的 y s(我的冰淇淋消耗量)和 X s(日期和我的位置)的概率,如果这些 y s 确实是由那些 θ s 和那些 X s 生成的。最大化似然性给了我们看起来最能解释数据的 θ s 组合。*

通常,我们试图搜索模型参数值的每一个组合,并计算具有该组特定模型参数值的模型生成我们的观察数据的概率。当然,在大多数实际情况下,搜索 θ 的每个组合是不可能的,所以在传统的机器学习中,我们用梯度下降等算法来优化这种搜索,这些算法根据当前值的组合在解释观察到的数据方面的表现来选择接下来要测试的 θ 的哪些值。然后,我们选择并报告最大化数据可能性的 θ 组合。

这种方法的一个问题是,我们报告的是 θ s 的单一组合作为我们的最佳估计值,但是看到这份报告的其他人不会知道我们对每个报告的参数值有多大的把握。这是一个问题,因为观察到的数据几乎总是真实总体的样本,并且本质上是有噪声的,不管我们收集了多少数据;我们永远不应该对模型参数的任何点估计有 100%的把握。考虑一下,如果我们观察到一个不同的或有限的人口样本(例如,如果我只记得记录我 75%的时间里的冰淇淋消费量,或者只有当我在纽约的时候,会怎么样?),我们报告的 θ s 会发生剧烈变化还是最小变化?知道了每个 θ 值的可信区间,就嵌入了这样的信息,即基于我们看到的数据,我们认为我们对给定模型参数的估计有多有代表性,这通常可能代表真实物理现象的影响。我们也很少知道关于我吃冰淇淋的知识会如何影响某个温度或我在某个城市的概率(即反向推断)。

贝叶斯推理

为了解决这些问题,我想介绍一下贝叶斯推理,贝叶斯法则是我们的口头禅:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Eqn 1: Bayes Rule

让我们看看如何将它应用到我们的目标中。回想一下,给定我们观察到的数据:P_M ( *θ | D),在我们选择的模型结构下,知道参数值 θ 的概率分布是理想的。*将此代入贝叶斯法则:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Eqn 2

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Eqn 3

我们现在可以将等式 2 改写为:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Eqn 4

如果我们选择 θ 的值来测试我们预先选择的模型,计算 P_M ( D | θ) 真的很容易,因为我们知道这个建模函数的所有输入/输出/参数(回想一下这被称为似然性), 我们还知道先验 P( θ) ,因为它代表了我们对特定 θ 的信念(例如,对于看似公平的硬币, θ 很可能是以 0.5 为中心的法线,根据我们对硬币公平程度的信念,我们可能会增加或减少该法线的方差)。 对于选定的 θ ,计算 EQN 4 的分子非常简单。

问我们每一个可能的 θ 的数量,我们很快意识到我们在传统的机器学习中遇到了同样的问题:我们无法对每一个 θ 进行采样!换句话说,EQN 4 的分母几乎无法计算。

MCMC

开发马尔可夫链蒙特卡罗(MCMC)技术是为了智能地采样 θ s,而不是直接对每个可能的 θ 的似然性和先验性求和。这些技术背后的主要思想类似于我们在传统机器学习中看到的 θ 更新技术:我们根据我们对当前一组 θ 值的可能性的评估,用一组新的 θ 值进行“更新”。这里最大的不同是,我们是取样而不是更新——换句话说,我们对我们探索过的价值观的历史感兴趣。这很重要,因为我们不再只是对知道每个参数的单个最佳估计感兴趣(这是我们在梯度下降中所做的),而是对知道每个参数的“好”估计的集合以及它们的可能性有多大感兴趣。(即给定 Dθ 的概率分布)。

让我们深入研究 MCMC 算法的高级概述以及它们在这里工作的原因。MCMC 关心跟踪两件事:

θ_current: 单个 θ 我们目前感兴趣的
trace_θ :所有 θ_current 的列表

MCMC 首先选择一个随机初始值 θ :

θ_ current =θ_ 0
trace θ=[θ 0】

并计算似然和先验(即等式 4 的分子)。创建 MCMC 的目的是,尽管分母在所有的 θ 选择中保持不变,但我们不能直接计算分母中的和,所以我们暂时把它放在一边。在这一点上,我们不知道我们选择的 θ_0 是否是一个好的选择。相反,我们选择一个提议 θ_1 (在这一点上,认为它被神奇地选择了,但我们很快就会回到那个问题上)如果它在 EQN 4 中产生一个更大的分子,我们可以同意它是对 θ 的更好选择。这是因为在 EQN 4 中分母是不变的,不管我们选择还是θ 来代入 EQN 4。既然我们知道 θ_1 更好,让我们把它加到我们的迹中,更新我们当前的 θ ,并计算似然和先验(即 EQN 4 的分子):

θ_ current =θ_ 1
trace θ=[θ 0,θ_ 1】

我们现在可以选择一个新的 θ_2 来提出(目前仍是一个神奇的过程),如果它不能很好地解释数据(即,它产生了等式 4 的一个较小的分子),那么我们这次不会立即接受它,而是将它接受到我们的 θ_currenttrace_θ 的概率𝛼:中

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Eqn 5

之所以这样,是因为我们可以推论出 θ_2 只有𝛼和 θ_current 一样好。这意味着在我们的采样历史中,我们应该期望我们采样的次数 θ_2 是我们采样的次数 θ_current 的𝛼的一个因子:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Eqn 6

在这种情况下,经过充分的采样后,您应该会有一种直觉,即我们将会探索大量的 θ 值,并将它们保存在跟踪变量中,其频率与 θ 值相对于其他θ值解释数据的程度成比例,这正是我们感兴趣的分布

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

最后,我们回到如何生成好的建议 θ s 的问题。如果我们没有方法并在 θ 的所有可能值中随机选择 θ s 来建议,我们将拒绝太多的样本(考虑到 θ 的真实密度可能是相对窄分布的)。相反,我们从建议分布q(θ_ proposed |θ_ current)中得出θs。例如,我们可以选择使 q 成为具有固定方差和平均值 θ_current 的正态分布。

这是最流行的 MCMC 算法之一 Metropolis-Hastings (MH)的本质。我们通过以下方式将其纳入我们的𝛼接受率:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Eqn 7

如果我们选择对称建议分布(如正态分布),则:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Eqn 8

由此可见,𝛼_ = 𝛼.这叫做随机漫步 MH 算法,你会得到这样的图:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image 1

左图是“intercept_mu”参数的 KDE 图(本质上是一个平滑的直方图),右图是每个采样链随时间变化的轨迹。我们可以推断,虽然参数(轨迹的模式,也称为地图)最可能的值是 0.16,但参数的可信区间可能在 0.1 和 0.21 之间。

附录:

  • 为了更直观地解释这个过程,请看这段视频
  • 大多数帮助你进行 MCMC 的软件包通常会运行 3 个或更多的轨迹(也称为“链”),它们具有不同的随机初始化,以确保链是“收敛的”。这很重要,因为聚合链表明你的马尔可夫链已经稳定。
  • 我通常会考虑老化期,它会丢弃最初的几千个样本,这些样本可能取决于θ的随机初始化
  • 先验的选择对抽样结果有影响。不要选择太窄的先验(因为你的偏见会妨碍对参数空间的正确探索,你的链将无法收敛)或太宽的先验(称为无信息先验,你收敛的机会也会减少,因为你会花太多时间拒绝无用的样本)。
  • 我通常使用曲线的模式或均值来报告最可能的值,并使用 HPD(最高后验密度)区间来建立可信区间。

大数据、Apache Spark 和 RDDs 简介

原文:https://towardsdatascience.com/an-introduction-to-big-data-apache-spark-and-rdds-975ef4d91be2?source=collection_archive---------8-----------------------

Spark 架构如何优化以处理大型数据集的基本方法

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by NASA on Unsplash

我们每天总共产生超过 2.5 万亿字节的数据。

yelp 评论、广告点击或地理坐标——只要你说得出,我们的数字足迹就可能在那里。从社交媒体平台上的数百万内容创作者到源源不断的交易行项目,我们的世界一直在以指数速度产生数据。它们的大小从 0.7 MB 的 twitter 帖子到 100 多 PB 的优步地理交通洞察

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Current big data systems are processing datasets in the Petabytes range

随着这一趋势,重要的是,我们有能力捕捉它,解释它,并基于它做出“数据驱动的决策”。但为了让我们真正获得这些见解,数据科学家围绕大数据以及如何处理如此庞大的信息创建了一个完整的领域。

特别是,大数据需要更强大的计算工具,而不仅仅是标准的 excel 回归,甚至是你可能熟悉的 python 熊猫。特别是在处理企业级生产级数据集或考虑为任何具有数据播放功能的初创公司进行扩展时,大数据平台是管理和分析您所有大数据需求的核心。其中一个平台 Apache Spark 已经成为处理大数据的事实平台,并继续成为学术界和行业中数据专家使用最多的平台。本文旨在将 Spark 的核心概念分解成简单明了的描述。

Spark 处理大数据

让我们从 Apache Spark 网站开始——Spark 是一个“用于大数据处理的统一分析引擎”从高层次来说,它是一个计算框架,允许我们:

  1. 加载/接收大量实时数据(流)
  2. 转换/清理大量数据(SQL 操作)
  3. 对大量数据运行 ML 分析技术(机器学习)
  4. 处理大量数据的图形网络(图形处理)

看到模式了吗?处理大数据的各种计算功能。我们用 Python、R、Scala 和 Java 为 Apache Spark 编写代码,脚本通常运行在支持这些大型计算的平台上。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

A Big Number of Big Machines process Big Data

这些运行 Spark 的平台通常是基于云的(微软 Azure、AWS、谷歌云等。)并写在与云环境相连的笔记本上。这些笔记本电脑由联网的计算机集群支持,可以高效地处理大型数据集,这是您单独的笔记本电脑或 PC 无法处理的。(更多关于如何以后)

RDD 作为火花的基本抽象

Apache Spark 通过一种称为弹性分布式数据集(RDD)的抽象来处理这些海量数据。你会经常听到这个词,因为它是 Spark 强大的数据处理引擎的基础。

从高层次上讲,RDD 是一种逻辑结构,它允许我们以我们熟悉的传统表格格式可视化数据,并在数据集上运行必要的 SQL 查询。它的核心是一个 java 对象,有内置的方法(如 RDD_example.map()RDD_example.filter() 等)。)允许我们操作传入的原始数据。RDD 仅仅是一个抽象,负责处理(存储&转换)我们传入的数据。

然而,在幕后,RDD 通过对数据子集进行分区来有效地处理大数据,这些子集可以在各个节点上并行地在上操作,并且每个分区都有副本以防止数据丢失。下面是一个用 RDD 表示数据的具体例子:

示例:让我们给 Spark 100GB 的数据:

假设在这个设置中我们有 5 个工作节点可用。Spark 认识到将所有 100 GB 分配给一个工作节点而让其他四个空着是低效的。相反,它选择将这个原始数据集划分到工作节点上,以平均分配工作负载。Spark 决定将数据划分为 100 个分区(从技术上讲,分区数量是您首先设置的参数),每个分区有不同的 GB。

现在,节点#1 获得第一个 20 GB,节点#2 获得 21–40gb,节点#3 获得 41–60gb,依此类推。

但是并不是所有的数据都是同等地创建的——有些数据可能比其他数据运行得更快,而有些数据可能过于繁重,以至于会导致节点崩溃。

Spark 决定为节点#1 提供 21–40gb 和 41–60gb 的副本,为节点#2 提供 41–60gb 和 61–80gb 的副本,依此类推。

因此,虽然每个工作节点主要负责其原始的 20 GB,但它也存储其他 GB 分区的副本。*因此,Spark 有效地将数据划分到节点上,这样工作节点可以并行计算数据,同时防止空闲节点。*也就是说,如果一个工作者节点提前完成了它的计算,它可以从另一个工作者节点(可能很慢或者已经崩溃)那里“拾起空闲”并支持另一个 GB 分区的计算。

从示例中,我们可以看到以下几点:

  1. 数据具有弹性 —通过存储数据的多个副本,每个副本存储在不同的节点中,我们可以避免在一个或多个节点发生故障的罕见情况下丢失数据。
  2. 数据是分布式的 —很明显,在最初的 100GB 数据中,我们已经跨多个节点对数据进行了分区或分片。这使得每个节点处理的数据更少,从而提高了整体运行速度。
  3. 数据是一个数据集 —它是一个保存数据的数据结构。在表功能中,它可以被格式化为具有索引的命名列,但是除了被分区之外,它也可以没有正式的结构组织。当它以 DataFrame 对象的形式使用内置方法时,可以为这种特殊的数据集提供更丰富的优化。

这就产生了弹性分布式数据集的名称。当然,这个过程还存在更多的细微差别,但是上面的例子试图说明 Spark 使用 rdd 的效率的一个简化的思考过程。

PySpark 中 rdd 的 4 行代码

RDD_example = sc.parallelize([1,2,3])
o = RDD _ example . filter(lambda I:I % 2)。map(lambda I:I * 2)
result = o . collect()
print(结果)

##(输出:2,6)

注意,使用并行化方法的第一行,我们从传入的整数列表中创建 RDD。可以把并行化想象成这样——创建 RDD,这样我们就可以并行处理数据。

在我们创建的 RDD 上,我们对该对象应用了两个额外的方法,这两个方法仍然返回 RDD 对象。过滤器和映射都是 MapReduce 框架的一部分,接受各自的匿名函数。在这种情况下,我们过滤 RDD 以包含奇数的元素,然后将加倍函数映射到这些相应的元素。

惰性评估和 Dag

在这一点上,RDD 的方法似乎与我们在 CS 入门课程中看到的方法相同。那么,为什么我们要费这么大的劲来过滤一个函数并把它映射到一个列表上呢?来评价一下 Spark 如何懒懒地计算*。*

上面的例子,在我们调用 collect 的最后一行,简洁地显示了 spark 转换动作之间的区别。在这里,我们可以深入了解——的转变。过滤器()和。先前的 map()没有被实际执行,而是被放入执行 map 中,以便稍后被动作激活。的。collect()操作方法实际上用于执行整个代码序列,并开始跨节点的计算。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

The local environment execution plan as a Directed Acyclic Graph (DAG) https://spark.apache.org/docs/latest/cluster-overview.html

转换在本地环境中创建的执行计划存储在一个有向无环图(DAG)中。与中一样,计算的步骤遵循一个连续的方向,永远不会循环回自身。

长话短说,转换方法是返回放入 DAG 的 RDD 的 RDD 方法。动作方法通常是启动 Spark 引擎进行计算的最终操作。转换在本地环境中添加 DAG,并且在动作调用时,DAG 被发送到主驱动程序上的主 Spark 解释器。

大局

在 Spark 如何运行以及 RDD 如何融入框架的更大范围内,下图抓住了中央驱动程序如何在工作节点之间分布的核心。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

https://spark.apache.org/docs/latest/cluster-overview.html

我们称之为初始的 sc 对象或 SparkContext。parallelize()方法是 Apache Spark 的内置功能,我们可以将其视为主驱动程序的一部分。这个火花上下文对象是我们创建的,或者是给予我们的,这样我们就有能力创建 RDD。从那里,主驱动程序从您的 PySpark 脚本接收 DAG 执行计划,序列化代码(例如,转换成位和字节),并将各自的分区发送到它们通过 API 调用接收的工作节点。然后,每个工人执行从 DAG 分配给他们的操作。这提升了 Spark 并行计算和高效处理大数据的能力。

fast.ai 中使用迁移学习的计算机视觉导论——飞机分类

原文:https://towardsdatascience.com/an-introduction-to-computer-vision-using-transfer-learning-in-fast-ai-aircraft-classification-a2685d266ac?source=collection_archive---------5-----------------------

使用 fastai 和 pytorch 的图像分类简介

介绍

我来 fast.ai 派对有点晚了,不过有句名言是这么说的,

迟做比不做好

这不是最伟大的格言,但对我来说很管用。

2018 年 11 月,我开始探索用于深度学习的 fast.ai 库,这是通过杰瑞米·霍华德同名的奇妙 MOOC 实现的,我想在一些数据集上对该库进行实验,以获得良好的感受。我还从我的朋友 Aayush Agrawal博客文章中获得了灵感,这篇文章是关于使用转移学习通过叶子图像检测植物疾病的

fast.ai 是一个 Python 深度学习库,位于脸书深度学习 PyTorch 框架之上。在这篇文章中,我们看看如何使用迁移学习对 9 个飞机模型进行分类,数据集是我通过从互联网下载 9 个飞机模型的图像手动构建的,如下所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Airbus A320 — Airbus A340 — Airbus A350

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Airbus A380 — Boeing 737 — Boeing 747

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Boeing 757 — Boeing 777 — Boeing 787

从小我就一直对飞机很着迷。也有一段时间,我梦想成为一名飞行员——但我猜这些梦想从未实现过(看到我在那里做了什么吗?)——所以我决定把这种魅力带进我的深度学习探索中。现在让我们深入 Python 代码,看看所有这些是如何展开的:

导入必要的模块

让我们从导入计算机视觉问题所需的模块开始:

from fastai.vision import *

可能会有一群 Pythonistas 等着向我扔鸡蛋,因为我使用了上面的import *,但这几乎是这篇文章所需要的。这个库包含了很多功能,随着我们对数据探索的深入,您将会意识到它的易用性。

探索数据

我们的图像数据集作为.jpg文件存储在 9 个不同的文件夹中,每个文件夹都带有文件夹中包含的图像的飞机模型名称。我们使用ImageDataBunch.from_folder()函数来加载图像,并根据读取图像的文件夹的名称给图像分配标签。

我们首先声明文件夹所在的路径:

这就是我们加载这些图像所需要做的一切。显然这是一个对编码者友好的库。

上面的.normalize(imagenet_stats)方法用于根据 ImageNet 数据集的 RGB 通道的统计数据来标准化数据集。

现在我们已经加载了数据集,让我们看一看它是什么样子的:

data.show_batch(rows=3, figsize=(7,8))

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我看没问题。让我们看看什么是图像类、类的数量以及训练集和测试集的大小:

data.classes —我们的数据集中有哪些类别的飞机?

['airbus_a320',
  'airbus_a340',
  'airbus_a350',
  'airbus_a380',
  'boeing_737',
  'boeing_747',
  'boeing_757',
  'boeing_777_300',
  'boeing_787']

data.c —我们的数据集中有多少个类?

9

len(data.train_ds) —我们的训练数据集有多大?

2473

len(data.valid_ds) —我们的验证数据集有多大?

618

因此,我们在训练集中有 2473 幅图像,在测试集中有 618 幅图像(约 20%),如上面的ImageDataBunch.from_folder()函数所定义。

训练模型

我们现在使用预训练的 ResNet50 卷积神经网络模型,并使用迁移学习来仅学习网络的最后一层的权重。

为什么要转学?因为使用迁移学习,你从一个现有的(经过训练的)用于图像识别的神经网络开始,然后在这里或那里稍微调整一下,为你的特定用例训练一个模型。我们为什么要这么做?训练一个合理的神经网络将意味着需要大约 300,000 个图像样本,并且为了实现真正良好的性能,我们将需要至少一百万个图像。在我们的例子中,我们的训练集中有大约 2500 幅图像——如果我们从头开始训练神经网络,你有一个猜测来决定这是否足够。

我们使用create_cnn()函数来加载预训练的 ResNet50 网络,该网络是在来自 ImageNet 数据库的大约一百万张图像上训练的。

现在,让我们拟合 4 个时期的一个周期,看看我们的模型在该数据集上的表现如何:

learn.fit_one_cycle(4)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

为什么只有 4 个纪元?我想尝试和基准我的第一次尝试与调整,我会在一段时间内,使一个合理的比较。通过 4 个时期,并且没有对我们的模型进行调整,我们已经成功地实现了(?)大约 32%的错误率(这相当于 68%的准确度)。这有多好?当我们进一步阅读时,我们会找到这个问题的答案。

让我们看看我们的模型预测有什么问题:

interp = ClassificationInterpretation.from_learner(learn)interp.plot_top_losses(8)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

上面图像中的热图描绘了图像中激活网络的区域——更简单地说,这些是图像中帮助网络识别类别的区域(在上面的案例中不是很有帮助,因为损失是最高的)。关于这方面的更多信息,本文给出了一个很好的演示。

一个突出的事实是,当它被输入到模型中时,大多数图像被裁剪成正方形( n x n 像素)。这是因为目前,GPU 输入只能是正方形图像。对于我们的用例来说,这是一个潜在的警告,因为帮助识别飞机的主要组件之一是它的鼻子,它在大多数图像中被裁剪掉,因此我们的模型没有足够的信息来学习。

为了克服这一点,现在让我们把我们的图像挤压成正方形,而不是裁剪它们。可以把它想象成从图像的两边施加压力,使它看起来有点扭曲,但保留了图像的组成部分,而没有裁剪它。为此,我们对我们的ImageDataBunch.from_folder()函数做了一点小小的改变。最初,我们将size参数设置为值 450,这意味着图像将被裁剪为450 x 450图像。让我们对该参数进行如下修改:

我们现在已经将size 的值从450改为**(450,450)**。这种变化虽然不明显,但会将图像压缩到上述相同的尺寸:

data_squished.show_batch(rows=3, figsize=(7,8))

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Images loaded with size = (450,450), with images squished but the aircraft noses are retained

这里的区别是显而易见的,与我们最初加载的图像相比,图像较宽的一端(大多数情况下,鼻子)被剪掉了:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Images loaded at the beginning of the post (size = 450), thus cropping the noses

现在让我们通过用新图像重新训练模型来创建另一个学习者:

learn2 = cnn_learner(data_squished, 
                     models.resnet50,       
                     metrics=error_rate)

现在让我们用 4 个时期来拟合我们的模型(一个时期意味着我们的模型扫描我们的数据一次——时期的数量越多,它在每次扫描中学习的就越多)

learn2.fit_one_cycle(4)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这个结果是 21%的错误率,比我们之前 32%的错误率有了相当大的改善。现在,让我们尝试通过微调来改进我们的模型:

让我们暂时保存模型(权重):

learn2.save('aircraft_classification_stg1')

深度学习模型中最重要的参数之一是学习速率。选择正确的学习率很重要,我们可以使用一个漂亮的函数— lr_finder()来找到一个非常好的学习率,供我们的模型学习,而不是随机猜测或多次试错。这个函数是 Leslie Smith 的论文中关于调整神经网络超参数的一个实现,所以读一下吧。

在我们运行lr_find()之前,我们可以解冻整个网络。我发现在运行lr_find()之前解冻网络能让我得到更好的结果。unfreeze()使我们能够更新整个网络的权重。理想情况下,我们希望而不是大幅度更新早期层的权重,但是小的变化(由低学习率定义)以及随着我们在各层之间移动而逐渐增加学习率可能会导致更好的结果。

learn2.unfreeze()
learn2.lr_find()

lr_find()本质上是用线性递增的学习率来训练模型,学习率通常在 10e-7 到 1 之间。运行后,我们绘制了损失与学习率的关系图,如下所示:

learn2.recorder.plot()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们可以选择我们的学习速率,使它低于损失开始显著上升的速率。在上图中,1e-4 似乎是最后一层组的合理学习速率。

我们可以通过选择学习率的范围来将学习率分布在网络的各层,其中最大学习率将是 1e-4(来自上图),最小学习率(将应用于第一学习组)可以是最大学习率的十分之一,在这种情况下将是 1e-5。

为了训练整个网络,我们首先需要 解冻 网络——这是我们在运行lr_find()之前做的事情,所以我们不必再做一遍。

现在让我们用 8 个时期来拟合我们的模型的一个周期——阅读更多关于fit_one_cycle的内容,这是一篇关于这个主题的很棒的文章。

learn2.fit_one_cycle(8, max_lr=slice(1e-5,1e-4))

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

通过以上步骤,我们已经将错误率降低到了约 4% —不错!我们最初的错误率是 32%,这是一个很大的进步!

现在让我们看看我们的混淆矩阵,看看我们的模型在哪里给出了错误的预测:

interp = ClassificationInterpretation.from_learner(learn2)
interp.plot_confusion_matrix()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

从混淆矩阵来看,看起来模型预测飞机是波音 787,而实际上它是另一个模型。让我们看看损失最大的例子:

interp.plot_top_losses(10, figsize = (20,20))

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们可以让我们的模型通过一些预测——例如,第四张图片只是一个引擎,我不认为我给模型提供了足够的放大引擎图像来准确区分飞机引擎。第七张图片是飞机前部的放大图,公平地说,这很难区分不同的飞机,特别是对于一个我们没有调整太多的模型。上图中的热图显示了图像的激活层。

结论

在没有对我们的模型进行深入调整的情况下,我们能够获得接近 97%的准确率。我们可以做大量的实验来进一步了解是否可以提高精度,例如增加历元的数量、多次运行单个历元周期、更多的数据扩充技术等。这篇文章的目的是说明 fastai 库的易用性和速度,以及它只需很少的调整就可以实现的最先进的结果,以及迁移学习在开发最先进的图像识别模型方面令人难以置信的能力。fast.ai 的人们正在不断开发这个库,它将激励人们更多地了解人工智能及其在建设更美好世界中的非凡用例。

这个项目的代码可以在我的 Github 档案中找到

卷积神经网络导论

原文:https://towardsdatascience.com/an-introduction-to-convolutional-neural-networks-bdf692352c7?source=collection_archive---------10-----------------------

一个简单的指南,介绍什么是 CNN,它们如何工作,以及如何用 Python 从头开始构建一个 CNN。

在过去的几年里,关于卷积神经网络(CNN)有很多讨论,特别是因为它们如何彻底改变了计算机视觉领域。在这篇文章中,我们将基于神经网络的基本背景知识和探索什么是 CNN,了解它们如何工作,并从头开始用 Python 构建一个真实的 CNNs】(仅使用 numpy )。

这篇文章假设只有神经网络的基础知识。我的神经网络介绍涵盖了你需要知道的一切,所以你可能想先读一下。

准备好了吗?让我们跳进来。

这篇文章的格式在 victorzhou.com 的原帖中看起来最好。

1.动机

CNN 的一个经典用例是执行图像分类,例如,查看宠物的图像并判断它是猫还是狗。这是一个看似简单的任务— 为什么不用普通的神经网络呢?

好问题。

原因 1:图像很大

现在用于计算机视觉问题的图像通常是 224x224 或更大。想象一下,构建一个神经网络来处理 224x224 彩色图像:包括图像中的 3 个颜色通道(RGB ),得出 224 x 224 x 3 = 150,528 输入特征!在这样的网络中,一个典型的隐藏层可能有 1024 个节点,因此我们必须为第一层训练 150,528 x 1024 =1.5 亿个以上的权重。我们的网络将会非常庞大,几乎无法训练。

我们也不需要那么多重量。图像的好处是我们知道像素在它们的邻居的上下文中最有用。图像中的物体由小的局部特征组成,比如眼睛的圆形虹膜或者一张纸的方形角。第一个隐藏层的每一个节点都要看每一个像素是不是显得很浪费?

原因 2:立场可以改变

如果你训练一个网络来检测狗,你会希望它能够检测一只狗*,不管它出现在图像*的什么地方。想象一下,训练一个对某个狗图像工作良好的网络,然后给它输入同一图像的稍微偏移的版本。狗不会激活同样的神经元,所以网络会做出完全不同的反应!

我们很快就会看到 CNN 如何帮助我们缓解这些问题。

2.资料组

在本帖中,我们将解决“你好,世界!”计算机视觉的: MNIST 手写数字分类问题。很简单:给定一个图像,将其归类为一个数字。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

MNIST 数据集中的每幅图像都是 28x28,包含一个居中的灰度数字。

说实话,一个普通的神经网络实际上可以很好地解决这个问题。您可以将每个图像视为一个 28 x 28 = 784 维的向量,将其输入到一个 784 维的输入层,堆叠几个隐藏层,最后得到一个包含 10 个节点的输出层,每个节点对应一个数字。

这只会起作用,因为 MNIST 数据集包含以为中心图像,所以我们不会遇到前面提到的大小或移动的问题。然而,在这篇文章的整个过程中请记住,大多数现实世界的图像分类问题并不容易。

足够的积累。让我们进入 CNN!

3.回旋

什么是卷积神经网络?

它们基本上只是使用卷积层的神经网络,也称为 Conv 层,基于卷积的数学运算。Conv 图层由一组滤镜组成,你可以把它们想象成 2d 数字矩阵。这是一个 3x3 滤波器的例子:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

A 3x3 filter

我们可以使用输入图像和滤波器,通过将滤波器与输入图像卷积来产生输出图像。这包括

  1. 将滤镜覆盖在图像顶部的某个位置。
  2. 在滤波器中的值和它们在图像中的相应值之间执行逐元素乘法
  3. 对所有元素的乘积求和。该总和是输出图像中目标像素的输出值。
  4. 对所有位置重复。

边注:我们(以及许多 CNN 实现)在技术上实际上使用 互相关 来代替这里的卷积,但它们做的几乎是同样的事情。我不会在这篇文章中深入讨论这种差异,因为它并不重要,但是如果你好奇的话,可以随意查看。

这个 4 步描述有点抽象,所以让我们来做一个例子。考虑一下这个小小的 4x4 灰度图像和这个 3x3 滤镜:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

A 4x4 image (left) and a 3x3 filter (right)

图像中的数字代表像素强度,其中 0 代表黑色,255 代表白色。我们将卷积输入图像和滤波器,以产生 2x2 输出图像:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

A 2x2 output image

首先,让我们在图像的左上角覆盖我们的过滤器:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Step 1: Overlay the filter (right) on top of the image (left)

接下来,我们在重叠的图像值和滤波器值之间执行逐元素乘法。以下是结果,从左上角开始,向右,然后向下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Step 2: Performing element-wise multiplication.

接下来,我们总结所有的结果。这很简单:62–33 =29

最后,我们将结果放在输出图像的目标像素中。因为我们的过滤器覆盖在输入图像的左上角,所以我们的目标像素是输出图像的左上角像素:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们做同样的事情来生成输出图像的其余部分:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

3.1 这有什么用?

让我们缩小一下,从更高的层面来看这个问题。用滤波器卷积图像有什么作用?我们可以从我们一直使用的示例 3x3 滤波器开始,它通常被称为垂直 Sobel 滤波器:

下面是垂直索贝尔滤波器的一个例子:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

An image convolved with the vertical Sobel filter

类似地,还有一个水平 Sobel 滤波器:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

An image convolved with the horizontal Sobel filter

看到发生了什么吗?索贝尔滤波器是边缘检测器。垂直 Sobel 滤波器检测垂直边缘,水平 Sobel 滤波器检测水平边缘。输出图像现在很容易解释:输出图像中的亮像素(具有高值的像素)表示原始图像中有很强的边缘。

你能看出为什么边缘检测图像可能比原始图像更有用吗?回想一下我们的 MNIST 手写数字分类问题。例如,在 MNIST 上训练的 CNN 可能通过使用边缘检测过滤器并检查图像中心附近的两个突出的垂直边缘来寻找数字 1。一般来说,卷积帮助我们寻找特定的局部图像特征(如边缘),我们可以在网络中稍后使用。

3.2 填充

还记得之前用 3×3 滤波器卷积 4×4 输入图像以产生 2×2 输出图像吗?很多时候,我们更希望输出图像和输入图像大小相同。为此,我们在图像周围添加零,这样我们可以在更多的地方覆盖过滤器。3x3 滤镜需要 1 个像素的填充:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

A 4x4 input convolved with a 3x3 filter to produce a 4x4 output using same padding

这被称为**“相同”填充**,因为输入和输出具有相同的尺寸。不使用任何填充,这是我们在这篇文章中一直在做并将继续做的,有时被称为**“有效”填充**。

3.3 Conv 层

现在我们知道了图像卷积的工作原理以及它为什么有用,让我们看看它在 CNN 中的实际应用。如前所述,CNN 包括 conv 层,它使用一组过滤器将输入图像转换为输出图像。conv 层的主要参数是它拥有的滤镜数量。

对于我们的 MNIST CNN,我们将使用一个带有 8 个过滤器的小 conv 层作为我们网络的初始层。这意味着它会将 28x28 的输入图像转换成 26x26x8 的输出音量:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

提醒:输出是 26x26x8,而不是 28x28x8,因为我们使用了 有效填充 ,将输入的宽度和高度减少了 2。

conv 层中的 8 个过滤器中的每一个都产生 26x26 的输出,所以堆叠在一起它们构成了 26x26x8 的体积。这一切的发生都是因为 3 x 3(滤镜大小)x 8(滤镜数量)= 只有 72 个权重

3.4 实现卷积

是时候将我们所学的内容转化为代码了!我们将实现一个 conv 层的前馈部分,它负责将滤波器与输入图像进行卷积,以产生输出体积。为简单起见,我们假设滤波器始终为 3x3(这是不正确的,5x5 和 7x7 滤波器也很常见)。

让我们开始实现一个 conv 图层类:

Conv3x3类只有一个参数:过滤器的数量。在构造函数中,我们存储过滤器的数量,并使用 NumPy 的 randn() 方法初始化一个随机过滤器数组。

注意:在初始化期间潜水 9 比你想象的更重要。如果初始值太大或太小,训练网络将无效。要了解更多信息,请阅读关于 Xavier 初始化

接下来,实际卷积:

iterate_regions()是一个助手生成器方法,为我们生成所有有效的 3x3 图像区域。这将有助于稍后实现该类的向后部分。

第 26 行实际上执行卷积。让我们来分解一下:

  • 我们有im_region,一个包含相关图像区域的 3x3 数组。
  • 我们有self.filters,一个三维阵列。
  • 我们做到了,它使用 numpy 的广播特性对两个数组进行元素相乘。结果是一个与self.filters维度相同的 3d 数组。
  • 我们 np.sum() 使用上一步的结果,产生一个长度为num_filters的 1d 数组,其中每个元素包含相应滤波器的卷积结果。

对输出中的每个像素执行上述序列,直到我们获得最终的输出量!让我们测试一下我们的代码:

目前看来不错。

注意:在我们的 *Conv3x3* 实现中,为了简单起见,我们假设输入是一个2dnumpy 数组,因为我们的 MNIST 图像就是这样存储的。这对我们有用,因为我们把它作为网络的第一层,但是大多数 CNN 有更多的 Conv 层。如果我们要构建一个需要多次使用 *Conv3x3* 的更大的网络,我们必须让输入成为一个3dnumpy 数组。

4.联营

图像中的相邻像素往往具有相似的值,因此 conv 图层通常也会为输出中的相邻像素产生相似的值。因此,conv 层输出中包含的大部分信息都是冗余的。例如,如果我们使用边缘检测滤波器,并在某个位置找到一个强边缘,那么我们也有可能在与原始位置偏移 1 个像素的位置找到相对强的边缘。不过,这些都是一样的边缘!我们没有发现任何新东西。

池层解决了这个问题。它们所做的只是通过(你猜对了)值汇集到输入中来减小输入的大小。池化通常通过简单的操作来完成,如maxminaverage。这是一个最大池层的示例,池大小为 2:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Max Pooling (pool size 2) on a 4x4 image to produce a 2x2 output

为了执行 max 池,我们以 2x2 块遍历输入图像(因为池大小= 2)并将 max 值放入输出图像的相应像素。就是这样!

池化将输入的宽度和高度除以池大小。对于我们的 MNIST CNN,我们将在最初的 conv 图层后放置一个池大小为 2 的最大池图层。池层将 26x26x8 的输入转换为 13x13x8 的输出:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

4.1 实施联营

我们将实现一个MaxPool2类,方法与上一节中的 conv 类相同:

这个类的工作方式类似于我们之前实现的Conv3x3类。关键的一行是第 30 行:为了从给定的图像区域中找到最大值,我们使用了 np.amax() ,numpy 的 array max 方法。我们设置它是因为我们只想最大化前两个维度,高度和宽度,而不是第三个维度num_filters

来测试一下吧!

我们的 MNIST CNN 开始团结起来了!

5.Softmax

为了完善我们的 CNN,我们需要赋予它实际预测的能力。我们将通过使用多类分类问题的标准最终层来做到这一点:Softmax 层,一个使用 Softmax 函数激活的全连接(密集)层。

提醒:全连接层的每个节点都连接到前一层的每个输出。如果你需要复习,我们在我的 神经网络介绍 中使用了全连接层。

如果你之前没有听说过 Softmax,那么在继续之前,请阅读我的soft max快速介绍。

5.1 用法

我们将使用一个有 **10 个节点的 softmax 层,每个节点代表一个数字,**作为 CNN 的最后一层。图层中的每个节点都将连接到每个输入。应用 softmax 变换后,概率最高的节点代表的数字将是 CNN 的输出!

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

5.2 交叉熵损失

你可能会对自己说,为什么要费心将输出转换成概率呢?产值最高的不会一直概率最高吗?如果你做了,那你就完全正确。我们实际上不需要使用 softmax 来预测一个数字——我们可以从网络中选择输出最高的数字!

softmax 真正做的是帮助我们量化我们对自己预测的确信程度,这在训练和评估我们的 CNN 时很有用。更具体地说,使用 softmax 让我们使用交叉熵损失,它考虑了我们对每个预测的确信程度。我们是这样计算交叉熵损失的:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

其中 c 是正确的类别(在我们的例子中是正确的数字), pc 是类别 c 的预测概率, ln自然对数。一如既往,损失越低越好。例如,在最好的情况下,我们会

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在更现实的情况下,我们可能会

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在这篇文章的后面,我们将再次看到交叉熵损失,所以请记住这一点!

5.3 实施 Softmax

现在你已经知道该怎么做了——让我们实现一个Softmax层类:

这里没什么太复杂的。几个亮点:

  • 我们 flatten() 输入使其更容易处理,因为我们不再需要它的形状。
  • np.dot()inputself.weights逐元素相乘,然后对结果求和。
  • np.exp() 计算用于 Softmax 的指数。

我们现在已经完成了 CNN 的整个转发过程!综合起来看:

运行cnn.py会产生类似于下面的输出:

MNIST CNN initialized!
[Step 100] Past 100 steps: Average Loss 2.302 | Accuracy: 11%
[Step 200] Past 100 steps: Average Loss 2.302 | Accuracy: 8%
[Step 300] Past 100 steps: Average Loss 2.302 | Accuracy: 3%
[Step 400] Past 100 steps: Average Loss 2.302 | Accuracy: 12%

这是有道理的:通过随机权重初始化,你会认为 CNN 只是随机猜测。随机猜测将产生 10%的准确度(因为有 10 个类别)和交叉熵损失 ln(0.1)=2.302,这就是我们得到的结果!

想自己尝试或修改这段代码吗? 在浏览器中运行本 CNN**。**在 Github 上也有。

6.结论

CNN 的介绍到此结束!在本帖中,我们

  • 为什么 CNN 可能对某些问题更有用,比如图像分类。
  • 介绍了 MNIST 手写数字数据集。
  • 了解了 Conv 图层,它将滤镜与图像进行卷积,以产生更有用的输出。
  • 谈到了池层,它可以帮助修剪一切,但最有用的功能。
  • 实现了一个 Softmax 层,这样我们就可以使用交叉熵损失

还有很多我们还没有涉及的,比如如何实际训练一个 CNN。我的下一篇文章将深入训练 CNN ,包括导出渐变和实现反向投影,敬请关注!

如果你渴望看到一个训练有素的 CNN 在工作:这个例子 Keras CNN 在 MNIST 训练达到 99.25% 的准确率。CNN 很厉害!

原载于https://victorzhou.com

卷积神经网络导论

原文:https://towardsdatascience.com/an-introduction-to-convolutional-neural-networks-eb0b60b58fd7?source=collection_archive---------0-----------------------

描述什么是卷积神经网络,它们如何工作,如何使用,以及为什么它们如此强大

卷积神经网络(CNN)是一种具有一个或多个卷积层的神经网络,主要用于图像处理、分类、分割以及其他自相关数据。

卷积本质上是在输入上滑动滤波器。考虑卷积的一个有用的方法是引用 Prasad Samarakoon 博士的话:“卷积可以被认为是“观察一个函数的周围环境,以更好/准确地预测其结果”。"

与其一次查看整个图像来寻找某些特征,不如查看图像的较小部分会更有效。

CNN 的常见用途

CNN 最常见的用途是图像分类,例如识别包含道路的卫星图像或对手写字母和数字进行分类。还有其他相当主流的任务,如图像分割和信号处理,CNN 在这些方面表现良好。

CNN 已经被用于自然语言处理(NLP)和语音识别中的理解,尽管对于 NLP 经常使用递归神经网络(RNNs)。

CNN 也可以被实现为 U-Net 架构,其本质上是两个几乎镜像的 CNN,导致 CNN 的架构可以呈现为 U 形。u-net 用于输出需要与输入大小相似的场合,例如分割和图像改善。

除了图像处理,CNN 还有其他有趣的用途

CNN 架构越来越多不同且有趣的用途正在被发现。非图像应用的一个例子是 Lex Flagel 等人的“卷积神经网络在群体遗传推断中的不合理有效性”。这用于执行选择性扫描,寻找基因流,推断群体大小变化,推断重组率。

有一些研究人员,比如 T2 量子生物学实验室的 Gerald Quon 教授,使用 CNN 作为单细胞基因组学的生殖模型来识别疾病。

CNN 也在天体物理学中被用于解释射电望远镜数据,以预测代表数据的可能的视觉图像。

Deepmind 的 WaveNet 是一个用于生成合成语音的 CNN 模型,用作谷歌助手的语音合成器的基础。

卷积核

每个卷积层包含一系列称为卷积核的滤波器。过滤器是一个整数矩阵,用于输入像素值的子集,大小与内核相同。每个像素乘以内核中的相应值,然后将结果相加得到单个值,为简单起见,在输出通道/特征图中表示网格单元,如像素。

这些是线性变换,每个卷积都是一种仿射函数。

在计算机视觉中,输入通常是 3 通道 RGB 图像。为简单起见,如果我们取一个具有一个通道(二维矩阵)和一个 3×3 卷积核(二维矩阵)的灰度图像。内核遍历输入的数字矩阵,逐列水平移动,滑动/扫描包含图像像素值的矩阵的第一行。然后内核垂直向下移动到后续行。注意,过滤器可以一次跨越一个或几个像素,这将在下面进一步详述。

在其他非视觉应用中,一维卷积可以在输入矩阵上垂直滑动。

从卷积核创建特征图

下图显示了卷积核的操作。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

A stride one 3x3 convolutional kernel acting on a 8x8 input image, outputting an 8x8 filter/channel. Source: https://www.researchgate.net/figure/a-Illustration-of-the-operation-principle-of-the-convolution-kernel-convolutional-layer_fig2_309487032

下面是一个精彩演示的可视化,展示了内核扫描输入矩阵中的值。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Kernel scanning over the values in the input matrix. Source: Otavio Good: excerpt https://www.youtube.com/watch?v=f0t-OCG79-U from https://www.youtube.com/watch?v=Oqm9vsf_hvU

填料

为了处理边缘像素,有几种方法:

  • 丢失边缘像素
  • 用零值像素填充
  • 反射填充

反射填充是目前最好的方法,卷积核处理边缘像素所需的像素数被添加到外部,从图像边缘复制像素。对于 3x3 内核,需要在外部周围添加一个像素,对于 7x7 内核,则需要在外部周围反射三个像素。每条边周围添加的像素是尺寸,减半并向下取整。

传统上,在许多研究论文中,边缘像素被忽略,这丢失了一小部分数据,并且如果有许多深卷积层,这变得更糟。出于这个原因,我无法找到现有的图表来轻松传达这里的一些要点,而不会误导和混淆步幅 1 卷积和步幅 2 卷积。

使用填充时,宽度为 w、高度为 h 的输入的输出将为宽度为 w、高度为 h(与使用单个输入通道的输入相同),假设内核一次跨越一个像素。

使用多个内核创建多个通道/特征图

当在一个卷积层中应用多个卷积核时,会创建许多通道/特征图,每个卷积核一个。下图显示了正在创建的通道/特征地图。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Visualisation of channels/feature maps created from a layer of convolutional kernels. Source: Otavio Good: excerpt https://www.youtube.com/watch?v=f0t-OCG79-U from https://www.youtube.com/watch?v=Oqm9vsf_hvU

RGB 3 通道输入

大多数图像处理需要对具有三个通道的 RGB 图像进行操作。RGB 图像是数字的三维阵列,也称为秩三张量。

当处理三通道 RGB 图像时,通常会使用一个卷积核,它是一个三维数组/秩为 3 的数字张量。卷积核的大小通常为 3x3x 3——卷积核就像一个立方体。

通常至少有三个卷积核,以便每个卷积核可以充当不同的滤波器,以从每个颜色通道获得洞察力。

卷积核作为一个组构成一个四维阵列,也称为秩 4 张量。当维度高于三个维度时,即使不是不可能,也是很难想象的。在这种情况下,把它想象成一个三维立方体的列表。

过滤器以同样的方式在输入数据中移动,滑动或大步跨过行,然后向下移动列并大步跨过行,直到到达右下角:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

3x3x3 convolutional kernel acting on a 3 channel input. Source: https://machinethink.net/images/vggnet-convolutional-neural-network-iphone/ConvolutionKernel@2x.png

在填充和步长为 1 的情况下,来自宽度 x、高度 y 和深度 3 的输入的输出将是宽度 x、高度 y 和深度 1,因为立方体从每个步长产生单个求和输出值。例如,对于 3×64×64 的输入(例如 64×64 的 RGB 三通道图像),则一个内核以 1 为步长填充边缘像素,将输出 64×64 的通道/特征图(一个通道)。

值得注意的是,输入通常是标准化的,这将在下面进一步详述。

大步

通常使用跨距 2 卷积而不是跨距 1 卷积,其中卷积核一次跨越 2 个像素,例如我们的 3×3 核将从位置(1,1)开始,然后跨距到(1,3),然后到 1,5)等等,与跨距为 1 的卷积核相比,输出通道/特征图的大小减半。

使用填充,来自宽度为 w、高度为 h、深度为 3 的输入的输出将是宽度为 w/2、高度为 h/2、深度为 1 的上限,因为内核从每个步幅输出单个求和输出。

例如,对于 3×64×64 的输入(例如 64×64 的 RGB 三通道图像),一个内核采取两个步长并填充边缘像素,将产生 32×32 的通道/特征图。

许多内核

在 CNN 模型中,通常有三个以上的卷积核,一个卷积层中有 16 个甚至 64 个核是常见的。

这些不同的卷积核各自充当不同的滤波器,创建代表不同事物的通道/特征图。例如,内核可以过滤顶部边缘、底部边缘、对角线等等。在更深层次的网络中,这些内核可以过滤动物的特征,如眼睛或鸟的翅膀。

卷积核的数量越多,通道/特征图的数量就越多,数据量也越大,这就需要更多的内存。根据上述示例,步长 2 卷积有助于减少内存使用,因为步长 2 卷积的输出通道的宽度和高度是输入通道的一半。这假设使用了反射填充,否则它可能会稍微小一些。

stride 2 的几个卷积层的示例

对于具有三个通道和 16 个 3x3x3 内核的 64 像素方形输入,我们的卷积层将具有:

输入:64×64×3
卷积核:16×3×3×3(四维张量)
卷积核的输出/激活:16×32×32(16 个通道/32×32 的特征图)

网络然后可以应用批量标准化来减少学习时间和减少过度拟合,更多细节如下。此外,通常应用诸如 RELU 的非线性激活函数,以允许网络更好地逼近,下面有更多细节。

通常有几层 stride 2 卷积,创建越来越多的通道/特征图。以上一层的例子为例:

输入 : 16x32x32
卷积核 : 64x3x3x3
卷积核的输出/激活 : 64x16x16 (64 通道 16x16 的特征图)

然后,在应用 ReLU 和批量标准化(见下文)之后,应用另一个跨距 2 卷积:

输入:64×16×16
卷积核:128×3×3×3
卷积核的输出/激活:128×8×8(8×8 的 128 通道/特征图)。

分类

例如,如果一幅图像属于 42 个类别中的一个,并且网络的目标是预测该图像属于哪个类别。

根据上述输出为 128×8×8 的例子,首先取秩 3 张量的平均池。平均池是每个通道的平均,在这个例子中,每个 8×8 矩阵被平均成一个数字,具有 128 个通道/特征图。这创建了 128 个数字,一个大小为 1x128 的向量。

下一层是 128×42 权重的矩阵或秩 2 张量。输入的 1×128 矩阵乘以 128×42 矩阵(点积),产生 1×42 向量。42 个网格单元/向量元素中的每一个的激活程度是预测与该向量元素所代表的分类的匹配程度。Softmax 作为激活函数应用,然后 argmax 选择元素最高值。

整流线性单元

整流线性单元被用作非线性激活函数。一个 ReLU 表示如果值小于零,就向上舍入到零。

标准化

标准化是减去平均值并除以标准差的过程。它将数据的范围转换为-1 和 1 之间,使数据使用相同的比例,有时称为最小-最大比例。

通常对输入特征进行归一化,通过移除平均值和缩放至单位方差来标准化数据。输入要素以零为中心并且具有相同数量级的方差通常很重要。

对于一些数据,如图像,数据被缩放,使其范围在 0 和 1 之间,最简单的是将像素值除以 255。

这也允许训练过程更快地找到最佳参数。

批量标准化

批量规格化的好处在于,有助于使网络输出更稳定的预测,通过规格化减少过度拟合,并将训练速度提高一个数量级。

批次标准化是在当前批次的范围激活层内进行标准化的过程,减去批次激活的平均值并除以批次激活的标准偏差。

这是必要的,因为即使在标准化输入之后,由于一些激活可能更高,这可能导致后续层行为异常并使网络更不稳定。

由于批量归一化已经缩放并移动了激活输出,下一层中的权重将不再是最优的。随机梯度下降(SGD)将取消标准化,因为它将最小化损失函数。

为了防止这种效应,可以向每层添加两个可训练参数,以允许 SGD 对输出进行反规格化。这些参数是平均参数“β”和标准偏差参数“γ”。批量归一化为每个激活输出设置这两个权重,以允许归一化被反转来获得原始输入,这通过避免必须更新其他权重来避免影响网络的稳定性。

为什么 CNN 如此强大

简单来说,一个足够大的 CNN 可以解决任何可以解决的问题。

在许多不同的图像处理任务中表现出色的著名 CNN 架构有 VGG 模型(K. Simonyan 和 A. Zisserman)、ResNet 模型(明凯何等人)和谷歌盗梦空间模型(克里斯蒂安塞格迪等人)。这些模型有数百万个可训练的参数。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

VGG-16 Network Architecture. Source: https://neurohive.io/wp-content/uploads/2018/11/vgg16-1-e1542731207177.png

通用逼近定理

通用逼近定理本质上陈述了如果一个问题可以被解决,那么它可以通过深度神经网络来解决,给定足够的仿射函数层与非线性函数层。本质上,一堆线性函数后跟非线性函数可以解决任何可以解决的问题。

实际上,在实施中,这可以是许多矩阵乘法,足够大的矩阵后接 RELU,堆叠在一起,这些具有数学属性,能够以任意高的精度求解任意复杂的数学函数,假设您有时间和资源来训练它。

这是否会给神经网络理解是一个有争议的话题,特别是由认知科学家。论点是,无论你对一个问题的语法和语义理解得多好,你永远也不会理解它。这基本上是塞尔的中国房间论点的基础。有些人会说,如果你能很好地逼近问题的解决方案,与理解问题没有区别,这有什么关系吗?

Fastai 课程

我要感谢 Fastai 团队,他们的课程帮助巩固了我的深度学习和 CNN 知识,为进一步学习和理解提供了一个极好的起点。

降维引论

原文:https://towardsdatascience.com/an-introduction-to-dimenstionality-reduction-8c7d1c80737d?source=collection_archive---------10-----------------------

降维如何使您的数据集更易于管理

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

高维数据集是所有数据科学中最大的挑战之一。挑战很简单。机器学习算法要求数据集是密集的,以便做出准确的预测。随着维度越来越多,数据空间变得极其庞大。巨大的数据空间需要极大的数据集来维持密度。这一挑战可能会导致模型预测不准确(例如,我描述了 k-nearest neighbors 算法如何在 k -Nearest Neighbors 和维数灾难中的高维数据空间中变得无用),或者数据集太大,计算机无法合理处理。

幸运的是,数据科学家已经找到了解决这个问题的方法。这叫降维。降维的本质很简单:你搜索数据集,寻找暗示数据集沿着不同于你最初假设的维度运行的趋势,然后你相应地转换你的数据。通过这种方式,您可以减少数据集中的维数。

降维是如何工作的?

降维的工作原理是识别数据集中真正重要的维度。一旦确定了真正重要的维度,您就可以转换数据集,以便沿着这些维度而不是最初显示的维度来表示这些点。

让我们用一个例子来讨论这个问题。在 k-最近邻居和维度的诅咒中,我给出了一个有点半开玩笑的花园侏儒分界线的例子。在这个例子中,假设你正在研究一个城市中花园侏儒的位置,并绘制它们。你首先确定城市中每个花园侏儒的纬度和经度,然后将它们绘制成二维图表。这两个维度是南北向和东西向,以距离城市中心的英里数表示。这是一种非常合理的呈现数据的方式,并且只有两个维度就足够了。

然而,假装你是一个完美主义者,希望用尽可能少的维度来呈现数据。你还会注意到,出于某种奇怪的原因,花园侏儒们从城市的东北角到城市的西南角形成了一条近乎完美的直线。数据集不是花园 gnome 位置的云,而是一条线。注意到这一点,你意识到你可以根据东北-西南方向离市中心的距离来绘制每个花园侏儒的位置。这种表示只需要一维。

下一步是执行转换。你需要沿着新的轴计算每个点离城市中心的距离,并声明你的新数据集。新的距离可以用代数方法计算。完成后,可以绘制出最终的剖面图,以一维方式显示您的数据集。

这个过程是什么样的?

我们将使用前面的花园 Gnome 分界线的例子来完成这个过程。我将使用 pandas 和 numpy 的功能,用 python 来完成所有这些工作。关于如何使用这些工具的详细说明,我强烈推荐阅读 Wes McKinney 的 Python for Data Analysis(韦斯是熊猫的创造者,所以你可以打赌他知道他在说什么。我将使用 python 包 bokeh 生成图。关于这个包的有用介绍可以在用散景进行数据可视化的实践中找到。

我在一个名为 GardenGnomeLocations 的熊猫数据框架中构建了我的数据集。它有一个包含 31 个条目的索引,以及代表每个花园侏儒在南北轴和东西轴上的位置的列。这些列被命名为“南北(mi)”和“东西(mi)”。

图 1 展示了原始数据集,显示了城市中每个花园侏儒沿南北和东西轴的位置。每个圆圈代表一个花园侏儒相对于市中心的位置。请注意数据中呈现的上述趋势;出于某种神秘的原因,花园侏儒的位置是一条从城市东北角到城市西南角的直线。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure 1: Location of Each Garden Gnome in the City Using the North-South and East-West Axes

一旦注意到这种趋势,很明显花园侏儒的位置确实可以用一个单一的维度,一个单一的轴来呈现。我们可以利用这些知识创建一个新的轴,东北-西南轴(或者,我喜欢称之为花园侏儒分界线)。然后,数据可以在一个维度上显示,即沿该轴到市中心的距离。

为了执行这种转换,我们在每个数据点上使用勾股定理。为了计算每个花园侏儒沿新轴到市中心的距离,我们需要使用 for 循环、pandas.loc 函数、math.sqrt 函数和一些代数表达式。计算新距离并将其添加到数据框中的“距离(mi)”列的代码如下:

for i in GardenGnomeLocations.index: GardenGnomeLocations.loc[i, 'Distance (mi)'] =      math.sqrt(GardenGnomeLocations.loc[i, 'NorthSouth (mi)'] ** 2 + GardenGnomeLocations.loc[i, 'EastWest (mi)'] ** 2) if GardenGnomeLocations.loc[i, 'NorthSouth (mi)'] < 0: GardenGnomeLocations.loc[i, 'Distance (mi)'] = -1 * GardenGnomeLocations.loc[i, 'Distance (mi)']

代码块顶部的 for 循环告诉脚本对 GardenGnomeLocations 数据帧中的每一行执行此计算,并使用变量 I 跟踪它在数据帧中的位置。第二行执行实际的计算,并将数据存储在 dataframe 中的适当位置。您会注意到,这个等式归结为 c = sqrt(a + b),这是勾股定理的常见形式。第一个术语 GardenGnomeLocations.loc[i,’ Distance (mi)‘]告诉 python 我们将要计算的值应该放在 GardenGnomeLocations 数据帧中’ Distance (mi)'列的第 I 行。等式的另一边使用“南北(mi)”和“东西(mi)”列中的相应数据来计算结果。请记住,勾股定理只会返回距离的绝对值。为了克服这一点,我们添加了最后两行代码。第一个确定原始数据点的值是正还是负。如果原始值为负,则第二个函数将距离乘以-1,使其为负。

绘制这些数据的结果如图 2 所示。数据看起来非常相似,因为这个图是二维的,但是注意这里的轴。图 2 显示了每个侏儒的位置,而不是用南北轴和东西轴来表示,而是用离市中心的距离来表示。在一维空间。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Figure 2: Location of Each Garden Gnome in the City Using the Distance

这种缩减到一个维度的做法使得数据集更容易使用。需要更少的点来确保数据集足够密集以返回准确的预测。更少的数据点意味着相同质量结果的计算时间减少。一些算法,如 k-最近邻算法,比使用更高的维度更有可能返回有用的结果。

然而,这种转变确实增加了解释数据的难度。最初,数据很容易理解;每个数据点都用我们常用的术语表示花园侏儒的位置。我们可以确定南北距离,东西距离,并简单的使用。现在,我们离市中心有一段距离,但数据并没有明确指出方向。为了理解这些数据,我们必须保留所有先前的数据集和算法。通过这种方式,我们可以在以后将新轴的数据转换回原始轴,这样就可以很容易地理解和使用它。

真的这么简单吗?

不幸的是,没有。事情没那么简单。这是一个过于简化、有些滑稽的例子,旨在演示基本概念。在现实中,没有一个数据集会像这个数据集那样沿着一条完美的直线运行,也不可能简单地使用勾股定理来转换数据。真实的数据集看起来更像隐藏着模糊趋势的数据云,您需要使用一种称为主成分分析的技术来转换数据。这项技术超出了这篇介绍性文章的范围,但是乔尔·格罗出色地演示了如何从零开始在数据科学中实现它。

包装它

高维数据集给数据科学家带来了严峻的挑战。随着维度数量的增加,数据空间也在增加。随着越来越多维度的加入,空间变得异常巨大。这种巨大的空间使得大多数机器学习算法很难发挥作用,因为数据集中的差距呈现出模型无法匹配的区域。一些算法,如k-最近邻算法,特别敏感,因为它们要求数据点在每个维度的T5 接近,这在有多个维度时变得非常罕见。

维度问题的明显解决方案是更大的数据集。这可以用来保持数据密度;然而,非常大的数据空间需要非常大的数据集。这些数据集可能会变得太大,超过计算机执行必要计算的能力。在这种情况下,解决方案是应用降维。

降维是指注意到数据点与最初使用的数据点沿不同的轴对齐,并转换数据集以沿这些轴呈现它们。我们用遍布整个城市的花园侏儒的例子来证明这一点。最初,它们被绘制在直观的南北轴和东西轴上。然而,在检查了这些数据后,很明显它们是沿着一条从城市东北角到西南角的独立轴线排列的。翻译数据集相应地将数据集从一维减少到二维。虽然这是一个小例子,但原理可以应用于更大的数据集。

数据科学家的离散化技术介绍

原文:https://towardsdatascience.com/an-introduction-to-discretization-in-data-science-55ef8c9775a2?source=collection_archive---------5-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by Kevin Ku from Pexels

特征工程:要学习的 4 种离散化技术。

离散化是我们将连续变量、模型或函数转换成离散形式的过程。我们通过创建一组连续的区间(或箱)来做到这一点,这些区间跨越了我们期望的变量/模型/函数的范围。

连续数据 测得的, 离散数据**是算出的。

|| I ||为什么离散化很重要

有连续数据的数学问题有无穷多个自由度。由于我们的计算不可能永远进行下去,所以这样的问题必然要求有限的自由度。出于多种原因,数据科学家需要使用离散化。Kaggle 上的许多顶级贡献使用离散化,原因如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by Ryoji Iwata on Unsplash

符合问题陈述

通常,将连续数据(如体重)划分并存储到有意义的类别或组中会更容易理解。比如我们可以把一个连续变量,体重,分成以下几组来存储:
100 磅以下 (轻),140–160 磅之间 (中),200 磅以上 (重)

如果我们看不到属于同一权重类别的变量之间的客观差异,我们将认为该结构是有用的。
在我们的例子中,85 磅
和 56 磅的重量传达了相同的信息(物体很轻)。因此,如果数据符合问题陈述,离散化有助于使我们的数据更容易理解。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by William Daigneault on Unsplash

解释特征

由于具有无限的自由度,连续特征与目标变量关联的机会较小,并且可能具有复杂的非线性关系。因此,可能更难解释这样的函数。在离散化变量之后,可以解释对应于目标的组。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by Franck V. on Unsplash

与模型/方法不兼容

某些模型可能与连续数据不兼容,例如,替代决策树模型(如随机森林模型)不适合连续特征。

特征工程方法,例如任何基于熵的方法可能无法处理连续数据,因此我们将离散化变量以处理不同的模型和方法。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by Mariano Werneck on Unsplash

信噪比

当我们离散化一个模型时,我们将它拟合到箱中,并减少数据中小波动的影响。通常,我们会将微小的波动视为噪声。我们可以通过离散化来减少这种噪声。这是“平滑”的过程,其中每个箱平滑波动,从而减少数据中的噪声。

|| II ||离散化方法

  • 无监督:
    —等宽
    —等频
    — K 均值
  • 监督:
    —决策树

|| III ||等宽离散化

将所有可能的值分成“ N 个仓,每个仓具有相同的宽度。间隔宽度的公式:

*Width =(最大值-最小值)/ N 其中 N 是仓或区间的数量。

在 python 上,您可能希望导入以下内容进行离散化:

*from sklearn.preprocessing import KBinsDiscretizer
from feature_engine.discretisers import EqualWidthDiscretiser*

按照以下方式设置等宽离散化器:

*discretizer = EqualWidthDiscretiser(bins=10, variables = ['var1', 'var2'])#OR discretizer = KBinsDiscretizer(n_bins=10, encode='ordinal', strategy='uniform')*
  • 相等的宽度不会改善值的分布
  • 它可以处理异常值
  • 可以与分类编码结合使用

|| IV ||等频离散化

将所有可能的值分成数量为“ N 的箱,每个箱具有相同数量的观察值。区间可以对应于分位数值。

在 python 上,您可能希望导入以下内容进行离散化:

*from sklearn.preprocessing import KBinsDiscretizer
from feature_engine.discretisers import EqualFrequencyDiscretiser*

按照以下方式设置等频离散化器:

*discretizer = KBinsDiscretizer(n_bins=10, encode='ordinal', strategy='quantile')#OR discretizer = EqualFrequencyDiscretiser(q=10, variables = ['var1', 'var2'])*
  • 相等的频率确实提高了值的分布
  • 它可以处理异常值
  • 可以与分类编码结合使用

| | V | | K-均值离散化

我们将 K 均值聚类应用于连续变量,从而将其划分为离散的组或聚类。

在 python 上,您可能希望导入以下内容以使用 K-means 进行离散化:

*from sklearn.preprocessing import KBinsDiscretizer*

按照以下方式设置 K 均值离散化器:

*discretizer = KBinsDiscretizer(n_bins=5, encode='ordinal', strategy='kmeans')*
  • K-Means 并不能提高价值传播
  • 它可以处理异常值,但是可能存在质心偏差。
  • 可以与分类编码结合使用

|| VI ||决策树离散化

我们使用决策树来确定箱的最佳数量。当模型做出决定时,它为每个节点分配一个观察值。然后,这些观察结果被分类为变量的离散输出。

在 python 上,您可能希望导入以下内容以使用决策树进行离散化:

*from sklearn.model_selection import train_test_split
from feature_engine.discretisers import DecisionTreeDiscretiser*

您的离散化器应按以下方式设置:

*# cross-validation number (cv)
# how to evaluate model performance (scoring)
# the variables we want to discretise (variables)
# whether it is a target for regression or classification
# and the grid with the parameters we want to testtreeDisc = DecisionTreeDiscretiser(cv=10, scoring='accuracy',
                                   variables=['var1', 'var2'],
                                   regression=False,
                                   param_grid={'max_depth': [1,2,3],
'min_samples_leaf':[10,4]})*
  • 决策树不能提高价值分布
  • 它可以很好地处理异常值,因为树对于异常值是健壮的。
  • 创建单调的关系

|| VII ||下一步

离散化变量后,您可以执行以下任一操作:

  • 构建决策树算法并直接使用离散化的输出作为箱的数量。决策树可以发现离散化变量和目标变量之间的非线性关系。
  • 使用线性模型,而箱与目标变量没有线性关系。通过将箱子视为具有某种编码的类别来改进模型。

感谢你的阅读!

关注我,了解更多关于数据科学的内容。

梯度下降导论

原文:https://towardsdatascience.com/an-introduction-to-gradient-descent-c9cca5739307?source=collection_archive---------6-----------------------

机器学习和深度学习之旅

从理论到实践,在数据集上实现批量梯度下降、小批量梯度下降和随机梯度下降

本博客将涵盖以下问题和主题:

1.什么是渐变?

2.什么是梯度下降?

3.三种常见的梯度下降

4.用 Python 实现

1。梯度

梯度是一个向量,它与一个函数相切,并指向该函数最大增长的方向。梯度在局部最大值或最小值处为零,因为没有单一的增加方向。在数学中,梯度被定义为函数的每个输入变量的偏导数。例如,我们有一个函数:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

函数的图形如下所示,我们可以看到函数的最小值是(0,0)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在这种情况下,梯度的 x 分量是相对于 x 的偏导数,梯度的 y 分量是相对于 y 的偏导数。上述函数的梯度为:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

如果我们想找到在点(1,2)处增加函数最多的方向,我们可以将(1,2)代入上面的公式,得到:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

2。梯度下降

由于梯度是指向函数最大增量的向量,负梯度是指向函数最大减量的向量。因此,我们可以通过向负梯度方向迭代移动一点来最小化一个函数。这就是梯度下降的逻辑。

给定一个起点:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们可以构建一个迭代过程:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

上式中的参数α被称为学习率,它在大多数情况下是一个小常数,范围从 0 到 1。迭代过程不会停止,直到它收敛。以前面的例子为例,我们已经知道梯度是:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

因此,梯度下降的迭代过程可以写成:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

那么我们可以得到:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

最后,假设α小于 1,那么我们可以得到:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

结论与我们在上图中观察到的一样。

解释梯度下降的另一种直观方式是在函数的上下文中考虑下面的三维图形。我们的目标是从右上角的山移动到左下角的深蓝色的海。箭头代表从任何给定点开始的最陡下降方向(负梯度)——尽可能快地降低函数的方向。”[3]

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image Source: https://ml-cheatsheet.readthedocs.io/en/latest/gradient_descent.html

在机器学习中,我们更关注代价函数和参数之间的关系,而不是因变量和自变量。机器学习中梯度下降的一般思想是迭代地调整参数,以便最小化成本函数。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image Source: https://saugatbhattarai.com.np/what-is-gradient-descent-in-machine-learning/

在某些情况下,我们可以应用封闭形式的方程来直接计算最适合模型训练数据集的参数。例如,为了最小化线性回归的 MSE,参数可以写成:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

然而,在其他情况下,我们没有封闭形式的方程,如逻辑回归。因此,应用类似梯度下降的迭代优化方法。

梯度下降中的一个重要参数是学习率,它决定了每一步的大小。当学习率太大时,梯度下降可能会跳过山谷,到达另一边。这将导致成本函数发散。另一方面,当学习率太小时,算法需要很长时间才能收敛。因此,在梯度下降开始之前,需要适当的学习速率。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image Source: https://towardsdatascience.com/gradient-descent-in-a-nutshell-eaf8c18212f0

归一化对梯度下降起着重要作用。如果特征没有被归一化,则具有大规模的特征将在更新中占主导地位,因此该算法将生成之字形学习路径。要达到最小值需要很多不必要的步骤和更长的时间。在所有特征被归一化之后,成本函数是更接近球形的形状。梯度下降算法直接走向最小值。执行标准化的一种方法是减去平均值并除以标准偏差。也可以直接在 Scikit-Learn 中应用 StandardScaler 函数。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image Source: https://www.jeremyjordan.me/batch-normalization/

3。三种典型的梯度下降

我们将研究在机器学习中广泛使用的梯度下降的几种变体:批量梯度下降、小批量梯度下降和随机梯度下降。

批量梯度下降

批量梯度下降在每一步都使用整批训练数据。它计算每条记录的误差,并取平均值来确定梯度。分批梯度下降法的优点是计算效率更高,产生稳定的学习路径,更容易收敛。但是,当训练集很大时,批量梯度下降需要更长的时间。

随机梯度下降

在另一种极端情况下,随机梯度下降法在每一步只从训练集中选取一个实例,并只根据该单个记录更新梯度。随机梯度下降的优点是算法在每次迭代时都快得多,这弥补了批量梯度下降的局限性。然而,与批量梯度下降相比,该算法产生的学习路径不太规则和稳定。成本函数不是平滑递减,而是上下跳动。经过多轮迭代后,算法可能会找到一个好的参数,但最终结果不一定是全局最优的。

小批量梯度下降

小批量梯度下降结合了批量和随机梯度下降的概念。在每一步,该算法基于训练集的子集而不是完整数据集或仅一个记录来计算梯度。小批量梯度下降法的优点是算法在计算过程中可以利用矩阵运算,并且代价函数比随机梯度下降法下降得更平稳。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image Source: https://towardsdatascience.com/gradient-descent-algorithm-and-its-variants-10f652806a3

4。用 Python 实现

在这一部分中,我将使用著名的数据集 iris 来展示梯度体面如何在逻辑回归中工作。

首先,导入包。

*from sklearn import datasets
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.lines as mlines*

接下来,加载数据。注意,为了简单起见,我只选择 2 种虹膜。

# Load data
iris = datasets.load_iris()
X=iris.data[0:99,:2]
y=iris.target[0:99]# Plot the training points
x_min, x_max = X[:, 0].min() - .5, X[:, 0].max() + .5
y_min, y_max = X[:, 1].min() - .5, X[:, 1].max() + .5plt.figure(2, figsize=(8, 6))
plt.clf()plt.scatter(X[:, 0], X[:, 1], c=y, cmap=plt.cm.Set1,edgecolor='k')
plt.xlabel('Sepal length')
plt.ylabel('Sepal width')
plt.xlim(x_min, x_max)
plt.ylim(y_min, y_max)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

批量梯度下降

# Function for batch gradient decent    
def Batch_GD (Learning_Rate,num_iterations,X,y):
    #Step 1: Initial Parameter
    N=len(X)
    w=np.zeros((X.shape[1],1))
    b=0
    costs=[]
    # Starting Loop
    for i in range(num_iterations):
        #Step 2: Apply Sigmoid Function and get y prediction
        Z=np.dot(w.T,X.T)+b
        y_pred=1/(1+1/np.exp(Z))

        #Step 3: Calculate Loss Function
        cost=-(1/N)*np.sum(y*np.log(y_pred)+(1-y)*np.log(1-y_pred))

        #Step 4: Calculate Gradient
        dw=1/N*np.dot(X.T,(y_pred-y).T)
        db=1/N*np.sum(y_pred-y)

        #Step 5: Update w & b
        w = w - Learning_Rate * dw
        b = b - Learning_Rate * db

        # Records cost
        if i % 1000 == 0:
            costs.append(cost)
            #print(cost)
    return(w,b,costs)# Run a function
Result_BatchGD=Batch_GD(Learning_Rate=0.01,num_iterations=100000,X=X,y=y)

随机梯度下降

# Function for Stochastic Gradient Descent       
def Stochastic_GD (Learning_Rate,num_iterations,X,y):
    # Step 1: Initial Parameter
    N=len(X)
    w=np.zeros((X.shape[1],1))
    b=0
    costs=[]
    # Starting two layer of loops
    for i in range(num_iterations):
        for j in range(N):
            # Choose 1 record
            XX=X[j,:]
            yy=y[j]
            # Step 2: Apply Sigmoid Function and get y prediction
            Z=np.dot(w.T,XX.T)+b
            y_pred=1/(1+1/np.exp(Z))
            #Step 3: Calculate Loss Function
            cost=-(yy*np.log(y_pred)+(1-yy)*np.log(1-y_pred))
            #Step 4: Calculate Gradient
            dw=np.multiply(XX,(y_pred-yy)).reshape((2,1))
            db=y_pred-yy
            #Step 5: Update w & b
            w = w - Learning_Rate * dw
            b = b - Learning_Rate * db

        #Step 6: Calculate Loss Function       
        Z_full=np.dot(w.T,X.T)+b
        y_pred_full=1/(1+1/np.exp(Z_full))
        cost=-(1/N)*np.sum(y*np.log(y_pred_full)+(1-y)*np.log(1-y_pred_full))
        #Records cost
        if i % 100 == 0:
            costs.append(cost)
            #print(cost)

    return(w,b,costs)# Run a function
Result_Stoc_GD=Stochastic_GD(Learning_Rate=0.01,num_iterations=2000,X=X,y=y)

小批量梯度下降

# Function for mini batch Gradient Descent
def Minibatch_GD (Learning_Rate,num_iterations,X,y,Minibatch):
    # Part 1: Mini Batch 
    np.random.seed(1000)
    N=len(X)
    mini_batches=[]

    #Step 1: Shuffle (X,y)
    permutation=list(np.random.permutation(N))
    shuffled_X=X[permutation,:]
    shuffled_y=y[permutation]

    #Step 2: Partition
    num_complete_minibatches=int(np.floor(N/Minibatch))

    for i in range(num_complete_minibatches):
        mini_batch_X=shuffled_X[i*Minibatch:(i+1)*Minibatch,:]
        mini_batch_y=shuffled_y[i*Minibatch:(i+1)*Minibatch]

        mini_batch = (mini_batch_X, mini_batch_y)
        mini_batches.append(mini_batch)

    if N % Minibatch !=0:
        mini_batch_X=shuffled_X[N-Minibatch:N,:]
        mini_batch_y=shuffled_y[N-Minibatch:N]

        mini_batch = (mini_batch_X, mini_batch_y)
        mini_batches.append(mini_batch)

    # Part 2: Gradient Descent
    w=np.zeros((X.shape[1],1))
    b=0
    costs=[]

    for i in range(num_iterations):
        for j in range(num_complete_minibatches+1):
            #Select Minibatch
            XX=mini_batches[j][0]
            yy=mini_batches[j][1]
            #Step 2: Apply Sigmoid Function and get y prediction
            Z=np.dot(w.T,XX.T)+b
            y_pred=1/(1+1/np.exp(Z))

            #Step 3: Calculate Gradient
            dw=1/Minibatch*np.dot(XX.T,(y_pred-yy).T)
            db=1/Minibatch*np.sum(y_pred-yy)
            #Step 4: Update w & b
            w = w - Learning_Rate * dw
            b = b - Learning_Rate * db

        #Step 5: Calculate Loss Function       
        Z_full=np.dot(w.T,X.T)+b
        y_pred_full=1/(1+1/np.exp(Z_full))
        cost=-(1/N)*np.sum(y*np.log(y_pred_full)+(1-y)*np.log(1-y_pred_full))

        if i % 1000 ==0:
            costs.append(cost)
            #print(cost)

    return(w,b,costs)# Run a function
Result_MiniGD=Minibatch_GD(Learning_Rate=0.01,num_iterations=100000,X=X,y=y,Minibatch=50)

可视化结果

# Plot linear classification
fig, ax = plt.subplots()
ax.scatter(X[:, 0], X[:, 1], c=y, cmap=plt.cm.Set1,edgecolor='k')
line_B_GD=mlines.Line2D([0,7],[-0.5527,4.1577],color='red')
line_Mini_GD=mlines.Line2D([0,7],[-0.56185,4.1674],color='blue')
line_Sto_GD=mlines.Line2D([0,7],[-0.5488,4.1828],color='green')
ax.add_line(line_B_GD)
ax.add_line(line_Mini_GD)
ax.add_line(line_Sto_GD)
ax.set_xlabel('Sepal length')
plt.show()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

从上图可以看出,三种梯度下降产生了相似的线性决策边界。

总结

在这篇文章中,你学到了很多关于梯度下降的知识。你现在知道了梯度背后的基本数学,并且理解了算法是如何在幕后工作的。第二,你了解了为什么学习速率和规范化对算法的成功如此重要。最后,您了解了最常见的梯度下降类型以及如何在 python 中实现这些算法。这些知识使你能够更好地理解机器学习和深度学习。你可以点击以下链接阅读更多博客:

[## 机器学习和深度学习之旅

这一系列博客将从理论和实现两个方面对深度学习进行介绍。

medium.com](https://medium.com/@songyangdetang_41589/table-of-contents-689c8af0c731)

参考

[1] Aurélien Géron,使用 Scikit-Learn & TensorFlow 进行机器学习,2018 年

[2]伊恩·古德费勒,约舒阿·本吉奥,亚伦·库维尔,(2017) 深度学习

[3]https://ml-cheat sheet . readthedocs . io/en/latest/gradient _ descent . html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值