-- λ³Έ ν¬μ€ν
μ νμ΄ν μΉλ‘ λ°°μ°λ μμ°μ΄ μ²λ¦¬ (νλΉλ―Έλμ΄) μ±
μ μ°Έκ³ ν΄μ μμ±λ κΈμ
λλ€.
-- μμ€μ½λ ) https://github.com/rickiepark/nlp-with-pytorch
βΆ λ μ€ν λ 리뷰 κ°μ± λΆλ₯νκΈ°
μλ ν¬μ€ν μμ μ΄λ»κ² μ μ²λ¦¬λ λ°μ΄ν°λ₯Ό μ¬μ©νκ² λλμ§ λ―Έλ¦¬ νμ΅νλ©΄ μ’μ κ²μ΄λ€. νμ§λ§ ν΄λΉ μ½λμμλ 'μ μ²λ¦¬ κ³Όμ 'μ΄ μλ΅λ 'μ μ²λ¦¬ λμ΄μ§ λ°μ΄ν°'λ₯Ό νμ©νκ³ μλ€λ κ²λ§ μμλμ.
https://didu-story.tistory.com/83
1. νμ΄ν μΉ λ°μ΄ν°μ μ΄ν΄νκΈ°
ν΄λΉ νλ‘μ νΈλ pytorch νλ μμν¬λ₯Ό κΈ°λ°μΌλ‘ μ§νλλ€. κ·Έλ¦¬κ³ ν΄λμ€ κ°μ²΄λ₯Ό νμ©ν΄μ μ£Όμν νμ΄νλΌμΈμ μννκ² λλ€. νμ΄μ¬μ ν΄λμ€κ°μ²΄μ λν μ΄ν΄κ° λΆμ‘±νλ€λ©΄ μλ ν¬μ€ν μ μ°Έκ³ νκ³ μ΄ν΄νκ³ μ€μ. λν νμ΄ν μΉλ Dataset, DataLoader λ₯Ό νμ©νμ¬ λ°μ΄ν°μ ννλ₯Ό λ³νμμΌμ£Όλλ°, μ΄μλν κ²λ μλ ν¬μ€ν μ μ°Έκ³ νλ©΄ μ΄ν΄κ° λ μ¬μΈ κ²μ΄λ€.
https://didu-story.tistory.com/85
https://didu-story.tistory.com/84
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