NLP_Preprocessing : 6)Batchify with torchtext
- -
Preprocessing Workflow
1. 코퍼스 수집 : 구입,외주,크롤링
2. 정제 : Task에 따른 노이즈 제거, 인코딩 변환
(3. 레이블링 : Task에 따른 문장 or 단어마다 labeling 수행)
4. Tokenization : 형태소 분석기 활용하여 분절 수행
(5. Subword Segmentation : 단어보다 더 작은 의미 추가 분절 수행)
6. Batchify : 사전 생성 및 word2index 맵핑 수행, 효율화를 위한 전/후처리
1~5번 과정에서 전처리를 진행하였다. 전처리가 다 된 후에는 이제 모델에 넣기 위한 처리가 필요하다.
- Split Train/Valid/Test data set
- 단어를 index로 mapping하기 위해 train set을 기반으로 어휘 사전 생성
: 빈도 순으로 단어 사전을 정렬한다. - 길이로 Sorting
: Sequence의 차원의 크기는 미니 배치내의 가장 긴 문장에 의해 결정이 되는데,
만약 가장 긴 문장은 100단어이고 어떤 문장은 16단어로 구성되어 있다면 그 어떤 문장은 84 timestep이 <pad>로 채워지게 된다. 그러면 학습할 때 84 timestep동안 놀게된다.
→ 짧은 문장끼리 미니배치를 만들고, 긴 문장끼리 미니 배치를 만들면 training effficiency를 높일 수 있을 것이다!
길이로 sorting을 하고 미니배치 순서 자체를 shuffling해서 넣어준다. - integer로 변환 (각 token들을 사전을 활용하여 str → index 맵핑)
- Batchify and pad
- Shuffle
TorchText는 NLP 또는 텍스트와 관련된 기계학습 또는 딥러닝을 수행하기 위한 데이터를 읽고 전처리 하는 코드를 모아놓은 라이브러리이다.
from torchtext import data ## torchtext==0.8.0
step 1: "Define Fields"
self.label = data.Field(Sequential=False,
use_vocab=True,
unk_token=None,
)
self.test = data.Field(use_vocab=True,
batch_first=True,
include_lengths=False,
eos_token='<EOS>' if use_eos else None
)
step 2: "Define Dataset with Fields"
train, valid = data.TabularDataset.splits(path='',
train=train_fn,
validation=valid_fn,
format='tsv',
fields=[('label', self.label,
('text', self.text)]
)
step 3: "Get DataLoaders from Datasets"
self.train_loader, self.valid_loader = data.BucketIterator.splits((train,valid),
batch_size=batch_size,
device='cuda:%d' % device if device >=0 else 'cpu'
shuffle=shuffle,
sort_key=lambda x: len(x.text),
sort_within_batch=True,
)
step 4: "Make Vocab dictionary"
self.label.build_vocab(train)
self.text.build_vocab(train, max_size=max_vocab, min_freq=min_freq)
torchtext == 0.8.0을 사용하였다.
from torchtext import data
class DataLoader(object):
"""
Data loader class to load text file using torchtext library.
"""
def __init__(
self,
train_fn,
batch_size=64,
valid_ratio=0.2,
device=-1,
max_vocab=999999,
min_freq=1,
use_eos=False,
shuffle=True,
):
"""
DataLoader initialization.
:param train_fn: Train-set filename
:param batch_size: Batchify data fot certain batch size.
:param device: Device-id to load data (-1 for CPU)
:param max_vocab: Maximum vocabulary size
:param min_freq: Minimum frequency for loaded word.
:param use_eos: If it is True, put <EOS> after every end of sentence.
:param shuffle: If it is True, random shuffle the input data.
"""
super().__init__()
# field 정의
# positive/negative , text
self.label = data.Field(sequential=False, use_vocab=True, unk_token=None)
self.text = data.Field(
use_vocab=True,
batch_first=True,
include_lengths=False,
eos_token="<EOS>" if use_eos else None,
)
# two columns will be delimited by TAB.
# TabularDataset to load two columns in the input file.
# Files consist of two columns: label field and text field.
train, valid = data.TabularDataset(
path=train_fn,
format="tsv",
fields=[
("label", self.label),
("text", self.text),
],
).split(split_ratio=(1 - valid_ratio))
# train loadee and valid loader
# We sort input sentences by length, to group similar lengths.
self.train_loader, self.valid_loader = data.BucketIterator.splits(
(train, valid),
batch_size=batch_size,
device="cuda:%d" % device if device >= 0 else "cpu",
shuffle=shuffle,
sort_key=lambda x: len(x.text),
sort_within_batch=True,
)
# making mapping table between words and indice.
self.label.build_vocab(train)
self.text.build_vocab(train, max_size=max_vocab, min_freq=min_freq)
review.sorted.uniq.refined.tok.tsv를 shuffle 한 tsv 파일을 만든다.
shuf < review.sorted.uniq.refined.tok.tsv > review.sorted.uniq.refined.tok.shuf.tsv
korea@LAPTOP-J8PRNVSI MINGW64 ~/OneDrive/바탕 화면/NLP study/preprocessing/5_batchify
$ head -n 2 ./review.sorted.uniq.refined.tok.shuf.tsv
negative 렌치 가 다 찌그려 지 는 거 파 시 나요 너무 하 네요
negative 먼지 가 너무 붙 어요 . .
(mecab_venv)
korea@LAPTOP-J8PRNVSI MINGW64 ~/OneDrive/바탕 화면/NLP study/preprocessing/5_batchify
$ head -n 2 ./review.sorted.uniq.refined.tok.tsv
negative !
negative ! 다 녹 아서 왓 어요 . . 짜증
(mecab_venv)
train은 62943개, test는 10000개로 데이터를 분리한다.
korea@LAPTOP-J8PRNVSI MINGW64 ~/OneDrive/바탕 화면/NLP study/preprocessing/5_batchify
$ head -n 62943 ./review.sorted.uniq.refined.tok.shuf.tsv > review.sorted.uniq.refined.tok.shuf.train.tsv
(mecab_venv)
korea@LAPTOP-J8PRNVSI MINGW64 ~/OneDrive/바탕 화면/NLP study/preprocessing/5_batchify
$ tail -n 10000 ./review.sorted.uniq.refined.tok.shuf.tsv > review.sorted.uniq.refined.tok.shuf.test.tsv
(mecab_venv)
앞에서 정의한 DataLoader을 이용하여 train loader와 valid loader을 만든다.
loaders = DataLoader(
train_fn='./review.sorted.uniq.refined.tok.shuf.train.tsv',
batch_size=256,
valid_ratio=.2,
device=-1,
max_vocab=999999,
min_freq=5,
)
만든 loader을 통해 train sample의 개수, valid sample 개수를 확인할 수 있다.
print("|train|=%d" % len(loaders.train_loader.dataset))
print("|valid|=%d" % len(loaders.valid_loader.dataset))
|train|=50354
|valid|=12589
text vocab은 8690개의 단어로 이루어짐을 확인할 수 있다.
print("|vocab|=%d" % len(loaders.text.vocab))
print("|label|=%d" % len(loaders.label.vocab))
|vocab|=8690
|label|=2
미니배치를 하나만 받아오기 위해 iter로 받아온다. 90개의 단어로 이루어져있음을 알 수 있다.
data = next(iter(loaders.train_loader))
print(data.text.shape)
print(data.label.shape)
torch.Size([256, 90])
torch.Size([256])
미니배치의 마지막 문장을 확인해보면,
print(data.text[-1])
tensor([ 256, 341, 254, 43, 8, 7, 37, 2704, 6, 4889, 43, 84,
55, 77, 3, 92, 29, 37, 133, 11, 549, 733, 8562, 12,
159, 52, 286, 50, 42, 13, 4633, 4215, 8562, 12, 38, 186,
351, 1980, 5, 7, 37, 559, 1269, 6, 2101, 43, 577, 61,
55, 80, 5253, 559, 5, 64, 482, 21, 17, 37, 251, 575,
12, 266, 58, 61, 790, 151, 57, 67, 329, 234, 99, 61,
52, 64, 321, 29, 37, 335, 5, 83, 37, 1, 1, 1,
1, 1, 1, 1, 1, 1])
tensor형태의 데이터를 text로 복원하였다.
x = data.text[-1]
line = []
for x_i in x:
line += [loaders.text.vocab.itos[x_i]]
print(' '.join(line))
와 기대 이상 으로 좋 네요 ! 볼트 도 여분 으로 더 주 시 고 감사 합니다 ! 제 가 타 브랜드 철봉 은 써 보 진 않 았 는데 멜 킨 철봉 은 가격 대비 매우 훌륭 하 네요 ! 조립 방법 도 동영상 으로 설명 해 주 어서 따라서 조립 하 니 금방 했 어요 ! 내 구성 은 계속 사용 해 봐야 알 겠 지만 일단 몇 번 해 보 니 튼튼 합니다 ! 번창 하 세요 ! '딥러닝 > 자연어 처리' 카테고리의 다른 글
[WordEmbedding] Word2Vec & Glove & FastText (0) | 2022.06.28 |
---|---|
[WordEmbedding] 딥러닝 이전의 단어 임베딩 (0) | 2022.06.28 |
NLP_Preprocessing : +)Detokenization (0) | 2022.06.27 |
NLP_Preprocessing : 5)Subword Segmentation (0) | 2022.06.27 |
NLP_Preprocessing : 4)Tokenization (0) | 2022.06.27 |