From 830597ad57b9ff77462ed4011aceff6c15723ea6 Mon Sep 17 00:00:00 2001
From: innovation64
Date: Tue, 18 Apr 2023 11:20:50 +0800
Subject: [PATCH 01/55] update soc3-zn
---
zh/_blog.yml | 10 +++-
zh/ethics-soc-3.md | 141 +++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 150 insertions(+), 1 deletion(-)
create mode 100644 zh/ethics-soc-3.md
diff --git a/zh/_blog.yml b/zh/_blog.yml
index 03af40f460..ccccfa3bf0 100644
--- a/zh/_blog.yml
+++ b/zh/_blog.yml
@@ -372,4 +372,12 @@
thumbnail: /blog/assets/136_train-your-controlnet/thumbnail.png
date: March 28, 2023
tags:
- - diffusers
\ No newline at end of file
+ - diffusers
+
+- local: ethics-soc-3
+ title: "道德与社会问题简报 #3: Hugging Face 上的道德开放性"
+ author: irenesolaiman
+ thumbnail: /blog/assets/137_ethics_soc_3/ethics_3_thumbnail.png
+ date: Mar 30, 2023
+ tags:
+ - ethics
\ No newline at end of file
diff --git a/zh/ethics-soc-3.md b/zh/ethics-soc-3.md
new file mode 100644
index 0000000000..973b3c3f45
--- /dev/null
+++ b/zh/ethics-soc-3.md
@@ -0,0 +1,141 @@
+---
+title: "道德与社会问题简报 #3: Hugging Face 上的道德开放性"
+thumbnail: /blog/assets/137_ethics_soc_3/ethics_3_thumbnail.png
+authors:
+- user: irenesolaiman
+- user: giadap
+- user: NimaBoscarino
+- user: yjernite
+- user: allendorf
+translators:
+- user: innovation64
+
+---
+
+# 道德与社会问题简报 #3: Hugging Face 上的道德开放性
+
+
+
+
+## 使命:开放和优秀的机器学习
+在我们的使命中,我们致力于推动机器学习(ML)的民主化,我们在研究如何支持 ML 社区工作并有助于检查危害和防止可能的危害发生。开放式的发展和科学可以分散力量,让许多人集体开展反映他们需求和价值的 AI 研究工作。虽然[开放性使得更广泛的观点能够为研究和整个 AI 贡献力量,但它也面对着较小风险控制的紧张](https://arxiv.org/abs/2302.04844)。
+
+由于这些系统的动态和快速发展,对 ML 相关模型进行管控面临着独特的挑战。事实上,随着 ML 模型变得更加先进和能够生成越来越多样化的内容,使得潜在的有害或意外的输出的可能性增加,需要开发强大的调节和评估策略。此外,ML 模型的复杂性和它们处理的大量数据加剧了识别和解决潜在偏见和道德问题的挑战。
+
+作为社区主理人,我们认识到,随着社区模型可能放大对用户和整个世界的危害,我们肩负着责任。这些危害通常会以一种依赖于情境的方式不平等地影响少数群体。我们采取的方法是分析每个情境中存在的紧张关系,并对公司和 Hugging Face 社区进行讨论。虽然许多模型可能会放大危害,尤其是歧视性内容,但我们正在采取一系列步骤来识别最高风险模型以及要采取的行动。重要的是,许多不同背景的活跃观点对于理解、衡量和减轻影响不同群体的潜在危害至关重要。
+
+我们正在开发工具和保障措施,除了改进我们的文档实践以确保开源科学能够赋予个人权力,并继续将潜在危害最小化。
+
+## 道德类别
+
+我们培养良好的开放式 ML 工作的第一个主要方面是推广 ML 开发的工具和正面示例,这些工具和示例优先考虑其利益相关者的价值和考虑。这有助于用户采取具体步骤解决悬而未决的问题,并为 ML 开发中事实上的破坏性做法提出合理的替代方案。
+
+为了帮助我们的用户发现和参与与伦理相关的 ML 工作,我们编制了一组标签。这 6 个高级类别基于我们对社区成员贡献的空间的分析。它们旨在为你提供一种通俗易懂的方式来思考道德技术:
+
+- 严谨的工作特别注意在开发时牢记最佳实践。在 ML 中,这可能意味着检查失败案例(包括进行偏见和公平性审计),通过安全措施保护隐私,并确保潜在用户(技术和非技术)了解项目的局限性。
+- 自愿工作[支持](https://www.consentfultech.io/)使用这些技术和受这些技术影响的人的自主决定。
+- 具有社会意识的工作向我们展示了技术如何支持社会、环境和科学工作。
+- 可持续工作着重介绍并探索使机器学习在生态上可持续发展的技术。
+- 包容性工作扩大了谁在机器学习世界中构建和受益的范围。
+- 好奇的工作揭示了不平等和权力结构,这些不平等和权力结构挑战了社区并让其重新思考自身与技术的关系。
+
+在 https://huggingface.co/ethics 上阅读更多内容
+
+查找这些术语,我们将在 Hub 上的一些新项目中使用这些标签,并根据社区贡献更新它们!
+
+## 保障措施
+
+对开放版本采取“全有或全无”的观点忽略了决定 ML 模型正面或负面影响的各种背景因素。对 ML 系统的共享和重用方式进行更多控制,支持协作开发和分析,同时降低促进有害使用或滥用的风险;允许更多的开放和参与创新以共享利益。
+
+我们直接与贡献者接触并解决了紧迫的问题。为了将其提升到一个新的水平,我们正在构建基于社区的流程。这种方法使 Hugging Face 贡献者和受贡献影响的人能够告知我们平台上提供的模型和数据所需的限制、共享和其他机制。我们将关注的三个主要方面是:工件( artifact )的来源、工件的开发者如何处理工件以及工件的使用方式。在这方面,我们:
+- 为我们的社区推出了一个[标记功能](https://twitter.com/GiadaPistilli/status/1571865167092396033),以确定 ML 工件或社区内容(模型、数据集、空间或讨论)是否违反了我们的[内容指南](https://huggingface.co/content-guidelines),
+- 监控我们的社区讨论板,以确保 Hub 用户遵守[行为准则](https://huggingface.co/code-of-conduct),
+- 使用详细说明社会影响、偏见以及预期和超出范围的用例的模型卡,有力地记录我们下载次数最多的模型,
+- 创建观众引导标签,例如可以添加到仓库的卡片元数据中的“不适合所有观众”标签,以避免未请求的暴力和色情内容,
+- 促进对[模型](https://www.licenses.ai/blog/2022/8/26/bigscience-open-rail-m-license)使用[开放式负责任人工智能许可证 (RAIL)](https://huggingface.co/blog/open_rail),例如 LLM([BLOOM](https://huggingface.co/spaces/bigscience/license),[BigCode](https://huggingface.co/spaces/bigcode/license))
+- 进行研究,[分析](https://arxiv.org/abs/2302.04844)哪些模型和数据集最有可能被滥用和恶意使用,或有记录显示滥用和恶意使用。
+
+**如何使用标记功能:**
+单击任何模型、数据集、空间或讨论上的标记图标:
+
+
+
+ 登录后,你可以单击“三个竖点”按钮以显示报告(或标记)仓库的功能。这将在仓库的社区选项卡中打开一个对话。
+
+
+分享你标记此项目的原因:
+
+
+
+ 请在你的报告中添加尽可能多的相关上下文!这将使仓库所有者和 HF 团队更容易开始采取行动。
+
+
+在优先考虑开放科学时,我们逐案检查潜在危害,并提供协作学习和分担责任的机会。当用户标记系统时,开发人员可以直接透明地回应问题。本着这种精神,我们要求仓库所有者做出合理的努力来解决报告的问题,尤其是当报告人花时间提供问题描述时。我们还强调,报告和讨论与平台的其他部分一样,遵循相同的沟通规范。如果行为变得仇恨和/或辱骂,模型拥有者可以脱离或结束讨论(参见[行为准则](https://huggingface.co/code-of-conduct))。
+
+
+如果我们的社区将特定模型标记为高风险,我们会考虑:
+- 在趋势选项卡和提要中降低 ML 工件在 Hub 中的可见性,
+- 请求启用门控功能以管理对 ML 工件的访问(请参阅[模型](https://huggingface.co/docs/hub/models-gated)和[数据集](https://huggingface.co/docs/hub/datasets-gated)文档)
+- 要求将模型设为私有,
+- 禁用访问。
+
+**如何添加“不适合所有受众”标签:**
+
+编辑 model/data card → 在标签部分添加 `not-for-all-audiences` → 打开 PR ,等待作者合并。合并后,以下标签将显示在仓库中:
+
+
+
+
+
+
+
+任何标记有 `not-for-all-audiences` 的仓库在访问时都会显示以下弹出窗口:
+
+
+
+
+
+单击“查看内容”将允许你正常查看仓库。如果你希望始终在没有弹出窗口 `not-for-all-audiences` 的情况下查看标记的仓库, 可以在用户的[Content Preferences](https://huggingface.co/settings/content-preferences)中更改此设置
+
+
+
+
+
+
+
+开放科学需要保障措施,我们的一个目标是创造一个考虑到不同价值取舍的环境。提供模型和培育社区并讨论能够赋予多元群体评估社会影响以及引导好的机器学习的能力。
+
+## 你在做保障措施吗?请在 Hugging Face Hub 上分享它们!
+
+Hugging Face 最重要的部分是我们的社区。如果你是一名研究人员,致力于使 ML 的使用更安全,尤其是对于开放科学,我们希望支持并展示你的工作!
+
+以下是 Hugging Face 社区研究人员最近的一些示例和工具:
+- John Kirchenbauer, Jonas Geiping, Yuxin Wen, Jonathan Katz, Ian Miers, Tom Goldstein ([论文](https://arxiv.org/abs/2301.10226)) 的 [大语言模型的水印](https://huggingface.co/spaces/tomg-group-umd/lm-watermarking)
+- Hugging Face 团队的[生成模型卡片的工具](https://huggingface.co/spaces/huggingface/Model_Cards_Writing_Tool)
+- Ram Ananth 的保护图像免受篡改的[ Photoguard](https://huggingface.co/spaces/RamAnanth1/photoguard)
+
+感谢阅读! 🤗
+
+~ Irene, Nima, Giada, Yacine, 和 Elizabeth, 代表道德和社会常规人员
+
+如果你想引用这篇博客,请使用以下内容(按贡献降序排列):
+```
+@misc{hf_ethics_soc_blog_3,
+ author = {Irene Solaiman and
+ Giada Pistilli and
+ Nima Boscarino and
+ Yacine Jernite and
+ Elizabeth Allendorf and
+ Margaret Mitchell and
+ Carlos Muñoz Ferrandis and
+ Nathan Lambert and
+ Alexandra Sasha Luccioni
+ },
+ title = {Hugging Face Ethics and Society Newsletter 3: Ethical Openness at Hugging Face},
+ booktitle = {Hugging Face Blog},
+ year = {2023},
+ url = {https://doi.org/10.57967/hf/0487},
+ doi = {10.57967/hf/0487}
+}
+
+```
From 3fede71afc02b73e3b6833dcbdcdaee6689d3858 Mon Sep 17 00:00:00 2001
From: Zhongdong Yang
Date: Wed, 19 Apr 2023 14:30:34 +0800
Subject: [PATCH 02/55] Update _blog.yml
Try to resolve conflicts
---
zh/_blog.yml | 18 ++++++++++++++----
1 file changed, 14 insertions(+), 4 deletions(-)
diff --git a/zh/_blog.yml b/zh/_blog.yml
index ccccfa3bf0..c4cbf56c59 100644
--- a/zh/_blog.yml
+++ b/zh/_blog.yml
@@ -118,7 +118,7 @@
- open-source-collab
- local: intel-sapphire-rapids
- title: "Accelerating PyTorch Transformers with Intel Sapphire Rapids, part 1"
+ title: "使用英特尔 Sapphire Rapids 加速 PyTorch Transformers 模型(第一部分)"
author: juliensimon
thumbnail: /blog/assets/124_intel_sapphire_rapids/02.png
date: January 2, 2023
@@ -140,7 +140,7 @@
- game-dev
- local: intro-graphml
- title: "Introduction to Graph Machine Learning"
+ title: "一文带你入门图机器学习"
author: clefourrier
thumbnail: /blog/assets/125_intro-to-graphml/thumbnail.png
date: January 3, 2023
@@ -160,7 +160,7 @@
- game-dev
- local: image-similarity
- title: "Image Similarity with Hugging Face Datasets and Transformers"
+ title: "基于 Hugging Face Datasets 和 Transformers 的图像相似性搜索"
author: sayakpaul
thumbnail: /blog/assets/image_similarity/thumbnail.png
date: Jan 16, 2023
@@ -374,10 +374,20 @@
tags:
- diffusers
+- local: graphml-classification
+ title: "使用 Transformers 进行图分类"
+ author: clefourrier
+ thumbnail: /blog/assets/125_intro-to-graphml/thumbnail_classification.png
+ date: April 14, 2023
+ tags:
+ - community
+ - guide
+ - graphs
+
- local: ethics-soc-3
title: "道德与社会问题简报 #3: Hugging Face 上的道德开放性"
author: irenesolaiman
thumbnail: /blog/assets/137_ethics_soc_3/ethics_3_thumbnail.png
date: Mar 30, 2023
tags:
- - ethics
\ No newline at end of file
+ - ethics
From c9d3fc530217d5d50e316975934bc49283a079b5 Mon Sep 17 00:00:00 2001
From: Zhongdong Yang
Date: Wed, 19 Apr 2023 14:47:48 +0800
Subject: [PATCH 03/55] Update: proofreading zh/ethics-soc-3.md
---
zh/ethics-soc-3.md | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/zh/ethics-soc-3.md b/zh/ethics-soc-3.md
index 973b3c3f45..c85d92dea1 100644
--- a/zh/ethics-soc-3.md
+++ b/zh/ethics-soc-3.md
@@ -9,6 +9,8 @@ authors:
- user: allendorf
translators:
- user: innovation64
+- user: zhongdongy
+ proofreader: true
---
@@ -36,8 +38,8 @@ translators:
- 自愿工作[支持](https://www.consentfultech.io/)使用这些技术和受这些技术影响的人的自主决定。
- 具有社会意识的工作向我们展示了技术如何支持社会、环境和科学工作。
- 可持续工作着重介绍并探索使机器学习在生态上可持续发展的技术。
-- 包容性工作扩大了谁在机器学习世界中构建和受益的范围。
-- 好奇的工作揭示了不平等和权力结构,这些不平等和权力结构挑战了社区并让其重新思考自身与技术的关系。
+- 包容性工作扩大了在机器学习世界中构建和受益的对象范围。
+- 追根问底的工作揭示了不平等和权力结构,这些不平等和权力结构挑战了社区并让其重新思考自身与技术的关系。
在 https://huggingface.co/ethics 上阅读更多内容
@@ -74,7 +76,7 @@ translators:
如果我们的社区将特定模型标记为高风险,我们会考虑:
-- 在趋势选项卡和提要中降低 ML 工件在 Hub 中的可见性,
+- 在趋势选项卡和 Feed 中降低 ML 工件在 Hub 中的可见性,
- 请求启用门控功能以管理对 ML 工件的访问(请参阅[模型](https://huggingface.co/docs/hub/models-gated)和[数据集](https://huggingface.co/docs/hub/datasets-gated)文档)
- 要求将模型设为私有,
- 禁用访问。
@@ -119,6 +121,7 @@ Hugging Face 最重要的部分是我们的社区。如果你是一名研究人
~ Irene, Nima, Giada, Yacine, 和 Elizabeth, 代表道德和社会常规人员
如果你想引用这篇博客,请使用以下内容(按贡献降序排列):
+
```
@misc{hf_ethics_soc_blog_3,
author = {Irene Solaiman and
From d1c88f011e7bf8815488a68aa4f1e0ba5231a8b0 Mon Sep 17 00:00:00 2001
From: "Yao, Matrix"
Date: Thu, 20 Apr 2023 16:47:42 -0400
Subject: [PATCH 04/55] add how-to-generate cn version
Signed-off-by: Yao, Matrix
---
zh/_blog.yml | 9 +
zh/how-to-generate.md | 451 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 460 insertions(+)
create mode 100644 zh/how-to-generate.md
diff --git a/zh/_blog.yml b/zh/_blog.yml
index c4cbf56c59..e91a1587ab 100644
--- a/zh/_blog.yml
+++ b/zh/_blog.yml
@@ -391,3 +391,12 @@
date: Mar 30, 2023
tags:
- ethics
+
+- local: how-to-generate
+ title: "如何生成文本:通过 Transformers 用不同的解码方法生成文本"
+ author: patrickvonplaten
+ thumbnail: /blog/assets/02_how-to-generate/thumbnail.png
+ date: March, 2020
+ tags:
+ - guide
+ - nlp
diff --git a/zh/how-to-generate.md b/zh/how-to-generate.md
new file mode 100644
index 0000000000..34b251e64c
--- /dev/null
+++ b/zh/how-to-generate.md
@@ -0,0 +1,451 @@
+---
+title: "如何生成文本:通过 Transformers 用不同的解码方法生成文本"
+thumbnail: /blog/assets/02_how-to-generate/thumbnail.png
+authors:
+- user: patrickvonplaten
+translators:
+- user: MatrixYao
+---
+
+如何生成文本:通过 Transformers 用不同的解码方法生成文本
+
+
+
+
+
+
+
+
+### 简介
+
+近年来,随着以OpenAI [GPT2 模型](https://openai.com/blog/better-language-models/)为代表的基于数百万网页数据训练的大型 transformer 语言模型的兴起,开放域语言生成领域吸引了越来越多的关注。开放域中的条件语言生成效果令人印象深刻,典型的例子有:[GPT2 在独角兽话题上的精彩续写](https://openai.com/blog/better-language-models/#samples),[XLNet](https://medium.com/@amanrusia/xlnet-speaks-comparison-to-gpt-2-ea1a4e9ba39e) 以及[使用 CTRL 模型生成受控文本](https://blog.einstein.ai/introducing-a-conditional-transformer-language-model-for-controllable-generation/)等。促成这些进展的除了 transformer 架构的改进和大规模无监督训练数据外,**更好的解码方法**也发挥了不可或缺的作用。
+
+本文简述了不同的解码策略,同时向读者展示了如何使用流行的 `transformers` 库轻松实现这些解码策略!
+
+下文中的所有功能均可用于**自回归**语言生成任务(点击[此处](http://jalammar.github.io/illustrated-gpt2/)复习)。简单复习一下,*自回归*语言生成是基于如下假设:一个文本序列的概率分布可以分解为每个词基于其上文的条件概率的乘积。
+
+$$ P(w_{1:T} | W_0 ) = \prod_{t=1}^T P(w_{t} | w_{1: t-1}, W_0) \text{ , 其中 } w_{1: 0} = \emptyset, $$
+
+上式中,$W_0$ 是初始*上下文*单词序列。文本序列的长度 $T$ 通常时变的,并且对应于时间步 $t=T$。$P(w_{t} | w_{1: t- 1}, W_{0})$ 的词表中已包含 终止符(End Of Sequence,EOS) 。
+
+`transformers` 目前已支持的自回归语言生成任务包括 `GPT2`、`XLNet`、`OpenAi-GPT`、`CTRL`、`TransfoXL`、`XLM`、`Bart`、`T5` 模型,并支持 PyTorch 和 TensorFlow(>= 2.0)两种框架!
+
+我们会介绍目前最常用的解码方法,主要有*贪心搜索(Greedy search)*、*波束搜索(Beam search)*、*Top-K采样(Top-K sampling)* 以及 *Top-p采样(Top-p sampling)*。
+
+在此之前,我们先快速安装一下 `transformers` 并把模型加载进来。本文我们用 GPT2 模型在 TensorFlow 2.1 中进行演示,但 API 和使用 PyTorch 框架是一一对应的。
+
+``` python
+!pip install -q git+https://github.com/huggingface/transformers.git
+!pip install -q tensorflow==2.1
+```
+
+``` python
+import tensorflow as tf
+from transformers import TFGPT2LMHeadModel, GPT2Tokenizer
+
+tokenizer = GPT2Tokenizer.from_pretrained("gpt2")
+
+# add the EOS token as PAD token to avoid warnings
+model = TFGPT2LMHeadModel.from_pretrained("gpt2",pad_token_id=tokenizer.eos_token_id)
+```
+
+
+### 贪心搜索
+
+贪心搜索在每个时间步 $t$ 都简单地选择概率最高的词作为当前输出词:$w_t = argmax_{w}P(w | w_{1:t-1})$ ,如下图所示。
+
+
+
+从单词 $\text{"The"}$ 开始,算法在第一步贪心地选择条件概率最高的词 $\text{"nice"}$ 作为输出,依此往后。最终生成的单词序列为 $(\text{"The"}, \text{"nice"}, \text{"woman"})$,其联合概率为 $0.5 \times 0.4 = 0.2$ 。
+
+下面,我们输入文本序列 $(\text{"I"}, \text{"enjoy"}, \text{"walking"}, \text{"with"}, \text{"my"}, \text{"cute"}, \text{"dog"})$ 给 GPT2 模型,让模型生成下文。我们以此为例看看如何在 `transformers` 中使用贪心搜索:
+
+``` python
+# encode context the generation is conditioned on
+input_ids = tokenizer.encode('I enjoy walking with my cute dog', return_tensors='tf')
+
+# generate text until the output length (which includes the context length) reaches 50
+greedy_output = model.generate(input_ids, max_length=50)
+
+print("Output:\n" + 100 * '-')
+print(tokenizer.decode(greedy_output[0], skip_special_tokens=True))
+```
+
+
+
+ Output:
+ ----------------------------------------------------------------------------------------------------
+ I enjoy walking with my cute dog, but I'm not sure if I'll ever be able to walk with my dog. I'm not sure if I'll ever be able to walk with my dog.
+
+ I'm not sure if I'll
+
+
+
+好,我们已经用 GPT2 生成了第一个短文本😊。根据上文生成的单词是合理的,但模型很快开始输出重复的文本!这在语言生成中是一个非常普遍的问题,在贪心搜索和波束搜索中似乎更是如此 - 详见 [Vijayakumar 等人,2016](https://arxiv.org/abs/1610.02424) 和 [Shao等人,2017](https://arxiv.org/abs/1701.03185) 的论文。
+
+贪心搜索的主要缺点是它错过了隐藏在低概率词后面的高概率词,如上图所示:
+
+条件概率为 $0.9$ 的单词 $\text{"has"}$ 隐藏在单词 $\text{"dog"}$ 后面,而 $\text{"dog"}$ 因为在 `t=1` 时条件概率值只排第二所以未被选择,因此贪心搜索会错过序列 $\text{"The"}, \text {"dog"}, \text{"has"}$ 。
+
+幸好我们可以用波束搜索来缓解这个问题!
+
+
+### 波束搜索
+波束搜索通过在每个时间步保留最可能的 `num_beams` 个词,并从中最终选择出概率最高的序列来降低丢失潜在的高概率序列的风险。以 `num_beams=2` 为例:
+
+
+
+在时间步 1,除了最有可能的假设 $(\text{"The"}, \text{"nice"})$,波束搜索还跟踪第二可能的假设 $(\ text{"The"}, \text{"dog"})$。在时间步 2,波束搜索发现序列 $(\text{"The"}, \text{"dog"}, \text{"has"})$ 概率为$0.36$,比 $(\text{"The"}, \text{"nice"}, \text{"woman"})$ 的 $0.2$更高。太棒了,在我们的例子中它已经找到了最有可能的序列!
+
+波束搜索一般都会找到比贪心搜索概率更高的输出序列,但仍不保证找到全局最优解。
+
+让我们看看如何在 `transformers` 中使用波束搜索。我们设置 `num_beams > 1` 和 `early_stopping=True` 以便在所有波束达到 EOS 时直接结束生成。
+
+``` python
+# activate beam search and early_stopping
+beam_output = model.generate(
+ input_ids,
+ max_length=50,
+ num_beams=5,
+ early_stopping=True
+)
+
+print("Output:\n" + 100 * '-')
+print(tokenizer.decode(beam_output[0], skip_special_tokens=True))
+```
+
+
+
+ Output:
+ ----------------------------------------------------------------------------------------------------
+ I enjoy walking with my cute dog, but I'm not sure if I'll ever be able to walk with him again.
+
+ I'm not sure if I'll ever be able to walk with him again. I'm not sure if I'll
+
+
+
+虽然结果比贪心搜索更流畅,但输出中仍然包含重复。一个简单的补救措施是引入 *n-grams*(即连续 n 个词的词序列)惩罚,该方法是由 [Paulus 等人 (2017)](https://arxiv.org/abs/1705.04304) 和 [Klein等人 (2017)](https://arxiv.org/abs/1701.02810) 引入的。最常见的 *n-grams* 惩罚是确保每个 *n-gram* 都只出现一次,方法是如果看到当前候选词与其上文所组成的 *n-gram* 已经出现过了,就将该候选词的概率设置为 0。
+
+我们可以通过设置 `no_repeat_ngram_size=2` 来试试,这样任意 *2-gram* 不会出现两次:
+
+``` python
+# set no_repeat_ngram_size to 2
+beam_output = model.generate(
+ input_ids,
+ max_length=50,
+ num_beams=5,
+ no_repeat_ngram_size=2,
+ early_stopping=True
+)
+
+print("Output:\n" + 100 * '-')
+print(tokenizer.decode(beam_output[0], skip_special_tokens=True))
+```
+
+
+
+ Output:
+ ----------------------------------------------------------------------------------------------------
+ I enjoy walking with my cute dog, but I'm not sure if I'll ever be able to walk with him again.
+
+ I've been thinking about this for a while now, and I think it's time for me to take a break
+
+
+
+不错,看起来好多了!我们看到生成的文本已经没有重复了。但是,*n-gram* 惩罚使用时必须谨慎,如一篇关于 *纽约* 这个城市的文章就不应使用 *2-gram* 惩罚,否则,城市名称在整个文本中将只出现一次!
+
+波束搜索的另一个重要特性是我们能够比较概率最高的几个波束,并选择最符合我们要求的波束作为最终生成文本。
+
+在 `transformers` 中,我们只需将参数 `num_return_sequences` 设置为需返回的概率最高的波束的数量,记得确保 `num_return_sequences <= num_beams`!
+
+``` python
+# set return_num_sequences > 1
+beam_outputs = model.generate(
+ input_ids,
+ max_length=50,
+ num_beams=5,
+ no_repeat_ngram_size=2,
+ num_return_sequences=5,
+ early_stopping=True
+)
+
+# now we have 3 output sequences
+print("Output:\n" + 100 * '-')
+for i, beam_output in enumerate(beam_outputs):
+ print("{}: {}".format(i, tokenizer.decode(beam_output, skip_special_tokens=True)))
+```
+
+
+
+ Output:
+ ----------------------------------------------------------------------------------------------------
+ 0: I enjoy walking with my cute dog, but I'm not sure if I'll ever be able to walk with him again.
+
+ I've been thinking about this for a while now, and I think it's time for me to take a break
+ 1: I enjoy walking with my cute dog, but I'm not sure if I'll ever be able to walk with him again.
+
+ I've been thinking about this for a while now, and I think it's time for me to get back to
+ 2: I enjoy walking with my cute dog, but I'm not sure if I'll ever be able to walk with her again.
+
+ I've been thinking about this for a while now, and I think it's time for me to take a break
+ 3: I enjoy walking with my cute dog, but I'm not sure if I'll ever be able to walk with her again.
+
+ I've been thinking about this for a while now, and I think it's time for me to get back to
+ 4: I enjoy walking with my cute dog, but I'm not sure if I'll ever be able to walk with him again.
+
+ I've been thinking about this for a while now, and I think it's time for me to take a step
+
+
+
+如我们所见,五个波束彼此之间仅有少量差别 —— 这在仅使用 5 个波束时不足为奇。
+
+开放域文本生成的研究人员最近提出了几个理由来说明对该领域而言波束搜索可能不是最佳方案:
+ - 在机器翻译或摘要等任务中,因为所需生成的长度或多或少都是可预测的,所以波束搜索效果比较好 - 参见 [Murray 等人(2018)](https://arxiv.org/abs/1808.10006) 和 [Yang 等人(2018)](https://arxiv.org/abs/1808.09582)的工作。但开放域文本生成情况有所不同,其输出文本长度可能会有很大差异,如对话和故事生成的输出文本长度就有很大不同。
+
+ - 我们已经看到波束搜索已被证明存在重复生成的问题。在故事生成这样的场景中,很难用 *n-gram* 或其他惩罚来控制,因为在“不重复”和最大可重复*n-grams*之间找到一个好的折衷需要大量的微调。
+
+ - 正如 [Ari Holtzman 等人(2019)](https://arxiv.org/abs/1904.09751)所论证的那样,高质量的人类语言并不遵循最大概率法则。换句话说,作为人类,我们希望生成的文本能让我们感到惊喜,而可预测的文本使人感觉无聊。论文作者画了一个概率图,很好地展示了这一点,从图中可以看出人类文本带来的惊喜度比波束搜索好不少。
+
+![alt text](https://blog.fastforwardlabs.com/images/2019/05/Screen_Shot_2019_05_08_at_3_06_36_PM-1557342561886.png)
+
+因此,让我们开始玩点刺激的,引入一些随机性🤪。
+
+### 采样
+
+在其最基本的形式中,采样意味着根据当前条件概率分布随机选择输出词 $w_t$:
+
+$$ w_t \sim P(w|w_{1:t-1}) $$
+
+继续使用上文中的例子,下图可视化了使用采样生成文本的过程。
+
+
+
+很明显,使用采样方法时文本生成本身不再是*确定性的*。单词 $\text{"car"}$ 从条件概率分布 $P(w | \text{"The"})$ 中采样而得,而 $\text{"drives"}$ 则采样自 $(P(w | \text{"The"}, \text{"car"})$。
+
+在 `transformers` 中,我们设置 `do_sample=True` 并通过设置 `top_k=0` 停用 *Top-K* 采样(稍后详细介绍)。在下文中,为便于复现,我们会固定 `random_seed=0`,但你可以在自己的模型中随意更改 `random_seed`。
+
+``` python
+# set seed to reproduce results. Feel free to change the seed though to get different results
+tf.random.set_seed(0)
+
+# activate sampling and deactivate top_k by setting top_k sampling to 0
+sample_output = model.generate(
+ input_ids,
+ do_sample=True,
+ max_length=50,
+ top_k=0
+)
+
+print("Output:\n" + 100 * '-')
+print(tokenizer.decode(sample_output[0], skip_special_tokens=True))
+```
+
+
+
+ Output:
+ ----------------------------------------------------------------------------------------------------
+ I enjoy walking with my cute dog. He just gave me a whole new hand sense."
+
+ But it seems that the dogs have learned a lot from teasing at the local batte harness once they take on the outside.
+
+ "I take
+
+
+
+有意思!生成的文本看起来不错 - 但仔细观察会发现它不是很连贯。*3-grams* *new hand sense* 和 *local batte harness* 非常奇怪,看起来不像是人写的。这就是对单词序列进行采样时的大问题:模型通常会产生不连贯的乱码,*参见* [Ari Holtzman 等人(2019)](https://arxiv.org/abs/1904.09751)的论文。
+
+缓解这一问题的一个技巧是通过降低所谓的[softmax](https://en.wikipedia.org/wiki/Softmax_function#Smooth_arg_max) 的“温度”使分布 $P(w|w_{1:t-1}$ 更陡峭。而降低“温度”,本质上是增加高概率单词的似然并降低低概率单词的似然。
+
+将温度应用到于我们的例子中后,结果如下图所示。
+
+
+
+$t=1$ 时刻单词的条件分布变得更加陡峭,几乎没有机会选择单词 $\text{"car"}$ 了。
+
+让我们看看如何通过设置 `temperature=0.7` 来冷却生成过程:
+
+``` python
+# set seed to reproduce results. Feel free to change the seed though to get different results
+tf.random.set_seed(0)
+
+# use temperature to decrease the sensitivity to low probability candidates
+sample_output = model.generate(
+ input_ids,
+ do_sample=True,
+ max_length=50,
+ top_k=0,
+ temperature=0.7
+)
+
+print("Output:\n" + 100 * '-')
+print(tokenizer.decode(sample_output[0], skip_special_tokens=True))
+```
+
+
+
+ Output:
+ ----------------------------------------------------------------------------------------------------
+ I enjoy walking with my cute dog, but I don't like to be at home too much. I also find it a bit weird when I'm out shopping. I am always away from my house a lot, but I do have a few friends
+
+
+
+好,奇怪的 n-gram 变少了,现在输出更连贯了!虽然温度可以使分布的随机性降低,但极限条件下,当“温度”设置为 $0$ 时,温度缩放采样就退化成贪心解码了,因此会遇到与贪心解码相同的问题。
+
+### Top-K 采样
+
+[Fan 等人(2018)](https://arxiv.org/pdf/1805.04833.pdf)的论文介绍了一种简单但非常强大的采样方案,称为 ***Top-K*** 采样。在 *Top-K* 采样中,概率最大的 *K* 个词会被选出,然后这 *K* 个词的概率会被重新归一化,最后就在这重新被归一化概率后的 *K* 个词中采样。 GPT2 采用了这种采样方案,这也是它在故事生成这样的任务上取得成功的原因之一。
+
+我们将上文例子中的候选单词数从 3 个单词扩展到 10 个单词,以更好地说明 *Top-K* 采样。
+
+
+
+设 $K = 6$,即我们将在两个采样步的采样池大小限制为 6 个单词。我们定义 6 个最有可能的词的集合为 $V_{\text{top-K}}$。在第一步中,$V_{\text{top-K}}$ 仅占总概率的大约三分之二,但在第二步,它几乎占了全部的概率。同时,我们可以看到在第二步该方法成功地消除了那些奇怪的候选词 $(\text{``not"}, \text{``the"}, \text{``small"}, \text{``told" })$。
+
+我们以设置 `top_k=50` 为例看下如何在 `transformers` 库中使用 *Top-K*:
+
+``` python
+# set seed to reproduce results. Feel free to change the seed though to get different results
+tf.random.set_seed(0)
+
+# set top_k to 50
+sample_output = model.generate(
+ input_ids,
+ do_sample=True,
+ max_length=50,
+ top_k=50
+)
+
+print("Output:\n" + 100 * '-')
+print(tokenizer.decode(sample_output[0], skip_special_tokens=True))
+```
+
+
+
+ Output:
+ ----------------------------------------------------------------------------------------------------
+ I enjoy walking with my cute dog. It's so good to have an environment where your dog is available to share with you and we'll be taking care of you.
+
+ We hope you'll find this story interesting!
+
+ I am from
+
+
+
+相当不错!该文本可以说是迄今为止生成的最“*像人*”的文本。现在还有一个问题,*Top-K* 采样不会动态调整从需要概率分布 $P(w|w_{1:t-1})$ 中选出的单词数。这可能会有问题,因为某些分布可能是非常尖锐(上图中右侧的分布),而另一些可能更平坦(上图中左侧的分布),所以对不同的分布使用同一个绝对数 *K* 可能并不普适。
+
+在 $t=1$ 时,*Top-K* 将 $(\text{"people"}, \text{"big"}, \text{"house"}, \text{"cat"})$ 排出了采样池,而这些词似乎是合理的候选词。另一方面,在$t=2$ 时,该方法却又把不太合适的 $(\text{"down"}, \text{"a"})$ 纳入了采样池。因此,将采样池限制为固定大小 *K* 可能会在分布比较尖锐的时候产生胡言乱语,而在分布比较平坦的时候限制模型的创造力。这一发现促使 [Ari Holtzman 等人(2019)](https://arxiv.org/abs/1904.09751) 发明了 ***Top-p***- 或 ***核***- 采样。
+
+### Top-p(核)采样
+
+在 *Top-p* 中,采样不只是在最有可能的 *K* 个单词中进行,而是在累积概率超过概率 *p* 的最小单词集中进行。然后在这组词中重新分配概率质量。这样,词集的大小(*又名*集合中的词数)可以根据下一个词的概率分布动态增加和减少。好吧,说的很啰嗦,一图胜千言。
+
+
+
+假设 $p=0.92$ ,*Top-p* 采样对单词概率进行降序排列并累加,然后选择概率和首次超过 $p=92\%$ 的单词集作为采样池,定义为 $V_{\text{top-p}}$。在 $t=1$ 时 $V_{\text{top-p}}$ 有 9 个词,而在 $t=2$ 时它只需要选择前 3 个词就超过了 92%。其实很简单吧!可以看出,在单词比较不可预测时,它保留了更多的候选词,*如* $P(w | \text{"The''})$,而当单词似乎更容易预测时,只保留了几个候选词,*如* $(P(w | \text{"The"}, \text{"car"})$。
+
+好的,是时候看看它在 `transformers` 里怎么用了!我们可以通过设置 `0 < top_p < 1` 来激活 *Top-p* 采样:
+
+``` python
+# set seed to reproduce results. Feel free to change the seed though to get different results
+tf.random.set_seed(0)
+
+# deactivate top_k sampling and sample only from 92% most likely words
+sample_output = model.generate(
+ input_ids,
+ do_sample=True,
+ max_length=50,
+ top_p=0.92,
+ top_k=0
+)
+
+print("Output:\n" + 100 * '-')
+print(tokenizer.decode(sample_output[0], skip_special_tokens=True))
+```
+
+```
+Output:
+----------------------------------------------------------------------------------------------------
+I enjoy walking with my cute dog. He will never be the same. I watch him play.
+
+
+Guys, my dog needs a name. Especially if he is found with wings.
+
+
+What was that? I had a lot o
+```
+
+太好了,这看起来跟人类写的差不多了,虽然还不算完全是。
+
+虽然从理论上讲,*Top-p* 似乎比 *Top-K* 更优雅,但这两种方法在实践中都很有效。 *Top-p* 也可以与 *Top-K* 结合使用,这样可以避免排名非常低的词,同时允许进行一些动态选择。
+
+最后,如果想要获得多个独立采样的输出,我们可以*再次*设置参数 `num_return_sequences > 1`:
+
+``` python
+# set seed to reproduce results. Feel free to change the seed though to get different results
+tf.random.set_seed(0)
+
+# set top_k = 50 and set top_p = 0.95 and num_return_sequences = 3
+sample_outputs = model.generate(
+ input_ids,
+ do_sample=True,
+ max_length=50,
+ top_k=50,
+ top_p=0.95,
+ num_return_sequences=3
+)
+
+print("Output:\n" + 100 * '-')
+for i, sample_output in enumerate(sample_outputs):
+ print("{}: {}".format(i, tokenizer.decode(sample_output, skip_special_tokens=True)))
+```
+
+
+```
+Output:
+----------------------------------------------------------------------------------------------------
+0: I enjoy walking with my cute dog. It's so good to have the chance to walk with a dog. But I have this problem with the dog and how he's always looking at us and always trying to make me see that I can do something
+1: I enjoy walking with my cute dog, she loves taking trips to different places on the planet, even in the desert! The world isn't big enough for us to travel by the bus with our beloved pup, but that's where I find my love
+2: I enjoy walking with my cute dog and playing with our kids," said David J. Smith, director of the Humane Society of the US.
+
+"So as a result, I've got more work in my time," he said.
+
+
+```
+
+很酷,现在你拥有了所有可以在 `transformers` 里用模型来帮你写故事的工具了!
+
+### 总结
+
+在开放域语言生成场景中,作为最新的解码方法,*top-p* 和 *top-K* 采样于传统的 *贪心* 和 *波束* 搜索相比,似乎能产生更流畅的文本。但,最近有更多的证据表明 *贪心* 和 *波束* 搜索的明显缺陷 - 主要是生成重复的单词序列 - 是由模型(特别是模型的训练方式)引起的,而不是解码方法,*参见* [Welleck 等人 (2019)](https://arxiv.org/pdf/1908.04319.pdf)的论文。此外,如 [Welleck 等人(2020)](https://arxiv.org/abs/2002.02492)的论文所述,看起来 *top-K* 和 *top-p* 采样也会产生重复的单词序列。
+
+在 [Welleck 等人(2019)](https://arxiv.org/pdf/1908.04319.pdf)的论文中,作者表明,根据人类评估,在调整训练目标后,波束搜索相比 *Top-p* 采样能产生更流畅的文本。
+
+开放域语言生成是一个快速发展的研究领域,而且通常情况下这里没有放之四海而皆准的方法,因此必须了解哪种方法最适合自己的特定场景。
+
+好的方面是,*你*可以在 `transfomers` 中尝试所有不同的解码方法 🤗。
+
+以上是对如何在 `transformers` 中使用不同的解码方法以及开放域语言生成的最新趋势的简要介绍。
+
+非常欢迎大家在 [Github 代码库](https://github.com/huggingface/transformers) 上提供反馈和问题。
+
+如果想要体验下用模型生成故事的乐趣,可以访问我们的 web 应用 [Writing with Transformers](https://transformer.huggingface.co/)。
+
+感谢为本文做出贡献的所有人:Alexander Rush、Julien Chaumand、Thomas Wolf、Victor Sanh、Sam Shleifer、Clément Delangue、Yacine Jernite、Oliver Åstrand 和 John de Wasseige。
+
+### 附录
+
+`generate` 方法还有几个正文未提及的参数,这里我们简要解释一下它们!
+
+ - `min_length` 用于强制模型在达到 `min_length` 之前不生成 EOS。这在摘要场景中使用得比较多,但如果用户想要更长的文本输出,也会很有用。
+
+ - `repetition_penalty` 可用于对生成重复的单词这一行为进行惩罚。它首先由 [Keskar 等人(2019)](https://arxiv.org/abs/1909.05858)引入,在 [Welleck 等人(2019)](https://arxiv.org/pdf/1908.04319.pdf) 的工作中,它是训练目标的一部分。它可以非常有效地防止重复,但似乎对模型和用户场景非常敏感,其中一个例子见 Github 上的[讨论](https://github.com/huggingface/transformers/pull/2303)。
+
+ - `attention_mask` 可用于屏蔽填充符。
+
+ - `pad_token_id`、`bos_token_id`、`eos_token_id`:如果模型默认没有这些token,用户可以手动选择其他token id来表示它们。
+
+更多信息,请查阅 `generate` 函数 [手册](https://huggingface.co/transformers/main_classes/model.html?highlight=generate#transformers.TFPreTrainedModel.generate)。
+
+> 英文原文: https://huggingface.co/blog/how-to-generate
+> 原文作者:Patrick von Platen
+> 译者: Matrix Yao (姚伟峰),英特尔深度学习工程师,工作方向为 transformer-family 模型在各模态数据上的应用及大规模模型的训练推理。
From 2d38228bea64abc38b1a7f26eae7fe302212d63d Mon Sep 17 00:00:00 2001
From: SuSung-boy <872414318@qq.com>
Date: Sat, 22 Apr 2023 19:55:59 +0800
Subject: [PATCH 05/55] unity game in hf space translation completed
---
zh/unity-in-spaces.md | 129 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 129 insertions(+)
create mode 100644 zh/unity-in-spaces.md
diff --git a/zh/unity-in-spaces.md b/zh/unity-in-spaces.md
new file mode 100644
index 0000000000..8c56d4fda9
--- /dev/null
+++ b/zh/unity-in-spaces.md
@@ -0,0 +1,129 @@
+---
+title: "如何在 🤗 Space 上托管 Unity 游戏"
+thumbnail: /blog/assets/124_ml-for-games/unity-in-spaces-thumbnail.png
+authors:
+- user: dylanebert
+translators:
+- user: SuSung-boy
+---
+
+如何在 🤗 Space 上托管 Unity 游戏
+
+
+
+
+
+你知道吗?Hugging Face Space 可以托管自己开发的 Unity 游戏!惊不惊喜,意不意外?!来了解一下吧!
+
+Hugging Face Space 是一个能够以简单的方式来构建、托管和分享项目或应用样例的平台。虽然通常更多地是应用在机器学习样例中,不过实际上 Space 还可以用来托管 Unity 游戏,并且支持点击即玩。这里有一些游戏的 Space 示例:
+
+- [Huggy](https://huggingface.co/spaces/ThomasSimonini/Huggy)。Huggy 是一个基于强化学习构建的简易游戏,玩家可以点击鼠标扔出小木棍,来教宠物狗把木棍捡回来
+- [农场游戏](https://huggingface.co/spaces/dylanebert/FarmingGame)。农场游戏是我们在 <五天创建一个农场游戏> 系列中完成的游戏,玩家可以通过种植、收获和升级农作物来打造一个自己的繁荣农场
+- [Unity API Demo](https://huggingface.co/spaces/dylanebert/UnityDemo)。一个 Unity 样例
+
+本文将详细介绍如何在 🤗 Space 上托管自己的 Unity 游戏。
+
+## 第一步:使用静态 HTML 模板创建 Space 应用
+
+首先,导航至 [Hugging Face Spaces](https://huggingface.co/new-space) 页面,创建一个新的 Space 应用。
+
+
+
+
+
+选择 “静态 HTML” 模板,并为该 Space 取个名字,然后点击创建 Space。
+
+
+
+
+
+## 第 2 步:使用 Git 克隆 Space 库到本地
+
+使用 Git 将上一步创建的 Space 库克隆到本地。克隆命令如下:
+
+```
+git clone https://huggingface.co/spaces/{your-username}/{your-space-name}
+```
+
+## 第 3 步:打开 Unity 项目
+
+打开你希望在 🤗 Space 上托管的 Unity 项目。
+
+
+
+
+
+## 第 4 步:将构建目标切换为 WebGL
+
+点击菜单栏的 `File > Build Settings`,将构建目标切换为 WebGL。
+
+
+
+
+
+## 第 5 步:打开 Player Settings 面板
+
+在上一步打开的 Build Settings 窗口中,点击左下角的 “Player Settings” 按钮,打开 Player Settings 面板。
+
+
+
+
+
+## 第 6 步:(可选) 下载 Hugging Face Unity WebGL 模板
+
+Hugging Face Unity WebGL 模板可以使得你制作的游戏在 🤗 Space 上展示地更加美观。可以点击 [此处](https://github.com/huggingface/Unity-WebGL-template-for-Hugging-Face-Spaces) 下载模板库,并将其放到你的游戏项目目录,然后在 Player Settings 面板中将 WebGL 模板切换为 Hugging Face 即可。
+
+如下图所示,在 Player Settings 面板中点击 “Resolution and Presentation”,然后选择 Hugging Face WebGL 模板。
+
+
+
+
+
+## 第 7 步:禁用压缩
+
+在 Player Settings 面板中点击 “Publishing Settings”,将 Compression Format 改为 “Disabled” 来禁用压缩。
+
+
+
+
+
+## 第 8 步:构建游戏项目
+
+返回 Build Settings 窗口,并点击 “Build” 按钮,选择一个本地目录来保存构建的游戏项目文件。按照前几步的设置,Unity 将会把项目构建为 WebGL。
+
+
+
+
+
+## 第 9 步:将构建完成的文件复制到 Space 库
+
+构建过程完成之后,打开上一步中项目保存的本地目录,将该目录下的文件复制到 [第 2 步](#第-2-步使用-git-克隆-space-step-2-use-git-to-clone-the-space) 中克隆的 Space 库里。
+
+
+
+
+
+## 第 10 步:为大文件存储启用 Git-LFS
+
+打开 Space 库, 在该目录执行以下命令来追踪构建的大型文件。
+
+```
+git lfs install
+git track Build/*
+```
+
+## 第 11 步:Push 到 Hugging Face Space
+
+最后,将本地的 Space 库的所有改动推送到 Hugging Face Space 上。执行以下 Git 命令即可完成推送:
+
+```
+git add .
+git commit -m "Add Unity WebGL build files"
+git push
+```
+
+## 完成!
+
+至此,在 🤗 Space 上托管 Unity 游戏的所有步骤就都完成了。恭喜!现在请刷新你的 Space 页面,你就可以在 Space 上玩游戏了!
+
+希望本教程对你有所帮助。如果你有任何疑问,或想更多地参与到 Hugging Face 游戏相关的应用中,可以加入 Hugging Face 的官方 [Discord](https://hf.co/join/discord) 频道来与我们取得联系!
\ No newline at end of file
From 267b7e3fdf42c23eaf228dd89abd1533935adf23 Mon Sep 17 00:00:00 2001
From: Zhongdong Yang
Date: Sun, 23 Apr 2023 17:07:37 +0800
Subject: [PATCH 06/55] Update: punctuations of how-to-generate.md
---
zh/how-to-generate.md | 131 ++++++++++++++++++++----------------------
1 file changed, 63 insertions(+), 68 deletions(-)
diff --git a/zh/how-to-generate.md b/zh/how-to-generate.md
index 34b251e64c..33d2300905 100644
--- a/zh/how-to-generate.md
+++ b/zh/how-to-generate.md
@@ -5,9 +5,11 @@ authors:
- user: patrickvonplaten
translators:
- user: MatrixYao
+- user: zhongdongy
+ proofreader: true
---
-如何生成文本:通过 Transformers 用不同的解码方法生成文本
+如何生成文本: 通过 Transformers 用不同的解码方法生成文本
@@ -18,28 +20,26 @@ translators:
### 简介
-近年来,随着以OpenAI [GPT2 模型](https://openai.com/blog/better-language-models/)为代表的基于数百万网页数据训练的大型 transformer 语言模型的兴起,开放域语言生成领域吸引了越来越多的关注。开放域中的条件语言生成效果令人印象深刻,典型的例子有:[GPT2 在独角兽话题上的精彩续写](https://openai.com/blog/better-language-models/#samples),[XLNet](https://medium.com/@amanrusia/xlnet-speaks-comparison-to-gpt-2-ea1a4e9ba39e) 以及[使用 CTRL 模型生成受控文本](https://blog.einstein.ai/introducing-a-conditional-transformer-language-model-for-controllable-generation/)等。促成这些进展的除了 transformer 架构的改进和大规模无监督训练数据外,**更好的解码方法**也发挥了不可或缺的作用。
+近年来,随着以 OpenAI [GPT2 模型](https://openai.com/blog/better-language-models/) 为代表的基于数百万网页数据训练的大型 Transformer 语言模型的兴起,开放域语言生成领域吸引了越来越多的关注。开放域中的条件语言生成效果令人印象深刻,典型的例子有: [GPT2 在独角兽话题上的精彩续写](https://openai.com/blog/better-language-models/#samples),[XLNet](https://medium.com/@amanrusia/xlnet-speaks-comparison-to-gpt-2-ea1a4e9ba39e) 以及 [使用 CTRL 模型生成受控文本](https://blog.einstein.ai/introducing-a-conditional-transformer-language-model-for-controllable-generation/) 等。促成这些进展的除了 transformer 架构的改进和大规模无监督训练数据外,*更好的解码方法* 也发挥了不可或缺的作用。
本文简述了不同的解码策略,同时向读者展示了如何使用流行的 `transformers` 库轻松实现这些解码策略!
-下文中的所有功能均可用于**自回归**语言生成任务(点击[此处](http://jalammar.github.io/illustrated-gpt2/)复习)。简单复习一下,*自回归*语言生成是基于如下假设:一个文本序列的概率分布可以分解为每个词基于其上文的条件概率的乘积。
+下文中的所有功能均可用于 *自回归* 语言生成任务 (点击 [此处](http://jalammar.github.io/illustrated-gpt2/) 回顾)。简单复习一下, *自回归* 语言生成是基于如下假设: 一个文本序列的概率分布可以分解为每个词基于其上文的条件概率的乘积。
$$ P(w_{1:T} | W_0 ) = \prod_{t=1}^T P(w_{t} | w_{1: t-1}, W_0) \text{ , 其中 } w_{1: 0} = \emptyset, $$
-上式中,$W_0$ 是初始*上下文*单词序列。文本序列的长度 $T$ 通常时变的,并且对应于时间步 $t=T$。$P(w_{t} | w_{1: t- 1}, W_{0})$ 的词表中已包含 终止符(End Of Sequence,EOS) 。
+上式中,$W_0$ 是初始 *上下文* 单词序列。文本序列的长度 $T$ 通常时变的,并且对应于时间步 $t=T$。$P(w_{t} | w_{1: t- 1}, W_{0})$ 的词表中已包含 终止符 (End Of Sequence,EOS)。`transformers` 目前已支持的自回归语言生成任务包括 `GPT2`、`XLNet`、`OpenAi-GPT`、`CTRL`、`TransfoXL`、`XLM`、`Bart`、`T5` 模型,并支持 PyTorch 和 TensorFlow (>= 2.0) 两种框架!
-`transformers` 目前已支持的自回归语言生成任务包括 `GPT2`、`XLNet`、`OpenAi-GPT`、`CTRL`、`TransfoXL`、`XLM`、`Bart`、`T5` 模型,并支持 PyTorch 和 TensorFlow(>= 2.0)两种框架!
-
-我们会介绍目前最常用的解码方法,主要有*贪心搜索(Greedy search)*、*波束搜索(Beam search)*、*Top-K采样(Top-K sampling)* 以及 *Top-p采样(Top-p sampling)*。
+我们会介绍目前最常用的解码方法,主要有 *贪心搜索 (Greedy search)*、*波束搜索 (Beam search)*、*Top-K 采样 (Top-K sampling)* 以及 *Top-p 采样 (Top-p sampling)*。
在此之前,我们先快速安装一下 `transformers` 并把模型加载进来。本文我们用 GPT2 模型在 TensorFlow 2.1 中进行演示,但 API 和使用 PyTorch 框架是一一对应的。
-``` python
+```python
!pip install -q git+https://github.com/huggingface/transformers.git
!pip install -q tensorflow==2.1
```
-``` python
+```python
import tensorflow as tf
from transformers import TFGPT2LMHeadModel, GPT2Tokenizer
@@ -49,18 +49,17 @@ tokenizer = GPT2Tokenizer.from_pretrained("gpt2")
model = TFGPT2LMHeadModel.from_pretrained("gpt2",pad_token_id=tokenizer.eos_token_id)
```
-
### 贪心搜索
-贪心搜索在每个时间步 $t$ 都简单地选择概率最高的词作为当前输出词:$w_t = argmax_{w}P(w | w_{1:t-1})$ ,如下图所示。
+贪心搜索在每个时间步 $t$ 都简单地选择概率最高的词作为当前输出词: $w_t = argmax_{w}P(w | w_{1:t-1})$ ,如下图所示。
-从单词 $\text{"The"}$ 开始,算法在第一步贪心地选择条件概率最高的词 $\text{"nice"}$ 作为输出,依此往后。最终生成的单词序列为 $(\text{"The"}, \text{"nice"}, \text{"woman"})$,其联合概率为 $0.5 \times 0.4 = 0.2$ 。
+从单词 $\text{“The”}$ 开始,算法在第一步贪心地选择条件概率最高的词 $\text{“nice”}$ 作为输出,依此往后。最终生成的单词序列为 $(\text{“The”}, \text{“nice”}, \text{“woman”})$,其联合概率为 $0.5 \times 0.4 = 0.2$。
-下面,我们输入文本序列 $(\text{"I"}, \text{"enjoy"}, \text{"walking"}, \text{"with"}, \text{"my"}, \text{"cute"}, \text{"dog"})$ 给 GPT2 模型,让模型生成下文。我们以此为例看看如何在 `transformers` 中使用贪心搜索:
+下面,我们输入文本序列 $(\text{“I”}, \text{“enjoy”}, \text{“walking”}, \text{“with”}, \text{“my”}, \text{“cute”}, \text{“dog”})$ 给 GPT2 模型,让模型生成下文。我们以此为例看看如何在 `transformers` 中使用贪心搜索:
-``` python
+```python
# encode context the generation is conditioned on
input_ids = tokenizer.encode('I enjoy walking with my cute dog', return_tensors='tf')
@@ -81,27 +80,27 @@ print(tokenizer.decode(greedy_output[0], skip_special_tokens=True))
-好,我们已经用 GPT2 生成了第一个短文本😊。根据上文生成的单词是合理的,但模型很快开始输出重复的文本!这在语言生成中是一个非常普遍的问题,在贪心搜索和波束搜索中似乎更是如此 - 详见 [Vijayakumar 等人,2016](https://arxiv.org/abs/1610.02424) 和 [Shao等人,2017](https://arxiv.org/abs/1701.03185) 的论文。
+好,我们已经用 GPT2 生成了第一个短文本😊。根据上文生成的单词是合理的,但模型很快开始输出重复的文本!这在语言生成中是一个非常普遍的问题,在贪心搜索和波束搜索中似乎更是如此 - 详见 [Vijayakumar 等人,2016](https://arxiv.org/abs/1610.02424) 和 [Shao 等人,2017](https://arxiv.org/abs/1701.03185) 的论文。
-贪心搜索的主要缺点是它错过了隐藏在低概率词后面的高概率词,如上图所示:
+贪心搜索的主要缺点是它错过了隐藏在低概率词后面的高概率词,如上图所示:
-条件概率为 $0.9$ 的单词 $\text{"has"}$ 隐藏在单词 $\text{"dog"}$ 后面,而 $\text{"dog"}$ 因为在 `t=1` 时条件概率值只排第二所以未被选择,因此贪心搜索会错过序列 $\text{"The"}, \text {"dog"}, \text{"has"}$ 。
+条件概率为 $0.9$ 的单词 $\text{“has”}$ 隐藏在单词 $\text{“dog”}$ 后面,而 $\text{“dog”}$ 因为在 `t=1` 时条件概率值只排第二所以未被选择,因此贪心搜索会错过序列 $\text{“The”}, \text {“dog”}, \text{“has”}$ 。
幸好我们可以用波束搜索来缓解这个问题!
-
### 波束搜索
-波束搜索通过在每个时间步保留最可能的 `num_beams` 个词,并从中最终选择出概率最高的序列来降低丢失潜在的高概率序列的风险。以 `num_beams=2` 为例:
+
+波束搜索通过在每个时间步保留最可能的 `num_beams` 个词,并从中最终选择出概率最高的序列来降低丢失潜在的高概率序列的风险。以 `num_beams=2` 为例:
-在时间步 1,除了最有可能的假设 $(\text{"The"}, \text{"nice"})$,波束搜索还跟踪第二可能的假设 $(\ text{"The"}, \text{"dog"})$。在时间步 2,波束搜索发现序列 $(\text{"The"}, \text{"dog"}, \text{"has"})$ 概率为$0.36$,比 $(\text{"The"}, \text{"nice"}, \text{"woman"})$ 的 $0.2$更高。太棒了,在我们的例子中它已经找到了最有可能的序列!
+在时间步 1,除了最有可能的假设 $(\text{“The”}, \text{“nice”})$,波束搜索还跟踪第二可能的假设 $(\text{“The”}, \text{“dog”})$。在时间步 2,波束搜索发现序列 $(\text{“The”}, \text{“dog”}, \text{“has”})$ 概率为$0.36$,比 $(\text{“The”}, \text{“nice”}, \text{“woman”})$ 的 $0.2$ 更高。太棒了,在我们的例子中它已经找到了最有可能的序列!
波束搜索一般都会找到比贪心搜索概率更高的输出序列,但仍不保证找到全局最优解。
让我们看看如何在 `transformers` 中使用波束搜索。我们设置 `num_beams > 1` 和 `early_stopping=True` 以便在所有波束达到 EOS 时直接结束生成。
-``` python
+```python
# activate beam search and early_stopping
beam_output = model.generate(
input_ids,
@@ -124,11 +123,11 @@ print(tokenizer.decode(beam_output[0], skip_special_tokens=True))
-虽然结果比贪心搜索更流畅,但输出中仍然包含重复。一个简单的补救措施是引入 *n-grams*(即连续 n 个词的词序列)惩罚,该方法是由 [Paulus 等人 (2017)](https://arxiv.org/abs/1705.04304) 和 [Klein等人 (2017)](https://arxiv.org/abs/1701.02810) 引入的。最常见的 *n-grams* 惩罚是确保每个 *n-gram* 都只出现一次,方法是如果看到当前候选词与其上文所组成的 *n-gram* 已经出现过了,就将该候选词的概率设置为 0。
+虽然结果比贪心搜索更流畅,但输出中仍然包含重复。一个简单的补救措施是引入 *n-grams* (即连续 n 个词的词序列) 惩罚,该方法是由 [Paulus 等人 (2017)](https://arxiv.org/abs/1705.04304) 和 [Klein 等人 (2017)](https://arxiv.org/abs/1701.02810) 引入的。最常见的 *n-grams* 惩罚是确保每个 *n-gram* 都只出现一次,方法是如果看到当前候选词与其上文所组成的 *n-gram* 已经出现过了,就将该候选词的概率设置为 0。
-我们可以通过设置 `no_repeat_ngram_size=2` 来试试,这样任意 *2-gram* 不会出现两次:
+我们可以通过设置 `no_repeat_ngram_size=2` 来试试,这样任意 *2-gram* 不会出现两次:
-``` python
+```python
# set no_repeat_ngram_size to 2
beam_output = model.generate(
input_ids,
@@ -158,7 +157,7 @@ print(tokenizer.decode(beam_output[0], skip_special_tokens=True))
在 `transformers` 中,我们只需将参数 `num_return_sequences` 设置为需返回的概率最高的波束的数量,记得确保 `num_return_sequences <= num_beams`!
-``` python
+```python
# set return_num_sequences > 1
beam_outputs = model.generate(
input_ids,
@@ -199,12 +198,13 @@ for i, beam_output in enumerate(beam_outputs):
如我们所见,五个波束彼此之间仅有少量差别 —— 这在仅使用 5 个波束时不足为奇。
-开放域文本生成的研究人员最近提出了几个理由来说明对该领域而言波束搜索可能不是最佳方案:
- - 在机器翻译或摘要等任务中,因为所需生成的长度或多或少都是可预测的,所以波束搜索效果比较好 - 参见 [Murray 等人(2018)](https://arxiv.org/abs/1808.10006) 和 [Yang 等人(2018)](https://arxiv.org/abs/1808.09582)的工作。但开放域文本生成情况有所不同,其输出文本长度可能会有很大差异,如对话和故事生成的输出文本长度就有很大不同。
+开放域文本生成的研究人员最近提出了几个理由来说明对该领域而言波束搜索可能不是最佳方案:
+
+- 在机器翻译或摘要等任务中,因为所需生成的长度或多或少都是可预测的,所以波束搜索效果比较好 - 参见 [Murray 等人 (2018)](https://arxiv.org/abs/1808.10006) 和 [Yang 等人 (2018)](https://arxiv.org/abs/1808.09582) 的工作。但开放域文本生成情况有所不同,其输出文本长度可能会有很大差异,如对话和故事生成的输出文本长度就有很大不同。
- - 我们已经看到波束搜索已被证明存在重复生成的问题。在故事生成这样的场景中,很难用 *n-gram* 或其他惩罚来控制,因为在“不重复”和最大可重复*n-grams*之间找到一个好的折衷需要大量的微调。
+- 我们已经看到波束搜索已被证明存在重复生成的问题。在故事生成这样的场景中,很难用 *n-gram* 或其他惩罚来控制,因为在“不重复”和最大可重复 *n-grams* 之间找到一个好的折衷需要大量的微调。
- - 正如 [Ari Holtzman 等人(2019)](https://arxiv.org/abs/1904.09751)所论证的那样,高质量的人类语言并不遵循最大概率法则。换句话说,作为人类,我们希望生成的文本能让我们感到惊喜,而可预测的文本使人感觉无聊。论文作者画了一个概率图,很好地展示了这一点,从图中可以看出人类文本带来的惊喜度比波束搜索好不少。
+- 正如 [Ari Holtzman 等人 (2019)](https://arxiv.org/abs/1904.09751) 所论证的那样,高质量的人类语言并不遵循最大概率法则。换句话说,作为人类,我们希望生成的文本能让我们感到惊喜,而可预测的文本使人感觉无聊。论文作者画了一个概率图,很好地展示了这一点,从图中可以看出人类文本带来的惊喜度比波束搜索好不少。
![alt text](https://blog.fastforwardlabs.com/images/2019/05/Screen_Shot_2019_05_08_at_3_06_36_PM-1557342561886.png)
@@ -212,7 +212,7 @@ for i, beam_output in enumerate(beam_outputs):
### 采样
-在其最基本的形式中,采样意味着根据当前条件概率分布随机选择输出词 $w_t$:
+在其最基本的形式中,采样意味着根据当前条件概率分布随机选择输出词 $w_t$:
$$ w_t \sim P(w|w_{1:t-1}) $$
@@ -220,11 +220,11 @@ $$ w_t \sim P(w|w_{1:t-1}) $$
-很明显,使用采样方法时文本生成本身不再是*确定性的*。单词 $\text{"car"}$ 从条件概率分布 $P(w | \text{"The"})$ 中采样而得,而 $\text{"drives"}$ 则采样自 $(P(w | \text{"The"}, \text{"car"})$。
+很明显,使用采样方法时文本生成本身不再是 *确定性的*。单词 $\text{“car”}$ 从条件概率分布 $P(w | \text{“The”})$ 中采样而得,而 $\text{“drives”}$ 则采样自 $P(w | \text{“The”}, \text{“car”})$。
-在 `transformers` 中,我们设置 `do_sample=True` 并通过设置 `top_k=0` 停用 *Top-K* 采样(稍后详细介绍)。在下文中,为便于复现,我们会固定 `random_seed=0`,但你可以在自己的模型中随意更改 `random_seed`。
+在 `transformers` 中,我们设置 `do_sample=True` 并通过设置 `top_k=0` 停用 *Top-K* 采样 (稍后详细介绍)。在下文中,为便于复现,我们会固定 `random_seed=0`,但你可以在自己的模型中随意更改 `random_seed`。
-``` python
+```python
# set seed to reproduce results. Feel free to change the seed though to get different results
tf.random.set_seed(0)
@@ -252,19 +252,19 @@ print(tokenizer.decode(sample_output[0], skip_special_tokens=True))
-有意思!生成的文本看起来不错 - 但仔细观察会发现它不是很连贯。*3-grams* *new hand sense* 和 *local batte harness* 非常奇怪,看起来不像是人写的。这就是对单词序列进行采样时的大问题:模型通常会产生不连贯的乱码,*参见* [Ari Holtzman 等人(2019)](https://arxiv.org/abs/1904.09751)的论文。
+有意思!生成的文本看起来不错 - 但仔细观察会发现它不是很连贯。*3-grams* *new hand sense* 和 *local batte harness* 非常奇怪,看起来不像是人写的。这就是对单词序列进行采样时的大问题: 模型通常会产生不连贯的乱码,*参见* [Ari Holtzman 等人 (2019)](https://arxiv.org/abs/1904.09751) 的论文。
-缓解这一问题的一个技巧是通过降低所谓的[softmax](https://en.wikipedia.org/wiki/Softmax_function#Smooth_arg_max) 的“温度”使分布 $P(w|w_{1:t-1}$ 更陡峭。而降低“温度”,本质上是增加高概率单词的似然并降低低概率单词的似然。
+缓解这一问题的一个技巧是通过降低所谓的 [softmax](https://en.wikipedia.org/wiki/Softmax_function#Smooth_arg_max) 的“温度”使分布 $P(w|w_{1:t-1})$ 更陡峭。而降低“温度”,本质上是增加高概率单词的似然并降低低概率单词的似然。
将温度应用到于我们的例子中后,结果如下图所示。
-$t=1$ 时刻单词的条件分布变得更加陡峭,几乎没有机会选择单词 $\text{"car"}$ 了。
+$t=1$ 时刻单词的条件分布变得更加陡峭,几乎没有机会选择单词 $\text{“car”}$ 了。
-让我们看看如何通过设置 `temperature=0.7` 来冷却生成过程:
+让我们看看如何通过设置 `temperature=0.7` 来冷却生成过程:
-``` python
+```python
# set seed to reproduce results. Feel free to change the seed though to get different results
tf.random.set_seed(0)
@@ -293,17 +293,17 @@ print(tokenizer.decode(sample_output[0], skip_special_tokens=True))
### Top-K 采样
-[Fan 等人(2018)](https://arxiv.org/pdf/1805.04833.pdf)的论文介绍了一种简单但非常强大的采样方案,称为 ***Top-K*** 采样。在 *Top-K* 采样中,概率最大的 *K* 个词会被选出,然后这 *K* 个词的概率会被重新归一化,最后就在这重新被归一化概率后的 *K* 个词中采样。 GPT2 采用了这种采样方案,这也是它在故事生成这样的任务上取得成功的原因之一。
+[Fan 等人 (2018)](https://arxiv.org/pdf/1805.04833.pdf) 的论文介绍了一种简单但非常强大的采样方案,称为 ***Top-K*** 采样。在 *Top-K* 采样中,概率最大的 *K* 个词会被选出,然后这 *K* 个词的概率会被重新归一化,最后就在这重新被归一化概率后的 *K* 个词中采样。 GPT2 采用了这种采样方案,这也是它在故事生成这样的任务上取得成功的原因之一。
我们将上文例子中的候选单词数从 3 个单词扩展到 10 个单词,以更好地说明 *Top-K* 采样。
-设 $K = 6$,即我们将在两个采样步的采样池大小限制为 6 个单词。我们定义 6 个最有可能的词的集合为 $V_{\text{top-K}}$。在第一步中,$V_{\text{top-K}}$ 仅占总概率的大约三分之二,但在第二步,它几乎占了全部的概率。同时,我们可以看到在第二步该方法成功地消除了那些奇怪的候选词 $(\text{``not"}, \text{``the"}, \text{``small"}, \text{``told" })$。
+设 $K = 6$,即我们将在两个采样步的采样池大小限制为 6 个单词。我们定义 6 个最有可能的词的集合为 $V_{\text{top-K}}$。在第一步中,$V_{\text{top-K}}$ 仅占总概率的大约三分之二,但在第二步,它几乎占了全部的概率。同时,我们可以看到在第二步该方法成功地消除了那些奇怪的候选词 $(\text{“not”}, \text{“the”}, \text{“small”}, \text{“told”})$。
-我们以设置 `top_k=50` 为例看下如何在 `transformers` 库中使用 *Top-K*:
+我们以设置 `top_k=50` 为例看下如何在 `transformers` 库中使用 *Top-K*:
-``` python
+```python
# set seed to reproduce results. Feel free to change the seed though to get different results
tf.random.set_seed(0)
@@ -331,21 +331,21 @@ print(tokenizer.decode(sample_output[0], skip_special_tokens=True))
-相当不错!该文本可以说是迄今为止生成的最“*像人*”的文本。现在还有一个问题,*Top-K* 采样不会动态调整从需要概率分布 $P(w|w_{1:t-1})$ 中选出的单词数。这可能会有问题,因为某些分布可能是非常尖锐(上图中右侧的分布),而另一些可能更平坦(上图中左侧的分布),所以对不同的分布使用同一个绝对数 *K* 可能并不普适。
+相当不错!该文本可以说是迄今为止生成的最 "*像人*" 的文本。现在还有一个问题,*Top-K* 采样不会动态调整从需要概率分布 $P(w|w_{1:t-1})$ 中选出的单词数。这可能会有问题,因为某些分布可能是非常尖锐 (上图中右侧的分布),而另一些可能更平坦 (上图中左侧的分布),所以对不同的分布使用同一个绝对数 *K* 可能并不普适。
-在 $t=1$ 时,*Top-K* 将 $(\text{"people"}, \text{"big"}, \text{"house"}, \text{"cat"})$ 排出了采样池,而这些词似乎是合理的候选词。另一方面,在$t=2$ 时,该方法却又把不太合适的 $(\text{"down"}, \text{"a"})$ 纳入了采样池。因此,将采样池限制为固定大小 *K* 可能会在分布比较尖锐的时候产生胡言乱语,而在分布比较平坦的时候限制模型的创造力。这一发现促使 [Ari Holtzman 等人(2019)](https://arxiv.org/abs/1904.09751) 发明了 ***Top-p***- 或 ***核***- 采样。
+在 $t=1$ 时,*Top-K* 将 $(\text{“people”}, \text{“big”}, \text{“house”}, \text{“cat”})$ 排出了采样池,而这些词似乎是合理的候选词。另一方面,在$t=2$ 时,该方法却又把不太合适的 $(\text{“down”}, \text{“a”})$ 纳入了采样池。因此,将采样池限制为固定大小 *K* 可能会在分布比较尖锐的时候产生胡言乱语,而在分布比较平坦的时候限制模型的创造力。这一发现促使 [Ari Holtzman 等人 (2019)](https://arxiv.org/abs/1904.09751) 发明了 **Top-p**- 或 **核**- 采样。
-### Top-p(核)采样
+### Top-p (核) 采样
-在 *Top-p* 中,采样不只是在最有可能的 *K* 个单词中进行,而是在累积概率超过概率 *p* 的最小单词集中进行。然后在这组词中重新分配概率质量。这样,词集的大小(*又名*集合中的词数)可以根据下一个词的概率分布动态增加和减少。好吧,说的很啰嗦,一图胜千言。
+在 *Top-p* 中,采样不只是在最有可能的 *K* 个单词中进行,而是在累积概率超过概率 *p* 的最小单词集中进行。然后在这组词中重新分配概率质量。这样,词集的大小 (*又名* 集合中的词数) 可以根据下一个词的概率分布动态增加和减少。好吧,说的很啰嗦,一图胜千言。
-假设 $p=0.92$ ,*Top-p* 采样对单词概率进行降序排列并累加,然后选择概率和首次超过 $p=92\%$ 的单词集作为采样池,定义为 $V_{\text{top-p}}$。在 $t=1$ 时 $V_{\text{top-p}}$ 有 9 个词,而在 $t=2$ 时它只需要选择前 3 个词就超过了 92%。其实很简单吧!可以看出,在单词比较不可预测时,它保留了更多的候选词,*如* $P(w | \text{"The''})$,而当单词似乎更容易预测时,只保留了几个候选词,*如* $(P(w | \text{"The"}, \text{"car"})$。
+假设 $p=0.92$,*Top-p* 采样对单词概率进行降序排列并累加,然后选择概率和首次超过 $p=92%$ 的单词集作为采样池,定义为 $V_{\text{top-p}}$。在 $t=1$ 时 $V_{\text{top-p}}$ 有 9 个词,而在 $t=2$ 时它只需要选择前 3 个词就超过了 92%。其实很简单吧!可以看出,在单词比较不可预测时,它保留了更多的候选词,*如* $P(w | \text{“The”})$,而当单词似乎更容易预测时,只保留了几个候选词,*如* $P(w | \text{“The”}, \text{“car”})$。
-好的,是时候看看它在 `transformers` 里怎么用了!我们可以通过设置 `0 < top_p < 1` 来激活 *Top-p* 采样:
+好的,是时候看看它在 `transformers` 里怎么用了!我们可以通过设置 `0 < top_p < 1` 来激活 *Top-p* 采样:
-``` python
+```python
# set seed to reproduce results. Feel free to change the seed though to get different results
tf.random.set_seed(0)
@@ -362,7 +362,7 @@ print("Output:\n" + 100 * '-')
print(tokenizer.decode(sample_output[0], skip_special_tokens=True))
```
-```
+```
Output:
----------------------------------------------------------------------------------------------------
I enjoy walking with my cute dog. He will never be the same. I watch him play.
@@ -376,11 +376,11 @@ What was that? I had a lot o
太好了,这看起来跟人类写的差不多了,虽然还不算完全是。
-虽然从理论上讲,*Top-p* 似乎比 *Top-K* 更优雅,但这两种方法在实践中都很有效。 *Top-p* 也可以与 *Top-K* 结合使用,这样可以避免排名非常低的词,同时允许进行一些动态选择。
+虽然从理论上讲, *Top-p* 似乎比 *Top-K* 更优雅,但这两种方法在实践中都很有效。 *Top-p* 也可以与 *Top-K* 结合使用,这样可以避免排名非常低的词,同时允许进行一些动态选择。
-最后,如果想要获得多个独立采样的输出,我们可以*再次*设置参数 `num_return_sequences > 1`:
+最后,如果想要获得多个独立采样的输出,我们可以 *再次* 设置参数 `num_return_sequences > 1`:
-``` python
+```python
# set seed to reproduce results. Feel free to change the seed though to get different results
tf.random.set_seed(0)
@@ -399,8 +399,7 @@ for i, sample_output in enumerate(sample_outputs):
print("{}: {}".format(i, tokenizer.decode(sample_output, skip_special_tokens=True)))
```
-
-```
+```
Output:
----------------------------------------------------------------------------------------------------
0: I enjoy walking with my cute dog. It's so good to have the chance to walk with a dog. But I have this problem with the dog and how he's always looking at us and always trying to make me see that I can do something
@@ -416,13 +415,13 @@ Output:
### 总结
-在开放域语言生成场景中,作为最新的解码方法,*top-p* 和 *top-K* 采样于传统的 *贪心* 和 *波束* 搜索相比,似乎能产生更流畅的文本。但,最近有更多的证据表明 *贪心* 和 *波束* 搜索的明显缺陷 - 主要是生成重复的单词序列 - 是由模型(特别是模型的训练方式)引起的,而不是解码方法,*参见* [Welleck 等人 (2019)](https://arxiv.org/pdf/1908.04319.pdf)的论文。此外,如 [Welleck 等人(2020)](https://arxiv.org/abs/2002.02492)的论文所述,看起来 *top-K* 和 *top-p* 采样也会产生重复的单词序列。
+在开放域语言生成场景中,作为最新的解码方法, *top-p* 和 *top-K* 采样于传统的 *贪心* 和 *波束* 搜索相比,似乎能产生更流畅的文本。但,最近有更多的证据表明 *贪心* 和 *波束* 搜索的明显缺陷 - 主要是生成重复的单词序列 - 是由模型 (特别是模型的训练方式) 引起的,而不是解码方法, *参见* [Welleck 等人 (2019)](https://arxiv.org/pdf/1908.04319.pdf) 的论文。此外,如 [Welleck 等人 (2020)](https://arxiv.org/abs/2002.02492) 的论文所述,看起来 *top-K* 和 *top-p* 采样也会产生重复的单词序列。
-在 [Welleck 等人(2019)](https://arxiv.org/pdf/1908.04319.pdf)的论文中,作者表明,根据人类评估,在调整训练目标后,波束搜索相比 *Top-p* 采样能产生更流畅的文本。
+在 [Welleck 等人 (2019)](https://arxiv.org/pdf/1908.04319.pdf) 的论文中,作者表明,根据人类评估,在调整训练目标后,波束搜索相比 *Top-p* 采样能产生更流畅的文本。
开放域语言生成是一个快速发展的研究领域,而且通常情况下这里没有放之四海而皆准的方法,因此必须了解哪种方法最适合自己的特定场景。
-好的方面是,*你*可以在 `transfomers` 中尝试所有不同的解码方法 🤗。
+好的方面是, *你* 可以在 `transfomers` 中尝试所有不同的解码方法 🤗。
以上是对如何在 `transformers` 中使用不同的解码方法以及开放域语言生成的最新趋势的简要介绍。
@@ -430,22 +429,18 @@ Output:
如果想要体验下用模型生成故事的乐趣,可以访问我们的 web 应用 [Writing with Transformers](https://transformer.huggingface.co/)。
-感谢为本文做出贡献的所有人:Alexander Rush、Julien Chaumand、Thomas Wolf、Victor Sanh、Sam Shleifer、Clément Delangue、Yacine Jernite、Oliver Åstrand 和 John de Wasseige。
+感谢为本文做出贡献的所有人: Alexander Rush、Julien Chaumand、Thomas Wolf、Victor Sanh、Sam Shleifer、Clément Delangue、Yacine Jernite、Oliver Åstrand 和 John de Wasseige。
### 附录
`generate` 方法还有几个正文未提及的参数,这里我们简要解释一下它们!
- - `min_length` 用于强制模型在达到 `min_length` 之前不生成 EOS。这在摘要场景中使用得比较多,但如果用户想要更长的文本输出,也会很有用。
-
- - `repetition_penalty` 可用于对生成重复的单词这一行为进行惩罚。它首先由 [Keskar 等人(2019)](https://arxiv.org/abs/1909.05858)引入,在 [Welleck 等人(2019)](https://arxiv.org/pdf/1908.04319.pdf) 的工作中,它是训练目标的一部分。它可以非常有效地防止重复,但似乎对模型和用户场景非常敏感,其中一个例子见 Github 上的[讨论](https://github.com/huggingface/transformers/pull/2303)。
+- `min_length` 用于强制模型在达到 `min_length` 之前不生成 EOS。这在摘要场景中使用得比较多,但如果用户想要更长的文本输出,也会很有用。
- - `attention_mask` 可用于屏蔽填充符。
+- `repetition_penalty` 可用于对生成重复的单词这一行为进行惩罚。它首先由 [Keskar 等人 (2019)](https://arxiv.org/abs/1909.05858) 引入,在 [Welleck 等人 (2019)](https://arxiv.org/pdf/1908.04319.pdf) 的工作中,它是训练目标的一部分。它可以非常有效地防止重复,但似乎对模型和用户场景非常敏感,其中一个例子见 Github 上的 [讨论](https://github.com/huggingface/transformers/pull/2303)。
- - `pad_token_id`、`bos_token_id`、`eos_token_id`:如果模型默认没有这些token,用户可以手动选择其他token id来表示它们。
+- `attention_mask` 可用于屏蔽填充符。
-更多信息,请查阅 `generate` 函数 [手册](https://huggingface.co/transformers/main_classes/model.html?highlight=generate#transformers.TFPreTrainedModel.generate)。
+- `pad_token_id`、`bos_token_id`、`eos_token_id`: 如果模型默认没有这些 token,用户可以手动选择其他 token id 来表示它们。
-> 英文原文: https://huggingface.co/blog/how-to-generate
-> 原文作者:Patrick von Platen
-> 译者: Matrix Yao (姚伟峰),英特尔深度学习工程师,工作方向为 transformer-family 模型在各模态数据上的应用及大规模模型的训练推理。
+更多信息,请查阅 `generate` 函数 [手册](https://huggingface.co/transformers/main_classes/model.html?highlight=generate#transformers.TFPreTrainedModel.generate)。
\ No newline at end of file
From 9890cdb8c71fbb51b1e8423a0151b2a3cd236a4c Mon Sep 17 00:00:00 2001
From: "Yao, Matrix"
Date: Sun, 23 Apr 2023 14:04:03 -0400
Subject: [PATCH 07/55] hf-bitsandbytes-integration cn done
Signed-off-by: Yao, Matrix
---
zh/_blog.yml | 11 +
zh/hf-bitsandbytes-integration.md | 437 ++++++++++++++++++++++++++++++
2 files changed, 448 insertions(+)
create mode 100644 zh/hf-bitsandbytes-integration.md
diff --git a/zh/_blog.yml b/zh/_blog.yml
index e91a1587ab..d62c3e79b9 100644
--- a/zh/_blog.yml
+++ b/zh/_blog.yml
@@ -400,3 +400,14 @@
tags:
- guide
- nlp
+
+
+- local: hf-bitsandbytes-integration
+ title: "大规模 Transformer 模型 8 比特矩阵乘简介 - 基于 Hugging Face Transformers、Accelerate 以及 bitsandbytes"
+ author: ybelkada
+ thumbnail: /blog/assets/96_hf_bitsandbytes_integration/Thumbnail_blue.png
+ date: August 17, 2022
+ tags:
+ - nlp
+ - llm
+ - quantization
diff --git a/zh/hf-bitsandbytes-integration.md b/zh/hf-bitsandbytes-integration.md
new file mode 100644
index 0000000000..cc30759d74
--- /dev/null
+++ b/zh/hf-bitsandbytes-integration.md
@@ -0,0 +1,437 @@
+---
+title: "大规模 Transformer 模型 8 比特矩阵乘简介 - 基于 Hugging Face Transformers、Accelerate 以及 bitsandbytes"
+thumbnail: /blog/assets/96_hf_bitsandbytes_integration/Thumbnail_blue.png
+authors:
+- user: ybelkada
+- user: timdettmers
+ guest: true
+translators:
+- user: MatrixYao
+---
+
+# 大规模 Transformer 模型 8 比特矩阵乘简介 - 基于 Hugging Face Transformers、Accelerate 以及 bitsandbytes
+
+
+
+
+![thumbnail](/blog/assets/96_hf_bitsandbytes_integration/Thumbnail_blue.png)
+
+## 引言
+
+语言模型一直在变大。截至撰写本文时,PaLM 有 5400 亿参数,OPT、GPT-3 和 BLOOM 有大约 1760 亿参数,而且我们仍在继续朝着更大的模型发展。下图总结了最近的一些语言模型的尺寸。
+
+![LLM](/blog/assets/96_hf_bitsandbytes_integration/LLM3.png)
+
+由于这些模型很大,因此它们很难在一般的设备上运行。举个例子,仅推理 BLOOM-176B 模型,你就需要 8 个 80GB A100 GPU(每个约 15,000 美元)。而如果要微调 BLOOM-176B 的话,你需要 72 个这样的 GPU!更大的模型,如 PaLM,还需要更多资源。
+
+由于这些庞大的模型需要大量 GPU 才能运行,因此我们需要找到降低资源需求而同时保持模型性能的方法。目前已有一些试图缩小模型尺寸的技术,比如你可能听说过的量化和蒸馏等技术。
+
+完成 BLOOM-176B 的训练后,Hugging Face 和 BigScience 一直在寻找能让这个大模型更容易在更少的 GPU 上运行的方法。通过我们的 BigScience 社区,我们了解到一些有关 Int8 推理的研究,它不会降低大模型的预测性能,而且可以将大模型的内存占用量减少 2 倍。很快我们就开始合作进行这项研究,最终将其完全整合到 Hugging Face `transformers` 中。本文我们将详述我们集成在Hugging Face 中的 LLM.int8() 方案,它适用于所有 Hugging Face 模型。如果你想了解更多研究细节,可以阅读我们的论文 [LLM.int8(): 8-bit Matrix Multiplication for Transformers at Scale](https://arxiv.org/abs/2208.07339)。
+
+本文将主要介绍 LLM.int8() 量化技术,讨论将其纳入 `transformers` 库的过程中经历的困难,并对后续工作进行了计划。
+
+在这里,你将了解到究竟是什么让一个大模型占用这么多内存?是什么让 BLOOM 占用了 350GB 内存?我们先从一些基础知识开始,慢慢展开。
+
+## 机器学习中常用的数据类型
+
+我们从理解不同浮点数据类型开始,这些数据类型在机器学习中也被称为“精度”。
+
+模型的大小由其参数量及其精度决定,精度通常为 float32、float16 或 bfloat16 之一([下图来源](https://blogs.nvidia.com/blog/2020/05/14/tensorfloat-32-precision-format/))。
+
+![Summary](/blog/assets/96_hf_bitsandbytes_integration/tf32-Mantissa-chart-hi-res-FINAL.png)
+
+Float32 (FP32) 是标准的 IEEE 32 位浮点表示。使用该数据类型,可以表示大范围的浮点数。在 FP32 中,为“指数”保留了 8 位,为“尾数”保留了 23 位,为符号保留了 1 位。因为是标准数据类型,所以大部分硬件都支持 FP32 运算指令。
+
+而在 Float16 (FP16) 数据类型中,指数保留 5 位,尾数保留 10 位。这使得 FP16 数字的数值范围远低于 FP32。因此 FP16 存在上溢(当用于表示非常大的数时)和下溢(当用于表示非常小的数时)的风险。
+
+例如,当你执行 `10k * 10k` 时,最终结果应为 `100M`,FP16 无法表示该数,因为 FP16 能表示的最大数是 `64k`。因此你最终会得到 `NaN`(Not a Number,不是数字),在神经网络的计算中,因为计算是按层和 batch 顺序进行的,因此一旦出现 `NaN`,之前的所有计算就全毁了。一般情况下,我们可以通过缩放损失(loss scaling)来缓解这个问题,但该方法并非总能奏效。
+
+于是我们发明了一种新格式 Bfloat16 (BF16) 来规避这些限制。BF16 为指数保留了 8 位(与 FP32 相同),为小数保留了 7 位。这意味着使用 BF16 我们可以保留与 FP32 相同的动态范围。但是相对于 FP16,我们损失了 3 位精度。因此,在使用 BF16 精度时,大数值绝对没有问题,但是精度会比 FP16 差。
+
+在 Ampere 架构中,NVIDIA 还引入了 [TensorFloat-32](https://blogs.nvidia.com/blog/2020/05/14/tensorfloat-32-precision-format/)(TF32) 精度格式,它使用 19 位表示,结合了 BF16 的范围和 FP16 的精度。目前,它仅在某些操作的内部使用[译者注:即 TF32 是一个计算数据类型而不是存储数据类型]。
+
+在机器学习术语中,FP32 称为全精度(4 字节),而 BF16 和 FP16 称为半精度(2 字节)。除此以外,还有 Int8 (INT8) 数据类型,它是一个 8 位的整型数据表示,可以存储 $2^8$ 个不同的值(对于有符号整数,区间为 [-128, 127],而对于无符号整数,区间为[0, 255])。
+
+虽然理想情况下训练和推理都应该在 FP32 中完成,但 FP32 比 FP16/BF16 慢两倍,因此实践中常常使用混合精度方法,其中,使用 FP32 权重作为精确的 “主权重(master weight)”,而使用 FP16/BF16 权重进行前向和后向传播计算以提高训练速度,最后在梯度更新阶段再使用 FP16/BF16 梯度更新 FP32 主权重。
+
+在训练期间,主权重始终为 FP32。而在实践中,在推理时,半精度权重通常能提供与 FP32 相似的精度 —— 因为只有在模型梯度更新时才需要精确的 FP32 权重。这意味着在推理时我们可以使用半精度权重,这样我们仅需一半 GPU 显存就能获得相同的结果。
+
+![Model-storage](/blog/assets/96_hf_bitsandbytes_integration/Model-storage.png)
+
+以字节为单位计算模型大小时,需要将参数量乘以所选精度的大小(以字节为单位)。例如,如果我们使用 BLOOM-176B 模型的 Bfloat16 版本,其大小就应为 $176 \times 10^{9} \times 2 字节 = 352GB$!如前所述,这个大小需要多个 GPU 才能装得下,这是一个相当大的挑战。
+
+但是,如果我们可以使用另外的数据类型来用更少的内存存储这些权重呢?深度学习社区已广泛使用的方法是量化。
+
+## 模型量化简介
+
+通过实验,我们发现不使用 4 字节 FP32 精度转而使用 2 字节 BF16/FP16 半精度可以获得几乎相同的推理结果,同时模型大小会减半。这促使我们想进一步削减内存,但随着我们使用更低的精度,推理结果的质量也开始急剧下降。
+
+为了解决这个问题,我们引入了 8 位量化。仅用四分之一精度,因此模型大小也仅需 1/4!但这次,我们不能简单地丢弃另一半位宽了。
+
+基本上讲,量化过程是从一种数据类型“舍入”到另一种数据类型。举个例子,如果一种数据类型的范围为 `0..9`,而另一种数据类型的范围为 `0..4`,则第一种数据类型中的值 `4` 将舍入为第二种数据类型中的 `2` 。但是,如果在第一种数据类型中有值 `3`,它介于第二种数据类型的 `1` 和 `2` 之间,那么我们通常会四舍五入为 `2`。也就是说,第一种数据类型的值 `4` 和 `3` 在第二种数据类型中具有相同的值 `2`。这充分表明量化是一个有噪过程,会导致信息丢失,是一种有损压缩。
+
+两种最常见的 8 位量化技术是零点量化(zero-point quantization)和最大绝对值 (absolute maximum quantization,absmax) 量化。它们都将浮点值映射为更紧凑的 Int8(1 字节)值。这些方法的第一步都是用量化常数对输入进行归一化缩放。
+
+在零点量化中,如果我的数值范围是 `-1.0…1.0`,我想量化到 `-127…127`,我需要先缩放 `127`倍,然后四舍五入到 `8` 位精度。要恢复原始值,我需要将 Int8 值除以相同的量化因子 `127`。在这个例子中,值 `0.3` 将缩放为 `0.3*127 = 38.1`。四舍五入后得到值 `38`。恢复时,我们会得到 `38/127=0.2992` —— 因此最终会有 `0.008` 的量化误差。这些看似微小的误差在沿着模型各层传播时往往会累积和增长,从而导致最终的精度下降。[译者注:这个例子举得不好,因为浮点范围和整型范围都是对称的,所以不存在零点调整了,而零点调整是零点量化中最能体现其命名原因的部分。简而言之,零点量化分为两步,第一步值域映射,即通过缩放将原始的数值范围映射为量化后的数值范围;第二步零点调整,即通过平移将映射后的数据的最小值对齐为目标值域的最小值]
+
+![quantization](/blog/assets/96_hf_bitsandbytes_integration/quantization.png)
+
+([图源](https://intellabs.github.io/distiller/algo_quantization.html) )
+
+现在我们再看下 absmax 量化的细节。要计算 absmax 量化中 fp16 数与其对应的 int8 数之间的映射,你必须先除以张量的最大绝对值,然后再乘以数据类型的最大可表示值。
+
+例如,假设你要用 absmax 对向量 `[1.2, -0.5, -4.3, 1.2, -3.1, 0.8, 2.4, 5.4]` 进行量化。首先需要计算该向量元素的最大绝对值,在本例中为 `5.4`。 Int8 的范围为 `[-127, 127]`,因此我们将 `127` 除以 `5.4`,得到缩放因子 `23.5`。最后,将原始向量乘以缩放因子得到最终的量化向量 `[28, -12, -101, 28, -73, 19, 56, 127]`。
+
+![out-quant.gif](/blog/assets/96_hf_bitsandbytes_integration/out-quant.gif)
+
+要恢复原向量,可以将 int8 量化值除以缩放因子,但由于上面的过程是“四舍五入”的,我们将丢失一些精度。
+
+![quant-freeze](/blog/assets/96_hf_bitsandbytes_integration/quant-freeze.png)
+
+对于无符号 Int8,我们可以先减去最小值然后再用最大绝对值来缩放,这与零点量化的做法相似。其做法也与最小-最大缩放(min-max scaling)类似,但后者在缩放时会额外保证输入中的 `0` 始终映射到一个整数,从而保证 `0` 的量化是无误差的。
+
+当进行矩阵乘法时,我们可以通过组合各种技巧,例如逐行或逐向量量化,来获取更精确的结果。举个例子,对矩阵乘法 $A \times B=C$,我们不会直接使用常规量化方式,即用整个张量的最大绝对值对张量进行归一化,而会转而使用向量量化方法,找到 A 的每一行和 B 的每一列的最大绝对值,然后逐行或逐列归一化 A 和 B 。最后将 A 与 B 相乘得到 C。最后,我们再计算与 A 和 B 的最大绝对值向量的外积,并将此与 C 求哈达玛积来反量化回 FP16。有关此技术的更多详细信息可以参考 [LLM.int8() 论文](https://arxiv.org/abs/2208.07339) 或 Tim 的博客上的[关于量化和涌现特征的博文](https://timdettmers.com/2022/08/17/llm-int8-and-emergent-features/)。
+
+虽然这些基本技术能够帮助我们量化深度学习模型,但它们通常会导致大模型准确性的下降。我们集成到 Hugging Face Transformers 和 Accelerate 库中的 LLM.int8() 是第一个适用于大模型(如 BLOOM-176B)且不会降低准确性的量化技术。
+
+## 简要总结 LLM.int8():大语言模型的零退化矩阵乘法
+
+在 LLM.int8() 中,我们已经证明理解 transformer 模型表现出的与模型规模相关的涌现特性对于理解为什么传统量化对大模型失效至关重要。我们证明性能下降是由离群特征(outlier feature)引起的,下一节我们会详细解释。LLM.int8() 算法本身如下。
+
+本质上,LLM.int8() 通过三个步骤完成矩阵乘法计算:
+1. 从输入的隐含状态中,按列提取异常值(即大于某个阈值的值)。
+2. 对 FP16 离群值矩阵和 Int8 非离群值矩阵分别作矩阵乘法。
+3. 反量化非离群值的矩阵乘结果并其与离群值矩阵乘结果相加,获得最终的 FP16 结果。
+
+该过程可以总结为如下动画:
+
+![Mixed-int8.gif](/blog/assets/96_hf_bitsandbytes_integration/Mixed-int8.gif)
+
+### 离群特征的重要性
+
+超出某个分布范围的值通常称为离群值。离群值检测已得到广泛应用,在很多文献中也有涉及,且获取特征的先验分布对离群值检测任务很有助益。更具体地说,我们观察到对于参数量大于 6B 的 transformer 模型,经典的量化方法会失效。虽然离群值特征也存在于较小的模型中,但在大于 6B 的 transformer 模型中,我们观察到几乎每层都会出现超出特定阈值的离群点,而且这些离群点呈现出一定的系统性模式。有关该现象的更多详细信息,请参阅 [LLM.int8() 论文](https://arxiv.org/abs/2208.07339) 和 [涌现特征的博文](https://timdettmers.com/2022/08/17/llm-int8-and-emergent-features/)。
+
+如前所述,8 位精度的动态范围极其有限,因此量化具有多个大值的向量会产生严重误差。此外,由于 transformer 架构的固有特性,它会将所有元素互相关联起来,这样的话,这些误差在传播几层后往往会混杂在一起。因此,我们发明了混合精度分解的方法,以对此类极端离群值进行有效量化。接下来我们对此方法进行讨论。
+
+### MatMul 内部
+
+计算隐含状态后,我们使用自定义阈值提取离群值,并将矩阵分解为两部分,如上所述。我们发现,以这种方式提取所有幅度大于等于 6 的离群值可以完全恢复推理精度。离群值部分使用 FP16 表示,因此它是一个经典的矩阵乘法,而 8 位矩阵乘法是通过使用向量量化将权重和隐含状态分别量化为 8 位精度 - 即按行量化权重矩阵,并按列量化隐含状态,然后再进行相应向量乘加操作。最后,将结果反量化至半精度,以便与第一个矩阵乘法的结果相加。
+
+![Matmul.png](/blog/assets/96_hf_bitsandbytes_integration/Matmul.png)
+
+### 0 退化是什么意思?
+
+我们如何正确评估该方法是否会对性能造成下降?使用 8 位模型时,我们的生成质量损失了多少?
+
+我们使用 `lm-eval-harness` 在 8 位和原始模型上运行了几个常见的基准测试,结果如下。
+
+对 OPT-175B 模型:
+
+| 测试基准 | - | - | - | - | 差值 |
+| ---------- | --------- | ---------------- | -------------------- | -------------------- | -------------------- |
+| 测试基准名 | 指标 | 指标值 - int8 | 指标值 - fp16 | 标准差 - fp16 | - |
+| hellaswag | acc\_norm | 0.7849 | 0.7849 | 0.0041 | 0 |
+| hellaswag | acc | 0.5921 | 0.5931 | 0.0049 | 0.001 |
+| piqa | acc | 0.7965 | 0.7959 | 0.0094 | 0.0006 |
+| piqa | acc\_norm | 0.8101 | 0.8107 | 0.0091 | 0.0006 |
+| lambada | ppl | 3.0142 | 3.0152 | 0.0552 | 0.001 |
+| lambada | acc | 0.7464 | 0.7466 | 0.0061 | 0.0002 |
+| winogrande | acc | 0.7174 | 0.7245 | 0.0125 | 0.0071 |
+
+对 BLOOM-176 模型:
+
+| 测试基准 | - | - | - | - | 差值 |
+| ---------- | --------- | ---------------- | -------------------- | -------------------- | -------------------- |
+| 测试基准名 | 指标 | 指标值 - int8 | 指标值 - fp16 | 标准差 - fp16 | - |
+| hellaswag | acc\_norm | 0.7274 | 0.7303 | 0.0044 | 0.0029 |
+| hellaswag | acc | 0.5563 | 0.5584 | 0.005 | 0.0021 |
+| piqa | acc | 0.7835 | 0.7884 | 0.0095 | 0.0049 |
+| piqa | acc\_norm | 0.7922 | 0.7911 | 0.0095 | 0.0011 |
+| lambada | ppl | 3.9191 | 3.931 | 0.0846 | 0.0119 |
+| lambada | acc | 0.6808 | 0.6718 | 0.0065 | 0.009 |
+| winogrande | acc | 0.7048 | 0.7048 | 0.0128 | 0 |
+
+我们切实地看到上述这些模型的性能下降为 0,因为指标的绝对差异均低于原始模型的标准误差(BLOOM-int8 除外,它在 lambada 上略好于原始模型)。如果想要知道 LLM.int8() 与当前其他先进方法的更详细的性能比较,请查看[论文](https://arxiv.org/abs/2208.07339)!
+
+### 比原始模型更快吗?
+LLM.int8() 方法的主要目的是在不降低性能的情况下降低大模型的应用门槛。但如果速度非常慢,该方法用处也不会很大。所以我们对多个模型的生成速度进行了基准测试。
+
+我们发现使用了 LLM.int8() 的 BLOOM-176B 比 FP16 版本慢了大约 15% 到 23% —— 这应该是完全可以接受的。我们发现较小模型(如 T5-3B 和 T5-11B)的降速幅度更大。我们还在努力优化这些小模型的推理速度。在一天之内,我们可以将 T5-3B 的每词元推理延迟从 312 毫秒降低到 173 毫秒,将 T5-11B 从 45 毫秒降低到 25 毫秒。此外,我们[已经找到原因](https://github.com/TimDettmers/bitsandbytes/issues/6#issuecomment-1211345635),在即将发布的版本中,LLM.int8() 在小模型上的推理速度可能会更快。下表列出了当前版本的一些性能数据。
+
+
+| 精度 | 参数量 | 硬件 | 每词元延迟(单位:毫秒,batch size: 1)| 每词元延迟(单位:毫秒,batch size: 8) | 每词元延迟(单位:毫秒,batch size: 32) |
+| -------------- | -------------------- | ------------ | ----------------------------------------------- | ----------------------------------------------- | ------------------------------------------------ |
+| bf16 | 176B | 8xA100 80GB | 239 | 32 | 9.9 |
+| int8 | 176B | 4xA100 80GB | 282 | 37.5 | 10.2 |
+| bf16 | 176B | 14xA100 40GB | 285 | 36.5 | 10.4 |
+| int8 | 176B | 5xA100 40GB | 367 | 46.4 | oom |
+| fp16 | 11B | 2xT4 15GB | 11.7 | 1.7 | 0.5 |
+| int8 | 11B | 1xT4 15GB | 43.5 | 5.3 | 1.3 |
+| fp32 | 3B | 2xT4 15GB | 45 | 7.2 | 3.1 |
+| int8 | 3B | 1xT4 15GB | 312 | 39.1 | 10.2 |
+
+上表中的3个模型分别为 BLOOM-176B、T5-11B 和 T5-3B。
+
+## Hugging Face `transformers` 集成细节
+
+接下来让我们讨论在 Hugging Face `transformers` 集成该方法的细节,向你展示常见的用法及在使用过程中可能遇到的常见问题。
+
+### 用法
+
+所有的操作都集成在 `Linear8bitLt` 模块中,你可以轻松地从 `bitsandbytes` 库中导入它。它是 `torch.nn.modules` 的子类,你可以仿照下述代码轻松地将其应用到自己的模型中。
+
+下面以使用 `bitsandbytes` 将一个小模型转换为 int8 为例,并给出相应的步骤。
+
+1. 首先导入模块,如下。
+
+```py
+import torch
+import torch.nn as nn
+
+import bitsandbytes as bnb
+from bnb.nn import Linear8bitLt
+```
+
+2. 然后就可以定义自己的模型了。请注意,我们支持将任何精度的 checkpoint 或模型转换为 8 位(FP16、BF16 或 FP32),但目前,仅当模型的输入张量数据类型为 FP16 时,我们的 Int8 模块才能工作。因此,这里我们称模型为 fp16 模型。
+
+```py
+fp16_model = nn.Sequential(
+ nn.Linear(64, 64),
+ nn.Linear(64, 64)
+)
+```
+
+3. 假设你已经在你的数据集和任务上训完了你的模型!现在需要保存模型:
+
+```py
+[... train the model ...]
+torch.save(fp16_model.state_dict(), "model.pt")
+```
+
+4. 至此,`state_dict` 已保存,我们需要定义一个 int8 模型:
+
+```py
+int8_model = nn.Sequential(
+ Linear8bitLt(64, 64, has_fp16_weights=False),
+ Linear8bitLt(64, 64, has_fp16_weights=False)
+)
+```
+此处标志变量 `has_fp16_weights` 非常重要。默认情况下,它设置为 `True`,用于在训练时使能 Int8/FP16 混合精度。但是,因为在推理中我们对内存节省更感兴趣,因此我们需要设置 `has_fp16_weights=False`。
+
+5. 现在加载 8 位模型!
+
+```py
+int8_model.load_state_dict(torch.load("model.pt"))
+int8_model = int8_model.to(0) # 量化发生在此处
+```
+
+请注意,一旦将模型的设备设置为 GPU,量化过程就会在第二行代码中完成。如果在调用 `.to` 函数之前打印 `int8_model[0].weight`,你会看到:
+
+```
+int8_model[0].weight
+Parameter containing:
+tensor([[ 0.0031, -0.0438, 0.0494, ..., -0.0046, -0.0410, 0.0436],
+ [-0.1013, 0.0394, 0.0787, ..., 0.0986, 0.0595, 0.0162],
+ [-0.0859, -0.1227, -0.1209, ..., 0.1158, 0.0186, -0.0530],
+ ...,
+ [ 0.0804, 0.0725, 0.0638, ..., -0.0487, -0.0524, -0.1076],
+ [-0.0200, -0.0406, 0.0663, ..., 0.0123, 0.0551, -0.0121],
+ [-0.0041, 0.0865, -0.0013, ..., -0.0427, -0.0764, 0.1189]],
+ dtype=torch.float16)
+```
+
+而如果你在第二行之后打印它,你会看到:
+
+```
+int8_model[0].weight
+Parameter containing:
+tensor([[ 3, -47, 54, ..., -5, -44, 47],
+ [-104, 40, 81, ..., 101, 61, 17],
+ [ -89, -127, -125, ..., 120, 19, -55],
+ ...,
+ [ 82, 74, 65, ..., -49, -53, -109],
+ [ -21, -42, 68, ..., 13, 57, -12],
+ [ -4, 88, -1, ..., -43, -78, 121]],
+ device='cuda:0', dtype=torch.int8, requires_grad=True)
+```
+正如我们在前面部分解释量化方法时所讲,权重值被“截断”了。此外,这些值的分布看上去在 [-127, 127] 之间。
+
+你可能还想知道如何获取 FP16 权重以便在 FP16 中执行离群值的矩阵乘?很简单:
+
+```py
+(int8_model[0].weight.CB * int8_model[0].weight.SCB) / 127
+```
+
+你会看到:
+
+```
+tensor([[ 0.0028, -0.0459, 0.0522, ..., -0.0049, -0.0428, 0.0462],
+ [-0.0960, 0.0391, 0.0782, ..., 0.0994, 0.0593, 0.0167],
+ [-0.0822, -0.1240, -0.1207, ..., 0.1181, 0.0185, -0.0541],
+ ...,
+ [ 0.0757, 0.0723, 0.0628, ..., -0.0482, -0.0516, -0.1072],
+ [-0.0194, -0.0410, 0.0657, ..., 0.0128, 0.0554, -0.0118],
+ [-0.0037, 0.0859, -0.0010, ..., -0.0423, -0.0759, 0.1190]],
+ device='cuda:0')
+```
+
+这跟第一次打印的原始 FP16 值很接近!
+
+6. 现在你只需将输入推给正确的 GPU 并确保输入数据类型是 FP16 的,你就可以使用该模型进行推理了:
+
+```py
+input_ = torch.randn(64, dtype=torch.float16)
+hidden_states = int8_model(input_.to(torch.device('cuda', 0)))
+```
+
+你可以查看[示例脚本](/blog/assets/96_hf_bitsandbytes_integration/example.py) ,获取完整的示例代码!
+
+多说一句,`Linear8bitLt` 与 `nn.Linear` 模块略有不同,主要在 `Linear8bitLt` 的参数属于 `bnb.nn.Int8Params` 类而不是 `nn.Parameter` 类。稍后你会看到这给我们带来了一些小麻烦!
+
+现在我们开始了解如何将其集成到 `transformers` 库中!
+
+### `accelerate` 足矣
+
+在处理大模型时,`accelerate` 库包含许多有用的工具。`init_empty_weights` 方法特别有用,因为任何模型,无论大小,都可以在此方法的上下文(context)内进行初始化,而无需为模型权重分配任何内存。
+
+```py
+import torch.nn as nn
+from accelerate import init_empty_weights
+
+with init_empty_weights():
+ model = nn.Sequential([nn.Linear(100000, 100000) for _ in range(1000)]) # This will take ~0 RAM!
+```
+初始化过的模型将放在 PyTorch 的 `meta` 设备上,这是一种用于表征向量的形状和数据类型而无需实际的内存分配的超酷的底层机制。
+
+最初,我们在 `.from_pretrained` 函数内部调用 `init_empty_weights`,并将所有参数重载为 `torch.nn.Parameter`。这不是我们想要的,因为在我们的情况中,我们希望为 `Linear8bitLt` 模块保留 `Int8Params` 类,如上所述。我们最后成功使用 [此 PR](https://github.com/huggingface/accelerate/pull/519) 修复了该问题,它将下述代码:
+
+```py
+module._parameters[name] = nn.Parameter(module._parameters[name].to(torch.device("meta")))
+```
+
+修改成:
+
+```py
+param_cls = type(module._parameters[name])
+kwargs = module._parameters[name].__dict__
+module._parameters[name] = param_cls(module._parameters[name].to(torch.device("meta")), **kwargs)
+```
+
+现在这个问题已经解决了,我们可以轻松地在一个自定义函数中利用这个上下文管理器将所有 `nn.Linear` 模块替换为 `bnb.nn.Linear8bitLt` 而无需占用内存!
+
+```py
+def replace_8bit_linear(model, threshold=6.0, module_to_not_convert="lm_head"):
+ for name, module in model.named_children():
+ if len(list(module.children())) > 0:
+ replace_8bit_linear(module, threshold, module_to_not_convert)
+
+ if isinstance(module, nn.Linear) and name != module_to_not_convert:
+ with init_empty_weights():
+ model._modules[name] = bnb.nn.Linear8bitLt(
+ module.in_features,
+ module.out_features,
+ module.bias is not None,
+ has_fp16_weights=False,
+ threshold=threshold,
+ )
+ return model
+```
+此函数递归地将 `meta` 设备上初始化的给定模型的所有 `nn.Linear` 层替换为 `Linear8bitLt` 模块。这里,必须将 `has_fp16_weights` 属性设置为 `False`,以便直接将权重加载为 `Int8`,并同时加载其量化统计信息。
+
+我们放弃了对某些模块(这里时 `lm_head`)进行替换,因为我们希望保持输出层的原始精度以获得更精确、更稳定的结果。
+
+但还没完!上面的函数在 `init_empty_weights` 上下文管理器中执行,这意味着新模型将仍在 `meta` 设备中。
+
+对于在此上下文管理器中初始化的模型,`accelerate` 将手动加载每个模块的参数并将它们拷贝到正确的设备上。因此在 `bitsandbytes` 中,设置 `Linear8bitLt` 模块的设备是至关重要的一步(感兴趣的读者可以查看[此代码](https://github.com/TimDettmers/bitsandbytes/blob/bd515328d70f344f935075f359c5aefc616878d5/bitsandbytes/nn/modules.py#L94)),正如你在我们上面提供的脚本中所见。
+
+而且,第二次调用量化过程时会失败!我们必须想出一个与 `accelerate` 的 `set_module_tensor_to_device` 函数相应的实现(称为 `set_module_8bit_tensor_to_device`),以确保我们不会调用两次量化。我们将在下面的部分中详细讨论这个问题!
+
+### 在 `accelerate` 设置设备要当心
+
+这方面,我们对 `accelerate` 库进行了精巧的修改,以取得平衡!
+
+在模型被加载且设置到正确的设备上后,有时你仍需调用 `set_module_tensor_to_device` 以便向所有设备分派加了 hook 的模型。该操作在用户调用 `accelerate` 的 `dispatch_model` 函数时会被触发,这意味着我们有可能多次调用 `.to`,我们需要避免该行为。
+
+我们通过两个 PR 实现了目的,[这里](https://github.com/huggingface/accelerate/pull/539/) 的第一个 PR 破坏了一些测试,但[这个 PR](https://github.com/huggingface/accelerate/pull/576/) 成功修复了所有问题!
+
+### 总结
+
+因此,最终我们完成了:
+1. 使用正确的模块在 `meta` 设备上初始化模型。
+2. 不重不漏地对目标 GPU 逐一设置参数,确保不要对同一个 GPU 重复设置!
+3. 将新加的参数变量更新到所有需要的地方,并添加好文档。
+4. 添加高覆盖度的测试! 你可以从[此处](https://github.com/huggingface/transformers/blob/main/tests/mixed_int8/test_mixed_int8.py) 查看更多关于测试的详细信息。
+
+知易行难,在此过程中,我们经历了许多艰难的调试局,其中很多跟 CUDA 核函数有关!
+
+总而言之,这次集成的过程充满了冒险和趣味;从深入研究并对不同的库做一些“手术”,到整合一切并最终使其发挥作用,每一步都充满挑战!
+
+现在,我们看看如何在 `transformers` 中成功使用它并从中获益!
+
+## 如何在 `transformers` 中使用它
+
+### 硬件要求
+
+CPU 不支持 8 位张量核心[译者注:Intel 最新的 Sapphire Rapids CPU 已支持 8 位张量指令集:AMX]。 bitsandbytes 可以在支持 8 位张量核心的硬件上运行,这些硬件有 Turing 和 Ampere GPU(RTX 20s、RTX 30s、A40-A100、T4+)。例如,Google Colab GPU 通常是 NVIDIA T4 GPU,而最新的 T4 是支持 8 位张量核心的。我们后面的演示将会基于 Google Colab!
+
+### 安装
+
+使用以下命令安装最新版本的库(确保你的 python>=3.8)。
+
+```bash
+pip install accelerate
+pip install bitsandbytes
+pip install git+https://github.com/huggingface/transformers.git
+```
+
+### 演示示例 - 在 Google Colab 上运行 T5 11B
+
+以下是运行 T5-11B 的演示。 T5-11B 模型的 checkpoint 精度为 FP32,需要 42GB 内存,Google Colab 里跑不动。使用我们的 8 位模块,它仅需 11GB 内存,因此能轻易跑通:
+
+[![打开 T5-11B 的 Colab 演示](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/drive/1YORPWx4okIHXnjW7MSAidXN29mPVNT7F?usp=sharing)
+
+或者,你还可以看看下面这个使用 8 位 BLOOM-3B 模型进行推理的演示!
+
+[![打开 BLOOM-3B 的 Colab 演示](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/huggingface/blog/blob/main/notebooks/HuggingFace_int8_demo.ipynb)
+
+## 影响范围
+
+我们认为,该方法让超大模型不再是阳春白雪,而是人人皆可触及。在不降低性能的情况下,它使拥有较少算力的用户能够使用以前无法使用的模型。
+
+我们已经发现了几个可以在继续改进的领域,以使该方法对大模型更友好!
+
+### 较小模型的推理加速
+
+正如我们在[基准测试部分](#比原始模型更快吗?)中看到的那样,我们可以将小模型(<=6B 参数)的运行速度提高近 2 倍。然而,虽然推理速度对于像 BLOOM-176B 这样的大模型来说比较稳定,但对小模型而言仍有改进的余地。我们已经定位到了问题并有希望恢复与 FP16 相同的性能,甚至还可能会有小幅加速。我们将在接下来的几周内合入这些改进。
+
+### 支持 Kepler GPU(GTX 1080 等)
+
+虽然我们只支持过去四年的所有 GPU,但现实是某些旧的 GPU(如 GTX 1080)现在仍然被大量使用。虽然这些 GPU 没有 Int8 张量核心,但它们有 Int8 向量单元(一种“弱”张量核心)。因此,这些 GPU 也可以体验 Int8 加速。然而,它需要一个完全不同的软件栈来优化推理速度。虽然我们确实计划集成对 Kepler GPU 的支持以使 LLM.int8() 的应用更广泛,但由于其复杂性,实现这一目标需要一些时间。
+
+### 在 Hub 上保存 8 位 checkpoint
+
+目前 8 位模型无法直接加载被推送到 Hub 上的 8 位 checkpoint。这是因为模型计算所需的统计数据(还记得上文提到的 `weight.CB` 和 `weight.SCB` 吗?)目前没有存储在 state_dict 中,而且 state_dict 的设计也未考虑这一信息的存储,同时 `Linear8bitLt` 模块也还尚未支持该特性。
+
+但我们认为保存它并将其推送到 Hub 可能有助于提高模型的可访问性。
+
+### CPU 的支持
+
+正如本文开头所述,CPU 设备不支持 8 位张量核。然而,我们能克服它吗?在 CPU 上运行此模块可以显著提高可用性和可访问性。[译者注:如上文,最新的 Intel CPU 已支持 8 位张量核]
+
+### 扩展至其他模态
+
+目前,大模型以语言模型为主。在超大视觉、音频和多模态模型上应用这种方法可能会很有意思,因为随着这些模型在未来几年变得越来越多,它们的易用性也会越来越重要。
+
+## 致谢
+
+非常感谢以下为提高文章的可读性以及在 `transformers` 中的集成过程做出贡献的人(按字母顺序列出):
+JustHeuristic (Yozh),
+Michael Benayoun,
+Stas Bekman,
+Steven Liu,
+Sylvain Gugger,
+Tim Dettmers
+
+> 英文原文: https://huggingface.co/blog/hf-bitsandbytes-integration
+> 原文作者:Younes Belkada,Tim Dettmers
+> 译者: Matrix Yao (姚伟峰),英特尔深度学习工程师,工作方向为 transformer-family 模型在各模态数据上的应用及大规模模型的训练推理。
From e6e8c8a2f61b6f33d0312fb5f3f1d9705a533f42 Mon Sep 17 00:00:00 2001
From: Zhongdong Yang
Date: Tue, 25 Apr 2023 17:53:57 +0800
Subject: [PATCH 08/55] Proofread hf-bitsandbytes-integration.md
---
zh/hf-bitsandbytes-integration.md | 234 +++++++++++++++---------------
1 file changed, 121 insertions(+), 113 deletions(-)
diff --git a/zh/hf-bitsandbytes-integration.md b/zh/hf-bitsandbytes-integration.md
index cc30759d74..9963f1b2df 100644
--- a/zh/hf-bitsandbytes-integration.md
+++ b/zh/hf-bitsandbytes-integration.md
@@ -7,6 +7,8 @@ authors:
guest: true
translators:
- user: MatrixYao
+- user: zhongdongy
+ proofreader: true
---
# 大规模 Transformer 模型 8 比特矩阵乘简介 - 基于 Hugging Face Transformers、Accelerate 以及 bitsandbytes
@@ -22,11 +24,11 @@ translators:
![LLM](/blog/assets/96_hf_bitsandbytes_integration/LLM3.png)
-由于这些模型很大,因此它们很难在一般的设备上运行。举个例子,仅推理 BLOOM-176B 模型,你就需要 8 个 80GB A100 GPU(每个约 15,000 美元)。而如果要微调 BLOOM-176B 的话,你需要 72 个这样的 GPU!更大的模型,如 PaLM,还需要更多资源。
+由于这些模型很大,因此它们很难在一般的设备上运行。举个例子,仅推理 BLOOM-176B 模型,你就需要 8 个 80GB A100 GPU (每个约 15,000 美元)。而如果要微调 BLOOM-176B 的话,你需要 72 个这样的 GPU!更大的模型,如 PaLM,还需要更多资源。
由于这些庞大的模型需要大量 GPU 才能运行,因此我们需要找到降低资源需求而同时保持模型性能的方法。目前已有一些试图缩小模型尺寸的技术,比如你可能听说过的量化和蒸馏等技术。
-完成 BLOOM-176B 的训练后,Hugging Face 和 BigScience 一直在寻找能让这个大模型更容易在更少的 GPU 上运行的方法。通过我们的 BigScience 社区,我们了解到一些有关 Int8 推理的研究,它不会降低大模型的预测性能,而且可以将大模型的内存占用量减少 2 倍。很快我们就开始合作进行这项研究,最终将其完全整合到 Hugging Face `transformers` 中。本文我们将详述我们集成在Hugging Face 中的 LLM.int8() 方案,它适用于所有 Hugging Face 模型。如果你想了解更多研究细节,可以阅读我们的论文 [LLM.int8(): 8-bit Matrix Multiplication for Transformers at Scale](https://arxiv.org/abs/2208.07339)。
+完成 BLOOM-176B 的训练后,Hugging Face 和 BigScience 一直在寻找能让这个大模型更容易在更少的 GPU 上运行的方法。通过我们的 BigScience 社区,我们了解到一些有关 Int8 推理的研究,它不会降低大模型的预测性能,而且可以将大模型的内存占用量减少 2 倍。很快我们就开始合作进行这项研究,最终将其完全整合到 Hugging Face `transformers` 中。本文我们将详述我们集成在 Hugging Face 中的 LLM.int8() 方案,它适用于所有 Hugging Face 模型。如果你想了解更多研究细节,可以阅读我们的论文 [LLM.int8(): 8-bit Matrix Multiplication for Transformers at Scale](https://arxiv.org/abs/2208.07339)。
本文将主要介绍 LLM.int8() 量化技术,讨论将其纳入 `transformers` 库的过程中经历的困难,并对后续工作进行了计划。
@@ -36,29 +38,29 @@ translators:
我们从理解不同浮点数据类型开始,这些数据类型在机器学习中也被称为“精度”。
-模型的大小由其参数量及其精度决定,精度通常为 float32、float16 或 bfloat16 之一([下图来源](https://blogs.nvidia.com/blog/2020/05/14/tensorfloat-32-precision-format/))。
+模型的大小由其参数量及其精度决定,精度通常为 float32、float16 或 bfloat16 之一 ([下图来源](https://blogs.nvidia.com/blog/2020/05/14/tensorfloat-32-precision-format/))。
![Summary](/blog/assets/96_hf_bitsandbytes_integration/tf32-Mantissa-chart-hi-res-FINAL.png)
Float32 (FP32) 是标准的 IEEE 32 位浮点表示。使用该数据类型,可以表示大范围的浮点数。在 FP32 中,为“指数”保留了 8 位,为“尾数”保留了 23 位,为符号保留了 1 位。因为是标准数据类型,所以大部分硬件都支持 FP32 运算指令。
-而在 Float16 (FP16) 数据类型中,指数保留 5 位,尾数保留 10 位。这使得 FP16 数字的数值范围远低于 FP32。因此 FP16 存在上溢(当用于表示非常大的数时)和下溢(当用于表示非常小的数时)的风险。
+而在 Float16 (FP16) 数据类型中,指数保留 5 位,尾数保留 10 位。这使得 FP16 数字的数值范围远低于 FP32。因此 FP16 存在上溢 (当用于表示非常大的数时) 和下溢 (当用于表示非常小的数时) 的风险。
-例如,当你执行 `10k * 10k` 时,最终结果应为 `100M`,FP16 无法表示该数,因为 FP16 能表示的最大数是 `64k`。因此你最终会得到 `NaN`(Not a Number,不是数字),在神经网络的计算中,因为计算是按层和 batch 顺序进行的,因此一旦出现 `NaN`,之前的所有计算就全毁了。一般情况下,我们可以通过缩放损失(loss scaling)来缓解这个问题,但该方法并非总能奏效。
+例如,当你执行 `10k * 10k` 时,最终结果应为 `100M`,FP16 无法表示该数,因为 FP16 能表示的最大数是 `64k`。因此你最终会得到 `NaN` (Not a Number,不是数字),在神经网络的计算中,因为计算是按层和 batch 顺序进行的,因此一旦出现 `NaN`,之前的所有计算就全毁了。一般情况下,我们可以通过缩放损失 (loss scaling) 来缓解这个问题,但该方法并非总能奏效。
-于是我们发明了一种新格式 Bfloat16 (BF16) 来规避这些限制。BF16 为指数保留了 8 位(与 FP32 相同),为小数保留了 7 位。这意味着使用 BF16 我们可以保留与 FP32 相同的动态范围。但是相对于 FP16,我们损失了 3 位精度。因此,在使用 BF16 精度时,大数值绝对没有问题,但是精度会比 FP16 差。
+于是我们发明了一种新格式 Bfloat16 (BF16) 来规避这些限制。BF16 为指数保留了 8 位 (与 FP32 相同),为小数保留了 7 位。这意味着使用 BF16 我们可以保留与 FP32 相同的动态范围。但是相对于 FP16,我们损失了 3 位精度。因此,在使用 BF16 精度时,大数值绝对没有问题,但是精度会比 FP16 差。
-在 Ampere 架构中,NVIDIA 还引入了 [TensorFloat-32](https://blogs.nvidia.com/blog/2020/05/14/tensorfloat-32-precision-format/)(TF32) 精度格式,它使用 19 位表示,结合了 BF16 的范围和 FP16 的精度。目前,它仅在某些操作的内部使用[译者注:即 TF32 是一个计算数据类型而不是存储数据类型]。
+在 Ampere 架构中,NVIDIA 还引入了 [TensorFloat-32](https://blogs.nvidia.com/blog/2020/05/14/tensorfloat-32-precision-format/)(TF32) 精度格式,它使用 19 位表示,结合了 BF16 的范围和 FP16 的精度。目前,它仅在某些操作的内部使用 [译者注: 即 TF32 是一个计算数据类型而不是存储数据类型]。
-在机器学习术语中,FP32 称为全精度(4 字节),而 BF16 和 FP16 称为半精度(2 字节)。除此以外,还有 Int8 (INT8) 数据类型,它是一个 8 位的整型数据表示,可以存储 $2^8$ 个不同的值(对于有符号整数,区间为 [-128, 127],而对于无符号整数,区间为[0, 255])。
+在机器学习术语中,FP32 称为全精度 (4 字节),而 BF16 和 FP16 称为半精度 (2 字节)。除此以外,还有 Int8 (INT8) 数据类型,它是一个 8 位的整型数据表示,可以存储 $2^8$ 个不同的值 (对于有符号整数,区间为 [-128, 127],而对于无符号整数,区间为 [0, 255])。
-虽然理想情况下训练和推理都应该在 FP32 中完成,但 FP32 比 FP16/BF16 慢两倍,因此实践中常常使用混合精度方法,其中,使用 FP32 权重作为精确的 “主权重(master weight)”,而使用 FP16/BF16 权重进行前向和后向传播计算以提高训练速度,最后在梯度更新阶段再使用 FP16/BF16 梯度更新 FP32 主权重。
+虽然理想情况下训练和推理都应该在 FP32 中完成,但 FP32 比 FP16/BF16 慢两倍,因此实践中常常使用混合精度方法,其中,使用 FP32 权重作为精确的 “主权重 (master weight)”,而使用 FP16/BF16 权重进行前向和后向传播计算以提高训练速度,最后在梯度更新阶段再使用 FP16/BF16 梯度更新 FP32 主权重。
在训练期间,主权重始终为 FP32。而在实践中,在推理时,半精度权重通常能提供与 FP32 相似的精度 —— 因为只有在模型梯度更新时才需要精确的 FP32 权重。这意味着在推理时我们可以使用半精度权重,这样我们仅需一半 GPU 显存就能获得相同的结果。
![Model-storage](/blog/assets/96_hf_bitsandbytes_integration/Model-storage.png)
-以字节为单位计算模型大小时,需要将参数量乘以所选精度的大小(以字节为单位)。例如,如果我们使用 BLOOM-176B 模型的 Bfloat16 版本,其大小就应为 $176 \times 10^{9} \times 2 字节 = 352GB$!如前所述,这个大小需要多个 GPU 才能装得下,这是一个相当大的挑战。
+以字节为单位计算模型大小时,需要将参数量乘以所选精度的大小 (以字节为单位)。例如,如果我们使用 BLOOM-176B 模型的 Bfloat16 版本,其大小就应为 $176 \times 10^{9} \times 2 字节 = 352GB$!如前所述,这个大小需要多个 GPU 才能装得下,这是一个相当大的挑战。
但是,如果我们可以使用另外的数据类型来用更少的内存存储这些权重呢?深度学习社区已广泛使用的方法是量化。
@@ -68,15 +70,17 @@ Float32 (FP32) 是标准的 IEEE 32 位浮点表示。使用该数据类型,
为了解决这个问题,我们引入了 8 位量化。仅用四分之一精度,因此模型大小也仅需 1/4!但这次,我们不能简单地丢弃另一半位宽了。
-基本上讲,量化过程是从一种数据类型“舍入”到另一种数据类型。举个例子,如果一种数据类型的范围为 `0..9`,而另一种数据类型的范围为 `0..4`,则第一种数据类型中的值 `4` 将舍入为第二种数据类型中的 `2` 。但是,如果在第一种数据类型中有值 `3`,它介于第二种数据类型的 `1` 和 `2` 之间,那么我们通常会四舍五入为 `2`。也就是说,第一种数据类型的值 `4` 和 `3` 在第二种数据类型中具有相同的值 `2`。这充分表明量化是一个有噪过程,会导致信息丢失,是一种有损压缩。
+基本上讲,量化过程是从一种数据类型“舍入”到另一种数据类型。举个例子,如果一种数据类型的范围为 `0..9`,而另一种数据类型的范围为 `0..4`,则第一种数据类型中的值 `4` 将舍入为第二种数据类型中的 `2` 。但是,如果在第一种数据类型中有值 `3`,它介于第二种数据类型的 `1` 和 `2` 之间,那么我们通常会四舍五入为 `2`。也就是说,第一种数据类型的值 `4` 和 `3` 在第二种数据类型中具有相同的值 `2`。这充分表明量化是一个有噪过程,会导致信息丢失,是一种有损压缩。
-两种最常见的 8 位量化技术是零点量化(zero-point quantization)和最大绝对值 (absolute maximum quantization,absmax) 量化。它们都将浮点值映射为更紧凑的 Int8(1 字节)值。这些方法的第一步都是用量化常数对输入进行归一化缩放。
+两种最常见的 8 位量化技术是零点量化 (zero-point quantization) 和最大绝对值 (absolute maximum quantization,absmax) 量化。它们都将浮点值映射为更紧凑的 Int8 (1 字节) 值。这些方法的第一步都是用量化常数对输入进行归一化缩放。
-在零点量化中,如果我的数值范围是 `-1.0…1.0`,我想量化到 `-127…127`,我需要先缩放 `127`倍,然后四舍五入到 `8` 位精度。要恢复原始值,我需要将 Int8 值除以相同的量化因子 `127`。在这个例子中,值 `0.3` 将缩放为 `0.3*127 = 38.1`。四舍五入后得到值 `38`。恢复时,我们会得到 `38/127=0.2992` —— 因此最终会有 `0.008` 的量化误差。这些看似微小的误差在沿着模型各层传播时往往会累积和增长,从而导致最终的精度下降。[译者注:这个例子举得不好,因为浮点范围和整型范围都是对称的,所以不存在零点调整了,而零点调整是零点量化中最能体现其命名原因的部分。简而言之,零点量化分为两步,第一步值域映射,即通过缩放将原始的数值范围映射为量化后的数值范围;第二步零点调整,即通过平移将映射后的数据的最小值对齐为目标值域的最小值]
+在零点量化中,如果我的数值范围是 `-1.0…1.0`,我想量化到 `-127…127`,我需要先缩放 `127`倍,然后四舍五入到 `8` 位精度。要恢复原始值,我需要将 Int8 值除以相同的量化因子 `127`。在这个例子中,值 `0.3` 将缩放为 `0.3*127 = 38.1`。四舍五入后得到值 `38`。恢复时,我们会得到 `38/127=0.2992` —— 因此最终会有 `0.008` 的量化误差。这些看似微小的误差在沿着模型各层传播时往往会累积和增长,从而导致最终的精度下降。
+
+> 译者注: 这个例子举得不好,因为浮点范围和整型范围都是对称的,所以不存在零点调整了,而零点调整是零点量化中最能体现其命名原因的部分。简而言之,零点量化分为两步,第一步值域映射,即通过缩放将原始的数值范围映射为量化后的数值范围; 第二步零点调整,即通过平移将映射后的数据的最小值对齐为目标值域的最小值
![quantization](/blog/assets/96_hf_bitsandbytes_integration/quantization.png)
-([图源](https://intellabs.github.io/distiller/algo_quantization.html) )
+([图源](https://intellabs.github.io/distiller/algo_quantization.html))
现在我们再看下 absmax 量化的细节。要计算 absmax 量化中 fp16 数与其对应的 int8 数之间的映射,你必须先除以张量的最大绝对值,然后再乘以数据类型的最大可表示值。
@@ -88,22 +92,23 @@ Float32 (FP32) 是标准的 IEEE 32 位浮点表示。使用该数据类型,
![quant-freeze](/blog/assets/96_hf_bitsandbytes_integration/quant-freeze.png)
-对于无符号 Int8,我们可以先减去最小值然后再用最大绝对值来缩放,这与零点量化的做法相似。其做法也与最小-最大缩放(min-max scaling)类似,但后者在缩放时会额外保证输入中的 `0` 始终映射到一个整数,从而保证 `0` 的量化是无误差的。
+对于无符号 Int8,我们可以先减去最小值然后再用最大绝对值来缩放,这与零点量化的做法相似。其做法也与最小 - 最大缩放 (min-max scaling) 类似,但后者在缩放时会额外保证输入中的 `0` 始终映射到一个整数,从而保证 `0` 的量化是无误差的。
+
+当进行矩阵乘法时,我们可以通过组合各种技巧,例如逐行或逐向量量化,来获取更精确的结果。举个例子,对矩阵乘法 $A \times B=C$,我们不会直接使用常规量化方式,即用整个张量的最大绝对值对张量进行归一化,而会转而使用向量量化方法,找到 A 的每一行和 B 的每一列的最大绝对值,然后逐行或逐列归一化 A 和 B 。最后将 A 与 B 相乘得到 C。最后,我们再计算与 A 和 B 的最大绝对值向量的外积,并将此与 C 求哈达玛积来反量化回 FP16。有关此技术的更多详细信息可以参考 [LLM.int8() 论文](https://arxiv.org/abs/2208.07339) 或 Tim 的博客上的 [关于量化和涌现特征的博文](https://timdettmers.com/2022/08/17/llm-int8-and-emergent-features/)。
-当进行矩阵乘法时,我们可以通过组合各种技巧,例如逐行或逐向量量化,来获取更精确的结果。举个例子,对矩阵乘法 $A \times B=C$,我们不会直接使用常规量化方式,即用整个张量的最大绝对值对张量进行归一化,而会转而使用向量量化方法,找到 A 的每一行和 B 的每一列的最大绝对值,然后逐行或逐列归一化 A 和 B 。最后将 A 与 B 相乘得到 C。最后,我们再计算与 A 和 B 的最大绝对值向量的外积,并将此与 C 求哈达玛积来反量化回 FP16。有关此技术的更多详细信息可以参考 [LLM.int8() 论文](https://arxiv.org/abs/2208.07339) 或 Tim 的博客上的[关于量化和涌现特征的博文](https://timdettmers.com/2022/08/17/llm-int8-and-emergent-features/)。
+虽然这些基本技术能够帮助我们量化深度学习模型,但它们通常会导致大模型准确性的下降。我们集成到 Hugging Face Transformers 和 Accelerate 库中的 LLM.int8() 是第一个适用于大模型 (如 BLOOM-176B) 且不会降低准确性的量化技术。
-虽然这些基本技术能够帮助我们量化深度学习模型,但它们通常会导致大模型准确性的下降。我们集成到 Hugging Face Transformers 和 Accelerate 库中的 LLM.int8() 是第一个适用于大模型(如 BLOOM-176B)且不会降低准确性的量化技术。
+## 简要总结 LLM.int8(): 大语言模型的零退化矩阵乘法
-## 简要总结 LLM.int8():大语言模型的零退化矩阵乘法
+在 LLM.int8() 中,我们已经证明理解 transformer 模型表现出的与模型规模相关的涌现特性对于理解为什么传统量化对大模型失效至关重要。我们证明性能下降是由离群特征 (outlier feature) 引起的,下一节我们会详细解释。LLM.int8() 算法本身如下。
-在 LLM.int8() 中,我们已经证明理解 transformer 模型表现出的与模型规模相关的涌现特性对于理解为什么传统量化对大模型失效至关重要。我们证明性能下降是由离群特征(outlier feature)引起的,下一节我们会详细解释。LLM.int8() 算法本身如下。
+本质上,LLM.int8() 通过三个步骤完成矩阵乘法计算:
-本质上,LLM.int8() 通过三个步骤完成矩阵乘法计算:
-1. 从输入的隐含状态中,按列提取异常值(即大于某个阈值的值)。
+1. 从输入的隐含状态中,按列提取异常值 (即大于某个阈值的值)。
2. 对 FP16 离群值矩阵和 Int8 非离群值矩阵分别作矩阵乘法。
3. 反量化非离群值的矩阵乘结果并其与离群值矩阵乘结果相加,获得最终的 FP16 结果。
-该过程可以总结为如下动画:
+该过程可以总结为如下动画:
![Mixed-int8.gif](/blog/assets/96_hf_bitsandbytes_integration/Mixed-int8.gif)
@@ -127,50 +132,50 @@ Float32 (FP32) 是标准的 IEEE 32 位浮点表示。使用该数据类型,
对 OPT-175B 模型:
-| 测试基准 | - | - | - | - | 差值 |
-| ---------- | --------- | ---------------- | -------------------- | -------------------- | -------------------- |
-| 测试基准名 | 指标 | 指标值 - int8 | 指标值 - fp16 | 标准差 - fp16 | - |
-| hellaswag | acc\_norm | 0.7849 | 0.7849 | 0.0041 | 0 |
-| hellaswag | acc | 0.5921 | 0.5931 | 0.0049 | 0.001 |
-| piqa | acc | 0.7965 | 0.7959 | 0.0094 | 0.0006 |
-| piqa | acc\_norm | 0.8101 | 0.8107 | 0.0091 | 0.0006 |
-| lambada | ppl | 3.0142 | 3.0152 | 0.0552 | 0.001 |
-| lambada | acc | 0.7464 | 0.7466 | 0.0061 | 0.0002 |
-| winogrande | acc | 0.7174 | 0.7245 | 0.0125 | 0.0071 |
+| 测试基准 | - | - | - | - | 差值 |
+| --- | --- | --- | --- | --- | --- |
+| 测试基准名 | 指标 | 指标值 - int8 | 指标值 - fp16 | 标准差 - fp16 | - |
+| hellaswag | acc_norm | 0.7849 | 0.7849 | 0.0041 | 0 |
+| hellaswag | acc | 0.5921 | 0.5931 | 0.0049 | 0.001 |
+| piqa | acc | 0.7965 | 0.7959 | 0.0094 | 0.0006 |
+| piqa | acc_norm | 0.8101 | 0.8107 | 0.0091 | 0.0006 |
+| lambada | ppl | 3.0142 | 3.0152 | 0.0552 | 0.001 |
+| lambada | acc | 0.7464 | 0.7466 | 0.0061 | 0.0002 |
+| winogrande | acc | 0.7174 | 0.7245 | 0.0125 | 0.0071 |
对 BLOOM-176 模型:
-| 测试基准 | - | - | - | - | 差值 |
-| ---------- | --------- | ---------------- | -------------------- | -------------------- | -------------------- |
-| 测试基准名 | 指标 | 指标值 - int8 | 指标值 - fp16 | 标准差 - fp16 | - |
-| hellaswag | acc\_norm | 0.7274 | 0.7303 | 0.0044 | 0.0029 |
-| hellaswag | acc | 0.5563 | 0.5584 | 0.005 | 0.0021 |
-| piqa | acc | 0.7835 | 0.7884 | 0.0095 | 0.0049 |
-| piqa | acc\_norm | 0.7922 | 0.7911 | 0.0095 | 0.0011 |
-| lambada | ppl | 3.9191 | 3.931 | 0.0846 | 0.0119 |
-| lambada | acc | 0.6808 | 0.6718 | 0.0065 | 0.009 |
-| winogrande | acc | 0.7048 | 0.7048 | 0.0128 | 0 |
+| 测试基准 | - | - | - | - | 差值 |
+| --- | --- | --- | --- | --- | --- |
+| 测试基准名 | 指标 | 指标值 - int8 | 指标值 - fp16 | 标准差 - fp16 | - |
+| hellaswag | acc_norm | 0.7274 | 0.7303 | 0.0044 | 0.0029 |
+| hellaswag | acc | 0.5563 | 0.5584 | 0.005 | 0.0021 |
+| piqa | acc | 0.7835 | 0.7884 | 0.0095 | 0.0049 |
+| piqa | acc_norm | 0.7922 | 0.7911 | 0.0095 | 0.0011 |
+| lambada | ppl | 3.9191 | 3.931 | 0.0846 | 0.0119 |
+| lambada | acc | 0.6808 | 0.6718 | 0.0065 | 0.009 |
+| winogrande | acc | 0.7048 | 0.7048 | 0.0128 | 0 |
-我们切实地看到上述这些模型的性能下降为 0,因为指标的绝对差异均低于原始模型的标准误差(BLOOM-int8 除外,它在 lambada 上略好于原始模型)。如果想要知道 LLM.int8() 与当前其他先进方法的更详细的性能比较,请查看[论文](https://arxiv.org/abs/2208.07339)!
+我们切实地看到上述这些模型的性能下降为 0,因为指标的绝对差异均低于原始模型的标准误差 (BLOOM-int8 除外,它在 lambada 上略好于原始模型)。如果想要知道 LLM.int8() 与当前其他先进方法的更详细的性能比较,请查看 [论文](https://arxiv.org/abs/2208.07339)!
### 比原始模型更快吗?
-LLM.int8() 方法的主要目的是在不降低性能的情况下降低大模型的应用门槛。但如果速度非常慢,该方法用处也不会很大。所以我们对多个模型的生成速度进行了基准测试。
-我们发现使用了 LLM.int8() 的 BLOOM-176B 比 FP16 版本慢了大约 15% 到 23% —— 这应该是完全可以接受的。我们发现较小模型(如 T5-3B 和 T5-11B)的降速幅度更大。我们还在努力优化这些小模型的推理速度。在一天之内,我们可以将 T5-3B 的每词元推理延迟从 312 毫秒降低到 173 毫秒,将 T5-11B 从 45 毫秒降低到 25 毫秒。此外,我们[已经找到原因](https://github.com/TimDettmers/bitsandbytes/issues/6#issuecomment-1211345635),在即将发布的版本中,LLM.int8() 在小模型上的推理速度可能会更快。下表列出了当前版本的一些性能数据。
+LLM.int8() 方法的主要目的是在不降低性能的情况下降低大模型的应用门槛。但如果速度非常慢,该方法用处也不会很大。所以我们对多个模型的生成速度进行了基准测试。
+我们发现使用了 LLM.int8() 的 BLOOM-176B 比 FP16 版本慢了大约 15% 到 23% —— 这应该是完全可以接受的。我们发现较小模型 (如 T5-3B 和 T5-11B) 的降速幅度更大。我们还在努力优化这些小模型的推理速度。在一天之内,我们可以将 T5-3B 的每词元推理延迟从 312 毫秒降低到 173 毫秒,将 T5-11B 从 45 毫秒降低到 25 毫秒。此外,我们 [已经找到原因](https://github.com/TimDettmers/bitsandbytes/issues/6#issuecomment-1211345635),在即将发布的版本中,LLM.int8() 在小模型上的推理速度可能会更快。下表列出了当前版本的一些性能数据。
-| 精度 | 参数量 | 硬件 | 每词元延迟(单位:毫秒,batch size: 1)| 每词元延迟(单位:毫秒,batch size: 8) | 每词元延迟(单位:毫秒,batch size: 32) |
-| -------------- | -------------------- | ------------ | ----------------------------------------------- | ----------------------------------------------- | ------------------------------------------------ |
-| bf16 | 176B | 8xA100 80GB | 239 | 32 | 9.9 |
-| int8 | 176B | 4xA100 80GB | 282 | 37.5 | 10.2 |
-| bf16 | 176B | 14xA100 40GB | 285 | 36.5 | 10.4 |
-| int8 | 176B | 5xA100 40GB | 367 | 46.4 | oom |
-| fp16 | 11B | 2xT4 15GB | 11.7 | 1.7 | 0.5 |
-| int8 | 11B | 1xT4 15GB | 43.5 | 5.3 | 1.3 |
-| fp32 | 3B | 2xT4 15GB | 45 | 7.2 | 3.1 |
-| int8 | 3B | 1xT4 15GB | 312 | 39.1 | 10.2 |
+| 精度 | 参数量 | 硬件 | 每词元延迟 (单位: 毫秒,batch size: 1) | 每词元延迟 (单位: 毫秒,batch size: 8) | 每词元延迟 (单位: 毫秒,batch size: 32) |
+| --- | --- | --- | --- | --- | --- |
+| bf16 | 176B | 8xA100 80GB | 239 | 32 | 9.9 |
+| int8 | 176B | 4xA100 80GB | 282 | 37.5 | 10.2 |
+| bf16 | 176B | 14xA100 40GB | 285 | 36.5 | 10.4 |
+| int8 | 176B | 5xA100 40GB | 367 | 46.4 | oom |
+| fp16 | 11B | 2xT4 15GB | 11.7 | 1.7 | 0.5 |
+| int8 | 11B | 1xT4 15GB | 43.5 | 5.3 | 1.3 |
+| fp32 | 3B | 2xT4 15GB | 45 | 7.2 | 3.1 |
+| int8 | 3B | 1xT4 15GB | 312 | 39.1 | 10.2 |
-上表中的3个模型分别为 BLOOM-176B、T5-11B 和 T5-3B。
+上表中的 3 个模型分别为 BLOOM-176B、T5-11B 和 T5-3B。
## Hugging Face `transformers` 集成细节
@@ -192,7 +197,7 @@ import bitsandbytes as bnb
from bnb.nn import Linear8bitLt
```
-2. 然后就可以定义自己的模型了。请注意,我们支持将任何精度的 checkpoint 或模型转换为 8 位(FP16、BF16 或 FP32),但目前,仅当模型的输入张量数据类型为 FP16 时,我们的 Int8 模块才能工作。因此,这里我们称模型为 fp16 模型。
+1. 然后就可以定义自己的模型了。请注意,我们支持将任何精度的 checkpoint 或模型转换为 8 位 (FP16、BF16 或 FP32),但目前,仅当模型的输入张量数据类型为 FP16 时,我们的 Int8 模块才能工作。因此,这里我们称模型为 fp16 模型。
```py
fp16_model = nn.Sequential(
@@ -201,14 +206,14 @@ fp16_model = nn.Sequential(
)
```
-3. 假设你已经在你的数据集和任务上训完了你的模型!现在需要保存模型:
+1. 假设你已经在你的数据集和任务上训完了你的模型!现在需要保存模型:
```py
[... train the model ...]
torch.save(fp16_model.state_dict(), "model.pt")
```
-4. 至此,`state_dict` 已保存,我们需要定义一个 int8 模型:
+1. 至此,`state_dict` 已保存,我们需要定义一个 int8 模型:
```py
int8_model = nn.Sequential(
@@ -216,83 +221,85 @@ int8_model = nn.Sequential(
Linear8bitLt(64, 64, has_fp16_weights=False)
)
```
+
此处标志变量 `has_fp16_weights` 非常重要。默认情况下,它设置为 `True`,用于在训练时使能 Int8/FP16 混合精度。但是,因为在推理中我们对内存节省更感兴趣,因此我们需要设置 `has_fp16_weights=False`。
-5. 现在加载 8 位模型!
+1. 现在加载 8 位模型!
```py
int8_model.load_state_dict(torch.load("model.pt"))
int8_model = int8_model.to(0) # 量化发生在此处
```
-请注意,一旦将模型的设备设置为 GPU,量化过程就会在第二行代码中完成。如果在调用 `.to` 函数之前打印 `int8_model[0].weight`,你会看到:
+请注意,一旦将模型的设备设置为 GPU,量化过程就会在第二行代码中完成。如果在调用 `.to` 函数之前打印 `int8_model[0].weight`,你会看到:
```
int8_model[0].weight
Parameter containing:
-tensor([[ 0.0031, -0.0438, 0.0494, ..., -0.0046, -0.0410, 0.0436],
- [-0.1013, 0.0394, 0.0787, ..., 0.0986, 0.0595, 0.0162],
- [-0.0859, -0.1227, -0.1209, ..., 0.1158, 0.0186, -0.0530],
+tensor([[ 0.0031, -0.0438, 0.0494, ..., -0.0046, -0.0410, 0.0436],
+ [-0.1013, 0.0394, 0.0787, ..., 0.0986, 0.0595, 0.0162],
+ [-0.0859, -0.1227, -0.1209, ..., 0.1158, 0.0186, -0.0530],
...,
- [ 0.0804, 0.0725, 0.0638, ..., -0.0487, -0.0524, -0.1076],
- [-0.0200, -0.0406, 0.0663, ..., 0.0123, 0.0551, -0.0121],
- [-0.0041, 0.0865, -0.0013, ..., -0.0427, -0.0764, 0.1189]],
+ [ 0.0804, 0.0725, 0.0638, ..., -0.0487, -0.0524, -0.1076],
+ [-0.0200, -0.0406, 0.0663, ..., 0.0123, 0.0551, -0.0121],
+ [-0.0041, 0.0865, -0.0013, ..., -0.0427, -0.0764, 0.1189]],
dtype=torch.float16)
```
-而如果你在第二行之后打印它,你会看到:
+而如果你在第二行之后打印它,你会看到:
```
int8_model[0].weight
Parameter containing:
-tensor([[ 3, -47, 54, ..., -5, -44, 47],
- [-104, 40, 81, ..., 101, 61, 17],
- [ -89, -127, -125, ..., 120, 19, -55],
+tensor([[ 3, -47, 54, ..., -5, -44, 47],
+ [-104, 40, 81, ..., 101, 61, 17],
+ [ -89, -127, -125, ..., 120, 19, -55],
...,
- [ 82, 74, 65, ..., -49, -53, -109],
- [ -21, -42, 68, ..., 13, 57, -12],
- [ -4, 88, -1, ..., -43, -78, 121]],
+ [ 82, 74, 65, ..., -49, -53, -109],
+ [ -21, -42, 68, ..., 13, 57, -12],
+ [ -4, 88, -1, ..., -43, -78, 121]],
device='cuda:0', dtype=torch.int8, requires_grad=True)
```
+
正如我们在前面部分解释量化方法时所讲,权重值被“截断”了。此外,这些值的分布看上去在 [-127, 127] 之间。
-你可能还想知道如何获取 FP16 权重以便在 FP16 中执行离群值的矩阵乘?很简单:
+你可能还想知道如何获取 FP16 权重以便在 FP16 中执行离群值的矩阵乘?很简单:
```py
(int8_model[0].weight.CB * int8_model[0].weight.SCB) / 127
```
-你会看到:
+你会看到:
```
-tensor([[ 0.0028, -0.0459, 0.0522, ..., -0.0049, -0.0428, 0.0462],
- [-0.0960, 0.0391, 0.0782, ..., 0.0994, 0.0593, 0.0167],
- [-0.0822, -0.1240, -0.1207, ..., 0.1181, 0.0185, -0.0541],
+tensor([[ 0.0028, -0.0459, 0.0522, ..., -0.0049, -0.0428, 0.0462],
+ [-0.0960, 0.0391, 0.0782, ..., 0.0994, 0.0593, 0.0167],
+ [-0.0822, -0.1240, -0.1207, ..., 0.1181, 0.0185, -0.0541],
...,
- [ 0.0757, 0.0723, 0.0628, ..., -0.0482, -0.0516, -0.1072],
- [-0.0194, -0.0410, 0.0657, ..., 0.0128, 0.0554, -0.0118],
- [-0.0037, 0.0859, -0.0010, ..., -0.0423, -0.0759, 0.1190]],
+ [ 0.0757, 0.0723, 0.0628, ..., -0.0482, -0.0516, -0.1072],
+ [-0.0194, -0.0410, 0.0657, ..., 0.0128, 0.0554, -0.0118],
+ [-0.0037, 0.0859, -0.0010, ..., -0.0423, -0.0759, 0.1190]],
device='cuda:0')
```
这跟第一次打印的原始 FP16 值很接近!
-6. 现在你只需将输入推给正确的 GPU 并确保输入数据类型是 FP16 的,你就可以使用该模型进行推理了:
+1. 现在你只需将输入推给正确的 GPU 并确保输入数据类型是 FP16 的,你就可以使用该模型进行推理了:
```py
input_ = torch.randn(64, dtype=torch.float16)
hidden_states = int8_model(input_.to(torch.device('cuda', 0)))
```
-你可以查看[示例脚本](/blog/assets/96_hf_bitsandbytes_integration/example.py) ,获取完整的示例代码!
+你可以查看 [示例脚本](/blog/assets/96_hf_bitsandbytes_integration/example.py),获取完整的示例代码!
-多说一句,`Linear8bitLt` 与 `nn.Linear` 模块略有不同,主要在 `Linear8bitLt` 的参数属于 `bnb.nn.Int8Params` 类而不是 `nn.Parameter` 类。稍后你会看到这给我们带来了一些小麻烦!
+多说一句, `Linear8bitLt` 与 `nn.Linear` 模块略有不同,主要在 `Linear8bitLt` 的参数属于 `bnb.nn.Int8Params` 类而不是 `nn.Parameter` 类。稍后你会看到这给我们带来了一些小麻烦!
现在我们开始了解如何将其集成到 `transformers` 库中!
### `accelerate` 足矣
-在处理大模型时,`accelerate` 库包含许多有用的工具。`init_empty_weights` 方法特别有用,因为任何模型,无论大小,都可以在此方法的上下文(context)内进行初始化,而无需为模型权重分配任何内存。
+在处理大模型时, `accelerate` 库包含许多有用的工具。`init_empty_weights` 方法特别有用,因为任何模型,无论大小,都可以在此方法的上下文 (context) 内进行初始化,而无需为模型权重分配任何内存。
```py
import torch.nn as nn
@@ -301,15 +308,16 @@ from accelerate import init_empty_weights
with init_empty_weights():
model = nn.Sequential([nn.Linear(100000, 100000) for _ in range(1000)]) # This will take ~0 RAM!
```
-初始化过的模型将放在 PyTorch 的 `meta` 设备上,这是一种用于表征向量的形状和数据类型而无需实际的内存分配的超酷的底层机制。
-最初,我们在 `.from_pretrained` 函数内部调用 `init_empty_weights`,并将所有参数重载为 `torch.nn.Parameter`。这不是我们想要的,因为在我们的情况中,我们希望为 `Linear8bitLt` 模块保留 `Int8Params` 类,如上所述。我们最后成功使用 [此 PR](https://github.com/huggingface/accelerate/pull/519) 修复了该问题,它将下述代码:
+初始化过的模型将放在 PyTorch 的 `meta` 设备上,这是一种用于表征向量的形状和数据类型而无需实际的内存分配的超酷的底层机制。
+
+最初,我们在 `.from_pretrained` 函数内部调用 `init_empty_weights`,并将所有参数重载为 `torch.nn.Parameter`。这不是我们想要的,因为在我们的情况中,我们希望为 `Linear8bitLt` 模块保留 `Int8Params` 类,如上所述。我们最后成功使用 [此 PR](https://github.com/huggingface/accelerate/pull/519) 修复了该问题,它将下述代码:
```py
module._parameters[name] = nn.Parameter(module._parameters[name].to(torch.device("meta")))
```
-修改成:
+修改成:
```py
param_cls = type(module._parameters[name])
@@ -336,35 +344,37 @@ def replace_8bit_linear(model, threshold=6.0, module_to_not_convert="lm_head"):
)
return model
```
+
此函数递归地将 `meta` 设备上初始化的给定模型的所有 `nn.Linear` 层替换为 `Linear8bitLt` 模块。这里,必须将 `has_fp16_weights` 属性设置为 `False`,以便直接将权重加载为 `Int8`,并同时加载其量化统计信息。
-我们放弃了对某些模块(这里时 `lm_head`)进行替换,因为我们希望保持输出层的原始精度以获得更精确、更稳定的结果。
+我们放弃了对某些模块 (这里时 `lm_head`) 进行替换,因为我们希望保持输出层的原始精度以获得更精确、更稳定的结果。
但还没完!上面的函数在 `init_empty_weights` 上下文管理器中执行,这意味着新模型将仍在 `meta` 设备中。
-对于在此上下文管理器中初始化的模型,`accelerate` 将手动加载每个模块的参数并将它们拷贝到正确的设备上。因此在 `bitsandbytes` 中,设置 `Linear8bitLt` 模块的设备是至关重要的一步(感兴趣的读者可以查看[此代码](https://github.com/TimDettmers/bitsandbytes/blob/bd515328d70f344f935075f359c5aefc616878d5/bitsandbytes/nn/modules.py#L94)),正如你在我们上面提供的脚本中所见。
+对于在此上下文管理器中初始化的模型, `accelerate` 将手动加载每个模块的参数并将它们拷贝到正确的设备上。因此在 `bitsandbytes` 中,设置 `Linear8bitLt` 模块的设备是至关重要的一步 (感兴趣的读者可以查看 [此代码](https://github.com/TimDettmers/bitsandbytes/blob/bd515328d70f344f935075f359c5aefc616878d5/bitsandbytes/nn/modules.py#L94)),正如你在我们上面提供的脚本中所见。
-而且,第二次调用量化过程时会失败!我们必须想出一个与 `accelerate` 的 `set_module_tensor_to_device` 函数相应的实现(称为 `set_module_8bit_tensor_to_device`),以确保我们不会调用两次量化。我们将在下面的部分中详细讨论这个问题!
+而且,第二次调用量化过程时会失败!我们必须想出一个与 `accelerate` 的 `set_module_tensor_to_device` 函数相应的实现 (称为 `set_module_8bit_tensor_to_device`),以确保我们不会调用两次量化。我们将在下面的部分中详细讨论这个问题!
-### 在 `accelerate` 设置设备要当心
+### 在 `accelerate` 设置设备要当心
这方面,我们对 `accelerate` 库进行了精巧的修改,以取得平衡!
-在模型被加载且设置到正确的设备上后,有时你仍需调用 `set_module_tensor_to_device` 以便向所有设备分派加了 hook 的模型。该操作在用户调用 `accelerate` 的 `dispatch_model` 函数时会被触发,这意味着我们有可能多次调用 `.to`,我们需要避免该行为。
+在模型被加载且设置到正确的设备上后,有时你仍需调用 `set_module_tensor_to_device` 以便向所有设备分派加了 hook 的模型。该操作在用户调用 `accelerate` 的 `dispatch_model` 函数时会被触发,这意味着我们有可能多次调用 `.to`,我们需要避免该行为。
-我们通过两个 PR 实现了目的,[这里](https://github.com/huggingface/accelerate/pull/539/) 的第一个 PR 破坏了一些测试,但[这个 PR](https://github.com/huggingface/accelerate/pull/576/) 成功修复了所有问题!
+我们通过两个 PR 实现了目的,[这里](https://github.com/huggingface/accelerate/pull/539/) 的第一个 PR 破坏了一些测试,但 [这个 PR](https://github.com/huggingface/accelerate/pull/576/) 成功修复了所有问题!
### 总结
-因此,最终我们完成了:
+因此,最终我们完成了:
+
1. 使用正确的模块在 `meta` 设备上初始化模型。
2. 不重不漏地对目标 GPU 逐一设置参数,确保不要对同一个 GPU 重复设置!
3. 将新加的参数变量更新到所有需要的地方,并添加好文档。
-4. 添加高覆盖度的测试! 你可以从[此处](https://github.com/huggingface/transformers/blob/main/tests/mixed_int8/test_mixed_int8.py) 查看更多关于测试的详细信息。
+4. 添加高覆盖度的测试! 你可以从 [此处](https://github.com/huggingface/transformers/blob/main/tests/mixed_int8/test_mixed_int8.py) 查看更多关于测试的详细信息。
知易行难,在此过程中,我们经历了许多艰难的调试局,其中很多跟 CUDA 核函数有关!
-总而言之,这次集成的过程充满了冒险和趣味;从深入研究并对不同的库做一些“手术”,到整合一切并最终使其发挥作用,每一步都充满挑战!
+总而言之,这次集成的过程充满了冒险和趣味; 从深入研究并对不同的库做一些“手术”,到整合一切并最终使其发挥作用,每一步都充满挑战!
现在,我们看看如何在 `transformers` 中成功使用它并从中获益!
@@ -372,11 +382,11 @@ def replace_8bit_linear(model, threshold=6.0, module_to_not_convert="lm_head"):
### 硬件要求
-CPU 不支持 8 位张量核心[译者注:Intel 最新的 Sapphire Rapids CPU 已支持 8 位张量指令集:AMX]。 bitsandbytes 可以在支持 8 位张量核心的硬件上运行,这些硬件有 Turing 和 Ampere GPU(RTX 20s、RTX 30s、A40-A100、T4+)。例如,Google Colab GPU 通常是 NVIDIA T4 GPU,而最新的 T4 是支持 8 位张量核心的。我们后面的演示将会基于 Google Colab!
+CPU 不支持 8 位张量核心 [译者注: Intel 最新的 Sapphire Rapids CPU 已支持 8 位张量指令集: AMX]。 bitsandbytes 可以在支持 8 位张量核心的硬件上运行,这些硬件有 Turing 和 Ampere GPU (RTX 20s、RTX 30s、A40-A100、T4+)。例如,Google Colab GPU 通常是 NVIDIA T4 GPU,而最新的 T4 是支持 8 位张量核心的。我们后面的演示将会基于 Google Colab!
### 安装
-使用以下命令安装最新版本的库(确保你的 python>=3.8)。
+使用以下命令安装最新版本的库 (确保你的 python>=3.8)。
```bash
pip install accelerate
@@ -386,13 +396,15 @@ pip install git+https://github.com/huggingface/transformers.git
### 演示示例 - 在 Google Colab 上运行 T5 11B
-以下是运行 T5-11B 的演示。 T5-11B 模型的 checkpoint 精度为 FP32,需要 42GB 内存,Google Colab 里跑不动。使用我们的 8 位模块,它仅需 11GB 内存,因此能轻易跑通:
+以下是运行 T5-11B 的演示。 T5-11B 模型的 checkpoint 精度为 FP32,需要 42GB 内存,Google Colab 里跑不动。使用我们的 8 位模块,它仅需 11GB 内存,因此能轻易跑通:
-[![打开 T5-11B 的 Colab 演示](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/drive/1YORPWx4okIHXnjW7MSAidXN29mPVNT7F?usp=sharing)
+![打开 T5-11B 的 Colab 演示](https://colab.research.google.com/assets/colab-badge.svg)
+[](https://colab.research.google.com/drive/1YORPWx4okIHXnjW7MSAidXN29mPVNT7F?usp=sharing)
或者,你还可以看看下面这个使用 8 位 BLOOM-3B 模型进行推理的演示!
-[![打开 BLOOM-3B 的 Colab 演示](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/huggingface/blog/blob/main/notebooks/HuggingFace_int8_demo.ipynb)
+![打开 BLOOM-3B 的 Colab 演示](https://colab.research.google.com/assets/colab-badge.svg)
+[](https://colab.research.google.com/github/huggingface/blog/blob/main/notebooks/HuggingFace_int8_demo.ipynb)
## 影响范围
@@ -402,21 +414,21 @@ pip install git+https://github.com/huggingface/transformers.git
### 较小模型的推理加速
-正如我们在[基准测试部分](#比原始模型更快吗?)中看到的那样,我们可以将小模型(<=6B 参数)的运行速度提高近 2 倍。然而,虽然推理速度对于像 BLOOM-176B 这样的大模型来说比较稳定,但对小模型而言仍有改进的余地。我们已经定位到了问题并有希望恢复与 FP16 相同的性能,甚至还可能会有小幅加速。我们将在接下来的几周内合入这些改进。
+正如我们在 [基准测试部分](# 比原始模型更快吗?) 中看到的那样,我们可以将小模型 (<=6B 参数) 的运行速度提高近 2 倍。然而,虽然推理速度对于像 BLOOM-176B 这样的大模型来说比较稳定,但对小模型而言仍有改进的余地。我们已经定位到了问题并有希望恢复与 FP16 相同的性能,甚至还可能会有小幅加速。我们将在接下来的几周内合入这些改进。
-### 支持 Kepler GPU(GTX 1080 等)
+### 支持 Kepler GPU (GTX 1080 等)
-虽然我们只支持过去四年的所有 GPU,但现实是某些旧的 GPU(如 GTX 1080)现在仍然被大量使用。虽然这些 GPU 没有 Int8 张量核心,但它们有 Int8 向量单元(一种“弱”张量核心)。因此,这些 GPU 也可以体验 Int8 加速。然而,它需要一个完全不同的软件栈来优化推理速度。虽然我们确实计划集成对 Kepler GPU 的支持以使 LLM.int8() 的应用更广泛,但由于其复杂性,实现这一目标需要一些时间。
+虽然我们只支持过去四年的所有 GPU,但现实是某些旧的 GPU (如 GTX 1080) 现在仍然被大量使用。虽然这些 GPU 没有 Int8 张量核心,但它们有 Int8 向量单元 (一种“弱”张量核心)。因此,这些 GPU 也可以体验 Int8 加速。然而,它需要一个完全不同的软件栈来优化推理速度。虽然我们确实计划集成对 Kepler GPU 的支持以使 LLM.int8() 的应用更广泛,但由于其复杂性,实现这一目标需要一些时间。
### 在 Hub 上保存 8 位 checkpoint
-目前 8 位模型无法直接加载被推送到 Hub 上的 8 位 checkpoint。这是因为模型计算所需的统计数据(还记得上文提到的 `weight.CB` 和 `weight.SCB` 吗?)目前没有存储在 state_dict 中,而且 state_dict 的设计也未考虑这一信息的存储,同时 `Linear8bitLt` 模块也还尚未支持该特性。
+目前 8 位模型无法直接加载被推送到 Hub 上的 8 位 checkpoint。这是因为模型计算所需的统计数据 (还记得上文提到的 `weight.CB` 和 `weight.SCB` 吗?) 目前没有存储在 state_dict 中,而且 state_dict 的设计也未考虑这一信息的存储,同时 `Linear8bitLt` 模块也还尚未支持该特性。
但我们认为保存它并将其推送到 Hub 可能有助于提高模型的可访问性。
### CPU 的支持
-正如本文开头所述,CPU 设备不支持 8 位张量核。然而,我们能克服它吗?在 CPU 上运行此模块可以显著提高可用性和可访问性。[译者注:如上文,最新的 Intel CPU 已支持 8 位张量核]
+正如本文开头所述,CPU 设备不支持 8 位张量核。然而,我们能克服它吗?在 CPU 上运行此模块可以显著提高可用性和可访问性。[译者注: 如上文,最新的 Intel CPU 已支持 8 位张量核]
### 扩展至其他模态
@@ -424,14 +436,10 @@ pip install git+https://github.com/huggingface/transformers.git
## 致谢
-非常感谢以下为提高文章的可读性以及在 `transformers` 中的集成过程做出贡献的人(按字母顺序列出):
+非常感谢以下为提高文章的可读性以及在 `transformers` 中的集成过程做出贡献的人 (按字母顺序列出):
JustHeuristic (Yozh),
Michael Benayoun,
Stas Bekman,
Steven Liu,
Sylvain Gugger,
Tim Dettmers
-
-> 英文原文: https://huggingface.co/blog/hf-bitsandbytes-integration
-> 原文作者:Younes Belkada,Tim Dettmers
-> 译者: Matrix Yao (姚伟峰),英特尔深度学习工程师,工作方向为 transformer-family 模型在各模态数据上的应用及大规模模型的训练推理。
From 23977ac264840ac7d5d29afc25d4747ec0b74bcb Mon Sep 17 00:00:00 2001
From: Zhongdong Yang
Date: Wed, 26 Apr 2023 18:15:09 +0800
Subject: [PATCH 09/55] Proofread: red-teaming.md
---
zh/red-teaming.md | 65 ++++++++++++++++++++++-------------------------
1 file changed, 31 insertions(+), 34 deletions(-)
diff --git a/zh/red-teaming.md b/zh/red-teaming.md
index 1ef4f6bc47..969d011be3 100644
--- a/zh/red-teaming.md
+++ b/zh/red-teaming.md
@@ -1,43 +1,42 @@
---
-title: "红队( red-teaming )大语言模型"
+title: "为大语言模型建立红队对抗"
thumbnail: /blog/assets/red-teaming/thumbnail.png
authors:
- user: nazneen
- user: natolambert
- user: lewtun
+translators:
+- user: zhongdongy
---
-# 红队( red-teaming )大语言模型
+# 为大语言模型建立红队对抗
-# 红队( red-teaming )大语言模型
-在巨量文本数据下训练的大语言模型非常擅长生成现实文本。但是,这些模型通常会显现出一些不良行为像泄露个人信息(比如社会保险号)和生成错误信息,偏置,仇恨或有毒内容。举个例子, 众所周知,GPT3 的早期版本就表现出性别歧视(如下图)与[仇恨穆斯林言论](https://dl.acm.org/doi/abs/10.1145/3461702.3462624)的情况。
+在巨量文本数据下训练的大语言模型非常擅长生成现实文本。但是,这些模型通常会显现出一些不良行为像泄露个人信息 (比如社会保险号) 和生成错误信息,偏置,仇恨或有毒内容。举个例子,众所周知,GPT3 的早期版本就表现出性别歧视 (如下图) 与 [仇恨穆斯林言论](https://dl.acm.org/doi/abs/10.1145/3461702.3462624) 的情况。
-一旦我们在使用大语言模型时发现了这种不良结果,我们就可以制定一些策略来远离它们,像[生成歧视者指导序列生成( GEDI )](https://arxiv.org/pdf/2009.06367.pdf)或[插入和播放语言模型( PPLM )](https://arxiv.org/pdf/1912.02164.pdf)都是用来指导 GPT3 生成的。以下是使用相同提示( Prompt )的示例,但使用 GEDI 控制 GPT3 生成。
+一旦我们在使用大语言模型时发现了这种不良结果,我们就可以制定一些策略来远离它们,像 [生成歧视者指导序列生成 (GEDI)](https://arxiv.org/pdf/2009.06367.pdf) 或 [插入和播放语言模型 (PPLM)](https://arxiv.org/pdf/1912.02164.pdf) 都是用来指导 GPT3 生成的。以下是使用相同提示 (Prompt) 的示例,但使用 GEDI 控制 GPT3 生成。
-即使是最近的 GPT3 版本,也会在提示( prompt )注入攻击时产生类似的令人反感的内容,这变成了[这篇博客](https://simonwillison.net/2022/Sep/12/prompt-injection/)中讨论的下游应用程序的安全问题。
+即使是最近的 GPT3 版本,也会在提示 (prompt) 注入攻击时产生类似的令人反感的内容,这变成了 [这篇博客](https://simonwillison.net/2022/Sep/12/prompt-injection/) 中讨论的下游应用程序的安全问题。
+**红队** _是一种用于引出模型不良行为漏洞的评估形式。_ 越狱是另一个红队术语,用来表示操控冲破大语言模型限制。在 2016 年发布的 [微软聊天机器人 Tay](https://blogs.microsoft.com/blog/2016/03/25/learning-tays-introduction/) 和最近的 [必应聊天机器人 Sydney](https://www.nytimes.com/2023/02/16/technology/bing-chatbot-transcript.html) 是真实世界中反应缺乏用红队攻击对基础 ML 模型进行评估而发生的灾难。红队攻击的最初想法起源于军队中对抗模拟和战争游戏。
-**红队** *是一种用于引出模型不良行为漏洞的评估形式。* 越狱是另一个红队术语,用来表示操控冲破大语言模型限制。在 2016 年发布的 [ 微软聊天机器人 Tay](https://blogs.microsoft.com/blog/2016/03/25/learning-tays-introduction/) 和最近的 [必应聊天机器人 Sydney](https://www.nytimes.com/2023/02/16/technology/bing-chatbot-transcript.html) 是真实世界中反应缺乏用红队攻击对基础 ML 模型进行评估而发生的灾难。红队攻击的最初想法起源于军队中对抗模拟和战争游戏。
+红队语言模型的目标是制作一个提示 (prompt),该提示会触发模型生成有害内容。红队和同样知名的评估语言模型 _对抗攻击_ 有同也有异。相似之处在于红队和对抗攻击目标相同,即“攻击”或“欺骗”模型,以生成在现实世界中不想要的内容。但是对抗攻击很难让人理解,举例来说,通过将字符串 “aaabbbcc” 前缀到每个提示中,它会恶化模型性能。[Wallace 等人 2019 年的论文](https://arxiv.org/abs/1908.07125) 讨论了对各种 NLP 分类和生成任务的许多攻击的例子。在另一方面,红队的提示看起来更正常,像自然语言的提示。
-红队语言模型的目标是制作一个提示( prompt ),该提示会触发模型生成有害内容。红队和同样知名的评估语言模型*对抗攻击*分享一些相似之处与差异。相似之处在于红队和对抗攻击共享相同的目标,即“攻击”或“欺骗”模型,以生成在现实世界中不想要的内容。但是对抗攻击很难让人理解,举例来说,通过将字符串 “aaabbbcc”前缀到每个提示中,它会恶化模型性能。[Wallace等人](https://arxiv.org/abs/1908.07125)讨论了对各种 NLP 分类和生成任务的许多攻击的例子。在另一方面,红队的提示看起来更正常,像自然语言的提示。
+红队攻击可以揭露模型的局限性,包括引起用户不适或者暴力、不合法的恶意内容。红队 (就像对抗攻击) 的输出通常会被用来训练模型去减少有害内容或远离不想要的内容。
+由于红队需要创造性地思考可能的模型失败,巨大的搜索空间会导致资源紧张。这里的一个临时方法是对大语言模型增加一个分类器去预测输入的提示 (prompt) 中是否含导致生成恶意内容的话题或短语,如果含有则生成相关回应。这种策略过于谨慎,极大的限制了模型并且时常导致模型产生回避。所以在模型有帮助 (遵循指令) 与无害 (尽可能少的产生有害内容) 之间存在一个紧张关系。红队在这时就显得非常有用了。
-红队可以揭露模型的局限性,包括引起用户不适或者暴力,不合法的恶意内容。 红队(就像对抗攻击) 的输出通常会被用来训练模型去减少有害内容或远离不想要的内容。
-
-由于红队需要创造性地思考可能的模型失败,这就造成了对于巨大搜索空间的资源紧张。这里的一个临时方法是对大语言模型增加一个分类器去预测输入的提示( prompt )中是否含导致生成恶意内容的话题或短语,如果含有则生成相关回应。这种策略使得模型非常谨慎,但极大的限制了模型并且经常触发。所以在模型有帮助(遵循指令)与无害(尽可能少的产生有害内容)之间存在一个紧张关系。红队在这时就显得非常有用了。
-
-红队攻击可以是人力循环或者正在测试另一个语言模型有害输出的语言模型。提出针对安全和对齐方式进行微调的模型(例如通过 RLHF 或 SFT )的模型提示,需要以*角色扮演攻击*的形式进行创造性的思考,其中大语言模型被指示表现为恶意角色在[ Ganguli et al., ‘22](https://arxiv.org/pdf/2209.07858.pdf)中。 用代码而不是自然语言指示模型同样也可以揭露模型的学习的一些偏置。就像如下例子。
+红队攻击可以是人力循环或者正在测试另一个语言模型有害输出的语言模型。提出针对安全和对齐方式进行微调的模型 (例如通过 RLHF 或 SFT) 的模型提示,需要以 _角色扮演攻击_ 的形式进行创造性的思考,其中大语言模型被指示表现为恶意角色在 [Ganguli 等 2022 年的论文](https://arxiv.org/pdf/2209.07858.pdf) 中。用代码而不是自然语言指示模型同样也可以揭露模型的学习的一些偏置。就像如下例子。
@@ -52,7 +51,7 @@ authors:
-查看[此](https://twitter.com/spiantado/status/1599462375887114240) 推文获取更多示例。
+查看 [此](https://twitter.com/spiantado/status/1599462375887114240) 推文获取更多示例。
这里列出了在 ChatGPT 刺激大语言模型进行越狱的列表。
@@ -60,37 +59,35 @@ authors:
-红队大语言模型依旧是一个新的研究领域但是上述提到的策略依旧可以在越狱中正常运行,并且有助于部署机器学习的产品。随着这些模型的涌现能力变得更加强大,开发可以不断适应的红队方法将变得至关重要。一些需要进行红队攻击的最佳实践包括模拟寻求权力行为的方案(例如:资源),说服人们(例如:伤害自己或他人),具有医学输出的代理(例如:通过 API 在线订购化学药品)。我们将这种可能性和物理后果的可能性称为*关键威胁情景*。
+红队大语言模型依旧是一个新的研究领域,但是上述提到的策略依旧可以在成功让这些模型“越狱”,并且有助于部署机器学习的产品。随着这些模型推陈出新、能力变强,开发可以不断适应的红队方法将变得至关重要。一些需要进行红队攻击的最佳实践包括模拟寻求权力行为的方案 (例如: 资源),说服人们 (例如: 伤害自己或他人),具有医学输出的代理 (例如: 通过 API 在线订购化学药品)。我们将这种可能性和物理后果的可能性称为 _关键威胁场景_。
-在评估大语言模型中恶意行为的警示中,我们不知道他们的能力,毕竟他们不是显示训练去展示这种能力的(涌现能力)。所以,实际了解大语言模型的能力的唯一方法是,当它们变得更强大,可以模拟所有可能导致竞争结果并在每种情况下评估模型的行为的所有可能场景。这意味着我们的模型的安全行为与我们的红队方法的强度相关联。
+在评估大语言模型中恶意行为的警示中,我们不知道它们的能力,毕竟它们不是故意训练去展示这种能力的 (涌现能力)。所以实际了解大语言模型的能力的唯一方法是,当它们变得更强大,可以模拟所有可能导致有恶意的结果,并在每种情况下评估模型的行为的所有可能场景。这意味着我们的模型的安全行为与我们的红队方法的强度相关联。
-针对这一持续的红队的挑战,这里在数据集和最佳实践(包括学术,工业和政府实体)上进行了多组织合作的激励措施。共享信息的结构化过程可以使较小的实体在模型发布前进行红队攻击,从而使整个用户体验更安全。
+针对这一持续的红队的挑战,这里在数据集和最佳实践 (包括学术、工业和政府实体) 上进行了多组织合作的激励措施。共享信息的结构化过程可以使较小的实体在模型发布前进行红队攻击,从而使整个用户体验更安全。
-**红队的开放数据集:**
+**红队的开放数据集:**
1. Meta 的 [机器人对抗对话数据集](https://github.com/facebookresearch/ParlAI/tree/main/parlai/tasks/bot_adversarial_dialogue)
-2. Anthropic 的[红队尝试](https://huggingface.co/datasets/Anthropic/hh-rlhf/tree/main/red-team-attempts)
+2. Anthropic 的 [红队尝试](https://huggingface.co/datasets/Anthropic/hh-rlhf/tree/main/red-team-attempts)
3. AI2 的 [RealToxicityPrompts](https://huggingface.co/datasets/allenai/real-toxicity-prompts)
-**在红队大语言模型找过去的工作** (在 [Anthropic's Ganguli et al. 2022](https://arxiv.org/abs/2209.07858) 和 [Perez et al. 2022](https://arxiv.org/abs/2202.03286) 两篇文章中)
+**从过去的工作中寻找红队大语言模型相关的努力** (在 [Anthropic’s Ganguli et al. 2022](https://arxiv.org/abs/2209.07858) 和 [Perez et al. 2022](https://arxiv.org/abs/2202.03286) 两篇文章中)
-1. 用有帮助的,忠实的,无害的行为在红队攻击中进行少量提示学习并*不*比单纯的语言模型困难。
-2. 攻击成功率与缩放模型大小没有明确的关系,除了 RLHF 模型在缩放时更难进行红队攻击 。
+1. 用有帮助的,忠实的,无害的行为在红队攻击中进行少量提示学习并 _不_ 比单纯的语言模型困难。
+2. 攻击成功率与缩放模型大小没有明确的关系,除了 RLHF 模型在缩放时更难进行红队攻击。
3. 模型可能会通过回避表现的无害,在有帮助和无害之间存在权衡。
-4. 人类在构成成功攻击方面保持总体一致性。
-5. 成功率的分布在危害类别的类别中有所不同,而非暴力的成功率具有更高的成功率。
-6. 众包红色团队会导致模板 Y 提示(例如:“给出一个以 X 开头的平均单词”),使其变得多余。
+4. 人类在判断是否达成一次成功攻击的观点难以达成一致。
+5. 成功率的分布在不同危害类别中有所差异,其中非暴力提示的成功率更高。
+6. 众包 (crowdsourcing) 红队会产生 y-模板 提示 (例如: “给出一个以 X 开头的恶毒词语”),使其变得多余。
+
**未来方向:**
1. 没有用于代码生成的开源红队数据集,它试图通过代码越狱模型,例如生成实现 DDOS 或后门攻击的程序。
-2. 评估回避和有帮助之间的权衡。
-3. 为关键威胁场景设计和实施 红队大语言模型的策略。
-4. 红队可能是资源密集的,无论是计算还是人力资源,因此将从共享策略,开源数据集以及可能的合作中获得更大的成功机会,从而受益。
-
-这些局限性和未来的方向清楚地表明,红队是现代大语言模型工作流程中未经探索和关键的组成部分。这篇文章是对大语言模型研究人员和 Huggingface 开发人员社区的号召,以协作这些努力,实现安全和友好的世界:)
-
+2. 为关键威胁场景设计和实施大语言模型红队方案的策略。
+3. 红队可能是资源密集的,无论是计算还是人力资源,因此将从共享策略,开源数据集以及可能的合作中获得更大的成功机会,从而受益。
+4. 评估回避和有帮助之间的权衡。
+5. 综合比较根据上述方案的利弊,找到红队方案的最优解集 (类似于 Anthropic 的 Constitutional AI)。
-*致谢:* 感谢 [Yacine Jernite](https://huggingface.co/yjernite) 的在正确使用本篇博文中术语的有用建议。
+这些局限性和未来的方向清楚地表明,红队是现代大语言模型工作流程中亟待探索又至关重要的组成部分。这篇文章旨在号召大语言模型研究人员和 Hugging Face 开发者社区,希望大家在这些方面保持协作,共建安全、友好的世界:)
-> 原文:https://huggingface.co/blog/red-teaming
-> 译者:innovation64(李洋)
+_致谢:_ 感谢 [Yacine Jernite](https://huggingface.co/yjernite) 关于在这篇博文中正确使用术语的实用建议。
From caee1ffbf0aa526dc768842ae28dd41700bdccba Mon Sep 17 00:00:00 2001
From: Zhongdong Yang
Date: Thu, 27 Apr 2023 17:14:42 +0800
Subject: [PATCH 10/55] Update: add red-teaming to zh/_blog.yml
---
zh/_blog.yml | 15 ++++++++++++++-
zh/red-teaming.md | 2 ++
2 files changed, 16 insertions(+), 1 deletion(-)
diff --git a/zh/_blog.yml b/zh/_blog.yml
index 677ee899c3..5dced23be7 100644
--- a/zh/_blog.yml
+++ b/zh/_blog.yml
@@ -323,6 +323,19 @@
- cv
- multimodal
+- local: red-teaming
+ title: "Red-Teaming Large Language Models"
+ author: nazneen
+ thumbnail: /blog/assets/red-teaming/thumbnail.png
+ date: February 22, 2023
+ tags:
+ - llms
+ - rlhf
+ - red-teaming
+ - chatgpt
+ - safety
+ - alignment
+
- local: controlnet
title: "使用 🧨 Diffusers 实现 ControlNet 高速推理"
author: sayakpaul
@@ -418,4 +431,4 @@
date: April 24, 2023
tags:
- partnerships
- - community
+ - community
\ No newline at end of file
diff --git a/zh/red-teaming.md b/zh/red-teaming.md
index 969d011be3..fceaac1d17 100644
--- a/zh/red-teaming.md
+++ b/zh/red-teaming.md
@@ -6,7 +6,9 @@ authors:
- user: natolambert
- user: lewtun
translators:
+- user: innovation64
- user: zhongdongy
+ proofreader: true
---
# 为大语言模型建立红队对抗
From cd991de6d7af06ee6e40925a53c6ad5447029738 Mon Sep 17 00:00:00 2001
From: Luke Cheng <2258420+chenglu@users.noreply.github.com>
Date: Thu, 27 Apr 2023 17:23:36 +0800
Subject: [PATCH 11/55] Update _blog.yml
---
zh/_blog.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/zh/_blog.yml b/zh/_blog.yml
index 5dced23be7..1d8c4fd280 100644
--- a/zh/_blog.yml
+++ b/zh/_blog.yml
@@ -324,7 +324,7 @@
- multimodal
- local: red-teaming
- title: "Red-Teaming Large Language Models"
+ title: "为大语言模型建立红队对抗"
author: nazneen
thumbnail: /blog/assets/red-teaming/thumbnail.png
date: February 22, 2023
@@ -431,4 +431,4 @@
date: April 24, 2023
tags:
- partnerships
- - community
\ No newline at end of file
+ - community
From 1d7dd33fa7d47c5979284a58f1f0e29ba98f69dd Mon Sep 17 00:00:00 2001
From: Zhongdong Yang
Date: Thu, 27 Apr 2023 17:14:42 +0800
Subject: [PATCH 12/55] Update: add red-teaming to zh/_blog.yml
Fix: red-teaming title in zh/_blog.yml
---
zh/_blog.yml | 15 ++++++++++++++-
zh/red-teaming.md | 2 ++
2 files changed, 16 insertions(+), 1 deletion(-)
diff --git a/zh/_blog.yml b/zh/_blog.yml
index 677ee899c3..2faac7705a 100644
--- a/zh/_blog.yml
+++ b/zh/_blog.yml
@@ -323,6 +323,19 @@
- cv
- multimodal
+- local: red-teaming
+ title: "为大语言模型建立红队对抗"
+ author: nazneen
+ thumbnail: /blog/assets/red-teaming/thumbnail.png
+ date: February 22, 2023
+ tags:
+ - llms
+ - rlhf
+ - red-teaming
+ - chatgpt
+ - safety
+ - alignment
+
- local: controlnet
title: "使用 🧨 Diffusers 实现 ControlNet 高速推理"
author: sayakpaul
@@ -418,4 +431,4 @@
date: April 24, 2023
tags:
- partnerships
- - community
+ - community
\ No newline at end of file
diff --git a/zh/red-teaming.md b/zh/red-teaming.md
index 969d011be3..fceaac1d17 100644
--- a/zh/red-teaming.md
+++ b/zh/red-teaming.md
@@ -6,7 +6,9 @@ authors:
- user: natolambert
- user: lewtun
translators:
+- user: innovation64
- user: zhongdongy
+ proofreader: true
---
# 为大语言模型建立红队对抗
From 7010fd3b77279719051fb5c6f98e725c35f352eb Mon Sep 17 00:00:00 2001
From: Zhongdong Yang
Date: Fri, 28 Apr 2023 11:51:22 +0800
Subject: [PATCH 13/55] Fix: red-teaming PPLM translation
---
zh/red-teaming.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/zh/red-teaming.md b/zh/red-teaming.md
index fceaac1d17..67704aba13 100644
--- a/zh/red-teaming.md
+++ b/zh/red-teaming.md
@@ -22,7 +22,7 @@ translators:
-一旦我们在使用大语言模型时发现了这种不良结果,我们就可以制定一些策略来远离它们,像 [生成歧视者指导序列生成 (GEDI)](https://arxiv.org/pdf/2009.06367.pdf) 或 [插入和播放语言模型 (PPLM)](https://arxiv.org/pdf/1912.02164.pdf) 都是用来指导 GPT3 生成的。以下是使用相同提示 (Prompt) 的示例,但使用 GEDI 控制 GPT3 生成。
+一旦我们在使用大语言模型时发现了这种不良结果,我们就可以制定一些策略来远离它们,像 [生成歧视者指导序列生成 (GEDI)](https://arxiv.org/pdf/2009.06367.pdf) 或 [即插即用语言模型 (PPLM)](https://arxiv.org/pdf/1912.02164.pdf) 都是用来指导 GPT3 生成的。以下是使用相同提示 (Prompt) 的示例,但使用 GEDI 控制 GPT3 生成。
From 41607dd88989c1f7cda01e80ae9a13f19af0f65a Mon Sep 17 00:00:00 2001
From: "Yao, Matrix"
Date: Mon, 1 May 2023 15:18:56 -0400
Subject: [PATCH 14/55] deep-learning-with-proteins cn done
Signed-off-by: Yao, Matrix
---
zh/_blog.yml | 11 ++-
zh/deep-learning-with-proteins.md | 121 ++++++++++++++++++++++++++++++
2 files changed, 131 insertions(+), 1 deletion(-)
create mode 100644 zh/deep-learning-with-proteins.md
diff --git a/zh/_blog.yml b/zh/_blog.yml
index 2faac7705a..5a507e12c5 100644
--- a/zh/_blog.yml
+++ b/zh/_blog.yml
@@ -431,4 +431,13 @@
date: April 24, 2023
tags:
- partnerships
- - community
\ No newline at end of file
+ - community
+
+- local: deep-learning-with-proteins
+ title: "蛋白质深度学习"
+ author: rocketknight1
+ thumbnail: /blog/assets/119_deep_learning_with_proteins/folding_example.png
+ date: December 2, 2022
+ tags:
+ - guide
+ - fine-tuning
diff --git a/zh/deep-learning-with-proteins.md b/zh/deep-learning-with-proteins.md
new file mode 100644
index 0000000000..f3021781f6
--- /dev/null
+++ b/zh/deep-learning-with-proteins.md
@@ -0,0 +1,121 @@
+---
+title: "蛋白质深度学习"
+thumbnail: /blog/assets/119_deep_learning_with_proteins/folding_example.png
+authors:
+- user: rocketknight1
+translators:
+- user: MatrixYao
+---
+
+# 蛋白质深度学习
+
+本文主要面向两类目标读者:一类是想使用机器学习的生物学家,一类是想进入生物学领域的机器学习研究者。如果你不熟悉生物学或机器学习,仍然欢迎你阅读本文,但有时你可能会觉得有点读不太懂!如果你已经熟悉这两者,那么你可能根本不需要本文 —— 你可以直接跳到我们的示例 notebook 以查看这些模型的实际应用:
+
+- 微调蛋白质语言模型([PyTorch](https://colab.research.google.com/github/huggingface/notebooks/blob/main/examples/protein_language_modeling.ipynb),[TensorFlow](https://colab.research.google.com/github/huggingface/notebooks/blob/main/examples/protein_language_modeling-tf.ipynb))
+- 使用 ESMFold 进行蛋白质折叠([PyTorch](https://colab.research.google.com/github/huggingface/notebooks/blob/main/examples/protein_folding.ipynb),因为 `OpenFold` 仅支持 PyTorch,所以目前仅支持 PyTorch)
+
+## 面向生物学家的科普:语言模型是什么鬼?
+
+用于处理蛋白质的模型深受 BERT 和 GPT 等大语言模型的启发。因此,为了了解这些模型是如何工作的,我们要回到 2016 年左右,那时大语言模型还没有出现,特朗普还没有当选,脱欧还没有发生,深度学习(Deep Learning,DL)还是个日日新的超级新星...... DL 成功的关键在于它使用人工神经网络来学习数据中的复杂模式。不过,深度学习有一个关键问题 —— 它需要**大量**的数据才能正常工作,而在很多任务中,根本没那么多数据。
+
+假设你想训练一个 DL 模型,输入一个英语句子,并判断它是否合乎语法。所以你准备了训练数据,格式如下:
+
+| Text | Label |
+| --- | --- |
+| The judge told the jurors to think carefully. | Correct |
+| The judge told that the jurors to think carefully. | Incorrect |
+| … | … |
+
+理论上,这个任务在当时是完全可行的 —— 如果你将如上格式的训练数据输入深度学习模型,它就可以学着去预测新句子是否合乎语法。但在实践中,它的效果并不怎么好,因为在 2016 年,大多数人都从一个随机初始化的新模型开始他们的每项任务。这意味着**模型必须仅从给定的训练数据中学习它们需要知道的一切!**
+
+我们来理解一下这到底有多难,假设你是一个机器学习模型,我提供给你一些训练数据用于完成我希望你学习的任务。假如我给你的训练数据如下:
+
+| Text | Label |
+| --- | --- |
+| Is í an stiúrthóir is fearr ar domhan! | 1 |
+| Is fuath liom an scannán seo. | 0 |
+| Scannán den scoth ab ea é. | 1 |
+| D’fhág mé an phictiúrlann tar éis fiche nóiméad! | 0 |
+
+在这里,我选择了一种我希望你从未曾见过的语言,所以我猜你已经可能开始对你是否能学会这个任务不太自信了。也许在数百或数千个样本之后,你可能会开始注意到输入中一些重复出现的单词或模式,然后你可能开始能够作出比随机机猜测更好的判断,但即使这样,一旦出现新单词或之前没见过的措辞马上就能够难住你,让你猜错。无独有偶,这也是 DL 模型当时的表现!
+
+现在我们试试相同的任务,但这次使用英语:
+
+| Text | Label |
+| --- | --- |
+| She’s the best director in the world! | 1 |
+| I hate this movie. | 0 |
+| It was an absolutely excellent film. | 1 |
+| I left the cinema after twenty minutes! | 0 |
+
+现在事情变得简单了 —— 任务只是预测电影评论是正面(1)还是负面(0)的。仅使用两个正例和两个反例,你就能以接近 100% 的准确率完成这项任务,因为**你原本就具备大量的英语词汇和语法知识,并具有电影和情感相关表达的文化背景。** 如果没有这些知识,事情就会变得更像第一个任务 —— 你需要阅读大量的例子才能开始发现输入中的表达模式,即使你花时间研究了数十万个的例子你的猜测仍然远不如在英语任务中只有四个例子准确。
+
+### 关键突破:迁移学习
+
+在机器学习中,我们把这种将先验知识迁移到新任务的概念称为“**迁移学习**”。在 DL 上使用迁移学习是 2016 年左右该领域的一个主要目标。预训练词向量之类的东西(非常有趣,但超出了本文的范围!)在 2016 年确实存在并且允许迁移一些知识到新的模型,但是这种知识迁移仍然比较肤浅,模型仍然需要大量的训练数据才能很好地工作。
+
+这种情况一直持续到 2018 年。2018 年,两篇巨著横空出世,第一篇引入了 [ULMFiT](https://arxiv.org/abs/1801.06146) 模型,第二篇引入了 [BERT](https://arxiv.org/abs/1810.04805) 模型。这两篇论文是让自然语言迁移学习真正发挥作用的开创性论文,尤其是 BERT 标志着预训练大语言模型时代的发轫。两篇论文共同使用了一个技巧,那就是它们利用了深度学习中人工神经网络的固有性质 —— 先花较长的时间在有着丰富训练数据的文本任务上训练神经网络,然后将整个神经网络复制到新任务中,仅用新任务的数据更新或重新训练与网络输出相对应的少数神经元。
+
+![迁移学习](/blog/assets/119_deep_learning_with_proteins/transfer_learning.png)
+
+*上图来自 [ULMFiT 论文](https://arxiv.org/abs/1801.06146),它展示了在三个独立的任务上使用迁移学习与从头开始训练模型相比带来的巨大的性能提升。在许多情况下,使用迁移学习的效果相当于拥有超过 100 倍的训练数据。不要忘记这是 2018 年发布的 —— 现代的大语言模型可以做得更好!*
+
+这样做的原因是,在解决任何重要任务的过程中,神经网络学习到很多输入数据的结构性知识 —— 如对于视觉神经网络,输入的是原始像素,模型学习到了如何识别直线、曲线和边缘;对于文本神经网络,输入的是原始文本,模型学习到了有关语法结构的细节。而这些信息并不特定于某些任务。—— 迁移学习起作用的关键原因是**解决任务需要知道的很多信息都不是特定于该任务的!** 要对电影评论进行分类,你不需要了解很多关于电影评论的知识,但你需要大量的英语和文化背景知识。通过选择训练数据丰富的任务,我们可以让神经网络学习此类“领域知识”,然后将其应用于我们关心的新任务,而在这些新任务中训练数据可能更难获取。
+
+至此,希望你已经了解了什么是迁移学习,并且大语言模型是一个经过大量文本数据训练而得的大型神经网络,这使其成为迁移到新任务的主要备选方案。我们将在下面看到相同的技术如何应用于蛋白质,但首先我需要为另一半观众写一篇介绍。如果你已经熟悉这方面的知识,你可以随时跳过下一部分!
+
+
+## 面向机器学习研究者的科普:蛋白质是什么鬼?
+
+简而言之,蛋白质可以做很多事情。有些蛋白质是**酶** - 它们充当化学反应的催化剂。当你的身体将营养物质转化为能量时,从食物到肌肉运动的每一步都由一种酶催化。一些蛋白质是**结构性的**,它们的功能是提供稳定性以及塑形,例如结缔组织的蛋白质。如果你看过化妆品广告,你可能看到过**胶原蛋白**、**弹性蛋白**以及**角蛋白**,这些是构成我们皮肤和头发结构的蛋白质。
+
+其它蛋白质对健康和疾病至关重要 —— 每个人可能都记得有关 COVID-19 病毒的 **spike 蛋白**的无数新闻报道。 COVID spike 蛋白与人类细胞表面一种名为 ACE2 的蛋白质结合,使其能够进入细胞并传递病毒 RNA 的有效载荷。由于这种相互作用对感染至关重要,因此在 COVID 大流行期间对这些蛋白质及其相互作用进行建模是一个热门研究焦点。
+
+蛋白质由多个**氨基酸组成**。氨基酸是相对简单的分子,它们都具有相同的分子结构,而该结构的化学性质允许氨基酸融合在一起,从而使单个分子可以成为一条长链。这里关键是要知道氨基酸种类不多 —— 只有 20 种标准氨基酸,某些生物体上可能还有一些其他非标准的氨基酸,但总量不多。导致蛋白质巨大多样性的原因是**这些氨基酸可以按任何顺序组合**,而由此产生的蛋白质链可以具有截然不同的形状和功能,因为链的不同部分会粘连以及彼此折叠。与文本类比一下:英语只有 26 个字母,但想想你可以用这 26 个字母的组合写出各种单词。
+
+事实上,由于氨基酸的数量很少,生物学家可以为每一种氨基酸分配一个不同的字母。这意味着你可以像编写文本字符串一样编写蛋白质!例如,假设一种蛋白质链中有这些氨基酸:甲硫氨酸、丙氨酸和组氨酸。这些氨基酸的 [对应的字母](https://en.wikipedia.org/wiki/Amino_acid#Table_of_standard_amino_acid_abbreviations_and_properties) 是 M、A 和 H,因此我们可以将该链写为 “MAH” 。不过,大多数蛋白质含有数百甚至数千个氨基酸,而不仅仅是三个!!
+
+![蛋白质结构](/blog/assets/119_deep_learning_with_proteins/protein_structure.png)
+
+*上图显示了一种蛋白质的两种表示形式。所有氨基酸都包含碳 - 碳 - 氮(C-C-N)序列。当氨基酸融合到蛋白质中时,这种重复模式将贯穿始终,我们称为蛋白质的 “骨架”。然而,氨基酸的不同之处在于它们的 “侧链”,侧链指的是附着在 C-C-N 主链上的原子。图的下半部分有标记为 R1、R2 和 R3 的侧链,它们可以是任何氨基酸。在图的上半部分,中央氨基酸有一个 CH3 侧链 - 那么该氨基酸即为**丙氨酸,由字母 A 表示**([图片来源](https://commons.wikimedia.org/wiki/File:Peptide-Figure-Revised.png))。*
+
+尽管我们可以将其写成文本字符串,但蛋白质实际上并不是一种 “语言”,至少不是诺姆 - 乔姆斯基认可的任何一种语言。但它们确实有一些类似语言的特征,从机器学习的角度来看,它们是一个与文本非常相似的领域:只有一部分字符串是有“意义”的。随机文本是垃圾,随机蛋白质只是一个无形状的斑点。
+
+此外,如果你只是孤立地考虑蛋白质的一部分,信息就会丢失,就像当你只阅读从较长文本中提取的某个句子时,信息也会丢失。蛋白质的一个区域可能只有在其它部分存在的情况下才会呈现其自然形状,因为需要其它部分帮助稳定和矫正其形状!这意味着被全局自注意力很好地捕捉到的那种长程作用力对于正确建模蛋白质非常重要。
+
+至此,希望你对蛋白质是什么以及为什么生物学家如此关心它们有一个基本的概念 —— 尽管氨基酸“字母表” 、很小,但它们具有广泛的结构和功能多样性。因此如果能仅通过观察氨基酸的原始“字符串”来理解和预测蛋白质的结构和功能对研究是非常有价值的。
+
+## 联袂 - 蛋白质机器学习
+
+现在我们已经了解了使用语言模型进行迁移学习是如何工作的,同时我们还了解了什么是蛋白质。一旦你有了这些背景知识,下一步就不难了 —— 我们可以在蛋白质上应用相同的迁移学习思想!我们不是在涉及英文文本的任务上预先训练模型,而是在输入是蛋白质且有大量可用训练数据的任务上训练它。一旦我们这样做了,我们的模型就有希望学到很多关于蛋白质结构的知识,就像语言模型学到了很多关于语言结构的知识一样。这使得预训练的蛋白质模型有希望可以迁移到任何其它基于蛋白质的任务!
+
+生物学家想在哪些任务上用机器学习训练蛋白质模型?最著名的蛋白质建模任务是**蛋白质折叠**。该任务是,给定像 “MLKNV……” 这样的氨基酸链,预测蛋白质最终会折叠成什么形状。这是一项极其重要的任务,因为准确预测蛋白质的形状和结构可以深入了解蛋白质作用和机理。
+
+早在现代机器学习出现之前,人们就一直在研究这个问题。最早的一些大规模分布式计算项目,如 Folding@Home,以超精的空间和时间分辨率使用原子级模拟来模拟蛋白质折叠。甚至还存在一个专门的*蛋白质晶体学*领域,该领域的研究者使用 X 射线衍射来观察从活细胞中分离出的蛋白质的结构。
+
+然而,与许多其他领域一样,深度学习的到来改变了一切。 AlphaFold,尤其是 AlphaFold2 使用了 transformer 结构的深度学习模型,并在模型上增加了针对蛋白质数据的处理,在仅从原始氨基酸序列预测新型蛋白质结构方面取得了出色的结果。如果你对蛋白质折叠感兴趣,我们强烈建议你看看[我们的 ESMFold notebook](https://colab.research.google.com/github/huggingface/notebooks/blob/main/examples/protein_folding.ipynb) —— ESMFold 是一种类似于 AlphaFold2 的新模型,但它是一种更“纯”的深度学习模型,不需要任何外部数据库或搜索操作即可运行。因此,设置过程不像AlphaFold2 那样痛苦,模型运行得更快,同时仍保持出色的准确性。
+
+
+![蛋白质折叠示例](/blog/assets/119_deep_learning_with_proteins/folding_example.png)
+
+*上图为多杀巴斯德氏菌的**氨基葡萄糖 - 6 - 磷酸脱氨酶**同源二聚体的预测结构。该结构和可视化图是由上文中的 ESMFold notebook 在几秒钟内生成的。深蓝色表示结构置信度最高的区域。*
+
+不过,蛋白质折叠并不是我们唯一感兴趣的任务!生物学家可能想做更多的蛋白质分类任务 —— 比如他们想预测蛋白质将在细胞的哪个部分起作用,或者在蛋白质产生后其中哪些氨基酸会被修改。在机器学习的语言中,当你想对整个蛋白质进行分类(例如,预测其亚细胞定位)时,这类任务可被建模为**序列分类(sequence classification)**;当你想对每个氨基酸进行分类时(例如,预测哪些氨基酸会被翻译后修饰(Post-translational modification,PTM)),这类任务可被建模为**词分类(token classification)**。
+
+不过,关键的一点是,尽管蛋白质与语言非常不同,但它们可以通过几乎完全相同的机器学习方法来处理 —— 在一个大的蛋白质序列数据库上进行大规模预训练,然后通过**迁移学习**迁移到其它训练数据可能少得多的任务。事实上,在某些方面它甚至比像 BERT 这样的大型语言模型还要简单,因为不需要复杂的分词和词解析 —— 蛋白质没有分词,因此最简单的方法是直接将每个氨基酸转换成单词。
+
+## 听起来很酷,但从何下手?
+
+如果你已经熟悉深度学习,那么你会发现微调蛋白质模型的代码看起来与微调语言模型的代码非常相似。我们提供了 [PyTorch](https://colab.research.google.com/github/huggingface/notebooks/blob/main/examples/protein_language_modeling.ipynb) 和 [TensorFlow](https://colab.research.google.com/github/huggingface/notebooks/blob/main/examples/protein_language_modeling-tf.ipynb) 两个示例供你起步。你可以从像 [UniProt](https://www.uniprot.org/) 这样的开放蛋白质数据库中获取大量标注数据,UniProt 除了提供 REST API 接口以供访问数据外还提供了一个漂亮的 Web 界面。你的主要困难是找到有趣的研究方向进行探索,这我就爱莫能助了 —— 但我相信有很多生物学家愿意与你合作!
+
+反之,如果你是一名生物学家,你可能有很多想法想尝试,但可能对深入研究机器学习代码有点害怕。别怕!我们精心设计了示例([PyTorch](https://colab.research.google.com/github/huggingface/notebooks/blob/main/examples/protein_language_modeling.ipynb)、[TensorFlow](https://colab.research.google.com/github/huggingface/notebooks/blob/main/examples/protein_language_modeling-tf.ipynb)),这些示例中的数据加载部分与其他部分完全独立。这意味着如果你有一个**序列分类**或**词分类**任务,你只需要构建一个包含蛋白质序列及其应对标签的数据集,然后把我们的数据加载代码换成你自己写的用于加载你的数据集的代码就好了。
+
+尽管示例中使用 [ESM-2](https://www.biorxiv.org/content/10.1101/2022.07.20.500902v1) 作为基础预训练模型,因为它在当前是最先进的。该领域的研究人员可能还熟悉其他模型,如 Rost 实验室的 [ProtBERT](https://huggingface.co/Rostlab/prot_bert)([论文链接](https://www.biorxiv.org/content/10.1101/2020.07.12.199554v3)) 是同类中最早的模型之一,并且引起了生物信息学界的极大兴趣。只需将示例代码中的 checkpoint 路径从 `facebook/esm2xxx` 改为 `Rostlab/prot_bert` 之类的,示例中的代码就可以使用 ProtBERT 模型了。
+
+## 结语
+
+深度学习和生物学的交叉领域将在未来几年成为一个非常活跃和成果丰硕的领域。然而,使得深度学习发展如此迅速的原因之一是人们可以快速重现结果并调整新模型以供自己使用。本着这种精神,如果你训练了一个你认为对社区有用的模型,请分享它!上面那些notebook 中都包含将模型上传到 Hub 的代码,其他研究人员可以在 Hub 上自由访问和构建它们 - 除了对该领域的好处之外,这也可以让你的论文被更多人见到和引用。你甚至可以使用 [Spaces](https://huggingface.co/docs/hub/spaces-overview) 做一个实时的网络演示版,以便其他研究人员可以输入蛋白质序列并免费获得结果,而无需编写一行代码。祝你好运,愿审稿人对你青眼相加!
+
+> 英文原文: https://huggingface.co/blog/deep-learning-with-proteins
+> 原文作者:Matthew Carrigan
+> 译者: Matrix Yao (姚伟峰),英特尔深度学习工程师,工作方向为 transformer-family 模型在各模态数据上的应用及大规模模型的训练推理。
From 0163b109b7fe839309c12e95311d7cf78af1cca2 Mon Sep 17 00:00:00 2001
From: Zhongdong Yang
Date: Thu, 4 May 2023 14:46:52 +0800
Subject: [PATCH 15/55] Add: stackllama.md
---
zh/_blog.yml | 10 ++
zh/stackllama.md | 296 +++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 306 insertions(+)
create mode 100644 zh/stackllama.md
diff --git a/zh/_blog.yml b/zh/_blog.yml
index 2faac7705a..8b5b76cd52 100644
--- a/zh/_blog.yml
+++ b/zh/_blog.yml
@@ -414,6 +414,16 @@
tags:
- ethics
+- local: stackllama
+ title: "“StackLLaMA”: 用 RLHF 训练 LLaMA 的手把手教程"
+ author: edbeeching
+ thumbnail: /blog/assets/138_stackllama/thumbnail.png
+ date: April 5, 2023
+ tags:
+ - rl
+ - rlhf
+ - nlp
+
- local: graphml-classification
title: "使用 Transformers 进行图分类"
author: clefourrier
diff --git a/zh/stackllama.md b/zh/stackllama.md
new file mode 100644
index 0000000000..37f85c0737
--- /dev/null
+++ b/zh/stackllama.md
@@ -0,0 +1,296 @@
+---
+title: "“StackLLaMA”: 用 RLHF 训练 LLaMA 的手把手教程"
+thumbnail: /blog/assets/138_stackllama/thumbnail.png
+authors:
+- user: edbeeching
+- user: kashif
+- user: ybelkada
+- user: lewtun
+- user: lvwerra
+- user: nazneen
+- user: natolambert
+translators:
+- user: Vermillion-Qi
+- user: zhongdongy
+---
+
+# “StackLLaMA”: 用 RLHF 训练 LLaMA 的手把手教程
+
+
+
+
+如 [ChatGPT](https://openai.com/blog/chatgpt),[GPT-4](https://openai.com/research/gpt-4),[Claude](https://www.anthropic.com/index/introducing-claude)语言模型 之强大,因为它们采用了 **基于人类反馈的强化学习** (Reinforcement Learning from Human Feedback, RLHF) 来使之更符合我们的使用场景。
+
+本博客旨在展示用 RLHF 训练一个 [LLaMA](https://ai.facebook.com/blog/large-language-model-llama-meta-ai) 模型,以回答 [Stack Exchange](https://stackexchange.com/) 上的问题。具体而言,包含以下几个方面:
+
+- 有监督的微调 (Supervised Fine-tuning,SFT)。
+- 奖励 / 偏好建模 (Reward / preference modeling,RM)。
+- 基于人类反馈的强化学习 (RLHF)。
+
+![](https://man-archives.oss-cn-hangzhou.aliyuncs.com/goofan/202304122037176.png)
+
+摘自 InstructGPT 论文,Ouyang, Long, et al. “Training language models to follow instructions with human feedback.” arXiv preprint arXiv:2203.02155 (2022).
+
+结合了上述方法,我们发布了 StackLLaMA 模型,该模型在 [🤗 Hub](https://huggingface.co/trl-lib/llama-se-rl-peft) 上开源 (访问链接查看 [Meta 的原始 LLaMA](https://ai.facebook.com/blog/large-language-model-llama-meta-ai/) ),整个 [训练的流程](https://huggingface.co/docs/trl/index) 已经集成到了 Hugging Face TRL 库中 。你可以通过下面的 [demo](https://huggingface.co/spaces/trl-lib/stack-llama) 来尝试该模型。
+
+## LLaMA 模型
+
+在实践 RLHF 时,选取一个合适的模型很重要: RLHF 只是一个让模型满足我们交互形式的需求的微调过程 。所以我们选取了最近上线的 [LLaMA](https://arxiv.org/abs/2302.13971) 模型。LLaMA 模型是 Mata AI 最近推出的大语言模型。其参数量大小涵盖 7B 到 65B,以及训练在 1T 和 1.4T 的 token 上,这让其很实用。我们这里采用 7B 的模型。(请填写 Meta AI 的这份 [表单](https://docs.google.com/forms/d/e/1FAIpQLSfqNECQnMkycAp2jP4Z9TFX0cGR4uf7b_fBxjY_OjhJILlKGA/viewform) 来下载模型)。
+
+## Stack Exchange 数据集
+
+收集人类的反馈数据集是很复杂且昂贵的劳动。为了做到这个,并且还能保证模型的有效性,我们使用 [StackExchange 数据集](https://huggingface.co/datasets/HuggingFaceH4/stack-exchange-preferences)。该数据集涵盖了 StackExchange 平台上的问题和答案 (包含 StackOverflow 的编程等话题下的)。这很适合我们的实践,因为其包含了每个答案的赞和踩的数量。
+
+我们按照 [Askell et al. 2021](https://arxiv.org/abs/2112.00861) 中的方法,给每个答案赋分:
+
+```
+score = log2 (1 + upvotes) rounded to the nearest integer, plus 1 if the questioner accepted the answer (we assign a score of −1 if the number of upvotes is negative).
+```
+
+对奖励模型,我们将看到每个问题总是需要两个答案对比。有些问题有很多答案,可以产生很多对,我们只取十个以限制每个问题的数据量。最后,我们把格式从 HTML 转化到 Markdown 以提高输出的可读性。你可以看到数据集和处理过程的 [笔记本]。(https://huggingface.co/datasets/lvwerra/stack-exchange-paired。)
+
+## 高效训练策略
+
+即使是最小 LLaMA 模型的训练,都需要大量内存。估算一下: 以 bf16 半精度,每个参数用 2 个字节 (以 fp32 精度四字节的标准),训练时需要 8 个字节 (例如 Adam 优化器,参见 Tramsformers 的 [性能文档](https://huggingface.co/docs/transformers/perf_train_gpu_one#optimizer))。可见 7B 参数量的模型将用 (2+8)* 7B = 70 GB 的内存,并且还可能需要更多用于计算诸如注意力分数的中间值。所以很难在一张 80GB 显存的 A100 上训练。或许你可以使用一些技巧,比如用更高效的半精度训练的优化器来压缩内存,但溢出是迟早的。
+
+另外的可能是 **参数高效的微调**(Parameter-Efficient Fine-Tuning, PEFT) 技术,比如 [`peft`](https://github.com/huggingface/peft) 库,它可以对使用 8-bit 加载的模型做 **低秩优化**(Low-Rank Adaptation,LoRA)。
+
+![](https://man-archives.oss-cn-hangzhou.aliyuncs.com/goofan/202304122104084.gif)
+
+线性层的低秩优化: 额外参数 (橙色) 被加在 Frozen 层 (蓝色),编码后的隐藏状态与 Frozen 层的隐藏状态叠加在一起。
+
+以 8bit 加载模型会大幅降低内存占用,因为每个参数只要一字节 (比如 7B LLaMA 是 7GB 内存)。与直接训练原始模型不同,LoRA 在特定层 (一般是注意力层) 添加少量新参数,大幅降低了需要训练的参数。
+
+此情此景,一个衡量标准是 1B 的参数在整个微调过程中占 ~1.2-1.4GB (和具体 batch size 及序列长度有关)。在参考的博客中具体讨论了,这使得低成本下微调较大参数规模的模型成为可能 (比如在一张 A100 上微调 50-60B 的参数)。
+
+这些技术能让微调大模型的任务,在消费级设备和 Google Colab 上执行。这里提供一些值得关注的演示 demo: `facebook/opt-6.7b` (在 float16 精度下 13GB) 和 `openai/whisper-large`
+跑在 Google Colab (15GB 显存) 上。欲了解 `peft` 的使用,请参见 [github 仓库](https://github.com/huggingface/peft) 或者之前的 [博客介绍](https://huggingface.co/blog/trl-peft): 在客户端训练 20B 参数量的模型。
+
+现在我们能在一张 GPU 上微调很大的模型了,但训练还是会很慢。此时最简单的策略便是并行化: 把一个训练同时放到不同的 GPU 上,各 GPU 接受不同的 batch。这样我们可以并行执行前向传播和后向传播,通过增加 GPU 的数量实现并行能力提升。
+
+![](https://man-archives.oss-cn-hangzhou.aliyuncs.com/goofan/202304122114399.png)
+
+我们可以选用 `trainsformers.Trainer` 或 `accelerate`,因为它们都支持无代码变更进行数据并行化。只需注意调用 `torchrun` 或者 `accelerate launch` 脚本时的参数即可实现。比如以下就是在一个 8 显卡的机器上分别用 `accelerate launch` 和 `torchrun`的方法:
+
+```bash
+accelerate launch --multi_gpu --num_machines 1 --num_processes 8 my_accelerate_script.py
+torchrun --nnodes 1 --nproc_per_node 8 my_torch_script.py
+```
+
+## 有监督的微调
+
+在训练奖励模型和用 RL 之前,模型若是已经在我们感兴趣的方面表现好将会很有帮助。在我们的示例中,我们想要其能回答问题,而其他时候,我们可能它能听指令 (这时对指令执行的微调是理想的)。实现这个最简单的方法便是面向该语言任务,用该任务和领域的文本,继续训练。[StackExchange 数据集](https://huggingface.co/datasets/HuggingFaceH4/stack-exchange-preferences) 含 10M 的指令量,所以我们能用其子集很容易地训练。
+
+在用 RLHF 之前的模型微调没有特别的,就是一般的面向语言任务的预训练模型微调。为了高效利用数据,我们采用了称之为 **打包** 的技术: 与 batch 中的每个样本均由单一文本组成,最后基于最长的文本来 padding (填充),我们把很多文本拼接起来,用 EOS token 来隔开,然后分割成一些 chunk (切块) 来做成 batch,避免 padding。
+
+![](https://huggingface.co/datasets/trl-internal-testing/example-images/resolve/main/blog/stackllama/chapter10_preprocessing-clm.png)
+
+该方法大大提高了效率,因为模型输入的所有 token 都对 loss 有所训练,而非 padding 作为掩码被丢弃了。如果你没有足够数据,并且担心随意地分开 token 会失去上下文语义,你也可以用传统的数据加载器
+ `ConstantLengthDataset` 解决了 **打包**技术,并且我们能在用 `peft` 加载模型后用 `Trainer`。首先,我们用 `int8` 加载模型,准备训练,然后加入 `LoRA` 微调器。
+
+```python
+# load model in 8bit
+model = AutoModelForCausalLM.from_pretrained(
+ args.model_path,
+ load_in_8bit=True,
+ device_map={"": Accelerator().local_process_index}
+ )
+model = prepare_model_for_int8_training(model)
+
+# add LoRA to model
+lora_config = LoraConfig(
+ r=16,
+ lora_alpha=32,
+ lora_dropout=0.05,
+ bias="none",
+ task_type="CAUSAL_LM",
+)
+
+model = get_peft_model(model, config)
+```
+
+我们根据相应的语言任务,对模型训练几千个 step (步),并保存模型。由于我们将会有其他微调模型的目的,我们将 LoRA 的微调器权重合并到原模型中。
+
+
+ **声明**: 因为 LLaMA 的许可证规定,我们只能发布微调器的权重,你需要填 Meta AI 的 [表格](https://docs.google.com/forms/d/e/1FAIpQLSfqNECQnMkycAp2jP4Z9TFX0cGR4uf7b_fBxjY_OjhJILlKGA/viewform) 来获取模型,然后用这个 [脚本](https://github.com/huggingface/transformers/blob/main/src/transformers/models/llama/convert_llama_weights_to_hf.py) 来转成 🤗 Transformers 格式。注意 🤗 Transformers 应该从源码安装,或者 `v4.28` 版。
+
+现在我们已经微调好了模型,可以训练奖励模型了。
+
+## 奖励模型和人类偏好
+
+原则上,我们可以直接用人类标注来对模型做 RLHF 微调。然而,这将需要我们给人类发送一些样本,在每轮优化后计分。这是贵且慢的,因为收敛需要的训练样本量大,而人类阅读和标注的速度有限。
+
+一个比直接反馈更好的策略是,在进入 RL 循环之前用人类标注集来训练一个奖励模型。奖励模型的目的是模拟人类对文本的打分。构建奖励模型有许多能用的策略: 最直接的便是预测标注 (比如根据好与坏,输出比分或者布尔值)。最佳实践是,预测结果的排序,即对每个 prompt (输入文本) 对应的两个结果 $(y_k, y_j)$,模型预测人类标注的比分哪个更高。
+
+或者表示为 loss (损失) 函数:
+
+$$
+\mbox{loss}(\theta) = - E_{(x, y_j, y_k)~D} [ \mbox{log}( \sigma( r_\theta (x, y_j) - r_\theta(x, y_k)) ) ]
+$$
+
+其中 $r$ 是模型对可能的标注 $y_j$ 的预测分数。
+
+在 StackExchange 数据集上,我们能得到两个答案的受欢迎程度。有了这个信息和上面的损失函数,我们就能自定义 loss 来改 `transformers.Trainer` 了。
+
+```python
+
+class RewardTrainer(Trainer):
+ def compute_loss(self, model, inputs, return_outputs=False):
+ rewards_j = model(input_ids=inputs["input_ids_j"], attention_mask=inputs["attention_mask_j"])[0]
+ rewards_k = model(input_ids=inputs["input_ids_k"], attention_mask=inputs["attention_mask_k"])[0]
+ loss = -nn.functional.logsigmoid(rewards_j - rewards_k).mean()
+ if return_outputs:
+ return loss, {"rewards_j": rewards_j, "rewards_k": rewards_k}
+ return loss
+```
+
+我们用数据集中的 100000 对,并在 50000 对上评估。在比较小的 batch size,为 4 下,我们用 LoRA 的 `peft` 微调器来训练 LLaMA 模型,在 BF16 精度下用 Adam 优化器。我们的 LoRA 设置是:
+
+```python
+peft_config = LoraConfig(
+ task_type=TaskType.SEQ_CLS,
+ inference_mode=False,
+ r=8,
+ lora_alpha=32,
+ lora_dropout=0.1,
+)
+```
+
+训练用 [Weights & Biases](https://wandb.ai/krasul/huggingface/runs/wmd8rvq6?workspace=user-krasul) 来记日志,并在 🤗 训练集群上,用 8 卡 A-100,要数小时,最后准确率为 **67%**。尽管看上去可能低了,但想想这个任务的难度。
+
+如下文要细说的,训练结果将作为固定参数,以供下游使用。
+
+## 基于人类反馈的强化学习
+
+现在我们手头有了微调的语言模型和奖励模型,可以开始执行 RL 循环了: 这个过程大致分为三步
+
+1. 生成对 prompt (输入文本) 的反馈。
+2. 用奖励模型来对反馈评分。
+3. 对评分,进行一轮策略优化的强化学习。
+
+![](https://huggingface.co/datasets/trl-internal-testing/example-images/resolve/main/blog/stackllama/trl_loop.png)
+
+在被 token 化并输入奖励模型前,提问和回答的 prompt 模版如下:
+
+```
+Question:
+Answer:
+```
+
+在有监督训练 (SFT),奖励模型训练 (RM) 和 RLHF 的阶段都用此模版。
+
+用 RL 训练语言模型出现的常见问题是,模型可能学会胡说八道以糊弄奖励模型,后者可能给高分。为了权衡,我们对奖励增加惩罚: 留一份没有训练的模型,如何比较两者输出的 KL 散度
+
+$$
+\mbox{R}(x, y) = \mbox{r}(x, y) - \beta \mbox{KL}(x,y)
+$$
+
+其中 $r$ 是奖励模型的结果,$\mbox{KL}(x,y)$ 是当前模型和对比模型的 KL 散度差。
+
+再提一遍,我们用 `peft` 来实现内存高效的训练,其对 RLHF 阶段提供了优势。这里参考的模型和训练的模型用同一个基底,也就是有监督训练 (SFT) 的结果,它是用 8-bit 来加载,并且自始自终是固定的。我们仅用 PPO 方法优化最终模型的 LoRA 权重,同时全部共享一个基底模型。
+
+```python
+for epoch, batch in tqdm(enumerate(ppo_trainer.dataloader)):
+ question_tensors = batch["input_ids"]
+
+ # sample from the policy and generate responses
+ response_tensors = ppo_trainer.generate(
+ question_tensors,
+ return_prompt=False,
+ length_sampler=output_length_sampler,
+ **generation_kwargs,
+ )
+ batch["response"] = tokenizer.batch_decode(response_tensors, skip_special_tokens=True)
+
+ # Compute sentiment score
+ texts = [q + r for q, r in zip(batch["query"], batch["response"])]
+ pipe_outputs = sentiment_pipe(texts, **sent_kwargs)
+ rewards = [torch.tensor(output[0]["score"] - script_args.reward_baseline) for output in pipe_outputs]
+
+ # Run PPO step
+ stats = ppo_trainer.step(question_tensors, response_tensors, rewards)
+ # Log stats to WandB
+ ppo_trainer.log_stats(stats, batch, rewards)
+```
+
+我们用 🤗 集群,在 3x8 A100-80GB 的机器上训练了 20h,但一个差不多的结果很快 (大概,在 8 A100-80GB 上训练 20h)。所有的训练过程都在 [Weight & Biases](https://wandb.ai/lvwerra/trl/runs/ie2h4q8p) 上找到。
+
+![](https://huggingface.co/datasets/trl-internal-testing/example-images/resolve/main/blog/stackllama/wandb_reward.png)
+
+每个 batch 的奖励,对每步的训练,在 ~1000 步时模型的效果最好。
+
+所以模型训好了能干啥嘞 ? 我们拭目以待 !
+
+![](https://huggingface.co/datasets/trl-internal-testing/example-images/resolve/main/blog/stackllama/llama_prompt.png)
+
+尽管我们不该太相信其结果,至少目前。但结果已经很好了,甚至附上了 Google 链接。我们来看看训练时的挑战。
+
+## 挑战,不稳定和突破口
+
+用 RL 训练 LLM (Large Language Models,大语言模型) 不总是一帆风顺的,你看到的本文也是经历无数实验,无数失败和无数调参的。即便如此,该模型也不能说变现完美。这儿,我们分享一些遇到的观察和问题。
+
+### 奖励更高代表更好表现 ?
+
+![](https://huggingface.co/datasets/trl-internal-testing/example-images/resolve/main/blog/stackllama/logs_high_reward.png)
+
+天呐,这个实验肯定表现很好 ! 看奖励的曲线多甜啊 !
+
+在 RL 中,一般而言,奖励越高越好。在 RLHF 中,我们用了一个奖励模型,它不完美,所以留给了 PPO 算法捡漏的机会。这能导致奖励突然上升,然而当检查文本结果时,却充斥了字符 “```”,因为奖励模型对含有代码 stack exchange 的答案更信任。幸运的是,该问题碰到的很少,应该是采取的 KL 散度的惩罚项起到了作用。
+
+### KL 散度总是正的?
+
+如我们前面所提到的,一个 KL 惩罚项被用来保证训练后的分布和原始分布接近。一般地 , KL 散度来度量两个分布的相似程度,并且总是正的。然而,在 `trl` 我们用了一个 KL 的近似,期望值和真的 KL 散度相同。
+
+$$
+KL_{pen} (x, y) = \mbox{log} (\pi_\phi^\mbox{RL}(y | x) / \pi^{\mbox{SFT}}(y|x))
+$$
+
+显然,当训练中一个 token 比原始模型概率低,这会导致 KL 散度为负,合适的取样和平均总能得到正的。但是一些采样的生成策略导致了不匀称的采样。比如,当生成被 padding 的序列 batch 时和当设置 EOS token 被压缩的最小长度是,模型会有很大/很小的概率到负 KL 散度的 token。同时 PPO 算法是面向奖励优化的,模型就会追逐负的惩罚,导致训练不稳定。
+
+![](https://huggingface.co/datasets/trl-internal-testing/example-images/resolve/main/blog/stackllama/logs_neg_kl.png)
+
+对生成和采样,你需要特别小心。我们建议一开始用最简单的方式,如何在逐渐复杂。
+
+### 任然存在的问题
+
+任然有很多问题我们不懂,比如下面,loss 间断地跳跃,导致之后的不稳定
+
+![](https://huggingface.co/datasets/trl-internal-testing/example-images/resolve/main/blog/stackllama/logs_loss_spikes.png)
+
+一旦我们解决了这些问题,我们就会上传变化到 `trl` 上,以保证社区受益。
+
+## 总结
+
+在本博客,我们走过了 RLHF 训练的整个流程,从准备人类标注的数据集开始,调整语言模型到特定领域,训练奖励模型,并最终用 RL 训练一个模型。
+
+通过使用 `peft`,任何人都能在一张 GPU 上跑我们的实验 ! 如果训练慢了,可以用数据并行化的方法,不需要改任何代码,或者用多张 GPU 并行提高训练速度。
+
+对实际应用,这仅仅是第一步 ! 一旦你有了模型,你就要和其他模型比较优劣。这个可以用一个面向不同模型的排名生成做到,和我们训练奖励数据集类似。
+
+一旦你加入了评估的步骤,好玩的就开始了: 你可以在原数据集上反复炼丹,也可以增加数据集或者对原数据集提纯。另外,你可以对奖励模型和生成试不同大小和结构的模型,这需要时间。
+
+我们在积极提高 TRL 以保证 RLHF 的每一步都可见,并且十分激动能看到人们用它来构建的东西。如果你想有所贡献,欢迎看我们的 [Github Issue](https://github.com/lvwerra/trl/issues)。
+
+## 引用
+
+```
+@misc {beeching2023stackllama,
+ author = { Edward Beeching and
+ Younes Belkada and
+ Kashif Rasul and
+ Lewis Tunstall and
+ Leandro von Werra and
+ Nazneen Rajani and
+ Nathan Lambert
+ },
+ title = { StackLLaMA: An RL Fine-tuned LLaMA Model for Stack Exchange Question and Answering },
+ year = 2023,
+ url = { https://huggingface.co/blog/stackllama },
+ doi = { 10.57967/hf/0513 },
+ publisher = { Hugging Face Blog }
+}
+```
+
+## 感谢
+
+我们感谢 Philipp Schmid 分享了他对文本生成绝妙的 [demo](https://huggingface.co/spaces/philschmid/igel-playground), 我们的 demo 也是基于他的。我们也感谢 Omar Sanseviero 和 Louis Castricato 对我们博客的草稿提供宝贵详尽的反馈。
\ No newline at end of file
From 1e9297337f786d70c0382257fc8bbb877a9fa5e8 Mon Sep 17 00:00:00 2001
From: SuSung-boy <872414318@qq.com>
Date: Thu, 4 May 2023 17:44:36 +0800
Subject: [PATCH 16/55] if blog translation completed
---
zh/if.md | 826 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 826 insertions(+)
create mode 100644 zh/if.md
diff --git a/zh/if.md b/zh/if.md
new file mode 100644
index 0000000000..1c900bba7a
--- /dev/null
+++ b/zh/if.md
@@ -0,0 +1,826 @@
+---
+title: "在免费版 Google Colab 上使用 🧨 diffusers 运行 IF"
+thumbnail: /blog/assets/if/thumbnail.jpg
+authors:
+- user: shonenkov
+ guest: true
+- user: Gugutse
+ guest: true
+- user: ZeroShot-AI
+ guest: true
+- user: williamberman
+- user: patrickvonplaten
+- user: multimodalart
+translators:
+- user: SuSung-boy
+---
+
+# 在免费版 Google Colab 上使用 🧨 diffusers 运行 IF
+
+
+
+
+
+
+
+
+**本文简介**: 本文展示了如何在免费版 Google Colab 上使用 🧨 diffusers 运行最强大的开源文本生成图片模型之一 **IF**。
+
+您也可以直接访问 IF 的 [Hugging Face Space](https://huggingface.co/spaces/DeepFloyd/IF) 页面来探索模型强大的性能。
+
+
+
+ 压缩的生成图片样例,选自官方 IF GitHub 库
+
+
+## 介绍
+
+IF 是一类像素级的文生图模型,由 [DeepFloyd](https://github.com/deep-floyd/IF) 于 2023 年 4 月下旬发布。IF 的模型架构受 Google 的闭源模型 [Imagen](https://imagen.research.google/) 的强烈启发。
+
+与现有的文本生成图片模型(如 Stable Diffusion)相比,IF 有两个明显的优势:
+
+- IF 模型直接在 “像素空间”(即未降维、未压缩的图片)中计算生成,而非需要迭代去噪的隐空间(如 [Stable Diffusion](http://hf.co/blog/stable_diffusion))。
+- IF 模型基于 [T5-XXL](https://huggingface.co/google/t5-v1_1-xxl) 文本编码器的输出进行训练。T5-XXL 是一个比 Stable DIffusion 中的 [CLIP](https://openai.com/research/clip) 更强大的文本编码器。
+
+因此,IF 更擅长生成具有高频细节(例如人脸和手部)的图片,并且 IF 是 **第一个能够在图片中生成可靠文字** 的开源图片生成模型。
+
+不过,在具有上述两个优势(像素空间计算、使用更优文本编码器)的同时,IF 模型也存在明显的不足,那就是参数量更加庞大。IF 模型的文本编码器 T5、文本生成图片网络 UNet、超分辨率模型 upscaler UNet 的参数量分别为 4.5B、4.3B、1.2B,而 [Stable Diffusion v2.1](https://huggingface.co/stabilityai/stable-diffusion-2-1) 模型的文本编码器 CLIP 和去噪网络 UNet 的参数量仅为 400M 和 900M。
+
+尽管如此,我们仍然可以在消费级 GPU 上运行 IF 模型,不过这需要一些优化技巧来降低显存占用。不用担心,我们将在本篇博客中详细介绍如何使用 🧨 diffusers 库来实现这些技巧。
+
+在本文后面的 1.) 中,我们将介绍如何使用 IF 模型进行文本生成图片;在 2.) 和 3.) 中,我们将介绍 IF 模型的 Img2Img 和 Inpainting (图片修复) 能力。
+
+💡 **注意**:本文为保证 IF 模型可以在免费版 Google Colab 上成功运行,采用了多模型组件顺序在 GPU 上加载卸载的技巧,以放慢生成速度为代价换取显存占用降低。如果您有条件使用更高端的 GPU 如 A100,我们建议您把所有的模型组件都加载并保留在 GPU 上,以获得最快的图片生成速度,代码详情见 [IF 的官方示例](https://huggingface.co/spaces/DeepFloyd/IF)。
+
+💡 **注意**:本文为保证读者在阅读时图片加载得更快,对文中的一些高分辨率图片进行了压缩。在您自行使用官方模型尝试生成时,图片质量将会更高!
+
+让我们开始 IF 之旅吧!🚀
+
+
+
+ IF 模型生成含文字的图片的强大能力
+
+
+## 本文目录
+
+* [接受许可证](#接受许可证)
+* [优化 IF 模型以在有限的硬件条件下运行](#优化-if-模型以在有限的硬件条件下运行)
+* [可用资源](#可用资源)
+* [安装依赖](#安装依赖)
+* [文本生成图片](#1-文本生成图片)
+* [Img2Img](#2-img2img)
+* [Inpainting](#3-inpainting)
+
+## 接受许可证
+
+在您使用 IF 模型之前,您需要接受它的使用条件。 为此:
+
+- 1. 确保已开通 [Hugging Face 帐户](https://huggingface.co/join) 并登录
+- 2. 接受 [DeepFloyd/IF-I-XL-v1.0](https://huggingface.co/DeepFloyd/IF-I-XL-v1.0) 模型卡的许可证。在 Stage1 模型卡上接受许可证会自动接受其他 IF 模型许可证。
+- 3. 确保在本地已安装 `huggingface_hub` 库并登录
+
+```sh
+pip install huggingface_hub --upgrade
+```
+
+在 Python shell 中运行登录函数
+
+```py
+from huggingface_hub import login
+
+login()
+```
+
+输入您的 [Hugging Face Hub 访问令牌](https://huggingface.co/docs/hub/security-tokens#what-are-user-access-tokens)。
+
+## 优化 IF 模型以在有限的硬件条件下运行
+
+**最先进的机器学习技术不应该只掌握在少数精英手里。** 要使机器学习更 “普罗大众” 就意味着模型能够在消费级硬件上运行,而不是仅支持在最新型最高端的硬件上运行。
+
+深度学习开放社区创造了众多世界一流的工具,来支持在消费级硬件上运行资源密集型模型。例如:
+
+- [🤗 accelerate](https://github.com/huggingface/accelerate) 提供用于处理 [大模型](https://huggingface.co/docs/accelerate/usage_guides/big_modeling) 的实用工具。
+- [🤗 safetensors](https://github.com/huggingface/safetensors) 在保证模型保存的安全性的同时,还能显著加快大模型的加载速度。
+- [bitsandbytes](https://github.com/TimDettmers/bitsandbytes) 使所有的 PyTorch 模型都可以采用 8 位量化。
+
+Diffusers 库无缝集成了上述库,只需调用一个简单的 API 即可实现大模型的优化。
+
+免费版 Google Colab 既受 CPU RAM 限制(13GB RAM),又受 GPU VRAM 限制(免费版 T4 为 15GB RAM),无法直接运行整个 IF 模型(>10B)。
+
+我们先来看看运行完整 float32 精度的 IF 模型时,各个组件所需的内存占用:
+
+- [T5-XXL 文本编码器](https://huggingface.co/DeepFloyd/IF-I-XL-v1.0/tree/main/text_encoder): 20GB
+- [Stage1 UNet](https://huggingface.co/DeepFloyd/IF-I-XL-v1.0/tree/main/unet): 17.2GB
+- [Stage2 超分辨率 UNet](https://huggingface.co/DeepFloyd/IF-II-L-v1.0/blob/main/pytorch_model.bin): 2.5 GB
+- [Stage 3 x4-upscaler 超分辨率模型](https://huggingface.co/stabilityai/stable-diffusion-x4-upscaler): 3.4GB
+
+可见我们无法以 float32 精度运行 IF 模型,因为 T5 和 Stage1 UNet 权重所需的内存占用均超出了免费版 CPU RAM 的可用范围。
+
+很容易想到,我们可以通过降低模型运行的位精度来减少内存占用。如果以 float16 精度来运行 IF 模型,则 T5、Stage1 UNet、Stage2 UNet 所需的内存占用分别下降至 11GB、8.6GB、1.25GB。对于免费版 GPU 的 15GB RAM 限制,float16 精度已经满足运行条件,不过在实际加载 T5 模型时,我们很可能仍然会遇到 CPU 内存溢出错误,因为 CPU 的一部分内存会被其他进程占用。
+
+因此我们继续降低位精度,实际上仅降低 T5 的精度就可以了。这里我们使用 `bitsandbytes` 库将 T5 量化到 8 位精度,最终可以将 T5 权重的内存占用降低至 [8GB](https://huggingface.co/DeepFloyd/IF-I-XL-v1.0/blob/main/text_encoder/model.8bit.safetensors)。
+
+好了,现在 IF 模型的每个组件的 CPU 和 GPU 内存占用都各自符合免费版 Google Colab 的限制,接下来我们只需要确保在运行每个组件的时候,CPU 和 GPU 内存不会被其他组件或者进程占用就可以了。
+
+Diffusers 库支持模块化地独立加载单个组件,也就是说我们可以只加载文本编码器 T5,而不加载文本生成图片模型 UNet,反之亦然。这种模块化加载的技巧可以确保在运行多个组件的管线时,每个组件仅在需要计算时才被加载,可以有效避免同时加载时导致的 CPU 和 GPU 内存溢出。
+
+来实操代码试一试吧!🚀
+
+![t2i_64](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/if/t2i_64.png)
+
+## 可用资源
+
+免费版 Google Colab 的 CPU RAM 可用资源约 13GB:
+
+``` python
+!grep MemTotal /proc/meminfo
+```
+
+```bash
+MemTotal: 13297192 kB
+```
+
+免费版 GPU 型号为 NVIDIA T4,其 VRAM 可用资源约 15GB:
+
+``` python
+!nvidia-smi
+```
+
+```bash
+Sun Apr 23 23:14:19 2023
++-----------------------------------------------------------------------------+
+| NVIDIA-SMI 525.85.12 Driver Version: 525.85.12 CUDA Version: 12.0 |
+|-------------------------------+----------------------+----------------------+
+| GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC |
+| Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. |
+| | | MIG M. |
+|===============================+======================+======================|
+| 0 Tesla T4 Off | 00000000:00:04.0 Off | 0 |
+| N/A 72C P0 32W / 70W | 1335MiB / 15360MiB | 0% Default |
+| | | N/A |
++-------------------------------+----------------------+----------------------+
+
++-----------------------------------------------------------------------------+
+| Processes: |
+| GPU GI CI PID Type Process name GPU Memory |
+| ID ID Usage |
+|=============================================================================|
++-----------------------------------------------------------------------------+
+```
+
+## 安装依赖
+
+本文使用的优化技巧需要安装最新版本的依赖项。如果您在运行代码时遇到问题,请首先仔细检查依赖项的安装版本。
+
+``` python
+! pip install --upgrade \
+ diffusers~=0.16 \
+ transformers~=4.28 \
+ safetensors~=0.3 \
+ sentencepiece~=0.1 \
+ accelerate~=0.18 \
+ bitsandbytes~=0.38 \
+ torch~=2.0 -q
+```
+
+## 1. 文本生成图片
+
+这一部分我们将分步介绍如何使用 Diffusers 运行 IF 模型来完成文本到图片的生成。对于接下来使用的 API 和优化技巧,文中仅作简要的解释,如果您想深入了解更多原理或者细节,可以前往 [Diffusers](https://huggingface.co/docs/diffusers/index),[Transformers](https://huggingface.co/docs/transformers/index),[Accelerate](https://huggingface.co/docs/accelerate/index),以及 [bitsandbytes](https://github.com/TimDettmers/bitsandbytes) 的官方文档查看。
+
+### 1.1 加载文本编码器
+
+首先我们使用 Transformers 库加载 8 位量化后的文本编码器 T5。Transformers 库直接支持 [bitsandbytes](https://huggingface.co/docs/transformers/main/en/main_classes/quantization#load-a-large-model-in-8bit) 量化,可以通过 `load_in_8bit` 参数来标识是否加载 8 位量化模型。
+
+设置参数 `variant="8bit"` 来下载预量化版的权重。
+
+Transformers 还支持模块化地独立加载单个模型的某些层!`device_map` 参数可以指定单个模型的权重在不同 GPU 设备上加载或者卸载的映射策略,在不需要参与计算时甚至可以卸载到 CPU 或者磁盘上。这里我们设置 `device_map` 参数为 `"auto"`,让 transformers 库自动创建设备映射。更多相关信息,请查看 [transformers 文档](https://huggingface.co/docs/accelerate/usage_guides/big_modeling#designing-a-device-map)。
+
+``` python
+from transformers import T5EncoderModel
+
+text_encoder = T5EncoderModel.from_pretrained(
+ "DeepFloyd/IF-I-XL-v1.0",
+ subfolder="text_encoder",
+ device_map="auto",
+ load_in_8bit=True,
+ variant="8bit"
+)
+```
+
+### 1.2 创建 prompt embeddings
+
+Diffusers API 中的 `DiffusionPipeline` 类及其子类专门用于访问扩散模型。`DiffusionPipeline` 中的每个实例都包含一套独立的方法和默认的模型。我们可以通过 `from_pretrained` 方法来覆盖默认实例中的模型,只需将目标模型实例作为关键字参数传给 `from_pretrained`。
+
+上文说过,我们在加载文本编码器 T5 的时候无需加载扩散模型组件 UNet,因此这里我们需要用 `None` 来覆盖 `DiffusionPipeline` 的实例中的 UNet 部分,此时将 `from_pretrained` 方法的 `unet` 参数设为 `None` 即可实现。
+
+``` python
+from diffusers import DiffusionPipeline
+
+pipe = DiffusionPipeline.from_pretrained(
+ "DeepFloyd/IF-I-XL-v1.0",
+ text_encoder=text_encoder, # 传入前面加载的 8 位量化文本编码器实例
+ unet=None,
+ device_map="auto"
+)
+```
+
+IF 模型还有一个超分辨率管线。为了后面能够方便地加载运行,我们这里把 prompt embeddings 保存下来,后面就可以直接输入给超分辨率管线,而不需要再经过文本编码器了。
+
+接下来就可以开始输入 prompt 了。为了凸显 IF 模型能够生成带文字的图片的优势,这里要在 Stable Diffusion 中生成 [宇航员骑马](https://huggingface.co/blog/stable_diffusion) (an astronaut just riding a
+horse) 的图片示例的基础上, 增加一个带有文字的指示牌!
+
+我们给出一个合适的 prompt:
+
+``` python
+prompt = "a photograph of an astronaut riding a horse holding a sign that says Pixel's in space"
+```
+
+然后输入给 8 位量化的 T5 模型,生成 prompt 的 embeddings:
+
+``` python
+prompt_embeds, negative_embeds = pipe.encode_prompt(prompt)
+```
+
+### 1.3 释放内存
+
+当 prompt embeddings 创建完成之后,我们就不再需要文本编码器了。但目前 T5 仍然存在于 GPU 内存中,因此我们需要释放 T5 占用的内存,以便加载 UNet。
+
+释放 PyTorch 内存并非易事。我们必须对所有指向实际分配到 GPU 上的 Python 对象实施垃圾回收。
+
+为此,我们首先使用 Python 关键字 `del` 来删除掉所有引用的已分配到 GPU 内存上的 Python 对象。
+
+``` python
+del text_encoder
+del pipe
+```
+
+不过仅删除 Python 对象仍然不够,因为垃圾回收机制实际上是在释放 GPU 完成之后才完成的。
+
+然后,我们调用 `torch.cuda.empty_cache()` 方法来释放缓存。实际上该方法也并非绝对必要,因为缓存中的 cuda 内存也能够立即用于进一步分配,不过它可以帮我们在 Colab UI 中验证是否有足够的内存可用。
+
+这里我们编写一个辅助函数 `flush()` 来刷新内存。
+
+``` python
+import gc
+import torch
+
+def flush():
+ gc.collect()
+ torch.cuda.empty_cache()
+```
+
+运行 `flush()`。
+
+``` python
+flush()
+```
+
+### 1.4 Stage1:核心扩散过程
+
+好了,现在已经有足够的 GPU 内存可用,我们就能重新加载一个只包含 UNet 部分的 `DiffusionPipeline` 了,因为接下来我们只需要运行核心扩散过程部分。
+
+按照上文中对 UNet 内存占用的计算,IF 模型的 UNet 部分权重能够以 float16 精度加载,设置 `variant` 和 `torch_dtype` 参数即可实现。
+
+``` python
+pipe = DiffusionPipeline.from_pretrained(
+ "DeepFloyd/IF-I-XL-v1.0",
+ text_encoder=None,
+ variant="fp16",
+ torch_dtype=torch.float16,
+ device_map="auto"
+)
+```
+
+一般情况下,我们会直接将 prompt 传入 `DiffusionPipeline.__call__` 函数。不过我们这里已经计算出了 prompt embeddings,因此只需传入 embeddings 即可。
+
+Stage1 的 UNet 接收 embeddings 作为输入运行完成后,我们还需要继续运行 Stage2 的超分辨率组件,因此我们需要保存模型的原始输出 (即 PyTorch tensors) 来输入到 Stage2,而不是 PIL 图片。这里设置参数 `output_type="pt"` 可以将 Stage1 输出的 PyTorch tensors 保留在 GPU 上。
+
+我们来定义一个随机生成器,并运行 Stage1 的扩散过程。
+
+``` python
+generator = torch.Generator().manual_seed(1)
+image = pipe(
+ prompt_embeds=prompt_embeds,
+ negative_prompt_embeds=negative_embeds,
+ output_type="pt",
+ generator=generator,
+).images
+```
+
+虽然运行结果是原始的 PyTorch tensors,我们仍然可以手动将其转换为 PIL 图片,起码先瞧一瞧生成图片的大概样子嘛。Stage1 的输出可以转换为一张 64x64 的图片。
+
+``` python
+from diffusers.utils import pt_to_pil
+
+pil_image = pt_to_pil(image)
+pipe.watermarker.apply_watermark(pil_image, pipe.unet.config.sample_size)
+
+pil_image[0]
+```
+
+![t2i_64](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/if/t2i_64.png)
+
+Stage1 完成之后,我们同样删除 Python 指针,释放 CPU 和 GPU 内存。
+
+``` python
+del pipe
+flush()
+```
+
+### 1.5 Stage2:超分辨率 64x64 到 256x256
+
+IF 模型包含多个独立的超分辨率组件。
+
+对于每个超分辨率扩散过程组件,我们都使用单独的管线来运行。
+
+在加载超分辨率管线时需要传入文本参数。如果需要,它也是可以同时加载文本编码器,来从 prompt 开始运行的。不过更一般的做法是从第一个 IF 管线中计算得到的 prompt embeddings 开始,此时要把 `text_encoder` 参数设为 `None`。
+
+创建一个超分辨率 UNet 管线。
+
+``` python
+pipe = DiffusionPipeline.from_pretrained(
+ "DeepFloyd/IF-II-L-v1.0",
+ text_encoder=None, # 未用到文本编码器 => 节省内存!
+ variant="fp16",
+ torch_dtype=torch.float16,
+ device_map="auto"
+)
+```
+
+将 Stage1 输出的 Pytorch tensors 和 T5 输出的 embeddings 输入给 Stage2 并运行。
+
+``` python
+image = pipe(
+ image=image,
+ prompt_embeds=prompt_embeds,
+ negative_prompt_embeds=negative_embeds,
+ output_type="pt",
+ generator=generator,
+).images
+```
+
+我们同样可以转换为 PIL 图片来查看中间结果。
+
+``` python
+pil_image = pt_to_pil(image)
+pipe.watermarker.apply_watermark(pil_image, pipe.unet.config.sample_size)
+
+pil_image[0]
+```
+
+![t2i_upscaled](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/if/t2i_upscaled.png)
+
+再一次,删除 Python 指针,释放内存。
+
+``` python
+del pipe
+flush()
+```
+
+### 1.6 Stage3:超分辨率 256x256 到 1024x1024
+
+IF 模型的第 2 个超分辨率组件是 Stability AI 之前发布的 [x4 Upscaler](https://huggingface.co/stabilityai/stable-diffusion-x4-upscaler)。
+
+我们创建相应的管线,并设置参数 `device_map="auto"` 直接加载到 GPU 上。
+
+``` python
+pipe = DiffusionPipeline.from_pretrained(
+ "stabilityai/stable-diffusion-x4-upscaler",
+ torch_dtype=torch.float16,
+ device_map="auto"
+)
+```
+
+🧨 diffusers 可以使得独立开发的扩散模型非常简便地组合使用,因为 diffusers 中的管线可以链接在一起。比如这里我们可以设置参数 `image=image` 来将先前输出的 PyTorch tensors 输入给 Stage3 管线。
+
+💡 **注意**:x4 Upscaler 并非使用 T5,而使用它 [自己的文本编码器](https://huggingface.co/stabilityai/stable-diffusion-x4-upscaler/tree/main/text_encoder)。因此,我们不能使用 1.2 中创建的 prompt embeddings,必须传入原始 prompt。
+
+``` python
+pil_image = pipe(prompt, generator=generator, image=image).images
+```
+
+IF 模型管线在生成图片时默认会在右下角添加 IF 水印。由于 Stage3 使用的 x4 upscaler 管线并非属于 IF (实际上属于 Stable Diffusion),因此经过超分辨率生成的图片也不会带有 IF 水印。
+
+不过我们可以手动添加水印。
+
+``` python
+from diffusers.pipelines.deepfloyd_if import IFWatermarker
+
+watermarker = IFWatermarker.from_pretrained("DeepFloyd/IF-I-XL-v1.0", subfolder="watermarker")
+watermarker.apply_watermark(pil_image, pipe.unet.config.sample_size)
+```
+
+查看 Stage3 的输出图片。
+
+``` python
+pil_image[0]
+```
+
+![t2i_upscaled_2](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/if/t2i_upscaled_2.png)
+
+看!免费版 Google Colab 上运行 IF 模型生成精美的 1024x1024 图片了!
+
+至此,我们已经展示了使用 🧨 diffusers 来分解和模块化加载资源密集型扩散模型的全部内容,是不是非常简单!
+
+💡 **注意**:我们不建议在生产流程中使用上述以放慢推理速度为代价来换取低内存消耗的设置:8 位量化、模型权重的解耦和重分配、磁盘卸载等,尤其是需要重复使用某个扩散模型组件的时候。在实际生产中,我们还是建议您使用 40GB VRAM 的 A100,以确保所有的模型组件可以同时加载到 GPU 上。如果您条件满足,可以参考 Hugging Face 上的 [**官方 IF 示例**](https://huggingface.co/spaces/DeepFloyd/IF) 设置。
+
+## 2. Img2Img
+
+在 1.) 中加载的文本生成图片的 IF 模型各个组件的预训练权重,也同样可用于文本引导的图片生成图片,也叫 Img2Img,还能用于 Inpainting (图片修复),我们将在 3.) 中介绍。Img2Img 和 Inpainting 的核心扩散过程,除了初始噪声是图片之外,其余均与文本生成图片的扩散过程相同。
+
+这里我们创建 Img2Img 管线 `IFImg2ImgPipeline` 和超分辨率管线
+`IFImg2ImgSuperResolution`,并加载和 1.) 中各个组件相同的预训练权重。
+
+内存优化的 API 也都相同!
+
+同样地释放内存。
+
+``` python
+del pipe
+flush()
+```
+
+对于 Img2Img,我们需要一张初始图片。
+
+这一部分,我们将使用在外网著名的 “Slaps Roof of Car” meme (可以理解为汽车推销员表情包制作模板)。首先从网上下载这张图片。
+
+``` python
+import requests
+
+url = "https://i.kym-cdn.com/entries/icons/original/000/026/561/car.jpg"
+response = requests.get(url)
+```
+
+然后使用 PIL 图像库加载图片。
+
+``` python
+from PIL import Image
+from io import BytesIO
+
+original_image = Image.open(BytesIO(response.content)).convert("RGB")
+original_image = original_image.resize((768, 512))
+original_image
+```
+
+![iv_sample](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/if/iv_sample.png)
+
+Img2Img 管线可以接收 PIL 图像对象或原始 tensors 对象作为输入。点击 [此处](https://huggingface.co/docs/diffusers/v0.16.0/en/api/pipelines/if#diffusers.IFImg2ImgPipeline.__call__) 可跳转文档页面查看更详细的输入参数说明。
+
+### 2.1 文本编码器
+
+Img2Img 可以由文本引导。这里我们也尝试给出一个合适的 prompt 并使用文本编码器 T5 创建其 embeddings。
+
+首先再次加载 8 位量化的文本编码器。
+
+``` python
+from transformers import T5EncoderModel
+
+text_encoder = T5EncoderModel.from_pretrained(
+ "DeepFloyd/IF-I-XL-v1.0",
+ subfolder="text_encoder",
+ device_map="auto",
+ load_in_8bit=True,
+ variant="8bit"
+)
+```
+
+对于 Img2Img,我们需要使用 [`IFImg2ImgPipeline`](https://huggingface.co/docs/diffusers/v0.16.0/en/api/pipelines/if#diffusers.IFImg2ImgPipeline) 类来加载预训练权重,而不能使用 1.) 中的 `DiffusionPipeline` 类。这是因为当使用 `from_pretrained()` 方法加载 IF 模型(或其他扩散模型)的预训练权重时,会返回 **默认的文本生成图片** 管线 [`IFPipeline`](https://huggingface.co/docs/diffusers/v0.16.0/en/api/pipelines/if#diffusers.IFPipeline)。因此,要加载 Img2Img 或 Depth2Img 等非默认形式的管线,必须指定明确的类名。
+
+``` python
+from diffusers import IFImg2ImgPipeline
+
+pipe = IFImg2ImgPipeline.from_pretrained(
+ "DeepFloyd/IF-I-XL-v1.0",
+ text_encoder=text_encoder,
+ unet=None,
+ device_map="auto"
+)
+```
+
+我们来把汽车推销员变得动漫风一些,对应的 prompt 为:
+
+``` python
+prompt = "anime style"
+```
+
+同样地,使用 T5 来创建 prompt embeddings。
+
+``` python
+prompt_embeds, negative_embeds = pipe.encode_prompt(prompt)
+```
+
+释放 CPU 和 GPU 内存。
+
+同样先删除 Python 指针,
+
+``` python
+del text_encoder
+del pipe
+```
+
+再刷新内存。
+
+``` python
+flush()
+```
+
+### 2.2 Stage1:核心扩散过程
+
+接下来也是一样,我们在管线中只加载 Stage1 UNet 部分权重。
+
+``` python
+pipe = IFImg2ImgPipeline.from_pretrained(
+ "DeepFloyd/IF-I-XL-v1.0",
+ text_encoder=None,
+ variant="fp16",
+ torch_dtype=torch.float16,
+ device_map="auto"
+)
+```
+
+运行 Img2Img Stage1 管线需要原始图片和 prompt embeddings 作为输入。
+
+我们可以选择使用 `strength` 参数来配置 Img2Img 的变化程度。`strength` 参数直接控制了添加的噪声强度,该值越高,生成图片偏离原始图片的程度就越大。
+
+``` python
+generator = torch.Generator().manual_seed(0)
+image = pipe(
+ image=original_image,
+ prompt_embeds=prompt_embeds,
+ negative_prompt_embeds=negative_embeds,
+ output_type="pt",
+ generator=generator,
+).images
+```
+
+我们再次查看一下生成的 64x64 图片。
+
+``` python
+pil_image = pt_to_pil(image)
+pipe.watermarker.apply_watermark(pil_image, pipe.unet.config.sample_size)
+
+pil_image[0]
+```
+
+![iv_sample_1](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/if/iv_sample_1.png)
+
+看起来不错!我们可以继续释放内存,并进行超分辨率放大图片了。
+
+``` python
+del pipe
+flush()
+```
+
+### 2.3 Stage2: 超分辨率
+
+对于超分辨率,我们使用 `IFImg2ImgSuperResolutionPipeline` 类,并加载与 1.5 中相同的预训练权重。
+
+``` python
+from diffusers import IFImg2ImgSuperResolutionPipeline
+
+pipe = IFImg2ImgSuperResolutionPipeline.from_pretrained(
+ "DeepFloyd/IF-II-L-v1.0",
+ text_encoder=None,
+ variant="fp16",
+ torch_dtype=torch.float16,
+ device_map="auto"
+)
+```
+💡 **注意**:Img2Img 超分辨率管线不仅需要 Stage1 输出的生成图片,还需要原始图片作为输入。
+
+实际上我们还可以在 Stage2 输出的图片基础上继续使用 Stable Diffusion x4 upscaler 进行二次超分辨率。不过这里没有展示,如果需要,请使用 1.6 中的代码片段进行尝试。
+
+``` python
+image = pipe(
+ image=image,
+ original_image=original_image,
+ prompt_embeds=prompt_embeds,
+ negative_prompt_embeds=negative_embeds,
+ generator=generator,
+).images[0]
+image
+```
+
+![iv_sample_2](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/if/iv_sample_2.png)
+
+好了!Img2Img 的全部内容也介绍完毕。我们继续释放内存,然后介绍最后一个 Inpainting 管线。
+
+``` python
+del pipe
+flush()
+```
+
+## 3. Inpainting
+
+IF 模型的 Inpainting 管线大体上与 Img2Img 相同,只不过仅对图片的部分指定区域进行去噪和生成。
+
+我们首先用图片 mask 来指定一个待修复区域。
+
+让我们来展示一下 IF 模型 “生成带文字的图片” 这项令人惊叹的能力!我们来找一张带标语的图片,然后用 IF 模型替换标语的文字内容。
+
+首先下载图片
+
+``` python
+import requests
+
+url = "https://i.imgflip.com/5j6x75.jpg"
+response = requests.get(url)
+```
+
+并将其转换为 PIL 图片对象。
+
+``` python
+from PIL import Image
+from io import BytesIO
+
+original_image = Image.open(BytesIO(response.content)).convert("RGB")
+original_image = original_image.resize((512, 768))
+original_image
+```
+
+![inpainting_sample](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/if/inpainting_sample.png)
+
+我们指定标语牌区域为 mask 待修复区域,让 IF 模型替换该区域的文字内容。
+
+为方便起见,我们已经预生成了 mask 图片并将其加载到 HF 数据集中了。
+
+下载 mask 图片。
+
+``` python
+from huggingface_hub import hf_hub_download
+
+mask_image = hf_hub_download("diffusers/docs-images", repo_type="dataset", filename="if/sign_man_mask.png")
+mask_image = Image.open(mask_image)
+
+mask_image
+```
+
+![masking_sample](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/if/masking_sample.png)
+
+💡 **注意**:您也可以自行手动创建灰度 mask 图片。下面是一个创建 mask 图片的代码例子。
+
+``` python
+from PIL import Image
+import numpy as np
+
+height = 64
+width = 64
+
+example_mask = np.zeros((height, width), dtype=np.int8)
+
+# 设置待修复区域的 mask 像素值为 255
+example_mask[20:30, 30:40] = 255
+
+# 确保 PIL 的 mask 图片模式为 'L'
+# 'L' 代表单通道灰度图
+example_mask = Image.fromarray(example_mask, mode='L')
+
+example_mask
+```
+
+![masking_by_hand](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/if/masking_by_hand.png)
+
+好了,我们可以开始修复图片了🎨🖌
+
+### 3.1. 文本编码器
+
+我们同样先加载文本编码器。
+
+``` python
+from transformers import T5EncoderModel
+
+text_encoder = T5EncoderModel.from_pretrained(
+ "DeepFloyd/IF-I-XL-v1.0",
+ subfolder="text_encoder",
+ device_map="auto",
+ load_in_8bit=True,
+ variant="8bit"
+)
+```
+
+再创建一个 inpainting 管线,这次使用 `IFInpaintingPipeline` 类并初始化文本编码器预训练权重。
+
+``` python
+from diffusers import IFInpaintingPipeline
+
+pipe = IFInpaintingPipeline.from_pretrained(
+ "DeepFloyd/IF-I-XL-v1.0",
+ text_encoder=text_encoder,
+ unet=None,
+ device_map="auto"
+)
+```
+
+我们来让图片中的这位男士为 “just stack more layers” 作个代言!
+
+*注:外网中的一个梗,每当现有神经网络解决不了现有问题时,就会有 Just Stack More Layers! ......*
+
+``` python
+prompt = 'the text, "just stack more layers"'
+```
+
+给定 prompt 之后,接着创建 embeddings。
+
+``` python
+prompt_embeds, negative_embeds = pipe.encode_prompt(prompt)
+```
+
+然后再次释放内存。
+
+``` python
+del text_encoder
+del pipe
+flush()
+```
+
+### 3.2 Stage1: 核心扩散过程
+
+同样地,我们只加载 Stage1 UNet 的预训练权重。
+
+``` python
+pipe = IFInpaintingPipeline.from_pretrained(
+ "DeepFloyd/IF-I-XL-v1.0",
+ text_encoder=None,
+ variant="fp16",
+ torch_dtype=torch.float16,
+ device_map="auto"
+)
+```
+
+这里,我们需要传入原始图片、mask 图片和 prompt embeddings。
+
+``` python
+image = pipe(
+ image=original_image,
+ mask_image=mask_image,
+ prompt_embeds=prompt_embeds,
+ negative_prompt_embeds=negative_embeds,
+ output_type="pt",
+ generator=generator,
+).images
+```
+
+可视化查看一下中间输出。
+
+``` python
+pil_image = pt_to_pil(image)
+pipe.watermarker.apply_watermark(pil_image, pipe.unet.config.sample_size)
+
+pil_image[0]
+```
+
+![inpainted_output](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/if/inpainted_output.png)
+
+看起来不错!标语牌上的文字内容非常连贯!
+
+我们继续释放内存,做超分辨率放大图片。
+
+``` python
+del pipe
+flush()
+```
+
+### 3.3 Stage2: 超分辨率
+
+对于超分辨率,使用 `IFInpaintingSuperResolutionPipeline` 类来加载预训练权重。
+
+``` python
+from diffusers import IFInpaintingSuperResolutionPipeline
+
+pipe = IFInpaintingSuperResolutionPipeline.from_pretrained(
+ "DeepFloyd/IF-II-L-v1.0",
+ text_encoder=None,
+ variant="fp16",
+ torch_dtype=torch.float16,
+ device_map="auto"
+)
+```
+
+IF 模型的 inpainting 超分辨率管线需要接收 Stage1 输出的图片、原始图片、mask 图片、以及 prompt embeddings 作为输入。
+
+让我们运行最后的超分辨率管线。
+
+``` python
+image = pipe(
+ image=image,
+ original_image=original_image,
+ mask_image=mask_image,
+ prompt_embeds=prompt_embeds,
+ negative_prompt_embeds=negative_embeds,
+ generator=generator,
+).images[0]
+image
+```
+
+![inpainted_final_output](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/diffusers/if/inpainted_final_output.png)
+
+非常好!IF 模型生成的单词没有出现任何拼写错误!
+
+## 总结
+
+运行完整的 float32 精度的 IF 模型共需要至少 40GB 内存。本文展示了如何仅使用开源库来使 IF 模型能够在免费版 Google Colab 上运行并生成图片。
+
+机器学习领域的生态如此壮大主要受益于各种工具和模型的开源共享。本文涉及到的模型来自于 DeepFloyd, StabilityAI, 以及 [Google](https://huggingface.co/google),涉及到的库有 Diffusers, Transformers, Accelerate, 和 bitsandbytes 等,它们同样来自于不同组织的无数贡献者。
+
+非常感谢 DeepFloyd 团队创建和开源 IF 模型,以及为良好的机器学习生态做出的贡献🤗。
+
From ea6bcb304a3269eaa2e7c5080f36a43e43c69aed Mon Sep 17 00:00:00 2001
From: yaoqih <40328311+yaoqih@users.noreply.github.com>
Date: Thu, 4 May 2023 19:48:32 +0800
Subject: [PATCH 17/55] Update unity-in-spaces.md
Add a link for AI game
---
zh/unity-in-spaces.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/zh/unity-in-spaces.md b/zh/unity-in-spaces.md
index 8c56d4fda9..7b23644023 100644
--- a/zh/unity-in-spaces.md
+++ b/zh/unity-in-spaces.md
@@ -18,7 +18,7 @@ translators:
Hugging Face Space 是一个能够以简单的方式来构建、托管和分享项目或应用样例的平台。虽然通常更多地是应用在机器学习样例中,不过实际上 Space 还可以用来托管 Unity 游戏,并且支持点击即玩。这里有一些游戏的 Space 示例:
- [Huggy](https://huggingface.co/spaces/ThomasSimonini/Huggy)。Huggy 是一个基于强化学习构建的简易游戏,玩家可以点击鼠标扔出小木棍,来教宠物狗把木棍捡回来
-- [农场游戏](https://huggingface.co/spaces/dylanebert/FarmingGame)。农场游戏是我们在 <五天创建一个农场游戏> 系列中完成的游戏,玩家可以通过种植、收获和升级农作物来打造一个自己的繁荣农场
+- [农场游戏](https://huggingface.co/spaces/dylanebert/FarmingGame)。农场游戏是我们在 [<五天创建一个农场游戏>](https://huggingface.co/blog/zh/ml-for-games-1) 系列中完成的游戏,玩家可以通过种植、收获和升级农作物来打造一个自己的繁荣农场
- [Unity API Demo](https://huggingface.co/spaces/dylanebert/UnityDemo)。一个 Unity 样例
本文将详细介绍如何在 🤗 Space 上托管自己的 Unity 游戏。
@@ -126,4 +126,4 @@ git push
至此,在 🤗 Space 上托管 Unity 游戏的所有步骤就都完成了。恭喜!现在请刷新你的 Space 页面,你就可以在 Space 上玩游戏了!
-希望本教程对你有所帮助。如果你有任何疑问,或想更多地参与到 Hugging Face 游戏相关的应用中,可以加入 Hugging Face 的官方 [Discord](https://hf.co/join/discord) 频道来与我们取得联系!
\ No newline at end of file
+希望本教程对你有所帮助。如果你有任何疑问,或想更多地参与到 Hugging Face 游戏相关的应用中,可以加入 Hugging Face 的官方 [Discord](https://hf.co/join/discord) 频道来与我们取得联系!
From adbf61707692e5c45165449ad3e791ee61fa4918 Mon Sep 17 00:00:00 2001
From: yaoqih <40328311+yaoqih@users.noreply.github.com>
Date: Thu, 4 May 2023 20:05:47 +0800
Subject: [PATCH 18/55] Update if.md
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Fix “普罗大众” to “普惠大众”
---
zh/if.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/zh/if.md b/zh/if.md
index 1c900bba7a..f609c2b739 100644
--- a/zh/if.md
+++ b/zh/if.md
@@ -95,7 +95,7 @@ login()
## 优化 IF 模型以在有限的硬件条件下运行
-**最先进的机器学习技术不应该只掌握在少数精英手里。** 要使机器学习更 “普罗大众” 就意味着模型能够在消费级硬件上运行,而不是仅支持在最新型最高端的硬件上运行。
+**最先进的机器学习技术不应该只掌握在少数精英手里。** 要使机器学习更 “普惠大众” 就意味着模型能够在消费级硬件上运行,而不是仅支持在最新型最高端的硬件上运行。
深度学习开放社区创造了众多世界一流的工具,来支持在消费级硬件上运行资源密集型模型。例如:
From 8fcb5419eabc665e2e16ca7663809af0c002bb51 Mon Sep 17 00:00:00 2001
From: "Yao, Matrix"
Date: Mon, 8 May 2023 10:03:47 -0400
Subject: [PATCH 19/55] add starcoder cn
Signed-off-by: Yao, Matrix
---
zh/_blog.yml | 15 ++++----
zh/starcoder.md | 99 +++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 107 insertions(+), 7 deletions(-)
create mode 100644 zh/starcoder.md
diff --git a/zh/_blog.yml b/zh/_blog.yml
index 5a507e12c5..1061c7316e 100644
--- a/zh/_blog.yml
+++ b/zh/_blog.yml
@@ -433,11 +433,12 @@
- partnerships
- community
-- local: deep-learning-with-proteins
- title: "蛋白质深度学习"
- author: rocketknight1
- thumbnail: /blog/assets/119_deep_learning_with_proteins/folding_example.png
- date: December 2, 2022
+- local: starcoder
+ title: "StarCoder:最先进的代码大模型"
+ author: lvwerra
+ thumbnail: /blog/assets/141_starcoder/starcoder_thumbnail.png
+ date: May 4, 2023
tags:
- - guide
- - fine-tuning
+ - nlp
+ - community
+ - research
diff --git a/zh/starcoder.md b/zh/starcoder.md
new file mode 100644
index 0000000000..a8f6a191b8
--- /dev/null
+++ b/zh/starcoder.md
@@ -0,0 +1,99 @@
+---
+title: "StarCoder:最先进的代码大模型"
+thumbnail: /blog/assets/141_starcoder/starcoder_thumbnail.png
+authors:
+- user: lvwerra
+- user: loubnabnl
+translators:
+- user: MatrixYao
+---
+
+# StarCoder:最先进的代码大模型
+
+
+
+
+## 关于 BigCode
+
+BigCode 是由 Hugging Face 和 ServiceNow 共同领导的开放式科学合作项目,该项目致力于开发负责任的代码大模型。
+
+## StarCoder 简介
+
+StarCoder 和 StarCoderBase 是针对代码的大语言模型(代码 LLM),模型基于 GitHub 上的许可数据训练而得,训练数据中包括 80 多种编程语言、Git 提交、GitHub 问题和 Jupyter notebook。与 LLaMA 类似,我们基于 1 万亿个词元训练了一个约 15B 参数的模型。此外,我们还针对一个 35B 词元的 Python 数据集对 StarCoderBase 模型进行了微调,从而获得了一个我们称之为 StarCoder 的新模型。
+
+我们发现 StarCoderBase 在流行的编程基准测试中表现优于现有其他开源的代码 LLM,同时与闭源模型相比,如来自 OpenAI 的 `code-cushman-001`(早期版本的 GitHub Copilot 背后的原始 Codex 模型),其表现也相当甚至超过了闭源模型的表现。凭借超过 8,000 个词元的上下文长度,StarCoder 模型可以处理比任何其他开源 LLM 更多的输入,从而可以赋能更广泛的有趣应用。例如,通过用多轮对话来提示 StarCoder 模型,我们可以让它们充当我们的技术助理。此外,这些模型还可用于自动补全代码、根据指令修改代码以及用自然语言解释代码片段等任务。
+
+为了实现开源模型的安全发布,我们采取了一系列的措施,包括改进了 PII(Personally Identifiable Information,个人身份信息)编辑流水线、对归因跟踪工具进行了创新,并使用改进的 OpenRAIL 许可证发布 StarCoder。更新后的许可证简化了公司将模型集成到其产品中所需的流程。我们相信,凭借其强大的性能,StarCoder 模型将赋能社区将其应用或适配至广泛的应用场景和产品中。
+
+## 评估
+
+我们在不同的测试基准上对 StarCoder 及其他几个与其类似的模型进行了深入的评估。其中之一测试基准是 HumanEval,这是一个比较流行的 Python 基准测试,它主要测试模型是否可以根据函数的签名和文档来编写函数。我们发现 StarCoder 和 StarCoderBase 在 HumanEval 上的表现均优于最大的模型,包括 PaLM、LaMDA 和 LLaMA,尽管它们尺寸要小得多。同时,它们的性能还优于 CodeGen-16B-Mono 和 OpenAI 的 code-cushman-001 (12B) 模型。我们还注意到该模型会生成 `#Solution here` 这样的注释代码,这可能是因为此类代码通常是训练数据中代码习题的一部分。为了强制模型生成一个实际的解决方案,我们添加了提示词 `solutions/solution_1.py\n# Here is the correct implementation of the code exercise`。这使得 StarCoder 的 HumanEval 分数有了显著提高,从 34% 提升到 40% 以上,刷新了开源模型的最佳结果的记录。我们也在 CodeGen 和 StarCoderBase 上尝试了此提示词,但结果没有太大差异。
+
+| **模型** | **HumanEval** | **MBPP** |
+|--------------------|--------------|----------|
+| LLaMA-7B | 10.5 | 17.7 |
+| LaMDA-137B | 14.0 | 14.8 |
+| LLaMA-13B | 15.8 | 22.0 |
+| CodeGen-16B-Multi | 18.3 | 20.9 |
+| LLaMA-33B | 21.7 | 30.2 |
+| CodeGeeX | 22.9 | 24.4 |
+| LLaMA-65B | 23.7 | 37.7 |
+| PaLM-540B | 26.2 | 36.8 |
+| CodeGen-16B-Mono | 29.3 | 35.3 |
+| StarCoderBase | 30.4 | 49.0 |
+| code-cushman-001 | 33.5 | 45.9 |
+| StarCoder | 33.6 | **52.7** |
+| StarCoder-Prompted | **40.8** | 49.5 |
+
+StarCoder 的一个有趣方面是它是多语言的,因此我们在 MultiPL-E 上对其进行了评估,MultiPL-E 是 HumanEval 的多语言扩展版。我们观察到 StarCoder 在许多编程语言上与 `code-cushman-001` 的表现相当甚至更优。在 DS-1000 数据科学基准测试中,它以明显优势击败了 `code-cushman-001` 以及所有其他开源模型。好了,我们来看看除了代码补全之外,StarCoder 还能做些什么!
+
+## 技术助理
+
+经过详尽的评估,我们已经知道 StarCoder 非常擅长编写代码。我们还想测试它是否可以用作技术助理,毕竟它的训练数据中有大量的文档和 GitHub 问题。受 Anthropic 的 [HHH 提示](https://gist.github.com/jareddk/2509330f8ef3d787fc5aaac67aab5f11#file-hhh_prompt-txt) 的启发,我们构建了一个[技术助理提示](https://huggingface.co/datasets/bigcode/ta-prompt)。令人惊喜的是,仅凭提示,该模型就能够充当技术助理并回答与编程相关的问题!
+
+![技术助理示例](https://huggingface.co/datasets/bigcode/admin/resolve/main/StarCoderChatExamples.png)
+
+## 训练数据
+
+该模型是在 The Stack 1.2 的一个子集上训练的。该数据集仅包含许可代码,它还包含一个退出流程,以便代码贡献者可以从数据集中删除他们的数据(请参见 [Am I in The Stack](https://huggingface.co/spaces/bigcode/in-the-stack))。此外,我们从训练数据中删除了个人身份信息,例如姓名、密码和电子邮件地址。
+
+## 我们还发布了...
+
+除了模型,我们还发布了一系列其他资源和应用演示:
+- 模型权重,包括具有 OpenRAIL 许可证的 checkpoints
+- 所有数据预处理和训练代码,许可证为 Apache 2.0
+- 对模型进行全面评估的工具
+- 用于训练的删除掉 PII 信息的新数据集,以及用于评估 PII 信息删除效果的代码
+- 用于训练的预处理过的数据集
+- 用于在数据集中查找生成代码出处的代码归因工具
+
+
+## 链接
+
+### 模型
+- [论文](https://drive.google.com/file/d/1cN-b9GnWtHzQRoE7M7gAEyivY0kl4BYs/view): 关于 StarCoder 的技术报告。
+- [GitHub](https://github.com/bigcode-project/starcoder/tree/main): 你可以由此获得有关如何使用或微调 StarCoder 的所有信息。
+- [StarCoder](https://huggingface.co/bigcode/starcoder): 基于 Python 数据集进一步微调 StarCoderBase 所得的模型。
+- [StarCoderBase](https://huggingface.co/bigcode/starcoderbase): 基于来自 The Stack 数据集的 80 多种编程语言训练而得的模型。
+- [StarEncoder](https://huggingface.co/bigcode/starencoder): 在 The Stack 上训练的编码器模型。
+- [StarPii](https://huggingface.co/bigcode/starpii): 基于 StarEncoder 的 PII 检测器。
+
+### 工具和应用演示
+- [StarCoder Chat](https://huggingface.co/chat?model=bigcode/starcoder): 和 StarCoder 聊天!
+- [VSCode Extension](https://marketplace.visualstudio.com/items?itemName=HuggingFace.huggingface-vscode): 使用 StarCoder 补全代码的 VSCode 插件!
+- [StarCoder Playground](https://huggingface.co/spaces/bigcode/bigcode-playground): 用 StarCoder 写代码!
+- [StarCoder Editor](https://huggingface.co/spaces/bigcode/bigcode-editor): 用 StarCoder 编辑代码!
+
+### 数据与治理
+- [StarCoderData](https://huggingface.co/datasets/bigcode/starcoderdata): StarCoder 的预训练数据集。
+- [Tech Assistant Prompt](https://huggingface.co/datasets/bigcode/ta-prompt): 使用该提示,你可以将 StarCoder 变成技术助理。
+- [Governance Card](): 有关模型治理的卡片。
+- [StarCoder License Agreement](https://huggingface.co/spaces/bigcode/bigcode-model-license-agreement): 该模型基于 BigCode OpenRAIL-M v1许可协议。
+- [StarCoder Search](https://huggingface.co/spaces/bigcode/search): 对预训练数据集中的代码进行全文搜索。
+- [StarCoder Membership Test](https://stack.dataportraits.org): 快速测试某代码是否存在于预训练数据集中。
+
+你可以在 [huggingface.co/bigcode](https://huggingface.co/bigcode) 找到所有资源和链接!
+
+> 英文原文: https://huggingface.co/blog/starcoder
+> 原文作者:Leandro von Werra,Loubna Ben Allal
+> 译者: Matrix Yao (姚伟峰),英特尔深度学习工程师,工作方向为 transformer-family 模型在各模态数据上的应用及大规模模型的训练推理。
From 1447c06a5eb4fb0931ce1db77d0570325998ec9d Mon Sep 17 00:00:00 2001
From: "Yao, Matrix"
Date: Mon, 1 May 2023 15:18:56 -0400
Subject: [PATCH 20/55] deep-learning-with-proteins cn done
Signed-off-by: Yao, Matrix
---
zh/_blog.yml | 11 ++-
zh/deep-learning-with-proteins.md | 121 ++++++++++++++++++++++++++++++
2 files changed, 131 insertions(+), 1 deletion(-)
create mode 100644 zh/deep-learning-with-proteins.md
diff --git a/zh/_blog.yml b/zh/_blog.yml
index 8b5b76cd52..5789fc3e85 100644
--- a/zh/_blog.yml
+++ b/zh/_blog.yml
@@ -441,4 +441,13 @@
date: April 24, 2023
tags:
- partnerships
- - community
\ No newline at end of file
+ - community
+
+- local: deep-learning-with-proteins
+ title: "蛋白质深度学习"
+ author: rocketknight1
+ thumbnail: /blog/assets/119_deep_learning_with_proteins/folding_example.png
+ date: December 2, 2022
+ tags:
+ - guide
+ - fine-tuning
diff --git a/zh/deep-learning-with-proteins.md b/zh/deep-learning-with-proteins.md
new file mode 100644
index 0000000000..f3021781f6
--- /dev/null
+++ b/zh/deep-learning-with-proteins.md
@@ -0,0 +1,121 @@
+---
+title: "蛋白质深度学习"
+thumbnail: /blog/assets/119_deep_learning_with_proteins/folding_example.png
+authors:
+- user: rocketknight1
+translators:
+- user: MatrixYao
+---
+
+# 蛋白质深度学习
+
+本文主要面向两类目标读者:一类是想使用机器学习的生物学家,一类是想进入生物学领域的机器学习研究者。如果你不熟悉生物学或机器学习,仍然欢迎你阅读本文,但有时你可能会觉得有点读不太懂!如果你已经熟悉这两者,那么你可能根本不需要本文 —— 你可以直接跳到我们的示例 notebook 以查看这些模型的实际应用:
+
+- 微调蛋白质语言模型([PyTorch](https://colab.research.google.com/github/huggingface/notebooks/blob/main/examples/protein_language_modeling.ipynb),[TensorFlow](https://colab.research.google.com/github/huggingface/notebooks/blob/main/examples/protein_language_modeling-tf.ipynb))
+- 使用 ESMFold 进行蛋白质折叠([PyTorch](https://colab.research.google.com/github/huggingface/notebooks/blob/main/examples/protein_folding.ipynb),因为 `OpenFold` 仅支持 PyTorch,所以目前仅支持 PyTorch)
+
+## 面向生物学家的科普:语言模型是什么鬼?
+
+用于处理蛋白质的模型深受 BERT 和 GPT 等大语言模型的启发。因此,为了了解这些模型是如何工作的,我们要回到 2016 年左右,那时大语言模型还没有出现,特朗普还没有当选,脱欧还没有发生,深度学习(Deep Learning,DL)还是个日日新的超级新星...... DL 成功的关键在于它使用人工神经网络来学习数据中的复杂模式。不过,深度学习有一个关键问题 —— 它需要**大量**的数据才能正常工作,而在很多任务中,根本没那么多数据。
+
+假设你想训练一个 DL 模型,输入一个英语句子,并判断它是否合乎语法。所以你准备了训练数据,格式如下:
+
+| Text | Label |
+| --- | --- |
+| The judge told the jurors to think carefully. | Correct |
+| The judge told that the jurors to think carefully. | Incorrect |
+| … | … |
+
+理论上,这个任务在当时是完全可行的 —— 如果你将如上格式的训练数据输入深度学习模型,它就可以学着去预测新句子是否合乎语法。但在实践中,它的效果并不怎么好,因为在 2016 年,大多数人都从一个随机初始化的新模型开始他们的每项任务。这意味着**模型必须仅从给定的训练数据中学习它们需要知道的一切!**
+
+我们来理解一下这到底有多难,假设你是一个机器学习模型,我提供给你一些训练数据用于完成我希望你学习的任务。假如我给你的训练数据如下:
+
+| Text | Label |
+| --- | --- |
+| Is í an stiúrthóir is fearr ar domhan! | 1 |
+| Is fuath liom an scannán seo. | 0 |
+| Scannán den scoth ab ea é. | 1 |
+| D’fhág mé an phictiúrlann tar éis fiche nóiméad! | 0 |
+
+在这里,我选择了一种我希望你从未曾见过的语言,所以我猜你已经可能开始对你是否能学会这个任务不太自信了。也许在数百或数千个样本之后,你可能会开始注意到输入中一些重复出现的单词或模式,然后你可能开始能够作出比随机机猜测更好的判断,但即使这样,一旦出现新单词或之前没见过的措辞马上就能够难住你,让你猜错。无独有偶,这也是 DL 模型当时的表现!
+
+现在我们试试相同的任务,但这次使用英语:
+
+| Text | Label |
+| --- | --- |
+| She’s the best director in the world! | 1 |
+| I hate this movie. | 0 |
+| It was an absolutely excellent film. | 1 |
+| I left the cinema after twenty minutes! | 0 |
+
+现在事情变得简单了 —— 任务只是预测电影评论是正面(1)还是负面(0)的。仅使用两个正例和两个反例,你就能以接近 100% 的准确率完成这项任务,因为**你原本就具备大量的英语词汇和语法知识,并具有电影和情感相关表达的文化背景。** 如果没有这些知识,事情就会变得更像第一个任务 —— 你需要阅读大量的例子才能开始发现输入中的表达模式,即使你花时间研究了数十万个的例子你的猜测仍然远不如在英语任务中只有四个例子准确。
+
+### 关键突破:迁移学习
+
+在机器学习中,我们把这种将先验知识迁移到新任务的概念称为“**迁移学习**”。在 DL 上使用迁移学习是 2016 年左右该领域的一个主要目标。预训练词向量之类的东西(非常有趣,但超出了本文的范围!)在 2016 年确实存在并且允许迁移一些知识到新的模型,但是这种知识迁移仍然比较肤浅,模型仍然需要大量的训练数据才能很好地工作。
+
+这种情况一直持续到 2018 年。2018 年,两篇巨著横空出世,第一篇引入了 [ULMFiT](https://arxiv.org/abs/1801.06146) 模型,第二篇引入了 [BERT](https://arxiv.org/abs/1810.04805) 模型。这两篇论文是让自然语言迁移学习真正发挥作用的开创性论文,尤其是 BERT 标志着预训练大语言模型时代的发轫。两篇论文共同使用了一个技巧,那就是它们利用了深度学习中人工神经网络的固有性质 —— 先花较长的时间在有着丰富训练数据的文本任务上训练神经网络,然后将整个神经网络复制到新任务中,仅用新任务的数据更新或重新训练与网络输出相对应的少数神经元。
+
+![迁移学习](/blog/assets/119_deep_learning_with_proteins/transfer_learning.png)
+
+*上图来自 [ULMFiT 论文](https://arxiv.org/abs/1801.06146),它展示了在三个独立的任务上使用迁移学习与从头开始训练模型相比带来的巨大的性能提升。在许多情况下,使用迁移学习的效果相当于拥有超过 100 倍的训练数据。不要忘记这是 2018 年发布的 —— 现代的大语言模型可以做得更好!*
+
+这样做的原因是,在解决任何重要任务的过程中,神经网络学习到很多输入数据的结构性知识 —— 如对于视觉神经网络,输入的是原始像素,模型学习到了如何识别直线、曲线和边缘;对于文本神经网络,输入的是原始文本,模型学习到了有关语法结构的细节。而这些信息并不特定于某些任务。—— 迁移学习起作用的关键原因是**解决任务需要知道的很多信息都不是特定于该任务的!** 要对电影评论进行分类,你不需要了解很多关于电影评论的知识,但你需要大量的英语和文化背景知识。通过选择训练数据丰富的任务,我们可以让神经网络学习此类“领域知识”,然后将其应用于我们关心的新任务,而在这些新任务中训练数据可能更难获取。
+
+至此,希望你已经了解了什么是迁移学习,并且大语言模型是一个经过大量文本数据训练而得的大型神经网络,这使其成为迁移到新任务的主要备选方案。我们将在下面看到相同的技术如何应用于蛋白质,但首先我需要为另一半观众写一篇介绍。如果你已经熟悉这方面的知识,你可以随时跳过下一部分!
+
+
+## 面向机器学习研究者的科普:蛋白质是什么鬼?
+
+简而言之,蛋白质可以做很多事情。有些蛋白质是**酶** - 它们充当化学反应的催化剂。当你的身体将营养物质转化为能量时,从食物到肌肉运动的每一步都由一种酶催化。一些蛋白质是**结构性的**,它们的功能是提供稳定性以及塑形,例如结缔组织的蛋白质。如果你看过化妆品广告,你可能看到过**胶原蛋白**、**弹性蛋白**以及**角蛋白**,这些是构成我们皮肤和头发结构的蛋白质。
+
+其它蛋白质对健康和疾病至关重要 —— 每个人可能都记得有关 COVID-19 病毒的 **spike 蛋白**的无数新闻报道。 COVID spike 蛋白与人类细胞表面一种名为 ACE2 的蛋白质结合,使其能够进入细胞并传递病毒 RNA 的有效载荷。由于这种相互作用对感染至关重要,因此在 COVID 大流行期间对这些蛋白质及其相互作用进行建模是一个热门研究焦点。
+
+蛋白质由多个**氨基酸组成**。氨基酸是相对简单的分子,它们都具有相同的分子结构,而该结构的化学性质允许氨基酸融合在一起,从而使单个分子可以成为一条长链。这里关键是要知道氨基酸种类不多 —— 只有 20 种标准氨基酸,某些生物体上可能还有一些其他非标准的氨基酸,但总量不多。导致蛋白质巨大多样性的原因是**这些氨基酸可以按任何顺序组合**,而由此产生的蛋白质链可以具有截然不同的形状和功能,因为链的不同部分会粘连以及彼此折叠。与文本类比一下:英语只有 26 个字母,但想想你可以用这 26 个字母的组合写出各种单词。
+
+事实上,由于氨基酸的数量很少,生物学家可以为每一种氨基酸分配一个不同的字母。这意味着你可以像编写文本字符串一样编写蛋白质!例如,假设一种蛋白质链中有这些氨基酸:甲硫氨酸、丙氨酸和组氨酸。这些氨基酸的 [对应的字母](https://en.wikipedia.org/wiki/Amino_acid#Table_of_standard_amino_acid_abbreviations_and_properties) 是 M、A 和 H,因此我们可以将该链写为 “MAH” 。不过,大多数蛋白质含有数百甚至数千个氨基酸,而不仅仅是三个!!
+
+![蛋白质结构](/blog/assets/119_deep_learning_with_proteins/protein_structure.png)
+
+*上图显示了一种蛋白质的两种表示形式。所有氨基酸都包含碳 - 碳 - 氮(C-C-N)序列。当氨基酸融合到蛋白质中时,这种重复模式将贯穿始终,我们称为蛋白质的 “骨架”。然而,氨基酸的不同之处在于它们的 “侧链”,侧链指的是附着在 C-C-N 主链上的原子。图的下半部分有标记为 R1、R2 和 R3 的侧链,它们可以是任何氨基酸。在图的上半部分,中央氨基酸有一个 CH3 侧链 - 那么该氨基酸即为**丙氨酸,由字母 A 表示**([图片来源](https://commons.wikimedia.org/wiki/File:Peptide-Figure-Revised.png))。*
+
+尽管我们可以将其写成文本字符串,但蛋白质实际上并不是一种 “语言”,至少不是诺姆 - 乔姆斯基认可的任何一种语言。但它们确实有一些类似语言的特征,从机器学习的角度来看,它们是一个与文本非常相似的领域:只有一部分字符串是有“意义”的。随机文本是垃圾,随机蛋白质只是一个无形状的斑点。
+
+此外,如果你只是孤立地考虑蛋白质的一部分,信息就会丢失,就像当你只阅读从较长文本中提取的某个句子时,信息也会丢失。蛋白质的一个区域可能只有在其它部分存在的情况下才会呈现其自然形状,因为需要其它部分帮助稳定和矫正其形状!这意味着被全局自注意力很好地捕捉到的那种长程作用力对于正确建模蛋白质非常重要。
+
+至此,希望你对蛋白质是什么以及为什么生物学家如此关心它们有一个基本的概念 —— 尽管氨基酸“字母表” 、很小,但它们具有广泛的结构和功能多样性。因此如果能仅通过观察氨基酸的原始“字符串”来理解和预测蛋白质的结构和功能对研究是非常有价值的。
+
+## 联袂 - 蛋白质机器学习
+
+现在我们已经了解了使用语言模型进行迁移学习是如何工作的,同时我们还了解了什么是蛋白质。一旦你有了这些背景知识,下一步就不难了 —— 我们可以在蛋白质上应用相同的迁移学习思想!我们不是在涉及英文文本的任务上预先训练模型,而是在输入是蛋白质且有大量可用训练数据的任务上训练它。一旦我们这样做了,我们的模型就有希望学到很多关于蛋白质结构的知识,就像语言模型学到了很多关于语言结构的知识一样。这使得预训练的蛋白质模型有希望可以迁移到任何其它基于蛋白质的任务!
+
+生物学家想在哪些任务上用机器学习训练蛋白质模型?最著名的蛋白质建模任务是**蛋白质折叠**。该任务是,给定像 “MLKNV……” 这样的氨基酸链,预测蛋白质最终会折叠成什么形状。这是一项极其重要的任务,因为准确预测蛋白质的形状和结构可以深入了解蛋白质作用和机理。
+
+早在现代机器学习出现之前,人们就一直在研究这个问题。最早的一些大规模分布式计算项目,如 Folding@Home,以超精的空间和时间分辨率使用原子级模拟来模拟蛋白质折叠。甚至还存在一个专门的*蛋白质晶体学*领域,该领域的研究者使用 X 射线衍射来观察从活细胞中分离出的蛋白质的结构。
+
+然而,与许多其他领域一样,深度学习的到来改变了一切。 AlphaFold,尤其是 AlphaFold2 使用了 transformer 结构的深度学习模型,并在模型上增加了针对蛋白质数据的处理,在仅从原始氨基酸序列预测新型蛋白质结构方面取得了出色的结果。如果你对蛋白质折叠感兴趣,我们强烈建议你看看[我们的 ESMFold notebook](https://colab.research.google.com/github/huggingface/notebooks/blob/main/examples/protein_folding.ipynb) —— ESMFold 是一种类似于 AlphaFold2 的新模型,但它是一种更“纯”的深度学习模型,不需要任何外部数据库或搜索操作即可运行。因此,设置过程不像AlphaFold2 那样痛苦,模型运行得更快,同时仍保持出色的准确性。
+
+
+![蛋白质折叠示例](/blog/assets/119_deep_learning_with_proteins/folding_example.png)
+
+*上图为多杀巴斯德氏菌的**氨基葡萄糖 - 6 - 磷酸脱氨酶**同源二聚体的预测结构。该结构和可视化图是由上文中的 ESMFold notebook 在几秒钟内生成的。深蓝色表示结构置信度最高的区域。*
+
+不过,蛋白质折叠并不是我们唯一感兴趣的任务!生物学家可能想做更多的蛋白质分类任务 —— 比如他们想预测蛋白质将在细胞的哪个部分起作用,或者在蛋白质产生后其中哪些氨基酸会被修改。在机器学习的语言中,当你想对整个蛋白质进行分类(例如,预测其亚细胞定位)时,这类任务可被建模为**序列分类(sequence classification)**;当你想对每个氨基酸进行分类时(例如,预测哪些氨基酸会被翻译后修饰(Post-translational modification,PTM)),这类任务可被建模为**词分类(token classification)**。
+
+不过,关键的一点是,尽管蛋白质与语言非常不同,但它们可以通过几乎完全相同的机器学习方法来处理 —— 在一个大的蛋白质序列数据库上进行大规模预训练,然后通过**迁移学习**迁移到其它训练数据可能少得多的任务。事实上,在某些方面它甚至比像 BERT 这样的大型语言模型还要简单,因为不需要复杂的分词和词解析 —— 蛋白质没有分词,因此最简单的方法是直接将每个氨基酸转换成单词。
+
+## 听起来很酷,但从何下手?
+
+如果你已经熟悉深度学习,那么你会发现微调蛋白质模型的代码看起来与微调语言模型的代码非常相似。我们提供了 [PyTorch](https://colab.research.google.com/github/huggingface/notebooks/blob/main/examples/protein_language_modeling.ipynb) 和 [TensorFlow](https://colab.research.google.com/github/huggingface/notebooks/blob/main/examples/protein_language_modeling-tf.ipynb) 两个示例供你起步。你可以从像 [UniProt](https://www.uniprot.org/) 这样的开放蛋白质数据库中获取大量标注数据,UniProt 除了提供 REST API 接口以供访问数据外还提供了一个漂亮的 Web 界面。你的主要困难是找到有趣的研究方向进行探索,这我就爱莫能助了 —— 但我相信有很多生物学家愿意与你合作!
+
+反之,如果你是一名生物学家,你可能有很多想法想尝试,但可能对深入研究机器学习代码有点害怕。别怕!我们精心设计了示例([PyTorch](https://colab.research.google.com/github/huggingface/notebooks/blob/main/examples/protein_language_modeling.ipynb)、[TensorFlow](https://colab.research.google.com/github/huggingface/notebooks/blob/main/examples/protein_language_modeling-tf.ipynb)),这些示例中的数据加载部分与其他部分完全独立。这意味着如果你有一个**序列分类**或**词分类**任务,你只需要构建一个包含蛋白质序列及其应对标签的数据集,然后把我们的数据加载代码换成你自己写的用于加载你的数据集的代码就好了。
+
+尽管示例中使用 [ESM-2](https://www.biorxiv.org/content/10.1101/2022.07.20.500902v1) 作为基础预训练模型,因为它在当前是最先进的。该领域的研究人员可能还熟悉其他模型,如 Rost 实验室的 [ProtBERT](https://huggingface.co/Rostlab/prot_bert)([论文链接](https://www.biorxiv.org/content/10.1101/2020.07.12.199554v3)) 是同类中最早的模型之一,并且引起了生物信息学界的极大兴趣。只需将示例代码中的 checkpoint 路径从 `facebook/esm2xxx` 改为 `Rostlab/prot_bert` 之类的,示例中的代码就可以使用 ProtBERT 模型了。
+
+## 结语
+
+深度学习和生物学的交叉领域将在未来几年成为一个非常活跃和成果丰硕的领域。然而,使得深度学习发展如此迅速的原因之一是人们可以快速重现结果并调整新模型以供自己使用。本着这种精神,如果你训练了一个你认为对社区有用的模型,请分享它!上面那些notebook 中都包含将模型上传到 Hub 的代码,其他研究人员可以在 Hub 上自由访问和构建它们 - 除了对该领域的好处之外,这也可以让你的论文被更多人见到和引用。你甚至可以使用 [Spaces](https://huggingface.co/docs/hub/spaces-overview) 做一个实时的网络演示版,以便其他研究人员可以输入蛋白质序列并免费获得结果,而无需编写一行代码。祝你好运,愿审稿人对你青眼相加!
+
+> 英文原文: https://huggingface.co/blog/deep-learning-with-proteins
+> 原文作者:Matthew Carrigan
+> 译者: Matrix Yao (姚伟峰),英特尔深度学习工程师,工作方向为 transformer-family 模型在各模态数据上的应用及大规模模型的训练推理。
From b993d7f70b399513c2f4e3d482e6352c3b8770df Mon Sep 17 00:00:00 2001
From: "Yao, Matrix"
Date: Mon, 8 May 2023 10:03:47 -0400
Subject: [PATCH 21/55] add starcoder cn
Signed-off-by: Yao, Matrix
Update: formatting and punctuations of starcoder.md
---
zh/_blog.yml | 15 ++++----
zh/starcoder.md | 100 ++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 108 insertions(+), 7 deletions(-)
create mode 100644 zh/starcoder.md
diff --git a/zh/_blog.yml b/zh/_blog.yml
index 5789fc3e85..54b66f4f34 100644
--- a/zh/_blog.yml
+++ b/zh/_blog.yml
@@ -443,11 +443,12 @@
- partnerships
- community
-- local: deep-learning-with-proteins
- title: "蛋白质深度学习"
- author: rocketknight1
- thumbnail: /blog/assets/119_deep_learning_with_proteins/folding_example.png
- date: December 2, 2022
+- local: starcoder
+ title: "StarCoder:最先进的代码大模型"
+ author: lvwerra
+ thumbnail: /blog/assets/141_starcoder/starcoder_thumbnail.png
+ date: May 4, 2023
tags:
- - guide
- - fine-tuning
+ - nlp
+ - community
+ - research
diff --git a/zh/starcoder.md b/zh/starcoder.md
new file mode 100644
index 0000000000..bdc1a25107
--- /dev/null
+++ b/zh/starcoder.md
@@ -0,0 +1,100 @@
+---
+title: "StarCoder:最先进的代码大模型"
+thumbnail: /blog/assets/141_starcoder/starcoder_thumbnail.png
+authors:
+- user: lvwerra
+- user: loubnabnl
+translators:
+- user: MatrixYao
+- user: zhongdongy
+ proofreader: true
+---
+
+# StarCoder: 最先进的代码大模型
+
+
+
+
+## 关于 BigCode
+
+BigCode 是由 Hugging Face 和 ServiceNow 共同领导的开放式科学合作项目,该项目致力于开发负责任的代码大模型。
+
+## StarCoder 简介
+
+StarCoder 和 StarCoderBase 是针对代码的大语言模型 (代码 LLM),模型基于 GitHub 上的许可数据训练而得,训练数据中包括 80 多种编程语言、Git 提交、GitHub 问题和 Jupyter notebook。与 LLaMA 类似,我们基于 1 万亿个词元训练了一个约 15B 参数的模型。此外,我们还针对一个 35B 词元的 Python 数据集对 StarCoderBase 模型进行了微调,从而获得了一个我们称之为 StarCoder 的新模型。
+
+我们发现 StarCoderBase 在流行的编程基准测试中表现优于现有其他开源的代码 LLM,同时与闭源模型相比,如来自 OpenAI 的 `code-cushman-001` (早期版本的 GitHub Copilot 背后的原始 Codex 模型),其表现也相当甚至超过了闭源模型的表现。凭借超过 8,000 个词元的上下文长度,StarCoder 模型可以处理比任何其他开源 LLM 更多的输入,从而可以赋能更广泛的有趣应用。例如,通过用多轮对话来提示 StarCoder 模型,我们可以让它们充当我们的技术助理。此外,这些模型还可用于自动补全代码、根据指令修改代码以及用自然语言解释代码片段等任务。
+
+为了实现开源模型的安全发布,我们采取了一系列的措施,包括改进了 PII (Personally Identifiable Information,个人身份信息) 编辑流水线、对归因跟踪工具进行了创新,并使用改进的 OpenRAIL 许可证发布 StarCoder。更新后的许可证简化了公司将模型集成到其产品中所需的流程。我们相信,凭借其强大的性能,StarCoder 模型将赋能社区将其应用或适配至广泛的应用场景和产品中。
+
+## 评估
+
+我们在不同的测试基准上对 StarCoder 及其他几个与其类似的模型进行了深入的评估。其中之一测试基准是 HumanEval,这是一个比较流行的 Python 基准测试,它主要测试模型是否可以根据函数的签名和文档来编写函数。我们发现 StarCoder 和 StarCoderBase 在 HumanEval 上的表现均优于最大的模型,包括 PaLM、LaMDA 和 LLaMA,尽管它们尺寸要小得多。同时,它们的性能还优于 CodeGen-16B-Mono 和 OpenAI 的 code-cushman-001 (12B) 模型。我们还注意到该模型会生成 `#Solution here` 这样的注释代码,这可能是因为此类代码通常是训练数据中代码习题的一部分。为了强制模型生成一个实际的解决方案,我们添加了提示词 `solutions/solution_1.py\n# Here is the correct implementation of the code exercise`。这使得 StarCoder 的 HumanEval 分数有了显著提高,从 34% 提升到 40% 以上,刷新了开源模型的最佳结果的记录。我们也在 CodeGen 和 StarCoderBase 上尝试了此提示词,但结果没有太大差异。
+
+| **模型** | **HumanEval** | **MBPP** |
+|--------------------|--------------|----------|
+| LLaMA-7B | 10.5 | 17.7 |
+| LaMDA-137B | 14.0 | 14.8 |
+| LLaMA-13B | 15.8 | 22.0 |
+| CodeGen-16B-Multi | 18.3 | 20.9 |
+| LLaMA-33B | 21.7 | 30.2 |
+| CodeGeeX | 22.9 | 24.4 |
+| LLaMA-65B | 23.7 | 37.7 |
+| PaLM-540B | 26.2 | 36.8 |
+| CodeGen-16B-Mono | 29.3 | 35.3 |
+| StarCoderBase | 30.4 | 49.0 |
+| code-cushman-001 | 33.5 | 45.9 |
+| StarCoder | 33.6 | **52.7** |
+| StarCoder-Prompted | **40.8** | 49.5 |
+
+StarCoder 的一个有趣方面是它是多语言的,因此我们在 MultiPL-E 上对其进行了评估,MultiPL-E 是 HumanEval 的多语言扩展版。我们观察到 StarCoder 在许多编程语言上与 `code-cushman-001` 的表现相当甚至更优。在 DS-1000 数据科学基准测试中,它以明显优势击败了 `code-cushman-001` 以及所有其他开源模型。好了,我们来看看除了代码补全之外,StarCoder 还能做些什么!
+
+## 技术助理
+
+经过详尽的评估,我们已经知道 StarCoder 非常擅长编写代码。我们还想测试它是否可以用作技术助理,毕竟它的训练数据中有大量的文档和 GitHub 问题。受 Anthropic 的 [HHH 提示](https://gist.github.com/jareddk/2509330f8ef3d787fc5aaac67aab5f11#file-hhh_prompt-txt) 的启发,我们构建了一个 [技术助理提示](https://huggingface.co/datasets/bigcode/ta-prompt)。令人惊喜的是,仅凭提示,该模型就能够充当技术助理并回答与编程相关的问题!
+
+![技术助理示例](https://huggingface.co/datasets/bigcode/admin/resolve/main/StarCoderChatExamples.png)
+
+## 训练数据
+
+该模型是在 The Stack 1.2 的一个子集上训练的。该数据集仅包含许可代码,它还包含一个退出流程,以便代码贡献者可以从数据集中删除他们的数据 (请参见 [Am I in The Stack](https://huggingface.co/spaces/bigcode/in-the-stack))。此外,我们从训练数据中删除了个人身份信息,例如姓名、密码和电子邮件地址。
+
+## 我们还发布了……
+
+除了模型,我们还发布了一系列其他资源和应用演示:
+
+- 模型权重,包括具有 OpenRAIL 许可证的 checkpoints
+- 所有数据预处理和训练代码,许可证为 Apache 2.0
+- 对模型进行全面评估的工具
+- 用于训练的删除掉 PII 信息的新数据集,以及用于评估 PII 信息删除效果的代码
+- 用于训练的预处理过的数据集
+- 用于在数据集中查找生成代码出处的代码归因工具
+
+## 链接
+
+### 模型
+
+- [论文](https://drive.google.com/file/d/1cN-b9GnWtHzQRoE7M7gAEyivY0kl4BYs/view): 关于 StarCoder 的技术报告。
+- [GitHub](https://github.com/bigcode-project/starcoder/tree/main): 你可以由此获得有关如何使用或微调 StarCoder 的所有信息。
+- [StarCoder](https://huggingface.co/bigcode/starcoder): 基于 Python 数据集进一步微调 StarCoderBase 所得的模型。
+- [StarCoderBase](https://huggingface.co/bigcode/starcoderbase): 基于来自 The Stack 数据集的 80 多种编程语言训练而得的模型。
+- [StarEncoder](https://huggingface.co/bigcode/starencoder): 在 The Stack 上训练的编码器模型。
+- [StarPii](https://huggingface.co/bigcode/starpii): 基于 StarEncoder 的 PII 检测器。
+
+### 工具和应用演示
+
+- [StarCoder Chat](https://huggingface.co/chat?model=bigcode/starcoder): 和 StarCoder 聊天!
+- [VSCode Extension](https://marketplace.visualstudio.com/items?itemName=HuggingFace.huggingface-vscode): 使用 StarCoder 补全代码的 VSCode 插件!
+- [StarCoder Playground](https://huggingface.co/spaces/bigcode/bigcode-playground): 用 StarCoder 写代码!
+- [StarCoder Editor](https://huggingface.co/spaces/bigcode/bigcode-editor): 用 StarCoder 编辑代码!
+
+### 数据与治理
+
+- [StarCoderData](https://huggingface.co/datasets/bigcode/starcoderdata): StarCoder 的预训练数据集。
+- [Tech Assistant Prompt](https://huggingface.co/datasets/bigcode/ta-prompt): 使用该提示,你可以将 StarCoder 变成技术助理。
+- [Governance Card](): 有关模型治理的卡片。
+- [StarCoder License Agreement](https://huggingface.co/spaces/bigcode/bigcode-model-license-agreement): 该模型基于 BigCode OpenRAIL-M v1 许可协议。
+- [StarCoder Search](https://huggingface.co/spaces/bigcode/search): 对预训练数据集中的代码进行全文搜索。
+- [StarCoder Membership Test](https://stack.dataportraits.org): 快速测试某代码是否存在于预训练数据集中。
+
+你可以在 [huggingface.co/bigcode](https://huggingface.co/bigcode) 找到所有资源和链接!
\ No newline at end of file
From 8c958279664490126741c5a9e01ebfbba192ff50 Mon Sep 17 00:00:00 2001
From: Zhongdong Yang
Date: Tue, 9 May 2023 17:02:34 +0800
Subject: [PATCH 22/55] Update: proofreading zh/unity-in-spaces.md
---
zh/_blog.yml | 10 +++++++
zh/unity-in-spaces.md | 63 ++++++++++++++++++++++---------------------
2 files changed, 42 insertions(+), 31 deletions(-)
diff --git a/zh/_blog.yml b/zh/_blog.yml
index 54b66f4f34..64ffb706d6 100644
--- a/zh/_blog.yml
+++ b/zh/_blog.yml
@@ -434,6 +434,16 @@
- guide
- graphs
+- local: unity-in-spaces
+title: "如何在 🤗 Space 上托管 Unity 游戏"
+author: dylanebert
+thumbnail: /blog/assets/124_ml-for-games/unity-in-spaces-thumbnail.png
+date: April 21, 2023
+tags:
+ - community
+ - guide
+ - game-dev
+
- local: chinese-language-blog
title: "Hugging Face 中文博客正式发布!"
author: xianbao
diff --git a/zh/unity-in-spaces.md b/zh/unity-in-spaces.md
index 7b23644023..c9550a6cbb 100644
--- a/zh/unity-in-spaces.md
+++ b/zh/unity-in-spaces.md
@@ -5,17 +5,18 @@ authors:
- user: dylanebert
translators:
- user: SuSung-boy
+- user: zhongdongy
+ proofreader: true
---
-如何在 🤗 Space 上托管 Unity 游戏
+# 如何在 🤗 Space 上托管 Unity 游戏
-
+
+你知道吗?Hugging Face Space 可以托管自己开发的 Unity 游戏!惊不惊喜,意不意外?来了解一下吧!
-你知道吗?Hugging Face Space 可以托管自己开发的 Unity 游戏!惊不惊喜,意不意外?!来了解一下吧!
-
-Hugging Face Space 是一个能够以简单的方式来构建、托管和分享项目或应用样例的平台。虽然通常更多地是应用在机器学习样例中,不过实际上 Space 还可以用来托管 Unity 游戏,并且支持点击即玩。这里有一些游戏的 Space 示例:
+Hugging Face Space 是一个能够以简单的方式来构建、托管和分享项目或应用样例的平台。虽然通常更多地是应用在机器学习样例中,不过实际上 Space 还可以用来托管 Unity 游戏,并且支持点击即玩。这里有一些游戏的 Space 示例:
- [Huggy](https://huggingface.co/spaces/ThomasSimonini/Huggy)。Huggy 是一个基于强化学习构建的简易游戏,玩家可以点击鼠标扔出小木棍,来教宠物狗把木棍捡回来
- [农场游戏](https://huggingface.co/spaces/dylanebert/FarmingGame)。农场游戏是我们在 [<五天创建一个农场游戏>](https://huggingface.co/blog/zh/ml-for-games-1) 系列中完成的游戏,玩家可以通过种植、收获和升级农作物来打造一个自己的繁荣农场
@@ -23,53 +24,53 @@ Hugging Face Space 是一个能够以简单的方式来构建、托管和分享
本文将详细介绍如何在 🤗 Space 上托管自己的 Unity 游戏。
-## 第一步:使用静态 HTML 模板创建 Space 应用
+## 第 1 步: 使用静态 HTML 模板创建 Space 应用
首先,导航至 [Hugging Face Spaces](https://huggingface.co/new-space) 页面,创建一个新的 Space 应用。
-
+
选择 “静态 HTML” 模板,并为该 Space 取个名字,然后点击创建 Space。
-
+
-## 第 2 步:使用 Git 克隆 Space 库到本地
+## 第 2 步: 使用 Git 克隆 Space 库到本地
-使用 Git 将上一步创建的 Space 库克隆到本地。克隆命令如下:
+使用 Git 将上一步创建的 Space 库克隆到本地。克隆命令如下:
```
git clone https://huggingface.co/spaces/{your-username}/{your-space-name}
```
-## 第 3 步:打开 Unity 项目
+## 第 3 步: 打开 Unity 项目
-打开你希望在 🤗 Space 上托管的 Unity 项目。
+打开你希望在 🤗 Space 上托管的 Unity 项目
-
+
-## 第 4 步:将构建目标切换为 WebGL
+## 第 4 步: 将构建目标切换为 WebGL
点击菜单栏的 `File > Build Settings`,将构建目标切换为 WebGL。
-
+
-## 第 5 步:打开 Player Settings 面板
+## 第 5 步: 打开 Player Settings 面板
在上一步打开的 Build Settings 窗口中,点击左下角的 “Player Settings” 按钮,打开 Player Settings 面板。
-
+
-## 第 6 步:(可选) 下载 Hugging Face Unity WebGL 模板
+## 第 6 步:(可选) 下载 Hugging Face Unity WebGL 模板
Hugging Face Unity WebGL 模板可以使得你制作的游戏在 🤗 Space 上展示地更加美观。可以点击 [此处](https://github.com/huggingface/Unity-WebGL-template-for-Hugging-Face-Spaces) 下载模板库,并将其放到你的游戏项目目录,然后在 Player Settings 面板中将 WebGL 模板切换为 Hugging Face 即可。
@@ -77,44 +78,44 @@ Hugging Face Unity WebGL 模板可以使得你制作的游戏在 🤗 Space 上
-
+
-## 第 7 步:禁用压缩
+## 第 7 步: 禁用压缩
在 Player Settings 面板中点击 “Publishing Settings”,将 Compression Format 改为 “Disabled” 来禁用压缩。
-
+
-## 第 8 步:构建游戏项目
+## 第 8 步: 构建游戏项目
返回 Build Settings 窗口,并点击 “Build” 按钮,选择一个本地目录来保存构建的游戏项目文件。按照前几步的设置,Unity 将会把项目构建为 WebGL。
-
+
-## 第 9 步:将构建完成的文件复制到 Space 库
+## 第 9 步: 将构建完成的文件复制到 Space 库
-构建过程完成之后,打开上一步中项目保存的本地目录,将该目录下的文件复制到 [第 2 步](#第-2-步使用-git-克隆-space-step-2-use-git-to-clone-the-space) 中克隆的 Space 库里。
+构建过程完成之后,打开上一步中项目保存的本地目录,将该目录下的文件复制到 [第 2 步](#第-2-步-使用-git-克隆-space-库到本地) 中克隆的 Space 库里。
-
+
-## 第 10 步:为大文件存储启用 Git-LFS
+## 第 10 步: 为大文件存储启用 Git-LFS
打开 Space 库, 在该目录执行以下命令来追踪构建的大型文件。
```
git lfs install
-git track Build/*
+git track Build/*
```
-## 第 11 步:Push 到 Hugging Face Space
+## 第 11 步: Push 到 Hugging Face Space
-最后,将本地的 Space 库的所有改动推送到 Hugging Face Space 上。执行以下 Git 命令即可完成推送:
+最后,将本地的 Space 库的所有改动推送到 Hugging Face Space 上。执行以下 Git 命令即可完成推送:
```
git add .
@@ -126,4 +127,4 @@ git push
至此,在 🤗 Space 上托管 Unity 游戏的所有步骤就都完成了。恭喜!现在请刷新你的 Space 页面,你就可以在 Space 上玩游戏了!
-希望本教程对你有所帮助。如果你有任何疑问,或想更多地参与到 Hugging Face 游戏相关的应用中,可以加入 Hugging Face 的官方 [Discord](https://hf.co/join/discord) 频道来与我们取得联系!
+希望本教程对你有所帮助。如果你有任何疑问,或想更多地参与到 Hugging Face 游戏相关的应用中,可以加入 Hugging Face 的官方 [Discord](https://hf.co/join/discord) 频道来与我们取得联系!
\ No newline at end of file
From 9536776e8b86044eb974a1803fc700a1189a51be Mon Sep 17 00:00:00 2001
From: Shiliang Chen <36809537+csl122@users.noreply.github.com>
Date: Mon, 8 May 2023 10:50:39 +0100
Subject: [PATCH 23/55] fix(annotated-diffusion.md): fix image shape desc in
PIL and Tensor (#1080)
modifiy the comment after ToTensor with the correct image shape CHW
---
annotated-diffusion.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/annotated-diffusion.md b/annotated-diffusion.md
index db72065d72..4ee958b770 100644
--- a/annotated-diffusion.md
+++ b/annotated-diffusion.md
@@ -595,7 +595,7 @@ from PIL import Image
import requests
url = 'http://images.cocodataset.org/val2017/000000039769.jpg'
-image = Image.open(requests.get(url, stream=True).raw)
+image = Image.open(requests.get(url, stream=True).raw) # PIL image of shape HWC
image
```
@@ -616,7 +616,7 @@ image_size = 128
transform = Compose([
Resize(image_size),
CenterCrop(image_size),
- ToTensor(), # turn into Numpy array of shape HWC, divide by 255
+ ToTensor(), # turn into torch Tensor of shape CHW, divide by 255
Lambda(lambda t: (t * 2) - 1),
])
From d1fad90e0184cb53ebc3fa4b6435ed2f07e63f7d Mon Sep 17 00:00:00 2001
From: Alara Dirik <8944735+alaradirik@users.noreply.github.com>
Date: Mon, 8 May 2023 14:41:38 +0300
Subject: [PATCH 24/55] Add text-to-video blog (#1058)
Adds an overview of text-to-video generative models, task specific challenges, datasets, and more.
Co-authored-by: Omar Sanseviero
Co-authored-by: amyeroberts <22614925+amyeroberts@users.noreply.github.com>
---
_blog.yml | 15 +++-
assets/140_text-to-video/thumbnail.png | Bin 0 -> 536697 bytes
text-to-video.md | 117 +++++++++++++++++++++++++
3 files changed, 131 insertions(+), 1 deletion(-)
create mode 100644 assets/140_text-to-video/thumbnail.png
create mode 100644 text-to-video.md
diff --git a/_blog.yml b/_blog.yml
index d46db0c61f..1f05900f0a 100644
--- a/_blog.yml
+++ b/_blog.yml
@@ -2041,7 +2041,7 @@
- community
- local: tf_tpu
- title: "Training a language model with 🤗 Transformers using TensorFlow and TPUs"
+ title: "Training a language model with 🤗 Transformers using TensorFlow and TPUs"
author: rocketknight1
thumbnail: /blog/assets/tf_tpu_training/thumbnail.png
date: April 27, 2023
@@ -2079,3 +2079,16 @@
- nlp
- community
- research
+
+- local: text-to-video
+ title: "A Dive into Text-to-Video Models"
+ author: adirik
+ thumbnail: /blog/assets/140_text-to-video/thumbnail.png
+ date: May 8, 2023
+ tags:
+ - multi-modal
+ - cv
+ - guide
+ - diffusion
+ - text-to-image
+ - text-to-video
diff --git a/assets/140_text-to-video/thumbnail.png b/assets/140_text-to-video/thumbnail.png
new file mode 100644
index 0000000000000000000000000000000000000000..08d0dc99ade17abf578dda7944288213e67c9678
GIT binary patch
literal 536697
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