【深度学习-Day 45】实战演练:用 RNN/LSTM 构建情感分析模型 (PyTorch)

Langchain系列文章目录

01-玩转LangChain:从模型调用到Prompt模板与输出解析的完整指南
02-玩转 LangChain Memory 模块:四种记忆类型详解及应用场景全覆盖
03-全面掌握 LangChain:从核心链条构建到动态任务分配的实战指南
04-玩转 LangChain:从文档加载到高效问答系统构建的全程实战
05-玩转 LangChain:深度评估问答系统的三种高效方法(示例生成、手动评估与LLM辅助评估)
06-从 0 到 1 掌握 LangChain Agents:自定义工具 + LLM 打造智能工作流!
07-【深度解析】从GPT-1到GPT-4:ChatGPT背后的核心原理全揭秘
08-【万字长文】MCP深度解析:打通AI与世界的“USB-C”,模型上下文协议原理、实践与未来

Python系列文章目录

PyTorch系列文章目录

机器学习系列文章目录

深度学习系列文章目录

Java系列文章目录

JavaScript系列文章目录

深度学习系列文章目录

01-【深度学习-Day 1】为什么深度学习是未来?一探究竟AI、ML、DL关系与应用
02-【深度学习-Day 2】图解线性代数:从标量到张量,理解深度学习的数据表示与运算
03-【深度学习-Day 3】搞懂微积分关键:导数、偏导数、链式法则与梯度详解
04-【深度学习-Day 4】掌握深度学习的“概率”视角:基础概念与应用解析
05-【深度学习-Day 5】Python 快速入门:深度学习的“瑞士军刀”实战指南
06-【深度学习-Day 6】掌握 NumPy:ndarray 创建、索引、运算与性能优化指南
07-【深度学习-Day 7】精通Pandas:从Series、DataFrame入门到数据清洗实战
08-【深度学习-Day 8】让数据说话:Python 可视化双雄 Matplotlib 与 Seaborn 教程
09-【深度学习-Day 9】机器学习核心概念入门:监督、无监督与强化学习全解析
10-【深度学习-Day 10】机器学习基石:从零入门线性回归与逻辑回归
11-【深度学习-Day 11】Scikit-learn实战:手把手教你完成鸢尾花分类项目
12-【深度学习-Day 12】从零认识神经网络:感知器原理、实现与局限性深度剖析
13-【深度学习-Day 13】激活函数选型指南:一文搞懂Sigmoid、Tanh、ReLU、Softmax的核心原理与应用场景
14-【深度学习-Day 14】从零搭建你的第一个神经网络:多层感知器(MLP)详解
15-【深度学习-Day 15】告别“盲猜”:一文读懂深度学习损失函数
16-【深度学习-Day 16】梯度下降法 - 如何让模型自动变聪明?
17-【深度学习-Day 17】神经网络的心脏:反向传播算法全解析
18-【深度学习-Day 18】从SGD到Adam:深度学习优化器进阶指南与实战选择
19-【深度学习-Day 19】入门必读:全面解析 TensorFlow 与 PyTorch 的核心差异与选择指南
20-【深度学习-Day 20】PyTorch入门:核心数据结构张量(Tensor)详解与操作
21-【深度学习-Day 21】框架入门:神经网络模型构建核心指南 (Keras & PyTorch)
22-【深度学习-Day 22】框架入门:告别数据瓶颈 - 掌握PyTorch Dataset、DataLoader与TensorFlow tf.data实战
23-【深度学习-Day 23】框架实战:模型训练与评估核心环节详解 (MNIST实战)
24-【深度学习-Day 24】过拟合与欠拟合:深入解析模型泛化能力的核心挑战
25-【深度学习-Day 25】告别过拟合:深入解析 L1 与 L2 正则化(权重衰减)的原理与实战
26-【深度学习-Day 26】正则化神器 Dropout:随机失活,模型泛化的“保险丝”
27-【深度学习-Day 27】模型调优利器:掌握早停、数据增强与批量归一化
28-【深度学习-Day 28】告别玄学调参:一文搞懂网格搜索、随机搜索与自动化超参数优化
29-【深度学习-Day 29】PyTorch模型持久化指南:从保存到部署的第一步
30-【深度学习-Day 30】从MLP的瓶颈到CNN的诞生:卷积神经网络的核心思想解析
31-【深度学习-Day 31】CNN基石:彻底搞懂卷积层 (Convolutional Layer) 的工作原理
32-【深度学习-Day 32】CNN核心组件之池化层:解密最大池化与平均池化
33-【深度学习-Day 33】从零到一:亲手构建你的第一个卷积神经网络(CNN)
34-【深度学习-Day 34】CNN实战:从零构建CIFAR-10图像分类器(PyTorch)
35-【深度学习-Day 35】实战图像数据增强:用PyTorch和TensorFlow扩充你的数据集
36-【深度学习-Day 36】CNN的开山鼻祖:从LeNet-5到AlexNet的架构演进之路
37-【深度学习-Day 37】VGG与GoogLeNet:当深度遇见宽度,CNN架构的演进之路
38-【深度学习-Day 38】破解深度网络退化之谜:残差网络(ResNet)核心原理与实战
39-【深度学习-Day 39】玩转迁移学习与模型微调:站在巨人的肩膀上
40-【深度学习-Day 40】RNN入门:当神经网络拥有记忆,如何处理文本与时间序列?
41-【深度学习-Day 41】解密循环神经网络(RNN):深入理解隐藏状态、参数共享与前向传播
42-【深度学习-Day 42】RNN的“记忆”难题:深入解析长期依赖与梯度消失/爆炸
43-【深度学习-Day 43】解密LSTM:深入理解长短期记忆网络如何克服RNN的遗忘症
44-【深度学习-Day 44】GRU详解:LSTM的优雅继任者?门控循环单元原理与PyTorch实战
45-【深度学习-Day 45】实战演练:用 RNN/LSTM 构建情感分析模型 (PyTorch)



摘要

在本篇文章中,我们将跨越理论的鸿沟,踏入循环神经网络(RNN)与长短期记忆网络(LSTM)的实战应用。继前几篇文章我们深入探讨了 RNN、LSTM 和 GRU 的内部机制后,本文将手把手带你完成一个经典且极具代表性的自然语言处理(NLP)任务:电影评论情感分析。我们将使用经典的 IMDB 数据集,并借助强大的 PyTorch 框架,从数据预处理、模型构建、训练、评估到最终的预测,完整走过一个深度学习项目的全流程。通过本章的学习,你不仅能巩固对序列模型的理解,更将掌握如何运用它们解决真实世界中的文本分类问题,为你开启 NLP 的大门奠定坚实基础。

一、引言:从理论到实践的跨越

在掌握了 RNN 与 LSTM 的核心原理后,我们知道它们凭借其“记忆”能力,在处理序列数据方面具有得天独厚的优势。理论知识是根基,但只有通过实践,才能真正将其转化为解决问题的能力。

1.1 为何选择文本分类作为 RNN 实战项目?

文本分类是自然语言处理(NLP)中最基础、最常见的任务之一,其应用场景无处不在:

  • 情感分析:判断一段文本(如产品评论、社交媒体帖子)的情感倾向(正面、负面、中性)。
  • 垃圾邮件检测:识别一封邮件是否为垃圾邮件。
  • 新闻主题分类:将新闻文章自动归类到体育、科技、财经等不同频道。
  • 意图识别:在对话系统中,判断用户输入的意图。

由于文本本质上是一个单词序列,这与 RNN/LSTM 的设计理念完美契合。因此,选择情感分析作为我们的第一个 RNN 实战项目,是检验和深化理论知识的最佳途径。

1.2 项目目标与技术栈概览

  • 任务目标:构建一个深度学习模型,能够准确判断 IMDB 电影评论的情感是积极(Positive)还是消极(Negative)。
  • 数据集:IMDB 数据集,包含 50,000 条电影评论,已标注为正面或负面。
  • 核心模型:我们将主要使用 LSTM(长短期记忆网络),你也可以轻松地将其替换为基本 RNN 或 GRU。
  • 技术栈
    • Python: 主要编程语言。
    • PyTorch: 主流的深度学习框架,用于模型构建与训练。
    • TorchText: PyTorch 官方的 NLP 库,用于简化数据加载和预处理(尽管新版本有所变化,我们仍将使用其经典且易于理解的功能)。

下面,让我们开始这场激动人心的实战之旅!

二、项目准备:数据加载与预处理

“Garbage in, garbage out.” 这句名言在机器学习领域尤为重要。对于 NLP 任务,高质量的数据预处理是模型成功的关键。计算机无法直接理解 “good” 或 “bad” 这样的单词,我们必须将它们转化为机器能够处理的数字形式。

2.1 文本预处理的四大步骤

对于文本数据,我们通常需要执行以下步骤:

  1. 分词 (Tokenization):将完整的句子或段落切分成一个个独立的词元(Token),通常是单词。例如,“I love this movie!” -> ["I", "love", "this", "movie", "!"]
  2. 构建词汇表 (Vocabulary):收集数据集中所有出现过的词元,并为每个词元分配一个唯一的整数索引。例如,{"I": 1, "love": 2, "this": 3, ...}
  3. 数据编码 (Encoding):根据构建好的词汇表,将每个文本序列转换成对应的整数序列。例如,["I", "love", "this"] -> [1, 2, 3]
  4. 填充/截断 (Padding/Truncation):由于 RNN 在批处理时要求输入序列具有相同的长度,我们需要将较短的序列用一个特殊的“填充符”补齐,并将过长的序列截断。

这个流程听起来繁琐,但幸运的是,TorchText 库可以为我们自动化大部分工作。

2.2 使用 TorchText 加载 IMDB 数据集

我们将使用 torchtext 内置的 IMDB 数据集加载器,它极大地简化了数据准备过程。

(1) 安装 TorchText

如果尚未安装,请运行:

pip install torchtext

注意: torchtext 的版本迭代较快,API 变化较大。本教程将采用一个兼容性好且易于理解的版本 V0.9.0 左右的接口风格。如果你的版本较新,可能需要参考官方文档进行适配。

(2) 代码实现:数据加载与处理
import torch
from torchtext.legacy import data
from torchtext.legacy import datasets
import random

# 设置随机种子以确保结果可复现
SEED = 1234
torch.manual_seed(SEED)
torch.backends.cudnn.deterministic = True

# 1. 定义字段(Field):如何处理数据
# TEXT 字段:包含分词方法、是否转为小写、是否包含长度信息等
TEXT = data.Field(tokenize='spacy', tokenizer_language='en_core_web_sm', batch_first=True, include_lengths=True)
# LABEL 字段:定义标签的数据类型
LABEL = data.LabelField(dtype=torch.float, batch_first=True)

# 2. 加载 IMDB 数据集
# splits 方法会自动下载数据集并按我们定义的 Field 进行处理
train_data, test_data = datasets.IMDB.splits(TEXT, LABEL)

# 我们可以查看一条数据,验证格式
print(vars(train_data.examples[0]))
# 输出示例:
# {'text': ['I', 'loved', 'this', 'movie', 'since', 'I', 'was', 'a', 'child',...], 'label': 'pos'}

# 3. 构建词汇表(Vocabulary)
# min_freq=2 表示只包含在训练集中至少出现 2 次的单词
# 这有助于过滤掉稀有词和拼写错误,减小词汇表大小
TEXT.build_vocab(train_data, min_freq=2)
LABEL.build_vocab(train_data)

print(f"Unique tokens in TEXT vocabulary: {len(TEXT.vocab)}")
print(f"Unique tokens in LABEL vocabulary: {len(LABEL.vocab)}")
# 词汇表示例
print(TEXT.vocab.freqs.most_common(10)) # 查看最常见的10个词
print(LABEL.vocab.stoi) # 查看标签与索引的映射 {'neg': 0, 'pos': 1}

# 4. 创建数据迭代器(Iterator)
BATCH_SIZE = 64
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

# BucketIterator 会将长度相近的句子打包在一起,可以最小化 padding 的数量,提高效率
train_iterator, test_iterator = data.BucketIterator.splits(
    (train_data, test_data),
    batch_size=BATCH_SIZE,
    sort_key=lambda x: len(x.text), # 按文本长度排序
    sort_within_batch=True,
    device=device)

通过以上几步,我们已经高效地完成了数据加载、分词、词汇表构建和批处理迭代器的创建,为模型训练做好了充分的准备。

三、核心模型构建:从词嵌入到 LSTM

现在,让我们来搭建用于情感分类的 LSTM 模型。模型结构主要包含三个部分:

  1. 词嵌入层 (Embedding Layer):将输入的单词索引转换为密集向量。
  2. LSTM 层 (LSTM Layer):处理词向量序列,提取句子的深层语义特征。
  3. 全连接层 (Linear Layer):根据 LSTM 的输出进行最终的二分类(正面/负面)。

3.1 词嵌入层(Embedding Layer):文本的向量化表示

我们在 [Day 46] (预告) 会详细讲解词嵌入,这里先做应用。One-hot 编码维度过高且稀疏,无法表达词与词之间的关系。词嵌入(Word Embedding)将每个词映射到一个低维、稠密的向量,使得语义相近的词在向量空间中也相互靠近。
在 PyTorch 中,nn.Embedding 层就是一个简单的查找表,它存储了整个词汇表的词向量。

3.2 LSTM 层:捕捉序列依赖

nn.LSTM 是 PyTorch 实现的 LSTM 层。其关键参数包括:

  • input_size: 输入特征的维度,即词嵌入的维度。
  • hidden_size: LSTM 隐藏状态的维度,表示模型的“记忆”容量。
  • num_layers: LSTM 的层数,堆叠多个 LSTM 可以学习更复杂的模式。
  • batch_first=True: 一个极其重要的参数,它让输入的张量维度变为 (batch_size, sequence_length, feature_size),更符合直觉。
  • dropout: 在多层 LSTM 之间添加 Dropout,用于正则化。

LSTM 会返回两个输出:output(每个时间步的隐藏状态)和 (hidden, cell)(最后一个时间步的隐藏状态和细胞状态)。对于分类任务,我们通常只关心最后一个时间步的隐藏状态,因为它被认为是整个句子的语义摘要。

3.3 全连接层(Linear Layer):最终分类

我们将 LSTM 最后一个时间步的隐藏状态(或多个隐藏状态的组合)送入一个全连接层 nn.Linear,将其从 hidden_size 维度映射到最终的输出维度。对于二分类问题,输出维度是 1。

3.4 整合模型:完整的 SentimentLSTM

现在,我们将以上三个部分组装成一个完整的 PyTorch 模型。

import torch.nn as nn

class SentimentLSTM(nn.Module):
    def __init__(self, vocab_size, embedding_dim, hidden_dim, output_dim, n_layers,
                 bidirectional, dropout, pad_idx):
        """
        初始化模型
        :param vocab_size: 词汇表大小
        :param embedding_dim: 词向量维度
        :param hidden_dim: LSTM 隐藏层维度
        :param output_dim: 输出层维度 (对于二分类是1)
        :param n_layers: LSTM 层数
        :param bidirectional: 是否使用双向 LSTM
        :param dropout: Dropout 比例
        :param pad_idx: padding token 的索引,在嵌入层中会被忽略
        """
        super().__init__()

        # 1. 词嵌入层
        self.embedding = nn.Embedding(vocab_size, embedding_dim, padding_idx=pad_idx)

        # 2. LSTM 层
        self.lstm = nn.LSTM(embedding_dim,
                            hidden_dim,
                            num_layers=n_layers,
                            bidirectional=bidirectional,
                            dropout=dropout,
                            batch_first=True)

        # 3. 全连接层
        # 如果是双向 LSTM,其输出维度是 hidden_dim * 2
        self.fc = nn.Linear(hidden_dim * 2 if bidirectional else hidden_dim, output_dim)

        # 4. Dropout 层,防止过拟合
        self.dropout = nn.Dropout(dropout)

    def forward(self, text, text_lengths):
        """
        前向传播
        :param text: 输入的文本张量 [batch_size, sent_len]
        :param text_lengths: 文本的实际长度 [batch_size]
        :return: 预测结果
        """
        # embedded: [batch_size, sent_len, emb_dim]
        embedded = self.dropout(self.embedding(text))

        # PyTorch 的 pack_padded_sequence 可以提高处理变长序列的效率
        # 它会忽略掉 padding 的部分,只对实际内容进行计算
        packed_embedded = nn.utils.rnn.pack_padded_sequence(embedded, text_lengths.to('cpu'), batch_first=True, enforce_sorted=False)

        # packed_output: packed sequence
        # hidden: [num_layers * num_directions, batch_size, hid_dim]
        # cell: [num_layers * num_directions, batch_size, hid_dim]
        packed_output, (hidden, cell) = self.lstm(packed_embedded)

        # 将双向 LSTM 的最后一个时间步的两个方向的隐藏状态拼接起来
        # hidden[-2,:,:] 是前向 LSTM 的最后一个隐藏状态
        # hidden[-1,:,:] 是后向 LSTM 的最后一个隐藏状态
        hidden = self.dropout(torch.cat((hidden[-2,:,:], hidden[-1,:,:]), dim=1))

        # hidden: [batch_size, hid_dim * 2]
        # output: [batch_size, output_dim]
        return self.fc(hidden)

我们的模型已经定义完毕!这里我们使用了双向(Bidirectional)LSTM,它可以同时从前向后和从后向前读取文本,能更全面地捕捉上下文信息。

四、模型训练与评估

这是见证奇迹的时刻!我们将定义训练所需的一切,并启动训练循环。

4.1 定义超参数与设备

# 模型超参数
INPUT_DIM = len(TEXT.vocab)
EMBEDDING_DIM = 100
HIDDEN_DIM = 256
OUTPUT_DIM = 1
N_LAYERS = 2
BIDIRECTIONAL = True
DROPOUT = 0.5
PAD_IDX = TEXT.vocab.stoi[TEXT.pad_token] # 获取 padding token 的索引

# 实例化模型
model = SentimentLSTM(INPUT_DIM,
                      EMBEDDING_DIM,
                      HIDDEN_DIM,
                      OUTPUT_DIM,
                      N_LAYERS,
                      BIDIRECTIONAL,
                      DROPOUT,
                      PAD_IDX)

4.2 初始化模型、损失函数与优化器

我们将模型的未知参数(unk)和填充(pad)的词向量初始化为零,这样它们就不会在训练中产生影响。

# 初始化 embedding 层的 padding 权重为 0
model.embedding.weight.data[PAD_IDX] = torch.zeros(EMBEDDING_DIM)

# 定义优化器
import torch.optim as optim
optimizer = optim.Adam(model.parameters())

# 定义损失函数
# BCEWithLogitsLoss 将 Sigmoid 和 BCELoss 结合在一起,数值上更稳定
criterion = nn.BCEWithLogitsLoss()

# 将模型和损失函数移动到 GPU (如果可用)
model = model.to(device)
criterion = criterion.to(device)

4.3 编写训练与评估函数

我们需要一个函数来计算模型的准确率,并分别编写训练和评估的逻辑。

def binary_accuracy(preds, y):
    """
    计算二分类准确率
    """
    # 将概率值转换为 0 或 1
    rounded_preds = torch.round(torch.sigmoid(preds))
    correct = (rounded_preds == y).float()
    acc = correct.sum() / len(correct)
    return acc

def train(model, iterator, optimizer, criterion):
    epoch_loss = 0
    epoch_acc = 0
    model.train() # 设置为训练模式

    for batch in iterator:
        optimizer.zero_grad()
        text, text_lengths = batch.text
        
        # 前向传播
        predictions = model(text, text_lengths).squeeze(1)
        
        # 计算损失
        loss = criterion(predictions, batch.label)
        
        # 计算准确率
        acc = binary_accuracy(predictions, batch.label)
        
        # 反向传播
        loss.backward()
        
        # 更新权重
        optimizer.step()
        
        epoch_loss += loss.item()
        epoch_acc += acc.item()
        
    return epoch_loss / len(iterator), epoch_acc / len(iterator)

def evaluate(model, iterator, criterion):
    epoch_loss = 0
    epoch_acc = 0
    model.eval() # 设置为评估模式

    with torch.no_grad(): # 在评估模式下,不计算梯度
        for batch in iterator:
            text, text_lengths = batch.text
            predictions = model(text, text_lengths).squeeze(1)
            loss = criterion(predictions, batch.label)
            acc = binary_accuracy(predictions, batch.label)
            
            epoch_loss += loss.item()
            epoch_acc += acc.item()
            
    return epoch_loss / len(iterator), epoch_acc / len(iterator)

4.4 启动训练

现在,万事俱备,我们开始训练模型!

import time

def epoch_time(start_time, end_time):
    elapsed_time = end_time - start_time
    elapsed_mins = int(elapsed_time / 60)
    elapsed_secs = int(elapsed_time - (elapsed_mins * 60))
    return elapsed_mins, elapsed_secs

N_EPOCHS = 5
best_valid_loss = float('inf')

for epoch in range(N_EPOCHS):
    start_time = time.time()
    
    train_loss, train_acc = train(model, train_iterator, optimizer, criterion)
    valid_loss, valid_acc = evaluate(model, test_iterator, criterion) # 使用测试集作为验证集
    
    end_time = time.time()
    
    epoch_mins, epoch_secs = epoch_time(start_time, end_time)
    
    # 保存表现最好的模型
    if valid_loss < best_valid_loss:
        best_valid_loss = valid_loss
        torch.save(model.state_dict(), 'sentiment-model.pt')
    
    print(f'Epoch: {epoch+1:02} | Epoch Time: {epoch_mins}m {epoch_secs}s')
    print(f'\tTrain Loss: {train_loss:.3f} | Train Acc: {train_acc*100:.2f}%')
    print(f'\t Val. Loss: {valid_loss:.3f} |  Val. Acc: {valid_acc*100:.2f}%')

经过几个 Epoch 的训练,你应该能看到模型的准确率在 85% 以上,证明我们的模型已经学会了如何区分正面和负面评论。

五、模型预测与应用

训练好的模型如果不能用于预测,那将毫无意义。让我们来编写一个函数,用它来分析任意一句新的影评。

5.1 编写预测函数

这个函数需要完成之前数据预处理的所有步骤:分词、编码,然后将其送入模型。

import spacy
nlp = spacy.load('en_core_web_sm')

def predict_sentiment(model, sentence):
    model.eval()
    tokenized = [tok.text for tok in nlp.tokenizer(sentence)] # 分词
    indexed = [TEXT.vocab.stoi[t] for t in tokenized] # 编码
    length = [len(indexed)]
    tensor = torch.LongTensor(indexed).to(device)
    tensor = tensor.unsqueeze(0) # 添加 batch 维度
    length_tensor = torch.LongTensor(length)
    
    prediction = torch.sigmoid(model(tensor, length_tensor))
    
    return prediction.item()

# 加载训练好的最佳模型
model.load_state_dict(torch.load('sentiment-model.pt'))

5.2 实际测试

# 测试正面评论
review_pos = "This film is fantastic! The acting was superb and the plot was gripping."
sentiment = predict_sentiment(model, review_pos)
print(f"Review: '{review_pos}'")
print(f"Sentiment Score: {sentiment:.4f} -> {'Positive' if sentiment > 0.5 else 'Negative'}")
# 预期输出: 接近 1.0 的值, Positive

print("-" * 30)

# 测试负面评论
review_neg = "What a waste of time. The movie was boring and predictable."
sentiment = predict_sentiment(model, review_neg)
print(f"Review: '{review_neg}'")
print(f"Sentiment Score: {sentiment:.4f} -> {'Positive' if sentiment > 0.5 else 'Negative'}")
# 预期输出: 接近 0.0 的值, Negative

看到模型给出了正确的预测,是不是成就感满满?

六、总结

恭喜你!你已经成功地完成了从零开始构建、训练和部署一个基于 LSTM 的情感分析模型的全过程。通过本次实战,我们收获了以下核心知识点:

  1. NLP 项目全流程:我们系统地经历了文本数据预处理(分词、构建词汇表、编码、填充)、模型构建、训练、评估和预测的完整生命周期。
  2. TorchText 的应用:学习了如何使用 torchtext.legacy 库高效地加载和准备文本数据集,大大简化了繁琐的预处理工作。
  3. 序列模型搭建:掌握了如何在 PyTorch 中组合 nn.Embeddingnn.LSTMnn.Linear 层来构建一个强大的序列分类模型,并理解了双向 LSTM 和 Dropout 的作用。
  4. 模型训练技巧:了解了在 RNN 训练中的一些实用技巧,如使用 pack_padded_sequence 提高效率,选择 BCEWithLogitsLoss 增强数值稳定性,以及保存最佳模型以备后用。
  5. 实践与应用:最终,我们将训练好的模型应用于新的、未见过的文本上,实现了真正的预测功能,直观地感受到了深度学习的威力。

本次实战是通往更复杂 NLP 任务的基石。在未来,你可以在此基础上进行诸多改进,例如:使用更先进的 GRU 或 Transformer 架构,加载预训练的词向量(如 Word2Vec、GloVe)来提升性能,或者挑战更复杂的多分类文本任务。继续前进,NLP 的世界还有更多精彩等待你去探索!


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

吴师兄大模型

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值