[技術筆記]Stable Diffusion 閱讀營第一週筆記

簡單使用Diffusion模型與生成圖片

Posted by 李定宇 on Wednesday, October 18, 2023

week-1

擴散模型筆記

什麼是擴散模型?

一杯水被滴入一滴墨,要計算一開始墨的擴散,是十分困難的;但在一段時間後,墨在水中形成均勻分佈,這時計算墨在水中的分佈機率就十分簡單。擴散模型就是基於這樣一個「從混亂到有序」的機率分佈,然後「反過來」、訓練模型回推。

最早的擴散模型為DDPM(Denosing Diffusion Probabilistic Model),其假設擴散的過程是一個馬爾可夫過程(每一個時間步的機率分佈是由上次一個時間步的狀態加上當前時間步的高斯噪聲得到),而逆過程是高斯分佈。

TODO:數學算式

擴散模型和其他模型的差別?

以下是目前查到

  • GANs(Generative Adversarial Networks):生成對抗網絡。GANs由兩個部分組成:生成器和鑑別器,生成器會生成「偽造圖片」,然後鑑別器會鑑別真實圖片和偽造圖片。透過這種對抗過程,生成器會逐漸學會越來越逼真的圖片。
  • Flow-based models:核心思想是建立一個可逆的變換,將已知的簡單分佈(如高斯分佈)映射到複雜的數據分佈。由於這種變換是可逆的,所以可以輕易地在兩個分佈之間相互轉換。這種模型的一個重要特點是它可以直接計算生成數據的確切概率。
  • VAEs(Variational Autoencoders ):它是使用「變分推理」的方式來學會一張圖片的表示、且學會如何用這個表示來生成圖片。
  • Auto-Regressive Models :這算是一種分類,如PixelRNN和PixelCNN,它們是一個一個生成像素,並且是考慮之前的像素來生成接下來的像素
  • Transformer-based Models: 主要是受NLP的transformer影響,也用其來訓練預處理模型,並生成圖片(如 OpenAI的 DallE系列)

而擴散模型的主要優勢,是「能夠生成質量足夠高的圖片」、以及「可解釋性」,由於是以馬爾可夫鏈計算高斯分佈,所以能夠比較好的評估機率、以及解釋模型。

如何用他人寫好的模型來生成圖片?

一個是直接用別人寫好的服務,一個是利用HuggingFace上別人以開源的模型,來進行生成。

以下是一個在Colab環境中、使用StableAI的模型來簡單實現:

  • 安裝依賴:

    !pip install -qq -qq -U diffusers datasets transformers accelerate ftfy pyarrow==9.0.0 gradio
    
  • 登入HuggingFace

    from huggingface_hub import notebook_login
    
    notebook_login()
    
  • 導入庫,並選擇模型

    from PIL import Image
    import numpy as np
    import torch
    from diffusers import StableDiffusionPipeline
    
    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
    
    # 使用 stabilityai 的model
    model_id = "stabilityai/stable-diffusion-2"
    
    # Load the pipeline
    pipe = StableDiffusionPipeline.from_pretrained(model_id, torch_dtype=torch.float16).to(
    device
    )
    
  • 設定Prompt並生成圖片

    prompt = "an apple in the outer space"
    image = pipe(prompt, num_inference_steps=100, guidance_scale=7.5).images[0]
    
    # num_inference_steps 擴散步數。步數多,圖片質量越好
    # guidance_scale 控制prompt對圖片生成的指導作用
    image
    

以上的範例,最主要的就是pipe = StableDiffusionPipeline.from_pretrained(model_id, torch_dtype=torch.float16).to( device ) 這一段就是載入 StableDiffusion 類型的預訓練模型,

如何自己訓練一個擴散模型

簡單過程

  • 模型的建立與訓練
    • 使用 UNet2DModel 建立一個 U-Net 模型。其為用於圖像去噪和圖像分割的深度學習結構
    • 設置 DDPMScheduler 用於管理噪音的添加
    • 在迴圈中訓練模型,讓模型嘗試從加噪的的圖像中還原原始圖像
  • 使用模型
    • 訓練過後的模型,就可以給特定的圖像添加噪音,然後試圖中噪音中還原圖像。
    • 模型的「預測結果」,就是模型從加噪圖像還原的圖像
  • 保存和加載模型
    • 使用DDPMPipelinehuggingface_hub工具將訓練好的模型保存到Hugging Face Hub。
    • 然後就可以從Hugging Face Hub 加載該模型,使用它生成新圖像

其中,「利用prompt來生成圖片」是讓模型先有「隨機起點」的圖片,然後進行多次迭代(或者將前一張圖片進行輸入)、用當前step中的噪音來修改圖像

colab 示範

TODO

ChangeLog

  • 20231018-初稿