Programming lab

Pytorchのネットワークの書き方を徹底解説

Pytorchのネットワークの書き方を徹底解説

 

 

  • Pytorchのネットワークの定義方法がよくわからない…
  • 人によってPytorchのネットワークの定義方法が異なってよくわからない…

 

本記事では、その悩みを解決していきます。

実は、Pytorchのネットワークの定義方法を理解することで、自由自在にネットワークの構造をカスタマイズすることができます。

カスタマイズ性に関しては、他のライブラリ以上です!

本記事では、Pytorchのネットワークの書き方を徹底的に解説していきます。

 

Pytorchのモデルを設計するための準備

 

Pytorchでニューラルネットワーク、ディープラーニングのモデル設計を行うための準備を本章では行います。

 

モデル設計のためのライブラリをインポート

 

まずは、モデル設計のためのライブラリをインポートしていきましょう。

具体的には、下記のコードを実行してください。

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

 

基本的には、Pytorchの『Tensor』に関しては、既知であることを仮定して作成しています。

『Tensor?』という方は、下記の記事を参考にしてから本記事に戻ってきてください。

 

【Pytorch】tensor型とは(知らないとまずいものをまとめてみた)PyTorchのTensorに関してまとめてみました。この中で紹介しているTensorの関数やメソッドは、どれも機械学習で必要不可欠なものばかりです。15分程度で読み終わるので一読して頭を整理させましょう。...

 

具体的なサンプルデータを生成

 

本記事では、具体的にネットワークを設計し、サンプルデータを実際にネットワークに入力し順伝搬の結果を出力するまでを実装します。

そのため、このタイミングでサンプルデータを生成しておきます。

サンプルデータを生成するための下記のコードを実行してください。

<Input>

sample = torch.randn(1, 10)
sample

 

<out>

tensor([[ 0.4883,  0.9117, -0.3643,  0.9628,  1.9357, -0.6975, -0.5308, -0.0492,
          0.6824, -0.3260]])

 

今回は、特徴量の数が10個ある一つのデータをサンプルデータとして使用します。

 

ネットワークの設計方法は2種類ある

 

PyTorchでネットワークを設計する方法は大きく分けて2種類あります。

  1. nn.Sequentialを使用する書き方
  2. ネットワークをモジュール化する書き方

 

この二つの方法に関しては、次章で順番に詳しく説明していきます。

 

nn.Sequentialを使用する書き方

 

本章では、nn.Sequentialを使用してモデルを設計する書き方を説明します。

まずは、nn.Sequentialを使用するメリット・デメリットを説明します。

 

nn.Sequentialを使用するメリット・デメリット

 

nn.Sequentialを使用するメリット・デメリットは以下のようになります。

メリット

  1. 簡単にネットワークを定義できる

デメリット

  1. カスタマイズ性が低い

 

わかりやすくコードが書けますが、複雑なネットワークを定義することができません。

 

nn.Sequentialの実装

 

今回は、活性化関数をReLU関数とした3層のネットワークを具体例として定義していきます。

ネットワークの処理をまとめて書くだけで、Sequentialを書くことができます。

具体的なコードは下記を参考にしてください。

<Input>

# Sequentialの書き方
model = nn.Sequential(
            nn.Linear(10, 32),
            nn.ReLU(),
            nn.Linear(32, 16),
            nn.ReLU(),
            nn.Linear(16, 10)
            )

print(model)

 

<Output>

Sequential(
  (0): Linear(in_features=10, out_features=32, bias=True)
  (1): ReLU()
  (2): Linear(in_features=32, out_features=16, bias=True)
  (3): ReLU()
  (4): Linear(in_features=16, out_features=10, bias=True)
)

 

とても簡単にネットワークを構築することができます。

 

nn.Sequentialの順伝搬

 

ネットワークが定義できたので、先ほどのサンプルデータを順伝搬させ、動作を確認しましょう。

<Input>

y = model(sample)
y

 

<Output>

tensor([[-3.0313e-01, -1.1111e-04,  7.7502e-02, -2.0157e-01,  3.7895e-03,
          5.1864e-02, -7.6282e-02, -5.4766e-03,  6.1397e-02,  1.0263e-01]],
       grad_fn=<AddmmBackward>)

 

このように、出力を計算することができましたね。

 

ネットワークをモジュール化する書き方

 

本章では、ネットワークをモジュール化する書き方を説明していきます。

同様に、モジュール化する書き方のメリット・デメリットを説明します。

 

ネットワークをモジュール化する書き方のメリット・デメリット

 

ネットワークをモジュール化する書き方のメリット・デメリットを説明します。

メリット

  1. カスタマイズ性が高い
  2. 再利用しやすい

デメリット

  1. 定義するのに手間がかかる

 

Pytorchの良さはカスタマイズ性なので、多くの方がこれから紹介するモジュール化する書き方を使用します。

 

ネットワークのモジュール化を実装

 

基本的な書き方は、nn.Moduleクラスを継承し、クラスに対して以下を定義します。

  1. __init__ : コンストラクタでネットワークを定義する
  2. forwardメソッド : forwardメソッドで順伝搬を定義する

 

具体例を以下に示します。

# ネットワークのモジュール化
class Model(nn.Module):
    def __init__(self, input):
        super(Model, self).__init__()
        
        # ネットワークを定義
        self.linear1 = nn.Linear(input, 32)
        self.linear2 = nn.Linear(32, 16)
        self.linear3 = nn.Linear(16, 10)
        self.relu = nn.ReLU()

    # 順伝搬を定義
    def forward(self, x):
        x = self.linear1(x)
        x = self.relu(x)
        x = self.linear2(x)
        x = self.relu(x)
        x = self.linear3(x)
        return x

 

これで、Sequentialで定義したネットワークと同じネットワークを定義できます。

 

自作定義したネットワークの順伝搬

 

先ほとモジュール化したネットワークに対して、サンプルデータを入力し、順伝搬の出力を行いましょう。

下記のコードを実行してください。

<Input>

# instance化
model = Model(input=10)

# 順伝搬
y = model(sample)
y

 

<Output>

tensor([[-0.1017, -0.2631, -0.1403,  0.1053,  0.0721, -0.0560,  0.2038, -0.1486,
          0.3030,  0.1571]], grad_fn=<AddmmBackward>)

 

この自作モジュールを複数使用してネットワークを作成することもできます。

 

自作モジュールを複数使用して新たな自作モジュールを作成

 

自作モジュールを作成するメリットを理解していただけるように、簡単な例ですが、上記のネットワークを二つの自作モジュールを使用して構築します。

まずは、活性化関数も含めた各層の処理を以下のコードでモジュール化します。

# Custum Layer
class CustomLayer(nn.Module):
    def __init__(self, input, output):
        super(CustomLayer, self).__init__()
        self.linear=nn.Linear(input, output)
        self.relu=nn.ReLU()
    def forward(self, x):
        x=self.linear(x)
        x=self.relu(x)
        return x

 

さらに、この自作モジュールを使用して、これまで定義したネットワークと同じネットワークを作成します。

# ネットワークをモジュール化
class Model(nn.Module):
    def __init__(self, input):
        super(Model, self).__init__()
        self.custom1 = CustomLayer(input, 32)
        self.custom2 = CustomLayer(32, 16)
        self.linear3 = nn.Linear(16, 10)

    def forward(self, x):
        x = self.custom1(x)
        x = self.custom2(x)
        x = self.linear3(x)
        return x

 

順伝搬を実装してみます。

<Input>

model = Model(input=10)
y = model(sample)
y

 

<Output>

tensor([[0.0000, 0.1822, 0.2371, 0.1343, 0.0995, 0.1915, 0.2539, 0.0000, 0.0348,
         0.0000]], grad_fn=<ReluBackward0>)

 

より高度なモデルを実装する際は、一つのモジュールに全てのネットワークを定義すると可読性が下がってしまいます。

今回は、簡単な例だったのでありがたみが上手く伝らなったかもしれませんが、このような再利用性とカスタマイズ性がPytorchの強みの一つです。

 

まとめ

 

今回は、Pytorchのネットワークの書き方を二つ紹介しました。

特に後者の自作モジュールを作成する方法は、理解するのは少し難しいですが、複雑なネットワークを簡単に作成できる方法です。

あとは、DatasetとDataLoaderで作成したデータを入力し、パラメータを更新することでネットワークを学習することができます。

DatasetとDataLoaderに関しては下記を参考にしてください

 

 

本記事が皆様の役に立てたら光栄です…

『Pytorchで深層学習を実装してみたい!』という方は下記を参考にしてください。

 

【PyTorch入門】多層パーセプトロンでMNISTを分類本記事では、PyTrochで多層パーセプトロンを構築し、手書き文字のデータセットのMNISTを分類しました。本記事を理解することでPytorchを使用してディープラーニングを構築する基本が身につきます。...

 

ABOUT ME
努力のガリレオ
【運営者】 : 東大で理論物理を研究中(経歴)東京大学, TOEIC950点, NASA留学, カナダ滞在経験有り, 最優秀塾講師賞, オンライン英会話講師試験合格, ブログと独自コンテンツで収益6桁達成 【編集者】: イングリッシュアドバイザーとして勤務中(経歴)中学校教諭一種免許取得[英語],カナダ留学経験あり, TOEIC650点