深度学习(4)手写数字识别实战
Step0. 数据及模型准备
1. X and Y(数据准备)
(1) (xs, ys)
容量为60k,即共有6万张图片;
(2) xs.shape
: [60k, 28, 28]; ys.shape
: [60k];
(3) xs = tf.convert_to_tensor
: mnist.load_data格式为numpy,而要使用GPU需要将其转化为tensor格式;
(4) db = tf.data.Dataset.from_tensor_slices((xs, ys))
: 将数据转化为Dataset类型,这样可以利用batch一批送入多个数据,默认情况下一批送入一个数据; 如果后边加上.batch(64)
那么一批就可以送入64个数据;
(5) for step, (x, y) in enmuerate(db):print(step, x.shape,y, y.shape)
: 循环迭代db,并输出每条数据的shape,如下图所示:
注: 如果设置.batch(64)
的话,x.shape
: [64, 28, 28];y.shape
: [64];
运行结果如下图所示:
2. o u t = r e l u { r e l u { r e l u [ X @ W 1 + b 1 ] @ W 2 + b 2 } @ W 3 + b 3 } out=relu\{relu\{relu[X@W_1+b_1]@W_2+b_2\}@W_3+b_3\} out=relu{relu{relu[X@W1+b1]@W2+b2}@W3+b3}(模型准备)
(1) 降维过程: 784
→
\to
→ 512
→
\to
→ 256
→
\to
→ 10;
(2) Dense函数: 每层需要调用Dense函数,这是全连接(线性层)中的函数,用来组成每层的结构;
layers.Dense(512, activation=‘relu’),
表示图片由784降维成512,并且非线性因子(即激活函数)为relu;
layers.Dense(256, activation=‘relu’),
表示图片由512降维成256,并且非线性因子(即激活函数)为relu;
layers.Dense(10, activation=‘relu’),
表示图片由256降维成10;
(3) 每个参数的更新规则为:
w
′
=
w
−
l
r
∗
∂
l
∂
w
w'=w-lr*\frac{∂l}{∂w}
w′=w−lr∗∂w∂l;
(4) optimizer
的作用就是需要哪些参数,optimizer
就会自动按照规则进行更新,只需要设置其步长(即学习率
l
r
lr
lr)即可;
Step1&2. Cmpute o u t out out& l o s s loss loss(计算 h 1 h_1 h1、 h 2 h_2 h2和 h 3 h_3 h3)
(1) x = tf.rehsape(x, (-1, 28*28))
: 将数据进行“打平”操作,即由28*28变为784维向量;
(2) 这部分不需要考虑
h
1
h_1
h1和
h
2
h_2
h2,只需要考虑
o
u
t
out
out,最终的
o
u
t
:
[
1
,
10
]
out: [1, 10]
out:[1,10];
(3) loss = tf.reduce_sum(tf.squre(out - y)) / x.shape[0]
:
y
y
y和
o
u
t
out
out之间的欧式距离就是
l
o
s
s
loss
loss,即:
l
o
s
s
=
1
n
∑
(
y
−
o
u
t
)
2
loss=\frac{1}{n}\sum(y-out)^2
loss=n1∑(y−out)2 ;
Step3. Compute gradient and optimize(更新)
(1) tape.gradient(loss, model.trainable_variables)
: 自动求导工具,因为网络层数增加,每层都计算导数会非常麻烦,所以我们需要这个工具; tape.gradient(y, x)
就是
∂
y
∂
x
\frac{∂y}{∂x}
∂x∂y; 对于手写数字识别问题来说,
l
o
s
s
loss
loss就是
y
y
y,而model.trainable_variables
(即
[
W
1
,
W
2
,
W
3
,
b
1
,
b
2
,
b
3
]
[W_1,W_2,W_3,b_1,b_2,b_3]
[W1,W2,W3,b1,b2,b3])就是
x
x
x;
(2) 得到grads后,利用规则:
w
′
=
w
−
l
r
∗
∂
l
∂
w
w'=w-lr*\frac{∂l}{∂w}
w′=w−lr∗∂w∂l 和自动更新工具optimizer对所有参数进行更新;
Step4. Loop(循环迭代)
(1) train_dataset
里共有60k个样本,假设一次取60张图片,那么一共需要循环1000次训练,把对60k个样本进行一次训练叫做一个epoch
; 把对60张图片(即一个batch
)进行一次训练叫做一个step
; 一个epoch
通常包含多个step
;
(2) train_epoch(epoch)
: 对整个数据集迭代一次; 多次调用即可完成对数据集的多次迭代和多次更新;
(3) 将batch
设置为200,也就是一共训练30次。
运行结果如下:
注: 如果出现以下报错:
None -- [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1123)
则为证书验证问题,需要添加:
import ssl
ssl._create_default_https_context = ssl._create_unverified_context
即可。
完整代码
import os
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import datasets, layers, optimizers, Sequential, metrics
import ssl
ssl._create_default_https_context = ssl._create_unverified_context
# 设置GPU使用方式
# 获取GPU列表
gpus = tf.config.experimental.list_physical_devices('GPU')
if gpus:
try:
# 设置GPU为增长式占用
for gpu in gpus:
tf.config.experimental.set_memory_growth(gpu, True)
except RuntimeError as e:
# 打印异常
print(e)
(x, y), (x_val, y_val) = datasets.mnist.load_data()
x = tf.convert_to_tensor(x, dtype=tf.float32) / 255.
y = tf.convert_to_tensor(y, dtype=tf.int32)
y = tf.one_hot(y, depth=10)
print('datasets:', x.shape, y.shape)
train_dataset = tf.data.Dataset.from_tensor_slices((x, y))
train_dataset = train_dataset.batch(200)
model = keras.Sequential([
layers.Dense(512, activation='relu'),
layers.Dense(256, activation='relu'),
layers.Dense(10)])
optimizer = optimizers.SGD(lr=0.01)
def train_epoch(epoch):
# Step4. loop
for step, (x, y) in enumerate(train_dataset):
with tf.GradientTape() as tape:
# 打平操作,[b, 28, 28] => [b, 784]
x = tf.reshape(x, (-1, 28 * 28))
# Step1. 得到模型输出output [b, 784] => [b, 10]
out = model(x)
# Step2. Compute loss
loss = tf.reduce_sum(tf.square(out - y)) / x.shape[0]
# Step3. optimizer and update w1, w2, w3, b1, b2, b3
grads = tape.gradient(loss, model.trainable_variables)
# w' = w - lr * grad
optimizer.apply_gradients(zip(grads, model.trainable_variables))
if step % 100 == 0:
print(epoch, step, loss.numpy())
def train():
for epoch in range(30):
train_epoch(epoch)
if __name__ == '__main__':
train()
运行结果
.
.
.
...
...
参考文献:
[1] 龙良曲:《深度学习与TensorFlow2入门实战》
[2] https://blog.csdn.net/qq_43653405/article/details/108449661