|
<!--Copyright 2024 The HuggingFace Team. All rights reserved. |
|
|
|
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with |
|
the License. You may obtain a copy of the License at |
|
|
|
http://www.apache.org/licenses/LICENSE-2.0 |
|
|
|
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on |
|
an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the |
|
specific language governing permissions and limitations under the License. |
|
--> |
|
|
|
# μ¬ν κ°λ₯ν νμ΄νλΌμΈ μμ±νκΈ° |
|
|
|
[[open-in-colab]] |
|
|
|
μ¬νμ±μ ν
μ€νΈ, κ²°κ³Ό μ¬ν, κ·Έλ¦¬κ³ [μ΄λ―Έμ§ νλ¦¬ν° λμ΄κΈ°](resuing_seeds)μμ μ€μν©λλ€. |
|
κ·Έλ¬λ diffusion λͺ¨λΈμ 무μμμ±μ λ§€λ² λͺ¨λΈμ΄ λμκ° λλ§λ€ νμ΄νλΌμΈμ΄ λ€λ₯Έ μ΄λ―Έμ§λ₯Ό μμ±ν μ μλλ‘ νλ μ΄μ λ‘ νμν©λλ€. |
|
νλ«νΌ κ°μ μ ννκ² λμΌν κ²°κ³Όλ₯Ό μ»μ μλ μμ§λ§, νΉμ νμ© λ²μ λ΄μμ λ¦΄λ¦¬μ€ λ° νλ«νΌ κ°μ κ²°κ³Όλ₯Ό μ¬νν μλ μμ΅λλ€. |
|
κ·ΈλΌμλ diffusion νμ΄νλΌμΈκ³Ό 체ν¬ν¬μΈνΈμ λ°λΌ νμ© μ€μ°¨κ° λ¬λΌμ§λλ€. |
|
|
|
diffusion λͺ¨λΈμμ 무μμμ±μ μμ²μ μ μ΄νκ±°λ κ²°μ λ‘ μ μκ³ λ¦¬μ¦μ μ¬μ©νλ λ°©λ²μ μ΄ν΄νλ κ²μ΄ μ€μν μ΄μ μ
λλ€. |
|
|
|
<Tip> |
|
|
|
π‘ Pytorchμ [μ¬νμ±μ λν μ μΈ](https://pytorch.org/docs/stable/notes/randomness.html)λ₯Ό κΌ μ½μ΄λ³΄κΈΈ μΆμ²ν©λλ€: |
|
|
|
> μμ νκ² μ¬νκ°λ₯ν κ²°κ³Όλ Pytorch λ°°ν¬, κ°λ³μ μΈ μ»€λ°, νΉμ λ€λ₯Έ νλ«νΌλ€μμ 보μ₯λμ§ μμ΅λλ€. |
|
> λν, κ²°κ³Όλ CPUμ GPU μ€νκ°μ μ¬μ§μ΄ κ°μ seedλ₯Ό μ¬μ©ν λλ μ¬ν κ°λ₯νμ§ μμ μ μμ΅λλ€. |
|
|
|
</Tip> |
|
|
|
## 무μμμ± μ μ΄νκΈ° |
|
|
|
μΆλ‘ μμ, νμ΄νλΌμΈμ λ
Έμ΄μ¦λ₯Ό μ€μ΄κΈ° μν΄ κ°μ°μμ λ
Έμ΄μ¦λ₯Ό μμ±νκ±°λ μ€μΌμ€λ§ λ¨κ³μ λ
Έμ΄μ¦λ₯Ό λνλ λ±μ λλ€ μνλ§ μ€νμ ν¬κ² μμ‘΄ν©λλ€, |
|
|
|
[DDIMPipeline](https://huggingface.co/docs/diffusers/v0.18.0/en/api/pipelines/ddim#diffusers.DDIMPipeline)μμ λ μΆλ‘ λ¨κ³ μ΄νμ ν
μ κ°μ μ΄ν΄λ³΄μΈμ: |
|
|
|
```python |
|
from diffusers import DDIMPipeline |
|
import numpy as np |
|
|
|
model_id = "google/ddpm-cifar10-32" |
|
|
|
# λͺ¨λΈκ³Ό μ€μΌμ€λ¬λ₯Ό λΆλ¬μ€κΈ° |
|
ddim = DDIMPipeline.from_pretrained(model_id) |
|
|
|
# λ κ°μ λ¨κ³μ λν΄μ νμ΄νλΌμΈμ μ€ννκ³ numpy tensorλ‘ κ°μ λ°ννκΈ° |
|
image = ddim(num_inference_steps=2, output_type="np").images |
|
print(np.abs(image).sum()) |
|
``` |
|
|
|
μμ μ½λλ₯Ό μ€ννλ©΄ νλμ κ°μ΄ λμ€μ§λ§, λ€μ μ€ννλ©΄ λ€λ₯Έ κ°μ΄ λμ΅λλ€. λ¬΄μ¨ μΌμ΄ μΌμ΄λκ³ μλ κ±ΈκΉμ? |
|
|
|
νμ΄νλΌμΈμ΄ μ€νλ λλ§λ€, [torch.randn](https://pytorch.org/docs/stable/generated/torch.randn.html)μ |
|
λ¨κ³μ μΌλ‘ λ
Έμ΄μ¦ μ κ±°λλ κ°μ°μμ λ
Έμ΄μ¦κ° μμ±νκΈ° μν λ€λ₯Έ λλ€ seedλ₯Ό μ¬μ©ν©λλ€. |
|
|
|
κ·Έλ¬λ λμΌν μ΄λ―Έμ§λ₯Ό μμ μ μΌλ‘ μμ±ν΄μΌ νλ κ²½μ°μλ CPUμμ νμ΄νλΌμΈμ μ€ννλμ§ GPUμμ μ€ννλμ§μ λ°λΌ λ¬λΌμ§λλ€. |
|
|
|
### CPU |
|
|
|
CPUμμ μ¬ν κ°λ₯ν κ²°κ³Όλ₯Ό μμ±νλ €λ©΄, PyTorch [Generator](https://pytorch.org/docs/stable/generated/torch.randn.html)λ‘ seedλ₯Ό κ³ μ ν©λλ€: |
|
|
|
```python |
|
import torch |
|
from diffusers import DDIMPipeline |
|
import numpy as np |
|
|
|
model_id = "google/ddpm-cifar10-32" |
|
|
|
# λͺ¨λΈκ³Ό μ€μΌμ€λ¬ λΆλ¬μ€κΈ° |
|
ddim = DDIMPipeline.from_pretrained(model_id) |
|
|
|
# μ¬νμ±μ μν΄ generator λ§λ€κΈ° |
|
generator = torch.Generator(device="cpu").manual_seed(0) |
|
|
|
# λ κ°μ λ¨κ³μ λν΄μ νμ΄νλΌμΈμ μ€ννκ³ numpy tensorλ‘ κ°μ λ°ννκΈ° |
|
image = ddim(num_inference_steps=2, output_type="np", generator=generator).images |
|
print(np.abs(image).sum()) |
|
``` |
|
|
|
μ΄μ μμ μ½λλ₯Ό μ€ννλ©΄ seedλ₯Ό κ°μ§ `Generator` κ°μ²΄κ° νμ΄νλΌμΈμ λͺ¨λ λλ€ ν¨μμ μ λ¬λλ―λ‘ νμ `1491.1711` κ°μ΄ μΆλ ₯λ©λλ€. |
|
|
|
νΉμ νλμ¨μ΄ λ° PyTorch λ²μ μμ μ΄ μ½λ μμ λ₯Ό μ€ννλ©΄ λμΌνμ§λ μλλΌλ μ μ¬ν κ²°κ³Όλ₯Ό μ»μ μ μμ΅λλ€. |
|
|
|
<Tip> |
|
|
|
π‘ μ²μμλ μλλ₯Ό λνλ΄λ μ μκ° λμ μ `Generator` κ°μ²΄λ₯Ό νμ΄νλΌμΈμ μ λ¬νλ κ²μ΄ μ½κ° λΉμ§κ΄μ μΌ μ μμ§λ§, |
|
`Generator`λ μμ°¨μ μΌλ‘ μ¬λ¬ νμ΄νλΌμΈμ μ λ¬λ μ μλ \λλ€μν\μ΄κΈ° λλ¬Έμ PyTorchμμ νλ₯ λ‘ μ λͺ¨λΈμ λ€λ£° λ κΆμ₯λλ μ€κ³μ
λλ€. |
|
|
|
</Tip> |
|
|
|
### GPU |
|
|
|
μλ₯Ό λ€λ©΄, GPU μμμ κ°μ μ½λ μμλ₯Ό μ€ννλ©΄: |
|
|
|
```python |
|
import torch |
|
from diffusers import DDIMPipeline |
|
import numpy as np |
|
|
|
model_id = "google/ddpm-cifar10-32" |
|
|
|
# λͺ¨λΈκ³Ό μ€μΌμ€λ¬ λΆλ¬μ€κΈ° |
|
ddim = DDIMPipeline.from_pretrained(model_id) |
|
ddim.to("cuda") |
|
|
|
# μ¬νμ±μ μν generator λ§λ€κΈ° |
|
generator = torch.Generator(device="cuda").manual_seed(0) |
|
|
|
# λ κ°μ λ¨κ³μ λν΄μ νμ΄νλΌμΈμ μ€ννκ³ numpy tensorλ‘ κ°μ λ°ννκΈ° |
|
image = ddim(num_inference_steps=2, output_type="np", generator=generator).images |
|
print(np.abs(image).sum()) |
|
``` |
|
|
|
GPUκ° CPUμ λ€λ₯Έ λμ μμ±κΈ°λ₯Ό μ¬μ©νκΈ° λλ¬Έμ λμΌν μλλ₯Ό μ¬μ©νλλΌλ κ²°κ³Όκ° κ°μ§ μμ΅λλ€. |
|
|
|
μ΄ λ¬Έμ λ₯Ό νΌνκΈ° μν΄ π§¨ Diffusersλ CPUμ μμμ λ
Έμ΄μ¦λ₯Ό μμ±ν λ€μ νμμ λ°λΌ ν
μλ₯Ό GPUλ‘ μ΄λμν€λ |
|
[randn_tensor()](https://huggingface.co/docs/diffusers/v0.18.0/en/api/utilities#diffusers.utils.randn_tensor)κΈ°λ₯μ κ°μ§κ³ μμ΅λλ€. |
|
`randn_tensor` κΈ°λ₯μ νμ΄νλΌμΈ λ΄λΆ μ΄λμμλ μ¬μ©λλ―λ‘ νμ΄νλΌμΈμ΄ GPUμμ μ€νλλλΌλ **νμ** CPU `Generator`λ₯Ό ν΅κ³Όν μ μμ΅λλ€. |
|
|
|
μ΄μ κ²°κ³Όμ ν¨μ¬ λ λ€κ°μμ΅λλ€! |
|
|
|
```python |
|
import torch |
|
from diffusers import DDIMPipeline |
|
import numpy as np |
|
|
|
model_id = "google/ddpm-cifar10-32" |
|
|
|
# λͺ¨λΈκ³Ό μ€μΌμ€λ¬ λΆλ¬μ€κΈ° |
|
ddim = DDIMPipeline.from_pretrained(model_id) |
|
ddim.to("cuda") |
|
|
|
#μ¬νμ±μ μν generator λ§λ€κΈ° (GPUμ μ¬λ¦¬μ§ μλλ‘ μ‘°μ¬νλ€!) |
|
generator = torch.manual_seed(0) |
|
|
|
# λ κ°μ λ¨κ³μ λν΄μ νμ΄νλΌμΈμ μ€ννκ³ numpy tensorλ‘ κ°μ λ°ννκΈ° |
|
image = ddim(num_inference_steps=2, output_type="np", generator=generator).images |
|
print(np.abs(image).sum()) |
|
``` |
|
|
|
<Tip> |
|
|
|
π‘ μ¬νμ±μ΄ μ€μν κ²½μ°μλ νμ CPU generatorλ₯Ό μ λ¬νλ κ²μ΄ μ’μ΅λλ€. |
|
μ±λ₯ μμ€μ 무μν μ μλ κ²½μ°κ° λ§μΌλ©° νμ΄νλΌμΈμ΄ GPUμμ μ€νλμμ λλ³΄λ€ ν¨μ¬ λ λΉμ·ν κ°μ μμ±ν μ μμ΅λλ€. |
|
|
|
</Tip> |
|
|
|
λ§μ§λ§μΌλ‘ [UnCLIPPipeline](https://huggingface.co/docs/diffusers/v0.18.0/en/api/pipelines/unclip#diffusers.UnCLIPPipeline)κ³Ό κ°μ |
|
λ 볡μ‘ν νμ΄νλΌμΈμ κ²½μ°, μ΄λ€μ μ’
μ’
μ λ° μ€μ°¨ μ νμ κ·Ήλλ‘ μ·¨μ½ν©λλ€. |
|
λ€λ₯Έ GPU νλμ¨μ΄ λλ PyTorch λ²μ μμ μ μ¬ν κ²°κ³Όλ₯Ό κΈ°λνμ§ λ§μΈμ. |
|
μ΄ κ²½μ° μμ ν μ¬νμ±μ μν΄ μμ ν λμΌν νλμ¨μ΄ λ° PyTorch λ²μ μ μ€νν΄μΌ ν©λλ€. |
|
|
|
## κ²°μ λ‘ μ μκ³ λ¦¬μ¦ |
|
|
|
κ²°μ λ‘ μ μκ³ λ¦¬μ¦μ μ¬μ©νμ¬ μ¬ν κ°λ₯ν νμ΄νλΌμΈμ μμ±νλλ‘ PyTorchλ₯Ό ꡬμ±ν μλ μμ΅λλ€. |
|
κ·Έλ¬λ κ²°μ λ‘ μ μκ³ λ¦¬μ¦μ λΉκ²°μ λ‘ μ μκ³ λ¦¬μ¦λ³΄λ€ λλ¦¬κ³ μ±λ₯μ΄ μ νλ μ μμ΅λλ€. |
|
νμ§λ§ μ¬νμ±μ΄ μ€μνλ€λ©΄, μ΄κ²μ΄ μ΅μ μ λ°©λ²μ
λλ€! |
|
|
|
λ μ΄μμ CUDA μ€νΈλ¦Όμμ μμ
μ΄ μμλ λ λΉκ²°μ λ‘ μ λμμ΄ λ°μν©λλ€. |
|
μ΄ λ¬Έμ λ₯Ό λ°©μ§νλ €λ©΄ νκ²½ λ³μ [CUBLAS_WORKSPACE_CONFIG](https://docs.nvidia.com/cuda/cublas/index.html#results-reproducibility)λ₯Ό `:16:8`λ‘ μ€μ ν΄μ |
|
λ°νμ μ€μ μ€μ§ νλμ λ²νΌ ν¬λ¦¬λ§ μ¬μ©νλλ‘ μ€μ ν©λλ€. |
|
|
|
PyTorchλ μΌλ°μ μΌλ‘ κ°μ₯ λΉ λ₯Έ μκ³ λ¦¬μ¦μ μ ννκΈ° μν΄ μ¬λ¬ μκ³ λ¦¬μ¦μ λ²€μΉλ§νΉν©λλ€. |
|
νμ§λ§ μ¬νμ±μ μνλ κ²½μ°, λ²€μΉλ§ν¬κ° 맀 μκ° λ€λ₯Έ μκ³ λ¦¬μ¦μ μ νν μ μκΈ° λλ¬Έμ μ΄ κΈ°λ₯μ μ¬μ©νμ§ μλλ‘ μ€μ ν΄μΌ ν©λλ€. |
|
λ§μ§λ§μΌλ‘, [torch.use_deterministic_algorithms](https://pytorch.org/docs/stable/generated/torch.use_deterministic_algorithms.html)μ |
|
`True`λ₯Ό ν΅κ³ΌμμΌ κ²°μ λ‘ μ μκ³ λ¦¬μ¦μ΄ νμ±ν λλλ‘ ν©λλ€. |
|
|
|
```py |
|
import os |
|
|
|
os.environ["CUBLAS_WORKSPACE_CONFIG"] = ":16:8" |
|
|
|
torch.backends.cudnn.benchmark = False |
|
torch.use_deterministic_algorithms(True) |
|
``` |
|
|
|
μ΄μ λμΌν νμ΄νλΌμΈμ λλ² μ€ννλ©΄ λμΌν κ²°κ³Όλ₯Ό μ»μ μ μμ΅λλ€. |
|
|
|
```py |
|
import torch |
|
from diffusers import DDIMScheduler, StableDiffusionPipeline |
|
import numpy as np |
|
|
|
model_id = "runwayml/stable-diffusion-v1-5" |
|
pipe = StableDiffusionPipeline.from_pretrained(model_id).to("cuda") |
|
pipe.scheduler = DDIMScheduler.from_config(pipe.scheduler.config) |
|
g = torch.Generator(device="cuda") |
|
|
|
prompt = "A bear is playing a guitar on Times Square" |
|
|
|
g.manual_seed(0) |
|
result1 = pipe(prompt=prompt, num_inference_steps=50, generator=g, output_type="latent").images |
|
|
|
g.manual_seed(0) |
|
result2 = pipe(prompt=prompt, num_inference_steps=50, generator=g, output_type="latent").images |
|
|
|
print("L_inf dist = ", abs(result1 - result2).max()) |
|
"L_inf dist = tensor(0., device='cuda:0')" |
|
``` |
|
|