TensorFlow笔记之卷积神经网络

news2024/12/22 18:41:46

文章目录

  • 前言
  • 一、卷积神经网络CNN
  • 二、Tensorflow1.x
    • 1.加载数据集
    • 2.数据处理
    • 3.定义模型
    • 4.训练模型
    • 5.结果可视化
  • 二、Tensorflow2.x
    • 1.加载数据集
    • 2.数据处理
    • 3.定义模型
    • 4.训练模型
    • 5.结果可视化
  • 总结


前言

记录在tf1.x与tf2.x中使用卷积神经网络完成CIFAR-10数据集识别多分类任务,并进行断点续训。


一、卷积神经网络CNN

1、全连接网络:参数增多,速度减慢,过拟合
2、卷积神经网络:每层由多个二维平面组成,每个平面由多个独立神经元组成
输入层→(卷积层+→池化层?)+→全连接层+
(1)卷积层:增强特征,降低噪音

#卷积
y = tf.nn.conv2d(x, w, strides, padding) + b
'''
x:输入4维张量[batch,height,weight,channel]
w:[height,weight,input_channel,output_channel]
b:output_channel
strides:每一维步长
'''
#卷积层
tf.keras.layers.Conv2D(filters,#卷积核数目
					   kernel_size,#卷积核大小
          			   activation,#激活函数
          			   padding#填充方式))

图像 ⟶ 卷积核 权值矩阵 特征图 图像\underset{权值矩阵}{\overset{卷积核}{\longrightarrow}}特征图 图像权值矩阵卷积核特征图
局部连接,权值共享
步长:卷积核移动格数,得到不同尺寸输出(降采样)
[ N 1 , N 1 ] ⟶ [ N 1 , N 1 ] S [ ( N 1 − N 2 ) / S + 1 , ( N 1 − N 2 ) / S + 1 ] [N1,N1]\underset{S}{\overset{[N1,N1]}{\longrightarrow}}[(N1-N2)/S+1,(N1-N2)/S+1] [N1,N1]S[N1,N1][(N1N2)/S+1,(N1N2)/S+1]
0填充:用0填充边缘,使输入输出大小相同
多通道卷积:使用多个卷积核提取特征
(2)降采样层:减少参数,降低过拟合

#池化
y1 = tf.nn.max_pool(y, ksize, strides, padding)
'''
y:输入4维张量[batch,height,weight,channel]
ksize:池化窗口[1,height,weight,1]
'''
#池化层
tf.keras.layers.MaxPooling2D(pool_size)

池化:计算区域均值(背景特征)或最大值(纹理特征),合并特征

二、Tensorflow1.x

1.加载数据集

在tensorflow2.x中调用CIFAR-10数据集
10分类32x32RGB彩色图片,训练集50000张,测试集10000张
x_train:(50000, 32, 32, 3)
y_train:(10000, 1)
x_test:(10000, 32, 32, 3)
y_test:(10000, 1)

import tensorflow as tf2
import matplotlib.pyplot as plt
import numpy as np
cifar10 = tf2.keras.datasets.cifar10
(x_train, y_train), (x_test, y_test) = cifar10.load_data()
#显示16张图片
def show(images, labels, preds):
    label_dict = {0:'plane', 1:'car', 2:'bird', 3:'cat',\
                  4:'deer', 5:'dog', 6:'frog', 7:'horse',\
                  8:'ship', 9:'trunk'}
    fig1 = plt.figure(1, figsize=(12, 12))
    for i in range(16):
        ax = fig1.add_subplot(4, 4, i+1)
        ax.imshow(images[i], cmap='binary')
        label = label_dict[np.argmax(labels[i])]
        pred = label_dict[np.argmax(preds[i])]
        title = 'label:%s,pred:%s' % (label, pred)
        ax.set_title(title)
        ax.set_xticks([])
        ax.set_yticks([])

2.数据处理

import tensorflow.compat.v1 as tf
from sklearn.preprocessing import OneHotEncoder
from sklearn.utils import shuffle
from time import time
import os
tf.disable_eager_execution()

#维度转换,灰度值归一化,标签独热编码
x_train = (x_train/255.0).astype(np.float32)
x_test = (x_test/255.0).astype(np.float32)
y_train = OneHotEncoder().fit_transform(y_train).toarray()
y_test = OneHotEncoder().fit_transform(y_test).toarray()
#训练集50000个样本,取5000个样本作为验证集;测试集10000个样本
x_valid, y_valid = x_train[45000:], y_train[45000:]
x_train, y_train = x_train[:45000], y_train[:45000]

3.定义模型

#输入层
#输入通道3,图像大小32*32
with tf.name_scope('Input'):
    x = tf.placeholder(tf.float32, [None, 32, 32, 3], name='X')
#卷积层1
#输出通道32,卷积核3*3,步长为1,图像大小32*32
with tf.name_scope('Conv_1'):
    w1 = tf.Variable(\
         tf.truncated_normal((3,3,3,32), stddev=0.1), name='W1')
    b1 = tf.Variable(tf.zeros(32), name='B1')
    y1 = tf.nn.conv2d(x, w1, strides=[1,1,1,1], padding='SAME') + b1
    y1 = tf.nn.relu(y1)
#池化层1
#输出通道32,最大值池化2*2,步长为2,图像大小16*16
with tf.name_scope('Pool_1'):
    y2 = tf.nn.max_pool(y1, ksize=[1,2,2,1], strides=[1,2,2,1], padding='SAME')
#卷积层2
#输出通道64,卷积核3*3,步长为1,图像大小32*32
with tf.name_scope('Conv_1'):
    w3 = tf.Variable(\
         tf.truncated_normal((3,3,32,64), stddev=0.1), name='W3')
    b3 = tf.Variable(tf.zeros(64), name='B3')
    y3 = tf.nn.conv2d(y2, w3, strides=[1,1,1,1], padding='SAME') + b3
    y3 = tf.nn.relu(y3)
#池化层2
#输出通道64,最大值池化2*2,步长为2,图像大小8*8
with tf.name_scope('Pool_1'):
    y4 = tf.nn.max_pool(y3, ksize=[1,2,2,1], strides=[1,2,2,1], padding='SAME')
#全连接层
#输入8*8*64,128个神经元
with tf.name_scope('Output'):
    w5 = tf.Variable(\
         tf.truncated_normal((8*8*64, 128), stddev=0.1), name='W5')
    b5 = tf.Variable(tf.zeros((128)), name='B5')
    y5 = tf.reshape(y4, (-1, 8*8*64))
    y5 = tf.matmul(y5, w5) + b5
    y5 = tf.nn.relu(y5)
    y5 = tf.nn.dropout(y5, keep_prob=0.8)
#输出层
#输出10个神经元
with tf.name_scope('Output'):
    w6 = tf.Variable(\
         tf.truncated_normal((128, 10), stddev=0.1), name='W6')
    b6 = tf.Variable(tf.zeros((10)), name='B6')
    pred = tf.matmul(y5, w6) + b6
    #pred = tf.nn.softmax(y6)
#优化器
with tf.name_scope('Optimizer'):
    y = tf.placeholder(tf.float32, [None, 10], name='Y')
    loss_function = tf.reduce_mean(\
                    tf.nn.softmax_cross_entropy_with_logits(\
                    logits=pred, labels=y))
    optimizer = tf.train.AdamOptimizer(learning_rate=0.001)\
                .minimize(loss_function)
#准确率
equal = tf.equal(tf.argmax(y, axis=1), tf.argmax(pred, axis=1))
accuracy = tf.reduce_mean(tf.cast(equal, tf.float32))

4.训练模型

训练参数

train_epoch = 10
batch_size = 1000
batch_num = x_train.shape[0] // batch_size
#损失函数与准确率
step = 0
display_step = 10
loss_list = []
acc_list = []
epoch = tf.Variable(0, name='epoch', trainable=False)
#变量初始化
sess = tf.Session()
init = tf.global_variables_initializer()
sess.run(init)

断点续训

ckpt_dir = './ckpt_dir/cifar10'
if not os.path.exists(ckpt_dir):
    os.makedirs(ckpt_dir)
vl = [v for v in tf.global_variables() if 'Adam' not in v.name]
saver = tf.train.Saver(var_list=vl, max_to_keep=1)
ckpt = tf.train.latest_checkpoint(ckpt_dir)
if ckpt != None:
    saver.restore(sess, ckpt)
start_ep = sess.run(epoch)

迭代训练

start_time = time()
for ep in range(start_ep, train_epoch):
    #打乱顺序
    x_train, y_train = shuffle(x_train, y_train)
    print('epoch:{}/{}'.format(ep+1, train_epoch))
    for batch in range(batch_num):
        xi = x_train[batch*batch_size:(batch+1)*batch_size]
        yi = y_train[batch*batch_size:(batch+1)*batch_size]
        sess.run(optimizer, feed_dict={x:xi, y:yi})
        step = step + 1
        if step % display_step == 0:
            loss, acc = sess.run([loss_function, accuracy],\
                                 feed_dict={x:x_valid, y:y_valid})
            loss_list.append(loss)
            acc_list.append(acc)
    #保存检查点
    sess.run(epoch.assign(ep+1))
    saver.save(sess, os.path.join(ckpt_dir,\
              'cifar10_model.ckpt'), global_step=ep+1)

5.结果可视化

end_time = time()
y_pred, acc = sess.run([pred, accuracy],\
                        feed_dict={x:x_test, y:y_test})
fig2 = plt.figure(2, figsize=(12, 6))
ax = fig2.add_subplot(1, 2, 1)
ax.plot(loss_list, 'r-')
ax.set_title('loss')
ax = fig2.add_subplot(1, 2, 2)
ax.plot(acc_list, 'b-')
ax.set_title('acc')
print('用时%.1fs' % (end_time - start_time))
print('Accuracy:{:.2%}'.format(acc))
show(x_test[0:16], y_test[0:16], y_pred[0:16])

在第8次训练后中断,再次运行,从第9次开始训练

验证集上的损失与准确率

前16张图片的标签与预测值


二、Tensorflow2.x

1.加载数据集

标签值采用整数,不进行独热编码

import tensorflow as tf
import matplotlib.pyplot as plt
import numpy as np
from time import time
cifar10 = tf.keras.datasets.cifar10
(x_train, y_train), (x_test, y_test) = cifar10.load_data()
#显示16张图片
def show(images, labels, preds):
    label_dict = {0:'plane', 1:'car', 2:'bird', 3:'cat',\
                  4:'deer', 5:'dog', 6:'frog', 7:'horse',\
                  8:'ship', 9:'trunk'}
    fig1 = plt.figure(1, figsize=(12, 12))
    for i in range(16):
        ax = fig1.add_subplot(4, 4, i+1)
        ax.imshow(images[i], cmap='binary')
        label = label_dict[labels[i]]
        pred = label_dict[preds[i]]
        title = 'label:%s,pred:%s' % (label, pred)
        ax.set_title(title)
        ax.set_xticks([])
        ax.set_yticks([])

2.数据处理

不进行验证集的划分

#维度转换,灰度值归一化,标签独热编码
x_train = (x_train/255.0).astype(np.float32)
x_test = (x_test/255.0).astype(np.float32)

3.定义模型

创建模型

model = tf.keras.models.Sequential()
#添加层
model.add(tf.keras.layers.Conv2D(filters=32, kernel_size=(3,3),\
          input_shape=(32,32,3), activation='relu', padding='same'))
model.add(tf.keras.layers.Dropout(rate=0.3))
model.add(tf.keras.layers.MaxPooling2D(pool_size=(2,2)))
model.add(tf.keras.layers.Conv2D(filters=64, kernel_size=(3,3),\
          activation='relu', padding='same'))
model.add(tf.keras.layers.Dropout(rate=0.3))
model.add(tf.keras.layers.MaxPooling2D(pool_size=(2,2)))
model.add(tf.keras.layers.Flatten())
model.add(tf.keras.layers.Dense(units=10,\
          kernel_initializer='normal', activation='softmax'))
#模型摘要
model.summary()

加载模型

'''
#加载模型(整个模型)
mpath = './model/cifar10.h5'
model.load_weights(mpath)
'''
#加载模型(检查点)
cdir = './model/'
ckpt = tf.train.latest_checkpoint(cdir)
if ckpt != None:
    model.load_weights(ckpt)

训练模式

#整数类型作标签
model.compile(optimizer='adam',\
              loss='sparse_categorical_crossentropy',\
              metrics=['accuracy'])

4.训练模型

#回调参数设置检查点与早停
cpath = './model/cifar10.{epoch:02d}-{val_loss:.4f}.H5'
callbacks = [tf.keras.callbacks.ModelCheckpoint(filepath=cpath,
                                                save_weights_only=True,
                                                verbose=1,
                                                save_freq='epoch'),
             tf.keras.callbacks.EarlyStopping(monitor='val_loss',
                                              patience=3)]
#模型训练
start_time = time()
history = model.fit(x_train, y_train,\
                    validation_split=0.2, epochs=10, batch_size=1000,\
                    callbacks=callbacks, verbose=1)
end_time = time()
print('用时%.1fs' % (end_time-start_time))

5.结果可视化

history.history:字典类型数据
loss,accuracy,val_loss,val_accuracy

fig2 = plt.figure(2, figsize=(12, 6))
ax = fig2.add_subplot(1, 2, 1)
ax.plot(history.history['val_loss'], 'r-')
ax.set_title('loss')
ax = fig2.add_subplot(1, 2, 2)
ax.plot(history.history['val_accuracy'], 'b-')
ax.set_title('acc')

模型评估

test_loss, test_acc = model.evaluate(x_train, y_train, verbose=1)
print('Loss:%.2f' % test_loss)
print('Accuracy:{:.2%}'.format(test_acc))

模型预测

#分类预测
preds = model.predict_classes(x_test)
show(x_test[0:16], y_test[0:16].flatten(), preds[0:16])
#保存模型
#model.save_weights(mpath)

网络结构

训练后保存模型

验证集损失值与准确率

前16张图片的标签值与预测值

导入模型,准确率与之前相同

在第二批训练后停止程序

再次训练时准确率在之前的基础上提升
在这里插入图片描述

总结

卷积神经网络能够对数据进行特征提取,减少参数的数量,提高训练速度;
使用OneHotEncoder进行独热编码后需要使用toarray()转化为数组形式参与运算;
在训练时间较长时可定时保存进行断点续训;
在tf1.x中保存检查点时会保存多个同名的权重,可不保存名称中含有Adam的权重,保存前后需要重启控制台以避免加载时权重名称不对应。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/183521.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【ThreeJs 初学习】实现简单的场景渲染

简单的场景渲染 从今天开始进军 3D相关的技术。第一是因为项目需要,第二是因为年中的KPI目标。刚开始分享的内容会相对基础,望各位谅解。 根据官网的文档整理出一份API文档, 地址是:ThreeJs 官网文档,其目的还是为了方便查阅 1. …

移动应用测试流程

以下是这段时间测试手机app的流程总结。 从需求阶段开始介入。参加软件功能设计,在软件编码之前,在仍有可能大的设计变更的时候,积极参加软件的计划阶段,这会帮助我们了解正被考虑的折衷和权衡从而了解客户需要的产品的雏形。在此…

Docker部署oracle -11g

Docker部署oracle -11g 拉取镜像 docker pull registry.cn-hangzhou.aliyuncs.com/helowin/oracle_11g启动容器 docker run -d -p 1521:1521 --name oracle11g registry.cn-hangzhou.aliyuncs.com/helowin/oracle_11g执行 docker ps 命令确认容器启动成功 进行配置 &#xf…

蓝桥杯 分巧克力

题目描述 儿童节那天有 K 位小朋友到小明家做客。小明拿出了珍藏的巧克力招待小朋友们。 小明一共有 NN 块巧克力,其中第 ii 块是 H_i \times WiHi​Wi 的方格组成的长方形。为了公平起见, 小明需要从这 NN 块巧克力中切出 K 块巧克力分给小朋友们。切…

读书笔记:神经网络的学习 train_neuralnet.py ← 斋藤康毅

提醒:本例涉及到三个 Python 文件,即 two_layer_net.py,train_neuralnet.py,mnist.py 等。 显然,要进行神经网络的学习,必须先构建神经网络。 因此,本文先构建了一个2层神经网络。代码详见 two_…

玩转代码|解决Chrome浏览器内置谷歌翻译功能无法使用问题!

最近这几天在使用Chrome浏览器的内置谷歌翻译功能时,总是一直停留在不翻译的状态,一开始我还以为是网络波动过几天就好了,过了好几天依旧是这样。去看了新闻才知道谷歌翻译已经退出了中国市场。根据TechCrunch的消息称,谷歌发言人…

我本芬芳

我本芬芳推荐语: 读完前几章,一边为惠才遇人不淑感到遗憾,又不觉想起自己的童年种种,书中简单的三言两语,却又不断地在触动我。我不由得想到上世纪六七十年代的女子们,也就是我的奶奶外婆们,将自…

我的周刊(第076期)

我的信息周刊,记录这周我看到的有价值的信息,主要针对计算机领域,内容主题极大程度被我个人喜好主导。这个项目核心目的在于记录让自己有印象的信息做一个留存以及共享。🎯 项目python-wechaty[1]Wechaty 是一个开源聊天机器人框架…

力扣刷题|226.翻转二叉树、101. 对称二叉树

文章目录LeetCode 226.翻转二叉树题目链接🔗思路递归法迭代法LeetCode 101. 对称二叉树题目链接🔗思路递归法迭代法相关题目LeetCode 226.翻转二叉树 题目链接🔗 LeetCode 226.翻转二叉树 思路 这道题目使用前序遍历和后序遍历都可以&…

PVID和VID相关小知识

欢迎来到东用知识小课堂!1.PVID和VID的区别PVID和VID经常出现于二、三层交换机里,很多时候由于PVID和VID的设置不合理,造成VLAN划分变得混乱。一般你去超市买东西有个扫描设备扫描一下商品上的标签,然后价格就会出现。商品上的标签…

分布式锁与数据库悲观、乐观锁

分布式锁 什么是分布式锁 要介绍分布式锁,首先要提到与分布式锁相对应的是线程锁、进程锁。 1.线程锁 主要用来给方法、代码块加锁。当某个方法或代码使用锁,在同一时刻仅有一个线程执行该方法或该代码段。线程锁只在同一JVM中有效果,因为…

Redis主从复制与读写分离

1、为什么要主从复制、读写分离Redis在作为缓存的时候,随着项目访问量的增加,对Redis服务器的操作也越加频繁,虽然Redis读写速度都很快,但是一定程度上也会造成一定的延时,甚至出现宕机的可能性,这时候就出…

如何使用知行之桥搭建SFTPServer

知行之桥EDI系统同时支持SFTP Server和SFTP Client功能,既可以作为SFTP Server供多个Client连接,也可以作为Client连接多个Server。无论是作为SFTP Server还是SFTP Client,都只需要简单的配置即可实现。 SFTP Server的特性包括一下几点&…

【React全家桶】react路由

react路由5.1. 路由的简介5.2 路由的基本使用5.3 路由组件与一般组件5.4 NavLink及其封装5.5 Switch5.6 路由的模糊匹配与严格匹配5.7 Redirect重定向5.8 向路由组件传递参数5.9 编程式路由导航5.10withRouter的使用5.12 BrowserRouter与HashRouter的区别5.1. 路由的简介 单页W…

代码随想录--二叉树章节总结 Part III

代码随想录–二叉树章节总结Part III 1.Leetcode106 从中序与后序遍历序列构造二叉树 给定两个整数数组 inorder 和 postorder ,其中 inorder 是二叉树的中序遍历, postorder 是同一棵树的后序遍历,请你构造并返回这颗 二叉树 。 解题思路…

【Go基础】并发编程

文章目录1. 并发模型2. Goroutine的使用3. Channel的同步与异步4. 并发安全性5. 多路复用6. 协程泄漏7. 协程管理1. 并发模型 任何语言的并行,到操作系统层面,都是内核线程的并行。同一个进程内的多个线程共享系统资源,进程的创建、销毁、切…

【监控开发】jps命令怎么远程调用另一个IP的机器,jstatd服务支持

jsp命令远程调用咩有Linux服务器启动jstatd服务的时候Linux服务器如何启动jstatd服务1.查找jdk所在目录2.在jdk的bin目录下创建文件jstatd.all.policy3.给这个文件赋权4.这个文件写入安全配置,赋值粘贴即可5.启动jstatd服务6.查看是否启动成功再去另外一台服务器调用…

第一章:Go语言为并发而生

在早期 CPU 都是以单核的形式顺序执行机器指令。Go语言的祖先C语言正是这种顺序编程语言的代表。顺序编程语言中的顺序是指:所有的指令都是以串行的方式执行,在相同的时刻有且仅有一个 CPU 在顺序执行程序的指令。 随着处理器技术的发展,单核…

C语言深度解剖-关键字(4)

目录 signed、unsigned 关键字补充内容 关于大端和小端 大小端存储数据方式 判断大小端 深入理解数据存储 练习: 写在最后: signed、unsigned 关键字补充内容 关于大端和小端 我们通过在内存中存储一个值, 用于观察数据在内存中的存…

Python连接Liunx中mysql数据库-保姆级教程

首先确保你的liunx中已经安装好了mysql数据库如果没有安装mysql数据库看这篇文章Centos6从零开始安装mysql和tomcat后台环境,并成功部署Tomcat项目图文详细过程 python连接Liunx中mysql数据库进行增删改查liunx中相关环境改变Python中连接liunx中的mysql数据库在Nav…