|
<!--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. |
|
--> |
|
|
|
# μ€μΌμ€λ¬ |
|
|
|
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:]))) |
|
``` |
|
|
|
<Tip warning={true}> |
|
|
|
λ€μ Flax μ€μΌμ€λ¬λ *μμ§* Flax Stable Diffusion νμ΄νλΌμΈκ³Ό νΈνλμ§ μμ΅λλ€. |
|
|
|
- `FlaxLMSDiscreteScheduler` |
|
- `FlaxDDPMScheduler` |
|
|
|
</Tip> |
|
|
|
|