ディープラーニング 03 - 畳み込みニューラル ネットワーク (CNN)

導入

CNN (畳み込みニューラル ネットワーク) は、画像やビデオの処理に一般的に使用される深層学習モデルです。従来のニューラル ネットワークと比較して、CNN は画像の特徴を自動的に学習し、最も有用な情報を抽出できるため、画像を処理してデータをシーケンスする能力に優れています。

CNN の中核機能はコンボリューション演算で、画像に対してスライディング ウィンドウ計算を実行し、フィルター (コンボリューション カーネルとも呼ばれます) とプーリング層 (Max Pooling) を通じて画像の特徴を抽出できます。畳み込み演算は、画像の空間構造情報を保持しながら、重みの数を効果的に減らし、計算量を減らすことができます。プーリング層は、特徴マップの次元を変更することなく、計算量を削減し、モデルの堅牢性を向上させることができます。

CNN の一般的な構造には、畳み込み層、プーリング層、全結合層などが含まれます。同時に、過剰適合を防ぐために、CNN はドロップアウトや L2 正則化などのいくつかの正則化手法も追加します。

CNN は、画像分類、ターゲット検出、音声認識などの分野で広く使用されています。画像分類タスクでは、CNN の古典的なモデルには LeNet-5、AlexNet、VGG、GoogleNet/Inception が含まれます。これらのモデルの設計思想とネットワーク構造は異なりますが、いずれも畳み込みニューラル ネットワークの開発に重要な貢献をしています。貢献する。

開発パス

畳み込みニューラル ネットワーク (CNN) は、画像認識、コンピューター ビジョンなどの分野で広く使用されている深層学習モデルです。CNN の開発過程では、多くの古典的なモデルが登場しましたが、ここではいくつかの有名なモデルを簡単に紹介します。

  1. ルネット-5

LeNet-5 は、1998 年に Yann LeCun らによって提案され、広く使用された最初の畳み込みニューラル ネットワーク モデルでした。これは主に手書きの数字認識に使用され、畳み込み層、プーリング層、全結合層が含まれています。LeNet-5 の設計により、MNIST 手書き数字認識タスクで非常に優れたパフォーマンスを達成できます。少ない数のコンボリューション カーネル (6 および 16) と少数のパラメータが特徴で、最初のコンボリューション層はサイズ 5×5 の 6 つのコンボリューション カーネルを使用し、2 番目のコンボリューション層はサイズ 16 A のコンボリューション カーネルを使用します。 5×5。この設計はモデルのパラメータ数を効果的に削減できますが、畳み込みニューラル ネットワークの元祖であり、後続のモデルの基礎を築きます。

  1. アレックスネット

AlexNet は、2012 年に Alex Krizhevsky らによって提案されました。これは、ImageNet 画像分類コンテストで優れた結果を達成した最初の畳み込みニューラル ネットワーク モデルです。複数の畳み込み層とプーリング層を使用し、ReLU 活性化関数とドロップアウト正則化技術を使用します。AlexNet の設計は、ImageNet 画像分類競争において他のモデルを大きくリードし、畳み込みニューラル ネットワークの新たな開発ラウンドをリードしました。多数のコンボリューション カーネル (約 6,000) と多数のパラメータを使用するのが特徴ですが、精度と効率の点で優れたパフォーマンスを備えています。

  1. VGG

VGG は、2014 年に Karen Simonyan と Andrew Zisserman によって提案されました。その主な貢献は、より大きなコンボリューション カーネルの代わりにより小さなコンボリューション カーネル (3x3) の使用を提案したことです。この設計により、ネットワークがより深くなり、パラメータが少なくなるため、効率と精度が向上します。VGG には 16 または 19 の畳み込み層とプーリング層が含まれており、これらの層はすべて同じ畳み込みカーネル サイズとストライドを使用します。VGG は、ImageNet 画像分類コンテストで非常に良い結果を達成し、その後の ResNet やその他のモデルにインスピレーションを与えました。

  1. GoogleNet/インセプション

GoogleNet は、2014 年に Google チームによって提案されました。その主な貢献は、パラメータの量を増やすことなくネットワークの深さと幅を増やすことができるインセプション モジュールです。インセプション モジュールは、特徴抽出に複数のコンボリューション カーネルとさまざまなサイズのプーリング層を使用し、それらを接続してモジュールを形成します。GoogleNet はまた、完全接続層の代わりにグローバル平均プーリング層を使用し、パラメータの数をさらに削減します。GoogleNet は、ImageNet 画像分類コンテストで非常に良い結果を達成し、その後の ResNet、DenseNet、その他のモデルにインスピレーションを与えました。

  1. レスネット

ResNet は、2015 年に Microsoft Research Asia チームによって提案されました。その主な貢献は、深層畳み込みニューラル ネットワークの劣化問題を解決できる残差学習を提案することです。劣化問題とは、ネットワークの深さが増すにつれて精度が低下する現象を指します。残留学習では、クロスレイヤー接続を導入して入力を出力に直接転送することで、情報の損失を回避します。ResNet にはよ​​り深いネットワーク構造 (152 層) が含まれていますが、より優れた精度を実現します。ResNet の設計思想は、その後の DenseNet、MobileNet、その他のモデルに継承されました。

  1. 高密度ネット

DenseNet は、2017 年に Gao Huang らによって提案されました。その主な貢献は、ネットワークの深さと幅を増やし、効率と精度を向上させることができる高密度接続を提案することです。密な接続とは、各層の出力を後続のすべての層の入力に接続して、密な接続構造を形成することを指します。この設計により、ネットワークがよりコンパクトになり、パラメータが少なくなり、機能の再利用性も向上します。DenseNet は、ImageNet 画像分類コンテストで非常に良い結果を達成し、ShuffleNet や EfficientNet などの後続のモデルにもインスピレーションを与えました。

  1. モバイルネット

MobileNet は 2017 年に Google チームによって提案されました。その主な貢献は、良好な精度を維持しながらパラメータの数を削減できる深さ分離可能な畳み込みを提案することです。深さ方向の分離可能な畳み込みとは、畳み込み演算を深さ方向の畳み込みとポイント単位の畳み込みの 2 つのステップに分割し、それによって計算量とパラメータを削減することを指します。MobileNet は、複数の深さ分離可能な畳み込み層とプーリング層を使用して、モバイル デバイスなどのリソースに制約のある環境で効率的な画像分類とターゲット検出を実現します。MobileNet の設計思想は、ShuffleNet や EfficientNet などの後続モデルに受け継がれています。

  1. シャッフルネット

ShuffleNet は、2018 年に Microsoft Research Asia チームによって提案されました。その主な貢献は、精度を維持しながらパラメーターと計算の量を大幅に削減できるチャネルの再編成とグループ畳み込みを提案することです。チャネルの再編成とは、異なるグループ間で情報を交換できるようにするために、入力チャネルをグループ化および再グループ化することを指します。グループ畳み込みとは、畳み込み演算をグループ内畳み込みとグループ間畳み込みの2段階に分割し、計算量とパラメータを削減することを指します。ShuffleNet は、複数のチャネル再編成とグループ畳み込み層を使用して、リソースに制約のある環境で効率的な画像分類とターゲット検出を実現します。

  1. EfficientNet

EfficientNet は、2019 年に Google チームによって提案されました。その主な貢献は、精度を維持しながらパラメータと計算の量を大幅に削減できるネットワーク スケーリングと複合係数を提案することです。ネットワーク スケーリングとは、モデル構造を変更せずにネットワークの深さ、幅、解像度を同時にスケーリングして最適化することを指します。複合係数とは、深さ、幅、解像度のスケーリング係数を組み合わせて、より効率的なモデルを取得することを指します。EfficientNet は、ImageNet 画像分類コンテストで非常に良い結果を達成し、その後のモデルの最適化にインスピレーションを与えました。

  1. RegNet

RegNet は、2020 年に Facebook AI Research チームによって提案されました。その主な貢献は、精度を維持しながらパラメーターと計算の量を大幅に削減できるネットワーク構造の適応ルールを提案することです。適応ルールとは、より効率的なモデルを取得するために、検索と最適化を通じてネットワーク構造のハイパーパラメーターを自動的に調整することを指します。RegNet は、ImageNet 画像分類コンテストで非常に良い結果を達成し、その後のモデルの最適化にインスピレーションを与えました。

上記はいくつかのよく知られた畳み込みニューラル ネットワーク モデルであり、設計思想やネットワーク構造は異なりますが、いずれも畳み込みニューラル ネットワークの開発に重要な貢献を果たしています。

概略原理

畳み込みニューラル ネットワークは画像認識に威力を発揮し、前例のない精度を達成し、幅広い用途に使用できます。次に、画像認識を例にして畳み込みニューラル ネットワークの原理を紹介します。

場合

以下の図に示すように、与えられた画像 (おそらく文字 X または文字 O) を CNN を使用して X か O かを識別できると仮定します。どうすればよいでしょうか?
ここに画像の説明を挿入します

画像入力

古典的なニューラル ネットワーク モデルを使用する場合、画像全体をニューラル ネットワーク モデルの入力として読み込む必要があります (つまり、全結合)。画像のサイズが大きくなると、それに接続されるパラメーターが多くなり、結果として、大量の計算が必要で、非常に膨大です。
一般に人間の外界の認識は局所的なものから大域的なものへと進み、まず局所的な部分を知覚的に理解し、徐々に全体を認識していく、これが人間の理解モデルです。画像内の空間的なつながりも同様で、局所的な範囲のピクセルは密接につながっていますが、遠く離れたピクセル間の相関は弱くなります。したがって、各ニューロンは実際には大域的な画像を知覚する必要はなく、局所的な部分を知覚するだけでよく、その後、局所的な情報をより高いレベルで合成して大域的な情報を取得する。このモードは、畳み込みニューラル ネットワークのパラメーター、つまり局所受容野の数を減らす際の重要な成果物です。
ここに画像の説明を挿入します

特徴抽出

例えば、以下の図に示すように、文字の移動、拡大縮小、回転、微小変形などが行われた場合、
ここに画像の説明を挿入します
私たちの目標は、特徴を効果的に抽出する方法を含む CNN を通じて、さまざまな形態変化における X と O を正確に識別することです。識別の重要な要素として。
前述の「局所受容野」モードを思い出してください。CNN の場合、小さな断片を比較し、2 つの画像のほぼ同じ位置にある大まかな特徴 (小さな画像パッチ) を見つけます。マッチングでは、従来の比較と比較して、画像全体を 1 つずつ分析することで、CNN の小ブロック マッチング手法により 2 つの画像間の類似性をより適切に比較できます。以下の図に示すように
ここに画像の説明を挿入します
、黒の文字を例にとると
ここに画像の説明を挿入します

ここに画像の説明を挿入します

上記の特徴抽出は仮定であり、実際には、入力として複数の画像がある場合、畳み込みニューラル ネットワークは画像ごとに特徴を抽出します。具体的なプロセスは次のとおりです: 入力画像は最初の畳み込み層を通過し、畳み込みカーネルが画像内に表示されます。上にスワイプして、エッジやコーナーなどの低レベルの特徴を抽出します。

畳み込みニューラル ネットワークでは、複数の異なる畳み込みカーネルが使用される場合、各畳み込みカーネルの局所受容野サイズは同じですが、異なる畳み込みカーネルの重みは異なるため、各畳み込みカーネルは異なる特徴を学習できます。

たとえば、畳み込み層で 3 つの異なる畳み込みカーネルを使用するとします。最初の畳み込みカーネルの重みはエッジの検出に使用され、2 番目の畳み込みカーネルの重みはテクスチャ特徴の検出に使用され、3 番目の畳み込みカーネルの重みはテクスチャ特徴の検出に使用されます。カーネルはエッジの検出に使用され、コンボリューション カーネルの重みはターゲットの形状の検出に使用されます。これら 3 つのコンボリューション カーネルのローカル受容野はすべて同じサイズですが、重みが異なるため、各コンボリューション カーネルは異なる特徴を学習できます。

コンボリューション カーネルのサイズとステップ サイズは、各コンボリューション カーネルの局所的な受容野サイズにも影響することに注意してください。コンボリューションカーネルのサイズが大きくなると、それに応じて局所受容野も大きくなり、ステップサイズが大きくなると、コンボリューションカーネルが毎回スライドする距離もそれに応じて大きくなり、コンボリューションカーネルに影響を与えます。局所的な受容野。

たとえば、コンボリューション カーネル
[-1, 0, 1],
[-1, 0, 1],
[-1, 0, 1]]

この行列は実際にはコンボリューション カーネルであり、ソーベル フィルターとしても知られています。画像内の垂直エッジを検出するために使用できます。
コンピューター ビジョンでは、エッジとは、グレー値が大きく変化する画像内の領域を指します。垂直エッジとは、画像の上部から下部へ、または下部から上部へのグレー値の変化を指します。
コンボリューション カーネルの動作原理は、画像のピクセルとコンボリューション カーネルを畳み込み、画像の特徴を抽出することです。この例では、コンボリューション カーネルの中心要素は 0 であり、画像の中心ピクセルとは何の関係もないことを示しています。コンボリューション カーネルの要素の上部行 [-1, 0, 1] は、画像の上部ピクセルでコンボリューション演算を実行することを示します。同様に、コンボリューション カーネルの下の行の要素 [-1, 0, 1] は、画像の下位ピクセルでコンボリューション演算を実行することを示します。

コンボリューション カーネルが画像内のピクセルとコンボリューションされるとき、画像に垂直エッジがある場合、コンボリューションの結果は明らかな変化を示します。具体的には、垂直エッジの一方の側では、畳み込み結果はより大きな正の値を取得しますが、垂直エッジのもう一方の側では、畳み込み結果はより大きな負の値を取得します。このようにして、しきい値処理された畳み込み結果を通じて画像内の垂直エッジを識別することができ、負の部分は直接 0 に戻されます。

たとえば、一部が垂直エッジである画像があるとします。この画像の垂直エッジ部分にコンボリューションカーネルを適用すると、コンボリューション結果は正と負の値を示すため、コンボリューション結果を閾値処理することで垂直エッジの位置を抽出できます。

この例が、行列 [-1, 0, 1] を使用して垂直エッジを検出できる理由を理解するのに役立つことを願っています。
別の例は
[[-0.1111, -0.1111, -0.1111],
[-0.1111, 1.0000, -0.1111],
[-0.1111, -0.1111, -0.1111]]で
、これはラプラシアン フィルターまたは鮮鋭化フィルターと呼ばれます。画像のエッジを強調するために使用できます。
このマトリックスでは、中心要素 1 は、画像の中心ピクセルに関連していることを意味します。周囲の要素 -0.1111 は、それらが画像の周囲のピクセルに関連していることを意味します。

コンボリューション カーネルが画像とコンボリューションされると、中央のピクセルの値が増幅され、周囲のピクセルの値が抑制されます。このように、画像のエッジでは、ピクセル値の大きな変化により、畳み込み結果はより大きな正と負の値を示し、エッジのコントラストが強調されます。

たとえば、いくつかのエッジを含む画像があるとします。このコンボリューション カーネルを画像に適用すると、コンボリューションの結果によりエッジのコントラストが強調され、エッジがより鮮明になります。

したがって、このコンボリューション カーネルはエッジを検出し、エッジのコントラストを強調することでエッジをより明瞭にすることができます。

エッジとは、画像内のピクセルのグレー値が大きく変化する場所で、通常、画像内のオブジェクトのエッジ、輪郭、テクスチャなどの情報を表します。画像処理やコンピュータ ビジョンでは、エッジ検出は画像のセグメント化や特徴の抽出などに使用できる一般的な技術です。
たとえば、以下に示すように、
ここに画像の説明を挿入します
エッジ抽出の効果は次のようになります。
ここに画像の説明を挿入します

角点

コーナーポイントは、明らかな角度変化を伴う画像の局所領域にある特別なポイントです。コーナーポイントは通常、異なる方向のエッジの交差によって形成され、ガウス曲率を持ち、画像の重要な特徴の 1 つです。コーナー検出は、画像レジストレーション、オブジェクト追跡、画像マッチングなどで一般的に使用されるテクノロジでもあります。一般的に使用されるコーナー検出アルゴリズムには、Harris コーナー検出、Shi-Tomasi コーナー検出などが含まれます。
以下に示すように
ここに画像の説明を挿入します

opencv

OpenCV (オープンソース コンピューター ビジョン ライブラリ) は、オープンソースのコンピューター ビジョンおよび機械学習ソフトウェア ライブラリです。開発者が画像処理、物体検出、顔認識、ビデオ分析などのコンピューター ビジョン アプリケーションを迅速に構築するのに役立ちます。

OpenCV はもともと Intel Corporation によって開始され、現在では C++、Python、Java などの複数のプログラミング言語をサポートし、Windows、Linux、macOS などのオペレーティング システム上で実行できるクロスプラットフォームのオープン ソース プロジェクトになりました。

ここでは Opencv を使用して、特定の画像のエッジとコーナーを抽出します。
ここに画像の説明を挿入します

ここでは opencv について詳しく説明しません。記事の後半で説明します。
コード

#%%
import cv2  #注意安装open-cv  conda install open-cv
import numpy as np
import matplotlib.pyplot as plt

# 读入lena图像
img = cv2.imread('d:/9.png')
# 将BGR图像转换为RGB图像,便于matplotlib显示
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

# 将图像转换为灰度图像
gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
gray_ori=gray
# 使用Canny边缘检测函数检测图像的边缘
edges = cv2.Canny(gray, 100, 200)

# 创建SIFT对象
sift = cv2.xfeatures2d.SIFT_create()
# 检测图像的特征点
keypoints = sift.detect(gray, None)
# 在图像上绘制特征点
img_sift = cv2.drawKeypoints(img, keypoints, None, flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)

# 检测图像的角点
dst = cv2.cornerHarris(gray, 2, 3, 0.04)
# 将角点标记为红色
img_corner = img.copy()
img_corner[dst > 0.01 * dst.max()] = [255, 0, 0]

# 创建一个Matplotlib窗口并显示图像及其各种特征
plt.rcParams['font.family'] = 'SimHei'
fig, axs = plt.subplots(2, 2, figsize=(10, 10))
axs[0, 0].imshow(img)
axs[0, 0].set_title('原始图像')
axs[0, 1].imshow(edges, cmap='gray')
axs[0, 1].set_title('边缘')
axs[1, 0].imshow(img_sift)
#SIFT的全称是Scale Invariant Feature Transform,尺度不变特征变换。具有旋转不变性、尺度不变性、亮度变化保持不变性,是一种非常稳定的局部特征。
axs[1, 0].set_title('SIFT特征')
axs[1, 1].imshow(img_corner)
axs[1, 1].set_title('角点特征')
plt.show()

出力効果
ここに画像の説明を挿入します

特徴抽出原理

[Convolution] の章を読んだ後にこのセクションをお読みください。
一般的に使用されるコンボリューション カーネルには次のものがあります。

  1. ガウス フィルター: 画像の平滑化に使用され、画像のノイズを軽減できます。
  2. ハイパス フィルター: 画像内のエッジ、コーナーなどの高周波情報を強調表示するために使用されます。
  3. ローパス フィルター: ぼかし、スムージングなど、画像内の低周波情報を強調表示するために使用されます。
  4. ソーベルフィルター: 画像内のエッジ情報を検出するために使用されます。
  5. ラプラシアン フィルター: エッジ、ディテールなどの画像の高周波情報を強調するために使用されます。
  6. Scharr フィルター: Sobel フィルターに似ていますが、エッジにより敏感です。
  7. Prewitt フィルター: Sobel フィルターに似ていますが、エッジに対する応答がよりスムーズです。

これらのコンボリューション カーネルは、エッジ検出、画像の平滑化、画像の強調など、画像処理のさまざまなタスクに使用できます。適切なコンボリューション カーネルを選択して、さまざまなタスクに基づいて画像を処理できます。

以下で定義される畳み込みカーネルは、その中心ピクセルに大きな重みが与えられ、周囲のピクセルには小さな重みが与えられるため、ハイパス フィルターとみなすことができます。この重み分布により、コンボリューション カーネルは画像内のエッジやコーナーなどの高周波情報を検出できるようになります。畳み込み演算では、画像内の各ピクセルに畳み込みカーネルが乗算され、その結果が加算されて新しいピクセル値が取得されます。コンボリューションカーネルの中心ピクセルの周囲のピクセル値と中心ピクセル値の差が大きい場合、コンボリューション演算の結果はより大きくなり、このピクセルがエッジ点である可能性があることを示します。したがって、このコンボリューション カーネルは、画像内のエッジ情報を強調表示できます。

kernel = np.array([[-1,-1,-1], [-1,9,-1], [-1,-1,-1]])

以下のような図がありますが、
ここに画像の説明を挿入します
これをopencvで読み込み、コンボリューションカーネルで畳み込みます。

import cv2
import numpy as np
from myutils.common import show,fillColor
# 读取图片
img = cv2.imread('./images/z.png')

# 将图像转换为灰度图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 定义卷积核
kernel = np.array([[-1,-1,-1], [-1,9,-1], [-1,-1,-1]])
# kernel = np.array([[-1,-1,-1,-1,-1],[-1,-1,-1,-1,-1], [-1,-1,20,-1,-1],[-1,-1,-1,-1,-1], [-1,-1,-1,-1,-1]])
# kernel = cv2.getGaussianKernel(5, 1)

# 对灰度图像进行卷积操作,#注意如果-1 <0的值会被归一化为0
edges = cv2.filter2D(gray, cv2.CV_32F, kernel)
print(edges[:][edges<0])
# 对卷积结果进行ReLU处理
edges_relu = np.maximum(0, edges)
show(img,'Original Image',cmap="gray",debug=True)  
show(edges, 'Edges Image',cmap="gray",debug=True)
show(edges_relu, 'Edges ReLU Image',cmap="gray",debug=True)

def show(dilate, title, cmap=None, debug=False):
    if debug:
        plt.title(title)
        plt.imshow(dilate, cmap=cmap)
        plt.show()

ここに画像の説明を挿入します

畳み込み演算では relu を使用せずに線形特徴が抽出されると言われるのはなぜですか?

畳み込み演算自体では非線形特徴を抽出できないことを示す簡単な例を見てみましょう。

次の値を含む入力行列 X があるとします。

X = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

ここで、サイズ 2x2 の畳み込みカーネル K を使用して X を畳み込みます。畳み込みカーネルの値は次のとおりです。

K = [[1, 1], [1, 1]]

行列乗算を使用して畳み込み演算を実行できます。具体的には、K 行列を反転し、X 行列との内積演算を実行して、出力行列 Y を取得します。

Y = K*X = [[12, 16], [24, 28]]

出力行列 Y は入力行列 X の線形結合であることがわかり、畳み込み演算自体はエッジやテクスチャなどの入力行列 X の線形特徴のみを抽出できます。

ただし、ReLU 活性化関数などの非線形活性化関数を使用して出力行列 Y を処理すると、線形特徴を非線形特徴に変換できます。たとえば、ReLU 関数を Y に適用すると、次のような非線形特性が得られます。

ReLU(Y) = [[12, 16], [24, 28]]

したがって、畳み込み演算だけでは入力行列の線形特徴しか抽出できませんが、非線形活性化関数と組み合わせることで非線形特徴も抽出できます。

畳み込み

では、これらの特徴はマッチングのためにどのように計算されるのでしょうか? (ピクセルを 1 つずつ一致させるとは言わないでください、汗!)
ここで、今日の重要なゲスト、コンボリューションを招待する必要があります。では、畳み込みとは何ですか? 以下でゆっくり説明しますので、ご心配なく。
新しい画像が与えられると、CNN はこれらの特徴が元の画像のどの部分と一致する必要があるかを正確に知りません。そのため、元の画像内の可能なすべての位置を試します。これは、この特徴をフィルターに変えるのと同じです。このマッチング処理は畳み込み演算と呼ばれ、畳み込みニューラル ネットワークの名前の由来にもなっています。
畳み込み演算を次の図に示します。
ここに画像の説明を挿入します

黄色の部分はコンボリューション カーネルで、前の画像抽出されたすべての可能な 3* 特徴[1,0,1]][0,1,0]
[[1,0,1]


この場合、元の画像上でそれに対応する特定の小さなパッチの特徴(特徴)とその結果を計算するには、2 つの小さなパッチの対応する位置のピクセル値を乗算し、次に乗算するだけで済みます。小さなパッチ全体 演算結果は累積され、最終的に小さなブロック内のピクセルの総数で除算されます (注: 総数で割る必要はありません)。
両方のピクセルが白 (両方の値が 1) の場合、1 1 = 1、両方のピクセルが黒の場合、(-1) (-1) = 1、つまり、ピクセルの各ペアは乗算結果と一致します。は1です。同様に、一致しないピクセルには -1 が乗算されます。具体的なプロセスは次のとおりです (最初、2 番目...、最後のピクセルの結果を照合します):
まず、畳み込みのために以前に抽出した 3 つの特徴の 1 つを使用します
ここに画像の説明を挿入します
。たとえば、最初の特徴を緑の枠で囲みます。 部品の比較
ここに画像の説明を挿入します
ここに画像の説明を挿入します
ここに画像の説明を挿入します
コンボリューションの計算方法によれば、最初の特徴マッチング後のコンボリューション計算は次のようになり、結果は1になります。他の位置のマッチング(中央部分
ここに画像の説明を挿入します
マッチングなど)も同様であり
ここに画像の説明を挿入します
特徴画像は上記の処理を連続的に繰り返し、各特徴(feature)の畳み込み演算により新たな2次元配列が得られ、これを特徴マップ(feature map)と呼びます値が 1 に近いほど、対応する位置とフィーチャの一致がより完全になります。-1 に近いほど、対応する位置とフィーチャの反対側の一致がより完全になります。値が近いほど、対応する位置とフィーチャの反対側の一致がより完全になります。値が 0 に近づくほど、対応する位置とフィーチャの一致がより完全になります。値が 0 に近づくほど、対応する位置とフィーチャの一致がより完全になります。以下の図に示すように、
ここに画像の説明を挿入します
画像サイズが増加すると、内部加算、乗算、除算の演算数が急速に増加し、各フィルタのサイズとフィルタの数が直線的に増加することがわかります。非常に多くの要素が関係するため、計算量が非常に膨大になる可能性があります。

プーリング

計算量を効果的に削減するために、CNN で使用されるもう 1 つの有効なツールは「プーリング」と呼ばれます。プーリングとは、入力画像を縮小してピクセル情報を削減し、重要な情報のみを保持することです。
プーリングの操作も非常に簡単で、通常、プーリング領域のサイズは 2 2 で、最大値 (max-pooling) と平均値 (mean) を取るなど、一定のルールに従って対応する値に変換されます。 -pooling) などでは、この値を結果のピクセル値として使用します。
下図は、
左上隅の 2 2 プーリング領域の max-pooling 結果を示しています。下図に示すように、この領域の最大値 max(0.77,-0.11,-0.11,1.00) をプール結果とします。 : 左側のプーリング領域
ここに画像の説明を挿入します
、2 番目の小さなブロックは、以下に示すように、プーリングの結果として最大値 max (0.11、0.33、-0.11、0.33) を取得します。他の領域も同様で、領域内の
ここに画像の説明を挿入します
最大値を次のように取得します。プーリングの結果、最後にプーリング後、結果は次のようになります。
ここに画像の説明を挿入します
すべての機能マップに対して同じ操作を実行すると、結果は次のようになります。
ここに画像の説明を挿入します
max-pooling は、各小さなブロックの最大値を保持します。これは、このブロックの最良の値 一致結果 (値が 1 に近いほど一致が高いことを意味するため)。言い換えれば、ウィンドウ内のどの場所が一致するかには特に焦点を当てず、どこかに一致があるかどうかだけに焦点を当てます。
プーリング層を追加することで画像が削減され、計算量が大幅に削減されマシン負荷が軽減されます。

活性化関数 ReLU (Rectified Linear Units)

一般的に使用される活性化関数には、sigmoid、tanh、relu などが含まれます。最初の 2 つの sigmoid/tanh は全結合層でより一般的であり、後者の ReLU は畳み込み層で一般的です。
先ほどのパーセプトロンを振り返ると、パーセプトロンは各入力を受け取り、それを合計し、活性化関数を通過した後に出力します。活性化関数の機能は、非線形要素を追加し、畳み込み層の出力結果の非線形マッピングを実行することです。
ここに画像の説明を挿入します
畳み込みニューラル ネットワークでは、活性化関数には通常、高速な収束と単純な勾配計算を特徴とする ReLU (The Rectified Linear Unit、修正線形ユニット) が使用されます。計算式も非常に単純で、max(0,T) です。つまり、負の入力値の場合、出力はすべて 0 になり、正の値の場合、出力は変化しません。
この場合の ReLU 活性化関数の演算プロセスを見てみましょう:
以下に示すように、最初の値は max(0,0.77) として取られ、結果は 0.77 になります。2 番目の値は
ここに画像の説明を挿入します
max(0, 0.77) として取られます。 -0.11)、以下に示すように、結果は 0 になります。 図
ここに画像の説明を挿入します
同様に、ReLU アクティベーション関数を通過した後の結果は次のようになります。
ここに画像の説明を挿入します
すべての機能マップに対して ReLU アクティベーション関数の操作を実行すると、結果は次のようになります。
ここに画像の説明を挿入します

ディープニューラルネットワーク

上記の畳み込み、活性化関数、プーリングを組み合わせると、次の図になります。
ここに画像の説明を挿入します
ネットワークの深さを増やし、層を追加すると、次のようなディープ ニューラル ネットワークが得られます。
ここに画像の説明を挿入します

完全に接続された層

全結合層は畳み込みニューラル ネットワーク全体で「分類器」の役割を果たします。つまり、畳み込み、活性化関数、プーリングなどの深いネットワークを通過した後、結果は全結合層を通じて識別および分類されます。
まず、畳み込み、活性化関数、およびプーリング後のディープ ネットワークの結果が、以下の図に示すようにつなぎ合わされます。 ニューラル ネットワークは教師あり学習に属するため、モデルのトレーニング中に、モデルはトレーニング サンプルに基づいてトレーニングされます
ここに画像の説明を挿入します
。全結合を取得します 層の重み (文字を予測するすべての結合の重みなど)
ここに画像の説明を挿入します
計算結果を重み付けして合計し、各結果の予測値を取得し、最大値を認識結果として採用します (図を参照)下の図では、最終的に計算された文字 X の認識値は 0.92、文字 O の認識値は 0.51 であり、結果は次のように判断されます
ここに画像の説明を挿入します

ここに画像の説明を挿入します

畳み込みニューラル ネットワーク

上記の結果をすべてつなぎ合わせた後、以下の図に示すように、「畳み込みニューラル ネットワーク」(CNN) 構造が形成されます。 最後に、レビューして要約すると、畳み込みニューラル ネットワークは主に 2 つの部分で構成され、1 つの部分は特徴抽出です
ここに画像の説明を挿入します
。 (畳み込み、活性化関数、プーリング)、残りの部分は分類認識 (全結合層) 以下の図は、有名な手書き文字認識畳み込みニューラル ネットワークの構造図です。
ここに画像の説明を挿入します

この章の内容の参照先: https://my.oschina.net/u/876354/blog/1620906

コンボリューション API

変換2D

Conv2D は、畳み込みニューラル ネットワークのコア層の 1 つで、画像などの 2 次元データの畳み込み処理に使用される層です。Conv2D の機能は、コンボリューション カーネルを通じて入力 2 次元画像またはデータに対して一連のコンボリューション演算を実行し、それによって画像またはデータ内の特徴を抽出することです。

Conv2D 層の入力はテンソルです。テンソルの形状は通常 (batch_size、高さ、幅、チャネル) です。ここで、batch_size は入力データの数を表し、高さと幅は入力データの高さと幅を表します。 Channel は入力データのチャンネル数を表します (例: RGB 画像のチャンネル数は 3)。

Conv2D 層の出力もテンソルであり、畳み込み演算後に取得された特徴マップを表します。出力テンソルの形状は通常 (batch_size、conv_height、conv_width、filters) です。ここで、conv_height と conv_width は、コンボリューション カーネルが適用された後に取得される特徴マップの高さと幅を表し、フィルターはコンボリューション カーネルの数を表します。 、出力特徴マップのチャネル数。

畳み込みプロセス中、Conv2D 層は入力データに畳み込みカーネルを適用し、各畳み込みカーネルと入力データの間の畳み込み演算を 1 つずつ計算することによって畳み込み出力特徴マップを取得します。畳み込みプロセス中に、畳み込みカーネルのサイズ、ステップ サイズ、充填方法などのパラメーターを自由に設定して、さまざまなアプリケーション シナリオに適応できます。
TensorFlow 2.0 と Keras では、次のコードを使用して Conv2D レイヤーを作成できます。

from tensorflow.keras.layers import Conv2D

conv_layer = Conv2D(filters=32, kernel_size=(3, 3), strides=(1, 1), padding='same', activation='relu', input_shape=(height, width, channel))
  • フィルター: コンボリューション カーネルの数、つまり出力特徴マップの数。
  • kernel_size: 畳み込みカーネルのサイズ。正方形の畳み込みカーネルの辺の長さを表す整数、または異なる長さと幅を持つ畳み込みカーネルを表すタプルにすることができます。
  • strides: ストライド。コンボリューション カーネルが入力特徴マップ上で移動する距離です。これは、2 つの隣接するコンボリューション カーネル間の距離を示す整数にすることも、ステップ サイズが長さ方向と幅方向で異なることを示すタプルにすることもできます。
  • padding: パディング方法。「同じ」または「有効」にすることができます。「同じ」は、出力特徴マップのサイズが入力特徴マップのサイズと同じであり、一部の値を入力特徴マップの周囲にパディングする必要があることを意味し、「有効」はパディングが必要ないことを意味します。出力特徴マップのサイズは、入力特徴マップと畳み込みカーネルに基づき、サイズによって異なります。
  • アクティベーション: アクティベーション関数。非線形変換を特徴マップに追加するために使用されます。一般的な活性化関数には、「relu」、「sigmoid」、「tanh」などが含まれます。
  • input_shape: 入力特徴マップの形状。高さ、幅、チャネル数を表す 3 つの値を指定できます。このパラメータは最初の畳み込み層で指定する必要があります。
  • kernel_regulatoryizer: 深層学習では、モデルの過学習を防ぐために、通常、モデルを制約するために正則化テクノロジが使用されます。一般的に使用される正則化手法の 1 つは L2 正則化です。L2 正則化とは、モデルの重みのサイズを制限するためにモデルの損失関数に L2 ノルム ペナルティ項を追加することを指します。
    Keras では、regularizers.l2(0.001) を使用して L2 正則化ペナルティを追加します。このうち、0.001 は正則化パラメータで、正則化の強度を制御します。正則化パラメータが大きいほど、重みに対するペナルティ項の影響が大きくなり、モデルの複雑さが軽減されるため、過剰適合が効果的に防止されます。
    具体的には、regularizers.l2(0.001) は、全結合層、畳み込み層など、ニューラル ネットワーク内の任意の重み行列に適用できます。ネットワークの定義では、対応する層の kernel_regulatoryizer パラメーターを使用して L2 正則化を追加できます。たとえば、Keras で L2 正則化を使用して完全接続層を追加するコードは次のとおりです。
layers.Conv2D(32, (3, 3), activation='relu', kernel_regularizer=regularizers.l2(0.001), input_shape=(28, 28, 1)),

畳み込みの例

minist10 枚の写真を撮り、畳み込みに 10 個のコンボリューション カーネルを使用し、特徴マップを出力し、画像を表示します。
各写真は 10 個のコンボリューション カーネルを生成するため、合計 100 個の特徴マップが生成されます。

#%%
import tensorflow as tf
import matplotlib.pyplot as plt
import numpy as np

# 加载mnist数据集
mnist = tf.keras.datasets.mnist
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()

# 取1张训练集图片
images = train_images[:10]

# 将图片转换为float类型
images = images.astype('float32') / 255.0
# 将图片reshape成4D张量,大小为(10, 28, 28, 1),也就是第一个维度表示有10张图像,每张图像由28行、28列和1个# 通道(灰度)组成
images = np.expand_dims(images, axis=3)
# 定义卷积核数量
num_filters = 10

# 定义卷积层
model = tf.keras.models.Sequential([
    tf.keras.layers.Conv2D(num_filters, (3, 3), activation='relu', input_shape=(28, 28, 1)),
])

# 计算卷积后的特征图
features = model.predict(images)

# 绘制卷积后的特征图
fig, axs = plt.subplots(nrows=num_filters, ncols=10, figsize=(10, num_filters))
for i in range(num_filters):
    for j in range(10):
        axs[i][j].imshow(features[j, :, :, i], cmap='gray')
        axs[i][j].axis('off')
plt.show()

出力
ここに画像の説明を挿入します

np.expand_dims 関数は、指定された軸上の配列の次元を拡張するために使用されます。この例では、images は形状の配列 (10, 28, 28) であり、10 個の 28x28 グレースケール画像を表します。ただし、機械学習モデルは通常、4 次元配列、つまり (サンプル数、画像の高さ、画像の幅、チャネル数) を入力する必要があります。したがって、画像配列の最後の次元 (チャネル数) を 1 次元拡張して、形状 (10、28、28、1) の配列に変換する必要があります。
具体的には、axis=3 は、配列の 3 番目の軸 (0 から数えて) の次元を拡張することを意味します。これにより、各画像の最後の次元に 1 次元が追加され、各画像が (28, 28, 1) の 3 つの形状に変わります。次元配列。最後に、画像配列の形状は (10, 28, 28, 1) になります。これは、28x28 グレースケール画像が 10 個あり、各画像が 1 つのチャネルで構成されていることを意味します。このようにして、画像を入力として機械学習モデルに渡すことができます。

上の出力図からわかるように、一部のコンボリューション カーネルの出力は、エッジ、一部のコーナー、および一部のテクスチャに偏っています。

MaxPooling2D

keras.layers.MaxPooling2D((2, 2)) は、最大プーリング操作に使用される Keras のレイヤーです。
最大プーリングは一般的に使用される畳み込みニューラル ネットワーク操作であり、画像サイズを変更せずに画像内のパラメーターの数を削減できるため、計算量とメモリ消費量を削減できます。最大プーリング操作は、入力イメージを重複しないブロックに分割し、各ブロックの最大値を出力として取得します。畳み込みニューラル ネットワークでは、最大プーリングは通常、画像の空間特徴を抽出するために畳み込み層と同じ意味で使用されます。

MaxPooling2D レイヤーのパラメーターはタプル (2, 2) で、プーリング ウィンドウのサイズが 2x2 であることを示します。これは、入力画像がサイズ 2x2 の複数のブロックに分割され、各ブロックの最大値が出力として取得されることを意味します。プーリング ウィンドウ サイズが (3, 3) に設定されている場合、入力画像はサイズ 3x3 の複数のブロックに分割され、各ブロックの最大値が出力として取得されます。

つまり、MaxPooling2D レイヤーは、計算量とメモリ消費量を削減しながら、畳み込みニューラル ネットワークが画像の空間特徴を抽出するのに役立ちます。

平らにする

keras.layers.Flatten() は、入力を 1 次元ベクトルに「平坦化」するために使用される Keras のレイヤーです。

畳み込みニューラル ネットワークでは、通常、畳み込み層とプーリング層を使用して画像の特徴を抽出し、全結合層を分類に使用します。全結合層の入力は 1 次元ベクトルであるため、前の特徴マップを 1 次元ベクトルに「平坦化」する必要があります。これが Flatten レイヤーの機能です。

Flatten レイヤーにはパラメータはなく、入力テンソルを順番に 1 次元ベクトルに展開するだけです。たとえば、入力テンソルの形状が (batch_size, 7, 7, 64) である場合、Flatten 層の出力形状は (batch_size, 7 7 64 )になります。

畳み込みニューラル ネットワークを構築する場合、通常、畳み込み層とプーリング層の後に平坦化層を追加して、特徴マップを 1 次元ベクトルに平坦化し、それを分類のために全結合層に接続します。

密|ドロップアウト

多層パーセプトロンを参照

手書き数字認識

畳み込み mnist データセット

MNIST データセットをロードして前処理し、ピクセル値を 0 から 1 の間でスケーリングし、データセットをトレーニング セットとテスト セットに分割します。
データ処理の詳細な説明については、多層パーセプトロンを参照してください。

import tensorflow as tf
import tensorflow.keras
from tensorflow.keras import layers
from tensorflow.keras.datasets import mnist
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras import regularizers
(x_train, y_train), (x_test, y_test) = mnist.load_data()

x_train = x_train.astype('float32') / 255.
x_test = x_test.astype('float32') / 255.

x_train = x_train[..., tf.newaxis]
x_test = x_test[..., tf.newaxis]

num_classes = 10

y_train = tf.keras.utils.to_categorical(y_train, num_classes)
y_test = tf.keras.utils.to_categorical(y_test, num_classes)

次に、畳み込みニューラル ネットワーク モデルを定義します。2 つの畳み込み層と 2 つのプーリング層を使用し、その後に 2 つの全結合層と 1 つの出力層を使用します。また、オーバーフィッティングを防ぐためにドロップアウトと L2 正則化も使用します。

model = tf.keras.Sequential([
    layers.Conv2D(32, (3, 3), activation='relu', kernel_regularizer=regularizers.l2(0.001), input_shape=(28, 28, 1)),
    layers.MaxPooling2D((2, 2)),
    layers.Conv2D(64, (3, 3), activation='relu', kernel_regularizer=regularizers.l2(0.001)),
    layers.MaxPooling2D((2, 2)),
    layers.Flatten(),
    layers.Dense(128, activation='relu', kernel_regularizer=regularizers.l2(0.001)),
    layers.Dropout(0.5),
    layers.Dense(64, activation='relu', kernel_regularizer=regularizers.l2(0.001)),
    layers.Dropout(0.5),
    layers.Dense(num_classes, activation='softmax')
])

model.summary() は Keras のモデル オブジェクトのメソッドで、各レイヤーの名前、出力形状、パラメーターの数などを含むモデルの構造情報を出力するために使用されます。これは、モデルのデバッグ、最適化、モデル構造の理解に役立ちます。

model.summary()

次に、モデルをコンパイルし、データ拡張技術を使用して、過剰適合をさらに防ぎます。データ拡張テクノロジーは、回転、変換、スケーリングなどの一連のランダム変換を適用して、新しいトレーニング サンプルを生成します。これにより、モデルがより堅牢になり、過剰適合が防止されます。

model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])

datagen = ImageDataGenerator(
    rotation_range=10,
    width_shift_range=0.1,
    height_shift_range=0.1,
    zoom_range=0.1
)

次に、トレーニング セットを使用してモデルをトレーニングし、テスト セットを使用してモデルのパフォーマンスを評価します。

datagen.fit(x_train)
batch_size = 1024
epochs = 10
checkpoint = tf.keras.callbacks.ModelCheckpoint('./model.h5', save_best_only=True, save_weights_only=False, monitor='val_loss')
history = model.fit(datagen.flow(x_train, y_train, batch_size=batch_size),
                    epochs=epochs,
                    validation_data=(x_test, y_test),
                    steps_per_epoch=len(x_train) // batch_size,callbacks=[checkpoint])

score = model.evaluate(x_test, y_test, verbose=0)
print('Test loss:', score[0])
print('Test accuracy:', score[1])

ステップごとのエポックとバッチ_サイズの違いは
、バッチ_サイズが各トレーニング バッチ (バッチ) に含まれるサンプルの数を指すことです。深層学習では、通常、トレーニング セットは複数のバッチに分割され、各バッチには複数のサンプルが含まれます。この利点は、行列演算を使用して計算を高速化できることと、過剰適合を避けるためにトレーニング プロセス中にサンプルの順序をランダムに変更することもできることです。

steps_per_epoch は、1 エポックでモデルをトレーニングする必要があるバッチの数を指します。各エポックには複数のバッチが含まれるため、steps_per_epoch を設定して、エポック内で渡す必要があるバッチの数を指定する必要があります。通常、steps_per_epoch の値はトレーニング セットのサイズとbatch_sizeから計算できます。たとえば、トレーニング セットのサイズが 1000 で、batch_size が 32 の場合、1 エポックで 1000 / 32 = 31 個のバッチをトレーニングする必要があるため、steps_per_epoch を 31 に設定する必要があります。

ステップごとのエポックは、トレーニングセットのサイズをバッチサイズで割ったものと必ずしも等しいわけではないことに注意してください。トレーニング セットのサイズがbatch_sizeで割り切れない場合、最後のバッチにはbatch_sizeよりも少ないサンプルが含まれる可能性があります。この状況を回避するには、下向き丸め操作 // を使用して step_per_epoch を計算し、トレーニング セット全体が各エポックで処理できるようにすることができます。

微調整

微調整とは、より優れたパフォーマンスを達成するために、特定のタスクまたは特定のデータセットに対してすでにトレーニングされたモデルを微調整する方法を指します。通常、ImageNet やその他のデータ セットなどの大規模なデータ セットで事前トレーニングされたモデルを使用します。このモデルは、トレーニング プロセス中に多くの共通の特徴とパターンを学習しています。このモデルを新しいタスクや新しいデータセットにより適したものにするために、このモデルを微調整したり、いくつかのパラメーターを調整したり、いくつかの新しいレイヤーを追加したりすることができます。事前トレーニングされたモデルにはすでに適切な初期重みと特徴抽出機能があるため、このアプローチは通常、モデルを最初からトレーニングするよりも効率的です。

mnist-c データセット

MNIST-C は MNIST データ セットのバリアントであり、MNIST データ セットに人工ノイズが追加されています。MNIST データセットは、60,000 のトレーニング サンプルと 10,000 のテスト サンプルを含む手書き数字認識データセットで、各サンプルは 28 x 28 ピクセルのグレースケール画像です。MNIST-C データセットは、MNIST データセットの画像にランダム ノイズを追加することによって作成されます。これらのノイズには、ぼやけ、歪み、明るさの変化などが含まれ、モデルがより堅牢になります。

MNIST-C データセットは、さまざまなタイプのノイズに対するモデルの堅牢性をテストできるため、機械学習モデルの堅牢性をテストするのに非常に役立ちます。MNIST-C データセット内の各画像には、それが表す番号を示すラベルが含まれています。これらのラベルは MNIST データセット内の対応するラベルと同一であるため、同じトレーニングおよびテスト プロセスを使用してモデルのトレーニングとテストを行うことができます。

https://github.com/google-research/mnist-c/ でデータ セットをダウンロードします。この github アドレスはソース コードのアドレスです。実際のダウンロード アドレスは Readme に記載されています: https://zenodo.org/record /3239543# .ZF2rzXZByUl、ダウンロードして解凍します。
ここに画像の説明を挿入します
これらのフォルダーはすべて、npy 形式でエクスポートされた numpy 配列です。
各フォルダーの最初の 10 枚の画像を読み取って表示します

# 数据集的开源地址:https://github.com/google-research/mnist-c/
import os
import numpy as np
import matplotlib.pyplot as plt
#加载数据集并打印每个子文件夹前10个数据集
data_root = './mnist_c'
dirlist=os.listdir(data_root)
fig, axs = plt.subplots(len(dirlist), 10, figsize=(10, 10))

for i, folder_name in enumerate(dirlist):
    folder_path = os.path.join(data_root, folder_name)
    if os.path.isdir(folder_path):
        file_path = os.path.join(folder_path, 'train_images.npy')
        data = np.load(file_path)
        for j in range(0,10):
            axs[i, j].imshow(data[j].reshape(28,28), cmap='gray')
            axs[i, j].axis('off')
plt.tight_layout()
plt.show()

出力
ここに画像の説明を挿入します

微調整メソッドのトレーニング

./model.h5 にある minist のトレーニング済みモデルの試行を開始すると仮定します。モデルをロードしてから、minist-c データのトレーニングを続けるためにモデルを試行する必要があります。

#%%

import os
import numpy as np
import tensorflow.keras as layers
import tensorflow as tf
import datetime

TARGET_MODEL_DIR="./"
MODEL_NAME="model.h5"
epochs_count=5
"""
   jupyter打印的日志太大导致ipynb打开很慢,这里写个一模一样代码的py运行
"""
def againTrain(x_train, y_train, x_test, y_test):
    targetModel=os.path.join(TARGET_MODEL_DIR,MODEL_NAME)
    #记载CNN模型
    model=tf.keras.models.load_model(targetModel)
    """
    在使用Fine-tuning方法微调预训练模型时,通常会冻结模型的前几层,只调整模型的后面几层,这是因为:
    1.预训练模型的前几层通常是针对原始数据集的通用特征提取器,这些特征对于不同的任务和数据集都是有用的,因此我们可以直接保留这些特征提取器,不需要进行微调。
    2.预训练模型的后几层通常是针对特定任务进行的微调,这些层的参数需要根据具体任务和数据集进行调整,以使模型更好地适应特定的任务和数据集。
    3.如果我们将整个模型的所有层都进行微调,会导致训练时间较长,而且可能会出现过拟合等问题。因此,冻结前几层可以有效地减少训练时间,并提高模型的泛化能力。
    总之,冻结模型的前几层可以节省计算资源和训练时间,同时还可以提高模型的泛化能力,使其更好地适应新的任务和数据集。
    """
    model.layers[0].trainable = False
    model.layers[1].trainable = False
    # 对输入图像进行预处理
    x_train = x_train.reshape(-1, 28, 28, 1)
    x_train = x_train.astype('float32') / 255.0
    x_test = x_test.reshape(-1, 28, 28, 1)
    x_test = x_test.astype('float32') / 255.0
    y_train = tf.keras.utils.to_categorical(y_train, num_classes=10)
    y_test = tf.keras.utils.to_categorical(y_test, num_classes=10)
    now = datetime.datetime.now()  # 获取当前时间
    format_time = now.strftime("%Y-%m-%d%H-%M-%S")  # 转换为指定格式
    checkpoint = tf.keras.callbacks.ModelCheckpoint(targetModel, save_best_only=True, save_weights_only=False, monitor='val_loss')
    # 继续训练模型
    history = model.fit(x_train, y_train, batch_size=128, epochs=epochs_count, validation_data=(x_test, y_test),
                        callbacks=[checkpoint])
    test_loss, test_acc = model.evaluate(x_test, y_test)
    print('Test accuracy:', test_acc)
"""
  传入mnist-c,数据会非常大加载数据很慢,这里每加载一份子目录就训练一次,节省内存开销。
"""
def loadDataMnistC(data_root,func):
    dirlist=os.listdir(data_root)
    for i, folder_name in enumerate(dirlist):
        folder_path = os.path.join(data_root, folder_name)
        if os.path.isdir(folder_path):
            print("开始读取:"+folder_path)
            train_images = np.load(os.path.join(folder_path, 'train_images.npy'))
            train_labels = np.load(os.path.join(folder_path, 'train_labels.npy'))
            test_images = np.load(os.path.join(folder_path, 'test_images.npy'))
            test_labels = np.load(os.path.join(folder_path, 'test_labels.npy'))
            print("开始训练:"+folder_path)
            func(train_images,train_labels,test_images,test_labels)
            print("训练完成:"+folder_path)
# 加载 MNIST-C 数据集
data_root = './mnist_c'
model=None;
loadDataMnistC(data_root,againTrain)
print("全部训练完成")

ここでは、毎回特定の型を 1 回読み取ってから、モデルをトレーニング用のサブフォルダーに書き戻し、トレーニングが完了するまで最終モデルを取得します。

おすすめ

転載: blog.csdn.net/liaomin416100569/article/details/130597944