iT邦幫忙

2021 iThome 鐵人賽

DAY 28
0
AI & Data

Deep Learning 從零開始到放棄的 30 天 PyTorch 數字辨識模型系列 第 30

Day-29 Pytorch 還可以更輕鬆更簡單!Pytorch Lightning

  • 我們整個系列帶領大家從 Python 轉移到 Pytorch 的撰寫,我們在這個過程應該已經深刻體驗 Framework 的威力了,但是!如果我告訴你,我們還可以更輕鬆,你相不相信?
  • 我們今天就來介紹一個 Open Source 計畫,也就是 Pytorch Lightning ~

What is Pytorch Lightning

  • Pytorch 雖然足夠便捷了,但是仍然存在一些底層 Framework 的硬傷,例如
    • model 狀態屬於 eval() or train()
    • device 要是 tpu, gpu, cpu
    • optimizer 的歸零
    • ...
  • 可以發現小問題仍然非常非常多,這些東西在實驗的過程和嘗試的過程中,其實容易造成不必要的困擾,尤其當整體架構變得更加複雜時,這些細節往往容易影響到模型狀態,卻也容易造成不必要的實驗困擾
  • 那 Pytorch Lightning 就順應而生了,他提供了更加簡潔的環境,提供了更加靈活的設備兼容,解決了不少 Pytorch 本身沉重且複雜的流程
  • 那由於是 open source project,因此我們可以在 pytorch lightning github 找到他們,也可以去看美美的官網

how to use it ?

  • 那要使用 Pytorch lightning 很簡單,誠如他們網站所說,第一步是去安裝,第二步就是開箱及用啦~
  • install
    • 視設備和環境使用 pip 或是其他方式下載,這邊就不特別介紹了,可以自己去官網看看
  • 那實際使用我們就直接改寫前面的模型來做為示範吧~

Rewrite Feed-Forward Neural Network

  • 我們就直接改寫 Feed-Forward Neural Network 來作為一個示範
  • 那這邊的改寫順序就依照官方文檔的順序改造
  • 首先基本的 import 要有之外,要記得多放 import pytorch_lightning as pl
    import numpy as np
    import pandas as pd
    
    import torch
    import torch.nn as nn
    from torch.utils.data import Dataset, DataLoader
    from torch.utils.data.sampler import SubsetRandomSampler
    
    import pytorch_lightning as pl
    
  • 依照文檔的第一步,我們要把原本的模型宣告放上來,更改中間的 nn.Modulepl.LightningModule,那這樣的改寫不會影響到任何舊的撰寫,原因是 pl.LightningModule 中有提供所有 nn.Module 中的所有 function,且多提供了 Lightning 會用的 function
    class FeedForwardNeuralNet(pl.LightningModule):
    
        def __init__(self, input_size, hidden_size, num_classes):
            super(FeedForwardNeuralNet, self).__init__()
            # define first layer
            self.l1 = nn.Linear(input_size, hidden_size)
            # activation function
            self.relu = nn.ReLU()
            # define second layer
            self.l2 = nn.Linear(hidden_size, num_classes)
    
        def forward(self, x):
            out = self.l1(x)
            out = self.relu(out)
            out = self.l2(out)
    
            return out
    
  • 那第二步驟是把原本寫在外面的 optimizer 更改到裡面的 configure_optimizers,所以我們會多一個
    def configure_optimizers(self, learning_rate):
        optimizer = torch.optim.Adam(self.parameters(), lr=learning_rate)
    
        return optimizer
    
  • 那接下來我們要把 train loop 也給寫進去,但是這邊要注意一件事情,Pytorch lightning 已經幫忙把大部分的事情全部做完了,因此我們寫進來的只需要計算 loss 就可以了,因此會寫成這樣
    def training_step(self, batch, batch_idx):
        datas, labels = batch
        outputs = self(datas)
        loss = F.cross_entropy(outputs, labels)
    
        return loss
    
    • 那要特別注意,現在的 loss function 要利用 torch.nn.functional 套件的 functions
  • 所以到這裡我們整個 class 會長成怎樣?
    class FeedForwardNeuralNet(pl.LightningModule):
    
        def __init__(self, input_size, hidden_size, num_classes):
    
            super(FeedForwardNeuralNet, self).__init__()
            # define first layer
            self.l1 = nn.Linear(input_size, hidden_size)
            # activation function
            self.relu = nn.ReLU()
            # define second layer
            self.l2 = nn.Linear(hidden_size, num_classes)
    
        def forward(self, x):
    
            out = self.l1(x)
            out = self.relu(out)
            out = self.l2(out)
    
            return out
    
        def training_step(self, batch, batch_idx):
    
            datas, labels = batch
            outputs = self(datas)
            loss = F.cross_entropy(outputs, labels)
    
            return loss
    
        def configure_optimizers(self):
    
            optimizer = torch.optim.Adam(self.parameters(), lr=learning_rate)
    
            return optimizer
    
  • 那讓我們使用看看我們改寫的部分,在要使用 Pytorch Lightning System 需要 import 一個 Trainer
    from pytorch_lightning import Trainer
    
    trainer = Trainer()
    
  • 那我們一樣取得訓練資料,我們就一樣拿手寫資料集,所以我們的 Dataset 跟 Dataloader 會寫成
    train_dataset = torchvision.datasets.MNIST(root='./data', 
                                               train=True,
                                               transform=transforms.ToTensor(), 
                                               download=False)
    train_loader = DataLoader(dataset=train_dataset, 
                              batch_size=batch_size,
                              shuffle=True)
    
  • 那訓練操作就會是
    model = FeedForwardNeuralNet(input_size, hidden_size, num_classes)
    trainer = Trainer()
    trainer.fit(model, train_loader)
    
  • 這邊要特別注意,Pytorch lightning 的 Trainer 會自動化
    • Epoch 跟 Batch size
    • Optimizer.step() 還有 backward, zero_grad()
    • 還有宣告 .eval() 或是 .train()
    • ...
      簡單來說就是都幫你做好了
  • 那剩下還有驗證跟測試等等部份的撰寫,就請大家自己去官網理解了,官方文檔寫得非常非常清楚

每日小結

  • Pytorch Lightning 是一個能夠讓模型建立更加單純的工具,高度自動化,高度輕量,大大的減少了建立模型上的困難
  • 但是為什麼不一開始就教學使用 pytorch lightning ? 可以發現 Pytorch Lightning 已經跳脫了很多基礎架構的東西了,結構也有了明顯的變化,甚至撰寫的邏輯也不同了,因此對於初學沒有太大的幫助,只是在有基礎概念之後,可以發現 Pytorch lightning 可以減少更多問題,因此在這裡提出
  • 到這裡,我們已經把所有 Pytorch 需要知道的東西都學完了~ 恭喜大家~

上一篇
Day-28 手把手的手寫辨識模型 0x3:CNN is the end?模型大哉問
下一篇
Day-30 不完美收工
系列文
Deep Learning 從零開始到放棄的 30 天 PyTorch 數字辨識模型31

尚未有邦友留言

立即登入留言