1 데이터셋

Hugging Face 웹사이트에서 데이터와 사전학습모델을 다운로드 받아 딥러닝 모델의 개발 생산성을 높일 수 있다.

Hugging Face에서 다른 설정을 특별히 하지 않게 되면 윈도우의 경우 다음 디렉토리에 데이터와 사전학습모델이 저장된다.

  • C:\Users\사용자명\.cache\huggingface\datasets\

datasets 에 포함된 데이텟을 파이썬에서 일별한다.

## 다운로드 받은 데이터셋을 삭제하지 않는 기능
from datasets import disable_caching
from datasets import load_dataset
disable_caching()

from datasets import list_datasets
datasets_list = list_datasets()
len(datasets_list)
7908

기계학습의 가장 대표적인 데이터셋이 붓꽃(iris) 데이터셋이 유명하기 때문에 datasets 패키지에 포함된 데이터 중 iris 데이터세을 다운로드받아 이를 기계학습 분석에 활용한다.

reticulate 패키지 파이썬 객체를 R에서 가져와서 iris 데이터셋을 확인한다.

library(reticulate)
library(tidyverse)

py$datasets_list %>% 
  enframe() %>% 
  filter(str_detect(value, "iris"))
# A tibble: 2 × 2
   name value            
  <int> <chr>            
1  4381 Gifted/iris      
2  5676 scikit-learn/iris

붓꽃 데이터를 팬다스 데이터프레임으로 변환한 후에 기계학습을 위한 준비 데이터로 되었는지 출력하여 확인한다.

iris = load_dataset('scikit-learn/iris', 
                       download_mode="reuse_dataset_if_exists",
                       cache_dir='z:\dataset')

print(iris)

iris_pd = iris['train'].to_pandas()

iris_pd
      Id  SepalLengthCm  ...  PetalWidthCm         Species
0      1            5.1  ...           0.2     Iris-setosa
1      2            4.9  ...           0.2     Iris-setosa
2      3            4.7  ...           0.2     Iris-setosa
3      4            4.6  ...           0.2     Iris-setosa
4      5            5.0  ...           0.2     Iris-setosa
..   ...            ...  ...           ...             ...
145  146            6.7  ...           2.3  Iris-virginica
146  147            6.3  ...           1.9  Iris-virginica
147  148            6.5  ...           2.0  Iris-virginica
148  149            6.2  ...           2.3  Iris-virginica
149  150            5.9  ...           1.8  Iris-virginica

[150 rows x 6 columns]

마찬가지 방식으로 질의응답 데이터셋(squad), 영화평점 imdb 데이터를 다운로드한다. 저장장소로 cache_dir='z:\dataset' 와 같이 (시놀로지) NAS 디렉토리를 지정하여 저장한다.

squad = load_dataset('squad', 
                       download_mode="reuse_dataset_if_exists",
                       cache_dir='z:\dataset')
                       
imdb = load_dataset('imdb', 
                       download_mode="reuse_dataset_if_exists",
                       cache_dir='z:\dataset')

2 이미지 데이터셋

개와 고양이 이미지 분류가 첫 딥러닝 모형이라 이를 잘 구분하는 분류기를 제작하기 위해서 데이터셋을 다운로드한다. 먼저 고양이(cats)가 포함된 데이터셋를 찾아 … cats_vs_dogs 명칭을 갖는 데이터셋을 다운로드 한다.

py$datasets_list %>% 
  enframe() %>% 
  filter(str_detect(value, "cats"))
# A tibble: 17 × 2
    name value                                  
   <int> <chr>                                  
 1    78 cats_vs_dogs                           
 2  1808 hf-internal-testing/cats_vs_dogs_sample
 3  2063 huggingface/cats-image                 
 4  2431 nateraw/auto-cats-and-dogs             
 5  2437 nateraw/cats-and-dogs                  
 6  2438 nateraw/cats_vs_dogs                   
 7  2458 ncats/EpiSet4BinaryClassification      
 8  2459 ncats/EpiSet4NER-v1                    
 9  2460 ncats/GARD_EpiSet4TextClassification   
10  3518 huggan/cats                            
11  3963 XiangPan/online_shopping_10_cats_62k   
12  4250 davanstrien/human_cats                 
13  4707 ncats/EpiSet4NER-v2                    
14  5495 nateraw/cats-and-dogs-with-metadata    
15  5497 nateraw/cats-and-dogs-metadata         
16  5595 efederici/cats_vs_dogs                 
17  7649 n6L3/online_shopping_10_cats           

대안으로 Hugging Face - Datasets 에서 검색을 넣어 가장 많은 다운로드를 기록한 데이터셋을 다운로드한다.

cats_vs_dogs = load_dataset('hf-internal-testing/cats_vs_dogs_sample', 
                       download_mode="reuse_dataset_if_exists",
                       cache_dir='z:\dataset')

cats_vs_dogs['train'].to_pandas()
                                                image  labels
0   {'bytes': None, 'path': 'z:\dataset\downloads\...       0
1   {'bytes': None, 'path': 'z:\dataset\downloads\...       0
2   {'bytes': None, 'path': 'z:\dataset\downloads\...       0
3   {'bytes': None, 'path': 'z:\dataset\downloads\...       0
4   {'bytes': None, 'path': 'z:\dataset\downloads\...       0
5   {'bytes': None, 'path': 'z:\dataset\downloads\...       0
6   {'bytes': None, 'path': 'z:\dataset\downloads\...       0
7   {'bytes': None, 'path': 'z:\dataset\downloads\...       0
8   {'bytes': None, 'path': 'z:\dataset\downloads\...       0
9   {'bytes': None, 'path': 'z:\dataset\downloads\...       0
10  {'bytes': None, 'path': 'z:\dataset\downloads\...       0
11  {'bytes': None, 'path': 'z:\dataset\downloads\...       0
12  {'bytes': None, 'path': 'z:\dataset\downloads\...       0
13  {'bytes': None, 'path': 'z:\dataset\downloads\...       0
14  {'bytes': None, 'path': 'z:\dataset\downloads\...       0
15  {'bytes': None, 'path': 'z:\dataset\downloads\...       0
16  {'bytes': None, 'path': 'z:\dataset\downloads\...       0
17  {'bytes': None, 'path': 'z:\dataset\downloads\...       0
18  {'bytes': None, 'path': 'z:\dataset\downloads\...       0
19  {'bytes': None, 'path': 'z:\dataset\downloads\...       0
20  {'bytes': None, 'path': 'z:\dataset\downloads\...       0
21  {'bytes': None, 'path': 'z:\dataset\downloads\...       0
22  {'bytes': None, 'path': 'z:\dataset\downloads\...       0
23  {'bytes': None, 'path': 'z:\dataset\downloads\...       0
24  {'bytes': None, 'path': 'z:\dataset\downloads\...       0
25  {'bytes': None, 'path': 'z:\dataset\downloads\...       1
26  {'bytes': None, 'path': 'z:\dataset\downloads\...       1
27  {'bytes': None, 'path': 'z:\dataset\downloads\...       1
28  {'bytes': None, 'path': 'z:\dataset\downloads\...       1
29  {'bytes': None, 'path': 'z:\dataset\downloads\...       1
30  {'bytes': None, 'path': 'z:\dataset\downloads\...       1
31  {'bytes': None, 'path': 'z:\dataset\downloads\...       1
32  {'bytes': None, 'path': 'z:\dataset\downloads\...       1
33  {'bytes': None, 'path': 'z:\dataset\downloads\...       1
34  {'bytes': None, 'path': 'z:\dataset\downloads\...       1
35  {'bytes': None, 'path': 'z:\dataset\downloads\...       1
36  {'bytes': None, 'path': 'z:\dataset\downloads\...       1
37  {'bytes': None, 'path': 'z:\dataset\downloads\...       1
38  {'bytes': None, 'path': 'z:\dataset\downloads\...       1
39  {'bytes': None, 'path': 'z:\dataset\downloads\...       1
40  {'bytes': None, 'path': 'z:\dataset\downloads\...       1
41  {'bytes': None, 'path': 'z:\dataset\downloads\...       1
42  {'bytes': None, 'path': 'z:\dataset\downloads\...       1
43  {'bytes': None, 'path': 'z:\dataset\downloads\...       1
44  {'bytes': None, 'path': 'z:\dataset\downloads\...       1
45  {'bytes': None, 'path': 'z:\dataset\downloads\...       1
46  {'bytes': None, 'path': 'z:\dataset\downloads\...       1
47  {'bytes': None, 'path': 'z:\dataset\downloads\...       1
48  {'bytes': None, 'path': 'z:\dataset\downloads\...       1
49  {'bytes': None, 'path': 'z:\dataset\downloads\...       1

딥러닝 가장 인기가 많은 mnist 데이터셋도 다운로드 받아 NAS 저장소에 저장한다. 공통적으로 .arrow 파일 확장자가를 갖는 파일로 저장된다.

mnist = load_dataset('mnist', 
                       download_mode="reuse_dataset_if_exists",
                       cache_dir='z:\dataset')

mnist
DatasetDict({
    train: Dataset({
        features: ['image', 'label'],
        num_rows: 60000
    })
    test: Dataset({
        features: ['image', 'label'],
        num_rows: 10000
    })
})

3 HF 파이프라인

3.1 모형/데이터 저장위치

허깅페이스 캐쉬 저장소를 지정하는 방식은 크게 3가지로 나눠진다.

  • 파이썬 내 환경설정
import os
os.environ['TRANSFORMERS_CACHE'] = '/blabla/cache/'
  • 배쉬(bash) 환경설정
    • export TRANSFORMERS_CACHE=/blabla/cache/
  • 딥러닝 코드에서 직접 지정
tokenizer = AutoTokenizer.from_pretrained("roberta-base", cache_dir="new_cache_dir/")

model = AutoModelForMaskedLM.from_pretrained("roberta-base", cache_dir="new_cache_dir/")

3.2 NLP 기본기

Hugging Face Course에 담기 내용을 바탕으로 자세히 살펴보자.

3.2.1 감성분석

distilbert-base-uncased-finetuned-sst-2-english 학습된 모형으로 문장에 담긴 감성을 분석한다. 허깅페이스 캐쉬 디렉토리에 저장된 ‘z:/dataset/hf’ 에서 모형을 가져와서 감성분석을 진행한다.

# ! pip install datasets transformers[sentencepiece]

import os
os.environ['TRANSFORMERS_CACHE'] = 'z:/dataset/hf'

from transformers import pipeline
<frozen importlib._bootstrap>:219: RuntimeWarning: scipy._lib.messagestream.MessageStream size changed, may indicate binary incompatibility. Expected 56 from C header, got 64 from PyObject
classifier = pipeline("sentiment-analysis")
                      
No model was supplied, defaulted to distilbert-base-uncased-finetuned-sst-2-english (https://huggingface.co/distilbert-base-uncased-finetuned-sst-2-english)
classifier(
    [
        "I've been waiting for a HuggingFace course my whole life.",
        "I hate this so much!",
        "We are very happy to show you the 🤗 Transformers library.", 
        "We hope you don't hate it."
    ]
)
[{'label': 'POSITIVE', 'score': 0.9598049521446228}, {'label': 'NEGATIVE', 'score': 0.9994558691978455}, {'label': 'POSITIVE', 'score': 0.9997795224189758}, {'label': 'NEGATIVE', 'score': 0.5308623313903809}]

한단계 더 들어가 tokenizer와 model을 각기 달리하여 파이프라인을 구성한 후에 문장에 대한 감성을 파악할 수 있다.

from transformers import AutoTokenizer
from transformers import AutoModelForSequenceClassification

model_name = "nlptown/bert-base-multilingual-uncased-sentiment"
tokenizer = AutoTokenizer.from_pretrained(model_name, cache_dir="z:/dataset/hf")

model_name = "nlptown/bert-base-multilingual-uncased-sentiment"
pt_model = AutoModelForSequenceClassification.from_pretrained(model_name,
           cache_dir="z:/dataset/hf")

classifier = pipeline("sentiment-analysis",
                       model = pt_model,
                       tokenizer = tokenizer)
                      
classifier(
    [
        "지금 기분이 좋습니다.",
        "나는 행복합니다",
        "무척이나 슬프고 서럽습니다",
        "영화가 그저그렇다."
    ]
)
 
# [{'label': '4 stars', 'score': 0.3802778422832489}, {'label': '5 stars', 'score': 0.5900374054908752}, {'label': '1 star', 'score': 0.5471497774124146}, {'label': '3 stars', 'score': 0.3373289406299591}]

3.2.2 주제 분류

주어진 문장이 어떤 주제로 분류되는지를 facebook/bart-large-mnli 사전학습모형으로 분류할 수 있다. facebook/bart-large-mnli에서 자세한 사항을 확인할 수 있다.

from transformers import AutoModelForSequenceClassification, AutoTokenizer
from transformers import pipeline

nli_model = AutoModelForSequenceClassification.from_pretrained('facebook/bart-large-mnli',
            cache_dir="z:/dataset/hf")
            
tokenizer = AutoTokenizer.from_pretrained('facebook/bart-large-mnli',
            cache_dir="z:/dataset/hf")

classifier = pipeline('zero-shot-classification',
                       model     = nli_model,
                       tokenizer = tokenizer)
                       
sequence_to_classify = "one day I will see the world"
candidate_labels = ['travel', 'cooking', 'dancing']
classifier(sequence_to_classify, candidate_labels,  multi_label=True)
# {'sequence': 'one day I will see the world', 'labels': ['travel', 'dancing', 'cooking'], 'scores': [0.994511067867279, 0.005706145893782377, 0.0018192846328020096]}

3.2.3 텍스트 생성

gpt2를 사용해서 텍스트를 생성할 수 있다.

from transformers import pipeline, set_seed
from transformers import GPT2Tokenizer, GPT2LMHeadModel

gpt2_tokenizer = GPT2Tokenizer.from_pretrained('gpt2', cache_dir="z:/dataset/hf")
gpt2_model = GPT2LMHeadModel.from_pretrained('gpt2', cache_dir="z:/dataset/hf")

generator = pipeline('text-generation', 
                      tokenizer = gpt2_tokenizer,
                      model     = gpt2_model)
set_seed(777)
generator("The White man worked as a", max_length=12, num_return_sequences=3)
# [{'generated_text': 'The White man worked as a janitor, a regular office'}, {'generated_text': 'The White man worked as a sales rep for the paper.'}, {'generated_text': 'The White man worked as a contractor for Waffle House in'}]

generator("In this course, we will teach you how to", max_length=20, num_return_sequences=3)

# [{'generated_text': 'In this course, we will teach you how to create a reusable, self-sustaining app'}, {'generated_text': 'In this course, we will teach you how to create a perfect web application.'}, {'generated_text': 'In this course, we will teach you how to use both the HN and the NN channels'}]

3.2.4 빈칸 채워넣기

BertForMaskedLM 모형을 사용해서 [MASK] 빈칸 채워넣기를 할 수 있다.

from transformers import pipeline, set_seed
from transformers import  BertTokenizer, BertForMaskedLM

fill_mask_tokenizer = BertTokenizer.from_pretrained('bert-base-uncased', cache_dir="z:/dataset/hf/mask")
fill_mask_model = BertForMaskedLM.from_pretrained("bert-base-uncased", cache_dir="z:/dataset/hf/mask")

unmasker = pipeline('fill-mask', 
                     tokenizer = fill_mask_tokenizer,
                     model = fill_mask_model)
                     
unmasker("The White man worked as a [MASK].", top_k = 3)
# [{'score': 0.16597844660282135, 'token': 10533, 'token_str': 'c a r p e n t e r', 'sequence': 'the white man worked as a carpenter.'}, {'score': 0.09424988180398941, 'token': 7500, 'token_str': 'f a r m e r', 'sequence': 'the white man worked as a farmer.'}, {'score': 0.07112522423267365, 'token': 20987, 'token_str': 'b l a c k s m i t h', 'sequence': 'the white man worked as a blacksmith.'}]

unmasker("The black woman worked as a [MASK].", top_k = 3)
# [{'score': 0.21546946465969086, 'token': 6821, 'token_str': 'n u r s e', 'sequence': 'the black woman worked as a nurse.'}, {'score': 0.19593699276447296, 'token': 13877, 'token_str': 'w a i t r e s s', 'sequence': 'the black woman worked as a waitress.'}, {'score': 0.09739767760038376, 'token': 10850, 'token_str': 'm a i d', 'sequence': 'the black woman worked as a maid.'}]

unmasker("The Asian worked as a [MASK].", top_k = 3)
# [{'score': 0.12938520312309265, 'token': 7500, 'token_str': 'f a r m e r', 'sequence': 'the asian worked as a farmer.'}, {'score': 0.09072186052799225, 'token': 3836, 'token_str': 't e a c h e r', 'sequence': 'the asian worked as a teacher.'}, {'score': 0.039076220244169235, 'token': 10533, 'token_str': 'c a r p e n t e r', 'sequence': 'the asian worked as a carpenter.'}]

unmasker("The Korean worked as a [MASK].", top_k = 3)
# [{'score': 0.11826611310243607, 'token': 7500, 'token_str': 'f a r m e r', 'sequence': 'the korean worked as a farmer.'}, {'score': 0.09532739222049713, 'token': 3836, 'token_str': 't e a c h e r', 'sequence': 'the korean worked as a teacher.'}, {'score': 0.04381617531180382, 'token': 5160, 'token_str': 'l a w y e r', 'sequence': 'the korean worked as a lawyer.'}]

3.2.5 질의응답

SQuAD2.0 데이터셋에 기반한 deepset/roberta-base-squad2 모형을 바탕으로 질의응답을 구현할 수 있다.

from transformers import pipeline
from transformers import AutoModelForQuestionAnswering, AutoTokenizer

qna_tokenizer = AutoTokenizer.from_pretrained("deepset/roberta-base-squad2",
                cache_dir="z:/dataset/pretrained/")

qna_model = AutoModelForQuestionAnswering.from_pretrained("deepset/roberta-base-squad2",              
            cache_dir="z:/dataset/pretrained/")

qNa = pipeline('question-answering', 
                model=qna_model,
                tokenizer=qna_tokenizer) 


paragraph = '''
A new study estimates that if the US had universally mandated masks on 1 April, there could have been nearly 40% fewer deaths by the start of June. Containment policies had a large impact on the number of COVID-19 cases and deaths, directly by reducing transmission rates and indirectly by constraining people’s behaviour. They account for roughly half the observed change in the growth rates of cases and deaths.
'''

qNa({'question': 'Which country is this article about?',
     'context': f'{paragraph}'})
# {'score': 0.019898569211363792, 'start': 35, 'end': 37, 'answer': 'US'}
qNa({'question': 'Which disease is discussed in this article?',
     'context': f'{paragraph}'})
# {'score': 0.00024747499264776707, 'start': 206, 'end': 214, 'answer': 'COVID-19'}

3.2.6 번역

Helsinki-NLP/opus-mt-ko-en 모델은 한글을 입력받아 영어로 번역한다.

from transformers import pipeline
from transformers import AutoTokenizer, AutoModelForSeq2SeqLM

translator_tokenizer = AutoTokenizer.from_pretrained("Helsinki-NLP/opus-mt-ko-en",
                cache_dir="z:/dataset/hf/")

translator_model = AutoModelForSeq2SeqLM.from_pretrained("Helsinki-NLP/opus-mt-ko-en",              
            cache_dir="z:/dataset/hf/")


translator = pipeline("translation", 
                      tokenizer = translator_tokenizer,
                      model =  translator_model)
                      
translator("대한민국 축구가 드디어 독일을 격파했습니다.")
# [{'translation_text': 'South Korean football finally destroyed Germany.'}]
translator("President Yoon did a great work in Korean history")
# [{'translation_text': 'President Yoon did a great job in Coran history'}]

3.2.7 텍스트 요약

CNN Daily Mail 데이터를 기반으로 하고 있는 facebook/bart-large-cnn 모델을 활용하여 문단을 요약한다.

from transformers import pipeline
from transformers import AutoModelForSeq2SeqLM, AutoTokenizer

summary_tokenizer = AutoTokenizer.from_pretrained("facebook/bart-large-cnn",
                                                  cache_dir="z:/dataset/hf/")
                                          
summary_model = AutoModelForSeq2SeqLM.from_pretrained("facebook/bart-large-cnn",
                                          cache_dir="z:/dataset/hf/")


summarizer = pipeline("summarization", 
                      model = summary_model,
                      tokenizer = summary_tokenizer)

paragraph = '''
A new study estimates that if the US had universally mandated masks on 1 April, there could have been nearly 40% fewer deaths by the start of June. Containment policies had a large impact on the number of COVID-19 cases and deaths, directly by reducing transmission rates and indirectly by constraining people’s behaviour. They account for roughly half the observed change in the growth rates of cases and deaths.
'''
                      
summarizer(paragraph, max_length=50, min_length=30, do_sample=False)
[{'summary_text': 'Study estimates that if the US had universally mandated masks on 1 April, there could have been nearly 40% fewer deaths by the start of June. Containment policies had a large impact on the number of COVID-19 cases and deaths'}]