はじめに:LeNetとは?
LeNet(ルネット)は、現代のAI、特に画像認識技術の基礎を築いた、非常に重要な畳み込みニューラルネットワーク(CNN)のモデルです。 1998年に、後に「ディープラーニングの父」の一人と呼ばれるヤン・ルカン氏らによって発表されました。
当時は、コンピューターが画像の中のモノを正確に識別することは非常に困難な課題でした。LeNetは、特に手書き数字の認識という分野で、その高い精度を証明し、CNNが画像認識タスクに対して非常に有効であることを世界に示しました。 この成功が、今日の自動運転技術や顔認証システムなど、様々な画像認識AIの発展につながる出発点となったのです。
LeNetの画期的な構造
LeNetが画期的だったのは、その構造にあります。人間の脳が視覚情報を処理する方法にヒントを得ており、以下の2つの重要な層を交互に組み合わせているのが特徴です。
- 畳み込み層 (Convolutional Layer): 画像の上を「フィルター」と呼ばれる小さな窓をスライドさせながら、エッジや線、模様といった画像内の局所的な特徴を抽出します。 これにより、画像全体のピクセルを一度に見るのではなく、部分的な特徴を捉えることができます。
- プーリング層 (Pooling Layer / Subsampling Layer): 畳み込み層で抽出した特徴マップを縮小する層です。 画像のサイズを小さくして計算量を減らすと同時に、多少の位置のズレがあっても同じ特徴として認識できるようにする役割(位置不変性)を持ちます。
これらの層を通過させた後、最終的に全結合層 (Fully Connected Layer)で、抽出されたすべての特徴を統合し、「画像がどの数字であるか」を分類・判断します。 この「畳み込みとプーリングを繰り返して特徴を抽出し、最後に全結合層で分類する」という流れは、現代の多くのCNNモデルでも採用されている基本的な構造です。
代表的なモデル「LeNet-5」
一般的に「LeNet」という場合、1998年に発表された「LeNet-5」という7層構造のモデルを指すことが多いです。 LeNet-5は、手書き数字データセット「MNIST」で非常に高い認識精度を達成し、その実用性を示しました。 実際に、米国の郵便局で郵便番号の自動読み取りに利用されるなど、実社会でも活躍しました。
LeNet-5の構造は以下のようになっています。
層の種類 | 処理内容 | 主な役割 |
---|---|---|
入力層 | 32×32ピクセルのグレースケール画像 | 認識したい手書き数字の画像を入力 |
C1: 畳み込み層 | 5×5のフィルター6種類で畳み込み | エッジや線などの基本的な特徴を抽出 |
S2: プーリング層 | 2×2の領域で平均プーリング | 特徴の位置ズレを吸収し、データを圧縮 |
C3: 畳み込み層 | 5×5のフィルター16種類で畳み込み | より複雑な特徴(線の組み合わせなど)を抽出 |
S4: プーリング層 | 2×2の領域で平均プーリング | 再度、位置ズレを吸収し、データを圧縮 |
C5: 全結合層 (畳み込み) | 120個のニューロンに接続 | 分類のための特徴をさらに整理 |
F6: 全結合層 | 84個のニューロンに接続 | 特徴を統合し、分類の準備 |
出力層 | 10クラス(0~9)に分類 | 最終的な認識結果を出力 |
現代のCNNと比較すると、活性化関数にReLUではなくtanh関数が使われていたり、プーリングにMaxプーリングではなく平均プーリングが使われているなどの違いはありますが、その基本的な思想は受け継がれています。
LeNetをPyTorchで実装してみよう
LeNetは、構造が比較的シンプルなため、ディープラーニングの学習用として現在でもよく利用されます。 ここでは、人気の深層学習フレームワークであるPyTorchを使って、LeNet-5を簡易的に実装する例を紹介します。
import torch
import torch.nn as nn
import torch.nn.functional as F
class LeNet5(nn.Module): def __init__(self): super(LeNet5, self).__init__() # 畳み込み層 (入力チャネル数1, 出力チャネル数6, カーネルサイズ5x5) self.conv1 = nn.Conv2d(1, 6, 5) # 畳み込み層 (入力チャネル数6, 出力チャネル数16, カーネルサイズ5x5) self.conv2 = nn.Conv2d(6, 16, 5) # 全結合層 # 16チャネルで5x5の特徴マップを平坦化 -> 120次元 self.fc1 = nn.Linear(16 * 5 * 5, 120) # 120次元 -> 84次元 self.fc2 = nn.Linear(120, 84) # 84次元 -> 10次元 (0-9の10クラス) self.fc3 = nn.Linear(84, 10) def forward(self, x): # 畳み込み -> 活性化関数(ReLU) -> プーリング x = F.max_pool2d(F.relu(self.conv1(x)), (2, 2)) # 畳み込み -> 活性化関数(ReLU) -> プーリング x = F.max_pool2d(F.relu(self.conv2(x)), 2) # データを1次元に平坦化(flatten) x = torch.flatten(x, 1) # 全結合層 -> 活性化関数(ReLU) x = F.relu(self.fc1(x)) x = F.relu(self.fc2(x)) # 出力層 x = self.fc3(x) return x
# モデルのインスタンスを作成
net = LeNet5()
print(net)
このコードはLeNetの骨格を定義するものです。実際に手書き数字を学習させるには、データセットを読み込み、損失関数や最適化アルゴリズムを設定してトレーニング処理を記述する必要があります。
まとめ
LeNetは、1998年に登場した古典的なモデルでありながら、その後のAIによる画像認識技術の発展に絶大な影響を与えた、まさに「原点」と言える存在です。 畳み込み層とプーリング層を組み合わせるという革新的なアイデアは、AlexNet、VGG、ResNetといった現代の高性能なCNNモデルにも受け継がれています。
ディープラーニングや画像認識の歴史を学ぶ上で、LeNetは避けては通れない重要なマイルストーンです。そのシンプルな構造と基本的な考え方は、複雑な最新モデルを理解するための第一歩として、今なお多くのことを教えてくれます。