畳み込みニューラルネットワーク(CNN)は、現代のコンピュータビジョンの基盤であり、画像認識、顔検出、自動運転車などのアプリケーションを可能にしています。これらのネットワークは画像からパターンや特徴を自動的に抽出するよう設計されており、視覚タスクにおいて従来の機械学習技術よりも強力です。
このチュートリアルでは、研究や本番環境において使いやすく効率的なディープラーニングフレームワークであるPyTorchを使用してCNNを実装します。
前提条件:ディープラーニングとPyTorch
CNNの詳細に入る前に、ディープラーニングの分野と環境のセットアップ中に使用するPythonライブラリに精通している必要があります。
ディープラーニングは機械学習のサブセットであり、基本的なモデル構造は入力、隠れ層、出力のネットワークです。このようなネットワークには1つまたは複数の隠れ層が存在することができます。ディープラーニングの元の直感は、人間の脳が学習する方法に着想を得たモデルを作成することでした:ニューロンと呼ばれる相互接続された細胞によって。これが、私たちがディープラーニングモデルを「ニューラル」ネットワークと継続して呼ぶ理由です。これらの層状モデル構造は、他の教師付き学習モデルよりもはるかに多くのデータを学習する必要があり、非構造化データからパターンを導出するために通常、少なくとも数十万のデータポイントについて話します。
いくつかのフレームワークやパッケージが存在して深層学習アルゴリズムを実装するために使用されていますが、私たちは最も人気でメンテナンスが行き届いているフレームワークの1つであるPyTorchに焦点を当てます。PyTorchは産業界の深層学習エンジニアによって使用されるだけでなく、研究者の間でも好まれるツールです。多くの深層学習論文がPyTorchを使用して公開されています。PyTorchは直感的で使いやすいように設計されており、PythonライブラリNumPyと多くの共通点を共有しています。
これらの概念の基礎を理解したい場合は、今日からPyTorchでの深層学習コースに登録を検討してみてください。
畳み込みニューラルネットワーク(CNN)とは何ですか?
畳み込みニューラルネットワーク、一般的にCNNまたはConvNetと呼ばれるものは、コンピュータビジョンタスクに適した特定の種類の深層ニューラルネットワークです。CNNの発明は1980年代にさかのぼります。しかし、GPUの実装から生じたコンピューティングのブレークスルーに続いて、2010年代にメインストリームとなりました。実際、CNNの急速な普及は、ニューラルネットワークの分野が注目を浴びるようになり、現在も続くいわゆる「三番目のニューラルネットワークの波」を導いたのです。
CNNは具体的には生物学的な視覚皮質から着想を得ています。皮質には、視覚野の特定の領域に敏感な細胞の小さな領域があります。このアイデアは、1962年にHubelとWieselによる魅力的な実験によって拡張されました。
CNNは、異なるタスク固有の層から成る複雑なニューラルネットワークを作成することで、この特徴を再現しようとします。CNNは「フィードフォワード」と呼ばれ、情報がモデルを直接流れるため、他のバックプロパゲーションなどの手法を使用するモデルと比較して、モデルの出力が自身にフィードバックされるフィードバック接続はありません。
特に、CNNは通常、次の層から構成されています:
畳み込み層
これはCNNの最初の構成要素です。その名前が示すように、行われる主な数学的タスクは畳み込みと呼ばれ、画像を表すピクセルの行列にスライディングウィンドウ関数を適用することです。行列に適用されるスライディング関数はカーネルまたはフィルターと呼ばれます。畳み込み層では、同じサイズの複数のフィルターが適用され、各フィルターは画像から特定のパターンを認識するために使用されます。例えば、数字の曲線、エッジ、数字の全体的な形状などです。
活性化関数
通常、各畳み込み操作の後にReLU活性化関数が適用されます。この関数は、画像内の特徴間の非線形関係を学習するのに役立ち、異なるパターンを識別するためのネットワークをより堅牢にします。また、勾配消失問題を緩和するのにも役立ちます。
プーリング層
プーリング層の目標は、畳み込まれた行列から最も重要な特徴を抽出することです。これは、集約演算を適用することによって行われ、特徴マップ(畳み込まれた行列)の次元を削減し、ネットワークのトレーニング中に使用されるメモリを削減します。プーリングは過学習を緩和するのにも役立ちます。
完全に接続された層
これらの層は、畳み込みニューラルネットワークの最後の層にあり、その入力は最後のプーリング層によって生成された平坦化された一次元行列に対応しています。非線形性のためにReLU活性化関数が適用されます。
畳み込みニューラルネットワークアーキテクチャ。出典:DataCamp
CNNの数学的背景についての詳細な説明は、弊社のチュートリアル「Pythonにおける畳み込みニューラルネットワーク」で読むことができます。
画像分類にCNNを使用する理由は何ですか?
畳み込みニューラルネットワークは、コンピュータビジョン分野で最も影響力のある革新の1つとなっています。従来の機械学習モデル(SVMsや決定木など)よりも優れたパフォーマンスを発揮し、最先端の結果を生み出しています。
さらに、畳み込み層によってCNNには位置、向き、スケール、翻訳の変動に関係なくデータからパターンや特徴を特定・抽出する移動不変特性が与えられています。
CNNは、画像分類、物体検出、セグメンテーション、顔認識などのさまざまな実践事例や応用で成功を収めています:
- 画像分類、物体検出、セグメンテーション、顔認識;
- 畳み込みニューラルネットワークを活用する自動運転車;
- 畳み込みニューラルネットワークを用いた結晶構造の分類;
- セキュリティカメラシステム。
画像分類タスク以外にも、CNNは多目的であり、自然言語処理、時系列解析、音声認識などさまざまな分野に適用することができます。
PyTorchを使用してCNNを実装
CNNの理論に慣れたので、いよいよ実際の作業に取り掛かる準備が整いました。このセクションでは、PyTorchを使用してシンプルなCNNを構築し、トレーニングします。私たちの目標は、画像内の数字を分類するモデルを構築することです。モデルのトレーニングとテストには、有名なMNISTデータセットを使用します。これは手書き数字の70,000枚のグレースケール、28×28の画像のコレクションです。
1. 必要なライブラリのインポート
以下に、このチュートリアルで使用するライブラリが記載されています。基本的に、PyTorchを活用してCNNを構築し、PyTorchのコンピュータビジョンモジュールtorchvision
を使用してMNISTデータセットをダウンロードおよびロードします。最後に、モデルのパフォーマンスを評価するためにtorchmetrics
も使用します。
import numpy as np import pandas as pd import matplotlib.pyplot as plt import torch from torch import optim from torch import nn from torch.utils.data import DataLoader from tqdm import tqdm # !pip install torchvision import torchvision import torch.nn.functional as F import torchvision.datasets as datasets import torchvision.transforms as transforms # !pip install torchmetrics import torchmetrics
2. データセットの読み込みと前処理
PyTorchには、コンピュータビジョン向けのモジュールであるtorchvisionを含む多くのツールや拡張機能があります。Torchvisionには、トレーニングやテストに使用できるいくつかの画像データセットが含まれています。このチュートリアルでは、MNISTデータセットを使用します。
まず、MNISTデータセットをダウンロードしてテンソルに変換します。テンソルは、PyTorchの中心的なデータ構造であり、NumPy配列と似ていますがGPUアクセラレーションの機能を備えています。
その後、トレーニングデータセットとテストデータセットの両方をバッチ処理およびシャッフリングするためにDataLoaderも使用します。 PyTorchのDataLoaderは、データを読み込み、バッチに分割し、必要に応じてデータに変換を行うためにデータセットから作成できます。 その後、トレーニング用にデータサンプルを提供します。以下のコードでは、データを読み込んで、バッチサイズが60の画像でDataLoaderに保存します。
batch_size = 60 train_dataset = datasets.MNIST(root="dataset/", download=True, train=True, transform=transforms.ToTensor()) train_loader = DataLoader(dataset=train_dataset, batch_size=batch_size, shuffle=True) test_dataset = datasets.MNIST(root="dataset/", download=True, train=False, transform=transforms.ToTensor()) test_loader = DataLoader(dataset=test_dataset, batch_size=batch_size, shuffle=True)
オプションで、トレーニングデータセットをさらにトレーニングと検証の2つのパーティションに分割することができます。 検証は、トレーニング中のモデルパフォーマンスを評価するために使用されるディープラーニングのテクニックです。 モデルの過学習や適合不足を検出するのに役立ち、ハイパーパラメータを最適化するのに特に役立ちます。 ただし、このチュートリアルではシンプルさのため、検証は使用しません。 検証について詳しく知りたい場合は、PyTorchコースでディープラーニング入門で完全な説明をチェックできます。
データが揃ったので、ランダムな数字のバッチがどのように見えるかを見てみましょう。
def imshow(img): npimg = img.numpy() plt.imshow(np.transpose(npimg, (1, 2, 0))) plt.show() # いくつかのランダムなトレーニング画像を取得 dataiter = iter(dataloader_train) images, labels = next(dataiter) labels # 画像を表示 imshow(torchvision.utils.make_grid(images))
3. CNNアーキテクチャの定義
分類問題を解決するために、nn.Module
クラスを活用します。これは、洗練されたニューラルネットワークアーキテクチャを直感的に作成するためのPyTorchの基本構造要素です。
以下のコードでは、CNN
というクラスを作成し、nn.Module
クラスのプロパティを継承します。CNN
クラスは、2つの畳み込み層に続く全結合層を持つCNNの設計図となります。
PyTorchでは、畳み込み層を定義するためにnn.Conv2d
を使用します。入力と出力の特徴マップの数を渡します。また、カーネルサイズやパディングなど、畳み込み層の動作に必要ないくつかのパラメータを設定します。
次に、nn.MaxPool2d
を使用してMaxプーリング層を追加します。前の畳み込み層の出力に非オーバーラップのウィンドウをスライドさせます。各位置で、ウィンドウから最大値を選択して前に進めます。この操作により、特徴マップの空間次元が削減され、ネットワーク内のパラメータおよび計算の複雑さが削減されます。最後に、全結合の線形層を追加します。
forward()
関数は、異なる層がどのように接続されるかを定義し、各畳み込み層の後にいくつかのReLU活性化関数を追加します。
class CNN(nn.Module): def __init__(self, in_channels, num_classes): """ Building blocks of convolutional neural network. Parameters: * in_channels: Number of channels in the input image (for grayscale images, 1) * num_classes: Number of classes to predict. In our problem, 10 (i.e digits from 0 to 9). """ super(CNN, self).__init__() # 1番目の畳み込み層 self.conv1 = nn.Conv2d(in_channels=in_channels, out_channels=8, kernel_size=3, padding=1) # 最大プーリング層 self.pool = nn.MaxPool2d(kernel_size=2, stride=2) # 2番目の畳み込み層 self.conv2 = nn.Conv2d(in_channels=8, out_channels=16, kernel_size=3, padding=1) # 完全に接続された層 self.fc1 = nn.Linear(16 * 7 * 7, num_classes) def forward(self, x): """ Define the forward pass of the neural network. Parameters: x: Input tensor. Returns: torch.Tensor The output tensor after passing through the network. """ x = F.relu(self.conv1(x)) # 最初の畳み込みとReLUアクティベーションを適用 x = self.pool(x) # 最大プーリングを適用 x = F.relu(self.conv2(x)) # 2番目の畳み込みとReLUアクティベーションを適用 x = self.pool(x) # 最大プーリングを適用 x = x.reshape(x.shape[0], -1) # テンソルをフラット化 x = self.fc1(x) # 完全に接続された層を適用 return x x = x.reshape(x.shape[0], -1) # テンソルをフラット化 x = self.fc1(x) # 完全に接続された層を適用 return x
定義したCNN
クラスがあれば、モデルを作成して、そのモデルがトレーニングおよび実行されるデバイスに移動させることができます。
GPU上で実行される場合、CNNを含むニューラルネットワークはより良いパフォーマンスを示しますが、あなたのコンピューターでそのようになるとは限りません。したがって、利用可能な場合にのみモデルをGPU上で実行します。それ以外の場合は通常のCPUを使用します。
device = "cuda" if torch.cuda.is_available() else "cpu" model = CNN(in_channels=1, num_classes=10).to(device) print(model) >>> CNN( (conv1): Conv2d(1, 8, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (pool): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) (conv2): Conv2d(8, 16, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (fc1): Linear(in_features=784, out_features=10, bias=True) )
CNNモデルのトレーニング
モデルができたので、訓練を行う時が来ました。そのためにまず、モデルの性能を測定する方法を決定する必要があります。多クラス分類の問題に取り組んでいるので、PyTorchでnn.CrossEntropyLoss
として利用可能な交差エントロピー損失関数を使用します。また、最も人気のある最適化アルゴリズムであるAdamオプティマイザも使用します。
# 損失関数を定義 criterion = nn.CrossEntropyLoss() # オプティマイザを定義 optimizer = optim.Adam(model.parameters(), lr=0.001)
10のエポックとトレーニングバッチを繰り返して、モデルを訓練し、各バッチについて通常の手順を実行します。
num_epochs=10 for epoch in range(num_epochs): # トレーニングバッチを繰り返す print(f"Epoch [{epoch + 1}/{num_epochs}]") for batch_index, (data, targets) in enumerate(tqdm(dataloader_train)): data = data.to(device) targets = targets.to(device) scores = model(data) loss = criterion(scores, targets) optimizer.zero_grad() loss.backward() optimizer.step()
Epoch [1/10] 100%|██████████| 1000/1000 [00:13<00:00, 72.94it/s] Epoch [2/10] 100%|██████████| 1000/1000 [00:12<00:00, 77.27it/s] Epoch [3/10] 100%|██████████| 1000/1000 [00:12<00:00, 77.16it/s] Epoch [4/10] 100%|██████████| 1000/1000 [00:12<00:00, 77.00it/s] Epoch [5/10] 100%|██████████| 1000/1000 [00:13<00:00, 75.69it/s] Epoch [6/10] 100%|██████████| 1000/1000 [00:12<00:00, 77.24it/s] Epoch [7/10] 100%|██████████| 1000/1000 [00:12<00:00, 78.23it/s] Epoch [8/10] 100%|██████████| 1000/1000 [00:12<00:00, 78.16it/s] Epoch [9/10] 100%|██████████| 1000/1000 [00:12<00:00, 77.96it/s] Epoch [10/10] 100%|██████████| 1000/1000 [00:12<00:00, 77.93it/s]
5. モデルの評価
モデルが訓練されたら、テストデータセットでの性能を評価できます。分類問題において一般的な指標である精度を使用します。精度は、データセット内のオブジェクトの総数に対する正しく分類されたケースの割合を測定します。モデルによって行われた正しい予測の数を、モデルが行った予測の総数で割ることによって計算されます。
まず、torchmetricsから精度メトリックを設定します。次に、モデルの.evalメソッドを使用して、モデルを評価モードに設定します。なぜなら、PyTorchモデルの一部のレイヤーは、トレーニングとテストの段階で異なる動作をするからです。また、torch.no_grad
を使用して、勾配の計算を行わないことを示すPythonコンテキストを追加します。
その後、勾配の計算を行わながらテスト例を繰り返します。各テストバッチに対して、モデルの出力を取得し、最も可能性の高いクラスを取得して、ラベルと共に精度関数に渡します。最後に、メトリックを計算して結果を表示します。私たちは0.98の精度スコアを得ました。これは、モデルが数字の98%を正しく分類したことを意味します。悪くないですね!
# マルチクラス精度メトリックの設定 acc = Accuracy(task="multiclass",num_classes=10) # データセットバッチを繰り返します model.eval() with torch.no_grad(): for images, labels in dataloader_test: # テストデータバッチの予測確率を取得します outputs = model(images) _, preds = torch.max(outputs, 1) acc(preds, labels) precision(preds, labels) recall(preds, labels) # 総合テスト精度を計算します test_accuracy = acc.compute() print(f"Test accuracy: {test_accuracy}") >>> Test accuracy: 0.9857000112533569
他の一般的な分類メトリック、リコールや精度を使用することもできます。当社のPyTorch中級ディープラーニングコースで、これらのメトリックについて実践的な例をすべて紹介します。
モデルのパフォーマンスを向上させる
CNNモデルは強力なパフォーマンスを発揮していますが、その精度、頑健性、および新しいデータへの汎化をさらに向上させるために使用できるいくつかの戦略があります。
このセクションでは、データ拡張、ハイパーパラメータの調整、転移学習などの主要なテクニックを探求して、モデルのパフォーマンスを最適化します。
データ拡張技術
データ拡張は、新しいトレーニングデータをランダムに作成することで、モデルの精度を向上させるために使用される技術です。例えば、読み込み中に、トレーニング画像にリサイズ、水平または垂直反転、ランダムな回転などの変換を適用することができます。このようにして拡張された画像を作成し、元の画像と同じラベルを割り当てることで、トレーニングセットのサイズを増やすことができます。
元の画像にランダムな変換を追加することで、データをより多く生成し、トレーニングセットのサイズと多様性を増やすことができます。これにより、モデルは実世界の画像に一般的に見られる変動や歪みに対してより頑丈になり、モデルがランダムな変換を無視するように学習することで過学習が軽減されます。
ただし、データ拡張には注意が必要です。時にはトレーニングプロセスに悪影響を及ぼすことがあります。例えば、問題によっては、数字「6」に垂直反転を適用すると数字「9」のように見えることがあります。それを「6」としてモデルに渡すと、モデルが混乱しトレーニングが妨げられます。これらの例は、特定の拡張がラベルに影響を及ぼすことがあることを示しています。
ハイパーパラメータの調整
モデルのパフォーマンスを向上させる別の戦略は、モデルの異なる層に関与するハイパーパラメータの値を変更することです。このハイパーパラメータチューニングには、ニューラルネットワークの数学的背景や異なるハイパーパラメータの重要性を深く理解する必要があります。
たとえば、CNN層のフィルタサイズを変更したり、パディングを増やしたりしてチューニングすることができます。また、ニューロンの初期重みに異なる値を設定することもできます。
事前に最適なハイパーパラメータの値を知ることができないため、ある程度の試行錯誤が必要になります。これは通常、グリッドサーチとして知られる技術を使用して行われます。これにより、パラメータ値のグリッド全体でモデルを系統的に評価することができます。
ただし、この技術を使用する際には注意が必要です。特に、複雑なニューラルネットワークや大規模なトレーニングデータセットを扱う場合は、通常、計算コストが高くなります。
同様に、畳み込み層や線形層を追加することでモデルの複雑さを増すこともできます。ただし、新しい層を追加する際には注意が必要です。ニューロンの数が急激に増える可能性があり、トレーニング時間が長くなり、過学習の可能性があります。
PyTorchコースへのディープラーニング入門でハイパーパラメータチューニングについて詳しく学ぶことができます。
事前トレーニング済みモデル
ディープラーニングモデルをゼロからトレーニングすることは、長くて退屈なプロセスであり、通常は多くのトレーニングデータが必要です。代わりに、私たちはしばしば事前にトレーニングされたモデル、つまりすでにあるタスクでトレーニングされたモデルを使用することができます。
時々、私たちは、すでに私たちが気にしているタスクを解決できる場合、事前にトレーニングされたモデルを直接再利用することができます。他の場合には、新しいタスクに適合するように事前にトレーニングされたモデルを調整する必要があるかもしれません。これは転移学習として知られています。
PyTorchで事前にトレーニングされたモデルを使用することはかなり簡単です。Torchvisionは、さまざまな画像関連タスク用に事前にトレーニングされたモデルのコレクションを提供しています。これらのモデルは大規模な画像データセットで事前にトレーニングされており、簡単に利用できます。詳細については、PyTorchコースで画像のディープラーニングをチェックしてください。
CNNモデルの展開
PyTorchで非常に正確な分類モデルをトレーニングしたら、モデルとその事前にトレーニングされた重みを保存して将来の使用やチームと共有できるようにすることができます。
モデルを保存するには、torch.save
を使用できます。torchモデルの一般的なファイル拡張子はpt
またはpth
です。モデルの重みを保存するには、model.state_dict
をtorch.save
に渡し、出力ファイル名を指定します。たとえば、MulticlassCNN.pth
です。
保存されたモデルをロードするには、同じアーキテクチャで新しいモデルを初期化します。その後、torch.load
を使用してパラメータを新しいモデルにロードするために、load state dict
メソッドを使用します。
# モデルを保存する torch.save(model.state_dict(), 'MulticlassCNN.pth') # 新しいモデルを作成する loaded_model = CNN(in_channels=1, num_classes=10) # 保存されたモデルをロードする loaded_model.load_state_dict(torch.load('MulticlassCNN.pth')) print(loaded_model) CNN( (conv1): Conv2d(1, 8, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (pool): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) (conv2): Conv2d(8, 16, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (fc1): Linear(in_features=784, out_features=10, bias=True) )
結論
私たちはCNNの完全な概要をカバーし、CNNアーキテクチャの各レイヤーについて詳細を提供しました。さらに、PyTorchでCNNを実装する方法についてのガイドを提供し、データのロードやモデル設計からモデルのトレーニングと評価までの主要なステップをカバーしました。最後に、モデルのパフォーマンスを向上させるためのいくつかの戦略も分析しました。これらのスキルセットを、マルチクラス分類タスクに関連する実世界のシナリオに適用しました。
ディープラーニングについてはたくさんのことを学ぶことができ、AI分野で最もエキサイティングで要求の高い分野の1つと言えるでしょう。幸いにも、DataCampがお手伝いします。専用の教材やコースをチェックして、ニューラルネットワークの専門家になりましょう:
Source:
https://www.datacamp.com/tutorial/pytorch-cnn-tutorial