mnist手写数字识别_使用残差网络实现MNIST手写数字识别

在上一节的内容中我们已经介绍了残差网络的相关知识,并使用数学知识进行了原理解释,我们知道深度网络随着层数的增加,很容易造成“退化”和“梯度消失”的问题,训练数据的过拟合,ResNet中给出了一种解决方案:增加一个identity mapping,今天的内容主要是使用残差网络处理MNIST手写数字识别数据集。实现的流程主要如下所示:1导入相关模块2 定义Block类3 定义相关函数4 求解损失函数第一是先导入MNIST数据集,定义权重和偏置量:

05dfd003243346b48c39f0d02a2e6c59.png

在第二步中,我们根据输入和输出的尺寸是否相同,分为identity_block和conv_block,每种block都有如下两种模式:3卷积和2卷积形式,3卷积的速度的要更快一些。定义identity_block层的代码如下,下面是有3个卷积层,在输出的时候把输入值x_input和经过3层卷积层后输出的x相加,使用激活函数relu后输出得到result

f7fbe3616b458e7cf25d9effdcae7726.png

下面是定义conv_block模块,由于该模块定义时输入和输出尺度不同,所以我们使用一个卷积层改变原来输入x_input的尺寸;再和3层卷积层操作后输出的x进行融合,通过一个激活函数relu,得到result

8a4a68585fcc56edbf9e7a6a0cc21757.png

输入我们要使用的值x1,由x1经过一层卷积、池化等操作后成为残差网络的输入,在下面的代码中我们给出了3个x2,其中一个是使用convolutional_block函数求出的,另外两个是使用identity_block函数求出,一个为block b,一个为block c,大小都是14x14x246,经过reshape操作后大小变为7x7x256. 最后是一个全连接层,全连接层这里使用到了droupout函数

4b3815cde9f899352c5135e3a2bd85c7.png

建立损失函数,使用交叉熵来计算:

b90881cd39c2803e789517236369e61e.png


初始化变量,每100次训练输出一次值出来;

9ab64d2b0c874446be622bda95e4cb27.png

最后是我们输出的结果:

e52a95182083f29b7573165a033d2807.png

可以看到准确率已经达到97.4%,我们训练次数越多,这个效果会更加好,下面我们把训练次数增加到20000次,结果显示准确率达到了98.2%

232ed3416194d6c9d8f574f4ceff7491.png


总结:本节用tensorflow实现了一个残差网络,通过代码可以发现,残差网络的设置并不难,只需要把经过卷积和池化操作后的输出值和输入值相加就得到了残差网络的输出。我们可以发现设置了残差网络后的效果也是很好的,训练20000次的准确率已经有98%了。读者如果有兴趣的话,可以多设置几个卷积层进行实验,看看最终的结果会如何,同时也可以利用我们前两节讲的保存模型方法来把我们训练后的model保存下来,以方便下次再使用。

关注小鲸融创,一起深度学习金融科技!

e4f0781c835ea9723899acfa3268d558.png
以下是使用ResNet网络模型实现MNIST手写数字识别代码示例: ```python import tensorflow as tf from tensorflow.keras.datasets import mnist from tensorflow.keras.layers import Input, Conv2D, BatchNormalization, ReLU, Add, GlobalAveragePooling2D, Dense from tensorflow.keras.models import Model # 加载MNIST数据集 (x_train, y_train), (x_test, y_test) = mnist.load_data() # 数据预处理:将像素值缩放到0到1之间,并增加一维通道数 x_train = x_train.astype('float32') / 255.0 x_train = x_train.reshape(x_train.shape[0], 28, 28, 1) x_test = x_test.astype('float32') / 255.0 x_test = x_test.reshape(x_test.shape[0], 28, 28, 1) # 定义ResNet网络模型 def residual_block(inputs, filters, strides=1): shortcut = inputs # 第一个卷积层 x = Conv2D(filters, kernel_size=3, strides=strides, padding='same')(inputs) x = BatchNormalization()(x) x = ReLU()(x) # 第二个卷积层 x = Conv2D(filters, kernel_size=3, strides=1, padding='same')(x) x = BatchNormalization()(x) # 如果输入和输出的维度不同,则使用1x1卷积调整维度 if shortcut.shape[-1] != filters: shortcut = Conv2D(filters, kernel_size=1, strides=strides, padding='same')(shortcut) shortcut = BatchNormalization()(shortcut) # 将残差块的输出与输入相加,构成下一层的输入 x = Add()([x, shortcut]) x = ReLU()(x) return x def ResNet(input_shape=(28, 28, 1), num_classes=10): inputs = Input(shape=input_shape) # 第一层卷积 x = Conv2D(64, kernel_size=3, strides=1, padding='same')(inputs) x = BatchNormalization()(x) x = ReLU()(x) # 残差块组1 x = residual_block(x, filters=64, strides=1) x = residual_block(x, filters=64, strides=1) x = residual_block(x, filters=64, strides=1) # 残差块组2 x = residual_block(x, filters=128, strides=2) x = residual_block(x, filters=128, strides=1) x = residual_block(x, filters=128, strides=1) # 残差块组3 x = residual_block(x, filters=256, strides=2) x = residual_block(x, filters=256, strides=1) x = residual_block(x, filters=256, strides=1) # 残差块组4 x = residual_block(x, filters=512, strides=2) x = residual_block(x, filters=512, strides=1) x = residual_block(x, filters=512, strides=1) # 全局平均池化 x = GlobalAveragePooling2D()(x) # 全连接层 x = Dense(num_classes, activation='softmax')(x) model = Model(inputs=inputs, outputs=x) return model # 创建ResNet模型 model = ResNet(num_classes=10) # 编译模型 model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy']) # 训练模型 model.fit(x_train, y_train, batch_size=128, epochs=10, validation_data=(x_test, y_test)) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值