如何正确地将正则化添加到 Keras 预训练模型中
使用 Tensorflow 2.0 正则化预训练的 Keras 模型
Photo by Kelly Sikkema on Unsplash
介绍
如果你以训练深度学习模型为生,你可能会厌倦知道一件具体而重要的事情:
微调深度预训练模型需要大量的正则化工作。
作为对比,你可能已经注意到,如何向来自深度学习库(如 Keras)的预训练模型添加正则化并不总是显而易见的。此外,找到这个问题的正确答案也不容易。在撰写这篇文章的过程中,我遇到了许多关于堆栈溢出的代码片段和一些博客文章,它们根本没有得到正确的解释。然后,作为减少您的 Google 搜索的一种方式(并帮助我未来的自己),我将向您展示如何以正确的方式将正则化添加到预训练的 Keras 模型中。
让我们从基础开始。
微调
微调是指采用预先训练好的模型,并将其作为优化不同(大多数情况下相关)任务的起点的过程。你可以想象使用一个在 ImageNet 数据库上训练的 ResNet50 模型,并用它来解决一个新问题,比如昆虫分类。
这个过程通常遵循简单的步骤。
- **我们首先加载模型架构和预训练权重。**对于迁移学习更为成熟的计算机视觉,这是我们加载这些著名架构之一的地方,如 DenseNets 或 MobileNets 及其各自的权重(在 ImageNet 上训练)。
- **然后,我们在预训练模型的顶部添加一个特定于任务的分类层。**这通常是一个具有 softmax 或 sigmoid 激活的致密层。请注意,分类层中单元的数量必须等于新问题的类的数量。所以,如果你的昆虫数据集包含 28 种虫子之类的东西,那么最后一层需要有 28 个单元。
- 然后,我们完成了模型的准备。在 Keras 中,我们使用优化器和损失函数编译模型,设置超参数,并调用 fit。
附注:这可能过于简单,但对我们的例子来说很好。
对抗过度拟合
我们必须记住的一件事是:
当微调预训练模型时,过度拟合是一个更大的问题。
问题很容易看出来。如果你有一个小的训练数据,你会不断地向网络一遍又一遍地显示相同的实例。此外,正如我们所知,ImageNet 上预先训练的 ConvNets 通常非常复杂;即它们有许多训练参数。因此,模型会很快完全记住你的训练数据。
作为解决方案,微调通常需要两件事:
- 大量的正规化
- 非常小的学习率
对于正规化,任何事情都可能有所帮助。我通常使用 l1 或 l2 正则化,并提前停止。对于没有批量标准化的 ConvNets,空间丢失也是有帮助的
作为补充说明,深度学习模型是众所周知的数据饥渴。这些模型需要大量数据来将非常复杂的高维空间分解成特征空间中的线性可分决策。许多人将微调视为使用较小数据集训练深度模型的一种方式。虽然在实践中,这种观点听起来可能是正确的,但这里有一个重要的陷阱。即使您可以使用小得多的数据集来拟合新模型,请记住,您的预训练模型训练了几天(使用多个 GPU)。换个说法,微调其实就是——站在巨人的肩膀上。
现在让我们直接进入代码。
黑客攻击
直观地说,添加正则化的过程很简单。在加载我们预先训练好的模型后,称为 基础模型 ,我们将遍历它的所有层。对于每一层,我们检查它是否支持正则化,如果支持,我们添加它。代码如下所示。
看起来我们结束了。事实上,如果你在谷歌上搜索如何将正则化添加到 Keras 预训练模型中,你会发现相同的结果。
作为安全检查,让我们确保正则化设置正确。在 Keras 中,我们可以通过访问层或模型的 loss 属性来检索损耗。在我们的例子中,我们可以通过以下方式访问所有损失的列表(通过正则化来自所有层):
如果你对术语感到困惑,这个属性叫做损失,因为在优化过程中正则化惩罚被添加到损失函数中。
如你所见,有些奇怪的事情正在发生。列表是空的,这意味着没有正则化惩罚应用于卷积核。
但是刚刚发生了什么?
好吧,直接进入问题,看起来当我们改变一个层的属性时,正如我们所做的,**唯一真正改变的是模型配置。**因此,模型对象本身就和我们加载时一样。完全没有变化。
添加正则化后,看一下配置文件。kernel _ regulator属性和我们设置的一样。
这个问题的一个简单解决方案是重新加载模型配置。这很容易做到,也解决了问题。
现在,如果我们试图看到*,我们就有了。*
然而,作为一种常见的黑客行为,这又引入了另一个问题。如果您更仔细地注意模型的权重,在从配置文件重新加载模型之后,权重被重置! 我们刚刚丢失了,所有的 ImageNet 预训练参数!
好吧,一个快速的解决方法是使用相同的策略。我们可以在重新加载模型配置之前保存权重,并在模型正确加载后重新加载权重。
下面的函数完成了全部工作。您可以传递来自 Keras 应用 (使用 Tensorflow 2.0) 的任何模型,以及您想要的正则化器,它会返回正确配置的模型。请注意,在从配置文件重新加载模型之前和之后,我们是如何保存和重新加载模型权重的。
同样,您可以使用相同的代码添加bias _ regulator和activity _ regulator*。*
就是这样。一个快速但有希望的有用的技巧来调整你的预训练模型。
感谢阅读!
如何调整检测网
一种由 NVIDIA 创建的对象检测架构
Photo by Christian Wiediger on Unsplash
DetectNet 是由 NVIDIA 创建的对象检测架构。它可以从 NVIDIA 的 Deep Learning 图形用户界面 DIGITS 运行,通过该界面,您可以快速设置和开始训练分类、物体检测、分割和其他类型的模型。
NVIDIA 提供了两个基本的 DetectNet prototxt 文件:
- 单个类一个(为原件),可在这里找到,并且
- 两个等级中的一个可以在这里找到。
DetectNet 最初的架构是用 Caffe 编写的。除了在英伟达网站上发表的两篇博客文章和一些(主要)重申博客内容的教程之外,我没有找到太多关于该架构的文档。我确实发现,在 NVIDIA/DIGITS 存储库中,有一个特定的 GitHub 问题问题#980 已经积累了大量信息。
以下是我从 GitHub 问题中收集的重点:
- 训练集中的图像大小不应该不同。如果是,您应该填充它们或调整它们的大小,使其大小相等。调整大小或填充可以在数字数据集创建步骤中完成。
- DetectNet 对大小在 50x50 像素到 400x400 像素之间的边界框很敏感。它很难识别超出这个范围的边界框。
- 如果您想检测比检测网敏感的尺寸小的对象,您可以调整图像的大小,使大部分边界框适合检测网的首选范围,或者您可以将模型的步距更改得更小。
- 图像尺寸必须可被步幅整除。例如,1248 和 384(检测网的默认图像大小)可以被 16 整除。
- 如果您正在使用不同于原始架构的图像分辨率来训练模型(原始架构期望图像的宽度为 1248,高度为 384),您需要在架构内的行 57 、 58 、 79 、 80 、 118 、 119 、 2504 、 2519 上更改指定的图像尺寸
- 要更改模型步幅,您必须在行 73 、 112 、 2504 、 2519 和 2545 中将默认步幅值(16)更改为您想要的值(这些行指的是单个类 DetectNet prototxt)。
- 如果指定一个较小的步幅,则需要减少网络中的层数来调整维度。降低维数的一种方法是将 pool3/3x3_s2 层的内核和步幅参数更改为 1。该层存在于从行 826 到 836 (这些行指的是单个类 DetectNet prototxt)。
对于多类目标检测,其中您想要检测两个以上的类,您可以更改 2 类检测网络协议[ 5 ]。取决于类别数量的行有:
- 第 82 行到第 83 行:为每个额外的类添加一行,递增地或基于数据集标签文本文件中的类值更改“src”和“dst”。
- 第 2388 行:更改你的模型将识别的类别数量。
- 第 2502 至 2503 行:每增加一个等级增加一行
- 第 2507 行:将最后一个数字更改为您的模型将识别的类的数量。
- 2518-2519行:每增加一节课就增加一行。
- 2523行:将最后一个数字更改为您的模型将识别的类的数量。
- 2527-2579 行:这里有 4 层,每层 2 层。每个类别有一个对应于分数的层(该层对指定类别的检测进行评分)和一个对应于 mAP 的层(该层计算指定类别的 mAP)。为每一个额外的类别添加一个分数和类别图层,并确保在图层的顶部和底部 blobs 中指定正确的类别号。
综上所述:(I)确保数据集中的所有图像大小相同(如果不相同,请调整大小或填充它们);(ii)如果使用的是自定义大小的数据集,则必须修改 DetectNet prototxt 文件中的多行内容;(iii)确保数据中的大部分边界框的大小在 50x50 和 400x400 像素之间;(iv)如果要将跨步更改为较小的值, 您必须减少网络中的层,并且(v)您可以调整 DetectNet 体系结构,通过将一些数字更改为您要识别的类的数目,并在 prototxt 文件中添加额外的行和层来进行多类对象检测。
我建议您阅读下面提到的所有参考资料,以便更好地了解 DetectNet 以及如何针对您的问题对其进行修改。
参考文献:
- 检测网:数字量物体检测的深层神经网络
- 1 级检测网网络原型
- 2 级检测网网络原型
- GitHub NVIDIA/DIGITS 问题#980:如何使用 DetectNet 获取自定义大小的数据?
- 数字用户:将初始步幅从 16 改为 8
- 使用 Nvidia 数字训练自定义多类对象检测模型
如何使用 Python 分析笔记本电脑上的 100 GB 数据
Image Credit: Flickr User Kenny Louie
理解大数据
许多组织正试图收集和利用尽可能多的数据,以改善他们如何经营业务、增加收入或如何影响他们周围的世界。因此,数据科学家面对 50GB 甚至 500GB 大小的数据集变得越来越常见。
现在,这种数据集使用起来有点…不舒服。它们足够小,可以放入日常笔记本电脑的硬盘,但又太大,无法放入 RAM。因此,它们已经很难打开和检查,更不用说探索或分析了。
处理此类数据集时,通常采用 3 种策略。第一个是对数据进行子采样。这里的缺点是显而易见的:一个人可能会因为没有看到相关的部分而错过关键的洞察力,或者更糟糕的是,因为没有看到全部而误解了它所讲述的故事和数据。下一个策略是使用分布式计算。虽然在某些情况下这是一种有效的方法,但是它会带来管理和维护集群的巨大开销。想象一下,必须为一个刚好超出 RAM 范围的数据集设置一个集群,比如 30–50gb 的范围。对我来说这似乎是一种过度杀戮。或者,您可以租用一个强大的云实例,它具有处理相关数据所需的内存。例如,AWS 提供了 1tb 内存的实例。在这种情况下,您仍然需要管理云数据桶,在每次实例启动时等待数据从桶传输到实例,处理将数据放在云上带来的合规性问题,以及处理在远程机器上工作带来的所有不便。更不用说成本,虽然开始很低,但随着时间的推移,成本会越来越高。
在本文中,我将向您展示一种新的方法:一种更快、更安全、总体上更方便的方法,使用几乎任意大小的数据进行数据科学研究,只要它能够适合您的笔记本电脑、台式机或服务器的硬盘驱动器。
Vaex
Vaex 是一个开源的 DataFrame 库,它可以对硬盘大小的表格数据集进行可视化、探索、分析甚至机器学习。为此,Vaex 采用了内存映射、高效核外算法和惰性评估等概念。所有这些都包含在一个熟悉的熊猫式的 API 中,所以任何人都可以马上开始使用。
十亿次出租车乘坐分析
为了说明这个概念,让我们对一个数据集做一个简单的探索性数据分析,这个数据集太大了,以至于不能放入典型笔记本电脑的 RAM 中。在本文中,我们将使用纽约市(NYC)的出租车数据集,其中包含标志性的黄色出租车在 2009 年至 2015 年间进行的超过10 亿次出租车旅行的信息。这些数据可以从这个网站下载,并且是 CSV 格式的。完整的分析可以在本 Jupyter 笔记本 中单独查看。
清扫街道
第一步是将数据转换成内存可映射文件格式,如 Apache Arrow 、 Apache Parquet 或 HDF5 。如何将 CSV 数据转换为 HDF5 的示例可参见这里的。一旦数据是内存可映射格式,用 Vaex 打开它是即时的(0.052 秒!),尽管它在磁盘上的大小超过 100GB:
Opening memory mapped files with Vaex is instant (0.052 seconds!), even if they are over 100GB large.
为什么这么快?当你用 Vaex 打开一个内存映射文件时,实际上没有数据读取。Vaex 只读取文件元数据,如数据在磁盘上的位置、数据结构(行数、列数、列名和类型)、文件描述等。那么,如果我们想要检查数据或与数据进行交互,该怎么办呢?打开一个数据集会产生一个标准的数据框,检查它的速度很快,而且很简单:
A preview of the New York City Yellow Taxi data
请再次注意,单元执行时间非常短。这是因为显示 Vaex 数据帧或列只需要从磁盘读取前 5 行和后 5 行。这让我们想到了另一个要点:Vaex 只会在必要时检查整个数据集,并且会尽量少地检查数据。
无论如何,让我们从清除这个数据集的极端异常值或错误的数据输入开始。一个好的开始方式是使用describe
方法获得数据的高层次概述,该方法显示每列的样本数、缺失值数和数据类型。如果列的数据类型是数字,还会显示平均值、标准偏差以及最小值和最大值。所有这些统计数据都是通过对数据的一次遍历计算出来的。
Getting a high level overview of a DataFrame with the describe
method. Note that the DataFrame contains 18 column, but only the first 7 are visible on this screenshot.
describe
方法很好地说明了 Vaex 的能力和效率:所有这些统计数据都是在我的 MacBook Pro (15 英寸,2018,2.6GHz 英特尔酷睿 i7,32GB 内存)上在不到 3 分钟的时间内计算出来的。其他库或方法需要分布式计算或超过 100GB 的云实例来执行相同的计算。使用 Vaex,您需要的只是数据,而您的笔记本电脑只有几 GB 的内存。
查看describe
的输出,很容易注意到数据包含一些严重的异常值。首先,让我们从检查提货地点开始。移除异常值的最简单方法是简单地绘制上下车地点,并直观地定义我们要重点分析的纽约市区域。由于我们正在处理如此大的数据集,直方图是最有效的可视化方式。用 Vaex 创建和显示直方图和热图是如此之快,这样的图可以是交互式的!
df.plot_widget(df.pickup_longitude,
df.pickup_latitude,
shape=512,
limits='minmax',
f='log1p',
colormap='plasma')
一旦我们交互式地决定了我们想要关注纽约的哪个区域,我们就可以简单地创建一个过滤数据框架:
上面的代码块很酷的一点是它只需要很少的内存就可以执行!过滤 Vaex 数据帧时,不会复制数据。相反,只创建对原始对象的引用,并对其应用二进制掩码。该掩码选择显示哪些行并用于将来的计算。这为我们节省了 100GB 的 RAM,这是复制数据时所需要的,正如当今许多标准数据科学工具所做的那样。
现在,让我们检查一下passenger_count
列。单次出租车行程记录的最大乘客人数是 255 人,这似乎有点极端。我们来统计一下每名乘客的出行次数。用value_counts
方法很容易做到这一点:
The value_counts
method applied on 1 billion rows takes only ~20 seconds!
从上图中我们可以看到,超过 6 名乘客的行程可能是罕见的异常值,或者只是错误的数据输入。还有大量 0 旅客的车次。因为此时我们不了解这些是否是合法的旅行,所以让我们也将它们过滤掉。
让我们用行程距离做一个类似的练习。由于这是一个连续变量,我们可以绘制出行距离的分布。望最低(负!)和最大值(比火星还远!)距离,我们来画一个直方图,有一个比较感性的范围。
A histogram of the trip distances for the NYC taxi dataset.
从上图中我们可以看出,旅行次数随着距离的增加而减少。在大约 100 英里的距离,分布有一个大的下降。现在,我们将以此为分界点,根据行程距离消除极端异常值:
行程距离列中极端异常值的存在是调查出租车行程持续时间和平均速度的动机。这些特征在数据集中不容易获得,但是计算起来很简单:
上面的代码块不需要任何内存,也不需要任何时间来执行!这是因为代码会导致创建*虚拟列。*这些列只存放数学表达式,仅在需要时才进行计算。否则,虚拟列的行为就像任何其他常规列一样。注意,对于同样的操作,其他标准库需要几十 GB 的 RAM。
好的,让我们画出旅行持续时间的分布图:
Histogram of durations of over 1 billion taxi trips in NYC.
从上面的图中我们看到,95%的出租车行程不到 30 分钟就能到达目的地,尽管有些行程可能需要 4-5 个小时。你能想象在纽约被困在出租车里 3 个多小时吗?无论如何,让我们思想开放,考虑所有持续时间不超过 3 小时的旅行:
现在让我们调查出租车的平均速度,同时为数据限制选择一个合理的范围:
The distribution of average taxi speed.
基于分布变平的位置,我们可以推断出合理的平均滑行速度在每小时 1 到 60 英里的范围内,因此我们可以更新我们的过滤数据帧:
让我们把焦点转移到出租车旅行的费用上。从describe
方法的输出中,我们可以看到在 *fare_amount、total_amount、*和 tip_amount 列中有一些疯狂的离群值。首先,这些列中的任何值都不应该是负数。另一方面,数字表明一些幸运的司机仅仅乘坐一次出租车就几乎成为百万富翁。让我们看看这些量的分布,但在一个相对合理的范围内:
The distributions of the fare, total and tip amounts for over 1 billion taxi trips in NYC. The creation of these plots took only 31 seconds on a laptop!
我们看到上述三种分布都有相当长的尾部。尾部的一些值可能是合法的,而其他值可能是错误的数据输入。无论如何,现在让我们保守一点,只考虑 *fare_amount、*total _ amount、 tip_amount 少于 200 美元的乘车。我们还要求 fare_amount,total_amount 值大于$0。
最后,在对数据进行所有初始清理之后,让我们看看还有多少次出租车出行需要我们进行分析:
我们剩下超过 11 亿次旅行!这些数据足以让我们对出租车行业有一些有价值的了解。
坐到司机座位上
假设我们是一名未来的出租车司机,或者出租车公司的经理,并且有兴趣使用这个数据集来学习如何最大化我们的利润,最小化我们的成本,或者仅仅是改善我们的工作生活。
让我们首先找出搭载乘客的地点,平均来说,这些地点会带来最好的收益。天真的是,我们可以绘制一个热图,显示按平均票价金额进行颜色编码的上车地点,并查看热点地区。然而,出租车司机自己也有成本。例如,他们必须支付燃料费。因此,带乘客去很远的地方可能会导致更高的票价,但这也意味着更大的燃料消耗和时间损失。此外,从那个遥远的地方找到乘客去市中心的某个地方可能不是那么容易的,因此没有乘客的情况下开车回来可能是昂贵的。解释这一点的一种方法是通过费用金额和行程距离之间的比率的平均值对热图进行颜色编码。让我们考虑这两种方法:
Heatmaps of NYC colour-coded by: average fare amount (left), and average ratio of fare amount over trip distance.
在天真的情况下,当我们只关心获得所提供服务的最高票价时,搭载乘客的最佳区域是纽约机场,以及沿主要道路,如范威克高速公路和长岛高速公路。当我们考虑到旅行的距离,我们得到一个稍微不同的画面。Van Wyck 高速公路和长岛高速公路以及机场仍然是搭载乘客的好地方,但是它们在地图上已经不那么突出了。然而,一些新的亮点出现在哈得逊河的西侧,看起来非常有利可图。
当出租车司机可能是一份相当灵活的工作。为了更好地利用这种灵活性,除了应该潜伏在哪里之外,知道什么时候开车最有利可图也是有用的。为了回答这个问题,让我们制作一个图表,显示每天和一天中的每个小时的平均费用与行程距离的比率:
The mean ratio of fare over trip distance per day of week and hour of day.
上面的数字是有道理的:最好的收入发生在一周工作日的高峰时间,尤其是中午前后。作为出租车司机,我们收入的一小部分给了出租车公司,所以我们可能会对哪一天、什么时间顾客给的小费最多感兴趣。让我们绘制一个类似的图,这次显示的是平均小费百分比:
The mean tip percentage per day of week and hour of day.
上面的情节很有意思。它告诉我们,乘客在早上 7-10 点之间给出租车司机的小费最多,在一周的前几天晚上也是如此。如果你在凌晨 3 点或 4 点接乘客,不要指望得到大笔小费。结合上两个图的观点,一个好的工作时间是早上 8-10 点:一个人将会得到每英里不错的票价和不错的小费。
加速你的引擎!
在本文的前面部分,我们简要关注了 trip_distance 列,在清除异常值的同时,我们保留了所有低于 100 英里的行程。这仍然是一个相当大的临界值,特别是考虑到黄色出租车公司主要在曼哈顿运营。 trip_distance 列描述了出租车在上车地点和下车地点之间行驶的距离。然而,人们通常可以在两个确切的上下车地点之间选择不同距离的不同路线,例如为了避免交通堵塞或道路施工。因此,作为 trip_distance 列的对应项,让我们计算一个接送位置之间的最短可能距离,我们称之为 arc_distance:
For complicated expressions written in numpy, vaex can use just-in-time compilation with the help of Numba, Pythran or even CUDA (if you have a NVIDIA GPU) to greatly speed up your computations.
用于计算 arc_distance 的公式非常复杂,它包含了大量的三角学和算术,并且计算量很大,尤其是当我们处理大型数据集时。如果表达式或函数仅使用 Numpy 包中的 Python 操作和方法编写,Vaex 将使用您机器的所有内核并行计算它。除此之外,Vaex 还支持通过 Numba (使用 LLVM)或py tran(通过 C++加速)进行实时编译,从而提供更好的性能。如果你碰巧有 NVIDIA 显卡,你可以通过jit_cuda
方法使用 CUDA 来获得更快的性能。
无论如何,让我们画出行程距离和*弧距离:*的分布
Left: comparison between trip_distance and arc_distance. Right: the distribution of trip_distance for arc_distance<100 meters.
有趣的是,弧距从未超过 21 英里,但出租车实际行驶的距离可能是它的 5 倍。事实上,上百万次出租车旅行的下车地点都在上车地点 100 米(0.06 英里)以内!
多年来的黄色出租车
我们今天使用的数据集跨越了 7 年。有趣的是,我们可以看到一些兴趣是如何随着时间的推移而演变的。借助 Vaex,我们可以执行快速的核外分组和聚合操作。让我们来看看票价和旅行距离在这 7 年中是如何演变的:
A group-by operation with 8 aggregations for a Vaex DataFrame with over 1 billion samples takes less than 2 minutes on laptop with a quad-core processor.
在上面的单元块中,我们执行了一个 group-by 操作,然后是 8 个聚合,其中 2 个聚合在虚拟列上。上面的单元块在我的笔记本电脑上运行了不到 2 分钟。考虑到我们使用的数据包含超过 10 亿个样本,这是相当令人印象深刻的。不管怎样,让我们看看结果。以下是多年来出租车费用的变化情况:
The average fare and total amounts, as well as the tip percentage paid by the passengers per year.
我们看到出租车费和小费随着时间的推移而增加。现在让我们看看出租车行驶的平均行程距离和弧距与年份的关系:
The mean trip and arc distances the taxis travelled per year.
上图显示,行程距离和弧线距离都有小幅增加,这意味着,平均而言,人们倾向于每年旅行更远一点。
给我看看钱
在我们的旅行结束之前,让我们再停一站,调查一下乘客是如何支付乘车费用的。数据集包含 payment_type 列,所以让我们看看它包含的值:
从数据集文档中,我们可以看到该列只有 6 个有效条目:
- 1 =信用卡支付
- 2 =现金支付
- 3 =不收费
- 4 =争议
- 5 =未知
- 6 =无效行程
因此,我们可以简单地将 payment_type 列中的条目映射到整数:
现在,我们可以根据每年的数据分组,看看纽约人在出租车支付方面的习惯是如何变化的:
Payment method per year
我们看到,随着时间的推移,信用卡支付慢慢变得比现金支付更加频繁。我们真正生活在一个数字时代!注意,在上面的代码块中,一旦我们聚合了数据,小的 Vaex 数据帧可以很容易地转换成 Pandas 数据帧,我们可以方便地将其传递给 Seaborn 。我不想在这里重新发明轮子。
最后,让我们通过绘制现金与卡支付次数之间的比率来看看支付方式是取决于一天中的时间还是一周中的某一天。为此,我们将首先创建一个过滤器,仅选择由现金或卡支付的乘车费用。下一步是我最喜欢的 Vaex 特性之一:带有选择的聚合。其他库要求对每种支付方式的单独过滤的数据帧进行聚合,然后合并成一种支付方式。另一方面,使用 Vaex,我们可以通过在聚合函数中提供选择来一步完成。这非常方便,只需要一次数据传递,从而为我们提供了更好的性能。之后,我们可以用标准方式绘制结果数据帧:
The fraction of cash to card payments for a given time and day of week.
看上面的图,我们可以注意到一个类似的模式,显示了小费百分比作为一周中的某一天和一天中的某个时间的函数。从这两个图中,数据表明刷卡的乘客比现金支付的乘客倾向于给更多的小费。为了查明这是否确实是真的,我想邀请你去尝试并弄清楚它,因为现在你已经有了知识、工具和数据!你也可以看看这个 Jupyter 笔记本来获得一些额外的提示。
我们到达了你的目的地
我希望这篇文章是对 Vaex 的一个有用的介绍,并且它将帮助您减轻您可能面临的一些“令人不舒服的数据”问题,至少在表格数据集方面。如果您有兴趣探索本文中使用的数据集,可以直接从 S3 使用 Vaex。参见完整版 Jupyter 笔记本了解如何做到这一点。
有了 Vaex,人们可以在几秒钟内,在自己舒适的笔记本电脑上浏览 10 亿多行数据,计算各种统计数据、汇总数据,并生成信息丰富的图表。它是免费和开源的,我希望你能尝试一下!
数据科学快乐!
本文中介绍的探索性数据分析基于由 Maarten Breddels 创建的早期 Vaex 演示。
请查看下面我们来自 PyData London 2019 的现场演示:
如何用 python 分析 A/B 测试结果?
这是书中的一个数据挑战案例: 《数据科学带回家的挑战集锦》。 数据集可以在上面的网站购买,本文只讲解决方案和 python 技巧。所有代码都在我的 Github 上。
1.实验概述
XYZ 公司是一个全球性的电子商务网站,提供网站的本地化版本。XYZ 的一位数据科学家注意到,西班牙用户的转化率比任何其他西班牙语国家都高。
他们认为一个原因可能是翻译。所有说西班牙语的国家都有一个西班牙人写的网站的相同翻译。他们同意尝试一个测试,每个国家都有一个由本地人写的翻译。
然而,在他们进行测试后,他们真的很惊讶,因为测试是阴性的。也就是说,似乎非本地化翻译做得更好!
试验性变更:非本地化到本地化翻译
2.数据分析
看看这个数据框。
我们有 12 列,分别是“用户标识”、“日期”、“来源”、“设备”、“浏览器语言”、“广告频道”、“浏览器”、“转换”、“测试”、“性别”、“年龄”、“国家”。
所有来自西班牙的数据都在对照组。
data overview
1)确认测试实际上是阴性的。
首先,我们需要证明,在对照组中,西班牙在变革前的表现优于其他国家。
groupby_country = data[data['test'] == 0][['conversion', 'country']].groupby('country').mean()
groupby_country = groupby_country.reset_index()
groupby_country = groupby_country.sort_values('conversion', ascending = **False** )
*# Visualization*
fig, ax = plt.subplots(figsize=(18, 6))
sns.barplot(x='country', y='conversion', data=groupby_country, ax=ax)
plt.show()
然后,我们需要确认非本地化翻译表现更好的实验结果,或者可以说,在除西班牙以外的国家,控制组比测试组做得更好
*# Visualization* fig, ax = plt.subplots(figsize=(18, 6))
sns.barplot(x=’country’, y=’conversion’, hue=’test’, data=data, ax=ax)
plt.show()
并用统计学方法来证明。
*# A/B test*
test_data = data[data['country'] != 'Spain']
test_val = test_data[test_data['test'] == 1]['conversion'].values
cont_val = test_data[test_data['test'] == 0]['conversion'].values*# Welch Two Sample t-test*
print(ttest_ind(test_val, cont_val, equal_var=**False**))
ttest _ indResult(statistic =-7.3939374121344,pvalue=1.42829947540 e-13)
绝对正确。
然而,我们可以看到,测试组的平均转化率为 0.0434,对照组为 0.0483,下降 10%,如果这是真的,那将是惊人的。所以我们需要深入研究。
2)解释为什么会发生这种情况。本地化的翻译真的很差吗?
很可能,由于某种原因,一些用户更有可能进入测试或控制阶段,这部分用户的转化率明显高于/低于测试或控制阶段,这影响了整体结果。
只看西班牙以外国家的数据:(Github 上更多图表)
- 日期
- sourse
- 设备
- 语言
- 国家
我们可以看到,除了国家,所有测试组在其他细分领域的表现都比较差。所以仔细看看这个国家。
在理想的情况下,每个部分的测试和控制人员的分布应该是相同的。因此,我们可以使用决策树来测试随机化是否有效,其中变量是用户维度,结果变量是用户是在测试中还是在控制中。
**import** **h2o**
**from** **h2o.frame** **import** H2OFrame
**from** **h2o.estimators** **import** H2OGradientBoostingEstimatorh2o.init()
h2o.remove_all()
h2o_df = H2OFrame(data)
h2o_df['test'] = h2o_df['test'].asfactor()
h2o_df['ads_channel'] = h2o_df['ads_channel'].asfactor()
h2o_df.summary()feature = ['user_id', 'date', 'source', 'device', 'browser_language',
'ads_channel', 'browser', 'sex', 'age',
'country']
target = 'test'*# Build random forest model*
model = H2OGradientBoostingEstimator(ntrees = 2, max_depth = 2)
model.train(x=feature, y=target, training_frame=h2o_df)print(model)
data.groupby(['country','test']).size()=====================================country test
Argentina 0 9356
1 37377
Bolivia 0 5550
1 5574
Chile 0 9853
1 9884
Colombia 0 27088
1 26972
Costa Rica 0 2660
1 2649
Ecuador 0 8036
1 7859
El Salvador 0 4108
1 4067
Guatemala 0 7622
1 7503
Honduras 0 4361
1 4207
Mexico 0 64209
1 64275
Nicaragua 0 3419
1 3304
Panama 0 1966
1 1985
Paraguay 0 3650
1 3697
Peru 0 16869
1 16797
Uruguay 0 415
1 3719
Venezuela 0 16149
1 15905
missing 0 245
1 209
dtype: int64
阿根廷和乌拉圭加起来有 80%的测试和 20%的控制!随机化在这两个国家并不成功。
让我们在控制国家之后检查测试结果。
countries = [name **for** name **in** data['country'].unique() **if** name **is** **not** np.nan]
**for** country **in** countries:
test_val = data[(data['country'] == country) & (data['test'] == 1)]['conversion'].values
cont_val = data[(data['country'] == country) & (data['test'] == 0)]['conversion'].values
test_mean = test_val.mean()
cont_mean = cont_val.mean()
p_val = ttest_ind(test_val, cont_val, equal_var=**False**).pvalue
print('**{0:15s}** **{1:15.5f}** **{2:15.5f}** **{3:10f}**'.format(country, test_mean, cont_mean, p_val))
在我们对国家进行控制后,检验显然显得不显著。考虑到目标是提高转化率,这并不是一个很大的成功,但至少我们知道本地化的翻译没有让事情变得更糟!
如何分析分层随机抽样数据
使用实验设计来增加你的分析能力
Rock stratification is a topic for a different day. Credit: https://en.wikipedia.org/wiki/Stratigraphy
当构建一个实验时,要问的最重要的问题之一是:我应该如何从我的总体中取样?很明显,你想进行某种随机抽样程序,但是如何进行随机抽样会对你的分析产生很大的影响。虽然有许多关于如何进行分层随机抽样的有用指南,但我注意到,关于如何正确分析分层抽样数据的指南很少。在这篇文章中,我将讨论如何进行分层抽样,以及如何使用一些模拟数据作为例子来分析结果数据。
设计实验
首先,我想简要回顾一下分层抽样以及它的重要性。假设我是 X 公司的数据科学家。X 公司拥有来自美国各地的大约 500,000 名用户。我们的大多数用户生活在城市,但也有很大一部分生活在小城镇。我有兴趣做一个实验,看看改变我们的应用程序的用户界面会如何改变从应用程序到二级网站的点击率。一个非常简单的 A/B 测试。假设我有相关的权限和足够匿名的数据,我应该如何选择这个实验的用户?
我有两个选择:1)我可以从用户群中随机抽样,或者 2)我可以对我的用户中的两个子群(城市和城镇)进行分层抽样。如果我想使用分层抽样,我会从每个亚组中随机抽取样本,并把其中的一半分配给 A 组或 B 组。
但是我为什么要这么做呢?在这种情况下,如果我认为亚组之间存在真正的差异,我会分层。例如,也许“我的城市”子组的基线点击率高于“城镇”子组。另一种可能性是,治疗 B 的效应可能会因城市和城镇而异。也许城市里的人和城镇里的人有不同的审美观,而且真的喜欢 B 处理,导致 B 处理对点击率有更强的影响。在这种情况下,我不会讨论这种可能性,但在其他情况下,这可能很重要。
在这篇文章中,我将模拟一个用户群,并用一个假设的反应进行一个实验。首先使用完全随机抽样(又名简单随机抽样),然后使用分层随机抽样。然后,我将检查我对实验的推断在两种取样方式之间是如何变化的。这两个亚组的基线点击率有很大不同,但每组的治疗效果是相同的。
构造数据
我将使用 pandas、numpy、scipy 和 statsmodels 进行分析。你可以用 sklearn 代替 statsmodels 来做这些,但是我更喜欢 statsmodels 的统计输出。
我需要做的第一件事是建立一个用户群。
首先,为了可再现性,我为 numpy 设置了一个随机种子,用于它的随机选择算法。人口数据帧中的每一行代表一个唯一的用户。我的用户群有 50 万人,来自城市的人比来自城镇的人丰富 15 倍。在模拟数据集中,城市和城镇的人口比例并不完全是 15:1,因为我使用的是随机过程:
city 468520
town 31480
由于来自 R 背景,我还在这个数据帧中包含了一个 id 列。Pandas 通常用它的索引功能来解决这个问题,但是当我从一个群体中取样时,我喜欢有一个不变的 id 号。
随机抽样实验
对于这个实验,我感兴趣的是在实现一个改变后,用户点击应用的概率是否会增加。例如,为了增加流量,X 公司可能想改变一个指向合作伙伴网站的按钮。
在第一种情况下,我将从整体人口中随机抽样,不考虑城镇和城市之间的差异。
在上面的代码中,我设置了每次治疗 500 个用户的样本量(总共 1000 个用户)。然后,我从所有用户中抽取 1000 个样本,并基于这些样本创建一个新的数据框架。理想情况下,您应该使用功效分析来决定样本大小。但是我会在文章的最后回到这个话题。
下一步是分配治疗方案。为了让事情变得简单,我创建了一个函数,它可以对完全随机抽样和分层随机抽样都这样做。
在这个过程的最后,我们得到了一个类似这样的数据帧:
我已经为分配的治疗添加了一列,也为每个虚拟变量添加了一列。虚拟变量列将使合成响应变量更容易。
每个城市类别中有多少被分配到每个治疗?
我们马上就能看到一些担忧。相对于城市类别,城镇类别的样本非常少(正如我们根据它们在人口中的丰富程度所预期的)。更重要的是,处理 B 中的城镇个体几乎是处理 a 中的两倍。如果城镇个体与城市个体非常不同,这可能是一个真正的问题。(提示:这里会是个问题。)
随机抽样分析
为了计算预期的信号,我需要指定基线点击率以及界面变化产生的提升。对于这个例子,我假设城市用户的基线点进概率为 0.3,而城镇用户的基线点进概率为 0.1。然后,我假设 B 组中的用户的点击概率会增加 0.05 个百分点。它有点大,但是在这个玩具例子中很有用。
为了创建响应数据,我根据我在上一段中列出的概率,从每个组的二项分布中取样。
要分解上面代码块中发生的事情,从 np.random.binomial()函数开始。我从二项分布中抽样 500 次,每次只有一次试验,其中成功的概率是我刚才列出的概率中的任何一个(0.3,0.1,或者其他两个加上额外的 0.05)。这就是虚拟变量派上用场的地方。请记住,只有当用户来自某个城市时,city 列才为 1,其他地方都为 0,对于 A、B 和 town 列也是如此。这意味着我们可以将四个二项式响应变量中的每一个乘以它们各自的虚拟变量,然后将所有 4 列相加,得到一个响应变量列。这个过程类似于一般线性回归模型用来分析分类数据的过程。
从这里我们可以很容易地进行 t 检验,看看我们的治疗是否有效果。
responseA = completerandom_df['response'][completerandom_df['A']==1]
responseB = completerandom_df['response'][completerandom_df['B']==1]stats.ttest_ind(responseA, responseB)
运行这段代码得到的 t 统计值为-0.90,p 值为 0.37。不太好。如果我们把数据绘制成图表,我们就能了解正在发生的事情。
分层抽样实验&分析
现在,我们不进行简单的随机抽样,而是使用分层随机抽样,看看分析结果如何变化。
那么我们如何进行分层随机抽样呢?结果这和最初的完全随机抽样非常相似。
步骤如下:
- 定义要从中取样的子群体
- 从每个亚群中进行完全随机抽样
我做这个实验的方法是创建 k 个指数列表,每个指数代表一个我想要取样的亚群。然后,我将它们连接成一个长列表,并使用新的索引列表从原始群体中提取数据。我喜欢这样做,这样我可以跟踪数据帧是如何构建的,但是可能有更有效的解决方案。
现在,我用和上面一样的方法计算响应变量,然后运行
t 检验的代码保持不变:
responseA = stratified_df['response'][stratified_df['A']==1]
responseB = stratified_df['response'][stratified_df['B']==1]stats.ttest_ind(responseA, responseB)
这里的输出是 t 值 2.55 和 p 值 0.011。比原来的完全随机抽样制度好得多。
我可以再次对这些数据进行 t 检验,就像我上面做的那样。然而,现在我已经确保从两个亚群中取样,我可以使用 ANOVA 来解释一些差异并增强信号。
但是,当我们使用子群体的额外信息并对数据进行双向方差分析时,会发生什么呢?
model = ols('response ~ treatment + cities', data = stratified_df).fit()
aov_table = anova_lm(model, typ=1)
print(aov_table) df sum_sq mean_sq F PR(>F)
treatment 1 1.16 1.16 6.89 0.0090
town_size 1 10.82 10.82 64.47 2.75e-15
Residual 997 167.27 0.17 NaN NaN
双向方差分析是估计每个变量(治疗和反应)对反应总误差的贡献。您可以在表的第二列的 sum_sq 项中看到这个输出。基于此,看起来城市变量比治疗变量多贡献了大约 9.4 倍的方差,这基于我如何构建响应变量是有意义的。此外,在这种情况下,我没有获得比传统 t 检验低得多的治疗效果 p 值。那主要是因为两个城市治疗的效果是一样的。当亚组之间的治疗效果相同时,双向方差分析是否优于简单的 t 检验取决于采样数据的确切分布。
如果我们看看这个图,我们就能明白为什么方差分析表现得如此之好。
因为我们使用分层随机抽样增加了我们的分析能力,我们的初始样本量计算在分层随机抽样和完全随机抽样程序之间是不同的。我不会在这里深入探讨这个问题,但从本质上讲,当我们从完全随机抽样转向分层随机抽样时,我们对每个总体方差的估计会发生变化。
结论
这篇文章主要有两点。首先,考虑进行分层随机抽样时,信号可能是非常不同的亚群。第二,当你使用分层随机抽样进行实验时,使用一种可以考虑分类变量的分析方法。
总的来说,分层随机抽样增加了你的分析能力。在最初的完全随机抽样实验中,A/B 测试的信号被未解释的城镇亚人群引入的额外变异所稀释。一旦我考虑了这个亚群,那么 A/B 测试的信号就变得清晰了。
我希望这有助于你的分层随机抽样需求!我已经将我进行分析的 Jupyter 笔记本和一个类似的 R 脚本添加到我的 GitHub 库中。以下是进一步阅读 ANOVAs 和分层随机抽样的一些链接:
- 网上有许多文章介绍了不同类型的采样方法。看这里,这里这里,或者这里。
- 宾夕法尼亚州立大学的这门课程深入研究了分层随机抽样的统计学。
- 如何在 R 和 Python 中对虹膜数据集进行方差分析的示例。
- 如何使用传统的方法和模拟数据进行功率分析。
如何使用 Python 分析调查数据
如何使用 Python 读取 SPSS/SAV 数据,使用权重并执行典型的 SPSS 命令作为频率和交叉表
如果你从事市场调研,你可能还需要处理调查数据。通常这些都是 SAV 或 SPSS 文件。SPSS 对于调查数据的统计分析非常有用,因为变量、变量标签、值和值标签都集成在一个数据集中。使用 SPSS,分类变量易于分析:
不幸的是,SPSS 在处理较大的数据集时速度较慢,自动化的宏系统不够直观,与 Python 相比提供的选项很少。因此,我将向您展示如何使用 Python 分析调查数据。
设置
首先,我们安装pyreadstat
模块,它允许我们将 SPSS 文件作为数据帧pip install pyreadstat
导入。如果您想手动安装它,您可以从这里下载软件包:
将 SAS、SPSS 和 Stata 文件读写到 pandas 数据帧中。
pypi.org](https://pypi.org/project/pyreadstat/)
读取数据
现在,我们将模块导入 Jupyter 笔记本并加载数据集:
import numpy as np
import pandas as pd
import pyreadstatdf, meta = pyreadstat.read_sav('...path\\Surveydata.sav')
df.head(5)
让我们看一下数据框:
Our DataFrame
我们不能从中读出太多,因为我们不知道变量和数字信息意味着什么。元容器包括所有其他数据,如标签和值标签。用meta.column_labels
我们可以打印变量标签:
对于列Sat_overall
,匹配的标签是“您的总体满意度如何?”。通过几个变量,你可以很容易地从列表中分配它。如果我们有数百个变量,整个事情会很混乱。因此,我们首先创建一个字典,以便在必要时可以有选择地显示某一列的正确标签。
meta_dict = dict(zip(meta.column_names, meta.column_labels))
有了meta_dict['Sat_overall']
,我们现在得到了匹配的标签。
未加权数据
在调查中,我们通常对选择特定答案类别的受访者的百分比感兴趣:
df['Age'].value_counts(normalize=True).sort_index()
从输出中,我们只能看到 29%的人投票支持类别 1,33%的人支持类别 2,几乎 38%的人支持类别 3。然而,在字典meta.value_labels
中,我们有所有的值标签:
df['Age'].map(meta.variable_value_labels['Age']).value_counts(normalize=True)
这样看起来更好!38%的受访者超过 50 岁,33%在 30 至 50 岁之间,其余的在 30 岁以下。我个人更喜欢按照价值标签的顺序排序。目前,这些值只是按比例大小排序:
df['Age'].map(meta.variable_value_labels['Age']).value_counts(normalize=True).loc[meta.variable_value_labels['Age'].values()]
完美!这就是我们所需要的,结果与 SPSS“频率”的输出非常匹配。通常,调查数据是根据社会人口特征进行评估的。例如,满意度如何因年龄组而异?为此,我们可以简单地使用交叉表函数:
pd.crosstab(df['Sat_overall'], df['Age'], dropna=True, normalize='columns')
同样,我们不能对输出做太多,所以让我们首先映射值标签:
pd.crosstab(df['Sat_overall'].\
map(meta.variable_value_labels['Sat_overall']), \
df['Age'].map(meta.variable_value_labels['Age']), \
dropna=True, normalize='columns'). \
loc[meta.variable_value_labels['Sat_overall'].values()]. \
loc[:,meta.variable_value_labels['Age'].values()]*100
现在,我们能够解释输出。对于 50 岁以上的人,有最完全满意的顾客。相比之下,30 岁以下的顾客最不满意。使用.loc
功能,我们可以再次在此指定顺序。
加权数据
在调查中,事后通常会发现社会人口特征的分布与客户群的分布并不一致。一开始我们看到三个组几乎是平均分布的。然而,我们知道 50%的顾客年龄在 30 岁以下,25%在 30 到 50 岁之间,其余的在 50 岁以上。因此,我们对数据进行加权以反映这种分布:
weight = np.NaN
df.loc[(df['Age'] == 1), 'weight'] = 0.5/(67/230)
df.loc[(df['Age'] == 2), 'weight'] = 0.25/(76/230)
df.loc[(df['Age'] == 3), 'weight'] = 0.25/(87/230)
但是我们现在如何在计算中考虑这个重量呢?对于频率分布,我们编写一个小的辅助函数:
def weighted_frequency(x,y):
a = pd.Series(df[[x,y]].groupby(x).sum()[y])/df[y].sum()
b = a.index.map(meta.variable_value_labels[x])
c = a.values
df_temp = pd.DataFrame({'Labels': b, 'Frequency': c})
return df_temp
因此,我们得到一个数据帧,其中包含相应的标签(按照从小到大的数字顺序)和相应的百分比频率:
weighted_frequency('Age','weight')
加权分布现在符合我们的客户结构。让我们再来看看满意度分布:
weighted_frequency('Sat_overall','weight')
例如,我们看到在加权分布中,更多的客户不满意。如果我们没有加权,我们会低估我们客户群中的奇怪之处。通过交叉表,可以轻松整合权重:
pd.crosstab(df['Sat_overall']. \
map(meta.variable_value_labels['Sat_overall']), \
df['Age'].map(meta.variable_value_labels['Age']),
df.weight, aggfunc = sum, dropna=True, \
normalize='columns'). \
loc[meta.variable_value_labels['Sat_overall'].values()]. \
loc[:,meta.variable_value_labels['Age'].values()]*100
我们所要做的就是添加权重参数(例如df.weight
)和函数参数aggfunc=sum
。在本例中,加权分布对应于未加权分布,因为组内病例的比率没有变化。
结论
第一步,我们安装了pyreadstat
,一个我们可以将 sav 文件读入 Python 并进一步处理它们的模块。之后,我们看了标签和价值标签是如何分配的,以及分析是如何以一种易于理解的方式呈现的。我们看到 Python 很好地处理了分类数据,并且易于使用。
开源代码库
资料馆:
https://github.com/bd317/surveydata_with_python
笔记本:
https://Github . com/BD 317/Survey Data _ with _ python/blob/master/Github _ Survey _ Data _ upload . ipynb
SPSS-Dataset:
https://Github . com/BD 317/Survey Data _ with _ python/blob/master/Survey Data . sav
如果您喜欢中级和高级数据科学,并且还没有注册,请随时使用我的推荐链接加入社区。
在特定领域应用 BERT 的几个例子
在特定领域中应用 BERT
Photo by Kendal James on Unsplash
2018 年发布了几个新的预训练的情境化嵌入。新的最先进的结果每个月都在变化。伯特是著名的模特之一。在这个故事中,我们将扩展 BERT 来看看我们如何在不同领域问题上应用 BERT。
艾伦人工智能研究所(AI2)对 BERT 进行了进一步研究,并发布了基于 BERT 的 SciBERT,以解决科学数据上的性能问题。它使用来自 BERT 的预训练模型,并通过使用科学出版物(其中 18%的论文来自计算机科学领域,82%来自广泛的生物医学领域)来微调上下文化嵌入。另一方面,Lee 等人从事生物医学领域的工作。他们还注意到,通用的预训练 NLP 模型在特定领域数据中可能不会很好地工作。因此,他们将 BERT 微调为 BioBERT,在生物医学的 NER、关系抽取和问答 NLP 任务中有 0.51% ~ 9.61%的绝对提升。
这个故事将讨论关于 SCIBERT:科学文本的预训练语境化嵌入 (Beltagy 等人,2019), BioBERT:生物医学文本挖掘的预训练生物医学语言表示模型 (Lee 等人,2019)。将涵盖以下内容:
- 数据
- 体系结构
- 实验
数据
SciBERT 和 BioBERT 还为预训练引入了特定领域的数据。Beltag 等人使用从语义学者中随机挑选 1.14M 的论文来微调 BERT 并构建 SciBERT。语料库包括 18%的计算机科学领域的论文和 82%的广义生物医学领域的论文。另一方面,Lee 等人使用 BERT 的原始训练数据来微调 BioBERT 模型,这些数据包括英语维基百科和图书语料库以及领域特定数据,即 PubMed 摘要和 PMC 全文文章。
Training data among models
一些变化被应用在科技文章中以获得成功。ScispaCy 作为 spaCy 的科学专用版本,用于将文档拆分成句子。之后,Beltagy 等人使用 SentencePiece 库为 SciBERT 构建新的单词表,而不是使用 BERT 的词汇表。
Different tokenization method among models.
体系结构
SciBERT 和 BioBERT 都遵循 BERT 模型架构,该架构是多双向转换器,并通过预测屏蔽令牌和下一句来学习文本表示。标记序列将被转换成标记嵌入、分段嵌入和位置嵌入。标记嵌入指的是语境化的单词嵌入,片段嵌入只包括 2 个嵌入,它们或者是 0 或者是 1 来表示第一个句子和第二个句子,位置嵌入存储相对于序列的标记位置。你可以访问这个故事来了解更多关于伯特的事情。
BioBERT Architecture (Lee et al., 2019)
实验
科学伯特(SciBERT)
命名实体识别(NER)和参与者干预比较结果提取(PICO)都是序列标记。依存句法分析(DEP)是预测句子中标记之间的依存关系。分类(CLS)和关系分类(REL)是分类任务。
Evaluation dataset (Beltagy et al., 2019)
Evaluation result among different dataset (Beltagy et al., 2019)
生物医学伯特
从下表中,你可以注意到 BioBERT 在特定领域数据集上的表现优于 BERT。
Comparison between BERT and BioBERT on relation extraction dataset (Lee et al., 2019)
Comparison between BERT and BioBERT on question answering dataset (Lee et al., 2019)
拿走
- 通用的预训练模型在特定领域可能无法达到最先进的结果。因此,需要微调步长来提高目标数据集的性能。
- 在伯特和伯特的基础模型之后,Transformer(多重自我关注)变得越来越有名。我还注意到,BERT 的基本模型保持了最先进的性能。
关于我
我是湾区的数据科学家。专注于数据科学、人工智能,尤其是 NLP 和平台相关领域的最新发展。欢迎在 LinkedIn 上与我联系,或者在 Medium 或 Github 上关注我。
延伸阅读
- 变压器的双向编码器表示(BERT)
- 西伯特 GIT 回购
- BioBERT GIT 回购【1】/【2】
参考
- 贝尔塔吉、科汉和罗。 SCIBERT:科学文本的预训练语境化嵌入。2019
- J.李,尹文伟,金圣贤,金圣贤,苏春河和姜俊杰。 BioBERT:用于生物医学文本挖掘的预训练生物医学语言表示模型。2019
如何将持续学习应用到你的机器学习模型中
通过持续学习提高模型准确性并增强性能
什么是持续学习?
学者和从业者都认为持续学习(CL)是迈向人工智能的基本步骤。持续学习是模型从数据流中持续学习的能力。在实践中,这意味着支持模型在新数据到来时自主学习和适应生产的能力。有些人可能称之为自适应学习或连续自动学习。CL 的想法是模仿人类在其一生中不断获取、调整和转移知识和技能的能力。如你所知,在机器学习中,目标是通过生产环境部署模型。通过持续学习,我们希望使用进入生产环境的数据,并根据新的活动重新训练模型。例如,我们都体验过网飞非常成功的“下一个”推荐系统。网飞推荐系统会在你的最后一集结束后直接推荐一个节目,通常随着时间的推移,你很难抗拒这种诱惑。这种生产模式需要定期重新培训,因为市场上有新电影、新口味和新趋势。通过不断学习,目标是使用输入的数据,并使用它来自动重新训练模型,这样您就可以真正获得高精度并保留高性能的模型。
为什么我们需要不断学习?
答案很简单,数据在不断变化。数据可能会因趋势或用户采取的不同行动而发生变化。例如,亚马逊 2000 年的畅销书是哈利波特。今天,你可能会惊讶地发现,畅销书是一个完全不同的类型:火与怒:特朗普白宫内部。
Why continual learning? Data is changing.
因此,亚马逊将不得不重新训练这种模式,并根据新的数据和趋势向客户推荐新书。更新一点的例子是巨幅下跌前的比特币价格。2017 年,比特币价值 19K 美元。大约一个半月后,降到了 6K 美元。
不仅数据在变化,而且研究人员已经表达了“终身学习仍然是机器学习和神经网络模型的一个长期挑战,因为从非平稳数据分布中不断获取增量可用信息通常会导致灾难性的遗忘或干扰。”持续学习的理由仍然很充分。对于数据科学家来说,持续学习将最终优化模型的准确性,提高模型性能,并通过使模型自适应来节省再培训时间。
不断学习的机器学习管道
Machine learning pipeline
上图展示了在应用持续学习的生产环境中,机器学习管道是什么样子的。你会注意到管道看起来很像任何其他机器学习管道。我们必须有数据,某种验证。这可能包括测试或内部基准,如确定数据质量。也可能是你操作的预处理。
接下来,即将推出的是 AutoML 。持续学习中的 AutoML 是流水线中非常重要的一部分,类似于典型机器学习流水线中的训练步骤。但是,我们将在后面详细讨论。
培训之后,您将做一些模型验证来测试模型,并确保它们都工作良好。在这里,您还可以选择最好的一个,并将其部署到生产环境中。到目前为止,这个管道看起来像一个经典的机器学习管道。为了应用持续学习,我们增加了监控并将循环连接回数据。
Machine learning with closed loop continual learning
将监视在模型部署区域收集的预测。监控完成后,您将清理数据并在需要时贴上标签。但是,对于像推荐系统或预测这样的东西,您将能够在没有人为标记的情况下关闭环路。在标记和清理数据之后,我们将把它移回数据,再次重复训练和验证过程。现在我们已经像飞轮一样闭合了回路。
持续学习管道中的 AutoML
AutoML 是应用持续学习的一个重要组成部分,因为我们处理的是持续不断的数据流。你可以保持简单,用相同的参数重新训练相同的算法,但因为我们仍然希望获得非常高的精度,我们将使用 AutoML。
AutoML 不一定是非常复杂的元学习。你可以只使用超参数优化、开源算法和框架——你会惊讶于它是多么简单。作为你研究的一部分,当你开始研究你的机器学习管道时,你必须选择你的算法空间。例如,如果你在做一个计算机视觉问题,你可能想用迁移学习作为训练算法。通过迁移学习,你有许多预先训练好的模型,你可以用它们来重新训练网络的最后一层,然后部署你的模型。
在这种情况下,你会选择一个流行的预建模型,如 VGG,盗梦空间,ResNet 和其他一些。对于每个模型,我们还必须指定其参数范围。
这可能会变成一个非常大的计算问题。作为一名数据科学家,你应该真正研究什么样的算法和参数对你的机器学习问题有用。
AutoML 链接: AutoKeras , Auto SciKitLearn ,特征工程的特征工具
追踪你的汽车
使用 AutoML,不仅要跟踪生产中的模型,而且要跟踪整个过程,这一点尤为重要。如果你让你的机器学习自动驾驶,你必须确保一切都被跟踪和管理。您需要跟踪一切:您使用的算法类型、超参数是什么、使用的计算类型、内存消耗、指标、准确性等等。假设你今天正在训练 60 个不同的实验。被跟踪的数据可能会在下周尝试重新部署和重新训练模型时使用。
你也可以使用这些信息进行元学习,试图了解什么样的算法对问题有效,这将使每次的实验次数最少。
自动化您的基础设施
关于 AutoML 的另一个关键问题——尤其是深度学习——是自动化你的机器学习基础设施。启动一个深度学习就绪的实例可能需要很多时间(想想 CUDA、依赖项、数据、代码等等)。我们建议在您所有首选的云提供商之上使用 Kubernetes。事实上,您将拥有一个 Kubernetes 集群并运行,这使得部署新的实验变得非常容易。使用 Kubernetes,您可以非常快速地启动许多实验,并跟踪它们以确保所有实验都运行良好。
但是请记住,维护 Kubernetes 集群并不那么简单,可能需要 IT/数据工程团队的额外帮助。
在持续学习管道中部署模型
一旦您训练并选择了具有最佳性能的模型,您的模型就可以部署了。持续学习的一个主要挑战是如何在不影响用户体验和保持高准确性的情况下将新模型部署到相同的环境中。
为持续学习部署模型与经典的模型部署有点不同。通常,即使是一个数据科学家也能够部署一个模型,但是因为这是自动化的,我们必须非常小心。正如您不会将一个有缺陷的软件部署到生产环境中一样,您也不会部署一个没有被成功训练和验证的模型。为了确保您的新模型运行良好,您将在部署之前和部署期间对旧数据进行测试。此外,您还需要监控系统的性能和健康状况。
现在,在软件开发中,有很多不同的方法来部署新软件。对于机器学习来说,这个领域仍然很新,但是我们推荐使用金丝雀部署技术。Canary 是一种引入新软件版本的技术,以某种方式影响部分用户,根据测试逐渐增加用户数量。使用这种技术将会逐渐将模型部署到更大的用户子集。
在实现层面——我们建议使用 Kubernetes 和 Istio 进行模型部署,这样您就可以进行 A/B 测试,并确保您的模型部署良好。我们的博客上还有一个关于如何使用 Kubernetes 部署机器学习模型的指南。
持续学习管道的监控
随着持续学习,监控是机器学习的一个特别重要的部分。您需要确保,如果您的模型发生了不好的事情,或者如果发送到您的模型的数据被破坏,您有一种机制可以得到警告。
最常见的情况是,一个数据科学家会同时管理几个机器学习管道。所以警报设置至关重要。一旦将新模型部署到生产环境中,目标就是为数据科学家或数据工程师提供监控机器学习模型所需的控制和透明度。为了能够自动部署模型的新版本,您必须监控输入数据,以检测数据漂移和异常。监测对于预测数据也很重要,以确保高性能和准确性。
除了 AlertManager 之外,Kubernetes 或 Prometheus 中也有很好的工具,可以用来监控所有的输入数据。你应该利用云服务和 Kubernetes 来自动化你的机器学习基础设施和实验。
触发并重新训练您的模型,以便继续学习
连续学习 ML 管道的最后一步是触发再训练并结束循环。您的 ML 渠道为持续学习做好了准备:
- 你有数据
- 实验正在进行训练
- 预测正在被收集和监控
- 正在清理新数据
接下来,您必须决定重新训练您的模型的触发器。有几种方法可以做到这一点。我们的客户会定期重新培训他们的模型。例如,对于推荐系统或广告,我们看到团队每 30 分钟重新培训一次。您也可以考虑只根据新的数据来重新训练模型。
其他方法是跟踪和监控模型衰减和模型偏差、低置信度以及生产环境中触发再训练的任何其他类型的警报。最重要的是,如果你自动触发了机器学习管道,你应该跟踪和验证触发器。不知道您的模型何时被重新训练会导致重大问题。您应该始终控制模型的再训练,即使这个过程是自动化的。这样,您就可以在生产环境中理解和调试模型。
关闭 ML 循环
一旦你的自动化、部署和监控系统到位,你就能完成机器学习的循环。您的模型将不断学习,并自动适应新的数据和趋势。不仅你的模型精度会自动提高,而且总体上你的模型在应用程序中的表现会更好。
如何申请数据科学工作
(或者任何技术类的工作,真的。)
剧透:让招聘人员或招聘经理的工作更容易。
我为什么要写这个?:我们(Data Eng & Data Science @ Kik)正在招聘全职员工和合作者。最近几个月,我审查了大约 600 份提交的简历中的 300 份(有几个职位空缺)。我想帮助你,我最后四行的忠实读者,避免愚蠢的错误。
**你为什么会读这个?😗*如果你是因为在申请了 Kik 的一个职位后在谷歌上搜索了我,那么恭喜你,否则:
在过去十年里,我花了 1000 多个小时阅读简历和进行面试(写简历、准备和参加面试)。这些齿尖经过了现场测试。
步骤 1:简历
你得到了我 30 秒的注意力,有机会赢得 3 分钟。让我相信,在你所拥有的技能和经验与所需的技能和经验之间,至少有一部分是匹配的,我应该继续阅读。就像博客文章中折叠上方的文字一样。(就在这里结束 iianm。简历的第一部分应该是非常简短的声明,说明你是谁,你擅长什么,你想做什么。(见下面链接中的简历模板)
你应该在简历上花多少时间。
大多数从事技术行业的人每 3-5 年找一次工作。每隔几年花 15-20 个小时润色你的简历是没问题的。我说的不是“越来越擅长<技能 >”。我说的是修改描述你技能的文件。你将对格式进行微小的修改,将它发送给朋友进行校对和反馈,改变措辞以符合时态,确保时态、语法和标点符号是统一的。
会根据“关注细节”来评判你,关注细节。你申请的前 5 份工作应该受益于一个小时的调整你的简历,以确保你突出了与特定工作相关的经验和技能。
最重要的不要就是:不要掺水。
我怎么强调这一点都不为过。
你申请的是一份技术工作——“Microsoft Word&Google Docs”是掺水,是同义反复(毕竟我在看你打出来的简历)。
再次强调:不要用水稀释!
更多不要的,请看简历错误宾果。(根据真实故事改编)
如何合理地“充实”一份简历
如果你刚刚起步,你没有什么成就可以夸耀,可能会有几十个,有时几百个申请人申请同一个职位。
脱颖而出。 如果你有一个有趣的爱好,一些你引以为豪的事情,一些你致力于的事情,一些你赢得的东西,一个副业,志愿活动,组织,成就等等。-不要害羞。突出显示它们。
网络。 如果一个普通的熟人给我指出你的简历,你基本上已经通过了第一次筛选,恭喜你。更好地连接
变好。如果你有时间,希望你在你感兴趣的领域找一份工作,在那个领域做些事情。(Kaggle、开源项目、课程等。).关键建议是“演示完成”。没有"搞定,就不能拼成"聪明,漂亮,搞定
不要忘记修改你的简历:
当你刚从学校毕业时,加入一堆卡格尔比赛,这很好。但是现在,几年过去了,你有了更多的工作经验;更新你的简历并不意味着仅仅添加最新的成就,也意味着删除旧的不那么令人印象深刻的东西。也许只保留排名最高的那一场 Kaggle 比赛。
如果你已经很久没有使用一门语言了,并且不想被问到,那么帮大家一个忙,把它从你的简历中删掉。(你中学学的法语也是一样)
去面试!
你可能认为一旦你得到了面试机会,简历就不重要了。这几乎是真的。它会绊倒你;例如,我可以问你一些新的特性,或者一些你已经有一段时间没有使用的语言 ******* 的幕后细节。
第 2 部分:准备和面试
这是一篇关于申请的博客,我附上了面试技巧,因为准备应该是申请不可或缺的一部分。
以前
准备面试就像准备考试一样。我面试过的应届毕业生的平均得分比业内资深人士的平均得分高很多。对此,我唯一的解释是,学生们在学习上更加紧跟时代。
如果你要参加白板面试,花 20 美元买一个小白板和记号笔(最好是细的),在上面练习。感觉不一样,你不想在压力下第一次做。(面试时带上记号笔会让你的白板空间翻倍,给面试官留下深刻印象。)
在 25–30 分钟内练习完全解决面试问题(见下文)。
聊天 有人说面试是你证明自己的机会。这只说对了一半。面试也是你了解自己是否喜欢这个职位的机会。对我面试时的精神状态最有帮助的建议是:
你可能会和面试你的人一起度过你的工作日,让他们让你相信他们很好,你们会相处得很好。让他们试着通过你的关卡。
技术问题。
确保你理解了问题,提出问题来澄清它,也许走过一个微小的例子。
然后— 开始。我不是说马上开始编码,不要那样做。在你编码之前解决问题,检查你的解决方案。然后,如果你被要求编写代码,就去做。抽象地解决问题表明你很聪明。
编码表明你把事情做好了。
用几个例子展示你的解决方案,表明你关注细节。
故障排除
倾听暗示。
面试官会给你提示。不要错过他们。接受暗示会让你更好地找到解决方案(并为你赢得*“善于接受反馈”*分)。面试官可能熟悉一些错误的解决方案,并希望引导你离开。或者他们可能在寻找特定的解决方案。
如果你被卡住了,接受提示。如果你认为你的解决方案很好,但是面试官的暗示导致了不同的解决方案,那么——这是一个艰难的情况。我个人倾向于候选人明确认识到这一点。嗯,看起来这和我正在尝试的不相容,你介意我在尝试你的建议之前再花 2-3 分钟在这个方向上吗
摆脱困境——放松、休息,然后重启
有时候人们会陷入困境。他们可能自己意识到了这一点(他们很幸运),或者被面试官推到了死胡同(压力很大)。许多人会说:“等一下,让我重新开始。”这太好了,除此之外,他们不会真的重新开始!!他们想着自己,想着自己把问题弄错了。
如果我把它做成卡通形式,它会是这样的:
野狼🦊正拿着锤子和炸弹🔨 💣,想象着💭他自己试图把炸弹锤进一个盒子里。🔨 💣 🎁这个盒子太小了。
然后是思想泡沫中的郊狼💭停止锤击 🛑🔨又抬眼,思考。💭和一个更小的思想泡泡💭💭与另一只小野狼一起出现🦊它内部命中了炸弹。这导致了第一只假想的郊狼🦊重新开始锤击🔨,这导致了真正的狡猾🦊重新开始愉快地敲打他的(真正的)炸弹💣。三只土狼都停下来,交换了一下眼神,然后看向镜头。所有炸弹都会爆炸。**
重启是最难的技能,尤其是在压力下。练习解决有时间压力的问题,学会摆脱困境。你能在面试中做到这一点会得到额外的加分。你可以这样做:你说“等一下,让我重新开始。”
然后你闭上眼睛,默默地😃)数 5 次呼吸。如果你觉得尴尬,3 也可以。不要想问题!(必要时边呼吸边数)。睁开你的眼睛,微笑,重述问题,然后真正重新开始。
总而言之:
不要浪费你或我的时间。保留有影响的语句,去掉其余的。也许写简历 V1 包括一切,然后找出什么是上面的栏“令人印象深刻”和修剪其余的。
脱颖而出,不要害羞。(但是不要在简历上做虚假承诺) **练习,**然后再多练一些,然后在白板上带着时间压力练习。
结语+链接
有一些关于如何写简历和如何准备面试的令人惊讶的帖子,你也可以看看。史蒂夫·耶格关于简历的建议是永恒的。(除了关于纯文本的部分)。Lazlo Bock 关于简历的建议是最好的。
更有一些不要的在恢复错误宾果格式。(似曾相识)
下面是一份 元简历 。我已经用该文本的描述替换了该文本。为了每一件美好的事情,请在发送前替换掉元文本。
如何将机器学习和深度学习方法应用于音频分析
作者:Niko Laskaris,面向客户的数据科学家, Comet.ml
要查看本文末尾的代码、训练可视化和关于 python 示例的更多信息,请访问 Comet 项目页面。
介绍
虽然许多关于深度学习的写作和文献都涉及计算机视觉和自然语言处理(NLP) ,但音频分析——一个包括自动语音识别(ASR) 、数字信号处理以及音乐分类、标记和生成的领域——是深度学习应用的一个不断增长的子域。一些最受欢迎和最广泛的机器学习系统,虚拟助手 Alexa,Siri 和 Google Home,很大程度上是建立在可以从音频信号中提取信息的模型之上的产品。
我们在 Comet 的许多用户都在从事音频相关的机器学习任务,如音频分类、语音识别和语音合成,因此我们为他们构建了工具,使用 Comet 的元机器学习平台来分析、探索和理解音频数据。
使用 Comet 进行音频建模、训练和调试
这篇文章专注于展示数据科学家和人工智能从业者如何使用 Comet 在音频分析领域应用机器学习和深度学习方法。为了理解模型如何从数字音频信号中提取信息,我们将深入探讨一些用于音频分析的核心特征工程方法。然后,我们将使用 Librosa ,一个用于音频分析的伟大 python 库,来编写一个简短的 python 示例,在 UrbanSound8k 数据集上训练神经架构。
音频的机器学习:数字信号处理,滤波器组,梅尔频率倒谱系数
构建机器学习模型来分类、描述或生成音频通常涉及输入数据是音频样本的建模任务。
来自 UrbanSound8k 的音频数据集样本的示例波形
这些音频样本通常表示为时间序列,其中 y 轴度量是波形的幅度。振幅通常作为最初拾取音频的麦克风或接收器设备周围的压力变化的函数来测量。除非有与音频样本相关联的元数据,否则这些时间序列信号通常将是拟合模型的唯一输入数据。
查看下面的样本,这些样本取自 Urbansound8k 数据集中的 10 个类别中的每一个类别,从目测可以清楚地看出,波形本身可能不一定产生清晰的类别识别信息。考虑发动机怠速、汽笛和手提钻的波形,它们看起来非常相似。
事实证明,从音频波形(以及一般的数字信号)中提取的最佳特征之一自 20 世纪 80 年代以来一直存在,并且仍然是最先进的:梅尔频率倒谱系数(MFCCs),由 Davis 和 Mermelstein 于 1980 年提出。下面我们将从技术上讨论 MFCCs 是如何产生的,以及为什么它们在音频分析中有用。这部分有些技术性,所以在开始之前,我们先定义几个与数字信号处理和音频分析相关的关键术语。如果你想更深入地了解,我们将链接到维基百科和其他资源。
混乱但有用的术语
在信号处理中,采样是将连续信号缩减为一系列离散值。采样频率或速率是在一定时间内采集的样本数量。高采样频率导致较少的信息损失,但是计算费用较高,而低采样频率具有较高的信息损失,但是计算快速且便宜。
声波的振幅是其在一段时间(通常是时间)内变化的量度。振幅的另一个常见定义是变量极值之间的差值大小的函数。
傅立叶变换将时间函数(信号)分解成组成频率。同样,音乐和弦可以通过其组成音符的音量和频率来表达,函数的傅立叶变换显示了基础函数(信号)中每个频率的振幅(量)。
顶部:数字信号;下图:信号的傅立叶变换
傅立叶变换有多种变体,包括短时傅立叶变换,它在 Librosa 库中实现,涉及将音频信号分割成帧,然后对每帧进行傅立叶变换。一般来说,在音频处理中,傅立叶变换是将音频信号分解成其组成频率的一种优雅且有用的方式。
*资源:到目前为止,我找到的最好的傅立叶变换视频来自 3Blue1Brown *
在信号处理中,周期图是对信号频谱密度的估计。上面的周期图显示了大约 30Hz 和大约 50Hz 的两个正弦基函数的功率谱。傅立叶变换的输出可以被认为是(不完全)本质上的周期图。
时间序列的功率谱是一种将功率分布描述为组成该信号的离散频率分量的方式。一个信号的统计平均值,通过它的频率含量来测量,被称为它的频谱。数字信号的频谱密度描述了信号的频率成分。
梅尔标度是一种由听众判断彼此距离相等的音高标度。mel 标度和正常频率测量之间的参考点是通过将 1000 mels 的感知音调分配给 1000 Hz 来任意定义的。在大约 500 Hz 以上,越来越大的音程被听众判断为产生相等的音高增量。名称 mel 来自单词 melody,表示音阶基于音高比较。
将 f 赫兹转换成 m 英里的公式是:
倒谱是对信号的估计功率谱的对数进行傅立叶变换的结果。
Urbansound8k 数据集中音频样本的 Mel 频谱图
频谱图是信号频谱随时间变化的直观表示。考虑频谱图的一个好方法是将一些时间间隔数字信号的周期图叠加起来。
耳蜗内耳的螺旋腔,包含耳蜗器官,它对声音振动产生神经冲动。
音频预处理:数字信号处理技术
数据集预处理、特征提取和特征工程是我们从底层数据中提取信息的步骤,这些信息在机器学习上下文中应该对预测样本的类别或某些目标变量的值有用。在音频分析中,这个过程很大程度上是基于寻找音频信号的成分,这些成分可以帮助我们将其与其他信号区分开来。
如上所述,MFCCs 仍然是从音频样本中提取信息的现有技术工具。尽管 Librosa 之类的库为我们提供了一个 python 命令行程序来计算音频样本的 MFCCs,但底层的数学有点复杂,所以我们将一步一步地讲解它,并包含一些有用的链接以供进一步学习。
计算给定音频样本的 MFCCs 的步骤:
- 将信号分割成短帧(时间)
- 计算每帧功率谱的周期图估计
- 将 mel 滤波器组应用于功率谱,并对每个滤波器中的能量求和
- 对对数滤波器组能量进行离散余弦变换(DCT)
关于 MFCC 推导和计算的精彩附加阅读可以在博客文章这里和这里找到。
- 将信号分割成短帧
将音频信号分割成短帧是有用的,因为它允许我们将音频采样成离散的时间步长。我们假设在足够短的时间尺度上,音频信号不会改变。短帧持续时间的典型值在 20-40 毫秒之间。通常每帧重叠 10-15 毫秒。
注意,重叠的帧会使我们最终生成的特征高度相关。这就是为什么我们必须在最后进行离散余弦变换的基础。
2。计算每一帧的功率谱
一旦我们有了帧,我们需要计算每个帧的功率谱。时间序列的功率谱描述了组成该信号的频率分量的功率分布。根据傅立叶分析,任何物理信号都可以分解成许多离散的频率,或连续范围内的频谱。根据频率成分分析的特定信号的统计平均值称为其频谱。
我们将短时傅立叶变换应用于每一帧,以获得每一帧的功率谱。
3。将 mel 滤波器组应用于功率谱,并对每个滤波器的能量求和
一旦我们有了功率谱,我们还有一些工作要做。人的耳蜗不能很好地辨别附近的频率,并且这种影响只会随着频率的增加而变得更加明显。 mel-scale 是一种工具,它允许我们比线性频带更接近人类听觉系统的响应。
Source: Columbia
从上面的可视化中可以看出,mel 滤波器随着频率的增加而变宽,我们不太关心较高频率下的变化。在低频时,差异对人耳来说更明显,因此在我们的分析中更重要,滤波器较窄。
通过对我们的输入数据应用傅立叶变换得到的我们的功率谱的幅度,通过将它们与每个三角形 Mel 滤波器相关联而被装箱。通常应用该宁滨,使得每个系数乘以相应的滤波器增益,因此每个 Mel 滤波器保持代表该通道中频谱幅度的加权和。
一旦我们有了滤波器组能量,我们就取每个能量的对数。这是由人类听觉限制推动的另一个步骤:人类无法感知线性范围内的音量变化。要使声波的感知音量加倍,声波的能量必须增加 8 倍。如果一个声波已经是高音量(高能量),那么该波能量的巨大变化听起来不会有很大的不同。
4。对对数滤波器组能量进行离散余弦变换
因为我们的滤波器组能量是重叠的(见步骤 1),所以它们之间通常有很强的相关性。进行离散余弦变换有助于去相关能量。
对我们来说,值得庆幸的是, Librosa 的创建者已经抽象出了大量的这种数学,并使得为你的音频数据生成 MFCCs 变得很容易。让我们通过一个简单的 python 示例来展示这种分析的实际效果。
范例项目:Urbansound8k + Librosa
我们将为 UrbanSound8k 数据集拟合一个简单的神经网络(keras + tensorflow backend)。首先,让我们加载我们的依赖项,包括 numpy、pandas、keras、scikit-learn 和 librosa。
#### Dependencies ######## Import Comet for experiment tracking and visual tools
from comet_ml import Experiment
####import IPython.display as ipd
import numpy as np
import pandas as pd
import librosa
import matplotlib.pyplot as plt
from scipy.io import wavfile as wavfrom sklearn import metrics
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import train_test_split from keras.models import Sequential
from keras.layers import Dense, Dropout, Activation
from keras.optimizers import Adam
from keras.utils import to_categorical
首先,让我们创建一个 Comet 实验作为我们所有工作的包装。我们将能够捕获任何和所有工件(音频文件、可视化、模型、数据集、系统信息、培训指标等。)自动。
experiment = Experiment(api_key="API_KEY",
project_name="urbansound8k")
让我们加载数据集,并从数据集中为每个类获取一个样本。我们可以使用 Comet 从视觉和听觉上检查这些样本。
# Load dataset
df = pd.read_csv('UrbanSound8K/metadata/UrbanSound8K.csv')# Create a list of the class labels
labels = list(df['class'].unique())# Let's grab a single audio file from each class
files = dict()
for i in range(len(labels)):
tmp = df[df['class'] == labels[i]][:1].reset_index()
path = 'UrbanSound8K/audio/fold{}/{}'.format(tmp['fold'][0], tmp['slice_file_name'][0])
files[labels[i]] = path
我们可以使用 librosa 的 display.waveplot 函数查看每个样本的波形。
fig = plt.figure(figsize=(15,15))# Log graphic of waveforms to Comet
experiment.log_image('class_examples.png')
fig.subplots_adjust(hspace=0.4, wspace=0.4)
for i, label in enumerate(labels):
fn = files[label]
fig.add_subplot(5, 2, i+1)
plt.title(label)
data, sample_rate = librosa.load(fn)
librosa.display.waveplot(data, sr= sample_rate)
plt.savefig('class_examples.png')
我们将把这个图形保存到我们的彗星实验中。
# Log graphic of waveforms to Comet
experiment.log_image('class_examples.png')
接下来,我们将记录音频文件本身。
# Log audio files to Comet for debugging
for label in labels:
fn = files[label]
experiment.log_audio(fn, metadata = {'name': label})
一旦我们将样本记录到 Comet,我们就可以直接从 UI 中监听样本、检查元数据等等。
预处理
现在我们可以从数据中提取特征。我们将使用 librosa,但是我们也将展示另一个实用程序 scipy.io,用于比较和观察正在发生的一些隐式预处理。
fn = 'UrbanSound8K/audio/fold1/191431-9-0-66.wav'
librosa_audio, librosa_sample_rate = librosa.load(fn)
scipy_sample_rate, scipy_audio = wav.read(fn)print("Original sample rate: {}".format(scipy_sample_rate))
print("Librosa sample rate: {}".format(librosa_sample_rate))
原始采样率:48000
Librosa 采样率:22050
Librosa 的 load 函数会自动将采样率转换为 22.05 KHz。它还将归一化-1 和 1 之间的位深度。
print('Original audio file min~max range: {} to {}'.format(np.min(scipy_audio), np.max(scipy_audio)))print('Librosa audio file min~max range: {0:.2f} to {0:.2f}'.format(np.min(librosa_audio), np.max(librosa_audio)))
原始音频文件最小~最大范围:-1869 到 1665
自由音频文件最小~最大范围:-0.05 到-0.05
Librosa 还将音频信号从立体声转换为单声道。
plt.figure(figsize=(12, 4))
plt.plot(scipy_audio)
plt.savefig('original_audio.png')
experiment.log_image('original_audio.png')
原始音频(注意是立体声——两个音频源)
# Librosa: mono track
plt.figure(figsize=(12,4))
plt.plot(librosa_audio)
plt.savefig('librosa_audio.png')
experiment.log_image('librosa_audio.png')
Librosa 音频:转换为单声道
使用 Librosa 从音频中提取 MFCCs】
还记得我们之前为了理解梅尔频率倒谱系数而经历的所有数学运算吗?使用 Librosa,下面是如何从音频中提取它们(使用我们上面定义的 librosa_audio)
mfccs = librosa.feature.mfcc(y=librosa_audio, sr=librosa_sample_rate, n_mfcc = 40)
就是这样!
print(mfccs.shape)
(40, 173)
Librosa 计算了 173 帧音频样本的 40 个 MFCCs。
plt.figure(figsize=(8,8))
librosa.display.specshow(mfccs, sr=librosa_sample_rate, x_axis='time')
plt.savefig('MFCCs.png')
experiment.log_image('MFCCs.png')
我们将定义一个简单的函数来提取数据集中每个文件的 MFCCs。
def extract_features(file_name):audio, sample_rate = librosa.load(file_name, res_type='kaiser_fast')
mfccs = librosa.feature.mfcc(y=audio, sr=sample_rate, n_mfcc=40)
mfccs_processed = np.mean(mfccs.T,axis=0)
return mfccs_processed
现在我们来提取特征。
features = []# Iterate through each sound file and extract the features
for index, row in metadata.iterrows():file_name = os.path.join(os.path.abspath(fulldatasetpath),'fold'+str(row["fold"])+'/',str(row["slice_file_name"]))
class_label = row["class"]
data = extract_features(file_name)
features.append([data, class_label])# Convert into a Panda dataframe
featuresdf = pd.DataFrame(features, columns=['feature','class_label'])
我们现在有一个数据帧,其中每行有一个标签(类)和一个特征列,由 40 个 MFCCs 组成。
featuresdf.head()
featuresdf.iloc[0]['feature']
数组([-2.1579300e+02,7.1666122e+01,-1.3181377e+02,-5.2091331e+01,-2.2115969e+01,-2.1764181e+01,-1.1183747e+01,1.8912683e+01,6.7266388e+00,1.40
现在,我们已经成功地从底层音频数据中提取了我们的特征,我们可以建立和训练一个模型。
模型建立和训练
我们首先将 MFCCs 转换成 numpy 数组,并对分类标签进行编码。
from sklearn.preprocessing import LabelEncoder
from keras.utils import to_categorical# Convert features and corresponding classification labels into numpy arrays
X = np.array(featuresdf.feature.tolist())
y = np.array(featuresdf.class_label.tolist())# Encode the classification labels
le = LabelEncoder()
yy = to_categorical(le.fit_transform(y))
我们的数据集将被分成训练集和测试集。
# split the dataset
from sklearn.model_selection import train_test_split x_train, x_test, y_train, y_test = train_test_split(X, yy, test_size=0.2, random_state = 127)
让我们定义并编译一个简单的前馈神经网络架构。
num_labels = yy.shape[1]
filter_size = 2def build_model_graph(input_shape=(40,)):
model = Sequential()
model.add(Dense(256))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(256))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(num_labels))
model.add(Activation('softmax'))
# Compile the model
model.compile(loss='categorical_crossentropy', metrics=['accuracy'], optimizer='adam') return modelmodel = build_model_graph()
让我们来看一个模型总结,并计算训练前的准确性。
# Display model architecture summary
model.summary()# Calculate pre-training accuracy
score = model.evaluate(x_test, y_test, verbose=0)
accuracy = 100*score[1]
print("Pre-training accuracy: %.4f%%" % accuracy)
训练前准确率:12.2496%
现在是时候训练我们的模型了。
from keras.callbacks import ModelCheckpoint
from datetime import datetime num_epochs = 100
num_batch_size = 32model.fit(x_train, y_train, batch_size=num_batch_size, epochs=num_epochs, validation_data=(x_test, y_test), verbose=1)
及时完成的培训:
甚至在训练完成之前,Comet 就记录了我们实验的关键信息。我们可以从 Comet UI 中实时可视化我们的精度和损耗曲线(注意橙色旋转轮表示训练正在进行中)。
彗星的实验可视化仪表板
一旦经过训练,我们就可以在训练和测试数据上评估我们的模型。
# Evaluating the model on the training and testing set
score = model.evaluate(x_train, y_train, verbose=0)
print("Training Accuracy: {0:.2%}".format(score[1]))score = model.evaluate(x_test, y_test, verbose=0)
print("Testing Accuracy: {0:.2%}".format(score[1]))
训练准确率:93.00%
测试准确率:87.35%
结论
我们的模型已经训练得相当好了,但可能还有很大的改进空间,也许可以使用 Comet 的超参数优化工具。在少量代码中,我们已经能够从音频数据中提取数学上复杂的 MFCC,建立和训练神经网络以基于这些 MFCC 对音频进行分类,并在测试数据上评估我们的模型。
如何在 Android 应用中应用机器学习(ML)
机器学习是人工智能(AI)的一种应用,它使软件能够在没有人类干预的情况下自动学习、探索和设想结果。机器学习已经在许多领域得到应用,并且正在积极地服务于移动应用开发。
在 Android 应用程序中应用机器学习有多种方式。最合适的方式依赖于你想要在机器学习的辅助下破解的工作或任务。
机器学习算法可以对目标用户行为模式进行分析,并有搜索请求来提出建议和推荐。它广泛用于移动电子商务应用。а视频和音频识别甚至是 Snapchat 等娱乐领域使用的一种 ML。
它还可以用于面部或指纹识别,以简化身份验证。否则,你可以在你的移动应用程序中添加聊天机器人,这种应用程序已经变得很受欢迎,如苹果 Siri 。
根据 bccresearch 的研究,2017 年全球机器学习市场总额为 14 亿美元,预计到 2022 年将达到 88 亿美元。机器学习 vs 人工智能也是数据分析师争论最多的话题。
技术专业人士甚至通过在 Android 应用中启用 ML 来优化搜索过程。通过增加拼写纠正、语音搜索或搜索程序,你的目标用户会变得更自然,更少烦恼。
面向移动应用的机器学习
移动应用开发者可以从机器学习(ML)在整个行业提供的创新转型中受益匪浅。这是可能的,因为移动应用程序带来的技术能力支持更流畅的用户界面和体验,并为企业提供突出的功能,如提供精确的基于位置的建议或立即检测慢性疾病。
如今,人们希望他们的体验绝对个性化。所以,仅仅创建一个高质量的应用程序是不够的,你甚至必须让你的目标用户坚持使用你的移动应用程序。
在这里,机器学习可以帮助你。机器学习技术可以将你的移动应用翻新到用户的视野中。
如何制作一个机器学习 App
制作 ML 应用程序是一个迭代过程,涉及用目前观察到的内容和您希望模型预见的解决方案来构建核心机器学习问题。接下来,您需要收集、清理和过滤数据,提供结果,并进一步利用模型为新生成的数据实例生成所需答案的预测。
一些顶级的机器学习应用-
1)网飞
在网飞,他们利用机器学习算法。它通过使用线性回归和逻辑回归以及更多此类算法,提供了精确、个性化的参考。
网飞应用程序使用多种多样的内容,分为品种、演员、用户和评论家的评论、时间跨度、年份等等,以提供给他们的观众。所有这些信息都会进入机器学习算法。
网飞的人工智能算法是通过跟踪用户行为的用户动作来训练的。它监控我看什么电视节目或者我在网上提供什么类型的评论。机器学习算法熟悉这种用户行为,以提供非常个性化的内容。
2) 火绒
我们知道 tinder 是一款帮助寻找约会对象的手机应用。它使用机器学习算法来找到精确的匹配。它使用发布的图片等信息,随机展示它们,并分析它们被浏览的频率,这有助于应用程序通过将最常观察到的照片放在最前面来重新排序你的照片。这一创新功能增加了用户发现理想匹配的机会。
3) 谷歌地图
谷歌地图利用机器学习寻找停车位。它使用数据分析技术来做到这一点。
谷歌的研究人员从一个非常大的人群样本中收集和研究数据。他们问他们需要多长时间以及他们在寻找停车位时是否遇到困难。他们通过创建不同于那些共享其位置信息的人的训练模型来获取、聚集和使用这些数据。
机器学习进一步通过 Tensorflow 在 Android 移动应用程序上应用流程,tensor flow 是一个基本的 ML 框架。
如何将机器学习应用到 Android 上
有许多机器学习框架可用,我们在这里以 Tensorflow 为例。
TensorFlow 是谷歌的开源库,在 Android 中用于实现机器学习。TensorFlow Lite 是 TensorFlow 针对移动设备的轻量级解决方案。它支持使用低延迟的设备上 ML 推断,这就是它非常快速的原因。它非常适合移动设备,因为它采用较小的二进制大小,甚至通过利用 Android 神经网络 API 支持硬件加速。
在 Android 应用程序中使用 tensor flow Lite
下面是 android TensorFlow 机器学习实例总结,以及如何将机器学习应用到 android 上。要使用 TensorFlow Lite 执行模型,您必须将模型更改为模型(。tflite),这是 TensorFlow Lite 认可的。使用 TensorFlow Lite 时重要的事情是建立一个模型(。这与标准张量流模型截然不同。
通过获得模型和标签文件,可以在 Android 应用程序中启动和标记文件,以便通过利用所需的 TensorFlow Lite 库来加载所需的模型和预测输出。
我们拥有通过使用 TensorFlow Lite 构建完整的运行样本应用程序的经验,该应用程序旨在用于所需的对象检测。
在 Android 上训练 TensorFlow 模型
训练需要大量数据的张量流模型可能需要更长的时间。然而,有一种方法可以大大缩短这个过程,而不需要巨大的 GPU 处理能力和千兆字节的图像。迁移学习是使用先前训练好的模型并对其进行再训练以建立新模型的行为过程。
您可以按照以下步骤进行培训-
步骤 1:收集培训数据
步骤 2:将数据转换成所需的图像
第三步:创建图像文件夹,并将它们分组
步骤 4:用新图像重新训练模型
第 5 步:为无障碍移动设备优化模型
第六步:嵌入。tflite 文件到应用程序中
步骤 7:在本地运行应用程序,观察它是否检测到图像
使用机器学习的入门难度正在变得不那么显著。许多公司已经创建了训练有素的机器学习 API,您可以立即开始使用:
一些训练有素的机器学习服务和 API
Google Play 服务——移动视觉应用编程接口
机器学习服务的主要群体被创建到 Google Play 服务 SDK 中。这意味着任何 Android 开发者都可以在他们的应用中使用这些服务。 谷歌的云视觉 API 就是其中一个例子,它让开发者能够使用 Android 摄像头来感知人脸、检查条形码和识别文本。
ML Rest 服务——谷歌云 ML API
rest 服务训练有素,随时可以用于智能任务。有许多这样的休息服务可供选择,既有免费的也有付费的。
Google 的 ML 平台由翻译、语音识别、NLP 和工作列表 API 组成,积累到 REST 版本中。要开始使用 Google ML 平台,您只需要一个 Google 云平台帐户来登录和使用服务。
REST Vision API 支持多种请求,包括与标签、文本、图像属性等相关的信息。
前进
机器学习服务 使智能平台能够协助你创建、训练和托管所需的预测模型。一旦你接触到这些平台,它们就会变得柔软且易于使用。少数缺点是从一开始就设置机器学习应用程序所需的各种算法和配置的压倒性景观。然而,如果您已经掌握了机器学习开发的最新知识,那么高级服务将提供强大而足智多谋的计算资源,来进行准确的数据分析以及高度精确的预测。
如何对表格数据应用自我监督:介绍 dfencoder
Have a slice of cake. You’ve earned it.
日常数据科学家的去噪自动编码器。
2016 年,脸书首席 AI 科学家严乐存打了个比方:
“如果智能是一种蛋糕……无监督学习是 génoise,蛋糕的大部分。”
—颜乐存,深度学习与 AI 的未来,2016
他详细阐述了这个类比,将监督学习比作蛋糕上的糖衣,将强化学习比作顶端的樱桃。
2019 年,他更新了他的类比,将无监督学习修正为自监督学习。
LeCun’s updated cake analogy slide, presented at the 2019 IEEE International Solid-State Circuits Conference.
自我监督学习
无监督学习是机器学习中一个古老且众所周知的问题;乐存选择将其替换为他蛋糕类比中的明星,这不是他应该掉以轻心的事情!
如果你深入自我监督学习的定义,你会开始发现它实际上只是一种无监督学习的方法。由于这十年来机器学习的许多突破都是基于监督学习技术,当研究人员将一个无监督的问题重新构建为一个有监督的问题时,无监督问题中的成功往往会出现。具体来说,在自我监督学习中,我们找到了一种不需要人工标注器就能生成标签的聪明方法。
一个简单的例子是称为下一步预测的技术。给定一个序列(例如,文字或视频帧),模型可以预测下一步。因为我们已经有了序列,所以没有必要让人类注释者创建标签;我们可以只在步骤t-1截断序列,并使用步骤 t 作为“标签”(或目标)来优化我们的监督学习算法。
下一步预测是一个简单的例子,但是在自我监督技术的爆炸领域中有一整套技巧。
去噪自动编码器:新狗的老把戏?
You can’t teach an old dog new tricks, but denoising autoencoders have been around for a long time.
严乐存自己在 1987 年提出了去噪自动编码器(DAE)的概念,他的工作在 2000 年的和 2010 年的的该领域正在进行的研究中被引用。
这个想法与经典自动编码器有关,但有一个有趣的转折:与经典的模型输入等于监督目标的设置不同,我们在将每个例子输入模型之前,对其进行破坏或添加噪声。目标是示例的未损坏版本。
Visual example: We can add noise to an MNIST image and use the un-altered version as a target to train a neural network.
多元解释
在无监督学习的情况下,无监督模型的任务是学习样本在特征空间中的分布;这种分布可以理解为特征空间中的一个流形。
通过破坏输入,我们获取示例并人为地将它们“推”离歧管。通过使用未改变的输入示例作为目标,我们能够训练我们的模型来近似一个将特征空间中的点投影到特征分布流形上的函数。
The manifold interpretation of the denoising task. We’re looking at a simple feature space, where the “true” distribution of examples lies close to the line (manifold). The circle on the left shows the result of corrupting an input. The lines on the right show the learned function of projecting points onto the manifold (source).
对于任何正在努力理解流形概念的读者来说,这只是一种说法,即被破坏的输入看起来不像“在野外”的例子,但它们的目标看起来像。学习使被破坏的输入“看起来”像真实输入的任务给了我们的模型一种学习分布本身的方法。
这样,去噪任务是一种执行无监督学习任务的方式,该无监督学习任务学习样本在特征空间中的分布。好处是我们可以用示例/目标对进行训练,这为使用监督学习技术打开了大门。这使得这成为一个自我监督的学习计划。这是最古老的自我监督计划之一!
Self-supervised learning? Oh yeah, I used to be into that… before it went all “mainstream.”
与传统的自动编码器相比
“普通的”自动编码器不会破坏输入。模型的输入与目标相同。这些模型学习近似身份函数。
因为 identity 函数很容易学习,所以经典的自动编码器有一个特定的要求:模型输入的内部表示中至少有一个必须比输入的维数少。这样,任务就真的“压缩”了。我们如何以保留信息但降低维数的方式对输入向量进行编码?自动编码器知道如何回答这个问题。
Classic “vanilla” autoencoder setup; a “bottleneck” layer (z) is required to make the identity function non-trivial (source).
DAE 不是真正的自动编码器,因为它不学习识别功能。它实际上学习了一个将点投射到前面描述的流形上的函数。这消除了 DAE 中对瓶颈层的需求。
A DAE does not need a low-dimensional “bottleneck” layer. Copyright by Kirill Eremenko (Deep Learning A-Z™: Hands-On Artificial Neural Networks)
表征学习
深度神经网络之所以如此强大,是因为它们能够学习示例的潜在特征,或表示。
那是什么意思?
这里有一个简单的人为的例子。想象我们是一家汽车保险公司。我们有一份申请表,上面有我们的申请人想要确保的汽车特性。下面是该表中的一个片段:
Our contrived example dataset.
这里潜在特征的一个例子是“财富。“虽然我们不知道申请人有多少钱,我们也不能仅仅根据这些特征来确定,但驾驶法拉利的申请人很可能比驾驶本田思域的申请人更富有。
What do you think about the owners of these two cars? What’s different about them? Those are latent features.
这是一种人工神经网络可以解决的事情— 而无需明确地将财富的概念引入模型。
普通的自动编码器是一个好主意,但是对瓶颈层的需求迫使我们的网络做一些总结。这锻炼了模型做好表征学习的能力。
这就是为什么 DAE 是一个好主意!我们可以不压缩我们的例子,而是把它们打开;我们可以将每个示例扩展到一个更高维度的空间,其中包括潜在特征,显式地表达从每个示例中的整个数据集学习到的信息。
为什么是表格数据?
这些技术在研究中非常有效,但是我们很少在论文中看到表格数据。我希望我的读者开始考虑将 DAE 用于表格数据。
这是因为在平凡、普通、日复一日的数据科学家的工作中,表格数据就是我们所拥有的。
数据驱动的企业挤满了巨大的分布式数据存储系统,所有这些系统都塞满了数百万行和列的表格数据**。**
Though underrepresented in ML research, the vast majority of our information is stored in tables.
用于表格数据的 DAE:一个成功的故事
2017 年,一位 Kaggle 竞赛获胜者透露了他的获胜策略:用 DAE 进行表征学习。
这是一个完全表格化的数据集。
对于表格数据,不管你怎么说 DAE,但是证据就在布丁中。迈克尔用 DAE 赢得了比赛。
桌子的噪音
表格数据面临的挑战是,每一列都代表其独特的分布。我们有类别,数字,排名,二进制值等。,都融合到同一个例子中。
这给应用 DAE 带来了重大挑战:我们使用哪种噪声?
DAE 中的一些原创研究通过将输入值设置为零来破坏它们。对于分类列,“零”没有意义。我们是否只是随机地将一些值设置为编码为零的类别?这似乎不太合适。
交换噪声
迈克尔成功解决方案的关键是一种他称之为“交换噪音”的噪音
这是一个非常简单的想法,只适用于表格数据。
我们不会将值设置为零或给它们添加一些高斯噪声,而是在我们的数据帧中随机选取一些单元格,然后用来自同一列但随机采样的行的值替换它们的值**。**
这为从列的分布中获取样本值提供了一种计算成本低廉的方法,同时避免了实际建模这些分布的需要。****
噪音带有一个参数:我们交换一个给定值的可能性有多大?kaggle 获奖推荐:
" 15%的 swapNoise 是一个很好的起始值."
— 迈克尔·贾雷尔,波尔图安全车手大赛冠军
也就是说,表格中 15%的单元格应该随机替换为它们自己列中的值。从这里开始,调整 nob,看看什么最适合您的数据集。
dfencoder —用于表格数据的 DAE
我想亲自尝试一下。我想,“如果一个熊猫数据帧有一个应用交换噪声的方法不是很好吗?”
对熊猫来说,拥有这个特性并没有什么意义,但我会发现它很有帮助。我决定自己实施。于是,dfencoder 诞生了。第一个特性:EncoderDataFrame。这是一个熊猫的数据框。swap(),一种返回应用了交换噪声(默认值为. 15)的数据帧副本的方法。
Example of .swap() method usage.
从那时起,这个项目就像滚雪球一样变成了现在的样子:一个完整的端到端框架,用于构建和训练带有表格数据的 DAE。
要了解如何使用该框架的更多信息,请看一下演示笔记本。(项目仍在开发中,但在 BSD 许可下可以免费使用。)
DAE 的应用
我们已经讨论了作为特征提取器的 DAE。但是他们还能为我们做什么呢?
有许多应用,但仅举几个例子:
- 特征插补
- 异常检测
- 特征抽出
- 探索性分析(例如,类别嵌入)
你可以在 dfencoder 演示笔记本中看到如何处理这些用例。
也许您或您的组织只有一堆未使用的数据表—如果您有一些未使用的计算资源,为什么不将它们用于学习数据的有用表示呢?
使用 TensorboardX 实现 EDA 和更多功能
我不喜欢 Tensorflow ,但是这个生态系统的一个伟大之处就是它的传感器板。对于替代性深度学习库来说,没有什么比它更好的了。
幸运的是,有tensor board x——tensor board 的一个通用扩展。
Tensorboard’s user-friendly GUI.
我在 dfencoder 库中添加了一个 TensorboardXLogger 类,让您可以更密切地监控您的模型优化。
Tensorboard 的另一个很酷的特性是能够在你的模型已经学习的类别嵌入上运行 PCA 或 t-SNE——所有这些都有一个很好的 GUI。
PCA on category embeddings for education-level column in adult census dataset. Learned through DAE.
你不需要 tensorboardX 或 tensorflow 来运行 dfencoder,但是如果你想使用 tensorboard 后端,你可以只安装这些库,并将 logger='tensorboard ',logdir='your/logdir/'参数添加到 AutoEncoder 构造函数中。
dfencoder 理念
你有很多事情要做:截止日期,正在进行的次要项目,还有朋友和家人。
我们没有时间深入兔子洞,试图建立最先进的表征学习模型。我们坚持有效的方法:增强模型,随机森林;见鬼,正则化逻辑回归几乎总是奏效!
dfencoder 已经领先,处理所有的样板代码,所以你不必。如果您想构建一个 DAE,您需要担心的事情已经够多了:
- 隐藏层数
- 隐藏层的大小
- 激活功能
- 交换噪声参数
- 学习率
- 【计算机】优化程序
- 正规化
- 特征缩放
- 还有更多!
我希望您专注于这些东西,并实际制作一个有用的 DAE,调整这些参数以优化您正在做的任何事情。我不想让你写一堆我已经写好的代码!
这就是我创建 dfencoder 的原因。
查看该库——它适用于 python 3.6,并使用 torch 作为其深度学习后端。
重现获奖结果
我开始了这个项目,希望能够重现 DAE kaggle 冠军所获得的结果。我没有 GPU,所以我使用 Google Colab 作为免费的 GPU 后端——不幸的是,系统内存(~14 GB)不足以像 Michael 那样解决问题(32 GB 内存)。更不用说,训练花了他几天的时间。
复制他程序的笔记本的开端可以在这里找到;任何有硬件的人都可以看一看这款笔记本,并根据需要对其进行修改,以适应获胜的超参数。让我知道你是否能让它工作!
祝你好运!
我对你的故事很好奇。如果你觉得有趣或有用,在这里评论或在某处提及这个库!欢迎反馈和功能请求:)
如何处理机器学习问题?
机器学习是让计算机像孩子一样学习的过程。就像一个孩子需要被教会如何理解问题,从给定的情况中利用洞察力并采取相应的行动一样,机器学习模型也需要被教会。
在当今世界,数据是最昂贵的商品。它甚至比钻石或黄金还贵!原因是数据可以通过机器学习模型以各种不同的方式使用,以获得有意义的见解和预测未来的行为。
Source of Image :https://techgrabyte.com/10-machine-learning-algorithms-application/
现在我们已经确立了数据和机器学习的重要性,让我们开始讨论如何识别问题、决定数据集、制作模型和评估以获得期望的结果。
就区域应用和未来研究范围而言,机器学习算法能够解决的可能问题集是巨大的。我建议选择任何你感兴趣的问题。首先确定一个你想从事的领域。下一步是在那个领域里选择一个能让你感动的问题。一旦你有了问题,然后试着在互联网上找到什么样的数据集,因为许多研究人员开放他们的数据集和代码供学术界使用。此外,谷歌人工智能、微软研究院和脸书博览会等公司的研究部门通过挑战开源了各种有用的数据集,促进了各种领域的研究。
有时,我们必须根据我们所拥有的数据来修改问题陈述。别灰心!关键是要持之以恒。如果你对一个问题或想法充满热情,但没有数据集,你可能会考虑花时间收集数据(通过道德手段),并确保你或一些专家可以验证你的数据的用途。如果您已经找到适合您的问题的数据集,那么让我们继续下一步。
人们经常陷入的下一个问题是,哪种算法适合他们的问题陈述。这当然很难处理,但并非不可能。诀窍是对你的问题打算解决什么以及你想如何着手去做有一个非常清晰的想法。例如,如果你的问题是分类,那么你应该考虑看看各种机器学习和深度学习算法,它们将为你执行分类。但是,工作还没有完成!你还有很多选择。哪种算法最适合你的问题?你怎么会知道?
有两种方法来处理这样的困境。首先是测试!在你的数据上测试所有可能的算法,看看哪个最适合你。这种方法有利也有弊。好处是,你肯定知道一个或一组算法是你的问题陈述的更好的选择。然而,人们往往没有意识到我们在现实世界中拥有海量的数据。你能想象在如此庞大的数据集上运行所有可能的算法排列组合需要多少时间和空间吗?解决方法是走第二条路,在决定它是否适合你的问题之前,试着理解算法做什么。不要害怕深入算法本身的基础知识!你对算法的工作原理和它的局限性了解得越多,你就越有可能确定它对你的问题来说是不是一个好的选择!
一旦缩小了算法的范围,下一步就是构建模型,并根据数据对其进行训练。不要忘记调整超参数的重要性,因为它有助于提高模型的性能。如果你不知道什么是超参数,那么不用担心!这很容易。超参数就像煤气炉的旋钮。同样,在烹饪时,你需要确保旋钮上的设置是你烹饪食物的理想选择,同样,对于机器或深度学习模型,你需要调整这些旋钮来优化你的性能。
这个过程的另一个重要方面是选择一个与你的问题相关的好的评估标准。许多人在分类、回归等任务中追求准确性,仅仅是因为这是最容易理解的度量标准,但情况可能并不总是如此。例如,假设您的问题是确定在给定数据的情况下,您的模型预测患者患癌症的概率有多准确。在这种情况下,仅仅精确是不够的。在这样的问题中,你还关心精度和召回率。知道你的模型有多精确是个好主意。它是否将患有癌症患者归类为非癌症患者?如果是这样的话,那么这样的模型用在现实世界中岂不是很可怕?因此,对于你想从你的模型中得到什么,要非常小心,并相应地选择你的评估指标。现在你已经准备好进入测试阶段了!
这是如何处理任何问题的一个非常简短的概述。我相信使用好的和合理的策略可以帮助提高每件事和每个人的表现!
我希望这篇文章有助于提供机器学习世界的幕后展望。
谢谢!
资源:
要了解更多关于如何选择机器学习算法的信息,可以看看这个链接:
如何像创新者一样处理问题
来自我的先驱导师的三个经过实地检验的教训
Photo by Olav Ahrens Røtne on Unsplash
如果你和我一样,你会发现自己对当代一些最著名的人有点困惑。所有人都说,他们是天才,是工业巨人,远远领先于我们这些凡人,有人猜测他们是变形蜥蜴。然而,他们的言论如此简单,他们的方法如此基本和直观,我们不禁认为他们只是在用他们朴素的外表欺骗我们——不可能用如此简单的手段达到如此复杂的目的。
在科学方面,我们有阿尔伯特·爱因斯坦和他的简单思维实验。在投资领域,有沃伦巴菲特,与其说他是金融家,不如说他是哲学家。在商界,无忧无虑的理查德·布兰森浮现在脑海中。
我的导师阿赫蒂·海因拉 Skype 的联合创始人和机器人技术的先驱——也是一个类似的谜。他向我们——一屋子卓越的工程师——提出了一个复杂的问题,我们想出了一个复杂的技术解决方案,需要几天才能实现。阿赫蒂等待着熙熙攘攘的人群停下来,通常情况下,他会提出自己别出心裁的方法——一种可以在算盘上五分钟完成的方法。
这里有一个例子:我们原本自主的送货机器人偶尔会被困在障碍物后面——也许是灌木丛。在这种情况下,指挥中心的人负责控制,并通过实时视频观察机器人的周围环境,操纵机械人绕过障碍物,就像它是一辆遥控汽车一样。我们想测量执行这样的机动所花费的平均时间。
然而,问题是这样的信息不容易从数据库中获得。当我们都在考虑如何为此目的重新构建系统时,Ahti 调出了一些此类案件的视频,并手动计算了秒数。这个问题在几分钟内就解决了,我们目瞪口呆。
教训:正是因为我们太老练,我们才发现自己被问题困住,被分析麻痹。随着时间的推移,通过第一手经验,我注意到 Ahti 身上的几个特征反映了其他伟大创新者的特征。它们都讲述了同一个故事:简单是关键。
为了让自己变得不复杂,让我们从他们的剧本中吸取一页:
从基本原则出发思考
2017 年,埃隆·马斯克(Elon Musk)提出了一个想法,将洛杉矶等大都市的车辆交通转移到一个互联的地下隧道网络中。他认为,如果隧道费用至少降低一个数量级,从每英里 10 亿美元降到 1 亿美元,这样的计划在经济上是可行的。
他的新企业,无聊公司,就是要这样做。他概述了如何在 TED 演讲中实现这一壮举:
- 通过将直径减半,使隧道小于典型的。根据公式 S = π ×r,横截面积 S 因此减少了四倍。由于挖掘成本与面积成比例,成本下降到 2.5 亿美元。
- 在加固隧道壁的同时,继续钻探过程,挖掘得更智能。简化传统的停止挖掘隧道的程序,同时提供支持,将成本降低了两倍,降至 1 . 25 亿英镑。
- 通过加大钻孔机的功率来更快地挖掘隧道,这些钻孔机并没有以其最大能力工作。至少,这应该使效率加倍,使我们达到大约 6000 万,远低于必要的 1 亿大关。
现在,没有人否认这些步骤中的每一步都极其困难,取决于多年的技术和操作突破。但通过自下而上而不是自上而下地解决问题,马斯克迫使自己独立思考,导致对传统智慧的重新评估,并确定了明确的改进途径。
像马斯克一样,我们需要摆脱现状的束缚。当面临问题时,我们应该而不是从现有的解决方案向后工作,试图找出一些瓶颈——这只会导致不值得我们花费时间的渐进进步。相反,我们应该从基本原则开始建立对问题的理解,只有这样我们才有希望创造出真正崇高的东西。
我们的心态必须是建筑师的心态,而不是雕塑家的心态——我们不是在剥离已经存在的东西,我们是在构建一个全新的存在。
从头开始工作的优势有两方面。首先,它迫使我们关注大局,跳过那些在解决问题的早期探索阶段只会拖累我们的不必要的细节。当然,技术细节很重要,但只是在一定程度上允许我们实现我们的总体愿景。作为创新者,我们必须区分细节和一般,让后者引导前者,而不是相反。
第二,它允许我们的思想自由漫游,不受以前做过的事情的污染。我们多年来获得的独特技能赋予了我们一个独特的视角,其他人从未用这个视角探索过手头的主题。批判性地思考现在让我们挖掘潜力,当我们意识到自己的独特性时,我们的信心会增加。我们不再试图随大流,而是拥抱我们个人的工具箱,以用它来重建我们周围的世界为乐。
“云中城堡没有建筑规则”——吉尔伯特·k·切斯特顿
内化抽象概念
作为一个小男孩,物理学家理查德·费曼过去常常坐在他父亲的腿上,听他讲大英百科全书中的故事。年轻的费曼对奇妙的恐龙世界特别着迷,他的父亲通过将书中枯燥的统计数据转化为现实,使恐龙世界变得栩栩如生。
例如,说到霸王龙,百科全书会说它有 25 英尺高,头部有 6 英尺宽。然后,他的父亲会停下来,把这些事实转化为对他儿子来说切实的东西:“这意味着,如果它站在我们的前院,它就足够高,可以看到我们的房间。但是他很难吃掉我们,因为他的头有点太宽了,无法穿过窗户。”
据费曼自己承认,这种早期影响对他成长为一名特立独行的科学家起了重要作用。通过将他的思维建立在日常类比的基础上,他对物理学产生了一种本能的感觉——做科学变得更像是一种讲故事的练习,而不是严格的数学推理。正是他对抽象概念的直觉理解,让费曼简化了量子力学,用一个图形框架取代了复杂的数学表达式——这项工作为他赢得了诺贝尔奖。
我们应该从费曼那里学到的是理解和仅仅知道之间有着巨大的差异。后者可以通过材料的被动积累来实现,而前者需要一种主动的方法。一个关心理解的人总是在重组他的思维,将她遇到的每一个新概念编织到她现有的知识网络中,从不允许任何空隙。
我们必须优先考虑根据我们已经内化的东西来理解外部世界的抽象新奇事物。
这种对抽象事物的本能控制使我们的思维更敏锐,更有独创性。当其他人被过度的形式主义所困,经常屈服于单调乏味时,我们能够以无与伦比的旺盛精力解决问题,这是出于我们已经想到的许多类比。就像组装乐高积木一样,玩我们直观的原始模型,在我们的想象中重新配置它们以获得新的见解,这是一件非常有趣的事情。
此外,想法的深层内化允许它们渗透到我们的潜意识中,在那里它们将与我们已经吸收的其他概念混合和匹配。解决问题的方法会逐渐出现在我们面前,因为最初困扰我们的完全不同的概念会形成连贯的模式。这往往会带来顿悟的时刻,当事物之间隐藏的联系突然在直觉的闪现中变得可见——历史上许多最具突破性的发现都是这种潜意识过程的结果。
“为什么眼睛在梦中比清醒时的想象看得更清楚?”—莱昂纳多·达芬奇
立即采取行动
对于亚马逊的客户服务部来说,2000 年的假日季节特别混乱。随着圣诞节销售的增加,亚马逊的电话等待时间越来越长。由于互联网泡沫的破裂,消费者对科技公司的信任已经减弱,这是一场灾难。
为了控制这个问题,该公司的首席执行官杰夫·贝索斯召集了一系列紧急会议。在一次这样的会议上,贝佐斯要求提供客户等待时间的统计数据,并得到保证,在没有任何证据的情况下,他们远远低于一分钟。贝佐斯对此大吃一惊——这个数字远低于他的印象。他脱离现实了吗?
令他的高管困惑的是,贝佐斯当时就通过会议桌中间的扬声器拨打了亚马逊的帮助热线。他用手表记录时间,坚定地守在电话旁。随着时间的推移,这位线人在房间里其他坐立不安的高管中惊慌失措,并试图通过短信偷偷召唤他的下属。
最终,在漫长的五分钟等待后,贝佐斯的电话被一位愉快的代表接听了:“你好,亚马逊!”在没有任何冗长的后续会议和昂贵的分析的情况下,贝佐斯凭借这一独特的天才之举,不仅淘汰了无能的高管,还凸显了亚马逊运营中的一个重大问题。
阿赫蒂萨里也有类似的迅速而审慎行动的倾向。对于他来说,为了寻找答案,在会议中途浏览源代码并不罕见。或者实时编写新的功能和缺陷修复程序。事实上,他的即时感是如此强烈,以至于他让通常被动的人看起来不可思议地活跃——当提出想法时,他的注意力是如此坚定,注意力是如此敏锐,就好像他积极地将信息输入他的大脑。
培养我们对行动的这种偏见有三重好处。首先,我们的热情,也就是我们投入到手头工作中的热情增加了。我们的热情随着问题的开始和解决之间的距离的增加而减少。因此,为了抓住转瞬即逝的窗口,让我们的情绪准备状态有可能达到最佳状态——心流状态——现在就行动是必要的。
我们必须把我们对工作的热情等同于一段新的关系——它需要迅速培养,否则它会失败。
第二,我们以前所未有的清晰和专注推进。通过及时解决问题,我们对问题出现的背景仍然记忆犹新。这让我们能够专注于提供解决方案——我们不想耗尽我们的认知资源试图记住过去问题的复杂细节。这种可用性在协作环境中尤为重要,在协作环境中,任何信息的丢失都会以辅助会议的形式带来巨大的开销。
第三,就像阿提提一样,我们发展出一种关于我们自己的活力光环。不再焦虑,不再被不断增加的积压工作拖垮,不再把我们的注意力转移到内心,我们挺直腰板,以不同寻常的感知度生活。我们的思想和行动交织在一起,前者毫不拖延地呈现了后者,我们又一次像小孩子一样,可爱地躁动不安,永远充满好奇。作为一个额外的收获,我们会给人一种完全真实的感觉,吸引别人来看我们。
“我们走得越慢,我们死得越快”——乔治·克鲁尼
如果把这些信条融入我们自己,我们的生活会突然变得既容易又困难。从某种意义上说,我们所关注的本质是独立的,避免了我们被纠缠在细节中。更难是因为从基本原则出发思考,我们不能再沉迷于模仿,而必须从内部寻找灵感。更难是因为概念的深度内化会导致最初的开销——当其他人已经取得进展时(直到他们不可避免地被缺乏深度所阻碍),我们仍然处于明显的被动状态,或多或少是在做白日梦。
当然,我们已经知道——获得成功是困难的,更不用说达到最伟大的人的水平了。我只是想通过阿赫蒂和其他人告诉你,事情不必复杂。让我们感到欣慰的是:这远不容易,但至少很简单。
简单到我们现在就可以开始。
如何提出好的问题?
Photo by Cristofer Jeschke on Unsplash
什么是好问题?为什么问一个好问题?怎么做呢?这个故事探讨了这三个问题。
为什么要问好问题?
在进入“如何”部分之前,你可能想知道为什么你应该关心问好问题,所以让我们花点时间来理解为什么。问题旨在引出答案、信息、满足好奇心——这是我们所有人在生活中都渴望的。我们经常尝试这样做:从简单的谷歌搜索到详细的论文回复,一切都涉及到提问的概念。事实上,伏尔泰认为提出正确问题的能力比拥有所有答案更重要:
“判断一个人要看他的问题,而不是他的回答。”
—伏尔泰
因此,既然问问题是我们生活中不可或缺的一部分,问好问题不仅对个人有益,对职业也有好处。对于数据科学来说尤其如此,因为一些数据科学家认为,提出正确的问题是分析中最重要的过程——,这就是为什么它是增加数据科学价值的关键。
但是到底什么是好的问题呢?我来解释一下我的观点。
什么是好问题?
我们的问题可以根据针对的对象进行分类;广义来说,我们要么问一个人类(朋友、家人或陌生人),要么问一个非人类(语音助手、搜索引擎等)。).互联网上有如此多的信息,人类和非人类对问题有如此多的解释,一个好的问题应该被正确理解,并及时得到准确的答案。为了识别这些问题,我们需要数据和比较问题的方法。
但是,*我们如何衡量呢?有没有一个指标可以帮我们做到这一点?*一种可能是计算你需要最终得出答案的 个跟进问题 的数量。例如,假设您搜索“世界各地的生育率”数据。你一开始没有找到你要找的数据是有可能的,因为搜索引擎不知道你在看什么时间框架:你想要过去 1 年还是 50 年的数据?你想要历史数据还是预测,还是两者都要?
或者说你搜索“世界上最富有的国家”同样,对这些有很多解释:我们用什么指标来衡量“富有”? GDP? GNI ?我们在看什么时间框架?
这些模糊性要求你问一系列的“后续”问题,在这些问题中,你要么调整你原来的问题,要么提出一个全新的问题,直到你找到答案。作为一个重视时间的聪明人,你肯定想避免时间,同时保持高效和有效。通常情况下,一个问题是不够的,也可能不够,但我们知道这是我们的理想场景:如果我们知道一个理想的问题,我们可以一口气找到我们的答案!认为这过于乐观了吗?至少爱因斯坦不这么认为:
“如果我有一个小时来解决一个问题,而我的生命取决于这个问题的解决方案,我会用前 55 分钟来确定要问的恰当问题,因为一旦我知道了恰当的问题,我就可以在不到 5 分钟的时间里解决这个问题”——阿尔伯特·爱因斯坦。
这句话重申了提出好的问题对于快速有效地找到答案的重要性。在某种程度上,跟进问题的数量,正如 Charles Burke 所说,是我们的“富士山指标”
Photo by Daniel Seßler on Unsplash
我们的目标是指标的顶端(也就是山峰)。虽然我们可能永远也不会实现它,但是不断地朝着它前进将会帮助我们取得巨大的进步。问问题是一种技能,如果你不断向顶峰攀登,也许会像第一张照片中的那个人一样到达顶峰,你就可以发展这种技能。
如何?
既然你知道什么是好问题,为什么它们很重要,你就准备好揭开最棘手的部分:如何揭开?
正如在“是什么”部分中所讨论的,一个好的理想的问题是一个足以在一瞬间找到答案的问题。因此,问好问题的关键是问具体、详细的问题。但是*多少才算够?*越多越好吗?不一定。考虑这样一个场景:两个人走进一家咖啡馆,想要点吃的:
我可以要一个芝士汉堡吗?
我能要两个小圆面包,一个肉饼,生菜,西红柿,番茄酱,奶酪都堆在一起吗?
你明白了。你想找到正确的平衡,下面是你在设计问题前应该考虑的 3 个因素。让我给你举个例子,告诉你这些因素是如何产生的。假设您想了解世界各地的富人有多富有,以及不同地理区域之间的差异。
#1:特定术语
你问的术语是特定于那个领域的吗?如果没有,你能改进吗?在我看来,提出一个“前置问题”来巩固你对一个术语的理解,然后用具体的词来提出问题要容易得多。让我们假设你不太懂经济学或商业(如果你懂,那很好,你可以跳到第二点)。
一个好的开头或“前置问题”会问“经济学家如何衡量个人的财富?”或者“用什么指标衡量个人财富?”这可能会让你想到人均 GDP、人均 GNP 等术语。你的问题就变成了“世界上个人的 ______ 相比如何?”空白处由您选择的指示器填充。
#2:具体范围
虽然你用行话使问题更加清晰,但仍有工作要做。你需要有一个范围,否则你将不得不问一系列后续问题。例如,你对特定的国家、地区或大洲感兴趣吗?您是担心他们当前的财富,还是想要 xyz 年前的数据?
决定范围是困难的,主要是因为你不确定你想要进入的方向。这完全没问题,但是更具体地确定一个方向,去做它并决定不做它,与确定你的路径相比,需要更少的后续问题,因为你在问问题,这也可能导致混乱。
因为提问是一项你可以随着时间磨练的技能,随着时间的推移,这方面会变得更加舒适,你的“好”问题组合的大小也会增加。
#3:具体来源
来源指的是你问这个问题的广义对象。合理吗?例如,你走进一家餐馆,问一个关于暗物质为什么存在的完美框架的问题。有意义吗?绝对不行。
提问时你在哪里寻找答案至关重要。尽管这可能主要是由你的“估计”驱动的,但你肯定是错的。在一个城市里向游客 a 问路,向谷歌寻求对一个论文问题的回应,甚至只是向错误的朋友寻求帮助,都是浪费时间,如果不是完全错误的话。
你想关注的是富士山指标:你想问一个一语中的问题,为了做到这一点,你必须瞄准正确的方向——答案的来源。
像#2 一样,这方面也会随着时间的推移而发展,但在此之前,你也可以问“前置问题”来确定来源。前置问题与跟进问题的美妙之处在于,前置问题在你提问之前给你指明了方向(你可以记住它以便下次提问),而跟进问题在提问过程中寻找方向。
如果你已经通过阅读上面的所有内容完成了这一点,那就太好了!你已经向顶峰迈出了第一步!但是如果你想测试你的问题有多好呢?一种可能是将它粘贴到谷歌中,然后点击“我感觉很幸运”按钮,这将绕过搜索结果页面(有多个结果),直接进入你所提问题的排名第一的页面。如果你的问题足够好,你就会找到答案。这是我们的理想场景。
祝你在提问过程中好运,并让我知道进展如何!你可以通过 LinkedIn 或 Twitter 联系我。
如何用排列测试评估数据的统计显著性
随机抽样可以帮助您评估数据的统计显著性。下面是如何用几行 Python 代码实现的。
在处理统计数据时,随机性可能是我们手头最强大的现象之一。它可能不那么明显,但在正确的范围内,它可以帮助我们发现数据中隐藏的模式。传统上来说,我们依靠分析解决方案来进行假设检验。想想比较两个分布的平均值的 t 测试,或者测量两个变量之间的线性相关性的皮尔逊相关。这些统计值的意义总是依赖于一个 p 值。如果我们不知道其 p 值,0.30 的相关性没有任何意义,因为相关性分数可以用机会来解释。像这样,任何统计数据的解释都与它有关,它越小,我们看到的模式被偶然解释的概率就越低。
这些参数检验的缺点是它们依赖于假设(如 example⁴数据的正态性),并且只有一个目的。双样本 t 测试可以帮助您确定两个正态分布的平均值是否存在显著差异。中位数,众数,峰度,偏度等呢?两个分布的?可以认为它们在统计学上是不同的吗?这个问题不能用这个测试来回答。为此,我们可以利用随机性。
在这里,我将展示一个非常简单的方法,你可以使用随机排列 testing⁵.来测试几乎任何你想要的统计数据的显著性我假设你已经知道 Python 中的简单编码,并且理解基本的代数和统计。在本教程结束时,我希望你知道如何应用这种强大的技术来评估你自己数据中的统计显著性。我们开始吧!
Permuting a color grid means shuffling it! The proportion in the data is the same, but the structure is lost with every new iteration.
排列测试基本上是在做这张图片正在做的事情,但是是对我们的数据。我们将所有东西混在一起,形成一个大的数据池,然后将这个数据池与混洗前的数据池进行比较。不完全是这样,但是你可以知道我们在这里要做什么。
一般来说,我们会用到两种排列测试。第一个是评估两个分布之间的统计差异被偶然解释的概率。考虑一个 t 测试,但是对于任何你想要的度量,不仅仅是平均值。第二是测量两个变量(相关性、相互 information⁵等)之间的相关性被偶然解释的概率。这个概率越低,你的测试的意义就越高。
我将坚持使用鸢尾花数据集,它可以在sklearn
中找到,利用它我们可以很容易地探索特征之间的统计意义。在构建置换算法之前,让我们导入所有模块并加载数据集:
测量两个变量之间度量差异的显著性的算法
构建该算法的分步指南如下所示:
**1。**选择你的度量标准,我们称之为 τ 。这可以是任何分布度量,如平均值、中值、峰度等。我选择了平均值,并将只对第一个特征(萼片长度)进行排列测试,在北美鸢尾和杂色鸢尾之间,你可以根据你想要的任何度量/特征改变它。
2。根据你的两个变量计算 τ ₁和 τ ₂之间的地面真实绝对差值δτ:
或者在我们示例的代码中:
gT = np.abs(np.average(feat_vir[:,0]) — np.average(feat_ver[:,0]))
3。将你的变量集中到一个单一的分布中:
pV = list(feat_vir[:,0]) + list(feat_ver[:,0])
4。随机采样(也称为自举)而不替换两个大小与该汇集分布的原始分布相等的分布,以计算两个置换样本之间的度量的绝对差Rδτ:
并且重复这个 p 次(这里我们会做 1000 次):
**5。**最后,置换差高于你的地面真值差的比例就是你的显著性值:
p_val = len(np.where(pD>=gT)[0])/p
就是这样!看起来是这样的:
Blue represents all permuted differences (pD) for sepal length while thin orange line the ground truth computed in step 2.
嘣!这基本上意味着我们的地面真实差异(gT)远远高于随机重采样产生的 1000 个差异。没有置换的差异更高,所以我们可以说,这两个变量的平均值之间的差异很难解释。这两个物种的相同特征之间的参数值测试怎么样?
stats.ttest_ind(feat_vir[:,0], feat_ver[:,0])
Ttest_indResult(statistic=5.629165259719801, pvalue=**1.7248563024547942e-07**)
也非常重要。明白我的意思了吗?更进一步,比较第二个特征(萼片宽度)与一个t-测试抛出一个 p - 值为 0.0018。仍然很重要,但不像另一个那么低。我们的排列测试怎么办?
Blue represents all permuted differences (pD) for sepal width while thin orange line the ground truth computed in step 2.
太棒了。更令人惊讶的是,我们置换的 p - 值为 0.001(很少是偶然解释的),与我们传统的t-测试中一模一样!
这两种方法都可以用来评估均值的显著差异,但请记住,排列可以用于任何其他指标。现在,让我们构建统计相关性的算法,并使用皮尔逊相关性作为我们的 τ 。
测量两个变量之间相关性显著性的算法
对于这个例子,我将选择测量*鸢尾的萼片长度和萼片宽度之间的线性相关性的显著性。*这些变量之间的散点图如下所示:
好消息是步骤几乎相同。唯一的区别是,我们不是计算绝对差值,而是简单地计算相关性 τ ,就像基本事实的皮尔逊相关性,以及在每个置换步骤中,同时仅改变一个变量并保持另一个 intact⁷.在代码中是这样的:
打印 p_val 抛出一个 0,这再次意味着高度重要!最后,这些置换关联看起来像这样:
Blue represents all permuted correlations while thin orange line the ground truth.
已解决的难题
Photo by Hans-Peter Gauster
通过本教程,您应该能够将这种技术应用到您自己的数据中。请记住,您可以使用任何您想要的统计指标/依赖关系。也许你想测量两个变量的峰度是否不同?没问题。两个变量之间相互 Information⁶的显著性?没什么大不了的。这种方法让你在所有这些类型的情况下。
编码快乐,感谢阅读!
参考资料:
[1]关于 t 检验的文章:https://medium.com/@kangeugine/hypothesis-test-21795f788f7d
[2]关于皮尔逊相关性的一句话:https://medium . com/@ silent flame/Pearson-correlation-A-mathematical-understanding-c9aa 686113 CB
[3]一篇关于 p 值含义的文章:https://towardsdatascience . com/p-values-explained-by-data-scientist-f40a 746 cf c8
[4]哈塞米,a .,& Zahediasl,S. 统计分析的正态性检验:非统计人员指南(2012)《国际内分泌与代谢杂志》, 10 (2),486。
[5] Ojala,m .,& Garriga,G. C. 研究分类器性能的排列测试(2010)《机器学习研究杂志》,11(6 月),1833–1863。
[6]曾,G. 互信息的统一定义及其在机器学习中的应用(2015)工程中的数学问题, 2015 。
[7]Fran ois,d .,Wertz,v .,& Verleysen,M. 互信息特征选择的排列检验(2006)ESANN(第 239-244 页)。
如何攻击机器学习(规避、投毒、推理、木马、后门)
Gerd Altmann Pixabay
在我之前的文章中,我提到了三类人工智能威胁(间谍、破坏和欺诈)。如果从技术层面来看,攻击可能发生在两个不同的阶段:训练或推理阶段。
UPD 2021: 这里你可以找到关于 AI 和 ML 攻击的最新报告
训练期间的袭击比你想象的更频繁。大多数生产 ML 模型定期用新数据重新训练它们的系统。例如,社交网络不断分析用户的行为,这意味着每个用户都可能通过修改行为来重新训练这个系统。
根据攻击者的实际目标(间谍、破坏、欺诈)和机器学习管道的阶段(培训和生产),对 ML 模型的攻击有不同的类别,或者也可以分别称为对算法的攻击和对模型的攻击。它们是规避、中毒、特洛伊木马、后门、重新编程和推理攻击。现在最普遍的是逃避、投毒和推断。简单地看一下它们(表 1)。
回避(对抗性例子)
规避是在推理过程中对机器学习模型进行的最常见的攻击。它指的是设计一个输入,这个输入对人类来说似乎是正常的,但是被 ML 模型错误地分类了。一个典型的例子是在上传之前改变一张图片中的一些像素,这样图像识别系统就无法对结果进行分类。事实上,这个对立的例子可以愚弄人类。见下图。
图 1。人类的反面例子
根据模型、数据集和其他属性,可以使用不同的方法来执行这种攻击。自 2004 年发布名为“对抗性分类”的研究以来,已有超过 300 篇研究论文考虑了 arXiv 的类似主题,大约相同数量的论文描述了各种保护措施。
人们的兴趣越来越大——见图表。2018 年的统计数据是在 7 月份收集的,因此预计今年年底至少会增加一倍。
图二。Arxiv 上关于对抗性攻击的研究论文的大概数量。
在选择正确的攻击方法之前,应该考虑一些限制:目标、知识和方法限制。
目标限制(定向对非定向对通用)
假阳性闪避,这是什么?想象一下,有人想要对结果进行错误分类,比如说,绕过拒绝除高层管理人员之外的所有员工的访问控制系统,或者只需要用错误的预测来淹没系统。这是某种形式的假阳性逃避。
事实上,有针对性的攻击比无针对性的攻击更复杂,但完整列表如下所示:
- 信心降低——我们没有改变一个职业,但却极大地影响了信心
- 错误分类——我们改变了一个没有任何特定目标的类
- 有针对性的错误分类——我们将一个类别更改为一个特定的目标
- 源/目标分类错误—我们将特定源更改为特定目标
- 普遍的错误分类——我们可以将任何来源改变成特定的目标
知识限制(白盒、黑盒、灰盒)
与任何其他类型的攻击一样,对手在了解目标系统方面可能有不同的限制。
黑盒方法——攻击者只能向系统发送信息并获得关于某个类的简单结果。
灰箱方法——攻击者可能知道数据集或一种神经网络、其结构、层数等的详细信息。
白盒方法-关于网络的一切都是已知的,包括训练该网络的所有权重和所有数据。
方法限制(l-0,l-1,l-2,l-无穷大—范数)
方法限制与可以对原始数据执行的更改有关。例如,如果谈论图像识别,改变较少的像素,反之亦然——稍微修改尽可能多的像素。或者介于两者之间。
事实上,基于 l-infinity 范数(最大像素差)的攻击更频繁,也更容易执行。然而,它们不太适用于现实生活,因为微小的变化会被相机的质量所抵消。如果攻击者有一张图片,并对多个像素进行小的扰动,他们就可以欺骗模型。如果他们有一个真实的对象和一个系统来制作这个对象的照片,然后将这个照片发送到 ML 系统,那么相机很有可能识别大多数干扰,并且被干扰的对抗性示例的照片将不再是对抗性的。因此,使用 l-0 或 l-1 范数的攻击看起来更真实并且更难执行。除图像之外的另一个约束可以是其他类型的数据。对于其他数据(如文本或二进制文件),约束可能更加严格,因为不可能改变许多输入特征。创建将绕过分析解决方案的恶意软件提出了更复杂的任务,因为输入特征可以具有甚至更少的要改变的选项,使得所产生的恶意软件示例将绕过检测算法并执行其功能。
白盒对抗性攻击
让我们从理论转向实践。对抗性攻击的第一个例子是基于流行的手写数字数据库演示的。它说明了可以对一个数字的初始图像进行微小的改变,从而使其被识别为另一个数字。这并不是系统混淆“1”和“7”的唯一例子。存在从每 10 个数字到每 10 个数字的所有 100 种可能的数字错误分类的例子。
那是以一种人们无法识别赝品的方式进行的。进一步的研究表明,图像的微小扰动可能导致错误分类,系统识别出一辆汽车而不是一只熊猫。
目前有超过 50 种方法来欺骗 ML 算法,我会给你一个例子。
首先,我们计算一个依赖矩阵,即所谓的雅可比矩阵,它显示了每个输入特征(对于图像,输入特征是像素值)的输出预测(结果类)的变化。之后,对图片进行修改,改变其最有影响的像素。如果有可能通过一点优化的强制对结果进行错误分类,选择下一个像素再试一次。结果令人印象深刻,但并非没有缺点。这是在白盒模式下完成的。这意味着研究人员曾经用众所周知的架构、数据集和响应来攻击一个系统。这似乎只是一个理论,在现实生活中不太现实和可实施。他们的研究不久后被另一个团队(https://arxiv.org/pdf/1707.03501.pdf)更新。
2017 年 7 月,一篇题为“对深度学习模型的强大物理世界攻击”的文章发表,揭示了识别系统可能会被愚弄,自动驾驶汽车可能会对路标进行错误分类。该实验以静态和动态模式进行,从不同角度捕捉视频,准确率为 84%。此外,他们使用艺术品和涂鸦来掩饰类似常规破坏行为的袭击。
有超过 100 篇关于 50 种不同攻击的研究论文,如 BIM、DeepFool、JSMA、C&W 等。
图片。3.对抗性攻击示例
给一幅描绘熊猫的图像添加一些噪声,将有助于将其归类为长臂猿的图片。
灰盒对抗性攻击或可转移性攻击
2016 年,第一项引入灰箱攻击的研究浮出水面。事实上,在白盒和黑盒之间有多个层次。灰盒意味着一个人知道一些关于系统的信息,它的体系结构或者其他什么。大多数流行的解决方案使用公开可用的架构,如 Google。“针对机器学习的实际黑盒攻击”研究表明,通过发送各种输入和收集输出,可以从黑盒系统中收集信息。然后你要根据这些例子训练替身模型,发动攻击。因此,对立的例子是可以转移的。如果有人能够破解一个模型,他或她很可能会破解相似的模型。原来,所有以前的研究例子考虑白盒攻击可能被用来执行黑盒攻击。
这还不是最糟糕的部分。在现实生活中,你甚至不需要数据集。这些网络在数据处理方面存在弱点,例如在卷积层。2017 年的许多研究论文表明,有可能制作一个通用的对抗性例子,可以从一种模式转移到另一种模式。其实知道数据集是没必要的。
图片。4.型号可移植性比较
正如你在图中看到的。4、圆顶模型具有接近 100%的可转移性。
黑盒对抗性攻击
这种可转移性不行怎么办?我们能做点什么吗?
原来我们可以!
通过对模型的黑盒访问,可以进行更改,而模型将无法识别初始图片。有时候只用一个像素就能达到目的。还有许多其他奇怪的方式。我最喜欢的方法之一是当我们向 NN 展示一辆车,但它认出了一只猫。为此,我们拍一张汽车的照片,稍微把它变成一只猫,同时保持 NN 回答它仍然是一辆汽车。这里有一个相反的技巧:不是通过稍微修改像素来改变我们的源到目标,他们取了一个目标,并开始在源的方向上改变像素,同时根据需要保持模型输出相同。
图片。5.一步一步的猫对狗的错误分类
对抗性重新编程
2018 年,研究人员分享了一些奇妙的发现,考虑到一种叫做对抗性重新编程的新型攻击。这是对人工智能模型进行破坏攻击的最真实的场景。顾名思义,该机制基于使用特殊图像对神经网络算法进行远程重新编程。对抗性攻击允许他们创建类似于特定噪音和一个大黑方块中的几个小白方块的图像。他们选择图片的方式是,例如,网络认为黑色背景上有白色方块的噪音是一只狗,有两个白色方块的噪音是一只猫,等等。总共有 10 张照片。
因此,研究人员拍了一张照片,上面有准确数量的白色方块作为背景
输入,然后系统用特定的动物产生结果。回应成功了
可以看到图中的方块数。
事实上,他们的图像识别系统后来变成了一个可以计算图片中正方形数量的模型。从更广阔的角度考虑。攻击者可以使用一些用于图像识别的开放机器学习 API 来解决他们需要的其他任务,并使用目标 ML 模型的资源。
图片。6.将 ImageNet 分类器转换为平方计算器
隐私攻击(推理)
看一看另一类攻击。目标是间谍活动和保密。
攻击者的目的是探索系统,比如模型,或者可以进一步派上用场的数据集。
鉴于大量的系统和专有算法,目标之一是获得关于人工智能系统及其模型的知识——模型提取攻击。
对于处理数据的攻击,可以借助属性推理,通过成员推理和数据属性等攻击来检索数据集的信息。最后,模型反转攻击有助于从模型中提取特定的数据。
目前大多数研究涵盖了生产阶段的推理攻击,但它们也可能发生在训练阶段。如果我们可以注入训练数据,我们就可以根据这些数据了解算法是如何工作的。例如,如果我们想了解一个社交媒体网站如何决定你属于一个目标受众,比如说,一群孕妇,以便向你展示一个特定的广告,我们可以改变我们的行为,例如,试图搜索有关 dippers 的信息,并检查我们是否收到了针对未来妈妈的广告。
图片。7.ML 模型的三种隐私攻击
成员推理和属性推理
成员关系推断是一种不太常见的攻击类型,但却是第一种,并且是数据提取的处理器。成员推断是一种攻击,我们想要知道一个特定的例子是否在数据集中。如果谈到图像识别,我们希望检查特定的人是否在训练数据集中。这是理解 AI 厂商如何遵循隐私规则的一种方式。
此外,它还可以帮助计划进一步的攻击,例如基于可转移性的黑盒规避攻击。在可转移性攻击中,您的数据集与受害者数据集越相似,您训练您的模型与受害者模型相似的机会就越多。属性推断有助于您提取有关训练数据的有价值的信息(例如,语音识别模型中说话者的口音)。
属性推断(猜测数据类型)和成员推断(特定数据示例)至关重要,这不仅是因为隐私问题,也是规避攻击的探索阶段。你可以在关于这个主题的第一篇论文中找到更多细节——“针对机器学习模型的成员推理攻击
图片。8.成员推理攻击
成员推断攻击是猜测这只特定的狗是否在训练数据集中。
输入推断(模型反演、数据提取)
输入推理或模型反演是迄今为止最常见的攻击类型,已有超过 10 篇不同的研究论文发表。与成员资格推断不同,在成员资格推断中,您可以猜测您的示例是否在训练数据集中,而在这里,您可以实际从训练数据集中提取数据。在处理图像时,有可能从数据集中提取某个图像,例如,只要知道一个人的名字,就可以得到他或她的照片。就隐私而言,这对任何系统都是一个大问题,尤其是在 GDPR 合规蓬勃发展的今天。
另一篇论文描述了针对 ML 模型的攻击的一些细节,该模型用于根据患者的基因型【https://www.ncbi.nlm.nih.gov/pubmed/27077138来辅助医疗。维护患者个人和医疗记录的隐私是医疗保健领域的一项重要要求,也是许多国家的法律规定。
图片。9.输入推理示例。左边是从模型中恢复的原始图片。
参数推断(模型提取)
参数推断或模型提取是不太常见的攻击,公开研究论文不到 12 篇。这种攻击的目标是知道确切的模型,甚至是模型的超参数。这些信息对于黑盒环境中的规避等攻击非常有用。
一篇关于规避攻击的最新论文使用一些模型反演方法,利用现有知识更快地执行攻击。我相信第一个关于推理攻击的实用信息是在 2013 年发表在“用更聪明的机器入侵智能机器:如何从机器学习分类器中提取有意义的数据”中
图。10.模型参数提取算法
中毒
中毒是另一类攻击,可以认为是最普遍的攻击之一。使用噪声数据进行学习实际上是一个老问题,可以追溯到 1993 年— “在存在恶意错误的情况下进行学习” —和 2002 年,然而,这些案例都是关于少量噪声数据有机发生的,而中毒意味着有人故意试图利用 ML 模型的过程。对 ML 的中毒攻击始于 2008 年的一篇文章,标题为“利用机器学习颠覆你的垃圾邮件过滤器”。本文给出了一个攻击垃圾邮件过滤器的例子。后来,发表了 30 多篇关于中毒攻击和中毒防御的其他研究论文。
中毒和逃避是不同的。首先,可以有不同的目标,如有针对性的和无针对性的攻击。下一个区别是环境限制,简单地说,就是我们到底能做什么来执行攻击。我们可以注入任何数据还是只注入有限的类型?我们可以注入数据并标记它,只注入它还是只标记现有的数据?
有四种宽泛的攻击策略可以根据对抗能力改变模型:
标签修改 :这些攻击允许对手单独修改监督学习数据集中的标签,但对于任意数据点。通常受到总修改成本的限制。
数据注入 :对手无法访问训练数据以及学习算法,但有能力向训练集增加新数据。通过将对立样本插入训练数据集中,有可能破坏目标模型。
数据修改 :对手没有访问学习算法的权限,但有完全访问训练数据的权限。在用于训练目标模型之前,可以通过修改数据来直接毒化训练数据。
逻辑腐败: 对手有能力干预学习算法。这些攻击被称为逻辑讹误。
投毒攻击是如何运作的?这一切都始于 2012 年对 SVM 等更简单的分类器的投毒攻击。SVM 方法在不同类别之间画出了决策界限。该算法输出一个分类新实例的最佳超平面。在二维空间中,这个超平面是一条将平面分成两部分的线,其中每一类例子位于该线的不同侧。
请看下图,因为它详细说明了毒药攻击以及与经典对抗性攻击的比较。
图片。11.对抗性攻击和中毒攻击的比较
中毒攻击改变分类界限,而对抗性攻击改变输入示例(见图。11).
如果我们给训练数据增加一个点,决策边界就会改变。如果我们展示我们的目标对象,它将在一个不同的类别。实际上,神经网络模型也可以用同样的方法被愚弄。就把这张图想象成我们复杂神经网络最后一层的特征。最新的研究甚至提出了一种在不标记数据的情况下毒害复杂神经网络的方法。对手可以将中毒的图像放在网上,等待它们被机器人抓取,在这种情况下,他们想绕过垃圾邮件过滤器,所以他们注入了电子邮件。他们从测试集中选择一个目标实例,比如一封普通的电子邮件。然后,他们从基类中抽取一个基本实例,并对其进行细微的更改,以创建一个病毒实例,然后将病毒图像注入到训练数据中。他们达到了 100%的攻击成功率,值得注意的是,测试准确率仅下降了 0.2%。
还有两种其他攻击类型,如后门和木马。这种攻击的目标和攻击者的类型不同,但从技术上讲,它们与投毒攻击非常相似。区别在于攻击者可以获得的数据类型。
特洛伊宁
中毒时,攻击者无法访问模型和初始数据集,他们只能向现有数据集添加新数据或修改它。至于特洛伊木马,攻击者仍然无法访问初始数据集,但可以访问模型及其参数,并可以重新训练该模型。这什么时候能发生?目前,大多数公司不是从零开始构建自己的模型,而是对现有模型进行再培训。例如,如果有必要为癌症检测创建一个模型,他们会采用最新的图像识别模型,并用数据集对其进行重新训练,因为缺乏数据和癌症图像不允许从头开始训练复杂的模型。这意味着大多数人工智能公司从互联网上下载流行的模型,黑客可以用自己的修改版本替换它们。
Trojaning 的想法是发现在某些情况下改变模型行为的方法,使现有行为保持不变。如何在注入任何数据后重新训练系统,使其仍然执行原来的任务?研究人员找到了一种方法——首先,从模型中减去数据集,然后将其与新的输入相结合,然后重新训练模型。我不会深入细节,但推荐阅读这篇研究论文。
图 12。木马攻击算法
走后门
即使在黑盒和灰盒环境中,以及在访问模型和数据集的完全白盒模式下,模型的行为修改(如中毒和特洛伊木马)也是可能的。尽管如此,主要的目标不仅仅是注入一些额外的行为,而是以这样一种方式来实现,即在重新训练系统之后,后门将会运行。
下一次攻击是在 2017 年重点强调的。这个想法来自最古老的 IT 概念之一,即所谓的后门。研究人员想教一个神经网络来解决主要任务和特定任务。
基于两个主要原则,攻击有可能在全球范围内发生:
- 用于图像识别的卷积神经网络表示由数百万个神经元形成的大型结构。为了对这种机制做出微小的改变,有必要修改一小组神经元。
- 能够识别诸如 Inception 或 ResNet 等图像的神经网络的操作模型是复杂的。他们受过海量数据和计算能力的训练,这是中小公司几乎不可能再造的。这就是为什么许多处理 MRI 或癌症照片等图像的公司会重用大公司预先训练好的神经网络。因此,原本旨在识别名人面部的网络开始检测癌变肿瘤。
- 犯罪分子可以黑客攻击存储公共模型的服务器,并通过后门上传他们自己的模型,神经网络模型将保留模型重新训练后制作的后门黑客。
例如,NYU 的研究人员证明,即使他们重新训练系统识别瑞典而不是美国的路标,他们的路标检测器中内置的后门仍然活跃。实际上,如果你不是专家,几乎不可能发现这些后门。幸运的是,不久前,研究人员发现了解决方案。我可以肯定的说,以后也会绕过这个机制。
图 13。后门攻击示例
总结
最后,简单地说,我们现在没有列出的问题的最佳解决方案,也许,我们根本无法发明一个通用的解决方案。听起来很悲伤,但是等等!有一些东西启发了我——人工智能系统很容易受到攻击的事实。为什么?既然我们知道这个秘密武器,我们就不应该害怕 AI 和人类之间的任何战争。
订阅阅读关于人工智能安全的新文章,因为这只是开始,我们应该了解更多关于防御的知识。