卷积神经网络与循环神经网络实战 --- 手写数字识别及诗词创作

卷积神经网络与循环神经网络实战 — 手写数字识别及诗词创作

文章目录

  • 卷积神经网络与循环神经网络实战 --- 手写数字识别及诗词创作
    • 一、神经网络相关知识
      • 1. 深度学习
      • 2. 人工神经网络回顾
      • 3. 卷积神经网络(CNN)
        • 3.1 卷积层
        • 3.2 汇集(池化)层
        • 3.3 深层卷积神经网络
        • 3.4 卷积神经网络的演化和几个代表性模型
        • 3.5 卷积神经网络在非图像数据上的应用举例
      • 4. 循环神经网络(RNN)
        • 4.1 Hopfield神经网络
        • 4.2 循环神经网络
    • 二、运行环境
    • 四、积神经网络完成手写字体识别(Sequential)
    • 五、卷积神经网络完成手写字体识别
    • 六、循环神经网络完成诗词创作
    • 七、使用异步序列到序列编码器-解码器的方法完成诗词创作任务
        • 循环神经网络的三种模式
    • 八、拓展练习
        • 使用卷积神经网络对cifar10数据进行10分类预测,并在训练结束后,以corgi.jpg为例,尝试画出某一个卷积层的输出特征向量映射,以观察卷积神经网络的运作逻辑。
          • cifar10数据集介绍

一、神经网络相关知识

1. 深度学习

– 1986年,Rina Dechter提出这个词,以搜索和推理为核心

– 2000年,I. Aizenberg 引入到神经网络研究

– 具有多层结构神经网络模型的机器学习方法

– 是一大类机器学习方法的总称

• 深度学习也与神经网络与贝叶斯学习等结合起来,并不限于狭义的神经网络的概念

2. 人工神经网络回顾

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3. 卷积神经网络(CNN)

• 用于解决图像识别领域的问题

• 原有多层感知器解决图像识别面临欠学习或参数过多问题

• 图像中待识别对象的像素点间存在空间关联关系

• 图像对象中存在多种不变性因素:

– 位置,大小,变形并不影响字符的属性

3.1 卷积层

• 单个卷积核:局部信息提取

• 所有位置扫描,一个卷积核得到一个特征图(Feature Map)

• 多个卷积核称作多个通道(channel),用于不同特征提取

• 一维卷积:相应位置加权求和

在这里插入图片描述

• 超参数(hyper-parameters)

–卷积核尺寸

–步幅(stride)

–边宽或边衬(pad)

• 对训练过程与结果有重要影响

在这里插入图片描述

• 权值共享(weight sharing):一轮扫描中卷积核参数不变

• 前向传播后,通过输出端误差进行反向传播优化

• 多个并行卷积核构成多个通道,提取不同特征

• 图像尺寸𝑛×𝑛,卷积核尺寸𝑘×𝑘,步幅为s ,边衬为p且对称 ,则特征图维数:⌊(n+2p-k)/s+1⌋

• 挤压(squashing):对卷积结果进行非线性运算

• 非线性激活函数

– 传统S型函数(sigmoid) 或双曲正切函数(tanh)

– 常用ReLU函数:矫正线性单元(Rectified Linear Unit)

在这里插入图片描述

3.2 汇集(池化)层

• 汇集(“池化”):对卷积后特征图进行降采样

–最大汇集(max pooling):选局部区域最大值

–平均汇集(Average pooling):选区域数值平均值

• 两个参数:汇集区域大小和步幅
在这里插入图片描述

3.3 深层卷积神经网络

  • AlexNet

​ – 使用局部感受野、权值共享、最大汇集等措施减少参数量

​ – 自由参数:~6.1×10^7

​ – 数据扩增(data augmentation):利用预处理增加训练样本数目

在这里插入图片描述

3.4 卷积神经网络的演化和几个代表性模型

• 1990年:LeNet-1

• 2012年:AlexNet

• 2013年:ZFNet

• 2014年:VGG 网络

• 2014年:GoogLeNet

• 2015年:残差网络(ResNet)

• 2017年:密集网络(DenseNet)

• 2018年:多尺度密度网络(MSDNet)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.5 卷积神经网络在非图像数据上的应用举例

在这里插入图片描述
在这里插入图片描述

4. 循环神经网络(RNN)

4.1 Hopfield神经网络

在这里插入图片描述
在这里插入图片描述

4.2 循环神经网络

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

二、运行环境

Python 3.9.13 (其它与tensorflow对应版本均可)

PyCharm 2022.3 (Professional Edition非硬性要求)

jupyter notebook (备选)

tensorflow-gpu== 2.6.0 (使用GPU进行加速,需单独安装该版本,详见下面文档)

cuDNN== 8.1 (tensorflow-gpu显卡依赖)

CUDA== 11.2 (tensorflow-gpu显卡依赖)

numpy==1.19.2 (python科学计算库)

keras == 2.6.0(开源人工神经网络库)

tensorflow和keras版本对应关系:
在这里插入图片描述

建议执行:

pip insatll googlemaps # 同时根据提示内容安装或降级所有依赖包

官方TensorFlow安装文档 (安装必看)


折腾了一下午,妥协了! 除非你自己电脑的tensorflow是1.x版本的,否则不建议使用自己的电脑运行之后的代码,(总之,很难改2.x就对了)反正就是出不了结果,虚拟环境也是如此(gpu虚拟环境报错)。

这里选择阿里云的 天池Notebook 使用也还算比较方便。使用方法自行百度。

官网链接: https://tianchi.aliyun.com/notebook-ai/


四、积神经网络完成手写字体识别(Sequential)

使用TensorFlow的Sequential建立卷积神经网络,完成手写字体识别任务。

# -*- coding: utf-8 -*-
# @Author : Xenon
# @Date : 2023/2/5 23:14 
# @IDE : 天池notebook Python3.7.13
"""使用TensorFlow的Sequential建立卷积神经网络,完成手写字体识别任务。"""import os
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers, optimizers, datasets
from tensorflow.keras.layers import Dense, Dropout, Flatten
from tensorflow.keras.layers import Conv2D, MaxPooling2Dos.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'def mnist_dataset():"""数据集的读取使用TensorFlow下载mnist数据集,取训练集中的前20000个样本作为本实验的训练集,测试集的所有样本(20000个)作为本实验的测试集。对于样本,将其属性值调整为tf.float32类型并归一化,标签调整为tf.int64类型,随机打乱顺序,训练样本每100个分为一个batch,测试样本只有一个batch。:return: 训练集ds, 测试集test_ds(TensorFlow的dataset格式)"""(x, y), (x_test, y_test) = datasets.mnist.load_data()x = x.reshape(x.shape[0], 28, 28, 1)x_test = x_test.reshape(x_test.shape[0], 28, 28, 1)ds = tf.data.Dataset.from_tensor_slices((x, y))ds = ds.map(prepare_mnist_features_and_labels)ds = ds.take(20000).shuffle(20000).batch(100)test_ds = tf.data.Dataset.from_tensor_slices((x_test, y_test))test_ds = test_ds.map(prepare_mnist_features_and_labels)test_ds = test_ds.take(20000).shuffle(20000).batch(20000)return ds, test_dsdef prepare_mnist_features_and_labels(x, y):x = tf.cast(x, tf.float32) / 255.0y = tf.cast(y, tf.int64)return x, yif __name__ == '__main__':# 模型的建立(顶层代码)使用Sequential,建立一个模型并将模型实例化为对象model。model = keras.Sequential([# 该模型要求具有7层(不计入输入层),分别为:Conv2D(32, (5, 5), activation='relu', padding='same'),  # 卷积层:二维卷积层,输出深度32,卷积核5*5,激活函数为relu,零填充方式为等宽卷积;MaxPooling2D(pool_size=2, strides=2),  # 池化层:最大池化层,区域为2*2,步长为2Conv2D(64, (5, 5), activation='relu', padding='same'),  # 卷积层:二维卷积层,输出深度64,卷积核5*5,激活函数为relu,零填充方式为等宽卷积;MaxPooling2D(pool_size=2, strides=2),  # 池化层:最大池化层,区域为2*2,步长为2;Flatten(),  # Flatten()层:用于将输入特征张量拉平为一维向量,在理论角度不算作一层;layers.Dense(128, activation='tanh'),  # 全连接层:节点数为128,激活函数为tanh;layers.Dense(10)])  # 全连接层:节点数为10,无激活函数。optimizer = optimizers.Adam(0.0001)  # 设置optimizer,使用Adam算法,参数为0.0001# 使用model.compile配置训练过程,将optimizer输入,自动将标签独热向量化。model.compile(optimizer=optimizer,loss='sparse_categorical_crossentropy',  # 损失方程为交叉熵损失函数metrics=['accuracy']  # 评价指标为准确率)train_ds, test_ds = mnist_dataset()# 读取数据集,使用model.fit方法,对训练集进行5轮训练(参数epochs=5)。model.fit(train_ds, epochs=5)# 使用model. evaluate方法,对测试集进行测试。model.evaluate(test_ds)

输出结果:(天池)

在这里插入图片描述

五、卷积神经网络完成手写字体识别

使用TensorFlow的基础功能编写卷积神经网络,手动编写权重向量与前向计算逻辑,使用梯度带进行反向传播,完成手写字体识别任务。

# -*- coding: utf-8 -*-
# @Author : Xenon
# @Date : 2023/2/5 23:14 
# @IDE : PyCharm(2022.3.2) Python3.9.13
"""使用TensorFlow的基础功能编写卷积神经网络,手动编写权重向量与前向计算逻辑,使用梯度带进行反向传播,完成手写字体识别任务。"""
import os
# import tensorflow as tf
import tensorflow.compat.v1 as tf
from keras.api._v1 import keras
from keras.api._v1.keras import datasets, optimizersfrom tensorflow.python.keras.layers import Conv2D, MaxPooling2D
from tensorflow.python.layers import layers
from tensorflow.python.layers.core import Flatten# from tensorflow.keras import layers, optimizers, datasets
# from tensorflow.keras.layers import Dense, Dropout, Flatten# 版本兼容问题 https://zhuanlan.zhihu.com/p/352494279 仍然失败,建议使用tf1.x算了
tf.disable_v2_behavior()
tf.disable_eager_execution()os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'def mnist_dataset():"""数据集的读取使用TensorFlow下载mnist数据集,取训练集中的前20000个样本作为本实验的训练集,测试集的所有样本(20000个)作为本实验的测试集。对于样本,将其属性值调整为tf.float32类型并归一化,标签调整为tf.int64类型,随机打乱顺序,训练样本每100个分为一个batch,测试样本只有一个batch。:return:训练集ds, 测试集test_ds(TensorFlow的dataset格式)"""(x, y), (x_test, y_test) = datasets.mnist.load_data()x = x.reshape(x.shape[0], 28, 28, 1)x_test = x_test.reshape(x_test.shape[0], 28, 28, 1)ds = tf.data.Dataset.from_tensor_slices((x, y))ds = ds.map(prepare_mnist_features_and_labels)ds = ds.take(20000).batch(100)test_ds = tf.data.Dataset.from_tensor_slices((x_test, y_test))test_ds = test_ds.map(prepare_mnist_features_and_labels)test_ds = test_ds.take(20000).batch(20000)return ds, test_dsdef prepare_mnist_features_and_labels(x, y):x = tf.cast(x, tf.float32) / 255.0y = tf.cast(y, tf.int64)return x, y#  模型的建立
class myConvModel(keras.Model):"""定义类myConvModel,继承自父类keras.Model,在构造函数中运行父类的构造函数,定义属性见下文注释:"""def __init__(self):super(myConvModel, self).__init__()# l1_conv:二维卷积层,输出深度32,卷积核5*5,激活函数为relu,零填充方式为等宽卷积self.l1_conv = Conv2D(filters=32,kernel_size=(5, 5),activation='relu', padding='same')# l2_conv:二维卷积层,输出深度64,卷积核5*5,激活函数为relu,零填充方式为等宽卷积self.l2_conv = Conv2D(filters=64,kernel_size=(5, 5),activation='relu', padding='same')# pool:最大池化层,区域为2*2,步长为2self.pool = MaxPooling2D(pool_size=(2, 2), strides=2)# flat:Flatten()层,用于将输入特征张量拉平为一维向量,在理论角度不算作一层;self.flat = Flatten()# dense1:全连接层,节点数为128,激活函数为tanh;self.dense1 = layers.Dense(100, activation='tanh')# dense2:全连接层,节点数为10,无激活函数。self.dense2 = layers.Dense(10)@tf.functiondef call(self, x):"""对输入的样本属性集x进行前向计算。分别经过属性l1_conv,pool,l2_conv,pool,flat,dense1,dense2计算,conv输入值为x,下一个属性的输入值是上一个属性的输出值。最后再进行softmax函数处理。:param x: 样本属性集x:return: 前向计算结果logits"""h1 = self.l1_conv(x)h1_pool = self.pool(h1)h2 = self.l2_conv(h1_pool)h2_pool = self.pool(h2)flat_h = self.flat(h2_pool)dense1 = self.dense1(flat_h)logits = self.dense2(dense1)probs = tf.nn.softmax(logits, axis=-1)return probsif __name__ == '__main__':model = myConvModel()  # 将myConvModel实例化为对象modeloptimizer = optimizers.Adam()  # 设置optimizer,使用Adam算法,参数为0.0001# 使用model.compile配置训练过程,要求将optimizer输入,损失方程为交叉熵损失函数,自动将标签独热向量化,评价指标为准确率.model.compile(optimizer=optimizer,loss='sparse_categorical_crossentropy',metrics=['accuracy'])train_ds, test_ds = mnist_dataset()# 读取数据集,使用model.fit方法,对训练集进行5轮训练(参数epochs=5)model.fit(train_ds, epochs=5)# 使用model. evaluate方法,对测试集进行测试.model.evaluate(test_ds)

输出结果:


六、循环神经网络完成诗词创作

使用TensorFlow建立循环神经网络,完成诗词创作任务。限制只取前500首唐诗。

# -*- coding: utf-8 -*-
# @Author : Xenon
# @Date : 2023/2/5 23:15 
# @IDE : PyCharm(2022.3.2) Python3.9.13
"""使用TensorFlow建立循环神经网络,完成诗词创作任务。限制只取前500首唐诗。"""import collections
# import tensorflow as tf
import tensorflow.compat.v1 as tf  # 版本兼容问题,我使用的是tf2.6.0
from keras.api._v1.keras import optimizers
from tensorflow import keras# from tensorflow.keras import layers
# from tensorflow.keras import layers, optimizers, datasetsstart_token = 'bos'
end_token = 'eos'def process_dataset(fileName):"""使用process_dataset函数读取与数据集附注:本实验中,每个字是一个样本,在理论上与实际训练过程中,每首诗是一个样本序列,在dataset数据中,每首诗+诗的字数是一个样本序列。:param fileName: 文件名:return: 样本序列instances, 字到编号的索引word2id, 编号到字的索引id2word"""# 根据给定的文件名,读取每一行诗词,去掉结尾的换行符,把第一个英文冒号“:”前面的诗名去除,# 在剩余内容的前面添加开始符'bos',后面添加结束符'eos',忽略长度大于200的诗,其它诗加入样本集。examples = []with open(fileName, 'r', encoding='utf-8') as fd:times = 0for line in fd:outs = line.strip().split(':')content = ''.join(outs[1:])ins = [start_token] + list(content) + [end_token]if len(ins) > 200:continueexamples.append(ins)times += 1# todo 若只训练500首古诗(古文?)请打开下面两行注释if times >= 500:breakcounter = collections.Counter()for e in examples:for w in e:counter[w] += 1# 统计各个字的频率,按照字频从大到小的顺序为字编号,将填充符号'PAD',未知字符标记'UNK'加入字表,生成字到编号、编号到字的索引(字典类型)sorted_counter = sorted(counter.items(), key=lambda x: -x[1])words, _ = zip(*sorted_counter)words = ('PAD', 'UNK') + words[:len(words)]word2id = dict(zip(words, range(len(words))))id2word = {word2id[k]: k for k in word2id}# 将诗词中的字转化为数字编号indexed_examples = [[word2id[w] for w in poem]for poem in examples]#  统计各个诗词的字数seqlen = [len(e) for e in indexed_examples]# 将编号化的诗(列表),与诗的长度(整数)合并成一个样本序列。依次生成所有样本序列。instances = list(zip(indexed_examples, seqlen))return instances, word2id, id2worddef poem_dataset():"""编写poem_dataset函数,进一步处理数据:return: 数据集ds, 字到编号的索引word2id, 编号到字的索引id2word"""# 使用process_dataset函数,得到返回值instances, word2id, id2wordinstances, word2id, id2word = process_dataset('./poems.txt')# 利用from_generator,将返回值转化为TensorFlow的dataset,传入的参数分别为:# 函数lambda: [ins for ins in instances]:遍历其中的样本,生成dataset# 数据类型(tf.int64, tf.int64):编号化的诗词与字数都是TensorFlow的64位整型# 形状(tf.TensorShape([None]),tf.TensorShape([]),编号化的诗词是一维向量,长度待定,字数是一个变量。ds = tf.data.Dataset.from_generator(lambda: [ins for ins in instances],(tf.int64, tf.int64),(tf.TensorShape([None]), tf.TensorShape([])))# 使用shuffle函数打乱数据集ds = ds.shuffle(buffer_size=10240)# 使用padded_batch函数,将每个样本序列填充并分批,即:每100个样本序列分为一批(batch),每个batch的样本序列长度不一,此时均填充到与当前batch的最长序列相同# (注:样本序列中的诗词长度不一,填充到最长,而诗词长度固定为一个变量,无需填充,也无需改变数值)ds = ds.padded_batch(100, padded_shapes=(tf.TensorShape([None]), tf.TensorShape([])))# 使用map函数,对样本序列进行处理,每个样本序列由原有的[编号化的诗词,诗词长度]改为[编号化的诗词去掉最后一个字,编号化的诗词去掉第一个字,诗词长度-1]# (注:编号化的诗词去掉最后一个字,是训练的输入序列,编号化的诗词去掉第一个字,是训练的真实标签,# 这样,对一个序列的训练过程中,输入样本与真实标签内容相同但错开一位,每个输入样本(一个字)对应的标签是这首诗的下一个字,# 也就是说,训练的目的是根据一首诗的当前字,预测下一个字)ds = ds.map(lambda x, seqlen: (x[:, :-1], x[:, 1:], seqlen - 1))return ds, word2id, id2wordclass myRNNModel(keras.Model):"""编写模型myRNNModel,参数为词到编号的索引w2id,继承自keras.Model"""def __init__(self, w2id):  # 执行父类的构造函数super(myRNNModel, self).__init__()self.v_sz = len(w2id)  # v_sz:训练集中的不同字的数量(包括开始符、结束符、填充标记、未知字符标记)# embed_layer:使用keras.layers.Embedding进行嵌入,每一个字是一个样本,# 如果经过独热向量处理,样本的属性数量是词表长度,现在经过嵌入,得到的是64个编码(64个属性),效果与独热向量近似。self.embed_layer = tf.keras.layers.Embedding(self.v_sz, 64,batch_input_shape=[None, None])# rnncell:使用keras.layers.SimpleRNNCell,建立一个时间步的RNN隐含层,有128个神经元self.rnncell = tf.keras.layers.SimpleRNNCell(128)# rnn_layer:使用keras.layers.RNN,利用rnncell,建立所有时间步的RNN隐含层,每个时间步返回一个输出self.rnn_layer = tf.keras.layers.RNN(self.rnncell, return_sequences=True)# dense:一个全连接层,神经元数量为v_sz,进行一个分类任务,类别数是v_sz。self.dense = tf.keras.layers.Dense(self.v_sz)@tf.functiondef call(self, inp_ids):""" 用于训练。将输入值用embed_layer嵌入,由[batch中的样本序列数,样本序列中的样本数(填充)]变为[batch中的样本序列数,样本序列中的样本数(填充),64]。用rnn_layer处理,此时的输出事实上是隐状态,每个字都将返回长度为128的隐状态。用dense得到输出,每个字的长度为128的隐状态都将进行处理,各自得到一个长度为v_sz的输出。:param inp_ids: 样本集inp_ids:return: 预测结果(概率)logits"""inp_emb = self.embed_layer(inp_ids)rnn_out = self.rnn_layer(inp_emb)logits = self.dense(rnn_out)return logits@tf.functiondef get_next_token(self, x, state):"""用于测试输入一个字,用embed_layer嵌入,用rnncell.call执行一个时间步的RNN算法,用dense得到输出,用argmax得到预测结果:param x: 当前输入样本:param state: 上一个时刻的隐状态:return: 当前预测结果(标签)out, 当前时刻的隐状态state"""inp_emb = self.embed_layer(x)h, state = self.rnncell.call(inp_emb, state)logits = self.dense(h)out = tf.argmax(logits, axis=-1)return out, statedef mkMask(input_tensor, maxLen):shape_of_input = tf.shape(input_tensor)shape_of_output = tf.concat(axis=0, values=[shape_of_input, [maxLen]])oneDtensor = tf.reshape(input_tensor, shape=(-1,))flat_mask = tf.sequence_mask(oneDtensor, maxlen=maxLen)return tf.reshape(flat_mask, shape_of_output)def reduce_avg(reduce_target, lengths, dim):"""用于辅助交叉熵损失函数的计算根据每个batch中各个输入预测的loss(包括填充符),以及每个batch中每首诗的长度,计算不含填充符的loss其中,设置mkMask函数,根据batch的最长长度与每首诗的长度,使用tf.sequence_mask,生成一个矩阵,其中非填充符为True,填充符为False。将False处的损失设为0(可以利用矩阵对应位置相乘),计算每个序列的总损失,然后除以每个序列的无填充诗词长度,计算每个序列的平均损失。:param reduce_target: 一个batch中各样本(非样本序列)的损失:param lengths: 各序列的真实长度:param dim: 需要求均值的维度:return: 各序列的平均损失red_avg"""shape_of_lengths = lengths.get_shape()shape_of_target = reduce_target.get_shape()if len(shape_of_lengths) != dim:raise ValueError(('Second input tensor should be rank %d, ' +'while it got rank %d') % (dim, len(shape_of_lengths)))if len(shape_of_target) < dim + 1:raise ValueError(('First input tensor should be at least rank %d, ' +'while it got rank %d') % (dim + 1, len(shape_of_target)))rank_diff = len(shape_of_target) - len(shape_of_lengths) - 1mxlen = tf.shape(reduce_target)[dim]mask = mkMask(lengths, mxlen)if rank_diff != 0:len_shape = tf.concat(axis=0, values=[tf.shape(lengths), [1] * rank_diff])mask_shape = tf.concat(axis=0, values=[tf.shape(mask), [1] * rank_diff])else:len_shape = tf.shape(lengths)mask_shape = tf.shape(mask)lengths_reshape = tf.reshape(lengths, shape=len_shape)mask = tf.reshape(mask, shape=mask_shape)mask_target = reduce_target * tf.cast(mask, dtype=reduce_target.dtype)red_sum = tf.reduce_sum(mask_target, axis=[dim], keepdims=False)red_avg = red_sum / (tf.cast(lengths_reshape, dtype=tf.float32) + 1e-30)return red_avg###
@tf.function
def compute_loss(logits, labels, seqlen):"""计算交叉熵损失函数要求使用TensorFlow中的交叉熵损失函数,规定样本预测标签为logits形式,需要用softmax函数处理,真实标签未经独热向量处理,需要自动处理。然后返回平均损失。:param logits: Logits形式的预测标签:param labels: 未经独热向量处理的真实标签:param seqlen::return: 平均损失loss"""losses = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=logits, labels=labels)losses = reduce_avg(losses, seqlen, dim=1)return tf.reduce_mean(losses)@tf.function
def train_one_step(model, optimizer, x, y, seqlen):"""进行训练(一次优化)在梯度带中,调用模型的call方法(注意该方法如何调用?),预测样本的标签,并调用compute_loss函数计算损失值。利用梯度带进行一次随机梯度下降法训练。:param model: 模型:param optimizer: 优化器(用于指定优化方法):param x: 属性集:param y: 真实标签集:param seqlen::return: 损失loss"""with tf.GradientTape() as tape:logits = model(x)loss = compute_loss(logits, y, seqlen)grads = tape.gradient(loss, model.trainable_variables)optimizer.apply_gradients(zip(grads, model.trainable_variables))return lossdef train(epoch, model, optimizer, ds):"""进行训练(全部优化过程)根据当前训练回合数epoch,模型model,优化器optimizer,数据集ds进行训练,每次读取一个batch,将model,optimizer,batch的属性集x,标签集y(事实上是错了一位的属性集),诗词长度seqlen输入train_one_step中,进行一次训练。附注:之前的实验中,模型自身没有时间步,此时“每个时间步”指梯度下降法的每个时间步,在RNN中,模型自身有时间步(每输入样本序列中的一个样本为一个时间步),为避免混淆,梯度下降法的一个时间步称为“一次优化”:param epoch: 当前训练回合数:param model: 模型:param optimizer: 优化器:param ds: 数据集:return: 损失loss"""loss = 0.0accuracy = 0.0for step, (x, y, seqlen) in enumerate(ds):loss = train_one_step(model, optimizer, x, y, seqlen)print('epoch', epoch, ': loss', loss.numpy())return loss# 执行训练(顶层函数)设置使用Adam法进行优化,参数为0.0005
optimizer = optimizers.Adam(0.0005)
# 使用poem_dataset()读取数据集
train_ds, word2id, id2word = poem_dataset()
#  实例化myRNNModel
model = myRNNModel(word2id)
# 执行3个epoch的训练,每次调用一遍train函数
for epoch in range(3):loss = train(epoch, model, optimizer, train_ds)def gen_sentence():"""用于测试生成随机的初始状态state(注:根据相关源代码,若生成一个序列的初始状态,只取其中第一个),以开始符bos作为初始输入cur_token,执行50次get_next_token方法,每一次执行,更新输入cur_token为执行后的输出,状态state为执行后的状态,将更新后的输入与状态作为下一次执行的参数。收集输出值,并将其重新转化为汉字。:return: 转化为汉字的诗词,每个字存储为列表的一个元素[id2word[t] for t in collect]"""state = [tf.random.normal(shape=(1, 128), stddev=0.5)]cur_token = tf.constant([word2id['bos']], dtype=tf.int32)collect = []for _ in range(50):cur_token, state = model.get_next_token(cur_token, state)collect.append(cur_token.numpy()[0])return [id2word[t] for t in collect]# 将gen_sentence的返回值拼接成一个字符串,进行输出(顶层代码)
print(''.join(gen_sentence()))

输出结果:(代码不是我写的,无能为力。。。)

在这里插入图片描述

每次运行结果不同,但是一言难尽。上面的代码中默认只训练前500首,可以将其注释(见第39行code),训练时间稍长,下面的我其中一次运行的输出结果:

在这里插入图片描述

在这里插入图片描述

就吐槽一句,chatGPT要是见到这玩意儿估计能气死。。。。。

七、使用异步序列到序列编码器-解码器的方法完成诗词创作任务

循环神经网络的三种模式

循环神经网络可以应用到很多不同类型的机器学习任务中,我们根据这些任务的特点将其分为以下三种模式:序列到类别的模式、同步的序列到序列模式、异步的序列到序列模式
在这里插入图片描述

参考:邱锡鹏《神经网络与深度学习》

代码实现:

时间不够充裕,后面有时间单独发一篇,敬请关注。

八、拓展练习

使用卷积神经网络对cifar10数据进行10分类预测,并在训练结束后,以corgi.jpg为例,尝试画出某一个卷积层的输出特征向量映射,以观察卷积神经网络的运作逻辑。

cifar10数据集介绍

CIFAR-10数据集由10类32x32的彩色图片组成,一共包含60000张图片,每一类包含6000图片。其中50000张图片作为训练集,10000张图片作为测试集。CIFAR-10数据集被划分成了5个训练的batch和1个测试的batch,每个batch均包含10000张图片。测试集batch的图片是从每个类别中随机挑选的1000张图片组成的,训练集batch以随机的顺序包含剩下的50000张图片。不过一些训练集batch可能出现包含某一类图片比其他类的图片数量多的情况。训练集batch包含来自每一类的5000张图片,一共50000张训练图片。下图显示的是数据集的类,以及每一类中随机挑选的10张图片,如图 1 CIFAR-10数据集:
在这里插入图片描述

数据集下载:
在这里插入图片描述

下载极慢,建议去官网下载 CIFAR-10数据集

代码实现:

见后面博文...

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

chatgpt赋能python:如何在Python中中断程序并退出程序

如何在Python中中断程序并退出程序 在Python编程的过程中&#xff0c;有时候我们需要中断程序的执行&#xff0c;并让程序退出。这在调试程序时尤为重要。本文将介绍Python中如何中断程序并退出程序。 使用sys.exit()函数 在Python中&#xff0c;我们可以使用sys.exit()函数…

常见快捷令与指令

快捷指令 ctrlc:复制 ctrlv:粘贴 ctrla:全选 ctrlx:剪切 ctrlz:撤销 ctrls:保存 altF4:关闭窗口 打开cmd的方式 开始Windows系统找到命令提示符 win键R 输入cmd打开控制台&#xff08;推荐使用&#xff09; 管理员身份运行&#xff1a;右键选择以管理员方式运行即可 …

linux基本功系列之chattr命令

文章目录 一. chattr命令介绍二. 语法格式及常用选项三. 参考案例3.1 给指定文件添加隐藏属性&#xff0c;阻止文件被修改&#xff1a;3.2 撤销i属性3.3 允许补充&#xff08;追加&#xff09;内容&#xff0c;无法覆盖/删除内容 总结 前言&#x1f680;&#x1f680;&#x1f…

外箱标签是怎么制作的

外箱标签设计都较为复杂&#xff0c;无论条码类型还是数据都比较多&#xff0c;且在出库时每个标签上的条码、数字一般都是流水变化的。外箱标签一般包含了供应商、收货人、产品编码、生产日期、发货日期等信息。下面我们就看看这样的外箱标签是如何制作的。 启动条码标签软件&…

5分钟包你搞懂箱形图分析!

最近有很多用户说到了年终需要回顾这一年的工作&#xff0c;根据这一年的数据看看有没有异常的情况&#xff0c;那么哪种图能够清晰直观地展现出这一信息呢&#xff1f; 答案只有一个&#xff0c;那就是... 箱形图 箱形图&#xff08;英文&#xff1a;Box plot&#xff09;&…

Python绘制箱型图-boxplot()

boxplot(&#xff09;语法格式如下&#xff1a; boxplot(x,notchnone,symnone,vertnone,whisnone,positionsnone,widthsnone,patch_artistnone,meanlinenone,showcapsnone,showboxnone,showfliersnone,boxpropsnone,) x:表示箱型图的数据。 sym:表示异常值对应的符号&#x…

【java基础】包装类,自动装箱和自动拆箱

文章目录 基本介绍包装类自动装箱自动拆箱包装类注意事项包装类比较包装器内容不可变 基本介绍 有时&#xff0c;需要将int这样的基本类型转换为对象。所有的基本类型都有一个与之对应的类。 例如&#xff0c;Integer类对应基本类型int。通常&#xff0c;这些类称为包装器&…

纸箱外观设计 包装盒版面设计 纸箱尺寸设计 纸箱纸盒包装设计 纸箱设计图

瓦楞纸板是由面纸、里纸、芯纸和加工成波形瓦楞的瓦楞纸通过粘合而成。根据商品包装的需求&#xff0c;瓦楞纸板可以加工成单面瓦楞纸板、三层瓦楞纸板、五层、七层、十一层等瓦楞纸板。 不同波纹形状的瓦楞&#xff0c;粘结成的瓦楞纸板的功能也有所不同。即使使用同样质量的面…

今年下半年程序员生存指南!

​ 见字如面&#xff0c;我是军哥&#xff01; 今天早上一醒来发现今天都 7 月 3 日&#xff0c;2023 的上半年已经悄然无声的离开我们了&#xff0c;你今年上半年目标达成如何&#xff1f; 最近看到新闻报道 5 月份&#xff0c;我国青年失业率 20.8%&#xff0c;比 4 月还高了…

脉脉、兼职猫逐梦AIGC,在线招聘江湖酝酿新变?

配图来自Canva可画 求职难与招聘难同时出现&#xff0c;人力资源行业供需双方互相嫌弃的问题如何解决&#xff1f;人力资源平台给出了新答案——AIGC。 2023年是AIGC在人力资源市场集中爆发的一年。脉脉平台上线类ChatGPT产品“万能的脉友”&#xff1b;数字化灵活用工平台兼…

AutoGPT太火了,无需人类插手自主完成任务,GitHub2.7万星

点击上方“AI遇见机器学习”&#xff0c;选择“星标”公众号 第一时间获取价值内容 来自&#xff5c;机器之心 OpenAI 的 Andrej Karpathy 都大力宣传&#xff0c;认为 AutoGPT 是 prompt 工程的下一个前沿。 近日&#xff0c;AI 界貌似出现了一种新的趋势&#xff1a;自主人工…

Ubuntu下不能切换中文,qt creator无法输入中文,sogo输入法(详细步骤)

目录&#xff1a; 1、解决ubuntu 不支持切换中文&#xff0c;并安装sogo输入法步骤&#xff1b; 2、解决Qt Creator不支持中文输入&#xff1a; 详细步骤&#xff1a; 一、解决ubuntu 不支持切换中文&#xff0c;并安装sogo输入法步骤&#xff1a; 1、如果在键盘输入法系统中&a…

经典文献阅读之—OverlapNet

点击上方“3D视觉工坊”&#xff0c;选择“星标” 干货第一时间送达 作者丨lovely_yoshino 来源丨古月居 简介 我们在之前的博客中讨论了一些激光回环检测的方法&#xff0c;但是基本都是围绕着点云特征去做的&#xff0c;并未涉足过深度学习的相关方法&#xff0c;之前作者在查…

文献阅读——How to give an Academic Talk

How to give an Academic Talk v4.0 By Paul N. Edwards,School of Information University of Michigan The awful academic talk 令人讨厌的学术演讲
这一场景你也许经历了上百次&#xff1a;
演讲者走进房子低下头&#xff0c;坐在桌边&#xff0c;不几乎不能透过眼前的…

一分钟get✔一个文献阅读的最核心技巧(用的是小绿鲸文献阅读器)

文章目录 最最核心的技巧——建立个人语料库其他技巧思维导图模板以及导图和大纲的相互转换一键导入知网文献自定义数据库的网址翻译 博主申请的福利 最最核心的技巧——建立个人语料库 参考我的语料库标签 每读一篇 就积累一些语料&#xff0c; 这样写的时候 写引言&#xff…

英文文章写作|文献管理|​​​​​​​阅读文献|引用文献|国内文章

目录 英文文章写作 1.阅读10篇文献&#xff0c;总结100个常用句型和常用短语 2.找3-5篇技术路线和统计方法与你的课题接近的文章&#xff0c;精读 3.针对论文的每一部分&#xff0c;尤其是某种具体方法、要讨论的某一具体方面&#xff0c;各找5-8 篇文献阅读&#xff0c;充…

英文不好的人如何阅读外文文献?

文章目录 0 前言1 工具2 查找文献3 阅读4 总结 0 前言 疫情在家&#xff0c;又要赶毕业设计。会遇到诸多烦恼。学校没有购买相应的数据库&#xff0c;买了也不能远程访问&#xff0c;怎么才能下载外文文献&#xff1f;英语不好&#xff0c;怎么才能读懂外文文献&#xff1f;不…

经典文献阅读之--OverlapNet

0. 简介 我们在之前的博客中讨论了一些激光回环检测的方法&#xff0c;但是基本都是围绕着点云特征去做的&#xff0c;并未涉足过深度学习的相关方法&#xff0c;之前作者在查找《经典文献阅读之–BoW3D》资料时看到了一个比较感兴趣的工作《OverlapNet: Loop Closing for LiD…

chatgpt赋能python:Python手把手教学:如何长截屏?

Python 手把手教学&#xff1a;如何长截屏&#xff1f; 导言 长截屏&#xff08;full-page screenshot&#xff09;是一种抓取整个网页、而不仅仅是可见区域的截屏。有时&#xff0c;你需要截取完整网页来记录信息、生成报告、分享内容或仅仅是作为计算机文件的样本。而 Pyth…

学计算机的女生后来都怎么样了?

上一篇&#xff1a;铁饭碗也不铁了 我估计有不少读者感兴趣&#xff0c;学计算机的女生都是怎么样的&#xff1f; 女程序员真的就如下面这张图形容的那样&#xff0c;没时间洗头、皮肤暗淡、黑眼圈吗&#xff1f;不尽然。 在我工作的9年里&#xff0c;我也接触过不少女开发。大…