-- ๋ณธ ํฌ์คํ
์ ํ์ดํ ์น๋ก ๋ฐฐ์ฐ๋ ์์ฐ์ด ์ฒ๋ฆฌ (ํ๋น๋ฏธ๋์ด) ์ฑ
์ ์ฐธ๊ณ ํด์ ์์ฑ๋ ๊ธ์
๋๋ค.
-- ์์ค์ฝ๋ ) https://github.com/rickiepark/nlp-with-pytorch
โถ ๋ ์คํ ๋ ๋ฆฌ๋ทฐ ๊ฐ์ฑ ๋ถ๋ฅํ๊ธฐ
์ด์ ํฌ์คํ ์์ ๋ฐฐ์ด ํผ์ ํธ๋ก ๊ณผ ์ง๋ ํ์ต ํ๋ จ ๋ฐฉ๋ฒ์ ์ฌ์ฉํ์ฌ ์ํ(Yelp)์ ๋ ์คํ ๋ ๋ฆฌ๋ทฐ๊ฐ ๊ธ์ ์ ์ธ์ง๋ถ์ ์ ์ธ์ง ๋ถ๋ฅํ๋ ์์ ์ ์งํํด ๋ณด์. ํด๋น ํ๋ก์ ํธ๋ ๋ฆฌ๋ทฐ์ ๊ฐ์ฑ๋ ์ด๋ธ(๊ธ์ or๋ถ์ )์ด ์์ ์ด๋ฃจ๋ ์ํ ๋ฐ์ดํฐ์ ์ ์ฌ์ฉํ๋ค. ๋ฐ์ดํฐ๋ฅผ ์ ์ ํ๊ณ , ํ๋ จ, ๊ฒ์ฆ, ํ ์คํธ์ธํธ๋ก ๋๋๋ ์ ์ฒ๋ฆฌ ๋จ๊ณ๋ฐ ๋ช ๊ฐ์ง๋ฅผ ์ถ๊ฐ๋ก ์ค๋ช ํ๋ฉด์ ํ๋ก์ ํธ๋ฅผ ์งํํด๋ณด์.
์์ผ๋ก ๋งค๋ฒ ์ฌ์ฉํ 3๊ฐ์ ๋ณด์กฐ ํด๋์ค์ ๋ํด์ ๊ฐ๋จํ๊ฒ ์ค๋ช
ํด๋ณด๋ฉด,
Vocabularay = ์ํ๊ณผ ํ๊น์ ์ธ์ฝ๋ฉ์์ ์ค๋ช
ํ ์ ์์ ํ ํฐ ๋งคํ์ ์ํ.
Vectorizer = ์ดํ ์ฌ์ ์ ์บก์ํํ๊ณ ๋ฆฌ๋ทฐ ํ
์คํธ ๊ฐ์ ๋ฌธ์์ด ๋ฐ์ดํฐ๋ฅผ ํ๋ จ๊ณผ์ ์์ ์ฌ์ฉํ ์์น ๋ฒกํฐ๋ก ์ ํ.
DataLoader = ๊ฐ๋ณ ๋ฒกํฐ ๋ฐ์ดํฐ ํฌ์ธํธ๋ฅผ ๋ฏธ๋ ๋ฐฐ์น๋ก ๋ชจ์ผ๋ ์ญํ .
1. ๋ฐ์ดํฐ์ (๊ฐ๋จํ ๋ฐ์ดํฐ ์ ์ฒ๋ฆฌ ๊ณผ์ )
์์ ์ธ๊ธํ๋ฏ์ด, ์ํ ๋ฐ์ดํฐ์ ์ ํ์ฉํ๋ค. ์ํ ๋ฐ์ดํฐ์ ์ ํ๋ จ ์ํ 560000๊ฐ์ ํ ์คํธ์ํ 38000๊ฐ๋ก ๋๋์ด์ ธ ์์ง๋ง, ํด๋น ํ๋ก์ ํธ์์๋ ๋ฐ์ดํฐ์ ์ ํ๋ จ ์ํ์ 10%๋ง ์ฌ์ฉํ ๊ฒ์ด๋ค. (ํด๋น ์ฑ ์์๋ ์ด ๋ฐ์ดํฐ์ ์ '๋ผ์ดํธ'๋ฒ์ ์ด๋ผ๊ณ ํํํ๋ค.) ์ด๋ ๊ฒ ์์ ๋ฐ์ดํฐ์ ์ ์ฌ์ฉํ๋ฉด ํ๋ จ๊ณผ ํ ์คํธ๊ฐ ๋นจ๋ผ์ ์ด์ฉํ๋ ๊ฒ๋ ์์ง๋ง, ์ ์ฒด ๋ฐ์ดํฐ์ ์ ์ฌ์ฉํ ๋๋ณด๋ค ๋ฎ์ ์ ํ๋๋ฅผ ๊ฐ์ง๋ค๋ ์ ์ ๊ผญ ๊ธฐ์ตํ์.
๋ฐ์ดํฐ์
์ ํ๋ จ, ๊ฒ์ฆ, ํ
์คํธ์ฉ์ผ๋ก ๋๋ ๊ฒ์ด๋ค.
ํ๋ จ์ธํธ๋ก ๋ชจ๋ธ์ ํ๋ จํ๊ณ , ๊ฒ์ฆ ์ธํธ๋ก ๋ชจ๋ธ์ด ์ผ๋ง๋ ์ ์๋ํ๋์ง ํ๊ฐํ๋ค. ๊ฒ์ฆ ์ธํธ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ๋ชจ๋ธ์ ์ ํํ๊ฒ ๋๋ฉด ๋ถ๊ฐํผํ๊ฒ ๋ชจ๋ธ์ด ๊ฒ์ฆ์ธํธ์ ๋ ์ ์ํ๋๋๋ก ํธํฅ๋๊ธฐ ๋๋ฌธ์ ๋ชจ๋ธ์ด ์ ์ฐจ ๊ฐ์ ๋๋์ง ์ฌํ๊ฐํด๋ณด๊ธฐ์ํด ์ธ๋ฒ์งธ ์ธํธ์ธ ํ๊ฐ์ธํธ๋ฅผ ํ์ฉํด์ ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํด๋ณด๋๋ก ํ๋ค.
์ฐ์ , ์ด ์ฑ ์ ๊นํ๋ธ์์ ์ ๊ณตํ๋ ์๋ณธ์ฝ๋์๋ '์ ์ฒ๋ฆฌ๋ ๋ฐ์ดํฐ๋ฅผ ๋ค์ด๋ฐ๋ ์ฝ๋'๊ฐ ๋ด์ฅ๋์ด ์์ด ๋ฐ๋ก ์ ์ฒ๋ฆฌ ๊ณผ์ ์์ด ์ฝ๋ ์คํ์ด ๊ฐ๋ฅํ์ง๋ง, ์ด๋ป๊ฒ ๋ฐ์ดํฐ๊ฐ ์ ์ฒ๋ฆฌ ๋์๋์ง ์ดํด๋ณด๋๋ก ํ์.
1.1 import
import collections
import numpy as np
import pandas as pd
import re
from argparse import Namespace
1.2 ํ๋ จ, ๊ฒ์ฆ, ํ ์คํธ ์ธํธ๋ก ๋ฐ์ดํฐ ๋ถํ
args = Namespace(
raw_train_dataset_csv="data/yelp/raw_train.csv",
raw_test_dataset_csv="data/yelp/raw_test.csv",
proportion_subset_of_train=0.1,
train_proportion=0.7,
val_proportion=0.15,
test_proportion=0.15,
output_munged_csv="data/yelp/reviews_with_splits_lite.csv",
seed=1337
)
- ์ธ์์ ๋ถ์๋ช ๋ น์ ์ํ ๋ช ๋ นํ ์ต์ ์ธ, argparse ๋ฅผ ํ์ฉํ์ฌ ํ์ด์ฌ ๋ด๋ถ์์ ํ์ผ์ ๋ค์ด๋ฐ๊ณ , ๋ฐ์ดํฐ๋ฅผ ๋๋์ด์ค ์ ์๋ค.
- train 70% / validation 15% / test 15% ๋ก ๋ฐ์ดํฐ๋ฅผ ๋ถํ ํ ์์ ์ด๋ค.
# ์๋ณธ ๋ฐ์ดํฐ๋ฅผ ์ฝ์ต๋๋ค
train_reviews = pd.read_csv(args.raw_train_dataset_csv, header=None, names=['rating', 'review'])
- ๋ค์ด๋ฐ์ ์๋ณธ๋ฐ์ดํฐ๋ฅผ ํ์ด์ฌ์์ ํ์ฉํ๊ธฐ ์ํด train_reviews ๋ณ์์ ๋ฐ์ดํฐ๋ฅผ ์ฝ์ด์ฃผ๊ณ , ์ปฌ๋ผ๋ช ์ rating๊ณผ review๋ก ์ง์ ํด์ฃผ์๋ค.
# ๋ฆฌ๋ทฐ ํด๋์ค ๋น์จ์ด ๋์ผํ๋๋ก ๋ง๋ญ๋๋ค
by_rating = collections.defaultdict(list)
for _, row in train_reviews.iterrows():
by_rating[row.rating].append(row.to_dict())
review_subset = []
for _, item_list in sorted(by_rating.items()):
n_total = len(item_list)
n_subset = int(args.proportion_subset_of_train * n_total)
review_subset.extend(item_list[:n_subset])
review_subset = pd.DataFrame(review_subset)
- ์์ ์ธ๊ธํ๋ฏ์ด ํด๋น ์ฑ ์์ ์ฌ์ฉ๋ ๋ผ์ดํธ๋ฒ์ ์ ๋ฐ์ดํฐ์ ์ ์ ์ฒด ๋ฐ์ดํฐ์ ์ 10%๊ฐ ์ฌ์ฉ๋๋ค.
- ๋ฐ๋ผ์ review_subset์ ์กด์ฌํ๋ ๋ฐ์ดํฐ์์ 10%์ ํด๋นํ๋ ๋ฐ์ดํฐ๋ง ๋ฐ๋ก ์ ์ฅํด์ค๋ค.
- ๊ทธ๋ฆฌ๊ณ defaultdic๋ฉ์๋๋ฅผ ํ์ฉํด์ ํด๋์ค๋ณ๋ก ๋น์จ์ด ๋์ผํ๋๋ก ๋ง๋ค์ด์ค ๊ฒ์ด๋ค.
review_subset.head()
- ๊ทธ๋ ๊ฒ ์ถ๋ ฅ๋ ๋ฐ์ดํฐ๋ ์ด๋ฐ ํํ๋ฅผ ๊ฐ์ง๊ณ ์๋ค.
train_reviews.rating.value_counts()
- ์์์ ํด๋์ค๋ณ๋ก ๋น์จ์ด ๋์ในํ๋๋ก ๋ง๋ค์ด ์ค ๊ฒฐ๊ณผ๊ฐ์ด๋ค. (ํด๋์ค๋ณ๋ก ๊ฐ๊ฐ 280000๊ฐ)
# ๊ณ ์ ํด๋์ค
set(review_subset.rating)
- ํด๋์ค๋ 1๊ณผ 2๋ก ๋๋์ด์ง๋ ๊ฒ์ ๋ณผ ์ ์๋ค.
- (์ถํ ๋์ฌ ๊ฒ์ด์ง๋ง) 1์ negative, 2๋ positive ํด๋์ค์ด๋ค.
# ํ๋ จ, ๊ฒ์ฆ, ํ
์คํธ๋ฅผ ๋ง๋ค๊ธฐ ์ํด ๋ณ์ ์ ๊ธฐ์ค์ผ๋ก ๋๋๋๋ค
by_rating = collections.defaultdict(list)
for _, row in review_subset.iterrows():
by_rating[row.rating].append(row.to_dict())
# ๋ถํ ๋ฐ์ดํฐ๋ฅผ ๋ง๋ญ๋๋ค.
final_list = []
np.random.seed(args.seed)
for _, item_list in sorted(by_rating.items()):
np.random.shuffle(item_list)
n_total = len(item_list)
n_train = int(args.train_proportion * n_total)
n_val = int(args.val_proportion * n_total)
n_test = int(args.test_proportion * n_total)
# ๋ฐ์ดํฐ ํฌ์ธํฐ์ ๋ถํ ์์ฑ์ ์ถ๊ฐํฉ๋๋ค
for item in item_list[:n_train]:
item['split'] = 'train'
for item in item_list[n_train:n_train+n_val]:
item['split'] = 'val'
for item in item_list[n_train+n_val:n_train+n_val+n_test]:
item['split'] = 'test'
# ์ต์ข
๋ฆฌ์คํธ์ ์ถ๊ฐํฉ๋๋ค
final_list.extend(item_list)
- ์์ ๋์๋ args์์ ์ง์ ํ 7:1.5:1.5 ๋น์จ๋ก ๊ฐ๊ฐ ๋ฐ์ดํฐ๋ฅผ train / val / test ๋ก ์ง์ ํ๊ณ , ์ต์ข ๋ฆฌ์คํธ์ ์ถ๊ฐํด์ฃผ์๋ค.
# ๋ถํ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์ดํฐ ํ๋ ์์ผ๋ก ๋ง๋ญ๋๋ค
final_reviews = pd.DataFrame(final_list)
- ๋ฆฌ์คํธํํ์ ๋ฐ์ดํฐ๋ฅผ ๋ถ์์ ์ฉ์ดํ pandas ๋ฐ์ดํฐ ํ๋ ์์ผ๋ก ๋ง๋ค์ด์ค๋ค.
final_reviews.split.value_counts()
- ๋ฐ์ดํฐ์ ์๋ฅผ ํ์ธํจ์ผ๋ก์จ 7: 1.5 : 1.5๋ก ์ ๋๋์๋์ง ํ์ธํด๋ณธ๋ค.
1.3 ๋ฐ์ดํฐ ์ ์
# ๋ฆฌ๋ทฐ๋ฅผ ์ ์ฒ๋ฆฌํฉ๋๋ค
def preprocess_text(text):
text = text.lower()
text = re.sub(r"([.,!?])", r" \1 ", text)
text = re.sub(r"[^a-zA-Z.,!?]+", r" ", text)
return text
final_reviews.review = final_reviews.review.apply(preprocess_text)
- ์ต์ํ์ ๋ฐ์ดํฐ ์ ์ ์์ ์ ๊ฑฐ์น๋ค.
- ์ ๊ท์์ ํ์ฉํ์ฌ ๊ธฐํธ ์๋ค์ ๊ณต๋ฐฑ์ ๋ฃ๊ณ , ๊ตฌ๋์ ์ด ์๋ ๊ธฐํธ๋ฅผ ์ ๊ฑฐํ๋ ์ ์ ์์ ์ ์งํํด์ฃผ์๋ค.
final_reviews['rating'] = final_reviews.rating.apply({1: 'negative', 2: 'positive'}.get)
final_reviews.head()
- ํด๋น ํ๋ก์ ํธ์์๋ ์ด๋ ๊ฒ ์ ์ ๋ ๋ฐ์ดํฐ๋ฅผ ํ์ฉํ ๊ฒ์ด๋ค.
final_reviews.to_csv(args.output_munged_csv, index=False)
<NEXT> ๋ฐ์ดํฐ ์ฒ๋ฆฌ๋ฅผ ์ํ ํด๋์ค ์ดํด๋ณด๊ธฐ
https://didu-story.tistory.com/86