山内セミナーⅠ(2020/08/05)

関連サイトと資料

1.Getting Started with PyTorch for Deep Learning

Building models

モデルは、入力を処理して出力を生成する、接続されたレイヤーのコレクションです。 nnパッケージを使用してモデルを定義できます。 nnパッケージは、一般的なディープラーニング層を提供するモジュールのコレクションです。 nnのモジュールまたは層は、入力テンソルを受け取り、出力テンソルを計算し、重みがあればそれを保持します。 PyTorchでモデルを定義するために使用できる2つの方法があります:nn.Sequentialとnn.Moduleです。

How to do it...

線形層、2層ネットワーク、および多層畳み込みネットワークを定義します。

Defining a linear layer

線形レイヤーを作成し、その出力サイズを表示してみましょう。

次のコードは、その出力サイズを出力します。

次のセクションでは、nn.Sequentialパッケージを使用してモデルを定義する方法を示します。

Defining models using nn.Sequential

nn.Sequentialパッケージを使用して、レイヤーを順番に渡すことでディープラーニングモデルを作成できます。 次の図に示す2層ニューラルネットワークを考えてみます。

ご覧のとおり、ネットワークには入力として4つのノード、非表示層に5つのノード、出力として1つのノードがあります。 次に、ネットワークの実装方法を示します。

  1. nn.Sequentialを使用してモデルを実装および表示してみましょう。

    上記のコードの出力は次のとおりです。

次のセクションでは、モデルを定義する別の方法を紹介します。

Defining models using nn.Module

PyTorchでモデルを定義する別の方法は、nn.Moduleクラスをサブクラス化することです。 このメソッドでは、クラスの__init__メソッドでレイヤーを指定します。 次に、forwardメソッドで、レイヤーを入力に適用します。 この方法は、カスタマイズされたモデルを構築するためのより優れた柔軟性を提供します。

次の図に示すように、多層モデルを考えます。

上の図に示すように、モデルには2つの畳み込み層と2つの全接続層があります。 次に、モデルの実装方法を示します。

nn.Moduleを使用して多層モデルを実装してみましょう:

  1. まず、クラスの大部分を実装します。
  2. 次に、__ init__関数を定義します。
  3. 次に、フォワード関数を定義します。
  4. 次に、__ init__とforwardの両方のクラス関数をオーバーライドします。
  5. 次に、Netクラスのオブジェクトを作成し、モデルを出力します。

上記のコードの出力は次のとおりです。

次のセクションでは、モデルをCUDAデバイスに移動する方法を示します。

Moving the model to a CUDA device

モデルはパラメーターのコレクションです。 デフォルトでは、モデルはCPUでホストされます。

  1. モデルのデバイスを取得しましょう:

    上記のスニペットは、次の出力を出力します。
  2. 次に、モデルをCUDAデバイスに移動します。

次のセクションでは、モデルの概要を表示する方法を示します。

Printing the model summary

通常、モデルの概要を取得して、各レイヤーの出力形状とパラメーターの数を確認すると便利です。 モデルを表示しても、この種の情報は提供されません。 この目的のために、次のGitHubリポジトリからtorchsummaryパッケージを使用できます。 https://github.com/sksq96/pytorch-summary 始めましょう:

  1. torchsummaryパッケージをインストールします。
  2. torchsummaryを使用してモデルの概要を取得しましょう:

上記のコードは、実行時にモデルの概要を表示します。

次のセクションでは、各ステップについて詳しく説明します。

How it works...

最初に、nnパッケージを使用して線形レイヤーを作成する方法を示しました。 線形レイヤーは64 * 1000ディメンションの入力を受け取り、 1000 * 100ディメンションの重みを保持し、64 * 100ディメンションの出力を計算します。

次に、nn.Sequentialを使用して2層ニューラルネットワークを定義しました。 入力層には4つのニューロン、非表示層には5つのニューロン、出力層には1つのニューロンがありました。 printコマンドを使用して、モデルのレイヤーを視覚化できます。

次に、nn.Moduleを使用して多層モデルを定義しました。 モデルには2つのConv2dレイヤーと2つの完全に接続された線形レイヤーがあります。 コードを読みやすくするために、Netクラスをいくつかのスニペットで示しました。 まず、クラスの大部分を定義しました。 次に、__ init__関数を定義しました。 ご覧のとおり、この関数では2つのConv2dレイヤーと2つの線形レイヤーが定義されています。 次に、フォワード関数を定義しました。 この関数では、モデルのアウトラインとレイヤーの相互接続方法を定義しました。

torch.nn.functionalのreluとmax_pool2dを使用して、アクティベーション機能とプーリングレイヤーをそれぞれ定義しました。 .viewメソッドを使用して、Conv2dレイヤーから抽出された特徴量をフラット化する方法を確認してください。 特徴量のサイズは4 * 4で、self.conv2レイヤーには50のチャネルがありました。 このため、平坦化されたサイズは50 * 4 * 4です。 また、forward関数からの戻り値を確認してください。 見てきたように、log_softmax関数が出力に適用されました。 次に、Netクラス関数をオーバーライドしました。 最後に、Netクラスのオブジェクトを作成し、モデルと呼びました。 次に、モデルを表示しました。 printコマンドは、reluやmax_pool2dなどの機能レイヤーを表示しないことに注意してください。

モデルをCUDAデバイスに移動するサブセクションでは、モデルがCPUデバイスでホストされていることを確認しました。 次に、.toメソッドを使用してモデルをCUDAデバイスに移動しました。 ここでは、最初のGPUまたは「cuda:0」を移動しました。 システムに複数のGPUデバイスが搭載されている場合は、「cuda:2」などの別の番号を選択できます。

次に、提供されたコマンドを使用して、conda環境にtorchsummaryパッケージをインストールしました。

このパッケージをインストールしたくない場合は、他のオプションとして、コードのフォルダーにtorchsummary.pyをコピーします。

torchsummaryを使用してモデルの要約を取得するには、入力ディメンションを要約関数に渡す必要があります。 MNISTの例では、(1,28,28)を入力ディメンションとして渡し、モデルの概要を表示しました。 ご覧のように、機能レイヤーを除く各レイヤーの出力形状とパラメーター数が要約に表示されます。

最後に、torchsummaryパッケージを使用してモデルの概要を取得しました。

Defining the loss function and optimizer

損失関数は、モデル出力とターゲットの間の距離を計算します。 これは、目的関数、コスト関数、または指標とも呼ばれます。 問題に応じて、適切な損失関数を定義します。 たとえば、分類問題では、通常、クロスエントロピー損失を定義します。

オプティマイザーを使用して、トレーニング中にモデルパラメーター(重みとも呼ばれます)を更新します。 PyTorchのoptimパッケージは、さまざまな最適化アルゴリズムの実装を提供します。 これらには、確率的勾配降下法(SGD)とそのバリアント、つまりAdam、RMSpropなどが含まれます。

How to do it...

このセクションでは、PyTorchでの損失関数とオプティマイザの定義について見ていきます。

Defining the loss function

損失関数を定義し、ミニバッチでテストします。 始めましょう:

  1. 最初に、負の対数尤度損失を定義します。
  2. ミニバッチで損失関数をテストしましょう:

    上記のスニペットは、次の出力を出力します。
  3. モデルパラメータに関する勾配を計算してみましょう。

次のステップでは、オプティマイザを定義する方法を示します。

Defining the optimizer

オプティマイザを定義し、逆のステップを示します。 始めましょう:

  1. Adamオプティマイザを定義しましょう:
  2. 次のコードを使用して、モデルパラメータを更新します。
  3. 次に、グラデーションをゼロに設定します。

次のセクションでは、各ステップについて詳しく説明します。

How it works...

まず、損失関数を定義しました。 torch.nnパッケージを使用して、負の対数尤度損失を定義しました。 この損失は、複数のクラスで分類問題をトレーニングするのに役立ちます。 この損失関数への入力は対数確率でなければなりません。 「モデルの構築」セクションを思い出してください。 モデルから対数確率を取得するために、出力層にlog_softmaxを適用しました。 次に、フォワードパスを示しました。 ミニバッチを抽出してモデルに供給し、損失値を計算しました。 次に、.backwardメソッドを使用して、モデルパラメーターに関する損失の勾配を計算しました。 このステップは、逆伝播アルゴリズム中に使用されます。

次に、Adamオプティマイザを定義します。 オプティマイザへの入力は、モデルパラメータと学習率です。 次に、.step()モデルを提示して、モデルパラメータを自動的に更新しました。 次のバッチの勾配を計算する前に、勾配をゼロに設定することを忘れないでください。

See also

torch.nnパッケージは、いくつかの一般的な損失関数を提供します。 サポートされている損失関数のリストについては、次のリンクにアクセスしてください。 https://pytorch.org/docs/stable/nn.html

torch.optimパッケージの詳細については、次のリンクにアクセスしてください。 https://pytorch.org/docs/stable/optim.html

Training and evaluation

すべての材料の準備ができたら、モデルのトレーニングを開始できます。 このレシピでは、ディープラーニングモデルを適切にトレーニングして評価する方法を学びます。

How to do it...

バッチ処理とエポック処理のヘルパー関数を開発し、モデルをトレーニングします。 始めましょう:

  1. ミニバッチあたりの損失値を計算するヘルパー関数を開発しましょう:
  2. 次に、ミニバッチごとの精度を計算するヘルパー関数を定義します。
  3. 次に、データセットの損失とメトリック値を計算するヘルパー関数を定義します。
  4. 最後に、train_val関数を定義します。
  5. いくつかのエポックについてモデルをトレーニングしましょう:

次のコードに示すように、トレーニングが開始され、進行状況が表示されます。

次のセクションでは、モデルを保存およびロードする方法を示します。

Storing and loading models

トレーニングが完了したら、トレーニングしたパラメータをファイルに保存して、導入および将来の使用に備えます。 これには2つの方法があります。

最初の方法を見てみましょう:

  1. まず、モデルパラメータまたはstate_dictをファイルに保存します。
  2. ファイルからモデルパラメータを読み込むために、Netクラスのオブジェクトを定義します。
  3. 次に、state_dictをファイルからロードします。
  4. 次に、state_dictをモデルに設定します。

次に、2番目の方法を見てみましょう。

  1. まず、モデルをファイルに保存します。
  2. ファイルからモデルパラメータを読み込むために、Netクラスのオブジェクトを定義します。
  3. 次に、ローカルファイルからモデルをロードします。

次のセクションでは、モデルをデプロイする方法を示します。

Deploying the model

モデルをデプロイするには、前のセクションで説明した方法を使用してモデルをロードする必要があります。 モデルがメモリに読み込まれたら、新しいデータをモデルに渡すことができます。 始めましょう:

  1. 検証データセットのサンプル画像にモデルをデプロイするには、サンプルテンソルを取得します。

    次のスクリーンショットにサンプル画像を示します。
  2. 次に、テンソルを前処理します。
  3. 次に、モデル予測を取得します。

    上記のコードを実行すると、モデル予測とグラウンドトゥルースラベルが出力されます。

次のセクションでは、各ステップについて詳しく説明します。

How it works...

最初に、ミニバッチあたりの損失とメトリック値を計算するヘルパー関数を開発しました。 関数のopt引数はオプティマイザを参照します。 指定した場合、勾配が計算され、モデルパラメータがミニバッチごとに更新されます。

次に、パフォーマンスメトリックを計算するヘルパー関数を開発しました。 パフォーマンスメトリックは、タスクに応じて定義できます。 ここでは、分類タスクの精度メトリックを選択しました。 output.argmaxを使用して、確率が最も高い予測クラスを取得しました。

次に、データセット全体の損失とメトリック値を計算するヘルパー関数を定義しました。 データローダーオブジェクトを使用してミニバッチを取得し、モデルにフィードして、ミニバッチごとの損失とメトリックを計算しました。 2つの実行変数を使用して、損失とメトリック値を追加しました。

次に、複数のエポックについてモデルをトレーニングするヘルパー関数を定義しました。 各エポックでは、検証データセットを使用してモデルのパフォーマンスも評価しました。 それぞれmodel.train()とmodel.eval()を使用してトレーニングモードと評価モードでモデルを設定することに注意してください。 さらに、torch.no_grad()を使用して、autogradが評価中に勾配を計算しないようにしました。

次に、トレーニング済みモデルを保存する2つの方法を検討しました。 最初のメソッドでは、state_dictまたはモデルパラメータのみを保存しました。 デプロイのためにトレーニング済みモデルが必要なときはいつでも、モデルのオブジェクトを作成し、 ファイルからパラメーターをロードして、パラメーターをモデルに設定する必要があります。 これは、PyTorchの作成者が推奨する方法です。

2番目の方法では、モデルをファイルに保存しました。 つまり、モデルとstate_dictの両方を1つのファイルに格納しました。 デプロイ用のトレーニング済みモデルが必要なときはいつでも、Netクラスのオブジェクトを作成する必要があります。 次に、ファイルからモデルをロードしました。 したがって、以前の方法と比較して、これを行うことの実際の利点はありません。

次に、検証データセットのサンプル画像にモデルをデプロイしました。 サンプル画像の形状はC * H * Wです。 したがって。 1 * C * H * Wになる新しい次元を追加しました。 次に、テンソルタイプをtorch.float32に変換し、CUDAデバイスに移動しました。

Tip: モデルとデータがデプロイ時に同じデバイスでホストされていることを確認してください。そうしないと、エラーが発生します。

There's more...

深層学習モデルをトレーニングするには、直感を発達させる必要があります。 次の章では、過学習を回避してパフォーマンスを向上させるための早期停止や学習率のスケジュールなどの他の手法を紹介します。