개발자의시작

Natural Language Processing with PyTorch 정리 3-3 본문

자연어처리

Natural Language Processing with PyTorch 정리 3-3

LNLP 2020. 6. 10. 18:59

이 글은 Natural Language Processing with Pytorch 강의자료를 번역 및 정리해놓은 글입니다.

 

강의 자료 및 코드 링크 :

https://github.com/dlsucomet/MLResources/blob/master/books/%5BNLP%5D%20Natural%20Language%20Processing%20with%20PyTorch%20(2019).pdf

 

dlsucomet/MLResources

Repository for Machine Learning resources, frameworks, and projects. Managed by the DLSU Machine Learning Group. - dlsucomet/MLResources

github.com

 

Example: Classifying Sentiment of Restaurant Reviews

앞 절에서 우리는 장난감 예시를 가지고 지도학습에 대해 살펴봤고 많은 기본적인 개념들을 설명했다. 이 섹션에서는 이 과정을 반복하지만 이번에는 실제 작업과 데이터 세트를 통해 Yelp에 대한 레스토랑 리뷰가 긍정적이거나 부정적이거나를 퍼셉트론과 지도학습을 사용하여 분류한다. 이것은 이 책의 첫 번째 완전한 NLP 예시이기 때문에, 매우 상세하게 보조 데이터 구조와 훈련 루틴을 설명한다. 이후의 장의 예는 매우 유사한 패턴을 따를 것이므로, 이 절과 함께 주의 깊게 따르고 필요한 경우 다시 참조할 것을 권장한다.

 

이 자료의 각 예제를 시작할 때, 우리가 사용하고 있는 데이터셋을 설명한다. 이 예에서는 긍정 또는 부정의 레이블을 포함하는 리뷰 데이터 쌍 집합을 사용한다. 또한 데이터셋을 다듬고 학습, 검증, 평가 데이터 세트로 분할하기 위해 수행한 몇 가지 데이터셋 조작에 대해 설명한다.

 

데이터 집합을 이해한 후 이 책 전반에 걸쳐 반복되며 텍스트 데이터를 벡터화된 형태인 어휘로 변환하는 Vocabulary, Vectorizer, DataLoader 클래스를 정의하는 패턴을 볼 수 있다. Vocabulary 는 Observation and Target Encoding 에서 논의한 integer-to-token 매핑을 조정한다. 우리는 텍스트 토큰을 정수에 매핑하는 것과 클래스 레이블을 정수에 매핑하는 데 모두 Vectorizer를 사용한다. 다음으로 Vectorizer는 어휘를 캡슐화하여 리뷰의 텍스트처럼 문자열 데이터를 수집하고 훈련 루틴에서 사용될 숫자 벡터로 변환하는 역할을 담당한다. 최종 보조 클래스인 PyTorch의 DataLoader를 사용하여 개별 벡터화된 데이터 포인트를 그룹화하고 미니배치(minibatch)로 결합한다. 

 

다음 절에서는 퍼셉트론 분류기와 훈련 루틴을 설명한다. 훈련 루틴은 이 책 모든 예에 대해 대부분 동일하게 유지되지만, 이 절에서 좀 더 자세히 논의하기 때문에, 다시 한번 이 예를 향후 훈련 루틴에 대한 참고 자료로 활용할 것을 권한다. 우리는 그 결과에 대해 토론하고 그 모델이 무엇을 배웠는지 알아보기 위해 들여다본다.

 

 

The Yelp Review Dataset

2015년 옐프는 식당의 평점을 예측해 달라고 참가자들에게 요청하는 콘테스트를 열었다. 장, 자오, 레쿤(2015년)은 1, 2성 등급을 '부정' 감정 등급, 3, 4성 등급을 '긍정' 감정 등급으로 전환해 데이터 집합을 단순화한 뒤 훈련 표본 56만 개와 시험 표본 38,000개로 나눴다. 이 예에서는 두 가지 사소한 차이가 있는 단순화된 Yelp 데이터 집합을 사용한다. 이 섹션의 나머지 부분에서는 데이터를 최소화하고 최종 데이터 집합을 도출하는 프로세스에 대해 설명한다. 그런 다음 PyTorch의 Dataset 클래스를 활용하는 구현에 대해 개략적으로 설명한다.

 

첫 번째로 언급된 차이점 중 하나는 교육용 샘플의 10%를 전체 데이터 세트로 선택하여 도출한 데이터 세트의 "light" 버전을 사용한다는 것이다. 이것은 두 가지 결과를 낳는다. 첫째, 작은 데이터 집합을 사용하면 교육-테스트 루프가 빨라져 신속하게 실험할 수 있다. 둘째, 모든 데이터를 사용함으로써 얻을 수 있는 것보다 낮은 정확도의 모델을 생산한다. 작은 부분 집합에서 얻은 지식을 사용하여 전체 데이터 집합을 재교육할 수 있기 때문에 이 낮은 정확도는 보통 큰 문제가 아니다. 이것은 많은 상황에서 훈련 데이터의 양이 엄청날 수 있는 딥러닝 모델을 훈련하는 데 있어 매우 유용한 속임수다.

 

이 작은 부분 집합에서 데이터 집합을 세 개의 파티션으로 나누었는데, 하나는 학습용, 다른 하나는 검증용, 다른 하나는 테스트용이었습니다. 원래 데이터 세트는 파티션이 두 개뿐이지만 검증 세트가 중요하다. 머신러닝(machine learning)에서는 데이터 세트의 교육 파티션에서 모델을 교육하고 모델이 얼마나 잘 수행되었는지를 평가하기 위해 홀드 아웃 파티션이 필요한 경우가 많다. 모델 결정이 보류된 부분에 기초한다면, 모델은 보류된 부분에서 더 나은 성과를 내는 쪽으로 편향될 수밖에 없다. 점진적 진행률 측정이 필수적이기 때문에, 이 문제의 해결책은 가능한 한 평가에 거의 사용되지 않는 세 번째 칸막이를 갖는 것이다.

 

요약하자면, 모델 매개변수를 도출하기 위해 데이터 집합의 교육 파티션을 사용해야 하며, 하이퍼 파라미터 중에서 선택할 데이터 집합의 검증 파티션(모델링 결정) 및 최종 평가 및 보고를 위한 데이터 집합의 테스트 파티션을 사용해야 한다. 예제 3-12에서는 데이터 집합을 분할하는 방법을 보여 준다. 랜덤 시드는 정적 숫자로 설정되며, 클래스 분포를 보장하기 위해 클래스 레이블별로 먼저 집계한다는 점에 유의하십시오.

 

Yelp dataset

Yelp dataset

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import collections
import numpy as np
import pandas as pd
import re
 
from argparse import Namespace
 
 
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
)
 
# Read raw data
train_reviews = pd.read_csv(args.raw_train_dataset_csv, header=None, names=['rating''review'])
 

print(train_reviews)

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# making the subset equal across the review classes
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)
 

print(review_subset)

 

train_reviews.rating.value_counts()

2        280000

1        280000

 

review_subset.rating.value_counts()

2        28000

1        28000

 

set(review_subset.rating)

{1, 2}

 

example 3-12 Creating training, validation, and testing splits

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
 
# Splitting the subset by rating to create our new train, val, and test splits
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)
    
    # Give data point a split attribute
    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'
 
    # Add to final list
    final_list.extend(item_list)
 
 

 

 

 

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
 
# Create split data
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)
    
    # Give data point a split attribute
    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'
 
    # Add to final list
    final_list.extend(item_list)
final_reviews = pd.DataFrame(final_list)
`cs

final_reviews.split.value_counts()

train        39200

test         8400

val          8400

Name: split, dtype: int64

 

 

학습, 검증 및 테스트를 위해 세 개의 파티션이 있는 서브셋을 만드는 것 외에도, 우리는 예시 3-13과 같이 문장 부호 주위에 공백을 추가하고 모든 분할에 문장 부호가 아닌 외부 기호를 제거하여 데이터를 최소한으로 청소(전처리)한다.

 

example 3-13 Minimally cleaning the data

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Preprocess the reviews
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)
 
 

 

print(final_revies.head())

 

Understanding PyTorch’s Dataset Representation

 

예제 3-14에 제시된 ReviewDataset 클래스는 최소로 정리되고 세 개의 파티션으로 분할된 데이터 집합을 가정한다. 특히 데이터 세트는 리뷰에서 토큰 리스트를 얻기 위해 공백에 따라 리뷰를 분할할 수 있다고 가정한다. 또한, 데이터에는 데이터 분할이 속하는 주석이 있다고 가정한다. Python의 classmethod decorator를 사용하여 이 데이터 집합 클래스에 대한 진입점 방법을 표시한다는 점에 유의하십시오. 우리는 이 패턴을 따라 책을 읽는다.

 

PyTorch는 Dataset 클래스를 제공함으로써 데이터 집합에 대한 추상화를 제공한다. Dataset 클래스는 추상 반복기입니다. 새 데이터 집합과 함께 PyTorch를 사용할 때는 먼저 데이터 집합 클래스를 하위 클래스(또는 데이터 집합에서 상속)하고 이러한 _getitem__() 및 _len_() 메서드를 구현해야 한다. 이 예에서는 PyTorch의 Dataset 클래스에서 상속되는 ReviewDataset 클래스를 생성하여 __getitem_____len__의 두 가지 방법을 구현한다.

 

이것은 다양한 PyTorch 유틸리티가 우리의 데이터 세트와 함께 작동할 수 있도록 하는 개념적인 협약을 만든다. 다음 섹션에서는 이러한 유틸리티 중 특히 DataLoader에 대해 다룹니다. 이어지는 구현은 ReviewVectorizer라는 클래스에 크게 의존한다. 다음 절에서는 ReviewVectorizer를 설명하지만, 직관적으로 검토 텍스트에서 검토를 나타내는 숫자 벡터로의 변환을 처리하는 클래스로 그려볼 수 있다. 어떤 벡터화 단계를 통해서만 신경 네트워크가 텍스트 데이터와 상호작용을 할 수 있다. 전체적인 설계 패턴은 하나의 데이터 포인트에 대해 벡터화 로직을 처리하는 데이터 집합 클래스를 구현하는 것이다. 그런 다음 PyTorch의 DataLoader(다음 절에서도 설명됨)는 데이터 집합에서 샘플링 및 데이터 정렬을 통해 미니 배치를 생성한다.

 

example 3-15. A PyTorch Dataset class for the Yelp Review dataset

 

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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
from torch.utils.data import Dataset
 
class ReviewDataset(Dataset):
    def __init__(self, review_df, vectorizer):
    """
    Args:
        review_df (pandas.DataFrame): the dataset    
        vectorizer (ReviewVectorizer): vectorizer instantiated from dataset
    """
 
    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')
 
@classmethod
def load_dataset_and_make_vectorizer(cls, review_csv):
    """Load dataset and make a new vectorizer from scratch
 
    Args:
        review_csv (str): location of the dataset    
    Returns:
    an instance of ReviewDataset    
    """
    review_df = pd.read_csv(review_csv)
    return cls(review_df, ReviewVectorizer.from_dataframe(review_df))
 
def get_vectorizer(self):
    """ returns the vectorizer """
    return self._vectorizer
 
 
def set_split(self, split="train"):
    """ selects the splits in the dataset using a column in the dataframe
    Args:
        split (str): one of "    train", "val", or "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):
    """the primary entry point method for PyTorch datasets
    Args:
        index (int): the index to the data point    
        Returns:    
        a dict of the data point's features (x_data) and label (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):
    """Given a batch size, return the number of batches in the dataset
    Args:
        batch_size (int)
        Returns:    
        number of batches in the dataset
    """
    return len(self) // batch_size
 
 
 
 
 

 

The Vocabulary, the Vectorizer, and the DataLoader

 

Vocabulary, Vectorizer, DataLoader는 이 자료 거의 모든 예에서 중요한 파이프라인을 수행하기 위해 사용하는 세 가지 클래스이다. 텍스트 입력을 벡터화된 미니 배치로 변환하는 것이다.

 

파이프라인은 사전 처리된 텍스트로 시작하며, 각 데이터 포인트는 토큰의 모음이다. 이 예에서 토큰은 단어 일 수 있지만, 4장과 6중에서 볼 수 있듯이 문자도 토큰이 될 수 있다. 다음 하위 섹션에 제시된 세 가지 클래스는 각 토큰을 정수에 매핑하고, 이 매핑을 각 데이터 포인트에 적용하여 벡터화된 형태를 만든 다음, 벡터화된 데이터 포인트를 모델의 미니배치로 그룹화하는 역할을 담당한다.

 

VOCABULARY

 

텍스트에서 벡터화된 미니배치로 가는 첫 번째 단계는 각각의 토큰을 그 자체의 숫자 버전에 매핑하는 것이다. 표준 방법론은 토큰과 정수 사이의 편향(반복될 수 있는 매핑)을 갖는 것이다. Python에서 이것은 단순히 두 개의 사전이다. 우리는 3-15 와 같이 캡슐화한다.

 

 

Example 3-15 The Vocabulary class maintains token to integer mapping needed for the rest of the machine learning pipeline

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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
class Vocabulary(object):
    """Class to process text and extract Vocabulary for mapping"""
    def __init__(self, token_to_idx=None, add_unk=True, unk_token="<UNK>"):
    """
    Args:
        token_to_idx (dict): a preexisting
        map of tokens to indices
        add_unk (bool): a flag that indicates whether to add the UNK token
        unk_token (str): the UNK token to add into the Vocabulary    
    """
    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):
    """ returns a dictionary that can be serialized """
        return {'token_to_idx': self._token_to_idx, 'add_unk': self._add_unk,'unk_token': self._unk_token}
 
    @classmethod
    def from_serializable(cls, contents):
        """ instantiates the Vocabulary from a serialized dictionary """
        return cls(**contents)
    
    def add_token(self, token):
        """Update mapping dicts based on the token.
        Args:
            token (str): the item to add into the Vocabulary
            Returns:
            index (int): the integer corresponding to the token
        """
        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 lookup_token(self, token):
        """Retrieve the index associated with the token
        or the UNK index if token isn't present.
        Args:
            token (str): the token to look up
            Returns:
            index (int): the index corresponding to the token
            Notes:
            `unk_index` needs to be >=0 (having been added into the Vocabulary)
            for the UNK functionality
        """
 
        if self.add_unk:
            return self._token_to_idx.get(token, self.unk_index)
        else:
            return self._token_to_idx[token]
 
 
    def lookup_index(self, index):
        """Return the token associated with the index
        Args:
            index (int): the index to look up        
            Returns:
            token (str): the token corresponding to the index
        Raises:
            KeyError: if the index is not in the Vocabulary
        """
 
        if index not in self._idx_to_token:
            raise KeyError("the index (%d) is not in the Vocabulary" % 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)
 
 

 

Vectorizer

 

텍스트 데이터 집합에서 벡터화된 미니 배치로 이동하는 두 번째 단계는 입력 데이터 포인트의 토큰을 통해 반복하고 각 토큰을 정수 형태로 변환하는 것이다. 이 반복의 결과는 벡터가 되어야 한다. 이 벡터는 다른 데이터 포인트의 벡터와 결합되기 때문에 벡터라이저에 의해 생성된 벡터의 길이가 항상 같아야 한다는 제약이 있다. 이러한 목표를 달성하기 위해 벡터라이저 클래스는 리뷰 어휘를 캡슐화하여 리뷰의 단어를 정수에 매핑한다. example 3-16에서 벡터라이저는 파이썬의 @classmethod decorator를 from_dataframe()의 방법에 활용하여 벡터라이저를 인스턴스화 하는 진입점을 나타낸다. from_datafram()의 방법은 두 가지 목표를 가지고 Pandas의 DataFrame의 행에 반복된다. 첫 번째 목표는 데이터 집합에 존재하는 모든 토큰의 빈도를 세는 것이다. 두 번째 목표는 제공된 키워드 인수만큼 빈번한 토큰만 사용하는 "Vocabulary"를 만드는 것이다. 효과적으로, 이 방법은 적어도 컷오프 타임에 발생하는 모든 단어를 찾아 어휘에 추가하는 것이다. UNK 토큰도 어휘에 추가되기 때문에 어휘의 lookup_token() 메서드가 호출될 때 추가되지 않은 모든 단어는 unk_index를 갖게 된다.

 

Vectorize() 메서드는 벡터라이저의 핵심 기능을 캡슐화한다. 그것은 리뷰를 나타내는 문자열을 논쟁으로 삼고, 리뷰의 벡터화된 표현을 반환한다. 이 예에서는 1장에서 소개한 one-hot 표현을 사용한다. 이 표현은 어휘의 크기와 같은 길이를 가진 0과 1의 벡터인 이진 벡터를 만든다. 이진 벡터는 리뷰의 단어에 해당하는 위치에 1이 있다. 이 표현에는 몇 가지 한계가 있다는 점에 유의해야 한다. 첫째는 그것이 희소하다는 것이다. 리뷰의 고유 단어 수는 항상 어휘의 고유 단어 수 보다 훨씬 적을 것이다. 두 번째는 리뷰에 나타난 순서를 무시하는 것이다(bag-of-words) 다음 장에서는 이러한 제한이 없는 다른 방법을 볼 수 있다.

 

Example 3-16. The Vectorizer class converts text to numeric vectors

 

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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
class ReviewVectorizer(object):
    """ The Vectorizer which coordinates the Vocabularies and puts them to use"""
    def __init__(self, review_vocab, rating_vocab):
        """
        Args:
            review_vocab (Vocabulary): maps words to integers
            rating_vocab (Vocabulary): maps class labels to integers
        """
        self.review_vocab = review_vocab
        self.rating_vocab = rating_vocab
 
    def vectorize(self, review):
        """Create a collapsed onehit vector for the review
        Args:
            review (str): the review
        Returns:
            one_hot (np.ndarray): the collapsed onehotencoding 
        """
        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
 
    @classmethod
    def from_dataframe(cls, review_df, cutoff=25):
        """Instantiate the vectorizer from the dataset dataframe
        Args:
            review_df (pandas.DataFrame): the review dataset
            cutoff (int): the parameter for frequencybasedfiltering 
        Returns:
            an instance of the ReviewVectorizer    
        """
        review_vocab = Vocabulary(add_unk=True)
        rating_vocab = Vocabulary(add_unk=False)
 
        # Add ratings
        for rating in sorted(set(review_df.rating)):
            rating_vocab.add_token(rating)
 
        # Add top words if count > provided count
        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):
        """Intantiate a ReviewVectorizer from a serializable dictionary
            Args:    
                contents (dict): the serializable dictionary    
            Returns:    
                an instance of the ReviewVectorizer class
        """
        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):
        """Create the serializable dictionary for caching
 
        Returns:
            contents (dict): the serializable dictionary    
        """
        return {'review_vocab': self.review_vocab.to_serializable(),
            'rating_vocab': self.rating_vocab.to_serializable()}
cs

 

DATALOADER

 

텍스트-벡터-미니배치치 파이프라인의 마지막 단계는 실제로 벡터화된 데이터 포인트를 그룹화하는 것이다. 미니 배치로 그룹화하는 것은 신경망 훈련의 필수적인 부분이기 때문에, PyTorch는 과정을 조정하기 위해 DataLoader라고 불리는 빌트인 클래스를 제공한다. DataLoader 클래스는 PyTorch 데이터 집합(예: 이 예에 대해 정의된 ReviewDataset), batch_size 및 소수의 기타 키워드 인수를 제공하여 인스턴스화 된다. 결과 개체는 데이터 집합에 제공된 데이터 포인트를 그룹화하고 결합하는 Python 반복기입니다. 예제 3-17에서는 DataLoader를 generate_batches() 함수로 포장하는데, 이 함수는 CPU와 GPU 간에 데이터를 편리하게 전환할 수 있는 생성기다.

 

Example 3-17. Generating minibatches from a dataset

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def generate_batches(dataset, batch_size, shuffle=True,drop_last=True, device="cpu"):
    """
        A generator function which wraps the PyTorch DataLoader. It will
        ensure each tensor is on the write device location.
    """
    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
 
 

 

 

 

Comments