中文版擴散模型課程:第一單元
于 11 月底正式開課的擴散模型課程正在火熱進行中,在中國社區(qū)成員們的幫助下,我們組織了「抱抱臉中文本地化志愿者小組」并完成了擴散模型課程的中文翻譯,感謝 @darcula1993、@XhrLeokk、@hoi2022、@SuSung-boy 對課程的翻譯!
第一單元:擴散模型簡介
歡迎來到 Hugging Face 擴散模型課程第一單元!在本單元中,你將學習有關擴散模型如何工作的基礎知識,以及如何使用 ?? diffusers 庫。

什么是擴散模型?
擴散模型是「生成模型」算法家族的新成員通過學習給定的訓練樣本,生成模型可以學會如何?生成?數(shù)據,比如生成圖片或者聲音。一個好的生成模型能生成一組?樣式不同?的輸出。這些輸出會與訓練數(shù)據相似,但不是一模一樣的副本。擴散模型如何實現(xiàn)這一點?為了便于說明,讓我們先看看圖像生成的案例。

擴散模型成功的秘訣在于擴散過程的迭代本質。最先生成的只是一組隨機噪聲,但經過若干步驟逐漸改善,有意義的圖像將最終會出現(xiàn)。在每一步中,模型都會估計如何從當前的輸入生成完全去噪的結果。因為我們在每一步都只做了一個小小的變動,所以在早期階段(預測最終輸出實際上非常困難),這個估計中的任何 error 都可以在以后的更新中得到糾正。
與其他類型的生成模型相比,訓練擴散模型相對較為容易。我們只需要重復以下步驟即可:
從訓練數(shù)據中加載一些圖像
添加不同級別的噪聲。請記住,我們希望模型在面對添加了極端噪聲和幾乎沒有添加噪聲的帶噪圖像時,都能夠很好地估計如何「修復」(去噪)。
將帶噪輸入送入模型中
評估模型對這些輸入進行去噪的效果
使用此信息更新模型權重
為了用訓練好的模型生成新的圖像,我們從完全隨機的輸入開始,反復將其輸入模型,每次根據模型預測進行少量更新。我們之后會學到有許多采樣方法試圖簡化這個過程,以便我們可以用盡可能少的步驟生成好的圖像。
我們將在第一單元的實踐筆記本中詳細介紹這些步驟。在第二單元中,我們將了解如何修改此過程,來通過額外的條件(例如類標簽)或使用指導等技術來增加對模型輸出的額外控制。第三單元和第四單元將探索一種非常強大的擴散模型,稱為穩(wěn)定擴散 (stable diffusion),它可以生成給定文本描述的圖像。
實踐筆記本
到這里,您已經足夠了解如何開始使用附帶的筆記本了!這里的兩個筆記本以不同的方式表達了相同的想法。
在?Diffuser 介紹?這個 Notebook 中,我們使用?diffusers
?庫中的構造模塊顯示了與上述不同的步驟。你將很快看到如何根據您選擇的任何數(shù)據創(chuàng)建、訓練和采樣您自己的擴散模型。在筆記本結束時,您將能夠閱讀和修改示例訓練腳本,以訓練擴散模型,并將其與全世界共同分享!本筆記本還介紹了與本單元相關的主要練習,在這里,我們將共同嘗試為不同規(guī)模的擴散模型找出好的「訓練腳本」—— 請參閱下一節(jié)了解更多信息。
在?擴散模型從零到一?這個?Notebook?中,我們展示了相同的步驟(向數(shù)據添加噪聲、創(chuàng)建模型、訓練和采樣),并盡可能簡單地在 PyTorch 中從頭開始實現(xiàn)。然后,我們將這個「玩具示例」與?diffusers
?版本進行比較,并關注兩者的區(qū)別以及改進之處。這里的目標是熟悉不同的組件和其中的設計決策,以便在查看新的實現(xiàn)時能夠快速確定關鍵思想。我們也會在接下來的推送中發(fā)布這個 Notebook 的內容。
實踐和分享
現(xiàn)在,你已經掌握了基本知識,可以開始訓練你自己的擴散模型了!Diffuser 介紹?筆記本的末尾有一些小提示,希望您能與社區(qū)分享您的成果、訓練腳本和發(fā)現(xiàn),以便我們能夠一起找出訓練這些模型的最佳方法。
一些額外的材料
《Hugging Face 博客: 帶注釋的擴散模型》是對 DDPM 背后的代碼和理論的非常深入的介紹,其中包括數(shù)學和顯示了所有不同的組件的代碼。它還鏈接了一些論文供進一步閱讀:
https://hf.co/blog/annotated-diffusionHugging Face 文檔: 無條件圖像生成 (Unconditional Image-Generation),包含了有關如何使用官方訓練示例腳本訓練擴散模型的一些示例,包括演示如何創(chuàng)建自己的數(shù)據集的代碼:
https://hf.co/docs/diffusers/training/unconditional_trainingAI Coffee Break video on Diffusion Models:
https://www.youtube.com/watch?v=344w5h24-h8Yannic Kilcher Video on DDPMs:
https://www.youtube.com/watch?v=W-O7AZNzbzQ
Diffuser 介紹 Notebook
在這個 Notebook 里,你將訓練你的第一個擴散模型來?生成美麗的蝴蝶的圖片 ??。在此過程中,你將了解 ?? Diffuers 庫,它將為我們稍后將在課程中介紹的更高級的應用程序提供良好的基礎
讓我們開始吧!
你將學習到
看到一個強大的自定義擴散模型管道 (并了解到如何制作一個自己的版本)
通過以下方式創(chuàng)建你自己的迷你管道:
回顧擴散模型背后的核心思想
從 Hub 中加載數(shù)據進行訓練
探索如何使用 scheduler 將噪聲添加到數(shù)據中
創(chuàng)建和訓練一個 UNet 模型
將各個組件拼裝在一起來形成一個工作管道 (working pipelines)
編輯并運行一個腳本,用于初始化一個較長的訓練,該腳本將處理
使用 Accelerate 來進行多 GPU 加速訓練
實驗日志記錄以跟蹤關鍵統(tǒng)計數(shù)據
將最終的模型上傳到 Hugging Face Hub
?如果你有任何問題,請發(fā)布在 Hugging Face 的 Discord 服務器#diffusion-models-class
頻道中。你可以在這里完成注冊:
https://hf.co/join/discord
預備知識
在進入 Notebook 之前,你需要:
?? 閱讀完上面的的材料
?? 在 Hugging Face Hub 上創(chuàng)建一個賬戶。你可以在這里完成注冊:
https://hf.co/join
步驟 1: 設置
運行以下單元以安裝 diffusers 庫以及一些其他要求:
%pip?install?-qq?-U?diffusers?datasets?transformers?accelerate?ftfy?pyarrow
接下來,請前往 https://huggingface.co/settings/tokens 創(chuàng)建具有寫權限的訪問令牌:

你可以使用命令行來通過此令牌登錄 (huggingface-cli login
) 或者運行以下單元來登錄:
然后你需要安裝 Git LFS 來上傳模型檢查點:
最后,讓我們導入將要使用的庫,并定義一些方便函數(shù),稍后我們將會在 Notebook 中使用這些函數(shù):
好了,我們都準備好了!
Dreambooth:即將到來的巔峰
如果你在過去幾個月里看過人工智能相關的社交媒體,你就會聽說過 Stable Diffusion 模型。這是一個強大的文本條件隱式擴散模型(別擔心,我們將會學習這些概念)。但它有一個缺點:它不知道你或我長什么樣,除非我們足夠出名以至于互聯(lián)網上發(fā)布我們的照片。
Dreambooth 允許我們創(chuàng)建自己的模型變體,并對特定的面部、對象或樣式有一些額外的了解。Corridor Crew 制作了一段出色的視頻,用一致的任務形象來講故事,這是一個很好的說明了這種技術的能力的例子:
這是一個使用了一個名為「Mr Potato Head」的模型作為例子。該模型的訓練使用了 5 張著名的兒童玩具 "Mr Potato Head"的照片。模型地址:
https://hf.co/sd-dreambooth-library/mr-potato-head
首先,讓我們來加載這個管道。這些代碼會自動從 Hub 下載模型權重等需要的文件。由于這個只有一行的 demo 需要下載數(shù) GB 的數(shù)據,因此你可以跳過此單元格,只需欣賞樣例輸出即可!
Fetching 15 files: ? 0%| ? ? ? ? ?| 0/15 [00:00<?, ?it/s]
管道加載完成后,我們可以使用以下命令生成圖像:
練習:?你可以使用不同的提示 (prompt) 自行嘗試。在這個 demo 中,sks
?是一個新概念的唯一標識符 (UID) - 那么如果把它留空的話會發(fā)生什么事呢?你還可以嘗試改變?num_inference_steps
?和?guidance_scale
。這兩個參數(shù)分別代表了采樣步驟的數(shù)量(試試最多可以設為多低?)和模型將花多大的努力來嘗試匹配提示。
這條神奇的管道里有很多事情!課程結束時,你將知道這一切是如何運作的?,F(xiàn)在,讓我們看看如何從頭開始訓練擴散模型。
MVP (最簡可實行管道)
?? Diffusers 的核心 API 被分為三個主要部分:
管道: 從高層出發(fā)設計的多種類函數(shù),旨在以易部署的方式,能夠做到快速通過主流預訓練好的擴散模型來生成樣本。
模型: 訓練新的擴散模型時用到的主流網絡架構,舉個例子?UNet:
https://arxiv.org/abs/1505.04597管理器 (or 調度器): 在?推理?中使用多種不同的技巧來從噪聲中生成圖像,同時也可以生成在?訓練?中所需的帶噪圖像。
管道對于末端使用者來說已經非常棒,但你既然已經參加了這門課程,我們就索性認為你想了解更多其中的奧秘!在此篇筆記結束之后,我們會來構建屬于你自己,能夠生成小蝴蝶圖片的管道。下面這里會是最終的結果:
也許這看起來并不如 DreamBooth 所展示的樣例那樣驚艷,但要知道我們在訓練這些圖畫時只用了不到訓練穩(wěn)定擴散模型用到數(shù)據的 0.0001%。說到模型訓練,從引入介紹直到本單元,訓練一個擴散模型的流程看起來像是這樣:
從訓練集中加載一些圖像
加入噪聲,從不同程度上
把帶了不同版本噪聲的數(shù)據送進模型
評估模型在對這些數(shù)據做增強去噪時的表現(xiàn)
使用這個信息來更新模型權重,然后重復此步驟
我們會在接下來幾節(jié)中逐一實現(xiàn)這些步驟,直至訓練循環(huán)可以完整的運行,在這之后我們會來探索如何使用訓練好的模型來生成樣本,還有如何封裝模型到管道中來輕松的分享給別人,下面我們來從數(shù)據入手吧。
步驟 2:下載一個訓練數(shù)據集
在這個例子中,我們會用到一個來自 Hugging Face Hub 的圖像集。具體來說,是個 1000 張蝴蝶圖像收藏集。這是個非常小的數(shù)據集,我們這里也同時包含了已被注釋的內容指向一些規(guī)模更大的選擇。如果你想使用你自己的圖像收藏,你也可以使用這里被注釋掉的示例代碼,從一個指定的文件夾來裝載圖片。
圖像集地址:
https://hf.co/datasets/huggan/smithsonian_butterflies_subset
我們可以從中取出一批圖像數(shù)據來看一看他們是什么樣子:
/tmp/ipykernel_4278/3975082613.py:3: DeprecationWarning: NEAREST is deprecated and will be removed in Pillow 10 (2023-07-01). Use Resampling.NEAREST or Dither.NONE instead.
show_images (xb).resize ((8 * 64, 64), resample=Image.NEAREST)

我們在此篇 Notebook 中使用一個只有 32 像素的小圖片集來保證訓練時長是可控的。
步驟 3:定義管理器
我們的訓練計劃是,取出這些輸入圖片然后對它們增添噪聲,在這之后把帶噪的圖片送入模型。在推理階段,我們將用模型的預測值來不斷迭代去除這些噪點。在?diffusers
?中,這兩個步驟都是由?管理器(調度器)?來處理的。
噪聲管理器決定在不同的迭代周期時分別加入多少噪聲。我們可以這樣創(chuàng)建一個管理器,是取自于訓練并能取樣 'DDPM' 的默認配置。基于此篇論文 Denoising Diffusion Probabalistic Models: https://arxiv.org/abs/2006.11239
DDPM 論文這樣來描述一個損壞過程,為每一個「迭代周期」 (timestep) 增添一點少量的噪聲。設在某個迭代周期有?, 我們可以得到它的下一個版本??(比之前更多一點點噪聲):

這就是說,我們取?, 給他一個??的系數(shù),然后加上帶有??系數(shù)的噪聲。這里??是根據一些管理器來為每一個 t 設定的,來決定每一個迭代周期中添加多少噪聲?,F(xiàn)在,我們不想把這個推演進行 500 次來得到?,所以我們用另一個公式來根據給出的??計算得到任意 t 時刻的?:

數(shù)學符號看起來總是很可怕!好在有管理器來為我們完成這些運算。我們可以畫出??(標記為sqrt_alpha_prod
) 和??(標記為sqrt_one_minus_alpha_prod
) 來看一下輸入 (x) 與噪聲是如何在不同迭代周期中量化和疊加的:
練習:?你可以探索一下使用不同的?beta_start
?時曲線是如何變化的,beta_end
?與?beta_schedule
?可以通過以下注釋內容來修改:
不論你選擇了哪一個管理器 (調度器),我們現(xiàn)在都可以使用?noise_scheduler.add_noise
?功能來添加不同程度的噪聲,就像這樣:
再來,在這里探索使用這里不同噪聲管理器和預設參數(shù)帶來的效果。這個視頻很好的解釋了一些上述數(shù)學運算的細節(jié),同時也是對此類概念的一個很好引入介紹。視頻地址:
https://www.youtube.com/watch?v=fbLgFrlTnGU
步驟 4:定義模型
現(xiàn)在我們來到了核心部分:模型本身。
大多數(shù)擴散模型使用的模型結構都是一些 U-net 的變形 (https://arxiv.org/abs/1505.04597),也是我們在這里會用到的結構。
概括來說:
輸入模型中的圖片經過幾個由 ResNetLayer 構成的層,其中每層都使圖片尺寸減半。
之后在經過同樣數(shù)量的層把圖片升采樣。
其中還有對特征在相同位置的上、下采樣層殘差連接模塊。
模型一個關鍵特征既是,輸出圖片尺寸與輸入圖片相同,這正是我們這里需要的。
Diffusers 為我們提供了一個易用的UNet2DModel
類,用來在 PyTorch 創(chuàng)建所需要的結構。
我們來使用 U-net 為我們生成目標大小的圖片吧。注意這里down_block_types
對應下采樣模塊 (上圖中綠色部分), 而up_block_types
對應上采樣模塊 (上圖中紅色部分):
當在處理更高分辨率的輸入時,你可能想用更多層的下、上采樣模塊,讓注意力層只聚焦在最低分辨率(最底)層來減少內存消耗。我們在之后會討論該如何實驗來找到最適用與你手頭場景的配置方法。
我們可以通過輸入一批數(shù)據和隨機的迭代周期數(shù)來看輸出是否與輸入尺寸相同:
在下一步中,我們來看如何訓練這個模型。
步驟 5:創(chuàng)建訓練循環(huán)
終于可以訓練了!下面這是 PyTorch 中經典的優(yōu)化迭代循環(huán),在這里一批一批的送入數(shù)據然后通過優(yōu)化器來一步步更新模型參數(shù) - 在這個樣例中我們使用學習率為 0.0004 的 AdamW 優(yōu)化器。
對于每一批的數(shù)據,我們要
隨機取樣幾個迭代周期
根據預設為數(shù)據加入噪聲
把帶噪數(shù)據送入模型
使用 MSE 作為損失函數(shù)來比較目標結果與模型預測結果(在這里是加入噪聲的場景)
通過
loss.backward()
與optimizer.step()
來更新模型參數(shù)
在這個過程中我們記錄 Loss 值用來后續(xù)的繪圖。
NB: 這段代碼大概需 10 分鐘來運行 - 你也可以跳過以下兩塊操作直接使用預訓練好的模型。供你選擇,你可以探索下通過縮小模型層中的通道數(shù)會對運行速度有多少提升。
官方擴散模型示例訓練了在更高分辨率數(shù)據集上的一個更大的模型,這也是一個極為精簡訓練循環(huán)的優(yōu)秀示例,示例地址:
https://colab.research.google.com/github/huggingface/notebooks/blob/main/diffusers/training_example.ipynb
Epoch:5, loss: 0.16273280512541533
Epoch:10, loss: 0.11161588924005628
Epoch:15, loss: 0.10206522420048714
Epoch:20, loss: 0.08302505919709802
Epoch:25, loss: 0.07805309211835265
Epoch:30, loss: 0.07474562455900013
繪制 loss 曲線,我們能看到模型在一開始快速的收斂,接下來以一個較慢的速度持續(xù)優(yōu)化(我們用右邊 log 坐標軸的視圖可以看的更清楚):
[<matplotlib.lines.Line2D at 0x7f40fc40b7c0>]

你可以選擇運行上面的代碼,也可以這樣通過管道來調用模型:
步驟 6:生成圖像
我們怎么從這個模型中得到圖像呢?
方法 1:建立一個管道:
0%| ? ? ? ? ?| 0/1000 [00:00<?, ?it/s]

我們可以在本地文件夾這樣保存一個管道:
檢查文件夾的內容:
model_index.json ?scheduler ?unet
這里scheduler
與unet
子文件夾中包含了生成圖像所需的全部組件。比如,在unet
文件中能看到模型參數(shù) (diffusion_pytorch_model.bin
) 與描述模型結構的配置文件。
config.json ?diffusion_pytorch_model.bin
以上,這些文件包含了重新建立一個管道的全部內容。你可以手動把它們上傳到 hub 來與他人分享你制作的管道,或使用下一節(jié)的 API 方法來記載。
方法 2:寫一個取樣循環(huán)
如果你去查看了管道中的 forward 方法,你可以看到在運行image_pipe()
時發(fā)生了什么:
從隨機噪聲開始,遍歷管理器的迭代周期來看從最嘈雜直到最微小的噪聲變化,基于模型的預測一步步減少一些噪聲:
noise_scheduler.step()
?函數(shù)相應做了?sample
(取樣)時的數(shù)學運算。其實有很多取樣的方法 - 在下一個單元我們將看到在已有模型的基礎上如何換一個不同的取樣器來加速圖片生成,也會講到更多從擴散模型中取樣的背后原理。
步驟 7:把你的模型 Push 到 Hub
在上面的例子中我們把管道保存在了本地。把模型 push 到 hub 上,我們會需要建立模型和相應文件的倉庫名。我們根據你的選擇(模型 ID)來決定倉庫的名字(大膽的去替換掉model_name
吧;需要包含你的用戶名,get_full_repo_name()
會幫你做到):
'https://huggingface.co/lewtun/sd-class-butterflies-32/blob/main/model_index.json'
最后一件事是創(chuàng)建一個超棒的模型卡,如此,我們的蝴蝶生成器可以輕松的在 Hub 上被找到(請在描述中隨意發(fā)揮?。?/p>
Fetching 4 files: ? 0%| ? ? ? ? ?| 0/4 [00:00<?, ?it/s]
0%| ? ? ? ? ?| 0/1000 [00:00<?, ?it/s]

太棒了,成功了!
使用 ?? Accelerate 來進行大規(guī)模使用
這篇筆記是用來教學,為此我盡力保證代碼的簡潔與輕量化。但也因為這樣,我們也略去了一些內容你也許在使用更多數(shù)據訓練一個更大的模式時,可能所需要用到的內容,如多塊 GPU 支持,進度記錄和樣例圖片,用于支持更大 batchsize 的導數(shù)記錄功能,自動上傳模型等等。好在這些功能大多數(shù)在這個示例代碼中包含 here.
你可以這樣下載該文件:
打開文件,你就可以看到模型是怎么定義的,以及有哪些可選的配置參數(shù)。我使用如下命令運行了該代碼:
如之前一樣,把模型 push 到 hub,并且創(chuàng)建一個超酷的模型卡(按你的想法隨意填寫?。?/p>
'https://huggingface.co/lewtun/sd-class-butterflies-64/blob/main/README.md'
大概 45 分鐘之后,得到這樣的結果:
0%| ? ? ? ? ?| 0/1000 [00:00<?, ?it/s]
練習:?看看你能不能找到訓練出在短時內能得到滿意結果的模型訓練設置參數(shù),并與社群分享你的發(fā)現(xiàn)。閱讀這些腳本看看你能不能理解它們,如果遇到了一些看上去令人迷惑的地方,請向大家提問來尋求解釋。
更高階的探索之路
希望這些能夠讓你初步了解可以使用 ?? Diffusers library 來做什么!可能一些后續(xù)的步驟是這樣:
嘗試在新數(shù)據集上訓練一個無限制的擴散模型 —— 如果你能直接自己完成那就太好了!你可以在 Hub 上的HugGan 社區(qū)小組頁面找到一些能完成這個任務的超棒圖像數(shù)據集。如果你不想等待模型訓練太久的話,一定記得對圖片做下采樣!
創(chuàng)建自己的圖片數(shù)據集:
https://hf.co/docs/datasets/image_dataseHugGan 社區(qū)小組頁面:
https://hf.co/huggan試試用 DreamBooth 來創(chuàng)建你自己定制的擴散模型管道,請查看下面兩個鏈接:Dreambooth Training Space 應用:
https://hf.co/spaces/multimodalart/dreambooth-trainingDreambooth fine-tuning for Stable Diffusion using d??ffusers 這個 Notebook:
https://colab.research.google.com/github/huggingface/notebooks/blob/main/diffusers/sd_dreambooth_training.ipynb修改訓練腳本來探索使用不同的 UNet 超參數(shù)(層數(shù)深度,通道數(shù)等等),不同的噪聲管理器等等。
接下來我們將發(fā)布第一單元課程的第二個 Notebook 內容,敬請關注!
第一單元譯者:
@darcula1993、@XhrLeokk:魔都強人工智能孵化者,二里街調參記錄保持人,一切興趣使然的 AIGC 色圖創(chuàng)作家的庇護者,圖靈神在五角場的唯一指定路上行走。
感謝茶葉蛋蛋對本文貢獻設計素材!
再次感謝社區(qū)成員們對本課程的貢獻,歡迎通過鏈接加入我們的本地化小組與大家共同交流:
https://bit.ly/3G40j6U