当前位置: 首页 > article >正文

【机器学习】任务十二:循环神经网络

1.循环神经网络

1.1 什么是循环神经网络(RNN)?

循环神经网络(Recurrent Neural Network, RNN) 是一种用于处理序列数据的神经网络类型,它的主要特点是拥有循环连接,使得网络可以对序列中的每个时间步(timestep)进行处理,并将前一个时间步的信息传递到当前时间步,从而捕捉序列数据中的时序依赖关系。

1.2 RNN的基本结构和工作原理

RNN 的核心思想是:通过每个时间步的“隐藏状态”(hidden state)来记录过去的信息,并将这些信息传递给下一个时间步。这个隐藏状态不仅依赖于当前的输入,还依赖于上一个时间步的隐藏状态。

(1)输入:在每个时间步 ttt,RNN 接收一个输入 xtx_txt​,这个输入可以是序列数据的一个元素,如单词、音频信号的一个采样点等。

(2)隐藏状态:每个时间步都会更新一个隐藏状态 hth_tht​,它不仅受到当前输入的影响,还受到上一个时间步的隐藏状态的影响。隐藏状态捕捉了当前时刻和过去时刻的上下文信息。

隐藏状态的更新公式:

其中:

  • ht:当前时间步的隐藏状态。
  • ht−1​:上一个时间步的隐藏状态。
  • xt​:当前时间步的输入。
  • Wh:权重矩阵,分别控制隐藏状态和输入的影响。
  • b:偏置项。
  • f:激活函数,通常是非线性函数(如 tanhReLU)。

(3)输出:经过多个时间步后,RNN 会输出序列的预测结果。这个输出可以是每个时间步的预测(如时间序列预测),也可以是序列整体的预测(如文本分类)。

1.3 RNN的优缺点

优点:

  • 序列数据处理能力:RNN 可以自然地处理序列数据(如文本、语音、时间序列等),并且能够捕捉到时间步之间的依赖关系。
  • 共享权重:RNN 在每个时间步使用相同的权重,因此参数量相对较少,训练更加高效。

缺点:

  • 梯度消失/爆炸问题:在长序列的训练过程中,RNN 的梯度可能变得非常小(梯度消失)或者非常大(梯度爆炸),导致网络难以学习长时间依赖关系。
  • 长期依赖问题:标准 RNN 难以记住长期的依赖关系,因为每个时间步的隐藏状态只通过一个单一的矩阵乘法进行更新,导致远距离的信息丢失。

1.4 RNN的变种

为了解决 RNN 的缺点,出现了许多改进的变种:

  1. 长短期记忆网络(LSTM):LSTM 是 RNN 的一种改进,它通过引入三个门(输入门、遗忘门和输出门)来控制信息的流动,能有效缓解梯度消失和长期依赖问题。
  2. 门控循环单元(GRU):GRU 是另一种改进的 RNN 变种,与 LSTM 类似,但结构更简单,计算量较小,同样能够捕捉长期依赖。

1.5 RNN的应用

RNN 被广泛应用于需要处理时序数据的任务,以下是一些典型的应用场景:

自然语言处理(NLP)

  • 机器翻译:RNN 能够处理句子的顺序信息,因此它在机器翻译任务中非常有效。
  • 情感分析:分析文本中情感的倾向。
  • 文本生成:生成连贯的文本内容。

语音识别:将语音信号转换为文本,RNN 能够捕捉音频信号的时序特性。

时间序列预测:用于股市预测、天气预报等领域,RNN 可以基于历史数据预测未来的趋势。

视频分析:在视频流中,RNN 可以用来捕捉帧与帧之间的时序关系,用于视频分类、动作识别等任务。

1.6 总结

        RNN 是一种非常适合处理序列数据的神经网络架构,通过循环连接的方式,能够捕捉时序数据中的上下文信息。尽管它在处理短期依赖上表现良好,但由于梯度消失和长期依赖问题,RNN 在实际应用中往往被 LSTM 和 GRU 等变种所取代。这些变种改进了 RNN 的性能,能够更好地处理长序列数据中的长期依赖关系。

2.小实验

2.1 数字填充

2.1.1 代码与结果

如何使用 TensorFlow 的 pad_sequences 函数对一个不等长的序列进行填充

import tensorflow as tf  # 导入所需库

s = [[1], [2, 3], [4, 5, 6]]  # 初始化填充前序列 s
print("填充前序列为\n", s)  # 显示填充前序列 s

# 填充序列并赋值给 a
a = tf.keras.preprocessing.sequence.pad_sequences(s, padding='post')
print("填充后序列为\n", a)  # 显示填充后序列 a

填充前序列为
 [[1], [2, 3], [4, 5, 6]]
填充后序列为
 [[1 0 0]
 [2 3 0]
 [4 5 6]]

2.1.2 关键代码解释

# 填充序列并赋值给 a
a = tf.keras.preprocessing.sequence.pad_sequences(s, padding='post')

这里的 pad_sequences 是 TensorFlow 中的一个函数,属于 tf.keras.preprocessing.sequence 模块,用于对不同长度的序列进行填充,使它们的长度一致。具体来说,pad_sequences 会自动将每个子序列(列表)填充为相同的长度。

(1)参数详解

s: 这是输入的原始序列,可以是一个嵌套的列表(或数组),每个子列表的长度可以不同。例如,在你的代码中,s = [[1], [2, 3], [4, 5, 6]] 是一个 3×3 的嵌套列表,不同的子序列有不同的长度:第一个子序列只有一个元素,第二个有两个,第三个有三个。

padding='post': 这个参数指定了填充的位置。

  • 'post': 表示在序列的 末尾 添加填充值(默认是 0)。
  • 'pre': 表示在序列的 前面 添加填充值。
    你在代码中选择了 'post',所以会在每个子序列的末尾填充零。

(2)填充的方式

在这个例子中,原始序列的最大长度是 3,因为第三个子序列([4, 5, 6])有三个元素。所以 pad_sequences 会将其他长度较短的子序列填充到 3 的长度。

  • [1] 会被填充成 [1, 0, 0],填充了两个零。
  • [2, 3] 会被填充成 [2, 3, 0],填充了一个零。
  • [4, 5, 6] 不需要填充,因为它的长度已经是 3。

(3)填充后的序列

假设 s = [[1], [2, 3], [4, 5, 6]],填充后的结果 a 会是:

a = [[1, 0, 0], [2, 3, 0], [4, 5, 6]]

这样,所有的子序列就被填充成了相同的长度 3,方便后续的操作(例如,在神经网络中进行批处理时,通常需要所有输入数据的形状一致)。

(4)默认填充值

默认情况下,pad_sequences 会使用 0 进行填充,如果需要填充其他值,可以通过 value 参数来指定填充值。例如,如果你想用 -1 填充,可以这样写:

a = tf.keras.preprocessing.sequence.pad_sequences(s, padding='post', value=-1)

2.2 序列剪裁

2.2.1 代码与结果

import tensorflow as tf  # 导入所需库
s = [[1, 2, 3, 9], [4, 5, 6], [7, 8]]  # 初始化剪裁前序列 s
print("剪裁前序列为\n", s)  # 显示剪裁前序列 s

# 剪裁序列并赋值给 a,
# maxlen=2: 通过设置 maxlen 参数,将序列的长度裁剪为2。如果序列的长度超过2,则保留最后的两个元素
a = tf.keras.preprocessing.sequence.pad_sequences(s, maxlen=2)
print("剪裁后序列为\n", a)  # 显示剪裁后序列 a

剪裁前序列为
 [[1, 2, 3, 9], [4, 5, 6], [7, 8]]
剪裁后序列为
 [[3 9]
 [5 6]
 [7 8]]

2.2.2 关键代码解释

a = tf.keras.preprocessing.sequence.pad_sequences(s, maxlen=2)

(1)tf.keras.preprocessing.sequence.pad_sequences 作用

pad_sequences 是 TensorFlow 中用于处理变长序列的工具,它能够将一组不等长的序列填充或裁剪到相同的长度。这对于处理文本、时间序列或其他形式的序列数据尤其重要,因为在许多机器学习模型中(尤其是神经网络),输入的形状必须一致。

(2)maxlen 参数的作用

  • maxlen=2: 这是控制输出序列最大长度的参数。

    • maxlen 指定了每个序列的目标长度。如果一个子序列的长度超过了 maxlen,则会裁剪它(即从前端或后端去掉多余的元素)。如果一个子序列的长度小于 maxlen,则会根据 padding 参数填充元素(默认为 0)。

    • 在你的代码中,maxlen=2 表示每个序列都会被裁剪或填充到 2 的长度。如果子序列的长度大于 2,它会裁剪;如果子序列的长度小于 2,它会用默认的填充值(0)填充。

(3)默认的裁剪方式

  • 裁剪方式(truncating: 默认情况下,pad_sequences 会从 序列的前面(pre) 裁剪多余的元素。如果你不指定 truncating 参数,它会假设为 'pre',也就是裁剪掉超过 maxlen 的前面的部分,保留后面的部分。

  • 如果你希望从序列的末尾(post)裁剪,可以通过设置 truncating='post' 来改变默认行为。

(4)填充方式

  • 填充方式(padding: 默认情况下,pad_sequences 会在序列的末尾(post)添加零填充,如果你希望填充的内容是其他值,可以通过 value 参数指定填充值。

  • 默认填充位置是 post,即在序列的末尾进行填充。

(5)具体操作

考虑到 s = [[1, 2, 3, 9], [4, 5, 6], [7, 8]],每个子序列的长度不一致:

  • 第一子序列 [1, 2, 3, 9] 长度为 4。
  • 第二子序列 [4, 5, 6] 长度为 3。
  • 第三子序列 [7, 8] 长度为 2。

maxlen=2 时,pad_sequences 会裁剪这些子序列的长度,使其都为 2。

  • 第一子序列 [1, 2, 3, 9] 长度超过 2,所以会被裁剪,裁剪后的结果是 [3, 9](默认从前面裁剪)。
  • 第二子序列 [4, 5, 6] 长度为 3,所以它的前一个元素会被裁剪,裁剪后的结果是 [5, 6]
  • 第三子序列 [7, 8] 已经是 2 个元素,因此它不需要裁剪或填充,保持不变。

2.3 keras 搭建模型

2.3.1 代码和结果

这段代码展示了如何使用 TensorFlow 和 Keras 创建一个简单的神经网络模型,并使用嵌入层(Embedding)来处理文本数据。

# 3.最常见的 100 个单词
import tensorflow as tf  # 导入 TensorFlow 库
import numpy as np       # 导入 NumPy 库

# 构建空的网络模型 model
model = tf.keras.Sequential()

# 创建嵌入层
embedding = tf.keras.layers.Embedding(output_dim=32, input_dim=100, input_length=400)
model.add(embedding)  # 添加到网络模型 model 中

model.summary()  # 显示网络模型的参数信息

# 显示 embedding 矩阵的值
print("embeddings矩阵=\n", embedding.get_weights())

# 定义输入文本
text = "Deep learning is an important concept raised by the current sciences."

# 定义分词器对象
token = tf.keras.preprocessing.text.Tokenizer(num_words=100)
token.fit_on_texts([text])  # 分词
input = token.texts_to_sequences([text])  # 输出向量序列

# 序列填充
test_seq = tf.keras.preprocessing.sequence.pad_sequences(
    input, padding='post', maxlen=400, truncating='post'
)

# 使用向量序列应用网络模型
output_array = model.predict(test_seq)

# 输出矩阵的形状
print("输出矩阵的形状=", output_array.shape)

Model: "sequential"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 embedding (Embedding)       (None, 400, 32)           3200      
                                                                 
=================================================================
Total params: 3,200
Trainable params: 3,200
Non-trainable params: 0
_________________________________________________________________
embeddings矩阵=
 [array([[-0.02878962, -0.03292129,  0.04554972, ..., -0.0058917 ,
         0.01143857,  0.0233766 ],
       [ 0.01397041, -0.01258515,  0.00929421, ..., -0.04004631,
         0.0135694 ,  0.0277424 ],
       [ 0.04916861, -0.04198183, -0.04687737, ..., -0.03828448,
         0.02139128,  0.02899126],
       ...,
       [-0.0321876 ,  0.0293329 ,  0.02029986, ..., -0.00899869,
        -0.00628114, -0.02092808],
       [-0.0257414 ,  0.03492158, -0.00921569, ..., -0.0181116 ,
        -0.03592857,  0.02451548],
       [ 0.04689746,  0.02985245, -0.04975928, ..., -0.02757919,
        -0.01401014, -0.03509605]], dtype=float32)]
1/1 [==============================] - 0s 75ms/step
输出矩阵的形状= (1, 400, 32)

2.3.2 代码解释

(1)导入必要的库

import tensorflow as tf  # 导入 TensorFlow 库
import numpy as np       # 导入 NumPy 库
  • tensorflow 用于构建神经网络模型及其相关操作。
  • numpy 用于数组操作,尽管在这个代码片段中未直接使用,但它通常用于处理数值数据和矩阵。

(2)构建空的神经网络模型

model = tf.keras.Sequential()

  • 这里使用 tf.keras.Sequential 创建了一个空的顺序模型 model。这是一个简单的线性堆叠模型,用于顺序地添加层(例如 Embedding 层)。

(3)创建嵌入层(Embedding Layer)

embedding = tf.keras.layers.Embedding(output_dim=32, input_dim=100, input_length=400)
model.add(embedding)  # 添加到网络模型 model 中

  • Embedding 层用于将输入的整数序列映射为稠密的向量表示。这里的 output_dim=32 表示嵌入空间的维度为 32,也就是说每个词会被映射为一个 32 维的向量。
  • input_dim=100 表示输入的词汇表大小是 100,即模型将处理的词汇表最多包含 100 个不同的词。
  • input_length=400 表示每个输入序列的长度为 400。也就是说,输入的每个文本序列将被填充或截断到 400 个词。

这个嵌入层将每个整数(词汇的索引)转换为一个 32 维的向量。

(4)打印模型结构

model.summary()  # 显示网络模型的参数信息

  • model.summary() 会打印出当前模型的结构、各层的类型、每一层的参数量、输出形状等信息,帮助你理解模型的结构。

(5)获取并显示嵌入矩阵的值

print("embeddings矩阵=\n", embedding.get_weights())

  • embedding.get_weights() 会返回嵌入层的权重矩阵。这个权重矩阵是一个二维数组,其形状是 (input_dim, output_dim),即 (100, 32),表示每个词汇对应的 32 维向量表示。

(6)定义输入文本并进行分词处理

text = "Deep learning is an important concept raised by the current sciences."

  • 这是输入的文本数据,用于展示如何将文本转换为模型可以处理的数值格式。
token = tf.keras.preprocessing.text.Tokenizer(num_words=100)
token.fit_on_texts([text])  # 分词
input = token.texts_to_sequences([text])  # 输出向量序列

  • Tokenizer 是 Keras 提供的文本处理工具,用于将文本转换为整数序列(每个单词对应一个唯一的整数)。
  • num_words=100 表示词汇表的大小限制为前 100 个最常见的词。
  • token.fit_on_texts([text]) 对输入文本进行分词,构建词汇表。
  • input = token.texts_to_sequences([text]) 将文本转换为整数序列(将文本中的每个单词替换为它在词汇表中的索引)。

假设词汇表中的单词被编码为整数,转换后的 input 可能是类似于 [1, 2, 3, 4, 5, 6, 7, ...] 的形式。

(7)序列填充

test_seq = tf.keras.preprocessing.sequence.pad_sequences(
    input, padding='post', maxlen=400, truncating='post'
)

  • pad_sequences 用于将不同长度的输入序列填充或截断到相同的长度。这里,maxlen=400 表示每个输入序列的最大长度为 400,超过这个长度的部分会被截断,长度不够的部分会被填充。
  • padding='post' 表示填充将在序列的末尾进行(默认填充的值是 0)。
  • truncating='post' 表示如果序列超过 maxlen,会从序列的末尾裁剪超出部分。

(8)使用模型进行预测

output_array = model.predict(test_seq)

  • 通过调用 model.predict() 方法,将填充后的文本序列 test_seq 输入到模型中,进行预测。此时,嵌入层会将每个单词(以索引表示)映射到对应的嵌入向量,输出一个矩阵。

(9) 输出矩阵的形状

print("输出矩阵的形状=", output_array.shape)

  • 输出 output_array 的形状。由于模型只有一个 Embedding 层,输出的形状应该是 (batch_size, input_length, output_dim)。具体来说,batch_size 是输入文本的批次大小(这里只有一个文本,批次大小为 1),input_length=400 是序列的长度,output_dim=32 是每个词的嵌入维度。因此,输出的形状应该是 (1, 400, 32)

2.3.3 结果分析

(1)模型结构(model.summary() 的输出)

Model: "sequential"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 embedding (Embedding)       (None, 400, 32)           3200      
                                                                 
=================================================================
Total params: 3,200
Trainable params: 3,200
Non-trainable params: 0
_________________________________________________________________

  • 模型类型:模型是一个 Sequential 类型的神经网络,它包含一系列按顺序排列的层。
  • 嵌入层(Embedding)
    • 输出形状(None, 400, 32),表示输入的每个序列都将转换为 400 个词的向量表示,每个词的嵌入向量是 32 维的。
    • 参数数量3200。这个值表示嵌入层的权重矩阵的参数数量。嵌入层的权重矩阵大小为 input_dim * output_dim = 100 * 32 = 3200,即 100 个词汇(词表大小)每个词用一个 32 维的向量表示。

(2)嵌入矩阵的权重(embedding.get_weights() 的输出)

embeddings矩阵=
 [array([[-0.02878962, -0.03292129,  0.04554972, ..., -0.0058917 ,
         0.01143857,  0.0233766 ],
       [ 0.01397041, -0.01258515,  0.00929421, ..., -0.04004631,
         0.0135694 ,  0.0277424 ],
       [ 0.04916861, -0.04198183, -0.04687737, ..., -0.03828448,
         0.02139128,  0.02899126],
       ...,
       [-0.0321876 ,  0.0293329 ,  0.02029986, ..., -0.00899869,
        -0.00628114, -0.02092808],
       [-0.0257414 ,  0.03492158, -0.00921569, ..., -0.0181116 ,
        -0.03592857,  0.02451548],
       [ 0.04689746,  0.02985245, -0.04975928, ..., -0.02757919,
        -0.01401014, -0.03509605]], dtype=float32)]

  • 这是嵌入层的权重矩阵。这个矩阵的维度是 (input_dim, output_dim),即 (100, 32),表示词汇表中每个词都被映射为一个 32 维的向量。
  • embedding.get_weights() 返回的是一个列表,其中包含嵌入层的权重矩阵。每个词的向量在该矩阵中都有一个对应的行。
  • 这些向量的数值是经过训练优化得到的。你可以看到,这些向量的值是浮动的,表示模型学到的词嵌入。

(3)模型的预测输出(model.predict() 的输出)

1/1 [==============================] - 0s 75ms/step

输出矩阵的形状= (1, 400, 32)

  • model.predict(test_seq) 返回的是模型对输入序列的预测输出。这里,模型的输出是每个输入单词的嵌入表示(通过 Embedding 层)。
  • 输出矩阵的形状(1, 400, 32),说明:
    • 1 是批次大小,表示输入数据只有一个样本(即只有一个文本输入)。
    • 400 是输入序列的最大长度,每个序列被填充到 400 个词。
    • 32 是每个单词的嵌入维度,每个单词被映射为一个 32 维的向量。

这表明,对于每个输入序列中的每个词,模型输出一个 32 维的嵌入向量,总共有 400 个词,每个词由 32 维向量表示。

(4)总结

  • 模型架构:你的模型只有一个嵌入层,负责将输入的词序列转换为对应的 32 维向量表示。
  • 嵌入矩阵的权重:这个权重矩阵大小为 (100, 32),表示你定义了一个包含 100 个词汇的词表,每个词的向量表示有 32 个维度。
  • 预测输出:模型根据输入文本,将每个词映射为一个 32 维的向量,输出的形状是 (1, 400, 32),即每个输入文本(长度为 400)的每个词(总共 400 个词)都有一个 32 维的嵌入表示。

这个过程展示了如何使用 Keras 创建一个基本的嵌入层,并通过 Tokenizer 将文本转换为适合嵌入层处理的格式。 

2.4 RNN网络模型

2.4.1 代码和结果

# 构建 RNN 网络模型
import tensorflow as tf  # 导入所需库

# 创建空的网络模型 model
model = tf.keras.Sequential()

# 创建嵌入层并添加到 model 中
model.add(tf.keras.layers.Embedding(10, 5, input_length=6))

# 创建简单循环层并添加到 model 中
model.add(tf.keras.layers.SimpleRNN(128))

# 创建全连接层作为输出层,并添加到 model 中
model.add(tf.keras.layers.Dense(5, activation='softmax'))

# 显示网络模型的参数信息
model.summary()

Model: "sequential_1"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 embedding_1 (Embedding)     (None, 6, 5)              50        
                                                                 
 simple_rnn (SimpleRNN)      (None, 128)               17152     
                                                                 
 dense (Dense)               (None, 5)                 645       
                                                                 
=================================================================
Total params: 17,847
Trainable params: 17,847
Non-trainable params: 0
_________________________________________________________________

2.4.2 代码解释

(1)导入 TensorFlow 库

import tensorflow as tf # 导入所需库
  • 导入 TensorFlow 库,这是使用 Keras 构建和训练模型的核心库。

(2)创建空的网络模型

model = tf.keras.Sequential()
  • 使用 Sequential 创建一个空的顺序模型(model)。在 Sequential 模型中,层是按顺序堆叠的,每一层的输入是前一层的输出。

(3)添加嵌入层(Embedding Layer)

model.add(tf.keras.layers.Embedding(10, 5, input_length=6))

Embedding(10, 5, input_length=6):嵌入层将输入的整数(每个词的索引)转换为一个 5 维的稠密向量。它的输出形状将是 (batch_size, input_length, output_dim),在这个例子中,输出形状是 (batch_size, 6, 5)

  • input_dim=10:词汇表的大小为 10,即输入数据中的单词索引最多为 9。
  • output_dim=5:每个单词将被嵌入为一个 5 维的向量。
  • input_length=6:每个输入序列的长度为 6,即每个输入将包含 6 个单词(或词汇索引)。

(4)添加循环层(SimpleRNN

model.add(tf.keras.layers.SimpleRNN(128))

SimpleRNN(128):创建一个简单的循环神经网络(RNN)层,包含 128 个隐藏单元。

  • 这个循环层将接收前一层(Embedding 层)输出的向量序列,并使用 RNN 单元(128 个)处理这个序列数据,生成最终的一个输出向量。
  • 输出的形状是 (batch_size, 128),即将输入的长度为 6 的序列压缩成一个 128 维的向量。

(5)添加全连接层(Dense Layer)

model.add(tf.keras.layers.Dense(5, activation='softmax'))

Dense(5, activation='softmax'):这是一个全连接层,用于最终输出分类结果。

该层的输出形状是 (batch_size, 5),表示每个样本将有 5 个类别的概率输出,且这些概率的和为 1。

  • 5:表示输出的类别数(即输出层有 5 个神经元)。
  • activation='softmax':使用 softmax 激活函数,将输出值转换为概率分布,适用于多分类任务。

(6)显示网络模型的参数信息

model.summary()  # 显示网络模型的参数信息
  • model.summary() 会打印出模型的各层结构,包括每一层的输出形状、参数数量等信息。这有助于了解网络的整体架构。

(7)模型结构和参数分析

假设批量大小(batch_size)为 32,输入序列的长度为 6。通过 model.summary() 可以看到模型的详细参数信息。下面是每一层的详细解释:

  • 嵌入层(Embedding)

    • 输入:词汇表大小为 10,输出:每个单词是 5 维的向量。
    • 参数数量:input_dim * output_dim = 10 * 5 = 50,即嵌入层有 50 个可训练参数。
    • 输出形状:(batch_size, 6, 5),即每个输入序列(长度 6)都会被转换为 6 个 5 维的向量。
  • 简单循环层(SimpleRNN)

    • 输入:每个单词被表示为 5 维向量(来自嵌入层),序列长度为 6。
    • 输出:128 维的向量表示整个序列的特征(最终的 RNN 输出)。
    • 参数数量:(input_dim * units) + (units * units) + units = (5 * 128) + (128 * 128) + 128 = 640 + 16384 + 128 = 17052,即该层有 17,052 个可训练参数。
    • 输出形状:(batch_size, 128),即每个输入序列通过 RNN 处理后输出一个 128 维的向量。
  • 全连接层(Dense)

    • 输入:128 维的向量(来自 RNN 层)。
    • 输出:5 维的概率分布(来自 softmax 激活)。
    • 参数数量:(input_dim * output_dim) + output_dim = (128 * 5) + 5 = 640 + 5 = 645,即该层有 645 个可训练参数。
    • 输出形状:(batch_size, 5),即每个输入样本会有 5 个类别的概率输出。

2.4.3 结果分析

 embedding_1 (Embedding)     (None, 6, 5)              50        
                                                                 
 simple_rnn (SimpleRNN)      (None, 128)               17152     
                                                                 
 dense (Dense)               (None, 5)                 645       
                                                                 
=================================================================
Total params: 17,847
Trainable params: 17,847
Non-trainable params: 0

第一层:embedding_1 (Embedding Layer)

  • 输出形状(None, 6, 5),表示每个输入序列(长度为 6)会被映射为 6 个 5 维的向量。
  • 参数数量50。这个值由 input_dim * output_dim 计算得出,即 10 * 5 = 50input_dim=10 表示词汇表的大小,output_dim=5 表示每个词将被映射为一个 5 维的向量。

第二层:simple_rnn (SimpleRNN Layer)

  • 输出形状(None, 128),表示该层将输入的序列压缩成一个 128 维的向量。RNN 会处理输入序列,并将每个时间步的输出与前一时间步的状态结合,最终生成一个固定大小的输出向量。

  • 参数数量17,152。这个参数数量是由以下公式计算的:

    参数数量=(input_dim×units)+(units×units)+units\text{参数数量} = (input\_dim \times units) + (units \times units) + units参数数量=(input_dim×units)+(units×units)+units
    • input_dim = 5(来自嵌入层的每个词的向量维度)
    • units = 128(SimpleRNN 中的隐藏单元数量)

    所以参数数量是:(5×128)+(128×128)+128=640+16,384+128=17,152

第三层:dense (Dense Layer)

  • 输出形状(None, 5),表示该层将产生一个 5 维的向量,用于分类任务的 5 个类别的概率。

  • 参数数量645。这个值是由以下公式计算得出的:

    参数数量=(input_dim×output_dim)+output_dim\text{参数数量} = (input\_dim \times output\_dim) + output\_dim参数数量=(input_dim×output_dim)+output_dim
    • input_dim = 128(来自 RNN 层的输出维度)
    • output_dim = 5(输出层的神经元数量)

    所以参数数量是:(128×5)+5=640+5=645

总参数数量

  • 总参数数量17,847,是所有层的参数总和,计算公式如下:

    50(嵌入层)+17,152(RNN层)+645(全连接层)=17,84750

总结

  • 嵌入层(Embedding):输入的整数序列(最大长度 6,每个单词映射到 5 维的向量),共有 50 个参数。
  • RNN 层(SimpleRNN):接收嵌入层的输出,处理整个序列,输出一个 128 维的向量,包含 17,152 个可训练参数。
  • 全连接层(Dense):将 RNN 输出的 128 维向量映射为 5 类的概率分布,包含 645 个参数。

这个网络模型是一个简单的序列分类模型,首先通过嵌入层将词汇序列转化为向量,再通过 RNN 层学习序列的时序特征,最后通过全连接层进行分类。

2.5 构建LSTM网络     

创建了一个包含 LSTM(长短期记忆) 层的神经网络模型。与普通的 RNN 层不同,LSTM 层能够捕捉更长范围的时序依赖关系,因为它包含了门控机制(如遗忘门、输入门、输出门)

2.5.1 代码和结果

import tensorflow as tf  # 导入所需库

# 创建空的网络模型 model
model = tf.keras.Sequential()

# 创建嵌入层并添加到 model 中
model.add(tf.keras.layers.Embedding(10, 5, input_length=6))

# 创建长短期记忆层(LSTM)并添加到 model 中
model.add(tf.keras.layers.LSTM(128))

# 创建全连接层作为输出层,并添加到 model 中
model.add(tf.keras.layers.Dense(5, activation='softmax'))

# 显示网络模型的参数信息
model.summary()

Model: "sequential_2"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 embedding_2 (Embedding)     (None, 6, 5)              50        
                                                                 
 lstm (LSTM)                 (None, 128)               68608     
                                                                 
 dense_1 (Dense)             (None, 5)                 645       
                                                                 
=================================================================
Total params: 69,303
Trainable params: 69,303
Non-trainable params: 0
_________________________________________________________________

2.5.2 代码解释                  

(1)导入 TensorFlow 库

import tensorflow as tf # 导入所需库
  • 这里导入了 tensorflow 库,它包含了构建和训练深度学习模型所需的工具。

(2)创建空的网络模型

model = tf.keras.Sequential()
  • 使用 Sequential 模型来创建一个线性堆叠的网络模型,意味着每一层的输出都是下一层的输入。

(3)添加嵌入层(Embedding Layer)

model.add(tf.keras.layers.Embedding(10, 5, input_length=6))

Embedding(10, 5, input_length=6)

该层的输出形状是 (batch_size, 6, 5),表示每个输入序列(长度为 6)将被转换为 6 个 5 维的词向量。

  • input_dim=10:词汇表的大小为 10(输入的数据中的每个词汇的索引不超过 9)。
  • output_dim=5:每个词将被表示为一个 5 维的向量。
  • input_length=6:每个输入序列的长度为 6,即每个输入样本由 6 个词组成。

(4)添加 LSTM 层(LSTM

model.add(tf.keras.layers.LSTM(128))

LSTM(128):这是一个 LSTM 层,包含 128 个隐藏单元。

  • LSTM 层能够学习输入数据的时序特征,捕捉长时间跨度的依赖关系。
  • 该层的输出形状是 (batch_size, 128),即每个输入序列经过 LSTM 处理后将被压缩成一个 128 维的向量。LSTM 层会为输入序列生成一个固定长度的输出。

(5)添加全连接层(Dense

model.add(tf.keras.layers.Dense(5, activation='softmax'))

Dense(5, activation='softmax'):这是一个全连接层,用于生成分类任务的输出。

该层的输出形状是 (batch_size, 5),即每个输入样本会生成一个 5 维的概率分布,表示其属于每个类别的概率。

  • 5:表示输出的类别数,即 5 个分类。
  • activation='softmax':使用 softmax 激活函数,将输出的 5 个值转换为一个概率分布。softmax 会将输出值转换为 0 到 1 之间的概率,且所有输出的概率和为 1。

(6)显示网络模型的参数信息

model.summary() # 显示网络模型的参数信息
  • model.summary() 会打印出模型的层结构、每一层的输出形状以及可训练的参数数量,帮助我们了解模型的详细结构。

2.5.3 结果分析

 Layer (type)                Output Shape              Param #   
=================================================================
 embedding_2 (Embedding)     (None, 6, 5)              50        
                                                                 
 lstm (LSTM)                 (None, 128)               68608     
                                                                 
 dense_1 (Dense)             (None, 5)                 645       
                                                                 
=================================================================
Total params: 69,303
Trainable params: 69,303
Non-trainable params: 0

(1)嵌入层(embedding_2

  • 输出形状(None, 6, 5),表示输入的每个序列(长度为 6)会被映射为 6 个 5 维的向量。
  • 参数数量50,这个是由 input_dim * output_dim 计算得出的,即 10 * 5 = 50
    • input_dim=10:词汇表的大小(输入数据的词汇数量,即最大单词索引为 9)。
    • output_dim=5:每个词的词向量维度。

(2)LSTM 层(lstm

  • 输出形状(None, 128),表示 LSTM 层会将每个输入序列压缩成一个 128 维的向量。

  • 参数数量68,608,这是由以下公式计算的:

    参数数量=4×(input_dim×units+units×units+units)\text{参数数量} = 4 \times (input\_dim \times units + units \times units + units)参数数量=4×(input_dim×units+units×units+units)

    其中:

    • input_dim = 5(来自嵌入层的词向量维度)。
    • units = 128(LSTM 层的隐藏单元数)。

    所以,LSTM 层的参数数量为:

    4×((5×128)+(128×128)+128)=4×(640+16,384+128)=68,6084

(3)全连接层(dense_1):

  • 输出形状(None, 5),表示该层输出 5 个类别的概率值。

  • 参数数量645,这是由以下公式计算的:

    参数数量=(input_dim×output_dim)+output_dim

    其中:

    • input_dim = 128(来自 LSTM 层的输出维度)。
    • output_dim = 5(全连接层的输出维度,即 5 个类别)。

    所以,全连接层的参数数量为:(128×5)+5=640+5=645

(4)总参数数量

  • 总参数数量69,303,是所有层的参数总和,即:

    50(嵌入层)+68,608(LSTM 层)+645(全连接层)=69,30350 (\text{嵌入层}) + 68,608 (\text{LSTM 层}) + 645 (\text{全连接层}) = 69,30350(嵌入层)+68,608(LSTM 层)+645(全连接层)=69,303

    所有这些参数都是 可训练的,因此 Trainable params69,303Non-trainable params0

(5)总结

这个模型是一个简单的文本分类模型,包含:

  • 嵌入层:将词汇索引转换为 5 维的词向量。
  • LSTM 层:捕捉输入序列的时序特征,并输出一个 128 维的向量表示。
  • 全连接层:输出 5 个类别的概率分布,用于多分类任务。

3.基于 GRU 、LSTM的情感分析模型

3.1 构建 GRU 神经网络模型

实现了一个基于 GRU(门控循环单元)的情感分类任务,目标是利用 IMDb 数据集预测影评是正面(1)还是负面(0)。这段代码实现了一个基于 GRU 的情感分析模型,处理 IMDb 数据集中的电影评论情感分类任务。模型通过训练数据来学习并进行预测,并在每一轮训练时绘制损失和准确率图,以帮助评估模型的训练过程。最终,模型在测试集上的表现通过损失和准确率输出。

3.1.1 代码和结果

import tensorflow as tf
from tensorflow.keras.datasets import imdb
from tensorflow.keras.preprocessing.sequence import pad_sequences
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Embedding, Dropout, GRU, Dense
from tensorflow.keras.optimizers import RMSprop
import matplotlib.pyplot as plt

# (1) 准备数据
# 导入 IMDb 数据集
vocab_size = 4000  # 词汇表大小
maxlen = 400       # 输入序列的最大长度

# 加载数据集(仅保留 vocab_size 个最常用的单词)
(x_train, y_train), (x_test, y_test) = imdb.load_data(num_words=vocab_size)

# 对训练集和测试集的特征值进行序列填充
x_train = pad_sequences(x_train, maxlen=maxlen, padding='post', truncating='post')
x_test = pad_sequences(x_test, maxlen=maxlen, padding='post', truncating='post')

# (2) 构建 GRU 神经网络模型
model = Sequential()
# 嵌入层
model.add(Embedding(input_dim=vocab_size, output_dim=32, input_length=maxlen))
# Dropout 层
model.add(Dropout(0.3))
# GRU 层
model.add(GRU(64))
# Dropout 层
model.add(Dropout(0.3))
# 输出层
model.add(Dense(1, activation='sigmoid'))

# 显示模型的参数信息
model.summary()

# (3) 编译、训练和评估 GRU 神经网络模型
# 编译模型
model.compile(optimizer=RMSprop(), loss='binary_crossentropy', metrics=['accuracy'])

# 训练模型
history = model.fit(
    x_train, y_train,
    batch_size=64,
    epochs=50,
    validation_split=0.2,
    verbose=2
)

# 评估模型
test_loss, test_accuracy = model.evaluate(x_test, y_test, batch_size=64, verbose=2)
print(f"Test Loss: {test_loss:.4f}, Test Accuracy: {test_accuracy:.4f}")

# (4) 绘制损失和准确率图
# 获取历史数据
train_loss = history.history['loss']
val_loss = history.history['val_loss']
train_accuracy = history.history['accuracy']
val_accuracy = history.history['val_accuracy']

# 创建子图
plt.figure(figsize=(12, 6))

# 子图 1:损失函数值折线图
plt.subplot(1, 2, 1)
plt.plot(train_loss, label='Training Loss')
plt.plot(val_loss, label='Validation Loss')
plt.title('Loss Function')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend()

# 子图 2:准确率折线图
plt.subplot(1, 2, 2)
plt.plot(train_accuracy, label='Training Accuracy')
plt.plot(val_accuracy, label='Validation Accuracy')
plt.title('Accuracy')
plt.xlabel('Epochs')
plt.ylabel('Accuracy')
plt.legend()

# 显示图形
plt.tight_layout()
plt.show()

3.1.2 代码解释

这段代码实现了一个基于 GRU(门控循环单元) 的情感分析模型,使用 IMDb 数据集来进行电影评论的情感分类任务。下面逐部分分析代码:

(1)准备数据

from tensorflow.keras.datasets import imdb
from tensorflow.keras.preprocessing.sequence import pad_sequences

vocab_size = 4000  # 词汇表大小
maxlen = 400       # 输入序列的最大长度

# 加载数据集(仅保留 vocab_size 个最常用的单词)
(x_train, y_train), (x_test, y_test) = imdb.load_data(num_words=vocab_size)

# 对训练集和测试集的特征值进行序列填充
x_train = pad_sequences(x_train, maxlen=maxlen, padding='post', truncating='post')
x_test = pad_sequences(x_test, maxlen=maxlen, padding='post', truncating='post')

  • imdb.load_data():加载 IMDb 数据集,num_words=vocab_size 参数限制了使用数据集中前 4000 个最常见的单词。返回的数据 (x_train, y_train)(x_test, y_test) 分别是训练集和测试集的数据和标签。
    • x_trainx_test 是电影评论的单词索引序列。
    • y_trainy_test 是对应的情感标签,0 代表负面评论,1 代表正面评论。
  • pad_sequences():对输入序列进行填充或截断。maxlen=400 限制了每个评论的最大长度为 400,padding='post' 表示在序列的末尾进行填充,truncating='post' 表示截断序列时,从末尾开始截取。

(2)构建 GRU 神经网络模型

from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Embedding, Dropout, GRU, Dense

model = Sequential()
# 嵌入层
model.add(Embedding(input_dim=vocab_size, output_dim=32, input_length=maxlen))
# Dropout 层
model.add(Dropout(0.3))
# GRU 层
model.add(GRU(64))
# Dropout 层
model.add(Dropout(0.3))
# 输出层
model.add(Dense(1, activation='sigmoid'))

  • Sequential():创建一个顺序模型,即每一层的输出都作为下一层的输入。
  • Embedding(input_dim=vocab_size, output_dim=32, input_length=maxlen):嵌入层将每个单词的索引转换为固定长度的稠密向量。input_dim=vocab_size 表示词汇表的大小为 4000,output_dim=32 表示嵌入向量的维度是 32,input_length=maxlen 表示每个输入序列的长度是 400。
  • Dropout(0.3):在训练过程中随机丢弃 30% 的神经元,以防止过拟合。
  • GRU(64):GRU 层包含 64 个单元。GRU 是一种循环神经网络(RNN)变体,能够捕捉序列数据的长期依赖关系。相比于 LSTM,GRU 结构更简洁,但通常在很多任务中表现相似。
  • Dense(1, activation='sigmoid'):输出层,使用 sigmoid 激活函数来输出一个 0 到 1 之间的值,表示电影评论的情感分类(正面或负面)。

(3)编译、训练和评估 GRU 神经网络模型

from tensorflow.keras.optimizers import RMSprop

# 编译模型
model.compile(optimizer=RMSprop(), loss='binary_crossentropy', metrics=['accuracy'])

# 训练模型
history = model.fit(
    x_train, y_train,
    batch_size=64,
    epochs=50,
    validation_split=0.2,
    verbose=2
)

# 评估模型
test_loss, test_accuracy = model.evaluate(x_test, y_test, batch_size=64, verbose=2)
print(f"Test Loss: {test_loss:.4f}, Test Accuracy: {test_accuracy:.4f}")

  • model.compile():编译模型,指定优化器 RMSprop()、损失函数 binary_crossentropy(用于二分类任务),并设置评估指标为准确率(accuracy)。
  • model.fit():训练模型,使用训练数据 x_train 和标签 y_trainbatch_size=64 表示每次训练时使用 64 个样本,epochs=50 表示训练 50 轮,validation_split=0.2 表示将 20% 的训练数据用于验证,verbose=2 会打印出每轮的训练进度。
  • model.evaluate():评估模型,计算测试集的损失和准确率,batch_size=64 表示每次评估时使用 64 个样本。

(4)绘制损失和准确率图

import matplotlib.pyplot as plt

# 获取历史数据
train_loss = history.history['loss']
val_loss = history.history['val_loss']
train_accuracy = history.history['accuracy']
val_accuracy = history.history['val_accuracy']

# 创建子图
plt.figure(figsize=(12, 6))

# 子图 1:损失函数值折线图
plt.subplot(1, 2, 1)
plt.plot(train_loss, label='Training Loss')
plt.plot(val_loss, label='Validation Loss')
plt.title('Loss Function')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend()

# 子图 2:准确率折线图
plt.subplot(1, 2, 2)
plt.plot(train_accuracy, label='Training Accuracy')
plt.plot(val_accuracy, label='Validation Accuracy')
plt.title('Accuracy')
plt.xlabel('Epochs')
plt.ylabel('Accuracy')
plt.legend()

# 显示图形
plt.tight_layout()
plt.show()

  • history.history:包含训练过程中每一轮的损失值和准确率,以及在验证集上的损失和准确率。
  • plt.subplot():创建一个 1 行 2 列的子图,第一个子图用于显示损失函数的变化,第二个子图用于显示准确率的变化。
  • plt.plot():绘制折线图,分别显示训练集和验证集的损失值和准确率。
  • plt.legend():添加图例,标注训练集和验证集。
  • plt.tight_layout():调整子图布局,确保图形不会重叠。

3.2 构建LSTM神经网络模型

3.2.1 代码和结果

这段代码实现了一个简单的 LSTM 模型,处理 IMDb 数据集中的电影评论情感分类任务,包含数据预处理、模型构建、训练、评估和可视化步骤。通过训练 50 轮后,模型可以对测试集进行评估,并通过图形展示训练过程中的损失和准确率变化情况。

import tensorflow as tf
from tensorflow.keras.datasets import imdb
from tensorflow.keras.preprocessing.sequence import pad_sequences
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Embedding, Dropout, LSTM, Dense
from tensorflow.keras.optimizers import RMSprop
import matplotlib.pyplot as plt

# (1) 准备数据
# 导入 IMDb 数据集
vocab_size = 4000  # 词汇表大小
maxlen = 400       # 输入序列的最大长度

# 加载数据集(仅保留 vocab_size 个最常用的单词)
(x_train, y_train), (x_test, y_test) = imdb.load_data(num_words=vocab_size)

# 对训练集和测试集的特征值进行序列填充
x_train = pad_sequences(x_train, maxlen=maxlen, padding='post', truncating='post')
x_test = pad_sequences(x_test, maxlen=maxlen, padding='post', truncating='post')

# (2) 构建 LSTM 神经网络模型
model = Sequential()
# 嵌入层
model.add(Embedding(input_dim=vocab_size, output_dim=32, input_length=maxlen))
# Dropout 层
model.add(Dropout(0.3))
# LSTM 层
model.add(LSTM(64))
# Dropout 层
model.add(Dropout(0.3))
# 输出层
model.add(Dense(1, activation='sigmoid'))

# 显示模型的参数信息
model.summary()

# (3) 编译、训练和评估 LSTM 神经网络模型
# 编译模型
model.compile(optimizer=RMSprop(), loss='binary_crossentropy', metrics=['accuracy'])

# 训练模型
history = model.fit(
    x_train, y_train,
    batch_size=64,
    epochs=50,
    validation_split=0.2,
    verbose=2
)

# 评估模型
test_loss, test_accuracy = model.evaluate(x_test, y_test, batch_size=64, verbose=2)
print(f"Test Loss: {test_loss:.4f}, Test Accuracy: {test_accuracy:.4f}")

# (4) 绘制损失和准确率图
# 获取历史数据
train_loss = history.history['loss']
val_loss = history.history['val_loss']
train_accuracy = history.history['accuracy']
val_accuracy = history.history['val_accuracy']

# 创建子图
plt.figure(figsize=(12, 6))

# 子图 1:损失函数值折线图
plt.subplot(1, 2, 1)
plt.plot(train_loss, label='Training Loss')
plt.plot(val_loss, label='Validation Loss')
plt.title('LSTM - Loss Function')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend()

# 子图 2:准确率折线图
plt.subplot(1, 2, 2)
plt.plot(train_accuracy, label='Training Accuracy')
plt.plot(val_accuracy, label='Validation Accuracy')
plt.title('LSTM - Accuracy')
plt.xlabel('Epochs')
plt.ylabel('Accuracy')
plt.legend()

# 显示图形
plt.tight_layout()
plt.show()

3.2.2 代码解释

(1)准备数据

from tensorflow.keras.datasets import imdb
from tensorflow.keras.preprocessing.sequence import pad_sequences

vocab_size = 4000  # 词汇表大小
maxlen = 400       # 输入序列的最大长度

# 加载数据集(仅保留 vocab_size 个最常用的单词)
(x_train, y_train), (x_test, y_test) = imdb.load_data(num_words=vocab_size)

# 对训练集和测试集的特征值进行序列填充
x_train = pad_sequences(x_train, maxlen=maxlen, padding='post', truncating='post')
x_test = pad_sequences(x_test, maxlen=maxlen, padding='post', truncating='post')
  • imdb.load_data():加载 IMDb 数据集,num_words=vocab_size 参数指定仅使用数据集中最常见的 4000 个单词进行处理。返回的 (x_train, y_train)(x_test, y_test) 是训练和测试数据,x_trainx_test 是评论的单词索引列表,y_trainy_test 是对应的标签(0 或 1,表示负面或正面评论)。
  • pad_sequences():对评论序列进行填充或截断,以确保所有输入序列的长度为 400。padding='post' 表示如果评论短于 400,则在后面填充 0;truncating='post' 表示如果评论超过 400,则截断评论后面的部分。

(2)构建 LSTM 神经网络模型

from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Embedding, Dropout, LSTM, Dense

model = Sequential()
# 嵌入层
model.add(Embedding(input_dim=vocab_size, output_dim=32, input_length=maxlen))
# Dropout 层
model.add(Dropout(0.3))
# LSTM 层
model.add(LSTM(64))
# Dropout 层
model.add(Dropout(0.3))
# 输出层
model.add(Dense(1, activation='sigmoid'))

  • Sequential():创建一个顺序模型,即每一层的输出连接到下一层。
  • Embedding():嵌入层将每个单词的索引转换为一个固定长度的稠密向量(这里是 32 维)。input_dim=vocab_size 表示词汇表大小为 4000,output_dim=32 表示嵌入向量的维度为 32,input_length=maxlen 表示每个输入序列的长度为 400。
  • Dropout(0.3):在训练过程中随机丢弃 30% 的神经元,防止过拟合。
  • LSTM(64):LSTM 层包含 64 个单元,主要用于处理序列数据,捕捉时间序列中的长期依赖关系。
  • Dense(1, activation='sigmoid'):输出层,使用 sigmoid 激活函数输出一个 0 到 1 之间的值,表示正面(1)或负面(0)的概率。

(3)编译、训练和评估模型

from tensorflow.keras.optimizers import RMSprop

# 编译模型
model.compile(optimizer=RMSprop(), loss='binary_crossentropy', metrics=['accuracy'])

# 训练模型
history = model.fit(
    x_train, y_train,
    batch_size=64,
    epochs=50,
    validation_split=0.2,
    verbose=2
)

# 评估模型
test_loss, test_accuracy = model.evaluate(x_test, y_test, batch_size=64, verbose=2)
print(f"Test Loss: {test_loss:.4f}, Test Accuracy: {test_accuracy:.4f}")

  • model.compile():编译模型,指定优化器 RMSprop()、损失函数 binary_crossentropy(二分类问题使用的常见损失函数),并设置评估指标为准确率(accuracy)。
  • model.fit():训练模型,使用训练数据 x_train 和标签 y_trainbatch_size=64 表示每次训练时处理 64 个样本,epochs=50 表示训练 50 轮,validation_split=0.2 表示将 20% 的训练数据用于验证,verbose=2 会打印出每轮的训练进度。
  • model.evaluate():在测试集上评估模型的性能,返回损失和准确率。

(4)绘制损失和准确率图

import matplotlib.pyplot as plt

# 获取历史数据
train_loss = history.history['loss']
val_loss = history.history['val_loss']
train_accuracy = history.history['accuracy']
val_accuracy = history.history['val_accuracy']

# 创建子图
plt.figure(figsize=(12, 6))

# 子图 1:损失函数值折线图
plt.subplot(1, 2, 1)
plt.plot(train_loss, label='Training Loss')
plt.plot(val_loss, label='Validation Loss')
plt.title('LSTM - Loss Function')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend()

# 子图 2:准确率折线图
plt.subplot(1, 2, 2)
plt.plot(train_accuracy, label='Training Accuracy')
plt.plot(val_accuracy, label='Validation Accuracy')
plt.title('LSTM - Accuracy')
plt.xlabel('Epochs')
plt.ylabel('Accuracy')
plt.legend()

# 显示图形
plt.tight_layout()
plt.show()

  • history.history:包含训练过程中每一轮的损失值(loss)和准确率(accuracy)以及验证集上的损失值和准确率。
  • plt.subplot():创建一个 1 行 2 列的子图,分别用于显示损失函数值和准确率的变化。
  • plt.plot():绘制折线图,分别显示训练集和验证集的损失和准确率。
  • plt.legend():添加图例,区分训练和验证数据。
  • plt.tight_layout():调整子图布局,确保不重叠。 

http://www.kler.cn/a/428013.html

相关文章:

  • Python从0到100(八十六):神经网络-ShuffleNet通道混合轻量级网络的深入介绍
  • Nuxt:利用public-ip这个npm包来获取公网IP
  • 【逻辑学导论第15版】A. 推理
  • 前端axios拦截器
  • HttpClient学习
  • 【Julia】Julia预编译与外部库:从崩溃到完美集成
  • 服务器守护进程化
  • 【Java计算机毕业设计】Springboot+vue校园外卖配送服务管理系统【源代码+数据库+LW文档+开题报告+答辩稿+部署教程+代码讲解】
  • KGDB使用
  • C/C++基础知识复习(39)
  • C++:std::fstream详细介绍
  • 数据结构 ——链式队列
  • Wordpress ElementorPageBuilder插件存在文件读取漏洞(CVE-2024-9935)
  • gdb逆向调试功能太强了~
  • pycharm报错
  • centos7.9编译升级openssl和openssh的记录
  • 【JVM】JVM基础教程(一)
  • 阳光电脑公司的维修服务微信小程序ssm+论文源码调试讲解
  • 数据库原理实验实验二 SQL SERVER查询分析器的使用
  • Unity在运行状态下,当物体Mesh网格发生变化时,如何让MeshCollider碰撞体也随之实时同步变化?
  • HTTP 网络技术学习:缓存;为什么有时候出现问题要清除浏览器缓存?客户端缓存和服务端缓存是什么。
  • LLMs之Agent之Lares:Lares的简介、安装和使用方法、案例应用之详细攻略
  • PyTorch 切片运算 (Slice Operator)
  • 【人工智能】用Python构建高效的自动化数据标注工具:从理论到实现
  • MySQL 存储引擎详解
  • 负载均衡OJ项目中遇到的问题