目录
一、引言
二、经典神经网络回顾
(一)结构与计算过程
(二)局限性
三、循环神经网络(RNN)原理
(一)基本结构
(二)计算过程
(三)梯度消失与梯度爆炸问题
四、门控循环单元(GRU)原理
(一)结构改进
(二)计算过程
五、长短期记忆网络(LSTM)原理
(一)复杂结构
(二)计算过程
六、双向 RNN 原理
(一)结构特点
(二)输出计算
七、卷积神经网络(CNN)原理
(一)卷积层
(二)池化层
(三)全连接层
八、实际案例编程
(一)使用 RNN 进行时间序列预测
(二)使用 LSTM 进行文本情感分析
一、引言
你们的点赞、收藏、评论、关注是我创作的最大动力~
二、经典神经网络回顾
经典神经网络,通常指多层感知机(Multilayer Perceptron,MLP),是一种前馈神经网络。它由输入层、若干隐藏层和输出层组成。每一层包含多个神经元,神经元之间通过带有权重的连接相互关联。
(一)结构与计算过程
(二)局限性
- 处理序列数据的局限性:经典神经网络在处理具有序列结构的数据(如时间序列或自然语言)时存在困难,因为它无法有效利用数据中的时间依赖关系。每个输入在处理时被视为独立的,不考虑其在序列中的位置和前后元素的关联。
- 参数数量与过拟合问题:在处理图像等具有空间结构的数据时,由于其全连接结构,参数数量会随着输入维度和隐藏层神经元数量的增加而急剧增长。这不仅导致计算成本高昂,还容易引发过拟合问题,使得模型在训练集上表现良好,但在测试集上泛化能力较差。
三、循环神经网络(RNN)原理
循环神经网络(RNN)专为处理序列数据而设计,其核心特点是能够在处理序列时保持对之前信息的 “记忆”。
(一)基本结构
RNN 的核心结构是循环体。在每个时间步,循环体接收当前输入
和上一时刻的隐藏状态
,并计算当前时刻的隐藏状态
。
(二)计算过程
- 隐藏状态更新:
(三)梯度消失与梯度爆炸问题
- 问题产生原因:在 RNN 的反向传播过程中,梯度需要沿着时间序列进行反向传播。由于权重矩阵
在每个时间步都被重复使用,梯度在时间序列上不断相乘。当
的某些特征值的绝对值大于 1 时,随着时间步的增加,梯度会指数级增长,导致梯度爆炸;当
的某些特征值的绝对值小于 1 时,梯度会指数级衰减,导致梯度消失。
- 影响:梯度消失会使得模型在训练过程中难以学习到长距离的依赖关系,因为较早时间步的梯度在反向传播过程中变得极小,对参数更新的贡献几乎可以忽略不计。梯度爆炸则会导致参数更新过大,使得模型无法收敛,甚至出现权重变为无穷大的情况。
四、门控循环单元(GRU)原理
门控循环单元(GRU)是对 RNN 的改进,旨在解决梯度消失问题并更好地处理长序列数据。
(一)结构改进
GRU 引入了两个重要的门控机制:重置门 和更新门
。这些门控机制能够动态地控制信息的流动,决定哪些信息需要被保留或丢弃。
(二)计算过程
五、长短期记忆网络(LSTM)原理
长短期记忆网络(LSTM)同样是为解决 RNN 的梯度问题而设计,它具有更复杂但强大的结构,能够更好地处理长序列数据。
(一)复杂结构
LSTM 包含输入门、遗忘门
、输出门
和记忆单元
。记忆单元
可以看作是一条贯穿时间序列的 “高速公路”,允许信息在序列中长时间流动,而门控机制则控制信息的流入和流出。
(二)计算过程
六、双向 RNN 原理
(一)结构特点
双向 RNN 由两个方向相反的 RNN 组成,一个按顺序处理序列(正向),另一个按逆序处理序列(反向)。这两个 RNN 分别捕捉序列中的过去信息和未来信息。
(二)输出计算
七、卷积神经网络(CNN)原理
卷积神经网络(CNN)主要用于处理具有网格结构的数据,如图像、音频等,其核心在于卷积层和池化层的应用。
(一)卷积层
(二)池化层
(三)全连接层
经过卷积和池化后,数据被展平并输入到全连接层。全连接层的作用是将提取到的特征进行整合,并进行最终的分类或回归任务。全连接层的每个神经元与上一层的所有神经元都有连接,其计算方式与经典神经网络中的隐藏层和输出层类似,通过加权求和和激活函数变换得到输出。
八、实际案例编程
(一)使用 RNN 进行时间序列预测
以预测正弦波序列为例,使用 PyTorch 实现:
import torch
import torch.nn as nn
import numpy as np
import matplotlib.pyplot as plt
# 生成正弦波数据
time_steps = 100
data = np.sin(np.linspace(0, 10 * np.pi, time_steps))
data = torch.FloatTensor(data).view(-1, 1)
class RNN(nn.Module):
def __init__(self, input_size, hidden_size, output_size):
super(RNN, self).__init__()
self.hidden_size = hidden_size
self.rnn = nn.RNN(input_size, hidden_size, batch_first=True)
self.fc = nn.Linear(hidden_size, output_size)
def forward(self, x, hidden):
out, hidden = self.rnn(x, hidden)
out = self.fc(out[:, -1, :])
return out, hidden
input_size = 1
hidden_size = 10
output_size = 1
rnn = RNN(input_size, hidden_size, output_size)
criterion = nn.MSELoss()
optimizer = torch.optim.Adam(rnn.parameters(), lr=0.01)
# 训练
hidden = torch.zeros(1, 1, hidden_size)
for epoch in range(1000):
output, hidden = rnn(data.view(1, -1, 1), hidden)
loss = criterion(output, data[-1].view(1, -1))
optimizer.zero_grad()
loss.backward()
optimizer.step()
if epoch % 100 == 0:
print(f'Epoch {epoch}, Loss: {loss.item()}')
# 预测
with torch.no_grad():
future_steps = 10
predictions = []
current_data = data[-1].view(1, 1, 1)
for _ in range(future_steps):
output, hidden = rnn(current_data, hidden)
predictions.append(output.item())
current_data = output.view(1, 1, 1)
plt.plot(range(time_steps), data.numpy(), label='Original')
plt.plot(range(time_steps, time_steps + future_steps), predictions, label='Prediction')
plt.legend()
plt.show()
代码解释:
- 数据生成:通过
np.linspace
生成一个包含 100 个点的正弦波序列,并将其转换为 PyTorch 的张量。 - 模型定义:定义了一个简单的 RNN 模型,包含一个 RNN 层和一个全连接层。RNN 层用于处理序列数据,全连接层用于将 RNN 的输出转换为预测值。
- 训练过程:使用均方误差损失函数(MSE)和 Adam 优化器进行训练。在每个 epoch 中,将数据输入到模型中进行前向传播,计算损失,然后进行反向传播和参数更新。
- 预测过程:在训练完成后,使用最后一个时间步的数据作为初始输入,进行未来 10 个时间步的预测。预测结果通过循环不断更新输入,逐步生成。
- 可视化:使用
matplotlib
库将原始序列和预测序列绘制在同一张图上,方便直观观察预测效果。
(二)使用 LSTM 进行文本情感分析
下面是一个使用 PyTorch 实现的基于 LSTM 的文本情感分析示例,使用的数据集为 IMDB 电影评论数据集。
import torch
import torch.nn as nn
import torch.optim as optim
from torchtext.legacy import data, datasets
# 定义字段
TEXT = data.Field(tokenize='spacy', lower=True)
LABEL = data.LabelField(dtype=torch.float)
# 加载数据集
train_data, test_data = datasets.IMDB.splits(TEXT, LABEL)
# 构建词汇表
TEXT.build_vocab(train_data, max_size=25000, vectors="glove.6B.100d")
LABEL.build_vocab(train_data)
# 创建迭代器
train_iterator, test_iterator = data.BucketIterator.splits(
(train_data, test_data),
batch_size=64,
device=torch.device('cuda' if torch.cuda.is_available() else 'cpu')
)
# 定义 LSTM 模型
class LSTMClassifier(nn.Module):
def __init__(self, vocab_size, embedding_dim, hidden_dim, output_dim, n_layers, bidirectional, dropout):
super().__init__()
self.embedding = nn.Embedding(vocab_size, embedding_dim)
self.lstm = nn.LSTM(embedding_dim,
hidden_dim,
num_layers=n_layers,
bidirectional=bidirectional,
dropout=dropout)
self.fc = nn.Linear(hidden_dim * 2 if bidirectional else hidden_dim, output_dim)
self.dropout = nn.Dropout(dropout)
def forward(self, text):
embedded = self.dropout(self.embedding(text))
output, (hidden, cell) = self.lstm(embedded)
if self.lstm.bidirectional:
hidden = self.dropout(torch.cat((hidden[-2, :, :], hidden[-1, :, :]), dim=1))
else:
hidden = self.dropout(hidden[-1, :, :])
return self.fc(hidden.squeeze(0))
# 初始化模型
vocab_size = len(TEXT.vocab)
embedding_dim = 100
hidden_dim = 256
output_dim = 1
n_layers = 2
bidirectional = True
dropout = 0.5
model = LSTMClassifier(vocab_size, embedding_dim, hidden_dim, output_dim, n_layers, bidirectional, dropout)
# 加载预训练的词向量
pretrained_embeddings = TEXT.vocab.vectors
model.embedding.weight.data.copy_(pretrained_embeddings)
# 定义损失函数和优化器
criterion = nn.BCEWithLogitsLoss()
optimizer = optim.Adam(model.parameters())
# 训练模型
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model = model.to(device)
criterion = criterion.to(device)
for epoch in range(5):
model.train()
for batch in train_iterator:
optimizer.zero_grad()
predictions = model(batch.text).squeeze(1)
loss = criterion(predictions, batch.label)
loss.backward()
optimizer.step()
# 评估模型
model.eval()
total_correct = 0
total_count = 0
with torch.no_grad():
for batch in test_iterator:
predictions = model(batch.text).squeeze(1)
rounded_preds = torch.round(torch.sigmoid(predictions))
correct = (rounded_preds == batch.label).float().sum()
total_correct += correct
total_count += batch.label.shape[0]
accuracy = total_correct / total_count
print(f'Epoch {epoch + 1}, Test Accuracy: {accuracy.item()}')
代码解释:
- 数据处理:使用
torchtext
库加载 IMDB 电影评论数据集,并进行分词、构建词汇表等预处理操作。 - 模型定义:定义了一个基于 LSTM 的文本分类模型,包含嵌入层、LSTM 层和全连接层。嵌入层将输入的文本转换为词向量,LSTM 层用于捕捉文本中的序列信息,全连接层用于进行情感分类。
- 加载预训练词向量:使用预训练的 GloVe 词向量初始化嵌入层的权重,有助于提高模型的性能。
- 训练过程:使用二元交叉熵损失函数(BCEWithLogitsLoss)和 Adam 优化器进行训练。在每个 epoch 中,将数据输入到模型中进行前向传播,计算损失,然后进行反向传播和参数更新。
- 评估过程:在每个 epoch 结束后,在测试集上评估模型的准确率。通过将预测结果进行四舍五入,与真实标签进行比较,计算正确预测的样本数,从而得到准确率。