AI 학습 채널에 정리해둔 글 날아갔길래 5ch -> 4chan 정리본 번역해봤음

난 학습할 생각은 없는데 관심 생겨서 대충 페이퍼 참고하고 번역한거라 틀릴 수 있으니 양해 부탁함

특히나 기술적인 부분은 전부 거르고 페이퍼 직접 읽는걸 추천함

반박시 니가 무조건 맞음

원본: https://rentry.org/2chAI_LoRA_Dreambooth_guide_english


간단 용어 정리

스테이블 디퓨전 = 문장을 이미지로 만들어주는 기술 이름

자동좌 웹UI = 스테이블 디퓨전을 웹 페이지로 쉽게 사용할 수 있게 만들어 준 프로젝트
체크포인트, 모델 파일 =  ckpt 또는 safetensors 등

파인튠, 파인튜닝 = 체크포인트 모델을 특정 방향으로 추가 학습하는 행위

네트워크, 학습 모델 파일 = 파인튜닝으로 생성한 파일 (pt 등)


LoRA 란?[arXiv:2106.09685]

LoRA(Low-rank Adaption for Fast Text-to-Image Diffusion Fine-tuning)는 

Hypernetwork, Textual Inversion (TI = Embedding) 같은 스테이블 디퓨젼의 파인튜닝 방식 중 하나로

기존 모델(pretrained-model weights)을 건들이지 않고(freeze) 레이어 사이에 새로운 레이어를 추가(inject)하는 형태로 학습하는 기술로

다음과 같은 장점을 가지고 있음:

- 드림부스보다 두 배 이상 빠름

- 이미지 생성(inference)시 추가 시간이 소요되지 않음

- 출력된 네트워크 파일의 용량이 작음

- 과거 파인튜닝 방식보다 결과 퀄리티가 다소 좋은 편임


요구 사양: 6GB 이상의 VRAM 과 CUDA 코어가 있는 NVIDIA 그래픽 카드


사용 방법

LoRA 네트워크를 사용하기 위해선 두 방법이 있음:

1. 추가 가중치(Additional weights) 로 바로 사용하기

2. 스테이블 디퓨젼 모델에 병합해 사용하기


첫번째 방법 - 추가 가중치 (추천)

자동좌 웹UI 에 kohya-ss 가 만든 확장 기능 설치하기

https://github.com/kohya-ss/sd-webui-additional-networks

네트워크 파일들은 따로 설정하지 않았다면 기본 값인 models/lora 디렉터리에 두면 됨


새 패널 열기활성화 뒤 원하는 모델 선택하고
가중치를 원하는만큼 주기



두번째 방법 - 모델에 병합해 사용하기

자동좌 웹UI 에 d8ahazard 가 만든 확장 기능 설치하기

https://github.com/d8ahazard/sd_dreambooth_extension

safetensors 파일은 아직 지원하지 않으므로 ckpt 파일을 구해두자


새 탭 열기Settings 탭에서 Use LORA 체크박스 활성화하기


Create 탭에서 Source Checkpoint 으로 기반 모델 선택한 뒤
좌측 Lora Model 고르고 상단 Generate Ckpt 버튼 클릭하기



데이터셋 준비하기

들어가기 앞서 읽어두면 좋은 조언들


조언 #1 - 모델 별로 다른 점

씹덕 모델(NAI, AnythingV3 등)로 학습한다면 이미지 설명은 갤부루나 단부루의 태그 형태를 사용해야함

예시: 1girl, short hair, green eyes, black hair, school uniform...


SD 1.x 과 2.x 모델로 학습한다면 이미지에 보이는 것들을 영어(자연어)로 적어둬야함

턱수염 달린 어부의 이미지의 예시: pencil art of man fishing, bread

안경을 쓰고 빨간 셔츠를 입은 친구가 일출 앞에서 웃고 있는 사진의 예시: photo of 친구이름, smiling, wearing glasses, red shirt, sunset in the background


조언 #2 - 컨셉 단어

캐릭터를 학습시킨다면 그 캐릭터가 존재하는 이미지에만 캐릭터를 가르키는 이름 같은 키워드를 넣어줘야함

예: 1girl, shiina mayuri, short hair, green eyes...

예: artist name, mountains, night, moon, snowy peaks, stars...


조언 #3 - 이미지 정리

대상을 제외한 다른 사람의 몸, 이목을 끄는 물체, 작가의 서명(싸인) 등

학습에 불필요한, 생성된 결과물에서 보고 싶지 않은 것들은 미리 지우거나 잘라내는게 좋음


조언 #4 - 작업 속도 올리기

노가다는 가능한 모두 기계에게 시키자

라벨링(태깅) 작업은 sd-tagging-helper 같은 프로그램을 사용하면 편리함

데이터셋 관리하는 프로그램이나 자동좌 웹UI 의 확장 기능도 있음:

* https://github.com/toshiaki1729/stable-diffusion-webui-dataset-tag-editor

* https://github.com/toriato/stable-diffusion-webui-wd14-tagger

* https://github.com/SesuMoe/sd-tagger-webui

또, Grabber 를 이 이미지처럼 설정하면 손 쉽게 데이터셋을 모을 수 있음


kohya 가 만든 스크립트 사용하기

폴더 구조 예시


좋은 데이터셋의 예제 (MEGA 폴더 주소, 컨셉 대상: 실비키우기의 실비)


이미지에 보이는 n 은 컨셉 이름인 conceptAconceptB 를 몇 번이나 반복할지 가르키는 숫자임


반복 횟수(n)는 특정 폴더에 담겨진 이미지에 가중치를 주는 것을 의미함

예를 들어 저퀄 이미지 10장을 담아둔 1_LowRes 폴더와 고퀄 이미지 20장을 모아둔 2_HighRes 폴더가 있다고 가정할 때

총 50(1 * 10 + 2 * 20)장의 이미지를 첫번째 폴더로부터 20%(1 * 10 / 50)를, 두번째 폴더로부터 80%(2 * 20 / 50) 학습하게 됨

최종적으로 저퀄 이미지가 담겨진 폴더를 덜 학습하게 됨


컨셉 폴더는 얼마든지 만들어도 상관 없으나 하나 이상은 꼭 있어야함


컨셉 이름은 다른 컨셉들과 중복되지 않는 한에서 맘대로 입력해도 상관 없음

예를 들어 woods, gun, pistol, doraemon 같이 이미 학습 됐을 수도 있는 단어들은 피해야함

컨셉 이름 고르기 전에 본문 하단의 '$keep_tokens' 변수 관련 내용을 읽어보는 걸 추천함


모든 컨셉 폴더 내에는 학습할 이미지 파일과 동일한 파일 이름을 가진 텍스트(.txt) 파일이 있어야함

텍스트 파일에는 해당 이미지를 설명할 수 있는 키워드들이 담겨있어야하고 키워드 수에는 따로 제한이 없음


학습할 이미지는 크기에 맞게 자를 필요 없음일 줄 알았으나

AI 그림 학습 채널에서 관련 이슈로 불탄 적 있으니 아래 글 참고해서 자르던지 말던지 하셈

https://arca.live/b/hypernetworks/67695414


regularization_images 폴더는 정규화 이미지를 담아두는 곳으로 비워둬도 상관 없음

정규화는 학습할 이미지의 스타일(그림체 등)로부터 원하는 컨셉(캐릭터 등)만 뽑아내는 작업으로

좋던 나쁘던 학습 정확도에 큰 영향을 줄 수 있고 학습한 모델이 아닌 다른 모델에 적용할 수 있는 호환성(transferability)이 높아짐


아래는 정규화 과정 사용 여부만 다르고 동일한 데이터셋과 설정, 학습 속도 그리고 시드로 학습하여 만든 모델로 이미지를 생성하여 비교한 예제임

둘 다 30분 간 1.91s/it 속도로 학습하였고 정규화 과정을 거친 모델만 정규화 이미지로 30분간 추가 학습함

예제 이미지와 학습한 모델 그리고 스크립트는 여기서 확인할 수 있음



정규화 과정을 거친 모델은 좀 더 다양한 형태(옷과 포즈 등)를 취하고 있는 것을 볼 수 있음


학습 시작하기

kohya 가 만든 스크립트 사용하기


필요한 프로그램과 파일들:

Notepad++Visual Studio Code 같은 편집기 (메모장으로 생고생 할거면 말리진 않겠음)

Git for Windows (32비트 다운로드, 64비트 다운로드)

Python 3.10.x (32비트 다운로드, 64비트 다운로드)

PowerShell 스크립트 파일 (들어가서 오른쪽 클릭 후 다른 이름으로 저장, 확장명 .ps1 확인!)


1. 작업 폴더 만들고 스크립트 받기 

작업 폴더 쉬프트 + 오른쪽 클릭 눌러서 새 PowerShell 창 열기


2. kohya-ss/sd-scripts 레포지토리 클론하기

git clone --depth 1 https://github.com/kohya-ss/sd-scripts


3. 아래 명령어 한 줄씩 순서대로 복붙하기

# 외부에서 받아온 스크립트 실행할 수 있도록 제한 해제

Set-ExecutionPolicy Unrestricted -Scope CurrentUser


# 가상 환경 만들고 적용하기

python -m venv venv

.\venv\Scripts\Activate.ps1


# 종속 패키지 설치하기

pip install torch==1.12.1+cu116 torchvision==0.13.1+cu116 --extra-index-url https://download.pytorch.org/whl/cu116
pip install --upgrade -r requirements.txt
pip install -U -I --no-deps https://github.com/C43H66N12O12S2/stable-diffusion-webui/releases/download/f/xformers-0.0.14.dev0-cp310-cp310-win_amd64.whl


# 윈도우 환경에서 컴파일된 CUDA 라이브러리 복사하기
cp .\bitsandbytes_windows\*.dll .\venv\Lib\site-packages\bitsandbytes\
cp .\bitsandbytes_windows\cextension.py .\venv\Lib\site-packages\bitsandbytes\cextension.py
cp .\bitsandbytes_windows\main.py .\venv\Lib\site-packages\bitsandbytes\cuda_setup\main.py


# Accelerate 설정 열기

accelerate config


4. 다음과 같이 설정하기:

In which compute environment are you running?
This machine (화살표 위 아래 키로 변경하고 엔터 키 누르기)
Which type of machine are you using?
No distributed training
Do you want to run your training on CPU only (even if a GPU is available)?
NO (대소문자까지 완벽히 동일하게 입력해야함)
Do you wish to optimize your script with torch dynamo?
NO
Do you want to use DeepSpeed?
NO
What GPU(s) (by id) should be used for training on this machine as a comma-seperated list?
all
Do you wish to use FP16 or BF16 (mixed precision)?
– 
fp16 또는 bf16 (BF16 을 지원하는 장치에서만 선택)


5. 스크립트 변수 수정하기

위에서 받았던 스크립트 파일을 편집기로 연 뒤 아래 주석을 참고해 수정


##### Config start #####

# 경로 변수
$sd_scripts_dir = "X:\git-repos\sd-scripts\" # kohya-ss/sd-scripts 레포지토리 경로
$ckpt = "X:\SD-models\checkpoint.safetensors" # 체크포인트 모델 경로 (ckpt 또는 safetensors)
$is_sd_v2_ckpt = 0 # SD 2.x 체크포인트 모델이라면 '1' 로 설정
$is_sd_v2_768_ckpt = 0 # SD 2.x-768 체크포인트 모델이라면 '1' 로 설정
$image_dir = "X:\training_data\img\" # 학습할 데이터가 위치한 경로
$reg_dir = "" # 정규화 데이터가 위치한 경로 (선택 가능)
$output_dir = "X:\LoRA\" # LoRA 네트워크(모델)이 저장될 경로
$output_name = "my_LoRA_network_v1" # LoRA 네트워크 파일명 (확장명 없이)
$use_vae = 0 # 체크포인트 모델 불러올 때 VAE 사용하고 싶다면 '1' 로 설정
$vae_path = "X:\SD-models\checkpoint.vae.pt" # VAE 모델 경로

# 사용자 학습 시간 (선택 가능)
$desired_training_time = 0 # 0 보다 크다면 n분 동안  If greater than 0, ignore number of images with repetitions when calculating training steps and train network for N minutes
$gpu_training_speed = "1.23it/s | 1.23s/it" # 평균 학습 속도, GPU 에 따라 다름. XX.XXit/s 또는 XX.XXs/it 형태로 작성할 수 있음

# 주 변수
$train_batch_size = 1 # 얼마나 많은 이미지를 한 번에 학습할지. 높을 수록 학습 스텝이 낮아지고(빠르고) VRAM 을 많이 사용함
$resolution = 512 # 학습 해상도 (px)
$num_epochs = 10 # epoch 수. $desired_training_time 가 0 보다 크다면 설정한 값을 무시함
$save_every_n_epochs = 1 # n번 epoch 마다 저장
$save_last_n_epochs = 999 # 마지막 epoch n개만 저장하기
$max_token_length = 75 # 최대 토큰 수. 사용할 수 있는 값: 75 / 150 / 225

# Advanced variables
$learning_rate = 1e-4 # 학습률 (Learning rate)
$unet_lr = $learning_rate # U-Net 학습률. 기본 값은 학습률과 같음
$text_encoder_lr = $learning_rate # 텍스트 인코더 학습률. 기본 값은 학습률과 같음
$scheduler = "cosine_with_restarts" # 학습률에 사용할 스케줄러. 사용할 수 있는 값: linear, cosine, cosine_with_restarts, polynomial, constant (기본 값), constant_with_warmup
$lr_warmup_ratio = 0.0 # 전체 학습 스텝 중 warm up 스텝과 학습률 스케줄러의 비율 (0 과 1 사이)
$network_dim = 128 # 네트워크 크기. 높을 수록 정확해지고 결과 파일 크기와 사용하는 VRAM 크기도 커짐
$save_precision = "fp16" # 저장할 때 사용할 정밀도(precision) 종류. 사용할 수 있는 값: no, float, fp16, bf16
$mixed_precision = "fp16" # 학습할 때 사용할 정밀도 종류. 사용할 수 있는 값: no, fp16, bf16
$is_random_seed = 1 # 학습 시드. 1 = 무작위 시드, 0 = 고정 시드
$shuffle_caption = 1 # 쉼표로 나눠진 캡션(키워드) 무작위로 섞기
$keep_tokens = 0 # 캡션을 무작위를 섞을 때 토큰 n개는 가만히 두기 (컨셉 이름 등)
$do_not_interrupt = 0 # 사용자의 확인이 필요한 순간에 스크립트 멈추지 않으려면 '1' 로 설정. Enabled by default if running in a chain
# 순차적으로 실행할 스크립트들
# 순서대로 실행할 스크립트들의 경로를 개수 제한 없이 넣을 수 있음
$script_paths = @(
  "<X:\Path\to\script\script.ps1>",
  "<.\script.ps1>",
  "<script.ps1>"
)

# 로깅과 디버깅
$test_run = 0 # 메인 스크립트 실행하지 않기
$do_not_clear_host = 0 # 실행할 때 콘솔 지우기 않기
$logging_enabled = 0
$logging_dir = "X:\LoRA\logs\"
$log_prefix = $output_name
$debug_dataset = 0
$dont_draw_flags = 0 # 플래그를 표시하지 않기

##### Config end #####


5-1. 스크립트 변수에 관한 자세한 설명


$train_batch_size

이 값을 올릴 때 $learning_rate 값과 같이 올리는 것을 추천함

cloneofsimo 가 작성한 댓글 참고: https://github.com/cloneofsimo/lora/discussions/53#discussioncomment-4437440


$num_epochs

이 값은 학습 스텝 수를 계산하는데 사용됨.

epoch 가 클 수록 학습에 드는 시간도 덩달아 증가함.

값을 줄이거나 키울 때 생성되는 결과의 차이는 아래에 있는 $learning_rate 변수에 대한 설명 참고


$max_token_length

태그(설명)를 적어두는 텍스트 파일 중 가장 큰 파일을 열어 복사한 뒤 웹UI 프롬프트 입력 란에 넣으면 우측에 토큰 수가 표시됨

이 값이 75 보다 적으면 75 를, 그보다 크다면 150 를, 더 크다면 225 를 입력하면 됨

225 이상의 값은 스크립트에서 아직 지원하지 않음 (직접 줄여야 함)


$clip_skip

Stable Diffusion 기반 체크포인트 모델(Waifu Diffusion 등)이라면 '1'

유출된 노벨AI 기반 체크포인트 모델(Anything 등)이라면 '2'


$learning_rate

1.x 기반 체크포인트 모델이라면 '1e-4' 값을 추천함

2.x 기반은 확실하지 않음, 위 값과 동일하게 설정 했을 때 기괴하게 나온다는 평이 있으나 재현성에는 부족함이 있음


낮은 학습률과 낮은 스텝 수에선 과소적합(underfit) 현상이 발생해 네트워크가 컨셉을 이해하지 못하는 현상이 발생할 수 있음

높은 속도와 많은 데이터 수에선 과적합(overfit) 현상이 발생해 네트워크가 컨셉만 이해하여 컨셉만 생성하고 나머지 프롬프트는 무시될 수 있음


이 사이트에서 학습률에 따른 Gradient descent 를 볼 수 있고 Local minima 와 과적합 현상을 직접 경험해볼 수 있음

아래로 내려갈수록 내가 원하는 목표(컨셉)을 달성하는걸 의미하는데 이 과정을 경사 하강법(Gradient descent)이라고 함

학습률이 너무 낮으면 움푹 패여있는 언덕인 local minimum 을 넘어가지 못해 과소적합 되고

학습률이 너무 높으면 학습 목표인 global minimum 까지 도달할 수 있지만 경로가 난잡하고 끝까지 도달해도 계속해서 움직이는 등 과적합 현상이 일어나는 것을 볼 수 있음

(좌측 하단의 골뱅이 아이콘 클릭해 학습률을 원하는만큼 조절하고 지형 클릭하면 이동하는 걸 볼 수 있음)


다음 그리드 이미지는 각기 다른 learning_rate 값을 사용할 때의 결과를 보여주고 있음

모든 네트워크는 동일한 데이터셋(작가 픽시브)으로 학습됐고 이미지는 같은 시드와 다른 프롬프트로 생성함


learning_rate = <X>, unet_lr = learning_rate, text_encoder_lr = learning_rate, scheduler = linear


$unet_lr

U-Net 학습률, U-Net 은 노이즈(무작위로 만들어진 픽셀들)를 원하는 이미지로 변환하는 과정을 담당함

실험이 더 필요한 변수임

이 GitHub Discussion 에서 다양한 시도와 결과를 찾아볼 수 있음


learning_rate = 1e-4, unet_lr = <X>, text_encoder_lr = learning_rate, scheduler = linear


$text_encoder_lr

CLIP 텍스트 인코더의 학습률

전체 학습률의 절반만큼 줄이면(예: 1e-4 = 0.0001 의 경우 5e-5 = 0.00005) 최종 결과가 개선된다는 의견이 있음

또한 텍스트 인코더를 파인튜닝 하는 것이 얼굴 표현에 도움이 된다고 함

실험이 더 필요한 변수임


learning_rate = 1e-4, unet_lr = learning_rate, text_encoder_lr = <X>, scheduler = linear


$scheduler


설명
그래프
constant
학습 시작부터 끝까지 학습률이 변하지 않음
lr_warmup_ratio 값을 사용하지 않는 유일한 스케줄러
(기본 값)
linear
learning_rate 값부터 0 까지 직선으로 감소함
cosine
learning_rate 과 0 사이를 코사인 함수를 통해 감소함
cosine_with_restarts
learning_rate 과 0 사이를 코사인 함수를 통해 감소하고
중간에 warmup 과정을 포함한 재시작을 함
polynomial

constant_with_warmup
constant 와 동일하나 warmup 과정이 있음


learning_rate = 1e-4, unet_lr = learning_rate, text_encoder_lr = learning_rate, scheduler = <X>


$lr_warmup_ratio



$network_dim

128/256 이상의 값은 큰 영향을 주지 않는다고 알려짐 (1024 이상을 쓰는 사람도 간혹 있음)

값이 높으면 높을수록 VRAM 을 많이 쓰고 출력 파일 크기도 커짐


$save_precision $mixed_precision

BF16 사용할 수 있는 글카라면 'bf16' 값 추천

지원 안하는 글카라면 'fp16' 값


$keep_tokens

만약 $shuffle_caption 이 참이라면 이 값을 사용해 첫 n번째 토큰을 제외하고 무작위로 섞을 수 있음


최대 4글자까지 한 토큰으로 인식되는데 이 목록에서 아무꺼나 골라서 컨셉 태그(토큰)로 써먹을 수 있음

(SKS 를 초기 단어로 사용하는 이유가 여기에 있는데, sks 는 모델에 따라서 총으로 인식될 수 있으니 사용을 권하지 않음)


데이터셋 폴더에 있는 모든 txt 태그 파일의 시작 지점에 위에서 고른 태그를 입력하고 

$shuffle_captions = '1' 그리고 $keep_tokens = '1' 으로 변경하면 사용할 수 있음



6. 스크립트 실행하기

만약 스크립트 실행이 안된다면?

스크립트 파일이 있는 폴더 속 빈 공간을 쉬프트 + 오른쪽 클릭한 뒤

터미널에서 열기 또는 여기서 PowerShell 창 열기 클릭하고

.\train_network.ps1 입력한 뒤 엔터 누르면 실행할 수 있음




시간 있을 때 지속적으로 이어서 번역하고 수정하는 중...