🚴‍♂️
TIL
  • MAIN
  • : TIL?
  • : WIL
  • : Plan
  • : Retrospective
    • 21Y
      • Wait a moment!
      • 9M 2W
      • 9M1W
      • 8M4W
      • 8M3W
      • 8M2W
      • 8M1W
      • 7M4W
      • 7M3W
      • 7M2W
      • 7M1W
      • 6M5W
      • 1H
    • 새사람 되기 프로젝트
      • 2회차
      • 1회차
  • TIL : ML
    • Paper Analysis
      • BERT
      • Transformer
    • Boostcamp 2st
      • [S]Data Viz
        • (4-3) Seaborn 심화
        • (4-2) Seaborn 기초
        • (4-1) Seaborn 소개
        • (3-4) More Tips
        • (3-3) Facet 사용하기
        • (3-2) Color 사용하기
        • (3-1) Text 사용하기
        • (2-3) Scatter Plot 사용하기
        • (2-2) Line Plot 사용하기
        • (2-1) Bar Plot 사용하기
        • (1-3) Python과 Matplotlib
        • (1-2) 시각화의 요소
        • (1-1) Welcome to Visualization (OT)
      • [P]MRC
        • (2강) Extraction-based MRC
        • (1강) MRC Intro & Python Basics
      • [P]KLUE
        • (5강) BERT 기반 단일 문장 분류 모델 학습
        • (4강) 한국어 BERT 언어 모델 학습
        • [NLP] 문장 내 개체간 관계 추출
        • (3강) BERT 언어모델 소개
        • (2강) 자연어의 전처리
        • (1강) 인공지능과 자연어 처리
      • [U]Stage-CV
      • [U]Stage-NLP
        • 7W Retrospective
        • (10강) Advanced Self-supervised Pre-training Models
        • (09강) Self-supervised Pre-training Models
        • (08강) Transformer (2)
        • (07강) Transformer (1)
        • 6W Retrospective
        • (06강) Beam Search and BLEU score
        • (05강) Sequence to Sequence with Attention
        • (04강) LSTM and GRU
        • (03강) Recurrent Neural Network and Language Modeling
        • (02강) Word Embedding
        • (01강) Intro to NLP, Bag-of-Words
        • [필수 과제 4] Preprocessing for NMT Model
        • [필수 과제 3] Subword-level Language Model
        • [필수 과제2] RNN-based Language Model
        • [선택 과제] BERT Fine-tuning with transformers
        • [필수 과제] Data Preprocessing
      • Mask Wear Image Classification
        • 5W Retrospective
        • Report_Level1_6
        • Performance | Review
        • DAY 11 : HardVoting | MultiLabelClassification
        • DAY 10 : Cutmix
        • DAY 9 : Loss Function
        • DAY 8 : Baseline
        • DAY 7 : Class Imbalance | Stratification
        • DAY 6 : Error Fix
        • DAY 5 : Facenet | Save
        • DAY 4 : VIT | F1_Loss | LrScheduler
        • DAY 3 : DataSet/Lodaer | EfficientNet
        • DAY 2 : Labeling
        • DAY 1 : EDA
        • 2_EDA Analysis
      • [P]Stage-1
        • 4W Retrospective
        • (10강) Experiment Toolkits & Tips
        • (9강) Ensemble
        • (8강) Training & Inference 2
        • (7강) Training & Inference 1
        • (6강) Model 2
        • (5강) Model 1
        • (4강) Data Generation
        • (3강) Dataset
        • (2강) Image Classification & EDA
        • (1강) Competition with AI Stages!
      • [U]Stage-3
        • 3W Retrospective
        • PyTorch
          • (10강) PyTorch Troubleshooting
          • (09강) Hyperparameter Tuning
          • (08강) Multi-GPU 학습
          • (07강) Monitoring tools for PyTorch
          • (06강) 모델 불러오기
          • (05강) Dataset & Dataloader
          • (04강) AutoGrad & Optimizer
          • (03강) PyTorch 프로젝트 구조 이해하기
          • (02강) PyTorch Basics
          • (01강) Introduction to PyTorch
      • [U]Stage-2
        • 2W Retrospective
        • DL Basic
          • (10강) Generative Models 2
          • (09강) Generative Models 1
          • (08강) Sequential Models - Transformer
          • (07강) Sequential Models - RNN
          • (06강) Computer Vision Applications
          • (05강) Modern CNN - 1x1 convolution의 중요성
          • (04강) Convolution은 무엇인가?
          • (03강) Optimization
          • (02강) 뉴럴 네트워크 - MLP (Multi-Layer Perceptron)
          • (01강) 딥러닝 기본 용어 설명 - Historical Review
        • Assignment
          • [필수 과제] Multi-headed Attention Assignment
          • [필수 과제] LSTM Assignment
          • [필수 과제] CNN Assignment
          • [필수 과제] Optimization Assignment
          • [필수 과제] MLP Assignment
      • [U]Stage-1
        • 1W Retrospective
        • AI Math
          • (AI Math 10강) RNN 첫걸음
          • (AI Math 9강) CNN 첫걸음
          • (AI Math 8강) 베이즈 통계학 맛보기
          • (AI Math 7강) 통계학 맛보기
          • (AI Math 6강) 확률론 맛보기
          • (AI Math 5강) 딥러닝 학습방법 이해하기
          • (AI Math 4강) 경사하강법 - 매운맛
          • (AI Math 3강) 경사하강법 - 순한맛
          • (AI Math 2강) 행렬이 뭐예요?
          • (AI Math 1강) 벡터가 뭐예요?
        • Python
          • (Python 7-2강) pandas II
          • (Python 7-1강) pandas I
          • (Python 6강) numpy
          • (Python 5-2강) Python data handling
          • (Python 5-1강) File / Exception / Log Handling
          • (Python 4-2강) Module and Project
          • (Python 4-1강) Python Object Oriented Programming
          • (Python 3-2강) Pythonic code
          • (Python 3-1강) Python Data Structure
          • (Python 2-4강) String and advanced function concept
          • (Python 2-3강) Conditionals and Loops
          • (Python 2-2강) Function and Console I/O
          • (Python 2-1강) Variables
          • (Python 1-3강) 파이썬 코딩 환경
          • (Python 1-2강) 파이썬 개요
          • (Python 1-1강) Basic computer class for newbies
        • Assignment
          • [선택 과제 3] Maximum Likelihood Estimate
          • [선택 과제 2] Backpropagation
          • [선택 과제 1] Gradient Descent
          • [필수 과제 5] Morsecode
          • [필수 과제 4] Baseball
          • [필수 과제 3] Text Processing 2
          • [필수 과제 2] Text Processing 1
          • [필수 과제 1] Basic Math
    • 딥러닝 CNN 완벽 가이드 - Fundamental 편
      • 종합 실습 2 - 캐글 Plant Pathology(나무잎 병 진단) 경연 대회
      • 종합 실습 1 - 120종의 Dog Breed Identification 모델 최적화
      • 사전 훈련 모델의 미세 조정 학습과 다양한 Learning Rate Scheduler의 적용
      • Advanced CNN 모델 파헤치기 - ResNet 상세와 EfficientNet 개요
      • Advanced CNN 모델 파헤치기 - AlexNet, VGGNet, GoogLeNet
      • Albumentation을 이용한 Augmentation기법과 Keras Sequence 활용하기
      • 사전 훈련 CNN 모델의 활용과 Keras Generator 메커니즘 이해
      • 데이터 증강의 이해 - Keras ImageDataGenerator 활용
      • CNN 모델 구현 및 성능 향상 기본 기법 적용하기
    • AI School 1st
    • 현업 실무자에게 배우는 Kaggle 머신러닝 입문
    • 파이썬 딥러닝 파이토치
  • TIL : Python & Math
    • Do It! 장고+부트스트랩: 파이썬 웹개발의 정석
      • Relations - 다대다 관계
      • Relations - 다대일 관계
      • 템플릿 파일 모듈화 하기
      • TDD (Test Driven Development)
      • template tags & 조건문
      • 정적 파일(static files) & 미디어 파일(media files)
      • FBV (Function Based View)와 CBV (Class Based View)
      • Django 입문하기
      • 부트스트랩
      • 프론트엔드 기초다지기 (HTML, CSS, JS)
      • 들어가기 + 환경설정
    • Algorithm
      • Programmers
        • Level1
          • 소수 만들기
          • 숫자 문자열과 영단어
          • 자연수 뒤집어 배열로 만들기
          • 정수 내림차순으로 배치하기
          • 정수 제곱근 판별
          • 제일 작은 수 제거하기
          • 직사각형 별찍기
          • 짝수와 홀수
          • 체육복
          • 최대공약수와 최소공배수
          • 콜라츠 추측
          • 크레인 인형뽑기 게임
          • 키패드 누르기
          • 평균 구하기
          • 폰켓몬
          • 하샤드 수
          • 핸드폰 번호 가리기
          • 행렬의 덧셈
        • Level2
          • 숫자의 표현
          • 순위 검색
          • 수식 최대화
          • 소수 찾기
          • 소수 만들기
          • 삼각 달팽이
          • 문자열 압축
          • 메뉴 리뉴얼
          • 더 맵게
          • 땅따먹기
          • 멀쩡한 사각형
          • 괄호 회전하기
          • 괄호 변환
          • 구명보트
          • 기능 개발
          • 뉴스 클러스터링
          • 다리를 지나는 트럭
          • 다음 큰 숫자
          • 게임 맵 최단거리
          • 거리두기 확인하기
          • 가장 큰 정사각형 찾기
          • H-Index
          • JadenCase 문자열 만들기
          • N개의 최소공배수
          • N진수 게임
          • 가장 큰 수
          • 124 나라의 숫자
          • 2개 이하로 다른 비트
          • [3차] 파일명 정렬
          • [3차] 압축
          • 줄 서는 방법
          • [3차] 방금 그곡
          • 거리두기 확인하기
        • Level3
          • 매칭 점수
          • 외벽 점검
          • 기지국 설치
          • 숫자 게임
          • 110 옮기기
          • 광고 제거
          • 길 찾기 게임
          • 셔틀버스
          • 단속카메라
          • 표 편집
          • N-Queen
          • 징검다리 건너기
          • 최고의 집합
          • 합승 택시 요금
          • 거스름돈
          • 하노이의 탑
          • 멀리 뛰기
          • 모두 0으로 만들기
        • Level4
    • Head First Python
    • 데이터 분석을 위한 SQL
    • 단 두 장의 문서로 데이터 분석과 시각화 뽀개기
    • Linear Algebra(Khan Academy)
    • 인공지능을 위한 선형대수
    • Statistics110
  • TIL : etc
    • [따배런] Kubernetes
    • [따배런] Docker
      • 2. 도커 설치 실습 1 - 학습편(준비물/실습 유형 소개)
      • 1. 컨테이너와 도커의 이해 - 컨테이너를 쓰는이유 / 일반프로그램과 컨테이너프로그램의 차이점
      • 0. 드디어 찾아온 Docker 강의! 왕초보에서 도커 마스터로 - OT
    • CoinTrading
      • [가상 화폐 자동 매매 프로그램] 백테스팅 : 간단한 테스팅
    • Gatsby
      • 01 깃북 포기 선언
  • TIL : Project
    • Mask Wear Image Classification
    • Project. GARIGO
  • 2021 TIL
    • CHANGED
    • JUN
      • 30 Wed
      • 29 Tue
      • 28 Mon
      • 27 Sun
      • 26 Sat
      • 25 Fri
      • 24 Thu
      • 23 Wed
      • 22 Tue
      • 21 Mon
      • 20 Sun
      • 19 Sat
      • 18 Fri
      • 17 Thu
      • 16 Wed
      • 15 Tue
      • 14 Mon
      • 13 Sun
      • 12 Sat
      • 11 Fri
      • 10 Thu
      • 9 Wed
      • 8 Tue
      • 7 Mon
      • 6 Sun
      • 5 Sat
      • 4 Fri
      • 3 Thu
      • 2 Wed
      • 1 Tue
    • MAY
      • 31 Mon
      • 30 Sun
      • 29 Sat
      • 28 Fri
      • 27 Thu
      • 26 Wed
      • 25 Tue
      • 24 Mon
      • 23 Sun
      • 22 Sat
      • 21 Fri
      • 20 Thu
      • 19 Wed
      • 18 Tue
      • 17 Mon
      • 16 Sun
      • 15 Sat
      • 14 Fri
      • 13 Thu
      • 12 Wed
      • 11 Tue
      • 10 Mon
      • 9 Sun
      • 8 Sat
      • 7 Fri
      • 6 Thu
      • 5 Wed
      • 4 Tue
      • 3 Mon
      • 2 Sun
      • 1 Sat
    • APR
      • 30 Fri
      • 29 Thu
      • 28 Wed
      • 27 Tue
      • 26 Mon
      • 25 Sun
      • 24 Sat
      • 23 Fri
      • 22 Thu
      • 21 Wed
      • 20 Tue
      • 19 Mon
      • 18 Sun
      • 17 Sat
      • 16 Fri
      • 15 Thu
      • 14 Wed
      • 13 Tue
      • 12 Mon
      • 11 Sun
      • 10 Sat
      • 9 Fri
      • 8 Thu
      • 7 Wed
      • 6 Tue
      • 5 Mon
      • 4 Sun
      • 3 Sat
      • 2 Fri
      • 1 Thu
    • MAR
      • 31 Wed
      • 30 Tue
      • 29 Mon
      • 28 Sun
      • 27 Sat
      • 26 Fri
      • 25 Thu
      • 24 Wed
      • 23 Tue
      • 22 Mon
      • 21 Sun
      • 20 Sat
      • 19 Fri
      • 18 Thu
      • 17 Wed
      • 16 Tue
      • 15 Mon
      • 14 Sun
      • 13 Sat
      • 12 Fri
      • 11 Thu
      • 10 Wed
      • 9 Tue
      • 8 Mon
      • 7 Sun
      • 6 Sat
      • 5 Fri
      • 4 Thu
      • 3 Wed
      • 2 Tue
      • 1 Mon
    • FEB
      • 28 Sun
      • 27 Sat
      • 26 Fri
      • 25 Thu
      • 24 Wed
      • 23 Tue
      • 22 Mon
      • 21 Sun
      • 20 Sat
      • 19 Fri
      • 18 Thu
      • 17 Wed
      • 16 Tue
      • 15 Mon
      • 14 Sun
      • 13 Sat
      • 12 Fri
      • 11 Thu
      • 10 Wed
      • 9 Tue
      • 8 Mon
      • 7 Sun
      • 6 Sat
      • 5 Fri
      • 4 Thu
      • 3 Wed
      • 2 Tue
      • 1 Mon
    • JAN
      • 31 Sun
      • 30 Sat
      • 29 Fri
      • 28 Thu
      • 27 Wed
      • 26 Tue
      • 25 Mon
      • 24 Sun
      • 23 Sat
      • 22 Fri
      • 21 Thu
      • 20 Wed
      • 19 Tue
      • 18 Mon
      • 17 Sun
      • 16 Sat
      • 15 Fri
      • 14 Thu
      • 13 Wed
      • 12 Tue
      • 11 Mon
      • 10 Sun
      • 9 Sat
      • 8 Fri
      • 7 Thu
      • 6 Wed
      • 5 Tue
      • 4 Mon
      • 3 Sun
      • 2 Sat
      • 1 Fri
  • 2020 TIL
    • DEC
      • 31 Thu
      • 30 Wed
      • 29 Tue
      • 28 Mon
      • 27 Sun
      • 26 Sat
      • 25 Fri
      • 24 Thu
      • 23 Wed
      • 22 Tue
      • 21 Mon
      • 20 Sun
      • 19 Sat
      • 18 Fri
      • 17 Thu
      • 16 Wed
      • 15 Tue
      • 14 Mon
      • 13 Sun
      • 12 Sat
      • 11 Fri
      • 10 Thu
      • 9 Wed
      • 8 Tue
      • 7 Mon
      • 6 Sun
      • 5 Sat
      • 4 Fri
      • 3 Tue
      • 2 Wed
      • 1 Tue
    • NOV
      • 30 Mon
Powered by GitBook
On this page
  • 데이터 업로드
  • 1. 데이터 클래스 준비
  • Question
  • 2. 모델 아키텍처 준비
  • 3. 모델 학습

Was this helpful?

  1. TIL : ML
  2. Boostcamp 2st
  3. [U]Stage-NLP

[필수 과제2] RNN-based Language Model

210908

데이터 업로드

부스트코스에서 제공된 wikitext-2.zip 파일을 사용한다. 내부는 train.txt, valid.txt, test.txt 로 이루어져 있다.

path_train = './train.txt'
with open(path_train, 'r', encoding="utf8") as f:
    corpus_train = f.readlines()    

# train dataset 크기 확인
print(len(corpus_train))

# 처음 10 문장을 print 해 봅시다.
for sent in corpus_train[:10]:
    print(sent)
36718
 

 = Valkyria Chronicles III = 

 

 Senjō no Valkyria 3 : <unk> Chronicles ( Japanese : 戦場のヴァルキュリア3 , lit . Valkyria of the Battlefield 3 ) , commonly referred to as Valkyria Chronicles III outside Japan , is a tactical role @-@ playing video game developed by Sega and Media.Vision for the PlayStation Portable . Released in January 2011 in Japan , it is the third game in the Valkyria series . <unk> the same fusion of tactical and real @-@ time gameplay as its predecessors , the story runs parallel to the first game and follows the " Nameless " , a penal military unit serving the nation of Gallia during the Second Europan War who perform secret black operations and are pitted against the Imperial unit " <unk> Raven " . 

 The game began development in 2010 , carrying over a large portion of the work done on Valkyria Chronicles II . While it retained the standard features of the series , it also underwent multiple adjustments , such as making the game more <unk> for series newcomers . Character designer <unk> Honjou and composer Hitoshi Sakimoto both returned from previous entries , along with Valkyria Chronicles II director Takeshi Ozawa . A large team of writers handled the script . The game 's opening theme was sung by May 'n . 

 It met with positive sales in Japan , and was praised by both Japanese and western critics . After release , it received downloadable content , along with an expanded edition in November of that year . It was also adapted into manga and an original video animation series . Due to low sales of Valkyria Chronicles II , Valkyria Chronicles III was not localized , but a fan translation compatible with the game 's expanded edition was released in 2014 . Media.Vision would return to the franchise with the development of Valkyria : Azure Revolution for the PlayStation 4 . 

 

 = = Gameplay = = 

 

 As with previous <unk> Chronicles games , Valkyria Chronicles III is a tactical role @-@ playing game where players take control of a military unit and take part in missions against enemy forces . Stories are told through comic book @-@ like panels with animated character portraits , with characters speaking partially through voiced speech bubbles and partially through <unk> text . The player progresses through a series of linear missions , gradually unlocked as maps that can be freely <unk> through and replayed as they are unlocked . The route to each story location on the map varies depending on an individual player 's approach : when one option is selected , the other is sealed off to the player . Outside missions , the player characters rest in a camp , where units can be customized and character growth occurs . Alongside the main story missions are character @-@ specific sub missions relating to different squad members . After the game 's completion , additional episodes are unlocked , some of them having a higher difficulty than those found in the rest of the game . There are also love simulation elements related to the game 's two main <unk> , although they take a very minor role . 

1. 데이터 클래스 준비

라이브러리 임포트

import os
from io import open
import torch

Dictionary Class

class Dictionary(object):
    def __init__(self):
        self.word2idx = {}
        self.idx2word = []

    def add_word(self, word):
        if word not in self.word2idx:
            self.idx2word.append(word)
            self.word2idx[word] = len(self.idx2word) - 1
        return self.word2idx[word]

    def __len__(self):
        return len(self.idx2word)
  • word를 입력하면 index를, index를 입력하면 word를 받을 수 있도록 설정한다.

Corpus Class

class Corpus(object):
    def __init__(self, path):
        self.dictionary = Dictionary()
        self.train = self.tokenize(os.path.join(path, 'train.txt'))
        self.valid = self.tokenize(os.path.join(path, 'valid.txt'))
        self.test = self.tokenize(os.path.join(path, 'test.txt'))

    def tokenize(self, path):
        """Tokenizes a text file."""
        assert os.path.exists(path)
        # Add words to the dictionary
        with open(path, 'r', encoding="utf8") as f:
            for line in f:
                words = line.split() + ['<eos>']
                for word in words:
                    self.dictionary.add_word(word)

        # Tokenize file content
        with open(path, 'r', encoding="utf8") as f:
            idss = []
            for line in f:
                words = line.split() + ['<eos>']
                ids = []
                for word in words:
                    ids.append(self.dictionary.word2idx[word])
                idss.append(torch.tensor(ids).type(torch.int64))
            ids = torch.cat(idss)

        return ids
  • 말뭉치 클래스는 각 데이터들을 토크나이징 하고 이를 보캡에 추가한다.

  • 토크나이징 방식은 단순히 공백문자를 기준으로 나누며 각 줄에 마지막에는 eos 토큰을 추가한다. 그리고 각 단어들을 딕셔너리에 넣는다.

  • 이후, vocab을 참조해서 각 문장의 단어를 인덱스화 해서 저장한다. 이들은 학습에 사용할 것이므로 torch.tensor 로 캐스팅해준다.

# corpus 확인
path = './'
corpus = Corpus(path)

print(corpus.train.size())
print(corpus.valid.size())
print(corpus.test.size())
torch.Size([2088628])
torch.Size([217646])
torch.Size([245569])
  • 각 범주별 데이터의 수를 알 수 있다. 훈련 데이터는 검증 데이터와 평가 데이터의 10배 정도의 크기이다.

Question

현재 코드는 train, valid, test 데이터를 모두 dictionary에 갖게 된다. 이 때 발생하는 문제점은 무엇일까?

이를 해결하려면 코드를 어떻게 바꿔야 할까?

2. 모델 아키텍처 준비

라이브러리 임포트

import math
import torch
import torch.nn as nn
import torch.nn.functional as F

RNN Model Class

init

class RNNModel(nn.Module):
    """Container module with an encoder, a recurrent module, and a decoder."""

    def __init__(self, rnn_type, ntoken, ninp, nhid, nlayers, dropout=0.5):
        super(RNNModel, self).__init__()
        self.ntoken = ntoken
        self.drop = nn.Dropout(dropout)
        self.encoder = nn.Embedding(ntoken, ninp)
        if rnn_type in ['LSTM', 'GRU']:
            self.rnn = getattr(nn, rnn_type)(ninp, nhid, nlayers, dropout=dropout)
        else:
            try:
                nonlinearity = {'RNN_TANH': 'tanh', 'RNN_RELU': 'relu'}[rnn_type]
            except KeyError:
                raise ValueError( """An invalid option for `--model` was supplied,
                                 options are ['LSTM', 'GRU', 'RNN_TANH' or 'RNN_RELU']""")
            self.rnn = nn.RNN(ninp, nhid, nlayers, nonlinearity=nonlinearity, dropout=dropout)
        self.decoder = nn.Linear(nhid, ntoken)

        self.init_weights()

        self.rnn_type = rnn_type
        self.nhid = nhid
        self.nlayers = nlayers
  • token의 개수 ntoken 을 입력받아 Embedding의 입력차원으로 구성한다. ninp 는 임베딩 차원을 의미하며 nhid 는 히든 차원을 의미한다.

  • LSTM, GRU, RNN_TANH, RNN_RELU 에 대한 4가지 모듈을 사용할 수 있다.

init_weights

    def init_weights(self):
        initrange = 0.1
        nn.init.uniform_(self.encoder.weight, -initrange, initrange)
        nn.init.zeros_(self.decoder.weight)
        nn.init.uniform_(self.decoder.weight, -initrange, initrange)
  • 인코더의 파라미터를 -0.1 부터 0.1 사이의 균등분포를 만족하도록 초기화한다.

  • 디코더도 마찬가지.

forward

    def forward(self, input, hidden):
        emb = self.encoder(input)
        emb = self.drop(x)
        output, hideen = self.rnn(emb, hidden)
        output = self.drop(output)
        decoded = self.decoder(output)
       
       return F.log_softmax(decoded, dim=1), hidden

init_hidden

    def init_hidden(self, bsz):
        weight = next(self.parameters())
        if self.rnn_type == 'LSTM':
            return (weight.new_zeros(self.nlayers, bsz, self.nhid),
                    weight.new_zeros(self.nlayers, bsz, self.nhid))
        else:
            return weight.new_zeros(self.nlayers, bsz, self.nhid)
  • RNN 타입이 LSTM일 경우 Cell state와 Hidden state 두 개의 가중치를, 그외의 경우에는 Hidden state 한 개의 가중치를 반환한다.

3. 모델 학습

모델에 필요한 argument를 설정한다.

import argparse
import time
import math
import os
import torch
import torch.nn as nn

# argparse 대신 easydict 사용
import easydict
args = easydict.EasyDict({
    "data"    : './',                   # location of the data corpus
    "model"   : 'RNN_TANH',             # type of recurrent net (RNN_TANH, RNN_RELU, LSTM, GRU)
    "emsize"  : 200,                    # size of word embeddings
    "nhid"    : 200,                    # number of hidden units per layer
    "nlayers" : 2,                      # number of layers
    "lr"      : 20,                     # initial learning rate
    "clip"    : 0.25,                   # gradient clipping
    "epochs"  : 6,                      # upper epoch limit
    "batch_size": 20,                   # batch size
    "bptt"    : 35,                     # sequence length
    "dropout" : 0.2,                    # dropout applied to layers (0 = no dropout)
    "seed"    : 1111,                   # random seed
    "cuda"    : True,                   # use CUDA
    "log_interval": 200,                # report interval
    "save"    : 'model.pt',             # path to save the final model
    "dry_run" : True,                   # verify the code and the model

})

# 디바이스 설정
device = torch.device("cuda" if args.cuda else "cpu")

이후, 말뭉치 데이터를 특정 배치만큼 나눠준다.

###############################################################################
# Load data
###############################################################################

corpus = Corpus(args.data)

# Starting from sequential data, batchify arranges the dataset into columns.
# For instance, with the alphabet as the sequence and batch size 4, we'd get
# ┌ a g m s ┐
# │ b h n t │
# │ c i o u │
# │ d j p v │
# │ e k q w │
# └ f l r x ┘.
# These columns are treated as independent by the model, which means that the
# dependence of e. g. 'g' on 'f' can not be learned, but allows more efficient
# batch processing.

def batchify(data, bsz):
    # Work out how cleanly we can divide the dataset into bsz parts.
    nbatch = data.size(0) // bsz
    # Trim off any extra elements that wouldn't cleanly fit (remainders).
    data = data.narrow(0, 0, nbatch * bsz)
    # Evenly divide the data across the bsz batches.
    data = data.view(bsz, -1).t().contiguous()
    return data.to(device)

eval_batch_size = 10
train_data = batchify(corpus.train, args.batch_size)
val_data = batchify(corpus.valid, eval_batch_size)
test_data = batchify(corpus.test, eval_batch_size)
  • torch.narrow 는 input, dim, start, length 를 인자로 받으며, input의 dim차원에 대해 start부터 length까지만 슬라이싱한다.

    • 여기서는 가장 바깥쪽 차원에 대해서 처음부터 nbatch * bsz 만큼까지 슬라이싱하는데, 이는 bsz로 데이터를 나누면 마지막에 남는 데이터가 생겨서 이를 제거해주기 위함이다.

  • view 를 통해 transpose 해준다. 근데 그 뒤에 또 .t() 로 transpose 해준다...? 뭘까? 언뜻 보면 transpose의 transpose를 해준다고 보이지만 첫 data가 1차원이어서 이를 2차원으로 만들어주고 transpose를 해준다.

    • 아니, 그러면 애초에 data.view(-1, bsz) 를 해주면 되는거 아니야? 라고 또 할 수 있지만 둘의 원소 배열이 좀 다르다. 일단 배치 사이즈만큼으로 행을 구성하고 transpose를 해줘야 하며, 처음부터 배치 사이즈만큼으로 열을 구성하게 되면 시퀀스의 배치가 섞이게 된다.

  • contiguous()는 텐서의 모양을 변형할 때 메모리에 텐서가 뒤죽박죽 쌓이게 된다고 한다. 변형해서 생성된 텐서를 마치 처음 생성한 것처럼 메모리에 쌓이게 해준다고 한다.

    • 변형될 때 메모리에 흩어진다는 뜻은 아니며, 메모리의 원소들의 순서가 뒤죽박죽이라는 이야기. 아무래도 메모리의 지역성을 고려해주는 것 같다. 순서가 뒤죽박죽이면 그로인해 생기는 delay가 있을테니!

###############################################################################
# Build the model
###############################################################################

ntokens = len(corpus.dictionary)

model = RNNModel(args.model, ntokens, args.emsize, args.nhid, args.nlayers, args.dropout).to(device)

criterion = nn.NLLLoss()
###############################################################################
# Training code1 - define functions
###############################################################################

def repackage_hidden(h):
    """Wraps hidden states in new Tensors, to detach them from their history."""

    if isinstance(h, torch.Tensor):
        return h.detach()
    else:
        return tuple(repackage_hidden(v) for v in h)


# get_batch subdivides the source data into chunks of length args.bptt.
# If source is equal to the example output of the batchify function, with
# a bptt-limit of 2, we'd get the following two Variables for i = 0:
# ┌ a g m s ┐ ┌ b h n t ┐
# └ b h n t ┘ └ c i o u ┘
# Note that despite the name of the function, the subdivison of data is not
# done along the batch dimension (i.e. dimension 1), since that was handled
# by the batchify function. The chunks are along dimension 0, corresponding
# to the seq_len dimension in the LSTM.

def get_batch(source, i):
    seq_len = min(args.bptt, len(source) - 1 - i)
    data = source[i:i+seq_len]
    target = source[i+1:i+1+seq_len].view(-1)
    return data, target


def evaluate(data_source):
    # Turn on evaluation mode which disables dropout.
    model.eval()
    total_loss = 0.
    ntokens = len(corpus.dictionary)
    hidden = model.init_hidden(eval_batch_size)
    with torch.no_grad():
        for i in range(0, data_source.size(0) - 1, args.bptt):
            data, targets = get_batch(data_source, i)
            output, hidden = model(data, hidden)
            hidden = repackage_hidden(hidden)
            total_loss += len(data) * criterion(output, targets).item()
    return total_loss / (len(data_source) - 1)


def train():
    # Turn on training mode which enables dropout.
    model.train()
    total_loss = 0.
    start_time = time.time()
    ntokens = len(corpus.dictionary)
    hidden = model.init_hidden(args.batch_size)
    for batch, i in enumerate(range(0, train_data.size(0) - 1, args.bptt)):
        data, targets = get_batch(train_data, i)
        # Starting each batch, we detach the hidden state from how it was previously produced.
        # If we didn't, the model would try backpropagating all the way to start of the dataset.
        model.zero_grad()

        hidden = repackage_hidden(hidden)
        output, hidden = model(data, hidden)

        ############################ ANSWER HERE ################################
        # TODO: train 함수를 (이곳에) 완성해주세요.
        #
        # Hint1: output 을 받았으니, loss를 계산할 차례입니다.
        #        loss 를 계산한 후 해야 하는 일은 무엇일까요?
        #########################################################################
        loss = criterion(output, targets)
        loss.backward()

        # `clip_grad_norm` helps prevent the exploding gradient problem in RNNs / LSTMs.
        torch.nn.utils.clip_grad_norm_(model.parameters(), args.clip)
        for p in model.parameters():
            p.data.add_(p.grad, alpha=-lr)

        total_loss += loss.item()

        if batch % args.log_interval == 0 and batch > 0:
            cur_loss = total_loss / args.log_interval
            elapsed = time.time() - start_time
            print('| epoch {:3d} | {:5d}/{:5d} batches | lr {:02.2f} | ms/batch {:5.2f} | '
                    'loss {:5.2f} | ppl {:8.2f}'.format(
                epoch, batch, len(train_data) // args.bptt, lr,
                elapsed * 1000 / args.log_interval, cur_loss, math.exp(cur_loss)))
            total_loss = 0
            start_time = time.time()
        if args.dry_run:
            break
  • repackage_hidden

    • 히든 스테이트를 다시 재구성 하는 작업이다. 재구성을 왜 해야될까? 한번 forward를 하고 backward를 하면 이 때 grad값이 hidden state에 남아있게된다. 그러면 두번째 학습에서 grad를 전파할 때 이전 grad값이 영향을 주게 된다. 그래서 detach 라는 함수를 써서 이를 초기화하는 것이다.

  • get_batch

    • 현재는 train_data 안에 X와 y값이 모두 들어있으므로 이를 data와 target으로 분리해주는 역할을 한다. 각 시퀀스는 바로 뒷 단어를 예측하면 되므로 인덱스를 +1 해서 슬라이싱 해준다.

  • evaluate

    • train 과정과 동일하다. 아래에서 부가 설명

  • train

    • 기존과는 다르게 optimizer.zero_grad 를 해주지 않고 model.zero_grad 를 해준다. 왜일까? 왜냐하면 optimizer가 없기 때문이다.

    • 그럼 optimizer는 없는거야? 아니다! 단순히 optimizer라는 모듈을 쓰지 않을 뿐이고

    • line 57 그리고 73-74에서 그 역할을 하게된다.

    • grad를 0으로 초기화해주는 repackage 작업을 거친뒤 모델에서 output과 hidden을 얻고 loss를 계산하고, 파라미터를 갱신해주는 작업을 거친다.

Previous[필수 과제 3] Subword-level Language ModelNext[선택 과제] BERT Fine-tuning with transformers

Last updated 3 years ago

Was this helpful?