HuggingFace로 모델 학습시키기 - 2

안녕하세요.

HuggingFace 10기 파트너 정정민입니다.


이번에는 9기 마지막 포스팅이었던,

HuggingFace로 모델 학습시키기 - 1 포스팅의 뒷 부분 내용을 적어보려 합니다.



살짝 리마인드


딥러닝 모델의 학습은 위와 같이

  • 데이터를 불러오고 : Data

  • 모델에게 넣어줄 수 있는 형태로 변경하고 : Pre-processing

  • 모델에 넣어서 정답을 기반으로 학습을 진행하며 : Feed forward, Loss, Optimize

  • 학습이 다 된 후, 모델의 결과를 사람이 이해할 수 있는 형태로 변화 : Post-processing

과정으로 구성됩니다.


각각의 과정은 개별적인 module로 구현되고 핸들링이 되어져야 했습니다.

(심지어 내부에 더욱 더 복잡한 과정들이 포함되어 있어요!!)


하지만 HuggingFace에서는

각 과정을 포함해, 추가로 필요한 과정을

추상적으로 구현할 수 있도록 지원해줍니다.

각 과정들에 대응되는 HuggingFace 코드 개념이 위 그림의 빨간 글씨로 표시되어있습니다.



사용할 데이터 다운로드 및 준비 (Data)

이번 포스팅에서는 이전 제 포스팅에서 살펴보았던 인도 음식 이미지 데이터셋을 사용하려 합니다.


공개된 해당 데이터는 간단한 huggingface 함수를 통해 불러올 수 있습니다.

dataset = load_dataset("rajistics/indian_food_images")

Downloading readme: 100%|██████████| 660/660 [00:00<00:00, 1.81MB/s]
Downloading metadata: 100%|██████████| 1.20k/1.20k [00:00<00:00, 2.74MB/s]
Downloading data: 100%|██████████| 1.36G/1.36G [01:09<00:00, 19.6MB/s]
Downloading data: 100%|██████████| 241M/241M [00:14<00:00, 16.9MB/s] 
Generating train split: 100%|██████████| 5328/5328 [00:04<00:00, 1328.32 examples/s]
Generating test split: 100%|██████████| 941/941 [00:00<00:00, 1898.49 examples/s]


이전 포스팅과 중복되는 내용이 많아

구체적인 내용이 궁금하시면 이전 포스팅을 참고해주세요 ^^



학습에 맞는 데이터 변환 (Pre-processing)

일반적으로 수집한 데이터는

그 자체로 바로 딥러닝 모델에 들어가기가 어렵습니다.

즉, 모델이 잘 이해할 수 있는 형태로 변환이 필요합니다.


그럼 모델이 어떤 데이터를 받아들일 수 있을까요??

이는 다루는 모델, 데이터, 상황에 따라 다릅니다. ㅠㅠ


이러한 어려움을 해결하기위해 HuggingFace에서는

기준이 될 만한 선행 연구 모델의 변환 과정을 함께 수집 & 제공해줍니다.


이번 실습에서는 ResNet-18 이라는 이미지 처리 기본 모델을 사용할 예정입니다.

따라서 이 모델을 학습시켰던 상황에서의 데이터 전처리 과정을 그대로 가져옵니다.

그리고 해당 과정을 전체 데이터에 적용해 데이터를 변환하죠!

image_processor = AutoImageProcessor.from_pretrained("microsoft/resnet-18")
image_processor.size['shortest_edge'] = 32 # 사용할 이미지 크기를 작게 설정합니다. 원래 : 224 

def preprocess_data(examples): 
    images = examples["image"]
    images = [image.convert("RGB") for image in images]
    pixel_values = image_processor(images, return_tensors="pt").pixel_values
    labels = examples["label"]
    return {"pixel_values": pixel_values, "labels": labels}

train_dataset = dataset["train"].with_transform(preprocess_data)
test_dataset = dataset["test"].with_transform(preprocess_data)


데이터 변환에 필요한 과정은

다소 깊이 있는 딥러닝 이론 내용이라 여기서는 생략하겠습니다!



모델 생성

앞서 ResNet-18이라는 모델을 사용한다고 했죠?

이 모델 또한 매우 간단한 방법으로 불러옵니다.


기본적으로 HuggingFace에서는 AutoModelLoader라는 함수를 사용해 모델을 불러오지만

ResNet 모델은 더욱 구체화 된 함수(ResNetForImageClassification)를 사용해 불러옵니다.

(정확히는 AutoModelLoader 함수에는 구현이 안되어있습니다 ㅎㅎ;;)


model = ResNetForImageClassification.from_pretrained("microsoft/resnet-18",
    id2label={idx: food for idx, food in enumerate(dataset['train'].features['label'].names)},
    label2id={food: idx for idx, food in enumerate(dataset['train'].features['label'].names)},
    ignore_mismatched_sizes=True)

torch.nn.init.kaiming_normal_(model.classifier[1].weight, mode='fan_out')
torch.nn.init.zeros_(model.classifier[1].bias)


위 과정을 진행하면, 학습이 완료된 모델을 불러옵니다.

하지만 우리는 인도 음식 분류에 최적화 된 모델을 새로 학습 시킬 예정이잖아요?

그래서 모델의 뒷 부분을 약간 변경해야 합니다.

그것을 위해 id2label이라든지, label2id, 혹은 torch.nn.init이라는 과정을 진행합니다.



학습 고고씽


이제 학습을 위한 준비가 거의 완료되었습니다.

HuggingFace를 사용하지 않는다면

이제부터 위 그림에 있는 Feed forward, Loss, Optimizer 와 같은 과정을 구현해야하는데,

HuggingFace에서는 Trainer라는 객체로 알아서 학습하게 해줍니다.


그리고 그 Trainer가 어떻게 움직이게 할지

학습에 필요한 명세(설정)를 TrainingArguments 라는 객체로 넘겨주죠


training_args = TrainingArguments(
    output_dir="./results", # 저장 위치 
    learning_rate=0.001,  # 학습 속도 
    num_train_epochs=10, # 학습량 
    per_device_train_batch_size=256, # 학습 시 한번에 사용할 데이터 수 
    per_device_eval_batch_size=256, # 학습 중간의 평가 시 한번에 사용할 데이터 수 
    remove_unused_columns=False, # 불러오는 데이터 중 데이터 강제 누락 여부 
    eval_steps=5, # 평가 주기 
    save_steps=25, # 저장 주기 
    logging_steps=20, # 평가 결과 추적 주기 
    evaluation_strategy="steps", # 평가 시간 단위 
    save_total_limit=2, # 저장 갯수 
    load_best_model_at_end=True, # 학습 완료 후 로드 모델 지정 
)

trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=train_dataset,
    eval_dataset=test_dataset,
    compute_metrics=metric_fc,
    data_collator=collate_fc,
)


위에 적은 설정 조건 이외에도 엄~청 많은 파라미터들이 있습니다.

그래서 다양한 조건으로 학습할 수 있도록 지원하죠!


이제 학습 해볼까요??

trainer.train()


참 쉽죠?? ㅎㅎ


이후 과정

학습 이후에는 학습한 모델을 가지고

실제 이미지를 넣어보고 결과를 살펴볼 시간입니다만,

이건 다음 포스팅에서 조금 더 살펴보도록 하겠습니다 ㅎㅎ



주의사항

HuggingFace는

Pytorch 라는 딥러닝 프레임워크를 쉽게 사용할 수 있도록 만든 wrapper입니다.


그 말은 즉,

쉽게 사용할 수 있지만

그만큼 사용할 수 있는 환경이 제한적일 수 있다는 말입니다.


HuggingFace에서 많이 제공하려하겠지만

고급 모델을 만들고, 고급 학습 방법을 사용하려면

어쩔 수 없이 포장지(wrapper) 안에 있는 Pytorch라는 프레임워크를 사용해야 합니다.


마치 에어컨 컨트롤러를 통해 에어컨을 조작할 때,

간단한 조작은 매우 쉽지만

구체적으로 방향을 바꾸거나, 시간 설정을 한다면

뚜껑을 열어야 하는것과 비슷합니다.



그럼에도 사용법을 익힌다면

쉽게 코드를 구현하고 실행시킬 수 있음은 분명해 보입니다!



다음 포스팅은

학습 이후 실제 이미지를 불러와 테스트 해보는 시간을 갖도록 하겠습니다.


제가 학습시킨 모델이

맛있는 난을 알아볼 수 있는지 기대해주세요 ^^


감사합니다.

#10기HuggingFace #10기 #HuggingFace



작성자 : 정정민

블로그 : 링크

4
1개의 답글

👉 이 게시글도 읽어보세요