이번에는 사전학습된 모델을 불러와서 아주 간단하게 문장 일부를 주면 뒷문장을 써주는 모델을 만들어보겠다.
전체코드(colab사용)
import torch
model = torch.hub.load('huggingface/pytorch-transformers', 'modelForCausalLM', 'gpt2').to('cuda')
tokenizer = torch.hub.load('huggingface/pytorch-transformers', 'tokenizer', 'gpt2')
input_text="Once upon a time" #사용자가 제공하는 텍스트
tokenizer.pad_token = tokenizer.eos_token
encoded_input = tokenizer(input_text, return_tensors='pt', padding=True).to('cuda')
output = model.generate(
encoded_input['input_ids'],
attention_mask=encoded_input['attention_mask'],
max_length=50,
pad_token_id=tokenizer.eos_token_id,
num_return_sequences=1
)
generated_text = tokenizer.decode(output[0], skip_special_tokens=True)
print(generated_text)
import torch
model = torch.hub.load('huggingface/pytorch-transformers', 'modelForCausalLM', 'gpt2').to('cuda')
tokenizer = torch.hub.load('huggingface/pytorch-transformers', 'tokenizer', 'gpt2')
사전학습된 모델과 토크나이저를 불러오는 코드
colab의 GPU를 활성화하고 모델과 데이터를 GPU로 전송시키기 위해 .to('cuda')를 써줬다.
(내 컴퓨터에는 cuda CPU버전밖에 설치가 안 되는 이슈로 colab 사용)
tokenizer.pad_token = tokenizer.eos_token
이건 토크나이저에서 패드토큰과 문장을 끝내는 토큰(end of sentence, eos) 을 같은걸로 설정하는 코드
입력하지 않으면 토큰 관련된 오류가 난다.
GPT-2는 패딩토큰이 설정되어 있지 않아서 임시로 eos토큰을 패딩토큰으로 가져다 쓴 것
나중에 attention mask를 설정해서 패딩과 문장이 끝나는 것을 구분할 수 있게 해주면 된다.
encoded_input = tokenizer(input_text, return_tensors='pt', padding=True).to('cuda')
input_text(사용자가 입력한 내용)를 토큰화하고(tokenizer),
파이토치텐서(=pt)로 변환해서 패딩처리한 내용을 encoded_input에 저장했다.
이 때 encoded_input을 확인해보면 아래와 같이 input_id와 attenstion_mask를 키로 하는 딕셔너리임을 알 수 있다.

input_id: 문자열을 숫자로 변환하고 텐서로 처리
attention mask: 중요한 부분을 1로 그렇지 않은 부분을 0으로 표기한다.
attention mask는 어텐션 메커니즘이 특정 위치에 주의를 기울이도록 하는 필터
ex 문장길이를 6으로 설정해서 남은 부분에 패딩을 한다고 하면
text='I love you'
input_ids=[342, 46, 354, eos, pad, pad]
attention_mask=[1,1,1,1,0,0]
이 예시를 보면 attention mask에서 문장이 끝났을때는 1로 표시되지만 패딩은 0으로 표시되는 것을 알 수 있다.
-> attention mask를 설정해서 패딩과 문장이 끝나는 것을 구분
참고)tokenizer.encode(input_text, return_tensors='pt')
tokenizer() 가 아닌 tokenizer.encode() 를 쓰면 input_ids만 만들어진다.
이러면 나중에 attention_mask를 따로 정의해서 써야 하기 때문에 귀찮아진다.
output = model.generate(
encoded_input['input_ids'],
attention_mask=encoded_input['attention_mask'],
max_length=50,
pad_token_id=tokenizer.eos_token_id,
num_return_sequences=1
)
결과를 우리가 불러온 모델에서 생성
참고로 output은 [tensor([ 342, 46, 354 , ...])] 이런식으로 'tensor형태로 저장된 시퀀스'가 들어있는 리스트이다.
(사실 많은것들이 리스트형태로 받고 또 리스트형태로 내놓는다..)
encoded_input['input_ids'], attention_mask=encoded_input['attention_mask']
위에서 확인한 바에 따르면
encoded_input={'input_ids':value1, 'attention_mask': value2} 형식의 딕셔너리였고, 여기서 키로 벨류를 호출하고 있는것
max_length=50
최대 50개까지의 토큰만 생성
pad_token_id=tokenizer.eos_token_id
GPT-2는 패딩처리가 없기 때문에 패딩토큰을 문장을 끝내는 토큰과 동일하게 처리해줌
참고로 위에서 tokenizer.pad_token = tokenizer.eos_token 이렇게 쓴 것은 토크나이저에서 두 토큰이 같다고 한 것이고, 모델에서 생성할 때는 명시적으로 pad_token_id를 지정해줘야 오류가 안생긴다.
num_return_sequences=1
생성할 시퀀스의 개수가 1개 -> 한 가지 문장이 출력됨
generated_text = tokenizer.decode(output[0], skip_special_tokens=True)
tokenizer.decode는 숫자를 사람이 읽을수있는 문장으로 바꿔주는 함수
output[0]은 생성한 시퀀스 리스트의 첫번째를 의미
리스트에 시퀀스가 하나만 있어도 output[0]을 해줘야 한다.
그냥 output만 입력하면 정수값을 받아야 하는데 리스트를 받았다는 오류가 난다.
그렇다면, num_return_sequences를 여러 개 해서 문장을 여러 개 뽑아볼 수 있을까?
이제 output[0]을 입력하면 시퀀스들의 첫번째가 반환되고, output[1]을 입력하면 두번째가 반환된다.
우리는 num_beams> num_return_sequences=3이므로 output[2] 까지 출력할 수 있다.
만약 output[0] 이런식으로 입력하지 않고 생성된 모든 시퀀스를 다 보고싶다면?
이렇게 리스트 컴프리헨션을 사용하고 for in 문으로 반복해주면 된다.
What's next?
AI 활용 강의 듣기(금,토,일)
딥러닝+감정분석
Style Transfer Model
'머신러닝' 카테고리의 다른 글
openAI API를 활용한 챗봇 구현 (0) | 2024.11.04 |
---|---|
Sentiment Analysis with LSTM (2) | 2024.11.01 |
skin cancer HAM10000(2) (0) | 2024.10.30 |
skin cancer HAM10000 (0) | 2024.10.29 |
wordcloud (2) | 2024.10.28 |