猫と犬の画像認識 (詳細な畳み込みニューラル ネットワーク (CNN))

目次

1. モデル設計

(1) 畳み込みニューラルネットワークの知識

(3) 畳み込みニューラルネットワークの設定

①シーケンスモデルのインポート

②入力レイヤー設定

③隠しレイヤー設定

④寸法変化

⑤出力層

2. コードの詳細説明

(1) 画像ファイルのマッチング

(2) グラフィッククリッピング

(3) 関数のパラメータ設定とコールバック

(4) 結果の可視化

3. パラメータ調整

4. 結果分析


1. モデル設計

(1) 畳み込みニューラルネットワークの知識

1. 入力レイヤー (必須)。入力層は、ニューラル ネットワーク全体の入力であり、画像を処理する畳み込みニューラル ネットワークでは、通常、画像のピクセル マトリックスを表します。たとえば、上の図の左端の 3 次元マトリックスは画像を表すことができます。3 次元マトリックスの長さと幅はイメージのサイズを表し、3 次元マトリックスの深さはイメージのカラー チャネルを表します。たとえば、白黒画像の深度は 1 ですが、RGB カラー モードでは画像の深度は 3 です。畳み込みニューラル ネットワークは、入力層から開始して、最後の全結合層まで、さまざまなニューラル ネットワーク構造を介して、前の層の 3 次元行列を次の層の 3 次元行列に変換します。

2.畳み込み層(場合によっては)。名前からわかるように, 畳み込み層は畳み込みニューラル ネットワークの最も重要な部分です. 従来の全結合層とは異なり, 畳み込み層は畳み込みニューラル ネットワークの最も重要な部分です. 従来の完全結合層とは異なります.接続層. 畳み込み層の各ノードの入力は前の層のニューラル ネットワークのほんの一部であり、この小さな部分の一般的に使用されるサイズは 3*3 または 5*5 です. 畳み込み層はしようとしますニューラルネットワークの各小さな部分を実行する より詳細な分析により、より抽象的な機能が得られます。一般的に、畳み込み層で処理されるノード行列は深くなるため、上図から畳み込み層以降のノード行列の深さが増すことがわかります。

3. プーリング層。プーリング層ニューラル ネットワークは、3 次元マトリックスの深さを変更しませんが、マトリックスのサイズを縮小できます。プーリング操作は、高解像度の画像を低解像度の画像に変換するものと考えることができます。プーリング層を通じて、最後の全結合層のノード数をさらに減らすことができ、それによってニューラル ネットワーク全体のパラメータを削減するという目的を達成できます。

4. 全結合層 (必須)、畳み込み層とプーリング層の複数回のラウンドの後、畳み込みニューラル ネットワークの最後で、一般に 1 ~ 2 個の全結合層によって最終的な分類結果が得られます。畳み込み層とプーリング層の処理を数回繰り返した後、画像内の情報と抽象化は、より情報量の多い特徴になったと見なすことができます。自動画像特徴抽出のプロセスとして、畳み込み層とプーリング層を見ることができます。特徴抽出が完了した後も、完全に接続されたレイヤーを使用して分類タスクを完了する必要があります。

5. ソフトマックス層 (必須). ソフトマックス層は主に分類問題に使用されます. ソフトマックス層を通じて, 異なるタイプに属する現在のサンプルの確率分布を得ることができます.

(3) 畳み込みニューラルネットワークの設定

①シーケンスモデルのインポート

シーケンシャル モデルは、ニューラル ネットワークのレイヤーを接続して、モデル フレームワークに相当するディープ ニューラル ネットワークを構築するために使用されます。後で sunmmary() メソッドを使用して、モデルの構築を表示できます。

#顺序模型
model=Sequential()
#查看搭建模型框架
model.summary()

②入力レイヤー設定

# 输入层:第一层
# 添加第一个卷积层/最大池化层(必选)
model.add(Conv2D(filters=32,  # 32 个过滤器
                 kernel_size=(3,3),  # 卷积核大小 3 x 3
                 input_shape=input_shape,  # 图像输入维度
                 activation='relu'))  # 'relu' 激活函数
model.add(MaxPooling2D(pool_size=(2, 2)))  # 池化核大小 2 x 2

最初のレイヤーは 32 個のフィルターを設定し、畳み込みカーネル サイズは 3x3、プール カーネル サイズは 2x2 に設定されます。

活性化機能の役割

活性化関数を使用しない場合、順方向演算では val=np.dot(w,x) が計算されて計算が終了し、同様に逆方向演算では error=y (実際の値)-y (計算値) 終わりも終わり この時、終わりに効果はあるのですが、中間層は全く効果がありません。活性化関数はディープ ラーニングで非常に重要な役割を果たし、ネットワークに非線形性を与え、ニューラル ネットワークが任意の複雑な関数に適合できるようにします。活性化関数がなければ、ネットワークがどんなに複雑であっても、1 つの線形変換と同等であり、非線形関数を適合させることはできません。

③隠しレイヤー設定

パラメータ設定は以前と同じです。

隠れ層の役割:

ニューラル ネットワークにおける隠れ層の役割: 中間のブラック ボックス, これは、他の多くの異なる機能層の一般的な用語と考えることができます. 各層は、必要な機能を前の層に適用できます (通常は線形変換、そして圧縮非線形性)。隠れ層の仕事は、入力を出力層が使用できるものに変換することです。出力層は、非表示層の活性化を、出力を希望する任意のスケールに変換します。単一の隠れ層の意味 隠れ層の意味は、入力データの特性を別の次元空間に抽象化して、より抽象的な特徴を示すことです。これは、より適切に線形分割できます。

隠れ層の借用点を選択する方法は?

入力層のノード数と出力層のノード数はそれに応じて決定されます. 最初に直面する非常に重要で困難な問題は、隠れ層のノード数と隠れ層の数をどのように最適化するかです. 実験によると、隠れ層ノードの数が少なすぎると、ネットワークは必要な学習能力と情報処理能力を持つことができません。逆に、多すぎると、ネットワーク構造の複雑さが大幅に増加するだけでなく (これは、ハードウェアで実装されたネットワークでは特に重要です)、学習プロセス中にネットワークが極小点に陥る可能性が高くなります。ネットワークの学習速度が非常に遅くなります。隠れ層のノード数の選択は、ニューラル ネットワークの研究者によって常に高く評価されてきました。

隠れ層の計算方法は次のとおりです。

方法 1: fangfaGorman は、中間層のノード数 s とパターン数 N の関係は、s=log2N; であると指摘しました。  

方法 2: コルモゴロフの定理は、中間層のノード数 s=2n+1 (n は入力層のノード数) を示しています。

 方法 3: s=sqrt(0.43mn+0.12nn+2.54m+0.77n+0.35)+0.51 (m は入力層の数、n は出力層の数)

# 隐藏层:介于第一层和最后一层之间
# 添加第二个卷积层/最大池化层(可选)
model.add(Conv2D(filters=32, kernel_size=(3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))

# 添加第三个卷积层/最大池化层(可选)
model.add(Conv2D(filters=64, kernel_size=(3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))

# 添加第三个卷积层/最大池化层(可选)
model.add(Conv2D(filters=64, kernel_size=(3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))

# 由于卷积层是 2D 空间,训练时需要将数据展平为 1D 空间
model.add(Flatten())  # 添加展平层(必选)
model.add(Dense(units=64, activation='relu'))  # 添加全连接层(必选) 64 个神经元
model.add(Dropout(0.5))  # 添加丢弃层,防止过拟合

④寸法変化

畳み込み層は 2D 空間であるため、トレーニング中にデータを 1D 空間に平坦化する必要があり、最終的な平坦化層が同時に追加され、破棄層が最後に追加されます。オーバーフィッティングを防ぎ、モデルの精度を下げることです。

model.add(Flatten())  # 添加展平层(必选)
model.add(Dense(units=64, activation='relu'))  # 添加全连接层(必选) 64 个神经元
model.add(Dropout(0.5))  # 添加丢弃层,防止过拟合

⑤出力層

活性化関数はディープ ラーニングで非常に重要な役割を果たし、ネットワークに非線形性を与え、ニューラル ネットワークが任意の複雑な関数に適合できるようにします。

活性化関数がなければ、ネットワークがどんなに複雑であっても、1 つの線形変換と同等であり、非線形関数を適合させることはできません。

現在、深層学習で最も一般的な活性化関数は relu ですが、swish や GELU など、新しく導入された活性化関数もいくつかあります.活性化関数を使用しない場合、フォワード演算では val=
np.dot (w,x) の計算が終わったら終了. 同様に, 逆の計算では, error=y (実際の値)-y (計算値) で計算が終了します. このとき, 影響はありますが結局、中間層はまったく効果がありません。数学的にも簡単です. 活性化関数を使わない場合, 活性化関数は f(x)=x と仮定できます. 同様に, 導関数 f'(x)=1, 誤差を逆にすると,中層は変わらない。

同時に、ここでは活性化関数 sigmoid を選択します。これには次の利点があります。

1. 実装が簡単で、導関数が簡単に得られる。

2. 出力は [0,1] にあるため、確率を表す出力レイヤーとして使用できます。

3. 最大エントロピー モデルは、ノイズ データの影響をあまり受けません。

# 输出层:最后一层,神经元控制输出的维度,并指定分类激活函数
model.add(Dense(units=2, activation='sigmoid'))  # 指定分类激活函数

model.summary()

model.compile(loss='binary_crossentropy',  # 指定损失函数类型
              optimizer='rmsprop',  # 优化器
              metrics=['accuracy'])  # 评价指标

最後に model.compile() でオプティマイザー、損失関数、精度評価基準を設定します。

よく使用するパラメーターはオプティマイザーです。これは、トレーニング中に使用するオプティマイザーと、損失構成トレーニング中に使用する損失関数を構成するために使用されます。メトリックの説明はより詳細です. 深層学習モデルの評価指標を指定するために使用されます. より単純で一般的に使用されるものは metrics=['accuracy'] です. 公式ドキュメントでは、多出力モデルの場合、辞書を使用して metrics={'output_a': 'accuracy', 'output_b': ['accuracy', 'mse' などのメトリックを渡すことができることも指摘しています。 ]} このように使用される 多出力モデルの異なる出力に対して異なる評価指標を指定します。(私が推測する) 含意は、複数の出力に同じ評価指標を使用することです. metrics=['accuracy'] を使用する方が簡単です. もちろん、metrics={'output_a': 'accuracy', 'output_b': 'accuracy' '}.

もちろん、さらに興味深いパラメーター loss_weights も表示されます。公式の説明では、このパラメーターはリストまたは辞書にすることができます (リストを例にとります)。リストには、定数 (0.7、0.3) などが格納されます (例として、デュアル出力モデルを取り上げます)。モデル最適化のプロセスでは、損失関数を最小化することは、2 つの損失値の合計を最小化することを意味し、この loss_weights を使用して、これら 2 つの出力の損失値を重み付けします。

2. コードの詳細説明

(1) 画像ファイルのマッチング

この実験では、os、glob、load_img、img_to_array、array_to_img およびその他のライブラリを使用します。そのうちの os.path.join(path,name): ディレクトリとファイル名またはディレクトリを接続します。glob.glob(): 一致基準に一致するすべてのファイルのパスを返します。最後に、フォルダー内の各ファイルが for ループを通過し、画像が配列に変換されます. 同時に、画像のスケール マップが matplotlib ライブラリを使用して作成され、後続のグラフィック選択のパラメーター基準が提供されます.

path = 'data'
os.path.join(path, '*/*/*.*')
# 使用 glob 模块批量匹配图像, * 代表匹配所有东西
img_list = glob.glob(os.path.join(path, '*/*/*.*'))
print('>>>图像数量:', len(img_list))
print(img_list[:5])

for i, img_path in enumerate(img_list[:6]):
    img_plot = load_img(img_path)  # 加载图像
    arr = img_to_array(img_plot)  # 将图像转换成数组
    print(arr.shape)  # 图像形状
    plt.subplot(2, 3, i + 1)
    plt.imshow(img_plot)

(2) グラフィッククリッピング

データの長さと高さ、つまりピクセルを定義することで、後続の画像特徴抽出により適切に使用できます。幅と高さの値は、データが最初にロードされたときに生成された画像比率のグラフィックスに従って決定されます。同時に、.image_data_format() を使用して画像のサイズを確認し、画像のサイズの順序 ("channels_first" または "channels_last") を返し、最後にジェネレーターとジェネレーターの使用を定義し、ズーム倍率を再生します。 , これは後でクロッピングするために画像をズームすることです. 特徴の抽出, 定義された画像ジェネレーターは単にグラフィックスの特徴をよりよく抽出することです. ここでは、トレーニングセットとに使用される2つの画像ジェネレーターを使用していることがわかりますそれぞれテスト セット。固有値を抽出するのに適しています。

# 统一定义图像像素的宽度和高度
img_width, img_height = 200, 200
# 定义训练集、验证集的图形路径(文件夹路径即可)
train_data_dir = 'data/train/'
validation_data_dir = 'data/validation/'

# 图像输入维度设置
if K.image_data_format() == 'channels_first':
    input_shape = (3, img_width, img_height)
else:
    input_shape = (img_width, img_height, 3)
# 定义图像生成器
train_datagen = ImageDataGenerator(rescale=1. / 255,  # 重缩放因子
                                   shear_range=0.2,  # 剪切强度(以弧度逆时针方向剪切角度)
                                   zoom_range=0.2,  # 随机缩放范围
                                   horizontal_flip=True,  # 随机水平翻转
                                   rotation_range=360  # 360度范围内随机旋转
                                   )
# 使用图像生成器,从train_data_dir目录中读取图片,生成训练集(X_train图片数据, y_train图片所在的目录名称)
train_generator = train_datagen.flow_from_directory(train_data_dir,  # 训练数据的文件夹路径
                                                    target_size=(img_width, img_height),  # 统一像素大小
                                                    batch_size=batch_size,  # 每一批次的观测数
                                                    class_mode='categorical'  # 指定分类模式,指定二分类
                                                    )
test_datagen = ImageDataGenerator(rescale=1. / 255,
                                  shear_range=0.2,  # 剪切强度(以弧度逆时针方向剪切角度)
                                  zoom_range=0.2,  # 随机缩放范围
                                  horizontal_flip=True)  # 随机水平翻转

validation_generator = test_datagen.flow_from_directory(validation_data_dir,  # 验证集文件夹路径
                                                        target_size=(img_width, img_height),
                                                        batch_size=batch_size,
                                                        class_mode='categorical'  # 二分类
                                                        )

(3) 関数のパラメータ設定とコールバック

最初の部分は、実行結果のストレージ パスとコールバック関数のトレーニング結果のストレージ パス、model.fit_generator() を設定することです。これは一般にジェネレータ関数であり、主な関数はジェネレータを使用してデータをバッチでモデルを作成すると、単一のメモリの消費を効果的に節約できます。

コールバック関数の機能:

コールバック関数は、トレーニングの特定の段階で呼び出される一連の関数です.コールバック関数を使用して、トレーニング プロセス中にネットワークの内部状態と統計を観察できます. コールバック関数リストをモデルの .fit() に渡すことにより、この関数セットの関数を特定のトレーニング ステージで呼び出すことができます。

# tensorboard回调函数
logs = os.path.join("logs")
if not os.path.exists(logs):
    os.mkdir(logs)
train_callbacks = [
    TensorBoard(
        log_dir=r'./logs',
        histogram_freq=1,
    )
]

tensorboard_dir = os.path.join(r'.\logs\plugins\profile')
history = model.fit_generator(train_generator,
                              steps_per_epoch=nb_train_samples,
                              epochs=epochs,
                              validation_data=validation_generator,
                              validation_steps=nb_validation_samples,
                              callbacks=train_callbacks
                              )

(4) 結果の可視化

最終結果の視覚化は、以前に選択した model.compile() に関連しています. グラフの美しさとトレーニング結果の変化をよりよく観察するために、データ結果を視覚化することを選択します. データ結果の視覚化により、結果の変化は、トレーニングと検証結果の精度をより適切に反映することができます。

#现在将训练后的结果可视化。
acc = history.history['acc']
val_acc = history.history['val_acc']

loss = history.history['loss']
val_loss = history.history['val_loss']

epochs_range = range(epochs)

plt.figure(figsize=(20, 10))
plt.subplot(1, 2, 1)
plt.plot(epochs_range, acc, label='Training Accuracy')
plt.plot(epochs_range, val_acc, label='Validation Accuracy')
plt.legend(loc='lower right')
plt.title('Training and Validation Accuracy')

plt.subplot(1, 2, 2)
plt.plot(epochs_range, loss, label='Training Loss')
plt.plot(epochs_range, val_loss, label='Validation Loss')
plt.legend(loc='upper right')
plt.title('Training and Validation Loss')
plt.show()

3. パラメータ調整

モデル フレームワークが構築された後、決定する必要があるのは、このモデル トレーニングのパラメーターです。次のコードのパラメーターは、トレーニング結果に影響を与える重要な要素です。ステップ サイズは、トレーニング セットと検証セットごとに選択されたデータの数です。つまり、トレーニング データ セット全体について、ジェネレーターがトラバーサル ラウンド (エポック) を完了するのに必要なステップ数であり、各ステップでロードするデータ量 (batch_size) を指定します。steps_per_epoch は、トレーニング イメージの数をバッチ サイズで割って計算されます。

パラメーターの反復回数 (エポック) によって、ネットワーク内のすべての画像のトレーニング回数が決まり、一般的には 50 が最適な選択です。

したがって、1,000 枚の画像をトレーニングするときに数回反復することを選択でき、トレーニングのステップ サイズは需要によって異なります。

私のコンピューターは 50 回の反復を実行し、ステップ サイズは 100、50 です。80% 以上の効果を達成するようにトレーニングできますが、これはパーソナル コンピューターの状況に基づいています。

注: 1 回の反復で、入力データが大きすぎたり、トレーニング時間が長すぎたりして、コンピューターに一定の負荷がかかり、一部のコンピューターはそれに耐えられないことがあります。注意深い。

# 模型训练的参数设置
nb_train_samples = 60#步长
nb_validation_samples = 30
epochs = 30  # 迭代次数
batch_size = 32  # 每个批量观测数

# 统一定义图像像素的宽度和高度
img_width, img_height = 200, 200

4. 結果分析

最後に、loss(トレーニングセットの全体の損失値)、val_loss(検証セット(テストセット)の全体の損失値)をパラメータとし、両者の関係を次のような結果変化グラフにします。 :

  • 損失が減少すると、val_loss が減少します: 通常のトレーニング、最良のケース。
  • 損失が減少すると、val_loss が安定します: ネットワークの過剰適合。この時点で、Dropout および Max プーリングを追加できます。
  • 損失が安定し、val_loss が低下した場合: データ セットに重大な問題があることを意味します.ラベル ファイルに注釈エラーがあるかどうか、またはデータ セットの品質が低すぎるかどうかを確認できます. 再選択することをお勧めします。
  • 損失が安定している場合、val_loss は安定しています: 学習プロセスがボトルネックに遭遇し、学習率を下げる (適応ネットワークは効果的ではありません) またはバッチ数を減らす必要があります。
  • 損失が増加すると、val_loss が増加します。ネットワーク構造の設計の問題、不適切なトレーニング ハイパーパラメータ設定、データ セットのクリーニングが必要など、最悪の場合です。

視覚化の結果から、上記の方法でトレーニングの結果が良いかどうかを知ることができます.同時に、作成されたトレーニングと検証の精度図を通じて、このトレーニングの精度を確認し、トレーニング結果を観察することができます.この2つの方法で。

おすすめ

転載: blog.csdn.net/Sheenky/article/details/125282134