LeNetネットワーク(1989年提案、1998年改良)
1. LeNet ネットワークの概要
ルネット:
LeNet畳み込みニューラル ネットワークのプロトタイプ: 1989 年に、LeCun らは手書き郵便番号用の畳み込みニューラル ネットワークを設計し、バックプロパゲーション アルゴリズムを使用して畳み込みニューラル ネットワークをトレーニングし、それを米国郵便公社に適用しました。
パフォーマンス: LeNet ネットワークは優れたパフォーマンスを備えており、郵便番号デジタル データ セットのテスト結果では、ネットワーク エラー率がわずか 1% であることが示されています。
制限: 当時のコンピューターのハードウェア機能の制限により、畳み込みニューラル ネットワークの規模をこれ以上拡大することができず、より複雑なタスクや大規模なデータ セットでの開発が制限され、広く注目を集めることができませんでした。
LeNet-5 ネットワーク:古典的で先駆的な作品であり、畳み込みニューラル ネットワークのパイオニアです。
用途: 最初はコンピュータ ビジョンの問題に対処するために使用され、手書き数字の認識精度において非常に優れた結果を達成しました。
開発:改良版LeNet-5 が1998 年に登場しました。
1998 年の論文: 「文書認識に適用された勾配ベースの学習」 - Yann LeCun et al。
主に手書き文字認識に使用されます。
ステータス: 畳み込み層、プーリング層、全結合層、その他のディープ ニューラル ネットワークの基本モジュールを含む、他のディープ ネットワーク モデルを学習するための基礎として使用できる層はほとんどありません。
LeNet-5 ネットワーク構造如图0
を次の図に示します。
図0
LeNet-5ネットワークは、左からINPUT層、C1層、S2層、C3層、S4層、C5層、F6層、OUTPUT層となっています。
これには、入力層、2 つの畳み込み層 (Convolutions)、2 つのプーリング層 (プーリング/ダウンサンプリング層、サブサンプリング)、および 3 つの完全接続層 (フル接続) の合計が含まれます。
入力は 32×32×1 のグレースケール画像で、出力には 0 ~ 9 の 10 個の手書き文字を表す 10 個のカテゴリがあります。
以下は階層的な紹介です。
(1) INPUT層(入力層)
デフォルトの入力データは、32×32×1 グレースケール イメージ、つまり高さと幅が 32 の単一カラー チャネル イメージである必要があります。
実際、入力画像の元のサイズは 28×28 ピクセルで、文字サイズは 20×20 ピクセルを超えませんが、ここでは、畳み込み層後のエッジが確実に表示されるように、入力画像を 32×32 ピクセルに仕上げます。画像の情報が失われることはありません。
(2) C1層(最初の畳み込み層)
使用される畳み込みスライディング ウィンドウのサイズは 5×5×1、ストライドは 1、パディングは使用されません。
套用卷积の一般公式:
出力 = [ (入力 − フィルター サイズ + 2 ∗ パディング ) / ストライド ] + 1 出力 = [(入力フィルター サイズ + 2 * パディング)/ストライド] + 1出力する_ _ _=[ (入力_ _−フィルターサイズ_ _ _ _ _+2∗パディング) /ストライド] _ _ _ _ _ _ _ _ _+1
出力特徴マップの高さと幅は 28=[(32-5+2*0)/1]+1 です。
同時に、図 0 から、この畳み込み層の最終的に必要な深さは、深さ 6 の特徴マップを出力することであるため、同じ畳み込み演算 (6 つの畳み込みカーネル) を 6 回実行する必要があることがわかります。最終的な出力特徴マップは次のようになります。寸法は 28×28×6 です。
畳み込みの層の後、画像のサイズは小さくなりますが、深さは増加します。
(3) S2層(第1プーリング層/ダウンサンプリング層/アグリゲーション層)
ダウンサンプリング層の機能: 入力特徴マップのサイズを縮小します。ここでは、最大プーリング層がダウンサンプリングに使用されます。
入力特徴マップの次元は 28×28×6 です。
S2 層のサンプリング方法は特別であり、学習可能なパラメータが含まれています。形式的には、畳み込みカーネル サイズ 2*2およびストライド 2の非重複畳み込みに似ています。
違いは、出力が次のようになることです。
2×2 内の 4 つの入力データ xi については、最初に合計され、次にトレーニング可能なパラメーター w とトレーニング可能なバイアス b が乗算され、その結果がシグモイド関数を通じてアクティブ化されます。
入力は 6 チャネル データであるため、S2 層には 6 つの学習可能なコンピューティング コアと合計 12 の学習可能なパラメーターがあります。
さらに、S2 層には本質的に活性化層が含まれており、使用される活性化関数はシグモイド関数です。
出力特徴マップ サイズ: [(28-2+2×0)/2]+1=14
最終的な出力特徴マップの次元は 14×14×6 です。
この論文が書かれた時代では、人々は一般に平均プーリング方式を使用することを好んでいたため、LeNet-5 ネットワークのすべてのプーリング操作は平均プーリングを使用していました。
注:プーリング操作では、機能マップの深さは変わりません。つまり、チャネルの数は変わりません。
(4) C3層(第2畳み込み層)
コンボリューション カーネル: 5×5×6 入力特徴マップの次元は 14×14×6 であるため、コンボリューション カーネル ウィンドウの深さは入力特徴マップの深さと一致する必要があります。
ステップ サイズは 1 で、パディングは使用されません。
出力特徴マップ サイズ: [(14-5+2×0)/1]+1=10
同時に、この畳み込み層は深さ 16 の最終出力特徴マップを必要とするため、16 の畳み込みが必要となり、最終出力特徴マップの次元は次のようになります。
10×10×16
(5) S4層(第2プーリング層/ダウンサンプリング層/アグリゲーション層)
入力特徴マップは、C3 によって出力された 10×10×16 の次元の特徴マップです。
スライディング ウィンドウのサイズは 2 × 2 × 16 で、ステップ サイズは 2 です。
出力特徴マップの高さと幅: [(10-2+2×0)/2]+1=5
最終的な出力特徴マップの次元は 5×5×16 です。
(6) C5層(第1全結合層)
畳み込みプーリング層とそれに続く全結合層の間の最初の中間層/隠れ層であり、第 3 の畳み込み層とみなすことができます。120 個のニューロンで構成されています。活性化関数は Tanh または Sigmoid 関数を使用します。
入力特徴マップの次元は 5×5×16 です
畳み込みカーネルのスライディング ウィンドウ サイズ: 5×5×16、ステップ サイズは 1、パディングは使用されません。
最終的な出力特徴マップの高さと幅: [(5-5+2×0)/1]+1=1
同時に、この畳み込み層は深さ 120 の最終出力特徴マップを必要とするため、120 回の畳み込みが必要です。最終出力特徴マップの次元は 1×1×120 で、実際には 2 次元の平坦化が実現されます。データ。
(7) F6層(第2全結合層)
これは、畳み込みプーリング層とそれに続く全結合層の間の 2 番目の中間/隠れ層です。84 個のニューロンで構成され、活性化関数は前の層と同じ Tanh または Sigmoid 関数です
入力データは、1×1×120 の次元の特徴マップです。
最後に、深さ 84 の特徴マップを出力する必要があるため、この層のタスクは入力特徴マップを圧縮し、最終的に 1×84 の次元の特徴マップを取得することです。
このプロセスを完了するには、入力特徴マップに 120×84 の次元の重みパラメータを乗算する必要があります。
行列演算規則によると、[1×120]×[120×84]=[1×84]
出力ノードの数は 84 です。特徴マップがサイズ 7×12=84 の ASCII コード ビット イメージにマッピングされるため、84 が選択されます。
各画像では、-1 が白、1 が黒を表すため、各シンボルのビットマップの黒と白がコードに対応します。
出力特徴マップ: 次元 1×84 の行列
(8) OUTPUT層(出力層/全結合層)
出力層も、それぞれ 0 ~ 9 の数字を表す合計 10 個のノードを持つ全結合層です。
LeNet-5 は分類問題を解くために使用されるため、入力画像に基づいて画像内の手書き数字のカテゴリを決定する必要があり、出力結果は入力画像が 10 個のカテゴリに該当する可能性があります。
その前に、F6 層で入力された 1 84 次元のデータを 1 × 10 次元のデータに圧縮する必要がありますが、これは 84 × 10 次元の行列に依存することで完成します。(出力層には 84 10=840 のパラメーターと接続があります)
[1×84]×[84×10]=[1×10]
最終的に得られた 10 個のデータをすべて Softmax 活性化関数に入力すると、モデルによって予測された入力画像に対応する 10 個のカテゴリの可能性値が得られます。
LeNet-5 ネットワーク構造の概要:
(1) C1 層は 6 つの 5×5 コンボリューション カーネルを使用し、ステップ サイズ 1 でコンボリューションを実行します。活性化関数は Tanh または Sigmoid 関数を使用し、バイアス値を持ちます。
(2) S2層は2×2の平均プーリングを行う
(3) C3 層は 16 個の 5×5 コンボリューション カーネルを使用し、ステップ サイズ 1 でコンボリューションを実行します。活性化関数は Tanh または Sigmoid 関数を使用し、バイアス値を持ちます。
(4) S4層は2×2の平均プーリングを行う
(5) C5 層には 120 個のニューロンがあり、活性化関数は Tanh または Sigmoid 関数を使用し、バイアス値を持ちます。
(6) F6 層には 84 個のニューロン、Tanh または Sigmoid 関数があり、バイアス値があります。
(7) 分類器には 10 個の分類出力があります
レイヤー名 | 入力 | カーネルサイズ | kernel_num | ストライド | パディング | 出力 |
---|---|---|---|---|---|---|
C1層(畳み込み層) | 32×32×1 | 5×5 | 6 | 1 | 0 | [(32-5+2×0)/1]+1=28 28×28×6 |
S2層(プーリング層) | 28×28×6 | 2×2 | 6 | 2 | 0 | [(28-2+2×0)/2]+1=14 14×14×6 |
C3層(畳み込み層) | 14×14×6 | 5×5 | 16 | 1 | 0 | [(14-5+2×0)/1]+1=10 10×10×16 |
S4層(プーリング層) | 10×10×16 | 2×2 | 16 | 2 | 0 | [(10-2+2×0)/2]+1=5 5×5×16 |
C5層(全結合層) | 5×5×16 | 5×5 | 16 | 1 | 0 | [(5-5+2×0)/1]+1=1 1×1×120 |
F6層(全結合層) | 1×1×120 | [1×120]×[120×84]=[1×84] 1×84 | ||||
出力層(全結合層) | 1×84 | [1×84]×[84×10]=[1×10] 1×10 |
2. LeNetネットワークコードの説明
画像分類:pytorch公式デモコード説明
参考:
ステーション b のブロガー @霹雳巴拉Wz: https://space.bilibili.com/18161609/channel/index
github:https://gitcode.net/mirrors/wzmiaomiao/deep-learning-for-image-processing?utm_source=csdn_github_accelerator
代码位置:\deep-learning-for-image-processing-master\pytorch_classification\Test1_official_demo
pytorch 公式 Web サイトの対応するコードが使用されます: https://pytorch.org/tutorials/beginner/blitz/cifar10_tutorial.html
このレッスンの主な内容:
- LeNet ネットワークのモデルを説明する
- pytorch を使用して LeNet モデルを構築しました
- CIFAR10 データセットの導入、データセットのダウンロード、およびデータセットの前処理
- データセットを表示し、LeNet モデルをインポートしました
- 定義された損失関数、オプティマイザー
- ネットワークトレーニングを実行し、トレーニングされた重みを保存します
- 予測のために、pridect.py スクリプトを通じて保存されたモデルの重みを呼び出します。
Pytorch Tenor のチャンネルソート: [バッチ、チャンネル、高さ、幅]
LeNet-5ネットワークの概略図の説明、如图0
図0
解説ページ:model.py
import torch.nn as nn
import torch.nn.functional as F
class LeNet(nn.Module):
def __init__(self):
super(LeNet, self).__init__()
#输入图像矩阵深度=3,输出图像矩阵深度/卷积核个数=16,卷积核大小5*5
self.conv1 = nn.Conv2d(3, 16, 5)
self.pool1 = nn.MaxPool2d(2, 2)#池化核2*2,步长=2
#输入图像矩阵深度=16(因为第一个卷积层输出矩阵深度为16,池化层不改变图像深度),输出图像矩阵深度/卷积核个数=32,卷积核大小5*5
self.conv2 = nn.Conv2d(16, 32, 5)
self.pool2 = nn.MaxPool2d(2, 2)#池化核2*2,步长=2
#全连接层 全连接层的输入是一个一维的向量,所以需要将得到的特征矩阵展平,展成一个一维的向量。
#图0中这一层的结点个数是120,所以第二个参数是120(120这个参数是自定义的)
self.fc1 = nn.Linear(32*5*5, 120)
#第二个全连接层的输入是第一个全连接层的输出:120个节点。
#图0中这一层设置的是84个节点,所以第二个参数是84(84这个参数是自定义的)
self.fc2 = nn.Linear(120, 84)
#最后一个全连接层的输入是上一层的输出:84个节点
#输出需要根据训练集来进行修改,因为今天使用的训练集是有10个类别的,所以第二个参数设置成10
self.fc3 = nn.Linear(84, 10)
#正向传播过程
#x代表输入的数据,数据就是pytorch Tensor的通道顺序:[batch,channel,height,width]
def forward(self, x):
#首先数据经过卷积层1(conv1),然后得到的输出通过relu激活函数
x = F.relu(self.conv1(x)) # input(3, 32, 32) output(16, 28, 28)
#然后再将上面的输出经过下采样一层(pool1)
x = self.pool1(x) # output(16, 14, 14)
#将上面的输出进入到第二个卷积层(conv2),然后得到的输出通过relu激活函数
x = F.relu(self.conv2(x)) # output(32, 10, 10)
#然后再将输出通过第二个下采样层(pool2)
x = self.pool2(x) # output(32, 5, 5)
#接下来要把数据放到全连接层中,但是全连接层的输入是一维向量。所以要把现在的向量展平成一维向量
#做法:使用.view函数展平向量,第一个参数-1代表第一个维度,进行自动推理(因为第一维是batch,所以设置成-1)第二个维度是展平后的节点的个数32*5*5
x = x.view(-1, 32*5*5) # output(32*5*5)
#全连接层1,如图0中,自定义了120个节点,所以第一个全连接层的输出是120
x = F.relu(self.fc1(x)) # output(120)
#全连接层2,自定义了输出是84个节点
x = F.relu(self.fc2(x)) # output(84)
#全连接层3,自定义了输出是10个节点
#输出需要根据训练集来进行修改,因为今天使用的训练集是有10个类别的,所以第二个参数设置成10
x = self.fc3(x) # output(10)
#为什么这里没有用softmax层(对于一般分类问题最后一个全连接层会跟上一个softmax层,将输出转化成为一个概率分布,理论上确实应该这么做,但是在我们训练网络过程中,计算卷积交叉熵的过程中已经实现了一个更加高效的softmax方法,所以在这里不需要添加softmax层了)
return x
pytorch でモデルを構築するプロセス:
-
親クラス nn.Module を継承する新しいクラス LeNet を作成します。
-
このクラスに 2 つのメソッドを実装します。
- 1 つは初期化関数です: def__ init__(self)
初期化関数は、ネットワークの構築プロセスで使用されるいくつかのネットワーク層構造を実装します。
まずはスーパー関数を使用します(多重継承がある限りスーパー関数が使用されます)。
- 最初の畳み込み層を定義する: nn.Conv2d 関数を使用して、pytorch で畳み込み層を定義します。
Ctrl キーを押しながら Conv2d をクリックします。
def __init__( self, in_channels: int, #输入图像矩阵的深度(RGB就是3) out_channels: int,#输出特征矩阵的深度=卷积核的个数 kernel_size: _size_1_t,#卷积核的大小 stride: _size_1_t = 1,#步长,默认为1 padding: Union[str, _size_1_t] = 0,#在四周进行补0处理,默认=0 dilation: _size_1_t = 1,#高阶用法 groups: int = 1,#高阶用法 bias: bool = True,#偏执,默认使用=True padding_mode: str = 'zeros', # TODO: refine this type device=None, dtype=None )
畳み込み後の行列サイズを計算する式は次のとおりです: N=(W-F+2P)/S+1
- 画像サイズ W×W を入力してください
- フィルタサイズ F×F (コンボリューションカーネルサイズ)
- ステップサイズS
- パディングPのピクセル数
したがって、最初の畳み込み層の出力は次のように計算されます。
- 入力サイズは 32×32、コンボリューション カーネル サイズは 5×5、ステップ サイズのデフォルトは 1、パディングのデフォルトは 0 です。
- 式を使用して N=28 を計算します。つまり、出力画像のサイズは 28×28 になります。
- 出力画像の深さ = コンボリューション カーネルの数 = 16
- したがって、出力画像サイズは 16×28×28 となります。
- ダウンサンプリング層 pool1 を定義します。使用されるメソッド: nn.MaxPool2d
Ctrl キーを押しながら MaxPool2d をポイントします。
class _MaxPoolNd(Module): __constants__ = ['kernel_size', 'stride', 'padding', 'dilation', 'return_indices', 'ceil_mode'] return_indices: bool ceil_mode: bool def __init__(self, kernel_size: _size_any_t, stride: Optional[_size_any_t] = None, padding: _size_any_t = 0, dilation: _size_any_t = 1, return_indices: bool = False, ceil_mode: bool = False) -> None: super().__init__() self.kernel_size = kernel_size #stride步长指定或者步长=卷积核大小 self.stride = stride if (stride is not None) else kernel_size self.padding = padding self.dilation = dilation self.return_indices = return_indices self.ceil_mode = ceil_mode
プーリングは特徴マトリックスの幅と高さを変更するだけであるため、チャネルは変更されません。
したがって、プーリング層後の出力行列の深さ = 16 (前の畳み込み層の出力は、このプーリング層の入力として機能します)
ステップ サイズ = 2 なので、出力画像サイズは入力の半分に縮小されます。入力は 28×28 なので、出力は 14×14 になります。
- 2 番目の畳み込み層 conv2 を定義します。nn.Conv2d 関数を使用します。
- 2 番目のプーリング層、pool2 を定義します。nn.MaxPool2d 関数を使用します。
- 1 つは、forward 関数で順方向伝播のプロセスを定義することです: def forward(self, x)
このクラスをインスタンス化した後、インスタンスにパラメータを渡すときに順方向伝播が実行されます (つまり、順方向の順序で実行されます)。
説明ページ:train.pyレイヤー
def main():
# transform这个函数首先通过transforms.Compose这个函数将所要使用的一些预处理方法给打包成为一个整体
# 在这里使用了两个预处理方法:
# 第一个是ToTensor,ctrl点进去看具体功能
transform = transforms.Compose(
[transforms.ToTensor(),
transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])
ToTensor 関数 Ctrl キーを押して次のように入力します。
class ToTensor: #这是一个把PIL图像或者ndarray转化成tensor的函数 """Convert a PIL Image or ndarray to tensor and scale the values accordingly. This transform does not support torchscript. # 导入的图片不管是通过PIL导入还是通过ndarray导入,所显示的数据图像的顺序是高度Height*宽度#Width*通道数/深度Channels。每个维度的像素值范围都是0-255 Converts a PIL Image or numpy.ndarray (H x W x C) in the range [0, 255] to a torch. #通过ToSensor这个函数把shape变成了通道数/深度Channels*高度Height*宽度#Width。 #并且将每个维度的像素值范围从0-255变成了0-1 FloatTensor of shape (C x H x W) in the range [0.0, 1.0] if the PIL Image belongs to one of the modes (L, LA, P, I, F, RGB, YCbCr, RGBA, CMYK, 1)
要約: テンソル関数:
入力画像の元のチャネル順序は、高さ×幅#幅×奥行きチャネルです。各次元のピクセル値の範囲は 0 ~ 255 です。
ToSensor機能により、深さチャンネル×高さ高さ×幅幅に形状が変化します。
そして、各次元のピクセル値の範囲を 0 ~ 255 から 0 ~ 1 に変更します。
正規化機能 Ctrl キーを押しながらクリックします:
class Normalize(torch.nn.Module): #使用均值和标准差来标准化我们的tensor #计算过程:输出=(原始数据-均值)/标准差 """Normalize a tensor image with mean and standard deviation. This transform does not support PIL Image. #提供的参数有均值mean,标准差std #这个模型将会标准化每个输入的通道 Given mean: ``(mean[1],...,mean[n])`` and std: ``(std[1],..,std[n])`` for ``n`` channels, this transform will normalize each channel of the input ``torch.*Tensor`` i.e., #计算过程:输出=(原始数据-均值)/标准差 ``output[channel] = (input[channel] - mean[channel]) / std[channel]``
train.py ページを実行すると、結果が表示されます如图1
図1
トレーニング後、モデル重みファイルが現在のルート ディレクトリに生成されます: Lenet.pth、如图2
図2
次に、インターネットから飛行機の写真をダウンロードし、現在のプロジェクトのルート ディレクトリに置きます。
detect.py ファイルを開きます。このファイルは、予測用のモデルの重みを呼び出すスクリプトです。
実行すると結果が得られますが、如图3
画像3
3. 参考文献
1.「深層学習とニューラルネットワーク」趙莫光編
出版社: Electronic Industry Press、初版 2023 年 1 月
ISBN: 978-7-121-44429-6
2.「深層畳み込みニューラルネットワークの原理と実践」Zhou Pucheng、Li Congli、Wang Yong、Wei Zhe 編
出版社: 北京: 電子産業プレス、2020.10
ISBN: 978-7-121-39663-2
3. 王凱編『Pythonニューラルネットワーク入門と実践』
出版社: 北京大学出版局
ISBN: 9787301316290
4. B ステーションブロガー @霹雳巴拉Wz: https://www.bilibili.com/video/BV187411T7Ye/?spm_id_from=333.788&vd_source=647760d93691c99109dee33aad004b62