集成 Prefect 和 Databricks 来管理您的 Spark 作业
Justin Jairam 的照片来自 @jusspreme (经允许)
Prefect 是一个工作流管理系统,使用户能够轻松地使用数据应用程序并添加重试、日志记录、动态映射、缓存、故障通知、调度等功能,所有这些都使用功能性 Python API。Prefect 允许用户将他们现有的代码转换成 DAG(有向无环图),并且依赖关系已经确定[1]。它简化了 ETL 管道和依赖项的创建,并使用户能够严格地关注应用程序代码而不是管道代码(看着你的气流)。Prefect 甚至可以创建分布式管道来并行化您的数据应用程序。
Databricks 的核心是一个 PaaS(平台即服务),它可以提供完全托管的 Spark 集群、交互式和协作式笔记本电脑(类似于 Jupyter)、生产流水线调度程序以及为基于 Spark 的应用提供支持的平台。它集成在 Azure 和 AWS 生态系统中,使处理大数据变得简单。Databricks 使用户能够在其管理的 Spark 集群上运行定制的 Spark 应用程序。它甚至允许用户将他们的笔记本电脑安排为 Spark 作业。它完全简化了大数据开发和围绕它的 ETL 过程。
Databricks 已经成为一个不可或缺的大数据 ETL 工具,一个我每天在工作中使用的工具,所以我为 Prefect 项目做了一个贡献,使用户能够将 Databricks 作业与 Prefect 集成。在本教程中,我们将讨论这一点——如何将正在运行的数据块笔记本和 Spark 作业整合到您的完美流程中。
先决条件
这个帖子不需要任何先验知识,但是推荐一个免费的府尹账号来实现这个例子。虽然这篇文章会涉及到级长的基础知识,但它不是一个深入的级长教程。
完美基础
任务
Prefect 中的任务相当于数据管道中的一个步骤。它就像应用程序或脚本中的 Python 函数一样简单。对任务的简单或复杂程度没有限制。也就是说,最好遵循编码最佳实践并开发您的功能,这样它们只做一件事。级长自己推荐这个。
一般来说,我们鼓励小任务而不是大任务,每个任务应该执行工作流程中一个独立的逻辑步骤,但不能更多。[2]
通过保持小任务,您将最大限度地利用 Prefect 的引擎,例如高效的状态检查点。
流
流程是将所有任务及其依赖关系联系在一起的东西。它描述了任务、它们的顺序和数据流之间的依赖关系。流将任务集合在一起,并使其成为一个管道,从而完善您的数据应用程序。
完美的流动可视化(图片由作者提供)
Prefect 中的本机数据块集成
我通过实现任务DatabricksRunNow
& DatabricksRunSubmit
来实现 perfect 和 Databricks 之间的无缝集成,从而为 perfect 项目做出了贡献。通过这些任务,用户可以从外部触发一个已定义的 Databricks 作业或一个 jar、Python 脚本或笔记本的单次运行。一旦任务被执行,它就使用 Databricks 本地 API 调用来运行笔记本或 Spark 作业。当任务运行时,它将继续轮询运行的当前状态,直到任务完成。一旦任务完成,如果成功,它将允许下游任务运行。
使用数据块任务创建流
在开始编写任何代码之前,我们必须创建一个完美的秘密来存储我们的数据块连接字符串。从你的提督云账户,点击左侧菜单中的Team
,进入Secrets
部分。这个部分是你管理完美流程的所有秘密的地方。
要生成 Databricks 连接字符串,您需要 Databricks 实例的主机名以及 Databricks 帐户的 PAT。要创建数据块 PAT,请遵循数据块文档中的步骤。连接字符串必须是有效的 JSON 对象。秘密的标题必须是DATABRICKS_CONNECTION_STRING
。
数据块连接字符串的完美秘密(图片由作者提供)
创建任务
让我们从定义一些运行 Databricks 笔记本和 Spark 作业所需的常见任务开始我们的流程。
from prefect import task, Flow
from prefect.tasks.databricks.databricks_submitjob import (
DatabricksRunNow,
DatabricksSubmitRun,
)
from prefect.tasks.secrets.base import PrefectSecretconn **=** PrefectSecret("DATABRICKS_CONNECTION_STRING")
*# Initialize Databricks task class as a template
# We will then use the task function to pass in unique config options & params* RunNow **=** DatabricksRunNow(conn)
SubmitRun **=** DatabricksSubmitRun(conn)
我们定义了两个任务对象RunNow
和SubmitRun
,作为模板来运行我们的数据块作业。我们可以通过不同的配置重用这些相同的任务,从而轻松创建新的数据块作业。让我们创建一些助手任务来动态创建我们的作业的配置。
**@**task
**def** **get_submit_config**(python_params: list):
"""
SubmitRun config template for the DatabricksSubmitRun task, Spark Python Task params must be passed as a list.
"""
**return** {
"run_name": "MyDatabricksJob",
"new_cluster": {
"spark_version": "7.3.x-scala2.12",
"node_type_id": "r3.xlarge",
"aws_attributes": {
"availability": "ON_DEMAND"
},
"num_workers": 10
},
"spark_python_task": {
"python_file": "/Users/ashton/databricks_task/main.py",
"parameters": python_params,
},
} **@**task
**def** **get_run_now_config**(notebook_params: dict):
"""
RunNow config template for the DatabricksSubmitRun task, Notebook Task params must be passed as a dictionary.
"""
**return** {"job_id": 42, "notebook_params": notebook_params}
get_submit_config
任务允许我们动态地将参数传递给 DBFS (Databricks 文件系统)上的 Python 脚本,并返回一个配置来运行一次性 Databricks 作业。您可以通过在 Databricks 作业配置中创建更多映射到配置选项的参数来增加灵活性。get_run_now_config
执行相同的任务,除了它为DatabricksRunNow
任务返回一个配置来运行一个预配置的数据块笔记本任务。get_run_now_config
和get_submit_config
的模式分别匹配现在运行和运行提交 API。
Python 文件参数必须作为列表传递,而笔记本参数必须作为字典传递。
现在让我们创建一个可以运行我们的任务的流。
创造流动
我们将创建一个流程,在 Databricks 上运行一个预配置的笔记本作业,然后是两个后续的 Python 脚本作业。
**with** Flow("Databricks-Tasks", schedule**=**None) **as** flow: run_now_config **=** get_run_now_config({"param1": "value"})
submit_config_a **=** get_submit_config(["param1"])
submit_config_b **=** get_submit_config(["param2"]) run_now_task **=** RunNow(json**=**run_now_config) submit_task_a **=** SubmitRun(json**=**submit_config_a) submit_task_b **=** SubmitRun(json**=**submit_config_b) *# Since Databricks tasks don't return any data dependencies we can leverage,
* *# we have to define the dependencies between Databricks tasks themselves
* flow.add_edge(run_now_task, submit_task_a)
flow.add_edge(submit_task_a, submit_task_b)
我们首先需要通过使用我们的get_run_now_config
和get_submit_config
任务来创建数据块作业配置。通过json
参数将立即运行配置传递给RunNow
任务,并将提交运行配置传递给SubmitRun
任务。json
参数接受一个与上面提到的Run Now
和Submit Run
API 匹配的字典。为了运行更多的数据块作业,我们实例化我们创建的RunNow
或SubmitRun
模板,并传入一个新的 json 作业配置。
Prefect flow 的一个令人惊叹的特性是,它可以从您的任务中自动构建一个 DAG。它将任务输入视为数据依赖,并由此推断出在其他任务运行之前需要完成哪些任务。例如,由于我们的run_now_task
有输入run_now_config
,流程构建 DAG,知道get_run_now_config
任务必须在run_now_task
之前运行。
有些任务不返回可用作下游任务输入的数据。例如,数据块任务只返回一个作业 ID。我们仍然可以通过使用.add_edge
函数来定义流程的任务间依赖关系。这将增加任务之间的相关性,这些相关性不会用作后续下游任务的输入。例如,flow.add_edge(run_now_task, submit_task_a)
表示submit_task_a
是run_now_task
的下游任务,在run_now_task
完成之前submit_task_a
不能运行。通过将边添加到剩余的数据块任务中,我们得到了最终的流程,您也可以在 Prefect schematics 选项卡中查看。
我们流程的 DAG(图片由作者提供)
为了运行流,我们调用流对象的.run()
方法— flow.run()
。最终的流程如下所示:
from prefect import task, Flow
from prefect.tasks.databricks.databricks_submitjob import (
DatabricksRunNow,
DatabricksSubmitRun,
)
from prefect.tasks.secrets.base import PrefectSecret **@**task
**def** **get_submit_config**(python_params: list):
"""
SubmitRun config template for the DatabricksSubmitRun task, Spark Python Task params must be passed as a list.
"""
**return** {
"run_name": "MyDatabricksJob",
"new_cluster": {
"spark_version": "7.3.x-scala2.12",
"node_type_id": "r3.xlarge",
"aws_attributes": {
"availability": "ON_DEMAND"
},
"num_workers": 10
},
"spark_python_task": {
"python_file": "/Users/ashton/databricks_task/main.py",
"parameters": python_params,
},
} **@**task
**def** **get_run_now_config**(notebook_params: dict):
"""
RunNow config template for the DatabricksSubmitRun task, Notebook Task params must be passed as a dictionary.
"""
**return** {"job_id": 42, "notebook_params": notebook_params} conn **=** PrefectSecret("DATABRICKS_CONNECTION_STRING")
*# Initialize Databricks task class as a template
# We will then use the task function to pass in unique config options & params* RunNow **=** DatabricksRunNow(conn)
SubmitRun **=** DatabricksSubmitRun(conn)**with** Flow("Databricks-Tasks", schedule**=**None) **as** flow: run_now_config **=** get_run_now_config({"param1": "value"})
submit_config_a **=** get_submit_config(["param1"])
submit_config_b **=** get_submit_config(["param2"]) run_now_task **=** RunNow(json**=**run_now_config) submit_task_a **=** SubmitRun(json**=**submit_config_a) submit_task_b **=** SubmitRun(json**=**submit_config_b) *# Since Databricks tasks don't return any data dependencies we can leverage,
* *# we have to define the dependencies between Databricks tasks themselves
* flow.add_edge(run_now_task, submit_task_a)
flow.add_edge(submit_task_a, submit_task_b)flow.run()
*# flow.register("YOUR_PROJECT") to register your flow on the UI*
结论
现在,作为 ETL 流程的一部分,您已经掌握了运行 Databricks 笔记本和 Spark 作业所需的所有知识。要了解更多关于 Prefect 和 Databricks 作业的信息,我推荐阅读它们的文档,在这里找到在这里找到和在这里找到。
反馈
一如既往,我鼓励对我的帖子的任何反馈。如果你有任何问题或者需要任何帮助,你可以给我发邮件到 sidhuashton@gmail.com 或者在帖子上留言。
你也可以通过 Twitter 联系我并关注我,地址是 @ashtonasidhu 。
参考
- https://docs.prefect.io/core/,提督文件
- https://docs .提督. io/core/Getting _ Started/first-steps . html,提督入门
教程:Python 中 Networkx 和 Plotly 的网络可视化基础
从莎士比亚的剧本到网络图
人物网络图仲夏夜之梦
对于这个项目,我想结合我对文学、社会学和数据科学的热爱。更具体地说,我从大学时代起就对社交网络感兴趣,鉴于最近的事件,代表不同代理如何连接变得越来越重要。所以我开发了一个仲夏夜之梦的人物网络,这是我最喜欢的莎翁剧。如果你还没有读过它,并且喜欢一些相当异想天开的东西,我会推荐它!
在下面的帖子中,我将首先介绍网络的基础知识。然后,我将简要回顾一下我用来以我需要的格式获取数据的代码。然后,我检查了我用来创建和定制上述图表的代码。我使用的所有资源都在底部链接。希望这篇教程有帮助!如有任何问题,欢迎留言!制图快乐!
所有的代码都可以在my GitHub repo上找到。
(这篇博客的灵感来自马丁·格兰让的惊人之作《将莎士比亚悲剧中的网络可视化》,你可以在这里找到。)
目标
- 解释如何使用 Python 的 Networkx 包和 Plotly 创建视觉上吸引人的网络图
- 为了举例说明一个网络绘图的应用程序和我采取的一些数据清理步骤(因为我处理的是自然语言数据,所以数据清理比我在这篇文章中介绍的要复杂得多)
- 提供一些技巧、示例代码和资源
01:网络由哪些部分组成?
在我们可视化任何东西之前,我们需要理解我们如何定义一个网络。出于本练习的目的,我们将使用以下定义:
一个网络由一组节点组成,这些节点通过一组边相互连接。
我们可以将节点视为我们试图连接的任何类型的代理或对象。例如,在我的例子中,我的节点是仲夏夜之梦中的人物,但是如果您想要显示纽约市的地铁网络,您的节点可能是地铁站。
你可以把边想象成节点之间的连接。在我的项目中,我认为连接剧中角色的是他们一起出现的场景。我认为,如果两个角色(节点)一起出现在一个场景中(一条边),它们就是相连的。对于地铁网络的例子,它可能是地铁线路。所以两个地铁站(节点)是相连的,如果一条地铁线在两个站(一条边)之间运行。
02:让我们看一个 NLP 的例子
既然我们已经了解了网络的基本知识,我们可以开始将我们的理解转化为代码。我们需要以下东西来创建网络图:
- 最原始的数据——一个文本文件的脚本的《仲夏夜之梦》
- 节点——T4《仲夏夜之梦》中的人物列表
- *边缘——一种数据结构,告诉我们每个角色何时与另一个角色一起出现在场景中 (注意:这是项目中最耗时的部分)
既然我们已经在高层次上建立了我们所需要的东西,我们就可以开始编码了。
导入包
对于这个项目,我需要两套不同的包。第一个是收集和清理我的数据,这样我就可以在 Python 数据结构中拥有一组节点和边。第二组包用于可视化。
# Import packages for data cleaning
import numpy as np
import pandas as pd
import re # For finding specific strings in the text# Import packages for data visualization
import plotly.offline as py
import plotly.graph_objects as go
import networkx as nx
加载数据
在安装和加载包之后,您可以加载原始数据。我在这里找到了古腾堡计划的仲夏夜之梦的文本。
古腾堡计划 是一个令人惊叹的免费电子书图书馆。有超过 60,000 本电子书,如果你想探索自然语言处理(NLP)的世界,我强烈推荐你把它作为一种资源。
# Load the data
f = open("midsummer.txt", "r")
whole_text = f.read()
检查和清理数据:简要概述
因为这不是一篇 NLP 文章,所以我只强调我在处理自然语言数据时必须考虑的一些问题。
如果你对我的数据清理代码的细节部分感兴趣,请随意查看我的 GitHub,上面和下面都有链接。
第一步:查看你的数据
我知道这听起来很基本,但是如果你想可视化你的数据,最好的做法是真正理解你的数据。例如,下面是我问我的数据的一些问题:
- 有我能得到我的节点的一个字符列表吗?我怎样才能找到它?(是的。从“戏剧人物”开始)
- 有没有一条线清楚地把每个场景分开?(是的。“场景”)
- 在这个关键字之前或之后,是否有多余的字符需要我处理或删除?(是的。)
- 我怎样才能知道一个场景中有哪些角色?(特定格式的阶段说明!“进入”、“退出”和许多不同的变化,我不会在这里进入,因为它是非常特定的 NLP。)
第二步:从你的数据中提取一个简单的样本,并尝试处理它
如果您试图获取整个脚本并对其进行处理,这将非常容易出错,并且您可能会错过模块化代码的机会。所以我拍了第一幕第二场,因为所有的角色都在场景的开始进入,没有其他的角色进入,也没有人在场景结束前离开。
- 什么样的数据结构最适合以最符合逻辑的方式获取最多的信息?(我主要用了一本字典的字典。)
第三步: 模块化你的流程
我用两个主函数和几个辅助函数创建了一个 process.py 文件。这绝不是唯一的方法,但这是我解决问题的方法,我的数据是复杂多样的。
- 1 函数为节点和边创建了一个空数据结构
- 1 函数接收一个场景,并获取在给定时间内出现的所有角色
- 当一个新的角色出现或者一个角色退出时,辅助函数进行处理,等等。
下面是我的数据结构的一个例子:
# Create the empty data structure using custom function
appearance_counts = get_empty_appearances(characters, True)# Show a part of the data structure
# Dictionary of dictionaries where each key is each character and each value is a dictionary with all other characters as keys, and values as 0 or [].
appearance_counts
{'Theseus': {'Hippolyta': 0,
'Egeus': 0,
'Hermia': 0,
'Helena': 0,
'Lysander': 0,
'Demetrius': 0,...
第四步:使用你的函数来处理数据
现在我有了这些数据结构,我需要用重要的信息填充这个结构——每个字符与另一个字符(边)一起出现了多少次。
还有很多代码支持下面的代码片段。如果你有问题,你可以看到我的 GitHub 回购链接以上和以下的更多细节。
# For each character that appears, get how many scenes the character # appears in and how many times each pair of characters appears
# together
for character in all_appearances:
scene_counts[character] = []
for co_char in all_appearances[character]:
appearance_counts[character][co_char] = len(all_appearances[character][co_char])
scene_counts[character].extend(all_appearances[character][co_char])
scene_counts[character] = len(set(scene_counts[character]))
终于!你有你的优势!
****注意:如果你对记录两个节点是如何连接的不感兴趣,而只关心两个节点是否连接,你可以只使用一个布尔值而不是一个整数。
# If the number is greater than 0, then the characters appeared in a
# scene together.appearance_counts
{'Theseus': {'Hippolyta': 3,
'Egeus': 2,
'Hermia': 3,
'Helena': 2,
'Lysander': 3,
'Demetrius': 3,
'Philostrate': 2,
'Quince': 1,
'Snug': 1,
'Bottom': 2,
'Flute': 1,
'Snout': 1,
'Starveling': 1,...
不要忘记你的节点!
****注意:如果您对跟踪每个节点的重要性不感兴趣,而只关心节点的存在,那么您可以只使用一个列表来跟踪节点,而不是字典。
# Number of scenes that each character appeared in
scene_counts
{'Theseus': 3,
'Hippolyta': 3,
'Egeus': 2,
'Hermia': 5,
'Helena': 6,
'Lysander': 5,
'Demetrius': 6,...
创建您的网络图
我们将从创建图形、添加节点和添加边开始。有几行代码可以让你自定义你的图表,我会在这篇博文的最后一节把它们说出来。
添加节点&边
****注意:我分别根据一个角色出现的场景数和两个角色共享的场景数,定制了节点的 size 变量和边的 weight 变量。这是可选的。
midsummer = nx.Graph()# Add node for each character
for char in scene_counts.keys():
if scene_counts[char] > 0:
midsummer.add_node(char, size = scene_counts[char])# For each co-appearance between two characters, add an edge
for char in appearance_counts.keys():
for co_char in appearance_counts[char].keys():
# Only add edge if the count is positive
if appearance_counts[char][co_char] > 0:
midsummer.add_edge(char, co_char), weight = appearance_counts[char][co_char])
您可以使用属性仲夏.节点和仲夏.边查看 Networkx 图中的节点和边。
获得职位
然后我们需要得到图中节点的位置。有几种不同的布局可供选择。我认为春季的布置看起来是最好的。您可以在图形布局部分的 Networkx 包的开发说明中看到更多选项。
# Get positions for the nodes in G
pos_ = nx.spring_layout(midsummer)
制作边缘痕迹
因为我是根据两个角色一起出现的场景数量来定制每条边的宽度/重量,所以我创建了一个定制函数,使用 Plotly 为每个节点对创建一个唯一的边轨迹。
该函数接受两个节点(字符), x 和 y ,当您将鼠标悬停在边缘上时想要显示的任何文本**,以及边缘轨迹的宽度。**
# Custom function to create an edge between node x and node y, with a given text and width
def make_edge(x, y, text, width):
return go.Scatter(x = x,
y = y,
line = dict(width = width,
color = 'cornflowerblue'),
hoverinfo = 'text',
text = ([text]),
mode = 'lines')
现在您已经使用您的规范创建了一个函数,迭代您的边,并为指定宽度(由边的权重决定)的每条边创建一个边迹。
# For each edge, make an edge_trace, append to list
edge_trace = []
for edge in midsummer.edges():
if midsummer.edges()[edge]['weight'] > 0:
char_1 = edge[0]
char_2 = edge[1]x0, y0 = pos_[char_1]
x1, y1 = pos_[char_2]text = char_1 + '--' + char_2 + ': ' + str(midsummer.edges()[edge]['weight'])
trace = make_edge([x0, x1, None], [y0, y1, None], text,
width = 0.3*midsummer.edges()[edge]['weight']**1.75)edge_trace.append(trace)
制作节点轨迹
对于节点,您可以坚持只进行单个节点跟踪—单个散布对象—并仍然自定义每个节点的大小。
# Make a node trace
node_trace = go.Scatter(x = [],
y = [],
text = [],
textposition = "top center",
textfont_size = 10,
mode = 'markers+text',
hoverinfo = 'none',
marker = dict(color = [],
size = [],
line = None))
# For each node in midsummer, get the position and size and add to the node_trace
for node in midsummer.nodes():
x, y = pos_[node]
node_trace['x'] += tuple([x])
node_trace['y'] += tuple([y])
node_trace['marker']['color'] += tuple(['cornflowerblue'])
node_trace['marker']['size'] += tuple([5*midsummer.nodes()[node]['size']])
node_trace['text'] += tuple(['<b>' + node + '</b>'])
03:绘制和定制您的网络
现在我们有了包含所有节点的节点轨迹,以及我们的边轨迹,我们可以把它们放在一个图表中,看看它看起来像什么。
自定义您的布局
为了定制我的布局,我修改了网格线、图例和刻度标签的背景颜色和外观。
# Customize layout
layout = go.Layout(
paper_bgcolor='rgba(0,0,0,0)', # transparent background
plot_bgcolor='rgba(0,0,0,0)', # transparent 2nd background
xaxis = {'showgrid': False, 'zeroline': False}, # no gridlines
yaxis = {'showgrid': False, 'zeroline': False}, # no gridlines
)# Create figure
fig = go.Figure(layout = layout)# Add all edge traces
for trace in edge_trace:
fig.add_trace(trace)# Add node trace
fig.add_trace(node_trace)# Remove legend
fig.update_layout(showlegend = False)# Remove tick labels
fig.update_xaxes(showticklabels = False)
fig.update_yaxes(showticklabels = False)# Show figure
fig.show()
自定义您的颜色和文本
在最基本的层面上,您总是可以自定义节点和边的颜色,以及静态显示在节点/边旁边或当您将鼠标悬停在节点或边上时显示的任何文本。
你可以很容易地访问颜色和文本**,只需使用节点和边缘轨迹中的属性。您会注意到我在本文分享的代码片段中调用这些属性的地方。但是我用来使我的文本更加突出的一个巧妙的技巧是学习如何加粗我的节点旁边的静态文本:**
# Add <b> and </b> at the beginning and end of your string to bold
# the text in question!
node_trace['text'] += tuple(['<b>' + node + '</b>'])
自定义边缘宽度和节点大小
最后,我想在视觉上突出我所做的最重要的定制。这涉及到我认为最好的尝试和错误。以下代码行分别位于关于创建边跟踪和节点跟踪的部分:
# Line that customized the width of each edge trace
trace = make_edge([x0, x1, None], [y0, y1, None], text,
width = 0.3*midsummer.edges()[edge]['weight']**1.75)# Line that customized the size of each node in the node trace
node_trace['marker']['size'] += tuple([5*midsummer.nodes()[node]['size']])
正如你所看到的,我硬编码了标量和指数,以确定在剧中 x 和 y 场景中出现的差异有多大(节点的大小),或者在 x 和 y 场景中出现的角色相同(边缘的宽度)。你所使用的具体数字会极大地改变你的图表的外观。所以和他们一起玩,直到你感到满意为止!
奖金:未来网络项目的想法
- 创建一个以时间为变量的动画网络
- 创建一个基于进出链接的维基百科文章网络
- 根据地铁线路在城市中创建地铁站网络
- 在一群人之间建立一个社交网络(注意,你需要某种封闭的系统或方法来监控网络成员在特定时间的变化)
资源
古登堡计划是一个拥有超过 60,000 本免费电子书的图书馆。在免费的 epub 和 Kindle 电子书中选择,下载它们或…
www.gutenberg.org](https://www.gutenberg.org/) [## 网络图
Dash 是一个用于构建分析应用程序的开源框架,不需要 Javascript,而且它是紧密结合的…
plotly.com](https://plotly.com/python/network-graphs/) [## 网络可视化:映射莎士比亚的悲剧
莎士比亚的悲剧结构都一样吗?这些角色是相当孤立的,成组的,还是都有联系的…
www . martingrandjen . ch](http://www.martingrandjean.ch/network-visualization-shakespeare/) [## NetworkX - NetworkX 文档
NetworkX 是一个 Python 包,用于创建、操作和研究…的结构、动力学和功能
networkx.github.io](http://networkx.github.io/) [## rweng 18/仲夏 _ 网络
创建字符网络图。在……上创建一个帐户,为 rweng 18/summers _ network 的发展做出贡献
github.com](https://github.com/rweng18/midsummer_network)**
LSTMs 教程:计算观点
杰克·纳格兹在 Unsplash 上的照片
目录
1\. [Introduction](#6d31)2\. [Why Do we need RNNs?](#95b4)3\. [RNN Training and Inference](#7194)4\. [Structure of an RNN](#8ca2)5\. [Time Unrolling](#3226)6\. [Vanishing Gradient](#aa74)7\. [Long Short-Term Memory (LSTM)](#0d00)8\. [LSTM equations](#b10c)9\. [Understanding the LSTM dimensionalities](#da46)10\. [Time Unroll and Multiple Layers](#ada8)11\. [Example: Sentiment Analysis using LSTM](#4019)12\. [Testing your knowledge](#c240)
介绍
最近,人们对将深度学习模型嵌入硬件非常感兴趣。当涉及到深度学习模型部署时,尤其是在边缘,能量是至关重要的。Pete Warden 在“为什么机器学习的未来很小”上发表了一篇关于为什么能源对 AI@Edge 很重要的博文。程序(或模型)的能量优化只能通过对底层计算的良好理解来完成。在过去几年与深度学习人员——硬件架构师、微内核程序员、模型开发人员、平台程序员和受访者(尤其是受访者)的合作中,我发现人们从定性的角度理解 LSTMs,但从定量的角度理解不好。如果你不能很好地理解某事,你就不能优化它。缺乏了解导致 LSTMs 开始失宠。本教程试图通过方程解释 LSTMs 所需的计算来弥合定性和定量之间的差距。同时,这也是我从计算的角度巩固对 LSTM 的理解的一种方式。希望它也能对以不同身份使用 LSTMs 的其他人有用。
注意:这里的免责声明是,我既不声称自己是 LSTMs 方面的专家,也不声称自己的理解完全正确。如果有不正确或令人困惑的地方,请随意发表评论。
为什么我们需要 RNNs?
需要递归神经网络(RNNs ),因为我们希望设计能够识别(或操作)序列的网络。卷积神经网络(CNN)不关心它们识别的图像的顺序。另一方面,RNN 用于视频、手写识别等序列。这在图 1 中用一个高层次的卡通图来说明。
图 1:反馈网络和前馈网络之间区别的卡通图示。原图来自 维基百科 。
简而言之,如果我们试图识别视频、手写或语音等序列,我们就需要 RNNs。注意,我们仍然没有谈论 LSTMs。我们仍在试图了解 RNN。稍后我们将讨论 LSTMs。
悬崖笔记版本
当我们试图处理序列时,需要 rnn。
RNN 训练和推理
如果你跳过了前一部分,我们首先试图理解香草 RNN 的工作原理。如果你试图理解 LSTMs,我鼓励并敦促你通读这一部分。
在本节中,我们将了解以下内容:
- RNN 的结构。
- 时间展开
我们将基于这些概念来更好地理解基于 LSTM 的网络。
RNN 的结构。
图 2 显示了一个简单的 RNN 结构。该图的灵感来自于深度学习书籍(具体是第 10 章第 373 页的图 10.3)。
图中需要注意一些事情:
- 我在括号中用红色表示了每个节点的变量。在下一张图和下一节中,我将使用变量(在等式中),所以请花几秒钟时间理解它们。
- 从预期产量到损失的箭头方向不是错别字。
- 变量 U,V,W 就是这个网络的权重矩阵。
- 反馈路径中的黄色斑点(由绿色箭头指示)表示单位延迟。如果你是 DSP 的,就把这个当成(z^-1)
- 反馈(用绿色箭头表示)使这个玩具例子有资格成为 RNN。
图 2:RNN 结构的例子。这个形象的灵感来源于 深度学习书籍
在我们进入方程之前。让我们看看图表,了解发生了什么。
- 在宇宙之初。输入 ‘x(t=0)’ 与矩阵 U 相乘得到 *x(t=0)U 。
- 上一时间步的反馈乘以矩阵 W. 由于这是初始阶段,反馈值为零(为简单起见)。因此,反馈值为 h(t=-1)*W = 0。因此,乘积是 0+x(t=0)*U = x(t=0)*U
- 现在,它与矩阵 V 相乘,得到 x(t=0)UV。
- 对于下一个时间步长,这个值将存储在 h(t)中,并且不是一个非零值。
因此,上述也可以总结为以下等式:
在上述方程中,我们忽略了非线性和偏差。将它们添加到等式中,如下所示。不要担心这些看起来很复杂。
悬崖笔记版本
rnn 的结构中有一个反馈环。这使得他们能够处理序列。
时间展开
时间展开是理解 RNNs 和 LSTMs 的一个重要概念。
rnn 也可以表示为其自身的时间展开版本。这是表示它们的另一种方式,方程没有变化。时间展开只是另一种表现,而不是一种转换。我们之所以要用这种方式表示它们,是因为这样更容易推导出正向和反向传递方程。时间展开如下图所示:
展开的 RNN 画像。形象的灵感来源于 深度学习书籍
在左上图中,RNN 的结构和我们之前看到的一样。右边是时间展开的表示。
从该图中可以得出一些重要结论:
- 权重矩阵 U,V,W 不随时间变化。这意味着一旦训练了 RNN,权重矩阵在推断期间是固定的,并且不依赖于时间。换句话说,相同的权重矩阵(U,V,W)用于每个时间步。
- 浅色阴影的 h(…)两边分别表示 h(t-1)之前和 h(t+1)之后的时间步长。
- 上图显示了 RNN 的向前(或推断)传球。在每个时间步,都有一个输入和一个相应的输出。
- 在正向传递中,“信息”(或内存)通过变量 h. 传递到下一级
悬崖笔记版本
rnn 可以表示为时间展开的版本。这只是一个表示,而不是转换。在前向传递中,权重矩阵 U、V、W 不依赖于时间。
消失梯度
rnn 存在为长距离序列保留上下文的问题。换句话说,rnn 不能处理非常长的序列(想想长句或长演讲)。给定输入对隐藏层(以及输出)的影响作为时间(或序列长度)的函数呈指数衰减(或爆发和饱和)。消失梯度问题如下图所示,来自亚历克斯·格雷夫斯的论文。节点的阴影表示网络节点在给定时间对输入的敏感度。阴影越暗,灵敏度越高,反之亦然。如图所示,当我们从时间步长=1 快速移动到时间步长=7 时,灵敏度会衰减。网络会忘记第一次输入。
来自 Alex Grave 论文的图显示了隐藏节点对梯度的敏感性。
这是使用 LSTMs 的主要动机。消失梯度问题导致研究人员多次尝试提出解决方案。其中最有效的是 LSTM 或长短期记忆,由 Hochreiter 于 1997 年提出。
悬崖笔记版本
传统的 RNNs 对于长序列(序列长度大约大于 10 个时间步长)的输入不敏感。1997 年提出的 LSTMs 仍然是克服 rnn 这一缺点的最流行的解决方案。
长短期记忆(LSTM)
LSTMs 是由 Hochreiter 在 1997 年提出的,作为一种减轻与普通 rnn 相关的棘手问题的方法。
一些博客和图片描述了 LSTMs。如您所见,在描述 LSTMs 的方式上有很大的差异。在这篇文章中,我想通过方程式来描述它们。我发现它们通过方程式更容易理解。有很多优秀的博客可以让你直观地理解它们,我强烈推荐你去看看:
(b) LSTM 来自维基百科
阎石的博客上媒
(d)来自深度学习书籍的 LSTMs
描述 LSTMs 的流行博客和论文中的不同图片。(一)克里斯多夫·奥拉赫的博客。 (b) LSTM 来自维基百科 阎石的博客关于中(d)lstm 来自深度学习书籍 (e) 英伟达的博客关于加速 lstm(f)LSTM 图来自关于人体活动检测的会议论文
LSTM 方程
下图显示了单个时间步长的 LSTM 的输入和输出。这是一个时间步长的输入、输出和时间展开表示的方程。LSTM 有一个输入 x(t) ,它可以是 CNN 的输出或者直接是输入序列。 h(t-1) 和 c(t-1) 是来自前一时间步 LSTM 的输入。o(t) 是该时间步长的 LSTM 的输出。LSTM 还生成 c(t) 和 h(t) 用于下一时间步 LSTM 的消耗。
LSTM 输入输出和单个时间步长的相应方程。
注意,LSTM 方程也产生 f(t),i(t),c’(t),这些是 LSTM 的内部消耗,用于产生 c(t)和 h(t)。
从上面可以看出一些要点:
- 上述等式仅适用于一次性步骤。这意味着这些方程必须在下一个时间步重新计算。因此,如果我们有 10 个时间步长的序列,那么对于每个时间步长,上述等式将分别计算 10 次。
- 权重矩阵(Wf,Wi,Wo,Wc,Uf,Ui,Uo,Uc)和偏差(bf,bi,bo,bc)不依赖于时间。这意味着这些权重矩阵不会从一个时间步长改变到另一个时间步长。换句话说,为了计算不同时间步长的输出,使用相同的权重矩阵。
下面的伪代码片段显示了十个时间步长的 LSTM 时间计算。
说明 10 个时间步长的 LSTM 计算的代码片段。
悬崖笔记版本
LSTM 网络的权重矩阵从一个时间步长到另一个时间步长不变。LSTM 由 6 个方程式组成。如果 LSTM 正在学习长度为“seq_len”的序列。然后,这六个方程将被计算总共‘seq _ len’。基本上,每一步都要计算方程。
理解 LSTM 维度
沃洛季米尔·赫里先科在 Unsplash 上的照片
理解了 LSTM 的单个时间步长所需的计算之后,我们进入下一个方面——维度。根据我的经验,LSTM 维度是 lstm 混乱的主要原因之一。另外,这是我最喜欢问的面试问题之一;)
让我们再看看下图中的 LSTM 方程。正如你已经知道的,这些是单个时间步长的 LSTM 方程:
单时间步长的 LSTM 方程
让我们从一个简单的 x(t)开始。这是输入信号/特征向量/CNN 输出。我假设 x(t)来自一个嵌入层(想想 word2vec),输入维数为[80x1]。这意味着 Wf 的维数为[某个值 x 80]。
至此我们已经:
x(t)是[80 X 1] —输入假设
Wf 是[Some_value X 80 ] —矩阵乘法法则。
让我们做另一个假设,LSTM 的输出维数是[12×1]。假设这是输出类的数量。因此,在每个时间步长,LSTM 产生大小为[12×1]的输出 o(t)。
既然 o(t)是[12x1],那么 h(t)必须是[12 x 1],因为 h(t)是通过一个元素接一个元素的乘法来计算的(看看最后一个关于如何从 o(t)和 c(t)计算 h(t)的等式)。因为 o(t)是[12x1],那么 c(t)必须是[12x1]。如果 c(t)是[12x1],那么 f(t),c(t-1),i(t)和 c’(t)必须是[12x1]。为什么?因为 h(t)和 c(t)都是通过逐元素乘法来计算的。
因此我们有:
o(t)是[12 X 1] —输出假设
h(t)和 c(t)是[12x1] —因为 h(t)是通过公式中 o(t)和 tanh(c(t))的逐元素乘法计算的。
f(t),c(t-1),i(t)和 c’(t)是[12x1]——因为 c(t)是[12 x1],并且是通过要求相同大小的元素方式运算来估计的。
因为 f(t)的维数是[12×1],那么 Wf 和 x(t)的乘积必须是[12×1]。我们知道 x(t)是80x1那么 Wf 必须是[12x80]。再看 f(t)的等式,我们知道偏置项 bf 是[12x1]。
因此,我们有:
x(t)是[80 X 1] —输入假设
o(t)是[12 X 1] —输出假设
h(t)和 c(t)是[12x 1]——因为 h(t)是通过等式中 o(t)和 tanh(c(t))的逐元素相乘来计算的。
f(t),c(t-1),i(t)和 c’(t)是[12x1]——因为 c(t)是[12 x1],并且是通过要求相同大小的元素式运算来估计的。
Wf 是[12x80] —因为 f(t)是[12x1],x(t)是[80x1]
bf 是[12x1] —因为所有其他项都是[12x1]。
以上内容看起来可能比实际情况要复杂一些。花点时间自己解决它。相信我,没那么复杂。
现在进入令人困惑的部分:)开个玩笑!
在 f(t)的计算中,Uf 和 h(t-1)的乘积也必须是[12x1]。现在根据前面的讨论我们知道 h(t-1)是[12x1]。h(t)和 h(t-1)将具有相同的维数[12×1]。因此,Uf 将具有[12×12]的维数。
所有 Ws (Wf,Wi,Wo,Wc)将具有相同的[12x80]尺寸,所有 bias(BF,bi,bc,bo)将具有相同的[12x1]尺寸,所有 Us (Uf,Ui,Uo,Uc)将具有相同的[12x12]尺寸。
因此:
x(t)是[80 X 1] —输入假设
o(t)是[12 X 1] —输出假设
Wf、Wi、Wc、Wo 的尺寸均为【12x 80】
Uf、Ui、Uc、Uo 每个都有[12x12]的尺寸
bf、bi、bc、bo 的尺寸均为【12 x1】
ht,ot,ct,ft,it 各有一个维度【12 x1】
LSTM 的总权重矩阵大小为
权重 _ LSTM = 4 *[12x 80]+4 *[12x 12]+4 *[12x 1]
= 4 *[输出尺寸 x 输入尺寸]+4 *[输出尺寸]+4 *[输入尺寸]
= 4*[960] + 4*[144] + 4*[12] = 3840 + 576+48= 4,464
让我们验证将以下代码粘贴到您的 python 设置中
请注意,LSTM 的参数数量是 4464。这也是我们通过计算得到的结果!
在我们进入下一部分之前,我想强调一个关键的方面。LSTMs 有两个定义它们的东西:输入维度和输出维度(以及我稍后将谈到的时间展开)。在文献(论文/博客/代码文档)中,术语有很多模糊之处。有些地方称之为单位数、隐藏维数、输出维数、LSTM 单位数等。我没有争论哪个是正确的或者哪个是错误的,只是在我看来这些通常意味着同样的事情——输出维度。
到目前为止,我们已经查看了权重矩阵的大小。大多数框架将权重矩阵合并存储为单个矩阵。下图说明了这个权重矩阵和相应的维度。
注意:根据您使用的框架,权重矩阵将以不同的顺序存储。例如,Pytorch 可以在 Wf 或 Caffe 可以首先存储 Wo 之前保存 Wi。
LSTM 权重矩阵维度。
悬崖笔记版本
有两个参数定义时间步长的 LSTM。输入维度和输出维度。权重矩阵大小为:4 * Output _ Dim *(Output _ Dim+Input _ Dim+1)[感谢 Cless 捕捉到错别字]。当谈到 LSTMs 时,有很多模糊性——单位的数量、隐藏维度和输出维度。请记住,有两个参数定义了 LSTM-输入维度和输出维度。
时间展开和多层
下图中有两个独立的 LSTM 网络。两个网络都显示为展开三个时间步长。图(A)中的第一个网络是单层网络,而图(B)中的网络是双层网络。
两个 LSTM 网络(A)展开三个时间步长的单层 LSTM 网络(B)展开三个时间步长的双层 LSTM 网络
在第一个单层网络的情况下,我们初始化 h 和 c ,并且每个时间步产生一个输出,连同 h 和 c 一起被下一个时间步消耗。注意,即使在最后的时间步 h(t)和 c(t)被丢弃,为了完整起见,我还是显示了它们。正如我们之前讨论的,对于三个时间步长,权重(Ws、Us 和 bs)是相同的。
双层网络有两个 LSTM 层。第一层的输出将是第二层的输入。它们都有自己的权重矩阵和各自的 *hs、cs 和 os。*我通过使用上标来表明这一点。
示例:使用 LSTM 的情感分析
让我们来看看一个非常简单但很现实的 LSTM 网络,看看这是如何工作的。任务很简单,我们必须想出一个网络来告诉我们一个给定的句子是否定的还是肯定的。为了简单起见,我们假设句子是固定长度的。如果实际句子的字数少于预期长度,则填充零;如果实际句子的字数多于序列长度,则截断句子。在我们的例子中,我们将句子长度限制为 3 个单词。为什么是 3 个字?只是一个我喜欢的数字,因为它对我来说更容易画出图表:)。
严肃地说,您可以绘制数据集中一个句子的字数直方图,并根据直方图的形状选择一个值。大于预定单词数的句子将被截断,单词数较少的句子将用零或空单词填充。
不管怎样,回到我们的例子。我们坚持三个词。我们将使用一个嵌入层,将一个英文单词转换成大小为[80x1]的数字向量。为什么是 80?因为我喜欢 80 这个数字:)不管怎样,网络如下图所示。
使用 LSTM 的情感分析网络示例。
我们将尝试对一个句子进行分类——“我很快乐”。在 t=0 时,第一个字“I”被嵌入层转换成长度为[80x1]的数字向量。并且穿过 LSTM,随后是完全连接的层。然后在时间 t=1,第二个单词通过网络,接着是在时间 t=2 的最后一个单词“happy”。我们希望网络等待整个句子让我们了解感情。我们不希望它过于急切,一字不漏地把感悟告诉我们。这就是为什么在下图中,LSTM 的输出只显示在最后一步。Keras 将这个参数称为 **return_sequence。**将此项设置为“假”或“真”将决定 LSTM 和随后的网络是否在每个时间步长或我们示例中的每个单词生成输出。我想在这里强调的一个关键点是,仅仅因为你将返回序列设置为假,并不意味着 LSTM 方程被修改了。他们仍然在计算每个时间步长的 h(t),c(t)。因此计算量不会减少。
以下是 Keras 在 IMDB 数据集上进行情感分析的示例:
https://github . com/keras-team/keras/blob/master/examples/IMDB _ lstm . py
测试你的知识!
安吉丽娜·莉文在 Unsplash 上的照片
让我们试着巩固一下到目前为止所学的知识。在这一部分,我列出了一些样本/玩具网络的问题。如果我能测试我的理解是否正确,这将有助于我感觉更好,因此这一部分采用了这种格式。或者,您也可以使用这些来准备与 LSTMs 相关的面试:)
样本 LSTM 网络# 1
LSTM 网络# 1 示例
- 这个网络中有多少个 LSTM 层?— 网络有一层。不要与多个 LSTM 盒混淆,它们代表不同的时间步长,只有一层。
- 如图所示,序列长度或时间步数是多少?— 时间步长的数量为 3。看看时间索引。
- 如果输入维数,即 x(t)是[18x1],o(t)是[19x1],那么 h(t),c(t)的维数是多少?— h(t)和 c(t)的尺寸为【19x 1】
样本 LSTM 网络# 2
示例 LSTM 网络# 2
- 这个网络中有多少个 LSTM 层?—LSTM 的总层数为 5 层。
- 如图所示,序列长度或时间步数是多少?— 这个网络的序列长度为 1。
- 如果 x(t)是[45x1],h1(int)是[25x 1]——C1(int)和 o1(t)的维数是多少?— c1(t)和 o1(t)将与 h1(t)具有相同的尺寸,即[25x1]
- 如果 x(t)是[4x1],h1(int)是[5x1],o2(t)的大小是[4x1]。LSTM0 和 LSTM1 的权重矩阵的大小是多少?—LSTM 的权重矩阵为[4 * output _ dim (input _ dim+output _ dim+1)]。LSTM0 的输入尺寸为[4x1],LSTM0 的输出尺寸为[5x1]。LSTM1 的输入是 LSTM0 的输出,因此 LSTM1 的输入 dim 与 LSTM0 的 output_dim 相同,即[5x1]。LSTM1 的输出 dim 为[4x1]。因此,LSTM0 是[46(5+4+1)]=288,而 LSTM1 是[44(5+4+1)] = 160。*
- 如果 x(t)是[10x1],h1(int)是[7 x1]lst m1 的输入维数是多少?— 看上面的解释。在计算之前,我们需要知道 LSTM0 的输出维数。
- 如果 x(t)是[6x1],h1(int)是[4x1],o2(t)是[3x1],o3(t)是[5x1],o4(t)是[9x1],o5(t)是[10x1]网络的总重量大小是多少?— *单个时间步长的 LSTM 的权重矩阵为[4 * output _ dim (input _ dim+output _ dim+1)]。通过估计单个层的输入输出维度来工作。
样本 LSTM 网络# 3
样本 LSTM 网络# 3
- 这个网络有多少层?— 有两层
- 这个网络中显示的序列长度是多少?— 每层展开 2 次。
- 如果 x(t)是[80x1],h1(int)是[10x1],那么 o(t),h1(t),c1(t),f(t),i(t)的维数是多少?这些在图中没有显示,但是您应该能够标记出来。— o(t),h1(t),c1(t),f1(t),i1(t)将具有与 h1(t)相同的尺寸,即【10x 1】
- 如果 x(t+1)是[4x1],o1(t+1)是[5x1],o2(t+1)是[6x1]。LSTM0 和 LSTM1 的权重矩阵的大小是多少?—LSTM 的权矩阵由 4 * output _ dim (input _ dim+output _ dim+1)给出。LSTM0 将是 45(4+5+1),即 200。LSTM2 将是 46(5+5+1) = 264。*
- 如果 x(t+1)是[4x1],o1(t+1)是[5x1],o2(t+1)是[6x1]。乘法和累加运算的总数是多少?——我把这个留给读者。如果有足够多的人问,我会回答:)
样本 LSTM 网络# 4
样本 LSTM 网络# 4
- 有多少层?— 有 3 层。
- 如图所示,这个网络展开了多少时间步?— 每层展开 3 次。
- 这个网络总共要执行多少个方程?— 每个 LSTM 需要 6 个方程(某些文本合并为 5 个方程)。然后是 6 个方程/时间步长/LSTM。因此,6 个方程 3 个 LSTM 层 3 个时间步长= 54 个方程**
- 如果 x(t)是[10x1]估计 LSTM1 的权矩阵还需要哪些信息?LSTM2 呢?— *一个 LSTM 的权重矩阵由 4 * output _ dim (input _ dim+out _ dim+1)给出。因此,对于每个 LSTM,我们都需要 input_dim 和 output_dim。LSTM 的输出是 LSTM1 的输入。我们有输入维度[10x1],因此我们需要输出维度或 o1(int)维度以及 LSTM1 的输出维度,即 o2(t)。同样,对于 LSTM2,我们需要知道 o2(t)和 o3(t)。
摘要
围绕 LSTMs 的博客和论文经常在定性的层面上讨论它。在本文中,我试图从计算的角度解释 LSTM 运算。从计算的角度理解 LSTMs 是至关重要的,尤其是对于机器学习加速器的设计者来说。
参考资料和其他链接
来自深度学习书籍的 LSTMs
Pete Warden 关于“为什么机器学习的未来很小”的博客。
教程:用 R 为 Python 难民绘图
来自 Pixabay 的背景图片。
了解 R 惊人的绘图能力
虽然 Python 和 R 都是用于数据分析和机器学习的伟大语言,但大多数人都同意的一点是,R 在数据可视化方面占上风。虽然 Python 可能更适合快速绘图,但 R 具有可定制性控件,可以创建 Python 可以创建的几乎所有东西,甚至更远。最重要的是,R library ggplot2
遵循“图形语法”,比 Python 有更有组织和结构化的方式来绘制图表。
如果您是一名 Python 难民,正在寻找一种更好、更有条理的方法来绘制数据,那么本教程就是为您准备的!
我们将使用的绘图库是 ggplot2。基于图形的语法,它的工作原理是每个图形都可以由三个部分组成:
- 数据集
- 坐标系
- 几何图形,或表示数据点的可视标记
为了显示数值,数据中的变量需要映射到几何、美学的属性,如尺寸、颜色或x
和y
轴位置。
让我们从数据集开始。ggplot2
有一些内置功能。这
options(scipen=999) # turn off scientific notation like 1e+06
library(ggplot2)
data("midwest", package = "ggplot2") # load the data
现在我们有了数据,是时候指定坐标系了。aes()
功能可用于指定x
和y
轴。area
和poptotal
是midwest
表格中的列。
ggplot(midwest, aes(x=area, y=poptotal))
这里有一个空白坐标系,最后,是时候添加几何图形了。在这种情况下,由于我们正在制作一个散点图,将使用geom_point()
,它将点放到坐标系中。
ggplot(midwest, aes(x=area, y=poptotal)) + geom_point()
我们还可以添加其他层。例如,如果我们想添加一个线性回归,我们可以添加一个geom_smooth(method=’lm’)
geom。它对由ggplot
公式的初始数据部分指定的相同数据进行操作。
ggplot(midwest, aes(x=area, y=poptotal)) + geom_point() + geom_smooth(method="lm")
我们还可以添加改变图形的层。例如,要放大图形的一部分,可以添加接受两个向量的coord_cartesian
层——一个描述x
轴范围,另一个描述y
轴范围。注意,在 R 中,c()或 concatenate 函数创建一个向量(类似于一个NumPy
数组或列表)。
ggplot(midwest, aes(x=area, y=poptotal)) + geom_point() + geom_smooth(method="lm") + coord_cartesian(xlim=c(0,0.1), ylim=c(0, 100000))
除了添加几何图形和缩放,+
操作符还允许标记标题和轴。在这种情况下,+ ggtitle(“Title”,subtitle = 'subtitle')
可用于为x
和y
轴添加标题和+ xlab(‘axis’)
和+ ylab(‘axis’)
。
ggplot(midwest, aes(x=area, y=poptotal)) + geom_point() + geom_smooth(method="lm") + coord_cartesian(xlim=c(0,0.1), ylim=c(0, 100000)) + ggtitle("Area Vs Population", subtitle="From midwest dataset") + xlab("Area") + ylab("Population")
为了以一种更加结构化的方式组织所有的层,而不是把它们都塞进一行,在+
之后创建一个新行。
ggplot(midwest, aes(x=area, y=poptotal)) +
geom_point() +
geom_smooth(method="lm") +
coord_cartesian(xlim=c(0,0.1), ylim=c(0, 100000)) +
ggtitle("Area Vs Population", subtitle="From midwest dataset") +
xlab("Area") +
ylab("Population")
每个图层都有自己的参数,例如,我们可以根据 geom 类型指定颜色和大小。
ggplot(midwest, aes(x=area, y=poptotal)) +
geom_point(col="purple", size=0.5) +
geom_smooth(method="lm", col="firebrick")
如果我们想根据类改变颜色,只需将颜色参数(col
)设置为与颜色应该区分的列名相同。aes()
需要指定引用的数据。
g <- ggplot(midwest, aes(x=area, y=poptotal)) +
geom_point(aes(col=state), size=3) + # Set color to vary based on state categories.
geom_smooth(method="lm", col="firebrick", size=2)
plot(g)
可以通过添加另一层来设置调色板。
gg + scale_colour_brewer(palette = "Set1")
在本教程中,您学习了:
- 图形的语法
- 向图中添加数据
- 向地块添加坐标
- 向图中添加散点图几何
- 向图中添加其他形式的几何图形,如回归
- 更改绘图的比例
- 调整几何图形的大小和颜色
- 更改调色板
感谢阅读!
教程:使用 CatBoost 进行泊松回归
如何使用泊松回归和 CatBoost 来提高基于计数的数据的准确性…并预测一条推文获得的赞数。
在本教程中,我们将讨论以下主题:
- 基于计数的数据的概念
- 什么是泊松回归,为什么它适用于基于计数的数据
- 如何用 CatBoost 包建立泊松回归模型
- 如何预测埃隆·马斯克的推文会获得多少赞
什么是基于计数的数据?
根据定义计数数据是一种数据类型,其中:
- 观察值只能取非负整数值{0,1,2,3,…}
- 这些整数来自计数
更具体地说,在我们的教程中,我们将关注基于计数的数据,其中每个点都是在某个固定时间单位 t 内发生的事件数量。我们还将假设在时间单元 t 期间平均发生事件 λ 的数量。 λ 则称为事件率。**事件发生率可能会随着时间的推移而变化,也可能会随着观察的不同而变化。**以下是此类数据的一些示例:
- 每周看医生的人数
- 过桥车辆数量
- 每天发布在 Instagram 上的照片数量
- 乔治·r·r·马丁每两年写的“冰之歌”的数量
值得注意的是,基于计数的数据的分布可能是相当偏斜的,因为大多数数据点具有完全相同的值。
泊松回归
泊松分布
泊松分布的概率质量函数如下:
泊松分布的 PMF
其中 P(k) 是在给定事件率的时间单位内看到 k 个事件的概率(=每时间单位的事件数) λ 。
我们可以用泊松分布来模拟基于计数的数据。
常数为 λ 的泊松分布示例如下:
生成泊松分布样本的代码:
事件率λ作为因变量
泊松回归的思想是说事件率 λ 是因变量。
例如,每天过桥的自行车数量取决于天气、一年中的时间、一周中的日期等。我们可以建立一个普通的 RMSE 回归模型,但是,这样的模型不能解释基于计数的数据属性。所以在泊松回归中,我们希望最大化泊松分布的对数似然。假设 X , y 是我们用于泊松回归任务的数据集(意味着 y 是基于计数的),那么我们想要最大化对数似然性:
数据集(X,y)上泊松分布的对数似然性
自日志*(咦!)*不依赖于 X 我们去掉这一项,尽量减少以下损失:
这种损失可以用不同的模型和优化方法来优化。在我们的教程中,我们使用 CatBoost 包。
定型泊松回归模型
资料组
我们的数据集是用 Twitter API 收集的。它由埃隆·马斯克的推文组成。我们将使用 2019 年 3 月至 2020 年 1 月的推文作为训练集,2020 年 2 月上半月的推文作为验证集,2020 年 2 月下半月的推文作为测试集。我们的目标是推特收到的赞数。在实践中,大多数推文在发布后的前两周内收到了所有的赞,所以我们假设我们的时间单位是两周。我们收集了至少两周前的推文。
特征
我们为我们的任务提取了一些非常简单的特征:
- 推文长度
- 其他 Twitter 用户提及的次数
- 推文中的 URL 数量
- 月
- 一天
- 小时
- 星期几
- 大小为 500 的 TF-IDF 特征向量(用
stop_words="english"
提取sklearn.feature_extraction.text.TfidfVectorizer
)
现在,我们将使用客观泊松来训练 CatBoost 模型。我们将使用我们的验证数据集来选择迭代次数。
bestIteration = 972
Shrink model to first 973 iterations.
R2 score: 0.555
RMSE score: 39844.35
56%的决定系数 R2 值表明,我们的模型对测试数据集的预测解释了超过一半的目标可变性,考虑到任务的复杂性和我们方法的简单性,这并不坏。
此外,为了进行比较,我们将训练一个具有标准 RMSE 目标的 CatBoost 模型:
bestIteration = 44
Shrink model to first 45 iterations.
R2 score: 0.483
RMSE score: 42936.22
鉴于 RMSE 模型的最佳迭代次数为 45,而泊松回归的最佳迭代次数为 972,我们可能会怀疑 CatBoost 自动选择的学习率 0.055185 对于 RMSE 模型来说太大了。为了解决这种可能的不公平,我们还训练了一个学习率小 30 倍的 RMSE 模型:
bestIteration = 748
Shrink model to first 749 iterations.
R2 score: 0.470
RMSE score: 43470.15
然而,较小的学习率无助于 RMSE 模型。
可以看出,考虑数据集性质的损失比标准 RMSE 损失产生更好的结果。
感谢您的关注!希望这篇教程对你有用。
教程:用 23 行 Python 在几秒钟内刮出 100 个标题
Scrapy 库的网页抓取快速,简单,而且非常强大。
如果你需要做任何类型的网页抓取,Scrapy 几乎是不可能错过的。借助并行请求、用户代理欺骗、robots.txt 策略等内置特性,您只需几行代码就可以构建一个强大的 web scraper。
在本教程中,我将展示如何创建一个基本的 Scrapy 蜘蛛,收集新闻文章的标题。在大多数网站上,你可以做到这一点,而不用担心付费墙、僵尸检测或奇怪的解析技巧,所以我将把这些担心留给另一个教程。
数据
这里的是一个有 100 个随机 URL 的文件,来自我从 NewsAPI 收集的数据集。前几行如下所示:
Python 库
我们将使用三个开源库(及其依赖项): Pandas 、 Scrapy 和 Readability 。假设您已经安装了pip,您可以通过在终端中运行以下命令来确保您的计算机已经安装了这些:
pip install scrapy pandas readability-lxml
然后,创建要组织项目的文件夹,并导航到该文件夹:
mkdir headline_scraper
cd headline_scraper
现在,我们可以创建蜘蛛。Scrapy 有一个startproject
命令可以设置整个项目,但是我发现它可能会很臃肿。我们将通过制作我们自己的蜘蛛来保持简单,正如所承诺的,它只有 23 行(包括注释和空白)🙂).以下是一个名为headline_scraper.py
的文件的内容:
与普通的 python 脚本不同,我们需要使用 scrapy 的runspider
命令来运行文件。使用-o
标志选择保存输出的位置:
scrapy runspider headline_scraper.py -o scraped_headlines.csv
就这些了!下面是对代码中发生的事情的解释。
遍历代码
初始化
除了导入库和声明PATH_TO_DATA
(指向存储 100 个 URL 的要点的链接)之外,下面是最初几行要做的事情:
class HeadlineSpider(scrapy.Spider)
创建了一个新的类“HeadlineSpider”,它继承了 scrapy 蜘蛛的基本功能name="headline_spider"
将新蜘蛛命名为“头条 _ 蜘蛛”,供 Scrapy 参考start_urls=read_csv(PATH_TO_DATA).url.tolist()
使用 pandas 的 csv 阅读器下载包含 100 个 url 的文件,然后获取“URL”列并将其转换为 python 列表。start_urls
是任何蜘蛛都需要的,但在这种情况下,它们是唯一会被访问的网址。
(如果您想使用具有自己的 URL 的不同文件,只需用您文件的位置替换PATH_TO_DATA
。然后,确保 url 列被标记为“URL”,或者将.url
替换为.name_of_your_column
,它可以在您的机器上,即PATH_TO_DATA=/Users/Jack/Desktop/file.csv
现在我们已经初始化了蜘蛛,我们需要告诉它当它到达一个网页时实际要做什么。
从语法上分析
要真正提取标题,我们必须实现parse
方法。每当 Scrapy 从列表start_urls
中检索到一个 url 时,它会自动向这个方法发送 http 响应,然后完全由您决定如何处理它。这个版本的功能如下:
doc=Document(response.text)
这一行使用可读性的功能来解析 html。你也可以使用其他的库,比如 BeautifulSoup 或者报纸来获取这个部分。yield
本质上是一个创建输出的 return 方法,您可以把它想象成生成的电子表格中的一行。'short_title':doc.short_title()
而它下面的几行只是简单的设置了返回对象的不同属性。您可以将'short_title'
视为结果电子表格中的一列,内容将是doc.short_title()
的输出(例如,“冠状病毒爆发如何影响全球经济”)
同样,这部分是非常可定制的。如果您想尝试获得文章的全文,只需更改 yield 行以包含如下的doc.summary()
。
yield {
'full_text': doc.summary(),
'short_title': doc.short_title(),
'full_title': doc.title(),
'url': response.url
}
这将在结果中增加一个名为full_text
的列。csv 文件,可读性最好的提取文章文本的尝试。
结果
下面是运行scrapy runspider headline_scraper.py -o scraped_headlines.csv:
的输出文件
嘣!至少大部分情况下。Scrapy 是非常容错的,所以只有 95/100 的 URL 返回。没有回来的 5 遇到了某种 http 错误,就像你有时在浏览网页时看到的 404 错误。此外,一些行(我数了 7 行)写着“警告”和“你是机器人吗?”而不是提供真实的标题。(彭博似乎有非常有效的机器人检测。)
有许多策略来处理 bot 检测,其中一些已经在 Scrapy 中实现。如果您感兴趣,请告诉我,我可以在以后的教程中介绍这些策略。
照片由 Divyadarshi Acharya 在 Unsplash 上拍摄
如果您对代码有任何疑问、意见或问题,欢迎回复本文或在Twitter上给我发消息。谢谢!
教程:停止从命令行运行 Jupyter 笔记本
将您的 Jupyter 笔记本作为独立的网络应用程序运行
Justin Jairam 的照片来自 @jusspreme (经允许)
Jupyter Notebook 提供了一个很好的平台来生成包含代码、等式、分析及其描述的人类可读文档。一些人甚至认为它与 NBDev 结合是一个强大的发展。对于这样一个完整的工具,开箱启动并不是最好的。每次使用都需要从命令行启动 Jupyter web 应用程序,并输入您的令牌或密码。整个 web 应用程序依赖于打开的终端窗口。有些人可能会“混淆”这个过程,然后使用 nohup 将它从他们的终端中分离出来,但这不是最优雅和可维护的解决方案。
幸运的是,Jupyter 已经提出了一个解决这个问题的方案,推出了 Jupyter 笔记本的扩展,作为一个可持续的网络应用程序运行,并具有内置的用户身份验证。为了在上面添加一个樱桃,它可以通过 Docker 管理和维护,允许隔离的开发环境。
在这篇文章的最后,我们将利用 JupyterHub 的能力来访问一个 Jupyter 笔记本实例,该实例可以在没有终端的情况下从网络中的多个设备访问,并且是一种更加用户友好的身份验证方法。
先决条件
关于 Docker 和命令行的基本知识将有助于设置这一功能。
我建议在你拥有的最强大的设备上这样做,并且一天的大部分时间都是开着的,最好是一整天。这种设置的一个好处是,你可以在网络上的任何设备上使用 Jupyter Notebook,但是所有的计算都在我们配置的设备上进行。
什么是 Jupyter Hub
JupyterHub 将笔记本电脑的强大功能带给用户组。JupyterHub 背后的想法是将 Jupyter 笔记本的使用范围扩大到企业、教室和大型用户组。然而,Jupyter Notebook 应该作为一个本地实例,由一个开发人员在一个节点上运行。不幸的是,JupyterHub 的可用性和可伸缩性与运行本地 Jupyter 笔记本的简单性之间没有折中。也就是说,直到现在。
JupyterHub 有预建的 Docker 映像,我们可以利用这些映像心血来潮地生成一个笔记本,在技术复杂性方面几乎没有开销。我们将使用 Docker 和 JupyterHub 的组合,从同一网址随时随地访问 Jupyter 笔记本。
体系结构
我们的 JupyterHub 服务器的架构将由两个服务组成:JupyterHub 和 JupyterLab。JupyterHub 将是入口点,并将为任何用户生成 JupyterLab 实例。这些服务中的每一个都将作为 Docker 容器存在于主机上。
JupyterLab 架构图(图片由作者提供)
构建 Docker 图像
为了构建我们的家用 JupyterHub 服务器,我们将使用 JupyterHub & JupyterLab 的预构建 Docker 映像。
码头文件
JupyterHub Docker 图像很简单。
FROM jupyterhub/jupyterhub:1.2# Copy the JupyterHub configuration in the container
COPY jupyterhub_config.py .# Download script to automatically stop idle single-user servers
COPY cull_idle_servers.py .# Install dependencies (for advanced authentication and spawning)
RUN pip install dockerspawner
我们使用预先构建的 JupyterHub Docker 映像,并添加我们自己的配置文件来停止空闲的服务器,cull_idle_servers.py
。最后,我们通过 Docker 安装额外的包来生成 JupyterLab 实例。
Docker 撰写
为了将所有的东西放在一起,让我们创建一个docker-compose.yml
文件来定义我们的部署和配置。
version: '3'services:
# Configuration for Hub+Proxy
jupyterhub:
build: . # Build the container from this folder.
container_name: jupyterhub_hub # The service will use this container name.
volumes: # Give access to Docker socket.
- /var/run/docker.sock:/var/run/docker.sock
- jupyterhub_data:/srv/jupyterlab
environment: # Env variables passed to the Hub process.
DOCKER_JUPYTER_IMAGE: jupyter/tensorflow-notebook
DOCKER_NETWORK_NAME: ${COMPOSE_PROJECT_NAME}_default
HUB_IP: jupyterhub_hub
ports:
- 8000:8000
restart: unless-stopped # Configuration for the single-user servers
jupyterlab:
image: jupyter/tensorflow-notebook
command: echovolumes:
jupyterhub_data:
需要注意的关键环境变量是DOCKER_JUPYTER_IMAGE
和DOCKER_NETWORK_NAME
。JupyterHub 将使用环境变量中定义的图像创建 Jupyter 笔记本。有关选择 Jupyter 图像的更多信息,您可以访问以下 Jupyter 文档。
DOCKER_NETWORK_NAME
是服务使用的 Docker 网络的名称。这个网络从 Docker Compose 自动获得一个名称,但是集线器需要知道这个名称来连接 Jupyter 笔记本服务器。为了控制网络名,我们使用了一个小技巧:我们将一个环境变量 COMPOSE_PROJECT_NAME 传递给 Docker Compose,网络名是通过向它附加 _default 获得的。
在与docker-compose.yml
文件相同的目录下创建一个名为.env
的文件,并添加以下内容:
COMPOSE_PROJECT_NAME**=**jupyter_hub
停止空闲服务器
因为这是我们的主设置,所以我们希望能够停止空闲的实例来保留我们机器上的内存。JupyterHub 有一些服务可以和它一起运行,其中之一就是 jupyterhub-idle-culler 。该服务停止任何长时间空闲的实例。
要添加这个服务,创建一个名为cull_idle_servers.py
的新文件,并将 jupyterhub-idle-culler 项目的内容复制到其中。
请确保“cull_idle_servers.py”与 docker 文件位于同一文件夹中。
要了解更多关于 JupyterHub 服务的信息,请查看他们的官方文档。
Jupyterhub 配置
最后,我们需要定义配置选项,如卷装载、Docker 映像、服务、身份验证等。对于我们的 JupyterHub 实例。
下面是我使用的一个简单的jupyterhub_config.py
配置文件。
import os
import sysc.JupyterHub.spawner_class **=** 'dockerspawner.DockerSpawner'
c.DockerSpawner.image **=** os.environ['DOCKER_JUPYTER_IMAGE']
c.DockerSpawner.network_name **=** os.environ['DOCKER_NETWORK_NAME']
c.JupyterHub.hub_connect_ip **=** os.environ['HUB_IP']
c.JupyterHub.hub_ip **=** "0.0.0.0" *# Makes it accessible from anywhere on your network*c.JupyterHub.admin_access **=** Truec.JupyterHub.services **=** [
{
'name': 'cull_idle',
'admin': True,
'command': [sys.executable, 'cull_idle_servers.py', '--timeout=42000']
},
]c.Spawner.default_url **=** '/lab'notebook_dir **=** os.environ.get('DOCKER_NOTEBOOK_DIR') **or** '/home/jovyan/work'
c.DockerSpawner.notebook_dir **=** notebook_dir
c.DockerSpawner.volumes **=** {
'/home/sidhu': '/home/jovyan/work'
}
请注意以下配置选项:
'command': [sys.executable, 'cull_idle_servers.py', '--timeout=42000']
: Timeout 是空闲 Jupyter 实例关闭之前的秒数。c.Spawner.default_url = '/lab'
:使用 Jupyterlab 代替 Jupyter 笔记本。注释掉这一行以使用 Jupyter 笔记本。'/home/sidhu': '/home/jovyan/work'
:我将我的主目录挂载到 JupyterLab 主目录,以便访问我桌面上的任何项目和笔记本。这也允许我们在创建新笔记本的情况下实现持久性,它们被保存到我们的本地机器,并且不会在我们的 Jupyter Notebook Docker 容器被删除时被删除。
如果您不希望挂载您的主目录,请删除这一行,并且不要忘记将sidhu
改为您的用户名。
启动服务器
要启动服务器,只需运行docker-compose up -d
,在浏览器中导航到localhost:8000
,您应该能够看到 JupyterHub 登录页面。
JupyterHub 登陆页面截图(图片由作者提供)
要在网络上的其他设备(如 asva 笔记本电脑、iPad 等)上访问它,请通过在 Unix 机器上运行ifconfig
在 Windows 上运行& ipconfig
来识别主机的 IP。
Ipconfig(图片作者提供)
从您的另一台设备上,导航到您在端口 8000: http://IP:8000
上找到的 IP,您应该会看到 JupyterHub 登录页面!
鉴定
这就给我们留下了向服务器进行认证的最后一项任务。因为我们没有设置 LDAP 服务器或 OAuth,所以 JupyterHub 将使用 PAM(可插拔认证模块)认证来认证用户。这意味着 JupyterHub 使用主机的用户名和密码进行身份验证。
为了利用这一点,我们必须在 JupyterHub Docker 容器上创建一个用户。还有其他方法可以做到这一点,例如在容器上放置一个脚本,并在容器启动时执行,但我们将手动完成它作为一个练习。如果您拆除或重建容器,您将必须重新创建用户。
我不建议将用户凭证硬编码到任何脚本或 docker 文件中。
1)找到 JupyterLab 容器 ID: docker ps -a
JupyterLab 容器 ID(图片由作者提供)
2)“SSH”进入容器:docker exec -it $YOUR_CONTAINER_ID bash
3)创建用户,按照终端提示创建密码:useradd $YOUR_USERNAME
4)使用凭证登录,一切就绪!
现在,您已经拥有了一台随时可用的 Jupyter 笔记本电脑服务器,可以从任何设备访问,尽在您的掌握之中!编码快乐!
反馈
我欢迎任何关于我的帖子和教程的反馈。你可以在 sidhuashton@gmail.com 的推特上给我发消息,或者发电子邮件给我。
教程:使用 CatBoost 进行不确定性估计
理解为什么你的模型是不确定的,以及如何估计不确定性的水平
数据不确定性示例(图片由 Yandex 提供)。
本教程涵盖以下主题:
- 什么是预测不确定性,为什么要关心它?
- 不确定性的两个来源是什么?
- 如何使用 CatBoost 梯度增强库估计回归问题的不确定性
你可以使用这个 Jupyter 笔记本遵循所有步骤。
什么是不确定性?
机器学习已经广泛应用于一系列任务。然而,在某些高风险应用中,如自动驾驶、医疗诊断和金融预测,一个错误可能会导致致命的后果或巨大的经济损失。在这些应用中,重要的是检测系统何时出错并采取更安全的措施。此外,还需要收集这些“故障场景”,标记它们,并通过主动学习教会系统做出正确的预测。
预测不确定性估计可用于检测误差。理想情况下,模型表明在可能出错的情况下存在高度的不确定性。这使我们能够发现错误并采取更安全的行动。至关重要的是,行动的选择可能取决于为什么模型是不确定的。不确定性的来源主要有两种:数据不确定性(也称任意不确定性)和知识不确定性(也称认知不确定性)。如果我们的目标是检测错误,就没有必要分离这两种不确定性。然而,如果我们的目标是主动学习,那么我们希望检测新的输入,而知识不确定性可以用于此。
数据的不确定性源于数据固有的复杂性,如附加噪声或重叠类别。在这些情况下,模型知道输入具有多个类的属性或者目标有噪声。重要的是,数据不确定性不能通过收集更多的训练数据来减少。
当模型的输入来自训练数据稀疏覆盖的区域或远离训练数据的区域时,知识不确定性出现。在这些情况下,模型对这一地区知之甚少,很可能出错。与数据不确定性不同,知识不确定性可以通过从了解不多的区域收集更多的训练数据来减少。
这篇教程文章详细介绍了如何在 CatBoost 中量化数据和知识的不确定性。
CatBoost 中的数据不确定性
为了说明这些概念,我们将使用一个简单的合成示例。
假设我们有两个分类特征 x₁和 x₂,每个有 9 个值,因此有 81 个可能的特征组合。目标取决于以下特征
y = mean(x₁,x₂) + eps(x₁,x₂)
其中均值 (x₁,x₂) 是某个未知的固定值,eps (x₁,x₂) 是均值为 0、方差为 var (x₁,x₂) 的正态分布噪声(即数据不确定性)。在我们的示例中,mean (x₁,x₂) 是随机生成的,var (x₁,x₂) 有两个值(0.01 和 0.04),分布如下:
数据中的差异。白色区域没有训练示例。
因此,心脏上的点比心脏外的点在目标中具有更多的噪声。请注意,我们为更好的可视化列举了类别,但是在数据集中,两个特征都是分类的,即没有给出顺序。
当我们生成具有这种分布的数据集时,我们假设心脏内部没有任何训练样本,这些特征组合被视为数据集的异常值。
用 RMSE 损失优化的标准模型只能预测 mean(x₁,x₂).好吧,但是如果我们想估计 y 的方差,也就是数据不确定性呢?换句话说,如果我们想了解哪些预测是有噪声的呢?为了估计数据的不确定性,人们不得不使用概率回归模型预测均值和方差。为此,CatBoost 中有一个新的损失函数,称为 RMSEWithUncertainty。对于这种损失,CatBoost 估计正态分布的均值和方差,优化负对数似然,并使用自然梯度,类似于 NGBoost 算法[1]。对于每个示例,CatBoost 模型返回两个值:估计平均值和估计方差。
让我们试着将这个损失函数应用到我们的简单例子中。我们得到以下方差:
用 RMSEWithUncertainty 猫靴损失估计的方差(数据不确定性)。
我们可以看到,CatBoost 成功地预测了心脏内外的方差。在心脏内部,我们没有训练数据,所以任何事情都可以在那里预测。
CatBoost 中的知识不确定性
好,我们知道如何估计数据中的噪声。但是,如何衡量某个特定地区缺乏训练数据所带来的知识不确定性呢?如果我们想检测异常值,该怎么办?估计知识的不确定性需要一个模型集合。如果所有模型都理解一个输入,它们将给出相似的预测(低知识不确定性)。然而,如果模型不理解输入,那么它们很可能提供不同的预测,并且彼此强烈不一致(高知识不确定性)。对于回归,知识不确定性可以通过测量跨越多个模型的平均值的方差来获得。注意,这不同于单个模型的预测方差*,后者捕捉数据不确定性。*
让我们考虑如下生成的 GBDT 模型的集合:
使用选项后验采样生成模型,因为这允许获得的(随机)预测很好地分布(具有良好的理论特性,这里我们参考[2]了解细节)。
然后,为了估计知识的不确定性,我们只需计算模型预测的平均值的方差:
knowledge = np.var(ens_preds, axis=0)[:, 0]
我们得到以下结果:
通过模型集成估计知识不确定性。
该模型正确地检测了心脏内部的知识不确定性(我们看不到原始心脏边界的痕迹)。这说明了如何通过估计知识的不确定性,我们可以检测异常输入。
在实践中,训练几个 CatBoost 模型的集合可能过于昂贵。理想情况下,我们希望训练一个单一的模型,但仍然能够检测异常值。有一个解决方案:我们可以使用从单个训练模型获得的虚拟集合:
由于只有一个训练好的模型,CatBoost 会为每个示例返回几个预测。这些预测是通过截断模型获得的:
虚拟合奏(图片由作者提供)
同样,我们使用选项后验采样来保证裁剪预测的理想分布。让我们看看我们得到了什么:
由虚拟集合估计的知识不确定性。
注意,知识不确定性的预测绝对值现在小得多,因为虚拟系综元素是相关的。但是,它仍然可以成功地检测未被占用的区域(异常值)。
我们可以使用prediction _ type = ’ total uncertainty ',而不是*prediction _ type = ’ virt ensembles '*返回几个模型的预测,这样更容易得到相同的结果。对于这种预测类型,CatBoost 使用虚拟集合计算所有类型的不确定性。也就是说,对于 RMSEWithUncertainty,它返回以下统计数据:[均值预测、知识不确定性、数据不确定性]:
感谢您的关注!我希望这篇教程能帮助你更好地理解不确定性的概念,以及如何用 CatBoost 估计它。我们将在以后的文章中告诉你更多关于不确定性的应用。敬请期待😺
[1] T. Duan 等, NGBoost:概率预测的自然梯度推进 (2020),2020
[2] A. Ustimenko,L. Prokhorenkova 和 A. Malinin,通过系综进行梯度增强的不确定性(2020),arXiv 预印本 arXiv:2006.10562
辅导强化学习
强化学习代理从零开始,什么都不知道,凭经验学习,有效但慢。我们能给他们一些提示让他们开始吗?
这个故事基于我与人合著的一篇论文,你可以在这里找到。
近年来,强化学习在视频游戏、机器人和推荐系统等任务中取得了令人惊讶的结果。然而,这些成功的结果是在训练 RL 代理数百万次迭代之后得到的。在那之前,经纪人的表现将远远谈不上伟大。事实上,当智能体开始时,它的行为在探索它可以采取的不同行动时是随机的,即使经过几次迭代并获得一些经验,智能体也会因为其在环境中的行动的可变性和随时可能出现的看不见的状态而经常出错。
在像视频游戏这样的环境中,这可能不是问题(尽管这意味着您需要时间和一些重要的计算资源),但在现实世界的系统中,这是一个严重的挑战。你可能会想到一个使用 RL 来学习如何移动的机器人:机器人可能需要几天来学习如何正确移动,如果移动是危险的,它可能会损坏自己。
你不得不爱失败,虽然[视频来自 IEEE。]
作为人类,我们不会从头开始学习一切,如果我们会,我们离穴居人就不远了。我们取得的所有进步都是通过学习他人的成就并加以改进而实现的。我们不能用 RL 做类似的事情吗?我们能不能教代理一些通用的规则,让它在从自己的经验中学习时可以应用?
我和我的同事们一直在研究这个想法,我们开发了一种叫做 Tutor4RL 的方法。我们已经在今年的 AAAI 制造:在实践中结合机器学习和知识工程上发表了它,你可以在这里看到它(不幸的是,今年的春季会场被取消了,但论文发表了。)Tutor4RL 仍在开发中,所以我在这里介绍我们方法和目前为止的初步结果。
常见方法
正如我所说,学习速度慢是学习者面临的一个普遍挑战,许多方法已经出现来解决这个问题:
- Simulations :一种常见的方法是创建一个模拟环境,在将代理部署到真实环境之前,代理可以在其中进行实验和培训。这种方法非常有效,但是创建模拟环境需要很大的努力,并且我们通常最终会对真实环境做出假设来创建模拟,这可能并不总是正确的。这些假设会影响代理在真实环境中的表现。
- 基于模型的 RL :与无模型的 RL 相反,基于模型的 RL 创建其环境的模型,这允许代理更快地学习。在机器人的例子中,我们可以把我们的 RL 模型建立在机器人的物理学和力学的基础上。然而,为了制作这个模型,我们需要大量来自环境的知识,同样,我们通常会做出伤害我们的假设。此外,生成的代理是特定于其环境的,如果我们想将其用于不同的环境,我们需要修改其模型,这涉及到额外的工作。
- 从演示中学习:在 Hester et al. (2018)中,作者开发了一种方法,使智能体可以有效地从人类的演示中学习。学习速度大大加快,并且代理能够达到最先进的结果。但是,如果我们事先无法接触到环境,因此无法提供演示,会发生什么情况呢?这种方法可以与 Tutor4RL 结合使用,当代理已经部署在其环境中时,使用 Tutor 来提供演示。
Tutor4RL
我们希望我们的代理从一开始就表现得好(或者至少体面),但是当我们事先无法访问环境时,这是非常困难的,如果我们对环境做出任何假设,而这些假设是错误的,那么代理的表现将会受到影响,不仅是最初,而是贯穿其整个生命周期。但是,这并不意味着我们不能提供一些有用的信息,代理一旦部署到环境中就可以使用这些信息。
最后,当我们学到一些东西时,我们并没有被告知我们将会遇到的每一种情况的所有细节。相反,我们可以从理论观点和其他人给我们的提示中学习。一个 RL 特工能做到这些吗?
为了做到这一点,我们修改了 RL 框架,如下图所示:
与 Tutor4RL 框架相比的标准 RL 框架[摘自原始出版物。]
我们添加了一个组件,我们称之为 Tutor,它包含了外部知识,是一个知识函数的集合。这些函数是普通的可编程函数,将状态和奖励作为输入,并输出一个向量,该向量带有每个动作的值,其方式类似于策略如何将状态映射到带有 Q 值的动作。有两种类型的知识函数:
- 向导功能:这些功能向代理表达向导或提示,并被解释为建议,即使它们是错误的,代理也会根据自己的经验得知它们不好,不会遵循它们。
- 约束函数:这些函数限制了智能体的行为,当我们确定智能体在某个场景中不应该做某件事的时候,它们会很有用,也许是因为这可能会伤害到它自己,或者可能会导致一些危险的情况。约束函数告诉代理不要做什么,输出一个向量,其中 1 表示可以采取的每个动作,0 表示不可以采取的每个动作。
当代理不确定要做什么时,例如在最初的步骤中,它可以向导师询问它的知识。指导者将回复它的功能集合,然后代理将使用它来选择要执行的动作,并从这个经验中学习。以这种方式,指导者指导代理,但是代理总是能够发现来自指导者的建议是否是错误的,或者通过使用一些探索机制,例如ε-贪婪,还能够发现是否存在比指导者的选择更好的行动。然而,约束函数总是应用于向导函数和代理的策略,因此它提供了一个安全层来避免可能使代理处于危险中或对任务有很大负面影响的严重错误。
估价
外部环境:从 OpenAI 健身房突围。
我们已经在 Python 上使用 Keras-RL 实现了 Tutor4RL 的原型。我们已经将 Tutor4RL 应用到一个 DQN 代理(Mnih et al. 2015) ,在 OpenAI Gym 上玩突围。我们使用了一个简单的引导函数,如果球不在横杠的正上方,它告诉代理向球所在的方向移动(不是说在这个测试中,我们没有使用约束函数)。此外,我们实现了一个非常简单的方法来控制代理何时使用导师的指南:我们定义了一个名为τ的参数,其使用方式与ε在ε-贪婪探索中的使用方式相同。当τ大于取自 U(0,1)分布的样本时,我们使用导师的输出,否则,我们使用策略的输出。我们将代理初始化为τ=1,并随时间线性减少,因此当代理启动时,导师的输出被大量使用,但随着代理积累更多经验,这种情况会减少。
下面,你可以看到 DQN 代理与 Tutor4RL 相比标准的普通 DQN 代理所获得的回报。突围中的奖励直接是游戏上达到的分数,所以你突破的格挡越多,分数越高,奖励也越高。正如你所看到的,在普通的 DQN 代理苦苦挣扎的时候,由于导师的指导,带 Tutor4RL 的 DQN 代理显示了最初的良好表现。普通 DQN 代理需要大约 130 万次迭代才能赶上,在 150 万次迭代中,导师完全停止使用。请注意,在此之前,导师是间歇性使用的,取决于每次迭代中减少的τ值。在那之后,我们可以看到两个代理有相似的表现,显示出被辅导的 DQN 代理也学会了但避免了普通 DQN 代理的粗糙开始。
与普通 DQN 代理人相比,使用 Tutor4RL 的 DQN 代理人的平均报酬【摘自原始出版物。]
结论
Tutor4RL 已被证明能够帮助代理从其环境的一些知识开始,提高其初始步骤的性能。然而,Tutor4RL 仍在发展中,有几个方面可以改进:
- 我们只测试了引导函数,所以接下来的步骤是实现约束函数的机制以及一些示例约束函数并测试它们。
- 用τ管理不确定性是一种幼稚的方法,可以通过使用其他方法得到很大改善,如自举法( Kahn 等人(2017) )或贝叶斯法(Clements 等人(2020))。
- 可能有更好的方法来集成和使用来自知识函数的输出向量,利用函数之间的相关性,如通气管(Ratner et al. (2019)) 。
一如既往的感谢阅读!我希望你对这种方法感兴趣,并期待听到你的反馈。我相信还有更多方法可以改进 Tutor4RL。
电视节目对人工智能感到害怕是正确的——因为所有错误的原因
我们已经多次看到好莱坞对人工智能灾难的处理,但这个行业及其消费者实际上应该担心什么?
去年夏天,当福克斯公司宣布他们的新“科幻小说”击中“下一个”时,该节目的描述听起来类似于黑镜或菲利普·k·迪克(Philip K. Dick)的《电梦》(Electric Dreams),这是一个关于控制技术对其用户的侵蚀的警示故事:
“接下来是一部推进性的、基于事实的惊悚片,讲述了一种致命的、流氓式的人工智能的出现,它结合了脉冲冲击行动和对技术如何入侵我们的生活并以我们尚不了解的方式改变我们的分层检查。”
然而, 从它的预告片 来看,这部剧的故事情节离这个总结太远了。预告片以一个类似 Alexa 的东西开场,一切看起来都很好,直到它获得了自己的意志,以邦德超级反派的微妙和冗长肆虐并反抗其用户和人类创造者。这种试图用“入侵者”的形象来描绘社会恐惧的赫伯特·乔治·威尔斯方法可能对世界之战或哥斯拉有用。然而,在这种情况下使用人工智能会严重误导我们对人工智能和决策算法的现实担忧,其中许多都严重影响了我们生活在其中的非虚构现实中的人类生活。
这不仅仅是数据隐私
要明确的是,数据隐私是一个组成部分。你应该关心你的数据,人工智能的支柱,去哪里了。越来越不可避免的是,作为社会的积极参与者,你将被迫把你的品味和行为的很大一部分交给数据收集公司。这些公司的唯一目的是从数据中榨取尽可能多的价值,如果不成为数字隐士,我们对此几乎无能为力。
你知道吗,不仅你可以通过点击和在线搜索被跟踪和识别,你的身体动作也可以被跟踪和识别。那些开始覆盖笔记本电脑网络摄像头的人可能在正确的道路上,但可能没有听说过行为生物测定学:通过这些技术,你在键盘上打字的节奏或你鼠标的移动模式等细节可以将你与你的身份联系起来(了解如何在这里停止)。
现在,我不是说你不应该尝试最小化你的数字数据足迹。此外,围绕数据隐私工作的对话也应该关注公众对更严格的安全和隐私政策的强烈要求。在 Vox 播客“Recode Decode 的最近一集,DuckDuckGo 的首席执行官 Gabe Weinberg 认为,选择加入数据跟踪应该是默认的,而不是许多数据公司实施的模糊的选择退出方法。这是许多欧洲国家通过政策认同的一个流行观点,需要在全球范围内采纳。
行为转变策略
数据公司已经意识到,他们不仅可以使用他们的资产和工具进行数据收集和行为预测,而且他们现在可以部署他们的洞察力来转变行为,有效地操纵我们未来的行动,为他们带来最佳利益。在《监视资本主义的时代》一书中,作者肖莎娜·祖博夫认为 资本主义行为分析的最终结果可能不仅仅是对我们隐私的威胁,而是对我们非常自由的意志的威胁——预设决策和自我实现预言的决定性景观。祖博夫认为:
“监视资本主义单方面宣称人类经验是转化为行为数据的免费原材料。虽然这些数据中的一些被用于服务改进,但其余的被宣布为专有的行为盈余,被输入到被称为“机器智能”的先进制造流程中,并被制作成预测产品,预测您现在、不久和将来会做什么。最后,这些预测产品在一种新的市场中交易,我称之为行为期货市场。监视资本家从这些交易操作中变得非常富有,因为许多公司愿意对我们未来的行为下注”
在资本主义思维控制下,不受监管的数据跟踪和操纵的影响应该是显而易见的。从对我们行为的威胁到民主本身,我们不需要一个电脑化的超级恶棍来想象一个真实存在的人工智能威胁。如果我们想在自主性完好无损的情况下走出这个新的数字黄金时代,一种稳健且基于道德的数据政策实施方法是根本。
没有无偏见这回事
偏见无处不在,算法于事无补,它们模糊了问题,加剧了问题。数据和算法不是我们世界的客观反映;他们带着来自创造他们的文化和组织的同样的偏见、成见和误解。除了它们隐藏在鼓励对这些偏见缺乏问责的包装中,使得更容易证明将决定论误认为客观性是正确的。通过实施决定谁优先接受医疗护理、谁涉嫌犯罪或向儿童推荐什么在线内容的系统,我们正在增加问责制的缺乏,而没有解决紧迫的问题。
Rachel Thomas 是旧金山大学数据研究所的教授,也是 Fast.ai 的联合创始人,她曾就这个主题发表过长篇大论:
“我们的算法和产品影响着世界,是反馈回路的一部分。考虑一种预测犯罪并确定向哪里派遣警察的算法:向特定的街区派遣更多的警察不仅是一种效果,也是一种原因。在给定的街区,更多的警察可以导致更多的逮捕,这可能会导致算法向该街区派遣更多的警察(这种机制在关于失控反馈循环的论文 中有所描述)。
与欧洲血统的人相比,计算机视觉算法 在有色人种 上表现不佳,因为绝大多数面部数据来自欧洲血统的人。 M ost 收集的行为数据来自发达国家的富裕地区 ,自动填充算法更有可能为男性建议 STEM 相关的职业术语,为女性建议家政术语。这些刻板印象不是恶意的结果,而是反映在数据广度和宽度上的社会和个人偏见。然而,不管来自何方,这些问题都需要解决。
算法和数据远非客观真理的仲裁者,而是我们偏见的载体,这种偏见非常丰富。缺乏对那些执行、部署、消费和管理它们的人的理解,导致我们被我们创造的有偏见的、可操纵的机器推下悬崖。自人工智能诞生以来,伦理考量就一直是其核心的重要组成部分。因此,等到损害已经造成,或者相信巨额罚款的威胁不仅仅是解决更大问题的权宜之计,都是错误的。
认知偏差法典,设计:约翰·马诺吉安三世,类别和描述:巴斯特·本森,实现:蒂尔曼纳[CC BY-SA]
我们能做些什么呢?
可悲的是,解决这些问题不会像“下一个”电视节目让我们相信的那样,像号召邋遢顽固的侦探打败 Alexa 的邪恶表弟那样容易。这里没有“其他人”,没有来自错误实验的流氓人工智能,只是对我们社会偏见和疑虑的认可,包装成闪亮的代码行。
我们已经知道如何处理偏见。人类以前已经足够聪明,能够(在不同程度上)认识到并纠正它们。挑战在于我们是否有能力将这些解决方案应用到我们曾经认为公平或客观的系统中。这样做的下一步是为负责数据流程中每个步骤(数据的收集、存储、探索、建模和部署)的人员建立限制和问责制。此外,我们需要始终意识到偏见是多么容易被忽略,并理解算法可能会犯错误——频繁,而且比预期的影响更大。最终取得成功意味着准备好主动纠正问题,如果不能,在损害不可逆转之前放弃算法。
在 InfoQ 的一次介绍会上 ,Rachel Thomas 概述了一些我们上面讨论的问题的解决方案,比如:
- 不要最大化指标 —想要数字增加很容易,但我们越是将数据简化为数字,就越容易遗漏错误并奖励我们提供的服务中存在的负面行为,或者启用不公正地歪曲所述服务的限制性反馈循环。
- 雇佣多元化的团队 —研究表明多元化的团队表现更好,从分析角度来看,他们有助于更好地理解数据集所包含的主题,带来更好的、可操作的见解,并确保偏见不是来自你的团队。
- “先进的技术不能代替好的政策,”托马斯说。偏见很难捕捉;不管你的算法或者管道有多好。需要制定法规和协议,以便用户可以对算法做出的决定提出上诉。
- 永不放弃 —我们永远不会达到人类和我们的算法没有偏见的地步。我们一开始就是这么过来的!我们有责任训练人们时刻警惕反馈循环、偏见和我们数据中隐含的偏见。
最后,把黑白场景留给周末科幻电视节目。
使用 Python 对网飞和亚马逊 Prime Video 等在线流媒体服务上的电视节目进行可视化比较
使用 Python 的 Seaborn 和 Matplotlib 库创建关于流行在线流媒体服务的信息图的比较研究
简介:
在疫情期间不会倒闭的为数不多的服务中,有像网飞和亚马逊 Prime Video 这样的在线流媒体服务。看看下面的谷歌趋势结果,从 1 月 1 日到 6 月 12 日。在 2020 年 3 月中旬左右,新冠肺炎和网飞的网络搜索量明显上升,当时新冠肺炎病例在全球范围内飙升,企业因不可避免的封锁而关闭。还有一个有趣的每周模式,搜索数量在周末增加。
网飞和科维德在谷歌上的搜索次数时间表。谷歌表示,这些数字代表了在给定地区和时间,相对于图表最高点的搜索兴趣。这种明显的增长在 3 月中旬尤为明显,当时新冠肺炎病例在全球范围内飙升,企业纷纷关门。此外,还有一个很好的周线模式。
谷歌搜索的受欢迎程度:
我想,到目前为止,最受欢迎的服务是网飞。为了支持我的假设,这里有一张亚马逊 Prime Video、网飞、Disney+和 Hulu 日均搜索量的柱状图。
在左边的分布中,从年初到 6 月 12 日,平均每天有 56 次对网飞的搜索,其次是 9 的亚马逊 Prime Video、迪士尼+4和 4 的 Hulu。
如果我们用日均谷歌搜索量来衡量受欢迎程度,那么网飞无疑以较大优势高居榜首。看起来,网飞的受欢迎程度是亚马逊 Prime Video 的六倍。迪士尼+和 Hulu 的受欢迎程度只有亚马逊 Prime Video 的一半,不及网飞的 14 倍。唷!
订户比较:
每个在线流媒体服务的用户都以百万计。(数据来源:https://en.wikipedia.org/wiki/Streaming_service_provider)
网飞的用户数量几乎是亚马逊 Prime Video 的 2.5 倍。两者都是全球服务提供商,而 Disney+和 Hulu 都有特定的目标国家。
Disney+和 Hulu 属于同一个母公司,华特·迪士尼公司。Disney+成立还不到一年,其订阅用户比 Hulu 多 80%,尽管 Hulu 有更多的节目和更好的目标观众分布(参见以下部分的可视化)。Hulu 于 2007 年推出,同年网飞也推出了。亚马逊 Prime Video 比他们早一年在 2006 年推出。
令人惊讶的是,Walk Disney 公司在线流媒体服务的用户总数无法超过网飞的用户总数。更确切地说,亚马逊 Prime Video、Hulu 和 Disney+这三家网站都无法与网飞的用户总数相提并论。
数据来源:
以下是所用 Kaggle 数据集的链接:
[## 网飞、Prime Video、Hulu 和 Disney+上的电视节目
这些流媒体平台上的电视节目集
www.kaggle.com](https://www.kaggle.com/ruchi798/tv-shows-on-netflix-prime-video-hulu-and-disney)
步骤 1:清理数据
数据集看起来像左边的表。
该数据集有 5611 个缺少年龄、IMDb 和烂番茄评分的实例。我没有删除这些行,而是仅用字符串“N/A”填充了“Age”。我还使用 str.replace 删除了烂番茄评级中的“%”符号。评级网站的绘图不需要 NaNs 进行屏蔽,尽管我必须为烂番茄对它们进行一些预处理。因为这些是数字列,所以在浏览和可视化数据时,零会导致数据集中不必要的偏斜,除非经过过滤,这种情况发生在我身上(是的…傻)。详细的代码可以在我的知识库中找到(博客底部的链接)。
我还将所有的电视节目标题转换成小写字母,并去掉标点符号,以查看名称的重叠部分。此外,我创建了另一个包含电视节目名称和发行年份的列,以区分 ABC Show 1991 和 ABC Show 2020。
步骤 2:创建可视化效果
对于视觉效果,我选择了网飞、亚马逊 Prime Video、Disney+和 Hulu 的颜色代码。
# My Custom Palette for the Services
pallete_dict = {
'Netflix': ['#A9A9A9', '#E50914'], # Red
'Prime Video': ['#A9A9A9', '#00A8E1'], # The Lighter Blue
'Hulu' : ['#A9A9A9', '#3DBB3D'], # Green
'Disney+' : ['#A9A9A9', '#113CCF'] # Darker Blue
}
颜色:#E50914,#00A8E1,#3DBB3D,#113CCF
Viz 1:每个在线流媒体服务上电视节目数量的条形图
ax = sns.barplot(y=counts_list, x=list(pallete_dict.keys()),
palette= ['#00A8E1', '#E50914', '#3DBB3D',
'#113CCF'],
order=['Prime Video', 'Netflix', 'Hulu', 'Disney+'] )
*reset_bar_width(ax, 0.3)*
plt.ylabel('Number of TV Shows')
plt.grid(True, axis='y', color='grey')
plt.savefig('demo6.png', transparent=True)
我创建了 reset_bar_width 函数来动态设置条形宽度,因为我喜欢右边的条形图。
这里的代码用于设置条形宽度:
def reset_bar_width(ax, new_width):
for patch in ax.patches:
old_width = patch.get_width()
patch.set_width(new_width)
shift = old_width - new_width. # To re-align the labels
patch.set_x(patch.get_x() + shift * .5)
Viz 2:散点图,用于沿着数据集中的整个时间线绘制电视节目
为了生成这个图表,我过滤了 1930 年以后的电视节目(它们是不正确的),然后根据每个在线流媒体服务中的存在或不存在进行分组。在这些组中,我将电视节目按字母顺序排序,以注入随机性——不确定是否需要。这些图表看起来不错:
col_names_online_media = ['Netflix', 'Prime Video', 'Disney+',
'Hulu']for col_name, num in zip(col_names_online_media,
range(1,len(col_names_online_media) + 1)):
ax = fig.add_subplot(2, 2, num)
sns.scatterplot(x="Year", y="Title Unique Labels",
palette = pallete_dict[col_name],
hue=col_name,
data=df[df.Year > 1930].sort_values(by=
[col_name,
'Title Unique Labels']),
ax=ax)
sns.despine
ax.set_title('TV Shows on ' + col_name, fontsize=25)
handles, labels = ax.get_legend_handles_labels()
ax.legend(loc='upper left',
frameon=None,
edgecolor='black',
fontsize=15,
framealpha=0.2,
handles=[handles[2]],
labels=['On ' + col_name])
ax.set_xlim(1930, 2022)
ax.set(yticklabels=[])
ax.set(ylabel=None, xlabel=None)
fig.tight_layout()
for ax in fig.get_axes():
ax.label_outer()
plt.savefig('demo1.png', transparent=True)
plt.show()
即 3:所有在线流媒体服务的目标年龄组
有五个明确界定的目标年龄组:7 岁以上、13 岁以上、16 岁以上、18 岁以上和所有年龄组。几乎 44%的数据是未知的,所以我把它们标为“不适用”。有趣的是,Disney+拥有最多适合儿童观看的节目,而且收视率相当稳定,我们将在下面的可视化中看到这一点。
palette_list=['Reds_r',
['#0BB5FF', '#000000', '#63D1F4', '#98F5FF',
'#C1F0F6', '#E0FFFF'],
['#00009C', '#000000', '#000000', '#000000',
'#003EFF', '#CAE1FF'],
'Greens_r' ]
**for** col_name, num **in** zip(col_names_online_media,
range(1,len(col_names_online_media) + 1)):
data = df[df[col_name] ==1].groupby(by='Age')
.count()
.reset_index()[['Age', col_name]]
data[col_name] = data[col_name]*100/len(df)
ax = fig.add_subplot(2, 2, num)
sns.barplot(x="Age",
y=col_name,
data=data,
order=['7+', '13+', '16+', '18+', 'all', 'N/A'],
palette=palette_list[num-1])
reset_bar_width(ax, 0.3)
ax.set_title('Age Restriction Distribution of ' + col_name,
fontsize=15)
ax.set_ylabel('Percentage of TV Shows')
ax.set_ylim(0, 25)
ax.grid(**True**, color='grey', axis='y')
fig.tight_layout()
plt.savefig('demo3.png', transparent=**True**)
plt.show()
正确图形
即 4:可视化每个电视节目分级网站对每个在线流媒体服务的分级的集中和范围
箱线图是可视化连续变量分布的最佳方式。正如我之前提到的,Disney+的一致性在这里显而易见。网飞、亚马逊和 Hulu 以相似的评分分布相互竞争。总的来说,网飞的范围更广。
palette_colour_from_dict = [v[1] **for** v **in** list(pallete_dict.values())]
sns.boxplot(x='Variable',
y='Value',
palette=palette_colour_from_dict,
order=list(pallete_dict.keys()),
data=df_box_plot_prep_imdb)
*# plt.xlabel('Online Streaming Media')*
plt.xlabel(xlabel=**None**)
plt.ylabel('IMDb Ratings')
plt.grid(**True**, axis='y', color='grey')
plt.savefig('demo4.png', transparent=**True)**
Viz 5:电视节目标题中最常见的词
我试图创建一个三角形的文字云来适应信息图。我很少用这个,但我真的很想用。我的意思是我用了一个透明的版本,因为颜色、间距和样式不匹配。
mask_image = 'path_to_my_jpg'
image_mask = np.array(Image.open(mask_image))
image_colors = ImageColorGenerator(image_mask)
wordcloud = WordCloud(width = 2000, height = 1200, max_words = 500,
normalize_plurals = **True**, colormap='YlOrBr',
mask=image_mask,
background_color = 'white', font_step = 1,
relative_scaling = 0.8,
collocations = **False**,
include_numbers = **False**)
.generate(' '.join([each_token.upper()
**for** each_token **in** token_list]))
plt.figure(figsize = (20,13))
plt.imshow(wordcloud)
plt.axis("off")
plt.savefig('demo7.png', transparent=**True**)
plt.show()
Viz 6:电视节目标题中十大常用词的条形图
这将生成一个带有标签和值的条形图。我对实际信息图中的图表进行了一点格式化。
我首先从我的信息图模板(#FFC000)中选择十六进制代码。这次我使用了 power-point,颜色选择器工具对获取自定义十六进制代码非常有帮助。单词的文本位置很容易。我选择了 x 的一个常数函数,并画出了单词。对于数字,我选择了一个常数来绘制第一个文本,并根据当前和以前的条形高度之差(或者换句话说,字典中当前和以前的字数之差)来减少它,以绘制其余的文本。我根据剩下的数字调整了图中的第一个数字(102 ),因为它多了一个数字,而且没有完全对齐。
这是代码,下面是图表:
ax = sns.barplot(x=list(word_freq_dict.keys()),
y=list(word_freq_dict.values()),
palette = ['#404040'] * 10)# Set up labels
for i, xlabel_text in enumerate(list(word_freq_dict.keys())):
# text placement for the top 10 words
ax.text(i - .095 , 5, xlabel_text, color='#FFC000',
fontweight='bold', rotation=90, fontsize=20)
if i == 0:
ax.text(i - .095 , 93, word_freq_dict[xlabel_text],
color='#FFC000', fontweight='bold', rotation=90,
fontsize=20)
else:
ax.text(i - .095 ,
95-(list(word_freq_dict.values())[0] -
list(word_freq_dict.values())[i]),
word_freq_dict[xlabel_text], color='#FFC000',
fontweight='bold', rotation=90, fontsize=20)
plt.yticks([])
plt.xticks([])
reset_bar_width(ax, 0.5)
plt.savefig('demo8.png', transparent=True)
前 10 个词是爱情、世界、表演、生活、战争、故事、女孩、冒险、男人和美国人。我原以为《爱》、《生活》和《世界》会进入前 10 名,现在它们出现了——“爱”一路领先。
然后我制作了一个信息图:
我用 Microsoft Power Point 把所有的图表和计算累积成一个信息图。我给大纲加了框,在标题和首页文字上使用了“百老汇”字体。
下载: PDF 链接
这是我第一次尝试创建一个信息图,很快就会使用 Tableau。我很想听到一些关于这个创作的反馈,因为这是我的第一次尝试,并希望改进。
存储库链接:
[## royn5618/Medium_Blog_Codes
permalink dissolve GitHub 是超过 5000 万开发人员的家园,他们一起工作来托管和审查代码,管理…
github.com](https://github.com/royn5618/Medium_Blog_Codes/blob/master/Online%20Streaming%20Services%20Comparison.ipynb)
感谢光临。我希望你喜欢阅读这篇博客。
调整中国的冠状病毒技术策略以击败西方的病毒
一个高科技系统,类似于中国的系统,可以有效地抗击新冠肺炎病毒,同时保护个人隐私
编者按: 走向数据科学 是一份以数据科学和机器学习研究为主的中型刊物。我们不是健康专家或流行病学家,本文的观点不应被解释为专业建议。想了解更多关于疫情冠状病毒的信息,可以点击 这里 。
中国政府利用先进技术建立了世界历史上最有效的流行病控制系统。最近几周,中国的疫情疫情得到控制,每天只有 50 例报告。对于一个拥有 14 亿居民的国家来说,这是一个巨大的成功。然而,该系统受到西方世界人士的广泛批评,因为它要求获得有关中国人行踪的私人信息;他们的聊天记录、社交联系、购物记录和其他信息。这些数据随后被存储在中央数据库中,并通过先进的人工智能(AI)算法来对抗病毒的传播。在下面的文章中,我们将提出一个同样有效的类似系统,但它解决了个人的隐私问题。个人的个人数据永远不会离开这个人的设备,但它仍然有助于中央系统识别潜在的热点。
这种系统的唯一要求是人们在他们的移动设备上安装一个应用程序。与中国的系统不同,它不需要分布在全国各地的视频监控摄像头或安装在住宅小区门口的生物扫描仪。人们也不需要进出他们的生活区。
该系统采用移动应用程序的形式,类似于中国现有的微信,并且它还集成了不同的服务。因此本地化、社交媒体、聊天和电子钱包都将可用。然而,这是相似之处的终点。用户的手机存储了所有的个人信息,而不是一个中央服务器。用户将拥有对数据的完全访问权,他可以选择保留或删除数据。此外,该系统将使用两个 AI 组件,一个位于远程,另一个在设备本身上,如下所述。
就电子钱包而言,第一个优势是使用非接触式虚拟卡进行支付,无需兑换真实货币。因此,这种物理交换的缺乏自动减少了病毒的传播。
电子钱包还包括购物时所逛商店的信息。该系统存储商店的位置,并在用户的设备中记录时间。这条信息然后在稍后阶段由定位模块处理。从购买中,本地人工智能可以收集关于个人健康的信息。它可以很容易地推断出,如果购买了某些物品(如药品),那么这个人或他身边的人很可能生病了。然后,人工智能开始与用户聊天,询问他或他身边的人是否有一些症状,并提出一种前进的方式。这些可以包括开始自我隔离,预约拭子或采取任何适当的措施。重要的是选择权仍在用户手中,任何部门都不能共享任何信息。这样的人工智能系统是可能的,因为今天,我们有人工智能引擎,它们可以在移动设备上有效地工作,而不必与服务器通信。一个这样的工具是专门为设备上的机器学习设计的 TensorFlow Lite。
此外,移动医疗的应用也在不断增加。有各种各样的症状追踪应用程序帮助用户做出适当的决定,他们是否需要制度化的护理。它还可以缓解他们可以自己处理的小病的症状。如果用户需要特定的帮助,it 可以直接将他与适当的提供商联系起来。无国界医生组织甚至更进一步,创建了第一个移动分诊应用。卡耐基梅隆大学走得更远,刚刚推出了第一个 COVID 语音检测器,它声称只需通过手机通话就可以测试用户是否携带病毒。当然,这个系统仍然是实验性的,他们不能保证它的准确性。
照片由 henry perks 在 Unsplash 上拍摄
定位模块提供关于人的行踪的精确信息(误差在几米之内)。当然,这些信息只存储在设备上,不会与任何人共享。我们可以通过一种叫做联合学习的新颖人工智能方法,在不泄露用户身份的情况下使用这些信息。该系统的工作原理如下:该设备从服务器下载 AI 模型,并通过从手机上的数据中进行学习,在本地对其进行改进。新模型的概要被创建并发送到云。没有任何个人信息会离开设备,也不可能从发送的更新中提取任何信息,因为它只是一个摘要。通过设备上的人工智能模型,系统知道城市的哪些区域是危险的。如果用户密切接触到有人感染病毒的地方,人工智能会立即提醒他,并让他避开该地区。
通过社交媒体模块,如果用户被感染,他可以很容易地向他的社交朋友圈发送警告消息,并提醒他们,以便他们采取必要的预防措施。
系统还可以自动计算健康代码,该代码可以是:红色、琥珀色或绿色。这种编码是为了帮助用户做出保护他人安全的选择。绿色意味着这个人可以不受限制地自由走动。刚从国外回来或可能到过疫区的人会有黄色代码,系统会建议他们在几天内限制活动。那些可能被感染的人属于红色类别,他们将不得不被隔离。
这种应用的范围不是取代手动系统,而是通知人们并指导他们采取适当的行动。它还通过利用人工智能的力量来接触更多的人,从而缓解了医疗保健系统的压力。最后,没有一个系统是完美的,实现平衡是不容易的。然而,通过将中国系统的好处与大多数西方国家期望的隐私标准结合起来,我们将拥有一个新的强大工具,可以自动拯救无数生命。
这篇文章最初发表在 https://www.businesstoday.com.mt请在下面留下你的想法,如果你喜欢这篇文章,请随时关注我🐦推特,🔗 LinkedIn 或😊脸书。
新冠肺炎如何对我们的经济产生负面影响以及可能的解决方案
towardsdatascience.com](/the-domino-effect-of-the-coronavirus-66fdd72fc9fd)*
Alexei DingliProf 是马耳他大学的 AI 教授。二十多年来,他一直在人工智能领域进行研究和工作,协助不同的公司实施人工智能解决方案。他的工作被国际专家评为世界级,并赢得了几个当地和国际奖项(如欧洲航天局、世界知识产权组织和联合国等)。他出版了几本同行评审的出版物,并且是马耳他的成员。人工智能工作组是由马耳他政府成立的,旨在使马耳他成为世界上顶尖的人工智能国家之一。
特威迪损失函数
长尾右偏数据的损失函数
如今,观察具有右偏分布和长尾的数据并不罕见,例如,来自电子商务网站、广告点击&购买、保险索赔等的数据。
在这种情况下,如果使用其他分布的损失函数(例如,高斯分布的 MSE ),预测模型可能不会被很好地训练。在本文中,我们介绍了一种使用基于 Tweedie 的损失函数的方法,用于在这种长尾右偏数据上训练的模型。
特威迪分布
Tweedie 分布是带有幂参数 p 的指数离差模型(EDM)的特例,其分布均值和方差之间的幂关系如下
其中 μ 和 ϕ 分别是均值和离差参数。
功率参数 p 决定了族内分布的子类。例如, p =1 链接到泊松分布, p =3 链接到逆高斯分布,而本文的重点, p∈ (1,2)链接到复合泊松-伽马分布。
特威迪分布族的普通成员。
假设是复合分布,随机变量 X ~ Tw ( p,μ,ϕ )可以刻画为
x 的概率密度函数(pdf)为
其中 α ( x,ϕ,p )是一个归一化常数,确保这是一个有效的 pdf。
作为损失函数的特威迪
为了将 Tweedie 分布转换为损失函数,我们需要通过模型训练来最大化样本数据的可能性。一种常见的方法是通过负对数似然
如果我们使用分布均值 μ 作为估计量(即预测),那么损失函数变成
履行
给定预定义的功率参数 p (超参数),Tweedie 损失函数可用于各种基于梯度的模型,如梯度提升树、神经网络等。下面给出了一个实现的例子。
import tensorflow as tf
def tweedie_loss_func(p):
def tweedie_loglikelihood(y, y_hat):
loss = - y * tf.pow(y_hat, 1 - p) / (1 - p) + \
tf.pow(y_hat, 2 - p) / (2 - p)
return tf.reduce_mean(loss)return tweedie_loglikelihood
参考
鹤舟先生,杨熠,钱伟。"对于极度不平衡的零膨胀数据的梯迪梯度提升."2019.
阿里特拉·哈尔德,沙里克·穆罕默德,陈坤,迪帕克·戴伊。" Tweedie 复合泊松双广义线性模型中的空间风险估计."2020.
用神经网络生成推文:LSTM 和 GPT-2
我们的递归神经网络能在多大程度上近似政治人物和艺人的推文?
来源: PhotoMIX-Company ,via: pixabay
witter 是数百万人就任何话题发表意见的地方,它也成为名人和他们的粉丝互动的地方。这启发我们探索递归神经网络的局限性,看看它们是否可以用于 Twitter 等社交网络的自动文本生成。作为我们人工神经网络和深度学习课程的最终项目,我们的目标是为 Twitter 上的 10 个受欢迎的帐户生成推文,使用 NLP 技术分析它们,并比较结果。此外,我们还考察了不同的网络,并评估了各种可能性。我们决定观察政治家和艺人,自己建立一个网络,并找到另一个预先训练好的网络来比较结果。
数据收集
我们使用在 Github 上找到的这个库从 10 个公众人物的账户中挖掘推文。出于对群体差异及其对训练我们网络的影响的兴趣,我们选择了五位政治人物和五位艺人:
政治人物:唐纳德·特朗普(@realDonaldTrump),伯尼·桑德斯(@BernieSanders)。伊丽莎白·沃伦(@ewarren)、亚历山大·奥卡西奥-科尔特斯(@AOC)、比尔·盖茨(@比尔·盖茨)
艺人:贾斯汀比伯(@justinbieber)、爱莉安娜·格兰德(@arianagrande)、凯文·哈特(@KevinHart4real)、勒布朗·詹姆斯(@KingJames)、克莉茜·泰根(@chrissyteigen)
对于每个公众人物,我们挖掘了他们最近的 10,000 条推文(请注意,对于少数人物,他们完整的推文历史总计不到 10,000 条,所以我们只是使用了可用的内容)。对于有额外推文的数字,我们收集了另外 1 万条来训练 LSTM 网络。
数据清理:对于我们的训练数据,我们删除了任何只包含“pics.twitter”链接的帖子(在 twitter 上,这些链接显示为照片和视频)。我们还想分析我们的训练数据,并识别推文中的任何模式,这需要额外的清理。对于词频分析,我们删除了标点符号和停用词(由 nltk 库定义)。此外,我们用关键字“http”替换了剩余的链接,以跟踪它们的频率。
通过 NLP 技术评估 Twitter 数据
词频分析
在所有 10 个人中,“http”是使用频率最高的术语之一,这表明他们都相对频繁地在推文中发布链接。因为我们只使用关键字“http”作为链接频率的指标,所以在我们的可视化中没有考虑它。
政治人物:常用词
五位政治人物的前三名都是“人民”这些政治人物深入参与社会事务,并做出影响大多数人的决策。他们的工作围绕着人,所以“人”被他们所有人共同使用是有道理的。
十个最常用的单词象征着每个人的修辞和说话风格。例如,人们已经开始将某些词与特朗普的浮夸风格联系起来——“伟大”、“让美国再次伟大”、“大”和“许多”。列表中还有“假”和“新闻”——特朗普创造的另一个标志性术语。对桑德斯来说,“健康”+“护理”排在第五和第六位。对沃伦来说,“打架”和“打架”都在前十名。
有趣的是,特朗普第四大常用词是“民主党”,即反对党。这说明特朗普在推特上花了多少时间谈论两极化、党派问题。同样,桑德斯和沃伦的十大词汇中都有“特朗普”。
AOC 的前十个单词比前三个更通用。有趣的是,她第三个最常用的词是“谢谢”,这(我们接下来会看到)是艺人推特的典型特征——也许是因为她是迄今为止最年轻、最懂社交媒体的政治人物。虽然比尔·盖茨没有直接参与政治,但他也参与了塑造我们的社会和社区。他的人道主义观点体现在他的前十个词中,包括“世界”、“一”、“帮助”和“进步”。
艺人:常用词
艺人使用社交媒体作为与粉丝互动的平台,他们大量使用“感谢”和“爱”这两个词就是明证。像政治人物一样,他们常用的术语体现了他们的个人风格和方言。哈特是最明显的例子,他创造了两个术语——“dope pic”(如#DopeEpic)和“comedicrockstarshit”——在用法上排名第六和第八。一般来说,艺人的词汇云提供的洞察力不如政治人物,因为他们经常使用 Twitter 进行宣传和简短的粉丝互动。然而,政治人物使用 Twitter 来传达关于他们的立场、政策、时事等更复杂的信息。
政治人物与艺人:平均推文长度
我们发现,平均而言,艺人的推文长度大约是政治人物推文长度的一半。我们可以看到政治人物的训练数据和艺人的训练数据之间的差异如何影响我们的网络生成的推文。随着训练的推文越来越长,我们的网络为政治人物生成的推文的质量和相似度也越来越高。
情绪分析
我们使用 VADER(用于情感推理的效价感知词典)工具对训练数据进行情感分析。我们采用复合得分——一种计算所有词汇评分总和的指标,这些词汇评分在-1(最极端的负面)和+1(最极端的正面)之间标准化——来比较各组的情绪。
与政治人物相比,艺人的推文数量远高于 0.0(中性)。从柱状图来看,艺人有更多的轻尾分布。许多艺人使用社交媒体平台进行推广(中性)和粉丝互动(积极)——最明显的是比伯和格兰德。詹姆斯显示了大量积极情绪的推文,这可能与他的激励信息有关。Teigen 在所有艺人中有更多负面情绪的推文,这可能归因于她直言不讳的本性。
另一方面,政治人物箱线图的 IQR 通常比艺人的宽,即中间 50%的数据落在更大的范围内。对于政治人物来说,可能需要通过表达批评(消极情绪)或争取支持(积极情绪)来吸引公众。
川普拥有最大的 IQR,从-0.50 到 0.75。条形图表示在他的推文中显示了双峰分布情绪。情感模式证实了他对戏剧和表演的天赋;他倾向于强烈批评或高度赞扬。沃伦和盖茨拥有最偏右的分布,这证明了他们高度乐观和积极推动社会变革的声誉。
为推文生成选择神经网络
我们希望创建我们自己的 LSTM 网络,此外还有一个最新的最先进的网络,以便比较结果并了解它们如何工作的特点。我们还考虑开发一个用于文本生成的 GAN 网络,因为我们试图生成看起来像特定用户的推文的推文,所以我们创建了一个鉴别器,并做了一个反向投影,帮助生成器生成更好的输出,看起来像我们的初始训练数据会产生更好的结果。以下是我们发现的每个网络(Transformer XL、CTRL 和 GPT-2)的利与弊的简要概述,以及我们最终选择 LSTM 和 GPT-2 的原因。
LSTM
LSTM(长短期记忆)是一种递归神经网络(RNN)。我们选择创建一个 LSTM 模型来为 10 位政治家和艺人生成新的推文,因为这个特定的模型学习并掌握风格、语言和语法,因为 LSTM 能够检测和学习长期的依赖性。在学习输入文本的序列时,模型能够生成新的文本。
LSTMs 使用一种可以被描述为循环效应的学习过程,这意味着网络解释输入并产生输出。该输出及其信息随后被传递到网络中的下一个步骤。这是很重要的,因为它允许模型拾取文本中的模式,以便生成与所讨论的文本风格相似的更好的输出。
变压器-XL
我们考虑实施 Transformer-XL 网络的主要原因是它的效率。与其他广泛传播的语言模型相比,Transformer-XL 不能捕获文本中的长期依赖关系,它能够识别单词级和字符级的上下文连接。它通过将变压器网络的概念与相对位置编码相结合来实现这一目标。传统的转换器能够捕获固定长度的片段的上下文。因此,上下文变得支离破碎。相对位置编码有助于 Transformer-XL(代表“超长”)在更长的段中捕获上下文,使模型在生成文本时更有效。
由于我们希望以特定艺人和政治家的风格生成推文,我们希望网络能够了解不同推文之间的依赖关系,而不仅仅是一个推文内部的依赖关系。然而,由于 Transformer-XL 是不久前开发的,即使它的代码是开源的,我们也无法找到足够的代码遍历来帮助我们实现该模型。关于该模型的更多信息可以在这些文章中找到: Transformer-XL:释放注意力模型的潜力作者谷歌人工智能是该模型的作者Transformer-XL 的简单介绍— dair.ai 来自 Medium 上的一个博客。
开始
当我们考虑使用 GAN 生成文本时,我们想到了相关讲座中提到的由 GAN 生成的图像示例。由于结果令人印象深刻,我们想知道尝试将相同的概念用于文本生成是否会很有趣。然而,随着我们开始做更多的研究,我们发现使用 GAN 进行文本生成是非常有问题的,因为如果我们使用 RNN 进行文本生成,我们将面临 backprop 的问题,因为 RNN“挑选”下一个单词的操作是不可微的。因为有办法解决这个问题,所以我们寻找了一些已经测试过的用于文本生成的 GANs 的例子。我们在 GitHub 上找到了几个例子,包括 LeakGAN 和 SeqGAN ,但我们没有找到证据表明这些网络会比常规的 LSTM 网络或一些先进的网络如 GPT-2 或 CTRL 更好。在进一步阅读下,你可以看看我们发现的一些有趣的阅读,关于 gan 在文本生成中的表现。
计算机的 Ctrl 按键(控制键)
CTRL 是 Salesforce 在 2019 年展示的大规模文本生成网络。它代表条件转换器语言模型。创建这个模型是为了让用户对生成的文本有更多的控制,这是其他大规模模型通常所缺乏的。这个模型是开源的,可以在 GitHub 上获得。在我们研究的所有模型中,CTRL 拥有最多由创建者提供的文档。然而,使用 CTRL 主要是为了从链接、文本等的提示中产生故事。因为我们的目标是创建推文,而不是故事,所以我们决定继续使用 GPT-2,尽管用用户资料的链接来测试 CTRL 会很有趣。这是关于 CTRL CTRL:可控生成的条件转换器语言模型的原始文章,作者是 Nitish Shirish Keskar、Bryan McCann、Lav R. Varshney、Xiong、Salesforce Research 的 Richard Socher 和的 GitHub repo 并附有文档。
GPT-2
GPT-2 是 Open AI 在 2019 年发布的最新文本生成网络。它基于 transformer 网络,并在来自互联网的 40GB 文本上进行训练。因为创作者担心使用这种模型产生假新闻的可能性,他们决定发布一个小得多的模型。这个模型生成的文本很容易被误认为是人类的,而且语法和拼写几乎完美无缺。在我们观察的所有模型中,这一个是研究人员采用最多的,因此有更多关于其使用的说明和解释。对于我们的文本生成,我们使用了 Max Woolf GPT-2 Simple 的模型,并使用了他各自的 Colab 笔记本来检查模型。第一次尝试的结果令人印象深刻,所以我们决定停止这一次,因为它有最佳的训练时间和最佳的结果质量。关于该模型的更多信息可以在 Open AI 的文章更好的语言模型及其含义中找到。
建立网络和发微博
LSTM
为了使用 LSTM 网络生成推文,来自 CSV 的 10,000 条推文被转移到熊猫文件中。推文中存在差异,因此我们尽最大努力清理数据,同时不减少用于训练模型的数据量。正因为如此,我们决定尝试训练模型来学习链接。我们只删除了长度小于 60 个字符的推文。通过删除低于一定长度的推文,它会删除只有一个单词的推文以及 CSV 文件中的空推文。接下来,推文被分成等长的序列,放入一个叫做句子的列表中。这些句子将用作模型的训练示例。
矢量化是下一步。在这里,我们将推文平均分成 x 和 y 两部分。 x 是一个 3D 矩阵,具有句子总数、步长(40)和唯一字符数的形状。 y 是一个 2D 矩阵,它包含句子的总长度和唯一的字符,这个向量的目的是检索x给出的句子后面的下一个字符。现在,数据已经收集完毕,准备用于训练,是时候构建 LSTM 模型了。
在花了几天时间试图找到合适且高效的完美模型后,我们偶然发现了以下模型。特别是这个模型,在我们训练的 10 个不同的模型中表现最好。该模型与其他模型的不同之处在于,额外的神经元、激活函数、SELU 和常规批量标准化适合于所使用的训练数据的大小。
在模型的训练期间,每个历元花费大约 30 分钟,并且在 10 个历元之后,模型停止学习,每个数据集的损失大约为 1.5。在训练期间,模型基于概率分布输出下一个字符。这就是所谓的多样性。多样性是一个决定生成的句子有多随机的值。出于训练目的,我们将多样性设置为 0.2、0.5、0.7、1.0 和 1.2,以便直观显示哪种多样性生成了最有意义的推文。
最后一步是为用户生成新的推文。generate_tweets 函数接受一个随机种子,它是来自 tweet 列表的一个随机 tweet,以及一个集合多样性。我们选择了 0.7 的多样性,因为与其他相比,它表达了最容易理解的推文。在收到一个随机种子和一个多样性值后,该函数将种子长度减少到 40 个字符。这样做是因为使用一条已经公式化的推文来创建另一条推文是良性的,因为一旦一条新的推文生成,它将超过 twitter 上允许的最大字符长度。
**
在将句子设置为随机种子的前 40 个字符后,我们创建了由生成的变量,该变量将存储生成的 tweet 的开头、随机种子的前 40 个字符以及由模型预测提供的 120 个其他生成的字符。生成 2000 条推文所需的时间从 45 分钟到 2 小时不等。下面,我为下面的四个人提供了 2000 条推文中的一条:
伯尼·桑德斯:
2018 年你可能错过的好消息。感谢世界的承诺我们已经完成的事情考虑:【http://b-gat.es/2vwmyaw】pic.twitter.com/eyfhwch8gpngw
比尔·盖茨:
老师们正在做着不可思议的工作来保持世界上最贫穷的:【http://b-gat.es/1u6yecf】T4pic.twitter.com/h4g6vdscdhoamgetpiwel108heepsang it:http://b-gat.es/2dp
凯文·哈特:
我有更多突发新闻抽搐!现在就去电影院吧!!!!# hustlehart # hustlehart #创造历史#喜剧明星…#想想电影中的阿曼斯顿
贾斯汀比伯:
我的专辑出来了,但我大哥的@ jesicnolker @ showmybirthdi @ americcaem @ dankan ter 和@ its beliebers @ spendwer @ changelhttps://twitter.com/smazurgop/status也出来了
结果
为了找到一个适合将准确率提高到 40%以上的模型,花了几天时间。就这个特定模型的准确性而言,政治家伯尼·桑德斯和比尔盖茨在他们的推文中分享了相同的推文风格和语法,用于训练该模型。这种一致性提供了 62%及更高的准确度结果。因为艺人经常发微博,而且他们的微博从一个话题到另一个话题,这影响了他们训练的准确性。这使得该模型能够为伯尼·桑德斯和比尔盖茨生成更好的推文。
总的来说,还有一些可以改进的地方。首先,我们可以从推文中排除链接,但问题是,因为所有被选中的人都使用大量链接来推广自己。这将导致数据集的大小大幅下降。但是,通过收集每个用户大约五万条推文,它会给模型更多的句子来训练和学习。然而,这将需要几周的时间来实现和产生每个人。
GPT-2 简单
为了用 GPT-2 生成推文,我们使用了马克斯·伍尔夫的教程如何用 GPT-2 制作定制的人工智能生成的文本。至于推文生成的这一部分,我们使用了无法定制的网络,我们可以试验的主要内容是学习率和时代数量。当 eta 设置为 0.0001,epochs 的数量为 1000 时,生成的 tweets 的质量最好。我们还能够在 GPT-2 模型的尺寸版本之间进行选择——124 米、355 米和 774 米模型。我们决定运行最小的一个,因为我们需要在 1000 个时期内训练模型 10 次,然后生成 20000 条推文(每个用户 2000 条),所以时间是我们关心的问题。我们使用 Google Colab notebook 来运行代码,以使用 Google 的 GPU 并使其更快,但即使是最小的模型也需要大约 1 小时来为每个用户进行训练,大约 20 分钟来产生推文。由于 Google Colab 会频繁断开运行时,我们决定不冒险运行较重的模型,所以我们可以在截止日期前生成推文。即使使用最小的模型,推文的质量也令人印象深刻。
我们注意到艺人和政客之间的推文质量有很大差异。总的来说,政治家的推文要长得多,有更多的内容,因此,对于网络来说,学习起来容易得多,因为当提供 10000 条推文时,它会得到更多的单词。与此同时,艺人们会有很多宣传片和短信,它们并不是很独特,比如“爱你”等。因此,当网络处理艺人的推文时,结果质量较低,包含更多只有空格的空推文。当我们标准化推文的长度时,我们用空格增加了它们,所以推文越短,空格占书面文本的比例就越高。
GPT-2 的制造商还提到,网络的一个缺点是重复。我们看到,在每个用户的大量推文中,网络会停在某个词上,并生成 10 次或更多次。这样的推文的一个例子是为贾斯汀比伯生成的:“XXL 回来了。你知道该怎么做。@ scooter Braun @ scrappy @ luda cris @ luda cris @ luda cris @ luda cris @ luda cris @ luda cris @ luda cris @ luda cris @ luda cris @ luda cris @ luda cris @ luda cris @ luda cris”。
我们看到的重复的另一个问题是,当网络生成同一条推文的几个变体,只是改变时间,链接的结尾,结尾的几个词,等等。例如,网络为盖茨生成的推文改变了“更新”时间:
更新,上午 19:45:这篇文章已经更新,澄清我最近得到的脊髓灰质炎疫苗不是“脊髓灰质炎疫苗”确实是。
更新,2:58:这篇文章已经更新,澄清我最近得到的脊髓灰质炎疫苗不是“脊髓灰质炎疫苗”确实是。
更新,凌晨 3:58:这篇文章已经更新,澄清我最近得到的脊髓灰质炎疫苗不是“脊髓灰质炎疫苗”确实是。
更新,凌晨 4:55:这篇文章已经更新,澄清我最近得到的脊髓灰质炎疫苗不是“脊髓灰质炎疫苗”确实是。
更新,上午 5:45:这篇文章已经更新,澄清我最近得到的脊髓灰质炎疫苗不是“脊髓灰质炎疫苗”确实是。
更新,上午 6:30:这篇文章已经更新,澄清我最近得到的脊髓灰质炎疫苗不是“脊髓灰质炎疫苗”确实是。
更新,上午 7:45:这篇文章已经更新,澄清我最近得到的脊髓灰质炎疫苗不是“脊髓灰质炎疫苗”确实是。
另一个例子是链接结尾的 10 种变化:
这个世界比以往任何时候都好,但我很惊讶很少有人知道这一点。https://b-gat.es/2BZcNFk
这个世界比以往任何时候都好,但我很惊讶很少有人知道这一点。https://b-gat.es/2E3zEMw
这个世界比以往任何时候都好,但我很惊讶很少有人知道这一点。https://b-gat.es/2EJzX1V
这个世界比以往任何时候都好,但我很惊讶很少有人知道这一点。https://b-gat.es/2Ft7tBS
这个世界比以往任何时候都好,但我很惊讶很少有人知道这一点
这个世界比以往任何时候都好,但我很惊讶很少有人知道这一点。https://b-gat.es/2HfkiQi
这个世界比以往任何时候都更好,但我很惊讶很少有人知道这一点。https://b-gat.es/2I0xWEWT
这个世界比以往任何时候都好,但我很惊讶很少有人知道这一点。https://b-gat.es/2I4m0JT
这个世界比以往任何时候都更好,但我很惊讶很少有人知道这一点。https://b-gat.es/2I9cVMr
这个世界比以往任何时候都更好,但我很惊讶很少有人知道这一点。https://b-gat.es/2JsNJoh
还有,当推文被拉出来的时候,一些像撇号这样的符号还没有读好,所以在生成的推文中,我们可以看到一些奇怪的符号或者符号的组合,而不是撇号,在句子的结尾等等。下面是一些用 those:"iрір‚в„ўm”代替“我是”、“iвђ™m”、“рвђрёр‡рёпїѕ”等的例子。
GPT-2 文本生成的积极方面是,该网络能够抓住所有用户谈论的主要话题,包括他们的签名标签、他们共享链接的网站、他们从事的项目和个人谈话风格。例如,对于特朗普的虚假推文,该网络发现特朗普经常从福克斯新闻频道转发,而亚历山德拉·奥卡西奥-科尔特斯生成的推文来自《纽约时报》。比伯生成的推文中有很多关于新歌和专辑的公告,而桑德斯的推文中有很多关于全民医疗保健的内容。盖茨在推特上发表了很多关于经济发展、抗击小儿麻痹症、疟疾等文章的评论,还提到了梅林达·盖茨的书和评论。
以下是我们制作的一些最佳推文:
款待者
贾斯汀比伯:
你可以发送短信 SUMMER 至 22837 预订#AsLongAsYouLoveMe,当我们推出独家原声专辑时,应用程序会通知你。#AsLongAsYouLoveMe 和#LoveYourself 将出现在 ITUNES 上,也将进入我们的前十名。#BIEBERBLAST
爱莉安娜·格兰德:
今晚是#危险女人之旅的最后一晚,我们很荣幸能在巴克莱中心表演。非常感谢你们今晚所有的爱、能量、兴奋和爱。https://www.instagram.com/p/BRiT3YZrH6R/
凯文·哈特:
我刚刚在我的“不负责任的旅行”中增加了另一个节目…我等不及让你们看这部电影了!!!https://Twitter . com/originalcinema/status/924093577757350208
勒布朗·詹姆斯:
NBA 季后赛终于来了!我很期待今晚的比赛,我也会期待下一场比赛。
克莉茜·泰根:
《向前看》全文明天出!在我的简历中预订!!#渴望系列#克里斯·库#克里斯·库#克里斯·布利斯·pic.twitter.com/aI1oIOyCEI
政治家
亚历山德拉·奥卡西奥·科尔特斯:
14 年来,国会和共和党一直致力于解散患者保护与平价医疗法案。他们不能在不废除法律的情况下废除 ACA,这意味着将保险市场减半。我们需要用更多的东西来代替 ACA。
比尔·盖茨:
许多人认为非洲是一个饥饿的大陆。它实际上是世界上最大的经济体之一。这里有 5 个惊人的统计数据:【http://b-gat.es/1o5YKV7】pic.twitter.com/wZ8EFmYJFl
伯尼·桑德斯:
几周前,特朗普总统签署了一项行政命令,削减对某些项目和活动的资金,包括计划生育。特朗普的行动必须结束并立即停止对计划生育的所有资助和乳腺癌筛查的所有供应。https://Twitter . com/realDonaldTrump/status/11668362477942539
唐纳德·特朗普:
你认为管理我们国家和经济的人会允许这个荒谬的弹劾骗局继续下去吗?我们的经济是有史以来最好的,民主党正在追杀你们!
伊丽莎白·沃伦:
一年前的今天,奥巴马总统签署了一项行政命令,强制关闭私人监狱。今天,在我写这篇文章的时候,46 个州已经实施了他们自己版本的计划,国会也签署了,这要感谢@KamalaHarris 和@ AyannaPressley。
结果
总的来说,GPT-2 Simple 在为我们选择的用户生成推文方面做得很好。文本是相同的风格,相同的主题,包括每个用户特有的细节。我们还看到,结果高度依赖于输入数据的质量。对于几乎所有艺人来说,与政客相比,网络产生的推文质量要低得多,重复和空洞的推文也多得多。对于政治家来说,由于网络有更多的数据可以处理,因此产生的推文有意义,错误少得多,并且对每个用户来说更容易识别。总而言之,GTP-2 是一个用相对少的数据快速生成高质量文本的好方法。对于那些一开始我们无法获得所有 10000 条推文的用户,即使有 5000 条推文,结果也令人印象深刻。根据我们使用的 Max Woolf 的教程,几乎任何人都可以使用这个模型快速生成高质量的文本。
比较实际的推文和生成的推文
LSTM 只为四位公众人物(比伯、哈特、盖茨和桑德斯)发布了推文,而 GPT 2 号为所有十位公众人物发布了推文。因此,我们首先对所有十个人的 GPT-2 与训练数据进行了分析,然后我们将两个网络与训练数据进行了比较。
GPT-2 与实际推文
政治人物生成的推文的十个最常见的词与训练数据中的 6-8 个匹配,而艺人的匹配数量是一半(3-4 个)。
对于大多数公众人物来说,GPT-2 网络产生的推文的链接频率类似于训练数据的链接频率。在新 GPT 协议生成的 twitter 数据中,“http”是 10 个最常见的术语之一。我们可以通过比较爱莉安娜·格兰德常用词的分布来观察链接用法的差异:
比较艺人的实际推文和生成的推文的词云,我们可以看到网络仍然生成与个人的一般语气相匹配的词。作为一个例子,这里有一个爱莉安娜·格兰德的词云的对比:
我们还绘制了训练数据和 GPT-2 并排生成的推文的推文长度和情绪。有趣的是,GPT-2 网络持续生成的推文长度是它被训练的推文长度的一半,甚至更少。此外,他们的情感得分远比训练数据更加中立。我们可以从每个人的情绪得分的轻尾分布中看到,生成的推文中的情绪变化要小得多,我们将在下一节回到这一点。
**
比较 LSTM 和 GPT-2 生成的推文
当谈到推文长度时,LSTM 网络的表现类似于 GPT-2 网络。一个例外是沃伦,LSTM 网络实际上平均生成了略长的推文。
**
与 GPT-2 网络相比,LSTM 产生了更积极的情绪得分,更接近实际的推特数据。然而,正如我们在桑德斯身上看到的那样,生成的推文和实际推文之间的情感分布仍有明显差异。对于两个网络,生成推文的分布都是非常轻尾的,分数都集中在 0.0 左右(中性)。显然,网络可以令人信服地模仿推文风格,但要获得正确的情感需要更多的细微差别。更短的推文长度和生成的推文中更多的链接的组合可能有助于更高的中性情绪。
结论
总的来说,我们在这个项目中学到了很多。我们的两个网络都为政治家生成了质量更好、相似度更高的推文。这可能归因于这两个群体在推特上的不同方式。政治家倾向于发布更长、更复杂的信息来反映他们的平台,而大多数艺人使用 Twitter 来发布宣传片并与粉丝互动。
关于我们的网络,我们的主要结论是,GPT-2 简单是更容易和更快地使用比 LSTM 网络。它产生了相当不错的推文,看起来很像真的。作为这个项目的延伸,将我们使用的模型的结果与更大版本的 GPT-2 进行比较将会很有趣。此外,我们观察到生成文本的质量与训练网络的数据质量直接相关。因此,如果你想产生更好的结果,花更多的时间清理和调整你的数据。
从我们的网络和生成的推文中,我们看到了 OpenAI 对发布完全训练有素的网络的担忧的证据——如果创建看起来几乎与真实政治家的推文完全一样的推文那么容易,那么滥用这种模型生成假新闻的威胁就令人担忧。然而,我们注意到,我们的网络在模仿政治人物和艺人的推特上的各种情绪方面甚至都不接近。也许这些网络还没有发现人类说话的模式。
参考
* [## Transformer-XL:释放注意力模型的潜力
为了正确理解一篇文章,有时需要参考几千年前出现的一个词或一个句子…
ai.googleblog.com](https://ai.googleblog.com/2019/01/transformer-xl-unleashing-potential-of.html) [## Transformer-XL 简介
一种支持长期依赖的注意力语言建模新技术概述。
medium.com](https://medium.com/dair-ai/a-light-introduction-to-transformer-xl-be5737feb13) [## CTRL:用于可控生成的条件转换器语言模型
大规模语言模型显示了有前途的文本生成能力,但是用户不能容易地控制特定的…
arxiv.org](https://arxiv.org/abs/1909.05858) [## 销售力量/控制
作者:Nitish Shirish Keskar,Bryan McCann,Lav Varshney,Xiong,和 Richard Socher
github.com](https://github.com/salesforce/ctrl#generations) [## 更好的语言模型及其含义
我们已经训练了一个大规模的无监督语言模型,它可以生成连贯的文本段落,实现…
openai.com](https://openai.com/blog/better-language-models/) [## Twitter 数据挖掘:挖掘没有 API 键的 Twitter 数据。
使用一行命令获取旧的 Twitter 大数据进行分析。
medium.com](https://medium.com/@IrekponorVictor/twitter-data-mining-mining-twitter-data-without-api-keys-a2a2bd3f11c)
进一步阅读
由于语义的模糊性和长文本建模的困难,生成高质量的文本是一个具有挑战性的问题
www.semanticscholar.org](https://www.semanticscholar.org/paper/Evaluating-Generative-Models-for-Text-Generation-Kawthekar/0a4e66bd2ba65a53b11684250f2adc76eb768222) [## 使用知识蒸馏和生成对抗网络的文本生成…
文本生成在许多自然语言处理应用中有着特殊的意义,如机器翻译、语言建模和语义分析等
www.semanticscholar.org](https://www.semanticscholar.org/paper/TextKD-GAN%3A-Text-Generation-Using-Knowledge-and-Haidar-Rezagholizadeh/abcbfa04b14ee6cc76afe8c5e504daf815d14fa2) [## 文本生成的生成性对抗网络——第一部分
用于文本生成的 GANs 的问题以及解决这些问题的方法
becominghuman.ai](https://becominghuman.ai/generative-adversarial-networks-for-text-generation-part-1-2b886c8cab10) [## 文本生成的生成性对抗网络第 2 部分:RL
使用强化学习解决文本中的不可微性问题。
becominghuman.ai](https://becominghuman.ai/generative-adversarial-networks-for-text-generation-part-2-rl-1bc18a2b8c60)*
推文,使用 Q 块的表情符号情感分析
自然语言处理
我第一次尝试租 GPU 加速软件。在我的回购中可获得全部代码。
在下面的文章中,我将租用 Q Blocks GPU 来运行一个计算要求苛刻的 AI 模型。我将运行一个名为 DeepMoji 的深度学习模型,给定一个句子,该模型将估计出可以描述该句子的前 n 种情绪(单击非链接进行尝试)。我将租用 GPU 的平台仍然处于早期访问阶段,所以你可以在购买之前试用它(这个平台为你提供 20 小时的免费 GPU,一个很好的开始),看看你是否适应它。
租 Q 块 GPU
为了进行这个实验,我想从替代提供商而不是亚马逊 AWS 租赁 GPU,我被告知这很贵。,只有在运行巨大的模型时才变得方便。
到目前为止,我发现一个很好的提议尝试 Q 块 GPU。GPU 不是用使用量买的,是用时间买的。这项服务每小时只需 0.05 美元。是一个非常合理的价格,你将基本上支付相同的 CPU 成本的 GPU。Q Blocks 使用的分布式计算技术允许该提供商在不降低质量的情况下保持低价。
买 GPU 有必要吗?
如果你是初学者,肯定不是。常见的在线编译器,如 Google Colab 或 Kaggle,提供了免费(但不强大)的计算能力。如果您像每个初学者一样处理小数据集,它不需要很高的计算能力,您可以使用免费版本。
相反,如果你需要调整你的模型(就像每个专业人士需要的那样),你将不得不在电脑前等待无数个小时,等待可能会让你失望的结果。建立更具挑战性的模型的前一步是增加你的计算能力。
例如,在不使用 GPU 的情况下运行这个算法将需要我几个小时才能完成。我的实验在于更快地完成这个项目。
如何高效使用 QBlocks:不浪费 GPU!
我将使用此服务的截图来简化事情。然而,我假设每个供应商都根据你的需求提供不同的服务。因为我不需要过多的计算能力,所以我可以每小时使用 100 个块,相当于每小时 0.10 美元。
如果这是你第一次租用 GPU,你可能会感到沮丧。当你启动模型时,它将开始消耗。因此,至关重要的是,你知道你在做什么,你不要在服务提供的笔记本上做实验。如果有错误,你需要在付费的工作簿中调试你的代码,你的时间将会是昂贵的。当你意识到调试时间花费了你多少钱时,你可能会转向另一家 GPU 提供商。
-
- *确保您在另一个工作簿中有一个工作模型的副本。您可以简单地导入并运行该副本,而不会浪费宝贵的时间。
Q Blocks 与在线 Jupyter 笔记本有关联。例如,如果你在 Google Colab 中开始你的模型,可能会有一些问题。访问文件或下载库的语法略有不同,当您的笔记本正在运行时,您可能会浪费时间在网上搜索解决方案。因为我在制作这个模型时遇到了类似的问题,所以我将详细说明如何克服解决方案。
因此,在免费 Jupyter 工作簿中编写您的模型之前,如果它可以工作,那么在您使用的平台上导入该模型(在我的例子中是 Q 块)以节省时间。
提供商可能会启动一个加载了 GPU 的空笔记本。我们可以开始编码了…
导入数据集
您要做的第一件事是导入您可以访问的数据集。每个笔记本都有一个上传文档的部分,我稍后会创建一个到那个文档的连接,用熊猫导入它。
火炬装置
很可能,在尝试这个实验时,最困难的事情是安装 torchMoji。我将把这个装置分成两部分。首先,我将安装运行 torchMoji 所需的库:
!pip3 install torch==1.0.1 -f [https://download.pytorch.org/whl/cpu/stable](https://download.pytorch.org/whl/cpu/stable)
!git clone [https://github.com/huggingface/torchMoji](https://github.com/huggingface/torchMoji)
import os
os.chdir('torchMoji')
!pip3 install -e .
#if you restart the package, the notebook risks to crash on a loop
#if you managed to be curious and to make it stuck, just clic on RunTime, Factory Reset Runtime
#I did not restart and worked fine#se questo funziona, poi crasha in future linee di codice, anche se chiudiamo e riapriamo dovrebbe essere a posto per 12 ore
第二步,我将下载并安装权重,这将允许神经网络基于任何文本选择表情符号。
-
- *非常小心,Jupyter Notebook 中有一个错误(我不知道我是否可以将其归类为错误),它阻止您输入是或否之类的答案。要解决此问题并防止您的 GPU 在循环中迭代,从而消耗您的可用处理能力,请使用以下代码行解决 Jupyter Notebook 中的问题。
#!python3 scripts/download_weights.py
! yes | python3 scripts/download_weights.py
在传统的笔记本中,你应该被允许在选项是和否之间进行选择。然而,Jupyter Notebook 没有为您提供任何输入选择的可能性。我使用上面的代码绕过了它,并立即声明了 yes 选择。
定义转换函数
我现在将创建一个函数,作为输入,它将接受一个文本字符串,并根据我们想要提取的情绪数量,输出相应的表情符号。
#si connette a DeepMoji per una request, non posso modificare i parametri, credo
!python3 examples/text_emojize.py --text f" {Stay safe from the virus} "!pip3 install --upgrade numpy!pip install numpy==1.18
!pip install scipy==1.1.0
!pip install scikit-learn==0.21.3import numpy as np
import emoji, json
from torchmoji.global_variables import PRETRAINED_PATH, VOCAB_PATH
from torchmoji.sentence_tokenizer import SentenceTokenizer
from torchmoji.model_def import torchmoji_emojis
EMOJIS = ":joy: :unamused: :weary: :sob: :heart_eyes: :pensive: :ok_hand: :blush: :heart: :smirk: :grin: :notes: :flushed: :100: :sleeping: :relieved: :relaxed: :raised_hands: :two_hearts: :expressionless: :sweat_smile: :pray: :confused: :kissing_heart: :heartbeat: :neutral_face: :information_desk_person: :disappointed: :see_no_evil: :tired_face: :v: :sunglasses: :rage: :thumbsup: :cry: :sleepy: :yum: :triumph: :hand: :mask: :clap: :eyes: :gun: :persevere: :smiling_imp: :sweat: :broken_heart: :yellow_heart: :musical_note: :speak_no_evil: :wink: :skull: :confounded: :smile: :stuck_out_tongue_winking_eye: :angry: :no_good: :muscle: :facepunch: :purple_heart: :sparkling_heart: :blue_heart: :grimacing: :sparkles:".split(' ')
model = torchmoji_emojis(PRETRAINED_PATH)
with open(VOCAB_PATH, 'r') as f:
vocabulary = json.load(f)
st = SentenceTokenizer(vocabulary, 30)def deepmojify(sentence, top_n=5, return_emoji=True, return_prob=False):
#converte lista probabilità in emoticon più probabili
def top_elements(array, k):
ind = np.argpartition(array, -k)[-k:]
return ind[np.argsort(array[ind])][::-1]tokenized, _, _ = st.tokenize_sentences([sentence])
#print(tokenized)
#lista di probabilità
prob = model(tokenized)[0]
#se ci sono errori parte da qui: too many values to unpack (expected 2), non riesce a trovare prob
#trova le n emoticono più alte
emoji_ids = top_elements(prob, top_n)#converte questi numeri in emoticons
emojis = map(lambda x: EMOJIS[x], emoji_ids)
if return_emoji == False and return_prob == False:
return None
elif return_emoji == True and return_prob == False:
return emoji.emojize(f"{sentence} {' '.join(emojis)}", use_aliases=True)
elif return_emoji == True and return_prob == True:
return emoji.emojize(f"{sentence} {' '.join(emojis)}", use_aliases=True), prob
elif return_emoji == False and return_prob == True:
return prob
deepmojify('ciao, come stai?', top_n=3, return_emoji=True, return_prob=False)
输入字符串的输出如下:
'ciao, come stai? 💓 💛 ❤'
定义我们的主要功能
我现在将创建一个函数,将一个列表转换为一个数据集,其估计的表情符号位于不同的列中。正如你在上面的字符串中看到的,这个函数将表情符号和输入字符串连接在一起,我将把它们分开,分别放在数据集的不同列中。
def emoji_dataset(list1, n_emoji=3, only_prob=False):
emoji_list = [[x] for x in list1]for _ in range(len(list1)):
for n_emo in range(1, n_emoji+1):
print(_)
if only_prob == False:
emoji_list[_].append(deepmojify(list1[_], top_n=n_emoji, return_emoji=True, return_prob=False)[2*-n_emo+1])
else:
emoji_list[_].append(deepmojify(list1[_], top_n=1, return_emoji=False, return_prob=True))emoji_list = pd.DataFrame(emoji_list)
return emoji_listdf_ = emoji_dataset(list1, 3)
df_
下载数据集
现在我已经准备好了,我可以运行整个项目了。我会下载数据集,快速预处理,然后启动算法。
import pandas as pd
X = pd.read_csv(open('tweets.csv'))
如果你还没有注意到,我正在使用 read_csv 里面的函数 open 。如果没有这个函数,代码将返回一个错误。这种行为是朱庇特笔记本所特有的。
X.pop('Unnamed: 0')
X = pd.DataFrame(X)
X.columns = ['tweets']
Xdf = X.copy()
df
作为最后一步,我将把 25000 条推文的列表变成一个列表。我可以使用这个列表作为主函数的输入。
list1 = df['tweets'].to_list()
我终于可以开始模型了。因此,我将拥有 25000 条带有相应情绪的推文列表。
list1 = list1[0:25000]
df_.to_csv('25k_emotions.csv')
df_
输出的示例
当您的模型设置好后,不要忘记删除笔记本以保存您剩余的学分。
结论
该模型的执行速度相对较快。与 GPU 相比,免费的云编译器可以达到快 10 倍的速度。在 Google Colab 上运行这个算法需要 1 个多小时,相比之下,我使用 Q 块大约需要 10 分钟才能达到相同的结果。如果你打算租用更强大的 GPU,根据你的需求,这个数字只会增加。
云计算很快将成为新的规范。有了区块链和像素流技术等革命性创新,人们将不再需要购买 GPU 硬件。像 Q Blocks 这样使用对等计算的提供商,通过使计算能力更容易获得,加速创新,做出了贡献。