mirror of
https://github.com/huggingface/diffusers.git
synced 2026-01-27 17:22:53 +03:00
327 lines
12 KiB
Markdown
327 lines
12 KiB
Markdown
<!--Copyright 2025 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.
|
|
-->
|
|
|
|
# ์ค์ผ์ค๋ฌ
|
|
|
|
diffusion ํ์ดํ๋ผ์ธ์ diffusion ๋ชจ๋ธ, ์ค์ผ์ค๋ฌ ๋ฑ์ ์ปดํฌ๋ํธ๋ค๋ก ๊ตฌ์ฑ๋ฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ ํ์ดํ๋ผ์ธ ์์ ์ผ๋ถ ์ปดํฌ๋ํธ๋ฅผ ๋ค๋ฅธ ์ปดํฌ๋ํธ๋ก ๊ต์ฒดํ๋ ์์ ์ปค์คํฐ๋ง์ด์ง ์ญ์ ๊ฐ๋ฅํฉ๋๋ค. ์ด์ ๊ฐ์ ์ปดํฌ๋ํธ ์ปค์คํฐ๋ง์ด์ง์ ๊ฐ์ฅ ๋ํ์ ์ธ ์์๊ฐ ๋ฐ๋ก [์ค์ผ์ค๋ฌ](../api/schedulers/overview.md)๋ฅผ ๊ต์ฒดํ๋ ๊ฒ์
๋๋ค.
|
|
|
|
|
|
|
|
์ค์ผ์ฅด๋ฌ๋ ๋ค์๊ณผ ๊ฐ์ด diffusion ์์คํ
์ ์ ๋ฐ์ ์ธ ๋๋
ธ์ด์ง ํ๋ก์ธ์ค๋ฅผ ์ ์ํฉ๋๋ค.
|
|
|
|
- ๋๋
ธ์ด์ง ์คํ
์ ์ผ๋ง๋ ๊ฐ์ ธ๊ฐ์ผ ํ ๊น?
|
|
- ํ๋ฅ ์ ์ผ๋ก(stochastic) ํน์ ํ์ ์ ์ผ๋ก(deterministic)?
|
|
- ๋๋
ธ์ด์ง ๋ ์ํ์ ์ฐพ์๋ด๊ธฐ ์ํด ์ด๋ค ์๊ณ ๋ฆฌ์ฆ์ ์ฌ์ฉํด์ผ ํ ๊น?
|
|
|
|
์ด๋ฌํ ํ๋ก์ธ์ค๋ ๋ค์ ๋ํดํ๊ณ , ๋๋
ธ์ด์ง ์๋์ ๋๋
ธ์ด์ง ํ๋ฆฌํฐ ์ฌ์ด์ ํธ๋ ์ด๋ ์คํ๋ฅผ ์ ์ํด์ผ ํ๋ ๋ฌธ์ ๊ฐ ๋ ์ ์์ต๋๋ค. ์ฃผ์ด์ง ํ์ดํ๋ผ์ธ์ ์ด๋ค ์ค์ผ์ค๋ฌ๊ฐ ๊ฐ์ฅ ์ ํฉํ์ง๋ฅผ ์ ๋์ ์ผ๋ก ํ๋จํ๋ ๊ฒ์ ๋งค์ฐ ์ด๋ ค์ด ์ผ์
๋๋ค. ์ด๋ก ์ธํด ์ผ๋จ ํด๋น ์ค์ผ์ค๋ฌ๋ฅผ ์ง์ ์ฌ์ฉํ์ฌ, ์์ฑ๋๋ ์ด๋ฏธ์ง๋ฅผ ์ง์ ๋์ผ๋ก ๋ณด๋ฉฐ, ์ ์ฑ์ ์ผ๋ก ์ฑ๋ฅ์ ํ๋จํด๋ณด๋ ๊ฒ์ด ์ถ์ฒ๋๊ณค ํฉ๋๋ค.
|
|
|
|
|
|
|
|
|
|
|
|
## ํ์ดํ๋ผ์ธ ๋ถ๋ฌ์ค๊ธฐ
|
|
|
|
๋จผ์ ์คํ
์ด๋ธ diffusion ํ์ดํ๋ผ์ธ์ ๋ถ๋ฌ์ค๋๋ก ํด๋ณด๊ฒ ์ต๋๋ค. ๋ฌผ๋ก ์คํ
์ด๋ธ diffusion์ ์ฌ์ฉํ๊ธฐ ์ํด์๋, ํ๊น
ํ์ด์ค ํ๋ธ์ ๋ฑ๋ก๋ ์ฌ์ฉ์์ฌ์ผ ํ๋ฉฐ, ๊ด๋ จ [๋ผ์ด์ผ์ค](https://huggingface.co/stable-diffusion-v1-5/stable-diffusion-v1-5)์ ๋์ํด์ผ ํ๋ค๋ ์ ์ ์์ง ๋ง์์ฃผ์ธ์.
|
|
|
|
*์ญ์ ์ฃผ: ๋ค๋ง, ํ์ฌ ์ ๊ท๋ก ์์ฑํ ํ๊น
ํ์ด์ค ๊ณ์ ์ ๋ํด์๋ ๋ผ์ด์ผ์ค ๋์๋ฅผ ์๊ตฌํ์ง ์๋ ๊ฒ์ผ๋ก ๋ณด์
๋๋ค!*
|
|
|
|
```python
|
|
from huggingface_hub import login
|
|
from diffusers import DiffusionPipeline
|
|
import torch
|
|
|
|
# first we need to login with our access token
|
|
login()
|
|
|
|
# Now we can download the pipeline
|
|
pipeline = DiffusionPipeline.from_pretrained("stable-diffusion-v1-5/stable-diffusion-v1-5", torch_dtype=torch.float16)
|
|
```
|
|
|
|
๋ค์์ผ๋ก, GPU๋ก ์ด๋ํฉ๋๋ค.
|
|
|
|
```python
|
|
pipeline.to("cuda")
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## ์ค์ผ์ค๋ฌ ์ก์ธ์ค
|
|
|
|
์ค์ผ์ค๋ฌ๋ ์ธ์ ๋ ํ์ดํ๋ผ์ธ์ ์ปดํฌ๋ํธ๋ก์ ์กด์ฌํ๋ฉฐ, ์ผ๋ฐ์ ์ผ๋ก ํ์ดํ๋ผ์ธ ์ธ์คํด์ค ๋ด์ `scheduler`๋ผ๋ ์ด๋ฆ์ ์์ฑ(property)์ผ๋ก ์ ์๋์ด ์์ต๋๋ค.
|
|
|
|
```python
|
|
pipeline.scheduler
|
|
```
|
|
|
|
**Output**:
|
|
|
|
```
|
|
PNDMScheduler {
|
|
"_class_name": "PNDMScheduler",
|
|
"_diffusers_version": "0.8.0.dev0",
|
|
"beta_end": 0.012,
|
|
"beta_schedule": "scaled_linear",
|
|
"beta_start": 0.00085,
|
|
"clip_sample": false,
|
|
"num_train_timesteps": 1000,
|
|
"set_alpha_to_one": false,
|
|
"skip_prk_steps": true,
|
|
"steps_offset": 1,
|
|
"trained_betas": null
|
|
}
|
|
```
|
|
|
|
์ถ๋ ฅ ๊ฒฐ๊ณผ๋ฅผ ํตํด, ์ฐ๋ฆฌ๋ ํด๋น ์ค์ผ์ค๋ฌ๊ฐ [`PNDMScheduler`]์ ์ธ์คํด์ค๋ผ๋ ๊ฒ์ ์ ์ ์์ต๋๋ค. ์ด์ [`PNDMScheduler`]์ ๋ค๋ฅธ ์ค์ผ์ค๋ฌ๋ค์ ์ฑ๋ฅ์ ๋น๊ตํด๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค. ๋จผ์ ํ
์คํธ์ ์ฌ์ฉํ ํ๋กฌํํธ๋ฅผ ๋ค์๊ณผ ๊ฐ์ด ์ ์ํด๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
|
|
|
|
```python
|
|
prompt = "A photograph of an astronaut riding a horse on Mars, high resolution, high definition."
|
|
```
|
|
|
|
๋ค์์ผ๋ก ์ ์ฌํ ์ด๋ฏธ์ง ์์ฑ์ ๋ณด์ฅํ๊ธฐ ์ํด์, ๋ค์๊ณผ ๊ฐ์ด ๋๋ค์๋๋ฅผ ๊ณ ์ ํด์ฃผ๋๋ก ํ๊ฒ ์ต๋๋ค.
|
|
|
|
```python
|
|
generator = torch.Generator(device="cuda").manual_seed(8)
|
|
image = pipeline(prompt, generator=generator).images[0]
|
|
image
|
|
```
|
|
|
|
<p align="center">
|
|
<br>
|
|
<img src="https://huggingface.co/datasets/patrickvonplaten/images/resolve/main/diffusers_docs/astronaut_pndm.png" width="400"/>
|
|
<br>
|
|
</p>
|
|
|
|
|
|
|
|
|
|
## ์ค์ผ์ค๋ฌ ๊ต์ฒดํ๊ธฐ
|
|
|
|
๋ค์์ผ๋ก ํ์ดํ๋ผ์ธ์ ์ค์ผ์ค๋ฌ๋ฅผ ๋ค๋ฅธ ์ค์ผ์ค๋ฌ๋ก ๊ต์ฒดํ๋ ๋ฐฉ๋ฒ์ ๋ํด ์์๋ณด๊ฒ ์ต๋๋ค. ๋ชจ๋ ์ค์ผ์ค๋ฌ๋ [`SchedulerMixin.compatibles`]๋ผ๋ ์์ฑ(property)์ ๊ฐ๊ณ ์์ต๋๋ค. ํด๋น ์์ฑ์ **ํธํ ๊ฐ๋ฅํ** ์ค์ผ์ค๋ฌ๋ค์ ๋ํ ์ ๋ณด๋ฅผ ๋ด๊ณ ์์ต๋๋ค.
|
|
|
|
```python
|
|
pipeline.scheduler.compatibles
|
|
```
|
|
|
|
**Output**:
|
|
|
|
```
|
|
[diffusers.schedulers.scheduling_lms_discrete.LMSDiscreteScheduler,
|
|
diffusers.schedulers.scheduling_ddim.DDIMScheduler,
|
|
diffusers.schedulers.scheduling_dpmsolver_multistep.DPMSolverMultistepScheduler,
|
|
diffusers.schedulers.scheduling_euler_discrete.EulerDiscreteScheduler,
|
|
diffusers.schedulers.scheduling_pndm.PNDMScheduler,
|
|
diffusers.schedulers.scheduling_ddpm.DDPMScheduler,
|
|
diffusers.schedulers.scheduling_euler_ancestral_discrete.EulerAncestralDiscreteScheduler]
|
|
```
|
|
|
|
ํธํ๋๋ ์ค์ผ์ค๋ฌ๋ค์ ์ดํด๋ณด๋ฉด ์๋์ ๊ฐ์ต๋๋ค.
|
|
|
|
- [`LMSDiscreteScheduler`],
|
|
- [`DDIMScheduler`],
|
|
- [`DPMSolverMultistepScheduler`],
|
|
- [`EulerDiscreteScheduler`],
|
|
- [`PNDMScheduler`],
|
|
- [`DDPMScheduler`],
|
|
- [`EulerAncestralDiscreteScheduler`].
|
|
|
|
์์ ์ ์ํ๋ ํ๋กฌํํธ๋ฅผ ์ฌ์ฉํด์ ๊ฐ๊ฐ์ ์ค์ผ์ค๋ฌ๋ค์ ๋น๊ตํด๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
|
|
|
|
๋จผ์ ํ์ดํ๋ผ์ธ ์์ ์ค์ผ์ค๋ฌ๋ฅผ ๋ฐ๊พธ๊ธฐ ์ํด [`ConfigMixin.config`] ์์ฑ๊ณผ [`ConfigMixin.from_config`] ๋ฉ์๋๋ฅผ ํ์ฉํด๋ณด๋ ค๊ณ ํฉ๋๋ค.
|
|
|
|
|
|
|
|
```python
|
|
pipeline.scheduler.config
|
|
```
|
|
|
|
**Output**:
|
|
|
|
```
|
|
FrozenDict([('num_train_timesteps', 1000),
|
|
('beta_start', 0.00085),
|
|
('beta_end', 0.012),
|
|
('beta_schedule', 'scaled_linear'),
|
|
('trained_betas', None),
|
|
('skip_prk_steps', True),
|
|
('set_alpha_to_one', False),
|
|
('steps_offset', 1),
|
|
('_class_name', 'PNDMScheduler'),
|
|
('_diffusers_version', '0.8.0.dev0'),
|
|
('clip_sample', False)])
|
|
```
|
|
|
|
๊ธฐ์กด ์ค์ผ์ค๋ฌ์ config๋ฅผ ํธํ ๊ฐ๋ฅํ ๋ค๋ฅธ ์ค์ผ์ค๋ฌ์ ์ด์ํ๋ ๊ฒ ์ญ์ ๊ฐ๋ฅํฉ๋๋ค.
|
|
|
|
๋ค์ ์์๋ ๊ธฐ์กด ์ค์ผ์ค๋ฌ(`pipeline.scheduler`)๋ฅผ ๋ค๋ฅธ ์ข
๋ฅ์ ์ค์ผ์ค๋ฌ(`DDIMScheduler`)๋ก ๋ฐ๊พธ๋ ์ฝ๋์
๋๋ค. ๊ธฐ์กด ์ค์ผ์ค๋ฌ๊ฐ ๊ฐ๊ณ ์๋ config๋ฅผ `.from_config` ๋ฉ์๋์ ์ธ์๋ก ์ ๋ฌํ๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค.
|
|
|
|
```python
|
|
from diffusers import DDIMScheduler
|
|
|
|
pipeline.scheduler = DDIMScheduler.from_config(pipeline.scheduler.config)
|
|
```
|
|
|
|
|
|
|
|
์ด์ ํ์ดํ๋ผ์ธ์ ์คํํด์ ๋ ์ค์ผ์ค๋ฌ ์ฌ์ด์ ์์ฑ๋ ์ด๋ฏธ์ง์ ํ๋ฆฌํฐ๋ฅผ ๋น๊ตํด๋ด
์๋ค.
|
|
|
|
```python
|
|
generator = torch.Generator(device="cuda").manual_seed(8)
|
|
image = pipeline(prompt, generator=generator).images[0]
|
|
image
|
|
```
|
|
|
|
<p align="center">
|
|
<br>
|
|
<img src="https://huggingface.co/datasets/patrickvonplaten/images/resolve/main/diffusers_docs/astronaut_ddim.png" width="400"/>
|
|
<br>
|
|
</p>
|
|
|
|
|
|
|
|
|
|
## ์ค์ผ์ค๋ฌ๋ค ๋น๊ตํด๋ณด๊ธฐ
|
|
|
|
์ง๊ธ๊น์ง๋ [`PNDMScheduler`]์ [`DDIMScheduler`] ์ค์ผ์ค๋ฌ๋ฅผ ์คํํด๋ณด์์ต๋๋ค. ์์ง ๋น๊ตํด๋ณผ ์ค์ผ์ค๋ฌ๋ค์ด ๋ ๋ง์ด ๋จ์์์ผ๋ ๊ณ์ ๋น๊ตํด๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
|
|
|
|
|
|
|
|
[`LMSDiscreteScheduler`]์ ์ผ๋ฐ์ ์ผ๋ก ๋ ์ข์ ๊ฒฐ๊ณผ๋ฅผ ๋ณด์ฌ์ค๋๋ค.
|
|
|
|
```python
|
|
from diffusers import LMSDiscreteScheduler
|
|
|
|
pipeline.scheduler = LMSDiscreteScheduler.from_config(pipeline.scheduler.config)
|
|
|
|
generator = torch.Generator(device="cuda").manual_seed(8)
|
|
image = pipeline(prompt, generator=generator).images[0]
|
|
image
|
|
```
|
|
|
|
<p align="center">
|
|
<br>
|
|
<img src="https://huggingface.co/datasets/patrickvonplaten/images/resolve/main/diffusers_docs/astronaut_lms.png" width="400"/>
|
|
<br>
|
|
</p>
|
|
|
|
|
|
[`EulerDiscreteScheduler`]์ [`EulerAncestralDiscreteScheduler`] ๊ณ ์ 30๋ฒ์ inference step๋ง์ผ๋ก๋ ๋์ ํ๋ฆฌํฐ์ ์ด๋ฏธ์ง๋ฅผ ์์ฑํ๋ ๊ฒ์ ์ ์ ์์ต๋๋ค.
|
|
|
|
```python
|
|
from diffusers import EulerDiscreteScheduler
|
|
|
|
pipeline.scheduler = EulerDiscreteScheduler.from_config(pipeline.scheduler.config)
|
|
|
|
generator = torch.Generator(device="cuda").manual_seed(8)
|
|
image = pipeline(prompt, generator=generator, num_inference_steps=30).images[0]
|
|
image
|
|
```
|
|
|
|
<p align="center">
|
|
<br>
|
|
<img src="https://huggingface.co/datasets/patrickvonplaten/images/resolve/main/diffusers_docs/astronaut_euler_discrete.png" width="400"/>
|
|
<br>
|
|
</p>
|
|
|
|
|
|
```python
|
|
from diffusers import EulerAncestralDiscreteScheduler
|
|
|
|
pipeline.scheduler = EulerAncestralDiscreteScheduler.from_config(pipeline.scheduler.config)
|
|
|
|
generator = torch.Generator(device="cuda").manual_seed(8)
|
|
image = pipeline(prompt, generator=generator, num_inference_steps=30).images[0]
|
|
image
|
|
```
|
|
|
|
<p align="center">
|
|
<br>
|
|
<img src="https://huggingface.co/datasets/patrickvonplaten/images/resolve/main/diffusers_docs/astronaut_euler_ancestral.png" width="400"/>
|
|
<br>
|
|
</p>
|
|
|
|
|
|
์ง๊ธ ์ด ๋ฌธ์๋ฅผ ์์ฑํ๋ ํ์์ ๊ธฐ์ค์์ , [`DPMSolverMultistepScheduler`]๊ฐ ์๊ฐ ๋๋น ๊ฐ์ฅ ์ข์ ํ์ง์ ์ด๋ฏธ์ง๋ฅผ ์์ฑํ๋ ๊ฒ ๊ฐ์ต๋๋ค. 20๋ฒ ์ ๋์ ์คํ
๋ง์ผ๋ก๋ ์คํ๋ ์ ์์ต๋๋ค.
|
|
|
|
|
|
|
|
```python
|
|
from diffusers import DPMSolverMultistepScheduler
|
|
|
|
pipeline.scheduler = DPMSolverMultistepScheduler.from_config(pipeline.scheduler.config)
|
|
|
|
generator = torch.Generator(device="cuda").manual_seed(8)
|
|
image = pipeline(prompt, generator=generator, num_inference_steps=20).images[0]
|
|
image
|
|
```
|
|
|
|
<p align="center">
|
|
<br>
|
|
<img src="https://huggingface.co/datasets/patrickvonplaten/images/resolve/main/diffusers_docs/astronaut_dpm.png" width="400"/>
|
|
<br>
|
|
</p>
|
|
|
|
|
|
๋ณด์๋ค์ํผ ์์ฑ๋ ์ด๋ฏธ์ง๋ค์ ๋งค์ฐ ๋น์ทํ๊ณ , ๋น์ทํ ํ๋ฆฌํฐ๋ฅผ ๋ณด์ด๋ ๊ฒ ๊ฐ์ต๋๋ค. ์ค์ ๋ก ์ด๋ค ์ค์ผ์ค๋ฌ๋ฅผ ์ ํํ ๊ฒ์ธ๊ฐ๋ ์ข
์ข
ํน์ ์ด์ฉ ์ฌ๋ก์ ๊ธฐ๋ฐํด์ ๊ฒฐ์ ๋๊ณค ํฉ๋๋ค. ๊ฒฐ๊ตญ ์ฌ๋ฌ ์ข
๋ฅ์ ์ค์ผ์ค๋ฌ๋ฅผ ์ง์ ์คํ์์ผ๋ณด๊ณ ๋์ผ๋ก ์ง์ ๋น๊ตํด์ ํ๋จํ๋ ๊ฒ ์ข์ ์ ํ์ผ ๊ฒ ๊ฐ์ต๋๋ค.
|
|
|
|
|
|
|
|
## Flax์์ ์ค์ผ์ค๋ฌ ๊ต์ฒดํ๊ธฐ
|
|
|
|
JAX/Flax ์ฌ์ฉ์์ธ ๊ฒฝ์ฐ ๊ธฐ๋ณธ ํ์ดํ๋ผ์ธ ์ค์ผ์ค๋ฌ๋ฅผ ๋ณ๊ฒฝํ ์๋ ์์ต๋๋ค. ๋ค์์ Flax Stable Diffusion ํ์ดํ๋ผ์ธ๊ณผ ์ด๊ณ ์ [DDPM-Solver++ ์ค์ผ์ค๋ฌ๋ฅผ](../api/schedulers/multistep_dpm_solver) ์ฌ์ฉํ์ฌ ์ถ๋ก ์ ์คํํ๋ ๋ฐฉ๋ฒ์ ๋ํ ์์์
๋๋ค .
|
|
|
|
```Python
|
|
import jax
|
|
import numpy as np
|
|
from flax.jax_utils import replicate
|
|
from flax.training.common_utils import shard
|
|
|
|
from diffusers import FlaxStableDiffusionPipeline, FlaxDPMSolverMultistepScheduler
|
|
|
|
model_id = "stable-diffusion-v1-5/stable-diffusion-v1-5"
|
|
scheduler, scheduler_state = FlaxDPMSolverMultistepScheduler.from_pretrained(
|
|
model_id,
|
|
subfolder="scheduler"
|
|
)
|
|
pipeline, params = FlaxStableDiffusionPipeline.from_pretrained(
|
|
model_id,
|
|
scheduler=scheduler,
|
|
variant="bf16",
|
|
dtype=jax.numpy.bfloat16,
|
|
)
|
|
params["scheduler"] = scheduler_state
|
|
|
|
# Generate 1 image per parallel device (8 on TPUv2-8 or TPUv3-8)
|
|
prompt = "a photo of an astronaut riding a horse on mars"
|
|
num_samples = jax.device_count()
|
|
prompt_ids = pipeline.prepare_inputs([prompt] * num_samples)
|
|
|
|
prng_seed = jax.random.PRNGKey(0)
|
|
num_inference_steps = 25
|
|
|
|
# shard inputs and rng
|
|
params = replicate(params)
|
|
prng_seed = jax.random.split(prng_seed, jax.device_count())
|
|
prompt_ids = shard(prompt_ids)
|
|
|
|
images = pipeline(prompt_ids, params, prng_seed, num_inference_steps, jit=True).images
|
|
images = pipeline.numpy_to_pil(np.asarray(images.reshape((num_samples,) + images.shape[-3:])))
|
|
```
|
|
|
|
> [!WARNING]
|
|
> ๋ค์ Flax ์ค์ผ์ค๋ฌ๋ *์์ง* Flax Stable Diffusion ํ์ดํ๋ผ์ธ๊ณผ ํธํ๋์ง ์์ต๋๋ค.
|
|
>
|
|
> - `FlaxLMSDiscreteScheduler`
|
|
> - `FlaxDDPMScheduler`
|
|
|