[DL Wizard] Long Short-Term Memory (LSTM) network with PyTorch 번역 및 정리

2020. 2. 8. 01:04nlp

반응형

https://www.deeplearningwizard.com/deep_learning/practical_pytorch/pytorch_lstm_neuralnetwork/

 

Long Short Term Memory Neural Networks (LSTM) - Deep Learning Wizard

Long Short-Term Memory (LSTM) network with PyTorch About LSTMs: Special RNN Capable of learning long-term dependencies LSTM = RNN on super juice RNN Transition to LSTM Building an LSTM with PyTorch Model A: 1 Hidden Layer Unroll 28 time steps Each step inp

www.deeplearningwizard.com

 

 

Model A : 1 Hidden Layer

- 입력 데이터는 MNIST 손글씨 데이터

- 입력 사이즈 (28,1) 

- 반복 횟수는 28 

 

 

Create Model Class

 

class LSTMModel(nn.Module):
    def __init__(self, input_dim, hidden_dim, layer_dim, output_dim):
        super(LSTMModel, self).__init__()
        
        self.hidden_dim = hidden_dim
        self.layer_dim = layer_dim # 은닉층 개수 
        
        # LSTM
        # batch_first : input/output 텐서가 (batch_dim, seq_dim, feature_dim) 형태가 됨 
        # batch_dim = batch_size, seq_dim = 반복 횟수, feature_dim = ?
        self.lstm = nn.LSTM(input_dim, hidden_dim, layer_dim, batch_first=True)
        
        # Readout layer
        self.fc = nn.Linear(hidden_dim, output_dim)
        
    def forward(self, x):
        # 은닉상태를 0으로 초기화
        h0 = torch.zeros(self.layer_dim, x.size(0), self.hidden_dim).requires_grad_()
        # cell state를 0으로 초기화
        c0 = torch.zeros(self.layer_dim, x.size(0), self.hidden_dim).requires_grad_()
        
        # 28 time steps (28번 반복) 
        # truncated BPTT
        # detach 안 하면 다음 배치로 넘어가서도 맨 앞까지 오차역전파함
        out, (hn, cn) = self.lstm(x, (h0.detach(), c0.detach()))
        
        # out.size() -> 100, 28, 100 
        # out[:, -1, :] -> 100, 100 (마지막 반복의 은닉 상태만)
        
        out = self.fc(out[:, -1, :])
        # 100,100 을 FC에 넣어서 이제 100,10
        # out.size() -> 100,10
        return out
        
        

 

Instantiate Model Class

 

input_dim = 28
hidden_dim = 100
layer_dim = 1
output_dim = 10

model = LSTMModel(input_dim, hidden_dim, layer_dim, output_dim)

 

Parameter 살펴보기

전체 파라미터 개수 = 6개

 

• input -> forget/input/new candidate/output gates로 가는 W, b

- 3개의 gate + new candidate = 총 4개로 보내는 걸 하나의 큰 가중치 행렬로 만듦

- 각 가중치는 [100,28] * input(x) [28,1] + 편향 [100,1] = [100,1]

- 그런데 총 4개를 합쳐서 100 -> 400

- 전체 가중치 [400,28] * input(x) [28,1] + 편향 [400,1] = [400,1]

 

• 은닉 상태(h) -> forget/input/new candidate/output gates로 가는 W, b 

- 3개의 gate + new candidate = 총 4개로 보내는 걸 하나의 큰 가중치 행렬로 만듦

- 각 가중치는 [100,100] * 은닉상태(h) [100,1] + 편향 [100,1] = [100,1]

- 그런데 총 4개를 합쳐서 100 -> 400

- 전체 가중치 [400,100] * 은닉상태(h) [100,1] + 편향 [400,1] = [400,1]

 

• 은닉 상태 (h) -> output으로 가는 W, b 

-  FC 가중치 [10,100] * 은닉상태(h) [100,1] + 편향 [10,1] = [10,1]

 

 

 

Train/Test Model

 

images = images.view(-1, seq_dim, input_dim).requires_grad_()

images = images.view(-1, seq_dim, input_dim)

 

# 반복횟수
seq_dim = 28  

iter = 0
for epoch in range(num_epochs):
    for i, (images, labels) in enumerate(train_loader):
        
        # images = (batch_size, seq_dim, input_dim) = (100, 28, 28)
        images = images.view(-1, seq_dim, input_dim).requires_grad_()

        # Clear gradients 
        optimizer.zero_grad()

        # outputs.size() --> 100, 10
        outputs = model(images)

        # Calculate Loss: softmax --> cross entropy loss
        loss = criterion(outputs, labels)

        # Getting gradients w.r.t. parameters
        loss.backward()

        # Updating parameters
        optimizer.step()

        iter += 1

        if iter % 500 == 0:
            # Calculate Accuracy         
            correct = 0
            total = 0
            # Iterate through test dataset
            for images, labels in test_loader:
                # Resize images
                images = images.view(-1, seq_dim, input_dim)

                # Forward pass only to get logits/output
                outputs = model(images)

                # Get predictions from the maximum value
                _, predicted = torch.max(outputs.data, 1)

                # Total number of labels
                total += labels.size(0)

                # Total correct predictions
                correct += (predicted == labels).sum()

            accuracy = 100 * correct / total

            # Print Loss
            print('Iteration: {}. Loss: {}. Accuracy: {}'.format(iter, loss.item(), accuracy))

 

cf. 은닉층 2개 (layer_dim=2) 로 변경했을 때 Parameter 변화

 

 

반응형