Spaces:
Running
on
Zero
Running
on
Zero
<!--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')" | |
``` | |