[딥러닝 스터디] 자연어 전처리 실습

[딥러닝 스터디] 자연어 전처리 실습

자연어 처리 라이브러리인 토치텍스트를 활용해 이전 포스트의 전처리 이론을 실제로 구현해보자.

토치텍스트

: 텍스트에 대한 여러 추상화 기능을 제공하는 자연어 처리 라이브러리

토치텍스트 제공 기능

  1. 파일 로드하기(File Loading) : 다양한 포맷의 코퍼스를 로드한다.
  2. 토큰화(Tokenization) : 문장을 단어 단위로 분리한다.
  3. 단어 집합 생성(Vocab) : 단어 집합을 만든다.
  4. 정수 인코딩(Integer encoding) : 전체 코퍼스의 단어들을 각각의 고유한 정수로 맵핑한다.
  5. 단어 벡터(Word Vector) : 단어 집합의 단어들에 고유한 임베딩 벡터를 만들어줍니다. 랜덤값으로 초기화한 값일 수도 있고, 사전 훈련된 임베딩 벡터들을 로드할 수도 있습니다.
  6. 배치화(Batching) : 훈련 샘플들의 배치를 만들어줍니다. 이 과정에서 패딩 작업(Padding)도 이루어집니다.

실습 1. IMDB 리뷰데이터 분류하기(영어)

데이터 다운 및 용도에 따른 분류 진행(훈련/테스트)

  • 데이터는 text(리뷰데이터)와 sentiment(리뷰의 긍정:1/부정:0 여부)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 토치텍스트 설치
pip install torchtext

import urllib.request
import pandas as pd

# IMDB 리뷰 데이터 다운로드
urllib.request.urlretrieve("https://raw.githubusercontent.com/LawrenceDuan/IMDb-Review-Analysis/master/IMDb_Reviews.csv", filename="IMDb_Reviews.csv")

# 데이터 csv파일로 저장, 상위 5개 행 출력해본다
df = pd.read_csv('IMDb_Reviews.csv', encoding='latin1')
df.head()

# 훈련 데이터와 테스트 데이터로 분류(총 5만개)
train_df = df[:40000]
test_df = df[40001:]

# 각 데이터를 csv 파일로 저장 (index=False :: 인덱스를 저장하지 않음)
train_df.to_csv("train_data.csv", index=False)
test_df.to_csv("test_data.csv", index=False)

필드 정의하기(torchtext.data)

torchtext.data 의 Field함수를 활용해 진행할 자연어 전처리를 정의할 수 있다.

  • sequential : 순차적인 데이터 여부. (True가 기본값) LABEL은 긍정/부정의 단순한 클래스를 나타내는 숫자값이지 순차적 데이터가 아니므로 False이다.
  • use_vocab : 단어 집합을 만들 것인지 여부. (True가 기본값)
  • tokenize : 어떤 토큰화 함수를 사용할 것인지 지정. (string.split이 기본값)
  • lower : 영어 데이터를 전부 소문자화한다. (False가 기본값)
  • batch_first : 신경망에 입력되는 텐서의 첫번째 차원값이 batch_size가 되도록 한다. (False가 기본값)
  • is_target : 레이블 데이터 여부. (False가 기본값)
  • fix_length : 최대 허용 길이. 이 길이에 맞춰서 패딩 작업(Padding)이 진행된다.
1
2
3
4
5
6
7
8
9
10
from torchtext.data import TabularDataset

# 경로, 훈련데이터, 테스트데이터, 데이터포멧, 텍스트객체
train_data, test_data = TabularDataset.splits(
path='.', train='train_data.csv', test='test_data.csv', format='csv',
fields=[('text', TEXT), ('label', LABEL)], skip_header=True)

# 훈련 데이터의 샘플을 확인한다.
print(vars(train_data[1])['text'])
print(vars(train_data[1])['label'])
1
2
3
[결과]
['believe', 'it', 'or', 'not,', 'this', 'was', 'at', 'one', 'time', 'the', 'worst', 'movie', 'i', 'had', 'ever', 'seen.', 'since', 'that', 'time,', 'i', 'have', 'seen', 'many', 'more', 'movies', 'that', 'are', 'worse', '(how', 'is', 'it', 'possible??)', 'therefore,', 'to', 'be', 'fair,', 'i', 'had', 'to', 'give', 'this', 'movie', 'a', '2', 'out', 'of', '10.', 'but', 'it', 'was', 'a', 'tough', 'call.']
0

단어집합을 생성한다.

  • 전체 리뷰의 단어들 내에서 중복을 제거한 단어집합을 생성한다.
  • 각 단어에 고유한 정수를 부여한다(정수 인코딩)
    • 정의한 필드 객체의 .build_vocab() 함수를 활용해 단어집합을 생성할 수 있다.
1
2
3
4
5
6
7
# 리뷰 데이터의 단어집합을 만든다.
# min_freq : 단어집합에 추가되기 위한 최소 등장빈도조건
# max_size : 단어집합의 최대 크기
TEXT.build_vocab(train_data, min_freq=10, max_size=10000)

print('Size of vocab : ', len(TEXT.vocab))
print('Integer index of word [the] : ', TEXT.vocab.stoi['the'])
1
2
3
[결과]
Size of vocab : 10002
Integer index of word [the] : 2
  • 이때 단어집합의 크기는 기존에 정의한 10000이 아닌 10002임을 알 수 있다. 더해진 두개는 토치텍스트가 자동으로 추가한 특별토큰 unk\pad\이다.
  • unk는 0, pad는 1의 정수가 부여된다.

(+) 데이터로더 만들기 : 특정 배치크기로 데이터를 로드하도록 하는 데이터 로더를 만든다. torchtext.data의 Iterator를 사용해 만들 수 있다.

1
2
3
4
5
from torchtext.data import Iterator

# 배치사이즈 100으로 훈련데이터에 대한 데이터로더를 만든다
train_loader = Iterator(dataset=train_data, batch_size=100)
print("len of train data : ", len(train_data), " | num of batches : ", len(train_loader))
1
2
[결과]
len of train data : 40000 | num of batches : 400

실습 2. 네이버 영화데이터 분류하기(한국어)

: 이전 IMDB데이터를 토치텍스트로 전처리 한 것과 마찬가지의 과정으로 진행한다.

  1. 네이버 영화리뷰데이터 다운
  2. 훈련데이터/테스트 데이터로 분류
  3. 필드 정의하기(전처리 방식 지정)
  4. 데이터셋 제작하기(전처리 수행)
  5. 단어집합 생성/정수인코딩 수행
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# 한국어 형태소 분석기 Mecab 설치
!git clone https://github.com/SOMJANG/Mecab-ko-for-Google-Colab.git
%cd Mecab-ko-for-Google-Colab
!bash install_mecab-ko_on_colab190912.sh

# 1.네이버 영화 리뷰데이터 다운
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")

# 2.훈련 데이터와 테스트 데이터로 분리한다.
train_data = pd.read_table('ratings_train.txt')
test_data = pd.read_table('ratings_test.txt')

from torchtext import data
from konlpy.tag import Mecab

# 3.필드 정의하기(전처리 방식 지정)
TEXT = data.Field(sequential=True,
use_vocab=True, # 단어집합을 만든다
tokenize=Mecab().morphs, # 토크나이저로는 Mecab 사용.
lower=True,
batch_first=True,
fix_length=20) # 패딩 길이는 20

LABEL = data.Field(sequential=False,
use_vocab=False,
is_target=True)

# ID필드는 사용하지 않는다.
# 디민 TabularDataset.splits()은 받은 데이터를 앞에서부터 순서대로 자르므로 필요함.
# 네이버 영화리뷰 데이터는 [리뷰아이디, 리뷰, 라벨] 세가지로 이뤄져있기 때문
ID = data.Field(sequential=False,
use_vocab=False,)

from torchtext.data import TabularDataset

# 4.데이터셋 제작하기(전처리 수행)
train_data, test_data = TabularDataset.splits(
path='.', train='ratings_train.txt', test='ratings_test.txt', format='tsv',
fields=[('id', ID), ('text', TEXT), ('label', LABEL)], skip_header=True)

print('훈련 샘플의 개수 : {}'.format(len(train_data)))
print('테스트 샘플의 개수 : {}'.format(len(test_data)))
print('훈련 데이터 예제 : {}'.format(vars(train_data[0])))
1
2
3
4
[결과]
훈련 샘플의 개수 : 150000
테스트 샘플의 개수 : 50000
훈련 데이터 예제 : {'id': '9976970', 'text': ['아', '더', '빙', '.', '.', '진짜', '짜증', '나', '네요', '목소리'], 'label': '0'}
1
2
3
4
5
# 5.단어집합을 생성한다(정수인코딩 수행)
TEXT.build_vocab(train_data, min_freq=10, max_size=10000)

# 생성된 단어집합 내 단어 확인해보기
print('단어 "좋아"의 인덱스는 [{}]'.format(TEXT.vocab.stoi['좋아']))
1
2
[결과]
단어 "좋아"의 인덱스는 [8343]

댓글