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')" | |
| ``` | |