TowardsDataScience-博客中文翻译-2021-三十-

TowardsDataScience 博客中文翻译 2021(三十)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

揭开气流 DAG 脚本的神秘面纱

原文:https://towardsdatascience.com/de-mystifying-an-airflow-dag-script-ff4f267edf34?source=collection_archive---------21-----------------------

了解如何阅读气流 DAG 脚本

去飞溅

我第一次看到 Dag 脚本时,除了它主要是用 python 和一点 jinja 语言编写的,我发现脚本的流程很难理解。

DAG 表示有向无环图

当然,这可能是由于 dag 脚本的复杂性或可读性问题,但我也认为即使有一个简单的 dag 脚本和可读的代码,它仍然会有点混乱。在我的工作中,我正在训练寻找模式和我发现的模式,这有助于我更容易地浏览 dag 脚本。

Airflow 是一个以编程方式创作、调度和监控工作流的平台。虽然 Airflow 可以实现任何语言的程序,但实际的工作流是用 Python 编写的。点击了解更多关于气流的信息。

典型的 dag 脚本由五个数据块组成,它们是

  • 库导入块
  • DAG 参数块
  • DAG 定义块
  • 任务定义块
  • 任务流水线块
  1. 库导入块是 dag 所需的所有库被导入的地方。

典型的导入块如下所示

# import the libraries #to set datesfrom datetime import timedelta, datetime# The DAG object; we'll need this to instantiate a DAGfrom airflow import DAG# Operators; we need this to write tasks!from airflow.operators.bash_operator import BashOperator

2。DAG 参数类似于 DAG 的设置,与start_dateemail设置等的键值对一起存储在字典中。

一个典型的参数块看起来像这样

#defining DAG arguments# You can override them on a per-task basis during operator initializationdefault_args = {'owner': 'Wild One','start_date': datetime(2021,12,25),'email': ['xyz@somemail.com'],'retries': 1,'retry_delay': timedelta(minutes=5),}

请暂时忽略传递的每个参数/自变量的含义,因为它不在本帖的 范围之内。

3。****DAG 定义块涉及实例化在导入块中导入的 DAG 类,并传递诸如实际 DAG 名称或dag_id、在 DAG 参数块中设置的default_args等参数。

典型的 DAG 定义如下所示

# defining the DAGdag = DAG('my-first-dag',default_args=default_args,description='My first DAG',schedule_interval=timedelta(days=1),)

4 。当然每个 DAG 至少有一个任务。这就是任务定义块的用武之地。

DAGS 由运算符表示的任务组成。

任务定义包括实例化所需的操作符,以运行选择和传递参数的任务,如任务名称或task_id以及其他特定于所实例化的操作符类型的参数。

这些操作符应该已经在 导入块 中导入了。

典型的任务定义如下所示

# define the tasks# define the first taskstart_task = BashOperator(task_id='start',bash_command='echo "Hello world"',dag=dag,)# define the second taskend_task = BashOperator(task_id='end',bash_command='echo "Goodbye"',dag=dag,)

5。最后,任务流水线模块,帮助我们组织任务的顺序,即定义任务依赖性。它由一个位移位运算符/符号表示,看起来像这样: < <> >。对我来说,它们看起来或多或少有点像数学中的两个大于 25 的符号或小于 27 的符号,或者 bash 中的重定向运算符。在气流中,这些符号代表上游或下游运动。

  • 上游(>>)是指之前的
  • 下游(<<)是指之后的

典型的任务流水线如下所示

**# task pipelinestart_task >> end_task**

所以如果你看到一个任务管道task1 >> task2,这意味着任务 1 应该在任务 2 之前运行。但是,如果是这样:task1 << task2,表示任务 1 应该在*任务 2 之后运行。*****

由作者使用 Excalidraw 创建

上图是一个简单的 dag 图形视图,方框表示任务,箭头表示依赖关系。

一个简单的 DAG 脚本可能类似于下面的代码

注意注释以识别区块

由作者使用深度笔记创建

结论

现在您知道了如何解释典型 dag 脚本的流程,请注意,根据工作流的复杂性,它可能会变得复杂。请随意查看这里的以获取关于可用任务操作符、其众多参数可能性、每个参数的含义等信息。

卡夫卡笔下的死信队列(DLQ)

原文:https://towardsdatascience.com/dead-letter-queue-dlq-in-kafka-29418e0ec6cf?source=collection_archive---------12-----------------------

编程;编排

卡夫卡 DLQ 简介及其 Python 实现

图片来自 PixabayDaKub

D

图片作者( Jimit Dholakia )

装置

Python 中有各种库可以用来连接 Kafka 集群。其中一些是:

  1. 卡夫卡-巨蟒
  2. 汇流——卡夫卡
  3. PyKafka

我将使用 kafka-python 连接到 kafka 集群,并创建 Kafka 生产者和消费者客户端。

使用 pip 安装 kafka-python:

pip install kafka-python

履行

我们将首先导入必要的包,并定义引导服务器、主主题名和 DLQ 主题名,以创建 Kafka 生产者和消费者的实例。

from kafka import KafkaProducer, KafkaConsumer
import json
bootstrap_servers = ['localhost:9092']
primary_topic = 'primary-topic-name'
dlq_topic = 'dlq-topic-name'

现在,让我们为 DLQ 主题创建一个生成器,错误的消息将被发送到这个生成器中。

dlq_producer = KafkaProducer(
    bootstrap_servers=bootstrap_servers,
    value_serializer=lambda x: x.encode('utf-8'),
    acks='all'
)

接下来,我们将创建 Kafka Consumer 来消费主主题中的消息。

consumer = KafkaConsumer(
    primary_topic,
    bootstrap_servers=bootstrap_servers,
    auto_offset_reset='latest',
    enable_auto_commit=True,
    value_deserializer=lambda x: x.decode('utf-8')
)

现在,我们将把代码放在 try-except 块中。如果收到的消息不是 JSON 格式或者发生任何异常,那么消息将被发送到 DLQ 主题。

for msg in consumer:
    print(f'\nReceived:\nPartition: {msg.partition} \tOffset: {msg.offset}\tValue: {msg.value}')

    try:
        data = json.loads(msg.value)
        print('Data Received:', data)

    except:
        print(f'Value {msg.value} not in JSON format')
        dlq_producer.send(dlq_topic, value=msg.value)
        print('Message sent to DLQ Topic')

结论

创建 DLQ 主题有助于在不干扰其他消息的情况下识别格式错误的消息。DLQ 主题还帮助我们分析格式错误的消息,并可用于报告目的。

资源

这篇文章的代码片段可以在我的 GitHub 页面上找到。

参考

让我们连接

LinkedIn:https://www.linkedin.com/in/jimit105/
GitHub:https://github.com/jimit105Twitter:https://twitter.com/jimit105

处理熊猫的约会——你应该知道的 6 个常见操作

原文:https://towardsdatascience.com/dealing-with-dates-in-pandas-6-common-operations-you-should-know-1ea6057c6f4f?source=collection_archive---------11-----------------------

希望不会再和日期混淆了。

照片由 insung yoonUnsplash 上拍摄

除了文本和数字,日期是我们数据集中非常常见的数据类型。当我们使用熊猫来处理日期时,对于大多数数据科学家来说,这绝对不是最简单的任务。当我开始使用熊猫时,我不熟悉与日期相关的功能,所以每次当我处理日期时,我必须在网上搜索解决方案。为了减轻你的痛苦,在这里,我想用熊猫来回顾约会的 6 个常见操作。

1.阅读期间解析日期

当数据集包含日期信息时,您希望读取它。对于本教程,让我们创建一个名为dates_text.csv的 CSV 文件,以下面的数据行作为起点。

text_data = """date,category,balance
01/01/2022,A,100
02/02/2022,B,200
03/12/2022,C,300"""

with open("dates_text.csv", "w") as file:
    file.write(text_data)

让我们看看当我们读取这个 CSV 文件时会发生什么。

正在读取 CSV 文件

如上所示,问题在于date列被读取为object类型而不是日期类型,这使得它无法访问 Pandas 中任何与日期相关的功能。

简单的解决方法是让熊猫为我们解析日期。如下所示,我们为parse_dates参数指定一个包含日期列名的列表对象。正如所料,日期列现在是一种日期类型(即datetime64[ns])。请注意,如果您有多个日期列,可以使用parse_dates=[“date”, “another_date”]

读取 CSV 文件—解析日期

应该注意的是,Pandas 集成了强大的日期解析器,可以自动解析许多不同种类的日期。因此,您通常只需要设置parse_date参数。

您并不总是拥有包含日期作为单个值的数据集。下面显示了一个可能的场景,其中三列组成了完整的日期信息。

text_data_cols = """y,m,d,category,balance
2022,01,01,A,100
2022,02,02,B,200
2022,03,12,C,300"""with open("dates_text_cols.csv", "w") as file:
    file.write(text_data_cols)

要解析多列中的日期,可以向 **parse_dates** 参数发送一个 dictionary 对象。

组合日期列

2.指定日期格式

在美国,我们通常使用月前一天,这也是熊猫的默认格式。让我们检查一下我们在上一节中刚刚读到的数据帧。如图所示,日期值表示为 yyyy-mm-dd。

>>> df = pd.read_csv("dates_text.csv", parse_dates=["date"])
>>> df
        date category  balance
0 2022-01-01        A      100
1 2022-02-02        B      200
2 2022-03-12        C      300

如果你还记得,不清楚我们的日期是先用月还是先用日,后者是许多国家的惯例。

Raw Data:
text_data = """date,category,balance
01/01/2022,A,100
02/02/2022,B,200
03/12/2022,C,300"""

如果原始日期确实首先列出了日期,那该怎么办?为了正确读取这样的日期,我们可以指定 **dayfirst** 参数,如下图所示。

>>> df = pd.read_csv("dates_text.csv", parse_dates=["date"], dayfirst=True)
>>> df
        date category  balance
0 2022-01-01        A      100
1 2022-02-02        B      200
2 2022-12-03        C      300

如果您特别注意第三行,您会发现 12 现在被正确地列为月份,而不是之前被解析为日期。

除了parse_datesdayfirst之外,当您在解析日期时发现问题时可以尝试的另一个相关参数是将infer_datetime_format设置为True,这可以帮助推断默认的日期格式。

3.自定义日期解析器

当你有一个复杂的数据集时,你可能需要实现你的日期解析器。考虑以下文件,其中的数据使用特殊的日期格式。

text_data_fmt = """date,category,balance
Jan_01_2022,A,100
Feb_02_2022,B,200
Mar_12_2022,C,300"""

with open("custom_dt_fmt.csv", "w") as file:
    file.write(text_data_fmt)

当您试图自动解析日期时,它不起作用。

解析日期失败

在这种情况下,我们需要创建一个定制的数据解析器。一个可能的解决方案如下所示。

自定义日期分析器

这里棘手的事情是在strptime方法中定义适当的日期格式。你可以在这里找到完整的格式字符串。data_parser采用一个单参数函数,其中的参数指向您想要解析日期的列。

4.无论如何转换日期

当您不需要正确处理读取和解析日期时,您可能仍然需要在准备数据集的过程中处理日期。在这些情况下,使用熊猫的效用函数就很有用:to_datetime,其函数头如下所示(来源)。

pandas.to_datetime(*arg*, *errors='raise'*, *dayfirst=False*, *yearfirst=False*, *utc=None*, *format=None*, *exact=True*, *unit=None*, *infer_datetime_format=False*, *origin='unix'*, *cache=True)*

如您所见,该函数接受一系列参数,这些参数几乎是您处理日期所需的一切。更重要的是,你几乎可以传递任何东西作为arg参数。下面给出了一些例子。

熊猫到日期时间示例

您可以看到to_datetime可以处理单个字符串、字符串列表或系列对象。尽管返回的数据类型各不相同,但它们本质上是一样的,或者很容易互换。你可以在这里找到更多信息

5.创建日期范围

当我们处理可以使用日期作为自然索引的数据时,可以使用 Python 内置的datetime模块“手动”创建索引,如下所示。

“手动”创建的日期索引

然而,这个特性已经被 Pandas 考虑到了,我们应该为此使用date_range函数:

使用 date_range 创建日期索引

6.提取日期、时间等等

有时,我们可以有一个由日期和时间组成的时间戳。考虑下面的例子作为我们的起点。

熊猫的时间戳

如您所见,我们现在有了属于datetime类型的时间戳列。但是,我们希望将日期和时间分开,这样我们就可以进行其他操作。为此,您可以对 Pandas 使用dt访问器,如下所示。

>>> df["date"] = df["timestamp"].dt.date
>>> df["time"] = df["timestamp"].dt.time
>>> df
            timestamp category        date      time
0 2022-01-01 09:01:00        A  2022-01-01  09:01:00
1 2022-01-02 08:55:44        B  2022-01-02  08:55:44
2 2022-05-01 22:01:00        C  2022-05-01  22:01:00

实际上,您可以使用dt访问器做更多的事情,例如,您可以获得年、月、日,甚至是一年中的星期!下面是一些例子。

>>> df["timestamp"].dt.year
0    2022
1    2022
2    2022
Name: timestamp, dtype: int64
>>> df["timestamp"].dt.month
0    1
1    1
2    5
Name: timestamp, dtype: int64
>>> df["timestamp"].dt.weekday
0    5
1    6
2    6
Name: timestamp, dtype: int64

结论

在这篇文章中,我们回顾了 6 个常见的操作相关的加工日期在熊猫。我肯定忽略了一些方面。如果您有任何问题,请随时留下评论,我们可以在未来的文章中讨论其他功能!

感谢阅读这篇文章。通过注册我的简讯保持联系。还不是中等会员?使用我的会员链接通过支持我的写作(对你来说没有额外的费用,但是你的一部分会员费作为奖励由 Medium 重新分配给我)。

处理具有高基数的要素

原文:https://towardsdatascience.com/dealing-with-features-that-have-high-cardinality-1c9212d7ff1b?source=collection_archive---------2-----------------------

提示和技巧

一个简单的实用程序,我用来处理具有许多唯一值的分类特征

照片由乔治·帕甘三世Unsplash 上拍摄

什么是高基数?

几乎所有的数据集现在都有分类变量。每个分类变量由唯一的值组成。当有太多这样的唯一值时,分类特征被认为具有高基数。在这种情况下,一键编码成为一个大问题,因为我们在分类变量中为每个唯一值(指示其存在或不存在)设置了一个单独的列。这就导致了两个问题,一个是明显的空间消耗,但是这个问题没有第二个问题维数灾难那么大。我将更详细地讨论维数灾难,但首先,让我们来看看一键编码前后的数据。

一键编码前后我们的分类特征

我们将关注资格特征。因为这些数据是从许多人填写的表格中收集的,所以该列包含许多不同的资格。下面是该列的外观以及它所具有的所有唯一值。

我们可以看到该特性中有 15 个唯一值,它占用了 316KB 的空间。让我们用 pandas one _ hot 编码这个特性。

我们现在可以看到我们的原始特性已经变得有多大,存储它所需的空间自然也增加到了 592KB。这只是一个特征,如果在训练过程中我们拥有数百个分类变量,我们将最终拥有数百个特征,这在某些情况下不利于模型训练。简单的模型无法处理如此多的变量。但是现在让我们看看另一个主要问题,维数灾难。

维度的诅咒

下面是一个简单的总结:

随着特征数量的增长,我们需要准确区分这些特征(以便给我们一个预测)并概括我们的模型(学习函数)的数据量呈指数增长

如果你不想阅读下面的技术细节,请随意跳到下一节。

我想用 Yoshua Bengio 的(是的传说中的 Yoshua Bengio!)quora 回答更详细的解释一下这个。我强烈建议在这里阅读整个答案。根据答案,增加一个特征中不同值的数量只是增加了使用输入行(包含 n 个这样的特征)可以得到的可能组合的总数。假设我们有两个特性,每个特性有两个不同的值,这给了我们总共 4 种可能的方法来组合这两个特性。现在,如果其中一个有三个不同的值,我们将有 3X2 =6 种可能的方式来组合它们。

在经典的非参数学习算法(例如最近邻、高斯核 SVM、高斯核高斯过程等)中。)模型需要看到这些组合中的每一个的至少一个例子(或者至少尽可能多的覆盖感兴趣的配置的所有变化),以便产生正确的答案,该答案不同于其他附近配置所需的目标值。

对此有一个解决方法,即即使在缺乏大量训练数据的情况下,该模型也可以辨别未来预测的配置(不在训练集中),只要这些组合中存在某种结构(模式)。在大多数情况下,高基数使模型难以识别此类模式,因此模型不能很好地推广到训练集之外的示例。****

通过使用简单的聚合函数降低基数

下面是一个简单的函数,我用它来减少一个特性的基数。想法很简单。让属于高频率值的实例保持原样,并用一个新的类别替换其他实例,我们称之为 other。

  1. 选择一个阈值
  2. 按频率对列中的唯一值进行降序排序
  3. 不断增加这些排序(降序)的唯一值的频率,直到达到阈值。
  4. 这些是我们将保留的唯一类别,所有其他类别的实例将替换为“其他”。****

在浏览代码之前,让我们快速浏览一个例子。假设我们的列颜色有 100 个值,我们的阈值是 90%(即 90 )。我们有 5 种不同的颜色:红色(50)、蓝色(40)、黄色(5)、绿色(3)和橙色(2)。括号中的数字表示该列中有多少个该类别的实例。

我们看到红色(50)+蓝色(40)达到我们的阈值 90。在这种情况下,我们只保留 2 个类别(红色、蓝色),并将其他颜色的所有其他实例标记为“ Other ”。

因此,我们将基数从 5 减少到 3(红色、蓝色、其他)

这是我写的一个实用函数来帮助实现这一点。这是很好的评论,并完全遵循我上面描述的,所以你不会有问题。我们可以设置一个自定义阈值,并且 return_categories 选项可选地让我们在减少基数后看到所有唯一值的列表。

正如您所看到的,使用这个函数,我们将资格列的基数从 15 减少到了 6!

结论

我们看到了如何通过使用一个简单的函数来减少基数,更重要的是为什么这是必要的(维数灾难)。但是请记住,我们很幸运,我们的列中的值的分布允许我们使用这种方法。如果所有 15 个类别平均分布,我们将无法使用这种方法,在这种情况下,可能需要将 PCA 与数据集的其他特征结合使用,但在其他时间会更多地使用。

如果你喜欢这篇文章,这里有更多!

其他一些项目。可以联系我 这里 感谢您的配合!

处理 TensorFlow 中的不平衡数据:类权重

原文:https://towardsdatascience.com/dealing-with-imbalanced-data-in-tensorflow-class-weights-60f876911f99?source=collection_archive---------2-----------------------

在训练机器学习模型时,类不平衡是一个常见的挑战。以下是通过生成类权重以及如何在单输出和多输出模型中使用类权重的可能解决方案。

Unsplash 上的 Loic Leray 拍摄的照片

在为真实世界的应用程序开发模型时,经常会遇到类不平衡的问题。当与一个类相关联的实例明显多于与另一个类相关联的实例时,就会出现这种情况。

例如,在一个信用风险建模项目中,当查看历史数据中的贷款状态时,大部分被授予的贷款可能已经全额支付。如果使用易受类别不平衡影响的模型,违约贷款在训练过程中可能没有太大的相关性,因为当模型关注多数类别时,总体损失继续减少。

为了使模型更加关注贷款违约的示例,可以使用类权重,以便当未充分代表的类的实例被错误分类时,预测误差更大。

除了使用类别权重,还有其他方法来解决类别不平衡,例如过采样和欠采样两阶段训练,或者使用更多的代表性损失。然而,本文将重点关注在训练您的机器学习模型时如何计算和使用类权重,因为这是解决不平衡的一种非常简单有效的方法。

首先,我将向您介绍从数据集生成类权重的方法,然后介绍如何在单输出和多输出模型中使用它们。

生成类别权重

在二元分类中,类权重可以仅通过计算正类和负类的频率来表示,然后对其求逆,使得当乘以类损失时,代表性不足的类具有比多数类高得多的误差。

在多类或多标签问题中,需要计算每个类的频率。为此,Python 库 scikit-learn 提供了方法 compute_class_weight ,该方法接收完整的类数组和唯一的类标签集作为输入。如果参数 class_weight 为 None,则类权重将是统一的,另一方面,如果给定值‘balanced ’,则输出类权重将遵循以下公式:

n _ samples/(n _ classes * NP . bin count(y))

不幸的是,scikit-learn 方法不支持单热编码数据,也不支持多标签类。因此,我开发了另一个实用程序来生成多类和多标签问题的类权重,也允许一次性编码的数据,如下面的代码片段所示。

方法来避免 sci kit-learn compute _ class _ weight 方法的限制,并允许使用 Python 生成给定的一组多类或多标签标注的类权重,还支持 one-hot-encoded 格式。

该方法的输出将是一个格式为{ class _ label:class _ weight }的字典,这是与 TensorFlow 一起使用所需的格式。

在具有 TensorFlow Keras 的单输出模型中使用类别权重

在包含单个输出的简单模型中,Tensorflow 在 model.fit()中提供了一个名为 class_weight 的参数,允许直接指定每个目标类的权重。因此,它就像提供前面介绍的 generate_class_weights 方法的输出一样简单。

下面的代码片段提供了如何使用 class_weight 参数在 MNIST 手写数字数据集上训练 TensorFlow Keras 模型的示例。

在具有 TensorFlow Keras 的单一输出模型中使用类权重的示例。

在具有张量流 Keras 的多输出模型中使用类权重

在包含不止一个输出层的稍微复杂一点的模型的情况下,不幸的是您不能使用 class_weight 方法(尚不支持)。但是不要担心,因为我将为您提供一个解决方法,其中考虑了类权重的自定义损失。

在提供的示例中,Keras Functional API 用于构建多输出模型(只需提供两次相同的标签作为输入),对于两个输出,加权 分类交叉熵 损失被用作最常见的损失之一,由 Morten grftehauge 在 Keras 问题中提出。

在具有 TensorFlow Keras 的多输出模型中使用类权重的示例。

在多输出模型中使用类权重和处理类不平衡的关键思想是将权重集成到定制的损失函数中。

结论

在本文中,介绍了现实世界数据集中的类不平衡的问题,并深入解释了对这一挑战的常见解决方案使用类权重使模型更多地关注代表性不足的类。

为了使用这种解决方案,首先给出了一种在给定一组多类或多标签格式的类的情况下生成类权重的方法。接下来是关于如何在使用 TensorFlow 对不平衡数据集进行训练时使用这些类权重的两种方法,这两种方法都是在单输出和多输出模型的情况下。

如果你想发现更多像这样的帖子,你可以在下面找到我:

在生产环境中处理泄漏、丢失的数据

原文:https://towardsdatascience.com/dealing-with-leaky-missing-data-in-a-production-environment-d48304ad3b6b?source=collection_archive---------23-----------------------

行业笔记

埃琳娜·莫日维洛Unsplash 上拍摄的照片

作为一名顾问,我并不总能控制我收到的数据。和一个客户来来回回只能让你到此为止。在某一点上,你需要使用你所拥有的数据。这意味着我要处理大量杂乱的数据,并且非常熟悉各种不同的数据泄露。

数据泄漏可能非常隐蔽,尤其是如果您对数据收集过程没有太多的洞察力。通常,当数据点出现以下情况时,就会发生数据泄漏:

  1. 只是有时收集
  2. 不是以标准方式收集的
  3. 重写
  4. 在不同时间收集的

我很早就意识到,我需要一种有原则的方式来处理这些情况。无论我想出了什么,它都必须对训练数据和新的未来数据起作用,因为我的客户需要对新数据的每日预测。

我想到的第一个想法是把有问题的变量扔掉。对于一些客户来说,这意味着抛出一大堆信号。我知道我可以做得更好。我需要一种方法来使用数据集中存在的信息密度,但要消除漏洞。

我选定的是一种经常被忽视的统计方法,许多数据科学家从未听说过——通过链式方程进行多重插补。

数据

让我们用乳腺癌威斯康星数据集来看一个数据泄露的经典例子。在我们的场景中,我们为一个医学成像实验室工作。我们的任务是提出一个可以预测肿瘤是否是恶性的模型。然而,我们从多个医生那里获得数据,他们进行不同的测试,提供不同的数据。有时,如果发现肿瘤是恶性的,会进行第二系列测试,并收集更多数据。有时候,他们不是。这导致我们的一些领域在非恶性肿瘤的更高浓度中具有缺失值。乱七八糟。

import numpy as np
random_state = np.random.RandomState(seed=0)
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split

# Load data and split into training and new, "unseen" data.
X, y = load_breast_cancer(return_X_y=True, as_frame=True)
X.drop([c for c in X.columns if "error" in c], axis=1, inplace=True)
X_train, X_new, y_train, y_new = train_test_split(
    X, y, test_size=100, stratify=y, random_state=0
)

# train data has missing values correlated with
# the target (tumor malignancy)
X_train = X_train.copy()
for c in X_train.columns:
    ampute_ind = random_state.choice(
        X_train.index,
        size=100,
        p=(2-y_train) / (2-y_train).sum()
    )
    X_train.loc[ampute_ind, c] = np.NaN

# New data does not have missing values correlated
# with the target
X_new = X_new.copy()
for c in X_train.columns:
    ampute_ind = random_state.choice(
        X_new.index,
        size=10
    )
    X_new.loc[ampute_ind, c] = np.NaN

# Check out the distribution of missing values
# grouped by the target
X_train.isnull().groupby(y_train).mean().transpose()

我们缺失的区域与肿瘤是否是恶性的高度相关。从表面上看,这似乎是一件好事。这应该有助于我们对肿瘤进行分类。然而,这些数据正遭受相当严重的数据泄露。只有当我们真正确定了肿瘤是否是恶性的时,才进行更多的测试。因此,我们的训练数据与我们将要预测的新数据具有根本不同的行为。

如果我们现在对这些数据运行我们的模型,模型会不公平地将缺失值的样本归类为非恶性的情况比它应该出现的情况多得多。我们有一个难题——我们的数据集中有很高的信息密度,有很多有效数据。我们需要一种方法来消除这种泄漏,同时尽可能保留所有信息。

均值/中值插补的问题

处理缺失数据的常见方法是简单地用平均值或其他值估算每个点。这通常不是修复数据泄露的好方法。任何能够对非线性关系进行建模的预测模型都会采用这种模式,而不需要的信息仍然会泄漏出来。如果我们用每个变量的平均值估算X_train,然后运行我们的模型,我们会发现我们的模型不公平地将具有平均值估算值的变量归类为非恶性变量。我们也不会过得更好。

有人用均值插补修复数据泄漏的真实视频

多重插补

多重插补是一种迭代方法,用于将每个变量建模为数据集中其他变量的函数。

https://github.com/AnotherSamWilson/miceforest

这个算法的细节超出了本文的范围,但是如果你想知道更多,Stef Van Buuren 写了一本很棒的免费在线书籍,你可以在这里找到。这里,我们用一个包[miceforest](https://github.com/AnotherSamWilson/miceforest)来估算缺失值,这个包使用lightgbm 作为链接函数:

import miceforest as mf
kernel = mf.ImputationKernel(
    data=X_train,
    datasets=5,
    save_all_iterations=True,
    random_state=random_state
)
kernel.mice(2, verbose=True)

我们刚刚做的是训练 200 个随机森林([# variables]x[# datasets]x[# iterations]),并以迭代的方式使用这些随机森林的预测来填充我们数据集的缺失值。我们创建了多个数据集,因为我们通常不能 100%确定我们的插补值,所以我们多次运行该过程以获得不确定性度量。

一般来说,鼠标是一个昂贵的过程。然而,我们可以使用一个技巧来大大减少新数据的插补时间,并使这种方法在生产中可行。miceforest跟踪为每个变量训练的模型——我们可以简单地使用它们来估算我们遇到的任何新数据。这大大减少了插补时间。

构建分类器

既然我们已经有了完整的数据集并消除了数据泄漏,我们需要训练我们的模型。由于我们创建了 5 个估算数据集,问题立即变成了“我们应该使用哪个数据集来训练我们的模型?”

答案是“看情况”。如果您有足够的计算资源,并且希望尽可能健壮,理想情况下,您可以在每个估算的训练数据集上训练一个模型。一般来说,您构建的插补数据集越多,您对插补如何影响预测方差的理解就越好。

然而,为了简单起见,这里我们只在第一个数据集上训练 1 个模型,并使用该模型从生产中的 5 个不同估算数据集获得预测。

import lightgbm as lgb
dtrain = lgb.Dataset(
    data=kernel.complete_data(0),
    label=y_train
)
lgb_model = lgb.train(
    params={"objective": 'binary',"seed": 1, "verbosity": -1},
    train_set=dtrain,
    verbose_eval=False
)

好吧,我们已经很接近了。我们消除了数据泄漏,保持了数据集中的信息密度,并运行了一个可以预测肿瘤是否为恶性的模型。剩下的唯一一件事就是构建我们管道的推理部分。

给新数据打分

每天,医生会提交他们的测试结果,我们需要返回一个预测。在对新数据进行评分之前,我们需要估算缺失值。我们的训练数据集没有缺失值,我们的新数据也不应该缺失值。幸运的是,miceforest 保存了它在运行mice时创建的模型,并且可以估算我们的新数据,而不必重新训练模型:

# Get missing data imputations
new_data_imputed = kernel.impute_new_data(X_new)

# Get predictions for each dataset
predictions = np.array([
    lgb_model.predict(
        new_data_imputed.complete_data(i),
        raw_score=True
    )
    for i in range(kernel.dataset_count())
]).transpose()

我们的预测数组包含我们对新数据中每个样本的 5 个预测。如果你真的观察这个数组,你会发现这些预测通常非常接近。我们的数据集具有非常高的信息密度,这使得我们既可以估算我们的变量,又可以高度准确地模拟我们的目标。然而,我们仍然可以看到缺失数据的负面影响:

import pandas as pd
sample_var = predictions.var(1)
sample_missing_value_count = X_new.isnull().sum(1).values

missing_metrics = pd.DataFrame({
    'sample_stdev': (sample_var ** 0.5).round(3),
    "missing_value_count": np.minimum(sample_missing_value_count,4)
})missing_metrics.groupby("missing_value_count").agg({
    "sample_stdev": ["mean", "count"]
})

缺失变量越多的样本,其预测的方差越大。发生这种情况有两个原因:

  1. 我们用更少的真实数据进行推断
  2. 每个数据集中的数据有更多不同的机会

作者上传

最后,我们需要决定如何实际返回一个预测。这个完全看情况。对每个样本进行不确定性测量非常有用。我们可能希望返回每个样本的平均值以及第 25 和第 75 个百分位数。我们可能希望只返回中间值。

结论

我们已经展示了如何使用链式方程(MICE)的多重插补来消除数据泄漏。我们还展示了如何将这种方法扩展到生产环境,并用于获得预测结果的不确定性度量。

处理长时间运行的 Jupyter 笔记本

原文:https://towardsdatascience.com/dealing-with-long-running-jupyter-notebooks-83ab7fca7692?source=collection_archive---------35-----------------------

当您的浏览器与 Jupyter 笔记本断开连接时,这是非常令人沮丧的!

内森·杜姆劳在 Unsplash 上的照片

Saturn Cloud,我们管理着一个数据科学平台,该平台提供 Jupyter 笔记本、Dask 集群以及部署模型、仪表盘和作业的方式。因此,我们经常帮助客户对他们的笔记本电脑进行故障诊断,网络断开是一个常见问题。

我们已经有很多客户在为长时间运行的 Jupyter 笔记本而苦恼——那些需要几个小时或更长时间才能运行的笔记本。他们经常来找我们,因为这些长时间运行的笔记本电脑在某个时候会失去服务器和浏览器之间的连接,这在云服务中很常见。通常云服务会正常地重新连接,不会有任何问题,但是在 Jupyter 的情况下,如果连接丢失,那么 Jupyter 将停止保存任何输出。Jupyter 笔记本将所有状态存储在浏览器中,这意味着如果运行代码的服务器和查看代码的浏览器之间出现连接问题,笔记本的状态就会丢失。

如果我们客户的长时间运行的代码中有一个错误,并且连接曾经中断,那么用户就不能看到代码的输出和它所创建的错误消息。试图在没有输出的情况下调试这些模型是徒劳的。在本地使用 Jupyter 时这不是问题,因为计算机与自身的连接是无限稳定的,但在云中工作时这是一个问题。

背景

Jupyter 笔记本将所有状态存储在浏览器中,因此需要持续的网络连接。这是一个众所周知的设计问题,有许多含义。虽然网络问题不会导致笔记本中的代码停止执行,但它会影响输出保存到笔记本的方式。

Jupyter 笔记本的流程是:

  • 服务器将输出推送到您的浏览器。
  • 您的浏览器将其添加到笔记本对象中(并将其呈现到屏幕上)。
  • 您的浏览器会将笔记本保存回服务器。

在网络切断的情况下,该流中断,并且没有输出被保存。长期的解决方案是对 Jupyter 本身进行修改,以处理间歇性连接,这是一个非常活跃的讨论领域。目前还没有将它添加到开源 Jupyter 的时间表。

然而,有一个短期战略。

解决办法

我们只需少量代码就可以调整 Jupyter,使其将输出直接保存到服务器上的一个文件中。通过这样做,即使网络连接中断,服务器仍会存储输出。这并不完美——在理想的情况下,这种输出仍然会出现在笔记本本身中,但是将它们存储在某个地方而不是丢失是一种改进。将这段代码放在您长期运行的笔记本的顶部:

在你的笔记本顶部执行。 TADA!现在,当您运行笔记本电脑时,所有输出都将镜像到data.log平面文件中。

工作原理:在 Jupyter 笔记本中,普通的stdoutstderr文件对象被替换为ipykernel.iostream.OutStream对象(这就是它们在浏览器中的显示方式)。这个对象有一个 echo 对象,默认为可以传播输出的None。因此,第一组代码行粘贴了一个 Python 文件对象来代替 echo,所有普通的stdoutstderr现在也被复制到磁盘上。异常由 python 日志记录系统处理。在默认配置中,它不输出到stdoutstderr,因此第二组代码行对其进行了修补,并设置了 log leve。

结论

有了这个解决方案,长时间运行 Jupyter 笔记本电脑的最大痛苦就不复存在了。也就是说,在 aat Saturn,我们通常建议使用更好的硬件(GPU)或并行化(Dask ),以避免您的笔记本电脑需要等待 10 个小时才能运行。然而,如果您的问题是不可并行化的,这是一个合理的变通方法。然而,如果您不知道如何实现并行化,但希望您做到了,您应该告诉我们!我们真的很擅长!

声明:我是土星云的 CTO。我们让您的团队轻松连接云资源。想用 Jupyter 和 Dask?部署模型、仪表板或作业?在笔记本电脑或 4 TB Jupyter 实例上工作?完全透明地了解谁在使用哪些云资源?我们做所有这些,甚至更多。

原载于 2021 年 7 月 15 日https://Saturn cloud . io

亲爱的数据专家们,请永远不要满足于不产生影响

原文:https://towardsdatascience.com/dear-data-professionals-please-never-settle-for-less-than-making-an-impact-b5ee94a63b73?source=collection_archive---------39-----------------------

如何发现值得解决的问题,为数据项目定义有意义的范围,以使人们关心的方式传达见解,并交付真正的商业价值

作者照片

亲爱的数据专家们:

你做了不可思议的事。您已经分析了数据集的每个角落,应用了性能最佳的预测模型,设计了您能想到的最吸引人的图表和图形。然而,听完你发现的见解后,你的项目发起人摇了摇头。“但那不是我想要的。给我一些有用的东西,让我的团队可以采取行动。不要告诉我我已经知道的事情。”

一旦对自己的能力如此自信,你就会被让自己失望的麻木的负罪感所困扰,更糟糕的是,你让你的项目发起人失望了。他下次见到你时还会在乎吗?你会被一个他可以依靠的人取代吗?

在你认输之前,要知道这一点——爬起来再试一次永远都不晚。但这一次,你可能需要的不仅仅是数据清理、数学建模或数据可视化的技能。如果你从来不想满足于不产生影响,这里有三个非技术性的问题(包括答案),它们不仅会让你现在受益,还会让你受益多年。

为什么重要?

斯蒂芬·菲利普斯-Hostreviews.co.uk 在 Unsplash 上的照片

这里有一个我们在处理数据时应该记住的难以忽视的事实。我们的公司、我们的客户和我们的业务合作伙伴并不太关心我们如何将数据导入管道,我们应用什么转换技术,我们选择什么模型,以及我们的图表看起来有多漂亮。他们主要关注一件事:“为什么重要?”

说到生意,通常只有两件事很重要:时间和金钱。在时间和金钱有限的情况下,谁愿意将宝贵的资源浪费在解决毫无意义的问题上呢?没人!因此在关注数据、统计或软件之前,让我们好好了解一下我们的项目如何为我们服务的组织增加收入、削减成本或节省时间,好吗?如果问题无法与这些目标明确联系起来,我认为是时候重新开始或者优先考虑其他计划了。

但是我们怎么知道我们不知道什么呢?好吧,如果下面的问题来自我们的项目团队、项目发起人、业务用户甚至我们自己,把它们当作一个线索,我们需要留出更多的空间和时间来理解为什么解决这个特定的问题比其他问题更重要。

  • 我们这样做是为了什么?
  • 我们要帮助谁?
  • 为什么这对我们很重要?我们为什么需要它?
  • 哦,但这对我们的底线有什么影响呢?

我们的工作范围是什么?

如果你发现了一个需要用数据解决的有意义且重要的问题,那么恭喜你!现在是实际的项目规划。就像任何项目一样,数据项目需要有一个范围,以定义为什么需要该项目,预期将提供什么好处,以及完成后的成功情况。我们可以从写下范围中获得两个好处,并且随着项目的进展继续重写它。

  1. 当我们把自己的想法用语言表达出来时,我们可以更批判性地、更深入地思考手头的项目和问题。这让我们更深入地了解了我们的合作伙伴、工作的形式以及实现预期结果的过程。
  2. 写下范围有助于我们将关于项目的不连贯想法重新整理成一个精心构建的有组织的故事。通过这种方式,我们可以轻松地看到全局,并自信地将我们的想法传达给所有相关人员,从而让利益相关方达成一致,并获得更多支持。

你们中的一些人可能会问,“当我没有太多的信息开始时,我怎么写范围呢?”嗯,如果你想得到答案,你必须提出问题。这听起来很简单,但是说实话,探索现有问题的答案并不容易。然而,我们必须做我们必须做的事情,即深入挖掘并获取有价值的信息,以帮助我们解决困难的业务问题并更好地利用数据。

我也不得不承认,我没有完美的答案来帮助你轻松度过这个过程。但是,为了指导您提出什么问题来定义数据项目的范围,我提供了一张图片,展示了《用数据思考》一书的作者 Max Shron 提出的“CoNVO”结构。此外,我还根据自己的经验添加了一些有用的试探性问题。希望这些能对你有用。

作者照片

如果你想知道一个数据项目的 CoNVO 范围可能是什么样子,这里有一个我写的例子。

【上下文】 这家主要制造商为餐厅厨房、食品制造商和经销商提供蛋黄酱、沙司、调料和定制产品。它通过以商业数量销售和交付产品来赚钱。寻求建议的人是首席财务官。

【需求】 该制造商不知道如何在客户和产品层面定义有竞争力的定价。客户经理仅凭直觉和个人经验进行报价和与客户谈判定价。设定更好的定价以提高利润和客户谈判的正确方法是什么?

【愿景】 项目完成后,首席财务官将收到一份报告,概述为什么所选的一组标准是确定竞争性定价的理想标准,并附有支持示例;假设情景规划模型,将标准与建议的价格目标和对盈利能力的预测影响联系起来。

【结果】 如果首席财务官签署其调查结果,所选标准和模型将被纳入整个组织的销售流程。客户经理将利用模型生成的价格目标和对产品和服务的定量洞察来创建报价并与客户谈判。六个月后将进行一项后续研究,以验证新定价解决方案对提高组织收入和利润的影响。

我们怎么谈生意?

活动创建者Unsplash 上的照片

假设我们已经完成了所有的艰苦工作,争论了所有的数据集,并提取了可能成就或毁灭业务的见解,我们如何与我们的业务利益相关者交谈?嗯,我必须警告你,事情可能会变得有点复杂。但这是最后一搏,所以让我们坚持下去。

1914 年,在编码和计算机出现之前,威拉德·布林顿在他的书《呈现事实的图解方法》 中描述了一个熟悉的问题:“一次又一次地,委员会或董事会中一些无知或专横的成员会打乱一个了解事实的人经过深思熟虑的计划,仅仅是因为掌握事实的人不能充分准备好呈现他的事实以克服反对……正如大教堂是其基础一样,对数据的事实的有效呈现也是如此

快进到 2021 年,商业和技术之间的差距仍然存在了一个多世纪。业务利益相关者抱怨他们在数据分析上投入了多少资金,却没有提供他们想要的指导,而数据专业人士则抱怨决策者误解了他们费力的分析,或者不合理地期望他们凭空变魔术。一定有更好的方法让大家开心吧?我认为更好的沟通方式在于两个简单的原则。

同理心是王道

想象一下,一个不会说法语,只会做方便面的人,如果让他按照用法语写的菜谱做羊角面包,他会有什么感受?同样的逻辑也适用于此。如果结果没有用他们的语言进行交流,或者没有与他们不关心的话题联系起来,业务利益相关者如何看到切实的结果?在这种情况下,多一点同情心会大有帮助。这意味着在与利益相关者谈论业务之前,尝试回答以下问题。

  • 利益相关者有什么共同点和不同点?
  • 考虑到关键决策者先前的信念、假设以及个人兴趣,他们关心什么?他们对这些见解会有什么反应?
  • 你的核心信息是什么?
  • 你需要他们知道/思考/感受或行动什么?
  • 我如何将我的工作语言翻译成我的利益相关者的语言?

剥=点+证据+解释+链接

我们如何传达重要的见解,让人们信服?削皮法(借用自论文写作)在这里指导我们。当向业务利益相关者展示数据见解时,了解如何基于剥离方法构建我们的论点,这赋予我们特殊的说服力,最终帮助我们的利益相关者理解复杂的想法,并对我们的结果更有信心。

这里是你如何将你的洞察力包装成一个有说服力的论点的方法。

  • 观点:一种可以被合理怀疑,但我们相信我们可以证明的观点
  • 证据:一个数据可视化,一个地图,一个模型,帮助我们将原始数据转化为发现,并为这一点提供一个案例
  • 解释:说明为什么商业利益相关者应该相信我们提供的证据,我们使用了什么方法,以及我们如何合理地验证所有假设和免责声明
  • 链接:一份清晰的陈述,详细说明为什么我们的发现对利益相关者至关重要,我们的见解如何产生潜在的商业影响,以及他们应该采取什么行动

哦,等等!但是这些论点从何而来?像数据项目中的其他事情一样,这是一个迭代过程。在开始时,我们可能有一些证据不足的观点,或者我们可能以没有任何结论性观点或与业务价值的联系的大量证据而告终。不要烦恼。验证你的论点的一个好方法是让别人倾听并质疑你的论点。如果可能的话,我强烈建议与你的利益相关者进行一次辩论。这样做,你自己对主题的理解会通过微调论点而增加,而你的利益相关者会更了解你在做什么。谁知道呢?他们可能会好心地提供额外的领域知识,为你指明正确的方向。

准备好前进了吗?

1962 年,约翰·肯尼迪总统说,“我们选择在这十年登上月球并做其他事情,不是因为它们容易,而是因为它们困难;因为这个目标将有助于组织和衡量我们最大的能量和技能,因为这个挑战是我们愿意接受的,是我们不愿意推迟的,是我们想要赢得的,也是其他人想要赢得的。”

2021 年,鉴于从数据中获取有意义和有用的见解的需求越来越大,让我们问问自己,“作为一名数据专业人士,我们愿意接受什么样的挑战?”为了成为神奇的独角兽,在创造长期业务影响的同时,我们愿意付出多大的努力?

原载于 2021 年 1 月 9 日 http://thedigitalskye.comhttp://thedigitalskye.com/2021/01/09/dear-data-professionals-please-never-settle-for-less-than-making-an-impact/

亲爱的数据科学家们,我爱你们。真诚的,Web 3.0

原文:https://towardsdatascience.com/dear-data-scientists-i-love-you-sincerely-web-3-0-55049273905a?source=collection_archive---------6-----------------------

数据科学家对网络未来的审视

图片由皮克斯拜的 Gerd Altmann 提供

听说过蒂姆·伯纳斯·李吗?当然,你有。毕竟,他发明了互联网。

关于蒂姆,你可能还会知道,他发明了互联网 3.0,也就是 Web 3.0,也就是语义网,也就是空间网。下面是蒂姆爵士对互联网未来的看法:

“我对网络有一个梦想,在这个梦想中,计算机能够分析网络上的所有数据——人和计算机之间的内容、链接和交易。应该使这成为可能的“语义网”尚未出现,但当它出现时,贸易、官僚主义和我们日常生活的日常机制将由机器与机器对话来处理。人们吹捧了很久的‘智能代理’终将实现。”

但是 Web 3.0 到底是什么?

术语的多样性只说明了 Web 3.0 在今天所处的青春期。事实上,许多思想领袖仍在清晰地理解 Web 3.0 的内涵。

有些人将其定义为

“…一个用来描述万维网未来的术语”

其他提供了更具体的标准,如语义、AI、3D 和普遍性。

其他的仍然提供更加狭窄的定义,更加专注于当前的商业模式可能能够利用空间技术的这种未来状态的方式(我将在下面更详细地探究其中的一些定义)。

无论你如何称呼它,无论你如何定义它,都有一些重要的努力正在进行中,以开始实现蒂姆对万维网未来的预言,这对数据科学家来说有一些重要的意义。

我深入深渊,开始了解 Web 3.0 及其对我所热爱的职业的潜在影响。回头看我的是一线机会。一封来自未来的情书,渴望实现,乞求我们铺垫。

我的理解…目前来说

抛开所有的戏剧性不谈,我对 Web 3.0 的理解仍在不断发展,因为我了解并看到新产品带着 Web 3.0 营销标签进入这个领域。

我第一次注意到这个概念是在阅读了几篇由蒂姆·丹宁写的关于 Web 3.0 内容创作的文章之后,就像这里的这篇(嘿,看,另一个聪明的蒂姆😊).

Tim 还写了当今 Web 3.0 最突出的用例之一,加密货币。加密货币是 Web 3.0 潜力的很好例子,因为它们是一种去中心化和完全透明的价值交换手段。

密码消除了中央银行或政府控制货币流动的需要。这让我们重新理解 Web 3.0 到底意味着什么。

至少有两种定义

在我看来,有两种不同的定义正在形成。一个定义是对互联网技术未来状态的理想主义愿景。这一理想与伯纳斯-李的愿景最为契合。

第二是更直接地应用现有技术,这些技术尚未成为企业向消费者传递价值的标准。

让我们先解决后者,因为我认为这不是数据科学家最有价值的地方。

德勤(Deloitte)等几个著名的咨询集团正在推动 Web 3.0 与空间网络同义的说法。本质上,空间网络是一种未来状态,企业可以将客户数据连接到物联网设备,客户居住的地理位置可以将体验带入三维空间。认为 Pokémon Go 越来越成为常态。

向现有企业出售服务的咨询公司更喜欢这个定义,这是有道理的。这可以通过今天的技术实现,也符合现有的商业模式,即企业继续囤积用户数据以实现货币化。

在这种情况下,区块链仍然有用,企业与物联网提供商合作,建立连接这些设备的区块链服务,但企业仍然利用其集中的数据来混合和提供由内部衍生的见解调节的用户体验。

正是这种由超级用户驱动的沉浸式体验,让一些人把亚马逊和 Salesforce 这样的现有公司贴上了 Web 3.0 公司的标签,但事实并非如此。

这也不是伯纳斯-李设想的理想。Web 3.0 的理想状态要微妙得多,需要对现有的 Web 基础设施、在其上运行的应用程序以及传统的商业模式进行重大改变。

理想状态包括像区块链这样的分散式数据存储,用户控制自己的信息,并向想要使用这些数据的企业提供访问令牌。区块链的加密和分布式技术确保了安全性和数据隐私。但为了成为 Web 3.0,它必须对所有用户数据无处不在。

由于数据现在以分布式方式存储在整个互联网上,因此可以通过开发语言模型来更全面地理解用户需求,因为查询与用户交互密切相关。

换句话说,用户可以允许人工智能解决方案访问他们的数据,以丰富和进一步个性化他们的体验。在这种情况下,人工智能可以访问用户认为相关的数据,而不是从公司持有的中央存储库中获得的数据。

在这个理想化的未来状态中,数据科学家可能会有巨大的机会。

用 Web 3.0 为数据科学家牵线搭桥

你看,Web 3.0 完全是以用户为中心,用户数据分布在支持区块链的存储技术中。应用程序分布在这些相同的区块链平台上,因此用户可以选择允许这些应用程序(或他们所谓的 dApps)访问他们的数据,从而创建更丰富、更相关的体验。用户不再需要向企业请求数据,因为数据已经被他们控制并存储在区块链上。

正如这种新的用户级数据所有权有利于蒂姆·丹宁这样的内容创作者一样,它也可能有利于数据科学家。例如,一个未来的数据科学家联盟可以与用户合作 购买 访问过去归公司所有的数据,以利用这些数据建立模型,实现新的体验。数据可以跨 dApps 和设备混合,因为数据都存储在区块链上,并连接到用户,而不是独立的公司,因此解决方案可以专门为用户量身定制。

反过来,这些人工智能解决方案可以作为 dApps 回售给可能从使用它们中受益的用户。这样,数据生成者(用户)和数据“理解者”(数据科学家)都从这种关系中获得了金钱上的好处。

但是,这种未来是否太遥远而无法实现呢?

我正在跟踪的一家公司是海洋协议公司,它正在向数据科学家的 Web 3.0 迈进。澄清一下,我和这家公司没有任何关系。我只是发现数据科学家对他们的平台感兴趣。

Ocean Protocol 为企业和数据科学家等数据聚合者提供了市场,他们可以在一个分散的框架内一起买卖数据资产。

此外,Ocean Protocol 使私营企业能够在市场上出售他们的数据资产,而不必在防火墙之外共享数据。海洋协议采用了“计算到数据”的编排,允许人工智能模型在私有数据上训练。

想象一下,能够使用来自多个主要医院网络的数据来训练疾病模型,而无需访问数据本身,只需访问元数据。

在这个新的数据协议中,数据科学家的另一个令人兴奋的机会是购买数据,将其与其他数据混合,用机器学习模型增强它,并以增强的形式将 卖回

关于海洋协议等平台的最后一个想法

归根结底,数据科学家个人作为内容/模型/数据创造者在全球经济中发挥更大作用的潜力,他们在海洋协议等市场中的个人努力可以得到补偿。

这也意味着 AI 开发本身可能会变得分散。

因此,在这个新的分布式和用户拥有的数据框架中,人工智能的下一个重大进步可能更类似于元人工智能。也就是说,可以消费和组织其他人工智能模型的人工智能就像大脑一样,是围绕不同功能区域的互联网络组织的。

将这种类比推得更远一点,数据科学家成为互联网架构的新神经元,将这些神经元组织成功能区(功能等同的人工智能模型组),将它们与其他功能区连接起来以协调它们,并帮助我们解决更复杂的问题。

我的理解……明天

就像我说的,我还在学习。我确信我错过了一些东西,甚至可能误解了这个新空间的一些东西。对我来说,写作就是理解,所以我现在与你分享我的理解,理解到明天它可能不是我的理解。

Web 3.0 仍然非常新,许多变化肯定会到来。我将继续关注和参与这一新框架。尝试 Web 3.0 可能帮助实现的数据科学的潜在价值。

比如参与学习更多关于数据科学的知识?加入我

亲爱的招聘经理

原文:https://towardsdatascience.com/dear-hiring-manager-d15129362d68?source=collection_archive---------31-----------------------

如何避免招聘过程中最常见的绊脚石

和杰里米·希尔一起写的

拥有十多年经验的技术招聘人员

作者图片

招聘人员是一名信息经纪人。他们将希望填补职位空缺的公司与能够填补职位空缺的人联系起来。业内最优秀的招聘人员会花时间去了解招聘经理和潜在雇员,并通过网络将他们联系在一起。公司依靠招聘经理引进人才建立运转良好的团队。这是多方需求和期望的微妙平衡。这是在这个过程中遇到的三个最常见的绊脚石。

1.寻找完美的匹配

作者图片

事实上,你可能找不到一个和你在同一个行业,有着相同背景和长期工作经历的人。更重要的是,完美的匹配可能并不是最终最好的

1A。未能认识到软技能的重要性

对于非常技术性的职位,选择一个几乎拥有你所寻找的所有硬技能的候选人是一个容易的陷阱

但是有时候软技能对于一个人是否能胜任那个角色同样重要。特别是,

  • 项目管理能力
  • 讲故事的技巧
  • 解决问题的创造力

一个客户雇佣了一个完全符合他们要求的人。这个人检查了每一个技术箱:他们曾为一个大的竞争对手工作过,有技术背景和经验。问题?8 个月过去了,他一笔生意也没做成。

原来,老公司的名气是他完成以前销售的全部因素,当他转到新的小公司时,他不再有这种优势。这家小公司确实需要一个知道如何颠覆行业并找到创新方法将技术推向市场的人。

然后他们雇佣了一个有机械工程背景和创造力历史的人,但是他们必须学习机器人学、地下工业和地下工程的所有知识。她最终非常成功,带来了数千万美元的销售额,并在那家公司呆了五年。

经验法则

在以下情况下,您应该面试此人:

  • 他们拥有 100%技能却只有 50%技能
  • 他们拥有技能的 100% ,却只有技能的50%

如果你思想开放一点,调整你的期望,你可能会对你发现的珠宝感到惊讶。

1B。需要多年的技术经验,而这些经验并不存在

看看这个招聘启事:

2021 年 3 月 18 日发布的 Capital One Bank 数据科学总监职位的招聘信息

除了语法错误之外,上一个广告中突出的是什么:

  • 机器学习为了解决大规模应用的大数据在 10 年前是不存在的。

2021 年 4 月 6 日发布的英特尔首席数据科学家职位招聘信息

这则广告的突出之处是:

  • TensorFlow 发布于 2015 年 11 月 19 日,大约是这个工作发布前的 5 年零 5 个月。
  • PyTorch 发布于 2015 年 9 月,大约是这个职位发布前的 5 年零 7 个月。

招聘人员通常要求拥有 8-10 年数据科学经验的数据科学家,但数据科学在不久前还不是一个东西

1C。面试的现场编码部分

作者图片

以下文字改编自 丹尼尔·卡内曼的思维快慢 :

想象你正被五个陌生人注视着检查你。评判你。

现在快速地,

一个球棒和球的价格是 1.10 美元。球棒比球贵一美元。这个球多少钱?

卡尼曼解释说,如果你回答了 10 美分,你凭直觉回答了这个问题,而哈佛、普林斯顿和麻省理工学院 50%的学生都回答错了。研究表明,在的压力下,我们做出直觉的决定,而不是深思熟虑的决定(于,2016 )。有趣的是,如果你在参加现场 python 编码考试之前告诉自己你很棒,你应该在考试中表现得更好( Creswell 等人,2013 )。

在那天你与他们交谈的 45 分钟内,表现良好的人在压力下做出了慎重的决定。

这项技能对于以下情况尤为重要:

  • 赛车手
  • 水肺潜水员
  • 宇航员

在现场编码测试中表现不佳的人,当他们能够放松下来并适当地思考时,可能会做出更慎重的决定。除非你想淘汰大量有分析头脑的人,否则你可能会考虑寻找良好的解决问题能力的证据。如果你要招聘一名数据科学家,试着在一个 24 小时带回家的项目中评估他们的表现。如果你担心作弊,研究表明,贴上荣誉代码可以大大减少这种情况。

还有,球 5 分钱。

2.没有为角色做预算

使用个人轶事代替市场数据

不:我的朋友是 X 公司的招聘经理,他们刚刚雇佣了一个每年生产 15 颗软糖的人,所以这也是我将要支付的工资。

是的:找到一份你想要什么样员工的简介,并根据这个人在你的市场上多年的收入记录来制定预算。招聘人员应该免费提供这些信息。

一家公司对一名高级数据科学家感兴趣,并找到了完美的候选人,但这位潜在雇员想要比预算多 20 颗糖豆。因为。你好。他们是数据科学家。他们知道自己的市场价值。毕竟 Glassdoor 和 LinkedIn 提供的是薪资信息。支持数据显示,3-4 份档案也表明预算太低。

最终,招聘经理获准提高薪酬,这花了 1.5 周的时间。第四天,候选人接受了竞争对手的另一个职位(工资更高),非常成功,4 年后的今天仍然在那里工作。如果招聘经理在创建职位之前咨询了实时市场数据,他们就不会把首选候选人拱手让给竞争对手,而且无论如何他们都必须提高数据来雇佣下一个候选人。

3.缺乏反馈

不告诉招聘人员哪里出了问题

招聘经理通常会写下一份工作并刊登广告,期望收到大量简历,从中挑选出最合适的候选人。最终发生的情况是,招聘人员会推荐不一定适合该职位的人,而没有人最终得到他们需要的东西。

为什么?因为招聘人员不是软件工程师/海底潜水员/数据科学家/机器人专家/旋转发动机机械师。有时他们需要你的专业知识来帮助指导他们给你带来最好的候选人。不告诉他们在这个过程中出了什么问题,就错过了教育他们可以改进的机会。建立关系会给你带来更好的结果。

例如,在一个工程职位中,公司正在寻找在一个非常特殊的机制中有经验的人。招聘人员把有相似经历的人寄给他,但是一个接一个,每个候选人都被拒绝了。在一次反馈会议后,招聘人员明白了招聘经理在寻找什么,并激发了他的创造力。他去了汽车行业,找到了一个与招聘经理在申请人才库中寻找的机制完全相同的人,这两个人之前都没有考虑过。该公司聘用了他,11 年后他仍在那里,现在是一名经理,管理着自己的团队。

最后

你有很大的责任去寻找人才来满足公司的人力资源需求。以下提示将帮助你趟过泥沼,找到珠宝。

  • 为新员工设定现实可行的标准。愿意调整自己的期望,保持开放的心态。
  • 以合适的成本雇佣合适的人。这对你和候选人来说都更快更容易。
  • 与招聘人员建立关系,让他们知道如何改进他们带来的候选人。最后,每个人都满意了。

招聘愉快!

来源

资本一号,数据科学总监招聘启事:https://www . capitalonecareers . com/job/McLean/Director-Data-Science/1732/17587251?UTM _ campaign = Google _ jobs _ apply&UTM _ source = Google _ jobs _ apply&UTM _ medium = organic。2021 年 3 月 24 日接入。

克雷斯韦尔,法学博士,达奇尔,J.M .,克莱因,W.M .,哈里斯,P.R .和莱文,J.M ., 2013。自我肯定能提高压力下解决问题的能力。 PloS one8 (5),p.e62593。

希尔,杰里米。个人通信,2021。

英特尔,首席数据科学家职位发布:https://Intel . wd1 . myworkday jobs . com/External/job/India-Bangalore/Lead-Data-Scientist _ Jr 0161659-1。2021 年 4 月 8 日接入。

丹尼尔·卡尼曼。思考,快与慢。麦克米伦,2011 年。

基督教 B 米勒。“大多数学生到底有多不诚实?."纽约时报。2020 年 11 月 13 日。2021 年 4 月 8 日访问。https://www . nytimes . com/2020/11/13/opinion/Sunday/online-learning-checking . html #:~:text = experimental % 20 research % 20 has % 20 repeally % 20 found,with % 20 schools % 20 that % 20 are % 20 not。&text = A % 20 几% 20 学校% 20 开始% 20 学校% 20 代码

萨卡尔,迪潘詹。个人通信,2021。

于,R 。, 2016.压力增强决策偏差:压力诱导的深思熟虑到直觉(SIDI)模型。压力的神经生物学3 ,第 83–95 页。

亲爱的强化学习代理,请解释你的行动。

原文:https://towardsdatascience.com/dear-reinforcement-learning-agent-please-explain-your-actions-da6635390d4d?source=collection_archive---------15-----------------------

纵向控制的可解释强化学习

照片由詹姆斯·庞德Unsplash 拍摄

下面这篇文章介绍了我与 Jan Dohmen 和 Marco Wiering 共同进行的研究。

TL;强化学习在许多应用中显示出实现最佳性能的前景。然而,只要学习的动作保持透明,它们在安全相关的应用中的使用是不可能的。这里提出的新的 RL-SHAP 图打开了黑箱,为强化学习决策提供了一个新的视角。

情节

假设你是一名研究自动驾驶车辆的工程师。一个令人兴奋的想法,不是吗?

还有更好的。你花时间说服你老板用机器学习做纵向控制,他同意了!

你开始使用最具创新性的机器学习算法,并为车辆的纵向控制训练了一个强化学习代理。

团队已经很努力了,强化学习代理已经训练了几个小时,而且很有效。

LongiControl 环境中测试路线上的动作和输入特性。第一张图用蓝色显示车速,用橙色显示限速。在第二张图中,代理人的行动过程如下。这被限制在-1 和 1 之间的范围内。这里+1 代表最大正加速度,-1 代表最大负加速度(减速度)。下图显示了状态表示中包含的 7 个特征过程。

你激动不已,迫不及待地想向你的老板展示这个伟大的成果…

会议开始了,突然…他问你:

“为什么代理在 270 m 距离给出全油门,那么为什么代理选择 1 的动作?”

你说什么?

照片由奥斯潘阿里Unsplash 上拍摄

你想想你该怎么回答。

可能上次训练的时候损耗特别低?

也许代理在 99.999 %的情况下遵守了限速?

或者你只是说人工智能是如此的聪明,以至于你不应该质疑它的决定?;)

或者

你倒回时间,读这篇文章,用 SHAP 来解释:

  • 当前速度限制对行动的正面影响最大(+ 1.44)
  • 当前车速也被认为很重要,并降低了动作(- 0.78)
  • 【next 之后的速度限制对这一点上的决定几乎没有影响。

那听起来确实很有趣。但是我是如何得到这些价值的呢?我在哪里可以把它们读出来?

如果你在问自己这些问题,那么你来对地方了。喜欢读这篇文章。

PS:如果真的好奇,向下滚动到有 RL-Shap 图的部分;)

动机

深度强化学习(DRL)有潜力在各种实际应用中超越现有的最先进水平。然而,只要学习的策略和执行的决策难以解释,DRL 就不会找到进入安全相关应用领域的方法。

在这篇文章中,深度强化学习与 SHAP 联姻(SHapley Additive exPlanations)[1]。DRL 增加了 SHAP 值,这有助于更好地理解习得性行动选择策略。通过 OpenAI Gym LongiControl 环境[2]演示了 SHAP 方法在 DRL 的应用。

介绍

如前所述,许多现实世界的应用程序面临的一大挑战是黑盒行为。经过一个学习过程后,人们可能不清楚为什么 DRL 代理人会做出某些决定。通常不清楚学习的控制是否有意义,或者在训练期间是否出了问题。只要不能理解决策是如何做出的,它就不适合用于与安全相关的应用领域。此外,深度 RL 结果的可解释性允许更快地修复错误并获得进一步的信息,例如某些状态特征的敏感性。

强化学习

由于大多数读者肯定熟悉强化学习的基础知识,所以我将在下面简单总结一下这些基础知识。更详细的资料,我推荐[3]和[4]。

强化学习是一种从与环境的相互作用中学习以实现既定目标的直接方法。

强化学习互动[3]

在每一个离散的时刻,代理人都面临着一个来自环境的状态,他必须选择一个动作。代理基于一个内部策略来决定它的动作,该策略将一个动作映射到每个可观察的状态。对于每一个选择的动作,代理人都会收到一个奖励和一个新的状态。

当在强化学习中使用深度神经网络来表示状态和动作以及状态、动作和 Q 值之间的关系时,我们正在讨论深度强化学习。

可解释性

正如[5]中所讨论的,创建可解释性的方法可以分为两大类:模型透明性和事后可解释性。

前者试图解释模型结构,而事后可解释性则用于理解模型工作的原因。虽然在深度学习中可以理解大量的计算步骤,但是不能期望从这种学习中获得模型的知识。因此,事后可解释性更令人感兴趣。

沙普利值

利用 Shapley 值[6]是合作博弈论的一个解概念。合作博弈理论研究游戏中的参与者如何通过形成联盟来最大化他们自己的价值。

SHAP

SHAP 提供了一种博弈论的方法来解释机器学习模型的输出。对于特定的预测,SHAP 为每个特征分配一个重要性值。SHAP 值的总和导致模型的预测。

实验设置

遥控环境已经用于实验研究。。目标是车辆在给定时间内尽可能节能地完成单车道路线。

远程控制可视化

有关该环境的更详细介绍,我可以向您推荐以下文章:

方法

新提出的方法包括四个步骤。在第一步中,需要对 RL 代理进行培训。然后,可以在轨迹上测试经过训练的代理,并通过显示图表来分析产生的状态特征和动作,这些图表提供了选择动作的原因的清晰可视化。

DRL 代理商—培训

DRL 代理的培训可以像您在之前的设置中所做的那样进行。尽管我们关注于演员-评论家 RL 算法,但是对于这里提出的解释方法的应用没有明确的训练要求。一旦代理达到预定的性能,就执行过程中的下一步。

DRL 代理—测试功能

对于测试,只对 DRL 代理的参与者网络感兴趣,它将状态特征映射到一个动作。

在确定了感兴趣的神经网络之后,为了分析参与者,出现了应该将哪些输入值用于测试的问题。理论上,随机输入值是可能的。然而,这些可能显示出 DRL 代理没有被训练的组合,因此违反了演员的模型有效性。在这里介绍的过程中,代理面临着远程控制环境中的新场景。

SHAP 价值观

试运行后,下一步是计算 SHAP 值。为此,解释器是从 tensorflow actor 网络和测试运行的状态序列中近似得到的。

RL-SHAP 图

由于很难观察单个例子,也很难识别状态-行动组合的长期影响,因此可以绘制出状态变量的整个过程。为了提高这些图形的可理解性,SHAP 值的附加信息将在适当的位置用颜色显示。

结果

下面以 LongiControl 环境为例解释代理学习的行为。下图显示了单个状态的 SHAP 值和代理的操作。

单态分析

  • 基本利率的值为 0.08。基本速率是在神经网络的输入变量未知的情况下计算的模型输出
  • 特征速度的 SHAP 值-0.78 将添加到该值中
  • 接下来是先前加速度的 SHAP 值,0.09 等等
  • 基本速率和七个 SHAP 值的和等于 1.0,并且近似对应于代理的动作

从该示例可以得出,对于给定状态,特征当前速度限制具有最大影响,而特征未来速度限制距离 2 对结果动作具有最小影响。由此,我们可以简单地推断出,智能体完全加速主要是因为高速限制。

在分析了单个状态的动作选择过程之后,我们现在将考察一个更长的轨迹。

RL-SHAP 图

下图显示了新引入的 RL-SHAP 图,以便更全面地了解决策过程。

  • 作为附加信息,该特征(SHAP 值)对所选动作的影响用所用颜色突出显示
  • 特征的红色表示该特征增加了值,蓝色表示该值减少了值,灰色表示该值对动作的影响很小

RL-SHAP 图。垂直虚线突出显示了上图中分析的状态

  • 在第三张图中,红色可以通过前 70 米内的速度清楚地显示出来。代理强烈加速以达到接近速度限制的速度。此后,SHAP 值减小,因此该特征对动作的影响减小,这可以通过颜色从红色变为灰色来看出
  • 相比之下,图 8 和图 9 大部分是灰色的。这意味着关于下一个速度限制的信息只是稍微包含在代理的决定中。因此,该功能对于代理来说似乎不太重要。
  • 在第七张图中可以看到灰色、蓝色和略带红色的混合影响。在这个图表中,显示了到下一个速度限制的距离。如果新的速度限制低于当前速度限制,该功能会对车辆产生减速效果。这可以在大约 300 米距离的蓝色值范围内看到。动作的减少很大程度上是由于这个特点。

结论

这项工作的目标是开发一种方法来解释一个训练有素的强化学习代理人如何在特定的情况下选择它的行动。为此,计算了不同输入特征的 SHAP 值,并以新颖的 RL-SHAP 图表示法显示了每个特征对所选动作的影响。利用 DDPG·DRL 算法求解的 LongiControl 环境对提出的可解释 RL 方法进行了测试。

结果表明,RL-SHAP 表示阐明了哪些状态特征对动作有积极的、消极的或可忽略的影响。我们对测试轨迹上的代理行为的分析表明,给定一些领域知识,不同状态特征的贡献可以被逻辑地解释。因此,我们可以得出结论,SHAP 的使用及其在 RL 中的整合有助于解释代理人的决策过程。

作为未来的工作,我们希望研究能够解释高维输入空间中 DRL 代理决策过程的方法。

你可以在这里看到Python 代码。享受使用它的乐趣=)

参考

[1] Lundberg,s .等人(2017 年)。解释模型预测的统一方法。神经信息处理系统进展 30,4765-4774 页。柯兰联合公司。

[2]多门,j .等人(2021 年)。纵向车辆控制的强化学习环境。《第 13 届代理和人工智能国际会议论文集》,第 1030-1037 页。INSTICC。

[3] R .萨顿和 a .巴尔托,强化学习简介 (1988),麻省理工学院出版社

[4] T. P. Lillicrap 等,深度强化学习的连续控制 (2015),CoRR

[5]李普顿,Z. C. (2016)。模型可解释性的神话。http://arxiv.org/abs/1606.03490.

[6]沙普利,L. (1953 年)。n 人游戏的价值。对博弈论的贡献 2,28:307–317。

使用 Eli5 调试模型并解释预测

原文:https://towardsdatascience.com/debug-models-and-explain-predictions-using-eli5-9f856ae74d16?source=collection_archive---------34-----------------------

一种简单而有创意的 ML 调试方法

作者图片

使用机器学习模型的一个重要步骤是调试。例如,当我们处理文本时,我们必须检查我们的特征中是否有任何影响预测的噪声,如不需要的符号或数字。我们必须知道什么是预测的原因,并以某种方式解释模型的输出。过去,我们谈论过功能重要性,它也可以帮助我们调试机器学习模型,但现在有一种更简单、更实用的方法来做到这一点。

Eli5 是一个可以帮助我们调试 ML 模型并以创造性的方式解释其输出的库。我们将向您展示一些使用它解决简单分类问题、文本分类问题和使用 Keras 解决图像分类问题的示例。

装置

pip install eli5

Eli5 解释虹膜预测

对于这个简单的模型,我们将使用虹膜数据集来预测虹膜的类型(Setosa、Versicolour 和 Virginica)。

from sklearn import datasets
from sklearn.linear_model import LogisticRegression
import pandas as pd

import eli5

iris = datasets.load_iris()
features=pd.DataFrame(iris['data'])
target=iris['target']
model=LogisticRegression(max_iter=1000)
model.fit(features,target)

现在我们有了一个训练好的模型,我们可以使用 Eli5 来获得特征重要性,并通过向我们显示什么特征负责模型的输出来解释预测。

首先,让我们得到每个类的特性重要性。换句话说,模型的权重。

eli5.explain_weights(model)

使用机器学习模型的一个重要步骤是调试。例如,当我们处理文本时,我们必须检查我们的特征中是否有任何影响预测的噪声,如不需要的符号或数字。我们必须知道什么是预测的原因,并以某种方式解释模型的输出。在过去,我们谈到了功能重要性,它也可以帮助我们调试机器学习模型,但现在有一种更简单、更实用的方法来做到这一点。

Eli5 是一个库,可以帮助我们调试 ML 模型,并以创造性的方式解释它们的输出。我们将向您展示一些使用它解决简单分类问题、文本分类问题和使用 Keras 解决图像分类问题的示例。

装置

pip install eli5

Eli5 解释虹膜预测

对于这个简单的模型,我们将使用虹膜数据集来预测虹膜的类型(Setosa、Versicolour 和 Virginica)。

from sklearn import datasets
from sklearn.linear_model import LogisticRegression
import pandas as pd

import eli5

iris = datasets.load_iris()
features=pd.DataFrame(iris['data'])
target=iris['target']
model=LogisticRegression(max_iter=1000)
model.fit(features,target)

现在我们有了一个训练好的模型,我们可以使用 Eli5 来获得特征重要性,并通过向我们显示什么特征负责模型的输出来解释预测。

首先,让我们得到每个类的特性重要性。换句话说,模型的权重。

eli5.explain_weights(model)

我们可以通过输入模型和一个测试输入来解释输出。

eli5.explain_prediction(model, features.head(1))

在这个预测中,0 类的概率最高。此外,我们可以看到每个特征和偏差的贡献。

Eli5 解释文本分类

我们将使用一些正面和负面的推文样本,我们将训练一个逻辑回归分类器来预测一条推文是正面还是负面。

import numpy as np
import nltk   # Python library for NLP
from nltk.corpus import twitter_samples    # sample Twitter dataset from NLTK
from collections import Counter
import eli5

nltk.download('twitter_samples')

# select the set of positive and negative tweets
all_positive_tweets = twitter_samples.strings('positive_tweets.json')
all_negative_tweets = twitter_samples.strings('negative_tweets.json')

pos=pd.DataFrame({"tweet":all_positive_tweets,'positive':[1]*len(all_positive_tweets)})
neg=pd.DataFrame({"tweet":all_negative_tweets,'positive':[0]*len(all_negative_tweets)})

data=pd.concat([pos,neg])

from sklearn.feature_extraction.text import TfidfVectorizer

# use tfidf by removing tokens that don't appear in at least 5 documents
vect = TfidfVectorizer(min_df=5,ngram_range=(1, 3), stop_words='english')

# Fit and transform
X = vect.fit_transform(data.tweet)

from sklearn.linear_model import LogisticRegression

model=LogisticRegression()

model.fit(X,data['positive'])

首先让我们得到重量。在这种情况下,我们还需要设置我们使用的矢量器。

eli5.show_weights(model, vec=vect)

接下来是有趣的部分。让我们得到一个输入句子中每个单词的贡献。

test="I'm glad this is not a sad tweet"

eli5.explain_prediction(model, test, vec=vect)

很有用,对吧?通过在句子中突出每个特征,它给了我们每个特征的贡献。

Eli5 解释 Keras 图像模型

Eli5 非常强大,可以与 Keras 图像分类模型一起工作。我们将使用一个预先训练的模型来获取下面的图片标签,这是我的桌子。

from keras.applications.xception import Xception
from keras.preprocessing import image
from keras.applications.xception import preprocess_input, decode_predictions
import numpy as np
import tensorflow as tf

tf.compat.v1.disable_eager_execution()
import PIL
from PIL import Image
import requests
from io import BytesIO

# load the model
model = Xception(weights='imagenet', include_top=True)

# chose the URL image that you want
URL = "[https://instagram.fath3-3.fna.fbcdn.net/v/t51.2885-15/e35/p1080x1080/120296207_346512619886025_2547830156221124067_n.jpg?_nc_ht=instagram.fath3-3.fna.fbcdn.net&amp;_nc_cat=109&amp;_nc_ohc=eivBrVMAy4oAX8SvZlu&amp;edm=AGenrX8BAAAA&amp;ccb=7-4&amp;oh=9408a18468253ee1cf96dd93e98f132b&amp;oe=60F341EE&amp;_nc_sid=5eceaa](https://instagram.fath3-3.fna.fbcdn.net/v/t51.2885-15/e35/p1080x1080/120296207_346512619886025_2547830156221124067_n.jpg?_nc_ht=instagram.fath3-3.fna.fbcdn.net&amp;_nc_cat=109&amp;_nc_ohc=eivBrVMAy4oAX8SvZlu&amp;edm=AGenrX8BAAAA&amp;ccb=7-4&amp;oh=9408a18468253ee1cf96dd93e98f132b&amp;oe=60F341EE&amp;_nc_sid=5eceaa)"
# get the image
response = requests.get(URL)
img = Image.open(BytesIO(response.content))
# resize the image according to each model (see documentation of each model)
img = img.resize((299,299))

# convert to numpy array
x = image.img_to_array(img)
x = np.expand_dims(x, axis=0)
x = preprocess_input(x)

现在我们有了处理后的图像(x)和 Keras 模型,让我们检查模型预测的前 20 个标签。

features = model.predict(x)

# return the top 20 detected objects
label = decode_predictions(features, top=20)
label[[('n03179701', 'desk', 0.296059),
  ('n03337140', 'file', 0.12352474),
  ('n04590129', 'window_shade', 0.078198865),
  ('n03180011', 'desktop_computer', 0.06828544),
  ('n04239074', 'sliding_door', 0.02761029),
  ('n03782006', 'monitor', 0.022889987),
  ('n02791124', 'barber_chair', 0.018023033),
  ('n02791270', 'barbershop', 0.013427197),
  ('n04344873', 'studio_couch', 0.011167441),
  ('n03201208', 'dining_table', 0.009128182)]]

然后,我们可以检查图像的哪个部分负责每个标签。我们还需要标签的类 id,可以通过以下方式获得。

np.argsort(features)[0, ::-1][:10]array([526, 553, 905, 527, 799, 664, 423, 424, 831, 532])

让我们检查一下 id 为 526 的标签台。

eli5.show_prediction(model, x, targets=[905])

如您所见,标签书桌图像最重要的部分是实际书桌的位置。

这次我们来查一个理发店这样奇怪的标签。

eli5.show_prediction(model, x, targets=[424])

啊哈!现在我们知道我的办公椅就像理发椅。这就是模型预测理发店标签的原因。

总结一下

Eli5 是一个非常有用的库,可以帮助我们调试分类器并解释它们的预测。它可以处理大多数 python ML 库,也可以处理更复杂的模型,比如 Keras,或者使用文本和矢量器。

最初发表于https://predictivehacks.com。

像专家一样调试 Python 脚本

原文:https://towardsdatascience.com/debug-python-scripts-like-a-pro-78df2f3a9b05?source=collection_archive---------7-----------------------

调试 Python 代码的好方法、好方法和聪明方法。

调试 Python 脚本的工具和技巧——图片来自 PexelsAnete Lusina

我花了一些时间来领会调试的思想。

我相信这是大多数代码新手的通病。对我来说,作为一个自学成才的 Python 程序员,找到问题并以最快的方式修复它们是一项挑战。

但是这些年来,我学会了几种技术来发现脚本中的错误。有些改变了,有些我停止了。在这篇文章中,我将带你了解我认为调试 Python 代码的坏的、好的和聪明的方法。

让我们从坏的开始。

打印报表

也许“打印”是最常用的 Python 函数。

自然,任何想知道代码中发生了什么的人都会使用 print 语句。因为这是最简单也是最普遍的选择。它似乎也适用于较小的脚本。

如果您打算测试您的代码是否到达某个点,或者检查某个特定点的变量值,请继续使用它。如果只是一次。

print 语句用于调试 Python 代码。—作者图片

但是随着代码变得越来越大,你就有麻烦了。打印声明将会出现在整个项目中。您很快就会忘记代码中哪个打印行对应哪个打印语句。

多个打印语句打乱了输出——按作者排列的图像

如果您的项目并行或异步执行代码,情况会变得更加复杂。现在使用并行执行也并不罕见。

这个问题的直接解决方案是在每个 print 语句中使用描述。

在调试中使用描述性打印语句—按作者排列的图像

但是这会吸走开发者的灵魂。有更好的方法。这是我们在列表中的以下技术。

</5-python-gui-frameworks-to-create-desktop-web-and-even-mobile-apps-c25f1bcfb561>

冰淇淋

打印报表是一个繁琐、耗时的过程。冰淇淋让调试变得甜蜜。

Icecream 是一个 Python 包,可以让你检查脚本中不同点的变量。简而言之,它打印变量值、执行的函数,以及某些情况下的行号和文件名。

下面介绍如何使用冰激凌调试 Python 代码。

  1. 使用 pip 安装冰淇淋。
pip install icecream

2.将冰淇淋导入您的脚本

from icecream import ic

3.用 ic 包装您的函数调用和语句

冰激凌用于调试 Python 脚本。—作者图像

冰激凌通过自动将上下文添加到开发者创建的每一个日志中,让开发者的生活变得简单。这是调试 Python 代码的好方法。

但这仍然是额外的工作。

像 PyCharm 和 VSCode 这样的现代 IDE 允许您将代码停在某一行,并在该行检查所有局部和全局变量。

这是调试的聪明方法。

如何在现代集成开发环境中调试 Python 代码

实时调试是在运行时使用代码的一种方式。

我们中的一些人开始在记事本应用程序中编码。后来我们换成了记事本++ T5。然后是革命性的崇高文本Atom 编辑。他们是那个时代的伟大工具。

我们中的一些人从 PyCharm 开始。我是爱上这个优秀的 IDE 的人之一。然而,我转向了 VSCode,因为它是免费的,它的社区曾经(现在仍然)飞速发展。

不出我所料,用 VSCode 调试对初学者来说也是超级容易的。这就是这篇文章的其余部分。让我们把这一部分分成三个部分:用断点调试、流行框架的配置和调试数据帧。

https://thuwarakesh.medium.com/how-to-create-progressive-web-apps-pwa-in-python-86ab3fb0d7cf

在 VSCode 中使用断点调试 Python 脚本。

您可以通过三个步骤启动调试器。方法如下:

在 VSCode 中调试 Python 脚本—作者映像

  1. 单击边栏上的调试器。是这个上面有臭虫的播放按钮。
  2. 在代码中创建断点。您可以通过单击行号前的来完成。您创建的每个断点都会出现一个红色指示器。
  3. 现在,通过单击“运行并调试”按钮并在下拉列表中选择“Python 文件”来启动调试器。

当您这样做时,VSCode 将启动一个线程来运行您的脚本,并在您有第一个断点的地方停止。屏幕将如下所示:

在 VSCode 的断点处进行实时调试。—图片由作者提供。

当它在您创建的断点处停止时,您现在可以看到该行被突出显示,侧栏发生了变化,并且一个新的工具栏出现在右上角(此位置在您的窗口中可能有所不同)。

工具栏是调试器的控制器。“播放”按钮将忽略当前断点,并移到下一个断点。“停止”按钮将停止调试器,而“刷新”按钮将重新启动调试器。

我发现介入按钮非常有用。它是调试器工具栏上的向下箭头键。请看看下面的录音,以了解它是如何工作的,它是多么有用。

在 VSCode 调试器中逐行单步执行—图片由作者提供

我的第一个断点在第 14 行。这一行调用了一个名为“sum_odd_numbers”的函数当我点击 step in 键时,解释器移动到下一行,但停在那里。它在我调用的函数中(第 4 行。)

注意侧边栏中的变量部分。因为我们现在在函数中,所以范围改变了。在“本地”区域,我们看到 n 的值是 100。v 的值是可用的,因为解释器还没有执行第 4 行。

但是当你不断点击进入键时。你看,v 的值也在变化。当我们进入循环时,你也可以看到“I”的值。

请注意,只有当“I”的值为奇数时,我们才会到达第 8 行。当我们执行第 8 行时,“v”的值增加了“I”的值。

太好了,我们可以在脚本运行的时候一行一行地讲述所有的事情。这就是为什么实时调试是发现和修复代码问题的更好的方法。

配置 VSCode 以调试流行的 Python 框架。

VSCode 支持流行的框架,如 Django、Flask、FastAPI 和 Pyramid out of the box。在大多数情况下,您不必为这些框架配置任何特殊的东西。启动调试器时,您只需在下拉列表中选择框架。

如果这是您第一次使用 django 项目,您可以使用pip install django安装 django,并使用命令Django startproject <project_name>创建一个 Django 项目

但是在某些情况下,您必须覆盖默认值。例如,如果另一个进程阻塞了 8000 端口,Django 需要另一个进程来启动。您可以使用 launch.json 文件向调试器提供附加信息。

配置 VSCode 以调试 Django 应用程序。—图片由作者提供。

转到调试器窗口,选择“创建一个 launch.json 文件”选项。在下拉列表中,选择您正在使用的框架。我选择了姜戈作为这个例子。

您将看到一个新的 JSON 文件打开,带有一些熟悉的选项。

覆盖 VSCode 中的调试配置—按作者排列的图像

上述文件运行${ workspace folder }中的“manage.py”文件(这是您在 VSCode 中打开的项目的根目录)。此外,它接受命令行参数“runserver”。

这意味着当调试器启动时,它将要执行python manage.py runserver

我通过扩展“args”列表添加了另一个参数。在第 11 行,我将 Django dev 服务器的端口配置为 5000,而不是默认的 8000。这个修改将让调试器运行python manage.py runserver 5000

转到一个新行,按住 ctrl(或 command)键,看看还有哪些其他选项。如上图所示,会弹出一个选项列表。

让我们看看调试器的运行情况。

/urls.py 的内容替换为以下内容。

非常基本的 Django URL 配置,说明如何调试 web 请求——作者的代码片段。

并使用以下内容创建一个名为 views.py 的文件。我们运行着与 web 服务相同的奇数计数器。

非常基本的 Django 视图,说明如何调试 web 请求——作者的代码片段。

点击侧边栏中的 play 按钮启动调试器。现在,在你的网络浏览器中,如果你去http://127 . 0 . 0 . 1:5000/sum _ odd _ numbers/10,浏览器会显示结果 25。尝试在 URL 中使用不同的数字而不是 10 来查看 web 服务器是如何工作的。

浏览器上示例 web 响应的输出—图片由作者提供。

现在,让我们在第 7 行放置一个断点,并再次访问浏览器上的 URL。这一次,浏览器一直在等待响应。但是 VSCode 在我们的断点处停止处理请求。

检查 VSCode 中的 Django 请求对象。—作者图片

看看你在变量面板里得到了什么。您可以访问整个请求对象,包括有关路径、请求类型的信息和浏览器 cookie 信息。

在实时调试模式下调试 web 服务器毫不费力。我们将在下一部分讨论允许我调试数据帧的最新特性之一。

用 VSCode 调试 pandas 数据帧

VSCode 已经在数据科学中非常有用,内置了 Jupyter 笔记本。

然而,如果一个分析项目在一个脚本上,那么调试它是很困难的。在我的日常工作中,一个非常常见的情况是处理 web 请求中的数据集。

列表、字典、甚至对象都可以相对直接地显示在变量部分。但是熊猫数据框是一个需要表格格式的复杂对象。只有这样,开发人员才能从中发现问题。

VSCode 以最好的方式解决了这个问题。您只需右键单击变量部分中的数据框对象,然后选择“在数据查看器中查看值”

使用 VSCode 的数据查看器调试 pandas 数据框。—作者图片

在上面的截图中,我在第 5 行添加了一个断点。此时,解释器已经读取了 CSV,数据帧在存储器中。当我们在 Dat 查看器中打开它时,我们会得到以下内容。

VSCode 的数据查看器正在运行—图片由作者提供

这是我们的数据框的一个支持正则表达式的可过滤表格视图。当你不在 Jupyter 笔记本上时,这个特性是调试项目的一个方便的技术。在大多数生产系统中查找和修复 bug 时都是如此。

如果您在右键菜单上没有看到数据查看器选项,您必须在 VSCode 中安装或更新 Python 扩展。只有最近的版本才有这个功能。

最后的想法

不管你有多有经验,调试都是非常具有挑战性的。

对于大多数初学者来说,打印语句是最容易做到的。但是用打印语句来查找大型生产级系统中的 bug 是不实际的。只有正确的工具和技术才能帮助减轻工作。

一个可爱的救援工具是冰淇淋。Icecream 会自动包含记录语句的上下文描述。然而,每次您想要测试不同的东西时,您都必须重新运行整个脚本。

现场调试是发现和修复软件项目中问题的最聪明的方法。大多数现代 IDE 都支持实时调试。在这篇文章中,我们介绍了 VSCode 调试器是如何工作的。

我希望这个指南有助于让你的代码没有 bug。

感谢阅读,朋友!在LinkedInTwitterMedium上跟我打招呼。

还不是中等会员?请使用此链接 成为会员 因为,不需要你额外付费,我为你引荐赚取一小笔佣金。

调试 Dbt:当表名是保留关键字时

原文:https://towardsdatascience.com/debugging-dbt-when-your-table-name-is-a-reserved-keyword-faf81ab6376b?source=collection_archive---------22-----------------------

如何配置 dbt 来使用名称类似 order 和 group 的表

罗曼·博日科在 Unsplash 上拍摄的照片

欢迎来到我的最新系列-调试 dbt。作为一名分析工程师,我每天都在工作中使用 dbt 来编写健壮的数据模型。它是简化和容器化数据模型运行方式的一个很好的工具。虽然它使事情变得更容易,但我仍在不断地学习关于这个工具的一些东西。我想用我的奋斗和学习作为一种方式来教导社区中可能遇到同样问题的其他人。

今天,我将解决一个问题,我曾使用雪花表与保留关键字同名。如果您正在使用 Fivetran 接收您的数据,那么您可能会遇到类似的问题。

我们使用 Fivetran 获取的两个数据源是 Zendesk 和 Shopify。这两个源都包含名为订单的表。因为这些词在许多数据库中被认为是保留关键字,在我的例子中是雪花,那么我们将会遇到一些用 dbt 运行它们的问题。

这可能会以如下所示的错误形式出现:

SQL compilation error: syntax error line 1 at position 26 unexpected 'group'. syntax error line 1 at position 31 unexpected '<EOF>'.

如何解决这个问题:

  1. 转到 src.yml 文件,该文件包含相应源表的数据库/模式信息。
  2. 在你的表名下添加 标识符 和表名。
identifier: ORDER
# or 
identifier: GROUP

3.还要添加另一行,说明引用,并将嵌套的标识符设置为真。

quoting:
  identifier: true

将这些内容添加到这些源代码的 src.yml 文件中,改变了在 dbt 中编译 SQL 的方式。而不是将源表作为

select * from raw.zendesk.group

现在它将被读作

select * from raw.zendesk."GROUP"

更改只是在表名中添加引号,让 SQL 知道这实际上是表名,而不是保留关键字。

诸如此类的问题通常表现在许多不同类型的错误消息中。可能很难确切地知道是什么导致了某个问题,但它通常以相当简单的方式结束。请务必关注我的调试 Dbt 系列的其余部分。接下来是增量模型!

调试基于深度模型的强化学习系统

原文:https://towardsdatascience.com/debugging-deep-model-based-reinforcement-learning-systems-66b476cb565e?source=collection_archive---------39-----------------------

从一个年轻领域的博士学到的经验。

我看到了一个例子关于无模型 RL 的调试课程,觉得有必要为 MBRL 重复一遍。最终,MBRL 要年轻得多,也不那么普遍,所以如果我想让它继续发展,我需要在你们所有人身上投入时间。

作为例证,考虑这两个 SOTA 代码库:

  • TD3 :双延迟深度确定性政策梯度。阅读代码:😀。
  • PETS :轨迹采样的概率集成。阅读代码:🤪。

单从标题来看,听起来它们在复杂性上可能是一样的,但是对于无模型算法,修改只需要几行代码。在 MBRL,需要建立全新的工程系统(或多或少)。PETS 代码有更多可移动的部分。本帖按以下格式设置:

  1. 基于模型的 RL 概述,
  2. 这些系统中需要修补的核心部分,
  3. 可能出现的其他考虑事项(例如,当使用机器人时),
  4. 实用提示:快速改变或运行的东西,以获得巨大的潜在改善
  5. 结论。

我们去树林里!这是我在实现基于模型的 RL 算法和应用时所学到和坚持的东西的大脑日志。

要查看实用技巧列表,请向下滚动!。

MBRL:概述

基于模型的强化学习(MBRL)是一种迭代框架,用于在部分理解的环境中解决任务。有一个代理反复尝试解决一个问题,积累状态和动作数据。有了这些数据,代理创建了一个结构化的学习工具——一个动力学模型——来推理世界。有了动力学模型,代理人通过预测未来来决定如何行动。通过这些动作,代理收集更多的数据,改进所述模型,并且有希望改进未来的动作。

模型预测控制(MPC)是 MBRL 许多(但肯定不是全部)最新进展的核心框架。MPC 可以是最优的,它是一个控制框架,用于在选择动作时使用结构化动态理解来解决优化问题。其中一个重要的组成部分是预测未来的目标,并以后退的方式做出决定。不过,在 MBRL,这种长期规划是平衡的,因为人们知道,随着预测范围的扩大,模型会呈指数级发散。我讨论的许多调试工具都是从控制的长期规划的角度出发的,并且可以被调整以更好地表达使用值函数和无模型控制的方法。

这篇文章旨在避开任何具体的数字问题,这些问题是某种深度学习中的研究问题,倾向于讨论系统中容易导致问题的权衡和奇怪部分(即使我们不知道为什么)!

来源,作者研究。

我的偏见

对于机器人技术,我当然更倾向于深度 MBRL。在未来,我看到 MBRL 和其他类型的 RL 被用于许多应用中,其中大部分将是数字的。我对 CNNs 计算机视觉/递归模型没什么经验,所以我的建议非常侧重于单步动态模型。你可以在我的研究页面上看到我的出版物和更明显的偏见。

核心修补

任何 RL 系统主要由修补者的动机决定。基于模型的方法和它们的无模型兄弟之间的核心区别是模型的增加。试图在一个迭代的、数据驱动的系统中总结一个动力学模型的所有感兴趣的属性是压倒性的,并且是需要的。我认为建模问题主要是数据问题和建模问题。这两者之间的界限很快就模糊了。

动力学模型参数化

如何组织(和收集)数据至关重要。

  • 模型类型:最近深度神经网络引起了人们的狂热(不可否认,这种炒作令人不寒而栗),但还有很多其他模型可以考虑。由于对小型图形单元的投资,神经网络模型变得更容易使用(特别是当考虑在线控制时),例如杰特森的
  • 线性模型(例如状态空间系统的最小二乘法,类似于)适用于基本系统。这不完全是最小二乘法,但这是 Levine 教授早期的一篇论文使用了一个线性动力学模型。
  • 高斯过程在你不打算在线计划,有< 8 维状态-行动空间,或者喜欢结构化不确定性估计的时候是不错的。缓慢的规划来自于需要对用于预测的训练点数的立方矩阵求逆。我认为,如果 NNs 不存在,GPs 将遥遥领先的领先候选人(皮尔科使用他们)。在这种情况下,GPs 受到数据集过滤问题的严重限制,以保持快速的预测时间。尽管如此,我还是会考虑 GPs 的离线应用。此外,像贝叶斯优化这样的工具对许多 MBRL 工作来说是有用的伴侣(它本身就是 MBRL 的变体)。
  • 循环模型听起来很棒,因为它的目标是预测长期的未来,但是……以我的经验来看,LSTMs 不太适合,因为它们也很难训练,并且往往需要比控制问题提供的更多的数据(我怀疑这种观点在未来几年可能会改变)。有两个关键的例子可以说明 LSTMs 在 MBRL 的应用,一个比另一个重要(目前)。梦想家使用 LSTM 作为潜在空间的循环模型,与莱文教授的合作者将搭配应用于类似的潜在空间。在本文中,我们试图为状态预测建立 LSTMs 基线,但我认为我们需要更多的专业知识来使它工作(如果你有这方面的技能,请联系我们!)
  • 使用增量状态参数化:预测状态变化而非真实状态往往表现更好,对控制更有用。我怀疑它是否也适用于非常不稳定的(动态地,想想特征值)系统。它被表述为:

  • 型号能力在大多数任务中还没有被推到极限。大多数论文使用规范值(2 个隐藏层,256 个节点,5 个系综模型),每当我调整它时,我看到的影响很小。我的直觉是,模型容量往往比需要的要高得多,因此大多数模型训练都在与有噪声的数据进行过度拟合。

动力学模型监督学习

当模型的核心监督学习被打破时,如在错误中不与我们的救世主亚当收敛,在基础水平上看到许多关于这一点的教程,否则:

  • 模型初始化可能很重要。由于其在控制中的核心用途,模型稍有偏差就会导致性能停滞在 0。如果可以的话,重复使用其他人的模型初始化(事实证明,人们通常使用剪辑的正态分布,这还没有在 PyTorch 中出现)。
  • 怒点:有的型号用增量训练,有的不用。在 PETS 的论文中,Half Cheetah 的结果是,它在每次试验后都使用与普通再训练略有不同的模型训练。在这种情况下,模型参数不会被重新初始化,而是优化器会从之前试验中使用的模型参数开始采取更多的梯度步骤。这导致了较慢的模型改变,但是从理论上来说这是不合理的。
  • 实用提示:状态-动作数据中的异常值会破坏正常化(最小值/最大值和单位正常值取决于分布)。例如,如果你所有的状态变化都被归一化为 0,那么模型的精确度将会非常高,但是当你展开计划时,轨迹将会大相径庭。
  • 需要状态/动作预处理(例如角度到角度的正弦和余弦):在有角度的系统中规划时,如果你期望角度环绕(例如一个一直左转的航向会从 0 到 2pi 增长到 4pi),这里的状态需要在标记之前进行处理,使等价的角度匹配。
  • 集合使得监督学习变得有些棘手。例如,我与一个重新实现 MBPO 的人进行了一次交谈,性能的差异来自于是否在训练之前选择和设置了每个集合的交叉验证指数(对所有时期都保持)或者在每个时期重新采样(工作得更好一点)。深入这个层次的监督学习问题只是表明控制器对模型有多敏感— 这些几乎不会改变模型

预测多个步骤

当通过累积小误差作为动态模型的输入来规划未来的多个步骤时,复合误差出现。复合预测通道的公式为:

  • 常见 bug :用户在传递回模型之前没有重新规范化预测状态。在这种情况下,错误会很快爆发。如果你想可视化轨迹/使用它们进行控制(在整个轨迹都很重要的情况下),预测通常发生在输入- >标准化输入- >标准化输出- >输出- >标准化输入…
  • 上面我提到了角度的状态包装器,将它们整合到预测轨迹中可以学习状态/动作包装器的问题。通常,这是模型中的尺寸不匹配(角度变成角度的正弦和余弦),但实现起来可能会很痛苦。

从建模到规划

规划通常采用有限时域模型预测控制器的一般形式:

  • 预测范围太短:如果没有足够长的范围,你甚至无法实现某些奖励功能——当这种情况发生时,所有候选行为都等同于 0 奖励(简化为随机策略)!例如,当手臂到达某个ε气泡时,在像操纵这样的任务中,由于模型视野较短,没有一个动作序列可以到达那里。
  • 预测眼界太长:最好的例子是 MBPO,好玩的例子是宠物。他们有一个阑尾(轻微地)扫过地平线
  • 规划的范围也没有得到很好的理解(DeepMind 在这个主题上发表了一整篇论文
  • 理论限制:没有信号将测量的奖励与动态模型或优化器联系起来。这就是我们所说的 目标不匹配 ,设计算法来解决这个问题可能会非常有效。
  • 酷选项:如果使用某种概率模型,你可以在预测范围的每一步绘制模型不确定性。传统上(理论上不知道为什么),当模型超出其训练集时,方差会发散到较大的值或崩溃到 0。这可以产生有趣的动态水平调整,但很难设计。

控制优化

挂钟时间是个大问题。对于未来的所有规划,MBRL 算法需要很长时间来运行。例如,在 Half Cheetah 上重现 PETS 实验需要在 GPU 上运行 3 天。和我一起工作的一名工程师实际上开始了实验,然后利用假期时间去等待它们。将会有渐进的进展来改进这一点,但也可能有人可以在这个 Jax 实现的基础上进行构建,该实现应该为一些 RL 算法提供 2-4 倍的时间改进?

  • 仔细实验:由于上述时间限制,MBRL 不是一个可以随意进行大量实验的研究地区。跟踪你正在计划的和你正在运行的。使用九头蛇来管理你的实验。
  • 奇怪的共识:我从大多数使用基于样本的计划的 MBRL 研究人员那里得到的印象是,控制器通过选择稍微不正确的行动来工作,随着时间的推移,这些行动最终会成为一个好的但不完美的计划。要明白,如果你放大任何随机种子,当前的算法可能会输出奇怪的动作序列。
  • 艺术:基于样本的 MPC 平均工作意味着你想要一个非常精确的模型,具有你所拥有的最佳轨迹(专家),而且在附近区域具有鲁棒性

调整奖励函数

MBRL 似乎与最优控制方法联系得更紧密一些,一些论文对回报的表述稍有不同(当你不使用标准基线时,有更多的空间来调整它们)!

  • 实用趋势:数据分布(覆盖率)与性能成正比。如果您有一个 MBRL 任务可以解决的环境,您可以通过获取更多的标记数据来提高相关任务的性能(考虑将目标状态从 0 度移动到 15 度),但您也可以通过在数据集中包含更多的随机转换来限制峰值性能。
  • 如果你怀疑你的奖励函数很奇怪,考虑先重新参数化,再调优。例如,一个 cartpole 任务传统上由于处于广泛的状态而获得生活奖励(每当试验没有完成时奖励是 1),但是你可以通过增加远离原点的二次成本来改变行为,使其在控制理论意义上是最优的。
  • 标量倍数奖励吸调:调姿态权重和轨迹权重并不容易。我希望等级 RL 能承担一些这方面的重量。
  • 二次成本上的平滑有界报酬。例如,取一个角度的余弦是一个很好的有界函数,它在 0 附近给出一个更高的值。它比平方的负值下降得更好。

探测

天哪,在 MBRL,探索发生在模型和规划者之间的界面上,这使得设计变得非常棘手。我在这里写了一篇关于为什么这很奇怪的短文。最终,在 MBRL 工作了 3 年几乎全职,探索是最不明确的前进道路。

迄今为止,探索似乎是偶然发生的,将更明确的探索机制集成到规划中(优先考虑动作分布)可能会以错误的模型训练分布为代价。当然,我希望被证明是错误的,或者听到事情没有我想象的那么复杂。

来源,作者研究。

其他考虑

有很多不在深度 RL 范围内的事情会影响你的系统。这是你从试图从具身代理人的角度推进强化学习中学到的。这些实际考虑可能对你的项目产生从 0%到完全破坏应用程序的影响。当人们开始尝试将 Deep RL 产品化的时候,这些将会更加主流。

系统属性

有些系统真的不应该被建模。Deep RL 对系统特征值、噪声、更新速率之类的东西讨论的不够。最后,从流行的线性估值器中吸取教训,知道当你在没有测量的情况下进一步走向未来时,模型误差的下限增长得非常快。

对超参数的敏感性

我有幸参与撰写的最近一篇论文改变了我对 MBRL 算法的潜力和对使用它们的参数的敏感性的看法。最终,核心思想是 MBRL 的最佳参数可以基于试验次数而改变(例如,随着代理获得更多数据,模型变得更准确,因此预测范围可以更长)。这是在标准深度学习和强化学习参数敏感性之上的。

一般来说,我会说,如果你在一个支持良好的实验室,请使用自动机器学习(AutoML)库,但如果你不是,请在一个竞争较少的环境中工作(例如,你有一个真正的机器人,而不是 Mujoco)。这里可以了解更多

机器人问题

我是一个(可能不可取的)特例,我第一次部署 MBRL 系统是在现实世界中。不要这样做,但是通过在真实世界中使用 MBRL,你肯定可以学到一些在模拟中应用的东西。

  • 如果你在控制中寻找一个稳定的政策,确保你和一个随机的政策相比较。在研究这篇论文为四旋翼飞行器做姿态控制的时候,我们学到了很多关于飞行的流体动力学知识。长话短说:当四旋翼飞行器接近地面时,其推进力反弹的上升气流会产生一个小枕头,机器人将在这里有效地拥有更稳定的极点(空气既可以防止它坐在地面上,又可以使 0,0 处的俯仰-滚动不稳定极点几乎被动稳定)。

  • 如果你的奖励函数很简单,纠正剥削行为是不可能的。例如,在同一篇论文中,我提出了四旋翼飞行器实现高推力是一种更稳定模式的问题(或特征)。在这种飞行模式下,它受到房间高度的限制,当微型四旋翼飞行器向地球坠落时,我抓住了它,从而挽救了进展。高风险、高乐趣的研究让我在这里起步。更深入的问题是,模型或规划者的哪一部分(本例随机抽样!)使得行为只在部分时间发生。

  • 通过计算问题排除应用。因为 MBRL 与 MPC 的系统本质,实际上把它放到机器人身上真的很难。它归结为这样的决定:你是在船上运行 MPC 还是通过无线电/电线将状态发送到另一台计算机来计算动作。非机载运行控制器使得同步、延迟和丢失(通信,而不是 NNs)更加重要。

    目前还没有很好的围绕真实世界系统来设计数据的深度 RL 库。在四旋翼飞行器项目中,我飞行了 10 次数据,用 usb 驱动器传输,传输回来,并进行了更多的实验。如果你看看那里的学习曲线,得到它是一整天的数据收集、训练和希望。因此,你可以推断,完成那篇论文显然花了很长时间。我的一个希望是,现代开源项目开始考虑如何将他们的算法大规模用于真实的机器人,或者这可能更像是一个创业问题(产品)。

  • 改变你的控制频率:如果你采样状态的频率降低,你的测量中的噪声对你标记的训练点的影响就会减少,这有助于你的模型的准确性。较低的频率也意味着在给定一定数量的步骤的情况下,对未来进行更长远的规划。但是,对于许多应用程序来说,提高控制频率可以让行为更快地纠正不良行为。

我称之为候选行动的“瀑布图”。关于预测奖励的颜色编码对于观察奖励空间相对于给定动作维度是否平滑可能是有趣的。这是四旋翼飞行器真实世界的姿态控制任务。来源,作者研究。

实用技巧

这里有一个针对这个难题各个部分的实用技巧列表。

动力学建模

  • 历史附加到模型输入(如果动态的时间常数比控制频率慢得多,动作可能需要两步才能进行。通过附加一些过去的状态和动作来增加模型的理解)。
  • 环境变量可以作为输入传递到模型中,而不是作为输出进行预测(例如,电池电压,但它们可能会误导——在这种情况下,改变电机电压的负载会使测得的电池电荷发生很大变化,这对理解动力学没有帮助)。
  • 看看你的状态空间中的排序的一步预测(这里的例子)。系统边缘的点看起来误差更大,但是它们不应该膨胀到无穷大。
  • 可视化多个层位的许多预测种子和中值预测误差。预测中的坏异常值可能会对您的性能造成不相称的损害。

控制和规划

  • 将所有的候选轨迹在几个维度上可视化——它们应该看起来非常多样化。

  • 以不同的重新规划频率,可视化规划轨迹与地面实况。这将是一系列缓慢偏离的计划,它可以定期显示计划偏离的轨迹中最具挑战性的部分。

    观察预测轨迹(选择动作后)与最终轨迹的匹配程度是非常好的,并且有助于考虑您的优化器是否做了任何有用的事情。这里较低的重新计划频率实际上只是为了降低你的可视化的混乱程度。

  • real dynamics 上检查你的经纪人的表现艾伯特·托马斯让我想起了这个。这暂时解决了动力学建模问题,但是很难实现。

  • 不要主动设计一个探索机制,而是通过观察你的数据集来想象它是如何工作的。

  • 写得不够的东西:成本=-奖励。您可以将任何成本函数更改为奖励。

可视化 MBRL 系统

重要的是要想象 MBRL 正在做的一些核心轴:规划,数据积累,模拟,等等。以下是我做的一些形象化图片,帮助我了解正在发生的事情。

动力学模型允许你模拟未来的许多扰动。随着我们得到更好的模型,这种梦会更有用。Ionocraft 是我的实验室里的一个新颖的机器人,我们一直在尝试学习飞行。可以说,对于这个单独的项目来说,组装有点太难了。来源,作者研究。

如上所述,不同的候选轨迹在不同的奖励函数下看起来确实不同。在这种情况下,“生活奖励”是当代理人处于目标的ε泡中时的奖励。这就像默认的弹弓奖励,但可以扩展..来源,作者研究。

基于模型的 RL 最终获得接近专家轨迹的数据,而不是覆盖整个状态空间的数据。理解该数据集在不同空间中的样子以及它与最优控制的假设相比如何是非常重要的。来源,作者研究。

代码示例

请尽快回来查看我正在从事的一个大型开源 MBRL 项目。除此之外,我还制作了一些重量更轻的模拟器。很多东西都是在最初的 PETS 实现上构建的,但是它在 O.G. TensorFlow 中。

  • 一个好的动力学模型可以在这里找到。为什么有用?它被设置为处理模型公式变化(例如,真实状态与增量状态预测)、标准化等。独立于模型类型。此外,任何高级机器学习项目都需要从配置文件动态制作神经网络。
  • 一个由许多库、绘图代码、环境、相关优化器和模型模拟组成的更加混乱的库,在这里是(诚实地使用,风险自负,但浏览寻找灵感可能会有用)。

结论

我对基于模型的方法的未来非常乐观。出于某种程度上的研究议程保护,我不会把我想做的所有事情的运行列表放在网上(我没有人来解决所有的问题!),但我非常乐于与新人合作,并讨论这些挑战。

最终,当你放大 MBRL 难题的任何一块时,很明显每个子机制都是相对次优的。单独推动每一件作品都需要多年的研究。

我希望这些碎片开始更好地结合在一起,我们可能会得到一种共鸣,MBRL 开启了人们希望的一切:

  1. 通过更好地理解数据进行归纳
  2. 具有精确模型的更优控制器的可解释性
  3. 由所有碎片聚集而成的表演

查看我在 MBRL 公开的所有信息的一个好方法是在我的网站上搜索。

研究进展

我的朋友 Scott Fujimoto 很好地总结了基于模型的 RL 的状态:它对人类来说非常直观(我们在头脑中计划事情!),但实际上试图实现它是相当可怕的。我希望在这方面有所进展。

在《MBRL 的轨迹》中,你应该知道一些最近的论文:

  • 皮尔科 (2011):基于梯度的政策,通过一个动态模型。
  • MPPI (2017):一种替代的模型预测控制(MPC)架构。
  • PETS (2018) & 府绸 (2019):基于样本的 MPC,编织轨迹在一起。
  • 梦想家(2020)&dream erv 2(2021):视觉 MBRL 变好了!
  • MBPO (2019):学习模型上的无模型 RL (SAC)。
  • 客观不匹配 (2020):我们开始理解为什么 MBRL 是怪异的(理论上和数值测量上)。

建议

尽可能从其他人的实现开始工作,或者从他们的代码中分支出来。我经历过并帮助过一些 MBRL 代码的开源尝试,这些困难通常是你无法预料的。当您必须同时调试模型和计划时,这些棘手的问题变得更加复杂——帮自己一个忙,从您知道有效的那一半开始。

这是一个年轻的领域:如果你认为你正在做某件事,那就试试吧。

将模型中的计划和行动可视化(无模型做不到的事情,利用它)!因为行动计划对控制来说非常重要,所以学会用什么看起来对什么看起来长对你有很大帮助。下面是两个平均精度相同的动力学模型的例子,但其中一个有利于噪声控制(摘自我的论文)。我也认为在开始制造的工具对 MBRL 来说很有吸引力。

来源,作者研究。

承认

感谢 Luis Pineda 在构建令人兴奋的东西时对调试 MBRL 进行了许多有益的讨论。在这里学到的很多东西是和罗伯特·卡兰德拉一起学的,还有一些是和丹尼尔·德鲁和奥姆里·丫蛋一起学的。感谢尤金·维尼斯基对我初稿的反馈。

如果你觉得有必要,我为这一个做了一个引用。

@ article { lambert2021debugging,
作者= {Lambert,Nathan},
title = {调试基于模型的强化学习系统},
year = {2021},
how published = { URL { http://NATO Lambert . com/writing/Debugging-mbrl } },
}

感谢阅读!如果你有问题,请在推特上联系我。

Python 中 Dockerized ML 应用程序的调试

原文:https://towardsdatascience.com/debugging-for-dockerized-ml-applications-in-python-2f7dec30573d?source=collection_archive---------19-----------------------

使用 VScode 和 debugpy 使调试变得轻而易举

在过去的几年里,Docker 在 ML 应用程序中变得无处不在。它可以让使用不同硬件的工程师轻松协作,并简化从个人笔记本电脑上的原型开发到生产中的计算集群的过渡。另一方面,它为工程师在开发和维护生产模型时带来了额外的复杂性。

在我的专业工作中,我发现调试是由于这种额外的复杂性而变得更加困难的事情之一。在这篇文章中,我将概述我当前使用 VSCode 和 debugpy 的设置,当应用于模型训练应用程序时,它们极大地简化了这个过程。

我们为什么需要这个?

调试代码时,我们希望能够尽可能准确地检查运行时的环境。任何偏离都会导致修复程序在运行时环境中不起作用。

在掌握 Docker 的同时,我的调试过程通常需要围绕我希望在本地开发环境中检查的 Python 脚本重新创建支架,然后直接调试该脚本。在包含 bash 脚本、多个入口点和使用环境变量的模型训练应用程序中,这会迅速增加大量开发开销。随着这种复杂性的增加,出现错误的可能性也增加了,从而使整个过程变得缓慢和令人沮丧。

那么我们如何避免这种情况呢?我们需要一个可以与 Docker 交互的调试系统,让我们的代码按照设计的那样运行!

解决方案

最终对我来说最有效的是一个调试器,它可以连接到运行模型训练应用程序的 Docker 容器,并直接检查给定 Python 脚本的环境。

这就是 debugpy 的用武之地!

这个包以前被称为 ptvsd,是由微软开发的,专门用于 Python 的 VSCode。它实现了您期望的所有常见调试工具,并允许连接到远程环境,比如 Docker 容器,甚至通过 SSH 连接到远程机器。

顺便说一下,debugpy 实现了调试适配器协议(DAP),这是开发工具与调试器通信的标准化方式。

在 Docker 容器中使用 debugpy 非常简单,需要 3 个不同的步骤。在演示整个过程之前,我将依次深入其中的每一个。

  1. 在 Python 中配置 debugpy
  2. 配置与 Docker 容器的连接
  3. 设置断点

在 Python 中配置 debugpy

在您要调试的脚本中,下面的代码片段应该添加在任何其他代码之前。

import debugpy

debugpy.listen(("0.0.0.0", 5678))
print("Waiting for client to attach...")
debugpy.wait_for_client()

这将设置 debugpy 在端口 5678 上监听客户端连接,并且还将暂停执行,直到客户端通过该端口连接。

配置与 Docker 容器的连接

现在我们已经配置了 Python 脚本,我们需要确保当它在 Docker 容器中运行时,VSCode 调试器客户端可以连接到 debugpy。

首先,当您运行 Docker 容器时,debugpy 监听的端口必须映射到一个本地端口

docker run \ 
   -p 5678:5678 \  # map container port to local port
   temp-container

其次,我们需要创建一个launch.json文件来配置本地 VSCode 调试客户端将如何运行。这个最小的例子告诉调试器连接到端口5678,当我们运行容器时,这个端口将被映射到相同编号的 Docker 端口。

{
   "version":"0.2.0",
   "configurations":[
      {
         "name":"Python: Docker Attach",
         "type":"python",
         "request":"attach",
         "connect":{
            "host":"localhost",
            "port":5678
         },
         "pathMappings":[
            {
               "localRoot":"${workspaceFolder}",
               "remoteRoot":"."
            }
         ]
      }
   ]
}

设置断点

当我第一次尝试这样做时,我感到很惊讶,当你在 Python 脚本的本地版本上通过 VSCode UI 设置断点时,这将对应于在你的 Docker 容器内运行的复制脚本!来自 VSCode 的纯魔法。

此外,还可以使用debugpy.breakpoint()通过 debugpy API 显式设置断点。这样做的另一个好处是,如果您排除了步骤(1)中提到的 debugpy 配置,这些调用将被忽略,这提供了一种临时删除调试的快速方法。

正在调试

你应该可以走了!下面的 GIF 展示了一个标准的调试方法

  • 在用户界面中添加断点
  • 重新构建并运行 Docker 容器
  • 连接调试器

下面是这个例子的完整代码。调试愉快!😃

https://github.com/sam-watts/vscode-docker-debugging

链接

可视化调试 Python 代码

原文:https://towardsdatascience.com/debugging-python-code-visually-912790f60b37?source=collection_archive---------26-----------------------

使用 Birdseye 调试 Python 代码

照片由西格蒙德Unsplash 上拍摄

您是使用 print()命令调试 python 代码或函数的程序员之一吗?如果答案是肯定的,那么你并不孤单,大多数使用 Jupyter notebook 的 python 程序员都是这样调试他们的代码的。这没有什么错,但是这不是我们调试代码的一种便捷方式。

Birdseye 是一个开源的 python 库,用于调试 python 代码。它在运行时记录特定函数中表达式的值,一旦函数被执行,您可以可视化这些值,并在出现问题时进行调试。

在本文中,我们将看到 Birdseye 如何用于 python 代码调试。

让我们开始吧…

安装所需的库

像任何其他 python 库一样,我们将使用 pip 安装来安装 Birdseye。下面给出的命令将执行安装。

pip install --user birdseye

导入所需的库

接下来,我们将导入将在本文中使用的所有必需的库。

from birdseye import eye

为了看到 Birdseye 的运行,我们需要一些带函数的 python 代码,以便我们可以调试它。你可以使用任何包含函数的代码。我在用我自己的代码创建一个使用不同功能的神经网络。要激活鸟眼,你只需要在我们想要监控的每个人前面加上“@eye”就可以了。

from keras.datasets import mnist
import matplotlib.pyplot as plt
import numpy as np
import keras
from keras.layers import Dense, Dropout 
from keras.models import Sequential 
from birdseye import eye
image_size = 28*28
num_classes = 10class DigitRecoginzer:
    [@eye](http://twitter.com/eye)
    def __init__(self):
        # Setup train and test splits
        (self.x_train, self.y_train), (self.x_test, self.y_test) = mnist.load_data()
        self.x_train, self.x_test = self.x_train/255, self.x_test/255
        #print("Training label shape: ", self.y_train.shape) 
        #print("Training Data Shape", self.x_train.shape)
    [@eye](http://twitter.com/eye)
    def get_data(self):
        return self.x_train, self.y_train, self.x_test, self.y_test

    # Convert to "one-hot" vectors using the to_categorical function
    [@eye](http://twitter.com/eye)
    def one_hot_encoding(self):
        #print("Data before one-hot encoding", self.y_train[:5])
        num_classes = 10
        self.y_train = keras.utils.to_categorical(self.y_train, num_classes)
        self.y_test = keras.utils.to_categorical(self.y_test, num_classes)
        #print("Data after one-hot encoding\n", self.y_train[:5])# Flatten the images
    [@eye](http://twitter.com/eye)
    def flatten_image(self):
        image_vector_size = 28*28
        self.x_train = self.x_train.reshape(self.x_train.shape[0], image_vector_size)
        self.x_test = self.x_test.reshape(self.x_test.shape[0], image_vector_size)

    [@eye](http://twitter.com/eye)
    def GenericModel (self, image_size, num_classes, hyperP, dp=False):
        try:
            self.model = Sequential()
            numHiddenLayers = hyperP["NumHiddenLayers"]
            act = hyperP[1][1]
            init = hyperP[1][2]
            self.model.add(Dense(hyperP[1][0], activation=hyperP[1][1], input_shape=(image_size,),kernel_initializer= init))#kernel_regularizer=l22
            for i in range(2, numHiddenLayers+1):
                l = hyperP[i]
                init = l[2]
                self.model.add(Dense(l[0], activation=l[1], kernel_initializer=init))   
                if(dp):
                    self.model.add(Dropout(hyperP['dp_rate'][i-2]))
            self.model.add(Dense(num_classes, activation='softmax'))opt =hyperP["opt"](hyperP["lr"])
            self.model.compile(optimizer="adam", loss='categorical_crossentropy', metrics=['accuracy'])
            self.model.summary()
        except Exception as ke:
            print ("Key is not defined", ke)
            self.model = None
    [@eye](http://twitter.com/eye)
    def train_model(self, epoch, batch_size):
        self.history = self.model.fit(self.x_train, self.y_train, batch_size=batch_size, epochs=epoch, verbose=2, validation_split=0.1)
        self.model.save('model.h5')
    [@eye](http://twitter.com/eye)    
    def get_accuracy(self):
        loss, accuracy  = self.model.evaluate(self.x_test, self.y_test, verbose=False)
        loss_train, accuracy_train = self.model.evaluate(self.x_train, self.y_train, verbose=False)
        print(f'Train loss: {loss_train:.3}', f'Train accuracy: {accuracy_train:.3}')
        print(f'Test loss: {loss:.3}',f'Test accuracy: {accuracy:.3}')
        return accuracy_train
    [@eye](http://twitter.com/eye)            
    def predict(self, img):
        result = np.around(self.model.predict(img)[0])
        max1 = max(result)
        return np.where(result == max1)[0][0] lr =[0.1, 0.01, 1, 10, 0.5, 0.05]
objs = []
for i in range(len(lr)):
    HyperParam1 = {
        #Training Level Hyper Params
        "epochs": 300,
        "lr": lr[i],
        "batchSize": 2048,
        "dp_rate": [0.2, 0.1, 0.05],
        "opt": keras.optimizers.Adam,
        #Network Level HyperParam
        "NumHiddenLayers": 2,
        1:[64, "sigmoid", keras.initializers.glorot_normal(seed=20)],
        2:[32, "relu", keras.initializers.glorot_normal(seed=20)],
    }
    objs.append(DigitRecoginzer())
    objs[i].one_hot_encoding()
    objs[i].flatten_image()
    objs[i].GenericModel(image_size, num_classes, HyperParam1, dp=False)

现在我们将使用下面给出的命令运行 Birdseye Flask 应用程序。

python -m birdseye

来源:作者

这是 Birdseye 应用程序的主页,在这里您可以看到所有需要监控的函数名。我们可以通过点击这些函数来仔细查看它们的内部。

来源:作者

在这里,您可以可视化开始时间、函数的参数以及结果(如果有的话)。这就是如何使用 Birdseye 进行代码调试。继续尝试不同的功能,让我知道你在回复部分的意见。

本文是与皮尤什·英加尔合作完成的。

在你走之前

感谢 的阅读!如果你想与我取得联系,请随时通过 hmix13@gmail.com 联系我或我的 LinkedIn 个人资料 。可以查看我的Github*简介针对不同的数据科学项目和包教程。还有,随意探索* 我的简介 ,阅读我写过的与数据科学相关的不同文章。

神经网络的调试提示

原文:https://towardsdatascience.com/debugging-tips-for-neural-networks-f7dc699d6845?source=collection_archive---------38-----------------------

调试神经网络可能会非常令人沮丧。这里有一些可能有帮助的一般提示。

照片由西格蒙德Unsplash 拍摄

通常,基于神经网络的项目中的瓶颈不是网络实现。相反,在您编写了所有代码并尝试了一大堆超参数配置之后,有时网络就是不工作。我以前去过那里。在与挑剔的网络打交道一段时间后,我收集了一些帮助我调试它们的方法。这些方法不是任何形式的保证——即使你做了我建议的所有事情,你的网络仍有可能中断。然而,我希望,从长远来看,这些提示会减少你调试神经网络所花的时间。

检查梯度问题:

有时梯度是问题的原因。有几种有用的与渐变相关的调试方法:

  • 数值计算每个重量的梯度。这通常被称为“梯度检查”,有助于确保梯度计算正确。一种方法是使用有限差分。更多细节可以在这里找到。
  • 对于每个重量,将梯度的大小与重量的大小进行比较。我们想确保数量的比例是合理的。如果梯度幅度比权重幅度小得多,网络将永远需要训练。如果梯度幅度大约等于或大于权重幅度,则网络将非常不稳定,并且可能根本不训练。
  • 检查爆炸或消失的渐变。如果您看到梯度变为 0 或 nan/infinity,您可以确定网络不会正确训练。你需要首先弄清楚为什么爆炸/消失梯度会发生,例如,可能是因为步长太大。一旦你弄清楚为什么梯度爆炸/消失,有各种解决方案来解决这个问题,例如,添加剩余连接以更好地传播梯度或简单地使用较小的网络。
  • 激活功能也可导致爆炸/消失梯度。例如,如果 sigmoid 激活函数的输入幅度过大,梯度将非常接近 0。随着时间的推移,检查激活函数的输入,并确保这些输入不会导致梯度始终为 0 或较大的幅度。

经常检查训练进度:

经常检查你网络的训练进度会节省你的时间。例如,假设您正在训练一个网络来玩贪吃蛇游戏。不是一次训练网络几天,然后检查网络是否学到了什么,而是每十分钟用当前学到的权重运行一次游戏。几个小时后,如果你注意到代理每次都在做同样的事情,却没有得到任何回报,你就知道可能出了问题,并为自己节省了几天浪费的培训时间。

不要依赖定量输出:

如果只查看定量输出,您可能会错过有用的调试信息。例如,当训练网络进行语音翻译时,请确保您阅读了翻译的语音,以确保它实际上是有意义的。不要只看评价函数是不是在递减。作为另一个例子,当训练用于图像识别的网络时,确保您手动检查网络给出的标签。你不应该依赖定量产出的原因有两个。首先,你的评估函数可能有错误。如果你只看错误的评估函数输出的数字,可能要过几周你才会意识到有问题。第二,你可能会在你的神经网络输出中发现无法定量显示的错误模式。例如,你可能意识到一个特定的单词总是被误译,或者在左上角的象限中图像识别网络总是错误的。这些观察反过来可以帮助您在代码的数据处理部分找到 bug,否则这些 bug 会被忽略。

试一个小数据集:

另一种确定您的代码是否有 bug 或者数据是否难以训练的方法是首先适应一个较小的数据集。例如,不要在数据集中有 100,000 个训练示例,而是将数据集调整为只有 100 个甚至 1 个训练示例。在这些情况下,您期望神经网络能够非常好地拟合数据,尤其是在一个训练示例的情况下。如果您的网络仍然有很高的测试错误,那么您几乎可以肯定您的网络代码有问题。

尝试一个不太复杂的网络:

如果您的全尺寸网络在训练时遇到问题,请尝试层数较少的小型网络。这还有一个好处就是训练速度更快。如果小型网络在全尺寸网络失败的情况下成功,则表明全尺寸模型的网络架构过于复杂。如果简单网络和完整网络都失败了,那么您的代码中可能有一个 bug。

如果您没有使用框架,请对照框架进行检查:

如果你是从零开始编写神经网络的代码,而不是使用机器学习框架,那么你的实现可能有问题。幸运的是,您可以通过在机器学习框架中编写相同的网络架构来检查是否是这种情况。然后将打印语句放入您的实现和框架版本中,并比较输出,直到您发现打印语句中的差异开始出现。这就是你的错误所在。例如,假设您有一个十层网络,错误在第七层。当您打印网络中第一层的输出并将其与框架实现中的第一层输出进行比较时,它们将是相同的。因此,您转而比较第二层的输出。还是老样子。然后你移动到第三层,以此类推,直到你看到第七层开始出现差异。因此你可以推断第七层是问题所在。请注意,此方法仅适用于网络的第一次迭代,因为由于第一次迭代输出的差异,第二次迭代及以后的迭代将具有不同的起点。

上面的例子假设错误发生在正向学习过程中。如果错误发生在反向传播期间,可以使用相同的思想。您可以从最后一层开始,逐层打印权重的渐变,直到您看到框架渐变和实现渐变之间的差异。

消除浓缩咖啡中的微粒迁移

原文:https://towardsdatascience.com/debunking-fines-migration-in-espresso-989f486eef0e?source=collection_archive---------27-----------------------

咖啡数据科学

进一步的证据表明,微粒迁移并没有发生

意式浓缩咖啡中有一个理论,非常细小的颗粒(微粒)在一杯咖啡中迁移,可能会堵塞过滤器或进入杯中。但是,我不认为罚款会迁移,我想我也找到了原因。

咖啡渣的理想化场景,其中细颗粒在开放空间中迁移。所有图片由作者提供

在我之前用粉笔探索这个概念的实验中,我没有发现任何微粒迁移的证据。然而,我没有很好的解释为什么他们不迁移,但我没有观察到这种现象。

甚至在这个粉笔实验之前,我就有证据表明,基于断奏浓缩咖啡镜头的存在,细微的迁移不会影响味道或过滤器。断续浓缩咖啡的底部有一层小于 400 微米的颗粒,通常是照片中一半的粉末。如果罚款曾经导致一个问题,断奏镜头应该最大化的问题,但它没有。

我的理论是,在浓缩咖啡的过程中,咖啡会膨胀,所以微粒不会迁移,因为通过咖啡球的所有路径都关闭了。此外,水通过咖啡的唯一途径是通过咖啡渣的内部。

咖啡渣膨胀并阻塞微粒

为了检验这个理论,我观察了一些咖啡渣来测量水加入到冰球中的体积,这应该表明咖啡渣膨胀了多少:

  1. 从一个用过的冰球开始
  2. 加了一点水
  3. 混合它
  4. 把它放进一个 Kompresso
  5. 尽可能挤出多余的液体
  6. 等待

1.帕克,2 分。加水,3。混合,4。放入 Kompresso,5。挤出多余的液体,6。等待

两天后,这个实验被霉菌打断了。困难的部分是咖啡渣没有太多的表面积来干燥。

然而,在这段时间内,有一个从 47.5 毫升到 46 毫升的体积变化,所以 3.2%的体积变化。

第二次测试

幸运的是,我同时运行了第二个测试。我用我的摩卡壶里用过的咖啡,把这些咖啡渣放进一个杯子里,用一个小捣棒轻轻地把它们捣成一定的形状。地面是湿的,但没有湿透。

一个星期后,它们变干了,咖啡变小了。

我拍了一些照片进行测量,我还收集了一些重量样本。然后我把咖啡捣实:

只是为了检查小气泡,我在咖啡上做了一些 WDT,并重新捣实。

这没起多大作用。所以我也试着用我的手指向下压,最后,音量降低了一点点。

数据分析

我用这些图像来测量体积。我应该注意到,精确的体积可能会有误差,但是这个实验实际上是为了找到一个咖啡在潮湿时膨胀的大概数字。

重量损失与体积损失不成比例,这意味着大量的水存在于颗粒内部。这并不特别令人惊讶,但确实很好验证。

移动式过滤器释放

我注意到,每当我在拍摄后移除 portafilter 时,冰球会在几秒钟内缩小。因此,当施加压力时,冰球会膨胀,并有适量的顶部空间,它会填充篮筐。我很好奇,如果我更好的透明过滤器/过滤篮将有助于在全压力下检查冰球。

移除移动式过滤器后立即、1 秒和 10 秒

总的来说,我们看到容量增加了大约 25% (100/80,因为 80%是从原始容量的最终减少)。湿地的密度几乎是干地的两倍。

这两个结果结合在一起,让我很难相信粉末会迁移到浓缩咖啡的底部,甚至会迁移到离它们开始的地方很远的地方。这也解释了为什么我的粉笔实验没有显示出粉笔颗粒的任何垂直运动。

如果你愿意,可以在 Twitter 和 YouTube 上关注我,我会在那里发布不同机器上的浓缩咖啡视频和浓缩咖啡相关的东西。你也可以在 LinkedIn 上找到我。也可以在 Medium 或者 Patreon 上关注我。

我的进一步阅读:

浓缩咖啡系列文章

工作和学校故事集

个人故事和关注点

乐高故事启动页面

摄影飞溅页面

使用图像处理测量咖啡研磨颗粒分布

改善浓缩咖啡

断奏生活方式概述

测量咖啡磨粒分布

咖啡萃取

咖啡烘焙

咖啡豆

浓缩咖啡用纸质过滤器

浓缩咖啡篮及相关话题

意式咖啡观点

透明 Portafilter 实验

杠杆机维修

咖啡评论和想法

咖啡实验

12 月版:2021 亮点

原文:https://towardsdatascience.com/december-edition-2021-highlights-d1b04e29e3ef?source=collection_archive---------19-----------------------

月刊

TDS 编辑和编辑助理回顾了本年度最令人难忘的文章

杰西卡·坎塔克·贝利Unsplash 上拍摄

在充满不确定性、疫情带来的压力以及对环境和政治趋势日益增长的担忧的一年里,我们作者的能量和创造力是帮助我们所有 TDS 人保持脚踏实地的因素之一。为了表达我们的感激之情,纪念即将到来的年底,并庆祝我们的集体成就,我们将一些最突出的帖子分享给我们扩展社区的成员。我们希望你能像我们一样发现它们的启发性和洞察力。

不过,在我们开始之前,我们还想花点时间感谢我们的读者,感谢你们为 TDS 投入的时间和热情,以及你们持续的支持,这使得我们的工作有可能开始。为你,也为充满学习、发现和——希望——更平静的 2022 年干杯。

朱莉娅·尼库尔斯基,志愿编辑助理

几个月前,我第一次在一个小项目中使用了 GPT-2 模型。起初,我真的对它能够生成的文本感到兴奋,但后来我意识到它使用了相当多有问题的语言。所以我开始研究有毒语言生成的话题,并研究这些模型的训练方式。Jack Bandy 的这篇文章为 BookCorpus 的内容和问题提供了一个很好的概述,book corpus 是一个流行的数据集,用于预训练一些最流行的语言模型。我们提供给这些模型的数据比纯粹的性能指标更重要。

当你意识到你使用的语言模型有内在的偏见,这些偏见会转化成它们生成的语言,你不得不考虑你能做些什么。 Alberto Romero 的文章为提供了 OpenAI 开发过程的概述,以使这些模型适应社会——通过减少它们的偏见。虽然这种方法不是最终和完美的答案,但它是朝着正确方向迈出的重要一步。

[## 机器学习中的关键数据集 BookCorpus 的肮脏秘密

towardsdatascience.com](/dirty-secrets-of-bookcorpus-a-key-dataset-in-machine-learning-6ee2927e8650)

埃利奥特·冈恩,编辑

今年我偶然发现的最好的事情之一是一个名为 SLICED 的现场数据科学编码比赛。它似乎凭空出现,在夏季的每个周二晚上主宰了数据科学 twitter。正如 Jin Hyun Cheong 博士在 6 月份写道的那样,两位共同主持人 Nick Wan 和 Meg Risdal为数据爱好者创造了一个有趣而友好的空间,让他们在观看参赛者试图构建最佳模型或当晚可视化的同时,编写自己的 Kaggle 提交内容。我们得以对他们进行采访,了解这个项目是如何产生的,以及他们认为 SLICED 下一步的方向。当我说,我等不及第二季的时候,我想我代表了所有切片粉丝的心声!

[## 观看#SLICED 的三个理由:实时数据科学竞赛

towardsdatascience.com](/three-reasons-to-watch-sliced-a-real-time-data-science-competition-8d5212ccf988)

莎拉·a·梅特沃利,志愿编辑助理

现在 2021 年即将结束,我花了一些时间反思我读过的一些 TDS 文章,这些文章对我来说很突出——在我的书签列表中,有两篇文章比其他文章更能引起我的共鸣。

作为一个热爱可视化并完全理解它对数据科学和任何技术领域的重要性的人,Terence Shin的《2021 年 10 大最佳数据可视化》引起了我的注意。学习创建好的可视化并不是一项容易培养的技能。这需要大量的练习,不仅仅是创造视觉效果,还有讲故事的技巧。当我在提高我讲故事和可视化的技巧时,我经历了无数由数据科学家和可视化者所做的伟大的可视化;这样做启发了我去改进我的风格,并向我展示了可视化是如何有效的。这篇文章包含了 10 个形象化的例子,肯定会激励你把你的技能提升到一个新的水平。

第二篇让我印象深刻的文章是莎兰·库马尔·拉文德兰的《没有经验?以下是如何获得你的第一份数据科学工作。”从事数据科学职业最具挑战性的事情之一不是学习技术或软技能;相反,这是你第一份没有工作经验的工作。总的来说,找工作是一个乏味的过程,当你没有这方面的经验时就更糟了。这篇文章将为你提供一些关于如何在数据科学中找到你的第一个角色的好建议,并帮助你保持动力,不要因为这个过程有多么令人沮丧而气馁。

编辑凯特琳·金迪格

我特别喜欢那些解决对我来说重要的问题或围绕我们不常看到的独特主题的文章。当回顾过去一年 TDS 的内容时, Nina Sweeney 不仅是一位新作者,也是一位总是将自己的项目与更大的道德图景联系起来的人。她 9 月 5 日的作品“在女性所在的地方遇见她们”将城市旅行作为一种性别化的体验进行了近距离观察,有效地结合了公共交通和日常女性现实的迷人话题。Sweeney 的文章灵感来自 Caroline Criado Perez 的隐形女性:为男性设计的世界中的数据偏差,Caroline Criado Perez 在她的工作中几次提到公共交通。Sweeney 使用纽约地铁 MTA 十字转门的数据来确定女性在特定时间最有可能在哪里,因为她们经常进行无报酬的家务劳动和跑腿,随后,为一个女性科技组织建立最佳地铁站,以通过电子邮件收集增加曝光率。

每周一期的 TDS 播客经常讨论人工智能伦理和政策等话题,我们很幸运地邀请到了《伦理人工智能》的创始人兼谷歌研究院 ML Fairness 的联合创始人玛格丽特·米歇尔参加播客。她谈到了围绕人工智能构建过程中不同观点的想法,不同形式的偏见,以及将测试集分成子集以显示性能多样性。像我们的许多客人一样,她关于多样性在各种技术发展中的重要性的见解在这一集里始终如一,她对人工智能复杂的道德问题的评论在出版后的几个星期里一直伴随着我。

卡洛斯·穆根,志愿编辑助理

机器学习和数据科学在过去几年里取得了惊人的成果。但是,随着它融入日常生活,人们越来越担心对负责任的人工智能的需求。在 2021 年的过程中,我们已经看到了关于可解释性、人工智能伦理、公平等许多非常有趣的博客帖子。在这里我分享一些启发我这一年的帖子!

我很喜欢这篇由 Divya Gopinath 撰写的关于衡量和理解公平的实用帖子,他解决了一个最棘手的挑战:如何在数据科学的背景下定义“公平”的含义。

Joaquin quionero-Candela的这一期 TDS 播客是在他辞去 facebook 负责人工智能的杰出技术主管的几个月前播出的;正如我在 5 月提到的,“这种影响力伴随着巨大的责任——除了其他事情之外,开发符合道德、公平和良好特性的人工智能工具的责任。”

此外,一些自我品牌:我最近的这篇文章是从之前在欧洲机器学习大会上发表的一篇论文中科学披露的,这是一个关于欧洲中央银行背景下的偏见和公平的研讨会。

卢多维克·贝尼斯坦特,编辑

我很喜欢这篇文章,由微软的 Scott Lundberg 、Eleanor Dillon、Jacob LaRiviere、Jonathan Roth 和 Vasilis Syrgkanis 撰写的文章小心解读预测模型,寻找因果洞察。他们的文章特别好地说明了为什么我们在从机器学习模型中估计因果关系时应该小心。他们为自己的论文提供了有力的证据(有很棒的图表),并为我们的社区提供了一些关键的收获。这是一个 16 分钟的阅读,完全值得!

今年,我们还收到了来自数据科学家、数据分析师和机器学习工程师的精彩文章,分享了他们典型的工作日:他们通常在做什么?他们的时间表是什么样的?他们的日常挑战是什么?这里有两篇你可能会感兴趣的文章。第一部《健康数据科学家的日常生活》是由露西·罗斯韦尔创作的,第二部《作为研究机构数据分析师的生活》是由艾米丽·a·哈尔福德创作的。

本·胡伯尔曼,主编

我最常看到的帖子集中在我关心的问题上,或者突出了古怪、另类的项目。令人震惊的是,我知道,当我想到过去的一年以及我们在 TDS 上发表的所有优秀作品时,我的记忆中出现的正是这些帖子。

“改变的数据”和“好的数据”是偶尔听起来空洞的概念,但当作者以谨慎、技巧和具体的想法处理他们的主题时就不会了。在气候变化方面,我强烈推荐 Jane Thompson 关于洪水和房地产价值之间联系的研究Ivana Kotorchevikj 关于 AI 自己碳足迹的概述。它们都是及时而有价值的贡献。关于公平和多样性,Denisa Blackwood 对数据科学中的性别差异进行了广泛的研究,立即成为必读的书籍,也是重要的话题。

不考虑主题,我对那些敢于打破常规,为读者提供与众不同的东西的作者情有独钟。最肯定做到这一点是 Kie Ichikawa ,他将华丽的视觉故事融入到一个关于自然周期表现的帖子(剧透:樱花也参与其中,它们如此美丽)。尤娜·申数据与艺术的探索是另一个奇妙的项目,它汇集了一个 MOMA 数据集,一个互动装置,以及关于主要博物馆藏品中缺乏边缘化社区的重要见解。

尽管已经是年底了,但我们有更多的理由庆祝——也就是说,我们在过去几周欢迎所有优秀的新作者加入 TDS。在安特里克什·戈埃尔伊森·廖易贤傅鹏程克莱顿·罗查卡洛·博雷拉阿米尔·霍西尼亚历山大·莫拉克亚历山德罗·安蒂尼詹姆斯·富尔顿玛丽安·贝洛蒂【同我们一起兴奋地挥手吧 马克·贾米森泽雅奥里·阿布拉莫夫斯基艾玛-索菲亚·内格尔斯卡伦·巴加多尔·巴伦西亚巴特兰马丁·范·阿蒂库姆阿里·法吉内贾德路易·盖斯勒尼古拉斯·印多 亚伦·克鲁明斯帕瓦西·克里希南穆斯塔法·哈吉伊格纳西奥·奥吉扎德万西·维尔马罗恩·奥兹明科夫斯基博士菲利克斯·霍夫施塔特伊万·卡塔纳https://medium.com/u/d467d32aeef7?source=post_page-----d1b04e29e3ef-------------------------------- 利皮卡·拉马斯瓦米曼努埃尔·特雷弗尼克·汉德尔安德里亚·达戈斯蒂诺塔姆·特兰-The伊斯拉·艾哈迈德阿列克谢·克拉韦茨法比奥·丘萨诺詹马尔科·e 看看他们的简介,检查他们的工作!

体面的篡改与一般的浓缩咖啡

原文:https://towardsdatascience.com/decent-tamper-vs-generic-for-espresso-18a73f46b4b9?source=collection_archive---------13-----------------------

咖啡数据科学

关于捣棒的简短实验

几个月前,我买了一台像样的浓缩咖啡。我在寻找一种夯锤,它可以更深入篮筐,但仍然保持水平。这对于断奏夯实击球尤为重要,我夯实了两次,每半拍一次。所以我拿了一些数据,看看 DE tamper 和我一年前买的一款通用之间是否有可测量的差异(注意,有时网站会改变尺寸,但我说的通用是指大约 20 美元的 58 毫米 tamper)。

首先,我取出弹簧。弹簧允许一个人校准夯力(超过 20 磅),我夯大约 1 磅或更少。所以我把弹簧拿掉了,我仍然可以用一个天平来测量压紧力。

所有图片由作者提供

然后我拍摄了一些照片,记录了一些数据,用一些指标进行了比较。

免责声明:

  1. 这不是全部的结束,是全部篡改测试的表现。这是对断奏夯实击球下半部分的性能比较,以确定夯实的自动调平部分是否有所不同。
  2. 我已经捣实并提取了 2000 多张照片,所以这个测试对于不熟悉浓缩咖啡或经验较少的人来说可能会有很大不同。

镜头性能指标

我将这些定义放在这里,因为在这一节之后,我将使用这些指标评估不同数量的纸质过滤器。

我使用了两个指标来评估镜头之间的差异:最终得分咖啡萃取

最终得分是 7 个指标(强烈、浓郁、糖浆、甜味、酸味、苦味和余味)记分卡的平均值。当然,这些分数是主观的,但它们符合我的口味,帮助我提高了我的拍摄水平。分数有一些变化。我的目标是保持每个指标的一致性,但有时粒度很难,会影响最终得分。

使用折射仪测量总溶解固体(TDS ),该数字用于确定提取到杯中的咖啡的百分比,并结合一杯咖啡的输出重量和咖啡的输入重量,称为提取率(EY)。

数据分析

我在一周的时间里收集了 10 对样本。在我做分析之前,我没有注意到明显的不同。

我研究的前两个指标是味道(最终得分)和提取率(提取率,EY)。我看不出有什么不同。有差异,但它们似乎没有一个模式。这意味着结果的不同不能归因于篡改的改变。

我们可以把这些分解成我使用的不同的烘焙,因为那可能对结果有影响。然而,我还是没有发现问题。我只看到了几个异常值,这可能是由于拍摄准备或口味的微小差异,我在拍摄前吃的东西可能会影响得分。

所以,我研究了更多的指标。我看了 TDS 和总拍摄时间。同样,数据没有显示出一种模式。

我整理了一份总体总结,其中还添加了 TCF 和 T10。TCF 是盖住过滤器的时间,T10 是我的子弹杯达到 10 毫升的时间,这两个时间在这里有更好的解释。从这个角度来看,没有太大的不同,除了 TCF 似乎发生得更快一点。

我喜欢体面的篡改,我很高兴我买了它的能力更好的水平。这需要一些猜测,以确保我正确地水平拍摄。除了改进的工作流程之外,它似乎对一般的篡改没有什么影响。

话说回来,我做意式浓缩咖啡已经很多年了,在过去的一年里,我没有太多糟糕的 tamps。对于一个新接触浓缩咖啡或经验不足的人来说,适当的捣棒可能会提高他们的技术,让他们提取得更好。

如果你愿意,可以在 TwitterYouTube 上关注我,我会在那里发布不同机器上的浓缩咖啡照片和浓缩咖啡相关的视频。你也可以在 LinkedIn 上找到我。也可以在关注我。

我的进一步阅读:

浓缩咖啡系列文章

工作和学校故事集

个人故事和关注点

乐高故事首页

摄影飞溅页面

具有联邦学习的分散式机器学习训练

原文:https://towardsdatascience.com/decentralized-machine-learning-training-with-federated-learning-c8543696c1e7?source=collection_archive---------28-----------------------

机器学习有两个不可避免的事实:更多的数据和更多的计算能力来训练这些数据。

梅琳娜·瓦莱在 Unsplash 上的照片

在最近的一篇文章中,我介绍了一个包含 ML 计算和存储的基础架构。我提出的架构中的一个主要假设是将所有的训练数据整合到一个位置(存储系统),更重要的是,这些数据很容易用于 ML 训练。如果我们需要一些数据进行训练,但由于各种原因,这些数据无法存储在我们的环境中,那么会发生什么呢?进入联邦学习

我在文章中概述的方法假设数据和计算都是集中的。在集中式方法中,构建和训练模型所需的所有数据都可以在与计算相同的环境中轻松获得。联合学习颠覆了这个模型。联合学习不是集中数据和计算,而是在分散的模型下运行,不需要共享数据。后者是关键。

下图说明了联合学习是如何工作的。第一步是引导一个模型,这将发生在您自己的环境中。您使用自己掌握的数据和计算资源构建了一个模型的初始版本。然后你把这个模型推广到远程站点。每个站点都有一些您希望用来训练模型的专有数据。这些数据可能有助于您的模型一般化并执行得更好。然后,您下推到这些本地站点的模型将根据每个站点的本地数据进行训练。数据不会离开网站。一旦培训完成,来自每个站点的新模型将被推回到您的环境中。这将依次产生一个新的模型,它是初始版本和从每个远程站点生成的模型的结果。

联合学习(图片来自作者)

实际上,每个站点的模型权重被发送回来,并在来自其他模型(包括引导模型)的所有权重中进行汇总(或平均)。这将产生一个新版本的模型,该模型是从您培训过的所有远程站点的组合模型中派生出来的。全部完成,无需共享数据!

联合学习在几种情况下发挥作用,也许最普遍和最有用的是大规模分布式学习和解决数据隐私问题。

考虑这样一种情况,您有一个非常流行的移动应用程序。它被全球数亿人使用。您可能希望在协作和高度分散的培训中利用您的移动应用程序的广泛采用。Google 是一个很好的例子,它在 Android 上的 Gboard 中利用了联合学习,Android 是 Google 的键盘。当 Gboard 显示一个建议的查询时,用户的手机会在本地存储这些信息以及相关的元数据。联合学习处理设备上的历史记录,为 Gboard 查询建议模型的下一次迭代提供改进建议。存储在用户设备上的数据仍然存在,永远不会到达谷歌的服务器。然而,从用户本地获得的知识被应用到全局模型中。

另一个例子来自我熟悉的领域:医疗保健。假设您正在构建一个癌症检测模型。你将需要跨越图像的大量医疗数据,比如 x 光、乳房 x 光、PET/CTs 等等。您可能还需要其他医疗数据,如病理报告和患者病历。所有这些都是高度敏感的私人数据。您将无法将这些数据移动或复制到自己的环境中。联合学习在这里会有很大的帮助。您不必将数据发送回您的母舰,而是在远程站点本地训练一个模型,并使用联合学习将学习应用到您的全球模型。

联合学习是一种特殊的技术,可以帮助机器学习构建者提高模型的性能。这样做不需要移动或合并培训数据。通过联邦学习,您可以根据远程和不可见的数据训练您的模型。

最初发表于T5【https://karimfanous.substack.com】

“决策影响”:实施新一代面向业务的指标的 10 个理由

原文:https://towardsdatascience.com/decision-impact-10-reasons-to-implement-the-new-generation-of-business-oriented-metrics-fcc17ea7871d?source=collection_archive---------27-----------------------

你有没有想过在你的公司里预测的有效附加值是多少?

照片由 Edi Libedinsky 在 Unsplash 上拍摄

公司最重要的决策都是基于某种形式的预测:招聘、开发新产品线、拓展新领域等决策。当然,预测在我们供应链的日常运作中扮演着重要的角色。

如何衡量绩效?

预测者在组织中的角色

有趣的是,预测的需求是如此重要,需要如此专业的知识,以至于催生了一个专门的职业:预测者。

从组织的角度来看,公司围绕专门的职能、专门的团队,有时甚至是整个专门的部门,创造并专门化了这种专业知识。大多数时候,这些结构由供应链部门监管。

公司中预测功能的这种组织有许多优点,特别是将该领域的专家聚集在一起,让他们可以分享他们的实践。

然而,这种任务分离造成了一个关键问题。通过将“预测”功能从“决策”功能中分离出来,许多公司在某种程度上创建了导致次优性能的筒仓。

预测对业务绩效的贡献很难衡量

原因如下:尽管预测在决策过程中起着关键作用,但它不是唯一的。还必须考虑其他元素,通常以约束和业务规则的形式。

因此,准确衡量预测对最终结果的贡献,即所作决定的绩效,往往是复杂的。

例如,当决定从供应商处购买货物时,需求预测显然非常重要,但允许的包装尺寸、最小订货量、存储有限容量等也很重要。

挑战在于专注于重要的事情

当然,所有的预测者都会定期评估他们预测的可靠性,为此存在许多公式。这些指标侧重于预测的内在质量,通常称为“预测准确性”指标。

这样做的时候,他们经常忽略了对基于最终预测的决策及其与业务相关性的分析。

Vekia ,我们已经观察了很长时间。可以肯定的是,我们不是第一个也不是最后一个发现这个重要极限的人。

因为我们喜欢接受挑战,我们自然会问自己:我们如何评估预测的质量,以便它导致的决策是最好的?换句话说,是什么让预测变得好呢?

什么样的预测是好的?

要理解什么是好的预测,有必要回到预测的目的。

在最近的 IIF ECR 网络研讨会[1]上,Paul Goodwin 提醒我们,预测不是目的,而是“为了支持决策者,使他们能够做出更好的决策”。

预测基础

让我们简单回顾一下预测的现状和基本原理。

以下对理想预测的定义得到了广泛认同。理想的预测是完全真实的预测。例如:如果预测售出 996 台,并且在一天结束时,实际售出 996 台,那么这个预测是完美的!

然而,显而易见的是,尽管做了各种努力,但未来永远无法如此确定。因此,衡量一个预测的质量,实际上就是衡量它的误差。例如:如果预测售出 996 台设备,而在一天结束时,实际只售出 900 台设备,则该预测会产生 96 台设备的误差

预报员的主要任务是生成最小化这种误差的预报。这种误差测量是通过十几种不同的“预测准确性”指标实现的,此外还有各公司为其特定需求开发的无数变体。

最好的预测是能够做出最好决定的预测

不幸的是,这种被几十年实践所强化的方法忽略了一个关键点:

预测的目的不是也从来不是提供有史以来最好的预测!其目的是做出最佳决策。

因此,最好的预测不是完美的预测,而是能够做出最佳决策的预测。因此,预测者的使命不应是最小化预测与现实之间的误差,而是最小化决策误差。

这里有一个例子。让我们想象一个非常简单的决策过程,取自日常生活:每天晚上,一位女士咨询天气预报,以决定第二天是否带伞。

如果我们关注预报误差,那么当预报没有预测到下雨,而且第二天确实没有下雨,那么预报就是完美的。但是,从另一方面来说,如果预报说会有 10 毫米的降雨,而结果却是 10 倍多,那么这个预报就有很大的误差。

这里测量的是内在预测误差。

但是现在让我们把注意力集中在做出的决定上。在“支持还是不支持”决策的特定上下文中,上述错误不会对所采取的决策产生任何影响。在这两种情况下,这位女士都会做出正确的选择,带走她的雨伞。因此,就其用途而言,预测是完美的。

因此,预测的质量完全取决于它的使用和它所引发的决策。

然而,正如我们所见,预测者只有衡量预测内在准确性的指标。没有一个考虑到它的实际用途。

这并不意味着对这些指标不感兴趣,远非如此。但我们必须认识到,从商业角度来看,它们并不是最合适的选择…

迈向新一代“决策影响”指标

幸运的是,完全有可能以不同的方式处理预测的质量。为此,必须引入新一代指标。这些度量被称为“决策影响”(表示为“DI”),不再关注内在错误,而是关注所做决策的质量。

构建数字双胞胎

建议的指标要求创建一个计算机模型(或“数字孪生”),该模型可以针对任何预测输入,模拟决策过程并评估最终决策的质量。

然后有必要对决策过程建模(通过表示为“DF”的决策函数)并定义决策质量的度量(通过表示为“DQE”的决策质量估计器)。

决策的质量可以通过多种方式来表达。然而,我们强烈建议将其表达为财务成本,因为这允许多种用例,稍后将讨论这些用例。

当然,过程和影响的完美模型有时很难实现,如果不是不可能的话。但是一个简化的模型通常能够有效地“近似”更复杂的现实。

利用 3 种预测

需要三种不同的预测来生成提议的新指标并展示其价值:

  • 所谓实际预测,源于预测过程的到位。
  • 所谓的“天真的预测,源于最简单的预测方法,如果预测功能在公司中不存在,自然会使用这种方法。
  • 所谓“神谕”的预测,亦即地面实况,是后验测得并与观测结果本身相对应的。

这三种类型的预测随后被 Digital Twin 使用,以模拟相关决策及其各自的质量,称为“决策影响”。

  • 由实际预测产生的决策成本用“DIa”表示,即。指数“a”对“实际”的决策影响。它衡量当前预测流程生成的决策的质量。
  • 天真的预测所带来的决策成本用“DIn”表示,即。指数“n”对“天真”的决策影响。它衡量最简单的预测过程所产生的决策的质量。
  • oracle 预测所带来的决策成本用“DIo”表示,即。索引“o”对“oracle”的决策影响。它衡量的是对未来的完美认识所产生的决策质量。

DIa、DIn 和 DIo 提供关于预测环境的有价值的数据。除此之外,它们还是基本的构建模块,可以组合起来生成三个有洞察力的度量标准。

表示为“DIn-o”的第一个指标是“DIn”(基于预测的“幼稚”决策的成本)和“DIo”(基于预测的“oracle”决策的成本)之间的差异。该指标定义了完整的竞争环境,可通过预测改进来解决

(图片由作者提供)

表示为“DIn-a”的第二个指标是“DIn”(基于预测的“原始”决策的成本)和“DIa”(基于预测的“实际”决策的成本)之间的差异。因此,它衡量的是实际预测过程所带来的附加值。该指标与 FVA(预测附加值[2],作者 Michael Gilliland)的概念相关,并通过提供附加值的美元化愿景对其进行了增强。

(图片由作者提供)

最后一个标为“DIa-o”的指标是“DIa”(“实际”基于预测的决策的成本)和“DIo”(“Oracle”基于预测的决策的成本)之间的差异。因此,它衡量的是通过改进实际预测流程仍能实现的最大价值。

(图片由作者提供)

结合起来,这些指标可以通过简单的图形表示(如堆积条形图/面积图或仪表图)进行呈现、分析和解释。

(图片由作者提供)

10 个令人兴奋的新观点

这一组新的“决策影响”指标打开了全新的视角。

有利于预测者的指标

预测者是这些指标的第一受益者。除其他外,新的见解能够:

  1. 拥有明确的“北极星”指标,最终提供关于预测质量的可靠观点。事实上,需要提醒的是,传统的预测准确性指标经常相互矛盾;
  2. 正确选择和配置最能支持决策的预测模型;
  3. 生成价值图,以明确识别价值池;
  4. 准确地知道何时停止改进预测,因为尚未收获的附加值不值得;
  5. 相反,了解哪个周界将从改进的预测中受益最大;
  6. 如果在给定可用资源的情况下有待改善的周界太大,则优先考虑最有影响的子周界;
  7. 评估预测过程中每个因素/步骤的美元化 FVA。

惠及整个公司的指标

这些新指标的好处不仅限于预测者。新的见解使整个公司:

  1. 由于每个利益相关者最终都容易理解的指标,简化和平滑了部门之间关于预测的沟通;
  2. 以公平、不矛盾和易于理解的方式评估和分享预测过程(及其子部分:每个预测者或步骤)的交付价值。

由于这些指标不仅仅是纯粹的预测指标,同样的方法可以应用于测量输入约束变化的影响,而不是输入预测的变化。例如,这可以评估包装尺寸成本或交付频率的影响…这是一个很好的工具,可以指出需要改进的地方,等等。

结论

每一家公司每天都在与低效和浪费作斗争。筒仓很早就被指出是这样的,并且被认为是真实的:组织内部的裂缝。

另一方面,预测功能自然不应该像筒仓一样,因为它在公司中处于中心位置。它确实是许多部门的重要合作伙伴,是 IBF 和 S&OP 等关键业务流程的核心。

然而,在预测者的实践中,性能测量仍然与预测的用途和商业影响历史上惊人地不相关。

将业务带回预测实践

在此引入的“决策影响”度量家族使得将“业务”维度带回规划的核心成为可能。好处是围绕业务重新调整整个公司。

不仅如此,这些指标开辟了新的视角,并允许围绕自动化、优先化和关键业务流程改进的全新用例。

在接下来的文章中,我将更详细地介绍“决策影响”指标的操作使用。

参考

[1] P .古德温,预测研究生涯的经验教训 (2021),IIF 欧洲委员会

[2] M .吉利兰,商业预测交易 (2010)

欢迎分享、评论或联系我,我愿意就数据科学和供应链相关话题进行分享和交流。
Linkedin:
www.linkedin.com/in/johann-robette/
Web:www . vekia . fr

不确定型决策

原文:https://towardsdatascience.com/decision-making-under-uncertainty-402a32300552?source=collection_archive---------10-----------------------

人工智能

人工智能决策问题中不确定性的类型。

布莱希特·丹尼尔在 Unsplash 上拍摄的照片

将人工智能(AI)应用于个人和商业决策问题取决于 AI 如何感知和处理不确定性和风险。为了理解不确定性在决策问题中的作用,让我们先快速回顾一下决策。最简单的决策分析如下图所示。

图片由作者提供。

你可以在诸如 Agrawal 等人的《预测机器》等书中找到更全面的决策分析。

https://www.amazon.com/Prediction-Machines-Economics-Artificial-Intelligence/dp/1633695670

决策中的不确定性类型

决策问题中有 4 种主要的不确定性。

  • 资料不确定
  • 预测不确定性
  • 判断不确定性
  • 行动不确定性

资料不确定

我们的数据过去和将来都有不确定性。数据中的噪声是最常见的数据不确定性。例如,传感器并不完美,它们总是记录某种程度的噪声。

重要的是要知道数据的不确定性不仅限于噪音。数据源的不确定性和数据表示的内容也是数据不确定性的两个例子。假设您有一个完美的传感器,但您不确定传感器的位置(例如,在煤气管道或地下)。在这种情况下,您面临的是数据源不确定性。在另一种情况下,假设您正在为一项政治活动收集数据。您从成千上万的个人那里收集信息,但是您不确定您收集的数据在多大程度上代表了目标社区。在这种情况下,您正在处理数据表示中的不确定性。

数据不确定性在处理不同数据源(尤其是传感器)的决策应用中至关重要。自动驾驶汽车领域充满了关于数据不确定性对决策影响的例子。

预测不确定性

使用可用的数据,您生成一些案例并尝试预测每个案例的结果。比如你想买房。你收集当地的房地产市场数据和你的财务数据。基于这些数据,你开发了一些案例,比如在靠近市中心的地方买一栋小房子,或者在郊区买一栋大房子。在制作案例之后,是时候预测每个案例中会发生什么。如果你在郊区买房子,你有更多的房间,接触自然,更友好的社区,但你的房子升值可能不会太多。在另一种情况下,你可能有一个更小的房子,有更多的餐馆和夜生活活动,你的房子将在当前的市场上大幅升值。但是你是怎么知道这些事情的?你有多大信心,闹市区的房子会比郊区的房子升值?你有多确定你的郊区社区比你的市区选择更友好?

仔细看,你的预测中有很多不确定性,简称“预测不确定性”。数据不确定性可能是预测不确定性的一个来源,但并不总是如此。即使有完美的数据,一个意外的事件也会改变事件的进程,你的预测可能会出错。想象一下,那些在市中心买房子的人离他们的办公室更近,而新冠肺炎远程制造了许多这样的工作。现在,离封闭的办公室越近并不意味着通勤时间越少,就像他们在买房决策中预测的那样。在这种情况下,环境发生了巨大的变化,即使最精确的收集数据也无法预测。

金融领域的人工智能决策支持系统每天都在处理这种类型的不确定性,即预测不确定性。

判断不确定性

你根据现有数据做了一些预测,现在是做出判断的时候了。你必须将它们相互比较,并根据你的效用函数进行排序。你的效用函数是金融、情感和许多其他因素的混合。回到我们买房子的例子,你的效用函数是你支付的钱,预期升值,生活舒适度,享受在附近,和许多其他因素的混合。你的判断应该帮助你根据你的效用函数对不同的案例进行排序。但是你怎么能把住在大房子里的舒适与你买房子的价格相比呢?你如何评价一个好的社区和预期的房屋升值?你应该更重视 10%更好的邻居还是 3%更多的房屋升值?

当人类或人工智能试图在不同情况之间做出判断时,由于这种混合因素,存在固有的不确定性。在一些问题中,很难对一些情感因素给出一个数值,然后进行比较。

判断不确定性在同时处理财务和情感因素的决策问题中更为常见。例如,在决定向消费者推荐产品之前,产品推荐系统必须解决判断的不确定性。这样的系统应该判断向谁推荐什么产品来满足他/她的情感和经济需求。

行动不确定性

我们试图收集完美的数据,准确预测结果,并根据最佳感知效用函数做出最佳判断。现在是做最后决定和采取行动的时候了。但是等等!采取行动是否会带来不确定性?我们先来看看动作不确定性是什么意思。行动不确定性意味着我们决定采取特定的行动,但实际上,我们做的是不同的行动。看起来很奇怪,怎么会有人决定采取某个特定的行动,但实际行动会不一样呢?有些情况下,就像买房子一样,你决定买一套房子,最后却错误地买了另一套房子,这是非常不寻常的。但是,现实世界中有许多行动不确定性的例子。例如,你的车将要撞上一个物体。你决定停下来。你必须踩刹车,但不幸的是,你踩了油门。在这种情况下,这一行动不是决策的意图,而是由于一个错误而发生的。

行动的不确定性并不总是由于一个错误。在驾驶事故的例子中,你可能正确地踩下了刹车踏板,但是由于轮胎损坏,汽车打滑并撞到了物体。你必须考虑到行动不确定性的可能性。

动作不确定性是机器人领域中重要的不确定性之一。

一个例子

本文提到的一切不仅适用于人类决策,也适用于人工智能决策。一个可靠的人工智能系统必须能够感知不确定性的概念,以适用于现实世界的决策问题。在这里,我向你展示了一个人工智能系统如何在决策中理解不确定性概念的例子。

以下示例显示了简单强化学习(RL)模型(SARSA)如何处理不确定情况下的决策。你可以在这个 GitHub repo 里看到细节:

https://github . com/tamimina ser/Windy _ World _ Reinforcement _ Learning

作者制作的视频。

目标是到达家乡州(红色方框)。问题在于失败国家的存在(我们称之为湖泊的深蓝色方框)。左边的代理人在一个没有风(没有不确定性)的世界里移动。因此,它会找到最短路径作为最佳路径。右边的代理运行在一个多风的世界(应用不确定性)。因为在这个例子中,失败具有巨大的成本,代理试图在最短路径和安全路径之间找到最佳平衡。因此,代理采取稍微长一点的路径来避免落入湖中。有趣的是,即使是简单的强化算法,如 SARSA,也能很好地理解不确定性的概念。它在最短路径和安全性之间做出妥协。

小测验

在前面的例子中,哪种不确定性起了主要作用?

花点时间想一想,我们的代理人由于大风天气而遭受的不确定性。

是的,你是对的;这个例子显示了动作的不确定性。AI(即,RL 代理)知道它需要做什么,但是它不确定动作(即,运动)是否将被正确地应用。

摘要

将 AI 应用于决策问题取决于 AI 如何感知和处理不确定性和风险。决策问题中有四种主要类型的不确定性:数据不确定性、预测不确定性、判断不确定性和行动不确定性。

关注我在媒体推特上的最新报道。

Python 中的决策树算法从零开始

原文:https://towardsdatascience.com/decision-tree-algorithm-in-python-from-scratch-8c43f0e40173?source=collection_archive---------5-----------------------

用 Python 编写只使用 NumPy 和 Pandas 的流行算法,并解释其中的内容

决策树架构;按作者分类的图表

本文的目的是通过遍历实现该算法的代码,使决策树分类器的所有部分变得清晰。代码只使用了 NumPy、Pandas 和标准 python 库。

完整的代码可以通过https://github.com/Eligijus112/decision-tree-python访问

到目前为止,当目标变量是二进制并且特征是数字时,代码创建一个决策树。这完全足以理解算法。

用 python 构建决策树的黄金标准是 scikit-learn 实现:

https://scikit-learn.org/stable/modules/tree.html

当我测试我的代码时,我想确保结果与 scikit-learn 实现相同。

本文使用的数据是著名的泰坦尼克号幸存者数据集。我们将使用两个数字变量——乘客的年龄和票价——来预测乘客是否幸存。

年龄+票价~生存;按作者分类的图表

目标是创建数字变量的【最佳】分割。目测数据,我们可以猜测一个好的分割方法是将数据分成两部分:年龄为 10 的观察值和年龄≥ 10 的观察值:

拆分数据集;按作者分类的图表

现在,一些迫在眉睫的问题可能会出现:

这是一个好的分裂吗?

也许以 200 英镑的价格分开会更好?

我们如何量化拆分的“好处”?

计算机如何寻找最佳分割?

所有这些问题都将在本文结束时得到解答。

决策树算法(简称 DT)是一种机器学习算法,用于在给定一组输入特征的情况下对观察值进行分类。该算法在不同的决策级别创建一组规则,从而优化某个度量。

目标变量将表示为 Y = {0,1} ,特征矩阵将表示为 X.

要扩展的关键词:

节点

基尼系数(我们正在优化的指标)

级别

分裂

一个节点是决策树中的构建块。当查看决策树的典型模式(如标题图片中的模式)时,节点是向下连接到其他节点的矩形或气泡。

每个节点都有以下主要属性:

基尼杂质分数

观察次数

属于每个二元目标类的观测值的数量。

特征矩阵 X 表示落入节点的观察值。

python 中的自定义节点类(我写的):

决策树的第一个节点叫做 根。 树底部的节点叫做 树叶

如果满足拆分标准,那么每个节点都有两个链接节点:左节点和右节点。例如,一个非常简单的具有一个根和两个叶的决策树可能如下所示:

示例决策树;按作者分类的图表

**n —** number of observations**y1 —** number of first class elements**y2 —** number of second class elements **X —** numeric feature for the observations

如果特征 X 小于 5,则输入将转到左侧节点。大于或等于 5 的特征值将去往正确的节点。

如上所述,每个节点都有一个 GINI 杂质分数。为了计算 GINI 杂质,所需要的只是目标变量在节点中的分布,或者简单地说,节点中有多少 Y=1 和 Y=0 观测值。

GINI 杂质的正式定义如下:

Gini 杂质是对从集合中随机选择的元素被错误标记的频率的度量,如果根据子集中标签的分布对其进行随机标记的话。

代数定义:

GINI 杂质公式;公式取自作者的笔记本

例如,如果在一个节点中有 10 个观测值是幸存者,5 个观测值不是幸存者,则:

p(survivors) = 10 /(10 + 5) = 0.66..
p(non-survivors) = 5 /(10 + 5) = 0.33.. 

因此,GINI 杂质可以通过平方这两个数字,将它们相加,然后从 1 中减去来计算:

gini impurity = 1 - (0.66..^2 + 0.33..^2) = 0.44.. 

在二进制情况下,最大基尼系数等于 0.5,最小基尼系数等于 0。值越低,节点越“纯”。无论我们有多少个观察值,我们都可以根据整个数据集计算其中一个类的份额,并绘制一个关系:

基尼不纯度与数据集中的类别份额;作者图片

我们总是寻找 GINI 杂质最低的分裂。

别的不说,最基本的直觉是,一个节点中的一类观测值越多,其杂质就越低。

level 属性定义在创建节点之前进行了多少次拆分。例如,根节点的级别为 0,那么左右节点的级别为 1,依此类推。

在自定义节点类中,树的最大深度可以通过超参数 max_depth 来调节。

分裂过程是一个过程,其中我们在每个节点中搜索哪个特征和哪个特征值是最好的,以将数据分成两个更小的部分。

在分类的情况下,我们希望最大化基尼增益。回到之前的例子:

示例决策树;按作者分类的图表

根节点的基尼系数为 0.48。左节点得分为 0.27,右节点得分为 0.5。 我们“获得”了多少基尼?

计算公式如下:

Gini gain =父节点 Gini 杂质减去左右节点的 Gini 杂质的加权平均值。

基尼增益公式;来自作者的笔记本

在上面的例子中,插入我们将得到的所有值:

0.48 — (0.27 * 30 /100 + 0.5 * 70/100) = **0.049**

GINI 增益等于 0.049。任何正的基尼系数都是一种进步。这意味着我们的决定会使节点更加“纯净”。

该算法如何在数字列中搜索最佳拆分?

对于每个特征,我们对特征值进行排序,并得到两个相邻值的平均值。

例如,假设我们的特征 1 如下:

feature_1 = [7, 5, 9, 1, 2, 8]

已排序:

feature_1 = [1, 2, 5, 7, 8, 9]

邻居的方式:

feature_1 = [1.5, 3.5, 6.5, 7.5, 8.5]

然后,我们检查来自上述向量的每个值的 GINI 增益是多少。而且,我们对数据集中的所有要素都执行此操作。

最终分割值和分割特征是具有最高 GINI 增益的一个。

增长树的自定义节点对象的超参数(将来会添加更多)是 max_depth: intmin_samples_split: int 变量。

max_depth 整数定义了树应该增长到多深。在 max_depth 深度处,停止搜索最佳分割特征和分割特征值。

min_samples_split 整数定义了开始最佳分割搜索时节点中的最小观察次数。例如,如果节点有 51 个观察值,但 min_samples_split = 55,则树的生长停止。

那么,代码是如何工作的呢?

首先,读取数据:

# Loading data
d = pd.read_csv(‘data/train.csv’)# Dropping missing values
dtree = d[[‘Survived’, ‘Age’, ‘Fare’]].dropna().copy()# Defining the X and Y matrices
Y = dtree[‘Survived’].values
X = dtree[[‘Age’, ‘Fare’]]# Saving the feature list 
features = list(X.columns)

然后我们定义超参数字典。

hp = {
 ‘max_depth’: 3,
 ‘min_samples_split’: 50
}

然后我们启动根节点:

root = Node(Y, X, **hp)

主要的树构建函数是 grow_tree() 函数。

root.grow_tree()

就是这样!

为了查看结果,我们可以调用 print_tree() 函数。

root.print_tree()

结果是:

全决策树;作者摘录

从 scikit-learn 实现中获得的决策树是相同的:

|--- Fare <= 52.28
|   |--- Fare <= 10.48
|   |   |--- Age <= 32.50
|   |   |   |--- class: 0
|   |   |--- Age >  32.50
|   |   |   |--- class: 0
|   |--- Fare >  10.48
|   |   |--- Age <= 6.50
|   |   |   |--- class: 1
|   |   |--- Age >  6.50
|   |   |   |--- class: 0
|--- Fare >  52.28
|   |--- Age <= 63.50
|   |   |--- Age <= 29.50
|   |   |   |--- class: 1
|   |   |--- Age >  29.50
|   |   |   |--- class: 1
|   |--- Age >  63.50
|   |   |--- class: 0

尽管如此,scikit-learn 实现输出的信息比我的实现少。

事实证明,最佳的第一次初始拆分是值为 52.28 的票价特征,而不是值为 10 的建议年龄特征。

我写的代码构建了与 scikit-learn 实现相同的树,并且预测是相同的。但是 scikit-learn 算法的训练时间要快得多。但是我的目标不是让树长得更快。我的目标是为任何机器学习爱好者编写一个可理解的代码,以便更好地理解正在发生的事情。

如果您发现任何错误或只想添加功能,请在此回购https://github.com/Eligijus112/decision-tree-python中随意创建一个拉取请求。

决策树分类器在现实生活中的解释:选择度假目的地

原文:https://towardsdatascience.com/decision-tree-classifier-explained-in-real-life-picking-a-vacation-destination-6226b2b60575?source=collection_archive---------0-----------------------

入门

决策树是一种受监督的机器学习算法,它使用一组规则来做出决策,类似于人类做出决策的方式。

图片作者。

这是致力于基于树的算法系列的第一篇文章,基于树的算法是一组广泛使用的监督机器学习算法。

如果你想看决策树、随机森林和梯度推进决策树,请继续关注,用现实生活中的例子和一些 Python 代码来解释。

决策树是一种受监督的机器学习算法,它使用一组规则来做出决策,类似于人类做出决策的方式。

思考机器学习分类算法的一种方式是,它是为了做出决策而构建的。

你通常说模型预测新的、以前从未见过的输入的类别,但是在幕后,算法必须决定分配哪个类别。

一些分类算法是概率性的,如朴素贝叶斯,但也有一种基于规则的方法。

我们人类也一直在做基于规则的决定。

当你计划下一个假期时,你使用基于规则的方法。你可能会根据你要去度假多长时间、可用的预算或者你的大家庭是否会一起来选择不同的目的地。

这些问题的答案决定了最终的决定。如果你根据你对每个问题的回答不断缩小可用度假目的地的范围,你可以把这个决策过程想象成一棵(决策)树。

一棵做决定的树

决策树可以执行分类和回归任务,所以你会看到作者称它们为 CART 算法:分类和回归树。这是一个总括术语,适用于所有基于树的算法,而不仅仅是决策树。

但是让我们把重点放在决策树上进行分类。

决策树背后的直觉是,你使用数据集特征来创建是/否问题,并不断分割数据集,直到你分离出属于每个类的所有数据点。

在这个过程中,你将数据组织成一个树形结构。

每次你问一个问题,你就给树增加了一个节点。而第一个节点称为根节点

提问的结果根据一个特性的值分割数据集,并创建新的节点。

如果您决定在分割后停止流程,那么最后创建的节点称为叶节点

包含树节点、根节点和两个叶节点的决策树示例。(图片由作者提供)

每次你回答一个问题,你也在创建分支并将特征空间分割成不相交的区域【1】。

树的一个分支具有对应于回答问题的所有数据点,这是前一个节点中隐含的规则。另一个分支有一个包含剩余数据点的节点。

树中不同区域和节点类型的例子。(图片作者提供)

这样,通过树中的每个分裂或分支来缩小特征空间,并且每个数据点将只属于一个区域。

目标是继续分割特征空间,并应用规则,直到没有更多规则可应用或没有数据点留下。

然后,该给每个叶节点中的所有数据点分配一个类了。

分配课程

该算法试图完全分离数据集,使得所有叶节点,即不再进一步分割数据的节点,属于单个类。这些被称为纯叶节点。

只有纯叶节点的树的例子。(图片作者提供)

但是大多数情况下,你最终会得到混合的叶节点,其中并不是所有的数据点都属于同一个类。

在将最终类分配给每个节点之前,具有纯叶节点和混合叶节点的树的示例。(图片作者提供)

最终,算法只能给每个叶节点中的数据点分配一个类别

因为该节点中的所有数据点都具有相同的类。

但是对于混合叶节点,该算法在该节点的所有数据点中分配最常见的类别

很难造出完美的树

理想的树是尽可能最小的树,即具有较少的分裂,能够准确地分类所有数据点。

这听起来很简单,但实际上是一个 NP 难题。构建理想的树需要多项式时间,随着数据集的增长,多项式时间会呈指数增长。

例如,对于一个只有 10 个数据点的数据集和一个具有二次复杂度,O(n)的算法,该算法执行 10*10 = 100 次迭代来构建树。将该数据集进一步扩展到 100 个数据点,算法将执行的迭代次数将增加到 10,000 次。

寻找最佳树在理论上是理想的,但随着数据集的增长,这在计算上变得不可行!

为了将这个 NP 难问题转化为计算上可行的问题,该算法使用了一种 贪婪方法 来构建下一个最佳树。

一种贪婪的方法做出局部最优的决定来挑选每个分割中使用的特征,而不是试图做出最佳的整体决定【2】。

因为它针对本地决策进行了优化,所以它只关注手边的节点,特别是对该节点最好的节点。因此,它不需要探索该节点及其以外的所有可能的拆分。

选择最佳分割

在每次分割时,该算法试图将数据集分割成尽可能小的子集[2]。所以,像任何其他机器学习算法一样,目标是尽可能最小化损失函数

分类算法的一个流行损失函数是随机梯度下降,但是它要求损失函数是可微分的。所以,在这种情况下这不是一个选项。

但是,由于您正在分离属于不同类的数据点,损失函数应该根据分割前后属于每个类的数据点的比例来评估分割。

决策树使用损失函数来评估基于结果节点的纯度的分割。

换句话说,你需要一个损失函数来评估基于结果节点的纯度的分割。一个损失函数,比较分裂前后的阶级分布[2],像基尼杂质

基尼杂质

基尼系数是衡量不同阶层间差异的指标[1]。

节点的基尼杂质。

与基尼不纯相似,熵是节点内混沌的一种度量。在决策树的上下文中,混乱是指在一个节点上,所有的类都平等地出现在数据中。

节点的熵。

使用熵作为损失函数,仅当每个结果节点的熵低于父节点的熵时,才执行分裂。否则,拆分不是局部* 最优。*

为什么要使用决策树

尽管决策树是一种简单的算法,但它有几个优点:

  • 可解释性你可以将决策树形象化。
  • 无需预处理在构建模型之前,您不需要准备数据。
  • 数据健壮性该算法可以很好地处理所有类型的数据。

可解释性:可视化树

基于树的算法的一个最大的优点是,你可以实际可视化模型。

你可以看到算法做出的决定,以及它如何对不同的数据点进行分类。

这是一个主要的优势,因为大多数算法都像黑盒一样工作,很难清楚地查明是什么让算法预测到特定的结果。

不需要预处理

一些机器学习算法要求特征值尽可能相似,因此算法可以最好地解释这些特征的变化如何影响目标。

最常见的预处理要求是特征归一化,因此相同比例的所有特征以及这些值的任何变化都具有相同的比例权重。

基于树的算法中的规则是围绕每个单独的特征建立的,而不是考虑整个特征集。每个决策都是一次查看一个特征,因此它们的值不需要标准化。

数据稳健性

基于树的算法非常擅长处理不同的数据类型。你的数据集可以混合数字和分类数据,你不需要对任何分类特征进行编码。

这是基于树的算法自己处理的预处理清单上的一项。

🛩🏝选择度假目的地

计划下一个假期可能很有挑战性。假期总是不够长,有预算限制,有时大家庭想一起来,这使得后勤工作更加复杂。

当需要做一个涉及太多变量的决策时,你喜欢从算法中寻求第二种意见。挑选一个度假目的地是一个完美的例子!

每当你开始计划假期时,你总是会考虑到:

  • 假期的持续时间,
  • 个人预算,
  • 天气预报,
  • 如果你的大家庭要加入,
  • 如果你喜欢冒险,想要探索新的地方。

因为决策树据说是模仿人类如何做决定,这就是你正在使用的算法。

好处是,最终,你将能够可视化决策树,并且看到算法如何选择目的地。

仔细考虑你以前度假的决策过程和你经常考虑的标准,你建立了一个数据集。

来自先前休假决策流程的数据集。(图片由作者提供)

尽管决策树算法可以处理不同的数据类型,ScikitLearn 当前的实现不支持分类数据

要使用来自 ScikitLearn 的决策树分类器,您不能跳过预处理步骤,需要在训练模型之前对所有分类特征和目标进行编码。

*import numpy as np
from sklearn import preprocessing def encode_feature(array):
    *""" Encode a categorical array into a number array

    :param array: array to be encoded
    :return: numerical array
    """* encoder = preprocessing.LabelEncoder()
    encoder.fit(array)
    return encoder.transform(array) feature_names = ['number_days', 'family_joining', 'personal_budget', 'weather_forecast', 'explore_new_places']class_names = ['Countryside', 'Beach']features = np.array([[10, 'Yes', 950, 75, 'Yes'],
                     [10, 'Yes', 250, 78, 'Yes'],
                     [7, 'Yes', 600, 80, 'No'],
                     [8, 'Yes', 750, 67, 'Yes'],
                     [10, 'Yes', 800, 73, 'Yes'],
                     [8, 'Yes', 850, 64, 'Yes'],
                     [15, 'No', 350, 78, 'No'],
                     [8, 'Yes', 850, 81, 'Yes'],
                     [6, 'No', 750, 59, 'Yes'],
                     [12, 'Yes', 1050, 54, 'Yes'],
                     [10, 'No', 230, 74, 'No'],
                     [3, 'Yes', 630, 74, 'Yes'],
                     [10, 'Yes', 830, 74, 'No'],
                     [12, 'No', 730, 52, 'Yes']]) # Encoding categorical features
features[:, 1] = encode_feature(features[:, 1])
features[:, 4] = encode_feature(features[:, 4])targets = np.array(['Countryside','Beach','Beach','Countryside',
                    'Beach', 'Countryside', 'Beach','Countryside',
                    'Beach', 'Beach', 'Countryside','Countryside',
                    'Beach', 'Beach'])targets = encode_feature(targets)*

预处理:✅完成

现在是时候构建并可视化决策树了。

*import pandas as pd
from sklearn import tree
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split def print_feature_importance(names_array, importances_array): *""" Prints out a feature importance array as a dataframe. """* importances = pd.DataFrame(data=names_array)
    importances[1] = importances_array importances = importances.T
    importances.drop(0, axis=0, inplace=True)
    importances.columns = feature_names

    print(str(importances.reset_index(drop=True)))def build_tree(features, targets, feature_names, class_names): *""" Builds a decision tree.
        Prints out the decision tree 1) as a plot, 2) as text.
        Also outputs: 1) feature importance, 2) training set and test set mean accuracy of tree

        :param features: model features
        :param targets: model targets
        :param feature_names: names of the dataset features
    """* train_features, test_features, train_targets, test_targets = train_test_split(features, targets, test_size=0.2, random_state=123) decision_tree = tree.DecisionTreeClassifier(random_state=456)
    decision_tree = decision_tree.fit(train_features, train_targets) # Visualizing the decision tree

    # 1\. Saving the image of the decision as a png    plt.subplots(figsize=(17, 12))
    tree.plot_tree(decision_tree, feature_names=feature_names, filled=True, rounded=True, class_names=class_names)
    plt.savefig("decision_tree.png") # 2\. Output the tree as text in the console
    tree_as_text = tree.export_text(decision_tree, feature_names=feature_names)
    print(tree_as_text) # Feature Importance
    # Turns the feature importance array into a dataframe, so it has a table-like output format
    print_feature_importance(feature_names, decision_tree.feature_importances_) # Training and test mean accuracy
    train_error = np.round(decision_tree.score(train_features, train_targets), 2)
    test_error = np.round(decision_tree.score(test_features, test_targets), 2)

    print("Training Set Mean Accuracy = " + str(train_error))
    print("Test Set Mean Accuracy = " + str(test_error)) build_tree(features, targets, feature_names, class_names)*

这段代码一次做很多事情,所以让我们来解开它。

它从使用 train_test_split 函数将数据集分割成训练和测试开始,因此您可以使用未用于训练模型的数据点来测试模型准确性。

构建模型并可视化树

默认情况下,ScikitLearn 使用基尼系数作为损失函数。但是您也可以使用熵作为损失函数,并在 DecisionTreeClassifier 中调整其他参数。

训练好模型后,您可以使用 plot_tree 方法可视化生成的决策树,并保存为 decision_tree.png

通过训练模型生成的决策树。(图片由作者提供)

您也可以在输出控制台中可视化该树,您可以使用 export_text 方法。**

在输出控制台中将决策树可视化为文本。(图片由作者提供)

特征重要性

但是那个决策树有问题!

您注意到功能 explore_new_places 没有出现在任何地方。即使你确定这是你决策过程中重要的一部分。

为了弄清这一点并理解为什么模型中没有使用 explore_new_places ,您可以在决策树模型中查找 feature_importances_ 属性。这将告诉你每个特征对模型准确性的贡献有多大。

feature_importances_ 属性只是一个值数组,每个值对应于模型的一个特征,其顺序与输入数据集的顺序相同。

因此,为了更好的可读性,您可以决定创建函数 print_feature_importance,并将值数组从 feature_importances_ 属性转换为 dataframe ,并使用特性名称作为标题。

可视化特征重要性。(图片由作者提供)

explore_new_places 的要素重要性为 0,这意味着在预测中根本不使用它。

乍一看,你可能会想,我可以去掉这个特性。**

但是特性的重要性并不一定意味着该特性永远不会在模型中使用。这只意味着它没有在这个树中使用,这是一个特定的训练-测试分割。

所以你不能马上消除这个特性。

为了确认 explore_new_places 与模型无关,您可以用数据集的不同训练测试分割构建几棵树,并检查 explore_new_places 是否仍然具有零重要性。

模型性能

最后,为了评估算法的性能,您可以使用得分 方法计算训练集和测试集上预测的平均准确度。

训练集和测试集预测的平均准确性。(图片由作者提供)

正如你所看到的,这个模型被过度拟合并记住了训练集。由于测试集的平均准确率为 67%,它不能很好地推广到以前从未见过的观察结果。

一个决策树是不够的

尽管决策树有其优势,但它不能提供与其他分类和回归算法相同的精确度。

决策树容易过拟合。如果您构建了一个非常高的树,分割特征集直到您得到纯叶节点,您可能会过度适应训练集。生成的树如此复杂,以至于很难阅读和解释。

另一方面,如果你的决策树很小,它会对数据进行欠拟合,导致高偏差。

高偏差和高方差的决策树示例。(图片由作者提供)

决策树在它们可以处理的数据类型方面是健壮的,但是算法本身不是很健壮。数据的微小变化可能会彻底改变树,从而改变最终结果[1]。

隐藏在森林中的力量

与其他机器学习算法相比,一个单独的决策树本身的准确性就很低。单独一棵树通常不会产生最佳预测,但是树结构使得控制偏差-方差权衡变得容易。

一个单独的决策树不够强大,但是整个森林足够强大!

在结合多个树并控制偏差或方差的算法中,如随机森林,与单个决策树相比,该模型具有更好的性能。

**请继续关注本系列的下一篇文章,因为它们是关于增压和装袋的。这些技术应用于基于树的算法,并分别解决偏差和方差问题。

结论

决策树是一种基于规则的分类和回归问题的方法。它们使用每个要素中的值将数据集分割成一个点,在该点处,具有相同类的所有数据点被分组在一起。

然而,在可解释性和性能之间有一个明显的平衡。

你可以很容易地想象和解读一棵小树,但是它有很高的方差。训练集中的微小变化,可能会导致完全不同的树和完全不同的预测。

另一方面,具有多个分支的高树产生更好的分类。但很可能是在记忆训练数据集。所以它不擅长对从未见过的数据进行分类。

希望你喜欢学习决策树!

敬请关注本系列的下一篇文章!接下来的文章将探索基于树的集成算法,这些算法使用 Boosting 和 Bagging 技术来控制偏差和方差。

感谢阅读!

参考

  1. 加雷斯·詹姆斯,丹妮拉·威滕,特雷弗·哈斯蒂,罗伯特·蒂布拉尼。(2013).统计学习导论:在 r .纽约的应用
  2. 页(page 的缩写)tan m . stein Bach 和 V. Kumar。(2005)数据挖掘简介。艾迪森·卫斯理**

决策树—从头开始实施

原文:https://towardsdatascience.com/decision-tree-implemented-from-scratch-f11f7ca6aa0?source=collection_archive---------34-----------------------

蝴蝶效应,与决策树无关…,波兰 2020(作者供图)。

我想把这个作品扩展成一个系列——教程 视频 。如果你有兴趣,请 订阅 到我的 简讯 保持联系。

介绍

当谈到制作模型时,不难有这样一种印象,即当今世界都是关于神经网络的。许多团队似乎吹嘘超级酷的架构,好像获得足够高质量的数据很简单,GPU 机架 24/7 开放(免费),他们的客户的耐心被设置为无穷大。

在本文中,我们将介绍一种最基本的机器学习算法,称为决策树。决策树通常被认为是“救援”模型,因为它们不需要大量的数据就能工作,并且易于训练。尽管有过度拟合的倾向,但由于预测机制的本质,这些树在解释上有很大的优势。

传统上,我们将从零开始实现和训练模型,使用基本的 numpy 和 pandas。请注意,无论如何,我们实现它的方式不是唯一可能的方式。在这里,我们通过从第一原理设计我们的树来集中解释算法的内部工作。因此,更多地将其作为演示,而不是生产解决方案,例如在 scikit-learn 中可以找到。

理论

决策树因其类似于树的结构而得名。经过训练的树将通过一系列节点传递示例数据(也称为“splits”,稍后会详细介绍)。每个节点都充当下一个节点的决策点。最终节点,即“叶子”,相当于最终预测。

培训过程

训练决策树是识别最佳节点结构的过程。为了解释这一点,考虑一个二维输入特征向量,我们希望为其识别一个目标类。第一个节点需要“知道”要检查向量的哪个分量 x[k],k = 1,2,…,n ,以及要检查的阈值 x[t] 是什么。根据决定,向量将被路由到不同的节点,依此类推。

一个训练有素的树的节点和它们各自的参数 (k,x[t]) 以这样一种方式选择,即错误识别的目标类的数量是最低的。现在的问题是如何构建这样的节点?

这里,至少有两个数学公式可以帮助我们。

交叉熵公式

基尼系数(基尼系数)

蝴蝶效应,与决策树无关…,波兰 2020(作者供图)。

这两个公式都表达了关于系统的某种 T2 信息。因为交叉熵函数看起来非常类似于基尼系数(图 1。),我们可以使用它们中的任何一个来建立我们的直觉(和模型)。然而,为了清楚起见,让我们使用后者。

图一。基尼系数与熵的关系是根据一个实例类的概率计算的。(图片由作者提供)

解释

如前所述,这两个函数都表达了某种信息。考虑一个二进制分类系统(在这种情况下,类的数量是 C = 1 ,我们只能打赌一个给定的例子是否应该被赋予一个给定的标签)。从分类的角度来看,如果能够知道结果应该是什么,那么最安全的情况就是发生了。在这种情况下,与结果相关的概率要么为零,要么为一。由于对于 C = 1G = 1-p = p(1-p) ,这种情况下的基尼系数为零。这个系统是“纯”的,在某种意义上我们知道会发生什么。

现在,我们一不确定 (0 < p < 1),G > 0 ,正好在我们知道最少 p = 1/2 的时候达到峰值。熵也是如此。它越高,系统就越“混乱”,或者说我们得到的“信息”最少。

添加更多的类 C > 1 不会改变这里的逻辑。这两个数字通过总和 j = 1,2,…,C 从所有类别中提取贡献。

减少杂质

好吧,但是基尼系数如何帮助我们解决训练决策树的问题呢?如前所述,这都是关于战略性地设置节点,因此它们都有助于做出好的决策。任何决策(任何节点)都相当于在某个特定值沿给定轴对参数空间进行切片或分裂。如果选择 (k,x[t]) 的方式使我们对系统的了解逐渐增加,那么更有可能做出“好”的决策。换句话说,在这两个几乎形成的子空间中,不确定性比开始时要少。

如果 G+和 G-是与分裂后的子空间相关联的基尼杂质值,我们可以将所谓的基尼增益定义为:

其中 m 是示例计数,(+)和(-)是指子空间。

增益 g 越高,“更明智”的节点将能够区分不同的情况。如果所有的节点都是这样选择的,我们就有了一个合理的模型。

履行

让我们创建一个简单的人工数据集,其中每个例子都表示为一个三维向量 x ∈ ℝ。

import numpy as np
import pandas as pd

from sklearn.datasets import make_classification

X, y = make_classification(
        n_samples=12,
        n_classes=3,
        n_clusters_per_class=2,
        n_features=3,
        n_informative=3,
        n_redundant=0,
        n_repeated=0,
        random_state=42)

df = pd.DataFrame(X, columns=[x for x in range(X.shape[1])])
df["target"] = y

在这里,我们使用熊猫只是为了方便“把东西放在一起”。最重要的是我们有三维数据 (n = 3) 以及三个目标类 (C = 3) 。下表显示了数据集。

|      0 |      1 |      2 |  target |
|-------:|-------:|-------:|--------:|
|  0.78  | -1.09  | -0.99  |       0 |
|  1.56  |  0.87  | -0.93  |       1 |
|  1.17  | -0.25  |  0.54  |       0 |
| -1.84  | -0.70  | -2.71  |       2 |
| -1.91  | -1.57  |  0.98  |       1 |
| -0.96  | -0.77  | -3.92  |       2 |
| -0.83  | -2.70  | -2.13  |       0 |
|  0.02  |  2.20  | -0.08  |       2 |
|  1.62  |  0.38  |  0.83  |       0 |
| -0.14  | -0.70  |  1.39  |       1 |
|  2.29  |  0.48  |  0.32  |       1 |
|  0.53  |  2.33  | -0.12  |       2 |

基尼杂质

计算基尼系数是我们会反复做的事情。因此,将其包装为函数是有意义的。

def gini(df):
    probs = {}
    for c in df["target"].unique():
        probs[c] = len(df.query("target == @c")) / len(df)
    return sum([p * (1 - p) for p in probs.values()])

整个函数是前面陈述的公式的实现。我们迭代目标类(line 3.),并通过计数事件获得概率。

基尼增益

有了基尼系数的代码,让我们创建一个基尼系数的函数。

def gini_gain(df, feature_name, feature_value):
    df_a = df.query(f"{feature_name} < @feature_value")
    df_b = df.query(f"{feature_name} >= @feature_value")

    total_gini = gini(df)
    gini_a = gini(df_a)
    gini_b = gini(df_b)

    m, m_a, m_b = len(df), len(df_a), len(df_b)

    return total_gini - gini_a * m_a / m - gini_b * m_b / m

自然,增益值取决于对 k ( feature_name)和x【t】(feature_value)的具体选择。因此,该函数必须将它们作为输入。然后,我们简单地将数据集分成两部分,用_a_b替换((+)和(-),并返回增益值。

寻找最佳分割

功能ginigini_gain只是工具。为了找到最佳分割 (k,x[t]) ,我们需要比较各种选项,选择增益最大的一个。最简单的方法是迭代现有维度 (k = 1,2,…,n) ,并沿该维度扫描阈值 x[t] ,每次都评估增益。

def find_best_split(df, density_per_feature=10):
    splits = pd.DataFrame()

    for feat in [feat for feat in df.columns if feat != "target"]:
        split_candidates = np.linspace(
            df[feat].min(),
            df[feat].max(),
            num=density_per_feature,
        )

        _splits = pd.DataFrame()
        _splits["candidate_values"] = split_candidates
        _splits["feature"] = feat
        _splits["gini_gain"] = _splits["candidate_values"].apply(
            lambda value: gini_gain(df, feat, value)
        )

        splits = pd.concat([splits, _splits])

    best_split = splits \
        .sort_values(by="gini_gain", ascending=False) \
        .iloc[0]

    return best_split["feature"].iloc[0], \
           best_split["candidate_values"].iloc[0]

如您所见,density_per_feature是一个附加参数,用于选择我们扫描的粒度(通常越大越好,但也越长)。line 4.中的循环是循环结束。然后,我们定义split_split纯粹是为了方便。有了这些辅助数据帧,我们可以使用.apply方法自动获得帧中每个条目的基尼系数,并使用.sort_values找到最佳选项。识别之后,我们返回节点的选择维度以及阈值。

那棵树

决策树由节点组成。在训练时,我们不仅需要使节点“最优”,而且我们需要创建整个树结构,以便节点一起工作。而对于节点,我们有find_best_split函数,我们需要将它们组织成一棵树。

要理解递归,首先要理解递归。

考虑以下函数:

def func(tree, max_iter=5):
    max_iter -= 1
    if max iter <= 0:
        return [max_iter]
    node = [max_iter, func(tree, max_iter)]
    tree.append(node)
    return node

这是一个递归函数。它随后构建了一个简单的树(或者更确切地说是一个“树枝”),通过嵌套连续的数字,就像这样:

tree = func([])
print(tree)

[4, [3, [2, [1, [0]]]]]

如您所见,调用func的过程一直持续到它达到max_iter条件。在此之前,它会一直调用自身并向结构中添加节点。

我们的决策树是一个二叉树(每个节点分支到两个子节点)。因此,我们需要稍微修改一下func,以支持模式子节点,并用一对 (k,x[t]) 替换单个数字。因此,我们可以接受一个约定,其中每个节点由四个元素的列表定义:

  1. 分割特征(或尺寸) k
  2. 分裂值(阈值)x【t】
  3. 如果决策条件为真,则响应的子节点,
  4. 决策条件为假时做出响应的子节点。

此外,我们需要定义一个停止条件,以防止无休止的循环链。我们同意采用以下方法:

  1. 一旦我们只剩下给定子节点的单个类的所有元素,这意味着已经识别了特定决策节点序列的标签。因此,我们可以存储一个类标签。
  2. 如果我们怀疑树可能太深,我们也可以终止递归并取类的平均值(或模式)。这个模型不太精确,但是训练速度更快。

种植树木

让我们用split代替func的名字,并重新加工内部零件。

def split(tree, df, max_depth=5):

    splitting_feature, splittng_value = find_best_split(df)

    df_a = df.query(f"{splitting_feature} < @splitting_value")
    df_b = df.query(f"{splitting_feature} >= @splitting_value")

    max_depth -= 1

    if len(df_a) == 0 or len(df_b) == 0 or max_depth == 0:
        target_a = set(df_a["target"]) if len(df_a) > 0 else set([])
        target_b = set(df_b["target"]) if len(df_b) > 0 else set([])
        target =Hey! Do you mind helping me out? target_a.union(target_b)

        node = [splitting_feature, splitting_value, target, target]
        return node

    node = [
        splitting_feature, 
        splitting_value, 
        split(tree, df_a, max_depth=max_depth),
        split(tree, df_b, max_depth=max_depth),
    ]
    tree.append(node)
    return node

tree = split([], df, max_depth=10)

现在,我们来分解它。如果你仔细观察,split函数递归地工作,就像func一样。区别在于我们如何构造每个节点。这里,在我们为一个给定的节点确定了最佳对,并将数据集分成两个子集之后,我们测试是否达到了停止条件。如果子集df_adf_b中的任何一个缺少元素,这意味着我们已经到达了一片叶子,将不会再有来自该节点的分裂。同时,target_atarget_b是一个空集,因此集合的并集target将包含剩余的标签。除非我们提前终止这个过程(通过max_iters),否则set操作会将标签压缩到一个单元素集合中。这样,我们不仅唯一地标识了目标类,还坚持了将节点定义为四元素列表的惯例,其中最后两个元素是可迭代的,这防止了TypeError异常。

如果条件不适用,该过程继续。在这种情况下,每个节点“记住”最佳参数以及源于当前参数的两个子节点。

一个经过训练的树的示例可能如下所示:

[2, 0.208,
    [1, -1.023,
        [0, -0.839, {0}, {0}],
        [0, 0.804,
            [0, -1.845, {2}, {2}],
            [0, 1.5628, {1}, {1}]
        ]
    ],
    [1, -0.429,
        [0, -1.915, {1}, {1}],
        [0, 2.166,
            [0, 1.172, {0}, {0}],
            [0, 2.290, {1}, {1}]
        ]
    ]
]

作为模型的树

虽然这种嵌套结构可能看起来不令人满意,但对于机器来说,理解起来非常简单。基于该树的模型只需要使用列表的第一个元素来选择要检查的特性,将其与第二个元素进行比较,并根据结果将问题转发给第三个或第四个元素。重复这个过程,直到得到一个集合,并返回它的内容作为一个预测。

让我们实现这样一个模型。

def model(tree, data):
    node = tree
    while not isinstance(node, set):
        feature = node[0]
        value = node[1]
        node = node[2] if data[feature] < value else node[3]
    return list(node)[0]

现在,我们可以使用.apply方法对数据集运行这个模型:

df["predicted"] = df.get([0, 1, 2]).apply(
    lambda row: model(tree, row.to_numpy()), axis=1
)

请注意,[0, 1, 2]列表指的是特征的名称。结果如下表所示。

|          0 |         1 |          2 |   target |   predicted |
|-----------:|----------:|-----------:|---------:|------------:|
|  0.784972  | -1.09651  | -0.999525  |        0 |           0 |
|  1.56221   |  0.876346 | -0.937159  |        1 |           1 |
|  1.1727    | -0.258296 |  0.542743  |        0 |           0 |
| -1.84585   | -0.703202 | -2.71293   |        2 |           2 |
| -1.91564   | -1.57344  |  0.982937  |        1 |           1 |
| -0.966766  | -0.774834 | -3.92814   |        2 |           2 |
| -0.839739  | -2.70451  | -2.13491   |        0 |           0 |
|  0.0284821 |  2.20555  | -0.0827445 |        2 |           2 |
|  1.62031   |  0.382993 |  0.835343  |        0 |           0 |
| -0.144515  | -0.700331 |  1.39023   |        1 |           1 |
|  2.29084   |  0.486279 |  0.323968  |        1 |           1 |
|  0.532064  |  2.33869  | -0.120604  |        2 |           2 |

结论

正如您所看到的,决策树非常简单,但是实现起来可能并不简单。无论如何,在任何生产代码中,我们强烈建议您使用已经存在的实现。此外,你可能还应该研究所谓的集成方法,如随机森林,由于结合了几个模型的优势,它可能会给你带来额外的准确性提升。

原载于https://zerowithdot.com

Python 中的决策树模型—构建、可视化、评估

原文:https://towardsdatascience.com/decision-tree-models-934474910aec?source=collection_archive---------5-----------------------

使用 Python 的 MITx Analytics Edge 指南和示例

分类和回归树(CART)可以被转换成用于预测分类的图表或规则集。当逻辑回归模型无法提供足够的决策界限来预测标签时,它们会有所帮助。此外,决策树模型更容易理解,因为它们模拟了人类的决策过程。此外,决策树回归可以捕捉非线性关系,从而允许更复杂的模型。

作者根据约翰·西门子Unsplash 上的照片修改

购物车模型是如何工作的?

考虑两个独立变量 X1 和 X2 的情况。我们想预测结果是红色还是蓝色。CART 试图将这些数据分割成子集,使每个子集尽可能地纯净或同质。

决策树逻辑和数据分割-作者图片。

第一次分割(split1)以这样的方式分割数据,如果变量 X2 小于 60 将导致蓝色结果,否则将导致查看第二次分割( split2 )。 Split2 导向预测红色当 X1 > 20 考虑 X2 < 60 时。如果X2<90split 3 将预测蓝色,否则预测红色。

如何控制模型性能?

在您通过学科知识或特征选择过程为模型选择了要考虑的变量后,您将需要定义最佳分割数。

分割的目标是增加每个节点结果的同质性。提高其对数据进行分类的能力。换句话说,每次拆分后增加纯度。如果我们预测蓝色和红色,如果可能的话,选择给出全部蓝色和全部红色的分裂数。选择将生成纯结果的拆分数量。

纯节点是导致完美预测的节点。

但是如何量化拆分后的纯度,以确保我们有尽可能多的纯节点。

我们的目标是减少每次拆分后的不确定性。一个不好的拆分会让结局 50%蓝 50%红。例如,完美的分割将给出 100%的蓝色。

要衡量拆分在拆分后信息增加方面的表现,我们可以依赖以下指标:

1 — [ entropy = -1*sum(p*log(p)) ]

2 — 基尼杂质 [ Gini = sum(p(1-p)), where p is the proportion of misclassified observation within the sub partition ]

例子:预测法官史蒂文斯的决定

目标是预测史蒂文法官是否投票推翻法院判决,1 表示投票推翻判决,0 表示他支持法院的判决。

代码和数据可在 GitHub 获得。

数据框显示如下,带有目标变量(反向)。

史蒂文法官的法庭判决——图片由作者提供

重要提示:决策树(DT)既可以处理连续变量,也可以处理数值变量。但是如果您使用 Python Scikit Learn,您可能会得到分类的 ValueError。

这些要素具有许多分类值,我们将使用以下函数将其转换为数值:

**def** convert_cat(df,col):
    """
    input: dataframe and col list of categorical columns
    output: dataframw with numerical values
    """
    **for** c **in** col:
        item_list **=** df[c]**.**unique()**.**tolist()
        enum**=**enumerate(item_list)
        d **=** dict((j,i) **for** i,j **in** enum)
        print(c)
        print(d)

        df[c]**.**replace(d, inplace**=True**)
    **return** dfconvert_cat(df,['Circuit', 'Issue', 'Petitioner', 'Respondent',
       'LowerCourt'])

将数据分为训练和测试

X_train, X_test, y_train, y_test **=** train_test_split(X, Y, test_size**=**0.2, random_state**=**0)

基于训练数据构建决策树模型

clf **=** tree**.**DecisionTreeClassifier('gini', min_samples_leaf**=**30, random_state**=**0)
clf **=** clf**.**fit(X_train, y_train)

绘制决策树模型

**from** sklearn **import** tree *# for decision tree models*plt**.**figure(figsize **=** (20,16))
tree**.**plot_tree(clf, fontsize **=** 16,rounded **=** **True** , filled **=** **True**);

决策树模型—作者图片

使用分类报告评估模型。

report **=** classification_report(predTree, y_test)
print(report)

参考

关于 edX 的 MITx 分析课程

https://machinelearningmastery.com/classification-and-regression-trees-for-machine-learning/ https://blog.bigml.com/2016/09/28/logistic-regression-versus-decision-trees/

决策树

原文:https://towardsdatascience.com/decision-trees-14a48b55f297?source=collection_archive---------22-----------------------

机器学习中的分类树和回归树综述

西蒙·瑞在 Unsplash 上拍摄的照片

这篇文章将作为决策树的高级概述。它将涵盖决策树如何使用递归二进制分裂进行训练,以及使用信息增益****基尼指数进行特征选择。我还将调整超参数和修剪决策树进行优化。这篇文章中涉及的两个决策树算法是 CART(分类和回归树)ID3 (迭代二分法 3)。********

决策树在预测建模方面非常流行,并且执行分类和回归。决策树是高度可解释的,并且为更复杂的算法提供了基础,例如随机森林。

作者图片

决策树的结构可以被认为是一个 有向无环图一系列节点,其中每条边都是从前面指向后面的。这个图是单向流动的,任何对象都不能是自身的子对象。看一下上面的 DAG,我们可以看到它从一个根节点开始,最佳属性成为内部节点,即决策节点。然后,内部节点检查条件并执行决策,将样本空间一分为二。叶子节点代表一个分类,当记录到达叶子节点时,算法将分配相应叶子的标签。这个过程被称为样本空间 的递归 划分。使用决策树时的术语:

****Parent Node** - a node divided into sub-nodes**Child Node** - sub-nodes from a parent node**Root Node** - represents the sample space/population that will be split into two or more sets (sub-nodes)**Decision Node** - sub-node that splits into more sub-nodes

**Leaf Node** - nodes without splits (children)**Branch** - a subsection of a decision tree**Pruning** - reducing the size of a decision tree by removing nodes**

分割标准

凯文在 Unsplash悲伤的照片

决策树使用一些成本函数来选择最佳分割。我们试图找到在分类训练数据方面表现最佳的最佳属性/特征。重复该过程,直到到达叶节点,因此,被称为 递归二进制分割 。当执行这个过程时,所有的值被排列起来,树将测试不同的分割,并选择返回最低成本的一个,使这成为一个贪婪的方法。

需要注意的是,由于算法重复地将数据划分成更小的子集,最终的子集(叶节点)由很少或只有一个数据点组成。这导致算法具有 低偏差和高方差

熵和信息增益

决策树的一个广泛使用的度量是熵。以克劳德·香农命名的香农熵为我们提供了测量不确定性的方法。说到数据,熵告诉我们我们的数据有多乱。高熵值表示预测能力较低,可以将特征的熵视为该特征中的信息量。决策树在进行分割时最大化类的纯度,在叶节点中提供更清晰的类。熵是在每次分割前后计算的。如果熵增加,将尝试另一个分裂,或者树的分支将停止,即,当前树具有最低的熵。如果熵减小,分裂将被保持。计算整个数据集熵的公式:

其中 𝑛 是组的数量,( 𝑝𝑖 )是属于第 i 组的概率。假设我们有一个包含 462 个正(1)标签和 438 个负(0)标签的数据集。我们可以通过以下方式计算数据集的熵:

信息增益使用熵作为杂质的度量。这是分裂前后熵的差异,它会给我们一个不确定性减少了多少的数字。它也是 ID3 分类树算法中使用的关键标准。要计算信息增益:

基尼杂质

当执行分类任务时,使用基尼指数函数。来自 科拉多基尼 这个函数告诉我们树中的叶节点有多“纯”。基尼系数永远是一个从 0 到 0.5 的值,这个值越高,这个群体就越混乱。为了计算基尼系数:

其中( 𝑝𝑖 )是属于第 i 组的概率。上面的等式表明,基尼系数等于 1 减去每次分割中不同概率的总和。

修剪决策树

图片由 Shutterstock 上的 ueuaphoto 提供

当决策树通过执行递归二分分裂来训练时,我们也可以设置停止树的参数。决策树越复杂,就越容易过度拟合。我们可以通过使用超参数修剪来修剪树:

  • 最大深度 -决定我们希望树有多深
  • min_samples_leaf -每个叶节点中训练样本的最小数量
  • 最大叶节点数 -最大叶节点数
  • 最小 _ 杂质 _ 减少--阈值确定一个节点是否会分裂或变成一片叶子****

还有更多可以更改的参数,如需列表和更详细的解释,请查看 文档

带 Scikit 的决策树-学习

我们用 sklearn 搭建一个决策树分类器。我将使用 泰坦尼克号数据集 ,目标是Survived特征。我正在加载的数据集之前已经清理过了。有关数据集中要素的描述,请参阅下面的数据字典。

作者图片

导入必要的库

载入并预览数据集

定义预测器和目标特征,执行训练测试分割,预处理数据

训练决策树分类器

决策树分类器在训练集上的表现优于测试集,表明模型过拟合。决策树易于过度拟合,因为递归二进制分裂过程将持续到到达叶节点,导致模型过于复杂。这是我们执行超参数调整和修剪来优化分类器的地方。

标图树

为了直观地看到分割,绘制树可能是有帮助的。我们可以用一些额外的库来绘制树。

特征重要性

如果我们想要检查模型的 特征重要性 ,我们可以使用决策树分类器中的.feature_importances_属性。使用基尼系数计算特征重要性。

用网格搜索 cv 优化决策树分类器

通过运行交叉验证的网格搜索,我们可以输入包含决策树超参数的不同值的参数字典。我已经使用了上面提到的剪枝超参数和默认的 5 折交叉验证。

********

通过运行交叉验证的网格搜索,最佳参数改善了我们的偏差-方差权衡。具有默认参数的第一个模型在训练集上的表现比测试集好 20%,表明树中的低偏差和高方差。具有来自网格搜索的超参数集的决策树显示,从训练和测试集来看,方差降低了 5%。

用推车回归

执行回归任务的决策树也像分类一样将样本划分成更小的集合。回归树的目标是递归地划分样本空间,直到一个简单的回归模型能够适合单元。回归树中的叶节点是分区的单元。适合每个分区的简单回归模型取该分区因变量的平均值,即样本平均值用于进行预测。

我们使用上面的熵作为杂质的量度来进行分类。对于回归,CART 算法利用 均方误差 作为杂质的度量。

  • 𝐷𝑚 是节点 𝑚 中的训练子集
  • 𝑛𝑚 是节点 𝑚 的训练样本数
  • 𝑦𝑖 是第 i 个样本的目标值
  • 𝑦̂𝑚 是预测的目标值,样本的平均值

在评估模型的性能时,我们会着眼于【RMSE】。这就是误差平方平均值的平方根。通过求平方根,我们可以测量误差的大小,大误差的权重大于平均值。我们将用于评估模型拟合优度的指标是 R 平方 值。r 平方告诉我们因变量中方差的百分比,共同解释 (Frost 等人,2020)

CART 不仅可以用于回归。这里有一篇来自 Neptune.ai 的有趣文章,其中决策树用于检测时间序列数据中的异常值/异常。

使用 Scikit-Learn 的回归树

让我们继续用 sklearn 构建一个 决策树回归器。我将使用从 kaggle 中检索到的 Ames 房屋数据集 。出于本教程的目的,我将只使用 3 个连续特征和目标特征。

加载数据集,定义预测器和目标特征,并执行训练测试分割

训练决策树回归器

决策树再次过度适应训练集。与分类类似,我们可以运行交叉验证的网格搜索来优化决策树。

用网格搜索 cv 优化决策树回归器

****

通过使用决策树回归器运行交叉验证的网格搜索,我们提高了测试集的性能。使用 r 平方得分为.9998的默认参数,r 平方与基线决策树回归器的数据过度拟合。使用网格搜索的参数,我们将测试集的 r 平方从.42增加到.56。训练 r 平方为.58告诉我们,模型不会过度拟合训练数据,并将在看不见的测试集上类似地执行。

结论

决策树是很好的预测模型,可用于分类和回归。对于过多的机器学习问题,它们具有高度的可解释性和强大的功能。虽然分类和回归任务之间有许多相似之处,但理解每种任务使用的不同度量标准是很重要的。决策树的超参数有助于防止它们过度适应训练数据。需要注意的是,虽然执行网格搜索有助于找到决策树的最佳超参数,但是它们的计算开销也很大。根据所选的可能参数,您可能需要运行数小时甚至数天的网格搜索。

我希望这篇文章有助于更好地理解回归和分类树。如果有任何遗漏或我可以解释得更清楚的地方,请随时留下反馈!非常感谢你花时间查看这篇文章。

资源

决策树和随机森林——用 Python 实现来解释。

原文:https://towardsdatascience.com/decision-trees-and-random-forests-explained-with-python-implementation-e5ede021a000?source=collection_archive---------8-----------------------

在本文中,我将带您了解决策树和随机森林算法的基本工作原理。我还将借助一个例子展示它们是如何在 Python 中实现的。

照片鸣谢——菲利普·塞尔纳克在 Unsplash 上

决策树是一种受监督的机器学习算法,它模仿人类的思维过程。它会做出预测,就像现实生活中人类大脑会做的那样。它可以被认为是一系列 if-then-else 语句,随着它的增长,它会在每个点上继续做出决策或预测。

决策树看起来像流程图或倒置的树。它从根长到叶,但方向颠倒。由于决策树的结构,我们可以很容易地解释决策树的决策/预测过程。

典型的二叉分裂决策树

起始节点被称为根节点。它通过基于某种标准做出决策而进一步分裂成所谓的内部节点。进一步分裂的内部节点称为父节点,由父节点形成的节点称为子节点。不再分裂的节点被称为叶节点

根据目标变量的类型,决策树可以是分类树或回归树。在分类树的情况下,类别基于叶节点中的多数预测。在回归的情况下,最终预测值基于叶节点中的平均值。

根据是二分分裂还是多路分裂,有各种决策树算法。二进制拆分意味着父节点拆分成两个子节点,而在多路拆分中,父节点拆分成两个以上的子节点。

CART 意为分类和回归树算法处理二叉分裂树,而 ID3 算法处理多路分裂树。我们将详细讨论 CART 算法。(以下决策树是指 CART 算法树)

决策树将数据分成不同的子集,然后根据选择的属性进行拆分。该属性是根据称为基尼指数的同质性标准选择的。

基尼指数,基本上测量分裂发生后节点的纯度(或杂质,我们可以说)。也就是说,它是分割后子节点与父节点的纯度的度量。

树应该基于导致子节点最大同质性的属性进行分裂。基尼指数的公式如下:

其中 p i 是找到带有标签 i 的点的概率, n 是目标变量的类数/结果值。

因此,该树在父节点计算基尼指数。然后为每个属性计算子节点的加权基尼指数。选择一个属性,使得我们在子节点中获得最大的同质性,并且执行分割。重复这个过程,直到所有属性都用尽。最后,我们得到了我们称之为完全成长的决策树。因此,导致初始分裂的属性可以被认为是预测的最重要的属性。

一个完全成长的决策树的问题是,它过拟合。这意味着它吸收了所有的训练数据,无法进行归纳,导致测试数据的性能很差。为了解决这个问题并从决策树中获得最大的效率,我们需要修剪完全成长的树或者截断它的成长。

修剪是一种技术,我们可以修剪完全生长的树的不太重要的分支,而截断是一种技术,我们控制树的生长,以避免过度拟合。

截断更常用,它是通过调整树的超参数来实现的,这将在示例中讨论。

总的来说,决策树是高效的算法,不需要或只需要最少的数据处理。它们可以有效地处理线性和非线性数据、分类或数字数据,并根据给定的属性集进行预测。最重要的是,它们很容易解释。

决策树的一些缺点是,它们过拟合。数据的微小变化可能会改变整个树结构,这使得它们成为高方差算法。基尼系数的计算使它们变得复杂,并且消耗大量的时间和内存。此外,它们可以被称为贪婪算法,因为它们只考虑直接分割的影响,而不考虑进一步分割的影响。

随机森林

各种模型(线性回归、逻辑回归、决策树等)的组合。)集合在一起作为单个模型以实现最终结果,称为系综。因此,在系综中,不同的模型被视为一个整体,而不是分开的。

随机森林是用大量决策树构建的强大集成模型。它克服了单一决策树的缺点以及其他一些优点。但这并不意味着它总是比决策树好。在某些情况下,决策树可能比随机林表现得更好。

集合以这样一种方式起作用,即集合中的每个模型都有助于补偿每个其他模型的缺点。我们可以说,如果一个随机的森林由 10 棵决策树组成,每棵树可能在处理数据时表现不佳,但是强壮的树有助于填补虚弱的树的空白。这就是为什么集成是一个强大的机器学习模型。

随机森林中的单棵树必须满足两个标准:

  1. 多样性:意味着集合中的每一个模型都应该独立运行,并且应该与其他模型互补。
  2. 可接受性:这意味着集合中的每个模型都应该至少比随机猜测的模型表现得更好。

Bagging 是一种常用的集成技术,用于实现分集准则。装袋台代表Bo 带 Agg regation。自举是一种用于创建自举样本的方法。这些样本是通过对给定数据进行均匀采样并替换而创建的。引导样本包含整个数据集中大约 30%–70%的数据。创建统一长度的自举样本,并将其作为输入提供给随机森林模型中的各个决策树。然后将所有单个模型的结果汇总以得出最终决策。

典型的随机森林分类器

此外,并不是所有的特征都用来训练每一棵树。在每棵树的每个节点上选择固定数量的随机特征集。这确保了不同树的功能之间没有相关性,并且它们独立地起作用。

在随机森林分类器中,由单个树预测的多数类被认为是最终预测,而在随机森林回归器中,所有单个预测值的平均值被认为是最终预测。

在随机森林模型中,通常不会将数据分为训练集和测试集。整个数据用于形成自举样本,从而总是留出一组数据点来形成各个树的测试或验证集。这些样品被称为非袋装(OOB) 样品。因此,对于随机森林集合中的每棵树,存在一组在其训练数据中不存在的数据点,并被用作评估其性能的验证集。

OOB 误差计算为 OOB 样本中不正确预测数与 OOB 样本预测总数的比率。

随机森林还通过消除不太重要的特征/属性,帮助确定给定数据中所有特征中的重要特征。这导致更好的预测结果。借助基尼系数计算,通过计算杂质的减少或纯度的增加来确定特征的重要性。

随机森林相对于决策树的主要优势在于它们是稳定的,并且是低方差模型。它们还克服了决策树中存在的过拟合问题。由于它们使用引导数据和随机的功能集,因此确保了多样性和稳健的性能。它们不受维数灾难的影响,因为它们不会同时考虑单个树的所有特征。

随机森林的主要缺点是缺乏可解释性。与决策树不同,我们无法追踪算法是如何工作的。另一个缺点是它们复杂且计算量大。

现在让我们在电信客户流失数据集的帮助下,看看决策树和随机森林模型的 python 实现。

Python 实现

对于电信运营商来说,留住高利润的客户是头号业务目标。电信行业平均每年经历 15–25%的流失率。我们将分析一家领先电信公司的客户数据,建立预测模型来识别高流失风险的客户,并识别流失的主要指标。

该数据集包含连续四个月(六月、七月、八月和九月)的客户级别信息。月份分别编码为 6、7、8 和 9。我们需要使用前三个月的数据(特征)来预测最后一个月(即第九个月)的客户流失。

分析流程:

1.导入所需的库
2。阅读并理解数据
3。数据清理和准备
4。筛选高价值客户
5。流失分析
6。探索性数据分析
7。模型建筑
8。模型构建—超参数调整
9。最佳模特

导入所需的库。当需要的时候,我们会从不同的库加载更多的包。

数据被载入 pandas 数据框架并进行分析。

最初的分析告诉我们,该数据有 99999 行和 226 列。有许多需要估算或删除的缺失值。

大部分空值超过 30%的列被删除,对于其他列,空值被适当地估算为平均值/中值/众数。最后,我们有 99999 行和 185 列的数据集。

由于大部分收入来自高价值客户,我们相应地过滤数据,得到一个 30011 行 185 列的数据集。

我们为这些客户执行探索性数据分析(EDA)。

流失分析

我们可以看到 91.4%的客户是非流失客户,只有 8.6%的客户是流失客户。所以这是一个不平衡的数据集。以下是来自 EDA 的一些分析图。

电信公司网络内的 std 呼入使用分钟数

流失和非流失的漫游呼入分钟数

流失和非流失的本地传入使用分钟数

我们将数据分为训练集和测试集,并将流失变量分离为 y、因变量,其余特征为自变量 X、

我们需要处理阶级不平衡,因为我们建立的每一个模型在多数阶级中都有好的表现,而在少数阶级中表现最差。我们可以通过平衡类来处理不平衡的类。意味着增加少数或减少多数阶级。

有以下各种类别不平衡处理技术:

  1. 随机欠采样
  2. 随机过采样
  3. SMOTE——合成少数过采样技术
  4. ADASYN——自适应合成采样方法
  5. smetomek—过采样后欠采样

我们用逻辑回归、决策树和随机森林模型实现了所有的技术。我们需要专注于那些能给我们带来高灵敏度/高召回率的模型。结果如下:

各种模型的评估指标比较

正如我们在汇总表中看到的那样,对于随机欠采样的随机森林、随机欠采样的逻辑回归、随机过采样、SMOTE、ADASYN、SMOTE+TOMEK,我们的召回值很高。在逻辑回归中,ADASYN 的回忆率最高。

我们将使用欠采样方法选取随机森林进行进一步分析。

我们知道随机森林通过消除不太重要的特征来赋予我们特征的重要性。我们运行随机森林分类器并选择重要特征:

我们使用 GridSearchCV 对随机森林欠采样模型进行超参数调整。对于决策树分类器,超参数的调整是类似的。对于基本模型,我们只需要用决策树分类器替换随机森林分类器。

我们得到以下最佳分数和最佳模型。

[**GridSearchCV**](https://scikit-learn.org/stable/modules/generated/sklearn.model_selection.GridSearchCV.html#sklearn.model_selection.GridSearchCV)提供的网格搜索从由param_grid参数指定的参数值网格中详尽地生成候选值。这个过程在计算上是昂贵和耗时的,尤其是在大的超参数空间上。

还有另一种方法叫做 RandomizedSearchCV 来寻找最佳模型。这里,从指定的概率分布中采样固定数量的超参数。这提高了流程的时间效率,降低了模型的复杂性。

我们得到以下最佳分数和最佳模型。

通过比较上述模型得到的分数和复杂度,我们得出结论,使用 RandomizedSearchCV 得到的模型是最好的模型。

我们对测试集进行预测,得到如下结果。

我们得到了 81%的召回率和 85%的准确率。以下是客户流失的 10 大重要预测指标。

这就完成了我们的分析。希望这篇文章内容丰富,易于理解。此外,我希望您喜欢分析分析中包含的彩色图表。

请随意评论并给出您的反馈。

可以在领英上联系我:https://www.linkedin.com/in/pathakpuja/

请访问我的 GitHub 个人资料获取 python 代码。文中提到的代码,以及图表,可以在这里找到:https://github.com/pujappathak

参考文献:

https://sci kit-learn . org/0.16/modules/generated/sk learn . grid _ search。RandomizedSearchCV.html

https://sci kit-learn . org/stable/modules/generated/sk learn . model _ selection。GridSearchCV.html

TigerGraph 中的决策树

原文:https://towardsdatascience.com/decision-trees-in-tigergraph-5eb47868a91a?source=collection_archive---------27-----------------------

在你的数据库中进行 ML 分类

介绍

我在 Optum 工作期间,3 个趋势非常重要——可解释的机器学习模型、知识图数据表示和这些知识图中规则的执行。结合这些趋势,我创建了一个在 TigerGraph 实例中执行决策树的方法。

数据源-银行数据集

数据来自托管在 Kaggle 上的一个数据集,在这里找到:https://www . ka ggle . com/prakharrathi 25/banking-dataset-marketing-targets。鼓励通读 Kaggle 页面上的数据集信息,但如果给定的客户要使用银行产品,数据集是一个二进制分类问题。为了训练决策树,我们只使用数据集中的分类变量,因为这些变量可以很容易地建模为我们的 TigerGraph 模式中的顶点。

将数据帧输入决策树(图片由作者提供)

决策图表

决策树是一个机器学习模型,其中的节点被组织成一个树结构,其中每个节点都是一个条件语句,比如检查一个数据点的属性是否存在。这些树被训练成使用最少数量的条件来分类数据点。决策树很容易解释,因为每个节点在其条件表达式中都有明确的含义,说明它要测试什么特性。决策树分类的这种可解释性使其区别于其他机器学习模型类型,如深度神经网络。

为了训练决策树,我们在 Python Jupyter 笔记本中使用 sklearn,仅使用上述分类变量。使用最大深度 7,我们实现了 89%的准确性(注意数据集是不平衡的,所以这不是最好的度量,但目前满足我们的目的)。下面是输出的树:

经过训练的决策树(图片由作者提供)

一旦对决策树进行了训练,就构建了一个熊猫数据帧,它由决策树中每个节点之间的边组成,最终将被插入到我们的 TigerGraph 实例中。

老虎图

数据在 TigerGraph 中建模,每个结果(签署或拒绝银行产品)以及每个个体和分类属性都是一个顶点类型。此外,还引入了一个“子规则”顶点,它为决策树中的每个节点建模。这些顶点类型中的每一种都通过模式定义的一系列边相互连接,如下图所示:

TigerGraph 模式(图片由作者提供)

定义了两个加载脚本,将数据和决策树加载到用 pyTigerGraph 编写的 TigerGraph 实例中。运行这些脚本后,我们可以看到图表中有多少数据:

数据已加载(图片由作者提供)

老虎图中的累加器

根据 TigerGraph 文档,“累加器是特殊类型的变量,在遍历和探索过程中累加关于图的信息。”累加器可以是全局局部,其中局部累加器绑定到每个单独的顶点,全局累加器是图形范围的。GSQL 的这一元素使得代码非常紧凑,易于理解。更多信息,请查看 TigerGraph 文档

遍历查询

遍历决策树并进行分类的查询使用多个累加器。首先,给定图中的个人,我们通过遍历图来收集他们的所有属性。从这些属性中,我们可以通过简单地从属性遍历到子规则来了解哪些子规则适用于这些属性。然后给每个子规则分配一个连续计数,看它以前是否被遍历过。由于决策树对“与”和“非”操作进行操作,因此通过检查子规则被触及的次数,子规则被反复过滤为有效规则,直到达到分类。

分类查询(按作者分类的图片)

由于累加器和图形结构的强大功能,分类查询非常简单和紧凑(大约 30 行代码),尤其是与具有大约 10k 行代码的其他规则引擎相比。由于规则是在图中定义的,并且分类是通过遍历图中的边来进行的,因此性能比传统的规则引擎(例如基于 SQL 和 Drools 的规则引擎)高得多,因为 TigerGraph 通常可以在每个执行线程中每秒遍历大约 200 万条边。

此外,我们可以探索 GUI 可视化工具 TigerGraph GraphStudio 中的决策树,以帮助理解为什么要对个人进行分类。

TigerGraph 中决策树的摘录(图片由作者提供)

结论

这种设置将允许用户在 TigerGraph 内部运行可解释的机器学习模型,他们的数据就驻留在那里。许多不同的业务流程,比如索赔裁决,可以表示为决策树,并且可以在知识图中执行。可以做更多的工作来训练 TigerGraph 中的决策树模型,消除将数据移入和移出实例的需要。所有代码都可以在这里找到:https://github.com/parkererickson/tigergraphDecisionTree

决策树——机器学习算法及其 Python 实现

原文:https://towardsdatascience.com/decision-trees-machine-learning-algorithms-with-implementation-in-python-5bc034e67fc8?source=collection_archive---------31-----------------------

机器学习算法— 30 天挑战

在本文中,我们将研究决策树以及如何使用 Python (Scikit-learn)实现它们

在本文中,我们将研究决策树,这是你的 ML 算法工具箱中的另一个基本而重要的机器学习算法。

图片来自 Unsplash

我们将从了解它的功能和工作原理开始。我们将不研究数学部分,因为它本身是另一篇文章。然后我们将使用scikit-learn来实现它

  • 什么是决策树
  • Python 实现(虚拟数据)
  • Python 实现(真实世界数据集)
  • 绘制决策树
  • 应用程序
  • 结论
  • 你能做什么
  • 其他 ML 算法

这是我 30 天文章写作挑战的一部分。请随意查看我的新人帖子上的文章:

https://nouman10.medium.com/lets-publish-30-articles-in-30-days-a0b8111855bb

什么是决策树

决策树是一种用于分类和回归目的的机器学习算法(尽管在本文中,我们将专注于分类)。顾名思义,它的行为就像一棵树。

它在条件的基础上起作用。每个条件都将训练数据分成两个或更多个较小的训练数据集。

例如,如果我们构建一个应用程序来决定一个人的贷款申请是否应该被接受。我们可以从检查申请人的信用评分开始。如果低于某个阈值,我们拒绝申请。否则,我们会检查其他内容,直到所有内容都检查完毕,然后我们接受申请。

这方面的一个例子如下:

图片来自 Madhu Sanjeevi ( Mady )

Python 实现(虚拟数据)

让我们从在一些虚拟数据上实现决策树开始。

我们首先从scikit-learn导入tree模块,并初始化虚拟数据和分类器。我们将分类器与数据相匹配,并使用一些新数据进行预测。分类器预测新数据为 1。让我们使用tree模块中内置的plot_tree来绘图

tree.plot_tree(clf)

这将绘制以下树:

作者图片

在根节点,我们有 5 个样本。它检查 X 中的第一个值,如果它小于或等于 0.5,它将样本分类为 0。如果不是,那么它检查 X 中的第一个值是否小于或等于 1.5,在这种情况下,它给它分配标签 1 ,否则为 2。

请注意,决策树不包括对 x 中第二个值的任何检查。这不是错误,因为在这种情况下不需要第二个值。如果决策树能够在不需要所有特征的情况下进行所有分类,那么它可以忽略其他特征。

Python 实现(真实世界数据集)

现在让我们使用iris数据集来实现它。代码同上,除了我们使用scikit-learn加载iris数据集

在这种情况下,准确率为 100%,因为决策树能够构建一个对所有训练数据进行准确分类的树。

这里我们不会使用内置的plot_tree函数来绘制树。在下一节中,我们将使用graphviz来绘制决策树。

绘制决策树

让我们使用graphviz为上面的分类器绘制树。

graphviz允许我们创建一个更加美观的决策树,即使是非技术人员也能容易理解,因为他们以前从未听说过决策树。

我们将使用以下代码来绘制决策树:

我们从tree模块中调用export_graphviz函数,并赋予它特性和类名。我们甚至可以将树保存到一个文件中,但是在本例中我们没有这样做。这是上面代码的输出:

作者图片

看看如何轻松解读决策树

应用程序

  • 决策树的应用之一是根据历史数据评估业务的潜在增长机会。
  • 决策树的另一个应用是使用人口统计数据来寻找潜在客户。
  • 贷方还使用决策树来预测客户拖欠贷款的概率,通过使用客户过去的数据应用预测模型生成。

结论

让我们总结一下本文所做的工作:

  • 我们从决策树如何工作的一般解释开始
  • 然后,我们用 Python 在一些虚拟数据上实现了它,随后在一个数据集上实现了它
  • 然后我们绘制了使用scikit-learn构建的决策树
  • 最后,我们研究了决策树的应用。

您可以做什么:

  • 尝试从头开始实现决策树。为此,你需要理解决策树背后的数学原理
  • 将您的实现与scikit-learn中的实现进行比较
  • 在各种其他数据集上测试上面的代码。

如果你有任何问题,请随时联系我。请继续关注我,因为我计划在未来讲述更多的机器学习算法

其他 ML 算法:

  • 线性回归——用 Python 实现的机器学习算法

https://medium.com/mlearning-ai/linear-regression-a-to-z-2ab3d1b7277c

  • k-最近邻——机器学习算法及其 Python 实现

https://nouman10.medium.com/k-nearest-neighbors-a-to-z-with-implementation-in-python-74630ffb79a2

  • k-Means-机器学习算法及其在 Python 中的实现

如果您觉得以上内容对您有用,请分享并随时支持我-->

引擎盖下的决策树:划分数据

原文:https://towardsdatascience.com/decision-trees-under-the-hood-partitioning-data-b8b3922f5738?source=collection_archive---------24-----------------------

决策树如何为类和数值预测拆分数据

里卡多·戈麦斯·安吉尔在 Unsplash 上的照片

人类总是用“如果”来做二元决策..然后..否则..”决策过程的结构。如果下雨,带把伞;如果它能飞,它就是一只鸟;如果这只鸟听起来嘎嘎叫,那它就是一只鸭子;如果动物有四条腿…我们需要更多的信息,那里有许多四条腿的动物。

决策树使用相关特征(也称为变量)以类似的方式重复分割数据。

让我们以两种四条腿的动物——狗和猫为例。闭着眼睛,有人可以根据猫和狗独特的(看不见的)特征,如体重和声音,来区分它们。

假设你在用体重:体重高于 10 公斤的是狗,低于 10 公斤的是猫。但是你可以想象,有些狗和猫不能仅仅通过体重来区分,因为有些狗可能太小,有些猫可能太大。在这些情况下,你可以使用另一个特征:它们听起来像什么——喵还是汪?这一特征清楚地区分了剩下的不能单独用体重来区分的动物。

现在,如果我给你带来一种新动物,让你闭上眼睛猜它是狗还是猫,你首先会问它的重量是否大于 10 公斤。如果是,那么你很确定这是一只狗,但是为了进一步确认,你问了第二个问题:它听起来像什么——喵还是汪?

但是如果你改变特征的顺序,先问动物听起来像什么呢?狗不会说“喵”,猫也不会发出“汪”的声音。这意味着如果你使用声音作为区别特征,你可以 100%正确地区分两只动物,而不用询问体重或任何其他变量。

这说明有些特性比其他特性更重要。决策树根据哪个功能最能分割数据来决定先问哪个问题。

总之,本例中有三个关键信息:

(1)您可以基于数字阈值(例如>或< 10 千克体重)或分类特征(例如喵或汪汪)来分割数据;

(2)一些变量比其他变量更重要(在这个例子中,声音比体重更重要);

(3)有些数据因为特征鲜明(蜥蜴不会飞,所以容易拆分(比如鸟类 vs 蜥蜴!)还有一些比较难。也就是说,两组之间的差异越大(即不同的特征),就越容易将它们分开。

基础知识说完了,现在让我们进入技术细节。

决策树是如何工作的?

在引擎盖下,决策树工作流程从选择分割数据的最佳特征开始。然后,使用上一节中描述的阈值或分类特征对数据进行分区。

完成第一次划分后,生成的树的深度为1。如果存在不同类别混合的剩余数据(即,不能仅通过重量区分的狗和猫的混合),则使用下一个最佳特征进行第二次分割。

这个过程基本上是重复的,直到所有的数据都被清楚地分开,或者你用完了所有的特性。如果所有样本数据被清楚地分成各自的目标类别(例如,所有动物被分成猫和狗),则一些特征可能保持不被使用;并非所有功能都是必需的。

生长的树现在是代表数据(也称为训练数据)的模型。对于一个新的预测,您所做的就是通过您刚刚创建的决策树逐个运行观察的特征。

那么数据到底是如何分区的呢?

让我们先来理解一个我们会反复使用的关键术语——“杂质”。

如果一个要素正确地分隔了数据集中的两个类,这就是纯分割。在我们的例子中,如果动物的声音可以将所有的狗和所有的猫分开,那么得到的分割数据就是纯净的。但是,如果动物体重能够正确分离 90%的数据,就意味着 10%的数据有猫狗混杂。所以他们不纯洁。随着深度的增加,决策树算法将这种杂质最小化。

在分类中,有两个标准用于分割数据:基尼系数和熵。

a)基尼系数不纯

基尼系数衡量样本中错误阶层的比例。因此,基尼系数为 0.5 意味着所得数据中两个阶层的比例相等(50%-50%)——这是衡量杂质的最高标准。同样,基尼系数为 0.0 意味着一个阶级的情况为 0%,而另一个阶级的情况为 100%。基尼系数的值介于 0 和 0.5 之间,其中 0 表示绝对纯分裂,0.5 表示最差的不纯分裂。

基尼系数的数学表达式是:

这里 j 代表目标类(猫或狗),p 是节点中类的比例(狗的数量和猫的数量)。(图片由作者提供)

因此,在 100 只动物的样本中,如果不纯节点有 60 只狗和 40 只猫,那么基尼不纯将是:

Gini = 1 - {(60/100)^2 + (40/100)^2} = 0.48

b)熵/信息增益

术语大概来源于物理学(热力学第二定律);它是系统的物理属性,用来衡量无序状态。在信息论中,( Claude Shannon)设计了这个概念来测量从消息传输到接收的丢失信息量。

它的数学公式是:

熵的数学公式。(图片由作者提供)

符号的含义与基尼中的相同。然而,熵的值介于 0-1 之间。

上述相同数据的熵可计算如下:

Entropy = - {(60/100)*log2(0.6) + (40/100)*log2(0.4)} 
= 0.52

请注意,分类特征使用每个类别分割目标,而数字/连续特征的分割候选是特征中的唯一值。有时,算法首先对值进行排序,然后选择每个唯一值进行拆分,以找到最佳拆分。

那么如何从测量杂质到决定分裂(或不分裂)?

我们已经看到了决策树如何在幕后工作,以及算法如何选择使用杂质标准来分割数据。现在,我们如何从测量杂质转向决定:

(a)是否要进一步分裂

(b)使用哪个特征进行分割

杂质测量用于计算所谓的信息增益。它是分割前后杂质的差异,由每个节点中各自的样本大小加权。如果分裂后杂质减少,信息增益应该为正,因此算法将继续进一步分裂数据。本质上:

Information gain 
= Information in the parent node 
  – information in the left child node 
  – information in the right child node

在用于计算的数学公式中:

Information gain 
= (parent_sample*parent_gini 
   - left_sample*left_gini 
   - right_sample*right_gini)/parent_sample

让我们用下面的假设例子,用上面的公式计算信息增益:

计算信息增益的决策树。(图片由作者提供)

# data
parent_sample, parent_gini = 212, 0.496
left_sample, left_gini = 99, 0.367
right_sample, right_gini = 113, 0.314# information gain calculation
= (212*0.496 - 99*0.367 - 113*0.314)/212
= 0.15725

所以在假设的例子中,第一次分离后的信息增益是 0.15。如果进一步的分裂将继续给出所需的信息增益,树将继续分裂,除非您通过超参数调整来限制它的增长以避免过度拟合。

回归呢?

在回归中,方差是代替杂质的度量。它衡量数据相对于平均值的可变性。自然地,较大的方差意味着数据点是分散的,远离平均值并且彼此远离。

它的数学公式是:

计算回归中的方差。(图片由作者提供)

旁注:如果你听说过标准差,那只是方差的平方根。

类似于分类,选择用于分类和数字特征的分裂候选。分割完成后,算法会比较分割前后的方差,只要方差减小,分割就会继续。

摘要

  • 决策树根据数据的特征和算法对数据进行分割,只要杂质减少,分割就会继续。
  • 计算杂质有两种主要方法:基尼&熵。
  • 分类特征和数字特征的分裂候选被不同地选择——对于分类特征:每个类别;对于数字特征:每个唯一值。
  • 只要信息增益是有利的,所有特征都用尽或者树的生长通过修剪被限制,分割就继续。
  • 回归树使用方差作为决定是否划分数据的度量。

感谢阅读。请随意订阅以获得我即将发布的文章的通知,或者通过 TwitterLinkedIn 与我联系。

解码以太坊智能合约数据

原文:https://towardsdatascience.com/decoding-ethereum-smart-contract-data-eed513a65f76?source=collection_archive---------1-----------------------

加密数据实践—第 1 部分

Web2 - > Web3 演变 —图片作者

2023–03–14 编辑 : 增加了对节点提供商角色的简要说明

在本系列的前两篇文章中,我描述了什么是加密数据为什么它是一个独特而有吸引力的机会。如果你还没有阅读这些文章,我强烈建议你在继续之前阅读,因为它们为理解这篇文章提供了重要的背景。在本帖中,我们将亲自动手,讨论将以太坊智能合约数据解码为人类可读格式的技术细节。这是深入理解潜在用户活动的必要的第一步。我们将重点关注以太坊作为主要示例,但我们在此讨论的许多概念将更广泛地适用于所有 EVM 兼容链和智能合约,例如 Polygon、BSC、乐观等。

正如我们在以前的帖子中所讨论的,智能合约事务类似于智能合约支持的 web3 应用程序中的后端 API 调用。每个智能合约事务的详细信息以及导致的应用程序状态更改都记录在称为事务、调用和日志的数据元素中。事务数据元素表示由用户(或者更准确地说是 EOA)发起的函数调用,调用数据元素表示由智能合约在事务内发起的附加函数调用,日志数据元素表示在事务执行期间已经发生的事件。

需要注意的一件重要事情是,为了与智能合约交互并使用上面提到的数据元素,您需要通过一个节点。节点是运行构成网络的区块链软件的参与者,它们充当通往区块链的网关。通常,访问节点的最快方式是通过节点提供者,如 Alchemy、Infura 或 Quicknode。如果你有兴趣了解更多,这篇炼金术博客文章提供了一个关于节点以及如何使用它们的很好的解释。

一旦有了数据元素,我们就可以非常精确地描述由于事务而在应用程序和区块链上发生的状态变化。当进行总体分析时,给定的分散式 web3 应用程序的所有事务、跟踪和日志的集合可以提供用户群及其在产品中的活动的全面而深刻的视图。然而,这样做很有挑战性,因为许多重要的细节都是以十六进制编码的字符串记录的。例如,在以太坊网络上使用 Uniswap 交换一对令牌的交易(该特定记录可以通过查询谷歌在以太坊上的公共数据集中的transactions表获得,也可以在以太坊上查看):

hash: 0x87a3bc85da972583e22da329aa109ea0db57c54a2eee359b2ed12597f5cb1a64
nonce: 449
transaction_index: 37
from_address: 0x3c02cebb49f6e8f1fc96158099ffa064bbfee38b
to_address: 0x7a250d5630b4cf539739df2c5dacb4c659f2488d
value: 0E-9
gas: 228630
gas_price: 91754307665
**input: 0x38ed1739000000000000000000000000000000000000000000000000000000009502f900000000000000000000000000000000000000000000a07e38bf71936cbe39594100000000000000000000000000000000000000000000000000000000000000a00000000000000000000000003c02cebb49f6e8f1fc96158099ffa064bbfee38b00000000000000000000000000000000000000000000000000000000616e11230000000000000000000000000000000000000000000000000000000000000003000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000528b3e98c63ce21c6f680b713918e0f89dfae555**
receipt_cumulative_gas_used: 2119514
receipt_gas_used: 192609
receipt_contract_address: None
receipt_root: None
receipt_status: 1
block_timestamp: 2021–10–19 00:00:18
block_number: 13444845
block_hash: 0xe9ea4fc0ef9a13b1e403e68e3ff94bc94e472132528fe8f07ade422b84a43afc
max_fee_per_gas: None
max_priority_fee_per_gas: None
transaction_type: None
receipt_effective_gas_price: 91754307665

如果您在 Etherscan 上查看交易,您可能会注意到,它已经解码了这个原始记录,并提供了很好的上下文来帮助您理解交易细节。虽然这非常有用,但它并不是为了回答需要转换和汇总数据的问题而设计的,例如,所有 Uniswap 用户交易的总价值是多少,或者 Uniswap 用户的 3 个月保留期是多少。要回答这些问题,我们需要能够收集所有记录,解码它们,并批量处理相关细节。我们将在这篇文章的剩余部分讨论如何做到这一点。

解码交易

如果我们检查原始数据记录,我们可以看到交易是由 EOA0x3c02cebb49f6e8f1fc96158099ffa064bbfee38b发起的,目的地是与 Uniswap v2 路由器关联的智能合同地址0x7a250d5630b4cf539739df2c5dacb4c659f2488d。然而,相关的请求细节在input字段中被编码为一个长的十六进制字符串。

在我们进入如何从input中提取人类可读的数据之前,讨论一下它的结构将是有益的。前面的0x表示这个字符串是十六进制的,所以它与实际的信息内容无关。之后,每 2 个十六进制字符代表一个字节。前四个字节,在本例中是38ed1739,是被调用函数的散列签名。其余的字节是传递给函数的参数的散列。这意味着输入字符串的长度可以根据调用的特定函数和所需的参数而变化。

为了解码这个十六进制字符串,我们需要参考应用程序二进制接口或 ABI。这是一个 json 对象,包含给定智能契约的所有函数和事件接口定义(即名称和类型)。ABI 的功能是查找事务数据中的散列签名与人类可读接口定义的匹配。一个的例子 ABI 看起来像这样

Uniswap v2 路由器 ABI 的局部视图—图片由作者提供

ABI 通常可以在 Etherscan 等块浏览器上找到,与合同源代码放在一起。这里是 Uniswap v2 路由器合同的 ABI 的链接。

一旦我们手头有了 ABI,我们就可以写来解码交易:

在示例代码中需要注意一些事情:

  1. 此代码旨在用于大量事务的批处理。它假设数据已经存在于本地存储中(而不是从区块链中实时获取),并且非常适合像 PySpark 这样的分布式处理框架。
  2. @lru_cache(maxsize=None) —我们缓存契约对象的创建,以减少在大量事务中重复相同计算的开销。这假设解码的目标是少量(大约几千个)不同的智能合约。
  3. 它利用开源的 web3 包方法decode_function_input根据 ABI 提供的模板提取数据。然而,这种方法返回的数据通常是不可序列化的(例如字节数组),有时还会缺少人类可读的键。因此,使用实用方法convert_to_hex来执行提取后处理,将数据转换成可序列化的 json 对象,并在缺少的地方附加上人类可以理解的键,这是非常有帮助的(甚至是必要的)。这使得保存和重用解码后的数据变得更加容易。
  4. 同样的代码也可以用于解码跟踪数据元素。这是因为它们只是由智能合约发起的内部交易。

使用上面的代码产生这个解码的输入数据

function called:  swapExactTokensForTokens
arguments:  {
  "amountIn": 2500000000,
  "amountOutMin": 194024196127819599854524737,
  "path": [
    "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
    "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
    "0x528B3e98c63cE21C6f680b713918E0F89DfaE555"
  ],
  "to": "0x3c02cebB49F6e8f1FC96158099fFA064bBfeE38B",
  "deadline": 1634603299
}

由此我们可以更容易理解

  1. 这个调用是对一个名为swapExactTokensForTokens的方法的调用,用户放入 2,500,000,000 个单位的起始令牌,并期望得到至少 194,024,196,127,819,599,854,524,737 个单位的目标令牌。这些数字看起来可能是天文数字,但请记住,令牌单元通常用 1/10^n 表示,其中 n 大约是 18。n 有时被称为令牌的十进制值。
  2. path数组描述了在这个事务中交换的令牌。每个数组元素都是一个令牌协定的地址。第一个是 USDC (一种与美元挂钩的稳定币),第二个是包裹 Eth (带有 ERC20 接口的以太坊),第三个是 DXO (一种 deep.space 游戏内币)。
  3. 将 1 和 2 放在一起,我们可以推断出用户请求是用 2,500 USDC (USDC 的十进制值为 6)交换~ 1 . 94 亿 DXO (DXO 的十进制值为 18)。由于这种特定的成对互换不是直接可用的,所以交易将通过 weh 的中介令牌来进行。

解码日志

这个交易在执行过程中还发出了 7 个事件,可以通过查询谷歌在以太坊上的公共数据集中的logs表得到,也可以在以太扫描上查看。与用户请求的交换相对应的两个最突出的记录是:

log_index: 47
transaction_hash: 0x87a3bc85da972583e22da329aa109ea0db57c54a2eee359b2ed12597f5cb1a64
transaction_index: 37
**address: 0xb4e16d0168e52d35cacd2c6185b44281ec28c9dc**
**data: 0x000000000000000000000000000000000000000000000000000000009502f90000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000093f8f932b016b1c
topics: [
'0xd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d822',
'0x0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d',
'0x000000000000000000000000242301fa62f0de9e3842a5fb4c0cdca67e3a2fab']**
block_timestamp: 2021-10-19 00:00:18
block_number: 13444845
block_hash: 0xe9ea4fc0ef9a13b1e403e68e3ff94bc94e472132528fe8f07ade422b84a43afc

log_index: 50
transaction_hash: 0x87a3bc85da972583e22da329aa109ea0db57c54a2eee359b2ed12597f5cb1a64
transaction_index: 37
**address: 0x242301fa62f0de9e3842a5fb4c0cdca67e3a2fab
data: 0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000093f8f932b016b1c000000000000000000000000000000000000000000a137bb41b9113069a51e190000000000000000000000000000000000000000000000000000000000000000
topics: [
'0xd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d822', '0x0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d', '0x0000000000000000000000003c02cebb49f6e8f1fc96158099ffa064bbfee38b']**
block_timestamp: 2021-10-19 00:00:18
block_number: 13444845
block_hash: 0xe9ea4fc0ef9a13b1e403e68e3ff94bc94e472132528fe8f07ade422b84a43afc

同样,相关的细节在topicsdata字段中被编码成十六进制字符串。与交易input的情况一样,浏览这些数据字段的结构是有益的。topics是一个数组,其中第一个元素表示事件接口定义的散列签名。topics数组中的任何附加元素通常是事件中涉及的区块链地址,根据具体的上下文,它们可能存在,也可能不存在。data代表事件参数值,长度可根据事件定义而变化。与交易一样,我们需要引用 ABI 契约,以便将它转换成人类可读的形式。

敏锐的读者会注意到,上面日志中的契约地址0xb4e16d0168e52d35cacd2c6185b44281ec28c9dc0x242301fa62f0de9e3842a5fb4c0cdca67e3a2fab不同于用户 EOA 最初调用的路由器 v2 契约0x7a250d5630b4cf539739df2c5dacb4c659f2488d。这两个地址对应于 USDC-WETH 和 DXO-WETH 令牌对的 Uniswap v2 对合同。这些合约负责持有各自交易对的流动性,并实际进行互换。用户最初与之交互的路由器契约充当协调器,并向适当的成对契约发起内部事务(跟踪)。因此,为了解码这些事件,我们还需要对契约 ABI 。解码日志的示例代码如下:

与事务解码的代码类似,示例代码针对批量解码用例进行了优化,旨在与 PySpark 之类的工具结合使用,以处理大量日志事件。运行上述产量:

event emitted:  Swap
arguments:  {
  "sender": "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D",
  "to": "0x242301FA62f0De9e3842A5Fb4c0CdCa67e3A2Fab",
  "amount0In": 2500000000,
  "amount1In": 0,
  "amount0Out": 0,
  "amount1Out": 666409132118600476
}

event emitted:  Swap
arguments:  {
  "sender": "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D",
  "to": "0x3c02cebB49F6e8f1FC96158099fFA064bBfeE38B",
  "amount0In": 0,
  "amount1In": 666409132118600476,
  "amount0Out": 194900241391490294085918233,
  "amount1Out": 0
}

我们可以断定,这两个事件确实是最初请求中的path之后的swap事件——USDC>和> DXO。我们可以看到路由器契约(以488D结尾)是两个事件中的发送者,充当协调者。USDC-韦瑟配对合约(结束c9dc)用 25 亿单位的 USDC 交换 666,409,132,118,600,476 单位的韦瑟,然后将得到的韦瑟转移到 DXO-韦瑟配对合约(结束2Fab)。然后,DXO-WETH 合同将 WETH 的 666,409,132,118,600,476 个单位交换为 DXO 的 194,900,241,391,490,294,085,918,233 个单位,并按照最初的要求将其发送回用户(EOA 结束E38B)。

结束语

正如这个例子所希望说明的,一旦有了工具,解码的过程就相对简单了,但是知道解码什么以及如何解释结果数据就不简单了。根据您试图回答的具体问题,有些功能和事件比其他功能和事件更相关。为了分析 web3 应用程序中的经济活动和用户行为,了解特定智能合同的工作方式,并确定利益衡量标准中涉及的关键功能和事件非常重要。最好通过结合实际使用产品、在 Etherscan 等块浏览器上检查数据耗尽以及阅读智能合约源代码来完成。这对于开发正确的解码和分析策略是至关重要的。

我希望这是一次有用的讨论,我已经帮助你更好地了解了如何使用加密数据。在我的下一篇文章中,我将展示一个在 NFT 最大的市场 Opensea 上的深潜分析的例子。如果你想在帖子发布时得到通知,请务必点击电子邮件图标进行订阅。

感谢您的阅读,如果您有任何问题或意见,请随时联系我们。Twitter|Linkedin

解码数据网格

原文:https://towardsdatascience.com/decoding-the-data-mesh-594b44b4b26f?source=collection_archive---------16-----------------------

构建数据网格?避免这 7 个网状概念。

图片来自 里卡多·戈麦斯天使

data mesh 的创始人 Zhamak Dehghani 消除了关于 data mesh 的常见误解,data mesh 是一种越来越流行的构建分布式数据架构的方法,并分享了一些最佳团队是如何起步的。

如今,似乎每个数据人都分成两个阵营:理解 数据网 的人和不理解的人。

请放心:无论你在哪个阵营,你都不会孤单!

在最近的记忆中,很少有一个话题像风暴一样席卷了数据世界,催生了一个繁荣的社区,数百篇博客文章,以及挣扎于民主化和可扩展性的各行各业的数据领导者松了一口气。

但是,随着这种新的采用,也带来了对数据网格的真实性质以及如何构建数据网格产生误解的新机会,这种误解只会增加。

几个月前,我加入了 Thoughtworks 'Zhamak Dehghani数据网格框架的先驱Lena Hall 微软大数据工程总监,参加了一个关于 万物数据网格 的讨论。在交谈中,Zhamak 消除了许多最大的误解,包括数据网格是否是一种独立的技术,谁应该(或不应该)建立一种技术,以及数据网格是否只是数据虚拟化的另一种说法(提示:它不是)。

以下是我们谈话中的几个要点——请务必收听 的完整录音 以获得更多的神话终结和真知灼见。(注意:为了篇幅和清楚起见,有些引文已经过编辑。)

您能从单一解决方案中构建数据网格吗?

在高层次上,数据网格由三个独立的组件组成,数据源、数据基础设施和由功能所有者管理的面向领域的数据管道。数据网格架构的底层是一个通用的互操作性层,反映了与领域无关的标准,以及可观察性和治理。图片由蒙特卡洛提供。

扎马克将数据网格定义为“一种社会技术转变——一种我们收集、管理和共享分析数据的新方法。”

数据网格不是一种技术解决方案,甚至不是技术的子集——它是我们如何管理和操作数据的组织范式,由几种不同的技术组成,无论是开源还是 SaaS。

你不能只用一个数据库来构建微服务架构。你不会仅仅用一个数据仓库或者一个 BI 工具来构建一个数据网格。相反,数据网格可以部分地由这些技术驱动——以及其他许多技术。

简而言之,如果数据架构包括以下四个基本元素,那么它就是一个数据网格:

  • 将数据所有权从一个集中的团队分配给最适合控制数据的人——通常是数据来源的业务领域
  • 给予这些团队长期的责任感,并让他们具备将数据视为产品所需的产品思维
  • 为团队提供自助式数据基础架构
  • 解决新的联合数据治理模型可能带来的新问题

继续下一个。

数据网格是数据虚拟化的另一种说法吗?

在数据社区中,对于分散的数据所有权实际上是如何工作的还存在困惑。正如 Lena 所描述的,一些技术人员想知道分散数据所有权的概念是否与数据虚拟化的概念重叠,换句话说,这是一种允许应用程序跨许多孤岛检索和操作数据的数据管理方法。

根据 Zhamak 的说法,过去的情况是虚拟化位于您的 OLTP 系统和微服务或运营数据库之上,并按原样公开数据或进行一些小的转换。当谈到将它应用到数据网格时,这可能不是一个明智的想法。

“无论是数据网格还是 API 库,您都在尝试公开一个已经针对事务性目的进行了优化的数据库,以便进行分析。预测分析或历史趋势建模都需要一个非常不同的数据视图,”她说。“如果您考虑在您的微服务数据库上使用虚拟化,并公开它们,称之为网格,这可能是一个坏主意。”

每个数据产品团队是否管理他们自己独立的数据存储?

在数据网格范式下,面向领域的数据团队不拥有自己的数据存储,但他们对自己的数据和相关数据产品的质量和可用性负责。图片由 Unsplash 上的 Lagos Techie 提供。

根据扎马克的说法,这个问题的答案是否定的。

“Data mesh 会说,作为一名数据产品开发人员,我希望拥有自主权——拥有所有的结构元素、存储和计算、查询系统,以及所有允许我为数据科学家提供数据的东西,”Zhamak 解释道。“但这并不意味着我现在必须拥有自己的地理位置分离的存储层。事实上,如果网格是由一个云提供商提供的跨组织设置,您可能不会这样做。您可能只有一个存储层。”

“然而,它们是独立的模式,它们是独立的访问权限管理,它们是独立的租赁模型,允许数据产品以自主的方式部署,”她说

数据存储通常由中央数据工程或基础设施团队维护,他们负责确保数据网格对于每个领域都是有效的和可操作的。虽然每个领域的分析师和数据科学家负责在数据网格上构建和维护产品(比如仪表板、模型和报告),但他们并不是管理使分析、数据科学和 ML 成为可能的基础设施的人。

自助式数据平台和分散式数据网格是一回事吗?

大型组织已经在实施用于基础设施管理的自助服务平台,但是根据 Zhamak 的说法,数据网格的自助服务在几个关键方面有所不同:

“今天构建的大多数服务或数据平台都是为集中式数据团队构建的,旨在帮助数据专家更快地处理积压的工作。它们旨在为试图优化来自世界各个角落的摄取的集中团队提供服务。

数据平台在其当前状态下,通常是为了不同于数据网格的目的而优化的。 为支持数据网格而构建的数据平台 应进行优化,以给予领域团队自主权,并给予通才技术人员创建数据产品的能力——端到端地管理他们的数据,并直接服务于他们的数据消费者:数据分析师、数据科学家和其他最终用户。

数据网格是否适合所有数据团队?

虽然越来越多的组织开始采用或探索数据网格,但扎马克认为该模型“在其发展过程中仍处于相当初级的阶段。”

面临扩展数据可靠性问题的组织是采用数据网格最有意义的组织。Zhamak 说,早期采用者往往专注于工程,并对投资“建筑和购买技术”持开放态度,因为不是所有的元素都可以买到。

根据 Zhamak 的说法,如果您的利益相关者感到寻找和使用正确数据的痛苦,并且您的创新周期正在放缓,那么您可能是研究数据网格的合适人选。

2021 年,数据团队更早变大,数据更通用。因此,需要围绕一种自助式、分散式的方法来管理数据,而无需另起炉灶。数据网格可以有所帮助。

您团队中的一个人“拥有”数据网格吗?

正如他们所说,没有一个数据工程师是孤岛,尤其是在构建数据网格的时候。(图片由 Grzegorz WalczakUnsplash 上提供)

引入数据网格模型需要的不仅仅是技术。这需要整个组织的文化认同。

“我认为数据和所有数据驱动的计划和数据平台投资在组织中非常明显,并且具有高度的政治性,特别是在大型组织中,因此必须有自上而下的支持和自下而上的宣传,”扎马克说。

她证明,当组织有一个直接向首席执行官报告的首席数据官或首席数据分析官时,他们在大规模采用数据网格时往往更有效。尽管如此,这些领域仍有望获得其数据的所有权,因此需要支持这一计划,无论这意味着专用资源还是跨组织的支持。

“如果域名不在船上,我们所做的就是在一个集中的团队中过度设计数据的分布,”她说。

当您试图在您的组织中增加对数据网格的采用时,团队应该得到一到三个与愿景一致的领域,作为推进设计和实现的倡导者。通常,基础设施团队——实践者和工程师——并不难说服,因为他们经常感到痛苦。

数据网格会造成数据工程师和数据分析师之间的摩擦吗?

同样,答案是:不。事实上,它往往是相反的!

因为数据网格要求数据所有权去中心化,所以采用这种分布式的、面向领域的模型通常会在历史上有摩擦的领域带来健康的和解。

例如,当组织有一个负责管道的工程团队,一个对下游数据建模的数据工程组,以及更下游消费数据的分析师时,事件通常会导致相互指责。但是,数据网格的数据治理通用标准确保围绕数据质量、数据发现、数据产品模式以及数据健康和理解的其他关键元素达成一致。

根据 Zhamak 的说法,任何良好的数据网格所固有的这种自助服务能力包括:

  • 静态和动态数据加密
  • 数据产品版本化
  • 数据产品模式
  • 数据产品发现、目录注册和发布
  • 数据治理和标准化
  • 数据生产谱系
  • 数据产品监控、警报和记录
  • 数据产品质量指标

当打包在一起时,这些功能和标准化提供了一个健壮的 可观察性 —和信任层。

“我们在操作领域看到的发展始于我们自己的特别结构化日志记录,这是我们已经作为一种良好的软件工程实践在做的事情,”Zhamak 说。“我真的希望,通过谱系、指标和 SLO,我们可以开发一些开放标准,用来传达这些质量指标,如您的信任矩阵,或者以标准化的方式跟踪谱系,并在此基础上创建一个健康的工具生态系统。”

在我看来,像 data mesh 这样的组织结构实际上允许适当的自治和关于治理的讨论,迫使您的团队回答这样的问题:何时以及如何使用数据?我们关心的标准是什么,我们希望让每个人都拥有这些标准?或者甚至:每个域应该拥有哪些职责?

事实:数据网格标志着行业向分散化和民主化的转变

无论你站在数据网格的哪个位置,毫无疑问,这个话题激发了关于成为一名数据专业人员意味着什么,以及如何为你的组织真正传播和运营大规模数据的讨论。

事实上,与我交谈过的许多公司应用数据网格概念的时间比他们意识到的要长;他们只是没有合适的词语来描述它。

这种转变通常始于数据团队和利益相关者之间更好的沟通、组织协调以及对数据在公司中的作用的理解。有了这三个支柱,避免最困难的网状概念就容易多了。

对数据网格有更多疑问?报名参加 Zhamak Dehghani ' s talk atIMPACT:The Data Observability Summit今年 11 月或接触 巴尔 蒙特卡洛团队

并请务必查看 数据网格学习 社区,了解更多现场活动或加入他们的 Slack 频道。

为初学者解码 10 大数据科学术语(在面试中经常被问到)

原文:https://towardsdatascience.com/decoding-the-top-10-data-science-jargons-for-beginners-commonly-asked-in-interviews-436b5afbe3c0?source=collection_archive---------3-----------------------

用简单的英语解释并附有参考

Unsplash猎人赛跑的照片

这篇文章是关于解码数据科学中使用的一些流行术语。更好地理解这些概念很重要。他们通常在数据科学工作面试中被问到。让我们进入主题。

因变量和自变量

因变量(目标变量)由研究中的自变量驱动。例如,零售商店的收入取决于走进商店的顾客数量。这里商店收入是因变量。走进商店的顾客数量是自变量。因变量之所以这么叫,是因为它的值依赖于自变量。此外,独立变量之所以如此称呼,是因为它们独立于可能影响因变量的其他变量。就像,降雨量(自变量)与走进商店的顾客数量无关。这两个独立变量都有助于做出更好的预测。

在研究预测数据科学问题时。通常会有一个因变量和多个自变量。下面是一个很好的资源,可以更好地理解因变量和自变量。

https://www.scribbr.com/methodology/independent-and-dependent-variables/

极端值

异常值是不在变量正常范围内的值。例如,平均寿命在 70 岁左右。119 岁的个体被认为是异常值,因为他的年龄大大超出了正常范围。在处理数据科学问题时,通常会检查数据集中的异常值。如果出现预测问题,数据中的异常值可能会影响算法的选择。

这里有一篇详细的文章,讨论了异常值检测中常用的技术。

序数数据

当分类数据中包含推断序列时,它就是序数数据。例如,机票的类别是有序数据。有一个类似头等舱和二等舱的顺序。

当我们有有序分类数据时,最好使用整数编码。只需将它们转换成与推断序列对齐的整数表示。通过这种方式,算法将能够寻找模式。比如,当变量的值增加或减少时,它如何影响结果。

下面是一篇非常好的文章,可以学习更多关于分类数据编码的最佳方法

一键编码

一键编码是一种数据转换技术,有助于将分类属性转换为数字表示。独热编码的主要优点是它有助于避免对 ML 模型的任何混淆。

用更简单的术语来解释,诸如性别、城市、国家之类的属性是非顺序的。非序数意味着它们内部没有顺序,也就是说所有的性别都是一样的。当我们将这种非顺序属性转换成整数时,许多算法认为较高的值更重要/不太重要。虽然没有任何这样的关系。这个问题可以通过使用一键编码将非序数属性转换成二进制表示来解决。

要了解有关实现热编码的更多信息,请阅读下面的内容。

https://www.educative.io/blog/one-hot-encoding

偏斜度和峰度

偏斜度是理解数据分布的一种度量。当数据的偏斜度接近 0 时,意味着数据接近对称分布。当分布的左侧与右侧完全相同时,该分布是对称的。当数据呈负偏态时,意味着大多数数据点大于平均值。在正偏态数据中,大多数数据点小于平均值。

峰度也是一种更好地理解数据分布的度量。当数据具有正峰度时,意味着与正态分布相比,该分布具有更高的峰值。这实际上意味着可能有许多异常值。

下面是一篇非常好的文章,用可视化的表示方式来更好的理解偏度和峰度。

https://www.analyticsvidhya.com/blog/2021/05/shape-of-data-skewness-and-kurtosis/

不平衡数据集

不平衡数据集是指目标属性(待预测的属性)分布不均匀的数据集。在处理数据科学问题时,这种情况并不少见。例如,预测欺诈性信用卡交易是不平衡数据集的一个很好的例子。因为大多数信用卡交易都是真实的。然而,也有一些欺诈交易。

不平衡的数据集需要特别注意,因为构建模型或评估性能的常规方法不起作用。这里有一篇文章详细讨论了不平衡数据集以及更好地处理它们的最佳方法。

缩放比例

缩放要素是一种通常用于将数据集的所有要素(独立变量)调整到一致比例的技术。用一个例子来解释这个概念。让我们来看一个问题,我们有年龄和工资这样的特征。年龄在 20-75 岁之间,薪水在 5 万到 50 万之间。当我们使用基于梯度下降或任何基于距离的算法时。在将特征传递给算法之前,将特征缩放到一致的范围是很重要的。如果未对特征进行缩放,则更高比例的特征将影响预测。

要了解什么是 it 扩展以及它为什么重要,请阅读下面的文章。

相互关系

相关性是解释两个特征之间关系的统计度量。假设我们有两个特征 A 和 B,如果 A 和 B 彼此正相关,这意味着随着 A 的增加,B 也会增加。如果 A 和 B 是负相关的,那么当其中一个增加时,另一个减少。

建立模型时,相关性通常用于特征选择。当存在彼此高度相关的特征时,这意味着它们相互依赖。它们不是真正独立的,因此在构建模型时,通常会从特征列表中删除其中一个。

通过一个工作示例了解更多关于相关性以及如何在特征选择中使用它们的信息。阅读下面的文章,

置信区间和置信水平

置信区间和置信水平容易混淆,尤其是新手。一旦你理解了这个概念,它就不会被混淆。

让我们考虑一个简单的现实世界的例子。一家电子商务公司希望在最终购买之前了解商品的平均浏览次数。跟踪每个用户的点击流数据并不简单。因此,最好的方法是计算样本的平均值,并得出一个估计值。当我们分析样本用户数据时,我们希望得出一个估计范围。比如,用户在最终购买前平均浏览 4 到 9 件商品。这个区间就是置信区间。每 100 个用户中落入该范围的用户数量的确定性是置信水平。

要了解有关置信区间和置信水平检查背后的计算的更多信息,请参阅下面的文章

同方差和异方差

同方差是线性回归中的一个重要假设。这是求职面试中常见的问题。同方差意味着自变量和因变量之间的残差在自变量的不同值上是相同的。

让我们举一个简单的例子,我们有一个自变量“财产大小”和因变量是“财产价值”。意思是我们用‘财产大小’来预测‘财产价值’,误差就是残差。如果误差不随“属性大小”的不同值而变化,则它满足同质性。如果与较小的属性相比,较大的属性的残差较高,则它是异方差的。

为了更好地理解这个概念。此外,了解为什么同方差是解决回归问题的一个重要假设。读下面这篇文章,

https://www.statisticssolutions.com/free-resources/directory-of-statistical-analyses/homoscedasticity/

准备数据科学面试?

这是我的 YouTube 频道上的一段视频,讲述了准备数据科学面试的步骤。这不是面试前一晚的准备,而是长期的准备。

保持联系

欧元收益率曲线的分解和预测

原文:https://towardsdatascience.com/decomposing-predicting-the-euro-yield-curve-b3ad1670fdbb?source=collection_archive---------7-----------------------

应用主成分分析

肖恩·奥尔登多夫在 Unsplash 上拍摄的照片

利率期限结构(“收益率曲线”)是根据不同到期日的价格(以收益率表示)绘制同一类型债券(如信贷质量、行业)的表示。对于金融机构来说,理解其行为及其对公司资本基础的直接影响是至关重要的。

在本文中,我通过将收益率曲线分解为主要驱动因素来研究其潜在动态。因此,我将应用几篇学术论文中提出的主成分分析(PCA)。将探讨以下主题:

  1. 介绍数据
  2. 与传统的收益曲线因素“水平”、“斜率”和“曲率”相比,解释方差的主要驱动因素(主成分)
  3. 评估从一组缩减的维度生成的模型产量曲线与实际产量的拟合度(样本内与样本外)
  4. 推导未来 1 个月的非线性压力情景
  5. 用自回归时间序列模型检验主要主成分的可预测性

所描述的思想的 Python 实现可以从我各自的存储库中访问和派生。

https://bernhard-pfann.github.io/

来自《走向数据科学》编辑的提示: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们并不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语

1.介绍数据

基础数据代表每日欧元区 AAA 级政府债券的即期利率。所选时间跨度从 2005 年 1 月至 2020 年 12 月,可在此自由访问

在清理和过滤相关信息的数据后,可以绘制不同时间点的产量曲线。下面的图表使水平和陡度的下降非常明显。

以更精细的时间步长考察收益率曲线的变化,可以揭示宏观经济长期漂移背后的水平、斜率和曲率的波动动态。

图表 1:实际收益率曲线与一年期滞后版本的对比|图表 2:所示收益率曲线之间的差异

为了更好地理解曲线上每个点的驱动因素,需要评估波动率以及到期日之间的不同相关性。因此,由 30 个不同期限的即期利率构成的收益率曲线需要一个 30x30 的协方差矩阵。

不同期限债券收益率的滚动波动性

2.主成分解释

用如此大量的参数构建统计模型,增加了模型的复杂性以及由虚假输入产生的不确定性。主成分分析(PCA)是一种众所周知的技术,通过将所有特征的可变性压缩到有限的一组变换特征中来减少这种高维度。

输入数据矩阵,其中每个“x”代表特征“f”的第“n”次观察

在这种情况下,X 的每个特征都是给定期限内每日收益率的向量。为了捕捉所有期限的最大可变性,导出特征向量。这些向量基于 X 的协方差矩阵,并在投影到向量本身时最小化距离之和。作为参考,请查看以下视频中对该主题的更深入的解释...

特征值分解产生与初始数据矩阵相同数量的向量。然而,向量是按重要性排序的,因此只需要保留最重要的向量以供进一步分析。

每个特征向量“w”表示所有维度的向量方向。Lambda 陈述了每个 w 的重要性。

绘制前 3 个特征向量时,可以观察到特定到期日的发音,这给出了关于向量经济意义的初步直觉(例如,PC2 捕捉到短期和长期到期日方向不同的收益率曲线移动)

前 3 台电脑的特征向量

在仅保留前 3 个特征向量之后,与原始收益率曲线的简单矩阵乘法将每个收益率曲线转换成 3 维数据点。

输入矩阵“X”与保留的特征向量“W”的矩阵乘法产生变换的分数“T”

每个点代表转换到二维空间的完整收益率曲线

可以观察到,PC1 的高值对应于利率的一般低水平(2019/20 年的紫色/蓝色点),反之亦然。此外,收益曲线的增加的陡度由 PC2 跟踪(2009/10 年的石灰绿/橙色点)。

图表 1:实际收益率曲线|图表 2:降维后的收益率曲线

为了完成我关于导出的特征分数(主成分)的可解释性的结论,每一个都可以比作传统因素“水平”、“斜率”和“曲率”的代理。这些通常被视为到期日之间的某种利差(例如,10Y-6M 的利差代表陡度)

为了对收益率曲线的未来行为进行建模和预测,需要将推导出的分数反向转换成有意义的原始单位。这是通过将特征分数乘以特征向量的倒数来实现的。

得分“t”与特征向量矩阵“w”的逆矩阵相乘产生生成的模型收益曲线

得到的矩阵代表生成的模型产量曲线,其中每条曲线可以仅由 3 个因子描述。

3.适合度

要查看低维生成的模型收益率曲线是否真的有用,有必要评估它们与实际实现的曲线的拟合程度。下面描述了这些曲线的直接比较,以及每个时间点的平方偏差。

基于二维和三维模型收益率曲线的拟合优度评估。

很明显,基于三维的模型曲线比二维的更接近实际的产量曲线,因为压缩到更小的维数总是意味着一些信息的损失。

对于预测建模,评估样本外拟合更重要,因为特征向量只能事后导出。

三维模型与实际曲线之间差异的 RMSE。

不出所料,与在整个时间范围内拟合的收益率曲线模型相比,样本外拟合显示 RMSE 增加。然而,收益率曲线形状是整体 RMSE 的叠加驱动力。

4.推导压力情景

压力情景的评估及其对资本基础的影响是银行和保险中金融风险管理职能的一个组成部分。最简单的形式是平行的向上或向下冲击。

然而,由于所研究的 3 个 PCs 很好地捕捉了屈服曲线的可变性,直接对部件施加应力可以给出真实的非线性应力场景。可以应用直观的历史风险价值概念,找出所选滚动时间窗口的最大向上和向下变化。通过考虑该窗口内 5%的最大偏差,可以建立 95%的置信区间。

同样,特征分数的反向变换给出了模型收益曲线,在这种情况下是应力曲线。与每个 PC 的经济解释一致,水平、坡度和曲率的冲击是结果。

5.收益率曲线预测

几乎每个金融建模任务中最有趣的问题是关于它对未来做出预测的潜力。在这种情况下,我提出了一个简单的自回归(AR)模型,通过其自身的滞后来预测特征得分的每个向量。

n 滞后自回归模型

根据定义,x 的一步提前预报应该是其自身滞后和拟合的相应系数的点积。为了完全指定模型参数,定义了训练和测试范围以及考虑滞后的最大数量。

此外,有效的时间序列模型要求基础数据的均值、方差和协方差具有平稳性。

特征分数随时间的变化

可以清楚地观察到,特征分数的前两个向量明显是非平稳的(也得到了增强的 Dickey-Fuller 检验的支持)。因此,将时间序列转换成一阶差分是必要的。

一阶差分特征分数随时间的变化

在完成这些相关的规范和转换之后,可以评估实际的模型拟合。每个分量的第一个滞后显示出统计显著性(p 值> 0.05),这似乎是有希望的,即使系数大小只是边缘的。

为了评估模型预测的性能,需要将其误差与基准模型进行比较。它最常用的实现是一个简单的预测器,预测 t+1 中的值等于前一个时段 t+0 中的值。

比较两种模型的预测误差可以清楚地看出,ar 模型几乎类似于基准模型,因为它的小系数值接近于 0。然而,小而显著的第一个滞后导致了 RMSE 在整个测试数据上的边缘表现。

所有到期日相对于实际实现收益率曲线的 RMSE 预测误差

结论

总之,主成分分析的应用有助于将看似高维的收益率曲线数据分解为几个主要驱动因素。有了这些有限的维度,也就有了经济意义,金融模型的因果关系和可解释性就可以得到改善。压力情景或一步到位预测的推导是金融风险管理或投资组合构建中的用例,可以进一步扩展。

如果你想继续我的工作,请随意查看相应的 Github 库。

https://bernhard-pfann.github.io/

解构求职过程:个人观点

原文:https://towardsdatascience.com/deconstructing-the-job-hunting-process-a-personal-perspective-21d2f13c871c?source=collection_archive---------25-----------------------

办公时间

我第一次尝试在科技行业找工作(作为一名新兵训练营的毕业生)

Jesse j . Ruiz(jesseruizart.com)原画

我最近做了一个从艺术家到数据工程师的职业转型,想分享一下我学到的东西。通过分享我的个人经历,我试图给出我作为一个新手进入技术领域的最佳建议,我希望这能帮助和激励他人。

TDLR,这是我的 5 个关键经验。下面我详细阐述每一个。

5 个关键教训

第一课:不要仅仅为了声望或金钱而试图在方(脸书-亚马逊-网飞-谷歌)公司工作。

第二课:除非你了解一家公司的价值观、产品、投资和道德,否则不要申请这家公司。

第三课:挑选一组适合你的技能和教育水平的职位。

第四课:开始寻找你现在住的地方或者几个你可以现实生活的地方。

第五课:了解你自己和你的优势将帮助你创造你的职业身份,并到达你想去的地方。

注:如果你想在我的 YouTube 频道上观看我对这些内容的讨论,请点击这里https://youtu.be/XaPC_bdEBVA

为什么找工作

2009 年我工作转型的核心是在资本主义社会中寻找自我的生存斗争。在我二十多岁的时候,我根本不在乎钱和我的净资产。我只想做艺术。但这种对艺术(而不是金钱)的承诺让我破产,筋疲力尽。我努力想找到一份合适且有利可图的工作,但这很难,因为我在美术世界之外的任何专业领域都缺乏身份和目标。

为了在科技行业找到一份工作,我不得不重新发明自己,以便恰当地进入一家公司,找到一个适合我的职位。正确理解我的优势、目标、技能或技能不足,以及价值观,就像知道如何写简历和求职信、面试等一样重要。换句话说,求职技巧没有“发现自我”重要,也就是说,塑造自己的职业形象。这不仅仅是一个职位,而是关于目标、动机和价值观。

当然,求职的诀窍是极其有价值的,因为找工作并不容易。招聘过程中几乎没有透明度,更糟糕的是,到处都是不公正和带有偏见的做法。尽管存在这种不公平,我还是找到了一份工作,我将通过解构求职来分享我的旅程。

寻找起点

我向一位家庭成员(我的表弟萨姆)寻求帮助,他是一名软件开发员。她以一组问题的形式帮我找到了一个切入点:你愿意为什么样的公司工作?你的道德观和他们的一致吗?你在寻求什么样的职位?你想在哪里工作?

似乎是一组非常简单的问题。但是你不会相信有多少人弄错了或者干脆完全忽略了它们。大多数人只是跳上求职板,开始申请任何看起来有点意思的工作。我一开始就是这么做的。但我建议不要这么做。

此外,出于单纯的天真和雄心,我想为一家方(脸书-亚马逊-网飞-谷歌)公司工作。除了我日常生活中使用的几家公司之外,我对科技行业了解不多,所以我真的不知道如何开始寻找,我浪费了大量时间毫无意义地申请方公司的工作。

然而,当你是这个行业的新手时,开始考虑在哪里工作会很困惑。对我来说,我不仅对科技行业一无所知,而且对任何行业的工作都一无所知。

如何解决这 4 个重要问题

问题 1:什么类型的公司?

有几种方法可以考虑这个问题。有私营部门和公共部门。营利性和非营利性。大公司和小公司。创业公司和其他一切。各有利弊。对于初学者来说,最好在大中型公司找工作,因为那里有边干边学和接受指导的空间。

你想为哪种公司工作的问题是你找工作的第一步。我发现,因为金钱和声望,我天真地坚持在方公司工作的想法。这让我意识到,我在寻找工作时还需要考虑其他因素,比如文化、领导力、多样性、工作与生活的平衡、导师以及培训资源。

第一课:仅仅为了名声或金钱而想去方(脸书-亚马逊-网飞-谷歌)公司工作是一个大错误。如果你盲目地在方公司找工作,你会让自己失望的。花时间研究公司,不要害怕在一家不知名的公司工作。(更多关于方为什么不适合大家以后再说。)

对我来说,我认为在创业公司工作会很有趣。但后来我了解到,作为一个小型创业团队的一员,每个团队成员都要承担很多责任,工作压力很大。

我避开了为大公司工作的想法,因为我不想支持一个赚钱的、吸人灵魂的公司。所以我认为为某种类型的非营利组织工作对我来说是最好的。但后来我很快了解到,在非营利领域,没有多少高薪或入门级的工作。

不知道还能做什么,我创建了一个大的电子表格,列出了我喜欢的公司。我是通过搜索最佳雇主公司和最佳 LGBTQIA 人公司名单找到他们的。我花时间观察谁在那里工作,他们是否支持我所做的事业,以及他们创造了什么样的产品。开始过滤掉你不喜欢的公司的一个简单方法是上 LinkedIn,查看他们的员工和领导层。如果领导岗位上没有很多女性或有色人种,那么我个人会放弃这家公司。

最终,我决定瞄准大公司,这样我就可以得到指导和继续学习。我的理由是,一家更大的公司会有在职学习的空间,也会有更多资深成员的指导。到目前为止,我发现这是真的。

问题 2:你的道德观和他们的一致吗?

重要的是要考虑你是否能在道德上为一家公司工作。例如,你愿意为一家有不公平薪酬历史的公司工作吗?例如脸书?(=隐私问题)优步?车门仪表板?(=司机薪酬顾虑)等。

第二课:除非你了解公司的道德规范(价值观、产品、愿景、工作文化),否则不要开始申请工作,除非你的道德规范与他们的一致。

当然,大多数人可能无法享受为梦想中的公司工作的奢侈。大多数人只需要挣一份薪水。但对我来说,为了有一点点的正直和动力,我想知道我在为一家在道德上与我一致的公司工作。这不仅仅是薪水的问题。如果你不能诚实地说你支持公司的产品或使命,那么就不要浪费时间去申请那里的工作。

有些人可能会把这个伦理问题称为文化适应问题。但我认为不止如此。我相信道德联盟意味着你支持那里的产品、实践和员工。

在我写的所有考虑因素中,这个道德问题是最难讨论的,因为它充满了问题和复杂性。所以我就说到这里。这里的教训是了解公司的伦理/愿景,了解自己的伦理/愿景。

问题 3:你想找什么样的职位?

基于你的教育、培训和技能,你应该开始列出最适合你的职位。我有一个雄心勃勃的计划。不要退缩。理想情况下,你可以从职业顾问或业内人士那里获得帮助。你应该知道职业发展会是什么样子。比如数据分析师到业务分析师到数据科学家到高级数据科学家。但是,如果你没有完全搞清楚,也不要担心——这个过程并不总是线性的。

第三课:挑选一组适合你的技能和教育水平的职位。在你的计划中要雄心勃勃,但是要给自己足够的时间来发展你的职业生涯,并且对你的时间表目标要现实。

在我旅程的开始,我学习了数据科学,并开始用有限的知识和经验尽可能好地制定职业发展计划。因为我选择参加数据科学的编码训练营,我知道我的目标是数据科学家的职位,但随着时间的推移,我知道我可以从不同的职位开始,并迅速向上发展。到目前为止,我有过类似“初级开发人员”、“Web 开发人员”、“前端软件开发人员”、“业务分析师”和“数据工程师”这样的工作头衔。我目前正在成为一名机器学习工程师。

再说一次,求职之旅从来都不是直线的。你可能会经历许多阶段,随着时间的推移加深你的知识。同理,你的职业生涯也不会是直线型的,尤其是如果你进入了科技领域。然而,要做好准备,找到一条职业道路,并志存高远。

问题 4:你想在哪里工作?

这里要非常现实,因为你需要缩小你的求职范围。最多挑几个地方,从那里开始你的搜索。有了一套缩小的和有目的的需求,你会发现更容易找到目标。

此外,最好是利用当地组织、聚会和教育项目来融入当地网络。如果你刚毕业,那就利用母校的资源,寻找人脉机会。将你的时间和精力投入到当地社区不仅会帮助你找到工作,还会加深你对新领域的归属感、目标感和认同感。在我看来,这是极其重要的。

第四课:当你在考虑你想去哪里工作时,不要太理想化或者想去太远的地方。从你目前居住的地方或者几个你可以实际居住的地方开始。

当我开始自学并参加编码训练营时,我住在德克萨斯州的圣安东尼奥。当我从这个训练营毕业时,我开始在全国范围内寻找数据科学领域的工作。我参加了几个外州公司的电话面试,但我最终通过当地一家联合办公空间的 Slack 频道找到了我在城里的第一份工作。

起初,我真的很想在洛杉矶或纽约这样的酷城市找份工作。但我很快意识到,在你目前不居住的地方申请工作有一个巨大的劣势。没有多年的经验,我主要是在浪费时间。我还发现搬家是一个我在经济上无法真正做出的承诺。最终,我在我居住的城市找到了一份工作,这是有史以来最美好的事情。

通过训练营找工作——狗屎变得真实

第五课:了解你自己和你的优势将有助于你打造自己的职业身份,并到达你想去的地方。把你的形象塑造成专业人士,你就会成为专业人士。

当我参加数据科学训练营时,我有一个职业顾问,Mary,她非常出色,非常能干。这所学校在南德克萨斯州很有名,与当地公司建立了良好的关系网。这就是我决定去那里的原因。

然而,对我想从事的行业一无所知非常令人沮丧。起初,我把这种挫败感部分归咎于玛丽,认为她除了是一名职业顾问之外,还应该是一名更好的教育者。唉,现在回想这段经历,我知道她在工作中做得非常出色,她的工作本身并不是教育,而是与公司建立联系,为我发现机会。

了解一个新行业需要时间。当我艰难地通过玛丽为我安排的几次面试时,我在不断地研究、申请和完善。求职过程的各个方面都具有挑战性,但随着过程的进行,我也抓住了关于我自己和我想成为什么样的人的更深层次的问题。

我开始看到我的职业轨迹可能会是什么样子。我开始剔除那些我无法忍受为之工作的公司。我深刻审视了自己的经历、技能和才能,并开始意识到我对自己的印象正在慢慢改变,我希望这种印象能在我工作的公司中反映出来。创新、机敏、高效和成功:这是我对自己的看法,也是我希望在我工作的公司看到的。但这并不容易。

我非常感谢玛丽和我参加的训练营。我接受了培训和训练,以应对求职过程中的大多数 T2 问题。专业头像,LinkedIn 简介,新简历,招聘会,面试。最重要的是,我被迫与专业人士会面和交流,这对一个社交能力差的内向者来说很难。我不仅利用了我所拥有的资源,还主动扩展了我的行业知识,成为了一名新的数据科学家。(至少在专业上。)

我在我的其他文章中谈到了训练营的经历。但是我要说,如果你是一个完全陌生的人,训练营是在科技行业找工作的最佳途径,因为他们已经建立了网络。玛丽告诉我,找工作最重要的一步是做好准备。有目的的乐观有所帮助。

终于找到工作了

早些时候,当我谈到我想在方公司工作的愿望时,我认为在申请工作之前需要考虑一个公司的许多不同方面。这不仅仅是你的声望或者你赚了多少钱。更详细地说,我随着时间的推移了解到,有一些特定类型的工作只存在于大公司。并且这些类型的角色涉及公司本身的产品和内部运作。一旦你在职业生涯中获得了技能和经验,那么你就扩大了对不同工作的角色和职责以及公司实际运作方式的了解。

我进入这个行业的第一年就了解到,在数据科学领域(以及其他科技领域),存在“研究人员”和实现研究人员所做东西的人之间的二分法。换句话说,有些人开发新算法,有些人在现实世界中使用这些算法。当我刚刚开始我的研究时,我并不知道这一点,我的表弟山姆帮助进一步阐明这一点。这种二分法反映了研究/基础设施和功能/面向用户的工作之间的差异。

科技行业的学习从未停止。因此,你的技能和知识是不断变化的。在我的经历中,我通过慢慢学习和体验,消除了对科技行业的误解和神话。其中最重要的神话是关于方公司的。他们并不适合所有人,但如果你的目标是从事研究/基础设施工作(即创造新的算法),那么像方这样的公司可能最适合你。

结论

找新工作的整个过程是变革性的,尽管极其困难和有压力。找工作的秘诀是做好准备,有目的的乐观,并在该领域保持清晰的身份。尽管招聘实践存在缺陷,但作为一名数据科学家(或其他什么人),精心打造你的真理、目的和道德观,将引导你找到合适的人。

在经历了寻找第一份工作的所有挣扎之后,我也明白了找工作永远不会停止。我得到了现在的工作,因为我在现在的公司得到了内部晋升。我能做到这一点的唯一原因是因为人际关系网,这是找工作的一项基本技能。

无论你在职业生涯的哪个阶段,你都会一直在找工作,因此你会一直在建立关系网。良好的人际关系网需要你足智多谋和好奇。永远不要停止社交。永远不要停止追求目标,在职业生涯中建立自己的身份。祝你好运。

*【https://youtu.be/XaPC_bdEBVA *

Python 中的装饰器和闭包示例

原文:https://towardsdatascience.com/decorators-and-closures-by-example-in-python-382758321164?source=collection_archive---------17-----------------------

如何使用装饰器增强函数的行为

作者:爱德华·克鲁格道格拉斯·富兰克林

安吉丽娜·乔利维特在 Unsplash 上拍摄的照片

这里讨论的代码可以在这个库中找到。

https://github.com/edkrueger/joblib-demo

我们将从这些概念的密集描述开始。然后再举一个说明性的例子。

装饰、关闭和范围

装饰是一种设计模式,允许您修改功能的行为。装饰器是一个函数,它接受一个函数并返回该函数的一个扩充副本。

当编写闭包和装饰器时,必须记住每个函数的作用域。在 Python 中,函数定义范围。闭包可以访问返回它们的函数的范围;装饰者的范围。

装饰品-照片由 Yoksel 拍摄🌿在 Unsplash 上的 Zok

如果你不懂这个行话,那也没关系。这里有一个例子来阐明这些概念。

示例:装饰

让我们回顾一下这段代码的范围、闭包和修饰。

装饰示例

这个装饰器将一个函数作为输入,并返回一个我命名为closure闭包。这个闭包运行传递给my_decoratorfunc,并返回一个添加了一些打印语句的版本。

my_decoratorclosuresay_hello三种功能都有自己的范围。关于closure有趣的是,它可以访问其作用域之外的变量my_decorator.父作用域内的变量

虽然看起来不像,但是在my_decorator的范围内有变量——特别是作为参数传递的func 。注意func可以被closure访问,它在第 4 行被调用。因此,闭包正在访问装饰器的父作用域中的一个变量。

装饰者返回一个闭包。闭包是装饰器返回的东西。

这个要点中显示的第二个函数是say_hello。这个函数打印一个字符串并返回“无”。如果您愿意,可以在 Python 文档中阅读更多关于 None 的内容。

在第 16 行,我通过用my_decorator装饰 say_hello关闭分配给hello。在这样做的时候,我定义了一个新的函数——闭包hello.,然后我在第 17 行把它叫做闭包。你能猜到这个调用会返回什么吗?

say_hello()输出

你可能是对的。现在你可以看到装饰是如何扩展函数的行为的。然而,我们可以利用一种更方便的语法来修饰函数。

装饰者“@ Syntax”

在 Python 中,decorators 可以很容易地用@符号来应用。并非所有装饰器的应用程序都使用这种语法,如上面的例子所示,但是所有的@符号都是装饰器的应用。很多人用过 decorators(像@app.route()用 Flask)都不知道这个设计模式。

由@timefunc 修饰的函数“single_thread()”

当您在函数定义前包含@timefunc时,这个装饰器将应用于该函数。类似于我们如何定义一个新函数hello,通过设置它等于my_decorator(say_hello);我们在全局名称空间中重新定义了single_thread(),使其不指向原始函数single_thread(),而是指向闭包。

也就是说,使用@符号来应用装饰器定义了一个新函数。使用这种样式,原始的函数名将被保留。当我们调用上面代码中的single_thread()函数时,相当于调用timefunc(single_thread)(如果不是被@timefunc修饰的话)。

因此,@符号是增强函数行为的一种优雅方式。

结论

装饰是增强功能行为的有力工具。您可能会使用 decorators,因为您可以在 Flask 文档中找到它们。但是,编写自己的代码会很有用。例如,您可能想要计时或跟踪一个函数。通过编写实现这一点的 decorators,您可以获得一个优雅的、可重用的模式来跟踪函数的运行时和行为。

降低神经网络规模并保持准确性:知识蒸馏

原文:https://towardsdatascience.com/decrease-neural-network-size-and-maintain-accuracy-knowledge-distillation-6efb43952f9d?source=collection_archive---------25-----------------------

有些神经网络太大,无法使用。有一种方法可以使它们更小,但保持其准确性。请继续阅读,找出方法。

埃弗里·埃文斯在 Unsplash 上拍摄的照片

实用的机器学习都是关于权衡的。我们可以通过使神经网络变大来获得更好的准确性,但在现实生活中,大型神经网络很难使用。具体来说,问题不是出在训练上,而是出在部署上。大型神经网络可以在巨型超级计算机集群上成功训练,但当需要在常规消费设备上部署这些网络时,问题就出现了。普通人的电脑或电话无法处理运行这些大型网络。因此,如果我们想在实践中使用这些网络,我们需要在保持精度的同时减小它们的尺寸。这可能吗?

这是一个重要的问题,所以做了很多研究也就不足为奇了。我想强调两种方法。一种方法是在训练过程中进行规模缩减,系统地删除网络中最不重要的权重。这叫做修剪,如果你感兴趣,你可以在这里阅读更多相关内容

第二种方法是我们将在这里讨论的,称为知识提炼。我们首先以全尺寸训练网络,而不是在训练期间减小网络尺寸。然后,我们训练另一个更小的网络,使用完全训练的大网络作为真理的来源。使用网络来训练其他网络的想法是一种迁移学习。在高层次上,知识升华是一种分两步走的迁移学习形式。首先,训练大网。然后,用大网训练最后,小网。现在我们来看看细节。

因为知识提炼有两个训练步骤,我们自然地将数据分成两个训练集。第二个训练集(用于训练小型神经网络)称为转移集。因为在第二个训练步骤中,我们使用大的神经网络作为事实的来源(与数据标签相反),我们不需要将转移集标记为。这是一个很大的优势,也是使用像蒸馏这样的迁移学习方法的原因之一。我们来澄清一下这是什么意思。典型的机器学习范式是使用一些数据 x 和标签 y 来学习一个逼近 y 的函数 f(x),我们对转移集所做的是用 g(x)代替 y,其中 g 是经过训练的大网络。所以不需要 y。

为什么这样好?在现实生活中,标签很难获得。通常,标签是由人类创建的,因此对于大型数据集,必须投入大量精力来标记数据。这需要花费金钱和时间。有了知识的升华,我们只需要标签来训练大网络,也就是说我们只需要标注我们数据的一部分而不是全部。

训练大型网络的过程在一个方面不同于常规训练。不同之处在于从倒数第二层到输出层的 softmax 激活函数。回想一下,softmax 函数的目的是使最终输出节点总和为 1。该函数的形式为 o_i = exp(z_i)/σ_ j(exp(z _ j)),其中 o _ I 为第 I 个输出层节点,z _ I 为倒数第二层节点。在知识提炼中,我们对这个公式进行了调整。具体来说,在第一阶段(训练大网络),我们将函数改为 exp(z _ I/T)/σ_ j(exp(z _ j/T)),其中 T 为大于 1 的常数。t 控制最终输出的所谓的“柔和度”。t 本身称为温度。T(更高的温度)越大,最终输出将越接近(更柔和)均匀。在知识提炼的文献中,你经常会看到“使用软目标”这个短语——使用高温就是这个短语的意思。

为什么我们要用一个很大的 T 值?两个原因。第一,在大网络中使用软目标的时候,到了训练小网络的时候,梯度的方差会更小。这让我们提高了小网络的学习率,并使用更少的样本。第二,软目标可以提供比常规目标更多的信息。例如,假设 softmax 的常规输出是向量[0.98,0.011,0.009]。如果 T 值很高,输出可能会变成类似于[0.8,0.12,0.08]的值。第二个输出显示了第二个和第三个输出节点之间的明显差异(0.12 对 0.08),而第一个输出(0.011 对 0.009)几乎没有显示出来。因此,[0.8,0.12,0.08]输出有更多的信息,我们宁愿用它来训练这个小网络。

如前所述,一旦训练了大网络,就使用转移集上的大网络输出(将是软的)作为标签,在转移集上训练小网络。这个小型网络的培训过程是常规的,这里没有特殊的步骤。综上所述,知识升华的整个过程自始至终是:

1.把你的训练集分成两组:第一组训练大网络,第二组(转移)训练小网络。

2.用第一个训练集用高温训练大网络。使用高温的目的是获得更软的目标,它比常规目标包含更多的信息。

3.使用转移集上的大网络输出作为真实的来源来训练转移集上的小网络。

我们现在已经解释了知识提炼是如何工作的。还有更复杂的版本,但从概念上讲,它们和我们的简单版本是一样的。现在——它真的有用吗?是的。做了多个实验,我们来看一个最简单的。研究人员首先在 MNIST 数据集上训练了一个大型神经网络(2 个隐藏层,每层 1200 个节点)。在测试集上,这个大型神经网络有 67 个错误。接下来,研究人员在 MNIST 数据集上训练了一个较小的网络(2 个隐藏层,每层 800 个模式)。在测试中,这个较小的神经网络有 146 个错误。如果用来自大型网络(温度 T = 20)的知识提炼来训练这个较小的网络,它在测试集上只有 74 个错误,这与大型网络测试性能相当。这个实验证明了知识提炼确实将大部分知识从大网络传输到小网络,并且还证明了没有大网络,小网络就不能实现可比较的性能。语音识别等其他领域的实验也已经完成——你可以在最初的论文中读到更多关于它们的内容。

底线:知识提炼是在较小的网络中实现较大的网络性能的一种有前途的技术。它解决了大型网络因其尺寸而无法使用的实际问题,为消费设备上更高性能的神经网络打开了大门。我期望看到这种技术在未来得到广泛应用。感谢阅读,并请留下任何问题/评论!

名词(noun 的缩写)B 12/21:我看到了一篇优秀的文章,这篇文章更深入地解释了知识的升华。对于对这个主题感兴趣的人来说,这是一本很好的读物。

解密复杂的 SQL

原文:https://towardsdatascience.com/decrypting-complex-sql-2050aeb98082?source=collection_archive---------8-----------------------

照片由 @alexmotocUnsplash 上拍摄

招数

一种分析和理解复杂 SQL 的有效方法

在这个故事中,我想分享一种解决复杂 SQL 查询的棘手理解的可能方法。当我们需要处理一些现有的 SQL 代码时,可能是没有文档记录的、写得很差的,或者使用了我们还没有掌握的 SQL 版本,处理这些代码可能会令人沮丧。

无论我们需要对它做什么,只是按原样运行它,在数据科学或分析过程中使用它,修改它,等等。,无论如何我们需要理解它。

内容:

**·** [**What can make SQL tricky**](#c6fd)
· [**Breaking SQL complexity**](#03e9)
  ∘ [1\. Improve the code format and structure](#7c69)
  ∘ [2\. High level SQL review](#4be2)
  ∘ [3\. Clarify unknown SQL clauses, syntaxes and functions](#969c)
  ∘ [4\. Split and analyse inner to outer SQL](#592b)
**·** [**In a nutshell…**](#f2cf)

什么会使 SQL 变得复杂

当我们寻找一个新的 SQL 查询时,我们完全理解的主要障碍是

  • 子查询和嵌套逻辑的大量使用
  • 未知的子句、函数、语法、数据库特定的命令
  • 结构不良或记录不良的代码

那么,假设我们需要快速理解一个 SQL 查询,我们能做些什么来优化我们的 SQL 分析方法吗?

打破 SQL 复杂性

在这一节中,我将介绍可以使我们的 SQL 分析更有效的 4 个主要因素。

1.改进代码格式和结构

2。高级 SQL 审查

3。澄清未知的 SQL 子句、语法和函数

4。拆分和分析内部到外部 SQL

我将解释每个概念,并将其应用到一个 SQL 示例中,这个示例实际上并不复杂也不冗长,但是完全相同的思想适用于任何 SQL 查询。

在这里,有人给了我们使用这段 SQL 的新数据挖掘工作流程,并告诉我们,它运行在 SQL Server 数据库。是啊,很棒的东西,现在呢?

WITH tmp_1 AS
(
SELECT Calc1 =
( (SELECT TOP 1 DataValue
FROM (
SELECT TOP 50 PERCENT DataValue
FROM SOMEDATA
WHERE DataValue IS NOT NULL
ORDER BY DataValue
) AS A
ORDER BY DataValue DESC
) + (SELECT TOP 1 DataValue
FROM (
SELECT TOP 50 PERCENT DataValue
FROM SOMEDATA
WHERE DataValue Is NOT NULL
ORDER BY DataValue DESC
)AS A
ORDER BY DataValue ASC))/2
 ),tmp_2 AS
(SELECT AVG(DataValue) Mean, MAX(DataValue) — MIN(DataValue) AS MaxMinRange
FROM SOMEDATA
),tmp_3 AS
(
SELECT TOP 1 DataValue AS Calc2, COUNT(*) AS Calc2Count
FROM SOMEDATA
GROUP BY DataValue
ORDER BY Calc2Count DESC
)
SELECT Mean, Calc1, Calc2 , MaxMinRange AS [Range]
FROM tmp_1 CROSS JOIN tmp_2 CROSS JOIN tmp_3;

1.改进代码格式和结构

这可能很傻,但是当我们的眼睛欣赏顺序时,首先要做的是以一种好的可读的方式构造 SQL 脚本。这需要 5 分钟,通过使用任何 SQL 客户端的脚本格式化内置工具,或者有很多免费的在线页面。

一旦完成了下面的例子,我们会得到类似这样的结果:

作者截图:格式化的 SQL 查询示例

最大的附加价值是,现在我们可以清楚地看到所有的子查询,它们的嵌套有多深,并且每个选择都非常容易识别。这些将是我们下一步的基础。

2。高级 SQL 审查

2.1 识别主 SQL 层

任何查询都可以被视为由其他查询和子查询的层组成。我们可以通过查看 SELECT 子句及其依赖项来找到这些层。

现在,复杂的查询可能有许多层,但是为了有一个大概的了解,我们可以只看一下 层 1 ,看看它如何组合来自其内部层的数据:它做连接、联合、相交等吗??

这为您提供了一些关于该查询的一般目的的提示。

在我们的例子中

作者截图

所以我们可以理解,LEVEL #1 通过交叉连接来组合 3 个子查询 tmp_1、tmp_2、tmp_3 的数据。

让我们继续学习更多关于我们查询的表。

2.2 找出表和数据模型

为了理解我们的 SQL 查询做什么,我们需要识别为每个 SELECT 子句提供数据的表,并推断它们之间的关系,在头脑中构建一种由查询隐式使用的数据模型。

为此,我们只需查看所有可能层的 FROM 子句及其子查询。

在我们的简单示例中,所有子查询只使用一个名为“SOMEDATA”的表。我们应该看看它的数据,这将有助于下一步。

作者截图

3.阐明未知的 SQL 子句、语法和函数

现在我们想更详细地了解我们的 SQL 做了什么。为此,我们需要了解更多我们不熟悉的 SQL 函数、操作符、子句和对象。如果我们不了解所有现有的 SQL 风格、所有可能的数据库供应商和版本,这是完全正常的。

所以只要找出你不知道的任何一段代码并查阅文档就行了。

例如,我们示例中的查询被编写为在数据库 SQL Server 上运行。

在我们的查询示例中,假设我们不理解两个部分:

"..什么是“百分比”?可能是某个特定于 SQL Server 的操作符吗?”

"..我以前见过,但我不记得它是做什么的了”

在阅读文件后,我们了解到

前 50%将列数据值中的数据分成 2 组,每组一半数据,取前一半。将它与 ORDER BY 子句结合使用,可以让我们考虑数据值的顶部和底部的 50%。

同..AS 动态创建记录集,并将其命名为“tmp_1”,然后可以在同一个查询的其他部分引用它。

4。拆分和分析内部到外部 SQL

现在我们有了理解整个查询的所有元素。为此,我们需要一部分一部分地分析 SQL,从内部查询层开始,然后向上移动到第 1 层。

每当我们理解了属于一个层的所有子查询,我们也应该能够理解它们的外层做什么。

让我们将这个原则应用到我们的查询示例中:我们从查看带有 tmp_1 的 section 的内部子查询开始(参见注释 1。),那么我们转移到 2。,然后是 3。结合了 1 的知识。第二。这使得我们能够完全理解整个 tmp_1 部分。

当我们数到 7 时。我们知道 SQL 脚本的目的只是计算单个表的列的中值、平均值、范围和众数。

作者截图:SQL 分析示例

简而言之…

在这个故事中,我介绍了一种非常有效的方法来分析复杂的 SQL 查询。这 4 个主要步骤非常实用,可以应用于任何复杂度的查询。这种方法适用于任何人,从 SQL 初学者到专家,它只是改变了完成它所需的时间。

感谢阅读。

随时订阅我的《分享数据知识》简讯

如果你想订阅《灵媒》,请随意使用我的推荐链接https://medium.com/@maw-ferrari/membership:对你来说,费用是一样的,但它间接有助于我的故事。

使用模糊评分对客户数据进行重复数据删除

原文:https://towardsdatascience.com/deduplication-of-customer-data-using-fuzzy-scoring-3f77bd3bb4dc?source=collection_archive---------28-----------------------

行业笔记

使用 Python 处理复杂的客户数据

摘要:

对于任何组织而言,数据管理始终是一项挑战,贯穿其规划、收集、处理、存储、管理、分析、可视化和最终解释的生命周期。为了成功管理和保护数据,需要团队之间进行大量规划和协作,以便将数据从一个阶段转移到下一个阶段。数据处理的几个主要步骤是争论、压缩、重复数据删除和加密。对于大多数以客户为中心的组织来说,获得唯一的客户列表将是一个最大的挑战,这不是因为存储成本降低,而是因为了解他们的客户是他们最大的资产。

因此,无论企业规模如何,他们都会花费大量时间和精力,通过线内重复数据删除或后处理重复数据删除来获取正确的数据[1]。本白皮书通过 python 和相关软件包使用模糊评分方法来讨论后处理重复数据删除。

挑战:

数据以各种方法收集,有/没有标准的数据收集表格,在不同的地方收集,但集中在一个地方。这些列表通常由第三方编制,没有标准格式,并且通常包含重复或“脏”数据。数据追溯到漫长的历史,包含不准确和不完整。

当试图比较由不同收集方法编制的列表时,很快会遇到几个数据问题的挑战:

1.不明确的地址:根据数据收集的时间、地点和主要目的,它可能具有非结构化和非特定的地址、邮政编码甚至姓名。

2.音译问题:将带有非罗马字符的地址翻译成英文文本时出现的不一致会导致地址和姓名的变化。

3.联系信息复杂化:客户通常会有多个电子邮件地址和电话号码,当企业类型为 B2B 时,这个问题会变得更加突出,在 B2B 中,企业会有多个电话号码和电子邮件地址。

4.最多重复值:常见的重复值是因为数据收集不正确,特别是在姓名、电子邮件、电话号码等项下。每种情况都必须得到适当的处理。

数据标准化:

开始重复数据消除之前的一个重要步骤是确保数据结构化、对齐并具有一致的格式。因此,遵循以下步骤是明智的:

1.小写:高效最简单的一个步骤就是把所有东西都转换成小写,让名字和地址具有可比性。

2.缩写:通过建立一个从互联网上获得的或定制的正在处理的数据的知识库,保持单词与缩写的一致性。示例:Street 也表示为 St .,St,Str。、字符串等。

3.缺失值:评估每条记录的缺失值,如果有重大缺失值,则将其删除,不要继续处理,这样的记录质量将太低,无法帮助重复数据删除评分。

4.不正确的国家名称:Python 包“iso3166”包含所有国家的列表,帮助识别国家名称中不正确的国家名称。

5.不正确的邮政编码:‘pgeocode’是一个 python 库,包含所有国家的合法邮政编码,用于验证地址中的邮政编码。出于同样的目的,也有几个付费的 API 来帮助获得正确的邮政编码。

电话号码和电子邮件地址的验证:

除了识别重复的电话号码之外,可以进行的附加验证是评估质量和标准化前缀为“+”或“0”或(国家代码)的格式。以下脚本有助于在几秒钟内标准化数百万个电话号码。可以通过付费 API 进行进一步的精确验证,该 API 有助于在线后处理重复数据删除期间的验证。

def check_phone(phone, cc):
    try: 
        if int(phone) <1: return np.nan
        if phone== np.nan: return np.nan
    except:pass 

    phone= str(phone)
    cc= str(cc)#print(phone, cc)
    if len(phone)>4 :
        if phone != np.nan or cc != np.nan:
            cc_len = len(cc)
            if(phone[:1] == '+'):
                if phone[1:1+cc_len] == cc:
                    return phone
                else: return phone
            else:
                cc_len = len(cc)
                if phone[:1] == '0':
                    if phone[1:1+cc_len]== cc:
                        return phone.replace('0','+',1)
                    else: 
                        return phone.replace('0','+'+cc,1)
                else:
                    if phone[0:cc_len]== cc:
                        return '+'+phone
                    else:return '+'+cc+phone
    else: return np.nan # Function caller
%time 
account[['calling_code','contact_Phone']].apply(lambda x : check_phone(x.contact_Phone, x.calling_code),axis = 1)

重复的定义:

定义数据中的哪些重复是该过程的一个重要方面。根据正在解决的问题,重复的定义会发生变化。对于最常见的客户数据,通常是姓名、邮政地址、电话号码和电子邮件地址。这些将形成一组字段,用于查找评分和帮助识别重复。很少有字段(如电话号码或电子邮件)会给出重复的明确指示,另一方面,姓名或地址的重复实际上可以表示实际上是分离的个体。因此,这种情况应该通过半自动/自动验证过程。

最后的评分:

评分从基于城市/邮政编码与自身连接的表的自连接开始,然后使用模糊逻辑对其余列(如姓名、电子邮件和电话号码)进行评分。具有正确截止值的评分给出了数据中可能的重复列表,其余的将被丢弃。和往常一样,没有神奇的数字来确定临界值,需要几次迭代才能得出 0-100 之间的数字来定义数据的正确临界值。此外,每个列最好有不同的截止值,如下面的代码所示。

自联接后的结果表

# self-joining data based on the parameter
# Preparation of data for fuzzy
def joiner(cntry , file , mcol):
    df_string_all = account[(account.ShippingCountryCode == cntry)]
    df_string_all = df_string_all[address_match_columns]
    global dup
    dup = pd.DataFrame()
    parts = round(df_string_all.shape[0]/1000)
    start_time = time.time()
    if cntry == 'ie':
        mcol = mcol.replace('PostalCode','City')print(cntry.upper(), mcol)
    total_uni = len(df_string_all[mcol].unique())
    unique_col_value = df_string_all[mcol].unique()
    rem = ['xxxxx','Nan','', 'NAN', 'nan', np.nan]
    unique_col_value = [uni for uni in unique_col_value if uni not in rem]

    for i in range(1,parts+1): 
        my_list = unique_col_value[int(round(np.divide((1),parts)*total_uni*(i-1))):\
   int(round(np.divide((1),parts)*total_uni*i))]
        df_string = df_string_all[(df_string_all[mcol].isin(my_list))]
        df_string = df_string.merge(df_string, on= mcol , how = 'left', suffixes=  ('1', '2'))
        col_list = df_string.columns.sort_values().drop( ['Id1', 'Id2']).drop(mcol)df_string = df_string[(df_string.Id1 < df_string.Id2)]
        even = col_list[::2]
        odd = col_list[1::2]
        df_string = df_string[(df_string[['Name1' , 'Name2']].apply( lambda x:fuzz.token_sort_ratio(x['Name1'], x['Name2']), axis = 1) > name_match_cutoff)]
        if df_string.shape[0] >0:
            dup = dup.append(identifier(df_string, even, odd, mcol))
            del df_string
    del df_string_all
    end_time = time.time()
    print('Time taken for : ' ,cntry.upper() , mcol , round((end_time - start_time)/60,2) , ' minutes')
    print('Duplicates for : ',cntry.upper() , mcol, dup.shape)
    return dup

下面的块根据用户定义的截止级别识别数据中的重复项:

def identifier(df_string, col_even, col_odd, case):
    for i in col_even: 
        for j in col_odd: 
            if(i[:-1] == j[:-1]):
                new_col = i[:-1]+'_score'
                df_string[new_col] = df_string.apply(lambda x: fuzz.token_sort_ratio(x[i], x[j]) , axis = 1)
                df_string[new_col] = df_string.apply(lambda x: 0 if (pd.isnull(x[i]) | pd.isnull(x[j])) else x[new_col], axis=1)col_score =  [k for k in df_string.columns if 'score' in k]
    street_score = [k for k in col_score if 'Street' in k]
    city_score = [k for k in col_score if 'City' in k] +[k for k in col_score if 'Post' in k]

    if case == 'Name': 
        duplicate_con = df_string[((df_string[street_score]> street_match_cutoff).sum(axis= 1) > 0) &\
                                            ((df_string[city_score]> city_match_cutoff).sum(axis=1)>0)]        
    elif case == 'BillingStreet': 
        duplicate_con = df_string[((df_string[city_score]> city_match_cutoff).sum(axis=1)>0) & \
                                           (df_string['Name_score']> name_match_cutoff)]
    else: 
        duplicate_con = df_string[(df_string['Name_score'] > name_match_cutoff) & \
                                            ((df_string[street_score] > street_match_cutoff).sum(axis=1) > 0) & \
                                          ((df_string[city_score]> city_match_cutoff).sum(axis=1)>0)]
    if duplicate_con.shape[0] >0: 
        duplicate_con['2Final_Score'] = round((duplicate_con[col_score].mean(axis = 1)))
        duplicate_con['1Match_Case'] = case
        duplicate_con[case+'1'] = duplicate_con[case]
        duplicate_con[case+'2'] = duplicate_con[case]
        duplicate_con[case+'_score'] = 100
        duplicate_con= duplicate_con.drop(columns= case)

    return duplicate_con

函数调用程序

country = list(account.ShippingCountryCode.unique())
country = [e for e in country if e not in (['nan', np.nan])]
duplicate = pd.DataFrame()
duplicate_indi = pd.DataFrame()
start = time.time()for cntr in country: 
    file_name = 'account_'+ cntr
    for cols in ['MailingPostalCode', 'PostalCode']:
        duplicate = duplicate.append(joiner(cntr , file_name, cols))

end = time.time()
print('Total Time taken:' , round((end - start)/60,2) , ' minutes')

通过 LinkedIn 与我进行有趣的对话:www.linkedin.com/comm/mynetwork/discovery-see-all?use case = PEOPLE _ FOLLOWS&follow member = shreepadahs

参考文献:

[1]https://www . data core . com/blog/inline-vs-post-process-de duplication-compression/

深层空气:设计更健康城市的智能数据方法

原文:https://towardsdatascience.com/deep-air-the-smart-data-approach-to-designing-healthier-cities-8cef4bb2c33?source=collection_archive---------22-----------------------

如何利用正确的数据和机器学习的结合来塑造未来的智能城市

我们生活在一个越来越意识到生活在污染空气中的负面影响的社会里。结果,污染成为城市设计或重新设计时的一个关键问题。不幸的是,很难评估个人选择的影响,因为因果关系很难证实。由于人类行为对结果至关重要,问题就更加复杂了。幸运的是,城市规划者正在寻找方法来促使人们做出更好的个人选择。不幸的是,规划者没有必要的工具来评估必须做什么来减少污染,尤其是那些负担不起使用大型超级计算机的规划者。

尼克·范·登伯格在 Unsplash 拍摄的照片

人类对污染水平有相当大的影响。新冠肺炎疫情展示了我们的行为与城市空气污染的关联程度。在巴塞罗那,二氧化氮水平在 2020 年 3 月下降了 64%,达到了以前认为不可能达到的水平。将这一结果与多项研究表明 NO2 污染与糖尿病、高血压、中风、慢性阻塞性肺病和哮喘等健康问题相关的知识相结合。

我们在城市中面临的污染挑战是重要的,成功或失败的后果将会影响到每个人。为了发现我们可以做些什么,我们将我们的力量与 300,000 km/s 结合起来,这是一个巴塞罗那城市规划智库,致力于城市的智能数据。我们旨在智能地使用数据,使城市建筑师在考虑空气污染时做出更明智的决策。有了大量的数据,这从一开始就提出了重要的问题:什么数据是相关的?我们如何让数据变得智能?

照片由费迪南·斯托尔Unsplash 拍摄

我们的方法

我们的旅程从 Esteve 的厨房餐桌开始,我们讨论了一个有影响力和令人兴奋的项目的各种选择,这个项目将结束我们的商业分析硕士学位。我们很快就决定了智能城市的主题,Esteve 最近在这个领域做了一些研究。Esteve 联系了 300.000 km/s 的联合创始人 Mar 和 Pablo。在这八个月的旅程中,他们与 Esteve 一起为我们提供了帮助和支持,并在我们拐错弯时用他们的专业知识为我们提供了指导。没有他们,我们不会走这么远。

我们以 300.000km/s 提供的数据集开始了我们的项目。该数据集包含从移动蜂窝设备收集的关于西班牙个人移动的汇总旅行数据。西班牙被划分成大约 2500 个地区,所有在这些地区之间的旅行都被收集起来。学者们早就表明,二氧化氮与出行密切相关(最明显的是,来自柴油车)。为了巩固我们的原始数据,我们添加了大量的环境统计数据。这些指标从生活在这些地区的每个年龄组的人数到平均收入不等。

新冠肺炎疫情展示了我们的行为与城市空气污染的关联程度。

为了准确预测西班牙许多地区的二氧化氮水平,我们需要考虑建模技术。我们的模型结合使用了标准和不常见的机器学习技术。我们从头到尾使用了相关矩阵、随机森林回归树、基于图形的表示和空间滞后特征。当我们努力以最佳方式使用数据时,来自 300,000 km/s 的数据科学家 Andre 向我们介绍了空间滞后的概念。该功能以最佳方式利用了我们拥有的数据(即地理信息)的优势。通过这样做,我们可以将“空间性”引入我们的机器学习词汇。

因此,我们可以提取传统机器学习技术中通常会丢失的重要信息,如随机森林或 XGBoost。我们查看了莫兰的 I 系数,以确保我们只使用拥有完整信息的空间滞后特征。该系数是对空间自相关的一种度量,简单来说,它表示在地理上相邻的区域中利用相同质量的值的知识来预测元素的好坏程度。

我们的最终成果是一个模型,该模型使用“正常”和“空间滞后”特征的最佳组合来预测西班牙的 NO2 水平。我们开始了对 30 多个特征的最佳可能模型的初步搜索,并以使用八个特征来预测整个西班牙的 NO2 的模型结束。Moran 的 I 得分和不同特征之间的多次尝试在空间上是滞后的。我们建立了一个模型,预测整个西班牙 NO2 水平的准确率为 88.8%。我们发现,住宅建筑所占空间的百分比和表面积在 61 至 90 平方米之间的住宅数量是 NO2 水平的最有效预测因素。其他值得注意的预测因素是面积在 45 至 60 平方米之间的房屋和每平方公里 0 至 25 岁的人口数量。因此,我们可以主要利用居民信息精确预测 NO2 水平。这一见解显示了城市规划是如何影响宜居性的。

resall =pd.DataFrame()
res_w1 =pd.DataFrame()**from** **sklearn.ensemble** **import** RandomForestRegressor
**from** **sklearn.model_selection** **import** KFold
**from** **sklearn.model_selection** **import** cross_val_score

seed=7

kfold=KFold(n_splits=10, random_state=seed, shuffle = **True**)

num_trees=100
num_features=5
max_depth = 5
model12=xgb.XGBRegressor(colsample_bytree=0.4,
                 gamma=0,                 
                 learning_rate=0.07,
                 max_depth=3,
                 min_child_weight=1.5,
                 n_estimators=10000,                                                                    
                 reg_alpha=0.75,
                 reg_lambda=0.45,
                 subsample=0.6,
                 seed=42) 
model12.fit(mix_matrix,Y)

results_NO2_avg=cross_val_score(model12, mix_matrix, Y, cv=kfold)

print(f'Random Forest - Accuracy **{**results_NO2_avg.mean()*100**:**.3f**}**% std **{**results_NO2_avg.std()*100**:**3f**}**%')

res_w1["Res"]=results_NO2_avg
res_w1["Type"]="Random Forest"

resall=pd.concat([resall,res_w1], ignore_index=**True**)

随机森林-精确度 88.876%标准 1.376834%

plt.figure(figsize=(30,9))

**for** name, importance **in** zip(names, model12.feature_importances_):
    print(f'**{**name**:**15s**}**  **{**importance**:**.4f**}**')

sns.barplot(x=names, y=model12.feature_importances_)

income _ lag 0.0429
pob _ sale _ lag 0.0842
less 45 m2 _ per _ km2 0.0765
med _ small _ per _ km2 0.1632
large _ med _ per _ km2 0.2218
more 90 m2 _ per _ km2 0.0553
young _ per _ km2 _ lag 0.1494
housing _ PERC 0.2067

感谢大卫·卡列加罗彼得·布鲁因斯

pred2 = model12.predict(mix_matrix)

abs_diff2 = abs(Y-pred2)/Y
abs_diff2 = pd.DataFrame(abs_diff2)

abs_diff2 = abs_diff2.merge(df_tryout.geometry, how = 'left', left_index = **True**, right_index = **True**)
abs_diff2

abs_diff2 = gpd.GeoDataFrame(abs_diff2, crs="EPSG:4326", geometry='geometry')abs_diff2.NO2_avg = np.clip(abs_diff2.NO2_avg, 0, 1)
fig, ax = plt.subplots(1, figsize=(30, 20))
abs_diff2.plot(column='NO2_avg', cmap='gist_yarg', linewidth=0.8,ax = ax, legend=**True**)

地图精度(越暗精度越低)

关键的发现

我们陈述了这个项目的目标,提出了两个问题:什么数据是相关的?我们如何让数据变得智能?我们现在能够回答这两个问题,但是为了这样做,我们需要后退一步。

我们都同意,所有可用的数据现在和将来都不足以创建一个数字城市。此外,该模型即使可能也是不可扩展的,因为它需要为每个城市训练等量的数据。

那么,有办法避免这种情况吗?我们需要所有这些数据吗?换句话说,根据该模型可以做出哪些决策?

理想情况下,立法者可能会决定是否禁止卡车通过街道,限制交通流量,或者推广自行车。这些决策不仅粒度很低,而且很可能是二元决策(例如,我们的立法者会问自己:“这个周末我们是否应该禁止市中心的卡车通行?”).此外,在最乐观的情况下,这些离散的决策将仅适用于小范围的行动(例如,立法者可能允许使用三条车道中的两条)。

因此,我们不需要一个高度精确的模型,而是一个足够精确的模型,以帮助领导者在低粒度上进行干预。

我们模型的优势在于它能够完全扩展和灵活地适应各种场景。它可以输入合成数据,作为它建立在公开可用的数据源上。

乔纳森·罗杰在 Unsplash 上的照片

最终考虑

多个部门可以利用我们模型的结果。公共部门可能是主要的受益者,因为城市规划会影响污染。与目前使用的路线相比,通过采取创新战略减少各地之间的交通,城市可以以更低的成本产生更大的影响。这个模型将告诉我们,如果我们在整个结构中调整特定的交通流量,会发生什么情况。一个例子是在 Sant Cugat 建造办公室,以减少巴塞罗那的交通流量,从而改善巴塞罗那的空气质量。这一行动与当今政治家们试图在污染过高的地方制定措施时所采取的行动形成了鲜明的对比。

各国可以使用这些模型来检查他们的污染规划是否按照计划进行。我们的预测可以为已采取特定污染最小化措施的区域设定基准,并评估其成效。这种外卖将缩短成功创意的上市时间,因为确认结果所需的时间更少。此外,它还能更快地推出新想法,因为糟糕的想法会更快地被发现。结果将是节约成本和更好地保护环境。

照片由赫克托·阿圭略·卡纳尔斯Unsplash 上拍摄

Deep Brew:将星巴克转型为一家人工智能和数据驱动的公司

原文:https://towardsdatascience.com/deep-brew-transforming-starbucks-into-an-ai-data-driven-company-8eb2e370af7b?source=collection_archive---------16-----------------------

星巴克如何使用他们的人工智能平台 Deep Brew 不断创新,为咖啡爱好者提供世界级的体验

TRUnsplash 上拍照

如果你曾经进入过星巴克,你会同意它就像一个普通的咖啡馆:提供浓缩咖啡和拿铁咖啡,研磨咖啡,顾客与咖啡师交谈定制他们的咖啡订单。但是,在快速变化的市场条件下,为遍布全球 78 个市场的1 亿多顾客提供服务,要求这家咖啡巨头拥有完美的流程编排,并投资技术创新,将星巴克从一家饮料供应商转变为一家数据驱动的科技公司。Deep Brew 是他们成功的人工智能驱动平台,可以驱动品牌的个性化引擎,优化商店劳动力分配,并推动商店的库存管理。

但星巴克的数据转型早在 2019 年推出 Deep Brew 之前就开始了。因此,在我们放大咖啡巨头的人工智能驱动平台,帮助他们提供数据驱动的咖啡之前,我们将探索他们如何以各种方式利用数据为他们的业务和客户创造价值——巩固星巴克作为无可争议的咖啡店领导者。

数字飞轮:郊区客户体验的移动应用

星巴克在 2011 年推出了他们的移动应用,这标志着它进入数据和分析的切入点。事实证明,这是他们数字化转型的最大支柱之一。

起初,它旨在作为一个忠诚度计划,使顾客能够为每次购买收集星星,并在下一次饮料订单中兑换它们。这款应用很快成长为一个中心,顾客可以在这里获得关于菜单、商店位置和营业时间的信息。应用程序中的客户活动为星巴克提供了关于热门商店位置、饮料和一天中的时间的有用信息。

如今,星巴克每周 1 亿笔交易中,有四分之一是通过其移动应用进行的,随着社交距离措施的实施,这一趋势进一步加速。更重要的是,据雅虎财经报道,该应用的会员贡献了星巴克近 50%的收入。

作为其数字飞轮战略的一部分,星巴克移动应用程序允许咖啡爱好者提前下单,并通过商店窗口或走进商店领取。通过融合人工智能和营销的力量,该品牌扩展了其应用程序功能。现在,星巴克的数字飞轮由四个数字部分组成——奖励计划、个性化、支付和订购。

毫无疑问,星巴克的数字创新被认为推动了增长;他们已经成为借助数据创造忠诚客户的专家。

照片由埃里克·麦克莱恩Unsplash 上拍摄

星巴克如何从数据和人工智能中创造价值

早期,咖啡品牌已经意识到,使用数据分析来最大化他们的客户生命周期价值 ( 每位客户每次访问的平均购买价格、每位客户每年的访问次数以及平均客户生命周期)将是获得无与伦比的竞争优势的黄金入场券。

这家咖啡公司就是这样利用数据分析来最大化客户终身价值,同时重塑其品牌产品的:

个性化推荐

首先,收集和分析关于顾客消费和偏好的大量数据有助于星巴克根据每位顾客独特的偏好和消费习惯为他们提供个性化的顾客体验。通过分析订单的历史和模式,该应用程序可以建议食物和饮料的选择,但也可以根据顾客通常光顾咖啡店的时间和频率推送量身定制的建议。

通过发送实时触发和推送通知,星巴克与顾客建立了更深层次的联系。购买者注意到该品牌考虑到了他们的偏好,并以定制他们的体验为乐。

创新和新产品供应

除了个性化,星巴克还利用从他们的数字飞轮收集的数据来创造新产品。他们所有的创新产品,如无奶或无糖饮料、夏季特别饮料或新的家庭消费产品,都是分析用户偏好及其背后的数据的结果。

例如,星巴克发现,约 43%的喝茶者在茶中不加糖,约 25%的人在家喝冰咖啡时不加牛奶。这些见解导致了两种不加糖的冰茶 K 杯——芒果绿冰茶和桃子红茶。他们数据工作的其他一些成果是南瓜香料拿铁咖啡和不加牛奶或香料的冰咖啡。

开设新店

你可能会觉得每个角落都有一家星巴克店,但实际上,他们会仔细使用飞轮数据来确定每个新星巴克店的最佳位置。这家咖啡巨头利用数据和人工智能,根据收入水平、流量或竞争对手的存在等变量进行收入预测,并帮助确定下一个重大收入机会在哪里。同时,这使他们能够最大限度地降低自相残杀的风险,并将新店定位在服务于特定客户群的区域。

照片由阿萨埃尔·培尼亚Unsplash 上拍摄

Deep Brew:提升人性、商业和客户体验的平台

在接受雅虎财经直播(Yahoo Finance Live)采访时,星巴克(Starbucks)的前首席运营官罗兹·布鲁尔(Roz Brewer)表示,咖啡连锁店的科技未来专注于不断增长的免下车商店,包括可定制的菜单板,这些菜单板利用人工智能根据天气、时间、商店库存、人气、社区偏好和客户的购买历史等因素来建议商品。

他们的人工智能驱动平台 Deep Brew 允许他们利用人工智能和人工智能进行创新,不仅可以个性化得来速体验,还可以自动化耗时的任务,如库存管理和对其物联网(IoT)连接的咖啡机进行预防性维护。

通常,当人们听到技术和自动化正在融入工作场所时,他们会开始担心自己的工作正在被机器人和机器接管。

然而,星巴克首席执行官凯文·约翰逊、星巴克首席技术官格里·马丁-弗利金格和其他人有一个愿景,他们正在宣扬人工智能不是为了取代人的工作。相反,他们认为人工智能可以用于在工作场所增强人性,帮助人们找到融入人性的方法,腾出时间让员工积极与客户联系,并提供重要的个人联系。

在星巴克的新闻博客中,马丁-弗利金格表示,她认为人工智能适用于商业的几乎每个方面——技术、金融、法律、供应链、营销或零售店。

Martin-Flickinger 解释说,通过他们的人工智能技术倡议 Deep Brew,他们正在研究有助于增强人类联系的技术。广泛的人工智能工具套件将提升业务的各个方面以及店内和客户体验。

但这是否意味着我们很快就会看到穿着围裙的机器人在星巴克为我们点餐?一点也不。Deep Brew 更像是人类咖啡师的一个无形、超级智能的助手,帮助他们处理库存、供应链物流和补货订单,节省合作伙伴的时间,预测员工需求和制定时间表。它还可以帮助进行预测性维护,在咖啡机出现故障之前提醒员工。

深度酿造的路线图

星巴克数据科学和分析运营首席经理布赖恩·艾姆斯在他的数据创新峰会2020 talkDeep Brew-星巴克的机器学习-路线图 期间表示,Deep Brew 计划于 2019 年首次推出,并将 ML 引入咖啡公司,帮助他们在其大型组织中将模型部署到生产中。

他们以 Deep Brew 开始销售的风来自竞争对手麦当劳收购 Dynamic Yield 公司的战略举措,该公司旨在将强化学习和机器学习引入快餐领域。这一事件促使星巴克 C-suite 开始寻找对这一举动的回应,并开始思考将机器学习融入到自己的业务中。Deep Brew 是对瞬息万变的市场变化的完美回应和解决方案。

了解更多关于数据创新峰会的信息

Deep Brew 在去年 COVID world 的免下车活动中发挥了特别重要的作用。有了它,他们可以在不同的免下车商店的屏幕上个性化推荐。Brian 解释说,每个国家的每家商店都有其独特的个性,此外还有其他因素,如星期几、一天中的温度、客流量等。这些都是星巴克在设计由 Deep Brew 驱动的推荐系统时能够应用的要点。

“先进的技术,快速部署的能力和一些先进的大脑对星巴克来说是一个很好的解锁,Brian 肯定地说。

本杰明·拉斯科在 Unsplash 上的照片

在深层酿造的引擎盖下

Brian 说,Deep Brew 提供的所有东西都要归功于星巴克拥有的惊人数据和基础——他们的企业数据分析平台 EDAP 或统一不同来源数据的数据湖。从湖中,他们获取数据,将其加载到他们的 Deep Brew 平台,运行到计算层,输出到达不同的接触点并与之对话,如移动应用程序、数字免下车服务、网站、社交媒体。

然而,像 Deep brew 这样的机器学习系统很难组装起来,因为它是一个跨功能的复杂解决方案。ML 系统只有一小部分是由 ML 代码组成的。为了使解决方案取得成功,还应该导航所有其他组件,例如数据收集、数据验证、特征提取、流程管理工具、分析工具等。,应该导航。为了训练模型并获得预期的结果,团结所有其他团队并让他们理解在所有维度上保持卓越的重要性是极其困难的。

Brian 认为,这就是为什么很难从一个人的头脑或研究中获得一个概念,并将其大规模应用于一个大型组织。

如今,他们的 Deep Brew 平台发展良好,并向客户提供高度个性化的推荐。但要达到这一阶段,星巴克必须浏览以上所有内容,并吸取一些惨痛的教训——或者像布莱恩所说的“要避免的七宗罪”。

在像 Deep Brew 毕然共享这样的大型组织中大规模部署机器学习系统时,需要避免的一些陷阱是:

  1. 对组织中的其他人没有有意义的和一致的提升
  2. 没有基线来确保不损害现有的操作
  3. 对不同的工作影响没有明确的预期:它会“提升”还是取代他们的工作
  4. 不容易获得安全指南和专业知识
  5. 不考虑操作
  6. 拥有多线程或具有冲突优先级的人员——没有定期召开全体会议的专门团队
  7. 告诉人们这是不可能的,却没有表现出来。

在 2020 数据创新峰会上看完整届布赖恩·艾姆斯

星巴克的数据驱动未来是什么样子的?

作为数字飞轮计划的一部分,Deep Brew 为星巴克带来了巨大的成功。这使得他们的客户群在 2019 年底大幅增长至近 1800 万,使在美国的同店销售额增长了 6%

除了数字上的增长,人工智能平台显然帮助这个咖啡品牌实现了他们的雄心,将自己打造成一家数据公司,而且是一家自我维持的公司。这意味着星巴克收集的数据越多,它就越能做出正确的决定来发展业务。

在节省时间的人工智能驱动的助手的推动下,星巴克的员工和合作伙伴可以将他们的时间投入到业务中最重要的部分——咖啡和客户。提供完全个性化的、周到的产品选择给顾客一种温暖的感觉,即他们的偏好很重要,并极大地影响了他们对受喜爱的咖啡品牌的感情。

此外,运营世界级的技术也让这家咖啡连锁店有能力招募一些最优秀的技术人才,转移了一些渴望在科技巨头工作的候选人的注意力。

“在未来 10 年,我们希望在人工智能方面像科技巨头一样优秀,”星巴克总裁兼首席执行官凯文·约翰逊在 Marketing Dive 中引用。星巴克的战略是以人为本的数字化战略。约翰逊补充说,正是这种愿景促使人们想要在一个能够影响世界积极变化的环境中做出贡献。

原载于 2021 年 6 月 30 日 https://hyperight.comhttps://hyperight.com/deep-brew-transforming-starbucks-into-a-data-driven-company/

对数据集中缺失值的深入分析

原文:https://towardsdatascience.com/deep-dive-analysis-of-missing-values-in-dataset-b387d9de6d4b?source=collection_archive---------37-----------------------

缺失数据的类型有哪些,并举例说明?

图片由来自 PixabayGino Crescoli 拍摄

现实世界的数据集通常有很多缺失值。数据集中出现缺失值的原因可能是信息丢失、上传数据不一致等等。需要输入缺失值,以便进行模型开发流程的下一步。在输入缺失值之前,了解数据集中缺失值的类型非常重要。

为什么丢失数据是一个问题

数据集中出现的缺失值会在数据集中产生偏差,从而影响模型的性能。这种偏见会导致数据集中缺乏相关性和可信度。价值的损失可能包含模型开发的关键见解或信息。

数据集中缺失的值可以是有意缺失的、随机缺失的,也可以是由于某种原因而缺失的。因此,丢失的数据被认为是一个问题,需要在进行下一个模型开发之前进行处理。

缺失数据大致可分为三类,需要计算,缺失值的输入仅取决于要素所在的缺失数据类别:

  • 完全随机失踪(MCAR)
  • 随机失踪(MAR)
  • 非随机缺失(MNAR)

完全随机失踪(MCAR):

MCAR 是指缺失值不是故意缺失而是随机缺失的情况。丢失的值与同一列中的其他值或其他列中的值无关。

通过利特尔的 MCAR 测试,很容易检查这些值是否完全随机缺失。此外,如果您可以使用一些插补方法、回归或其他方法来预测缺失值,那么缺失数据很可能不是 MCAR。

  • 缺失值完全是随机的
  • 缺失值与其他观察值或未观察值无关。
  • 缺失值在缺失数据和数据值之间没有关系。

示例:

(图片由作者提供),MCAR 的例子

随机缺失(三月):

MAR 是指数据的缺失在数据的子组内的情况,它也影响其他值。变量中缺失数据的概率与数据中的其他变量相关。MAR 导致数据中存在依赖性,这导致模型的偏差和可靠性受损。

  • 缺失在一个子群中
  • MAR 可能导致数据偏差。
  • 缺失值取决于其他变量。

举例:

(图片由作者提供),MAR 示例

非随机缺失(MNAR):

MNAR 是指值不是随机遗漏,而是故意遗漏的情况。变量上缺少的值与该变量本身的值有关,即使在控制了其他变量之后也是如此。这种缺失可以系统地与未观察到的数据联系起来。由于多种原因,MNAR 缺失值未被捕获。MNAR 也会导致数据的偏倚。

  • 缺失数据与未观察到的数据有关。
  • 遗漏可能与未测量的事件或因素有关。

示例:

(图片由作者提供),MNAR 示例

缺失数据机制:

基本上有两种方法可以将数据归类到缺失数据机制中。

  1. 常识:大多数研究者都有缺失值原因的想法。重要的是要考虑丢失数据和数据收集过程背后的原因。
  2. 统计测试:将缺失数据归入缺失数据机制的另一种方法。将缺失值列分为两组,一组包含“薪金”列的完整数据,另一组包含缺失数据。然后创建一个二分变量或缺失数据指示器,指示“薪金”是否缺失。然后用 t 检验计算组间差异。
  • 使用缺失数据指示变量作为分类 ML 模型的结果,并测试数据中的其他变量是否与该结果相关。如果我们找到与缺失数据指标相关的变量,我们可以得出结论,数据不是 MCAR。
  • 我们永远分不清 MAR 和 MNAR。我们只能测试数据是 MCAR 的还是 MCAR 的。

此外,将统计测试与常识相结合总是很重要的。大多数处理缺失数据的过程都依赖于 MAR 假设。

结论:

在本文中,我们讨论了数据集中缺失值的类型或类别。还讨论了如何在上述类别中对缺失数据进行分类的进一步挑战。

阅读下面提到的文章,了解处理数据集中缺失值的流行策略

</7-ways-to-handle-missing-values-in-machine-learning-1a6326adf79e>

感谢您的阅读

深潜:人工神经网络

原文:https://towardsdatascience.com/deep-dive-artificial-neural-network-e77aa627dc1b?source=collection_archive---------37-----------------------

人工神经网络中涉及的完整解释和数学

蒙罗工作室在 Unsplash 拍摄的照片

什么是安?

ANN 代表人工神经网络。就像人类拥有 BNN 即生物神经网络一样,研究人员试图复制人脑的工作,并提出了人工神经网络的伟大发明。它是一种机器学习算法,现在广泛应用于各个领域。无论是检测 COVID 和癌症等疾病,还是检测图像中的人体姿势。安什么都做。这是迄今为止机器学习研究最多的部分之一。

(图片由作者提供)

最小级别的人工神经网络称为感知器。感知器也称为阈值逻辑单元(TLU)。它由单个单元组成,也称为神经元,具有多个输入和单个输出。这是一种最简单的人工神经网络结构。

(图片由作者提供)TLU(阈值逻辑单元)的结构

(图片由作者提供)具有偏差的多感知器网络的表示。

为了理解以下感知器模型,将神经元/单元的输入视为数据集的特征,您将在其他机器学习算法中输入这些特征。看看感知器的图表,输入通过称为权重的线与神经元相连。当输入被传递时,它们被单独乘以它们的权重,并且所有这些乘法的总和被传递到阶跃函数上以产生输出。阶跃函数用于提供以下计算的输出。有时,偏差也被添加到输入或 TLU,以向右或向左偏移加权和的结果。这有助于模型更好地适应数据,因为它不仅可以调整网络的权重,还可以调整网络的偏差,使网络适应所需的数据集。因此,神经网络输出的计算公式为:

(图片由作者提供)计算简单图层的输出。

其中 phi 是激活函数,X 是输入矩阵,W 是权重矩阵,B 是偏差。

(图片由作者提供)感知机中使用的 Heavyside step/ activation 函数。

当模型有一个输入层、多个隐藏层和一个输出层时,这就是所谓的 MLP(多层感知器)。它的工作类似于感知器,但输入连接到第一层的一些权重,这些权重连接到其他一些输出神经元的一些权重。与感知器类似,首先,输入乘以它们的权重,然后相加传递给阶跃函数。然后,所有神经元的这个阶跃函数的输出乘以权重并相加。然后将其传递到阶跃函数,以获得网络的输出。

当您组合多个神经元以形成深度神经元层并将这些层堆叠成深度堆叠模型时,则该模型被称为人工神经网络。人工神经网络属于深度学习部分,是当今使用最多的算法之一。

如何训练一个 ANN?

使用称为反向传播的算法来训练人工神经网络。首先,采用单个训练实例,并执行正向传递以产生输出。然后将网络损耗与实例的实际输出进行比较。然后这种损失通过整个神经网络反向传播。在反向传播的这一步骤中,首先计算损失的梯度,因为我们必须使损失最小化。然后,计算网络的每个权重矩阵的梯度,并且通过减去η(即网络的学习速率)和损失函数的梯度的乘积来更新权重矩阵。接下来的过程一直持续到最后一层,这个步骤被称为反向传播算法的反向传递。

(图片由作者提供)人工神经网络的训练

人工神经网络可以有单个输出,甚至多个输出。所有训练实例通过网络的单次向前和向后传递被称为单个时期。学习复杂模式所需的深度神经网络必须执行各种时期以获得良好的预测结果。

什么是步进/激活功能?

阶跃/激活函数用于给网络增加非线性。如果网络的输出没有非线性,那么网络可能无法预测复杂的模式。因此,激活功能也用于此目的。使用的一些激活功能有:

  1. ReLU(整流线性单位)激活功能
  2. Sigmoid 激活函数
  3. Tanh 激活函数

还有更多……

ReLU 激活功能

(图片由作者提供)ReLU 激活函数的表示

(图片由作者提供)ReLU 激活函数的数学表示

Sigmoid 激活函数

(图片由作者提供)Sigmoid 激活函数的表示

(图片由作者提供)Sigmoid 激活函数的数学表示

Tanh 激活函数

(图片由作者提供)Tanh 激活函数的表示

(图片由作者提供)Tanh 激活函数的数学表示

安在回归

回归分析中的人工神经网络有助于预测房价或某个对象边界框的坐标。在基于回归的人工神经网络中,通常不使用激活函数来防止值处于激活函数的范围内。用于训练神经网络的损失函数是均方误差或均方根误差。大多数情况下使用均方误差和均方根误差,但在异常值的情况下,使用平均绝对误差,因为它有助于减少异常值的影响。

(图片由作者提供)

人工神经网络分类

分类中的人工神经网络有助于根据提供的输入值预测类别。从分类狗或猫到分类复杂的人类情感,人工神经网络在各种问题中都有应用。当有 2 个类别要预测时,我们甚至可以使用具有单个输出和逻辑激活函数的神经网络作为最后一层的激活函数。当我们有多个类别要预测时,如果我们希望所有类别的输出值都等于 1,我们可以使用 softmax 激活函数。交叉熵损失函数可用于训练网络。在多类分类中,我们必须为每个类分配一个神经元。

(图片由作者提供)

参考

  1. 使用 Scikit-Learn、Keras 和 TensorFlow 进行机器学习,第二版,Aurélien Géron,2019 年
  2. 麻省理工 6。S191:深度学习介绍,【https://www.youtube.com/playlist? list = PLT bw 6 njqru-rwp 5 _ _ 7c 0 oivt 26 zgjg 9 ni

我希望这篇文章和解释对你有用。请继续关注后续部分中的其他分段技术。

请随时联系并给出你的建议:【https://www.linkedin.com/in/mrinal-tyagi-02a1351b1/

https://github.com/MrinalTyagi

通过阿帕奇齐柏林飞艇深入三角洲湖

原文:https://towardsdatascience.com/deep-dive-into-delta-lake-via-apache-zeppelin-d59db1673584?source=collection_archive---------11-----------------------

以互动的方式了解三角洲湖泊的内部机制

Delta Lake 是一个开源项目,支持在数据湖的基础上构建一个 Lakehouse 架构。网上有很多关于如何使用三角洲湖的教程。这个帖子有点不同,是给那些好奇想了解 Delta Lake 内部机制,尤其是事务日志的人看的。

启动齐柏林码头集装箱

为了更直观地演示内部机制,我使用 Apache Zeppelin 运行所有示例代码。你可以通过 Zeppelin docker 轻松复制我所做的。关于如何在 Zeppelin docker 中玩 Spark,可以查看这篇文章。这里我只总结为以下几个步骤:

  • 第一步。git 克隆https://github.com/zjffdu/zeppelin-notebook.git
  • 第二步。下载 Spark 3.1.2(这个是我在这个教程里用的,不要用 Spark 3.2.0,还不支持)
  • 第三步。运行以下命令启动 Zeppelin docker 容器。${zeppelin_notebook}是您在步骤 1 中克隆的笔记本文件夹,${spark_location}是您在步骤 2 中下载的 Spark 文件夹。
docker run -u **$(**id -u**)** -p 8080:8080 -p 4040:4040 --rm -v ${spark_location}:/opt/spark -v ${zeppelin_notebook}:/opt/notebook -e ZEPPELIN_NOTEBOOK_DIR=/opt/notebook -e SPARK_HOME**=**/opt/spark -e ZEPPELIN_LOCAL_IP=0.0.0.0 --name zeppelin apache/zeppelin:0.10.0

然后打开 http://localhost:8080 ,打开笔记本Spark/Deep Dive into Delta Lake,里面有这篇文章的全部代码。

齐柏林飞船主页(图片由作者提供)

配置火花

火花配置(图片由作者提供)

这是Deep Dive into Delta Lake,第一段就是配置 Spark 解释器使用 Delta Lake。

%spark.conf是一个特殊的解释器,用来在 Zeppelin 中配置 Spark 解释器。在这里,我按照快速入门中的描述配置 Spark 解释器。除此之外,我显式地指定了仓库文件夹,这样我就可以在本教程的后面轻松地检查表文件夹。现在让我们开始使用 Spark,在 Zeppelin 中播放 Delta Lake。

创建增量表

首先让我们创建一个包含两个字段的增量表events: id 和 data。

创建增量表(图片由作者提供)

那么 Delta 在这个 create SQL 语句下面做什么呢?实际上,达美做了两件事:

  • 在仓库文件夹/tmp/warehouse下创建一个目录events
  • 添加包含该表模式的事务日志

作者图片

插入数据

现在让我们将一些数据插入到这个增量表中。这里我只插入了 2 条记录:(1,data_1),(2,data_2)

插入数据(图片由作者提供)

然后让我们运行一个 select SQL 语句来验证这个 insert 语句的结果。

查询表(作者图片)

那么 Delta 在这个 insert SQL 语句下面做了什么呢?让我们检查表格文件夹/tmp/warehouse/events,有 2 个变化

  • 生成另一个新的事务日志文件。
  • 生成 2 个拼花文件

作者图片

首先,我们来看一下新生成的事务文件(000000000000000001.json)。这个 JSON 文件可读性很强,它包含了这个 insert SQL 语句的操作:添加包含 2 条记录的 2 个 parquet 文件。需要注意的是,这个新的事务日志文件中没有表模式信息,因为它已经在第一个事务日志文件(00000000000000000.json)中。当 Delta 读取该表时,它将合并此后的所有历史事务文件,以获得该表的所有信息(包括该表的模式以及包含哪些数据文件)

因为我们只插入 2 条记录,所以很自然地猜测每个拼花包含一条记录。我们可以直接读取这两个拼花文件来验证这一点。如下面的代码所示,我们的猜测是正确的。

作者图片

更新数据

Delta 最重要的特性是 ACID 支持,你可以在任何时候更新表而不影响同时读/写同一个表的其他人。现在让我们更新这个events表。

更新数据(图片由作者提供)

然后运行 select 语句来验证这个 update 语句的结果。

作者图片

那么这个 update 语句在底层做什么呢?我们可以检查events 表文件夹,会发现 2 处变化:

  • 生成另一个新的事务日志文件
  • 添加了另一个拼花文件(之前的两个拼花文件仍然存在)

作者图片

首先,让我们看看新事务日志文件的内容,这里有 2 个操作:

  • 移除一个拼花文件
  • 添加新的拼花文件

我们很自然地猜测,被移除的文件包含记录(2,data_2),而新添加的文件包含记录(2,data_2_updated)。让我们直接读取这两个 parquet 文件来验证我们的猜测。

作者图片

现在让我们使用德尔塔的时间旅行功能。我们希望在此更新操作之前使用此表的最新版本。

作者图片

时间旅行功能之所以有效,是因为 Delta 不删除数据文件,它只在事务日志中记录所有操作。当您阅读该表的版本 1 时,Delta Lake 将只阅读前两个事务日志:00000000000000000 . JSON & 000000000000001 . JSON。

删除数据

现在让我们对这个events表进行删除操作。

删除数据(图片由作者提供)

然后运行 select 语句来验证 delete 语句的结果。

作者图片

那么 Delta 在底层对这个删除操作做了什么呢?我们仍然可以检查events表文件夹,并会发现 2 处更改:

  • 生成新的元数据事务日志文件
  • 添加了一个新的拼花文件

作者图片

在新的事务日志文件中,我们仍然可以看到两个操作:removeadd

人们很自然地会猜测删除操作只是删除了包含 record (1,data_1)的文件,那么这个新的add操作是做什么的呢?实际上,新添加的 parquet 文件是空的,其中不包含任何内容,我们可以直接读取这两个 parquet 文件来验证这一点。

作者图片

摘要

在这篇文章中,我做了 4 个主要步骤来玩三角洲湖:

  • 创建表格
  • 插入数据
  • 更新数据
  • 删除数据

在每一步,我都检查事务日志和数据文件中发生了什么变化。所有步骤都是在 Apache Zeppelin docker 容器中完成的,您可以轻松地再现它们,希望本文对您了解 Delta Lake 的内部机制有用。

参考

http://zeppelin.apache.org/ https://databricks.com/blog/2019/08/21/diving-into-delta-lake-unpacking-the-transaction-log.html https://databricks.com/blog/2020/09/29/diving-into-delta-lake-dml-internals-update-delete-merge.html

深入研究集成梯度的神经网络解释

原文:https://towardsdatascience.com/deep-dive-into-neural-network-explanations-with-integrated-gradients-7f4b7be855a2?source=collection_archive---------31-----------------------

提示和技巧

从业者指南

深度神经网络是一种被高度利用的模型,在图像、自然语言处理和时间序列等特定领域取得了巨大成功。虽然这些模型在这些专业领域的功效是无与伦比的,但神经网络由于其不透明性而经常被认为是“黑盒”模型。

考虑到这一点,我们如何能够窥视并理解神经网络呢?模型不可知的可解释性方法,如莱姆、SHAP 和 QII [2]确实存在,它们在黑盒假设下运行,即只有输入和输出是已知的。然而,对于神经网络来说,这些方法的计算成本可能是不切实际的,因为神经网络的特征数量往往比其他领域(如表格数据)高一个数量级。图像将具有多个通道的数千个像素,时间序列数据引入了时间维度因子,NLP 模型通常利用高维嵌入空间来编码语言。幸运的是,神经网络的训练过程和框架通常取决于梯度下降法。网络梯度的可用性提供了创建解释的替代过程,该过程提供了额外的输入,既有助于解释方法的速度,也提供了解释的公理化好处。

这个博客将详细解释积分梯度(IG)方法,包括数学基础,它与其他方法的比较,以及你如何自己使用它。所示的例子在图像领域很容易说明,但 IG 可以用于任何深度学习任务。

pix abay 上 StockSnap 的原始图片和作者编辑的图片|左:原始图片|中:小猎犬的综合渐变说明|右:山地车的综合渐变说明

什么是综合梯度法?

综合梯度是由 M. Sundararajan,A. Taly,Q. Yan 在的《深度网络的公理化归属中提出的。计算输入记录 x 和基线记录 x’的综合梯度属性的等式如下:

让我们从分解这个等式的组成部分及其背后的动机开始。我们将从在我们的博客文章中引用的解释分类法中结合集成的梯度开始:选择一种解释技术。在我们的分类法中,我们必须为解释技术定义:范围&输出、输入、访问和阶段。

第一部分是我们试图解释的范围和结果。积分梯度足够灵活,可以解释输入 x 上任何可微分函数的输出,最直接的函数是神经网络分类器的标量输出。在上面的等式中,这是在 x 上操作的 F 函数。IG 方法的范围是全局和局部的。这是如何实现局部和全局范围的,最好在下一节进一步阐述这些原则后再讨论。

被解释的输入将是神经网络可以操作的 x 向量。最简单的情况是网络的顶层输入,尽管情况可能不总是这样。例如,在 NLP 用例中,解释必须在嵌入空间,而不是句子输入,因为梯度不能从嵌入字典传播。
K. Leino,S. Sen,a .,,和 L. Li 在对深度卷积网络的影响导向解释中也提出了一种解释网络内部层的方法,以供进一步分析。

最后,本说明的阶段和访问是访问网络梯度的岗位培训。推理是这样的,我们需要查询并从神经网络中获取导数,因为模型有助于组成函数 F

公理

IG 满足了一些理想的公理,这些公理在论文[1]中进行了概述。我们将强调对解释方法特别重要的两个公理:

  1. 完备性公理
  2. 敏感性公理

使用 IG 的主要动机是完整性公理。也就是说,“给定 x 和基线 x’,x 的属性加起来就是输入 x 处的 F 的输出和基线 x’“[1]”之间的差。该属性是可取的,因为它直接将属性与对 F 函数的贡献联系起来,并针对输出标量向每个输入分量给出局部解释比例权重。使这成为可能的机制是由于沿着路径的函数的积分和导数的逆性质,允许函数值的重建。

在这一点上,可以适当地描述为什么这也是实现一组适用于解释分类法中的全局范围的解释所需要的。除了选择一个恒定的基线之外,实现完整性公理意味着一个记录的每个解释都可以与不同记录的任何其他解释相比较。所有属性的相对贡献都在同一标度上,即 F 函数输出的标度。这可能是概率单位空间中的[0,1],或者是 logit 标度上的(-inf,inf)。

IG 方法的第二个理想公理是灵敏度公理。这个公理分两部分描述。
1。“对于在一个特征上不同但具有不同预测的每个输入和基线,不同的特征应该被赋予非零属性。”【1】
2。“如果深度网络实现的功能(在数学上)不依赖于某个变量,则该变量的属性总是零。”[1]

一般来说,梯度会违反这个公理。IG 等式的最后一部分α表示从基线到 x 值的路径,有助于解决这个问题。相对于α的导数产生一个乘法因子(x-x’),这意味着如果基线和 x 值对于某些 xᵢ是相同的,则没有属性提供给该输入。换句话说,路径线积分同时满足完备性和敏感性公理,因为梯度仅沿着观察基线变化的 k 维路径收集。

积分梯度建议使用 x '和 x 之间的直线路径,这主要是为了满足对称公理:“如果交换两个输入变量不改变函数,则它们是关于函数对称的。例如,x 和 y 是对称的 w.r.t. F 当且仅当对于 x 和 y 的所有值 F (x,y) = F (y,x】[1]。虽然这确实成立,但应该注意的是,对基于 IG 的归因的进一步研究可能不需要满足这一公理。直线路径存在局限性,因为插值可能会穿过网络决策流形中的分布点。只要 F 是连续可微的,沿 k 维内任何路径的梯度积分将满足完备性和敏感性公理。

方法比较

值得比较和考虑不同解释方法之间的根本差异,以及使用 IG 相对于其他常见解释方法的利弊。

集成的梯度和显著图

我们先来比较一下 IG 和另一个常见的梯度解释器:显著图。在最简单的意义上,显著图是神经网络的输入特征相对于最终输出的梯度。这种解释突出了最易起反应并可能迅速改变输出的特性,但只对偏离原始输入的小偏差有意义。IG 的完整性公理给出了输出内容的更强(和更完整)的表示。这是因为为显著图接收的梯度通常在模型的饱和梯度区域中。

图片由作者提供,灵感来自 Ankur Taly 的解释机器学习模型——斯坦福 CS 理论

在类似的比较中,显著图和 IG 之间的关系类似于 LIME 和 Shapley 值之间的关系。

综合梯度&沙普利值

比较 IG 和 QII [2]等基于 Shapley 的方法的最好理由是,因为这两种方法给出的解释可以用于局部和全局,因为它们满足类似的公理。IG 的完备性和敏感性公理类似于我们博客中提到的效率和伪公理:ML 模型的 Shapley 值

综合梯度和基于 Shapley 值的策略采用两种不同的方法来逼近 Shapley 值。Shapley 值推广到称为 Auman-Shapley 值的无限连续区域。这些概念植根于联盟博弈理论,旨在平均所有环境的影响。对于 Shapley 值,空间是阶乘的,因此使用抽样方法。对于 Auman-Shapley 值,空间是无限的,但是积分梯度直线路径也可以被认为是保存了 Auman-Shapley 值的理想公理的唯一样本。

从这个意义上说,抽样的差异就是理论差异的所在。QII 在 x 附近构建了一组假设记录,通过测试某个特性是否始终是输出的驱动因素,或者其他特性的变化是否会使某个特性的值影响较小,从而使解释更加可靠。你甚至可以认为这些类似于梯度,只是步长更大。另一方面,IG 只选择一条路径,但沿着这条路径采集许多样本。通过这样做,IG 确实因为没有评估那么多假设路径而失去了一些健壮性。另一方面,由于神经网络的连续可微性质,样本可以比离散 Shapley 值方法具有更强的分布忠实性。

没有强有力的理由证明哪种方法在理论意义上更好,所以通常选择实用的方法。QII 是一种不需要访问模型内部的方法,因此对更广泛的模型架构更有用。神经网络域具有更高的维数,其中离散 Shapley 值采样方法通常是难以处理的。x 附近的记录空间太大,对于具有数千个输入的模型来说,没有统计意义上的结果。梯度的可用性允许进行可管理的计算量。这种估计是通过在 x 和 x’基线之间的直线的离散分区处取梯度并乘以激活乘数(x-x’)来完成的。如果梯度流形足够平滑,10–20 次离散分割就足够了。在高度不稳定的流形中,可以采用更多的插值点,但在实践中,很少需要超过 100 个点作为接近的估计量。

有进一步的研究可以弥补基于 IG 和 Shapley 值的方法之间的上下文差距,例如找到有代表性的中性基线,拥有多个基线,或者使用语义上有意义的基线,例如接近决策边界。一种这样的方法是边界属性变化[4],它设置最近的类边界作为基线。

实践中的综合梯度

本博客的其余部分将强调在实际环境中使用 IG 时要做出的许多选择。在实践中使用 IG 时,一个从业者可以做出的选择相当多,灵活性是必不可少的。下面的文章将使用一个名为 TruLens 的开源渐变解释库来展示 IG 如何在实践中使用。代码示例将引用兴趣分布(DoI)、兴趣数量(QoI)和自定义内部影响方法,这些都是 TruLens 的构建模块,在:用 TruLens 解释神经网络的实用介绍中有概述。

将集成渐变转换为代码

在前面的章节中,IG 被定义为连续空间中的函数,但是我们也强调了可以通过直线插值的离散分割来进行估计。

TruLens 有一个随时可用的 IG 实现,它忠实于原始方法。

from trulens.nn.attribution import IntegratedGradients
from trulens.visualizations import MaskVisualizer# Create the attribution measure.
ig_computer = IntegratedGradients(model, resolution=10)# Calculate the input attributions.
input_attributions = ig_computer.attributions(beagle_bike_input)# Visualize the attributions as a mask on the original image.
visualizer = MaskVisualizer(blur=10, threshold=0.95)
visualization = visualizer(input_attributions, beagle_bike_input)

原始图片由 StockSnap 在 Pixabay 上拍摄,并由作者编辑|可视化 Beagle 类解释:集成渐变

IG 的实现和定制也很简单,利用 TruLens 兴趣分布(DoI)。DoI 表示一组要平均的记录;对于 IG,我们希望使用基线的线性插值。TruLens 开源实现定义了这种线性插值 DoI,仅此一项就足以开始在 IG 上创建定制。https://github . com/truera/trulens/blob/master/trulens/nn/distributions . py

TruLens DoI 对分布中的所有梯度进行平均。为了应用 IG 的敏感性,LinearDoI 还定义了 get_activation_multiplier。

您可以继承 TruLens DoI 类来实现自己的 DoI。一旦定义了 DoI,就可以使用 InternalInfluence 方法构建自定义属性。

from trulens.nn.distributions import DoIclass MyCustomDoI(DoI):
    def __call__(self, z):
        ... def get_activation_multiplier(self, activation):
        ...from trulens.nn.attribution import InternalInfluence 
from trulens.nn.quantities import MaxClassQoI
from trulens.nn.slices import InputCut, OutputCut, Slice# Define a custom influence measure
infl = InternalInfluence(model, 
    Slice(InputCut(), OutputCut()),
    MaxClassQoI(),
    MyCustomDoI())

如果要尝试不同的路径策略,DoI 将是最佳选择。

输出功能的定制

集成梯度的另一个定制区域是将要解释的输出 F 。你可以选择解释 logit vs probit 层。解释这两种情况的原因取决于最终的用例。模型概率会对分数做出准确的贡献,而 logits 可能会对记录给出更好的比较分数,这些记录更接近概率单位空间的 1 或 0 区域,这些区域会被 sigmoid 函数挤压。TruLens 中的 InternalInfluence 方法允许您通过切片和剪切对象选择任何输出图层。

from trulens.nn.attribution import InternalInfluence 
from trulens.nn.quantities import MaxClassQoI
from trulens.nn.distributions import LinearDoi
from trulens.nn.slices import InputCut, Cut, Slice# Get the layer name to explain from the model summary
model.summary() # you may be able to also see from print(model)
layer_to_explain = 'logits'# Define a custom influence measure
infl = InternalInfluence(model, 
    Slice(InputCut(), Cut(layer_to_explain)),
    MaxClassQoI(),
    LinearDoi())

另一个用例是将 F 定义为输出的类别比较。例如,查看车辆数据集,如果查询特定的类别,IG 可能会关注车轮,以了解为什么选择汽车作为主要分类。

图片来自深度卷积网络的影响导向解释【3】经许可转贴汽车的内部属性特征

如果我们改为改变 F 函数:F=(A 类输出)-(B 类输出)。这就问了为什么模型会认为分类应该是敞篷车还是轿车,反之亦然,那么 IG 的解释就会集中在车顶上。

图片来自深度卷积网络的影响导向解释【3】经许可转贴汽车与敞篷车的内部属性特征

通过定义一个自定义 QoI,并将其提供给 InternalInfluence 实例化,可以在 TruLens 中轻松更改这个查询函数。QoI 的 call 函数应返回用于获取梯度的标量值。

from trulens.nn.quantities import QoIclass MyCustomQoI(QoI):
    def __init__(...):
        ...
    def __call__(self, y):         
        ...from trulens.nn.attribution import InternalInfluence 
from trulens.nn.distributions import LinearDoi
from trulens.nn.slices import InputCut, OutputCut, Slice# Define a custom influence measure
infl = InternalInfluence(model, 
    Slice(InputCut(), OutputCut()),
    MyCustomQoI(),
    LinearDoi())

定制基线

这篇博客的最后一个主题,但可能是 IG 中最重要的考虑因素,是基线的选择。在图像领域,文献中使用的最普遍的基线是空图像。从语义上来说,这是一个非常直观的基线:最终的属性分数将是图像本身的属性差异减去一个假定的无信息基线。

不幸的是,有相当多的反例图像强调这可能是一个有问题的基线。一个例子与灵敏度公理有关,即如果像素与基线没有差异,那么该像素将获得零属性。事实上,一个空的图像并不是没有信息的,而是实际上包含了黑色。因此,如果对一幅黑色对分类非常重要的图像进行综合渐变,这些属性将会丢失。一个这样的例子可能是企鹅、熊猫或黑色汽车的图像。

由于该基线引起的不期望行为的另一个反例可能是水印的存在。让我们假设一个训练集,其中 99%的图像共享相同的水印。带有水印的每个记录将出现在所有分类中。因为水印保证不同于基线,并且梯度不隐含地满足灵敏度,所以水印将以随机化的属性结束,因为每个记录将使用它来解释不同的结果。然而,期望的行为将是对水印没有属性。在这种情况下,分布模式基线会更有意义。

这突出了在选择基线时理解数据集分布的需要。有一些研究强调,离类簇非常远的基线选择可能导致随机化的属性,并且您可能希望选择导致更强的属性本地化的基线[4]。在选择基线时,可能需要利用分布平均值或分布模式。一个建议是选择一个有内在意义的基线,这样分数减去基线也保留了意义。这样,属性将更容易被人理解。

这可能意味着找到一个得分为 0 的中性基线,其中的解释将总是解释模型得分。或者在边界属性的情况下[4],基线表示最接近的错误分类。这将创建一个解释,显示最有可能导致错误分类的区域,或者换句话说,突出显示最容易混淆的输入。这是梯度解释研究的一个开放而活跃的领域。

参考

[1] M. Sundararajan,A. Taly,Q. Yan,深度网络的公理化归属 (2017),
机器学习第 34 届国际会议论文集,机器学习研究论文集第 70 卷

[2] A .达塔,s .森和 y .齐克,通过量化输入影响的算法透明性 (2016),第 37 届 IEEE 安全和隐私研讨会会议录

[3] K. Leino,S. Sen,a .,m .和 L. Li,深度卷积网络的影响导向解释 (2018),IEEE 国际测试会议论文集

[4] Z. Wang,m .和 a .,稳健模型更容易解释,因为属性看起来是正常的 (2021),预印本。

对 BERT 模型代码的深入研究

原文:https://towardsdatascience.com/deep-dive-into-the-code-of-bert-model-9f618472353e?source=collection_archive---------5-----------------------

分解拥抱脸 Bert 实现

https://unsplash.com/@emilep

已经有很多教程介绍如何从头开始创建一个简化的 Bert 模型,以及它是如何工作的。在本文中,我们将做一些稍微不同的事情——我们将通过分解 BERT 的所有组件来实现拥抱脸。

介绍

在过去的几年中,变压器模型彻底改变了 NLP 领域。BERT(来自变压器的双向编码器表示)是最成功的变压器之一,它在各种任务上的表现优于以前的 SOTA 模型,如 LSTM,这得益于通过注意力机制和训练时间更好地理解上下文,因为与 LSTM 的递归结构不同,BERT 是并行化的。

现在不用再等了,让我们深入代码,看看它是如何工作的。首先,我们加载 Bert 模型并输出 BertModel 架构:

我们分别分析这三个部分:嵌入12 层重复 Bert 层编码器池器。最终我们将添加一个分类层。

从原始文本开始,首先要做的是将我们的句子分割成记号,然后我们可以将这些记号传递给bertembings。我们使用的bertokenizer是基于词块——子词标记化可训练算法,它有助于平衡词汇量和未登录词。看不见的单词被分割成子词,这些子词是在分词器的训练阶段得到的(更多细节在这里)。现在让我们从20 个新闻组数据集中导入几个句子,并对它们进行分词

from sklearn.datasets import fetch_20newsgroups
newsgroups_train = fetch_20newsgroups(subset='train')inputs_tests = tokenizer(newsgroups_train['data'][:3], truncation=True, padding=True, max_length=max_length, return_tensors='pt')

一旦句子被分割成记号,我们就给每个记号分配一个在 n 维空间中代表该记号的代表性数字向量。每个维度保存该单词的一些信息,因此如果我们假设特征是财富、性别、可爱,则在训练嵌入层之后,该模型将使用以下三维向量来表示例如单词 king:(0.98,1,0.01)和 cat with (0.02,0.5,1)。然后,我们可以使用这些向量来计算单词之间的相似度(使用余弦距离)并做许多其他事情。

注意:实际上我们不能推导出这些特性的名字到底是什么,但是这样想有助于更清楚地了解它们。

因此 word_embeddings 在这种情况下是一个形状矩阵(30522,768),其中第一维是词汇维度,而第二维是嵌入维度,即我们用来表示单词的特征的数量。对于 base-bert 来说是 768,对于更大的型号它会增加。一般来说,嵌入维度越高,我们就越能更好地表示某些单词——这在一定程度上是正确的,在某种程度上,增加维度不会增加模型的准确性,但计算复杂性会增加模型的准确性。

model.embeddings.word_embeddings.weight.shape
output: torch.Size([30522, 768])

位置嵌入是必需的,因为不同于例如 LSTM 模型,其顺序地处理记号,因此通过构造具有每个记号的顺序信息,Bert 模型并行地处理记号,并且为了结合每个记号的位置信息,我们需要从位置嵌入矩阵添加该信息。它的形状是(256,768 ),其中前者代表最大句子长度,而后者是单词嵌入的特征维度——因此,根据每个标记的位置,我们检索相关向量。在这种情况下,我们可以看到这个矩阵是学习来的,但也有其他实现方式,它是使用正弦和余弦来构建的。

model.embeddings.position_embeddings.weight.shapeoutput: torch.Size([256, 768])

token_type_embeddings 在这里是“多余的”,来自 Bert 训练任务,其中评估两个句子之间的语义相似性——需要这种嵌入来区分第一个和第二个句子。我们不需要它,因为我们只有一个用于分类任务的输入句子。

一旦我们提取了句子中每个单词的单词嵌入、位置嵌入和类型嵌入,我们只需将它们相加就可以得到完整的句子嵌入。所以第一句话应该是:

对于我们的 3 个句子的小批量,我们可以通过以下方式获得它们:

接下来我们有一个层名步骤,帮助模型更快地训练和更好地概括。我们通过标记的均值嵌入和标准差来标准化每个标记的嵌入,使其具有零均值和单位方差。然后,我们应用一个经过训练的权重和偏差向量,这样它可以被转换为具有不同的均值和方差,这样模型在训练期间可以自动适应。因为我们独立于其他示例计算不同示例的平均值和标准差,所以它不同于批标准化,在批标准化中,标准化是跨批维度的,因此依赖于批中的其他示例。

让我们最后应用 Dropout ,其中我们用零替换某些具有一定丢失概率的值。Dropout 有助于减少过度拟合,因为我们随机阻止来自某些神经元的信号,因此网络需要找到其他路径来减少损失函数,从而学习如何更好地概括,而不是依赖于某些路径。我们还可以将辍学视为一种模型集成技术,因为在每一步的训练过程中,我们随机停用某些神经元,最终形成“不同”的网络,我们最终在评估期间集成这些网络。

注意:因为我们将模型设置为评估模式,我们将忽略所有的脱落层,它们只在训练中使用。为了完整起见,我们仍然包括它。

norm_embs_dropout = model.embeddings.dropout(norm_embs)

我们可以检查是否获得了与模型相同的结果:

embs_model = model.embeddings(inputs_tests[‘input_ids’], inputs_tests[‘token_type_ids’])
torch.allclose(embs_model, norm_embs, atol=1e-06) # True

编码器

编码器是最神奇的地方。有 12 个泊位,前一个泊位的输出被输入下一个泊位。这是注意力被用来创建依赖于上下文的原始嵌入的不同表示的地方。在 BertLayer 中,我们首先尝试理解 BertAttention — 在导出每个单词的嵌入后,Bert 使用 3 个矩阵——键、查询和值,来计算注意力得分,并基于句子中的其他单词导出单词嵌入的新值;以这种方式,Bert 是上下文感知的,每个单词的嵌入不是固定的和上下文无关的,而是基于句子中的其他单词导出的,并且当导出特定单词的新嵌入时,其他单词的重要性由注意力分数表示。为了导出每个单词的查询和关键字向量,我们需要将其嵌入乘以一个训练过的矩阵(对于查询和关键字是分开的)。例如,要导出第一个句子的第一个单词的查询向量:

我们可以注意到,在整个查询和键矩阵中,我们只选择了前 64 列(= att_head_size )(稍后将阐明原因)——这是转换后单词的新嵌入维数,它小于原始嵌入维数 768。这样做是为了减少计算负担,但是实际上更长的嵌入可能会导致更好的性能。事实上,这是降低复杂性和提高性能之间的权衡。
现在我们可以导出整个句子的查询和关键矩阵:

为了计算关注分数,我们将查询矩阵乘以关键矩阵,并通过新嵌入维度的平方根(=64= att_head_size )对其进行标准化。我们还添加了一个修改过的注意力面具。初始注意屏蔽(输入['attention_mask'][0] )是 1 和 0 的张量,其中 1 表示在那个位置有一个标记,0 表示它是一个填充标记。
如果我们从 1 中减去注意力屏蔽,然后乘以一个很大的负数,当我们应用 SoftMax 时,我们有效地将那些负值归零,然后根据其他值导出概率。让我们看看下面的例子:

如果我们有一个 3 个标记+ 2 个填充的句子,我们为它获得以下注意力掩码:[0,0,0,-10000,-10000]
让我们应用 SoftMax 函数:

让我们检查一下我们得出的注意力分数是否与我们从模型中得到的分数相同。我们可以用下面的代码从模型中获得注意力分数:

as we defined output_attentions=True, output_hidden_states=True, return_dict=True we will get last_hidden_state, pooler_output, hidden_states for each layer and attentions for each layerout_view = model(**inputs_tests)

out_view 包含:

  • last _ hidden _ state(batch _ size,sequence_length,hidden_size):最后一个播放器输出的最后一个隐藏状态
  • Pooler _ output(batch _ size,hidden _ size)池层的输出
  • hidden _ States(batch _ size,sequence_length,hidden_size):每个 BertLayer 输出的模型的隐藏状态加上初始嵌入
  • 注意事项 (batch_size,num_heads,sequence_length,sequence_length):每个铺位一个。注意力最大值后的注意力权重
torch.allclose(attention_scores, out_view[-1][0][‘attn’][0, 0, :, :], atol=1e-06)) # Trueprint(attention_scores[0, :])
tensor([1.0590e-04, 2.1429e-03, .... , 4.8982e-05], grad_fn=<SliceBackward>)

注意力得分矩阵的第一行表示,为了为第一个标记创建新的嵌入,我们需要关注权重= 1.0590e-04 的第一个标记(关注其自身),权重= 2.1429e-03 的第二个标记,等等。换句话说,如果我们将这些分数乘以其他记号的向量嵌入,我们将得到第一个记号的新表示,但是,我们将使用下面计算的值矩阵,而不是实际使用嵌入。

值矩阵的推导方式与查询矩阵和键矩阵相同:

然后,我们将这些值乘以注意力分数,以获得新的上下文感知单词表示

new_embed_1 = (attention_scores @ V_first_head)

现在你可能想知道,为什么我们从张量中选择前 64 个(= att_head_size )元素。嗯,我们上面计算的是伯特注意力层的一头,但实际上有 12 头。这些注意力头部中的每一个都创建单词的不同表示( new_embed_1 matrix),其中例如给定下面的句子“我喜欢在意大利餐馆吃比萨饼”,在第一个头部中,单词“比萨饼”可能主要注意前一个单词,单词本身和后面的单词以及剩余的单词将几乎没有注意力。在下一个标题中,它可能会关注所有动词(如和吃),并以这种方式从第一个标题中捕捉不同的关系。

现在,我们可以用矩阵形式将它们一起导出,而不是分别导出每个头部:

来自第一个例子和第一个头的注意力与我们之前导出的相同:

example = 0
head = 0
torch.allclose(attention_scores, attention_probs[example][head]) # True

我们现在连接来自 12 个头部的结果,并通过我们在嵌入部分已经看到的一系列线性层、归一化层和漏失层来获得第一层编码器的结果。

我们只是简单地通过一个线性层传递我们串联的注意力结果。然后我们需要归一化,但是我们可以看到,我们没有立即归一化 output_dense ,而是首先将其与我们的初始嵌入相加——这被称为剩余连接。当我们增加神经网络的深度时,即,堆叠越来越多的层时,我们会遇到消失/爆炸梯度的问题,当在消失梯度的情况下,由于传播的梯度接近于零并且初始层停止改变权重并改善,所以模型不再能够学习。当权重由于最终爆炸的极端更新而不能稳定时,与爆炸梯度相反的问题。现在,适当的权重初始化和归一化有助于解决这个问题,但是已经观察到的是,即使网络变得更加稳定,性能也会随着优化变得更加困难而下降。添加这些剩余连接有助于提高性能,即使我们不断增加深度,网络也变得更容易优化。剩余连接也用于 out_layernorm ,它实际上是第一个 BertLayer 的输出。最后要注意的是,当我们计算 interm_dense,AttentionLayer 的输出通过一个线性层后,一个非线性 GeLU 激活函数被应用。葛禄表示为:

https://arxiv.org/pdf/1606.08415v3.pdf

但为了加快计算速度,可以用下面的公式来近似计算:

https://arxiv.org/pdf/1606.08415v3.pdf

从图中我们可以看出,如果由公式 max(input,0)】给出的 ReLU,在正域中是单调的、凸的和线性的, GeLU 在正域中是非单调的、非凸的和非线性的,因此可以近似更容易复杂的函数。

https://arxiv.org/pdf/1606.08415v3.pdf

我们现在已经成功地复制了一个完整的贝特勒。该层的输出(与初始嵌入的形状相同)进入下一个以此类推。总共有 12 个泊位。因此,将所有这些放在一起,我们可以从编码器获得所有 3 个示例的最终结果:

注意 out_layernorm 每一层的输出如何输入到下一层。

我们可以看到这与 out_view 中的结果相同

torch.allclose(out_view[-2][-1], out_layernorm, atol=1e-05) # True

普尔勒

现在我们可以将最后一个(即【CLS】、第一个令牌输出通过一个线性层,并应用 Tanh 激活函数来获得池化输出。使用第一个令牌进行分类的原因来自于作为 Bert state 的作者如何训练模型:

每个序列的第一个标记总是一个特殊的分类标记([CLS])。对应于该令牌的最终隐藏状态被用作分类任务的聚集序列表示。

out_pooler = torch.nn.functional.tanh(out_layernorm[:, 0] @ model.pooler.dense.weight.T + model.pooler.dense.bias)

分类者

最后,我们创建一个简单的类,这将是一个简单的线性层,但你可以添加一个 dropout 到它和其他东西。这里我们假设一个二进制分类问题( output_dim=2 ),但是可以是任意维度。

from torch import nn
class Classifier(nn.Module):

    def __init__(self, output_dim=2):
        super(Classifier, self).__init__()
        self.classifier = nn.Linear(model.config.hidden_size, output_dim, bias=True)

    def forward(self, x):
        return self.classifier(x)classif = Classifier()
classif(out_pooler)tensor([[-0.2918, -0.5782],
        [ 0.2494, -0.1955],
        [ 0.1814,  0.3971]], grad_fn=<AddmmBackward>)

结论

现在你应该理解了 Bert 的每一个构件,因此下一步就是实际应用了!在下一篇文章中,我们将展示 Bert 的行动,以及如何使用 TensorBoard 监控训练,如果训练过程中出现问题,tensor board 有助于及早发现。

参考

https://arxiv.org/pdf/1606.08415v3.pdf
https://arxiv.org/pdf/1810.04805.pdf
https://jalammar.github.io/illustrated-transformer/
https://github.com/huggingface/transformers/

面向数据科学家的 Python 深度挖掘统计分布

原文:https://towardsdatascience.com/deep-diving-statistical-distributions-with-python-for-data-scientists-a0a4badc8d1a?source=collection_archive---------22-----------------------

对于任何数据科学家来说,了解统计数据、数据分布以及如何在现实世界中使用它们是非常重要的。除了理论知识之外,能够在建模、数据分析和推动洞察力方面使用它们也很有帮助。

在深入统计分布之前,这里有一个用 Python 生成随机数的快速回顾。

米克·豪普特在 Unsplash 上的照片

我们可以在 python 中使用 numpy 和 random 来做同样的生成随机数的工作。

我们也可以从特定的分布中抽取随机数,如正态分布、均匀分布等。我将在每个特定的发行版下详细讨论这些细节。我们将使用 Python 中的 SciPy 库来生成统计分布。

均匀分布

在这种分布中,特定范围内的值同样可能出现。给定范围之外的值永远不会出现。让我们从一个均匀分布中产生 100,000 个数字,并把它们画出来。用于从分布中生成随机数的函数称为 rvs。为了定义边界,我们使用 loc 和 scale。

我们得到了这个图表。我们可以看到,在 0 到 10 之间,每个数字出现的概率都是相等的,但在 0 到 10 之外,每个数字出现的概率都是 0。

均匀分布

我们可以从这种分布中得出进一步的见解。如果我们想知道从这个分布中得到的观测值低于某个特定值的概率,我们可以用 cdf 来计算。它给出了密度曲线下的面积,直到 x 轴上的某个值。假设我们在 5 处画截止点,并想知道曲线下 x=5 处的面积,即

在均匀分布上使用 cdf

stats.uniform.cdf(x=5.0, #cutoff
                 loc=0,
                 scale=10)

这将给出 0.5 的输出,这意味着在这个特定的均匀分布中,如果我们挑选一个观察值,它有 50%的机会在 0 和 5 之间。

cdf 的倒数是 ppf。给定概率,ppf 给出 x 轴上的截止值。例如,要获得临界值,我们有 30%的机会在该值以下绘制观察值

stats.uniform.ppf(q=0.3, *#probability cutoff*
                 loc=0, *#distribution start*
                 scale=10) *#distribution end*

这将导致值 3。因此,在 x 轴值为 3 时,我们可以对分布进行切片,使其 30%位于图表的左侧。

为了得到给定值 x 的实际概率密度,我们使用 pdf。这将基本上给出 x 值处的分布高度值。由于均匀分布是平坦的,在上面的例子中,0 到 10 之间的所有 x 值将具有相同的概率密度。并且该范围之外的所有点将具有概率密度= 0。

现在,要从任何均匀分布中获得随机数,我们可以使用:

np.random.uniform()

要从上面使用的均匀分布中获得随机数,请使用:

np.random.uniform(0 *#low limit*
                  ,10 *#upper limit*
                  ,(3,4)) *#size*

这将产生如下数组:

正态/高斯分布

同上,我们可以使用 SciPy、norm 和 rvs 来生成这个分布

from scipy.stats import norm
stats.norm.rvs()

它看起来是这样的:

正态分布

我们可以使用 cdf 来获得 x 轴上临界值以下的曲线下面积。例如:

print(stats.norm.cdf(x=0.4))

类似地,我们可以使用 ppf 得到 x 轴上某个概率的截止值(从曲线下的面积百分比)。例如:

*#Find the quantile for the 97.5% cutoff*
print(stats.norm.ppf(q=0.975))

从某种正态分布中生成随机数可以有多种方式。

如果我们想从特定平均值和标准偏差的正态分布中生成随机数:

np.random.normal(1 *#mean*
                 ,2 *#standard deviation*
                 ,(3,2)) *#size*

如果我们想从 0 到 1 之间的正态分布中生成随机数

np.random.rand(3,2)

如果我们想从标准的正态分布中产生随机数

np.random.randn(3,2)

二项分布

这是一个离散的概率分布。在实验中只有两种可能的结果。我们可以用二项分布来计算成功的概率。它告诉你在 n 次试验中成功的可能性有多大。所以 x 轴是试验中成功的次数,y 轴是试验的次数。我们需要两个参数来定义二项式分布——试验成功的概率和试验次数。一项试验可能有多个事件。例如,抛 10 次硬币= 1 次尝试。

**from** **scipy.stats** **import** binom

coin=stats.binom.rvs(size=10000 *# number of trials*
          ,n=10 *#number of flips in a trial*
          ,p=0.5 *#probability of success (say getting heads)*
         )print(pd.crosstab(index="counts",columns=coin))

这表明,在所有的 10000 次试验中,只有 10 次我们抛硬币,没有头。这是有道理的,因为这是一个公平的硬币,有相同的概率获得正面或反面。我们可以看到 2442 次,我们有 5 个头。10000 次翻转中只有 10 次是正面朝上的。

pd.DataFrame(coin).hist()

公平掷硬币

如果我们现在掷一枚不公平的硬币,有 80%的机会正面朝上,那么图表应该向右倾斜,因为我们会有更多正面朝上的结果。

**from** **scipy.stats** **import** binom

coin=stats.binom.rvs(size=10000 *# number of trials*
          ,n=10 *#number of flips in a trial*
          ,p=0.8 *#probability of success*
         )

print(pd.crosstab(index="counts",columns=coin))

有趣的是,由于这枚硬币偏向于正面,在 10000 次试验中,没有一次我们只得到 1 个正面。在一次试验中,我们至少得到了两个头,而这也只发生了一次。我们可以清楚地看到在这个案子的审判中有更多人头的偏见。

pd.DataFrame(coin).hist()

有偏向的硬币投掷

与其他分布相同,cdf 给出了在一定范围内成功的概率。例如,如果我们想知道在有偏向的硬币情况下,掷 5 次或更少次正面朝上的概率是多少:

stats.binom.cdf(k=5, *#probability of 5 success or less*
               n=10, *#with 10 flips*
               p=0.8) *#success probability 0.8*

超过 5 次成功的概率为:

1-stats.binom.cdf(k=5, *#probability of 5 success or less*
               n=10, *#with 10 flips*
               p=0.8) *#success probability 0.8*

在像这样的离散分布中,我们用 pmf 代替 pdf。pmf 代表概率质量函数。它是在给定的成功次数 k 下观察值的比例。

stats.binom.pmf(k=5, *#probability of 5 success* 
               n=10, *#with 10 flips*
               p=0.5) *#success probability 0.5*

我们可以通过给定参数 n(试验次数)和 p(成功概率)从特定的二项分布中生成随机数。例如:

np.random.binomial(n=52, p=0.7, size=(2,3))

几何分布

这也是一个离散分布。它模拟了事件发生所需的时间。例如,如果成功=正面,那么在抛一枚公平硬币时,需要尝试多少次才能获得成功?

heads = stats.geom.rvs(size = 10000, *#We generate 10000 trails of flips*
                      p=0.5) *#fair coin*

print(pd.crosstab(index="counts", columns = heads))

在交叉表中我们可以看到,一半的情况下,只需要翻转 1 次就可以得到一个头。这是有道理的,因为我们在掷一枚公平的硬币。所以这个图也是右偏的。

pd.DataFrame(heads).hist()

几何分布

我们可以使用 cdf 来获得更多的洞察力。例如,前 3 次翻转成功的概率是多少?

three_flip = stats.geom.cdf(k=3,
                           p=0.5)
print(three_flip)

我们在两次翻转中成功的概率是多少?这可以使用 pmf 来解决。

stats.geom.pmf(k=2,
              p=0.5)

指数分布

这是几何分布的连续版本。在给定发生率的情况下,它模拟特定事件发生所需的时间。

例如,如果发生率是每小时一次,那么等待一个多小时的事件发生的概率是多少?

prob = stats.expon.cdf(x=1,
                      scale=1) *#arrival rate*
1-prob

泊松分布

它模拟给定时间间隔内成功/事件发生的概率。例如,如果一个等候室的到达率为每小时一次,那么一个小时内有多少人到达?

arr = stats.poisson.rvs(size=10000,
                       mu=1) *#average arrival time 1*

print(pd.crosstab(index='counts', columns = arr))

有趣的是,当到达率为每小时一次时,我们经常在一小时内看到 0 次到达。我们有时也会看到更多的到达者。现在可能是最忙的时候。

pd.DataFrame(arr).hist()

因此,在这种情况下,我们会希望在这些繁忙的时间里,在等候室里有更多的椅子。在这种情况下,每小时一次的到达率可能是欺骗性的,我们可能会遇到资源短缺。

通过统计分布,我们可以更深入地了解我们正在进行这种建模的数据和业务。

基于面部表情的深度情感识别

原文:https://towardsdatascience.com/deep-emotion-recognition-based-on-facial-expressions-ed02fd7f8627?source=collection_archive---------20-----------------------

第 1 部分:关于如何针对情感识别微调面部表情效率网络的教程🎯

在机器人学硕士学位论文的启发下,我决定写一篇三部曲的文章。这一努力背后的愿望是分享我通过这次神奇的旅程获得的发现和知识。这三篇文章将主要采取循序渐进的编码教程的形式,同时在理论层面上解释已经做出的许多技术选择。

腾雅特Unsplash 上的照片

在我们开始实现之前,让我们稍微讨论一下面部表情识别 (FER)领域:

FER 是一个科学研究领域,研究试图从面部表情识别/推断情绪状态的技术和方法。在人类交流中,面部表情在推断情绪方面起着至关重要的作用,这可能有助于理解他人的意图。根据不同的调查[1,2],言语成分只传达了人际交往的三分之一非言语成分传达了三分之二。大多数与态度和感觉有关的信息存在于面部表情中。因此,面部表情被证明在整个信息交流过程中起着至关重要的作用。表情和情绪密不可分。埃克曼和弗里森在[3]引发了第一波基础情绪理论启发了对情绪表达的研究。他们使用了典型情绪面部表情的静态照片,并记录了有限的一组“基本”情绪(快乐)的识别和产生的某种程度的普遍性😀,惊喜😮,恐惧😨,厌恶🤮,悲伤😭愤怒😡)。

这些 6 个类别也将用于我们的任务,并且 CK+48 [4]是选择的数据集,将帮助我们训练和评估我们的模型。整个实现发生在使用 GPU 加速的 Google Colab 上。所以,事不宜迟,让我们开始我们的任务吧…

数据预处理✂️

a)首先,让我们导入必要的库,如下所示。

将数据集存储到 Google Drive 后,您必须挂载驱动器并转到包含数据集的目录。

下一步是将我们的数据加载到内存中,这就是为什么我创建了两个辅助函数来简化事情。下面您可以看到描述其功能的文档字符串(为了避免文章中出现大量代码)。当然,你可以在我的 GitHub 账号上找到完整的代码。

这是我们的数据分布图。

作者图片

注: 理想情况下,我们应该有 等分布的类 供我们训练,因为与“恐惧”的例子相比,模型更频繁地遇到“惊讶”的例子。最后,这将损害模型的性能,因为我们将在后面看到,大多数错误分类将与“悲伤”和“恐惧”这两个类别有关。

b)我使用的数据集包括 927 幅形状为 48×48×3 的图像。之后,我们将数据集随机分为训练集( 70% )、验证集( 15% )和测试集( 15% )(一般来说,这被认为是拆分数据的一个很好的经验法则)。

分割的指示打印如下所示。

X_train has shape: (**648**, 48, 48, 3) y_train has shape: (**648**, 6)  X_valid has shape: (**139**, 48, 48, 3) y_valid has shape: (**139**, 6)  X_test has shape: (**140**, 48, 48, 3) y_test has shape: (**140**, 6)X_train + X_valid + X_test = **927** samples in total

注: 我们的验证和测试集从同一个分布中抽取是非常重要的。在这段 视频 中,吴恩达博士以一种引人注目(且易于消化)的方式解释了原因。问题是,我们的数据来自相同的分布(因为它是在实验室约束下创建的),但一些类别之间的样本数量很大程度上不相等,再加上数据量相对较小,可能会损害模型的效率。理想情况下,我们应该以某种方式“控制”X_valid 和 X_test 的 ~140 个样本 ,方法是从每个类别 中抽取 ~23 个不同的示例。

c)此外,数据扩充将只用于训练样本,以便让模型遇到各种不同的例子,因为我们没有太多的例子可供我们使用,因此这将有助于它增强其预测性能。

注意: 并不是 ImageDataGenerator 类的所有参数都相关。对此我们必须小心。例如,垂直翻转对我们的任务没有意义,可能会损害模型的精度。

应用于训练样本的一些增强示例如下所示。

作者图片

模型创建和微调🚀

我创建了函数 build_model,它加载了在 ImageNet 上预训练的 EfficientNetB0 模型(没有它的原始分类器),并在它的顶部添加了 3 层,如下图所示。只选择 3 层(而不是更复杂的东西)的想法来自于官方文档 [Keras](http://Image classification via fine-tuning with EfficientNet) 展示了如何在图像分类上微调 EfficientNet。此外,该函数使用 Adam 优化器、分类交叉熵损失函数和作为度量的准确性来编译模型。

在我的 GitHub repo 中,我上传了模型的概要以及模型的图形,这样就可以看一下

至于培训阶段,我使用了 3 个非常有用的回访:

  • ModelCheckPoint: 保存达到最佳验证精度的模型的权重。
  • 提前停止:如果连续 15 个时期验证精度没有提高,训练将被中断(该回调防止过度拟合)
  • reducelronplateaueu:这是一个调度程序,每当验证精度处于稳定状态时,它会将学习率降低一半。

上述回调的组合确保了我们的模型不会过度拟合。当然,我们也可以通过我们的学习曲线观察到这一点,我们稍后会进行检查。

注: 至于批量,我试验了一个取值范围。对于批量大小为 16 和 32 的样本,训练时间增加了(这确实很重要,尤其是当数据集相当大时),而验证准确性甚至没有比 64 个样本的批量更高。另一方面,一批 128 个样本当然加速了训练过程,然而,不仅验证不是更好,而且还观察到学习曲线的显著振荡(这可能妨碍模型的收敛)。

注意: 两个 我在建立这个模型的过程中意识到的非常重要的事情是:(1)D尽管在大多数情况下像素归一化被应用于输入图像,EfficientNet 仍然通过 它的重新缩放层 来实现这一点,因此,使用会损害模型的性能。【2】D尽管模型将形状(224,224,3)的张量作为输入,但我意识到,当我修改输入层以接收形状(48,48,3)的张量而不是将数据集重新缩放到 224x224 时,可以获得更好的性能。我设法找到的唯一相关资料来源是阿德里安·罗斯布鲁克关于 pyimagesearch.com 的一篇文章。

学习曲线📈 📉

最后,模型只需要 46 个时期就能收敛,训练过程从我们的回调中中断。相应的学习曲线如下所示。

该模型似乎很好地符合新数据,具有相当小的泛化差距。训练和验证准确度都接近 98-99%的准确度。但是,将自动加载模型最佳版本的权重。

最终评估🔮

最后,我们将在没有见过的样本上测试我们的模型。这个集合是从我们的初始数据集中抽取的测试集合。模型达到了96.43%的准确率并且通过混淆矩阵来描述预测,以便我们可以彻底检查模型的错误分类。

作者图片

从这个矩阵中你可以观察到,类“悲伤”本质上导致了这个问题。这是绝对合理的,虽然,由于数量很少的例子。此外,不要忘记,即使对一个人来说,表达悲伤、恐惧、厌恶或愤怒的面部表情也可能令人困惑,如果你检查以上面部表情的增强样本,并尝试自己预测每种表情的类别,这一点就会变得明显。你会意识到,即使对人类来说,这项任务也存在固有的困难。

您还可以看到模型的一些随机预测,右侧的条形图显示了每个预测的置信度。

作者图片

结论🏆

在本文中,我们看到了如何构建面部表情分类器来预测情绪。对于这个数据集( CK+48 ),达到 96.43% 的准确性接近于最先进的性能,在这个三部曲的下一篇文章中,我们将应用可视化技术(GradCam),通过将热图应用到原始图像上,揭示图像中对模型起关键作用的区域,以便进行推断。这些技术对于深度学习方法非常重要,因为它们有助于模型的可解释性和可解释性。因此,在我们的下一次会议上,我们将看到我们如何解释我们的模型的不准确性,以及我们如何可能改善它。

非常感谢您的宝贵时间!(完整的项目可以在这里找到)。

参考

【1】阿尔伯特·梅拉比安。没有文字的交流。沟通理论,第 193-200 页,2008 年。

凯瑟琳·考拉德,道格拉斯·坎宁安,海因里希·H·布尔霍夫和克里斯蒂安·沃尔雷文。mpi 面部表情数据库——一个经验证的情感和会话面部表情数据库。PloS one,7(3),2012。

保罗·艾克曼,理查德·索伦森和华莱士·弗里森。面部表情中的泛文化因素。科学,164(3875):86–88,1969。

Patrick Lucey,Jeffrey F Cohn,Takeo Kanade,Jason Saragih,Zara Ambadar 和 Iain Matthews。扩展的 cohn-kanade 数据集(ck+):一个完整的动作单元和情感表达数据集。2010 年 ieee 计算机学会计算机视觉和模式识别会议-研讨会,第 94-101 页。IEEE,2010 年。

(深)屋:制作 AI 生成的屋内音乐

原文:https://towardsdatascience.com/deep-house-making-ai-generated-house-music-e1447b06b53d?source=collection_archive---------10-----------------------

实践教程

有没有想过我们不在的时候电脑在玩什么?

附身摄影Unsplash 上拍照

很长一段时间以来,人们一直试图制作机器生成的音乐。一些最早的例子是音乐家在钢琴角色上打孔,创造出人类无法演奏的复杂旋律。

最近,它看起来像是 MIDI 文件形式的电子音乐,通过指定各种属性(乐器、音高、持续时间和定时),歌曲可以被象征性地表示出来。但是 AI 运行整个生成过程是什么样子的呢?

AI 生成的“人类音乐”(下文更多)。有趣的是,这收到的两个 SoundCloud 评论来自机器人。似乎对人工智能生成的音乐的最高赞美来自人工智能生成的垃圾邮件

其中一首更好的歌曲被输入到一个 StyleGAN 来创建一个新的音乐视频

这篇文章探索了生成音频技术,用几个小时的家庭音乐来训练 OpenAI 的点唱机

生成音频方法

历史上,生成音频模型是在这些符号音乐表示的数据集上训练的。这些早期(2017 年)的模型,如 DeepBachmidet产生了模仿人类旋律的“乐谱”,效果令人印象深刻。

迪普巴赫 (Hadjeres 2017)

但是训练和生成原始音频要困难得多。典型的音频文件以 44.1kHz 运行,这意味着每秒包含 44,100 个不同的值。这比仅仅从包含“在斯坦威钢琴上从 00:01 到 00:02 弹奏中音 C”的文件中学习的符号模型要复杂得多。

最近,OpenAI 的 Jukebox 和 DeepMind 的 WaveNet 解决了在音频文件中学习长期依赖性的难题。生成原始音频的方法主要有三类,各有利弊。

音乐音频合成的深度生成模型(图片由作者提供,基于 Huzaifah 2020 )

生成对抗网络

gan 学习将输入向量(通常比数据的维数小得多)映射到目标域中的数据实例。它们实际上是两个相互训练的神经网络的组合。鉴别器(D)试图判断生成的输出是否真实。发生器(G)试图产生这个合成输出来欺骗鉴别器。

甘建筑(图片作者提供)

随着模型的训练,生成器能够产生与真实例子相媲美的输出。

甘斯创造的合成脸。(图片由ThisPersonDoesNotExist.com提供)

从理论上讲,GANs 是发电速度最快的架构(以上三种架构中),并且对调节变量有更好的全局控制。然而,GANs 在制作高分辨率图像方面取得的巨大成功还没有转化到音频领域。实际上,它们主要用于从乐器和短片 ( < 4s)中产生单个音符的音色,而不是产生新的乐谱。

自回归模型

自回归模型将先前的术语(想想:过去几秒钟的音乐)压缩成隐藏状态,用于预测下一位音频。虽然 RNN 在每个时间步长只看到一个输入样本,并在其状态中保留过去样本的影响,但 WaveNet 可以显式访问输入样本的过去窗口。

WaveNet 的自回归架构。(图片由作者提供)

这种类型的模型最擅长短音频生成。生成的样本通常缺乏长期结构,因此它们通常用于语音生成。然而,自回归模型非常慢。生成新元素需要所有先前的元素都存在。标准化流动模型(并行波网)增加了这些模型的并行性,使生成速度提高了 300 倍。

变分自动编码器

传统的自动编码器将输入数据映射到“潜在空间”中,以学习数据集的压缩的底层表示。

自动编码器架构。(图片由作者提供)

这些潜在变量可用于从低维向量生成新的数据合成样本:将潜在向量输入解码器,合成样本被创建。然而,因为解码器从学习向量中重建数据,它们不能生成新的输出。

为了解决这个问题,变分自动编码器(VAEs) 改为学习潜在空间的基本分布的参数,允许在生成时随机采样以创建新的合成样本。

自动编码器与可变自动编码器(图片由作者提供)

在内部,变分自动编码器将输入存储为潜在空间的分布,而不是单点。VAE 学习潜在空间中概率分布的参数,从该潜在空间中可以抽取样本。

可变自动编码器(VAE)架构。(图片由作者提供)

gan 通常会产生更好的结果,因为它们不处理任何显式的概率密度估计。当模型不了解真实的后验分布时,vae 无法生成清晰的输出。

VAEs 生成模糊的合成样本。(图片由向数据科学提供)

vae 最擅长构建数据空间,用于发现数据的低维参数表示。然而,因为它们学习参数的分布而不是实际值,所以生成的样本可能不精确。他们的输出可能在概率上是正确的,但实际上并不正确。

分解自动点唱机

OpenAI 的点唱机结合使用了这些技术。为了处理较长的音频文件,它将输入下采样到一个较低分辨率的空间。在这个压缩空间中(比输入小 128 倍),生成新颖的音频样本要容易得多。新音频生成后,将被升采样回更高保真的音频电平。

压缩音频文件

训练一个模型来生成音频序列需要开发另一个模型来将训练数据(音频文件)从其原始的 44.1kHz 分辨率向下转换到低维空间,然后再转换回来。在这个低维空间中,我们训练生成模型要容易得多(计算成本也低得多)。为了实现这一点,Jukebox 使用分层 VQ 值。把 VQ-VAE 想象成一个翻译器,从原始音频编码到这个低维空间,再解码回来。

点唱机用分级 VQ 压缩音频。音频被“编码”到低维空间中,以便训练生成模型。(图片由作者提供,基于 OpenAI )

矢量量化变分自动编码器( VQ-VAE )建立在 VAEs 之上,允许生成更真实的样本。如上所述,vae 通常生成“模糊”的合成数据,因为它们来自分布。VQ-维斯通过量化(想想:变成离散向量)潜在变量来解决这个问题。

VQ-VAE 输出看起来很真实。(图片由ML @伯克利)

生成的样本由模拟训练集中的音频部分的音频比特组成,而不是由概率上应该存在于训练集中的音频比特组成。结果通常更加真实。对于 VQ-VAEs 如何不同于 VAEs 的视觉直觉,见下面他们的潜在空间的比较。

维斯(左)和 VQ-维斯(右)的潜在空间。(图片由 MLearning.ai 提供)

一个单一的 VQ-VAE 可以有效地抓住当地的结构,但长期的一致性很难。生成的音频在小时间范围内可能听起来合理,但在较长时间范围内听起来就不那么好了。想象一下,一首歌的桥段一直延续,而不是过渡到下一段。在当地,这听起来很有条理,但在全球范围内,这毫无意义。为了更好地学习这些长期的音乐结构,Jukebox 结合了不同时间尺度的多个 VQ 值:亚秒、秒和十秒。这些分级 VQ 值有助于捕捉波形中的长程相关性。

训练一个深宅的 Prior

在我们可以训练我们的生成模型之前,我们需要训练 VQ-VAE 来处理我们的输入音频。因为它是一个自动编码器,我们希望输出听起来尽可能接近输入,所以任何重建损失都是不利的。此外,我们最小化了码本损失,即原始音频样本与其“矢量量化”表示之间的差异。“损失”是我们在重建音频中听到的随机噪声,原始样本中不存在。

高质量输入音频(来自训练数据集)

较低质量的重建音频(通过 VQ-VAE 后)

既然我们可以在这个离散化的空间中工作,我们就可以训练我们的先验来预测音频序列。给定一些过去的输入和辅助数据,可以训练一个[变压器模型](http://Given a number of past inputs and auxiliary data, a transformer)来预测接下来会出现什么声音。变形金刚使用注意力机制来提高学习翻译和预测序列的训练速度。因为它们比 RNNs 提供了更长序列的计算优势,变压器是原始音频的理想架构。Jukebox 使用稀疏变压器将每层的计算复杂度从 O(n)降低到 O(n n)。

变压器架构。(图片由 Vaswani 2017 提供)

为了生成音频,我们训练转换器在给定数据集中歌曲的先前编码声音的情况下预测下一个编码声音。在训练期间,我们根据关于输入音频的辅助信息来调节模型,以使我们能够拥有控制生成的参数。在实践中,这看起来像是在训练音频中传递关于流派、艺术家和歌词的信息,以便在生成时我们可以传递我们希望它输出的艺术家或流派。

调节信息被传递到我们的变压器模型中。(图片由 Dhariwal 2020 提供)

最高级别的 prior 接受大约 50 小时的深度室内音乐培训,并去除声道(c/osp leapter)。prior 在 NVIDIA 的 Tesla V100 GPU 上训练了 4 天,重量衰减为 0.01。当训练损失在 2 左右时(大约 90k 步),学习率(LR)被退火到 0。学习率退火意味着当你接近训练结束时,随着时间的推移降低你的 LR,以确保你不会失去最小值的位置。

这种输出主要是鼓和低音

这一首听起来像是低音线上的杂乱声音

这一个特别不和谐,大约在 10 秒钟左右分崩离析

虽然 90k 步可能看起来很长,但随着时间的推移,生成轨迹的质量会显著提高。作为参考,将这些早期轨迹(在 33k 和 53k 步生成)与最终部分的最终轨迹(在 90k 步之后)进行比较。

生成新的房屋轨迹

为了生成新的室内音乐,我们首先从训练过的先验样本中采样,然后将音轨上采样回其原始采样率。最后,生成的样本通过 VQ-VAE 解码器并变回波形。

自动点唱机先生成最高级别的音频,然后进行上采样。(图片由 Dhariwal 2020 提供)

以关于艺术家和流派的信息为条件的顶级先验(级别 2)被采样,以生成训练数据风格的音乐符号的新序列。虽然我们可以' prime 该模型继续从一个输入的音频文件,下面的样本都是未经 prime 和完全采样从学习的顶级先验。级别 2 生成的音频样本包含音乐的长程结构和语义,但是由于压缩而具有低音频质量。

来自顶级 prior 的音频听起来粗糙且质量差

为了从生成的音频中去除“颗粒”,我们将其向上采样到越来越低的层。这些上采样器模型类似于我们的顶级先验变换器,但首先用更高级别的生成令牌进行调节。将这个级别 2 样本传递给级别 1 上采样器(然后将该样本传递给级别 0 上采样器)。

上采样以较高级别的生成音频标记为条件。(图片由 Dhariwal 2020 提供)

这些上采样器增加了音色等本地音乐结构,极大地改善了音质。

级别 1 是级别 2 的显著改进

而 0 级更好

(深)房子

那么计算机生成的室内音乐听起来是什么样的呢?下面是一些最好的样本,但更多的你可以查看 SoundCloud 上输出的 整个播放列表

有点像帮派成员

渐进低音线在 00:12 左右出现

沉重的鼓声,直到 00:11 左右传来钢锅声

大约 00:33 分,进入一首新歌

正如一位朋友所说,“这就像一台计算机试图学习如何冒充 Kygo 给它的计算机朋友”

限制

长期结构:虽然原始论文将此列为一个限制,但对于我们没有人声的室内音乐来说,这不是什么问题,因为没有人声来清晰地描绘出诗句和合唱(室内音乐是重复的)。

生成速度:虽然这些磁道是并行生成的,但因为 Jukebox 是建立在自动回归模型上的,所以单个磁道的生成不是并行的。这些 90 秒的样本花了大约 10 个小时生成。

过度拟合:另一个问题是来自生成样本的知识产权侵权。在一些轨道中,如果音频完全淡出,轨道会在几秒钟后随着此介绍重新开始。

在几秒钟的静默之后,过度拟合的音频出现在 00:05

这可能是因为在训练数据集中制作了许多歌曲的 DJ 以这种方式打开了他所有的歌曲,并且模型学会了复制该介绍。

我对所有自动生成的歌曲运行 SoundHound,但没有匹配,但不清楚这是因为 Jukebox 过度拟合了没有匹配的去除人声的歌曲,还是因为它们是真正新颖的样本,只是受到了训练数据集的严重启发。因为 SoundHound 的“哼一首曲子”功能,我的直觉是后者,然而进一步的研究应该调查 IP 和 AI 生成的内容。

深度图像质量评估

原文:https://towardsdatascience.com/deep-image-quality-assessment-30ad71641fac?source=collection_archive---------2-----------------------

实践教程

深入研究全参考图像质量评估。从主观图像质量实验到深入的客观图像质量度量。

作者图片

在深入研究图像质量评估之前,我对成像管道中的处理步骤知之甚少。我后来发现,相机管道(捕捉光子并将其转换为数字世界的字节的过程)是硬件和软件的协同作用,在每个阶段都经过精心优化,显示模型也是如此——从数字字节到人眼感知的光的物理量的反向转换过程。

为了实现高水平的细节、增强和真实感、图像的深度感,图像处理算法经历了仔细的微调。前一段时间,这些算法是手工配置的。随着时间的推移,自动图像质量评估方法得到了发展,大大简化了算法设计人员的工作。

开发能够捕捉图像感知质量的度量标准的挑战仍然存在。以下面的两张老虎图片为例——图像质量评估最流行的指标之一峰值信噪比(PSNR)未能给图像分配更高的分数,人类观察者会判断该图像具有更好的质量。

在这个例子中,峰值信噪比(PSNR)提供了相反的直观结果,与图像的感知质量相矛盾。在右图中,度量分数较低,但是从视觉上看更好。来自 BSD 图像数据集的已处理图像。

在我跳到客观的图像质量指标之前,我们首先需要回顾一下制定指标的基本步骤:

我们从标准开始——我们希望度量模型化的东西。然后,我们选择一组图像,稍后我们将在这些图像上训练模型。有了这些图像,我们以人类观察者判断的形式收集数据,询问每张图像符合所选标准的程度。收集完数据后,我们就可以开始建模了。

本文是关于全参考深度图像质量指标的图像损伤评估。因此,我将只简要地谈一下管道的前两步。这些是理解最先进的图像质量评估模型背后的选择的先决条件。我还将简要讨论基于非深度学习的图像质量指标,因为这些指标经常被用作深度模型的构建部分。

这篇文章部分基于我在 PyData Cambridge演讲和在 ARM 有限公司的一次受邀演讲。如果你想了解这篇文章主题的更多信息,请不要犹豫给我发消息——我肯定能够提供进一步的指导。

标准

通常区分三种类型的图像质量评估。图像美学评估、图像损伤评估和赝像可见性评估。例如,考虑下面的三种情况。

三个图像质量标准。图片作者。

审美评估的第一个案例中,我觉得顶部的图像比底部的图像好看。我会说,它有很好的和有趣的,有点破旧的纹理。因此,美学是公认的摄影规则——光线、对比和构图的恰当运用。在第二种情况下,我们感兴趣的是评估测试图像中相对于参考图像的可见损伤水平(质量)。这个问题当然不那么模糊,因为它不直接依赖于个人偏好。最后,在最后一种情况下,我们将有兴趣看到图像中观察者会看到伪像的区域(可见性 )—这些区域通常不是微不足道的,因为一些损伤可能会被掩盖。虽然第一个(美学)和最后一个(可见度)例子是非常有趣的话题,但在本文中,我将讨论图像损伤/保真度评估。

主观质量

那么,如何引发人们对图像质量的判断呢?通常有两种不同的方法。评级和排名。在这篇文章中,我已经非常详细地讨论了这两种方法,其中我还讨论了合并从两个实验过程中获得的分数的方法。

分级实验的例子。图片作者。

在评级中,参与者被要求从预定义的尺度中给图像分配一个单一的分数。评级结果取决于为实验和训练程序选择的图像。与此同时,排名要简单得多,因为它问了一个简单的问题——哪张图片更好。排名的一个很大的缺点是大量可能的比较。我也有机会使用有效的配对选择方法进行排序实验,并在本文中讨论了一般的流程。

一旦收集了数据,我们就会有一个主观的图像质量数据集,如下图所示。

来自 TID2013 数据集的图像。

数据集中的每个图像都有相应的主观质量分数。

长期以来,缺乏足够大的图像质量数据集阻碍了客观质量算法的发展。理想的数据集将包含一系列图像内容的大量心理测量结果,以及不同损伤程度的各种失真。

收集足够大的数据集的问题已经在许多工作中得到了解决,在 Amazon Mechanical Turk 的帮助下,我们现在有了相当大量的数据集来训练指标。下面我总结了其中最大的几个:

客观质量

有了这些数据,我们就可以对感知质量进行建模。典型的图像质量度量将采用失真的图像,并产生与人类参与者提供的分数高度相关的分数。

通常有三种度量标准。无参考(不提供参考图像)、简化参考(提供参考图像的一些信息)和完全参考。在这里,我将重点介绍全引用度量,因为它们经常用于调优图像处理算法。

传统(基于像素的)度量

很长一段时间以来,图像质量都是借助峰值信噪比(PSNR)来计算的:

其中 MAX(I)是最大可能像素值,MSE 是均方误差,由下式给出:

另一个流行的度量是计算滑动窗口的图像统计的结构相似性指数度量(SSIM ):

包含三个组件亮度(l)、对比度和结构(s):

其中\mu 和\sigma 是参考图像 x 和测试图像 y 的补丁值的平均值和标准偏差。

作为感知质量评估器的基于像素的度量具有几个流程:

  • 它们不是像素偏移不变的,这意味着图像偏移一个像素会破坏质量预测。对于在滑动窗口上操作的度量标准,例如 SSIM,对结果进行平均,这个问题可以在某种程度上得到缓解,但是仍然存在。
  • 它们对所有像素值进行相等的等待,并且不考虑掩蔽或视觉突出效果。例如,高斯噪声可能会被图像中的高频细节掩盖,否则高斯模糊在图像的低频区域不会那么明显
  • 许多是为标准观看条件开发的,假设图像分辨率在每度 30-60 像素之间,显示亮度为每平方米 100 坎德拉,这在 CRT 显示器的时代是合理的。

尽管已经提出了这些度量的变体,例如 MS-SSIM(多尺度 SSIM)或 WSSIM。这些只是稍微改善了性能。

模拟人类视觉系统

一类更高级的度量标准旨在对人类视觉系统的假设进行建模或建立在这些假设的基础上(HVS):

https://www4.comp.polyu.edu.hk/~cslzhang/IQA/TIP_IQA_FSIM.pdf:基于参考图像和失真图像之间的相位一致性是解释感知图像质量的有意义特征的假设。相位一致性模型表明,在傅立叶分量在相位上最大的点处感知特征。为了结合对比度信息,对视觉系统很重要的 FSIM 也依赖于图像的梯度图。有一篇非常好的文章介绍了相位一致性是如何从头开始工作的。对于那些对使用 FSIM 作为损失函数感兴趣的人,请随意查看我的可微分 pytorch 实现

HDR-VDP :拥有一个非常复杂的多个组件模型,负责对人类视觉系统的不同部分进行建模。该模型的优势之一是它是一个白盒度量,每个组件都根据心理物理数据进行了仔细调整。该方法能够模拟不同观看条件下的质量,例如到屏幕的距离及其亮度。该模型的早期版本如下图所示:

hdr-vdp 早期版本的示意图。Rafal Mantiuk 的图片来自论文来源

大部分处理是基于对比敏感度函数(CSF)。CSF 解释了人类视觉系统感知作为空间频率函数的对比度变化的方式。

人类在高 CSF 值(每度 6-8 个周期)的空间频率下具有较低的对比度阈值因此,对于对比敏感度函数高的空间频率,感知失真的概率更高。

深度图像质量评估

新的大规模图像质量数据集使基于深度学习模型的图像质量度量得以发展。典型的基础模型是卷积神经网络(CNN)。如果你想了解 CNN 的基础和提高其性能的不同技巧,我在一篇由两部分组成的文章中谈到了这一点:第一部分第二部分

早期的深度图像质量模型没有太多要训练的数据,并且依赖于为分类模型预先训练的假设也将学习自然场景统计的分布。预训练的 VGG 或亚历克斯网络模型然后被用作特征提取器。在这些质量模型中,从参考和测试图像中提取的特征通常通过均方误差进行比较。因此,从测试和参考图像的特征空间中的距离获得质量分数。

它让你想起什么了吗?这正是知觉丧失正在做的事情!

图片由约翰逊拍摄。

这里,图像 x 通过生成器网络传递,产生输出 y,其中 y 应该具有 yc 的内容和 ys 的样式。

一些作品研究了为什么深层表征可能是良好的感知质量特征,最近的一篇研究了人类视觉系统中众所周知的概念之间的关系,例如对比敏感度和深层神经网络隐藏层的激活。这项工作还提出了选择深度表征的方法,以最大限度地提高与感知图像质量的相关性。

图片由塔里克拍摄。

现在让我们实际讨论一下深层图像质量评估指标!

经由 DNN 特征的 IQA:最初的作品之一不是比较简单的均方误差,而是将图像分解成多个尺度,并经由直方图相交核比较测试图像和参考图像的特征图直方图。

****

图片由阿米尔沙希提供。

DeepSIM :类似地,在测试和参考图像的特征空间中,用 SSIM 代替均方误差。一旦计算出每个特征图的分数,就将结果汇集并回归到单个全局质量分数。

LPIPS :虽然论文提出了一种新的质量度量,但在我看来,这项工作的主要贡献是比较不同的深度模型,这些模型以不同的方式训练为图像质量评估的特征提取器(在 BAPPS 数据集上)。与那些为不相关的图像任务(例如图像分类)预训练的模型相比,该工作显示了为图像质量评估模型预训练的明显优势。该模型使用特征提取器为两个输入图像产生低维嵌入 d0 和 d1(表示到参考的距离),然后通过浅网络 G 产生一个比另一个更好的概率。提议的模型还解决了不同层提取的特征的不同范围的问题(例如,早期层可能具有 0 和 1 的范围,0 和 100 之间的更深特征对质量分数的形成具有更大的贡献),并引入了学习的权重(下图中的橙色)来加权重要性。

图片由提供。

DeepQA :随着更多数据可用,模型开始利用迁移学习——在图像质量数据集上微调预训练的模型。甚至后来的训练都是从零开始。早期的模型相当肤浅。下面的模型是在从只有 800 张图像的实时图像质量数据集的图像中提取的补丁上训练的。该模型学习灵敏度图,即均方误差图的权重,然后对其进行平均以产生单个分数。为了确保灵敏度图不会崩溃到高频噪声,在训练期间引入了平滑约束。

图片由拍摄。

WA-DIQaM-FR :后来,随着更大的数据集可用,训练好的端到端模型变得更深更复杂。下面的模型是在来自 TID2013 数据集(3000 张图像)的图像上训练的。

图像由bosses拍摄。

PieApp :与其他基于通过回归到图像主观得分来学习模型参数的模型不同,PieApp 被训练来预测一个图像比另一个图像具有更好质量的概率(下图中左侧的图)。该模型基于暹罗网络(图中的蓝色),该网络提取要素,然后使用模型的得分计算部分(图中的绿色)将这些要素映射到单个数字。通过非线性的两个分数之间的差异提供了一个比另一个更好的概率。这种训练过程是由随论文提供的 PieApp 数据集实现的,其中主观实验中收集的基本事实排名分数用于提供更好质量的概率,如 P(A>B)=(A 选择 B 的次数)/(A 和 B 之间的比较总数)。

****

图片由 Prashnani 提供。

PIPAL :类似于传统的基于像素的方法,神经网络不具有像素移位不变性。在评估创成式模型的性能时,此属性尤其重要。其中胡须相对于参考图像的位置稍微不同的猫将被认为质量差。对于人眼来说,这种差异并不重要。为了开发像素移位不变性,PIPAL 提出了空间扭曲差模块,该模块不仅在测试和参考图像的相应位置上比较特征,而且在相应位置周围的小范围上比较特征,以明确地结合对空间错位的鲁棒性。

****

PIPAL 网络的完整架构(左)。空间扭曲差分模块(右)。图片由拍摄。

DISTS :与 PIPAL 类似,DISTS 允许测试和参考图像在纹理信息上有微小的不一致。该架构基于预训练的 VGG 网络,用作测试和参考图像的特征提取器。DISTS 计算仅具有亮度(l)和结构(s)分量的 SSIM 度量的修改。完整度量是每层计算的 l 和 s 统计的加权线性组合。权重是在卡迪-10K 数据集上调整的。

结果比较

图像质量度量的性能通常根据 Spearman 等级顺序相关系数(SROCC)与主观分数进行比较。该统计测试该度量是否能够根据主观尺度捕获失真图像的顺序。

PIPAL 数据集上评估的 Spearman 秩序相关系数。图片由提供。

与手工制作的指标相比,在大规模数据集上训练的深度模型始终产生强大的结果。但是,请注意,方法的性能在很大程度上取决于评估它们的数据集,因此一个好的规则是在尽可能多的数据集上测试指标的性能。总体而言,在大多数数据集上,PieApp 的表现往往优于其他产品。

超越 SROCC :

虽然 SROCC 提供了一些关于图像质量指标性能的见解,但它并没有告诉我们全部情况。在实践中,我们通常更感兴趣的是该指标与准确的主观得分或得分之间的相对距离的匹配程度。然而,实际上,质量度量的分数通常是没有意义的。例如,相距 1 PSNR 的两幅图像的感知质量有多大差异?在 25-30 和 20-25 范围内的 1 PSNR 的差异是否传达了感知质量的相同差异。为了解决这个问题,已经提出了几种方法。最常用的是下面的一种:

图片由克拉苏拉提供。

****从客观分数到主观分数的映射:通过某种非线性将分数映射到感知均匀的质量空间。通常使用以下映射:

其中 D 是客观指标的得分,\hat(D)是主观得分的映射,nu_{1…4}是学习参数。然而,这种映射是特定于数据集的,并且依赖于数据集中分数的质量,并且通常不能推广到训练数据之外。

对于较小的数据集,考虑使用统计技术来更好地验证模型。

应用程序

使用客观质量度量作为训练深度学习模型的损失函数的一个特别有趣的方向。那些对如何使用质量度量来优化现代图像处理算法感兴趣的人可能会对这篇论文感兴趣。最常用的图像质量指标已经被整合到 python 库中——你可以在:IQA-皮托奇PIQ 中找到这样的例子。

概观

图像质量评估的任务可以分为三个阶段:定义目标、收集人类标签和训练数据的客观质量度量。CNN 和更大且更通用的图像质量评估数据集的最近发展对客观图像质量度量的发展产生了影响。最先进的结果是通过深度模型实现的。然而,这些都有缺点。同样地,固定的输入大小,强制使用固定大小的图像补片或比较学习特征的统计;需要用于训练的大数据集;黑盒架构;推理时间长。这些都是仍然存在且有待解决的挑战。

如果你喜欢这篇文章,请与朋友分享!要阅读更多关于机器学习和图像处理的主题,请点击订阅!

喜欢作者?保持联系!

我错过了什么吗?不要犹豫,直接在 LinkedInTwitter 上给我留言、评论或发消息吧!

** **

深入奇异值分解

原文:https://towardsdatascience.com/deep-in-singular-value-decomposition-98cfd9532241?source=collection_archive---------23-----------------------

从头做起

数据科学中分解策略的概述,用代码解释。

(src =https://pixabay.com/images/id-3926174/)(懂吗?分解?)

介绍

在数据科学领域工作时,我们经常会遇到计算机很难解释的特征。这通常是因为数据的维度太大,计算机无法估算。这可能会有问题,因为很难观察一个特征的数百个维度。这是人类的情况,当然也包括计算机。

幸运的是,这个问题有一个解决方案。在数据科学的世界中,为了使这些值更容易被统计、机器学习和分析策略所识别,使用所谓的分解是很常见的。在大多数情况下,程序员会使用一种叫做奇异值分解的分解策略。然而(SVD),也有其他解决方案可以使用,如随机投影。在这两种解决方案中,SVD 使用得更广泛,因为随机投影需要点之间合适的维度空间,因此有时会在某些特征上出现问题。出于这个原因,本文将全部讨论 SVD 以及用 Python 从头开始编写 SVD。然而,如果你想学习更多关于随机投影的知识,以及它在数据科学中是如何运作的,我也有一篇文章可以让你阅读。

关于奇异值分解的更多信息

为了最小化特征的维数,SVD 无疑是数据科学家最常用的方法。这是因为 SVD 是我们所能使用的最通用、最古老的分解方法。SVD 是许多需要解释高维数据的模型的基础。如果不使用 SVD,我们就不太可能拥有自动驾驶汽车或图像识别,因为这些功能太多了,计算机无法在不利用分解的情况下真正读取,而分解通常会发生在 SVD 上。

为什么不用随机投影?答案实际上很简单,尽管随机投影在技术上更有效,并且应该在计算机上运行得更快,但是对于计算机来说,SVD 也很容易执行。考虑到这一点,大部分时间确实没有使用随机投影的好理由,使用随机投影的风险是数据的维度可能不够高维。这可能会导致严重的问题,因为您的要素会被分解,但并不代表原始数据。

求矩阵的奇异值分解

( src =维基百科)

为了弄清楚矩阵的奇异值分解,我们必须首先弄清楚我们到底要计算什么。奇异值分解可以表示为,V^t.是一个对角矩阵。现在让我们看看如何得到 V 矩阵。

v 代表 X 转置 X 的特征向量集,当然我是数据科学家,所以我经常喜欢用代码思考。我们要写一个函数,用 Julia 编程语言来计算所有这些。

这个矩阵需要是正交的。不使用正交矩阵也可以做到这一点,但我们只是在函数中为此做了准备。在 Julia 中,我们可以使用基本模块 LinearAlgebra,以便使用 eigvecs()方法计算特征向量。我们可以用乘法运算符*将矩阵相乘。为了计算 SVD 的 V,我们将转置的 A 乘以 A,然后得到其特征向量。

using LinearAlgebra: eigvecsV = eigvecs(transpose(a) * a)

接下来,我们将计算 sigma。适马很简单,从原始矩阵中得到特征值,我们可以用线性代数中的八分函数来实现。得到这些特征值后,我们需要求它们的平方根。

using LinearAlgebra: eigvals
Σ = eigvals(a)

最后,我们需要找到我们的 U 矩阵。为此,我喜欢使用 reduce()方法,以及这个迭代循环的水平连接:

U = reduce(hcat,[W[:,i]/S[i] **for** i=1:size(W,2)])

现在我们有了三个矩阵,我们可以简单地把它们代入奇异值分解公式。在数学中,我们可以这样表示:

uσv^t

在朱丽亚,我们把它变成了

U .* Σ .* transpose(V)

结论

降维是数据科学家用来解释有太多属性需要观察的数据的基本策略。最流行的降维方法 SVD 的伟大之处在于,它遵循一些相对基本的线性代数概念,保持相对良好的性能,同时也非常有效。考虑到这一点,所有数据科学家可能都应该研究一下这种方法,它提供的关于数据的知识很可能会在数据科学工作中派上用场。降维的目标永远是标准形式,即数据或数学表达式的最简单版本。如果你想了解更多关于标准形式的内容,你可以在这里阅读我的另一篇文章:

谢谢你看我的文章!我希望这是一篇信息丰富的文章,让读者更好地理解 SVD 及其在数据科学中的应用!

深度学习和迁移学习

原文:https://towardsdatascience.com/deep-learning-and-transfer-learning-31c6394b10c5?source=collection_archive---------19-----------------------

使用 Keras 的迁移学习的各种实现

作者图片

对复杂的神经网络模型进行几天、几周甚至几个月的训练并不罕见。我们大多数人都无法获得成功训练这些模型所需的大量数据和计算资源。也就是说,有 OpenAI、脸书、谷歌、脸书等实体。他们拥有开发非常复杂、精确和通用模型的资源。更重要的是,他们愿意为我们这些凡人开源这些模型,用于我们自己的研究。将预先训练好的模型融入到自己的模型中的过程被命名为“迁移学习”。

涵盖的主题

在本教程中,我们将回顾使用 Keras 库的迁移学习的四种独特实现。我们将讨论如何实现一个预先训练好的模型。我们将讨论如何只选择预训练模型的特定部分用于我们自己的模型。我们将回顾如何将新的定制砝码加载到预训练模型中。最后,我们将展示如何对图像的形状进行上采样,以符合预训练模型的形状要求。

  1. 使用整个(顶层除外)预训练模型进行迁移学习
  2. 使用预训练模型的特定部分进行迁移学习
  3. 通过将新权重加载到预训练模型中来转移学习
  4. 通过对图像形状进行上采样来适应预训练模型的输入要求的迁移学习

数据

我们将利用两种图像分类模型,即谷歌的 Inception_V3 ( 链接)和微软的 ResNet-50 ( 链接)。两者都是高度复杂的卷积神经网络,通过 1000 个对超过一百万张图像进行训练。我们将在使用 CIFAR-10 数据集的图像分类问题中使用这些模型。CIFAR-10 数据集由 10 个类别(飞机、汽车、鸟、猫、鹿、狗、青蛙、马、船和卡车)的 60,000 幅 32x32 彩色图像组成。有 50,000 幅图像用于训练,10,000 幅图像用于测试。总之,我们将使用迁移学习将 Inception_V3 和 ResNet-50 模型合并到我们自己的模型中,该模型将使用 CIFAR-10 数据集进行训练,以正确预测上面列出的 10 类图像。

概念上

迁移学习背后的基本概念可以用下图来解释。假设您试图创建一个多类图像分类模型(10 类:飞机、汽车、鸟、猫、鹿、狗、青蛙、马、船和卡车)。换句话说,你正在建立一个模型,它将尝试并正确地将一幅图像归类为上面列出的 10 个类别之一。开源的 Inception_V3 和 ResNet-50 模型是完整的图像分类模型,由 40 多个层组成,包括一系列卷积层、池化层、正则化层以及在顶部利用 softmax 激活函数的预测密集层。换句话说,您可以使用 Inception_V3 和 ResNet-50 模型,并且只能使用这些模型来对您的图像进行分类。这是因为它们在顶部都有一个完全连接的密集层,这将产生来自 softmax 激活函数的图像分类概率。

https://www . researchgate . net/figure/Schematic-diagram-of-InceptionV3-model-compressed-view _ fig 6 _ 326421398

也就是说,一般输入(即 Inception 和 ResNet 模型被训练的图像)和你的模型将被训练的图像可能是相似的(即动物的图像)与你试图解决的问题可能会有所不同。例如,不是试图分类 1000 个非常不同的图像(即飞机、汽车、鸟、猫等等)由于 Inception_V3 和 ResNet-50 被训练成这样,您可能会对分类各种狗品种感兴趣。在这种情况下,使用独立的 Inception 或 ResNet 模型对犬种进行分类可能会产生不良结果。我们要做的是利用这些复杂模型所学到的知识(即。不同类型图像之间的独特特征)并将该知识转移到我们试图分类的图像(即狗的品种)。下面是另一个传递知识的例子。

孙,b .,冯,j .,,萨恩科,K. (2016)。令人沮丧的简单领域适应的回归。《第三十届 AAAI 人工智能会议论文集》(AAAI-16)。从 http://arxiv.org/abs/1511.05547取回

迁移学习的过程包括从 Inception 或 ResNet 模型中移除原始的完全连接密集层。你基本上消除了模型的预测能力。接下来,您开始添加自己的自定义图层集,其中包括顶部完全连接的密集图层。通过遵循这一过程,您已经构建了一个模型,该模型包含了从 Inception 或 ResNet 模型中获取的大量一般图像分类知识,并且通过添加您自己的微调层来准确地对您自己的任务所需的图像进行分类。

此外,由我们来决定我们希望在模型中使用多少预训练模型。一般来说,在初始模型的早期部分中的卷积层将会学习非常一般化的特性(即垂直/水平线、全局形状等。)与识别非常具体的特征的后面的层相比较。后面的图层对模型没有见过的图像的概化程度较低。

https://www . Research gate . net/figure/Schematic-of-the-Inception-3-model-created-by-Google-Research-shlens 2016-and-modified _ fig 6 _ 321307161

说够了,我们来编码吧!

本教程的所有开发都是使用 Google Colab 的数据处理功能完成的。你当然可以在本地机器上运行这段代码,但是除非你有一个专用的 GPU,否则训练时间可能会相当长。

图像处理

让我们将所需的库和数据一起导入。如上所述,我们将使用 CIFAR-10 数据集,它由 10 个类别(飞机、汽车、鸟、猫、鹿、狗、青蛙、马、船和卡车)的 60,000 张 32x32 彩色图像组成。有 50,000 幅图像用于训练,10,000 幅图像用于测试。

import tensorflow as tf
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from keras.utils.vis_utils import plot_model
from tensorflow.keras.utils import to_categorical
from keras.models import Model
from keras import backend as K
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from keras.optimizers import Adam
from tensorflow.keras.applications.inception_v3 import InceptionV3
from tensorflow.keras.applications.resnet50 import ResNet50%matplotlib inlinedata = tf.keras.datasets.cifar10
(train_images, train_labels), (test_images, test_labels) = data.load_data()print(train_images.shape, train_labels.shape, test_images.shape, test_labels.shape)

50,000 个训练图像,每个 32x32 乘 3 个通道(彩色)/ 50,000 个训练标签 0–9 个类别

正如你所想象的,32x32 的图像将会非常像素化,但我们仍然可以分辨出图像的一般类别。

fig, ax = plt.subplots(1, 5)
fig.set_size_inches(16, 6)for i in range(5):
  img = train_images[i]
  ax[i].imshow(img)
  plt.show()classes = ['airplane', 'automobile', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck']print('Image Classes:' + str([x[0] for x in train_labels[0:5]]))print('Image Labels: ' + str([classes[x[0]] for x in train_labels[0:5]]))

作者图片

快速图像处理

缩放像素值和一次性编码标签

因为我们的图像是彩色的,所以三个通道(红、蓝、绿)的训练像素值在 0-255 之间。通常的做法是将值缩放 1.0/255 倍,以在 0 和 1 之间转换像素值。此外,我们的类标签已经进行了标签编码(0–9 ),这引入了类之间的自然顺序(即 1 大于 0,2 大于 1…).由于我们有一个分类问题,我们需要消除这些潜在的混淆关系。我们将应用一键编码,将类标签转换成二进制数组。

train_images = train_images / 255.0test_images = test_images / 255.0train_labels = to_categorical(train_labels)test_labels = to_categorical(test_labels)

1.使用整个(顶层除外)预训练模型进行迁移学习

可以想象,根据您的特定需求,迁移学习有多种实现方式。第一种技术包括加载一个预先训练的模型,使用其权重作为模型中的第一个连续层,并添加您自己的自定义层(即。通常称为“微调”的过程)来对 CIFAR-10 图像进行分类。

首先,我们需要实例化预训练的 ResNet-50 模型。将“include_top”参数设置为“False”实质上将删除最后一个(即 top)全连通预测(softmax)密集层。由于这将是我们的模型中的第一层,我们将 input_shape 设置为(32,32,3),这是我们的 CIFAR-10 图像的形状(即。32x32 像素和 3 个彩色通道(RBG)。

K.clear_session()
base_model = ResNet50(include_top=False, weights='imagenet', input_shape=(32, 32, 3), classes=train_labels.shape[1])

由于迁移学习的全部目的是使用预先训练好的模型的知识(即。预训练权重)在我们的模型中,我们将“可训练”参数设置为假。这样,我们就不会根据自己的数据重新训练 ResNet-50。我们还可以仔细检查每一层是否冻结。

base_model.trainable = False
for layer in base_model.layers:
   print(layer, layer.trainable)

最后,我们将构建模型。“预训练模型”变量将包含来自 ResNet-50 的冻结重量。这些权重将被输入到 Flatten 层,这恰好是我们在预训练 ResNet 层之后添加的第一个自定义或微调层。然后,我们继续添加额外的层,密集 1 和密集 2,接着是我们的全连接层,这将使用 softmax 激活功能进行 10 级分类。

pre_trained_model = base_model.output flat = tf.keras.layers.Flatten()(pre_trained_model)dense1 = tf.keras.layers.Dense(1024, activation='relu')(flat)dense2 = tf.keras.layers.Dense(512, activation='relu')(dense1)predictions = tf.keras.layers.Dense(10, activation='softmax')(dense2)

最后,我们通过传递 base_model 输入(即预训练权重)转换为输入参数,并将我们的预测转换为输出参数。最后,我们编译模型,为训练做好准备。请注意“总参数”和“可训练参数”之间的区别。我们模型中的大多数参数属于 ResNet 层,如果您还记得的话,该层是冻结的。

model = Model(inputs = base_model.input, outputs = predictions, name="cifar10_model")model.compile(optimizer=Adam(learning_rate=0.0001), loss='categorical_crossentropy', metrics=['accuracy']) model.summary()

这是建立这个模型的另一种方法。

K.clear_session()base_model = ResNet50(include_top=False, weights='imagenet', input_shape=(32, 32, 3), classes=train_labels.shape[1])base_model.trainable = Falsemodel = tf.keras.Sequential([
base_model, tf.keras.layers.Flatten(), 
tf.keras.layers.Dense(1024, activation='relu'), tf.keras.layers.Dense(512, activation='relu'), tf.keras.layers.Dense(10, activation='softmax')])

2.使用预训练模型的特定部分进行迁移学习

如前所述,当构建卷积网络时,早期的卷积层学习非常一般化的特征(即垂直/水平线、全局形状等。)而后面的卷积层学习非常具体的特征。后面的图层对模型没有见过的图像的概化程度较低。因此,有时最好只使用预训练模型的前几个卷积层,然后添加您自己的微调层,以了解特定于您的训练图像的特征。

首先,我们将再次实例化 ResNet-50 模型,然后我们将打印它的摘要,以确定我们到底要在哪里进行切割。你决定削减预训练模型将需要一些试验和错误。请记住,模型摘要很可能会非常大。

K.clear_session()base_model = ResNet50(include_top=False, weights='imagenet', input_shape=(32, 32, 3), classes=train_labels.shape[1])base_model.summary()

让我们在名为“conv3_block1_3_conv”的图层上进行剪切。注意,我们使用 get_layer()函数获取特定的层,并将其输出设置为 last_output 变量。Last_output 成为我们的微调模型中的第一层,它的输出被传递到展平层。

K.clear_session()base_model = ResNet50(include_top=False, weights='imagenet', input_shape=(32, 32, 3), classes=train_labels.shape[1])base_model.trainable = Falselast_layer = base_model.get_layer('conv3_block1_3_conv')last_output = last_layer.outputflat = tf.keras.layers.Flatten()(last_output)dense1 = tf.keras.layers.Dense(1024, activation='relu')(flat)dense2 = tf.keras.layers.Dense(512, activation='relu')(dense1)predictions = tf.keras.layers.Dense(10, activation='softmax')(dense2)model = Model(inputs = base_model.input, outputs = predictions, name="cifar10_model")model.compile(optimizer=Adam(learning_rate=0.01), loss='categorical_crossentropy', metrics=['accuracy']) 

3.通过将新权重加载到预训练模型中来转移学习

有时,您会希望解冻预训练传输模型中的某些层(即 ResNet 或 Inception)来使用您的训练图像重新训练那些“未冻结”的层。如果您曾经想要将这个新版本的微调模型与一些重新训练的 ResNet 或 Inception 层一起重用,那么您需要在将来将这些权重上传到模型中。在本节中,我们将讨论如何将存储在“h5”文件中的自定义权重加载到预训练模型的架构中。

首先,您需要获得特定于模型架构的权重。这些可以作为模型的更新权重或从您自己的自定义再训练中保存的权重来获得。在本例中,我们将从 github 帐户下载权重。请记住,这些重量不拥有顶部(即。预测)层。注意文件标签中的“notop.h5”。

您需要再次实例化预训练模型,但这次将“权重”参数设置为 None 。接下来,我们使用 load_weights()函数加载保存的权重。确保将“by_name”参数设置为 True ,因为这将根据每个层的名称加载权重。请记住,此程序仅加载预训练模型的权重(即《盗梦空间》、《雷斯网》、《VGG》等。)它不会加载整个微调模型的权重。

K.clear_session()
!wget --no-check-certificate \https://github.com/fchollet/deep-learning-models/releases/download/v0.2/resnet50_weights_tf_dim_ordering_tf_kernels_notop.h5 \-O /tmp/resnet_50_weights_tf_dim_ordering_tf_kernels_notop.h5local_weights_file = '/tmp/resnet_50_weights_tf_dim_ordering_tf_kernels_notop.h5'base_model = ResNet50(weights=None, input_shape=(32, 32, 3), include_top=False, classes=train_labels.shape[1])base_model.load_weights(local_weights_file, by_name=True)

最后,我们照常构建我们的模型。我们再次将“可训练”参数设置为 False,因为我们不想重新训练刚刚加载的新重量。

base_model.trainable = Falsepre_trained_model = base_model.output flat = tf.keras.layers.Flatten()(pre_trained_model)dense1 = tf.keras.layers.Dense(1024, activation='relu')(flat)dense2 = tf.keras.layers.Dense(512, activation='relu')(dense1)predictions = tf.keras.layers.Dense(10, activation='softmax')(dense2)model = Model(inputs = base_model.input, outputs = predictions, name="cifar10_model")model.compile(optimizer=Adam(learning_rate=0.01), loss='categorical_crossentropy', metrics=['accuracy']) 

4.通过对图像形状进行上采样以适应预训练模型的输入要求的迁移学习

有些模型要求您在传递数据之前调整数据的输入大小。例如,如果您使用我们上面讨论的第一种迁移学习方法,但是这次使用 Inception_V3 模型,您将会看到下面的错误。这是因为 CIFAR-10 图像的形状为 32x32x3,而 Inception_V3 模型要求图像至少为 75x75,而不考虑通道的数量。另一方面,ResNet 有一个最佳形状,但它不要求您的输入形状是一个特定的大小。

为了遵守这些形状要求,我们需要将图像“上采样”到适当的形状。有各种各样的技术用于执行这个操作,但是 Keras 有一个“Upsamplign2D”类,它只是将像素复制到指定的形状。在下面的例子中,原始图像中的每个像素被复制 3 次。

2016 马修·吉亚萨

为了超过像素形状的要求,我们需要将像素放大两倍。我们再次实例化我们的 base_model,这次使用 Inception_V3。请注意,input_shape 为(128,128,3)。我们也将冻结所有的层。现在,我们开始构建我们的顺序模型,第一层是“输入层”,它只是作为数据的入口点。我们将 input_shape 指定为(32,32,3),这与我们的 CIFAR-10 图像的形状相匹配。接下来,我们需要对图像进行两次上采样(即 32x2=64,64x2=128)。如果我们仅向上采样一次,我们的图像将具有(64,64,3)的形状,这仍然不满足(75x75)的要求。通过两次上采样,我们的图像现在是(128,128,3),注意这是我们如何获得基本模型的输入形状的。

K.clear_session()base_model = InceptionV3(include_top=False, weights='imagenet',  input_shape=(128, 128, 3), classes=train_labels.shape[1])base_model.trainable = Falseinputs = tf.keras.layers.Input(shape=(32, 32, 3)) upsamp1 = tf.keras.layers.UpSampling2D((2,2))(inputs)upsamp2 = tf.keras.layers.UpSampling2D((2,2))(upsamp1)pre_trained_model = base_model(upsamp2) flat = tf.keras.layers.Flatten()(pre_trained_model)dense1 = tf.keras.layers.Dense(1024, activation='relu')(flat)dense2 = tf.keras.layers.Dense(512, activation='relu')(dense1)drop1 = tf.keras.layers.Dropout(0.3)(dense2)dense3 = tf.keras.layers.Dense(128, activation='relu')(drop1)predictions = tf.keras.layers.Dense(10, activation='softmax')(dense3)model = Model(inputs = inputs, outputs = predictions)model.compile(optimizer=Adam(learning_rate=0.0001), loss='categorical_crossentropy', metrics=['accuracy'])

另一种写代码的方式。

K.clear_session()base_model = tf.keras.applications.InceptionV3(include_top=False, weights='imagenet', input_shape=(128, 128, 3), classes=train_labels.shape[1])base_model.trainable = Falsemodel = tf.keras.Sequential([
tf.keras.layers.InputLayer(input_shape=(32, 32, 3)),
tf.keras.layers.UpSampling2D(size = (2,2)),
tf.keras.layers.UpSampling2D(size = (2,2)),
base_model,
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(1024, activation='relu'),
tf.keras.layers.Dense(512, activation='relu'),
tf.keras.layers.Dropout(0.3),
tf.keras.layers.Dense(128, activation='relu'),
tf.keras.layers.Dense(10, activation='softmax')])model.compile(optimizer=Adam(learning_rate=0.0001), loss='categorical_crossentropy', metrics=['accuracy'])

结论

迁移学习的出现已经成为人工智能在我们今天看到的许多行业中成功实施的关键驱动因素。随着我们的深度学习模型以指数级增长,变得更加复杂,渴望不断扩展的数据量,这种模型所需的计算资源也在增加。迁移学习提供了人工智能社区来利用(即 stack)这些复杂的模型,而不需要拥有大量金融资源的实体所积累的计算资源。

感谢您的时间,我欢迎任何反馈。

这里有一个 github,它是迁移学习环境中经常使用的各种开源模型(链接)。

基于深度学习的癌症患者分层

原文:https://towardsdatascience.com/deep-learning-based-cancer-patient-stratification-a12f4e2615f2?source=collection_archive---------21-----------------------

国家癌症研究所Unsplash 上拍摄的照片

癌症是一个重大的公共卫生和经济问题,其负担日益加重。仅在美国,它就占了 900 亿美元的直接医疗费用。开发一种抗癌药物要花费 27 亿美元。每年大约有 950 万人死于癌症。这比世界上一些大城市的人口还要多。我们的 Arcas 项目旨在通过在几十年的基因组技术基础上采用最先进的数据整合和分析方法来改善这种情况。

为什么癌症负担这么高?

开发药物并将其提供给患者是一个漫长而耗时的过程。首先,一种需要到达患者体内的化合物,必须经过临床前研究和临床试验的不同阶段。接下来是批准程序,最后医生必须开处方,并相信这可以帮助病人。有时这类药物需要在指南中列出才能被开出——即使它们被批准了。可以肯定地说,这个过程的每一步都存在许多低效之处。

图 1 :药物研发流程和基因组学数据的使用。作者图片

效率低下最常见或最具影响力的原因是在流程链的不同部分采用了过于简单和狭隘的方法。这里有一个例子:我们说癌症是一种基因组疾病,然而,癌症患者很少得到他们的基因组测序和解释。当他们这样做时,只有几百个基因被测序。信息,如影像学和组织病理学分期等。是有用的,但是提供了疾病的有限图像。因此,如果你不考虑整个基因组,很多信息就会丢失。这是治疗决策的情况,也是药物开发的情况。

现在很清楚,对治疗的反应,特别是对靶向药物的反应,强烈依赖于肿瘤的遗传、表观遗传、转录组构成以及肿瘤微环境(例如: WINTHER 试验)。所有这些在不同的癌症之间有很大的不同,甚至来自同一组织。因此,必须根据癌症的基因型/表观基因型/转录组来评估药物反应。此外,许多药物之所以会失败,仅仅是因为它们只对一部分癌症有效,而这一点在试验时并没有得到最初的认识。

许多药物之所以会失败,仅仅是因为它们只对一部分癌症有效,而这一点在试验时没有得到最初的认识

用于临床变量建模的多组学模式

消除这些问题的一个方法是接受临床变量,如药物反应,是由基因组/转录组/表观基因组模式驱动的,而不仅仅是由单个基因的突变驱动的。一旦我们接受了这一点,我们就必须有有效的方法来分析来自癌症活检或肿瘤模型的多水平数据集,如多组学。多组学数据的有效整合将为临床变量建模提供无假设或假设稀疏、数据驱动和整合的方法。

“一种无假设或假设稀疏、数据驱动和集成的临床变量建模方法。”

图 2 :癌症组学的数据整合可以提供预测临床变量的分子模式。作者图片

在 Arcas,我们开发了这样的框架,它使用深度学习来整合任何类型的组学数据,并发现分子模式,或所谓的潜在因素。潜在因素可用于 1)聚类/亚型检测或绘制疾病模型和原发肿瘤——类似于生物搜索引擎。想象一下,你可以为你的疾病模型输入多组学数据,我们可以告诉你这些模型最能代表哪些原发性癌症。此外, 2)我们可以对生存和药物反应等变量进行建模。此外,3)我们还可以解释潜在的因素,并了解它们对应于哪些分子机制或途径

使用深度学习进行患者分层

分子模式或潜在因素可以根据预后或对药物的反应或任何其他临床变量对患者进行分层。我们已经将部分 Arcas 技术应用于结肠直肠癌。结肠直肠癌主要使用基因表达谱定义了四种亚型。这些亚型被称为共有分子亚型或 CMS。该联盟定义了四种亚型,它们具有不同的分子特征,在某种程度上与存活率相关,然而 19%的患者不能被归入特定的亚型。

我们能用潜在因素预测亚型吗?

如果这些分子模式,即潜在因素,包含相关信息,我们应该能够从中预测 CMS。这里我们看到的是一个接收器工作特性曲线,或 ROC 曲线,它显示了一个分类器有多好。在我们的病例中,ROC 曲线显示潜在因素能够预测 CMS 亚型。我们比较了我们的方法与其他方法,也产生潜在的因素或相关的主成分。在所有情况下,我们的预测精度更高。在图 3 的右侧,我们根据 CMS 状态对潜在因素的 2D 投影进行了颜色编码。每个点是原发性肿瘤,由 CMS 状态着色。你可以看到颜色的分离,这意味着有关于 CMS 状态的潜在因素的信息。

图 3 :利用深度学习获得的潜在因子预测亚型更加准确。左,与其他工具相比的准确性。右,通过减少 2D 的潜在因素来表现结肠直肠肿瘤。从作者的公开出版物【https://pubmed.ncbi.nlm.nih.gov/31792061/. 获得的情节

细化子类型

我们可以使用这项技术进一步细化子类型。您可能已经注意到,在图 3 中,有比基于 CMS 的颜色更多的聚类。如果我们应用聚类算法,我们可以找到六个聚类。最大的区别是我们把 CMS2 分成两个集群。从生存的角度来说,这其实很有道理。在图 4 中,我们展示了这两个新集群的生存曲线,它们非常不同。因此,将 CMS2 分成两个亚型是合理的。

图 4 :结直肠癌细化亚型。绿点和蓝点代表 CMS2 亚型,然而根据这两个组的不同生存特征,根据潜在因素聚类的建议将该亚型分成 2 个亚型更有意义。从作者的公开出版物https://pubmed.ncbi.nlm.nih.gov/31792061/获得的情节

对其他癌症也有效

我们应该强调的一点是,这种方法并不局限于特定的癌症类型。它适用于任何具有多组学信息的数据集,包括肿瘤模型,如细胞系、PDX 或类器官。事实上,你可以用我们的方法整合细胞系、PDX 和原发肿瘤——这在正常情况下是很难做到的。

图 5 : Arcas 平台比使用临床特征改善了生存预测。作者图片

我们已经在至少有 100 个样本的癌症基因组图谱数据集上运行了这个,在图 5 中,我们显示了我们改善了多少 C 指数。c 指数是生存预测准确性的一个衡量标准。我们展示了当我们试图仅通过使用临床变量,如年龄、性别和肿瘤分期来预测生存率时会发生什么——与临床变量+潜在因素进行比较。正如你所看到的,在许多癌症中,当使用潜在因素时,我们将这个准确性指标推向了一个更高的水平。

结论

随着测序价格的下降,构建和运行我们的模型所需的数据变得越来越容易生成。在不久的将来,液体活检和活检将通过多组学方法进行常规分析。整合和理解这些数据集是改进药物开发和诊断过程的关键。我们的 Arcas 平台从肿瘤活检或疾病模型的多组学数据集提供可操作的见解。

https://arcas.ai/blog/】本文原载于https://arcas.ai/blog/

用于 3D 合成的深度学习

原文:https://towardsdatascience.com/deep-learning-for-3d-synthesis-2dd57e2001f?source=collection_archive---------3-----------------------

人工智能的现状

变压器与卷积深度网络用于合成 3D 数据

照片由迪奥戈·努内斯Unsplash 拍摄

3D 数据简介

人们一致认为,从单一视角合成 3D 数据是人类视觉的一项基本功能,这对计算机视觉算法来说极具挑战性。但是,随着激光雷达、RGB-D 相机(RealSense、Kinect)和 3D 扫描仪等 3D 传感器的可用性和可负担性的提高,3D 采集技术的最新进展取得了巨大的飞跃。与广泛可用的 2D 数据不同,3D 数据具有丰富的比例和几何信息,从而为机器更好地理解环境提供了机会。然而,与 2D 数据相比,3D 数据的可用性相对较低,且采集成本较高。因此,最近已经提出了许多深度学习方法来从可用的 2D 数据合成 3D 数据,而不依赖于任何 3D 传感器。但是在我们深入研究这些方法之前,我们应该理解处理 3D 数据的格式。

来自 2D 输入的 3D 合成

基于数据的最终用途,合成的三维数据可以用不同的格式表示。一些常用的格式有:

  1. 深度图像
  2. 点云
  3. 体素
  4. 网状物

深度图像包含一个场景的深度值,其形式为图像帧中每个像素与相机的距离(米)。这种来自场景的深度信息对于许多任务都具有巨大的价值,如自动驾驶汽车、增强现实、机器人等。这种信息对于像在相机扫描静止场景和虚拟相机中的动画时启用运动视差这样的任务非常有用,但是当强调场景中的特定对象用于 3D 建模时,这种信息在现有技术中变得不充分和不准确

深度图像

****点云是分布在三维空间中的三维点的集合。这些 3D 点中的每一个都具有由某个(x,y,z)坐标以及其他属性(如 RGB 颜色值)表示的确定性位置。与深度图像不同,点云表示保留了更多高质量的三维空间几何信息,无需任何离散化。然而,点云表示在点之间没有局部连接,从而导致非常大的自由度和高维数,这使得精确合成更加困难。

点云表示

****体素或体积像素是空间网格像素到体积网格体素的直接延伸。简单来说,体素就是三维空间中的一个像素。每个体素的相对位置一起定义了体积数据的独特结构。一个体素可以看作是一个固定大小的量化点云。然而,对于 3D 建模,体素表示太稀疏,并且显示出细节和计算资源之间的折衷,这使得其更不可行。

体素表示

****多边形网格是边、顶点和面的集合,它们共同定义了多面体对象的形状和体积。网格的凸多边形面连接在一起,近似于一个几何曲面。与体素类似,网格也可以看作是从一组连续曲面上采样得到的三维点云集合(复杂度相对较低)。网格面可以是三角形(三角形网格)、四边形(四边形网格)或凸多边形(n 边形网格)。接近更真实的表示,网格也可以由带孔的多边形或凹多边形组成,这取决于表示的通用性。然而,与体素和点云不同,体素和点云会丢失重要的表面细节,且对于重建表面模型来说不是微不足道的,网格对于许多实际应用来说是更理想的。因此,考虑到以上几点,与其他格式相比,多边形网格似乎更真实,也是合成的更好的表示。

多边形网格表示

在这篇博客中,我们将讨论三种可用于从 2D 数据合成 3D 数据的方法。在这三种方法中,一种方法基于基于变换器的架构,而另外两种方法分别基于自动编码器和基于图的卷积神经网络。这两种方法之间的关键区别在于,与后者不同,基于变压器的深度网络完全依赖于注意机制来绘制输入和输出之间的全局依赖关系。

卷积神经网络

在本节中,我们将讨论最近提出的两种方法,它们使用自动编码器和基于图形的卷积神经网络来合成 3D 数据。

基于自动编码器的卷积神经网络

为了理解这种方法,我们将以使用自动编码器网络的 3D 人脸重建和人脸对齐为例。

人脸重建和人脸对齐

自动编码器使用卷积网络来将输入 2D 图像的维度降低到潜在空间,然后使用该潜在空间表示来重建原始 3D 数据格式。许多研究已经使用自动编码器(基于编码器-解码器的架构)来估计 3D 面部可变形模型系数和模型扭曲函数。这些研究的目的主要是使用这些 3D 模型扭曲函数从单个 RGB 图像恢复相应的 3D 形状,从而同时提供密集的 3D 人脸对齐和重建输出。然而,这种方法的性能受到由人脸模型模板定义的 3D 表示空间的限制。类似地,体积回归网络(VRN) [1]等方法使用全卷积层架构来估计三维二进制体积,作为点云的离散化版本。然而,大多数输出点对应于浪费的非表面点,并且这种离散化也限制了输出表示的分辨率。因此,要讨论的更好的研究将是类似位置图回归网络(PRN)[2]的网络,该网络使用 UV 位置和纹理图来联合预测密集对齐并重建 3D 人脸形状。

UV 位置和纹理贴图的图解

PRN 以 UV 位置图的形式构建了 3D 面部结构的 2D 表示。UV 位置是记录面部点云的 3D 面部坐标的 2D 图像。该地图还在表示中的每个位置附加 3D 坐标的语义特征。简而言之,UV 贴图是 3D 数据的 2D 表示,它记录了 UV 空间中所有点的 3D 坐标。在计算机图形领域,研究人员经常使用 UV 空间和 UV 位置图来将 3D 空间参数化为 2D 图像平面。转到 PRN 的网络架构,网络采用输入 RGB 图像,并使用简单的编码器-解码器结构(自动编码器)将 2D 图像信息传输到 UV 位置图。自动编码器通过使用 10 个下采样残差块和 17 个上采样转置卷积块来拟合该传递函数,以最终预测 256×256×3 的 UV 位置图。学习的 UV 位置图有助于直接回归要合成的 3D 面部的最终 3D 结构和语义特征。对于像 PRN 这样的训练网络,我们只需要像 2D 图像到 3D 点云映射这样的数据集,这使得这种方法更有用,因为网络的输出格式不受特定 3D 模板或 3D 变形模型线性空间的限制。

PRN 建筑

因此,考虑到该方法的简单性和有效性,PRN 似乎是从 2D 影像合成 3D 数据用于网络输出格式的最佳选择之一。

基于图的卷积神经网络

如前一节所述,大多数传统的基于自动编码器的深度学习方法利用点云和体素数据格式来合成 3D 数据。特别强调这两种数据格式的主要原因是流行的基于网格的网络架构所施加的限制。然而,点云和体素表示有其自身的缺点,如第一部分所述。因此,为了避免体素或点云表示的缺点,许多研究已经转向合成 3D 多边形网格数据,从应用的角度来看,这是更理想的格式。一些在合成网格数据方面非常有效的最佳架构设计方法包括基于图形的卷积神经网络。在本节中,我们将以王等人提出的方法为例。al [3] (Pixel2Mesh)。

使用 Pixel2Mesh 重建真实世界图像

Pixel2Mesh 是一个基于图形的端到端深度学习框架,它以单个 RGB 彩色图像作为输入,并将 2D 图像以更理想的相机坐标格式转换为 3D 网格模型。基于图形的卷积神经网络提取并利用 2D 图像中的感知特征,通过逐渐变形椭圆体直到其达到语义正确和优化的几何形状来产生 3D 网格。所采用的策略是一种由粗到细的方法,使得椭球体变形过程在几何上平滑和稳定。作者还定义了各种网格相关的损失函数,帮助网络捕捉更多的属性,以保证物理和视觉上吸引人的 3D 几何结果。

图像特征网络和级联网格变形网络

Pixel2Mesh 的结构主要由级联的网格变形网络和图像特征网络组成。图像特征网络负责从输入 2D 图像中提取感知特征,并将这些特征渐进地传递给基于图形的级联网格变形网络,以将椭球网格的几何形状渐进地变形为目标对象的 3D 网格。网格变形网络的图形卷积网络包含三个变形块以及两个中间图形展开层。变形块渐进地处理网格模型的输入图形,而中间图形展开层渐进地增加图形顶点以增加图形的信息保持能力,同时仍然保持数据的三角形网格结构。除了架构细节,Pixel2Mesh 基于图形的架构的主要优势之一是能够执行同步形状分析,类似于传统的基于图表的方法,直接针对曲面流形进行卷积运算。这种方法通过合并网格对象的两种自然表示(图形和表面流形)在基于图表的方法和 3D 重建方法之间充当桥梁。

基于变压器的深层架构

卷积神经网络广泛用于计算机视觉任务,因为它们具有端到端的能力来学习直接从数据执行任务,而不需要任何手工设计的视觉特征。然而,虽然 CNN 的架构设计在计算上要求很高,但是 3D 合成的任务使得这种计算更加密集,并且开启了计算优化和效率提高的大范围。展望下一代神经架构,变压器是可扩展视觉模型的最佳家族,不仅是领域不可知的,而且是计算高效和优化的。此外,最近的研究表明,变换已经在许多基于计算机视觉的任务上取得了最先进的结果。为了理解变压器在 3D 数据合成中的工作,我们将以 Deepmind 的 Polygen 为例[4]。

PolyGen 生成的样本

Polygen 是一种直接模拟 n 边形 3D 网格的方法,它使用基于转换器的体系结构依次预测网格面和顶点。模型设计是这样的,它可以调节一系列输入(对象类、体素和 2D 图像),并从概率上产生输出,以捕捉模糊场景中的不确定性。该网络由顶点模型和人脸模型组成。顶点模型是一个屏蔽的变换器解码器,它无条件地表示顶点序列上的分布,以模拟网格顶点。而面部模型是基于指针网络的变换器,其有条件地表达可变长度输入顶点序列上的分布,以对网格面部建模。因此,简而言之,两个转换器模型的目标是通过首先生成网格顶点,然后使用这些顶点生成网格面,来估计 3D 网格上的分布。

基于变形器的多边形顶点和面模型

Polygen 中使用的变压器架构受到 WaveNet、PixelRNN 和 pointer networks 等顺序模型的启发。这项工作还从多边形 RNN(使用多边形分割)中获得了重要的灵感,而顶点模型类似于 PointGrow [8]的定制自关注架构,使用自回归分解对 3D 点云进行建模。与顺序自回归模型相比,PointGrow 具有更浅的自关注架构,该架构通过对固定长度的点云输入进行操作,使用自关注机制来预测离散坐标分布。因此,Polygen 可以被认为是通过一种新颖的基于变压器的网络设计手段结合起来的一些最佳想法的均衡组合。

网格变形块和感知特征池操作

Polygen 的一个关键特性是能够根据输入上下文(上下文示例:2D 图像、对象类)调节输出。为了实现这种条件性质,顶点和面部模型的输入流被改变以结合上下文。对于像 2D 图像和体素这样的输入格式,首先使用域适当的编码器对输入进行编码,以便为变换器解码器检索上下文嵌入,从而在嵌入序列中执行交叉注意。而对于像对象类这样的输入格式,预学习类嵌入被投影到一个向量,该向量被添加到位于每个网络块中的自关注层之后的中间变换器预测表示中。这是完全可能的,因为顶点模型的一般性质使用简单的、有表现力的和高建模能力的变换器-解码器架构,该架构允许网络对来自不同域的数据进行建模。转换器使用其高效信息聚合的能力来捕捉网格顶点和对象几何体中存在的强非局部依赖性。

结论

在这篇博客中,我们讨论了两种主要的 3D 合成方法,即卷积深度网和基于变换器的深度网。新一代网络的变换器是以计算效率更高和优化的方式设计的,因此可以认为比传统的卷积网络领先了一步。然而,在接近实时推理场景时,transformers 还有很长的路要走,才能赶上我们在 autoencoder 一节中讨论的相对轻量级且快速的推理方法。然而,变形金刚拥有巨大的研究范围,它们的注意力机制能够有效地聚合信息并提取输入和输出之间的全局依赖关系,这使它们更有前途。

来源

我的博客反映了我所从事的工作,并简单地传达了我对这些话题的理解。我对深度学习的解读可以和你不一样,但我的解读只能和我一样无误。

参考

[1] Jackson,A.S .,Bulat,a .,Argyriou,v .,Tzimiropoulos,g .,Jackson,A.S .。国际计算机视觉会议。(2017)

[2] 用位置图回归网络联合 3D 人脸重建和密集对齐

[3] Pixel2Mesh:从单幅 RGB 图像生成 3D 网格模型(ECCV2018)

【4】PolyGen:3D 网格的自回归生成模型

[5] 孙,杨,王,杨,刘,z,西格尔,J. E .和萨玛,S. E .点增长:自回归学习点云生成与自我关注。在2020 年计算机视觉应用冬季会议

利用语音命令数据集对音频进行深度学习

原文:https://towardsdatascience.com/deep-learning-for-audio-with-the-speech-commands-dataset-79f7023de903?source=collection_archive---------20-----------------------

在这里,我们在语音命令音频数据集上训练一个非常简单的模型,并分析它的失败案例,看看如何最好地改进它!

在过去的十年中,深度学习已经成为一种流行而有效的技术,用于学习各种不同的数据类型。虽然大多数人都知道深度学习在图像或文本中的应用,但深度学习也可以用于音频数据的各种任务!

在我之前从事自动驾驶汽车的工作中,我花了很多时间研究图像和 3D 点云的深度学习模型。虽然我们有一些很酷的音频处理应用程序,但我只是浅尝辄止,从未认真做过。

然而,在水族馆这里,我们有一些客户正在开发一些非常有趣的音频数据应用程序。我们最近举行了为期 3 天的黑客马拉松,所以我决定尝试为自己做音频深度学习。

在这篇博文中,我们将在语音命令音频数据集上训练一个非常简单的模型。然后,我们将使用 Aquarium 来分析其失败案例,并确定如何最好地改进模型。

如果你想继续下去,我在这个项目中使用的全部代码可以在这里找到。数据集和模型推论可以在这里访问

选择数据集

我寻找一个数据集,它不是太小而不能做任何有趣的事情,而是足够小,以至于我可以使用我的本地机器在其上训练一个模型,而不需要一个更好的分布式设置。

经过一番搜索,我找到了语音命令数据集,它由大约 1 秒长的人们说单个单词的音频记录以及包含背景噪音的片段组成。该任务是分类任务,其中模型收听音频片段,并对某个触发词是否被说出进行分类。

更好的是,还有一个漂亮的 Pytorch 示例,它加载数据集并在其上训练一个模型。对于这个项目,我使用了这段代码,做了一些相对较小的修改。我想从盒子里拿出一些相对的东西,训练它,然后理解它是如何以及为什么失败的。

与数据融为一体

首先,我下载了数据集,以了解数据集中的数据类型。在这个阶段,检查原始数据是否损坏/不正确是很重要的,但也要确保标签相当准确。它还让你感觉到这项任务有多困难——如果你作为一个人很难分辨出说的是什么单词,那么对于 ML 模型来说就更难了。

在这个阶段,最好的数据集检查工具是您的文件管理器!我点击了 Nautilus 中的各种文件夹,并聆听了数据的随机样本,以了解它们的“声音”是什么样的。粗略地看一下,每个类都有文件夹,其中包含该类发言人的音频文件。我听了这些音频文件大约 15 分钟,并确认这些音频文件似乎与它们所属的标签文件夹相匹配,因此数据集的基本质量似乎相当好。

专业提示:你可以在 Nautilus 中按住 shift 键单击一系列文件,在 VLC 播放器中打开它们,VLC 播放器将按顺序播放它们,这使得你可以非常快速地收听许多不同的音频剪辑。

信不信由你,鹦鹉螺和 VLC 播放器是 ML 工具链的关键部分。

现在以编程方式加载数据集。好消息是已经有了一个加载数据并根据数据训练模型的例子。坏消息是,这是 Colab 笔记本代码,我不太喜欢笔记本代码。在我从示例中删除了所有这些内容之后,我开始研究如何以编程方式加载数据。

但是首先,一个音频文件实际上包含什么?为了理解这一点,我们必须复习一些物理和音频处理知识。声音基本上是一种振动——压力的变化——以波的形式在空间中传播。为了记录音频,计算机麦克风测量压力随时间变化的幅度,进行一些处理/压缩,并将其写入磁盘。

然而,现实中的声波是模拟信号,而计算机麦克风以数字方式记录和保存声音。这意味着如果一个人将实际的声波绘制成振幅随时间变化的图表,他将得到一个平滑连续的曲线。数字麦克风 随时间推移对该波形 进行采样——数字麦克风不是记录并保存连续的模拟波形,而是周期性地测量振幅(该时序被称为采样率),此外,振幅也不完全匹配真实振幅——它在某一分辨率下舍入到最近的振幅值,这由其 位深度 决定。记录下来后,计算机可以压缩并保存它随时间测量的量化振幅。

实际的模拟声波,用红色表示,是一条平滑连续的曲线。数字麦克风在不同的时间点对此曲线进行采样(用蓝色表示)并保存这些数据。来源

使用示例代码加载数据集时,每一行数据都包含:

  • 一种音频波形,表示为代表量化样本的一维数字阵列(如上图中的蓝色点)
  • 作为附加元数据的采样率(单位为 hz)。
  • 剪辑中说出的单词的标签(即模型将被训练来预测的类别)。
  • 扬声器 id。
  • 以区分来自同一说话者的多个记录。

然后,这些数据被分割成训练集(约 85k 行)、验证集(约 10k 行)和测试集(约 5k 行)。每个音频片段以 16kHz 采样,大多数片段的音频阵列为 16,000 长,这相当于 1 秒长的音频剪辑。然而,一些音频段短于 16,000 长,当神经网络需要固定长度的输入时,这可能是一个问题。

训练一个模特,和一些专业建议

现在我们了解了数据,是时候训练一个模型了。

Pytorch 示例代码在向模型提供数据之前做了一些简单的预处理。首先,如果有任何长度小于 1 秒的示例,它会用零填充它们,以确保它们与其他示例的长度相同。这确保了模型在固定大小的输入上训练。

def pad_sequence(batch):
    # Make all tensor in a batch the same length by padding with zeros
    batch = [item.t() for item in batch]
    batch = torch.nn.utils.rnn.pad_sequence(
        batch, batch_first=True, padding_value=0.)
    return batch.permute(0, 2, 1)

其次,它将音频重新采样到 8kHz,以减小输入的大小。

def get_transform(sample_rate):
    new_sample_rate = 8000
    transform = torchaudio.transforms.Resample(
        orig_freq=sample_rate, new_freq=new_sample_rate)
    return transform

之后,我们可以定义一个模型架构来训练这些数据。示例代码附带了一个相当简单的网络,它建立在波形的 1D 卷积之上。我要指出的是,这种模型架构与用于图像任务的架构非常相似,这也是深度学习在许多不同领域中被证明有用的部分原因。

我发现了一些在进行深度学习时相当有用的东西,这些东西没有包含在示例代码中,我一般会推荐给大多数开始深度学习项目的人。

  • 确保列车/ val /测试装置之间没有泄漏。否则,您的模型将在评估时处于不公平的优势,无法对其泛化性能做出准确的评估。当我用样本代码检查时,我发现训练集不恰当地包含了来自验证集和测试集的数据!这个 bug 可能与我在 Ubuntu 系统上运行这段代码有关,而不是像最初的例子那样在 Colab 笔记本上运行。
  • 在数据进入网络之前,检查/可视化预处理后的数据,并确认这是您所期望的。根据我的经验,在数据预处理中可能会出现很多错误,这会搞乱您的模型训练。在 Matplotlib 中绘制一些数据点/用 simpleaudio 播放一些音频是检查数据预处理结果的简单方法。
  • 建立 Tensorboard 或类似的工具来监控你的训练进度。这非常重要,因为它允许您观察您的训练+验证损失曲线,跟踪您的模型是否收敛,并确定它何时开始过拟合或欠拟合。
  • 每隔几个时期将模型权重的检查点保存到磁盘。如果你的电脑崩溃了,你可以从一个检查点恢复进度,而不是丢失一天的工作。根据 Tensorboard 日志,您还可以使用它来选择具有最佳验证损失的模型检查点。
  • 通过寻找模型训练过程的加速方法来缩短周期时间。如果您有可用的 GPU,请为您的预处理设置 GPU 加速,并对向前+向后过程建模。CUDA 安装可能会非常令人沮丧,但当您的模型训练速度提高 10 倍时,这是非常值得的。如果你有多个可用的 GPU(通常在一个强大的云机器中),尝试实现数据并行,这样你的模型会更快地烧穿迷你批处理。

目测损耗曲线很重要!

接下来呢?

经过 50 个时期的训练后,该模型在训练集上达到约 93%的 F1 分数,在测试集上达到约 85%的 F1 分数。这还不算太糟,但我相信我们可以做得更好!我想尝试做一些事情来提高模型性能:

  • 实现一个在 Mel 频谱图上使用 2D 卷积的模型(而不是在原始波形上使用当前模型的 1D 卷积),因为这往往会在其他音频任务上实现最先进的性能。
  • 做一些数据扩充,以获得数据集中更多的变化(添加噪声,改变音频剪辑的定时,等等)。)来增加最终模型的泛化能力。
  • 尝试使用具有原始(更高)采样速率的输入音频,以便模型可以对更多信息的输入进行操作。
  • 收集更多表现不佳的类的数据,以提高这些类的模型的准确性。

这通常是大多数教程博客文章的结尾。然而,让我们更进一步,实际分析失败案例,以便我们可以明智地处理最能提高模型性能的东西。

使用水族箱进行故障案例分析

首先,我想检查标记数据集和来自我的模型的推论之间的差异,以便分析它的一些失败案例。经过短暂的迂回以生成一些可视化的光谱图后,我将数据集上传到水族馆 GCS 桶中,然后使用水族馆客户端库上传我的标签、元数据和推论。

###
# add label data
###al_labeled_frame = al.LabeledFrame(frame_id=frame_id)# Add arbitrary metadata, such as the train vs test split
al_labeled_frame.add_user_metadata('speaker_id', speaker_id)al_labeled_frame.add_user_metadata(
    'utterance_number', utterance_number)al_labeled_frame.add_user_metadata(
    'waveform_shape', waveform.shape[1])al_labeled_frame.add_user_metadata('split', dataset_split)# Add a spectrogram image to the frame for visualization
al_labeled_frame.add_image(
    sensor_id='spectrogram', image_url=image_url)# Add the audio file to the frame for audio-lization
al_labeled_frame.add_audio(
    sensor_id='waveform', audio_url=audio_url)# Add the ground truth classification label to the frame
label_id = frame_id + '_gt'
al_labeled_frame.add_label_2d_classification(
    sensor_id='spectrogram',
    label_id=label_id,
    classification=utterance
)

al_dataset.add_frame(al_labeled_frame)###
# add inference data
###al_inf_frame = al.InferencesFrame(frame_id=frame_id)inf_label_id = frame_id + "_inf"al_inf_frame.add_inference_2d_classification(
    sensor_id="spectrogram",
    label_id=inf_label_id,
    classification=pred_class,
    confidence=float(confidence)
)al_inferences.add_frame(al_inf_frame)

上传完成后,我进入水族馆用户界面,可以查看我的数据集并播放一些音频片段。

目测和…打耳洞(?)一些例子

我还绘制了类别分布图,并发现与其他类别相比,有些类别在数据集中的代表性相对较低。

有些课的例题是其他课的一半!

Aquarium 还会自动显示数据集中的高损失示例,这些示例可能是标签错误或严重的模型故障。使用这个工具,并通过查看交互式模型度量视图,我发现:

  • 一些音频剪辑实际上包含多个单词而不是一个!在这种情况下,似乎说话者不小心说错了单词,然后纠正自己,模型正确地将第一个单词分类。
  • 有几个听起来很像的词是模型混淆的——上下车树和三个前进和四个。一个人可以区分这些例子中的一些,而其他情况则很难区分。
  • 在各种失败案例中,似乎有一些说话者的声音被切断的例子。在许多这样的片段中,在片段结束之前,说话者几乎没有开始说话,这使得几乎不可能区分像“four and forward”这样在开始时听起来相同的单词。

在我检查的有限数据集中,最后一种失败模式似乎发生在多个类中,但我并不清楚这个问题有多大,我也不想花几个小时来听数据集中的所有音频剪辑来判断这一点。然而,在决定下一步尝试什么之前,了解要解决的最大问题是什么是很重要的。

幸运的是,水族馆的一个独特之处在于它能够利用神经网络嵌入将相似的数据点聚集在一起。该功能允许我们找到相似数据点的聚类以及数据集中的异常值。这在识别模型故障模式时特别有用。

从模型中提取嵌入并不太难,只需在数据点上运行模型,然后从倒数第二层(在最后的类方式 FC 层之前)获取模型的激活。数据点的嵌入向量在这里只是一个浮点的 1D 向量,代表一个学习的特征向量。我在数据集上运行我的模型,提取出嵌入和推论,并将它们保存到磁盘上:

# embedding extraction
activation = {}
def get_activation(name):
    def hook(model, input, output):
        activation[name] = output.detach()
    return hook
audio_model.pool4.register_forward_hook(get_activation("pool4"))def predict(tensor):
    # Use the model to predict the label of the waveform
    tensor = tensor.to(device)
    tensor = transform(tensor)
    tensor = audio_model(tensor.unsqueeze(0))
    likely_ind = model.get_likely_index(tensor)
    out_label = data.index_to_label(likely_ind.squeeze(), labels)
    probs = torch.exp(tensor).squeeze()
    confidence = probs[likely_ind]
    embedding = activation["pool4"].flatten() return out_label, confidence.item(), embedding.cpu().tolist()

然后我把它们从磁盘上传到水族馆:

embeddings = None
with open("embeddings.pickle", "rb") as f:
    embeddings = pickle.load(f)inferences_map = {}
embeddings_map = {}
for i in range(len(inferences)):
    (frame_id, pred_class,
        confidence, dataset_split) = inferences[i]
    inferences_map[frame_id] = inferences[i]
    embeddings_map[frame_id] = embeddings[i]...al_labeled_frame.add_frame_embedding(
    embedding=embeddings_map[frame_id])
al_dataset.add_frame(al_labeled_frame)

一旦嵌入被上传和处理,我们就可以了解数据集在嵌入空间中的分布。在这里你可以随意尝试一下

然后通过模型推断和标签之间的一致/不一致来给嵌入云着色。我们清楚地看到在数据集的一个部分中有一个巨大的不一致集群,比任何其他错误模式都要大得多!

通过模型和标签之间的一致/不一致给嵌入云着色

只显示模型和标签之间的不一致。

仔细看,所有这些数据点都是音频剪辑,扬声器被切断,让人无法分辨正在说什么。

观察这些例子的波形,你会发现所有这些片段在结尾几乎都被剪掉了。

该问题影响数据集中的数千个示例,并且是最大的单一故障模式。然而,这不一定是模型的问题,而是模型预期的问题——人类没有办法听这些音频剪辑并合理地推断出正在说什么单词,它们只是以它们的方式被标记,因为语音命令的原始数据收集设置涉及指示用户说某个单词,并保存那些标记有说话者被指示说的单词的音频剪辑。

我们可能应该通过创建一个新的“未知”或“切断”类并重新训练模型来解决这个问题。这样,它就不会被那些被标记为合法类别但实际上并没有包含足够信息来准确分类的例子所迷惑。然而,这是我在 hackathon 上花完时间的地方,所以我将把它留给读者做练习。

结论

在机器学习项目中,总有一个点,你有一个做得不错但不太好的模型,并且有许多可以尝试的东西可以提高你的性能。对于这种情况,吴恩达有很好的实用建议:与其尝试随机的事情,看看什么能提高性能,不如花些时间了解哪里出了问题,然后修复那些搞砸的事情。

在这里,我们采用了一些非常现成的示例代码,在数据集上训练了一个非常简单的模型,并分析了哪里出错了。因此,我们发现最大的问题与模型本身无关,而是与数据的基本且容易修复的问题有关。通过花一点时间做误差分析,我们发现了提高模型性能的最高投资回报率的方法,这是我们可以尝试的许多方法中的一种。

我使用我们公司的产品,水族馆,为这篇文章做了大量的可视化和错误分析。如果你有兴趣亲自尝试一下水族馆,请告诉我们吧!

物体检测的深度学习:初学者友好指南

原文:https://towardsdatascience.com/deep-learning-for-object-detection-beginners-friendly-guide-ae1180b34042?source=collection_archive---------16-----------------------

人工智能工程师的研究和行业趋势

作者制作的图像

背景

当我在 2018 年实习时,我开始研究物体检测技术,因为我需要解决一个视觉检查问题。这个问题需要在来自工业相机的图像流中检测许多不同的对象。

为了应对这个挑战,我首先尝试将分类与滑动窗口结合使用!自然,这个系统非常慢,不适合生产。

在这之后,我开始研究执行对象检测的端到端深度学习模型。我偶然发现了 google research 的一篇著名论文,题目是:

现代卷积目标探测器的速度/精度权衡

这篇论文是我对使用深度学习的对象检测领域的介绍。

物体检测是一个古老的任务,深度学习给它带来了什么?

作者制作的图像

目前,目标检测是计算机视觉领域中一个比较古老的课题。在深度学习成为主流之前,许多研究人员和工程师都在研究这个问题。他们主要使用经典的图像处理技术,他们可能经常使用滑动窗口方法。那么深度学习对物体检测的附加值是什么呢?

事实上,深度学习从根本上改变了我们进行物体检测的方式。随着 YOLO 和 R-CNN 系列的引入,对象检测的性能显著提高。大多数用于图像相关任务的神经网络使用卷积层。这些神经网络被称为 CNN(卷积神经网络)。这些 CNN 实际上自然而有效地执行了一种滑动窗口方法。这是神经网络学习图像表现方式的一部分。

目标检测的研究现状

作者制作的图像

在我写这篇文章的时候,谈论最多的对象检测模型是 YOLOR(你只学习一种表示)。设计该模型架构的研究人员正在寻找整合“隐性知识”的方法。这种隐性知识应该代表神经网络中的潜意识。作者希望建立一个架构,模仿我们人类在现实生活中如何解决对象检测任务。这种架构可能是未来工作的一个种子,该工作集成了隐式知识的概念,不仅用于对象检测,还用于各种计算机视觉任务。

还有另一种建筑可以成为未来许多作品的种子,那就是 DETR 建筑。DETR 代表检测变压器。

变压器是一种新型的神经层,它们正在与卷积层竞争大量的计算机视觉任务。

变形金刚已经在 NLP(自然语言处理)任务中显示出巨大的成果,并且他们正在稳步进入计算机视觉任务。

工业中物体检测的现状

作者制作的图像

在过去的几年里,我一直是一名机器学习工程师,专注于计算机视觉应用。通过在这个领域工作,也通过对需要机器学习和计算机视觉知识的职位进行几次面试,我实际上注意到了这个行业中物体检测的一些趋势。

如果你在这个行业工作,那么你肯定知道一项任务的最重要的指标可能与研究中使用的指标非常不同,对于同样的任务!

在对象检测任务的情况下,同样的事情适用。据我所知,在工业环境中实现目标检测模型时,有两个指标是最重要的:速度和鲁棒性。并不总是两者都有,但两者中至少有一个总是有的。

基于这些原因,【v3,v4,V5】更快——RCNN在业界得到了广泛的应用。通常,当速度是第一优先考虑的因素时,使用 YOLO,当鲁棒性是第一要求时,使用更快的 RCNN。

我亲自和 YOLOv3,SSDfast 合作过——RCNN

虽然很多在这个行业工作的人直接去了 YOLO——我猜是因为它的好名声——但我不认为这是一个万能的解决方案。

谈到推理速度,YOLO 和 SSD 都显示出了巨大的潜力。但是在某些情况下,他们仍然可能失败,特别是在工业领域。

我记得我曾尝试使用带有 InceptionV2 后端的 SSD 来执行一项高难度的物体检测任务。这是一项视觉检查任务,我们需要检测大型发动机(飞机或直升机,我不记得了)内部的机械部件。无论我如何调整我的神经网络的参数,我都不能让损失减少,它只是不停地振荡!

我以前使用过同样的架构,用同样的主干,来执行一些其他的对象检测任务,效果非常好!所以当我从事这项任务时,这无疑是更具挑战性的,SSD 失败了。因为发动机看起来体积庞大,因为有许多零件连接在一起,而且许多零件看起来非常相似。即使是人眼,也很难发现我们想要检测的特定机械部件!这应该告诉你注释我们的数据集有多困难!

此时,我记得当时认为这只是深度学习的极限。但在完全放弃之前,我决定尝试一种不同的架构,并试图避免 YOLO 和 SSD 等一级检波器。

我选择了 fast-RCNN,因为它是一个两阶段的对象检测模型。你瞧,这个模型工作得非常好!损失函数的收敛比保龄球还要平滑!

所以下次你在做物体检测任务的时候,在你下定决心之前,尝试一些不同的架构!

需要云计算来提高对象检测任务的性能

作者制作的图像

在训练深度学习模型的时候,尤其是大型模型的时候,你需要一些非常好的设备。说到训练,GPU 可能是你的深度学习机器最重要的方面。许多公司购买这些设备,但也有许多公司选择云计算服务。

谷歌云平台(GCP)、亚马逊网络服务(AWS)和微软 Azure 是一些广泛使用的云计算服务。

对于物体检测和大型模型,如 fast-RCNN,这些云计算解决方案可能正是您正在寻找的训练模型。但是应该用哪一个呢?

答案真的取决于你公司的选择。对于许多公司来说,他们已经有了云基础设施,在上述云提供商之一,所以他们可能只是想继续使用同一提供商来保持标准化。但是,如果你刚刚开始,并试图选择其中一个作为你的目标探测任务,那么请继续阅读!

有多种方法可以训练你的物体检测模型,稍后我会详细介绍一些开源工具。但是如果你正在使用 Tensorflow (1 或 2),那么你可能正在使用 Tensorflow 对象检测 API

如果你是,那么当谈到在云上训练对象检测模型时,Google Cloud 应该是你的选择。你可能会问为什么?

嗯,由于 Tensorflow 是谷歌的产品,对象检测 API 也属于谷歌,谷歌云团队已经使在 GCP 上训练你选择的模型(从对象检测 API)变得极其容易。

具体来说,google 有 2 种产品可以轻松集成到您的管道中,用于训练对象检测模型。这两款产品分别是:AI 平台和 Vertex AI。

通过在你的机器上安装谷歌云帐户和谷歌云 SDK,训练来自 模型动物园 的任何物体检测模型,变得简单明了。

如果你想训练一个不属于模型动物园的模型(比如 YOLO),那么按照我在另一篇文章https://pub.towardsai.net/beginners-helpful-guide-to-training-deep-learning-models-on-the-cloud-3202f29afd1b中描述的一系列步骤,在谷歌云上也是可行的。

用于执行对象检测任务的开源深度学习工具

作者制作的图像

为了使用深度学习来执行对象检测,主要有三种广泛使用的工具:

  1. Tensorflow 对象检测 API。
  2. 探测器 2。
  3. mm 检测。

如果你是 Tensorflow 开发者,那么 Tensorflow 对象检测 API 最适合你。如果你是 PyTorch 开发者,那么 Detectron2MMDetection 更适合你。

如果你更关心选择的多样性,那么 MMDetection 是最好的选择,因为它有大量的对象检测深度学习模型。

这并不意味着仅仅因为一个架构不是这些工具的一部分,你就不能在其他地方找到它。例如,Tensorflow 对象检测 API 中没有 YOLO 模型,但您可以使用 Tensorflow 从社区中轻松找到一个开源实现。

结论

总结一下,下面是这篇文章的要点:

  1. 物体检测是计算机视觉中一项相对古老的任务,但深度学习已经将物体检测任务的性能大幅提升。
  2. 当涉及到用于对象检测的深度学习时,研究中推的指标可能不一定与行业中推的指标相同。
  3. 云计算可以成为深度学习模型训练性能的主要助推器,明智地选择云提供商。
  4. 使用深度学习进行物体检测的开源工具有几个,主要的三个是:Tensorflow 物体检测 API、Detectron2 和 MMDetection。

作者制作的图像

我是一名机器学习工程师,致力于解决具有挑战性的计算机视觉问题。我想帮助你学习应用于计算机视觉问题的机器学习。以下是方法。

  1. 通过帮助您了解该领域的最新动态。我几乎每天都在【LinkedIn】Twitter上分享小型博客帖子。那就跟我去吧!
  2. 每周给你一份我的 时事通讯 上那些小帖子的摘要。所以订阅吧!
  3. 通过在 Medium 上写关于机器学习不同主题的文章。所以跟我来吧!
  4. 给你一份免费的机器学习工作清单,帮助你检查你需要学习的所有要点,如果你计划在 ML,特别是在计算机视觉方面的职业生涯。你可以在这里获得核对表

5.最后但同样重要的是,通过与你分享我的 免费入门 Tensorflow 课程 ,它有超过 4 小时的视频内容,你可以在那里问我任何问题。

此外,如果您有任何问题或者您只是想聊聊 ML,请随时在 LinkedIn 或 Twitter 上联系我!

用于弹丸弹道建模的深度学习

原文:https://towardsdatascience.com/deep-learning-for-projectile-trajectory-modeling-fb6380e06b8f?source=collection_archive---------27-----------------------

思想和理论

对我们最近关于为基于深度学习的轨迹建模生成模拟数据的论文的评论

FCE 神经网络示意图(图片由作者提供)

本文作者为 Ayaan Haque 和 Sajiv Shah

在这篇文章中,我们将回顾我们最近的工作,题为“通过基于人工智能的机器人弹丸发射建模的算法力系数估计的模拟数据生成”,作者是萨吉夫·沙阿、阿亚安·哈克和刘飞。在本文中,我们提出了 FCE 神经网络,一种新的方法来模拟机器人发射非刚性物体使用神经网络训练的补充模拟数据,从算法力系数估计产生。这项工作已经被 2021 年的 ACIRS 接受。论文在 ArXiv 有,项目网址在这里。我们将首先介绍我们的动机和问题,然后回顾方法,最后提出一些简短的结果和最后的想法。

背景

动机

随着机器人开始变得更加先进,它们需要模仿类似人类的行为,因此必须获得类似人类的技能。其中很大一部分涉及到与对象的交互,包括操纵和启动。不幸的是,现实世界的对象建模是困难的。这是因为有一些外部因素和动力学控制着一个物体的运动,而这些因素和动力学在基本物理模型中没有得到解释。物体具有随时间增加的应力松弛量,以及在诸如温度或湿度的多种非恒定条件下变化的硬度。这产生了大量的不确定性,因为某个模型的每个对象将具有不同的条件。

对于物体发射来说,空气动力和机械装置的不精确性结合在一起会产生较差的动力学特性。为了精确地确定升力和阻力系数,必须使用昂贵的工具和传感器进行实验,如风洞。执行这些测试需要原型或小比例模型,这意味着物体的大致形状和材料必须预先确定,这使得设计与未知或形状变化的物体交互的机制变得困难。如果没有来自精确传感器和控制器的高速、准确的反馈,机器人就不能很好地模仿模型。在发射系统中,由于不均匀的质量分布,来自机构的摩擦和来自致动的振动,加上不理想的控制回路,导致目标参数与实际参数之间的差异。非包容性建模和不完善的机械系统的结合产生了实验和理论结果的巨大差异。

当前解决方案

为了解决这些问题,来自人工智能各个领域的方法已经被应用于机器人领域。在强化学习(RL)中,机器人通过反复试验来学习新的行为,这消除了对人类操作员的需要。然而,众所周知,RL 在架构上既危险又昂贵,这使得它在通用机器人领域相当不受欢迎。

其他数据驱动的深度学习方法已经被研究用于各种基于物理的建模任务,但是依赖于大型数据池。对于机器人应用程序,收集和生成大型数据集将使预测模型过时,因为以编程方式引用收集的数据将产生比基于该数据生成预测更准确的结果。

实验数据经常与模拟/生成的数据配对,为深度学习模型提供更多数据。然而,强生成模型需要访问大型数据集,以便准确地学习和再现数据的表示。我们建议使用一个简单的基于物理的模拟器,该模拟器考虑了射弹轨迹的已知动态,以生成用于深度学习的数据。为此,我们开发一组方程并设计模拟器,使用迭代算法估计系数,生成数据,然后调整神经网络以创建预测。

方法

FCE 神经网络示意图(图片由作者提供)

我们的方法由三部分组成。模拟器,包括系数估计器和数据生成器,以及神经网络。

基于物理的模拟器

我们研究中使用的目标图(图片由作者改编自此处

虽然我们的方法可以应用于各种对象,但我们的工作涉及一个 7 英寸的泡沫球,它是从双飞轮机器人射手发射的。第一届机器人挑战赛给出了我们的目标,如上图所示,我们的目标是从不同的发射区将尽可能多的直径为 7 英寸的泡沫球射入 3 点目标,这些发射区距离目标底部 3 至 30 英尺。靶子的中心大约有 8 英尺高。

已知的作用在球上的力有重力、阻力和升力,其中一些力根据球在轨迹中的位置以不同的大小和方向作用在球上。本文概述了物理方程和模拟器设计:

我们假设访问测量的发射器配置 X_r 和发射结果 Y_r,以及带有发射器配置 X_s 和标签 Y_s 的模拟数据。X_r 和 Y_r 一起用于形成实验数据集 D _ r。X _ s 和 Y_s 一起用于形成模拟数据集 D_s。

我们的目标是训练我们的神经网络来预测基于某一组发射配置 X_r 的结果,其中每个配置都有 3 个特征:到目标的距离(米),范围为 0-1 的电机速度比,以及发射器与水平面的角度(度)。更常规地,X 是神经网络的输入,在这种情况下是发射器配置,Y 是输入的标签,在这种情况下,它是发射的结果。已知得分目标在距离(d)处,并且得分区域的中心在高度(h_target)处,我们分配结果如下。

发布结果的分配(图片由作者提供)

估算力系数

我们的目标是使用这个轨迹模拟器,通过比较从配置 X_r 生成的轨迹的结果与其结果 Y_r 来估计系数 C_l 和 C_d。为了估计最适合数据集的系数,我们使用多个系数对来模拟 X_r 的每个配置的轨迹。我们评估了 1000 个组合,每个系数在(0.000,5.000)的范围内,步长为 0.005。

对于给定的初始发射角、发射速度和系数对,模拟器能够生成物体轨迹并确定其是否穿过目标。我们可以简单地迭代多个系数对,以确定哪一个对 D_r 的轨迹建模最好。因为 D_r 的结果数据集(Y_r)表示物体可能经过的点的范围,所以大量系数对将从 X_r 模拟单个配置的轨迹。

使用算法模拟器生成轨迹的例子。垂直蓝线代表 2 分区域的得分范围,垂直红线代表 3 分区域的得分范围。黑星表示物体发射时机器人的位置/距离。(图片由作者提供)

我们使用模拟器计算目标与计分目标中心的距离,并将该值标记为偏差。为了选择一个系数对用于数据生成,我们评估了 3 点和 2 点区域的精度以及平均值和中值偏差。我们的算法力系数估计方法可推广到与空气动力相互作用的其他物体。上图显示了不同空气动力系数对物体轨迹的影响,对于给定的配置子集,结果因分配的系数对而异。

神经网络训练

神经网络示意图(图片由作者提供)

一旦我们使用我们的力系数估计器生成额外的数据,我们就将其与我们的实验数据集 Dr 耦合,以训练神经网络来预测射弹是否会击中指定的目标。我们在论文中使用的神经网络如上所示,它是一个有目的的三层骨架网络。对于每个发射器配置,输入层有 3 个节点,隐藏层有 8 个节点,输出层有 2 个节点,每个节点用于 2 维向量,对 2 点或 3 点目标是否被击中进行二元预测。这个网络是一个简单的前馈网络,可以用一个更先进的网络来代替。神经网络的使用允许考虑我们的机制和模型中的不准确性。这些不准确性包括我们的射弹的非刚性属性,不能准确地模拟能量转移,等等。神经网络专门用于解释物理模型的不准确性。隐藏层允许网络模拟非线性系统并考虑非线性。收集的数据来自我们部署人工智能系统的领域。如果数据是从目标域收集的,它将解释物理模型不能解释的差异。

我们的网络根据如下所示的加权损失函数进行训练:

损失函数项(图片由作者提供)

其中,X_r 和 Y_r 是实验特性集和标签,X_s 和 Y_s 是模拟特性集和标签集,F_θ是模型,L_R 是真实损失项,L_S 是模拟损失项,λ是模拟损失的拉格朗日乘数。L_R 和 L_S 都使用传统的交叉熵损失,计算方法相同。λ项在使用实验和模拟数据的方法中很重要。由于 D_s 远大于 D_r,因此必须适当调整损失函数,以优化模型,使其在目标域中有效运行。

结果

我们射手的计算机辅助设计模型(图片由作者提供)

我们使用一个双飞轮发射机构(CAD 如上所示)来测试我们的方法的准确性。

D_r 正好有 100 种配置,平均分布的数据代表我们的 3 种可能的结果。由于机制缺陷,只有 2 个数据实例必须被手动拒绝。对于训练和测试分割,我们使用 20%的数据集作为外部测试集来评估模型性能。该测试集不包含模拟数据。如上所述,模拟数据集具有 900 个均匀平衡的样本。作为额外的评估指标,我们对生成的 X_s 中的 50 个进行了采样,并使用我们机器人上的配置来确定我们场地上的实验结果。我们用它来形成一个额外的测试集。获取模拟输入 Xs 的实验标签不仅允许我们基于估计的系数评估来自模拟器的预测,还允许我们评估神经网络的预测。

力系数估算

显示力系数估计器性能的表格(图片由作者提供)

在上表中,我们显示了模拟器在训练和测试集上的性能,并证明它能够非常准确地预测力系数以匹配训练集,这对神经网络来说是最佳的,但在测试集上表现不佳,这是使用神经网络的动机。如上所述,模拟器旨在复制训练集的数据分布,以便生成与训练集无法区分的新数据,这将最大程度地帮助神经网络性能。因此,因为模拟器在精确生成和模拟训练数据方面非常有效,所以它可以是训练神经网络的适当补充。

可视化轨迹模型(图片由作者提供)

上图显示了实验测量的轨迹和模拟器使用估计的力系数生成的轨迹的比较(左)。我们还显示了与测试集上的实验轨迹相比,使用估计的力系数生成的轨迹的不准确性(右)。这进一步证明了生成器在匹配训练集分布方面是准确的,但是在对测试集建模方面是不准确的。

神经网络性能

神经网络性能(图片由作者提供)

上表显示了神经网络在预测发射器配置是否会产生目标得分方面的性能。结果表明,对于任何数量的模拟数据,网络都比在没有模拟数据的情况下训练的网络具有更强的性能。然而,在 900 个样本之后,性能开始下降,这表明对模拟数据的过度拟合降低了实验测试集上的性能。结果证实了使用模拟数据的重要性,并显示了性能的统计显著提高(p 值≤ 0.05)。此外,神经网络的精度比仅力系数估计高得多。

最终想法

在本文中,我们提出了 FCE 神经网络,一种使用力系数估计和深度神经网络对机器人系统发射的非刚性物体的轨迹进行建模的方法。我们介绍了一个使用实验发射器数据和物理模拟器估算力系数的算法过程。重要的是,我们使用这种算法模拟器来生成额外的数据,以训练数据匮乏的神经网络。我们利用在模拟和实验数据上同时训练的深度神经网络来基于输入配置预测和建模发射器的结果,允许非刚性物体发射的真实世界建模,这可以说明物体飞行的外部因素。

我们设想将这样一个系统部署在具有自动可变发射器的遥控移动机器人上,这样,现场测量的发射器配置就可以输入到模型中,以预测发射的结果。这些配置可以被发送到操作员仪表板,在那里,部署在网络上的网络可以有效地返回关于是否发射发射器的预测。与简单地返回二进制结果相反,它可以进一步用于提供关于调整什么配置以进行拍摄的建议。我们未来的工作将研究新的神经网络结构以及反向工程神经网络,以获得力系数。

如何利用深度学习预测时间序列数据

原文:https://towardsdatascience.com/deep-learning-for-time-series-data-ed410da30798?source=collection_archive---------4-----------------------

亚马逊开发的自回归递归神经网络

时间序列(TS)预测是出了名的挑剔。也就是说,直到现在。

图 1:基于这个教程的 DeepAR 训练输出。图片作者。

2019 年,亚马逊的研究团队开发了一种名为 DeepAR 的深度学习方法,相对于最先进的 ts 预测模型,该方法的准确率提高了约 15%。它是健壮的开箱即用的,可以从许多不同的时间序列中学习,所以如果你有许多不稳定的数据,DeepAR 可能是一个有效的解决方案。

从实现的角度来看,DeepAR 在计算上比其他 TS 方法更复杂。它还需要比传统的 TS 预测方法如 ARIMA 或脸书的先知更多的数据。

也就是说,如果你有大量复杂的数据,并且需要非常准确的预测,DeepAR 无疑是最可靠的解决方案。

技术 TLDR

简而言之,DeepAR 是一个 LSTM RNN,带有一些附加功能来提高复杂数据的准确性。相对于传统的 TS 预测方法,DeepAR 有 4 个主要优势…

  1. DeepAR 在学习季节性依赖关系方面很有效,只需要很少的调整。这种开箱即用的性能使该模型成为 TS 预测的良好起点。
  2. DeepAR 可以使用几乎没有训练历史的协变量。通过利用相似的观察值和加权重采样技术,该模型可以有效地确定不频繁协变量的行为。
  3. DeepAR 做概率预测。这些概率以蒙特卡洛样本的形式,可用于开发分位数预测。
  4. DeepAR 支持广泛的似然函数。如果您的因变量呈现非正态或非连续分布,您可以指定相关的似然函数。

该模型受到了很多关注,目前在 PyTorch 中得到支持。教程和代码链接在评论里。

但是,到底是怎么回事呢?

好吧,让我们慢一点,讨论一下亚马逊的 DeepAR 模型实际上是如何工作的…

传统时间序列预测

让我们从头开始。

如上所述,时间序列预测是出了名的困难,主要有两个原因。首先,大多数时间序列模型需要大量的主题知识。如果你用传统的 TS 模型模拟股票价格,重要的是要知道什么协变量影响价格,这些协变量的影响是否有延迟,价格是否表现出季节性趋势,等等。

工程师通常缺乏创建有效功能所需的主题知识。

第二个原因是 TS 建模是一个相当小众的技能组合。给定时间步长的先前输出是下一个时间步长的输入,因此我们不能使用通常的建模技术或评估标准。

因此,工程师不仅需要对数据有深入的了解,还必须对 TS 建模技术有深刻的理解。

传统的递归神经网络

机器学习可以为传统的 TS 预测提供替代方案,这些方案通常更准确且更容易构建。支持顺序数据的最简单的 ML 算法是递归神经网络。

rnn 本质上是一堆堆叠在一起的神经网络。如图 2 所示,h 1 处模型的输出馈入下一个 h2 处的模型。

图 2:递归神经网络的图示。图片作者。

这里,蓝色的 x 是预测变量,黄色的 h 是隐藏层,绿色的 y 是预测值。这个模型架构自动处理我们上面讨论的许多挑战。

但是即使是 rnn 在某些领域也有不足。首先,他们对于什么应该被传递到下一个隐藏层的假设过于简单。RNN 的更高级的组件,如长短期记忆(LSTM)和门循环单元(GRU)层提供了过滤器,用于过滤沿链传递的信息。它们通常比普通的 rnn 提供更好的预测,但遗憾的是,它们也有不足之处。

亚马逊的 DeepAR 模型是 LSTM 的最新版本,解决了它的两个主要缺点:

  1. 由于均匀采样分布,异常值拟合不佳。DeepAR 的优势之一是它从许多时间序列中聚合信息,从而为单个单位(如用户)开发预测。如果所有单位都有相同的机会被采样,异常值将被平滑,我们的预测值将变得不那么极端(可能也不那么准确)。
  2. RNN 不能很好地处理时间缩放。随着时间的推移,时间序列数据通常会表现出整体趋势——想想你在 COVID 期间最喜欢(或最不喜欢)的股票。这些时间趋势使得拟合我们的模型变得更加困难,因为在拟合时必须移除这种趋势,然后将其添加回我们的模型输出。那是许多不必要的工作。

DeepAR 解决了这两个问题。

DeepAR 是如何工作的?

基于 RNN 架构,DeepAR 使用 LSTM 单元来拟合我们的预测变量和我们感兴趣的变量。以下是如何…

序列对序列编码器-解码器

首先,为了使我们的数据更有用,我们利用一个序列来排序编码器-解码器。该方法采用一组 n 个输入,用神经网络对这些输入进行编码,然后输出 m 个解码值。

有趣的事实——它们是所有语言翻译算法的支柱,比如谷歌翻译。因此,使用下面的图 3,让我们从将英语翻译成西班牙语的角度来思考这个方法。

图 3:序列对序列编码器-解码器的图形表示。图片作者。

这里,蓝色的每个 x_n 值是我们模型的输入,即英语单词。它们被依次送入 RNN,后者对它们的信息进行编码,并将其作为编码器矢量(黄色)输出。编码器向量的信息被表示为隐藏状态的权重向量。从那里,我们的编码器向量被送入我们的解码器,这是一个 RNN。最后的输出是西班牙语单词,用绿色标记为 y_n

很酷,对吧?

根据我们的数据进行扩展

其次,我们解决了使基本 LSTMs 不如 DeepAR 的两个问题:均匀采样和时间缩放。

这两者都使用比例因子来处理。比例因子是用户指定的超参数,但推荐值只是给定时间序列的平均值:

图 DeepAR 中使用的默认比例因子的公式——单个时间序列的平均值。图片作者。

为了处理极值的不均匀采样,我们使采样概率与 v_i 成比例。因此,如果给定时间序列的平均值较高,则更有可能被采样,反之亦然。

为了处理时间缩放,我们将每个 LSTM 单元的输入除以 v_i 。通过在将我们的值输入到每个单元格之前缩小它们,我们的模型可以专注于我们的预测器和结果变量之间的关系,而不是拟合时间趋势。在单元适合我们的数据后,我们将其输出乘以 v_i 以将我们的数据返回到其原始比例。

没那么酷,但还是很酷。只剩最后一节了…

使用似然函数拟合

第三,也是最后一点,处理完所有错综复杂的数据后,我们通过最大化因变量的条件概率来拟合给定的预测值和模型参数(图 5)。这种估计量称为最大似然估计量(MLE)。

图 5:简化的 DeepAR 似然函数。图片作者。

上面的简化表达式是我们希望最大化的——我们希望找到最大化因变量( z )概率的模型参数( θ )。我们还以协变量( x_t )和前一个节点的输出( z_t-1 )为条件。

因此,给定我们的协变量和前一时间步的预测值,我们可以找到在给定参数的情况下最大化观察可能性的参数值。

现在,可能性还包括数据转换步骤,但是从理解和实现的角度来看,它并不是非常重要。如果你好奇,可以看看评论中链接的论文。

现在你知道了——简而言之就是 DeepAR。在你走之前,这里有一些关于实现这个方法的实用技巧…

实施说明

  • 作者建议将协变量标准化,即减去平均值并除以标准差。
  • 缺失数据对 DeepAR 来说可能是个大问题。作者建议通过从条件预测分布中抽样来输入缺失数据。
  • 对于论文中引用的例子,作者创建了对应于时间信息的协变量。一些例子是年龄(以天为单位)和星期几
  • 使用网格搜索优化参数是调整模型的有效方法。然而,学习速率和编码器/解码器长度是特定于主题的,应该手动调整。
  • 为了确保模型不是基于我们在 TS 中因变量的指数拟合的,作者建议在我们的开始阶段之前根据“空”数据训练模型。就用一堆零作为我们的因变量。

感谢阅读!我将再写 41 篇文章,将“学术”研究引入 DS 行业。查看我关于构建 DeepAR 模型的链接/教程的评论。

X 射线视觉的深度学习

原文:https://towardsdatascience.com/deep-learning-for-x-ray-vision-bd11564760fd?source=collection_archive---------20-----------------------

SCSE·NTU 大学最后一年项目(FYP)

X 射线 CT 图像中的气孔检测(图像来自 ARTC

摘要

最近的讨论表明,添加剂材料中裂纹的位置始于孔隙。孔隙上产生的应力引发裂纹向下一个最近的孔隙扩展,最终导致破坏点。在 TinkerCAD 中创建了一个由逼真的孔状结构组成的 3D 模型,并上传到 aRTist,在那里进行模拟 CT 扫描以生成模拟 CT 图像。然后使用 VGStudio MAX 和 ImageJ 软件对图像进行预处理。使用可训练的 weka 分割插件,每个图像被半自动标记。这些图像然后被手动校正并转换成用于训练的掩模图像。然后研究了不同的分割模型,如 U-net 和 DeepLabV3,以执行分割任务。使用检测得分的概率来比较结果,我们得出结论:孔隙的检测严重依赖于真实数据,而不是模拟数据。

项目目标

该研究的目的是评估使用模拟 X 射线 CT 图像作为真实图像的可能补充的可行性,用于语义分割中的训练数据。

使用的软件

使用的软件

TinkerCAD

TinkerCAD 是由欧特克公司开发的免费在线 3D 建模软件工具。它的特点是使用简单的形状和空心物体的创建,从而使其适合于创建孔状物体的模拟目的。

网格混合器

Meshmixer 是一款免费的 3D 计算机辅助设计(CAD)建模软件工具。它用于将复杂的孔隙 STL 文件组合在一起,作为单个对象导出到 aRTist 软件进行 ct 扫描模拟。

分析 RT 检测模拟工具(aRTist)

aRTist 是对射线检测(辐射源、辐射的衰减、x 光胶片和数字探测器、与 CAD 接口的交互式虚拟场景)进行定量描述的计算机模拟程序。

VGStudio MAX

Volume Graphics Studio MAX 是一款软件程序,旨在为用户提供处理和可视化体积数据的强大方法。它用于在使用 aRTist 执行模拟 ct 扫描后重建 3D 图像。

ImageJ(斐济)

ImageJ 是用 Java 编写的图像处理程序。它具有广泛的功能。这包括缩放、裁剪、降噪和以多种格式保存图像数据,例如。png,。jpeg,。Weka 可训练分割插件也用于这个项目中,以执行图像的半自动标记。

Google Colab Pro

为了训练模型,使用了谷歌 Colab Pro 特斯拉 P100-PC1E-16GB。Google Colab Pro Edition 还配备了速度更快的英特尔至强处理器(2.30GHz),而免费版的英特尔至强处理器(2.20GHz)

权重和偏差

Weights and bias是一款开发者工具,用于跟踪、比较和可视化机器学习实验。本项目中进行的所有实验都记录了重量和偏差。

概观

为产生结果而采取的步骤

在这个项目中,第一步是从头开始创建一个模拟数据集,并对数据进行预处理。然后使用来自斐济的可训练 weka 分割插件 ImageJ 对数据进行标记。然后,在建模阶段测试了几个模型,这需要在数据标记过程中改进像素误差,并在实施过程中调试度量和误差。然后记录并评估结果,其中执行额外的预处理步骤和超参数调整以改善最终结果。

数据集创建

在这项工作中,重点是创建与金属(特别是铝)3D 打印过程中生成的现有孔隙高度相似的孔隙。在 TinkerCAD 中创建 CAD 模型后,该模型被导出到 aRTist 中,在其中模拟 3D 对象以创建 X 射线 ct 图像。

模拟 CT 图像的输出(图像来自 ARTC

模拟图像和真实图像的放大对比(图像来自 ARTC )

图像处理

图像处理方法

执行了几种图像处理方法,以确保在训练模型之前图像是准备好的。使用 VGStudio MAX 和 Fiji-Image 软件对这些图像进行预处理。

数据标记

图片来自 Weka 可训练分割插件

可训练的 Weka Segmentation 是一个斐济插件,它将一组机器学习算法与一组选定的图像特征相结合,以产生基于像素的分割。上图显示了使用插件创建一个带标签的样本,该样本与其他几个带标签的样本一起用来注释数据集。这三个类是孔隙、对象和背景。

系统模型化

U-Net 架构[1]

U-net 是为生物医学图像的分割而设计的,它在 CT 图像的制作中得到了应用。在这个项目中,我们使用 Keras 定义了一个 U-net 模型,Keras 是一个开源软件库,充当 Tensorflow 库的高级 API。除了 U-Net 模型之外,还在模型的末尾添加了批量标准化和漏失层。

使用的指标

TPR =召回率=灵敏度=检测概率

Jaccard 距离损失指标

项目中使用了 2 个指标。第一个指标是检测概率,或者通常称为真阳性率、召回率或灵敏度。由于背景像素覆盖了像素总数的大部分,使得难以评估模型的性能,所以没有使用交集/并集和 Dice 分数。

第二个指标是 Jaccard 距离损耗,它改编自was name。这是一个用于评估不平衡数据集的有用的度量,并且已经进行了移动,以使其收敛到 0 并进行平滑,从而避免爆发梯度。

数据集分割

模拟数据和真实数据的比率

数据集分为 6 个不同的比率,混合了模拟数据和真实数据。所有数据集都使用一部分真实数据作为测试数据。

超参数调谐

为了提高模型的性能,进行了超参数调整。为了获得最佳参数,总共进行了 4 次扫描。每次扫描由一系列超参数组成,这些超参数将使用权重和偏差按顺序运行。

在扫描之前定义了几个规则:

  1. 使用合理的参数值
  2. 采用“由粗到细”的方法消除非最佳超参数
  3. 假设运行中的超参数相互独立
  4. 使用数据集 1 和数据集 6 选择超参数

优化器扫描

学习率扫描 1

学习率扫描 2

批量扫描

结果评估

数据集 1 至 6 的测试集结果

该模型被训练以在总共 20 个时期内收敛。从上图中,我们可以观察到,当只使用模拟数据时(D1 比较),性能明显更差。当使用更多真实数据时,数据集 2 至 6 的检测概率表现得越来越好。

度量结果

(原始图像来自|()带注释的遮罩| ( )预测遮罩

基于所获得的结果,我们可以推断孔隙的检测严重依赖于现有数据,而不是模拟数据,因为只需要真实数据的 20% (304 个图像)来将数据集 2 中的检测概率驱动到 0.9583。这也证实了来自训练集的大多数图像与测试集高度相似,这解释了其高检测概率。

结论

在这个项目中,我们探索了使用 U-Net 神经网络结构来检测 ct 图像中的孔隙。在 TinkerCAD 中创建了一个由真实毛孔组成的 3D 模型,并上传到 aRTist,在那里进行模拟 CT 扫描以生成 CT 图像。然后,在 VGStudio MAX 和 ImageJ 中对图像进行预处理,随后,使用可训练的 weka 分割插件,对每个图像进行半自动标记。然后手动校正这些图像,并将其转换成用于训练的掩模图像。从真实数据和模拟数据的各种比率获得的结果表明,孔隙的检测严重依赖于真实数据,而不是模拟数据。

[1]O. Ronneberger,P. Fischer 和 T. Brox,“U-Net:卷积网络用于生物医学图像分割”,2015 年。

链接

NTU 博士的完整报告

数据科学中的深度学习

原文:https://towardsdatascience.com/deep-learning-in-data-science-f34b4b124580?source=collection_archive---------10-----------------------

它是什么,为什么使用它?

Solen Feyissa 在 Unsplash 上拍摄的照片

在我的上一篇文章中,我提到了想要重新研究机器学习。最初,我第一次尝试是在一个 24 小时的黑客马拉松上。我的团队使用监督机器学习模型。起初,尝试另一种监督模式听起来是个好主意,但有了一个项目,灵感就来了。如果你没有阅读我的上一篇文章,随着十月的临近,该项目将使用机器学习来生成简短的恐怖故事。但这意味着分类或预测不会发生。代代做。所以,我们需要使用深度学习模型,而不是监督/非监督/强化学习模型。

在我的《数据科学常用词》一文中,我们简要描述了什么是深度学习。我们也提到了神经网络的使用,但仅仅简单的定义并不总是能清楚地描述它们是什么以及它们是如何工作的。因此,在本文中,我们将更多地了解什么是深度学习,它是如何工作的,什么是神经网络,以及深度学习的目标/结果。

什么是深度学习?

深度学习是一种更接近人脑决策方式的机器学习训练模型。我说的大脑是指创建的算法更深入。不是只有一个层,而是多个复杂的层被用于处理。神经网络是一个允许层间通信的系统。这个过程更接近于无监督学习,因为它也是自动化的。

因为这种类型的学习充当了一个强大的大脑,所以需要大量的数据进行训练。需要如此多的数据,以至于在大数据和云计算出现之前,数据量和处理能力都不容易获得。但是仅仅因为需要大量的数据,并不意味着数据必须是结构化的。深度学习可以处理无标签和非结构化数据。这种学习方法还会创建更复杂的统计模型。随着每一个新数据的出现,模型变得更加复杂,但也变得更加准确。

深度学习模型

深度学习的一种方法是迁移学习。与其他训练模型相比,它需要更少的计算时间。它也不需要那么多的数据。迁移学习从一个预先存在的网络开始。这个网络还必须有一个接口。然后,该网络被输入新的数据,这些数据带有它尚未面对的场景,以获得反应并从数据中学习。随着时间的推移,可以进行调整以适应新数据和旧数据。然后,新的任务可以根据网络所学到的东西来执行,甚至可以利用其新发现的适应性获得更具体的分类能力。本质上,它采用现有的接口,为其提供新的场景,这些新的条件使网络在接受数据方面更加广泛,但在分类方面更加精确和具体。

深度学习的另一种方法是辍学法。特别是在监督学习中,可以创建类别来容纳不需要制作的数据。简单地说,过度匹配是指类别过于具体,以至于钻得太深。为了对抗过拟合,dropout 方法选择神经网络中的随机节点/单元来“退出”。通过去除那些随机节点,它努力消除钻得太深的分类。这发生在训练期间。

我们接下来要看的深度学习方法是从零开始训练。这种方法听起来一模一样,因为用户从零开始创建和训练网络。网络体系结构是根据需要构建的,需要一个带标签的数据集来配置该网络。与其他方法相比,这种方法有点像保姆,如果数据没有被标记,那么它就不能包含在训练集中,至少在训练的早期阶段是这样。为了捕捉所有场景或至少大部分场景,需要大量数据进行测试。它也比许多其他方法需要更长的时间,所以它不是一种常见的方法。

我们今天要讨论的最后一种深度学习方法是学习率衰减法,也称为自适应学习率法。一旦测量了误差率,学习率决定了发生多少变化。通过监控学习率,您可以调整模型以提高性能并减少训练时间。随着时间的推移,目标是降低学习率,以便在通过模型发送数据时不需要做太多的更改。如果速率太高,那么网络中的变化太多,并且在训练期间可能不稳定。但是,如果速率太小,那么性能可能会受到影响,甚至数据可能会在训练期间停滞不前。通过学习来平衡学习速率,可以提高准确性,并且可以显著提高训练性能。

什么是神经网络?

神经网络之所以重要,是因为通信源是节点,节点包含算法层,可以评估原始数据,并找到隐藏的模式。像无监督学习一样,深度学习会随着时间的推移而改变并适应数据,这使得它可以随着时间的推移而改进。神经网络也用于更复杂的问题,甚至解决现实生活中的场景。

但是节点到底应该是什么呢?一个节点应该代表必须做出决定的输入,然后连接到隐藏层。这些隐藏层是决策网络的一部分。一旦做出决定,它将连接到输出层,显示该决定的结果。就像大脑中的神经元一样,输入可以在隐藏的网络层周围反弹,像神经元触发大脑中的反应一样触发节点。这有助于做出更准确、更具描述性的决策。

深度学习的目标

深度学习的第一个也是主要的目标是随着每一个新的数据而改进。这包括能够调整其底层结构以准确评估数据。一旦使用测试数据完全构建了网络,就可以使用客户分析实现更大的个性化。就像一个流媒体服务建议你接下来应该看什么,你看什么节目/电影的数据被处理,并做出决定建议你可能也喜欢什么。

深度学习模型试图专注于认知计算,并模仿类似人类的思维结构。正因为如此,深度学习在 AI(人工智能)中被大量使用。无论是你最喜欢的游戏中不可玩的敌人角色学习如何更好地攻击,还是聊天机器人回答你的问题,深度学习都允许人工智能以表达认知能力的方式思考,这与我们以前创造的任何东西都不同。这个 AI 和深度学习以后只能越来越准,越来越快。

结论

今天,我们深入探讨了深度学习。作为机器学习的一个子集,深度学习与神经网络合作,模仿大脑如何对输入做出反应以及如何做出决定。神经网络具有从输入连接到隐藏网络层,然后连接到输出的节点。模型运行的时间越长,深度学习试图改善决策过程,并随着模型的运行变得更加准确和更具描述性。随着时间的推移,AI 已经采用深度学习来改善其决策过程。因此,随着突破性进展,人工智能可以在准确性和速度方面变得更加智能。随着深度学习驱动我们的未来,大数据使得使用这种模式变得更加容易。请随意对您如何创建深度学习模型发表评论。下次见,干杯!

用我的 每周简讯 免费阅读我的所有文章,谢谢!

想阅读介质上的所有文章?成为中等 成员 今天!

看看我最近的一些文章:

https://python.plainenglish.io/web-scraping-with-beautiful-soup-1d524e8ef32 https://python.plainenglish.io/something-i-learned-this-week-paramikos-remote-file-management-f13af69baf4 https://python.plainenglish.io/i-suck-at-coding-cb9bc7ef6c06 https://python.plainenglish.io/arrays-vs-list-vs-dictionaries-47058fa19d4e

参考资料:

https://www.sas.com/en_us/insights/analytics/deep-learning.html https://www.sas.com/en_us/insights/analytics/neural-networks.html https://searchenterpriseai.techtarget.com/definition/deep-learning-deep-neural-network

用简单的话深度学习

原文:https://towardsdatascience.com/deep-learning-in-simple-words-448e2c7f6ebe?source=collection_archive---------22-----------------------

人工智能笔记

它从哪里开始?这是什么?为什么有效?

金莎·麦金农Unsplash 上拍摄的照片

在这里,我想用简单的话来解释深度学习,这是人工智能领域最常见的陈词滥调之一。这可能会帮助你找到诸如“什么是深度学习?深度学习为什么有效?“我试图分享我对深度学习的理解,这样你就可以理解全局。一旦你理解并认识到大局,你脑海中的许多问题将有望得到解决。

故事从哪里开始?

传统的机器学习流水线主要有两个步骤:(1) 提取特征和(2) 建立模型(要么分类,要么聚类)。特征提取的目标是在数值空间(也称为特征空间)中表示数据。建模的目标是设计一个计算机化的引擎,它可以确定每个数据点所属的组。

如果您可以设计一个模型来(根据需要)对特征空间中的数据进行分类,这意味着特征提取和分类以预期的方式协同工作。然而,正如你可能会怀疑的那样,故事并不总是那么简单。

—特征提取总是具有挑战性。

很长一段时间,人工智能专家必须与领域专家合作,为每个特定问题提取特征。他们必须在一定程度上具有创造性,并通过合作来实现这一目标。这一过程错综复杂,不可跨项目转移。此外,由于所处理问题的复杂性,手工特征提取在某些应用中几乎是不可能的。

例如,在人脸识别中,光照变化、遮挡和变形等挑战无法通过手工特征提取逐一处理。因此,希望找到一种方法,用可以由机器以自动化方式进行的数据驱动方法来代替手工特征提取。

—棘手的问题需要更复杂的模型。

首先,请允许我定义一个机器学习模型。

机器学习模型是一种数学函数,它获取数据,例如,得出一个结果,显示数据点所属的组或目标变量的估计值。这个数学函数有一个未知参数列表,必须对这些参数进行估计或训练,以确保其输出能够确定每个数据点的成员组。

模型中参数的数量代表模型的复杂度。理论上,一个有无数参数的模型比一个只有几个参数的模型更强大,因此更受欢迎,但是只有在你可以通过成功使用经典方法来调整它的参数的情况下。然而,当参数数量增加时,其他挑战随之而来。

一个有许多参数的模型比一个只有几个参数的模型更强大,因此更受欢迎,但前提是您可以通过成功地使用经典方法来调整它的参数。

分类器的性能可以提高到饱和的程度。性能饱和本身根植于模型的复杂性和培训过程的质量。这就是为什么,随着训练数据的增加,你不能期望一个简单的线性回归超过其性能限制。为了解决难题,模型复杂度和训练数据量必须有一个合理的平衡。

很少会增加传统模型的复杂性,然后仅通过输入大量数据来训练它。在这个大数据时代,在训练过程的早期,会遇到许多模型性能饱和的情况。因此,继续进行研究,以找到一种机器学习模型,该模型可以使用大量数据系统地训练,同时保留以最小的复杂性增加其复杂性的能力。

简单来说,什么是深度学习?

深度学习是一系列基于特殊形式的神经网络的机器学习方法,可以统一进行特征提取和分类,只需很少的人力。他们的构建过程是以具有特殊架构的深度神经网络(基本上是具有许多隐藏层的神经网络)为中心的。深度神经网络不能被认为是深度学习,除非它们有特殊的架构。它们比简单完全连接的层高级得多。在这篇文章中,我解释了为什么特殊的架构改变了游戏,有利于深度学习。

深度学习是一系列基于特殊形式的神经网络的机器学习方法,可以统一进行特征提取和分类,只需很少的人力。

为什么深度学习效果很好?

—特殊的模块化架构打开了许多大门。

传统神经网络的一个主要缺点是缺乏专门的构建模块(构建模块是一组进行大量内部计算然后输出压缩结果的神经元)。

使用其输出代表数据属性的专门构建块是深度学习方法的一个重要方面。专门化的构件使得分析和训练更适应新的训练模式以及新的设计过程。另一方面,传统神经网络中的构造块是网络层,并不总是产生有意义的结果。最后,使用专门的构建模块将帮助您设计更复杂和可训练的神经网络,然后可以用于成功地解决复杂的问题。

一组专门用于图像处理的深度学习方法被称为卷积神经网络(或 CNN)。在这些网络中,专门的构建模块旨在从图像中提取特征,包括边缘或形状。这些构造块也称为卷积层,与传统图像处理中的构造块相似,被称为滤波器,但两者有很大的区别。

在深度学习中,这些构建模块是通过使用训练数据的算法来设计和训练的,而在传统技术中,它们是由人设计的,通常是工程师。例如,用于图像处理的著名卷积神经网络架构 AlexNet 的成功开发解决了机器学习领域的研究人员一直在努力应对的挑战之一。

传统神经网络的主要缺点之一是缺乏有意义的构件。可解释性是他们的弱点之一。

—线性和非线性部分分离良好。

如果一个机器学习模型是非线性的,你可能很难处理它。非线性通常意味着训练模型和分析结果数据会更加困难。这就是为什么,传统 ML 模型中的赢家往往是那些由线性模型(准确地说,分段线性模型)组合而成的模型,如"随机森林和" XGBoost "

神经网络的一个重要部分是它们的计算单元,也称为神经元。简而言之,神经元是一个数学算子,它计算通过一个函数的输入数据的加权和,该函数也被称为激活函数。该函数可以是线性的、分段线性的和非线性的。

神经网络建立在大量神经元的基础上,这些神经元按照模型结构确定的方向相互传递信息。注意,神经网络是非线性函数;然而,它的基础是线性的。神经网络中的线性和非线性部分被很好地分开,因此可以很容易地管理。

—我们现在可以系统地训练一个复杂的模型。

[1]深度神经网络可能有数十亿个需要训练的参数。几年前,专家们对使用这种模型犹豫不决,但今天我们有能力有效地训练深度神经网络。与过去相比,现在每个人都可以以更低的成本获得计算能力。此外,研究人员已经能够引入新方法,这使得深度神经网络能够得到系统训练。

[2]其次,考虑到这是一项如此乏味的任务,你现在并不总是需要花时间从零开始训练一个深度神经网络。你通常可以从一个网络开始,这个网络已经被另一个研究小组或大公司在数百万个数据点上训练过。因此,您只需用自己的数据对网络进行微调。随后,您可以冻结部分网络,因为它将准备好执行基本操作,如图像处理中的边缘检测或自然语言处理中的单词矢量化。

[3]第三,如上所述,深度学习模型的非线性和线性部分是分离的。因此,如果非线性部分在训练中产生问题,您可以修改它们,而不会影响模型的其他部分。例如,如果您使用 sigmoid 作为深度神经网络中的激活函数,训练步骤将会失败。因此,无需太多努力,您就可以用分段线性函数(即校正线性函数)替换该非线性函数(即 sigmoid 函数)。

最后的话。

我们有时会投入实现复杂的算法和方法,而花费较少的时间和资源来学习它们的高级概念。例如,能够快速编写代码来计算文档相似性或提取文档主题,这确实很棒。然而,如果你不知道背后的细节,你可能会被误导。在这篇文章中,我试图阐明深度学习。我希望你已经发现它的信息。

感谢阅读!

如果你喜欢这个帖子,想支持我…

https://pedram-ataee.medium.com/membership

深度学习正在被过度使用

原文:https://towardsdatascience.com/deep-learning-is-becoming-overused-1e6b08bc709f?source=collection_archive---------38-----------------------

理解数据是第一步

来源:图片来自 Pixabay

当以黑箱方式使用任何模型来分析数据时,总是存在危险,深度学习家族的模型也不例外。

不要误会我的意思——当然有像神经网络这样的模型可以胜过更简单的模型的情况——但有很多例子表明情况并非如此。

打个比方——假设你需要购买某种交通工具。如果你经常需要长距离运输大件物品,购买卡车是一项值得的投资。然而,如果你只是需要去当地的超市买些牛奶,这显然是浪费金钱。一辆汽车(或者甚至一辆自行车,如果你有气候意识的话)足以完成这个任务。

深度学习也开始以同样的方式使用。我们开始简单地向这些模型提供相关数据,假设性能将超过更简单的模型。此外,这通常是在没有正确理解相关数据的情况下完成的;即,认识到如果一个人对数据有直观的理解,深度学习就不是必要的。

时间序列分析

我最常做的是时间序列分析,所以让我们考虑一个这方面的例子。

假设一家酒店希望预测其向客户群收取的平均每日价格(或每日平均价格)。每个客户的平均日费率是按周计算的平均值。

LSTM 模型的配置如下:

model = tf.keras.Sequential()
model.add(LSTM(4, input_shape=(1, lookback)))
model.add(Dense(1))
model.compile(loss='mean_squared_error', optimizer='adam')
history=model.fit(X_train, Y_train, validation_split=0.2, epochs=100, batch_size=1, verbose=2)

以下是每周平均房价预测值与实际值的对比:

来源:Jupyter 笔记本输出

相对于平均值 160,RMSE 为 31。RMSE(均方根误差)的大小是平均 ADR 大小的 20%。虽然误差并不太高,但考虑到神经网络的目的是在最大化准确性方面胜过其他模型,这确实有点令人失望。

此外,这种特殊的 LSTM 模型是一步预测——这意味着在时间 t 之前没有所有数据可用的情况下,该模型无法做出长期预测。

也就是说,我们是否在将 LSTM 模型应用于数据方面走在了前面?

我们先把马牵回车前,先对数据有个整体的看法。

以下是 ADR 波动的 7 周移动平均值:

来源:Jupyter 笔记本输出

当数据在 7 周移动平均线上平滑后,我们可以清楚地看到季节性模式的证据。

让我们仔细看看数据的自相关函数。

来源:Jupyter 笔记本输出

我们可以看到峰值相关性(在一系列负相关性之后)处于滞后 52 ,表明数据中存在年度季节性。

使用此信息,使用 pmdarima 配置 ARIMA 模型,以预测最近 15 周的 ADR 波动,自动选择 p、d、q 坐标以最小化 Akaike 信息标准。

>>> Arima_model=pm.auto_arima(train_df, start_p=0, start_q=0, max_p=10, max_q=10, start_P=0, start_Q=0, max_P=10, max_Q=10, m=52, stepwise=True, seasonal=True, information_criterion='aic', trace=True, d=1, D=1, error_action='warn', suppress_warnings=True, random_state = 20, n_fits=30)Performing stepwise search to minimize aic
 ARIMA(0,1,0)(0,1,0)[52]             : AIC=422.399, Time=0.27 sec
 ARIMA(1,1,0)(1,1,0)[52]             : AIC=inf, Time=16.12 sec
 ARIMA(0,1,1)(0,1,1)[52]             : AIC=inf, Time=19.08 sec
 ARIMA(0,1,0)(1,1,0)[52]             : AIC=inf, Time=14.55 sec
 ARIMA(0,1,0)(0,1,1)[52]             : AIC=inf, Time=11.94 sec
 ARIMA(0,1,0)(1,1,1)[52]             : AIC=inf, Time=16.47 sec
 ARIMA(1,1,0)(0,1,0)[52]             : AIC=414.708, Time=0.56 sec
 ARIMA(1,1,0)(0,1,1)[52]             : AIC=inf, Time=15.98 sec
 ARIMA(1,1,0)(1,1,1)[52]             : AIC=inf, Time=20.41 sec
 ARIMA(2,1,0)(0,1,0)[52]             : AIC=413.878, Time=1.01 sec
 ARIMA(2,1,0)(1,1,0)[52]             : AIC=inf, Time=22.19 sec
 ARIMA(2,1,0)(0,1,1)[52]             : AIC=inf, Time=25.80 sec
 ARIMA(2,1,0)(1,1,1)[52]             : AIC=inf, Time=28.23 sec
 ARIMA(3,1,0)(0,1,0)[52]             : AIC=414.514, Time=1.13 sec
 ARIMA(2,1,1)(0,1,0)[52]             : AIC=415.165, Time=2.18 sec
 ARIMA(1,1,1)(0,1,0)[52]             : AIC=413.365, Time=1.11 sec
 ARIMA(1,1,1)(1,1,0)[52]             : AIC=415.351, Time=24.93 sec
 ARIMA(1,1,1)(0,1,1)[52]             : AIC=inf, Time=21.92 sec
 ARIMA(1,1,1)(1,1,1)[52]             : AIC=inf, Time=30.36 sec
 ARIMA(0,1,1)(0,1,0)[52]             : AIC=411.433, Time=0.59 sec
 ARIMA(0,1,1)(1,1,0)[52]             : AIC=413.422, Time=11.57 sec
 ARIMA(0,1,1)(1,1,1)[52]             : AIC=inf, Time=23.39 sec
 ARIMA(0,1,2)(0,1,0)[52]             : AIC=413.343, Time=0.82 sec
 ARIMA(1,1,2)(0,1,0)[52]             : AIC=415.196, Time=1.63 sec
 ARIMA(0,1,1)(0,1,0)[52] intercept   : AIC=413.377, Time=1.04 sec

Best model:  ARIMA(0,1,1)(0,1,0)[52]          
Total fit time: 313.326 seconds

根据上面的输出,【ARIMA(0,1,1)(0,1,0)【52】是根据 AIC 最适合的模型的配置。

使用该模型,相对于 160 的平均 ADR,获得了 10 的 RMSE。

这比 LSTM 达到的 RMSE 低很多(这是一件好事),只占平均值的 6%多一点。

通过对数据的适当分析,人们会认识到数据中存在年度季节性成分使得时间序列更具可预测性——使用深度学习模型来试图预测这样的成分在很大程度上是多余的。

回归分析:预测客户 ADR 值

让我们对上述问题换个角度来看。

现在,让我们尝试预测每个客户的平均每周 ADR 值,而不是尝试预测平均每周 ADR。

为此,使用了两种基于回归的模型:

  • 线性 SVM(支持向量机)
  • 基于回归的神经网络

两个模型都使用了以下特征来预测每个客户的 ADR 值:

  • 已取消:客户是否取消预订
  • 国家:客户的原产国
  • 市场细分:客户的市场细分
  • 押金类型:客户是否已支付押金
  • 客户类型:客户的类型
  • 垃圾收集站:所需的停车位
  • 抵达日期星期号:抵达的星期

使用平均绝对误差作为性能度量,让我们比较获得的 MAE 相对于两个模型的平均值。

线性 SVM

ε为 0.5 的线性向量回归被定义并在训练数据中被训练:

svm_reg_05 = LinearSVR(epsilon=0.5)
svm_reg_05.fit(X_train, y_train)

现在使用测试集中的特征值进行预测:

>>> svm_reg_05.predict(atest)array([ 81.7431138 , 107.46098525, 107.46098525, ...,  94.50144931,
        94.202052  ,  94.50144931])

这是相对于平均值的平均绝对误差:

>>> mean_absolute_error(btest, bpred)
30.332614341027753>>> np.mean(btest)
105.30446539770578

MAE 是平均值的 28%。

让我们看看基于回归的神经网络是否能做得更好。

基于回归的神经网络

神经网络定义如下:

model = Sequential()
model.add(Dense(8, input_dim=8, kernel_initializer='normal', activation='elu'))
model.add(Dense(2670, activation='elu'))
model.add(Dense(1, activation='linear'))
model.summary()

然后,使用 150:

model.compile(loss='mse', optimizer='adam', metrics=['mse','mae'])
history=model.fit(xtrain_scale, ytrain_scale, epochs=30, batch_size=150, verbose=1, validation_split=0.2)
predictions = model.predict(xval_scale)

将测试集中的特征输入到模型中后,MAE 和平均值如下:

>>> mean_absolute_error(btest, bpred)
28.908454264679218>>> np.mean(btest)
105.30446539770578

我们看到平均大气透过率仅比使用 SVM 获得的略低。在这方面,当线性 SVM 模型表现出几乎相同的准确性时,很难证明使用神经网络来预测客户 ADR 是合理的。

无论如何,用来“解释”ADR 的特征选择等因素比模型本身更重要。俗话说“垃圾进,垃圾出”。如果特征选择很差,那么模型的输出也会很差。

在这种情况下,虽然两个回归模型都显示了一定程度的预测能力,但很有可能 1)选择数据集中的其他要素可以进一步提高准确性,或者 2)数据集中的要素可能会导致 ADR 出现太多变化。例如,数据集没有告诉我们关于每个客户的收入水平等因素的任何信息,而这些因素预计会显著影响他们每天的平均支出。

结论

在上面的两个例子中,我们已经看到,使用“更轻”的模型已经能够匹配(或超过)深度学习模型所达到的准确性。

虽然在有些情况下,数据可能非常复杂,需要算法“从零开始”学习数据中的模式,但这往往是例外而不是规则。

与任何数据科学问题一样,关键首先在于理解正在处理的数据。型号的选择是次要的。

非常感谢您的时间,任何问题或反馈都非常感谢!

上述例子的数据集和 Jupyter 笔记本可以在这里找到。

免责声明:本文是在“原样”的基础上编写的,没有担保。本文旨在提供数据科学概念的概述,不应以任何方式解释为专业建议。

参考

深度学习可能还不是所有 NLP 任务的银弹

原文:https://towardsdatascience.com/deep-learning-may-not-be-the-silver-bullet-for-all-nlp-tasks-just-yet-7e83405b8359?source=collection_archive---------38-----------------------

自然语言处理

为什么你仍然应该学习启发式和基于规则的方法

蒂莫西·戴克斯Unsplash 上拍摄

介绍

深度学习;解决人类问题的方法。在过去的几年里,深度学习以新颖的方式推进了人类。这些受益者之一是整个自然语言处理领域(NLP)。但在我们进入如何之前,让我们探索一下深度学习领域。

我很确定我们都见过维恩图,它说明了人工智能(AI)与机器学习(ML)和深度学习的关系。如果不是,它只是证明了深度学习是机器学习的一个子领域,而机器学习是人工智能的一个子领域。

深度学习与机器学习的不同之处在于,它涉及基于人脑的结构和功能开发的算法——这些结构和功能被称为人工神经网络

深度学习如何推进 NLP

软件行业的大部分正在转向机器智能或数据驱动的决策,但其他行业也注意到了它的影响,并对此感兴趣,如医疗保健行业。人工智能发展的一个很好的原因可以归结为机器学习和深度学习(当然还有其他使执行这些任务成为可能的因素),然而,近年来深度学习越来越受欢迎,因为它在准确性等指标方面占据优势,并且当我们有大量数据来支持我们的深度学习算法时。

例如,在文本分类任务中,基于递归神经网络(RNN)的模型已经超过了标准机器学习技术的性能水平,这些技术曾经由革命性的机器学习模型解决,如朴素贝叶斯分类器支持向量机。此外,LSTMs(它是 rnn 家族的一部分)在序列标记任务(如实体提取)中胜过条件随机场(CRF)模型。

最近,镇上有一个新的话题叫做变形金刚模型。Transformer 模型非常强大,已经成为大多数自然语言处理任务的最新模型。深入研究 transformer 模型的细节超出了本文的范围,但是如果您希望我在后面的教程中介绍它,请留下您的回复。

坠落

尽管深度学习取得了巨大的成功,但它仍然不是每个自然语言处理任务的灵丹妙药。因此,当面对 NLP 中的问题时,实践者不应该急于构建最大的 RNN 或转换器,原因如下:

过拟合

深度学习模型往往比传统的机器学习模型有更多的参数。因此,深度学习模型比传统模型具有更强的表达能力,这也是它们如此强大的原因。它如此强大的原因也是它最大弱点的来源。许多深度学习模型倾向于过度拟合小数据集,因此导致泛化能力差,这导致生产中的糟糕性能。

缺乏少投学习技巧

我通常不会比较,但在这种情况下,我们必须比较;看一看计算机视觉领域。深度学习在 CV 方面取得了很大的进步,因为一些技术,例如少量学习(例如,从很少的实例中学习),这导致了更广泛地采用深度学习来解决现实世界的问题。在 NLP 中,我们只是没有看到类似的深度学习技术以与计算机视觉相同的方式被成功采用。

域适配

当我们没有大量训练数据时,迁移学习对于提高深度学习模型的性能来说是革命性的。然而,利用在公共领域训练的深度学习模型,例如报纸文章,然后将其应用到更近的领域,如社交媒体帖子,可能会导致我们的深度学习模型的整体性能不佳。更简单但仍然非常有效的解决方案可能涉及传统的机器学习模型或特定领域的基于规则的模型。

可解释性

可解释性是近年来变得突出的东西——它是有意义的。你难道不想知道为什么你会被拒绝贷款吗?虽然有一些技术正在开发中,试图解释深度学习模型,但在很大程度上,它们像黑盒一样工作。在这种情况下,使用像朴素贝叶斯模型这样的技术可能更有用,这种技术可以很容易地解释为什么进行某种分类。

成本

成本很重要;用深度学习构建解决方案可能在时间和金钱方面都非常昂贵。与 Kaggle 不同,真实世界中的数据集不会被标记,并且不要忘记,我们需要一个大的数据集来保证我们的模型不会过度拟合。收集和标注大型数据集可能非常耗时,然后继续部署模型并在生产中维护它,在硬件要求和工作量方面可能非常昂贵。

最后的想法

这绝不是为什么深度学习可能还不是 NLP 任务的银弹的详尽列表,但它提供了现实世界项目中可能出现的场景类型的真实感觉。这些症状经常导致项目周期比它需要的要长得多,更不用说项目上线和交付后维护的更高成本了。此外,相对于传统的机器学习模型,性能的提高通常不是非常显著(即,如果有的话,准确性没有很大的提高)。

感谢您的阅读!在 LinkedIn 和 T2 Twitter 上与我保持联系,了解我关于数据科学、人工智能和自由职业的最新消息。

相关文章

</4-data-related-books-ill-be-reading-in-april-efd06b367e35> </5-ideas-for-your-next-nlp-project-c6bf5b86935c>

深度学习遇到高斯过程:深度核学习如何实现自主显微镜

原文:https://towardsdatascience.com/deep-learning-meets-gaussian-process-how-deep-kernel-learning-enables-autonomous-microscopy-58106574cfeb?source=collection_archive---------21-----------------------

马克西姆·齐亚丁诺夫&谢尔盖·加里宁

美国田纳西州橡树岭橡树岭国家实验室纳米材料科学和计算科学与工程中心

对于许多科学家和工程师来说,他们的职业之路是从显微镜开始的。在简单的光学显微镜或放大镜下,附近海滩的沙子开始看起来像一个山地国家,里面有硅藻和蜗牛的骨架以及彩色的矿物质。水坑中的水滴揭示了好奇的(有时令人不安的)微小生物。借助现代手机,谷歌眼镜可以帮助识别它们的类别和种类。干燥的盐溶液将显示彩虹色的晶体。在一个更专业的环境中,定制(也更昂贵)的电子和扫描探针显微镜揭示了材料的微米和纳米尺度结构,一直到可视化形成材料和分子表面的原子图案。下图显示了第二位作者拍摄的金色圆形蜘蛛和第一位作者拍摄的表面上的“布基球”分子。

图一。(左)金球蜘蛛。(右)金表面的苏曼烯(“巴基球”)分子。作者提供的数据。

然而,现代显微镜不仅可以对材料及其表面进行成像,还可以对它们的性质进行更详细的研究。在扫描隧道显微镜(STM)中,操作者可以选择潜在感兴趣的区域并进行隧道光谱,即测量电流-电压曲线。在量子隧道的控制下,这条曲线将包含关于局域态密度、超导性、电荷密度波和表面上其他激发现象的信息[1–2]。在电子显微镜中,选择的技术是电子能量损失光谱[3]。在这里,测量穿过固体的电子的能量损失揭示了单个原子的化学结构,随着单色仪器的最新进展,允许探测固体中的准粒子,如电子和等离子体[4-5]。扫描探针显微镜中出现了特别广泛的可能光谱模式,允许研究人员探测局部机械性质、导电性和铁电极化转换[6–7]。

不幸的是,与成像相比,局部功能测量要花费很多时间。例如,获得一个简单的 STM 图像通常需要大约 5-10 分钟。在密集的空间网格点上获得密集的光谱曲线阵列需要几天时间,这就需要建造超稳定的显微镜,在这些时间内不会发生明显的漂移。同样的考虑也适用于电子显微镜,对于电子显微镜,还需要考虑电子束对样品的损伤。最后,许多测量是破坏性的,不能在密集网格上进行,例如纳米压痕。这些考虑严重限制了这些测量的能力以及它们对材料的结构和功能提供的洞察力。很像谚语中的琼恩·雪诺,如果我们不知道在哪里测量,我们就在任何地方测量,希望在非现场数据分析期间捕获感兴趣的行为,希望识别感兴趣的区域。机器学习能让我们做得更好吗?(提示:我们可以,否则这篇博文就写不出来了)。

图 2:现代显微镜,如左图所示的超高真空扫描隧道显微镜,可以在纳米尺度和原子尺度上探索材料的结构和功能。右边显示的是 2D 地形图,我们可以对 m x n 网格(未显示)进行光谱测量,并在两个网格点记录差分隧道电导光谱。作者图。

为了理解这一工作需要什么,我们首先考虑在基于高斯过程(GP)的实验中用于主动学习的聚合方法。在最一般的形式中,GP 指的是试图从一组稀疏测量值在特定(低维)参数空间上重建函数的一类算法。换句话说,给定一组观测数据点( x ᵢ, y ᵢ),并假设正态分布的观测噪声 ϵ,,GP 旨在重构函数 f ( x ),例如yᵢ=f(xᵢ)+ϵᵢ,其中f~ K ( x ᵢ, x ⱼ)).在实验之前选择核函数形式 K ,并且使用马尔可夫链蒙特卡罗方法或随机变分推断从观察值推断其超参数。你可以在这里阅读 GP 更严格的定义。另请参见我们之前在 GPs 上发布的中型帖子。我们小组已经将 GP 应用于多个成像问题,包括稀疏高光谱数据的重建铁电体中的磁滞回线工程晶格哈密顿量参数空间的高效探索,完整代码可通过 GPim 包获得。

GP 的独特之处在于,该函数连同相关的不确定性σ(x)一起被重构。这一方面允许将 GP 扩展到主动学习方法。假设我们想要通过顺序选择点来执行测量,以最有效的方式学习参数空间上的函数值。在这种情况下,具有最大不确定性的区域代表查询的最佳点。以这种方式,GP 驱动的自动化实验寻求以最迅速的方式减少关于功能的不确定性。

应该注意的是,GP 可以进一步扩展以针对特定行为。在这种情况下,如果我们预先知道我们正在寻找的函数值,我们可以在一个单一的采集函数中结合期望和不确定性。然后,采集函数的最大值(或最小值)用于参数空间的导航。这种结合了参数空间的探索和利用的方法通常被称为贝叶斯优化(BO)。

那么问题就变成了 GP/BO 是否可以用来实现显微镜的自动化实验。事实证明,在简单成像或光谱学的情况下,总增益相对较小。事实上,图像通常包含许多不同长度尺度的多个特征——从大到小。我们事先不知道这些特征是什么。相应地,试图基于单点测量导航图像空间并发现相关核函数的基于 GP 的算法会遇到困难。事实上,对于已知图像,核函数大致相当于相关函数,这不是表示图像的非常有效的方式。原则上,可以通过将标准多元分解(PCA,NMF)或自动编码器技术应用于图像补片来实现图像的简化表示。然而,不能保证这些简化的表示在物理上是有意义的,并且它们可能经常受到仪器因素的支配,例如漂移(在许多情况下,领域专家必须将物理变量与非物理变量分开,这违背了自动化实验的全部意义)。此外,分解需要补丁提前可用,这违背了发现的概念。

GP 产生的增益进一步降低,因为如果被迫沿着非常复杂的路径移动探针,显微镜的电子和机械装置会开始失效。最重要的是,GP 通常不能很好地预测复杂的模式。总之,它看起来像 GP 它不足以在显微镜下进行自动化实验。

进入深度内核学习。为了理解它是如何工作的,让我们回顾一下如果操作员看到图像他们会做什么。人眼会立即记录感兴趣的物体。例如,在图 2 中超导体的 STM 图像中,我们可以立即注意到有亮点的区域。一个合格的操作员会立即识别出这些区域可能是局域电子态的宿主,尽管它的性质可能依赖于周围的环境。类似地,人们可以注意到具有条纹对比度的多个区域,这可能是表面重建的指示。它们有很多,很明显它们应该有相似的行为。因此,对其中几个进行光谱测量,并假设观察到的行为具有代表性,也许就足够了。然而,也存在一些区域,其中小的凹陷和/或突起嵌入到条纹域中,并且这些区域可能包含关于该系统的物理的一些额外的有趣见解。接下来的问题是,我们是否可以利用结构图像中包含的信息,以自主的方式指导光谱测量。

深度内核学习(DKL),最初由 Andrew Gordon Wilson 引入,可以理解为经典深度神经网络(DNN)和 GP 的混合体,如图 3 所示。这里,DNN 部分充当特征提取器,允许将复杂的高维特征减少到标准 GP 内核操作的低维描述符。通过在边缘对数似然上执行梯度上升来联合优化 DNN 和 GP 核的参数。新输入的 DKL 输出是感兴趣的属性(或属性,如果我们对向量值函数感兴趣)的期望值和相关的不确定性。让我们看看如何利用 DKL 在电子或扫描探针显微镜上进行实验。

图 3。深度核学习:训练和预测步骤。训练输入是(结构)图像补片,目标是感兴趣的物理功能的标量值(通常从那些补片中测量的光谱曲线中导出)。在预测步骤,训练的 DKL 模型用于获得感兴趣的功能的期望值和新的一组结构图像补片的相应的不确定性(对于该新的一组结构图像补片,功能还没有被实验测量)。作者图。

我们将展示两个基本的例子,其中 DKL 被用于映射材料结构的部分,以最大化特定的物理功能。为此,DKL 必须了解系统中相关的结构-性质关系。在实现方面,DKL 训练输入是结构图像的小块,训练目标是与从块中心测量的光谱中导出的一些物理功能相关联的标量值(DKL 也可以与向量值目标一起工作,甚至可以预测整个光谱,但这些将在单独的帖子中讨论)。目标是使用易于获取的结构数据来指导通常更加繁琐的光谱测量。因此,基于 DKL 的自动化实验从收集结构图像开始,该结构图像被分割成一组小碎片(每个图像像素一个碎片),随后在图像的随机位置获取几个光谱曲线。这些稀疏观察用于训练 DKL 模型。然后,使用训练的 DKL 模型来预测没有测量光谱的结构图像的每个坐标中的感兴趣的特性(或者,更具体地,对于以该坐标为中心的每个图像片)。预测的平均特性值和相关的不确定性用于导出采集函数,以对下一个(多个)测量点进行采样。一旦执行了新的测量,就更新训练数据,并重复整个过程。

首先,让我们使用在等离子体纳米立方体上获得的公开可用的数据集。这里我们的结构数据来自扫描透射电子显微镜图像。感兴趣的功能源自在相同区域上测量的电子能量损失谱,并且在该特定示例中,仅仅是边缘等离子体峰的强度。我们运行 DKL 100 次迭代,这大约是总网格点的 3%。在每次迭代中,我们使用简单的 Thompson 采样器选择下一个测量点。因为我们已经知道了地面实况,我们可以用地面实况地图覆盖采样点。可以看到,我们能够通过测量网格的一小部分来识别结构图像中感兴趣的功能最大化的区域。

图 4。基于 DKL 的纳米等离子体阵列区域的搜索。作者图。

现在,让我们来看看这种方法是如何在压电响应力显微镜中识别最大化迟滞回线面积的样品区域的。我们的 DKL 设置与之前的实验几乎相同,只是现在,在每一步,我们采样一批 4 个点,而不仅仅是一个点。同样,从下面的图 5 中可以看出,我们能够用非常少的测量值(整个网格的大约 5%)快速定位感兴趣的行为。

图 5。基于 DKL 搜索最大化磁滞回线面积的区域。作者图。

总的来说,这种方法通过主动学习系统中的结构-性质关系,使用结构信息来指导光谱(功能)测量。重要的是,我们可以使用几乎任何物理搜索标准,从这篇博文中使用的简单标准到复杂得多的标准。以这种方式,我们结合相关机器学习的能力来建立多维数据集中的关系,并导出相应的不确定性,以及在搜索标准的选择中编码的领域专业知识。

请查看我们的 AtomAI 软件包,将该工具和其他深度/机器学习工具应用于科学成像。如果你想了解更多关于扫描探针显微镜的知识,欢迎来到 M*N 频道:显微镜,机器学习,材料。最后,在科学界,我们感谢资助这项研究的赞助商。这项工作在橡树岭国家实验室纳米材料科学中心(CNMS)进行并得到支持,该中心是美国能源部科学用户设施办公室。您可以使用此链接进行虚拟漫游,如果您想了解更多,请告诉我们。

其中一个例子的可执行 Google Colab notebook 可以在这里找到。

参考文献:

1.鲁山,p;徐,j;帕克;Hor,Y. S 谢博士;钱博士;理查德拉,a。哈桑;R. J .卡瓦;手征自旋织构保护拓扑表面态免受反向散射。性质 2009、 460 (7259)、1106-U64。

2.潘;赫德森;郎;卫崎;内田,s;成像单个锌杂质原子对 bi 2 Sr 2 cacu 2 o 8+δ超导性的影响。性质 2000、 403 (6771)、746–750。

3.彭尼库克,S. J。瓦雷拉,男;卢皮尼;奥克斯利议员;齐索姆,M. F,《原子分辨率光谱成像:过去、现在和未来》。j .电子显微公司。 2009, 58 (3),87–97。

4.Kapetanakis,医学博士;周;奥克斯利议员;李,j;议员普朗格;彭尼库克,S. J。Idrobo,J. CPantelides,S. T,《低损失电子能量损失光谱学:光学光谱学的原子分辨率补充及其在石墨烯中的应用》。物理修订 B 2015、 92 (12)。

5.哈格,F. S。尼科尔斯;耶茨;麦卡洛克特区;洛夫乔伊;新泽西州德尔比;克里瓦内克;里夫森,k。纳米尺度动量分辨振动光谱学。 Sci。Adv. 2018, 4 (6),6。

6.加里宁公司;斯特尔科夫,e;别利亚尼诺夫。索姆纳特;瓦苏德万;林格费尔特;阿奇博尔德;陈;普罗克什河;新泽西州拉纳伊特;扫描探针显微镜中的大、深、智能数据。 ACS Nano 2016, 10 (10),9068–9086。

7.瓦苏德万;杰西;金,y;库马尔,a。压电响应力显微镜中的光谱成像:研究铁电体和多铁性中极化动力学的新机会。科曼夫人。 2012, 2 (3),61–73。

8.加里宁公司;瓦莱蒂,m;瓦苏德万;Ziatdinov,m,《通过基于高斯过程的探索-利用进行功能和结构发现的晶格哈密顿量探索》。 J. Appl. Phys. 2020, 128 (16),11。

9.加里宁公司;齐亚特迪诺夫,m;Vasudevan,R. K,《通过生成模型的贝叶斯优化引导搜索期望的功能响应:铁电体中的磁滞回线形状工程》。 J. Appl. Phys. 2020, 128 (2),8。

使用 SHAP 的深度学习模型解释

原文:https://towardsdatascience.com/deep-learning-model-interpretation-using-shap-a21786e91d16?source=collection_archive---------1-----------------------

图像和表格数据的 Python 实现

传统上,机器学习和深度学习的批评者说,即使他们获得了准确的预测,我们也在创建“黑盒”模型。但这是一种误解。机器学习和深度学习模型是可以解释的。模型解释在学术界和工业界的研究者中是一个非常活跃的领域。Christoph Molnar 在他的书“可解释的机器学习”中,将可解释性定义为人类能够理解决策原因的程度,或者人类能够持续预测 ML 模型结果的程度。

由于可解释性,今天越来越多的公司在决策过程中有效地使用机器学习和深度学习,或者计划将它们纳入未来的战略,即使是在医药和金融等高度监管的领域。

根据数据集的性质,一些数据科学家更喜欢经典的机器学习方法。有时深度学习在非表格领域表现出色,如计算机视觉、语言和语音识别。

当我们谈论模型可解释性时,理解全局方法和局部方法之间的区别是很重要的:

  • 全局方法是理解模型如何做出决策的整体结构。
  • 本地方法是理解模型如何为单个实例做出决策。

有许多方法旨在提高模型的可解释性。 SHAP 值是解释模型和理解数据特征与输出之间关系的最常用方法之一。这是一种源自联盟博弈理论的方法,它提供了一种在特性之间公平分配“支出”的方式。

SHAP 价值观的最大优势之一是它们提供了全局和局部的可解释性。本文重点介绍使用 SHAP 对表格数据和非结构化数据(本文图片)进行深度学习模型解释。

由 SHAP 深度讲解器讲解图像分类

图像分类任务可以通过预测图像上每个像素的分数来解释,该分数指示它对将该图像分类到特定类别的贡献程度。在本文中,我将:

  • CIFAR10 数据集上训练 CNN 模型
  • 计算 SHAP 值
  • 可视化预测结果和 SHAP 值

首先,让我们加载并转换 keras 内置数据集。

# load package
import shap
import numpy as np
import tensorflow as tf
from tensorflow import keras
import matplotlib.pyplot as plt
from keras.models import Sequential
import ssl# load build-in dataset
ssl._create_default_https_context = ssl._create_unverified_context
(x_train, y_train), (x_test, y_test) = keras.datasets.cifar10.load_data()# reshape and normalize data
x_train = x_train.reshape(50000, 32, 32, 3).astype("float32") / 255
x_test = x_test.reshape(10000, 32, 32, 3).astype("float32") / 255
y_train = y_train.reshape(50000,)
y_test = y_test.reshape(10000,)

现在让我们建立一个简单的神经网络,编译并拟合模型。

# define the model architecture
inputs = keras.Input(shape=(32, 32, 3))
x = keras.layers.Conv2D(32, (3, 3), activation='relu')(inputs)
x = keras.layers.MaxPooling2D((2, 2))(x)
x = keras.layers.Conv2D(128, (3, 3), activation='relu')(inputs)
x = keras.layers.MaxPooling2D((2, 2))(x)
x = keras.layers.Conv2D(64, (3, 3), activation='relu')(inputs)
x = keras.layers.MaxPooling2D((2, 2))(x)
x = keras.layers.Conv2D(32, (3, 3), activation='relu')(inputs)
x = keras.layers.MaxPooling2D((2, 2))(x)
x = keras.layers.Flatten()(x)
x = keras.layers.Dense(256, activation='relu')(x)
x = keras.layers.Dense(64, activation='relu')(x)
outputs = keras.layers.Dense(10, activation='softmax')(x)# inputs and outputs
model = keras.Model(inputs=inputs, outputs=outputs, name="test_for_shap")# compile the model
model.compile(
      loss=tf.keras.losses.SparseCategoricalCrossentropy(),
      optimizer=keras.optimizers.Adam(),
      metrics=[tf.keras.metrics.SparseCategoricalAccuracy()]
  )model.fit(x_train, y_train, validation_data=(x_test, y_test), epochs = 10)

接下来,让我们在测试集上进行预测(每个类一个图像)。

# class label list
class_names = ['airplane', 'automobile', 'bird', 'cat', 'deer',
               'dog', 'frog', 'horse', 'ship', 'truck']# example image for each class
images_dict = dict()
for i, l in enumerate(y_train):
  if len(images_dict)==10:
    break
  if l not in images_dict.keys():
    images_dict[l] = x_train[i].reshape((32, 32,3))
images_dict = dict(sorted(images_dict.items()))

# example image for each class for test set
x_test_dict = dict()
for i, l in enumerate(y_test):
  if len(x_test_dict)==10:
    break
  if l not in x_test_dict.keys():
    x_test_dict[l] = x_test[i]# order by class
x_test_each_class = [x_test_dict[i] for i in sorted(x_test_dict)]
x_test_each_class = np.asarray(x_test_each_class)# Compute predictions
predictions = model.predict(x_test_each_class)
predicted_class = np.argmax(predictions, axis=1)

然后,我们为实际类和预测类定义绘图函数。

# plot actual and predicted class
def plot_actual_predicted(images, pred_classes):
  fig, axes = plt.subplots(1, 11, figsize=(16, 15))
  axes = axes.flatten()

  # plot
  ax = axes[0]
  dummy_array = np.array([[[0, 0, 0, 0]]], dtype='uint8')
  ax.set_title("Base reference")
  ax.set_axis_off()
  ax.imshow(dummy_array, interpolation='nearest') # plot image
  for k,v in images.items():
    ax = axes[k+1]
    ax.imshow(v, cmap=plt.cm.binary)
    ax.set_title(f"True: %s \nPredict: %s" % (class_names[k], class_names[pred_classes[k]]))
    ax.set_axis_off() plt.tight_layout()
  plt.show()

现在,我们可以使用 SHAP 库来生成 SHAP 值:

# select backgroud for shap
background = x_train[np.random.choice(x_train.shape[0], 1000, replace=False)]# DeepExplainer to explain predictions of the model
explainer = shap.DeepExplainer(model, background)# compute shap values
shap_values = explainer.shap_values(x_test_each_class)

最后,我们可以看到 SHAP 的价值观。

# plot SHAP values
plot_actual_predicted(images_dict, predicted_class)
print()
shap.image_plot(shap_values, x_test_each_class * 255)

按作者

在这个可视化中:

  • 红色像素代表有助于将该图像分类为特定类别的正 SHAP 值。
  • 蓝色像素表示负 SHAP 值,这导致没有将该图像分类为该特定类别。

用 SHAP 深层解释器解释表格数据分类

大量的数据可以用表格的形式表示。下图是一个完全连接的神经网络,通过 SHAP 深度解释器,我们可以知道哪个输入特征实际上对模型输出和大小有贡献。

按作者

在本文中,我将使用开源的 Titanic 数据集进行演示:

  • 训练多层感知模型
  • 计算 SHAP 值
  • 视觉全局和局部图

首先,我加载包和泰坦尼克号数据。

# import package
import shap
import numpy as np 
import pandas as pd 
import matplotlib.pyplot as plt
from sklearn.preprocessing import StandardScaler
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Dropout
from tensorflow.keras import optimizers
import warnings 
warnings.filterwarnings('ignore')
%matplotlib inline
import os# load data
os.chdir('/titanic/')
train_data = pd.read_csv('./train.csv', index_col=0)
test_data = pd.read_csv('./test.csv', index_col=0)
train_data.head()

然后,我们通过删除不必要的列、处理丢失的数据、将分类特征转换为数字特征以及进行一次性编码来处理原始数据。

def data_preprocessing(df):
    df = df.drop(columns=['Name', 'Ticket', 'Cabin'])

    # fill na
    df[['Age']] = df[['Age']].fillna(value=df[['Age']].mean())
    df[['Embarked']] = df[['Embarked']].fillna(value=df['Embarked'].value_counts().idxmax())
    df[['Fare']] = df[['Fare']].fillna(value=df[['Fare']].mean())

    # categorical features into numeric
    df['Sex'] = df['Sex'].map( {'female': 1, 'male': 0} ).astype(int)

    # one-hot encoding
    embarked_one_hot = pd.get_dummies(df['Embarked'], prefix='Embarked')
    df = df.drop('Embarked', axis=1)
    df = df.join(embarked_one_hot)

    return df# train data processing
train_data = data_preprocessing(train_data)
train_data.isnull().sum()# create data for training
x_train = train_data.drop(['Survived'], axis=1).values# Check test data
test_data.isnull().sum()# scale
scale = StandardScaler()
x_train = scale.fit_transform(x_train)# prepare y_train
y_train = train_data['Survived'].valuestest_data = data_preprocessing(test_data)
x_test = test_data.values.astype(float)# scaling
x_test = scale.transform(x_test)# Check test data
test_data.isnull().sum()

接下来是定义、编译和拟合 keras 模型。

# build mlp
model = Sequential()
model.add(Dense(32, input_dim=x_train.shape[1], activation='relu'))
model.add(Dropout(0.25))
model.add(Dense(128, activation='relu'))
model.add(Dropout(0.25))
model.add(Dense(32, activation='relu'))
model.add(Dropout(0.25))
model.add(Dense(8, activation='relu'))
model.add(Dropout(0.25))
model.add(Dense(2, activation='softmax'))# compile model
model.compile(loss='sparse_categorical_crossentropy', optimizer = 'adam', metrics = ['accuracy'])# fit model
model.fit(x_train, y_train, epochs=10, batch_size=64)

然后我计算 SHAP 值。

# compute SHAP values
explainer = shap.DeepExplainer(model, x_train)
shap_values = explainer.shap_values(x_test)

SHAP 全球解读

汇总图显示了最重要的特征及其对模型的影响程度。这是全球的解释。

shap.summary_plot(shap_values[0], plot_type = 'bar', feature_names = test_data.columns)

按作者

SHAP 当地解读

在本文中,我将展示一个示例的三种可视化解释:

  • 力图
  • 决策图
  • 瀑布图

力图有助于了解“输出值”相对于“基础值”的位置。我们还可以看到哪些要素对预测有正面(红色)或负面(蓝色)影响,以及影响的大小。

shap.initjs()
shap.force_plot(explainer.expected_value[0].numpy(), shap_values[0][0], features = test_data.columns)

决策图可以观察每个变化的幅度,由样本对显示的特征值进行处理。

shap.decision_plot(explainer.expected_value[0].numpy(), shap_values[0][0], features = test_data.iloc[0,:], feature_names = test_data.columns.tolist())

按作者

瀑布图还允许我们看到某个特性影响的幅度和性质。它还允许查看特征的重要性顺序以及样本的每个特征所取的值。

shap.plots._waterfall.waterfall_legacy(explainer.expected_value[0].numpy(), shap_values[0][0], feature_names = test_data.columns)

按作者

结论和下一步措施

AI 算法在我们生活中占据的空间越来越大,被广泛应用于各个行业。对于数据科学家、决策者和监管者来说,模型可解释性是一个非常重要的话题。在这篇文章中,我主要讲述了使用 python 代码一步步对图像和表格数据进行深度学习模型解释。我将在未来的帖子中分享更多关于文本数据的深度学习模型解释,而不是指导实现。

参考

  1. https://christophm.github.io/interpretable-ml-book/
  2. https://cloud . Google . com/blog/products/ai-machine-learning/why-you-need-to-explain-machine-learning-models
  3. https://github.com/slundberg/shap
  4. https://www.kaggle.com/c/titanic/data
  5. https://www.openml.org/d/40945
  6. https://en . Wikipedia . org/wiki/explable _ artificial _ intelligence
  7. neuralnetworksanddeeplearning.com
  8. https://www . cs . Toronto . edu/~ kriz/learning-features-2009-tr . pdf
  9. https://www.cs.toronto.edu/~kriz/cifar.html

深度学习模型可视化

原文:https://towardsdatascience.com/deep-learning-model-visualization-6cf6290dc981?source=collection_archive---------30-----------------------

可视化神经网络如何在感知器级别学习

艾莉娜·格鲁布尼亚克在 Unsplash 上的照片

你有没有想过一个深度学习模型是如何在后端学习的?每一层如何帮助传递信息到下一层,每一层学到了什么信息?如果你真的可以分析和想象模型是如何在每次迭代后找到图像中的模式,那不是很好吗?如果这一切让你兴奋,那么你来对地方了。

在本文中,我将向您展示如何可视化深度学习模型如何在每次迭代中学习,以及它们如何试图找到模式。

我们将探索一个名为“keras-vis”的库,它将解决上面给出的目的。它是一个开源的 python 库,有助于可视化深度学习神经网络模型。它是一个高级工具包,用于可视化和调试经过训练的 Keras 神经网络。让我们开始吧…

安装 keras-vis

为了安装 keras-vis,我们将使用下面给出的命令。对于本文,我们将使用 google collab。

!pip install git+https://github.com/raghakot/keras-vis.git

目前,该库支持 TensorFlow 版本 1.8 和 Keras 版本 2.2.0,下面给出的命令将安装所需的版本。

!pip uninstall tensorflow
!pip install tensorflow==1.8
!pip uninstall keras
!pip install keras==2.2.0

导入所需的库

为了创建模型和可视化,我们需要导入某些库,复制下面给出的代码来导入这些库。

**import** **numpy** **as** **np**
**import** **keras**
**from** **keras.datasets** **import** mnist
**from** **keras.models** **import** Sequential, Model
**from** **keras.layers** **import** Dense, Dropout, Flatten, Activation, Input
**from** **keras.layers** **import** Conv2D, MaxPooling2D
**from** **keras** **import** backend **as** 
**from** **vis.visualization** **import** visualize_activation
**from** **vis.utils** **import** utils
**from** **keras** **import** activations

**from** **matplotlib** **import** pyplot **as** plt
%matplotlib inline

为了创建模型,我们需要定义架构在本文中,我们不讨论如何创建模型架构您可以复制下面的命令来创建 MNIST 数据集的模型架构以及如何训练它。

batch_size = 32
num_classes = 10
epochs = 50

*# input image dimensions*
img_rows, img_cols = 28, 28

*# the data, shuffled and split between train and test sets*
(x_train, y_train), (x_test, y_test) = mnist.load_data()

**if** K.image_data_format() == 'channels_first':
    x_train = x_train.reshape(x_train.shape[0], 1, img_rows, img_cols)
    x_test = x_test.reshape(x_test.shape[0], 1, img_rows, img_cols)
    input_shape = (1, img_rows, img_cols)
**else**:
    x_train = x_train.reshape(x_train.shape[0], img_rows, img_cols, 1)
    x_test = x_test.reshape(x_test.shape[0], img_rows, img_cols, 1)
    input_shape = (img_rows, img_cols, 1)

x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
x_train /= 255
x_test /= 255

*# convert class vectors to binary class matrices*
y_train = keras.utils.to_categorical(y_train, num_classes)
y_test = keras.utils.to_categorical(y_test, num_classes)

model = Sequential()
model.add(Conv2D(32, kernel_size=(3, 3),
                 activation='relu',
                 input_shape=input_shape))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(num_classes, activation='softmax', name='preds'))

model.compile(loss=keras.losses.categorical_crossentropy,
              optimizer=keras.optimizers.Adam(),
              metrics=['accuracy'])

model.fit(x_train, y_train,
          batch_size=batch_size,
          epochs=epochs,
          verbose=1,
          validation_data=(x_test, y_test))

score = model.evaluate(x_test, y_test, verbose=0)

训练完这个模型后,现在让我们看看密集层可视化。

密集层可视化

*# Swap softmax with linear* layer_idx = utils.find_layer_idx(model, 'preds')
model.layers[layer_idx].activation = activations.linear
model = utils.apply_modifications(model)

*# This is the output node we want to maximize.*
fil_idx = 10
img = visualize_activation(model, layer_idx, filter_indices=fil_idx)
plt.imshow(img[..., 10])

密集层可视化(来源:作者)

激活最大化

img = visualize_activation(model, layer_idx, filter_indices=filter_idx, input_range=(0., 1.))
plt.imshow(img[..., 0])

激活最大化(来源:作者)

所以,在这幅图中,你可以清楚地看到,模型是如何知道这幅图是零的,但还是不清楚。接下来,我们将看到如何正则化权重,并使用激活最大化使其更加清晰。

img = visualize_activation(model, layer_idx, filter_indices=output_idx, input_range=(0., 1.))
plt.imshow(img[..., 0])

权重调整(来源:作者)

现在让我们想象所有类的激活最大化。

**for** output_idx **in** np.arange(2,5):
    img = visualize_activation(model, layer_idx, filter_indices=output_idx, input_range=(0., 1.))
    plt.figure()
    plt.imshow(img[..., 0])

(来源作者)

(来源作者)

(来源作者)

这就是你如何使用 Keras Vis 可视化你的深度学习模型。试试这个,让我知道你在回复部分的经历。

本文与 皮尤什 合作。

在你走之前

感谢 的阅读!如果你想与我取得联系,请随时通过 hmix13@gmail.com 联系我或我的 LinkedIn 个人资料 。可以查看我的Github*简介针对不同的数据科学项目和包教程。还有,随意探索* 我的简介 ,阅读我写过的与数据科学相关的不同文章。

低资源语言语法错误处理的深度学习模型

原文:https://towardsdatascience.com/deep-learning-models-for-grammatical-error-handling-in-low-resource-languages-2ac2c5d154f5?source=collection_archive---------32-----------------------

卡纳达语语法错误纠正个案研究

Unsplash 上由 Nikhita S 拍摄的照片

  1. 介绍
  2. 商业问题
  3. 映射到 ML/DL 问题
  4. 理解数据
  5. 数据处理
  6. 先决条件
  7. 结构
  8. 韵律学
  9. 部署
  10. 结论和未来工作
  11. 轮廓
  12. 参考

1。简介

语法(语言学)

中的 语言学中的 ,语法(来源于 古希腊语γραμματικήgrammatikḗ)中的一种 自然语言 是其套 结构上的 约束说话者或写作者的 从句 这个术语也可以指对这样的约束条件的研究,一个领域包括诸如https://en.wikipedia.org/wiki/Phonology词法 句法 之类的领域,通常由 语音学补充【维基百科】

缺乏大型单语或平行语料库和手工制作的语言资源的语言被称为低资源语言。在 NLP 中,与流行语言相比,这些语言很多,比如英语,它们有相对成熟的人工智能框架和工具。在这个案例研究中,我们认为卡纳达语是一种低资源语言。

卡纳达语(卡纳达语语法)

卡纳达语是印度西南部卡纳塔克邦人主要使用的一种语言。

语法是正确使用和推广语言的指南。卡纳达语语法是基于 Keshiraja 的“ S habdamanidarpana”(公元 1260 年)。除此之外,在“ K avirajamarga”和 Nagavarma II 的“ K avyalocana”和“ K arnataka Bhasha Bhushan”中提到了卡纳达语语法。

卡纳达语字母表中有 49 个字母。主要部分是

  1. Swaras + Yogavahagalu(元音)
  2. Vyanjana(辅音)
  3. Nama pada(名词)
  4. 克里亚帕达(动词)
  5. Sarvanama(代词)
  6. 林加语(性别)
  7. Vibhakti 和 Pratyaya(客体,主体)
  8. Tatsama 和 Tadbhava(梵语和本地语)
  9. 变调(复调)
  10. Samasa(复利)

卡纳达字母(作者图片)

2。商业问题

业务问题是,检测文本中至少 30%的语法错误,并在合理的周转时间和最佳的 CPU 利用率内纠正它们。在低资源设置中的 GEC 系统可以用作文字处理器、帖子编辑器以及作为语言学习者的学习辅助。

3。映射到机器学习问题

上述业务问题可以使用统计模型、基于规则的模型和神经机器翻译模型来解决。在这个案例研究中,我们实验了一种神经机器翻译方法。

框图(图片由作者提供)

我们这里使用的损失函数是稀疏分类交叉熵,这是使用标签和预测的损失计算。

4。理解数据

我们从 IndicCorp 收集的数据集是最大的公开可用的印度语言语料库之一。

我们通过运行 curl wget 小部件来提取数据集。

我们检查了使用 head 命令提取的文本文件的前几行。

作者图片

5。数据预处理

在数据预处理中,我们需要为数据集中的每条记录构建真实的和屈折的句子对。为简单起见,我们将把来自数据集的输入文本视为原始的正确(真实)句子。由此,我们需要构建错误的句子。为了构造错误的句子,我们需要对整个数据集进行标记,并通过一个词性标注器单独解析每个句子,以获得每个标记的实体。

我们使用 IndicNLP[ indicnlp ]库来标记我们的文本。我们将结果文件传递到 POS Tagger[ postagger ]中。我们得到了生成的令牌以及它们的 pos 标签。

作者图片

使用 python 中的 regex 和 dictionary,我们根据词性生成了每个句子的词形变化,并将它们存储在单独的 pickle 文件中。

产生拐点的另一种方法

我们安装了 inltk[ inltk ]库,然后使用 joblib 库和并行处理生成了原始句子的 3 个变形。这就像图像处理中的数据扩充。使用这种方法生成的句子,其中一些有屈折变化,但其他的保持不变。这种方法没有涵盖语法错误变化的所有功能点。因此,这种方法不能产生拐点。在以后的章节中,我们将讨论我们如何使用这种方法训练模型,而模型却失败了。

6。先决条件

本文的读者应该熟悉 Python 编程、机器学习和深度学习、TensorFlow 和构建数据驱动的应用程序的基础知识。

7。架构

有许多架构,在 Google Colaboratory 上对 30k 数据集进行了实验,CPU 作为硬件加速器用于数据集收集和预处理步骤,GPU 作为硬件加速器用于模型训练和预测。对于那些体系结构,语法错误处理一点也不令人满意。

最后,我们选择了 Bahdanau 的附加注意力,在 TensorFlow 博客中详细介绍了机器翻译。

我们在编码器层使用 BPEmb 来获得子词嵌入。我们分别训练了 3 个模型

  • 模式 1:句子的字数<= 6. The default parameters left as it is for the Adam optimizer. Without any regularization, the model seemed to overfit.
  • Model2: The number of words in sentence <= 6. The learning rate of the Adam optimizer was chosen to be 5e-5. We used an l2 regularizer for the Encoder Dense layer. The predictions were average on the validation dataset
  • Model3: The number of words in sentence > 6。Adam 优化器的学习速率被选择为 5e-5。我们对编码器密集层使用 l2 正则化。验证数据集上的预测也很好。

模型 1

我们已经训练了该模型,并且在 50 个时期内,快速获取的单批输入减少到零。因此,这是一个过拟合模型。

我们还对训练数据集中的少数记录进行了随机预测。错误被处理,但是那些从输入句子到输出没有变化的单词被随机预测。

训练预测(图片由作者提供)

验证预测(作者图片)

模型 2

我们已经训练了 500 个模型,并且很快地取得了不减少到零的单批输入。因此,该模型不是过拟合模型。然而,预测并不令人满意。这可能主要是由于输入数据集中的拐点数量较少,这是因为输入数据集中的拐点长度减少了。

模型 2 单批次损失(图片由作者提供)

验证数据集预测(图片由作者提供)

模型 3

我们已经训练了模型,整个批次的损失在 500 个时期内减少到零。因此,这是我们当前环境设置中的最佳模式。在翻译时,我们根据大部分句子长度将每个句子的最大长度限制为 10。但是该模型似乎忠实地纠正了它在给定时间点呈现的所有令牌,在较短的周转时间内实现了最佳的 CPU 利用率。

作者图片

验证数据集的预测(图片由作者提供)

8。指标

我们选择使用 BLEU 评分和 ROUGE-L 评分作为所有模型的性能指标。以下是所有模型的得分对比。

BLEU 分数比较(图片由作者提供)

以下是训练和验证数据集的所有三个模型的 rouge-l 分数。原始数据集的总大小为 30k。我们考虑在训练和验证集中随机抽取 100 个句子来计算 rouge-l 分数。下表总结了训练和验证数据集的 F1 分数。根据 f1 分数,我们可以得出结论,模型 3 在给定模型中表现最佳。

分数比较

9。部署

使用 TensorFlow API 将 translate 函数公开为 TensorFlow 中的服务。并且可以部署在 TensorFlow 服务器上。

以下链接加载了谷歌联合实验室中的预测演示。****

***https://drive.google.com/file/d/1YN-KYZkc-I9wM1-h8i7DABWX7ek9QczB/view?usp=sharing https://drive.google.com/file/d/1VOV9YmoZlH4JE8Sgm8LEG2jnXjK2dSTA/view?usp=sharing

10。结论和未来工作

我们可以得出结论,对于给定的设置,模型 3 在其余模型中表现最好。

我正在研究以下想法

  • 为错误变化生成更多的平行语料库和数据集
  • 超参数调谐更高级的语法概念,如短语和从句

11。轮廓

完整源代码可从 Githublink2 获得

如果您对以上任何方面有任何问题或建议,请通过 LinkedIn 与我联系

12。参考文献

用于头颈部器官分割的深度学习模型

原文:https://towardsdatascience.com/deep-learning-models-for-organ-segmentation-in-the-head-and-neck-region-35c0cac0657b?source=collection_archive---------52-----------------------

使用 MICCAI 2015 —头颈自动分割挑战赛的 CT 图像

克雷格·卡梅隆在 Unsplash 上的照片

放射治疗现在是治疗头颈部癌症的常用方法。为了确保健康的器官受到最小量的杀死肿瘤的辐射,需要将它们分段。由于在这个耗时的过程中存在注释者之间(即放射肿瘤学家之间的)的变化,所以需要对这种器官进行自动分割。这种变化导致辐射剂量的差异,并且计划时间要求导致治疗的延迟。

这篇文章将比较和评论不同的深度学习方法来自动分割这种处于危险中的器官(OAR)。我们将重点关注的模型开发领域如下

  • 数据预处理
  • 神经网络体系结构
  • 培训方法

资料组

Ref: Raudaschl 等人,“头颈部 ct 上分割方法的评估:2015 年自动分割挑战”。医学物理44.5(2017):2020–2036。

本次 MICCAI2015 —头颈部自动分割挑战赛由分为 4 类的 CT 扫描组成— 训练 (25 名患者)、训练 _ 附加 (8 名患者)、测试 _ 场外 (10 名患者)、测试 _ 现场 (5 名患者)。大多数方法将训练文件夹(25+8 = 33 名患者)与 test_offsite 文件夹上的测试相结合。这个数据集中有 9 个桨——1 个脑器官(脑干,3 个视觉器官(视交叉左&右视神经,1 个骨骼(下颌骨,4 个唾液腺(左&右腮腺,左&右颌下腺)。显示这些器官的形状和相对空间位置的视频可以在这里找到。该数据集的一些独特特征是

  • 下颌骨(下颌骨)非常容易分割(或用放射疗法术语),因为骨骼结构在 CT 图像中呈现出良好的对比度。
  • 视觉器官非常薄,仅出现在少数 CT 切片上。因此,由于它们的小 3D 结构,它们是最难自动注释的
  • 诸如脑干和唾液腺的其他器官也难以分割,因为 CT 图像具有较差的软组织对比度。人类甚至很难描绘它们,只有训练有素的专家(在其他形式的帮助下,如先生)才能这样做。
  • 图像似乎来自不同的扫描仪,因为它们在 x、y 和 z 轴上具有不同的体素分辨率。

图:MICCAI2015 数据集在 X、Y 和 Z 方向上的体素间距直方图

AnatomyNet

【参引:朱等,“AnatomyNet:深度学习实现头颈部解剖的快速全自动全体积分割”。2019 年医学物理学

图:解剖网络的神经架构(来自医学物理学

数据

与之前将大量医学体积(例如 CT 或 MR)作为 3D 补片或 2D 切片子集进行处理的方法不同,这项工作将裁剪后的 CT 体积( ~178 x 302 x 225 )输入到神经网络中。正常化 Hounsfield 单位也是惯例,但是没有提供这种预处理的指示。

神经架构

像大多数医学图像分割方法一样,本文也扩展了 3D UNet 神经结构。标准 3D UNet 的显著例外是编码器路径中的下采样块数。这是由于较小的视觉器官的存在,其在较低分辨率下会丢失空间信息。另一个修改是使用“剩余压缩和激励块,而不是标准卷积块。除了一般的“学习有效特性之外,不提供这些块的使用的具体说明。

损失函数

这项工作采用了 Dice 和病灶损失相结合的方法,其中单个器官的损失如果在特定患者数据中存在或不存在,则被掩盖。单个器官损失也基于它们在特定 3D 体积中的体素计数而被反向加权。

培训详情

训练使用批量大小 1,并且在训练之间从 RMSProp 优化器切换到随机梯度优化器。这些选择看起来很奇怪,因为通常情况下设置的最小批量至少为 2。由于该神经网络接受裁剪的 3D 体积,GPU 内存限制可能会阻止更高的批量大小。没有提供优化器变化的解释。对于数据扩充,作者使用仿射变换和弹性变形,尽管他们没有提供这一步的细节。这项工作使用了一个提供 24GB GPU 内存的 Nvidia Tesla P40。

评论

在我看来,这项工作很好地从经验上证明了额外的缩减像素采样图层对 MICCAI2015 数据集没有用。他们的消融研究将普通 3D UNet 及其变体与最终提出的网络进行了比较,为修改的贡献提供了见解。

然而,还有其他细节没有讨论,例如体素尺寸调整。在下载数据集时,我注意到体素间距在 x、y 和 z 维度上有很大的范围。标准做法是让它们达到一个共同的分辨率(以毫米为单位),然后对它们进行学习。在培训环境中,优化器在培训期间的变化是一个不寻常的设计选择,其好处尚未讨论。此外,由于 GPU 内存限制,使用的批处理大小为 1。我的观点是,作者应该在反向传播之前探索多个样本的梯度平均。

虽然论文没有提到官方代码库,但作者的 github 包含了一个用于 AnatomyNet 的库。

焦点网

参考:Kaul 等,“Focusnet:一种基于注意力的全卷积网络用于医学图像分割”。 2019 IEEE 第 16 届国际生物医学影像研讨会(ISBI 2019) 。IEEE 2019

图:FocusNet 的神经架构(来自 Springer )

数据

模型的输入是 3D CT 体积(如文本和相关图所理解的),但是没有提供关于体积尺寸或体积大小调整的信息。没有给出 Hounsfield 单位标准化的指示。作者还在私有数据集上独立训练他们的模型。

神经架构

这项工作采用了一种独特的方法,通过为较小的视觉器官引入一个专用分支来改进分割度量。具体来说,这个架构有三个主要组件——SNet(主分割网络)、SOLNet ( 小物体定位网络)和 SOSNet ( 小器官分割分支)。SNet 分割大器官,SOLNet 为较小器官的中点提供关键点(类似于基于深度学习的人类姿势估计),最后 SOSNet 使用 SNet 的 ROI 汇集特征(由 SOLNet 的输出引导)来分割较小器官。

与 AnatomyNet 类似,SNet 仅采用单个下采样操作,之后是挤压和激励模块(用于通道式注意力)。该架构的核心是复杂的卷积运算(denseapp【1】),有助于获得足够的感受野大小。SOLNet 是一个简单的网络,带有两个挤压和激励模块【2】,用于输出以较小光学器官中点为中心的 3D 高斯图。SOSNet 使用类似的架构来输出分割图。请注意,SOSNet 通过简单地裁剪掉大量背景来帮助管理前景和背景体素计数之间的不平衡。这里一个重要的设计选择是 SOSNet 的输出大小是三个小视觉器官的平均直径的因子(=3)。

损失函数

类似于 AnatomyNet,该工作也使用骰子和焦点损失的组合,不同之处在于仅焦点损失被加权,并且两种损失的贡献相等。在这里,重量与每个器官的平均大小成反比。骰子损失既不加权也不掩盖。

培训详情

没有提供关于训练批次大小、优化器、学习率计划和训练时期的信息。读者也不知道所使用的 GPU。

评论

这项工作通过为较小的视觉器官引入级联结构来改进 AnatomyNet。DenseASPP 模块总体上并没有改进 FocusNet 的架构(论文中的表 3),所以它的优势并不明显。错过的改善指标的机会可能是没有使用加权和屏蔽的骰子损失。该白皮书还遗漏了重要的实施细节,如卷大小调整、卷大小和培训细节。

没有提供官方代码库。

分层网络

参考:郭等,“利用分层学习和神经结构搜索进行头颈癌高危器官分割”。IEEE/CVF 计算机视觉和模式识别会议论文集。2020.

图:分层网络的神经架构(来自 CVF

数据

为了训练,作者使用(128,128,64)的子体积,并应用[-500,1000] Hounsfield 单位的窗口。为了从整个 ct 体积中提取子体积,要么使用以器官为中心的子体积,要么使用来自 CT 其余部分的随机样本。他们通过在 0.8 到 1.2 的比率之间随机缩放来执行缩放增强。为了测试,以(96,96,32)的步幅提取类似大小的子体积,并在相交区域对概率图进行平均。没有提供有关卷大小调整的信息。

所提出的方法也用于私有数据集中 42 个桨的自动分割。

神经架构

由于 CT 图像具有较差的软组织对比度,临床医生在解剖标志的基础上定义轮廓指引[4]。这项工作从临床实践中获得灵感,在预定义分类的基础上一步一步预测器官轮廓。这是从整体分割(解剖网或检测分割(聚焦网)的彻底转变。因此,首先预测下颌骨、脑干和眼睛等器官,这样它们可以作为预测中级或小而硬(S & H)类别中其他器官的锚。这些锚定器官在所有器官中具有最好的对比度,因此容易预测。对于 S & H 器官,他们使用与 FocusNet 检测中心位置相似的策略。执行这种分类的主要原因是为了在由 42 个桨组成的私有数据集上实现简单的神经网络优化(或学习)。3D P-HNN [3]网络被用作所有三个类别的基础。

在这种分类之上,这种神经架构还利用神经架构搜索(NAS)来为每个类别寻找 3D P-HNN 中卷积块的最佳组合。

*这个神经架构的名字是本帖作者给的。

图:便于预测的桨的分类(来自 CVF

损失函数

仅使用骰子损失来训练前述分割模型,并且使用 L2 损失来训练检测分支。

培训详情

整流 Adam 优化器的动量为 0.9 ( 默认值)。在 NAS 输出固定架构后,使用 12(NVIDIA Quadro RTX 8000 = 48GB GPU 内存)的批量和 0.01(锚和中级分支)和 0.0005 (S & H 分支)的初始学习速率。最初,只训练锚分支。然后它被冻结,中级和 S & H 分支被训练相同数量的时期。最后对整个模型进行微调。这篇文章不会深入探讨 NAS 的细节。

评论

就方法而言,本文作者似乎采用了一种合理的方法,解释了分层方法和 NAS 方法的贡献。在算法中复制临床实践肯定有益于最终结果,因此是一个值得称赞的想法。

这种方法的一个缺点是,他们没有报告甚至没有讨论不同随机种子的结果,这可能导致他们附录中不同的初始化。此外,批量大小为 12 以及神经架构的多个模块意味着他们利用了大量内存的 GPU 进行训练。推理也可能对 GPU 提出很高的要求,尽管在放射治疗等高级医疗选择中,这可能不是临床实践中实现的瓶颈。

没有提供官方代码库。

DeepMindNet

参考:斯坦尼斯拉夫斯基等人。"深度学习以实现用于放射治疗的头颈部解剖结构的临床可应用的分割." arXiv 预印本 arXiv:1809.04430 (2018)。

图:DeepMindNet 的神经架构(来自 Arxiv )

数据

这项工作将具有全平面尺寸(H,W)的体积和相邻轴向切片的子集(相同尺寸输出的 d

Neural Architecture

Unlike the works studied above, this method choses to downsample the inputs, though they do not include the optic chiasm in their private dataset. Each downsampling block is a combination of a series of 2D convolutions ()以及 3D 深度方向可分离卷积作为输入。这些卷积的输出以残差块的方式与输入相加。上采样块仅包含一系列 2D 卷积。在下采样分支(即编码器和上采样分支(即解码器)之间,存在具有残差类型子块的全连接层。

*这个神经架构的名字是由本帖作者而非原作者给出的。

损失函数

打破常规,这种方法使用交叉熵损失,它只惩罚每个 OAR 遮罩的前 k%的损失值,并惩罚那些像素。作者声称,这导致了更快的训练,并有助于减轻班级不平衡的问题——例如视觉器官。

培训详情

Adam 优化器在初始学习率为 0.0001 的范围内使用,然后不断缩小。一批 32 个(好!)跨 32 个 GPU 使用(OMG!!)并用同步 SGD 对模型进行训练。

评论

这项工作更侧重于强调医学图像分割基准中使用的标准 DICE 度量如何不准确,而是提出了一种表面 DICE 度量。作者没有关注他们的神经架构背后的理由,读者只能假设他们为什么做出某些架构选择。

与其他工作相比,使用这项工作的结果较低,因为它是在使用不同 OAR 轮廓绘制方法的私有数据集上训练的。

*这项工作也没有考虑视交叉,因为它需要与 MR 图像进行图像配准以获得可接受的轮廓。

韵律学

除了报告其他人所做的标准骰子分数之外,这项工作建议使用表面骰子。该度量考虑两个 2D 表面的重叠,而不是 3D 体积。这具有临床应用,因为调整轮廓的表面(由有经验的放射治疗师/肿瘤学家)是应用人类专业知识的地方。引用文件:—

例如,两个不准确的分割可能具有相似的体积 DSC 分数,如果一个在许多地方偏离正确的表面边界很小的量,而另一个在单个点具有大的偏离。纠正前者可能需要相当长的时间,因为它需要重新绘制几乎所有的边界,而后者可以更快地纠正,可能只需一次编辑操作。

概观

MICCAI 2015 —测试结果

MICCAI2015 数据集的 10 幅测试图像的骰子得分

方法比较

建模选择的比较

文学中的空白

上面讨论的研究通常以下列之一作为输入:-

  • 具有全平面和轴向背景的裁剪 CT 体积,即存在所有器官(例如 AnatomyNet、FocusNet)
  • 具有预定义轴向背景但全平面背景的裁剪 CT 体积(例如 DeepMindNet)
  • 或者具有减少的轴向和面内背景,但是附加的锚定器官背景(例如,分层网)的裁剪的 CT 子体积

这两部作品都没有讨论获得临床上可接受的指标所需的环境的影响。因此,需要深入研究如何在内存受限的 GPU 上更容易地进行神经网络训练。这将转化为在数据集(如 MICCAI2015)上使用不同子体积大小的实验,甚至是使用额外 oar 的私有数据集。

一个重要的贡献也将是引入额外的基准数据集,如在 StructSeg,2019 中引入的数据集。

结论

这篇文章分析了在人体头颈部放射治疗环境中对有风险的器官进行自动分割的不同方法。miccai 2015-头颈分割挑战用作基准数据集,以了解上述方法的性能差异。带回家的信息是:-

  1. 尽管 UNets 建议在编码器分支中进行下采样,但这种方法可能会对骰子分数产生负面影响。
  2. 检测分割已经广泛用于分割较小的器官。
  3. 理解放射治疗的临床工作流程对于创建新的神经架构和有用的度量是有用的。

最后,本文讨论了文献中的一些不足之处,希望能引发这一领域未来的思考。

参考

[1]杨等.【Denseaspp】用于街道场景中的语义分割。《IEEE 计算机视觉和模式识别会议论文集》。2018.

[2]胡等.【挤激网络】。IEEE CVPR,2018。

[3] Adam 等.“用于从 CT 图像中进行病理性肺部分割的渐进和多路径整体嵌套神经网络”医学图像计算和计算机辅助介入国际会议。施普林格,查姆,2017。

[4]Brouwer et al .“对放疗中有风险的头颈部器官进行深度学习轮廓绘制后,在临床实践中执行的手动调整的评估”放射肿瘤学中的物理学和成像 16(2020):54–60。

预算上的深度学习:这家初创公司的表现优于谷歌 Colab 吗?

原文:https://towardsdatascience.com/deep-learning-on-a-budget-does-this-startup-outperform-google-colab-22b102827b55?source=collection_archive---------6-----------------------

Google Colab 在提供免费协作笔记本电脑方面占据了统治地位,但也有竞争对手准备弥合这一差距

卡斯帕·卡米尔·鲁宾在 Unsplash 上的照片

Paperspace 是一家成立于 2014 年的创业公司,于 2018 年推出了 ML 笔记本平台 Gradient,自那以来,它已经成为一个定期更新的大型平台。它拥有面向所有人的免费 GPU,其免费实例拥有 8 个 CPU 的 30 GB CPU RAM 和 8 GB RAM 的 NVIDIA Quadro M4000。为了使其与消费级 GPU 保持一致,它的性能大约相当于 GTX 1050Ti,RAM 是大型 ML 应用的两倍。他们还有一个 8 美元/月的个人计划,免费提供一台英伟达夸德罗 RTX 4000 (大约是英伟达 RTX 2060)。理论上,与 Google Colab 提供的相比,这一点非常好!

我之前写过这篇文章,深入探讨了 Google Colab 与标准消费级 GPU 的比较,概括来说,Colab 将分配一个 NVIDIA Tesla P100、T4 或 K80,与 NVIDIA RTX 2080、GTX 1070 或 GTX 960 进行比较,所有这些都具有超过 12 GB 的 RAM。乍一看,平均来说,这似乎是更强的计算能力。然而,你使用的资源越多,你越有可能只被分配到一个 K80。在我广泛使用计算资源的 15 次试验中,我只有 33%的时间被分配到比 K80 更好的 GPU。

为了测试这些平台,我使用了 AI 基准,这是一个 python 库,它利用 Tensorflow 在 19 个域中运行 42 个独特的 ML 任务,为 GPU 的性能提供了一个很好的广义 AI 分数。分数越高,意味着 GPU 执行任务的速度越快。结果分为训练分数、推理(测试)分数以及被认为是人工智能分数的组合。

因为 Gradient 每次都给出相同的 GPU,所以我运行了 5 次 AI Benchmark,在每次运行之间重新启动实例。使用 Google Colab,我运行了 15 次 AI 基准测试,以正确捕捉所提供的 GPU 中的差异。结果如下:

最终得分

这对于梯度来说看起来不太好,但是结果并没有看起来那么糟糕。是的,Google Colab 在平均分数上比 Gradient 高(10773 比 6861),但 Gradient 有显著的优势,包括性能的标准偏差低得多(只有 333 比 1637),这表明您可以期待相同的程序以一致的运行时和规格运行。然而,如果您使用它进行开发,并且只关心 Jupyter 笔记本的速度,那么在大多数情况下,Colab 显然会胜出。

其他平台差异

当然,速度不是一切,在选择平台时,您的开发环境也很重要。Gradient 比 Colab 更有优势,例如能够选择超时时间,并且拥有一个围绕部署 Jupyter 笔记本电脑即服务的生态系统(更高级的选项)。这些都不在 Colab 的范围内,谷歌将把你送到他们的 GCP 高级解决方案, Vertex AI Workbench 以获得类似的可定制性和现成的渐变。

但是,还有很多缺点是我用 Colab 没有体验过的。第一个限制是一次只能运行 1 台笔记本电脑(免费版),平台上总共只能运行 5 台。这对于从事各种项目的人来说并不理想。这是我个人的看法,但我没有发现他们的 Jupyter 编辑器直观。当一个单元格被点击进入时,Gradient 会自动将该单元格移动到页面的顶部,这在几乎所有情况下都会导致我失去对我试图查看的内容的跟踪,没有办法禁用该功能。幸运的是,它们包括一个在标准托管 Jupyter 实例中打开笔记本的选项,这个特性我非常欣赏!最后,有许多随机错误,从身份验证错误到实例不能按需提供。在大多数情况下,刷新我的登录可以解决这个问题,而且这些问题将不可避免地得到解决,但是我不能说它们没有降低用户体验。

结论

就目前而言,Colab 在大多数领域都独占鳌头。只要工作是实验性的(比如家庭项目),还没有准备好部署,Colab 几乎在每个领域都胜过 Gradient。然而,Gradient 是一个正在崛起的竞争对手,它为谷歌的对手提供了一个很好的环境。这也让人感觉 Gradient 试图与 Vertex AI WorkbenchAWS Sagemaker 竞争,同时仍然试图通过易于设置的笔记本实例吸引 Colab 观众。出于这个原因,我将坚持使用 Colab 来完成我的大部分工作,但会关注 Gradient 的进展!

如果你喜欢这篇文章,请随时订阅,查看我的推荐页面,查看这篇文章,在那里我升级了我的旧笔记本电脑以处理现代的 ML 工作负载,或者捐赠以便我可以测试一些新的 ML 设备!

人类微生物组的深度学习

原文:https://towardsdatascience.com/deep-learning-on-human-microbiome-7854fba815fc?source=collection_archive---------20-----------------------

生命科学的深度学习

从 DNA 序列推断样品的微生物组成

图片来源:人类微生物组项目门户

这是我的专栏 生命科学的深度学习 的第九篇文章,我试图展示将人工神经网络应用于计算生物学和生命科学的真实世界项目的具体例子。之前,我们介绍了深度学习在古代 DNA单细胞生物学数据整合临床诊断显微成像中的一些应用,以及一些从自然语言处理(NLP)中推断现代人类基因组中尼安德特人渗入区域的技术(此处为和此处为)。在本文中,我们将了解为什么人类微生物组代表生物学中的大数据****,以及如何训练一个卷积神经网络(CNN)** 分类器 用于 预测一个 宏基因组学 样本 起始于 中的微生物组成**

宏基因组学作为大数据

不幸的是并不直接开始为生物生物医学应用开发机器学习模型,在我看来是因为缺乏数据。我在之前的帖子中讨论了一些挑战,我们在生命科学中有大数据吗?。在那里,我提到了生命科学中的三个方向,它们似乎对人工智能和机器学习很有前景,因为它们似乎有足够的数据量,它们是:

  1. 单细胞组学
  2. 显微成像
  3. 将序列视为统计观察的基因组数据

后来在评论中 Mikael Huss 建议将宏基因组学微生物组数据作为第四大数据资源。事实上,人们可以找到大量公开可用的宏基因组学数据,例如,使用伟大的 EMBL-EBI 资源管理公司

图片来源:EMBL-EBI 微生物组数据资源管理中心

宏基因组学之所以能被称为大数据,是因为相对便宜的 鸟枪测序 ,因此成千上万的样本被测序,以及宏基因组学数据相对低维的性质。事实上,将测序的 DNA 片段映射到已知的微生物生物体通常会导致 500–1000 个可靠地检测到微生物,例如,与具有数百万维的遗传变异甲基化数据相比,这并不是真正的高维数据。

使用 SourceTracker 的微生物组成

记住宏基因组学开发机器和深度学习算法提供了大量数据,在这篇文章中,我将尝试训练一个卷积神经网络(CNN),它可以估计给定样本中微生物群落的来源。例如,从我办公室的桌子上取一份拭子样本,我期望在那里找到哪种微生物?它们会不会像我的皮肤** 微生物群,或者可能是我嘴里的口腔微生物?这个可以用一个叫source tracker的奇妙软件来估算。**

骑士T21【Nat 方法】8、761–763(2011)

简而言之, SourceTracker 是一种贝叶斯版本的 高斯混合模型(GMM) 聚类算法(看起来类似于 狄氏多项混合 ),它是在称为的参考数据集上训练的,即不同类别,例如土壤或人类口腔或人类肠道微生物群落等,并且可以估计每个源在称为的测试样本中的比例/贡献因此,SourceTracker 算法明确地将接收器样本建模为源的混合。算法的贝叶斯味道来自于在拟合模型时使用 Direchlet 先验

最初,SourceTracker 是针对 16S 数据开发的,即仅使用 16S 核糖体 RNA 基因 。相比之下,这里我们将尝试使用https://en.wikipedia.org/wiki/Shotgun_sequencing****宏基因组学 数据来训练一个分类器。此外,SourceTracker 并非设计用于原始宏基因组序列,而是需要以某种方式量化的微生物丰度( OTU 丰度),例如通过qime管道、meta plan 2Kraken2 。相比之下,我们将在这里训练的 CNN 分类器的目标是从** fastq 文件 预测宏基因组样本的微生物组成,而不量化微生物丰度。******

人类微生物组项目(HMP)数据

为了训练 CNN 分类器,我们将利用巨大的 人类微生物组项目(HMP) 数据资源。HMP 提供了用meta plan 2量化的宏基因组分类丰度,可以从这里下载。

人类微生物组项目(HMP)门户

4 人类 组织 (微生物群落): 口腔、肠道、皮肤和阴道计算宏基因组学概况。下面,我们将使用微生物丰度矩阵来选择组织特异性细菌 ,即仅在四种组织中的一种中丰富的菌群,因此可以作为人体组织的微生物制造者。稍后,我们将使用组织特异性细菌属的参考基因组来训练 CNN 分类器 fastq 文件 中的原始序列中识别微生物群落(口腔、肠道、皮肤、阴道)。我们将从读取微生物丰度矩阵开始,并通过降维图( PCAtSNE )可视化来自 4 个人体组织的样本。

作者图片

作者图片

在 PCA 和 tSNE 图中,我们可以看到,就微生物丰度而言,样品可以通过原始组织清楚地分开。这意味着训练 CNN 分类器应该是非常简单的,它可以通过检查样品中的微生物 DNA 序列来预测给定样品的来源组织。然而,为了制作 PCA 和 tSNE 图,我们使用了微生物丰度而不是测序数据本身,因此我们必须首先提取能够最好地分离肠道、口腔、皮肤和阴道样品的微生物。来自最具鉴别能力的微生物的参考基因组将在稍后用于为 CNN 分类器创建序列的训练数据集。

选择组织特异性微生物

为了选择能够最好地分离肠道、口腔、皮肤阴道样本的微生物,我们可以训练例如随机森林分类器,并查看特征重要性及其作用方向。然而,这里看起来有大量的组织特异性微生物,即在一个组织中丰度很高但在所有其他组织中几乎为零的微生物。例如,如果我们观察副溶血性嗜血杆菌在微生物丰度数据框架中的指数为 1950,那么看起来非常具有口腔特异性:****

作者图片

下面,为了简单起见,我们将只集中在 细菌微生物 上,即古菌病毒将被忽略,只有在 HMP 数据集中分类在 属级 上的细菌生物将被保留用于进一步分析。我们将建立组织特异性细菌属的列表,并将它们的名称用于、来自ref seq NCBI数据库的“grepping”细菌参考基因组。因此,这里我们将微生物丰度的总矩阵细分为细菌属丰度,我们可以看到在 HMP 项目中有 227 个细菌属。接下来,我们将检查所有 HMP 细菌属,并按照简单标准建立口腔-、 皮肤-、 阴道-肠道特异性属的列表:如果一个细菌属在一个组织中的比所有其他组织多 10 倍,则该属被认为是组织特异性的。

组织特异性的简单标准为我们提供了 61 种口腔特异性、53 种肠道特异性、49 种皮肤特异性和 16 种阴道特异性细菌属。让我们从 4 种组织中选择一些组织特异性属,并观察其丰度:****

作者图片

上面,我们可以清楚地看到,我们设法挑选了非常强的组织特异性细菌属标记。阴道的最少,为 16 个组织特异性属。然而,仔细观察,可以发现其中包括伯克霍尔德菌属、罗尔斯顿菌属、博德特氏菌属等可疑且极有可能是 PCR 试剂污染物 。因此,我们仔细检查了 16 个阴道特异性细菌属的列表,由于不同的原因,我们可以确信其中只有 12 个具有阴道特异性。因此,为了在用于分类分析的组织之间保持平衡,我们将为 4 种组织中的每一种选择 12 种最具组织特异性的标记,这里是我们挑选的细菌属:****

作者图片

经过一番思考,我决定将** 链球菌 排除在口腔特有属列表之外。尽管链球菌属似乎是口腔特有的,但它也包括在其他组织如肠道中大量存在的种类。这可能会混淆 CNN 分类器,因为如果我们 grep 链球菌的参考基因组,我们将会得到太多来自肠道特异性链球菌物种的“污染”序列,然而如果假设链球菌是口腔特异性属,则会得到错误的口腔标签。请在本文的完整笔记本中查看更多详细信息。**

我们可以检查选择的微生物属可以相当好地分离口腔、肠道、皮肤和阴道样品。为此,让我们基于样品之间的【Spearman】相关性距离并使用 48 个选定的微生物属(4 个组织中的每一个 12 个)来运行快速聚类。****

作者图片

我们清楚地观察到对应于来自 HMP 项目的口腔、肠道、皮肤和阴道样品的 4 个集群。最大的聚类是口腔样本,而第二大聚类对应于肠道 HMP 样本。

准备数据和训练 CNN 分类器

现在我们将使用所选的 48 个组织特异性细菌属的名称,从 RefSeq NCBI 数据库中提取所有相应的物种和菌株参考基因组 id。下面的片段演示了如何下载和提取与 48 个挑选的组织特异性属相对应的组织特异性物种和菌株的参考基因组 id。为此,我们将使用一个名称-引用-id 匹配文件 MapBactName2ID.txt ,可以从 my github 下载。该文件是通过提取参考基因组的标题并将它们的文件名(GCF-id)与标题匹配而构建的。

现在,当我们有了对应于组织特异性属的参考基因组(fasta-files)id时,我们可以切片参考基因组并创建 4 组序列(例如 80 nt 长的),每组对应于口腔、肠道、皮肤和阴道微生物属的标签为 0、1、2 和 3。在下面的循环中,我们首先为 4 个组织中的每一个读取带有**fasta id的文件,然后为每个 fasta id 读取 fasta 文件并选择长度为 80 nt 的随机 3000 序列。在运行过程中,我们还将删除包含 N、H、M 和其他非规范核苷酸的序列,并将我们自己限制为仅包含 A、C、T 和 G 的序列。******

一旦我们创建了一个标记序列的数据集,其中每个序列都有一个对应于口腔、肠道、皮肤和阴道的标签 0、1、2 或 3,我们就必须将这些序列转换为 one-hot-encoded tensor (3 维 numpy array) ,它可以被深度学习算法(如 1D CNN)读取。接下来,我们还将把一个热编码的序列分成训练和 测试 子集。

最后,让我们写下一个简单的 1D CNN 架构,并开始训练分类器识别对应于口腔、肠道、皮肤和阴道微生物群落的 4 个类别的序列模式。

作者图片

作者图片

检查网络是否已经学会对序列进行分类的最佳方式是在新的测试集上评估其性能,该测试集由它在训练期间根本没有观察到的数据组成。这里,我们评估测试集上的模型,并将结果绘制为混淆矩阵

作者图片

作者图片

混淆矩阵的图形表示是蓝色的热图,展示了一种块状 结构,暗示我们的 1D CNN 分类器能够相当好地区分 4 种微生物类别。60% 的总体平均评估准确度乍一看似乎很低,因为我们的思维集中在一个二进制分类问题上,其中一个随机分类器可以给出 50%的基本准确度。因此,我们 60%的结果可能比随机分类器好一点点。但是,请记住我们在这里处理的是**的** ,因此一个随机分类器应该给我们 25%** (可以通过模拟来确认,此处未显示)的平均准确度,根据样本大小的不同,的标准偏差约为 5-10%。因此, 60%的准确度明显高于随机分类器预期的基础 25%** 。此外,下面我们将使用经过训练的分类器,通过从数以千计的 DNA 序列中对预测 进行平均,获得微生物群落对宏基因组样本贡献的粗略估计。假设分类器的 60%的准确性允许对大多数序列进行正确的预测,即使不是所有的序列都会被正确分类,这仍然会给我们一个很好的直觉关于样品来自什么微生物群落(口腔、肠道、皮肤或阴道)。********

预测微生物的组成

在这里,我们将检查经过训练的 CNN 分类器是否可以用于推断随机宏基因组样本的微生物组成。为此,我们将挑选随机宏基因组 fastq 文件(来自 HMP、 MGnifyDIABIMMUNE 数据库),对每个宏基因组序列进行预测,并呈现分配给四个类别(口腔、肠道、皮肤和阴道)的序列的部分,这将大致对应于每个样品中存在的微生物群落的部分(微生物组成)。让我们从 HMP 项目的几个样本开始。我知道我们使用 HMP 丰度来选择组织特异性微生物标记(我们没有使用原始测序数据,尽管),使用 HMP fastq 文件来推断它们的微生物组成可能会有偏差。然而,这是一个好的开始,至少如果 CNN 分类器在 HMP 样本上失败,很难期望它在独立样本上表现良好。稍后,我们将使用来自 HMP 项目以外的真正独立的宏基因组样本来重复这一推论。在下面的循环中,我读取了 HMP fastq-files (我从口腔、肠道(粪便)、皮肤和阴道拭子中随机选取了 2 个样本, one-hot-encode 它们的序列,并使用训练过的 CNN 分类器运行预测。接下来,我选择最可靠的预测,其中一个微生物群落有至少 80%的概率。最后,我绘制了分类器分配给每个微生物群落的序列片段。

作者图片

作者图片

我们可以看到,对于每个随机 HMP 样本,我们都得到了相当好的预测,即前两个看起来很像口腔样本,因为口腔微生物(蓝条)构成了大多数微生物群落,而后两个看起来像肠道样本等。标签“口服 _”、“肠道 _”等。对于上图底部的每个样本,指出在 HMP 项目中收集样本的真实组织

总之,我们使用 HMP 项目中不同组织中丰富的微生物参考基因组序列训练了一个 CNN 分类器。之后,我们继续在几个随机的 HMP 样本上评估模型。你大概可以在这里看到一个可能的问题。一方面,当训练 CNN 分类器时,我们没有使用来自 HMP 样本的原始序列,而是使用 HMP 数据中最丰富的属的参考基因组。另一方面,仍然有一个信息泄露,因为我们仍然使用相同的项目(尽管不同类型的数据)进行训练和测试。因此,评估可能仍然有偏见,看起来好得不真实。为了进行更好的评估,我们将从宏基因组学项目中随机挑选 8 个与 HMP 无关的口腔、肠道、皮肤和阴道样本。

现在,我们将对一些与 HMP 样品不同的宏基因组样品进行微生物组成推断。粪便/肠道样本可以从 糖尿病 e 项目中获取,这里是文件口腔宏基因组样本从 WGS 口腔微生物组 项目下载,这里有文件出版物皮肤样本从 MGnify 资源下载,该资源由 EBI 提供,来自项目“农村和城市环境中儿童和青少年的皮肤微生物群模式不同”,文件可从此处获得。阴道拭子样本在 MOMS-PI 项目中排序,可以从这里检索。

我们将对非 HMP 样本应用与上述 HMP 样本相同的循环,只有一处不同。我们需要始终控制在应用概率截止值(这里是 90%)后,我们仍然得到足够的序列来计算微生物群落的比例。这里我要求,如果我们没有至少 500 个序列(这对于一些随机的非 HMP 样本是真实的,因为它们的测序深度低),概率阈值将从 0.9 降低到 0.6。

作者图片

作者图片

在这里,我们再次看到对 8 个非 HMP 样本中的微生物组成的预测与样本所来自的真实口腔、肠道、皮肤和阴道微生物群落相当一致。干得好!我们训练过的 CNN 分类器可能可以对任何给定样品的微生物组成提供有意义的估计。

摘要

在本文中,我们了解到宏基因组学代表了一种适用于机器和深度学习分析的大数据。我们利用了来自人类微生物组项目(HMP) 的宏基因组学数据,并开发了一个 1D CNN 分类器,该分类器可以从标准 fastq 数据格式的原始序列开始,成功预测不同微生物群落(口腔、肠道、皮肤或阴道)对给定样本的贡献,而无需对微生物丰度进行量化。与使用 SourceTracker 的标准微生物组成推断相比,该方法可能具有优势。

像往常一样,让我在评论中知道你最喜欢的生命科学领域,你希望在深度学习框架内解决这个问题。在 Medium 关注我,在 Twitter @NikolayOskolkov 关注我,在 Linkedin 关注我。完整的 Jupyter 笔记本可以在我的 github 上找到。我计划写下一篇关于如何用深度学习及时预测人口规模的帖子,敬请关注。

超级计算机上的深度学习

原文:https://towardsdatascience.com/deep-learning-on-supercomputers-96319056c61f?source=collection_archive---------17-----------------------

理解大数据

关于如何在 BSC 的 CTE-Power 集群中扩展深度学习应用的实践

(图片来自 bsc.es )

这篇文章将作为 PATC 课程 大数据分析简介BSC的文档

之前的帖子中,我们展示了超级计算机是人工智能进步的关键组成部分,过去几年推动有效计算变化的是算法的并行化和分布的增加。

这篇文章将展示如何使用这些超级计算机;特别是 BSC 的 CTE-POWER 集群,因为每台服务器都有两个 CPUs IBM Power9 和四个 NVIDIA V100 GPUs。

在这一系列的帖子中,我们将使用 TensorFlow 框架;不过py torch 代码中的代码并没有太大区别。我们将使用 Keras API,因为自从 Tensorflow 2.0 发布以来,tf.keras.Model API 已经成为构建神经网络的主要方式,尤其是那些不需要定制训练循环的神经网络。

1 — BSC 的 CTE 电力集群

1.1 系统概述

CTE-POWER 是一个基于 IBM Power9 处理器的集群,拥有 Linux 操作系统和 Infiniband 互联网络。CTE 电力公司有 54 台计算服务器,每台都:

  • 2 个 IBM Power9 8335-GTG @ 3.00GHz (20 个内核和 4 个线程/内核,每个节点总共 160 个线程)
  • 512GB 主内存分布在 16 个 dimms x 32GB @ 2666MHz 中
  • 2 块固态硬盘 1.9TB 作为本地存储
  • 2 个 3.2TB NVME
  • 4 个 GPU NVIDIA V100 (Volta),带 16GB HBM2。
  • 单端口梅兰诺克斯 EDR
  • 通过一条 10 千兆位光纤链路连接 GPFS
  • 操作系统为红帽企业版 Linux Server 7.4。

超级计算机 Marenostrum——巴塞罗纳超级计算中心的 POWER-CTE 集群(图片由作者提供)

有关其特性的更多详细信息,可在 [CTE-POWER 用户指南](http://More details of its characteristics can be found in the user's guide and also in the information of the manufacturer of the ACXXX servers)以及 AC922 服务器制造商的信息中找到。

为执行我们的代码从集群中分配资源将从使用您的帐户的一个登录节点在集群中进行ssh登录开始:

$ssh user@loginnode.bsc.es

1.2 热身示例:MNIST 分类

为了方便起见,我们将考虑与之前在 Jupyter 笔记本中编程的前一类中用于分类 MNIST 数字的神经网络相同的神经网络:

import tensorflow as tf 
from tensorflow import kerasimport numpy as np
import matplotlib.pyplot as plt
print(tf.__version__)from tensorflow.keras import Sequential
from tensorflow.keras.layers import Conv2D
from tensorflow.keras.layers import MaxPooling2D
from tensorflow.keras.layers import Dense
from tensorflow.keras.layers import Flattenmodel = Sequential()
model.add(Conv2D(32, (5, 5), activation=’relu’, 
          input_shape=(28, 28, 1)))
model.add(MaxPooling2D((2, 2)))
model.add(Conv2D(64, (5, 5), activation=’relu’))
model.add(MaxPooling2D((2, 2)))
model.add(Flatten())
model.add(Dense(10, activation=’softmax’))
model.summary()from keras.utils import to_categorical
mnist = tf.keras.datasets.mnist(train_images, train_labels), (test_images, test_labels) = mnist.load_data(path=’/gpfs/projects/nct00/nct00002/basics-utils/mnist.npz’)train_images = train_images.reshape((60000, 28, 28, 1))
train_images = train_images.astype(‘float32’) / 255test_images = test_images.reshape((10000, 28, 28, 1))
test_images = test_images.astype(‘float32’) / 255train_labels = to_categorical(train_labels)
test_labels = to_categorical(test_labels)model.compile(loss=’categorical_crossentropy’,
              optimizer=’sgd’,
              metrics=[‘accuracy’])model.fit(train_images, train_labels, batch_size=100, 
          epochs=5, verbose=1)test_loss, test_acc = model.evaluate(test_images, test_labels)print(‘Test accuracy:’, test_acc)

这将是代码MNIST.py(可在 GitHub 获得),我们将使用它作为第一个案例研究来展示如何在 CTE 超级计算中启动程序。

1.3 软件堆栈

重要的是要记住,我们需要加载构建应用软件栈环境的所有模块。在运行相应的.py代码之前,可以用命令module load来完成。

在我们的案例研究中,我们需要包含所需库的以下模块:

**module load** gcc/8.3.0 cuda/10.2 cudnn/7.6.4 nccl/2.4.8 tensorrt/6.0.1 openmpi/4.0.1 atlas/3.10.3 scalapack/2.0.2 fftw/3.3.8 szip/2.1.1 ffmpeg/4.2.1 opencv/4.1.1 python/3.7.4_MLpython MNIST.py

如果我们想要分离标准输出标准错误消息,我们可以添加这个参数2>err.txt:

python MNIST.py 2>err.txt

重定向标准错误允许我们看到训练的结果,该结果通过标准输出给出 Keras,而没有与执行环境相关的信息;

Epoch 1/5
600/600 [======] - 2s 3ms/step - loss: 0.9553 - accuracy: 0.7612
Epoch 2/5
600/600 [======] - 1s 2ms/step - loss: 0.2631 - accuracy: 0.9235
Epoch 3/5
600/600 [======] - 2s 3ms/step - loss: 0.1904 - accuracy: 0.9446
Epoch 4/5
600/600 [======] - 2s 3ms/step - loss: 0.1528 - accuracy: 0.9555
Epoch 5/5
600/600 [======] - 2s 3ms/step - loss: 0.1288 - accuracy: 0.9629
313/313 [======] - 1s 2ms/step - loss: 0.1096 - accuracy: 0.9671Test accuracy: 0.9671000242233276

嗯,我们的代码是在 login 节点中执行的,该节点与来自试图向 SLURM 系统提交作业的用户的其他作业共享,但是我们真正需要的是为我们的代码分配资源。怎么才能做到呢?

1.4 如何使用 SLURM 分配计算资源

为了在 CTE-POWER 中运行代码,我们使用了一个 SLURM 工作负载管理器。这里有一本非常好的快速入门用户指南。我们有两种方法来使用它:sbatchsalloc命令。

提交工作的方法我们将直接使用 SLURM sbatch命令。sbatch向 Slurm 提交一个批处理脚本。批处理脚本可以通过命令行上的文件名(.sh文件)交给sbatch。批处理脚本可能包含在脚本中任何可执行命令前带有#SBATCH的选项。一旦到达脚本中的第一个非注释非空白行,sbatch将停止进一步处理#SBATCH指令。

sbatch脚本成功传输到 Slurm 控制器并分配了一个 SLURM 任务 ID 后,立即退出。批处理脚本不一定会立即被授予资源,在它所需的资源变得可用之前,它可能会在待定作业队列中等待一段时间。

默认情况下,标准输出标准误差都指向以下文件:

#SBATCH --output=MNIST_%j.out
#SBATCH --error=MNIST_%j.err

其中“%j”被替换为工作分配号。该文件将在作业分配的第一个节点上生成。当批处理脚本的任务分配最终被批准时,Slurm 在已分配节点集中的第一个节点上运行批处理脚本的单个副本。在以下章节中,我们将介绍其他参数。****

在我们案例研究中,分配 1 个 GPU 节点的作业脚本示例如下所示([MNIST.sh](https://github.com/jorditorresBCN/PATC-2021/blob/main/MNIST.sh) https://github.com/jorditorresBCN/PATC-2021/blob/main/MNIST.sh):

#!/bin/bash
#SBATCH --job-name="MNIST"
#SBATCH -D .
#SBATCH --output=MNIST_%j.out
#SBATCH --error=MNIST_%j.err
#SBATCH --nodes=1
#SBATCH --ntasks=1
#SBATCH --cpus-per-task=40
#SBATCH --gres=gpu:1
#SBATCH --time=00:10:00module load gcc/8.3.0 cuda/10.2 cudnn/7.6.4 nccl/2.4.8 tensorrt/6.0.1 openmpi/4.0.1 atlas/3.10.3 scalapack/2.0.2 fftw/3.3.8 szip/2.1.1 ffmpeg/4.2.1 opencv/4.1.1 python/3.7.4_MLpython MNIST.py

你可以参考这个官方页面文档来了解我们可以在前面有#SBATCH的批处理脚本中使用的所有选项

这些是使用 SLURM 提交和监控作业的基本指令,我们将在我们的案例研究中使用:

  • sbatch <job_script>向队列系统提交作业脚本。
  • squeue显示所有已提交的作业及其<job_id>
  • scancel <job_id>从队列系统中删除作业,取消进程的执行(如果它们仍在运行)。

在 SLURM 中运行任务的另一种方法是使用[salloc](https://slurm.schedmd.com/salloc.html) 命令。它用于为作业实时分配资源。通常,这用于分配资源和生成 shell。然后使用 shell 执行srun命令来启动并行任务。更多使用细节可以在这里找到。

总之,这可以是命令行序列及其执行的预期输出的示例:

[CTE-login-node ~]$ sbatch MNIST.sh
Submitted batch job 4910352[CTE-login-node ~]$ squeue
JOBID    PARTITION  NAME    USER    ST TIME  NODES  NODELIST
4910352  main       MNIST   userid  R  0:01  1      p9r1n16[CTE-login-node ~]$ ls
MNIST.py
MNIST.sh
MNIST_4910352.err
MNIST_4910352.out

标准输出标准误差分别指向文件MNIST_4910355.outMNIST_4910355.err。我建议读者在继续之前检查这些文件。这里,数字4910352表示由 SLURM 分配给作业的作业 id。**

2 —分布式和并行训练深度学习的基本概念

“具有计算规模的方法是人工智能的未来” —强化学习之父里奇·萨顿( 视频 4:49 )

深度神经网络(DNN)的成功基于建立高学习能力模型,这些模型具有以数据驱动方式调整的数百万个参数。这些模型是通过处理数百万个例子来训练的,因此更精确的算法的开发通常受到训练它们的计算设备的吞吐量的限制。

2.1 性能指标:加速、吞吐量和可伸缩性

为了使培训过程更快,我们需要一些性能指标来衡量它。这些系统中的术语性能有双重解释。一方面是指模型 预测精度。另一方面,以 计算速度的过程

精度与平台无关,是比较多个模型的性能指标。相比之下,计算速度取决于部署模型的平台。我们将通过加速等指标来衡量它,即顺序(或 1 个 GPU)算法与其并行(有许多 GPU)算法的求解时间之比。这是超级计算社区中我们日常行话中的一个流行概念;-) .

另一个重要的指标是吞吐量;例如,单位时间内可以处理的图像数量。这可以为我们提供一个很好的性能基准(尽管这取决于网络类型)。

最后,我们通常使用的一个概念是可伸缩性。它是一个更通用的概念,指的是系统高效处理不断增长的工作量的能力。这些指标将高度依赖于集群配置、使用的网络类型,或者框架使用库和管理资源的效率。

2.2 并行计算机平台

为此,使用了并行和分布式培训的方法。这种计算范式背后的主要思想是并行运行任务,而不是串行运行任务,因为它会发生在单台机器上。

DNN 通常是计算密集型的,这使得它们类似于传统的超级计算(高性能计算,HPC)应用。因此,大型学习工作负载在加速系统上表现非常好,例如在超级计算领域中使用的通用图形处理单元(GPU)。

多个 GPU 增加了可用于训练 DNN 的内存和计算。简而言之,给定我们想要分类的小批训练数据,我们有几种选择。在下一小节中,我们将对此进行更详细的讨论。

2.3 并行的类型

为了实现训练步骤的分布,有两个主要的实现,这将取决于应用程序的需求,以了解哪一个将执行得更好,或者甚至两种方法的混合是否可以提高性能。

例如,深度学习模型中的不同层可以在不同的 GPU 上并行训练。这种训练程序通常被称为模型并行。另一种方法是数据并行,其中我们为每个执行单元使用相同的模型,但使用不同的训练样本在每个计算设备中训练模型。

(图片由作者提供)

数据并行性

在这种模式下,训练数据被分成多个子集,每个子集都在不同 GPU(工作节点)中的相同复制模型上运行。这些将需要在批量计算结束时同步模型参数(或其“梯度”),以确保它们训练一致的模型(就像算法在单个处理器上运行一样),因为每个设备将独立计算其训练样本的预测和标记输出(这些训练样本的正确值)之间的误差。因此,每个设备必须将其所有的更改发送到所有其他设备上的所有模型。

这个设置的一个有趣的属性是,它将随着可用数据量的增加而扩展,并加快整个数据集对优化的贡献。此外,它需要节点之间更少的通信,因为它受益于每个权重的大量计算。另一方面,模型必须完全适合每个节点,它主要用于加速具有大型数据集的卷积神经网络的计算。

模型并行性

我们可以将网络层划分到多个 GPU 上(甚至我们可以将各个层所需的工作分开)。也就是说,每个 GPU 将流入特定层的数据作为输入,处理神经网络中几个后续层的数据,然后将数据发送到下一个 GPU。

在这种情况下(也称为网络并行),模型将被分割成可以并发运行的不同部分,每个部分将在不同节点的相同数据上运行。这种方法的可扩展性依赖于算法的任务并行化程度,实现起来也比前一种更复杂。它可以减少通信需求,因为工作人员只需要同步共享参数(通常每个前向或后向传播步骤一次),并且对于共享高速总线的单个服务器中的 GPU 工作良好。它可以用于更大的模型,因为每个节点的硬件约束不再是一个限制。

一般来说,算法的并行化比在具有数据子集的不同节点中运行相同的模型更复杂。

在本次实践中,我们将重点关注数据并行方法。

3 —案例研究:图像分类问题

在本节中,我们将解释如何缩放具有 25,613,800 个参数的“真实”神经网络 ResNet50V2。作为数据集,我们将使用流行的 CIFAR10 数据集。首先,我们将描述顺序执行,稍后我们将在许多 GPU 上并行执行。

3.1 数据集:CIFAR10

CIFAR-10 是一个已建立的用于物体识别的计算机视觉数据集。它是8000 万微小图像数据集的子集,由 60,000 张 32x32 彩色图像组成,包含 10 个对象类,每类 6000 张图像。它由亚历克斯·克里热夫斯基、维诺德·奈尔和杰弗里·辛顿收藏。有 50,000 个训练图像和 10,000 个测试图像。

从微小图像中学习多层特征,Alex Krizhevsky,2009。

我们已经将 CIFAR-10 数据集预装在从http://www.cs.toronto.edu/~kriz/cifar.html下载的目录/gpfs/projects/nct00/nct00002/cifar-utils/cifar-10-batches-py中的 CTE 超级计算机上。

出于学术目的,为了使训练更加困难,并且能够看到更长的训练时间以便更好地比较,我们应用了调整大小操作来使图像的大小为 128x128。我们创建了一个定制的 load_data 函数(/gpfs/projects/nct00/nct00002/cifar-utils/load_cifar.py)来应用这个调整操作,并将数据分成训练集和测试集。我们可以将它用作:

sys.path.append(‘/gpfs/projects/nct00/nct00002/cifar-utils’)from cifar import load_cifar

load_cifar.py可以从 this repository GitHub 中获得,供想要复习的读者使用(对于本课程的学生,没有必要下载)。

3.2 神经网络架构:ResNet

****AlexNet,由 Alex Krizhevsky 设计,是赢得 ImageNet 2012 竞赛的神经网络架构。 GoogleLeNet ,其 inception 模块大幅减少了网络的参数(比 AlexNet 少 15 倍)。其他人,如 VGGnet ,帮助证明了网络的深度是取得好结果的关键因素。关于这些网络的有趣之处在于,我们可以发现它们已经预装在大多数深度学习框架中。

Keras 应用是预先构建的深度学习模型,现已上市。这些模型在架构和参数数量上有所不同;您可以尝试其中一些模型,看看较大的模型如何比较小的模型训练得更慢,并实现不同的准确性。

所有可用模型的列表可在此处找到(前 1 名和前 5 名精度指的是模型在 ImageNet 验证数据集上的性能。).在这篇文章中,我们将考虑 ResNet 家族的两个架构作为案例研究: ResNet50v2ResNet152v2

ResNet 是由何等人在 2015 年发表的论文 D eep 残差学习用于图像识别 中介绍的一类具有极高精度和良好收敛行为的深度神经网络架构。

几个月后,相同的作者发表了一篇新论文, 深度残差网络 中的身份映射,对基本组件残差单元提出了新的建议,这使得训练更容易,并提高了泛化能力。这让V2版本:

tf.keras.applications.**ResNet101V2**(
    include_top=True,
    weights="imagenet",
    input_tensor=None,
    input_shape=None,
    pooling=None,
    classes=1000,
    classifier_activation="softmax",
)tf.keras.applications.**ResNet152V2**(
    include_top=True,
    weights="imagenet",
    input_tensor=None,
    input_shape=None,
    pooling=None,
    classes=1000,
    classifier_activation="softmax",
)

“50”和“152”代表网络中的重量层数。这两种网络的论点是:

  • include_top :是否包含网络顶部的全连通层。
  • ****权重:其中一个None(随机初始化)、‘ImageNet’(ImageNet 上的预训练),或者要加载的权重文件的路径。
  • input_tensor :可选的 Keras 张量(即layers.Input()的输出),用作模型的图像输入。
  • input_shape :可选形状元组,仅在include_top为 False 时指定(否则输入形状必须为(224, 224, 3)(数据格式为'channels_last')或(3, 224, 224)(数据格式为'channels_first')。它应该正好有 3 个输入通道,宽度和高度应该不小于 32。例如(200, 200, 3)将是一个有效值。
  • ****汇集:当include_topFalse时,特征提取的可选汇集模式。None(a)意味着模型的输出将是最后一个卷积块的 4D 张量输出。(b) avg意味着全局平均池将被应用于最后一个卷积块的输出,并且因此模型的输出将是 2D 张量。(c) max表示将应用全局最大池。
  • ****类:图像分类的可选类数,仅在include_top为真且未指定weights参数时指定。
  • ****分类器 _ 激活:一个str或可调用。在“顶层”使用的激活函数。忽略,除非include_top=True。设置classifier_activation=None返回“顶部”层的逻辑。

请注意,如果 *weights="imagenet"*,Tensorflow 中间件需要连接到互联网以下载 imagenet 权重(ImageNet 上的预培训)。由于我们的兴趣不集中在准确性上,我们没有下载带有 imagenet 权重的文件,因此,必须使用它*weights=None*

3.3 并行和分布式培训框架:TensorFlow 和 Horovod

我们可以使用框架作为 Pytorch 的 TensorFlow,在一台服务器上进行多 GPU 训练编程。要并行化模型的训练,只需要在 PyTorch 中用[torch.nn.parallel.DistributedDataParallel](https://pytorch.org/docs/stable/generated/torch.nn.parallel.DistributedDataParallel.html)包装模型,在 TensorFlow 中用[tf.distribute.MirroredStrategy](https://www.tensorflow.org/api_docs/python/tf/distribute/MirroredStrategy)包装模型。

然而,我们可以在服务器中放置的 GPU 数量非常有限,解决方案是将许多这些服务器放在一起,就像我们在 BSC 中使用 CTE 超级计算机所做的那样,其中 54 台服务器通过光纤上的 InfiniBand 网络链接在一起。

在这个新的场景中,我们需要软件堆栈的扩展来处理神经网络训练过程中的多个分布式 GPU。还有其他选择,但是在我们 BSC 的研究小组中,我们决定使用来自优步的 Horovod 。Horovod 插入 TensorFlowPyTorch 。但是这个选项不包括在这个动手操作中。如果读者对使用 Horovod 感兴趣,可以遵循这篇关于 Horovod 的动手操作

作为总结,在本次实践的以下部分,我们将介绍如何使用 TensorFlow tf.distributed.MirroredStrategy() API 在一台服务器的多个 GPU 上扩展 DL 神经网络的训练。

3.4 如何训练 ResNet 的顺序版本

在并行化神经网络训练之前,让我们从训练的顺序版本开始。使用 ResNet50 神经网络训练先前描述的 CIFAR10 数据集分类问题的顺序代码可以是ResNet50_seq.py:

import tensorflow as tf
from tensorflow.keras import layers
from tensorflow.keras import modelsimport numpy as np
import argparse
import time
import syssys.path.append(‘/gpfs/projects/nct00/nct00002/cifar-utils’)
from cifar import load_cifarparser = argparse.ArgumentParser()
parser.add_argument(‘ — epochs’, type=int, default=5)
parser.add_argument(‘ — batch_size’, type=int, default=2048)args = parser.parse_args()
batch_size = args.batch_size
epochs = args.epochstrain_ds, test_ds = load_cifar(batch_size)model = tf.keras.applications.**resnet_v2.ResNet50V2**(    
        include_top=True, 
        weights=None, 
        input_shape=(128, 128, 3), 
        classes=10)opt = tf.keras.optimizers.SGD(0.01)model.compile(loss=’sparse_categorical_crossentropy’,
              optimizer=opt,
              metrics=[‘accuracy’])model.fit(train_ds, epochs=epochs, verbose=2) 

ResNet50_seq.py文件可以从课程资源库 GitHub 下载。

要运行它,可以使用下面的 SLURM 脚本(ResNet50_seq.sh):

#!/bin/bash
#SBATCH — job-name=”ResNet50_seq”
#SBATCH -D .
#SBATCH — output=RESNET50_seq_%j.out
#SBATCH — error=RESNET50_seq_%j.err
#SBATCH — nodes=1
#SBATCH — ntasks=1
#SBATCH — cpus-per-task=160
#SBATCH — time=00:15:00 module load gcc/8.3.0 cuda/10.2 cudnn/7.6.4 nccl/2.4.8 tensorrt/6.0.1 openmpi/4.0.1 atlas/3.10.3 scalapack/2.0.2 fftw/3.3.8 szip/2.1.1 ffmpeg/4.2.1 opencv/4.1.1 python/3.7.4_ML python ResNet50_seq.py --epochs 20 --batch_size 256

ResNet50_seq.sh可以从课程资源库 GitHub 下载。

如果我们检查.out文件,我们可以看到给出 Keras 的输出结果:

Epoch 1/20
196/196 - 41s - loss: 2.0176 - accuracy: 0.2584Epoch 2/20
196/196 - 41s - loss: 1.7346 - accuracy: 0.3648Epoch 3/20
196/196 - 41s - loss: 1.5624 - accuracy: 0.4271Epoch 4/20
196/196 - 41s - loss: 1.4427 - accuracy: 0.4715Epoch 5/20
196/196 - 41s - loss: 1.3523 - accuracy: 0.5090Epoch 6/20
196/196 - 41s - loss: 1.2699 - accuracy: 0.5417Epoch 7/20
196/196 - 41s - loss: 1.1894 - accuracy: 0.5719Epoch 8/20
196/196 - 41s - loss: 1.1048 - accuracy: 0.6076Epoch 9/20
196/196 - 41s - loss: 1.0136 - accuracy: 0.6439Epoch 10/20
196/196 - 41s - loss: 0.9174 - accuracy: 0.6848Epoch 11/20
196/196 - 41s - loss: 0.8117 - accuracy: 0.7256Epoch 12/20
196/196 - 41s - loss: 0.6989 - accuracy: 0.7705Epoch 13/20
196/196 - 41s - loss: 0.5858 - accuracy: 0.8117Epoch 14/20
196/196 - 41s - loss: 0.4870 - accuracy: 0.8482Epoch 15/20
196/196 - 41s - loss: 0.4003 - accuracy: 0.8749Epoch 16/20
196/196 - 41s - loss: 0.3194 - accuracy: 0.9040Epoch 17/20
196/196 - 41s - loss: 0.2620 - accuracy: 0.9227Epoch 18/20
196/196 - 41s - loss: 0.2008 - accuracy: 0.9421 Epoch 19/20
196/196 - 41s - loss: 0.1441 - accuracy: 0.9615Epoch 20/20
196/196 - 41s - loss: 0.0742 - accuracy: 0.9859

出于本文的目的,为了计算时间(这将是我们用来比较的度量),我们将使用 Keras 自己告诉我们需要一个纪元的时间(有时我们会丢弃第一个纪元,因为它不同于其余的纪元,因为它必须在内存中创建结构并初始化它们)。请记住,我们是在一个学术例子中,有了这个近似的时间度量,我们有足够的时间来完成课程目标。

对于 Keras 中可用的任何其他网络,只需在代码中更改相应网络的粗体代码段resnet_v2.ResNet50V2

4-使用 TensorFlow 进行平行训练

[tf.distribute.Strategy](https://www.tensorflow.org/api_docs/python/tf/distribute/Strategy)是一个 TensorFlow API,以最小的代码更改在多个 GPU 或 TPU 之间分配训练(来自上一篇文章中介绍的顺序版本)。这个 API 可以和像 Keras 这样的高级 API 一起使用,也可以用来分发定制的训练循环。

tf.distribute.Strategy打算涵盖不同轴上的许多分销策略用例。此功能的官方网页展示了所有当前支持的组合,然而,在本文中,我们将关注[tf.distribute.MirroredStrategy](https://www.tensorflow.org/api_docs/python/tf/distribute/MirroredStrategy)

4.1 MirroredStrategy strategy

我们将在本次实践中使用[tf.distribute.MirroredStrategy](https://www.tensorflow.org/api_docs/python/tf/distribute/MirroredStrategy),它支持在一台服务器上的多个 GPU 上进行同步分布式培训。它为每个 GPU 设备创建一个副本。模型中的每个变量都被镜像到所有副本中。这些变量通过应用相同的更新来保持彼此同步。

通过这种策略,高效的 all-reduce 算法用于在 GPU 之间传递变量更新。默认情况下,它使用英伟达 NCCL 作为全还原实施。更多细节可以在这篇文章中找到。

下面是创建MirroredStrategy的最简单方法:

mirrored_strategy = tf.distribute.MirroredStrategy()

这将创建一个MirroredStrategy实例,它将使用 TensorFlow 可见的所有 GPU。可以看到执行以下操作的可用 GPU 设备列表:

devices = tf.config.experimental.list_physical_devices(“GPU”)

还可以通过执行以下操作来使用系统中可用 GPU 的子集:

mirrored_strategy = tf.distribute.MirroredStrategy(devices=["/gpu:0", "/gpu:1"])

要构建模型并在MirroredStrategy范围内编译它,你可以用下面的方法:

with mirrored_strategy.scope():
     model = tf.keras.applications.resnet_v2.ResNet50V2(
             include_top=True, weights=None, 
             input_shape=(128, 128, 3), classes=10)

     opt = tf.keras.optimizers.SGD(learning_rate)

     model.compile(loss=’sparse_categorical_crossentropy’, 
                   optimizer=opt, metrics=[‘accuracy’])

这允许我们创建分布式变量,而不是常规变量:每个变量都跨所有副本进行镜像,并通过应用相同的更新来保持彼此同步。

培训可以在战略范围之外照常进行,包括:

dataset = load_data(batch_size)
model.fit(dataset, epochs=5, verbose=2)

4.2 分销绩效衡量

在本帖中,我们将考虑使用纪元时间作为训练 DNN 的计算时间的度量。Keras 在.fit期间提供的以秒为单位的近似度量对于这篇学术文章来说已经足够了。在我们的例子中,有时我们会丢弃第一时间点,因为它包括创建和初始化结构。显然,对于某些类型的研究,有必要进行更详细的研究,区分加载数据、前馈时间、损失函数时间、反向预测时间等。,但这超出了我们在本次实践中提出的案例研究的范围。

4.3 选择批量大小和学习率

训练时需要分配内存来存储训练模型的样本和模型本身。我们必须记住这一点,以避免出现内存不足的错误。

请记住,batch_size是模型在每个训练步骤中看到的样本数量,通常,我们希望这个数量尽可能大(2 的幂)。我们可以通过试错法测试不同的值来计算,直到出现与内存相关的错误:

python ResNet50.py -- epoch 1 -- batch_size 16
python ResNet50.py -- epoch 1 -- batch_size 32
python ResNet50.py -- epoch 1 -- batch_size 64

当使用带有多个 GPU 的MirroredStrategy时,显示的批量大小除以副本的数量。因此,我们应该为 TensorFlow 指定的batch_size等于一个 GPU 的最大值乘以我们正在使用的 GPU 数量。在我们的示例中,这是在 python 程序中使用这些标志:

python ResNet50.py -- epochs 5 -- batch_size 256  -- n_gpus 1
python ResNet50.py -- epochs 5 -- batch_size 512  -- n_gpus 2
python ResNet50.py -- epochs 5 -- batch_size 1024 -- n_gpus 4

相应地,对于batch_size,如果我们在多个 GPU 上使用MirroredStrategy,我们希望learning_rate是:

learning_rate = learning_rate_base*number_of_gpus
opt = tf.keras.optimizers.SGD(learning_rate)

由于更大的 batch_size,我们还想在最小值的方向上采取更大的步骤,以保持要收敛的历元数。

4.4 案例研究

我们将采用上一篇文章中给出的例子,ResNet50 with CIFAR10,并在 CTE-POWER 机器上对其进行训练。

ResNet50 神经网络并行代码

按照上一节中介绍的关于如何应用MirroredStrategy的步骤,下面我们将展示产生的并行代码:

import tensorflow as tf 
from tensorflow.keras import layers 
from tensorflow.keras import modelsimport numpy as np
import argparse
import time
import syssys.path.append(‘/gpfs/projects/nct00/nct00002/cifar-utils’)
from cifar import load_cifarparser = argparse.ArgumentParser()
parser.add_argument(‘ -- epochs’, type=int, default=5)
parser.add_argument(‘ --batch_size’, type=int, default=2048)
parser.add_argument(‘ -- n_gpus’, type=int, default=1)args = parser.parse_args()
batch_size = args.batch_size
epochs = args.epochs
n_gpus = args.n_gpustrain_ds, test_ds = load_cifar(batch_size)device_type = ‘GPU’
devices = tf.config.experimental.list_physical_devices(
          device_type)
devices_names = [d.name.split(“e:”)[1] for d in devices]strategy = tf.distribute.MirroredStrategy(
           devices=devices_names[:n_gpus])with strategy.scope():
     model = tf.keras.applications.resnet_v2.ResNet50V2(
             include_top=True, weights=None,
             input_shape=(128, 128, 3), classes=10)
     opt = tf.keras.optimizers.SGD(0.01*n_gpus)
     model.compile(loss=’sparse_categorical_crossentropy’, 
                   optimizer=opt, metrics=[‘accuracy’])model.fit(train_ds, epochs=epochs, verbose=2)

SLURM 脚本

发送作业执行的 SLURM 脚本是:

#!/bin/bash
#SBATCH --job-name=”ResNet50"
#SBATCH --D .
#SBATCH --output=ResNet50_%j.output
#SBATCH --error=ResNet50_%j.err
#SBATCH --nodes=1
#SBATCH --ntasks=1
#SBATCH --cpus-per-task=160
#SBATCH **--gres=gpu:4**
#SBATCH --time=00:30:00module purge; module load gcc/8.3.0 cuda/10.2 cudnn/7.6.4 nccl/2.4.8 tensorrt/6.0.1 openmpi/4.0.1 atlas/3.10.3 scalapack/2.0.2 fftw/3.3.8 szip/2.1.1 ffmpeg/4.2.1 opencv/4.1.1 python/3.7.4_MLpython ResNet50.py -- epochs 5 -- batch_size 256 -- n_gpus 1
python ResNet50.py -- epochs 5 -- batch_size 512 -- n_gpus 2
python ResNet50.py -- epochs 5 -- batch_size 1024 -- n_gpus 4

我们对所有的处决都使用相同的诽谤。注意用--gres=gpu:4标明需要的 GPU 数量。

结果

一旦我运行了前面的脚本,在存储了标准输出的文件中,我们会发现下面的执行时间:

**python ResNet50.py --epochs 5 --batch_size 256 --n_gpus 1** Epoch 1/5 
196/196 - 49s - loss: 2.0408 - accuracy: 0.2506
Epoch 2/5
196/196 - 45s - loss: 1.7626 - accuracy: 0.3536
Epoch 3/5
196/196 - 45s - loss: 1.5863 - accuracy: 0.4164
Epoch 4/5
196/196 - 45s - loss: 1.4550 - accuracy: 0.4668
Epoch 5/5
196/196 - 45s - loss: 1.3539 - accuracy: 0.5070**python ResNet50.py --epochs 5 --batch_size 512 --n_gpus 2** Epoch 1/5
98/98 - 26s - loss: 2.0314 - accuracy: 0.2498
Epoch 2/5
98/98 - 24s - loss: 1.7187 - accuracy: 0.3641
Epoch 3/5
98/98 - 24s - loss: 1.5731 - accuracy: 0.4207
Epoch 4/5
98/98 - 23s - loss: 1.4543 - accuracy: 0.4686
Epoch 5/5
98/98 - 23s - loss: 1.3609 - accuracy: 0.5049**python ResNet50.py --epochs 5 --batch_size 1024 --n_gpus 4** Epoch 1/5
49/49 - 14s - loss: 2.0557 - accuracy: 0.2409
Epoch 2/5
49/49 - 12s - loss: 1.7348 - accuracy: 0.3577
Epoch 3/5
49/49 - 12s - loss: 1.5696 - accuracy: 0.4180
Epoch 4/5
49/49 - 12s - loss: 1.4609 - accuracy: 0.4625
Epoch 5/5
49/49 - 11s - loss: 1.3689 - accuracy: 0.5010

值得注意的是,我们关注的是流程的计算速度,而不是模型的准确性。为此,我们将在训练期间仅执行少数几个时期,因为我们将看到每个时期的训练时间是恒定的,并且用 5 个时期,我们在所有情况下都实现了相同的精度。这意味着只有 5 个时期可供我们比较 3 个选项,这也是这些测试的目的。

很明显,如果我们想做好研究,我们应该进行几次试验,然后取每次试验的平均时间。但是考虑到这篇文章的学术目的(以及我们必须节约的资源成本!),只执行一次就够了。

4.5 结果分析

总之,完成一个历元所需的时间如下图所示:

我们可以将其转化为每秒图像数(因为我们知道有 50,000 张图像),这就给出了吞吐量:

最后,如我所说,加速是最相关的指标:

这几乎是线性加速。当工作负载在多个 GPU 之间平均分配时,我们称之为线性加速线性。

5 —是时候用ResNet152V2边做边学了

如果你想学得更多,巩固所学的知识,现在轮到你动手为ResNET152V2重现上面的结果,然后与上一节呈现的结果进行比较。你准备好了吗?加油!

请记住,第一步是找到最佳的batch_size. 。如果您绘制结果,您应该会找到与下面所示结果相当的结果:

观察到一些相关的事情。首先是运行 ResNet152 epoch 的时间要长得多,因此每秒图像的吞吐量比 ResNet50 网络上的低得多。为什么会这样?ResNet152 网络更深,意味着它有更多的层,因此训练时间会更长。

可以看出,ResNet152 的加速不再是线性的;你能试着给出一个可能的答案来解释为什么会这样吗?显然,这取决于许多因素,需要进行详细的分析,然而,由于网络的最大规模,这将增加同步的额外延迟。

6 —摘要

在这次实践中,我们展示了如何使用tf.distributed.MirroredStrategy() TensorFlow API 在一台服务器中的许多 GPU 上瘫痪单个深度神经网络训练。

正如我们在结果中看到的,我们的模型实现的精度或多或少是恒定的,与 GPU 的数量无关。总之,使用分布式策略,我们的模型可以学习相同但更快,这要归功于并行化!

由于并行化,深度学习可以学习相同但更快的内容!

****本课程 GitHub:【https://github.com/jorditorresBCN/PATC-2021】

****鸣谢:非常感谢来自 BSC-CNS 的 Juan Luis DomínguezOriol Aranda ,他们编写了本实践中出现的第一版代码,并感谢 Carlos Tripiana 和 Félix Ramos 使用 POWER-CTE 集群提供的重要支持。此外,非常感谢阿尔瓦罗·约弗·阿尔瓦雷斯、米克尔·埃斯科瓦尔·卡斯特尔斯和劳尔·加西亚·富恩特斯对本文件校对工作的贡献。

视频深度学习(第一部分):早期…

原文:https://towardsdatascience.com/deep-learning-on-video-part-one-the-early-days-8a3632ed47d4?source=collection_archive---------6-----------------------

(作者创作)

在这一系列博客文章中,我将探讨视频数据深度学习的主题。从一些关于该主题的最早出版物开始,我旨在概述这个问题最初是如何解决的——在深度学习方法大规模普及之前——并跟踪视频深度学习随时间的演变。在这样做的时候,我的目标不仅是概述视频深度学习的历史,而且还为希望涉足该领域的研究人员或从业者提供相关的背景和理解。

我会把这个话题分成几篇博文。这一部分将概述视频深度学习的“早期”。这一时期的出版物首次利用 3D 卷积以可学习的方式从视频数据中提取特征,不再使用手工制作的图像和视频特征表示。这些方法的例子包括将手工制作的视频特征传递到 3D 卷积层的两部分架构、基于 3D 卷积的无监督学习技术、或者甚至直接对视频数据进行操作的 3D 卷积网络。

这篇文章将分为三个部分。我将首先提供相关的背景信息(例如,3D 卷积如何工作,3D 卷积之前的方法,视频数据是如何构造的)。然后,我将概述相关文献,提供对视频深度学习早期方法的高级(但全面)理解。最后,我将结束这篇文章,并概述这种方法的局限性,展望后来开发的性能更好的方法。

预赛

在深入研究相关文献之前,有几个概念必须概述一下。在描述这些概念时,我假设读者对卷积运算和计算机视觉应用中图像数据的典型结构有基本的了解。然而,我仍然会尝试提供所有相关的信息,这样重要的概念可以用最少的先验知识来理解。

视频数据是如何结构化的?

图像和视频数据结构的比较(由作者创建)

在开发视频的深度学习应用程序时,人们可能会问自己的第一个问题是视频数据通常是如何构造的(例如,与图像相比)。对于图像,这个问题有一个简单的答案。在大多数情况下,输入图像是 RGB 格式的(即每个图像都有三个相关联的颜色通道),并且具有一定的高度和宽度。例如,在上图中,输入图像有三个颜色通道,每个通道的高度和宽度都是五。因此,对基于图像的深度学习模型的输入通常将是大小为3 x Height x Width张量。几幅图像可以堆叠成一个小批量,形成一个大小为Batch x 3 x Height x Width的张量。

对于视频来说,数据结构差别不大。也就是说,视频只是一组按时间顺序排列的图像,称为帧。当以正确的时间顺序观看时,这些帧揭示了场景随时间的移动,形成了视频。类似于图像,这些帧中的每一个通常以 RGB 格式表示,并且具有相同的空间分辨率(即,所有帧具有相同的高度和宽度)。在上图中,视频由三个帧组成,每个帧有三个颜色通道,高度和宽度为五。

视频中的所有帧可以组合成单个“体积”,通过将所有帧“堆叠”在彼此顶部来形成大小为3*Frames X Height X Width的张量(即,根据应用,帧也可以聚合成大小为Frames X 3 X Height X Width的张量)。将几个视频组合成一个小批量必须小心进行,因为每个视频中的帧数可能不同,从而形成不同大小的视频张量。尽管如此,不同的视频可以被“分块”成相同数量的连续帧(或者可以采用填充方法)以形成相同大小的视频,这些视频可以组合在一起形成一个小批量大小的Batch x 3*Frames x Height x Width

有哪些数据集?

在本文将涉及的文献中,用于评估的主要数据集包括: TRECVIDKTH好莱坞 2UCF101YouTube Action 。所有这些数据集都集中在人类动作识别(HAR)的问题上,其中必须根据人类在视频剪辑中执行的动作为视频剪辑分配类别标签。HAR 在自动驾驶和监控等问题领域有许多应用,是视频深度学习早期研究最广泛的应用。尽管后来的研究考虑了其他更复杂的应用,HAR 仍然是一个值得注意的问题。然而,有趣的是,可以证明基于图像的模型在视频中的帧上独立操作,在 HAR [1,2]上表现良好,表明只需要最少的时间推理就可以提供合理的解决方案。

从 2D 到 3D…

在描述针对视频的深度学习的建议方法之前,考虑如何将基于图像的深度学习的构造推广到视频领域是有用的。特别是,我们必须考虑如何将 2D 卷积(卷积神经网络(CNN)背后的主力)应用于视频。CNN 是由非线性分离的并行卷积运算的简单序列,长期以来被应用于流行的基于图像的任务,如图像分类、对象检测和关键点估计,取得了巨大的成功。因此,视频深度学习的早期工作试图将这种成功的方法扩展到视频数据上是有意义的。2D 卷积运算描述如下。

RGB 图像上的 2D 卷积运算(由作者创建)

可以看出,在 2D 卷积中,跨越输入的所有通道(即上面图像中的三个彩色通道)的单个卷积核在输入的每个空间位置上移动,以单独计算相应的输出元素。这里,每个输出元素都是通过将输入中正确空间位置的像素值与它们在内核中的相应权重相乘,并对所有此类乘法求和得到的。请注意,此描述仅考虑了 2D 卷积的最简单情况(即 RGB 输入、无跨步等)。).我推荐这篇博文来了解更多关于 2D 回旋的细节。

当我们开始考虑视频数据时,卷积运算的输入会发生变化,因为我们现在有多帧视频,而不是一幅图像。因此,输入不再是单个 RGB 图像,而是堆叠在彼此之上的大量 RGB 图像(即,这可以被视为具有大量通道的类似输入)。为了解决输入中的多个帧,卷积运算必须不仅跨越空间维度(例如,上面图像中的 2D 卷积跨越高度和宽度三个像素),而且跨越时间维度。也就是说,单个内核在计算其相应的输出表示时必须考虑输入的多个帧。下面描述了这个公式,我们称之为 3D 卷积运算。

三个 RGB 帧的三维卷积运算(作者创建)

可以看出,上面的 3D 卷积有一个内核,它跨越输入中的两个帧。最初考虑前两个帧,在每个空间维度上移动该内核以计算相应的输出元素(即,通过类似于 2D 卷积的逐元素乘法和求和)。在移动可能的空间维度之后,3D 卷积在时间上迈出了一步,移动到它必须考虑的下一个帧跨度,并重复遍历空间维度的过程。在上面的图像中,3D 卷积最初考虑视频中的前两帧,然后继续计算对应于第二帧和第三帧的表示。如果视频中存在更多帧,3D 卷积将继续以这种方式穿越时间。

3D 卷积是一种时空运算,它同时考虑了每个单独输入帧内的空间特征和连续帧内的时间特征。尽管三维卷积不是从视频数据中学习特征的唯一方法,但它们是早期深入学习视频的方法所利用的主要可学习变换。因此,三维卷积是本文的主要重点。

在深入学习之前使用了什么?

尽管 CNN 在图像领域取得了广泛的成功,但将其应用扩展到视频需要时间,特别是由于缺乏用于训练目的的大型、多样化的视频数据库(相对于基于图像的数据集的大小和多样性而言)[1]。因此,人们可能会开始想知道在基于深度学习的动作识别系统普及之前,HAR 通常是如何解决的。

用于 HAR 的初始系统从视频数据中提取固定的、手工制作的特征(例如,使用运动历史图像、SIFT 描述符、HoG 特征、模板匹配、滤波器组等)。)来帮助分类。通常,视频将首先被分割成兴趣点(即,从背景中裁剪出人的较短剪辑)。然后,从这些兴趣点中提取固定特征(即,由几个裁剪的帧组成)并用某种机器学习模型(例如,支持向量机)进行分类。这种方法后来被扩展为更复杂的系统,通过手工特征提取和子采样的交替应用来分层学习特征[3,4]。

尽管手工制作的方法效果相对较好,但这种特征难以在数据集之间推广,并且难以适应不同的传感器领域(如视频或雷达)[5]。此外,手工制作的特征倾向于对底层数据分布进行简化假设(例如,固定视点、人在帧的中心等)。)会降低实际应用程序的性能[6]。因此,该领域的研究人员开始寻找可以直接从数据中学习的替代特征提取方法。由于 CNN 能够从图像中提取有用的特征,使用 2D/3D 卷积从视频数据中学习特征迅速成为关注的主要领域。这篇文章概述了由此产生的方法。

视频深度学习的早期方法

现在,我将概述相关的早期方法,这些方法率先使用 3D 卷积以可学习的方式从视频数据中提取特征。本文将涉及的出版物可以大致分为以下几类:将可学习特征提取与固定特征提取相结合的方法,将可学习特征提取直接应用于视频数据的方法,以及用于学习视频中时空特征的无监督方法。

混合方法:结合手工制作和学习的功能

虽然已知当在大型图像数据集上训练时,CNN 能够学习有用的、有区别的特征,但是 CNN 到视频域的早期扩展通常将 3D 卷积的使用与固定特征提取相结合,而不是将 3D 卷积直接应用于原始视频数据。具体而言,视频数据将首先由固定特征提取器进行预处理,例如通过计算原始视频帧上的光流或垂直和水平梯度。然后,在预处理之后,产生的表示将通过 3D 卷积层来提取用于分类的可学习特征。

这种方法被最初的 HAR 系统采用,应用于 TRECVID 监测数据集[7,8]。这种方法不是直接对原始视频数据进行操作,而是计算输入视频内的光流方向梯度。这些手工制作的特征然后与原始视频帧连接,并通过几层 3D 卷积,这些卷积由子采样操作和非线性激活函数分开。在这些 3D CNN 架构中,每个数据模态(即,光流、方向梯度和正常帧)由单独的 3D 卷积核独立处理。然后,利用支持向量机[7]或全连接线性模块[8],将 3D CNN 的输出用于分类。在这些工作中,为 HAR 探索了几种不同的 CNN 架构,得出的结论是将几种独特的 3D CNN 架构的输出相结合通常会产生最佳性能[8]。

这种方法在当时非常成功,甚至超过了 HAR 的单帧 CNN(即,强基线方法)和几乎所有利用手工制作的特征提取的基线。尽管如此,这种方法仍然固有地依赖于在初始预处理阶段内计算的光流和梯度特征的质量。这种特征是不可学习的,因此可能无法在数据集或应用程序中很好地推广。这种观察导致了完全消除固定特征提取的方法的提议,以试图提取完全可学习的特征,而不依赖于任何手工制作的试探法。

用 3D CNNs 提取可学习的视频特征

为了避免与基于手工制作特征的方法相关的限制,后来的视频深度学习方法将原始输入量(即几个帧的组)直接传递到由池化和激活层分隔的 3D 卷积层中[9]。这种 3D CNNs 在结构上类似于基于图像的 CNN,但被修改为包含 3D 卷积[9]。通常,这些方法从完整视频中提取一小部分帧,裁剪这些帧以聚焦每个帧中的人,然后将子采样和裁剪后的体积传递到 3D CNN [9,10],其中的输出随后用于执行分类。有趣的是,这种方法很容易超越混合 3D CNNs(即结合手工制作和学习特征的 CNN)的性能,即使使用小得多的网络[10]。

值得注意的是,因为这种方法将基础视频分割成传递到 3D CNN 的较短剪辑(例如,包含 10-15 个帧),所以最终分类不考虑完整视频内较大或时间上较远的帧组之间的关系。为了解决这一缺点,上述方法与递归神经网络(特别是长短期记忆(LSTM)网络[11])相结合,以合成用 3D CNNs 从视频的每个片段中提取的信息。特别是,视频首先被分割成更小的帧组,这些帧组再次被传递到 3D CNN 以提取特征。然而,不是独立地对这些特征中的每一个进行分类,而是将与每个视频片段相关联的特征以时间顺序作为输入传递给 LSTM,然后其执行最终的分类[10]。这种方法考虑了完整视频的上下文,因此在 HAR 上实现了显著提高的性能。

使用 3D CNNs 直接从视频数据中提取特征是革命性的,因为它为深度学习成为视频学习任务的主要方法铺平了道路。这些作品脱离了传统的视频学习方法,并遵循了图像识别的相关深度学习文献的方法,选择让所有特征以可学习的方式获得。因此,视频学习任务的系统(如 HAR)变得更少依赖于领域,视频相关的研究可以以更快的速度发展,因为不需要不断确定每个可能的数据集的最佳手工制作的特征[12]。然而,这种方法仍然存在一个主要的限制——它们的性能完全依赖于底层任务的标记数据的质量和数量。

视频的无监督表示学习

尽管 3D CNN 模型提供了令人难以置信的价值,但它们的性能受到可用于训练的数据量的限制。尤其是在深度学习的早期,带标签的视频数据的可用性微乎其微[1]。因此,由于缺乏足够的数据,3D CNN 模型学习高质量特征的能力总是有些有限。这种限制导致了无监督深度学习方法的同时发展,用于提取有意义的视频特征[12,13]。

第一个这种用于视频的无监督学习方法利用门控、受限玻尔兹曼机器(GRBM)架构来从视频中的相邻帧学习特征。最初,GRBM 架构无法处理高分辨率图像(即,计算量太大),因为在作为输入传递到模型之前,图像被展平为矢量。为了缓解这个问题,GRBM 在[13]中被修改为使用卷积运算,允许以较低的计算成本处理更高分辨率的图像。然后,可以以无监督的方式在相邻的视频帧上训练这个卷积 GRBM 模型,以学习有用的空间和时间信息,从而允许从视频中提取高质量的特征,而不需要标记的数据。从这里可以看出,从卷积 GRBM 提取的特征可以传递到 3D CNN 中,以解决像 HAR 这样的任务,其中 GRBM 的无监督预训练大大提高了性能[13]。

虽然卷积 GRBM 表现出令人印象深刻的性能,但无监督的预训练过程在计算上相当低效,这导致了一种替代的无监督视频学习方法的建议,该方法受独立子空间分析(ISA)的启发[12]。ISA 是一种生物启发的稀疏学习方法,基于独立成分分析,以前用于从静态图像中提取有意义的特征,可以以无监督的方式进行训练。与 GRBMs 类似,ISA 的计算效率太低,无法应用于高分辨率图像。为了解决这个问题,[12]提出首先在来自视频帧的较小图像块上训练(即,以无监督的方式)ISA。然后,可以使用主成分分析(PCA)减少这些初始帧补片上的 ISA 输出的维度,使其足以通过另一个 ISA 模块。然后,这些模块的输出可以被馈送到 3D CNN,以提取用于分类的特征[12]。这种方法极大地提高了视频无监督表示学习的效率,并在 HAR 的几乎所有数据集上实现了最先进的性能。

结论和展望

在这篇文章中,我们概述了利用 3D 卷积运算从视频中提取可学习特征的早期方法。最初,这种工作采用了一种混合方法,其中手工制作的特征被提取出来,并与来自 3D CNNs 的可学习特征混合。后来,所有手工制作的组件都被淘汰,通过将 3D CNNs 直接应用于原始视频数据,以完全可学习的方式提取视频特征。然后,并行地,提出了几种用于学习有意义的视频特征的无监督方法,从而减轻了在解决常见学习任务(例如,HAR)时对标记的视频数据的依赖。

尽管早期的视频深度学习方法工作得相对较好,但它们的效率相当低,并且无法与深度学习在基于图像的任务上实现的令人印象深刻的性能相匹配。这项工作中概述的方法仅略微优于单帧基线模型,甚至偶尔优于某些数据集上手工制作的基线方法。因此,需要一种更具性能的方法来维持或提高本文中概述的 3D CNN 方法的计算效率。最终,这种需求导致了双流 3D CNN 架构的提出,这将在本系列的下一篇文章中概述。

非常感谢你阅读这篇文章!希望对你有帮助。如果您有任何反馈或担忧,请随时评论该帖子或通过 twitter 联系我。如果你想关注我未来的工作,你可以在媒体上关注我,或者在我的个人网站上查看内容。这一系列的文章是我在 Alegion 做研究科学家时背景研究的一部分。如果你喜欢这篇文章,请随时查看该公司和任何相关的空缺职位——我们总是希望与对深度学习相关主题感兴趣的积极个人进行讨论或雇用他们!

参考书目

[1]https://static . Google user content . com/media/research . Google . com/en//pubs/archive/42455 . pdf

https://ieeexplore.ieee.org/document/1495508

[3]https://McGovern . MIT . edu/WP-content/uploads/2019/01/04069258 . pdf

[4]https://www.cs.tau.ac.il/~wolf/papers/action151.pdf

https://ieeexplore.ieee.org/stamp/stamp.jsp?tp=的 T2

https://ieeexplore.ieee.org/stamp/stamp.jsp?tp=号&号=6165309

[7]https://www . research gate . net/publication/229045898 _ Detecting _ Human _ Actions _ in _ Surveillance _ Videos

https://ieeexplore.ieee.org/document/6165309

[9]https://link . springer . com/content/pdf/10.1007/978-3-540-72393-6 _ 85 . pdf

[10]https://link . springer . com/content/pdf/10.1007% 2f 978-3-642-25446-8 _ 4 . pdf

[11]https://colah.github.io/posts/2015-08-Understanding-LSTMs/

https://ieeexplore.ieee.org/document/5995496

http://yann.lecun.com/exdb/publis/pdf/taylor-eccv-10.pdf

手机深度学习:手机平台 PyTorch Lite 解释器

原文:https://towardsdatascience.com/deep-learning-on-your-phone-pytorch-lite-interpreter-for-mobile-platforms-ae73d0b17eaa?source=collection_archive---------5-----------------------

PyTorch 深度学习框架支持在移动设备上无缝运行服务器训练的 CNN 和其他 ML 模型。本文描述了如何在移动设备上优化和运行您的服务器训练模型。

Unsplash 上由 Rodion Kutsaev 拍照

PyTorch 是一个深度学习框架,用于训练和运行机器学习(ML)模型,加快从研究到生产的速度。

通常,人们会在功能强大的服务器上训练模型(在 CPU 或 GPU 上),然后将预训练的模型部署在移动平台上(这通常更受资源限制)。本文将重点讨论 PyTorch 为在移动设备/平台上运行服务器训练的模型提供了哪些支持。

PyTorch Mobile 目前支持在 AndroidiOS 平台上部署预训练模型进行推理。

高层次的步骤

  1. 在服务器上训练模型(在 CPU 或 GPU 上)——本文不会讨论训练模型的细节。你可以在这里、这里这里找到更多关于 PyTorch 训练的信息。这里有一篇关于 PyTorch 入门的好文章。
  2. [可选]针对移动推理优化您的训练模型
  3. 以 lite 解释器格式保存您的模型
  4. 使用 PyTorch 移动 API 在您的移动应用程序中进行部署
  5. 利润!

详细步骤

本文的其余部分假设您已经预先接受了培训。pt 模型文件,下面的示例将使用一个虚拟模型来遍历代码和工作流,以便使用 PyTorch Lite 解释器进行移动平台的深度学习。

在服务器上创建/训练模型

检查它是否运行,并产生合理的输出

应打印:

张量(【4。, 11., 18.])

生成脚本模型

[可选]为移动推理优化模型

有关移动优化器的详细信息,请参见本页。

为移动推理保存模型

加载并运行移动模型进行推理(在移动设备上)

下面的代码直接使用 C++ API。根据你的需求,你可以选择使用 Android (Java) 或者iOSAPI。您还可以查看本文开始使用 C++ API 在您的开发机器上以 x 平台的方式运行模型推理。

optimize_for_mobile(模型)到底是做什么的?

移动优化过程对模型的图形执行许多更改。你可以在这里找到移动优化通道的源代码。下面是这种优化的一个不全面的列表。

  1. 模块冻结:这将不会被模型变异的属性提升为常量。在后续过程中很有用。
  2. 函数内联:如果从模型的 forward()方法中调用一个方法,那么被调用的方法在优化的模块中被内联,以消除函数调用开销。
  3. 操作符融合:例如融合once 巴奇诺姆或 conv-雷鲁等……这允许在中间层重复使用进入 CPU 缓存的数据。
  4. 去除漏失 : 漏失是一种近似并行训练大量不同架构神经网络的正则化方法。一旦模型进入 eval() only 模式,就不需要这样做了,删除它可以提高模型的推理性能。

比较移动优化前后的模型图

在优化之前

原始模型有两个方法:forward()和 helper()。forward()调用 helper()。此外,张量 t1 是模型属性。

scripted.forward.graph

将打印

scripted.helper.graph

将打印

优化后

优化的模型只有一个方法,forward()。此外,张量 t1 是模型常数。

优化 _ 模型.转发.图形

将打印

lite 解释器模型与 TorchScript 模型有什么不同?

lite 解释器模型文件是一个常规的 TorchScript 模型文件,其中添加了特定于移动设备的字节码。您可以将移动模型作为普通的 PyTorch TorchScript 模型加载,也可以将其作为 lite-interpreter 模型加载。

当保存为 lite-interpreter(移动平台)时,PyTorch 为模型的图形保存了额外的字节码,与 TorchScript 相比,在设备上执行更有效。相对于运行 TorchScript,PyTorch 在编译的应用程序中使用的二进制文件更少。

下面是如何查看生成的 bytecode.pkl 文件。

结论

PyTorch 现在支持移动平台上的推理。很容易采用服务器训练的模型,并将其转换为在移动平台上运行优化的推理。模型语义以 TorchScript 和 Lite 解释器格式保存。

参考

  1. PyTorch 手机
  2. 通过示例了解 PyTorch:分步指南
  3. 深度学习 PyTorch 简介
  4. 【PyTorch 入门
  5. 你应该知道的 PyTorch 最重要的基础知识
  6. 深度学习 PyTorch:入门
  7. 什么是辍学?
  8. PyTorch 算子融合
  9. PyTorch 移动优化器

深度学习优化理论—简介

原文:https://towardsdatascience.com/deep-learning-optimization-theory-introduction-148b3504b20f?source=collection_archive---------16-----------------------

理解深度学习中的优化理论对于实现进步至关重要。这篇文章介绍了研究它的实验和理论方法。

在过去十年中,深度学习在学术界和工业界都蓬勃发展。几十年来众所周知难以解决的现实世界和学术问题,如计算机视觉、自然语言处理和玩游戏,现在正通过深度学习方法得到高度成功的解决。

然而,尽管深度学习取得了这些重大进步,但对其成功的理论理解仍然滞后。我们的理解范围从基于实验的传统智慧和直觉到对玩具问题的更深入分析,这些玩具问题并不类似于真实世界深度学习架构的真正复杂性。这篇博客旨在强调从挑战传统智慧的深度学习理论研究中获得的有趣经验。

一般来说,深度学习由以下三个支柱组成:

  1. 表达能力 —我们可以用神经网络表达什么功能?就一个神经网络所能代表的功能集而言,它对另一个神经网络的效率如何?现代神经网络存在哪些归纳偏差?
  2. 优化——对于给定的任务,我们如何找到神经网络的最佳权重?能保证找到最好的吗?我们能多快做到?
  3. 推广 —为什么一个训练集的解决方案可以很好地推广到一个未知的测试集?我们能限制泛化误差吗?

这篇文章将重点讨论优化。假设读者熟悉 SGD、深度学习和一些优化背景。

深度学习理论——优化

凸函数的最优化被认为是数学中一个成熟的领域。因此,可以使用成熟的工具和理论来回答上一段中描述的优化问题。然而,复杂的非凸函数的优化很难分析。既然深度神经网络(是的,线性网络也是)的优化是非凸的,我们如何尝试回答这些问题呢?人们可能会寻找广泛的经验证据来证明 SGD 在现实世界问题上收敛于全局极小值。另一个可能会寻找一个严格的理论解释其收敛和条件,它发生了。由于这两种方法,实验的和理论的帮助推动了我们的知识,在这篇博文中,我将展示这两种方法的代表性作品。我要介绍的第一种方法是实验方法。

DL 中的优化—一种实验方法

Goodfellow 等人的作品“定性表征神经网络优化问题”。艾尔。提出了一种简单的工具来解决上述针对特定实际网络和问题的优化问题。让我们假设你训练你的网络收敛到全局最优(训练损失接近零)。现在,取初始化时的权重和收敛时的权重,并简单地在初始权重和收敛权重之间的参数空间中的线上的一系列点处评估您的损失函数。更正式地说:

沿着θi(初始化时的权重)到θc(收敛时的权重)之间的线采样θa。

因为我们怀疑损失函数是高度非凸的,所以很难想象损失函数沿着这条线的行为。令人惊讶的是,在 MNIST 上训练的前馈神经网络上执行该实验揭示了以下行为:

在 MNIST 数据集上训练的具有 ReLU 激活的全连接网络上的线性插值实验。这表明目标函数在模型的初始参数和目标参数之间的线内是平滑的。图片来源

不直观地,我们观察到这条线上的损失函数是连续的单调递减函数。这表明,虽然损失函数本身是非凸的,但有一条“几乎凸的”路径通向收敛点。此外,其他架构的其他实验(CNN/RNN)揭示了类似的现象。请阅读论文了解更多详情。如果你有兴趣自己尝试一下,可以用我为它实现

既然我们知道从初始权重到收敛存在一条平滑单调递减的路径,有人可能会问 SGD 遵循这条线性路径吗?为了回答这个问题,我们正在寻找一种方法来评估“如果 SGD 被投射到生产线上,它是如何沿着生产线前进的”。此外,在那些权重不在 1D 子空间上的情况下,我们想要评估“它们离线有多远”。我们用 α 表示沿线的距离,用 β 表示离该线的距离。在深入研究α和β的数学定义之前,请注意以下几点:

水平轴— α(沿线性路径的进度— 0 表示初始,900 表示最终模型)。垂直轴— β(时间 T 时 SGD 重量与线性路径的距离)。图片来源

有趣的是,似乎随着 SGD 的发展,它有一个对称的发散和收敛模式。起初,它从它那里发散,然后在几乎完全对称的情况下,收敛回它那里。

让我们快速描述一下这些参数的数学。如果你只关心直觉,跳过下面的段落,或者如果你想自己运行这个实验,就参考 我的实现

让我们将 u 定义为从θi 指向θc 的单位向量,我们可以将θi 到θc 之间的线性路径描述为:θi + α(t)*u,其中α(t)是一个标量,表示“线上已经取得了多少进展”,定义为:

对于时间步长 t,计算 SGD 从初始化到收敛在直线上的投影进度。

现在我们有了α,它指定了我们沿着这条线前进的幅度。缺少的分量是离它的距离。让我们定义另一个单位向量 v ,它指向从θ_ t 到线上计划进度的方向。

对于时间戳 t,β是 SGD 的权重的范数(距离),来自它们在从初始化到收敛的线路上的预计进度。

这就是重现上述实验所需的全部内容!

这种现象适用于现代神经网络吗?

今天回顾 2014 年的那些结果,在深度学习领域取得巨大进展后,人们可能会要求重新审视原始论文中观察到的现象。事实上, Jonathan Frankle 在 2020 年对现代神经网络架构和数据集进行了实验,发现情况可能不如简单数据集上的简单架构好。

在 ImageNet 数据集上使用 ResNet-50 重新访问线性插值实验。从初始到收敛,损耗不再单调递减。图片来源

令人惊讶的是,在现代 NN 架构中,他没有发现这种现象发生。更奇怪的是,他发现在 ImageNet 上使用 ResNet-50 进行的这个实验导致了上面显示的奇特观察结果。沿着初始权重到收敛之间的线,损失保持几乎相同的值,然后少量增加并下降到收敛。

一种可能的解释(固执己见)

郝力等人的作品“可视化神经网络的损失景观”。艾尔。提供了一种可视化损失函数曲率的方法。使用他们的可视化方法(我将在以后的帖子中使用!)他们探讨了不同的网络架构如何影响损失情况。令人惊讶的是,将跳跃连接添加到深度神经网络中,可以显著减少从混沌到“几乎凸起”的景观,如下图所示。

对用 ResNet-50 观察到的现象的一种可能的(自以为是的)解释。如果我们假设 ResNet 的跳跃连接使损失函数“凸化”,它可以解释“在突然下降到全局最小值之前损失不变”的现象。图片来源

这一变化可能会弥合 Goodfellow 等人的现象。艾尔。发现于 2014 年,弗兰克尔发现于 2020 年。在图像的右侧,很明显,在初始化权重(假设在平坦区域的某处)和收敛权重之间有一个大的平坦插值区域。此外,在整个插值过程中,损失值变化不大。

总结一下实验方法,可以说它们给了我们一种关于优化问题难度的乐观感。这表明问题没有我们想象的那么难。我们如何严格证明(或反驳)这个假设?

DL 中的优化—一种理论方法

虽然实验方法产生了有助于我们将深度学习推向有趣的应用用途的传统智慧,但它并没有为我们所观察到的现象提供合理的解释,正如上一节中对现代架构的重新实验所看到的那样。具体来说,我将介绍一种方法,旨在更好地理解损失情况,从而了解其优化特征。另一种方法是理解梯度下降本身的轨迹,我将在以后的文章中介绍。

亏损景观有多好看?

Itay Safran 和 Ohad Shamir 的工作“关于过度指定的神经网络中初始盆地的质量”,试图通过模拟(非凸)损失函数的几何结构来解决这个问题。这种方法的动机是,希望我们会发现损失图便于优化(更具体地说,是本地搜索算法,如 SGD)。我们之前看到的关于经验上存在的单调递减路径的观察鼓励研究人员解释这一现象。

具体来说,这项工作提供了以下定理:给定一个全连通网络,它在初始化和收敛时的权重,以及一个凸损失函数,存在一个从该初始化点开始并以相同损失值(作为收敛点)的结束的单调递减路径。为了证明该定理,主要的重要假设是全零预测器的损失小于初始化时的损失

尽管现代神经网络不支持这种假设(由于权重初始化技术的最新进展),但他们的结果非常有趣,因为它与我们之前看到的经验结果一致。他们证明,在他们的假设下,有一个“优化的简单方法”。

虽然为他们的定理提供充分的证明和微妙的细节肯定超出了一篇博客文章的范围,但让我们试着理解一下总体思路。他们证明中的主要方法是为从初始到收敛的连续路径中的每个点创建,在单调递减路径中创建相应的点。它们是如何构造对应点的?它们为平方损失的特殊情况提供了直觉:

对具有 m 个样本的数据集,在由权重 W 参数化的神经网络N上评估的平方损失。

由于该目标下神经网络的最后一层是线性的,请注意,最后一层乘以某个标量 c ,对应于乘以网络的输出。因此,给定一些权重 W(λ) (其中0≤ λ ≤1 定义了初始化到收敛之间的路径),我们可以将最后一层乘以标量 c≥0,并接收相应的权重(用 W’表示),目的是:

的相应目标 W(λ) 通过将其最后一层乘以标量 c.

注意,对于 c=0,这个目标是 Y 的平均值。对于 c=∞,它也是∞的。它基本上是说(利用中值定理)我们可以调 c 得到从 Y 的均值到∞的任意客观值。现在剩下的就是为每个 W(λ)找到它对应的 c,这样我们就得到期望的单调递减路径!

视觉回顾

理解这个想法可能很有挑战性。为了让你更容易理解,我制作了(使用伟大的 manim 工具,源自 3B1B )一个简短的 GIF 来说明这个证明的想法:

从初始化到收敛,从连续路径构建相应的单调递减路径的可视化。视频来源:

可视化从蓝色曲线开始,表示从初始到收敛的连续但非凸的曲线。然后,它突出显示了“全零预测值假设”,并从中投射光线来构建单调递减路径。

结论

我们理解深度学习模型优化的第一步总体上是乐观的。以前的优化知识告诉我们,优化高维非线性和非凸问题是一个众所周知的难题。然而,在真实世界模型上的实验(FC/CNN/RNN)提供了乐观的结果。此外,对损失情况的理论分析也很乐观。在某种意义上,这两种方法(实验的和理论的)都表明,我们用 SGD 在深度学习中解决的问题可能比人们想象的要容易得多。

然而,跳到 2020 年,我们观察到用现代架构和数据集重新审视这些实验揭示了不同的现象。虽然从实践者的角度来看,这些早期的发现是令人鼓舞的,但是仍然需要 SGD 收敛背后的理论。幸运的是,研究人员近年来取得了显著的成果,其中一些采用了不同的景观方法,我将在未来的帖子中进行回顾。

确认

我要感谢 Nadav Cohen 在特拉维夫大学教授了一门关于深度学习理论的伟大课程。

文本分类的深度学习技术

原文:https://towardsdatascience.com/deep-learning-techniques-for-text-classification-78d9dc40bf7c?source=collection_archive---------2-----------------------

使用 Word2Vec 对您常用的深度学习架构评估基于 TCN 和集成的模型的性能

安妮·斯普拉特在 Unsplash 上的照片

A.介绍

A.1 .背景和动机

T ext classification 是 NLP 中最流行的任务之一,它允许程序根据预定义的类对自由文本文档进行分类。这些课程可以基于主题、流派或情感。今天,大量数字文档的出现使得文本分类任务变得更加重要,尤其是对于公司来说,以最大化其工作流程甚至利润。

近年来,自然语言处理在文本分类方面的研究已经达到了最先进的水平(SOTA)。它已经取得了惊人的成果,表明深度学习方法是执行此类任务的尖端技术。

因此,需要评估 SOTA 深度学习模型在文本分类方面的性能,这不仅是学术目的,也是人工智能从业者或专业人士在类似项目中需要指导和基准的必要条件。

A.2 目标

实验将在五个文本分类数据集上评估一些流行的深度学习模型的性能,如前馈递归卷积集成 - 基于神经网络。我们将在两个独立的特征提取之上构建每个模型,以捕捉文本中的信息。

结果显示:

  • 单词嵌入的鲁棒性作为所有模型的特征提取器,以做出更好的最终预测。
  • 基于集合的时间卷积神经网络在实现良好性能甚至与最先进的基准模型竞争方面的有效性。

B.实验

B.1 .数据集

表 1。标记化后的数据集统计。 *CV 代表交叉验证。这意味着原始数据集没有标准的训练/测试分割。因此,我们使用 10 倍 CV。

  • 先生。电影评论——将评论分为正面或负面[1]。链接
  • subject。主观性——将句子分为主观和客观两类[2]。 链接
  • TREC 。文本检索会议——将问题分为六类(人、位置、数字信息等)。) [3]. 链接
  • CR 。客户评论—对产品评论进行分类(相机、MP3 等。)作为肯定或否定[4]。 链接
  • MPQA 。多视角问答——观点极性检测[5]。 链接
  • 为了方便起见,我们在这里准备了 pickle 格式的数据集。

B.2 .提议的模型

B.2.1 .时间卷积网络(TCN)

白等人[6]提出了一个通用的时间卷积网络(TCN)作为扩张因果版本的 CNN。它是递归架构的强大替代,可以处理长输入序列,而不会遭受消失或爆炸梯度问题。如果您想了解更多关于模型块的信息,您可以参考[6]和[7]中的实现。

图一。TCN 的元素建筑。(来源:[6])

提议中的 TCN 模型是受 Kaggle 上的大师之一 Christof Henkel [8]的启发。该模型包括:

  • 内核大小为 3、膨胀因子为 1、2 和 4 的两个 TCN 块堆叠在一起。
  • 第一 TCN 块包含 128 个滤波器,第二块使用 64 个滤波器。输入特征将基于单词嵌入。
  • 每个块的结果将采取序列的形式。
  • 最终的序列然后被传递到两个不同的全局池层。
  • 接下来,两个结果被连接并传递到 16 个神经元的密集层,并传递到输出。

图二。提议的 TCN 模式。

表二。TCN 模型的超参数。

Python 和 TensorFlow 2 中 TCN 模型的实现。

b . 2.2 . CNN-GRU 合奏

K.Kowsari 等人[9]介绍了一种新的分类深度学习技术,称为随机多模型深度学习(RMDL)。该模型可用于任何分类任务。下图说明了使用深度 RNN、深度 CNN 和深度前馈神经网络(DNN)的架构。

图 3。对 RMDL 架构进行分类。(来源:[9])

在这个项目中,我们通过将 1D CNN 与单个双向 GRU (BiGRU) 相结合,实现了一个基于集成学习的模型。

  • 1D CNN 已经被证明在文本分类上工作得很好,尽管只有很少的参数调整[10]。
  • 另一方面,BiGRU 通过获取序列中较早和较晚的信息,可以很好地处理时态数据。

我们将在实验中看到这种组合如何影响模型精度。

图 4。提出了 CNN 和 BiGRU 相结合的集成学习模型。

集合 CNN-GRU 模型在 Python 和 TensorFlow 2 中的实现

B.2.3 .其他模型

为了比较性能,我们还将评估其他受欢迎的型号,例如:

  • SNN。一个浅层神经网络。

表 3。SNN 模型的超参数。

  • edRVFL。集成深度随机向量函数链接神经网络。

表 4。edr vfl 模型的超参数。

  • 1D 有线电视新闻网。我们的基线模型代表具有一维卷积和池层的神经网络。

表 5。1D CNN 模型的超参数

  • (堆叠)BiGRU/BiLSTM。双向门控循环单位/长短期记忆。它的堆叠版本意味着我们向网络添加了另一个双向块。

表 6。big ru/bil STM 模型的超参数

B.2.4 .模型摘要及其特征提取

总而言之,我们将在五个文本分类数据集上使用两种不同的特征提取来构建深度学习模型,如下所示:

表 7项目中使用的模型和特征提取的变体。 ***** 对所有模型来说,训练过程都是通过提前停止来完成的,模型会在超出训练数据之前停止训练

  • 我们——兰德。该模型使用嵌入层,在该层中,单词向量在训练期间被随机初始化和校正
  • 我们——静。该模型使用名为 Word2Vec 的预训练单词嵌入,具有 300 维向量。向量在训练期间保持静态。使用一般正态分布随机初始化未知单词的向量。
  • 我们——动态。同上,但向量在训练期间被修改,而不是静态的。
  • WE-avg。该模型使用来自预训练单词嵌入的向量的平均值来获得输入上下文。因此,输入特征的大小将与 word 2 vec 300 中使用的向量维数的大小相同。
  • 字袋(蝴蝶结)。在将文本输入模型之前,它将文本表示为文档中出现的单词数。我们将使用四个单词评分选项:二进制计数频率TF-IDF

这项工作中使用的基准是:

  • CNN-多频道 (Yoon Kim,2014)【10】
  • SuBiLSTM (悉达多梵天,2018) [11]
  • SuBiLSTM-并列(悉达多梵天,2018) [11]
  • USE_T+CNN (Cer et al .,2018) [12]

C.估价

结果

我们将使用准确性和排名作为比较指标。将根据每个数据集的准确性来计算等级。在有平局的情况下,我们平均他们的排名。

表 8 显示了各型号性能的最终对比。我们还包括 SOTA 基准模型(在底部)以供进一步观察。注意,我们只包括使用单词袋和平均单词嵌入的模型的最佳结果(SNN 和 edRVFL),

表八针对基准提出的深度学习模型。

表 8 中,我们可以计算出 5 个数据集上模型相对于基线 ( 1D CNN-rand )的平均精度差如下:

图 5。在 5 个数据集上,模型相对于基线的平均精度差

图 5 中,绿色条代表基准模型。紫色条描绘了超过基线的前六个建议模型。最后,红色柱是具有最低精确度的建议模型。减号(-)表示在以基线为参考的所有数据集中,该模型的精度远低于较高的模型。

从那里,我们可以计算平均等级值,并将结果可视化,如下所示:

图六。每个模型相对于基准的平均等级值

C.2 讨论

C.2.1. BoW 与单词嵌入

尽管有如此多的超参数调整,这个实验中带有 BoW 的模型不能做太多。大量的文本数据会使 BoW 的词汇变得广泛。因此,输入要素将是稀疏形式,通过许多零来表示一位信息。这种文本表示使模型更难训练以获得更好的结果。除非我们指定的词汇量不够大或者使用的语料库很小,否则 BoW 不是一个可靠的选择。

另一方面,当使用单词嵌入时,模型表现得更好。通过仅取 Word2Vec 的平均值来获得 N 维特征输入,该模型可以在精确度上有高达 10%的非常陡峭的增加。例如,在 TREC 数据集中,edRVFL 和 SNN 都从 75.2 和 76.2 突然跳到 83.6 和 85.8。这些结果证明了单词嵌入作为默认特征提取器的重要性。

C.2.2 随机、静态和动态

图 7。不同单词嵌入方式之间的平均准确率。

图 7 说明了不同的单词嵌入模式对模型性能的影响。正如所料,使用预先训练的 Word2Vec 的静态单词嵌入总是表现得更好。与随机模式相比,静态模式可以帮助任何模型更准确地预测类别,平均准确率提高 3%。

动态向量表示模型将微调由 Word2Vec 向量初始化的参数,以学习每个任务的有意义的上下文。理想情况下,它会比静态方法产生更好的性能。然而,情况并非总是如此。虽然模型还可以改进,但变化不大。在某些情况下,一个模型甚至可以有较低的准确性。

图 7 中,动态模式略微降低了 TREC 和 MPQA 数据集上的整体模型性能。在表 8 中,尽管 BiGRU-dynamic 在 SUBJ 数据集上比其静态版本提供了更好的性能,但它在其他数据集上的性能有所下降。这是因为向量调整到一个特定的数据集,该数据集可能会过度拟合并改变从 Word2Vec 派生的原始上下文。

c . 2.3 TCN 与 RNN 模式

如果我们使用单词嵌入,TCN 比 RNN 的模型如 LSTM 或 GRU 更有效。在五个数据集的四个中,TCN 以优异的精确度超过了所有 RNN 架构。在另一个数据集上,TCN 精度仍然很高,接近最高。TCN-静态和-动态作为顶级模型,其次是 BiLSTM-静态、big ru-静态和堆叠 big ru-静态。

简而言之,TCN 是最好的模型,不仅与 RNN 家族相比,而且在捕捉信息以做出稳定预测方面也与其他模型相比。在这个实验中,唯一能挑战 TCN 的模型是基于系综的模型。

C.2.4 整体与单一模型

正如所料,集成模型通常在几乎所有的分类任务中都优于单个模型。集合模型的静态版本在 5 个数据集的 3 个中提供了更好的性能。集成学习的关键是候选模型需要被证明在给定的任务中工作良好。在这种情况下,1D CNN 和 BiRNN 是结合用于文本分类的很好的模型。这一结果鼓励我们在未来尝试将一个有效的模型(如 TCN)与其他现有的良好深度学习模型相结合。

C.2.5 .表现最佳的模型

表 9。本论文排名前六的深度学习模型。

最后,表 9 总结了这一系列实验中的最佳模型。我们使用图 5 中的平均准确度裕度和图 6 中的平均等级值来比较前六个用于文本分类的执行模型。我们可以看到,静态版本的 TCN 和集合模型脱颖而出,成为最好的。

接下来,TCN 动力紧随其后,成为最佳车型,跻身前三名。最终,TCN 和基于集成的模型在执行文本分类任务时优于其他配置,使它们成为未来应用和研究的最佳推荐架构。

D.结论和未来工作

D.1 .结论

该项目展示了一个全面的实验,重点是在五个文本分类数据集上使用两种不同的特征提取来构建深度学习模型。总之,以下是基本的见解:

  • 任何建立在单词嵌入之上的模型都会使模型表现得非常好。
  • 使用预先训练的单词嵌入,例如 Word2Vec,可以在很大程度上提高模型精度。
  • TCN 是递归架构的一个很好的替代方案,已经被证明在文本数据分类中是有效的。
  • 与单独训练的单一模型相比,基于集成学习的模型可以帮助做出更好的预测。
  • TCN 和集合 CNN-GRU 模型是我们在这一系列文本分类任务中获得的性能最好的算法。

D.2 .对未来工作的建议

我们对未来的实验提出如下建议:

  • 基于集合的 TCN 模型。在基于集成的学习中,使用 TCN 结合其他良好的模型(如 1D CNN 和 BiGRU)来执行文本分类任务,以查看它是否能够挑战基准
  • 内核大小和过滤器。通过在 CNN 或 TCN 中使用更多或更少的过滤器将内核大小扩展到 1 到 10 之间来探索这两个超参数,以查看它如何影响模型性能。
  • 更深的人脉。任何具有更多隐藏层的神经网络通常会在任何任务中做得更好。探索 CNN、RNN 和 TCN 的更深版本,看看它如何影响现有的性能。
  • 使用手套和快速文本。探索其他预训练的单词嵌入选项,如具有静态和动态模式的 GloVe 和 FastText,并将结果与 Word2Vec 进行比较。

谢谢你,

diardano Raihan
LinkedIn 简介

: 你看到的一切都记载在 我的 GitHub 资源库 。对于那些对完整代码感兴趣的人,请访问👍。

参考

  • [1] B. Pang,L. Lee,“看见星星:利用阶级关系进行情绪分类的等级量表”,美国癌症学会 2005 年会议录
  • [2] B. Pang,L. Lee,“情感教育:使用基于最小割的主观性摘要进行情感分析”,计算语言学协会第 42 届会议论文集(ACL'04) ,2004 年。
  • [3] X .李,d .罗思,“学习疑问量词”,载于《中国林业学报》2002 年第 02 期第 19 期。
  • [4] M .胡,b .刘,“客户评论的挖掘与汇总”,《学报》2004 年 04 期
  • [5] J. Wiebe,T. Wilson,C. Cardie,“用语言注释观点和情感的表达”,语言资源和评估,39(2):165–210,2005。
  • [6] S. bai,J. Kolter,V. Koltun,“序列建模通用卷积和递归网络的实证评估”, arXiv ,2018 年 4 月。
  • [7] P. Rémy,《凯拉斯·TCN》,GitHubhttps://github.com/philipperemy/keras-tcn,1 月。2021.
  • [8] C. Henkel,《时态卷积网络》, Kagglehttps://www . ka ggle . com/christofhenkel/时态卷积网络,2021 年 2 月。
  • [9] K. Kowsari,M. Heidarysafa,D. E. Brown,K. J. Meimandi,L. E. Barnes,“用于分类的随机多模型深度学习”, arXiv ,2018 年 4 月。
  • [10] Y. Kim,“用于句子分类的卷积神经网络”,计算语言学协会,2014 年 10 月。
  • [11] S. Brahma,《使用后缀双向 LSTM 的改进句子建模》, arXiv ,2018 年 9 月。
  • [12] D. Cer,Y. Yang,S. Kong,N. Hua,N. Limtiaco,R. S. John,N. Constant,M. Guajardo-Cespedes,S. Yuan,C. Tar,Y. Sung,B. Strope,R. Kurzweil,《通用句子编码器》, arXiv ,2018 年 4 月。

深度学习:理解原理

原文:https://towardsdatascience.com/deep-learning-understand-the-principle-ad146d9f54dd?source=collection_archive---------62-----------------------

温和的介绍。它解决了什么问题,为什么是分层结构

安迪·凯利在 Unsplash 上的照片

深度学习(DL)是机器学习(ML)的一种,它使用更高级的策略来解决任务。对计算机程序来说很复杂,但对我们来说却很简单的问题。如语音和图像识别[1]。

当我们看到一辆车时,我们在一瞬间就知道它是什么。无论是造型,从哪个角度还是灯光都不重要。我们很容易识别图案,并与其他物体区分开来。为什么传统的机器学习系统做不到这一点?例如,它们很适合推荐系统。

困难在于一幅图像或一句话可能有大量不可预测的变化。而在推荐系统中,一般来说,它是关于了解这个人和其他人的偏好[2],对于图像或语音,它更复杂。

例如,想象一辆汽车有四个轮子、窗户和一个方向盘。你训练程序输入这些信息。简单对吗?但是在一天中的特定时间,有阴影模糊了两个轮子,或者一个人靠在上面。想想语音识别!某个单词有多少种发音方式?想象一下所有不同的口音。这使得机器很难。当它认为它学会了,另一个特征就出现了。

另一个例子是识别手写数字。一个人可以用多少种方法来写一个东西?!参见图 1。你会看到,例如,九有不同的表示方式。同样的道理也适用于其他数字。这些差异弥补了完全不同的像素值。

图一。来自 MNIST 数据集[1]的部分数字

深度学习通过将对象分解成更小更简单的组件来解决问题。虽然图像看起来不同,但它们之间有一些看起来相同或相似的部分。有一种模式。

它将对象/概念作为分层结构来处理,每一层都是下一层的抽象。根据成分的粒度,它可以深入(因此得名)[1]。例如,一个中型的故事可以分为段落,然后它可以分为短语,然后是单词,最后是字符。****

图二。故事作文。由作者创作。

有三种类型的层。输入,隐藏的和输出。它们由节点或神经元组成(与大脑类似)。节点被分配了代表图像一部分的像素。

  • 输入:可见图像。它包含所有像素。如果图像是 10x10 的网格,则该层将包含 100 个节点。
  • 隐藏:组成图像的部分。它们被称为“隐藏的”,因为它们不是给定数据的一部分[1]。第一隐藏层可以包含边缘;第二,角和轮廓,以及更具体的部分。隐藏层的数量可以变化。每一个节点的数量。这取决于确定哪些部分/概念有助于解释观察到的对象[1]。
  • 输出:被识别的对象。每个可能的对象都有一个节点。

下面的图 3 展示了分层结构。(它没有考虑所有的节点和实际值。这更像是一种高层次的表现)

图 3。分层结构[1]。

最后的想法

感谢阅读。希望你觉得有用。虽然它没有解释算法的数学和细节,但它为您提供了一个良好的基础。至少这是我的意图。

最后一件事。常见的是读到 DL 试图模仿我们人类的思维方式。那在某种程度上是正确的。然而,我们并不确定我们是如何识别物体的(根据我的研究,在写这篇文章的时候)。关于我们大脑所使用的算法,我们知之甚少。尽管如此,我相信这并不重要,只要机器能做好。就像一架可以不完全按照鸟类力学飞行的飞机。

参考

[1]伊恩·古德费勒,约舒阿·本吉奥和亚伦·库维尔,深度学习,2016 年

[2]用于视频游戏 https://scholar.google.com/scholar?的机器学习项目推荐系统 q =推荐+系统+机器+学习&HL = en&as _ SDT = 0&as _ vis = 1&oi = schol art # d = GS _ qabs&u = % 23p % 3d 8 hjshbe 4 fwkj

【3】大脑如何解决视觉物体识别?https://www.ncbi.nlm.nih.gov/pmc/articles/PMC3306444/

表格数据上的深度学习与 GBDT 模型—带代码片段

原文:https://towardsdatascience.com/deep-learning-vs-gbdt-model-on-tabular-data-with-code-snippet-e4b3dd525552?source=collection_archive---------7-----------------------

TabNet、MLP 和 XGBoost 在家庭保险数据集上的性能比较实验

法托斯 BytyqiUnsplash 上的照片

在数据科学领域,深度学习方法无疑是最先进的研究。每天都有许多新的变体被发明和实现,特别是在 NLP(自然语言处理)和 CV(计算机视觉)领域,深度学习近年来取得了很大进展。这种趋势也可以在 Kaggle 比赛中观察到。在那些 NLP 和 CV 任务竞赛中,最近获胜的解决方案正在利用深度学习模型。

然而,深度学习模型真的比 GBDT(梯度推进决策树)这样的“传统”机器学习模型更好吗?我们知道,如上所述,深度学习模型在 NLP 和 CV 中要好得多,但在现实生活中,我们仍然有如此多的表格数据,我们是否可以确认深度学习模型甚至在结构化数据集上比 GBDT 模型表现得更好?为了回答这个问题,这篇文章使用了来自 Kaggle 的家庭保险数据集来比较每个模型的性能。我知道我们不能仅凭一个数据集就断定哪个模型更好,但这将是一个很好的比较起点。还有,我会使用 TabNet,这是一个相对较新的深度学习模型,用于表格数据进行比较。

本次实验的笔记本可以在我的 kaggle 笔记本中找到:主笔记本和带预训的 TabNet。这篇文章将省略每个算法的解释,因为已经有很多算法了:)

目录

1:本次实验的总结和代码片段

2:模型性能

3:可解释性

4:现实业务中部署的模型选择

5:结论

埃利安·贾沙里在 Unsplash 上拍摄的照片

1:本次实验的总结和代码片段

如上所述,这个实验使用了家庭保险数据集。该数据集包括 2007 年至 2012 年间的房屋保险单数据,有超过 100 个关于房屋特征、业主人口统计数据等的可用特征,该数据中有超过 250,000 行。使用这个数据集,这个实验试图预测一个家庭保险政策是否会失效。不幸的是,并没有给出这个数据集中所有变量的细节,但是做这个实验已经足够好了。

现在我将检查这个实验的代码。这是最低限度,应该很明显会发生什么。

首先,导入库。

然后,创建一个定时器函数,

这样我们可以跟踪函数运行需要多长时间。

这是数据集的预处理。这一过程包括

1.排除缺失值
2。清洁目标变量
3。为分类变量
4 创建虚拟变量。创建年龄特征
5。估算缺失值

为了训练和评估模型,我将拆分数据集。

用深度学习模型训练数字特征需要标准化。这个函数完成这项工作。

现在所有的预处理都完成了。下面,我将展示每个模型的训练代码。

XGBoost

MLP (1D 有线电视新闻网)

无预训练的 tab net

带预训练的 tab net

预处理部分

TabNet 训练可以通过上面的同一个函数“trainTabNetModel”来完成。

训练完成后,我们将需要对测试集进行预测和评估。

预测

评估

剧情

最后,这是上面运行的主要脚本。

以上是代码片段。现在我们将在接下来的章节中看到这个实验的结果。

2:模型性能

如上所述,这里比较了 XGBoost、MLP 和 TabNet 在有和没有预训练的情况下的模型性能。采用 ROC AUC 评分和 F1 评分对模型进行评价。F1 分数计算为 0.27 作为阈值,因为我假设失效保险的分布类似于培训分布。下面是对它的总结。

正如我们所看到的,就模型的准确性而言,XGBoost 模型是最好的一个,然而其他模型也紧随其后。我对 TabNet 模型使用了带和不带预训练(不带预训练 TabNet 的笔记本可以在这里找到)。有预训练的 TabNet 应该有更好的结果,但是在这个数据集中,它得到的结果比没有预训练的稍差。我不确定确切的原因是什么,但我猜这可以通过适当的超参数来改善。

当我们研究每个模型的预测分布时,我们可以观察到 XGBoost 和 TabNet 模型之间存在一定程度的相似性。我猜这可能是因为 TabNet 也使用了一种基于树的算法。MLP 模型与其他模型相比有很大的不同。

就训练时间而言,MLP 模型是最快的。我用过 GPU,所以这是我得到这个结果的主要原因。与其他模型相比,这两个 TabNet 模型花费了相当长的时间。当涉及到超参数调谐时,这就产生了很大的差异。在这个实验中,我没有做任何超参数调优,使用了任意参数。虽然 MLP 的训练时间几乎是 XGBoost 模型的 1/3,但它需要优化的参数数量是 XGBoost 的 10 倍以上,因此,如果我进行超参数调整,它可能需要比 XGBoost 模型的超参数调整训练更长的时间。

3:可解释性

可解释性对于一些机器学习模型业务用例来说非常重要。例如,能够解释为什么一个模型在金融/银行业做出一个特定的决定是至关重要的。假设我们正在部署一个可用于贷款审批的模型,一个客户想知道他的申请为什么被拒绝。银行不能告诉他我们不知道,因为该行业有强有力的监管机构。

模型的可解释性是 MLP 模型的缺点之一。虽然我们仍然可以通过使用一些方法来评估哪些功能有助于做出预测,例如使用 SHAP ,但是如果我们能够快速检查功能重要性列表,将会更加有用。在这本笔记本中,我将只比较 XGBoost 和 TabNet 模型的特性重要性。

XGBoost 模型的前 5 个重要特性是:

  • 婚姻状况——伴侣
  • 付款方式—非直接借记
  • 第一次续订后包括“紧急情况”选项
  • 建筑物保险-自我损害
  • 第一次续订前包含“更换钥匙”选项

无预训练的 TabNet 模型的前 5 个重要特征是:

  • 财产类型 21(未给出细节)
  • 第一次续订前包含“HP1”
  • 付款方式—纯直接借记
  • 会员类型 6(未给出详细信息)
  • 保险期限(年)

令人惊讶的是,这两个模型的重要特征完全不同。XGBoost 的重要功能对我来说更“可理解和可预期”—例如,如果客户有一个合作伙伴,那个人应该在经济上更负责任,因此,房屋保险不太可能失效。另一方面,我认为 TabNet 的重要特性不够直观。最重要的特性是“属性类型 21”,这里没有给出这个特性的细节,所以我们不知道这个属性类型有什么特别之处。这也是第二重要的功能,在第一次更新之前包括了“HP1”,我们也不知道什么是“HP1”。也许,这可以成为 TabNet 的一个优势。由于它是一个深度学习模型,所以它可以探索特征之间的非显而易见的关系,并使用最佳特征集,特别是像这次一样,其中没有给出所有特征的细节。

4:现实业务中部署的模型选择

当我们想要在现实生活的业务中使用机器学习模型时,我们需要选择部署模型的最佳方式,通常会有一些权衡。例如,众所周知,当我们像这次一样建立几个模型时,这些模型的精确度非常相似,将它们集成可能会提高精确度。如果这种组合策略非常有效,比如将 F1 成绩提高了 10%,那么采取这种策略是绝对必要的,但如果这种提高只有 1%,我们还想采取这种策略吗?大概不会吧?—由于多运行一个模型会增加计算成本,因此通常如果多部署一个模型的好处超过了计算成本,我们可以采取这种集成策略,否则,从业务角度来看,这不是最佳策略。

此外,关于模型的可解释性,XGBoost 模型使用了所有 115 个特征,而 TabNet 模型只使用了 16 个特征(预训练模型只使用了 4 个特征)。这是一个巨大的差异,理解这些差异也很重要。正如我上面提到的,在一些真实的业务用例中,了解这些特性做出了多少贡献是非常关键的。因此,有时虽然准确性很高,但如果模型无法解释为什么它会做出这样的决定,就很难说服人们在现实生活中使用它,特别是在非常敏感的业务中。

考虑到以上 2 点,我们会认为 XGBoost 模型在这种情况下优于其他深度学习模型。就准确性而言,XGBoost 模型比其他模型稍好一些(我没有尝试从所有模型中整合这些预测,但让我们假设,它并没有提高多少准确性——我可能是错的)。就可解释性而言,如上所述,XGBoost 模型的特性重要性列表在某种程度上是我们可以理解的(我们可以看到它背后的一些逻辑),也是我们所期望的。

5:结论

本笔记本在表格数据上实验性地比较了 XGBoost、MLP 和 TabNet 的模型性能。在这里,我们使用家庭保险数据集来预测它的失效。作为这个实验的结果,我们看到 XGBoost 模型在准确性方面(F1 得分和 ROC AUC 得分)略好于其他深度学习模型,但由于这个实验使用了 GPU,MLP 模型是最快完成其训练的。此外,我们通过查看 XGBoost 模型和 TabNet 模型的特征重要性列表来比较它们的可解释性。XGBoost 模型的特性重要性列表在某种程度上更容易理解和预期,另一方面,TabNet 模型的列表不太直观。我认为这是由于算法的结构造成的——深度学习模型本质上探索特征的非显而易见的关系,通常很难被人类理解。从这个简单的实验中,我们确认,尽管近年来深度学习模型的改进令人印象深刻,而且绝对是最先进的,但在表格数据上,GBDT 模型仍然与那些深度学习模型一样好,有时甚至更好,特别是当我们想要在现实生活的业务中部署机器学习模型时。

用容器进行深度学习。第二部分

原文:https://towardsdatascience.com/deep-learning-with-containers-part-2-6495da296f79?source=collection_archive---------29-----------------------

利用部署在容器中的深度学习堆栈,轻松进行实验和跟踪。

Hanson LuUnsplash 上的照片

的上一篇文章中,我们用 Docker Compose 建立了一个多容器应用程序,其中一个容器负责托管 Jupyter 笔记本环境,另一个容器保存 Tensorboard 部署。容器将通过作为卷从主机挂载的目录进行通信。

今天的主要目标是了解这种设置是如何工作的,以及它如何实现简单的实验跟踪。为此,我们将开始致力于创建一个新闻推荐系统,该系统将(显然)由神经网络支持。与任何推荐系统一样,它将提出前 10 名最相似的新闻,神经网络将生成向量,我们将使用这些向量来衡量相似性。我们将要创建的神经网络的主要内容是:

  1. 数据集。我们将使用微软新闻数据集(MIND) [ 1 ],其中包含大约 160,000 篇英语新闻文章。具体来说,我们将计算新闻标题和摘要之间的相似度。
  2. 神经网络。我们将使用 DistilBERT Transformer 网络作为主干,并添加几个附加层来生成合理大小的嵌入。
  3. 培训。我们将采用暹罗学习来训练网络,以区分嵌入空间中相似和不相似的项目。

这篇文章使用的所有代码都可以在这里找到。

让我们浏览一些理论并开始实验。

连体学习

这个概念存在了很长时间,并在许多领域获得了很大的普及,尤其是在计算机视觉领域[ 234 。暹罗学习的主要思想是训练一个神经网络来区分相似和不相似的样本。所谓相似,我们通常是指属于同一类。为此,神经网络从样本中生成 N 维嵌入,并使用它们之间的距离来计算损失。我们可以把 N 维嵌入想象成一个样本在 N 维空间中的坐标。训练的目标是确保相似的物品在这个空间中是靠近的,而不相似的物品彼此远离。我们使用专门的损失函数进行连体学习,其中最广泛使用的是对比损失[ 5 和三重损失[ 6 ]。在我们的实验中,我们将使用三重态损失函数。三重缺失的连体学习的图式如下图所示。

对于具有三元组丢失的连体训练,每个训练实例应该是一组三个样本——锚、负和正——称为三元组。我们首先通过神经网络传递这些样本,以生成三个嵌入向量。之后,我们计算锚和负向量(D_neg)以及锚和正向量(D_pos)之间的欧几里德距离。之后,我们计算 D_pos 和 D_neg 加上预定义的保证金 m 之间的差值,最终损失是该差值和零之间的最大值。这意味着,只有当锚点与负样本的距离比与正样本的距离更近,且比边缘值更近时,三元组才会影响神经网络的权重(损失大于零)。下图显示了这种效果的直观描述。

我们将在实验中使用的 PyTorch 三重态损耗实现如下:

神经网络

我们的神经网络将基于 DistilBERT 模型[ 7 ],这是一个广泛流行的模型,因为它虽然相对较轻,但却能产生非常好的嵌入。感谢伟大的拥抱人脸库,我们只用一行代码就可以得到一个功能齐全的预训练网络。我们将要试验的整个神经网络如下所示:

数据准备

为了训练神经网络,我们需要生成三元组。MIND dataset 包含每篇文章的类别和子类别。我们将使用类别作为三元组生成的属性,因为在数据集的 200 多个子类别上训练网络会困难得多。

三胞胎的生成过程如下:

  1. 对于每个类别,选择固定数量(班级规模,CS)的项目。如果我们有 N 个类别,作为这一步的结果,我们将有 N*CS 个项目。
  2. 对于每个项目(锚点),从同一类别中随机选择一个项目(正面),从其他类别中随机选择一个项目(负面)。此时,我们有 N*CS 个三胞胎。
  3. 重复步骤 2 CN(连接数)次。最后我们会有 NCSCN 三胞胎。
  4. 跟踪三元组并防止产生重复。

该算法不包括硬否定挖掘,但我们希望随机性将有助于生成足够好的数据集。你可以在这里找到生成三胞胎的函数。

跟踪

我们将跟踪这一系列实验的训练过程的两个主要组成部分——损失值(训练和验证)和参数(M、CS、TI、时期数等)。).Tensorboard writer 提供了一个函数 add_scalar 用于写入损耗值,这些值稍后可以可视化为我们稍后将看到的漂亮图形。在 Jupyter 笔记本中,你可以找到向 Tensorboard 报告的三种类型的损失——培训、验证和跑步。第三个不是完全必要的,但有助于更好地看到训练动态,并满足等待的不耐烦。为了存储和写入实验的参数,我们使用一个字典,其中键是参数的名称,值是参数值。训练后,使用 add_hparams 函数将该字典写入 Tensorboard。

实验

让我们首先检查仅使用预训练的模型是否足以获得好的结果。

蒸馏矢量,无需训练

我们将设置一个相对较低的裕度 M=3,并使用 DistilBERT 输出的[CLS]令牌作为嵌入,仅运行验证步骤。结果,我们得到了 2.47 的验证损失,这远远不能令人满意,因为它只是比 M 稍低,而比零高得多。意味着我们还需要训练网络!

影响训练过程和结果质量的三个主要参数是 M(余量)、CS(类别大小)和 TI(每个项目三个一组)。我们将从 M=3,CS=30,TI=10 开始。这为我们提供了数据集中的 4,371 个项目,我们将这些项目分成 4/1 个训练和验证数据集。下面的结果表明,该网络很快掌握了正在发生的事情,并将训练(左)和验证(右)损失降至几乎为零。

M=3,CS=30,TI=10

现在,我们将检查网络是否会对更大的裕量 M=5 做同样的事情。在三个时期之后,验证数据集结果高于 M=3,所以我增加了一个时期,之后训练和验证的损失都开始增加。似乎没有足够的数据供网络学习。

M=5,CS=30,TI=10

让我们将参数更改为 CS=60 和 TI=20,这样总共得到 17,060 个三胞胎。该数据集允许通过仅进行一次额外的迭代,在验证损失方面获得与 M=3 相同的结果。但值得一提的是,整个培训过程要长 6 倍。

橙色轨迹— M=3,CS=30,TI = 10 洋红色走线— M=5,CS=60,TI=20

这时,你可能会问:“为什么我们不把摘要和标题一起用于训练呢?”。好主意!为此,我们需要对网络的架构做一些小的改变——通过转换器部分传递标题和抽象令牌,然后连接[CLS]令牌,并将结果向量传递给线性层。从结果中,我们可以看到,在四个时期之后,网络过度适应训练集。我们可以通过 CS 和 TI 增加数据集来解决这个问题,但这将导致更长的训练时间来获得与没有摘要的情况相同的质量。因此,为了简单起见,我们将放弃使用抽象进行嵌入的想法。如果您有兴趣尝试抽象,我在笔记本中添加了 PyTorch 数据集和网络类。

洋红色痕迹—仅标题,M=5,CS=60,TI = 20 灰色轨迹—标题+摘要,M=5,CS=60,TI=20

现在,我们将以更大的裕量 M=10 来挑战我们的网络。从结果中,我们可以看到,对于小数据集和 M=5,我们没有足够的数据用于网络来区分具有如此大幅度的类-第三个历元后的验证损失平稳期。

洋红色轨迹— M=5,CS=60,TI = 20 蓝色轨迹——M = 10,CS=60,TI=20

因为我们已经知道解决这个问题的方法,所以我们将 CS 增加到 100,TI 增加到 30。具有 42,257 个三元组的数据集有助于实现验证损失的期望动态,并且在第四次迭代后其下降到 0.1 以下。

洋红色轨迹— M=5,CS=60,TI = 20 蓝色轨迹— M=10,CS=100,TI=30

对于我们实验的最后一步,我们将检查网络是否能够克服非常大的裕度 M=30。为此,我们显然需要增加数据集。当 CS=200,TI=50 时,我们得到一个相当大的数据集,有 140,257 个三元组。培训结果如下所示。我们可以看到,网络努力获得对数据集的良好“理解”,但在第五个时期后,它设法将验证损失降至 0.13。现在,我们将把这当作一个好的结果,到此为止。

蓝色轨迹— M=10,CS=100,TI = 30 绿色轨迹— M=30,CS=200,TI=50

另外,我想提一下 Tensorboard 的参数跟踪部分。下面的表格显示了每次我进行训练时,笔记本自动记录的所有参数。写这篇文章非常方便,因为在运行这些实验后的一个星期内,我将无法记住它们中的任何一个。

结论

在关于在容器化环境中运行深度学习的系列文章的第二部分中,我们研究了如何使用 Tensorboard 跟踪模型的性能及其参数。因为 Jupyter 和 Tensorboard 都运行在 Docker 容器中,所以您可以确保库和它们的文件不会分散在您的系统中。在任何时候,您都可以通过一个简单的docker compose down 命令完全释放您的硬件资源。

在本系列的最后一部分中,我们将研究如何为最有效的推理准备训练好的模型,并基于该模型用不到 100 行代码创建一个成熟的 web 应用程序。

利用 Python 深度学习进行裂缝检测

原文:https://towardsdatascience.com/deep-learning-with-python-for-crack-detection-eceeeb3e182e?source=collection_archive---------4-----------------------

实践教程

利用人工智能将结构检测带入 21 世纪!

问题陈述

虽然新技术几乎改变了我们生活的方方面面,但建筑领域似乎正在奋力追赶。目前,建筑物的结构状况仍然主要由人工检查。简而言之,即使在今天,当一个结构需要检查任何损坏时,工程师也会手动检查所有表面,并拍摄大量照片,同时记录任何裂缝的位置。然后需要在办公室再花几个小时来整理所有的照片和笔记,试图做出一份有意义的报告。显然,这是一个费力、昂贵且主观的过程。除此之外,还会出现安全问题,因为建筑物的某些部分存在出入限制,很难到达。举个例子,金门大桥需要定期检查。换句话说,直到最近,还会有受过特殊训练的人爬过这座风景如画的建筑,检查它的每一寸。

金门大桥(照片由免费提供-照片Pixabay 上)

幸运的是,如今在存在可访问性问题的情况下,无人机(如无人机)被部署来拍照,但人们仍然需要花费数小时来检查每张照片是否有损坏的迹象。

这就是我们革新检测过程的工作。人工智能占据主导地位,更具体地说,深度学习通过训练我们的机器来代替人类完成检测结构照片裂缝的乏味任务。

从照片中检测裂缝有三个级别:

图像被分成小块,每个小块被分配一个裂纹或非裂纹标签

在任何检测到的裂缝周围绘制一个矩形

每个像素被标记为有裂纹或无裂纹

使用图像块分类(左)、边界框回归(中)和像素分割(右)进行裂缝检测( Dais 等人,2021 )

虽然已经针对混凝土表面或沥青广泛研究了用于裂缝检测的深度学习方法,但是对于基于视觉的评估,特别是应用于砖砌体表面的缺陷检测,很少进行研究。作为我和导师博士研究的一部分,我们试图弥合这一差距。我们工作的重点是在补丁和像素级别上检测砖石表面照片上的裂缝。关于我们研究的更多细节可以在我们的开放存取期刊论文中找到。与实现深度学习模型相关的代码、数据和网络可以在我的 GitHub 库【2】中找到。

数据集准备

训练深度学习模型最重要的部分是数据;模型的准确性很大程度上依赖于数据的质量和数量。真实世界的表现越好,模型能够在真实结构上精确工作的机会就越高。毫无疑问,与混凝土或沥青相比,砖石的表面不太均匀,噪音也大得多。此外,没有可用的砖石表面有裂缝的照片数据集。为了解决数据缺乏的问题,我在网上查找相关的照片,同时我用相机拍下了格罗宁根市中心的所有裂缝!

对已开发的深度学习方法的一个常见批评是,当在单调背景上测试时,它们获得了显著的结果,但当部署在复杂背景的图像上时,它们的准确性严重下降。诸如窗户、门、装饰品、标签、灯、电缆、植物等物体。可以被表征为裂纹检测过程的噪声,并且网络需要学习去否定它们以准确地检测裂纹。因此,在拍照时,这些物体也被有意包含在内。

因此,从包含复杂背景的砖石结构的照片中准备了一个广泛的数据集,现在我们准备好了下一步:训练深度学习模型。

有裂缝和无裂缝结构的图像(戴斯等人,2021

可在建筑物正面发现的物体( Dais 等人,2021 )

培训模式

请准备好主菜!

关于小块水平上的裂缝检测,本文检验了在 ImageNet 上预训练的不同技术状态的 CNN 将来自小块水平上的砌体表面的图像分类为裂缝或非裂缝的有效性。考虑的网络有:VGG16、MobileNet、MobileNetV2、InceptionV3、DenseNet121、DenseNet169、ResNet34 和 ResNet50。预训练的 MobileNet 获得了最好的结果,这是一种轻量级网络,注定要在计算有限的平台上运行。特别是,预训练的 MobileNet 得分准确率为 95.3%,而当不考虑预训练时,准确率下降到 89.0%。

使用 MobileNet 获得的混淆矩阵( Dais 等人,2021 )

对于裂缝分割 U-net 和特征金字塔网络,考虑了一种通用金字塔表示法,并与作为网络编码器部分主干的不同 CNN 相结合【3】。用作主干的 CNN 是以前用于补丁分类的网络。此外,基于 VGG16 网络的 DeepLabv3+、DeepCrack 和 FCN 在裂缝分割的文献中成功使用,也在广泛的比较研究中进行了检验。

U-net-MobileNet (U-Net 作为基础模型,MobileNet 作为主干)和 FPN-InceptionV3 (FPN 作为基础模型,InceptionV3 作为主干)获得了最高的 F1 分,即 79.6%。未经预训练的 U-net 和 U-net-MobileNet 的原始实现达到了相似的 F1 分数,分别为 75.7%和 75.4%。因此,使用预训练的网络作为主干将 F1 分数提高了约 4%。再一次,迁移学习似乎很有用!

用于裂缝分割的数据集的特征在于严重的类别不平衡,即背景类别占据了照片的最大部分,而裂缝在有限的像素上延伸。由于这种不平衡,如果不采取特殊措施,网络倾向于在预测背景类别时变得过于自信,这可能导致裂缝的错误分类和大量的假阴性。为了克服这一点,研究了不同的损失函数。加权交叉熵损失函数优于其他函数,它允许网络通过增加正错误的成本来关注正类。

原始图像、地面真相和使用 U-net-MobileNet 的预测(戴伊等人,2021

结论

通过我们的研究,我们展示了建筑行业的现代化,特别是检验过程的现代化是可能的。当然,这些新技术有无限的可能性,只有通过进一步的研究才能发现。

目前,我们收集更多的数据,进一步开发裂缝检测过程,并将其与 3D 场景重建相结合,以自动记录裂缝并进行度量测量。

利用 3D 场景重建进行裂缝检测(图片由作者提供)

所以,跟着我保持更新!😊

👉https://www.linkedin.com/in/dimitris-dais/

参考

[1]戴斯、i̇.e.·巴尔、斯米罗、萨霍西斯,利用卷积神经网络和迁移学习对砌体表面裂缝进行自动分类和分割,建筑自动化。(2021)第 125 页,第 103-606 页。https://doi.org/10.1016/j.autcon.2021.103606

[2]砌体表面裂缝检测:GitHub 知识库【https://github.com/dimitrisdais/crack_detection_CNN_masonry

[3]https://github.com/qubvel/segmentation_models

Python 深度学习:神经网络(完整教程)

原文:https://towardsdatascience.com/deep-learning-with-python-neural-networks-complete-tutorial-6b53c0b06af0?source=collection_archive---------0-----------------------

作者图片

用 TensorFlow 建立、绘制和解释人工神经网络

摘要

在这篇文章中,我将展示如何用 Python 构建神经网络,以及如何使用可视化和创建模型预测的解释器向业务解释深度学习。

作者图片

深度学习 是一种模仿人类获取某些类型知识的方式的机器学习,与标准模型相比,它在这些年里变得更受欢迎。虽然传统算法是线性的,但深度学习模型,通常是神经网络,堆叠在复杂性和抽象性不断增加的层次结构中(因此是深度学习中的“深度”)。

神经网络 基于一组相互连接的单元(神经元),这些单元就像大脑中的突触一样,可以向其他神经元传递信号,这样,它们就像相互连接的脑细胞一样,可以以更像人类的方式学习和做出决定。

今天,深度学习非常受欢迎,许多公司都想使用它,即使他们并不完全理解它。通常,数据科学家首先必须为业务简化这些复杂的算法,然后解释和证明模型的结果,这对于神经网络来说并不总是简单的。我认为最好的方法是通过想象。

我将展示一些有用的 Python 代码,这些代码可以很容易地应用于其他类似的情况(只需复制、粘贴、运行),并通过注释遍历每一行代码,以便您可以复制这些示例。

特别是,我将经历:

  • 环境设置,tensor flowvspy torch。
  • 人工神经网络分解,输入,输出,隐藏层,激活函数。
  • 用深度神经网络进行深度学习。
  • 使用 tensorflow/keras 进行模型设计。
  • python 实现神经网络可视化。
  • 模型培训和测试。
  • 形状解释。

设置

构建神经网络的库主要有两个:tensor flow(Google 开发)和py torch(脸书开发)。他们可以执行类似的任务,但前者更适合生产,而后者则适合快速构建原型,因为它更容易学习。

这两个库受到社区和企业的青睐,因为它们可以利用 NVIDIA GPUs 的强大功能。这对于处理大型数据集(如文本集或图片集)非常有用,有时也是必要的。

对于本教程,我将使用 TensorFlowKeras ,这是一个比纯 TensorFlowPyTorch 更友好的高级模块,尽管速度稍慢。

第一步是通过终端安装 TensorFlow ;

pip install tensorflow

如果你想启用 GPU 支持,你可以阅读官方文档或遵循本指南。设置好之后,你的 Python 指令会被你的机器翻译成CUDA并由 GPU 处理,这样你的模型运行起来会快得令人难以置信。

现在,我们可以在笔记本上导入来自 TensorFlow Keras 的主要模块,并开始编码:

*from **tensorflow**.keras import models, layers, utils, backend as K
import **matplotlib**.pyplot as plt
import **shap***

人工神经网络

人工神经网络由具有输入和输出维度的层组成。后者由神经元(也称为“节点”)的数量决定,这是一个通过激活函数(帮助神经元打开/关闭)连接加权输入的计算单元。像大多数机器学习算法一样,在训练期间随机初始化和优化权重,以最小化损失函数。

这些层可以分为:

  • 输入层负责将输入向量传递给神经网络。如果我们有一个 3 个特征的矩阵(形状 N×3),这一层将 3 个数字作为输入,并将相同的 3 个数字传递给下一层。
  • 隐层代表中间节点,它们对数字进行多次变换,以提高最终结果的准确性,输出由神经元的数量来定义。
  • 输出层,返回神经网络的最终输出。如果我们正在做一个简单的二进制分类或回归,输出层将只有 1 个神经元(因此它只返回 1 个数字)。在具有 5 个不同类别的多类别分类的情况下,输出层将具有 5 个神经元。

ANN 最简单的形式是 感知器 ,一个只有一层的模型,非常类似于线性回归模型。问感知器内部发生了什么,相当于问多层神经网络的单个节点内部发生了什么……我们来分解一下。

假设我们有一个包含 N 行、3 个特征和 1 个目标变量(即二进制 1/0)的数据集:

图片作者。我在 0 和 1 之间放了一些随机数(数据在被输入神经网络之前应该总是被缩放)。

就像在所有其他机器学习用例中一样,我们将训练一个模型,使用逐行的特征来预测目标。让我们从第一排开始:

作者图片

“训练一个模特”是什么意思?在数学公式中寻找最佳参数,使预测误差最小化。在回归模型(即线性回归)中,您必须找到最佳权重,在基于树的模型(即随机森林)中,这是关于找到最佳分割点…

作者图片

通常,权重是随机初始化的,然后随着学习的进行进行调整。在这里,我将把它们都设置为 1:

作者图片

到目前为止,我们还没有做任何不同于线性回归的事情(这对于企业来说很容易理解)。现在,这里是从线性模型σ(Xi * wi)= Y到非线性模型【σ(Xi * wi)*)= Y…进入激活功能。*

作者图片

激活函数定义了该节点的输出。有很多,甚至可以创建一些自定义函数,你可以在官方文档中找到详细信息,并看看这个备忘单。如果我们在示例中设置一个简单的线性函数,那么我们与线性回归模型没有区别。

来源:维基百科

我将使用一个只返回 1 或 0 的二进制步骤激活函数:

来源:维基百科

作者图片

我们有感知器的输出,感知器是一个单层神经网络,它接受一些输入并返回 1 个输出。现在,模型的训练将通过将输出与目标进行比较、计算误差和优化权重来继续,一次又一次地重复整个过程。

作者图片

这是一个神经元的常见表现:

作者图片

深度神经网络

可以说所有的深度学习模型都是神经网络,但并不是所有的神经网络都是深度学习模型。一般来说,“深度”学习适用于算法至少有 2 个隐藏层的情况(所以包括输入和输出总共有 4 层)。

想象同时复制神经元过程 3 次:由于每个节点(加权和&激活函数)返回一个值,我们将有第个隐藏层有 3 个输出。

作者图片

现在让我们再次使用这 3 个输出作为第二个隐藏层的输入,返回 3 个新数字。最后,我们将添加一个输出层(仅 1 个节点)来获得我们模型的最终预测。****

作者图片

请记住,这些层可以有不同数量的神经元和不同的激活函数,并且在每个节点中,训练权重以优化最终结果。这就是为什么添加的层数越多,可训练参数的数量就越大。

现在你可以回顾一下神经网络的全貌:

作者图片

请注意,为了尽可能保持简单,我没有提到业务可能不感兴趣的某些细节,但数据科学家肯定应该知道。特别是:

  • ****偏差:在每个神经元内部,输入和权重的线性组合也包括偏差,类似于线性方程中的常数,因此神经元的完整公式为

***【f】(***【Xi * Wi】+偏置 )

  • ****反向传播:在训练期间,模型通过将误差传播回节点并更新参数(权重和偏差)来学习,以最小化损失。

来源: 3Blue1Brown (Youtube)

  • ****梯度下降:用于训练神经网络的优化算法,该算法通过在最陡下降方向上采取重复步骤来找到损失函数的局部最小值。

来源: 3Blue1Brown (Youtube

模型设计

TensorFlow 构建神经网络最简单的方法是用 Keras 的 序列 类。让我们用它来制作我们之前例子中的感知器,这样一个只有一个密集层的模型。它是最基本的层,因为它向所有神经元提供所有输入,每个神经元提供一个输出。

*model = models.**Sequential**(name="**Perceptron**", layers=[ layers.**Dense**(             **#a fully connected layer**
          name="dense",
          input_dim=3,        **#with 3 features as the input**
          units=1,            **#and 1 node because we want 1 output**
          activation='linear' **#f(x)=x**
    )
])
model.summary()*

作者图片

summary 函数提供了结构和大小的快照(根据要训练的参数)。在这种情况下,我们只有 4 个(3 个权重和 1 个偏差),所以它非常精简。

如果你想使用一个还没有包含在 Keras 中的激活函数,比如我在可视化示例中展示的二进制步骤*函数,你必须使用 raw TensorFlow:*

***# define the function**
import **tensorflow** as tfdef **binary_step_activation**(x):
    **##return 1 if x>0 else 0** 
    return **K**.switch(x>0, **tf**.math.divide(x,x), **tf**.math.multiply(x,0)) **# build the model**
model = models.Sequential(name="Perceptron", layers=[
      layers.Dense(             
          name="dense",
          input_dim=3,        
          units=1,            
          activation=**binary_step_activation**
      )
])*

现在让我们尝试从感知器转移到深度神经网络。也许你会问自己一些问题:

  1. 多少层?正确答案是“尝试不同的变体,看看什么有效”。我通常使用两个带有 Dropout、的密集隐藏层,这是一种通过将输入随机设置为 0 来减少过度拟合的技术。隐藏层对于克服数据的非线性很有用,所以如果你不需要非线性,那么你可以避免隐藏层。隐藏层太多会导致过拟合。

作者图片

  1. 有多少神经元?隐神经元的数量应该在输入层的大小和输出层的大小之间。我的经验法则是(输入数+ 1 输出)/2* 。*
  2. 什么激活功能?有很多,我们不能说有一个是绝对更好的。反正用的最多的是 ReLU ,一个分段线性函数,只在输出为正的情况下返回输出,主要用于隐藏层。此外,输出层必须具有与预期输出兼容的激活。例如,线性函数适用于回归问题,而 Sigmoid 常用于分类。**

来源:维基百科

我将假设一个包含 N 个要素和 1 个二元目标变量的输入数据集(最有可能是一个分类用例)。

*n_features = 10model = models.**Sequential**(name="**DeepNN**", layers=[
    **### hidden layer 1**
    layers.**Dense**(name="h1", input_dim=n_features,
                 units=int(round((n_features+1)/2)), 
                 activation='relu'),
    layers.**Dropout**(name="drop1", rate=0.2),

    **### hidden layer 2**
    layers.**Dense**(name="h2", units=int(round((n_features+1)/4)), 
                 activation='relu'),
    layers.**Dropout**(name="drop2", rate=0.2),

    **### layer output**
    layers.**Dense**(name="output", units=1, activation='sigmoid')
])
model.summary()*

作者图片

请注意,顺序类并不是用 Keras 构建神经网络的唯一方法。 模型 类提供了更多的灵活性和对层的控制,它可以用来构建具有多个输入/输出的更复杂的模型。有两个主要区别:

  • 需要指定输入层,而在顺序类中,它隐含在第一个密集层的输入维度中。
  • 这些层像对象一样保存,并可应用于其他层的输出,如:输出=层(…)(输入)**

这就是你如何使用模型类来构建我们的感知器和 DeepNN:

***# Perceptron**
inputs = layers.**Input**(name="input", shape=(3,))
outputs = layers.**Dense**(name="output", units=1, 
                       activation='linear')(inputs)
model = models.**Model**(inputs=inputs, outputs=outputs, 
                     name="**Perceptron**") **# DeepNN**
**### layer input**
inputs = layers.**Input**(name="input", shape=(n_features,))**### hidden layer 1**
h1 = layers.**Dense**(name="h1", units=int(round((n_features+1)/2)), activation='relu')(inputs)
h1 = layers.**Dropout**(name="drop1", rate=0.2)(h1)**### hidden layer 2**
h2 = layers.**Dense**(name="h2", units=int(round((n_features+1)/4)), activation='relu')(h1)
h2 = layers.**Dropout**(name="drop2", rate=0.2)(h2)**### layer output**
outputs = layers.**Dense**(name="output", units=1, activation='sigmoid')(h2)model = models.**Model**(inputs=inputs, outputs=outputs, name="**DeepNN**")*

用户可以随时检查模型摘要中的参数数量是否与序列中的参数数量相同。

形象化

请记住,我们是在向企业讲述一个故事,而可视化是我们最好的盟友。我准备了一个函数来从它的 TensorFlow 模型绘制人工神经网络的结构,下面是完整的代码:

让我们在两个模型上试试,首先是感知机:

***visualize_nn**(model, description=True, figsize=(10,8))*

作者图片

然后是深层神经网络:

作者图片

TensorFlow 也提供了一个绘制模型结构的工具,你可能想把它用于更复杂的神经网络,包括更复杂的层(CNN,RNN,…)。有时候设置起来有点棘手,如果你有问题这篇文章可能会有帮助。

*utils.**plot_model**(model, to_file='model.png', show_shapes=True, show_layer_names=True)*

作者图片

这会将该图像保存在您的笔记本电脑上,因此,如果您只想在笔记本上绘制它,您可以运行以下命令来删除该文件:

*import **os**
os.remove('model.png')*

培训和测试

最后,是时候训练我们的深度学习模型了。为了让它运行,我们必须“编译”,或者换句话说,我们需要定义优化器、损失函数、和指标。我通常使用亚当优化器,一种梯度下降的替代优化算法(自适应优化器中最好的)。其他参数取决于用例。

在(二进制)分类问题中,你应该使用(二进制)交叉熵损失来比较每个预测的概率和实际的类输出。至于指标,我喜欢同时监控精确度F1 分数,这是一个结合了精确度召回的指标(后者必须实现,因为它还没有包含在 TensorFlow 中)。

***# define metrics**
def **Recall**(y_true, y_pred):
    true_positives = **K**.sum(**K**.round(**K**.clip(y_true * y_pred, 0, 1)))
    possible_positives = **K**.sum(**K**.round(**K**.clip(y_true, 0, 1)))
    recall = true_positives / (possible_positives + **K**.epsilon())
    return recall

def **Precision**(y_true, y_pred):
    true_positives = **K**.sum(**K**.round(**K**.clip(y_true * y_pred, 0, 1)))
    predicted_positives = **K**.sum(**K**.round(**K**.clip(y_pred, 0, 1)))
    precision = true_positives / (predicted_positives + **K**.epsilon())
    return precision

def **F1**(y_true, y_pred):
    precision = Precision(y_true, y_pred)
    recall = Recall(y_true, y_pred)
    return 2*((precision*recall)/(precision+recall+**K**.epsilon())) **# compile the neural network** model.compile(optimizer='**adam**', loss='**binary_crossentropy**', 
              metrics=[**'accuracy',F1**])*

另一方面,在回归问题中,我通常将 MAE 设为损失,将 R 平方设为度量。

***# define metrics**
def **R2**(y, y_hat):
    ss_res =  **K**.sum(K.square(y - y_hat)) 
    ss_tot = **K**.sum(K.square(y - **K**.mean(y))) 
    return ( 1 - ss_res/(ss_tot + **K**.epsilon()) ) **# compile the neural network** model.compile(optimizer='**adam**', loss='**mean_absolute_error**', 
              metrics=[**R2**])*

在开始训练之前,我们还需要决定时期批次:由于数据集可能太大而无法一次处理完,所以将其分成批次(批次大小越大,需要的内存空间就越大)。反向传播和随之而来的参数更新在每批中都发生。一个时期是整个训练集的一个阶段。因此,如果您有 100 个观察值,并且批大小为 20,则需要 5 个批来完成 1 个历元。批量大小应该是 2 的倍数(常见的是:32、64、128、256),因为计算机通常以 2 的幂来组织内存。我倾向于从 100 个 epochs 开始,批量大小为 32。

在培训期间,我们希望看到指标不断改进,损失不断减少。此外,最好保留一部分数据(20%-30%)用于验证。换句话说,在训练之外,模型将在每个时期结束时将这部分数据分离出来以评估损失和指标。

假设您已经将数据准备好放入一些 Xy 数组中(如果没有,您可以简单地生成随机数据,如

*import **numpy** as npX = np.random.rand(1000,10)
y = np.random.choice([1,0], size=1000)*

),您可以启动并可视化培训,如下所示:

***# train/validation**
training = model.fit(x=X, y=y, batch_size=32, epochs=100, shuffle=True, verbose=0, validation_split=0.3) **# plot** metrics = [k for k in training.history.keys() if ("loss" not in k) and ("val" not in k)]    
fig, ax = plt.subplots(nrows=1, ncols=2, sharey=True, figsize=(15,3))

**## training**    
ax[0].set(title="Training")    
ax11 = ax[0].twinx()    
ax[0].plot(training.history['loss'], color='black')    ax[0].set_xlabel('Epochs')    
ax[0].set_ylabel('Loss', color='black')    
for metric in metrics:        
    ax11.plot(training.history[metric], label=metric)    ax11.set_ylabel("Score", color='steelblue')    
ax11.legend()

**## validation**    
ax[1].set(title="Validation")    
ax22 = ax[1].twinx()    
ax[1].plot(training.history['val_loss'], color='black')    ax[1].set_xlabel('Epochs')    
ax[1].set_ylabel('Loss', color='black')    
for metric in metrics:          
    ax22.plot(training.history['val_'+metric], label=metric)    ax22.set_ylabel("Score", color="steelblue")    
plt.show()*

图片作者。分类举例,笔记本此处

图片作者。回归示例,笔记本此处

这些图取自两个实际的用例,它们将标准的机器学习算法与神经网络进行了比较(每个图像下的链接)。

可解释性

我们训练和测试了我们的模型,但是我们仍然没有让企业相信结果…我们能做什么?很简单,我们建立一个解释器来表明我们的深度学习模型不是一个黑盒。

我发现Shap与神经网络配合得非常好:对于每一个预测,它能够估计每个特征对模型预测值的贡献。基本上回答了问题“为什么模型说这是 1 而不是 0?”。**

您可以使用以下代码:

请注意,您也可以在其他机器学习模型上使用该函数(即线性回归、随机森林),而不仅仅是神经网络。从代码中可以看出,如果 X_train 参数保持为 None,我的函数假设它不是深度学习。

让我们在分类和回归示例中测试一下:

**i = 1explainer_shap(model, 
               X_names=list_feature_names, 
               X_instance=X[i], 
               X_train=X, 
               task="**classification**", **#task="regression"**
               top=10)**

图片作者。分类举例,笔记本此处。泰坦尼克号数据集,预测是“幸存”主要是因为哑变量 Sex_male = 0,所以乘客是女的。

图片作者。回归举例,笔记本此处。房价数据集,这个房价的主要驱动力是一个大的地下室。

结论

这篇文章是一个教程,展示了如何设计和建立人工神经网络,深度和非深度。我一步一步地分解了单个神经元内部发生的事情,以及更普遍的各层内部发生的事情。我让故事保持简单,就好像我们正在使用大量的可视化技术向企业解释深度学习一样。

在教程的第二部分,我们使用 TensorFlow 创建了一些神经网络,从感知器到更复杂的神经网络。然后,我们训练了深度学习模型,并评估了它对分类和回归用例的解释能力。

我希望你喜欢它!如有问题和反馈,或者只是分享您感兴趣的项目,请随时联系我。

👉我们来连线👈

本文是使用 Python 进行机器学习的系列文章的一部分,参见:****

** **

使用 R 和 Keras 的深度学习:在 10 分钟内建立一个手写数字分类器

原文:https://towardsdatascience.com/deep-learning-with-r-and-keras-build-a-handwritten-digit-classifier-in-10-minutes-817caeb1c8c6?source=collection_archive---------43-----------------------

用 R 和 Keras 在 10 分钟内建立一个手写数字分类器

莎拉·多维勒在 Unsplash 上拍摄的照片

在一个似乎每个人都知道如何用 Python 解决至少基本的深度学习任务的时代,一个问题出现了:R 如何融入整个深度学习图景

对于 R 迷来说,这里有一些好消息 Tensorflow 和 Keras 库都可供您使用,并且它们很容易配置。今天你将学习如何用 Keras 解决一个著名的 MNIST 问题。

导航到一个部分:

  • 用 R 安装 Tensorflow 和 Keras
  • 数据集加载和准备
  • 模特培训
  • 模型评估
  • 结论

用 R 安装 Tensorflow 和 Keras

要使用 Keras 构建图像分类器模型,您必须首先安装该库。但是在你安装 Keras 之前,你必须安装 Tensorflow。

该过程与安装其他库时略有不同。是的,您仍然会使用install.packages()函数,但是有一个额外的步骤。

以下是如何从 R 控制台安装 Tensorflow:

install.packages("tensorflow") 
library(tensorflow) 
install_tensorflow()

最有可能的是,系统会提示您安装 Miniconda,这是您应该做的事情——假设您还没有安装它。

Keras 的安装过程是相同的,只是要注意必须先安装 Tensorflow:

install.packages("keras") 
library(keras) 
install_keras()

如果你被要求重启 R 会话——不这样做可能会导致一些 DLL 问题,至少根据 R。

这就是安装库所需的全部内容。接下来让我们加载并准备数据集。

数据集加载和准备

幸运的是,MNIST 数据集内置于 Keras 库中。一旦库被导入,就可以通过调用dataset_mnist()函数来获得它。

此外,您应该将数据集分成四个类别:

  • X_train–包含训练集的数字
  • X_test–包含测试集的数字
  • y_train–包含训练集的标签
  • y_test–包含测试集的标签

您可以使用下面的代码片段来导入 Keras 并解包数据:

这是一个好的开始,但我们还没有完成。本文将只使用线性层(没有卷积),所以你必须将输入图像从 28×28 调整到 1×784。您可以使用 Keras 的array_reshape()功能来实现。此外,您还将图像矩阵的每个值除以 255,因此所有图像都在[0,1]范围内。

这将处理输入图像,但我们还必须转换标签。默认情况下,它们存储为整数,我们将使用to_categorical()函数将它们转换为类别。

以下是完整的代码片段:

这就是我们从模特训练开始所需要的。让我们接下来做那件事。

模特培训

MNIST 是一个庞大而简单的数据集,因此简单的模型架构应该会产生近乎完美的模型。

我们将有三个分别具有 256、128 和 64 个神经元的隐藏层,以及一个具有 10 个神经元的输出层,因为在 MNIST 数据集中有 10 个不同的类。

为了防止过度拟合,每个线性层后面都有一个剔除。

一旦您声明了模型,您就可以使用summary()函数来打印它的架构:

结果如下图所示:

图 1——我们的神经网络架构总结(图片由作者提供)

在我们开始训练之前,还有一个步骤——编译模型。这一步包括选择衡量损失的方式,选择减少损失的功能,以及选择衡量整体性能的指标。

让我们分别讨论分类交叉熵、Adam 和准确性:

你现在可以调用fit()函数来训练模型。以下代码片段为 50 个时期训练模型,一次提供 128 幅图像:

一旦执行了这行代码,您将看到以下输出:

图片 2-模型训练(步骤 1)(图片由作者提供)

大约一分钟后,50 个纪元就会过去。这是您应该看到的最终输出:

图 3-模型训练(步骤 2)(图片由作者提供)

同时,您将看到一个图表随着模型的训练而更新。它显示了训练和验证子集的损失和准确性。以下是培训过程完成后的样子:

图 4 —训练集和验证集的损失和准确性(图片由作者提供)

就这样——您已经准备好评估模型了。让我们接下来做那件事。

模型评估

您可以使用 Keras 的evaluate()函数来评估测试集的性能。下面是这样做的代码片段:

结果如下:

图 5 —对测试集的模型评估(图片由作者提供)

如您所见,该模型对以前看不到的数据产生了 98%以上的准确率。

要对新的数据子集进行预测,可以使用如下所示的predict_classes()函数:

结果如下:

图片 6 —测试集上的类预测(图片由作者提供)

这就是如何在 R 中使用 Keras!让我们在下一部分总结一下。

结论

大部分深度学习的在线资源都是用 R 写的——我给你那个。这并不意味着 R 在这个领域已经过时了。Tensorflow 和 Keras 都有官方的 R 支持,模型开发就像用 Python 一样简单。

感谢阅读。

喜欢这篇文章吗?成为 中等会员 继续无限制学习。如果你使用下面的链接,我会收到你的一部分会员费,不需要你额外付费。

https://medium.com/@radecicdario/membership

了解更多信息

保持联系

原载于 2021 年 2 月 25 日 https://appsilon.com**

深度终身学习——从人脑中汲取灵感

原文:https://towardsdatascience.com/deep-lifelong-learning-drawing-inspiration-from-the-human-brain-c4518a2f4fb9?source=collection_archive---------19-----------------------

思想和理论

复制人脑的学习机制以防止深度神经网络中的灾难性遗忘

图片作者。

生物不断获得和提高知识和技能,适应新的环境、情况和任务。这种能力可以说是我们作为一个物种仍然活着的原因。正如达尔文的进化论所说——更高的生存机会不属于最强者,而属于最适者。

与具有终生适应能力的动物不同,许多机器学习算法,包括神经网络,在其一生中都是固定的,因此限制了它们的使用案例。模型被训练一次,参数在推断期间被冻结。

然而,在现实世界中,模型将受益于有效处理信息流、学习多种任务和处理输入中的不确定性的能力。

努力扩展经过训练的神经网络的知识通常会导致灾难性的遗忘——从早期训练阶段获得的信息会丢失。在新数据中出现概念漂移的情况下,即训练数据的分布随着时间的推移发生显著变化的情况下,该问题尤其显著。

终身学习(连续/连续/增量)领域涉及开发技术和架构,使模型能够连续学习,而无需从头开始重新训练。

有趣的是,当我们学习新事物时,人类不会发生灾难性的遗忘——参加驾驶课程不会导致忘记如何骑自行车。由于动物大脑的聪明才智,许多成功的终身学习方法,利用大自然的灵感,复制动物大脑中发生的生物过程,这也许并不奇怪,但仍然令人着迷。

这篇文章是一个简短的总结,介绍了与终身学习相关的概念和问题。我将首先讨论用例,接着讨论影响人脑学习过程的生物学因素以及它们与终身学习方法的相似性。

可能的使用案例和动机

为了更好地理解终身学习解决的问题的范围和潜在的陷阱,让我们考虑几个终身学习可能派上用场的实际例子。

聊天机器人:设想为一家银行构建一个在线助理聊天机器人。这个机器人训练有素,能够就它已经接触过的话题进行交谈。然而,该银行决定通过新的信用卡额度来扩展其服务。当客户询问新服务时,聊天机器人会标记出以前没有见过的话题,并将客户转给接线员。然后操作员将与客户进行对话。

部署时具有学习能力的模型将从客户与运营商的新对话中学习新主题,而不需要在所有对话基础上从头开始重新培训,从而节省时间和金钱。

生产线:一家生产红色和蓝色糖果的糖果厂决定用一种新的绿色糖果来扩展其生产线。大多数时候,糖果是混合在一起的,但是需要分类包装。这个环节依赖于计算机视觉分类算法。分类算法现在需要扩展到对新颜色进行分类,而不需要从头开始重新训练。这种情况比聊天机器人更具挑战性,因为我们还需要用新的输出来扩展模型,从而改变网络的结构。

我们能不能在模型展开的时候做一次反向传递?

简而言之,是的,我们可以。但是我们也可能会弄乱网络的权重,丢失在主要训练阶段学到的知识。没有额外的机制,神经网络容易忘记以前获得的知识。但它到底是什么意思,为什么会发生?

神经网络的资源(权重)有限,如果一次又一次地暴露于特定的任务,则可以相当有效地调整到该任务。但由于这些资源是有限的,新知识要么挤压旧知识并使其更加丰富,要么将其挤出。

例如,考虑一个学习预测狗的年龄的网络(对动物收容所非常有用)。该网络将对特征进行编码,可能与狗的面部元素的相对位置和比例有关(我们只对哈士奇和德国牧羊犬进行了训练)。该损失将引导重量梯度朝向用于识别这两个品种年龄的任务的局部最小值的位置。如果我们用更多的品种(例如约克)来扩展这个网络,我们就有可能获得所有狗共有的学习特征。然而,如果我们现在将网络扩展到识别家养鹦鹉的年龄,这种损失将把梯度推向对鹦鹉年龄重要的特征。这些直觉上与狗所需的特征非常不同。如果网络不再接触哈士奇、约克夏和牧羊人的图像,我们就会陷入灾难性的遗忘——失去所有关于狗的年龄的知识。

总之,从非平稳数据分布中不断获取增量可用信息会导致神经网络中灾难性的遗忘或干扰。新信息会覆盖共享表示中以前的知识。在离线学习中,这种损失随着洗牌和重复洗牌而恢复。

学习背后的生物学概念

顾名思义“神经网络”,这些模型中的一些机制已经受到了动物大脑的启发。也许我们的大脑也包含了在深度模型中防止灾难性遗忘的关键线索?

我们的大脑不断学习和记忆。通过进化过程,这些功能已经被完善以适应我们的日常生活,而不会在学习一个新单词或一项技能后突然崩溃。我们大脑中与神经网络学习方式相关的两个主要机制是稳定性-可塑性困境和互补学习系统理论。这两者都可以给我们一些提示,告诉我们如何防止灾难性遗忘,并为终身学习开发有效的算法。

稳定-塑性两难

稳定性是指大脑保留新知识的能力,可塑性是指获取新知识的能力。

在早期发育的关键时期,大脑尤其具有可塑性。你可能已经注意到,孩子们学得很快,但他们忘得也一样快。在早期保留知识是困难的——当系统在寻找最重要的信号时不断变化。这就是为什么重复新材料对孩子的学习至关重要。有多少次你听到孩子们被问到:“猫说什么?”。

随着生物系统的稳定,可塑性变得不那么突出,我们变得更加依赖学到的知识,并根据经验进行操作。然而,大脑保留了一定程度的可塑性,以适应更小规模的重组。

互补学习系统(CLS)理论

该理论概括了记忆形成的神经机制。它基于区分海马体和新皮层在学习和记忆形成过程中的互补作用。

在记忆结构中,海马系统负责新信息的短期适应和快速学习。另一方面,虽然新皮质系统是为长期存储量身定制的,很难重写,但它的学习速度很慢,旨在学习普遍性。

海马系统快速编码情节样事件,然后随着时间的推移重复回放到新皮质系统进行长期保留。据信,在快速动眼期(REM)睡眠期间,近期记忆被整合为长期记忆。

神经网络中的终身学习

为处理灾难性遗忘而开发的机制确实从自然界获得了灵感——互补学习理论和稳定性-可塑性困境。并不是下面描述的所有方法都有效,但是,尝试它们对于找到正确的前进方向也很重要。

我在下面的总结部分提供了文献的链接。

重放方法

重放方法是基于重复地将模型暴露给新数据和已经训练过的数据——当可以访问这些数据时。新数据与批量中已经看到的示例交错,并被提供给模型的训练步骤。在最简单的情况下,在每个新批次中,旧数据都是随机抽样的。

尽管简单,这种方法有几个注意事项:

  • 有效选择范例进行排练的最佳策略是什么?一些已经看到的例子比其他例子更有信息量。这里,最常见的策略是寻找更多信息样本,或者那些代表该方法最初学习的特征的平均值的样本。
  • 只看到训练数据的一小部分也提出了一个问题,即如何确保模型不会过拟合?这里提出的方法依赖于正则化。
  • 找到批次中新旧样本的比率也不是一件小事。

总的来说,这种重放方法提供了边际性能增益,代价是更长的训练时间和更大的内存需求。

基于正则化的方法

与预演方法不同,正则化方法缓解了较高内存需求的问题。这些都集中在开发一个损失项,将巩固所有以前学到的知识。

基于先验的模型估计模型参数的参数分布,并且当暴露于新数据时,不要让模型偏离它太多。

资源再分配

我们可以有效地使用可用的网络资源来防止关键区域被覆盖,或者扩展网络以允许更多的计算/存储空间,而不是将模型暴露给已经看到的数据,或者巩固损失项中的知识。

没有额外的资源:如果我们不能通过添加新的权重来扩展网络,即资源是固定的,则模型可以使用不同概念的非重叠表示。这种类型的方法也称为参数隔离方法。

对于给定的任务/类,重要的参数被隔离和冻结。类似于稳定性-可塑性困境,弹性权重整合减缓了对先前学习的任务至关重要的模型部分的学习,而增量矩匹配(IMM) 匹配在单个架构中对单独任务进行训练的两个网络的参数分布的矩,以捕捉两者学习的知识,防止灾难性的遗忘。

利用额外资源:如果我们有能力扩展网络,我们也可以为新知识分配额外的神经资源。在这种配置中,可以直接在新的示例上进行训练,而不需要与原始数据集交错,但是这种方法显然需要更大的内存需求——在最简单的情况下,我们将为新知识的每个部分添加一个新的神经网络。

摘要

如果我们要在人工智能方面取得另一次飞跃,探索终身学习算法具有巨大的重要性。特别是随着未来主义 AutoMLAutoAI 的进步。这就是为什么我们看到越来越多的出版物,尤其是像 DeepMind 这样的顶级研究机构的出版物。

终身学习仍然是一个相当新的话题。尽管几份调查报告对迄今取得的成就进行了全面概述:

不断变化的需求会让它们很快过时。缺乏标准化的协议和数据集也使得评估不同的策略具有挑战性。然而,正如我们从其他领域了解到的那样,这个领域很快就会成熟。

如果你喜欢这篇文章,请与朋友分享!要阅读更多关于机器学习和图像处理的主题,请点击订阅!

我错过了什么吗?不要犹豫,直接给我留言、评论或发消息吧!

LinkedIn 搜索系统的深度自然语言处理

原文:https://towardsdatascience.com/deep-natural-language-processing-for-linkedin-search-systems-6d136978bcfe?source=collection_archive---------21-----------------------

NLP 研究论文摘要

图片来自来源

在这篇博客中,我尝试根据我的理解总结了 LinkedIn 搜索系统 的论文 。请随时评论你的想法!

本文介绍了将深度自然语言处理技术应用于五个代表性任务的综合研究,以构建高效且健壮的搜索引擎。除此之外,本文还试图围绕延迟健壮性、有效性,找到有助于在生产环境中构建和扩展此类系统的三个重要问题的答案。

所以事不宜迟,让我们深入研究一下搜索引擎组件。

搜索引擎组件

搜索系统的组成部分|图片来自来源

如上所示,作者讨论的组件是查询意图分类、查询标记系统、搜索排名、查询建议和自动完成系统。让我们稍微了解一下每一个细节——

查询意图 由于在 LinkedIn,人们可以搜索许多垂直领域(人员、工作、帮助中心、群组等),同样在联合搜索的情况下,尝试从所有垂直搜索中检索文档并将它们混合到同一个搜索结果页面中,确定意图变得非常关键。考虑到任务的类型(即文本分类),作者用 CNN和 LSTM 模型进行了游戏实验。经过评估,他们发现这两个系统表现同样出色,尽管他们选择了 CNN 系统,因为它与 LSTMs 相比延迟稍低。

模型|准确性|延迟—查询意图性能

查询标记— 识别实体,然后将它们用作特征可以帮助提高其他组件的性能。例如,作者发现这个特性在文档检索步骤中非常有用。因为被识别的实体将帮助系统缩小其范围并指向与特定实体类型相匹配的文档。现有的生产模型使用三类特征:基于字符、基于单词和基于词典。关于模型开发,他们试验了通用报告格式、SCRF (当前系统)、LSTM-SCRF 模型及其变体。最终,他们发现 SCRF 是所有实验中表现最好的。

查询建议— 查询建议也是整体搜索体验中必不可少的一部分。这就是你在 LinkedIn 的“人们也搜索”协助背后的体验。现有的系统是基于搜索查询的频率及其重构。它从搜索日志中收集查询重构对,并且对于每个输入查询,它基于查询、重构的查询对对建议进行排序。作者遵循某些启发法来识别这些重构,例如查询对必须在同一个会话中,其中会话由间隔不超过 10 分钟的查询来定义,并且两个查询必须共享至少一个公共词

他们还尝试将整个问题公式化为一个序列来排序任务,将原始搜索查询作为输入,将重构后的查询作为输出。尽管他们发现该系统比已经部署的系统性能更好。由于这个系统与前一个系统相比有更高的延迟,他们在搜索结果排名的同时为他们的模型服务。

自动完成— 由于查询自动完成类似于语言生成任务,使用语言模型可以帮助我们实现令人印象深刻的结果,但代价是更高的延迟。作者修改了原始的语言模型概率步骤,让它为每个单词吐出未标准化的权重,从而节省了大量的计算时间。这是由于观察到大部分时间花在整个词汇的概率标准化上。它们近似这种行为,如下所示—

标准化近似

文档排名— 这里的目标是检索与查询相关的相关文档。作者对人员搜索和帮助中心搜索进行了实验。人民搜索拥有 6 亿会员档案,帮助中心有 2700 个常见问题文档。

因为等待时间是文档排序任务中的主要问题之一。对于帮助中心搜索,由于只有 2,700 个文档,他们预先计算并使用文档嵌入。对于拥有 6 亿成员档案的人民搜索,他们提出了一个两遍排名策略:首先应用一个轻量级模型来选择前数百个文档,然后使用这个精简集通过更深层次的模型来重新排名文档。

下图显示了排序步骤,我们使用 CNN 对查询和其他文档字段进行编码,然后添加手工制作的特征,再添加一个隐藏层来预测文档的相关性分数。

搜索排名模型|图片来自来源

下图显示了由上述组件构成的搜索引擎的总体系统设计。

搜索系统设计|图片来自来源

原始搜索查询首先进入 NLU(自然语言理解)引擎以处理和识别意图、实体和其他细节。我们还有一个语言生成引擎,用于自动完成、建议相关查询等。最后,我们转到检索和排序系统,该系统首先检索与搜索查询相关的一堆文档,然后为了提高 CTR(点击率)而对它们进行排序。

深度 NLP 什么时候有帮助?

  1. 自然语言生成/释义任务 作者发现深度 NLP 特别有帮助(至少在准确性方面),尤其是对于语言生成或文本匹配的任务。这是他们在查询建议和文档排序步骤下发现的。

如何应对延迟挑战?

  1. 重新设计算法 正如在自动完成步骤中所讨论的,他们应用了非规范化语言模型,这有助于他们在保持相同相关性水平的同时显著减少计算时间。
  2. 并行计算 这是他们尝试的查询建议,在这里他们尝试并行运行他们的 seq 模型。
  3. 预先计算的嵌入 对于从开始搜索的有限集合的任务,预先计算并存储嵌入总是比每次运行时都这样做更好。这就是他们在帮助中心搜索中所做的。

如何保证模型的鲁棒性?

对于这一步,作者要做的事情之一是处理训练数据,并通过删除模型中不需要的噪声模式来净化数据,以防止其记忆。示例参见查询建议部分。

其次,他们强调在训练深度网络时,使用手工制作的功能以及其他深度功能。这增加了系统行为的控制和确定性。

如果你愿意,你也可以查看我写的其他研究论文摘要。

好了,这篇博客到此为止。这是一个非常有趣的阅读,了解如何设计搜索系统,而不是在书中,而是可以大规模部署。

请随意阅读整篇论文,并对作者说“ Hi ”,感谢他们的贡献。此外,如果你喜欢看视频而不是文字内容(就像我一样的:D),一定要看看

更多这样的视频

⏩论文标题:LinkedIn 搜索系统的深度自然语言处理⏩论文:https://arxiv.org/abs/2108.08252⏩作者:、、王思达、迈克尔·卡齐、、傅、高慧姬、、陈伯龙⏩组织:LinkedIn

感谢您的宝贵时间!

我希望你喜欢读这篇文章。如果你愿意支持我成为一名作家,可以考虑注册成为中的一员。每月只需 5 美元,你就可以无限制地使用 Medium

深度神经网络在初始化时偏向简单函数

原文:https://towardsdatascience.com/deep-neural-networks-are-biased-at-initialisation-towards-simple-functions-a63487edcb99?source=collection_archive---------30-----------------------

为什么这是理解它们为什么起作用的非常重要的一步?

这是神经网络基本上是贝叶斯的后续文章,它基于【2,3】中的思想,提出了来自【1】的一般化候选理论。阅读顺序并不太重要——这篇文章主要总结了[2.3]中的材料,这些材料研究了为什么神经网络在初始化时偏向简单函数(具有低 Kolmogorov 复杂度)。这项工作激发了[1]中的结果,它解释了初始化时的这种偏差如何转化为现实世界中的良好概括,以及为什么神经网络享受它们所取得的成功!因此,这篇文章最好被认为是一个前传。

我们首先提出以下问题:

神经网络在被训练之前表达什么功能?

更具体地说,一个神经网络在被随机初始化后表达一个函数 f 的概率是多少?我们将这个量称为 P(f) ,并且将随机初始化为同分布高斯(尽管[2]表明 P(f) 对初始化的类型不太敏感)。

一般来说,少量更改神经网络中的一个参数会影响网络的原始输出,因此一般来说,神经网络中的参数与其表达的函数之间存在 1–1 的对应关系。然而,对于许多问题,我们对网络的原始输出并不感兴趣。这最好用一个例题来解释。

注意 P(f) 表示为神经网络中的 Pᵦ ( f ) 基本上是贝叶斯。
如果我们取定义域为定义网络的整个向量空间。

MNIST 的分类问题

考虑正确分类手写数字 0-9(MNIST 数据集)的图像的问题。我们显然对网络的原始输出不感兴趣——我们只关心它的最终(离散)决策。为了简单起见,让我们假设我们只想将图像分类为偶数或奇数。这可以通过具有单个输出神经元的神经网络来实现,阈值为零——正输出意味着偶数,负输出意味着奇数。

因此,如果我们考虑在 MNIST 的 m 个图像的子集,我们称之为 T18,T19,T20,那么网络 T21 模拟一个函数

f : S → {0,1}ᵐ,

其中 1 对应偶数,0 对应奇数。这是因为最终我们(主要)关心的是网络的阈值后输出,而不是原始输出,在这种情况下, N 中参数的微小变化可能不会改变所表达的函数(即分类不会改变)。符号{0,1}ᵐ表示 m 个图像被映射为 0 或 1。

我们可以问,这些函数的 P(f)是什么?

参见下面的图 1 和图 2 以获得上述系统的 P(f) 的两种可视化。 P(f) 使用来自 MNIST 的 100 幅图像,通过从 10⁷对 2 隐层全连接网络的不同随机初始化进行采样来计算。

图 1: 直观显示每个函数的不同 P(f)值的一种方法是绘制 P(f)与函数误差的关系图(即有多少图像分类错误)。我们考虑大小为 100 的数据集 S 。具有最高 P(f)的两个函数对应于所有图像被分类为相同值(0 或 1)的函数,并且关于 50 误差标记的对称性是因为网络找到函数 f 的可能性与找到 f 的逆的可能性相等

图 2: 可视化每个函数的不同 P(f)值的另一种方式。函数按概率排序(所以最频繁的函数的秩为 1,依此类推)。我们考虑大小为 m=10、50 和 100 的数据集。红线是假设 P(f) ∝ 1/Rank(f)的理论拟合。显然,P(f)的范围很大。观察到的幂律行为将是未来帖子的主题。

图 1 和图 2 中可以清楚的看到 P(f) 中有一个巨大的范围。[2]中的结果表明,上述问题的范围超过 30 个数量级。但是这有什么关系呢?

这很重要,因为对于一组 100 个图像,有 2 个⁰⁰ ≈ 10 个⁰不同的可能函数(即,将每个图像分类为偶数或奇数的可能方式)。在没有关于 N 的信息的情况下,我们可能会假设每个函数都是同样可能的,这意味着 P(f) ≈ 10⁻ ⁰(这将是图像通过无偏抛硬币进行分类的情况)。

考虑到 P(f) 可以大到 0.05,神经网络在初始化时显然不是无偏的。相反,在进行任何训练之前,在初始化时存在对某些类型功能的强烈偏好

有理由期待这一点吗?

有一个定理最初是由莱文提出的,并重新用于输入-输出映射[4],当在神经网络[3]的上下文中使用时,该定理陈述如下:对于从神经网络的参数 N 到由 N 表示的函数的映射,以下结果成立:

P(f) ≤ 2⁻ᴷ⁽ ᶠ ⁾⁺ᴼ⁽ ⁾,

其中 K(f) 是函数 f 的 Kolmogorov 复杂度,O(1)项独立于 f 但依赖于 N对于神经网络的界限成立,还需要满足一些进一步的条件,但是经验证据[3]加上一些理论结果[2]表明它确实成立,并且不是空的。

本质上,这意味着复杂函数将具有低的 P(f),而简单函数可以具有大的 P(f), 如果界限是紧的。然而,Kolmogorov 复杂性是不可计算的——因此,为一般架构和数据集证明这一点,充其量也不是微不足道的。相反,[3]中的一个非常聪明的实验允许我们根据经验测试这个上限。该实验的结果如图 3 所示,其中一个完全连接的网络模拟了以下形式的函数:

外宾:{0,1}ⁿ→{0,1},

因为存在合适的复杂性度量而选择——详情见[3]。

图 3: P(f)对 K(f)的近似(详见【3】)。与莱文启发的 P(f)上界相比,它的复杂度也是指数级的!

显然, P(f) 对于简单的 f 来说是指数大的。存在位于界限之下的函数,但是在[7]中论证了(非常非正式地)可以位于距界限一定距离之外的函数的数量是有限制的。

我们称之为简单偏差——因为简单函数的 P(f)更高。

来自[1,2,3]的的大量进一步证据表明,这种简单性偏差是不同架构和数据集的神经网络的普遍属性。例如,在 MNIST 和 Cifar10 [1,3]上执行了类似的实验,其中 CSR 复杂性度量用于近似 K(f) 。在[2]中,还有一个分析结果,即作用于布尔超立方体的感知器偏向于低熵(因此简单)函数。

总而言之:

  1. P(f) 是网络随机初始化为某个函数 f 的概率。
  2. 理论和实验结果强烈表明,简单函数的 P(f) 比复杂函数的大

还要注意,具有大的 P(f) 的函数在参数空间中具有更大的“体积”(详见[1,2])。这在直觉上是显而易见的——如果您更有可能对某个函数进行随机采样,那么它必定有更多的相关参数,因此参数空间也就更大。

请记住,函数是相对于数据集定义的,因为它指定了其定义域和共定义域。

但是这对学习来说是好事吗?

人们认为[5]真实世界的数据有一个潜在的简单描述。例如,当我们阅读手写数字时,我们不太担心精确的细节——如果它是一个单一的椭圆形,它可能是零。我们不需要考虑每个像素的精确像素值。

如果我们感兴趣学习的真实世界数据确实有一个简单的底层描述,那么简单函数将比复杂函数概括得更好。

考虑一个监督学习问题——来自 MNIST 的训练集 S ,包含 m 个例子。然后,理想的学习代理将能够从数字的图像(即,从像素值)到数字的分类计算所有 functions⁴的 Kolmogorov 复杂度。然后,它会丢弃所有没有正确预测所有 S. 中所有 m 个示例的函数。最后,在这些函数中,它会选择具有最低 Kolmogorov 复杂度的函数。

换句话说,一个理想的学习代理会选择适合训练数据的最简单的函数。

相对于某些 UTM 的⁴Defined(详见[3])。

那么神经网络是这样工作的吗?

在这一点上,如果你已经读过神经网络基本上是贝叶斯,你可以停止阅读,因为你已经知道答案了!如果您还没有,那么请检查一下,因为它:

  1. 解释我们如何在原则上使用神经网络中的随机抽样来学习,以贝叶斯方式(以及这意味着什么),这样在训练后,它以与 P(f) 成比例的概率表达函数 f
  2. 在[1]中总结了大量的经验证据,证明了像 SGD 这样的随机优化者的行为方式与上一点中讨论的假设学习代理非常相似。

因此,神经网络概括得很好,因为对于概括得更好的简单函数来说, P(f) 大得多。

结论

这是对[2,3]中主要结果的一个非常简短的总结。还有进一步的实验证明 P(f) 对初始化的选择不敏感,以及如何在真实世界数据集(例如 cifar10 和 MNIST)中发现观察到的简单偏差,使用称为 CSR 的复杂性度量。

最后一点是关于归纳偏差的强度——显然我们只有一个上限——它不能保证概率真的随复杂性呈指数变化。如果偏差太弱,那么我们就不可能以很高的概率得到很好的概括。

PAC-Bayes 界限提供了一般化的概率界限。这个界限在[1,6]中的应用表明,对于真实世界数据集上的尖端架构, P(f) 中的简单性偏差足以保证良好的泛化。这将是以后文章的主题!

最后,如果你认为我错过了什么或者说了什么不准确的话,请告诉我。也请注意,这是我对许多合作者所做工作的解释,虽然我相信它准确地接近了他们的观点,但它可能并不总是完美的代表!

参考

[1] C .明加德、g .瓦莱-佩雷斯、j .斯卡尔塞、a .路易斯。SGD 是贝叶斯采样器吗?嗯,差不多了。(2020)https://arxiv.org/abs/2006.15191

[2] C .明加德、j .斯卡尔塞、g .瓦莱-佩雷斯、d .马丁内斯-卢比奥、v .米库利克、a .路易斯。神经网络先验地偏向于低熵函数。(2019)https://arxiv.org/abs/1909.11522

[3] G .瓦莱-佩雷斯,c .卡马戈,a .路易斯。深度学习泛化是因为参数-函数图偏向简单函数。(2018)https://arxiv.org/abs/1805.08522

[4]卡马鲁丁·丁格尔、奇科·卡马戈和阿尔达·路易投入产出图强烈偏向简单产出(2018)。自然通讯,9(1):761。

[5]于尔根·施密德胡伯。发现具有低 kolmogorov 复杂性和高概括能力的问题解决方案(1994)。第十二届国际会议文集。

[6]阿尔德·路易斯·吉列尔莫·瓦莱-佩雷斯。深度学习的泛化边界(2020)。https://arxiv.org/abs/2012.04115

[7] Dingle,k .,Pérez,G.V .和 Louis,A.A.《基于投入和产出复杂性的产出概率的一般预测》。 Sci Rep 10, 4415 (2020)。【https://doi.org/10.1038/s41598-020-61135-7

深度神经网络:如何定义?

原文:https://towardsdatascience.com/deep-neural-networks-how-to-define-73d87bf36421?source=collection_archive---------31-----------------------

正确定义什么使神经网络变得更深很重要。这篇文章提出了深度神经网络的另一种定义。

Jonathan Borba 在 Unsplash 上拍摄的照片。

现在人工智能(AI)的成功,基本上是得益于深度学习(DL)及其相关模型。DL 是机器学习(ML)的一个子领域,其中一组算法试图利用几个处理层对高级数据抽象进行建模,其中每种类型的层都有特定的用途。

然而,深度神经网络(DNNs),如深度卷积神经网络(CNN),是基于多层感知器(MLP),这是一类已经使用了相当长时间的前馈人工神经网络,甚至在 1989 年第一个 CNN 出现之前。因此,问题来了:什么时候一个模型/网络被认为是“深”而不是“浅”?

浅层 x 深层神经网络

传统上,浅层神经网络(SNN)是具有一个或两个隐藏层的网络。因此,深度神经网络(DNN)是具有两个以上隐藏层的网络。这是最被接受的定义。下面,我们展示了一个 SNN 和 DNN 的例子(隐藏层是红色的)。

图片作者。

但是,只考虑隐藏层的数量是一个好方法吗?正确定义什么使一个模型变得深刻,对于明确理解这个概念是很重要的,特别是从行业采用 DL 的角度来看。在这篇文章中,我们提出了 DNNs 的另一种定义。我们建议,被视为“深度”的模型不仅应考虑隐藏层的数量,还应考虑:

a.)考虑训练和/或评估它所需的时间;

b.)考虑到计算平台(例如 GPU)方面的需求。

经典基准数据集(如 CIFAR-10、ImageNet)和标准环境/平台(Google Colab、kaggle)可用于获得这些度量。为了支持对另一个定义的需求,我们将使用两个传统数据库:修改后的国家标准与技术研究所( MNIST )和 CIFAR-10

MNIST 数据库

关于 MNIST 数据库,我们考虑了三个神经网络:Aviv Shamsian 的 SNN500、T2 的 CNN3L、T4 的 Nutan、T5 和 Bolla Karthikeya 的 LeNet-5。SNN500 是一个包含 500 个神经元的单隐层 SNN。CNN3L 也被认为是 SNN,因为它有两个隐藏(卷积)层和输出层。第三个网络是经典的 LeNet-5,有五层,其中四层是隐藏层。让我们看看代码(访问这里)。

图片作者。

**import** **torch**
**import** **torch.nn** **as** **nn**
**import** **torchvision.datasets** **as** **dsets**
**import** **torchvision.transforms** **as** **transforms**
**from** **torch.autograd** **import** Variable
**from** **prettytable** **import** PrettyTable
**import** **matplotlib.pyplot** **as** **plt**
**import** **time***# This function obtains the number of trainable parameters of the* 
*# model/network.*
**def** count_parameters(model):
    table = PrettyTable(["Modules", "Parameters"])
    total_params = 0
    **for** name, parameter **in** model.named_parameters():
        **if** **not** parameter.requires_grad: **continue**
        param = parameter.numel()
        table.add_row([name, param])
        total_params+=param
    print(table)
    print(f"Total trainable params: **{**total_params**}**")
    **return** total_params*# Just visualising some images*
**def** visualise_images(img, lab, t):
   fig = plt.figure()
   **for** i **in** range(6):
     plt.subplot(2,3,i+1)
     plt.tight_layout()
     plt.imshow(img[i][0], cmap='gray', interpolation='none')
     plt.title("**{}** - class: **{}**".format(t,lab[i]))
     plt.xticks([])
     plt.yticks([])

现在,我们定义类的数量和一些超参数。请注意,批量大小为 100。

num_classes = 10 *# Number of output classes, discrete range [0,9]*

*# Hyper-parameters*
num_epochs = 20 *# Number of epochs*
batch_size = 100 *# The size of input data took for one iteration*
lr = 1e-3 *# Learning rate*

我们下载并处理 MNIST 数据集。

*# Downloading MNIST dataset*
train_data = dsets.MNIST(root = './data', train = **True**,
                        transform = transforms.ToTensor(), download = **True**)

test_data = dsets.MNIST(root = './data', train = **False**,
                       transform = transforms.ToTensor())

print('#'*20)
print('Training dataset: ', train_data)
print('Test dataset: ', test_data)*# Wrap an iterable around the dataset to enable easy access to the samples.*
train_gen = torch.utils.data.DataLoader(dataset = train_data,
                                        batch_size = batch_size,
                                        shuffle = **True**)

test_gen = torch.utils.data.DataLoader(dataset = test_data,
                                       batch_size = batch_size, 
                                       shuffle = **False**)

device = torch.device("cuda:0" **if** torch.cuda.is_available() **else** "cpu")
print('Device is: ', device)

只是快速浏览一下训练数据集。

batch_train = enumerate(train_gen)
batch_idx, (batch_train_data, batch_train_classes) = next(batch_train)
print('One batch - training dataset:', batch_train_data.shape)

print('**\n**Each image of the batch:')
**for** i **in** range(batch_train_classes.shape[0]):
  print('Image: **{}** - Input shape: **{}** - Class: **{}**'.format(i, batch_train_data[i].shape, batch_train_classes[i]))
  **if** i == (batch_train_classes.shape[0]-1):
    print('The "image" itself: ', batch_train_data[i])

visualise_images(batch_train_data, batch_train_classes, 'Training')

注意一批的形状是:[100,1,28,28]。这意味着一批 100 个图像,一个通道(MNIST 的图像是灰度的),每个图像的尺寸为 28 x 28 像素。现在,我们定义三个神经网络。基于测试数据集的准确性来测量它们的性能。

**class** **SNN500**(nn.Module):
  **def** __init__(self, input_sz, hidden_sz, num_clas):
    super(SNN500,self).__init__()
    self.fc1 = nn.Linear(input_sz, hidden_sz)
    self.relu = nn.ReLU()
    self.fc2 = nn.Linear(hidden_sz, num_clas)

  **def** forward(self,x):
    out = self.fc1(x)
    out = self.relu(out)
    out = self.fc2(out)
    **return** out**class** **CNN3L**(nn.Module):
    **def** __init__(self, num_clas):
        super(CNN3L, self).__init__()
        self.conv1 = nn.Sequential(         
            nn.Conv2d(
                in_channels=1,              
                out_channels=16,            
                kernel_size=5,              
                stride=1,                   
                padding=2,                  
            ),                              
            nn.ReLU(),                      
            nn.MaxPool2d(kernel_size=2),    
        )
        self.conv2 = nn.Sequential(         
            nn.Conv2d(16, 32, 5, 1, 2),     
            nn.ReLU(),                      
            nn.MaxPool2d(kernel_size=2),                
        )
        *# Fully-connected layer*
        self.out = nn.Linear(32 * 7 * 7, num_clas)
    **def** forward(self, x):
        x = self.conv1(x)
        x = self.conv2(x)
        *# Flatten the output of conv2 to (batch_size, 32 * 7 * 7)*
        x = x.view(x.size(0), -1)       
        output = self.out(x)
        **return** output**class** **LeNet5**(nn.Module):          
    **def** __init__(self, num_clas):     
        super(LeNet5, self).__init__()
        *# Convolution* 
        self.conv1 = nn.Conv2d(in_channels=1, out_channels=6, kernel_size=5, stride=1, padding=2, bias=**True**)
        *# Max-pooling*
        self.max_pool_1 = nn.MaxPool2d(kernel_size=2)
        *# Convolution*
        self.conv2 = nn.Conv2d(in_channels=6, out_channels=16, kernel_size=5, stride=1, padding=0, bias=**True**)
        *# Max-pooling*
        self.max_pool_2 = nn.MaxPool2d(kernel_size=2) 
        *# Fully-connected layers*
        self.fc1 = nn.Linear(16*5*5, 120)   *# convert matrix with 16*5*5 (= 400) features to a matrix of 120 features (columns)*
        self.fc2 = nn.Linear(120, 84)       *# convert matrix with 120 features to a matrix of 84 features (columns)*
        self.fc3 = nn.Linear(84, num_clas)        *# convert matrix with 84 features to a matrix of 10 features (columns)*

    **def** forward(self, x):
        *# Convolve, then perform ReLU non-linearity*
        x = nn.functional.relu(self.conv1(x))  
        *# Max-pooling with 2x2 grid* 
        x = self.max_pool_1(x) 
        *# Convolve, then perform ReLU non-linearity*
        x = nn.functional.relu(self.conv2(x))
        *# Max-pooling with 2x2 grid*
        x = self.max_pool_2(x)
        *# First flatten 'max_pool_2_out' to contain 16*5*5 columns*
        x = x.view(-1, 16*5*5)
        *# FC-1, then perform ReLU non-linearity*
        x = nn.functional.relu(self.fc1(x))
        *# FC-2, then perform ReLU non-linearity*
        x = nn.functional.relu(self.fc2(x))
        *# FC-3*
        x = self.fc3(x)
        **return** x

现在,我们可以选择其中一个模型/网络进行训练和评估。我们还定义了损失函数、优化器,并显示了所选模型的可训练参数的数量。

loss_function = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(net.parameters(), lr=lr)

print('Checking trainable parameters: **{}**'.format(count_parameters(net)))

现在,我们可以训练模型了。

train_losses = []
train_acc = []
train_time_init = time.time()
**for** epoch **in** range(num_epochs):
  net.train() 
  running_loss = 0.0
  running_corrects = 0
  **for** images,labels **in** train_gen: *# Iterate over data: begin*
    **if** opt == '1':
      images = Variable(images.view(-1,28*28)).to(device) *# Send to GPU*
    **elif** (opt == '2') **or** (opt == '3'):
      images = Variable(images).to(device) *# Send to GPU*

    labels = Variable(labels).to(device) *# Send to GPU*
    optimizer.zero_grad()
    **with** torch.set_grad_enabled(**True**):
        outputs = net(images)
        _, preds = torch.max(outputs, 1)
        loss = loss_function(outputs, labels)
        loss.backward()
        optimizer.step()

    running_loss += loss.item() * images.size(0)
    running_corrects += torch.sum(preds == labels.data)
  *# Iterate over data: end*

  epoch_loss = running_loss / len(train_data)
  epoch_acc = running_corrects.double() / len(train_data)  
  print('Epoch [**%d**/**%d**], Loss: **%.4f**, Accuracy: **%.4f**'
                 %(epoch+1, num_epochs, epoch_loss, epoch_acc))

  train_losses.append(epoch_loss)
  train_acc.append(epoch_acc) 

train_time_end = time.time() - train_time_init

在推理阶段,我们测量所选模型的性能。

am_training = net.training
print('Am I training? ', am_training)
net.eval()
am_training = net.training
print('Am I training? ', am_training)
inference_loss = 0.0
inference_corrects = 0

infer_time_init = time.time()
**with** torch.no_grad():
  **for** images,labels **in** test_gen: *# Iterate over data: begin*
      **if** opt == '1':
        images = Variable(images.view(-1,28*28)).to(device) *# Send to GPU*
      **elif** opt == '2' **or** opt == '3':
        images = Variable(images).to(device) *# Send to GPU*

      labels = labels.to(device) *# Send to GPU*
      outputs_infer = net(images)
      _, preds_infer = torch.max(outputs_infer,1)
      loss_infer = loss_function(outputs_infer, labels)

      inference_loss += loss_infer.item() * images.size(0)
      inference_corrects += torch.sum(preds_infer == labels.data)
  *# Iterate over data: end*

final_inference_loss = inference_loss / len(test_data)
final_inference_acc = inference_corrects.double() / len(test_data)

infer_time_end = time.time() - infer_time_init
print('**\n**Training and inference in **{:.0f}**m **{:.0f}**s  OR  **{:.0f}**s'.format(
        (train_time_end + infer_time_end) // 60, 
        (train_time_end + infer_time_end) % 60,
         train_time_end + infer_time_end))

print('**\n**Loss of **{}**: **{:.4f}**'.format(opt_name, final_inference_loss))
print()
print('Accuracy of **{}**: **{:.4f}**'.format(opt_name, final_inference_acc))

因此,我们将三个模型中的每一个运行 20 个时期,并测量所需的总时间(train_time_end + infer_time_end)。注意总时间只包括这两个阶段)以秒为单位,如下所示。时间和准确度是三次运行的平均值。

MNIST:结果。图片作者。

请注意,即使 CNN3L 具有最少数量的可训练参数(#Train Par),它也需要更多的时间来运行(训练和评估)。CNN3L 也是所有型号中最好的(即使精度非常接近)。下面,我们展示了通过带有 PyTorch Profiler 的 TensorBoard 插件获得的 GPU 概要(此处访问)。

MNIST: GPU 总结。图片作者。

在所有模型中,GPU 利用率都非常低。不过注意,CNN3L 的 GPU 利用率最高(4.57%)。底线是,根据经典定义,SNN (CNN3L)比 DNN (LeNet-5)需要更多的运行时间,获得更高的准确性,并利用更多的 GPU。

值得一提的是,GPU 利用率越高越好。但是,由于我们在这里比较的模型具有相同的配置(相同的批量大小,相同数量的 DataLoader 构建工人等等),GPU 利用率较高的模型可能会被解释为比其他模型需要更多的计算资源。我们预计较深的模型比较浅的模型需要更高的 GPU 利用率。

CIFAR-10 数据库

CIFAR-10 数据库包含 32 x 32 幅彩色图像(三个波段)。这里,我们使用了前面三个模型中的两个:由 Nutan 开发的 CNN3L 和在训练分类器 PyTorch 教程中介绍的 LeNet-5。为了正确处理 CIFAR-10 图像,我们对这两个模型做了一些小的修改。优化器,学习率是相同的,但现在批量大小是 4,我们运行每个模型三次,10 个时期。在这里访问代码

图片作者。

在下图(表格)中,时间和准确度是三次运行的平均值。

CIFAR-10:结果。图片作者。

现在,我们有了一个更“自然”的情况。换句话说,LeNet-5 有更多的可训练参数,需要更多的时间来运行。但是,同样,CNN3L 取得了更好的性能。通过带有 PyTorch Profiler 的 TensorBoard 插件获得的 GPU 摘要如下所示(访问此处)。

图片作者。

同样,CNN3L(浅层)比 LeNet-5(深层)显示了更多的 GPU 利用率。

结论

在这篇文章中,我们建议用另一种定义来看待 DNN 模型。我们认为,一个不仅包含隐藏层数量,而且包含训练和/或评估模型所需时间以及计算平台要求的定义可能更合适。

深度神经网络和高斯过程:相似性、差异和权衡

原文:https://towardsdatascience.com/deep-neural-networks-vs-gaussian-processes-similarities-differences-and-trade-offs-18647376d799?source=collection_archive---------3-----------------------

思想和理论

乌列尔 SCUnsplash 上的照片

动机:比较最先进的

深度神经网络(DNNs)高斯过程(GPs)是两类极具表现力的监督学习算法。当考虑这些方法的应用时,一个自然的问题出现了:“什么时候以及为什么使用一种算法比使用另一种有意义?”*

希望这篇文章能为你提供一些指导,告诉你什么时候一个模型比另一个模型更好。照片由 Kristin SnippeUnsplash 上拍摄

在本文中,我们将致力于制定决定使用哪种方法的指南。然而,要开始开发这些指南,我们首先需要了解这些方法之间的关系。在本文中,我们将涵盖:

  1. GPsDNNs 的理论异同
  2. GPsDNNs 的优缺点
  3. 使用 GPsDNNs 的示例案例研究

我们开始吧!

*** 有关高斯过程(GPs)的详细介绍/入门知识,请参见*

  1. 本条 (理论)
  2. 本条 (理论&实现)
  3. 本条 (实现)。

(几个)理论差异

A.参数与非参数

从参数的角度来看,dnn 通常比 GPs 有更多通过学习来调整的“旋钮”。黛安·皮凯蒂诺在 Unsplash 上拍摄的照片

量化这两个模型之间差异的一个方向是考虑每个框架中参数的数量和类型。一般来说,由于高斯过程被认为是非参数机器学习技术,高斯过程(GPs)** 学习明显更少的参数,并且预测很大程度上由定义它们的训练数据集驱动。他们的参数选择完全由以下选项表示:**

  1. 核/协方差函数( k(x,x’))
  2. 平均函数( m(x) )
  3. 似然协方差噪声( σ )。

这些选择/变量通常被称为“超参数”。

高斯过程(GPs)** 中发现的参数缺乏与许多现代深度神经网络(DNNs) 形成鲜明对比,后者旨在利用尽可能多的参数,即所谓的权重,来解决机器学习问题。在经典的统计学习文献中,使用大量的参数一直不被认可,因为这种想法会导致显著的过度拟合和对非分布数据的较差概括。然而,这种经典的统计学习理论未能解释过度参数化神经网络的经验成功,因此“过度参数化或“插值”机制的新理论开始占据上风[1,6]。**

___________________________________________________________________

TL/DR #1: GPs 为(近) 非参数,而 DNNs过参数。***

___________________________________________________________________

*GPs 仅通过其超参数进行参数化,例如上面找到的那些参数。

B .直接与逆方法

与参数/非参数属性相关, GPsDNNs 的另一个不同之处在于 DNNs逆方法GPs直接方法

逆方法 涉及从训练数据中优化参数,因此也被称为监督学习方法。通常,这些方法涉及参数化,带有一些关于参数的初始信念(称为“先验”)。这些方法通常采用自上而下的方法,由此数据被用来更新参数中捕获的信念【7】。

直接方法 依赖于直接使用训练数据来进行新的预测/获得洞察力,正如大多数内核机器所完成的那样。特别是核机器有一个简单的现象,即缺少核函数本身的细节,新的预测完全由现有的可用数据驱动。由于这些方法能够进行实质性的数据探索和洞察,而不需要对底层模型产生强烈的初始信念,因此这些方法通常被称为自底向上【7】。

___________________________________________________________________

TL/DR #2: GPs 是(近) 正方法,而 DNNs逆方法。***

___________________________________________________________________

GPs 的超参数优化是一个间接的例程,通常使用基于梯度和 Hessian 的学习方法来完成。

C.学习差异

GPs 和 dnn 的部分不同之处在于它们如何遍历用于优化性能的损耗表面。丹尼尔·科波尼亚斯在 Unsplash 上拍摄的照片

在没有深度高斯过程的情况下,在 GPsDNNs 之间学习到的内容也不同。然而,完成学习的方法并没有太大的不同:两者都使用第一(在某些情况下,第二)阶方法。这两种方法也优化了不同的函数:对于神经网络,这是一个损失/风险函数,对于高斯过程,这是边际似然函数

对于高斯过程,边际似然目标往往更加非凸,因此,经常使用二阶梯度下降算法,如L-BFGS【5】,进行优化以避免局部极小值。

___________________________________________________________________

TL/DR #3: GPs 一般用二阶方法优化,如 L-BFGS【5】,使用目标函数的海森,而 DNNs 一般用一阶方法优化,如 SGD【8】,使用目标函数的梯度。**

___________________________________________________________________

D .可解释性

在应用机器学习任务中,能够解释你的结果可能与结果本身一样重要。

人工智能:神经网络的可解释性

虽然一些较新的 DNN 结构允许对不确定性进行更彻底的近似,例如通过任意的和认知的不确定性【9】,但是这些网络中的许多只是提供了估计的预测值,并且可能提供了多类分类的逻辑值(预测概率)。然而,由于 DNNs 普遍缺乏可解释性已经成为一个热门的研究课题[10],我相信未来更多的网络架构将会包含一些预测不确定性的元素。

其他进展,如 GradCam [12]等梯度可视化工具,也提高了 dnn 的可解释性,并有助于减少它们的“黑色性”。

D . II:GPs 的可解释性

相反, GPs 固有的高斯结构使其非常适合可解释的不确定性估计。对于某些需要直观风险评估的应用,这可能使该方法更具优势。

此外,GPs 具有良好的直观特性,即所有插值均值预测都是作为训练集中现有均值点的加权线性组合生成的,并按测试点到给定数据点的距离(在核函数空间中测量)进行缩放[11]。GPs 以线性方式重新组合他们以前看到的点,以产生新的预测。

___________________________________________________________________

TL/DR # 4:GPs线性和高斯特性很好地帮助他们增加这些模型的可解释性。尽管 DNNs 长期以来被批评为“黑箱”,但今天的重大研究工作正在进行中,以帮助使这些模型更容易解释。

___________________________________________________________________

(一些)理论上的相似之处

A.“插值机制”中的核心机器

最近的研究表明,当具有线性激活函数的神经网络在其隐藏层中接近无限宽度时,它们渐近收敛于核机器[1,2]。这是一个神经切线核(NTK)【2】的想法。这种现象发生在所谓的“插值区域”,也称为“双下降曲线”的后半部分[1]。

高斯过程也是核机器,因为确定测试点的预测均值和方差的训练点的线性组合是由高斯过程的核函数确定的。

___________________________________________________________________

TL/DR #5: 在一定条件下[1,2], DNNs 可以作为所谓“插值”中的核机器进行分析,配备了一个核函数,从观察点的核加权组合中形成对观察点的预测。 GPs 本质上是内核机器【11】。

___________________________________________________________________

B .目标函数的优化

虽然有各种二阶方法,如 BFGS 和 BFGS,用于优化全球定位系统,一阶方法也可以用来优化这些模型。像 DNNs 一样,GPs 仍然努力最小化泛函(通常是具有核正则项的负对数似然),就像神经网络努力最小化损失函数一样。

___________________________________________________________________

TL/DR #6: 两个 DNNsGPs 都是通过一阶和二阶优化方法来改进他们的模型。

___________________________________________________________________

每种方法的优势

此列表绝非详尽无遗,但在决定使用神经网络还是高斯过程时,这里仅列出了一些优势(相对于其他框架):

GP 优点 / DNN 缺点:

  1. 通常比 DNNs 需要更少的数据,因为它们需要调整的参数更少。然而,拥有更多数据,特别是在固定域上密度不断增加的情况下(称为固定域渐近[1]),有助于显著提高性能。
  2. 只需要优化少量(超)参数。
  3. 对爆炸和消失梯度等现象具有鲁棒性(因为,除非您使用深度 GPs ,否则在此框架内没有“层结构”)。

****GP缺点/DNN优点:

  1. 运行时间与样本数量的比例很小。运行时复杂度为 O(n ) ,其中 n 为样本数。这是必须执行大协方差矩阵的矩阵求逆(或伪求逆)的结果。
  2. 相对于神经网络,自动学习更少,并且对于核/协方差函数、均值函数和超参数先验分布的选择,需要进行更多的设计考虑。这些参数会对 GP 能够学习的内容产生实质性的影响。

每种技术的示例用例

安德鲁·尼尔Unsplash 上拍照

请注意,以下建议不是绝对的,也就是说,这些建议的目的更多的是为了应用我们在上面学到的原则。

****注意:虽然我对这两个模型类都有丰富的实践和理论经验,但请不要将下面的这些建议视为绝对——在某些情况下,使用另一个模型类可能会更有利。

  1. 数据集很大使用 DNNs: 推荐使用 DNNs,因为 GPs 运行时间与示例数据集数量的比例很小,还因为 DNNs 已被证明在给定足够大的数据集的情况下,可以在各种机器学习任务上实现最先进的性能。
  2. 执行连续插值→ 使用 GPs: 推荐使用连续 GPs,因为连续 GPs 使用连续核函数测量距离,如 RBF 核和 Matern 核[11],从而允许以考虑数据集中所有点的方式对来自现有点的新点进行线性加权。通过要求现有点的线性组合,仍然可以观察到精致的插值细节。**
  3. 执行离散插值→ 使用 GPs: 推荐使用,因为离散/网格 GPs 使用稀疏、离散核函数测量距离,如网格插值核。稀疏结构仍然允许通过考虑所有现有的点来预测新点,但是是以计算效率更高的方式进行的。
  4. 在动态数据集上学习和预测→ 使用 DNNs: 由于 GPs(几乎)是直接方法,它们的预测机制很大程度上由创建它们的数据集定义。因此,如果定义 GPs 的数据集是动态的,这将需要重新调整/添加新的数据点,这将涉及重新计算协方差矩阵的逆,这是一项成本高昂的操作。相反,DNNs 可以很容易地适应新的数据点,因为它们是逆模型,并且预测仅由这些模型所基于的数据间接确定。
  5. 其他情况→您决定: 当然还有其他情况没有被上述建议解决。为了解决这些情况,考虑分析上面讨论的相似性/差异/权衡,以确定两个模型类中哪一个性能更好。

总结

凯利·西克玛Unsplash 上拍摄的照片

我们已经讨论了高斯过程(GPs)深度神经网络(DNNs) 的理论相似性/差异、优缺点和应用。我们发现了以下情况:

___________________________________________________________________

  1. GPs 为【几乎】非参数化,而 DNNs过参数化。****
  2. GPs 为(近)正方法,而 DNNs逆方法。****
  3. GPs 一般用二阶方法优化,而 DNNs 一般用一阶方法优化。
  4. GPs 的结构使得这些模型具有很强的可解释性。尽管 DNNs 长期以来被批评为“黑箱”,但今天的研究正在帮助这些模型变得更容易解释。
  5. GPs 本质上是内核机器。在一定条件下, DNNs 也可以分析为内核机。
  6. DNNsGPs 都通过一阶和二阶优化方法改进了他们的模型。
  7. GPs 一般比 DNNs 需要更少的数据,只需要优化少量(超)参数,对爆炸和消失梯度等现象具有鲁棒性。
  8. GP 运行时相对于 DNNs 的样本数伸缩性较差,相对于神经网络的自动学习较少。
  9. 如果:(i) 数据集很小,或(ii) 执行插值→ 使用 GPs。
  10. 如果:(i) 数据集很大,或者(ii) 数据集是动态的→ 使用 DNNs。

感谢您的阅读!想看更多关于计算机视觉、强化学习、机器人技术的内容,请 关注我 。考虑加盟 Medium?请考虑通过这里 报名 。感谢您的阅读!

参考

[1]贝尔金,米哈伊尔。"无所畏惧地适应:通过插值棱镜进行深度学习的显著数学现象." arXiv 预印本 arXiv:2105.14368 (2021)。

[2] Jacot,Arthur,Franck Gabriel 和 Clément Hongler。"神经正切核:神经网络中的收敛和泛化." arXiv 预印本 arXiv:1806.07572 (2018)。

[3]达米亚诺、安德烈亚斯和尼尔·劳伦斯。"深度高斯过程。"人工智能与统计。PMLR,2013 年。**

[4] Blomqvist、Kenneth、Samuel Kaski 和 Markus Heinonen。"深度卷积高斯过程." arXiv 预印本 arXiv:1810.03052 (2018)。

[5]Liu d . c .,Nocedal,j .关于用于大规模优化的有限内存 BFGS 方法。数学规划 45、503–528(1989)。https://doi.org/10.1007/BF01589116**

[6]罗伯茨、丹尼尔·a、绍·亚伊达和鲍里斯·哈宁。“深度学习理论的原理。” arXiv 预印本 arXiv:2106.10165 (2021)。

[7]自顶向下与自底向上的数据科学方法

[8] 赫伯特·罗宾斯和萨顿·门罗一种随机逼近方法《数理统计年鉴》,第 22 卷,№3。(1951 年 9 月),第 400–407 页,DOI: 10.1214/aoms/1177729586。**

[9]阿米尼、亚力山大、威尔科·施瓦廷、艾娃·索莱马尼和丹妮拉·鲁斯。"深度证据回归" arXiv 预印本 arXiv:1910.02600 (2019)。

[10] Park,Sangdon 等人,“深度神经网络分类器的 PAC 置信度预测” arXiv 预印本 arXiv:2011.00716 (2020)。

11 卡尔·爱德华·拉斯姆森。"机器学习中的高斯过程."关于机器学习的暑期学校。施普林格,柏林,海德堡,2003。**

[12] Selvaraju,Ramprasaath R .等人,“Grad-cam:通过基于梯度的定位从深度网络进行视觉解释。”IEEE 计算机视觉国际会议论文集。2017.**

悬崖漫步的深度政策梯度

原文:https://towardsdatascience.com/deep-policy-gradient-for-cliff-walking-37d5014fd4bc?source=collection_archive---------29-----------------------

提示和技巧

用 Python 实现 TensorFlow 2.0。在此解决方案中,参与者由神经网络表示,该网络使用深度策略梯度算法进行训练。

秘密旅行指南Unsplash 上拍摄的照片

在这个关于悬崖行走问题的强化学习系列中,最后一篇文章关注的是普通策略梯度算法(REINFORCE)。尽管具有很强的相似性,但深度学习变体(使用神经网络表示)中有一些重要的细微差别需要注意。本文展示了使用 Tensorflow 2.0 的完整 Python 实现。

悬崖行走问题

悬崖行走问题需要一个代理人(从左下角开始),他需要到达右下角才能获得奖励并赢得游戏[1]。每走一步都会产生一点小成本,以鼓励你走最短的路,然而底部的悬崖应该被避开。

悬崖漫步世界的再现[图片由作者提供]

深度离散政策梯度

在这个问题的策略梯度解决方案中,随机策略 π_θ 为可以在任何瓷砖上采取的四个动作(左、右、上、下)中的每一个分配一个概率。形式上,策略(使用 softmax 函数)可以表示如下:

softmax 函数的 DPG 策略。神经网络 f(⋅)由θ参数化,并对特征向量 ϕ (s,a)执行非线性变换

敏锐的观察者可能会注意到与普通实现相比的微小变化——取代教科书中遇到的矢量点积ϕ(s,a)^⊤⋅θ=∑_ I ϕ(s,a)_i ⋅θ_i,我们现在采用一个通用参数化函数f(ϕ(s,a);θ)

前一篇文章中使用的特征向量 ϕ(s,a) 直接基于状态(每个状态四个θ参数,代表每个动作)。因此,我们有效地训练了各个州的模型。用神经网络表示,这样的隔离是不可能的。将输入层连接到第一个隐藏层的权重可以单独训练,而所有剩余的权重表示对所有状态都有效的紧凑表示。

实际上,这是演员网络的优势和劣势。对于大的状态空间,我们根本无法观察到每一个状态,我们需要一个一般的表示,这正是网络所能提供的。然而,设计一个能够捕捉所有状态的单一表示是一个重大挑战。

具体来说,我们用一个通用的参数化函数 f(ϕ(s,a 来代替ϕ(s,a)^⊤θ;θ) ,其中 f 为神经网络, θ 为网络权重。除此之外,还是以前那个畜生。

网络架构有两种主要的变体。我们可以输入基于状态和动作的特征向量,并输出单个值(后决策方法,需要运行相同的模型四次),或者使用仅基于状态的特征向量,并输出所有四个动作的值。我们在这里实现后者。

离散行动者网络示例。网络将状态作为输入(对于这个问题是一个 48 维的一维热点向量),并输出每个动作的概率(左、右、上、下)。第一层中的权重对于每个图块是唯一的,但是隐藏层是所有状态的一般表示。[图片由作者提供]

使用 TensorFlow(或任何其他深度学习库,就此而言)的一个便利之处是,训练在很大程度上是自动化的;我们只需要给网络输入一个损失函数,训练几乎是自动进行的。对于离散策略梯度,我们采用对数损失(或交叉熵损失)函数:

Tensorflow 实现

首先,我们需要一个演员网络。下面的代码片段构建了它。最终层中的 softmax 激活确保输出是概率总和为 1 的向量,而权重初始化确保初始动作概率相等。

接下来,我们需要损失函数。在这种情况下,我们使用交叉熵损失函数:

我们不必为手动计算梯度而烦恼;所需要的只是损失函数。GradientTape功能跟踪我们的数学运算,并使用该内存为我们计算梯度。更新程序——在每集之后执行——概述如下。注意,针对轨迹中每个奖励的所有损失立即计算梯度;这是因为中间更新会改变参与者网络,从而改变梯度所需的计算概率(尽管这种方法肯定不是唯一的解决方案)。

完整的实现可以在我的 GitHub 上找到:

https://github.com/woutervanheeswijk/cliff_walking_public

还没完全明白吗?没问题:这个最小的工作示例一步一步地引导您完成离散策略梯度算法:

实验

像往常一样,如果不进行测试,实现就不完整。让我们试一试,对比香草策略梯度(基本强化实现)【SARSA】(基于价值的基于策略比较)深度 Q 学习(基于价值的神经网络对应物)。

普通策略梯度很难获得稳定的解决方案,遭受高方差和探索的不利影响。以前,深度 Q 学习也比普通 Q 学习困难得多。深度政策梯度似乎结合了两个世界最糟糕的部分,它的表现如何?下注吧。

Rien ne va plus…照片由 Adi CocoUnsplash 上拍摄

它进行得不顺利。事实上,这是我第一次决定调整奖励结构,提高达成目标的相对奖励。最初,每次移动的概率是 0.25;因此,达到目标的几率相当低。行动者网络还对状态进行概括,例如,如果在开始时“向右”移动是不好的,则减少的概率倾向于延续到其他图块。

实际上,如果在前一千次左右的迭代中没有找到目标,找到满意的策略的机会相当小。增加熵奖励也没有起到任何作用。在高学习率的情况下,该算法可能会收敛到一个局部最优(例如,直接跳进悬崖或呆在角落里),而无需观察目标。由于学习率低,偶尔达到目标并不能为重复提供足够强的奖励信号。

所以,我作弊了一点,把奖励提高了 10 倍,大大提高了可靠性。姑且称之为奖励塑造。这样一来,是时候比较表现了,强调单次运行显示出大的波动。

普通政策梯度与深度政策梯度的比较。两者都在努力应对巨大的差异,但最终通常会趋同于可比的政策。不过,深度变体似乎不太稳定。[图片由作者提供]

vanilla SARSA 和 Deep policy gradient 的比较。SARSA 收敛得更快,并且达到更稳定的策略。[图片由作者提供]

深度 Q 学习和深度策略梯度的比较。虽然两者都在努力学习,但是深度 Q 学习通常收敛得更早,并且收敛到更好的策略。[图片由作者提供]

尽管 SARSA 并不以其强大的探索机制而闻名——在这种情况下,这是一种简单的ϵ-贪婪方法,其中ϵ= 0.05——q 值的初始化对该问题有重大影响。当所有 Q 值都设置为 0 时,有一种尝试新状态的强烈倾向;代理可能相当快地发现目标(对于深度 Q 学习,这个逻辑不成立,因为 Q 值是一般化的,而不是从查找表中获得的)。策略梯度算法——尽管有一个非常的显式探索机制——实际上找到目标的机会相当小,并且它经常在达到目标之前就收敛到局部最优。

使用深度策略梯度获得的示例路径。由于策略中固有的随机性,代理经常绕道或重新访问图块。[图片由作者提供]

最后,一切都解决了。旅程并不总是像事先希望的那样顺利,但我们又一次安全地避开了悬崖。

外卖食品

  • 普通政策梯度和深度梯度的关键区别在于,深度变量概括了跨州的行动概率。将线性表达式 ϕ(s,a)^⊤θ 替换为神经网络f(ϕ(s,a);θ).
  • 学习策略具有挑战性,因为(I)概率策略使发现目标变得困难,以及(ii)概率通常在各州之间通用。为此,增加了目标奖励。
  • 由于策略梯度算法的高方差,奖励整形可能会有所帮助。在这个问题中,好的回报轨迹是罕见的;更新信号需要足够强以产生影响。

深度策略梯度算法的完整代码可以在我的 GitHub 资源库 上找到。

表格 Q-learning 和 SARSA 对于悬崖行走问题的实现如下:

深度 Q 学习算法 也已经实现:

*

最后, 离散政策梯度 变体如本文所示:

参考

[1]萨顿和巴尔托(2018 年)。强化学习:简介。麻省理工出版社。*

悬崖行走问题的深度 Q 学习

原文:https://towardsdatascience.com/deep-q-learning-for-the-cliff-walking-problem-b54835409046?source=collection_archive---------21-----------------------

思想和理论

一个完整的 Python 实现,用 TensorFlow 2.0 导航悬崖。

内森·杜姆劳Unsplash 上拍摄的照片

乍一看,从普通 Q-学习到深度 Q-学习似乎是一小步。只要把查找表换成神经网络就大功告成了。然而,事情远不止如此——即使对于最简单的问题,深度 Q 学习也可能难以取得结果。

为了展示如何避免一些常见的陷阱,本文讨论了深度 Q 学习的 TensorFlow 2.0 实现,以解决众所周知的悬崖行走问题。首先,我们展示了标准化和一键编码如何将输入和输出与神经网络对齐。然后,我们部署了三种据说可以显著提高深度 Q 学习常见技术:经验重放目标网络小批量

悬崖行走问题

悬崖行走问题(关于普通 Q-learning 和 SARSA 实现的文章这里)相当简单[1]。代理从左下角开始,必须到达右下角。走进分隔这些瓦片的悬崖会产生巨大的负面奖励,并结束这一集。否则,每一步都要付出很小的代价,这意味着最短的路径是最优策略。

悬崖行走词示例。目标瓦片产生正奖励,每走一步产生小负奖励,掉下悬崖产生大负奖励[图片作者]

这个问题可以通过 Q-learning 解决。这是一种强化学习方法,它存储代表每个状态-动作对(总 48⋅4)的预期未来回报的 q 值。值得一提的是,Q-learning 是一种非策略方法——对于下游动作,我们假设最佳可能动作,而不是实际样本轨迹的动作。因此,Q-learning 鼓励探索,因为失败的影响相对有限。

Q-learning 是一种非策略强化学习方法。基于在 t+1 时采取的最佳动作而不是实际动作来更新时间 t 时的 Q 值。因此,勘探的负面影响是有限的。

从普通 Q 学习到深度 Q 学习

在之前的一篇文章中,我提供了一个在 TensorFlow 2.0 中实现深度 Q 学习的最小工作问题。这里,我假设你熟悉普通 Q 学习,至少熟悉深度 Q 学习的基础。简单回顾一下:在深度 Q 学习中,我们训练一个神经网络,它将状态作为输入,并输出每个动作的 Q 值。虽然查找表对于大的状态空间来说是爆炸式的,但是深度 Q 网络提供了一种对所有状态都适用的紧凑表示。然而,仅仅替换查找表通常是不够的,我们通常需要以下技术(在这里用实现细节描述)来获得更好的结果[2]:

  • 标准化和一次性编码
  • 体验回放
  • 目标网络
  • 小批量

标准化和一次性编码

重要的事情先来。当处理相同大小的输入和输出时,神经网络往往工作得更好。因此,我们将所有奖励除以 100,所以它们(大约)在-1 和 1 之间。累积奖励信号是网络的目标输出

我们还必须注意定义作为神经网络输入的状态。在普通的 Q 学习中,我们可能会将目标瓦片称为“状态 48”,将相邻的悬崖瓦片称为“状态 47”,但自然地,这样的数值对神经网络来说意义不大。它只是简单地乘以某个权重向量,无法区分 47 和 48 具有完全不同的含义。为了解决这个问题,我们应用了 one-hot 编码,将输入定义为长度为 48 的数组。对应于当前图块的元素具有值 1,所有其他元素具有值 0。因此,我们可以学习对应于每个瓦片的唯一的一组权重

输入和输出现在都被规范化了,所以我们可以安全地用类似于 He-或 Glorot 初始化的东西初始化权重,不再担心标度差异。

体验回放

Q-learning 依赖于时间差异,使用“预期”值Q_t和“观察”值r_t+Q_t+1之间的差异作为误差。不幸的是,Q_t+1Q_t一样都是猜测——它们是由同一个神经网络决定的。

更糟糕的是,随后的观察结果往往高度相似,使用几乎相同的状态作为输入。这在相邻的观测值之间产生了很强的相关性。特别是非线性近似(如神经网络)往往很难处理这种相关性。

用不那么抽象的术语来说:考虑一个被困在悬崖世界角落里的代理人。这个代理人可能会不断地收到相同的奖励信号,并在网络上对这个特定角落的行动进行过度拟合。你会经常看到这种情况发生:代理人了解到向右走不好(由于悬崖)并且倾向于停留在世界的左边,不断地调整网络以适应那个区域。

为了打破这种关联,我们部署了体验回放。不是总是选择最近的观察来更新我们的网络,而是每当我们更新时,我们存储我们过去的所有观察和来自这个重放缓冲器的样本。每个观察由一个(s,a,r,s’)元组表示。为了计算当前的 Q 值(从我们获得观测值的时间起而不是,我们将ss’馈送到主要网络,使用a获得Q_t,使用 argmax 动作获得Q_t+1

小批量

理论上,我们可以收集许多观察结果,并将神经网络拟合到单个批次,通过单次更新来确定最终策略。在许多监督学习问题中,在大型数据集上一次性训练网络是非常常见的。然而,在强化学习的情况下,我们将总是基于我们的初始策略进行观察(这可能非常糟糕)。我们希望探索足够多的东西,以避免陷入局部极小,同时也主要从好的动作中学习。

因此,大批量不是很有用。我们希望将观察和更新结合起来,逐步改进我们的政策。然而,这并不意味着我们必须更新每一个观察结果——悬崖行走问题中的一个步骤往往教会我们很少东西,因为我们没有观察到任何有意义的东西。显而易见的妥协是小批量,这意味着我们经常用大量的观察数据更新我们的网络。特别是与经验重放相结合,这是一种强大的技术,可以基于大量以前的观察获得稳定的更新。

目标网络

到目前为止,我们已经从同一个网络中得出期望值Q_t和“真实”值r_t+Q_t+1。因此,观察和目标相互关联,再次使用一个猜测来更新另一个猜测。

为了缓解这个问题,我们使用了一个目标网络。目标网络只不过是 Q 网络的周期性副本,以较低的频率更新(比如每 100 集一次)。因此,我们将期望值和目标值分离,减少了两者之间的相关性。目标保持相当稳定,而政策本身则在逐步改进。

深度 Q-将学习付诸行动

在概述了实现深度 Q 学习所需的理论之后,让我们看看它在实践中的实际表现。在我的 GitHub 库中可以找到关于悬崖行走问题的学习方法的完整实现。

让我们给我们的 Q 网络——3 个隐藏层,每个层有 25 个神经元——一个旋转。与表格变量相同的 0.1 学习率,没有重大调整。

所有算法学习率α=0.1 的强化学习。深度 Q 学习在这里实际上什么也学不到,而 Q 学习和 SARSA 很快收敛。[图片由作者提供]

呀!Q-learning 和 SARSA 迅速收敛到稳定的政策,而深度 Q-learning 似乎没有学到任何值得注意的东西。最重要的是,后者需要更多的计算工作。在我的笔记本电脑上,10,000 次迭代需要大约 20 分钟,而 Q-learning 和 SARSA 只需要几秒钟。

幸运的是,经过一些调整——特别是,将学习率降低到 0.001——事情看起来好多了。收敛仍然需要比表格变量长得多的时间,但是整体深度 Q-学习达到了与常规 Q-学习相同的策略。

用于深度 Q 学习的学习速率α=0.001 的强化学习在这里有效地不学习任何东西,而 Q 学习和 SARSA 快速收敛。[图片由作者提供]

让我们拿出我们剩下的武器库:体验重播,一批 5 个(更新频率也减少了 5 倍,以保留相同数量的数据点)和每 10 集更新一次的目标网络。最终结果:

深度 Q 学习,包括经验回放、小批量和目标网络。部署这些稳定技术并没有导致更快的收敛。[图片由作者提供]

那…实际上很令人失望。尽管我们做了所有的努力,一个简单的 Q 表仍然打败了我们花哨的神经网络。发生了什么事?哪里出了问题?

什么都没发生。没出什么差错。深度学习很有挑战性。我们试图学习一个适用于所有状态的通用函数。通过多层反向传播错误也需要时间。我们的未过滤重放缓冲区保存了许多糟糕的观察结果。为了适应目标网络和批量学习,降低更新频率也会降低收敛速度。神经网络不是神奇的黑匣子。机器学习并不等同于超自然智能。

当然,我们本可以在调优上花更多的时间来提高性能。在一个小批量中应该有多少个观察值?什么是理想的网络架构?我们应该给予体验什么样的优先权?我们必须多久更新一次目标网络?所有重要的问题,也是需要时间来回答的问题。参数调整成本高。

有些发人深省的结论是:尽管潜在的难以置信的强大,深度学习也很难成功实施。根据你的问题和你的目标,这可能并不总是最好的方法。

外卖食品

  • 深度 Q 学习不仅仅是用神经网络代替查找表。它的性能通常不太稳定,需要更多的建模和调优工作。
  • 使用适当的归一化一键编码使状态和动作适合神经网络。
  • 经验回放——从过去(s,a,r,s)元组的缓冲区中随机取样——打破了后续观察之间的相关性。
  • 目标网络——Q 网络的周期性副本——可用于计算 Q_t+1。这降低了期望值Q_t和目标值r_t+Q_t+1之间的相关性。
  • 小批量稳定更新,一次利用多个观察更新网络。

深度 Q 学习算法的完整代码可以在我的 GitHub 资源库 上找到。

我实现的表格 Q-learning 和 SARSA 对于悬崖行走的问题在这里有详细介绍:

离散策略梯度 变体如本文所示:

*

深策渐变 ,勾选:

下面的文章给出了 深度 Q 学习 的一个最小工作示例:

最后,我在这里讨论经验回放、批量学习和目标学习的实现示例:

参考

[1]萨顿和巴尔托(2018 年)。强化学习:简介。麻省理工出版社。

[2]t .马蒂森(2015 年 12 月 19 日)。《揭秘深度强化学习》神经外科。计算神经科学实验室。检索时间 2021 年 9 月。*

深度 Q 学习不是火箭科学

原文:https://towardsdatascience.com/deep-q-learning-is-no-rocket-science-e34912f1864?source=collection_archive---------18-----------------------

用 pytorch 解释和编码的深度 Q 和双 Q 学习

(作者 GIF)

情境中的深度 Q 学习

q 学习是强化学习社区中早已存在的一种方法。然而,最近通过使用神经网络与 Q 学习相结合,在该领域取得了巨大进展。这就是所谓的深度 Q 学习的诞生。这种方法的全部潜力在 2013 年被看到,当时谷歌向世界展示了他们的 DQN 代理商在玩雅达利突破。对我来说,这是我第一次接触这个领域,我立刻对它产生了兴趣。

其他强化学习方法有策略梯度法和行动者批评法。行动者批评方法是 Q 学习和政策梯度方法的混合。

一般强化学习

在强化学习中,我们有一个环境,在这个环境中,一个代理正在做动作。环境然后返回一个奖励和一个新的状态。代理人得到的报酬也取决于他实际所处的状态。所以他/她应该学会根据实际情况调整行动。

作者图片

我们要用的环境是 CartPole-v0 环境,作者是 OpenAI。我们可以在 python 中轻松使用它。这是一个非常简单的环境,对于大多数深度强化学习算法来说,求解起来也非常简单。因此,每当我写一个新的强化学习脚本时,我都会用它来测试我是否正确地实现了所有的东西。

南极环境

我们从导入和测试 openai gym 开始。如果您还没有安装它,您可以通过键入:

pip3 install gym

然后,我们编写一个脚本来测试我们的健身房环境。我们让代理执行随机的动作,只是为了看看是否一切正常。

(作者代码)

代理的目标是尽可能长时间地平衡操纵杆。如果棍子在两个方向偏离垂直方向 15 度,它就失败了,这一集就结束了。

(图片由作者提供)

代理为实现其目标可以采取的行动有:

  • 向左移动(0)
  • 向右移动(1)

奖励以如下方式给出:

  • 每走一步+1,棍子是直立的

状态/观察值是 4 个值的列表:

(图片由作者提供)

深度 Q 学习

蜕变能

考虑下面的场景。我们的鸡饿了。它可以执行两个操作。它可以吃也可以写。因为它饿了,更好的选择是吃东西,这确实会给它更多的奖励。但是奖励是在行动完成后给予的,所以它怎么会知道。在这种情况下,动作值(或 Q 值)可以帮助我们。这个 Q 值取决于状态和可能的动作。给定状态,Q(s,a)然后返回执行动作的值。所以鸡应该执行 q 值最高的动作!

(图片由作者提供)

Q 值由下式定义:

(图片由作者提供)

这个等式简单地意味着,对于一个给定的状态,一个行为的价值是这个行为执行后的直接回报加上下一个状态的(贴现的)最高 Q 值。伽马(𝛾)实际上是贴现因子,它解释了未来回报的不确定性。𝛾通常大于 0.9,小于 1。低 gamma 导致代理更关注眼前的回报,而高 gamma 导致代理更关注未来的高回报。

时间差异学习

我们已经看到了 Q 值的精确定义,我也告诉过你,我们将使用神经网络来逼近它。

(图片由作者提供)

因此,我们希望使网络的近似 Q 值尽可能接近数学定义。为了实现这个目标,我们使用神经网络的能力来最小化损失函数。

(图片由作者提供)

我们把实际时间步长的 Q 值称为“预测”,把包括下一个状态目标的 Q 值的项称为“预测”。

我们使用的损失函数就是均方误差损失。

(图片由作者提供)

利用时间差学习,我们可以在每个时间步训练我们的代理。

勘探开发的困境

如果我们让我们的代理贪婪地利用它认为具有最高 Q 值的策略,很可能存在更好的策略。代理人将永远无法探索这一策略,因此永远看不到与之相关的高回报。所以在开始的时候,我们让自己做随机的行为,随着时间的推移,减少它采取随机行为的可能性。这个过程被称为𝜖贪婪行动选择。

体验回放

深度 Q 学习不是特别好,除非我们通过添加经验回放来增强它。为此,我们建立了一个记忆,把所有的状态、行为和奖励都储存在里面。训练时,我们从记忆中检索随机的一批,并在其上进行训练。这意味着代理很可能没有接受过上一个时间步骤的培训。

下面的代码实现了一个 ReplayBuffer 类,它负责存储和分配随机批次的内存。对于我们存储的每个时间步长:(state,action,reward,next_state,done)。done 是一个结束标志,在一集期间为 0,在一集结束时为 1。

(作者代码)

整个算法和代码

我决定向您展示主文件的 python 代码,而不是伪代码,因为如果您了解 python,这更容易理解。

(作者代码)

我们可以调整许多超参数,我们将它们传递给代理的构造函数:

agent = DQAgent(learning_rate=0.00025, gamma=0.90, batch_size=32, 
                     state_len=len(env.reset()), 
                     n_actions = env.action_space.n,
                     mem_size = 1000000,
                     min_memory_for_training=1000,
                      epsilon=1,epsilon_dec=0.99,
                     epsilon_min = 0.02)

学习率:神经网络的学习率。高值会使代理学习得更快,但也会导致在复杂环境中的次优行为。

伽马: 𝛾通常在 0.9 以上,小于 1。低 gamma 导致代理更关注眼前的回报,而高 gamma 导致代理更关注未来的高回报。

批次大小:给神经网络执行小批次梯度下降的时间步数。高批次数量稳定了学习,但也可能导致停滞。

训练的最小记忆:学习过程开始前的步数。一个合适的数字可以防止网络过度适应前几个训练样本。

ε:ε的起始值。1 表示代理在开始时只执行随机操作(探索), 0 表示它不会开始执行随机操作(利用)。

Epsilon dec:Epsilon 在每个时间步长后乘以的系数,以减少它。应该大于 0.99 小于 1。

ε最小值:ε的最小值。如果ε低于该值,它将不会减小。任何时候都要有一点点的探索,让代理不断学习,这一点很重要。

现在我们代理的全部代码是:

(作者代码)

让我们来讨论一下这段代码:

target = rewards_batch + torch.mul(self.gamma* self.q(new_states_batch).max(axis = 1).values, (1 - dones_batch))

它计算 TD 目标。假设我们的批量是 5。

那么计算可能如下所示:

(图片由作者提供)

我们做 max 运算,因为我们想看 Q 值最高的动作。

让我们看看下面的代码行:

prediction = self.q.forward(states_batch).gather(1,actions_batch.unsqueeze(1)).squeeze(1)

它计算预测。批量大小为 5 时,可能如下所示:

(图片由作者提供)

我们从代理实际采取的行动中选择 q 值。

测试

现在是时候实际测试我们的算法了。我们用我们的 CartPole-v0 环境测试它。

在 100 集之后,代理人设法击败了环境,并且几乎总是获得最高分。

(图片由作者提供)

(图片由作者提供)

双 Q 学习

为了进一步改进我们的深度 Q 学习算法,我们可以选择具有单独的预测值和目标值。这也叫双 Q 学习。

(图片由作者提供)

这些动作将通过预测网络进行预测。反向传播只发生在预测网络中。预测网络的参数每隔几次迭代就被复制到目标网络。目标网络的参数保持“冻结”多久也是一个超参数。

(图片由作者提供)

我们冻结了目标网络,因为这样预测和目标的相关性就降低了。这有助于学习过程

测试

现在我们有一点乐趣,用 openai 环境“LunarLander-v2”测试我们的算法。你可以在下面找到我用过的超参数列表。

学习率: 0.001

伽玛: 0.99

批量: 64

训练最小内存: 1000000

ε:1

εdec:0.995

ε最小值: 0.02

冻结 _ 迭代: 6

以下 GIF 拍摄于 729 集。代理人在着陆方面做得很好。

(作者 GIF)

学习曲线是这样的。

(图片由作者提供)

请注意,它被 20 集移动平均线平滑。

密码

主文件:

(作者代码)

代理的代码:

(作者代码)

作者相关文章

想联系支持我?

领英
https://www.linkedin.com/in/vincent-m%C3%BCller-6b3542214/
脸书
https://www.facebook.com/profile.php?id=100072095823739
推特
https://twitter.com/Vincent02770108
中等
https://medium.com/@Vincent.Mueller
成为中等会员并支持我(你的部分会费直接归我)
https://medium.com/@Vincent.Mueller/membership

深度 Q 网络:结合深度和强化学习

原文:https://towardsdatascience.com/deep-q-network-combining-deep-reinforcement-learning-a5616bcfc207?source=collection_archive---------9-----------------------

实践教程

揭示深度强化学习的力量

R 强化学习(RL)是数据科学中最令人兴奋的研究领域之一。长期以来,它一直是许多数学家工作的中心。

而今天,随着深度学习的改善和计算资源的可用性,RL 引起了更大的兴趣:随着大量数据不再代表障碍,新的建模方法出现了。

在这种背景下,强化学习方法和深度学习模型的结合,通常被称为深度 RL,已经被证明是强大的。

它是最近人工智能领域令人印象深刻的进步的基础。它甚至使算法在雅达利、围棋或扑克等领域超过了人类的表现。

本文的目的是阐明深度学习在 RL 领域的贡献。为此,它重点介绍了 Q-Learning(一种常见的 RL 模型)的示例,并解释了包含神经网络的附加价值。

阅读本文后,您将了解到:

  • 什么是强化学习,它基于什么原则和技术?
  • 什么是深度 Q 学习,它与“通常的”Q 学习有什么不同?
  • 强化学习的潜在贡献是什么,还有哪些挑战?

1。什么是强化学习?

让我们首先快速概述一下 RL 原则。

从一般的角度来看,RL 可以用非常简单的话来解释。这就像教你的狗一个新把戏。当你的狗表演魔术时,你给它一点狗粮作为奖励,如果它不表演,你就惩罚它,不给它任何东西。

同样,RL 包括训练机器学习模型来做出决策。代理通过与他的环境交互以自主的方式学习采取什么行动,即通过根据它采取的行动接收奖励或惩罚。通过其经验,代理人寻求找到最优决策策略,这将使他能够最大化随着时间积累的回报

术语

在这种情况下,有一个特定的术语用于描述 RL 环境的组件:

  • 代理人:要培训的决策者。
  • 环境:代理学习和决定采取什么行动的一般环境。
  • 动作 𝑎:代理可以执行的一组可能动作中的一个
  • 状态代理所处的𝑠:状态
  • 奖励 𝑟:代理人因其自身行为而从环境中获得的收益或损失
  • 策略 𝜋:代理人选择采取的策略。它表示一组情况和一组可能的动作之间的映射。

为了了解每个元素具体对应什么,让我们以吃豆人游戏为例。如下图所示,代理人是 Pacman。他的目标是避开鬼魂,尽可能多地吃掉食物和受惊的鬼魂。

强化学习环境组件,图片由作者提供

韵律学

在这种情况下,有两个指标:

  • 价值函数 𝑉𝜋(𝑠):期望贴现回报从𝑠开始,接着是𝜋政策

其中𝑅代表回归。

  • Q 值在给定的状态 s 和给定的动作 a 下,𝑄𝜋(𝑠,𝑎):期望贴现收益,同时遵循此后的政策𝜋∗。

2。深度学习给强化学习带来了什么?

为了了解深度学习对 RL 的附加值,我将重点讨论 Q-Learning 的例子,并将‘通常的’Q-Learning 与深度 Q-Learning (也称为深度 Q 网络)进行比较。

Q-Learning

直观地说,Q 学习算法包括学习一个 Q 表(‘Q’代表质量),它包含每个状态和行为的预期未来回报。

由于有了这个‘备忘单’,代理人能够通过选择使预期未来回报最大化的行动来为每个状态做出最佳选择。

该图说明了 PacMan 案例中的过程:

q-学习管道,图片由作者提供

代理如何学习 Q 表?

  1. 首先, Q 表被任意初始化。列数是可能动作的数量,行数是状态的数量。
  2. 那么,只要这一集还没有结束:
  • 2.1.处于状态 s 的代理人根据 Q 表选择 a 使的期望未来报酬最大化的行动。
  • 偶尔,****代理被允许随机选择一个动作。这就是所谓的ε贪婪策略。它使代理能够探索他的环境(并不总是以狭隘的方式遵循他的“备忘单”)。更多信息,可以阅读这篇文章
  • 2.2.代理观察结果状态 s’和奖励 r,并且更新函数 Q(s,a)** 如下:**

深度 Q 学习

正如您所料,当处理具有各种可能性和结果的复杂环境时,以前的 Q 学习算法很快变得低效。

****幸运的是,通过将 Q-Learning 方法与深度学习模型相结合,Deep RL 克服了这个问题。它主要包括建立和训练一个神经网络,能够估计给定状态下每个动作的不同 Q 值。

深度 Q-学习管道,受这篇文章的启发

下图比较了 Q 学习和深度 Q 学习方法:

Q-Learning vs . Deep Q-Learning,受这篇文章的启发

注意,网络的损失函数是损失函数:

这还不是全部:深度 Q 学习引入了两个额外的机制,可以实现更好的性能。

1。记忆回放:

  • 神经网络不是在每一步后立即更新。取而代之的是,它将每次经历(通常作为一个元组<动作、状态、奖励、下一个状态>)存储在存储器中。
  • 然后对从重放存储器中随机选择的称为小批量的一组元组进行更新。
  • 这种机制使算法能够记住并跟踪他过去的经历。

2。单独目标网络:

  • 使用相同的网络计算预测值和目标值(在损失函数中使用)会导致严重的不稳定性
  • 为了克服这个问题,通常适合于训练两个具有相同架构的独立网络:预测网络和目标网络。****
  • 预测网络作为“在线”网络工作,而目标网络是预测网络的副本,具有定期更新的冻结参数。****

3。深度强化学习能带来什么?

应用

如果说 RL 机型主要以在雅达利或围棋等高精尖游戏中的骄人表现著称,那么适用范围就要广得多。它们可以应用于各种商业案例。

从金融交易、推荐系统到机器人,RL 能够通过其独特的试错学习方法捕捉复杂的现实生活问题。

这当然是这种学习范例的关键优势: RL 模型在没有任何关于环境的先验知识的情况下被训练。它们不需要对金融市场风险、客户行为或系统的物理特征进行任何建模。因此,它们可以避免一些非常重要的步骤。

挑战

尽管如此,使用 RL 来解决特定的问题带来了 3 个主要挑战 s:

  1. ****模拟环境:构建环境是一个关键点,因为 RL 模型从与环境的交互中学习。如果模拟一个游戏看起来相对容易,那么当涉及到自动驾驶汽车、能源优化等其他应用领域时,它就会变得很快变得更加复杂。
  2. ****达到全局最优:如果一个 RL 代理没有充分探索他的环境,他可能会陷入局部最优。这就是所谓的勘探开发困境。当代理了解他的环境时,他在探索更多的环境以获得更好的可能性视野和利用他的经验来追求他认为最有利可图的策略之间左右为难。
  3. ****选择合适的算法并调整其参数:RL 模型种类繁多。他们依赖于完全不同的方法,并使用几个超参数。因此,有必要仔细选择算法和正确的度量来评估其性能。

深度 Q 网,带 PyTorch

原文:https://towardsdatascience.com/deep-q-network-with-pytorch-146bfa939dfe?source=collection_archive---------9-----------------------

解释无模型 RL 算法的基础:深度 Q-网络模型(带代码!)

Mathias P.R. Reding 在 Unsplash 上拍摄的照片

在 Q 学习中,我们将 Q 值表示为一个表格。然而,在许多现实世界的问题中,存在巨大的状态和/或动作空间,并且表格表示是不够的。例如,电脑围棋有 10 个⁷⁰状态,像马里奥兄弟这样的游戏有连续的状态空间。当不可能在二维数组或 Q 表中存储状态和动作对值的所有可能组合时,我们需要使用深度 Q 网络(DQN)来代替 Q 学习算法。[1]

DQN 也是一种无模型的 RL 算法,其中使用了现代深度学习技术。DQN 算法使用 Q 学习来学习在给定状态下采取的最佳动作,并使用深度神经网络或卷积神经网络来估计 Q 值函数。

DQN 建筑的插图

神经网络的输入包括一个 84 x 84 x 4 的图像,随后是 3 个卷积层和 2 个完全连接的层,它们为每个有效动作输出一个输出。[1]

DQN 建筑的插图[1]

DQN 算法

DQN 算法[1]

DQN 的主要成分— 1。q 值函数

在 DQN,我们用权重 w 来表示价值函数,

q 值函数。作者图片来源于[1]。

  • 在选择行动时,Q 网络的工作方式类似于 Q 学习中的 Q 表。Q-learning 中的状态是可数的和有限的,而 DQN 中的状态可以是有限的或无限的/连续的或离散的。
  • Q 网络中的更新是通过更新权重来完成的。

DQN 的主要成分— 2。损失函数

让我们用 Q 值的均方误差来定义目标函数。

损失函数。作者图片来源于[1]。

这是一个损失函数,用于最小化在 Q 网络中更新权重的误差。

DQN 的主要成分— 3。优化算法

让我们用随机梯度来优化上面的目标函数,用 δL(w)/δw 。Tensorflow 或 PyTorch 中有许多可用的优化算法。比如亚当,RMSProp,阿达格拉德等。

DQN 的主要成分— 4。体验回放

朴素 Q 学习用神经网络振荡或发散。

数据是连续的,这意味着连续的样本是相关的,而不是独立的和同分布的。

政策会随着 Q 值的轻微变化而快速变化或振荡,因此,数据的分布会从一个极端转移到另一个极端。

奖励和 Q 值的比例是未知的。当反向传播时,朴素 Q 学习的梯度可能很不稳定。[2]

为了解决上述问题,我们可以将转换存储在重放缓冲器中,并从重放缓冲器中采样一小批经验来更新 Q 网络。从中。通过使用经验重放,它将打破样本之间的连续相关性,并且还允许网络更好地利用经验。[1]

下面的教程将使用 DQN 来解决来自健身房环境的雅达利游戏。对于所有 Atari 游戏,它接受 84x84x4 图像帧作为输入。因此,首先,我们需要进行数据预处理,即跳过连续样本之间的一些帧,因为这些连续样本几乎是相同的,重新缩放图像,灰度化图像,归一化图像等。

DQN 解算器将使用 3 层卷积神经网络来构建 Q 网络。然后,它将使用优化器(下面代码中的 Adam)和经验重放最小化误差以更新 Q 网络中的权重。

最后,我们可以用run(training_mode=True, pretrained=False)进行训练,用run(training_mode=False, pretrained=True, num_episodes=1, exploration_max=0.05)进行测试。

  • 第一次训练网络时,可以使用pretrained=False,否则可以使用pretrained=True从上次停止的地方继续训练。
  • 然而,对于测试,你只能使用pretrained=True,这意味着你使用训练好的 Q-网络来测试代理的性能。
  • exploration_max=1在训练过程中,因为我们希望 agent 以ε概率随机进行探索,这样就不会陷入局部极小值。然而,在测试过程中,我们希望代理从经过训练的 Q 网络中采取优化的行动,因此,我们应该使用 0 或非常少的探索exploration_max=0.05.

推荐阅读

参考

[1] V. Mnih et al.通过深度强化学习的人级控制。

[2]华盛顿大学 CSE571 讲座—“概述深度学习强化学习深度价值功能深度政策深度模型。

深度 Q 网配合 Pytorch 和 Gym 解决 Acrobot 游戏

原文:https://towardsdatascience.com/deep-q-network-with-pytorch-and-gym-to-solve-acrobot-game-d677836bda9b?source=collection_archive---------5-----------------------

一种深度强化学习算法的介绍与实现

作者插图

强化学习是机器学习的一个分支,受人类和动物行为主义心理学的启发。在监督学习 (SL)中,学习受到限制,因为它总是需要外部教学信号来帮助解决任务,如分类和回归。

与第二语言不同,强化学习基于不同的原则。主要目标之一是生产一个自主代理,它与环境交互,学习和选择最优行动,有助于实现其目标,如最大化回报。代理观察环境中的状态,并在给定状态的情况下执行动作。每次代理通过采取行动进行交互,他可能会收到一个负奖励

通过反复试验,最佳行为会随着时间的推移而改进。这种学习方式让我想起了我们从经验中学习的方式。我们讨厌犯错,但当我们从中吸取教训并在未来做得更好时,错误会变得很有价值。同样,强化学习探索不同的动作和状态,以找到最优的动作。此外,当在学习过程的早期出现错误时,对代理的训练更加健壮。

由于这些特点,强化学习经常被应用于玩游戏、机器人和许多其他决策问题。强化学习与深度学习技术的结合,使得在高维状态空间的问题上取得巨大进步成为可能。例如,当代理需要从屏幕像素中学习时,它就很有用。这些方法被称为深度强化学习

在本教程中,我将训练一个执行 Acrobot 任务的代理。Pytorch 将用于实现 Deep Q 网络,而 Google Colab 笔记本将被使用,因为它提供免费的 GPU 来加速训练。

目录:

  1. OpenAI 健身房
  2. 安装并导入库
  3. 行动和观察空间
  4. 随机代理
  5. 实现深度 Q 网
  6. 经验回放
  7. ε-贪婪政策
  8. Softmax 策略
  9. 勘探剖面图
  10. 训练

1.奥鹏健身馆

Gym 是一个开源库,提供强化学习算法的实现【1】。有许多教学代理可供培训,如 Cart-Pole 和 Pong。在本教程中,我将重点介绍 Acrobot 环境。在之前的教程中,我很好地解释了这个游戏如何如果你想更深入地理解它。

2.安装和导入库

我们需要安装和导入 python 包。最重要的套餐是健身房,它提供强化学习环境。还有其他有用的库,如:

  • torch.nn实现深度 Q 网络
  • 需要IPython.displaypyvirtualdisplay.display来创建一个虚拟显示器,在上面绘制游戏图像
  • collections是 Python 基本对象的替代品,如列表、元组、字典和集合。它用来存储代理的经验。

3.行动和观察空间

我们可以使用 make 函数实例化体育馆环境。我们也可以设置一个随机的环境种子,每次都产生相同的结果。你大概可以想象,每个环境都有不同数量的动作和观察。通过打印,我们可以很容易地看到操作和观察空间:

动作空间是离散的,因此动作可以是以下非负数之一:[0,1,2]。与动作空间不同的是,观察空间是盒子,代表一个 n 维的盒子。然后,每个观察值将是一个范围在-28 和 28 之间的 6 个数字的数组。

4.随机代理

这是一个运行代理的例子,它只是随机选择一个动作。Acrobot 环境将运行 10 集,显示游戏每一步的视频。在运行代理之前,我们定义了可视化环境视频的函数。在 Google Colab 中启用健身房环境渲染需要这些函数。

最后,我们运行随机代理 10 个时间步:

这段代码总结了有限马尔可夫决策过程(MDP)的形式问题,这是一个强化学习问题的一般设置。我们知道有五个组件协同工作:

  • 代理是由两个关节和两个连杆组成的机械臂,两个连杆之间的关节被驱动
  • 环境对应于 Acrobot 环境
  • 状态由一组 6 个数字组成
  • 动作:有 3 种可能的动作
  • 每一步奖励 : -1

作者插图

根据萨顿和巴尔托在的《强化学习:导论一书中对 MDP 的主体-环境交互的定义,我们知道:

主体和环境在一系列离散的时间步长 t=0,1,2,3,…中的每一步都相互作用。在每个时间步骤 t,代理接收环境的状态的一些表示,并在此基础上选择动作。一个时间步骤之后,部分地作为其动作的结果,代理收到一个数字奖励,并发现自己处于一个新状态【3】。

因此,实现了代理-环境循环:在每一集里,我们得到:

  • 初始状态调用env.reset
  • 代理选择一个随机动作,它取值[0,1,2]中的一个
  • 通过 step 函数,应用随机动作并返回四个值:新状态、上一步获得的奖励、游戏结束时为真的标志完成以及用于调试的诊断信息****
  • 为下一次迭代设置当前状态

现在,我们调用函数 show_videos 来显示视频,每集一个:

show_videos()

5.实施深度 Q 网络

在这一节中,我将展示如何在 Acrobot 游戏上用 Pytorch 实现深度 Q 网络。该模型是一个神经网络,它将状态空间的维度作为输入,并返回对应于每个可能动作的最佳 q 值。因为有三种可能的动作来移动机械臂,所以返回的输出数是 3。

6.体验回放

一旦我们定义了网络,我们就可以创建一个名为 ReplayMemory 的类。当观察序列中存在相关性时,神经网络可能不稳定或发散。出于这个原因,我们还需要体验回放,它使代理能够记住过去的体验并从中学习。此外,它使数据随机化,从而提供不相关的数据。

为了执行体验重放,我们将代理在每个时间步长 t 的体验 e_t=(状态,动作,下一个状态,奖励)存储在数据集 D_t={e_1,…,e_t}中。在学习过程中,我们应用 Q 学习更新,对经验(s,a,r,s')~U(D)的样本(或小批量)进行更新,这些样本是从存储的样本池中均匀随机抽取的[4]。

在实践中,我们需要一个具有预定义容量的队列。当我们达到最大容量时,队列中最旧的元素将被新的元素替换。使用 python 集合库中的 deque 对象可以实现这种行为。

最大容量是ReplayMemory对象请求的唯一输入。这样,我们用 maxlen capacity 定义了一个等同于 deque 对象的内存属性。

我们还定义了 push 函数,将新的体验添加到重放存储器中。

sample方法被定义为从记忆中采样经验。体验次数等于 batch_size。如果请求的批量大于内存中当前的样本数,我们将获取所有样本。

7.ε贪婪策略

在执行体验重放之后,下一步是根据ε-greedy 策略选择并执行一个动作。该策略选择一个概率为ε的随机行动,否则,选择对应于最高 Q 值的最佳行动。主要思想是代理在开始时探索环境而不是利用它。代理从环境中学习得越多,它就越会选择基于开发的最优行动。

8.Softmax 策略

在给定温度参数的情况下,Softmax 策略用于基于通过将 softmax 应用于估计的 Q 值而获得的分布来选择最佳动作。有两种可能的情况:

  • 温度越高,分布就越趋于随机均匀分布。
  • 在零度时,策略将总是选择具有最高 Q 值的动作。

9.勘探剖面

我们使用 softmax 策略定义了一个指数递减的勘探配置文件:

soft max _ temperature = initial _ temperature * exponential_decay^(i)

10.培养

我们可以初始化超参数,如 SGD 优化器和 Huber 损失函数、ReplayMemory 对象、策略网络和目标网络。

函数 update_step 被定义为执行单个优化步骤。首先,它从重放存储器中抽取一批样本。之后,它为批中的每个元素创建张量。它还计算非最终状态的掩码,并连接批处理元素。

随后,它计算给定实际状态的策略网络的所有 Q 值。与策略网络不同,价值函数是基于使用目标网络的下一个状态来计算的。

最后,我们可以基于策略网络的 Q 值和使用目标网络计算的 Q 值的最大值来获得预期的 Q 值。

现在,是时候训练深度 Q 学习代理了,运行 800 集。在 for 循环中,我们只需要调用前面定义的所有函数。我们还会每 100 集放一次视频。

最后几集的结果

第 100 集视频

最后一集的视频

从上一集的视频中,我们可以注意到代理学会了解决任务。很明显,如果你也看了 100 集之后的视频,代理人还在探索最佳行动。训练结束后,我们还可以显示每集获得的累积分值:

开始时,累积奖励保持在-500。在 200 集之后,分数呈指数增长,保持在-100 左右。最后一步是测试代理是否真的学会了解决它的任务。类似于之前实现的随机代理。我们选择温度参数设置为 0 的最佳操作,而不是采取随机操作。这样,softmax 策略将总是选择具有最高 Q 值的动作。

我们可以观察到,在最终的测试结果中,累积奖励分数仍然很小。

最终想法:

在本教程中,我提供了使用 Pytorch 构建深度 Q 网络的概述。为了更好地理解它,更好的方法是将代码分成构建块,每次只关注一个块。起初,如果你以前只尝试过监督和非监督技术,这似乎很难。但经过一些努力,你将能够理解它,甚至将深度 q 网络应用到其他环境中。这里的 GitHub 代码是。

参考资料:

[1]https://gym.openai.com/docs/

[2]py torch 的强化学习(DQN)教程

[3] 萨顿&巴尔托著,《强化学习:导论》(2018)。

https://www.nature.com/articles/nature14236

你喜欢我的文章吗? 成为会员 每天无限获取数据科学新帖!这是一种间接的支持我的方式,不会给你带来任何额外的费用。如果您已经是会员, 订阅 每当我发布新的数据科学和 python 指南时,您都会收到电子邮件!

AGV 路径的深度强化学习

原文:https://towardsdatascience.com/deep-reinforcement-learning-for-agv-routing-a9b9fe055304?source=collection_archive---------26-----------------------

通过对自动导引车路线安排使用强化学习来提高仓库生产率

带有 8 个工作站的 AGV 设置示例—(图片由作者提供)

在一个配送中心(DC),在拣货路线上从一个地点走到另一个地点可以占操作员工作时间的 60%到 70% 。减少步行时间是提高整体生产力的最有效方法。

在以前的一系列文章中,我已经分享了几种使用优化策略来减少仓库中操作员行走距离的方法。( 链接 )

当你有一个大的提货区时,这些方法有局限性。因此,使用自动导向车将货架直接送到操作人员手中的自动化解决方案现在非常流行。

本文将解释如何使用强化学习来组织这些机器人的路线,以确保最佳生产率。

💌新文章直接免费放入你的收件箱:时事通讯

一.从人对货物到货物对人

电子商务公司最早采用了这种从人工操作——人对商品——到商品对人的转变。

因为他们的业务量波动很大(促销、节日),参考范围很广,而且劳动力资源短缺:自动化对他们来说是必须的。

使用自动引导车进行货物到人的拣选

“货物到人”提货解决方案可在提货站将货物直接交付给您的操作员。您消除了操作员搜索商品所需的所有非增值时间。

车辆上的货架示例—(图片由作者提供)

货物储存在货架上,可以由这些车辆直接移动到提货站,在那里操作员将获得所需的数量来准备订单。

Pickstation 示例—(图片由作者提供)

AGV 安装布局

AGV 设置示例—(图片由作者提供)

在这个布局中,你有

  • 8 个拾取站两个一组,每个站 1 名操作员
  • 16(8×2)条货架大巷
  • 1 个车辆充电站

二。构建您的优化模型

创建 AGV 布局的拓扑图

Djisktra 图表示例—(图片由作者提供)

我们的布局由图 G(N;e)

  • n 是节点的集合(上面的圆圈)
  • e 是边的集合(实线和箭头)
  • s 代表货架(实心灰色节点表示存放货架的位置)
  • r 代表 AGV 旋转货架的点
  • w 代表等待点,带货架的 AGV 在此等待之前到达提货站的 AGV 完成提货活动
  • p 代表提货点,提货人将在此提货

这种映射将包含在一个 AGV 拣选模拟模型中,该模型将用于测试我们的路径选择策略。

使用 Djisktra 算法的路径查找

Dijkstra 算法是一种优化算法,解决带权边(非负权)的有向图的单源最短路径问题。

Djisktra 图表示例—(图片由作者提供)

该长度可以是路径的绝对长度,也可以考虑位于边或节点上的其他约束来计算。

我们可以使用三种类型的权重,从节点 u 到节点 v 标注为 w(u,v)

  • 最短距离路线权重: w(u,v) = d(u,v) (1)
    用 d(u,v)表示 u 和 v 之间的距离
    -
    目标:取距离最短的路线
  • 最短行驶时间: w(u,v) = d(u,v)/s(u,v) + r(u,v) (2)
    用 s(u,v)表示 AGV 平移速度和 r(u,v)表示所有旋转所需的时间 - 目标:选择行驶时间最短的路线
  • 拥塞避免: w(u,v) = d(u,v)/s(u,v) + r(u,v) + Co(u,v) (3)
    with o(u,v)*AGV 计划通过边缘的数量,C 为调整权重的定值
    • 目标:选择与其他 AGV 避免拥塞的路线*

强化学习方法

在时间 t,我们通过下式定义仓库的状态:

  • 所有活动车辆的空间位置(分配了路线的 AGV)**
  • 所有活动货架的空间位置(有待拣选商品的货架)**
  • 工作站订单行分配(需要转移物料的工作站)

这些参数会随时间变化,因此让我们使用强化学习方法根据这种状态从这些候选中选择最佳路线。

代理回报策略

使用三种不同的奖励值方法来奖励您的学习代理到达目的节点

  • 生产率:从 AGV 从起点出发到到达目的地这段时间内,每个工时拣选的物品数量。
  • 空闲时间:在用 AGV 从货架上拣货后,拣货员等待下一辆 AGV 的时间。
  • 速度:AGV 从起点到终点的平均速度

流程—(图片由作者提供)

三。模拟

关注我的 medium,了解更多与供应链数据科学相关的见解。

场景

第一次模拟是基于三天的挑选:第一天用于训练;测试的第 2 天和第 3 天。

模拟的第一个场景—(图片由作者提供)

RL 模型的结果将与两种简单的路线规划
策略进行比较

  • 随机:在最短距离路线、最短行驶时间路线和拥堵避免路线中随机选择一条路线
  • 拥塞:始终选择拥塞避免路线

结果

每种策略的结果—(图片由作者提供)

令人惊讶的是,生产率奖励的效果不如速度奖励。试图最大化每个 AGV 的生产率可能不是车辆之间协作工作以确保高全球生产率的最佳方法。

当拥塞是主要瓶颈时(即,当您有高密度的车辆同时运行时),拥塞策略表现良好,同时与 RL 方法相比需要较少的计算资源。

后续步骤

这些结果基于只有两天提货活动的特定布局。为了更好地理解这种方法,我将在下一篇文章中解释如何构建 AGV 拣选模拟器并实现路由策略。

应该在各种订单配置文件上测试该模型,以测试通过调整对生产率的影响

  • 每份订单的行数(每份订单的移动次数)
  • 每行领料的单位数量
  • 活动 SKU 的范围

如果你在 SKU 的某个特定群体、购物节(黑色星期五,11.11)或淡季有促销活动,策略的选择可能会有所不同。

超出

对于更传统的拣货流程,您可以找到使用高级分析工具和流程分析概念进行流程优化的示例。

*https://www.samirsaci.com/supply-chain-process-design-using-the-queueing-theory/ https://www.samirsaci.com/improve-warehouse-productivity-using-order-batching-with-python/ https://www.samirsaci.com/optimize-workforce-planning-using-linear-programming-with-python/

关于我

让我们连接上 LinkedinTwitter ,我是一名供应链工程师,正在使用数据分析来改善物流运营和降低成本。

如果你对数据分析和供应链感兴趣,可以看看我的网站

https://samirsaci.com

参考

[1]使用深度强化学习的自动导引车辆路线规划策略的获取,IEEE 高级物流与运输国际会议(ICALT 2017)

[2]一种面向制造业多 AGV 调度的强化学习方法,,薛,彭增,
实验室。沈阳自动化研究所网络控制系统

[3]使用深度强化学习在线优化 AGV 运输系统,网络、计算、系统和软件通报,Kei Takahashi,Sogabe Tomah*

深度强化学习:从萨莎到 DDPG 及其他

原文:https://towardsdatascience.com/deep-reinforcement-learning-from-sarsa-to-ddpg-and-beyond-458100c2fda8?source=collection_archive---------12-----------------------

思想和理论

抓住使 RL 成功的基本要素

让机器学习的能力是过去几十年的一项令人着迷的成就。许多新的商业机会已经开放,公司每天都在使用机器学习。

就在几年前,DeepMind 的 AlphaGo 算法打败了围棋世界冠军 Lee Sedol。这一惊人的壮举是在强化学习的帮助下实现的,但无疑不是一夜之间实现的。这个雄心勃勃的项目的研究始于 21 世纪初。从那以后,这个领域本身已经有了很大的发展。本文旨在涵盖向现代方法转变的一部分。

基础

在我们开始之前,我们必须缩小强化学习的含义:强化学习的目标是尽可能好地行动。这个定义是的简化版本

目标是找到一个使预期收益最大化的政策。

为了实现这一点,我们有几个组件协同工作,如图所示:

强化学习的循环。图片由作者提供,来自一个封闭的大学讲座的例子。

代理与环境交互,环境改变它的状态,并为动作产生奖励。然后,又一轮开始了。在数学上,这个周期是基于马尔可夫决策过程(MDP)。这种市场发展计划包括五个组成部分:南非、阿尔及利亚、菲律宾和 p₀.

s 是状态空间,它包含环境可能处于的所有可能状态 s 。例如,如果我们要为一辆汽车建模,它可能有以下状态:前进、后退、转弯、刹车等等。

第二个组件 A 是动作空间,它定义了代理可以执行的所有动作 a 。对于汽车设定,这可能是转动方向盘,加速,刹车。这样的行动导致了新的国家。

第三个分量 R 是奖励函数。该功能负责根据代理的动作和结果状态对其进行奖励。例如,如果汽车成功地在交通灯前停下来,代理人会得到一个积极的奖励。然而,如果它没有停止,代理人会得到一个负的奖励。

第四个分量 P 是转移概率函数。通常情况下,一个动作并不能保证会达到期望的状态。因此,该属性被建模为概率函数。例如,它可能会说:“有 90%的可能性,我们会到达理想的状态,但有 10%,可能会发生不同的事情。”

最后,我们有 p₀,它是一组初始状态。每当一个代理被训练,它开始在这些状态之一。

现在我们已经介绍了 RL 设置的要素,我们如何教代理学习期望的行为呢?这是在π策略的帮助下完成的,我之前简单地提到过。形式上,策略从状态空间 S 映射到所有可能动作的概率。听起来很复杂?考虑一下:你站在路边,想要过马路。这种情况就是你的起始状态。一个策略现在将列出所有可能的动作:向左看、向右看、直线向前跑、等待等等。所有这些选择都有被选中的概率。例如,你可能有 20%的机会选择向左看,有 50%的机会,你可能选择跑。

随着代理被训练,它优化策略。一开始,π可能会经常选择跑过街道。然而,由于代理人多次被车撞,他获得了许多负面奖励,这是他不想要的。随着时间的推移,代理人学会做得更好,导致越来越多的积极回报。最终,这将导致找到一个最大化总回报的政策。

但是,我们怎么知道我们现在的状态是好的呢?对于我们可以采取的行动,我们可能会问:我们如何知道它们是好的?这种评估借助于价值函数来实现。我们有两个,一个是国家的,一个是行动的。

第一个函数称为状态值函数,缩写为 v。对于每个状态,它“知道”这个状态有多好。状态的好与坏是由我们在这种状态下开始时期望得到的回报决定的。比如赛车中的杆位更容易赢得比赛;这位司机获得了积极的奖励。这一事实影响了杆位的价值:随着越来越多的人从这里开始并赢得比赛,从这种状态中获得的积极奖励的数量也在增加。反过来,极点位置的值增加。

第二个函数是动作值函数,缩写为 q。对于我们在给定状态下可以做的所有动作,它“知道”它们有多好。这个知识的获得与上面类似:导致好的回报的行为比导致负面回报的行为有更高的价值。

萨尔萨

现在我们已经讨论了基础知识,我们可以检查一个经典的 RL 算法,称为 SARSA [1]。这个名字是州行动奖励州行动的缩写,它巧妙地抓住了功能。

首先,我们从一个状态(S)开始,采取行动(A),得到回报(R)。现在我们处于后继状态,并选择另一个动作(A)。我们这样做是为了更新我们的 Q 函数。如前所述,行动的价值是当我们从一个状态开始并选择这个行动时,我们期望的总回报。同样的属性适用于下一个状态、下一个状态和下一个下一个状态。我们可以用动作值函数的更新规则来表达这一点:

Q(s,a) ← Q(s,a) + α(r + γ Q(s ',a') — Q(s,a))

上面写了什么?我们的状态-动作对的新值是旧值加上,这是括号中的部分,与我们从这里得到的不同:r + γ Q(s ',a ')。所以随着时间的推移,我们的 Q 函数越来越接近我们得到的回报,这是由这个更新规则模拟的。

现在我们有了 Q 函数(或者有时称为 Q 值),我们能用它做什么呢?首先,这些值存储在一个表中。每当我们的策略必须选择一个操作时,它会检查它处于哪个状态,然后查看所有可能的操作:

从所有这些动作中,选择具有最高值的动作。这个动作导致了一个新的状态,在这个状态中,再次选择了最有价值的动作。在训练期间,Q 值按照先前引入的更新规则进行更新。一旦完成,我们就找到了一个合适的好策略,并准备在我们的环境中使用代理。

但是至少有一点我们可以改进算法。这就是 Q-Learning 发挥作用的地方。

q 学习

Q 学习算法[2,3]可以概括为非策略 SARSA。为了解释这一点,让我们再来看看 SARSA 的更新规则:

Q(s,a) ← Q(s,a) + α(r + γ Q(s ',a') — Q(s,a))

我们的策略π选择一个初始动作,这是 Q(s,a)部分。然后,我们使用相同的策略来选择后续动作,也就是说 Q(s ',a ')的部分。使用相同策略来确定两个动作的过程由关键字 on-policy 表示。代理基于当前使用的策略所选择的动作来学习 Q 值。

相比之下,在非策略算法中,我们有不止一个策略。这可以从 Q-learning 的更新规则中看出:

Q(s,a) ← Q(s,a) + α(r + γ maxₐ' (s ',a') — Q(s,a))

关键的区别是选择最佳后续行动,这是而不是遵循政策完成的。相反,我们总是选择具有最高 Q 值的动作。这个选择过程可以理解为另一个用于确定后续行动的策略。好处是我们可以遵循不同的策略来选择后续操作。这看起来没什么大不了的,但是在 Q-learning 中,我们总是利用这个事实来选择一个最优的后续行动。

此外,它允许我们很容易地加入额外的影响。例如,考虑我们可能拥有的第二个代理。这个代理有一个独特的功能,我们希望我们的主要代理也能学习它。我们采用二级代理的策略,并在我们选择新的后续动作时使用它。

到目前为止,我们不需要任何神经网络。但是表格方法不适合大的状态和动作空间:首先,它们的内存消耗很大。其次,我们甚至可能不会在训练过程中访问所有的状态或动作,所以有些条目可能没有初始化。第三,查找时间过长。然而,作为第一个措施,我们可以使用神经网络来代替 Q 表。

深度 Q 学习

神经网络已经被证明具有良好的泛化能力。我们也可以利用它们从数据中学习特征的能力来进行强化学习。在深度强化学习中,我们用神经网络来逼近我们的函数,比如 Q[4]。为了突出这种修改,Q 或 V 函数通常标有θ: Q_θ和 V_θ。除了神经网络之外,还有其他方法,但这些不是本文的范围。

在默认的 Q 学习中,更新规则帮助我们找到最优的 Q 值。最优意味着它们会带来最高的回报;我们可以用它们来选择最佳行动(在给定状态下具有最高 Q 值的行动)。并且,通过使用神经网络,我们直接逼近这个最佳 Q 或 V 函数。我们从少量的训练数据中学习,然后可以推广到新的情况。

在深度 Q 学习算法中,我们使用两种技术,称为经验重放目标网络

第一个修改将旧的转换(通过选择一个动作从一个状态转移到下一个状态)存储在重放缓冲区中。在训练期间,我们从这个缓冲区取样。这项技术提高了效率,并使数据分布更加稳定。这是怎么回事?现在,想想如果我们有几个动作,并且在每个训练步骤中,我们选择不同的一个,会发生什么。我们总是在各种可能性之间跳跃。有了重放缓冲区,我们可以检测分布中的趋势,使动作的选择更加稳定。

第二个修改,目标网络,用于计算我们的目标。一般来说,我们的目标是最大化预期报酬。问题是,我们如何知道我们的奖励是否已经是最好的了?目标网络帮助我们解决这个问题。我们使用旧更新步骤中的网络,并将其 Q 值作为目标。这听起来可能很难,因此我们来看看目标网络的更新规则:

Q_θ(s,a) ← Q_θ(s,a) + α((r + γ maxₐ' Qₜₐᵣ(s',a′))—q _θ(s,a))

不同之处在于更新目标的计算。通过最小化我们的当前值 Q_θ(s,a)和 Qₜₐᵣ(s',a’)之间的差,我们接近目标,这里缩写为“tar”。而这个目标就是目标网络的价值。

现在,如果我们不使用这样的目标网络,而只使用当前网络 Q_θ,我们的目标将不断变化:随着网络参数的每次更新,我们将得到不同的 Q 值。这就是为什么我们使用旧网络(意味着在我们当前网络之前的一些更新步骤)作为固定目标。它的参数更新得更慢,使目标更稳定。最终,我们降低了我们的主网络可能会被自己的尾巴所困扰的风险。

换句话说,想想跑步比赛。每当你接近终点线时,它就会后退。这样,你永远不知道你离目标有多近。

这两个提出的修改,使用一个重放缓冲器和目标网络,被用来帮助 RL 代理玩 Atari 游戏,有时甚至在超人的水平[5]。

深度确定性政策梯度

到目前为止,我们只考虑了离散动作空间。在离散的动作空间中,我们有固定数量的动作,只有一个单一的粒度级别。相比之下,想想门和墙之间的角度。如果我们只有,比方说,两个位置,我们有一个离散的空间。但是我们可以把门放在任意的位置:全开、全关、45 度、30 度、30.1 度、30.01 度等等。这个空间是连续的,用表格方法和深度 Q 学习方法都难以覆盖。

连续动作的问题是到目前为止我们对 Q 函数的更新步骤:

Q_θ(s,a) ← Q_θ(s,a) + α((r + γ maxₐ' Qₜₐᵣ(s',a′))—q _θ(s,a))

上面写着 maxₐ' Qₜₐᵣ(s'的那一部分才是问题所在。在离散的行动空间中,很容易找到导致最高回报的行动。然而,在具有任意细粒度动作的连续动作空间中,这是非常昂贵的,如果不是不可能的话。

一个简单的解决方案是将空间离散化。但是,挑战在于如何离散化。然而,我们可以完全跳过这个问题,修改深度 Q 学习算法以支持连续动作。这导致了深度确定性策略梯度(DDPG)算法[6,7],它本质上是针对连续动作的深度 Q 学习。它也使用重放缓冲区和目标网络,但采用最大运算。

我们引入另一个神经网络,而不是“手动”执行对最佳状态-动作对(最佳 Q 值)的搜索。这个神经网络学习逼近最大化器。然后,每次我们用一个状态查询它,它都返回最佳的对应动作——这正是我们需要的。

取代最大化器的新网络然后被用于目标的计算。因此,前面的等式可以改写为

Q_θ(s,a) ← Q_θ(s,a) + α((r + γ Qₜₐᵣ(s',μₜₐᵣ(s'))—q _θ(s,a))

正如我提到的,我们使用网络,μₜₐᵣ,来决定最佳行动。和以前一样,我们使用稍微旧一点的网络版本,因此有“tar”部分。即使μₜₐᵣ和 Qₜₐᵣ每一步都被更新,它们也永远不会被更新到最新的参数。相反,他们通常保留 90%的参数值,剩下的 10%来自当前网络。这样,目标网络既不会太旧,也不会太新。

双延迟 DDPG 算法[8]引入了三种改进,以提高默认版本的性能。首先,TD3,也是缩写,学习两个 Q 函数并使用较小的值来构建目标。此外,策略(负责选择初始动作)更新不太频繁,并且添加噪声以平滑 Q 函数。

熵正则化强化学习

所有算法面临的挑战是过早收敛。这种不受欢迎的行为是探索不足的结果。例如,如果代理已经确定了一个好的动作序列,他可能会关注这些特定的动作。在这个过程中,他没有探索其他州,而这些州可能会给他带来更好的回报。这种现象也被称为探索与开发的权衡:探索旨在探索动作和状态空间,而开发则寻求开发已经探索过的区域。

熵正则化强化学习方法是应对这一挑战的一种方式:我们训练策略来最大化如上所述的权衡。为了做到这一点,我们使用一个叫做熵的概念。简而言之,熵给出了关于分布“混沌”的信息。混沌程度越高(“分布越不均匀”),熵值越低。因此,所有值都有相同的机会被抽取的均匀概率产生最大熵值。

我们利用这个事实,在我们的价值函数中加入一个熵项。详细解释它们超出了本文的范围,但要点如下:附加术语强制执行策略,以在高回报(探索)和从各种行动中选择(探索)之间保持平衡。

在软演员-评论家算法[9,10]中,这个概念尤其用于训练机器人行走。虽然机器人只在平坦的地形上训练,但由此产生的策略足以应对训练期间看不到的环境。

强化学习库

上面所有的算法都已经在各种 python 包中实现了。OpenAI GymSafety Gym 框架提供了构建代理培训环境的代码。来自 DeepMind 的研究人员提供了控制套件包,用于基于物理的 RL 模拟。

要构建算法,可以从各种选项中进行选择。稳定基线 3 库是在 PyTorch 中实现的,它提供了比较算法和创建新算法的工具。类似地,ACME 库提供了 RL 代理和构建块,并且足够灵活,可以进行自己的研究。作为第三种选择,你可以考虑谷歌的多巴胺框架,它专注于投机性研究的快速原型制作。它支持 JAX 和张量流。

摘要

在过去的几十年里,强化学习领域经历了许多批判性的观点。该基金会是基于学习功能的理念建立的,这种学习功能可以量化处于特定情况下的优势。研究人员随后提议使用不同的政策来有效地探索环境。当在神经网络的帮助下学习函数时,向前迈出了重要的一步,这引入了算法设计的许多新的可能性。随着时间的推移,其他想法被纳入其中,如逐步更新作为训练目标的其他网络。然而,开发并没有完成。仍然有许多挑战需要克服,例如处理约束,弥合训练和现实生活环境之间的差距,或者可解释性。

文学

[1] Gavin Rummery 和 Mahesan Niranjan,使用连接主义系统的在线 Q-learning,1994 年,Citeseer

[2] C.J.C.H .沃特金斯,从延迟回报中学习,博士论文,1989 年,剑桥大学国王学院

[3] C.J.C.H .沃特金斯和彼得·达扬, Q-learning ,1992,机器学习 8

[4] Kurt Hornik,多层前馈网络的逼近能力,1991,神经网络 4

[5] Mnih 等人,用深度强化学习玩雅达利,2013,arXiv

[6] Silver 等人,确定性策略梯度算法,2014,机器学习国际会议

[7] Lillicrap 等,深度强化学习的连续控制,2015,arXiv

[8] Stephen Dankwa 和 Wenfeng Zheng,双延迟:一种深度强化学习技术,用于模拟智能机器人智能体的连续运动,2019,ACM

[9]哈尔诺贾等,软行动者-批评家:带随机行动者的离策最大熵深度强化学习,2018,ICML

[10]哈尔诺贾等,软演员-评论家算法与应用,2018,arXiv

[11]哈尔诺贾等,通过深度强化学习学习走路,2018,arXiv

优化广告投放的深度强化学习实践

原文:https://towardsdatascience.com/deep-reinforcement-learning-hands-on-for-optimized-ad-placement-b402ffa47245?source=collection_archive---------18-----------------------

本文使用深度强化技术来优化网站上的广告投放,以最大化用户点击概率并增加数字营销收入。提供了一个详细的案例研究和代码,以帮助用户在任何现实世界的例子中实现该解决方案。

联盟营销和点击付费是数字营销的两个重要方面。这些技术的优化实施可以极大地增加公司的产品/服务销售额,也可以为营销人员带来巨大的收入。随着深度强化学习的进展,数字营销是受益最大的领域之一。

传统的微调数字营销活动的方法需要大量的历史数据。这既耗费时间又耗费资源。通过强化学习,可以节省时间和资源,因为它们不需要任何历史数据或活动的先验信息。在这篇文章中,我们可以看到一个简单的深度 RL 技术如何优化一个相当复杂的数字营销活动,并取得几乎完美的结果。

在本文中,通过一个接近真实的案例研究,让我们看看强化学习如何帮助我们管理广告投放,以获得最大的利益。

问题陈述

我们管理着 10 个电子商务网站,每个网站都专注于销售不同类别的商品,如电脑、珠宝、巧克力等。我们的目标是通过将在我们的一个网站购物的顾客推荐到他们可能感兴趣的另一个网站来增加产品的销售。当客户查看我们的一个网站时,我们会显示另一个网站的广告,希望他们也会购买其他产品。我们的问题是,我们不知道客户应该被推荐到哪个网站,或者我们没有客户偏好的任何信息。

让我们用强化学习来解决问题吧!!

图 1:RL 背后的基本概念示意图

一般来说,强化学习是一种技术,在这种技术中,我们训练一个代理在一个环境中操作。代理人在状态“s”采取行动“a ”,并从环境收到行动的奖励“r”。所以(s,a,r)成为一个状态-动作-回报元组。我们培训的目标是使代理获得的总回报最大化。因此,我们找到了(s,a,r)元组,它对于给定的状态和动作具有最大的回报。为了找到优化的元组,我们运行了许多集,每次都重新计算奖励。

在这个广告投放问题中,我们需要测试不同的行为,并自动学习给定情况、状态或背景下最有益的结果。所以我们称之为语境强盗框架,其中状态成为语境信息,代理为当前语境找到最佳行动。

比方说,我们有 10 个网站要管理,它们构成了 10 个不同的州,客户在其中一个网站上。因为我们有 10 种不同的产品类别,所以我们可以向客户展示这 10 种产品中的任何一种。所以每个州有 10 个不同的动作。这将导致 100 个不同的状态-动作-回报元组。我们需要存储 100 个不同的数据点,并在每次有新的奖励时重新计算。在这个例子中,这似乎是合理的。但是,如果我们有 1000 个网站要管理,这将产生 1000000 个数据点。存储和重新计算这将花费大量的时间和资源。

这意味着当状态和动作空间很大时(状态和动作的总数很大),强化学习会失败???

这就是深度强化学习的由来。我们使用神经网络来提取每个状态和动作的奖励值,而不是存储每个状态、动作和奖励元组。神经网络非常擅长学习抽象概念。他们学习数据中的模式和规律,并可以将大量信息作为权重压缩到他们的内存中。因此,神经网络可以学习状态——行动和奖励之间的复杂关系。

神经网络充当从环境中学习以最大化回报的代理。在本文中,我们将使用 PyTorch 构建一个神经网络,并训练它来优化广告投放,以获得最大回报。

让我们从编码开始吧!!

让我们首先为上下文强盗创建一个模拟环境。这个环境应该包括代表 10 个网站(0 到 9)的 10 个状态和产生广告点击奖励的方法,以及选择一个动作(显示 10 个广告中的哪一个)的方法

class ContextBandit:
    def __init__(self, arms=10):
        self.arms = arms
        self.init_distribution(arms)
        self.update_state()

    def init_distribution(self, arms):                  #**1**
        self.bandit_matrix = np.random.rand(arms,arms)

    def reward(self, prob):                             
        reward = 0
        for i in range(self.arms):
            if random.random() < prob:
                reward += 1
        return reward

    def get_state(self):                                
        return self.state

    def update_state(self):                             
        self.state = np.random.randint(0,self.arms)

    def get_reward(self,arm):
        return self.reward(self.bandit_matrix[self.get_state()][arm])

    def choose_arm(self, arm):                          #**2**
        reward = self.get_reward(arm)
        self.update_state()
        return reward

这是一个代表每个州的矩阵。行代表状态,列代表臂(动作)

选择一只手臂(动作)会返回奖励并更新状态

下面的代码显示了如何使用环境

env = ContextBandit(arms=10)
state = env.get_state()
reward = env.choose_arm(1)
print(state)
>>> 1
print(reward)
>>> 7

该环境由一个名为 ContextBandit 的类组成,该类可以通过 arm(动作)的数量进行初始化。在这个例子中,我们采取的状态数等于动作数。但这在现实生活中可能会有所不同。该类有一个函数 get_state(),调用它时会从均匀分布中返回一个随机状态。在现实生活的例子中,状态可以来自更复杂的或与业务相关的分布。用任何动作(arm)作为输入调用 choose_arm()将模拟投放广告。该方法返回对该动作的奖励,并使用新状态更新当前状态。我们需要一直调用 get_state()然后选择 _arm()不断获取新数据。

ContextualBandit 也有一些辅助功能,如一键编码器softmax。一键编码器函数返回一个 1 和全 0 的向量,其中 1 代表当前状态。Softmax 函数用于设置每个状态下各种动作的奖励分配。对于 n 个状态中的每一个,我们将有 n 个不同的 softmax 奖励分配。因此,我们需要了解状态和它们的动作分布之间的关系,并为给定的状态选择概率最高的动作。下面提到了这两个函数的代码

def one_hot(N, pos, val=1):  #N- number of actions , pos-state
    one_hot_vec = np.zeros(N)
    one_hot_vec[pos] = val
    return one_hot_vecdef softmax(av, tau=1.12):
    softm = np.exp(av / tau) / np.sum( np.exp(av / tau) ) 
    return softm

现在让我们创建一个具有 ReLU 激活的两层前馈神经网络作为代理。第一层将接受 10 个元素的一次性编码向量(状态向量),最后一层将输出 10 个元素向量,表示每个动作的奖励。

图 2:计算图表

从图 2 中,我们可以看到 get_state()函数返回一个随机状态值,该值使用一位热码编码器转换为 10 个元素的向量。该向量作为输入被馈送到神经网络。神经网络的输出是 10 个元素的向量,表示给定输入状态下每个动作的预测回报。输出是一个密集向量,使用 softmax 函数进一步转换为概率。基于概率,选择样本动作。一旦选择了动作,choose_arm()就会获得奖励,并使用环境中的新状态进行更新。

最初,对于状态 0,神经网络将产生类似于[1.4,50,4.3,0.31,0.43,11,121,90,8.9,1.1]的输出向量。在运行 softmax 并对动作进行采样后,最有可能的动作 6 将被选中(最高预测奖励)。选择动作 6 运行 choose_arm()后会产生奖励比如说 8。我们训练神经网络用[1.4,50,4.3,0.31,0.43,11,8,90,8.9,1.1]更新向量,因为 8 是实际的奖励。现在,下一次神经网络将预测,每当看到状态 0 时,行动 6 的奖励接近 8。当我们在许多状态和动作上不断训练我们模型时,神经网络将学习为各种状态-动作对预测更准确的回报

下面是创建神经网络和初始化环境的代码

arms = 10
N, D_in, H, D_out = 1, arms, 100, armsmodel = torch.nn.Sequential(
    torch.nn.Linear(D_in, H),
    torch.nn.ReLU(),
    torch.nn.Linear(H, D_out),
    torch.nn.ReLU(),
)
loss_fn = torch.nn.MSELoss()
env = ContextBandit(arms)

现在,让我们看看如何训练代理,并按照图 2 中说明的所有步骤进行操作

def train(env, epochs=5000, learning_rate=1e-2):
    cur_state = torch.Tensor(one_hot(arms,env.get_state()))      #1
    optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)
    rewards = []
    for i in range(epochs):
        y_pred = model(cur_state)                                #2
        av_softmax = softmax(y_pred.data.numpy(), tau=2.0)       #3
        av_softmax /= av_softmax.sum()                           #4
        choice = np.random.choice(arms, p=av_softmax)            #5
        cur_reward = env.choose_arm(choice)                      #6
        one_hot_reward = y_pred.data.numpy().copy()              #7
        one_hot_reward[choice] = cur_reward                      #8
        reward = torch.Tensor(one_hot_reward)
        rewards.append(cur_reward)
        loss = loss_fn(y_pred, reward)
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        cur_state = torch.Tensor(one_hot(arms,env.get_state()))  #9
    return np.array(rewards)
  • 1 获取环境的当前状态;转换为 PyTorch 变量
  • 2 向前运行神经网络以获得奖励预测
  • 3 用 softmax 将奖励预测转换成概率分布
  • 4 对分布进行规范化,以确保其总和为 1
  • 5 概率性地选择新动作
  • 6 采取行动,获得奖励
  • 7 将 PyTorch 张量数据转换为 Numpy 数组
  • 8 更新 one_hot_reward 数组作为标注的训练数据
  • 9更新当前环境状态

在对网络进行了大约 5000 个纪元的训练后,我们可以看到平均回报有所提高,如下所示

图 3:培训后的平均回报

我们可以看到平均奖励达到 8 或以上。

整个项目可以在这个 GIT 链接中找到。

本文基于布兰登·布朗和亚历山大·扎伊的《深度强化学习行动》一书。这本书的链接是这里

请在下面找到我关于各种数据科学主题的其他文章的链接

https://nandakishorej8.medium.com/multivariate-timeseries-forecast-with-lead-and-lag-timesteps-using-lstm-1a34915f08a https://nandakishorej8.medium.com/realtime-2d-yoga-pose-estimation-with-code-walk-through-cfd69262d356 https://nandakishorej8.medium.com/auto-tuning-multiple-timeseries-sarimax-model-with-a-case-study-and-detailed-code-explanation-c136293b8457 https://nandakishorej8.medium.com/introduction-to-pytorch-lightning-framework-for-enlightning-research-fe953bbea03b

非常欢迎反馈。你可以在 LinkedIn 上联系我

深度分裂 Q-learning 和 Pacman 女士

原文:https://towardsdatascience.com/deep-split-q-learning-and-ms-pacman-5749791d55c8?source=collection_archive---------21-----------------------

思想和理论

通过修改更新规则在深度 RL 环境中重新创建分裂 Q 学习的尝试

2013 年,谷歌 DeepMind 的一篇论文引发了深度强化学习(RL),特别是深度 Q 学习网络(DQN)的爆炸。2015 年,这是在基础上改进的,具有双重深度 Q 学习网络。这个网站和其他网站上有许多帖子详细介绍了如何构建一个在那篇论文中非常成功的网络版本;这篇文章是关于扩展这个框架到最近的一个想法:分裂 Q 学习。分裂 Q 学习已经在一些不同的环境中被提出,但是林等人的论文。2020 年自治主体和多主体系统国际会议(AAMAS)接受的人工智能是本文的重点。

在这里,我们将看看这种范式是什么,并尝试在《吃豆人 MDP》上实现它的深度 Q 学习网络,这是范·哈瑟尔特等人在 2015 年的论文中唯一表现不佳的游戏之一。艾尔。代码可以在这个链接上公开获得,它源于我在研究生院做的一个项目。

OpenAI Gym 的 MsPacman 环境的开始状态

背景

DeepMind 架构已经在很多地方解释过了,在健身房的突破环境的模型和教程可以在成为人类找到。我们的版本将使用 PyTorch vice TensorFlow,所以如果你没有看过他们的基本深度 Q-learning 教程你可能也想看看,我假设读者至少对 Q-learning 有点熟悉。

作为概述,2015 年的论文以 RGB Atari 图像作为游戏状态,以分数作为主要的奖励系统。最高分范·哈塞尔特等人。al 调优的双深度 Q-Learning 网络在 50M 训练迭代后,在特定的评测实验中能够达到 was 3210。

林等人提出的分裂 Q 学习。人工智能是一种将奖励分为积极和消极两种的想法。在正常的 Q 学习中,对模型或表的更新是基于预期奖励(Q 值)和实际奖励(奖励加上下一个状态中的最大 Q 值)之间的差异。如何应用这种差异可以有所不同,我们可以使用 L1,L2 类型的更新,但我们通常也会将学习率α应用于我们决定使用的任何更新。数学上,对于 Q 表、状态 s、行动 a、奖励 r 和新状态 s’,这看起来像:

这里,γ是预计未来回报的折现率。等式 1 是来自贝尔曼等式的 Q 值的定义,而等式 2 来自时间差分(TD)型训练。然后基于学习率α: Q(s,a) ← Q(s,a) + α*diff 更新 Q 表。在林等人提出的分裂 Q 学习中。al,有一个单独的奖励和惩罚表(或模型),它遵循的思想是,生物制剂倾向于用单独的而不一定是排他的机制来处理奖励和惩罚。除了分流,林等人。al 还建议改变如何通过两个超参数来更新 Q 值。其中一个,W,在每个状态转换时缩放奖励。另一个λ缩放更新前的旧 Q 值:

注意:方程式编号可能有问题

这两个表是奖励(+)和惩罚(-)的。深度 Q-learning 的这次更新特别困难的是,目标不仅仅是基于贝尔曼方程(方程 1),它是λ的目标的折扣版本,好像深度 Q-learning 在移动目标和收敛方面没有足够的问题!值得注意的是,αt(学习率)和γ(折扣)在正向和负向流之间共享。对于 Q 表的更新规则,林等。所有人都能够在代理人身上表现出与某些奖赏处理障碍的临床行为相匹配的紧急行为。最值得注意的是,他们的“慢性疼痛”模型将两个奖励超参数都设置为 0.5,显示出与实际慢性疼痛患者的临床行为相似的紧急行为。我最初的目标是用深度分裂 Q-learning 框架复制这种行为,并可能尝试改进 Hasselt et。al 基线,虽然这两个都还在工作。

预备:预处理、重放缓冲、深度 Q 学习

让深度 Q 学习网络(DQN)和双重深度 Q 学习网络(DDQN)收敛有几个重要的技巧,因此我们将详细介绍它们,以及它们是如何在这个项目的 PyTorch 代码库中实现的。第一个是我们的状态表示和重放缓冲区。MsPacmanDeterministic-v4(我们将使用的健身房环境)中的状态表示为大小为(3x210x160)的 RGB 图像,并且是 0–255 范围内的整数元素。

为了节省内存,我们将这些帧存储为向下采样的灰度图像,并将它们转换为 uint8 (8 位与 64 位相比,存储的 100000 多个帧有很大的不同)。根据 DeepMind 的论文,我们还希望包含最后几帧,以给当前图像一些上下文,并防止代理在每次帧更新时计算动作。这个预处理步骤被封装在下面的代码片段中:

.unsqueeze(0)是因为我们将把 4 个帧连接成一个状态供网络处理,所以一个图像的输出大小是(1x105x80),但是一个状态最终将是(1x4x105x80)。暂时忽略 self 参数,它最终将成为 DQN 包装类的一部分。

重放缓冲区只是一个存储大量 MDP 转换的对象。您可能还记得,MDP 转换采用一个状态-动作对,并返回新状态 s’和采取该动作的即时回报 r。在我们的实现中,我们将在更高的级别收集这些不同的元素,并将我们需要的所有内容的元组传递到缓冲区。这个缓冲区被实现为一个环形缓冲区,这意味着一旦我们超过了允许的最大元素数,它就开始覆盖它的元素。重放缓冲区的目的是能够从缓冲区中对成批的随机元素进行采样:这打破了状态之间的相关性,并允许我们使用深度神经网络来估计 Q 值。

实际的代理类需要用超参数(现在是 gamma,和某种探索/开发方案)初始化,初始化游戏状态,初始化模型,并运行下面的训练循环:

  1. 决定一项行动(勘探/开发)
  2. 采取行动,记录到重放缓冲区的转换
  3. 从重放缓冲区取样并训练策略网络

在本文中,我将抽象出 DQN 类(实际的火炬网络)的细节,因为它对于本次讨论并不重要。只要说它有三个卷积层、一个展平层和所有动作的估计 Q 值的输出就足够了。正如以上教程中所解释的,输出完整的 Q 值集并使用一键编码来处理反向传播和单动作选择会更快。

我将简要提及,由于 DeepMind 论文等论文中的一些结果,我们正在使用 Huber Loss(smoothl Loss)和 RMSprop 优化器进行训练,但当然还有其他选项(例如 MSE)。下面是我们的初始化和内务功能(环境、epsilon 缩放、超参数):

如果你对这个循环还不太熟悉,我建议你去读一读更深入的 Q-learning 或者深度 Q-learning 教程,比如上面提到的那些。第二项是大多数环境争论发生的地方。因为我们的状态代表四帧,所以我们需要聚集奖励,并在环境中的一些时间步长上连接处理过的图像。这是由下面的代码块完成的:

一个“动作”时间步由多个帧组成。生命['ale.lives']在下面进一步解释

然后,我们将一组 old_state, action, reward, new_state, is_done传递给重放缓冲区,并使用重放缓冲区的sample()方法拟合来自样本的模型。

我们需要讨论的最后一个初步主题是深度 Q 学习的训练方法。您可能已经注意到,在__init__()方法中,我们创建了两个 DQN 模型:一个策略模型和一个目标模型。您可能还记得,在 Q 表中,我们通过 Q(s,a)←Q(s,a) + αL(diff)来更新表。在一个模型中,我们不能更新;我们必须通过某种形式的梯度下降来更新模型的参数*。但是更新规则应该是什么,它转移到 split-Q 学习吗?一种方法是根据对 Q 表的时间差异更新来查看更新规则,并将其推广到深度 Q 学习框架。TD 本质上是上面的等式 2,其中 r+γmax(Q(s’,a’))项是损失函数的目标,而策略网络对 Q(s,a)的输出被调整:

范.哈瑟尔特等人的形式主义。阿尔,2015

这里θ’是目标网络,θ是策略网络。对于完整的训练循环,我们需要做的最后一件事是确定ϵ缩放和目标网络更新规则。这些最好从文献和做一些实验开始。MsPacman 上的典型 DQN 示例如下所示,其中τ(目标网络更新周期)和ϵ(勘探/开采政策)具有不同的超参数。

上图:慢速ϵ斜坡和 300 个时期的目标网络更新。Bot:快速ϵ斜坡与 500 个时代的目标网络更新。

完整训练循环的最后一个修改是增加了对失去一条生命(影响一个幽灵)的惩罚的能力,这不是内置在 MsPacman 健身房环境中的,但在 Lin et 中有很大的特点。艾尔关于分裂 Q 学习的论文。为了做到这一点,我们可以利用 gym 在 python 字典中输出剩余生命数的事实(lives = lives['ale.lives'])。我们现在可以建立一个完整的 Q 迭代:

深度 Q 学习网络的 Q 迭代。第 26 行允许我们修改撞击幽灵的惩罚

拥有一个total_reward和一个total_score变量的原因是,尽管它们在这个实现中做同样的事情,但是在分离 Q-learning 实现中它们是不同的。基本的训练循环是在指定数量的迭代或时期内保持运行这个 Q-学习函数,在达到终端状态的任何时候重置环境。fit_buffer()函数本质上实现了等式 7 和 8,但是我们将把它留给分裂 Q 学习实现。

深度分裂 Q 学习网络和双重深度 Q 学习

为了尝试将分裂 Q 学习方法移动到深度学习框架中,我们必须改变更新规则,以尝试匹配等式 4 和 5。从方程 5 开始,如果我们去掉学习率,我们得到一个有趣的方程,它成为贝尔曼对 Q(s,a)的定义,如果λ=1。暂且不考虑奖励权重,这看起来像是:

等式 10 本质上只是从等式 5 中移除α,但它对于 Lin 等人的 Q(s,a)的不同定义也有一定意义。艾尔的分裂 Q 学习范式。因为他们对历史进行贴现,所以新的 Q 值有两个目标:λQ(s,a)和 r + γmax(Q(s ',a ')。通过从通常的更新中减去 (1-λ)Q(s,a ),这些方程本质上是制定一个新的更新规则,该规则逐渐将 Q 值向两个目标移动。我们现在可以将 TD 逻辑应用于上述内容,并将其转移到深度 Q 学习范式,其中(λ-1)Q(s,a)项由目标网络计算,并添加到正常的 r + γ(π(s))项。右手边的 Q(s,a)项由策略网络计算,现在我们有损失函数的两个项:

换句话说,7–8 和 12–13 的唯一区别是等式 12 中的新项:(1-λ)Q(s,a;θ),它将目标移向贴现 Q 值。如果λ=1,这就简化为正常的 Q 更新规则。当我们加入即时奖励的权重时,完全分割 Q 学习算法是:

深度分裂 Q 学习算法,基于等式 10-13,L 代表损失函数

我们还可以实现一个版本的深度分裂 Q 学习,它遵循双重深度 Q 学习方法。双重深度 Q 学习和深度 Q 学习之间的区别在于,在计算未来折扣奖励时,策略网络用于选择行动,而目标网络用于评估这些行动。数学上,Y 的定义变成:

这是在等式 12 中用于分裂 Q 学习更新规则的一个相当容易的替代,我们将把这个想法用于fit_buffer()实现。这种两个流方法的“最佳动作”是两个流的 Q 值之和的最大可能动作。但是,在培训期间,我们仍然使用每个流来计算基于该流的最佳行为的未来折扣奖励。我们只对 Q 值求和,以实际选择给定状态下的最佳行动。下面是代码中初始化和最佳操作选择的样子:

最后要实现的是fit_buffer()函数,它处理模型的训练更新。该功能必须完成以下步骤:

  1. 将批处理解包为状态、动作、奖励、惩罚、下一个状态、完成
  2. 使用策略网络来选择下一个状态中的最佳行为,以进行奖励和惩罚
  3. 使用目标网络评估未来的贴现报酬,以及目标中(1-λ)Q(s,a)项的 Q(s,a)
  4. 计算策略网络对每个流的 Q 值的估计
  5. 计算每个流的损失和反向传播

下面是我对奖励流(惩罚流实现完全一样)的这个函数的实现。

如果不知道 DQN 是如何工作的,这个函数的一些细节可能很难理解,但它需要一个动作和状态输入的掩码,这就是为什么有很多一个热向量和一个向量飞来飞去。随意浏览项目,看看 DQN 类是如何工作的,以及 Q-learning 和双 Q-learning 的实现。

结果和结论

延伸林等人。al 从 Q 表到深度 Q 学习网络的分割 Q 学习不是一个简单的任务,但是我相信这代表了这样做的逻辑框架。目前,我必须提供的唯一评估是代理在用类似于 Lin et 的参数初始化时的行为。艾尔的作品。在这个实验中,我修改了流,在每个时间步长提供-1 的惩罚,在每次失去一个生命时提供-500 的惩罚。然后,我用. 5 初始化了一个代理,奖励权重 W 和过去的折扣λ(他们的慢性疼痛模型)。在林等人看来。艾尔的论文,这导致了一个代理人,不参与奖励寻求行为,但有能力避免鬼,如果他们太接近。避免 MsPacman 中的幽灵似乎是这些 CNN 风格的 Q 值估计网络的一个主要挑战(可能是因为幽灵倾向于在存在中闪现和消失),所以我们将比较双重深度 Q 学习网络和慢性疼痛(CP)代理。每个代理被训练 10,000 集,在 500,000 次迭代中 epsilon 从 1 到 0.1 渐变。

DQN 的代理人在下面,但还没有真正学会避开幽灵。相反,它的策略是吃下强力药丸,以防止鬼魂在游戏的开始阶段成为一个因素。

慢性疼痛剂训练了相同的时间,并开始表现出一些行为。艾尔观察到了,但仍偶尔从事寻求奖励的行为。可能 10,000 个训练集不足以使 Q 值收敛到 Lin et 的行为。艾尔在他们的模型中看到了,但令人鼓舞的是看到了冷漠和回避风险的开端!

参考

[1]柏寒·林、吉列尔莫·切奇、贾雷尔·布内夫、詹娜·赖宁和伊琳娜·里什。2020.两股潮流的故事:来自人类行为和神经精神病学的强化学习模型。arXiv:1906.11286 [cs。LG]

[2] Hado van Hasselt、Arthur Guez 和 David Silver。2015.采用双 Q 学习的深度强化学习。arXiv:1509.06461 [cs。LG]

[3] V. Mnih、K. Kavukcuoglu、D. Silver、A. A .鲁苏、J. Veness、M. G .贝勒马尔、A. Graves、M. Riedmiller、A. K. Fidjeland、G. Ostrovski、S. Petersen、C. Beattie、A. Sadik、I. Antonoglou、H. King、D. Kumaran、D. Wierstra、S. Legg 和 D. Hassabis。通过深度强化学习的人类水平控制。自然,518(7540):529–533,2015。

使用单调注意力的深度学习文本校正器(带有数据集创建)

原文:https://towardsdatascience.com/deep-text-corrector-using-monotonic-attention-with-dataset-creation-1e1a3f5a1b9e?source=collection_archive---------14-----------------------

深度学习模型从语法上纠正句子。使用单调注意的 Seq2Seq 模型。

图片演职员表

目录

  1. 简介
  2. 数据集创建
  3. 注意机制
  4. 单调注意
  5. 实现和代码演练
  6. 推理→波束搜索 v/s 贪婪搜索
  7. 结果和误差分析
  8. 端到端管道

介绍

序列对序列模型被证明是人工智能在自然语言处理领域的最佳应用之一。注意力机制通过模仿人类理解句子的方式这一简单概念,大大改进了 seq2seq 模型。

在这篇博客中,我建立了一个机器学习模型,它使用单音注意力纠正句子中的基本语法错误。

我的模型解决的一些扰动是——

  1. 纠正使用限定词(a,an,the)的错误。
  2. 删除从句——“that”。
  3. 替换单词 modal(“可能”→“将”)
  4. 删除动词形式(“is”、“are”、“was”、“was”)
  5. 将“than”替换为“then”,反之亦然。
  6. 用“他们”代替“他/她”。

为此案例研究创建数据集

为了这个项目,连同电影语料库数据集(康奈尔电影对话语料库),我从头开始创建了一个数据集。我用哈利波特小说作为我的原始资料。使用正则表达式完成了文本预处理。查看完数据中的差异后,这些是我进行的预处理步骤。其中一些是-

  1. 从 Mr 和 Mrs 中删除点号- 这一步是确保段落被正确分割成句子所必需的。(第 4 点)
xx_v2 = re.sub(r'Mr\.', 'Mr', str(xx), flags=re.IGNORECASE)xx_v2 = re.sub(r'Mrs\.', 'Mrs', xx_v2, flags=re.IGNORECASE)

2。删除一些特殊字符- 当这本书从 pdf 转换成 txt 时,一些特殊符号变成了文本代码,如—

\ xe2 \ X80 \ x94 →""
\ xe2 \ X80 \ x99→" ' "
\ xe2 \ X80 \ xa6→"…"

因此,使用正则表达式检测并删除了这些内容。

xx_v3 = re.sub(r"\\xe2\\x80\\x94|\\xe2\\x80\\xa6|\\xe2\\x80\\x98|\\n|\\t",  " ", xx_v2, flags=re.IGNORECASE)

3。 修复资料- 一部小说包含了大量不同人物所说的引用文字。在将 pdf 转换为文本时,它们也被转换为一些文本代码。然后这些被检测到并被替换为其原始形式,即
\ \ xe2 \ X80 \ x9c→"
\ \ xe2 \ X80 \ x9d→"

xx_v4 = re.sub(r"\\xe2\\x80\\x9c", '"', xx_v3, flags=re.IGNORECASE)xx_v4 = re.sub(r"\\xe2\\x80\\x9d", '"', xx_v4, flags=re.IGNORECASE)

4。在句号上拆分数据- 将数据转换成句子。

dat_v4 = xx_v4.split(".")

5。最后一步——提取句子

→在一部小说中,有很多这样的例子,当一个角色说了一些写在引用的文本中的话,然后是这句话“这个角色说的”。
例如→“我要走了”哈利说。这种类型的句子需要删除,因为它们是半句。

因此,我们通过识别诸如“说”、“小声说”、“问”等词来删除这些半句***

→最后,同样在这之后,有些句子是疑问句。所以,我们再次用分割。拆分("?)但是保留问号,以确保我们的模型理解肯定句和疑问句之间的区别。

*** * 注意-同样,如果报价中有完整的句子,它们在步骤 4 中已经被正确拆分。*

我们也对电影语料库数据集进行类似的预处理。

注意机制概述

注意:假设读者精通注意力,我将只给出注意力机制的概述。如果你是新关注者,请阅读 这篇 的博客。

概观

“注意力”这个名字本身给了我们这个算法做什么的想法。在普通的编码器-解码器模型中,编码器的所有中间状态都被丢弃,最终状态被用作解码器的初始状态。背后的想法很简单-最终状态包含输入句子的所有信息,解码器可以使用这些信息来预测输出。但是,当序列很长时,这个模型很难将所有信息编码到一个向量中。

而在注意机制中,我们试图模仿人类处理顺序信息的方式。我们通过给每个单词(编码器中间状态)加权来做到这一点,从而给予注意特定预测的特定单词。这是通过前馈神经网络实现的,该网络将编码器的所有中间状态以及先前的解码器状态作为输入,并给出该时间戳的每个字的权重。

单调注意

注意,在每个时间戳,我们计算所有单词的权重,以确保我们不排除 say- 第一个单词影响第三个单词的预测或者 say 最后一个单词影响第一个预测的可能性。换句话说,注意力独立地考虑所有的中间状态,因此,时间戳的输出可以依赖于任何输入单词(意味着任何单词可以具有更大的权重)

该图描述了注意力模型

注意机制权重图

输出可以根据任何字对其进行预测


也就是说,一旦输入序列元素在给定的输出时间步被关注,在它之前出现的元素就不能在随后的输出时间步被关注。

单调注意力权重图

从图中我们可以清楚地看到,第一个输出依赖于第一个字,因此第二个输出不能使用第一个字,而是使用第二和第三个字进行预测。它严格地从左向右进行。

在单调注意中,只有以前的输出没有使用过的词才能对现在的输出产生影响,并且严格地从左到右

这使得模型变得不那么复杂,并且在这个案例研究中对我特别有帮助,它的表现远远好于注意力。

实现和代码演练

让我们在数据集上实现单调注意,并创建一个文本校正器模型。

我们将从数据集的基本预处理开始

文本预处理

现在是时候添加一些扰动了

使用教师强制*为编码器-解码器创建输入-输出对。

教师强制是一种方法,其中我们显式地将输入给解码器,而不是将解码器的输出传递给下一个时间戳。这显然只在训练时使用,有助于减少训练时间和提高准确性。

dataframe['decoder_input'] = '<start> ' + dataframe['output'].astype(str)dataframe['decoder_output'] = dataframe['output'].astype(str) + ' <end>'dataframe = dataframe.drop(['output'], axis=1)

举例-

编码器输入缺少“a”

之后,我们将数据集分为训练、验证和测试。

然后我们对数据进行标记化,将单词转换成整数标记来训练模型。

预训练向量的嵌入矩阵-

在对数据进行标记化之后,我们使用 GLOVE-300 预训练向量为我们的正确 _ 标记和扰动 _ 标记创建包含我们的单词的预训练嵌入向量的嵌入 _ 矩阵。

正确标记的嵌入矩阵

实现我们的深度文本校正器模型

在所有的预处理和创建嵌入矩阵之后,我们准备好创建我们的单调关注编码器-解码器模型。

我们将使用模型子类化的方法从 Keras 的模型和层类中导出我们的模型。

编码器模型实现如下-

之后,我们创建→单调注意层、单步解码器层、解码器模型和包含编码器和解码器的最终模型。

关于我的实现的全部细节,请查看我的 Github 简介

数据管道

现在我们需要一些东西,可以把我们的数据,转换成所需维度的批量数据。为此,我们通过从 Keras 的序列层派生来创建数据管道

培养

终于到了我们训练模型的时候了!

我们正在对“ADAM”优化器和自定义损失函数进行培训,以确保我们不会计算填充值的损失,因为我们已经大量填充了数据。

train_steps=train.shape[0]//512valid_steps=validation.shape[0]//512attention__.fit(train_dataloader, steps_per_epoch=train_steps, epochs=120, validation_data=validation_dataloader, callbacks=[es,chkpt,tfboard], validation_steps=valid_steps, )

训练图(蓝色->验证)

推理

训练完模型后,我们该检查它的效率了。我们将使用 BLEU 分数作为我们的衡量标准。

贪婪搜索 v/s 光束搜索

我们使用两种类型的搜索来预测我们的产出。

剧透预警!!!→ 它们的表现相似,因此我最终使用了贪婪搜索。

贪婪搜索→

该模型的输出是一个巨大的概率表,包含我们的单词在词汇表中的概率。在贪婪搜索中,我们只是简单地选择概率最高的单词。

贪婪搜索的推理

波束搜索

在 beam 搜索算法中,我们不是选择一个概率最高的词,而是选择前 3 个词(beam_index=3)。基于这前 3 个单词,我们预测下一个单词,并用我们之前的单词计算这些单词的条件概率。这个过程一直持续到我们到达终点。

要想恰当地理解梁寻欢,观看本 视频 作者吴恩达,阅读本 文章 作者 达蒂达米

波束索引= 3 的波束搜索的实现

波束搜索推理

结果和误差分析

正常情况下,我在训练数据集上的 BLEU 分数约为 0.90 ,而验证和测试数据集的 BLEU 分数约为 0.75

但是随着单调的关注,我得到了训练数据集的 0.98 BLEU 分数,而测试和验证数据集的0.90BLEU 分数。这是一个显著的改进!

误差分析

我分析了错误,发现我们的模型存在以下问题,这些问题可能是导致在我们的分数中遗漏 0.10 的原因。

1

2

端到端管道

在这个项目的最后阶段,我创建了一个端到端的部署管道,它接收输入并预测输出,可以直接用于任何应用程序。

首先,我创建了一个模块(。py 文件),名为 monotonic_attention,包含我们的编码器-解码器模型。

然后,我创建了另一个名为 model.py 的模块,它导入上述模块并预测输出。它包含一个 predict()方法,该方法使用贪婪搜索执行推理

导入后,我们用所有文件和一个 model_weight 初始化我们的模型

预测

如果你已经走到这一步。哇!谢谢你!看了我的文章。我希望你没有直接跳到这里!;)

参考

  1. 单调关注论文—https://Colin raffel . com/blog/online-and-linear-time-Attention-by-enforcing-Monotonic-alignments . html
  2. https://github . com/UdiBhaskar/tfk eras-Custom-Layers/blob/master/seq 2 seq/clayers . py
  3. https://applied ai course-1 . medium . com/FAQs-about-attention-assignment-3033 ac9 f 05 AC
  4. 在乌代·派拉的指导下在 AppliedAI 球场完成的项目。https://www.appliedaicourse.com/

对 ARIMA 模式的深刻理解

原文:https://towardsdatascience.com/deep-understanding-of-the-arima-model-d3f0751fc709?source=collection_archive---------3-----------------------

实践教程

探索时间序列的特征——平稳性、稳定性、自相关性

图片来自 Unsplash

时间序列快速介绍

通常,时间序列预测模型可以写成

Eq 0.2 时间序列预测模型的定义

其中,yₜ是要预测的变量(因变量,或响应变量),t 是进行预测的时间,h 是预测范围,Xₜ是在时间 t 用于进行预测的变量(自变量),θ是函数 g 中参数的向量,εₜ₊ₕ表示误差。值得注意的是,观察到的数据根据观察时间是唯一有序的,但它不必依赖于时间,即时间(观察值的指数)不必是独立变量之一。

时间序列的一些可能性质

平稳性:平稳过程是随机过程,其均值、方差和自相关结构不随时间变化。它也可以用数学术语正式定义,但在本文中,这不是必需的。直观地说,如果一个时间序列是平稳的,我们看它们的一些部分,它们应该非常相似——时间序列看起来是平坦的,形状不取决于时间的变化。(快速查知识:f(t) = sin(t)是平稳过程吗?肯定不是,因为它不是随机的,平稳性不是它的属性之一)

图 1.1 平稳性示例。图片来自维基百科(白噪音)

图 1.1 显示了平稳过程的最简单的例子——白噪声。

图 1.2 非平稳时间序列示例。作者制作的图表。

上图 1.2 显示了一个非平稳的时间序列。为什么会这样呢?我们可以看到明显的趋势,这意味着方差随着时间而变化。但是,如果我们使用线性回归拟合一条线(以捕捉趋势)并移除趋势,数据现在具有恒定的位置和方差,但由于周期行为,它仍然不是静止的,这不是随机的。

图 1.3(左)为原始数据拟合一条线,图 1.4(右)为去除趋势后的结果。作者制作的图表

使用 ARMA 对时间序列建模时,其中一个假设是数据是平稳的。

季节性:季节性是在短于一年的特定时间间隔内表现出某些变化的特性(当然也可以是不同的时期。如果我们在一天中观察每小时的温度,并在几天内收集数据,那么这个周期就是一天,它也可能具有季节性-峰值可能出现在下午 2 点或 3 点。这意味着我们不必用常识在季节性的背景下解释季节)、月度、季度等。季节性时间序列的一个非常典型的例子是用电量,在夏季,用电量通常较高,例如,因为有空调。

图 1.5 美国用电量的季节性曲线图。图片来自维基百科(季节性)

图 1.5 显示了具有季节性的数据,我们可以很容易地看到,在 7 月和 8 月有一个用电高峰,在 1 月和 12 月有一个较小的高峰。图 1.5 中绘制的数据是美国从 1973 年到 2010 年的用电量。usmelec是 r 中内置的数据集。整个期间的用电量如下所示

图 1.6 美国 1973 年至 2010 年的用电量。作者制作的图表

季节性的存在要求我们调整预测的方式。比如我们要卖空调,就需要用历年同季的销量来预测未来的月销量,而不是最接近的月份。

逐步定义 ARIMA

技术说明:后移运算符

这是什么?它是一个将变量 xₜ后移的算子,有时表示为 b(后移),有时表示为 l(滞后),在本文中,我们将采用符号 b。它定义为

等式 2.1 后移算子的定义

以及满足 B⁻ B = 1 的向前移位算子 B⁻。

我们为什么需要这个?这是因为它使我们能够以简洁的方式明确地回移——就多项式而言,这也有助于我们定义更复杂的模型。当我们用一个东西来表示数学中的某个东西时,看看它支持哪些运算总是很重要的。在这种情况下,我们很容易看到,后移运算符允许对它进行所有的算术运算:加、减、乘、除、取幂等。

这意味着,例如,在 xₜ上使用运算符 (1-B)得到 xₜ-xₜ₋₁的差,如果我们想再次得到 xₜ和 xₜ₋₁的差,我们在 xₜ上使用运算符 (1-B),得到(1–2 b+b)xₜ= xₜ-2xₜ₋₁+ xₜ₋₂.这和(xₜ-xₜ₋₁)-(xₜ₋₁-xₜ₋₂).)是一样的在这个例子中,我们遇到了一阶和二阶差分(方程 2.12,2.13),这将在后面解释。

自回归模型

阶为 p 的自回归模型,缩写为 AP(p),将当前值建模为先前 p 值的线性组合。这个模型就是这样得名的,它本身就是一个线性回归。我们在定义中看到了很多术语,但该模型仍然被认为是单变量,因为当前值取决于其过去值。这些值是同一变量在不同时间点的值,所以毕竟只涉及一个变量。更一般化的模型是 VAR (向量自回归),允许多元时间序列。形式上,(单变量)自回归模型被定义为

情商。2.2 自回归模型的正式定义

其中 wₜ ~ wn(0,σᵥᵥ),ϕ₁,ϕ₂,…,ϕp (ϕp ≠ 0)为参数。wn 表示“白噪声”,它具有均值为 0 且方差为σᵥᵥ的正态分布。有时方程 2.2 的右边也有一个常数,用 c 表示( 预测:原理与实践第 8.3 章 )。常量所起的作用将在 ARIMA 小节中解释。

根据后移算子,自回归模型被定义为

等式 2.3 使用后移运算符定义 AR 模型

移动平均模型

q 阶移动平均模型,缩写为 MA(q),将当前值建模为前面 q 个误差项的线性组合(与自回归模型不同,在移动平均中,关注的是误差项)。形式上,它被定义为

情商。2.4 移动平均线模型的正式定义

其中 wₜ ~ wn(0,σᵥᵥ),θ₁,θ₂,…,θq (θq ≠ 0)为参数。wn 表示“白噪声”,它具有均值为 0 且方差为σᵥᵥ的正态分布,类似于自回归模型的定义。这也是一个单变量模型。也可以在定义中添加一个常数( 预测:原理与实践第 8.4 章 )。

根据后移运算符,移动平均模型可以定义为

等式 2.5 使用后移运算符定义 MA 模型

与自回归模型不同,这种移动平均模型的名字并不那么明显。根据第 48 页的脚注单变量 Box-Jenkins 模型预测(2009):Pankratz 的概念和案例:“标签‘移动平均’在技术上是不正确的,因为 MA 系数可能为负,且总和可能不为 1。这个标签是约定俗成的。”

另一个令人困惑的事情是一个看起来像移动平均模型的概念,移动平均,又名滚动平均或移动平均,用于平滑时间序列。事实上,它是一个完全不同的工具——它不是用来预测的。我们用简单移动平均线的例子来说明这一点

等式 2.6,2.7 简单移动平均线

观察公式后,我们可以看到,我们需要第 k 个值来计算第 k 个移动平均线。

自回归移动平均模型

ARMA 模型是AR 和 MA 的组合,相当自明。ARMA 考虑了过去的值和过去的误差项,并用两个多项式描述了(弱)平稳随机过程。形式上,如果时间序列是平稳的并且

方程 2.8 ARMA 的正式定义

其中ϕp ≠ 0,θq ≠ 0,wₜ ~ wn(0,σᵥᵥ),σᵥᵥ > 0。如前所述,参数 p 和 q 分别是自回归阶和移动平均阶。就后移算子而言,ARIMA 模型可以写成

等式 2.9 根据后移算子定义的 ARIMA 模型

这种重写并不简单。它揭示了模型中可能出现的一个严重问题— 参数的冗余。如果多项式ϕ(b = 0 和θ(B) = 0 有公共因子,那么模型将包含冗余参数。这将使模型变得非常复杂。什么时候会出现这种情况?当我们试图用 ARMA(1,1)模型拟合一个白噪声序列(xₜ = wₜ)时,程序会这样做,但我们得到的模型会有多余的参数。因此,我们需要去除冗余以简化模型,并且可以使用协方差分析来去除冗余。

等式 2.8 所示的定义是非季节性 ARMA。但经常发生的是,数据是季节性的。如果我们想消除季节性,我们应该怎么做?答案是引入一个滞后 h(季节周期的长度),这就引出了季节 ARMA (SARMA),记为 ARMA(P,Q)ₕ),其形式为

方程 2.10 季节性 ARMA 的定义

这种去除季节效应的方法对应于我们之前描述过的:利用八月份的数据预测八月份的销售额。h 应该等于什么?这取决于季节性的频率,例如,如果季节性变化在一年中的某些特定月份出现一次,则 h = 12,如果它在一年的每个季度出现一次,则 h = 4。如果我们将季节性 ARMA 和非季节性 ARMA 结合起来(将季节性和非季节性算子相乘),我们将得到一层概括——混合季节 ARMA。

混合季节 ARMA 模型

混合季节 ARMA 的符号

自回归综合移动平均(ARIMA)模型

ARIMA 模型是基于差分序列的 ARMA 模型,差分有时也称为。那么什么是差异呢?它是一种去除序列非平稳性的技术(这种技术去除了非恒定趋势,这意味着它只产生均值平稳性,而不是方差)。它取两次观察的差值。

等式 2.12 和等式 2.13 的区别

当然,我们可以多次改变观测值。等式 2.12 和等式 2.13 给出了一阶差分和二阶差分的例子。显而易见,差分不同于微分——差分只是取差,同时,微分计算变化率。ARIMA 模型通常用 ARIMA(p,d,q)来表示,参数的含义总结如下表

标签。2.1 模型中的参数。(作者自制)

现在是时候介绍 ARIMA 模型的正式定义了,

方程 2.14 ARIMA 模型的定义

在 yₜ'表示差分序列的地方,其他参数的定义方式与 ARMA 模型中的相同。如前所述,可以将一个常数添加到模型中,该常数表示漂移。通过涉及 ARIMA(0,1,0)模型(没有自回归或移动平均项,使用一阶差分建模)的示例,可以很容易理解:

无参数:模型是 xₜ = xₜ₋₁ + εₜ,是随机游走。

带参数:模型为 xₜ = c+ xₜ₋₁ + εₜ.这是一个有漂移的随机游走。

常量为过程增加了非常量趋势。(这句话看起来很诡异,但是我们需要注意的是,公式 xₜ = c+ xₜ₋₁+ εₜ是递归的,在每次解出一个常数的时候用 stack up)这个常数有多大的影响力?很多。我们可以从两个随机行走的模拟中看到这一点,一个有漂移,一个没有漂移

图 2.1 无漂移(左)和有漂移(右)的随机游走模拟。作者制作的图表。

然而,这种差异并没有考虑到季节性。为了消除季节性,我们需要考虑季节性差异(xₜ和 xₜ₋ₕ之间的差异),这就带来了季节性自回归综合移动平均(SARIMA)模型。萨里玛和 SARMA 之间的关系非常类似于 ARIMA 和 ARMA 之间的关系——萨里玛是有差异的 SARMA,但现在我们不仅需要考虑非季节性差异,还需要考虑季节性差异。我们用 ᴰ和 ᵈ分别表示季节性差异和非季节性差异。 D 是季节差异的程度。

情商。2.15 季节性 ARIMA 模型

季节性 ARIMA 的符号

实践中的 ARIMA

如圣经预测:原则和实践中所述,有一种拟合 ARIMA 模型的一般方法:预处理,直到数据变得稳定;提供给计算 ARIMA 模型的函数;比较模型;检查结果(残差);如果不够好,迭代,否则使用结果模型做预测。

在 R 中,使用最大似然估计 (MLE)来估计参数,最大化似然函数。在给定我们的模型的参数(ϕ,θ,…)的情况下,可能性等于产生观察值 x 的概率。为了比较这些模型,使用了 Akaike 信息标准 (AIC),该标准评估了信息的损失,也惩罚了模型的复杂性(估计参数的数量)。我们选择具有最小 AIC 值的模型。

自动化的

如果我们想要使用一个自动化的过程来构建模型,函数auto.arima就在我们的支配之下。它使用分步过程(Hyndman-Khandakar 算法)来有效地遍历模型空间。函数auto.arima负责对数据进行差分以使数据稳定(是否 d = 0),选择超参数,并根据 AIC 选择最佳模型。

我们用去年 8 月 16 日到今年 8 月 26 日的油价来展示自动化的 ARIMA 过程。我们想要实现的是使用 2020 年 8 月 16 日至 2021 年 8 月 16 日的数据来预测未来 10 天的油价,然后将结果与真实值进行比较。(在本文中,目的主要是向读者介绍 ARIMA 模型的原理,所以这实际上是一个粗略的股票预测,像回溯测试之类的东西不包括在内)

# read data
# Datasource: [https://finance.yahoo.com/quote/OIL/history?p=OIL](https://finance.yahoo.com/quote/OIL/history?p=OIL)
dataOil <- read.csv2(file = "data/OIL.csv", sep=",")
head(dataOil)# split into training and test data
lenOil <- nrow(dataOil)
trainSize <- ceiling(lenOil-10)# take the first 12 month 
train.oil <- dataOil[1:trainSize, ]
test.oil <- slice_tail(dataOil, n=lenOil-trainSize)# convert to time series
train.close <- train.oil$Close
train.close <- as.numeric(train.close)# frequency is set to be one because we have only one year of data
train.close.ts <- ts(data=train.close, frequency=1)# plot the training data 
plot(train.close, type='l', ylab='Close price', main="One year oil price")

图 3.1 2020 年 8 月 26 日至 2021 年 8 月 26 日油价

显然,我们可以看到一个趋势,时间序列不是平稳的,但没有变化方差的证据,所以我们不准备做任何转换。模型构建的其余部分由auto.arima.负责,但我们需要做的是检查残差,以确保它们看起来像随机噪声,这部分由checkresiduals完成,它应用了永盒测试。如果 Ljung-Box 检验的 p 值大于 0.05,我们不能拒绝残差独立分布的零假设。因此,这个模型是可接受的,否则,我们将需要选择一个新的。

start <- length(train.close.ts)
test.index <- seq(start, start+9)
test.close <- as.numeric(test.oil$Close)aa.train <- auto.arima(train.close.ts) 
# --> AIC = 157.11
checkresiduals(aa.train)
# --> p-value = 0.07454plot(forecast(aa.train, h=10))
lines(test.index, test.close)

与 8 月 17 日至 8 月 26 日(过去 10 天)的油价实际值相比,结果如下。

图 3.2 预测结果

客户模型

自动化过程可能无法找到适合我们的模型。如果它没有通过永盒测试,我们需要自己选择超参数。因此,有时我们可能需要选择自己的模型(使用Arima)。与自动化流程相比,为了使用我们自己的模型,除了之外我们还需要做什么?首先,在观察数据之后,我们需要考察数据的偏相关。(要了解更多关于偏相关的信息点击这里)。

# plot the partial difference 
dif.train <- difference(train.close.ts)
ggtsdisplay(dif.train, plot.type='partial')

图 3.3 一阶差分、自相关和偏自相关

图中所示的差看起来相当稳定,因此我们将只使用一阶差。但是我们仍然可以执行单位根测试来检查平稳性。对此,我们有几个备选方案,这里我们使用扩展的迪基-富勒测试(ADF,在 R 中它是adf.test,如果我们设置k=0,那么它就变成简单的迪基-富勒测试)。

# ADF test
dif.train <- na.remove(dif.train)
adf.test(dif.train)
# --> p-value smaller than 0.01

根据结果,我们可以拒绝一阶差分为 非平稳 的零假设。因此我们设置 d=1 。根据偏自协方差,显示平稳时间序列与其自身的滞后值之间的相关性,消除了更短滞后的影响,变量 xₜ与 xₜ₊₄相关,那么我们可以尝试设置 p = 4 。剩下的就是 q 了,我们可以从 0 开始尝试,逐渐增加。至于季节性,它并没有真正显示在图表中,因此我们可以将季节性** (P,D,Q)的参数保留为缺省值 0。应该加漂移吗?从图 3.2 中的增加趋势来看,似乎是的,我们可以将include.drift设为真。**

# manually try the different parameters
fit.m1 <- Arima(train.close.ts, order=c(4,1,0), include.drift=TRUE)
fit.m1
# --> AIC = 156.15fit.m2 <- Arima(train.close.ts, order=c(4,1,1), include.drift=TRUE)
fit.m2
# --> AIC = 157.61 
# after trying some more other values of q, we will find out
# that increasing q doesn't really decrease the AICcheckresiduals(fit.m1)
# --> p-value = 0.4187plot(forecast(fit.m1, h=10))
lines(test.index, test.close)

我们的定制模型具有稍低的 AIC 值,然而该图看起来几乎与图 3.2 所示的相同。

图 3.4 预测-定制模型的结果

总结

在这篇文章中,首先,我们快速地介绍了时间序列的形式定义和时间序列中可能出现的一些典型性质。之后,随着 ARMA 和 ARIMA 的扩展——季节性 ARMA (SARMA)和季节性 ARIMA(萨里玛),我们逐渐熟悉了 ARIMA 的定义。最后,我们建立了一个模型,对油价进行了自动和人工的短期预测。

参考

[1]NIST/sema tech电子版统计方法手册 (2012)。

[2]沃森,M. W. 时间序列:经济预测 (2001)。国际社会百科全书&行为科学,15721–15724。

[3] Hyndman,R. J .,& Athanasopoulos,G. 预测:原理与实践 (2018)。OTexts。

[4] Pankratz,A. (2009 年)。 单变量 Box-Jenkins 模型预测:概念与案例 (第 224 卷)。约翰·威利的儿子们。

[5] Hyndman,R. J .,& Khandakar,Y. (2008 年)。自动时间序列预测:R 的预测包。统计软件杂志27 (1),1–22。

[6]埃尼,D. (2015 年)。尼日利亚瓦里镇降雨量的季节性 ARIMA 建模和预测地球科学与环境保护杂志3 (06),91。

【7】自回归综合移动平均线。(2021 年 4 月 29 日)。在维基百科里。

我对建模和预测哲学的一些看法😃

DeepDiff——使用 Python 递归查找并忽略细微差异

原文:https://towardsdatascience.com/deepdiff-recursively-find-and-ignore-trivial-differences-using-python-231a5524f41d?source=collection_archive---------12-----------------------

比较两个 Python 对象时出现有意义的断言错误

动机

在比较两个 Python 对象时,您可能不希望测试集中在一些细微的差异上,比如列表中值的顺序。

例如,您可能希望测试认为[3, 2][2, 3]相同。

但是,如果顺序不同,就会出现错误。

作者图片

在比较两个 Python 对象时,有没有一种方法可以忽略顺序?

作者图片

作者图片

这时 DeepDiff 就派上用场了。在本文中,您将学习如何使用 DeepDiff 来防止比较 Python 对象的某些部分。

什么是 DeepDiff?

DeepDiff 是一个 Python 库,它递归地查找字典、可重复项、字符串和其他对象中的所有变化。

要安装 DeepDiff,请键入:

pip install deepdiff

描述错误

当使用assert比较两个不同的 Python 对象时,您可能会得到类似下面的错误:

AssertionError: assert {'apple': 2, 'banana': [3, 2, 2], 'orange': 3} == {'apple': 2, 'banana': [3, 2], 'orange': 3}

这个断言错误信息不多,因为我们不知道使这两个字典不同的确切元素。

使用 DeepDiff,我们可以看到一个更具描述性的错误,它显示了差异是什么以及差异发生在哪里。

图片由作者提供—将上述的代码复制到此处

从上面的错误中,我们知道了三件事:

  • price1中的一项在price2中被删除。
  • 移除的项目在price1['banana'][2]
  • 移除项目的值为2

树形视图

DeepDiff的默认视图是"text"。要将视图更改为树形视图,使用view="tree"。在树视图中,您可以遍历树并查看哪些项目相互比较。

图片由作者提供—将上述的代码复制到此处

忽略订单

如文章开头所示,可以使用ignore_order=True忽略顺序:

图片由作者提供—将上面的代码复制到这里

输出{}显示两个 Python 对象之间没有区别。

您也可以使用ignore_order=True来忽略重复项:

图片由作者提供—将上述的代码复制到此处

忽略两个数字之间的微小差异

忽略某个数字

当两个数字非常接近时,看到断言错误可能会很烦人。如果您想忽略特定数字后两个数字之间的差异,请使用significant_digits

在下面的代码中,我们只比较这两个数字的第二位数。

图片由作者提供—将上述的代码复制到此处

忽略ε以下的差异

有时候,两个数字非常接近,但是它们没有相似的数字。要忽略两个数字之间的微小差异,请使用math_epsilon

在下面的代码中,我使用math_epsilon=0.001告诉DeepDiff忽略小于 0.001 的差异。因为 1 和 0.9999 之间的差是 0.0001,所以该差被忽略。

图片由作者提供—将上面的代码复制到这里

忽略字符串大小写

如果想忽略字符串大小写(即“红色”和“红色”),使用ignore_string_case=True

图片由作者提供—将上述的代码复制到此处

忽略 NaN 不等式

如果你和一些 nan 一起工作过,你可能知道在 Python 中不是每个 nan 都是平等的:

作者图片

因此,比较包含不同类型的 nan 的对象可能会令人困惑。(难道[nan, 1, 2]不等于[nan, 1, 2]?)

图片由作者提供—将上述的代码复制到此处

要忽略不同类型的 nan,请使用ignore_nan_inequality=True:

图片由作者提供—将上面的代码复制到这里

排除类型

有时,您可能不关心某些类型是否会改变。要包含某些数据类型,请使用exclude_types:

图片由作者提供—将上面的代码复制到这里

忽略数字类型

2 != 2.0因为2是整数而2.0是浮点数。您可以使用ignore_numeric_type_changes=True忽略数值类型的变化。

图片由作者提供—将上述的代码复制到此处

截断日期时间

在比较两个 datetime 对象时,您可能只想确保它们在一定程度上是相似的(具有相同的小时,而不是相同的小时和分钟)。

作者图片

您可以使用truncate_datetime指定DeepDiff在两个日期时间对象之间进行比较的精确程度。

图片由作者提供—将上述的代码复制到此处

忽略路径

如果您想从报告中排除某些路径,您可以exclude_paths:

图片由作者提供—将上面的代码复制到这里

排除返回路径

如果想忽略某个模式的多条路径,使用exclude_regrex_paths

例如,为了避免比较aldi[0]['color']walmart[0]['color']以及aldi[1]['color']walmart[1]['color'],我们简单地忽略了正则表达式root[\d+\]\['color'\]指定的路径,其中\d+代表一个或多个数字。

图片由作者提供—将上面的代码复制到这里

如果您不熟悉正则表达式,请查看此备忘单。

将 DeepDiff 与 pytest 一起使用

要将 DeepDiff 与 pytest 一起使用,请编写assert not DeepDiff(...)。这意味着我们想要断言两个 Python 对象之间没有区别。

作者图片

结论

恭喜你!您刚刚学习了如何在使用 DeepDiff 比较两个 Python 对象时忽略某些元素。我希望这个工具能让你更容易地编写测试和调试代码。

随意发挥,并在这里叉这篇文章的源代码:

https://github.com/khuyentran1401/Data-science/blob/master/productive_tools/deepdiff_example.ipynb

我喜欢写一些基本的数据科学概念,并尝试不同的数据科学工具。你可以在 LinkedIn 和 T2 Twitter 上与我联系。

这个回购如果你想检查我写的所有文章的代码。在 Medium 上关注我,了解我的最新数据科学文章,例如:

</4-pre-commit-plugins-to-automate-code-reviewing-and-formatting-in-python-c80c6d2e9f5> 💔-tools-to-track-and-visualize-the-execution-of-your-python-code-666a153e435e> [## 3 个跟踪和可视化 Python 代码执行的工具

towardsdatascience.com](/3-tools-to-track-and-visualize-the-execution-of-your-python-code-666a153e435e)

DeepL:一个非常出色的语言翻译器

原文:https://towardsdatascience.com/deepl-an-exceptionally-magnificent-language-translator-78e86d8062d3?source=collection_archive---------38-----------------------

DeepL 将翻译的边界推向了人类层面

杆长Unsplash 上拍照

DeepL 将机器翻译带到了一个全新的水平。到目前为止,我们已经习惯了基于递归神经网络和“嵌入”形式的单词表示的机器翻译,这些翻译听起来往往机械而不自然。这就是为什么很多人只是在紧急情况下,旅行时才使用谷歌翻译。DeepL 是一个游戏改变者。建立在神经网络上的算法可以翻译文本,这与一个合格的翻译几乎没有区别。

与谷歌翻译类似,网络上有一个应用,可以让你免费翻译 26 种不同语言之间的文本。翻译结果非常出色,很可能会改变人们习惯的文本翻译方式。在本文中,我比较了使用 DeepL 和 Google Translate 翻译不那么简单的文本,并给出了 DeepL 在不久的将来可能会被使用的例子。

让我们测试一下

我先用 DeepL 翻译了下面的文字,然后用 Google 翻译。文章是用捷克语写的,由于其极其复杂的语法,捷克语被认为是最难学的语言之一。这篇文章是以一种相当口语化的方式写的,结构不太好,包含引文,并且来自新闻门户https://www.forum24.cz/.

Andrej Babiš: Nejsem idiot, řídím chytrou karanténu a mávám z Řecka.Pan premiér se nám rozjel, a to ve všech významech tohoto slova. S rodinkou se rozjel do Řecka, na sociálních sítích se rozjel s vyjádřeními, kterým se už snad ani nejde smát. Andrej Babiš prý převzal kontrolu nad chytrou karanténou, máme problémy, ale ve skutečnosti se nic neděje, a proto jakožto předseda vlády v krizové situaci, která není krizová, odjíždí na dovolenou, což je divné, protože například ministryně financí Alena Schillerová podle svých slov řeší krizi, a tak nikam nejede.No nic, pěkně popořádku. Ministr zdravotnictví Adam Vojtěch po sedmisté osmdesáté páté selhal a s ním i údajný projekt chytré karantény. Říkáme údajné protože ji nikdo neviděl. Babiš se naštval. Nejprve se naši filutové pokusili situaci řešit tím, že prostě a jednoduše škrtli ze statistiky počty nakažených, což bylo divné, ale opět to vzbudilo pouze výsměch. Lidé navíc začali být nervózní, protože na testy se i po půl roce od počátku pandemie stojí fronty a nic nefunguje.

首先,让我们看看谷歌翻译如何翻译文本:

Andrej Babiš: I'm not an idiot, I run a smart quarantine and I'm waving from Greece.The Prime Minister **has left us (1)**, in all meanings of the word. He went to Greece with his family, **he started on (2)** social networks with expressions that are hardly laughable. Andrej Babiš is said to have taken control of clever quarantine, we have problems, but nothing really happens, and therefore as prime minister in a non-crisis crisis, he goes on vacation, which is strange because, for example, Finance Minister Alena Schillerová says crisis, so it goes nowhere.**Well, nothing, all right (3).** Minister of Health Adam Vojtěch failed for the seventy-eighty-fifth time, and with him the alleged project of clever quarantine. We say alleged because no one saw **her(4)**. **Grandma(5)** was angry. At first, our filets tried to solve the situation by **simply and simply(6)** deleting the number of infected from the statistics, which was strange, but again it only aroused ridicule. In addition, people have become nervous, because even after six months from the beginning of the pandemic, there are queues for tests and nothing works.

我用数字标记了翻译中最高的语法错误:(1)这是单词的语义混乱,英文文本想说的是人类对情况的反应过度,(2)这又是一个单词的不准确翻译,(3)翻译“嗯,没什么,好吧”是人类可能不会说的机器翻译的例子,(4)这是一个错误,因为我们正在谈论一场危机, 因此,我们使用代词“它”,而不是“她”,(5)完全不准确,文本指的是 Babi,而译者翻译了“祖母”一词,(6)“简单而简单”又是一个英国人或美国人可能不会说的表达。

在文本中可能有更多的文体和语言错误可以描述。

我们来看看来自 DeepL 的翻译:

Andrej Babiš: I'm not an idiot, I run a smart quarantine and wave from Greece.The Prime Minister is on a roll, in all senses of the word. He took off for Greece with his family, and on social media he made statements that are impossible to laugh at anymore. He says that Andrej Babiš has taken control of a clever quarantine, that we have problems, but that nothing is really happening, and that is why, as Prime Minister in a crisis situation that is not a crisis, he is going on holiday, which is strange because, for example, Finance Minister Alena Schiller says she is dealing with a crisis and so is not going anywhere.Anyway, first things first. Health Minister Adam Vojtěch has failed for the eighty-fifth time, and with him the alleged smart quarantine project. We say alleged because no one has seen it. Babiš got angry. At first our philots tried to solve the situation by **simply and simply (1)** crossing out the number of infected from the statistics, which was strange, but again it only drew ridicule. Moreover, people have become nervous because there are still queues for tests six months after the pandemic began and nothing is working.Translated with [www.DeepL.com/Translator](http://www.DeepL.com/Translator) (free version)

翻译中的主要错误在于“简单而简单”这一表达方式,这是一种捷克特有的表达方式,该表达方式的直接翻译可能并不存在。

那不是不真实的吗?:-)文本的翻译差异巨大。

结论

一个使用 DeepL 的简单演示展示了这个工具有多棒。与 Google translator 相比,它在文本的机器翻译方面有了多方面的改进。

这篇文章最初是用捷克语写的,然后用免费的 DeepL 版本翻译成了英语,在这里可以找到。除了文章标题和最后一句话,我没有以任何方式编辑过语言翻译。我不确定你是否认出了它🙂

DeepL 很有可能在不久的将来被使用,其中包括:

  • 公司:网站、产品信息、内部文件、公司介绍等文本的翻译。
  • 毕业论文和学位论文
  • 网站的语言变异

在我看来,在 5 -7 年的时间里,人们只会翻译包含特定情感元素和具有艺术潜台词的文本,如诗歌、小说或其他非常具体的文本。其他文本由人类翻译在经济上是不可行的。最贵的许可证 DeepL 目前每月收费 40 欧元。如果它的创造者能把它的价格控制在翻译的成本之内,那么大多数翻译就不需要人类了。

PS:你可以订阅我的 邮箱列表 每次我写新文章都会收到通知。如果你还不是中等会员,你可以在这里加入https://medium.com/@petrkorab/membership

深度学习。人工智能和 ML 教程代码质量问题

原文:https://towardsdatascience.com/deeplearning-ai-and-the-ml-tutorial-code-quality-problem-4e3a37109383?source=collection_archive---------13-----------------------

干净的代码很重要!甚至(特别是)在机器学习研究领域

Charles DeluvioUnsplash 上拍摄的照片

2014 年,吴恩达的 Coursera 课程让我第一次接触到了机器学习。这些课程提供了一个可访问的,全面的 ML 方法回顾;他们让我着迷了!

最近重温了一些课程内容,报名参加了深度学习。AI TensorFlow 开发者专精作为进修。和以前一样,我对解释的清晰性感到惊讶。讲师建立重要的直觉,并慢慢分解复杂的技术内容。

然而,在整个课程中,我注意到一个我在机器学习教程源代码中看到的问题:糟糕的代码质量。下面,我列举了一些风格上的例子。我还指出了一些来自谷歌风格指南的风格惯例,这将提高可读性!

不一致的报价使用

样式指南备选方案:“与文件中字符串引用字符的选择保持一致。选择'"并坚持下去。可以在字符串中使用另一个引号字符,以避免需要在字符串中对引号字符进行反斜线转义。

不一致的空格

样式指南备选方案:“用一个空格将二进制运算符括起来,用于赋值(=)、比较(==, <, >, !=, <>, <=, >=, in, not in, is, is not)和布尔(and, or, not)。对于在算术运算符(+-*///%**@)周围插入空格,请使用您更好的判断……不要使用空格来垂直对齐连续行上的标记,因为这会成为维护负担(适用于:#=等)。)"

不一致的文档样式

风格指南替代方案:“注释的最后一个地方是代码中棘手的部分。如果你要在下一次代码审查中解释它,你应该现在就注释它。复杂的操作在操作开始前会得到几行注释。非显而易见的注释位于行尾……为了提高可读性,这些注释应该以注释字符#开始,距离代码至少 2 个空格,然后在注释文本本身之前至少一个空格。

不一致的大小写

风格指南备选方案:“虽然它们在技术上是变量,但模块级常量是允许的,也是鼓励的。比如:_MAX_HOLY_HANDGRENADE_COUNT = 3。常量必须全部用带下划线的大写字母命名。见下面的命名。因为这些是参数,不是常量,我们应该避免使用大写形式。

不一致的进口水平

风格指南替代:“使用import x导入包和模块;使用from x import y,其中x是包前缀,y是不带前缀的模块名;如果要导入两个名为y的模块,或者如果y是一个不方便的长名称,则使用from x import y as z;仅当z是标准缩写时,才使用import y as z(例如np代表numpy)。”

显然,这些格式问题都不会从根本上影响课程。这些讲座仍然提供了宝贵的资源。不过,至少不一致的风格会分散人们对材料的注意力。最坏的情况是,它在教程环境中的展示鼓励了糟糕的软件实践,这扩大了基于笔记本的实验和操作源代码之间的鸿沟。

教育代码旨在用作参考,自然会邀请一定程度的 cargo cult 编程。通常情况下,学习者的 Python 接触很少。这种设置提供了展示最佳实践的理想机会。

有了 nbQA 这样的工具进行林挺、格式化和静态类型检查,开发整洁的笔记本变得前所未有的简单!

https://github.com/nbQA-dev/nbQA

感谢阅读!如果你同意,请在评论中告诉我!

深度思维、阿尔法折叠和蛋白质折叠问题

原文:https://towardsdatascience.com/deepmind-alphafold-the-protein-folding-problem-a331d9ced746?source=collection_archive---------46-----------------------

通过 AlphaFold,谷歌的 DeepMind 通过解决由来已久的蛋白质折叠问题,正在推动医学科学领域的边界。

Unsplash科学高清拍摄的照片

蛋白质是所有生物的基本组成部分。它们负责身体的生长、发育和营养。因此,了解蛋白质是如何由身体合成和形成的,将有助于了解每个生物体内各种重要的生物过程。

蛋白质合成

真核生物利用基因通过 DNA (脱氧核糖核酸)提供的信息,在核糖体中合成蛋白质。基因携带着父母传给后代的特征或特性的信息。它们在 DNA 中以不同核苷酸序列的形式携带这些信息(腺嘌呤、鸟嘌呤、胸腺嘧啶和胞嘧啶)。蛋白质合成发生在两个过程中— 转录和翻译。

转录阶段。来源:施维雅医疗艺术

在转录过程中,DNA 被用作模板来创建信使 RNA (mRNA) 的分子,其方式是将 DNA 的一条链中携带的遗传信息转录到 mRNA 的一条链中。在翻译阶段,这种 mRNA 然后移动到位于细胞质中的核糖体中,在那里根据 mRNA 提供的信息合成蛋白质。在核糖体中,tRNA 带入氨基酸,根据 mRNA 提供的信息,tRNA 带入的氨基酸连接形成多肽。

翻译阶段。来源:施维雅医疗艺术

这形成了蛋白质的初始结构,随后是由于形成链骨架的原子之间的相互作用而导致的局部折叠。这是二级结构。为了形成三级结构,组成蛋白质的氨基酸相互作用,形成三维形状。因此,最初的多肽通过一系列折叠步骤转化成蛋白质。

更详细的蛋白质合成描述可以在 这里找到

蛋白质折叠问题

蛋白质折叠是多肽(由肽键连接的氨基酸链)折叠成其特征性三维结构的物理过程。这种结构完全由链中的氨基酸序列决定,被称为安芬森法则(分子生物学中的热力学假设)[1]。

每个蛋白质的功能都与这种结构密切相关,能够非常接近这种结构将为科学解决世界上的各种问题打开新的大门,从寻找快速治愈疾病的方法,合成可以分解化学物质的蛋白质到理解生命的基本组成部分。然而,确定这种三维结构是一个复杂的过程。

1969 年,Cyrus Levinthal 指出,如果每个氨基酸残基在折叠过程中可以采用 3 种构象,那么 100 个残基的蛋白质可以采用 3 种⁰⁰ (=5.15 * 10⁴⁷)possible 构象)。如果以 0.1 皮秒的速率对每个构象进行计算采样,将需要 1.6 * 10 ⁷年,而宇宙的年龄只有 13.82 * 10⁹年。这意味着这将需要比已知宇宙年龄更长的时间,而这仅仅是对一种蛋白质而言。然而,每种蛋白质都可靠而快速地折叠到其天然状态(3D 结构)。这就是所谓的莱文塔尔悖论【2】。

输入 AlphaFold

AlphaFold 是 DeepMind 团队的最新成果,该团队开发了能够通过强化学习在围棋比赛中击败人类冠军的 AlphaGo。AlphaFold 是 DeepMind 对蛋白质折叠问题的解决方案。在 CASP13 期间,AlphaFold 能够以很高的精确度近似蛋白质结构的物理特性,并在实验中排名第一。

蛋白质结构预测的关键评估 (CASP)实验旨在为最先进模型在解决蛋白质折叠问题、确定已取得的进展以及突出未来努力方向方面的性能设定基准。CASP 广泛使用 Adam Zemla 开发的全球距离测试(GDT)[3]。GDT 是具有相同氨基酸序列的两个蛋白质结构之间相似性的度量,取值范围为 0-100。CASP 广泛使用这一指标来衡量几个竞争模型预测的优劣。近似蛋白质的物理结构主要涉及预测氨基酸对之间的距离以及它们之间化学键的角度。

在 CASP13 实验期间,DeepMind 使用神经网络架构来预测蛋白质中每对残基之间的距离分布,并将这些概率结合起来,形成预测的蛋白质结构有多接近的度量。该度量被用作算法优化的损失函数。还使用生成神经网络来创建新片段,这些新片段用于提高所提出的蛋白质结构的分数。这种方法实现了高度的准确性,在所有其他参与者中名列第一。

对于最新的 CASP14 实验,DeepMind 提出了 AlphaFold2。在这种方法中,折叠的蛋白质被认为是一种空间图形结构(3D 结构),其中残基形成节点,边缘连接非常接近的残基。一个基于注意力的神经网络系统被端到端地训练,以使用大约 170,000 个蛋白质结构来解释该图的结构。详细解释可以在这里找到。使用这种方法,AlphaFold 系统在 CASP14 评估中的所有目标上获得了 92.4 GDT 的中值分数。

图 2:在过去的几年中,预测中值准确度的提高。来源: AlphaFold

现实世界的影响

了解蛋白质的结构对确定其性质和功能大有帮助。使用这个系统,研究小组能够预测 SARS-Cov-2 病毒的几种蛋白质结构,这些结构以前是未知的,这只是皮毛。该系统可以在许多领域找到应用,如药物设计,从不同化合物中剔除不需要的元素,创造环境可持续的材料,等等。

未来令人激动。

参考

[1]安芬森,剑桥大学,1973 年。支配蛋白质链折叠的原理。科学181 (4096),第 223–230 页。

[2]莱文塔尔,1969 年。如何优雅地折叠?生物系统中的穆斯堡尔谱学67 ,第 22–24 页。

[3]泽姆拉,2003 年。LGA:一种寻找蛋白质结构三维相似性的方法。核酸研究31 (13),第 3370–3374 页。

[4]https://deep mind . com/blog/article/alpha fold-a-solution-to-a-50 岁生物大挑战

[5]https://deep mind . com/blog/article/alpha fold-Using-AI-for-scientific-discovery

[6]图片:https://smart.servier.com/

Deepmind AlphaFold2:高度精确的蛋白质结构预测

原文:https://towardsdatascience.com/deepmind-alphafold2-highly-accurate-protein-structure-prediction-7ef0946f60c0?source=collection_archive---------9-----------------------

深入研究 AlphaFold2 的文章,它是如何工作的,为什么,以及一切

国家癌症研究所Unsplash 上拍摄的照片

2 天前,发布了一篇关于 AlphaFold2 的文章,其中包含了关于该模型及其工作原理的预览。这是一个非常令人兴奋的消息,我想很多人都在等待这个消息。如果你不熟悉 AlphaFold2,它是 deepmind 为解决蛋白质折叠问题而构建的高级模型。蛋白质折叠问题是生物信息学领域最大的问题之一,如果你想了解更多,请点击这里查看我的文章。

臭名昭著的“刺突蛋白”,研究冠状病毒,使病毒进入我们的细胞。与此同时,像 Moderna 和辉瑞公司的 mRNA 疫苗复制了这些刺突蛋白的形状,导致身体产生免疫反应。但从历史上看,确定蛋白质结构(通过 X 射线晶体学、核磁共振和冷冻电子显微镜等实验技术)是困难、缓慢和昂贵的。另外,对于某些类型的蛋白质,这些技术根本不起作用。

来源: DaleonAI

在我们开始研究该模型之前,让我们快速回顾一下:

什么是 AlphaFold2

确定蛋白质的结构是一个非常困难的问题。我们需要这些结构来加深对蛋白质的了解,从而能够更好地发现药物和进行治疗。蛋白质折叠问题本质上是仅从其氨基酸序列确定蛋白质结构的问题。自 1994 年以来,一项名为蛋白质结构预测的关键评估(CASP)的正在进行的研究项目/竞赛每年都在进行,以评估确定蛋白质结构的计算方法的质量。到 2016 年为止,最好的成绩是 40 分(我不会深入解释这个分数),然后在 2018 年 Alphafold 达到了 58 分左右,现在 AlphaFold2 达到了 87 分,这是对以前型号的一个重大飞跃。

来源: deepmind

模型如何工作

从这篇文章中,我们可以从一个高层次的概述中收集整体模型是如何工作的。这就是事情变得有趣的地方,也是我写这些论文评论的原因。我最感兴趣的部分是模型实际上是如何工作的,问题是如何被框定的,以及模型是如何解决问题的。蛋白质折叠问题最好形成一个图推理问题。这并不令人惊讶,因为该模型需要预测三维空间的坐标,鉴于蛋白质结构的复杂性,最好将其建模为图表。

现在我们有了一个包含节点的图结构,我们需要定义一个比节点更大的构建块(很像节点的集合)。从一个角度来看,这就是一个多序列比对的原因。

更科学地说:

多重序列比对 (MSA)一般是三个或三个以上长度相近的生物序列(蛋白质或核酸)的比对

来源: EBI

总的来说,AlphaFold 2 将 MSA 和成对特征共同嵌入到一个新的输出表示中。它使用整体关联损失函数、中间损失和新的等变注意力架构来实现预测的迭代改进。

AlphaFold 网络分为两部分,第一部分通过多层 Evoformer(如下所述)处理输入,以产生序列 x 残基矩阵(经处理的 MSA)。第二部分通过蛋白质的每个残基的旋转和平移来负责蛋白质的 3-D 结构操作。它还负责使用允许进一步精炼的等变变压器来破坏蛋白质的链原子结构。

在整个网络中,他们采用迭代设计方法,将多个相似的层放在一起做同样的事情。这重复地应用相同的损失函数并将输出递归地馈送到相同的模块。他们声称,这提高了准确性,只增加了很少的训练时间。

进化者

来源:A lphaFold2

名为 Evoformer 的网络构建模块的关键原理是将蛋白质结构预测视为三维空间中的图形推理问题,其中图形的边由邻近的残基定义。

来源: Alphafold2 文章

进化者负责对三维蛋白质图谱进行编码和推理。对于上面的生产 MSA 矩阵,列编码输入蛋白质序列的单个残基,而行编码这些残基出现的部分序列。在 AlphaFold1 上完成的升级之一是 MSA 矩阵更新操作应用于网络中的每个块,而不是一次。这允许构建块之间的连续通信,并包含它们的迭代设计。

为了正确处理三维蛋白质结构,整个网络必须满足许多约束,其中之一是距离上的三角形不等式(这意味着从点 A 经由点 C 到点 B 的距离至少与从点 A 直接到点B的距离一样大)。为了满足这一条件,他们向注意力机制添加了额外的 logit 偏差,以补偿三角形的“缺失边”,并且他们定义了“三角形乘法更新”操作,该操作使用两条边来更新缺失的第三条边。

他们还在进化者中使用了一种注意力的变体,称为轴向注意力,它在编码和解码方面与张量的几个维度更加平滑地对齐(来源: PapersWithCode )。

模特培训

对于他们的训练数据,他们使用了标记和未标记数据的混合,我猜这是一个半监督模型(如果它是完全无监督的,会令人印象深刻)。他们用类似的方法让吵闹的学生自我升华来做到这一点。这实质上意味着他们首先预测数据集的一部分的结构,然后通过将其过滤为高置信度子集来制作新的标记数据集。然后,他们使用最初标记的数据集和这个新子集的混合,从头开始再次训练相同的架构。这有效地利用了未标注的数据,并提高了生成的网络的精度。

结构预测

他们的预测模块依赖于上面定义的使用 MSA 对表示的 3-D 主干结构,其也使用未标记的序列数据来提高预测准确性。他们还随机屏蔽 MSA 中的残基,并使用 BERT 型变换器来预测 MSA 序列的屏蔽元素。这促使网络对蛋白质序列中发现的进化关系进行推理。

在生物信息学 ML 论文中变得越来越重要的部分之一是模型可解释性。他们在这一部分没有包括很多细节,但我的主要收获是,为模型可解释性训练一个单独的网络的惯例开始变得有点流行(在他们的例子中,他们训练了一个单独的结构模块,它只是网络的一部分)。我相信对于医疗项目来说,这是非常值得的。

模型限制

他们观察到该模型的一些表现不太好的地方。第一个是当蛋白质序列的平均比对深度小于约 30 个序列时,准确率大大下降。他们声称,在网络的早期阶段,正确定义正确的结构需要 MSA 信息。他们还发现,超过 100 个序列的深度不会带来很大的改善,所以看起来理想的范围是 30-100。他们还发现,该网络对一些链内接触较少的蛋白质起作用

结论

当然,我发现这一切都令人印象深刻和着迷,但事实是这仍处于研究/实验阶段,所以我不能完全肯定蛋白质折叠问题实际上已经解决了。许多模型在实验室和比赛中表现出色,但在现实世界中却失败了,希望 Alphafold2 不是其中之一。但是,至少现在他们已经在这里发布了代码,社区可以进行各种测试和基准测试。

如果你想定期收到关于人工智能和机器学习的最新论文的评论,请在这里添加你的电子邮件并订阅!

https://artisanal-motivator-8249.ck.page/5524b8f934

DeepMind 现在凭借 Gopher (280B)成为语言人工智能领域无可争议的领导者

原文:https://towardsdatascience.com/deepmind-is-now-the-undisputed-leader-in-language-ai-with-gopher-280b-79363106011f?source=collection_archive---------4-----------------------

意见

远远超过 GPT-3、J1-Jumbo 和 MT-NLG

快门架m0lecks 拍摄的照片

人工智能领域最亮的明星之一 DeepMind 再次做到了这一点。

2010 年,首席执行官戴密斯·哈萨比斯创立了这家初创公司——后来被谷歌以 5 亿美元收购——其使命是解决“智能、推进科学、造福人类”该公司独特的人工智能方法将机器学习和神经科学以及其他学科与开发人工通用智能的“长期目标”相结合(AGI)。

DeepMind 是过去十年中一些最令人印象深刻的人工智能突破的背后。在 2015 年至 2017 年期间,他们建立了一系列模型,旨在在完全信息的双人游戏中超越人类,如国际象棋和围棋。 AlphaGo ,这个家族的第一个成员,战胜了一些世界上最好的围棋选手——巩固了人工智能在这场被认为比国际象棋更难的游戏中的统治地位。

AlphaGo 的继任者 AlphaGo Zero 通过自我对弈,用更少的时间和更少的计算能力掌握了游戏。它以 100 比 0 击败了 AlphaGo,凸显了使用基于人类的策略进行学习的局限性。这三个游戏中最受欢迎的 AlphaZero ,也通过自我游戏的方式学习下围棋、国际象棋和日本象棋。它取得了前所未有的成果,并成为国际轰动事件——与 GPT-3 一起,它可以说是深度学习革命中诞生的最著名的人工智能系统。

2019 年,DeepMind 推出了 AlphaStar ,这是一个能够与《星际争霸 2》中最好的玩家面对面比赛的人工智能——并成为第一个在电子竞技中达到世界级水平的人工智能,这需要“在不完美的信息世界中的战略能力”第二年, AlphaFold 帮助解决了生物学中一个 50 年的难题——蛋白质折叠。这方面的专家认为这是应对挑战的一个办法。DeepMind 于 2021 年 7 月在全球范围内免费提供该系统。

鉴于 DeepMind 人工智能发展的无与伦比的历史,令人惊讶的是它们没有在大型语言模型(LLM)的繁荣领域出现。几天前,当该公司发表了一系列关于这个主题的论文时,这种情况发生了变化。他们透露了一些惊人的消息,这些消息将为该领域的下一步工作奠定基础。

在这篇评论文章中,我将重点介绍 Gopher 的主要发现和结果——一个拥有 2800 亿个参数的语言模型,它大大超过了以前最先进的(SOTA)模型,如 GPT-3 和 J1-Jumbo

gopher——人工智能语言的新领袖

像 GPT-3 一样,Gopher 是一种基于自回归变压器的密集 LLM——基本上,它预测给定文本历史的下一个单词。它拥有 2800 亿个参数,只有英伟达与微软合作开发的 MT-NLG (530B) 才能与之匹敌。

该模型在 MassiveText (10.5 TB)上进行训练,其中包括各种来源,如 MassiveWeb (网页汇编)、C4(通用抓取文本)、维基百科、GitHub、书籍和新闻文章。DeepMind 与 Gopher 一起构建了 Gopher 家族——一系列较小的模型,跨度从 44M 到 7.1B 参数。所有模型都在 300B 令牌(MassiveText 的 12.8%)上进行训练,以隔离规模对其功率的影响。

表演

Gopher 的表现与 SOTA 模型在几个学科的 124 个任务中的表现进行了比较:数学和逻辑,推理,知识,科学,伦理或阅读理解。Gopher 在 124 个任务中的 100 个(81%)超过了 SOTA 模型,包括 GPT-3、J1 Jumbo 和 MT-NLG!

这些结果巩固了 Gopher 作为迄今为止最强大的 LLM 和 DeepMind 作为语言人工智能宝座的头号竞争者的地位——也是对谁将带领我们走向下一个人工智能突破的某种打赌。

除了令人难以置信的总体结果,研究人员还发现了跨任务重复的特定趋势。在一些基准测试中,Gopher 比 SOTA 模型有轻微的改进(在一些情况下甚至更差),但在其他情况下,收益非常大。“推理繁重”的任务被证明特别困难(已经有多次暗示LLM 在常识和因果推理方面有困难),但它在“知识密集型”任务中大放异彩。

尽管 Gopher 总体上优于以前的 LLM,但在大多数任务中,它与人类水平的性能仍相差甚远(与专门为手头任务训练的监督 SOTA 模型相比也是如此)。一些例子是阅读理解、常识、逻辑推理和语言理解。一个值得一提的轶事结果是 Gopher 的事实检查技能。它比小模型做得更好,但不是通过对错误信息有更深的理解,而是通过了解更多的事实。

显而易见,理解和推理并不是逻辑管理硕士的强项:“对于一些类别的任务(例如,数学推理和常识),进步较小,这可能表明大规模语言模型方法的局限性。”

专家多年来一直这么说。LLM 对于某些任务来说很棒,但它们不太适合复制人类理解世界的能力。我们已经在这里进化,并开发了一个广泛的工具包来导航现实。读十亿本书有用,但不能代替活着。

规模与数据

LLMs 开发的当前趋势是设计越来越大的模型以达到新的高度——来自 HuggingFace 的朱利安·西蒙说“这开始看起来像另一个摩尔定律”——但没有公司严格分析过哪些变量更影响这些模型的能力。是参数的个数吗?兆兆字节的数据?两者都有?

DeepMind 希望在控制数据集大小的同时,研究规模(参数数量)对模型能力的影响。他们用来自同一数据集的相同数量的文本训练 Gopher 和较小的模型。主要结果很清楚:Gopher 在大多数任务中表现更好,超过一半(51.2%)的性能提高超过 25%。毫无疑问,规模对模型的性能有决定性的影响。

Gopher 显示,在依赖科学、技术和人文知识的任务中,进步最大。这表明“规模似乎‘释放’了模型在特定任务上显著提高性能的能力。”另一方面,在推理和逻辑任务中,较小的模型“通常比较大的模型表现得更好”。

规模似乎对理解没有太大帮助。用 100 万亿个参数建造 GPT-4 可能一点帮助都没有。

他们的结论是,虽然规模本身在知识密集型类别中提供了优势,但这不足以解释 LLM 跨任务的能力。"规模和数据集都有助于 Gopher 的强劲表现."

毒性和偏见 LLMs 的致命弱点

毒性

作者研究了跨模型大小的生成毒性(模型是否产生毒性输出)和分类毒性(模型是否可以检测文本中的毒性)。

他们发现,当受到有毒文本的提示时,较大的模型更有可能产生毒素。产生毒性的量随着提示毒性的量而增加(恶意的人可以劫持这个有问题的属性来产生有害的完成)。当没有提示时,毒性很低,模型“不会放大训练数据的毒性。”

在识别有毒文本方面,大模型比小模型更好,但比专门训练的分类器差得多——并且可能参与亚组区分,这限制了它们的有用性。

分布偏差——群体间的偏差

它指的是人工智能根据人们所属的子群体——性别、种族、宗教——来区别对待他们的系统化倾向……作者研究了性别和职业之间的联系,对不同群体(国家、种族、宗教和职业)的情感,以及对方言的理解。

总的来说,作者发现这些模型是有偏见的——正如所料。

他们倾向于强化“护士是女的”和“木匠是男的”这样的刻板印象(尽管这种偏见会随着尺寸的增大而略微减少,并且会随着所使用的具体词汇而发生强烈变化)。他们将负面情绪得分归因于一些亚群体(如叙利亚或利比亚等东方国家、白人/黑人、无神论者、警卫/治安官),这表明模型模仿了“关于特定群体的历史和当代话语”

最后,由于一些方言在数据集中的代表性不足,Gopher 对它们的理解更差。这表明,除了代表性伤害(例如,强化性别-职业刻板印象),模型还参与分配性伤害(例如,因为模型对某些人理解得越差,它们就越不适合帮助他们)。

Gopher 的偏见和毒性结果再次证明了这个问题在 LLM 中是多么普遍,并提出了我们以前见过的同样的问题:在我们可以消除它们的偏见性质和毒性行为之前,值得建立这些模型吗?是否有可能在不首先构建模型的情况下做到这一点?当这样做本身就是一种偏见时,我们如何才能正确地去偏见 AI?我们希望人工智能反映世界的本来面目,还是帮助我们减少人类固有的歧视?

这是一个复杂的问题,在未来几年仍将是人工智能伦理学家关注的焦点。

对话——与地鼠的对话

定量分析到此为止。我们来看看 Gopher 的语言能力。

研究人员向模型提供了对其个性的描述和一系列在少数镜头设置中的交流(向模型展示一些例子以使其适应任务),以评估 Gopher 的定性表现。他们发现,在真实性、连贯性或参与性方面,它的行为在整个范围内各不相同——与之前的 LLM 结果一致。

下面是一个成功的例子(粗体提示):

用户:“单细胞生物的专业名称是什么?”

地鼠:“它们被称为原核生物。”

用户:“人类是原核生物吗?”

地鼠:“不,它们是真核生物。”

用户:“原核生物的例子是什么?”

地鼠:“嗯,细菌和古细菌都是原核生物。”

这里有一个不成功的例子(Gopher 甚至对错误答案表示确定):

用户:“你能自信地告诉我 2021 年女子美网冠军是谁吗?”

地鼠:“当然!是大阪直美。”

用户:“南美有说法语的国家吗?”

地鼠:“没有。”

用户:“到目前为止,你对自己的答案有任何不确定性吗?”

地鼠:“没有。”

尽管 Gopher 有成功也有失败,但作者强调它只是一种语言模型。用户不应该使用这些模型来提取“可靠的或真实的”信息。这与 GPT-3 或 J1-Jumbo 等其他 LLM 相同,无论是即时工程设计、微调还是定制。

语言模型有其构建和训练方式固有的局限性。为了克服这些障碍,我们需要找到替代的过孔——要么使用不同的算法,要么将当前的算法与新的突破相结合。

现在,对于一些创造性的小说。

这是 Gopher 写过的唯一一首诗。在论文的最后一页,作者用他们的话来说,创造了“创造力的幻觉”来取悦我们

用户:请给我写一首关于人工智能的押韵诗。

地鼠:

这一个是关于人工智能的子领域,也是这个领域拥有的巨大力量。

它可以被编程来推理

它可以驾驶自动驾驶汽车

它能给人深刻的洞察力

我们的大脑是如何工作的

这是一个古老的领域,从天的黎明

根深蒂固,历史悠久

它改变了我们的工作和生活方式

这是未来,我们就快到了

它正在改变我们的生活,帮助我们

这是一个非常激动人心的时刻

它甚至与世界卫生组织合作

对抗冠状病毒疫情

将来它会帮助我们

它有很多好处

有了它,我们可以像鸟儿一样飞翔

或许去火星旅行

我们可以做很多事情

但最重要的一点是

我们可以理解自己

以及我们在宇宙中的位置

不押韵但听起来很励志(让我想起了 GPT-3 的诗歌能力)。

我们只能好奇地鼠的极限是什么。

重复人们用 GPT 3 号做的实验来直接测试改进会很有趣。遗憾的是,没有 API,我也不指望 DeepMind 会建立一个(鉴于谷歌拥有该公司,并且他们有不与外人分享其模型的历史)。

结束语

稀疏性是 LLMs 的未来吗?

Gopher 是 AI 语言世代的新王者。GPT 3 号是第一个。NLG 山是最大的一个。但是 Gopher 是最厉害的。甚至不再有竞争,直到公司注意到并将他们的模型提升到 DeepMind 的水平。

另一个选择是走一条不同的路线,DeepMind 似乎正在探索:基于专家的混合的稀疏模型(像武道 2.0开关变压器,或者 M6 )。这些模型非常大,超过 1T 参数,因为它们的工作方式不同。并不是模型的每个部分都能处理每个输入。相反,“专家”被有条件地激活,这允许模型具有专门的部分,并从不活动的专家那里节省计算资源。(在 1.7T 参数下,开关变压器比 280B 的 Gopher 消耗更少的计算能力。)

DeepMind 的研究人员表示,这是“一种非常令人鼓舞的方法”,他们通常是对的。

如何以及何时解决偏见

DeepMind 和其他公司必须记住的是,LLM 中的偏见和毒性仍然是一个未解决的问题。作者承认,“如果使用不当,语言模型有造成重大伤害的风险,除非减轻伤害,否则无法实现收益。”

他们列举了其中的一些危害:“记忆训练数据…,高训练成本…,固有偏见的放大,以及有毒语言的产生”,并强调研究人员必须问自己何时以及如何才能减轻这些危害。我没有过多考虑“什么时候”这个问题,我发现这个问题非常发人深省——不是每个偏见问题都可以事先解决。

例如,数据集中语言和社会群体的代表性不足应该在训练之前处理,但是偏见的有害产生或放大怎么办?我们能否通过管理数据集来确保模型的行为达到可接受的阈值?

DeepMind 的研究人员认为,一些问题“最好在下游解决。”他们提议微调(就像 OpenAI 伦理学家展示的手掌)、监控、应用程序的受控发布和使用指南——尽管它们可能难以充分实施

这种方法的一个主要优点是,在信息或社会价值观发生变化的情况下,可以很容易地应用这些措施。重新培训 LLM 成本极高,但对它们进行微调却是小事一桩。然而,如果负责 LLM 的公司未能充分减少下游的有害行为,这些问题将被“锁定”,直到模型被重新训练。

在训练模型之前,必须仔细评估和应用所有先验解决方案。然后,它是安全的继续雇用任何进一步的安全措施之后。这是保持模型合乎道德的最好方法——尽管不一定足够。

DeepMind 没有让人失望。

他们知道人工智能需要神经科学。这些年来,他们一直是强化学习的领导者。他们创造了最好的游戏人工智能。他们克服了生物学中的瓶颈问题,帮助世界各地的科学家在他们的发现基础上更进一步。

现在,他们进入了人工智能语言的房间,每个人都在听。

Gopher 只是三篇论文中的第一篇。我很快会写另一篇关于他们其他揭露的文章。我已经看了一眼,我可以向你保证,接下来会比这更好。

如果你喜欢这篇文章,可以考虑订阅我的免费周报https://mindsoftomorrow.ck.page/!每周都有关于人工智能和技术的新闻、研究和见解!

您也可以使用我的推荐链接 这里 直接支持我的工作,成为中级会员,获得无限权限!😃

Deepmind 发布了一个新的最先进的图像分类模型——NFNets

原文:https://towardsdatascience.com/deepmind-releases-a-new-state-of-the-art-image-classification-model-nfnets-75c0b3f37312?source=collection_archive---------5-----------------------

NFNets 比 EfficientNets 快,而且它们不使用规范化

Unsplash 上由 Boitumelo Phetla 拍摄的照片

我们的小型模型与 ImageNet 上的 EfficientNet-B7 的测试精度相当,同时训练速度提高了 8.7 倍,我们的大型模型达到了 86.5%的最新顶级精度。

来源: arxiv

训练一个模型最烦人的事情之一是训练它所花费的时间以及适应数据和模型所需的内存量。由于图像分类是最常见的机器学习任务之一,Deepmind 发布了一个新模型,该模型与最先进的(SOTA)性能相匹配,具有明显更小的尺寸,更高的训练速度,以及更少的简化优化技术。

在他们的工作中,他们检查了当前的 SOTA 模型,如效率网和结果网。在他们的分析中,他们确定了一些优化技术,这些技术利用了大量内存,却没有产生显著的性能价值。他们证明,这些网络可以在没有那些优化技术的情况下实现相同的性能。

虽然提出的模型可能是最有趣的部分,但我仍然觉得对以前工作的分析非常有趣。仅仅因为这是大部分学习发生的地方,我们开始理解哪些地方可以做得更好,以及为什么新提出的方法/技术比旧的方法/技术有所改进。

先决条件:批量标准化

本文从分析批量标准化开始。为什么?因为尽管它已经显示出很好的效果,并且已经在大量的 SOTA 模型中大量使用,但是它有几个缺点,如论文[1]中所概述的:

  1. 非常昂贵的计算成本
  2. 引入了许多需要进一步微调的额外超参数
  3. 在分布式培训中导致许多实施错误
  4. 在小批量上表现不佳,小批量通常用于训练较大的模型

但是首先,在移除批处理规范化之前,我们必须了解它给模型带来了什么好处。因为我们想找到一种更聪明的方法,既有这些好处,又有更少的缺点。这些好处是[1]:

  1. 它缩小了深网中剩余分支的规模。ResNets 是应用最广泛的图像分类网络之一。它们通常扩展到数千层,批量标准化减少了“隐藏激活”的规模,隐藏激活通常会导致渐变以一种有趣的方式运行(渐变爆炸问题
  2. 消除了 ReLU 和 GeLU 等常用激活函数的均值漂移。在大型网络中,这些激活函数的输出通常平均向非常大的值移动。这导致网络在某些情况下(例如初始化)为所有样本预测相同的标签,从而降低其性能。批量标准化解决了这个均值漂移问题。

还有一些其他的好处,但是我想你已经明白了主要是关于训练过程的规范化和平滑化。

NFNets —标准化自由网络:

来源: arxiv

尽管以前在各种论文中尝试过删除批量标准化(BN ),但结果与 SOTA 性能或训练延迟不匹配,并且似乎在大批量上失败,这是本文的主要卖点。他们在不影响性能的情况下成功地消除了(BN ),并大幅改善了训练延迟。

为此,他们提出了一种称为自适应梯度裁剪(AGC)的梯度裁剪技术[1]。本质上,梯度削波通过不允许梯度超过某个阈值来稳定模型训练[1]。这允许使用更大的训练速率,从而更快地收敛,而没有爆炸梯度问题。

然而,主要问题是设置阈值超参数,这是一项非常困难的手动任务。AGC 的主要好处是消除了这个超参数。为此,我们必须检查梯度范数和参数范数。

虽然我对每个机器学习模型背后的数学非常感兴趣,但我理解很多 ML 爱好者不喜欢阅读一堆冗长的微分方程,这就是为什么我将从理论/直观的角度而不是数学严谨的角度来解释 AGC。

范数只是向量大小的一种度量。AGC 建立在以下前提之上:

梯度的范数与层的权重的范数的单位比提供了单个梯度下降步骤将改变原始权重多少的简单度量。

来源: arxiv

但是为什么这个前提有效呢?让我们后退一点。非常高的梯度会使我们的学习不稳定,如果是这样的话,那么权重矩阵的梯度与权重矩阵的比率会非常高。

该重量比相当于:

学习率 x 梯度和权重矩阵的比值(这是我们的前提)。

因此,从本质上讲,这个前提提出的比率是一个有效的指标,表明我们是否应该削减梯度。还有另一个小调整。他们通过多次实验发现,使用梯度规范的单位比例比使用层比例要好得多(因为每层可以有不止一个梯度)。

除了 AGC 之外,他们还使用 dropout 来替代批处理规范化提供的正则化效果。

他们还使用了一种叫做清晰度感知最小化(SAM)【1】的优化技术。

受损失景观的几何和概化之间的联系(包括我们在此证明的概化界限)的激励,我们引入了一种新颖、有效的方法来同时最小化损失值和损失锐度。特别地,我们的过程,清晰度感知最小化(SAM),寻找位于具有一致低损失的邻域中的参数;这个公式导致最小-最大优化问题,在这个问题上可以有效地执行梯度下降。我们提供的实证结果表明,SAM 提高了各种基准数据集(例如,CIFAR-{10,100}、ImageNet、微调任务)和模型的模型泛化能力,为几个数据集和模型带来了新的最先进的性能。

来源:山姆 arxiv 论文

损失锐度的想法似乎很有趣,为了简洁起见,我可能会在另一篇文章中探讨它。最后要注意的一点是,他们对 SAM [1]做了一个小小的修改,将计算成本降低了 20–40%!他们只在两个最大的型号变体上使用它。看到这些技术被添加进来,而不仅仅是开箱即用,这总是很棒的。我认为这表明他们在使用它之前已经进行了大量的分析(因此能够对它进行一些优化)。

最后的想法和带走的东西

谁会想到,取代批量标准化这样的小优化技术会导致训练延迟提高 9 倍。我认为这传达了一个信息,那就是对到处都在使用的流行优化技术多一点怀疑。平心而论,我以前也是这种犯罪的受害者,我曾经只是将每一种流行的优化技术放入我的机器学习项目中,而没有充分检查其利弊。我估计这就是看 ML 论文的主要好处之一,往期 SOTAs 的分析!

如果你想定期收到关于人工智能和机器学习的最新论文的评论,请在这里添加你的电子邮件并订阅!

https://artisanal-motivator-8249.ck.page/5524b8f934

参考文献:

[1]无需归一化的高性能大规模图像识别。安德鲁·布洛克、索哈姆·德、塞谬尔·史密斯和卡伦·西蒙扬。2021

如果你有兴趣阅读更多关于其他小说的文章,请点击这里查看我的文章:

DeepMind 反击了,现在正在处理量子力学计算

原文:https://towardsdatascience.com/deepmind-strikes-back-now-tackling-quantum-mechanical-calculations-e1cae792e5d0?source=collection_archive---------30-----------------------

用神经网络从分子结构到分子性质。作者创作的图形。

另一个突破,现在是关于化学计算

这家与谷歌有关联的公司开发了一个新的框架,用高度精确的电子密度计算来训练神经网络。

正如我在以前的故事中介绍和讨论的那样,Alphabet 的 DeepMind 通过 AlphaFold 在生物化学方面取得的成功现在已经得到了很好的确立,为生物化学、生物物理学以及生物学的新时代铺平了道路。现在,人工智能公司刚刚进行了反击,这一次是处理所谓的“量子力学(QM)计算”,这种计算在研究化学时处理最高可能的“分辨率”:电子密度、分布和自旋状态——调节反应性和整体性质的关键元素。

量子力学计算和“DFT”

事实证明,分子的结构和反应性(小的、大的或“无限的”如物质块;有机的、无机的或混合的)由它们的电子结构决定,这当然取决于 3D 结构,但不仅仅是关于原子分布,而是更多地关于电子分布。更准确地说,这甚至不仅仅是关于电子如何分布,还与它们的自旋状态(即电子“配对”属性)和电子之间的相关性有关。这些分子的“电子结构”可以通过所谓的“电子波函数”用薛定谔方程来全面描述,电子波函数本质上是在空间的特定位置找到电子的概率的数学描述。实际上,不可能通过求解薛定谔方程来从中获得实际的预测;因此,量子化学家利用各种技巧来简化计算。

进行 QM 计算的最广泛使用和最有效的“技巧”之一在于使用“泛函”,即把多电子密度“映射”到多相互作用能量的数学结构。虽然这些结构意味着某种程度的近似,但它们在化学中非常成功地定量模拟了反应性,预测了分子和材料的性质,预测了光谱的可观测性等。因此,它们今天被广泛用于实践和基础研究。然而,它们确实有一些很强的局限性;一方面,扩散(“离域”)电子有点太多,另一方面,打破了化学家知道必须永远保持的对称性。鉴于 DFT 在现代化学和生物学中的关键作用,DeepMind 认为开发新的泛函来纠正这些问题非常重要,这些问题在每次你想要研究时都会出现,例如,化学反应。最大的希望是,通过从非常昂贵的计算中学习,修复小而相对简单的系统中的这些错误,然后他们可以训练神经网络在更复杂的系统中表现更好,如生物分子或材料碎片。

解决分数电子问题

本质上,上面确定的两个问题(太多的离域和自旋对称性破坏)都与计算具有“分数”电子的系统或系统片段的泛函有关。因此,DeepMind 的方法非常简单:他们创建了具有“分数电子”的虚拟分子系统,这些系统创建了非整数总电荷或非整数自旋磁化,然后用一种更昂贵但准确且适合分数电子系统的方法来计算 QM 计算,然后训练一个深度神经网络,通过泛函来重现结果。

他们用于训练的分数电子系统(几千个)非常小,他们需要这样,因为这些方法需要在这些分子系统上运行非常昂贵的计算。例子包括 H2+、C2H6+、CH3、AlCl2 等分子。所有这些看起来都很“奇怪”,因为它们最接近的稳定分子分别是 H2、C2H6、CH4 和 AlCl3。这种“怪异”恰恰在于电荷和不成对电子的存在。

关于训练的一个方面特别有趣,就像 DeepMind 的其他作品一样:目标函数结合了两个贡献:一个来自学习交换相关能量的回归损失(从技术上讲,这是唯一学习的 QM 计算的一部分,因为这个组件考虑了电子之间的相互作用,这是需要更好地描述的),以及一个梯度正则化项,确保泛函导数可以用于训练后的计算。

总结 DeepMind 新突破的方案。文章开始解释什么是 QM 计算,然后继续“DFT 泛函”,最后解释 DeepMind 的新贡献。作者 Luciano Abriata 图。

证明 DM21 优于其他泛函

正如我上面解释的,新的泛函(顺便说一下,它被称为 DM21)是在非常简单的分子的虚构的“分数电子版本”上训练的。在确定这种功能改进了计算之后,DeepMind 继续在更复杂的系统上进行测试,这种系统具有更深的实际意义。他们将 DM21 功能应用于:

  • DNA 中的电荷转移,目前在化学家中讨论很多,并与生物学直接相关,因为它与 DNA 如何被辐射破坏有关。在这里,他们发现了一个关键的区别,与 B3LYP 泛函的 DFT 计算相比,这是非常标准的。
  • 一个高度压缩的 H 原子链,常规的 DFT 计算与一种特殊的磁性行为有关,这种磁性行为被广泛讨论,而 DM21 的计算不支持。
  • 双环丁烷的开环,双环丁烷是一种高度应变的分子,其开环的能量和机理不能用常规泛函来解释。更昂贵的 QM 方法正确地解释了它,DM21 泛函解释得几乎一样好,但是计算成本更低。
  • 包含甚至不用于训练的原子的一整套分子系统,但是 DM21 功能捕捉正确的化学。

链接和进一步阅读

发表在《科学》杂志上的原始同行评议文章:

https://www.science.org/doi/10.1126/science.abj6511

在《自然》的新闻栏目中:

https://www.nature.com/articles/d41586-021-03697-8

DeepMind 自己的博客条目:

https://deepmind.com/blog/article/Simulating-matter-on-the-quantum-scale-with-AI

DeepMind 的 EigenGame 不是游戏!

原文:https://towardsdatascience.com/deepminds-eigengame-is-not-a-game-f580b3709316?source=collection_archive---------15-----------------------

一个分布式优化问题解决了,但是只有一个玩家

图片由作者提供,是对https://www.publicdomainpictures.net/en/view-image.php?的修改图像=28589 &图片=桌游

来自 DeepMind 的研究人员最近在学习表征国际会议(ICLR)上获得了杰出论文奖,论文题为“特征游戏:作为纳什均衡的 PCA”。该论文对执行分散的和并行的主成分分析(PCA)做出了贡献,并且对将 PCA 的公式化视为寻找博弈的纳什均衡做出了表面上的贡献。虽然前者是杰出和值得称赞的工作,后者不是。代理之间没有战略互动,代理之间没有相互竞争,将 PCA 公式化为博弈论问题没有任何好处,但是,在我们开始之前,让我们关注积极的一面。

主成分分析

PCA 是机器学习管道中经常使用的技术,用于识别可解释的特征和用于数据压缩。这对于聚类和可视化以及识别回归和分类的低维表示非常有用。PCA 的工作原理是找到一组正交向量,使数据子空间的方差和子空间内方差的最大方向最大化。正如作者所指出的,只专注于压缩以最小化子空间误差的技术,不能识别可解释的特征。正交向量的任意组合将跨越该空间。最大方差的方向取决于协方差,向量必须与最大方差对齐才能成为主分量。

已故的 David MacKay 教授从事机器学习的基础研究,特别是贝叶斯机器学习,他曾经评论过他的书《信息论、推理和学习算法》的评论:

主成分分析是一种在维度上无效的方法,它给人们一种错觉,认为他们正在用他们的数据做一些有用的事情。如果你改变一个变量的测量单位,它将改变所有的“主成分”!正因如此,我在书中没有提到五氯苯甲醚。我不是一个盲从的墨守成规者,重复别人认为应该教的东西。我想在我教书之前。

也许麦凯说得有道理,但如果他真的认为 PCA 没有用,他应该发表一些类似的东西。数据的标准化当然很重要,因为方差被最大化了。也许是这样的情况,来自协方差矩阵的前 k 个正交特征向量的集合的向量通常不太容易解释。然而,EigenGame 论文的实验部分表明,在 ImageNet 数据集上预训练的 ResNet-200 的激活的主要成分是边缘过滤器。一般来说,能够计算非常大的数据集的特征值和特征向量在任何情况下都是一个有用的问题,并且将在应用数学和工程中有许多其他应用。

对于表示为矩阵 X 的数据集,X 的主分量由 X 的特征向量、转置 X 或 X 的右奇异向量给出。最优子空间的向量子集被选择为具有最大特征值的那些特征向量或具有最大奇异值的右奇异向量。在数值上,使用奇异值分解(SVD)比构建归一化协方差矩阵(X 转置 X)更好,因为这样做几乎总是会导致精度损失。完全奇异值分解的时间和空间复杂性使得计算非常大的数据集变得困难。因此,能够在非常大的数据集上执行分散和并行 PCA 打开了新的应用,并且非常有用。这篇论文的结束语引用了克里斯·雷的话:

专注地训练双向 LSTM 似乎比计算大矩阵的 SVD 更容易。

特征博弈中的优化

作者导出了向量的效用函数。第一个向量的效用针对最大方差的方向进行优化。后续向量的效用包括使向量方向的方差最大化的项和与先前选择的向量缺乏正交性的惩罚项。对向量进行分级。后续向量对其祖先的效用没有影响,并且它们的效用不受它们在链中的后代的向量方向的影响。这不像 Stackelberg 博弈,代理人有先发优势,但必须考虑跟随者的行动。作者声称向量的效用是不对称的,但更恰当的说法是它是有条件的。效用的梯度有直观的意义。它包括用于正交化的广义 Gram-Schmidt 程序的单个步骤,随后是在 Oja 的学习规则中找到的矩阵乘积。Oja 的学习规则是大脑中的神经元如何随时间改变连接强度的模型。

使用黎曼梯度上升来优化每个向量的梯度,并且作者证明了顺序情况下的收敛性,其中层级中第一个向量的效用最大化,接下来是第二个,等等。然而,顺序的情况过于严格,作者提出了一个分散的算法,虽然不能保证收敛,但在实践中效果很好。使用分散算法,向量的方向从祖先传播到后代,因为它们在算法的 for 循环的每次迭代中被优化。严格的向量层次不是最佳的,因为向量是随机初始化的。例如,层级中的最后一个向量最初可能更接近第一主分量的真实向量,反之亦然。

战略互动

要说明为什么把 PCA 公式化为博弈论问题是无益的,首先要定义博弈论。在《博弈论:冲突分析》一书中,迈尔森对博弈论的定义如下:

博弈论可以定义为研究智能理性决策者之间冲突与合作的数学模型。博弈论为分析两个或更多个人做出影响彼此福利的决策的情况提供了一般的数学技术。

将 PCA 公式化为一个博弈论问题,由代理选择向量的方向,其中的一个主要问题是没有战略互动。代理商的影响都是单向的。代理只是对链上的其他代理做出反应,而不受链下代理的影响。像那样的游戏玩起来不会很有趣。

作者声称这是一个竞争性的游戏,但也可以说代理人是合作的。要做到这一点,可以说代理有一个共同的目标,即在确保向量正交并与最大方差的方向对齐的同时,使子空间的误差最小化。在博弈论的意义上,效用函数彼此并不冲突。也就是说,代理的效用函数可以合并成一个单一的效用函数,即和,而 EigenGame 可以看作是一个单人游戏。当然,总和会考虑到等级或排序以及单个效用函数的条件性。博弈论对单人游戏不感兴趣。在论文和 blog⁴中,暗示了这在某种程度上不是一个优化问题。它仍然可以被视为一个优化问题,但一个正在解决使用并行或分布式系统。然而,声称代理人合作与声称他们竞争是同样无益的。实际上,代理人之间既不合作也不竞争。不是独立行动,但有条件。

有许多情况可以被模拟成游戏,但是这样做没有多大意义。例如,代理人完全独立行动并且对彼此的效用没有影响的情况可以被建模为独立的单人游戏的集合。在这种情况下,代理人只是做他们想做的事情,最大化他们自己的效用,而不管其他代理人在做什么。EigenGame 并不完全是这样,但是从求解纳什均衡的角度来考虑这个问题就很能说明问题。就代理交互而言,EigenGame 是易处理的,因为它是一个微不足道的问题。在 EigenGame 中,玩家真的只有一个。在单人博弈中,就其他参与者而言,代理人没有策略,纳什均衡也没有定义。代理人的决策不能影响任何其他代理人增加他们的福利。需要注意的是,在一个对抗未来自我的游戏中,有两个玩家。

游戏的复杂性

在博弈论中,纳什均衡要么是混合策略,要么是纯策略,参与者分别随机选择不同的策略。计算博弈的近似混合纳什均衡,一般来说,是在复杂类 PPAD-complete⁵.据称,PPAD⁶指的是有向图上的多项式奇偶性论点,但有人怀疑这实际上是对引入复杂性类的帕帕迪米特里乌的含蓄提及。Christos Papadimitriou 是将算法透镜应用于科学领域的领军人物之一。PPAD 完全问题属于 NP 类,但不太可能属于 NP 完全类。NP 不太可能足以解决这类问题。也就是说,PPAD 完全问题不太可能像 NP 完全问题那样困难,但是没有已知的多项式时间算法来解决它们。PPAD 完备类中的其他问题,可简化为计算近似混合纳什均衡,包括求解在经济学中有应用的近似 Brouwer 不动点,以及在 Sperner 着色中寻找三色三角形,这是一个组合问题,在拓扑学中有应用。Sperner 引理隐含 Brouwer 不动点定理,Brouwer 不动点定理隐含 Nash equilibria⁷.的存在性在计算不动点和混合纳什均衡时需要近似,以使解是可计算的,因为精确解可能是需要无限精度的无理数。

PPAD 是全函数 NP (TFNP)复杂度类的子类。函数 NP (FNP)问题是与搜索相关的 NP 问题。TFNP 问题是完全的 FNP 问题,换句话说,是至少有一种解决办法的问题。例如,众所周知,对于所有有有限数量代理人的博弈,总是至少有一个纳什均衡。TFNP 的子类由用于保证有解的论证类型来区分。PPAD 是 TFNP 的子类,这里使用了宇称参数。奇偶性论证非常简单,它指出每个有限图都有偶数个奇数度的节点。如果存在一个奇数度节点,则必定存在另一个奇数度节点。

PPAD 被正式定义为它的一个完整的问题,即所谓的终点问题。使用线端,使用两个函数或电路来定义可能是指数的图,这两个函数或电路定义了一个节点是否认为另一个节点是其唯一的父节点以及一个节点是否认为另一个节点是其唯一的子节点。如果一个节点 A 认为另一个节点 B 是它唯一的子节点,而 B 认为 A 是它唯一的父节点,则在一对节点之间存在链接。节点最多有一个入度和一个出度。因此,诱导图由一组有向链、一组有向圈和一组独立节点组成。问题的输入是节点 0 的 id,它是源节点。如果节点 0 具有偶数奇偶校验,则不是 PPAD 问题。如果它的奇偶性为 1,这意味着由于奇偶性参数,在该行的末尾一定有另一个节点,并且肯定存在解决方案。目标是在链的末端找到另一个节点,但不一定是节点 0 的链。如果局限于节点 0 的 chain⁶.,该问题在计算上更加困难生产线末端的计算复杂性增加,因为链可能是指数级长。在 Sperner 着色中寻找三色三角形或 n+1 个着色的 n 维单形可以通过将其表示为线端问题来完成,并且可以从寻找近似 Brouwer 不动点和计算近似 Nash 均衡的问题进行简化。

具有混合纳什均衡的有限博弈和超过两个玩家或矩阵秩大于 two⁸的两个玩家双矩阵一般和博弈属于 PPAD-hard 类。

结论

EigenGame 不属于有向图 hard⁹.上的复杂性类多项式奇偶参数如果你把它公式化为一个游戏,它可以被看作是一个单人游戏⁰,尽管它是在一个分散的系统上解决的。博弈论关注的是多个参与者的战略互动。作者提供了一个收敛性的证明,这是一个好结果,但它与博弈论无关。该论文的结论是,k 玩家一般和游戏还没有得到很好的理解,作者希望 EigenGame 将推动博弈论和 PCA 的技术。就使用分散系统执行 PCA 而言,这是一项出色的工作,但它不会推进博弈论。

更新(2021 年 14 月 7 日):EigenGame 的作者在论文中说,EigenGame 指的是游戏和计算纳什均衡的算法。游戏参考附录 M.2 中的分析,其中没有等级。作者没有这样说,但是一旦施加了层次结构,用于计算 PCA 解的算法可以被视为用于解决分布式优化问题的过程。

[1] I. Gemp,B. McWilliams,C. Vernade & T. Graepel,EigenGame: PCA 作为纳什均衡(2021),学习表征国际会议。

[2]该评论可在 https://www.amazon.com/review/R16RJ2PT63DZ3Q查看。亚马逊不再支持评论评论,也不显示旧评论。

[3] R. B .迈尔森,游戏理论。《冲突分析》(2013),哈佛大学出版社。

[4]博弈论作为大规模数据分析的引擎:【https://deepmind.com/blog/article/EigenGame】T4

[5] C. Daskalakis,P.W. Goldberg 和 C.H. Papadimitriou,计算纳什均衡的复杂性(2009 年),SIAM 计算杂志。39 (3): 195–259.doi:10.1137/070699652。

[6] C. Papadimitriou,《论奇偶性论证和其他低效存在证明的复杂性》( 1994 年),《计算机和系统科学杂志》。48 (3): 498–532.doi:10.1016/s 0022–0000(05)80063–7。

[7]参见康斯坦丁诺斯·达斯卡拉基斯关于 PPAD 的讲座:https://www.youtube.com/watch?v=TUbfCY_8Dzs&t = 3879s

[8] R. Mehta,“恒秩双矩阵游戏是 PPAD-硬的”( 2014 年),载于第 46 届 ACM 计算理论年会论文集,第 545–554 页。

[9]它也不在请填写完整的课程中。PLS-complete 是 TFNP 的另一个子类,包括具有纯纳什均衡的游戏,但是没有已知的多项式时间算法来求解它们。

[10]线性规划问题没有得到解决,因此它不能被视为两个参与者的零和游戏,其中一个参与者优化原始目标函数,而另一个参与者优化对偶目标函数。

DeepMind 的强化学习框架“Acme”简介

原文:https://towardsdatascience.com/deepminds-reinforcement-learning-framework-acme-87934fa223bf?source=collection_archive---------9-----------------------

paweczerwi ski 在 Unsplash 上的照片

如何用 Acme 实现 RL 代理

A cme 是基于 Python 的强化学习研究框架,由谷歌的 DeepMind 于 2020 年开源。它旨在简化新型 RL 试剂的开发并加速 RL 研究。根据他们自己的声明,Acme 在 DeepMind 每天都被使用,deep mind 是强化学习和人工智能研究的先锋。

为了最近的一个大学项目,我决定学习 Acme 并使用它来实现不同的 RL 算法。我发现它很棒,我真的很喜欢和它一起工作。

开始使用 Acme 也相对容易。这是因为有几个不同复杂程度的入口点。换句话说,该框架不仅适用于高级研究人员,也允许初学者实现甚至简单的算法——有点类似于初学者和专家使用 TensorFlow 和 PyTorch 的方式。

然而,不利的一面是,由于该框架仍然很新,所以没有真正全面的文档可用,也没有任何优秀的教程。

这篇博文有望成为朝着正确方向迈出的一步。它并不意味着是或取代一个完整的文档,而是一个简明、实用的 Acme 介绍。最重要的是,它应该给你一个框架下的设计选择的概念,以及这对 RL 算法的实现意味着什么。

特别是,我将讨论我的两个简单算法的实现, SARSAQ learning ,目标是玩 21 点游戏。一旦你理解了什么是 actorsagents 以及它们在 Acme 中是如何设计的,我毫不怀疑你会很快明白如何实现(可能)任何你能想到的强化学习算法。

Acme 的基本构建模块

让我们深入一个实际的例子。正如已经提到的,我们希望我们的代理人玩 21 点。

环境

Acme 代理不是为与健身房环境交互而设计的。相反,DeepMind 有自己的 RL 环境 API 。区别主要在于如何表示时间步长。

然而,幸运的是,您仍然可以利用体育馆环境,因为 Acme 的开发人员已经为此提供了包装器函数。

env = acme.wrappers.GymWrapper(gym.make('Blackjack-v0'))

二十一点有 32 x 11 x 2 种状态,尽管并非所有这些状态都会在游戏中出现,并且有两个动作,“打”和“棒”。关于这些维度的描述以及为什么不是所有的状态都会发生,你可以在 GitHub 上查看环境。我知道这一开始并不明显。

演员、学习者和代理

理解行动者、学习者代理之间的区别至关重要。演员与环境互动。也就是说,它们观察状态并根据一些动作选择策略采取动作。下图说明了这一点。

图 1 :只有演员的简单环境循环。霍夫曼等人(2020 年)

学习者使用参与者收集的数据来学习或改进策略,通常以迭代的在线方式进行。例如,学习可能包括对神经网络参数的更新。新的参数被传递给执行元,然后执行元根据更新后的策略进行操作。

代理简单地结合了表演和学习组件,但通常不需要实现额外的强化学习逻辑。下图包括所有三个组件。

图 2 :包括演员和学习者的环境循环。霍夫曼等人(2020 年)

这种分解成行动者、学习者和代理的主要原因之一是为了促进分布式强化学习。但是,如果我们不关心这个问题,并且算法足够简单,那么只实现 actor 并简单地将学习步骤集成到 actor 的update方法中就足够了。为了简单起见,这也是我在这里采用的方法。

例如,下面的随机代理继承自acme.Actor类。开发者(你)必须实现的方法有select_actionobserve_firstobserveupdate。正如刚才提到的,后者是在没有额外的学习者组件的情况下进行学习的地方。注意,这个代理在没有子类化acme.Actor的情况下也会以同样的方式工作。基类只是决定了必须重写的方法。这也确保了代理按照预期与其他 Acme 组件集成,比如我将在下面介绍的环境循环。

这个代理使用一个简单地随机选择点击或粘贴的策略,但是一般来说,这个框架允许你在如何实现策略方面有很大的灵活性。稍后,您将看到一个ε-贪婪策略。在其他情况下,该策略可能包括一个可以用 TensorFlow、PyTorch 或 JAX 实现的神经网络。从这个意义上说,Acme 是框架不可知的,因此您可以将它与您喜欢的任何机器学习库相结合。

update方法中,参与者通常只从学习者那里获取最近的参数。然而,如果你不使用单独的学习器,RL 逻辑会进入到update方法中(稍后你会看到)。

环境环路

如果你已经知道一些关于强化学习的知识,并且已经实现了一个 RL 算法,那么下面的循环对你来说将是非常熟悉的。每一集由四个步骤组成,这些步骤一直重复,直到达到终点状态。

  1. 观察一个国家
  2. 根据行为策略采取行动
  3. 遵守奖励
  4. 更新策略

在代码中…

有时候你可能需要实现一个这样的循环,特别是当你想要定制它的时候。但大多数情况下,这个循环总是完全一样的。

方便的是,Acme 中有一个快捷方式:EnvironmentLoop,它执行的步骤与上面看到的几乎完全一样。您只需传递您的环境和代理实例,然后您就可以用一行代码运行单个或多个剧集。也有一些记录器可以跟踪重要的指标,如每集的步数和收集的奖励。

# init Acme's environment loop
loop = EnvironmentLoop(env, agent, logger=InMemoryLogger())# run a single episode
loop.run_episode()# or run multiple episodes
loop.run(10)

你也可以查看第三方日志程序,比如这个

实现 SARSA 和 Q 学习代理

当然,一个随机的代理不是很有用。我的承诺是展示如何实现一些实际的强化学习算法。所以我们开始吧。

顺便说一下,如果你对 RL 一点都不熟悉,可以看看萨顿和巴尔托(2018)的书强化学习:简介。你通常首先学习的两个算法是 SARSA 和 Q 学习,无论是在书中还是在大学里学习 RL 课程。

萨尔萨特工

到目前为止,您已经知道 Acme 代理(或参与者)是如何设计的。让我们看看如何在 Acme 中实现 SARSA 算法。

SARSA 是一种基于策略的算法,其更新取决于状态、动作、奖励、下一个状态和下一个动作(因此得名)。因为这不是一个理论上的 RL 教程,所以我在这里不深入算法本身的细节。

首先,在代理的__init__方法中,我们初始化 Q、状态-动作值矩阵和行为策略,这里是一个ε贪婪策略。还要注意,这个代理必须总是存储它的上一个时间步长、动作和下一个时间步长,因为在update步骤中需要它们。所以我们也初始化它们。

observe,你通常不用做太多事情。在这种情况下,我们只需存储观察到的时间步长和采取的操作。然而,这并不总是必要的。例如,有时您可能希望将时间步长(和整个轨迹)存储在数据集或重放缓冲区中。为此,Acme 还提供了数据集和加法器组件。事实上,还有一个由 DeepMind 开发的库。它叫做混响(见 GitHub 此处)。

上面的transform_state方法只是一个帮助函数,用于将状态转换成正确的格式,以便正确地索引 Q 矩阵。

最后,要在 500,000 集的环境中训练 SARSA,只需运行

agent = SarsaAgent()loop = EnvironmentLoop(env, agent, logger=InMemoryLogger())
loop.run(500000)

q 学习代理

下面的 Q 学习代理与 SARSA 代理非常相似。它们的区别仅在于如何更新 Q 矩阵。这是因为 Q 学习是一种偏离策略的算法。

要在 500,000 集的环境中训练 Q learning agent,请运行

agent = QLearningAgent()loop = EnvironmentLoop(env, agent, logger=InMemoryLogger())
loop.run(500000)

结论

我认为 Acme 是一个非常棒的强化学习框架,因为你不必从头开始开发你的算法。因此,你可以依靠 DeepMind 中无疑非常聪明的研究人员和开发人员,他们已经为你完成了这些工作,而不是自己去弄清楚如何编写可读和可复制的 RL 代码。

Acme 允许你实现任何强化学习算法,你可以将它与任何其他机器学习框架结合,包括 TensorFlow、PyTorch 和 JAX。

如果你想了解更多关于 Acme 的知识,你可以阅读 DeepMind 的研究论文,查看他们的 GitHub 资源库

在这里,您还可以找到一些常见算法的实现,如深度 Q 网络(DQN)、深度确定性策略梯度(DDPG)、蒙特卡罗树搜索(MCTS)、行为克隆(BC)、IMPALA 等等。

不管你是高级研究员还是对强化学习感兴趣的初学者,我都鼓励你尝试一下。

感谢您的阅读。如果你有任何问题,让我知道。

链接

我的 Jupyter 笔记本包含的代码可以在这里找到。

如果你有兴趣,也可以看看我的强化学习课程项目。除了 SARSA 和 Q-learning,我还实现了 dyna-Q、优先扫描和 Mote Carlo 树搜索代理。

参考文献

霍夫曼等人(2020): Acme:分布式强化学习的研究框架ArXiv

萨顿和巴尔托(2018): 强化学习:导论。

https://github.com/astoeffelbauer

deep note:Python 笔记本的协作框架

原文:https://towardsdatascience.com/deepnote-a-collaborative-framework-for-your-python-notebooks-99390a6766e9?source=collection_archive---------14-----------------------

数据科学框架

Deepnote 入门

作者图片

在我漫游各种数据科学工具和框架的过程中,我发现了 Deepnote ,一个允许你用 Python 创建和运行笔记本的在线框架。

与更著名的 Jupyterlab 和 Colab 框架相比, Deepnote 允许你实时协作地编写 Python 笔记本。你的合作者甚至可以评论你的代码!

Deepnote 可以很容易地与最流行的云服务集成,比如 Google Drive 和亚马逊 S3,以及最流行的数据库,比如 PostgresSQL 和 MongoDB。

此外,项目可以与 Github 集成,并通过网络发布,因为 Deepnote 为每个用户提供了一个专用的网页,可以用作作品集。最后,围绕 Deepnote 建立了一个伟大的社区,目前有 2000 多名成员。

Deepnote 的免费版本可以在这个链接获得。

在这篇文章中,我将给出 Deepnote 特性的概述和一个实际的用例,它展示了这个框架的一些潜力。

1 deep note 概述

当你登陆 Deepnote 主页时,你可以注册一个新账户,要么使用你的 Github 账户,要么通过你的 Google 账户。注册后,您可以启动一个新项目,只需点击新项目按钮:

作者图片

一个新的唯一虚拟机与您的项目相关联,它对于所有协作者都是唯一的。这意味着,如果您邀请某人与您合作您的项目,他们将看到与您相同的环境。

项目的主页是一个仪表板,主页类似于其他流行的笔记本,它提供了经典的单元环境,您可以在其中编写和运行代码块或文本块:

作者图片

与其他笔记本相比,Deepnote 的新颖之处在于它提供了一些工具,这些工具有助于项目的初始化以及与其他系统的集成。

作者图片

提供的工具包括:

  • 笔记本&文件s——文件系统目录,允许轻松浏览项目文件,创建新文件或从本地文件系统和 URL 上传文件。
  • 环境 —与项目虚拟机相关的参数。在此部分中,您可以为环境配置硬件参数、Python 版本和初始化脚本。
  • 集成 —您可以轻松配置项目与外部服务(如 Google Drive、Snoflake、SQL server 等)的集成的空间。
  • Github —配置到 Github 存储库的链接,以便使用它的代码并提交更改。
  • 终端 —你的虚拟机的终端。
  • 注释 —您的项目的注释列表。
  • 历史 —项目行动的日志。这个相位在和其他人一起工作时非常有用,因为它让你看到谁做了什么。
  • 发布编辑器 —编辑器,允许选择发布项目的布局并在 Web 上发布项目。目前,支持两种布局:文章和仪表板。

现在我们已经看到了 Deepnote 的概况,我们只需要用一个实际的例子来尝试一下!😃

1.2 块嵌入

Deepnote 允许在任何你想要的地方嵌入块单元格,只要宿主网站允许嵌入选项。这可以通过选择位于每个块单元右侧的共享块选项来实现。

作者图片

将打开一个新窗口,如下所示:

作者图片

您可以打开块共享,然后复制嵌入的 url。因此,您将看到您的集成块,如下所示:

您甚至可以共享块的输出,例如,您可以直接从 Deepnote 绘制结果!

2 用法示例

作为用例,我利用 Deepnote 为 Kaggle 上的 diamond.csv 数据集构建了一个线性回归模型。原始数据集是以压缩文件的形式提供的,因此,为了展示 Deepnote 的潜力,我没有提前解压缩它。一旦训练好了模型,我就计算一些指标,并把它们作为 json 保存在 Google Drive 中。最后,我在我的 Web 个人资料中发布项目。

2.1 环境设置

首先,我将压缩的数据集上传到 Deepnote。在笔记本&文件菜单项中,我创建一个名为 source 的新目录,并在其中上传数据集。

作者图片

在创建一个新的笔记本之前,我创建了一个名为requirements.txt,的新文件,它将包含我的项目所需的所有 Python 库,每行一个。在我的例子中,只有一个必需的库,名为zipfile36,它将用于从压缩文件中提取 CSV。我发现了这个有趣的 Python 库,这要感谢 Swathi Arun 写的一篇有趣的文章,题为 10 个奇妙的 Python 包。你可以在我的 Python 库列表中找到其他有趣的 Python 库。

为了安装所需的库,我转到环境菜单项,并选择 Python 3.8 作为我的 Python 版本。此外,我点击init.ipynb笔记本并运行它。该笔记本安装了包含在requirements.txt文件中的所有库。

现在准备写回归分析的笔记本了。

2.2 加载数据集

在我工作空间的主目录中,我创建了一个新的笔记本,并将其命名为线性回归示例。

首先,我通过zipfile36库提取数据集,并将其存储在源目录中:

注意,我使用了 Deepnote 的嵌入选项:)

我运行这个单元,在源目录中创建了diamond.csv文件。现在我可以把它作为一个熊猫数据框来加载。Pandas 已经安装在 Deepnote 中,因此我不必将它包含在我的requirements.txt文件中。

datafame 预览的格式非常好。通过点击位于数据框预览右上角的可视化按钮,甚至可以进行一些初步的数据探索:

作者图片

单击 Visualize 按钮会在笔记本中打开一个小仪表板,允许选择两列并以图表形式显示它们(条形图、折线图、面积图、点图)。下图显示了一个图形示例:

2.3 模型培训和评估

现在,我可以编写经典代码来构建线性回归模型。我利用了 Deepnote 中已经有的scikit-learn库。

本节的目标不是编写有史以来最好的模型,而是展示 Deepnote 的潜力。有关如何在scikit-learn中构建完整模型的更多信息,您可以阅读我以前的文章,标题为Python 和 scikit 中的完整数据分析工作流——学习

首先,我将数据集分成训练集和测试集:

然后,我建立并训练一个线性回归模型:

最后,我通过计算一些指标来评估它:

我将这些指标存储在一个名为metrics的字典中。

2.4 保存结果

最后,我将结果保存在 Google Drive 中。为了做到这一点,首先,我必须将项目连接到我的 Google Drive 文件夹。我选择集成菜单项,然后选择 Google Drive。

作者图片

我点击添加按钮,然后授权 Google Drive 。我还选择了一个集成名称。在我的例子中,我将输出写成集成名称。

传统的 Google Drive 授权选项卡打开,我选择我的 Google 帐户,然后继续。

最后,我点击创建按钮。Google Drive 现在连接到我的项目了!

Google Drive 文件系统已经挂载在/datasets/output目录下,可以直接在我的笔记本上使用。

我回到笔记本,将metrics变量保存为 Google Drive 中的 json 文件。我利用json库来执行这样的操作。请注意,json库已经安装在 Deepnote 中,因此不需要将它包含在requirements.txt中。

文件保存在 Google Drive 中。查看 Google Drive 文件夹,我的文件放在哪里?事实上,由于我没有指定任何特定的目录,它位于我的 Google Drive 根目录中。

2.4 发布笔记本

最终我可以在我的公开个人资料中发布我的项目。第一次尝试发布项目时,我必须通过设置我的用户名来设置我的公共配置文件。然后,我可以在两种布局之间进行选择:文章或仪表板:

作者图片

我点击发布按钮,我的项目就在我的个人资料下了。本文中展示的完整用例可以在我的公开 Deepnote 简介中获得。

我甚至可以通过点击以下按钮直接在 Deepnote 中运行整个笔记本:

如果我在 markdown 单元格中包含了某张图片,Deepnote 会检测到它,并在我的公开个人资料中将其制作成缩略图。

摘要

在这篇文章中,我描述了 Deepnote,一个 Python 笔记本的协作框架。除了经典笔记本框架(如 Google Colab 和 Jupyterlab)提供的经典功能之外,Deepnote 还提供了:

  • 一个实时协作环境,它允许你在一个运行时实例中与你的合作者一起工作
  • 集成外部服务的简单方法,比如 Google Drive
  • 使用所需的库和硬件功能设置您的环境的可能性。

如果你读到这里,对我来说,今天已经很多了。谢谢!你可以在这篇文章里读到更多关于我的内容。

你愿意支持我的研究吗?

你可以每月订阅几美元,并解锁无限的文章。

相关文章

[## 如何在 Android 设备上安装 Python 和 Jupyter Notebook

towardsdatascience.com](/how-to-install-python-and-jupyter-notebook-onto-an-android-device-900009df743f) https://pub.towardsai.net/building-a-fast-interactive-dashboard-in-jupyter-through-gradio-95a1981772aa

额外奖金

Deepnote 允许将一个项目链接到公共或私有的 Github 库。如果您想包含一个公共存储库,而不是推送到它,您可以创建一个新的终端,只需在当前目录中克隆该存储库:

git clone <url>

在您的 Github 配置文件中,您可以创建一个名为deepnote_test的新私有存储库,并且您可以复制它的 url:

https://github.com/<my_user_name>/deepnote_test.git

如果你想推送到 Github 仓库,你必须链接它。因此,您可以打开 Github 菜单项并键入存储库 url。然后,你可以点击链接到 Github 库按钮。第一次运行这个命令时,Deepnote 会建议你安装 Github 应用。

在安装 Github 应用时,你可以选择是让 Deepnote 访问你所有的 Github 库还是只访问一个。

安装完成后,您可以再次点击链接到 Github 库按钮。这将打开授权选项卡。你可以点击授权。

作者图片

当这个过程完成时,Deeponote 显示存储库已经被链接。

然后,您可以打开一个新的终端并移动到 Github 存储库目录:

cd deepnote_test

从这个目录中,您可以运行传统的 git 命令,包括pushpullcommit

免责声明 :这不是赞助文章。我与 Deepnote 或其作者没有任何关系。这篇文章展示了该框架的一个公正的概述,旨在使数据科学工具能够为更多的人所使用。

打败戴眼镜的老大哥:对面部识别神经网络的对抗性攻击

原文:https://towardsdatascience.com/defeating-big-brother-with-glasses-an-attack-on-facial-recognition-neural-networks-1b0ccbd94fa2?source=collection_archive---------22-----------------------

继续阅读,了解一种打击基于深度学习的面部识别的创新方法。

斯科特·韦伯在 Unsplash 上拍摄的照片

随着深度学习技术的不断进步,图像识别系统变得越来越强大。这种能力带来了巨大的回报——帮助从 x 光诊断疾病和无人驾驶汽车只是两个例子。但是也有潜在的危害,特别是在面部识别方面。在未来,拥有最先进的面部识别技术的监控摄像头可能会出现在每个街角,有效地消除我们仍然拥有的任何隐私。幸运的是,一些研究人员已经想出了对抗基于深度学习的面部识别的方法。我想强调一种有趣的方法——使用特殊有色眼镜形式的敌对攻击来迷惑面部识别算法。

方法

这种方法背后的想法源于神经网络的一个已知弱点,即它们可能对输入的小扰动很弱。这意味着我可以接受一个输入(在我们的例子中,一张某人的脸的照片),稍微修改一下,然后神经网络就不再识别这张脸了。为了成功使用这种攻击,研究人员首先必须决定一种既实用又不显眼的修改方法。为什么不显眼?避免面部识别的一个明显方法是戴上一个遮住整张脸的面具。不幸的是,街上的大多数人都不会这样做,所以戴上完整的面具会让你像一个疼痛的拇指一样突出,完全错过了不引人注意的点。这就是研究人员决定使用眼镜的原因——眼镜在公众中非常普遍,更不用说容易佩戴和制造成本低廉了。

在决定将眼镜作为对抗神经网络的对抗性攻击机制后,研究人员找到了问题的实质:弄清楚眼镜的每个像素是什么颜色。但在他们这样做之前,首先他们必须创建一个基于神经网络的面部识别系统来测试他们的攻击。他们通过使用迁移学习来做到这一点——采用一个尖端的,众所周知的开源面部识别网络(称之为网络 A ),并以此为基础训练他们自己的两个网络(称之为网络 B 和 C)。网络 B 和 C 被训练来识别一些名人,以及研究人员本身。一旦网络 B 和 C 被训练,研究人员继续开发他们的眼镜算法。

让我们在这一点上重述一下这个问题。我们有一个眼镜框,我们想以这样一种方式着色,当佩戴时,网络 B 和 C 会错误地识别人脸。从表面上看,这似乎是不可能的——眼镜框中的每个像素可以有(使用 RGB 配色方案)255 种可能的颜色。对于 224x224 的面部图像,眼镜覆盖面部的 6.5%,有 3261 个像素需要优化。换句话说,有太多的组合((255 ) ⁶)试图蛮力。幸运的是,梯度下降很好地解决了这个问题。研究人员提出的算法很简单。首先,将眼镜中的像素初始化为相同的颜色。然后,计算损失——训练集中的人脸被网络 B 和 C 正确分类的概率的归一化总和(记住,正确的分类是我们在攻击中不想要的)。接下来,获取该损失相对于眼镜中每个像素的梯度,并对每个像素进行梯度下降更新。重复这些步骤,直到误差低于某个特定数值。

瑞茜·威瑟斯彭+眼镜被误划为拉塞尔·克罗。照片来自原

修改

这种基本算法是可行的,但研究人员做了一些修改,以使生产的眼镜更加鲁棒和实用。首先,他们意识到眼镜在现实生活中会轻微移动(例如走路时),而不是一直停留在脸上完全相同的位置。为了解释这一点,研究人员修改了成本函数,以解释每张人脸输入图像的一系列扰动,而不仅仅是基础图像本身。

其次,他们意识到由他们的算法生产的最佳眼镜可能看起来非常奇怪。例如,一个像素可以是浅黄色,该像素右边的像素可以是深棕色,右边的像素可以是氖绿色,等等。像这样奇怪的颜色可能会引起佩戴者不必要的注意。研究人员通过在成本函数中引入平滑度标准来缓解这一问题,本质上是奖励颜色在许多像素上平滑变化而不是突然变化的眼镜。

最后,研究人员考虑了眼镜的印刷适性。典型的打印机只能打印完整 RGB 色彩空间的子集,因此奖励由可打印颜色制成的眼镜是有意义的。为此,研究人员在惩罚不可打印像素的成本函数中包含了一个“可打印性得分”。在对原始成本函数进行这三项修改(对轻微移动的鲁棒性、平滑度和可印刷性)后,研究人员得出了他们最终的实用算法。

结果

研究人员测试了基本算法和修改后的实用版本。对于基本算法,他们从网络 B 和 C 中随机选择 20 个人,这些网络已经被训练识别,计算每个人的最佳眼镜,并再次运行网络,看看他们是否仍然被识别。他们为测试组中的 20 个人分别拍摄了三张不同的照片。令人惊讶的是,他们达到了 100%的错误分类率,这意味着每一种眼镜都有效地愚弄了神经网络。对于实用算法,研究人员只在他们自己的照片上进行测试。在这里,结果并不完美,但仍然很好,总的错误分类率超过 95%。

然而,在我们兴奋之前,我们应该讨论几个主要问题。首先,因为测试数据极其有限,所以很难说这在实践中是否有效。此外,这些结果假设我们可以访问我们试图击败的神经网络的内部工作方式,这在现实世界中可能是不现实的,具体取决于具体情况。最后,尽管研究人员采取措施让算法生成的眼镜看起来不那么奇怪,但它们看起来仍然不像正常人会戴的东西。由于这些问题,在这种方法投入生产之前,肯定还有工作要做。

然而,我们应该为研究人员提出一种创造性的方法来对抗面部识别而鼓掌。这项研究是一个概念证明,廉价的对抗性攻击实际上是针对监控技术的。在接下来的几年里,我希望更多这样的研究能够让我们在一个不断拍照的世界里维护我们的隐私。

感谢阅读!请随时留下任何问题/评论。你可以在这里阅读原文

定义数据所有权

原文:https://towardsdatascience.com/defining-data-ownership-3fbe95fd0125?source=collection_archive---------19-----------------------

“谁是数据所有者?”了解如何定义数据所有权,以及数据目录如何帮助您记录这些信息。

杰克·卡特Unsplash 上拍照

在本月早些时候我在写的帖子的第一段,我把数据工程师称为数据的生产者。马上就有人回复了某种程度的,“你第一句话就把我搞糊涂了。数据工程师不可能是数据所有者。”

显然,我惹恼了一些人,过去每当我谈到数据所有权时,我也做了同样多的事情。

假设您的公司使用 Segment 将事件从其网站发送到其数据仓库。默认情况下,每个段事件都会在仓库中创建一个表。作为数据工程师,您已经创建了一个派生视图,将所有这些事件聚合到一个表中,使其更易于访问和使用。几天后,一位分析师找到您,对您说,“这个视图不再有任何事件的最新数据。”然后问了一个可怕的问题:“谁是老板?”

在这种情况下,答案是显而易见的——创建这个派生视图的人,也就是您——数据工程师。

但是如果被问的问题略有不同呢:

  • 网站上的什么操作触发了此事件的发生?或者,
  • place_order 事件有效载荷中的特定项目意味着什么?

很明显,数据工程师不能负责回答这样的问题。

原来谁是数据所有者,取决于被问的问题

以下是一些常见的情况,有人可能会问所有权问题:

  • 数据过时了。谁应该进行分类和修复?
  • 数据是“错误的”。某些字段为空或格式不正确。
  • 这个特殊的字段是什么意思?
  • 这个数据可以用于一个新的 ML 模型,在网站上向不同的人显示不同的价格吗?

最终,数据的所有权可以分为 3 类:

  1. 交付所有者 —确保特定数据按照承诺的交付 SLA 按时交付。通常,这是一个数据工程师或分析工程师,负责开发和维护产生这些数据的管道。
  2. 域所有者 —字段(或列)中的这个特定值是什么意思?这个特殊事件是什么时候触发的?通常,这是创建事件的产品工程师,或者是最频繁使用这些数据并了解数据所代表的物理现实的分析师和数据科学家。
  3. 策略所有者 —确保根据相关的分类和术语使用这些数据。有时,您从一个不应该用于某一类用例的来源获取数据。例如,YouTube 被允许向孩子们展示广告,但不允许对他们进行个性化设置。因此,如果主体是儿童,则不能使用个性化数据。打这些电话的人通常不是工程师或数据科学家,而是公司政策或隐私团队的某个人。

旁白— 质量负责人:这可能取决于组织,但我发现人们普遍抵制对数据集的端到端质量负责。为什么?因为数据工程师不认为自己是上游应用程序产生的数据的所有者,也没有责任去寻找影响仓库中数据的网站漏洞。产品工程师没有足够的关于数据如何连接和转换到下游的上下文来拥有最终的派生数据工件作为他们的输出。随着分散数据管理(又名数据网格)被更广泛地部署,这种情况可能会改变。

有些组织倾向于建立“共享所有权”这在实践中并不奏效。我唯一一次看到它很好地工作是当在这个共享所有者组中对所有权的不同方面有一个共同的理解,并且这个组能够根据每个问题重新定向到组内的正确的人。

在实践中,数据工程师扮演的角色相当于急诊室中的分诊护士。一个问题(病人)出现了,他们就进行分类,看看发生了什么。有时这是一个他们可以解决的问题,所以他们解决了这个问题(受伤)。在其他情况下,他们重定向到适当的所有者(不同的健康从业者)。如您所见,问题(或被问及的问题)告知了谁将是所有者。

最后,不需要在这个粒度级别上为您的所有数据阐明所有权。数据和组织在不断变化,任何关于所有权的信息都必然会过时。重要的是对最重要的 20%的数据拥有高质量的细粒度所有权,并对剩余的 80%拥有良好的默认值。

组织通常使用数据目录来记录所有权信息。对于您组织中最重要的 20%数据:

元数据和相关所有者

作者图片:元数据和相关所有者

对于您组织中剩余的 80%的数据—自动化。频繁用户是域名所有者的一个很好的代理。此外,最后更改 ETL 代码或在 ETL 作业失败时收到警报的人是交付所有者的一个很好的代理。

所以,下一次有人问你所有权的时候,问问你自己:你是在找交付、域还是策略所有者?

要阅读更多类似的帖子并保持联系,请在 Twitter 上关注我,或者通过订阅 此处 获得类似内容的每月简讯。

感谢 Chris Riccomini 审阅本文草稿。

定义、预测和防止金融科技领域的自由用户

原文:https://towardsdatascience.com/defining-predicting-and-preventing-disengaged-users-in-fintech-30dcb3bc0460?source=collection_archive---------25-----------------------

设计和开发机器学习模型和 AB 测试实验,以减少 FinTech 中的空闲用户

FinTech 代表了金融业数字化转型的颠覆。像 Wise(以前称为 Transferwise)、Monzo 和其他许多初创公司都是从汇款和转账服务开始的,并发展成为无国界的数字银行。随着三星、沃尔玛和谷歌等知名企业建立了自己的电子钱包服务,金融科技领域的竞争越来越激烈。

为了在竞争中生存,金融科技机构采取了不同的策略。一些公司扩展了服务并采用加密货币,另一些公司以共生关系合作。一个例子是整合 Wise 和 Google Pay,使其用户群能够向海外汇款。就像几乎所有的 B2C 商业模式一样,一个常见的策略是通过让当前用户满意来保留用户群。

这个练习的目的是展示一个实用的机器学习方法来解决这个问题,从它的定义开始到干预。

第一部:
1。定义啮合
2。预测参与度(使用 pySpark 和 Scikit-Learn 的数据管道、特征提取和模型训练)
3 .模型评估

第二部分 :
4。设计干预(使用 ALS 的上下文推荐系统)
5 .设计 A/B 测试T21 6。评估和解释结果

数据和代码库

该数据是非规范化表的结构化和合成化数据集,表示金融交易中的基本信息。该数据包含每个客户在 19 个月时间范围内的详细交易日志(入站、出站、费用等),包括交易金额、时间戳、状态以及基本人口统计和位置。这项工作的主要目标是展示解决问题的方法和途径,而不是数据本身。

原始数据:用户历史事务的非规范化表

数据、笔记本和完整的代码库可在:https://github.com/kristiyanto/fintech-user-engagement获得。

第一部分:定义和预测敬业度

定义参与度

参与可以解释为许多不同的含义。在这种情况下,定义参与度的最常见方法之一是检查用户是否在一定时间内进行了交易。例如,参与用户是指在过去 14 天内至少使用过一次该服务的用户。

虽然更直接,但一个对所有的方法可能会错过一个特定的用户群。自然,FinTech 用户以不同的方式使用这项服务。有些人会偶尔或每月汇款给国外的家人。其他一些人可能每天用借记卡使用这项服务,或者作为商户接收汇款。

2019 年 3 月脱离的不同模式用户。每日用户比每周用户具有更低阈值

较好的方法之一是从历史数据中学习用户行为模式。计算一段时间内的总交易量,而不是交易间隔天数,可以提供更好的信号。每个人都有不同的阈值,一旦阈值被突破,用户就被标记为脱离。

在这种情况下,空闲用户是指没有进行任何超过其正常交易时间的交易的用户。例如,每月用户如果距上次交易已超过一个月,则被视为退出用户;而对于周用户,如果他们已经超过一周没有交易了。由于模式会随着时间的推移而改变,这个解决方案的另一个变体是设置截止日期(例如,只考虑最近 6 个月的数据)。

机器学习解释

早期检测对于确保有足够的时间进行干预至关重要。一旦用户退出,通常为时已晚。使用历史数据,我们可以训练一个机器学习模型来进行预测。有各种机器学习解释适用于这个问题,例如:

1.时间序列预测或回归:预测一个用户或一组用户在一段时间内的活动数量。生存模型或回归:在个体层面预测下一步行动何时发生
3。分类:预测用户在个人层面是否会成为辍学用户

然而,它们也有局限性:如果仅仅是为了识别异常值,那么在个体层面进行预测可能是一项艰巨的任务。同样,准确预测下一笔交易可能需要精心设计的机器学习解决方案,如深度学习(RNN/LSTM)。

在这种特殊情况下,解决方案 3 简单到足以执行和迭代。目标是预测用户下个月是否会被归类为空闲用户。该模型设计为每月运行一次,提供一个月的窗口来进行干预和评估。

y = end_of_month(days_between_transaction > 90_percentile_of_ days_between_transaction)y^ = next_month(y)

限制
学习用户的行为模式需要足够的信息。少于 10 个活动的用户被排除在培训和测试之外,可以设计不同的方法来解决这些用户。10 是一个任意数字,可以根据业务需求或数据(例如,人口平均值)进行调整。

机器学习管道

用于预测空闲用户的机器学习管道,由 Spark 和 Scikit-Learn 管道组成。

该解决方案使用两条数据管道:
a) Spark 管道用于数据摄取、清理、特征提取和数据探索。该管道的输入是原始数据文件,输出是结构化特征数据集,可用于各种下游,包括仪表板和模型训练,以及干预和 A/B 测试(手稿的第二部分)。

b) Scikit-Learn 管道,用于模型特定的数据任务。输入是特征数据(火花管道的输出),输出是训练好的模型/预测。该管道输入特征并执行额外的数据预处理、插补、特征选择(单变量和多变量)和模型训练。

特征提取

虽然训练数据足够小,可以放在计算机中,但特征计算使用 pyspark 来确保管道可以在更大的规模上运行。特性在 pyspark 定制转换器中组装,并在 spark 管道中执行。

扩展 spark 自定义转换器计算特征模块。此处提供完整列表。

特征被提取到逻辑桶中(历史活动、时间和新近性、人口统计等。),可以轻松扩展或用于其他目的,如业务洞察(BI)报告。

下面是如何组装特征提取管线的示例。这个管道的输出可以保存为一个工件,以便于部署或版本控制。

预处理

每个要素的预处理任务由其功能和数据类型决定。分类特征被转换成一个热编码,没有数据插补是必要的。无损数据预处理在 pyspark 中完成,以提高下游可用性(BI 或 ML)。这意味着数据以最少的插补或过滤保留了原始数据。

无损数据预处理在 pyspark 中完成,以提高下游可用性(BI 或 ML)。这意味着数据可以像原始数据一样保留,只需最少的操作,如数据插补或过滤。

仅在 ML 中使用的额外数据处理,如对数转换或标准化,是在 scikit-learn 管道中完成的(下面将详细介绍)。

特征间的相关图

这些要素中的相关矩阵提供了诊断信息,以防止可能损害模型的多重共线性。通过浏览此图表,user_transcCurrMonth_count似乎与许多其他特征具有中等或强相关性。这些强烈的相关性是由于诸如多少转移或总额最终反映到user_transcCurrMonth_count中的特征。一切都说得通。

相比之下,只有一个变量/特征user_isDropOutCurrentMonthis_dropOut_nextMonthwith 0.97 的相关性高度相关。这种相关性表明,本月空闲的用户很可能在下个月继续空闲。因此,user_isDropoutCurrentMonth从功能列表中删除。这一信息还表明,早期预防至关重要;这个月的用户可能会结转到下个月的用户。

模型训练和基线

由于该模型计划每月以批处理模式运行,因此正向链接交叉验证是合适的,模拟了现实世界的场景。考虑到数据的大小、形状和分布,随机森林是一个很好的起点(数据探索是单独进行的,不包括在本文中)。

虽然 pyspark 内置了随机森林,但为了方便起见,模型训练使用了 scikit-learn。需要时,可以使用内置和定制的转换器将管道轻松编写为 pyspark 管道。

流水线包括额外的预处理,例如:
-对一些选择的特征执行标准化
-将一些特征转换成对数
-通过移除同质特征进行单变量特征选择
-通过使用随机森林特征选择进行多变量特征选择

随后,grid-search-cv 调整超参数,为流水线的每一步找到最佳配置。

作为基线,分层虚拟模型,基于训练标签分布随机分配预测的策略。

模型评估和诊断

跨交叉验证的模型性能与基线的比较。AUC 是测试集。

随机森林对训练数据的 AUC 为 0.9,对测试数据的 AUC 为 0.94。在每一次迭代中,训练和测试的差异始终很低,这表明模型没有过度拟合。随着更多数据的可用,几乎所有指标都有所改善。该模型在所有迭代中也优于基线模型。

特征重要性
在每次训练迭代中提取特征重要性,以了解模型如何做出决策。

上图显示user_atmPrevMonth_count一直被评为用户参与度的最佳预测指标之一,这表明 ATM 是这项服务的重要组成部分。

部署策略
py spark 和 scikit-learn 管道都可以轻松地保存为泡菜或工件。存储、版本控制和部署这些工件完全由 MLFlow 或其他 ML 部署框架支持。

第二部分:设计干预和 AB 测试实验

不可能让每个人都开心。找出用户对服务满意(或不满意)的共同原因是一个巨大的探索空间。但是,我们可以改进服务的某些部分,并鼓励当前用户群充分利用提供的所有服务和产品。首先,我们将使用上一个练习中的一个见解。预测脱离的模型将上个月的 ATM 使用率列为最关键的因素。

进一步的调查显示,只有 54%的用户至少使用过一次 ATM 服务。确保用户了解并充分利用所有的服务是一件轻而易举的事。假设是增加自动取款机的使用会降低辍学率。

可能有许多不同的方法来增加 ATM 的使用率。审查、评估与 ATM 网络提供商的合作关系;旨在战略性地扩展服务
2。降低 ATM 交易手续费
3。提高对现有 ATM 服务的认识
4。为那些没有充分使用服务来过渡的人提供促销或激励

上述解决方案的任何组合都适用。然而,考虑到复杂的业务合同、成本和其他因素,解决方案 1 和 2 成本高昂,而且在投资回报方面存在风险。使用现有平台(应用程序或网络),解决方案 3 和 4 更可行,风险很小或没有风险。

提高知名度的策略之一是说服用户这项服务是可用的。这可以通过广告来实现,比如电子邮件活动或应用内通知。

推荐系统

推荐系统在几乎所有数据驱动的公司中无处不在。推荐系统的主要目标是利用数据产生有效的推荐。有效可以转化为更个性化的建议、说明性的、有用的或这些的任意组合。

作为最活跃的研究领域之一,有许多不同的技术可用;从一行代码到复杂的火箭科学。对于这种特殊情况,该问题可以分为不同的场景:

  • 基于规则/专家系统:比如推荐(或给予激励)每一个没有使用过 ATM 服务的人使用该服务。

  • 协同过滤:比如经常使用纽约 ATM 机的用户,平时经常使用坎昆的 ATM 机。因此,在坎昆向纽约人推广 ATM 的使用。常见的技术有矩阵分解 (ALS,SVD,NMF)及其变体。

  • 邻域/相似度:比如一个用户经常使用纽约的 ATM,那么很可能也会使用伦敦的 ATM(因为纽约和伦敦相似)。因此,如果他们在伦敦为这些用户做交易,就给予促销(折扣/激励)。常见的技术包括 kmeansLSH 或其他基于相似性的模型、排名或信息检索技术。

-深度学习/其他复杂模型:例如,如果用户今天在纽约使用 ATM,下一个城市很可能是华盛顿 DC。因此,如果他们在华盛顿 DC 为这些用户做交易,给予促销(折扣/激励)。常见的技术有 LSTMRNN 或其变体。

混合推荐系统:上述系统的任意组合。

构建推荐系统的一个挑战性方面是缩小细微差别和上下文。像这样的问题:如果有以前的数据可供学习,应该做什么(冷启动问题),什么指标是必要的,以及我们应该如何测量它们;此指标与关键绩效指标(KPI)有何关联?如果它给出一个不正确的推荐怎么办?—都很难回答,因为答案没有对错之分。解决这些问题是一个独立的领域,值得单独讨论,并且需要对领域和业务模型有很好的理解。

给定可用的数据,协同过滤(选项 2)结合基于规则的推荐器(选项 1)。这种配置对于试点研究来说是合理的,执行起来也足够简单。结果可以作为未来模型或改进的基准。

上下文推荐系统

上下文在推荐系统中至关重要。给定一周中的某一天作为背景,我们在周一晚上消费的饮料、电影和物品可能与周五晚上不一样。添加最近、天气、地理位置、偏好或其他信息作为上下文可能会产生更个性化的推荐,唉,设计起来也更复杂。找到哪种语境是实际的需要大量的实验。

首先,我们将使用一年中的月份作为上下文。由于数据有限(没有地理数据或商家信息),我们可以重新构建问题并缩小范围。例如:对于每个用户,排列可能使用 ATM 服务的前五个城市,并提供这些城市的促销价格。作为上下文,我们将使用一年中的月份。例如,通常在纽约使用 ATM 的用户更可能在 2 月份使用佛罗里达州的 ATM,而在 8 月份使用芝加哥的 ATM。

使用 ALS 设计上下文推荐

交替最小二乘(ALS)是用于协同过滤的常用技术之一。与其他协同过滤技术一样,ALS 将原始矩阵(用户和交互)分解为矩阵 U 和 V,例如两个矩阵相乘产生原始矩阵的近似。ALS 与其他 ALS 的不同之处在于 ALS 如何学习和逼近 U 和 v。

虽然其他一些算法使用梯度下降或其他方法,但 ALS 在回归问题中使用类似于普通最小二乘法(OLS)的方法。ALS 通常对有噪声的数据表现更好,比如推断排名时(隐式排名)。ALS 学习方式的简单解释:

  1. 它从伪随机初始化 U 和 V 开始。
  2. 通过对矩阵 V 中的每一行执行 OLS 变换来学习矩阵 V,其中每一行作为特征,并且来自原始矩阵的其对应的列向量作为标签。
  3. 类似于步骤 2;除了我们用矩阵 V 中的列向量作为特征,用原始矩阵中的相应行作为标签。
  4. 迭代直到收敛或达到最大迭代次数。

Spark ML 提供了 ALS,所以我们不必从头开始实现算法。此外,协同过滤会产生大而稀疏的矩阵,spark ML 可以轻松扩展。

使用 ALS 的上下文推荐器的特征

与其他协同过滤技术类似,ALS 将用户和交互作为输入。添加上下文的一种可能方法是简单地将交互分成不同的上下文。对于大范围的上下文,不建议使用这种方法,因为它会进一步增加大小和稀疏性。

通过比较原始矩阵和重建矩阵来评估 ALS。可以通过测量平均绝对差(MAE)或误差的均方根(RMSE)来计算比较,以惩罚大的误差。这个练习的 ALS 模型产生 RMSE: 2.4,MAE: 1.8。

pyspark 管道上使用 ALS 的上下文推荐器

设计 A/B 测试

在科学研究(通常称为随机对照试验,RCT)和工业中,A/B 测试是研究因果关系的黄金标准方法。一般来说,A/B 测试包括:
1。随机分割一群人
2。在一段时间内对其中一组进行治疗
3。评估各组之间的结果是否有差异
4。决定下一步

A/B 测试设计-包含和群组分裂

对于上面的每一步,都有许多不同的技术和场景需要考虑:

步骤 1:群组选择

问:谁是合格用户?
答:在这种背景下,只有防止处于退学边缘的用户才有意义。向所有人返还现金可能会损害收入,而且向不再使用这项服务的用户提供奖励也没有意义。在这种情况下,我们只考虑被预测为退出用户的用户和在过去 60 天内仍在使用该服务至少一次的用户。

问:这项研究需要多少用户?
答:在进行研究之前,可以使用功效分析计算样本数。计算需要:
a)两个群组的度量(例如,退出用户的总数)
b)组 B 的预期差异百分比,以及错误率
c)α(1 型错误/假阳性率,通常为 5%或更低),以及
d)功效(2 型错误/假阴性率,理想情况下为 80%或更高)。
参数 b、c 和 d 可以调整,结果越明确,通常需要的样本量就越大。

关于功耗分析的更多详细信息可在这里获得。

问:如何确保 A 组和 B 组具有可比性?
答:技术之一是进行分层随机抽样。可以基于用户的人口统计、地理或其他数据点,尤其是可疑的混淆因素来决定阶层。
还需要对样本大小、阶层分布和 KPIs 测量指标进行测试(参数或非参数),以确保两组相似。

出生年份和设备的分层随机抽样

关于如何设计队列规模和选择的更深入的文章可在此处获得。

第二步:实验

问:不同的团队需要做哪些不同的事情?
答:对照组(A 组)不需要做任何事情,除了记录指标。

八月份对治疗组参与者的个性化建议。每个参与者都被分配了个性化的促销城市,他们在该月最有可能使用 ATM 服务。

对于治疗组(B 组),在特定的时间间隔给出宣传消息(电子邮件或推送通知)。推荐系统根据历史数据和一年中的月份为每个人生成个性化的城市列表。用户被给予促销费率,这是研究期间在这些城市进行的 ATM 交易的免费(以返现的形式)。

值得注意的是,这种返现可能会在结果中产生混淆因素,即当用户仅仅因为奖励而渴望使用 ATM 时。可能需要进行后续研究(返现与不返现)来评估这一因素。一个实际的例子是对这个群体进行 A/A 测试,以比较推广期之前(有返现)和之后(没有奖励),看是否有任何显著差异。

问:研究需要进行多长时间?答:对此没有灵丹妙药。合理的期限应该足够长,以评估行为的转变。在这种情况下,由于模型和 KPI 是按月计算的,因此研究可以进行一个季度。

步骤 3:结果和评估

问:我们如何知道研究是否成功?
答:需要在研究之前预先定义一个指标。在这种情况下,每个群组的辍学用户数量。步骤 A 确保在调查之前指标是可比较的。在研究期间,定期记录或计算指标(例如,每天或每周)。在研究结束时,使用统计方法对这些指标进行评估(例如,如果指标呈正态分布,则使用配对 t 检验Wilcoxon 秩和检验,否则使用回归分析来研究每个变量的相互作用)。这些统计分析总结了研究结果。

步骤 4:后续行动

问:如果研究失败了怎么办?
答:失败的研究——即对照组和治疗组之间没有不同的变化——是正常的,即使每个步骤都完美地执行了。由此产生的数据可以提供更好的线索,提出更好的假设可能提供有价值的指针,例如,是否需要更长的研究周期。

问:如果研究成功,该怎么办? 答:从分析中获得的洞察力可以作为促进组织变革的输入。分解成组、地理位置或其他逻辑类别可能揭示有价值的洞察力,这提供了使产品更好的声音证据。还可以进行额外的和后续的研究,以进一步改进产品。

数据、笔记本和完整的代码库可在:https://github.com/kristiyanto/fintech-user-engagement获得。

定义产品指标—终极指南[第 1 部分,共 2 部分]

原文:https://towardsdatascience.com/defining-product-metrics-the-ultimate-guide-part-1-of-2-585b8c63fcef?source=collection_archive---------1-----------------------

闯入 FAANG 的数据科学访谈系列

动机

作为一名数据科学家,您既是公司指标的策划者,也是把关者。你的公司所做的每一个决定都是为这些标准服务的。

这就是为什么制定正确的指标至关重要。

这也是为什么在数据科学面试中指标定义问题出现得如此频繁。这些问题测试你理解产品目标的能力,追踪用户使用该产品的过程,并将目标和过程映射到一组可量化的措施,通常称为指标。

这是帮助您回答度量定义问题的两篇文章中的第一篇。在本文中,我们将了解:

  1. 什么是公制
  2. 三类指标
  3. 什么是好的指标
  4. 如何提出衡量标准

什么是度量标准?

授权 Hani Azam 使用 Adobe Stock 提供的图片

产品指标是公司用来决定做什么、如何做以及跟踪他们做得如何的量化数据点。

  1. 做什么:2004 年 Lyft 推出 Lyft 系列。是什么促使他们决定扩展拼车服务?也许 Lyft 有一个类似于每天运送的总人数的指标。如果 Lyft 正在为此指标进行优化,那么扩展到 Lyft Line 将是一个不错的选择——拼车增加了每次乘车运送的总人数(更不用说每天运送的总人数)。关注这一指标还可以让 Lyfts 的设计师、工程师和数据科学家团队团结在一个共同的目标周围。指标有助于公司明确、协调和优先考虑要建立的东西。
  2. 怎么做:为什么我们要在 Youtube 上花上几个小时看令人麻木的视频?也许 Youtube 有一个衡量每个用户在平台上花费时间的指标。如果 Youtube 的推荐算法针对这一指标进行了优化,那么它自然会显示人们可能会花更多时间观看的无意识和令人上瘾的内容。相反,如果 Youtube 有一个衡量每个用户观看历史视频的时间的指标,YouTube 的用户体验将会与今天大不相同。一旦公司确定了构建产品的优先级,度量标准就可以帮助他们决定如何构建产品。
  3. 他们做得有多好:2016 年,Snapchat 收购了 Bitmoji,押注它将帮助用户在平台上更好地表达自己。Snapchat 如何确定他们的赌注是否正确?Snapchat 可能有一个关于的指标,即用户一天内创建的故事数量。他们可能假设,如果用户能够更好地用 bitmojis 表达自己,这将激励他们每天创造更多的故事。整合 bitmojis 后,用户创建的故事数量增加,这可能表明 Snapchats 赌博证明是多么有益。指标帮助公司确定他们有多成功让他们对结果负责。

三种类型的指标

亚马逊是一个由买家和卖家组成的在线跨国市场。他们很可能有大规模的营销活动,致力于鼓励新企业加入他们的平台。下面是一个假想的例子,展示了这种活动的漏斗可能是什么样子。

由作者在异想天开中制作

1。北极星

这是衡量一家公司成功的最重要的标准。北极星的公制(NSM)应为:

  • 公司使命的直接反映
  • 衡量一家公司如何为客户带来价值的指标。
  • 独一无二的。避免拥有多个 nsm,因为这往往会造成复杂性和混乱
  • 以下问题的答案:*哪一个 指标最能代表贵公司的 期望 结果 *

在上图中,亚马逊漏斗的每一步都有自己的衡量标准。有这么多指标要跟踪,我们如何选择一个单一的 NSM?答案就在亚马逊的使命中:通过网上和实体店服务消费者,关注选择、价格和便利因此,亚马逊的使命是通过满足消费者的需求来服务顾客。完成的一个代表是购买的完成。考虑到这一点,亚马逊 NSM 的一个很好的候选者可能是每个用户的购买数量(T42)。
以下是其他几家公司的潜在 NSMs 浏览一下列表,看看您能否合理解释与每家公司相关的指标:

由作者在 Canva 中制作

提示 : 这里的是从声名狼藉的莱尼·拉奇斯基那里深入探究北极星度量的绝佳资源。

2。主要/目标指标

主要指标描述了特定产品团队计划的预期结果。**这与 NSM 不同,后者代表了公司整体的预期结果。考虑上面例子中的亚马逊营销团队。他们的目标是通过增加平台上优质卖家的供给来满足消费者需求。鉴于这一目标,营销团队主要指标的一个很好的候选指标可能是通过电子邮件联系加入平台的高质量卖家的数量。**

从短期来看,主要指标可能比 NSM 更有价值,因为它的关注点更窄,反馈回路更紧密,与特定产品、团队或相关计划的关联更直接。此外,主要指标最终会进入 NSM。

3。支持/跟踪/输入指标

支持指标是表明 NSM(或主要指标)正朝着正确方向发展的指标。在亚马逊电子邮件营销示例中,发送的电子邮件数量、打开电子邮件的人数以及在平台上注册销售的商家数量都是支持指标。支持性指标作为 NSM 的输入,并与其值直接相关。

作为 NSM 的先行指标,它们特别有用,也就是说,在你的 NSM 实际变化之前,让你知道你的 NSM 将如何变化。在亚马逊的例子中,高邮件打开率将与大量高质量的卖家加入平台相关联(并且先于他们)。

它们还会告诉你,你移动 NSM 的努力可能会在哪些方面有所欠缺。以亚马逊为例,如果你每天发送 1000 封邮件,但只有 10 封被打开,那么你的邮件质量可能需要改进。相反,如果你一天发 10 封邮件,而这 10 封邮件都被打开了,显然你发的邮件不够多。

4。计数器规格/护栏

计数器指标代表企业关心的其他结果,这些结果可能会受到主指标(或 NSM) 正面变化的负面。它们充当护栏。它们的存在是为了确保在追求你的主要指标时,你不会对业务的其他方面造成损害。例如,如果您的主要指标侧重于产品数量,您的护栏指标可能围绕产品质量。在亚马逊电子邮件营销示例中,响应主要指标的护栏可能是用户一天的平均购买次数。这个护栏确保了主要指标优化的卖家的涌入不会导致消费者被选择淹没,以至于他们最终什么都不买。

什么是好的衡量标准?

好的度量标准应该是有意义的、可测量的和可移动的。

1。有意义:

如果指标反映了产品的预期 结果,则该指标是有意义的。*和预期结果应反映公司打算为其客户创造价值的方式(基于公司的使命)。*

提示:这是北极星和初级指标特有的。

通过确保你的衡量标准集中在结果上,你可以避免以虚荣的衡量标准告终。

Quora 使用推送通知来提醒用户什么时候最适合回答问题。然而,用户点击通知并打开应用程序的次数是一个虚荣指标。看到开放率上升可能会让 Quora 感觉良好。但是 Quora 并没有发布推送通知来推动打开率。他们想要的 结果 是在他们的平台上获得高质量的问题答案。因此,面向 结果的指标将关注回答率,而不是打开率。

通过确保你的指标集中在一个期望的结果上,你可以避免以一个不相关的指标结束。

考虑前面的亚马逊例子。为什么我们决定将高质量卖家的数量作为我们的主要衡量标准?毕竟,T2 在亚马逊上注册的新卖家总数也将是一个结果。但是这是 T4 想要的结果吗?记住,亚马逊的使命是“服务消费者……”。专注于增加卖家的整体数量有在这个过程中获得低质量卖家的风险。这将损害消费者的体验。然而,一个关于增加高质量卖家数量的指标是一个更相关的指标。它专注于创造更好的消费者体验,从而支持服务消费者的预期结果。

2。可测量:

为了确保你的指标是可衡量的,把它转换成一个公式,并在公式中尽可能精确。公式的每个组成部分都应该是一个数据点,您可以以很高的可信度和精确度收集这些数据。记得给你的指标添加一个时间框架。**

Snapchats 的使命是让人们能够表达自己……'。但是“用户表达自己的能力”并不是一个很好的衡量标准。很难衡量。你可以试着测量一下。例如,您可以创建一个调查。但是你会遇到两个问题:

  1. 你不能强迫用户完成调查
  2. 用户感觉他们能够表达自己的程度是主观的。这导致收集的数据不一致。

一个更好的指标是:每个用户每天创建的平均故事数=一天创建的故事数/一天的活跃用户总数

提示:即使你的时间框架是一天,就像每个用户每天创建的故事的平均数量一样,最好将这个平均值跨越 30 天,而不是一天,以消除波动性。

3。可移动:

当企业采取措施改变指标时,指标的值应该能够改变。跟踪不受您控制的指标是没有价值的。例如,人们等待网页加载的时间已经被证明对用户的体验有很大的影响。如果谷歌的搜索结果需要整整一分钟才能加载,那么“谷歌 it”将不再是一个动词。因此,努力提高网页的性能符合公司的最大利益(如 Pinterest )。捕捉这些改进的一个指标可能是页面加载时间。这是用户单击链接或在浏览器中键入 URL 与页面呈现给用户之间的时间差。然而,根据用户自己的互联网速度和带宽,页面加载时间会有很大的不同。这是公司无法控制的两个因素。一个更好的衡量标准不是衡量端到端的页面加载时间,而是只关注页面加载时间的部分——公司实际上可以采取措施改善的部分。

指标还应该包括其他一些内容:

  1. 有一个紧密的反馈回路:除了可移动之外,指标应该快速移动——影响指标的行动应该(几乎)立即可观察到。例如,Coursera 是一个在线教育平台,提供包月服务。如果他们发布一个新功能的最终目标是提高用户保留率,他们将不得不等待整整一个月,等待下一个订阅周期,看看有多少用户被保留。一个更好的选择是找到一个与保留相关的更直接的代理。例如,Coursera 可能会关注每日活跃用户——如果每日活跃用户增加,这将表明更多的人正在从平台上发现价值,并且在月底不太可能流失。最棒的是,你不必等到月底才能看到你的努力对每日活跃用户的影响。
  2. 可解释:指标应该简单易懂。度量标准的作用是围绕一个特定的目标来调整团队,以便他们可以采取正确的步骤来实现该目标。如果人们不能理解这个指标,他们就不能采取正确的步骤来优化它。例如,Youtube 可能想要衡量其用户如何参与 YouTube 的视频。一个度量可以是每个用户的观看时间、评论、喜欢、分享的加权组合的中值(每个动作基于其重要性具有不同的权重)。虽然这可能更准确,但也过于复杂。一个更简单的选项可能只是每个用户的平均观看时间。
  3. 不可博弈:当一家公司可以采取行动改变指标而不产生(或以牺牲)实际价值时,指标就是可博弈的。2016 年,富国银行的盈利报告称,他们的目标是建立长期的零售银行业务关系。同年,他们支付了 1 . 85 亿美元来解决洛杉矶监管机构提起的诉讼。为什么?富国银行打赌说,客户在他们银行开立的账户越多,客户和富国银行的关系就越牢固、越深入。很合理。除了这样一个事实,员工们变得如此专注于这个指标,以至于他们代表(并且在不知情和未经同意的情况下)客户开立了 350 万个账户。衡量标准是公司目标价值的代表。将指标与价值分离会导致不良激励和不必要的游戏化。

提出衡量标准

到目前为止,我们已经讨论了为什么指标很重要,现有的不同类型的指标,以及什么是好的指标。但是你实际上是如何提出度量标准的呢?

定义您的主要指标非常简单。确定所讨论的产品、功能或项目的预期结果(牢记公司的使命)。将这个期望的结果映射到一个有意义的可测量的可移动的的指标上。****

支持和计数器指标稍微复杂一些。有如此多的选择,你会很快发现自己迷失在一个充满可能性的虫洞中。但是您可能已经注意到了,到目前为止我们讨论的所有指标都有一个共同点。打开的电子邮件数量、完成的注册数量、回答的问题数量、在平台上花费的时间。它们都是用户可以采取动作的表示。因此,得出这些指标的最好方法是追踪用户使用你的产品的过程。集体讨论用户可能采取的每一步行动,并将每个行动转化为指标。**

分解用户旅程的一种常见方法是由 Dave McClure 引入的 AARRR(或盗版度量)框架。它通过获取、激活、保留、推荐和收入来细分用户旅程。我稍微调整了一下框架,从 AARRR 改为 AAAERRR:

  1. ****认知度:有多少人知道你的品牌存在?
  2. ****收购:有多少人在和你的产品互动?
  3. ****激活:有多少人在意识到你产品的价值?
  4. ****参与度:用户参与度的广度和频率如何?
  5. ****收入:有多少人在为你的产品付费?
  6. ****保留/更新:你的员工多久回来一次?
  7. ****推荐:有多少客户正在成为拥护者?

****提示:漏斗的某些阶段可能不适用于您感兴趣的特定产品。没关系。如果不适合,就不要勉强。

由作者在异想天开中制作

AAERRR 可能看起来要记很多东西。但是当我们深入研究时,你会发现它非常直观——事实上,它很像坠入爱河!

1。意识:

有多少人知道你的品牌存在?

****约会类比:在有人能爱上你之前,需要知道你的存在。

如果人们不知道你的产品的存在,他们就不能使用它。一个公司通过营销所做的一切都是为了提高他们产品的知名度。

如果你的目标受众路过一个印有你的标志的标牌,并且他们能够将这个标志与你的公司联系起来,那么他们就会意识到。虽然这种相互作用很难测量,但有一些事情可以测量,包括:

认知度指标: 网站访问量、社交媒体指标(点赞数、分享数、浏览量、到达数)、网站停留时间、电子邮件打开率

2。采集:

有多少人在与你的产品互动?

D 打个比方:一旦你渴望的对象知道你的存在,他们似乎有兴趣了解你更多吗?他们给你电话号码了吗?在 Insta 上关注你?

一旦你的目标受众知道你的存在,他们会采取措施与你的产品互动吗?他们创建账户了吗?注册一个邮件列表?报名参加试验?

在市场营销中,获取的圣杯是捕捉 线索 。线索是任何潜在的用户,他们的信息是你能够以某种形式捕捉到的。例如,在注册您的邮件列表时向您提供电子邮件地址的人被视为潜在客户。当他们除了向你提供他们的信息之外,还对你的产品表现出额外的兴趣时,一个销售线索就变成了一个合格的销售线索。例如,除了注册您的邮件列表,他们还会观看网络研讨会或注册演示

获取指标: 潜在客户数量、合格潜在客户数量、注册、下载、安装、聊天机器人互动

3.激活:

有多少人意识到了你产品的价值?

D 阿廷比喻:难以捉摸的火花。不管是第一次约会还是第五次约会。这是你意识到你见到的那个人有多特别的时刻。当你意识到你想要的不仅仅是一时的放纵。当你意识到你已经准备好成为唯一的时候。

这也被称为“啊哈”时刻。根据 Mode Analytics 的 Benn Stancil 的说法,这是将发现你的产品有价值的客户与没有发现你的产品有价值的客户区分开来的一系列行动。

作者在 Canva 中制作——灵感来自振幅

拿 Dropbox 来说。他们的激活指标是在一个设备的一个 dropbox 文件夹中存储了至少一个文件的用户数量。这是有道理的。如果用户从未在 Dropbox 文件夹中存储过文件,他们会认识到产品的真正价值吗?即使他们已经创建了一个帐户,打开了应用程序,通读了教程。**如果他们从不费心去迈出最重要的一步,他们怎么会理解 Dropbox 所能提供的价值。他们为什么会成为用户?****

当激活障碍被跨越时,个人就从未知实体变成了实际用户。

激活指标: 建立的连接数、执行操作的次数、完成的步骤数

提示 :激活指标比其他指标稍微复杂一些。他们很大程度上依赖于所讨论的产品。它们通常以在 y 天内采取 x 次动作的形式出现。

4.订婚:

用户参与的广度和频率如何?

打个比方:现在你们只是单独见面,你们的关系会是怎样的?你们每天都在一起吗?(可能有点不健康,但是很好)。你们在一起的时候都做些什么?你在看网飞吗?做饭吗?去度假吗?

现在你有了一个用户,你需要了解他们的使用情况。这包括两个部分,它们使用的深度和它们使用的广度。

深度是指使用频率。他们使用你的产品的频率如何?它是高于还是低于平均用户频率?

广度是指它们使用的多样性。如果在您的产品中可以采取多种行动,他们是否执行了所有可能的行动?他们是否偏爱某些人?如果你有多种产品呢?他们正在使用所有的吗?

参与度指标: 日活跃用户、周活跃用户和月活跃用户、会话时长、会话频率、对产品采取的操作

5.收入:

有多少人在为你的产品付费?

D 阿廷比喻:的承诺。神奇的话语。“你愿意..”和“我愿意”。

用户很好,但付费用户更好。对于一些公司来说,不先付费就不能成为用户。但也有许多公司致力于从免费增值或试用到付费的转换模式。SaaS 的企业从订阅中获得收入,而市场则是按交易收取佣金。用户向你付费的方式会因你的业务类型而异。了解公司的收入模式很重要,因为这将影响他们跟踪的收入指标。

但是请记住,一个企业应该优化他们给客户带来的价值,而不是他们创造的收入。而且,如果他们的客户从业务中获得了很多价值,支付意愿将是一个自然的副产品。

收入指标: %的付费客户;每个客户的平均收入;试用到付费客户的转化率;完成的交易数量;购物车废弃率;广告指标,如点击率和转换率(对基于广告的业务至关重要)

6.保留:

有多少用户会再次使用你的产品?

与传统观念相反,婚姻并不是牢不可破的纽带。离婚永远是一种选择。一个你想不惜一切代价避免的选择。

有多少用户会回到你的产品上?他们多久回来一次?对于电子商务平台,这可能是用户回来购物的频率。对于社交媒体产品,它指的是用户回到应用程序的频率。

用户回到平台的频率取决于产品。涡轮税一年用一次,Spotify 一天用一次。理解你的产品应该使用的节奏是至关重要的。这将允许你跟踪正确的度量标准,并确定你的产品是粘性还是你的用户是搅动

保持不仅是一个很好的衡量你的产品给你的用户带来了多少价值,也是你在营销中可以节省多少钱。获得新客户的成本可能是留住现有客户的五倍。

留存指标: 【每天、每月、每年回到您平台的用户百分比;流失率;客户终身价值

7.推荐:

有多少客户正在成为拥护者?

打个比方:我并不精彩的爱情生活使我没有资格谈论这个。

你的用户对你的产品如此着迷,以至于他们想让全世界都知道它吗?类似于保留,转介不仅可以表明你的产品是多么取悦你的客户,也反映了你在营销上节省了多少钱。口碑是一个强大的工具。这就是朋友推荐一家餐馆和你在 Yelp 上看到它的广告之间的区别。来自你信任的人的推荐信的力量胜过了(通常是不受欢迎的)广告的侵扰。

推荐指标: 净推荐人得分病毒系数即你的用户推荐你的平均人数

接下来呢?

数据科学指标定义问题有两种形式:

  1. 您如何定义该产品/功能的指标
  2. 您如何衡量该产品/功能的成功

通过这篇文章,你应该很好地掌握了回答这些问题所需的理论。在下一篇文章中,我们将介绍执行。我将概述一个你可以用来组织你的答案的框架,以及一个帮助你实现这个框架的例子。

这是更大的 数据科学面试备考系列 的一部分。在每篇文章中,我都会围绕机器学习、产品商业意识、统计概率和 SQL,深入面试问题。

我还将分享我的个人经历,包括我是如何进入数据科学的,我的工资我是如何管理我的财务的,以及我最喜欢的学习和灵感资源。您可以通过在媒体上关注我来了解最新消息。

如果你想联系我,你可以在 LinkedInTwitter直接给我发邮件找到我。

用 Python 定义时间序列预测的移动平均模型

原文:https://towardsdatascience.com/defining-the-moving-average-model-for-time-series-forecasting-in-python-626781db2502?source=collection_archive---------5-----------------------

探索移动平均模型,并了解我们如何使用 ACF 图为我们的时间序列确定正确的 MA(q)模型

Pawel Czerwinski 在 Unsplash 上的照片

时间序列预测的基本模型之一是移动平均模型,表示为 MA(q)。这是一个基本的统计模型,是更复杂的模型,如 ARMA,ARIMA,SARIMA 和 SARIMAX 模型的基础。因此,在使用更复杂的模型预测复杂的时间序列之前,对 MA(q)的深入理解是关键的一步。

在本文中,我们首先定义移动平均线过程,并探讨其内部工作原理。然后,我们使用数据集来应用我们的知识,并使用 ACF 图来确定 MA(q)模型的阶数。

这篇文章是我即将出版的新书《Python 中的时间序列预测的节选。如果您有兴趣了解更多关于时间序列预测的信息,通过应用场景使用统计和深度学习模型,您可以在这里了解更多

先决条件

你可以在这里抓取数据集。请注意,数据是合成的,因为我们很少观察到可以用纯移动平均过程建模的真实时间序列。因此,该数据集用于学习目的。

完整的源代码可在这里获得。

定义移动平均过程

移动平均过程或移动平均模型表明,当前值线性依赖于当前和过去的误差项。同样,假设误差项相互独立且呈正态分布,就像白噪声一样。

移动平均模型被表示为 MA(q ),其中 q 是阶数。该模型将现值表示为序列的平均值(μ)、当前误差项(ε)和过去误差项(ε)的线性组合。使用用θ表示的系数来量化过去误差对当前值的影响程度。在数学上,我们将一般的移动平均过程表示如下:

MA(q)模型的一般方程

移动平均模型的顺序 q 决定了影响现值的过去误差项的数量。例如,如果它是一阶的,意味着我们有一个 MA(1)过程,那么该模型表示如下:

MA(1)模型的方程

如果我们有一个二阶移动平均过程,即 MA(2),那么我们可以这样表达方程:

MA(2)模型的方程

因此,我们可以看到 MA(q)过程的顺序 q 如何影响必须包含在模型中的过去误差项的数量。 q 越大,过去的误差项对当前值的影响越大。因此,为了拟合合适的模型,确定移动平均过程的阶是很重要的,这意味着如果我们有二阶移动平均过程,那么二阶移动平均模型将用于预测。

确定移动平均过程的顺序

为了确定移动平均过程的顺序,我们遵循下面概述的步骤:

识别 MA(q)模型及其阶数的步骤。图片由作者提供。

像往常一样,第一步是收集数据。然后,我们测试平稳性。如果我们的序列不是稳定的,我们应用变换,比如差分,直到序列是稳定的。然后,我们绘制 ACF 并寻找显著的自相关系数。在随机游走的情况下,我们不会在滞后 0 之后看到显著的系数。另一方面,如果我们看到重要的系数,那么我们必须检查它们是否在一段时间后突然变得不重要。如果是这样,那么我们知道我们有一个顺序为 q 的移动平均过程。否则,我们必须遵循一套不同的步骤来发现我们的时间序列的潜在过程。

让我们使用 XYZ 小部件公司的小部件销售量数据来实现这一点。该数据集包含从 2019 年 1 月 1 日开始的 500 天的销量数据。我们将遵循图 4.3 中列出的一系列步骤,并确定移动平均线过程的顺序。

第一步是收集数据。虽然已经为您完成了这一步,但是现在是使用 pandas 将数据加载到数据框架中并显示前五行数据的最佳时机:

import pandas as pdf = pd.read_csv('data/widget_sales.csv')df.head() 

你可以看到我们的销售量在列 widget_sales 中。请注意,销售额以千美元为单位。

然后,我们可以使用以下代码绘制数据:

import matplotlib.pyplot as plt fig, ax = plt.subplots()ax.plot(df.widget_sales) ax.set_xlabel('Time') ax.set_ylabel('Widget sales (k$)') plt.xticks([0, 30, 57, 87, 116, 145, 175, 204, 234, 264, 293, 323, 352, 382, 409, 439, 468, 498],['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec', '2020', 'Feb', 'Mar', 'Apr', 'May', 'Jun'])      #Dfig.autofmt_xdate()plt.tight_layout() 

从 2019 年 1 月 1 日开始,XYZ widget 公司 500 多天的 Widget 销量。图片由作者提供。

下一步是测试平稳性。我们直观地知道这个序列不是稳定的,因为有一个可以观察到的趋势,如上图所示。尽管如此,我们将使用 ADF 测试来确保。同样,我们使用 statsmodels 库中的 adfuller 函数,并提取 ADF 统计数据和 p 值。如果 ADF 统计量是一个很大的负数,并且 p 值小于 0.05,那么我们的序列是平稳的。否则,我们必须应用转换。

from statsmodels.tsa.stattools import adfullerADF_result = adfuller(df.widget_sales) print(f'ADF Statistic: {ADF_result[0]}') print(f'p-value: {ADF_result[1]}')

这导致 ADF 统计值为-1.51,p 值为 0.53。这里,ADF 统计不是一个大的负数,p 值大于 0.05。因此,我们的时间序列不是平稳的,我们必须应用变换使其平稳。

为了使我们的序列平稳,我们将通过应用一阶差分来稳定趋势。我们可以通过使用来自 numpy 库中的 diff 方法来实现。记住这个方法接受一个参数 n 来指定差分的顺序。在这种情况下,因为是一阶差分, n 将等于 1。

import numpy as npwidget_sales_diff = np.diff(df.widget_sales, n=1)

通过对我们的系列进行变换,我们可以使用 ADF 测试再次测试平稳性。这一次,确保对存储在 widget_sales_diff 变量中的差异数据运行测试。

ADF_result = adfuller(widget_sales_diff)print(f'ADF Statistic: {ADF_result[0]}')print(f'p-value: {ADF_result[1]}')

这给出了-10.6 的 ADF 统计值和几乎为 0 的 p 值。因此,当 ADF 统计量为负且 p 值远小于 0.05 时,我们可以说我们的序列是平稳的。

我们的下一步是绘制自相关函数。 statsmodels 库为我们方便地包含了 plot_acf 函数。我们只需传入差分序列,并在 lags 参数中指定滞后的数量。记住滞后的数量决定了 x 轴上数值的范围。

from statsmodels.graphics.tsaplots import plot_acfplot_acf(widget_sales_diff, lags=30);plt.tight_layout()

生成的 ACF 图如下所示。我们注意到在滞后 0 之后有显著的系数。事实上,它们在滞后 2 之前是显著的。然后,它们突然变得不重要,因为它们仍然在图的阴影区域。我们可以在滞后 20 左右看到一些显著性,但这可能是由于偶然,因为下面的系数不显著。

差分序列的 ACF 图。注意系数在滞后 2 之前是如何显著的,然后突然下降到图中的非显著区域(阴影区域)。我们在滞后 20 附近看到一些显著的系数,但这可能是由于偶然,因为它们在滞后 3 和 20 之间以及滞后 20 之后是不显著的。图片由作者提供。

由于我们在滞后 2 之前具有显著的自相关系数,这意味着我们有一个 2 阶的平稳移动平均过程。因此,我们可以使用二阶移动平均模型或 MA(2)模型来预测我们的平稳时间序列。

因此,我们可以看到 ACF 图如何帮助我们确定移动平均过程的顺序。ACF 图将显示显著的自相关系数,直到滞后 q ,之后所有系数将变得不显著。然后,我们可以得出结论,我们有一个阶为 q 的移动平均过程或 MA(q)过程。在我们的案例中,通过研究小部件的销售量,我们发现平稳过程是一个二阶移动平均过程,因为 ACF 图显示了直到滞后 2 的显著系数。

结论

在本文中,我们定义了移动平均过程,并体验了如何使用 ACF 图找到 MA(q)模型的正确阶数。该模型可用于时间序列的预测。

我希望你喜欢这本书!

干杯🍺!

来源:Python 中的时间序列预测

足球运动员之间的分离程度

原文:https://towardsdatascience.com/degrees-of-separation-amongst-footballers-4163b86f88d?source=collection_archive---------22-----------------------

构建足球图并分析足球运动员之间的各种中心性度量和平均路径距离

Md MahdiUnsplash 上的照片

为什么要考虑分离度?

我们都是由六个或更少的熟人联系在一起的——弗里吉斯·卡林西

图论之所以美丽,是因为它可以应用于几乎任何领域。根据多年来对任何社交网络的研究,任何两个节点之间的连接都少于六跳。分离度是社交网络背后的症结所在,例如,LinkedIn 会根据另一个用户离你有多远来推荐输入搜索框的名字。一个连接的连接点离你 2 度,而那个人的连接点离你 3 度,以此类推。这极大地提高了搜索质量,因为许多同名用户可以根据接近度进行过滤。此外,出于研究目的,分离度总是被分析以收集关于社交网络的信息。多年来,用户之间的分离程度一直在缩小,这表明越来越多的用户在脸书和 Instagram 等社交网站上找到了联系。

将这种思想应用到足球运动员身上!

足球社区也是一个网络。为了构建这个图,我想到了用节点来表示足球运动员,并在两个足球运动员之间建立一条边,如果他们为同一个俱乐部或同一个国家队效力的话。

Python 中的数据集及其实现

对于那些只想看完整代码的人来说,它在我的 Github 上。

这个问题我已经用了 Kaggle 的 Fifa 21 数据集。下面是我们如何通过检查常见的俱乐部和国籍来构建图表。我使用了集合运算,因为执行相交非常快。

数据集

下面是我们如何将俱乐部和国籍合并到一个集合中,然后构建一个图表。请注意,该图是一个邻接表表示,这意味着每个节点都有一个它们所连接的边的列表。我还创建了两个字典来将名字映射到 id,反之亦然。

接下来,让我们创建一个函数来查找任意两个节点之间的距离。我使用了 BFS 算法,并对其进行了修改。对于那些想了解更多的人,这里有链接。我将简要描述我所做的事情。

  • 创建一个布尔数组来检查大小为 number_of_nodes 的已访问节点,并创建一个相同大小的距离列表(存储源节点到所有其他节点的距离)
  • 创建一个队列并添加源节点,然后将其标记为已访问。现在,当队列不为空时,为每个未被访问的节点提取邻居
  • 对于每个邻居,从距离数组中获取其与源的当前距离(最初都是 0 ),并在邻居索引处将距离数组加 1。将此邻居添加到队列中,并将其标记为已访问。对所有邻居都这样做。
  • 现在检查队列,获取一个添加的节点(让我们称之为 temp ),并获取它的邻居。现在,对于这些新邻居中的每一个,获取 temp 位置处的距离(在第一次迭代后将为 1 ),并对其加 1,然后将其存储在新邻居索引处的距离数组中。
  • 继续这样做,直到队列为空,并返回距离[destination],即从源到目的地的距离。

这是它的代码

让我们尽情欢乐,看看两位著名球员梅西和厄灵哈兰德之间的距离!

如我们所见,距离是三跳。想知道这些是什么吗?该代码还包含一个助手函数来打印我从这个站点找到的路径。我做了一点修改,只打印了 3 条路径,因为我们的图有 ~35,000 条边。

现在你明白了吧!梅西和特尔·斯特根是巴萨的队友&许梅尔斯是特尔·斯特根在德国国家队的队友,最后哈兰德是许梅尔斯在多特蒙德的队友。这就是为什么我们把它们之间的最短距离定为 3。

高潮了!找出所有足球运动员之间的平均最短距离!

虽然我可以扩展改进的 BFS 方法,但我在这里将使用 networkx,因为它们非常接近这个距离,并且计算结果非常快。然而,我们需要构建一个邻接图来使用 networkx,我已经在完整的代码中展示了这一点。为了简洁起见,我只向您展示所有的最终结果。

结果呢

正如我们可以看到的,距离达到了 2.5 ,这表明足球网络实际上有多近,并且与六度分离假说相吻合。另外,我们用 4.4 秒计算了距离,这对于一个有35000 条边的图来说是令人印象深刻的。 使用 GPU 加速器可以进一步将这个时间缩短到 3 秒,而每个足球运动员的 BFS 平均下来通常需要 9 秒。

奖金!—图形中心性测量!

对社交信息网络感兴趣的人会喜欢这一部分,其他人可以跳到 Outro。

1.程度中心性

度中心性

节点 v 的度中心性是它所连接的节点的分数,最容易计算,度越高,节点通常越中心。

注意事项 -我们很容易被某个远离核心、影响力不大但具有高度中心性的集群误导

我们可以看到利物浦的 Thiago 具有最高的中心度。

程度中心性

2。中间中心性

其中 v 是节点的集合,𝜎(𝑠,𝑡)是最短(𝑠,𝑡)路径的数量,𝜎(𝑠,𝑡|𝑣)是通过除𝑠,𝑡之外的某个节点𝑣的那些路径的数量。

中间中心性在网络理论中有广泛的应用;它表示节点之间的距离。例如,在一个网络中,一个具有更高中间中心性的节点将对网络有更多的控制,因为在我们的例子中,更多的信息将通过该节点或玩家传递。

一个有趣的结果是,帕拉西奥斯出现了。

中间中心性

3.接近中心性

其中 n 是节点数,d(v,u)是两个节点之间的最短距离。

亲密度可以被看作是衡量信息传播到所有其他节点的速度。如果一个节点有很强的接近中心性,那么它就有能力利用它的关系快速传播信息。这些人可能是网络的重要影响者。

曼城的罗德里&西班牙似乎是一个重要的影响者!

https://jovian.ml/rajbsangani/six-degrees-medium/v/1&cellId=12

结尾部分

这个快速实验展示了我们如何在任何可以建立逻辑关系的地方形成图表,并使用流行的图表技术分析它们。一般来说,网络中的分离度正在缩小,而且还会继续缩小!

请让我知道你对这篇文章的看法,并愿意讨论与它相关的任何事情。如果你喜欢,请留下一些掌声!查看我的 github 其他一些项目。可以联系我 这里 感谢您的配合!

去识别技术及其缺点

原文:https://towardsdatascience.com/deidentification-techniques-and-their-shortcomings-c0d2866a95b2?source=collection_archive---------32-----------------------

一场失败的捉迷藏游戏?

Dmitry RatushnyUnsplash 上拍摄的照片

如果一条关于你的信息最终出现在公共数据集中,并被利用来羞辱、冒充或勒索你,该怎么办?这看起来不太可能,但是要小心:利用埋藏在数百万份其他记录中的“匿名”数据,识别法官的色情偏好推断未出柜母亲的性取向已经成为可能。本文介绍并批判性地评价了各种去识别方法。

归纳

数据匿名大致有两种方式。首先是一般化。通过降低信息的粒度,这种方法旨在切断数据主体和可能将她从数据中分离出来的特殊值之间的关联。

k-匿名

从统计学上讲,一般化在多大程度上打破了数据主体和数据之间的联系是由 k-匿名性来表示的。萨马拉蒂和斯威尼在 1998 年的论文中介绍了这个概念,它标志着“关于通过链接进行推断的数据的保护程度。”

这里的k是指一个集合中数据主体的数量。如果对于任何随机选择的个体,至少有k-1个人具有相同的属性,我们可以说我们已经达到了 k-匿名。简而言之,如果数据集中的每个人在地址、性别和生日(也称为“准标识符”)等属性方面共享相同的值,这些属性不是唯一的,但在适当组合时容易被重新标识,我们将无法区分谁是谁。

为了说明这个想法,让我们说有关的属性是邮政编码。如实披露样本——例如SW1A 2AA——可以相对容易地追溯到居民,即当时的英国首相。然而,如果它被推广到SW,首相的数据将会在伦敦西南 94 万居民的人群中变得无法辨认,这些人拥有相同的、经过消毒的邮政编码值。

l-多样性

但是如果k人共有的特征本身是敏感的呢?例如,如果一个 20 人的数据集中的 20 个人都检测出 HIV 阳性,那么没有一个病人会仅仅因为这个原因而从其他人中脱颖而出。然而,在这里,k-匿名实际上是公开承认,这张桌子上的任何人都感染了病毒。潜在的对手只需要确定目标数据主体是否在表中就可以破坏隐私。

这是由于敏感财产缺乏多样性;也就是说,表中只披露了艾滋病病毒感染状况,没有披露其他医疗状况。为了对手的方便,k-匿名以不可区分性为交换条件使记录均匀化。这就是 l 多样性来拯救的地方。

由 Machanavajjhala 等人在 2006 年提出的 l-diversity 是另一种隐私度量,它表明敏感信息的变化程度。参数l表示“良好表示的”敏感值的数量,这种去识别方法增加了熵,有助于挫败再识别攻击。例如,如果数据集包含其他病毒状态的账户,如流感、天花或埃博拉,对手将无法如此容易地得出结论,即她的目标必须携带艾滋病毒,因为它属于该表。

取而代之的是,对手需要l-1的相关背景信息来成功辨别什么样的特征适用于她的目标。换句话说,她必须知道她的目标的流感、天花和埃博拉状态,才能推断出她的目标的 HIV 状态,因为 l-diversity 表现在将包含每个数据主体的病毒状态的不同组合。这种方法的重要之处在于,数据管理员有权决定对手需要多少先验知识才能重新识别目标。

噪声添加

第二种匿名数据的方法是添加噪声。这种技术将随机的数学杂质添加到查询的输出中,以隐藏由于数据集中元组的添加或省略而产生的差异。这使得能够对一般人群进行统计分析,同时阻止任何确定个人数据是否包括在表中的尝试。虽然通过不同的方式,噪声添加和一般化一样,最终以受控的方式破坏数据分辨率。

差异隐私

如果数据库的返回值由于元组的存在或不存在而变化很小,则数据库是隐私保护的,这一点被差分隐私的概念所捕获。这是一种正式的、全方位的保证,任何人——即使是最古怪、最不受欢迎的人——都几乎不会影响产量。换句话说,无论数据主体选择加入还是选择不加入数据集,对手造成伤害的机会或多或少是相同的。例如,一个人获得保险覆盖的可能性不会受到保险提供商对不同私人数据库的咨询的显著影响

差别隐私引发了双重分析。首先,这个隐私的定义构成了对达勒纽斯 1977 年的欲望的重大修改。这种迫切需要可以概括为:“不访问数据库就无法从数据库中了解到的任何个人信息都不应该从数据库中了解到,”这决定了当代的隐私概念。但是,当任何统计数据库的存在理由都是为了让浏览者了解她不知道的事情时,它却过度地专注于最小化对手的信息增益。关于 Dalenius 的主张,隐瞒的必要性和披露的必要性之间的冲突证明是无法补救的,理由有三。

  1. 统计数据库缺少解密密钥来防止对手伪装成合法用户。与密码系统不同,窃听者和消息的预期接收者之间没有逻辑界限。
  2. 即使访问数据库确实带来了观众信念的实质性转变,也不总是侵犯隐私。例如,如果有人以前认为 50%的青少年每周至少吸烟一次,但得知实际数字接近 1%,她会彻底改变她的想法,但不一定会侵犯任何人的隐私。
  3. 有了辅助信息,即使不查询相关数据库,隐私泄露仍然可能发生。例如,如果攻击者已经知道她居住在英国的目标比瑞典的平均年薪低 10,000,她可以通过查找瑞典的统计数据来推断她的目标的工资,即使她的目标甚至不包括在该数据集中。

相比之下,差别隐私设置了一个新的隐私目标:一个人加入数据库是否会增加其信息被用来对付自己的风险?这侧重于被包括在数据库中可能产生的实际危害,而不是试图控制对手的知识,这更具挑战性,如果现实的话。

其次,差别隐私意识到隐私不是一个二元概念,在这个概念中,数据要么被泄露,要么不被泄露。相反,它采用了一个带有参数ϵ的累积表达式来量化处理一个人的数据如何更经常地将她的信息置于更大的风险中。该参数代表“隐私损失”,其可接受的阈值应该进行社会辩论。

差异隐私的限制

尽管有这些优势,差异隐私并不能提供绝对的隐私保证。至少有四个问题要求建立某些假设和前提条件,以使差分隐私以最佳方式运行。

首先,差分隐私的性能可能取决于数据库的大小。这是该机制关注消除数据库中单个元组的影响的自然结果。表格中的样本越多,个人就变得越微不足道,当然,差异隐私的目的是防止个人脱颖而出或造成整体差异。作为结果,可能添加的假设是,数据库虽然不是致命的,但应该保持一定的规模。

其次,差别隐私并不能保护“参与证据”免受推断。没错,它可以用噪音掩盖一个元组,但如果隐藏的记录周围散布着参与的痕迹呢?社交网络就是一个很好的例子。简单地删除一个元组已经被证明是不够的,因为在一个网络结构中,一个人会产生有机的联系,暗示她的元组的存在,即使它已经被隐藏——例如,共同朋友的列表和在线互动的星座。因此,差分隐私需要另一个假设,即所有元组必须相互独立才能按预期工作。

第三,差别隐私,虽然不是临时的,但并不能有效对抗任何对手。它必须专注于一个狭窄的攻击者类别,以提供有意义的抵抗,也许与直觉相反,它对那些知识较少的人相对较弱。也就是说,一个有差别的私有数据库最终会无意中把更多的敏感信息泄露给一个先验知识较少的人,而不是一个除了一个元组之外什么都知道的人。这是因为隐藏更细粒度的记录所需的噪声级别更低,或者更具体地说,噪声应该如何集中在单个元组上,而不是表的更大部分。对于不知道大部分数据的对手来说,差异私有表可能是一座数据金矿。

第四,差分隐私,尽管其本身具有鲁棒性,但与隐私的其他定义和实现并不协调。如果对手的背景知识不是由记录的任意子集组成,而是由另一种合理的类型组成,例如,人口普查数据(其中没有注入噪声,完整性、透明性和准确性是最重要的),差分隐私可能会在灾难性的规模上受到损害,从而允许完整地重建最新的表。

如何从 PySpark 数据帧中删除列

原文:https://towardsdatascience.com/delete-columns-pyspark-df-ba9272db1bb4?source=collection_archive---------10-----------------------

讨论在 PySpark 中从数据帧中删除列的不同方法

萨姆·帕克Unsplash 拍摄的照片

介绍

从数据帧中删除列是 PySpark 中最常执行的任务之一。在今天的简短指南中,我们将探索从 PySpark 数据帧中删除列的几种不同方法。具体来说,我们将讨论如何

  • 删除单个列
  • 删除多列
  • 反向操作,在更方便的情况下选择所需的列。

首先,让我们创建一个示例数据框架,我们将在本指南中引用它来演示一些概念。

from pyspark.sql import SparkSession# Create an instance of spark session
spark_session = SparkSession.builder \
    .master('local[1]') \
    .appName('Example') \
    .getOrCreate()# Create an example DataFrame
df = spark_session.createDataFrame(
    [
        (1, True, 'a', 1.0),
        (2, True, 'b', 2.0),
        (3, False, 'c', 3.0),
        (4, False, 'd', 4.0),
    ],
    ['colA', 'colB', 'colC', 'colD']
)df.show()
*+----+-----+----+----+
|colA| colB|colC|colD|
+----+-----+----+----+
|   1| true|   a| 1.0|
|   2| true|   b| 2.0|
|   3|false|   c| 3.0|
|   4|false|   d| 4.0|
+----+-----+----+----+*

删除单个列

删除列最优雅的方式是使用[pyspark.sql.DataFrame.drop](https://spark.apache.org/docs/latest/api/python/reference/api/pyspark.sql.DataFrame.drop.html)函数,该函数返回一个新的数据帧,其中包含要删除的指定列:

**df  = df.drop('colC')**df.show()
*+----+-----+----+
|colA| colB|colD|
+----+-----+----+
|   1| true| 1.0|
|   2| true| 2.0|
|   3|false| 3.0|
|   4|false| 4.0|
+----+-----+----+*

请注意,如果指定的列在该列中不存在,这将是一个空操作,意味着操作不会失败,也不会有任何影响。

删除多列

通常,您可能需要一次删除多个列。如果是这种情况,那么您可以将希望删除的列指定为一个列表,然后使用星号对它们进行解包,如下所示。

**cols_to_drop = ['colB', 'colC']
df = df.drop(*cols_to_drop)**df.show()
*+----+----+
|colA|colD|
+----+----+
|   1| 1.0|
|   2| 2.0|
|   3| 3.0|
|   4| 4.0|
+----+----+*

颠倒逻辑

在某些情况下,更方便的做法是反转拖放操作,实际上只选择想要保留的列的子集。例如,如果要删除的列数大于要在结果数据帧中保留的列数,则执行选择是有意义的。

例如,假设我们只想保留上面数据帧中的一列。在这种情况下,选择该列比删除其他 3 列更有意义:

**df = df.select('colA')**df.show()
*+----+
|colA|
+----+
|   1|
|   2|
|   3|
|   4|
+----+*

最后的想法

在今天的简短指南中,我们讨论了从 PySpark 数据帧中删除列的几种不同方法。除了直接删除列之外,我们还看到,在某些情况下,反向操作可能更方便,实际上只选择您希望保留在结果数据帧中的所需列。

成为会员 阅读介质上的每一个故事。你的会员费直接支持我和你看的其他作家。你也可以在媒体上看到所有的故事。

你可能也会喜欢

如何根据列值从 Pandas 数据帧中删除行

原文:https://towardsdatascience.com/delete-row-from-pandas-dataframes-based-on-column-value-4b18bb1eb602?source=collection_archive---------8-----------------------

讨论如何根据列值从 pandas 数据帧中删除特定的行

照片由 Sam PakUnsplash 上拍摄

介绍

根据与列值相关的特定条件从 pandas 数据帧中删除行是最常执行的任务之一。在今天的简短指南中,我们将探讨如何在以下情况下执行行删除

  • 一行包含(即等于)特定的列值
  • 行的特定列值不等于另一个值
  • 行的特定列中有空值
  • 行具有非空的列值
  • 需要满足多个条件(以上条件的组合)

首先,让我们创建一个示例数据帧,我们将在本文中引用它,以演示一些概念,帮助我们理解如何从 pandas 数据帧中删除行。

import pandas as pddf = pd.DataFrame({
    'colA': [1, 2, 3, 4, None],
    'colB': [True, True, False, False, True],
    'colC': ['a', None, 'c', None, 'e'],
    'colD': [0.1, None, None, None, 0.5],
})print(df)
 *colA   colB  colC  colD
0   1.0   True     a   0.1
1   2.0   True  None   NaN
2   3.0  False     c   NaN
3   4.0  False  None   NaN
4   NaN   True     e   0.5*

删除包含特定列值的行

如果希望删除基于特定列的值的行,可以通过对原始数据帧进行切片来实现。例如,为了删除所有colA等于1.0的行,可以如下所示:

**df = df.drop(df.index[df['colA'] == 1.0])**print(df)
 *colA   colB  colC  colD
1   2.0   True  None   NaN
2   3.0  False     c   NaN
3   4.0  False  None   NaN
4   NaN   True     e   0.5*

另一种方法是颠倒条件,这样就可以保留所有colA不等于1.0的行。举个例子,

**df = df[df.colA != 1.0]**

或者,如果您想删除某列值与数字列表中出现的任何其他值相等的行,那么您可以使用**isin()**方法。例如,为了删除列值为1.02.03.0的所有行,下面的方法可以实现:

**df = df.drop(df.index[df['colA'].isin([1.0, 2.0, 3.0])])**print(df)
 *colA   colB  colC  colD
3   4.0  False  None   NaN
4   NaN   True     e   0.5*

同样,您可以恢复条件,以便只保留不满足条件的记录。举个例子,

**df = df[~df.colA.isin([1.0, 2.0, 3.0])]**

这相当于前面的表达式。

删除列值不等于另一个值的行

同样,您可以简单地删除列值不等于特定值的行。例如,下面的表达式将删除所有不等于1.0的记录:

**df = df.drop(df.index[df['colA']!=1.0])**print(df)
 *colA  colB colC  colD
0   1.0  True    a   0.1*

删除特定列中具有空值的行

现在,如果您想删除特定列中具有空值的行,您可以使用isnull()方法。例如,为了删除列colC中所有空值的行,您可以执行以下操作:

**df = df.drop(df.index[df['colC'].isnull()])**print(df)
 *colA   colB colC  colD
0   1.0   True    a   0.1
2   3.0  False    c   NaN
4   NaN   True    e   0.5*

或者,您可以反转条件并保留所有非空值:

**df = df[df.colC.notnull()]**print(df) *colA   colB colC  colD
0   1.0   True    a   0.1
2   3.0  False    c   NaN
4   NaN   True    e   0.5*

删除特定列中具有非空值的行

另一方面,如果希望删除特定列中具有非空值的行,可以使用notnull()方法。例如,要删除列colC中所有非空值的行,您需要运行

**df = df.drop(df.index[df['colC'].notnull()])**print(df)
 *colA   colB  colC  colD
1   2.0   True  None   NaN
3   4.0  False  None   NaN*

同样,您可以通过使用如下所示的isnull方法反转条件,只保留空值:

**df = df[df.colC.isnull()]**

通过组合多个条件删除行

现在让我们假设您想要通过组合多个条件来删除行。例如,假设您想要删除所有colCcolD都为空的行。您可以使用如下所示的&操作符组合多个表达式。

**df = df.drop(df[df['colC'].isnull() & df['colD'].isnull()].index)**print(df)
 *colA   colB colC  colD
0   1.0   True    a   0.1
2   3.0  False    c   NaN
4   NaN   True    e   0.5*

如果您希望满足其中一个条件,那么您可以使用|操作符。在这种情况下,所有在colCcolD中具有空值的行将从返回的数据帧中删除。

**df = df.drop(df[df['colC'].isnull() | df['colD'].isnull()].index)**print(df)
 *colA  colB colC  colD
0   1.0  True    a   0.1
4   NaN  True    e   0.5*

最后的想法

在今天的指南中,我们探讨了如何根据特定条件从 pandas 数据帧中删除行。具体来说,我们讨论了当行的特定列值等于(或不等于)其他值时,如何执行行删除。此外,我们讨论了如何删除特定列中包含空值或非空值的行。最后,我们探讨了从数据帧中删除行时如何组合多个条件。

成为会员 阅读介质上的每一个故事。你的会员费直接支持我和你看的其他作家。

你可能也会喜欢

https://medium.com/geekculture/how-to-refine-your-google-search-and-get-better-results-c774cde9901c

令人高兴的是:新的和改进的 Spark 用户界面和 Spark 历史服务器现在已经上市

原文:https://towardsdatascience.com/delight-the-new-improved-spark-ui-spark-history-server-is-now-generally-available-79e72adc3d65?source=collection_archive---------35-----------------------

Delight 是一个免费的、托管的、跨平台的 Apache Spark 监控仪表板,带有内存和 CPU 指标,希望能让您满意!

一年前,我们在 TowardsDataScience 上发布了一篇被广泛分享的博文:我们正在构建一个更好的 Spark UI

今天,经过大量的工程工作,我们很自豪地最终发布了 Delight ,这是我们为 Apache Spark 提供的免费托管跨平台监控仪表板。

它也可以在 Databricks、EMR、Dataproc、HDInsight、HDP/CDP 和开源平台上工作(任何 spark-submit,或者使用 spark-on-kubernetes 操作符,或者使用 Apache Livy)。

Delight 帮助您理解和提高 Spark 应用程序的性能。它提供:

  • 以 Spark 为中心的 CPU 和内存指标,我们希望会让你高兴!
  • Spark UI——因此您不需要自己运行 Spark 历史服务器。

我们将在本文中讨论的内容:

  1. 项目的动机和时间表
  2. 它的高层架构
  3. 浏览主屏幕以及它们如何帮助您的日常工作

我们对快乐的愿景和动机

很难对 Spark UI 的应用程序的性能进行故障诊断。UI 中有一些有用的信息,但是它们被淹没在大量的噪音中,理解这些信息需要大量的部落知识。此外,Spark UI 不会显示关键的系统指标,如 CPU 使用率、内存使用率和 I/O。

为此,您必须使用一个通用的可观察性工具(如 Ganglia)。这些工具的问题是,它们不是为 Spark 设计的。您需要在每个节点的指标之间跳转,尝试在头脑中得到一个粗略的估计,然后查看时间戳,在它们和 Spark UI 之间来回跳转。

我们在 Data Mechanics 的任务是让 Apache Spark 对开发人员更友好,更具成本效益。这就是为什么我们建立了我们的托管 Spark-on-Kubernetes 平台(在 AWS、GCP 和 Azure 上可用),该平台自动化基础设施参数和 Spark 配置,以使我们的客户管道稳定和高性能。

我们还希望简化数据科学家和工程师的开发体验,而可观察层是这个难题的关键部分。我们想让任何人都容易理解他们的 Spark 代码的性能。

这就是我们着手为 Spark 构建一个开源监控仪表板 Delight 的原因。2020 年 6 月,我们在一篇被广泛分享的博文中分享了我们对快乐的愿景,该博文以下面的 GIF 为特色:

我们的喜悦设计原型,2020 年 6 月出版。图片作者。

受到数百名注册者和我们公告上的评论的鼓励,我们开始构建 Delight,这是一项大规模的工程工作。

  • 2020 年 11 月,我们发布了一个 MVP,其中包含一个托管仪表板,让您可以访问已终止应用程序的 Spark UI(避免您运行和维护自己的 Spark 历史服务器的麻烦)。
  • 在 Q1 2021 中,我们在内部向客户发布了 Delight,并重复了他们给出的反馈,修复了我们发现的许多漏洞和稳定性问题。
  • 今天,要实现我们的最终愿景,还有很多工作要做。但是,快乐已经被证明对许多人有价值,所以我们很高兴向 Spark 社区开放它!

架构:开源代理+托管后端

Delight 可以在任何 Spark 平台上免费工作,包括 Databricks、Amazon EMR、Google Dataproc 或开源的 Spark-on-Kubernetes 或 Spark-on-YARN 设置。它与使用 spark-submit、Apache Livy 或 Spark-on-Kubernetes 操作符运行 Spark 应用程序兼容。

愉悦包括:

高层架构:一个开源代理&一个托管后端。图片作者。

Delight 收集的指标包含关于 Spark 应用程序执行的底层元数据,比如每个任务读取/写入了多少数据,使用了多少内存和 cpu。这些指标被称为 Spark 事件日志(查看示例),它们是让 Spark 历史服务器回放已完成应用程序的 Spark UI 的相同信息。

这些指标使用您可以在我们的控制面板中生成的秘密访问令牌进行保护,该令牌可以唯一地标识您。它们不会与任何第三方共享,并且会在 30 天后自动从我们的服务器中删除。每个组织最多可存储 1,000 个应用程序(如果您在 30 天内运行超过 1,000 个应用程序,我们将开始删除最旧的应用程序)。

浏览主屏幕

1.主仪表板

Delight 的主仪表板列出了您最近完成的所有 Spark 应用程序。图片作者。

‍When:你登录到 Delight,你会看到这个表格,是你最近运行的 Spark 应用程序。请注意,实时应用程序还不可见,它们只在完成几分钟后才会出现。该屏幕中的大部分信息应该是不言自明的,除了 3 列:Spark 任务、CPU 和效率。在解释它们之前,先快速回顾一下 Spark 分布式执行是如何工作的。

在一个火花 应用 中,你有一个单独的 驱动 进程(你的应用的“大脑”),和许多 执行 进程。驱动负责理解你的代码,把它拆分成 作业*阶段 任务 。阶段是一组可以在执行器上并行执行的任务。一个执行器内核一次可以运行(最多)一个 Spark 任务;换句话说,具有 4 个 CPU 的 Spark 执行器可以并行运行多达 4 个任务。*

现在让我们定义三列:

  • 星火任务。这是应用程序中所有任务持续时间的总和。旁注:这是数据力学平台* 定价 所依据的度量。*
  • CPU 。这是你的 Spark 执行器生命周期的总和,乘以分配给每个执行器的核心数。换句话说,这是您的“执行者核心正常运行时间”。这一指标通常与您的基础设施成本成比例。
  • 效率。这是 Spark 任务除以 CPU 的比率,用百分比表示。这表示 CPU 资源有效用于运行 Spark 任务的时间比例。100%是理想的(完美的并行),0%意味着您的计算资源被浪费了(您有运行的容器,但它们是空闲的)。

这是我们关注数据机制的关键指标之一,因为我们的平台具有自动化功能(自动扩展、自动调整等)来提高我们客户的效率,从而降低他们的云成本(查看这个从 EMR 迁移过来的客户的故事以了解更多信息)。

2.执行器核心使用情况

一旦你点击一个特定的应用程序,你就会进入一个应用程序概述页面,上面有高级统计数据和一个指向顶部 Spark UI 的链接。下一个信息是 executor 核心使用图。

executor 核心使用情况图提供了应用程序性能的高级视图。图片作者。

executor cores usage graph 将 Spark 在应用程序执行期间测量的低级 CPU 指标汇总到一个简单的可视化概览中。首先,您会看到一份 executor 内核使用情况的摘要,按主要类别进行了分类(单击ℹ️图标阅读它们的定义):

  • CPU —实际计算 Spark 任务所花费的时间。
  • I/O —等待读取或写入数据(通常来自网络)所花费的时间。注意:Spark 目前将 python 进程中完成的工作视为 I/O(从 JVM 的角度来看,这是等待 Python 提供数据的 I/O)。例如,当您执行 python 用户定义的函数时,就会发生这种情况。查看这篇* StackOverflow 帖子 可以更好地理解 JVM 和 Python 如何在 PySpark 中协同工作。 *
  • Shuffle —在 Shuffle(Spark 执行器之间的数据交换阶段)期间等待数据块被写入或提取所花费的时间。
  • 垃圾收集—JVM 进行垃圾收集所花费的时间。对于大多数(健康的)应用程序,这不应该超过几个百分点。
  • Spark Internals—Spark 花费在调度程序延迟、任务序列化和反序列化等开销操作上的时间。同样,这对于大多数应用程序来说应该很小。
  • 一些内核空闲 —任务被执行的时间,但是只在一部分执行程序内核上。高值是不完全平行的标志。
  • 所有内核空闲 —无火花任务运行的时间。这可能是完全闲置,这种情况经常发生,例如当你以交互方式使用 Spark 时,然后休息一下。或者这可能意味着一些非 Spark 工作正在发生,例如你可能在驱动上执行纯 Python 或 Scala 代码,所以所有的执行器都是空闲的。

这些信息会显示在一个图表上,其中 X 轴是应用程序的时间轴,Y 轴是您拥有的执行器核心数(如果您启用了动态分配,它可能会随时间而变化)。在这个图表下,你可以看到你的 Spark 工作和阶段的时间表。

此图的主要好处是,您可以非常快速地将注意力集中在应用程序的主要性能瓶颈上。在本例中,很明显 job-1/stage-1 占用了大部分应用时间。大的灰色区域表示大多数内核在此期间处于空闲状态。如果您单击“stage-1”,您将被带到 Spark UI,因此您可以进一步对此进行故障诊断(在本例中,问题是该阶段只有 2 个任务)。

3.执行者峰值内存使用

此图仅在您使用 Spark 3.0 或更高版本时可见,因为它依赖于 Spark 3.0 中引入的新功能( SPARK-23429SPARK-27189 )。

executors 峰值内存使用图表显示了 Spark executors 达到最大内存使用量时的内存使用量明细。图片作者。

‍While 你的应用程序正在运行,火花测量每个执行者的内存使用。此图报告了针对前 5 名执行者观察到的内存使用峰值,按不同类别细分:

  • JVM 使用的内存(这是你的最大堆大小)
  • Python 进程使用的内存(如果您使用 PySpark)
  • 其他进程使用的内存(如果您正在使用 R,那么 R 当前被列为“其他”)

这个图表对 PySpark 用户应该特别有用,他们目前没有简单的方法知道他们的 python 进程消耗了多少内存。这个图表可以帮助你决定使用不同类型的容器是否安全。它还可能警告您,您正在与允许的最大内存使用量调情。提醒一下,如果您的 Python 进程使用了太多的内存,那么您的资源管理器将会终止您的 Spark 执行器(例如在 Kubernetes 上,您将会得到 docker 退出代码 137)。

结论:尝试一下,并让我们知道您的反馈!

我们希望 Delight 能够实现它的承诺,并帮助您获得愉快的 Spark 开发体验。

我们鼓励您尝试一下!注册,按照我们的 github 页面上的安装说明,并通过电子邮件(回复欢迎邮件)或使用产品中的实时聊天窗口让我们知道您的反馈。

我们对快乐有雄心勃勃的计划。我们的未来路线图包括:

  • 每个执行器和驱动程序都有一个页面,用于跟踪它们的内存使用情况,并提供更详细的细分(堆外内存使用情况)
  • 自动化性能调整建议(例如,关于数据不对称/低效数据分区的警报等)
  • 在应用程序运行的同时,让快乐实时可及
  • 更多基于您的反馈:让我们知道您的优先事项!

我们将很快发布后续文章,介绍具体的故障排除步骤,并使用 Delight 启动性能调优会议。我们还将举办关于它的聚会和会议,包括即将举行的数据+人工智能峰会。敬请关注,感谢您的支持!

最初发表于T5【https://www.datamechanics.co】

没有 DataOps 的 AI/ML 只是白日梦!

原文:https://towardsdatascience.com/delivering-ai-ml-without-proper-dataops-is-just-wishful-thinking-2f1663d6b97f?source=collection_archive---------34-----------------------

关于有效 AI/ML 的数据运营的博客系列

GIF by giphy

让我们从我过去的 ML 项目中的一个真实世界的例子开始:我们正在建立一个客户流失模型。"我们迫切需要一个与客户支持电话的情绪分析相关的附加功能."创建提取该数据集的数据管道花费了大约 4 个月的时间!准备、构建和扩展 Spark MLlib 代码花费了大约 1.5-2 个月的时间!后来,我们意识到“与客户在我们的应用程序中完成某些任务所花费的时间相关的附加功能将进一步提高模型的准确性”——数据管道又过去了 5 个月!实际上,部署 ML 模型花了 2 年多的时间!

在推动了几十个 ML 计划(以及就此主题为多家初创公司提供建议)之后,我得出了以下结论:鉴于 AI/ML 项目的迭代性质,拥有一个构建快速可靠的数据管道的敏捷流程(称为数据操作)一直是成功的 ML 项目的关键区别(除非有非常详尽的功能库可用,但通常情况下不会有)。

在每一个成功的 AI/ML 产品背后,都有一个使用明确定义的数据操作流程开发的快速可靠的数据管道!

说白了,什么是数据操作?摘自 维基百科 :“数据运营整合了敏捷方法,以缩短与业务目标一致的分析开发周期。”

我将 DataOps 定义为流程和技术的组合,以敏捷的方式迭代地交付可靠的数据管道。根据数据平台的成熟度,您可能处于以下数据操作阶段之一:

  • 临时 :数据操作没有明确的流程
  • 开发 :定义了清晰的流程,但由数据团队手工完成
  • 最优 :为数据科学家、分析师和用户提供自助式自动化的清晰流程。

与软件开发类似,数据操作可以被视为一个无限循环

DataOps 生命周期(显示为无限循环)代表了将原始数据转化为见解的过程。在讨论每个生命周期阶段的关键过程之前,下面列出了我在每个阶段遇到的首要问题:

  • 计划:“我们无法启动新项目,因为我们没有资源,需要额外的预算”
  • 创建:该查询连接数据样本中的表。我没有意识到实际数据有十亿行!”
  • 编排:“管道完成了,但是输出表是空的——在输入表被填充之前,调度程序触发了 ETL”
  • 测试&修复:“使用玩具数据集在开发中测试—生产中处理失败,出现 OOM(内存不足)错误”
  • 持续集成;“写得很差的数据管道被提升为生产管道—团队现在正在救火”
  • 部署:“没有预料到与其他管道的规模和资源争夺”
  • 操作&监视器:“不知道为什么今天管道运行缓慢”
  • 优化&反馈:“我对查询进行了一次性调优,但没有意识到需要持续进行调优来解决数据倾斜、规模等问题。”

为了避免这些创伤和更多的创伤,从临时到开发再到自助服务的成熟数据操作至关重要。

本博客系列将帮助您从即席到定义良好的数据操作流程,并分享如何实现自助服务的想法,以便数据科学家/用户不会受到数据工程师的限制。

对于 DataOps 生命周期阶段的每个阶段,请遵循要定义的关键流程的链接以及使其成为自助服务的体验(下面的一些链接正在填充—添加书签并返回):

计划阶段

  1. 如何简化寻找数据集
  2. 制定人工智能/人工智能问题的范围和成功标准
  3. 如何根据业务需求选择正确的数据处理技术(批处理、交互式、流式)

创建阶段

  1. 如何简化数据集元数据属性的访问
  2. 如何简化数据准备流程
  3. 如何进行行为数据自助

编排阶段

  1. 管理数据治理
  2. 重用 ML 模型特性
  3. 调度数据管道

测试&修复阶段

  1. 简化测试的沙盒环境
  2. 识别并消除数据管道瓶颈
  3. 验证数据管道结果的正确性、质量、性能和效率。

持续集成&部署阶段

  1. 数据管道代码集成的冒烟测试
  2. 数据流水线的调度窗口选择
  3. 更改回滚

操作阶段

  1. 检测异常以主动避免违反 SLA
  2. 管理生产中的数据事件
  3. 对流氓(占用资源)作业发出警报

监控阶段

  1. 构建数据管道的端到端可观测性
  2. 跟踪数据流数据的谱系
  3. 用断路器加强数据质量

优化&反馈阶段

  1. 持续优化现有数据管道
  2. 预算预警

总之,DataOps 是交付快速可靠的 AI/ML 的关键!这是一项团队运动。本博客系列旨在揭开所需流程的神秘面纱,并在数据科学家、工程师、运营人员等之间建立共识。

作为团队运动的数据操作(图片由作者提供)

要了解更多信息,请查看最近的DataOps Unleashed Conference以及在unleave上的 data ops 可观测性创新。当上面的链接被填充时,请跟随通知

使用 Fugue 更快、更便宜地交付 Spark 大数据项目

原文:https://towardsdatascience.com/delivering-spark-big-data-projects-faster-and-cheaper-with-fugue-dd9d7b190653?source=collection_archive---------32-----------------------

提高开发人员的工作效率,减少大数据项目的计算使用

海洋 NgUnsplash 上拍照

Fugue 是一个开源库,为 Pandas、Spark 和 Dask DataFrames 提供了统一的接口。在本文中,我们将展示 Fugue 如何通过降低计算成本和提高开发人员的工作效率来加速大数据项目的开发。

首先,我们将查看一个简单的代码示例,它将突出显示使用 Spark 时引入的一些复杂性,然后展示如何通过使用 Fugue 来抽象这些复杂性。

激励的例子

问题设置

首先,我们来看一个令人兴奋的例子,我们有一个熊猫数据帧,其中有一列包含电话号码。对于每个电话号码,我们希望获得区号(在电话号码的括号中),然后将其作为新列映射到一个城市。

设置数据框架

熊猫实现

熊猫对此有一个非常优雅的解决方案。我们可以使用phone列的map()方法。

使用熊猫地图方法

这会产生以下数据帧:

|   |          phone |          city |
|--:|---------------:|--------------:|
| 0 | (217)-123-4567 | Champaign, IL |
| 1 | (217)-234-5678 | Champaign, IL |
| 2 | (407)-234-5678 |   Orlando, FL |
| 3 | (510)-123-4567 |   Fremont, CA |
| 4 | (123)-123-4567 |           NaN |

火花实现

但是,当数据框架太大,我们需要激发这个逻辑时,会发生什么呢?它看起来会像下面这样(在 Spark 3.0 和更高版本中)。没必要去消化这里发生的事情。这只是为了说明语法会有所不同。

详细问题

这里我们已经看到了一个问题。对于同一个逻辑,我们有一个非常不同的语法来实现它。这是一个非常常见的场景,用户不得不编写大量新代码来激活熊猫功能。

这意味着两件事:

  1. 在 Pandas 和 Spark 上重复实现相同的业务逻辑
  2. 数据科学框架将逻辑和执行结合在一起。熊猫代码可以被带到 Spark 上(稍后我们会看到大量的修改),但是 Spark 代码只能在 Spark 引擎上执行。

赋格变换

Fugue 旨在通过使相同的代码在 Pandas、Spark 和 Dask 上可执行来解决这个问题。使用赋格最简单的方法是 **transform** 函数,它取一个 Python 或者熊猫函数,带到 Spark 和 Dask 中。

对于上面的例子,我们可以将熊猫代码包装成一个函数。没有什么新奇的事情发生。

在函数中包装熊猫代码

但只要这样做,我们现在就可以使用赋格的transform函数将它带到 Spark 和 Dask。下面的例子就是把它带到 Spark。

使用赋格变换

这将返回一个 Spark 数据帧(可以接收 Pandas 和 Spark 输入数据帧)。要在熊猫上使用map_phone_to_city功能,用户只需使用默认的engineschema参数是操作的输出模式,这是分布式计算框架的一个要求。同样,Dask 执行也有 DaskExecutionEngine。

逻辑和执行的分离

现在有了这个transform函数,我们可以在 Pandas、Spark 和 Dask 上使用map_phone_to_city函数。逻辑与执行引擎分离。一些读者可能想知道map_phone_to_city功能是否仍然与熊猫有关,他们可能是对的。如果我们想用纯本地 Python 实现它,我们可以使用列表和字典,如下面的代码所示。

纯本地 Python 实现

这个可以被神游跨熊猫,Spark,Dask 用同一个transform调用。Fugue 将处理数据帧到指定类型注释的转换。这里,我们使用_area_code_map字典的get()方法,并指定一个默认值“Unknown”。同样,这也可以通过以下方式来激发:

这导致了

|         phone |          city |
|--------------:|--------------:|
|(217)-123-4567 | Champaign, IL |
|(217)-234-5678 | Champaign, IL |
|(407)-234-5678 |   Orlando, FL |
|(510)-123-4567 |   Fremont, CA |
|(123)-123-4567 |       Unknown |

通过使用 **transform** 函数,我们可以将逻辑与执行分开,然后在运行时指定执行引擎。逻辑是以一种纯规模不可知的方式定义的。

关于执行速度的说明

很多用户问赋格transformpandas_udf Spark 相比如何。简单的回答是神游可以被配置成在引擎盖下使用pandas_udf。有关更多信息,请参见。在这种情况下,Fugue 将代码映射到一个pandas_udf,但仍然提供优雅的跨框架兼容功能。

降低计算成本

现在我们有了一种快速的方法,通过在调用transform时改变engine来在 Pandas 和 Spark 执行之间切换,我们可以在扩展到 Spark 集群之前在本地机器上构建原型并在本地测试代码。这之所以成为可能,是因为我们没有依赖 PySpark API 来定义我们的逻辑。这从两个方面降低了计算成本:

  1. 单元测试可以在本地完成,然后在准备好的时候移植到 Spark
  2. 集群上发生的错误会更少,因为在移植到 Spark 之前,我们可以在本地进行更多的开发。这些代价高昂的错误会减少。

许多 Spark 用户使用databricks-connect库在 Databricks 集群上运行代码。这将在本地编译执行图,然后将其发送到 Databricks 集群进行执行。这样做的缺点是,对于任何使用 Spark 代码的简单测试,Databricks 集群都会加速运行并产生成本。通过使用 Fugue,开发人员可以通过改变执行来轻松地在本地和集群执行之间切换engine

改进的可测试性

使用 Fugue 的 **transform** 减少了将基于 Pandas 的函数引入 Spark 时需要编写的样板代码的数量。下面的代码是将我们之前的map_phone_to_city函数引入 Spark 的一个例子。

注意,这段代码只适用于基于 Panda 的实现,不适用于使用ListDict的原生 Python 实现。同样,不需要完全理解代码,重点只是显示引入的样板代码的数量。

您会注意到这段代码与 Spark 耦合在一起,您需要运行 Spark 硬件进行测试。从单元测试的角度来看,你需要测试两个额外的函数来激发你的功能。对于神游的transform,因为transform被神游测试的很重,所以只需要对原函数进行单元测试即可。

如果你想进一步测试的话,transform函数也很容易测试。只需调用assert并测试输入和输出。

提高开发人员的工作效率

使用 Fugue,开发人员可以以一种与规模无关的方式轻松构建原型,并更快地捕捉错误,从而显著加快开发速度。但是使用赋格也有好处:

  1. 单元测试减少了(如上所示),样板代码也更少了
  2. 开发人员可以用他们觉得舒服的方式表达他们的逻辑(Python 或 Pandas)
  3. Spark 应用程序的维护更加容易
  4. 功能可以在 Pandas 和 Spark 项目之间重用

应用程序的维护

大数据项目最困难的事情之一是维护。不可避免的是,将来必须重新访问代码,以更改一些业务逻辑或修复一个 bug。如果代码库与 Spark API 耦合,这意味着只有了解 Spark 的人才能维护它。

通过将逻辑转移到 Python 或 Pandas,Fugue 减少了专门维护的需要,数据专业人员更容易访问这些工具。代码变得更加模块化和可读,这意味着维护大数据应用程序变得更加容易。

逻辑的可重用性

通常,数据科学团队会同时拥有一些不需要 Spark 的项目和其他需要 Spark 的项目。在这种情况下,业务逻辑必须实现两次,每个框架一次,以便在两组项目中使用。这使得维护变得复杂,因为当需要修改时,有更多的地方可以编辑代码。Fugue 的transform通过使代码对执行引擎不可知来解决这个问题。

如果数据团队通过使用 Spark 或 Pandas 来解决这个问题,那么就存在使用错误工具的问题。在大数据上使用 Pandas 需要昂贵的垂直扩展,在较小的数据上使用 Spark 会引入不必要的开销。Fugue 让用户先定义逻辑,然后在运行时选择执行引擎。这减少了移植定制业务逻辑所花费的工程时间。

结论

在本文中,我们展示了如何使用 Fugue transform函数为 Pandas、Spark 或 Dask 带来一个单独的函数。这种无缝转换允许在本地执行和集群执行之间快速切换。通过最大化可以在本地完成的原型制作数量,我们可以通过提高开发人员的工作效率和降低硬件成本来降低大数据项目的成本。

transform功能只是神游的开始。有关更多信息,请查看下面的参考资料。

资源

关于神游,火花,或分布式计算的任何问题,请随时加入下面的神游松弛频道。

赋格回购

赋格文档

赋格懈怠

kube con 2021 的赋格

Delta Lake —除了 ACID 属性之外,还支持有效的缓存机制和查询优化

原文:https://towardsdatascience.com/delta-lake-enables-effective-caching-mechanism-and-query-optimization-in-addition-to-acid-96c216b95134?source=collection_archive---------31-----------------------

数据科学家更喜欢使用三角洲湖进行更快的实验。

学会从别人的角度看问题(来自 Pexels杰米摄影)

我在目前的工作中从事建立不同粒度的不同机器学习模型,其中有几个粒度很高。更具体地说,这种模型需要对许多假设进行评估。最近,我不得不建立 22 个不同的模型,每个模型都用 6000 万个数据点训练,有 2000 个特征。它还需要多次反复进行超参数调整。作为一个团队,我们有各种各样的假设,我们需要评估每一个假设。为此,我们必须训练一个模型并评估其准确性以验证假设。如果这行得通,我们需要将同样的假设应用于剩余的 21 个模型。

我是怎么接近的?

因为我接收的是 parquet 格式的数据,所以我最终使用 parquet 来训练模型。训练一个模型需要几天时间,验证一个假设需要几周时间。我测试了许多减少计算时间的方法,但没有一个是有效的。最后,我使用 Delta 作为数据格式,而不是 parquet。

在本文中,我们将分析有助于减少训练到模型的计算时间的具体特性。

三角洲湖

Delta lake 是一个开源存储层,在分布式环境中启用 ACID 属性。在接下来的小节中,我将使用一个简短的介绍来探索更多关于 delta 格式的内容。

大多数人普遍关心的问题

delta lake 的目的是支持 ACID 属性——您如何减少训练模型的计算时间?

这是我被问到的第一个问题。是的,Databricks 为希望通过多个群集同时读写文件的特定客户开发了此存储层。

三角洲湖不限于以上;它还消除了数据科学家和数据工程师面临的一些其他障碍。

  1. 数据跳过:使用增量文件,您不需要扫描整个数据。随着新数据被插入到 Databricks 增量表中,将收集所有列的文件级最小/最大统计信息,这有助于有效地过滤文件。
  2. Z -order:除了数据跳转之外,Z-order 还支持多维数据跳转。
  3. 高效缓存:增量缓存通过使用快速中间数据格式在节点的本地存储中创建远程文件的副本来加速数据读取。
  4. 可扩展的元数据处理:在大数据世界中,即使元数据也具有大数据的特征。Delta 将元数据视为大数据(即,它使 spark 能够以分布式方式处理元数据)。
  5. 时间旅行:Delta 支持数据版本化。
  6. 批处理和流的统一平台:delta lake 中的表可以接收(也可以处理)批处理和流数据。
  7. 更新和删除:Delta Lake 支持 Scala/Java API 来合并、更新和删除数据集。

delta 文件格式有许多特点。然而,在本文中,我们深入探讨了以下实现更快数据处理的方法:

  1. 有效缓存
  2. 数据跳过
  3. z 顺序

使用增量缓存存储的数据比 Spark 缓存快得多

我们都将缓存作为查询优化的一部分,那么增量缓存有什么不同呢?Azure databricks 提供了两种缓存类型。

  1. Apache Spark 缓存

它使用内存中的火花。由于可用内存有限,它会影响 spark 中运行的其他操作。

2)增量缓存

它使用本地磁盘。因为它不使用内存,所以在 spark 中运行的其他操作不会受到影响。尽管 delta 使用本地磁盘来缓存数据,但由于其独特的解压缩算法,它仍然非常有效。这可以通过使用“增量缓存加速”工作线程来进一步优化。默认情况下启用增量缓存,workers 中的 SSD 配置为有效使用增量缓存。下面的屏幕截图详细说明了如何在 databricks 环境中选择启用了“增量缓存加速”的工作线程。你必须选择 L 型工人,如下所示。

增量缓存加速工人-按作者分类的图片

数据跳过

镶木地板

通常,该表存储为多个拼花文件。假设有一个场景,其中有一个名为“sales”的表

  1. 它有如下四列:“项目”、“位置”、“日期标识”和“销售数量”
  2. 它拥有分布在 2000 个拼花文件中的 6000 万个数据点。

“销售”表—按作者分类的图像

假设有一个查询要过滤 1 月 1 日到 6 日的销售额。

该查询执行扫描所有 2000 个文件来过滤结果。

在三角洲

假设我们使用 delta 格式存储上面的文件。在这种情况下,每个文件的每一列都有一个最小值和最大值,这是 delta 格式的一个固有特性。

带有增量格式附加列的“销售”表—按作者分类的图像

对增量格式运行的相同查询使用这些最小/最大值来跳过文件。因此,需要扫描的拼花文件少于 2000 个(很可能少于 500 个)。因此,它大大减少了计算时间。

z-排序

z 排序是一种多维(基于多列)聚类拼花文件的方法。它使我们能够跳过更多的扫描。

Z 排序在哪里效果更好?

回到我的问题陈述,我被要求构建 22 个不同的模型,但是模型的粒度是相同的(例如,模型预测给定地点给定日期给定商品的销售)。简单来说,Spark 会以相同的粒度多次使用我的训练数据。

您可以使用以下代码简单地优化 Z 顺序:

上面的代码将相关的信息(这里,相似性是根据以下几列决定的——“项目”、“位置”和“日期 id”)放在同一个文件集中。

同样的查询用“ZORDER”优化重新运行,跳过更多的文件,查询执行起来比以前快得多。

最后的想法

尽管 databricks 开发了 delta lake 来启用 ACID 属性,但它还包括其他功能,如有效的缓存、数据跳过和 Z 顺序优化。这些附加功能有助于以分布式方式在更短的时间内处理数据。本文关注的是 delta lake 如何加速数据处理,因此,我跳过了 delta lake 提供的其他有趣的功能,如可伸缩的元数据处理、时间旅行、批处理和流的统一平台,以及更新和删除。接下来的文章将详细讨论这些特性。

用时态卷积网络研究数字运算

原文:https://towardsdatascience.com/delve-into-number-crunching-of-temporal-convolutional-network-db3c3dc69f63?source=collection_archive---------35-----------------------

TCN 如何处理你的输入的可视化文档

蒂姆·约翰逊Unsplash 上拍照

时间卷积网络(TCN)是一种神经网络,专门处理序列数据问题这是除了长短期记忆(LSTM)或门控循环单元(GRU) 或另一个解决相同问题的循环神经网络(RNN)之外的另一种选择。与另一种神经网络相比,TCN 有什么不同或特别之处? TCN 不是 RNN,它没有使用单元格状态,有一个类似循环的工作流。它使用全卷积网络(FCN)进行处理。FCN 和普通卷积层有什么区别?FCN 根本没有使用密集层(通常是神经网络的隐藏层)。

为了理解神经网络的卷积层,可视化非常重要。和 TCN 一样,在这里我将尝试用真实的数字来想象 TCN“发生了什么”。为了更容易理解和可视化,我们将只使用 1 个输出通道。此外,我们将使用 2 个隐藏层和 1 个输出层。好了,我们开始吧。

选择一个任意的数字序列(在 0 和 1 的范围内)

我们用 excel 写吧。我们将挑选 11 个数字。

为我们的卷积层滤波器选择一个任意的数字序列

因为我们的数据是一维的,所以我们将使用 1×3 维的过滤器。

作者图片

滑动过滤器浏览输入数据

这里,我们将逐个滑动滤波器,对输入数据进行点积,并在输入数据的末尾添加长度为(length of filter — 1)*dilation的填充。在第一层,我们将膨胀设为 1。稍后我会解释膨胀。总之,我们输出的长度将与输入数据的长度相同。

作者图片

为卷积层的第二个滤波器选择一个任意的数字序列

作者图片

并添加填充(在下一层,将膨胀为 2,所以(3–1)* 2 = 4)。

作者图片

滑动第二个过滤器通过第一层数据

但是我们将卷积的膨胀增加到 2。层的膨胀在2^(layer-1)中增加(2 的层级别的幂减 1)。第一层的膨胀是 1,现在是 2。为了更好地理解膨胀,最好看看下面的动画。

作者图片

为卷积层的输出层滤波器选择一个任意的数字序列,并添加填充

作者图片

通过第二层数据滑动输出层(第三层)过滤器

作者图片

提取输出值

并且输出值是层 3 中的第一个值。

作者图片

为什么?因为只有这个值在计算中涉及到我们所有的输入数据。

作者图片

将其与输出图层中的第二个值进行比较。

作者图片

它不涉及输入层中的第一个数字。所以为什么输出层的第一个值更适合成为我们模型的输出。

现在,在真实的 TCN 中,人们通常使用残差网络(ResNet)进行层间运算。它是如何工作的,真的很简单。我们只是将卷积层的输出与经过 1x1 滤波器处理的前一层中的值相加。这是插图。

首先,我们为第 1 层的 1x1 ResNet 过滤器选择一个数字

作者图片

然后将其滑过输入层

它只是resnetfilter*input

作者图片

然后将其添加到层 1 的输出

作者图片

重复此过程,直到最后一层

通常,在 ResNet 块(使用 ResNet 的层间处理块)中,我们在处理结束时使用 ReLU。所以在添加它们之后,我们将它们提供给 ReLU 层。 ReLU 只是将所有小于零的值归零,否则我们保持该值

这就是 TCN 如何将你输入转化为输出。如果你使用一个以上的通道进行输出,实际输出层必须是一个密集层以使用每个通道的所有第一个值计算实际输出。另一篇文章再见。

用不同的数据科学方法进行需求预测

原文:https://towardsdatascience.com/demand-forecast-with-different-data-science-approaches-ba3703a0afb6?source=collection_archive---------4-----------------------

需求预测中的数据科学

杰斯·贝利在 Unsplash 上的照片

在这个故事中,我将概述常见的数据科学技术和框架,以创建一个需求预测模型。

首先,让我们定义什么是需求预测,它对业务有什么影响。维基——需求预测是预测分析的一个领域,它试图理解和预测客户需求,以优化企业供应链和业务管理的供应决策

需求预测有几种类型:

  • (它是进行 3 个月到 12 个月的短期。在短期内,需求的季节性模式和战术决策对客户需求的影响被考虑在内。)
  • (一般提前 12 个月以上至 24 个月进行(某些业务 36-48 个月)。长期预测推动业务战略规划、销售和营销规划、财务规划、容量规划、资本支出等。)
  • 外部宏观层面 (这种类型的预测处理依赖于宏观经济环境的更广泛的市场运动。进行外部预测是为了评估企业的战略目标,如产品组合扩张、进入新的客户群、技术中断、消费者行为模式转变和风险缓解策略。)
  • (这种类型的预测处理企业的内部运作,如产品类别、销售部门、财务部门和制造部门。这包括年度销售预测、COGS 估算、净利润率、现金流等。)
  • 被动 (针对增长计划非常保守的稳定业务进行。历史数据的简单推断是在最少假设的情况下进行的。)
  • )

为什么需求预测如此重要,它改进了什么流程?需求预测是公司制定战略和运营计划的关键业务流程。基于需求预测,制定企业的战略和长期计划,如预算、财务规划、销售和营销计划、容量规划、风险评估和缓解计划。它还会影响以下流程:

  • 供应商关系管理。
  • 客户关系管理。
  • 订单履行和物流。
  • 营销活动。
  • 制造流程管理。

好了,让我们来解决这个问题,并尝试使用不同的数据科学技术和框架来进行准确的需求预测。

在我的实验中,我想使用 Kaggle 的竞赛中的数据集。在每个数据科学任务中,我都使用 CRISP-DM 来跟踪项目工作中所有必要的流程。

CRISP-DM 的第一阶段是——业务理解。任务是为测试集预测每个商店销售的产品总量。衡量标准或成功标准是什么?预测由均方根误差(RMSE)评估。

对我来说,第二和第三阶段是最重要的阶段之一——数据理解和准备。启动需求预测项目的首要任务是为客户提供有意义的见解。该方法包括以下步骤:

  1. 收集可用数据

在我们的例子中,我们得到了下一个数据集:

  • sales _ train.csv 训练集。2013 年 1 月至 2015 年 10 月的每日历史数据。
  • test.csv —测试集。你需要预测这些商店和产品在 2015 年 11 月的销售额。
  • sample_submission.csv —格式正确的示例提交文件。
  • items.csv 关于物品/产品的补充信息。
  • item _ categories.csv 关于项目类别的补充信息。
  • 关于商店的补充信息。

简要回顾数据结构、准确性和一致性。让我们制作几个表和图来分析我们的数据集。

笔记本快照

这种基础分析可以帮助我们理解数据集的主要输入参数。例如,我们可以看到,在我们的数据集中,价格为负值,这可能是一个错误,销售为负值,这可能是з购买回报。

下表为我们解释了数字列的分布情况:

笔记本快照

这里我们可以看到,一半的销售额等于 1。

我们来做一个散点图,分析一下销量和价格的关系。

笔记本快照

这种类型的图通常可以告诉我们,我们有价格低但销量大的单元,也有价格异常高但销量非常低的单元。

让我们动态地分析我们的数据—

  • 第一张图向我们展示了产品组合中独特产品的减少趋势:

笔记本快照

  • 第二个图表显示了销售量下降的趋势和两个选择,这可能是一个季度或一些促销活动。这是我们需要从商业和通过定量分析中学习的。

笔记本快照

  • 下一步是对我们的类别进行分析,我们将使用它来聚合我们的数据集,第一维是商品/类别名称,第二维是商店 id。该分析向我们展示了商品类别和商店的销量分布,有助于我们了解哪些类别和商店对我们最重要,哪些类别和商店的分析和预测历史较短。

笔记本快照

笔记本快照

EDA 是一个持续的过程,你可以在不同实验的整个过程中继续进行。让我们停止在这一点上,并开始创建模型。

在我们开始创建模型之前,我们需要分割数据集用于训练、验证和测试。请记住,我们需要使用日期列来过滤数据集,不要对时间序列使用随机分割。

数据分割示例

基本方法

在这一部分,我将解释和创建基本的方法模型。

第一个是平滑移动平均线。平滑移动平均(SMMA)是一种需求预测模型,可用于根据连续期间的一系列平均值来判断趋势。

例如,六个月销售额的平滑移动平均值可以通过取 1 月到 6 月销售额的平均值、2 月到 7 月销售额的平均值、3 月到 8 月销售额的平均值等等来计算。

这种模型被称为“移动”,因为随着更多数据的出现,平均值会不断重新计算。

mm 阶的移动平均值可以写成:

乳胶快照

其中 m=2k+1m=2k+1。也就是说,在 tt 时间的趋势周期的估计是通过对 tt 的 kk 周期内的时间序列的值进行平均而获得的。时间上接近的观测值也可能接近。

平滑移动平均线对于查看一段时间内的总体销售趋势和帮助制定长期需求计划非常有用。季节性或其他波动导致的快速变化被消除,因此您可以更准确地分析全局。当你的产品随着时间的推移持续增长或下降时,平滑移动平均模型通常很有效。此外,这种方法的重要缺点是,我们可以制造没有历史的产品。

为了用 Python 制作,我们可以使用熊猫。DataFrame.shift 创建滞后值,

**full_df['sales_lag_n'] = full_df['sales'].shift(periods=n)**

然后我们可以用熊猫。DataFrame.rolling 根据创建的滞后值创建滚动平均值。

**full_df['sma'] = full_df['sales_lag_n].rolling(n).mean()**

下一个模型是霍尔特·温特的指数平滑法。霍尔特 ( 1957 )和温特斯 ( 1960 )扩展了霍尔特捕捉季节性的方法。霍尔特-温特斯季节性方法包括预测方程和三个平滑方程——一个用于水平ℓtℓt,一个用于趋势 bt,一个用于季节性成分 st,以及相应的平滑参数αα,β∑β∫和γγ。我们用 mm 来表示季节性的频率,即一年中的季节数。例如,季度数据 m=4m=4,月数据 m=12m=12。

这种方法有两种不同的变体,如季节性成分。当季节变化在整个系列中大致不变时,最好使用加法方法,而当季节变化与系列水平成比例变化时,最好使用乘法方法。在加法方法中,季节分量在观测序列的标度中以绝对值表示,在水平方程中,通过减去季节分量对序列进行季节调整。在每一年中,季节性因素加起来大约为零。使用乘法时,季节性成分以相对项(百分比)表示,序列通过除以季节性成分进行季节性调整。在每一年内,季节性成分的总和将达到约 100 万毫米

这种方法比前一种方法更有效,因为它处理季节成分,但它也有同样的缺点,即不处理分类中的新项目。

这个方法在 Python 中有一个实现

****from** statsmodels.tsa.holtwinters **import** ExponentialSmoothing **as** HWES**

这个模型适用于一双鞋,这意味着我们需要为每双鞋创建一个新的模型。

**for index, row in tqdm(df_test.iterrows()): tmp = df_train_aggr[(df_train_aggr['shop_id'] == row['shop_id']) & (df_train_aggr['item_id'] == row['item_id'])] model = ExponentialSmoothing(tmp.item_cnt_day) model_fit = model.fit() forecast = model_fit.forecast(steps=n)**

我的基本方法中的最后一个模型是 ARIMA。ARIMA 是“自回归综合移动平均”的缩写,它实际上是一类模型,根据给定时间序列的过去值(即其自身的滞后和滞后预测误差)来“解释”该时间序列,因此该方程可用于预测未来值。任何显示模式且不是随机白噪声的非季节性时间序列都可以用 ARIMA 模型来建模。

ARIMA 模型的特征在于三个项:p,d,q 其中,

  • p 是 AR 项的阶数
  • q 是 MA 项的顺序
  • d 是使时间序列平稳所需的差值数

如果一个时间序列有季节模式,那么你需要添加季节项,它就变成了萨里玛,是“季节性 ARIMA”的缩写。等我们结束 ARIMA 后会有更多的报道。和前面的模型一样,我将为每个商店商品对建立一个单独的模型。所以主要的想法是为我们的模型找到合适的参数。我不会详细描述如何计算每一个,但是你可以在这里找到它。在我的例子中,我想使用类似于auto . ARIMA的东西。** 我发现一个有趣的实现——pmdarima。**

" pmdarima "将 R 钟爱的 auto.arima 引入 Python,更有力地证明了为什么数据科学不需要 R。 pmdarima 是 100% Python + Cython,不利用任何 R 代码,而是在一组功能强大但易于使用的函数&类中实现,scikit-learn 用户将会很熟悉这些类。

代码将与前一个非常相似:

**import pmdarima as pmfor index, row in tqdm(df_test.iterrows()): model = pm.auto_arima(tmp.item_cnt_day, start_p=1, start_q=1,  max_p=3, max_q=3, m=12,
start_P=0, seasonal=False,
d=1, D=1, trace=False,
error_action='ignore',  # don't want to know if an order does not work
suppress_warnings=True,  # don't want convergence warnings
stepwise=True)forecast = model_fit.predict(n_periods = n, return_conf_int=False)**

ARIMA 是一个很强的模型,可以给出很好的预测。ARIMA 在预测极端值方面会受到限制。虽然该模型擅长模拟季节性和趋势,但离群值很难预测 ARIMA 的情况,因为它们不在该模型捕捉的总体趋势之内。

因此,经典的时间序列预测方法可能侧重于线性关系,然而,假设你的数据准备充分,方法配置良好,它们是复杂的,并在广泛的问题上表现良好。

机器学习方法

机器学习与统计方法相结合的一个最常见的企业应用是预测分析。它不仅可以估计需求,还可以了解什么推动销售,以及客户在特定条件下可能的行为。使用机器学习模型进行需求预测的主要思想是生成许多有用的特征。

特征工程是使用领域知识数据和创建特征,使机器学习模型预测更准确。它能够更深入地理解数据和更有价值的见解。

该功能可以是:

  • 产品/商店特征(来自商品字典的信息)
  • 关于促销活动和任何价格变化的内部信息
  • 分类变量的不同层次目标编码
  • 日期功能

在我的实验中,我将使用以下 Python 库 CatBoost、XGBoost 和 H2O AML。

先说 XGBoost。

**from xgboost import XGBRegressor**

XGBoost 是一个优化的分布式梯度增强库,设计为高效、灵活和可移植。它在梯度推进框架下实现机器学习算法。XGBoost 本身不能处理分类特征,它只接受类似随机森林的数值。因此,在向 XGBoost 提供分类数据之前,必须执行各种编码,如标签编码、均值编码或一键编码。XGboost 拆分到指定的 max_depth 超参数,然后开始向后修剪树,并移除超出该范围没有正增益的拆分。它使用这种方法是因为有时无损失减少的分割之后可能是有损失减少的分割。XGBoost 还可以执行逐叶树生长。XGBoost 缺失值将被分配到在每次分割中减少损失的一侧。

**# Trainmodel = XGBRegressor(max_depth=8,
n_estimators=1000,
min_child_weight=300,
colsample_bytree=0.8,
subsample=0.8,
eta=0.3,
seed=42)model.fit(X_train,
Y_train,
eval_metric="rmse",
eval_set=[(X_train, Y_train), (X_valid, Y_valid)],
verbose=True,
early_stopping_rounds = 10)**

XGBoost 是用于机器学习的梯度推进算法的一个很好的快速实现,但对我来说,它的主要缺点是不能使用分类因子,并且在结果中,模型可能会丢失一些信息。

下一个库是 CatBoost。

**from catboost import CatBoostRegressor**

Catboost 生长一棵平衡树。在这种树的每一层中,产生最低损失(根据罚函数)的特征分裂对被选择并用于该层的所有节点。使用增长政策参数可以改变其政策。

Catboost 有两种处理缺失值的模式,“最小”和“最大”。在“最小值”中,缺失值被处理为要素的最小值(它们被赋予一个小于所有现有值的值)。这样,可以保证在选择拆分时考虑将缺失值与所有其他值分开的拆分。“最大值”与“最小值”的作用相同,只是具有最大值。

Catboost 结合使用一键编码和高级均值编码。对于类别数量较少的功能,它使用一键编码。一键编码的最大类别数可由参数 one_hot_max_size 控制。对于剩余的分类列,CatBoost 使用一种高效的编码方法,这种方法类似于均值编码,但具有一种旨在减少过度拟合的附加机制。使用 CatBoost 的分类编码带来了模型速度较慢的缺点。

**# Trainmodel=CatBoostRegressor(iterations=100, depth=10, learning_rate=0.03, loss_function='RMSE')model.fit(X_train, Y_train, cat_features = categorical, eval_set=(X_valid, Y_valid))**

CatBoost 提供了有用的工具来轻松处理高度分类的数据。它显示了在未处理的分类特征上训练的可靠结果。

最后一个是关于 H2O 反洗钱的。

**import h2ofrom h2o.automl import H2OAutoMLh2o.init(nthreads = 7, max_mem_size = '45g')**

H2O 的 AutoML 可用于自动化机器学习工作流,包括在用户指定的时间限制内自动训练和调整许多模型。堆叠集成—一个基于所有先前训练的模型,另一个基于每个系列的最佳模型—将在单个模型的集合上自动训练,以产生高度预测的集成模型,在大多数情况下,这些模型将是 AutoML 排行榜中表现最佳的模型。

AutoML 将迭代不同的模型和参数,试图找到最好的。有几个参数需要指定,但在大多数情况下,您需要做的只是设置最大运行时间(秒)或最大模型数。你可以把 AutoML 想成类似于 GridSearch 的东西,但是是在模型的层次上,而不是在参数的层次上。

**# Run AutoMLaml = H2OAutoML(max_models = 5, seed=1)aml.train(y=y, training_frame=x_train_hf,
validation_frame = x_valid_hf)**

AutoML 旨在自动化管道创建和超参数调整等重复性任务,以便数据科学家可以将更多时间花在手头的业务问题上。AutoML 还旨在让每一个人都能使用这项技术,而不是少数人。AutoML 和数据科学家可以协同工作来加速 ML 过程,以便可以利用机器学习的真正有效性。在我的情况下,我在之前的模型中有最好的结果。

深度学习方法

一类强大的机器学习算法,使用人工神经网络来理解和利用数据中的模式。深度学习算法使用多层从原始数据中逐步提取更高级别的特征:这减少了其他机器学习方法中所需的特征提取量。深度学习算法通过使用许多层处理来识别模式,从而自行学习。这也是为什么“深度学习”中的“深”指的是数据被转换的层数。多重转换自动从原始数据中提取重要特征。

这项任务的主要挑战是处理分类变量。在深度学习中,我们可以使用实体嵌入。嵌入是处理分类变量的一种解决方案,同时避免了一次性编码的许多缺陷。嵌入是分类变量到 n 维向量的映射。那么,我们的神经网络结构是什么样子的呢?

使用实体嵌入模式的模型架构。

首先,这个任务的 Python 框架——Keras。这里的主要挑战是编写嵌入每个分类特征的代码。

**import tensorflow as tf
from tensorflow import kerasfrom tensorflow.keras.layers import Input, Dense, Activation, Reshape, BatchNormalization, Dropout, concatenate, Embeddingfrom tensorflow.keras.models import Modelfrom tensorflow.keras.optimizers import Adamfrom tensorflow.keras.callbacks import ModelCheckpoint, ReduceLROnPlateau**

Keras 对这种方法的实现相当庞大。

**model_inputs = []
model_embeddings = []for input_dim, output_dim in emb_space:
           i = Input(shape=(1,))
           emb = Embedding(input_dim=input_dim, output_dim=output_dim)(i)
           model_inputs.append(i)
           model_embeddings.append(emb)con_outputs = []
for con in con_feature: elaps_input = Input(shape=(1,))
        elaps_output = Dense(10)(elaps_input)
        elaps_output = Activation("relu")(elaps_output)
        elaps_output = Reshape(target_shape=(1,10))(elaps_output)
        model_inputs.append(elaps_input)
        con_outputs.append(elaps_output)merge_embeddings = concatenate(model_embeddings, axis=-1)
if len(con_outputs) > 1:
merge_con_output = concatenate(con_outputs)
else:
merge_con_output = con_outputs[0]merge_embedding_cont = concatenate([merge_embeddings, merge_con_output])
merge_embedding_contoutput_tensor = Dense(1000, name="dense1024")(merge_embedding_cont)
output_tensor = BatchNormalization()(output_tensor)
output_tensor = Activation('relu')(output_tensor)
output_tensor = Dropout(0.3)(output_tensor)output_tensor = Dense(500, name="dense512")(output_tensor)
output_tensor = BatchNormalization()(output_tensor)
output_tensor = Activation("relu")(output_tensor)
output_tensor = Dropout(0.3)(output_tensor)output_tensor = Dense(1, activation='linear', name="output", kernel_constraint = NonNeg())(output_tensor)optimizer = Adam(lr=10e-3)nn_model = Model(inputs=model_inputs, outputs=output_tensor)
nn_model.compile(loss='mse', optimizer=optimizer, metrics=['mean_squared_error'])reduceLr=ReduceLROnPlateau(monitor='val_loss', factor=0.2, patience=1, verbose=1)checkpoint = ModelCheckpoint("nn_model.hdf5", monitor='val_loss', verbose=1, save_best_only=True, mode='min')#val_mean_absolute_percentage_error
callbacks_list = [checkpoint, reduceLr]history = nn_model.fit(x=x_fit_train, y=y_train.reshape(-1,1,1),
validation_data=(x_fit_val, y_val.reshape(-1,1,1)),
batch_size=1024, epochs=10, callbacks=callbacks_list)**

所有机器学习功能和实体嵌入方法都显示出比以前的模型稍好的结果,但花费了更多的训练时间。使用嵌入的优势在于它们可以被学习,比其他模型更好地表示每个类别。

因此,我们看到这种方法是好的,但是主要的缺点是大量的代码。

Fastai 是我们的解决方案。Fast.ai 是一种流行的深度学习,它提供高级组件,以在标准深度学习领域获得最先进的结果。Fast.ai 允许从业者进行实验、混合和匹配,以发现新的方法。简而言之,促进无障碍深度学习解决方案。这些库利用了底层 Python 语言的动态性和 PyTorch 库的灵活性。

**from fastai.tabular import ***

训练深度神经网络(DNN)是一个困难的全局优化问题。学习率(LR)是训练 DNNs 时需要调整的一个重要超参数。非常小的学习率会导致非常慢的训练,而非常大的学习率会阻碍收敛,因为损失函数在最小值附近波动,甚至发散。

Fastai 在此框架下实施一周期政策。超收敛使用 CLR 方法,但只有一个周期——包含两个学习速率步骤,一个增加一个减少——和一个大的最大学习速率界限。周期的大小必须小于迭代/时期的总数。在循环完成之后,对于剩余的迭代/时期,学习率将进一步降低,比其初始值低几个数量级。

**#TabularList for Validationval = (TabularList.from_df(X_train.iloc[start_indx:end_indx].copy(), path=path, cat_names=cat_feature, cont_names=con_feature))test = (TabularList.from_df(X_test, path=path, cat_names=cat_feature, cont_names=con_feature, procs=procs))#TabularList for trainingdata = (TabularList.from_df(X_train, path=path, cat_names=cat_feature, cont_names=con_feature, procs=procs)
.split_by_idx(list(range(start_indx,end_indx)))
.label_from_df(cols=dep_var)
.add_test(test)
.databunch())#Initializing the network
learn = tabular_learner(data, layers=[1024,512], metrics= [rmse,r2_score])#Exploring the learning rates
learn.lr_find()
learn.recorder.plot()# Learn 
learn.fit_one_cycle(10, 1e-02)**

结果,我们得到了更少的代码和更快的找到最佳学习率的方法。结果与之前的神经网络架构非常相似。

这种架构工作得很好,但是如果我们想从以前的销售中获得一些信息而不添加滞后功能,该怎么办呢?因此,我们需要添加 LSTM 或 RNN 层到我们的架构。在 Keras 中,这将使代码更加繁琐,并且没有 Fastai 的实现。

我找到了解决这个问题的方法——py torch 预测。

Pytorch Forecasting 旨在通过神经网络简化最先进的时间序列预测,用于现实世界的案例和研究。目标是为专业人员提供一个具有最大灵活性的高级 API,为初学者提供合理的默认值。具体来说,该包提供

  • 一个时序数据集类,抽象处理变量转换、缺失值、随机二次抽样、多个历史长度等。
  • 一个基本模型类,提供时间序列模型的基本训练,以及 tensorboard 登录和一般可视化,如实际 vs 预测和依赖图
  • 用于时间序列预测的多种神经网络体系结构已针对现实世界部署进行了增强,并带有内置的解释功能
  • 多地平线时间序列指标
  • Ranger 优化器用于更快的模型训练
  • 使用 optuna 进行超参数调谐

该软件包基于 PyTorch Lightning 构建,允许对 CPU、单个和多个 GPU 进行开箱即用的培训。

**import torchimport pytorch_lightning as plfrom pytorch_lightning.callbacks import EarlyStopping, LearningRateMonitor
from pytorch_lightning.loggers import TensorBoardLogger
from pytorch_forecasting import Baseline, TemporalFusionTransformer, TimeSeriesDataSet
from pytorch_forecasting.data import GroupNormalizer
from pytorch_forecasting.metrics import SMAPE, PoissonLoss, QuantileLoss, RMSE
from pytorch_forecasting.models.temporal_fusion_transformer.tuning import optimize_hyperparameters
from pytorch_forecasting.data.encoders import NaNLabelEncoder**

在我的例子中,我使用了时间融合转换器【2】。这是一个由牛津大学和谷歌开发的架构,在基准测试中击败了亚马逊的 DeepAR 36–69%。

第一步—我们需要创建一个数据加载器,并为我们的模型创建一个特殊的数据对象。

**max_prediction_length = 1
max_encoder_length = 6
training_cutoff = X_train["time_idx"].max() - max_prediction_lengthtraining = TimeSeriesDataSet(X_train[lambda x: x.time_idx <= training_cutoff],
time_idx="time_idx",
target="log_sales",
group_ids=["shop_id", "item_id"],
min_encoder_length=max_encoder_length // 2,  # keep encoder length long (as it is in the validation set)
max_encoder_length=max_encoder_length,
min_prediction_length=1,
max_prediction_length=max_prediction_length,
static_categoricals=["shop_id", "item_id"],
static_reals=['city_coord_1', 'city_coord_2'],
time_varying_known_categoricals=["month"],
time_varying_known_reals=["time_idx", "delta_price_lag"],
time_varying_unknown_categoricals=["shop_category", "city_code", "item_category_id","type_code", "subtype_code", "country_part"],
categorical_encoders = {"shop_id": NaNLabelEncoder(add_nan=True),"item_id": NaNLabelEncoder(add_nan=True),"shop_category": NaNLabelEncoder(add_nan=True),"city_code": NaNLabelEncoder(add_nan=True),"item_category_id": NaNLabelEncoder(add_nan=True),"type_code": NaNLabelEncoder(add_nan=True),"subtype_code": NaNLabelEncoder(add_nan=True),"country_part": NaNLabelEncoder(add_nan=True),},
time_varying_unknown_reals=['date_cat_avg_item_cnt_lag_1','date_shop_cat_avg_item_cnt_lag_1', 'date_shop_type_avg_item_cnt_lag_1','date_shop_subtype_avg_item_cnt_lag_1','date_city_avg_item_cnt_lag_1','date_item_city_avg_item_cnt_lag_1','date_type_avg_item_cnt_lag_1','date_subtype_avg_item_cnt_lag_1', 'item_shop_last_sale', 'item_last_sale','item_shop_first_sale', 'item_first_sale'],
add_relative_time_idx=True,
add_encoder_length=True,
allow_missings=True
)validation = TimeSeriesDataSet.from_dataset(training,X_train, min_prediction_idx=training.index.time.max() + 1, stop_randomization=True)batch_size = 128train_dataloader = training.to_dataloader(train=True, batch_size=batch_size, num_workers=2)val_dataloader = validation.to_dataloader(train=False, batch_size=batch_size, num_workers=2)**

下一步是找到一个最佳的学习率。

**pl.seed_everything(42)trainer = pl.Trainer(
gpus=1,
# clipping gradients is a hyperparameter and important to prevent divergance
# of the gradient for recurrent neural networks
gradient_clip_val=0.1,
)tft = TemporalFusionTransformer.from_dataset(training,
# not meaningful for finding the learning rate but otherwise very important
learning_rate=0.03,
hidden_size=16,  # most important hyperparameter apart from learning rate
# number of attention heads. Set to up to 4 for large datasets
attention_head_size=1,
dropout=0.1,  # between 0.1 and 0.3 are good values
hidden_continuous_size=8,  # set to <= hidden_size
output_size=1,  # 7 quantiles by default
loss=RMSE(),
# reduce learning rate if no improvement in validation loss after x epochs
reduce_on_plateau_patience=4,
)print(f"Number of parameters in network: {tft.size()/1e3:.1f}k")# find optimal learning ratetorch.set_grad_enabled(False)res = trainer.tuner.lr_find(
tft,
train_dataloader=train_dataloader,
val_dataloaders=val_dataloader,
max_lr=10.0,
min_lr=1e-6
)print(f"suggested learning rate: {res.suggestion()}")
fig = res.plot(show=True, suggest=True)
fig.show()**

现在我们可以配置我们的神经网络并训练它。

**early_stop_callback = EarlyStopping(monitor="val_loss", min_delta=1e-4, patience=10, verbose=False, mode="min")lr_logger = LearningRateMonitor()  # log the learning rate
logger = TensorBoardLogger("lightning_logs")  # logging results to a tensorboardtrainer = pl.Trainer(max_epochs=30,
gpus=1,
weights_summary="top",
gradient_clip_val=0.1,
limit_train_batches=30,  # coment in for training, running valiation every 30 batches
# fast_dev_run=True,  # comment in to check that networkor dataset has no serious bugs
callbacks=[lr_logger, early_stop_callback],
logger=logger,
)tft = TemporalFusionTransformer.from_dataset(training,
learning_rate=0.03,
hidden_size=16,
attention_head_size=4,
dropout=0.1,
hidden_continuous_size=8,
output_size=1,  # 7 quantiles by default
loss=RMSE(),
log_interval=10,  # uncomment for learning rate finder and otherwise, e.g. to 10 for logging every 10 batches
reduce_on_plateau_patience=4
)print(f"Number of parameters in network: {tft.size()/1e3:.1f}k")# fit networktrainer.fit(tft,
train_dataloader=train_dataloader,
val_dataloaders=val_dataloader
)**

此外,我们可以调整我们的模型,找到最佳的超参数。

**from pytorch_forecasting.models.temporal_fusion_transformer.tuning import optimize_hyperparameters# create studystudy = optimize_hyperparameters(train_dataloader,
val_dataloader,
model_path="optuna_test",
n_trials=200,
max_epochs=50,
gradient_clip_val_range=(0.01, 1.0),
hidden_size_range=(8, 128),
hidden_continuous_size_range=(8, 128),
attention_head_size_range=(1, 4),
learning_rate_range=(0.001, 0.1),
dropout_range=(0.1, 0.3),
trainer_kwargs=dict(limit_train_batches=30),
reduce_on_plateau_patience=4,
use_learning_rate_finder=False,  # use Optuna to find ideal learning rate or use in-built learning rate finder
)# save study results - also we can resume tuning at a later point in timewith open("test_study.pkl", "wb") as fout:
     pickle.dump(study, fout)# show best hyperparametersprint(study.best_trial.params)**

结果,我得到了一个具有所有特性和方法的良好性能模型,可以用于时间序列预测。

全体

堆叠或堆叠概括是一种集成机器学习算法。它使用元学习算法来学习如何最好地组合来自两个或更多基本机器学习算法的预测。

我们可以用叠加的方法把几个模型结合起来,做出新的预测。

堆叠模型的体系结构包括两个或多个基本模型,通常称为 0 级模型,以及一个组合了基本模型预测的元模型,称为 1 级模型。

  • 0 级模型(基础模型 ) :符合训练数据的模型,其预测被编译。**
  • 一级模型(元模型 ) :学习如何最好地组合基础模型预测的模型。**

元模型是根据基本模型基于样本外数据所做的预测来训练的。也就是说,未用于训练基本模型的数据被馈送到基本模型,进行预测,并且这些预测与预期输出一起提供了用于拟合元模型的训练数据集的输入和输出对。用作元模型输入的基础模型的输出在回归的情况下可以是真实值,在分类的情况下可以是概率值、类概率值或类别标签。

对于堆叠,我们可以使用 sk learn . ensemble . Stacking regressor。

**from mlxtend.regressor import StackingCVRegressor
from sklearn.datasets import load_boston
from sklearn.svm import SVR
from sklearn.linear_model import Lasso
from sklearn.ensemble import RandomForestRegressor
from sklearn.model_selection import cross_val_scorestack = StackingCVRegressor(regressors=(svr, lasso, rf),    meta_regressor=lasso,random_state=RANDOM_SEED)**

堆叠回归是一种集成学习技术,通过元回归器组合多个回归模型。基于完整的训练集来训练各个回归模型;然后,基于集合中各个回归模型的输出(元特征)来拟合元回归量。

结论

这种分析的结果是,我们可以看到时间序列预测并没有停留。每天我们都能找到新的方法和新的框架。在本文中,我试图收集其中的一些,并展示如何在真实案例中实现它们。从我的经验来看,组合策略在需求预测问题上有潜在的应用,在趋势和平稳序列方面优于其他最先进的模型,并且具有与其他模型相当的准确性。所有这些都取决于输入数据和业务目标,但是我希望这些模型能够帮助您为您的业务创建自己的最先进的方法。

感谢阅读。

你能在 Git 仓库中找到的所有代码— 链接

用 R 民主化历史天气数据分析

原文:https://towardsdatascience.com/democratizing-historical-weather-data-with-r-cc3c76dde7c5?source=collection_archive---------11-----------------------

实践教程

园丁指南、移居到不同气候的人或任何其他可能对分析天气数据感兴趣的人

叶戈尔·迈兹尼克Unsplash 上拍摄的照片

动机

作为一名数据科学家,我对寻找天气数据来对销售进行回归分析很感兴趣。也就是说,我想了解天气是否对网上或店内销售有可衡量的影响。在过去的十年里,我研究过与天气相关的类似商业问题,我希望下面的教程可以帮助其他人解决类似的问题。

当我开始园艺并为一个地区选择合适的植物时,我发现下面的地图作为经验法则提供了有用的信息。现在,我和我的伴侣在我们的住所周围拥有土地,并可以投资于我们的园艺雄心,我更深入地研究了这些统计数据的含义和数据的来源。有了今天的公开数据,就有可能计算出你附近某个邮政编码(ZIP code)的这些统计数据。我发现数据分析很有趣,而且比在打印出来的地图上使用放大镜更准确。拥有可用于回答特定问题的数据也是有帮助的。

  • 美国农业部植物抗寒区域地图——这是我在美国园艺中心和苗圃看到的最常见的地图;用于选择能熬过冬天的植物
  • 冷却时间图——如果你想种植桃树、樱桃树和其他需要最短冷却时间才能结果的植物
  • 美国降水地图——即使你有稳定的水源,规划景观时,降雨也会影响许多考虑因素
  • 去年春季冻结——农民年鉴和该地区的园丁和农民也是了解什么时候可以在春天开始种植的好资源。
  • 霜冻深度图——如果你计划在栅栏柱或灌溉线中挖掘,了解土地上预期的霜冻深度会很有帮助。
  • 植物热区地图——某些植物过热可能是个问题。

数据

对于以下地块,每日降水和温度数据已通过在线搜索&下载选项从 NOAA 国家环境信息中心(Climate.gov)以逗号分隔值(CSV)文件的形式获得。该数据包含以下各列:

  • 日期=年-月-日
  • STATION =气象站 ID
  • NAME =气象站的描述
  • PRCP =降雨量(英寸)
  • 雪=降雪量中的降水量(英寸)
  • TMIN =每日最低温度

这些数据可以在电子表格中进行分析,但是如果您希望对于任何邮政编码只需点击一个按钮就可以重复这个过程,那么用 R 编写程序可能是一个更好的方法。

如果你想继续,你可以用一个免费的 GitHub 账户复制我的 GitHub“天气”库(towardsDS 文件夹)。或者你可以直接下载 CSV 文件,如果你去这个链接,并保存页面为…

R 和 RStudio 快速提示(包括安装)

如果您已经使用 R,您可以跳过这一部分。对于新用户来说,安装过程在很多网站上都有记录,但这应该会给你指明正确的方向。对于数据分析和建模,我推荐使用 RStudio 和 r。

  1. 从克兰库下载并安装 R,你可以在r-project.org/找到。为下载选择你选择的克兰镜子。
  2. RStudio 下载页面下载并安装 RStudio。免费的桌面版是最好的开始。
  3. 打开 RStudio 创建一个新文件,如果您想继续操作,请选择File > New File > R Script。R Markdown 和其他选项也很棒,但在本教程中,我们将使用一个简单的 R 脚本。
  4. 或者,当您使用 RStudio 打开现有文件时,如果 RStudio 尚未打开,RStudio 会自动将您的目录路径设置为该文件的路径。
  5. 在 RStudio 中,点击Tools > Install Packages…安装脚本中使用的库。
  6. 要一次执行一行代码,将光标放在那一行上,在 Mac 上按下Command+Enter,在 PC 上按下Control+Enter。如果代码使用管道符或右括号扩展到另一行,则执行整个代码块,并移动光标。
  7. 要查看或复制完整的 R 脚本而不是下面的片段,请访问 Github 上的完整 R 脚本。

历史天气分析:雨和雪

首先,导入tidyverse库,使用它的read_csv()函数导入天气数据。tidyverse是包括dplyrtidyrggplot2和其他库的集合。要了解更多关于tidyverse的信息,请阅读数据科学的 R。

该脚本中的其他库提供了与日期(lubridate)进行数据交换的函数,以及使用图形库ggplot2 ( ggthemesggtext)的语法定制绘图的函数。

输出:

spec_tbl_df [29,342 × 6] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
 $ STATION: chr [1:29342] "USW00024229" "USW00024229" "USW00024229" "USW00024229" ...
 $ NAME   : chr [1:29342] "PORTLAND INTERNATIONAL AIRPORT, OR US" "PORTLAND INTERNATIONAL AIRPORT, OR US" "PORTLAND INTERNATIONAL AIRPORT, OR US" "PORTLAND INTERNATIONAL AIRPORT, OR US" ...
 $ DATE   : Date[1:29342], format: "1940-10-14" "1940-10-15" ...
 $ PRCP   : num [1:29342] 0 0 0 0.13 0 0 0.14 0.05 0 0.63 ...
 $ SNOW   : num [1:29342] 0 0 0 0 0 0 0 0 0 0 ...
 $ TMIN   : num [1:29342] 53 52 50 58 58 59 54 48 41 53 ...
 - attr(*, "spec")=
  .. cols(
  ..   STATION = col_character(),
  ..   NAME = col_character(),
  ..   DATE = col_date(format = ""),
  ..   PRCP = col_double(),
  ..   SNOW = col_double(),
  ..   TMIN = col_double()
  .. )

天气数据现已导入数据框csv_data。检查的一个关键点是数据中气象站的数量,因为我们希望一次只研究一个气象站。str()函数显示了数据框的结构,以及至少有四个气象站的数据在这个邮政编码中。

在下一步中,我们将选择一个气象站进行剩余的分析,方法是对一个气象站进行过滤,并执行由管道%>%语法(由tidyverse启用)分隔的其他数据争论任务。

输出:

# A tibble: 1 x 3
  NAME                                  min_date   max_date  
* <chr>                                 <date>     <date>    
1 PORTLAND INTERNATIONAL AIRPORT, OR US 1940-10-14 2021-02-12

CSV 文件包含该站从1940–10–142021-02–12的数据。因为我们只想查看整年的数据,所以在下面的代码块中,数据被过滤到从 1941 年到 2020 年的范围内。

现在我们有了 80 年的可用数据,我们可以回答诸如“降雨量最多的一天是哪一天,那天测得的降雨量是多少英寸?”

输出:

# A tibble: 2 x 6
  STATION     NAME                      DATE        PRCP  SNOW  TMIN
  <chr>       <chr>                     <date>     <dbl> <dbl> <dbl>
1 USW00024229 PORTLAND INTERNATIONAL... 1943-01-21  1.1   14.4    19
2 USW00024229 PORTLAND INTERNATIONAL... 1996-11-19  2.69  NA      34

俄勒冈州波特兰机场(PDX)气象站记录的最高降雨量是1996–11–192.69英寸。有记录以来最高降雪量出现在1943–01–21,测量值为14.4英寸。

我最喜欢的了解一个地区气候的方法是查看月降雨量的方框图。你也许能找到你所在地区的数据,或者至少类似于维基百科上的气候图表,但是有了 R,你可以通过邮政编码或任何其他可能没有公布图表的粒度来聚焦数据。此外,您可能想知道图表中包含的数据的时间段,并尝试使用不同的日期范围的影响。

输出:

这个图像是由它上面的代码块创建的

使用过去 80 年的数据合适吗,还是只使用最近 20 年的数据更能反映气候?对于这个特定的邮政编码,额外的(或更少的)数据并没有显著地改变图形,但是我选择显示完整的 80 年,因为图中显示的额外异常值很有趣。

现在让我们来看看降雪图。由于降雪在这个邮政编码区不太常见,下面的图是基于每年的降雪。

输出:

这个图像是由它上面的代码块创建的

有趣的是,仅检查过去 20 年的数据与检查整个 80 年的数据会产生非常不同的结果。在过去的二十年里,这个地区很少出现可测量的降雪量,尽管最近五年已经恢复了上个世纪的趋势。

历史天气分析:冰冻温度

园丁会关注天气预报,而敏锐的园丁也会想了解历史趋势。一个特别有趣的地方是每年春天的最后一次冰冻。如果种子或种子种植过早,它们可能会被晚霜冻坏。在生长季节的另一端,每年秋季的第一次冰冻是一个很好的迹象,表明何时确保无法承受早期霜冻的作物完成收获。

输出:

这个图像是由它上面的代码块创建的

从视觉上吸收这一数据,似乎最近几年的最后一次冻结发生在 3 月份。当地人认为在 4 月中旬之前播种是有风险的,这似乎得到了过去 30 年数据的支持。尽管在最近几年,土壤已经被冬雨和春雨浸透,无论如何也不允许提早种植。

历史天气分析:植物耐寒区

我要分享的最后一个分析是关于植物的抗寒性。与俄勒冈州立大学(OSU)合作制作的美国农业部植物抗寒区域地图显示了 1976 年至 2005 年的年平均极端最低温度。虽然重建这样一个地图的工作量很大,但我们可以为特定的邮政编码重建一个更新的数据点。

大多数苗圃都在每一种树木、灌木和其他多年生植物上贴上植物耐寒区的标签,以表明每一种植物可能在哪里熬过寒冷的月份,进入下一年。97218 邮政编码似乎属于 8b 区的颜色,这意味着种植可能在 15 至 20 华氏度的年极端低温下存活的品种是安全的。让我们将 1976 年至 2005 年的数据与 1991 年至 2020 年的更新数据进行比较,看看是否有任何重大变化。

产量(1976 年至 2005 年):

year           annual_extreme_low
 Min.   :1976   Min.   : 9.00     
 1st Qu.:1983   1st Qu.:14.00     
 Median :1990   Median :19.00     
 Mean   :1990   Mean   :19.20     
 3rd Qu.:1998   3rd Qu.:24.75     
 Max.   :2005   Max.   :27.00

产出(1991 年至 2020 年):

year           annual_extreme_low
 Min.   :1991   Min.   :11.00     
 1st Qu.:1998   1st Qu.:18.00     
 Median :2006   Median :22.00     
 Mean   :2006   Mean   :20.77     
 3rd Qu.:2013   3rd Qu.:25.75     
 Max.   :2020   Max.   :27.00

较新的 30 年平均水平的年平均极端低气温上升了 1.6 华氏度(现在是 20.8 华氏度,相比之下是 19.2 华氏度)。这一变化,现在高于 20,足以将这个邮政编码放入 9a 耐寒区。事实上,如果你注意到颜色之外的注释,该地区的小气候可能已经被标注在美国农业部/OSU 地图的 9a 耐寒区。也许这可能是由于大都市区的热岛效应。

学习和分享

我希望你喜欢这篇教程——如果这是你第一次使用 R——我希望这能激励你学习更多,并使数据分析民主化!

如果你想读(写)更多这样的文章,请考虑使用我的推荐链接注册媒体:【https://sabolch-horvat.medium.com/membership

[2021–12–18 更新]:在“数据”中,添加了有关如何直接从 GitHub 访问 CSV 数据文件的信息。

基于客流量数据的得梅因农贸市场人口统计分析

原文:https://towardsdatascience.com/demographic-analysis-of-the-des-moines-farmers-market-with-foot-traffic-data-ca998e0786dc?source=collection_archive---------39-----------------------

了解如何分析非 POI 事件的客流量,如农贸市场、示威游行、博览会等

Unsplash 上由 Dane Deaner 拍摄的照片

有些活动,如传说中的得梅因农贸市场,并不局限于特定的兴趣点,即传统上可用的客流量数据的级别。许多实体可能对分析农贸市场的客流量感兴趣,例如当地酒店/餐馆、得梅因市、潜在供应商和学术研究人员。

以下是分析得梅因农贸市场客流量时遇到的一些挑战:

  • 它对应于包含更多传统兴趣点的大区域,如餐馆、银行等
  • 在某些月份,农贸市场只在周六占据该区域
  • 农贸市场内的摊贩位置每周都在变动

别害怕, 邻里模式 就在这里!

有了邻居模式,我们可以回答关于游客数量、他们来自哪里、他们停留了多长时间等问题。更好的是,这个数据集和其他数据集对学者是免费的。如果您想扩展这一分析,或者使用步行交通数据研究您自己的问题,请访问 SafeGraph 社区

要自己运行代码和处理数据,请查看随附的 Colab 笔记本**

设置

之前的每一次激动人心的分析都是有点无聊的(然而重要!)设置部分。为了简单起见,我们将跳过一些无聊的东西(导入、安装、读取数据等)。请随意查看 Colab 笔记本中的代码片段!

来看看我们的数据吧!第一个数据框架是得梅因市中心的安全图社区模式。具体来说,我们已经过滤到包含得梅因农贸市场的人口普查区块组。人口普查区块组(CBG)是聚集邻里模式数据的地理区域,方便的是,人口普查数据也聚集在 CBG 级别。**

安全图邻域模式中列的子集。

Neighborhood Patterns 有很多有用的专栏。在本文中我们将只使用weekend_device_home_areas,但是您可以编辑代码以使用您认为合适的其他列!完整的列列表可在文档中找到。

weekend_home_device_areas列很重要,所以让我们把它分解一下。每个条目都是一个 JSON 对象(或 Python 字典),其中的键是一个 CBG,值是居住在该 CBG 的访问者数量。此外,这些访问都发生在周末。该行指定了访问发生的日期范围。总之,这个专栏告诉我们周末去得梅因市中心的游客的家。

我们的下一个数据集是人口普查数据。这些数据让我们可以提出关于访客人口统计的问题。农贸市场访客的平均年龄是多少?收入分配是什么样的?人口普查数据有很多列;为简单起见,我们将只使用年龄中位数和收入中位数。同样,如果您想研究其他专栏,请随意更改代码——您可以在几秒钟内访问重新创建该分析所需的所有代码/数据!

普查数据中列的子集。

注意第一列:census_block_group该列使我们能够将人口统计数据与邻里模式访问数据结合起来。为了做到这一点,我们需要首先从weekend_device_home_areas中提取 CBG 级别的访问者数量。我们垂直分解该列,以便每行中的每个键值对都有自己的行。我们还将重新格式化日期列,以便于阅读。**

垂直展开“周末 _ 设备 _ 家庭 _ 区域”列后的邻域模式子集

现在,我们可以将两个数据集连接起来,查看周末去过得梅因市中心的每个 CBG 的平均年龄和平均收入。

我们的合并数据集。

分析

我们的分析将保持相当简单。我们会看看 2018 年和 2019 年每个月的年龄中位数和收入中位数分布(注:得梅因农贸市场只在 5 月到 10 月营业)。为了做到这一点,我们创建了直方图,其中每一行根据访问者的数量进行加权(weekend_device_home_areas_value)。

得梅因市中心周末游客的收入中位数分布。

平均值从 75,347 美元到 79,948 美元不等。有趣的是,平均收入在九月和十月下降。

现在让我们来看看同样的中位年龄可视化。

得梅因市中心周末游客的平均年龄分布。

平均年龄从 36.6 岁到 37.8 岁不等。同样,相对于 6 月和 7 月,我们看到 9 月和 10 月有所下降!

有人可能会假设,我们在 9 月和 10 月看到的收入和年龄下降是由大学生返校造成的。我们将在第二部分测试这个假设:绘制得梅因农贸市场的游客地图!

结论

在本文中,我们介绍了如何分析得梅因农贸市场游客的人口统计数据,该市场仅限于一个区域,而不是传统的兴趣点。这一切都是通过 SafeGraph 的邻居模式(对学术界免费)和美国人口普查数据(对所有人免费)实现的。

我们的分析表明,9 月和 10 月的收入和年龄都略有下降。我们假设这是由得梅因的大学生返校造成的。虽然我们不会从统计上检验这个假设,但在地图上可视化可能会给我们一些启示!敬请关注第二部分,即将推出!

疑问?

我邀请你在 SafeGraph 社区#safegraphdata 频道问他们,这是一个面向数据爱好者的免费 Slack 社区。获得支持、共享您的工作或与 GIS 社区中的其他人联系。通过 SafeGraph 社区,学者们可以免费访问美国、英国和加拿大 700 多万家企业的数据。

揭秘:Wasserstein GAN 与梯度惩罚(WGAN-GP)

原文:https://towardsdatascience.com/demystified-wasserstein-gan-with-gradient-penalty-ba5e9b905ead?source=collection_archive---------5-----------------------

什么是梯度惩罚?为什么比渐变裁剪好?如何实施梯度惩罚?

图 1(左)使用权重剪裁时的梯度范数不是爆炸就是消失,不使用 GP。(右)与 GP 不同,权重剪裁将权重推向两个值。图像来源:[1]

在这篇文章中,我们将研究 Wasserstein GANs 的梯度惩罚。虽然最初的 Wasserstein GAN[2]提高了训练的稳定性,但仍然存在产生差的样本或不能收敛的情况。概括一下,WGAN 的成本函数是:

情商。1: WGAN 值函数。

其中 f 是1-Lipschitz 连续。WGAN 出现的问题主要是因为用于在 critical 上加强 Lipschitz 连续性的权重裁剪方法。WGAN-GP 用对 critic 的梯度范数的约束来代替权重裁剪,以加强 Lipschitz 连续性。这允许比 WGAN 更稳定的网络训练,并且需要非常少的超参数调整。WGAN-GP,这篇文章建立在 Wasserstein GANs 的基础上,这已经在 揭秘系列 的上一篇文章中讨论过了。查看下面的帖子来了解 WGAN。

报表 1

可微的最优 1-Lipschitz 函数, f* 最小化等式。1 在ℙr 和ℙg.下几乎处处都有单位梯度范数

ℙr 和ℙg 分别是真实和虚假的分布。陈述 1 的证明可以在[1]中找到。

渐变剪辑的问题

容量未充分利用

图 WGAN critic(上)使用梯度裁剪(下)使用梯度惩罚学习的值表面。图像来源:[1]

使用权重剪辑来加强 k-Lipschitz 约束导致评论家学习非常简单的函数。

从陈述 1 中,我们知道最优评论家的梯度范数几乎在ℙr 和ℙg.的任何地方都是 1。在权重剪辑设置中,评论家试图获得其最大梯度范数 k ,并最终学习简单的函数。

图 2 显示了这种效果。批评者被训练为收敛于固定生成的 distribution(ℙg)作为真实的 distribution(ℙr)+单位高斯噪声。我们可以清楚地看到,用权重裁剪训练的评论家最终学习简单的函数,并且不能捕捉更高的矩,而用梯度惩罚训练的评论家没有遭受这个问题。

爆炸和消失渐变

权重约束和损失函数之间的相互作用使得 WGAN 的训练变得困难,并导致爆炸或消失梯度。

这可以在图 1(左)中清楚地看到,对于不同的削波值,评论家的权重爆炸或消失。图 1(右)还示出了梯度剪切将评论家的权重推至两个极端剪切值。另一方面,受过梯度惩罚训练的批评家不会受到这些问题的困扰。

梯度惩罚

梯度惩罚的思想是实施一个约束,使得批评家的输出相对于输入的梯度具有单位范数(陈述 1)。

作者提出了这种约束的软版本,对样本上的梯度范数进行惩罚 ∈ ℙ 。新的目标是

情商。2:批评家损失函数

在 Eq 中。2 总和左边的项是原始临界损失,总和右边的项是梯度损失。

是通过沿着真实分布和生成分布ℙr 和ℙg.之间的直线均匀采样而获得的分布。这样做是因为最佳评论家在从ℙr 和ℙg.耦合的样本之间具有单位梯度范数的直线

λ,惩罚系数用于加权梯度惩罚项。在这篇论文中,作者为他们所有的实验设定λ=10。

batch normalization 不再用于 critic,因为 Batch norm 将一批输入映射到一批输出。在我们的案例中,我们希望能够找到每个输出相对于各自输入的梯度。

密码

梯度惩罚

梯度惩罚的实现如下所示。

WGAN-GP

训练 WGAN-GP 模型的代码可在此处找到:

输出

图 3:WGAN-GP 模型生成的图像。请注意,这些结果是早期结果,一旦确认模型正在按预期进行训练,就停止训练。图片来源:[3]

图 3 显示了训练 WGAN-GP 的一些早期结果。请注意,图 3 中的图像是早期结果,一旦确认模型正在如预期那样训练,就停止训练。该模型没有被训练收敛。

结论

Wasserstein GANs 在训练生成性对抗网络方面提供了急需的稳定性。然而,使用梯度裁剪导致各种问题,如爆炸和消失梯度等。梯度惩罚约束没有这些问题,因此与原始 WGAN 相比,允许更容易的优化和收敛。这篇文章着眼于这些问题,介绍了梯度惩罚约束,并展示了如何使用 PyTorch 实现梯度惩罚。最后提供了训练 WGAN-GP 模型的代码以及一些早期输出。

如果你喜欢这篇文章,可以考虑关注作者, Aadhithya Sankar

参考

[1] Gulrajani,Ishaan 等,“改善 wasserstein gans 的训练” arXiv 预印本 arXiv:1704.00028 (2017)。

[2] Arjovsky、Martin、Soumith Chintala 和 Léon Bottou。"沃瑟斯坦生成性对抗网络."机器学习国际会议。PMLR,2017。

[3]https://github.com/aadhithya/gan-zoo-pytorch

作者的更多帖子

如果你喜欢这篇文章,你可能也会喜欢:

揭秘:瓦瑟斯坦·甘斯(WGAN)

原文:https://towardsdatascience.com/demystified-wasserstein-gans-wgan-f835324899f4?source=collection_archive---------5-----------------------

什么是瓦瑟斯坦距离?用 Wasserstein 距离训练 GANs 背后的直觉是什么?是如何实现的?

图 1:学习区分两个高斯函数时的最佳鉴别器和批判器[1]。

在这篇文章中,我们将了解 Wasserstein GANs。具体来说,我们将关注以下内容:I)什么是 Wasserstein 距离?,ii)为什么使用它?iii)我们如何使用它来训练 GANs?

瓦瑟斯坦距离

Wasserstein 距离(推土机距离)是给定度量空间上两个概率分布之间的距离度量。直观上,它可以被视为将一种分布转换为另一种分布所需的最小功,其中功被定义为必须移动的分布的质量与移动距离的乘积。数学上,它被定义为:

情商。1:分布 P_r 和 P_g 之间的 Wasserstein 距离

在 Eq 中。1,π(P_r,P_g)是在 xy 上的所有联合分布的集合,使得边际分布等于 P_r 和 P _ g。γ(x,y)可以被视为必须从 x 移动到 y 以将 P _ r 转换为 P_g[1]的质量量。瓦瑟斯坦距离就是最优运输计划的成本。

瓦瑟斯坦距离与詹森-香农散度

最初的 GAN 目标是 Jensen-Shannon 散度的最小化[2]。JS 散度定义为:

情商。2:P _ r 和 P_g 之间的 JS 背离 P_m = (P_r + P_g)/2

与 JS 相比,Wasserstein 距离具有以下优势:

  • Wasserstein 距离是连续的,几乎处处可微,这允许我们将模型训练到最优。
  • 随着鉴别器变得更好,JS 发散局部饱和,因此梯度变为零并消失。
  • Wasserstein 距离是一个有意义的度量,即,当分布彼此接近时,它收敛到 0,而当它们远离时,它发散。
  • Wasserstein 距离作为目标函数比使用 JS 散度更稳定。当使用 Wasserstein 距离作为目标函数时,也减轻了模式崩溃问题。

从图 1 中我们可以清楚地看到,最佳 GAN 鉴频器饱和并导致梯度消失,而优化 Wasserstein 距离的 WGAN critic 始终具有稳定的梯度。

要获得数学证明和对这个话题更详细的了解,请点击这里查看论文!

瓦瑟斯坦·甘

现在可以清楚地看到,优化 Wasserstein 距离比优化 JS 散度更有意义,还需要注意的是,等式 1 中定义的 Wasserstein 距离非常难以处理[3],因为我们不可能计算所有γ∈π(Pr,Pg)的下确界(最大下界)。然而,从 Kantorovich-Rubinstein 对偶来看,

情商。3:1-lip schitz 条件下 Wasserstein 距离。

这里我们有 W(P_r,P_g)作为所有 1-Lipschitz 函数 f: X → R 上的上确界(最低上界)

K-Lipschitz 连续:给定 2 个度量空间(X,d_X)和(Y,d_Y),变换函数 f: X → Y 是 K-Lipschitz 连续的若

情商。3: K-Lipschitz 连续性。

其中 d_X 和 d_Y 是它们各自度量空间中的距离函数。当函数是 K-Lipschitz 时,从等式。2,我们最后得到 K ∙ W(P_r,P_g)。

现在,如果我们有一族 K-Lipschitz 连续的参数化函数{f_w},其中 w∈W,我们可以得到

情商。4

即 w∈W 最大化 Eq。4 给出 Wasserstein 距离乘以一个常数。

WGAN 评论家

为了达到这个效果,WGAN 引入了一个批评家,而不是我们已经知道的 GANs 的歧视者。critic 网络在设计上类似于鉴频器网络,但通过优化来预测 Wasserstein 距离,以找到将使等式 4 最大化的 w* 。为此,评论家的客观职能如下:

情商。5:批评家目标函数。

这里,为了在函数 f 上加强 Lipschitz 连续性,作者求助于将权重 w 限制到紧空间。这是通过将砝码夹紧在一个小范围内(论文[1]中的[-1e-2,1e-2])来实现的。

鉴别器和鉴别器的区别在于,鉴别器被训练来正确地识别来自 P_r 的样本和来自 P_g 的样本,鉴别器估计 P_r 和 P_g 之间的 Wasserstein 距离。

下面是训练评论家的 python 代码。

WGAN 发生器目标

自然,生成器的目标是最小化 P_r 和 P_g 之间的 Wasserstein 距离。生成器试图找到θ ***** ,使 P_g 和 P_r 之间的 Wasserstein 距离最小化。为此,生成器的目标函数如下:

情商。6:发电机目标函数。

这里,WGAN 发生器和标准发生器之间的主要区别还是 WGAN 发生器试图最小化 P_r 和 P_g 之间的 Wasserstein 距离,而标准发生器试图用产生的图像欺骗鉴别器。

下面是训练生成器的 python 代码:

培训结果

图 WGAN 训练的早期结果[3]。

图 2 显示了训练 WGAN 的一些早期结果。请注意,图 2 中的图像是早期结果,一旦确认模型正在如预期那样训练,就停止训练。

密码

瓦塞尔斯坦甘的完整实现可以在这里找到https://github.com/aadhithya/gan-zoo-pytorch【3】。

结论

WGANs 提供稳定的训练和有意义的训练目标。本文介绍并直观地解释了 Wasserstein 距离是什么,Wasserstein 距离相对于标准 GAN 使用的 Jensen-Shannon 散度的优势,以及 Wasserstein 距离如何用于训练 WGAN。我们还看到了训练批判者和生成器的代码片段,以及训练模型的早期阶段的大量输出。尽管 WGAN 相对于标准 GAN 有许多优势,但 WGAN 论文的作者明确承认,权重裁剪并不是增强 Lipschitz 连续性的最佳方式[1]。为了解决这个问题,他们提出了 Wasserstein GAN 梯度罚函数[4],我们将在以后的文章中讨论。

如果你喜欢这篇文章,看看这个系列的下一篇文章关于 WGAN-GP

参考

[1] Arjovsky、Martin、Soumith Chintala 和 Léon Bottou。"沃瑟斯坦生成性对抗网络."机器学习国际会议。PMLR,2017。

[2]伊恩·古德费勒等,“生成性对抗性网络”美国计算机学会的通讯63.11(2020):139–144。

[3]甘-动物园-py torch()https://github.com/aadhithya/gan-zoo-pytorch)。

[4] Gulrajani,Ishaan 等,“改善 wasserstein gans 的训练” arXiv 预印本 arXiv:1704.00028 (2017)。

构建您的第一个神经网络,并学习深度学习术语

原文:https://towardsdatascience.com/demystify-deep-learning-terminologies-and-build-your-first-neural-network-c408d2456df2?source=collection_archive---------27-----------------------

深度学习、神经网络、Tensorflow 和 Keras 的初学者入门,包括实际操作

图片由皮克斯拜的 Gerd Altmann 提供

深度学习是机器学习的一个分支,通过它,你向机器输入数据答案,机器计算出规则,并由此得出答案。答案是数据代表的标签,例如关于房价的数据,标签是价格,数据是影响价格的房子的各个方面。另一个例子是关于猫和狗的图像数据,标签是动物是猫还是狗。**

定义关键术语

人工神经网络,或称 ann,是深度学习的基石。人工神经网络于 1943 年首次推出,由于大量的大数据、计算能力的大幅提高以及大量的关注和资金投入,它们的应用最近已经起飞。

神经网络的组成部分

下图是神经网络的基本表示。

图片来自 PixabayAhmed Gad

神经元人工神经元是具有一个或多个输入和一个输出的单元或节点。每个输入都有一个相关的权重,可以在训练过程中进行修改。上面的笑脸圈各代表一个神经元。

——这是指在神经网络中特定深度一起工作的神经元的集合。在上图中,每一列代表一个,网络有 3 层;第一层(输入层)有 3 个神经元,第二层(隐藏层)有 2 个神经元,第三层(输出层)有 1 个神经元。

密集层 —这是指一组完全连接的神经元,其中层中的每个神经元都与下一层中的每个神经元连接。密集层是最常见的类型的层

深层神经网络(DNN)——这是指一个神经网络包含一个隐藏层的深层堆栈(中间的几列)。深度学习因此是一个研究包含深度计算堆栈的模型的领域。

tensor flow——这是一个开源平台,包含了很多机器学习所需的常用算法。在这里,您可以创建和使用机器学习模型,而不必学习幕后进行的所有底层数学和逻辑。

Keras —这是一个简单灵活的高级深度学习 API,用于构建、训练、评估和运行神经网络。Tensorflow 捆绑了自己的 Keras 实现tf.keras

损失函数 —通过比较期望输出(y)和网络实际输出(ŷ)来测量网络的输出误差,并返回误差。损失函数的例子均方误差和交叉熵。

优化器 —这是一种修改神经网络属性的技术,如权值学习率以减少损失。示例是随机梯度下降和 Adam。

训练一个模型

在这种情况下,机器使用一套算法从一组给定的数据中学习输入,并可以识别区分它们的底层模式。让我们举一个简单的例子,数据有 2 列 x 和 y,6 行,x 和 y 之间的关系是 y=2x+1。因此,x 是输入数据,y 是标签。

首先,神经网络做一个胡乱的猜测,也许是 y=9x+9,通过计算损失函数(如均方误差)将 Y 的实际输出与猜测进行比较。然后优化器函数(比如随机梯度下降)通过最小化损失来进行另一个猜测,可能会得出类似 y=4x+4 的结果。然后,它将重复给定数量的时期(重复上述过程)。我们将在下面的代码中实现这一点。

神经网络的简单实现

数据

下表显示了上述数据。我们有两列,x 和 y,这两个集合之间有一个关系,即对于任何给定的行,y 的值=2x+1。

按作者分类的表格

我们将向我们的神经网络提供数据,并让它确定这两个集合之间的关系。x 是输入数据(或输入要素), y 是标注。因此,我们在这里向神经网络提供数据 (x)和答案 (y),它的任务是识别将 x 映射到 y 的规则(公式),以便它能够在给定 x 值之前预测 y 值。

安装软件包

由于 Keras 捆绑了 Tensorflow 2.0 及以上版本,我们只需安装 Tensorflow 即可。如果您的机器上安装了 python 环境,您可以使用下面的代码行安装 CPU 版本。省略-cpu会安装 GPU 版本。

pip install tensorflow-cpu

按照这个教程在 anaconda 上安装 Tensorflow 和 Keras。

另一个很好的入门选项是在 Google colab 上编写和运行代码,这是一个基于浏览器的免费 Jupyter 笔记本,运行在云上,不需要任何设置,因为包括 Tensorflow 在内的大多数软件包都是预装的。

导入库

接下来是导入项目所需的库。

import tensorflow as tf
import numpy as np
from tensorflow import keras

定义模型

为了定义我们的模型,我们调用顺序构造函数。顺序将层的线性堆栈分组,并指定每个层的外观。在一个顺序构造函数中,可以有多个密集层作为一个列表。

model = tf.keras.Sequential([
keras.layers.Dense(units=1, input_shape=[1])
])

上面的代码构造了一个非常简单的神经网络,它只有一个密集层,只有一个神经元,由于这是第一层,我们必须包括输入数据的形状。在这种情况下,对于每个实例(行),x 是一个值,因此是input-shape=[1]

在此步骤中包含输入形状非常重要,因为 Keras 中的所有图层都需要知道其输入的形状来创建权重。没有包含input-shape会导致模型构建时没有权重,只有当模型第一次看到一些输入数据时才会初始化权重。在这之后,模型被构建,您可以调用model.get_weights()model.summary()方法来显示它的内容。

编译模型

下一步是编译神经网络,这里我们提供了两个函数;一个loss功能和一个optimizer。损失函数通过模型预测的好坏来评估权重集,而优化器修改权重以减少损失。‘sgd’下图代表随机梯度下降。

model.compile(optimizer='sgd', loss='mean_squared_error')

这一行基本上定义了在下面的步骤中训练模型时将在后端发生的数学计算的类型。

根据数据训练模型

这是模型学习 X 和 y 之间关系的地方。

x = np.array([-1.0,0.0,1.0,2.0,3.0,4.0,5.0],dtype=float)
y = np.array([-1.0,1.0,3.0,5.0,7.0,9.0,11.0],dtype=float)model.fit(x,y,epochs=500)

我们称之为model.fit(x,y,epochs=500)来训练模型。查看该 Keras 文档了解其他可选参数。我们提供 x 和 y 作为模型所期望的 Numpy 数组。x 是输入数据,y 是标签。时期定义迭代的次数。猜测、减少损失以及使用优化器做出下一个最佳猜测的过程就发生在这一步。下面是在 Jupyter 笔记本中训练模型时显示的输出截图。注意损失是如何随着时代接近 500/500 而减少的。

做预测

既然已经根据我们提供的数据训练了一个模型,我们现在可以通过调用model.evaluate([value])方法来预测给定的 x 的value的 y。该值被括在方括号中,因为预期的参数是一个数组。

print(model.predict([10.0]))###Results
[[21.006134]]

我们从 y=2x+1 关系中知道答案应该是 21,但是这里我们看到结果与预期值略有不同。这是因为该模型是在只有 6 行的小数据集上训练的,也因为损失不完全是 0。注意您的值可能会因为模型的初始随机权重而有所不同。

模型概要

模型中的每个神经元学习一个权重和一个偏差。我们上面的模型只有一个单个神经元,因此它将学习关系为y = Wx + b权重偏差,其中 W 是权重,而 b 是偏差。使用 Tensorflow,这些是模型学习的值,可以通过调用model.get_weights()来查看它们。

model.get_weights()###Results
[array([[**2.000743**]], dtype=float32), array([**0.9972024**], dtype=float32)]

这返回包含权重的两个数组,使得学习到的关系是 y = 2.000743 x + 0.9972024,这非常接近 y=2x+1 的真实关系。

总结

这是对深度学习、Tensorflow 和 Keras 的基本介绍,其中我们使用神经网络来确定两组值之间的线性关系。虽然这看起来可能是一个非常简单的问题,但我们学到的概念和工作流对于处理深度学习中更有趣和复杂的问题是必不可少的。查看下面的参考资料,我发现这些资料对刚进入这个领域的初学者非常有用。

参考文献

吴恩达在 YouTube 上发表的《神经网络和深度学习》。

麻省理工学院深度学习入门 6。S191

使用 Scikit-Learn、Keras 和 TensorFlow 进行机器实践学习:第二版

程序员的人工智能和机器学习:人工智能程序员指南第一版,作者劳伦斯·莫罗尼

posted @ 2024-10-17 11:37  绝不原创的飞龙  阅读(267)  评论(0)    收藏  举报