# Textual Inversion

[Textual Inversion](https://hf.co/papers/2208.01618)는 학습시키고자 하는 대상의 예시 이미지 몇 장만으로 이미지 생성 모델을 개인화하는 학습 기법입니다. 이 기법은 제공한 예시 이미지에 맞춰 텍스트 임베딩을 학습하고 업데이트하는 방식으로 작동하며, 새로 학습된 임베딩은 프롬프트에서 반드시 사용해야 하는 특수 단어에 연결됩니다.

학습된 임베딩을 사용한 추론에 대해서는 [Textual inversion inference](../using-diffusers/legacy_adapters#textual-inversion)를 참조하세요.

vRAM이 제한된 GPU에서 학습을 수행하는 경우, 학습 명령에서 `gradient_checkpointing` 및 `mixed_precision` 매개변수를 활성화하도록 설정하는 것이 좋습니다. 또한 [xFormers](../optimization/attention_backends)를 사용하여 메모리 효율적인 어텐션을 적용하면 메모리 사용량을 줄일 수 있습니다.

이 가이드에서는 [textual_inversion.py](https://github.com/huggingface/diffusers/blob/main/examples/textual_inversion/textual_inversion.py) 스크립트를 살펴보고, 이를 더 잘 이해하며 자신의 사용 사례에 맞게 수정하는 방법을 안내합니다.

…

```bash
git clone https://github.com/huggingface/diffusers
cd diffusers
pip install .
```

학습 스크립트가 포함된 예제 폴더로 이동하고, 사용 중인 스크립트에 필요한 의존성을 설치하세요:

```bash
cd examples/textual_inversion
pip install -r requirements.txt
```
> [!TIP]
> 🤗 Accelerate는 여러 GPU/TPU 또는 혼합 정밀도로 학습하는 것을 돕는 라이브러리입니다. 하드웨어와 환경에 따라 학습 설정을 자동으로 구성합니다. 자세한 내용은 🤗 Accelerate [Quick tour](https://huggingface.co/docs/accelerate/quicktour)를 참고하세요.

🤗 Accelerate 환경을 초기화합니다:

```bash
accelerate config
```

어떤 구성도 선택하지 않고 기본 🤗 Accelerate 환경을 설정하려면:

```bash
accelerate config default
```

또는 노트북과 같이 인터랙티브 셸을 지원하지 않는 환경에서는 다음을 사용할 수 있습니다:

```py
from accelerate.utils import write_basic_config

write_basic_config()
```

마지막으로, 자체 데이터셋으로 모델을 학습하려면 [학습용 데이터셋 만들기](create_dataset) 가이드를 참고하여 학습 스크립트와 호환되는 데이터셋을 만드는 방법을 배워보세요.

> [!TIP]
> 다음 섹션에서는 스크립트를 수정하는 방법을 이해하는 데 중요한 학습 스크립트의 일부 부분을 강조합니다. 그러나 스크립트의 모든 측면을 자세히 다루지는 않습니다. 더 자세히 알고 싶으시다면 [스크립트](https://github.com/huggingface/diffusers/blob/main/examples/textual_inversion/textual_inversion.py)를 읽어보시고, 질문이나 우려 사항이 있으시면 알려주시기 바랍니다.

## 스크립트 매개변수

학습 스크립트에는 학습 실행을 필요에 맞게 조정할 수 있도록 다양한 파라미터가 제공됩니다. 모든 파라미터와 그 설명은 [`parse_args()`](https://github.com/huggingface/diffusers/blob/839c2a5ece0af4e75530cb520d77bc7ed8acf474/examples/textual_inversion/textual_inversion.py#L176) 함수에 나열되어 있습니다. 해당되는 경우, Diffusers는 학습 배치 크기나 학습률과 같은 각 파라미터에 대해 기본값을 제공하지만, 원하시는 경우 학습 명령에서 이러한 값을 자유롭게 변경할 수 있습니다.

예를 들어, 기본값인 1보다 그라디언트 누적 스텝 수를 늘리려면:

```bash
accelerate launch textual_inversion.py \
  --gradient_accumulation_steps=4
```

지정해야 할 다른 기본적이고 중요한 매개변수에는 다음이 포함됩니다:

- `--pretrained_model_name_or_path`: Hub의 모델 이름 또는 사전 학습된 모델의 로컬 경로
- `--train_data_dir`: 학습 데이터셋(예시 이미지)이 포함된 폴더의 경로
- `--output_dir`: 학습된 모델을 저장할 위치
- `--push_to_hub`: 학습된 모델을 Hub에 푸시할지 여부
- `--checkpointing_steps`: 모델 학습 중 체크포인트를 저장하는 주기입니다. 학습이 중단된 경우, 학습 명령에 `--resume_from_checkpoint`를 추가하여 해당 체크포인트에서 학습을 계속할 수 있습니다.
- `--num_vectors`: 임베딩을 학습하는 데 사용할 벡터의 수입니다. 이 값을 늘리면 모델이 더 잘 학습할 수 있지만 학습 비용이 증가합니다.
- `--placeholder_token`: 학습된 임베딩을 연결할 특수 단어 (추론 시 프롬프트에 해당 단어를 사용해야 합니다)
- `--initializer_token`: 학습하려는 대상이나 스타일을 대략적으로 설명하는 한 단어
- `--learnable_property`: 모델이 새로운 "스타일"(예: 반 고흐의 그림 스타일) 또는 "객체"(예: 당신의 개)를 학습하도록 훈련하는지 여부

## 학습 스크립트

다른 학습 스크립트와 달리, textual_inversion.py에는 데이터셋을 생성하기 위한 커스텀 데이터셋 클래스인 [`TextualInversionDataset`](https://github.com/huggingface/diffusers/blob/b81c69e489aad3a0ba73798c459a33990dc4379c/examples/textual_inversion/textual_inversion.py#L487)가 있습니다. 이미지 크기, 플레이스홀더 토큰, 보간 방법, 이미지 크롭 여부 등을 커스터마이즈할 수 있습니다. 데이터셋 생성 방식을 변경해야 하는 경우 `TextualInversionDataset`를 수정할 수 있습니다.

다음으로, [`main()`](https://github.com/huggingface/diffusers/blob/839c2a5ece0af4e75530cb520d77bc7ed8acf474/examples/textual_inversion/textual_inversion.py#L573) 함수에서 데이터셋 전처리 코드와 학습 루프를 확인할 수 있습니다.

스크립트는 [tokenizer](https://github.com/huggingface/diffusers/blob/b81c69e489aad3a0ba73798c459a33990dc4379c/examples/textual_inversion/textual_inversion.py#L616), [scheduler 및 model](https://github.com/huggingface/diffusers/blob/b81c69e489aad3a0ba73798c459a33990dc4379c/examples/textual_inversion/textual_inversion.py#L622)을 로드하는 것으로 시작합니다:

```py
# Load tokenizer
if args.tokenizer_name:
    tokenizer = CLIPTokenizer.from_pretrained(args.tokenizer_name)
elif args.pretrained_model_name_or_path:
    tokenizer = CLIPTokenizer.from_pretrained(args.pretrained_model_name_or_path, subfolder="tokenizer")

# Load scheduler and models
noise_scheduler = DDPMScheduler.from_pretrained(args.pretrained_model_name_or_path, subfolder="scheduler")
text_encoder = CLIPTextModel.from_pretrained(
    args.pretrained_model_name_or_path, subfolder="text_encoder", revision=args.revision
)
vae = AutoencoderKL.from_pretrained(args.pretrained_model_name_or_path, subfolder="vae", revision=args.revision)
unet = UNet2DConditionModel.from_pretrained(
    args.pretrained_model_name_or_path, subfolder="unet", revision=args.revision
)
```

특수 [placeholder token](https://github.com/huggingface/diffusers/blob/b81c69e489aad3a0ba73798c459a33990dc4379c/examples/textual_inversion/textual_inversion.py#L632)이 토크나이저 옆에 추가되고, 새로운 토큰을 반영하도록 임베딩이 재조정됩니다.

그 다음, 스크립트는 `TextualInversionDataset`에서 [데이터셋을 생성](https://github.com/huggingface/diffusers/blob/b81c69e489aad3a0ba73798c459a33990dc4379c/examples/textual_inversion/textual_inversion.py#L716)합니다:

```py
train_dataset = TextualInversionDataset(
    data_root=args.train_data_dir,
    tokenizer=tokenizer,
    size=args.resolution,
    placeholder_token=(" ".join(tokenizer.convert_ids_to_tokens(placeholder_token_ids))),
    repeats=args.repeats,
    learnable_property=args.learnable_property,
    center_crop=args.center_crop,
    set="train",
)
train_dataloader = torch.utils.data.DataLoader(
    train_dataset, batch_size=args.train_batch_size, shuffle=True, num_workers=args.dataloader_num_workers
)
```

마지막으로, [training loop](https://github.com/huggingface/diffusers/blob/b81c69e489aad3a0ba73798c459a33990dc4379c/examples/textual_inversion/textual_inversion.py#L784)은 노이즈 잔차를 예측하는 것부터 특수 플레이스홀더 토큰의 임베딩 가중치를 업데이트하는 것까지 나머지 모든 작업을 처리합니다.

학습 루프가 어떻게 작동하는지 더 자세히 알고 싶다면, 디노이징 과정의 기본 패턴을 단계별로 설명하는 [Understanding pipelines, models and schedulers](../using-diffusers/write_own_pipeline) 튜토리얼을 확인해 보세요.

## 스크립트 실행

모든 변경 사항을 완료했거나 기본 구성으로 진행하는 데 문제가 없다면, 학습 스크립트를 실행할 준비가 된 것입니다! 🚀

이 가이드에서는 [cat toy](https://huggingface.co/datasets/diffusers/cat_toy_example) 이미지의 일부를 다운로드하여 디렉터리에 저장합니다. 원하시는 경우, 직접 데이터셋을 생성하여 사용할 수 있습니다([Create a dataset for training](create_dataset) 가이드 참고).

```py
from huggingface_hub import snapshot_download

local_dir = "./cat"
snapshot_download(
    "diffusers/cat_toy_example", local_dir=local_dir, repo_type="dataset", ignore_patterns=".gitattributes"
)
```

환경 변수 `MODEL_NAME`을 Hub의 모델 ID 또는 로컬 모델 경로로, `DATA_DIR`을 방금 고양이 이미지를 다운로드한 경로로 설정하세요. 스크립트는 다음 파일들을 생성하여 저장소에 저장합니다:

- `learned_embeds.bin`: 예시 이미지와 대응하는 학습된 임베딩 벡터
- `token_identifier.txt`: 특수 자리표시자 토큰
- `type_of_concept.txt`: 학습할 개념의 유형("object" 또는 "style")

> [!WARNING]
> 전체 학습 실행은 단일 V100 GPU에서 약 1시간이 소요됩니다.

를 실행하기 전에 한 가지 더 확인할 사항이 있습니다. 학습 과정을 추적하는 데 관심이 있다면, 학습이 진행되는 동안 생성된 이미지를 주기적으로 저장할 수 있습니다. 학습 명령에 다음 매개변수를 추가하세요:

```bash
--validation_prompt="A <cat-toy> train"
--num_validation_images=4
--validation_steps=100
```

```bash
export MODEL_NAME="stable-diffusion-v1-5/stable-diffusion-v1-5"
export DATA_DIR="./cat"

accelerate launch textual_inversion.py \
  --pretrained_model_name_or_path=$MODEL_NAME \
  --train_data_dir=$DATA_DIR \
  --learnable_property="object" \
  --placeholder_token="<cat-toy>" \
  --initializer_token="toy" \
  --resolution=512 \
  --train_batch_size=1 \
  --gradient_accumulation_steps=4 \
  --max_train_steps=3000 \
  --learning_rate=5.0e-04 \
  --scale_lr \
  --lr_scheduler="constant" \
  --lr_warmup_steps=0 \
  --output_dir="textual_inversion_cat" \
  --push_to_hub
```

학습이 완료되면, 새로 학습한 모델을 다음과 같이 추론에 사용할 수 있습니다:

```py
from diffusers import StableDiffusionPipeline
import torch

pipeline = StableDiffusionPipeline.from_pretrained("stable-diffusion-v1-5/stable-diffusion-v1-5", dtype=torch.float16).to("cuda")  # or "mps", "xpu", "cpu"
pipeline.load_textual_inversion("sd-concepts-library/cat-toy")
image = pipeline("A <cat-toy> train", num_inference_steps=50).images[0]
image.save("cat-train.png")
```

## 다음 단계

Textual Inversion 모델을 직접 학습하셔서 축하드립니다! 🎉 새로 학습한 모델을 사용하는 방법에 대해 더 알고 싶으시다면, 다음 가이드가 도움이 될 수 있습니다:

- [Textual Inversion 임베딩을 로드](../using-diffusers/legacy_adapters#textual-inversion)하는 방법과 이를 네거티브 임베딩으로 사용하는 방법을 학습해 보세요.

