이론과 구현이 다르다?

  • logistic regression의 이론 공부를 마치고 나면 아래와 같이 생각이 정리된다.
    • output layer에 softmax layer를 두어 weited sum 의 output을 prob 형태로 변경한다.
    • prob 형태로 나온 output에 대해 실제 정답분포와의 cross entropy loss 를 사용하여 loss를 계산한다.
  • 근데... pytorch로 구현할때는...
    • output layer 에 softmax를 취하지 않고 바로 CrossEntropyLoss 를 적용한다...

왜?

  • pytorch 의 CrossEntropyLoss 안에 Softmax (정확하게는 log_softmax) 가 구현되어 있기 때문이다.

왜 이렇게 구현이..???

  • softmax 함수를 취할때 exp 함수를 적용하며, cross entropy를 계산할때 다시 log를 취한다....
  • 그럼 원래대로 돌아온다...
  • 다시 원복될거 두번할 필요도 없을 뿐더러... 더 중요한 이유가 있는데,
  • softmax를 취하기 위해 exp 함수를 적용하면서 overflow 문제가 발생하는 것이 더 주된 이유이다.
    • exp 함수를 취할때 overflow가 발생하면 log를 취하더라도 이미 값은 유실된 후이다(..... 는 뻘소리였나...)
  • 그래서 softmax가 따로 구현되어있지 않는 것임. 자세한 건 여기를 참조
  • 다 집어치우고, softmax + CrossEntropyLoss 를 합쳐서 구현하면... forward / backward 구현이 개 쉬워진다. 더하기 빼기로 구현되어버림... (당연히 계산량이 엄청 줄어듦...) 이제 진짜 이유. (공신력 있는 자료를 참고하는 습관을 갖자...)

'pytorch' 카테고리의 다른 글

02. model(network) 구현하기  (0) 2020.10.03
01. DataSet  (0) 2020.09.28

Dataset

Dataset 사용 전 참고사항

  • CASE1. 훈련 데이터셋을 메모리에 다 들고 있을 정도로 여유가 있는 경우. (아래의 예제를 참조, Dataframe으로 데이터셋 전체를 들고 있는 방법)
  • CASE2. 메모리에 다 들고 있을 수 없을 만큼 데이터의 양이 많은 경우.
    • IterableDataset을 참조

Custom Dataset 생성 방법

  1. torch.util.data.Dataset을 상속
  2. len 함수 구현
    • 전체 데이터셋의 크기를 반환하도록 구현
  3. init 함수 구현
    • Datapoint의 변환메소드나 사전 / Tokenizer 등의 초기화 작업을 진행
  4. getitem 함수 구현
    • 객체[i] 형태처럼 index를 통해 특정 원소를 참조하기 위해 구현하는 함수
  5. iter 함수 구현 (IterableDataset 에서 필요)
    • for 문과 같은 iteration 에서 어떤 순서로 원소를 가져오는 지 구현하는 부분

Transformers 사용하기

  • 일반적으로 Dataset 의 초기화 과정에서는 원본 형태의 Datapoint를 들고 있으며, 이 Datapoint를 torch 의 네트워크에 주입해 주기 위해 Tensor 형태로 바꾸기 위한 일련의 작업 과정이 필요하다. 보통 이러한 데이터 변환을 담당하는 Class 들을 구현한 후 이들의 객체를 리스트로 담아 Dataset의 초기화 인자로 넘겨주어 Dataset에서 리턴하는 모든 datapoint가 동일하게 변환과정을 거치도록 구현한다.

  • 텍스트의 경우, tokenizing / padding / index변환 등의 변환 과정이 구현된 객체가 transformers 인자로 전달된다.

  • 일반적으로 transformer의 마지막 step은 torch 의 Tensor로 변환하는 과정이다.

    class ToIdxTransform(object):
      def __init__(self, vocab_path, max_seq_length = 30, unk_tok = '[UNK]', pad_tok = '[PAD]'):
          with codecs.open(vocab_path, 'r', 'utf-8') as fin:
              chars = [i.strip('\n') for i in fin.readlines() if i.strip()]
    
          self.chars = chars
          self.idx_map = dict(zip(self.chars, range(len(self.chars))))
          self.max_seq_length = max_seq_length
    
          self.unk_tok = unk_tok
          self.pad_tok = pad_tok
    
          assert self.unk_tok in self.idx_map
          assert self.pad_tok in self.idx_map
    
          self.unk_idx = self.idx_map[self.unk_tok]
          self.pad_idx = self.idx_map[self.pad_tok]
    
      def __call__(self, dp):
          d = dp['document']
          char_ids = [self.idx_map.get(c, self.unk_idx) for c in d][:self.max_seq_length]
          char_ids.extend([self.pad_idx] * (self.max_seq_length - len(char_ids)))
    
          dp['document'] = char_ids
          return dp

Custom Dataset 의 구현 예시

class CharacterSequenceDataset(Dataset):
    def __init__(self, df, transformers=None):
        self.df = df
        self.labels = df['label'].map(lambda x : int(x)).to_list()
        self.titles = df['title'].map(lambda x : str(x)).to_list()
        self.transformers = transformers

        assert len(self.labels) == len(self.titles)

    def __len__(self):
        return len(self.labels)

    def __getitem__(self, idx):
        # Data point
        dp = OrderedDict( {
            'label' : self.labels[idx],
            'title' : self.titles[idx]
        })

        if self.transformers is not None:
            for transformer in self.transformers:
                dp = transformer(dp)

        return dp

'pytorch' 카테고리의 다른 글

02. model(network) 구현하기  (0) 2020.10.03
CrossEntropyLoss in pytorch (feat. log_softmax, nll_loss)  (0) 2020.09.30

Overview

  • 이 포스팅은 마크다운 문법 실습용 포스팅임.
  • 여기 를 참조하여 작성하였음.
  • 아래와 같은 효과를 어떻게 작성하는지 궁금하다면 위 링크를 참조.

제목 단계별 글씨 크기 예시입니다.

제목1

제목 2

제목 3

제목 4

제목 5
제목 6

이것은 강조하기 예시 입니다.

이탤릭체
두껍게

취소하기

밑줄긋기


이것은 리스트 형태의 항목 나열 예시 입니다.

  1. 첫번째
  2. 두번째
    • 설명1
    • 설명2
  3. 세번째
    1. 세번째_첫번째
    2. 세번째_두번째
  4. 네번째
  • 번호 붙이기 끝

링크 삽입하기 예시 입니다.

NAVER

꺽쇠를 사용하여 링크로 변환합니다. http://www.naver.com

이렇게 아래 참조링크도 사용이 가능합니다. 참조1 로 이동.


이미지 삽입하기 예시 입니다.

  • 쿠팡 이미지 입니다.
    쿠팡로고

코드삽입 예시 입니다. (파이썬 코드 예시)

import codecs
def main():
    print('hello world!')
if __name__ == "__main__":
    main()

표삽입 예시 입니다.

======

이름 나이
dan 37 192.32
novister 33 203.1
woney 31 184.92

의미 기본값
static 유형(기준) 없음 / 배치 불가능 static
relative 요소 자신을 기준으로 배치
absolute 위치 상 부모(조상)요소를 기준으로 배치
fixed 브라우저 창을 기준으로 배치

줄바꿈 예시입니다.

동해물과
백두산이
마르고
닳도록
하느님이
보우하사

우리나라만세

+ Recent posts