해당 내용은 김기현의 자연어 처리 딥러닝 캠프 파이토치편 및 Pytorch로 시작하는 딥러닝 입문읽으며 발췌 및 정리한 내용입니다.
2021.05.11 - [Study/NLP] - [NLP/자연어처리 ]자연어 처리 전처리(2) - 분절(토큰화) 라이브러리 소개
2021.05.12 - [Study/NLP] - [NLP/자연어처리] 자연어 처리 전처리(3) - 단어집합(Vocabulary), 패딩
이제 자연어 전처리에 이어서 토치 텍스트를 이용해 코퍼스를 모델을 훈련시키는 모양에 맞게 데이터 셋을 짜는 법에 대해서 이야기하려한다.
딥러닝 코드를 작성하다보면, 신경망 모델 자체를 코딩하는 시간보다 그 모델을 훈련시키기 위해 전처리하는 코드를 짜는 시간이 더 오래걸리기 마련이다. 데이터 입력을 준비하는 부분도 이에 해당한다고 할 수 있다.
토치텍스트(TorchText)는 Pytorch에서 자연어처리 문제 도는 텍스트에 관한 머신러닝이나 딥러닝을 수행하는 데이터를 읽고 전처리하는 코드를 모아둔 라이브러리다. 텍스트 분류나 언어모델, 기계번역의 경우에도 토치텍스트를 이용하여 쉽게 텍스트파일을 읽어내 훈련에 사용한다.
토치 텍스트가 제공하는 기능들은 간략하게 다음과 같다.
- 파일 로드하기(File Loading) : 다양한 포멧의 코퍼스를 로드한다.
- 토큰화(Tokenization): 문장을 단어 단위로 분리해준다.
- 단어 집합(Vocab) : 단어 집합을 만든다.
- 정수 인코딩(Integer encoding) : 전체 코퍼스의 단어들을 각각의 고유한 정수로 매핑한다.
- 단어 벡터(Word Vector) : 단어 집합의 단어들에 고유한 임베딩 벡터를 만들어준다. 랜덤값으로 초기화 한 값일수도 있고, 사전 훈련된 임베딩 벡터들을 로드할 수도 있다.
- 배치화(Batching) : 훈련 샘플들의 배치를 만들어준다. 이 과정에서 패딩 작업도 이루어진다.
1. 학습데이터 종류
자연어 처리 분야에서 주로 쓰이는 학습데이터는 크게 세 가지 형태로 분류할 수 있는데, 신경망이 주로 처리하는 형태는 x를 받아 알맞은 출력 y를 반환해주는 함수의 꼴이므로 x, y의 형태에 따라 분류해볼 수 있다.
x 데이터 | y 데이터 | 활용분야 |
코퍼스 | 클래스 | 텍스트 분류, 감성 분석 |
코퍼스 | - | 언어 모델 |
코퍼스 | 코퍼스 | 기계번역, 요약, 질의응답 |
보통 Field라는 클래스를 통해서 우리가 읽고자 하는 텍스트 파일 내의 필드를 정의한다. 이 안에서는 토크나이저로 무슨 함수를 사용할 것인지, 코퍼스의 길이는 어떻게 할 것인지, 단어집합을 만들 것인지 등을 정의한다. 텍스트 파일 내에서는 탭을 사용하여 필드를 구분하는 방식을 많이 사용한다. 쉼표의 경우에는 텍스트 내부에 많이 포함될 수 있으므로, 쉼표를 구분문자로 사용할 경우 올바르게 구분되지 않을 가능성이 크다.
이렇게 정의된 각 필드를 Dataset 클래스를 통해 읽어들인다. 그 코퍼스를 주어진 미니배치 크기에 따라 나뉠 수 있도록 Iterator에 들어가고, 미니배치를 구성하는 과정에서 문장의 길이가 다를 경우 문장의 앞 또는 뒤에 패딩을 삽입한다. 이후에 훈련 코퍼스에 대해 어휘사전을 만들어 단어를 숫자로 매핑하는 작업을 수행한다.
이제 실습을 할 예정인데, 실습 데이터로 한글 네이버 영화 리뷰 데이터를 사용해서 훈련할 예정이다. 형태소 분석기로 Mecab을 사용할 예정인데 Mecab은 이미 설치되었다고 가정한다.
2. 훈련데이터와 테스트 데이터 다운로드하기
import urllib.request
import pandas as pd
urllib.request.urlretrieve("https://raw.githubusercontent.com/e9t/nsmc/master/ratings_train.txt", filename="ratings_train.txt")
urllib.request.urlretrieve("https://raw.githubusercontent.com/e9t/nsmc/master/ratings_test.txt", filename="ratings_test.txt")
train_df = pd.read_table('./data/ratings_train.txt')
test_df = pd.read_table('./data/ratings_test.txt')
데이터의 형태는 아래와 같다. document는 영화 리뷰, label은 긍정 부정에 대한 라벨, id는 불필요하다.
print('훈련 데이터 샘플의 개수 : {}'.format(len(train_df)))
print('테스트 데이터 샘플의 개수 : {}'.format(len(test_df)))
훈련 데이터 샘플의 개수 : 150000
테스트 데이터 샘플의 개수 : 50000
3. 필드 정의하기(torchtext.data)
P.S. 현재 필자는 torchtext 0.9.1 버전을 사용하고 있다. 그런데 pytorch에서 Pytorch DataLoader와 통일하기 위해 torchtext만의 DataLoading 추상화 클래스를 중단했다고 한다. (link)
그래서 현재 우리가 사용하려는 Field 클래스는 torchtext의 legacy에 있으니 참고해서 불러오면 될 듯하다. (그런데 파이토치에서 Dataloader를 통일하기 위해 추상화 클래스를 중단한 건데 굳이 legacy에 가서 사용해야할까 싶긴하다. torchtext를 사용하지 않고도 구성할 수 있도록 해보자.)
from torchtext.legacy import data
from konlpy.tag import Mecab
tokenizer = Mecab() ## 토크나이저로 Mecab 사용
## 필드 정의
ID = data.Field(sequential = False,
use_vocab = False)
TEXT = data.Field(sequential = True, # 순차적인 데이터인지
use_vocab = True, #단어사전을 사용할 것인지
tokenize = tokenizer.morphs, # 사용할 토크나이저
lower = True, # 대문자를 전부 소문자로 변환
batch_first = True, # batch size를 가장 앞으로 둘건지. Default False.
fix_length = 20 # 최대문자 길이
)
LABEL = data.Field(sequential = False,
use_vocab = False,
is_target = True # target 여부. Default False.
)
해당 과정은 필드를 정의한 것이지, 아직 어떤 전처리도 하지 않은 상태이다.
4. 데이터 셋 만들기
다음은 TabularDataset을 이용해서 데이터를 불러와서 데이터 셋의 형식으로 바꿔주고, 그와 동시에 토큰화를 수행하는 작업을 진행할 것이다. 해당 클래스는 데이터를 로컬에서 불러오는 것에서 부터 시작된다. 자세한 내용은 pytorch document를 확인하자.
# 데이터 로컬에서 불러와서 Dataset의 형태로 변환
train_data, test_data = data.TabularDataset.splits(
path = './data', train = 'ratings_train.txt', test = 'ratings_test.txt', # 데이터경로 설정
format = 'tsv', # format (데이터 구분자가 무엇인지)
fields = [('id', ID),
('text', TEXT),
('label', LABEL)], # 위에서 정의한 필드 정의
skip_header = True
)
P.S. 만일 데이터를 따로따로 Dataset의 형태로 하고 싶으면, splits()을 쓰지 않고 정의하면 된다.
vars(train_data[0])
{'id': '9976970',
'text': ['아', '더', '빙', '.', '.', '진짜', '짜증', '나', '네요', '목소리'],
'label': '0'}
5. 단어집합(Vocabulary) 만들기
Field에 build_vocab()도구를 사용하면 단어 사전을 생성할 수 있다.
여기서 min_freq는 단어 집합에 추가할 떄 단어의 최소 등장 빈도 조건, max_size는 단어집합의 최대 크기를 지정하는 옵션이다.
TEXT.build_vocab(train_data, min_freq=10, max_size=10000)
TEXT.vocab.itos[:10]
>>> ['<unk>', '<pad>', '.', '이', '는', '영화', '다', '고', '하', '도']
len(TEXT.vocab)
>>> 10002
단어 집합의 크기를 10,000개로 제한했고, 특별 토큰인 <unk>와 <pad>이 0과 1번째 단어로 추가되면서 실제 생성된 단어는 0번부터 10001번까지 총 10002개이다.
6. 토치텍스트의 데이터로더 만들기
보통 파이토치에서 데이터 로더는 DataLoader를 사용하는데 토치텍스트에서는 Iterator를 사용해서 데이터로더를 만드는 듯 하다. 데이터로더는 데이터셋에서 미니배치만큼 데이터를 로드하게 만들어주는 역할을 하는 클래스다.
train_loader = data.Iterator(dataset = train_data, batch_size = 5)
test_loader = data.Iterator(dataset = test_data, batch_size = 5)
임의로 배치사이즈를 5로 주었다.
print('훈련 데이터의 미니 배치 수 : {}'.format(len(train_loader)))
print('테스트 데이터의 미니 배치 수 : {}'.format(len(test_loader)))
훈련 데이터의 미니 배치 수 : 30000
테스트 데이터의 미니 배치 수 : 10000
훈련데이터와 테스트 데이터를 배치 크기 5씩 묶어주었으므로, train_loader의 이터레이터 수 (미니배치의 개수)는 = 150000/5 = 30000개, test_loader는 50000/5 = 10000이다.
7. 결론( + 개인의 생각)
토치텍스트의 라이브러리에 대해서 알아보았다. 그런데 현업에서 프로젝트를 할때 해당 라이브러리를 활용할지는 조금 미지수인 것 같다. 프로젝트에서 데이터가 txt나 tsv형태가 아닌 바로 db에서 불러와야 하는 경우도 있을텐데, Field를 정의하고 TabluarDataset을 사용해서 불러오는것부터 할 필요가 있을까 싶기도 하고, 앞에서 언급했듯이 torchtext.data는 이미 pytorch와 통일하기 위해 중단한 상태이고, legacy를 사용해야만 사용할 수 있다. 차라리 로우단위로 짜고 Dataset이나 DataLoader등을 통일시켜서 사용하는게 더 낫지 않을까 싶다. 그래도 토치 텍스트가 유용한 것은 맞으니 알아두고 사용할지 말지 결정하는 것이 더 좋을 것 같다.
'Study > NLP' 카테고리의 다른 글
[NLP/자연어처리] 단어의 표현(2) - 카운트 기반의 단어 표현 (0) | 2021.05.18 |
---|---|
[NLP/자연어처리] 단어의 표현(1) - 원핫인코딩과 워드투벡터(Word2Vec) (0) | 2021.05.14 |
[NLP/자연어처리] 자연어 처리 전처리(3) - 단어집합(Vocabulary), 패딩 (4) | 2021.05.12 |
[NLP/자연어처리 ]자연어 처리 전처리(2) - 분절(토큰화) 라이브러리 소개 (0) | 2021.05.11 |
[NLP/자연어처리] 자연어 처리 전처리(1) - 코퍼스와 텍스트 정제 (0) | 2021.05.10 |