Python(Colab) 자연어처리 + HuggingFace 사용해보기

2023. 7. 11. 15:07파이썬/자연어 처리

✔️ Huggingface

* 머신 러닝을 사용하여 애플리케이션을 구축하기 위한 도구를 개발하는 회사
* 자연어 처리 애플리케이션용으로 구축된 Transformers 라이브러리와 사용자가 기계 학습 모델 및 데이터셋을 공유할 수 있는 플랫폼으로 유명
* 허깅페이스에 모델들은 기본적으로 PretrainedModel 클래스를 상속 받고 있다.

 


Huggingface 사용해보기

!pip install transformers
 
from transformers import AutoModel, AutoTokenizer, BertTokenizer
AutoModel 모듈 : 모델에 관한 정보를 처음부터 명시하지 않아도 자동으로 설정해주는 라이브러리
AutoTokenizer 모듈: 토큰화를 시켜주는 모듈
BertTokenizer 모듈: Bert모델에 특화 되어 있는 토큰나이저(텍스트를 작은 단위로 분할)

 

 

1. 미리 학습된 huggingface의 모델 불러오기 

access_token = 미리 huggingface의 인증키를 발급받기

bert_model = AutoModel.from_pretrained("bert-base-cased", use_auth_token=access_token

 

 

 

2. 사전 학습된 단어사전 확인하기

print(bert_tokenizer.vocab_size)

 

 

for i, key  in enumerate(bert_tokenizer.get_vocab()):
    print(key)
    if i > 10:
        break

 

 

 

3. 예제 문장 넣어서 모델에 적용해보기

tokenized_input_text = bert_tokenizer(sample_1,return_tensors='pt')

for key,value in tokenized_input_text.items():
    print('{}:\n\t{}'.format(key,value))
해석
모델에 적용 (return_tensor 파라미터는 token을 어떤 타입으로 반환할지 설정 pt:파이토치 / tf:트랜스폼/np:nparray)

for문을 통해 출력해보기
tokenized_input_text 안에는 input_ids / token_type_ids / attention_mask가 존재

input_ids : 맨앞에 101.102는 특별한 키(101 ~ 102는 한 문장의 시작과 끝을 의미)
token_type_ids  :  0 혹은 1로  식별 0과 1로 문장 1인지 문장 2인지 확인
                   예시) 문장 1의 token_type은 0,0,0,0,0 
                            문장 2의 token_type은 1,1,1,1,1 

attention_masks는 실제 단어가 있는지, padding으로 채워져 있는지 확인해주는 것
0 : padding
1: 실제 단어

 

 

 

4. 요소들 마다 출력해보기

# 요소들 출력해보기
print(tokenized_input_text['input_ids'])
print(tokenized_input_text.input_ids)

print('==========================')
print(tokenized_input_text['token_type_ids'])
print(tokenized_input_text.token_type_ids)

print('==========================')
print(tokenized_input_text['attention_mask'])
print(tokenized_input_text.attention_mask)

 

 

 

5. 해당 글자 뽑아보기

#해당 글자 뽑아보기
#tokenize() : 토큰 단위로 바꿔보기

tokenized_text = bert_tokenizer.tokenize(sample_1)
print(tokenized_text)


#번호값 확인 (101(CLS), 102(SEP)는 의미가 있는 것 태그)
input_ids = bert_tokenizer.encode(sample_1)
print(input_ids)

# 특별한 번호값 보기
decode_ids = bert_tokenizer.decode(input_ids)
print(decode_ids)
해석

Welcome이 단어사전 index 번호로 7236으로 저장 

CLS , SEP = 101,102 으로 문장의 시작과 끝을 나타낸다.

 

 

 

6.스페셜 토큰 없애기

#분절
tokenized_text = bert_tokenizer.tokenize(sample_1,add_special_tokens=False)
print(tokenized_text)

#인코딩
input_ids = bert_tokenizer.encode(sample_1,add_special_tokens=False)
print(input_ids)

#디코딩
decode_ids = bert_tokenizer.decode(input_ids)
print(decode_ids)
해석
add_special_tokens=False로 101,102,padding등을 없애르 수 있다.

 

 

 

7. 옵션 부여해보기

tokenized_text = bert_tokenizer.tokenize(
    sample_1,
    add_special_tokens=False,
    truncation=True,
    max_length=4
    )
print(tokenized_text)


input_ids = bert_tokenizer.encode(
    sample_1,
    add_special_tokens=False,
    truncation=True,
    max_length=3
    )
print(input_ids)
decoded_id = bert_tokenizer.decode(input_ids)
print(decoded_id)
해석
add_special_tokens = 스페셜 토큰을 부여할지 말지(True/False)
truncation = True / False = 입력 시퀸스 길이가 모델이 지원하는 최대 길이보다 길 때 어떻게 처리할지
              True: 초과하는 경우 초과하는 부분을 자르고 사용
              False: 초과할경우 에러를 발생 시킨다.
max_length: 최대 토큰 시퀸스의 길이를 지정해주는 파라미터

 

 

 

 

8. 일부로 넘치게 찍어보기

# 넘치게 찍어보기
# padding: max_length까지 나머지 부분을 채운다.

tokenized_text = bert_tokenizer.tokenize(
    sample_1,
    add_special_tokens=False,
    max_length=20,
    padding='max_length'
    )
print(tokenized_text)


# 디코딩 후 확인하기
input_ids = bert_tokenizer.encode(
    sample_1,
    add_special_tokens=False,
    max_length=20,
    padding='max_length'
    )
print(input_ids)
decoded_id = bert_tokenizer.decode(input_ids)
print(decoded_id)
 
해석

tokenized_text로 토큰단위 분절을 했고, max_length가 20개여서 기존 단어가 있는 6개 이외에 14개를 pad로 채움

인코딩으로 번호를 확인해보면 padding은 0으로 되어 있는 것을 볼 수 있다.

다시 디코딩으로 토큰을 확인해보면 [pad]라는 스페셜 토큰이 되어 있는걸 알 수 있다.

 

 

 

 

9. 한국어 해보기

#한국어 해보기

kor_text='아직도 목요일이네'
tokenized_text = bert_tokenizer.tokenize(
    kor_text,
    add_special_tokens=False,
    max_length=6,
    padding='max_length'
    )
print(tokenized_text)

#UNK는 등록되지 않은 것을 의미 (UnKnown) [100번을 의미]
한국어를 토큰화 시킨 후 확인해보면 [UNK] 토큰을 확인할 수 있다.
[UNK] = Unknown으로 등록되지 않은 token을 이미

 

 

 


2번째 모델 (한국어 텍스트모델 사용해보기)

모델명: bert-base-multilingual-cased

 

1. 모델 다운로드

multi_bert_model = AutoModel.from_pretrained('bert-base-multilingual-cased')
multi_bert_tokenizer = AutoTokenizer.from_pretrained('bert-base-multilingual-cased')

 

 

2. 단어사전 확인하기

print(multi_bert_tokenizer.vocab_size)

 

 

3.한국어 문장 분절시켜보기

text= '한국인이 알아볼 수 있는 한국어를 사용합니다'


#분절
tokenized_text = multi_bert_tokenizer.tokenize(text)
print(tokenized_text)

#인코딩
input_ids = multi_bert_tokenizer.encode(text)
print(input_ids)

#디코딩
decode_ids = multi_bert_tokenizer.decode(input_ids)
print(decode_ids)
해석

text라는 예시 한국어 문장을 셋팅

tokenizer로 분절
encode메소드로 해당 분절단어의 단어사전 번호를 확인
decode로 다시 한글 문장화 해보기

 

 

4.이상한 한국어 문장으로 해보기

unk_text= '한꾺인이 알아뽈 쑤 있뉸 한귝어를 샤용합뉘다'

#분절
tokenized_text = multi_bert_tokenizer.tokenize(unk_text)
print(tokenized_text)

#인코딩
input_ids = multi_bert_tokenizer.encode(unk_text)
print(input_ids)

#디코딩
decode_ids = multi_bert_tokenizer.decode(input_ids)
print(decode_ids)
해석
분절 / 인코딩 / 디코딩 순으로 진행
이상하게 만든 한국어는 [UNK]으로 판단 

 

5. 새로운 토큰 등록하기

added_token_num = multi_bert_tokenizer.add_tokens(['한꾺인','알아뽈','있뉸'])
 
tokenized_text = multi_bert_tokenizer.tokenize(unk_text, add_special_tokens=False)
print(tokenized_text)
 
input_ids = multi_bert_tokenizer.encode(unk_text, add_special_tokens=False)
print(input_ids)

 

decoded_ids = multi_bert_tokenizer.decode(input_ids)
print(decoded_ids)
해석
.add_tokens 으로 3개의 토큰 추가 (리스트로)
다시 해당 문장을 토큰화 후 확인

그 후 추가된 토큰의 인덱스 번호를 확인 하기 위해 encode

다시 decode로 문장 확인

 

 

6.스페셜 토큰 만들기

#스페셜 토큰 만들기
pecial_token_text = '[DAD]아빠[/DAD]가 방에 들어가신다'

added_token_num = multi_bert_tokenizer.add_special_tokens({'additional_special_tokens':['[DAD]','[/DAD]']})
print(added_token_num)

tokenized_text = multi_bert_tokenizer.tokenize(special_token_text,add_special_tokens=False)
print(tokenized_text)
해석 
add_special_tokens()안에 딕셔너리형태로 넣는다 
확인해보면 추가가 되어 있음.

 

 

7. 두가지 문장 한번에 토크나이즈 해보기

sample_list = ['아빠가 방에 들어가신다','[DAD]아빠[/DAD]가방에 들어가신다']

tokens = multi_bert_tokenizer(
    sample_list,
    padding=True
)
 
tokens
해석

input_ids라는 key에 2개의 리스트가 존재
token_type_ids라는 key에 2개의 리스트가 존재
attention_mask라는 key에 2개의 리스트가 존재

 

8. 이쁘게 출력해보기

for i in range(2):
    print('Tokens (int) : {}'.format(tokens['input_ids'][i]))
    print('Tokens (str) : {}'.format([multi_bert_tokenizer.convert_ids_to_tokens(s) for s in tokens['input_ids'][i]]))
    print('Tokens (attn_mask): {}'.format(tokens['attention_mask'][i]))
    print()
 
해석 

2번째 format 안에 리스트 컴프리헨션을 사용 
[for s in tokens['input_ids'][i]]에 해당하는 s를 반환하여 그것을 multi_bert_tokenizer.cover_ids_to_tokens()로 변환

 

🟡9. 사이에 들어갈 말 예측해보기

masked_text = '아빠가 [MASK] 들어가신다'

tokenized_text = multi_bert_tokenizer.tokenize(masked_text)
print(tokenized_text)
해석
테스트 데이터 준비 [MASK]안에 들어갈 말 예측해보기 위해서

 

from transformers import pipeline # 마스크를 채워주는 라이브러리
 
nlp_fill = pipeline('fill-mask', model ='bert-base-multilingual-cased')
nlp_fill(masked_text)
해석
1. pipeline이라는 모듈을 불러온다.
2. nlp_fill 변수에 pipeline 객체를 형성
                     ('fill-mask'는 파이프라인의 작업을 설정 (번역, 텍스트요 약, 질의응답다양함))
                     (model=안에 해당 모델을 적어준다)

3. nlp_fill에 테스트 데이터를 입력함
728x90