– 1986年,Rina Dechter提出这个词,以搜索和推理为核心
– 2000年,I. Aizenberg 引入到神经网络研究
– 具有多层结构神经网络模型的机器学习方法
– 是一大类机器学习方法的总称
• 深度学习也与神经网络与贝叶斯学习等结合起来,并不限于狭义的神经网络的概念
• 用于解决图像识别领域的问题
• 原有多层感知器解决图像识别面临欠学习或参数过多问题
• 图像中待识别对象的像素点间存在空间关联关系
• 图像对象中存在多种不变性因素:
– 位置,大小,变形并不影响字符的属性
• 单个卷积核:局部信息提取
• 所有位置扫描,一个卷积核得到一个特征图(Feature Map)
• 多个卷积核称作多个通道(channel),用于不同特征提取
• 一维卷积:相应位置加权求和
• 超参数(hyper-parameters)
–卷积核尺寸
–步幅(stride)
–边宽或边衬(pad)
• 对训练过程与结果有重要影响
• 权值共享(weight sharing):一轮扫描中卷积核参数不变
• 前向传播后,通过输出端误差进行反向传播优化
• 多个并行卷积核构成多个通道,提取不同特征
• 图像尺寸×,卷积核尺寸×,步幅为s ,边衬为p且对称 ,则特征图维数:⌊(n+2p-k)/s+1⌋
• 挤压(squashing):对卷积结果进行非线性运算
• 非线性激活函数
– 传统S型函数(sigmoid) 或双曲正切函数(tanh)
– 常用ReLU函数:矫正线性单元(Rectified Linear Unit)
• 汇集(“池化”):对卷积后特征图进行降采样
–最大汇集(max pooling):选局部区域最大值
–平均汇集(Average pooling):选区域数值平均值
– 使用局部感受野、权值共享、最大汇集等措施减少参数量
– 自由参数:~6.1×10^7
– 数据扩增(data augmentation):利用预处理增加训练样本数目
• 1990年:LeNet-1
• 2012年:AlexNet
• 2013年:ZFNet
• 2014年:VGG 网络
• 2014年:GoogLeNet
• 2015年:残差网络(ResNet)
• 2017年:密集网络(DenseNet)
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(开源人工神经网络库)
建议执行:
pip insatll googlemaps # 同时根据提示内容安装或降级所有依赖包
官方TensorFlow安装文档 (安装必看)
折腾了一下午,妥协了! 除非你自己电脑的tensorflow是1.x版本的,否则不建议使用自己的电脑运行之后的代码,(总之,很难改2.x就对了)反正就是出不了结果,虚拟环境也是如此(gpu虚拟环境报错)。
这里选择阿里云的 天池Notebook 使用也还算比较方便。使用方法自行百度。
官网链接: https://tianchi.aliyun.com/notebook-ai/
使用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, MaxPooling2D
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).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_ds
def prepare_mnist_features_and_labels(x, y):
x = tf.cast(x, tf.float32) / 255.0
y = tf.cast(y, tf.int64)
return x, y
if __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,步长为2
Conv2D(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, optimizers
from 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_ds
def prepare_mnist_features_and_labels(x, y):
x = tf.cast(x, tf.float32) / 255.0
y = 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,步长为2
self.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.function
def 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 probs
if __name__ == '__main__':
model = myConvModel() # 将myConvModel实例化为对象model
optimizer = 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, datasets
start_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 = 0
for line in fd:
outs = line.strip().split(':')
content = ''.join(outs[1:])
ins = [start_token] + list(content) + [end_token]
if len(ins) > 200:
continue
examples.append(ins)
times += 1
# todo 若只训练500首古诗(古文?)请打开下面两行注释
if times >= 500:
break
counter = 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, id2word
def poem_dataset():
"""编写poem_dataset函数,进一步处理数据
:return: 数据集ds, 字到编号的索引word2id, 编号到字的索引id2word
"""
# 使用process_dataset函数,得到返回值instances, word2id, id2word
instances, 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, id2word
class 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.function
def 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.function
def 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, state
def 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) - 1
mxlen = 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 loss
def 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.0
accuracy = 0.0
for 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要是见到这玩意儿估计能气死。。。。。
循环神经网络可以应用到很多不同类型的机器学习任务中,我们根据这些任务的特点将其分为以下三种模式:序列到类别的模式、同步的序列到序列模式、异步的序列到序列模式。
参考:邱锡鹏《神经网络与深度学习》
代码实现:
时间不够充裕,后面有时间单独发一篇,敬请关注。
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数据集
代码实现:
见后面博文...