TensorFlow学习笔记(5)之卷积神经网络

说到神经网络就离不开卷积,卷积神经网络的使用让我们能更加方便地去优化和更新模型。

神经网络即指人工神经网络,亦或称之为连接模型。依靠系统的复杂程度,通过调整内部大量节点间的权重参数,进而去学习如何处理和识别信息。在神经网络的内部使用的是向量乘法,实现自我学习的目的。

传统意义上的神经网络只有输入层、隐藏层和输出层,输入层和输出层的神经元个数我们很容易通过输入参数和可能的输出结果来确定,但是至今为止并没有哪一篇文章明确的说明隐藏层设置为多少层才是最合适的。

神经网络中权重参数的变化更是一个谜。我们并不能看到参数如何变化,甚至不明白某一个参数为什么这么变化(当然,我们知道整个网络都在很努力的向着我们期望的方向变化)。诚然,我们能够看到训练过后的参数,但这并不能对我们更深一步地理解它有所裨益。

整个网络像是黑匣子一般,似乎我们将数据输入之后就只能听天由命。

常见神经网络

全连接神经网络:每个神经元与前后相邻层的每一个神经元都有连接关系,输入是特征,输出为预测结果。

参数个数:

卷积神经网络:多层感知机,采用局部连接和权值共享的方式,一方面减少了权值数量使网络易于优化,一方面降低了模型复杂度使过拟合降低。

卷积神经网络的发展

LeNet5 第一个CNN

AlexNet 引入了 ReLU 和 dropout,relu函数提训练速度,dropout缓解过拟合;

VGGNet 小尺寸卷积核减少参数,网络结构规整,适合并行加速。常用 VGGNet-16 和 VGGNet19

Google Inception Net 1、用全局的平均池化取代最后的全连接层;2、引入 Inception Module 的4分支结合结构,每一个分支都运用了1x1的卷积。用较少的参数达到非线性和特征变换;3、Inception V2 版将所有的 5x5 变成 2 个 3x3,提出了 Batch Normalization(批正则化:提升感知能力)缓解过拟合、梯度消失;4、Inception V3 版将较大的二位卷积拆分成较小的一维卷积,加速运算、减少过拟合,同时更改了 Inception Module 的结构。

ResNet残差网络 层间残差跳连,引入前方信息,缓解模型退化,使神经网络层数加深成为可能。

常见的图片处理方式:先对原始图像进行特征提取,再把提取到的特征送给全连接神经网络。

卷积计算就是一个有效提取特征的过程

一般会用一个正方形的卷积核,按指定步长,在输入特征图上滑动遍历输入特征图上的所有像素点。每一个步长,卷积核都会与特征图上的像素点出现重合区域,重合区域的对应元素相乘、求和后再加上偏置项得到输出特征的一个像素点。

卷积核的通道数(个数)要与图片的通道数相同,灰度图只有一个通道,彩色图有三通道。卷积核会在每一个通道上提取不同的特征。输入特征图的深度决定了当前层卷积核的深度,当前层卷积核的深度决定了输出特征图的深度,提高卷积核的个数可以增加该层提取特征的能力,有n个卷积核就生成n个输出特征图,新生成的特征图叠加排列在后边,也就是常说的输出特征图通道数。

权值共享:借助卷积实现权值共享,通过卷积计算层提取空间特征,进入全连接神经网络。在图片的尺寸缩小时,往往通道数要增多,保留信息的完整性,达到不丢失信息的目的。

感受野:卷积神经网络各输出特征图中的每个像素点,在原始输入图片上映射区域的大小,根据映射到原始图片的像素区域来判断感受野大小。

感受野大小的优劣:两个3*3的卷积核和一个5*5的卷积核作用是相同的。但是当输入特征图边长大于10的时候,两层的3*3卷积核比一层的5*5卷积核更好,因为待训练的参数更少,计算量更小。这也就解释了为什么Google Inception Net 要使用1*1代替2*2。

全0填充:卷积会让图片的尺寸越来越小,为了使输入和输出图片边长一致,给图片四周进行全0填充。

批标准化:随着网络层数的增加,特征数据会出现偏离0的情况,因此要对数据进行批标准化,标准化后数据符合以0为均值,1为标准差的正态分布,将偏移的数据拉回0附近,常用在激活和卷积之间,提升了数据的区分力。通过缩放因子和偏移因子改变特征数据的宽窄,使其保持在较好的范围。

dropout层:在神经网络训练时,将一部分神经元按照一定的概率从神经网络中暂时舍弃。神经网络使用时,被舍弃的神经元恢复连接。

卷积层

池化:用于减少特征数据量。最大值池化可提取图片纹理,均值池化可保留背景特征。

卷积神经网络的主要模块

口诀:CBAPD

Lenet 代码注释:

import tensorflow as tf
import os
# 引入文件处理包
import numpy as np
from matplotlib import pyplot as plt
from tensorflow.keras.layers import Conv2D, BatchNormalization, Activation, MaxPool2D, Dropout, Flatten, Dense
# 从keras.layers引入Conv2D, BatchNormalization, Activation, MaxPool2D, Dropout, Flatten, Dense 等函数
from tensorflow.keras import Model
# 引入model模型

np.set_printoptions(threshold=np.inf)
# 控制显示的小数精度

cifar10 = tf.keras.datasets.cifar10
(x_train, y_train), (x_test, y_test) = cifar10.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0


class LeNet5(Model):
    def __init__(self):
        super(LeNet5, self).__init__()
        # super 调用父类函数,继承函数
        self.c1 = Conv2D(filters=6, kernel_size=(5, 5),
                         activation='sigmoid')
        # 卷积层,卷积核为6,卷积核大小为5*5,激活函数为sigmoid
        self.p1 = MaxPool2D(pool_size=(2, 2), strides=2)
        # 池化层,最大池化,池化核的尺寸2*2,步长为2
        self.c2 = Conv2D(filters=16, kernel_size=(5, 5),
                         activation='sigmoid')
        # 卷积层,卷积核16,尺寸5*5
        self.p2 = MaxPool2D(pool_size=(2, 2), strides=2)
        # 最大池化,
        self.flatten = Flatten()
        # 拉直层
        self.f1 = Dense(120, activation='sigmoid')
        # 全连接层
        self.f2 = Dense(84, activation='sigmoid')
        self.f3 = Dense(10, activation='softmax')

    def call(self, x):
        x = self.c1(x)
        x = self.p1(x)

        x = self.c2(x)
        x = self.p2(x)

        x = self.flatten(x)
        x = self.f1(x)
        x = self.f2(x)
        y = self.f3(x)
        return y


model = LeNet5()

model.compile(optimizer='adam',
              loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False),
              metrics=['sparse_categorical_accuracy'])

checkpoint_save_path = "./checkpoint/LeNet5.ckpt"
if os.path.exists(checkpoint_save_path + '.index'):
    print('-------------load the model-----------------')
    model.load_weights(checkpoint_save_path)

cp_callback = tf.keras.callbacks.ModelCheckpoint(filepath=checkpoint_save_path,
                                                 save_weights_only=True,
                                                 save_best_only=True)

history = model.fit(x_train, y_train, batch_size=32, epochs=5, validation_data=(x_test, y_test), validation_freq=1,
                    callbacks=[cp_callback])
model.summary()

# print(model.trainable_variables)
file = open('./weights.txt', 'w')
for v in model.trainable_variables:
    file.write(str(v.name) + '\n')
    file.write(str(v.shape) + '\n')
    file.write(str(v.numpy()) + '\n')
file.close()

###############################################    show   ###############################################

# 显示训练集和验证集的acc和loss曲线
acc = history.history['sparse_categorical_accuracy']
val_acc = history.history['val_sparse_categorical_accuracy']
loss = history.history['loss']
val_loss = history.history['val_loss']

plt.subplot(1, 2, 1)
plt.plot(acc, label='Training Accuracy')
plt.plot(val_acc, label='Validation Accuracy')
plt.title('Training and Validation Accuracy')
plt.legend()

plt.subplot(1, 2, 2)
plt.plot(loss, label='Training Loss')
plt.plot(val_loss, label='Validation Loss')
plt.title('Training and Validation Loss')
plt.legend()
plt.show()

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值