当前位置:   article > 正文

fast.ai 机器学习笔记(三)

fast.ai 机器学习笔记(三)

机器学习 1:第 8 课

原文:medium.com/@hiromi_suenaga/machine-learning-1-lesson-8-fa1a87064a53

译者:飞龙

协议:CC BY-NC-SA 4.0

来自机器学习课程的个人笔记。随着我继续复习课程以“真正”理解它,这些笔记将继续更新和改进。非常感谢 JeremyRachel 给了我这个学习的机会。

广义定义的神经网络

视频 / 笔记本

正如我们在上一课结束时讨论的那样,我们正在从决策树集成转向广义定义的神经网络。如你所知,随机森林和决策树受到一个限制,即它们基本上只是在做最近邻。它们所能做的就是返回一堆其他点的平均值。因此,它们无法外推,如果你在考虑如果我将价格提高 20%,而你以前从未定价到那个水平,或者明年的销售情况会发生什么,显然我们以前从未见过明年,外推是非常困难的。它也很难,因为它只能做大约对数 2 的 N 次决策,所以如果有一个时间序列需要拟合,需要 4 步才能到达正确的时间区域,然后突然它没有多少决策可以做了,所以它可以做的计算量有限。因此,它可以建模的关系复杂度有限。

问题:我可以问一个关于随机森林的另一个缺点吗?如果我们有一个数据作为分类变量,这些变量不是按顺序排列的,对于随机森林,我们对它们进行编码并将它们视为数字,假设我们有 20 个基数,那么随机森林给出的分割结果可能是小于 5 或小于 6。但如果类别不是按顺序排列(即没有任何顺序),那意味着什么?所以如果你有,比如说,让我们回到推土机,EROPS,带空调的 EROPS,OROPS,N/A 等,我们任意地将它们标记为 0 到 3。实际上我们知道真正重要的是是否有空调。那会发生什么?基本上它会说,如果我将 EROPS w A/C 和 OROPS 组合在一起,将 N/A 和 EROPS 组合在一起,这是一个有趣的分割,因为碰巧所有带空调的都会最终出现在右侧。做完这一步后,它会进一步注意到在 EROPS w A/C 和 OROPS 组中,它还需要将其进一步分成两组。最终它会到达那里。它会提取带有空调的类别。只是它需要更多的分割,比我们理想中希望的要多。所以这有点类似于它要建模一条线,只能通过大量分割并且只是近似地完成。

后续问题:那么随机森林对于不是连续的类别也可以吗?是的,它可以。只是在某些方面它不够理想,因为我们需要做比我们想要的更多的分割点,但它可以做到。它做得相当不错。因此,尽管随机森林确实存在一些缺陷,但它们非常强大,特别是因为它们几乎没有假设,所以很难出错。用随机森林赢得 Kaggle 比赛有点困难,但很容易进入前 10%。因此,在现实生活中,通常第三位小数并不是很重要,随机森林通常是你最终会做的事情。但对于像厄瓜多尔杂货比赛这样的事情,用随机森林很难得到好的结果,因为有一个巨大的时间序列组件,几乎所有的东西都是这两个大规模高基数的分类变量,即店铺和商品。因此,甚至没有太多的层可以用随机森林,每对店铺之间的差异在不同方面都是不同的,因此有一些事情即使对于随机森林来说也很难得到相对好的结果。

另一个例子是识别数字。你可以用随机森林得到可以接受的结果,但最终,空间结构之间的关系变得重要。你可能想要能够进行像查找边缘或其他计算一样的计算,这些计算会在计算中继续进行。因此,仅仅做一个聪明的最近邻类似于随机森林的方法并不理想。所以对于这样的事情,神经网络是理想的。神经网络被证明对于像厄瓜多尔杂货比赛(即通过店铺和商品预测销售额)和识别数字这样的事情非常有效。所以在这两个事情之间,神经网络和随机森林,我们覆盖了领域。我很长一段时间以来一直没有使用除了这两个方法之外的任何其他方法。在某个时候,我们将学习如何将这两种方法结合起来,因为你可以以非常酷的方式将它们结合起来。

MNIST [6:37]

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

这是 Adam Geitgey 的一张图片。一张图片只是一堆数字,每个数字都是从 0 到 255,暗的接近 255,亮的接近 0。这是来自 MNIST 数据集的一个数字的例子。MNIST 是一个非常古老的,就像神经网络的 hello world 一样。所以这是一个例子。

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

这里有 28x28 个像素。如果是彩色的话,会有三个 —— 一个红色的,一个绿色的,一个蓝色的。我们的任务是查看数字数组并弄清楚这是一个棘手的数字 8。我们如何做到这一点?

我们将使用一小部分 FastAI 的内容,并逐渐去除更多,直到最后,我们将从头开始实现自己的神经网络,自己的训练循环,以及自己的矩阵乘法。因此,我们将逐渐深入挖掘更多。

数据 [7:54]

from fastai.imports import *
from fastai.torch_imports import *
from fastai.io import *
path = 'data/mnist/'
import os
os.makedirs(path, exist_ok=True)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

MNIST 的数据,这个非常著名的数据集的名称,可以从这里获取:

URL='http://deeplearning.net/data/mnist/'
FILENAME='mnist.pkl.gz'
def load_mnist(filename):
   return pickle.load(gzip.open(filename, 'rb'), encoding='latin-1')
  • 1
  • 2
  • 3
  • 4

我们在 fastai.io 中有一个叫做 get_data 的东西,它会从 URL 中获取数据并将其存储在你的计算机上,除非它已经存在,否则它将继续使用它。我们这里有一个叫做 load_mnist 的小函数,它简单地加载数据。你会看到它是压缩的,所以我们可以使用 Python 的 gzip 来打开它。然后它也被 pickled,所以如果你有任何类型的 Python 对象,你可以使用这个内置的 Python 库叫做 pickle 来将其转储到你的磁盘上,分享它,稍后加载它,你会得到与开始时相同的 Python 对象。你已经看到了类似于 Pandas 的 feather 格式的东西。Pickle 不仅仅适用于 Pandas,也不仅仅适用于任何东西,它基本上适用于几乎每个 Python 对象。这可能会引发一个问题,为什么我们不为 Pandas 的 DataFrame 使用 pickle。答案是 pickle 适用于几乎每个 Python 对象,但对于几乎任何 Python 对象来说,它可能不是最佳选择。因此,因为我们正在查看具有超过一亿行的 Pandas DataFrames,我们真的希望快速保存,所以 feather 是专门为此目的设计的格式,因此它会非常快速地完成。如果我们尝试 pickle 它,那将需要更长的时间。另外请注意,pickle 文件仅适用于 Python,因此你不能将它们交给其他人,而 feather 文件可以传递。所以值得知道 pickle 的存在,因为如果你有一些字典或某种对象漂浮在周围,你想要稍后保存或发送给其他人,你总是可以将其 pickle 化。所以在这种特殊情况下,deeplearning.net 的人们很友好地提供了一个 pickled 版本。

Pickle 随着时间的推移有些变化,所以像这样的旧 pickle 文件(这是 Python 2 的一个),你实际上必须告诉它是使用这个特定的 Python 2 字符集编码的。但除此之外,Python 2 和 3,你通常可以打开彼此的 pickle 文件。

get_data(URL+FILENAME, path+FILENAME)
((x, y), (x_valid, y_valid), _) = load_mnist(path+FILENAME)
  • 1
  • 2

一旦我们加载了这个,我们就像这样加载 ((x, y), (x_valid, y_valid), _)。所以我们这里正在做的事情叫做解构。解构意味着 load_mnist 给我们返回了一个元组的元组。如果在等号的左边有一个元组的元组,我们可以填充所有这些内容。所以我们得到了一个训练数据的元组,一个验证数据的元组,以及一个测试数据的元组。在这种情况下,我不关心测试数据,所以我把它放到一个名为 _ 的变量中,Python 的人们倾向于认为这是一个特殊的变量,我们把要丢弃的东西放进去。它实际上并不特殊,但非常常见。如果你看到有东西被赋值给下划线,那可能意味着你只是要丢弃它。

顺便说一下,在 Jupyter 笔记本中它确实有一个特殊的含义,即你计算的最后一个单元格始终在下划线中可用。但这是一个独立的问题。

然后元组中的第一件事本身就是一个元组,所以我们将把它放入 x 和 y 中作为我们的训练数据,然后第二个元组放入 x 和 y 中作为我们的验证数据。所以这就是所谓的解构,它在许多语言中都很常见。有些语言不支持它,但那些支持的语言,生活会变得更容易。一旦我看到一些新的数据集,我就会查看我得到了什么。它是什么类型?Numpy 数组。它的形状是什么?50,000 x 784。那么因变量呢?那是一个数组,它的形状是 50,000。

type(x), x.shape, type(y), y.shape
'''
(numpy.ndarray, (50000, 784), numpy.ndarray, (50000,))
'''
  • 1
  • 2
  • 3
  • 4

我们之前看到的 8 的图像不是长度为 784,而是大小为 28 乘以 28。所以这里发生了什么?事实证明,他们只是将第二行连接到第一行,将第三行连接到第二行,将第四行连接到第三行。换句话说,他们将整个 28 乘以 28 展平成一个单一的一维数组。这有意义吗?所以它的大小将是 28²。这绝对不是正常的,所以不要认为你看到的一切都会是这样。大多数时候,当人们分享图像时,他们会将它们分享为 JPEG 或 PNG 格式,你加载它们,你会得到一个漂亮的二维数组。但在这种特殊情况下,出于某种原因,他们拿出来的东西被展平成了 784。这个“展平”这个词在处理张量时非常常见,所以当你展平一个张量时,这意味着你将它转换为比你开始的更低秩的张量。在这种情况下,我们为每个图像开始时是一个秩为 2 的张量(即矩阵),然后我们将每个图像转换为一个秩为 1 的张量(即向量)。所以整体来说,整个东西是一个秩为 2 的张量,而不是一个秩为 3 的张量。

所以只是为了提醒我们这里的行话,这在数学中我们会称之为向量。在计算机科学中,我们会称之为一维数组,但是因为深度学习的人们必须表现得比其他人更聪明,我们不得不称之为秩为 1 的张量。它们基本上意思相同,除非你是物理学家——在这种情况下,这意味着其他事情,你会对深度学习的人们感到非常生气,因为你会说“这不是张量”。所以就是这样。不要责怪我。这只是人们说的话。

所以这要么是一个矩阵,要么是一个二维数组,要么是一个秩为 2 的张量。

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

一旦我们开始进入三维,我们开始用完数学名字,这就是为什么我们开始友好地说秩为 3 的张量。所以实际上,没有什么特别的关于向量和矩阵使它们比秩为 3 或秩为 4 的张量更重要。所以我尽量不使用向量和矩阵这些术语,因为我真的不认为它们比其他秩的张量更特别。所以习惯将numpy.ndarray (50,000, 784)看作秩为 2 的张量是很好的。

然后是行和列。如果我们是计算机科学人员,我们会称之为零维和一维。但如果我们是深度学习人员,我们会称之为轴零和轴一。然后为了更加混淆,如果你是一个图像人员,列是第一个轴,行是第二个轴。

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

所以如果你想到电视,1920 乘以 1080——列乘以行。其他人包括深度学习和数学家,行乘以列。所以如果你使用 Python 图像库,你会得到列乘以行;几乎其他所有情况,行乘以列。所以要小心。[一个学生问“为什么他们这样做?”]因为他们讨厌我们,因为他们是坏人,我猜

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/78005
推荐阅读
相关标签