뒤로
이정민
이정민 ·

[Tip] 스노우가 2달 동안 150억 번 AI 프로필 이미지 만드는 방법 📷

바야흐로 대 AI 프로필 시대입니다.

20230623509628.jpg출처: 세계일보 - 링크 (장원영 스노우 프로필)

혹시 본인의 얼굴 사진 몇 장 만으로도 기깔나는 프로필 사진을 만들 수 있는 사실 알고 계셨나요?

AI 아바타는 사실 Lensa.ai 에서 매직 아바타라는 이름으로 '22 11월 말에 출시한 것이 처음입니다. (공오공 님께서 관련한 글을 작성하신 적이 있죠)

실제로 매출을 정말 많이 낸 서비스였습니다.

나만의 것 + 외모 보정 (+앱이라는 채널) 이라는 엄청난 가치를 주었기 때문인데요.

외국 뿐만 아니라 국내에서도 관련 서비스가 많이 등장하고 있습니다. 국내 기준으로도 꾸준한 매출이 나오는 시장으로 알려져 있기 때문입니다.

현재 네이버 스노우, 패러닷, 팀러너스, 마루AI, 십단콤보 등이 관련 서비스를 출시한 상태인데요.
(혹시 추가해야 할 기업은 알려주시면 수정하겠습니다)

그 중 AI 프로필 시장의 대표 주자인 네이버 스노우와 렌사와의 비교, 그리고 우리가 직접 해볼 수는 없는지를 확인해 보겠습니다.

1. 필터 특징

avatar 1-min.png(좌) 스노우 (우) 렌사

우선 스노우는 한국인이 좋아할 만한 포인트를 가장 잘 살린 AI 아바타 서비스를 운영 중입니다.
사진 촬영 스튜디오 중 가장 유명한 시현하다, 포토매틱 등의 느낌을 가장 잘 살려준다고 해야 할까요?

반면 렌사는 해당 시장 원조답게 정말 많은 필터를 보유하고 있습니다.
대신 한국인 취향의 필터는 아니고 밝은 톤의 강한 라인을 띄는 이미지를 주로 생성하고 있습니다.

2. 필요한 사진 내용

avartar 2-min.png(좌) 스노우 (우) 렌사

두 서비스 모두 10-20 장의 이미지를 요구하는 것은 동일합니다.
등록 가능한 사진 기준도 거의 유사한 것을 보면 알 수 있는데요.

우선 얼굴을 학습해야 하기 때문에, 동일한 인물 셀카 사진을 필요로 합니다.
반면 얼굴이 작게 나오거나, 흑백, 여러 명의 인물, 일부 부분이 가려지는 등 얼굴 특징을 추출해내기 어려운 이미지는 사용하실 수 없습니다.

참고로 한국은 행정안전부에서 6월 27일 자로 "주민등록증 사진에 변형이 가능하거나 본인 확인이 어려운 사진은 사용할 수 없다" 라고 규정한 상태입니다. 이에 따라 스노우 화면 하단에 관련 내용이 병기되어 있음을 확인할 수 있습니다.

3. 비용 및 시간

avatar 3.png(좌) 스노우 (우) 렌사

우선 스노우는 시간으로 비용을 설정한 것이 특징입니다.

제공되는 이미지 수는 30장 (마음에 드는 사진은 몇 장 이내) 으로 고정되어 있지만, 24시간 내에 전달 받고 싶은 경우, 1시간 내에 전달 받고 싶은 경우에 따라 3,300원 -> 6,600원으로 2배 차이가 나는 것을 확인할 수 있습니다. 빨리빨리 한국인의 특성을 잘 간파한 것으로 봐야 할 것 같습니다. (보통 가격을 얘기할 때 커피에 빗대어 표현하기 때문에, 빨리 받고 싶으면 커피 한 잔 덜 마셔라 같은 느낌)

반면 렌사는 제공되는 이미지 수에 따라 비용이 달라집니다. (50장, 100장, 200장 -> 118원, 89원, 60원)
생성 이미지 50장 기준 스노우에 비해 한 장당 가격이 8원 정도 비싸지만 20분 정도 밖에 소요되지 않아 스노우보다 빠른 결과물 확인이 가능합니다.

그러면 여기서 확인할 수 있는 내용은 다음과 같습니다. ✅

  • 멋지고 예쁜게 최고다 (그런데 '어떻게' 서비스 브랜딩을 할 지는 잘 생각해보자)

  • 이미지, 아직은 맘에 드는 것이 많이 없다 (성공률을 높이자)

  • 시간 너무 오래 소요된다 (더 빨리 학습 가능하게 하자)

  • 사실 원가는 GPU 시간에 비례한다 (위 내용을 달성하면 가격 경쟁력이 높아진다)

  • 셀피 10-20 장은 꽤나 많이 요구하는 것이긴 하다 (향후 개인정보 이슈에 대해 민감해질 수도 있다, 적은 사진으로 효과적인 학습을 하자)

그렇다면 직접 만들어 볼 수는 없을까요? 🤔

간단히 설명을 드리겠습니다.

  1. 우선 사진을 준비한다.

    • 저는 5장을 찍었습니다, 정면은 부담스러워서 제외하고 공유합니다.

    • 여러 각도에서 찍으면 더욱 좋습니다. 다만 얼굴을 크게 찍어주세요. (해당 예시는 조금 잘못된 예시입니다)

      selftest 1.png

  2. 구글 코랩 (GPU) 을 연다.

  • 스테이블 디퓨전의 파인 튜닝 기법인 드림부스(Dreambooth) 나 로라(LoRA) 를 진행하기 위해선 GPU 가 필요합니다.

  • 코랩은 연구/학습용으로 구글이 제공하는 클라우드 기반 Jupyter Notebook 환경입니다. 무료로도 사용 가능합니다.

  • 다음 코드를 입력해주세요.

구글 드라이브 연결 (승인 버튼 클릭 필요)

from google.colab import drive 
drive.mount('/content/drive')

필요 라이브러리 설치 (5분 소요)

!pip install -U autotrain-advanced
!autotrain setup --update-torch
!pip install xformers torch torchvision # in case for using xformers

자동 학습 진행 (A100-40GB, 5장 이미지, 배치 사이즈 1, 스텝 수(epoch) 1,000 기준 1시간 -> 배치 사이즈 키우고, 스텝 수 줄이면 시간 단축 가능) - (24.05.02 수정)

import os

model_name = 'stabilityai/stable-diffusion-xl-base-1.0'
keyword = ' ' # Need_to_fix_a_keyword
prompt = f"photo of a {keyword}" # Need_to_fix_a_keyword
output_path = "/content/drive/MyDrive"
image_path = f"/content/drive/MyDrive/{keyword}" # Need_to_fix_a_keyword

learning_rate = 1e-4
num_steps = 1000
batch_size = 2
gradient_accumulation = 4
resolution = 1024
use_8bit_adam = True
use_xformers = True
mixed_precision = 'fp16'
use_fp16 = True
train_text_encoder = False
disable_gradient_checkpointing = False

os.environ["MODEL_NAME"] = model_name
os.environ["PROJECT_NAME"] = keyword
os.environ["PROMPT"] = prompt
os.environ["IMAGE_PATH"] = image_path
os.environ["LEARNING_RATE"] = str(learning_rate)
os.environ["NUM_STEPS"] = str(num_steps)
os.environ["BATCH_SIZE"] = str(batch_size)
os.environ["GRADIENT_ACCUMULATION"] = str(gradient_accumulation)
os.environ["RESOLUTION"] = str(resolution)
os.environ["USE_8BIT_ADAM"] = str(use_8bit_adam)
os.environ["USE_XFORMERS"] = str(use_xformers)
os.environ["MIXED_PRECISION"] = str(mixed_precision)
os.environ["TRAIN_TEXT_ENCODER"] = str(train_text_encoder)
os.environ["DISABLE_GRADIENT_CHECKPOINTING"] = str(disable_gradient_checkpointing)

!autotrain dreambooth \
--train  \
--xl  \
--model ${MODEL_NAME} \
--project-name ${PROJECT_NAME} \
--image-path ${IMAGE_PATH} \
--prompt "${PROMPT}" \
--resolution ${RESOLUTION} \
--batch-size ${BATCH_SIZE} \
--num-steps ${NUM_STEPS} \
--gradient-accumulation ${GRADIENT_ACCUMULATION} \
--lr ${LEARNING_RATE} \
--mixed-precision ${MIXED_PRECISION} \
$( [[ "$USE_XFORMERS" == "True" ]] && echo "--xformers" ) \
$( [[ "$TRAIN_TEXT_ENCODER" == "True" ]] && echo "--train-text-encoder" ) \
$( [[ "$USE_8BIT_ADAM" == "True" ]] && echo "--use-8bit-adam" ) \
$( [[ "$DISABLE_GRADIENT_CHECKPOINTING" == "True" ]] && echo "--disable_gradient_checkpointing" )

변수(parameter)에 대한 설명은 다음에...

그러면 .safetensor 형식의 파일이 구글 드라이브("/content/drive/MyDrive") 에 저장되어 있을 것입니다.

해당 파일은 얼굴 이미지를 스테이블 디퓨전에 바로 적용 가능하도록 한 일부 레이어의 웨이트 값입니다.

이걸 이제 사용해서 이미지를 만들어 봐야겠죠?

  1. 계속 작업한다.

필요 라이브러리 설치

!pip install torch torchvision invisible_watermark transformers accelerate safetensors
!pip install git+https://github.com/huggingface/diffusers

스테이블 디퓨전 (SDXL) 세팅

from diffusers import DiffusionPipeline, StableDiffusionXLImg2ImgPipeline
import torch
model = "stabilityai/stable-diffusion-xl-base-1.0"
pipe = DiffusionPipeline.from_pretrained(
model,
torch_dtype=torch.float16,
)
pipe.to("cuda")
pipe.load_lora_weights("/content/drive/MyDrive/{filename}.safetensors")
refiner = StableDiffusionXLImg2ImgPipeline.from_pretrained(
"stabilityai/stable-diffusion-xl-refiner-1.0",
torch_dtype=torch.float16,
)
refiner.to("cuda")

이미지 생성

prompt = "A {keyword} man, photorealistic, bold and elegant, close up, sharp expression, look at camera, block noise, vibrant colors, glitchcore, fuzz, color bars, abstract background, pop kei, bold outlines, ultrafine detailed, best quality"
negative_prompt = "ugly, deformed, noisy, blurry, distorted, grainy, text, cropped"
#for seed in range(10):
generator = torch.Generator("cuda").manual_seed(43)
image = pipe(prompt=prompt, negative_prompt=negative_prompt, generator=generator, num_inference_steps=40)
image = image.images[0]
image = refiner(prompt=prompt, negative_prompt=negative_prompt, generator=generator, image=image)
image = image.images[0]

의 과정을 거치면 나오는 이미지들은 다음과 같습니다,

짜잔 🌟

selftest 2.png당장은 작업 시간이 많이 걸리는데

  • 저품질 이미지로도 특징을 추출하는 기술을 통해 빠른 학습 및 추론

  • 좋은 결과물을 만들어 내는 키워드

를 고민해 보고 있습니다.

앞으로 이런 내용들을 많이 공유해드릴게요. 기술적인 내용도 자세하게 다룰 수도 있고요 ㅎㅎ


이정민 (스모어톡, tonylee@smoretalk.io)

35

댓글

로그인 후 댓글을 남길 수 있습니다.

이정민
이정민

재미로 하는 일인데요 ㅎㅎ 감사합니다 :)

김연경
김연경

오 정말 좋은 글입니다. 덕분에 잘 읽고 갑니다.

이정민
이정민

감사합니다 :) 궁금한 내용 있으시면 남겨주시면 글 주제로 생각해보겠습니다.

장영운
장영운

와, 이번 주말에 직접 해볼게요. 정말 감사합니다.

이정민
이정민

저야 말로 읽어주셔서 감사드립니다. 혹시 코드 사용 관련해서 궁금한 거 있으시면 말씀해주세요. 코드 파일(.ipynb) 로 보내드릴게요 :)

LIM
LIM

와 ~~^^ 평소 궁금했는데 감사합니다.

이정민
이정민

관심 있게 읽어주셔서 감사합니다 :)

Doeon Kwon 권도언
Doeon Kwon 권도언

정민님 메이커로그가 Must Reads #243에 선정되었어요! https://stib.ee/xql8

이정민
이정민

캬 첫 번째 Must Reads 입니다.

조현호
조현호

흥미롭네요! 알려주신 방법대로 저도 한번 해봐야겠네요 :) 감사합니다!

이정민
이정민

감사합니다. 혹시 라이브러리 업데이트 때문에 코드가 안 돌아갈 수도 있습니다. 말씀 주시면 제가 해결방법 찾아 안내해드리겠습니다! :)

imstar
imstar

오...! 지금 코랩에다가 실행을 해보는 데 이 전 오류는 해결해보다가 스테이블 디퓨전 (SDXL) 세팅 부분에서 오류가 생기는 데 혹시 라이브러리 업데이트 하면서 바뀐 부분이 있을까용..? 항상 이런 정보 올려주셔서 감사해요 ㅎ

이정민
이정민

안녕하세요! 오 그러게요,,, 코드가 실행이 안되더라고요. 지금 글에 해당 부분 코드 수정했는데 한 번 실행해보아 주시겠어요? :) 저도 우선 학습 돌려보고 있는 상황입니다.

suhan kim
suhan kim

감사합니다! 따라해보고 있는데 모든 {keyword} 여기에 특정 이름을 고정해서 넣어줘야 하는건가요??

이정민
이정민

네 맞습니다. 저 같은 경우는 이름이 이정민이어서 jml 로 사용했습니다.

이선호 (서노)
이선호 (서노)

안녕하세요! 글 보고 코랩에서 따라 해봤는데, 맨 마지막에서 out of memory 문제가 발생했습니다. 혹시 어떻게 해결했는지 알 수 있을까요? 코랩에서 gpu T4 메모리 16G사용했습니다. OutOfMemoryError: CUDA out of memory. Tried to allocate 512.00 MiB (GPU 0; 14.75 GiB total capacity; 12.68 GiB already allocated; 472.81 MiB free; 13.03 GiB reserved in total by PyTorch) If reserved memory is >> allocated memory try setting max_split_size_mb to avoid fragmentation. See documentation for Memory Management and PYTORCH_CUDA_ALLOC_CONF

이정민
이정민

안녕하세요! 혹시 batch_size = 1로 한 번 해보시겠어요? 시간은 오래 걸릴텐데 가능할 것 같습니다. 직접 해보지는 않았는데 수치를 보니까 배치 크기만 줄이면 될 것 같네요.

서지수
서지수

안녕하세요..! 저 동일한 에러가 나고, batch_size = 1로 했는데도 똑같은 에러가 나는데, 어떻게 해결할 수 있을까요?

이썬즈
이썬즈

안녕하세요 이미지 생성부분 까지 마지막 코드를 정상적으로 입력 했는데, 코랩에서 이미지가 생성되지 않고 단순히 초록색 100% 바 2개만 출력되네요. 이미지는 어떻게 하면 출력되는지 궁금합니다.

이정민
이정민

안녕하세요! 마지막에 새로운 코드 블럭을 만들어서 image 만 입력하고 실행시키면 이미지가 출력될 거에요. 혹시 또 궁금한 것 있으시면 문의주세요 :)

정말이거 재밌는데
정말이거 재밌는데

raise ValueError("❌ Please specify a valid image directory") 에러가 발생하는데 Google Drive 에 이미지를 어떤구조로 넣고 path 를 지정해야할까요?

이정민
이정민

안녕하세요, 연락을 늦게 드리게 되어 죄송합니다. drive mount 하신 경우에는 /content/drive/MyDrive/ 를 prefix로 하여 학습 위한 이미지 담긴 폴더 경로로 작성하시면 됩니다.

서지수
서지수

안녕하세요? autotrain dreambooth 부분에서, /bin/bash: line 1: autotrain: command not found 이러한 에러가 나는데, 어떻게 해결할 수 있을까요..?

이정민
이정민

안녕하세요! 혹시 colab 에서 돌리고 계신가요? 제가 최근에 해당 코드를 안 돌린지가 좀 되서 코드를 보아야 할 것 같은데, 기본 개발 환경을 먼저 확인해보고자 문의드립니다.

서지수
서지수

네! colab에서 돌리고 있습니다!

서지수
서지수

그런데 그 전에 첫 pip에서부터 ERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts. google-colab 1.0.0 requires pandas==2.0.3, but you have pandas 2.2.2 which is incompatible. tensorflow 2.15.0 requires tensorboard<2.16,>=2.15, but you have tensorboard 2.16.2 which is incompatible. tensorflow-metadata 1.15.0 requires protobuf<4.21,>=3.20.3; python_version < "3.11", but you have protobuf 4.23.4 which is incompatible. 이런 에러가 났었네요...

이정민
이정민

!pip install -U autotrain-advanced !autotrain setup --update-torch 하시면 패키지 로딩 관련 이유로 재시작 하라는 알람이 갈 거에요. 그대로 재시작 하시면 작업이 되는 것 같습니다. 코드는 autotrain-advanced 라이브러리 보니까 일부 parameter 가 변경 되어서 그거 알려드릴게요.

이정민
이정민

라이브러리 포함해서 코드 수정을 다 하고 동작 여부도 확인했는데, 확실히 요즘 많이 안 사용하는 방식이다 보니 학습 시간이 엄청 걸리기는 하네요. 신규 코드로 한 번 업데이트 해서 글을 작성해야 될 것 같습니다. 확인해주셔서 감사합니다!

서지수
서지수

감사합니다. pip install --upgrade pip 이 명령어를 가장 먼저 작성한 후에 돌리니 뒤의 설치들은 잘 됩니다!

서지수
서지수

안녕하세요, 한 가지 더 질문해도 될까요?ㅠㅠ 자동 학습 중에 usage: autotrain <command> [<args>] AutoTrain advanced CLI: error: unrecognized arguments: --fp16 --gradient-checkpointing 라는 에러가 뜨는데, 혹시 이 부분은 어떤 문제인 것일까요??

이정민
이정민

fp16, gradient-checkpointing 이라는 parameter 가 autotrain-advanced 라이브러리의 autotrain 함수에서 사라졌어요. 그래서 해당 글에 코드를 새로 수정해서 두었습니다. 그걸로 하시면 작동할 거에요 ㅎㅎ

서지수
서지수

안녕하세요, 맨 마지막 생성 단계에서 OutOfMemoryError: CUDA out of memory. Tried to allocate 1024.00 MiB. GPU와 같은 에러가 나는데 어떻게 하면 해결할 수 있을까요?ㅠㅠ

이정민
이정민

요건 이제 GPU 의 메모리 문제입니다. 코드 상에서 해결할 수 없고, 더 큰 메모리를 가진 GPU 를 사용해야 하는 건데요. 즉, 비싼 비용을 들이셔야 하는데, 해당 학습 방법은 전체 모델 layer 를 학습시키는 Dreambooth 기반이고, 일부 Layer 만 학습시키는 LoRA 와 함께 학습 변수(batch size, gradient accumulation)를 조정하면 메모리를 좀 줄일 수 있을 거에요. 그리고 torch 가 2.0 버전 이상이 되면서 memory 최적화 할 수 있는 방식이 좀 달라져서 그 부분도 고려해보시면 좋을 것 같습니다.

서지수
서지수

정말 감사합니다!!ㅠㅠ AI를 하려면 비용을 들이는 건 어쩔 수가 없군요..

이정민
이정민

요건 제가 다음 주 중으로 코드 한 번 공유해드릴게요. 혹시 필요한 내용이 개인 프로젝트 때문인가요? 아니면 근무하시는 일 때문인가요? 급하시면 빨리 글을 작성해야겠다 싶어서요.

ouufff
ouufff

마지막 코드에서 RuntimeError: CUDA error: CUDA driver version is insufficient for CUDA runtime version CUDA kernel errors might be asynchronously reported at some other API call, so the stacktrace below might be incorrect. 이런 오류가 뜨는데 어떻게 해결할 수 있을까요?

이정민
이정민

안녕하세요, 혹시 코드 구동 환경이 어떻게 되는 지 알 수 있을까요? 지금 CUDA 버전 차이가 있는 것 같은데 확인이 필요합니다.