
-- ๋ณธ ํฌ์คํ
์ ํ์ดํ ์น๋ก ๋ฐฐ์ฐ๋ ์์ฐ์ด ์ฒ๋ฆฌ (ํ๋น๋ฏธ๋์ด) ์ฑ
์ ์ฐธ๊ณ ํด์ ์์ฑ๋ ๊ธ์
๋๋ค.
-- ์์ค์ฝ๋ ) https://github.com/rickiepark/nlp-with-pytorch
rickiepark/nlp-with-pytorch
<ํ์ดํ ์น๋ก ๋ฐฐ์ฐ๋ ์์ฐ์ด ์ฒ๋ฆฌ>(ํ๋น๋ฏธ๋์ด, 2021)์ ์์ค ์ฝ๋๋ฅผ ์ํ ์ ์ฅ์์ ๋๋ค. - rickiepark/nlp-with-pytorch
github.com
โถ ๋ ์คํ ๋ ๋ฆฌ๋ทฐ ๊ฐ์ฑ ๋ถ๋ฅํ๊ธฐ
์๋ ํฌ์คํ ์์ ์ด๋ป๊ฒ ์ ์ฒ๋ฆฌ๋ ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํ๊ฒ ๋๋์ง ๋ฏธ๋ฆฌ ํ์ตํ๋ฉด ์ข์ ๊ฒ์ด๋ค. ํ์ง๋ง ํด๋น ์ฝ๋์์๋ '์ ์ฒ๋ฆฌ ๊ณผ์ '์ด ์๋ต๋ '์ ์ฒ๋ฆฌ ๋์ด์ง ๋ฐ์ดํฐ'๋ฅผ ํ์ฉํ๊ณ ์๋ค๋ ๊ฒ๋ง ์์๋์.
https://didu-story.tistory.com/83
[NLP] ๋ ์คํ ๋ ๋ฆฌ๋ทฐ ๊ฐ์ฑ ๋ถ๋ฅํ๊ธฐ (1) (feat.ํ์ดํ ์น๋ก ๋ฐฐ์ฐ๋ ์์ฐ์ด ์ฒ๋ฆฌ)
-- ๋ณธ ํฌ์คํ ์ ํ์ดํ ์น๋ก ๋ฐฐ์ฐ๋ ์์ฐ์ด ์ฒ๋ฆฌ (ํ๋น๋ฏธ๋์ด) ์ฑ ์ ์ฐธ๊ณ ํด์ ์์ฑ๋ ๊ธ์ ๋๋ค. -- ์์ค์ฝ๋ ) https://github.com/rickiepark/nlp-with-pytorch (ํ๋น๋ฏธ๋์ด, 2021)์ ์์ค ์ฝ๋๋ฅผ ์ํ ์ ์ฅ์์ ..
didu-story.tistory.com
1. ํ์ดํ ์น ๋ฐ์ดํฐ์ ์ดํดํ๊ธฐ
ํด๋น ํ๋ก์ ํธ๋ pytorch ํ๋ ์์ํฌ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์งํ๋๋ค. ๊ทธ๋ฆฌ๊ณ ํด๋์ค ๊ฐ์ฒด๋ฅผ ํ์ฉํด์ ์ฃผ์ํ ํ์ดํ๋ผ์ธ์ ์ํํ๊ฒ ๋๋ค. ํ์ด์ฌ์ ํด๋์ค๊ฐ์ฒด์ ๋ํ ์ดํด๊ฐ ๋ถ์กฑํ๋ค๋ฉด ์๋ ํฌ์คํ ์ ์ฐธ๊ณ ํ๊ณ ์ดํดํ๊ณ ์ค์. ๋ํ ํ์ดํ ์น๋ Dataset, DataLoader ๋ฅผ ํ์ฉํ์ฌ ๋ฐ์ดํฐ์ ํํ๋ฅผ ๋ณํ์์ผ์ฃผ๋๋ฐ, ์ด์๋ํ ๊ฒ๋ ์๋ ํฌ์คํ ์ ์ฐธ๊ณ ํ๋ฉด ์ดํด๊ฐ ๋ ์ฌ์ธ ๊ฒ์ด๋ค.
https://didu-story.tistory.com/85
[Pytorch] ํ์ดํ ์น์ Custom dataset๊ณผ DataLoader ์ดํดํ๊ธฐ
1. ํ์ดํ ์น์ Custom dataset / DataLoader 1.1 Custom Dataset ์ ์ฌ์ฉํ๋ ์ด์ ๋ฐฉ๋ํ ๋ฐ์ดํฐ์ ์ --> ๋ฐ์ดํฐ๋ฅผ ํ ๋ฒ์ ๋ถ๋ฌ์ค๊ธฐ ์ฝ์ง ์์ ๋ฐ์ดํฐ๋ฅผ ํ ๋ฒ์ ๋ถ๋ฅด์ง ์๊ณ ํ๋์ฉ๋ง ๋ถ๋ฌ์ ์ฐ๋ ๋ฐฉ์์ ํ
didu-story.tistory.com
https://didu-story.tistory.com/84
[ํ์ด์ฌ] ํด๋์ค ๊ฐ์ฒด
1. ํด๋์ค(class)๋ ํด๋์ค๋ ๊ฐ์ฒด์ ๊ตฌ์กฐ์ ํ๋์ ์ ์ํ๋ค ๊ฐ์ฒด์ ํด๋์ค๋ ์ด๊ธฐํ๋ฅผ ํตํด ์ ์ดํ๋ค. (__init__) ๊ฐ์ฒด์งํฅ ํ๋ก๊ทธ๋๋ฐ, ๋ณต์กํ ๋ฌธ์ ๋ฅผ ๊ฐ๋จํ๊ฒ ํด๊ฒฐํ ์๋ค๋ ์ฅ์ ์กด์ฌ 2. ํด๋์ค
didu-story.tistory.com
1.1 Review Dataset
- ReviewDataset ํด๋์ค๋ ๋ฐ์ดํฐ์ ์ด ์ต์ํ์ผ๋ก ์ ์ ๋๊ณ 3๊ฐ๋ก ๋๋์๋ค๊ณ ๊ฐ์ ํ๋ค.
- ํนํ ํด๋น ๋ฐ์ดํฐ์ ์ ๊ณต๋ฐฑ์ ๊ธฐ์ค์ผ๋ก ๋๋ ์ ํ ํฐ ๋ฆฌ์คํธ๋ฅผ ์ป์ ์ ์๋ค๊ณ ๊ฐ์ ํ๋ค.
- ์ํ์ด ํ๋ จ, ๊ฒ์ฆ, ํ
์คํธ ์ค ์ด๋ ์ธํธ์ ์๋์ง ํ์๋์๋ค๊ณ ๊ฐ์ ํ๋ค.
- ํด๋น ๋ฐ์ดํฐ์ ์ ์ ์ฒ๋ฆฌ ๊ณผ์ ์ ์๋ ๋งํฌ ์ฐธ๊ณ
- https://didu-story.tistory.com/83
class ReviewDataset(Dataset):
#ํด๋์ค ์ธ์คํด์ค ์์ฑ์ ์ด๊ธฐํ ํ๋ฉด์ ์คํ๋๋ ๋ถ๋ถ
# self ๋? ์ธ์คํด์ค(ํด๋์ค์ ์ํด ๋ง๋ค์ด์ง ๊ฐ์ฒด) ์๊ธฐ์์ ์ ์๋ฏธ,
# self ๊ฐ ์๋ ๊ฒ์ด ์ธ์คํด์ค ๋ณ์
def __init__(self, review_df, vectorizer):
"""
๋งค๊ฐ๋ณ์:
review_df (pandas.DataFrame): ๋ฐ์ดํฐ์
vectorizer (ReviewVectorizer): ReviewVectorizer ๊ฐ์ฒด
"""
self.review_df = review_df
self._vectorizer = vectorizer
self.train_df = self.review_df[self.review_df.split=='train']
self.train_size = len(self.train_df)
self.val_df = self.review_df[self.review_df.split=='val']
self.validation_size = len(self.val_df)
self.test_df = self.review_df[self.review_df.split=='test']
self.test_size = len(self.test_df)
self._lookup_dict = {'train': (self.train_df, self.train_size),
'val': (self.val_df, self.validation_size),
'test': (self.test_df, self.test_size)}
self.set_split('train')
# ํด๋์ค ๋ฉ์๋ (๋ฐ์ฝ๋ ์ดํฐ ์ฌ์ฉ) = ํด๋์ค ๋ณ์๋ฅผ ์ปจํธ๋กค ํ ๋ ์ฌ์ฉ๋๋ค.
# cls ์ธ์๋ฅผ ๋ฐ์. cls? ReviewDataset ํด๋์ค๋ฅผ ๋ปํจ
@classmethod
def load_dataset_and_make_vectorizer(cls, review_csv):
# ReviewVectorizer๊ฐ์ฒด = ์๋ ๋์ด (์ดํ์ฌ์ ์ ์์ฑํ๊ณ ๊ด๋ฆฌํ๋ ๊ฐ์ฒด)
""" ๋ฐ์ดํฐ์
์ ๋ก๋ํ๊ณ ์๋ก์ด ReviewVectorizer ๊ฐ์ฒด๋ฅผ ๋ง๋ญ๋๋ค
๋งค๊ฐ๋ณ์:
review_csv (str): ๋ฐ์ดํฐ์
์ ์์น
๋ฐํ๊ฐ:
ReviewDataset์ ์ธ์คํด์ค
"""
review_df = pd.read_csv(review_csv) # ์๋์์ review_csv๋ฅผ ํตํด ์ ์ ๋ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ฌ๊ฑฐ์ผ
train_review_df = review_df[review_df.split=='train']
return cls(review_df, ReviewVectorizer.from_dataframe(train_review_df))
@classmethod
def load_dataset_and_load_vectorizer(cls, review_csv, vectorizer_filepath):
""" ๋ฐ์ดํฐ์
์ ๋ก๋ํ๊ณ ์๋ก์ด ReviewVectorizer ๊ฐ์ฒด๋ฅผ ๋ง๋ญ๋๋ค.
์บ์๋ ReviewVectorizer ๊ฐ์ฒด๋ฅผ ์ฌ์ฌ์ฉํ ๋ ์ฌ์ฉํฉ๋๋ค.
๋งค๊ฐ๋ณ์:
review_csv (str): ๋ฐ์ดํฐ์
์ ์์น
vectorizer_filepath (str): ReviewVectorizer ๊ฐ์ฒด์ ์ ์ฅ ์์น
๋ฐํ๊ฐ:
ReviewDataset์ ์ธ์คํด์ค
"""
review_df = pd.read_csv(review_csv)
vectorizer = cls.load_vectorizer_only(vectorizer_filepath)
return cls(review_df, vectorizer)
@staticmethod
def load_vectorizer_only(vectorizer_filepath):
""" ํ์ผ์์ ReviewVectorizer ๊ฐ์ฒด๋ฅผ ๋ก๋ํ๋ ์ ์ ๋ฉ์๋
๋งค๊ฐ๋ณ์:
vectorizer_filepath (str): ์ง๋ ฌํ๋ ReviewVectorizer ๊ฐ์ฒด์ ์์น
๋ฐํ๊ฐ:
ReviewVectorizer์ ์ธ์คํด์ค
"""
with open(vectorizer_filepath) as fp:
return ReviewVectorizer.from_serializable(json.load(fp))
def save_vectorizer(self, vectorizer_filepath):
""" ReviewVectorizer ๊ฐ์ฒด๋ฅผ json ํํ๋ก ๋์คํฌ์ ์ ์ฅํฉ๋๋ค
๋งค๊ฐ๋ณ์:
vectorizer_filepath (str): ReviewVectorizer ๊ฐ์ฒด์ ์ ์ฅ ์์น
"""
with open(vectorizer_filepath, "w") as fp:
json.dump(self._vectorizer.to_serializable(), fp)
def get_vectorizer(self):
""" ๋ฒกํฐ ๋ณํ ๊ฐ์ฒด๋ฅผ ๋ฐํํฉ๋๋ค """
return self._vectorizer
def set_split(self, split="train"):
""" ๋ฐ์ดํฐํ๋ ์์ ์๋ ์ด์ ์ฌ์ฉํด ๋ถํ ์ธํธ๋ฅผ ์ ํํฉ๋๋ค
๋งค๊ฐ๋ณ์:
split (str): "train", "val", "test" ์ค ํ๋
"""
self._target_split = split
self._target_df, self._target_size = self._lookup_dict[split]
def __len__(self):
return self._target_size
def __getitem__(self, index):
""" ํ์ดํ ์น ๋ฐ์ดํฐ์
์ ์ฃผ์ ์ง์
๋ฉ์๋
๋งค๊ฐ๋ณ์:
index (int): ๋ฐ์ดํฐ ํฌ์ธํธ์ ์ธ๋ฑ์ค
๋ฐํ๊ฐ:
๋ฐ์ดํฐ ํฌ์ธํธ์ ํน์ฑ(x_data)๊ณผ ๋ ์ด๋ธ(y_target)๋ก ์ด๋ฃจ์ด์ง ๋์
๋๋ฆฌ
"""
row = self._target_df.iloc[index]
review_vector = \
self._vectorizer.vectorize(row.review)
rating_index = \
self._vectorizer.rating_vocab.lookup_token(row.rating)
return {'x_data': review_vector,
'y_target': rating_index}
def get_num_batches(self, batch_size):
""" ๋ฐฐ์น ํฌ๊ธฐ๊ฐ ์ฃผ์ด์ง๋ฉด ๋ฐ์ดํฐ์
์ผ๋ก ๋ง๋ค ์ ์๋ ๋ฐฐ์น ๊ฐ์๋ฅผ ๋ฐํํฉ๋๋ค
๋งค๊ฐ๋ณ์:
batch_size (int)
๋ฐํ๊ฐ:
๋ฐฐ์น ๊ฐ์
"""
return len(self) // batch_size
- ํ์ดํ ์น์์ ์๋ก์ด ๋ฐ์ดํฐ์
์ ์ฌ์ฉํ๋ ค๋ฉด ๋จผ์ Dataset ํด๋์ค๋ฅผ ์์ํ์ฌ __getitem()__, __len__() ๋ฉ์๋๋ฅผ ๊ตฌํํด์ผํ๋ค.
- from torch.utils.data import Dataset, DataLoader
- ํด๋น ํด๋์ค ์์์๋ ๋ค์ํ ํ์ดํ ์น ์ ํธ๋ฆฌํฐ๋ฅผ ์ฌ์ฉํ๋๋ฐ, DataLoader / ReviewVectorizer ๊ณผ ๊ฐ์ ํด๋์ค๋ ์๋์ ๋์จ๋ค. (ํด๋์ค๋ค์ ์๋ก ํฌ๊ฒ ์์กดํ๋ค.)
- ReviewVectorizer => ๋ฆฌ๋ทฐํ ์คํธ๋ฅผ ์์น๋ก ๋ณํํ๋ ํด๋์ค
- DataLoader => ๋ฐ์ดํฐ์
์์ ์ํ๋งํ๊ณ ๋ชจ์์ ๋ฏธ๋๋ฐฐ์น๋ฅผ ๋ง๋๋ ํด๋์ค
- ๋ฐ์ดํฐ ๋ก๋์ ๋ฏธ๋๋ฐฐ์น? https://wikidocs.net/55580
โท ์ฌ๊ธฐ์ ์ ๊น, Dataset ํด๋์ค๋ฅผ ์์ํ๋ค๋ ๋ป์ด ๋ฌด์์ผ๊น?
- torch.utils.data.Dataset ์ ๋ฐ์ดํฐ์ ์ ๋ํ๋ด๋ '์ถ์ ํด๋์ค'์ด๋ค.
- ์ฐ๋ฆฌ๋ง์ ๋ฐ์ดํฐ์
์ Dataset์ ์์ํ๊ณ , ์๋์ ๊ฐ์ด ์ค๋ฒ๋ผ์ด๋ ํด์ผํ๋ค.
- len(dataset)์์ ํธ์ถ๋๋ __len__์ ๋ฐ์ดํฐ์ ์ ํฌ๊ธฐ๋ฅผ ๋ฆฌํดํ๋ค.
- dataset[i]์์ ํธ์ถ๋๋ __getitem__์ i๋ฒ์งธ ์ํ์ ์ฐพ๋๋ฐ ์ฌ์ฉ๋๋ค.
- ์ฆ, __init__์ ํตํด ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํด์ ๊ฐ์ ธ์ค์ง๋ง, __getitem__์ ์ด์ฉํด์ ๋ฐ์ดํฐ๋ฅผ ํ๋์ฉ ํ๋ ํ๋ค.
- ๊ทธ๋ฆฌ๊ณ ์ต์ข ๋ฆฌํด๊ฐ์{'x_data': review_vector, 'y_target': rating_index} ํํ์ ์ฌ์ ํํ๋ฅผ ๊ฐ์ง๋ค.
โท ReviewDataset ์ปค์คํ ๋ฐ์ดํฐ์ ์ ๋ฑ์ฅํ๋ ํจ์ ์ ๋ฆฌ
- __init__(self, review_df, Vectorizer)
- ๋ฐ์ดํฐ์ (review_df)
- ๋ฒกํฐํํด์ฃผ๋ ๊ฐ์ฒด(vectorizer)
- train_df / train_size / val_df / val_size / test_df / test_size ๋ณ์๋ฅผ ์ ์
- @classmethod load_dataset_and_make_vectorizer(cls, review_csv)
- ๋ฐ์ดํฐ์ ์ ๋ก๋ํ๊ณ ์๋ก์ด ReviewVectorizer ๊ฐ์ฒด๋ฅผ ๋ง๋ค์ด์ฃผ๋ ํจ์
- review_csv๋ผ๋ ๋ฐ์ดํฐ์ ์ ์์น๋ฅผ ๋งค๊ฐ๋ณ์๋ก ๋ฐ๋๋ค
- ReviewDataset(reveiw_df, ReviewVectorizer.from_dataset(train_review_df) ํ ๊ฒฐ๊ณผ๊ฐ์ ๋ฐํ
- ReviewVectorizer.from_dataset ๋ ๋ฐ์ดํฐ์
๋ฐ์ดํฐํ๋ ์์์ Vectorizer ๊ฐ์ฒด๋ฅผ ๋ง๋๋ ๋ฉ์๋
๋ฐํ๊ฐ์ด ReviewVectorizer ๊ฐ์ฒด์ด๋ค.
- ReviewVectorizer.from_dataset ๋ ๋ฐ์ดํฐ์
๋ฐ์ดํฐํ๋ ์์์ Vectorizer ๊ฐ์ฒด๋ฅผ ๋ง๋๋ ๋ฉ์๋
- @staticmethod load_vectorizer_only(vetorizer_filepath)
- ํ์ผ์์ ReviewVectorizer ๊ฐ์ฒด๋ฅผ ๋ก๋ํ๋ ์ ์ ๋ฉ์๋
- ReviewVectorizer.from_serializable(json.load(fp)) ๋ฅผ ๋ฐํํ๋ค.
- ReviewVectorizer.from_serializable ๋ ์ง๋ ฌํ๋ ๋์ ๋๋ฆฌ(json.load(fp))์์ ReviewVectorizer ๊ฐ์ฒด๋ฅผ ๋ง๋๋ ๋ฉ์๋
- save_vectorizer(self, vectorizer_filepath)
- ReviewVectorizer ๊ฐ์ฒด๋ฅผ jsonํํ๋ก ๋์คํฌ์ ์ ์ฅํ๋ ๋ฉ์๋
- get_vectorizer(self)
- ๋ฒกํฐ ๋ณํ ๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ ๋ฉ์๋self._vectorizer ๊ฐ์ ๋ฐํ
- set_split(self, split="train")
- ๋ฐ์ดํฐ ํ๋ ์์ ์๋ ์ด์ ์ฌ์ฉํ์ฌ ๋ถํ ์ธํธ๋ฅผ ์ ํ
"train", "test", "val" ์ค ํ๋
- ๋ฐ์ดํฐ ํ๋ ์์ ์๋ ์ด์ ์ฌ์ฉํ์ฌ ๋ถํ ์ธํธ๋ฅผ ์ ํ
- __len__(self)
- __getitem(self, index)
- {"x_data" : review_vector, "y_target" : rating_index} ๋ก ์ด๋ฃจ์ด์ง dicํํ๋ก ๋ฐํ
- get_num_batches(self, batch_size)
- ๋ฐฐ์น ํฌ๊ธฐ๊ฐ ์ฃผ์ด์ง๋ฉด ๋ฐ์ดํฐ์ ์ผ๋ก ๋ง๋ค ์์๋ ๋ฐฐ์น ๊ฐ์๋ฅผ ๋ฐํ
1.2 Vocabulary, Vetorizer, DataLoader ํด๋์ค
- ํด๋น ์์ ๋ ์ ์ธ๊ฐ์ ํด๋์ค๋ฅผ ํ์ฉํ์ฌ ์ค์ํ ํ์ดํ๋ผ์ธ์ ์ํํ๋ค.
- ํ
์คํธ์ ์
๋ ฅ์ ๋ฒกํฐ์ ๋ฏธ๋๋ฐฐ์น๋ก ๋ฐ๊ฟ์ฃผ๊ธฐ ์ํด ํด๋น ํด๋์ค๋ค์ ์ฌ์ฉํ๋ค.
- ์ด ์ธ๊ฐ์ ํด๋์ค๋ ๊ฐ ํ ํฐ์ ์ ์์ ๋งคํํ๊ณ , ์ด ๋งคํ์ ๊ฐ ๋ฐ์ดํฐํฌ์ธํธ์ ์ ์ฉํ์ฌ ๋ฒกํฐ ํํ๋ก ๋ณํํด์ค๋ค. ๊ทธ ๋ค์ ๋ฒกํฐ๋ก ๋ณํํ ๋ฐ์ดํฐ ํฌ์ธํธ๋ฅผ ๋ชจ๋ธ์ ์ํด ๋ฏธ๋๋ฐฐ์น๋ก ๋ชจ์๋ค.
- ์ ์ฒ๋ฆฌ ๋ ๋ฐ์ดํฐ(ํ ์คํธ)๋ฅผ ์ฌ์ฉํ๋ค. (์ฆ ๋ฐ์ดํฐํฌ์ธํธ๋ ํ ํฐํ๋ ์งํฉ์ด๋ค.
1.2.1 Vocabulary ํด๋์ค
- ๋จธ์ ๋ฌ๋ ํ์ดํ๋ผ์ธ์ ํ์ํ ํ ํฐ๊ณผ ์ ์ ๋งคํ์ ๊ด๋ฆฌํ๋ ํด๋์ค
- ํ ํฐ์ ์ ์๋ก ๋งคํํ๋ ํด๋์ค (ํ ์คํธ์ ๋ฐฐ์น๋ฅผ ๋ฏธ๋๋ฐฐ์น๋ก ๋ฐ๊พธ๋ ๊ณผ์ ์ ์ฒซ ๋จ๊ณ)
- ํ ํฐ๊ณผ ์ ์ ์ฌ์ด๋ฅผ 1:1 ๋งคํํ๋ ๋ฐฉ๋ฒ (๋ฐ๋๋ก ๋งคํํ๋ ๊ฒฝ์ฐ๊น์ง, ์ด ๋์ ๋๋ฆฌ ๋๊ฐ ํ์)
- ๋ ๋์ ๋๋ฆฌ๋ฅผ Vocabulary ํด๋์ค์ ์บก์ํ ํ ๊ฒ
- ํ๋ จ ๋ฐ์ดํฐ์
์ ์๋ ๋จ์ด๋ UNK (Unknown) ์ผ๋ก ์ฒ๋ฆฌ
- ์์ฃผ ๋ฑ์ฅํ์ง ์๋ ํ ํฐ๋ค์ ์ ํํด์ค => ์ด๋ฐ ํ ํฐ๋ค์ด UNK์ผ๋ก ์ฒ๋ฆฌ๋๋ ๊ฒ
class Vocabulary(object):
""" ๋งคํ์ ์ํด ํ
์คํธ๋ฅผ ์ฒ๋ฆฌํ๊ณ ์ดํ ์ฌ์ ์ ๋ง๋๋ ํด๋์ค """
def __init__(self, token_to_idx=None, add_unk=True, unk_token="<UNK>"):
"""
๋งค๊ฐ๋ณ์:
token_to_idx (dict): ๊ธฐ์กด ํ ํฐ-์ธ๋ฑ์ค ๋งคํ ๋์
๋๋ฆฌ
add_unk (bool): UNK ํ ํฐ์ ์ถ๊ฐํ ์ง ์ง์ ํ๋ ํ๋๊ทธ
unk_token (str): Vocabulary์ ์ถ๊ฐํ UNK ํ ํฐ
"""
if token_to_idx is None:
token_to_idx = {}
self._token_to_idx = token_to_idx
self._idx_to_token = {idx: token
for token, idx in self._token_to_idx.items()}
self._add_unk = add_unk
self._unk_token = unk_token
self.unk_index = -1
if add_unk:
self.unk_index = self.add_token(unk_token)
def to_serializable(self):
""" ์ง๋ ฌํํ ์ ์๋ ๋์
๋๋ฆฌ๋ฅผ ๋ฐํํฉ๋๋ค """
return {'token_to_idx': self._token_to_idx,
'add_unk': self._add_unk,
'unk_token': self._unk_token}
@classmethod
def from_serializable(cls, contents):
""" ์ง๋ ฌํ๋ ๋์
๋๋ฆฌ์์ Vocabulary ๊ฐ์ฒด๋ฅผ ๋ง๋ญ๋๋ค """
return cls(**contents)
# ์๋ก์ด ํ ํฐ์ ์ถ๊ฐํ๊ธฐ ์ํ ํจ์
def add_token(self, token):
""" ํ ํฐ์ ๊ธฐ๋ฐ์ผ๋ก ๋งคํ ๋์
๋๋ฆฌ๋ฅผ ์
๋ฐ์ดํธํฉ๋๋ค
๋งค๊ฐ๋ณ์:
token (str): Vocabulary์ ์ถ๊ฐํ ํ ํฐ
๋ฐํ๊ฐ:
index (int): ํ ํฐ์ ์์ํ๋ ์ ์
"""
if token in self._token_to_idx:
index = self._token_to_idx[token]
else:
index = len(self._token_to_idx)
self._token_to_idx[token] = index
self._idx_to_token[index] = token
return index
def add_many(self, tokens):
""" ํ ํฐ ๋ฆฌ์คํธ๋ฅผ Vocabulary์ ์ถ๊ฐํฉ๋๋ค.
๋งค๊ฐ๋ณ์:
tokens (list): ๋ฌธ์์ด ํ ํฐ ๋ฆฌ์คํธ
๋ฐํ๊ฐ:
indices (list): ํ ํฐ ๋ฆฌ์คํธ์ ์์๋๋ ์ธ๋ฑ์ค ๋ฆฌ์คํธ
"""
return [self.add_token(token) for token in tokens]
# ํ ํฐ์ ํด๋นํ๋ ์ธ๋ฑ์ค๋ฅผ ์ถ์ถํ๊ธฐ ์ํ ํจ์
def lookup_token(self, token):
""" ํ ํฐ์ ๋์ํ๋ ์ธ๋ฑ์ค๋ฅผ ์ถ์ถํฉ๋๋ค.
ํ ํฐ์ด ์์ผ๋ฉด UNK ์ธ๋ฑ์ค๋ฅผ ๋ฐํํฉ๋๋ค.
๋งค๊ฐ๋ณ์:
token (str): ์ฐพ์ ํ ํฐ
๋ฐํ๊ฐ:
index (int): ํ ํฐ์ ํด๋นํ๋ ์ธ๋ฑ์ค
๋
ธํธ:
UNK ํ ํฐ์ ์ฌ์ฉํ๋ ค๋ฉด (Vocabulary์ ์ถ๊ฐํ๊ธฐ ์ํด)
`unk_index`๊ฐ 0๋ณด๋ค ์ปค์ผ ํฉ๋๋ค.
"""
if self.unk_index >= 0:
return self._token_to_idx.get(token, self.unk_index)
else:
return self._token_to_idx[token]
# ์ธ๋ฑ์ค์ ํด๋นํ๋ ํ ํฐ์ ์ถ์ถํ๊ธฐ ์ํ ํจ์
def lookup_index(self, index):
""" ์ธ๋ฑ์ค์ ํด๋นํ๋ ํ ํฐ์ ๋ฐํํฉ๋๋ค.
๋งค๊ฐ๋ณ์:
index (int): ์ฐพ์ ์ธ๋ฑ์ค
๋ฐํ๊ฐ:
token (str): ์ธํ
์ค์ ํด๋นํ๋ ํ ํฐ
์๋ฌ:
KeyError: ์ธ๋ฑ์ค๊ฐ Vocabulary์ ์์ ๋ ๋ฐ์ํฉ๋๋ค.
"""
if index not in self._idx_to_token:
raise KeyError("Vocabulary์ ์ธ๋ฑ์ค(%d)๊ฐ ์์ต๋๋ค." % index)
return self._idx_to_token[index]
def __str__(self):
return "<Vocabulary(size=%d)>" % len(self)
def __len__(self):
return len(self._token_to_idx)
โท Vocabulary ํด๋์ค์ ๋ฑ์ฅํ๋ ํจ์ ์ ๋ฆฌ
- __init__(self, token_to_idx=None, add_unk=True, unk_token="<UNK>"
- ๋งค๊ฐ๋ณ์ ์ค๋ช
- token_to_idx (dict) : ๊ธฐ์กด ํ ํฐ-์ธ๋ฑ์ค ๋งคํ ๋์ ๋๋ฆฌ
- add_unk (bool) : UNK ํ ํฐ์ ์ถ๊ฐํ ์ง ์ง์ ํ๋ ํ๋๊ทธ
- unk_token (str) : Vocabulary์ ์ถ๊ฐํ UNK ํ ํฐ
- ๋งค๊ฐ๋ณ์ ์ค๋ช
- to_serializable(self)
- ์ง๋ ฌํ ํ ์ ์๋ ๋์
๋๋ฆฌ๋ฅผ ๋ฐํ
- {'token_to_idx': self._token_to_idx, 'add_unk': self._add_unk, 'unk_token': self._unk_token} ํํ
- ์ง๋ ฌํ ํ ์ ์๋ ๋์
๋๋ฆฌ๋ฅผ ๋ฐํ
- @classmethod from_serializable(cls, contents)
- ์ง๋ ฌํ๋ ๋์ ๋๋ฆฌ์์ vocabulary ๊ฐ์ฒด๋ฅผ ์์ฑ
- add_token(self, token)
- ์๋ก์ด ํ ํฐ์ ์ถ๊ฐํ๊ธฐ ์ํ ํจ์
- ํ ํฐ์ ๊ธฐ๋ฐ์ผ๋ก ๋งคํ ๋์ ๋๋ฆฌ๋ฅผ ์ ๋ฐ์ดํธํด์ค๋ค
- ๋งค๊ฐ๋ณ์ token ์ด Vocabulary์ ์ถ๊ฐํ ํ ํฐ์ด ๋๋ค.
- return index : ํ ํฐ์ ์์ํ๋ ์ธ๋ฑ์ค๊ฐ ๋ฐํ๊ฐ์ผ๋ก ์ถ๋ ฅ
- add_many(self, tokens)
- ํ ํฐ ๋ฆฌ์คํธ๋ฅผ vocabulary์ ์ถ๊ฐ
- tokens ๋ ๋ฌธ์์ด list
- ๋ฐํ๊ฐ๋ tokens ์ ์์ํ๋ ์ธ๋ฑ์ค๊ฐ
- lookup_token(self, token)
- ํ ํฐ์ ๋์ํ๋ ์ธ๋ฑ์ค๋ฅผ ์ถ์ถํ๋ ๋ฉ์๋
- ๋งค๊ฐ๋ณ์ token ์ด ์ฐพ์ ํ ํฐ์ด๊ณ
- ๋ฐํ๊ฐ์ token์ด ๊ฐ๋ ์ธ๋ฑ์ค๊ฐ
- lookup_index(self, index)
- ์ธ๋ฑ์ค์ ๋์ํ๋ ํ ํฐ์ ์ฐพ๋ ๋ฉ์๋
- ๋งค๊ฐ๋ณ์ index๊ฐ ์ฐพ์ ์ธ๋ฑ์ค
- ๋ฐํ๊ฐ์ index ์ ํด๋นํ๋ ํ ํฐ
1.2.2 Vectorizer ํด๋์ค
- ํ ์คํธ๋ฅผ ์์น ๋ฒกํฐ๋ก ๋ณํํ๋ ํด๋์ค์ด์, ์ดํ ์ฌ์ ์ ์์ฑํ๊ณ ๊ด๋ฆฌํ๋ ํด๋์ค
- ํ ์คํธ ๋ฐ์ดํฐ๋ฅผ ๋ฒกํฐ์ ๋ฏธ๋๋ฐฐ์น๋ก ๋ฐ๊พธ๋ ๋๋ฒ์งธ ๋จ๊ณ
- ์ ๋ ฅ ๋ฐ์ดํฐ ํฌ์ธํธ์ ํ ํฐ์ ์ํํ๋ฉด์ ๊ฐ ํ ํฐ์ ์ ์๋ก ๋ฐ๊ฟ์ฃผ๋ ๊ฒ
- ํด๋น ํด๋์ค์ ๊ฒฐ๊ณผ๋ '๋ฒกํฐ'
- ํญ์ ๊ธธ์ด๊ฐ ์ผ์ ํ ๋ฒกํฐ ์ถ๋ ฅ
class ReviewVectorizer(object):
""" ์ดํ ์ฌ์ ์ ์์ฑํ๊ณ ๊ด๋ฆฌํฉ๋๋ค """
def __init__(self, review_vocab, rating_vocab):
"""
๋งค๊ฐ๋ณ์:
review_vocab (Vocabulary): ๋จ์ด๋ฅผ ์ ์์ ๋งคํํ๋ Vocabulary
rating_vocab (Vocabulary): ํด๋์ค ๋ ์ด๋ธ์ ์ ์์ ๋งคํํ๋ Vocabulary
"""
self.review_vocab = review_vocab
self.rating_vocab = rating_vocab
# vectorize ๋งค์๋๋ ํด๋น ํด๋์ค์ ํต์ฌ์ ์ธ ๊ธฐ๋ฅ์ ์บก์ํ
# ๋งค๊ฐ ๋ณ์๋ก ๋ฆฌ๋ทฐ ๋ฌธ์์ด์ ๋ฐ์ (review) ์ด ๋ฆฌ๋ทฐ์ ๋ฒกํฐ ํํ์ ๋ฐํ
# ๋ฆฌ๋ทฐ ๋จ์ด์ ํด๋นํ๋ ์์น๊ฐ 1์ด ๋๋๋ก.
def vectorize(self, review):
""" ๋ฆฌ๋ทฐ์ ๋ํ ์-ํซ ๋ฒกํฐ๋ฅผ ๋ง๋ญ๋๋ค
๋งค๊ฐ๋ณ์:
review (str): ๋ฆฌ๋ทฐ
๋ฐํ๊ฐ:
one_hot (np.ndarray): ์-ํซ ๋ฒกํฐ
"""
one_hot = np.zeros(len(self.review_vocab), dtype=np.float32)
for token in review.split(" "):
if token not in string.punctuation:
one_hot[self.review_vocab.lookup_token(token)] = 1
return one_hot
# ๋ฐ์ฝ๋ ์ดํฐ๋ฅผ ์ฌ์ฉํ์ฌ from_dataframe()์ด Vectorizer ํด๋์ค๋ฅผ ์ด๊ธฐํํ๋ ์ง์
์ ์์ ๋ํ๋
# ํ๋ค์ค ๋ฐ์ดํฐํ๋ ์์ ์ํํ๋ฉด์ ์๋ ๋ ๊ฐ์ง ์์
์ ์ํ
# 1. ๋ฐ์ดํฐ์
์ ์๋ ๋ชจ๋ ํ ํฐ์ ๋น๋์ ์นด์ดํธ
# 2. ํค์๋ ๋งค๊ฐ๋ณ์ cutoff์ ์ง์ ํ ์๋ณด๋ค ๋น๋๊ฐ ๋์ ํ ํฐ๋ง ์ฌ์ฉํ๋ vocabulary ๊ฐ์ฒด ์์ฑ
# ์ต์ํ cutoff ํ์๋ณด๋ค ๋ง์ด ๋ฑ์ฅํ๋ ๋จ์ด๋ฅผ ๋ชจ๋ ์ฐพ์ vocabulary ๊ฐ์ฒด์ ์ถ๊ฐ
@classmethod
def from_dataframe(cls, review_df, cutoff=25):
""" ๋ฐ์ดํฐ์
๋ฐ์ดํฐํ๋ ์์์ Vectorizer ๊ฐ์ฒด๋ฅผ ๋ง๋ญ๋๋ค
๋งค๊ฐ๋ณ์:
review_df (pandas.DataFrame): ๋ฆฌ๋ทฐ ๋ฐ์ดํฐ์
cutoff (int): ๋น๋ ๊ธฐ๋ฐ ํํฐ๋ง ์ค์ ๊ฐ
๋ฐํ๊ฐ:
ReviewVectorizer ๊ฐ์ฒด
"""
review_vocab = Vocabulary(add_unk=True)
rating_vocab = Vocabulary(add_unk=False)
# ์ ์๋ฅผ ์ถ๊ฐํฉ๋๋ค
for rating in sorted(set(review_df.rating)):
rating_vocab.add_token(rating)
# count > cutoff์ธ ๋จ์ด๋ฅผ ์ถ๊ฐํฉ๋๋ค
word_counts = Counter()
for review in review_df.review:
for word in review.split(" "):
if word not in string.punctuation:
word_counts[word] += 1
for word, count in word_counts.items():
if count > cutoff:
review_vocab.add_token(word)
return cls(review_vocab, rating_vocab)
@classmethod
def from_serializable(cls, contents):
""" ์ง๋ ฌํ๋ ๋์
๋๋ฆฌ์์ ReviewVectorizer ๊ฐ์ฒด๋ฅผ ๋ง๋ญ๋๋ค
๋งค๊ฐ๋ณ์:
contents (dict): ์ง๋ ฌํ๋ ๋์
๋๋ฆฌ
๋ฐํ๊ฐ:
ReviewVectorizer ํด๋์ค ๊ฐ์ฒด
"""
review_vocab = Vocabulary.from_serializable(contents['review_vocab'])
rating_vocab = Vocabulary.from_serializable(contents['rating_vocab'])
return cls(review_vocab=review_vocab, rating_vocab=rating_vocab)
def to_serializable(self):
""" ์บ์ฑ์ ์ํด ์ง๋ ฌํ๋ ๋์
๋๋ฆฌ๋ฅผ ๋ง๋ญ๋๋ค
๋ฐํ๊ฐ:
contents (dict): ์ง๋ ฌํ๋ ๋์
๋๋ฆฌ
"""
return {'review_vocab': self.review_vocab.to_serializable(),
'rating_vocab': self.rating_vocab.to_serializable()}
- ํด๋น vectorize ๋ฉ์๋๋ฅผ ๋ณด๋ฉด ์ํซ๋ฐฑํฐ๋ก ํด๋น ๋จ์ด๊ฐ ํด๋นํ๋ ์์น์ 1์ด ๋๋ ๋ฒกํฐ๋ฅผ ๋ฐํํ๋ค.
- ํ์ง๋ง ์ด๋ฐ ํํ ๋ฐฉ๋ฒ์ ๋ช๊ฐ์ง ์ ์ฝ์ด ์กด์ฌํ๋ค.
- ํฌ์ํ ๋ฐฐ์ด์ด๋ผ๋ ์ ( ํ ๋ฆฌ๋ทฐ์ ๊ณ ์ ๋จ์ด ์๋ ํญ์ vocabulary ์ ์ฒด ๋จ์ด์ ๋ณด๋ค ํจ์ฌ ์๋ค.)
- ๋ฆฌ๋ทฐ์ ๋ฑ์ฅํ๋ ๋จ์ด ์์๋ฅผ ๋ฌด์ํ ๋ฐฉ๋ฒ์ด๋ค ( BoW ๋ฐฉ์)
1.2.3 DataLoader
- ๋ฒกํฐ๋ก ๋ณํํ๋ ๋ฏธ๋๋ฐฐ์น ํ์ดํ๋ผ์ธ์ ๋ง์ง๋ง ๋จ๊ณ๋ ๋ฒกํฐ๋ก ๋ณํํ ๋ฐ์ดํฐ ํฌ์ธํธ ๋ชจ์ผ๊ธฐ
- ํ์ดํ ์น ๋ด์ฅ ํด๋์ค์ธ DataLoader๋ ์ ๊ฒฝ๋ง์ ํ์์ ์ธ ๋ฏธ๋๋ฐฐ์น๋ก ๋ชจ์ผ๋ ์์ ์ ์ํํด์ค
- DataLoader ํด๋์ค๋ ํ์ดํ ์น DataSet(์ด ์์ ์์๋ ReviewDataset, batch_size ๋ฑ ๊ด๋ จํ ํค์๋๋ฅผ ๋งค๊ฐ๋ณ์๋ก ๋ฐ์
def generate_batches(dataset, batch_size, shuffle=True,
drop_last=True, device="cpu"):
"""
ํ์ดํ ์น DataLoader๋ฅผ ๊ฐ์ธ๊ณ ์๋ ์ ๋๋ ์ดํฐ ํจ์.
๊ฑฑ ํ
์๋ฅผ ์ง์ ๋ ์ฅ์น๋ก ์ด๋ํฉ๋๋ค.
"""
dataloader = DataLoader(dataset=dataset, batch_size=batch_size,
shuffle=shuffle, drop_last=drop_last)
for data_dict in dataloader:
out_data_dict = {}
for name, tensor in data_dict.items():
out_data_dict[name] = data_dict[name].to(device)
yield out_data_dict
<NEXT> https://didu-story.tistory.com/87
[NLP] ๋ ์คํ ๋ ๋ฆฌ๋ทฐ ๊ฐ์ฑ ๋ถ๋ฅํ๊ธฐ (3) (feat.ํ์ดํ ์น๋ก ๋ฐฐ์ฐ๋ ์์ฐ์ด ์ฒ๋ฆฌ) - ํ๋ จ ๋ฐ ํ๊ฐ, ์ถ๋ก ,
-- ๋ณธ ํฌ์คํ ์ ํ์ดํ ์น๋ก ๋ฐฐ์ฐ๋ ์์ฐ์ด ์ฒ๋ฆฌ (ํ๋น๋ฏธ๋์ด) ์ฑ ์ ์ฐธ๊ณ ํด์ ์์ฑ๋ ๊ธ์ ๋๋ค. -- ์์ค์ฝ๋ ) https://github.com/rickiepark/nlp-with-pytorch (ํ๋น๋ฏธ๋์ด, 2021)์ ์์ค ์ฝ๋๋ฅผ " data-og-des..
didu-story.tistory.com