TowardsDataScience 博客中文翻译 2019(二十六)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

BigQuery 模糊匹配之旅——[ 1,∞)之四——向 FuzzyWuzzy 致敬

原文:https://towardsdatascience.com/a-journey-into-bigquery-fuzzy-matching-4-of-1-a-tribute-to-fuzzywuzzy-54ff73e91a1c?source=collection_archive---------16-----------------------

这是一个正在进行的系列的一部分,还有其他的好处潜伏在那里!所有模糊的善良!

  • 【BigQuery 模糊匹配之旅—1/1,∞) — Soundex
  • 【BigQuery 模糊匹配之旅—2/1,∞) —更多 Soundex 和 Levenshtein 距离
  • 【BigQuery 模糊匹配之旅—3/1,∞) — NYSIIS

好的,我知道在上一篇文章中我说过我们将使用这个开始添加地址元素和匹配组(我保证他们还在路上),但是我想稍微绕一下路,在我们到达那里之前添加另一组函数。

让我们重温一下 Levenshtein 距离函数。之前我们用它来计算两个字符串之间的编辑距离。它旨在确定一个字符串变成另一个字符串所发生的变化的数量,帮助我们确定两个字符串是否应该是相同的。我们看到了如何在单词中使用它,但是当我们开始在越来越复杂的字符串中使用它时会发生什么呢?

在我们进入一些例子之前,让我们首先建立如何计算相似比,以便更容易理解这些比较。这是普通字符与总字符的简单比率。

((|a| + |b|) — ldist(a, b)) / (|a| + |b|)

让我们创建一个函数来计算它,因为我们会经常用到它。

CREATE OR REPLACE FUNCTION
dq.dq_fm_ldist_ratio(a STRING, b STRING) AS ( 
/*
 * Data Quality Function - Fuzzy Matching
 * dq_fm_ldist_ratio
 * input: Two strings to compare.
 * returns: The Levenshtein similarity ratio.
 */
(LENGTH(a) + LENGTH(b) - `dq.dq_fm_LevenshteinDistance`(a, b)) 
  / (LENGTH(a) + LENGTH(b)) 
);

为了了解这些函数如何处理日益复杂的字符串,我们需要一个数据集来测试。我们将使用来自 Expedia 和 Booking.com 的房间描述数据集。我们将把它加载到一个新的数据集中(我将使用fuzzy_matching)并快速浏览一下。

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

So what are we supposed to call these, then?

这些字符串对代表同一个房间,但你可以看到它们可能被称为不同的东西。当我们深入挖掘数据时,我们会看到一些更复杂的组合。

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

a != b

因此,让我们尝试使用我们拥有的工具,并将它们应用到这个数据集,看看它们的表现如何(剧透:它不会是准确的)。

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

Well, it figured one of them out at least.

现在,在我们继续之前,重要的是要注意,Levenshtein 距离可以用两种不同的方式实现,取决于你如何权衡事物。一些实现将替换视为单个操作,替换和添加的权重相等。其他实现方式给替换权重为 2(一个减法+一个加法)。在比较任何实现时,重要的是要注意它是如何权衡的,否则你可能会以无法解释的计算差异而告终。在我们的比赛中,我们用换人作为得分的权重。

回到结果。正如所料,编辑距离非常长,因为我们将整个字符串视为单个标记。正因为如此,匹配率将会很低。我们需要做的是标记化这些字符串,并对它们进行更智能的比较。

输入 FuzzyWuzzy 。字符串匹配库,而不是没有头发的熊。

FuzzyWuzzy 是一个 Python 库,它获取字符串,将其标记,然后以不同的方式匹配它们。这是一个可以利用的非常强大的包,但是 Python 不能被 BigQuery 使用。所以让我们看看我们是否能在 SQL 中复制一些这样的功能!

让我们从令牌排序比率开始。当您有非常相似但顺序不对的字符串标记时,这很方便。令牌排序比率的作用是将字符串分解成单个的令牌,按字母顺序对它们进行排序,将它们连接成一个字符串,然后基于此计算比率。为了实现这一功能,我们首先要创建两个助手函数,它们对数组进行分割、清理和排序。

CREATE OR REPLACE FUNCTION
dq.dq_hf_gh_clean_tokenize(a STRING) AS(
/*
 * (Helper) Data Quality Function
 * dq_hf_gh_clean_tokenize
 * This function removes all non-alphanumeric characters.
 * input: Uncleaned string
 * returns: String of tokenized and cleaned string.
 */
ARRAY(
  SELECT
    tokens
  FROM
    UNNEST(
      SPLIT(
        REGEXP_REPLACE(
          UPPER(
            TRIM(a)
          ), '[^a-zA-Z0-9 ]+', ''
        ), ' '
      )
    ) tokens
) 
);

添加另一个函数对其进行排序。

CREATE OR REPLACE FUNCTION
dq.dq_hf_gh_clean_sort_tokenize(a STRING) AS(
/*
 * (Helper) Data Quality Function
 * dq_hf_gh_clean_sort_tokenize
 * input: Uncleaned string
 * returns: String of tokenized, sorted, and cleaned string.
 */
ARRAY(
  SELECT
    x
  FROM
    UNNEST(`dq.dq_hf_gh_clean_tokenize`(a))
  AS x
  ORDER BY x)) ;

从这里,我们可以重新组装阵列,并进行比较。

CREATE OR REPLACE FUNCTION
dq.dq_fm_ldist_token_sort_ratio(a STRING, b STRING) AS( 
/*
 * Data Quality Function - Fuzzy Matching
 * dq_fm_ldist_token_sort_ratio
 * input: Two strings to compare.
 * returns: The Levenshtein similarity ratio with sorted tokens.
 */ 
`dq.dq_fm_ldist_ratio`(
  ARRAY_TO_STRING(`dq.dq_hf_gh_clean_sort_tokenize`(a),''),
  ARRAY_TO_STRING(`dq.dq_hf_gh_clean_sort_tokenize`(b), '')));

有了这两个,让我们继续将它添加到数据集,看看它是如何表现的。我们正在寻找具有高编辑距离(表明存在大量原始替换,因为一切都是无序的)和高排序率的条目,这意味着各个标记非常相似。

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

We’re starting to get some better matches!

这些结果表明,您可以使用它来匹配带有无序标记的字符串,同时允许一定程度的字符变化。

当字符串之间有一些共性,但其余字符串的令牌长度和实际内容却大相径庭时,会发生什么呢?这就是令牌集的用武之地!开发和开源 FuzzyWuzzy Python 包的 SeatGeek 的人们在他们的博客上对它做了一个非常好的描述。我建议阅读他们的博客文章,以更好地理解这一切是如何工作的,但这里是它的要点。

1 —对于字符串ab,对这两个字符串进行标记。
2 —创建三个字符串: *t0 = sorted intersection of tokens from a and b t1 = t0 + sorted remainder of tokens from a t2 = t0 + sorted remainder of tokens from b* 3 —从 *ldist(t0,t1)* *ldist(t0,t2)* *ldist(t1,t2)*返回最高比率

为什么会这样?正如 SeatGeek 的人解释的那样,“这里的直觉是,因为 SORTED_INTERSECTION 组件总是完全相同,所以当(a)它在整个字符串中占的百分比更大,并且(b)字符串的剩余部分更相似时,分数会增加。”让我们用一对房间描述来尝试一下,看看这是如何工作的。

a = "Deluxe Room, 1 Queen Bed (High Floor)"
b = "Deluxe Queen Room — High Floor With Free Wi-Fi"

对它们进行清理、排序和标记会给我们带来以下结果:

token_a =
  ['1','BED','DELUXE','FLOOR','HIGH','QUEEN','ROOM']
token_B = 
  ['DELUXE,'FI','FLOOR','FREE','HIGH','QUEEN','ROOM','WI','WITH']

相交的记号是,“豪华”、“楼层”、“高”、“女王”和“房间”。这给了我们以下三个字符串和比较:

t0 = 'DELUXEFLOORHIGHQUEENROOM'
t1 = 'DELUXEFLOORHIGHQUEENROOM1BED'
t2 = 'DELUXEFLOORHIGHQUEENROOMFIFREEWIWITH'`dq.dq_fm_ldist_ratio`(a, b) = 0.64
`dq.dq_fm_ldist_ratio`(t0, t1) = 0.92
`dq.dq_fm_ldist_ratio`(t0, t2) = 0.8
`dq.dq_fm_ldist_ratio`(t1, t2) = 0.83

所以这给了我们 0.92 的置信度,比原来的 0.64 高得多。这是可能的,因为交集由原始字符串的大部分组成,所以自然地,比较会很高。如果交集很小,但是剩余的令牌仍然相似,那么通过比较t1t2,我们仍然可以获得高置信度得分。我们从多个角度被覆盖!

现在让我们弄清楚如何将它放入 BigQuery 函数中。我们在前面已经有了一个函数,可以清理、标记和排序字符串。我们现在需要构造一些东西来找到排序后的交集。

CREATE OR REPLACE FUNCTION
dq.dq_hf_gh_find_array_intersection(a ARRAY<STRING>, b ARRAY<STRING>) AS(
/*
 * (Helper) Data Quality Function
 * dq_hf_gh_find_array_intersection
 * input: Two arrays to compare
 * returns: Array with the common elements
 */
 ARRAY(
    SELECT
      *
    FROM
      UNNEST(a) AS a
    INTERSECT DISTINCT
    SELECT
      *
    FROM
      UNNEST(b) AS b )) ;

我们还需要一些东西来计算两组令牌之间的差异。

CREATE OR REPLACE FUNCTION
dq.dq_hf_gh_find_array_difference(a ARRAY<STRING>, b ARRAY<STRING>) AS(
/*
 * (Helper) Data Quality Function
 * dq_hf_gh_find_array_difference
 * input: Two arrays to compare
 * returns: Array with elements a - b.
 */
 ARRAY(
    SELECT
      *
    FROM
      UNNEST(a) AS a
    EXCEPT DISTINCT
    SELECT
      *
    FROM
      UNNEST(b) AS b )) ;

现在我们只需要创建字符串并找到三次比较的最大值。

CREATE OR REPLACE FUNCTION
dq.dq_fm_ldist_token_set_ratio(a STRING,
    b STRING) AS( 
/*
 * Data Quality Function - Fuzzy Matching
 * dq_fm_ldist_token_set_ratio
 * input: Two strings to compare.
 * returns: The Levenshtein similarity of the maximum ratio
 *   between the different token sets.
 */ 
ARRAY(
  SELECT
    MAX(x)
  FROM
    UNNEST( [
      # First ratio is sorted intersection and combined A diff B
      `dq.dq_fm_ldist_ratio`( 
        ARRAY_TO_STRING(`dq.dq_hf_gh_find_array_intersection`(
          `dq.dq_hf_gh_clean_sort_tokenize`(a),
          `dq.dq_hf_gh_clean_sort_tokenize`(b)),'')
        ,
        CONCAT(
          ARRAY_TO_STRING(`dq.dq_hf_gh_find_array_intersection`(
            `dq.dq_hf_gh_clean_sort_tokenize`(a),
            `dq.dq_hf_gh_clean_sort_tokenize`(b)),'')
        , 
          ARRAY_TO_STRING(`dq.dq_hf_gh_find_array_difference`(
            `dq.dq_hf_gh_clean_sort_tokenize`(a),
            `dq.dq_hf_gh_clean_sort_tokenize`(b)),'')))
    , 
      # Second ratio is sorted intersection and combined B diff A
      `dq.dq_fm_ldist_ratio`(     
        ARRAY_TO_STRING(`dq.dq_hf_gh_find_array_intersection`(
          `dq.dq_hf_gh_clean_sort_tokenize`(a),
          `dq.dq_hf_gh_clean_sort_tokenize`(b)),'')
        ,
        CONCAT(
          ARRAY_TO_STRING(`dq.dq_hf_gh_find_array_intersection`(
            `dq.dq_hf_gh_clean_sort_tokenize`(a),
            `dq.dq_hf_gh_clean_sort_tokenize`(b)),'')
        , 
          ARRAY_TO_STRING(`dq.dq_hf_gh_find_array_difference`(
            `dq.dq_hf_gh_clean_sort_tokenize`(b),
            `dq.dq_hf_gh_clean_sort_tokenize`(a)),'')))
    , 
      # Third ratio is A diff B and B diff A
      `dq.dq_fm_ldist_ratio`(
        CONCAT(
          ARRAY_TO_STRING(`dq.dq_hf_gh_find_array_intersection`(
            `dq.dq_hf_gh_clean_sort_tokenize`(a),
            `dq.dq_hf_gh_clean_sort_tokenize`(b)),'')
          , 
          ARRAY_TO_STRING(`dq.dq_hf_gh_find_array_difference`(
            `dq.dq_hf_gh_clean_sort_tokenize`(a),
            `dq.dq_hf_gh_clean_sort_tokenize`(b)),''))
        ,
        CONCAT(
          ARRAY_TO_STRING(`dq.dq_hf_gh_find_array_intersection`(
            `dq.dq_hf_gh_clean_sort_tokenize`(a),
            `dq.dq_hf_gh_clean_sort_tokenize`(b)),'')
          , 
          ARRAY_TO_STRING(`dq.dq_hf_gh_find_array_difference`(
            `dq.dq_hf_gh_clean_sort_tokenize`(b),
            `dq.dq_hf_gh_clean_sort_tokenize`(a)),''))) 
    ] ) AS x)[OFFSET(0)]
);

现在让我们在room_data表上运行这个程序,看看我们会得到什么。

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

Hooray! Matches!

通过一些函数,您现在能够执行一些更复杂的字符串比较。通过对标记集执行编辑距离比较,您可以超越单个单词匹配来查看更广泛的实体。这不仅对产品和描述有用,也适用于地址。地址匹配是实体解析的一个重要部分,像这样的匹配方法是其中的一个重要部分。让我们快速看一下它是什么样子的。

我们将使用帝国大厦的地址,并有目的地以几种不同的方式改变地址。列出的地址是纽约州纽约市第 34 街 20 号,邮编 10001。

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

These are okay.

考虑到我们只是在看纯粹的令牌字符串比较,这些匹配相当不错。在这些例子中,我们得到了很多变化,因为字符串很短,将像“St”这样小的东西改为“Street”会产生很大的影响。

如果实体的域是预先知道的,比如“我们知道这将是地址数据”,那么让一些令牌得到预处理和标准化确实很有帮助。例如,对于美国的地址,我们通常可以假设“St”和“Street”是相同的,“Ave”和“Avenue”是相同的,等等。这种特定领域的预处理可以帮助我们提高两组数据之间的匹配百分比!

至此,我们的模糊匹配工具箱又多了几个新成员。希望这是对 FuzzyWuzzy 的一个有价值的致敬。有了这些构件,我们可以开始将它们应用于复杂的数据集,并使用它们来构建一些基本的匹配组。我们将在下一轮开始查看这些,敬请关注!

卷积神经网络可视化之旅

原文:https://towardsdatascience.com/a-journey-into-convolutional-neural-network-visualization-1abc71605209?source=collection_archive---------15-----------------------

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

Photo by Ricardo Rocha on Unsplash

关于计算机视觉有一个著名的都市传说。大约在 80 年代,美国军方希望使用神经网络来自动检测伪装的敌人坦克。他们拍了一些没有坦克的树的照片,然后拍了同样的树后面有坦克的照片。结果令人印象深刻。如此令人印象深刻,以至于军方想确定网络已经正确地概括了。他们拍摄了有坦克和没有坦克的树林的新照片,并在网络上再次展示。这一次,这个模型表现得很糟糕,它无法区分树林后面有坦克的图片和只有树的图片。原来没有坦克的照片都是阴天拍的,而有坦克的照片是晴天拍的!在现实中,网络学习识别天气,而不是敌人的坦克。

源代码可以在这里找到

这篇文章也可以作为交互式 jupyter 笔记本

没有自己的事情

在这篇文章中,我们将看到不同的技术来理解卷积神经网络内部发生了什么,以避免犯同样的美国陆军错误。

我们将使用 Pytorch 。所有的代码都可以在这里找到。大部分可视化都是从零开始开发的,然而,一些灵感和部分是从这里中获取的。

我们将首先介绍每种技术,对其进行简要解释,并在不同经典计算机视觉模型alexnetvgg16resnet之间进行一些示例和比较。然后,我们将尝试更好地理解机器人技术中使用的模型,仅使用正面摄像机的图像来预测本地距离传感器。

我们的目标不是详细解释每种技术是如何工作的,因为每篇论文都已经做得非常好了,而是使用它们来帮助读者可视化不同输入的不同模型,以更好地理解和突出不同模型对给定输入的反应。

稍后,我们将展示一个工作流程,在该流程中,我们将利用您在本次旅程中学到的一些技术来测试模型的健壮性,这对于理解和修复其局限性非常有用。

好奇的读者可以通过查看每个可视化的源代码和阅读参考资料来进一步理解。

序言

让我们从选择一个网络开始我们的旅程。我们的第一个模型将是老学校alexnet。Pytorch 的 torchvision.models包中已经提供了它

AlexNet( (features): Sequential( (0): Conv2d(3, 64, kernel_size=(11, 11), stride=(4, 4), padding=(2, 2)) (1): ReLU(inplace) (2): MaxPool2d(kernel_size=3, stride=2, padding=0, dilation=1, ceil_mode=False) (3): Conv2d(64, 192, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2)) (4): ReLU(inplace) (5): MaxPool2d(kernel_size=3, stride=2, padding=0, dilation=1, ceil_mode=False) (6): Conv2d(192, 384, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (7): ReLU(inplace) (8): Conv2d(384, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (9): ReLU(inplace) (10): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (11): ReLU(inplace) (12): MaxPool2d(kernel_size=3, stride=2, padding=0, dilation=1, ceil_mode=False) ) (classifier): Sequential( (0): Dropout(p=0.5) (1): Linear(in_features=9216, out_features=4096, bias=True) (2): ReLU(inplace) (3): Dropout(p=0.5) (4): Linear(in_features=4096, out_features=4096, bias=True) (5): ReLU(inplace) (6): Linear(in_features=4096, out_features=1000, bias=True) ) )

现在我们需要一些输入

现在我们需要一些输入图像。我们将使用三张图片,一只猫,美丽的圣彼得大教堂和一只狗和一只猫的图像。

我们装了一些包裹。在utils中,有几个效用函数来创建地块。

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

由于我们所有的模型都是在 imagenet 上训练的,这是一个包含1000不同类的巨大数据集,我们需要解析并规范化它们。

在 Pytorch 中,我们必须手动将数据发送到设备。在这种情况下,设备如果第一个gpu如果有,否则cpu被选中。

请注意,jupyter 没有垃圾收集,所以我们需要手动释放 gpu 内存。

我们还定义了一个实用函数来清理 gpu 缓存

正如我们所说的,imagenet是一个包含1000类的巨大数据集,由一个不太容易被人类理解的整数表示。我们可以通过加载imaganet2human.txt将每个类 id 与其标签相关联,并创建一个 python 字典。

[(0, 'tench Tinca tinca'), (1, 'goldfish Carassius auratus')]

权重可视化

第一个直观的方法是绘制目标层的权重。显然,当通道数增加时,我们越深入,每个图像变得越小。我们将每个通道显示为灰色阵列图像。不幸的是,每个 Pytorch 模块都可以嵌套,所以为了使我们的代码尽可能通用,我们首先需要跟踪输入遍历的每个子模块,然后按顺序存储每一层。我们首先需要trace我们的模型来获得所有层的列表,这样我们就可以选择一个目标层,而不用遵循模型的嵌套结构。在PyTorch中,模型可以无限嵌套。换句话说,我们在奉承模型的层,这是在[module2traced](https://github.com/FrancescoSaverioZuppichini/A-journey-into-Convolutional-Neural-Network-visualization-/blob/master/utils.py#)函数中实现的。

[Conv2d(3, 64, kernel_size=(11, 11), stride=(4, 4), padding=(2, 2)), ReLU(inplace), MaxPool2d(kernel_size=3, stride=2, padding=0, dilation=1, ceil_mode=False), Conv2d(64, 192, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2)), ReLU(inplace), MaxPool2d(kernel_size=3, stride=2, padding=0, dilation=1, ceil_mode=False), Conv2d(192, 384, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)), ReLU(inplace), Conv2d(384, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)), ReLU(inplace), Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)), ReLU(inplace), MaxPool2d(kernel_size=3, stride=2, padding=0, dilation=1, ceil_mode=False), Dropout(p=0.5), Linear(in_features=9216, out_features=4096, bias=True), ReLU(inplace), Dropout(p=0.5), Linear(in_features=4096, out_features=4096, bias=True), ReLU(inplace), Linear(in_features=4096, out_features=1000, bias=True)]

让我们画出第一层的重量。我们还打印出重量的形状,以便给读者一个正确的降维概念。

torch.Size([1, 55, 55])

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

让我们停下来解释一下这些图像代表了什么。我们通过计算图追踪输入,以便找出我们模型的所有层,在本例中是alexnet。然后我们实例化在visualization.core中实现的Weights类,我们通过传递当前输入、图像和目标层来调用它。作为输出,我们将当前层的所有权重作为灰色图像。然后,我们画出其中的 16 个。我们可以注意到,它们在某种程度上是有意义的;例如,图像边缘的一些像素更亮。

让我们绘制第一个MaxPool层,以便更好地看到这种效果,维度减少和一些有趣区域的更高亮度像素。

如果你想知道 maxpolling 操作在做什么,看看这个棒极了的回购

torch.Size([1, 27, 27])

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

让我们试试另一个输入,圣彼得大教堂

torch.Size([1, 27, 27])

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

通过观察它们,这些图像在某种程度上变得有意义;他们强调了巴西利卡的布局,但是很难理解这个模型实际上在做什么。我们的想法是,正确地计算一些东西,但是我们可以问一些问题,例如:它是在看圆顶吗?巴西利卡最重要的特征是什么?

此外,我们越深入,就越难识别输入。

torch.Size([1, 13, 13])

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

在这种情况下,我们不知道发生了什么。可以认为,权重可视化并不携带任何关于模型的有用信息,即使这几乎是真实的,也有一个绘制权重的好理由,尤其是在第一层。

当模型训练很差或根本没有训练时,第一个权重有很多噪声,因为它们只是随机初始化的,并且它们比训练的图像更类似于输入图像。这一特性有助于即时了解模型是否经过训练。然而,除此之外,重量可视化并不是了解您的黑盒在想什么的方法。下面,我们首先为未训练版本的alexnet和训练版本的绘制第一层的权重。

torch.Size([1, 55, 55]) torch.Size([1, 55, 55])

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

您可以注意到,在第一幅图像中可以更容易地看到输入图像。这不是一个通用的规则,但在某些情况下它会有所帮助。

与其他模型的相似之处

我们已经看到了alexnet的重量,但它们在不同型号之间相似吗?下面我们为alexnetvggresnet绘制每个第一层的前 4 个通道的权重

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

resnetvgg权重看起来比alexnet更类似于输入图像。但是,这又意味着什么呢?请记住,至少 resnet 的初始化方式与其他两个模型不同。

显著性可视化

深度卷积网络提出的一个想法:可视化图像分类模型和显著图 是相对于目标类别反向支持网络的输出,直到输入并绘制计算的梯度。这将突出显示负责该类的图像部分。先说 alexnet。

让我们首先打印网络的预测(如果重新运行单元,这可能会改变)

predicted class tiger cat

每个可视化都在自己的类中实现。你可以在这里找到代码。它将反向传播与对应于class tiger cat的数字的一个热编码表示相关的输出

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

我们可以看到alexnet对猫感到兴奋。我们甚至可以做得更好!反向推进时,我们可以将每个设置为0 relu 梯度。这项技术被称为guided

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

现在我们可以清楚地看到,网络在看猫的眼睛和鼻子。我们可以试着比较不同的模型

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

Alextnet似乎对眼睛更感兴趣,而VGG看耳朵,resnet 类似于alexnet。现在我们可以清楚地了解输入的哪一部分有助于网络给出预测。

虽然引导产生了更好的人可理解的图像,但是普通的实现可以用于定位感兴趣的对象。换句话说,我们可以通过从输入图像中裁剪出对应于梯度的区域来免费找到感兴趣的对象。让我们为每个模型绘制每个输入图像。

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

巴西利卡非常有趣,所有四个网络都正确地将其归类为dome,但只有resnet152对天空比对圆顶更感兴趣。在最后一列中,我们有一个包含两个类的图像,dogcat。所有的网络都突出了展台,就像vgg16中的狗的眼睛和猫的耳朵。如果我们只想发现与特定类相关的输入区域,该怎么办?用这种技术是不可能的。

类激活映射

类别激活映射是在学习深度特征用于鉴别定位中提出的技术。其思想是使用最后的卷积层输出和模型的线性层中负责目标类的神经元,通过取它们的点积来生成映射。然而,为了使这个工作,模型必须有一些约束。首先,卷积的输出必须首先通过全局平均轮询,它要求特征映射直接位于 softmax 层之前。为了让它与其他架构一起工作,比如alexnetvgg,我们必须改变模型中的一些层并重新训练它。这是一个主要缺点,将在下一节中解决。目前,我们可以通过 resnet 免费使用它!因为它的建筑是完美的。

实现可以在这里找到。我们可以向可视化传递一个target_class参数,以从 fc 层获得相对权重。

请注意,通过更改目标类,我们可以看到图像的不同部分被突出显示。第一个图像使用预测类,而第二个使用另一种类型的cat和最后一个bookcase,只是为了看看模型会对错误的类做什么。

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

这是有意义的,唯一的事情是在最后一行我们仍然有猫的一部分为bookcase高亮显示

让我们在不同的resnet建筑的cat图像上绘制 CAM。对于 resnet > 34,使用Bottleneck模块

Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers). Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers).

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

和预想的都很像。这种技术的一个很大的缺点是强迫你使用一个具有特定架构的网络,在解码器部分之前进行全局轮询。下一种技术通过利用一个特定层的梯度来推广这种方法。记住类激活时,我们使用特征图的权重作为最后一层通道的比例因子。要素地图必须位于 softmax 图层之前和平均池之后。下一项技术提出了一种更通用方法。

Grad Cam

Grad CamGrad-CAM 推出:通过基于梯度的定位从深度网络进行视觉解释。这个想法实际上很简单,我们对目标类的输出进行反投影,同时存储给定层的梯度和输出,在我们的例子中是最后的卷积。然后,我们对保存的梯度进行全局平均,保持信道维度,以获得 1-d 张量,这将表示目标卷积层中每个信道的重要性。然后,我们将卷积层输出的每个元素乘以平均梯度,以创建梯度 cam。整个过程是快速的,并且是独立于体系结构的。有趣的是,作者表明这是先前技术的一种推广。

这里的代码是这里的

我们可以用它来突出不同的模型在看什么。

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

alexnet看鼻子、vgg看耳朵、resnet看整只猫真的很有趣。有趣的是,这两个版本看起来像猫的不同部位。

下面我们为resnet34绘制了相同的输入,但是我们改变了每一列中的目标类,以向读者展示 grad cam 是如何相应改变的。

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

注意它们与CAM的输出是多么的相似。为了更好地比较我们的三个模型,下面我们为每个模型的每个输入绘制梯度凸轮

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

读者可以立即注意到不同型号之间的差异。

有趣的区域

我们之前讨论过有趣的区域本地化。Grad-cam 还可以用于从图像中提取类对象。很容易,一旦有了 grad-cam 图像,我们就可以用它作为蒙版从输入图像中裁剪出我们想要的东西。读者可以使用TR参数来查看不同的效果。

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

等着瞧!我们也可以再次改变类,并为该类裁剪感兴趣的区域。

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

不同型号

我们已经看到了在imagenet上训练的经典分类模型使用的所有这些技术。在不同领域使用它们怎么样?我已经把这篇论文移植到 Pytorch 并重新训练了它。该模型通过学习机器人正面摄像机的图像来预测本地距离传感器,以避开障碍物。让我们看看,通过使用这些技术,我们是否能更好地理解模型内部的情况。

使用来自短程传感器和里程计的自我监督学习远程感知

其思想是在给定远程传感器(如摄像机)的当前输出的情况下,预测短程传感器(如近程传感器)的未来输出。他们从机器人的相机图像中训练了一个非常简单的 CNN 来预测接近传感器的值。如果你对他们的工作感兴趣,你可以在这里阅读全文

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

我做了一个 PyTorch 实现,并从头开始重新训练这个模型。请注意,我没有微调或尝试不同的超参数集,所以我的模型可能没有作者的模型表现得好。

让我们导入它

我们知道需要一些输入来测试模型,它们直接取自测试集

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

然后作者标准化每张图片,这是由 callind pre_processing完成的。由于某种原因,在 mac 和 ubuntu 上的输入图像是不同的,如果你在 mac 上运行笔记本,结果是不同的。这可能是由于警告消息。

我们将使用SaliencyMapGradCam,因为它们是最好的

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

我们可以清楚地看到模型注视着物体。在第二张图片的GradCam行中,计划基本上由热图分割。有一个问题,如果你看第三张图,相机前面的白色方框没有被清晰地突出。这可能是因为地板的白色与盒子的颜色非常相似。我们来调查一下这个问题。

在第二行中,SaliencyMaps高亮显示所有对象,包括白色框。读者可以注意到,左边第一张图中的反射似乎激发了该区域的网络。我们还应该调查这个案例,但是由于时间限制,我们将把它作为一个练习留给好奇的读者。

为了完整起见,让我们也打印预测的传感器输出。该模型试图预测五个正面距离传感器给图像相机。

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

如果你和作者的照片比较,我的预测会更糟。这是因为为了加快速度,我没有使用所有的训练集,也没有进行任何超参数优化。所有的代码都可以在这里找到。现在让我们研究第一个问题,与地面颜色相似的物体。

相似的颜色

为了测试模型是否有一个与地面颜色相同的障碍物的问题,我们在 blender 中创建了四个不同的障碍物场景。如下图所示。

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

有四种不同的灯光配置和两种不同的立方体颜色,一种与地面相同,另一种不同。第一列代表真实的情况,而第二列有来自后面的非常强的光,在相机前面产生阴影。第三列左边有阴影,最后一列左边有一点阴影。

这是使用 gradcam 查看每个图像中的模型的完美场景。在下图中,我们绘制了 gradcam 结果。

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

第二列中的大阴影肯定会混淆模型。在第一列和最后一列,grad cam 更好地突出了红色立方体的角,尤其是在第一张图片中。我们可以肯定地说,这个模型与地面颜色相同的物体有些困难。由于这种考虑,我们可以改进数据集中相等对象/背景的数量,执行更好的预处理,改变模型结构等,并且有希望增加网络的鲁棒性。

结论

在这篇文章中,我们提出了不同的卷积神经网络可视化技术。在第一部分中,我们通过应用于一组著名的分类网络来介绍每一个。我们比较了不同输入的不同网络,并强调了它们之间的相似性和差异。然后,我们将它们应用于机器人学中采用的模型,以测试其鲁棒性,我们能够成功地揭示网络中的问题。

此外,作为一个附带项目,我开发了一个名为 mirro r 的交互式卷积神经网络可视化应用程序,它在短短几天内就在 GitHub 上收到了一百多颗星,反映了深度学习社区对这个主题的兴趣。

所有这些可视化都是使用一个公共接口实现的,并且可以作为 python 模块使用,因此它们可以在任何其他模块中使用。

感谢您的阅读

一种用于图像分割的 Keras 流水线

原文:https://towardsdatascience.com/a-keras-pipeline-for-image-segmentation-part-1-6515a421157d?source=collection_archive---------2-----------------------

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

Photo by Soragrit Wongsa on Unsplash

网上有数百个教程,教你如何使用 Keras 完成图像分割任务。这些非常有帮助,通常对您的用例来说已经足够了。然而,对于初学者来说,即使是从普通的深度学习任务开始,也可能显得势不可挡。在开始训练过程之前,有一些普通的操作需要完成——准备数据,创建分区(train,val,test ),准备模型。在本教程(分为 3 个部分)中,我试图创建一个可访问的整个图像分割管道的演练。这包括:

a)创建和结构化数据集

b)生成训练和评估图像

c)模型选择、加载和编译以及培训。

希望在本课程结束时,您能够轻松地尝试自己的图像分割初学者项目,或者任何此类专注于图像的深度学习问题。

我们开始吧!

第一部分:数据集

图像分割中的问题稍微复杂一点*(不像分类),因为你必须跟踪你的图像它们的遮罩。*

通常,你会使用 PASCAL VOC ,或者 MS COCO ,或者 Cityscapes ,这取决于你想要解决什么问题。

如果是这样的话,那么您的大部分工作就完成了,因为这些存储库已经为您创建了 train、val 和 test 集。你所要做的就是下载它们,并把它们放到相关的目录中[更多细节见下文]。

但是,如果您希望在自己的数据集上运行图像分割模型,请参考以下内容:

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

Structure of your data

其中 mask_001.png 对应 frame_001.png 的掩码,以此类推。

对于那些已经在使用我上面提到的公共数据集的人来说,你所要做的就是保持上面提到的目录结构。

对于其他使用自己的数据集的人,您需要编写一个脚本来完成这项工作。我写了一个给你参考:

让我们浏览一下这段代码。

我假设所有的图像都在“帧”目录中,相应的蒙版在“蒙版”目录中,都在DATA_PATH

随机化 train、test 和 val 分区的一个好方法是列出文件,按 id 对它们进行排序并对它们进行洗牌【注意使用一个恒定的随机种子——改变的种子将在洗牌中产生改变的顺序】。

这就是线23–34所实现的。

接下来,我们分别为我们的训练集、val 集和测试集使用一个70–20–10比率。这是通常使用的测试,尽管60–30–1080–10–10并非闻所未闻。这是 Python 中一个简单的列表索引操作。

我们在第39–44行中这样做。

随后的几行运行一个 list comprehension 来遍历所有帧,并简单地将训练帧添加到 train_frames ,将验证帧添加到 val_frames ,将测试帧添加到 test_frames

我们现在有了包含图像 id 的必要列表。但是,我们仍然需要将这些列表中的图像保存到相应的[正确]文件夹中。函数 add_frames()add_masks() 对此有所帮助。

正如您可能已经猜到的,有多种方法可以做到这一点。你可以通过实验找到最快的的方法,但是我发现了一个相当有效的方法:

  1. 从两个元组列表开始。元组构成了图像列表,以及它们相应的目录名。将这些 frame_foldersmask_folders ,前者保存我们所有帧列表的细节——train、val、test——后者保存我们所有 mask 列表的细节。
  2. 遍历 frame_foldersmask_folders【一个接一个】,使用 map() 函数将每张图片分别映射到 add_frames()add_masks() 函数。我使用 map 代替琐碎的循环,只是因为 Python 的内置 map()快得多。我还没有测试它更快的确切顺序,如果有读者这样做,我会很高兴。**

对于 1000 个图像[+1000 个遮罩]的非常小的数据集,设置文件夹只需不到一分钟的时间。一个很好的实验是找到更快的方法来做到这一点。我很想听听你的想法。

这样,我们就有了数据集!

第 1 部分到此结束。

在第 2 部分中,我们将研究图像分割管道的另一个重要方面——为训练生成批量图像。

在本教程的第一部分,我们学习了如何准备和组织我们的图像分割任务中使用的数据。在这一部分,我们将我们的任务向前推进了一步——生成这些图像。

第 2 部分:发电机

Keras 图像数据生成器

为了训练你的模型,理想情况下你需要生成一批图像来支持它。当你这样做的时候,你可能想对所有的图像进行普通的操作——像缩放、旋转、裁剪和移动等操作。这被称为数据增强。事实上,一个非常常见的做法是将所有图像的大小调整为一个形状,以使训练过程统一。

请注意,数据扩充不会改变你的图像——它只是创建了同一图像的另一种表示。想象一下,如果有人给你拍了一张照片,然后将这张照片旋转了某个角度。这是两张不同的图片,但是图片的对象【你】没有变化。

为了实现这一点,我们使用 Keras 的 ImageDataGenerator

根据文件:

通过实时数据扩充生成批量张量图像数据。数据将(分批)循环。

我们分别创建我们的训练和验证生成器对象。您可以看到,训练图像将通过重新缩放、水平翻转、剪切范围和缩放范围得到增强。

对于这些操作意味着什么的描述,更重要的是,它们看起来像什么,到这里

当谈到如何初始化对象时,没有唯一正确的答案。这取决于谁在设计它们,以及他的目标是什么。

现在我们的生成器对象已经创建好了,我们使用非常有用的flow_from_directory():来启动生成过程

我们需要向 Keras 提供的只是目录路径和批处理大小。还有其他的选择,但是现在,这已经足够让你开始了。

最后,一旦我们分别有了训练集和验证集的框架和掩码生成器,我们就 zip() 它们一起创建:

a) train_generator :训练帧和掩码的生成器。

b) val_generator :验证帧和掩码的生成器。

创建您自己的数据生成器

在设计生成器时,Keras ImageDataGenerator 绝不是唯一的选择。自定义生成器也经常使用。这些为设计者提供了更大的选择灵活性。请参见下面的示例:

我们已经决定让所有图像的大小为(512 * 512 * n),其中 n = 3,如果它是正常的 RGB 图像,n = 1,用于该图像的相应蒙版,这显然是灰度图像。

我们初始化两个数组来保存每个图像(和每个遮罩)的细节,这将是三维数组本身。所以, img遮罩是数组的数组。

我们使用 yield 的简单目的是生成一批图像,而不是使用 return 一次生成所有图像。关于何时使用其中一个而不是另一个的清晰解释,请参见

最后,我们创建我们的训练和验证生成器,通过一次 传递训练图像、遮罩路径和验证图像、遮罩路径以及批处理大小。****

然而,在这种情况下,我们并没有即时使用随机变换。假设您正在处理一个图像分割问题,其中要分割的对象的位置也很重要。你还会使用旋转、缩放和移动吗?精神食粮。

归根结底,这都是个人的选择。这两种方法都有效。在特定情况下,人们可能会发现一种方法比另一种更有用,反之亦然。

太好了!现在我们已经准备好了生成器对象。

训练时间到了!

第 3 部分:培训

在前两节中,我们学习了如何准备数据,以及如何创建图像生成器来帮助培训。在这最后一部分,我们将看到如何使用这些生成器来训练我们的模型。

这部分将结束我们的整个管道。

在我们开始训练之前,我们需要决定使用哪种架构。幸运的是,大多数流行的都已经实现了,并免费提供给公众使用。一些例子包括:

  1. Keras UNet 实施
  2. Keras FCNet 实现。

开始时,您不必太担心这些体系结构中的差异,以及在哪里使用什么。到目前为止,您可以简单地将这个 model.py 文件放在您的工作目录中,并将其导入到 train.py 中,这将是培训代码所在的文件。

希望您的工作目录如下所示:

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

请注意新的代码文件,以及我们之前看到的数据目录。

假设您正在使用 FCNet_VGG16_32s ,让我们来看看加载、编译和运行模型的一行程序。

在必要的导入之后,第8–13行初始化完全取决于您的数据集和您选择的输入的变量——例如:您决定的批量大小,以及您的模型将训练的时期数。

线 15 初始化路径,每个时期后的权重[一个 .h5 文件]将被保存到该路径。

17–22 行是加载和编译模型的必要步骤。请注意,我没有指定使用什么度量标准。对于图像分割任务,一个流行的度量是骰子系数【反之,骰子损失】。这里可以找到一个很好的实现

24–32行也是样板 Keras 代码,封装在一系列称为回调的操作下。

仅当满足模式参数时,我们才使用模型检查点来保存权重。要了解什么是监视器模式参数,请继续阅读。

我们确保我们的模型不会在不必要的长时间内训练,例如:如果损失在连续的时期内没有显著减少,我们设置一个耐心参数,在我们的损失没有显著减少的一定数量的时期后自动停止训练。当我提到“显著”时,我指的是 min_delta 参数。在这种情况下,我们检查我们的损失是否至少减少了 0.1%。在这种情况下,我们的耐心是 3 ,这是连续周期的数量,在此之后,如果损失没有减少至少 0.1,训练将自动停止。

****监视器参数定义了您想要检查其值的指标——在我们的例子中,是骰子损失。模式参数定义了训练停止的时间,如果监控量减少,则为【最大】,如果增加,则为【最小】

所以,如果你在监控精度,模式应该是最大**。但是如果你在监控均方差,模式将会是最小。**

这整个现象叫做。希望到现在为止,你已经理解了为什么这么叫了。****

第 34 行是训练步骤。我们传递所有需要的输入,包括:

a)训练和验证图像生成器,如前所述。

b)历元的数量。

c)每个时期的步骤数取决于图像总数和批次大小。

d)最后,我们的回调列表,包括模型检查点和提前停止的条件。

最后我们调用 fit_generator 在这些生成器上进行训练。

训练开始了!

一旦训练完成,您可以使用保存功能保存检查点架构及其所有权重。你可以随便给它起什么名字。

摘要

在这个由三部分组成的系列中,我们介绍了图像分割任务的整个 Keras 流程。从构建数据,到创建图像生成器,再到最终训练我们的模型,我们已经为初学者介绍了足够多的内容。当然,我们还可以做更多的事情。

您可以尝试不同的架构、不同的超参数(比如使用不同于 Adam 的优化器)、不同的停止条件(使用耐心参数)等等。

一个好主意是为不同的超参数绘制提前停止之前的时期数,评估度量值,并检查是否存在任何最佳超参数-模型-时期组合。****

我希望这个系列是可以理解的,如果有任何部分不清楚,我很乐意听到你的问题。

快乐深度学习!

深度神经网络的外行指南

原文:https://towardsdatascience.com/a-laymans-guide-to-deep-neural-networks-ddcea24847fb?source=collection_archive---------1-----------------------

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

深度学习基础

用 PyTorch 对深度神经网络的非数学介绍

序幕

最近关于人工智能的讨论已经在学术界和企业的神经网络中产生了足够的意识。你可能肯定遇到过强调某种形式的人工智能/神经网络系统将超越你的传统工作流程的内容。我相信你肯定听说过(尽管可能没有完全意识到)深度神经网络和深度学习。

在这篇文章中,我想用最短但有效的方法来介绍这个主题,以拥抱深度神经网络并使用 PyTorch 实现它们。

深度神经网络的外行定义,也称为深度学习

取 1

深度学习是人工智能(A.I .)中机器学习的一个子领域,它处理从大脑的生物结构和功能中获得灵感的算法,以帮助机器获得智能。

听起来复杂吗?让我们通过进一步分解定义中的每个单词来简化它,并再次与定义进行讨论。我们将首先从人工智能开始 A.I

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

Source — Learn Keras for Deep Neural Networks (Apress)

人工智能(A.I .)最一般的形式可以被定义为引入机器的智能质量。机器通常是愚蠢的,所以为了让它们更聪明,我们引入了某种智能,这样它们就可以独立做出决定。比如说,洗衣机可以决定摄入适量的水,决定浸泡、洗涤和脱水所需的时间,即在提供特定输入时做出决定,从而以更智能的方式工作。类似地,一台 ATM 机,它可以根据机器中可用的纸币的正确组合来支付你想要的金额。这种智能在技术上是以人工方式引入机器的,这就是为什么称之为人工智能的原因。

这里需要注意的重要一点是,这种智能是明确编程的,比如一个 if-else 规则的综合列表。设计系统的工程师仔细考虑了所有可能的组合,并设计了一个基于规则的系统,该系统可以通过遍历定义的规则路径来做出决定。如果我们需要在没有显式编程的情况下在机器中引入智能,可能是机器可以自己学习的东西,会怎么样。那就是我们用机器学习触底的时候。

机器学习可以定义为在没有显式编程的情况下,将智能诱导到系统或机器中的过程

  • 安德鲁·吴,斯坦福兼职教授

机器学习的例子可以是通过从历史测试结果和学生属性中学习来预测学生是否会在测试中失败或通过的系统。在这里,系统并没有编码有所有可能的规则的综合列表,这些规则可以决定学生是通过还是失败,相反,系统根据它从输入的历史训练数据中识别的模式进行自我学习。

那么,深度学习在这种背景下处于什么位置呢?碰巧的是,机器学习虽然对各种问题都非常有效,但在一些对人类来说非常容易的特定情况下却无法超越。例如,将图像分类为猫或狗,或者将音频剪辑区分为男性或女性声音等。机器学习通常在处理图像、音频和其他非结构化数据类型时表现不佳。在研究这种糟糕表现的原因时,一种灵感的想法导致了模仿人脑生物过程的想法,这种过程由数十亿神经元连接和协调组成,以适应学习新事物。与此同时,神经网络已经成为一个研究课题好几年了,并且由于当时计算和数据的限制,只取得了有限的进展。当研究人员到达机器学习和神经网络的尖端时,出现了深度学习领域,该领域通过开发深度神经网络来构建,即具有更多层的临时神经网络。

现在,让我们再做一次尝试来理解深度学习的定义。

取 2

深度学习是机器学习和人工智能(A.I .)中的一个领域,它处理从人脑中获得灵感的算法,在没有显式编程的情况下帮助机器获得智能。

现在不是更容易理解了吗?😃

深度学习擅长于机器学习落后的新领域。随着时间的推移,额外的研究和实验导致了这样一种理解,即我们可以利用深度学习来完成所有机器学习任务,并期望在有剩余数据可用的情况下获得更好的性能。因此,深度学习成为解决预测问题的无处不在的领域,而不仅仅局限于计算机视觉、语音等领域。

今天深度学习解决了哪些问题?

随着经济高效的计算能力和数据存储的出现,深度学习已经融入到我们日常生活的每个数字角落。基于深度学习的常见日常生活数字产品的几个例子是流行的虚拟助手,如Siri/Alexa/Google Assistant,在上传的脸书照片中标记朋友的建议,特斯拉中的自动驾驶, Snapchat 中的猫滤镜,亚马逊网飞中的产品推荐,以及最近流行的照片应用,如【face app你可能已经在没有意识到的情况下使用了基于深度学习的产品。

深度学习已经涉足几乎所有的行业垂直领域,如检测癌症和糖尿病视网膜病变的医疗保健、车队优化的航空、机器预测维护的石油&天然气、欺诈检测的银行&金融服务、客户流失预测的零售电信等等。Andrew NG 正确地引用了人工智能是新的电力。就像电改变了一切一样,在不久的将来,人工智能将改变几乎一切。

分解深层神经网络

深度神经网络的简化版本被表示为与其他神经元连接的神经元(类似于大脑中的神经元)的分级(分层)组织。这些神经元根据收到的输入向其他神经元传递消息或信号,并形成一个复杂的网络,通过某种反馈机制进行学习。下图表示一个“N”层深度神经网络。

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

A Deep Neural Network with N hidden layers

如上图所示,输入数据由第一层(未隐藏)中的神经元消耗,然后向下一层中的神经元提供输出,依此类推,提供最终输出。输出可能是“是”或“否”这样的预测(用概率表示)。每层可以有一个或多个神经元,每个神经元将计算一个小函数,即激活函数。激活功能模拟信号传递给下一个连接的神经元。如果输入神经元产生大于阈值的值,则输出被传递,否则被忽略。连续层的两个神经元之间的连接将具有关联的权重。权重定义了输入对下一个神经元的输出的影响,以及最终对整个最终输出的影响。在神经网络中,初始权重将全部是随机的,但是在模型训练期间,这些权重被迭代地更新,以学习预测正确的输出。分解网络,我们可以定义几个逻辑构建块,如一个神经元权重输入输出、一个激活函数以及最后一个 l 收益机制(优化器),这将帮助神经网络递增地更新权重(随机初始化的)为更合适的权重,从而有助于正确预测结果。

为了直观的理解,让我们举一个人类大脑如何学习识别不同人的例子。当你第二次见到一个人时,你就能认出他。这是怎么发生的?人在整体结构上有相似之处;两只眼睛,两只耳朵,一个鼻子,嘴唇等等。每个人都有相同的结构,但我们能够很容易地区分人,对不对?

大脑中学习过程的本质是相当直观的。它不是学习面部的结构来识别人,而是学习与普通面部的偏差,即他的眼睛与参考眼睛有多不同,然后可以量化为具有定义强度的电信号。类似地,它从参考基准学习面部所有部分的偏差,并将这些偏差组合成新的维度,并最终给出输出。所有这一切都发生在不到一秒钟的时间里,我们没有人意识到我们的潜意识实际上做了什么。

类似地,上面展示的神经网络试图使用数学方法来模拟相同的过程。输入由第一层中的神经元消耗,并且在每个神经元内计算激活函数。根据一个简单的规则,它将输出转发给下一个神经元,类似于人脑学习的偏差。神经元的输出越大,输入维度的重要性就越大。这些维度然后在下一层被组合起来形成额外的新维度,这是我们可能无法理解的。但是系统凭直觉学习。这一过程,当乘以几倍,发展成一个复杂的网络与几个连接。

现在已经了解了神经网络的结构,让我们来了解学习是如何发生的。当我们向已定义的结构提供输入数据时,最终输出将是一个预测(通过一系列矩阵乘法),它可能是正确的,也可能是不正确的。基于该输出,如果我们向网络提供反馈,以使用一些手段来改进,从而更好地预测,则系统通过更新连接的权重来学习。为了实现以正确的方式提供反馈和定义下一步进行更改的过程,我们使用了一种美丽的数学算法,称为“”。随着越来越多的数据逐步迭代该过程几次,有助于网络适当地更新权重,以创建一个系统,在该系统中,它可以根据它通过权重和连接为自己创建的规则来做出预测输出的决策。

深度神经网络的名称是从使用更多隐藏层演变而来的,使其成为学习更复杂模式的“深度”网络。深度学习的成功故事只是在最近几年才浮出水面,因为训练网络的过程计算量很大,需要大量数据。只有当计算和数据存储变得更加可用和经济实惠时,这些实验才最终得以实现。

深度学习有哪些流行的框架?

鉴于深度学习的采用已经以惊人的速度推进,生态系统的成熟度也显示出惊人的提高。多亏了许多大型技术组织和开源项目,我们现在有了太多的选择。这些深度学习框架为我们提供了可重用的代码块,这些代码块抽象了我们上面讨论的逻辑块,并在开发深度学习模型时提供了几个额外的便利模块。

我们可以将可用选项分类为低级或高级深度学习框架。虽然这绝不是业界公认的术语,但我们可以使用这种分离来更直观地理解框架。低级框架提供了更基本的抽象块,同时为定制和灵活性提供了大量空间。高级框架进一步聚合了抽象以简化我们的工作,同时限制了定制和灵活性的范围。高级框架使用低级框架作为后端,并且通常通过将源代码转换成期望的低级框架来执行。下面是深度学习框架的几个流行选择。

低层框架

  1. 张量流
  2. MxNet
  3. PyTorch

高层框架

  1. Keras(使用 TensorFlow 作为后端)
  2. 胶子(使用 mxnet 作为后端)

目前,最受欢迎的选择是 Tensorflow(由谷歌提供)。鉴于 Keras 在快速构建深度学习模型方面提供的便利,它也很受欢迎。然而,PyTorch(由脸书开发)是另一个流行的框架,它正以惊人的速度赶上这场竞赛。PyTorch 对于许多人工智能实践者来说是一个很好的选择,比 TensorFlow 有更容易的学习曲线,可以轻松地从原型开发到生产深度学习模型。

在本教程中,我们更喜欢使用 PyTorch 来实现一个婴儿神经网络。在决定选择框架之前,您应该进行更多的调查和研究。Skymind 的这篇 文章 提供了很好的对比和细节,有助于确定您需要的框架。

然而,这篇文章不会介绍 PyTorch。我会推荐探索 PyTorch 的官方教程。此外,猫王的这本指南对于 PyTorch 初学者来说也是一篇不错的文章。

用 PyTorch 构建婴儿神经网络

对这个主题有了一个基本的外行概述,我们现在可以开始在 PyTorch 中构建一个基本的神经网络。在本例中,我们生成了一个虚拟数据集,它模拟了一个具有 32 个特征(列)和 6000 个样本(行)的分类用例。数据集将使用 PyTorch 中的 randn 函数进行渲染。

这段代码也可以从 Github 库获得

总结想法

这篇文章的目的是用一种非常简单的语言给初学者一个简单的入门。保持数学的抽象和专注,从纯粹的功能性手段来利用现代企业项目的深度学习。大部分内容都是从我的书‘学习深度神经网络的 Keras’的第一章借来的。

在下一篇文章中,我将介绍“卷积神经网络的外行指南”,同样的例子将在 PyTorch 中给出。

从喀拉斯到皮托尔彻的专家指南

原文:https://towardsdatascience.com/a-laymans-guide-to-moving-from-keras-to-pytorch-37fe56b6f588?source=collection_archive---------26-----------------------

说真的,是时候搬家了

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

最近我在 Kaggle 上开始了一场关于文本分类的比赛,作为比赛的一部分,我不得不设法转移到 Pytorch 上以获得确定性的结果。现在,我过去一直与 keras 一起工作,它给了我相当好的结果,但不知何故,我知道 Keras 中的 CuDNNGRU/CuDNNLSTM 层不是确定性的,即使在设置种子之后。所以 Pytorch 来营救了。我很高兴我考虑过搬家。

作为边注:如果你想了解更多关于 NLP 的知识,我在此推荐 高级机器学习专精 中关于 自然语言处理 的这门牛逼课程。本课程涵盖了自然语言处理中从基础到高级的各种任务:情感分析、摘要、对话状态跟踪等等。

好吧,回到手头的任务。虽然 Keras 从深度学习开始很好,但随着时间的推移,你会对它的一些局限性感到不满。我考虑过搬到 Tensorflow。这似乎是一个很好的过渡,因为 TF 是 Keras 的后端。但是这很难吗?对于整个session.run命令和张量流会话,我有点困惑。它根本不是毕氏的。

Pytorch 在这方面有所帮助,因为它看起来像是 python 做事的方式。一切都在你的掌控之中,在性能方面没有任何损失。用安德烈·卡帕西的话说:

我已经使用 PyTorch 几个月了,从来没有感觉这么好过。我有更多的精力。我的皮肤更干净了。我的视力提高了。

—安德烈·卡帕西(@卡帕西)2017 年 5 月 26 日

所以事不宜迟,让我为你把 Keras 翻译成 Pytorch。

写你的网络的经典方式?

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

好,让我们首先在 keras 中创建一个示例网络,我们将尝试将它移植到 Pytorch 中。在这里,我也想给你一个建议。当你试图从 Keras 迁移到 Pytorch 时,使用你拥有的任何网络,并尝试将其移植到 Pytorch 。这会让你更好地理解 Pytorch。在这里,我试着写一个在 Quora 虚假问题分类挑战中给我很好结果的网络。这个模型具有至少任何文本分类深度学习网络可以包含的所有功能,包括 GRU、LSTM 和嵌入层,以及元输入层。因此可以作为一个很好的例子。如果你想了解更多关于比尔斯特姆/GRU 和注意力模型是如何工作的,请访问我的帖子这里

因此 pytorch 中的模型被定义为一个从nn.module继承而来的类(因此更优雅一点)。每个类都必须包含一个__init__程序块和一个forward通道块。

  • __init__部分,用户定义了网络将要拥有的所有层,但还没有定义这些层如何相互连接
  • 在正向传递模块中,用户定义数据如何在网络中从一层流向另一层。

为什么这是经典?

显然是因为上课而显得优雅。咄!但玩笑归玩笑,我发现它是有益的,原因有几个:

1)它让你对如何构建你的网络有很大的控制权。

2)当您构建网络时,您对网络有很多了解,因为您必须指定输入和输出维度。所以出错的几率更小。(虽然这个真的要看技能水平了)

  1. 易于调试的网络。任何时候你发现网络有任何问题,只要在正向传递中使用类似print("avg_pool", avg_pool.size())的东西来检查层的大小,你就可以很容易地调试网络

4)您可以从正向层返回多个输出。这在编码器-解码器架构中非常有用,因为您可以返回编码器和解码器的输出。或者在 autoencoder 的情况下,您可以返回模型的输出和数据的隐藏层嵌入。

  1. Pytorch 张量的工作方式与 numpy 数组非常相似。例如,我可以使用 Pytorch Maxpool 函数来编写 Maxpool 层,但是max_pool, _ = torch.max(h_gru, 1)也可以。

6)您可以用不同的初始化方案设置不同的层。一些你在喀拉斯做不到的事。例如,在下面的网络中,我改变了我的 LSTM 层的初始化方案。LSTM 图层对于偏差、输入图层权重和隐藏图层权重具有不同的初始化。

7)等到你看到 Pytorch 中的训练循环时,你会对它提供的控制感到惊讶。

现在 Pytorch 中的同一个模型看起来会像这样。请仔细阅读代码注释,了解更多关于如何移植的信息。

希望你还和我在一起。我想在这里强调的一点是,你需要用 Pytorch 编写一些代码来真正理解它是如何工作的。并且知道一旦你这样做了,你会很高兴你付出了努力。进入下一部分。

定制或现成:高度可定制的训练循环的最佳选择

在上面的部分,我写道,一旦你看到训练循环,你会感到惊讶。这是一种夸张。第一次尝试时,你会有点困惑。但是一旦你不止一次地通读这个循环,你会有很多直观的感觉。再次阅读注释和代码以获得更好的理解。

该训练循环对训练数据进行 k 重交叉验证,并输出对测试数据的运行进行平均的非折叠 train_preds 和 test_preds。如果这个流程看起来像是从 kaggle 竞赛中直接出来的,我很抱歉,但是如果你明白这一点,你就能够为自己的工作流程创建一个训练循环。这就是 Pytorch 的魅力。

所以这个循环的简要总结如下:

  • 使用培训数据创建分层拆分
  • 循环遍历拆分。
  • 使用X_train_fold = torch.tensor(x_train[train_idx.astype(int)], dtype=torch.long).cuda()命令将训练和 CV 数据转换为张量并将数据加载到 GPU
  • 使用model.cuda()命令将模型加载到 GPU 上
  • 定义损失函数、调度程序和优化程序
  • 创建train_loader和 valid_loader `来迭代批处理。
  • 开始运行纪元。在每个时代
  • 使用model.train()将模型模式设置为训练。
  • 检查train_loader中的批次并向前运行
  • 运行调度程序步骤以更改学习率
  • 计算损失
  • 将优化器中的现有梯度设置为零
  • 通过网络反向传播损失
  • 剪切渐变
  • 采取优化步骤来改变整个网络中的权重
  • 使用model.eval()将模型模式设置为评估。
  • 使用valid_loader获得验证数据的预测,并存储在变量valid_preds_fold
  • 计算损失并打印
  • 所有历元完成后,预测测试数据并存储预测。这些预测将在分割循环结束时进行平均,以获得最终的test_preds
  • 使用train_preds[valid_idx] = valid_preds_fold获得列车组的离差(OOF)预测
  • 然后,这些 OOF 预测可用于计算模型的局部 CV 分数。

但是为什么呢?为什么这么多代码?

好吧。我明白了。这可能是少数。在 keras 中用一个简单的.fit就可以完成的事情,在 Pytorch 中需要大量代码才能完成。但要明白,你也获得了很多权力。您需要了解的一些使用案例:

  • 在 Keras 中,您有预先指定的调度程序,如ReduceLROnPlateau(编写它们是一项任务),而在 Pytorch 中,您可以疯狂地尝试。如果你知道如何写 Python,你会过得很好
  • 想在两个时期之间改变模型的结构。是的,你能做到。动态更改卷积网络的输入大小。
  • 还有更多。只有你的想象会阻止你。

想自己经营吗?

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

You have all the tools! Do something…

这里还有一个小小的坦白。上面的代码将不会运行,因为有一些代码工件,我没有在这里显示。我这样做是为了让帖子更具可读性。就像你在上面的代码中看到的seed_everythingMyDatasetCyclicLR(来自杰瑞米·霍华德课程)函数和类,它们并没有真正包含在 Pytorch 中。但别担心,我的朋友。

我试过用完整的运行代码写一个 Kaggle 内核您可以在这里看到代码,并将其包含在您的项目中。

如果你喜欢这个帖子,请不要忘记也投票支持 内核 。我将不胜感激。

尾注和参考文献

这篇文章是许多优秀的 Kagglers 们努力的结果,我将在这一部分尝试引用他们。如果我漏掉了某个人,请理解我不是故意的。

原载于 2019 年 1 月 6 日mlwhiz.com

精益预测工作流程

原文:https://towardsdatascience.com/a-lean-forecasting-workflow-1a8a5eb2d4ab?source=collection_archive---------23-----------------------

如何使用精益数据科学工作流程创建良好的业务预测

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

Photo by Felix Wegerer on Unsplash

介绍

商业预测的工作基本上类似于典型的数据科学项目,但是它需要自己的调整才能正确完成。在本文中,我们打算应用精益框架,不仅产生良好的预测,而且确保您的流程为预测质量增值。

在这里,我们预测问题的例子将是预测一个零售连锁店的收入,但是它可以应用于许多其他用例。

工作流程

请求

这是你的客户提出他的预测请求的地方,你将开始发展你的业务理解。你可能有的许多问题会在这个过程的后期出现,但是没关系:只要确保你在一开始就已经涵盖了最重要的主题。以下是一些有用的问题:

  • 这些预测的目标是什么(了解你的总收入结构,指导生产决策,向股东报告…)?
  • 它们将如何被使用(它们应该被发送到一个漂亮的仪表板还是将被发送到另一个自动化系统)?
  • 谁会使用它们(是精通数据科学的人,公司的 CEO,投资者…)?
  • 我们会维护它们吗?谁来做?—我们稍后将详细讨论如何维护预测
  • 你想什么时候完成(截止日期是什么时候)?
  • 在什么水平上(整体、按商店、按产品……)?
  • 在什么时间段(每周,每月…)?
  • 我们将提前多长时间生成预测(下周、明年……)?
  • 是否有要使用的外部数据(天气、假期……)?

技术设置

在这里,您可以选择生成预测的工具或编程语言,还可以设计文件夹结构(如果适用)。就我个人而言,我喜欢每个步骤都有一个 Jupyter 笔记本:数据处理、分析和建模,但可以自由选择最适合你的。

这应考虑是否将预测发送到仪表板或存储您的数据的自动化系统,如果您的客户已经有一个预测系统,您打算如何获取外部数据,以及预测是否将被维护(以及由谁维护)。

在这一点上,你还必须设计你的数据工作流程:列出你的数据源,它们是如何被收集、存储和合并的,以及你的脚本在哪里。笔和纸在这里可能会有帮助。

数据处理

首先创建数据提取脚本:这些可能是来自数据库的查询,但也可能包括某种 web 清理。考虑所需的聚合级别、外部变量和时间框架。

一旦收集了数据,您将不得不清理它,这将提出一些常见的问题,例如如何处理离群值和缺失值?嗯,这个真的要看每个具体案例,我也不能真的给你提供一个最终的答案,但是试着问问自己:为什么这个值这么高/缺失?是真值,还是很可能是输入错误?然后考虑如何处理它:用一些公式(比如平均值)手动输入它,去掉它,用零代替它,等等。

最后,你会做一些特征工程:合并不同来源的数据,添加新的变量,现有变量的组合或函数(log,平方根等。)等等。你不必在这里面面俱到,如果需要的话,你可以稍后回到这一步,添加你在开始时没有想到的变量。

分析

这是你让你的好奇心自由奔跑的地方,并且真正理解你正在处理什么类型的数据。然而,这里可以回答几个问题作为进一步分析的起点:有趋势吗?这个时间序列是平稳的吗?有季节性吗?在什么级别(每天、每周…)?如果有外部变量,它们是如何相互作用的(尤其是与你试图预测的变量)?您可以为多对变量创建多个散点图。如果您发现您感兴趣的变量和另一个变量之间的关系具有某种特殊的形状,您可以返回到上一步,尝试在该变量上包含变换。例如,您可能会看到您的收入与观察到的降雨量有关,但不是以线性方式。

在分析过程中,您还需要根据数据定义适当的误差测量。常见的误差度量包括 RMSE、MAPE 和脉塞,但还有更多。根据你的目标和数据做出明智的选择。:MAPE 不适用于间歇性数据,即变量经常等于零的情况)。

一旦您定义了您的误差度量,您需要设置正确的基线:从现在开始,您将根据它来比较您获得的误差与您尝试的所有模型。你的基线是你用最简单的模型得到的误差。例如,如果您正在处理零售收入,该收入具有很强的年度季节性,您可以将明年 12 月的销售额预测为去年 12 月的销售额。你不需要一个奇特的模型或数据科学家来做这件事:一个 Excel 电子表格就可以了。因此,这是可接受的最大误差值,如果你的神经网络不能战胜它,那么它肯定不值得努力。低于这个级别的任何东西都可以被认为是一种改进,但是请记住,您可能不想为了几个额外的准确性点而牺牲可伸缩性和易于理解性。

现在你有了基线,你可以考虑适合你情况的模型。一些模型不处理季节性,而另一些不处理外部变量。现在有太多的方法,你不可能知道所有的方法,但是一定要列出所有的基本方法(这些方法往往执行得很好)和一些更高级的方法。基础知识包括 SARIMAX 系列模型和指数平滑方法。更复杂的方法包括使用 XGBoost、神经网络或脸书开发的 Prophet 算法。

系统模型化

建模部分本身是非常简单的,它将为返回到您的数据处理和分析步骤以及添加额外的变量和分析提供洞察力。

首先,您将把数据集分成三部分:训练、验证和测试。验证/测试术语通常有些混乱,但在这里,我假设训练数据用于训练您的模型,验证用于应用它们,查看哪个效果最好,并可能使用 insight 来更改一些超参数,测试集是您应用您的最佳模型并获得关于它在新数据上的表现的良好估计的地方。与其他数据科学问题不同,这种分裂不应该是随机的:因为你正在处理时间序列,所以你的观察顺序很重要,你应该保持这种顺序。相反,为每个数据集选择一个分割点(一个日期)。《出埃及记》:我将从 2015 年到 2018 年训练我的模型数据,在 2019 年的数据上验证它们,并在 2020 年的数据上测试我的最终模型。

但是,请记住,如果您的模型依赖于在它必须预测之前发生的观察,这种方法是不完整的。例如,如果您的模型应该根据过去三周来预测下周的预测,您将需要执行向前行走验证,这意味着当您每周进行预测时,您的训练集会逐渐变大。你可以在这里阅读更多相关信息

重复

通过应用所有这些模型,您肯定会了解更多关于您的数据行为的信息,这意味着您将通过数据处理和分析,甚至通过请求阶段,向您的客户询问您以前没有想到的问题并添加新功能。你这样做,直到你根据你的基线取得了令人满意的结果,或者如果你已经达到了客户给你的最后期限(或者如果你已经没有改进的想法了,很明显)。

同意

在许多情况下,您需要客户或更高层的批准来部署您的模型,这意味着您必须向他们展示您已经尝试过的模型、获得的结果,以及与基线相比您实现了多少。根据这些人是谁,您可能希望保持简单,或者更详细地了解度量和方法。但是,请确保您向他们现实地展示了他们可以从您的预测中得到什么(此处应使用预测置信区间)。

部署

到了部署的时候,您将使用您选择的基础设施来部署您的数据处理步骤,以及一个模型应用步骤,只包括您决定应用的模型(您不需要在这里继续测试模型,也不需要分析部分)。

监视

为了监控您的模型,您需要记住您想要跟踪的度量标准。不应该有太多(通常三个就足够了),他们至少应该测量偏差,平均误差和方差。除了这些指标之外,您还需要跟踪您的预测置信区间和实际观察值:确定一个可接受的误差阈值,无论何时您的预测开始偏离轨道,您的监控系统都应该发出某种标志。

结论

我希望这篇文章对您和您的预测需求有用,并记住这是整个工作流的一般指南,但这些步骤中的每一个可能都值得有自己的文章,因为每个步骤都有许多警告和注意点(我可能很快就会在这方面工作)。

有用的链接

本文展示了一个数据科学工作流的示例,并附有实际例子。

这家公司也有类似的目标,但重点是初创公司。

数据科学项目的模板(一种可以复制的文件夹结构)。

网飞管理数据科学项目的图书馆 meta flow。

脸书的先知,一个时间序列预测的优秀图书馆

用于嵌入人工智能的学习引擎

原文:https://towardsdatascience.com/a-learning-engine-for-embodied-ai-7ef54f6574f0?source=collection_archive---------26-----------------------

本文介绍了在游戏模拟器中创建自主代理的深度学习框架

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

An Agent Learning a Match to Sample Task using Neurostudio

由于能够创建物理和视觉环境的高保真表示,现代游戏引擎已经成为训练多种具体化人工智能的可行工具。术语“具体化人工智能”在这里用于区分机器学习算法的类型。一个被具体化的人工智能包含了一个环境中的视觉表现,不管是真实的还是虚拟的,并且正在优化一些服从于那个角色的东西。例如,垃圾邮件分类器并不代表具体化的人工智能,因为它在其环境中缺乏任何种类的可见身份。然而,用于动画表情的垃圾邮件分类器可以说是表示具体化的 AI,因为优化器现在具有时空内的物理表示。

创建这种具体化人工智能的工具可以被认为是一种新型的软件,或者我在这里称之为“学习引擎”。虽然这些例子已经存在,但大多数用于创建具体化代理的深度学习工具仍处于起步阶段,需要大量的专业知识来部署。在这篇文章中,我介绍了一个名为 Neurostudio 的深度学习框架,它利用 Unreal Game Engine 的可视化脚本语言蓝图,通过新手可以学习的几个简单步骤来创建自主学习代理。

https://www.youtube.com/watch?v=rgQWJ5bkVkk

为什么首先要使用视频游戏引擎来训练具体化的人工智能?在部署强化学习等下一代人工智能技术时,一个持久的障碍是缺乏合适的培训环境。各种各样的研究已经注意到使用基线现实训练具体化代理人的困难。通常,人工智能的物理约束,如机器人的电子执行器,禁止像深度强化学习这样的技术产生良好结果所需的高容量训练计划。

一种替代方法是使用模拟器来训练代理。从这里开始,智能体可以继续存在于模拟器中(就像电子游戏《NPC》的情况一样),或者它们的学习可以转移到“实体”现实中,就像机器人的情况一样。在这两种情况下,使用模拟器来训练具体化代理都有几个优点。首先,当事情发生灾难性的错误时,其结果通常没有在物理现实中发生灾难性错误时那么严重。一个疯狂奔跑的机器人的模拟和一个 800 磅重的四肢乱飞的怪物是完全不同的。更重要的是,很多时候人们可能希望代理人永远留在模拟器中,就像电子游戏角色的情况一样。

我在这里描述的系统将深度神经网络与强化学习算法相结合,以实现自我学习的具体化代理。使用这个系统,一个智能体可以简单地通过改变 AI 角色控制器中的奖励函数来执行任何涉及其环境中对象的动作组合。这是强化学习的主要优势——不需要手工制作行为,而是指定一个要奖励的行为,让代理自己学习实现奖励的必要步骤。本质上,这就是如何用食物奖励来教狗表演一个魔术。

同样的方法也可以用来训练 NPC、虚拟助理甚至机器人。通过这个系统可以获得各种各样的有意行为,包括路径寻找、NPC 攻击和防御以及许多类型的人类行为。最先进的实现包括那些用于在国际象棋、围棋和多人战略视频游戏中击败一流人类玩家的实现。

https://www.youtube.com/watch?v=SmBxMDiOrvs

强化学习已经成为训练具体化代理人的一个有前途的途径,因为这样的代理人几乎总是与一些时间和行动的概念有关。强化学习不同于人工智能的其他分支,因为它专门解决学习的问题,其中代理可以采取一些与时间和环境相关的行动。在这种情况下,时间可以是一系列的游戏移动或训练时期。以这样或那样的方式,有一个时间空间,在其中事情正在发生。人工智能不像监督学习技术那样简单地迭代一组冻结的标记数据。

一旦一个主体存在于时间和变化的环境中,复杂性就成了压倒一切的问题。在诸如表格 Q 学习的强化学习技术中,算法必须跟踪表格中环境变化、动作和奖励的所有组合。根据环境的复杂性和代理可用的操作,这可能会使这样的表变得非常大。即使几个环境因素相互作用也能迅速导致组合爆炸。

人类也使用强化学习的变体来获得许多技能,你可能会忍不住问,在复杂性成为问题之前,我们自己可以跟踪多少环境变量?从视觉上来说,答案少得惊人——根据物体是运动还是静止,在 4 到 8 个之间。根据我们对强化学习和组合爆炸的了解,这是有道理的——超过八个对象,注意力的空间分辨率就会停滞不前。四个动态对象可以以 24 种不同的方式组合,八个对象以 40,320 种方式组合!除此之外,我们进入了从人类的角度来看几乎毫无意义的数字——12 个物体可以以 4.79 亿种独特的方式组合。例如,在玩视频游戏的任何时候,我们通常会从成千上万的像素中抽象出 4 到 5 个不同的对象来跟踪。

那么,我们如何从所有这些像素组合中提取出少量有意义的特征呢?在人类中,进化为我们做了所有艰苦的工作,在生物学中这种天赋被称为潜在抑制。在这个过程中,熟悉的物体会失去它们的显著性,我们会随着时间的推移而忽略它们。遗忘的面纱确实是一个仁慈的面纱。虽然根据计算机的处理能力,计算机可以跟踪比人更多的特征,但组合爆炸甚至会加重现代超级计算机的负担。对计算机科学家来说幸运的是,“神经网络”可以帮助解决这种复杂的问题。

深度神经网络最常与称为“监督学习”的人工智能领域相关联,这需要有人提供一个标记训练数据的数据库,供算法从中学习模式。深度神经网络的惊人之处在于,它们可以像猫的照片一样获取嘈杂、非线性、非均匀的数据,并将其抽象为对其进行分类至关重要的几个特征。这就是你的垃圾邮件分类器如何在你的电子邮件收件箱中工作,以及网飞如何根据你喜欢或不喜欢的电影为你创建推荐。这种分类器在软件中越来越常见,并由于深度神经网络而受到了鼓舞。神经网络比早期的统计方法(如逻辑回归和贝叶斯分类器)更强大,因为它们擅长发现隐藏在多层复杂性下的模式。分类器是强大的工具,但与强化学习不同,它们通常需要某种标记数据来训练。

2015 年,DeepMind 公司的研究人员突发奇想,利用深度神经网络从雅达利视频游戏屏幕的屏幕像素中提取像素,以便将强化学习算法应用于玩游戏。如上所述,深度神经网络有能力获取非常嘈杂的大型数据集,并检测其中的模式。Atari 视频游戏的屏幕可以被认为是这样一个大而嘈杂的数据集。通过使用 Atari 控制台的屏幕作为神经网络的训练集,他们将所有像素组合的复杂性减少到与玩家可能做出的不同动作相关的少数几个特征,通常只有 4 或 5 个(Volodymyr Mnih,2015)。他们仅仅是幸运的没有一个游戏需要更多的动作来获胜吗?一点也不,因为这些游戏是为人类设计的,它们的活动和环境空间有限。为外星人设计的 Atari 视频游戏能够从 10,000 种不同的动作组合中学习,这完全是另一回事。然而,在大多数游戏功能只是装饰,对人们应该采取的行动没有任何意义的情况下,深度神经网络可以将复杂性降低到强化学习算法可以管理的程度。

雅达利的情况同样适用于围棋这样的棋类游戏。由于游戏固有的复杂性,这种古老的中国娱乐方式被认为是计算机无法掌握的。正如围棋专家喜欢提醒我们的那样,在一场围棋比赛中,可能的棋盘组合比宇宙有史以来存在的夸克数量还要多。但就像在雅达利电子游戏中一样,围棋游戏中的许多棋盘位置与游戏的任何给定回合都不相关。它们就像屏幕远处角落里的像素,在它表明敌人正向你走来之前并不重要。“深度强化学习”,即深度神经网络和强化学习的结合,被证明在掌握围棋方面与在 Attari 视频游戏中一样有效。2017 年,由 DeepMind 开发的围棋深度强化学习算法 AlphaZero 击败了几位世界领先的人类围棋选手以及最佳围棋人工智能。

当想到像围棋这样的游戏时,人们陷入的一个主要谬误是假设复杂的游戏需要复杂类型的学习。在分形几何中,看似无限变化的令人困惑的图案可以从简单的公式中推导出来。进化已经产生了无数极其复杂的生命形式,它受到一个同样简单的学习规则——错误——的指导。同样的学习方程式可以让你掌握井字游戏,也可以让你掌握像围棋这样的游戏。在这两个游戏中,强化学习可以发现与获胜相关的关键关联。这并不是说没有更复杂的方法来解决学习问题。1997 年在国际象棋比赛中击败加里·卡斯帕罗夫的 IBM 超级计算机 DeepBlue 是一个庞大的程序,其中内置了数千个由国际象棋专家和程序员编写的场景。但是这样复杂的程序,最终远不如像 Q 学习这样的简单算法健壮和强大。首先,他们编织了编码他们的人类的经验偏见。当雅达利深度强化学习算法在 DeepMind 开发出来时,它发现了一种在乒乓游戏中增加分数的方法,这种方法使用了一种人类玩家以前不知道的技巧。如果它完全是根据人类的经验编写的,它很可能永远不会做出这种“外星人”的动作。强化学习的优势在于,独自玩游戏时,它可以尝试数百万个游戏历史上从未有人想过要尝试的动作。

许多专家评论员在研究国际象棋强化学习算法 AlphaZero 时,看到了更高级版本的 DeepBlue,因此没有意识到他们正在研究一种完全不同的人工智能,一种具有完全不同含义的人工智能。因为强化学习模仿了人类学习的一种方式,所以可以用于掌握围棋的相同算法可以用于掌握煎蛋卷或叠衣服。当你第一次开始学习叠衣服时,你会犯错误,袖子不整齐,折痕不精确。通过重复,或者用计算机科学的话说,迭代,你慢慢地学会了让你达到目标状态,完美折叠衬衫所必需的正确动作。以这种方式,许多人类活动可以被“游戏化”并变成强化学习问题。

将神经网络与强化学习结合起来,允许人们采用诸如 Q 学习的算法,并扩大代理可以学习的环境和动作空间。极端情况下—代理学习的环境可以是屏幕的实际像素输入。这反映了人类和狗等哺乳动物从视野中学习的方式。

Neurostudio 学习引擎基于深度强化学习算法,称为深度 Q 学习,简称 DQN。对它的表亲表格式 Q 学习有一个基本的了解,对理解深度 Q 学习会有帮助。在下面的链接中,您可以找到表格 Q 学习的介绍,其中代理解决了一个简单的匹配样本难题:https://www . unrealenengine . com/market place/artificial-intelligence-Q-learning

Q 学习的工作方法有时被称为逆向归纳法。想象一下,一个徒步旅行者迷失了方向,正试图找到返回营地的路。首先,他们随机选择一个前进的方向。他们爬过一块岩石,观察这个动作是否能让他们更接近目标。从这个新的有利位置,他们决定如何评价他们以前的行为。爬过岩石是一个好的决定还是一个坏的决定?实际上,我们正在从猜测中学习猜测。首先对未来进行猜测(考虑到我的新状态,到达营地有多容易),然后根据第一次猜测对他们最后一次行动的值进行猜测(我爬过这块岩石,离大本营更近了,所以我的最后一次行动很好),我们通常称之为试错学习,或联想学习。在表格式的 Q 学习数学形式中,这需要表达式

Q(状态,动作)=奖励(状态,动作)+ Gamma * Max[Q(下一个状态,所有动作)]

其中 R(状态,动作)是由当前动作收集的任何奖励,gamma 是介于 0 和 1 之间的固定折扣率,它控制代理人对当前奖励和未来奖励的重视程度。Max[Q(下一个状态,所有动作)]也称为贝尔曼更新规则,使状态动作对的当前值依赖于可以从该位置采取的下一个最佳未来动作。这是等式的“向前看”部分。以这种方式,一个人相信将来会发生的奖励可以被向后链接到到达那里的步骤。

为了将 Q 学习与神经网络相结合,神经网络首先预测对应于给定其当前状态的代理可用的每个动作的值。最初,这些只是由神经网络产生的随机噪声。然而,在代理收到奖励后,它可以应用 Q 学习方程,并使用状态动作对的预测值和状态动作对的新值之间的结果误差来形成误差项。这个误差项可以用来训练神经网络。把神经网络想象成一个最小化预测误差的工具,把 Q 学习方程想象成提供这些预测误差的东西。

经过多次训练后,神经网络逐渐提高了对代理在模拟器中可能遇到的每个状态动作对的估计。为了进行战略性的移动,代理只需在给定网络当前状态的情况下向前运行网络,并采取预计具有最高价值的行动。

虽然我已经详细解释了 DQN 的工作原理,但是使用 Neurostudio 并不一定需要了解学习是如何发生的细节。相反,人们只需要清楚代理人正在从环境中的哪些元素学习,代理人可以采取的行动,以及它可以获得的回报。就像你不需要理解脑科学来教狗如何变戏法一样,你需要理解狗有什么能力,它发现什么是有益的,以及何时给予这些奖励来最大限度地学习。

也就是说,在选择神经网络的参数时,对深度学习原则(如过拟合)的理解可能是有帮助的。训练神经网络既是一门科学,也是一门艺术,因为神经网络的许多参数会影响学习。

虽然深度强化学习允许代理在复杂的真实世界环境中学习,但它们通常比表格 Q 学习代理做得更慢。给定影响神经网络的大量参数,也可能更难以“调整”代理的行为。

另一方面,使用神经网络允许代理人概括他们的策略——也就是说,他们将把学到的策略应用于各种各样的环境状态,这些环境状态类似于他们最初接受训练的环境状态。这使得他们即使在全新的环境中也能聪明地行动。相比之下,使用表格式 Q 学习,所学习的策略将仅在代理具有过去关联的确切环境状态中被调用。这种将学习推广到新任务和新环境的能力使深度强化学习成为目前可用的最强大的机器学习框架之一,也是学习引擎的自然起点。我期望使用这样的学习引擎来扩展真实和虚拟代理的视野,并迎来一个新的嵌入式人工智能时代。

购买多 GPU 系统的经验

原文:https://towardsdatascience.com/a-lesson-buying-a-multi-gpu-system-a14d3d1c710e?source=collection_archive---------7-----------------------

我在寻找用于深度学习实验的本地多 GPU 系统中学到了什么

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

这个故事是关于 H 字的,我指的是硬件或者更准确地说是用于繁重的深度学习任务的高端 GPU 系统。

所以在长时间使用 GPU 云实例,甚至编写 PyTorch 检查点处理程序来支持保存和加载模型权重和其他超参数作为快照后,更容易在 spot 实例上工作。是时候购买一台本地机器了。我目前专注于视频相关的任务和训练繁重的 I3D 型号,所以我需要一台坚固的多 GPU 机器来支持这些工作。使用大的小批量会占用大量的 GPU 内存。最新最好的 NVIDIA GPU 是配备 24GB 内存的泰坦 RTX ,售价为 2499 美元,所以为什么不买四个这样的宝贝呢?我联系了几个推荐的供应商,以获得这种系统的规格建议和价格估计。听到其中一家供应商说这不可能,而其他供应商确实提出了建议,我有点惊讶。

他的完整回答是这样的:

它们会在没有鼓风机的情况下加热,最物有所值的是 GeForce RTX 2080 Ti TURBO 11G ,因为每个价格一半,有 11GB 内存,只需 8 个。

我最近确实购买了一台配有单个 GEFORCE RTX 2080 Ti 的 GPU 机器,所以我问我是否可以为该机器添加更多 GPU,他问了确切的 GPU 型号,并再次表示:“不要**鼓风机,**机箱中会太热”。

那么这是怎么回事,鼓风机是什么?

困惑中,我开始寻找一个简单的答案,在谷歌的帮助下,我找到了这张图片和它所来自的伟大的博客文章。

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

A picture is worth a thousand words. The image is taken from: NVIDIA RTX Graphics Card Cooling Issues

是的,在右边——一台鼓风机!

技嘉网站所写的鼓风机是:

“千兆字节涡轮风扇冷却系统专为在空间有限的机箱中使用多个显卡的系统而设计。借助蒸汽室直触 GPU、鼓风机风扇和特殊形状的外部,它提供了更多的气流和更好的散热。”

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

The image is taken from: GIGABYTE product page

事实证明,游戏玩家模型,如泰坦 RTX ,并不专用于多 GPU 系统,而是为游戏而设计的。他们通过使用“露天”系统来降温。

在非服务器机架上组装多 GPU 系统迫使你将它们彼此靠近,而鼓风机的工作是负责散热。

所以下次你在寻找一个 GPU 来处理深度学习任务时,你最好问问你的供应商,GPU 是否有鼓风机。

更多阅读,推荐这篇很棒的博文:https://www . pugetsystems . com/blog/2019/01/11/NVIDIA-RTX-显卡-散热-问题-1326/

现代分类模型的一课

原文:https://towardsdatascience.com/a-lesson-on-modern-classification-models-938cbd731d9d?source=collection_archive---------17-----------------------

揭开 ML 的最新进展,为您构建一个更好的分类模型

在机器学习中,分类问题是最根本的令人兴奋挑战现有问题之一。一个合格的分类模型的含义是巨大的——这些模型被用于自然语言处理文本分类、图像识别、数据预测、强化训练以及无数的进一步应用。

然而,目前实现的分类算法很糟糕。在脸书期间,我发现任何机器学习分类问题的通用解决方案都是“扔一棵梯度下降推进树给它,然后抱最好的希望”。但情况不应该是这样的——研究正在投入到现代分类算法和改进中,这些算法和改进允许显著更准确的模型,而所需的训练数据却少得多。

在这里,我们探索一些特别有趣的现代分类算法的例子。这篇文章假设你对机器学习有一定的了解,但是,这篇文章的大部分内容不需要。

深度神经决策树

深度神经网络已经被证明在处理感知数据方面非常强大,比如图像和音频。然而,对于表格数据,基于树的模型更受欢迎有几个原因——其中一个重要原因是它们提供了自然的可解释性。

例如,考虑一个试图确定系统故障原因的企业。您可以使用几个参数创建一个预测模型,例如网络速度、正常运行时间、线程处理和系统类型。有了决策树,我们还可以了解系统失败的原因。

深度神经决策树结合了决策树的效用和神经网络产生的影响。由于它是通过神经网络实现的,DNDT 支持开箱即用的 GPU 加速和对不适合内存的数据集的最小批量学习,这要归功于现代深度学习框架。因此,在许多数据集上,它们比传统的决策更加准确。此外,它们易于使用——在 TensorFlow 或 PyTorch 中,一个实现需要大约 20 行代码

我们可以探索模型核心数学背后的概念。首先,我们需要一种方法来做出分割决策(即我们如何决定选择树的哪条路径)。然后,我们需要将我们分开的决策组合在一起,构建决策树

我们通过一个 宁滨函数做出拆分决定。宁滨函数接受一个输入,并生成该输入所属的条柱的索引。在我们的模型中,每个箱代表一个特性——例如,正常运行时间、网络速度或系统类型。

我们通过其自己的一层神经网络(我们模型的“深度神经”部分)和以下激活函数来绑定每个特征。

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

The activation function of each bin.

然后,我们通过克罗内克乘积将我们的箱彼此相乘,以构建我们的决策树。

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

每个特征都被它们自己的神经网络分类。这就给我们返回了一个表示 x 的分类的索引(即树中叶子节点的索引),完成了我们深度神经决策树的构建。

置信度加权线性分类

许多机器学习任务,特别是在自然语言处理中,最终会有许多不同的特征,其中大多数是二进制的,很少被操作。这导致数据稀疏,这需要大的训练集和非常大的参数向量。

考虑一个产品评论分类器,其目标是将评论标记为正面或负面。许多评论可能会说“我喜欢这个作者”,因此会将“喜欢”这个词与正面评论相关联。想象一下一个稍加修改的负面评论:“我喜欢这个作者,但觉得这本书索然无味”。分类器可能不会经常看到世界“沉闷”,这可能会错误地将该评论分类为积极的,因为该评论使用短语“喜欢该作者”,从而降低了收敛速度。

我们可以用置信度加权学习来解决这个问题,这是一种在每个参数中保持概率置信度的学习方法。较不自信的参数比较自信的参数更新得更积极。

在置信度加权学习中,我们确保对于每次迭代,每个训练实例的正确预测的概率大于或等于该预测的置信度。这可以正式定义。

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

就其本身而言,这可以附加到任何其他模型上(您需要决定如何度量置信度——一些想法是贝叶斯方法,如变分贝叶斯)。这导致模型的变化,趋向于解决稀疏数据集涉及的上述问题。

决定批量大小的贝叶斯原则

除了选择一个有代表性的模型,还有一系列的变量会影响我们的模型所代表的准确度。一个是批量大小——训练期间每次迭代使用的训练数据量。研究表明,不仅存在最大化测试准确性的最佳批量,而且我们可以应用贝叶斯原理来计算作为学习率训练数据量的比例函数。计算本身是一个多步骤的过程,超出了本文的范围,但是结果可以表示为一个线性比例函数:

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

由此,我们可以得出两个有益的结论。

首先,随着我们的训练数据的大小增加,每个批量迭代的大小应该增加相同的量。第二,随着学习数据的增加,我们应该增加批量。这使我们能够确定单个实验的最佳批量,并对其进行缩放,以确定任意数量的不同实验的批量,从而全面优化测试精度。

结论

这只是对现代机器学习研究中分类问题的广度(和深度)的一个尝试——本文中的所有内容都是在过去几个月中发表的。希望这向您展示了一点令人兴奋的复杂性,人们在未来选择分类模型时可能会考虑到这一点!

R 语言中的文本分析简介

原文:https://towardsdatascience.com/a-light-introduction-to-text-analysis-in-r-ea291a9865a8?source=collection_archive---------6-----------------------

使用语料库、文档术语矩阵、情感分析等…

介绍

这是我在 r 中使用一些文本分析工具的第一个项目的快速浏览。这个项目的目标是探索文本分析的基础,如使用语料库、文档术语矩阵、情感分析等…

使用的包

  • tm
  • 其他:tidyverse,SnowballC,wordcloud,RColorBrewer,ggplot2,RCurl

快速查看数据源

我使用了我最新的 网络搜集项目 中的职位描述。实际上,大约有 5300 个职位空缺。

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

我们将在这里集中讨论职位描述,因为它们包含了最多的文本和信息。让我们看看我们的第一份工作描述,看看我们在做什么。

**postings1$job_description[1]**

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

正如您所看到的,这是一个很大的字符串,包含了工作列表中的所有文本。

创建语料库

语料库(corpora pl。)只是一种存储文本数据的格式,在整个语言学和文本分析中使用。它通常包含每个文档或文本集,以及一些帮助描述该文档的元属性。让我们使用 tm 包从我们的工作描述中创建一个语料库。

**corpus <- SimpleCorpus(VectorSource(postings1$job_description))
# And lets see what we have
view(corpus)**

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

你可以看到我们最外面的列表是一个类型=列表**,长度= 5299,这是我们拥有的工作描述(或文档)的总数。当我们查看列表中的第一项时, [1],,我们看到这也是一个类型=列表,长度= 2。如果我们看这两个项目,我们会看到有内容元。内容属于类型=字符,包含字符串形式的工作描述文本。M eta类型=列表,长度为 7。这是自动添加到简单语料库中的 7 个元属性,即使我没有它们的任何值。**

  1. 作者=空
  2. 日期-时间戳=另一个列表…但是对于我的数据是空的
  3. 描述=空
  4. 标题=空
  5. id = '1 '(由职位自动创建)
  6. language = 'en '(我假设是 tm 包的默认值)
  7. 原点=空。

现在你知道了。这是一个简单语料库的一般格式。请记住,您可以编辑元属性来包含您想要的任何内容。

转换:清理我们的语料库

tm 包中的转换指的是在进行任何分析之前,我们可能要对文本进行预处理或格式化。我们将执行 5 个快速转换,这将为我们的分析准备数据。

**# 1\. Stripping any extra white space:
dfCorpus <- tm_map(dfCorpus, stripWhitespace)# 2\. Transforming everything to lowercase
dfCorpus <- tm_map(dfCorpus, content_transformer(tolower))# 3\. Removing numbers 
dfCorpus <- tm_map(dfCorpus, removeNumbers)# 4\. Removing punctuation
dfCorpus <- tm_map(dfCorpus, removePunctuation)# 5\. Removing stop words
dfCorpus <- tm_map(dfCorpus, removeWords, stopwords("english"))**

除了移除停用词功能,大多数转换都是自解释的。那到底是什么意思?停用词基本上只是被确定为对某些文本分析(如情感分析)没有什么价值的常用词。这是 tm 包将删除的停用词列表。

**stopwords(“english”)**

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

现在我们已经转换了我们的工作描述,让我们再看一下我们的第一个清单,看看有什么变化。

**corpus[[1]]$content**

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

堵塞物

词干提取是将单词压缩成共同词根的过程,这有助于词汇的比较和分析。tm 包使用 波特词干算法 来完成这个任务。让我们继续干我们的数据。

**dfCorpus <- tm_map(dfCorpus, stemDocument)**

现在让我们最后一次看一下我们的工作描述,看看有什么不同。

**corpus[[1]]$content**

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

很好,现在所有的工作描述都被清理和简化了。

创建文档术语矩阵(DTM)

文档术语矩阵是比较每个文档中所有术语或单词的简单方法。如果你把数据简单地看成一个矩阵;每行代表一个唯一文档,每列代表一个唯一的术语。矩阵中的每个单元格都是该术语在文档中出现次数的整数。

**DTM <- DocumentTermMatrix(corpus)
view(DTM)**

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

如你所见,DTM 实际上并不是作为矩阵存储在 R 中,而是属于类型= simple_triplet_matrix** 。这是一种更有效的存储数据的方式。你可以在这里 更好地了解它们是如何被格式化的 。出于我们的目的,最好把它想成一个矩阵,我们可以用inspect()函数看到它。**

**inspect(DTM)**

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

因此,我们可以看到我们有 5296 个文档(删除了三个 NA)和 41735 个术语。我们还可以看到一个 DTM 样图。现在让我们来看看在所有的招聘启事中最常用的词是什么。

创建最常用术语的词云

为此,我们首先要将 DTM 转换成一个矩阵,这样我们就可以对各列求和,从而得到所有文档的总术语数。然后,我可以在整个语料库中挑出前 75 个最常用的单词。

注意: 我选择使用无词干版本的语料库,这样我们就有了单词 cloud 的完整单词。

**sums <- as.data.frame(colSums(as.matrix(DTM)))
sums <- rownames_to_column(sums) 
colnames(sums) <- c("term", "count")
sums <- arrange(sums, desc(count))
head <- sums[1:75,]wordcloud(words = head$term, freq = head$count, min.freq = 1000,
  max.words=100, random.order=FALSE, rot.per=0.35, 
  colors=brewer.pal(8, "Dark2"))**

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

所以,这里没有什么太疯狂的,但我们可以很好地感受到这个工具有多强大。支持、学习、理解、沟通等术语可以帮助描绘出这些公司在候选人身上寻找什么。

情感分析

“情绪(名词) :对某事的总体感觉、态度或看法。”——剑桥英语词典

情感分析的目标很简单,但实现这一目标的过程却很复杂。桑杰·米娜有一篇很棒的介绍,值得一读:

** [## 你的情感分析指南

情感分析帮助你发现人们对你的产品或服务的看法、情感和感受

medium.com](https://medium.com/seek-blog/your-guide-to-sentiment-analysis-344d43d225a7)

我们将开始使用’sensitement analysis’包,使用Harvard-IV dictionary(General Inquirer)做一个简单的极性分析,这是一个与积极(1915 个单词)或消极(2291 个单词)情绪相关的单词字典。

sent <- analyzeSentiment(DTM, language = "english")# were going to just select the Harvard-IV dictionary results ..  
sent <- sent[,1:4]#Organizing it as a dataframe
sent <- as.data.frame(sent)# Now lets take a look at what these sentiment values look like. 
head(sent)

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

如你所见,每份文件都有字数统计、消极得分、积极得分和总体情绪得分。让我们来看看我们整体情绪的分布。

summary(sent$SentimentGI)

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

好的,总的来说,我们的工作描述是积极的。所有文件中的最低分是 0.0,所以看起来这些公司在写他们的职位描述方面做得很好。现在,为了好玩,让我们看看排名前五和后五的公司的情绪得分。

# Start by attaching to other data which has the company names 
final <- bind_cols(postings1, sent)# now lets get the top 5 
final %>% group_by(company_name) %>%
  summarize(sent = mean(SentimentGI)) %>%
  arrange(desc(sent)) %>%
  head(n= 5)

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

# And now lets get the bottom 5 
final %>% group_by(company_name) %>%
  summarize(sent = mean(SentimentGI)) %>%
  arrange(sent) %>%
  head(n= 5

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

就这样。现在,这显然不是一个很好的情感分析用例,但它是理解过程的一个很好的介绍。

情感

我们可以做的另一件有趣的事情是从工作描述中提取情感。我们将使用 NRC 情感词典 使用 syuzhet 包 来完成这项工作,该词典将单词与相关情感以及积极或消极情感联系起来。

sent2 <- get_nrc_sentiment(postings1$job_description)# Let's look at the corpus as a whole again:
sent3 <- as.data.frame(colSums(sent2))
sent3 <- rownames_to_column(sent3) 
colnames(sent3) <- c("emotion", "count")ggplot(sent3, aes(x = emotion, y = count, fill = emotion)) + geom_bar(stat = "identity") + theme_minimal() + theme(legend.position="none", panel.grid.major = element_blank()) + labs( x = "Emotion", y = "Total Count") + ggtitle("Sentiment of Job Descriptions") + theme(plot.title = element_text(hjust=0.5))

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

太棒了。我们已经知道工作描述大多是积极的,但令人感兴趣的是看到更高价值的信任和期望。显而易见,这可以应用于其他类型的数据,如评论或评论,以将大量文本数据简化为快速洞察。**

感谢您的阅读,我希望这篇文章能够帮助其他初学者开始使用 R 的文本分析包。我很乐意听到任何问题或反馈,因为我自己也刚刚开始。

面向物联网流的轻量级机器学习架构

原文:https://towardsdatascience.com/a-lightweight-machine-learning-architecture-for-iot-streams-bd1bf81afa2?source=collection_archive---------20-----------------------

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

在高频流数据上运行机器学习模型不一定要花大价钱。通过考虑我们的实时需求,我们可以设计更容易扩展的高效架构。

在过去的一年半时间里,我和我的团队一直在试图预测公共道路上的公共汽车的运动,并预测它们在公共汽车站的到达和离开时间。我们的客户,一家名为 Kolumbus 的公共交通公司,已经在许多车辆上安装了物联网(IoT)网关,每秒钟都在向微软 Azure 云发送消息。

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

虽然我们的大部分数据是地理空间数据,但问题本质上是时间问题。对它的研究让我思考时间的概念,以及它与实时系统各部分的关系。

伴随着大数据而来的是巨大的责任

86,400.这是一天中的秒数,这个数字解释了为什么物联网成为大数据时代的海报儿童。

单个传感器通常一天只能记录这么多信息。根据有效载荷的大小,这可能会产生大约 5 MB 的数据。虽然这听起来可能不多——只有一个略大的 mp3 文件的大小——但物联网解决方案很少只有一个传感器。嵌入式设备通常会连接几个传感器,它们依次连接到网关,网关路由来自多个设备的流量。此外,一个典型的流处理管道会在几个步骤中咀嚼、处理和丰富原始有效载荷,我们手上有一些重要的数据。

物联网设备产生大量数据,机器学习需要大量处理。当你把它们放在同一个句子中,通常不会首先想到“轻量级”这个词。现在你可能想知道为什么这三个都出现在这篇文章的标题中。我们会谈到这一点。

如果您在行业环境中从事物联网工作,您可能对以下场景很熟悉。

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

支持 IP 的物联网设备或网关使用 MQTT 或 AMQP 等通信协议向公共云中的中央消息代理发送遥测数据。该代理可以是像 Azure IoT Hub 或 AWS Kinesis 这样的云原生服务,也可以是像 Apache Kafka 或 Flink 这样的开源框架。这些技术可以以合理的成本接收来自数百万设备的消息,这意味着我们可以可靠地收集所有传感器数据。到目前为止,一切顺利。

对数据采取行动并产生可行见解的愿望不可避免地导致以下问题:

现在怎么办?

正是在这一点上,组织通常会雇用像我这样的顾问。

满足对数据的渴望

顾问们通常会提出这样的建议。

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

流处理器订阅来自代理的消息,并动态地对其进行反应性处理,然后立即将其提供给丰富数据的实时视图。在记录原始消息后的几百毫秒内,结果就可以在实时视图中显示,并显示在报告仪表板中。机器学习 web 服务与流处理器挂钩,并执行预测分析,成为实时输出的一部分。这被称为“从消防水管喝水”,是在流处理平台中使用机器学习模型的规范方式。它是这类系统的两个主要标准架构的核心:所谓的 Lambda 和 Kappa 架构。

当设计一个实时系统时,我们应该问自己的第一个问题是,它如何适应项目的特定约束和需求。将机器学习模型直接挂钩到流意味着请求将到达每一条物联网消息的预测端点。这可能意味着服务器集群和相当大的托管费用。当速度和数量增加时,成本、复杂性和延迟也会增加。

虽然在某些情况下从消防水管喝水是必要的,但从一杯水中啜饮通常更舒服。

实时的神话

设计软件时,我们有时会谈到“近实时”。这里的“近”暗指我们永远不可能在任何系统中实现零延迟。在系统能够响应之前,不可避免地要经过一些非零的处理时间。当它非常快时,我们作弊,称之为实时。但是我们在哪里划定界限呢?100 毫秒?一秒钟?一分钟?

在我们甚至考虑我们是否能够实现适当的实时或接近实时之前,我们应该考虑实时需求,这是另一个完全不同的地方。我们应该问自己一个更基本的问题,而不是简单地考虑技术上的可能性:缓慢响应的后果是什么?

实时要求分为三类:

  • 实时。延迟将导致整个系统的失败。也许它们会导致发电厂爆炸,飞机坠毁,太空探测器错失目标,或者无人驾驶飞机轰炸无辜平民。你通常列举的可怕事故。
  • 实盘实时。偶尔延迟是可以的。延迟的输出是无用的,但是系统仍然是可操作的。想象一下网飞。虽然偶尔停顿的电影流可能很烦人,但你可能不会因此失眠。
  • 实时。频繁的延误完全没问题。一个迟来的回应可能没那么有价值,但它仍然是有用的。

让我们面对现实吧。极少数系统实际上有严格的实时要求。但是,即使是严格的实时要求也很少。大多数系统都有相当宽松的时间限制。

回到我们的公交预测,这是一个具有软实时需求的系统的经典案例。如果我们在 8:30 预测一辆公共汽车将在 9:00 到达某个车站,那么这个预测在几秒钟后仍然有效并且几乎同样准确。即使是在 8:31 或 8:32,预计到达时间(ETA)也不会发生根本性的变化。

时间窗口

对于软实时要求,我们可以选择对数据进行下采样。毕竟,传感器信号的频率只是我们用来从设备中采样的任意时间段。我们并不需要处理每一条传入的消息。

流处理也有一种规范的方式来做到这一点,它被称为时间窗口。

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

这个简单的函数叫做滚动窗口,所有主流的流处理框架都支持它。通过查看固定大小的时间窗口,我们可以以某种方式聚集数据,或者只处理批处理中最新的消息。

在后一种情况下,我们只对捕捉传感器的最新状态感兴趣。当你想到它时,这就是物联网设备已经在做的事情,只是速度更快。

这允许稍微不同的架构。

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

在这种设置中,一个计划任务(如 cron 作业)会在特定的时间间隔醒来,查看来自流式管道的最新输出,生成预测,然后再次进入睡眠状态。当我们等待任务再次触发时,旧的预测仍然有效。记住,考虑到我们的软实时需求,预测在有限的时间内是有价值的。

这可能不是在每种情况下都有效,但是在适用的情况下,它可以大大降低系统的成本。借助现代云服务,我们通常不会为闲置的处理单元付费。

另一个好的方面是,我们将预测分析与我们希望对每条消息进行的更简单的处理形式分离开来。

作为旁注,我们也可以将一些相同的哲学应用于模型训练。对于在大型数据集上训练模型,下采样通常是一种不受重视的策略。

付诸实践

在我们的实时总线系统中,我们已经将预测和训练功能从流层中分离出来,并将它们放入单独的 Docker 容器中,这些容器在需要时会旋转起来。

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

通过这种方式,我们拥有了一个自包含的基础设施,只要流式管道接收到物联网消息,它就可以根据新数据保持训练模型并生成实时预测。

系统的这一部分目前每天处理几百万条消息,每月花费大约 60 美元。这包括托管、计算和存储。我们通过利用“容器即服务”( CaaS)和“功能即服务”( FaaS )(也称为“无服务器”)的云模式来实现这一目标。

目前,我们正在一个小型 Docker 容器上运行预测任务,该容器只有一个 CPU 内核和 2.5 GB 的内存,它的响应速度仍然相对较快。这还没有太多的优化。事实上,我们正在并行运行一些不同的机器学习模型,以评估它们在生产中的性能,所有这些都是在那个容器实例上进行的。限制流向终端的流量使我们可以享受这些自由。

但是推论是廉价的。那么训练呢?

训练模型需要更强大的服务器,但我们仍然运行一个相对适中的实例,具有四个 CPU 核心和 5 GB 内存。我们对数据进行了大量的缩减采样,每天只运行几分钟。通过这样做,我们将这项特殊任务的成本保持在每月 2 美元的低得离谱的水平。

我们预计我们系统的入站物联网流量将增加至少一个数量级,但负载测试结果显示,我们的设置可以相对轻松地处理它。训练容器可能需要更大的马力,但是考虑到它只运行一小部分时间,即使我们使用像 Kubernetes 这样的集群技术扩展到多个节点,它仍然是廉价的。

最后的想法

我上面所描述的并不适用于所有的问题。有些情况下,你需要连续预测每一个事件。但在物联网场景中,通常情况下你可以跳过时间步骤。事实上,平滑信号甚至有助于防止模型过度拟合。

我们的系统以惊人的低成本运行在最小的基础设施上,同时满足我们的性能要求。我们已经在 Azure 上部署了这个,但是我故意避免为我们的组件使用市场名称,因为这个概念和一般架构可以在任何通用的云平台上实现。

我的观点不是建议我们的架构作为每个人都要遵循的标准。它只是呼吁数据科学家和数据工程师在设计过于复杂和沉重的系统之前,考虑他们机器学习管道中每个单独组件的时间约束和实时要求。

随机森林回归的一个局限性

原文:https://towardsdatascience.com/a-limitation-of-random-forest-regression-db8ed7419e9f?source=collection_archive---------5-----------------------

邻居的规则如何影响你的预测。

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

One Tree from a Random Forest of Trees

随机森林是一种流行的机器学习模型,通常用于分类任务,这在许多学术论文、Kaggle 竞赛和博客帖子中可以看到。除了分类,随机森林还可以用于回归任务。随机森林的非线性特性可以帮助它超越线性算法,成为一个很好的选择。但是,了解您的数据并记住随机森林无法进行外推是很重要的。它只能做出预测,该预测是先前观察到的标签的平均值。从这个意义上说,它非常类似于 KNN 。换句话说,在回归问题中,随机森林可以做出的预测范围受到训练数据中最高和最低标签的限制。在训练和预测输入的范围和/或分布不同的情况下,这种行为会变得有问题。这被称为协变量移位,对于大多数模型来说很难处理,尤其是对于随机森林,因为它不能外推。

例如,假设您正在处理具有潜在趋势的数据,如股价、房价或销售额。如果您的训练数据缺少任何时间段,您的随机森林模型将会根据趋势低估或高估训练数据中时间段之外的示例。如果您将模型的预测值与真实值进行对比,这一点会非常明显。让我们通过创建一些数据来看看这一点。

import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
from sklearn.ensemble import RandomForestRegressor
%matplotlib inline#make fake data with a time trend
X = np.random.rand(1000,10)#add time feature simulating years 2000-2010
time = np.random.randint(2000,2011,size=1000)#add time to X
X = np.hstack((X,time.reshape(-1,1)))#create target via a linear relationship to X
weights = np.random.rand(11)
y = X.dot(weights)#create test data that includes years
#not in training data 2000 - 2019
X_test = np.random.rand(1000,10)
time_test = np.random.randint(2000,2020,size=1000)
X_test = np.hstack((X_test,time_test.reshape(-1,1)))
y_test = X_test.dot(weights)

让我们看看一个随机森林能多好地预测测试数据。

#fit and score the data using RF
RF = RandomForestRegressor(n_estimators=100)
RF.fit(X,y)
RF.score(X_test,y_test)
>>0.5872576516824577

那不太好。让我们对照它们的已知值来绘制我们的预测,看看发生了什么。

#plot RF as trees increase
#set starting point for subplots
index = 1#set the size of the subplot to something large
plt.figure(figsize=(20,20))#iterate through number of trees in model
#and plot predictions v actual
for i in [1,5,10,100]:
    plt.subplot(2, 2, index)
    RF_plot = RandomForestRegressor(n_estimators=i)
    RF_plot.fit(X,y)
    #split data btw vals RF can interploate vs. data
    #it needs to exptrapolate
    interpolate_index = X_test[:,10]<=2010
    extrapolate_index = X_test[:,10]>2010
    X_interpolate = X_test[interpolate_index]
    X_extrapolate = X_test[extrapolate_index]
    y_interpolate = y_test[interpolate_index]
    y_extrapolate = y_test[extrapolate_index]
    #plot predictions vs. actual
    plt.scatter(RFplot.predict(X_interpolate),
                y_interpolate,
                color="g",label="interpolate")
    plt.scatter(RFplot.predict(X_extrapolate),
                y_extrapolate,
                color="b",label="extrapolate")
    plt.xlabel('Predicted')
    plt.ylabel('Actual')
    plt.title('Random Forest with {} trees'.format(i))
    plt.subplots_adjust(wspace=.4, hspace=.4)
    plt.legend(loc="best")
    index += 1

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

Predicted vs. Actual Random Forest

该图清楚地表明,模型可以预测的最高值约为 961,而数据中的潜在趋势将更近的值推高至 966。不幸的是,随机森林无法外推线性趋势,也无法准确预测时间值高于训练数据(2000–2010)中所见时间值的新示例。即使调整树木的数量也不能解决问题。在这种情况下,由于我们对数据施加了完美的线性关系,因此像线性回归这样的模型将是更好的选择,并且在检测数据趋势和对训练数据中时间范围之外的数据做出准确预测方面不会有问题。

#fit the data using Linear Regression
LR = LinearRegression()
LR.fit(X,y)
LR.score(X_test,y_test)
>>1.0#plot predictions of Linear Regression against actual
plt.figure(figsize=(7,7))
plt.xlabel('Predicted')
plt.ylabel('Actual')
plt.title('Linear Regression - Test Data')
_ = plt.scatter(LR.predict(X_interpolate),y_interpolate,
               color="g",label="interpolate")
_ = plt.scatter(LR.predict(X_extrapolate),y_extrapolate,
               color="b",label="extrapolate")
plt.legend(loc="best")

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

Predicted vs. Actual Linear Regression

虽然随机森林通常是一个很好的模型选择,但了解它是如何工作的,以及在给定数据的情况下它是否有任何限制仍然很重要。在这种情况下,因为它是一个基于邻域的模型,所以它阻止我们对训练数据之外的时间范围进行准确预测。如果你发现自己处于这种情况,最好是测试其他模型,如线性回归或立体模型,和/或考虑在模型集合中使用随机森林。预测快乐!

马尔可夫链简介

原文:https://towardsdatascience.com/a-lite-introduction-to-markov-chains-eebe239f9147?source=collection_archive---------17-----------------------

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

Photo by JJ Ying on Unsplash

之前我写了一篇关于潜在狄利克雷分配的简介,作为深入探究自然语言处理(NLP)为何如此伟大的一部分。随着人工智能的不断发展,NLP 将在未来几年内(确切地说,直到 2025 年)加速发展。它是关键驱动因素之一,而且随着它继续成为我们日常生活的一部分,也许有必要了解它在幕后是如何工作的。有大量不同的概念、数学和模型进入不同的 NLP 用例,但我们只打算在基础层面上理解一个,那就是马尔可夫链。

启动马尔可夫链不仅用于 NLP。数字还有其他应用,但我们现在只关注它与 NLP 的关系。此外,还有许多与马尔可夫链(例如,转移图、转移概率矩阵和初始状态分布矩阵)和数学相关的术语,我们不会讨论。这篇文章是对马尔可夫链的简单介绍。在后面的系列文章中,我们可以深入探讨,但首先,让我们了解一下它的基本要点。

马尔可夫链,它的同名者是俄罗斯数学家安德烈·马尔可夫。定义为“…描述一系列可能事件的随机模型,其中每个事件的概率仅取决于前一个事件达到的状态。”随机模型是一种随机性模型。我们试图根据这个变量及其相关变量来发现接下来会发生什么。事实上,这个模型非常容易理解,但是理解它的基础是马尔可夫性。

马尔可夫性质表明我们不知道所有的历史,只知道以前的历史,我们是无记忆的。做出预测只需要最近的事件和未来事件的可能性。想象一下今天正在下雨,而你不知道过去还发生过什么天气事件。然而,你知道明天有 50%的可能会下雨,30%的可能是晴天,20%的可能是阴天。选择你的冒险。我们用最大概率去吧。现在继续到第二天,我们再次忘记前一天发生的事情,知道今天下雨,为了简单起见,概率是相同的,我们选择这次是晴天,一个新的状态,这意味着某事发生的新概率。如果太阳多的概率是 10%,下雨的概率是 20%,但是下雪的概率是 70%呢?

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

如果你看马尔可夫链,你可能会看到像这样的图像四处浮动。让我们来分解一下,从冰淇淋开始。这有点令人眼花缭乱,所以请原谅我。如果你吃了冰淇淋,有 10%的几率你会再次吃冰淇淋,20%的几率你会去睡觉,70%的几率你会去跑步。如果你跑步,你有 60%的机会再次跑步,30%的机会吃冰淇淋,10%的机会睡觉。如果你睡觉,有 20%的几率你会继续睡觉,20%的几率你会吃冰淇淋,60%的几率你会跑步。看起来宇宙,又名马尔可夫链,正试图告诉你一些事情:快跑!!

应用到自然语言处理中,我们可以用这个来预测单词。给定单词“我”,在它后面会有什么单词?在文本语料库中,我们可以找到所有直接跟在 I 后面的单词,并把它们放入字典中,以“I”作为关键字,所有与之相关的单词作为值。如果一个单词出现超过两次,那么它的概率就会增加,太少的话,它的概率就会下降。从那里,选择一个单词,然后我们继续下一个键:值对来做出另一个决定。只要你觉得你在代码中创建的函数合适,这个过程就会一直持续下去。

在 NLP 中使用它的问题是理解模型做得有多好。这个模型就是所谓的分室模型,在这个模型中,我们指定所考虑的不同状态,并且我们确定移动到下一步的概率,不管有多少个。如果我们用数字工作,这很容易评估它是如何工作的。一个生存或死亡的双态模型说明了这一点。假设我们有 1000 个人活着,你有 5%的几率死去,95%的几率活着。有了这些严格的数字,我们可以为自己的每次迭代创建期望。在第一次迭代中,50 人死亡,950 人活着,第二年又有 50 人死亡,900 人活着。我们可以不断设定期望值,然后运行我们的模型,看看它有多接近这些数字。这个例子很容易看出我们如何评估它,但现在想象一个有 1000 个单词的语料库和与之相关的每个单词的概率。这有点难以计算。我最近用它来生成文本,我能评估它的唯一方法是确定它听起来语法不正确,只是一堆混乱的单词。我能做的唯一实际评估是,把它和马尔可夫链创造的句子进行比较。将来,如果您打算使用 Markov Chain 来生成文本(它主要用于 NLP ),请尝试将其与递归神经网络模型生成的文本进行比较,看看 Markov Chain made 版本的效果如何。

供思考的一点空间:易于使用的 NLP 框架

原文:https://towardsdatascience.com/a-little-spacy-food-for-thought-easy-to-use-nlp-framework-97cbcc81f977?source=collection_archive---------19-----------------------

在下面的文章中,你将会看到如何快速简单地开始使用 spaCy。这是特别有用的初学者爱好者在 NLP 领域的一步一步的指示和光明的例子。

spaCy 是一个 NLP 框架,由 Explosion AI 于 2015 年 2 月发布。它被认为是世界上最快的。易于使用和有能力使用神经网络是它的其他优势。

第一步:安装空间

打开您的终端(命令提示符),写下:

pip install spacy

第二步:下载语言模型

编写以下命令(仍在您的终端中):

python -m spacy download en_core_web_lg

型号(en_core_web_lg)是 spaCy 最大的英文型号,大小为 788 MB。有英文版的小模型,也有其他语言版的模型(英语、德语、法语、西班牙语、葡萄牙语、意大利语、荷兰语、希腊语)。

第三步:导入库并加载模型

在 python 编辑器中编写了以下几行代码后,您就可以享受 NLP 的乐趣了:

import spacy
nlp = spacy.load(‘en_core_web_lg’)

步骤 4:创建样本文本

sample_text = “Mark Zuckerberg took two days to testify before members of Congress last week, and he apologised for privacy breaches on Facebook. He said that the social media website did not take a broad enough view of its responsibility, which was a big mistake. He continued to take responsibility for Facebook, saying that he started it, runs it, and he is responsible for what happens at the company. Illinois Senator Dick Durbin asked Zuckerberg whether he would be comfortable sharing the name of the hotel where he stayed the previous night, or the names of the people who he messaged that week. The CEO was startled by the question, and he took about 7 seconds to respond with no.”doc = nlp(sample_text)

步骤 5:拆分段落的句子

让我们把这篇文章分成几个句子,并在句尾写上每个句子的字符长度:

sentences = list(doc3.sents)
for i in range(len(sentences)):
 print(sentences[i].text) 
 print(“Number of characters:”, len(sentences[i].text))
 print(“ — — — — — — — — — — — — — — — — — -”)

输出:

Mark Zuckerberg took two days to testify before members of Congress last week, and he apologised for privacy breaches on Facebook.
Number of characters: 130
-----------------------------------
He said that the social media website did not take a broad enough view of its responsibility, which was a big mistake.
Number of characters: 118
-----------------------------------
He continued to take responsibility for Facebook, saying that he started it, runs it, and he is responsible for what happens at the company.
Number of characters: 140
-----------------------------------
Illinois Senator Dick Durbin asked Zuckerberg whether he would be comfortable sharing the name of the hotel where he stayed the previous night, or the names of the people who he messaged that week.
Number of characters: 197
-----------------------------------
The CEO was startled by the question, and he took about 7 seconds to respond with no.
Number of characters: 85
-----------------------------------

步骤 6:实体识别

实体识别性能是自然语言处理模型的一个重要评价标准。spaCy 用一行代码就成功地实现了这一点:

from spacy import displacy
displacy.render(doc, style=’ent’, jupyter=True)

输出:

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

步骤 7:标记化和词性标注

让我们对文本进行标记化,并查看每个标记的一些属性:

for token in doc:
 print(“{0}\t{1}\t{2}\t{3}\t{4}\t{5}\t{6}\t{7}”.format(
 token.text,
 token.idx,
 token.lemma_,
 token.is_punct,
 token.is_space,
 token.shape_,
 token.pos_,
 token.tag_
 ))

输出:

Mark	0	mark	False	False	Xxxx	PROPN	NNP
Zucker.	5	zucker.	False	False	Xxxxx	PROPN	NNP
took	16	take	False	False	xxxx	VERB	VBD
two	21	two	False	False	xxx	NUM	CD
days	25	day	False	False	xxxx	NOUN	NNS
to	30	to	False	False	xx	PART	TO
testify	33	testify	False	False	xxxx	VERB	VB
before	41	before	False	False	xxxx	ADP	IN
members	48	member	False	False	xxxx	NOUN	NNS
of	56	of	False	False	xx	ADP	IN

同样,它非常容易应用,并立即给出令人满意的结果。关于我打印出来的属性的简要说明:

text: token itselfidx: starting byte of the tokenlemma_: root of the wordis_punct: is it a punctuation symbol or notis_space: is it a space or notshape_: shape of the token to show which letter is the capitalpos_: the simple part of speech tagtag_: the detailed part of speech tag

什么是言语标记?

它是在将整个文本分割成标记后,给每个标记(如名词、动词、形容词)分配标记的过程。

第八步:只有数字

当我们在处理语言和文本时,数字从何而来?

由于机器需要把一切都转换成数字来理解世界,所以在 NLP 世界中每个单词都用一个数组(单词向量)来表示。以下是《空间词典》中“人”的词向量:

[-1.7310e-01,  2.0663e-01,  1.6543e-02, ....., -7.3803e-02]

spaCy 的词向量的长度是 300。在其他框架中可以不同。

在建立单词向量之后,我们可以观察到上下文相似的单词在数学上也是相似的。以下是一些例子:

from scipy import spatialcosine_similarity = lambda x, y: 1 — spatial.distance.cosine(x, y)print(“apple vs banana: “, cosine_similarity(nlp.vocab[‘apple’].vector, nlp.vocab[‘banana’].vector))print(“car vs banana: “, cosine_similarity(nlp.vocab[‘car’].vector, nlp.vocab[‘banana’].vector))print(“car vs bus: “, cosine_similarity(nlp.vocab[‘car’].vector, nlp.vocab[‘bus’].vector))print(“tomatos vs banana: “, cosine_similarity(nlp.vocab[‘tomatos’].vector, nlp.vocab[‘banana’].vector))print(“tomatos vs cucumber: “, cosine_similarity(nlp.vocab[‘tomatos’].vector, nlp.vocab[‘cucumber’].vector))

输出:

apple vs banana:  0.5831844210624695
car vs banana:  0.16172660887241364
car vs bus:  0.48169606924057007
tomatos vs banana:  0.38079631328582764
tomatos vs cucumber:  0.5478045344352722

印象深刻?当比较两种水果或蔬菜或两种交通工具时,相似性更高。当两个不相关的物体如一辆汽车和一根香蕉进行比较时,相似性很低。当我们检查西红柿和香蕉的相似性时,我们观察到它高于汽车对香蕉的相似性,但低于西红柿对黄瓜和苹果对香蕉的相似性,这反映了现实。

第九步:国王=王后+(男人——女人)?

如果一切都用数字来表示,如果我们可以用数学的方法计算相似性,我们可以做一些其他的计算吗?比如我们把“男”减去“女”,把差加到“后”,能不能找到“王”?让我们试试:

from scipy import spatial

cosine_similarity = lambda x, y: 1 — spatial.distance.cosine(x, y)

man = nlp.vocab[‘man’].vector
woman = nlp.vocab[‘woman’].vector
queen = nlp.vocab[‘queen’].vector
king = nlp.vocab[‘king’].vectorcalculated_king = man — woman + queenprint(“similarity between our calculated king vector and real king vector:”, cosine_similarity(calculated_king, king))

输出:

similarity between our calculated king vector and real king vector: 0.771614134311676

我觉得还不错。你可以用不同的单词替换来尝试,你会观察到相似的有希望的结果。

总之;

本文的目的是对 spaCy 框架做一个简单的介绍,并展示一些简单的 NLP 应用示例。希望它是完美的。你可以在他们设计精良、内容丰富的网站https://spacy.io/上找到详细的信息和大量的例子。

如果你有任何进一步的问题,请不要犹豫,写信给:haydarozler@gmail.com。

从各种图表看詹姆斯·哈登的《可笑的季节》

原文:https://towardsdatascience.com/a-look-at-ridiculous-season-by-james-harden-through-various-charts-cbc790ff5d7f?source=collection_archive---------23-----------------------

很多人爱哈登,更有甚者,受不了他的比赛。但他正在经历现代篮球史上最令人印象深刻的赛季之一。他在没有太多低效的情况下打出了惊人的高投篮命中率。他正在做的这一切都要归功于他的(甚至更令人讨厌的)顶级武器。

单人军队

没有必要去搜索高级统计数据来了解詹姆斯·哈登背上的负担有多大。他已经连续 31 场比赛得分超过 30 分,这是除了伟大的威尔特·张伯伦之外 NBA 历史上最长的连胜纪录。但那是一些不同的时代,在 1979-80 年开始的三分时代,连续 30 场比赛得分最多的第二名是科比·布莱恩特,连续 16 场比赛,第三名是特雷西·麦克格雷迪,14 场比赛。他们都在 2002-03 赛季取得了这样的成就。

那个荒谬的事实让我研究了哈登本赛季的统计数据,我接着寻找的第一件事就是助攻/无助攻投篮命中率。我收集了从 1999-00 赛季到今年的数据。从 1996-97 赛季开始跟踪助攻得分的百分比,但我排除了前几个赛季,因为三分球线较短,三分球的数量过多。

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

Assisted vs Unassisted field goals made since 1999–00 — Image by Author

在上面的图表中,你可以看到自 1999-00 赛季以来,前 10 名得分手在每个赛季中助攻和无助攻的投篮次数。我还标记了那段时间总得分最高的 10 名球员。有趣的是,威斯布鲁克,艾弗森,甚至勒布朗的投篮总数大致相同。虽然代表罚球的圆圈大小比威斯布鲁克的大一点,但区别在于只有 50 次罚球,这使他领先拉塞尔约 150 分。

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

Assisted vs Unassisted 3pt field goals since 1999–00 — Image by Author

所有这些想法促使我制作了第二张图表。这里可以看到,他比其他球员的优势是由于疯狂的无辅助三分球数量而实现的。他在除了詹姆斯·哈登以外的任何球员面前都有超过 100 个无助攻三分球。

运球和每次触球得分

看到哈登疯狂的无助攻投篮次数,我想看看他每次运球次数和得分之间的相关性。

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

Dribbles per touch and points per touch — Image by Author

只有两个球员的每次运球次数超过哈登,他们是托尼·帕克和 DJ 奥古斯丁。一般来说,很多每次运球超过 4 次的球员都是控卫,这是符合逻辑的,因为他们通常会带球过球场,并叫停比赛,等等。但即使这样,哈登的每次触球得分也非常高。这意味着大多数触球不仅仅是带球穿过球场,而是带球,最终创造投篮机会,大多数时候是投篮。

我不知道他的高 PPT(每触得分)和高运球次数是否比保罗·乔治每触得分半分更令人印象深刻,这意味着他每第二次触球得分。他看起来真的是威斯布鲁克的完美球员,也是真正的 MVP 候选人。

拍摄图表

这篇文章的第二部分将致力于分析詹姆斯·哈登的投篮图表,以及他的投篮选择。类似于我之前的帖子,关于Luka don CII

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

Image by Author

首先,这里是哈登本赛季所有投篮的常规投篮图。他投了很多三分球,更重要的是,他的命中率很高。在真正的莫雷球精神中,中距离跳投并不多,所以在投篮不够的情况下,百分比真的不重要。

退后跳投

但现在我们来到了这篇文章最有趣的部分之一,也是哈登最危险的武器。当然,他的武器库中最有争议的一个镜头是《退后一步》。如果你看了视频,你会注意到有一些看起来像旅行的尝试。这就是所有大惊小怪的地方。但是我不会在这篇文章中深入探讨这个问题。我只想看看詹姆斯·哈登在退后一步跳投方面有多棒。

如果你看了我关于卢卡·东契奇的帖子(我把上面的几段链接了起来),你可能会注意到我为他的后退跳投做了一个原始的投篮图表。

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

Too Cluttered — Image by Author

我试着在这里做同样的事情,但是结果是毫无意义的。这是因为詹姆斯·哈登退后跳投的次数几乎是他所有投篮尝试的三分之一(总共 1316 次投篮尝试中的 417 次退后)。这种镜头的数量对于这个原始镜头图表来说太大了,没有意义,所以我像绘制普通镜头图表一样绘制它。

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

Image by Author

现在,这个图表真的令人印象深刻。与联盟平均百分比的比较与上面图表中的方法相同。这意味着他在每个区域的得分百分比是用所有类型的击球来计算的,而不仅仅是后退。从这张图表中我们可以得出结论,詹姆斯·哈登的退后一步跳投远高于任何类型投篮的平均 3%的命中率。

为了更好地理解詹姆斯·哈登退后一步跳投的效率有多荒谬,这里有另一个图表。

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

Image by Author

只有几个球员的三分球比詹姆斯·哈登还多。确切的说,只有八个。他也很有效地把握住了这些机会,超过 40%的尝试都成功了。

卡里姆有他的天勾,乔丹,科比和德克有他们自己版本的后仰投篮,哈基姆有梦摇,哈登有后退。

效率和使用

当人们想到哈登时,他们会想到几件事:

退后跳投。

走向罚球线。

成为一个投很多球的投手。

第一点我已经讲过了。在这篇文章中,除了在几个图表中作为的辅助数据,我没有触及罚球的话题。但我将试图揭穿围绕他的第三个想法。

首先,让我解释一下将在接下来的几个图表中看到的术语使用率。根据篮球参考,使用率百分比(或比率)是一个球员在场上使用的团队比赛百分比的估计。更具体地说,这意味着使用率是一个衡量球员在场上的所有比赛中有多少次投篮、罚球或失误的指标。

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

Image by Author

现在我们用效率和使用量来看看今年的情况。这张图表显示了 PPG 排名前 100 位的运动员。就使用而言,詹姆斯·哈登是他自己的故事,乔尔·恩比德落后 7%。这里可以看出总的趋势,随着使用率的上升,真实命中率下降。最大的异类肯定是哈登,但值得一提的是库里,詹尼斯和杜兰特也是异类。

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

Image by Author

这张图表显示了三分时代前 100 名得分手的效率,取决于使用情况。如前所述,我没有包括老一代的玩家,因为没有使用率和其他高级指标的数据。

根据 basketball-reference 的数据,詹姆斯·哈登的使用率在现代历史上(嗯,跟踪使用率的历史)排名第二,仅次于拉塞尔·维斯特布鲁克的 monster 2016-17 赛季。但是,他的真实投篮命中率(PTS / (2 * (FGA + 0.44 * FTA))比他高大约 7%。事实上,真实的百分比也比联盟平均水平高 7%,同时具有历史最高的使用率。

在此期间,我还标记了前 10 名得分手,以及查尔斯·巴克利 1987-88 赛季和斯蒂芬·库里令人难以置信的高效 2015-17 赛季,令人难以置信的 67%的 TS%。

这两张图表本身应该足以阻止哈登投篮命中率低和效率低的说法。

基于情况类型的评分

我要讲的最后一个话题是基于动作类型的分数。这也是我在关于 don ci 的帖子中提到的东西,但是我为这个帖子做了一个更有趣的可视化。我决定将这些值绘制成一个平行图,这导致了下面的图表。

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

Image by Author

我试着想象 MVP 的前 5 名候选人是如何得分的。用灰色线条,我也代表了本赛季前 50 名的得分手。这实际上只是根据这六种类型的评分来概述分数的大致分布。展示哈登在得分和拉高得分方面的差距,以及展示他的接球和投篮得分有多少。他在这方面得分如此之少是有道理的,因为整个赛季他有大约 70 个助攻进球,但人们会认为这个数字会更高。

在那之后,我很好奇休斯顿火箭队球员的情况。

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

Image by Author

和预期的差不多。卡佩拉和法里德在内线得分和一些肘部跳投中占据主导地位,每个人都专注于接球和投篮(每场比赛大约有 6 名球员在 4 分左右徘徊)。似乎只有克里斯·保罗和埃里克·戈登是另外两个在某些时候创造进球机会的球员。

如果你现在仔细看第一张图表,你会发现卡佩拉在得分上领先联盟。保罗和哈登这两个伟大的组织者显然是一个巨大的推动。

辅助图表

对于本帖的最后一张图表,我决定看看哈登助攻的一些投篮得分,看看他是如何为队友服务的。我受到启发,想到多亏了我在 Nylon Calculus 上看到的这个很棒的帖子。不幸的是,我没有传球起点的位置,换句话说,哈登从哪里传球,所以我的图表看起来不那么有吸引力。

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

Image by Author

简而言之,这是一张图表,非常粗糙,因为我不知道如何在视觉上改进它,但它很有用。看到他的助攻有 8 次中距离投篮(如果不算 PJ 塔克在篮下的投篮,就更少了),真是令人印象深刻。看起来哈登要么把球踢到三分范围内,要么只是把球投低上篮/扣篮。正如我已经说过的,以真正的莫雷球的方式。

结论

最后,我想说研究哈登的数据是一件非常有趣和简单的事情。无论你在哪里看,他都在一些历史上很好的数据上表现,除了在防守上,但即使在那里他也是在最差的平均数据上。

有些人仍然试图淡化本赛季和 MVP 候选资格,因为防守和我提到的其他一些要点(罚球,退后一步旅行,等等。),但事实是詹姆斯·哈登是一个进攻怪兽,他正在经历 NBA 篮球历史上最繁荣和高效的赛季之一。对我来说,他是 MVP 竞争中的主要领跑者,尽管也有一些伟大的候选人,如保罗·乔治,詹尼斯,当然还有斯蒂芬库里。这将会是一个有趣而激动人心的赛季,MVP 也是如此。

所有这些图表都是由来自 stats.nba.com 或 T2 的数据生成的。所有图表都是用 Python 创建的,使用的是 matplotlib 和 seaborn。代码以 Jupyter 笔记本的形式存在于我的 Github 库中。

逻辑回归模型中特征重要性的研究

原文:https://towardsdatascience.com/a-look-into-feature-importance-in-logistic-regression-models-a4aa970f9b0f?source=collection_archive---------2-----------------------

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

在完成了一个调查 PUBG 中 winning 的项目(https://medium . com/@ jasonrichards 911/winning-in-PUBG-clean-data-does-mean-ready-data-47620 a 50564)之后,我突然想到不同的模型会产生不同的功能重要性排名。对于模型选择的级别(逻辑回归、随机森林、XGBoost)并不奇怪,但在我的数据科学头脑中,我必须挖掘得更深,特别是在逻辑回归中。

让我们为那些已经准备点击后退按钮的人换一个方向。特征选择是模型调整中的一个重要步骤。简而言之,它降低了数据集中的维数,从而提高了模型的速度和性能。现在,我知道这涉及到一个更老的(我们称之为“有经验的”)模型…但是我们知道有时候老狗正是你所需要的。

稍微研究了一下之后,我发现了三种在逻辑回归模型中排列特性的方法。这将通过系数值、递归特征消除(RFE)和 sci-kit Learn 的 SelectFromModels (SFM)来实现。

所有这些方法都应用于 sklearn.linear_model。物流回归,因为 RFE 和 SFM 都是 sklearn 包。另请注意,运行 Statsmodels 版本的逻辑回归(Logit)来比较初始系数值,初始排名是相同的,因此我会假设在 Logit 模型上执行任何其他方法都会产生相同的结果,但我确实讨厌 ass-u-me 这个词,因此如果有任何人想要测试该假设,请随意使用。在执行这些方法之前,数据也被擦洗、清洁和白化。

现在来看本质。第一,系数。系数越高,特征的“重要性”越高。为了设置基线,决定选择前八个特性(这就是项目中使用的特性)。数据被拆分和拟合。如果你看看下面的图片,碰巧所有的正系数都产生了前八个特性,所以我只是将布尔值与列索引相匹配,并列出下面的八个。(靴子,杀死,步行距离,助攻,杀死条纹,骑距离,游泳距离,武器获得)。

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

LogReg Feature Selection by Coefficient Value

接下来是 RFE,可在 sklearn.feature_selection.RFE 中找到。RFE 没有深入研究细节,它是一种特征选择方法,适合模型,并删除最弱的特征(或多个特征),直到达到指定的特征数量。要获得特性的完整排名,只需设置参数 n_features_to_select = 1。如果将它设置为大于 1 的任何值,它会将前 n 名排序为 1,然后按顺序递减。在这里,在一点点列表操作(增强,伤害,爆头,治疗,杀伤点,杀伤,连续杀伤,最长杀伤)后,排名是非常明显的。

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

LogReg Feature Selection by RFE

使用的最后一个方法是 sk learn . feature _ selection . selectfrommodel。该函数的预期方法是,它将按重要性选择特性,您可以将它们保存为自己的特性数据帧,并直接实施到调整后的模型中。操纵代码来提供所选列的名称需要一点工作,但是有了咖啡因、时间和 Stackoverflow,一切皆有可能。(提升,伤害,死亡,死亡条纹,比赛持续时间,骑行距离,团队死亡,步行距离)。

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

LogReg Feature Selection with SFM

现在来看看从每种方法中选择的特性是如何改进模型的。具有所有特征(总共 18 个)的原始 LogReg 函数产生 0.9771113517371199 的“曲线下面积”(AUC)和 93%的 F1 分数。

系数排名:AUC:0.975317873246652;F1: 93%。因为我们确实减少了一半以上的功能,失去. 002 是一个相当不错的结果。

RFE:AUC:0.9726984765479213;F1: 93%。实际表现比系数选择稍差,但差不了多少。

SFM:AUC:0.976537660071581;F1: 93%。最佳性能,但也差不了多少

结论:总的来说,这两种方法的性能没有太大的差别。从计算开销的角度来看,系数排名是目前最快的,SFM 紧随 RFE 之后。需要记住的是,在超参数调整后,精确度可能会受到指数影响,如果这是在一场以美元为单位的 Kaggle 竞赛中排名第一或第二之间的差异,那么如果逻辑回归是最适合的模型,那么用尽您的特征选择选项可能值得一点额外的计算费用。

顺便提一下:我的 XGBoost 选择了 ( 击杀、步行距离、最长击杀、获得武器、治疗、增强、辅助、爆头击杀),这导致了(在超参数调整之后)99.4%的测试准确度分数。

GLTR 研究(使用 GPT 新协议)

原文:https://towardsdatascience.com/a-look-into-gltr-using-gpt-2-76d823057421?source=collection_archive---------12-----------------------

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

Taken from http://gltr.io/

随着 BERT 模型[1]的发布,自然语言处理(NLP)领域在过去的一年中取得了巨大的进步,该模型改善了许多问题的技术水平,如文本分类、问题回答等。现在,Open AI [2]发布了名为 GPT-2 [3]的语言模型,据称该模型能够生成无法识别为机器或人类所写的文本样本。

最近,来自麻省理工学院-IBM 沃森人工智能实验室和哈佛大学的合作团队推出了一款名为GiantLangauge ModelTestRoom(GLTR)的文本取证工具。GLTR 基本上使用 GPT-2 语言模型来区分人类生成的文本和机器生成的文本。

在这篇文章中,我将使用**GLTR(Python 中的)**来分析不同来源的文本片段,看看它们在文本的平滑度方面有何不同。我将使用 https://github.com/HendrikStrobelt/detecting-fake-text的 GLTR 代码。

下面是这段代码,将文本作为输入并使用 GPT-2 模型来输出包含三样东西的有效载荷

  1. 给定上下文中每个单词的概率。
  2. 给定上下文,整个词汇表中每个单词的等级。
  3. 给定上下文,前 K 个单词及其概率。
*import* numpy *as* np
*import* torch
*import* time
*import* nltk

*from* pytorch_pretrained_bert *import* (GPT2LMHeadModel, GPT2Tokenizer,
                                     BertTokenizer, BertForMaskedLM)

*from* matplotlib *import* pyplot *as* plt

*class* AbstractLanguageChecker():
    *"""
    Abstract Class that defines the Backend API of GLTR.

    To extend the GLTR interface, you need to inherit this and
    fill in the defined functions.
    """

    def __init__*(*self*):
        *'''
        In the subclass, you need to load all necessary components
        for the other functions.
        Typically, this will comprise a tokenizer and a model.
        '''
        self*.device = torch.device(
            "cuda" *if* torch.cuda.is_available() *else* "cpu")

    *def* check_probabilities(*self*, in_text, topk=40):
        *'''
        Function that GLTR interacts with to check the probabilities of words

        Params:
        - in_text: str -- The text that you want to check
        - topk: int -- Your desired truncation of the head of the distribution

        Output:
        - payload: dict -- The wrapper for results in this function, described below

        Payload values
        ==============
        bpe_strings: list of str -- Each individual token in the text
        real_topk: list of tuples -- (ranking, prob) of each token
        pred_topk: list of list of tuple -- (word, prob) for all topk
        '''
        raise* NotImplementedError

    *def* postprocess(*self*, token):
        *"""
        clean up the tokens from any special chars and encode
        leading space by UTF-8 code '\u0120', linebreak with UTF-8 code 266 '\u010A'* ***:param*** *token:  str -- raw token text* ***:return****: str -- cleaned and re-encoded token text
        """
        raise* NotImplementedError

*def* top_k_logits(logits, k):
    *'''
    Filters logits to only the top k choices
    from https://github.com/huggingface/pytorch-pretrained-BERT/blob/master/examples/run_gpt2.py
    '''
    if* k == 0:
        *return* logits
    values, _ = torch.topk(logits, k)
    min_values = values[:, -1]
    *return* torch.where(logits < min_values,
                       torch.ones_like(logits, dtype=logits.dtype) * -1e10,
                       logits)

*class* LM(AbstractLanguageChecker):
    *def __init__*(*self*, model_name_or_path="gpt2"):
        super(LM, *self*).__init__()
        *self*.enc = GPT2Tokenizer.from_pretrained(model_name_or_path)
        *self*.model = GPT2LMHeadModel.from_pretrained(model_name_or_path)
        *self*.model.to(*self*.device)
        *self*.model.eval()
        *self*.start_token = '<|endoftext|>'
        print("Loaded GPT-2 model!")

    *def* check_probabilities(*self*, in_text, topk=40):
        *# Process input* start_t = torch.full((1, 1),
                             *self*.enc.encoder[*self*.start_token],
                             device=*self*.device,
                             dtype=torch.long)
        context = *self*.enc.encode(in_text)
        context = torch.tensor(context,
                               device=*self*.device,
                               dtype=torch.long).unsqueeze(0)
        context = torch.cat([start_t, context], dim=1)
        *# Forward through the model* logits, _ = *self*.model(context)

        *# construct target and pred* yhat = torch.softmax(logits[0, :-1], dim=-1)
        y = context[0, 1:]
        *# Sort the predictions for each timestep* sorted_preds = np.argsort(-yhat.data.cpu().numpy())
        *# [(pos, prob), ...]* real_topk_pos = list(
            [int(np.where(sorted_preds[i] == y[i].item())[0][0])
             *for* i *in* range(y.shape[0])])
        real_topk_probs = yhat[np.arange(
            0, y.shape[0], 1), y].data.cpu().numpy().tolist()
        real_topk_probs = list(map(*lambda* x: round(x, 5), real_topk_probs))

        real_topk = list(zip(real_topk_pos, real_topk_probs))
        *# [str, str, ...]* bpe_strings = [*self*.enc.decoder[s.item()] *for* s *in* context[0]]

        bpe_strings = [*self*.postprocess(s) *for* s *in* bpe_strings]

        *# [[(pos, prob), ...], [(pos, prob), ..], ...]* pred_topk = [
            list(zip([*self*.enc.decoder[p] *for* p *in* sorted_preds[i][:topk]],
                     list(map(*lambda* x: round(x, 5),
                              yhat[i][sorted_preds[i][
                                      :topk]].data.cpu().numpy().tolist()))))
            *for* i *in* range(y.shape[0])]

        pred_topk = [[(*self*.postprocess(t[0]), t[1]) *for* t *in* pred] *for* pred *in* pred_topk]
        payload = {'bpe_strings': bpe_strings,
                   'real_topk': real_topk,
                   'pred_topk': pred_topk}
        *if* torch.cuda.is_available():
            torch.cuda.empty_cache()

        *return* payload

    *def* sample_unconditional(*self*, length=100, topk=5, temperature=1.0):
        *'''
        Sample `length` words from the model.
        Code strongly inspired by
        https://github.com/huggingface/pytorch-pretrained-BERT/blob/master/examples/run_gpt2.py

        '''* context = torch.full((1, 1),
                             *self*.enc.encoder[*self*.start_token],
                             device=*self*.device,
                             dtype=torch.long)
        prev = context
        output = context
        past = *None
        # Forward through the model
        with* torch.no_grad():
            *for* i *in* range(length):
                logits, past = *self*.model(prev, past=past)
                logits = logits[:, -1, :] / temperature
                *# Filter predictions to topk and softmax* probs = torch.softmax(top_k_logits(logits, k=topk),
                                      dim=-1)
                *# Sample* prev = torch.multinomial(probs, num_samples=1)
                *# Construct output* output = torch.cat((output, prev), dim=1)

        output_text = *self*.enc.decode(output[0].tolist())
        *return* output_text

    *def* postprocess(*self*, token):
        with_space = *False* with_break = *False
        if* token.startswith('Ġ'):
            with_space = *True* token = token[1:]
            *# print(token)
        elif* token.startswith('â'):
            token = ' '
        *elif* token.startswith('Ċ'):
            token = ' '
            with_break = *True* token = '-' *if* token.startswith('â') *else* token
        token = '“' *if* token.startswith('ľ') *else* token
        token = '”' *if* token.startswith('Ŀ') *else* token
        token = "'" *if* token.startswith('Ļ') *else* token

        *if* with_space:
            token = '\u0120' + token
        *if* with_break:
            token = '\u010A' + token

        *return* token

为了检查一篇文章的通顺程度,我会画出每个单词的排名。根据 GPT-2 语言模型,如果文本中单词的排名较高,则文本将是不平滑的。以下代码用于为文本创建这些绘图。

*def* plot_text(vals, what, name):
    *if* what=="prob":
        ourvals = vals[0]
        x = list(range(1,len(ourvals)+1))
        y = ourvals
        plt.plot(x, y, color='orange')
        plt.ylim(0,1)
        plt.savefig(name + ".png")
        *# plt.show()
    elif* what=="rank":
        ourvals = vals[1]
        x = list(range(1, len(ourvals) + 1))
        y = ourvals
        plt.plot(x, y, color='orange')
        plt.ylim(-1000, 50000)
        plt.savefig(name + ".png")
        *# plt.show()**def* main_code(raw_text):
    lm = LM()
    start = time.time()
    payload = lm.check_probabilities(raw_text, topk=5)
    *# print(payload["pred_topk"])* real_topK = payload["real_topk"]
    ranks = [i[0] *for* i *in* real_topK]
    preds = [i[1] *for* i *in* real_topK]
    plot_text([preds, ranks], 'rank', "rank_")
    end = time.time()
    print("{:.2f} Seconds for a check with GPT-2".format(end - start))

现在,让我们看看不同来源的文本在流畅度方面是否有所不同。我们将检查以下文本。

  1. 由 GPT-2 语言模型生成的文本。
  2. 新闻文章中的文字。
  3. 来自博客的文本。

以下是情节:

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

Rank plot for GPT-2 Generated Text

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

Rank plot for News Article

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

Rank plot for Blog Text

GPT-2 生成的文本的等级图非常平滑,因为它是由 GPT-2 模型本身检查的。博客和新闻文章数据有一些峰值,这表明围绕这些词有一些不一致之处。

作为一个有趣的练习,你可以分析不同类型的文章,看看在流畅度方面有什么不同。

GLTR 的一个主要用途可能是在 Grammarly 这样的系统中。它可以指出导致不一致的单词,并提示用户进行更改。这至少是一个不错的 GitHub 项目。

参考文献

[1]https://arxiv.org/abs/1810.04805

[2]https://openai.com/

[3]https://d4mucfpksywv . cloudfront . net/better-language-models/language _ models _ are _ unsupervised _ multask _ learners . pdf

机器生成的书和算法作者

原文:https://towardsdatascience.com/a-machine-generated-book-and-an-algorithmic-author-f02d4e62ffbe?source=collection_archive---------18-----------------------

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

对比是显而易见的。在奥威尔的《1984 年的 T0》中,一台机器被用来大量生产书籍,并分发给大众。轻率,浮夸和重复,这些灰色的书养活了一个没有生命的文化。当发现人工智能已经被用来写一本学术书籍时,很难不去想那个画面。我们被告知,这种写作的自动化是获取大量知识的一种快速有效的新方法。

除了 33 页的序言,这本书是“由一种算法自动编译的”。该算法是由出版商 Springer Nature 和法兰克福歌德大学应用计算语言学实验室合作开发的。整本书是 Springer Nature 的第一本“机器生成的书”,可以在免费下载

这本书的封面不是作者,而是一个算法的名字:Beta Writer。有趣的是,他们给了这位机械作者一个名和姓,大概是为了让它在封面上看起来不会太不合适。

Beta Writer 的风格可以被描述为冗长而单调——内容中有四个庞大的章节是笨拙的描述。章节标题暗示了缺乏技巧。第四章标题为“模型、SOC、最大值、时间、单元、数据、参数”,是典型的平面子分析法。诚然,分析和微妙显然不是目标。这是一本专门针对机械化总结的书。

正如 Springer Nature 所说,“书籍原型概述了快速增长的锂离子电池领域的最新研究”,并补充说它“旨在帮助研究人员有效管理该学科的信息过载”。这本书和它的算法作者 Beta Writer 是作为一个大领域的范围的手段提出的,为研究人员提供了克服在特定主题上发现的令人困惑和压倒性数量的材料的手段。虽然我很好奇读者纯粹的无聊会让它的内容变得难以理解到什么程度。

这与其说是写作,不如说是将信息进行分组的练习。这不能被描述为策展,没有足够的选择或叙事正在进行。取而代之的是,它使用“聚类程序将源文档排列成连贯的章节”,然后从这些章节中“创建文章的简明摘要”。接下来的问题是,聚类是否是作者身份,或者一种新的写作和书籍类别是否正在这里产生。一个问题是,这种从一个领域捆绑信息的做法是否有所推进。书籍不仅仅需要找到模式,还需要给它们上色,塑造它们遇到的星座。

这一发展并不打算以这本书结束,它也是一个预期的未来方向的标志。Springer Nature 图书部总经理尼尔斯·彼得·托马斯(Niels Peter Thomas)表示,出版商利用这项技术“旨在塑造图书出版和阅读的未来”。托马斯声称,“围绕自然语言处理和人工智能的新技术为我们探索在算法的帮助下生成科学内容提供了充满希望的机会”。这里有一个未来的方向,暗示这是一个新的文学分支的开始。人类为这本书撰写的序言也让人们感觉这本书触发了某种不确定的东西:

与许多技术创新一样,我们也承认,机器生成的研究文本可能会成为一种全新的内容,其具体特征尚不完全可预见。如果说我们确切知道这段旅程将把我们带到未来的什么地方,那就太奢侈了。

有一种对未知未来的愿景,据推测,机器学习预计将带来未知但似乎肯定的好处。反思这一切对作者的角色意味着什么,《人类的序言》为这一潜在的未来增添了一点血肉:

我们预见,未来将有广泛的选择来创建内容——从完全由人类创建的内容到各种混合的人机文本生成,再到完全由机器生成的文本。我们不期望作者会被算法取代。相反,我们预计研究人员和作者的角色仍将很重要,但随着越来越多的研究内容由算法产生,这一角色将发生实质性变化。

这里的愿景是人类、机器和混合文本的变体。另一种看待这一点的方式是将作者身份放在自动化的范围内。看起来 Beta Writer 可能还有合作作者。支撑这一观点的是一个想法,事实上是一个庆祝,一个新的自动化机构将改变知识和写作。

从广义上讲,成为一名学者已经变得越来越算法化,这种发展是一系列正在发生的变化中的又一步。这需要一些批判性的思考。就像其他走向自动化的举措一样,这种算法作者身份也是一种不断增强的效率、便利性等等的举措。也许最令人惊讶的不是人工智能能写出这样的书,而是它比真正的人类学者更便宜。

随着人工智能的发展,可能值得反复回到为什么的问题上来。在这种特殊情况下,机器增加了什么?我们可以问这是一种增进知识和理解的方式,还是仅仅是一种机械的包装和分发系统。看起来这与其说是一次思考的练习,不如说是一次自动化信息编目和重新打包的尝试。

人们很容易得出这样的结论:这标志着作者的自动死亡,他们被更快、更全面的机器所取代,但我怀疑,通过展示作者需要做什么,他们会适得其反。这本书缺少的东西实际上突出了一个作者带来的东西。我毫不怀疑这些系统将会进步很快,将来可能会更接近地复制作者身份,但我怀疑这是否可取。就其现状而言,这种机械的内容缺乏洞察力,同时也很难阅读。要使任何领域都可以消化,即使是以总结的形式,也需要一些活力。

《数据凝视:资本主义、权力和感知》于 12 月出版,有平装本和电子书。

如果你对技术、媒体和文化感兴趣,可以在这里找到一份免费的每周时事通讯的详情。

从文本片段中识别恐怖小说作者的机器学习方法

原文:https://towardsdatascience.com/a-machine-learning-approach-to-author-identification-of-horror-novels-from-text-snippets-3f1ef5dba634?source=collection_archive---------3-----------------------

让我们开始吧…

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

有许多小说正在被创作,但其中一些在多年后获得了狂热的地位,并被人们铭记了很久。小说有几种体裁和跨体裁(几种体裁的混合)。恐怖小说是一种特殊的小说类型。有许多著名的恐怖小说,即使在发行几十年后,仍然是读者的绝对最爱。例如,RL Stine 的鸡皮疙瘩系列(1998–2016)已经家喻户晓,是现代最著名的恐怖小说之一。但是许多经典的恐怖小说出现在 21 世纪之前。比如 H.P .洛夫克拉夫特的恐怖小说【未知卡达思的寻梦(1943) 已经是 20 世纪必读的恐怖小说之一。从这里,如果我们再回到 19 世纪,怎么会有人忘记玛丽·雪莱的弗兰肯斯坦(1818 & 1823) 和埃德加·爱伦·坡的厄舍古屋的倒塌(1839) ?但是有一点很明显,

每位作家,无论是洛夫克拉夫特、玛丽·雪莱还是爱伦坡,都有自己的写作风格,其中包括使用特定词汇的标志性时尚,这使得他们的文学作品独一无二,易于辨认

所以,让我们利用这一事实,从他们的恐怖小说中摘录或引用的文字片段中确定作者(洛夫克拉夫特/玛丽·雪莱/坡)。自然语言处理(NLP)支持的机器学习是解决上述问题的一个很好的方案。所以,我们把问题陈述清楚,开始行动吧!!!

问题陈述:给出埃德加·爱伦·坡、玛丽·雪莱和惠普·洛夫克拉夫特的著名小说中的文字片段/引文,指出该文字片段或引文的作者是谁

为此,考虑由 Kaggle 准备的 幽灵作者识别数据集

所以,让我们使用 NLTK(自然语言工具包)和 Scikit-Learn 开始用 Python 开发机器学习模型吧!!!

I. 使用 Pandas 加载(读取)数据集:

import pandas as pddf = pd.read_csv('train.csv')
df.head(5) # **for showing a snapshot of the dataset**

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

Snapshot of the Dataset in which under label author, EAP -> (Edgar Allan Poe), HPL -> (HP Lovecraft) and MWS -> (Mary Wollstonecraft Shelley)

二。文本处理步骤:

  1. 删除标点符号→从数据集(语料库)的所有文本片段(实例或文档)中删除所有标点符号。
  2. 一个词的词形变化叫做引理。例如,(正在学习,已学习)是词根单词 study 的变形形式或引理。因此,一个单词的词条被分组在单个词根下。这样做是为了使语料库中的词汇只包含不同的单词。
  3. 停用词的去除→停用词通常是冠词(a,an,the),介词(in,on,under,…)以及其他不提供任何关键或必要信息的频繁出现的词。它们被从数据集(语料库)中存在的所有文本片段中移除。
# **Importing necessary libraries** import string
from nltk.corpus import stopwords
from nltk.stem import WordNetLemmatizerlemmatiser = WordNetLemmatizer()# **Defining a module for Text Processing** def text_process(tex):
    # **1\. Removal of Punctuation Marks** 
    nopunct=[char for char in tex if char not in string.punctuation]
    nopunct=''.join(nopunct)
    # **2\. Lemmatisation** a=''
    i=0
    for i in range(len(nopunct.split())):
        b=lemmatiser.lemmatize(nopunct.split()[i], pos="v")
        a=a+b+' '
    # **3\. Removal of Stopwords** return [word for word in a.split() if word.lower() not 
            in stopwords.words('english')]

三。类别标签编码:

因为这是一个分类问题,这里的类是上面提到的三个作者。但是在数据集中,可以看到标签是非数字的(MWS、EAP 和 HPL)。这些是标签编码,使其成为数字,从 0 开始,按字母顺序描述每个标签,即(0 → EAP,1 → HPL 和 2 → MWS)

# **Importing necessary libraries** from sklearn.preprocessing import LabelEncodery = df['author']
labelencoder = LabelEncoder()
y = labelencoder.fit_transform(y)

四。字云可视化:

随着机器学习模型的开发,基于作者在文本中使用特定单词时有自己独特的风格这一事实,在单词云的帮助下,取分别属于 3 个作者的 3 个文本片段,完成 3 个作者最常用的单词到最少使用的单词的可视化。

# **Importing necessary libraries** from PIL import Image
from wordcloud import WordCloud
import matplotlib.pyplot as pltX = df['text']wordcloud1 = WordCloud().generate(X[0]) # **for EAP**
wordcloud2 = WordCloud().generate(X[1]) # **for HPL**
wordcloud3 = WordCloud().generate(X[3]) # **for MWS** print(X[0])
print(df['author'][0])
plt.imshow(wordcloud1, interpolation='bilinear')
plt.show()print(X[1])
print(df['author'][1])
plt.imshow(wordcloud2, interpolation='bilinear')
plt.show()print(X[3])
print(df['author'][3])
plt.imshow(wordcloud3, interpolation='bilinear')
plt.show()

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

Word Clouds for the 3 authors taking their text-snippet samples

动词 (verb 的缩写)特色工程用词袋:

机器学习算法只对数字数据有效。但是在这里,数据仅以文本的形式出现。为此,通过某种方式,需要将文本数据转换成数字形式。这样做的一种方法是特征工程。在这种方法中,从文本数据中提取或设计数字特征。存在许多特征工程技术。在这个问题中,使用了特征工程的词袋技术。

= >词汇袋:

这里,存在于语料库中的词汇被维护。这些单词充当每个实例或文档(这里是文本片段)的特征。针对作为特征的每个单词,考虑其在当前文档(文本片段)中的频率。因此,以这种方式,从文本数据或语料库中设计或提取单词特征。

# **Importing necessary libraries**
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.model_selection import train_test_split# **80-20 splitting the dataset (80%->Training and 20%->Validation)** X_train, X_test, y_train, y_test = train_test_split(X, y
                                  ,test_size=0.2, random_state=1234)# **defining the bag-of-words transformer on the text-processed corpus** # **i.e., text_process() declared in II is executed...** bow_transformer=CountVectorizer(analyzer=text_process).fit(X_train)# **transforming into Bag-of-Words and hence textual data to numeric..**
text_bow_train=bow_transformer.transform(X_train)#**ONLY TRAINING DATA**# **transforming into Bag-of-Words and hence textual data to numeric..** text_bow_test=bow_transformer.transform(X_test)#**TEST DATA**

不及物动词训练模型:

多项式朴素贝叶斯算法(分类器)已经被用作分类机器学习算法[1]。

# **Importing necessary libraries** from sklearn.naive_bayes import MultinomialNB# **instantiating the model with Multinomial Naive Bayes..** model = MultinomialNB()# **training the model...** model = model.fit(text_bow_train, y_train)

七。车型性能分析:

= >训练准确度

model.score(text_bow_train, y_train)

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

Training Accuracy

= >验证准确性

model.score(text_bow_test, y_test)

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

Test/Validation Accuracy

= >精确度、召回率和 F1–分数

# **Importing necessary libraries** from sklearn.metrics import classification_report

# **getting the predictions of the Validation Set...**
predictions = model.predict(text_bow_test)
# **getting the Precision, Recall, F1-Score** print(classification_report(y_test,predictions))

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

Classification Report

= >混淆矩阵

# **Importing necessary libraries** from sklearn.metrics import confusion_matrix
import numpy as np
import itertools
import matplotlib.pyplot as plt# **Defining a module for Confusion Matrix...** def plot_confusion_matrix(cm, classes,
                          normalize=False,
                          title='Confusion matrix',
                          cmap=plt.cm.Blues):
    """
    This function prints and plots the confusion matrix.
    Normalization can be applied by setting `normalize=True`.
    """
    if normalize:
        cm = cm.astype('float') / cm.sum(axis=1)[:, np.newaxis]
        print("Normalized confusion matrix")
    else:
        print('Confusion matrix, without normalization')print(cm)plt.imshow(cm, interpolation='nearest', cmap=cmap)
    plt.title(title)
    plt.colorbar()
    tick_marks = np.arange(len(classes))
    plt.xticks(tick_marks, classes, rotation=45)
    plt.yticks(tick_marks, classes)fmt = '.2f' if normalize else 'd'
    thresh = cm.max() / 2.
    for i, j in itertools.product(range(cm.shape[0])
                                  , range(cm.shape[1])):
        plt.text(j, i, format(cm[i, j], fmt),
                 horizontalalignment="center",
                 color="white" if cm[i, j] > thresh else "black")plt.tight_layout()
    plt.ylabel('True label')
    plt.xlabel('Predicted label')cm = confusion_matrix(y_test,predictions)
plt.figure()
plot_confusion_matrix(cm, classes=[0,1,2], normalize=True,
                      title='Confusion Matrix')

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

Normalized Confusion Matrix

根据性能分析,可以得出结论,NLP 驱动的机器学习模型已经成功地有效地正确分类了 84.14%的未知(验证集)样本。换句话说,84.14%的文本片段被正确地识别出属于三个作者中的哪一个。

基于我们的模特表演,能不能得出哪位作者的文笔最独特?

答案是肯定的!!!让我们看看归一化的混淆矩阵。这里标签 2 是最正确的分类。由于标签 2 指的是玛莉·渥斯顿克雷福特·雪莱,因此可以得出结论

玛莉·渥斯顿克雷福特·雪莱写恐怖小说的风格最独特的是埃德加·爱伦·坡和惠普·洛夫克拉夫特。

另外,换个角度,我们能说玛丽·雪莱、埃德加·爱伦·坡和惠普·洛夫克拉夫特谁是最多才多艺的作家吗?

同样,答案是肯定的!!!再次查看混淆矩阵,标签 0 是分类最不正确的。标签 0 指的是埃德加·爱伦·坡,所以可以得出结论

埃德加·爱伦·坡比惠普·洛夫克拉夫特和玛丽·雪莱都多才多艺。

这样,可以使用机器学习和自然语言处理来开发文本检测模型。

使用经过训练的伯努利朴素贝叶斯(而不是多项式朴素贝叶斯)的相关网络应用程序也已经使用 Flask API 在 Heroku 开发和部署。Web 应用程序的链接如下所示:

https://authoridentifier.herokuapp.com/

参考文献

[1]https://towards data science . com/multinomial-naive-Bayes-classifier-for-text-analysis-python-8dd 6825 ECE 67

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值