皆さんこんにちは、ドンドンカンです。
画像認識の入門プロジェクトは数多くありますが、その中で間違いなく最も人気があるのは Mnist 手書き数字認識です。
このプロジェクトは、データセットが小さく、ニューラルネットワークが単純で、タスクが単純であるという利点を持ち、CNNネットワークにあるべきものを統合しており、スズメは小さいながらもすべての内臓を備えていると言えます。
初心者が学ぶのに非常に適しています。
この記事では、コードのウォークスルー形式でプロジェクトの詳細を説明します。
コードのダウンロード リンクは記事の最後に添付されており、GPU を使用せずにニューラル ネットワークを最初からトレーニングできます。
手書き数字認識とは
簡単に言えば、手書きの数字の認識を完了できる畳み込みニューラル ネットワークを構築することです。
紙にペンで 6 を書くと、ニューラル ネットワークがそれが 6 であると認識し、8 を書くと、ニューラル ネットワークがそれが 8 であると認識します。それはとても簡単です。
このタスクが単純である理由は、ラベルに 0 ~ 9 の 10 個の分類しかなく、resnet や ImageNet 上の他のネットワークの 1000 個の分類よりもはるかに少ないためです。
シンプルではありますが、その背後には多くの原則があり、典型的な CNN トレーニングとアルゴリズムはすべて含まれていません。
このプロジェクトと合わせて、有名な MNIST (Mathematical Numbers In Text) データセットです。
データセットには 60,000 枚のトレーニング画像と 10,000 枚のテスト画像が含まれており、画像はあらゆる種類の手書きの数字であり、基本的には次のようになります。
7 ステップの集中コード読み取り
プロジェクトの背景を簡単に理解した後、コードを読む形式で少しずつニューラル ネットワークを紹介していきます。
ステップ 1: 必要なライブラリをインポートする
# 导入NumPy数学工具箱
import numpy as np
# 导入Pandas数据处理工具箱
import pandas as pd
# 从 Keras中导入 mnist数据集
from keras.datasets import mnist
Keras は、オープンソースの人工ニューラル ネットワーク ライブラリであり、使用される mnist データ セットを含む、多くの古典的なニューラル ネットワークとデータ セットが含まれています。
ステップ 2: データセットをロードする
(x_train, y_train), (x_test, y_test)
= mnist.load_data()
このコマンドは、keras に付属の mnist モジュールを使用してデータセット (load_data) をロードし、それを 4 つの変数に割り当てます。
その中で、x_train はトレーニングに使用される画像を保存し、y_train は対応するラベルです。画像内の数値が 1 であるとすると、ラベルは 1 になります。
x_test と y_test はそれぞれ検証に使用する画像とラベル、つまり検証セットです。ニューラル ネットワークがトレーニングされた後、検証セット内のデータを使用して検証できます。
ステップ 3: データの前処理
前処理の内容の 1 つは、モデルの要件を満たすようにデータセットの形状を変更することです。
# 导入keras.utils工具箱的类别转换工具
from tensorflow.keras.utils import to_categorical
# 给标签增加维度,使其满足模型的需要
# 原始标签,比如训练集标签的维度信息是[60000, 28, 28, 1]
X_train = X_train_image.reshape(60000,28,28,1)
X_test = X_test_image.reshape(10000,28,28,1)
# 特征转换为one-hot编码
y_train = to_categorical(y_train_lable, 10)
y_test = to_categorical(y_test_lable, 10)
このデータセットには合計 60,000 枚のトレーニング画像と 10,000 枚の検証画像があり、各画像の長さと幅は 28 ピクセル、チャネル数は 1 です。
次に、トレーニング セット x_train の形状を NHWC = [60000, 28, 28, 1] に変更します。検証セットも同様です。
to_categorical の役割は、サンプル ラベルをワンホット エンコーディングに変換することであり、ワンホット エンコーディングの役割は、カテゴリの確率またはスコアをより適切に計算することです。
ワンホット
ワンホット エンコーディングが使用される理由は、0 ~ 9 を出力する 10 個のラベルについて、各ラベルのステータスが等しい必要があり、ラベル番号 2 が番号 1 より大きい状況が存在しないためです。
ただし、ラベルの元の値 (0 ~ 9) を直接使用して最終結果を計算すると、ラベル 2 がラベル 1 より大きくなる状況が発生します。
したがって、ほとんどの場合、ラベル間にサイズが存在しないように、ラベルをワンホット エンコーディング、つまりワンホット エンコーディングに変換する必要があります。
この例では、0 ~ 9 の数字のワンホット エンコーディングは次のとおりです。
array([[1., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 1., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 1., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 1., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 1., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 1., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 1., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 1., 0., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 1., 0.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 1.]]
ベクトルの各行はラベルを表します。
[1., 0., 0., 0., 0., 0., 0., 0., 0., 0.] が 0 を表し、[0., 1., 0., 0., 0.] が表されるとします。 , 0., 0., 0., 0., 0.] は 1 を表します。両者は直交独立していることがわかり、どちらが大きいかという問題はありません。
ステップ 4: ニューラル ネットワークを作成します。
# 从 keras 中导入模型
from keras import models
# 从 keras.layers 中导入神经网络需要的计算层
from keras.layers import Dense, Dropout, Flatten, Conv2D, MaxPooling2D
# 构建一个最基础的连续的模型,所谓连续,就是一层接着一层
model = models.Sequential()
# 第一层为一个卷积,卷积核大小为(3,3), 输出通道32,使用 relu 作为激活函数
model.add(Conv2D(32, (3, 3), activation='relu',
input_shape=(28,28,1)))
# 第二层为一个最大池化层,池化核为(2,2)
# 最大池化的作用,是取出池化核(2,2)范围内最大的像素点代表该区域
# 可减少数据量,降低运算量。
model.add(MaxPooling2D(pool_size=(2, 2)))
# 又经过一个(3,3)的卷积,输出通道变为64,也就是提取了64个特征。
# 同样为 relu 激活函数
model.add(Conv2D(64, (3, 3), activation='relu'))
# 上面通道数增大,运算量增大,此处再加一个最大池化,降低运算
model.add(MaxPooling2D(pool_size=(2, 2)))
# dropout 随机设置一部分神经元的权值为零,在训练时用于防止过拟合
# 这里设置25%的神经元权值为零
model.add(Dropout(0.25))
# 将结果展平成1维的向量
model.add(Flatten())
# 增加一个全连接层,用来进一步特征融合
model.add(Dense(128, activation='relu'))
# 再设置一个dropout层,将50%的神经元权值为零,防止过拟合
# 由于一般的神经元处于关闭状态,这样也可以加速训练
model.add(Dropout(0.5))
# 最后添加一个全连接+softmax激活,输出10个分类,分别对应0-9 这10个数字
model.add(Dense(10, activation='softmax'))
上記のコードの各行には、各行の機能を説明するコメントが付けられています。わずか数行で、この手書き数字認識ニューラル ネットワークの全体が構成されます。
ステップ 5: トレーニング
# 编译上述构建好的神经网络模型
# 指定优化器为 rmsprop
# 制定损失函数为交叉熵损失
model.compile(optimizer='rmsprop',
loss='categorical_crossentropy',
metrics=['accuracy'])
# 开始训练
model.fit(X_train, y_train, # 指定训练特征集和训练标签集
validation_split = 0.3, # 部分训练集数据拆分成验证集
epochs=5, # 训练轮次为5轮
batch_size=128) # 以128为批量进行训练
エポック 5/5
329/329 [===============================] - 15 秒 46ms/ステップ - 損失: 0.1054 - 精度 : 0.9718 - val_loss: 0.0681 - val_accuracy: 0.9826
トレーニング結果は上記の通りで、最終的なトレーニング精度は 98.26% に達しており、非常に高いことがわかります。
ステップ 6: 検証セットの検証
# 在测试集上进行模型评估
score = model.evaluate(X_test, y_test)
print('测试集预测准确率:', score[1]) # 打印测试集上的预测准确率
313/313 [===============================] - 1 秒 4ms/ステップ - 損失: 0.0662 - 精度: 0.9815 テストセット予測精度: 0.9815000295639038
検証セットの精度も 98% であることがわかります。
ステップ 7: 画像を確認する
# 预测验证集第一个数据
pred = model.predict(X_test[0].reshape(1, 28, 28, 1))
# 把one-hot码转换为数字
print(pred[0],"转换一下格式得到:",pred.argmax())
# 导入绘图工具包
import matplotlib.pyplot as plt
# 输出这个图片
plt.imshow(X_test[0].reshape(28, 28),cmap='Greys')
検証セットの最初の画像を検証の例として取り上げます。
1/1 [==============================] - 0s 17ms/ステップ
[4.2905590e-15 2.6790809e-11 2.8249305 e-09 2.3393848e-11 7.1304548e-14
1.8217797e-18 5.7493907e-19 1.0000000e+00 8.0317367e-15 4.6352322e-10]
形式を変換して取得します: 7
得られた数字は7、絵が表示されると確かに7です。これは、トレーニングされたモデルが実際に数値を認識するレベルに達していることを示しています。
要約する
手書き数字認識プロジェクトは、畳み込み層が 2 つだけと比較的単純で、全体の計算負荷も大きくなく、現在のコンピュータ構成に関する限り、ノートブックでも基本的にニューラル ネットワークのトレーニングと検証を完了できます。
興味があれば、「ドン・ドンカンは包囲ライオン」の公式アカウントに注目し、バックグラウンドで[mnist]に返信してソースコードを入手して実践してください。