全結合ニューラルネットの基本モデル作成

2022 年 12 月 22 日 by ueno-suguru
【概要】
本記事では、深層学習(Deep Learning)の基本となるモデルを
まずは動かしてみたいという人に向けて、
実装コードを展開するという内容になっています。
そのため、本記事では学習の安定化を図るドロップアウトや
バッチ正規化の実装、ニューラルネットに関する理論等、
については、取り扱っていないためご注意ください。
【本編】
初めに実装全体を眺めてみたいと思います。実装は、以下の通りです。
import torch
import torch.nn as nn
from torch.autograd import Variable
from torch.utils.data import DataLoader, TensorDataset

class Net(nn.Module):
    def __init__(self, input_dim, hidden_dim, output_dim, lr, batch_size, epoch):
        # パラメータの設定 ★
        # 学習率
        self.lr = lr
        # バッチサイズ
        self.batch_size = batch_size
        # エポック数(データ全体に対する学習の反復回数)
        self.epoch = epoch

        # 層構造の定義 ★
        super().__init__()
        self.fc1 = nn.Linear(input_dim, hidden_dim)
        self.act1 = nn.ReLU()
        self.fc2 = nn.Linear(hidden_dim, output_dim)
        self.layers = [self.fc1, self.act1, self.fc2]

        # 損失関数
        self.criterion = nn.MSELoss() 
        # 最適化手法の指定
        self.optimizer = torch.optim.Adam(self.parameters(), lr=self.lr)
    
    def forward(self, x):
      # 順伝播
      for layer in self.layers:
          x = layer(x)
      return x
    
    def fit(self, X, y=None, **params):
      # 学習フェーズへ切り替え
      self.train()
      # 学習データの変換
      tensorX = torch.from_numpy(X).float()
      tensorY = torch.from_numpy(y).float()
      train = TensorDataset(tensorX, tensorY)
      # 学習データ全体をランダムに並び替え、バッチサイズごとにループ処理できるように変換
      train_loader = DataLoader(train, batch_size=self.batch_size, shuffle=True)

      # 学習
      for epoch in range(self.epoch):
        total_loss = 0
        # バッチサイズ単位での処理
        for train_x, train_y in train_loader:
          train_x, train_y = Variable(train_x), Variable(train_y)
          # 勾配の初期化
          self.optimizer.zero_grad()
          # 順伝播
          output = self(train_x)
          # 損失の算出
          loss = self.criterion(output, train_y)
          # 誤差逆伝播
          loss.backward()
          self.optimizer.step() 
          total_loss += loss.data
        
        if (epoch+1) % 10 == 0:
          print(f'[epoch:{epoch+1}] loss:{loss}')
      return self

    def predict(self, X):
      # 検証フェーズへ切り替え
      self.eval()
      tensorX = torch.from_numpy(X).float()
      test_X = Variable(tensorX)
      return self(test_X)
基本的な実装ですが、
古典的な機械学習モデルや
scikit-learnのインターフェイスに慣れている人からすると、
実装コードの行数が多く、
Deep Learnig の実装は、大変に感じるかも知れません。
少なくとも、私はそうでした。。。

そんなとき、基本的なモデルで、
パラメータを変えて遊べるものがあればと思うことがあり、
同じような困り感がある人の助けになればと考え、
本記事を書くに至りました。

学習や予測に使われる関数群
forward()、fit()、predict()の中身はさておき、
(理論を学んだことがある方向けに、コードにはコメントを記載していますが、)

チューニングすべきパラメータは、コード上の「★」がついている箇所の
・ パラメータの設定 ★
・ 層構造の定義 ★
の部分のみです。

正規化/正則化の後、チューニングすべきかもしれませんが、
本記事の目標は、まずは動かすことなので、
ご容赦いただければと。。。

例えば、以下のようにパラメータを設定して、
動かすことができます。
※input_dimは特徴量の数、output_dimは目的変数の形式に応じて、
設定してください。
nn = Net(input_dim=10, hidden_dim=50, output_dim=1, lr=1e-4, batch_size=8, epoch=100)
nn.fit(train_X, train_y) # train_X:説明変数  train_y:目的変数
pred_y = nn.predict(test_X).data.numpy() # test_X:テストデータ
皆さんもよろしければ、Google Colab などで、動かしてみてください!

タグ: , ,

TrackBack