一緒に書く習慣をつけましょう!「ナゲッツデイリーニュープラン・4月アップデートチャレンジ」に参加して8日目です。クリックしてイベントの詳細をご覧ください。
バニラニューラルネットワークをトレーニングする
ニューラルネットワークの基本概念を学び、keras
ライブラリので、このセクションではさらに一歩進んで、実装することでニューラルネットワークの力を垣間見ることができます。実用的なモデル。
バニラニューラルネットワークとMNISTデータセットの概要
入力と出力の間に完全に接続された複数の層を積み重ねるネットワークは多層パーセプトロンと呼ばれ、口語的香草
にニューラルネットワーク(つまり、元のニューラルネットワーク)と呼ばれることもあります。バニラニューラルネットワークをトレーニングする方法を確認するために、データセット内の数字のラベルをMNIST
予測するデータセットは、さまざまな人のMNIST
手書きの数字で構成される非常に一般的に使用されるデータセットであり、トレーニングセットには画像が含まれ、テストセットには画像、各画像にはラベルがあり、画像サイズはです。250
60000
10000
28*28
Kerasを使用したニューラルネットワークモデルの構築
- 関連するパッケージとデータセットをインポートし、データセットを視覚化してデータを理解します。
from keras.datasets import mnist
import numpy as np
from keras.models import Sequential
from keras.layers import Dense, Dropout
from keras.utils import np_utils
import matplotlib.pyplot as plt
(x_train, y_train), (x_test, y_test) = mnist.load_data()
复制代码
上記のコードで、関連するKeras
メソッドとMNIST
データセットをインポートします。
MNIST
データセット内の画像の形状は次のとおり28 x 28
です。データセットをよりよく理解するために、データセット内のいくつかの画像をプロットします。
plt.subplot(221)
plt.imshow(x_train[0], cmap='gray')
plt.subplot(222)
plt.imshow(x_train[1], cmap='gray')
plt.subplot(223)
plt.imshow(x_test[0], cmap='gray')
plt.subplot(224)
plt.imshow(x_test[1], cmap='gray')
plt.show()
复制代码
次の画像は、上記のコードの出力を示しています。
28 x 28
画像をフラット化して、入力が1次元の784ピクセル値に変換され、Dense
レイヤーに入力されるようにします。また、ラベルはワンホットエンコーディングに変換する必要があります。このステップは、データセットの準備プロセスで重要です。
num_pixels = x_train.shape[1] * x_train.shape[2]
x_train = x_train.reshape(-1, num_pixels).astype('float32')
x_test = x_test.reshape(-1, num_pixels).astype('float32')
复制代码
在上示代码中,使用 reshape
方法对输入数据集进行形状变换,np.reshape()
将给定形状的数组转换为不同的形状。在此示例中,x_train
数组具有 x_train.shape[0]
个数据点(图像),每个图像中都有 x_train.shape[1]
行和 x_train.shape[2]
列, 我们将其形状变换为具有 x_train.shape[0]
个数据,每个数据具有 x_train.shape [1] * x_train.shape[2]
个值的数组。 接下来,我们将标签数据编码为独热向量:
y_train = np_utils.to_categorical(y_train)
y_test = np_utils.to_categorical(y_test)
num_classes = y_test.shape[1]
复制代码
我们简单了解下独热编码的工作原理。假设有一数据集的可能标签为 {apple,orange,banana,lemon,pear},如果我们将相应的标签转换为独热编码,则如下所示:
类别 | 索引0 | 索引1 | 索引2 | 索引3 | 索引4 |
---|---|---|---|---|---|
apple | 1 | 0 | 0 | 0 | 0 |
orange | 0 | 1 | 0 | 0 | 0 |
banana | 0 | 0 | 1 | 0 | 0 |
lemon | 0 | 0 | 0 | 1 | 0 |
pear | 0 | 0 | 0 | 0 | 1 |
每个独热向量含有
个数值,其中
为可能的标签数,且仅有标签对应的索引处的值为 1 外,其他所有值均为 0。如上所示,apple
的独热编码可以表示为 [1, 0, 0, 0, 0]
。在 Keras
中,使用 to_categorical
方法执行标签的独热编码,该方法找出数据集中唯一标签的数量,然后将标签转换为独热向量。
- 用具有 1000 个节点的隐藏层构建神经网络:
model = Sequential()
model.add(Dense(1000, input_dim=num_pixels, activation='relu'))
model.add(Dense(num_classes, activation='softmax'))
复制代码
输入具有 28×28=784
个值,这些值与隐藏层中的 1000
个节点单元相连,指定激活函数为 ReLU
。最后,隐藏层连接到具有 num_classes=10
个值的输出 (有十个可能的图像标签,因此 to_categorical
方法创建的独热向量有 10
列),在输出的之前使用 softmax
激活函数,以便获得图像的类别概率。
- 上述模型架构信息可视化如下所示:
model.summary()
复制代码
架构信息输出如下:
Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
dense (Dense) (None, 1000) 785000
_________________________________________________________________
dense_1 (Dense) (None, 10) 10010
=================================================================
Total params: 795,010
Trainable params: 795,010
Non-trainable params: 0
_________________________________________________________________
复制代码
在上述体系结构中,第一层的参数数量为 785000
,因为 784
个输入单元连接到 1000
个隐藏层单元,因此在隐藏层中包括 784 * 1000
权重值加 1000
个偏置值,总共 785000
个参数。类似地,输出层有10个输出,分别连接到 1000
个隐藏层,从而产生 1000 * 10
个权重和 10
个偏置(总共 10010
个参数)。输出层有 10
个节点单位,因为输出中有 10
个可能的标签,输出层为我们提供了给定输入图像的属于每个类别的概率值,例如第一节点单元表示图像属于 0 的概率,第二个单元表示图像属于 1 的概率,以此类推。
- 编译模型如下:
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['acc'])
复制代码
因为目标值是包含多个类别的独热编码矢量,所以损失函数是多分类交叉熵损失。此外,我们使用 Adam
优化器来最小化损失函数,在训练模型时,监测准确率 (accuracy
,可以简写为 acc
) 指标。
- 拟合模型,如下所示:
history = model.fit(x_train, y_train,
validation_data=(x_test, y_test),
epochs=50,
batch_size=64,
verbose=1)
复制代码
上述代码中,我们指定了模型要拟合的输入(x_train)和输出(y_train);指定测试数据集的输入和输出,模型将不会使用测试数据集来训练权重,但是,它可以用于观察训练数据集和测试数据集之间的损失值和准确率有何不同。
- 提取不同epoch的训练和测试损失以及准确率指标:
history_dict = history.history
loss_values = history_dict['loss']
val_loss_values = history_dict['val_loss']
acc_values = history_dict['acc']
val_acc_values = history_dict['val_acc']
epochs = range(1, len(val_loss_values) + 1)
复制代码
在拟合模型时,history
变量会在训练和测试数据集的每个 epoch
中存储与模型相对应的准确率和损失值,我们将这些值提取存储在列表中,以便绘制在训练数据集和测试数据集中准确率和损失的变化。
- 可视化不同epoch的训练和测试损失以及准确性:
plt.subplot(211)
plt.plot(epochs, loss_values, marker='x', label='Traing loss')
plt.plot(epochs, val_loss_values, marker='o', label='Test loss')
plt.title('Training and test loss')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend()
plt.subplot(212)
plt.plot(epochs, acc_values, marker='x', label='Training accuracy')
plt.plot(epochs, val_acc_values, marker='o', label='Test accuracy')
plt.title('Training and test accuracy')
plt.xlabel('Epochs')
plt.ylabel('Accuracy')
plt.legend()
plt.show()
复制代码
上記のコードを実行するための入力を次のグラフに示します。最初のグラフは、epoch
数値示し、2番目のグラフはepoch
、数値が増加するにつれてトレーニングとテストの精度を示します。
最終的なモデルは約97%正確です。
- さらに、テストセットの最終モデルの精度を手動で計算することもできます。
preds = model.predict(x_test)
correct = 0
for i in range(len(x_test)):
pred = np.argmax(preds[i], axis=0)
act = np.argmax(y_test[i], axis=0)
if (pred == act):
correct += 1
else:
continue
accuracy = correct / len(x_test)
print('Test accuracy: {:.4f}%'.format(accuracy*100))
复制代码
上記のコードpredict
でx_test
は、特定の入力(ここ)の予測出力値は、モデルの方法を使用して計算されます。次に、を使用してテストセットのすべての予測をループし、最も高い確率値を持つインデックスをargmax
計算します。同時に、テストデータセットの実際のラベル値についても同じことを行います。テストデータセットの予測値と真の値では、最も高い確率値のインデックスが同じであり、予測が正しいことを示しています。テストデータセット内の正しい予測の数をデータの合計量で割った値テストデータセットはモデルの精度です。
関連リンク
ニューラルネットワークの順伝播を最初から学ぶ-ナゲッツ(juejin.cn)