TensorFlow に基づいて MNIST データセットを分析する

目次

MNIST データセットの分析と前処理

CPU/GPUの選択

比較解析

具体操作

モデリング

モデルをコンパイルする

トレーニングモデル

評価モデル

モデルを保存

結果の視覚化

モデルを使用して予測を行う

AutoEncoder セルフエンコーダー

一般的なオートエンコーダ

畳み込みオートエンコーダ

MNIST データセットの分析と前処理

以下を参照できます。

MNIST データセットの簡単な紹介 - THE WHY ブログ - CSDN ブログ

CPU/GPUの選択

比較解析

CPU: 中央処理装置(Central Processing Unit)。演算量は少ないものの、複雑な汎用演算を実行できます。

GPU: グラフィックス プロセッシング ユニット (Graphics Processing Unit)。複雑さは低く単純な演算を実行できますが、計算量が多くなります。

上記 2 つの特徴を踏まえると、MNIST を解析するには、グラフィックスのような行列演算が主であり、計算量は多くなりますが、複雑な演算は含まれないため、 を選択するのが適切であることがわかりますGPU

具体操作

GPU を選択する前に、まずコンピューターに GPU があるかどうかを判断する必要があります。サポートされていないバージョンを避けるために、最新の TensorFlow GPU バージョンをインストールして使用するのが最善です。私は個人的にそのバージョンを使用しています2.11.0

コードは次のように実装されています:
利用可能な GPU があるかどうかを確認します。

print(tf.test.is_gpu_available())

戻り値が の場合False、使用可能な GPU はありません

GPU リストを印刷して表示することもできます。

pring(tf.config.experimental.list_physical_devices('GPU'))

利用可能な GPU がない場合は、GPU をインストールするか CPU を使用するかを選択できます

CPU を使用するために追加の構成を行う必要はありません。デフォルトでは、CPU が使用されます。もちろん、現在使用可能な CPU を表示することもできます。

pring(tf.config.experimental.list_physical_devices('CPU'))

利用可能な GPU がある場合は、使用する適切な GPU を選択できます。

gpu = tf.config.experimental.list_physical_devices('GPU')
tf.config.experimental.set_memory_growth(gpu[0],True) #具体选用哪个视情况而定

モデリング

メソッド別tf.keras.models.Sequential()モデル

Sequential は、線形スタックの層をモデルにロードして、入力層から出力層までのネットワーク構造を作成できるコンテナです。

# 建立模型
model = tf.keras.Sequential()
# 通过add方法向模型中加载网络层(layer)
model.add(tf.keras.layers.Flatten(input_shape=(28,28))) # 每个样本有28*28个像素点,通过拉直层进行输入
model.add(tf.keras.layers.Dense(128,activation='relu')) # 隐含层,设置128个结点,激活函数使用Relu
model.add(tf.keras.layers.Dense(10,activation='softmax')) # 输出层,设置10个结点(数字0-9),激活函数使用softmax归一化

使用されるレイヤーはFlattenDense

Flatten入力を処理し、入力テンソルを平坦化するために使用されます。input_shape=(28,28)入力サイズは 28*28 の 2 次元配列であり、Flattenレイヤーを通じて 1 次元配列に変換できるため、これらのデータはモデルの各ニューロンに効果的に渡すことができます

Dense: 全結合層、隠れ層、出力層はすべてDenseこの構造を使用し、パラメーターは次のように設定されます。

Dense(ニューロン数、activation = "活性化関数"、kernel_regulatory = "正則化手法")

オプションの活性化関数: relu、softmax、sigmoid、tanh など。

オプションの正則化メソッド: tf.keras.regulaizers.l1()、tf.keras.regulaizers.l2() など。

  • 隠れ層には 128 個のノードが設定されており、活性化関数は Relu 関数を使用します。
    • sigmod 関数:

    • レル関数:

    • 対照的に、relu 関数は計算プロセスを簡素化し、勾配降下法に対する指数関数の影響を排除し、計算コストを削減できるため、relu 関数を選択します。
  • 出力層では、10 個のノード (出力番号 0 ~ 9) を設定し、活性化関数は正規化にソフトマックス関数を使用します。

モデルが構築されたら、モデル関連の情報を出力できます。

print(model.summary())

出力は次のとおりです。

Layer (type): ネットワーク層の名前(タイプ)。名前は次tf.keras.layers.Dense()のようにname属性指定できます。

Output Shape: 各レイヤーの出力形状

Param: 全結合層ニューラルネットワークの各層のニューロンの重み数; 計算式: (input_shape+1) * ニューロンの数

  • たとえば、dense_1 レイヤー、input_shape=128、ニューロンの数は 10、(128+1)*10=1290

モデルをコンパイルする

次の方法でcompileモデルをコンパイルします。

# 优化器:选用adam优化器,学习率设置为0.1
optimizer = tf.keras.optimizers.Adam(lr=0.1)
# 损失函数:选用交叉熵损失函数 ‘from_logits=False’ 表示将输出转为概率分布的形式
loss_fn = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False)
model.compile(optimizer=optimizer,loss=loss_fn,metrics=['accuracy'])

このメソッドには 3 つのパラメータがあります。

1. オプティマイザー: オプティマイザー、関数または文字列の形式にすることができ、adam オプティマイザーを選択します。

optimizer="adam"またはoptimizer=tf.keras.optimizers.Adam()

学習率は関数形式を選択することで設定できます。tf.keras.optimizers.Adam(lr=)デフォルトの学習率は 0.001 です。

特定の情報とその他のオプティマイザーのリファレンス: tf.keras.optimizers.Adam | TensorFlow v2.12.0

2. loss: 関数または文字列の形式で指定できる損失関数。スパース分類クロスエントロピー損失関数を選択します。

loss="sparse_categorical_crossentropy"またはloss=tf.keras.losses.SparseCatagoricalCrossentropy(from_logits = False)

他の一般的に使用される損失関数も、MSE次のようにクロスエントロピー損失関数と比較されます。

MSE:

クロスエントロピー:

クロスエントロピー損失関数の勾配は局所最適解に「行き詰まる」のが難しいため、この勾配が推奨されます。

特定の情報およびその他の損失関数リファレンス: tf.keras.losses.SparseCategoricalCrossentropy | TensorFlow v2.12.0

3.metrics: 精度評価基準、共通オプション: 'accuracy'sparse_accuracysparse_categorical_accuracy

具体的な情報については、tf.keras.metrics.Accuracy | TensorFlow v2.12.0を参照してください。

トレーニングモデル

メソッドを使用してfitモデルをトレーニングします。

history = model.fit(x_train,y_train,batch_size=128,epochs=10,validation_split=0.1,verbose=2)

パラメータ分析:

fit(x=None, y=None, batch_size=None, epochs=1, verbose=1,validation_split=0.0)

x、y: 入力と出力、必須

batch_size: 各グラデーション更新のサンプル数。デフォルト値は 32 です。

エポック: 反復回数

詳細: ログ出力の形式: 0: ログ情報を出力しない; 1: 進行状況バーを表示する; 2: 反復ごとにレコードの行を出力する

validation_split: トレーニング データ セットの一部を検証データとして分割し、残りをトレーニング データとして分割します。

返される内容:

fitメソッドの戻り値は、データセットの損失とトレーニングの精度を含む History オブジェクトです。

loss = history.history['loss']
val_loss = history.history['val_loss']
accuracy = history.history['accuracy']
val_accuracy = history.history['val_accuracy']
print("训练集损失:",loss)
print("测试集损失:",val_loss)
print("训练集准确率:",accuracy)
print("测试集准确率:",val_accuracy)
# 注意,key的名称与选择的损失函数和准确率评测标准有关

印刷結果は次のとおりです。

各反復の関連パラメータが出力されていることがわかります。

詳細については、tf.keras.Model | TensorFlow v2.12.0を参照してください。

評価モデル

次の方法でモデルを評価しますevaluate

model.evaluate(x_test,y_test,verbose=2)

パラメータ分析:

model.evaluate(x,y,batch_size,verbose)

x、y: テスト データ セット、テスト データ セットのラベル

batch_size: 各評価計算に使用されるサンプルの数

詳細: ログ出力の形式: 0: ログ情報を出力しない; 1: 進行状況バーを表示する; 2: 反復ごとにレコードの行を出力する

詳細については、tf.keras.Model | TensorFlow v2.12.0を参照してください。

モデルを保存

パラメータ分析:

model.save(存储路径): モデルを対応するパスに保存します

model.save(模型名称): パスが指定されていない場合、デフォルトで現在の作業パスに保存されます。

したがって、トレーニング済みモデル全体を保存し、使用時に直接ロードできます。

model = tf.keras.models.load_model(模型路径)

このモデルは、次の用途に直接使用できます。model.predict

詳細については、トレーニング チェックポイント | TensorFlow コアを参照してください。

結果の視覚化

matplotlib.pyplotプロットには結果の視覚化を使用する必要があります

公式ドキュメント: matplotlib — Matplotlib 3.7.1 ドキュメント

1. plt.figure: カスタムキャンバス関連のプロパティ

plt.figure(num='first',figsize=(10,3),dpi=75, facecolor='#FFFFFF', edgecolor='#0000FF')

num: 画像の番号; figsize: キャンバスのサイズ; dpi: 1 インチあたりのピクセル数; facecolor: キャンバスの色;edgecolor: キャンバスの端の色

文档:matplotlib.figure — Matplotlib 3.7.1 ドキュメント

2. plt.subplot(nrows, ncols, index): 複数の部分グラフを一度に描画するために使用されます。

チャートのプロット領域全体は、nrows 行と ncols 列に分割されます。

左から右、上から下のルールに従ってサブグラフに番号を付けます。インデックスは描画領域全体で描画されるサブグラフの位置を指定します。

文档:matplotlib.pyplot.subplot — Matplotlib 3.7.1 ドキュメント

3. plt.plot: 折れ線グラフを描画します

plt.plot(x,y,color='b',label='标签名称')

x: x 軸データ、y: y 軸データ、color: ラベルの色 (一般的に使用される: b-青、r-赤)

データ セットが 1 つだけ入力されている場合、x 軸のデフォルト値は [0,1,2,3,4....] (y[] の長さ) で埋められます。

文档:matplotlib.pyplot.plot — Matplotlib 3.7.1 ドキュメント

4. plt.xlabel() plt.ylabel(): x、y軸の単位名

5. plt.legend(): 凡例に表示すべき要素を自動的に検出して表示します。

6. plt.title(): タイトルの設定

上記の一般的に使用される描画 API に従って、損失と精度の変化曲線を描画できます。

plt.figure(figsize=(10,3))
plt.plot(loss,color='b',label='train')
plt.plot(val_loss,color='r',label='test')
plt.ylabel('loss')
plt.legend()

plt.figure(figsize=(10,3))
plt.plot(accuracy,color='b',label='train')
plt.plot(val_accuracy,color='r',label='test')
plt.ylabel('accuracy')
plt.legend()

モデルを使用して予測を行う

① テスト データ セットから画像をランダムに選択します。

id = np.random.randint(1,10000)

tf.reshapeリファクタリングによりモデルの入力形式に合わせる。

num = tf.reshape(x_test[id],(1,28,28)) 

model.predict予測することで:

model.predict(num)

④ 予測結果の取得

res = np.argmax(model.predict(num))

予測結果(以下の形式)から最大値を求め、予測結果として


2023.4.10更新: 

AutoEncoder セルフエンコーダー

一般的なオートエンコーダ

オートエンコーダーは、教師なしデータ次元圧縮およびデータ特徴表現方法であり、次の 2 つの部分で構成されます。

エンコーダ: 入力を潜在空間表現に圧縮します。

デコーダー: 潜在空間表現から入力を再構築します。

簡単に言うと、オートエンコーダは出力を入力と同じにしようとするニューラル ネットワークです。ポテンシャル空間表現の次元を入力データの次元よりも小さく設定すると、オートエンコーダは不完全になり、強制的にオートエンコーダが実行されます。入力データを学習し、データから有用な情報をより適切に抽出するために、データの顕著な特徴を学習し、潜在空間表現から入力を再構成する際の精度が高くなります。

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

from keras import layers
from keras.models import Model

# 加载数据
mnist = tf.keras.datasets.mnist
(x_train, _), (x_test, _) = mnist.load_data()

# 获取训练集和测试集
x_train, x_test = x_train / 255.0, x_test / 255.0

# 选取10%的训练数据集
x_train = x_train[0:6000]

latent_dim = 64 # 控制编码器的压缩程度(隐含层的结点数量)

class Autoencoder(Model): # 继承Model类,自定义自编码器模型
  def __init__(self, latent_dim):
    super(Autoencoder, self).__init__() # 自编码器的初始化
    self.latent_dim = latent_dim
    # 编码器,将原始图像压缩成64维的隐向量,相当于是隐含层
    self.encoder = tf.keras.Sequential([
      layers.Flatten(),
      layers.Dense(latent_dim, activation='relu'),
    ])
    # 解码器,从隐空间中重构图像
    self.decoder = tf.keras.Sequential([
      layers.Dense(784, activation='sigmoid'),
      layers.Reshape((28, 28))
    ])

  def call(self, x):
    encoded = self.encoder(x) # 先编码
    decoded = self.decoder(encoded) # 然后解码
    return decoded # 返回解码后的图像

autoencoder = Autoencoder(latent_dim) # 创建自编码器

# 由于Autoencoder继承了Model类,因此创建的自编码器也就相当于一个自定义模型,可以使用model的方法对模型进行编译,训练
# 编译模型:使用adam优化器,交叉熵损失函数
autoencoder.compile(optimizer='adam', loss='categorical_crossentropy')
# 训练模型
autoencoder.fit(x_train, x_train,
                epochs=10,
                shuffle=True,
                validation_data=(x_test, x_test))
# 保存训练的模型
autoencoder.save_weights("AEtest.h5")

# 模型训练完成,输入测试集中的数据进行预测
encoded_imgs = autoencoder.encoder(x_test).numpy()
decoded_imgs = autoencoder.decoder(encoded_imgs).numpy()

n = 10
plt.figure(figsize=(20, 4))
for i in range(n):
  # 随机选取测试集中的一张图像
  num = np.random.randint(1, 10000)

  # 展示初始的图像
  ax = plt.subplot(2, n, i + 1)
  plt.imshow(x_test[num])
  plt.title("original")
  plt.gray()
  ax.get_xaxis().set_visible(False)
  ax.get_yaxis().set_visible(False)

  # 展示经过自编码器处理之后的图像
  ax = plt.subplot(2, n, i + 1 + n)
  plt.imshow(decoded_imgs[num])
  plt.title("reconstructed")
  plt.gray()
  ax.get_xaxis().set_visible(False)
  ax.get_yaxis().set_visible(False)
plt.show()

結果は次のとおりです。

上位層は入力テストセット、下位層はセルフエンコーダによるエンコードおよびデコード後に得られる画像です。

上記のテストでは MNIST データ セットを使用し、データの 10% を使用します。コード実装は公式 Web サイトの例から変更されています。

オートエンコーダーの紹介 | TensorFlow コア

上記の結果から、デコーダの再構成の効果は平均的であるとしか言えないことがわかります。また、モデルのトレーニング中に出力された情報から、損失と val_loss の両方が比較的大きいことがわかります。

そして、この現象は、データ セットの 1% のみを使用する場合にさらに顕著になります。トレーニング サンプルが不足しているため、オートエンコーダーはデータの特性を十分に学習できません。

上の図に示すように、非常に抽象的な結果が表示されます。

そこで、トレーニングの反復設定を 100 に増やしました。

ただし、テスト値の損失 (val_loss) が増加することがわかり、200 回の反復を試みた後、損失の減少は非常に限定されていることがわかります。

テストの結果も満足のいくものではありません。

これは、通常のオートエンコーダが小規模なデータセットから効果的な特徴を抽出するのが苦手であることを示しています。

畳み込みオートエンコーダ

これを修正するために、別の畳み込みオートエンコーダを試しました。

いわゆる畳み込みセルフ エンコーダは、簡単に言えば、特徴の抽出と再構成のために、通常のセルフ エンコーダの完全に接続されたニューラル ネットワークを畳み込みニューラル ネットワークに置き換えることです。

コードの実装は次のとおりです: (これも公式 Web サイトのコードに従って修正されました)

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

from keras import layers,losses
from keras.models import Model

# 加载数据
mnist = tf.keras.datasets.mnist
(x_train, _), (x_test, _) = mnist.load_data()

# 获取训练集和测试集
x_train, x_test = x_train / 255.0, x_test / 255.0

# 选取10%的训练数据集
x_train = x_train[0:600]

latent_dim = 64 # 控制编码器的压缩程度(隐含层的结点数量)

class Denoise(Model):
  def __init__(self):
    super(Denoise, self).__init__()
    self.encoder = tf.keras.Sequential([
      layers.Input(shape=(28, 28, 1)), # shape=(28,28,1)分表表示RGB图像的高,宽和通道数(由于MNIST数据集是单色的,所以通道数为1
      # 输入的每一个通道都要与每一个卷积核进行卷积运算,生成特征图
      # 每个通道都可以看做是原始图像的一个抽象,堆的越多,神经网络汇总每一层的信息就越多,原始图像的损失就越少
      # 而在自编码器中,对输入的象征进行降采样以提供较小维度潜在表示,并强制自编码器学习象征的压缩版本
      # 这里输入1个通道,设置16个卷积核,进行卷积运算后生成16个特征图,从而输出通道数就是16
      layers.Conv2D(16, (3, 3), activation='relu', padding='same', strides=2),
      # 这里输入16个通道,设置8个卷积核,进行卷积运算后生成8个特征图,从而输出通道数就是8
      layers.Conv2D(8, (3, 3), activation='relu', padding='same', strides=2)])

    self.decoder = tf.keras.Sequential([
      # 卷积的逆操作
      layers.Conv2DTranspose(8, kernel_size=3, strides=2, activation='relu', padding='same'),
      layers.Conv2DTranspose(16, kernel_size=3, strides=2, activation='relu', padding='same'),
      # 设置1个通道,生成的特征图就是经过自编码器编码解码处理后的图像
      layers.Conv2D(1, kernel_size=(3, 3), activation='sigmoid', padding='same')])

  def call(self, x):
    encoded = self.encoder(x)
    decoded = self.decoder(encoded)
    return decoded

autoencoder = Denoise()


autoencoder.compile(optimizer='adam', loss=losses.MeanSquaredError())# 训练模型

autoencoder.fit(x_train, x_train,
                epochs=10,
                shuffle=True,
                validation_data=(x_test, x_test))
# 保存训练的模型
# autoencoder.save_weights("AEtest.h5")

# 模型训练完成,输入测试集中的数据进行预测
encoded_imgs = autoencoder.encoder(x_test).numpy()
decoded_imgs = autoencoder.decoder(encoded_imgs).numpy()

n = 10
plt.figure(figsize=(20, 4))
for i in range(n):
  # 随机选取测试集中的一张图像
  num = np.random.randint(1, 10000)

  # 展示初始的图像
  ax = plt.subplot(2, n, i + 1)
  plt.imshow(x_test[num])
  plt.title("original")
  plt.gray()
  ax.get_xaxis().set_visible(False)
  ax.get_yaxis().set_visible(False)

  # 展示经过自编码器处理之后的图像
  ax = plt.subplot(2, n, i + 1 + n)
  plt.imshow(decoded_imgs[num])
  plt.title("reconstructed")
  plt.gray()
  ax.get_xaxis().set_visible(False)
  ax.get_yaxis().set_visible(False)
plt.show()

最初のテストでは、畳み込みカーネル 16 と 8 を使用して 2 層畳み込みネットワークをセットアップしました。

トレーニングのために 10 回繰り返します。トレーニング プロセスとテスト結果は次のとおりです。

畳み込みネットワークの畳み込みカーネルの数は画像のチャネル数に対応し、各チャネルは元の画像の抽象化と見なすことができるため、チャネルが増えるほど、ニューラル ネットワークが取得する情報が増加し、元の画像が少ないため、次のテストを再度実行しました。

それぞれ 32 と 16 の畳み込みカーネルを持つ 2 層畳み込みネットワークをセットアップします。

トレーニングのために 10 回繰り返します。トレーニング プロセスとテスト結果は次のとおりです。

損失低減と画像フィッティングの効果が比較的良好であることがわかります。

最後に、CNN オートエンコーダーの長所と短所をまとめます。

CNN オートエンコーダは、特徴抽出と再構成に畳み込みニューラル ネットワークを使用するオートエンコーダであり、その長所と短所は次のとおりです。

アドバンテージ:

画像の局所的な特徴を抽出できる: 畳み込みニューラル ネットワークは優れた局所的な認識能力を備えており、画像の局所的な特徴を抽出できるため、CNN オートエンコーダーは画像の局所的な構造をより適切に保存できます。

特徴は適応的に学習可能: CNN オートエンコーダーは、特徴抽出器を手動で設計することなく画像の特徴を適応的に学習できるため、さまざまなデータセットやタスクに適切に適応できます。

画像のノイズ低減とアーティファクトの除去に使用可能: CNN セルフエンコーダーは画像の低次元表現を学習でき、画像のノイズ低減とアーティファクトの除去タスクに使用できます。

欠点:

長いトレーニング時間: CNN オートエンコーダーは多数のパラメーターを学習する必要があるため、トレーニング時間が長くなり、大量のコンピューティング リソースと時間を必要とします。

オーバーフィットしやすい: CNN オートエンコーダーは強力な学習能力を備えているため、トレーニング セットでオーバーフィットしやすく、その結果、テスト セットでのパフォーマンスが低下します。

大規模な画像処理の効率が低い: CNN オートエンコーダーは画像全体に対して畳み込み演算を実行する必要があるため、大規模な画像の処理効率は低くなります。

上記から、MNIST データセットのトレーニングでは、特にトレーニング データ サンプルが少ない場合、CNN オートエンコーダーを使用する効果がより優れていることがわかります。CNN オートエンコーダーは、画像データをより適切に処理できます。畳み込み層を利用して画像内の空間特徴を抽出します。これらの畳み込み層は、入力画像内の局所的なパターンと構造をキャプチャして、画像をより適切に再構成できます。さらに、CNN オートエンコーダーはプーリング層を使用して画像の空間サイズを削減することもできるため、モデルのパラメーターの数が減り、トレーニング効率が向上します。

当面はこれらの内容を学習しました。今後も続けていきます。

(記事内に間違いがあればご指摘ください!筆者は始めたばかりの初心者なので、わからないところがあるのは仕方のないことです~)

おすすめ

転載: blog.csdn.net/qq_51235856/article/details/130043631