python深度学习——一个简单的全连接神经网络,预测mnist手写数字

代码来自《python深度学习》第二章:

from tensorflow.keras.datasets import mnist
from tensorflow import keras
from tensorflow.keras import layers


(train_images, train_labels), (test_images, test_labels) = mnist.load_data()
print(train_images.shape)
print(len(train_labels))
print(len(test_labels))

model = keras.Sequential([
    layers.Dense(512, activation="relu"),
    layers.Dense(10, activation="softmax")
])
model.compile(optimizer="rmsprop",
              loss="sparse_categorical_crossentropy",
              metrics=["accuracy"])

train_images = train_images.reshape((60000, 28 * 28))
train_images = train_images.astype("float32") / 255
test_images = test_images.reshape((10000, 28 * 28))
test_images = test_images.astype("float32") / 255
model.fit(train_images, train_labels, epochs=5, batch_size=128)
test_digits = test_images[0:10]
predictions = model.predict(test_digits)
print(predictions[0])
print(predictions[0].argmax())
print(predictions[0][7])
print(test_labels[0])
test_loss, test_acc = model.evaluate(test_images, test_labels)
print(f"test_acc: {test_acc}")

 

输出:

(60000, 28, 28)
60000
10000
2023-10-03 23:37:08.456556: I tensorflow/core/platform/cpu_feature_guard.cc:182] This TensorFlow binary is optimized to use available CPU instructions in performance-critical operations.      
To enable the following instructions: SSE SSE2 SSE3 SSE4.1 SSE4.2 AVX AVX2 AVX_VNNI FMA, in other operations, rebuild TensorFlow with the appropriate compiler flags.
Epoch 1/5
469/469 [==============================] - 2s 3ms/step - loss: 0.2671 - accuracy: 0.9231
Epoch 2/5
469/469 [==============================] - 1s 3ms/step - loss: 0.1078 - accuracy: 0.9684
Epoch 3/5
469/469 [==============================] - 1s 3ms/step - loss: 0.0707 - accuracy: 0.9792        
Epoch 4/5
469/469 [==============================] - 1s 3ms/step - loss: 0.0510 - accuracy: 0.9847
Epoch 5/5
469/469 [==============================] - 1s 3ms/step - loss: 0.0386 - accuracy: 0.9884
1/1 [==============================] - 0s 50ms/step
[2.5713994e-08 2.8117824e-09 1.9046666e-06 7.1580653e-06 1.1753074e-11
 9.5235375e-09 1.4759939e-12 9.9999058e-01 2.0594142e-08 3.4270093e-07]
7
0.9999906
7
313/313 [==============================] - 1s 2ms/step - loss: 0.0691 - accuracy: 0.9791
test_acc: 0.9790999889373779

  

【代码说明】 

这是一个简单的全连接神经网络(也称为密集连接网络或多层感知器),由两个 Dense 层组成。

1. 第一层是一个 Dense 层,有 512 个神经元,使用了 "relu"(线性整流单元)作为激活函数。这一层接收输入数据,并使用权重矩阵进行线性变换,然后应用 "relu" 激活函数。"relu" 函数的作用是将所有负值变为 0,这可以增加模型的非线性,使其能够学习更复杂的模式。

2. 第二层也是一个 Dense 层,有 10 个神经元,对应于 10 个类别(因为 MNIST 数据集有 10 个手写数字类别)。这一层使用了 "softmax" 作为激活函数,它可以将每个神经元的输出转换为概率分布,即所有输出值都在 0 到 1 之间,并且所有输出值的和为 1。这样,每个神经元的输出就可以被解释为输入属于对应类别的概率。

这个网络的输入应该是一个向量,长度为 784(因为 MNIST 图像的大小是 28x28,所以在输入网络之前,图像被展平为一个 784 维的向量)。网络的输出是一个长度为 10 的向量,表示输入图像属于每个类别的概率。
 
sparse_categorical_crossentropy的公式是什么?
该交叉熵损失的公式是:
L = - sum(y_true * log(y_pred))

其中:
- y_true 是真实的标签,它是一个 one-hot 编码的向量,表示真实的类别。
- y_pred 是模型预测的概率分布,它是一个向量,其长度等于类别的数量,每个元素表示对应类别的预测概率。
- log 是自然对数。
- * 表示元素级别的乘法。
- sum 表示对所有类别进行求和。

这个公式的含义是,对于每个类别,计算真实标签和预测概率之间的乘积,然后取对数,最后对所有类别求和。这个值越小,表示模型的预测结果越接近真实标签,模型的性能越好。

 

回忆下:

二分类交叉熵损失的公式是:

L = - (y_true * log(y_pred) + (1 - y_true) * log(1 - y_pred))

其中:
- y_true 是真实的标签,它是一个二进制值,表示真实的类别(0 或 1)。
- y_pred 是模型预测的概率,它是一个在 0, 1] 范围内的值,表示预测为类别 1 的概率。
- log 是自然对数。

这个公式的含义是,对于每个样本,计算真实标签和预测概率之间的交叉熵,然后对所有样本求和。这个值越小,表示模型的预测结果越接近真实标签,模型的性能越好。 

 

再回忆下信息熵:

信息熵的公式是:

H(X) = - sum(p(x) * log(p(x)))

其中:
- X 是一个随机变量。
- p(x) 是 X 取值 x 的概率。
- log 是自然对数。
- sum 表示对所有可能的 x 进行求和。

这个公式的含义是,对于每个可能的 x,计算其概率 p(x) 和 log(p(x)) 的乘积,然后对所有的 x 求和。信息熵 H(X) 表示的是随机变量 X 的不确定性或者说信息量。如果 X 的所有可能取值的概率都相等,那么 H(X) 就最大,表示 X 的不确定性最大。

交叉熵无非是将p(x)换了下而已,见我之前写的文章。

 

【写在最后】

上述代码测试精度约为97.8%,比训练精度(98.9%)低不少。训练精度和测试精度之间的这种差距是过拟合(overfit)造成的。过拟合是指机器学习模型在新数据上的性能往往比在训练数据上要差,它是第4章的核心主题。

 

 

posted @ 2023-10-03 23:49  bonelee  阅读(75)  评论(0编辑  收藏  举报