TensorFlow笔记之神经网络完成多分类任务

news2024/11/24 14:00:15

文章目录

  • 前言
  • 一、数据集调用
  • 二、Tensorflow1.x
    • 1.单隐藏层
    • 2.模型保存与调用
  • 三、Tensorflow2.x
    • 1.全连接层类
    • 2.keras建模
  • 总结


前言

对TensorFlow笔记之单神经元完成多分类任务进行修改,在tf1.x与tf2.x中使用神经网络完成手写体数字识别多分类任务。


一、数据集调用

数据集调用与预处理和上一篇完全相同

#数据集调用,在tensorflow2.x中调用数据集
import tensorflow as tf2
import matplotlib.pyplot as plt
import numpy as np
mnist = tf2.keras.datasets.mnist
(x_train, y_train), (x_test, y_test) = mnist.load_data()
#维度转换,灰度值归一化,标签独热编码
x_train = x_train.reshape((-1, 784))
x_train = tf2.cast(x_train/255.0, tf2.float32)
x_test = x_test.reshape((-1, 784))
x_test = tf2.cast(x_test/255.0, tf2.float32)
y_train = tf2.one_hot(y_train, depth=10)
y_test = tf2.one_hot(y_test, depth=10)
#训练集训练模型,验证集调整超参数,测试集测试模型效果
#训练集60000个样本,取5000个样本作为验证集;测试集10000个样本
x_valid, y_valid = x_train[55000:], y_train[55000:]
x_train, y_train = x_train[:55000], y_train[:55000]
#显示16张图片
def show(images, labels, preds):
    fig1 = plt.figure(1, figsize=(12, 12))
    for i in range(16):
        ax = fig1.add_subplot(4, 4, i+1)
        ax.imshow(images[i].reshape(28, 28), cmap='binary')
        label = np.argmax(labels[i])
        pred = np.argmax(preds[i])       
        title = 'label:%d,pred:%d' % (label, pred)
        ax.set_title(title)
        ax.set_xticks([])
        ax.set_yticks([])

二、Tensorflow1.x

1.单隐藏层

定义模型
增加一组权值作为隐藏层参数
输出层不进行softmax
使用截断正态分布减小随机权值的偏离程度

import tensorflow.compat.v1 as tf
from sklearn.utils import shuffle
from time import time
tf.disable_eager_execution()
with tf.name_scope('Model'):
    x = tf.placeholder(tf.float32, [None, 784], name='X')
    y = tf.placeholder(tf.float32, [None, 10], name='Y') 
    #隐藏层
    with tf.name_scope('Hide'):
        h1_nn = 256
        #截断正态分布
        w1 = tf.Variable(\
             tf.truncated_normal((784, h1_nn), stddev=0.1), name='W1')
        b1 = tf.Variable(tf.zeros((h1_nn)), name='B1')
        y1 = tf.nn.relu(tf.matmul(x, w1) + b1)
    #输出层
    with tf.name_scope('Output'):
        w2 = tf.Variable(\
             tf.truncated_normal((h1_nn, 10), stddev=0.1), name='W2')
        b2 = tf.Variable(tf.zeros((10)), name='B2')
        pred = tf.matmul(y1, w2) + b2

训练模型
使用结合softmax的损失函数,避免损失值过大

#训练参数
train_epoch = 10
learning_rate = 0.1
batch_size = 1000
batch_num = x_train.shape[0] // batch_size
#损失函数与准确率
step = 0
display_step = 5
loss_list = []
acc_list = []
#结合softmax的损失函数
loss_function = tf.reduce_mean(\
                tf.nn.softmax_cross_entropy_with_logits(\
                logits=pred, labels=y))
equal = tf.equal(tf.argmax(y, axis=1), tf.argmax(pred, axis=1))
accuracy = tf.reduce_mean(tf.cast(equal, tf.float32))
#优化器
optimizer = tf.train.AdamOptimizer(learning_rate).minimize(loss_function)
#变量初始化
init = tf.global_variables_initializer()
with tf.Session() as sess:
    sess.run(init)
    #tf转为numpy
    x_train = sess.run(x_train)
    x_valid = sess.run(x_valid)
    x_test = sess.run(x_test)
    y_train = sess.run(y_train)
    y_valid = sess.run(y_valid)
    y_test = sess.run(y_test)

迭代训练
使用time()记录训练时间

    start_time = time()
    for epoch in range(train_epoch):
        print('epoch:%d' % 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)
        #打乱顺序
        x_train, y_train = shuffle(x_train, y_train)

结果可视化

    end_time = time()
    y_pred, equ_list, acc = sess.run([pred, equal, 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))
#展示预测错误的图片
err_list = [ not equ for equ in equ_list]
show(x_test[err_list], y_test[err_list], y_pred[err_list])

准确率比使用单神经元有所提高

预测错误的图片

2.模型保存与调用

设置检查点目录

import os
ckpt_dir = './ckpt_dir/'
if not os.path.exists(ckpt_dir):
    os.makedirs(ckpt_dir)

不保存使用Adam优化器时产生的权重

vl = [v for v in tf.global_variables() if 'Adam' not in v.name]
saver = tf.train.Saver(var_list=vl)

每轮过后保存模型

    for epoch in range(train_epoch):
        saver.save(sess, os.path.join(ckpt_dir,\
                   'mnist_model_%d.ckpt' % (epoch+1)))

训练结束后保存模型

    saver.save(sess, os.path.join(ckpt_dir,\
              'mnist_model.ckpt'))

保留最近5份文件,文件较大,保存时间也较长

调用模型

from tensorflow.python.tools.inspect_checkpoint import print_tensors_in_checkpoint_file
with tf.Session() as sess:
    ckpt_dir = './ckpt_dir/'
    saver = tf.train.Saver()
    #获取最新检查点
    ckpt = tf.train.get_checkpoint_state(ckpt_dir)
    #打印权重信息
    print_tensors_in_checkpoint_file(ckpt.model_checkpoint_path,\
            tensor_name=None, all_tensors=True, all_tensor_names=True)
    #恢复模型
    saver.restore(sess, ckpt.model_checkpoint_path)

保存的模型里有两组权重Model与Model_1,分别为初始化时的权重与优化后的权重:
但在此Model为训练后的权重

Model_1为初始化时的权重

如果准确率过低,可能是用的初始化时的权重,需要将模型名称改为Model_1。模型保存后需要退出当前控制台再进行调用,否则可能会报错。

with tf.name_scope('Model_1'):

结果与训练后的一致

三、Tensorflow2.x

1.全连接层类

定义模型

import tensorflow as tf
from sklearn.utils import shuffle
from time import time
#全连接层
class fcn_layer():
    def __init__(self, input_dim, output_dim):
        self.w = tf.Variable(tf.random.truncated_normal(\
                            (input_dim, output_dim), stddev=0.1), tf.float32)
        self.b = tf.Variable(tf.zeros(output_dim), tf.float32)
    def cal(self, inputs, activation=None):
        y = tf.matmul(inputs, self.w) + self.b
        if activation != None:
            y = activation(y)
        return y

三层神经网络256x64x32

hide_1 = fcn_layer(784, 256)
hide_2 = fcn_layer(256, 64)
hide_3 = fcn_layer(64, 32)
out = fcn_layer(32, 10)
def model(x):
    y1 = hide_1.cal(x, tf.nn.relu)
    y2 = hide_2.cal(y1, tf.nn.relu)
    y3 = hide_3.cal(y2, tf.nn.relu)
    y4 = out.cal(y3, tf.nn.softmax)
    return y4

损失函数与准确率

#损失函数
def loss_function(x, y):
    pred = model(x)
    loss = tf.keras.losses.categorical_crossentropy(\
           y_true=y, y_pred=pred)
    return tf.reduce_mean(loss)
#准确率
def accuracy(x, y):
    pred = model(x)
    acc = tf.equal(tf.argmax(y, axis=1), tf.argmax(pred, axis=1))
    acc = tf.cast(acc, tf.float32)
    return tf.reduce_mean(acc)
#梯度
def grad(x, y):
    with tf.GradientTape() as tape:
        loss = loss_function(x, y)
        return  tape.gradient(loss, w_list+b_list)
#待优化变量列表
w_list = [hide_1.w, hide_2.w, hide_3.w, out.w]
b_list = [hide_1.b, hide_2.b, hide_3.b, out.b]

训练模型

#训练参数
train_epoch = 10
learning_rate = 0.01
batch_size = 1000
batch_num = x_train.shape[0] // batch_size
#展示间隔
step = 0
display_step = 5
loss_list = []
acc_list = []
#Adam优化器
optimizer = tf.keras.optimizers.Adam(learning_rate)

迭代训练

start_time = time()
for epoch in range(train_epoch):
    print('epoch:%d' % 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]
        grads = grad(xi, yi)
        optimizer.apply_gradients(zip(grads, w_list+b_list))
        step = step + 1
        if step % display_step == 0:
            loss_list.append(loss_function(x_valid, y_valid))
            acc_list.append(accuracy(x_valid, y_valid))
    #打乱顺序
    x_train, y_train = shuffle(x_train.numpy(), y_train.numpy())
    x_train = tf.cast(x_train, tf.float32)
    y_train = tf.cast(y_train, tf.float32)

结果可视化

#验证集结果
end_time = time()
print('用时%.1fs' % (end_time - start_time))
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')
#测试集结果
acc = accuracy(x_test, y_test)
print('Accuracy:{:.2%}'.format(acc))
y_pred = model(x_test)
show(x_test.numpy(), y_test, y_pred)

使用三层神经网络准确率进一步提升,训练时长也增长
在这里插入图片描述

2.keras建模

数据集调用

import tensorflow as tf
import matplotlib.pyplot as plt
from time import time
mnist = tf.keras.datasets.mnist
(x_train, y_train), (x_test, y_test) = mnist.load_data()

维度转换在flatten层进行,标签直接采用整数,只需要进行灰度值归一化,在此不需要进行验证集划分。

x_train = tf.cast(x_train/255.0, tf.float32)
x_test = tf.cast(x_test/255.0, tf.float32)

显示16张图片

def show(images, labels, preds):
    fig1 = plt.figure(1, figsize=(12, 12))
    for i in range(16):
        ax = fig1.add_subplot(4, 4, i+1)
        ax.imshow(images[i].reshape(28, 28), cmap='binary')  
        title = 'label:%d,pred:%d' % (labels[i], preds[i])
        ax.set_title(title)
        ax.set_xticks([])
        ax.set_yticks([])

创建模型

model = tf.keras.models.Sequential()

添加层

model.add(tf.keras.layers.Flatten(input_shape=(28,28)))
model.add(tf.keras.layers.Dense(units=256,\
          kernel_initializer='normal', activation='relu'))
model.add(tf.keras.layers.Dense(units=64,\
          kernel_initializer='normal', activation='relu'))
model.add(tf.keras.layers.Dense(units=32,\
          kernel_initializer='normal', activation='relu'))
model.add(tf.keras.layers.Dense(units=10,\
          kernel_initializer='normal', activation='softmax'))

模型摘要

model.summary()


训练模式

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

训练模型

#学习率自动调节,输出进度条日志
start_time = time()
history = model.fit(x_train, y_train,\
                    validation_split=0.2, epochs=10, batch_size=1000,\
                    verbose=1)
end_time = time()
print('用时%.1fs' % (end_time-start_time))

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))

使用keras的训练时间较短,模型准确率也有提升空间。

模型预测

#分类预测
preds = model.predict_classes(x_test)
show(x_test.numpy(), y_test, preds)

在这里插入图片描述


总结

一层神经网络包含多个神经元,输入数据维度对应于隐藏层权重的第一维度,神经元个数对应于隐藏层权重的第二维度,输出层将隐藏层输出转化为预测值维度。
在模型保存和加载时,可能出现权重名称不对应的情况,可将权重打印出来进行对照修改。
通过定义全连接层类可以省去定义多层神经网络时的重复操作,多层网络的参数较多,训练时间较长,对模型的表达能力更强,但准确率不一定更高,还需适当调节训练参数。
使用keras可以方便地定义模型、进行训练与评估,可以在内部进行维度变换和独热编码等操作,训练时间也较短。

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

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

相关文章

10、Javaweb_Cookkie会话Session修改IDEA代码模板

修改IDEA代码模板 选择Setting... 找到要修改的代码模板,点击ok修改即可 使用模板创建方法 ,点击文件包,右键New选择文件类型 点击ok即可 创建完成 会话技术 1. 会话:一次会话中包含多次请求和响应。 * 一次会话:浏览器第一次给服务器资…

JAVA开发(web常见安全漏洞以及修复建议)

web安全常见漏洞修复建议:SQL注入规避 代码层最佳防御sql漏洞方案:使用预编译sql语句查询和绑定变量。(1)使用预编译语句,使用PDO需要注意不要将变量直接拼接到PDO语句中。所有的查询语句都使用数据库提供的参数化查询…

92、【树与二叉树】leetcode ——222. 完全二叉树的节点个数:普通二叉树求法+完全二叉树性质求法(C++版本)

题目描述 原题链接:222. 完全二叉树的节点个数 解题思路 1、普通二叉树节点个数求法 (1)迭代:层序遍历BFS 遍历一层获取一层结点 /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode …

华为交换机、路由器设备批量配置端口方法步骤

华为交换机、路由器批量配置端口方法步骤 在现实工作中,如果要对多个端口做同样的配置,每个接口逐一进行相同的配置,很容易出错,而且造成大量重复工作。 配置端口组功能就可以解决这个问题啦。 你只需要将这些以太网接口加入同一…

HTML学习笔记(全)

HTML 文章目录HTML第一章——HTML 基础认识1. 1 基础补充1.1.1 网页组成1.1.2 代码如何转换成网页1.1.3 渲染引擎(了解)1.1.4 web 标准1.2 HTML 基础认知1. HTML的概念2. HTML页面固定结构3. **标签说明:**第二章——HTML基础语法2.1——注释…

国产linux操作系统——麒麟操作系统的来龙去脉

文章目录1、linux操作系统2、国产操作系统3、麒麟操作系统4、引用1、linux操作系统 目前市场主流的linux操作系统分类大致如此,国产操作系统的麒麟操作系统,底层比较杂,所以单独一类。 2、国产操作系统 排名日期截止到2022 这里提一下排名第…

科技云报道:从re:Invent 2022读懂亚马逊云科技的“生态棋局”

科技云报道原创。 懂棋的人都知道,下棋靠的是智力的角逐,也是气度的较量。 到了云计算发展的新时期,下棋的“人”已经变了,单靠一个人的智力解决不了N个用户的N种问题。 因此,近年来头部云厂商纷纷加大了对合作伙伴生…

centos7:jenkins+nodejs前端自动化部署

系统:centos7 nodejs版本:v16.18.1 npm版本:8.19.2 由于centos7最大只支持16.18.1版本,尽量让前端写代码时使用这个版本,linux系统如果要装高版本的node需要安装glibc库,很危险,尽量不要操作。 jenkin…

Hudi系列6:使用pyspark操作Hudi

文章目录前言一. pyspark连接hudi二. 创建表三. 插入数据四. 查询数据五. Time Travel查询六. 更新数据七. 增量查询八. 基于时间点查询九. 删除数据9.1 软删除9.2 硬删除十. 插入覆盖十一. Spark其它命令11.1 Alter Table11.2 Partition SQL Command参考:前言 软件版本Python…

低成本MEMS惯导系统的捷联惯导解算MATLAB仿真

低成本MEMS惯导系统的捷联惯导解算MATLAB仿真一、姿态角转换为四元数二、四元数转换为姿态角三、反对称阵四、位置更新五、姿态更新六、程序及数据主程序:子程序:数据及完整程序之前将高成本的捷联惯导忽略地球自转、圆锥曲线运动以及划桨运动等化简为可…

【学习笔记之Linux】工具之make/Makefile与git

make/Makefile: 背景知识: 一个工程中的源文件不计数,按类型、功能、模块分别放在若干个目录中,Makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,那些文件需要重新编…

电源《龙珠超:超级人造人》观后感

上周看了动画电影《龙珠超:超级人造人》,《龙珠》这个系列同《火影》、《死神》、《海贼王》和《名侦探柯南》等都存在了很长时间,不断在更新,都是非常好的IP,伴随着很多人走过童年,也是因为时间太长了,记得…

品牌打假,假货治理,有什么好的方法

品牌打假,清除渠道假货,可以提高消费者对品牌的满意度与忠诚度,增强经销商的经销信心,维护稳定的价格体系及经销体系,树立良好的品牌形象。 但是品牌在打假的过程中,由于经验、时间、方法、技术等方面的局…

测试开发 | 接口测试之HTTP 协议讲解

本文节选自霍格沃兹测试开发学社内部教材HTTP 协议是一种用于分布式、协作式和超媒体信息系统的应用层协议。HTTP 是万维网的数据通信的基础。客户端向服务端发送 HTTP 请求,服务端则会在响应中返回所请求的数据。了解了 HTTP 协议,才能对接口测试进行更…

sql实现字段分割一行转多行的示例代码

先看一下数据结构,我这里字段比较少,只弄了最重要的部分 根据我们上次学到的LEFT()函数进行分组 SELECT LEFT(provinces,6),COUNT(1) FROM region_map_copy GROUP BY LEFT(provinces,6) 得到的结果如下: 这样的效果并不是我们想要的&#x…

必贝特科创板IPO过会:预计2025年前实现商业化,钱长庚为实控人

2023年1月10日,上海证券交易所披露的信息显示,广州必贝特医药股份有限公司(下称“必贝特”)获得上市委会议审核通过。据贝多财经了解,必贝特于2022年6月29日在科创板递交上市申请。 公开信息显示,必贝特是一…

SwiftUI之深入解析如何使用组合矩形GeometryReader创建条形(柱状)图

一、图表布局 条形(柱状)图以矩形条的形式呈现数据的类别,其宽度和高度与它们表示的值成比例。SwiftUI 对探索不同布局和预览实时视图结果是很友好的,很容易将部分内容提取到子视图中,以便每个部分都很小且易于维护。…

给程序提速 | 多进程与多线程

目录 一、背景 1.1、前言 1.2、说明 二、线程与进程 2.1、什么是进程 2.2、什么是线程 2.3、进程与线程的关系 2.4、多进程与多线程的最佳使用条件 2.5、线程与进程的锁 2.6、特别注意 三、第一个线程、线程池 3.1、线程测试 3.2、执行结果 3.3、线程池测试 3.4…

华中科技大学计算机组成原理-计算机数据表示实验(全部通关)

计算机数据表示实验(HUST) 计算机数据表示目录 [建议收藏]计算机数据表示实验(HUST)第1关 汉字国标码转区位码实验第2关 汉字机内码获取实验第3关 偶校验编码设计第4关 偶校验解码电路设计第5关 16位海明编码电路设计第6关 16位海明解码电路设计第7关 海明编码流水传输实验第8关…

Leetcode:700. 二叉搜索树中的搜索(C++)

目录 问题描述: 实现代码与解析: 递归: 原理思路: 迭代: 原理思路: 问题描述: 给定二叉搜索树(BST)的根节点 root 和一个整数值 val。 你需要在 BST 中找到节点值…