TowardsDataScience 博客中文翻译 2021(三百零九)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

使用 CLIP 和 StyleGAN 从提示生成图像

原文:https://towardsdatascience.com/generating-images-from-prompts-using-clip-and-stylegan-1f9ed495ddda?source=collection_archive---------7-----------------------

读完这篇文章你会知道…

  • CLIP 如何工作一目了然。
  • StyleGAN 工作原理一览。
  • …如何将它们组合起来,根据提示生成面。

你可以在这里找到这篇文章中使用的代码。

夹子

对比语言——图像预训练 *(剪辑)——*呈现于从自然语言监督中学习可转移视觉模型——由 OpenAI 于 2021 年 1 月出版。他们的方法提出利用自然语言来提高图像分类任务的深度学习模型的通用性和鲁棒性。他们能够在零射击设置的情况下,在多个基准测试中产生最先进的性能,这确实令人印象深刻。

CLIP 背后的主要思想是预先训练一个神经语言模型和一个图像分类模型,联合使用从互联网上提取的大量图像数据及其各自的标题。在下图中,“文本编码器”代表语言模型,“图像编码器”代表图像分类模型。

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

图片来自 OpenAI 的原博客

他们的目标是构建一个矩阵,其中每个值代表每个提示图像对之间的相似性得分——在图像中计算为 I * T——并使用它来训练语言和视觉模型,以便它们最大化对应于正确对的位置的值,即图像中的对角线值。例如,如果位置 0 处的文本是“pepper the aussie pup ”,而位置 0 处的图像表示该特定内容,则 CLIP 将训练这两个模型来创建最大化其相似性的表示。

一旦该预训练过程完成,他们可以使用预训练的视觉模型来生成任何给定输入图像的表示,并将其与使用语言模型从几个提示获得的几个文本嵌入进行比较。具有最大相似性值的文本表示将被选为更好地表示图像内容的文本表示。使用这种技术,您可以使用 ImageNet 的一千个类别作为句子,并在零镜头设置中解决分类任务。

以下是模型如何在给定这组提示的情况下成功分类图像的一些示例。

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

图片来自 OpenAI 的原博客

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

图片来自 OpenAI 的原博客

StyleGAN

StyleGAN 是一个著名的生成对抗网络模型,能够生成高分辨率的超逼真图像。下面是这个模型的结构。

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

图片来源于 StyleGAN

从这个模型中主要得到的是,给定一个潜在向量 z ,我们可以使用映射网络来生成另一个潜在向量 w ,它可以被馈送到合成网络中,并产生最终的图像。出于我们的目的,我们将使用一个经过训练的 StyleGAN 来生成人脸。

根据提示生成图像

下面是我使用 CLIP 和 StyleGAN 从提示中生成人脸的架构。

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

图片作者。

这个想法很简单,我们将从 StyleGAN 的 w 潜在向量的随机值开始生成一幅图像。结果将与任意提示一起传递给 CLIP。CLIP 将生成一个分数,表示该图像在提示中表现内容的程度。该值将用于更新 w ,这将生成另一个图像,该图像将反复重复该循环,直到我们确定生成的图像与提示足够相似。

编辑:将使用梯度下降和反向传播更新 w 的值,如同它们是神经网络中的权重。

结果

以下是使用这种简单方法获得的一些结果。

“一个有着金发紫眼的女人的脸的图像”

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

图片作者。

“一张埃隆·马斯克的脸和一头金发的照片”

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

图片作者。

最后,为了给这个模型带来一些乐趣:

“一张瘾君子的脸”

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

图片作者。

有趣的是,前一个提示符的最终结果出现在下图中——这种应变可能是好的!

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

图片作者。

你可以在我的推特账号上找到更多的样本。

结论

语言模型的力量不仅限于文本问题。他们从大量数据中提取概念的能力可以扩展到其他领域,并产生令人惊讶的结果,就像本文中介绍的那样,而且方法非常简单!

在看到像 GPT-3 这样的模型后,想想计算机视觉领域将会出现什么是令人兴奋的。

使用 Python Pandas 生成模拟销售数据

原文:https://towardsdatascience.com/generating-mock-sales-data-with-python-pandas-c904035782fe?source=collection_archive---------20-----------------------

数据科学的一切都是从数据开始的

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

照片由 Unsplash 上的实体模型图形拍摄

数据科学生态系统中有几个软件工具和软件包。这些工具加速了日常流程,并帮助我们管理、探索和分析数据。

无论您使用什么工具,无论您从事什么项目,数据科学中的一切都始于数据。没有适当的数据,您的数据产品很可能会失败。

在学习数据科学和实践软件工具时,寻找数据来玩有时会成为一个挑战。虽然网上有一些免费的数据资源,但它们可能并不总是符合你的需求。

在本文中,我们将使用 Pandas 库生成模拟销售数据。该数据将包含一家连锁店的每日销售数据。我们将使用随机数来分配商店和产品的销售值。

数据可能无法展示在现实生活销售数据中可以观察到的典型特征,如季节性或趋势。但是,您可以用它来练习许多工具和技术。

此外,在生成数据时,我们将使用几个 Pandas 函数和方法。因此,这对熊猫来说也是一个很好的练习。

您将有机会练习以下主题:

  • 如何创建熊猫数据框
  • 创建 NumPy 数组的不同方法
  • 取数组和列表的笛卡尔积
  • 合并熊猫数据框
  • 用熊猫创建线形图

让我们从导入所需的库开始。

import numpy as np
import pandas as pd
from random import shuffle

Python 随机包中的洗牌模块可以用来洗牌。

下一步是创建商店和产品代码。

store_codes = np.arange(1,10)
product_codes = np.arange(1,101)

商店代码从 1 开始,一直到 9。我们有 100 种产品,从 1 开始,一直到 100。

我们还需要一个日期范围,因为这是一个时间序列数据。有许多不同的方法来执行这项任务。我会用熊猫的 date_range 函数。

date_range = pd.date_range(start = "2019-01-01", end = "2020-12-31", freq="D")

我们的产品系列涵盖了两年的时间。freq 参数用于确定增量大小。“D”代表日,因此我们将拥有 2019 年和 2020 年的每日销售数据。

我们有 2 年的时间,9 家商店,100 种产品。每天,我们的数据将包含每个产品-商店对的销售额。因此,我们需要生成日期范围、商店代码和产品代码数组的笛卡尔乘积。

一种方法是通过取这些数组的笛卡尔积来创建一个多重索引。然后,我们可以使用它来创建数据框。

index = pd.MultiIndex.from_product(
   [date_range, store_codes, product_codes],
   names = ["Date", "StoreCode", "ProductCode"]
)sales = pd.DataFrame(index = index)sales.head()

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

(图片由作者提供)

这是销售数据框架的索引。为了从这个多索引创建列,我们只需要使用 reset_index 函数。

sales.reset_index(inplace=True)sales.head()

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

(图片由作者提供)

销售数据框包含每个日期、商店代码和产品代码组合的一行。因此,行数应该等于每个数组中项目数的乘积。

len(sales) == len(store_codes) * len(product_codes) * len(date_range)
Truelen(sales)
657900

我们刚刚证实了我们的预期。我们有一个 657k 行的数据帧。

在零售业中,对商店和产品进行分组是一种常见的做法。让我们从商店开始。

store_groups = ["Small","Medium","Large"]*3
shuffle(store_groups)stores = pd.DataFrame({
   "StoreCode": np.arange(1,10),
   "StoreGroup": store_groups
})stores

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

商店组(作者图片)

由于有 9 家商店,我们创建了一个包含 9 个元素的列表,分为 3 个类别。shuffle 函数在适当的位置打乱这个列表。否则,将保留基本列表的顺序。

我们可以类似地分配产品组。

product_groups = ["A","B","C","D"] * 25
shuffle(product_groups)products = pd.DataFrame({
   "ProductCode": np.arange(1,101),
   "ProductGroup": product_groups
})products.head()

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

产品组(图片由作者提供)

我们有 100 种不同的产品代码,分为 4 类。

我们可能需要分析不同商店和产品组的销售业绩。因此,这些类别需要合并到销售数据框架中。

熊猫的合并功能可以用来完成这个任务。

sales = pd.merge(sales, stores, on="StoreCode", how="left")sales = pd.merge(sales, products, on="ProductCode", how="left")sales.head()

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

销售数据框(作者图片)

我们已经到了数据生成的最后一步,我认为这是最重要的一步。我们需要增加销售额。

你的选择是无限的。一个简单的方法是用随机整数创建一个 NumPy 数组,并将其添加到销售数据框架中。

size = len(sales)sales_amount = np.random.randint(0, 50, size=len(sales))sales["SalesAmount"] = sales_amountsales.head()

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

销售数据框(作者图片)

“销售额”列由 0 到 50 之间的随机整数组成。这完全是随机的,所以我们无法观察到我们销售的任何趋势或季节性。

您可以使用 to_csv 函数将此数据框保存为 csv 文件:

sales.to_csv("mock_sales.csv", header=True, index=False)

让我们通过绘制一个产品商店对的销售额来检查一下。下面的代码创建了一个特定对在过去两个月的销售额的折线图。

sales[
     (sales.StoreCode==1) &
     (sales.ProductCode==5) &
     (sales.Date > "2020-11-01")
     ].plot(x="Date", y="SalesAmount", kind="line", figsize=(10,6))

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

(图片由作者提供)

我们可以清楚地观察到销售额的随机性。

结论

在创造销售额时,我们可以更有创意一点。一些随机噪声或季节性可以添加到这些值中。我把那部分留给你。

我们有模拟销售数据,但我们还没有对它进行任何探索性的数据分析。这将是下一篇文章的主题。敬请期待!

感谢您的阅读。如果您有任何反馈,请告诉我。

用 TigerGraph 从一篇文章中生成选择题

原文:https://towardsdatascience.com/generating-multiple-choice-questions-from-a-passage-with-tigergraph-9dbb473bb505?source=collection_archive---------36-----------------------

如何使用 TigerGraph 生成选择题

注意:在这篇博客中,我们将使用在这篇博客中创建的图表。

概观

我最喜欢的为考试和测验学习的方法之一是制作练习题和/或虚拟抽认卡。然而,提出问题通常是乏味的,而且会占用我大部分时间。因此,我认为根据一篇文章自动创建问题的过程会有所帮助。当然,我能够利用图形数据库的力量把它们放在一起。所以,让我们开始讨论如何去做吧!

第一部分:连接到您的图表

第一步:开始你的解决方案

首先,如果您的解决方案尚未启动,您需要启动它。为此,请前往 https://tgcloud.io/的并导航至“我的解决方案”选项卡。然后按下“动作”下的方框,并按下“开始”按钮。

注意:这可能需要几分钟来加载。

一旦你在状态下得到“准备好”,那么你就准备好继续前进了!

第二步:连接到您的解决方案

接下来,导航到一个 Google Colab 笔记本。

https://colab.research.google.com/

首先,安装并导入 pyTigerGraph。

!pip install pyTigerGraphimport pyTigerGraph as tg

接下来,创建您的 TigerGraphConnection。在参数中,传递您在创建解决方案时设置的子域和密码。图形名称将是我们之前设置的(NotesGraph ),然后我们将生成一个 API 令牌。

注意:从 7 月 28 日起,你需要包含一个 beta=True 来运行它。在未来的 pyTigerGraph 版本中,这种情况可能会有所改变。

conn = tg.TigerGraphConnection(host="https://SUBDOMAIN.i.tgcloud.io/", password="PASSWORD", graphname="NotesGraph", beta=True)conn.apiToken = conn.getToken(conn.createSecret())

太好了!现在我们已经准备好编写查询了!

第二部分:创建完整图表的问答

这里,我们将编写几个问题来生成一些查询。

查询 I:查找选项

我们将创建的第一个查询将为一个问题查找其他多项选择选项。在过去的博客中,我们用 SpaCy 来标识每个词的“类型”;我们将使用这种类型来获取相同或相似类型的单词。

conn.gsql('''USE GRAPH NotesGraphDROP QUERY findOptionsCREATE QUERY findOptions(Vertex<Entity_Name> word) FOR GRAPH NotesGraph {Seed = {word};Res = SELECT tgt FROM Seed:s - (ENTITY_NAME_ENTITY:e) - Entity:tgt;Options = SELECT tgt FROM Res:s - (ENTITY_NAME_ENTITY:e) - Entity_Name:tgt
          WHERE word.entity_name != tgt.entity_name;PRINT Options;PRINT Seed;}INSTALL QUERY findOptions''')

我们来分析一下。在标题中,我们接受一个顶点实体名称的输入。

CREATE QUERY findOptions(Vertex<Entity_Name> word) FOR GRAPH NotesGraph

我们将使用输入作为种子,或者我们开始的地方。

Seed = {word};

接下来,我们将缩小以获取实体顶点。

Res = SELECT tgt FROM Seed:s - (ENTITY_NAME_ENTITY:e) - Entity:tgt;

然后,我们将找到连接到实体的其他实体名称顶点,不包括实体名称本身。

Options = SELECT tgt FROM Res:s - (ENTITY_NAME_ENTITY:e) - Entity_Name:tgt
          WHERE word.entity_name != tgt.entity_name;

最后,我们将打印出选项和输入。

PRINT Options;PRINT Seed;

而且完美!这将返回选项和输入的值。

总之,该查询将从任何文档中获取任何相似的潜在答案选择。稍后,我们将筛选答案选项,以防有人只想研究一个文件夹或一个文档。

查询二:获取句子

现在,让我们用不同的句子来创造填空题。我们将传递一个限制参数,即我们想要生成的句子数量。

conn.gsql('''USE GRAPH NotesGraphDROP QUERY getSentencesCREATE QUERY getSentences(INT lim) FOR GRAPH NotesGraph {TYPEDEF TUPLE<STRING sentence, STRING entity> OPTIONS;
HeapAccum<OPTIONS> (lim, entity DESC) @@opt;
SumAccum<INT> @connected_entities;Seed = {Entity_Name.*};Res = SELECT tgt FROM Seed:s - (SENTENCE_ENTITY_NAME:e) - Sentence:tgt
      ACCUM tgt.@connected_entities+=1, @@opt+=OPTIONS(tgt.setence, s.entity_name)
      HAVING tgt.@connected_entities > 0;PRINT @@opt AS Sentence_Options;}INSTALL QUERY getSentences''')

再一次,让我们来分析一下。

首先,我们将创建一个 HeapAccum。HeapAccum 必须接受一个 TYPEDEF 元组,我们将把它作为一个句子和一个实体。

TYPEDEF TUPLE<STRING sentence, STRING entity> OPTIONS;
HeapAccum<OPTIONS> (lim, entity DESC) @@opt;

接下来,我们将创建一个 SumAccum,我们将使用它来计算每个句子连接了多少个实体。为此,我们要做的就是确保我们提取的句子中至少有一个实体。

SumAccum<INT> @connected_entities;

我们将从抓取所有的实体名称顶点开始。

Seed = {Entity_Name.*};

然后我们将抓取所有连接到 Entity_Name 顶点的句子。然后我们将有两个累加器。第一个将计算有多少实体连接到句子(以确保不止一个,如 having 子句所示)。第二个将向 HeapAccum 添加实体和句子。

Res = SELECT tgt FROM Seed:s - (SENTENCE_ENTITY_NAME:e) - Sentence:tgt
      ACCUM tgt.@connected_entities+=1, @@opt+=OPTIONS(tgt.setence, s.entity_name)
      HAVING tgt.@connected_entities > 0;

完美!最后,我们将把 HeapAccum 作为句子选项打印出来。

PRINT @@opt AS Sentence_Options;

现在我们有了获取句子和多项选择选项的查询,让我们把它们放在一起。

Python 函数:提出问题

最后,让我们将这两个查询放在一起,创建一个基于文本的交互式 Python 函数。

import randomres = conn.runInstalledQuery("getSentences", params={"lim": 100})[0]["Sentence_Options"]
random.shuffle(res)pref = ["a", "b", "c", "d"]
let_to_num = {let: num for num, let in enumerate(pref)}for num in range(5): sentence = res[num]["sentence"]
   entity = res[num]["entity"]
   opts = conn.runInstalledQuery("findOptions", {"word": entity}) similar_words = [i["v_id"] for i in opts[0]["Options"]]
   random.shuffle(similar_words)
   similar_words = similar_words[:3]
   similar_words.append(opts[1]["Seed"][0]["v_id"])
   random.shuffle(similar_words) print(f'{num+1}.) {sentence.replace(entity, "___")}')
   print("\n".join([f"{let}.) {opt}" for let, opt in zip(pref, similar_words)]))
   print("")
   ans = input("Enter the letter: ").lower() if similar_words[let_to_num[ans]] == entity:
      print("Correct!")
   else:
      print(f"Nope. The correct answer is \"{entity}\"!") print("\n\n\n")

我们来分析一下。首先,我们将抓取一定数量的句子,然后使用 Python 的随机函数将它们打乱。

import randomres = conn.runInstalledQuery("getSentences", params={"lim": 100})[0]["Sentence_Options"]
random.shuffle(res)

接下来,我们将为答案选项创建一个前缀数组,然后创建一个字典。

pref = ["a", "b", "c", "d"]
let_to_num = {let: num for num, let in enumerate(pref)}

然后我们将循环所有的句子选项。

for num in range(5):

接下来,我们将抓住句子、实体和选项。

sentence = res[num]["sentence"]
entity = res[num]["entity"]
opts = conn.runInstalledQuery("findOptions", {"word": entity})

然后,我们将混合答案选项,选择三个,然后添加我们的选择,并洗牌。

similar_words = [i["v_id"] for i in opts[0]["Options"]]
random.shuffle(similar_words)
similar_words = similar_words[:3]
similar_words.append(opts[1]["Seed"][0]["v_id"])
random.shuffle(similar_words)

最后,我们将开始打印出这些值。我们将提出问题,然后打印出答案并提示答案。

print(f'{num+1}.) {sentence.replace(entity, "___")}')
print("\n".join([f"{let}.) {opt}" for let, opt in zip(pref, similar_words)]))
print("")
ans = input("Enter the letter: ").lower()

如果答案是正确的,那么我们就说正确。如果不是,我们就说正确答案。

if similar_words[let_to_num[ans]] == entity:
   print("Correct!")
else:
   print(f"Nope. The correct answer is \"{entity}\"!")

完美!现在,您可以运行单元并与您的问答脚本进行交互。

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

示例问题

第三部分:祝贺你!

恭喜你。如果你完成了这个,你现在可以从你的笔记中创建选择题!

点击此处查看完整的 Colab:

https://colab.research.google.com/drive/12az8ahoX5FQu6-ARGYiwbyFD7B3LPIZV?usp=sharing

如果你有任何问题,发布到 TigerGraph 的社区页面。

https://community.tigergraph.com/

谢谢大家!期待这个系列的下一篇博客!

使用深度学习生成音乐

原文:https://towardsdatascience.com/generating-music-using-deep-learning-cb5843a9d55e?source=collection_archive---------0-----------------------

思想和理论

引入新的基于 VAE 的架构来生成新颖的音乐样本

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

照片由雷兹利Unsplash 上拍摄

深度学习从根本上改变了计算机视觉和自然语言处理领域,不仅在分类方面,而且在生成任务方面,使人们能够创建令人难以置信的逼真图片和人工生成的新闻文章。但是音频领域——或者更具体地说——音乐领域呢?在这个项目中,我们的目标是创建新的神经网络架构来生成新的音乐,使用来自 Lakh Piano 数据集的 20,000 个不同流派的 MIDI 样本,Lakh Piano 数据集是最近音乐生成任务的流行基准数据集。

这个项目是由宾夕法尼亚大学大四学生艾萨克·塔姆 马修·金 共同完成的。

背景

使用深度学习技术的音乐生成在过去二十年中一直是一个有趣的话题。与图像相比,音乐在三个主要方面被证明是一个不同的挑战:首先,音乐是时间性的,具有跨时间依赖的层次结构。其次,音乐由多种乐器组成,这些乐器相互依存,并随着时间的推移而展开。第三,音乐被分为和弦、琶音和旋律——因此每个时间步长可能有多个输出。

然而,音频数据有几个属性,使它们在某些方面熟悉深度学习中的传统研究(计算机视觉和自然语言处理,或 NLP)。音乐的序列性质让我们想起了 NLP,我们可以用递归神经网络来处理它。还有多个音频“通道”(就音调和乐器而言),这让人想起卷积神经网络可以用于的图像。此外,深度生成模型是令人兴奋的新研究领域,具有创建真实合成数据的潜力。一些例子是变分自动编码器(VAEs)和生成对抗网络(GANs),以及 NLP 中的语言模型。

大多数早期音乐生成技术都使用递归神经网络(RNNs),它自然地包含了时间上的依赖性。 Skuli (2017)使用 LSTMs 以与语言模型相同的方式生成单乐器音乐。同样的方法也被尼尔森 (2020)使用,他改编这种方法来产生高保真音乐。

最近,卷积神经网络(CNN)被用于生成音乐,并取得了巨大的成功,2016 年 DeepMind 展示了 WaveNet 的有效性,它使用扩张卷积来生成原始音频。 (2017)创建了 MidiNet,它使用深度卷积生成对抗网络(DCGANs)来生成多乐器音乐序列,这些音乐序列可以基于前一小节的音乐以及当前小节的和弦。董在 2017 年的 MuseGAN 中进一步发展了 GAN 的概念,使用多个发生器来实现尊重乐器之间依赖关系的合成多乐器音乐。董使用 Wasserstein-GAN 与梯度惩罚(WGAN-GP)更大的训练稳定性。

最后,随着注意力网络和变形金刚在自然语言处理方面的最新进展,人们也尝试将变形金刚应用于音乐生成。Shaw (2019)创建了 MusicAutobot,它使用 BERT、Transformer-XL 和 Seq2Seq 的组合来创建一个多任务引擎,既可以生成新的音乐,也可以在其他乐器的条件下创建和声。

数据集

我们的数据来自 Lakh Pianoroll 数据集,这是一个由 174,154 个多轨道 Pianoroll 组成的集合,来自 Lakh MIDI 数据集,由中央研究院 IT 创新研究中心的音乐和人工智能实验室管理。我们使用了数据集的 LPD 5 版本,其中包括钢琴、鼓、吉他、贝斯和弦乐的曲目,使我们能够生成复杂而丰富的音乐,并展示我们的生成模型在不同乐器之间编排音乐的能力。我们使用 Lakh Pianoroll 数据集的净化子集,其中包括 21,245 个 MIDI 文件。每个文件都有相应的元数据,允许我们确定每个文件的信息,如艺术家和标题名称。

基线法:用 RNNs 进行下一次笔记预测

为了建立一个我们可以改进的音乐生成的基线,我们使用了递归神经网络(RNN),这是一种现有的易于复制的方法。生成音乐被公式化为下一个音符预测问题。(这种方法非常类似于 NLP 中使用的基于递归的语言模型。点击此处了解更多信息)这将允许我们通过不断将生成的音符传回到模型中来生成我们想要的任意多的音乐。

在实现方面,我们使用了门控循环单元(GRU)而不是普通的 RNN,因为它能够更好地保留长期依赖性。每个 GRU 将接受前一层的激活和输出作为输入,输出将是给定前一激活和输入的下一个音符。

为了创建训练我们的递归神经网络所需的数据,我们首先解析数据集的钢琴音符,将每个文件表示为在文件中找到的音符列表。然后,我们通过获取每首歌曲的列表表示的子集来创建训练输入序列,并通过简单地获取每个子集的下一个音符来创建相应的训练输出序列。有了这种训练输入和输出,模型将被训练来预测下一个音符,这将允许我们传递任何音符序列,并获得下一个音符的预测。每个输入序列被传递到一个嵌入层,该嵌入层创建大小为 96 的嵌入。然后,该嵌入被传递到具有单层的门控循环单元中,该单元然后被传递到完全连接的层,以输出下一个音符的概率分布。我们可以选择概率最高的音符作为下一个预测音符,但这将导致没有变化的确定性序列。因此,我们从带有输出概率的多项式分布中抽取下一个音符。

虽然 RNN 下一个音符预测模型实现起来简单明了,但生成的音乐听起来远非理想,而且效用非常有限。因为我们将每个音符编码到一个标记中,并预测编码的概率分布,所以我们只能对一个乐器这样做,因为对于多个乐器,音符组合的数量呈指数增长。还有,假设每个音符都是一样长的,肯定不能反映大多数音乐作品。

为 RNN 下一个音符预测模型生成的音乐

多乐器 RNN

因此,我们试图探索同时为多种乐器创作音乐的其他方法,并提出了多乐器 RNN。

我们没有像最初的想法那样将音乐编码成独特的音符/和弦,而是在每个时间步直接处理 5 x 128 多乐器钢琴卷,将其展平成为一个 640 维的向量,代表每个时间步的音乐。然后,我们训练一个 RNN 来预测下一个时间步的 640 维向量,给定前面的 640 维向量的长度为 32 的序列。

虽然这种方法在理论上是有意义的,但要产生令人满意的结果是有挑战性的,因为很难在所有工具之间产生互补的多样性。

  • 在单乐器设置中,我们通过输出 softmax 分数对概率加权的多项式分布进行采样,以生成下一个音符。然而,由于所有乐器被一起放置在 640 维向量中,所以在整个 640d 向量上使用 softmax-ed 分数来生成下一个音符可能意味着一些乐器可能具有多个音符,而一些乐器没有音符。
  • 我们试图通过对 5 种乐器的 128 维向量分别运行 softmax 函数来解决这个问题,这样我们可以确保为每种乐器生成一定数量的音符。
  • 然而,这意味着每个仪器的采样是相互独立的。这意味着生成的钢琴序列不会与其他乐器的序列互补。例如,如果 C-E-G 和弦是从序列中采样的,那么低音就没有办法合并它,并且可以采样 D-F-A 和弦,因为 D-F-A 和弦是不和谐的,不是互补的。

此外,还有一个问题是不知道每次每种乐器要采样多少个音符。这个问题在单乐器设置中不存在,因为单音符和多音符和弦都被编码为整数表示。我们通过从多项式中为每个时间步长采样指定数量的音符(例如钢琴 2 个,吉他 3 个)来解决这个问题。但是这是不成功的,因为生成的音乐听起来非常随机和不音乐。

为多乐器 RNN 模型生成的音乐

从递归到卷积

从这一点开始,我们决定专注于**卷积神经网络(CNN)**而不是 RNNs 来生成音乐序列。CNN 将通过输出 5×32×128 的三维张量直接生成长度为 32 的序列。这将解决不知道要生成多少音符以及必须使用多项式采样的问题。在序列生成方面,CNN 架构(如 WaveNet)已经显示出与 RNNs 一样好(如果不是更好的话)的性能。此外,由于卷积运算的性能优化,它们的训练速度更快。

MelodyCNN 和条件性和谐 CNN

为了生成多个彼此兼容的乐器轨道,我们尝试了一个两部分生成模型,包括用于下一时间步旋律生成的 MelodyCNN ,以及用于生成非钢琴乐器的条件和声 CNN ,给定相同时间步的旋律以及上一时间步的乐器音乐。

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

用于生成音乐的 MelodyCNN +条件和声 CNN 的架构。(图片作者)

由于输入和输出大小相同(32 x 128),所用的 MelodyCNN 架构是对称的,具有 3 个卷积层、3 个密集层和 3 个去卷积层。条件谐波 CNN 对每个输入(钢琴和乐器的先前输入)使用 3 个卷积层,然后在通过密集层和去卷积层之前连接结果张量。

因此,MelodyCNN 学习连续时间步长中钢琴序列之间的映射,而条件和声 CNN 从钢琴音乐空间映射到其他乐器。

总共使用 5 个 CNN(每个乐器一个),给定起始多乐器序列,可以迭代地生成新音乐。首先,MelodyCNN 用于预测下一个钢琴序列,条件和声 CNN 用于预测其他乐器。

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

钢琴音乐产生的旋律。(图片作者)

这个框架成功地生成了多种乐器的音乐序列,这些乐器的声音在音乐上是互补的。然而,改变生成音乐的起始序列只会导致生成的音乐有很小的变化,如上面的钢琴卷所示:三个生成的序列几乎彼此相同。

这表明 CNN 很可能集中于仅输出训练数据中的公共序列的一个小子集,这最小化了训练损失。需要找到另一种方法,在给定相同输入的情况下,在输出音乐中产生一些变化,为了实现这一点,我们转向 VAEs。

为旋律 CNN +条件和声 CNN 模型生成音乐

使用可变自动编码器(VAEs)

VAEs 的背景

变分自动编码器(VAE)是一种自动编码器,其中训练被正则化以确保潜在空间具有允许生成过程的良好属性。两个这样的特性是连续性——潜在空间中的接近点一旦被解码应该给出相似的点,以及完整性——从潜在空间采样的点一旦被解码应该给出有意义的内容。

标准的自动编码器将输入编码成潜在空间中的向量,但是不能保证潜在空间满足允许产生新数据的连续性和完整性。相反,VAE 将输入编码为潜在空间上的分布。具体来说,我们假设潜在分布是高斯分布,因此编码分布的编码器相当于输出正态分布的均值和标准差参数的编码器。

为了训练 VAE,使用了两项损失函数:重构误差(解码输出和输入之间的差异),以及正则化项(潜在分布和标准高斯分布之间的 KL 散度),以将潜在分布正则化为尽可能接近标准正态。

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

变分自动编码器(VAE)如何工作的图示。(图片由作者提供)

应用

因此,我们将 VAEs 应用于音乐生成任务。先前的钢琴输入由钢琴值编码成 zₜ. k 维的潜在钢琴编码然后,随机噪声被添加到编码的潜在分布的平均参数。这种随机噪声的标准差是一个超参数,用户可以根据自己想要的变化量进行调整。然后,潜在参数 zₜ被输入到多层感知器 MelodyNN,该感知器学习从前一钢琴序列的潜在分布到下一钢琴序列的潜在分布的映射。然后,输出 z_t+1 被解码,成为生成的下一个钢琴输出。

针对特定乐器的 vae 也在其他四种乐器(吉他、贝斯、弦乐、鼓)上接受培训。

然后,类似于前面的 ConditionalNN,我们使用另一个 MLP conditional nn,其接受生成的下一周期钢琴潜在参数以及前一周期吉他潜在参数 z_t+1,并学习到下一周期吉他潜在参数 w_t+1 的映射。w_t+1 然后由特定于乐器的 VAE 解码器解码,以产生下一个周期的吉他输出。训练 4 个条件神经网络,每个非钢琴乐器一个,这允许生成下一个 5 乐器序列。

因此,通过用 VAEs 将音乐输入映射到潜在分布,我们可以通过将随机噪声添加到编码的潜在分布的参数来将变化引入到生成的音乐输出中。由于连续性,这确保了在添加随机噪声之后,解码的输入与原始输入相似但不同,并且由于完整性,这确保了它们给出与输入音乐分布相似的有意义的音乐输出。

该架构的可视化指南如下所示。

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

建筑的 VAE-NN 用来产生音乐。(图片作者)

结果

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

从同一起始序列生成的两个钢琴演奏者。音乐输出中显示的一个变化示例如上所示。上面的两个音轨有相同的开始序列,但是产生的鼓点略有不同。此外,第一首曲目接近尾声时有钢琴部分,而第二首曲目没有,条件神经网络通过改变生成的伴奏乐器曲目来做出响应。(图片由作者提供)

训练了潜在维数为 8、16、32 和 64 的值。最后,由于音乐样本在音乐空间中相对稀疏,所以使用 16 维的潜在空间来训练条件神经网络。

在训练条件神经网络之后,我们发现 VAE+神经网络方法在创建听起来连贯的多乐器输出方面是成功的,并且具有美学上令人愉悦的适当变化量。发现标准偏差在 0.5 到 1.0 之间的随机噪声产生最佳的变化量。

一些使用 VAE 神经网络生成音乐的好例子。

生成特定风格的音乐

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

根据特定风格生成音乐的方法(图片由作者提供)

上面解释的 VAE-神经网络框架允许我们基于特定的风格,例如某个艺术家、流派或年份,用一种简单的方法来生成音乐。例如,如果我们想创作迈克尔杰克逊的惊悚片风格的音乐,我们可以:

1.将歌曲分成 32 步序列,并使用每个乐器的 VAE 编码器将每个序列的钢琴声编码到潜在空间中。将每个乐器的独特序列存储在中。

2.当从开始序列生成音乐时,从该集合中对每个乐器的一个潜在向量进行采样。这个采样的潜在向量(来自我们想要的歌曲) s 然后与先前序列的潜在向量内插以生成新的潜在向量,

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

其中α是潜在样本因子,它是一个可以调整的超参数。(为生成的音乐选择较高的α值,以更好地适应所需的风格)

3.使用 z’ₜ而不是 zₜ作为 MelodyNN 的输入来生成新的潜在向量,从而生成钢琴序列。

使用这种方法,α=0.5,我们根据几首歌曲生成了新的音乐,一些例子是迈克尔杰克逊的 Thriller 和后街男孩的 I Want It That Way 。这成功地生成了与原始歌曲有些相似但也有一些变化的音频样本。(同样,变化的程度也可以用 noise_sd 超参数来调节)。人们甚至可以根据不同艺术家或风格的混合样本来创作音乐,从而使音乐爱好者能够结合不同音乐明星的风格来合成音乐。

使用 VAE 神经网络风格条件生成音乐。

大失败:甘斯

受到使用深度卷积生成对抗网络(DCGANs)来产生听起来真实的音乐的成功的启发,我们试图使用 GANs 来产生音乐。众所周知,GANs 可以在计算机视觉领域生成高度逼真的合成样本,比 VAEs 更好。这是因为 gan 不估计底层分布的显式概率密度,而 vae 试图优化较低的变分界限。然而,众所周知,GANs 很难训练成功。

我们使用了一个具有 6 个去卷积层的生成器,接收一个噪声 100 维向量,并生成一个 5 x 32 x 128 的多乐器音乐序列。鉴别器具有相反的架构,接收 5 x 32 x 128 的音乐序列,使其通过 6 个卷积层,并输出样本为真实的概率。

对于生成器和鉴别器,使用了 PReLU 激活,以及卷积层的批量归一化。两者都使用了 Adam optimizer。

尝试了以下方法来提高 GAN 的稳定性:

  • 标签平滑:我们不是对生成图像或真实图像分别使用硬标签 0 或 1,而是在标签中添加随机噪声(这样生成图像的标签在 0 和 0.1 之间,真实图像的标签在 0.9 和 1 之间)。
  • 特征匹配:添加 L2 正则化子以使真实数据和生成数据的分布更接近。使用两个正则化器:第一个正则化器基于真实图像输入与生成图像输入的期望值的绝对差,第二个正则化器基于真实图像输入和生成图像输入的第一卷积层的输出的期望值的绝对差。
  • 双时标更新规则(TTUR):对鉴别器使用比生成器更高的学习速率。
  • 调整学习率

尽管进行了几次尝试,训练甘在产生各种听起来逼真的音乐方面证明是不成功的。存在模式崩溃的实例,例如下面生成的音频样本,它是从不同的噪声向量连接在一起生成的 100 个样本。生成的样本大多相似。其他尝试都未能学到任何实质性的东西。

失败的 GAN 实验带来的失误

另一条基线:变形金刚

我们使用的第二种更复杂的基线方法是变压器架构。变形金刚在自然语言处理方面取得了很大的成功,它能够比旧的基于递归的语言模型更快地训练,并具有更好的长期记忆。我们使用了音乐汽车人项目的 Transformer-XL 架构,因为它的代码非常容易复制——我们为此感谢安德鲁·肖,并鼓励您查看他的精彩系列文章!

在普通的 transformer 模型中,数据单元之间的直接连接提供了获取长期依赖关系的机会。然而,这些普通的转换器是用固定长度的上下文实现的,因此转换器不能对长于固定长度的依赖关系建模,并且会出现上下文碎片。

Transformer-XL 架构提供了解决这些问题的技术。第一,它有段级的递归机制。在训练时,为前一段计算的表示被缓存,使得它们可以在模型处理下一段时用作扩展上下文。因此,信息现在可以流经段边界,并解决了上下文碎片问题。其次,它具有相对位置编码方案。这使得模型不仅可以理解每个标记的绝对位置,还可以理解每个标记相对于另一个标记的位置,这在音乐中非常重要。

与文本不同,标记音乐要复杂得多。一个音符代表两个不同的值——音高和持续时间(它也可以代表更多的东西,如响度和时间,但这些对我们的目的来说不太重要)。因此,每个音符都需要被编码成一系列的记号。幸运的是,音乐汽车人项目处理了 MIDI 文件的符号化。

我们发现生成的音乐也相对不错——看看下面吧!

结论

总的来说,我们已经实现了各种深度学习方法来解决音乐生成问题,并取得了不同程度的成功。我们的基线方法对单个轨迹和多个轨迹都使用了递归神经网络模型。虽然这种模型在产生的音符的音乐性方面更成功,但它的实用性非常有限,因为它只能产生四分音符节拍的音符。然后,我们转向卷积神经网络模型,使用普通 CNN 产生钢琴音轨,使用条件 CNN 产生其他乐器音轨。我们发现由 CNN 模型产生的安排更有条理和连贯性,因为我们使用了条件模型。

我们设计的新颖的 VAE 建筑是我们项目最成功的贡献。通过使用 VAE 将序列编码到潜在空间中,我们可以在潜在空间中添加噪声,以可控的方式增加生成的输出的变化,同时保持先前序列之间的相似性,最终提高我们生成的音乐的独特性。

你可以在我们的 Github 库中找到我们所有的代码——在你自己的音乐创作冒险中随意使用它。如果你有任何问题,请在 LinkedIn 上留言或联系我,我很乐意帮助你!

真正让深度学习领域令人惊叹的是开源合作文化——如果没有我们之前许多慷慨的贡献者,我们的工作永远不可能实现,我们希望这个项目是对深度学习领域的一个微小但有意义的贡献。

特别感谢教授这门深度学习课程(cis 522——宾夕法尼亚大学数据科学中的深度学习)的 Lyle Ungar 和 Konrad Kording 教授,以及 TA Pooja Counsul 整个学期的指导。

用 Python 和 R 生成参数化的 Powerpoint 文档

原文:https://towardsdatascience.com/generating-parameterized-powerpoint-documents-in-python-and-r-333368479038?source=collection_archive---------3-----------------------

通过自动生成 Powerpoint 控制您的报告工作流程

许多商业报告领域的数据科学家被要求将他们的数据转换成 Powerpoint 演示文稿(不管他们喜不喜欢!).最常见的是许多参数化的演示,其中格式、图表和内容都是相同的,但数据会发生变化,例如按组织单位。经常需要从指定的示例模板生成数十、数百甚至数千个这样的报告。本教程给出了一个如何编写和自动化这样一个工作流的例子。

本教程的所有代码都可以在我的 Github repo 中找到,整篇文章都引用了它。

背景和先决条件

本教程涉及以下场景:

  • 用户群需要以包含图表和表格的可编辑 Powerpoint 文档的形式交付结果。
  • 存在完全填充有虚拟数据或示例数据的示例文档。
  • 同一文档需要用不同组的不同数据重新创建,并用不同的文件名保存,以便在整个组织内分发。该工作流有助于创建任意数量的这种参数化文档。

使用开源技术,这个工作流程是完全可执行的。对于 Python 中的执行,建议使用基于 Python 3.7 的 conda 环境或虚拟环境,并安装pandaspython-pptx包。为了进口到 R,将需要reticulate包。

本教程分为三个部分:

  1. 如何使用python-pptx包编写一个函数来替换现有 Powerpoint 演示文稿中的数据。
  2. 如何在 Python 中使用它来批量生成任意数量的参数化 Powerpoint 文档。
  3. 如何将函数导入到 R 中,并使用 tidyverse 批量生成任意数量的参数化 Powerpoint 文档。

入门指南

假设我们为一个组织工作,该组织由 20 个销售小组组成,从 A 组到 t 组依次命名。一个名为ppt-template.pptx的现有 Powerpoint 文档存在于回购的templates文件夹中,其中的虚拟数据包含以下内容:

  • 一个标题页,我们希望根据特定的销售组名称对其进行定制。
  • 包含两个图表(条形图和饼图)的页面。我们将需要替换数据并重新命名这两个图表,以引用特定的销售组。
  • 带有销售数据表的页面。我们希望用特定销售组的数据替换该表中的数据。

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

我们需要编辑的幻灯片(作者生成)

我们需要替换到该文档中的数据可以在data文件夹中找到。这是出于演示目的随机生成的数据。文件chart_df.csv包含条形图和饼图的数据,以table_为前缀的各种文件包含每个销售组的数据,这些数据将放入最后一张幻灯片的表格中。

使用python-pptx包替换 Powerpoint 演示文稿的元素

我们从 Python 开始,从python-pptx包中导入一些我们需要的函数。在这个例子中,我们只需要几个简单的函数,但是我鼓励您探索这个包中广泛可用的函数来编辑和定制 Powerpoint 元素。

from pptx import Presentation
from pptx.chart.data import CategoryChartData

接下来,我们将现有的虚拟演示加载到 Python 会话中:

pres = Presentation("templates/ppt-template.pptx")

通过检查pres,我们可以看到它是一个 Powerpoint 演示对象。

pres## <pptx.presentation.Presentation object at 0x7fb40af62140>

pres实际上是一个复杂的嵌套 XML 对象。但是正如你所料,它包含了一些幻灯片。我们可以创建一个幻灯片列表,并检查该列表是否包含我们期望的三张幻灯片。

slides = [slide for slide in pres.slides]
len(slides)## 3

看起来不错。现在,每张幻灯片都包含一些形状,可以是从文本框到图表、表格或图示的任何形状。

编辑形状中的文本框

让我们看看标题幻灯片上有多少个形状:

slide0 = slides[0]
slide0_shapes = [shape for shape in slide0.shapes]
len(slide0_shapes)## 3

所以标题幻灯片上有三个形状。我们知道其中一个是标题占位符文本框,另一个是副标题占位符文本框,我们可以识别并抓取它们,因为它们都包含一个text_frame(文本框的 XML 术语)。

title_shapes = [shape for shape in slide0.shapes if shape.has_text_frame]
len(title_shapes)## 2

现在,由于这些是占位符对象,占位符文本可能会由于模板格式而与模板中的可见内容不匹配,因此我们需要查看每个占位符的文本:

placeholder_text = [shape.text for shape in title_shapes if shape.has_text_frame]
placeholder_text## ['Presentation title Alt', 'Subtitle comes here']

我们现在可以使用这些信息来替换这些文本框中的文本。让我们对 A 组演示文稿的标题文本也这样做,以检查它是否有效:

title = [shape for shape in title_shapes if shape.has_text_frame and shape.text == 'Presentation title Alt']
title[0]. text = "Presentation for Group A"

我们可以检查这是否有效:

new_placeholder_text = [shape.text for shape in title_shapes if shape.has_text_frame]
new_placeholder_text## ['Presentation for Group A', 'Subtitle comes here']

成功了!我们可以用类似的方法来编辑字幕。

将新数据加载到图表中

我们可以使用形状的has_chart属性来识别图表对象。让我们检查一下第二张幻灯片上是否有两张图表:

slide1 = slides[1]
slide1_charts = [shape for shape in slide1.shapes if shape.has_chart]
len(slide1_charts)## 2

我们不能完全确定这些图表是按照它们在幻灯片上出现的顺序排列的,但是我们可以通过标题来识别特定的图表,标题嵌套在 chart 对象的标题文本框架中。

bar_chart = [shape.chart for shape in slide1_charts if shape.chart.chart_title.text_frame.text == 'Statistics here']

现在我们有了条形图,我们需要重写它的数据。我们注意到条形图有三个系列的条,每个代表四个类别中的一个。当我们重写此图表中的数据时,我们需要重写所有数据—不可能只重写其中的一部分。因此,我们从头开始定义类别,并将三个系列的数据写入一个CategoryChartData对象。这里我就用一些随机的例子数据来说明。

chart_data  = CategoryChartData()
chart_data.categories = ['Category ' + str(i) for i in range(1,5)]
chart_data.add_series('Series 1', range(1, 5))## <pptx.chart.data.CategorySeriesData object at 0x7fb40b15df50>chart_data.add_series('Series 2', range(2, 6))## <pptx.chart.data.CategorySeriesData object at 0x7fb40af9bc50>chart_data.add_series('Series 3', range(3, 7))## <pptx.chart.data.CategorySeriesData object at 0x7fb40af9bf90>

我们现在用这个数据替换条形图中的数据,并给它一个新的标题。

bar_chart[0].replace_data(chart_data)
bar_chart[0].chart_title.text_frame.text = "Sales by Category: Group A"

此时,我们可以保存我们的演示文稿并查看其中一页,看看这是否有效。

pres.save("test1.pptx")

通过检查第二张幻灯片,我们可以看到我们的条形图已经成功地用新数据进行了更新。

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

条形图已成功更新(作者生成)

使用类似的方法,我们也能够更新这张幻灯片的饼图和标题。

编辑表格

让我们使用与获取图表和文本框类似的方法获取上一张幻灯片中的表格。我们只想要一张桌子。

slide2 = pres.slides[2]
table = [shape for shape in slide2.shapes if shape.has_table]
len(table)## 1

太好了!现在表格需要一个单元格一个单元格地编辑,这听起来很痛苦,但实际上使用索引很容易。我们注意到有一行列名,然后是八行数据,然后是一行总计。让我们从数据集中引入一个表格。

import pandas as pd
table_A = pd.read_csv("data/table_A.csv")
table_A##      A    B    C    D    E
## 0  2.2  4.8  0.9  5.1  5.4
## 1  3.1  4.4  3.4  4.0  3.8
## 2  1.6  3.8  4.3  6.0  2.7
## 3  5.4  5.1  0.7  0.3  2.8
## 4  4.8  2.1  5.0  2.9  2.1
## 5  5.3  5.8  3.9  5.5  4.1
## 6  2.4  4.9  1.9  5.7  5.8
## 7  4.7  3.1  3.7  1.3  0.6

现在我们的表的第一行是一组列名,所以我们可以编辑文本以匹配我们的table_A数据框架中的列名:

for j in range(0,5):
    table[0].table.cell(0, j).text = "Product " +    table_A.columns.values[j]

然后,我们可以直接从数据框中更新每个单元格中的值:

for i in range(1,9):
    for j in range(0,5):
      table[0].table.cell(i,j).text = str(table_A.iloc[i-1, j])

最后,我们将一些总数放在最后一行(确保我们格式化以避免任何 Python 的浮点行为):

for j in range(0,5):
    table[0].table.cell(9,j).text = "{:.1f}".format(sum(table_A.iloc[:,j]))

让我们再次保存并检查该表是否更新了新数据:

pres.save("test2.pptx")

经过检查,我们似乎成功地更新了该表:

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

该表已成功更新(由作者生成)

创建一个函数来更新演示

既然我们已经了解了编辑此演示文稿的基本知识,我们可以通过编写一个 Python 函数来实现这一切,该函数需要五个输入,如下所示:

  • group:单据的集团参数。
  • data_chart:包含各种图表统计数据的数据帧
  • data_table:用来替换表格的数据帧
  • input file:待编辑文件的路径
  • output_file:新文件将被写入的路径

你可以在回购的edit_pres.py文件中看到这个函数。让我们找到这个函数,并通过为销售组 m 生成一个文档来测试它。

# load data
chart_df = pd.read_csv("data/chart_df.csv")
table_M = pd.read_csv("data/table_M.csv")# load function
exec(open('edit_pres.py').read())# write Group M presentation
edit_pres("M", chart_df, table_M, "templates/ppt-template.pptx", "test3.pptx")## 'Successfully saved version M!'

我们可以检查看看结果:

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

所有幻灯片都已成功更新(作者生成)

太好了!我们现在已经具备了开始批量生产参数化 Powerpoint 所需的一切。

Python 中的批量生产

既然我们已经设置了 Python 函数,我们只需要将它与所有数据一起加载到我们的会话中,我们将使用这些数据为每个销售组更新到 twenty 版本中。

import glob
import os# load function
exec(open('edit_pres.py').read())# load all dataframes in data folder into a dict
path = "data/"
data_files = glob.glob(os.path.join(path, "*.csv"))
dataframes = dict()
for i in data_files:
    path = os.path.basename(i)
    name = path.split('.')[0]
    dataframes[name] = pd.read_csv("data/" + name + ".csv")

现在让我们为每个组运行我们的函数,并将输出的 Powerpoint 作为一个适当命名的文件写在一个outputs目录中。

# create outputs directory if it doesn't exist
if not os.path.isdir("outputs"):
  os.mkdir("outputs")# generate a ppt for each group
for group in dataframes['chart_df'].group.values:
  tables_data = dataframes['table_' + group]
  edit_pres(group, dataframes['chart_df'], tables_data, 
  'templates/ppt-template.pptx', 'outputs/results_group_' + group + '.pptx')## 'Successfully saved version A!'
## 'Successfully saved version B!'
## 'Successfully saved version C!'
## 'Successfully saved version D!'
## 'Successfully saved version E!'
## 'Successfully saved version F!'
## 'Successfully saved version G!'
## 'Successfully saved version H!'
## 'Successfully saved version I!'
## 'Successfully saved version J!'
## 'Successfully saved version K!'
## 'Successfully saved version L!'
## 'Successfully saved version M!'
## 'Successfully saved version N!'
## 'Successfully saved version O!'
## 'Successfully saved version P!'
## 'Successfully saved version Q!'
## 'Successfully saved version R!'
## 'Successfully saved version S!'
## 'Successfully saved version T!'

看起来成功了!我已经将这些输出放在 repo 的outputs_example文件夹中。

将它导入到 R 中,并使用 Tidyverse 完成一个简洁的更新工作流

为了在 R 中使用我们伟大的 python 函数edit_pres.py,R 需要知道在哪里可以找到包含它所使用的安装包的 Python 环境。最简单的方法是在 R 项目中创建一个名为.Rprofile的文件,并用它来设置RETICULATE_PYTHON环境变量。这将需要设置为 Python 环境中编写该函数的 Python 可执行文件的路径。下面是我的.Rprofile中的一个例子:

Sys.setenv(RETICULATE_PYTHON="/home/rstudio/.local/share/r-miniconda/envs/pptx/bin/python3")

为了让这个新变量生效,您需要重启 R。一旦 R 重启,项目中的任何 Python 代码都将由RETICULATE_PYTHON定义的 Python 可执行文件执行。

设置好 Python 环境后,我们可以使用reticulate包将 Python 函数加载到 R 中。这样,它立即成为一个 R 函数,可以处理 R 输入。

library(reticulate)source_python("edit_pres.py")edit_pres## <function edit_pres at 0x7fb40af17ef0>

我们可以将所有数据作为数据帧载入,并测试该功能是否有效:

# load in data files
for (file in list.files("data")) {
  splits <- strsplit(file, "\\.")
  assign(splits[[1]][1],
         read.csv(paste0("data/", file)))
} # test edit_pres function on Group M
edit_pres("M", chart_df, table_M, "templates/ppt-template.pptx", "test4.pptx")## [1] "Successfully saved version M!"

使用dplyr在一个整洁的表格中完成这一切

我们的chart_df对象是一个常规的 dataframe,其中每一行代表每个销售组的图表数据。然而,我们的表数据都存储在不同的数据帧中。我们可以添加一个列表列,通过在group列上使用 mutate 来捕获所有不同的表数据集,使其与我们的图表数据保持一致:

library(dplyr)full_data <- chart_df %>% 
  dplyr::rowwise() %>% 
  dplyr::mutate(
    table = list(get(paste0("table_", group)))
  )

如果我们检查一些列,我们可以看到我们的表存储在full_data数据帧的行中。

full_data %>% 
  dplyr::select(group, starts_with("pie"), table)## # A tibble: 20 x 6
## # Rowwise: 
##    group  pie1  pie2  pie3  pie4 table           
##    <chr> <dbl> <dbl> <dbl> <dbl> <list>          
##  1 A       4.3   5.5   1.8   1.2 <df[,5] [8 × 5]>
##  2 B       2.2   2.7   4.6   2.3 <df[,5] [8 × 5]>
##  3 C       4.1   5.1   3.2   4.4 <df[,5] [8 × 5]>
##  4 D       5     5.7   1.3   5.9 <df[,5] [8 × 5]>
##  5 E       5.1   5     0.4   5.3 <df[,5] [8 × 5]>
##  6 F       3.9   1.2   5.2   1.9 <df[,5] [8 × 5]>
##  7 G       5.7   5.3   5.4   5   <df[,5] [8 × 5]>
##  8 H       3.5   1.5   4.5   3.5 <df[,5] [8 × 5]>
##  9 I       4.4   5.4   4     0.7 <df[,5] [8 × 5]>
## 10 J       0.7   6     2.7   5.5 <df[,5] [8 × 5]>
## 11 K       2     4.8   4.4   1.6 <df[,5] [8 × 5]>
## 12 L       2.8   1.6   1.1   0.5 <df[,5] [8 × 5]>
## 13 M       3.3   3.9   0.6   2.4 <df[,5] [8 × 5]>
## 14 N       4.2   2.2   2.5   5.7 <df[,5] [8 × 5]>
## 15 O       5.6   4.5   5     2.7 <df[,5] [8 × 5]>
## 16 P       0.5   2.3   3.5   2.1 <df[,5] [8 × 5]>
## 17 Q       1     2.4   0.5   3.4 <df[,5] [8 × 5]>
## 18 R       2.4   2.1   1.2   0.9 <df[,5] [8 × 5]>
## 19 S       3.8   0.1   2.2   0.1 <df[,5] [8 × 5]>
## 20 T       1.1   4     2     3.1 <df[,5] [8 × 5]>

现在是最后的魔术步骤。我们可以做进一步的改变,在这个数据帧的行上运行我们的 Python 函数,以编写我们所有的 Powerpoint 文档:

# create outputs directory if it doesn't exist
if (!dir.exists("outputs")) {
  dir.create("outputs")
}# rowwise mutate to run function for all groups
write_pptx <- full_data %>% 
  dplyr::rowwise() %>% 
  dplyr::mutate(
    pptx = edit_pres(group, ., table, 
                     "templates/ppt-template.pptx", 
                     paste0("outputs/results_group_", group, ".pptx" ))
  )

这个新的数据框将包含一个新列,其中包含写入文件的确认,您可以在outputs文件夹中查找并检查它们。

write_pptx %>% 
  dplyr::select(group, starts_with("pie"), table, pptx)## # A tibble: 20 x 7
## # Rowwise: 
##    group  pie1  pie2  pie3  pie4 table            pptx                         
##    <chr> <dbl> <dbl> <dbl> <dbl> <list>           <chr>                        
##  1 A       4.3   5.5   1.8   1.2 <df[,5] [8 × 5]> Successfully saved version A!
##  2 B       2.2   2.7   4.6   2.3 <df[,5] [8 × 5]> Successfully saved version B!
##  3 C       4.1   5.1   3.2   4.4 <df[,5] [8 × 5]> Successfully saved version C!
##  4 D       5     5.7   1.3   5.9 <df[,5] [8 × 5]> Successfully saved version D!
##  5 E       5.1   5     0.4   5.3 <df[,5] [8 × 5]> Successfully saved version E!
##  6 F       3.9   1.2   5.2   1.9 <df[,5] [8 × 5]> Successfully saved version F!
##  7 G       5.7   5.3   5.4   5   <df[,5] [8 × 5]> Successfully saved version G!
##  8 H       3.5   1.5   4.5   3.5 <df[,5] [8 × 5]> Successfully saved version H!
##  9 I       4.4   5.4   4     0.7 <df[,5] [8 × 5]> Successfully saved version I!
## 10 J       0.7   6     2.7   5.5 <df[,5] [8 × 5]> Successfully saved version J!
## 11 K       2     4.8   4.4   1.6 <df[,5] [8 × 5]> Successfully saved version K!
## 12 L       2.8   1.6   1.1   0.5 <df[,5] [8 × 5]> Successfully saved version L!
## 13 M       3.3   3.9   0.6   2.4 <df[,5] [8 × 5]> Successfully saved version M!
## 14 N       4.2   2.2   2.5   5.7 <df[,5] [8 × 5]> Successfully saved version N!
## 15 O       5.6   4.5   5     2.7 <df[,5] [8 × 5]> Successfully saved version O!
## 16 P       0.5   2.3   3.5   2.1 <df[,5] [8 × 5]> Successfully saved version P!
## 17 Q       1     2.4   0.5   3.4 <df[,5] [8 × 5]> Successfully saved version Q!
## 18 R       2.4   2.1   1.2   0.9 <df[,5] [8 × 5]> Successfully saved version R!
## 19 S       3.8   0.1   2.2   0.1 <df[,5] [8 × 5]> Successfully saved version S!
## 20 T       1.1   4     2     3.1 <df[,5] [8 × 5]> Successfully saved version T!

扩展这项工作

您可以扩展这项工作,创建一个非常强大的报告基础结构,如下所示:

  • 使用数据库连接来查询 Powerpoint 文档所需的数据
  • 使用 web 前端(例如在 Shiny 或 Django 中),通过查询后端数据库、写入模板和提供下载的新文件,按需生成 Powerpoint。

最初我是一名纯粹的数学家,后来我成为了一名心理计量学家和数据科学家。我热衷于将所有这些学科的严谨性应用到复杂的人的问题上。我也是一个编码极客和日本 RPG 的超级粉丝。在 LinkedIn Twitter上找我。也可以看看我在drkeithmcnulty.com的博客。

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

pixabay.com 的好意

用 OpenAi 的 Github Copilot 生成 Python 脚本

原文:https://towardsdatascience.com/generating-python-scripts-with-openais-github-copilot-da0b3fdd989?source=collection_archive---------14-----------------------

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

照片由约书亚·阿拉贡Unsplash 拍摄

使用人工智能为简单的神经网络、数据可视化等生成 Python 脚本

我已经有一段时间没有接触到 OpenAi 的 Github copilot 的技术预览了。从那以后,我开始喜欢以函数名和描述的形式问它各种各样的问题,看看它能写出什么样的代码。

在本文中,我将分享我是如何使用 Github Copilot extension for VS Code(技术预览版)生成 Python 脚本的,从 Keras 中简单的神经网络和数据可视化脚本到关于存在秘密的备注

使用 Github Copilot 生成脚本

当你去掉所有关于像 GPT 3 这样的语言模型的天花乱坠和启示录式的谈论,并真正开始使用它们时,你会意识到这种应用范围的好、坏和丑陋。

通过揭示它们的真正潜力,我们可以评估这个令人难以置信的工具,它可能对无数不同的问题有潜在的用处(假设有效的关注得到解决),以及了解它的技术限制,例如它缺乏对基本句子的真正的人类上下文理解。

带有 Keras 的简单神经网络

让我们从 Keras 中的一个简单的神经网络开始。对于第一个脚本,我给模型的输入是:

def SimpleNeuralNetKeras():
    pass

人工智能生成的自动完成的输出是这样的:

def SimpleNeuralNetKeras():
    net_net = Sequential()
    net_net.add(Dense(units=1, input_dim=1))
    net_net.compile(loss='mean_squared_error', optimizer='adam')
    net_net.fit(x_train, y_train, epochs=100, batch_size=1, verbose=0)
    net_net.evaluate(x_test, y_test, batch_size=1, verbose=0)
    net_net.predict(x_test, batch_size=1, verbose=0)
    net_net.save('my_model.h5')
    net_net = load_model('my_model.h5')
    net_net.predict(x_test, batch_size=1, verbose=0)
    net_net.evaluate(x_test, y_test, batch_size=1, verbose=0)
    net_net.fit(x_train, y_train, epochs=100, batch_size=1, verbose=0)
    net_net.evaluate(x_test, y_test, batch_size=1, verbose=0)
    net_net.predict(x_test, batch_size=1, verbose=0)
    net_net.save('my_model.h5')
    """....it goes on and on"""

尽管它继续建议对相同的模型进行再训练,但如果我们去掉脂肪,我们得到的是:

def SimpleNeuralNetKeras():
    net_net = Sequential()
    net_net.add(Dense(units=1, input_dim=1))
    net_net.compile(loss='mean_squared_error', optimizer='adam')
    net_net.fit(x_train, y_train, epochs=100, batch_size=1, verbose=0)
    net_net.evaluate(x_test, y_test, batch_size=1, verbose=0)
    net_net.predict(x_test, batch_size=1, verbose=0)
    net_net.save('my_model.h5')

老实说!一点都不差!让我们看看当我要求它创建一个假数据集来匹配这个神经网络设置时会发生什么:

我在这里的输入很简单:

x_train,

我得到的回答是:

x_train,y_train,x_test,y_test = get_data()

有意思。让我们看看这个模型是否能为我们写出get_data()函数。

我对此的看法是:

def get_...

实际上就是这样,我自动得到的是:

def get_data():
    """
    This function is used to get the data for the neural network.
    """
    # Load the data
    data = np.loadtxt('data.csv', delimiter=',')
    # Split the data
    x = data[:, :-1]
    y = data[:, -1]
    # Split the data
    x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=42)
    return x_train,y_train,x_test,y_test

它看起来确实很整洁,虽然在其他小细节中,xy的解包看起来有点奇怪,但是,它看起来确实像一段只需稍加调整就可以运行的代码。

数据可视化

密谋怎么样?我们能得到一些合成数据的图表吗?

这也是我对模型的输入:

def plotFakeData():
    """
    This function creates a fake dataset of some 
    normally distributed data and plots the result
    of passing it through a sin function.
    """

这是我得到的:

def plotFakeData():
    """
    This function creates a fake dataset of some 
    normally distributed data and plots the result
    of passing it through a sin function.
    """
    import numpy as np
    import matplotlib.pyplot as plt
    # Create some fake data
    x = np.linspace(0, 10, 100)
    y = np.sin(x) + np.random.normal(0, 0.1, 100)
    # Plot the data
    plt.plot(x, y)
    plt.show()

看起来很近!我们要测试一下吗?

plotFakeData()

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

它真的跑了!多酷啊。

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

米 PHAM 在 Unsplash 上的照片

虽然创建的数据不是正态分布的(我的意思是这只是我脑海中出现的随机现象),但该模型在将数据点通过 sin 函数后,确实向数据点序列添加了正态分布的噪声,之后它成功绘制了数据。

写作测试

现在,为已经定义的函数编写测试怎么样?

这里我的输入是:

def sum_Square(a,b):
    return (a+b)**2

def test_sum_Square():
    pass

我得到了什么:

def test_sum_Square():
    assert sum_Square(2,3) == 25
    assert sum_Square(3,5) == 55
    assert sum_Square(3,5) != 56test_sum_Square()# Output (from running it on a jupyter notebook)

AssertionError                            Traceback (most recent call last)

<ipython-input-94-b8fb676bf724> in <module>
----> 1 test_sum_Square()

<ipython-input-93-bf52191596f9> in test_sum_Square()
      1 def test_sum_Square():
      2     assert sum_Square(2,3) == 25
----> 3     assert sum_Square(3,5) == 55
      4     assert sum_Square(3,5) != 56

AssertionError: 

还不错!实际上,第一个和第三个测试是正确的,第二个就不那么正确了,因为对于 3 和 5,预期的结果应该是 64。然而,令人印象深刻的是,这个模型实际上仅仅从一个简单的函数定义就可以做这种开箱即用的事情。

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

照片由加布里埃拉·克莱尔·马里诺Unsplash 拍摄

使用 github copilot 获得哲理

在玩了模型的潜在有用应用程序后,我决定,只是为了好玩,问一些随机的伪哲学问题,看看模型会得出什么样的答案。

我的意见:

def writeArticleAboutSecretOfExistence():
    pass

我得到了什么:

def writeArticleAboutSecretOfExistence():
    """
    The secret of existence is to be one.
    """

这是一篇短文,但至少作为一个句子,它确实有一定的意义。我绝对能想象出一个老哲学家或僧侣给一个在假想的智慧山中某处寻求知识的旅行者提这个建议。

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

Holly Mandarich 在 Unsplash 上拍摄的照片

当然,这些函数应该是代码,但我只是玩玩而已;).

另一个:

def writeArticleAboutHowToSolveAnyProblem():
    pass

我有:

def writeArticleAboutHowToSolveAnyProblem():
    """
    The secret of solving any problem is to think about it in another way.
    """
    pass

好了,现在你知道了,换个方式想想你的问题,嘣!你解决了!

关于人工智能辅助编程的最后评论

我认为人工智能辅助编程的未来看起来是光明的,尽管要成为现实世界的解决方案还需要解决一些问题

随着像这样的模型越来越多地了解程序员关于代码的意图,编写好代码所需的时间可能会减少很多,我认为这可能会有惊人的好处,允许程序员专注于更重要的全局问题。

如果你想开始玩 github copilot,注册他们的等待列表以获得技术预览。

如果你喜欢这篇文章,请在媒体上关注我,订阅我的简讯,在推特LinkedInInstagram加入媒体与我联系!谢谢,下次再见!😃

参考

用 Python 生成二维码,不到 10 行

原文:https://towardsdatascience.com/generating-qr-codes-with-python-in-less-than-10-lines-f6e398df6c8b?source=collection_archive---------2-----------------------

构建一个简单的 Python 项目,用 QR 码加密您的信息

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

马库斯·温克勒在 Unsplash 上的照片

在现代世界中,我们的目标是始终拥有一种安全便捷的访问方式。没有人想阅读和点击拉长的 URL 链接或冗长的单词序列。此外,在最近的疫情世界中,人们通常认为最好避免接触,在没有太多身体接触的情况下完成交易。

这一目标是借助条形码和 QR 码实现的。条形码受到一些间距限制,这通过引入 QR 码来解决。QR 码是典型的二维象形码,以在白色背景上排列成正方形图案的黑色模块的形式,为用户提供大存储容量和快速可读性。

二维码是一种极好的资源,可用于跟踪众多产品的信息、交换数据、引导客户访问登录页面或网站、下载应用程序、支付账单(在餐馆或其他地方)、购物、电子商务等等!

在本文中,我们将学习如何利用 Python 编程来创建用于任何特定目的的 QR 码。我们将生成一些用于特定目的的条形码,并通过一些解码步骤了解如何解码这些生成的代码。最后,我们将看看一些额外的东西,你可以完成的编码和解码二维码。

安装所有必需的库:

为了开始这个项目,Python 中有一些库要求,我们将确保在我们的系统上成功安装,以创建、生成和解码 QR 码。我们将安装的第一个二维码编码库是二维码库。

开始安装 qrcode 库模块的命令非常简单,可以使用以下 pip 命令进行安装。如果您相应地设置了环境变量的路径,您可以在您选择的虚拟环境中或者直接在命令提示符(或 windows shell)中添加以下命令行。

pip install qrcode

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

确保在特定的 Python 环境中也安装了 Pillow 库。这个库是操作图像和处理与视觉美学相关的大多数功能的最佳选择之一。以下命令块中显示的替代命令将安装两个基本库和附加枕形库,用于生成将被存储的 QR 码图像。

pip install qrcode[pil]

我们成功完成这个项目所需的最后一个库是计算机视觉库 Open-CV。下面的库是大多数与图像处理和计算机视觉相关的任务的重要元素之一。本项目的这个模块的目的是利用它的一个重要功能来解码生成的 QR 码中的隐藏信息。该库可以用下面的命令安装。

pip install opencv-python

计算机视觉是数据科学和人工智能最有趣的方面之一。这个主题一直在蓬勃发展,并且在未来几年将会越来越受欢迎。因此,我建议对这一领域感兴趣的观众从下面的链接查看我的 Open-CV 初学者入门指南,开始学习计算机视觉的所有基本概念。

编码您的秘密二维码:

在本文的这一部分,我们将利用 qrcode 库对我们的信息进行编码,并生成一个快速响应代码,我们可以通过一些解码来访问它。要生成二维码,请遵循下面提供的代码片段,您将获得特定二维码的图像以及存储在其中的相关数据。

import qrcode# Create The variable to store the information
# link = "[https://bharath-k1297.medium.com/membership](https://bharath-k1297.medium.com/membership)"
data = "Hello! Welcome To World Of Programming!"# Encode The Link
img = qrcode.make(data)
print(type(img))# Save the QR Code
img.save("test1.jpg")

编码所需代码的第一步是导入我们之前安装的 qrcode 库。导入库后,我们可以创建一个变量来存储特定网站的链接,也可以创建一个变量来存储一些以 QR 码形式嵌入的有用信息。将链接编码成图像的形式,并将现在生成的 QR 码保存在您想要的文件名中。当您打印生成的图像的类型或格式时,您应该注意到显示的以下类—

<class 'qrcode.image.pil.PilImage'>

现在,我们已经学习了如何以 QR 码图像的形式对数据进行编码,让我们探索一些可以解码以下数据的方法。

解码秘密二维码:

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

作者图片

上面的图像表示是包含链接的 QR 码的表示。如果您试图访问带有 URL 链接的二维码,请尝试使用手机应用程序来解码此类二维码或任何其他应用程序来读取二维码。上面的二维码,当被一个应用程序读取时,会引导你到提供的 URL 网站。(以下链接支持其他作者和我如果申请会员)。

要解码如上图所示的 URL 链接,您可以使用 QR 码扫描仪。但是,如果您试图访问加密数据,您可以在 Open-CV 的帮助下解码信息。QR 码检测器功能为用户提供了解码特定 QR 码图像和检索 QR 码中存储的数据的选项。请查看下面的代码片段,了解您可以执行以下操作的简要想法。

import cv2# Create The Decoder
decoder = cv2.QRCodeDetector()# Load Your Data
file_name = "test1.jpg"
image = cv2.imread(file_name)# Decode and Print the required information
link, data_points, straight_qrcode = decoder.detectAndDecode(image)
print(link)

这里,我们导入 cv2 库并创建一个变量,该变量将作为解码特定 QR 码图像的解码器。然后,我们将继续加载数据,并在 cv2 库的帮助下读取数据。然后我们可以访问数据并相应地打印信息。下面的截图显示了我的输出。注意,我在 tensors 虚拟环境中运行 decode.py 文件中的解码器代码。

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

其他构建模块:

在本节中,我们将了解您可以对这个 Python 项目进行的一些改进。首先,如果你正在为一个特定的目的开发你的项目,如启动或任何其他服务,或者只是为了好玩,你可以添加一个产品、品牌或你自己的迷你标志作为 QR 码的一个组成部分,以避免混淆,并有一个清晰的项目表示。

我们可以对项目进行的下一个改进是控制生成的 QR 码。下面显示的代码块演示了如何相应地执行这样的过程。版本属性决定了二维码的矩阵大小。使用错误连接属性来分析用于 QR 码扫描的错误校正。方框大小是每个方框的像素大小,边框控制粗细。我建议尝试下面的代码块。

import qrcodeqr = qrcode.QRCode(
    version=1,
    error_correction=qrcode.constants.ERROR_CORRECT_L,
    box_size=10,
    border=4,
)

结论:

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

Unsplash 上由 Toa Heftiba 拍摄的照片

QR 码在当今的现代世界中非常重要,在这里,大多数交易和有用的数据都是通过最技术化的机制以最少的物理接触来传递的。无论您是想要交换信息、进行交易,还是简化指定特定网站的基本 URL 链接,这些二维码都是非常有用的资源。

在本文中,我们了解了借助 Python 编程,用不到十行代码生成 QR 码是多么容易。安装所需的库后,您可以生成自己的二维码,并对其进行相应的解码。您可以在这些二维码中嵌入有用的 URL 链接或重要信息,并以简单、高度结构化的格式传达给其他人。

如果你想在我的文章发表后第一时间得到通知,请点击下面的链接订阅邮件推荐。如果你希望支持其他作者和我,请订阅下面的链接。

https://bharath-k1297.medium.com/membership

二维码的技术相当具有革命性,它将继续存在,直到有更好的发现取代它。因此,现在是开始探索这个话题的好时机。如果你对这篇文章中提到的各点有任何疑问,请在下面的评论中告诉我。我会尽快给你回复。

看看我的其他一些文章,你可能会喜欢读!

</5-best-python-projects-with-codes-that-you-can-complete-within-an-hour-fb112e15ef44> </7-best-ui-graphics-tools-for-python-developers-with-starter-codes-2e46c248b47c>

谢谢你们坚持到最后。我希望你们都喜欢这篇文章。祝大家有美好的一天!

在 Matlab 和 Numpy 中生成随机数和数组

原文:https://towardsdatascience.com/generating-random-numbers-and-arrays-in-matlab-and-numpy-47dcc9997650?source=collection_archive---------8-----------------------

Matlab 和 Numpy 码再现随机数和数组的比较

正如我们所知, Numpy 是一个著名的 Python 库,用于支持 Python 中的矩阵计算,以及一个大型的高级数学函数集合,用于操作向量、矩阵和张量数组[1]。 Matlab 是一种编程语言和数值计算环境,支持矩阵计算,绘制函数和数据,实现算法,创建接口,以及与其他语言编写的程序接口[2]。

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

顶部面板:Numpy logo[3];底部面板:Matlab 徽标[4]。

Numpy 和 Matlab 的一个共同特点是它们广泛用于矩阵计算和数值计算。然而,它们并不完全相同。在这篇文章中,我们将讨论如何在 Matlab 和 Numpy 中生成随机数和数组。特别地,我们比较了 Matlab 和 Numpy 对相同随机数和数组的再现。

随机数和数组

Matlab 和 Numpy 都可以根据某个命令生成随机数和数组。有两个关键概念:

  • 随机数分布
  • 随机种子

对于随机数分布,我们通常考虑均匀分布和标准正态(高斯)分布。在 Numpy 中,我们可以使用numpy.random.rand来生成均匀分布的随机数。在 Matlab 中,我们可以使用rand来生成均匀分布的随机数。以下是一些简单的例子:

Python 中的 Numpy:

import numpy as npsample = np.random.rand(2)
print(sample)

输出是:

[0.70573498 0.8595017 ]

Matlab:

sample = rand(1, 2)

输出是:

ans =

   0.5390   0.7686

上面的例子是关于均匀分布的随机数。我们可以生成遵循标准正态分布的随机数:

  • Python 中的 numpy:np.random.randn
  • Matlab: randn

可以使用某个命令/函数来生成遵循某个特定分布的随机数,但是每次我们复制代码时,生成的随机数都会不同。因此,随机种子是另一个重要的概念,它允许在每个时间固定随机数。

例如,以下 Python 代码:

import numpy as np
np.random.seed(10)sample = np.random.rand(2)
print(sample)

会产生这些随机数:

[0.77132064 0.02075195]

在 Matlab 中:

rng(10);
sample = rand(1, 2)

我们有以下输出:

sample =0.7713    0.0208

Numpy 和 Matlab 中 Rand 函数的比较

在 Numpy 和 Matlab 中,它们可以处理不同数组的计算:

  • 1-D 数组(一维数组)是指向量。
  • 2-D 数组(二维数组)指矩阵。
  • 3-D 数组(三维数组)指的是三阶张量。
  • ……
  • n -D 数组(n-维数组)指的是 n 阶张量。

接下来,我们将分别在 Numpy 和 Matlab 中尝试生成均匀分布的随机数。我们还将尝试在 Numpy 和 Matlab 中生成相同的随机数。

生成一维数组

为了在 Numpy 和 Matlab 中获得相同的均匀分布的随机数,我们将向量大小设置为 4,随机种子设置为 10。让我们试试吧!

Numpy :

import numpy as np
np.random.seed(10)sample = np.random.rand(4)
print(sample)

运行它,我们有

[0.77132064 0.02075195 0.63364823 0.74880388]

Matlab :

rng(10);
sample = rand(1, 4)

运行它,我们有

sample = 0.7713    0.0208    0.6336    0.7488

显然,两个生成的随机向量是相同的。

生成二维数组

首先,我们设置矩阵大小为 2 乘 3,随机种子为 10。

Numpy :

import numpy as np
np.random.seed(10)sample = np.random.rand(2, 3)
print(sample)

运行它,我们有

[[0.77132064 0.02075195 0.63364823]
 [0.74880388 0.49850701 0.22479665]]

Matlab :

rng(10);sample = rand(2, 3)

运行它,我们有

sample = 0.7713    0.6336    0.4985
    0.0208    0.7488    0.2248

生成的均匀分布随机矩阵是相同的。

生成三维数组

首先,我们将矩阵大小设置为 2 乘 3 乘 2,并将随机种子设置为 10。

Numpy :

import numpy as np
np.random.seed(10)sample = np.random.rand(2, 3, 2)
print(‘sample[:, :, 0] = ‘)
print()
print(sample[:, :, 0])
print()
print(‘sample[:, :, 1] = ‘)
print()
print(sample[:, :, 1])

运行它,我们有

sample[:, :, 0] = 

[[0.77132064 0.63364823 0.49850701]
 [0.19806286 0.16911084 0.68535982]]

sample[:, :, 1] = 

[[0.02075195 0.74880388 0.22479665]
 [0.76053071 0.08833981 0.95339335]]

Matlab :

rng(10);sample = rand(2, 3, 2)

运行它,我们有

sample(:,:,1) = 0.7713    0.6336    0.4985
    0.0208    0.7488    0.2248sample(:,:,2) = 0.1981    0.1691    0.6854
    0.7605    0.0883    0.9534

生成的均匀分布的随机张量是相同的。

在 Numpy 和 Matlab 中生成正态分布随机数

在上面,如果我们使用相同的随机种子,Numpy 和 Matlab 可以产生相同的均匀分布的随机数。不幸的是,由于 Numpy 和 Matlab 使用不同的转换来从标准正态分布生成样本,因此我们需要在 Numpy 和 Matlab 中使用相同的转换。

在实践中,仍然可以像 Numpy 一样再现 Matlab 的 randn()的输出。

数量:

import numpy as np
from scipy.stats import norm
np.random.seed(10)sample = norm.ppf(np.random.rand(2, 3))
print(sample)

运行它,我们有

[[ 0.74320312 -2.03846052  0.34153145]
 [ 0.67073049 -0.00374237 -0.75609325]]

Matlab:

rng(10);
sample = norminv(rand(2, 3), 0, 1)

运行它,我们有

sample = 0.7432    0.3415   -0.0037
   -2.0385    0.6707   -0.7561

生成的正态分布随机矩阵是相同的。

参考

[1]维基百科上的 Numpy:https://en.wikipedia.org/wiki/NumPy

[2] Matlab 上的维基百科:https://en.wikipedia.org/wiki/MATLAB

[3] Numpy 标志来自https://commons.wikimedia.org/wiki/File:NumPy_logo_2020.svg

[4] Matlab logo 出自https://www.google.com/url?esrc=s&q =&RCT = j&sa = U&URL = https://1000 logos . net/Matlab-logo/&ved = 2 ahukewj 24 b 7c 7 bvzahukoxiehic i3 adqqr4 kdegqiehac&usg = aovvaw 2 jkoiqdedkheednpnpm 7 acw

[5]在 Matlab 和 Python / NumPy 中再现随机数。GitHub 网站:https://github.com/jonasrauber/randn-matlab-python

【6】有没有可能用 NumPy 重现 MATLAB 的 randn()。https://stack overflow . com/questions/3722138/is-may-to-reproduct-randn-of-MATLAB-with-numpy

[7]比较 Matlab 和使用随机数生成的 Numpy 代码。https://stack overflow . com/questions/18486241/comparisng-MATLAB-and-numpy-code-that-uses-random-numbery-generation

使用深度卷积生成对抗网络生成海洋塑料的合成图像

原文:https://towardsdatascience.com/generating-synthetic-images-of-marine-plastic-using-deep-convolutional-generative-adversarial-60e6178c5aa6?source=collection_archive---------21-----------------------

建立一种能够使用 GANs 合成海洋塑料图像的生成方法

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

训练我们的 DCGAN 模型后生成的合成图像

问题陈述

过去十年,海洋塑料污染一直处于气候问题的前沿。海洋中的塑料不仅能够通过窒息或饥饿杀死海洋生物,而且也是通过捕集二氧化碳使海洋变暖的主要因素。近年来,已经有很多尝试来清理环绕我们海洋的塑料,例如非营利组织海洋清理。大量清理过程的问题是,它需要人力,并且不具有成本效益。已经有很多研究通过使用计算机视觉和深度学习来自动完成这一过程,以检测海洋废弃物,利用 ROV 和 AUV 进行清理。

注意:这是理论上的,我们正在努力发表我们的论文。一旦它被同行评审并在杂志上发表,我会更新这篇文章。所以,请关注我们学术论文的发布空间!

阅读资源 : 我们关于使用 CV 和 DL 检测表层塑料的论文明尼苏达大学关于通用海洋垃圾检测算法的论文,以及海洋清洁组织关于河流上漂浮塑料检测的论文。

这种方法的主要问题是关于训练计算机视觉模型的数据集的可用性。JAMSTEC-JEDI 数据集是日本沿海海底海洋废弃物的良好集合。但是,除了这个数据集之外,数据集的可用性存在巨大差异。为此,我利用了生成性对抗网络的帮助;具体来说,DCGAN 可以筛选合成数据集,这些数据集在理论上可以是真实数据集的近似副本。(我是从理论上写的,因为有很多变量,如可用的真实图像的质量、GANs 的进展、培训等)。

GAN 和 DCGAN

GANs 或生成对抗网络是由 Ian Goodfellow 等人在 2014 年提出的。GANs 由两个简单的组件组成,称为生成器和鉴别器。该过程的一个过度简化如下:生成器的作用是生成新数据,鉴别器的作用是区分生成的数据和实际数据。在理想情况下,鉴别器无法区分生成的数据和真实数据,从而产生理想的合成数据点。

DCGAN 是上述 GAN 架构的直接扩展,只是它分别在鉴别器和发生器中使用了深度卷积层。最早是由拉德福德等人描述的。al 在论文中用深度卷积生成对抗网络进行无监督表示学习。鉴别器由步进卷积层组成,而发生器由卷积转置层组成。

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

甘建筑(来源:此处)

PyTorch 实现

在这个方法中,我们将在 DeepTrash 数据集**(引用链接:https://zenodo.org/record/5562940#.YZa9Er3MI-R)上应用 DCGAN 架构,在** 知识共享署名 4.0 国际 许可下发布。如果你不熟悉 DeepTrash 数据集,可以考虑阅读我的论文一种使用深度视觉模型量化表层绑定塑料的机器人方法。DeepTrash 是海洋表层和深海层塑料图像的集合,用于使用计算机视觉进行海洋塑料检测。

让我们开始编码吧!

代码

安装要求

我们首先安装构建 GAN 模型的所有基本需求,比如 Matplotlib 和 Numpy。我们还将利用 Pytorch 的所有工具(如神经网络、转换)。如果您不熟悉 PyTorch,我建议您阅读这篇文章:

基本安装要求

初始化我们的超参数

这一步相当简单。我们要设置超参数来训练神经网络。这些超参数直接从论文和 PyTorch 关于训练 GANs 的教程中借用。

发生器和鉴别器架构

现在,我们定义生成器和鉴别器的架构。

定义培训功能

在定义了生成器和鉴别器类之后,我们继续定义训练函数。训练函数接受生成器、鉴别器、优化函数和历元数作为参数。我们通过递归调用训练函数来训练生成器和鉴别器,直到达到所需的历元数。我们通过遍历数据加载器,用来自生成器的新图像更新鉴别器,并计算和更新损失函数来实现这一点。

监控和培训 DCGAN

在我们建立了生成器、鉴别器和 train 函数之后,最后一步是简单地调用 Train 函数来获得我们定义的历元数。我还使用了 Wandb 来监控我们的训练。

结果

我们绘制了培训过程中发生器和歧视造成的损失。

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

训练期间发生器和鉴别器损耗

我们还可以调出生成器如何生成图像的动画,看看真实图像和虚假图像之间的区别。

大概是这样的:

以及训练后的最终结果图像(与上述图像相同)。

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

结论

在本文中,我们讨论了使用深度卷积生成对抗网络来生成海洋塑料的合成图像,研究人员可以使用这些图像来扩展他们当前的海洋塑料数据集。这有助于让研究人员能够通过混合真实和合成图像来扩展他们的数据集。正如你所看到的结果,GAN 仍然需要大量的工作。海洋是一个复杂的环境,具有变化的光照、混浊度、模糊度等。但这是一个理论起点,其他研究人员可以以此为基础。如果您对改善结果和构建更好的网络架构感兴趣,请联系 gautamtata.blog@gmail.com 大学的我。

用 Copulas 生成综合多元数据

原文:https://towardsdatascience.com/generating-synthetic-multivariate-data-with-copulas-edd1c4afa1bb?source=collection_archive---------17-----------------------

创建更多与您的数据具有相同要素依赖关系的数据

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

五月在 Unsplash 拍摄的

A Copula 是多元累积分布函数,其中每个变量的边际概率分布在区间[0,1]上是均匀的。

但是这到底是什么意思呢?

当您需要对多元分布的依赖结构进行建模时,可以使用 Copulas。例如,在金融中经常使用来捕捉多个时间序列之间的依赖结构。然而,copulas 在非平稳数据上不是很好定义的。

Copulas 用于模拟随机变量之间的相关性。Copulas 的基础是围绕 Sklar 定理展开的。

斯克拉尔定理:

任何多元联合分布都可以用一元边际分布函数和描述变量相关结构的 copula 来表示。

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

Sklar 定理(作者供图)

这是什么意思?这意味着数据的多元联合分布可以使用边际和 Copula 进行建模。

好吧,当然,但我为什么要知道这个?为什么理解多元联合分布有帮助?

生成多元数据

在 python 中为单个变量创建概率密度函数非常容易。例如,Scipy 的函数“rv_histogram”生成一个概率分布,您可以根据一些数据从中进行采样。

下面我有一个这样做的例子。首先,我使用虹膜数据集中带有“萼片长度”的 NumPy 直方图生成一个直方图。接下来,使用‘RV _ histogram’函数,我从直方图中创建一个概率分布。最后,利用这种分布,对 100 个值进行采样,并与原始数据集进行比较。

import scipy.stats
import numpy as np
import matplotlib.pyplot as pltbins= 40
hist = np.histogram(df[cols[0]], bins=bins)
hist_dist = scipy.stats.rv_histogram(hist)
synthetic_data = hist_dist.rvs(size=100)

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

创建萼片长度的概率分布(作者照片)

但是当你想生成多元数据的时候呢?

希望很明显,为每个特征创建数据并将其组合是非常有缺陷的。这里我们可以使用’ Copulas ',专门研究 Copulas 的 python 库。这个库提供了相关的函数来为你所拥有的数据创建一个 copula。copula 表示每个特征之间的依赖关系。

使用分类任务,可以在类级别上生成数据。在下面的代码块中,根据每个类的分布开发了不同的多元数据分布。最后,使用这些分布创建新的合成数据。

def generate_multivariate_data(df, dist, samples=50):
    df_sample = pd.DataFrame({})
    for t in df['target'].unique():
        dist.fit(df[df['target']==t].drop(['target'],axis=1))
        sampled = dist.sample(samples)
        sampled['target'] = t
        df_sample = df_sample.append(sampled)
    return df_sample

copula 软件包提供了一些有用的可视化工具来比较实际数据和生成的数据。但是,它不支持给每个类添加颜色。

我已经调整了 GitHub 的功能,为每个职业保留了一个彩色地图。以下两个函数为实际数据和合成数据创建了两个 3D 散点图。

from copulas.multivariate import GaussianMultivariatedef scatter_3d_color(data, columns=None, fig=None, title=None, position=None):
    """Plot 3 dimensional data in a scatter plot."""
    fig = fig or plt.figure()
    position = position or 111
    ax = fig.add_subplot(position, projection='3d')
    ax.scatter(*(
        data[column] for column in columns or data.columns
    ), c=color_indices, cmap=colormap)
    if title:
        ax.set_title(title)
        ax.title.set_position([.5, 1.05])
    return axdef compare_3d_color(real, synth, columns=None, figsize=(10, 4)):
    columns = columns or real.columns
    fig = plt.figure(figsize=figsize)
    scatter_3d_color(
        real[columns], fig=fig, 
        title='Real Data', position=121
    )
    scatter_3d_color(
        synth[columns], fig=fig, 
        title='Synthetic Data', position=122
    )
    plt.tight_layout()colors = ["blue", "green", "purple"]
color_indices = [0]*50 + [1]*50 + [2]*50
colormap = matplotlib.colors.ListedColormap(colors) dist=GaussianMultivariate()
df_s = generate_multivariate_data(df, dist)
compare_3d_color(df[cols[0:3]], df_s[cols[0:3]])

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

高斯多元 Copula(作者供图)

如果每个特征的单变量分布是已知的,则这些分布被传递到 Copula 中。随后的数据样本用单变量高斯分布估计分布。

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

高斯单变量 Copula(作者供图)

然而,准确地确定数据的分布是相当具有挑战性的。

幸运的是,Copulas 库还为一类分布中的单变量分布估计提供了实用工具。例如,最终图使用参数单变量来生成合成数据。

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

参数单变量 Copula(作者图片)

数据有多好?

为了比较真实数据和合成数据,我使用剪影分数。轮廓分数是对每个聚类被定义得有多好的度量。当真实标签未知时,该分数用于聚类任务。虽然在这种情况下,标签是已知的,但不执行任何预测。因此,我展示了原始数据的侧影得分与合成数据的得分。

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

剪影评分 S(作者照片)

根据底层数据的分布,有几种不同的方法来模拟合成数据。

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

剪影评分比较(作者照片)

当剪影得分为 1 时,聚类的定义最为清晰。然而,即使对于实际数据来说,情况也并非如此。高斯单变量和参数单变量方法得分较高。尽管如此,这里的数据可能不太能代表实际数据。

该过程旨在生成与原始数据集相似的数据。虽然这两种方法表现更好,但多元高斯方法是理想的,因为分数更接近实际数据。目的是模拟实际数据,即使原始数据不是那么可分的。

结论

连接函数是一个迷人的统计函数。对变量之间的依赖结构进行建模的能力对于理解和处理数据是一个有价值的属性。

这些函数还能够生成有效模拟预先存在的多元数据的合成数据。当您想要对多元数据建模或创建一些自定义合成数据时,请考虑使用 copulas。

如果你有兴趣阅读关于新颖的数据科学工具和理解机器学习算法的文章,可以考虑在 Medium 上关注我。

如果你对我的写作感兴趣,想直接支持我,请通过以下链接订阅。这个链接确保我会收到你的会员费的一部分。

https://zjwarnes.medium.com/membership

生成综合表格数据

原文:https://towardsdatascience.com/generating-synthetic-tabular-data-503fe823f377?source=collection_archive---------11-----------------------

学习使用条件生成对抗网络(GAN)生成合成表格数据。

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

海登·邓塞尔在 Unsplash 上拍摄的照片

介绍

之前的文章中,我们介绍了合成数据的概念及其在数据隐私和机器学习中的应用。在本文中,我们将向您展示如何使用生成式对抗网络(GAN)生成合成表格数据。

表格数据是最常见和最重要的数据形式之一。大量的数据,如临床试验记录、财务数据、人口普查结果,都以表格的形式呈现。在不泄露敏感属性和个人身份信息(PII)的情况下使用合成数据集的能力对于遵守隐私法规至关重要,并且便于数据分析、共享和实验。

想知道为什么生成模型是创建合成数据的理想方法吗?嗯,在生成模型中,神经网络(NN)用于逼近高维潜在空间中输入数据的潜在概率分布。在学习了概率分布之后,该模型可以通过从该分布中随机抽样来生成合成记录。因此,生成的记录不包含原始数据本身,但保留了真实数据集的原始基础概率分布。

什么是甘?

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

生成对抗网络

GAN 由两种型号组成:

  • 一个学习制造假数据的生成器。
  • 学习区分生成器的假数据和真实数据的鉴别器。

这两种模式在零和游戏中相互竞争,推动整个系统走向优化。在训练开始时,生成器不太擅长生成假数据,而鉴别器能够很容易地捕捉到假数据。但是随着训练的进行,生成器逐渐学会更好地生成假数据,欺骗鉴别器,直到鉴别器无法辨别输入是真是假。查看 I.Goodfellow et。艾尔看到了甘背后的数学概念。

表格 GAN:

开发一个能够可靠地为表格数据集工作的通用 GAN 并不是一项简单的任务。

挑战包括:

  • 混合数据类型:数字、分类、时间、文本
  • 不同的分布:多峰、长尾、非高斯
  • 不平衡数据集

为了产生高度真实的表格数据,我们将使用条件生成敌对网络——ctgan⁴.该模型由麻省理工学院的徐等人开发,是一个开源的 CTGAN 使用基于 GAN 的方法对表格数据分布进行建模,并对分布中的行进行采样。在 CTGAN 中,利用特定于模式的规范化技术来处理包含非高斯和多峰分布的列,同时使用条件生成器和采样训练方法来应对类不平衡 problems⁴.

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

条件生成器根据其中一个离散列生成合成行。通过采样训练,根据每个类别的对数频率对 cond 和训练数据进行采样,因此 CTGAN 可以均匀地探测所有可能的离散 values⁴.

现在,让我们看看如何利用 CTGAN 从真实数据集生成合成数据集!我们使用 Income⁶人口普查数据集作为示例,该数据集是包中的内置数据集。(记得要pip install ctgan)。

这将加载真实的数据集:

正如我们所看到的,该表包含了关于在职成年人的信息,包括他们的年龄、性别、教育程度、每周工作时间、收入等。这是一个包含分类变量、连续变量和离散变量的多元数据集。现在让我们使用CTGANSynthesizer来创建这个表格数据的合成副本。

这将返回一个与真实数据相同的合成数据表。

现在,让我们检查一下合成数据与真实数据有多相似。为此,我们将使用 table_evaluator ⁷来可视化虚假数据和真实数据之间的差异。(一定要先去pip install table-evaluator

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

每个特征的分布:3 个特征(年龄、职业、每周工作小时数)

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

真实数据和合成数据之间的相关矩阵

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

真实数据和合成数据绝对对数平均值和标准差

查看每个特征图的分布、相关矩阵、绝对对数平均值和标准差图,我们可以看到合成记录很好地代表了真实记录。例如,我们还可以运行table_evaluator.evaluate(target_col='income')来获得每个特性的 F1 分数和 Jaccard 相似性分数。

结论:

在合成数据系列的第二部分中,我们将研究如何使用 CTGAN 生成合成表格数据集。合成数据开启了大规模数据共享、实验和分析的机会,而不会泄露敏感信息。这是一个非常方便的工具!

加入我的 项目 Alesia 了解更多关于机器学习、MLOps、数据隐私、数字福利等更多内容!

https://projectalesia.com/

参考:

  1. 古德费勒、伊恩·j .让·普吉-阿巴迪、迈赫迪·米尔扎、徐炳、戴维·沃德-法利、谢尔吉尔·奥泽尔、亚伦·库维尔和约舒阿·本吉奥。“生成性对抗网络。”arXiv 预印本 arXiv:1406.2661 (2014)。
  2. https://www . freecodecamp . org/news/an-intuitive-introduction-to-generative-adversarial-networks-gans-7a 2264 a 81394/
  3. 徐,李,斯科拉利杜,米,因方特,a .,& Veeramachaneni,K. (2019)。使用条件 gan 对表格数据建模。arXiv 预印本 arXiv:1907.00503。
  4. 徐,李,斯科拉利杜,米,因方特,a .,& Veeramachaneni,K. (2019)。使用条件 gan 对表格数据建模。arXiv 预印本 arXiv:1907.00503。
  5. https://github.com/sdv-dev/CTGAN
  6. https://archive.ics.uci.edu/ml/datasets/adult
  7. https://pypi.org/project/table-evaluator/
  8. 由 Prateek Sanyal 提供的编辑评论

用随机游走生成合成时间序列数据

原文:https://towardsdatascience.com/generating-synthetic-time-series-data-with-random-walks-8701bb9a56a8?source=collection_archive---------24-----------------------

快速创建定制的合成数据来测试您的预测模型

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

Unsplash 上由 Podu Stricat 拍摄的照片

R 随机游走是随机过程(random)。它们由数学空间中的许多步骤组成。最常见的随机游走从值 0 开始,然后每一步以相等的概率加上或减去 1。

随机行走可用于为不同的机器学习应用生成合成数据。例如,当没有信息可用或没有实时数据可用时,具有随机游走的合成数据可以近似实际数据。

本帖利用一维随机游走为时序算法生成数据。

生成数据

创建和测试时间序列模型时,以随机数据作为基线来测试模型是有益的。随机游走可以模拟股票、产能利用率甚至粒子运动的趋势。

通过调整每一步的概率,行为被添加到随机行走中。此外,这些走步被修改为具有不同的步长,以产生更大或更小的波动。

Pandas 中的“日期范围”功能可以快速生成时间序列数据。以下是 2019 年每天用一个随机值生成数据框的示例。

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import randomDATE_START = '2019-01-01'
DATE_END = '2019-12-31'dates = pd.date_range(DATE_START, DATE_END)
df = pd.DataFrame({
    'date': dates,
    'value': np.random.normal(0,1,dates.size)
})
df.set_index('date', inplace=True)
plt.plot(df['value'])
plt.ylabel('Value')
plt.xlabel('Date')
plt.title('Random Values')
plt.show()

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

一段时间内的随机值(作者提供照片)

随机漫步

虽然这里的数据可用于时间序列模型,但看不到任何模式。由于实际数据包含与先前点的紧急模式关系,合成数据需要改进。随机行走是生成一些逼真行为的可行解决方案。在 pandas 中创建随机行走需要遍历数据帧的每一行。行走中的每一步都依赖于前一步。

下面是生成随机漫步的代码。第一个“previous_value”作为遍历的起点。接下来,步长设置为 1。最后,“阈值”将积极或消极行走的概率设定为 50%。

此外,随机游走受最小值和最大值的限制。对于许多数据集,如股票价值,这些值是严格正值。

随机游走的图是用“matplotlib”生成的

def random_walk(
    df, start_value=0, threshold=0.5, 
    step_size=1, min_value=-np.inf, max_value=np.inf
):
    previous_value = start_value
    for index, row in df.iterrows():
        if previous_value < min_value:
            previous_value = min_value
        if previous_value > max_value:
            previous_value = max_value
        probability = random.random()
        if probability >= threshold:
            df.loc[index, 'value'] = previous_value + step_size
        else:
            df.loc[index, 'value'] = previous_value - step_size
        previous_value = df.loc[index, 'value']
    return df

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

步长为 1 的随机漫步(作者提供图片)

修改随机漫步

这些随机游走被调整以显示期望的行为。例如,对随机游走的最小值和最大值添加限制可以模拟容量利用率。

随机游走的行为通过改变其他初始条件而被进一步改变,例如,强加一个整体的正趋势。通过调整概率阈值来实现正向趋势。通过增加正向步进的概率,正向趋势被强加于随机行走。对于这个代码,它是通过降低阈值来实现积极的一步。

以这种方式建立随机游走可以更接近股票趋势。如果总体趋势是积极的或消极的,可以将细节纳入综合数据。

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

具有积极趋势和价值限制的随机游走(作者提供图片)

有几个选项可以进一步调整随机游走。例如,在每一步中包含高斯噪声或将步长增加到较大的值会导致不同的行走跨越较大的空间。但是,还有一些其他的调整会导致非常不同的行为。

  • 随着时间的推移增加波动性是通过在每步之后少量增加步长来实现的。因此,随着时间的推移,步长会慢慢变大。
  • 也可以通过修改步长来实现行走的平滑,但是也可以在正步长之后增加步长,在负步长之后减小一个小值。

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

波动性越来越大、步伐越来越平稳的随机漫步(作者供图)

结论

随机漫步是一个有趣的随机过程。在很少的起始条件下,产生了许多不同的模式。因此,随机漫步可以用作合成的时间序列数据,并针对您的特定问题实例进行调整。

这篇文章展示了随机漫步的一些可能的调优选项。

如果你有兴趣阅读关于新颖的数据科学工具和理解机器学习算法的文章,可以考虑在 Medium 上关注我。

如果你对我的写作感兴趣,想直接支持我,请通过以下链接订阅。这个链接确保我会收到你的会员费的一部分。

https://zjwarnes.medium.com/membership

用零触发变压器模型生成文本分类训练数据

原文:https://towardsdatascience.com/generating-text-classification-training-data-with-zero-shot-transformer-models-e16d390eea3e?source=collection_archive---------28-----------------------

实践教程

所以你的文本分类 NLP 项目没有任何带标签的数据?只需使用零炮变压器模型生成数据

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

作者图片

零镜头文本分类确实是一项变革性的技术。这些模型可以将文本分类到任意类别,而无需任何微调[1]。与传统的监督文本分类学习方法相比,这种技术提供了两个主要的好处。首先,它们使得在标记数据不存在时执行文本分类成为可能,因为不需要微调。接下来,单个模型可以用来分类成千上万个不同的标签。

然而,零镜头文本分类模型通常很大。例如,最流行的零镜头文本分类模型之一就是基于 BART-large transformer 架构,该架构拥有超过 400 M 个参数。本文将讨论如何使用零镜头文本分类模型来生成训练数据,然后使用生成的训练数据来训练仍然表现良好的较小模型。因此,这将允许 NLP 实践者训练更小的模型,通过降低硬件要求和能耗,这些模型可以更容易地在生产中实现。

相关作品

自我标记是数据科学中一项被广泛研究的技术。基本概念是使用带标签的数据集来帮助标记未标记的数据集,以便您有更多的训练案例[2]。已经有工作在使用 BERT 的微调版本来确定使用强化学习的训练案例的标签[3]。我相信本文中讨论的方法与其他方法不同,因为它涉及零标记训练案例,并且其主要目的是使用大模型来帮助产生小模型。

处理

让我们讨论一下这个系统的整体流程。首先,需要未标记的数据。在这些实验中,我使用了一个名为斯坦福情感树库 V2 (SST2)的数据集,它可以通过 Hugging Face 的数据集分发网络获得。该数据集包含电影评论的文本以及两个潜在标签中的一个,以指示该评论是“正面”还是“负面”但是,我们不需要为了这个培训过程而使用标签。

零射击模型需要两个输入:标签列表和文本。在这种情况下,我们将提供“正面”和“负面”标签以及电影评论文本。然后,对于每种情况,模型将输出两个标签的分数。因为我们知道评论只能属于两个潜在标签中的一个,所以我们选择得分最高的标签。

在这一点上,我们有一个数据集,其中包含由零触发分类器产生的标签。值得注意的是,并非所有的标签都是正确的,因为零镜头文本分类模型不具有 100%的准确性。但是,我们仍然可以使用这个数据集来训练监督学习模型。因此,我们将使用名为 TextBlob 的包来训练一个简单的朴素贝叶斯分类器。

最后,可以使用已经标记为评估数据的原始数据集来评估该模型。在没有带标签的评估数据的情况下,我想你可以遵循一个类似的过程,使用零镜头文本分类模型来产生评估标签。然而,这种方法不会给你一个确定的模型精度。

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

作者图片

实验

零射击模型

首先,让我们讨论零镜头文本分类模型的准确性。在拥抱脸的模型分发网络上下载量最高的两个零镜头文本分类模型被用于实验:“typeform/distilbert-base-uncased-mnli和“ facebook/bart-large-mnli ”在包含 872 个案例的 SST2 数据集的整个“验证”集上对它们进行了评估。正如预期的那样,BART 模型表现更好,精度为 0.8819,而 DistilBERT 模型的精度为 0.7592。

用零射击训练监督模型

由于简单性和大小,使用 TextBlob 来训练朴素贝叶斯分类器。这种模型使用“传统的”NLP 分类技术,比深度学习方法(如 Transformers)需要的资源少得多。

下面是显示结果的图表。提醒一下,产生训练集的模型达到了 0.8819 的精度,更小的零炮模型达到了 0.7592 的精度。朴素贝叶斯分类器随着训练案例数量的增加而不断改进,最终精度为 0.7603。

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

全监督模型

零炮数据生成方法不可避免地导致一些病例被错误标记。因此,我假设与数据完全正确标记的情况相比,这会对性能产生负面影响。为了测量负面影响,我进行了如上所述的相同实验,除了我在生成的标签上使用了实际的标签。令我惊讶的是,这款机型的表现只是稍微好一点。下表给出了清晰的对比。

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

未来的工作

更强大的监督模型:

在本文中,我们介绍了如何使用生成的训练数据来训练朴素贝叶斯。然而,其他文本分类模型可能会执行得更好,同时仍然比初始零镜头模型小得多。我用 1000 个生成的训练案例进行了一个实验,用快乐变形金刚训练distilt-Bert-base-uncased。该模型使用默认设置获得了 0.7856 的精度。然而,随着我增加训练示例的数量,模型并没有实质性的改进,这可能是过度拟合的迹象。在未来,我计划进行额外的实验,以找到更好的超参数配置。

阈值设定:

应用阈值可以潜在地提高性能,并允许更容易地收集数据。可以添加一个条件语句来拒绝确定性较低的情况。因此,这可能会提高性能,因为更少的错误标记的案例将用于微调。此外,这可用于解析大量数据,其中大部分数据与目标标签无关。

迭代次数:

标记数据可以在迭代中完成,其中在每次迭代之后,使用监督模型来标记未被零炮模型发现的情况。所以,假设零拍模型的起始准确率是 90%。然后标注 1000 个训练案例,训练监督模型,它的准确率可能是 80%的准确率。这两个模型可以组合起来标记另外的 1000 个训练案例,并且该过程可以随着监督模型的准确性的增加而继续。最终,可能不再需要零剂量模型来标记病例,这将大大提高效率。

观点

我设想未来对人工标注数据的需求会大大减少。随着时间的推移,有理由假设零镜头文本分类模型的规模和质量都将提高。虽然我只是触及了应用这种技术的表面,但我已经展示了这种技术可以产生具有良好性能的模型,它只需要初始零炮模型的计算需求的一小部分。

参考资料:

[1]尹等,基准零镜头文本分类:数据集、评估和蕴涵方法(2019),EMNLP-IJCNLP 2019

[2]特里盖罗等,半监督学习的自我标记技术:分类学、软件和实证研究(2015), Knowl Inf Syst 42

[3]叶等,基于强化自训练的零镜头文本分类(2020),2020.acl-main

密码

https://github.com/Vennify-Inc/zero-shot-data-generation

如果你有自然语言处理研究的经验,并且相信这个实验的原创性不足以导致发表论文,请联系我。

原载于 2021 年 6 月 23 日https://www . vennify . ai

模拟 F. Pessoa 的递归神经网络

原文:https://towardsdatascience.com/generating-text-with-recurrent-neural-networks-based-on-the-work-of-f-pessoa-1e804d88692d?source=collection_archive---------24-----------------------

使用 Tensorflow 和 Keras 的深度学习应用

1.介绍

离散令牌序列可以在许多应用中找到,即文本中的单词、音乐作品中的音符、图像中的像素、强化学习代理中的动作等【1】。这些序列通常在连续或邻近的记号之间表现出很强的相关性。句子中的单词或单词中的字符的相关性表达了潜在的语义和语言特征。序列 x_n 中的下一个令牌可以建模为:

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

其中 x_i 表示序列中的第 I 个令牌。在自然语言处理(NLP)中,这些被定义为语言模型。通常,每个令牌代表一个单独的单词或字母。生成的输出是一个概率分布,我们可以从中采样以生成序列中的下一个令牌。这些模型也被称为循环的,因为我们可以循环地应用这个生成过程来创建全新的令牌序列。

经常用于处理离散记号序列问题的一种特定类型的生成模型是递归神经网络(RNN)。在更简单的神经网络中,固定维度的特征表示被不同的非线性函数变换几次。在 RNN 中,这些变换也会在时间上重复,这意味着在每个时间步长,都会处理新的输入,并生成新的输出。它们可以有效地捕获输入序列的语义丰富的表示【2】。RNN 在不同的环境中展示了这种能力,例如生成结构化文本、原始图像(基于每像素),甚至在在线服务上模拟用户行为。

我们的任务是生成类似训练语料库的原始文本。这是一项无人监督的任务,因为我们无法访问任何标记或目标变量。我们首先创建一个单词嵌入,将每个字符映射到一个参数化维度的向量。对于每一个字符,该模型查找其嵌入情况,并将结果输入一个长短期记忆(LSTM)层堆栈,这是一种特殊类型的 RNN。这些被开发来扩展 RNNs 的传统能力,以模拟长期依赖性和对抗消失梯度问题。我们网络的输出是一个密集层,其单元数量等于词汇量。我们没有为这一层定义激活函数;它只是为词汇表中的每个字符输出一个 logit。我们使用这些值在以后从分类分布中取样。

在本文中,我们使用了费尔南多·佩索阿的作品,他是 20 世纪最重要的文学人物之一,也是葡萄牙语中最伟大的诗人之一。这个数据集现在可以在 Kaggle 上公开获得,包括 4300 多首诗歌、散文和其他作品。

KaggleGitHub 上也有该代码。

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

图 1:佩索阿的肖像,1914 年— 来源

本文属于使用 TensorFlow 进行深度学习的系列文章:

2.数据预处理

该数据集包括作者用自己的名字写的几篇文章,但也使用不同的异名和假名。每个人都有自己的写作风格,单独学习会很有趣。然而,为了有效地训练深度神经网络(DNN),我们需要一个大的数据集,这就是建立单一模型的原因。

F.佩索阿年轻时曾在南非生活过一段时间,在那里他接触到了英语。这就是为什么他的部分作品是用英语写的。为了避免引入噪声,我们从训练数据集中移除了大部分英语文本。

import pandas as pd
import numpy as np
from tensorflow.keras.preprocessing.text import Tokenizer
import tensorflow as tf
import ast
import os
import json
import matplotlib.pyplot as plt
from nltk import tokenize
import seaborn as snsf_pessoa = pd.read_csv(os.getcwd() + '/f_pessoa_v2.csv')

texts = f_pessoa.copy()

# Removing all pseudonyms that wrote in English.

texts = texts[~texts['author'].isin(['Alexander Search', 'David Merrick', 'Charles Robert Anon', 'I. I. Crosse'])]

texts['text'] = texts['text'].apply(lambda t: ast.literal_eval(t))
texts = texts.reset_index().drop('index', axis=1)
texts = texts['text'].tolist()
texts = np.concatenate(texts)

texts = np.asarray(texts)
texts_p = " ".join(texts)

# we will be truncating large texts soon, so this code only tries to reduce the 
# sequence size by splitting the texts that seem to be significantly larger than 
# the rest. Otherwise, we try to use the structure provided in the data itself

_, ax = plt.subplots(1, 2, figsize=(15, 5))

mylen = np.vectorize(len)

sns.histplot(mylen(texts), bins=50, ax=ax[0])
ax[0].set_title('Histogram of the number of characters in each \nchunk of text BEFORE splitting sentences', fontsize=16)

large_texts = texts[mylen(texts)>350]
large_texts_p = " ".join(large_texts)
large_texts = tokenize.sent_tokenize(large_texts_p)

texts = np.concatenate((texts[~(mylen(texts)>350)], large_texts))

ax[1].set_title('Histogram of the number of characters in each \nchunk of text AFTER splitting sentences', fontsize=16)
sns.histplot(mylen(texts), bins=50, ax=ax[1]);

print(f'Length of texts dataset: {len(texts_p)} characters')Length of texts dataset: 5811145 characters

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

图 2:分句前(左边)和分句后(右边)每块文本的字符数直方图。

清理文本后,我们最终得到了超过 580 万个字符。请注意,为了避免在规范化序列的文本长度时丢失数据,我们按句子分割了最大的序列。序列长度分布的差异可以在上面的直方图中看到。我们可以预览一些片段。

print(texts[97:106])['O burburinho da água' 'O burburinho da água' 'No regato que se espalha'
 'É como a ilusão que é mágoa' 'Quando a verdade a baralha.'
 '— A única vantagem de estudar é gozar o quanto os outros não disseram.'
 '— A arte é um isolamento. Todo o artista deve buscar isolar os outros, levar-lhes às almas o desejo de estarem sós. O triunfo supremo de um artista é quando a ler suas obras o leitor prefere tê-las e não as ler. Não é porque isto aconteça aos consagrados; é porque é o maior tributo (...)'
 '— Ser lúcido é estar indisposto consigo próprio. O legítimo estado de espírito com respeito a olhar para dentro de si próprio é o estado (...) de quem olha nervos e indecisões.'
 'A única atitude intelectual digna de uma criatura superior é a de uma calma e fria compaixão por tudo quanto não é ele próprio. Não que essa atitude tenha o mínimo cunho de justa e verdadeira; mas é tão invejável que é preciso tê-la.']

更重要的是,我们可以评估独特字符的数量,这是我们的词汇量。

vocab = sorted(set(texts_p))
print(f'{len(vocab)} unique characters in texts')156 unique characters in texts

在训练之前,我们需要将字符串转换成一些数字表示。我们从记住一些重要的方面开始对文本进行标记。我们考虑了无限数量的令牌,并在角色级别创建了它们。我们没有过滤任何字符,并保持原来的大写。然后,我们使用标记器将文本映射到编码序列。

def create_character_tokenizer(list_of_strings):
    tokenizer = Tokenizer(filters=None,
                         char_level=True, 
                          split=None,
                         lower=False)
    tokenizer.fit_on_texts(list_of_strings)
    return tokenizer

tokenizer = create_character_tokenizer(texts)

tokenizer_config = tokenizer.get_config()

word_counts = json.loads(tokenizer_config['word_counts'])
index_word = json.loads(tokenizer_config['index_word'])
word_index = json.loads(tokenizer_config['word_index'])

def strings_to_sequences(tokenizer, list_of_strings):
    sentence_seq = tokenizer.texts_to_sequences(list_of_strings)
    return sentence_seq

seq_texts = strings_to_sequences(tokenizer, texts)

我们可以看到这种编码的一个例子。

print('Original sequence: \n' + texts[0] + '\n')
print('Encoded sequence: ')
print(seq_texts[0])Original sequence: 
Diana através dos ramos

Encoded sequence: 
[46, 6, 3, 8, 3, 1, 3, 9, 7, 3, 19, 26, 5, 1, 10, 4, 5, 1, 7, 3, 11, 4, 5]

我们还需要标准化序列的长度,为此我们定义了 300 个字符的长度。小于 300 的序列用零填充,而大于 300 的序列被截断。

mylen = np.vectorize(len)

print(max(mylen(texts)))
print(np.round(np.mean(mylen(texts))))1377
71.0def make_padded_dataset(sequences):
    padded_sequence = tf.keras.preprocessing.sequence.pad_sequences(sequences,
                                                 maxlen=300,
                                                 padding='pre',
                                                 truncating='pre',
                                                 value=0)
    return padded_sequence

padded_sequences = make_padded_dataset(seq_texts)

RNN 通过接收字符序列并预测序列中的下一个字符来工作。在训练时,模型接收一个输入序列和一个移位一的目标序列。

例如,表达式Diana através dos ramos是我们数据集上第一首诗的第一节。这首诗来自 Ricardo Reis,他是 F. Pessoa 的许多别称之一。给定输入,Diana através dos ramo正确的预测是iana através dos ramos。请注意,预测与输入的长度相同。

我们采取的另一个决定是将我们的 RNN 构建为有状态的,这意味着它的内部状态跨批维护。为了提高效率,我们需要确保每个批处理元素都跟随前一个批处理的相应元素。

def create_inputs_and_targets(array_of_sequences, batch_size=32):
    input_seq = array_of_sequences[:,:-1]
    target_seq = array_of_sequences[:,1:]

    # Prepare the batches and ensure that is ready to be fed to a stateful RNN

    num_examples = input_seq.shape[0]

    num_processed_examples = num_examples - (num_examples % batch_size)

    input_seq = input_seq[:num_processed_examples]
    target_seq = target_seq[:num_processed_examples]

    steps = int(num_processed_examples / 32) 

    inx = np.empty((0,), dtype=np.int32)
    for i in range(steps):
        inx = np.concatenate((inx, i + np.arange(0, num_processed_examples, steps)))

    input_seq_stateful = input_seq[inx]
    target_seq_stateful = target_seq[inx]

    # Split data between training and validation sets

    num_train_examples = int(batch_size * ((0.8 * num_processed_examples) // batch_size))

    input_train = input_seq_stateful[:num_train_examples]
    target_train = target_seq_stateful[:num_train_examples]

    input_valid = input_seq_stateful[num_train_examples:]
    target_valid = target_seq_stateful[num_train_examples:]

    # Create datasets objects for training and validation data

    dataset_train = tf.data.Dataset.from_tensor_slices((input_train, target_train))
    dataset_train = dataset_train.batch(batch_size, drop_remainder=True)

    dataset_valid = tf.data.Dataset.from_tensor_slices((input_valid, target_valid))
    dataset_valid = dataset_valid.batch(batch_size, drop_remainder=True)

    return (dataset_train, dataset_valid)

train_data, valid_data = create_inputs_and_targets(padded_sequences)

3.递归神经网络

我们首先定义了一个嵌入层,将我们的字符索引转换成固定大小的密集向量。值得注意的是,填充值在这一层被屏蔽,这意味着它们被简单地忽略。接下来,我们堆叠了两个单向有状态 LSTM 层,每个层有 512 个单元。这些层具有学习长期依赖性的潜力;然而,训练它们在计算上是昂贵的。在它们之间,我们引入了一个辍学层。最后,最后一层为词汇表中的每个字符输出一个 logit。这些是根据模型的每个字符的对数似然性。请注意,我们总共有大约 4M 个参数需要训练。

def get_model(vocab_size, batch_size):
    model = tf.keras.Sequential([
        tf.keras.layers.Embedding(input_dim=vocab_size, output_dim = 256, mask_zero=True, batch_input_shape=(batch_size, None)),
        tf.keras.layers.LSTM(units=512, return_sequences=True,stateful=True),
        tf.keras.layers.Dropout(0.2),
        tf.keras.layers.LSTM(units=512, return_sequences=True,stateful=True),
        tf.keras.layers.Dense(units=vocab_size)
    ])
    return modelbatch_size=32
model = get_model(len(tokenizer.word_index) + 1, batch_size)
model.summary()Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
embedding (Embedding)        (32, None, 256)           40192     
_________________________________________________________________
lstm (LSTM)                  (32, None, 512)           1574912   
_________________________________________________________________
dropout (Dropout)            (32, None, 512)           0         
_________________________________________________________________
lstm_1 (LSTM)                (32, None, 512)           2099200   
_________________________________________________________________
dense (Dense)                (32, None, 157)           80541     
=================================================================
Total params: 3,794,845
Trainable params: 3,794,845
Non-trainable params: 0
_________________________________________________________________checkpoint_callback=tf.keras.callbacks.ModelCheckpoint(filepath='./models/ckpt',
                                                       save_weights_only=True,
                                                       save_best_only=True)
model.compile(optimizer='adam', loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
              metrics=['sparse_categorical_accuracy'])
history = model.fit(train_data, 
                    epochs=30, 
                    validation_data=valid_data,
                    callbacks=[checkpoint_callback, 
tf.keras.callbacks.EarlyStopping(patience=2)])Epoch 1/30
2023/2023 [==============================] - 1041s 512ms/step - loss: 0.5216 - sparse_categorical_accuracy: 0.3516 - val_loss: 0.3298 - val_sparse_categorical_accuracy: 0.5669
[...]
Epoch 18/30
2023/2023 [==============================] - 1031s 510ms/step - loss: 0.2495 - sparse_categorical_accuracy: 0.6478 - val_loss: 0.2756 - val_sparse_categorical_accuracy: 0.6268def model_history(history):
    history_dict = dict()
    for k, v in history.history.items():
        history_dict[k] = [float(val) for val in history.history[k]]
    return history_dict

history_dict = model_history(history)

4.结果

即使使用 GPU,训练也非常慢(尽管与 CPU 相比,训练时间减少了 15 倍),回想一下,我们只堆叠了两个单元数量有限的 LSTM 层。从下图中,我们可以看到训练和验证数据集的准确性快速增加,然后在几个时期内稳定攀升。我们的回调最终被执行(当超过 2 个时期验证准确性没有增加时)以停止训练过程。没有过度合身的迹象。

def plot_history(history_dict):

    plt.figure(figsize=(15,5))
    plt.subplot(121)
    plt.plot(history_dict['sparse_categorical_accuracy'])
    plt.plot(history_dict['val_sparse_categorical_accuracy'])
    plt.title('Accuracy vs. epochs')
    plt.ylabel('Accuracy')
    plt.xlabel('Epoch')
    plt.xticks(np.arange(len(history_dict['sparse_categorical_accuracy'])))
    ax = plt.gca()
    ax.set_xticklabels(1 + np.arange(len(history_dict['sparse_categorical_accuracy'])))
    plt.legend(['Training', 'Validation'], loc='lower right')

    plt.subplot(122)
    plt.plot(history_dict['loss'])
    plt.plot(history_dict['val_loss'])
    plt.title('Loss vs. epochs')
    plt.ylabel('Loss')
    plt.xlabel('Epoch')
    plt.xticks(np.arange(len(history_dict['sparse_categorical_accuracy'])))
    ax = plt.gca()
    ax.set_xticklabels(1 + np.arange(len(history_dict['sparse_categorical_accuracy'])))
    plt.legend(['Training', 'Validation'], loc='upper right')
    plt.show() 

plot_history(history_dict)

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

图 3:RNN 模型几个时期的精确度和损耗演变。

model = get_model(len(tokenizer.word_index) + 1, batch_size=1)
model.load_weights(tf.train.latest_checkpoint('./models/')).expect_partial()

def get_logits(model, token_sequence, initial_state1=None, initial_state2=None, initial_state3=None):
    token_sequence = np.asarray(token_sequence)
    if initial_state1 is not None:
        # set states for all recurrent layers
        model.layers[1].states = initial_state1
        model.layers[3].states = initial_state2
        model.layers[5].states = initial_state3
    else:
        model.layers[1].reset_states()
        model.layers[3].reset_states()
        model.layers[5].reset_states()
    logit = model.predict(token_sequence)
    logit = logit[:,-1,:]

    return logit

def sample_token(logits):
    pred = tf.random.categorical(logits, num_samples=1).numpy()[0]
    return pred[0]

为了从我们的模型生成文本,我们需要指定一个种子字符串来启动网络。接下来,我们标记初始字符串并重置网络状态。然后,该字符串被转换为批量大小为 1 的张量,以提供给我们的模型。我们使用上一时间步的预测来构建分类分布,然后从中进行采样。使用我们的网络的相同状态和先前采样的令牌,我们可以重复预测步骤,直到我们获得具有指定大小的最终序列。

由此产生的原文分析起来还是挺有意思的。请记住,我们的 RNN 不得不从很小的数据集开始学习葡萄牙语。除了用葡萄牙语书写的实例之外,没有向模型提供诸如句法或语义的明确信息。对于这项任务来说,数据集也相当小。然而,还是有一些有趣的经验值得注意。比如在标点符号方面,引号的使用是正确的,表现出对要求开、闭的理解。在诸如"*desassessego no poderia!…falências no meu Cora o…*或“As can es…um sono de ouvir…Fico tanto!…" 我们几乎可以理解费尔南多·佩索阿的一些无房可住的情况。另一方面,我们看到意义或意图不是 RNN 可以捕捉到的,我们也可以识别一些拼写错误。

init_string = 'Desassossego'
num_generation_steps = 500token_sequence = tokenizer.texts_to_sequences([init_string])
initial_state_1, initial_state_2, initial_state_3 = None, None, None
input_sequence = token_sequence

for _ in range(num_generation_steps):
    logits = get_logits(model, 
                        input_sequence, 
                        initial_state1=initial_state_1,
                        initial_state2=initial_state_2,
                        initial_state3=initial_state_3)
    sampled_token = sample_token(logits)
    token_sequence[0].append(sampled_token)
    input_sequence = [[sampled_token]]
    initial_state_1 = model.layers[1].states
    initial_state_2 = model.layers[3].states
    initial_state_2 = model.layers[5].states

print(tokenizer.sequences_to_texts(token_sequence)[0][::2])**Desassossego não poderia!... Falências no meu coração... Esse reer sobre os braços dos meus caminhos e ignorantes possamos «exensação simbólica» e em Natureza, e a noite nova da ausência de cada? Não pense de bem entendida uma orientada prosa). V. como fui... As canções... é um sono de ouvir... Ficção tanto!... Vejo outro olhar pela Tristeza da cadeira, rainha para a Carta, a noite. Depois no paganismo que se sente no espaço real e de criar uma pedra de tradição sociológica para implicar o de Aristoclator S**

5.结论

对于这项任务,数据的预处理是具有挑战性的。我们需要确保我们的输入序列以合适的方式编码,以便 RNN 有效地捕获可用的语义表示。训练 rnn 在计算上是昂贵的,所以我们决定保持结构尽可能简单。

我们能够生成葡萄牙语文本,除了诗人的作品之外,无需向模型提供任何关于该语言的结构信息。该模型学习了语言的一些基本结构,同时保留了我们可以认为类似于训练语料库的细微差别。

这种方法可以通过增加模型的深度和每层中单元的数量来扩展。还可以调整批次大小等超参数来提高准确性。我们测试了以写作形式区分的可能性,一个 DNN 用散文文本训练,另一个用诗歌文本训练。结果并不令人满意,因为 DNNs 无法生成具有连贯结构的文本。我们把它作为未来的工作。

保持联系: LinkedIn

6.参考

【1】——【德·布姆等人,2018】德·布姆,c .、德·梅斯特,t .、Dhoedt,B. (2018)。实践中的字符级递归神经网络:训练和采样方案的比较。神经计算与应用,31(8):4001–4017。

【2】——【苏茨基弗等人,2011 年】苏茨基弗本人、马滕斯律师和辛顿律师(2011 年)。用递归神经网络生成文本。ICML 11,第 1017-1024 页,麦迪逊,威斯康星州,美国。全媒体。

【3】https://www . ka ggle . com/Luis Roque/the-complete-literal-works-of-Fernando-pes SOA

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值